/**------------------------------------------ * * * GOOD - COP * * * --------------------------------------------- /!\ Some code patterns used here may not seem to follow good practice at first /!\ Here are some technical choices that have been taken and may not be intuitive: * Everything is in this file, since it's impossible to keep the exact `this` type when putting methods in another file (I tried a lot) * types and functional code are "separated" with returning `as NextAutocompletionChoices` this seems like the best way to choose what to display in the autocomplete suggestion while avoiding a class extension nighmare like in zod (the downside is that autocompletion is not as strict as in zod, but maintenability is way easier). Autocompletion example: when typing `_.object().`, `partial` and `complete` are suggested but `greaterThan` is not /!\ TO ADD A NEW DEFINITION /!\: => FirstLevelTypes: the types displayed on first autocomplete suggestion (base types like number, boolean...) => UniversalMethods: the types displayed everywhere else => You may then select additional methods to suggest via `NextAutocompletionChoices` in the definition */ import 'typescript-generic-types'; import { TranslationObj, MaybeArray } from './core-types.js'; import { DefinitionBase } from './DefinitionBaseClass.js'; import { MongoTypeObj, MongoFieldsRead, MongoFieldsWrite } from './helpers/backendDefinitionsHelpers.js'; import { GoodCopAutoWritedFieldNames, GoodCopDateMethods, GoodCopDefCtx, DefinitionObj, GoodCopDefinitionPartial, CoodCopDefinitionClassReceivedModelType, FirstLevelTypes, GenericDef, InferTypeRead, InferTypeWrite, GoodCopInferTypeArrRead, GoodCopInferTypeArrWrite, GoodCopLengthMethods, GoodCopNextDefinition, GoodCopNumberMethods, GoodCopStringMethods, TypedExclude, GoodCopProvidedModels, GoodCopErrorOptions } from './definitionTypes.js'; import { parseRegexp } from 'topkat-utils'; export declare class Definition extends DefinitionBase { /** Just an alias for tsTypeRead */ tsType: OverridedTypeRead; tsTypeRead: OverridedTypeRead; tsTypeWrite: OverridedTypeWrite; isRequiredType: IsRequiredType; modelTypes: ModelsType; constructor(models?: () => GoodCopProvidedModels, // any is for removing type reference and avoid circular type definition definition?: MaybeArray, previousThis?: any); /** Meant to be used only the first time you init the definition. Eg: new Definition(...).init() to provide correct autocomplete. This is because I couldn't return the good type from constructor. TODO */ init(): Pick; /** This is to create a new definition from configuration and a given type */ private _newDef; /** This is not a definition. This will output the mongo schema final type for definition. Eg: _.mongoModel([], { field1: _.string(), ... }})._getMongoType() === { field1: { type: String } ... } */ _getMongoType(): Record | MongoTypeObj; array(array?: R): GoodCopNextDefinition>, GoodCopInferTypeArrWrite>>>, GoodCopLengthMethods>; any(): GoodCopNextDefinition>>; boolean(): GoodCopNextDefinition>, "mergeWith">; date(): GoodCopNextDefinition>, GoodCopDateMethods>; date8(): GoodCopNextDefinition>, GoodCopDateMethods>; date12(): GoodCopNextDefinition>, GoodCopDateMethods>; /** simple emial validation: /^[^\s@]+@[^\s@]+\.[^\s@]+$/ */ email(): GoodCopNextDefinition>, GoodCopStringMethods>; /** Predefined list of values. Eg: status: _.enum(['success', 'error', 'pending']) OR _.enum([1, 2, 3]) */ enum(possibleValues: [...T] | readonly [...T]): GoodCopNextDefinition>, TypedExclude>; float(): GoodCopNextDefinition>, GoodCopNumberMethods>; false(): GoodCopNextDefinition>, "mergeWith">; true(): GoodCopNextDefinition>, "mergeWith">; /** This is to get the type of an already defined database model. Eg: model('myDb', 'user') to get the user type from a particular db that you registered at initialization */ model(dbId: A, modelName: B, modelType?: C): GoodCopNextDefinition>, "partial" | "complete">; /** With this, you can create mongo models, handling _id field type automatically and creator, lastUpdater... fields */ mongoModel(autoWriteFields: U, model: T): GoodCopNextDefinition & MongoFieldsRead, InferTypeWrite & MongoFieldsWrite>>>; /** force this field to be the userId instead of any id */ forceUserId(): GoodCopNextDefinition>>; /** An object which keys can be anything but where the value shall be typed. Eg: { [k: string]: number } */ genericObject( /** field name can be a string or an array, will be typed as { [string1]: { [string2]: myType } } */ keyName?: FieldName, valueType?: ValueType): GoodCopNextDefinition; } : FieldName extends [string, string] ? { [k: string]: { [k: string]: InferTypeRead; }; } : { [k: string]: { [k: string]: { [k: string]: InferTypeRead; }; }; }, FieldName extends string ? { [k: string]: InferTypeRead; } : FieldName extends [string, string] ? { [k: string]: { [k: string]: InferTypeRead; }; } : { [k: string]: { [k: string]: { [k: string]: InferTypeWrite; }; }; }>>, "partial" | "complete">; /** Only valid on objects, allow to merge two objects */ mergeWith(object: T): GoodCopNextDefinition & typeof this.tsTypeRead, InferTypeWrite & typeof this.tsTypeWrite>>, "partial" | "complete">; /** Array of predefined size and value: Eg: { signature: _.tuple([_.date(), _.string()]) } */ tuple(array: [...R]): GoodCopNextDefinition>>; object(object?: T, { /** Whenever to delete fields that are not included in the original model */ deleteForeignKeys, }?: { deleteForeignKeys?: boolean; }): GoodCopNextDefinition, InferTypeWrite>>, "complete" | "partial" | "mergeWith">; /** For all props of an object type to be OPTIONAL */ partial(): GoodCopNextDefinition, Partial>>, "mergeWith">; integer(): GoodCopNextDefinition>, TypedExclude>; /** String alias for readability. 24 char mongoDb id */ objectId(): GoodCopNextDefinition>, GoodCopStringMethods>; match(...params: [Parameters[0], Parameters[1]]): GoodCopNextDefinition>, TypedExclude>; number(): GoodCopNextDefinition>, GoodCopNumberMethods>; password({ regexp, // at least one upperCase, one lowerCase and a digit minLength, maxLength, encrypt }: { regexp?: RegExp; minLength?: number; maxLength?: number; encrypt(value: string): string | Promise; }): GoodCopNextDefinition>, GoodCopStringMethods>; percentage(): GoodCopNextDefinition>, GoodCopNumberMethods>; ref>(modelName: ModelName, alwaysPopulated?: AlwaysPopulated): GoodCopNextDefinition[ModelName] : AlwaysPopulated extends false ? string : MergeMultipleObjects[ModelName] | string, string>>>; regexp(regexpOrStr: string | RegExp, regexpOptions?: Parameters[1]): GoodCopNextDefinition>, TypedExclude>; string({ acceptEmpty }?: { acceptEmpty?: boolean; }): GoodCopNextDefinition>, GoodCopStringMethods>; stringConstant(hardCodedValue: T): GoodCopNextDefinition>, GoodCopStringMethods>; /** an object who's keys are locale and values are translation string. Eg: `{ fr: 'Salut', en: 'Hi' }` */ translation(): GoodCopNextDefinition>>; /** Simple url validation: /^https?:\/\/.+/ */ url(): GoodCopNextDefinition>, GoodCopStringMethods>; year(): GoodCopNextDefinition>, GoodCopDateMethods>; /** Should be used if the value is expected to be undefined */ void(): GoodCopNextDefinition>>; /** Should be used if the value is expected to be undefined */ undefined(): GoodCopNextDefinition>>; null(): GoodCopNextDefinition>>; /** **Note:** formatting will not work for typesOr checks */ typesOr(types: [...T]): GoodCopNextDefinition>, (typeof this)["tsTypeRead"] extends string ? GoodCopStringMethods : (typeof this)["tsTypeRead"] extends number ? GoodCopNumberMethods : never>; /** useful for database types where some fields may be always defined in read (_id, creationDate...) but not required on creation */ alwaysDefinedInRead(): GoodCopNextDefinition>, (typeof this)["tsTypeRead"] extends string ? GoodCopStringMethods : (typeof this)["tsTypeRead"] extends number ? GoodCopNumberMethods : never>; between(min: number, max: number): GoodCopNextDefinition>, TypedExclude>; /** For all props of an object type to be REQUIRED */ complete(): GoodCopNextDefinition, Required>>, "mergeWith">; gte(minVal: number): GoodCopNextDefinition>, TypedExclude>; greaterThan(minVal: number): GoodCopNextDefinition>, TypedExclude>; gt(minVal: number): GoodCopNextDefinition>, TypedExclude>; isFuture(): GoodCopNextDefinition>, GoodCopDateMethods>; length(length: number, comparisonOperator?: '<' | '>' | '==='): GoodCopNextDefinition>, (typeof this)["tsTypeRead"] extends any[] ? never : GoodCopStringMethods>; lessThan(maxVal: number): GoodCopNextDefinition>, TypedExclude>; lowerCase(): GoodCopNextDefinition>, TypedExclude>; upperCase(): GoodCopNextDefinition>, TypedExclude>; max(maxVal: number): GoodCopNextDefinition>, TypedExclude>; lte(maxVal: number): GoodCopNextDefinition>, TypedExclude>; lt(maxVal: number): GoodCopNextDefinition>, TypedExclude>; min(minVal: number): GoodCopNextDefinition>, TypedExclude>; round2(): GoodCopNextDefinition>, TypedExclude>; positive(): GoodCopNextDefinition>, TypedExclude>; trim(): GoodCopNextDefinition>, TypedExclude>; minLength(minLength: number): GoodCopNextDefinition>, (typeof this)["tsTypeRead"] extends any[] ? never : GoodCopStringMethods>; maxLength(maxLength: number): GoodCopNextDefinition>, (typeof this)["tsTypeRead"] extends any[] ? never : GoodCopStringMethods>; /** Formatting happens first, before every validations */ onFormat(callback: ((ctx: GoodCopDefCtx) => any) | ((ctx: GoodCopDefCtx) => Promise)): GoodCopNextDefinition>, (typeof this)["tsTypeRead"] extends string ? GoodCopStringMethods : (typeof this)["tsTypeRead"] extends number ? GoodCopNumberMethods : never>; default(defaultValue: ((ctx: GoodCopDefCtx) => any) | (string | any[] | Record | Date | boolean | number | null)): GoodCopNextDefinition>, (typeof this)["tsTypeRead"] extends string ? GoodCopStringMethods : (typeof this)["tsTypeRead"] extends number ? GoodCopNumberMethods : never>; optional(): GoodCopNextDefinition>, (typeof this)["tsTypeRead"] extends string ? GoodCopStringMethods : (typeof this)["tsTypeRead"] extends number ? GoodCopNumberMethods : never>; required(): GoodCopNextDefinition>, (typeof this)["tsTypeRead"] extends string ? GoodCopStringMethods : (typeof this)["tsTypeRead"] extends number ? GoodCopNumberMethods : never>; /** Append extra infos to any errors that may throw during format and validate */ errorExtraInfos(errorExtraInfos: GoodCopErrorOptions): GoodCopNextDefinition>, (typeof this)["tsTypeRead"] extends string ? GoodCopStringMethods : (typeof this)["tsTypeRead"] extends number ? GoodCopNumberMethods : never>; /** Alias to write paramName in extraInfos */ name(name: string, paramNumber?: number): Pick; /** NAME => Alias to write paramName in extraInfos */ n(name: string, paramNumber?: number): Pick; /** Make the callback return false to unvalidate this field and trigger an error. Note: validation happens after formating */ onValidate(callback: (ctx: GoodCopDefCtx) => any): GoodCopNextDefinition>, (typeof this)["tsTypeRead"] extends string ? GoodCopStringMethods : (typeof this)["tsTypeRead"] extends number ? GoodCopNumberMethods : never>; promise(): GoodCopNextDefinition>, (typeof this)["tsTypeRead"] extends string ? GoodCopStringMethods : (typeof this)["tsTypeRead"] extends number ? GoodCopNumberMethods : never>; unique(): GoodCopNextDefinition>, (typeof this)["tsTypeRead"] extends string ? GoodCopStringMethods : (typeof this)["tsTypeRead"] extends number ? GoodCopNumberMethods : never>; ts(tsString: string, tsTypeWrite?: string): GoodCopNextDefinition>, (typeof this)["tsTypeRead"] extends string ? GoodCopStringMethods : (typeof this)["tsTypeRead"] extends number ? GoodCopNumberMethods : never>; } export declare const _: Pick, "string" | "number" | "boolean" | "undefined" | "object" | "n" | "any" | "regexp" | "true" | "false" | "null" | "date" | "objectId" | "array" | "year" | "email" | "name" | "ref" | "model" | "password" | "url" | "float" | "integer" | "date12" | "date8" | "enum" | "genericObject" | "mongoModel" | "percentage" | "stringConstant" | "translation" | "tuple" | "typesOr" | "void">;