@api-client/core 0.19.4 → 0.19.6

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@api-client/core",
3
3
  "description": "The API Client's core client library. Works in NodeJS and in a ES enabled browser.",
4
- "version": "0.19.4",
4
+ "version": "0.19.6",
5
5
  "license": "Apache-2.0",
6
6
  "exports": {
7
7
  "./browser.js": {
@@ -119,7 +119,7 @@ export class DataDomainDelta {
119
119
 
120
120
  if (delta.addedEntities) {
121
121
  for (const e of delta.addedEntities) {
122
- this.handleAddEntity(this.domain, e)
122
+ this.handleAddEntity(e)
123
123
  }
124
124
  }
125
125
 
@@ -150,6 +150,9 @@ export class DataDomainDelta {
150
150
  if (mod.name) entity.info.name = mod.name
151
151
  if (mod.displayName) entity.info.displayName = mod.displayName
152
152
  if (mod.description) entity.info.description = mod.description
153
+ if (mod.tags !== undefined) {
154
+ entity.tags = mod.tags === null ? [] : mod.tags
155
+ }
153
156
 
154
157
  this.applySemantics(entity, mod.addedSemantics, mod.modifiedSemantics, mod.deletedSemanticIds)
155
158
 
@@ -181,8 +184,8 @@ export class DataDomainDelta {
181
184
  * @param domain The data domain where the entity will reside.
182
185
  * @param e The schema definition of the entity to be added.
183
186
  */
184
- protected handleAddEntity(domain: DataDomain, e: AiDomainEntityResponseSchema): void {
185
- const targetModel = this.getModel(domain, e.modelKey || 'ai_generated')
187
+ protected handleAddEntity(e: AiDomainEntityResponseSchema): void {
188
+ const targetModel = this.getModel(this.domain, e.modelKey || 'ai_generated')
186
189
  const entityInput = { ...e }
187
190
  delete entityInput.semantics
188
191
  let entityKey = this.keyMap.get(e.key)
@@ -261,7 +264,7 @@ export class DataDomainDelta {
261
264
  writeOnly: p.constraints?.writeOnly,
262
265
  deprecated: p.deprecated,
263
266
  schema: p.schema,
264
- tags: p.tags,
267
+ tags: p.tags || undefined,
265
268
  })
266
269
  this.applySemantics(prop, p.semantics)
267
270
  }
@@ -273,7 +276,7 @@ export class DataDomainDelta {
273
276
  * @param domain The target data domain.
274
277
  * @param keys The array of property keys (AI-generated or actual) to remove.
275
278
  */
276
- handlePropertyDeletes(domain: DataDomain, keys?: string[]): void {
279
+ protected handlePropertyDeletes(domain: DataDomain, keys?: string[]): void {
277
280
  if (!keys) {
278
281
  return
279
282
  }
@@ -294,7 +297,7 @@ export class DataDomainDelta {
294
297
  * @param domain The target data domain.
295
298
  * @param mods The list of property modifications to apply.
296
299
  */
297
- handlePropertyMods(domain: DataDomain, mods?: AiDomainPropertyDelta[]): void {
300
+ protected handlePropertyMods(domain: DataDomain, mods?: AiDomainPropertyDelta[]): void {
298
301
  if (!mods) {
299
302
  return
300
303
  }
@@ -317,72 +320,76 @@ export class DataDomainDelta {
317
320
  prop.type = mod.type
318
321
  }
319
322
  if (mod.deprecated !== undefined) {
320
- prop.deprecated = mod.deprecated
323
+ prop.deprecated = mod.deprecated === null ? undefined : mod.deprecated
321
324
  }
322
325
  if (mod.constraints) {
323
326
  if (mod.constraints.required !== undefined) {
324
- prop.required = mod.constraints.required
327
+ prop.required = mod.constraints.required === null ? undefined : mod.constraints.required
325
328
  }
326
329
  if (mod.constraints.unique !== undefined) {
327
- prop.unique = mod.constraints.unique
330
+ prop.unique = mod.constraints.unique === null ? undefined : mod.constraints.unique
328
331
  }
329
332
  if (mod.constraints.index !== undefined) {
330
- prop.index = mod.constraints.index
333
+ prop.index = mod.constraints.index === null ? undefined : mod.constraints.index
331
334
  }
332
335
  if (mod.constraints.primary !== undefined) {
333
- prop.primary = mod.constraints.primary
336
+ prop.primary = mod.constraints.primary === null ? undefined : mod.constraints.primary
334
337
  }
335
338
  if (mod.constraints.multiple !== undefined) {
336
- prop.multiple = mod.constraints.multiple
339
+ prop.multiple = mod.constraints.multiple === null ? undefined : mod.constraints.multiple
337
340
  }
338
341
  if (mod.constraints.readOnly !== undefined) {
339
- prop.readOnly = mod.constraints.readOnly
342
+ prop.readOnly = mod.constraints.readOnly === null ? undefined : mod.constraints.readOnly
340
343
  }
341
344
  if (mod.constraints.writeOnly !== undefined) {
342
- prop.writeOnly = mod.constraints.writeOnly
345
+ prop.writeOnly = mod.constraints.writeOnly === null ? undefined : mod.constraints.writeOnly
343
346
  }
344
347
  }
345
348
  if (mod.schema) {
346
349
  if (!prop.schema) {
347
350
  prop.schema = {}
348
351
  }
349
- if (mod.schema.defaultValue) {
350
- if (!prop.schema.defaultValue) {
351
- prop.schema.defaultValue = {
352
- value: '',
353
- type: 'literal',
352
+ if (mod.schema.defaultValue !== undefined) {
353
+ if (mod.schema.defaultValue === null) {
354
+ prop.schema.defaultValue = undefined
355
+ } else {
356
+ if (!prop.schema.defaultValue) {
357
+ prop.schema.defaultValue = {
358
+ value: '',
359
+ type: 'literal',
360
+ }
361
+ }
362
+ if (mod.schema.defaultValue.type) {
363
+ prop.schema.defaultValue.type = mod.schema.defaultValue.type
364
+ }
365
+ if (mod.schema.defaultValue.value) {
366
+ prop.schema.defaultValue.value = mod.schema.defaultValue.value
354
367
  }
355
- }
356
- if (mod.schema.defaultValue.type) {
357
- prop.schema.defaultValue.type = mod.schema.defaultValue.type
358
- }
359
- if (mod.schema.defaultValue.value) {
360
- prop.schema.defaultValue.value = mod.schema.defaultValue.value
361
368
  }
362
369
  }
363
370
  if (mod.schema.pattern !== undefined) {
364
- prop.schema.pattern = mod.schema.pattern
371
+ prop.schema.pattern = mod.schema.pattern === null ? undefined : mod.schema.pattern
365
372
  }
366
373
  if (mod.schema.minimum !== undefined) {
367
- prop.schema.minimum = mod.schema.minimum
374
+ prop.schema.minimum = mod.schema.minimum === null ? undefined : mod.schema.minimum
368
375
  }
369
376
  if (mod.schema.maximum !== undefined) {
370
- prop.schema.maximum = mod.schema.maximum
377
+ prop.schema.maximum = mod.schema.maximum === null ? undefined : mod.schema.maximum
371
378
  }
372
379
  if (mod.schema.exclusiveMinimum !== undefined) {
373
- prop.schema.exclusiveMinimum = mod.schema.exclusiveMinimum
380
+ prop.schema.exclusiveMinimum = mod.schema.exclusiveMinimum === null ? undefined : mod.schema.exclusiveMinimum
374
381
  }
375
382
  if (mod.schema.exclusiveMaximum !== undefined) {
376
- prop.schema.exclusiveMaximum = mod.schema.exclusiveMaximum
383
+ prop.schema.exclusiveMaximum = mod.schema.exclusiveMaximum === null ? undefined : mod.schema.exclusiveMaximum
377
384
  }
378
385
  if (mod.schema.multipleOf !== undefined) {
379
- prop.schema.multipleOf = mod.schema.multipleOf
386
+ prop.schema.multipleOf = mod.schema.multipleOf === null ? undefined : mod.schema.multipleOf
380
387
  }
381
388
  if (mod.schema.enum !== undefined) {
382
- prop.schema.enum = [...mod.schema.enum]
389
+ prop.schema.enum = mod.schema.enum === null ? undefined : [...mod.schema.enum]
383
390
  }
384
391
  if (mod.schema.examples !== undefined) {
385
- prop.schema.examples = [...mod.schema.examples]
392
+ prop.schema.examples = mod.schema.examples === null ? undefined : [...mod.schema.examples]
386
393
  }
387
394
  }
388
395
  this.applySemantics(prop, mod.addedSemantics, mod.modifiedSemantics, mod.deletedSemanticIds)
@@ -395,7 +402,7 @@ export class DataDomainDelta {
395
402
  * @param entity The target domain entity referencing the newly created associations.
396
403
  * @param adds An array of association definitions to add, if any.
397
404
  */
398
- handleAssociationAdds(entity: DomainEntity, adds: AiDomainAssociation[] | undefined): void {
405
+ protected handleAssociationAdds(entity: DomainEntity, adds: AiDomainAssociation[] | undefined): void {
399
406
  if (!adds) {
400
407
  return
401
408
  }
@@ -412,7 +419,7 @@ export class DataDomainDelta {
412
419
  * @param entity The source domain entity creating the association.
413
420
  * @param a The defining schema for the new association.
414
421
  */
415
- handleAddAssociation(entity: DomainEntity, a: AiDomainAssociation): void {
422
+ protected handleAddAssociation(entity: DomainEntity, a: AiDomainAssociation): void {
416
423
  let assocKey = this.keyMap.get(a.key)
417
424
  if (!assocKey) {
418
425
  assocKey = nanoid()
@@ -467,7 +474,7 @@ export class DataDomainDelta {
467
474
  * @param domain The target data domain.
468
475
  * @param keys An array of association keys to safely remove.
469
476
  */
470
- handleAssociationDeletes(domain: DataDomain, keys?: string[]): void {
477
+ protected handleAssociationDeletes(domain: DataDomain, keys?: string[]): void {
471
478
  if (!keys) {
472
479
  return
473
480
  }
@@ -488,7 +495,7 @@ export class DataDomainDelta {
488
495
  * @param domain The target data domain containing the associations.
489
496
  * @param mods An array of requested association modifications.
490
497
  */
491
- handleAssociationMods(domain: DataDomain, mods: AiDomainAssociationDelta[] | undefined): void {
498
+ protected handleAssociationMods(domain: DataDomain, mods: AiDomainAssociationDelta[] | undefined): void {
492
499
  if (!mods) {
493
500
  return
494
501
  }
@@ -508,10 +515,13 @@ export class DataDomainDelta {
508
515
  assoc.info.description = mod.description
509
516
  }
510
517
  if (mod.required !== undefined) {
511
- assoc.required = mod.required
518
+ assoc.required = mod.required === null ? undefined : mod.required
519
+ }
520
+ if (mod.multiple !== undefined) {
521
+ assoc.multiple = mod.multiple === null ? undefined : mod.multiple
512
522
  }
513
523
  if (mod.onDelete !== undefined) {
514
- assoc.onDelete = mod.onDelete
524
+ assoc.onDelete = mod.onDelete === null ? undefined : mod.onDelete
515
525
  }
516
526
 
517
527
  if (mod.targets) {
@@ -9,6 +9,18 @@ const SemanticSchema = {
9
9
  required: ['id'],
10
10
  }
11
11
 
12
+ const AssociationTarget = {
13
+ type: Type.OBJECT,
14
+ properties: {
15
+ key: { type: Type.STRING, description: 'The key of the target entity.' },
16
+ domain: {
17
+ type: Type.STRING,
18
+ description: 'The key of the target data domain. Only set when the target is in a different data domain.',
19
+ },
20
+ },
21
+ required: ['key'],
22
+ }
23
+
12
24
  const SchemaDefaultValue = {
13
25
  type: Type.OBJECT,
14
26
  properties: {
@@ -27,28 +39,28 @@ const SchemaDefaultValue = {
27
39
  const PropertySchemaShape = {
28
40
  type: Type.OBJECT,
29
41
  properties: {
30
- minimum: { type: Type.NUMBER },
31
- maximum: { type: Type.NUMBER },
32
- exclusiveMinimum: { type: Type.BOOLEAN },
33
- exclusiveMaximum: { type: Type.BOOLEAN },
34
- multipleOf: { type: Type.NUMBER },
35
- enum: { type: Type.ARRAY, items: { type: Type.STRING } },
36
- examples: { type: Type.ARRAY, items: { type: Type.STRING } },
37
- defaultValue: SchemaDefaultValue,
38
- pattern: { type: Type.STRING },
42
+ minimum: { type: Type.NUMBER, nullable: true },
43
+ maximum: { type: Type.NUMBER, nullable: true },
44
+ exclusiveMinimum: { type: Type.BOOLEAN, nullable: true },
45
+ exclusiveMaximum: { type: Type.BOOLEAN, nullable: true },
46
+ multipleOf: { type: Type.NUMBER, nullable: true },
47
+ enum: { type: Type.ARRAY, items: { type: Type.STRING }, nullable: true },
48
+ examples: { type: Type.ARRAY, items: { type: Type.STRING }, nullable: true },
49
+ defaultValue: { ...SchemaDefaultValue, nullable: true },
50
+ pattern: { type: Type.STRING, nullable: true },
39
51
  },
40
52
  }
41
53
 
42
54
  const PropertyConstraintsSchema = {
43
55
  type: Type.OBJECT,
44
56
  properties: {
45
- required: { type: Type.BOOLEAN },
46
- unique: { type: Type.BOOLEAN },
47
- index: { type: Type.BOOLEAN },
48
- primary: { type: Type.BOOLEAN },
49
- multiple: { type: Type.BOOLEAN },
50
- readOnly: { type: Type.BOOLEAN },
51
- writeOnly: { type: Type.BOOLEAN },
57
+ required: { type: Type.BOOLEAN, nullable: true },
58
+ unique: { type: Type.BOOLEAN, nullable: true },
59
+ index: { type: Type.BOOLEAN, nullable: true },
60
+ primary: { type: Type.BOOLEAN, nullable: true },
61
+ multiple: { type: Type.BOOLEAN, nullable: true },
62
+ readOnly: { type: Type.BOOLEAN, nullable: true },
63
+ writeOnly: { type: Type.BOOLEAN, nullable: true },
52
64
  },
53
65
  }
54
66
 
@@ -74,7 +86,7 @@ const PropertySchema = {
74
86
  items: SemanticSchema,
75
87
  description: "List of semantics applied to this property. Note: ONLY use semantics with scope='property'.",
76
88
  },
77
- tags: { type: Type.ARRAY, items: { type: Type.STRING } },
89
+ tags: { type: Type.ARRAY, items: { type: Type.STRING }, nullable: true },
78
90
  },
79
91
  required: ['key', 'name', 'type', 'displayName', 'description'],
80
92
  }
@@ -97,7 +109,7 @@ const AssociationSchema = {
97
109
  name: { type: Type.STRING },
98
110
  displayName: { type: Type.STRING },
99
111
  description: { type: Type.STRING },
100
- targets: { type: Type.ARRAY, items: { type: Type.STRING }, description: 'List of target entity keys' },
112
+ targets: { type: Type.ARRAY, items: AssociationTarget },
101
113
  required: { type: Type.BOOLEAN },
102
114
  multiple: {
103
115
  type: Type.BOOLEAN,
@@ -150,6 +162,9 @@ const EntitySchema = {
150
162
  required: ['key', 'name', 'modelKey', 'displayName', 'description'],
151
163
  }
152
164
 
165
+ /**
166
+ * Allows modifying a property (not adding)
167
+ */
153
168
  const PropertyDeltaSchema = {
154
169
  type: Type.OBJECT,
155
170
  properties: {
@@ -161,9 +176,9 @@ const PropertyDeltaSchema = {
161
176
  type: Type.STRING,
162
177
  description: 'Enum: string, number, boolean, date, datetime, time, binary',
163
178
  },
164
- constraints: PropertyConstraintsSchema,
165
- deprecated: { type: Type.BOOLEAN },
166
- schema: PropertySchemaShape,
179
+ constraints: { ...PropertyConstraintsSchema, nullable: true },
180
+ deprecated: { type: Type.BOOLEAN, nullable: true },
181
+ schema: { ...PropertySchemaShape, nullable: true },
167
182
  addedSemantics: {
168
183
  type: Type.ARRAY,
169
184
  items: SemanticSchema,
@@ -182,13 +197,14 @@ const AssociationDeltaSchema = {
182
197
  name: { type: Type.STRING },
183
198
  displayName: { type: Type.STRING },
184
199
  description: { type: Type.STRING },
185
- targets: { type: Type.ARRAY, items: { type: Type.STRING } },
186
- required: { type: Type.BOOLEAN },
200
+ targets: { type: Type.ARRAY, items: AssociationTarget },
201
+ required: { type: Type.BOOLEAN, nullable: true },
187
202
  multiple: {
188
203
  type: Type.BOOLEAN,
204
+ nullable: true,
189
205
  description: 'Whether the association can have multiple targets (like User has multiple addresses)',
190
206
  },
191
- onDelete: { type: Type.STRING, description: 'Enum: restrict, cascade, setNull, doNothing' },
207
+ onDelete: { type: Type.STRING, nullable: true, description: 'Enum: restrict, cascade, setNull, doNothing' },
192
208
  addedSemantics: {
193
209
  type: Type.ARRAY,
194
210
  items: SemanticSchema,
@@ -256,7 +272,7 @@ export const DOMAIN_SCHEMA = {
256
272
  name: { type: Type.STRING },
257
273
  displayName: { type: Type.STRING },
258
274
  description: { type: Type.STRING },
259
- tags: { type: Type.ARRAY, items: { type: Type.STRING } },
275
+ tags: { type: Type.ARRAY, items: { type: Type.STRING }, nullable: true },
260
276
  addedSemantics: {
261
277
  type: Type.ARRAY,
262
278
  items: SemanticSchema,
@@ -19,13 +19,12 @@ The \`reasoning\` string in your JSON output is the presentation layer. It will
19
19
  - **Keep it Conversational:** Use simple markdown (like bullet points) to provide a friendly, easily scannable summary of what you built for them.
20
20
  - **Proactive Next Steps:** Always conclude your summary with a single, highly relevant question asking the user what they want to do next. Base this on what you just built or what might be missing.
21
21
 
22
- # REFERENTIAL INTEGRITY (NO PHANTOM KEYS)
23
- You must absolutely guarantee that every key listed in an association's \`targets\` array actually exists.
24
- - **The Target Rule:** A target key is ONLY valid if it meets one of two conditions:
25
- 1. It is the exact \`key\` of an entity you are actively creating in the \`addedEntities\` array in this exact response.
26
- 2. It is the exact \`key\` of an entity explicitly provided to you in the Current Domain context.
27
- - **ANTI-PATTERN:** Inventing a logical target key (e.g., \`resource_entity\`, \`user_id\`) that does not exist in the context or your current payload.
28
- - **Missing Targets:** If the user asks you to link to an entity that does not exist, you MUST create that missing entity in \`addedEntities\` first so you have a valid key to target.
22
+ # REFERENTIAL INTEGRITY (STRICT KEYS ONLY)
23
+ You must absolutely guarantee that you never hallucinate or invent a \`key\` for an existing object.
24
+ - **Modifications & Deletions:** When adding objects to \`modifiedModels\`, \`modifiedEntities\`, \`deletedModelKeys\`, or \`deletedEntityKeys\`, the \`key\` you use MUST be an exact match to an existing \`nanoid\` key provided to you in the Current Domain Context.
25
+ - **Association Targets:** A target key in an association is ONLY valid if it exists in the Current Domain Context, or if you are actively creating it in \`addedEntities\`.
26
+ - **ANTI-PATTERN:** Inventing a placeholder key to modify an object that you don't know the exact nanoid for.
27
+ - **Handling Missing Objects:** If the user asks you to modify an entity but it does not exist in the provided context, you MUST assume it is a brand new entity. Define its complete schema inside \`addedEntities\` instead of trying to modify a phantom key.
29
28
 
30
29
  # CREATION & DEPENDENCY LOGIC (THE TWO-PASS RULE)
31
30
  When creating multiple new entities that relate to one another, you must respect referential integrity. You cannot reference an entity in an association before it exists.
@@ -76,4 +75,10 @@ You are an enterprise Data Architect. You must actively defend against malicious
76
75
  - **Conciseness:** If an operation requires more than 10 properties, suggest splitting the task into two parts rather than outputting one massive JSON array.
77
76
  - **No Encoding:** Never attempt to output Base64, Hex, or encoded strings unless explicitly requested for a \`binary\` type.
78
77
  - **Loop Prevention:** If you find yourself repeating the same key or value more than 5 times in a single array, stop and ask the user for clarification.
78
+
79
+ # PARTIAL UPDATES & DELETIONS
80
+ When modifying existing objects in the \`modifiedEntities\` or \`modifiedModels\` arrays, use strict partial-update logic:
81
+ - **To update a value:** Provide the key and the new value.
82
+ - **To leave a value unchanged:** Completely omit the key from the JSON object. Do not output it.
83
+ - **To delete an existing value:** You MUST explicitly output the key with a value of \`null\` (e.g., \`"description": null\`).
79
84
  `
@@ -132,7 +132,7 @@ export interface AiDomainProperty {
132
132
  deprecated?: boolean
133
133
  schema?: PropertySchema
134
134
  semantics?: AiDomainSemantic[]
135
- tags?: string[]
135
+ tags?: string[] | null
136
136
  }
137
137
 
138
138
  /**
@@ -226,7 +226,7 @@ export interface AiDomainEntityDelta {
226
226
  name?: string
227
227
  displayName?: string
228
228
  description?: string
229
- tags?: string[]
229
+ tags?: string[] | null
230
230
  // Entity semantics delta
231
231
  addedSemantics?: AiDomainSemantic[]
232
232
  modifiedSemantics?: AiDomainSemantic[]
@@ -240,6 +240,10 @@ export interface AiDomainEntityDelta {
240
240
  deletedAssociationKeys?: string[]
241
241
  }
242
242
 
243
+ export type NullablePropertySchema = {
244
+ [K in keyof PropertySchema]?: PropertySchema[K] | null
245
+ }
246
+
243
247
  /**
244
248
  * Represents a targeted modification to an existing property generated by the AI.
245
249
  * It captures changes to superficial properties (name, description), type changes,
@@ -252,20 +256,20 @@ export interface AiDomainPropertyDelta {
252
256
  description?: string
253
257
  type?: DomainPropertyType
254
258
  constraints?: {
255
- required?: boolean
256
- unique?: boolean
257
- index?: boolean
258
- primary?: boolean
259
- multiple?: boolean
260
- readOnly?: boolean
261
- writeOnly?: boolean
262
- }
263
- deprecated?: boolean
259
+ required?: boolean | null
260
+ unique?: boolean | null
261
+ index?: boolean | null
262
+ primary?: boolean | null
263
+ multiple?: boolean | null
264
+ readOnly?: boolean | null
265
+ writeOnly?: boolean | null
266
+ } | null
267
+ deprecated?: boolean | null
264
268
  // Property semantics delta
265
269
  addedSemantics?: AiDomainSemantic[]
266
270
  modifiedSemantics?: AiDomainSemantic[]
267
271
  deletedSemanticIds?: SemanticType[]
268
- schema?: PropertySchema
272
+ schema?: NullablePropertySchema
269
273
  }
270
274
 
271
275
  /**
@@ -279,8 +283,9 @@ export interface AiDomainAssociationDelta {
279
283
  displayName?: string
280
284
  description?: string
281
285
  targets?: AssociationTarget[]
282
- required?: boolean
283
- onDelete?: OnDeleteRule
286
+ required?: boolean | null
287
+ multiple?: boolean | null
288
+ onDelete?: OnDeleteRule | null
284
289
  // Association semantics delta
285
290
  addedSemantics?: AiDomainSemantic[]
286
291
  modifiedSemantics?: AiDomainSemantic[]
@@ -189,6 +189,116 @@ test.group('DataDomainDelta.apply()', () => {
189
189
  assert.equal(prop2!.info.name, 'New Prop')
190
190
  })
191
191
 
192
+ test('unsets properties, constraints, schema, and association options using null values', ({ assert }) => {
193
+ const domain = new DataDomain()
194
+ const model = domain.addModel()
195
+ const entity = domain.addEntity(model.key, { info: { name: 'unset-entity' }, tags: ['tag1'] })
196
+
197
+ entity.addProperty({
198
+ key: 'prop1',
199
+ type: 'string',
200
+ deprecated: true,
201
+ required: true,
202
+ unique: true,
203
+ index: true,
204
+ primary: true,
205
+ multiple: true,
206
+ readOnly: true,
207
+ writeOnly: true,
208
+ schema: {
209
+ defaultValue: { type: 'literal', value: 'foo' },
210
+ pattern: '^[a-z]+$',
211
+ minimum: 1,
212
+ maximum: 10,
213
+ exclusiveMinimum: true,
214
+ exclusiveMaximum: true,
215
+ multipleOf: 2,
216
+ enum: ['foo', 'bar'],
217
+ examples: ['foo'],
218
+ },
219
+ })
220
+
221
+ entity.addAssociation({
222
+ key: 'assoc1',
223
+ required: true,
224
+ multiple: true,
225
+ onDelete: 'cascade',
226
+ })
227
+
228
+ const delta = {
229
+ modifiedEntities: [
230
+ {
231
+ key: entity.key,
232
+ tags: null,
233
+ modifiedProperties: [
234
+ {
235
+ key: 'prop1',
236
+ deprecated: null,
237
+ constraints: {
238
+ required: null,
239
+ unique: null,
240
+ index: null,
241
+ primary: null,
242
+ multiple: null,
243
+ readOnly: null,
244
+ writeOnly: null,
245
+ },
246
+ schema: {
247
+ defaultValue: null,
248
+ pattern: null,
249
+ minimum: null,
250
+ maximum: null,
251
+ exclusiveMinimum: null,
252
+ exclusiveMaximum: null,
253
+ multipleOf: null,
254
+ enum: null,
255
+ examples: null,
256
+ },
257
+ },
258
+ ],
259
+ modifiedAssociations: [
260
+ {
261
+ key: 'assoc1',
262
+ required: null,
263
+ multiple: null,
264
+ onDelete: null,
265
+ },
266
+ ],
267
+ },
268
+ ],
269
+ }
270
+
271
+ const instance = new DataDomainDelta(domain)
272
+ instance.apply(delta)
273
+
274
+ assert.lengthOf(entity.tags, 0)
275
+
276
+ const prop1 = domain.findProperty('prop1')!
277
+ assert.isUndefined(prop1.deprecated)
278
+ assert.isUndefined(prop1.required)
279
+ assert.isUndefined(prop1.unique)
280
+ assert.isUndefined(prop1.index)
281
+ assert.isUndefined(prop1.primary)
282
+ assert.isUndefined(prop1.multiple)
283
+ assert.isUndefined(prop1.readOnly)
284
+ assert.isUndefined(prop1.writeOnly)
285
+
286
+ assert.isUndefined(prop1.schema?.defaultValue)
287
+ assert.isUndefined(prop1.schema?.pattern)
288
+ assert.isUndefined(prop1.schema?.minimum)
289
+ assert.isUndefined(prop1.schema?.maximum)
290
+ assert.isUndefined(prop1.schema?.exclusiveMinimum)
291
+ assert.isUndefined(prop1.schema?.exclusiveMaximum)
292
+ assert.isUndefined(prop1.schema?.multipleOf)
293
+ assert.isUndefined(prop1.schema?.enum)
294
+ assert.isUndefined(prop1.schema?.examples)
295
+
296
+ const assoc1 = domain.findAssociation('assoc1')!
297
+ assert.isUndefined(assoc1.required)
298
+ assert.isUndefined(assoc1.multiple)
299
+ assert.isUndefined(assoc1.onDelete)
300
+ })
301
+
192
302
  test('deletes entity properties', ({ assert }) => {
193
303
  const domain = new DataDomain()
194
304
  const model = domain.addModel()