@api-client/core 0.19.9 → 0.19.10
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/Testing.md +1 -1
- package/build/src/decorators/observed.d.ts.map +1 -1
- package/build/src/decorators/observed.js +91 -0
- package/build/src/decorators/observed.js.map +1 -1
- package/build/src/modeling/ApiModel.d.ts +21 -7
- package/build/src/modeling/ApiModel.d.ts.map +1 -1
- package/build/src/modeling/ApiModel.js +70 -29
- package/build/src/modeling/ApiModel.js.map +1 -1
- package/build/src/modeling/DomainValidation.d.ts +1 -1
- package/build/src/modeling/DomainValidation.d.ts.map +1 -1
- package/build/src/modeling/DomainValidation.js.map +1 -1
- package/build/src/modeling/ExposedEntity.d.ts +14 -0
- package/build/src/modeling/ExposedEntity.d.ts.map +1 -1
- package/build/src/modeling/ExposedEntity.js +59 -6
- package/build/src/modeling/ExposedEntity.js.map +1 -1
- package/build/src/modeling/actions/Action.d.ts +11 -1
- package/build/src/modeling/actions/Action.d.ts.map +1 -1
- package/build/src/modeling/actions/Action.js +21 -3
- package/build/src/modeling/actions/Action.js.map +1 -1
- package/build/src/modeling/actions/CreateAction.d.ts +2 -1
- package/build/src/modeling/actions/CreateAction.d.ts.map +1 -1
- package/build/src/modeling/actions/CreateAction.js +2 -2
- package/build/src/modeling/actions/CreateAction.js.map +1 -1
- package/build/src/modeling/actions/DeleteAction.d.ts +2 -1
- package/build/src/modeling/actions/DeleteAction.d.ts.map +1 -1
- package/build/src/modeling/actions/DeleteAction.js +2 -2
- package/build/src/modeling/actions/DeleteAction.js.map +1 -1
- package/build/src/modeling/actions/ListAction.d.ts +2 -1
- package/build/src/modeling/actions/ListAction.d.ts.map +1 -1
- package/build/src/modeling/actions/ListAction.js +2 -2
- package/build/src/modeling/actions/ListAction.js.map +1 -1
- package/build/src/modeling/actions/ReadAction.d.ts +2 -1
- package/build/src/modeling/actions/ReadAction.d.ts.map +1 -1
- package/build/src/modeling/actions/ReadAction.js +2 -2
- package/build/src/modeling/actions/ReadAction.js.map +1 -1
- package/build/src/modeling/actions/SearchAction.d.ts +2 -1
- package/build/src/modeling/actions/SearchAction.d.ts.map +1 -1
- package/build/src/modeling/actions/SearchAction.js +2 -2
- package/build/src/modeling/actions/SearchAction.js.map +1 -1
- package/build/src/modeling/actions/UpdateAction.d.ts +2 -1
- package/build/src/modeling/actions/UpdateAction.d.ts.map +1 -1
- package/build/src/modeling/actions/UpdateAction.js +2 -2
- package/build/src/modeling/actions/UpdateAction.js.map +1 -1
- package/build/src/modeling/actions/index.d.ts +2 -1
- package/build/src/modeling/actions/index.d.ts.map +1 -1
- package/build/src/modeling/actions/index.js +7 -7
- package/build/src/modeling/actions/index.js.map +1 -1
- package/build/src/modeling/index.d.ts +1 -0
- package/build/src/modeling/index.d.ts.map +1 -1
- package/build/src/modeling/index.js +1 -0
- package/build/src/modeling/index.js.map +1 -1
- package/build/src/modeling/types.d.ts +67 -0
- package/build/src/modeling/types.d.ts.map +1 -1
- package/build/src/modeling/types.js.map +1 -1
- package/build/src/modeling/validation/api_model_rules.d.ts +15 -0
- package/build/src/modeling/validation/api_model_rules.d.ts.map +1 -0
- package/build/src/modeling/validation/api_model_rules.js +599 -0
- package/build/src/modeling/validation/api_model_rules.js.map +1 -0
- package/build/src/modeling/validation/association_validation.d.ts.map +1 -1
- package/build/src/modeling/validation/association_validation.js +1 -3
- package/build/src/modeling/validation/association_validation.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/data/models/example-generator-api.json +8 -8
- package/eslint.config.js +0 -1
- package/package.json +17 -122
- package/src/decorators/observed.ts +91 -0
- package/src/modeling/ApiModel.ts +73 -33
- package/src/modeling/DomainValidation.ts +1 -1
- package/src/modeling/ExposedEntity.ts +63 -9
- package/src/modeling/actions/Action.ts +25 -2
- package/src/modeling/actions/CreateAction.ts +3 -2
- package/src/modeling/actions/DeleteAction.ts +3 -2
- package/src/modeling/actions/ListAction.ts +3 -2
- package/src/modeling/actions/ReadAction.ts +3 -2
- package/src/modeling/actions/SearchAction.ts +3 -2
- package/src/modeling/actions/UpdateAction.ts +3 -2
- package/src/modeling/types.ts +70 -0
- package/src/modeling/validation/api_model_rules.ts +640 -0
- package/src/modeling/validation/api_model_validation_rules.md +58 -0
- package/src/modeling/validation/association_validation.ts +1 -3
- package/tests/unit/modeling/actions/Action.spec.ts +40 -8
- package/tests/unit/modeling/actions/CreateAction.spec.ts +5 -5
- package/tests/unit/modeling/actions/DeleteAction.spec.ts +6 -6
- package/tests/unit/modeling/actions/ListAction.spec.ts +7 -7
- package/tests/unit/modeling/actions/ReadAction.spec.ts +6 -6
- package/tests/unit/modeling/actions/SearchAction.spec.ts +6 -6
- package/tests/unit/modeling/actions/UpdateAction.spec.ts +6 -6
- package/tests/unit/modeling/api_model.spec.ts +190 -13
- package/tests/unit/modeling/api_model_expose_entity.spec.ts +43 -19
- package/tests/unit/modeling/api_model_remove_entity.spec.ts +6 -6
- package/tests/unit/modeling/exposed_entity.spec.ts +123 -3
- package/tests/unit/modeling/exposed_entity_actions.spec.ts +41 -18
- package/tests/unit/modeling/exposed_entity_setter_validation.spec.ts +1 -1
- package/tests/unit/modeling/rules/restoring_rules.spec.ts +9 -5
- package/tests/unit/modeling/validation/api_model_rules.spec.ts +324 -0
- package/tsconfig.browser.json +1 -1
- package/tsconfig.node.json +1 -1
- package/bin/test-web.ts +0 -6
package/Testing.md
CHANGED
|
@@ -16,6 +16,6 @@ Most core libraries are also tested in the browser. We use the `@web/test-runner
|
|
|
16
16
|
|
|
17
17
|
### WTR Limitations
|
|
18
18
|
|
|
19
|
-
The web test runner requires an interactive mode to run. When using the watch mode we need to run two processes, one for compiling TS in watch mode, and the other to run tests in watch mode. This can't be done using `concurrently`
|
|
19
|
+
The web test runner requires an interactive mode to run. When using the watch mode we need to run two processes, one for compiling TS in watch mode, and the other to run tests in watch mode. This can't be done using `concurrently` as `concurrently` does not pass keyboard input to the process (perhaps a bug). There is an [https://github.com/modernweb-dev/web/issues/19](issue report) requesting to allow WTR running in non-interactive mode but for now we need to do this manually.
|
|
20
20
|
|
|
21
21
|
This means, run the `build:watch` command in one terminal first, and then `test:watch-only` in the other.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"observed.d.ts","sourceRoot":"","sources":["../../../src/decorators/observed.ts"],"names":[],"mappings":"AAKA,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;AAqCD;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,SAAS,CAwBzF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,QAAQ,CAAC,MAAM,GAAE,aAAkB,GAAG,iBAAiB,
|
|
1
|
+
{"version":3,"file":"observed.d.ts","sourceRoot":"","sources":["../../../src/decorators/observed.ts"],"names":[],"mappings":"AAKA,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;AAqCD;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,SAAS,CAwBzF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,QAAQ,CAAC,MAAM,GAAE,aAAkB,GAAG,iBAAiB,CA4MtE;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,KACpB,CAAC,SAAS,cAAc,EAAE,CAAC,SAAS,WAAW,GAAG,SAAS,EACjE,QAAQ,sBAAsB,CAAC,CAAC,EAAE,CAAC,CAAC,EACpC,SAAS,uBAAuB,CAAC,CAAC,EAAE,CAAC,CAAC,KACrC,GAAG,CAiEP"}
|
|
@@ -127,6 +127,74 @@ export function observed(config = {}) {
|
|
|
127
127
|
return target;
|
|
128
128
|
}
|
|
129
129
|
const value = Reflect.get(target, prop);
|
|
130
|
+
if (typeof value === 'function') {
|
|
131
|
+
if (target instanceof Map || target instanceof Set) {
|
|
132
|
+
if (['set', 'add', 'delete', 'clear'].includes(prop)) {
|
|
133
|
+
return (...args) => {
|
|
134
|
+
if (prop === 'set' && target.get(args[0]) === args[1]) {
|
|
135
|
+
return target;
|
|
136
|
+
}
|
|
137
|
+
if (prop === 'delete' && !target.has(args[0])) {
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
if (prop === 'clear' && target.size === 0) {
|
|
141
|
+
return undefined;
|
|
142
|
+
}
|
|
143
|
+
const result = value.apply(target, args);
|
|
144
|
+
notifyChange();
|
|
145
|
+
return result;
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
if (prop === 'get') {
|
|
149
|
+
return (...args) => {
|
|
150
|
+
const result = value.apply(target, args);
|
|
151
|
+
return createDeepProxy.bind(targetObject)(result, notifyChange);
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
if (prop === 'values' || prop === 'keys' || prop === 'entries') {
|
|
155
|
+
return (...args) => {
|
|
156
|
+
const iterator = value.apply(target, args);
|
|
157
|
+
return {
|
|
158
|
+
[Symbol.iterator]() {
|
|
159
|
+
return this;
|
|
160
|
+
},
|
|
161
|
+
next() {
|
|
162
|
+
const result = iterator.next();
|
|
163
|
+
if (result.done)
|
|
164
|
+
return result;
|
|
165
|
+
if (prop === 'entries') {
|
|
166
|
+
return {
|
|
167
|
+
done: false,
|
|
168
|
+
value: [result.value[0], createDeepProxy.bind(targetObject)(result.value[1], notifyChange)],
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
if (prop === 'keys') {
|
|
172
|
+
return result;
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
done: false,
|
|
176
|
+
value: createDeepProxy.bind(targetObject)(result.value, notifyChange),
|
|
177
|
+
};
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
if (prop === 'forEach') {
|
|
183
|
+
return (callback, thisArg) => {
|
|
184
|
+
value.call(target, (val, k, m) => {
|
|
185
|
+
callback.call(thisArg, createDeepProxy.bind(targetObject)(val, notifyChange), k, m);
|
|
186
|
+
});
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
return value.bind(target);
|
|
190
|
+
}
|
|
191
|
+
if (target instanceof WeakMap ||
|
|
192
|
+
target instanceof WeakSet ||
|
|
193
|
+
target instanceof Date ||
|
|
194
|
+
target instanceof RegExp) {
|
|
195
|
+
return value.bind(target);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
130
198
|
return createDeepProxy.bind(targetObject)(value, notifyChange);
|
|
131
199
|
},
|
|
132
200
|
set(target, prop, value) {
|
|
@@ -148,6 +216,29 @@ export function observed(config = {}) {
|
|
|
148
216
|
}
|
|
149
217
|
if (kind === 'accessor') {
|
|
150
218
|
return {
|
|
219
|
+
init(initialValue) {
|
|
220
|
+
let map = Reflect.get(this, reactiveSymbol);
|
|
221
|
+
if (!map) {
|
|
222
|
+
map = {};
|
|
223
|
+
Reflect.set(this, reactiveSymbol, map);
|
|
224
|
+
}
|
|
225
|
+
const notify = () => {
|
|
226
|
+
if (this.domain) {
|
|
227
|
+
this.domain.notifyChange();
|
|
228
|
+
}
|
|
229
|
+
else if (this.notifyChange) {
|
|
230
|
+
this.notifyChange();
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
let value = initialValue;
|
|
234
|
+
if (deep) {
|
|
235
|
+
value = createDeepProxy.bind(this)(initialValue, notify);
|
|
236
|
+
}
|
|
237
|
+
if (value !== undefined) {
|
|
238
|
+
map[context.name] = value;
|
|
239
|
+
}
|
|
240
|
+
return value;
|
|
241
|
+
},
|
|
151
242
|
set(value) {
|
|
152
243
|
let map = Reflect.get(this, reactiveSymbol);
|
|
153
244
|
if (!map) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"observed.js","sourceRoot":"","sources":["../../../src/decorators/observed.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nconst reactiveSymbol = Symbol('reactive')\nconst proxySymbol = Symbol('proxy')\nconst rawSymbol = Symbol('raw')\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\nfunction cleanProxies(obj: any, seen: WeakSet<object> = new WeakSet<object>()): any {\n if (typeof obj !== 'object' || obj === null) {\n return obj\n }\n if (seen.has(obj)) {\n return obj\n }\n seen.add(obj)\n\n if (Array.isArray(obj)) {\n for (let i = 0; i < obj.length; i++) {\n let item = obj[i]\n while (item && typeof item === 'object' && item[rawSymbol]) {\n item = item[rawSymbol]\n }\n if (item && typeof item === 'object') {\n cleanProxies(item, seen)\n }\n obj[i] = item\n }\n } else {\n for (const key of Object.keys(obj)) {\n let item = obj[key]\n while (item && typeof item === 'object' && item[rawSymbol]) {\n item = item[rawSymbol]\n }\n if (item && typeof item === 'object') {\n cleanProxies(item, seen)\n }\n obj[key] = item\n }\n }\n return obj\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 let mapped: any\n if (target && (target as any)[rawSymbol]) {\n let raw = (target as any)[rawSymbol]\n while (raw && (raw as any)[rawSymbol]) {\n raw = (raw as any)[rawSymbol]\n }\n mapped = raw\n } else {\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 mapped = key\n break\n }\n }\n }\n\n if (mapped) {\n return cleanProxies(mapped) as T\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 the `domain` 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 (the `domain` property).\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 proxies.get(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 if (prop === proxySymbol) {\n return Reflect.get(target, prop)\n }\n if (prop === rawSymbol) {\n return target\n }\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] === value) {\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 | undefined>(\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] === value) {\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"]}
|
|
1
|
+
{"version":3,"file":"observed.js","sourceRoot":"","sources":["../../../src/decorators/observed.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,MAAM,cAAc,GAAG,MAAM,CAAC,UAAU,CAAC,CAAA;AACzC,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,CAAA;AACnC,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;AA+B/B,SAAS,YAAY,CAAC,GAAQ,EAAE,OAAwB,IAAI,OAAO,EAAU;IAC3E,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QAC5C,OAAO,GAAG,CAAA;IACZ,CAAC;IACD,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QAClB,OAAO,GAAG,CAAA;IACZ,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAEb,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACpC,IAAI,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,CAAA;YACjB,OAAO,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC3D,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,CAAA;YACxB,CAAC;YACD,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACrC,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;YAC1B,CAAC;YACD,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;QACf,CAAC;IACH,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACnC,IAAI,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAA;YACnB,OAAO,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC3D,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,CAAA;YACxB,CAAC;YACD,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACrC,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;YAC1B,CAAC;YACD,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAA;QACjB,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,KAAK,CAA4B,MAAc,EAAE,MAAS;IACxE,IAAI,MAAW,CAAA;IACf,IAAI,MAAM,IAAK,MAAc,CAAC,SAAS,CAAC,EAAE,CAAC;QACzC,IAAI,GAAG,GAAI,MAAc,CAAC,SAAS,CAAC,CAAA;QACpC,OAAO,GAAG,IAAK,GAAW,CAAC,SAAS,CAAC,EAAE,CAAC;YACtC,GAAG,GAAI,GAAW,CAAC,SAAS,CAAC,CAAA;QAC/B,CAAC;QACD,MAAM,GAAG,GAAG,CAAA;IACd,CAAC;SAAM,CAAC;QACN,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,WAAW,CAAwB,CAAA;QACvE,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,SAAS,CAAA;QAClB,CAAC;QACD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;YAC7C,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;gBACrB,MAAM,GAAG,GAAG,CAAA;gBACZ,MAAK;YACP,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,YAAY,CAAC,MAAM,CAAM,CAAA;IAClC,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,UAAU,QAAQ,CAAC,SAAwB,EAAE;IACjD,OAAO,CACL,MAAoC,EACpC,OAAsC,EACjC,EAAE;QACP,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAA;QACxB,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,CAAA;QAEvB,SAAS,eAAe,CAAuB,GAAY,EAAE,YAAwB;YACnF,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;gBAC5C,OAAO,GAAG,CAAA;YACZ,CAAC;YACD,iEAAiE;YACjE,+DAA+D;YAC/D,4FAA4F;YAC5F,gDAAgD;YAChD,IAAI,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,WAAW,CAAwB,CAAA;YACnE,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,GAAG,IAAI,GAAG,EAAE,CAAA;gBACnB,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC,CAAA;YACzC,CAAC;YAED,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACrB,OAAO,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YACzB,CAAC;YAED,4DAA4D;YAC5D,MAAM,YAAY,GAAG,IAAI,CAAA;YAEzB,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,GAAG,EAAE;gBAC3B,GAAG,CAAC,MAAM,EAAE,IAAI;oBACd,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;wBACzB,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;oBAClC,CAAC;oBACD,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;wBACvB,OAAO,MAAM,CAAA;oBACf,CAAC;oBACD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;oBACvC,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE,CAAC;wBAChC,IAAI,MAAM,YAAY,GAAG,IAAI,MAAM,YAAY,GAAG,EAAE,CAAC;4BACnD,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,IAAc,CAAC,EAAE,CAAC;gCAC/D,OAAO,CAAC,GAAG,IAAW,EAAE,EAAE;oCACxB,IAAI,IAAI,KAAK,KAAK,IAAK,MAAwB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;wCACzE,OAAO,MAAM,CAAA;oCACf,CAAC;oCACD,IAAI,IAAI,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;wCAC9C,OAAO,KAAK,CAAA;oCACd,CAAC;oCACD,IAAI,IAAI,KAAK,OAAO,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;wCAC1C,OAAO,SAAS,CAAA;oCAClB,CAAC;oCACD,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;oCACxC,YAAY,EAAE,CAAA;oCACd,OAAO,MAAM,CAAA;gCACf,CAAC,CAAA;4BACH,CAAC;4BACD,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;gCACnB,OAAO,CAAC,GAAG,IAAW,EAAE,EAAE;oCACxB,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;oCACxC,OAAO,eAAe,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;gCACjE,CAAC,CAAA;4BACH,CAAC;4BACD,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gCAC/D,OAAO,CAAC,GAAG,IAAW,EAAE,EAAE;oCACxB,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;oCAC1C,OAAO;wCACL,CAAC,MAAM,CAAC,QAAQ,CAAC;4CACf,OAAO,IAAI,CAAA;wCACb,CAAC;wCACD,IAAI;4CACF,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAA;4CAC9B,IAAI,MAAM,CAAC,IAAI;gDAAE,OAAO,MAAM,CAAA;4CAC9B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gDACvB,OAAO;oDACL,IAAI,EAAE,KAAK;oDACX,KAAK,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,eAAe,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;iDAC5F,CAAA;4CACH,CAAC;4CACD,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;gDACpB,OAAO,MAAM,CAAA;4CACf,CAAC;4CACD,OAAO;gDACL,IAAI,EAAE,KAAK;gDACX,KAAK,EAAE,eAAe,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,YAAY,CAAC;6CACtE,CAAA;wCACH,CAAC;qCACF,CAAA;gCACH,CAAC,CAAA;4BACH,CAAC;4BACD,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gCACvB,OAAO,CAAC,QAAa,EAAE,OAAa,EAAE,EAAE;oCACtC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,GAAQ,EAAE,CAAM,EAAE,CAAM,EAAE,EAAE;wCAC9C,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,GAAG,EAAE,YAAY,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;oCACrF,CAAC,CAAC,CAAA;gCACJ,CAAC,CAAA;4BACH,CAAC;4BACD,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;wBAC3B,CAAC;wBACD,IACE,MAAM,YAAY,OAAO;4BACzB,MAAM,YAAY,OAAO;4BACzB,MAAM,YAAY,IAAI;4BACtB,MAAM,YAAY,MAAM,EACxB,CAAC;4BACD,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;wBAC3B,CAAC;oBACH,CAAC;oBACD,OAAO,eAAe,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,KAAK,EAAE,YAAY,CAAC,CAAA;gBAChE,CAAC;gBACD,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK;oBACrB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;oBAC1C,IAAI,QAAQ,KAAK,KAAK,EAAE,CAAC;wBACvB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,CAAA;wBAChC,YAAY,EAAE,CAAA;oBAChB,CAAC;oBACD,OAAO,IAAI,CAAA;gBACb,CAAC;gBACD,cAAc,CAAC,MAAM,EAAE,IAAI;oBACzB,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;oBACpC,YAAY,EAAE,CAAA;oBACd,OAAO,IAAI,CAAA;gBACb,CAAC;aACF,CAAC,CAAA;YACF,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;YACvB,OAAO,KAAK,CAAA;QACd,CAAC;QAED,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;YACxB,OAAO;gBACL,IAAI,CAAuB,YAAe;oBACxC,IAAI,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,cAAc,CAAC,CAAA;oBAC3C,IAAI,CAAC,GAAG,EAAE,CAAC;wBACT,GAAG,GAAG,EAAE,CAAA;wBACR,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,cAAc,EAAE,GAAG,CAAC,CAAA;oBACxC,CAAC;oBACD,MAAM,MAAM,GAAG,GAAG,EAAE;wBAClB,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;4BAChB,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAA;wBAC5B,CAAC;6BAAM,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;4BAC7B,IAAI,CAAC,YAAY,EAAE,CAAA;wBACrB,CAAC;oBACH,CAAC,CAAA;oBACD,IAAI,KAAK,GAAG,YAAY,CAAA;oBACxB,IAAI,IAAI,EAAE,CAAC;wBACT,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,MAAM,CAAC,CAAA;oBAC1D,CAAC;oBACD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;wBACxB,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,CAAA;oBAC3B,CAAC;oBACD,OAAO,KAAK,CAAA;gBACd,CAAC;gBACD,GAAG,CAAuB,KAAQ;oBAChC,IAAI,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,cAAc,CAAC,CAAA;oBAC3C,IAAI,CAAC,GAAG,EAAE,CAAC;wBACT,GAAG,GAAG,EAAE,CAAA;wBACR,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,cAAc,EAAE,GAAG,CAAC,CAAA;oBACxC,CAAC;oBACD,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,KAAK,EAAE,CAAC;wBAChC,OAAM;oBACR,CAAC;oBACD,MAAM,MAAM,GAAG,GAAG,EAAE;wBAClB,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;4BAChB,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAA;wBAC5B,CAAC;6BAAM,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;4BAC7B,IAAI,CAAC,YAAY,EAAE,CAAA;wBACrB,CAAC;oBACH,CAAC,CAAA;oBACD,IAAI,IAAI,EAAE,CAAC;wBACT,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;oBACnD,CAAC;oBACD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;wBACxB,gEAAgE;wBAChE,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;oBAC1B,CAAC;yBAAM,CAAC;wBACN,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,CAAA;oBAC3B,CAAC;oBACD,MAAM,EAAE,CAAA;gBACV,CAAC;gBAED,GAAG;oBACD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,cAAc,CAAC,IAAI,EAAE,CAAA;oBACnD,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;gBAC1B,CAAC;aACF,CAAA;QACH,CAAC;aAAM,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAA;YACxB,OAAO,UAAgC,KAAQ;gBAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAA4B,CAAC,CAAA;gBACnD,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;oBACvB,OAAM;gBACR,CAAC;gBACD,MAAM,MAAM,GAAG,GAAG,EAAE;oBAClB,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;wBAChB,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAA;oBAC5B,CAAC;yBAAM,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;wBAC7B,IAAI,CAAC,YAAY,EAAE,CAAA;oBACrB,CAAC;gBACH,CAAC,CACA;gBAAC,MAA6B,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;gBACjD,MAAM,EAAE,CAAA;YACV,CAAC,CAAA;QACH,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,mCAAmC,IAAI,EAAE,CAAC,CAAA;IAC5D,CAAC,CAAA;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO,CACL,MAAoC,EACpC,OAAsC,EACjC,EAAE;QACP,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAA;QACxB,SAAS,QAAQ;YACf,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBAChB,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAA;YAC5B,CAAC;QACH,CAAC;QACD,IAAI,OAAqD,CAAA;QACzD,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;YACxB,OAAO;gBACL,GAAG,CAAuB,KAAQ;oBAChC,IAAI,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,cAAc,CAAC,CAAA;oBAC3C,IAAI,CAAC,GAAG,EAAE,CAAC;wBACT,GAAG,GAAG,EAAE,CAAA;wBACR,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,cAAc,EAAE,GAAG,CAAC,CAAA;oBACxC,CAAC;oBACD,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,KAAK,EAAE,CAAC;wBAChC,OAAM;oBACR,CAAC;oBACD,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;oBAClC,IAAI,QAAQ,KAAK,KAAK,EAAE,CAAC;wBACvB,OAAM;oBACR,CAAC;oBACD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;wBACxB,gEAAgE;wBAChE,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;oBAC1B,CAAC;yBAAM,CAAC;wBACN,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,CAAA;oBAC3B,CAAC;oBACD,IAAI,QAAQ,IAAI,OAAO,EAAE,CAAC;wBACxB,QAAQ,CAAC,mBAAmB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;oBACjD,CAAC;oBACD,IAAI,KAAK,EAAE,CAAC;wBACV,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;wBAC7B,KAAK,CAAC,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;oBAC3C,CAAC;oBACD,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;wBAChB,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAA;oBAC5B,CAAC;gBACH,CAAC;gBAED,GAAG;oBACD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,cAAc,CAAC,IAAI,EAAE,CAAA;oBACnD,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;gBAC1B,CAAC;aACF,CAAA;QACH,CAAC;aAAM,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAA;YACxB,OAAO,UAAgC,KAAQ;gBAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAA4B,CAAiB,CAAA;gBACnE,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;oBACvB,OAAM;gBACR,CAAC;gBACD,CAAC;gBAAC,MAA6B,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;gBACjD,IAAI,QAAQ,IAAI,OAAO,EAAE,CAAC;oBACxB,QAAQ,CAAC,mBAAmB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;gBACjD,CAAC;gBACD,IAAI,KAAK,EAAE,CAAC;oBACV,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;oBAC7B,KAAK,CAAC,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;gBAC3C,CAAC;YACH,CAAC,CAAA;QACH,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,mCAAmC,IAAI,EAAE,CAAC,CAAA;IAC5D,CAAC,CAAA;AACH,CAAC","sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nconst reactiveSymbol = Symbol('reactive')\nconst proxySymbol = Symbol('proxy')\nconst rawSymbol = Symbol('raw')\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\nfunction cleanProxies(obj: any, seen: WeakSet<object> = new WeakSet<object>()): any {\n if (typeof obj !== 'object' || obj === null) {\n return obj\n }\n if (seen.has(obj)) {\n return obj\n }\n seen.add(obj)\n\n if (Array.isArray(obj)) {\n for (let i = 0; i < obj.length; i++) {\n let item = obj[i]\n while (item && typeof item === 'object' && item[rawSymbol]) {\n item = item[rawSymbol]\n }\n if (item && typeof item === 'object') {\n cleanProxies(item, seen)\n }\n obj[i] = item\n }\n } else {\n for (const key of Object.keys(obj)) {\n let item = obj[key]\n while (item && typeof item === 'object' && item[rawSymbol]) {\n item = item[rawSymbol]\n }\n if (item && typeof item === 'object') {\n cleanProxies(item, seen)\n }\n obj[key] = item\n }\n }\n return obj\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 let mapped: any\n if (target && (target as any)[rawSymbol]) {\n let raw = (target as any)[rawSymbol]\n while (raw && (raw as any)[rawSymbol]) {\n raw = (raw as any)[rawSymbol]\n }\n mapped = raw\n } else {\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 mapped = key\n break\n }\n }\n }\n\n if (mapped) {\n return cleanProxies(mapped) as T\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 the `domain` 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 (the `domain` property).\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 proxies.get(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 if (prop === proxySymbol) {\n return Reflect.get(target, prop)\n }\n if (prop === rawSymbol) {\n return target\n }\n const value = Reflect.get(target, prop)\n if (typeof value === 'function') {\n if (target instanceof Map || target instanceof Set) {\n if (['set', 'add', 'delete', 'clear'].includes(prop as string)) {\n return (...args: any[]) => {\n if (prop === 'set' && (target as Map<any, any>).get(args[0]) === args[1]) {\n return target\n }\n if (prop === 'delete' && !target.has(args[0])) {\n return false\n }\n if (prop === 'clear' && target.size === 0) {\n return undefined\n }\n const result = value.apply(target, args)\n notifyChange()\n return result\n }\n }\n if (prop === 'get') {\n return (...args: any[]) => {\n const result = value.apply(target, args)\n return createDeepProxy.bind(targetObject)(result, notifyChange)\n }\n }\n if (prop === 'values' || prop === 'keys' || prop === 'entries') {\n return (...args: any[]) => {\n const iterator = value.apply(target, args)\n return {\n [Symbol.iterator]() {\n return this\n },\n next() {\n const result = iterator.next()\n if (result.done) return result\n if (prop === 'entries') {\n return {\n done: false,\n value: [result.value[0], createDeepProxy.bind(targetObject)(result.value[1], notifyChange)],\n }\n }\n if (prop === 'keys') {\n return result\n }\n return {\n done: false,\n value: createDeepProxy.bind(targetObject)(result.value, notifyChange),\n }\n },\n }\n }\n }\n if (prop === 'forEach') {\n return (callback: any, thisArg?: any) => {\n value.call(target, (val: any, k: any, m: any) => {\n callback.call(thisArg, createDeepProxy.bind(targetObject)(val, notifyChange), k, m)\n })\n }\n }\n return value.bind(target)\n }\n if (\n target instanceof WeakMap ||\n target instanceof WeakSet ||\n target instanceof Date ||\n target instanceof RegExp\n ) {\n return value.bind(target)\n }\n }\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 init(this: DomainInstance, initialValue: V): V {\n let map = Reflect.get(this, reactiveSymbol)\n if (!map) {\n map = {}\n Reflect.set(this, reactiveSymbol, map)\n }\n const notify = () => {\n if (this.domain) {\n this.domain.notifyChange()\n } else if (this.notifyChange) {\n this.notifyChange()\n }\n }\n let value = initialValue\n if (deep) {\n value = createDeepProxy.bind(this)(initialValue, notify)\n }\n if (value !== undefined) {\n map[context.name] = value\n }\n return value\n },\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] === value) {\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 | undefined>(\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] === value) {\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"]}
|
|
@@ -144,8 +144,10 @@ export declare class ApiModel extends DependentModel {
|
|
|
144
144
|
/**
|
|
145
145
|
* The specific subset of Data Entities to be exposed by this API.
|
|
146
146
|
* These are the entities that are included in the data domain schema.
|
|
147
|
+
*
|
|
148
|
+
* The `key` is the key of the exposed entity. Using a Map to allow for quick lookups.
|
|
147
149
|
*/
|
|
148
|
-
accessor exposes: ExposedEntity
|
|
150
|
+
accessor exposes: Map<string, ExposedEntity>;
|
|
149
151
|
/**
|
|
150
152
|
* Optional array of access rules that define the access control policies
|
|
151
153
|
* for the API. These rules are used to enforce security and permissions
|
|
@@ -219,12 +221,6 @@ export declare class ApiModel extends DependentModel {
|
|
|
219
221
|
*/
|
|
220
222
|
removeExposedEntity(key: string): void;
|
|
221
223
|
private removeWithChildren;
|
|
222
|
-
/**
|
|
223
|
-
* Returns the exposed entity by its key.
|
|
224
|
-
* @param entityKey The key of the entity to find.
|
|
225
|
-
* @returns The exposed entity or undefined if not found.
|
|
226
|
-
*/
|
|
227
|
-
getExposedEntity(entity: AssociationTarget): ExposedEntity | undefined;
|
|
228
224
|
/**
|
|
229
225
|
* Clears the API model for a new data domain change.
|
|
230
226
|
* This method resets the dependencies, exposes, user,
|
|
@@ -239,5 +235,23 @@ export declare class ApiModel extends DependentModel {
|
|
|
239
235
|
* @throws Error if the domain does not have a version set in its info.
|
|
240
236
|
*/
|
|
241
237
|
attachDataDomain(domain: DataDomain): void;
|
|
238
|
+
/**
|
|
239
|
+
* Finds an existing root exposed entity that has the given resource path.
|
|
240
|
+
* Useful for detecting path collisions when adding or updating an exposed entity.
|
|
241
|
+
*
|
|
242
|
+
* @param path The resource path to check for collisions.
|
|
243
|
+
* @param ignore Optional key of an exposed entity to ignore during the check (usually the entity being updated).
|
|
244
|
+
* @returns The colliding `ExposedEntity` if found, otherwise `undefined`.
|
|
245
|
+
*/
|
|
246
|
+
findResourcePathCollision(path: string, ignore?: string): ExposedEntity | undefined;
|
|
247
|
+
/**
|
|
248
|
+
* Finds an existing root exposed entity that has the given collection path.
|
|
249
|
+
* Useful for detecting path collisions when adding or updating an exposed entity.
|
|
250
|
+
*
|
|
251
|
+
* @param path The collection path to check for collisions.
|
|
252
|
+
* @param ignore Optional key of an exposed entity to ignore during the check (usually the entity being updated).
|
|
253
|
+
* @returns The colliding `ExposedEntity` if found, otherwise `undefined`.
|
|
254
|
+
*/
|
|
255
|
+
findCollectionPathCollision(path: string, ignore?: string): ExposedEntity | undefined;
|
|
242
256
|
}
|
|
243
257
|
//# sourceMappingURL=ApiModel.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApiModel.d.ts","sourceRoot":"","sources":["../../../src/modeling/ApiModel.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAqC,MAAM,oBAAoB,CAAA;AACpF,OAAO,EAAE,KAAK,MAAM,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AACvD,OAAO,KAAK,EACV,iBAAiB,EACjB,2BAA2B,EAC3B,0BAA0B,EAC1B,mBAAmB,EAEnB,oBAAoB,EAEpB,aAAa,EACd,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,cAAc,EAAE,KAAK,oBAAoB,EAAE,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAItG,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACpE,OAAO,EAAE,yBAAyB,EAAE,+BAA+B,EAAE,MAAM,sCAAsC,CAAA;AAGjH;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,cAAe,SAAQ,oBAAoB;IAC1D;;OAEG;IACH,IAAI,EAAE,OAAO,YAAY,CAAA;IACzB;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAA;IACX;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IAEZ;;;;;OAKG;IACH,IAAI,CAAC,EAAE,iBAAiB,CAAA;IAExB;;;OAGG;IACH,cAAc,CAAC,EAAE,2BAA2B,CAAA;IAE5C;;;OAGG;IACH,aAAa,CAAC,EAAE,0BAA0B,CAAA;IAE1C;;;OAGG;IACH,OAAO,CAAC,EAAE,oBAAoB,CAAA;IAC9B;;;OAGG;IACH,OAAO,EAAE,mBAAmB,EAAE,CAAA;IAE9B;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,gBAAgB,EAAE,CAAA;IAC/B;;;OAGG;IACH,YAAY,CAAC,EAAE,+BAA+B,CAAA;IAC9C;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;OAEG;IACH,OAAO,CAAC,EAAE,UAAU,CAAA;IACpB;;OAEG;IACH,OAAO,CAAC,EAAE,UAAU,CAAA;CACrB;AAED,qBAAa,QAAS,SAAQ,cAAc;;IAC1C;;OAEG;IACH,IAAI,EAAE,OAAO,YAAY,CAAA;IACzB;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAA;IAEX;;OAEG;IACH,IAAI,EAAE,KAAK,CAAA;IACX;;;;;OAKG;IACH,IAAI,CAAC,EAAE,iBAAiB,CAAA;IAExB;;;OAGG;IACH,cAAc,CAAC,EAAE,2BAA2B,CAAA;IAE5C;;;OAGG;IACH,aAAa,CAAC,EAAE,0BAA0B,CAAA;IAE1C;;;OAGG;IACH,OAAO,CAAC,EAAE,oBAAoB,CAAA;IAC9B
|
|
1
|
+
{"version":3,"file":"ApiModel.d.ts","sourceRoot":"","sources":["../../../src/modeling/ApiModel.ts"],"names":[],"mappings":"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"}
|
|
@@ -86,6 +86,8 @@ let ApiModel = (() => {
|
|
|
86
86
|
/**
|
|
87
87
|
* The specific subset of Data Entities to be exposed by this API.
|
|
88
88
|
* These are the entities that are included in the data domain schema.
|
|
89
|
+
*
|
|
90
|
+
* The `key` is the key of the exposed entity. Using a Map to allow for quick lookups.
|
|
89
91
|
*/
|
|
90
92
|
get exposes() { return this.#exposes_accessor_storage; }
|
|
91
93
|
set exposes(value) { this.#exposes_accessor_storage = value; }
|
|
@@ -230,10 +232,10 @@ let ApiModel = (() => {
|
|
|
230
232
|
this.session = structuredClone(init.session);
|
|
231
233
|
}
|
|
232
234
|
if (Array.isArray(init.exposes)) {
|
|
233
|
-
this.exposes = init.exposes.map((e) => new ExposedEntity(this, e));
|
|
235
|
+
this.exposes = new Map(init.exposes.map((e) => [e.key, new ExposedEntity(this, e)]));
|
|
234
236
|
}
|
|
235
237
|
else {
|
|
236
|
-
this.exposes =
|
|
238
|
+
this.exposes = new Map();
|
|
237
239
|
}
|
|
238
240
|
if (Array.isArray(init.accessRule)) {
|
|
239
241
|
this.accessRule = init.accessRule.map((rule) => restoreAccessRule(rule));
|
|
@@ -263,7 +265,7 @@ let ApiModel = (() => {
|
|
|
263
265
|
kind: this.kind,
|
|
264
266
|
key: this.key,
|
|
265
267
|
info: this.info.toJSON(),
|
|
266
|
-
exposes: this.exposes.map((e) => e.toJSON()),
|
|
268
|
+
exposes: Array.from(this.exposes.values()).map((e) => e.toJSON()),
|
|
267
269
|
};
|
|
268
270
|
if (this.user) {
|
|
269
271
|
result.user = { ...this.user };
|
|
@@ -331,7 +333,13 @@ let ApiModel = (() => {
|
|
|
331
333
|
throw new Error(`No domain attached to API model`);
|
|
332
334
|
}
|
|
333
335
|
// checks whether the entity is already exposed as a root exposure.
|
|
334
|
-
|
|
336
|
+
let existing;
|
|
337
|
+
for (const exp of this.exposes.values()) {
|
|
338
|
+
if (exp.isRoot && exp.entity.key === entity.key) {
|
|
339
|
+
existing = exp;
|
|
340
|
+
break;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
335
343
|
if (existing) {
|
|
336
344
|
// quietly return the existing exposure
|
|
337
345
|
// TBD: should we throw an error here?
|
|
@@ -348,7 +356,7 @@ let ApiModel = (() => {
|
|
|
348
356
|
// Check for root path collision and resolve by appending a number
|
|
349
357
|
let counter = 1;
|
|
350
358
|
const originalCollectionPath = relativeCollectionPath;
|
|
351
|
-
while (this.
|
|
359
|
+
while (this.findCollectionPathCollision(relativeCollectionPath)) {
|
|
352
360
|
relativeCollectionPath = `${originalCollectionPath}-${counter}`;
|
|
353
361
|
relativeResourcePath = `${relativeCollectionPath}/{id}`;
|
|
354
362
|
counter++;
|
|
@@ -367,7 +375,7 @@ let ApiModel = (() => {
|
|
|
367
375
|
newEntity.exposeOptions = { ...options };
|
|
368
376
|
}
|
|
369
377
|
const created = new ExposedEntity(this, newEntity);
|
|
370
|
-
this.exposes.
|
|
378
|
+
this.exposes.set(created.key, created);
|
|
371
379
|
// Follow associations if requested
|
|
372
380
|
if (options?.followAssociations) {
|
|
373
381
|
if (options?.maxDepth === undefined || options.maxDepth > 0) {
|
|
@@ -408,7 +416,13 @@ let ApiModel = (() => {
|
|
|
408
416
|
continue;
|
|
409
417
|
}
|
|
410
418
|
// Check if this entity is ALREADY exposed anywhere in the model
|
|
411
|
-
|
|
419
|
+
let existingExposure;
|
|
420
|
+
for (const exp of this.exposes.values()) {
|
|
421
|
+
if (exp.entity.key === target.key) {
|
|
422
|
+
existingExposure = exp;
|
|
423
|
+
break;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
412
426
|
if (existingExposure) {
|
|
413
427
|
// If it's already exposed and NOT root (i.e., it's currently a nested child of someone else),
|
|
414
428
|
// promote it to ROOT to avoid duplicating it or deeply nesting it in multiple places.
|
|
@@ -422,7 +436,7 @@ let ApiModel = (() => {
|
|
|
422
436
|
let relativeResourcePath = `/${segment}/{id}`;
|
|
423
437
|
let counter = 1;
|
|
424
438
|
const originalCollectionPath = relativeCollectionPath;
|
|
425
|
-
while (this.
|
|
439
|
+
while (this.findResourcePathCollision(relativeCollectionPath)) {
|
|
426
440
|
relativeCollectionPath = `${originalCollectionPath}-${counter}`;
|
|
427
441
|
relativeResourcePath = `${relativeCollectionPath}/{id}`;
|
|
428
442
|
counter++;
|
|
@@ -466,7 +480,8 @@ let ApiModel = (() => {
|
|
|
466
480
|
depth: depth + 1,
|
|
467
481
|
},
|
|
468
482
|
};
|
|
469
|
-
|
|
483
|
+
const inst = new ExposedEntity(this, nestedExposure);
|
|
484
|
+
this.exposes.set(inst.key, inst);
|
|
470
485
|
if (depth + 1 >= maxDepth) {
|
|
471
486
|
nestedExposure.truncated = true;
|
|
472
487
|
}
|
|
@@ -489,28 +504,24 @@ let ApiModel = (() => {
|
|
|
489
504
|
* @param key The key of the exposed entity to remove.
|
|
490
505
|
*/
|
|
491
506
|
removeExposedEntity(key) {
|
|
492
|
-
|
|
493
|
-
if (index < 0) {
|
|
507
|
+
if (!this.exposes.has(key)) {
|
|
494
508
|
throw new Error(`Exposed entity with key "${key}" not found.`);
|
|
495
509
|
}
|
|
496
510
|
this.removeWithChildren(key);
|
|
497
511
|
}
|
|
498
512
|
removeWithChildren(key) {
|
|
499
|
-
|
|
500
|
-
if (index < 0) {
|
|
513
|
+
if (!this.exposes.has(key)) {
|
|
501
514
|
return;
|
|
502
515
|
}
|
|
503
516
|
// Remove the parent itself
|
|
504
|
-
this.exposes.
|
|
517
|
+
this.exposes.delete(key);
|
|
505
518
|
// Remove all children recursively
|
|
506
519
|
const removeChildren = (parentKey) => {
|
|
507
520
|
// Find all exposures whose parent.key matches parentKey
|
|
508
|
-
const
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
if (childIndex >= 0) {
|
|
513
|
-
this.exposes.splice(childIndex, 1);
|
|
521
|
+
for (const child of this.exposes.values()) {
|
|
522
|
+
if (child.parent?.key === parentKey) {
|
|
523
|
+
removeChildren(child.key);
|
|
524
|
+
this.exposes.delete(child.key);
|
|
514
525
|
}
|
|
515
526
|
}
|
|
516
527
|
};
|
|
@@ -518,14 +529,6 @@ let ApiModel = (() => {
|
|
|
518
529
|
removeChildren(key);
|
|
519
530
|
this.notifyChange();
|
|
520
531
|
}
|
|
521
|
-
/**
|
|
522
|
-
* Returns the exposed entity by its key.
|
|
523
|
-
* @param entityKey The key of the entity to find.
|
|
524
|
-
* @returns The exposed entity or undefined if not found.
|
|
525
|
-
*/
|
|
526
|
-
getExposedEntity(entity) {
|
|
527
|
-
return this.exposes.find((e) => e.entity.key === entity.key && e.entity.domain === entity.domain);
|
|
528
|
-
}
|
|
529
532
|
/**
|
|
530
533
|
* Clears the API model for a new data domain change.
|
|
531
534
|
* This method resets the dependencies, exposes, user,
|
|
@@ -534,7 +537,7 @@ let ApiModel = (() => {
|
|
|
534
537
|
cleanForDomainChange() {
|
|
535
538
|
this.dependencies.clear();
|
|
536
539
|
this.dependencyList = [];
|
|
537
|
-
this.exposes =
|
|
540
|
+
this.exposes = new Map();
|
|
538
541
|
this.user = undefined;
|
|
539
542
|
if (this.session) {
|
|
540
543
|
this.session.properties = [];
|
|
@@ -564,6 +567,44 @@ let ApiModel = (() => {
|
|
|
564
567
|
this.dependencyList = [{ key: domain.key, version: domain.info.version }];
|
|
565
568
|
this.notifyChange();
|
|
566
569
|
}
|
|
570
|
+
/**
|
|
571
|
+
* Finds an existing root exposed entity that has the given resource path.
|
|
572
|
+
* Useful for detecting path collisions when adding or updating an exposed entity.
|
|
573
|
+
*
|
|
574
|
+
* @param path The resource path to check for collisions.
|
|
575
|
+
* @param ignore Optional key of an exposed entity to ignore during the check (usually the entity being updated).
|
|
576
|
+
* @returns The colliding `ExposedEntity` if found, otherwise `undefined`.
|
|
577
|
+
*/
|
|
578
|
+
findResourcePathCollision(path, ignore) {
|
|
579
|
+
for (const e of this.exposes.values()) {
|
|
580
|
+
if (ignore && e.key === ignore) {
|
|
581
|
+
continue;
|
|
582
|
+
}
|
|
583
|
+
if (e.isRoot && e.resourcePath === path) {
|
|
584
|
+
return e;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
return undefined;
|
|
588
|
+
}
|
|
589
|
+
/**
|
|
590
|
+
* Finds an existing root exposed entity that has the given collection path.
|
|
591
|
+
* Useful for detecting path collisions when adding or updating an exposed entity.
|
|
592
|
+
*
|
|
593
|
+
* @param path The collection path to check for collisions.
|
|
594
|
+
* @param ignore Optional key of an exposed entity to ignore during the check (usually the entity being updated).
|
|
595
|
+
* @returns The colliding `ExposedEntity` if found, otherwise `undefined`.
|
|
596
|
+
*/
|
|
597
|
+
findCollectionPathCollision(path, ignore) {
|
|
598
|
+
for (const e of this.exposes.values()) {
|
|
599
|
+
if (ignore && e.key === ignore) {
|
|
600
|
+
continue;
|
|
601
|
+
}
|
|
602
|
+
if (e.isRoot && e.hasCollection && e.collectionPath === path) {
|
|
603
|
+
return e;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
return undefined;
|
|
607
|
+
}
|
|
567
608
|
};
|
|
568
609
|
})();
|
|
569
610
|
export { ApiModel };
|