Skip to content

Commit

Permalink
docs(core): Improve docs on ConfigurableOperationDef
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelbromley committed Aug 26, 2020
1 parent 6c909b3 commit 8881aee
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 19 deletions.
9 changes: 5 additions & 4 deletions packages/common/src/shared-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,7 @@ export type CustomFieldType = 'string' | 'localeString' | 'int' | 'float' | 'boo
* 1. How the argument form field is rendered in the admin-ui
* 2. The JavaScript type into which the value is coerced before being passed to the business logic.
*
* @docsCategory common
* @docsPage Configurable Operations
* @docsCategory ConfigurableOperationDef
*/
export type ConfigArgType = 'string' | 'int' | 'float' | 'boolean' | 'datetime' | 'ID';

Expand All @@ -114,8 +113,7 @@ export type ConfigArgType = 'string' | 'int' | 'float' | 'boolean' | 'datetime'
* The ids of the default form input components that ship with the
* Admin UI.
*
* @docsCategory common
* @docsPage Configurable Operations
* @docsCategory ConfigurableOperationDef
*/
export type DefaultFormComponentId =
| 'boolean-form-input'
Expand All @@ -130,7 +128,10 @@ export type DefaultFormComponentId =
| 'password-form-input';

/**
* @description
* Used to defined the expected arguments for a given default form input component.
*
* @docsCategory ConfigurableOperationDef
*/
type DefaultFormConfigHash = {
'date-form-input': { min?: string; max?: string; yearRange?: number };
Expand Down
133 changes: 119 additions & 14 deletions packages/core/src/common/configurable-operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ import { InjectableStrategy } from './types/injectable-strategy';
* ]
* ```
*
* @docsCategory common
* @docsPage Configurable Operations
* @docsCategory ConfigurableOperationDef
*/
export type LocalizedStringArray = Array<Omit<LocalizedString, '__typename'>>;

Expand Down Expand Up @@ -87,12 +86,44 @@ export type ConfigArgDef<T extends ConfigArgType> = T extends 'string'
* A object which defines the configurable arguments which may be passed to
* functions in those classes which implement the {@link ConfigurableOperationDef} interface.
*
* ## Data types
* Each argument has a data type, which must be one of {@link ConfigArgType}.
*
* @example
* ```TypeScript
* {
* apiKey: { type: 'string' },
* maxRetries: { type: 'int' },
* logErrors: { type: 'boolean' },
* }
* ```
*
* ## Lists
* Setting the `list` property to `true` will make the argument into an array of the specified
* data type. For example, if you want to store an array of strings:
*
* @example
* ```TypeScript
* {
* aliases: {
* type: 'string',
* list: true,
* },
* }
*```
* In the Admin UI, this will be rendered as an orderable list of string inputs.
*
* ## UI Component
* The `ui` field allows you to specify a specific input component to be used in the Admin UI.
* When not set, a default input component is used appropriate to the data type.
*
* @example
* ```TypeScript
* {
* operator: {
* type: 'string',
* ui: {
* component: 'select-form-input',
* options: [
* { value: 'startsWith' },
* { value: 'endsWith' },
Expand All @@ -101,12 +132,17 @@ export type ConfigArgDef<T extends ConfigArgType> = T extends 'string'
* ],
* },
* },
* term: { type: 'string' },
* secretKey: {
* type: 'string',
* ui: { component: 'password-form-input' },
* },
* }
* ```
* The available components as well as their configuration options can be found in the {@link DefaultFormConfigHash} docs.
* Custom UI components may also be defined via an Admin UI extension using the `registerFormInputComponent()` function
* which is exported from `@vendure/admin-ui/core`.
*
* @docsCategory common
* @docsPage Configurable Operations
* @docsCategory ConfigurableOperationDef
*/
export type ConfigArgs = {
[name: string]: ConfigArgDef<ConfigArgType>;
Expand Down Expand Up @@ -141,10 +177,9 @@ export type ConfigArgValues<T extends ConfigArgs> = {
/**
* @description
* Common configuration options used when creating a new instance of a
* {@link ConfigurableOperationDef}.
* {@link ConfigurableOperationDef} (
*
* @docsCategory common
* @docsPage Configurable Operations
* @docsCategory ConfigurableOperationDef
*/
export interface ConfigurableOperationDefOptions<T extends ConfigArgs> extends InjectableStrategy {
/**
Expand Down Expand Up @@ -177,11 +212,79 @@ export interface ConfigurableOperationDefOptions<T extends ConfigArgs> extends I

/**
* @description
* Defines a ConfigurableOperation, which is a method which can be configured
* by the Administrator via the Admin API.
* A ConfigurableOperationDef is a special type of object used extensively by Vendure to define
* code blocks which have arguments which are configurable at run-time by the administrator.
*
* This is the mechanism used by:
*
* * {@link CollectionFilter}
* * {@link PaymentMethodHandler}
* * {@link PromotionAction}
* * {@link PromotionCondition}
* * {@link ShippingCalculator}
* * {@link ShippingEligibilityChecker}
*
* @docsCategory common
* @docsPage Configurable Operations
* Any class which extends ConfigurableOperationDef works in the same way: it takes a
* config object as the constructor argument. That config object extends the {@link ConfigurableOperationDefOptions}
* interface and typically adds some kind of business logic function to it.
*
* For example, in the case of `ShippingEligibilityChecker`,
* it adds the `check()` function to the config object which defines the logic for checking whether an Order is eligible
* for a particular ShippingMethod.
*
* ## The `args` property
*
* The key feature of the ConfigurableOperationDef is the `args` property. This is where we define those
* arguments that are exposed via the Admin UI as data input components. This allows their values to
* be set at run-time by the Administrator. Those values can then be accessed in the business logic
* of the operation.
*
* The data type of the args can be one of {@link ConfigArgType}, and the configuration is further explained in
* the docs of {@link ConfigArgs}.
*
* ## Dependency Injection
* If your business logic relies on injectable providers, such as the TypeORM `Connection` object, or any of the
* internal Vendure services or those defined in a plugin, you can inject them by using the config object's
* `init()` method, which exposes the {@link Injector}.
*
* Here's an example of a ShippingCalculator that injects a service which has been defined in a plugin:
*
* @example
* ```TypeScript
* import { Injector, ShippingCalculator } from '\@vendure/core';
* import { ShippingRatesService } from './shipping-rates.service';
*
* // We keep reference to our injected service by keeping it
* // in the top-level scope of the file.
* let shippingRatesService: ShippingRatesService;
*
* export const customShippingCalculator = new ShippingCalculator({
* code: 'custom-shipping-calculator',
* description: [],
* args: {},
*
* init(injector: Injector) {
* // The init function is called during bootstrap, and allows
* // us to inject any providers we need.
* shippingRatesService = injector.get(ShippingRatesService);
* },
*
* calculate: async (order, args) => {
* // We can now use the injected provider in the business logic.
* const { price, priceWithTax } = await shippingRatesService.getRate({
* destination: order.shippingAddress,
* contents: order.lines,
* });
*
* return {
* price,
* priceWithTax,
* };
* },
* });
* ```
*
* @docsCategory ConfigurableOperationDef
*/
export class ConfigurableOperationDef<T extends ConfigArgs = ConfigArgs> {
get code(): string {
Expand All @@ -207,6 +310,7 @@ export class ConfigurableOperationDef<T extends ConfigArgs = ConfigArgs> {
}

/**
* @description
* Convert a ConfigurableOperationDef into a ConfigurableOperationDefinition object, typically
* so that it can be sent via the API.
*/
Expand All @@ -229,13 +333,14 @@ export class ConfigurableOperationDef<T extends ConfigArgs = ConfigArgs> {
}

/**
* @description
* Coverts an array of ConfigArgs into a hash object:
*
* from:
* [{ name: 'foo', type: 'string', value: 'bar'}]
* `[{ name: 'foo', type: 'string', value: 'bar'}]`
*
* to:
* { foo: 'bar' }
* `{ foo: 'bar' }`
**/
protected argsArrayToHash(args: ConfigArg[]): ConfigArgValues<T> {
const output: ConfigArgValues<T> = {} as any;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ import {
} from '../../common/configurable-operation';
import { Order } from '../../entity/order/order.entity';

/**
* @description
* Configuration passed into the constructor of a {@link ShippingEligibilityChecker} to
* configure its behavior.
*
* @docsCategory shipping
*/
export interface ShippingEligibilityCheckerConfig<T extends ConfigArgs>
extends ConfigurableOperationDefOptions<T> {
check: CheckShippingEligibilityCheckerFn<T>;
Expand Down Expand Up @@ -61,7 +68,6 @@ export class ShippingEligibilityChecker<T extends ConfigArgs = ConfigArgs> exten
* a particular shipping method.
*
* @docsCategory shipping
* @docsPage ShippingEligibilityChecker
*/
export type CheckShippingEligibilityCheckerFn<T extends ConfigArgs> = (
order: Order,
Expand Down

0 comments on commit 8881aee

Please sign in to comment.