import type { AutoPath } from '@mikro-orm/core/typings'; import type { SqlEntityManager as EntityManager } from '@mikro-orm/knex'; import { BaseRoutedController, KobpServiceContext, RouteMap, SchemableObject, HttpMethod } from 'kobp'; import { QueryOrderMap } from '@mikro-orm/core'; import { Middleware } from 'koa'; export declare class CrudError extends Error { private constructor(); static coded(type: string, resource: string, detail: string): CrudError; } export declare const helpers: { /** * Advance method for assigning complex object. * @param em * @param obj * @param payload * @returns */ persistNestedCollection(em: EntityManager, cnstr: new () => E, obj: E, payload: any): E; /** * Supported format * * - Date Operator: `$dt(milliseconds)` * - Between Operator: `$between(v1, v2)` * - In Operator: `$in(value split by comma)` * - Like Operator: `$like(value)` -- does not support $datetime * - iLike Operator: `$ilike(value)` -- does not support $datetime * - greater then Operator: `$gt(value)` * - less than Operator: `$lt(value)` * - is null: `$null` * - is not null: `$notNull` * * @param v */ evalQuery(v: string, resourceName: string): Partial<{ [key: string]: any; }> | "void"; }; export interface CrudControllerOption { /** * Calculate an ObjectLiteral to produce where condition for every request. * * Where object should matched the criteria that is needed. * * This will acting as scope limitation. */ forAllResources: (ctx: KobpServiceContext) => Partial<{ [key in keyof E]: any; }>; /** * Searchable fields */ searchableFields: (keyof E)[]; /** * list of fields that can be distincted by _lov endpoint. * * Adding field to this option will allow the controller to invoke (distinct list of value) * It is highly recommend that the fields to be present in this endpoint should be indexed for optimal performance. */ distinctableFields: (keyof E)[]; /** * Default populate options * - one = use when populate select one * - many = use when populate select many */ defaultPopulate: (ctx: KobpServiceContext, isMany: boolean) => AutoPath[]; /** * Injecting filters before any query to be made; * * @see https://mikro-orm.io/docs/filters */ defaultFilters: (ctx: KobpServiceContext, em: EntityManager) => Promise; /** * Process input */ sanitizeInputBody: (ctx: KobpServiceContext, em: EntityManager, body: any, isCreating: boolean) => Promise; /** * Searchable field should be converted */ searchableFieldValueConverter: Partial<{ [key in keyof E]: (raw: any) => string; }>; /** * Sorting options */ orderBy: QueryOrderMap; /** * Load a resource for create method. * * This method will replace basic default constructor upon resource creation. */ loadResourceToCreate: (ctx: KobpServiceContext, em: EntityManager) => Promise; /** * if not provided. Meaning there if only one resource in provided scope. * * Create method will become update method. * Delete method will become disabled. * * Possible value: * - `:paramName` * - `:paramNameAndColumnName` */ resourceKeyPath: string; /** * Hook that will apply to all objects loaded. */ afterLoad: ((ctx: KobpServiceContext, objects: E[]) => Promise)[]; /** * Hook that call to compare loadedFromDb against inputPayload (sanitizedBody). */ computeUpdatePayload: (ctx: KobpServiceContext, em: EntityManager, loadedFromDb: E, inputPayload: any) => Promise; /** * Hook that should never throw Error. */ preSave: ((ctx: KobpServiceContext, em: EntityManager, object: E, isCreating: boolean) => Promise)[]; /** * Hook to tune */ postSave: ((ctx: KobpServiceContext, em: EntityManager, object: E, isCreating: boolean) => Promise)[]; /** * Hook before destructive operation */ preDelete: ((ctx: KobpServiceContext, em: EntityManager, objects: E[]) => Promise)[]; /** * Hook after destructive operation */ postDelete: ((ctx: KobpServiceContext, em: EntityManager, deletedObjects: E[]) => Promise)[]; /** * Use _ as empty value * * Replace /^_$/ with '' value in keypath * * Use this option to avoid empty value in key path. */ replaceUnderscrollWithEmptyKeyPath: boolean; /** * All route middlewares */ middlewares: Middleware[] | ((path: string, method: HttpMethod) => Middleware[]); /** * Use document middleware */ useDocumentMiddleware?: { /** * used in returning payload * * @default to this.cnstr (constructor) which relies on ApiDoc decorator to decorate all properties */ resourceScheme?: SchemableObject; /** * used in updating request * * @default to rootScheme */ updateScheme?: SchemableObject; /** * used in creation request * * @default to rootScheme */ createScheme?: SchemableObject; }; } export declare class CrudController extends BaseRoutedController { private cnstr; readonly resourceName: string; protected options: CrudControllerOption; protected resolvedResourcePath: string; constructor(cnstr: new () => E, resourceName: string, options: Partial>); protected getEntityManager(context: KobpServiceContext): EntityManager; getRouteMaps(): RouteMap; /** * Create a single record. * @param context */ createOne(context: KobpServiceContext): Promise; getOne(context: KobpServiceContext, manager?: EntityManager, _supressFilters?: boolean): Promise; /** * Update a single record. * @param context */ updateOne(context: KobpServiceContext): Promise; /** * Delete requested resource by get the existing one first? * @param context */ deleteOne(context: KobpServiceContext): Promise; /** * !due to unfriendly merge option of filtering object. Nested merge is not really working. We * !utilise existing filter definition, and use it to merge on our own here. * * @param context * @param em */ private _filtersQuery; /** * */ index(context: KobpServiceContext): Promise<{ count: number; items: E[]; }>; distinct(context: KobpServiceContext): Promise; /** * Extract orderBy from incoming `context.request.query`. * @param context */ private _orderBy; private _whereClauseByQuery; /** * Return keyPair mapping of URL parameters. * * Format: * * ``` * :paramName(regex) * * or * :paramName(regex) => columnName = paramName * * or * :paramName => regEx = ([A-Za-z0-9_]{0,}) // ** based on Express document. * ``` */ protected get paramsToColumnNamePairs(): { columnName: string; paramName: string; pattern: string; }[]; private _forKeyPath; }