@radio-garden/ditojs-server 2.85.2-0.5067ad799

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.
Files changed (137) hide show
  1. package/README.md +6 -0
  2. package/package.json +95 -0
  3. package/src/app/Application.js +1186 -0
  4. package/src/app/Validator.js +405 -0
  5. package/src/app/index.js +2 -0
  6. package/src/cli/console.js +152 -0
  7. package/src/cli/db/createMigration.js +241 -0
  8. package/src/cli/db/index.js +7 -0
  9. package/src/cli/db/listAssetConfig.js +10 -0
  10. package/src/cli/db/migrate.js +12 -0
  11. package/src/cli/db/reset.js +23 -0
  12. package/src/cli/db/rollback.js +12 -0
  13. package/src/cli/db/seed.js +80 -0
  14. package/src/cli/db/unlock.js +9 -0
  15. package/src/cli/index.js +72 -0
  16. package/src/controllers/AdminController.js +322 -0
  17. package/src/controllers/CollectionController.js +274 -0
  18. package/src/controllers/Controller.js +657 -0
  19. package/src/controllers/ControllerAction.js +370 -0
  20. package/src/controllers/MemberAction.js +27 -0
  21. package/src/controllers/ModelController.js +63 -0
  22. package/src/controllers/RelationController.js +93 -0
  23. package/src/controllers/UsersController.js +64 -0
  24. package/src/controllers/index.js +5 -0
  25. package/src/errors/AssetError.js +7 -0
  26. package/src/errors/AuthenticationError.js +7 -0
  27. package/src/errors/AuthorizationError.js +7 -0
  28. package/src/errors/ControllerError.js +14 -0
  29. package/src/errors/DatabaseError.js +37 -0
  30. package/src/errors/GraphError.js +7 -0
  31. package/src/errors/ModelError.js +12 -0
  32. package/src/errors/NotFoundError.js +7 -0
  33. package/src/errors/NotImplementedError.js +7 -0
  34. package/src/errors/QueryBuilderError.js +7 -0
  35. package/src/errors/RelationError.js +21 -0
  36. package/src/errors/ResponseError.js +56 -0
  37. package/src/errors/ValidationError.js +7 -0
  38. package/src/errors/index.js +13 -0
  39. package/src/graph/DitoGraphProcessor.js +213 -0
  40. package/src/graph/expression.js +53 -0
  41. package/src/graph/graph.js +258 -0
  42. package/src/graph/index.js +3 -0
  43. package/src/index.js +9 -0
  44. package/src/lib/EventEmitter.js +66 -0
  45. package/src/lib/KnexHelper.js +30 -0
  46. package/src/lib/index.js +2 -0
  47. package/src/middleware/attachLogger.js +8 -0
  48. package/src/middleware/createTransaction.js +33 -0
  49. package/src/middleware/extendContext.js +10 -0
  50. package/src/middleware/findRoute.js +20 -0
  51. package/src/middleware/handleConnectMiddleware.js +99 -0
  52. package/src/middleware/handleError.js +29 -0
  53. package/src/middleware/handleRoute.js +23 -0
  54. package/src/middleware/handleSession.js +77 -0
  55. package/src/middleware/handleUser.js +31 -0
  56. package/src/middleware/index.js +11 -0
  57. package/src/middleware/logRequests.js +125 -0
  58. package/src/middleware/setupRequestStorage.js +14 -0
  59. package/src/mixins/AssetMixin.js +78 -0
  60. package/src/mixins/SessionMixin.js +17 -0
  61. package/src/mixins/TimeStampedMixin.js +41 -0
  62. package/src/mixins/UserMixin.js +171 -0
  63. package/src/mixins/index.js +4 -0
  64. package/src/models/AssetModel.js +4 -0
  65. package/src/models/Model.js +1205 -0
  66. package/src/models/RelationAccessor.js +41 -0
  67. package/src/models/SessionModel.js +4 -0
  68. package/src/models/TimeStampedModel.js +4 -0
  69. package/src/models/UserModel.js +4 -0
  70. package/src/models/definitions/assets.js +5 -0
  71. package/src/models/definitions/filters.js +121 -0
  72. package/src/models/definitions/hooks.js +8 -0
  73. package/src/models/definitions/index.js +22 -0
  74. package/src/models/definitions/modifiers.js +5 -0
  75. package/src/models/definitions/options.js +5 -0
  76. package/src/models/definitions/properties.js +73 -0
  77. package/src/models/definitions/relations.js +5 -0
  78. package/src/models/definitions/schema.js +5 -0
  79. package/src/models/definitions/scopes.js +36 -0
  80. package/src/models/index.js +5 -0
  81. package/src/query/QueryBuilder.js +1077 -0
  82. package/src/query/QueryFilters.js +66 -0
  83. package/src/query/QueryParameters.js +79 -0
  84. package/src/query/Registry.js +29 -0
  85. package/src/query/index.js +3 -0
  86. package/src/schema/formats/_empty.js +4 -0
  87. package/src/schema/formats/_required.js +4 -0
  88. package/src/schema/formats/index.js +2 -0
  89. package/src/schema/index.js +5 -0
  90. package/src/schema/keywords/_computed.js +7 -0
  91. package/src/schema/keywords/_foreign.js +7 -0
  92. package/src/schema/keywords/_hidden.js +7 -0
  93. package/src/schema/keywords/_index.js +7 -0
  94. package/src/schema/keywords/_instanceof.js +45 -0
  95. package/src/schema/keywords/_primary.js +7 -0
  96. package/src/schema/keywords/_range.js +18 -0
  97. package/src/schema/keywords/_relate.js +13 -0
  98. package/src/schema/keywords/_specificType.js +7 -0
  99. package/src/schema/keywords/_unique.js +7 -0
  100. package/src/schema/keywords/_unsigned.js +7 -0
  101. package/src/schema/keywords/_validate.js +73 -0
  102. package/src/schema/keywords/index.js +12 -0
  103. package/src/schema/relations.js +324 -0
  104. package/src/schema/relations.test.js +177 -0
  105. package/src/schema/schema.js +289 -0
  106. package/src/schema/schema.test.js +720 -0
  107. package/src/schema/types/_asset.js +31 -0
  108. package/src/schema/types/_color.js +4 -0
  109. package/src/schema/types/index.js +2 -0
  110. package/src/services/Service.js +35 -0
  111. package/src/services/index.js +1 -0
  112. package/src/storage/AssetFile.js +81 -0
  113. package/src/storage/DiskStorage.js +114 -0
  114. package/src/storage/S3Storage.js +169 -0
  115. package/src/storage/Storage.js +231 -0
  116. package/src/storage/index.js +9 -0
  117. package/src/utils/duration.js +15 -0
  118. package/src/utils/emitter.js +8 -0
  119. package/src/utils/fs.js +10 -0
  120. package/src/utils/function.js +17 -0
  121. package/src/utils/function.test.js +77 -0
  122. package/src/utils/handler.js +17 -0
  123. package/src/utils/json.js +3 -0
  124. package/src/utils/model.js +35 -0
  125. package/src/utils/net.js +17 -0
  126. package/src/utils/object.js +82 -0
  127. package/src/utils/object.test.js +86 -0
  128. package/src/utils/scope.js +7 -0
  129. package/types/index.d.ts +3547 -0
  130. package/types/tests/application.test-d.ts +26 -0
  131. package/types/tests/controller.test-d.ts +113 -0
  132. package/types/tests/errors.test-d.ts +53 -0
  133. package/types/tests/fixtures.ts +19 -0
  134. package/types/tests/model.test-d.ts +193 -0
  135. package/types/tests/query-builder.test-d.ts +106 -0
  136. package/types/tests/relation.test-d.ts +83 -0
  137. package/types/tests/storage.test-d.ts +113 -0
