1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | 'use strict';
|
7 |
|
8 | const debug = require('debug')('loopback:mixin');
|
9 | const assert = require('assert');
|
10 | const DefaultModelBaseClass = require('./model.js');
|
11 |
|
12 | function isModelClass(cls) {
|
13 | if (!cls) {
|
14 | return false;
|
15 | }
|
16 | return cls.prototype instanceof DefaultModelBaseClass;
|
17 | }
|
18 |
|
19 | module.exports = MixinProvider;
|
20 |
|
21 | function MixinProvider(modelBuilder) {
|
22 | this.modelBuilder = modelBuilder;
|
23 | this.mixins = {};
|
24 | }
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 | MixinProvider.prototype.applyMixin = function applyMixin(modelClass, name, options) {
|
33 | const fn = this.mixins[name];
|
34 | if (typeof fn === 'function') {
|
35 | if (modelClass.dataSource) {
|
36 | fn(modelClass, options || {});
|
37 | } else {
|
38 | modelClass.once('dataSourceAttached', function() {
|
39 | fn(modelClass, options || {});
|
40 | });
|
41 | }
|
42 | } else {
|
43 |
|
44 | const model = this.modelBuilder.getModel(name);
|
45 | if (model) {
|
46 | debug('Mixin is resolved to a model: %s', name);
|
47 | modelClass.mixin(model, options);
|
48 | } else {
|
49 | const errMsg = 'Model "' + modelClass.modelName + '" uses unknown mixin: ' + name;
|
50 | debug(errMsg);
|
51 | throw new Error(errMsg);
|
52 | }
|
53 | }
|
54 | };
|
55 |
|
56 |
|
57 |
|
58 |
|
59 |
|
60 |
|
61 | MixinProvider.prototype.define = function defineMixin(name, mixin) {
|
62 | assert(typeof mixin === 'function', 'The mixin must be a function or model class');
|
63 | if (this.mixins[name]) {
|
64 | debug('Duplicate mixin: %s', name);
|
65 | } else {
|
66 | debug('Defining mixin: %s', name);
|
67 | }
|
68 | if (isModelClass(mixin)) {
|
69 | this.mixins[name] = function(Model, options) {
|
70 | Model.mixin(mixin, options);
|
71 | };
|
72 | } else if (typeof mixin === 'function') {
|
73 | this.mixins[name] = mixin;
|
74 | }
|
75 | };
|