@weapnl/js-junction 0.0.1
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/CHANGELOG.md +128 -0
- package/README.md +348 -0
- package/babel.config.json +5 -0
- package/dist/index.js +4369 -0
- package/docker-compose.yml +14 -0
- package/index.d.ts +150 -0
- package/package.json +34 -0
- package/src/api.js +226 -0
- package/src/batch.js +39 -0
- package/src/builder/caster.js +67 -0
- package/src/builder/model.js +259 -0
- package/src/builder/properties/accessors.js +116 -0
- package/src/builder/properties/attributes.js +118 -0
- package/src/builder/properties/counts.js +79 -0
- package/src/builder/properties/property.js +37 -0
- package/src/builder/properties/relations.js +124 -0
- package/src/connection.js +83 -0
- package/src/filters/count.js +27 -0
- package/src/filters/filter.js +9 -0
- package/src/filters/filters.js +33 -0
- package/src/filters/limit.js +27 -0
- package/src/filters/order.js +30 -0
- package/src/filters/pluck.js +28 -0
- package/src/filters/relations.js +27 -0
- package/src/filters/scopes.js +30 -0
- package/src/filters/search.js +34 -0
- package/src/filters/whereIn.js +31 -0
- package/src/filters/wheres.js +32 -0
- package/src/index.js +12 -0
- package/src/mixins/actionMixin.js +20 -0
- package/src/mixins/filterMixin.js +104 -0
- package/src/mixins/modifierMixin.js +22 -0
- package/src/mixins/paginationMixin.js +20 -0
- package/src/modifiers/appends.js +28 -0
- package/src/modifiers/hiddenFields.js +27 -0
- package/src/modifiers/modifier.js +9 -0
- package/src/modifiers/modifiers.js +19 -0
- package/src/request/action.js +29 -0
- package/src/request/pagination.js +35 -0
- package/src/request.js +317 -0
- package/src/response.js +33 -0
- package/src/utilities/format.js +11 -0
- package/webpack.config.js +28 -0
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import Accessors from './properties/accessors';
|
|
2
|
+
import Attributes from './properties/attributes';
|
|
3
|
+
import Counts from './properties/counts';
|
|
4
|
+
import Relations from './properties/relations';
|
|
5
|
+
import Request from '../request';
|
|
6
|
+
|
|
7
|
+
export default class Model extends Request {
|
|
8
|
+
constructor (defaults = {}) {
|
|
9
|
+
super();
|
|
10
|
+
|
|
11
|
+
this._accessors = new Accessors(this);
|
|
12
|
+
this._attributes = new Attributes(this);
|
|
13
|
+
this._counts = new Counts(this);
|
|
14
|
+
this._relations = new Relations(this);
|
|
15
|
+
|
|
16
|
+
this.fill(defaults);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Create an instance of the model for the given json object.
|
|
21
|
+
*
|
|
22
|
+
* @param {Object} json
|
|
23
|
+
*
|
|
24
|
+
* @returns {this} An instance of the model.
|
|
25
|
+
*/
|
|
26
|
+
static fromJson (json) {
|
|
27
|
+
const instance = new (this)();
|
|
28
|
+
|
|
29
|
+
instance._accessors.fromJson(json);
|
|
30
|
+
instance._attributes.fromJson(json);
|
|
31
|
+
instance._counts.fromJson(json);
|
|
32
|
+
instance._relations.fromJson(json);
|
|
33
|
+
|
|
34
|
+
return instance;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Convert the attributes of the current instance to json.
|
|
39
|
+
*
|
|
40
|
+
* @return {Object} The attributes of the current instance as json object.
|
|
41
|
+
*/
|
|
42
|
+
toJson () {
|
|
43
|
+
return {
|
|
44
|
+
...this._accessors.toJson(),
|
|
45
|
+
...this._attributes.toJson(),
|
|
46
|
+
...this._counts.toJson(),
|
|
47
|
+
...this._relations.toJson(),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @param values
|
|
53
|
+
* @returns {this}
|
|
54
|
+
*/
|
|
55
|
+
fill (values = {}) {
|
|
56
|
+
this._attributes.set(values);
|
|
57
|
+
this._relations.set(values);
|
|
58
|
+
|
|
59
|
+
return this;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* The accessors of the model which were appended on the api side.
|
|
64
|
+
*
|
|
65
|
+
* @returns {Object.<any, Object>}
|
|
66
|
+
*/
|
|
67
|
+
static accessors () {
|
|
68
|
+
return {};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* The attributes of the model.
|
|
73
|
+
*
|
|
74
|
+
* @returns {Object.<any, Object>}
|
|
75
|
+
*/
|
|
76
|
+
static attributes () {
|
|
77
|
+
return {};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* The counts of relations of the model.
|
|
82
|
+
*
|
|
83
|
+
* @returns {Object.<any, Object>}
|
|
84
|
+
*/
|
|
85
|
+
static counts () {
|
|
86
|
+
return {};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* The relations of the model.
|
|
91
|
+
*
|
|
92
|
+
* @returns {Object.<any, Object>}
|
|
93
|
+
*/
|
|
94
|
+
static relations () {
|
|
95
|
+
return {};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* @returns {string} Endpoint of the model for the API.
|
|
100
|
+
*/
|
|
101
|
+
static get endpoint () {
|
|
102
|
+
throw new Error('No endpoint defined in the model.');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* @returns {int} Identifier attribute name of the model.
|
|
107
|
+
*/
|
|
108
|
+
get _identifier () {
|
|
109
|
+
return _.get(this, 'id');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Get a list of models.
|
|
114
|
+
*
|
|
115
|
+
* @returns {this[]} List of models.
|
|
116
|
+
*/
|
|
117
|
+
async index () {
|
|
118
|
+
this._response = await this._connection.get(
|
|
119
|
+
this._queryString(),
|
|
120
|
+
this.bodyParameters,
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
let items;
|
|
124
|
+
|
|
125
|
+
if (this._response.data) {
|
|
126
|
+
items = _.map(this._response.data.items, (item) => {
|
|
127
|
+
return this.constructor.fromJson(item);
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
await this.triggerResponseEvents(this._response, items);
|
|
132
|
+
|
|
133
|
+
return items;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Get a single model.
|
|
138
|
+
*
|
|
139
|
+
* @param {int} [identifier]
|
|
140
|
+
*
|
|
141
|
+
* @returns {this} Model found for the given id.
|
|
142
|
+
*/
|
|
143
|
+
async show (identifier) {
|
|
144
|
+
identifier ??= this._identifier;
|
|
145
|
+
|
|
146
|
+
if (! identifier) return null;
|
|
147
|
+
|
|
148
|
+
this._response = await this._connection.get(
|
|
149
|
+
this._queryString(identifier),
|
|
150
|
+
this.bodyParameters,
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
let item;
|
|
154
|
+
|
|
155
|
+
if (this._response.data) {
|
|
156
|
+
item = this.constructor.fromJson(this._response.data);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
await this.triggerResponseEvents(this._response, item);
|
|
160
|
+
|
|
161
|
+
return item;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Create an model.
|
|
166
|
+
*
|
|
167
|
+
* @param {Object} [extraData] Extra data to send to the API
|
|
168
|
+
*
|
|
169
|
+
* @returns {this} The created model.
|
|
170
|
+
*/
|
|
171
|
+
async store (extraData = {}) {
|
|
172
|
+
this._response = await this._connection.post(
|
|
173
|
+
this._queryString(),
|
|
174
|
+
{ ...this._attributes.toJson(), ...extraData },
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
let item;
|
|
178
|
+
|
|
179
|
+
if (this._response.data) {
|
|
180
|
+
item = this.constructor.fromJson(this._response.data);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
await this.triggerResponseEvents(this._response, item);
|
|
184
|
+
|
|
185
|
+
return item;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Update the current model.
|
|
190
|
+
*
|
|
191
|
+
* @param {Object} [extraData] Extra data to send to the API
|
|
192
|
+
*
|
|
193
|
+
* @returns {this} The updated model.
|
|
194
|
+
*/
|
|
195
|
+
async update (extraData = {}) {
|
|
196
|
+
this._response = await this._connection.put(
|
|
197
|
+
this._queryString(this._identifier),
|
|
198
|
+
{ ...this._attributes.toJson(), ...extraData },
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
let item;
|
|
202
|
+
|
|
203
|
+
if (this._response.data) {
|
|
204
|
+
item = this.constructor.fromJson(this._response.data);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
await this.triggerResponseEvents(this._response, item);
|
|
208
|
+
|
|
209
|
+
return item;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Delete the current model.
|
|
214
|
+
*
|
|
215
|
+
* @returns {boolean} Whether the deletion was successful.
|
|
216
|
+
*/
|
|
217
|
+
async destroy () {
|
|
218
|
+
this._response = await this._connection.delete(
|
|
219
|
+
this._queryString(this._identifier),
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
await this.triggerResponseEvents(this._response);
|
|
223
|
+
|
|
224
|
+
return !! this._response.data;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Save the current model. Based on the value of the identifier `store` or `update` will be called.
|
|
229
|
+
*
|
|
230
|
+
* @param {Object} [extraData] Extra data to send to the API
|
|
231
|
+
*
|
|
232
|
+
* @returns {this} The created or updated model.
|
|
233
|
+
*/
|
|
234
|
+
async save (extraData = {}) {
|
|
235
|
+
return ! this._identifier
|
|
236
|
+
? this.store(extraData)
|
|
237
|
+
: this.update(extraData);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* @returns {this} The new clone of the current model.
|
|
242
|
+
*/
|
|
243
|
+
clone () {
|
|
244
|
+
return this.constructor.fromJson(this.toJson());
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Generate the query string for this model.
|
|
249
|
+
* @private
|
|
250
|
+
*
|
|
251
|
+
* @param {int} [identifier] The identifier of the model.
|
|
252
|
+
*
|
|
253
|
+
* @returns {string} The querystring for the model.
|
|
254
|
+
*/
|
|
255
|
+
_queryString (identifier) {
|
|
256
|
+
return this.constructor.endpoint
|
|
257
|
+
+ (identifier ? `/${identifier}` : '');
|
|
258
|
+
}
|
|
259
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import Caster from '../caster';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @implements {Property}
|
|
5
|
+
*/
|
|
6
|
+
export default class Accessors {
|
|
7
|
+
/**
|
|
8
|
+
* @param {Model} model Instance of the model.
|
|
9
|
+
*/
|
|
10
|
+
constructor (model) {
|
|
11
|
+
this.model = model;
|
|
12
|
+
|
|
13
|
+
_.each(model.constructor.accessors(), (options, key) => {
|
|
14
|
+
this.set(key, _.has(options, 'default') ? options.default : null);
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @param {Object} json.
|
|
20
|
+
*/
|
|
21
|
+
fromJson (json) {
|
|
22
|
+
_.each(this.model.constructor.accessors(), (options, key) => {
|
|
23
|
+
let value = _.get(json, options.jsonKey ?? _.snakeCase(key), _.get(json, _.camelCase(key)));
|
|
24
|
+
|
|
25
|
+
if (_.isNil(value)) {
|
|
26
|
+
value = _.has(options, 'default') ? options.default : null;
|
|
27
|
+
} else {
|
|
28
|
+
value = Accessors._getCastedFromJsonValue(value, options);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
this.set(key, value);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @return {Object} The attributes casted to a json object.
|
|
37
|
+
*/
|
|
38
|
+
toJson () {
|
|
39
|
+
const json = {};
|
|
40
|
+
|
|
41
|
+
_.each(this.model.constructor.accessors(), (options, key) => {
|
|
42
|
+
let jsonValue = this.get(key);
|
|
43
|
+
|
|
44
|
+
jsonValue = Accessors._getCastedToJsonValue(jsonValue, options);
|
|
45
|
+
|
|
46
|
+
_.set(json, options.jsonKey ?? _.snakeCase(key), jsonValue);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
return json;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @param {string} attribute
|
|
54
|
+
*
|
|
55
|
+
* @returns {*} The value of the attribute.
|
|
56
|
+
*/
|
|
57
|
+
get (attribute) {
|
|
58
|
+
return _.get(this.model, attribute);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @param {string} attribute
|
|
63
|
+
* @param {*} value
|
|
64
|
+
*
|
|
65
|
+
* @returns {*} The value that was set.
|
|
66
|
+
*/
|
|
67
|
+
set (attribute, value) {
|
|
68
|
+
this.model[attribute] = value;
|
|
69
|
+
|
|
70
|
+
return value;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @private
|
|
75
|
+
*
|
|
76
|
+
* @param {*} value
|
|
77
|
+
* @param {Object} options
|
|
78
|
+
*
|
|
79
|
+
* @returns {*} The casted value.
|
|
80
|
+
*/
|
|
81
|
+
static _getCastedFromJsonValue (value, options) {
|
|
82
|
+
if (_.has(options, 'type') || _.has(options, 'fromJson')) {
|
|
83
|
+
const cast = options.type ? options.type : options.fromJson;
|
|
84
|
+
|
|
85
|
+
if (_.isArray(value)) {
|
|
86
|
+
return _.map(value, (val) => Caster.fromJson(cast, val));
|
|
87
|
+
} else {
|
|
88
|
+
return Caster.fromJson(cast, value);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return value;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* @private
|
|
97
|
+
*
|
|
98
|
+
* @param {*} value
|
|
99
|
+
* @param {Object} options
|
|
100
|
+
*
|
|
101
|
+
* @returns {*} The casted value.
|
|
102
|
+
*/
|
|
103
|
+
static _getCastedToJsonValue (value, options) {
|
|
104
|
+
if (_.has(options, 'type') || _.has(options, 'toJson')) {
|
|
105
|
+
const cast = options.type ? options.type : options.toJson;
|
|
106
|
+
|
|
107
|
+
if (_.isArray(value)) {
|
|
108
|
+
return _.map(value, (val) => Caster.toJson(cast, val));
|
|
109
|
+
} else {
|
|
110
|
+
return Caster.toJson(cast, value);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return value;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import Caster from '../caster';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @implements {Property}
|
|
5
|
+
*/
|
|
6
|
+
export default class Attributes {
|
|
7
|
+
/**
|
|
8
|
+
* @param {Model} model Instance of the model.
|
|
9
|
+
*/
|
|
10
|
+
constructor (model) {
|
|
11
|
+
this.model = model;
|
|
12
|
+
|
|
13
|
+
_.each(model.constructor.attributes(), (options, key) => {
|
|
14
|
+
this.set(key, _.has(options, 'default') ? options.default : null);
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @param {Object} json.
|
|
20
|
+
*/
|
|
21
|
+
fromJson (json) {
|
|
22
|
+
_.each(this.model.constructor.attributes(), (options, key) => {
|
|
23
|
+
let value = _.get(json, options.jsonKey ?? _.snakeCase(key), _.get(json, _.camelCase(key)));
|
|
24
|
+
|
|
25
|
+
if (_.isNil(value)) {
|
|
26
|
+
value = _.has(options, 'default') ? options.default : null;
|
|
27
|
+
} else {
|
|
28
|
+
value = Attributes._getCastedFromJsonValue(value, options);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
this.set(key, value);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @return {Object} The attributes casted to a json object.
|
|
37
|
+
*/
|
|
38
|
+
toJson () {
|
|
39
|
+
const json = {};
|
|
40
|
+
|
|
41
|
+
_.each(this.model.constructor.attributes(), (options, key) => {
|
|
42
|
+
let jsonValue = this.get(key);
|
|
43
|
+
|
|
44
|
+
jsonValue = Attributes._getCastedToJsonValue(jsonValue, options);
|
|
45
|
+
|
|
46
|
+
_.set(json, options.jsonKey ?? _.snakeCase(key), jsonValue);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
return json;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @param {string} attribute
|
|
54
|
+
*
|
|
55
|
+
* @returns {*} The value of the attribute.
|
|
56
|
+
*/
|
|
57
|
+
get (attribute) {
|
|
58
|
+
return _.get(this.model, attribute);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @param {string|Object} attribute
|
|
63
|
+
* @param {*} value
|
|
64
|
+
*
|
|
65
|
+
* @returns {Attributes}
|
|
66
|
+
*/
|
|
67
|
+
set (attribute, value = null) {
|
|
68
|
+
if (_.isObject(attribute)) {
|
|
69
|
+
_.each(this.model.constructor.attributes(), (options, key) => {
|
|
70
|
+
if (! _.has(attribute, key)) return;
|
|
71
|
+
|
|
72
|
+
this.set(key, attribute[key]);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
return this;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
this.model[attribute] = value;
|
|
79
|
+
|
|
80
|
+
return this;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* @private
|
|
85
|
+
*
|
|
86
|
+
* @param {*} value
|
|
87
|
+
* @param {Object} options
|
|
88
|
+
*
|
|
89
|
+
* @returns {*} The casted value.
|
|
90
|
+
*/
|
|
91
|
+
static _getCastedFromJsonValue (value, options) {
|
|
92
|
+
if (_.has(options, 'type') || _.has(options, 'fromJson')) {
|
|
93
|
+
const cast = options.type ? options.type : options.fromJson;
|
|
94
|
+
|
|
95
|
+
return Caster.fromJson(cast, value);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return value;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* @private
|
|
103
|
+
*
|
|
104
|
+
* @param {*} value
|
|
105
|
+
* @param {Object} options
|
|
106
|
+
*
|
|
107
|
+
* @returns {*} The casted value.
|
|
108
|
+
*/
|
|
109
|
+
static _getCastedToJsonValue (value, options) {
|
|
110
|
+
if (_.has(options, 'type') || _.has(options, 'toJson')) {
|
|
111
|
+
const cast = options.type ? options.type : options.toJson;
|
|
112
|
+
|
|
113
|
+
return Caster.toJson(cast, value);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return value;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @implements {Property}
|
|
3
|
+
*/
|
|
4
|
+
export default class Counts {
|
|
5
|
+
/**
|
|
6
|
+
* @param {Model} model Instance of the model.
|
|
7
|
+
*/
|
|
8
|
+
constructor (model) {
|
|
9
|
+
this.model = model;
|
|
10
|
+
|
|
11
|
+
_.each(model.constructor.counts(), (options, key) => {
|
|
12
|
+
this.set(this.key(key, true), _.has(options, 'default') ? options.default : null);
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @param {Object} json.
|
|
18
|
+
*/
|
|
19
|
+
fromJson (json) {
|
|
20
|
+
_.each(this.model.constructor.counts(), (options, key) => {
|
|
21
|
+
let value = _.get(json, this.key(key));
|
|
22
|
+
|
|
23
|
+
value = value !== undefined
|
|
24
|
+
? _.toInteger(value)
|
|
25
|
+
: null;
|
|
26
|
+
|
|
27
|
+
this.set(this.key(key, true), value);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @return {Object} The attributes casted to a json object.
|
|
33
|
+
*/
|
|
34
|
+
toJson () {
|
|
35
|
+
const json = {};
|
|
36
|
+
|
|
37
|
+
_.each(this.model.constructor.counts(), (options, key) => {
|
|
38
|
+
_.set(json, key, this.get(key));
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
return json;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @param {string} attribute
|
|
46
|
+
*
|
|
47
|
+
* @returns {*} The value of the attribute.
|
|
48
|
+
*/
|
|
49
|
+
get (attribute) {
|
|
50
|
+
return _.get(this.model, this.key(attribute, true));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @param {string} attribute
|
|
55
|
+
* @param {*} value
|
|
56
|
+
*
|
|
57
|
+
* @returns {*} The value that was set.
|
|
58
|
+
*/
|
|
59
|
+
set (attribute, value) {
|
|
60
|
+
this.model[this.key(attribute, true)] = value;
|
|
61
|
+
|
|
62
|
+
return value;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* @param {string} key
|
|
67
|
+
* @param {boolean} camelCase
|
|
68
|
+
* @returns {string} The key with `count` appended to it, in specified casing.
|
|
69
|
+
*/
|
|
70
|
+
key (key, camelCase = false) {
|
|
71
|
+
key = _.snakeCase(key);
|
|
72
|
+
|
|
73
|
+
if (! _.endsWith(key, '_count')) {
|
|
74
|
+
key = `${key}_count`;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return camelCase ? _.camelCase(key) : key;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @interface
|
|
3
|
+
*/
|
|
4
|
+
class Property {
|
|
5
|
+
/**
|
|
6
|
+
* @param {string} key
|
|
7
|
+
*
|
|
8
|
+
* @returns {*} The value of the attribute.
|
|
9
|
+
*/
|
|
10
|
+
get (key) {
|
|
11
|
+
throw new Error('not implemented');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @param {string} key
|
|
16
|
+
* @param {*} value
|
|
17
|
+
*
|
|
18
|
+
* @returns {*} The value that was set.
|
|
19
|
+
*/
|
|
20
|
+
set (key, value) {
|
|
21
|
+
throw new Error('not implemented');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @param {Object} json.
|
|
26
|
+
*/
|
|
27
|
+
fromJson (json) {
|
|
28
|
+
throw new Error('not implemented');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @return {Object} The json object.
|
|
33
|
+
*/
|
|
34
|
+
toJson () {
|
|
35
|
+
throw new Error('not implemented');
|
|
36
|
+
}
|
|
37
|
+
}
|