functional-models 2.1.13 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/types.d.ts ADDED
@@ -0,0 +1,692 @@
1
+ import * as openapi from 'openapi-types';
2
+ /**
3
+ * A function that returns the value, or just the value
4
+ */
5
+ type MaybeFunction<T> = T | (() => T);
6
+ /**
7
+ * The data or a promise that returns the data
8
+ */
9
+ type MaybePromise<T> = T | Promise<T>;
10
+ /**
11
+ * The value or null
12
+ */
13
+ type Nullable<T> = T | null;
14
+ /**
15
+ * The value, or undefined
16
+ */
17
+ type Maybe<T> = T | undefined;
18
+ /**
19
+ * The value or an array of the types of value
20
+ */
21
+ type Arrayable<T> = T | readonly T[];
22
+ /**
23
+ * A JSON compliant object.
24
+ */
25
+ type JsonObj = Readonly<{
26
+ [s: string]: JsonAble | null;
27
+ }>;
28
+ /**
29
+ * A description of valid json values.
30
+ */
31
+ type JsonAble = Arrayable<JsonObj> | readonly (number | string | boolean)[] | number | string | boolean | null;
32
+ /**
33
+ * This is a fully Json compliant version of a DataDescription
34
+ */
35
+ type JsonifiedData<T extends DataDescription> = {
36
+ readonly [P in keyof T]: JsonAble;
37
+ };
38
+ /**
39
+ * Removes the promise over a value
40
+ */
41
+ type Unpromise<T extends Promise<any>> = T extends Promise<infer U> ? U : never;
42
+ /**
43
+ * Removes promises from every property of an object.
44
+ */
45
+ type RemovePromises<T extends object> = {
46
+ [K in keyof T as T[K] extends Promise<any> ? K : never]: Unpromise<T[K]>;
47
+ } & {
48
+ [K in keyof T as T[K] extends Promise<any> ? never : K]: T[K];
49
+ };
50
+ /**
51
+ * The types that are allowed in a choice.
52
+ */
53
+ type ChoiceTypes = null | string | number | boolean;
54
+ /**
55
+ * A Model Reference that is only string|number|undefined|null
56
+ */
57
+ type FlattenModelReferences<TData extends DataDescription> = {
58
+ [K in keyof TData as TData[K] extends ModelInstance<any> ? never : K]: TData[K];
59
+ } & {
60
+ [K in keyof TData as TData[K] extends ModelInstance<TData> ? K : never]: PrimaryKeyType;
61
+ };
62
+ /**
63
+ * The result of a "toObj()" call. See {@link ModelInstance.toObj}
64
+ * This is guaranteed to be JSON compliant.
65
+ */
66
+ type ToObjectResult<TData extends DataDescription> = RemovePromises<FlattenModelReferences<TData>>;
67
+ /**
68
+ * A function that will provide a JSON compliant representation of the data.
69
+ * Useful for saving in a database, or sending out over a network.
70
+ */
71
+ type ToObjectFunction<TData extends DataDescription> = <R extends TData | JsonifiedData<TData> = JsonifiedData<TData>>() => Promise<ToObjectResult<R>>;
72
+ /**
73
+ * Getter functions that provide access to the value of a property of an instance.
74
+ */
75
+ type PropertyGetters<TData extends DataDescription> = {
76
+ readonly [PropertyKey in keyof Required<TData>]: () => TData[PropertyKey];
77
+ };
78
+ /**
79
+ * The most basic description of data supported by this framework.
80
+ * This includes all of JSON and additional functionality for referenced models.
81
+ */
82
+ type DataDescription = Readonly<{
83
+ [s: string]: Promise<PrimaryKeyType> | Arrayable<number> | Arrayable<string> | Arrayable<boolean> | Arrayable<null> | Arrayable<DataDescription> | Arrayable<Date> | Arrayable<undefined> | ModelReference<any> | Arrayable<JsonAble>;
84
+ }>;
85
+ /**
86
+ * These are the allowable types for setting a property of data to.
87
+ */
88
+ type DataValue = MaybePromise<Arrayable<JsonAble> | (() => DataValue) | Arrayable<null> | Arrayable<undefined> | Arrayable<Date> | Arrayable<DataDescription>>;
89
+ /**
90
+ * Additional context to a validation. Sometimes there are other validation information needed than what can be provided within a model itself.
91
+ */
92
+ type ValidatorContext = Readonly<Record<string, any>>;
93
+ /**
94
+ * A collection of errors for a property or model.
95
+ */
96
+ type ValidationErrors = readonly string[];
97
+ /**
98
+ * The response to a validation attempt of a model at the lowest level. Something is bad (a string), or its good (undefined)
99
+ */
100
+ type ComponentValidationErrorResponse = string | undefined;
101
+ /**
102
+ * The errors across an entire model. Contains both overall errors, as well as individualized property errors.
103
+ */
104
+ type ModelErrors<TData extends DataDescription> = {
105
+ readonly [Property in keyof Partial<TData>]: ValidationErrors;
106
+ } & Readonly<{
107
+ overall?: ValidationErrors;
108
+ }>;
109
+ /**
110
+ * The most flexible representation of a Property Validator.
111
+ * @param value - The raw value being evaluated
112
+ * @param instance - The model instance for context.
113
+ * @param instanceData - An already JSONified version of the model. This is a convenience so toObj() does not need to be called so frequently.
114
+ * @param context - Additional outside context to help with validation. (Most cases this is unused)
115
+ */
116
+ type PropertyValidatorComponentTypeAdvanced<TValue, TData extends DataDescription, TModelExtensions extends object = object, TModelInstanceExtensions extends object = object> = (value: TValue, instance: ModelInstance<TData, TModelExtensions, TModelInstanceExtensions>, instanceData: ToObjectResult<TData>, context: ValidatorContext) => ComponentValidationErrorResponse;
117
+ /**
118
+ * A Property Validator that does not use Promises
119
+ */
120
+ type PropertyValidatorComponentSync<TData extends DataDescription, TModelExtensions extends object = object, TModelInstanceExtensions extends object = object> = PropertyValidatorComponentTypeAdvanced<any, TData, TModelExtensions, TModelInstanceExtensions>;
121
+ /**
122
+ * A simple property validator that just looks at the value.
123
+ * @param value - A single value to validate
124
+ */
125
+ type ValuePropertyValidatorComponent<TValue extends Arrayable<DataValue>> = (value: TValue) => ComponentValidationErrorResponse;
126
+ /**
127
+ * A property validator that returns a promise.
128
+ * @param value - The value to validate
129
+ * @param instance - The instance the value comes from
130
+ * @param instanceData - The jsonified version of the data
131
+ * @param context - Additional context to validate against.
132
+ */
133
+ type PropertyValidatorComponentAsync<TData extends DataDescription, TModelExtensions extends object, TModelInstanceExtensions extends object> = (value: Arrayable<DataValue>, instance: ModelInstance<TData, TModelExtensions, TModelInstanceExtensions>, instanceData: ToObjectResult<TData>, context: ValidatorContext) => Promise<ComponentValidationErrorResponse>;
134
+ /**
135
+ * A property validator that is either Sync or Async.
136
+ */
137
+ type PropertyValidatorComponent<TData extends DataDescription, TModelExtensions extends object = object, TModelInstanceExtensions extends object = object> = PropertyValidatorComponentSync<TData, TModelExtensions, TModelInstanceExtensions> | PropertyValidatorComponentAsync<TData, TModelExtensions, TModelInstanceExtensions>;
138
+ /**
139
+ * The validator for an entire property. This is composed of multiple underlying validators that all get executed and then assembled together.
140
+ * @param instanceData - The instance data to compare
141
+ * @param context - Additional context for validating.
142
+ */
143
+ type PropertyValidator<TData extends DataDescription> = (instanceData: ToObjectResult<TData>, context: ValidatorContext) => Promise<ValidationErrors>;
144
+ /**
145
+ * The component of a Model Validator. These are combined to create a single model validator.
146
+ * @param instance - The instance of the model.
147
+ * @param instanceData - The JSONified version of the model.
148
+ * @param context - Additional context to assist with validating.
149
+ */
150
+ type ModelValidatorComponent<TData extends DataDescription, TModelExtensions extends object = object, TModelInstanceExtensions extends object = object> = (instance: ModelInstance<TData, TModelExtensions, TModelInstanceExtensions>, instanceData: ToObjectResult<TData>, context: ValidatorContext) => Promise<ComponentValidationErrorResponse>;
151
+ /**
152
+ * A function that will get the value of a property.
153
+ * Depending on what the property is, it'll either be a primitive value
154
+ * or it'll be a referenced model.
155
+ */
156
+ type ValueGetter<
157
+ /**
158
+ * The type of value
159
+ */
160
+ TValue extends Arrayable<DataValue>,
161
+ /**
162
+ * The value existing within a specific type of data.
163
+ */
164
+ TData extends DataDescription = DataDescription,
165
+ /**
166
+ * Any additional model extensions.
167
+ */
168
+ TModelExtensions extends object = object,
169
+ /**
170
+ * Any additional model instance extensions.
171
+ */
172
+ TModelInstanceExtensions extends object = object> = () => MaybePromise<TValue | ModelInstance<TData, TModelExtensions, TModelInstanceExtensions>>;
173
+ /**
174
+ * An instance of a property. This is used to describe a property in depth as well as provide functionality like validating values.
175
+ * @interface
176
+ */
177
+ type PropertyInstance<
178
+ /**
179
+ * The type of value that the property represents.
180
+ */
181
+ TValue extends Arrayable<DataValue>,
182
+ /**
183
+ * The data that the property sits within.
184
+ */
185
+ TData extends DataDescription = DataDescription,
186
+ /**
187
+ * Any additional model extensions.
188
+ */
189
+ TModelExtensions extends object = object,
190
+ /**
191
+ * Any additional model instance extensions.
192
+ */
193
+ TModelInstanceExtensions extends object = object> = Readonly<{
194
+ /**
195
+ * Gets the configuration passed into the property constructor.
196
+ */
197
+ getConfig: () => object;
198
+ /**
199
+ * Gets available choices for limiting the value of this property.
200
+ */
201
+ getChoices: () => readonly ChoiceTypes[];
202
+ /**
203
+ * If there is a default value
204
+ */
205
+ getDefaultValue: () => TValue | undefined;
206
+ /**
207
+ * If there is a constant value that never changes. (This is used above all else).
208
+ */
209
+ getConstantValue: () => TValue | undefined;
210
+ /**
211
+ * Gets the ValueType of the property. Unless custom properties are used, the value is a {@link PropertyType}.
212
+ * Otherwise the value could be string for custom types.
213
+ */
214
+ getPropertyType: () => PropertyType | string;
215
+ /**
216
+ * Creates a value getter.
217
+ * @param value - The type of value
218
+ * @param modelData - The type of data.
219
+ * @param modelInstance - An instance of the model that has the data.
220
+ */
221
+ createGetter: (value: TValue, modelData: TData, modelInstance: ModelInstance<TData, TModelExtensions, TModelInstanceExtensions>) => ValueGetter<TValue, TData, TModelExtensions, TModelInstanceExtensions>;
222
+ /**
223
+ * Gets a validator for the property. This is not normally used.
224
+ * Instead for validation look at {@link ModelInstance.validate}
225
+ * @param valueGetter - The getter for the value.
226
+ */
227
+ getValidator: (valueGetter: ValueGetter<TValue, TData, TModelExtensions, TModelInstanceExtensions>) => PropertyValidator<TData>;
228
+ }>;
229
+ /**
230
+ * A list of properties that make up a model.
231
+ */
232
+ type PropertiesList<TData extends DataDescription> = {
233
+ readonly [P in keyof TData as TData[P] extends Arrayable<DataValue> ? P : never]: PropertyInstance<any>;
234
+ };
235
+ /**
236
+ * An extends a Property to add additional functions helpful for dealing with
237
+ * referenced models.
238
+ */
239
+ interface ModelReferencePropertyInstance<TData extends DataDescription, TProperty extends Arrayable<DataValue>, TModelExtensions extends object = object, TModelInstanceExtensions extends object = object> extends PropertyInstance<TProperty> {
240
+ /**
241
+ * Gets the id (foreign key) of the referenced model.
242
+ * @param instanceValues - The ModelReference. (key, data, or instance)
243
+ */
244
+ readonly getReferencedId: (instanceValues: ModelReference<TData, TModelExtensions, TModelInstanceExtensions>) => Maybe<PrimaryKeyType>;
245
+ /**
246
+ * Gets reference's model
247
+ */
248
+ readonly getReferencedModel: () => ModelType<TData, TModelExtensions, TModelInstanceExtensions>;
249
+ }
250
+ /**
251
+ * A property of a model that references another model instance.
252
+ * This is a basic implementation of a "foreign key".
253
+ * The value of this property can be either a key type (string|number), or a model instance, or the model data itself. It depends on the ModelInstanceFetcher.
254
+ */
255
+ type ModelReference<TData extends DataDescription, TModelExtensions extends object = object, TModelInstanceExtensions extends object = object> = MaybePromise<TData | ModelInstance<TData, TModelExtensions, TModelInstanceExtensions> | ToObjectResult<TData> | PrimaryKeyType>;
256
+ /**
257
+ * Common property validator choices.
258
+ * @interface
259
+ */
260
+ type CommonValidators = Readonly<{
261
+ /**
262
+ * Is this property required?
263
+ */
264
+ required?: boolean;
265
+ /**
266
+ * Can the property only be an integer?
267
+ */
268
+ isInteger?: boolean;
269
+ /**
270
+ * Can the property only be a number?
271
+ */
272
+ isNumber?: boolean;
273
+ /**
274
+ * Can the property only be a string?
275
+ */
276
+ isString?: boolean;
277
+ /**
278
+ * Is the property an array of values?
279
+ */
280
+ isArray?: boolean;
281
+ /**
282
+ * Is the property only true or false?
283
+ */
284
+ isBoolean?: boolean;
285
+ }>;
286
+ /**
287
+ * Standard configuration options for properties.
288
+ * @interface
289
+ */
290
+ type PropertyConfigOptions<TValue extends Arrayable<DataValue>> = Readonly<Partial<{
291
+ /**
292
+ * A type override to override the property type of a property.
293
+ */
294
+ typeOverride: PropertyType | string;
295
+ /**
296
+ * A default value if one is never given.
297
+ */
298
+ defaultValue: TValue;
299
+ /**
300
+ * Determines if this value needs to go through denormalization.
301
+ */
302
+ isDenormalized: boolean;
303
+ /**
304
+ * The value of the property (if provided)
305
+ */
306
+ value: TValue;
307
+ /**
308
+ * Possible limiting choices of what the property can be.
309
+ */
310
+ choices: readonly ChoiceTypes[];
311
+ /**
312
+ * A lazy loading method, which will only run when the value is actually retrieved.
313
+ * IMPORTANT: Do not include promises as part of this because they are not thread safe.
314
+ * @param value - The current value
315
+ * @param modelData - The models current data
316
+ */
317
+ lazyLoadMethod: <TData extends DataDescription>(value: TValue, modelData: CreateParams<TData>) => TValue;
318
+ /**
319
+ * A thread safe (Atomic) version of lazyLoadMethod. Use this for all lazy loadings that requires Promises.
320
+ * @param value - The current value
321
+ * @param modelData - The models current data.
322
+ */
323
+ lazyLoadMethodAtomic: <TData extends DataDescription>(value: TValue, modelData: CreateParams<TData>) => Promise<TValue>;
324
+ /**
325
+ * An optional function that can select a "part" of the value to return.
326
+ * @param instanceValue
327
+ */
328
+ valueSelector: (instanceValue: MaybePromise<TValue>) => TValue;
329
+ /**
330
+ * Additional validators for the property.
331
+ */
332
+ validators: readonly PropertyValidatorComponent<any>[];
333
+ /**
334
+ * The maximum length of the value. (Drives validation)
335
+ */
336
+ maxLength: number;
337
+ /**
338
+ * The minimum length of the value. (Drives validation)
339
+ */
340
+ minLength: number;
341
+ /**
342
+ * The maximum size of the value. (Drives validation)
343
+ */
344
+ maxValue: number;
345
+ /**
346
+ * The minimum size of the value. (Drives validation)
347
+ */
348
+ minValue: number;
349
+ /**
350
+ * If the value should be created automatically. Used in date creation.
351
+ */
352
+ autoNow: boolean;
353
+ /**
354
+ * If you are using ModelReferences, this is required.
355
+ * A fetcher used for getting model references.
356
+ * This configuration item is used within the {@link AdvancedModelReferenceProperty} and any other property
357
+ * that is lazy loading (atomically) models.
358
+ */
359
+ fetcher: ModelInstanceFetcher;
360
+ }>>;
361
+ /**
362
+ * A function that has the ability to fetch an instance of a model.
363
+ * This is the backbone that provides the "ModelReference" functionality.
364
+ * This is useful downstream for building ORMs and other systems that require
365
+ * hydrating "foreign key" models.
366
+ * @param model - The model type that is being fetched.
367
+ * @param primaryKey - The primary key of the desired data.
368
+ */
369
+ type ModelInstanceFetcher<TModelExtensions extends object = object, TModelInstanceExtensions extends object = object> = <TData extends DataDescription>(model: ModelType<TData, TModelExtensions, TModelInstanceExtensions>, primaryKey: PrimaryKeyType) => Promise<TData | ModelInstance<TData, TModelExtensions, TModelInstanceExtensions> | ToObjectResult<TData>> | Promise<null> | Promise<undefined>;
370
+ /**
371
+ * The configurations for a property.
372
+ */
373
+ type PropertyConfig<TValue extends Arrayable<DataValue>> = (PropertyConfigOptions<TValue> & CommonValidators) | undefined;
374
+ /**
375
+ * Depending on your system a primary key is either a string or a number.
376
+ */
377
+ type PrimaryKeyType = string | number;
378
+ /**
379
+ * A function that has the ability to build models. (The models themselves, not instances of models)
380
+ * This is actually a "factory of model factories" but we're just calling it a ModelFactory.
381
+ *
382
+ * IMPORTANT:
383
+ * If you want to override and create extended Models/ModelInstances this is the place to do it.
384
+ * Create your own ModelFactory that adds additional functionality.
385
+ * For expanding a Model, you can just add it to the overall object. that {@link ModelFactory} produces.
386
+ *
387
+ * For expanding a ModelInstance, you will want to wrap the "create()" function of {@link ModelType}
388
+ *
389
+ * @param modelDefinition - The minimal model definitions needed.
390
+ * @param options - Additional model options.
391
+ */
392
+ type ModelFactory<TModelExtensions extends object = object, TModelInstanceExtensions extends object = object> = <TData extends DataDescription>(modelDefinition: MinimalModelDefinition<TData>, options?: ModelOptions<TData, TModelExtensions, TModelInstanceExtensions>) => ModelType<TData, TModelExtensions, TModelInstanceExtensions>;
393
+ /**
394
+ * Input parameters to a model's create function.
395
+ */
396
+ type CreateParams<TData extends DataDescription, IgnoreProperties extends string = ''> = Omit<TData | RemovePromises<TData>, IgnoreProperties>;
397
+ /**
398
+ * Higher Level Methods associated with a model based API. CRUDS
399
+ */
400
+ declare enum ApiMethod {
401
+ create = "create",
402
+ retrieve = "retrieve",
403
+ update = "update",
404
+ delete = "delete",
405
+ search = "search"
406
+ }
407
+ /**
408
+ * Basic REST information for a model.
409
+ * @interface
410
+ */
411
+ type RestInfo = {
412
+ /**
413
+ * The endpoint (not including the base domain). This format can include ":id" to describe a specific instance id.
414
+ * Example: /api/v2/whatever-i-want/model/:id
415
+ * The following are the defaults by API method:
416
+ * create: '/namespace/app',
417
+ * retrieve: '/namespace/app/id',
418
+ * update: '/namespace/app/id',
419
+ * delete: '/namespace/app/id',
420
+ * search: '/namespace/app/search',
421
+ */
422
+ endpoint: string;
423
+ /**
424
+ * Security descriptions
425
+ */
426
+ security: openapi.OpenAPIV3_1.SecurityRequirementObject;
427
+ /**
428
+ * The HTTP Method. The following are the defaults used:
429
+ * create: post,
430
+ * retrieve: get,
431
+ * update: put,
432
+ * delete: delete,
433
+ * search: post,
434
+ */
435
+ method: openapi.OpenAPIV3_1.HttpMethods;
436
+ };
437
+ /**
438
+ * A minimum input for a RestInfo.
439
+ */
440
+ type RestInfoMinimum = {
441
+ security?: openapi.OpenAPIV3_1.SecurityRequirementObject;
442
+ } & Omit<RestInfo, 'security'>;
443
+ /**
444
+ * Functional API documentation for a given model. This allows the automatic creation of tools and documentation such as OpenApi specs.
445
+ * This uses the standard "CRUDS" api methods that you might see on any API involving a model.
446
+ * Create, Retrieve, Update, Delete, Search
447
+ * @interface
448
+ */
449
+ type ApiInfo = {
450
+ /**
451
+ * If true, no api information should be published. This means, that no code-generation tool should produce
452
+ * any api code/documentation as it relates to this model. If you want partial publishing, look at "onlyPublish"
453
+ */
454
+ noPublish: boolean;
455
+ /**
456
+ * Similar to noPublish, but granular. This will only publish the methods shown. If noPublish is provided,
457
+ * this will be empty. If onlyPublish is empty, and noPublish is false, then all methods will be published.
458
+ */
459
+ onlyPublish: readonly ApiMethod[];
460
+ /**
461
+ * A description of each Api method to its rest info.
462
+ * If this is not manually overrided then defaults are used for each.
463
+ */
464
+ rest: Record<ApiMethod, RestInfo>;
465
+ /**
466
+ * Create normally can support bulk inserts (more than one). If this property is true, create will only handle "one" model at a time.
467
+ */
468
+ createOnlyOne: boolean;
469
+ };
470
+ /**
471
+ * An {@link ApiInfo} that has only part of RestInfo completed. (useful for overriding defaults)
472
+ * @interface
473
+ */
474
+ type ApiInfoPartialRest = Readonly<{
475
+ rest: Partial<Record<ApiMethod, RestInfoMinimum>>;
476
+ }> & Omit<ApiInfo, 'rest'>;
477
+ /**
478
+ * Expressively defines metadata for a given model.
479
+ * @interface
480
+ */
481
+ type ModelDefinition<TData extends DataDescription> = Readonly<{
482
+ /**
483
+ * The primary name for the model and instances of the model. This should be a name for multiple of the model instances.
484
+ */
485
+ pluralName: string;
486
+ /**
487
+ * The name that this model exists within, such as an app. This is used to combine with the pluralName to create
488
+ * a unique name across a system that it is used in.
489
+ *
490
+ * Recommended:
491
+ * If you are creating reusable libraries/packages for people, we recommend using the name of the package itself.
492
+ * Example: "@my-scoped-package/name"
493
+ *
494
+ * If you are creating this model to be used locally, just use the "app" name that the model corresponds to.
495
+ * Example: "auth"
496
+ *
497
+ * The namespace is also used in the auto-generation of {@link RestInfo.endpoint}. If you want to design the endpoint so that it looks/reads/flows better then consider overriding the endpoint yourself.
498
+ */
499
+ namespace: string;
500
+ /**
501
+ * The properties that make up the model.
502
+ */
503
+ properties: PropertiesList<Required<TData>>;
504
+ /**
505
+ * The name of the property that has the unique id for the model. Used to uniquely identify instances of this model vs other ones.
506
+ */
507
+ primaryKeyName: string;
508
+ /**
509
+ * Validators of the overall model (rather than properties)
510
+ */
511
+ modelValidators: readonly ModelValidatorComponent<TData>[];
512
+ /**
513
+ * The name for a model/instance where there is one of them.
514
+ */
515
+ singularName: string;
516
+ /**
517
+ * A text used for displaying the name of the model in a UI.
518
+ */
519
+ displayName: string;
520
+ /**
521
+ * A helpful human-readable description that explains what the model is and what it is used for.
522
+ */
523
+ description: string;
524
+ /**
525
+ * The raw api information provided in. When looking for a fleshed out version of this data
526
+ * look at {@link ModelType.getApiInfo}
527
+ */
528
+ api?: Partial<ApiInfoPartialRest>;
529
+ }>;
530
+ /**
531
+ * The most minimum information needed to create a model.
532
+ * @interface
533
+ */
534
+ type MinimalModelDefinition<TData extends DataDescription> = Partial<ModelDefinition<TData>> & {
535
+ namespace: string;
536
+ pluralName: string;
537
+ properties: PropertiesList<Required<TData>>;
538
+ };
539
+ /**
540
+ * Represents a Model. A Model creates instances (ModelInstance) as well as describes generally about the data. (ModelDefinition).
541
+ * @typeParam TData - The type of data
542
+ * @typeParam TModelExtensions - Extensions on the model.
543
+ * @typeParam TModelInstanceExtensions - Extensions on the instances produced by this model.
544
+ * @interface
545
+ */
546
+ type ModelType<TData extends DataDescription, TModelExtensions extends object = object, TModelInstanceExtensions extends object = object> = Readonly<{
547
+ /**
548
+ * This is a unique name combining namespace + pluralName. This can be used as a key to uniquely identify
549
+ * this model across an entire system.
550
+ * Example:
551
+ * pluralName=MyModels
552
+ * namespace=@my-package/namespace
553
+ *
554
+ * Return: '@my-package/namespace-my-models'
555
+ */
556
+ getName: () => string;
557
+ /**
558
+ * Gets the metadata that describes the model.
559
+ */
560
+ getModelDefinition: () => ModelDefinition<TData>;
561
+ /**
562
+ * Gets the primary key of instance data. This helpful method shortcuts having to figure out the primaryKey's name
563
+ * and then reaching inside the instance data to get the primary key.
564
+ * @param instanceData The underlying instance data that has the primary key.
565
+ */
566
+ getPrimaryKey: (instanceData: TData | ToObjectResult<TData>) => PrimaryKeyType;
567
+ /**
568
+ * Gets the options that were passed into the model.
569
+ */
570
+ getOptions: () => object & ModelOptions<TData>;
571
+ /**
572
+ * Gets the Api Information on the model.
573
+ *
574
+ * This will take what is manually provided via the ModelDefinition and autopopulate everything that is possible
575
+ * with default values, or values that make sense based on the ApiInformation provided.
576
+ */
577
+ getApiInfo: () => Required<ApiInfo>;
578
+ /**
579
+ * Creates an instance of this model with the data that is provided.
580
+ *
581
+ * @typeParam IgnorePrimaryKey - One or more properties to ignore type restrictions on. This is extremely useful for primaryKeys that have not been created yet, or other generated properties (that are required instead of optional).
582
+ * @param data - The data that makes up an instance of the model.
583
+ * NOTE: A tradeoff was made between supporting the DataDescription vs a ToObjectReturn<DataDescription>. One or the other could be supported, but not both.
584
+ * In order to support executing create() while passing in data that comes from ".toObj()" we recommend using that case feature of toObj().
585
+ */
586
+ create: <IgnoreProperties extends string = ''>(data: CreateParams<TData, IgnoreProperties>) => ModelInstance<TData, TModelExtensions, TModelInstanceExtensions>;
587
+ }> & TModelExtensions;
588
+ /**
589
+ * A function that can provide a model reference.
590
+ */
591
+ type ModelReferenceFunctions = Record<string, () => Maybe<PrimaryKeyType>>;
592
+ /**
593
+ * Records of Property name to Validator.
594
+ */
595
+ type PropertyValidators<TData extends DataDescription> = Readonly<Record<string, PropertyValidator<TData>>>;
596
+ /**
597
+ * An instance of a Model. This "wrapper" fully embodies the power of the framework, and provides the most enrichment of a single piece of a data possible.
598
+ * @typeParam TData - The type of data
599
+ * @typeParam TModelExtensions - Extensions on the overall model.
600
+ * @typeParam TModelInstanceExtensions - Extensions on all instances of a model.
601
+ * @interface
602
+ */
603
+ type ModelInstance<TData extends DataDescription, TModelExtensions extends object = object, TModelInstanceExtensions extends object = object> = Readonly<{
604
+ /**
605
+ * Gets the value of individual properties on the instance.
606
+ * These are memoized.
607
+ */
608
+ get: PropertyGetters<TData>;
609
+ /**
610
+ * Gets all model references that this instance may have as record of property name to function getter.
611
+ *
612
+ */
613
+ getReferences: () => ModelReferenceFunctions;
614
+ /**
615
+ * Gets a basic representation of the data.
616
+ * This function is memoized.
617
+ */
618
+ toObj: ToObjectFunction<TData>;
619
+ /**
620
+ * Gets the primary key of the instance (without having to know the primary key name).
621
+ */
622
+ getPrimaryKey: () => PrimaryKeyType;
623
+ /**
624
+ * Gets the validators for this model instance.
625
+ */
626
+ getValidators: () => PropertyValidators<TData>;
627
+ /**
628
+ * Runs validation against this instance.
629
+ * This function is memoized.
630
+ * @param options
631
+ */
632
+ validate: (options?: object) => Promise<ModelErrors<TData> | undefined>;
633
+ /**
634
+ * Gets the model that backs this instance.
635
+ */
636
+ getModel: () => ModelType<TData, TModelExtensions, TModelInstanceExtensions>;
637
+ }> & TModelInstanceExtensions;
638
+ /**
639
+ * A callback function for receiving when a new model has been created.
640
+ * @param instance - A newly created model instance.
641
+ */
642
+ type ModelCreatedCallback<TData extends DataDescription, TModelExtensions extends object = object, TModelInstanceExtensions extends object = object> = (instance: ModelInstance<TData, TModelExtensions, TModelInstanceExtensions>) => void;
643
+ /**
644
+ * Options to pass into model generation.
645
+ * @interface
646
+ */
647
+ type ModelOptions<TData extends DataDescription, TModelExtensions extends object = object, TModelInstanceExtensions extends object = object> = Record<string, any> & Readonly<{
648
+ /**
649
+ * 1 or more (array) of callback functions for when models get created.
650
+ */
651
+ instanceCreatedCallback?: Arrayable<ModelCreatedCallback<TData, TModelExtensions, TModelInstanceExtensions>>;
652
+ }>;
653
+ /**
654
+ * A function that can calculate a denormalized value. This is very useful for property values that have very complicated and often expensive calculations (but should be calculated once).
655
+ * NOTE: The data that comes in (to be normalized) via the modelData, is the raw data passed into create(). If other functions must fire to create values, they will not be present. Example: Foreign keys.
656
+ * @param modelData - The model's data as it was passed into the create() function.
657
+ * @param modelInstance - The instance that the model corresponds with
658
+ */
659
+ type CalculateDenormalization<TValue extends DataValue, TData extends DataDescription, TModelExtensions extends object = object, TModelInstanceExtensions extends object = object> = (modelData: CreateParams<TData>, modelInstance: ModelInstance<TData, TModelExtensions, TModelInstanceExtensions>) => MaybePromise<TValue | undefined>;
660
+ /**
661
+ * Higher level value types that describe what the value of a property is.
662
+ * These values can be used to generate expressive APIs as well as GUI elements.
663
+ */
664
+ declare enum PropertyType {
665
+ UniqueId = "UniqueId",
666
+ Date = "Date",
667
+ Datetime = "Datetime",
668
+ Array = "Array",
669
+ ModelReference = "ModelReference",
670
+ Integer = "Integer",
671
+ Text = "Text",
672
+ BigText = "BigText",
673
+ Number = "Number",
674
+ Object = "Object",
675
+ Email = "Email",
676
+ Boolean = "Boolean"
677
+ }
678
+ /**
679
+ * The most primitive data types that can be used.
680
+ */
681
+ declare enum PrimitiveValueType {
682
+ boolean = "boolean",
683
+ string = "string",
684
+ object = "object",
685
+ number = "number",
686
+ integer = "integer"
687
+ }
688
+ /**
689
+ * Dates can either be a Date or a string
690
+ */
691
+ type DateValueType = Date | string;
692
+ export { PrimitiveValueType, PropertyType, MaybeFunction, Maybe, MaybePromise, Nullable, Arrayable, JsonAble, ToObjectFunction, ToObjectResult, ModelInstance, ModelType, PropertyValidatorComponent, PropertyValidatorComponentSync, PropertyValidatorComponentAsync, PropertyValidator, ModelValidatorComponent, PropertyInstance, PropertyConfig, DataValue, ValueGetter, ModelReference, ModelDefinition, ModelOptions, ModelReferencePropertyInstance, PropertyGetters, PropertyValidators, PropertyValidatorComponentTypeAdvanced, DataDescription, ModelReferenceFunctions, ModelErrors, PrimaryKeyType, ModelFactory, ModelInstanceFetcher, CreateParams, ValidatorContext, ValuePropertyValidatorComponent, ValidationErrors, ComponentValidationErrorResponse, JsonifiedData, JsonObj, CalculateDenormalization, PropertiesList, MinimalModelDefinition, ChoiceTypes, PropertyConfigOptions, CommonValidators, DateValueType, ApiInfo, RestInfo, ApiMethod, RemovePromises, FlattenModelReferences, Unpromise, ApiInfoPartialRest, RestInfoMinimum, };