@colyseus/schema 5.0.0 → 5.0.2
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 +1 -0
- package/build/Reflection.d.ts +26 -26
- package/build/annotations.d.ts +11 -7
- package/build/index.cjs +71 -12
- package/build/index.cjs.map +1 -1
- package/build/index.d.ts +1 -1
- package/build/index.js +71 -12
- package/build/index.mjs +71 -12
- package/build/index.mjs.map +1 -1
- package/build/input/index.cjs +29 -5
- package/build/input/index.cjs.map +1 -1
- package/build/input/index.mjs +29 -5
- package/build/input/index.mjs.map +1 -1
- package/build/types/HelperTypes.d.ts +47 -3
- package/build/types/builder.d.ts +65 -35
- package/package.json +1 -1
- package/src/Metadata.ts +1 -0
- package/src/Reflection.ts +2 -2
- package/src/annotations.ts +58 -17
- package/src/index.ts +1 -1
- package/src/types/HelperTypes.ts +104 -19
- package/src/types/builder.ts +67 -21
- package/src/types/symbols.ts +45 -6
package/build/Metadata.d.ts
CHANGED
package/build/Reflection.d.ts
CHANGED
|
@@ -30,36 +30,36 @@ interface ReflectionStatic {
|
|
|
30
30
|
* Reflection
|
|
31
31
|
*/
|
|
32
32
|
export declare const ReflectionField: import("./annotations.js").SchemaWithExtendsConstructor<{
|
|
33
|
-
name: FieldBuilder<string>;
|
|
34
|
-
type: FieldBuilder<string>;
|
|
35
|
-
referencedType: FieldBuilder<number>;
|
|
36
|
-
}, import("./index.js").
|
|
37
|
-
name: FieldBuilder<string>;
|
|
38
|
-
type: FieldBuilder<string>;
|
|
39
|
-
referencedType: FieldBuilder<number>;
|
|
40
|
-
}
|
|
33
|
+
name: FieldBuilder<string, false, false>;
|
|
34
|
+
type: FieldBuilder<string, false, false>;
|
|
35
|
+
referencedType: FieldBuilder<number, false, false>;
|
|
36
|
+
}, import("./index.js").BuilderInitProps<{
|
|
37
|
+
name: FieldBuilder<string, false, false>;
|
|
38
|
+
type: FieldBuilder<string, false, false>;
|
|
39
|
+
referencedType: FieldBuilder<number, false, false>;
|
|
40
|
+
}>, typeof Schema>;
|
|
41
41
|
export type ReflectionField = SchemaType<typeof ReflectionField>;
|
|
42
42
|
export declare const ReflectionType: import("./annotations.js").SchemaWithExtendsConstructor<{
|
|
43
|
-
id: FieldBuilder<number>;
|
|
44
|
-
extendsId: FieldBuilder<number>;
|
|
45
|
-
fields: FieldBuilder<ArraySchema<{
|
|
46
|
-
name
|
|
47
|
-
type
|
|
48
|
-
referencedType
|
|
49
|
-
} & Schema<any> & Schema<unknown
|
|
50
|
-
}, import("./index.js").
|
|
51
|
-
id: FieldBuilder<number>;
|
|
52
|
-
extendsId: FieldBuilder<number>;
|
|
53
|
-
fields: FieldBuilder<ArraySchema<{
|
|
54
|
-
name
|
|
55
|
-
type
|
|
56
|
-
referencedType
|
|
57
|
-
} & Schema<any> & Schema<unknown
|
|
58
|
-
}
|
|
43
|
+
id: FieldBuilder<number, false, false>;
|
|
44
|
+
extendsId: FieldBuilder<number, false, false>;
|
|
45
|
+
fields: FieldBuilder<ArraySchema<{} & {
|
|
46
|
+
name?: string;
|
|
47
|
+
type?: string;
|
|
48
|
+
referencedType?: number;
|
|
49
|
+
} & Schema<any> & Schema<unknown>>, true, false>;
|
|
50
|
+
}, import("./index.js").BuilderInitProps<{
|
|
51
|
+
id: FieldBuilder<number, false, false>;
|
|
52
|
+
extendsId: FieldBuilder<number, false, false>;
|
|
53
|
+
fields: FieldBuilder<ArraySchema<{} & {
|
|
54
|
+
name?: string;
|
|
55
|
+
type?: string;
|
|
56
|
+
referencedType?: number;
|
|
57
|
+
} & Schema<any> & Schema<unknown>>, true, false>;
|
|
58
|
+
}>, typeof Schema>;
|
|
59
59
|
export type ReflectionType = SchemaType<typeof ReflectionType>;
|
|
60
60
|
export declare const Reflection: ReturnType<typeof schema<{
|
|
61
|
-
types: FieldBuilder<ArraySchema<ReflectionType
|
|
62
|
-
rootType: FieldBuilder<number>;
|
|
61
|
+
types: FieldBuilder<ArraySchema<ReflectionType>, true, false>;
|
|
62
|
+
rootType: FieldBuilder<number, false, false>;
|
|
63
63
|
}>> & ReflectionStatic;
|
|
64
64
|
export type Reflection = SchemaType<typeof Reflection>;
|
|
65
65
|
export {};
|
package/build/annotations.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { Schema } from './Schema.js';
|
|
|
3
3
|
import { ArraySchema } from './types/custom/ArraySchema.js';
|
|
4
4
|
import { MapSchema } from './types/custom/MapSchema.js';
|
|
5
5
|
import { TypeDefinition } from "./types/registry.js";
|
|
6
|
-
import type { InferValueType, InferSchemaInstanceType,
|
|
6
|
+
import type { InferValueType, InferSchemaInstanceType, BuilderInitProps } from "./types/HelperTypes.js";
|
|
7
7
|
import { CollectionSchema } from "./types/custom/CollectionSchema.js";
|
|
8
8
|
import { SetSchema } from "./types/custom/SetSchema.js";
|
|
9
9
|
import { StreamSchema } from "./types/custom/StreamSchema.js";
|
|
@@ -98,19 +98,21 @@ export declare function getPropertyDescriptor(fieldName: string, fieldIndex: num
|
|
|
98
98
|
export declare function deprecated(throws?: boolean): PropertyDecorator;
|
|
99
99
|
type ExtractInitProps<T> = T extends {
|
|
100
100
|
initialize: (...args: infer P) => void;
|
|
101
|
-
} ? P extends readonly [] ? never : P extends readonly [infer First] ? First extends object ? First : P : P :
|
|
101
|
+
} ? P extends readonly [] ? never : P extends readonly [infer First] ? First extends object ? First : P : P : BuilderInitProps<T>;
|
|
102
|
+
type HasRequiredKeys<X> = {} extends X ? false : true;
|
|
102
103
|
type IsInitPropsRequired<T> = T extends {
|
|
103
|
-
initialize: (
|
|
104
|
-
} ? true : T
|
|
104
|
+
initialize: (...args: infer P) => void;
|
|
105
|
+
} ? P extends readonly [] ? false : true : HasRequiredKeys<BuilderInitProps<T>>;
|
|
106
|
+
type HasExplicitInit<T> = T extends {
|
|
105
107
|
initialize: (...args: infer P) => void;
|
|
106
108
|
} ? P extends readonly [] ? false : true : false;
|
|
107
109
|
/**
|
|
108
110
|
* A `schema()` field definition accepts a FieldBuilder, a Schema subclass
|
|
109
111
|
* (shorthand for `t.ref(Class)`), or a method (attached to the prototype).
|
|
110
112
|
*/
|
|
111
|
-
export type FieldsAndMethods = Record<string, FieldBuilder<any> | (new (...args: any[]) => Schema) | Function>;
|
|
113
|
+
export type FieldsAndMethods = Record<string, FieldBuilder<any, boolean, boolean> | (new (...args: any[]) => Schema) | Function>;
|
|
112
114
|
export interface SchemaWithExtends<T, P extends typeof Schema> {
|
|
113
|
-
extend: <T2 extends FieldsAndMethods = FieldsAndMethods>(fields: T2 & ThisType<InferSchemaInstanceType<T & T2>>, name?: string) => SchemaWithExtendsConstructor<T & T2, ExtractInitProps<T2>, P>;
|
|
115
|
+
extend: <T2 extends FieldsAndMethods = FieldsAndMethods>(fields: T2 & ThisType<InferSchemaInstanceType<T & T2>>, name?: string) => SchemaWithExtendsConstructor<T & T2, ExtractInitProps<T & T2>, P>;
|
|
114
116
|
}
|
|
115
117
|
/**
|
|
116
118
|
* Get the type of the schema defined via `schema('Name', {...})` method.
|
|
@@ -127,7 +129,9 @@ export type SchemaType<T extends {
|
|
|
127
129
|
}> = T['~type'];
|
|
128
130
|
export interface SchemaWithExtendsConstructor<T, InitProps, P extends typeof Schema> extends SchemaWithExtends<T, P> {
|
|
129
131
|
'~type': InferSchemaInstanceType<T>;
|
|
130
|
-
new (...args: [
|
|
132
|
+
new (...args: [
|
|
133
|
+
InitProps
|
|
134
|
+
] extends [never] ? [] : InitProps extends readonly any[] ? InitProps : HasExplicitInit<T> extends true ? [InitProps] : IsInitPropsRequired<T> extends true ? ([] | [InitProps]) : [InitProps?]): InferSchemaInstanceType<T> & InstanceType<P>;
|
|
131
135
|
prototype: InferSchemaInstanceType<T> & InstanceType<P> & {
|
|
132
136
|
initialize(...args: [InitProps] extends [never] ? [] : InitProps extends readonly any[] ? InitProps : [InitProps]): void;
|
|
133
137
|
};
|
package/build/index.cjs
CHANGED
|
@@ -28,7 +28,31 @@ exports.OPERATION = void 0;
|
|
|
28
28
|
|
|
29
29
|
Symbol.metadata ??= Symbol.for("Symbol.metadata");
|
|
30
30
|
|
|
31
|
-
const
|
|
31
|
+
const _g = (function () {
|
|
32
|
+
if (typeof globalThis !== "undefined")
|
|
33
|
+
return globalThis;
|
|
34
|
+
if (typeof global !== "undefined")
|
|
35
|
+
return global;
|
|
36
|
+
if (typeof self !== "undefined")
|
|
37
|
+
return self;
|
|
38
|
+
if (typeof window !== "undefined")
|
|
39
|
+
return window;
|
|
40
|
+
return {};
|
|
41
|
+
})();
|
|
42
|
+
if (typeof Symbol === "function" && typeof Symbol.for !== "function") {
|
|
43
|
+
const REGISTRY_KEY = "colyseus.symbolRegistry";
|
|
44
|
+
const registry = _g[REGISTRY_KEY] || (_g[REGISTRY_KEY] = Object.create(null));
|
|
45
|
+
Symbol.for = function (key) {
|
|
46
|
+
return registry[key] || (registry[key] = Symbol(key));
|
|
47
|
+
};
|
|
48
|
+
Symbol.keyFor = function (sym) {
|
|
49
|
+
for (const k in registry)
|
|
50
|
+
if (registry[k] === sym)
|
|
51
|
+
return k;
|
|
52
|
+
return undefined;
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
const $refId = Symbol.for("$refId");
|
|
32
56
|
const $track = "~track";
|
|
33
57
|
const $encoder = "~encoder";
|
|
34
58
|
const $decoder = "~decoder";
|
|
@@ -40,12 +64,12 @@ const $deleteByIndex = "~deleteByIndex";
|
|
|
40
64
|
*
|
|
41
65
|
* Real JS Symbol — see the `$values` comment for rationale.
|
|
42
66
|
*/
|
|
43
|
-
const $changes = Symbol("$changes");
|
|
67
|
+
const $changes = Symbol.for("$changes");
|
|
44
68
|
/**
|
|
45
69
|
* Used to keep track of the type of the child elements of a collection
|
|
46
70
|
* (MapSchema, ArraySchema, etc.). Real Symbol — same rationale as $values.
|
|
47
71
|
*/
|
|
48
|
-
const $childType = Symbol("$childType");
|
|
72
|
+
const $childType = Symbol.for("$childType");
|
|
49
73
|
/**
|
|
50
74
|
* Self-reference an instance sets on `this` so its own methods can recover
|
|
51
75
|
* the underlying object even when `this` is a Proxy wrapper. Used by
|
|
@@ -53,7 +77,7 @@ const $childType = Symbol("$childType");
|
|
|
53
77
|
* once at the top of hot methods and then access fields directly without
|
|
54
78
|
* paying the Proxy.get cost on every read.
|
|
55
79
|
*/
|
|
56
|
-
const $proxyTarget = Symbol("$proxyTarget");
|
|
80
|
+
const $proxyTarget = Symbol.for("$proxyTarget");
|
|
57
81
|
/**
|
|
58
82
|
* Optional "discard" method for custom types (ArraySchema)
|
|
59
83
|
* (Discards changes for next serialization)
|
|
@@ -72,7 +96,7 @@ const $onDecodeEnd = "~onDecodeEnd";
|
|
|
72
96
|
* which means we can drop Object.defineProperty(...{ enumerable: false })
|
|
73
97
|
* and avoid the slow-path / dictionary-mode hazards that come with it.
|
|
74
98
|
*/
|
|
75
|
-
const $values = Symbol("$values");
|
|
99
|
+
const $values = Symbol.for("$values");
|
|
76
100
|
/**
|
|
77
101
|
* Brand for FieldBuilder instances so schema() can detect them.
|
|
78
102
|
*/
|
|
@@ -5386,9 +5410,23 @@ registerType("stream", { constructor: StreamSchema });
|
|
|
5386
5410
|
/**
|
|
5387
5411
|
* Chainable field builder. Instances are produced by `t.*()` factories.
|
|
5388
5412
|
*
|
|
5389
|
-
*
|
|
5390
|
-
* `
|
|
5391
|
-
*
|
|
5413
|
+
* Generics:
|
|
5414
|
+
* - `T` is the runtime/JS type of the field (e.g. `number`, `string`,
|
|
5415
|
+
* `ArraySchema<Item>`). `.optional()` widens it to `T | undefined`
|
|
5416
|
+
* so the inferred instance/toJSON shapes reflect absence.
|
|
5417
|
+
* - `HasDefault` is a compile-time flag that the field carries a
|
|
5418
|
+
* construction-time default — either an explicit `.default(v)` or an
|
|
5419
|
+
* auto-default from a collection factory (`t.array`, `t.map`, …) or a
|
|
5420
|
+
* Schema ref whose `initialize` takes zero args.
|
|
5421
|
+
* - `IsOptional` is a compile-time brand for `.optional()`. Both
|
|
5422
|
+
* `HasDefault` and `IsOptional` make the field omittable in
|
|
5423
|
+
* `BuilderInitProps<T>`. A separate brand (rather than reading
|
|
5424
|
+
* `undefined extends V`) sidesteps a TypeScript quirk where
|
|
5425
|
+
* class-generic-inferred `V` resolves `undefined extends V` as `true`
|
|
5426
|
+
* even for non-undefined types.
|
|
5427
|
+
*
|
|
5428
|
+
* schema() reads the internal configuration via `toDefinition()` and wires
|
|
5429
|
+
* up metadata through the existing pipeline.
|
|
5392
5430
|
*/
|
|
5393
5431
|
class FieldBuilder {
|
|
5394
5432
|
[$builder] = true;
|
|
@@ -5405,6 +5443,7 @@ class FieldBuilder {
|
|
|
5405
5443
|
_deprecatedThrows = true;
|
|
5406
5444
|
_static = false;
|
|
5407
5445
|
_stream = false;
|
|
5446
|
+
_optional = false;
|
|
5408
5447
|
_streamPriority = undefined;
|
|
5409
5448
|
constructor(type) {
|
|
5410
5449
|
this._type = type;
|
|
@@ -5499,6 +5538,16 @@ class FieldBuilder {
|
|
|
5499
5538
|
this._deprecatedThrows = throws;
|
|
5500
5539
|
return this;
|
|
5501
5540
|
}
|
|
5541
|
+
/**
|
|
5542
|
+
* Mark this field as optional — inferred instance type becomes
|
|
5543
|
+
* `T | undefined` and the property becomes omittable in initialization
|
|
5544
|
+
* props. Skips the auto-instantiation of collection / Schema-ref
|
|
5545
|
+
* defaults, so the field starts as `undefined` at runtime.
|
|
5546
|
+
*/
|
|
5547
|
+
optional() {
|
|
5548
|
+
this._optional = true;
|
|
5549
|
+
return this;
|
|
5550
|
+
}
|
|
5502
5551
|
toDefinition() {
|
|
5503
5552
|
return {
|
|
5504
5553
|
type: this._type,
|
|
@@ -5512,6 +5561,7 @@ class FieldBuilder {
|
|
|
5512
5561
|
deprecatedThrows: this._deprecatedThrows,
|
|
5513
5562
|
static: this._static,
|
|
5514
5563
|
stream: this._stream,
|
|
5564
|
+
optional: this._optional,
|
|
5515
5565
|
streamPriority: this._streamPriority,
|
|
5516
5566
|
};
|
|
5517
5567
|
}
|
|
@@ -5540,9 +5590,7 @@ const streamFactory = ((child) => {
|
|
|
5540
5590
|
b._stream = true;
|
|
5541
5591
|
return b;
|
|
5542
5592
|
});
|
|
5543
|
-
|
|
5544
|
-
return new FieldBuilder(ctor);
|
|
5545
|
-
}
|
|
5593
|
+
const refFactory = ((ctor) => new FieldBuilder(ctor));
|
|
5546
5594
|
const t = Object.freeze({
|
|
5547
5595
|
// Primitives
|
|
5548
5596
|
string: primitive("string"),
|
|
@@ -5999,6 +6047,7 @@ function schema(fieldsAndMethods, name, inherits = Schema) {
|
|
|
5999
6047
|
const staticFields = [];
|
|
6000
6048
|
const streamFields = [];
|
|
6001
6049
|
const streamPriorityFields = {};
|
|
6050
|
+
const optionalFields = [];
|
|
6002
6051
|
for (const fieldName in fieldsAndMethods) {
|
|
6003
6052
|
const value = fieldsAndMethods[fieldName];
|
|
6004
6053
|
if (isBuilder(value)) {
|
|
@@ -6028,11 +6077,15 @@ function schema(fieldsAndMethods, name, inherits = Schema) {
|
|
|
6028
6077
|
if (def.streamPriority !== undefined) {
|
|
6029
6078
|
streamPriorityFields[fieldName] = def.streamPriority;
|
|
6030
6079
|
}
|
|
6080
|
+
if (def.optional) {
|
|
6081
|
+
optionalFields.push(fieldName);
|
|
6082
|
+
}
|
|
6031
6083
|
if (def.hasDefault) {
|
|
6032
6084
|
defaultValues[fieldName] = def.default;
|
|
6033
6085
|
}
|
|
6034
|
-
else {
|
|
6086
|
+
else if (!def.optional) {
|
|
6035
6087
|
// Auto-instantiate collection/Schema defaults when none is provided.
|
|
6088
|
+
// `.optional()` opts out — field starts as undefined.
|
|
6036
6089
|
const rawType = def.type;
|
|
6037
6090
|
if (rawType && typeof rawType === "object") {
|
|
6038
6091
|
if (rawType.array !== undefined) {
|
|
@@ -6142,6 +6195,12 @@ function schema(fieldsAndMethods, name, inherits = Schema) {
|
|
|
6142
6195
|
Metadata.setStreamPriority(metadata, fieldName, streamPriorityFields[fieldName]);
|
|
6143
6196
|
}
|
|
6144
6197
|
}
|
|
6198
|
+
if (optionalFields.length > 0) {
|
|
6199
|
+
const metadata = klass[Symbol.metadata];
|
|
6200
|
+
for (const fieldName of optionalFields) {
|
|
6201
|
+
metadata[metadata[fieldName]].optional = true;
|
|
6202
|
+
}
|
|
6203
|
+
}
|
|
6145
6204
|
if (name) {
|
|
6146
6205
|
Object.defineProperty(klass, "name", { value: name });
|
|
6147
6206
|
}
|