@takeshape/schema 11.72.0 → 11.74.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.
Files changed (108) hide show
  1. package/dist/models/runtime-schema.js +1 -0
  2. package/dist/project-schema/latest.d.ts +6 -1
  3. package/dist/project-schema/v3.48.0.d.ts +6 -1
  4. package/dist/project-schema/v3.49.0.d.ts +6 -1
  5. package/dist/project-schema/v3.50.0.d.ts +6 -1
  6. package/dist/project-schema/v3.51.0.d.ts +6 -1
  7. package/dist/project-schema/v3.52.0.d.ts +6 -1
  8. package/dist/project-schema/v3.53.0.d.ts +6 -1
  9. package/dist/project-schema/v3.54.0.d.ts +6 -1
  10. package/dist/schemas/project-schema/experimental.json +20 -0
  11. package/dist/util/expressions.js +2 -2
  12. package/package.json +6 -6
  13. package/dist/__tests__/_examples.test.d.ts +0 -1
  14. package/dist/__tests__/_examples.test.js +0 -77
  15. package/dist/__tests__/agents.test.d.ts +0 -1
  16. package/dist/__tests__/agents.test.js +0 -163
  17. package/dist/__tests__/api-version.test.d.ts +0 -1
  18. package/dist/__tests__/api-version.test.js +0 -24
  19. package/dist/__tests__/builtin-schema.test.d.ts +0 -1
  20. package/dist/__tests__/builtin-schema.test.js +0 -18
  21. package/dist/__tests__/content-schema-transform.test.d.ts +0 -1
  22. package/dist/__tests__/content-schema-transform.test.js +0 -522
  23. package/dist/__tests__/create-input-schema.test.d.ts +0 -1
  24. package/dist/__tests__/create-input-schema.test.js +0 -184
  25. package/dist/__tests__/enum.test.d.ts +0 -1
  26. package/dist/__tests__/enum.test.js +0 -36
  27. package/dist/__tests__/flatten-templates.test.d.ts +0 -1
  28. package/dist/__tests__/flatten-templates.test.js +0 -40
  29. package/dist/__tests__/get-is-leaf.test.d.ts +0 -1
  30. package/dist/__tests__/get-is-leaf.test.js +0 -50
  31. package/dist/__tests__/interfaces.test.d.ts +0 -1
  32. package/dist/__tests__/interfaces.test.js +0 -219
  33. package/dist/__tests__/migration.test.d.ts +0 -1
  34. package/dist/__tests__/migration.test.js +0 -34
  35. package/dist/__tests__/mocks.test.d.ts +0 -1
  36. package/dist/__tests__/mocks.test.js +0 -24
  37. package/dist/__tests__/refs.test.d.ts +0 -1
  38. package/dist/__tests__/refs.test.js +0 -813
  39. package/dist/__tests__/relationships.test.d.ts +0 -1
  40. package/dist/__tests__/relationships.test.js +0 -638
  41. package/dist/__tests__/schema-transform.test.d.ts +0 -1
  42. package/dist/__tests__/schema-transform.test.js +0 -205
  43. package/dist/__tests__/schema-util.test.d.ts +0 -1
  44. package/dist/__tests__/schema-util.test.js +0 -1731
  45. package/dist/__tests__/service-dependencies.test.d.ts +0 -1
  46. package/dist/__tests__/service-dependencies.test.js +0 -360
  47. package/dist/__tests__/unions.test.d.ts +0 -1
  48. package/dist/__tests__/unions.test.js +0 -44
  49. package/dist/__tests__/validate.test.d.ts +0 -1
  50. package/dist/__tests__/validate.test.js +0 -1980
  51. package/dist/__tests__/workflows.test.d.ts +0 -3
  52. package/dist/__tests__/workflows.test.js +0 -149
  53. package/dist/layers/__tests__/layers.test.d.ts +0 -1
  54. package/dist/layers/__tests__/layers.test.js +0 -38
  55. package/dist/migration/to/__tests__/v3.10.0.test.d.ts +0 -1
  56. package/dist/migration/to/__tests__/v3.10.0.test.js +0 -90
  57. package/dist/migration/to/__tests__/v3.12.3.test.d.ts +0 -1
  58. package/dist/migration/to/__tests__/v3.12.3.test.js +0 -103
  59. package/dist/migration/to/__tests__/v3.17.test.d.ts +0 -1
  60. package/dist/migration/to/__tests__/v3.17.test.js +0 -71
  61. package/dist/migration/to/__tests__/v3.34.0.test.d.ts +0 -1
  62. package/dist/migration/to/__tests__/v3.34.0.test.js +0 -240
  63. package/dist/migration/to/__tests__/v3.39.0.test.d.ts +0 -1
  64. package/dist/migration/to/__tests__/v3.39.0.test.js +0 -116
  65. package/dist/migration/to/__tests__/v3.46.0.test.d.ts +0 -1
  66. package/dist/migration/to/__tests__/v3.46.0.test.js +0 -59
  67. package/dist/models/__tests__/fixtures.d.ts +0 -15
  68. package/dist/models/__tests__/fixtures.js +0 -56
  69. package/dist/models/__tests__/query.test.d.ts +0 -1
  70. package/dist/models/__tests__/query.test.js +0 -19
  71. package/dist/models/__tests__/runtime-schema.test.d.ts +0 -1
  72. package/dist/models/__tests__/runtime-schema.test.js +0 -43
  73. package/dist/models/__tests__/shape.test.d.ts +0 -1
  74. package/dist/models/__tests__/shape.test.js +0 -24
  75. package/dist/resolvers/ai/__tests__/rag-query.test.d.ts +0 -1
  76. package/dist/resolvers/ai/__tests__/rag-query.test.js +0 -49
  77. package/dist/services/__tests__/services.test.d.ts +0 -1
  78. package/dist/services/__tests__/services.test.js +0 -113
  79. package/dist/template-shapes/__tests__/index.test.d.ts +0 -1
  80. package/dist/template-shapes/__tests__/index.test.js +0 -40
  81. package/dist/template-shapes/__tests__/names.test.d.ts +0 -1
  82. package/dist/template-shapes/__tests__/names.test.js +0 -19
  83. package/dist/template-shapes/__tests__/templates.test.d.ts +0 -1
  84. package/dist/template-shapes/__tests__/templates.test.js +0 -80
  85. package/dist/template-shapes/__tests__/where.test.d.ts +0 -1
  86. package/dist/template-shapes/__tests__/where.test.js +0 -218
  87. package/dist/types/__tests__/utils.test.d.ts +0 -1
  88. package/dist/types/__tests__/utils.test.js +0 -159
  89. package/dist/util/__tests__/api-indexing.test.d.ts +0 -1
  90. package/dist/util/__tests__/api-indexing.test.js +0 -129
  91. package/dist/util/__tests__/detect-cycles.test.d.ts +0 -1
  92. package/dist/util/__tests__/detect-cycles.test.js +0 -193
  93. package/dist/util/__tests__/expressions.test.d.ts +0 -1
  94. package/dist/util/__tests__/expressions.test.js +0 -172
  95. package/dist/util/__tests__/find-shape-at-path.test.d.ts +0 -1
  96. package/dist/util/__tests__/find-shape-at-path.test.js +0 -41
  97. package/dist/util/__tests__/form-config.test.d.ts +0 -1
  98. package/dist/util/__tests__/form-config.test.js +0 -196
  99. package/dist/util/__tests__/get-return-shape.test.d.ts +0 -1
  100. package/dist/util/__tests__/get-return-shape.test.js +0 -27
  101. package/dist/util/__tests__/has-args.test.d.ts +0 -1
  102. package/dist/util/__tests__/has-args.test.js +0 -46
  103. package/dist/util/__tests__/merge.test.d.ts +0 -1
  104. package/dist/util/__tests__/merge.test.js +0 -1074
  105. package/dist/util/__tests__/patch-schema.test.d.ts +0 -1
  106. package/dist/util/__tests__/patch-schema.test.js +0 -82
  107. package/dist/util/__tests__/shapes.test.d.ts +0 -1
  108. package/dist/util/__tests__/shapes.test.js +0 -30
