@cepseudo/ngsi-ld 1.0.0

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 (142) hide show
  1. package/README.md +425 -0
  2. package/dist/cache/entity_cache.d.ts +42 -0
  3. package/dist/cache/entity_cache.d.ts.map +1 -0
  4. package/dist/cache/entity_cache.js +93 -0
  5. package/dist/cache/entity_cache.js.map +1 -0
  6. package/dist/components/ngsi_ld_collector.d.ts +25 -0
  7. package/dist/components/ngsi_ld_collector.d.ts.map +1 -0
  8. package/dist/components/ngsi_ld_collector.js +13 -0
  9. package/dist/components/ngsi_ld_collector.js.map +1 -0
  10. package/dist/components/ngsi_ld_harvester.d.ts +25 -0
  11. package/dist/components/ngsi_ld_harvester.d.ts.map +1 -0
  12. package/dist/components/ngsi_ld_harvester.js +13 -0
  13. package/dist/components/ngsi_ld_harvester.js.map +1 -0
  14. package/dist/components/type_guards.d.ts +15 -0
  15. package/dist/components/type_guards.d.ts.map +1 -0
  16. package/dist/components/type_guards.js +25 -0
  17. package/dist/components/type_guards.js.map +1 -0
  18. package/dist/endpoints/attrs.d.ts +7 -0
  19. package/dist/endpoints/attrs.d.ts.map +1 -0
  20. package/dist/endpoints/attrs.js +37 -0
  21. package/dist/endpoints/attrs.js.map +1 -0
  22. package/dist/endpoints/entities.d.ts +9 -0
  23. package/dist/endpoints/entities.d.ts.map +1 -0
  24. package/dist/endpoints/entities.js +149 -0
  25. package/dist/endpoints/entities.js.map +1 -0
  26. package/dist/endpoints/subscriptions.d.ts +8 -0
  27. package/dist/endpoints/subscriptions.d.ts.map +1 -0
  28. package/dist/endpoints/subscriptions.js +109 -0
  29. package/dist/endpoints/subscriptions.js.map +1 -0
  30. package/dist/endpoints/types.d.ts +7 -0
  31. package/dist/endpoints/types.d.ts.map +1 -0
  32. package/dist/endpoints/types.js +45 -0
  33. package/dist/endpoints/types.js.map +1 -0
  34. package/dist/helpers/property.d.ts +33 -0
  35. package/dist/helpers/property.d.ts.map +1 -0
  36. package/dist/helpers/property.js +40 -0
  37. package/dist/helpers/property.js.map +1 -0
  38. package/dist/helpers/urn.d.ts +26 -0
  39. package/dist/helpers/urn.d.ts.map +1 -0
  40. package/dist/helpers/urn.js +30 -0
  41. package/dist/helpers/urn.js.map +1 -0
  42. package/dist/index.d.ts +22 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +19 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/models/agrifood/agri_parcel.d.ts +17 -0
  47. package/dist/models/agrifood/agri_parcel.d.ts.map +1 -0
  48. package/dist/models/agrifood/agri_parcel.js +27 -0
  49. package/dist/models/agrifood/agri_parcel.js.map +1 -0
  50. package/dist/models/agrifood/agri_soil_measurement.d.ts +17 -0
  51. package/dist/models/agrifood/agri_soil_measurement.d.ts.map +1 -0
  52. package/dist/models/agrifood/agri_soil_measurement.js +31 -0
  53. package/dist/models/agrifood/agri_soil_measurement.js.map +1 -0
  54. package/dist/models/agrifood/agri_weather_observed.d.ts +20 -0
  55. package/dist/models/agrifood/agri_weather_observed.d.ts.map +1 -0
  56. package/dist/models/agrifood/agri_weather_observed.js +34 -0
  57. package/dist/models/agrifood/agri_weather_observed.js.map +1 -0
  58. package/dist/models/device/device.d.ts +24 -0
  59. package/dist/models/device/device.d.ts.map +1 -0
  60. package/dist/models/device/device.js +39 -0
  61. package/dist/models/device/device.js.map +1 -0
  62. package/dist/models/device/device_measurement.d.ts +16 -0
  63. package/dist/models/device/device_measurement.d.ts.map +1 -0
  64. package/dist/models/device/device_measurement.js +34 -0
  65. package/dist/models/device/device_measurement.js.map +1 -0
  66. package/dist/models/environment/air_quality_observed.d.ts +22 -0
  67. package/dist/models/environment/air_quality_observed.d.ts.map +1 -0
  68. package/dist/models/environment/air_quality_observed.js +50 -0
  69. package/dist/models/environment/air_quality_observed.js.map +1 -0
  70. package/dist/models/environment/noise_level_observed.d.ts +17 -0
  71. package/dist/models/environment/noise_level_observed.d.ts.map +1 -0
  72. package/dist/models/environment/noise_level_observed.js +31 -0
  73. package/dist/models/environment/noise_level_observed.js.map +1 -0
  74. package/dist/models/environment/water_quality_observed.d.ts +20 -0
  75. package/dist/models/environment/water_quality_observed.d.ts.map +1 -0
  76. package/dist/models/environment/water_quality_observed.js +46 -0
  77. package/dist/models/environment/water_quality_observed.js.map +1 -0
  78. package/dist/models/environment/weather_observed.d.ts +19 -0
  79. package/dist/models/environment/weather_observed.d.ts.map +1 -0
  80. package/dist/models/environment/weather_observed.js +46 -0
  81. package/dist/models/environment/weather_observed.js.map +1 -0
  82. package/dist/models/index.d.ts +25 -0
  83. package/dist/models/index.d.ts.map +1 -0
  84. package/dist/models/index.js +17 -0
  85. package/dist/models/index.js.map +1 -0
  86. package/dist/models/smart_city/parking_spot.d.ts +14 -0
  87. package/dist/models/smart_city/parking_spot.d.ts.map +1 -0
  88. package/dist/models/smart_city/parking_spot.js +27 -0
  89. package/dist/models/smart_city/parking_spot.js.map +1 -0
  90. package/dist/models/smart_city/street_light.d.ts +16 -0
  91. package/dist/models/smart_city/street_light.d.ts.map +1 -0
  92. package/dist/models/smart_city/street_light.js +33 -0
  93. package/dist/models/smart_city/street_light.js.map +1 -0
  94. package/dist/models/smart_city/traffic_flow_observed.d.ts +19 -0
  95. package/dist/models/smart_city/traffic_flow_observed.d.ts.map +1 -0
  96. package/dist/models/smart_city/traffic_flow_observed.js +37 -0
  97. package/dist/models/smart_city/traffic_flow_observed.js.map +1 -0
  98. package/dist/notifications/notification_sender.d.ts +16 -0
  99. package/dist/notifications/notification_sender.d.ts.map +1 -0
  100. package/dist/notifications/notification_sender.js +70 -0
  101. package/dist/notifications/notification_sender.js.map +1 -0
  102. package/dist/notifications/notification_worker.d.ts +19 -0
  103. package/dist/notifications/notification_worker.d.ts.map +1 -0
  104. package/dist/notifications/notification_worker.js +65 -0
  105. package/dist/notifications/notification_worker.js.map +1 -0
  106. package/dist/plugin.d.ts +35 -0
  107. package/dist/plugin.d.ts.map +1 -0
  108. package/dist/plugin.js +113 -0
  109. package/dist/plugin.js.map +1 -0
  110. package/dist/subscriptions/q_parser.d.ts +42 -0
  111. package/dist/subscriptions/q_parser.d.ts.map +1 -0
  112. package/dist/subscriptions/q_parser.js +113 -0
  113. package/dist/subscriptions/q_parser.js.map +1 -0
  114. package/dist/subscriptions/subscription_cache.d.ts +46 -0
  115. package/dist/subscriptions/subscription_cache.d.ts.map +1 -0
  116. package/dist/subscriptions/subscription_cache.js +105 -0
  117. package/dist/subscriptions/subscription_cache.js.map +1 -0
  118. package/dist/subscriptions/subscription_matcher.d.ts +23 -0
  119. package/dist/subscriptions/subscription_matcher.d.ts.map +1 -0
  120. package/dist/subscriptions/subscription_matcher.js +84 -0
  121. package/dist/subscriptions/subscription_matcher.js.map +1 -0
  122. package/dist/subscriptions/subscription_store.d.ts +42 -0
  123. package/dist/subscriptions/subscription_store.d.ts.map +1 -0
  124. package/dist/subscriptions/subscription_store.js +189 -0
  125. package/dist/subscriptions/subscription_store.js.map +1 -0
  126. package/dist/types/context.d.ts +9 -0
  127. package/dist/types/context.d.ts.map +1 -0
  128. package/dist/types/context.js +5 -0
  129. package/dist/types/context.js.map +1 -0
  130. package/dist/types/entity.d.ts +46 -0
  131. package/dist/types/entity.d.ts.map +1 -0
  132. package/dist/types/entity.js +2 -0
  133. package/dist/types/entity.js.map +1 -0
  134. package/dist/types/notification.d.ts +22 -0
  135. package/dist/types/notification.d.ts.map +1 -0
  136. package/dist/types/notification.js +2 -0
  137. package/dist/types/notification.js.map +1 -0
  138. package/dist/types/subscription.d.ts +54 -0
  139. package/dist/types/subscription.d.ts.map +1 -0
  140. package/dist/types/subscription.js +2 -0
  141. package/dist/types/subscription.js.map +1 -0
  142. package/package.json +74 -0
