adaptive-extender 0.10.5 → 0.11.1
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 +12 -1
- package/README.md +3 -3
- package/dist/core/array.d.ts +6 -0
- package/dist/core/array.js +18 -0
- package/dist/core/array.js.map +1 -1
- package/dist/core/bigint.js +1 -0
- package/dist/core/boolean.js +1 -0
- package/dist/core/color.js +1 -0
- package/dist/core/controller.js +1 -0
- package/dist/core/date.d.ts +10 -1
- package/dist/core/date.js +34 -0
- package/dist/core/date.js.map +1 -1
- package/dist/core/engine.js +1 -0
- package/dist/core/environment.js +1 -0
- package/dist/core/error.js +1 -0
- package/dist/core/function.js +1 -0
- package/dist/core/global.js +1 -1
- package/dist/core/index.js +1 -0
- package/dist/core/map.d.ts +14 -1
- package/dist/core/map.js +48 -1
- package/dist/core/map.js.map +1 -1
- package/dist/core/math.d.ts +5 -0
- package/dist/core/math.js +18 -6
- package/dist/core/math.js.map +1 -1
- package/dist/core/number.js +1 -0
- package/dist/core/object.js +1 -0
- package/dist/core/portable.d.ts +72 -47
- package/dist/core/portable.js +250 -315
- package/dist/core/portable.js.map +1 -1
- package/dist/core/primitives.js +1 -0
- package/dist/core/promise.js +1 -0
- package/dist/core/random.js +1 -0
- package/dist/core/reflect.d.ts +0 -20
- package/dist/core/reflect.js +1 -15
- package/dist/core/reflect.js.map +1 -1
- package/dist/core/set.d.ts +8 -1
- package/dist/core/set.js +18 -1
- package/dist/core/set.js.map +1 -1
- package/dist/core/string.js +1 -0
- package/dist/core/timespan.js +1 -0
- package/dist/core/vector-1.js +1 -0
- package/dist/core/vector-2.js +1 -0
- package/dist/core/vector-3.js +1 -0
- package/dist/core/vector.js +1 -0
- package/dist/core/version.js +1 -0
- package/dist/node/index.js +1 -0
- package/dist/web/archive.d.ts +68 -11
- package/dist/web/archive.js +60 -44
- package/dist/web/archive.js.map +1 -1
- package/dist/web/element.js +1 -0
- package/dist/web/engine.js +1 -0
- package/dist/web/index.d.ts +0 -1
- package/dist/web/index.js +1 -0
- package/dist/web/index.js.map +1 -1
- package/dist/web/metadata-injector.js +17 -16
- package/dist/web/metadata-injector.js.map +1 -1
- package/dist/web/parent-node.js +1 -0
- package/dist/web/promise.js +1 -0
- package/dist/worker/engine.js +1 -0
- package/dist/worker/index.js +1 -0
- package/dist/worker/promise.js +1 -0
- package/package.json +2 -1
- package/tsconfig.base.json +4 -0
- package/dist/web/url.d.ts +0 -1
- package/dist/web/url.js +0 -17
- package/dist/web/url.js.map +0 -1
package/dist/core/portable.js
CHANGED
|
@@ -9,28 +9,35 @@ import "./reflect.js";
|
|
|
9
9
|
import "./error.js";
|
|
10
10
|
import {} from "./global.js";
|
|
11
11
|
//#endregion
|
|
12
|
-
//#region
|
|
12
|
+
//#region Descriptors
|
|
13
|
+
Reflect.set(Symbol, "metadata", Reflect.get(Symbol, "metadata") ?? Symbol.for("Symbol.metadata"));
|
|
13
14
|
class FieldDescriptor {
|
|
14
15
|
#key;
|
|
15
16
|
#association;
|
|
16
17
|
#type;
|
|
17
|
-
|
|
18
|
+
#hasFallback = false;
|
|
19
|
+
#fallback;
|
|
20
|
+
constructor(key, type, options = {}) {
|
|
18
21
|
this.#key = key;
|
|
19
|
-
this.#association =
|
|
22
|
+
this.#association = options.name ?? key;
|
|
20
23
|
this.#type = type;
|
|
24
|
+
if (!("fallback" in options))
|
|
25
|
+
return;
|
|
26
|
+
this.#hasFallback = true;
|
|
27
|
+
this.#fallback = type.export(options.fallback);
|
|
21
28
|
}
|
|
22
|
-
get key() {
|
|
23
|
-
|
|
29
|
+
get key() { return this.#key; }
|
|
30
|
+
get association() { return this.#association; }
|
|
31
|
+
import(object, name) {
|
|
32
|
+
const association = this.#association;
|
|
33
|
+
const raw = Reflect.get(object, association);
|
|
34
|
+
const source = raw === undefined && this.#hasFallback ? this.#fallback : raw;
|
|
35
|
+
return this.#type.import(source, `${name}.${association}`);
|
|
24
36
|
}
|
|
25
|
-
|
|
26
|
-
return this.#
|
|
27
|
-
}
|
|
28
|
-
get type() {
|
|
29
|
-
return this.#type;
|
|
37
|
+
export(source) {
|
|
38
|
+
return this.#type.export(Reflect.get(source, this.#key));
|
|
30
39
|
}
|
|
31
40
|
}
|
|
32
|
-
//#endregion
|
|
33
|
-
//#region Descendant descriptor
|
|
34
41
|
class DescendantDescriptor {
|
|
35
42
|
#type;
|
|
36
43
|
#discriminator;
|
|
@@ -38,15 +45,99 @@ class DescendantDescriptor {
|
|
|
38
45
|
this.#type = type;
|
|
39
46
|
this.#discriminator = discriminator;
|
|
40
47
|
}
|
|
41
|
-
get
|
|
42
|
-
|
|
48
|
+
get discriminator() { return this.#discriminator ?? this.#type.name; }
|
|
49
|
+
accepts(discriminator) {
|
|
50
|
+
return this.discriminator === discriminator;
|
|
51
|
+
}
|
|
52
|
+
owns(instance) {
|
|
53
|
+
return instance instanceof this.#type;
|
|
43
54
|
}
|
|
44
|
-
|
|
45
|
-
return this.#
|
|
55
|
+
import(source, name) {
|
|
56
|
+
return this.#type.import(source, name);
|
|
57
|
+
}
|
|
58
|
+
export(source) {
|
|
59
|
+
return this.#type.export(source);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
class ModelSchema {
|
|
63
|
+
static #schemas = new WeakMap();
|
|
64
|
+
static #collect(object) {
|
|
65
|
+
const fields = new Map();
|
|
66
|
+
let current = object;
|
|
67
|
+
while (current !== null) {
|
|
68
|
+
for (const [key, descriptor] of PortabilityMetadata.for(current).fields)
|
|
69
|
+
fields.add(key, descriptor);
|
|
70
|
+
current = Object.getPrototypeOf(current);
|
|
71
|
+
}
|
|
72
|
+
return fields;
|
|
73
|
+
}
|
|
74
|
+
static resolve(model) {
|
|
75
|
+
const schemas = ModelSchema.#schemas;
|
|
76
|
+
let schema = schemas.get(model);
|
|
77
|
+
if (schema !== undefined)
|
|
78
|
+
return schema;
|
|
79
|
+
const object = ReferenceError.suppress(model[Symbol.metadata], `Required an implementation of Symbol.metadata in '${model.name}' to use portability`);
|
|
80
|
+
const { discriminator, descendants } = Object.hasOwn(model, Symbol.metadata)
|
|
81
|
+
? PortabilityMetadata.for(object)
|
|
82
|
+
: new PortabilityMetadata();
|
|
83
|
+
schema = descendants.length > 0
|
|
84
|
+
? new PolymorphicSchema(discriminator, descendants)
|
|
85
|
+
: new ConcreteSchema(model, ModelSchema.#collect(object));
|
|
86
|
+
schemas.set(model, schema);
|
|
87
|
+
return schema;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
class ConcreteSchema extends ModelSchema {
|
|
91
|
+
#model;
|
|
92
|
+
#fields;
|
|
93
|
+
constructor(model, fields) {
|
|
94
|
+
super();
|
|
95
|
+
this.#model = model;
|
|
96
|
+
this.#fields = fields;
|
|
97
|
+
}
|
|
98
|
+
import(source, name) {
|
|
99
|
+
const object = Object.import(source, name);
|
|
100
|
+
const instance = Reflect.construct(this.#model, []);
|
|
101
|
+
for (const descriptor of this.#fields.values())
|
|
102
|
+
Reflect.set(instance, descriptor.key, descriptor.import(object, name));
|
|
103
|
+
return instance;
|
|
104
|
+
}
|
|
105
|
+
export(source) {
|
|
106
|
+
const target = new Object();
|
|
107
|
+
for (const descriptor of this.#fields.values())
|
|
108
|
+
Reflect.set(target, descriptor.association, descriptor.export(source));
|
|
109
|
+
return target;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
class PolymorphicSchema extends ModelSchema {
|
|
113
|
+
#discriminator;
|
|
114
|
+
#descendants;
|
|
115
|
+
constructor(discriminator, descendants) {
|
|
116
|
+
super();
|
|
117
|
+
this.#discriminator = discriminator;
|
|
118
|
+
this.#descendants = descendants;
|
|
119
|
+
}
|
|
120
|
+
import(source, name) {
|
|
121
|
+
const key = this.#discriminator;
|
|
122
|
+
const object = Object.import(source, name);
|
|
123
|
+
const value = Reflect.get(object, key);
|
|
124
|
+
if (value === undefined)
|
|
125
|
+
throw new TypeError(`Missing '${key}' discriminator in ${name}`);
|
|
126
|
+
const discriminator = String.import(value, `${name}.${key}`);
|
|
127
|
+
const descriptor = this.#descendants.find(descendant => descendant.accepts(discriminator));
|
|
128
|
+
if (descriptor === undefined)
|
|
129
|
+
throw new TypeError(`Unknown '${discriminator}' discriminator for ${name}`);
|
|
130
|
+
return descriptor.import(source, name);
|
|
131
|
+
}
|
|
132
|
+
export(source) {
|
|
133
|
+
const descriptor = this.#descendants.find(descendant => descendant.owns(source));
|
|
134
|
+
if (descriptor === undefined)
|
|
135
|
+
throw new TypeError(`Invalid '${typename(source)}' type for source`);
|
|
136
|
+
const exported = descriptor.export(source);
|
|
137
|
+
Reflect.set(exported, this.#discriminator, descriptor.discriminator);
|
|
138
|
+
return exported;
|
|
46
139
|
}
|
|
47
140
|
}
|
|
48
|
-
//#endregion
|
|
49
|
-
//#region Portability metadata
|
|
50
141
|
class PortabilityMetadata {
|
|
51
142
|
static #registry = new WeakMap();
|
|
52
143
|
#fields = new Map();
|
|
@@ -61,40 +152,10 @@ class PortabilityMetadata {
|
|
|
61
152
|
registry.set(metadata, entry);
|
|
62
153
|
return entry;
|
|
63
154
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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
|
-
}
|
|
76
|
-
return metadata;
|
|
77
|
-
}
|
|
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;
|
|
85
|
-
}
|
|
86
|
-
get fields() {
|
|
87
|
-
return this.#fields;
|
|
88
|
-
}
|
|
89
|
-
get descendants() {
|
|
90
|
-
return this.#descendants;
|
|
91
|
-
}
|
|
92
|
-
get discriminator() {
|
|
93
|
-
return this.#discriminator;
|
|
94
|
-
}
|
|
95
|
-
set discriminator(value) {
|
|
96
|
-
this.#discriminator = value;
|
|
97
|
-
}
|
|
155
|
+
get fields() { return this.#fields; }
|
|
156
|
+
get descendants() { return this.#descendants; }
|
|
157
|
+
get discriminator() { return this.#discriminator; }
|
|
158
|
+
set discriminator(value) { this.#discriminator = value; }
|
|
98
159
|
}
|
|
99
160
|
//#endregion
|
|
100
161
|
//#region Model
|
|
@@ -110,89 +171,28 @@ export class Model {
|
|
|
110
171
|
* @throws {TypeError} If validation fails or types do not match.
|
|
111
172
|
*/
|
|
112
173
|
static import(source, name) {
|
|
113
|
-
|
|
114
|
-
const descendants = PortabilityMetadata.descendantsOf(model);
|
|
115
|
-
if (descendants.length > 0) {
|
|
116
|
-
const { discriminator: key } = PortabilityMetadata.read(model);
|
|
117
|
-
const object = Object.import(source, name);
|
|
118
|
-
const value = Reflect.get(object, key);
|
|
119
|
-
if (value === undefined)
|
|
120
|
-
throw new TypeError(`Missing '${key}' discriminator in ${name}`);
|
|
121
|
-
const discriminator = String.import(value, `${name}.${key}`);
|
|
122
|
-
const descriptor = descendants.find(descriptor => descriptor.discriminator === discriminator);
|
|
123
|
-
if (descriptor === undefined)
|
|
124
|
-
throw new TypeError(`Unknown '${discriminator}' discriminator for ${name}`);
|
|
125
|
-
return descriptor.type.import(source, name);
|
|
126
|
-
}
|
|
127
|
-
const object = Object.import(source, name);
|
|
128
|
-
const instance = Reflect.construct(this, []);
|
|
129
|
-
const { fields } = PortabilityMetadata.read(model);
|
|
130
|
-
for (const { key, association, type } of fields.values()) {
|
|
131
|
-
const raw = Reflect.get(object, association);
|
|
132
|
-
const value = type.import(raw, `${name}.${association}`);
|
|
133
|
-
Reflect.set(instance, key, value);
|
|
134
|
-
}
|
|
135
|
-
return instance;
|
|
174
|
+
return ModelSchema.resolve(this).import(source, name);
|
|
136
175
|
}
|
|
137
176
|
/**
|
|
138
177
|
* Serializes the model instance to a raw object.
|
|
139
178
|
* @param source The model instance to export.
|
|
140
179
|
*/
|
|
141
180
|
static export(source) {
|
|
142
|
-
|
|
143
|
-
const descendants = PortabilityMetadata.descendantsOf(model);
|
|
144
|
-
if (descendants.length > 0) {
|
|
145
|
-
const { discriminator: key } = PortabilityMetadata.read(model);
|
|
146
|
-
const descriptor = descendants.find(descriptor => source instanceof descriptor.type);
|
|
147
|
-
if (descriptor === undefined)
|
|
148
|
-
throw new TypeError(`Invalid '${typename(source)}' type for source`);
|
|
149
|
-
const descendant = descriptor.type;
|
|
150
|
-
const exported = descendant.export(source);
|
|
151
|
-
Reflect.set(exported, key, descriptor.discriminator);
|
|
152
|
-
return exported;
|
|
153
|
-
}
|
|
154
|
-
const object = new Object();
|
|
155
|
-
const { fields } = PortabilityMetadata.read(model);
|
|
156
|
-
for (const { key, association, type } of fields.values()) {
|
|
157
|
-
const value = Reflect.get(source, key);
|
|
158
|
-
const raw = type.export(value);
|
|
159
|
-
Reflect.set(object, association, raw);
|
|
160
|
-
}
|
|
161
|
-
return object;
|
|
181
|
+
return ModelSchema.resolve(this).export(source);
|
|
162
182
|
}
|
|
163
183
|
}
|
|
164
|
-
export function Field(type,
|
|
184
|
+
export function Field(type, options = {}) {
|
|
165
185
|
return function (_, context) {
|
|
166
186
|
if (context.static)
|
|
167
187
|
throw new TypeError("Portable fields cannot be static");
|
|
168
188
|
const key = context.name;
|
|
169
189
|
if (typeof (key) === "symbol")
|
|
170
190
|
throw new TypeError("Symbols are not supported as portable keys");
|
|
171
|
-
const association = name ?? key;
|
|
172
191
|
const { fields } = PortabilityMetadata.for(context.metadata);
|
|
173
192
|
if (!fields.has(key))
|
|
174
|
-
fields.set(key, new FieldDescriptor(key,
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
export function Descendant(descendant, discriminator) {
|
|
178
|
-
return function (model, context) {
|
|
179
|
-
void model;
|
|
180
|
-
const { descendants } = PortabilityMetadata.for(context.metadata);
|
|
181
|
-
descendants.push(new DescendantDescriptor(descendant, discriminator));
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* Decorator to register a custom discriminator key for the polymorphic model.
|
|
186
|
-
* @param key The property key to use for the discriminator.
|
|
187
|
-
*/
|
|
188
|
-
export function DiscriminatorKey(key) {
|
|
189
|
-
return function (model, context) {
|
|
190
|
-
void model;
|
|
191
|
-
PortabilityMetadata.for(context.metadata).discriminator = key;
|
|
193
|
+
fields.set(key, new FieldDescriptor(key, type, options));
|
|
192
194
|
};
|
|
193
195
|
}
|
|
194
|
-
//#endregion
|
|
195
|
-
//#region Adapters
|
|
196
196
|
/**
|
|
197
197
|
* Creates a wrapper for circular or deferred type references.
|
|
198
198
|
* @param resolver Function that returns the actual type constructor.
|
|
@@ -213,224 +213,159 @@ export function Deferred(resolver) {
|
|
|
213
213
|
},
|
|
214
214
|
};
|
|
215
215
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
return {
|
|
222
|
-
[Symbol.hasInstance](instance) {
|
|
223
|
-
return instance === undefined || type[Symbol.hasInstance](instance);
|
|
224
|
-
},
|
|
225
|
-
get name() {
|
|
226
|
-
return `${type.name} | undefined`;
|
|
227
|
-
},
|
|
228
|
-
import(source, name) {
|
|
229
|
-
return Reflect.mapUndefined(source, source => type.import(source, name));
|
|
230
|
-
},
|
|
231
|
-
export(source) {
|
|
232
|
-
return Reflect.mapUndefined(source, source => type.export(source));
|
|
233
|
-
},
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* Creates a portable wrapper for nullable types.
|
|
238
|
-
* @param type The inner portable type.
|
|
239
|
-
*/
|
|
240
|
-
export function Nullable(type) {
|
|
241
|
-
return {
|
|
242
|
-
[Symbol.hasInstance](instance) {
|
|
243
|
-
return instance === null || type[Symbol.hasInstance](instance);
|
|
244
|
-
},
|
|
245
|
-
get name() {
|
|
246
|
-
return `${type.name} | null`;
|
|
247
|
-
},
|
|
248
|
-
import(source, name) {
|
|
249
|
-
return Reflect.mapNull(source, source => type.import(source, name));
|
|
250
|
-
},
|
|
251
|
-
export(source) {
|
|
252
|
-
return Reflect.mapNull(source, source => type.export(source));
|
|
253
|
-
},
|
|
254
|
-
};
|
|
255
|
-
}
|
|
256
|
-
/**
|
|
257
|
-
* Creates a portable wrapper for array types.
|
|
258
|
-
* @param type The portable type of the array elements.
|
|
259
|
-
*/
|
|
260
|
-
export function ArrayOf(type) {
|
|
261
|
-
return {
|
|
262
|
-
[Symbol.hasInstance](instance) {
|
|
263
|
-
return Array[Symbol.hasInstance](instance);
|
|
264
|
-
},
|
|
265
|
-
get name() {
|
|
266
|
-
return `${type.name}[]`;
|
|
267
|
-
},
|
|
268
|
-
import(source, name) {
|
|
269
|
-
return Array.import(source, name).map((item, index) => type.import(item, `${name}[${index}]`));
|
|
270
|
-
},
|
|
271
|
-
export(source) {
|
|
272
|
-
return source.map(item => type.export(item));
|
|
273
|
-
},
|
|
216
|
+
export function Descendant(descendant, discriminator) {
|
|
217
|
+
return function (model, context) {
|
|
218
|
+
void model;
|
|
219
|
+
const { descendants } = PortabilityMetadata.for(context.metadata);
|
|
220
|
+
descendants.push(new DescendantDescriptor(descendant, discriminator));
|
|
274
221
|
};
|
|
275
222
|
}
|
|
276
223
|
/**
|
|
277
|
-
*
|
|
278
|
-
* @param
|
|
224
|
+
* Decorator to register a custom discriminator key for the polymorphic model.
|
|
225
|
+
* @param key The property key to use for the discriminator.
|
|
279
226
|
*/
|
|
280
|
-
export function
|
|
281
|
-
return {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
},
|
|
285
|
-
get name() {
|
|
286
|
-
return `Set<${type.name}>`;
|
|
287
|
-
},
|
|
288
|
-
import(source, name) {
|
|
289
|
-
return new Set(Array.import(source, name).map((item, index) => type.import(item, `${name}[${index}]`)));
|
|
290
|
-
},
|
|
291
|
-
export(source) {
|
|
292
|
-
return Array.from(source, item => type.export(item));
|
|
293
|
-
},
|
|
227
|
+
export function DiscriminatorKey(key) {
|
|
228
|
+
return function (model, context) {
|
|
229
|
+
void model;
|
|
230
|
+
PortabilityMetadata.for(context.metadata).discriminator = key;
|
|
294
231
|
};
|
|
295
232
|
}
|
|
233
|
+
//#endregion
|
|
234
|
+
//#region Adapters
|
|
296
235
|
/**
|
|
297
|
-
*
|
|
298
|
-
*
|
|
236
|
+
* Portable adapter class for optional (possibly-undefined) types.
|
|
237
|
+
* Use `Optional.Of(type)` to wrap an adapter, and `Optional.map` for conditional mapping.
|
|
299
238
|
*/
|
|
300
|
-
export
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
}
|
|
323
|
-
}
|
|
239
|
+
export class Optional {
|
|
240
|
+
constructor() {
|
|
241
|
+
throw new TypeError("Unable to create an instance of a static class");
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Creates a portable wrapper for optional types.
|
|
245
|
+
* @param type The inner portable type.
|
|
246
|
+
*/
|
|
247
|
+
static Of(type) {
|
|
248
|
+
return {
|
|
249
|
+
[Symbol.hasInstance](instance) {
|
|
250
|
+
return type[Symbol.hasInstance](instance);
|
|
251
|
+
},
|
|
252
|
+
get name() {
|
|
253
|
+
return `${type.name} | undefined`;
|
|
254
|
+
},
|
|
255
|
+
import(source, name) {
|
|
256
|
+
return Optional.map(source, source => type.import(source, name));
|
|
257
|
+
},
|
|
258
|
+
export(source) {
|
|
259
|
+
return Optional.map(source, source => type.export(source));
|
|
260
|
+
},
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Applies a callback to a non-undefined value, or passes through `undefined` unchanged.
|
|
265
|
+
* @param value The value to map.
|
|
266
|
+
* @param callback The function to apply if the value is not undefined.
|
|
267
|
+
*/
|
|
268
|
+
static map(value, callback) {
|
|
269
|
+
if (value === undefined)
|
|
270
|
+
return value;
|
|
271
|
+
return callback(value);
|
|
272
|
+
}
|
|
324
273
|
}
|
|
325
274
|
/**
|
|
326
|
-
*
|
|
327
|
-
*
|
|
328
|
-
* @param value The portable type of the map values.
|
|
275
|
+
* Portable adapter class for nullable (possibly-null) types.
|
|
276
|
+
* Use `Nullable.Of(type)` to wrap an adapter, and `Nullable.map` for conditional mapping.
|
|
329
277
|
*/
|
|
330
|
-
export
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
278
|
+
export class Nullable {
|
|
279
|
+
constructor() {
|
|
280
|
+
throw new TypeError("Unable to create an instance of a static class");
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Creates a portable wrapper for nullable types.
|
|
284
|
+
* @param type The inner portable type.
|
|
285
|
+
*/
|
|
286
|
+
static Of(type) {
|
|
287
|
+
return {
|
|
288
|
+
[Symbol.hasInstance](instance) {
|
|
289
|
+
return type[Symbol.hasInstance](instance);
|
|
290
|
+
},
|
|
291
|
+
get name() {
|
|
292
|
+
return `${type.name} | null`;
|
|
293
|
+
},
|
|
294
|
+
import(source, name) {
|
|
295
|
+
return Nullable.map(source, source => type.import(source, name));
|
|
296
|
+
},
|
|
297
|
+
export(source) {
|
|
298
|
+
return Nullable.map(source, source => type.export(source));
|
|
299
|
+
},
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Applies a callback to a non-null value, or passes through `null` unchanged.
|
|
304
|
+
* @param value The value to map.
|
|
305
|
+
* @param callback The function to apply if the value is not null.
|
|
306
|
+
*/
|
|
307
|
+
static map(value, callback) {
|
|
308
|
+
if (value === null)
|
|
309
|
+
return value;
|
|
310
|
+
return callback(value);
|
|
311
|
+
}
|
|
350
312
|
}
|
|
351
313
|
/**
|
|
352
|
-
*
|
|
353
|
-
*
|
|
314
|
+
* Portable adapter class for enum types.
|
|
315
|
+
* Use `Enum.Of(reference)` to create an adapter that validates against enum values.
|
|
354
316
|
*/
|
|
355
|
-
export
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
317
|
+
export class Enum {
|
|
318
|
+
constructor() {
|
|
319
|
+
throw new TypeError("Unable to create an instance of a static class");
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Creates a portable wrapper for enum types, strictly operating only on enum values.
|
|
323
|
+
* @param reference The enum object reference.
|
|
324
|
+
*/
|
|
325
|
+
static Of(reference) {
|
|
326
|
+
const values = new Set();
|
|
327
|
+
for (const [key, value] of Object.entries(reference)) {
|
|
328
|
+
const index = Number(key);
|
|
329
|
+
if (String(index) === key && typeof value === "string" && Reflect.get(reference, value) === index)
|
|
330
|
+
continue;
|
|
331
|
+
values.add(value);
|
|
332
|
+
}
|
|
333
|
+
return {
|
|
334
|
+
[Symbol.hasInstance](instance) {
|
|
335
|
+
return values.has(instance);
|
|
336
|
+
},
|
|
337
|
+
get name() {
|
|
338
|
+
return "Enum";
|
|
339
|
+
},
|
|
340
|
+
import(source, name) {
|
|
341
|
+
if (!values.has(source))
|
|
342
|
+
throw new TypeError(`Unable to import enum from ${name} due to invalid value`);
|
|
343
|
+
return source;
|
|
344
|
+
},
|
|
345
|
+
export(source) {
|
|
346
|
+
return source;
|
|
347
|
+
},
|
|
348
|
+
};
|
|
362
349
|
}
|
|
363
|
-
return {
|
|
364
|
-
[Symbol.hasInstance](instance) {
|
|
365
|
-
return values.has(instance);
|
|
366
|
-
},
|
|
367
|
-
get name() {
|
|
368
|
-
return "Enum";
|
|
369
|
-
},
|
|
370
|
-
import(source, name) {
|
|
371
|
-
if (!values.has(source))
|
|
372
|
-
throw new TypeError(`Unable to import enum from ${name} due to invalid value`);
|
|
373
|
-
return source;
|
|
374
|
-
},
|
|
375
|
-
export(source) {
|
|
376
|
-
return source;
|
|
377
|
-
},
|
|
378
|
-
};
|
|
379
350
|
}
|
|
380
351
|
/**
|
|
381
|
-
*
|
|
382
|
-
|
|
383
|
-
export const Timestamp = {
|
|
384
|
-
[Symbol.hasInstance](instance) {
|
|
385
|
-
return Date[Symbol.hasInstance](instance);
|
|
386
|
-
},
|
|
387
|
-
get name() {
|
|
388
|
-
return "Timestamp";
|
|
389
|
-
},
|
|
390
|
-
import(source, name) {
|
|
391
|
-
if (typeof (source) !== "number")
|
|
392
|
-
throw new TypeError(`Unable to import date from ${name} due its ${typename(source)} type`);
|
|
393
|
-
return new Date(source);
|
|
394
|
-
},
|
|
395
|
-
export(source) {
|
|
396
|
-
return source.getTime();
|
|
397
|
-
},
|
|
398
|
-
};
|
|
399
|
-
/**
|
|
400
|
-
* A portable adapter that facilitates the conversion between `Date` instances and Unix second timestamps.
|
|
401
|
-
*/
|
|
402
|
-
export const UnixSeconds = {
|
|
403
|
-
[Symbol.hasInstance](instance) {
|
|
404
|
-
return Date[Symbol.hasInstance](instance);
|
|
405
|
-
},
|
|
406
|
-
get name() {
|
|
407
|
-
return "UnixSeconds";
|
|
408
|
-
},
|
|
409
|
-
import(source, name) {
|
|
410
|
-
if (typeof (source) !== "number")
|
|
411
|
-
throw new TypeError(`Unable to import date from ${name} due its ${typename(source)} type`);
|
|
412
|
-
return new Date(source * 1000);
|
|
413
|
-
},
|
|
414
|
-
export(source) {
|
|
415
|
-
return Math.trunc(source.getTime() / 1000);
|
|
416
|
-
},
|
|
417
|
-
};
|
|
418
|
-
/**
|
|
419
|
-
* A portable adapter that allows any value to pass through without validation or transformation.
|
|
352
|
+
* Portable adapter class for unknown/any types.
|
|
353
|
+
* Pass `Any` directly to `@Field` to allow any value without validation or transformation.
|
|
420
354
|
*/
|
|
421
|
-
export
|
|
422
|
-
|
|
355
|
+
export class Any {
|
|
356
|
+
constructor() {
|
|
357
|
+
throw new TypeError("Unable to create an instance of a static class");
|
|
358
|
+
}
|
|
359
|
+
static [Symbol.hasInstance](instance) {
|
|
423
360
|
void instance;
|
|
424
361
|
return true;
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
return "Any";
|
|
428
|
-
},
|
|
429
|
-
import(source, name) {
|
|
362
|
+
}
|
|
363
|
+
static import(source, name) {
|
|
430
364
|
void name;
|
|
431
365
|
return source;
|
|
432
|
-
}
|
|
433
|
-
export(source) {
|
|
366
|
+
}
|
|
367
|
+
static export(source) {
|
|
434
368
|
return source;
|
|
435
|
-
}
|
|
436
|
-
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
//# sourceMappingURL=portable.js.map
|