@api-client/core 0.18.16 → 0.18.18

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 (56) hide show
  1. package/build/src/{modeling → decorators}/observed.d.ts +3 -3
  2. package/build/src/decorators/observed.d.ts.map +1 -0
  3. package/build/src/{modeling → decorators}/observed.js +4 -4
  4. package/build/src/decorators/observed.js.map +1 -0
  5. package/build/src/modeling/ApiModel.js +1 -1
  6. package/build/src/modeling/ApiModel.js.map +1 -1
  7. package/build/src/modeling/DataDomain.d.ts +7 -2
  8. package/build/src/modeling/DataDomain.d.ts.map +1 -1
  9. package/build/src/modeling/DataDomain.js +15 -2
  10. package/build/src/modeling/DataDomain.js.map +1 -1
  11. package/build/src/modeling/DomainAssociation.d.ts +7 -0
  12. package/build/src/modeling/DomainAssociation.d.ts.map +1 -1
  13. package/build/src/modeling/DomainAssociation.js +44 -1
  14. package/build/src/modeling/DomainAssociation.js.map +1 -1
  15. package/build/src/modeling/DomainEntity.d.ts +6 -0
  16. package/build/src/modeling/DomainEntity.d.ts.map +1 -1
  17. package/build/src/modeling/DomainEntity.js +21 -1
  18. package/build/src/modeling/DomainEntity.js.map +1 -1
  19. package/build/src/modeling/DomainModel.js +1 -1
  20. package/build/src/modeling/DomainModel.js.map +1 -1
  21. package/build/src/modeling/DomainNamespace.js +1 -1
  22. package/build/src/modeling/DomainNamespace.js.map +1 -1
  23. package/build/src/modeling/DomainProperty.d.ts +5 -0
  24. package/build/src/modeling/DomainProperty.d.ts.map +1 -1
  25. package/build/src/modeling/DomainProperty.js +38 -1
  26. package/build/src/modeling/DomainProperty.js.map +1 -1
  27. package/build/src/modeling/DomainSerialization.d.ts +6 -3
  28. package/build/src/modeling/DomainSerialization.d.ts.map +1 -1
  29. package/build/src/modeling/DomainSerialization.js +374 -52
  30. package/build/src/modeling/DomainSerialization.js.map +1 -1
  31. package/build/src/modeling/types.d.ts +69 -2
  32. package/build/src/modeling/types.d.ts.map +1 -1
  33. package/build/src/modeling/types.js.map +1 -1
  34. package/build/src/models/Thing.js +1 -1
  35. package/build/src/models/Thing.js.map +1 -1
  36. package/build/tsconfig.tsbuildinfo +1 -1
  37. package/data/models/example-generator-api.json +10 -10
  38. package/package.json +2 -1
  39. package/src/{modeling → decorators}/observed.ts +5 -5
  40. package/src/modeling/ApiModel.ts +1 -1
  41. package/src/modeling/DataDomain.ts +24 -3
  42. package/src/modeling/DomainAssociation.ts +51 -1
  43. package/src/modeling/DomainEntity.ts +24 -1
  44. package/src/modeling/DomainModel.ts +1 -1
  45. package/src/modeling/DomainNamespace.ts +1 -1
  46. package/src/modeling/DomainProperty.ts +43 -1
  47. package/src/modeling/DomainSerialization.ts +440 -56
  48. package/src/modeling/types.ts +73 -2
  49. package/src/models/Thing.ts +1 -1
  50. package/tests/unit/decorators/observed.spec.ts +527 -0
  51. package/tests/unit/modeling/data_domain_serialization.spec.ts +508 -0
  52. package/tests/unit/modeling/domain_asociation.spec.ts +376 -0
  53. package/tests/unit/modeling/domain_entity.spec.ts +147 -0
  54. package/tests/unit/modeling/domain_property.spec.ts +273 -0
  55. package/build/src/modeling/observed.d.ts.map +0 -1
  56. package/build/src/modeling/observed.js.map +0 -1
@@ -1377,3 +1377,276 @@ test.group('DomainProperty.toExample()', () => {
1377
1377
  assert.match(result as string, emailRegex)
1378
1378
  })
1379
1379
  })