@@ -1,1074 +0,0 @@
1
- import set from 'lodash/fp/set.js';
2
- import unset from 'lodash/fp/unset.js';
3
- import { describe, expect, test } from 'vitest';
4
- import { createMockSchema } from "../../mocks.js";
5
- import { createShape } from "../../schema-util.js";
6
- import { mergeDeepObjectSchemas, mergeFormConfigs, mergeObjectSchemas, mergeProjectSchemas } from "../merge.js";
7
- describe('mergeObjectSchemas', () => {
8
- test('it works', () => {
9
- const original = {
10
- type: 'object',
11
- properties: {
12
- a: { type: 'string' },
13
- b: { type: 'string' }
14
- },
15
- required: ['a', 'b']
16
- };
17
- const override = {
18
- type: 'object',
19
- properties: {
20
- c: { type: 'string' }
21
- },
22
- required: ['c']
23
- };
24
- expect(mergeObjectSchemas(original, override)).toEqual({
25
- type: 'object',
26
- properties: {
27
- a: { type: 'string' },
28
- b: { type: 'string' },
29
- c: { type: 'string' }
30
- },
31
- required: ['a', 'b', 'c']
32
- });
33
- });
34
- test('overrides', () => {
35
- const original = {
36
- type: 'object',
37
- properties: {
38
- a: { type: 'string' },
39
- b: { type: 'string' }
40
- },
41
- required: ['a', 'b']
42
- };
43
- const override = {
44
- type: 'object',
45
- properties: {
46
- b: { type: 'integer' }
47
- }
48
- };
49
- expect(mergeObjectSchemas(original, override)).toEqual({
50
- type: 'object',
51
- properties: {
52
- a: { type: 'string' },
53
- b: { type: 'integer' }
54
- },
55
- required: ['a', 'b']
56
- });
57
- });
58
- });
59
- describe('mergeDeepObjectSchemas', () => {
60
- test('deep merge', () => {
61
- const original = {
62
- type: 'object',
63
- properties: {
64
- obj: {
65
- type: 'object',
66
- properties: {
67
- a: { type: 'string' },
68
- b: { type: 'string' }
69
- },
70
- required: ['a', 'b']
71
- }
72
- }
73
- };
74
- const override = {
75
- type: 'object',
76
- properties: {
77
- obj: {
78
- type: 'object',
79
- properties: {
80
- c: { type: 'string' }
81
- },
82
- required: ['c']
83
- }
84
- }
85
- };
86
- expect(mergeDeepObjectSchemas(original, override)).toEqual({
87
- type: 'object',
88
- properties: {
89
- obj: {
90
- type: 'object',
91
- properties: {
92
- a: { type: 'string' },
93
- b: { type: 'string' },
94
- c: { type: 'string' }
95
- },
96
- required: ['a', 'b', 'c']
97
- }
98
- }
99
- });
100
- });
101
- test('uses allOf merge @ref', () => {
102
- const original = {
103
- type: 'object',
104
- properties: {
105
- obj: {
106
- '@ref': 'local:Test'
107
- }
108
- }
109
- };
110
- const override = {
111
- type: 'object',
112
- properties: {
113
- obj: {
114
- type: 'object',
115
- properties: {
116
- c: { type: 'string' }
117
- },
118
- required: ['c']
119
- }
120
- }
121
- };
122
- expect(mergeDeepObjectSchemas(original, override)).toEqual({
123
- type: 'object',
124
- properties: {
125
- obj: {
126
- allOf: [
127
- { '@ref': 'local:Test' },
128
- {
129
- type: 'object',
130
- properties: {
131
- c: { type: 'string' }
132
- },
133
- required: ['c']
134
- }
135
- ]
136
- }
137
- }
138
- });
139
- });
140
- test('properly handles duplicate refs', () => {
141
- const original = {
142
- type: 'object',
143
- properties: {
144
- a: {
145
- '@ref': 'local:Test'
146
- },
147
- b: { type: 'string' }
148
- }
149
- };
150
- const override = {
151
- type: 'object',
152
- properties: {
153
- a: {
154
- '@ref': 'local:Test'
155
- },
156
- c: { type: 'integer' }
157
- }
158
- };
159
- expect(mergeDeepObjectSchemas(original, override)).toEqual({
160
- type: 'object',
161
- properties: {
162
- a: {
163
- '@ref': 'local:Test'
164
- },
165
- b: {
166
- type: 'string'
167
- },
168
- c: {
169
- type: 'integer'
170
- }
171
- }
172
- });
173
- });
174
- });
175
- describe('mergeFormConfigs', () => {
176
- test('it works', () => {
177
- const primary = {
178
- order: ['shapePropertyType', 'name', 'isRequired'],
179
- properties: {
180
- name: {
181
- widget: 'singleLineText'
182
- },
183
- isRequired: {
184
- widget: 'checkbox'
185
- }
186
- }
187
- };
188
- const l10n = {
189
- order: ['enableLocalization'],
190
- properties: {
191
- widget: 'switch'
192
- }
193
- };
194
- const common = {
195
- order: ['name', 'title', 'description', 'instructions', 'widget'],
196
- properties: {
197
- name: {
198
- widget: 'shapePropertyName'
199
- },
200
- title: {
201
- widget: 'singleLineText'
202
- },
203
- description: {
204
- widget: 'singleLineText'
205
- },
206
- instructions: {
207
- widget: 'singleLineText'
208
- },
209
- widget: {
210
- properties: {
211
- name: {
212
- widget: 'dropdown',
213
- hiddenValues: ['custom']
214
- }
215
- }
216
- }
217
- }
218
- };
219
- expect(mergeFormConfigs(primary, l10n, common)).toEqual({
220
- order: [
221
- 'shapePropertyType',
222
- 'name',
223
- 'isRequired',
224
- 'enableLocalization',
225
- 'title',
226
- 'description',
227
- 'instructions',
228
- 'widget'
229
- ],
230
- properties: {
231
- description: {
232
- widget: 'singleLineText'
233
- },
234
- instructions: {
235
- widget: 'singleLineText'
236
- },
237
- isRequired: {
238
- widget: 'checkbox'
239
- },
240
- name: {
241
- widget: 'shapePropertyName'
242
- },
243
- title: {
244
- widget: 'singleLineText'
245
- },
246
- widget: {
247
- properties: {
248
- name: {
249
- hiddenValues: ['custom'],
250
- widget: 'dropdown'
251
- }
252
- }
253
- }
254
- }
255
- });
256
- });
257
- });
258
- const emptySchema = createMockSchema('projectId');
259
- const addedService = {
260
- ...emptySchema,
261
- queries: {
262
- Rick_characters: {
263
- resolver: {
264
- name: 'graphql:query',
265
- service: 'rick',
266
- fieldName: 'characters'
267
- },
268
- args: {
269
- type: 'object',
270
- properties: {
271
- page: { type: 'integer' },
272
- filter: { '@ref': 'rick:FilterCharacter' }
273
- }
274
- },
275
- shape: 'Rick_Characters'
276
- }
277
- },
278
- services: {
279
- rick: {
280
- id: 'rick',
281
- provider: 'graphql',
282
- title: 'Rick',
283
- namespace: 'Rick',
284
- serviceType: 'graphql',
285
- authenticationType: 'none',
286
- options: { endpoint: 'https://rickandmortyapi.com/graphql' }
287
- }
288
- }
289
- };
290
- const addedShape = {
291
- ...emptySchema,
292
- queries: {
293
- getHomepage: {
294
- shape: 'Homepage',
295
- resolver: {
296
- name: 'shapedb:get',
297
- service: 'shapedb',
298
- shapeName: 'Homepage'
299
- },
300
- description: 'Get a Homepage by ID',
301
- args: 'TSGetArgs<Homepage>'
302
- }
303
- },
304
- mutations: {
305
- updateHomepage: {
306
- shape: 'UpdateResult<Homepage>',
307
- resolver: {
308
- name: 'shapedb:update',
309
- service: 'shapedb',
310
- shapeName: 'Homepage'
311
- },
312
- description: 'Update Homepage',
313
- args: 'UpdateArgs<Homepage>'
314
- }
315
- },
316
- shapes: {
317
- Homepage: {
318
- id: '7fms3CQ6d',
319
- name: 'Homepage',
320
- title: 'Homepage',
321
- model: { type: 'single' },
322
- schema: {
323
- type: 'object',
324
- properties: {
325
- greeting: {
326
- title: 'Greeting',
327
- '@mapping': 'shapedb:Homepage.uq8t3G3O6',
328
- type: 'string'
329
- }
330
- }
331
- }
332
- }
333
- },
334
- forms: {
335
- Homepage: {
336
- default: {
337
- properties: { greeting: { widget: 'singleLineText' } },
338
- order: ['greeting']
339
- }
340
- }
341
- }
342
- };
343
- const addedProperty = set('shapes.Homepage.schema.properties.body', {
344
- title: 'Body',
345
- '@mapping': 'shapedb:Homepage.abcXYZ123',
346
- type: 'string'
347
- }, addedShape);
348
- describe('mergeProjectSchemas', () => {
349
- test('merges when base/parent are the same', () => {
350
- const { mergedSchema } = mergeProjectSchemas(emptySchema, emptySchema, addedShape);
351
- expect(mergedSchema).toEqual(addedShape);
352
- });
353
- test('removes sections', () => {
354
- const { mergedSchema } = mergeProjectSchemas(addedShape, addedShape, emptySchema);
355
- expect(mergedSchema).toEqual(emptySchema);
356
- });
357
- test('merges unrelated changes', () => {
358
- const { mergedSchema } = mergeProjectSchemas(addedShape, emptySchema, addedService);
359
- expect(mergedSchema).toMatchObject({
360
- shapes: { ...addedShape.shapes, ...addedService.shapes },
361
- forms: { ...addedShape.forms, ...addedService.forms },
362
- services: { ...addedShape.services, ...addedService.services }
363
- });
364
- });
365
- test('fails on removal conflicts', () => {
366
- const { error } = mergeProjectSchemas(addedService, addedShape, addedProperty);
367
- expect(error).toEqual('Attempting to update shapes.Homepage which has already been removed');
368
- });
369
- test('fails on type conflicts', () => {
370
- const main = {
371
- ...emptySchema,
372
- shapes: {
373
- Name: createShape('Name', {
374
- type: 'object',
375
- properties: {
376
- name: {
377
- type: 'string'
378
- }
379
- }
380
- })
381
- }
382
- };
383
- const branch = {
384
- ...emptySchema,
385
- shapes: {
386
- Name: createShape('Name', {
387
- enum: ['FOO', 'BAR', 'BAZ']
388
- })
389
- }
390
- };
391
- const { error } = mergeProjectSchemas(main, emptySchema, branch);
392
- expect(error).toEqual('Unable to merge shapes.Name schemas conflict');
393
- });
394
- test('overwrite shape schema when there is no conflicting change', () => {
395
- const parent = {
396
- ...emptySchema,
397
- shapes: {
398
- Name: createShape('Name', {
399
- type: 'object',
400
- properties: {
401
- name: {
402
- type: 'string'
403
- }
404
- }
405
- })
406
- }
407
- };
408
- const main = {
409
- ...parent,
410
- shapes: {
411
- ...parent.shapes,
412
- TacoBell: createShape('TacoBell', {
413
- type: 'object',
414
- properties: {
415
- bajaBlast: {
416
- type: 'boolean'
417
- }
418
- }
419
- })
420
- }
421
- };
422
- const branch = {
423
- ...parent,
424
- shapes: {
425
- ...parent.shapes,
426
- Name: createShape('Name', {
427
- enum: ['FOO', 'BAR', 'BAZ']
428
- })
429
- }
430
- };
431
- const result = mergeProjectSchemas(main, parent, branch);
432
- expect(result.mergedSchema).toEqual({
433
- ...main,
434
- shapes: {
435
- Name: {
436
- id: 'Name',
437
- name: 'Name',
438
- schema: {
439
- enum: ['FOO', 'BAR', 'BAZ']
440
- },
441
- title: 'Name'
442
- },
443
- TacoBell: {
444
- id: 'TacoBell',
445
- name: 'TacoBell',
446
- schema: {
447
- properties: {
448
- bajaBlast: {
449
- type: 'boolean'
450
- }
451
- },
452
- type: 'object'
453
- },
454
- title: 'TacoBell'
455
- }
456
- }
457
- });
458
- });
459
- test('merges object properties when both base/parent are equal', () => {
460
- const main = {
461
- ...emptySchema,
462
- shapes: {
463
- Test: createShape('Test', {
464
- type: 'object',
465
- properties: {
466
- foo: {
467
- type: 'string'
468
- },
469
- bar: {
470
- type: 'string'
471
- }
472
- },
473
- required: ['foo']
474
- })
475
- }
476
- };
477
- const branch = {
478
- ...emptySchema,
479
- shapes: {
480
- Test: createShape('Test', {
481
- type: 'object',
482
- properties: {
483
- foo: {
484
- type: 'string'
485
- },
486
- baz: {
487
- type: 'string'
488
- }
489
- },
490
- required: ['foo', 'baz']
491
- })
492
- }
493
- };
494
- const result = mergeProjectSchemas(main, main, branch);
495
- expect(result.mergedSchema).toEqual(branch);
496
- });
497
- test('merges object properties when both base/head add the same shape', () => {
498
- const main = {
499
- ...emptySchema,
500
- shapes: {
501
- Test: createShape('Test', {
502
- type: 'object',
503
- properties: {
504
- foo: {
505
- type: 'string'
506
- },
507
- bar: {
508
- type: 'string'
509
- }
510
- },
511
- required: ['foo']
512
- })
513
- },
514
- forms: {
515
- Test: {
516
- default: {
517
- order: ['foo', 'bar'],
518
- properties: {
519
- foo: {
520
- widget: 'singleLineText'
521
- },
522
- bar: {
523
- widget: 'singleLineText'
524
- }
525
- }
526
- }
527
- }
528
- }
529
- };
530
- const branch = {
531
- ...emptySchema,
532
- shapes: {
533
- Test: createShape('Test', {
534
- type: 'object',
535
- properties: {
536
- foo: {
537
- type: 'string'
538
- },
539
- baz: {
540
- type: 'string'
541
- }
542
- },
543
- required: ['foo', 'baz']
544
- })
545
- },
546
- forms: {
547
- Test: {
548
- default: {
549
- order: ['foo', 'baz'],
550
- properties: {
551
- foo: {
552
- widget: 'singleLineText'
553
- },
554
- baz: {
555
- widget: 'singleLineText'
556
- }
557
- }
558
- }
559
- }
560
- }
561
- };
562
- const result = mergeProjectSchemas(main, emptySchema, branch);
563
- expect(result.mergedSchema).toEqual({
564
- ...main,
565
- shapes: {
566
- Test: createShape('Test', {
567
- type: 'object',
568
- properties: {
569
- foo: {
570
- type: 'string'
571
- },
572
- bar: {
573
- type: 'string'
574
- },
575
- baz: {
576
- type: 'string'
577
- }
578
- },
579
- required: ['foo', 'baz']
580
- })
581
- },
582
- forms: {
583
- Test: {
584
- default: {
585
- order: ['foo', 'bar', 'baz'],
586
- properties: {
587
- foo: {
588
- widget: 'singleLineText'
589
- },
590
- bar: {
591
- widget: 'singleLineText'
592
- },
593
- baz: {
594
- widget: 'singleLineText'
595
- }
596
- }
597
- }
598
- }
599
- }
600
- });
601
- });
602
- test('rebase object properties when both base/head update shape', () => {
603
- const parent = {
604
- ...emptySchema,
605
- shapes: {
606
- Test: createShape('Test', {
607
- type: 'object',
608
- properties: {
609
- foo: {
610
- type: 'string'
611
- },
612
- bar: {
613
- type: 'string'
614
- },
615
- huh: {
616
- type: 'string'
617
- }
618
- },
619
- required: ['foo', 'huh']
620
- })
621
- },
622
- forms: {
623
- Test: {
624
- default: {
625
- order: ['foo', 'bar', 'huh'],
626
- properties: {
627
- foo: {
628
- widget: 'singleLineText'
629
- },
630
- bar: {
631
- widget: 'singleLineText'
632
- },
633
- huh: {
634
- widget: 'singleLineText'
635
- }
636
- }
637
- }
638
- }
639
- }
640
- };
641
- const main = {
642
- ...emptySchema,
643
- shapes: {
644
- Test: createShape('Test', {
645
- type: 'object',
646
- properties: {
647
- foo: {
648
- type: 'string'
649
- },
650
- bar: {
651
- type: 'string'
652
- }
653
- },
654
- required: ['foo']
655
- })
656
- },
657
- forms: {
658
- Test: {
659
- default: {
660
- order: ['foo', 'bar'],
661
- properties: {
662
- foo: {
663
- widget: 'singleLineText'
664
- },
665
- bar: {
666
- widget: 'singleLineText'
667
- }
668
- }
669
- }
670
- }
671
- }
672
- };
673
- const branch = {
674
- ...emptySchema,
675
- shapes: {
676
- Test: createShape('Test', {
677
- type: 'object',
678
- properties: {
679
- foo: {
680
- type: 'string'
681
- },
682
- bar: {
683
- type: 'string'
684
- },
685
- huh: {
686
- type: 'string'
687
- },
688
- baz: {
689
- type: 'string'
690
- }
691
- },
692
- required: ['foo', 'huh']
693
- })
694
- },
695
- forms: {
696
- Test: {
697
- default: {
698
- order: ['foo', 'bar', 'huh', 'baz'],
699
- properties: {
700
- foo: {
701
- widget: 'singleLineText'
702
- },
703
- bar: {
704
- widget: 'singleLineText'
705
- },
706
- huh: {
707
- widget: 'singleLineText'
708
- },
709
- baz: {
710
- widget: 'singleLineText'
711
- }
712
- }
713
- }
714
- }
715
- }
716
- };
717
- const result = mergeProjectSchemas(main, parent, branch);
718
- expect(result.mergedSchema).toEqual({
719
- ...main,
720
- shapes: {
721
- Test: createShape('Test', {
722
- type: 'object',
723
- properties: {
724
- foo: {
725
- type: 'string'
726
- },
727
- bar: {
728
- type: 'string'
729
- },
730
- baz: {
731
- type: 'string'
732
- }
733
- },
734
- required: ['foo']
735
- })
736
- },
737
- forms: {
738
- Test: {
739
- default: {
740
- order: ['foo', 'bar', 'baz'],
741
- properties: {
742
- foo: {
743
- widget: 'singleLineText'
744
- },
745
- bar: {
746
- widget: 'singleLineText'
747
- },
748
- baz: {
749
- widget: 'singleLineText'
750
- }
751
- }
752
- }
753
- }
754
- }
755
- });
756
- });
757
- test('merge object properties in extends when both base/head update shape', () => {
758
- const main = {
759
- ...emptySchema,
760
- shapes: {
761
- Test: createShape('Test', {
762
- extends: [
763
- {
764
- type: 'object',
765
- properties: {
766
- foo: {
767
- type: 'string'
768
- },
769
- bar: {
770
- type: 'string'
771
- }
772
- },
773
- required: ['foo']
774
- }
775
- ]
776
- })
777
- }
778
- };
779
- const branch = {
780
- ...emptySchema,
781
- shapes: {
782
- Test: createShape('Test', {
783
- extends: [
784
- {
785
- type: 'object',
786
- properties: {
787
- foo: {
788
- type: 'string'
789
- },
790
- baz: {
791
- type: 'string'
792
- }
793
- },
794
- required: ['foo', 'baz']
795
- }
796
- ]
797
- })
798
- }
799
- };
800
- const result = mergeProjectSchemas(main, emptySchema, branch);
801
- expect(result.mergedSchema).toEqual({
802
- ...main,
803
- shapes: {
804
- Test: createShape('Test', {
805
- extends: [
806
- {
807
- type: 'object',
808
- properties: {
809
- foo: {
810
- type: 'string'
811
- },
812
- bar: {
813
- type: 'string'
814
- },
815
- baz: {
816
- type: 'string'
817
- }
818
- },
819
- required: ['foo', 'baz']
820
- }
821
- ]
822
- })
823
- }
824
- });
825
- });
826
- test('rebase object properties in extends when both base/head update shape', () => {
827
- const parent = {
828
- ...emptySchema,
829
- shapes: {
830
- Test: createShape('Test', {
831
- extends: [
832
- { '@ref': 'local:Parent' },
833
- {
834
- type: 'object',
835
- properties: {
836
- foo: {
837
- type: 'string'
838
- },
839
- bar: {
840
- type: 'string'
841
- },
842
- huh: {
843
- type: 'string'
844
- }
845
- },
846
- required: ['foo', 'huh']
847
- }
848
- ]
849
- })
850
- }
851
- };
852
- const main = {
853
- ...emptySchema,
854
- shapes: {
855
- Test: createShape('Test', {
856
- extends: [
857
- { '@ref': 'local:Parent' },
858
- {
859
- type: 'object',
860
- properties: {
861
- foo: {
862
- type: 'string'
863
- },
864
- bar: {
865
- type: 'string'
866
- }
867
- },
868
- required: ['foo']
869
- }
870
- ]
871
- })
872
- }
873
- };
874
- const branch = {
875
- ...emptySchema,
876
- shapes: {
877
- Test: createShape('Test', {
878
- extends: [
879
- { '@ref': 'local:Parent' },
880
- {
881
- type: 'object',
882
- properties: {
883
- foo: {
884
- type: 'string'
885
- },
886
- bar: {
887
- type: 'string'
888
- },
889
- huh: {
890
- type: 'string'
891
- },
892
- baz: {
893
- type: 'string'
894
- }
895
- },
896
- required: ['foo', 'huh']
897
- }
898
- ]
899
- })
900
- }
901
- };
902
- const result = mergeProjectSchemas(main, parent, branch);
903
- expect(result.mergedSchema).toEqual({
904
- ...main,
905
- shapes: {
906
- Test: createShape('Test', {
907
- extends: [
908
- { '@ref': 'local:Parent' },
909
- {
910
- type: 'object',
911
- properties: {
912
- foo: {
913
- type: 'string'
914
- },
915
- bar: {
916
- type: 'string'
917
- },
918
- baz: {
919
- type: 'string'
920
- }
921
- },
922
- required: ['foo']
923
- }
924
- ]
925
- })
926
- }
927
- });
928
- });
929
- test('Should be able to merge identical changes', () => {
930
- const parent = {
931
- ...emptySchema
932
- };
933
- const main = {
934
- ...parent,
935
- shapes: {
936
- Test: createShape('Test', {
937
- extends: [{ '@ref': 'local:Parent' }]
938
- })
939
- }
940
- };
941
- const branch = {
942
- ...parent,
943
- shapes: {
944
- Test: createShape('Test', {
945
- extends: [{ '@ref': 'local:Parent' }]
946
- })
947
- }
948
- };
949
- const result = mergeProjectSchemas(main, parent, branch);
950
- expect(result.mergedSchema).toEqual(branch);
951
- });
952
- test('errors when extends do not match in conflicting change', () => {
953
- const parent = {
954
- ...emptySchema,
955
- shapes: {
956
- Test: createShape('Test', {
957
- extends: [
958
- { '@ref': 'local:Parent' },
959
- {
960
- type: 'object',
961
- properties: {
962
- foo: {
963
- type: 'string'
964
- },
965
- bar: {
966
- type: 'string'
967
- },
968
- huh: {
969
- type: 'string'
970
- }
971
- },
972
- required: ['foo', 'huh']
973
- }
974
- ]
975
- })
976
- }
977
- };
978
- const main = {
979
- ...emptySchema,
980
- shapes: {
981
- Test: createShape('Test', {
982
- extends: [
983
- { '@ref': 'local:Parent' },
984
- {
985
- type: 'object',
986
- properties: {
987
- foo: {
988
- type: 'string'
989
- },
990
- bar: {
991
- type: 'string'
992
- }
993
- },
994
- required: ['foo']
995
- }
996
- ]
997
- })
998
- }
999
- };
1000
- const branch = {
1001
- ...emptySchema,
1002
- shapes: {
1003
- Test: createShape('Test', {
1004
- extends: [
1005
- { '@ref': 'local:OtherParent' },
1006
- {
1007
- type: 'object',
1008
- properties: {
1009
- foo: {
1010
- type: 'string'
1011
- },
1012
- bar: {
1013
- type: 'string'
1014
- },
1015
- huh: {
1016
- type: 'string'
1017
- },
1018
- baz: {
1019
- type: 'string'
1020
- }
1021
- },
1022
- required: ['foo', 'huh']
1023
- }
1024
- ]
1025
- })
1026
- }
1027
- };
1028
- const result = mergeProjectSchemas(main, parent, branch);
1029
- expect(result.error).toEqual('Unable to merge shapes.Test schemas conflict');
1030
- });
1031
- test('rebase shape level properties', () => {
1032
- const parent = unset('shapes.Homepage.model', addedShape);
1033
- const main = addedShape;
1034
- const branch = set('shapes.Homepage.schema.properties.new', { type: 'string' }, addedShape);
1035
- const result = mergeProjectSchemas(main, parent, branch);
1036
- expect(result.mergedSchema?.shapes.Homepage).toEqual({
1037
- id: '7fms3CQ6d',
1038
- model: {
1039
- type: 'single'
1040
- },
1041
- name: 'Homepage',
1042
- schema: {
1043
- properties: {
1044
- greeting: {
1045
- '@mapping': 'shapedb:Homepage.uq8t3G3O6',
1046
- title: 'Greeting',
1047
- type: 'string'
1048
- },
1049
- new: {
1050
- type: 'string'
1051
- }
1052
- },
1053
- type: 'object'
1054
- },
1055
- title: 'Homepage'
1056
- });
1057
- });
1058
- test('non-merged field changed in head', () => {
1059
- const changedLocales = { ...emptySchema, locales: ['en-us', 'es-es'] };
1060
- const { mergedSchema } = mergeProjectSchemas(emptySchema, emptySchema, changedLocales);
1061
- expect(mergedSchema).toEqual(changedLocales);
1062
- });
1063
- test('non-merged field changed in base', () => {
1064
- const changedLocales = { ...emptySchema, locales: ['en-us', 'es-es'] };
1065
- const { mergedSchema } = mergeProjectSchemas(changedLocales, emptySchema, emptySchema);
1066
- expect(mergedSchema).toEqual(changedLocales);
1067
- });
1068
- test('conflict in non-merged field takes value from head without merge', () => {
1069
- const changedLocales1 = { ...emptySchema, locales: ['en-us', 'es-es'] };
1070
- const changedLocales2 = { ...emptySchema, locales: ['en-us', 'de-de'] };
1071
- const { mergedSchema } = mergeProjectSchemas(changedLocales1, emptySchema, changedLocales2);
1072
- expect(mergedSchema).toEqual(changedLocales2);
1073
- });
1074
- });