UNPKG

10.7 kBTypeScriptView Raw
1// Copyright IBM Corp. 2018,2019. All Rights Reserved.
2// Node module: loopback-datasource-juggler
3// This file is licensed under the MIT License.
4// License text available at https://opensource.org/licenses/MIT
5
6import {EventEmitter} from 'events';
7import {AnyObject, Options} from './common';
8import {DataSource} from './datasource';
9import {Listener, OperationHookContext} from './observer-mixin';
10
11/**
12 * Property types
13 */
14export type PropertyType =
15 | string
16 | Function
17 | {[property: string]: PropertyType};
18
19/**
20 * Property definition
21 */
22export interface PropertyDefinition extends AnyObject {
23 type?: PropertyType;
24 id?: boolean | number;
25}
26
27/**
28 * Schema definition
29 */
30export interface Schema {
31 name: string;
32 properties: ModelProperties;
33 settings?: ModelSettings;
34}
35
36/**
37 * ID definition
38 */
39export interface IdDefinition {
40 name: string;
41 id: number;
42 property: AnyObject;
43}
44
45/**
46 * Index definition
47 */
48export interface IndexDefinition extends AnyObject {}
49
50/**
51 * Column metadata
52 */
53export interface ColumnMetadata extends AnyObject {
54 name: string;
55}
56
57/**
58 * Definition of model properties, for example
59 * ```ts
60 * {
61 * name: {type: String, required: true},
62 * }
63 * ```
64 */
65export interface ModelProperties {
66 [name: string]: PropertyDefinition
67}
68
69/**
70 * Model settings, for example
71 * ```ts
72 * {
73 * strict: true,
74 * }
75 * ```
76 */
77export interface ModelSettings extends AnyObject {
78 strict?: boolean;
79 forceId?: boolean;
80}
81
82/**
83 * Model definition
84 */
85export declare class ModelDefinition extends EventEmitter implements Schema {
86 name: string;
87 properties: ModelProperties;
88 rawProperties: AnyObject;
89 settings?: ModelSettings;
90 relations?: AnyObject[];
91
92 constructor(
93 modelBuilder: ModelBuilder | null | undefined,
94 name: string,
95 properties?: ModelProperties,
96 settings?: ModelSettings,
97 );
98 constructor(modelBuilder: ModelBuilder | null | undefined, schema: Schema);
99
100 tableName(connectorType: string): string;
101 columnName(connectorType: string, propertyName: string): string;
102 columnNames(connectorType: string): string[];
103 columnMetadata(connectorType: string, propertyName: string): ColumnMetadata;
104
105 ids(): IdDefinition[];
106 idName(): string;
107 idNames(): string[];
108
109 defineProperty(
110 propertyName: string,
111 propertyDefinition: PropertyDefinition,
112 ): void;
113 indexes(): {[name: string]: IndexDefinition};
114 build(forceRebuild?: boolean): AnyObject;
115 toJSON(forceRebuild?: boolean): AnyObject;
116}
117
118/**
119 * Base class for LoopBack 3.x models
120 */
121export declare class ModelBase {
122 static dataSource?: DataSource;
123 static modelName: string;
124 static definition: ModelDefinition;
125 static readonly base: typeof ModelBase;
126
127 /**
128 * Extend the model with the specified model, properties, and other settings.
129 * For example, to extend an existing model:
130 *
131 * ```js
132 * const Customer = User.extend('Customer', {
133 * accountId: String,
134 * vip: Boolean
135 * });
136 * ```
137 *
138 * @param className Name of the new model being defined.
139 * @param subClassProperties child model properties, added to base model
140 * properties.
141 * @param subClassSettings child model settings such as relations and acls,
142 * merged with base model settings.
143 */
144 static extend<ChildModel extends typeof ModelBase = typeof ModelBase>(
145 modelName: string,
146 properties?: ModelProperties,
147 settings?: ModelSettings,
148 ): ChildModel;
149
150 /**
151 * Attach the model class to a data source
152 * @param ds The data source
153 */
154 static attachTo(ds: DataSource): void;
155
156 /**
157 * Get model property type.
158 * @param {string} propName Property name
159 * @returns {string} Name of property type
160 */
161 static getPropertyType(propName: string): string | null;
162
163 /**
164 * Checks if property is hidden.
165 * @param {string} propertyName Property name
166 * @returns {Boolean} true or false if hidden or not.
167 */
168 static isHiddenProperty(propertyName: string): boolean;
169
170 /**
171 * Checks if property is protected.
172 * @param {string} propertyName Property name
173 * @returns {Boolean} true or false if protected or not.
174 */
175 static isProtectedProperty(propertyName: string): boolean;
176
177 /**
178 * Gets properties defined with 'updateOnly' flag set to true from the model.
179 * This flag is also set to true internally for the id property, if this
180 * property is generated and IdInjection is true.
181 * @returns {updateOnlyProps} List of properties with updateOnly set to true.
182 */
183 static getUpdateOnlyProperties(): string[];
184
185 /**
186 * Constructor for ModelBase
187 *
188 * NOTE: We have to use `constructor(...args: any[]);` so that it can be used
189 * for `return class extends superClass`.
190 *
191 * @param {AnyObject} data Initial object data
192 * @param {Options} options An object to control the instantiation
193 */
194 constructor(...args: any[]);
195 // constructor(data: AnyObject, options?: Options);
196
197 /**
198 * Convert the model instance to a plain json object
199 */
200 toJSON(): AnyObject;
201
202 /**
203 * Populate properties from a JSON object
204 * @param obj The source object
205 */
206 fromObject(obj: AnyObject): void;
207
208 /**
209 * Convert model instance to a plain JSON object.
210 * Returns a canonical object representation (no getters and setters).
211 *
212 * @param options Options for the conversion
213 * @property {boolean} onlySchema Restrict properties to dataSource only.
214 * Default is false. If true, the function returns only properties defined
215 * in the schema; Otherwise it returns all enumerable properties.
216 * @property {boolean} removeHidden Boolean flag as part of the transformation.
217 * If true, then hidden properties should not be brought out.
218 * @property {boolean} removeProtected Boolean flag as part of the transformation.
219 * If true, then protected properties should not be brought out.
220 * @returns {object} returns Plain JSON object
221 */
222 toObject(options?: Options): AnyObject;
223
224 /**
225 * Define a property on the model.
226 * @param {string} prop Property name
227 * @param definition Various property configuration
228 */
229 defineProperty(
230 propertyName: string,
231 definition: Partial<PropertyDefinition>,
232 ): void;
233
234 getDataSource(): DataSource;
235
236 /**
237 *
238 * @param {string} anotherClass could be string or class. Name of the class
239 * or the class itself
240 * @param {Object} options An object to control the instantiation
241 * @returns {ModelClass}
242 */
243 static mixin(
244 anotherClass: string | ModelBaseClass | object,
245 options?: Options,
246 ): ModelBaseClass;
247
248 // ObserverMixin members are added as static methods, this is difficult to
249 // describe in TypeScript in a way that's easy to use by consumers.
250 // As a workaround, we include a copy of ObserverMixin members here.
251 //
252 // Ideally, we want to describe the context argument as
253 // `OperationHookContext<this>`. Unfortunately, that's not supported by
254 // TypeScript for static members. A nice workaround is described in
255 // https://github.com/microsoft/TypeScript/issues/5863#issuecomment-410887254
256 // - Describe the context using a generic argument `T`.
257 // - Use `this: T` argument to let the compiler infer what's the target
258 // model class we are going to observe.
259
260 /**
261 * Register an asynchronous observer for the given operation (event).
262 *
263 * Example:
264 *
265 * Registers a `before save` observer for a given model.
266 *
267 * ```javascript
268 * MyModel.observe('before save', function filterProperties(ctx, next) {
269 * if (ctx.options && ctx.options.skipPropertyFilter) return next();
270 * if (ctx.instance) {
271 * FILTERED_PROPERTIES.forEach(function(p) {
272 * ctx.instance.unsetAttribute(p);
273 * });
274 * } else {
275 * FILTERED_PROPERTIES.forEach(function(p) {
276 * delete ctx.data[p];
277 * });
278 * }
279 * next();
280 * });
281 * ```
282 *
283 * @param {String} operation The operation name.
284 * @callback {function} listener The listener function. It will be invoked with
285 * `this` set to the model constructor, e.g. `User`.
286 * @end
287 */
288 static observe<T extends typeof ModelBase>(
289 this: T,
290 operation: string,
291 listener: Listener<OperationHookContext<T>>,
292 ): void;
293
294 /**
295 * Unregister an asynchronous observer for the given operation (event).
296 *
297 * Example:
298 *
299 * ```javascript
300 * MyModel.removeObserver('before save', function removedObserver(ctx, next) {
301 * // some logic user want to apply to the removed observer...
302 * next();
303 * });
304 * ```
305 *
306 * @param {String} operation The operation name.
307 * @callback {function} listener The listener function.
308 * @end
309 */
310 static removeObserver<T extends typeof ModelBase>(
311 this: T,
312 operation: string,
313 listener: Listener<OperationHookContext<T>>,
314 ): Listener<OperationHookContext<T>> | undefined;
315
316 /**
317 * Unregister all asynchronous observers for the given operation (event).
318 *
319 * Example:
320 *
321 * Remove all observers connected to the `before save` operation.
322 *
323 * ```javascript
324 * MyModel.clearObservers('before save');
325 * ```
326 *
327 * @param {String} operation The operation name.
328 * @end
329 */
330 static clearObservers(operation: string): void;
331}
332
333export type ModelBaseClass = typeof ModelBase;
334
335export declare class ModelBuilder extends EventEmitter {
336 static defaultInstance: ModelBuilder;
337
338 models: {[name: string]: ModelBaseClass};
339 definitions: {[name: string]: ModelDefinition};
340 settings: ModelSettings;
341
342 defaultModelBaseClass: typeof ModelBase;
343
344 getModel(name: string, forceCreate?: boolean): ModelBaseClass;
345
346 getModelDefinition(name: string): ModelDefinition | undefined;
347
348 define(
349 className: string,
350 properties?: ModelProperties,
351 settings?: ModelSettings,
352 parent?: ModelBaseClass,
353 ): ModelBaseClass;
354
355 defineProperty(
356 modelName: string,
357 propertyName: string,
358 propertyDefinition: AnyObject,
359 ): void;
360
361 defineValueType(type: string, aliases?: string[]): void;
362
363 extendModel(modelName: string, properties: AnyObject): void;
364
365 getSchemaName(name?: string): string;
366
367 resolveType(type: any): any;
368
369 buildModels(
370 schemas: AnyObject,
371 createModel?: Function,
372 ): {[name: string]: ModelBaseClass};
373
374 buildModelFromInstance(
375 name: string,
376 json: AnyObject,
377 options: Options,
378 ): ModelBaseClass;
379}
380
381/**
382 * An extension of the built-in Partial<T> type which allows partial values
383 * in deeply nested properties too.
384 */
385export type DeepPartial<T> = { [P in keyof T]?: DeepPartial<T[P]>; };
386
387/**
388 * Union export type for model instance or plain object representing the model
389 * instance
390 */
391export type ModelData<T extends ModelBase = ModelBase> = T | DeepPartial<T>;