@cisstech/nestjs-expand
Version:
A NestJS module to build Dynamic Resource Expansion for APIs
271 lines (270 loc) • 10.4 kB
TypeScript
import 'reflect-metadata';
/**
* Symbol key for metadata associated with expanders.
*/
export declare const EXPANDER_KEY: unique symbol;
/**
* Symbol key for metadata associated with classes containing reusable expander methods.
*/
export declare const EXPANDER_METHODS_KEY: unique symbol;
/**
* Symbol key for metadata associated with expandable parameters on controller/expander methods.
*/
export declare const EXPANDABLE_KEY: unique symbol;
/**
* Symbol key for metadata associated with linking reusable expander methods.
*/
export declare const USE_EXPANSION_METHOD_KEY: unique symbol;
/**
* Symbol key for metadata associated with selectable parameters.
*/
export declare const SELECTABLE_KEY: unique symbol;
/**
* Represents the context in which an expansion is performed.
* @typeparam TRequest - The type of the incoming request.
* @typeparam TParentResource - The type of the parent resource being expanded.
*/
export type ExpandContext<TRequest = any, TParentResource = any> = {
/**
* The incoming request object.
*/
request: TRequest;
/**
* The parent resource being expanded.
*/
parent: TParentResource;
};
/**
* Represents a standard method on an @Expander class.
*/
export type StandardExpandMethod = (context: ExpandContext) => Promise<unknown>;
/**
* Represents a method within a @ExpanderMethods class.
* It takes specific arguments derived from the context.
*/
export type ReusableExpandMethod = (...args: any[]) => Promise<unknown>;
/**
* Parameters for the @ExpanderMethods decorator.
*/
export type ExpanderMethodsParams = {};
/**
* Configuration for the @UseExpansionMethod decorator.
* @typeparam TParentResource - The type of the parent DTO being expanded.
* @typeparam TReusableExpander - The type of the reusable expander class being used.
*/
export type UseExpansionMethodConfig<TParentResource = any, TReusableExpander = any> = {
/**
* The name of the field to populate in the expanded DTO.
*/
name: string;
/**
* The class decorated with @ExpanderMethods containing the logic.
*/
class: new (...args: any[]) => TReusableExpander;
/**
* The name of the method within the reusable expander class to call.
* Must be a key of TReusableExpander.
*/
method: keyof TReusableExpander;
/**
* Defines how to derive the arguments for the reusable method.
* Can be:
* - An array of strings: Each string is a property path on `context.parent`.
* Values are extracted in order and passed as arguments.
* Example: ['id', 'tenantId'] maps context.parent.id and context.parent.tenantId.
* - A function: Takes the `ExpandContext` and returns an array of arguments.
* Use for complex logic, transformations, or accessing `context.request`.
* Example: (context) => [context.parent.id, context.request.headers['x-tenant-id']]
*/
params: (keyof TParentResource)[] | ((context: ExpandContext<any, TParentResource>) => any[]);
};
/**
* Metadata stored by the @UseExpansionMethod decorator.
* This now directly stores the configuration object.
*/
export type UseExpansionMethodMetadata<TParentResource = any, TReusableExpander = any> = UseExpansionMethodConfig<TParentResource, TReusableExpander>;
/**
* Represents parameters for making a controller/expander response expandable.
*/
export type ExpandableParams = {
/**
* The DTO class to be expanded.
*/
target: Function;
/**
* The name of the field containing the dto to expand from the request response.
* This is useful when the dto is wrapped in a response object like in listing endpoints where the dto is in the `items` field
* along with other metadata like `count` and `total`.
*/
rootField?: string;
/**
* Overrides {@link ExpandConfig.expandQueryParamName} value for this endpoint.
*
* @remarks
* - This is useful when you want to have different query parameter names for different endpoints.
* - This is ignored if applied to a class decorated with `@Expander` since only root Expandable method are direclty linked to the incoming request.
*/
queryParamName?: string;
/**
* Specify the error policy for this expandable endpoint.
* @default The module's defaultErrorPolicy or 'ignore'
*/
errorPolicy?: ExpandErrorPolicy;
};
/**
* Represents parameters for making a controller response selectable.
*/
export type SelectableParams = {
/**
* The name of the field containing the dto to select from the request response.
* This is useful when the dto is wrapped in a response object like in listing endpoints where the dto is in the `items` field
* along with other metadata like `count` and `total`.
*/
rootField?: string;
/**
* Overrides {@link ExpandConfig.selectQueryParamName} value for this endpoint.
*/
queryParamName?: string;
};
/**
* Represents configuration for the ExpandModule.
*/
export type ExpandConfig = {
/**
* Whether to enable logging for the ExpandModule.
* @default `true`
*/
enableLogging?: boolean;
/**
* Whether to enable global selection for all endpoints.
*/
enableGlobalSelection?: boolean;
/**
* The name of the query parameter to use for selecting fields.
* A comma-separated list of fields can be provided.
* For example, `?selects=field1,field2`
*
* @remarks
* - nested fields can be selected using dot notation (e.g. `?selects=field1.nestedField`)
* - fields can be excluded by prefixing them with a minus sign (e.g. `?selects=-field1`)
* - wildcards can be used to select all fields of a given type on each level including the root level (e.g. `?selects=field1.*`)
* ``
* @default `selects`
*/
selectQueryParamName?: string;
/**
* The name of the query parameter to use for expanding resources.
* @default `expands`
*/
expandQueryParamName?: string;
/**
* Configure error handling for expansions.
*/
errorHandling?: ExpansionErrorHandlingConfig;
/**
* Log level for expansion logs.
* @default 'warn'
*/
logLevel?: 'debug' | 'log' | 'warn' | 'error' | 'none';
};
/**
* Error policy for expansion errors.
* - 'ignore': Ignore errors and continue with the expansion (default)
* - 'include': Include error details in the response
* - 'throw': Throw the error and interrupt the entire request
*/
export type ExpandErrorPolicy = 'ignore' | 'include' | 'throw';
/**
* Represents error metadata for failed expansions.
*/
export type ExpansionError = {
message: string;
path: string;
stack?: string;
};
/**
* Format function for expansion errors.
*/
export type ExpansionErrorFormatter = (error: Error, path: string) => Partial<ExpansionError>;
/**
* Error handling configuration for expansions.
*/
export type ExpansionErrorHandlingConfig = {
/**
* Whether to include error metadata in the response.
* @default false
*/
includeErrorsInResponse?: boolean;
/**
* Custom formatter for expansion errors.
* @default (error, path) => ({ message: error.message, path })
*/
errorResponseShape?: ExpansionErrorFormatter;
/**
* Default error policy for all expansions.
* @default 'ignore'
*/
defaultErrorPolicy?: ExpandErrorPolicy;
};
/**
* Decorator function to mark a class as a standard expander for a specific DTO.
*
* @remarks
* - The class must be a NestJS provider.
* - Methods on this class matching requested expansion fields will be called.
*
* @param target - The DTO class this expander is responsible for.
* @returns A metadata decorator.
*/
export declare const Expander: (target: Function) => import("@nestjs/common").CustomDecorator<typeof EXPANDER_KEY>;
/**
* Decorator function to mark a class as containing reusable expansion methods.
*
* @remarks
* - The class must be a NestJS provider.
* - Methods from this class can be linked to specific fields in standard @Expander
* classes using @UseExpansionMethod.
*
* @param params - Optional parameters.
* @returns A metadata decorator.
*/
export declare const ExpanderMethods: (params?: ExpanderMethodsParams) => import("@nestjs/common").CustomDecorator<typeof EXPANDER_METHODS_KEY>;
/**
* Decorator function to link a field in an @Expander class to a method
* in a @ExpanderMethods class. Applied at the CLASS level of an @Expander.
* Can be applied multiple times for different fields.
*
* @typeparam TParentResource - The type of the parent DTO (automatically inferred if possible).
* @typeparam TReusableExpander - The type of the reusable expander class.
*
* @param config - Configuration detailing the field name, reusable class, method, and parameter mapping.
* @returns A ClassDecorator.
*/
export declare const UseExpansionMethod: <TParentResource = any, TReusableExpander = any>(config: UseExpansionMethodConfig<TParentResource, TReusableExpander>) => ClassDecorator;
/**
* Decorator controller/expander method as expandable (for recursive expansion).
* Also used on controller endpoints to enable expansion for the response.
*
* @remarks
* - When used on an @Expander method, enables recursive expansion if that method's return value is requested for further expansion.
* - When used on a controller endpoint, enables expansion for the DTO returned by that endpoint.
*
* @param target - The DTO class returned by the method/endpoint.
* @param config - Additional configuration for expandable parameters.
* @returns A metadata decorator.
*/
export declare const Expandable: (target: Function, config?: Omit<ExpandableParams, "target">) => import("@nestjs/common").CustomDecorator<typeof EXPANDABLE_KEY>;
/**
* Decorator function to mark a controller endpoint response as selectable.
*
* @remarks
* - You can mark all endpoints of your app as selectable by setting the {@link ExpandConfig.enableGlobalSelection} option of the `NestKitExpandModule.forRoot()`.
*
* @returns A metadata decorator.
*/
export declare const Selectable: (config?: SelectableParams) => import("@nestjs/common").CustomDecorator<typeof SELECTABLE_KEY>;
/**
* Injection token for the ExpandConfig.
*/
export declare const EXPAND_CONFIG: unique symbol;
export declare const DEFAULT_EXPAND_CONFIG: Required<ExpandConfig>;