import { User, NoExtraProperties, MaybePromise, ObjectWithNoFn } from './core-types.js'; import type { Definition } from './DefinitionClass.js'; /** Type that matches all possible definitions */ export type DefinitionOut = Required> & Partial>; export type TypedExclude = Exclude; export type EnsureIsDefMethod = T; export type FirstLevelTypes = EnsureIsDefMethod<'any' | 'array' | 'boolean' | 'date' | 'date12' | 'date8' | 'email' | 'enum' | 'false' | 'float' | 'genericObject' | 'integer' | 'model' | 'mongoModel' | 'n' | 'name' | 'null' | 'number' | 'object' | 'objectId' | 'password' | 'percentage' | 'ref' | 'regexp' | 'string' | 'stringConstant' | 'translation' | 'true' | 'tuple' | 'typesOr' | 'undefined' | 'url' | 'void' | 'year'>; export type GoodCopUniversalMethods = EnsureIsDefMethod<'alwaysDefinedInRead' | '_definitions' | '_getDefinitionObjFlat' | '_getObjectCache' | '_getMongoType' | '_pushNewDef' | '_refValue' | 'default' | 'errorExtraInfos' | 'formatAndValidate' | 'getDefinitionValue' | 'getMainType' | 'getName' | 'getTsTypeAsString' | 'getSwaggerType' | 'getExampleValue' | 'isRequired' | 'isRequiredType' | 'isType' | 'onFormat' | 'onValidate' | 'optional' | 'promise' | 'required' | 'ts' | 'tsTypeRead' | 'tsTypeWrite' | 'tsType' | 'unique'>; export type GoodCopLengthMethods = EnsureIsDefMethod<'length' | 'maxLength' | 'minLength'>; export type GoodCopNumberMethods = EnsureIsDefMethod<'between' | 'greaterThan' | 'gt' | 'gte' | 'lt' | 'lte' | 'max' | 'min' | 'lessThan' | 'round2' | 'positive'>; export type GoodCopStringMethods = 'lowerCase' | 'upperCase' | 'trim' | 'match' | GoodCopLengthMethods; export type GoodCopDateMethods = 'isFuture'; export type GoodCopSecondLevelMethods = Exclude; export type GoodCopNextDefinition, Keys extends GoodCopSecondLevelMethods = never> = Pick; import { ErrorOptions } from 'topkat-utils'; export type GoodCopDaoGenericMethods = 'create' | 'update' | 'delete' | 'getOne' | 'getAll'; export type GoodCopMongoTypesString = 'date' | 'number' | 'boolean' | 'object' | 'string' | 'mixed' | 'objectId'; export type GoodCopMainTypes = Exclude | 'array' | 'any' | 'undefined'; export type GoodCopDefinitionPartialFn = () => GoodCopDefinitionPartial & { priority: number; }; export type GoodCopDefinitionPartial = NoExtraProperties<{ /** A string representation of the type BUT NOT TYPESCRIPT */ mainType?: GoodCopMainTypes; /** Name of the definition for used for debugging purpose */ name?: string; /** The lower, the more precedence it will take */ priority?: number; /** Documentation, not used actually */ doc?: string; /** Error message displayed when the validate function return falsey value */ errorMsg?: string | ((ctx: GoodCopDefCtx) => MaybePromise); /** Shall represent the ts type, the value should never be evaluated in code, only the inferred type, so we can type as `{ tsType: '' as any as anyTypeYouWant }` */ tsType?: ((previousType: string, depth?: number) => string) | any; /** string representation of the typescript type */ tsTypeStr?: ((previousType: string, depth?: number) => string) | string; /** string representation of the typescript type for write methods (update, create) */ tsTypeStrForWrite?: ((previousType: string, depth?: number) => string) | string; /** Use function to modify mongoType object directly, use object to pass a full or a string to define which type to use for mongo for that field */ mongoType?: ((mongoTypeObj: Record, definitions: (GoodCopDefinitionPartial | GoodCopDefinitionPartialFn)[]) => any) | GoodCopMongoTypesString | Record; /** string representation of the Swagger type */ swaggerType?: SwaggerSchema | ((depth?: number) => SwaggerSchema); /** string representation of an example value */ exempleValue?: string | ((depth?: number) => string); /** should return a truthy value if valid and falsey if not. Actually validation is done AFTER formatting. If you want it differently please use validateBeforeFormatting() */ validate?: (ctx: GoodCopDefCtx) => (any | Promise); /** This happen BEFORE formatting, unless classic validation should return a truthy value if valid and falsey if not */ validateBeforeFormatting?: (ctx: GoodCopDefCtx) => (any | Promise); format?: (ctx: GoodCopDefCtx) => (any | Promise); /** field is always defined when reading, for example if it has a default value */ alwaysDefinedInRead?: true; /** shall the function be triggered on undefined fields */ triggerOnUndefineds?: boolean; /** triggered only when method is the one selected */ methods?: GoodCopDaoGenericMethods | GoodCopDaoGenericMethods[]; required?: boolean; ref?: string; dbName?: string; model?: string; errorExtraInfos?: ErrorOptions; /** define param name when for example in an array (paramsValidator...) */ paramName?: string; /** */ objectCache?: DefinitionObjChild; /** does the field is an array or object that contains other definitions */ isParent?: boolean; /** used to determine the number of nested generic objects, when generic type is used */ nbNestedGenericObjects?: 1 | 2 | 3; /** Determine that null is a valid value for the field */ acceptNull?: boolean; }>; export interface GoodCopDefCtx { modelName: string; addressInParent: string; errorExtraInfos: ObjectWithNoFn; definition: GoodCopDefinitionPartial; dbId?: string; dbName?: string; method: GoodCopDaoGenericMethods; value: any; fields: ObjectWithNoFn; fieldAddr: string; map?: ObjectWithNoFn; user: User; /** Track depth in recursive functions */ depth: number; } export type GoodCopDefCtxWithoutValueAndAddr = Omit; export type InferType = InferTypeRead; /** Infer type for definition or object / array of definitions and all read methods (some requirement may vary between read/write types) */ export type InferTypeRead = T extends GenericDef ? T['tsTypeRead'] : { [K in keyof T as T[K] extends GenericDef ? T[K]['isRequiredType'] extends true ? K : never : K]: T[K] extends GenericDef ? T[K]['tsTypeRead'] : T[K] extends any[] ? GoodCopInferTypeArrRead : T[K] extends Record ? InferTypeRead : never; } & { [K in keyof T as T[K] extends GenericDef ? T[K]['isRequiredType'] extends true ? never : K : never]?: T[K] extends GenericDef ? T[K]['tsTypeRead'] : T[K] extends any[] ? GoodCopInferTypeArrRead : T[K] extends Record ? InferTypeRead : never; }; export type GenericDef = { tsType: any; tsTypeRead: any; tsTypeWrite: any; isRequiredType: boolean; getTsTypeAsString: () => ({ read: string; write: string; }); getSwaggerType: (depth?: number) => SwaggerSchema; getExampleValue: (depth?: number) => any; _definitions: GoodCopDefinitionPartial[]; }; export type GenericDefinition = GenericDef; export type GoodCopInferTypeArrRead = T extends [] ? [] : T[number] extends (infer U) ? U extends GenericDef ? U['tsTypeRead'][] : U extends Record ? InferTypeRead[] : never : never; /** Infer type for definition or object / array of definitions and all write methods (some requirement may vary between read/write types) */ export type InferTypeWrite = T extends GenericDef ? T['tsTypeWrite'] : { [K in keyof T as T[K] extends GenericDef ? T[K]['isRequiredType'] extends true ? K : never : K]: T[K] extends GenericDef ? T[K]['tsTypeWrite'] : T[K] extends any[] ? GoodCopInferTypeArrWrite : T[K] extends Record ? InferTypeWrite : never; } & { [K in keyof T as T[K] extends GenericDef ? T[K]['isRequiredType'] extends true ? never : K : never]?: T[K] extends GenericDef ? T[K]['tsTypeWrite'] : T[K] extends any[] ? GoodCopInferTypeArrWrite : T[K] extends Record ? InferTypeWrite : never; }; export type GoodCopInferTypeArrWrite = T extends [] ? [] : T[number] extends (infer U) ? U extends GenericDef ? U['tsTypeWrite'][] : U extends Record ? InferTypeWrite[] : never : never; export type DefinitionObjChild = GenericDef | DefinitionObj | GenericDef[] | DefinitionObj[]; export type DefinitionObj = { [field: string]: DefinitionObjChild; }; export type GoodCopAutoWritedFieldNames = 'lastUpdateDate' | 'creationDate' | 'lastUpdater' | 'creator'; export type CoodCopDefinitionClassReceivedModelType = { [databaseName: string]: { [modelName: string]: GoodCopModelReadWrite; }; }; export type GoodCopModelReadWrite = { Write: Record; Read: Record; }; export type GoodCopProvidedModels = { [databaseName: string]: { [modelName: string]: GenericDef; }; }; export type SwaggerSchema = { type: Record; example?: undefined; } | { oneOf: SwaggerSchema[]; example?: any; } | { type: 'string'; format?: 'byte' | 'binary' | 'date' | 'date-time' | 'password' | 'email' | 'uuid' | 'url'; example?: string; enum?: string[]; } | { type: 'number'; format?: 'float' | 'double'; example?: number; } | { type: 'integer'; format?: 'int32' | 'int64'; example?: number; } | { type: 'boolean'; example?: boolean; } | { type: 'array'; items: SwaggerSchema | {}; example?: any[]; } | { type: 'object'; properties?: Record; required?: string[]; example?: Record; }; export type GoodCopErrorOptions = Partial<{ code: number; doNotThrow: boolean; err: any; notifyAdmins: boolean; doNotDisplayCode: boolean; doNotWaitOneFrameForLog: boolean; noStackTrace: boolean; }> & Record;