UNPKG

@cisstech/nestjs-expand

Version:

A NestJS module to build Dynamic Resource Expansion for APIs

271 lines (270 loc) 10.4 kB
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>;