UNPKG

18.6 kBJavaScriptView Raw
1// Generated by CoffeeScript 1.10.0
2
3/*
4 *
5 * StringField 'username', minLength: 3, maxLength: 10
6 * StringField 'username', validations: [{rule: 'minLength:3', message: 'Invalid username'}]
7 *
8 */
9var BooleanField, DateField, DateTimeField, EmailField, EncryptedString, EncryptedStringField, Field, FloatField, IntField, JSONField, NumberField, StringField,
10 extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
11 hasProp = {}.hasOwnProperty,
12 bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
13
14Field = (function() {
15 function Field(name, options) {
16 if (options == null) {
17 options = {};
18 }
19 if (!(this instanceof Field)) {
20 return new Field(name);
21 }
22 this.name = name;
23 this.options = options;
24 }
25
26 Field.prototype.pluginOption = function(name, defaultVal) {
27 if (name in this.model.__bookshelf_schema_options) {
28 return this.model.__bookshelf_schema_options[name];
29 } else {
30 return defaultVal;
31 }
32 };
33
34 Field.prototype.option = function(name, pluginOptionName, defaultVal) {
35 var value;
36 if (arguments.length === 2) {
37 defaultVal = pluginOptionName;
38 pluginOptionName = name;
39 }
40 value = this.options[name];
41 if (value == null) {
42 value = this.pluginOption(pluginOptionName, defaultVal);
43 }
44 return value;
45 };
46
47 Field.prototype.contributeToSchema = function(schema) {
48 return schema.push(this);
49 };
50
51 Field.prototype.contributeToModel = function(cls) {
52 var base;
53 this.model = cls;
54 if ((base = this.model).__bookshelf_schema == null) {
55 base.__bookshelf_schema = {
56 validations: {},
57 parsers: [],
58 formatters: []
59 };
60 }
61 if (this.option('createProperty', 'createProperties', true)) {
62 this._createProperty(cls);
63 }
64 if (this.option('validation', true)) {
65 this._appendValidations(cls);
66 }
67 this._appendFormatter();
68 return this._appendParser();
69 };
70
71 Field.prototype.validations = function() {
72 var result;
73 result = this.options.validations ? this.options.validations.slice(0) : [];
74 this.acceptsRule(result, ['required', 'accepted', 'exists']);
75 return result;
76 };
77
78 Field.prototype.modelValidations = function() {};
79
80 Field.prototype.createGetter = function() {
81 var name;
82 name = this.name;
83 return function() {
84 return this.get(name);
85 };
86 };
87
88 Field.prototype.createSetter = function() {
89 var name;
90 name = this.name;
91 return function(value) {
92 return this.set(name, value);
93 };
94 };
95
96 Field.prototype.acceptsRule = function(validations, names, rule) {
97 var i, len, name;
98 if (!(names instanceof Array)) {
99 names = [names];
100 }
101 if (rule == null) {
102 rule = names[0];
103 }
104 for (i = 0, len = names.length; i < len; i++) {
105 name = names[i];
106 if (!(name in this.options)) {
107 continue;
108 }
109 validations.push(this._normalizeRule(rule, this.options[name]));
110 return;
111 }
112 };
113
114 Field.prototype._createProperty = function(cls) {
115 var getter, setter, spec;
116 if (this.name === 'id' || this.name in cls.prototype) {
117 return;
118 }
119 spec = {};
120 getter = this.createGetter();
121 setter = this.createSetter();
122 if (getter) {
123 spec.get = getter;
124 }
125 if (setter) {
126 spec.set = setter;
127 }
128 return Object.defineProperty(cls.prototype, this.name, spec);
129 };
130
131 Field.prototype._appendValidations = function(model) {
132 var meta, modelValidations, validations;
133 meta = model.__bookshelf_schema;
134 validations = this.validations();
135 if (validations && validations.length > 0) {
136 if (this.name in meta.validations) {
137 if (!(meta.validations[this.name] instanceof Array)) {
138 meta.validations[this.name] = [meta.validations[this.name]];
139 }
140 } else {
141 meta.validations[this.name] = [];
142 }
143 meta.validations[this.name].push.apply(meta.validations[this.name], validations);
144 }
145 modelValidations = this.modelValidations();
146 if (modelValidations && modelValidations.length > 0) {
147 if (meta.modelValidations == null) {
148 meta.modelValidations = [];
149 }
150 return meta.modelValidations.push.apply(meta.modelValidations, modelValidations);
151 }
152 };
153
154 Field.prototype._normalizeRule = function(rule, value) {
155 var k, result, v;
156 return this._withMessage((function() {
157 switch (false) {
158 case !(typeof value === 'object' && !(value instanceof Array)):
159 result = {
160 rule: rule
161 };
162 for (k in value) {
163 v = value[k];
164 result[k] = v;
165 }
166 if ('value' in result) {
167 if (typeof rule === 'string') {
168 result.rule += ':' + result.value;
169 } else {
170 result.params = result.value;
171 }
172 delete result.value;
173 }
174 result.params || (result.params = []);
175 return result;
176 case typeof value !== 'boolean':
177 return rule;
178 case typeof rule !== 'string':
179 return rule + ":" + value;
180 default:
181 return this._normalizeRule(rule, {
182 value: value
183 });
184 }
185 }).call(this));
186 };
187
188 Field.prototype._withMessage = function(rule) {
189 if (!((this.options.message != null) || (this.options.label != null))) {
190 return rule;
191 }
192 if (typeof rule !== 'object') {
193 rule = {
194 rule: rule
195 };
196 }
197 if (this.options.message != null) {
198 if (rule.message == null) {
199 rule.message = this.options.message;
200 }
201 }
202 if (this.options.label != null) {
203 if (rule.label == null) {
204 rule.label = this.options.label;
205 }
206 }
207 return rule;
208 };
209
210 Field.prototype._appendFormatter = function() {
211 if (typeof this.format === 'function') {
212 return this.model.__bookshelf_schema.formatters.push(this.format.bind(this));
213 }
214 };
215
216 Field.prototype._appendParser = function() {
217 if (typeof this.parse === 'function') {
218 return this.model.__bookshelf_schema.parsers.push(this.parse.bind(this));
219 }
220 };
221
222 return Field;
223
224})();
225
226StringField = (function(superClass) {
227 extend(StringField, superClass);
228
229 function StringField(name, options) {
230 if (!(this instanceof StringField)) {
231 return new StringField(name, options);
232 }
233 StringField.__super__.constructor.call(this, name, options);
234 }
235
236 StringField.prototype.validations = function() {
237 var result;
238 result = StringField.__super__.validations.apply(this, arguments);
239 this.acceptsRule(result, ['minLength', 'min_length']);
240 this.acceptsRule(result, ['maxLength', 'max_length']);
241 return result;
242 };
243
244 return StringField;
245
246})(Field);
247
248EmailField = (function(superClass) {
249 extend(EmailField, superClass);
250
251 function EmailField(name, options) {
252 if (!(this instanceof EmailField)) {
253 return new EmailField(name, options);
254 }
255 EmailField.__super__.constructor.call(this, name, options);
256 }
257
258 EmailField.prototype.validations = function() {
259 var result;
260 result = EmailField.__super__.validations.apply(this, arguments);
261 result.push(this._withMessage('email'));
262 return result;
263 };
264
265 return EmailField;
266
267})(StringField);
268
269EncryptedString = (function() {
270 function EncryptedString(encrypted, plain1, options1) {
271 var base;
272 this.encrypted = encrypted;
273 this.plain = plain1;
274 this.options = options1 != null ? options1 : {};
275 if ((base = this.options).saltLength == null) {
276 base.saltLength = 16;
277 }
278 }
279
280 EncryptedString.prototype.encrypt = function() {
281 return this._genSalt(this.options.saltLength).then((function(_this) {
282 return function(salt) {
283 return _this._genHash(_this.plain, salt).then(function(hash) {
284 return _this.encrypted = salt.toString('base64') + '$' + hash.toString('base64');
285 });
286 };
287 })(this));
288 };
289
290 EncryptedString.prototype.verify = function(value) {
291 var checked, salt;
292 checked = this.encrypted.split('$');
293 salt = new Buffer(checked[0], 'base64');
294 return this._genHash(value, salt).then(function(hash) {
295 return hash.toString('base64') === checked[1];
296 });
297 };
298
299 EncryptedString.prototype._genSalt = function(length) {
300 var crypto;
301 if (this.options.saltAlgorithm) {
302 return this.options.saltAlgorithm(length, callback);
303 } else {
304 crypto = require('crypto');
305 return new Promise(function(resolve, reject) {
306 return crypto.randomBytes(length, function(err, salt) {
307 if (err) {
308 return reject(err);
309 } else {
310 return resolve(salt);
311 }
312 });
313 });
314 }
315 };
316
317 EncryptedString.prototype._genHash = function(plain, salt) {
318 var crypto, digest, iterations, keylen;
319 iterations = this.options.iterations || 1000;
320 keylen = this.options.length || 512;
321 if (typeof this.options.algorithm === 'function') {
322 return this.options.algorithm(plain, salt, iterations, keylen);
323 } else {
324 crypto = require('crypto');
325 digest = typeof this.options.algorithm === 'string' ? this.options.algorithm : 'sha256';
326 return new Promise(function(resolve, reject) {
327 return crypto.pbkdf2(plain, salt, iterations, keylen, digest, function(err, hash) {
328 if (err) {
329 return reject(err);
330 } else {
331 return resolve(hash);
332 }
333 });
334 });
335 }
336 };
337
338 return EncryptedString;
339
340})();
341
342EncryptedStringField = (function(superClass) {
343 extend(EncryptedStringField, superClass);
344
345 function EncryptedStringField(name, options) {
346 if (options == null) {
347 options = {};
348 }
349 this._onSaving = bind(this._onSaving, this);
350 if (!(this instanceof EncryptedStringField)) {
351 return new EncryptedStringField(name, options);
352 }
353 EncryptedStringField.__super__.constructor.call(this, name, options);
354 }
355
356 EncryptedStringField.prototype.validations = function() {
357 var result;
358 result = EncryptedStringField.__super__.validations.call(this);
359 this.acceptsRule(result, ['minLength', 'min_length'], this._validateMinLenghth);
360 this.acceptsRule(result, ['maxLength', 'max_length'], this._validateMaxLenghth);
361 return result;
362 };
363
364 EncryptedStringField.prototype.initialize = function(instance) {
365 return instance.on('saving', this._onSaving);
366 };
367
368 EncryptedStringField.prototype.parse = function(attrs, options) {
369 if (attrs[this.name] == null) {
370 return attrs;
371 }
372 attrs[this.name] = new EncryptedString(attrs[this.name], null, this.options);
373 return attrs;
374 };
375
376 EncryptedStringField.prototype.format = function(attrs, options) {
377 var me;
378 me = attrs[this.name];
379 if (me == null) {
380 return attrs;
381 }
382 if (!(me instanceof EncryptedString && me.encrypted)) {
383 throw new Error("Field @name should be encryted first");
384 }
385 attrs[this.name] = me.encrypted;
386 return attrs;
387 };
388
389 EncryptedStringField.prototype._validateMinLenghth = function(value, minLength) {
390 if (value instanceof EncryptedString && (value.plain == null)) {
391 return;
392 }
393 value = value instanceof EncryptedString ? value.plain : value;
394 return value.length >= minLength;
395 };
396
397 EncryptedStringField.prototype._validateMaxLenghth = function(value, maxLength) {
398 if (value instanceof EncryptedString && (value.plain == null)) {
399 return;
400 }
401 value = value instanceof EncryptedString ? value.plain : value;
402 return value.length <= maxLength;
403 };
404
405 EncryptedStringField.prototype._onSaving = function(instance, attrs, options) {
406 var me;
407 me = attrs[this.name] || instance.attributes[this.name];
408 if (me == null) {
409 return;
410 }
411 if (me instanceof EncryptedString && !me.plain) {
412 return;
413 }
414 if (!(me instanceof EncryptedString)) {
415 me = attrs[this.name] = instance.attributes[this.name] = new EncryptedString(null, me, this.options);
416 }
417 return me.encrypt();
418 };
419
420 return EncryptedStringField;
421
422})(Field);
423
424NumberField = (function(superClass) {
425 extend(NumberField, superClass);
426
427 function NumberField(name, options) {
428 if (!(this instanceof NumberField)) {
429 return new NumberField(name, options);
430 }
431 NumberField.__super__.constructor.call(this, name, options);
432 }
433
434 NumberField.prototype.validations = function() {
435 var result;
436 result = NumberField.__super__.validations.apply(this, arguments);
437 this.acceptsRule(result, ['greaterThan', 'greater_than', 'gt']);
438 this.acceptsRule(result, ['greaterThanEqualTo', 'greater_than_equal_to', 'gte', 'min']);
439 this.acceptsRule(result, ['lessThan', 'less_than', 'lt']);
440 this.acceptsRule(result, ['lessThanEqualTo', 'less_than_equal_to', 'lte', 'max']);
441 return result;
442 };
443
444 return NumberField;
445
446})(Field);
447
448IntField = (function(superClass) {
449 extend(IntField, superClass);
450
451 function IntField(name, options) {
452 if (!(this instanceof IntField)) {
453 return new IntField(name, options);
454 }
455 IntField.__super__.constructor.call(this, name, options);
456 }
457
458 IntField.prototype.validations = function() {
459 var result;
460 result = IntField.__super__.validations.apply(this, arguments);
461 this.acceptsRule(result, ['naturalNonZero', 'positive']);
462 this.acceptsRule(result, 'natural');
463 result.unshift(this._withMessage('integer'));
464 return result;
465 };
466
467 IntField.prototype.parse = function(attrs) {
468 if (attrs[this.name] != null) {
469 return attrs[this.name] = parseInt(attrs[this.name]);
470 }
471 };
472
473 return IntField;
474
475})(NumberField);
476
477FloatField = (function(superClass) {
478 extend(FloatField, superClass);
479
480 function FloatField(name, options) {
481 if (!(this instanceof FloatField)) {
482 return new FloatField(name, options);
483 }
484 FloatField.__super__.constructor.call(this, name, options);
485 }
486
487 FloatField.prototype.validations = function() {
488 var result;
489 result = FloatField.__super__.validations.apply(this, arguments);
490 result.unshift(this._withMessage('numeric'));
491 return result;
492 };
493
494 FloatField.prototype.parse = function(attrs) {
495 if (attrs[this.name] != null) {
496 return attrs[this.name] = parseFloat(attrs[this.name]);
497 }
498 };
499
500 return FloatField;
501
502})(NumberField);
503
504BooleanField = (function(superClass) {
505 extend(BooleanField, superClass);
506
507 function BooleanField(name, options) {
508 if (!(this instanceof BooleanField)) {
509 return new BooleanField(name, options);
510 }
511 BooleanField.__super__.constructor.call(this, name, options);
512 }
513
514 BooleanField.prototype.parse = function(attrs) {
515 if (this.name in attrs) {
516 return attrs[this.name] = !!attrs[this.name];
517 }
518 };
519
520 BooleanField.prototype.format = function(attrs) {
521 if (this.name in attrs) {
522 return attrs[this.name] = !!attrs[this.name];
523 }
524 };
525
526 return BooleanField;
527
528})(Field);
529
530DateTimeField = (function(superClass) {
531 extend(DateTimeField, superClass);
532
533 function DateTimeField(name, options) {
534 if (!(this instanceof DateTimeField)) {
535 return new DateTimeField(name, options);
536 }
537 DateTimeField.__super__.constructor.call(this, name, options);
538 }
539
540 DateTimeField.prototype.validations = function() {
541 var result;
542 result = DateTimeField.__super__.validations.apply(this, arguments);
543 result.push(this._withMessage(this._validateDatetime));
544 return result;
545 };
546
547 DateTimeField.prototype.parse = function(attrs) {
548 if (attrs[this.name] != null) {
549 return attrs[this.name] = new Date(attrs[this.name]);
550 }
551 };
552
553 DateTimeField.prototype.format = function(attrs) {
554 if ((attrs[this.name] != null) && !(attrs[this.name] instanceof Date)) {
555 return attrs[this.name] = new Date(attrs[this.name]);
556 }
557 };
558
559 DateTimeField.prototype._validateDatetime = function(value) {
560 if (value instanceof Date) {
561 return true;
562 }
563 if (typeof value === 'string' && !isNaN(Date.parse(value))) {
564 return true;
565 }
566 return false;
567 };
568
569 return DateTimeField;
570
571})(Field);
572
573DateField = (function(superClass) {
574 extend(DateField, superClass);
575
576 function DateField(name, options) {
577 if (!(this instanceof DateField)) {
578 return new DateField(name, options);
579 }
580 DateField.__super__.constructor.call(this, name, options);
581 }
582
583 DateField.prototype.parse = function(attrs) {
584 var d;
585 if (attrs[this.name] != null) {
586 d = new Date(attrs[this.name]);
587 return attrs[this.name] = new Date(d.getFullYear(), d.getMonth(), d.getDate());
588 }
589 };
590
591 DateField.prototype.format = function(attrs) {
592 var d;
593 if (attrs[this.name] != null) {
594 d = !(attrs[this.name] instanceof Date) ? new Date(attrs[this.name]) : attrs[this.name];
595 return attrs[this.name] = new Date(d.getFullYear(), d.getMonth(), d.getDate());
596 }
597 };
598
599 return DateField;
600
601})(DateTimeField);
602
603JSONField = (function(superClass) {
604 extend(JSONField, superClass);
605
606 function JSONField(name, options) {
607 if (!(this instanceof JSONField)) {
608 return new JSONField(name, options);
609 }
610 JSONField.__super__.constructor.call(this, name, options);
611 }
612
613 JSONField.prototype.validations = function() {
614 var result;
615 result = JSONField.__super__.validations.apply(this, arguments);
616 result.push(this._withMessage(this._validateJSON));
617 return result;
618 };
619
620 JSONField.prototype.format = function(attrs) {
621 if (!(attrs[this.name] && typeof attrs[this.name] === 'object')) {
622 return;
623 }
624 return attrs[this.name] = JSON.stringify(attrs[this.name]);
625 };
626
627 JSONField.prototype.parse = function(attrs) {
628 if (!(attrs[this.name] && typeof attrs[this.name] === 'string')) {
629 return;
630 }
631 return attrs[this.name] = JSON.parse(attrs[this.name]);
632 };
633
634 JSONField.prototype._validateJSON = function(value) {
635 if (typeof value === 'object') {
636 return true;
637 }
638 if (typeof value !== 'string') {
639 return false;
640 }
641 JSON.parse(value);
642 return true;
643 };
644
645 return JSONField;
646
647})(Field);
648
649module.exports = {
650 Field: Field,
651 StringField: StringField,
652 EmailField: EmailField,
653 EncryptedStringField: EncryptedStringField,
654 NumberField: NumberField,
655 IntField: IntField,
656 FloatField: FloatField,
657 BooleanField: BooleanField,
658 DateTimeField: DateTimeField,
659 DateField: DateField,
660 JSONField: JSONField
661};