1380
+
1381
+ test.group('DomainProperty.duplicate()', () => {
1382
+ test('duplicates a property successfully', ({ assert }) => {
1383
+ const dataDomain = new DataDomain()
1384
+ const model = dataDomain.addModel()
1385
+ const entity = model.addEntity()
1386
+ const property = entity.addProperty({
1387
+ info: { name: 'originalProperty' },
1388
+ type: 'string',
1389
+ required: true,
1390
+ multiple: false,
1391
+ })
1392
+
1393
+ const duplicate = property.duplicate()
1394
+
1395
+ assert.isDefined(duplicate)
1396
+ assert.notEqual(duplicate.key, property.key)
1397
+ assert.equal(duplicate.info.name, 'originalProperty_copy')
1398
+ assert.equal(duplicate.type, 'string')
1399
+ assert.equal(duplicate.required, true)
1400
+ assert.equal(duplicate.multiple, false)
1401
+ })
1402
+
1403
+ test('places duplicate right after original property in fields list', ({ assert }) => {
1404
+ const dataDomain = new DataDomain()
1405
+ const model = dataDomain.addModel()
1406
+ const entity = model.addEntity()
1407
+
1408
+ // Add multiple properties to test ordering
1409
+ const property1 = entity.addProperty({ info: { name: 'first' } })
1410
+ const property2 = entity.addProperty({ info: { name: 'second' } })
1411
+ const property3 = entity.addProperty({ info: { name: 'third' } })
1412
+
1413
+ const duplicate = property2.duplicate()
1414
+
1415
+ // Check that duplicate is placed right after property2
1416
+ const fieldKeys = entity.fields.map((f) => f.key)
1417
+ const property2Index = fieldKeys.indexOf(property2.key)
1418
+ const duplicateIndex = fieldKeys.indexOf(duplicate.key)
1419
+
1420
+ assert.equal(duplicateIndex, property2Index + 1)
1421
+ assert.deepEqual(fieldKeys, [property1.key, property2.key, duplicate.key, property3.key])
1422
+ })
1423
+
1424
+ test('generates unique name when base name conflicts', ({ assert }) => {
1425
+ const dataDomain = new DataDomain()
1426
+ const model = dataDomain.addModel()
1427
+ const entity = model.addEntity()
1428
+
1429
+ const property = entity.addProperty({ info: { name: 'test' } })
1430
+ // Add a property that conflicts with the first generated name
1431
+ entity.addProperty({ info: { name: 'test_copy' } })
1432
+
1433
+ const duplicate = property.duplicate()
1434
+
1435
+ assert.equal(duplicate.info.name, 'test_copy_2')
1436
+ })
1437
+
1438
+ test('uses fallback name when original property has no name', ({ assert }) => {
1439
+ const dataDomain = new DataDomain()
1440
+ const model = dataDomain.addModel()
1441
+ const entity = model.addEntity()
1442
+
1443
+ const property = entity.addProperty({ info: {} }) // No name
1444
+
1445
+ // The property gets the default name "new_property" from schema creation
1446
+ assert.equal(property.info.name, 'new_property')
1447
+
1448
+ const duplicate = property.duplicate()
1449
+
1450
+ assert.equal(duplicate.info.name, 'new_property_copy')
1451
+ })
1452
+
1453
+ test('uses field fallback when property name is explicitly undefined', ({ assert }) => {
1454
+ const dataDomain = new DataDomain()
1455
+ const model = dataDomain.addModel()
1456
+ const entity = model.addEntity()
1457
+
1458
+ const property = entity.addProperty({ info: { name: 'test' } })
1459
+ // Manually set name to undefined to test the fallback logic
1460
+ property.info.name = undefined
1461
+
1462
+ const duplicate = property.duplicate()
1463
+
1464
+ assert.equal(duplicate.info.name, 'field_copy')
1465
+ })
1466
+
1467
+ test('does not copy key property', ({ assert }) => {
1468
+ const dataDomain = new DataDomain()
1469
+ const model = dataDomain.addModel()
1470
+ const entity = model.addEntity()
1471
+
1472
+ const property = entity.addProperty({
1473
+ key: 'custom-key',
1474
+ info: { name: 'testProperty' },
1475
+ })
1476
+
1477
+ const duplicate = property.duplicate()
1478
+
1479
+ assert.notEqual(duplicate.key, property.key)
1480
+ assert.notEqual(duplicate.key, 'custom-key')
1481
+ })
1482
+
1483
+ test('does not copy primary key flag', ({ assert }) => {
1484
+ const dataDomain = new DataDomain()
1485
+ const model = dataDomain.addModel()
1486
+ const entity = model.addEntity()
1487
+
1488
+ const property = entity.addProperty({
1489
+ info: { name: 'id' },
1490
+ primary: true,
1491
+ })
1492
+
1493
+ const duplicate = property.duplicate()
1494
+
1495
+ assert.isTrue(property.primary)
1496
+ assert.isUndefined(duplicate.primary)
1497
+ })
1498
+
1499
+ test('copies all other property attributes', ({ assert }) => {
1500
+ const dataDomain = new DataDomain()
1501
+ const model = dataDomain.addModel()
1502
+ const entity = model.addEntity()
1503
+
1504
+ const property = entity.addProperty({
1505
+ info: { name: 'complexProperty', description: 'A complex property' },
1506
+ type: 'number',
1507
+ required: true,
1508
+ multiple: true,
1509
+ index: true,
1510
+ readOnly: true,
1511
+ writeOnly: false,
1512
+ deprecated: true,
1513
+ tags: ['tag1', 'tag2'],
1514
+ semantics: [{ id: SemanticType.CreatedTimestamp }],
1515
+ schema: { minimum: 0, maximum: 100 },
1516
+ bindings: [{ type: 'web', schema: { format: 'float' } }],
1517
+ })
1518
+
1519
+ const duplicate = property.duplicate()
1520
+
1521
+ assert.equal(duplicate.info.name, 'complexProperty_copy')
1522
+ assert.equal(duplicate.info.description, 'A complex property')
1523
+ assert.equal(duplicate.type, 'number')
1524
+ assert.equal(duplicate.required, true)
1525
+ assert.equal(duplicate.multiple, true)
1526
+ assert.equal(duplicate.index, true)
1527
+ assert.equal(duplicate.readOnly, true)
1528
+ assert.equal(duplicate.writeOnly, false)
1529
+ assert.equal(duplicate.deprecated, true)
1530
+ assert.deepEqual(duplicate.tags, ['tag1', 'tag2'])
1531
+ assert.deepEqual(duplicate.semantics, [{ id: SemanticType.CreatedTimestamp }])
1532
+ assert.deepEqual(duplicate.schema, { minimum: 0, maximum: 100 })
1533
+ assert.deepEqual(duplicate.bindings, [{ type: 'web', schema: { format: 'float' } }])
1534
+ })
1535
+
1536
+ test('creates independent copy of schema and bindings', ({ assert }) => {
1537
+ const dataDomain = new DataDomain()
1538
+ const model = dataDomain.addModel()
1539
+ const entity = model.addEntity()
1540
+
1541
+ const property = entity.addProperty({
1542
+ info: { name: 'original' },
1543
+ schema: { minimum: 0 },
1544
+ bindings: [{ type: 'web', schema: { format: 'float' } }],
1545
+ })
1546
+
1547
+ const duplicate = property.duplicate()
1548
+
1549
+ // Modify original schema and bindings
1550
+ property.schema!.minimum = 10
1551
+ property.bindings[0].schema = { format: 'double' }
1552
+
1553
+ // Duplicate should be unaffected
1554
+ assert.equal(duplicate.schema!.minimum, 0)
1555
+ assert.deepEqual(duplicate.bindings[0].schema, { format: 'float' })
1556
+ })
1557
+
1558
+ test('notifies domain of changes', ({ assert }) => {
1559
+ const dataDomain = new DataDomain()
1560
+ const model = dataDomain.addModel()
1561
+ const entity = model.addEntity()
1562
+ const property = entity.addProperty({ info: { name: 'test' } })
1563
+
1564
+ let notificationCalled = false
1565
+ const originalNotify = dataDomain.notifyChange
1566
+ dataDomain.notifyChange = () => {
1567
+ notificationCalled = true
1568
+ originalNotify.call(dataDomain)
1569
+ }
1570
+
1571
+ property.duplicate()
1572
+
1573
+ assert.isTrue(notificationCalled)
1574
+
1575
+ // Restore original method
1576
+ dataDomain.notifyChange = originalNotify
1577
+ })
1578
+
1579
+ test('throws error when property has no parent entity', ({ assert }) => {
1580
+ const dataDomain = new DataDomain()
1581
+ const property = new DomainProperty(dataDomain, 'non-existent-parent', {
1582
+ info: { name: 'orphan' },
1583
+ })
1584
+
1585
+ assert.throws(() => {
1586
+ property.duplicate()
1587
+ }, 'Cannot duplicate property')
1588
+ })
1589
+
1590
+ test('throws error when property is not in parent entity fields list', ({ assert }) => {
1591
+ const dataDomain = new DataDomain()
1592
+ const model = dataDomain.addModel()
1593
+ const entity = model.addEntity()
1594
+ const property = new DomainProperty(dataDomain, entity.key, {
1595
+ info: { name: 'detached' },
1596
+ })
1597
+
1598
+ // Add property to graph but not to entity fields
1599
+ dataDomain.graph.setNode(property.key, property)
1600
+
1601
+ assert.throws(() => {
1602
+ property.duplicate()
1603
+ }, 'does not exist on the parent entity fields list')
1604
+ })
1605
+
1606
+ test('works with empty entity fields list', ({ assert }) => {
1607
+ const dataDomain = new DataDomain()
1608
+ const model = dataDomain.addModel()
1609
+ const entity = model.addEntity()
1610
+ const property = entity.addProperty({ info: { name: 'only' } })
1611
+
1612
+ const duplicate = property.duplicate()
1613
+
1614
+ assert.equal(entity.fields.length, 2)
1615
+ assert.equal(entity.fields[0].key, property.key)
1616
+ assert.equal(entity.fields[1].key, duplicate.key)
1617
+ })
1618
+
1619
+ test('handles duplication of property with associations in between', ({ assert }) => {
1620
+ const dataDomain = new DataDomain()
1621
+ const model = dataDomain.addModel()
1622
+ const entity = model.addEntity()
1623
+ const targetEntity = model.addEntity()
1624
+
1625
+ const property1 = entity.addProperty({ info: { name: 'prop1' } })
1626
+ const association = entity.addAssociation({ key: targetEntity.key })
1627
+ association.info.name = 'assoc1'
1628
+ const property2 = entity.addProperty({ info: { name: 'prop2' } })
1629
+
1630
+ const duplicate = property1.duplicate()
1631
+
1632
+ // Should maintain correct order
1633
+ const fieldKeys = entity.fields.map((f) => f.key)
1634
+ assert.deepEqual(fieldKeys, [property1.key, duplicate.key, association.key, property2.key])
1635
+ })
1636
+
1637
+ test('preserves field types correctly', ({ assert }) => {
1638
+ const dataDomain = new DataDomain()
1639
+ const model = dataDomain.addModel()
1640
+ const entity = model.addEntity()
1641
+ const property = entity.addProperty({ info: { name: 'test' } })
1642
+
1643
+ const duplicate = property.duplicate()
1644
+
1645
+ // Check that both original and duplicate have correct field type
1646
+ const originalField = entity.fields.find((f) => f.key === property.key)
1647
+ const duplicateField = entity.fields.find((f) => f.key === duplicate.key)
1648
+
1649
+ assert.equal(originalField?.type, 'property')
1650
+ assert.equal(duplicateField?.type, 'property')
1651
+ })
1652
+ })
@@ -1 +0,0 @@
1
- {"version":3,"file":"observed.d.ts","sourceRoot":"","sources":["../../../src/modeling/observed.ts"],"names":[],"mappings":"AAIA,UAAU,cAAc;IACtB,MAAM,CAAC,EAAE;QAAE,YAAY,IAAI,IAAI,CAAA;KAAE,CAAA;IACjC,YAAY,CAAC,EAAE,MAAM,IAAI,CAAA;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAEhC,CAAC,CAAC,SAAS,cAAc,EAAE,CAAC,EAC1B,MAAM,EAAE,4BAA4B,CAAC,CAAC,EAAE,CAAC,CAAC,EAC1C,OAAO,EAAE,6BAA6B,CAAC,CAAC,EAAE,CAAC,CAAC,GAC3C,4BAA4B,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAErC,CAAC,CAAC,SAAS,cAAc,EAAE,CAAC,EAC1B,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,EAC1B,OAAO,EAAE,2BAA2B,CAAC,CAAC,EAAE,CAAC,CAAC,GACzC,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,IAAI,CAAA;CAC/B;AAED,KAAK,uBAAuB,CAAC,CAAC,EAAE,CAAC,IAAI,6BAA6B,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,2BAA2B,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;AAC5G,KAAK,sBAAsB,CAAC,CAAC,EAAE,CAAC,IAAI,4BAA4B,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC,CAAA;AAE7F,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAA;CACf;AAED;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,SAAS,CAUzF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,QAAQ,CAAC,MAAM,GAAE,aAAkB,GAAG,iBAAiB,CA2GtE;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,KACpB,CAAC,SAAS,cAAc,EAAE,CAAC,SAAS,WAAW,EACrD,QAAQ,sBAAsB,CAAC,CAAC,EAAE,CAAC,CAAC,EACpC,SAAS,uBAAuB,CAAC,CAAC,EAAE,CAAC,CAAC,KACrC,GAAG,CAiEP"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"observed.js","sourceRoot":"","sources":["../../../src/modeling/observed.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nconst reactiveSymbol = Symbol('reactive')\nconst proxySymbol = Symbol('proxy')\n\ninterface DomainInstance {\n domain?: { notifyChange(): void }\n notifyChange?: () => void\n}\n\nexport interface PropertyDecorator {\n // accessor decorator signature\n <C extends DomainInstance, V>(\n target: ClassAccessorDecoratorTarget<C, V>,\n context: ClassAccessorDecoratorContext<C, V>\n ): ClassAccessorDecoratorResult<C, V>\n // setter decorator signature\n <C extends DomainInstance, V>(\n target: (value: V) => void,\n context: ClassSetterDecoratorContext<C, V>\n ): (this: C, value: V) => void\n}\n\ntype StandardPropertyContext<C, V> = ClassAccessorDecoratorContext<C, V> | ClassSetterDecoratorContext<C, V>\ntype StandardPropertyTarget<C, V> = ClassAccessorDecoratorTarget<C, V> | ((value: V) => void)\n\nexport interface ObserveConfig {\n /**\n * To be used when observing an object and not a primitive.\n * It creates a proxy that observes changes in the object.\n */\n deep?: boolean\n}\n\n/**\n * Reads the raw value of the object, that is, not proxied object.\n * @param source The source object that contains the object\n * @param target The target object set on the source object\n * @returns The not proxied object or undefined\n */\nexport function toRaw<T extends object = object>(source: object, target: T): T | undefined {\n const proxies = Reflect.get(source, proxySymbol) as Map<object, object>\n if (!proxies) {\n return undefined\n }\n for (const [key, value] of proxies.entries()) {\n if (value === target) {\n return key as T\n }\n }\n}\n\n/**\n * Turns a class property or a setter into an observed property\n * that notifies the root domain when changed.\n *\n * A property has to be declared with the `accessor` type to be\n * observed.\n *\n * ```typescript\n * @observed() accessor name: string | undefined\n *\n * @observed()\n * set height(value: number) {\n * this.#height = value\n * }\n *\n * get height(): number {\n * return this.#height\n * }\n * ```\n *\n * The decorator can be used in the following ways:\n * - As a class property decorator\n * - As a class setter decorator\n *\n * The property class either has to have a `root` property\n * or a `notifyChange` method. The decorator will call the\n * `notifyChange` method if it exists. Otherwise, it will\n * call the `notifyChange` method of the root domain.\n */\nexport function observed(config: ObserveConfig = {}): PropertyDecorator {\n return <C extends DomainInstance, V>(\n target: StandardPropertyTarget<C, V>,\n context: StandardPropertyContext<C, V>\n ): any => {\n const { kind } = context\n const { deep } = config\n\n function createDeepProxy(this: DomainInstance, obj: unknown, notifyChange: () => void): any {\n if (typeof obj !== 'object' || obj === null) {\n return obj\n }\n // instead of using the target object to store the proxy info, we\n // reflect the proxy info to the object itself. This way we can\n // keep the stored values clean, which helps with testing (deep equal would include symbols)\n // Keys are original objects, values are proxies\n let proxies = Reflect.get(this, proxySymbol) as Map<object, object>\n if (!proxies) {\n proxies = new Map()\n Reflect.set(this, proxySymbol, proxies)\n }\n\n if (proxies.has(obj)) {\n return obj\n }\n\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const targetObject = this\n\n const proxy = new Proxy(obj, {\n get(target, prop) {\n const value = Reflect.get(target, prop)\n return createDeepProxy.bind(targetObject)(value, notifyChange)\n },\n set(target, prop, value) {\n const oldValue = Reflect.get(target, prop)\n if (oldValue !== value) {\n Reflect.set(target, prop, value)\n notifyChange()\n }\n return true\n },\n deleteProperty(target, prop) {\n Reflect.deleteProperty(target, prop)\n notifyChange()\n return true\n },\n })\n proxies.set(obj, proxy)\n return proxy\n }\n\n if (kind === 'accessor') {\n return {\n set(this: DomainInstance, value: V): void {\n let map = Reflect.get(this, reactiveSymbol)\n if (!map) {\n map = {}\n Reflect.set(this, reactiveSymbol, map)\n }\n if (map[context.name] === context.name) {\n return\n }\n const notify = () => {\n if (this.domain) {\n this.domain.notifyChange()\n } else if (this.notifyChange) {\n this.notifyChange()\n }\n }\n if (deep) {\n value = createDeepProxy.bind(this)(value, notify)\n }\n if (value === undefined) {\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete map[context.name]\n } else {\n map[context.name] = value\n }\n notify()\n },\n\n get(): V {\n const map = Reflect.get(this, reactiveSymbol) || {}\n return map[context.name]\n },\n }\n } else if (kind === 'setter') {\n const { name } = context\n return function (this: DomainInstance, value: V): void {\n const oldValue = this[name as keyof DomainInstance]\n if (value === oldValue) {\n return\n }\n const notify = () => {\n if (this.domain) {\n this.domain.notifyChange()\n } else if (this.notifyChange) {\n this.notifyChange()\n }\n }\n ;(target as (value: V) => void).call(this, value)\n notify()\n }\n }\n throw new Error(`Unsupported decorator location: ${kind}`)\n }\n}\n\n/**\n * A decorator that can be used to retarget the change event\n * of a property to the root domain.\n *\n * This decorator should not be used with the `observed` decorator.\n * It does the same thing. It will notify about a change to the\n * property itself.\n */\nexport function retargetChange() {\n return <C extends DomainInstance, V extends EventTarget>(\n target: StandardPropertyTarget<C, V>,\n context: StandardPropertyContext<C, V>\n ): any => {\n const { kind } = context\n function observer(this: DomainInstance) {\n if (this.domain) {\n this.domain.notifyChange()\n }\n }\n let binding: ((this: DomainInstance) => void) | undefined\n if (kind === 'accessor') {\n return {\n set(this: DomainInstance, value: V): void {\n let map = Reflect.get(this, reactiveSymbol)\n if (!map) {\n map = {}\n Reflect.set(this, reactiveSymbol, map)\n }\n if (map[context.name] === context.name) {\n return\n }\n const oldValue = map[context.name]\n if (oldValue === value) {\n return\n }\n if (value === undefined) {\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete map[context.name]\n } else {\n map[context.name] = value\n }\n if (oldValue && binding) {\n oldValue.removeEventListener('change', binding)\n }\n if (value) {\n binding = observer.bind(this)\n value.addEventListener('change', binding)\n }\n if (this.domain) {\n this.domain.notifyChange()\n }\n },\n\n get(): V {\n const map = Reflect.get(this, reactiveSymbol) || {}\n return map[context.name]\n },\n }\n } else if (kind === 'setter') {\n const { name } = context\n return function (this: DomainInstance, value: V): void {\n const oldValue = this[name as keyof DomainInstance] as unknown as V\n if (value === oldValue) {\n return\n }\n ;(target as (value: V) => void).call(this, value)\n if (oldValue && binding) {\n oldValue.removeEventListener('change', binding)\n }\n if (value) {\n binding = observer.bind(this)\n value.addEventListener('change', binding)\n }\n }\n }\n throw new Error(`Unsupported decorator location: ${kind}`)\n }\n}\n"]}