@@ -0,0 +1,720 @@
1
+ import { convertSchema } from './schema.js'
2
+
3
+ describe('convertSchema()', () => {
4
+ it('expands objects with properties to full JSON schemas', () => {
5
+ const properties = {
6
+ myString: {
7
+ type: 'string'
8
+ },
9
+ myNumber: {
10
+ type: 'number'
11
+ },
12
+ myInteger: {
13
+ type: 'integer'
14
+ },
15
+ myBoolean: {
16
+ type: 'boolean'
17
+ },
18
+ myObject: {
19
+ type: 'object'
20
+ },
21
+ myArray: {
22
+ type: 'array'
23
+ }
24
+ }
25
+ expect(
26
+ convertSchema({
27
+ type: 'object',
28
+ properties
29
+ })
30
+ ).toEqual({
31
+ type: 'object',
32
+ properties,
33
+ unevaluatedProperties: false
34
+ })
35
+ })
36
+
37
+ it('supports falsy default values', () => {
38
+ const properties = {
39
+ myString: {
40
+ type: 'string',
41
+ default: ''
42
+ },
43
+ myNumber: {
44
+ type: 'number',
45
+ default: 0
46
+ },
47
+ myInteger: {
48
+ type: 'integer',
49
+ default: 0
50
+ },
51
+ myBoolean: {
52
+ type: 'boolean',
53
+ default: false
54
+ },
55
+ myObject: {
56
+ type: 'object',
57
+ default: null
58
+ },
59
+ myArray: {
60
+ type: 'array',
61
+ default: null
62
+ }
63
+ }
64
+ expect(
65
+ convertSchema({
66
+ type: 'object',
67
+ properties
68
+ })
69
+ ).toEqual({
70
+ type: 'object',
71
+ properties,
72
+ unevaluatedProperties: false
73
+ })
74
+ })
75
+
76
+ it(`expands 'text' types to 'string' JSON schema types`, () => {
77
+ expect(
78
+ convertSchema({
79
+ type: 'object',
80
+ properties: {
81
+ myText: {
82
+ type: 'text'
83
+ }
84
+ }
85
+ })
86
+ ).toEqual({
87
+ type: 'object',
88
+ properties: {
89
+ myText: {
90
+ type: 'string'
91
+ }
92
+ },
93
+ unevaluatedProperties: false
94
+ })
95
+ })
96
+
97
+ it('adds `required` arrays and formats for required properties', () => {
98
+ expect(
99
+ convertSchema({
100
+ type: 'object',
101
+ properties: {
102
+ myString: {
103
+ type: 'string',
104
+ required: true
105
+ },
106
+ myNumber: {
107
+ type: 'number',
108
+ required: true
109
+ }
110
+ }
111
+ })
112
+ ).toEqual({
113
+ type: 'object',
114
+ properties: {
115
+ myString: {
116
+ type: 'string',
117
+ format: 'required'
118
+ },
119
+ myNumber: {
120
+ type: 'number',
121
+ format: 'required'
122
+ }
123
+ },
124
+ unevaluatedProperties: false,
125
+ required: ['myString', 'myNumber']
126
+ })
127
+ })
128
+
129
+ it('preserves JSON schema-style `required` arrays', () => {
130
+ expect(
131
+ convertSchema({
132
+ type: 'object',
133
+ required: ['myString', 'myNumber'],
134
+ properties: {
135
+ myString: { type: 'string' },
136
+ myNumber: { type: 'number' }
137
+ }
138
+ })
139
+ ).toEqual({
140
+ type: 'object',
141
+ properties: {
142
+ myString: { type: 'string' },
143
+ myNumber: { type: 'number' }
144
+ },
145
+ unevaluatedProperties: false,
146
+ required: ['myString', 'myNumber']
147
+ })
148
+ })
149
+
150
+ it(`expands 'object' schemas with properties to JSON schemas allowing no unevaluated properties`, () => {
151
+ expect(
152
+ convertSchema({
153
+ type: 'object',
154
+ properties: {
155
+ myText: {
156
+ type: 'object',
157
+ properties: {}
158
+ }
159
+ }
160
+ })
161
+ ).toEqual({
162
+ type: 'object',
163
+ properties: {
164
+ myText: {
165
+ type: 'object',
166
+ unevaluatedProperties: false,
167
+ properties: {}
168
+ }
169
+ },
170
+ unevaluatedProperties: false
171
+ })
172
+ })
173
+
174
+ it('preserves pre-existing settings for no unevaluated properties', () => {
175
+ expect(
176
+ convertSchema({
177
+ type: 'object',
178
+ properties: {
179
+ myText: {
180
+ type: 'object',
181
+ unevaluatedProperties: true,
182
+ properties: {}
183
+ }
184
+ }
185
+ })
186
+ ).toEqual({
187
+ type: 'object',
188
+ properties: {
189
+ myText: {
190
+ type: 'object',
191
+ unevaluatedProperties: true,
192
+ properties: {}
193
+ }
194
+ },
195
+ unevaluatedProperties: false
196
+ })
197
+ })
198
+
199
+ it('expands nested object schemas with required properties', () => {
200
+ expect(
201
+ convertSchema({
202
+ type: 'object',
203
+ properties: {
204
+ myText: {
205
+ type: 'object',
206
+ properties: {
207
+ myProperty: {
208
+ type: 'text',
209
+ required: true
210
+ }
211
+ }
212
+ }
213
+ }
214
+ })
215
+ ).toEqual({
216
+ type: 'object',
217
+ properties: {
218
+ myText: {
219
+ type: 'object',
220
+ properties: {
221
+ myProperty: {
222
+ type: 'string',
223
+ format: 'required'
224
+ }
225
+ },
226
+ unevaluatedProperties: false,
227
+ required: ['myProperty']
228
+ }
229
+ },
230
+ unevaluatedProperties: false
231
+ })
232
+ })
233
+
234
+ it(`expands 'object' schemas with patternProperties`, () => {
235
+ expect(
236
+ convertSchema({
237
+ type: 'object',
238
+ properties: {
239
+ myText: {
240
+ type: 'object',
241
+ patternProperties: {
242
+ '^.*$': {
243
+ type: 'text'
244
+ }
245
+ }
246
+ }
247
+ }
248
+ })
249
+ ).toEqual({
250
+ type: 'object',
251
+ properties: {
252
+ myText: {
253
+ type: 'object',
254
+ patternProperties: {
255
+ '^.*$': {
256
+ type: 'string'
257
+ }
258
+ },
259
+ unevaluatedProperties: false
260
+ }
261
+ },
262
+ unevaluatedProperties: false
263
+ })
264
+ })
265
+
266
+ it('expands datetime types to their JSON schema representation', () => {
267
+ expect(
268
+ convertSchema({
269
+ type: 'object',
270
+ properties: {
271
+ myDate: {
272
+ type: 'date'
273
+ },
274
+ myDateTime: {
275
+ type: 'datetime'
276
+ },
277
+ myTimeStamp: {
278
+ type: 'timestamp'
279
+ }
280
+ }
281
+ })
282
+ ).toEqual({
283
+ type: 'object',
284
+ properties: {
285
+ myDate: {
286
+ type: ['string', 'object'],
287
+ format: 'date-time'
288
+ },
289
+ myDateTime: {
290
+ type: ['string', 'object'],
291
+ format: 'date-time'
292
+ },
293
+ myTimeStamp: {
294
+ type: ['string', 'object'],
295
+ format: 'date-time'
296
+ }
297
+ },
298
+ unevaluatedProperties: false
299
+ })
300
+ })
301
+
302
+ it('expands unrecognized types to `$ref` references', () => {
303
+ expect(
304
+ convertSchema({
305
+ type: 'object',
306
+ properties: {
307
+ myModel: {
308
+ type: 'MyModel'
309
+ }
310
+ }
311
+ })
312
+ ).toEqual({
313
+ type: 'object',
314
+ properties: {
315
+ myModel: {
316
+ $ref: 'MyModel'
317
+ }
318
+ },
319
+ unevaluatedProperties: false
320
+ })
321
+ })
322
+
323
+ it(`expands unrecognized types to \`instanceof\` keywords when the \`useInstanceOf\` option is provided`, () => {
324
+ expect(
325
+ convertSchema(
326
+ {
327
+ type: 'object',
328
+ properties: {
329
+ myModel: {
330
+ type: 'MyModel'
331
+ }
332
+ }
333
+ },
334
+ {
335
+ useInstanceOf: true
336
+ }
337
+ )
338
+ ).toEqual({
339
+ type: 'object',
340
+ properties: {
341
+ myModel: {
342
+ type: 'object',
343
+ instanceof: 'MyModel'
344
+ }
345
+ },
346
+ unevaluatedProperties: false
347
+ })
348
+ })
349
+
350
+ it('handles `nullable: true` correctly (now natively supported)', () => {
351
+ expect(
352
+ convertSchema({
353
+ type: 'object',
354
+ properties: {
355
+ myString: {
356
+ type: 'string',
357
+ nullable: true
358
+ }
359
+ }
360
+ })
361
+ ).toEqual({
362
+ type: 'object',
363
+ properties: {
364
+ myString: {
365
+ type: 'string',
366
+ nullable: true
367
+ }
368
+ },
369
+ unevaluatedProperties: false
370
+ })
371
+ })
372
+
373
+ it(`handles \`nullable: true\` references correctly`, () => {
374
+ expect(
375
+ convertSchema({
376
+ type: 'object',
377
+ properties: {
378
+ myModel: {
379
+ type: 'MyModel',
380
+ nullable: true
381
+ }
382
+ }
383
+ })
384
+ ).toEqual({
385
+ type: 'object',
386
+ properties: {
387
+ myModel: {
388
+ oneOf: [
389
+ { type: 'null' },
390
+ { $ref: 'MyModel' }
391
+ ]
392
+ }
393
+ },
394
+ unevaluatedProperties: false
395
+ })
396
+ })
397
+
398
+ it(`handles \`nullable: true\` dates correctly (now natively supported)`, () => {
399
+ expect(
400
+ convertSchema({
401
+ type: 'object',
402
+ properties: {
403
+ myDate: {
404
+ type: 'date',
405
+ nullable: true
406
+ }
407
+ }
408
+ })
409
+ ).toEqual({
410
+ type: 'object',
411
+ properties: {
412
+ myDate: {
413
+ type: ['string', 'object'],
414
+ format: 'date-time',
415
+ nullable: true
416
+ }
417
+ },
418
+ unevaluatedProperties: false
419
+ })
420
+ })
421
+
422
+ it(`handles \`nullable: true\` enums correctly`, () => {
423
+ expect(
424
+ convertSchema({
425
+ type: 'object',
426
+ properties: {
427
+ myEnum: {
428
+ type: 'string',
429
+ enum: ['one', 'two', 'three'],
430
+ nullable: true
431
+ }
432
+ }
433
+ })
434
+ ).toEqual({
435
+ type: 'object',
436
+ properties: {
437
+ myEnum: {
438
+ type: 'string',
439
+ enum: ['one', 'two', 'three', null],
440
+ nullable: true
441
+ }
442
+ },
443
+ unevaluatedProperties: false
444
+ })
445
+ })
446
+
447
+ it('converts schemas within oneOf properties', () => {
448
+ expect(
449
+ convertSchema({
450
+ type: 'object',
451
+ properties: {
452
+ myList: {
453
+ type: 'array',
454
+ items: {
455
+ oneOf: [
456
+ {
457
+ type: 'object',
458
+ properties: {
459
+ prop1: {
460
+ type: 'string',
461
+ required: true
462
+ },
463
+ prop2: {
464
+ type: 'number',
465
+ required: true
466
+ }
467
+ }
468
+ },
469
+ {
470
+ type: 'object',
471
+ properties: {
472
+ prop3: {
473
+ type: 'string',
474
+ required: true
475
+ },
476
+ prop4: {
477
+ type: 'number',
478
+ required: true
479
+ }
480
+ }
481
+ }
482
+ ]
483
+ }
484
+ }
485
+ }
486
+ })
487
+ ).toEqual({
488
+ type: 'object',
489
+ properties: {
490
+ myList: {
491
+ type: 'array',
492
+ items: {
493
+ oneOf: [
494
+ {
495
+ type: 'object',
496
+ properties: {
497
+ prop1: {
498
+ type: 'string',
499
+ format: 'required'
500
+ },
501
+ prop2: {
502
+ type: 'number',
503
+ format: 'required'
504
+ }
505
+ },
506
+ required: ['prop1', 'prop2'],
507
+ unevaluatedProperties: false
508
+ },
509
+ {
510
+ type: 'object',
511
+ properties: {
512
+ prop3: {
513
+ type: 'string',
514
+ format: 'required'
515
+ },
516
+ prop4: {
517
+ type: 'number',
518
+ format: 'required'
519
+ }
520
+ },
521
+ required: ['prop3', 'prop4'],
522
+ unevaluatedProperties: false
523
+ }
524
+ ]
525
+ }
526
+ }
527
+ },
528
+ unevaluatedProperties: false
529
+ })
530
+ })
531
+
532
+ it('supports `required: true` on object', () => {
533
+ expect(
534
+ convertSchema({
535
+ type: 'object',
536
+ properties: {
537
+ myObject: {
538
+ type: 'object',
539
+ required: true,
540
+ properties: {
541
+ prop1: {
542
+ type: 'string',
543
+ required: true
544
+ },
545
+ prop2: {
546
+ type: 'number',
547
+ required: true
548
+ }
549
+ }
550
+ }
551
+ }
552
+ })
553
+ ).toEqual({
554
+ type: 'object',
555
+ properties: {
556
+ myObject: {
557
+ type: 'object',
558
+ format: 'required',
559
+ properties: {
560
+ prop1: {
561
+ format: 'required',
562
+ type: 'string'
563
+ },
564
+ prop2: {
565
+ format: 'required',
566
+ type: 'number'
567
+ }
568
+ },
569
+ unevaluatedProperties: false,
570
+ required: ['prop1', 'prop2']
571
+ }
572
+ },
573
+ unevaluatedProperties: false,
574
+ required: ['myObject']
575
+ })
576
+ })
577
+
578
+ it('processes discriminator schemas correctly', () => {
579
+ expect(
580
+ convertSchema({
581
+ type: 'object',
582
+ discriminator: { propertyName: 'foo' },
583
+ required: ['foo'],
584
+ oneOf: [
585
+ {
586
+ properties: {
587
+ foo: { const: 'x' },
588
+ a: {
589
+ type: 'string',
590
+ required: true
591
+ }
592
+ }
593
+ },
594
+ {
595
+ properties: {
596
+ foo: { enum: ['y', 'z'] },
597
+ b: {
598
+ type: 'string',
599
+ required: true
600
+ }
601
+ }
602
+ }
603
+ ]
604
+ })
605
+ ).toEqual({
606
+ type: 'object',
607
+ discriminator: { propertyName: 'foo' },
608
+ unevaluatedProperties: false,
609
+ required: ['foo'],
610
+ oneOf: [
611
+ {
612
+ properties: {
613
+ foo: { const: 'x' },
614
+ a: {
615
+ type: 'string',
616
+ format: 'required'
617
+ }
618
+ },
619
+ required: ['a']
620
+ },
621
+ {
622
+ properties: {
623
+ foo: { enum: ['y', 'z'] },
624
+ b: {
625
+ type: 'string',
626
+ format: 'required'
627
+ }
628
+ },
629
+ required: ['b']
630
+ }
631
+ ]
632
+ })
633
+ })
634
+
635
+ it('supports nested Dito.js definitions', () => {
636
+ expect(
637
+ convertSchema(
638
+ {
639
+ type: 'object',
640
+ properties: {
641
+ prop1: {
642
+ $ref: '#type1'
643
+ },
644
+ prop2: {
645
+ type: 'object',
646
+ properties: {
647
+ prop3: {
648
+ $ref: '#type2'
649
+ }
650
+ },
651
+ definitions: {
652
+ '#type2': {
653
+ type: 'object',
654
+ properties: {
655
+ prop4: {
656
+ type: 'string'
657
+ },
658
+
659
+ prop5: {
660
+ $ref: '#type3'
661
+ }
662
+ },
663
+
664
+ definitions: {
665
+ '#type3': {
666
+ type: 'boolean'
667
+ }
668
+ }
669
+ }
670
+ }
671
+ }
672
+ },
673
+
674
+ definitions: {
675
+ '#type1': {
676
+ type: 'integer'
677
+ }
678
+ }
679
+ }
680
+ )
681
+ ).toEqual({
682
+ type: 'object',
683
+ unevaluatedProperties: false,
684
+ properties: {
685
+ prop1: {
686
+ $ref: '#/definitions/#type1'
687
+ },
688
+ prop2: {
689
+ type: 'object',
690
+ unevaluatedProperties: false,
691
+ properties: {
692
+ prop3: {
693
+ $ref: '#/definitions/#type2'
694
+ }
695
+ }
696
+ }
697
+ },
698
+ definitions: {
699
+ '#type1': {
700
+ type: 'integer'
701
+ },
702
+ '#type2': {
703
+ type: 'object',
704
+ unevaluatedProperties: false,
705
+ properties: {
706
+ prop4: {
707
+ type: 'string'
708
+ },
709
+ prop5: {
710
+ $ref: '#/definitions/#type3'
711
+ }
712
+ }
713
+ },
714
+ '#type3': {
715
+ type: 'boolean'
716
+ }
717
+ }
718
+ })
719
+ })
720
+ })