@@ -0,0 +1,15 @@
1
+ import type { NgsiLdCollector } from './ngsi_ld_collector.js';
2
+ import type { NgsiLdHarvester } from './ngsi_ld_harvester.js';
3
+ /**
4
+ * Duck-type guard: checks if a component implements the NgsiLdCollector contract.
5
+ *
6
+ * Uses structural typing to avoid a hard import of NgsiLdCollector in the engine.
7
+ */
8
+ export declare function isNgsiLdCollector(component: unknown): component is NgsiLdCollector;
9
+ /**
10
+ * Duck-type guard: checks if a component implements the NgsiLdHarvester contract.
11
+ *
12
+ * Uses structural typing to avoid a hard import of NgsiLdHarvester in the engine.
13
+ */
14
+ export declare function isNgsiLdHarvester(component: unknown): component is NgsiLdHarvester;
15
+ //# sourceMappingURL=type_guards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type_guards.d.ts","sourceRoot":"","sources":["../../src/components/type_guards.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAE7D;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,OAAO,GAAG,SAAS,IAAI,eAAe,CAQlF;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,OAAO,GAAG,SAAS,IAAI,eAAe,CAQlF"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Duck-type guard: checks if a component implements the NgsiLdCollector contract.
3
+ *
4
+ * Uses structural typing to avoid a hard import of NgsiLdCollector in the engine.
5
+ */
6
+ export function isNgsiLdCollector(component) {
7
+ return (component !== null &&
8
+ typeof component === 'object' &&
9
+ typeof component.toNgsiLdEntity === 'function' &&
10
+ typeof component.collect === 'function' &&
11
+ typeof component.getSchedule === 'function');
12
+ }
13
+ /**
14
+ * Duck-type guard: checks if a component implements the NgsiLdHarvester contract.
15
+ *
16
+ * Uses structural typing to avoid a hard import of NgsiLdHarvester in the engine.
17
+ */
18
+ export function isNgsiLdHarvester(component) {
19
+ return (component !== null &&
20
+ typeof component === 'object' &&
21
+ typeof component.toNgsiLdEntity === 'function' &&
22
+ typeof component.harvest === 'function' &&
23
+ typeof component.getUserConfiguration === 'function');
24
+ }
25
+ //# sourceMappingURL=type_guards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type_guards.js","sourceRoot":"","sources":["../../src/components/type_guards.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAAkB;IAChD,OAAO,CACH,SAAS,KAAK,IAAI;QAClB,OAAO,SAAS,KAAK,QAAQ;QAC7B,OAAQ,SAA6B,CAAC,cAAc,KAAK,UAAU;QACnE,OAAQ,SAA6B,CAAC,OAAO,KAAK,UAAU;QAC5D,OAAQ,SAA6B,CAAC,WAAW,KAAK,UAAU,CACnE,CAAA;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAAkB;IAChD,OAAO,CACH,SAAS,KAAK,IAAI;QAClB,OAAO,SAAS,KAAK,QAAQ;QAC7B,OAAQ,SAA6B,CAAC,cAAc,KAAK,UAAU;QACnE,OAAQ,SAA6B,CAAC,OAAO,KAAK,UAAU;QAC5D,OAAQ,SAA6B,CAAC,oBAAoB,KAAK,UAAU,CAC5E,CAAA;AACL,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { Router } from 'ultimate-express';
2
+ import type { EntityCache } from '../cache/entity_cache.js';
3
+ /**
4
+ * Registers the NGSI-LD attrs endpoint on the provided router.
5
+ */
6
+ export declare function registerAttrsEndpoints(router: Router, entityCache: EntityCache): void;
7
+ //# sourceMappingURL=attrs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attrs.d.ts","sourceRoot":"","sources":["../../src/endpoints/attrs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAqB,MAAM,kBAAkB,CAAA;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAG3D;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,GAAG,IAAI,CAkCrF"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Registers the NGSI-LD attrs endpoint on the provided router.
3
+ */
4
+ export function registerAttrsEndpoints(router, entityCache) {
5
+ /**
6
+ * PATCH /ngsi-ld/v1/entities/:entityId/attrs
7
+ * Append or update attributes on an existing entity (partial update).
8
+ */
9
+ router.patch('/ngsi-ld/v1/entities/:entityId/attrs', async (req, res) => {
10
+ const entityId = decodeURIComponent(req.params['entityId']);
11
+ try {
12
+ const existing = await entityCache.get(entityId);
13
+ if (!existing) {
14
+ res.status(404).json({
15
+ type: 'https://uri.etsi.org/ngsi-ld/errors/ResourceNotFound',
16
+ title: 'Entity not found',
17
+ });
18
+ return;
19
+ }
20
+ const attrsFragment = req.body;
21
+ // Merge attributes into the existing entity (NGSI-LD PATCH semantics)
22
+ const merged = {
23
+ ...existing,
24
+ ...attrsFragment,
25
+ // Preserve immutable fields
26
+ id: existing.id,
27
+ type: existing.type,
28
+ };
29
+ await entityCache.set(merged);
30
+ res.status(204).end();
31
+ }
32
+ catch (err) {
33
+ res.status(500).json({ type: 'https://uri.etsi.org/ngsi-ld/errors/InternalError', title: String(err) });
34
+ }
35
+ });
36
+ }
37
+ //# sourceMappingURL=attrs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attrs.js","sourceRoot":"","sources":["../../src/endpoints/attrs.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAc,EAAE,WAAwB;IAC3E;;;OAGG;IACH,MAAM,CAAC,KAAK,CAAC,sCAAsC,EAAE,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,EAAE;QACvF,MAAM,QAAQ,GAAG,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAW,CAAC,CAAA;QAErE,IAAI,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;YAChD,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACZ,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;oBACjB,IAAI,EAAE,sDAAsD;oBAC5D,KAAK,EAAE,kBAAkB;iBAC5B,CAAC,CAAA;gBACF,OAAM;YACV,CAAC;YAED,MAAM,aAAa,GAAG,GAAG,CAAC,IAA6B,CAAA;YACvD,sEAAsE;YACtE,MAAM,MAAM,GAAiB;gBACzB,GAAG,QAAQ;gBACX,GAAG,aAAa;gBAChB,4BAA4B;gBAC5B,EAAE,EAAE,QAAQ,CAAC,EAAE;gBACf,IAAI,EAAE,QAAQ,CAAC,IAAI;aACtB,CAAA;YAED,MAAM,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;YAC7B,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAA;QACzB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACX,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,mDAAmD,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QAC3G,CAAC;IACL,CAAC,CAAC,CAAA;AACN,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { Router } from 'ultimate-express';
2
+ import type { EntityCache } from '../cache/entity_cache.js';
3
+ import type { SubscriptionStore } from '../subscriptions/subscription_store.js';
4
+ import type { SubscriptionCache } from '../subscriptions/subscription_cache.js';
5
+ /**
6
+ * Registers NGSI-LD entity endpoints on the provided router.
7
+ */
8
+ export declare function registerEntityEndpoints(router: Router, entityCache: EntityCache, _subscriptionStore: SubscriptionStore, _subscriptionCache: SubscriptionCache): void;
9
+ //# sourceMappingURL=entities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entities.d.ts","sourceRoot":"","sources":["../../src/endpoints/entities.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAqB,MAAM,kBAAkB,CAAA;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAE3D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAA;AAC/E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAA;AAa/E;;GAEG;AACH,wBAAgB,uBAAuB,CACnC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,WAAW,EACxB,kBAAkB,EAAE,iBAAiB,EACrC,kBAAkB,EAAE,iBAAiB,GACtC,IAAI,CA8IN"}
@@ -0,0 +1,149 @@
1
+ import { NGSI_LD_CORE_CONTEXT } from '../types/context.js';
2
+ import { parseQ, evaluateQ } from '../subscriptions/q_parser.js';
3
+ const LD_JSON = 'application/ld+json';
4
+ function withContext(entity) {
5
+ return {
6
+ ...entity,
7
+ '@context': entity['@context'] ?? NGSI_LD_CORE_CONTEXT,
8
+ };
9
+ }
10
+ /**
11
+ * Registers NGSI-LD entity endpoints on the provided router.
12
+ */
13
+ export function registerEntityEndpoints(router, entityCache, _subscriptionStore, _subscriptionCache) {
14
+ /**
15
+ * GET /ngsi-ld/v1/entities
16
+ * Query entities by type, q-filter, attributes, pagination.
17
+ */
18
+ router.get('/ngsi-ld/v1/entities', async (req, res) => {
19
+ const type = req.query['type'];
20
+ const q = req.query['q'];
21
+ const attrs = req.query['attrs'];
22
+ const limit = parseInt(String(req.query['limit'] ?? '20'), 10);
23
+ const offset = parseInt(String(req.query['offset'] ?? '0'), 10);
24
+ try {
25
+ let entities = await entityCache.list({ type, limit, offset });
26
+ // Apply q-filter
27
+ if (q) {
28
+ try {
29
+ const expr = parseQ(q);
30
+ entities = entities.filter(e => evaluateQ(expr, e));
31
+ }
32
+ catch {
33
+ res.status(400).json({ type: 'https://uri.etsi.org/ngsi-ld/errors/BadRequestData', title: 'Invalid q filter' });
34
+ return;
35
+ }
36
+ }
37
+ // Project attributes
38
+ if (attrs) {
39
+ const attrsArray = attrs.split(',').map(a => a.trim());
40
+ entities = entities.map(e => {
41
+ const projected = { id: e.id, type: e.type };
42
+ for (const attr of attrsArray) {
43
+ if (e[attr] !== undefined)
44
+ projected[attr] = e[attr];
45
+ }
46
+ return withContext(projected);
47
+ });
48
+ }
49
+ else {
50
+ entities = entities.map(withContext);
51
+ }
52
+ res.setHeader('Content-Type', LD_JSON);
53
+ res.status(200).json(entities);
54
+ }
55
+ catch (err) {
56
+ res.status(500).json({ type: 'https://uri.etsi.org/ngsi-ld/errors/InternalError', title: String(err) });
57
+ }
58
+ });
59
+ /**
60
+ * POST /ngsi-ld/v1/entities
61
+ * Create or replace an entity in the cache.
62
+ */
63
+ router.post('/ngsi-ld/v1/entities', async (req, res) => {
64
+ const body = req.body;
65
+ if (!body || !body.id || !body.type) {
66
+ res.status(400).json({ type: 'https://uri.etsi.org/ngsi-ld/errors/BadRequestData', title: 'Missing id or type' });
67
+ return;
68
+ }
69
+ try {
70
+ await entityCache.set(body);
71
+ res.setHeader('Location', `/ngsi-ld/v1/entities/${encodeURIComponent(body.id)}`);
72
+ res.status(201).end();
73
+ }
74
+ catch (err) {
75
+ res.status(500).json({ type: 'https://uri.etsi.org/ngsi-ld/errors/InternalError', title: String(err) });
76
+ }
77
+ });
78
+ /**
79
+ * GET /ngsi-ld/v1/entities/:entityId
80
+ */
81
+ router.get('/ngsi-ld/v1/entities/:entityId', async (req, res) => {
82
+ const entityId = decodeURIComponent(req.params['entityId']);
83
+ const attrs = req.query['attrs'];
84
+ try {
85
+ let entity = await entityCache.get(entityId);
86
+ if (!entity) {
87
+ res.status(404).json({ type: 'https://uri.etsi.org/ngsi-ld/errors/ResourceNotFound', title: 'Entity not found' });
88
+ return;
89
+ }
90
+ if (attrs) {
91
+ const attrsArray = attrs.split(',').map(a => a.trim());
92
+ const projected = { id: entity.id, type: entity.type };
93
+ for (const attr of attrsArray) {
94
+ if (entity[attr] !== undefined)
95
+ projected[attr] = entity[attr];
96
+ }
97
+ entity = withContext(projected);
98
+ }
99
+ else {
100
+ entity = withContext(entity);
101
+ }
102
+ res.setHeader('Content-Type', LD_JSON);
103
+ res.status(200).json(entity);
104
+ }
105
+ catch (err) {
106
+ res.status(500).json({ type: 'https://uri.etsi.org/ngsi-ld/errors/InternalError', title: String(err) });
107
+ }
108
+ });
109
+ /**
110
+ * PATCH /ngsi-ld/v1/entities/:entityId
111
+ * Merge-patch an entity.
112
+ */
113
+ router.patch('/ngsi-ld/v1/entities/:entityId', async (req, res) => {
114
+ const entityId = decodeURIComponent(req.params['entityId']);
115
+ try {
116
+ const existing = await entityCache.get(entityId);
117
+ if (!existing) {
118
+ res.status(404).json({ type: 'https://uri.etsi.org/ngsi-ld/errors/ResourceNotFound', title: 'Entity not found' });
119
+ return;
120
+ }
121
+ const patch = req.body;
122
+ const merged = { ...existing, ...patch, id: existing.id, type: existing.type };
123
+ await entityCache.set(merged);
124
+ res.status(204).end();
125
+ }
126
+ catch (err) {
127
+ res.status(500).json({ type: 'https://uri.etsi.org/ngsi-ld/errors/InternalError', title: String(err) });
128
+ }
129
+ });
130
+ /**
131
+ * DELETE /ngsi-ld/v1/entities/:entityId
132
+ */
133
+ router.delete('/ngsi-ld/v1/entities/:entityId', async (req, res) => {
134
+ const entityId = decodeURIComponent(req.params['entityId']);
135
+ try {
136
+ const existing = await entityCache.get(entityId);
137
+ if (!existing) {
138
+ res.status(404).json({ type: 'https://uri.etsi.org/ngsi-ld/errors/ResourceNotFound', title: 'Entity not found' });
139
+ return;
140
+ }
141
+ await entityCache.delete(entityId);
142
+ res.status(204).end();
143
+ }
144
+ catch (err) {
145
+ res.status(500).json({ type: 'https://uri.etsi.org/ngsi-ld/errors/InternalError', title: String(err) });
146
+ }
147
+ });
148
+ }
149
+ //# sourceMappingURL=entities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entities.js","sourceRoot":"","sources":["../../src/endpoints/entities.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { Router } from 'ultimate-express';
2
+ import type { SubscriptionStore } from '../subscriptions/subscription_store.js';
3
+ import type { SubscriptionCache } from '../subscriptions/subscription_cache.js';
4
+ /**
5
+ * Registers NGSI-LD subscription CRUD endpoints on the provided router.
6
+ */
7
+ export declare function registerSubscriptionEndpoints(router: Router, store: SubscriptionStore, cache: SubscriptionCache): void;
8
+ //# sourceMappingURL=subscriptions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscriptions.d.ts","sourceRoot":"","sources":["../../src/endpoints/subscriptions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAqB,MAAM,kBAAkB,CAAA;AACjE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAA;AAC/E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAA;AAG/E;;GAEG;AACH,wBAAgB,6BAA6B,CACzC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,iBAAiB,EACxB,KAAK,EAAE,iBAAiB,GACzB,IAAI,CA4GN"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Registers NGSI-LD subscription CRUD endpoints on the provided router.
3
+ */
4
+ export function registerSubscriptionEndpoints(router, store, cache) {
5
+ /**
6
+ * POST /ngsi-ld/v1/subscriptions
7
+ * Create a new subscription.
8
+ */
9
+ router.post('/ngsi-ld/v1/subscriptions', async (req, res) => {
10
+ const body = req.body;
11
+ if (!body?.notification?.endpoint?.uri) {
12
+ res.status(400).json({
13
+ type: 'https://uri.etsi.org/ngsi-ld/errors/BadRequestData',
14
+ title: 'Missing notification.endpoint.uri',
15
+ });
16
+ return;
17
+ }
18
+ try {
19
+ const sub = await store.create(body);
20
+ await cache.add(sub);
21
+ res.setHeader('Location', `/ngsi-ld/v1/subscriptions/${sub.id}`);
22
+ res.setHeader('Content-Type', 'application/ld+json');
23
+ res.status(201).json(sub);
24
+ }
25
+ catch (err) {
26
+ res.status(500).json({ type: 'https://uri.etsi.org/ngsi-ld/errors/InternalError', title: String(err) });
27
+ }
28
+ });
29
+ /**
30
+ * GET /ngsi-ld/v1/subscriptions
31
+ * List all active subscriptions.
32
+ */
33
+ router.get('/ngsi-ld/v1/subscriptions', async (_req, res) => {
34
+ try {
35
+ const subs = await store.findAll();
36
+ res.setHeader('Content-Type', 'application/ld+json');
37
+ res.status(200).json(subs);
38
+ }
39
+ catch (err) {
40
+ res.status(500).json({ type: 'https://uri.etsi.org/ngsi-ld/errors/InternalError', title: String(err) });
41
+ }
42
+ });
43
+ /**
44
+ * GET /ngsi-ld/v1/subscriptions/:subscriptionId
45
+ */
46
+ router.get('/ngsi-ld/v1/subscriptions/:subscriptionId', async (req, res) => {
47
+ const id = req.params['subscriptionId'];
48
+ try {
49
+ const sub = await store.findById(id);
50
+ if (!sub) {
51
+ res.status(404).json({
52
+ type: 'https://uri.etsi.org/ngsi-ld/errors/ResourceNotFound',
53
+ title: 'Subscription not found',
54
+ });
55
+ return;
56
+ }
57
+ res.setHeader('Content-Type', 'application/ld+json');
58
+ res.status(200).json(sub);
59
+ }
60
+ catch (err) {
61
+ res.status(500).json({ type: 'https://uri.etsi.org/ngsi-ld/errors/InternalError', title: String(err) });
62
+ }
63
+ });
64
+ /**
65
+ * PATCH /ngsi-ld/v1/subscriptions/:subscriptionId
66
+ * Partially update a subscription.
67
+ */
68
+ router.patch('/ngsi-ld/v1/subscriptions/:subscriptionId', async (req, res) => {
69
+ const id = req.params['subscriptionId'];
70
+ const patch = req.body;
71
+ try {
72
+ const updated = await store.update(id, patch);
73
+ if (!updated) {
74
+ res.status(404).json({
75
+ type: 'https://uri.etsi.org/ngsi-ld/errors/ResourceNotFound',
76
+ title: 'Subscription not found',
77
+ });
78
+ return;
79
+ }
80
+ await cache.update(updated);
81
+ res.status(204).end();
82
+ }
83
+ catch (err) {
84
+ res.status(500).json({ type: 'https://uri.etsi.org/ngsi-ld/errors/InternalError', title: String(err) });
85
+ }
86
+ });
87
+ /**
88
+ * DELETE /ngsi-ld/v1/subscriptions/:subscriptionId
89
+ */
90
+ router.delete('/ngsi-ld/v1/subscriptions/:subscriptionId', async (req, res) => {
91
+ const id = req.params['subscriptionId'];
92
+ try {
93
+ const deleted = await store.delete(id);
94
+ if (!deleted) {
95
+ res.status(404).json({
96
+ type: 'https://uri.etsi.org/ngsi-ld/errors/ResourceNotFound',
97
+ title: 'Subscription not found',
98
+ });
99
+ return;
100
+ }
101
+ await cache.remove(id);
102
+ res.status(204).end();
103
+ }
104
+ catch (err) {
105
+ res.status(500).json({ type: 'https://uri.etsi.org/ngsi-ld/errors/InternalError', title: String(err) });
106
+ }
107
+ });
108
+ }
109
+ //# sourceMappingURL=subscriptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscriptions.js","sourceRoot":"","sources":["../../src/endpoints/subscriptions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { Router } from 'ultimate-express';
2
+ import type { EntityCache } from '../cache/entity_cache.js';
3
+ /**
4
+ * Registers the NGSI-LD types endpoint on the provided router.
5
+ */
6
+ export declare function registerTypesEndpoints(router: Router, entityCache: EntityCache): void;
7
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/endpoints/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAqB,MAAM,kBAAkB,CAAA;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAG3D;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,GAAG,IAAI,CA0CrF"}
@@ -0,0 +1,45 @@
1
+ import { NGSI_LD_CORE_CONTEXT } from '../types/context.js';
2
+ /**
3
+ * Registers the NGSI-LD types endpoint on the provided router.
4
+ */
5
+ export function registerTypesEndpoints(router, entityCache) {
6
+ /**
7
+ * GET /ngsi-ld/v1/types
8
+ * Returns a summary of all known entity types.
9
+ */
10
+ router.get('/ngsi-ld/v1/types', async (_req, res) => {
11
+ try {
12
+ const types = await entityCache.listTypes();
13
+ const typeDetails = await Promise.all(types.map(async (type) => {
14
+ const entities = await entityCache.listByType(type);
15
+ const attributeNames = new Set();
16
+ for (const entity of entities) {
17
+ for (const key of Object.keys(entity)) {
18
+ if (key !== 'id' && key !== 'type' && key !== '@context') {
19
+ attributeNames.add(key);
20
+ }
21
+ }
22
+ }
23
+ return {
24
+ id: `urn:ngsi-ld:EntityTypeInfo:${type}`,
25
+ type: 'EntityTypeInfo',
26
+ typeName: type,
27
+ entityCount: entities.length,
28
+ attributeNames: Array.from(attributeNames),
29
+ };
30
+ }));
31
+ res.setHeader('Content-Type', 'application/ld+json');
32
+ res.status(200).json({
33
+ id: 'urn:ngsi-ld:EntityTypeList:default',
34
+ type: 'EntityTypeList',
35
+ typeList: types,
36
+ typeDetails,
37
+ '@context': NGSI_LD_CORE_CONTEXT,
38
+ });
39
+ }
40
+ catch (err) {
41
+ res.status(500).json({ type: 'https://uri.etsi.org/ngsi-ld/errors/InternalError', title: String(err) });
42
+ }
43
+ });
44
+ }
45
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/endpoints/types.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAE1D;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAc,EAAE,WAAwB;IAC3E;;;OAGG;IACH,MAAM,CAAC,GAAG,CAAC,mBAAmB,EAAE,KAAK,EAAE,IAAa,EAAE,GAAa,EAAE,EAAE;QACnE,IAAI,CAAC;YACD,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,SAAS,EAAE,CAAA;YAE3C,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,GAAG,CACjC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAC,IAAI,EAAC,EAAE;gBACnB,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;gBACnD,MAAM,cAAc,GAAG,IAAI,GAAG,EAAU,CAAA;gBACxC,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;oBAC5B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;wBACpC,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,UAAU,EAAE,CAAC;4BACvD,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;wBAC3B,CAAC;oBACL,CAAC;gBACL,CAAC;gBACD,OAAO;oBACH,EAAE,EAAE,8BAA8B,IAAI,EAAE;oBACxC,IAAI,EAAE,gBAAgB;oBACtB,QAAQ,EAAE,IAAI;oBACd,WAAW,EAAE,QAAQ,CAAC,MAAM;oBAC5B,cAAc,EAAE,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC;iBAC7C,CAAA;YACL,CAAC,CAAC,CACL,CAAA;YAED,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,qBAAqB,CAAC,CAAA;YACpD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBACjB,EAAE,EAAE,oCAAoC;gBACxC,IAAI,EAAE,gBAAgB;gBACtB,QAAQ,EAAE,KAAK;gBACf,WAAW;gBACX,UAAU,EAAE,oBAAoB;aACnC,CAAC,CAAA;QACN,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACX,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,mDAAmD,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QAC3G,CAAC;IACL,CAAC,CAAC,CAAA;AACN,CAAC"}
@@ -0,0 +1,33 @@
1
+ import type { NgsiLdProperty, NgsiLdGeoProperty, NgsiLdRelationship, GeoJsonGeometry } from '../types/entity.js';
2
+ /**
3
+ * Creates an NGSI-LD Property attribute.
4
+ *
5
+ * @param value - The property value
6
+ * @param meta - Optional metadata (observedAt, unitCode, etc.)
7
+ */
8
+ export declare function property<T>(value: T, meta?: {
9
+ observedAt?: string;
10
+ unitCode?: string;
11
+ [key: string]: unknown;
12
+ }): NgsiLdProperty<T>;
13
+ /**
14
+ * Creates an NGSI-LD GeoProperty attribute.
15
+ *
16
+ * @param geojson - A GeoJSON geometry object
17
+ * @param meta - Optional metadata (observedAt, etc.)
18
+ */
19
+ export declare function geoProperty(geojson: GeoJsonGeometry, meta?: {
20
+ observedAt?: string;
21
+ [key: string]: unknown;
22
+ }): NgsiLdGeoProperty;
23
+ /**
24
+ * Creates an NGSI-LD Relationship attribute.
25
+ *
26
+ * @param urn - The URN of the related entity
27
+ * @param meta - Optional metadata (observedAt, etc.)
28
+ */
29
+ export declare function relationship(urn: string, meta?: {
30
+ observedAt?: string;
31
+ [key: string]: unknown;
32
+ }): NgsiLdRelationship;
33
+ //# sourceMappingURL=property.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"property.d.ts","sourceRoot":"","sources":["../../src/helpers/property.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAEhH;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EACtB,KAAK,EAAE,CAAC,EACR,IAAI,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,GAC1E,cAAc,CAAC,CAAC,CAAC,CAMnB;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CACvB,OAAO,EAAE,eAAe,EACxB,IAAI,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,GACvD,iBAAiB,CAMnB;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CACxB,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,GACvD,kBAAkB,CAMpB"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Creates an NGSI-LD Property attribute.
3
+ *
4
+ * @param value - The property value
5
+ * @param meta - Optional metadata (observedAt, unitCode, etc.)
6
+ */
7
+ export function property(value, meta) {
8
+ return {
9
+ type: 'Property',
10
+ value,
11
+ ...meta
12
+ };
13
+ }
14
+ /**
15
+ * Creates an NGSI-LD GeoProperty attribute.
16
+ *
17
+ * @param geojson - A GeoJSON geometry object
18
+ * @param meta - Optional metadata (observedAt, etc.)
19
+ */
20
+ export function geoProperty(geojson, meta) {
21
+ return {
22
+ type: 'GeoProperty',
23
+ value: geojson,
24
+ ...meta
25
+ };
26
+ }
27
+ /**
28
+ * Creates an NGSI-LD Relationship attribute.
29
+ *
30
+ * @param urn - The URN of the related entity
31
+ * @param meta - Optional metadata (observedAt, etc.)
32
+ */
33
+ export function relationship(urn, meta) {
34
+ return {
35
+ type: 'Relationship',
36
+ object: urn,
37
+ ...meta
38
+ };
39
+ }
40
+ //# sourceMappingURL=property.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"property.js","sourceRoot":"","sources":["../../src/helpers/property.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CACpB,KAAQ,EACR,IAAyE;IAEzE,OAAO;QACH,IAAI,EAAE,UAAU;QAChB,KAAK;QACL,GAAG,IAAI;KACV,CAAA;AACL,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CACvB,OAAwB,EACxB,IAAsD;IAEtD,OAAO;QACH,IAAI,EAAE,aAAa;QACnB,KAAK,EAAE,OAAO;QACd,GAAG,IAAI;KACV,CAAA;AACL,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CACxB,GAAW,EACX,IAAsD;IAEtD,OAAO;QACH,IAAI,EAAE,cAAc;QACpB,MAAM,EAAE,GAAG;QACX,GAAG,IAAI;KACV,CAAA;AACL,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Builds an NGSI-LD URN from a type and local identifier.
3
+ *
4
+ * @example
5
+ * buildUrn('AirQualityObserved', 'sensor-42')
6
+ * // => 'urn:ngsi-ld:AirQualityObserved:sensor-42'
7
+ */
8
+ export declare function buildUrn(type: string, localId: string): string;
9
+ /**
10
+ * Result of parsing an NGSI-LD URN.
11
+ */
12
+ export interface ParsedUrn {
13
+ type: string;
14
+ localId: string;
15
+ }
16
+ /**
17
+ * Parses an NGSI-LD URN into its type and local identifier components.
18
+ *
19
+ * @throws {Error} When the URN does not conform to the `urn:ngsi-ld:<type>:<localId>` format.
20
+ *
21
+ * @example
22
+ * parseUrn('urn:ngsi-ld:AirQualityObserved:sensor-42')
23
+ * // => { type: 'AirQualityObserved', localId: 'sensor-42' }
24
+ */
25
+ export declare function parseUrn(urn: string): ParsedUrn;
26
+ //# sourceMappingURL=urn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"urn.d.ts","sourceRoot":"","sources":["../../src/helpers/urn.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAClB;AAED;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAS/C"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Builds an NGSI-LD URN from a type and local identifier.
3
+ *
4
+ * @example
5
+ * buildUrn('AirQualityObserved', 'sensor-42')
6
+ * // => 'urn:ngsi-ld:AirQualityObserved:sensor-42'
7
+ */
8
+ export function buildUrn(type, localId) {
9
+ return `urn:ngsi-ld:${type}:${localId}`;
10
+ }
11
+ /**
12
+ * Parses an NGSI-LD URN into its type and local identifier components.
13
+ *
14
+ * @throws {Error} When the URN does not conform to the `urn:ngsi-ld:<type>:<localId>` format.
15
+ *
16
+ * @example
17
+ * parseUrn('urn:ngsi-ld:AirQualityObserved:sensor-42')
18
+ * // => { type: 'AirQualityObserved', localId: 'sensor-42' }
19
+ */
20
+ export function parseUrn(urn) {
21
+ const parts = urn.split(':');
22
+ if (parts.length < 4 || parts[0] !== 'urn' || parts[1] !== 'ngsi-ld') {
23
+ throw new Error(`Invalid NGSI-LD URN format: "${urn}". Expected "urn:ngsi-ld:<type>:<localId>"`);
24
+ }
25
+ // type is index 2, localId is everything from index 3 onward (supports colons in localId)
26
+ const type = parts[2];
27
+ const localId = parts.slice(3).join(':');
28
+ return { type, localId };
29
+ }
30
+ //# sourceMappingURL=urn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"urn.js","sourceRoot":"","sources":["../../src/helpers/urn.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,OAAe;IAClD,OAAO,eAAe,IAAI,IAAI,OAAO,EAAE,CAAA;AAC3C,CAAC;AAUD;;;;;;;;GAQG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAW;IAChC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC5B,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;QACnE,MAAM,IAAI,KAAK,CAAC,gCAAgC,GAAG,4CAA4C,CAAC,CAAA;IACpG,CAAC;IACD,0FAA0F;IAC1F,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;IACrB,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACxC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA;AAC5B,CAAC"}