adaptive-extender 0.10.3 → 0.10.5
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/CHANGELOG.md +3 -0
- package/dist/core/global.js +1 -0
- package/dist/core/portable.js +40 -24
- package/package.json +4 -6
- package/tsconfig.base.json +27 -27
package/CHANGELOG.md
CHANGED
package/dist/core/global.js
CHANGED
package/dist/core/portable.js
CHANGED
|
@@ -4,7 +4,9 @@ import "./string.js";
|
|
|
4
4
|
import "./boolean.js";
|
|
5
5
|
import "./array.js";
|
|
6
6
|
import "./object.js";
|
|
7
|
+
import "./map.js";
|
|
7
8
|
import "./reflect.js";
|
|
9
|
+
import "./error.js";
|
|
8
10
|
import {} from "./global.js";
|
|
9
11
|
//#endregion
|
|
10
12
|
//#region Field descriptor
|
|
@@ -47,24 +49,39 @@ class DescendantDescriptor {
|
|
|
47
49
|
//#region Portability metadata
|
|
48
50
|
class PortabilityMetadata {
|
|
49
51
|
static #registry = new WeakMap();
|
|
50
|
-
#model;
|
|
51
52
|
#fields = new Map();
|
|
52
53
|
#descendants = [];
|
|
53
54
|
#discriminator = "$type";
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
static for(metadata) {
|
|
56
|
+
const registry = PortabilityMetadata.#registry;
|
|
57
|
+
let entry = registry.get(metadata);
|
|
58
|
+
if (entry !== undefined)
|
|
59
|
+
return entry;
|
|
60
|
+
entry = new PortabilityMetadata();
|
|
61
|
+
registry.set(metadata, entry);
|
|
62
|
+
return entry;
|
|
56
63
|
}
|
|
57
64
|
static read(model) {
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
65
|
+
const object = ReferenceError.suppress(model[Symbol.metadata], `Required an implementation of Symbol.metadata in '${model.name}' to use portability`);
|
|
66
|
+
const metadata = PortabilityMetadata.for(object);
|
|
67
|
+
const fields = metadata.#fields;
|
|
68
|
+
let current = object;
|
|
69
|
+
while (true) {
|
|
70
|
+
if (current === null)
|
|
71
|
+
break;
|
|
72
|
+
for (const [key, descriptor] of PortabilityMetadata.for(current).#fields)
|
|
73
|
+
fields.add(key, descriptor);
|
|
74
|
+
current = Object.getPrototypeOf(current);
|
|
75
|
+
}
|
|
64
76
|
return metadata;
|
|
65
77
|
}
|
|
66
|
-
|
|
67
|
-
|
|
78
|
+
static descendantsOf(model) {
|
|
79
|
+
if (!Object.hasOwn(model, Symbol.metadata))
|
|
80
|
+
return [];
|
|
81
|
+
const object = model[Symbol.metadata];
|
|
82
|
+
if (object === null || object === undefined)
|
|
83
|
+
return [];
|
|
84
|
+
return PortabilityMetadata.for(object).#descendants;
|
|
68
85
|
}
|
|
69
86
|
get fields() {
|
|
70
87
|
return this.#fields;
|
|
@@ -94,8 +111,9 @@ export class Model {
|
|
|
94
111
|
*/
|
|
95
112
|
static import(source, name) {
|
|
96
113
|
const model = this;
|
|
97
|
-
const
|
|
114
|
+
const descendants = PortabilityMetadata.descendantsOf(model);
|
|
98
115
|
if (descendants.length > 0) {
|
|
116
|
+
const { discriminator: key } = PortabilityMetadata.read(model);
|
|
99
117
|
const object = Object.import(source, name);
|
|
100
118
|
const value = Reflect.get(object, key);
|
|
101
119
|
if (value === undefined)
|
|
@@ -122,8 +140,9 @@ export class Model {
|
|
|
122
140
|
*/
|
|
123
141
|
static export(source) {
|
|
124
142
|
const model = this;
|
|
125
|
-
const
|
|
143
|
+
const descendants = PortabilityMetadata.descendantsOf(model);
|
|
126
144
|
if (descendants.length > 0) {
|
|
145
|
+
const { discriminator: key } = PortabilityMetadata.read(model);
|
|
127
146
|
const descriptor = descendants.find(descriptor => source instanceof descriptor.type);
|
|
128
147
|
if (descriptor === undefined)
|
|
129
148
|
throw new TypeError(`Invalid '${typename(source)}' type for source`);
|
|
@@ -150,18 +169,15 @@ export function Field(type, name) {
|
|
|
150
169
|
if (typeof (key) === "symbol")
|
|
151
170
|
throw new TypeError("Symbols are not supported as portable keys");
|
|
152
171
|
const association = name ?? key;
|
|
153
|
-
context.
|
|
154
|
-
|
|
155
|
-
const { fields } = PortabilityMetadata.read(model);
|
|
156
|
-
if (fields.has(key))
|
|
157
|
-
return;
|
|
172
|
+
const { fields } = PortabilityMetadata.for(context.metadata);
|
|
173
|
+
if (!fields.has(key))
|
|
158
174
|
fields.set(key, new FieldDescriptor(key, association, type));
|
|
159
|
-
});
|
|
160
175
|
};
|
|
161
176
|
}
|
|
162
177
|
export function Descendant(descendant, discriminator) {
|
|
163
|
-
return function (model) {
|
|
164
|
-
|
|
178
|
+
return function (model, context) {
|
|
179
|
+
void model;
|
|
180
|
+
const { descendants } = PortabilityMetadata.for(context.metadata);
|
|
165
181
|
descendants.push(new DescendantDescriptor(descendant, discriminator));
|
|
166
182
|
};
|
|
167
183
|
}
|
|
@@ -170,9 +186,9 @@ export function Descendant(descendant, discriminator) {
|
|
|
170
186
|
* @param key The property key to use for the discriminator.
|
|
171
187
|
*/
|
|
172
188
|
export function DiscriminatorKey(key) {
|
|
173
|
-
return function (model) {
|
|
174
|
-
|
|
175
|
-
metadata.discriminator = key;
|
|
189
|
+
return function (model, context) {
|
|
190
|
+
void model;
|
|
191
|
+
PortabilityMetadata.for(context.metadata).discriminator = key;
|
|
176
192
|
};
|
|
177
193
|
}
|
|
178
194
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "adaptive-extender",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.5",
|
|
4
4
|
"description": "Adaptive library for JS/TS development environments",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/core/index.js",
|
|
@@ -57,16 +57,14 @@
|
|
|
57
57
|
"build:web": "tsc -p ./src/web/tsconfig.json",
|
|
58
58
|
"build:worker": "tsc -p ./src/worker/tsconfig.json",
|
|
59
59
|
"build": "npm run build:core && npm run build:node && npm run build:web && npm run build:worker",
|
|
60
|
-
"test": "vitest run",
|
|
60
|
+
"test": "npm run build & vitest run",
|
|
61
61
|
"coverage": "vitest run --coverage"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
|
-
"@babel/plugin-proposal-decorators": "^7.29.7",
|
|
65
|
-
"@rolldown/plugin-babel": "^0.2.3",
|
|
66
64
|
"@types/jsdom": "^21.1.7",
|
|
67
65
|
"esbuild": "^0.28.0",
|
|
68
66
|
"jsdom": "^27.0.0",
|
|
69
|
-
"typescript": "^
|
|
70
|
-
"vitest": "^4.
|
|
67
|
+
"typescript": "^5.9.3",
|
|
68
|
+
"vitest": "^4.0.10"
|
|
71
69
|
}
|
|
72
70
|
}
|
package/tsconfig.base.json
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
/* Language & Environment */
|
|
4
|
-
"target": "ES2022",
|
|
5
|
-
"module": "ESNext",
|
|
6
|
-
"useDefineForClassFields": true,
|
|
7
|
-
|
|
8
|
-
/* Module Resolution / Bundler */
|
|
9
|
-
"moduleResolution": "bundler",
|
|
10
|
-
"moduleDetection": "force",
|
|
11
|
-
"verbatimModuleSyntax": true,
|
|
12
|
-
|
|
13
|
-
/* Interop & Compatibility */
|
|
14
|
-
"esModuleInterop": true,
|
|
15
|
-
"allowJs": true,
|
|
16
|
-
"skipLibCheck": false,
|
|
17
|
-
|
|
18
|
-
/* Type Checking & Linting */
|
|
19
|
-
"strict": true,
|
|
20
|
-
"strictPropertyInitialization": false,
|
|
21
|
-
"noUnusedLocals": false,
|
|
22
|
-
"noUnusedParameters": false,
|
|
23
|
-
|
|
24
|
-
/* Miscellaneous */
|
|
25
|
-
"forceConsistentCasingInFileNames": true,
|
|
26
|
-
}
|
|
27
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
/* Language & Environment */
|
|
4
|
+
"target": "ES2022",
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"useDefineForClassFields": true,
|
|
7
|
+
|
|
8
|
+
/* Module Resolution / Bundler */
|
|
9
|
+
"moduleResolution": "bundler",
|
|
10
|
+
"moduleDetection": "force",
|
|
11
|
+
"verbatimModuleSyntax": true,
|
|
12
|
+
|
|
13
|
+
/* Interop & Compatibility */
|
|
14
|
+
"esModuleInterop": true,
|
|
15
|
+
"allowJs": true,
|
|
16
|
+
"skipLibCheck": false,
|
|
17
|
+
|
|
18
|
+
/* Type Checking & Linting */
|
|
19
|
+
"strict": true,
|
|
20
|
+
"strictPropertyInitialization": false,
|
|
21
|
+
"noUnusedLocals": false,
|
|
22
|
+
"noUnusedParameters": false,
|
|
23
|
+
|
|
24
|
+
/* Miscellaneous */
|
|
25
|
+
"forceConsistentCasingInFileNames": true,
|
|
26
|
+
}
|
|
27
|
+
}
|