@colyseus/schema 5.0.1 → 5.0.3
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/build/Metadata.d.ts +7 -0
- package/build/Reflection.d.ts +18 -2
- package/build/index.cjs +53 -11
- package/build/index.cjs.map +1 -1
- package/build/index.d.ts +1 -1
- package/build/index.js +53 -11
- package/build/index.mjs +53 -11
- package/build/index.mjs.map +1 -1
- package/build/input/index.cjs +28 -11
- package/build/input/index.cjs.map +1 -1
- package/build/input/index.mjs +28 -11
- package/build/input/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/Metadata.ts +44 -22
- package/src/Reflection.ts +46 -1
- package/src/index.ts +1 -1
package/package.json
CHANGED
package/src/Metadata.ts
CHANGED
|
@@ -329,6 +329,49 @@ export const Metadata = {
|
|
|
329
329
|
return metadata?.[$streamPriorities]?.[index];
|
|
330
330
|
},
|
|
331
331
|
|
|
332
|
+
/**
|
|
333
|
+
* Install a single field with full encoder wiring: accessor descriptor
|
|
334
|
+
* on the prototype + `metadata[$encoders]` slot for primitives. Shared
|
|
335
|
+
* between `Metadata.setFields` (build path) and
|
|
336
|
+
* `Reflection.makeEncodable` (Reflection upgrade path).
|
|
337
|
+
*/
|
|
338
|
+
defineField(
|
|
339
|
+
target: any,
|
|
340
|
+
metadata: any,
|
|
341
|
+
fieldIndex: number,
|
|
342
|
+
fieldName: string,
|
|
343
|
+
type: DefinitionType,
|
|
344
|
+
) {
|
|
345
|
+
const normalized = getNormalizedType(type);
|
|
346
|
+
const { complexTypeKlass, childType } = resolveFieldType(normalized);
|
|
347
|
+
|
|
348
|
+
Metadata.addField(
|
|
349
|
+
metadata,
|
|
350
|
+
fieldIndex,
|
|
351
|
+
fieldName,
|
|
352
|
+
normalized,
|
|
353
|
+
getPropertyDescriptor(fieldName, fieldIndex, childType, complexTypeKlass),
|
|
354
|
+
);
|
|
355
|
+
|
|
356
|
+
// Install accessor descriptor on the prototype (once per class field).
|
|
357
|
+
if (metadata[$descriptors][fieldName]) {
|
|
358
|
+
Object.defineProperty(target.prototype, fieldName, metadata[$descriptors][fieldName]);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// Pre-compute encoder function for primitive types.
|
|
362
|
+
if (typeof normalized === "string") {
|
|
363
|
+
if (!metadata[$encoders]) {
|
|
364
|
+
Object.defineProperty(metadata, $encoders, {
|
|
365
|
+
value: [],
|
|
366
|
+
enumerable: false,
|
|
367
|
+
configurable: true,
|
|
368
|
+
writable: true,
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
metadata[$encoders][fieldIndex] = (encode as any)[normalized];
|
|
372
|
+
}
|
|
373
|
+
},
|
|
374
|
+
|
|
332
375
|
setFields<T extends { new (...args: any[]): InstanceType<T> } = any>(target: T, fields: { [field in keyof InstanceType<T>]?: DefinitionType }) {
|
|
333
376
|
// for inheritance support
|
|
334
377
|
const constructor = target.prototype.constructor;
|
|
@@ -364,28 +407,7 @@ export const Metadata = {
|
|
|
364
407
|
}
|
|
365
408
|
|
|
366
409
|
for (const field in fields) {
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
const { complexTypeKlass, childType } = resolveFieldType(type);
|
|
370
|
-
|
|
371
|
-
Metadata.addField(
|
|
372
|
-
metadata,
|
|
373
|
-
fieldIndex,
|
|
374
|
-
field,
|
|
375
|
-
type,
|
|
376
|
-
getPropertyDescriptor(field, fieldIndex, childType, complexTypeKlass)
|
|
377
|
-
);
|
|
378
|
-
|
|
379
|
-
// Install accessor descriptor on the prototype (once per class field).
|
|
380
|
-
if (metadata[$descriptors][field]) {
|
|
381
|
-
Object.defineProperty(target.prototype, field, metadata[$descriptors][field]);
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
// Pre-compute encoder function for primitive types.
|
|
385
|
-
if (typeof type === "string") {
|
|
386
|
-
metadata[$encoders][fieldIndex] = (encode as any)[type];
|
|
387
|
-
}
|
|
388
|
-
|
|
410
|
+
Metadata.defineField(constructor, metadata, fieldIndex, field, fields[field] as DefinitionType);
|
|
389
411
|
fieldIndex++;
|
|
390
412
|
}
|
|
391
413
|
|
package/src/Reflection.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { Decoder } from "./decoder/Decoder.js";
|
|
|
7
7
|
import { Schema } from "./Schema.js";
|
|
8
8
|
import { t, FieldBuilder } from "./types/builder.js";
|
|
9
9
|
import { ArraySchema } from "./types/custom/ArraySchema.js";
|
|
10
|
+
import { $encodeDescriptor, $numFields } from "./types/symbols.js";
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Static methods available on Reflection
|
|
@@ -29,6 +30,23 @@ interface ReflectionStatic {
|
|
|
29
30
|
* @returns Decoder instance
|
|
30
31
|
*/
|
|
31
32
|
decode: <T extends Schema = Schema>(bytes: Uint8Array, it?: Iterator) => Decoder<T>;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Upgrade a class produced by `Reflection.decode` so its instances
|
|
36
|
+
* can be used as encode sources (for `InputEncoder` or `Encoder`).
|
|
37
|
+
*
|
|
38
|
+
* `Reflection.decode` reconstructs classes with decoder-only field
|
|
39
|
+
* slots — `inst.x = 7` lands as a direct own property and bypasses
|
|
40
|
+
* the change-tracking + `$values` plumbing that encoders rely on.
|
|
41
|
+
* Calling `makeEncodable(ctor)` installs the same prototype accessor
|
|
42
|
+
* descriptors and `metadata[$encoders]` lookup table that the
|
|
43
|
+
* `schema(...)` / `@type` builders install at class-definition time.
|
|
44
|
+
*
|
|
45
|
+
* Idempotent. Pay-as-you-go: callers that only decode never invoke
|
|
46
|
+
* this and pay nothing extra. Must be called BEFORE any instance of
|
|
47
|
+
* the class is constructed and assigned to.
|
|
48
|
+
*/
|
|
49
|
+
makeEncodable: (ctor: typeof Schema) => typeof Schema;
|
|
32
50
|
}
|
|
33
51
|
|
|
34
52
|
/**
|
|
@@ -249,4 +267,31 @@ Reflection.decode = function <T extends Schema = Schema>(bytes: Uint8Array, it?:
|
|
|
249
267
|
const state: T = new (typeContext.get(reflection.rootType || 0) as unknown as any)();
|
|
250
268
|
|
|
251
269
|
return new Decoder<T>(state, typeContext);
|
|
252
|
-
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
Reflection.makeEncodable = function (ctor: typeof Schema): typeof Schema {
|
|
273
|
+
const metadata: any = (ctor as any)[Symbol.metadata];
|
|
274
|
+
if (!metadata) return ctor;
|
|
275
|
+
|
|
276
|
+
const numFields = metadata[$numFields];
|
|
277
|
+
if (numFields === undefined) return ctor;
|
|
278
|
+
|
|
279
|
+
// Walk every field index across the inheritance chain. Repeat calls
|
|
280
|
+
// are cheap: defineField overwrites the same descriptor and re-stamps
|
|
281
|
+
// the same `metadata[$encoders]` slot (idempotent).
|
|
282
|
+
for (let i = 0; i <= numFields; i++) {
|
|
283
|
+
const field = metadata[i];
|
|
284
|
+
if (!field) continue;
|
|
285
|
+
Metadata.defineField(ctor, metadata, i, field.name, field.type);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Invalidate any cached encode descriptor — `getEncodeDescriptor`
|
|
289
|
+
// memoizes on the constructor. If something already constructed it
|
|
290
|
+
// (e.g. a prior `InputEncoder(...)` call that threw), drop the stale
|
|
291
|
+
// entry so the next read sees the upgraded metadata.
|
|
292
|
+
if (Object.prototype.hasOwnProperty.call(ctor, $encodeDescriptor)) {
|
|
293
|
+
delete (ctor as any)[$encodeDescriptor];
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
return ctor;
|
|
297
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -71,7 +71,7 @@ export { t, FieldBuilder, isBuilder, type BuilderDefinition, type ChildType } fr
|
|
|
71
71
|
export { TypeContext } from "./types/TypeContext.js";
|
|
72
72
|
|
|
73
73
|
// Helper types for type inference
|
|
74
|
-
export type { InferValueType, InferSchemaInstanceType, AssignableProps } from "./types/HelperTypes.js";
|
|
74
|
+
export type { InferValueType, InferSchemaInstanceType, AssignableProps, BuilderInitProps } from "./types/HelperTypes.js";
|
|
75
75
|
|
|
76
76
|
export { getDecoderStateCallbacks, type CallbackProxy, type SchemaCallback, type CollectionCallback, type SchemaCallbackProxy } from "./decoder/strategy/getDecoderStateCallbacks.js";
|
|
77
77
|
export { Callbacks, StateCallbackStrategy } from "./decoder/strategy/Callbacks.js";
|