@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/index.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ export { Metadata } from "./Metadata.js";
|
|
|
22
22
|
export { type, deprecated, owned, unreliable, transient, view, schema, entity, type DefinitionType, type PrimitiveType, type Definition, type FieldsAndMethods, type SchemaWithExtendsConstructor, type SchemaWithExtends, type SchemaType, } from "./annotations.js";
|
|
23
23
|
export { t, FieldBuilder, isBuilder, type BuilderDefinition, type ChildType } from "./types/builder.js";
|
|
24
24
|
export { TypeContext } from "./types/TypeContext.js";
|
|
25
|
-
export type { InferValueType, InferSchemaInstanceType, AssignableProps } from "./types/HelperTypes.js";
|
|
25
|
+
export type { InferValueType, InferSchemaInstanceType, AssignableProps, BuilderInitProps } from "./types/HelperTypes.js";
|
|
26
26
|
export { getDecoderStateCallbacks, type CallbackProxy, type SchemaCallback, type CollectionCallback, type SchemaCallbackProxy } from "./decoder/strategy/getDecoderStateCallbacks.js";
|
|
27
27
|
export { Callbacks, StateCallbackStrategy } from "./decoder/strategy/Callbacks.js";
|
|
28
28
|
export { getRawChangesCallback } from "./decoder/strategy/RawChanges.js";
|
package/build/index.js
CHANGED
|
@@ -32,7 +32,31 @@
|
|
|
32
32
|
|
|
33
33
|
Symbol.metadata ??= Symbol.for("Symbol.metadata");
|
|
34
34
|
|
|
35
|
-
const
|
|
35
|
+
const _g = (function () {
|
|
36
|
+
if (typeof globalThis !== "undefined")
|
|
37
|
+
return globalThis;
|
|
38
|
+
if (typeof global !== "undefined")
|
|
39
|
+
return global;
|
|
40
|
+
if (typeof self !== "undefined")
|
|
41
|
+
return self;
|
|
42
|
+
if (typeof window !== "undefined")
|
|
43
|
+
return window;
|
|
44
|
+
return {};
|
|
45
|
+
})();
|
|
46
|
+
if (typeof Symbol === "function" && typeof Symbol.for !== "function") {
|
|
47
|
+
const REGISTRY_KEY = "colyseus.symbolRegistry";
|
|
48
|
+
const registry = _g[REGISTRY_KEY] || (_g[REGISTRY_KEY] = Object.create(null));
|
|
49
|
+
Symbol.for = function (key) {
|
|
50
|
+
return registry[key] || (registry[key] = Symbol(key));
|
|
51
|
+
};
|
|
52
|
+
Symbol.keyFor = function (sym) {
|
|
53
|
+
for (const k in registry)
|
|
54
|
+
if (registry[k] === sym)
|
|
55
|
+
return k;
|
|
56
|
+
return undefined;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
const $refId = Symbol.for("$refId");
|
|
36
60
|
const $track = "~track";
|
|
37
61
|
const $encoder = "~encoder";
|
|
38
62
|
const $decoder = "~decoder";
|
|
@@ -44,12 +68,12 @@
|
|
|
44
68
|
*
|
|
45
69
|
* Real JS Symbol — see the `$values` comment for rationale.
|
|
46
70
|
*/
|
|
47
|
-
const $changes = Symbol("$changes");
|
|
71
|
+
const $changes = Symbol.for("$changes");
|
|
48
72
|
/**
|
|
49
73
|
* Used to keep track of the type of the child elements of a collection
|
|
50
74
|
* (MapSchema, ArraySchema, etc.). Real Symbol — same rationale as $values.
|
|
51
75
|
*/
|
|
52
|
-
const $childType = Symbol("$childType");
|
|
76
|
+
const $childType = Symbol.for("$childType");
|
|
53
77
|
/**
|
|
54
78
|
* Self-reference an instance sets on `this` so its own methods can recover
|
|
55
79
|
* the underlying object even when `this` is a Proxy wrapper. Used by
|
|
@@ -57,7 +81,7 @@
|
|
|
57
81
|
* once at the top of hot methods and then access fields directly without
|
|
58
82
|
* paying the Proxy.get cost on every read.
|
|
59
83
|
*/
|
|
60
|
-
const $proxyTarget = Symbol("$proxyTarget");
|
|
84
|
+
const $proxyTarget = Symbol.for("$proxyTarget");
|
|
61
85
|
/**
|
|
62
86
|
* Optional "discard" method for custom types (ArraySchema)
|
|
63
87
|
* (Discards changes for next serialization)
|
|
@@ -76,7 +100,7 @@
|
|
|
76
100
|
* which means we can drop Object.defineProperty(...{ enumerable: false })
|
|
77
101
|
* and avoid the slow-path / dictionary-mode hazards that come with it.
|
|
78
102
|
*/
|
|
79
|
-
const $values = Symbol("$values");
|
|
103
|
+
const $values = Symbol.for("$values");
|
|
80
104
|
/**
|
|
81
105
|
* Brand for FieldBuilder instances so schema() can detect them.
|
|
82
106
|
*/
|
|
@@ -5390,9 +5414,23 @@
|
|
|
5390
5414
|
/**
|
|
5391
5415
|
* Chainable field builder. Instances are produced by `t.*()` factories.
|
|
5392
5416
|
*
|
|
5393
|
-
*
|
|
5394
|
-
* `
|
|
5395
|
-
*
|
|
5417
|
+
* Generics:
|
|
5418
|
+
* - `T` is the runtime/JS type of the field (e.g. `number`, `string`,
|
|
5419
|
+
* `ArraySchema<Item>`). `.optional()` widens it to `T | undefined`
|
|
5420
|
+
* so the inferred instance/toJSON shapes reflect absence.
|
|
5421
|
+
* - `HasDefault` is a compile-time flag that the field carries a
|
|
5422
|
+
* construction-time default — either an explicit `.default(v)` or an
|
|
5423
|
+
* auto-default from a collection factory (`t.array`, `t.map`, …) or a
|
|
5424
|
+
* Schema ref whose `initialize` takes zero args.
|
|
5425
|
+
* - `IsOptional` is a compile-time brand for `.optional()`. Both
|
|
5426
|
+
* `HasDefault` and `IsOptional` make the field omittable in
|
|
5427
|
+
* `BuilderInitProps<T>`. A separate brand (rather than reading
|
|
5428
|
+
* `undefined extends V`) sidesteps a TypeScript quirk where
|
|
5429
|
+
* class-generic-inferred `V` resolves `undefined extends V` as `true`
|
|
5430
|
+
* even for non-undefined types.
|
|
5431
|
+
*
|
|
5432
|
+
* schema() reads the internal configuration via `toDefinition()` and wires
|
|
5433
|
+
* up metadata through the existing pipeline.
|
|
5396
5434
|
*/
|
|
5397
5435
|
class FieldBuilder {
|
|
5398
5436
|
[$builder] = true;
|
|
@@ -5409,6 +5447,7 @@
|
|
|
5409
5447
|
_deprecatedThrows = true;
|
|
5410
5448
|
_static = false;
|
|
5411
5449
|
_stream = false;
|
|
5450
|
+
_optional = false;
|
|
5412
5451
|
_streamPriority = undefined;
|
|
5413
5452
|
constructor(type) {
|
|
5414
5453
|
this._type = type;
|
|
@@ -5503,6 +5542,16 @@
|
|
|
5503
5542
|
this._deprecatedThrows = throws;
|
|
5504
5543
|
return this;
|
|
5505
5544
|
}
|
|
5545
|
+
/**
|
|
5546
|
+
* Mark this field as optional — inferred instance type becomes
|
|
5547
|
+
* `T | undefined` and the property becomes omittable in initialization
|
|
5548
|
+
* props. Skips the auto-instantiation of collection / Schema-ref
|
|
5549
|
+
* defaults, so the field starts as `undefined` at runtime.
|
|
5550
|
+
*/
|
|
5551
|
+
optional() {
|
|
5552
|
+
this._optional = true;
|
|
5553
|
+
return this;
|
|
5554
|
+
}
|
|
5506
5555
|
toDefinition() {
|
|
5507
5556
|
return {
|
|
5508
5557
|
type: this._type,
|
|
@@ -5516,6 +5565,7 @@
|
|
|
5516
5565
|
deprecatedThrows: this._deprecatedThrows,
|
|
5517
5566
|
static: this._static,
|
|
5518
5567
|
stream: this._stream,
|
|
5568
|
+
optional: this._optional,
|
|
5519
5569
|
streamPriority: this._streamPriority,
|
|
5520
5570
|
};
|
|
5521
5571
|
}
|
|
@@ -5544,9 +5594,7 @@
|
|
|
5544
5594
|
b._stream = true;
|
|
5545
5595
|
return b;
|
|
5546
5596
|
});
|
|
5547
|
-
|
|
5548
|
-
return new FieldBuilder(ctor);
|
|
5549
|
-
}
|
|
5597
|
+
const refFactory = ((ctor) => new FieldBuilder(ctor));
|
|
5550
5598
|
const t = Object.freeze({
|
|
5551
5599
|
// Primitives
|
|
5552
5600
|
string: primitive("string"),
|
|
@@ -6003,6 +6051,7 @@
|
|
|
6003
6051
|
const staticFields = [];
|
|
6004
6052
|
const streamFields = [];
|
|
6005
6053
|
const streamPriorityFields = {};
|
|
6054
|
+
const optionalFields = [];
|
|
6006
6055
|
for (const fieldName in fieldsAndMethods) {
|
|
6007
6056
|
const value = fieldsAndMethods[fieldName];
|
|
6008
6057
|
if (isBuilder(value)) {
|
|
@@ -6032,11 +6081,15 @@
|
|
|
6032
6081
|
if (def.streamPriority !== undefined) {
|
|
6033
6082
|
streamPriorityFields[fieldName] = def.streamPriority;
|
|
6034
6083
|
}
|
|
6084
|
+
if (def.optional) {
|
|
6085
|
+
optionalFields.push(fieldName);
|
|
6086
|
+
}
|
|
6035
6087
|
if (def.hasDefault) {
|
|
6036
6088
|
defaultValues[fieldName] = def.default;
|
|
6037
6089
|
}
|
|
6038
|
-
else {
|
|
6090
|
+
else if (!def.optional) {
|
|
6039
6091
|
// Auto-instantiate collection/Schema defaults when none is provided.
|
|
6092
|
+
// `.optional()` opts out — field starts as undefined.
|
|
6040
6093
|
const rawType = def.type;
|
|
6041
6094
|
if (rawType && typeof rawType === "object") {
|
|
6042
6095
|
if (rawType.array !== undefined) {
|
|
@@ -6146,6 +6199,12 @@
|
|
|
6146
6199
|
Metadata.setStreamPriority(metadata, fieldName, streamPriorityFields[fieldName]);
|
|
6147
6200
|
}
|
|
6148
6201
|
}
|
|
6202
|
+
if (optionalFields.length > 0) {
|
|
6203
|
+
const metadata = klass[Symbol.metadata];
|
|
6204
|
+
for (const fieldName of optionalFields) {
|
|
6205
|
+
metadata[metadata[fieldName]].optional = true;
|
|
6206
|
+
}
|
|
6207
|
+
}
|
|
6149
6208
|
if (name) {
|
|
6150
6209
|
Object.defineProperty(klass, "name", { value: name });
|
|
6151
6210
|
}
|
package/build/index.mjs
CHANGED
|
@@ -26,7 +26,31 @@ var OPERATION;
|
|
|
26
26
|
|
|
27
27
|
Symbol.metadata ??= Symbol.for("Symbol.metadata");
|
|
28
28
|
|
|
29
|
-
const
|
|
29
|
+
const _g = (function () {
|
|
30
|
+
if (typeof globalThis !== "undefined")
|
|
31
|
+
return globalThis;
|
|
32
|
+
if (typeof global !== "undefined")
|
|
33
|
+
return global;
|
|
34
|
+
if (typeof self !== "undefined")
|
|
35
|
+
return self;
|
|
36
|
+
if (typeof window !== "undefined")
|
|
37
|
+
return window;
|
|
38
|
+
return {};
|
|
39
|
+
})();
|
|
40
|
+
if (typeof Symbol === "function" && typeof Symbol.for !== "function") {
|
|
41
|
+
const REGISTRY_KEY = "colyseus.symbolRegistry";
|
|
42
|
+
const registry = _g[REGISTRY_KEY] || (_g[REGISTRY_KEY] = Object.create(null));
|
|
43
|
+
Symbol.for = function (key) {
|
|
44
|
+
return registry[key] || (registry[key] = Symbol(key));
|
|
45
|
+
};
|
|
46
|
+
Symbol.keyFor = function (sym) {
|
|
47
|
+
for (const k in registry)
|
|
48
|
+
if (registry[k] === sym)
|
|
49
|
+
return k;
|
|
50
|
+
return undefined;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const $refId = Symbol.for("$refId");
|
|
30
54
|
const $track = "~track";
|
|
31
55
|
const $encoder = "~encoder";
|
|
32
56
|
const $decoder = "~decoder";
|
|
@@ -38,12 +62,12 @@ const $deleteByIndex = "~deleteByIndex";
|
|
|
38
62
|
*
|
|
39
63
|
* Real JS Symbol — see the `$values` comment for rationale.
|
|
40
64
|
*/
|
|
41
|
-
const $changes = Symbol("$changes");
|
|
65
|
+
const $changes = Symbol.for("$changes");
|
|
42
66
|
/**
|
|
43
67
|
* Used to keep track of the type of the child elements of a collection
|
|
44
68
|
* (MapSchema, ArraySchema, etc.). Real Symbol — same rationale as $values.
|
|
45
69
|
*/
|
|
46
|
-
const $childType = Symbol("$childType");
|
|
70
|
+
const $childType = Symbol.for("$childType");
|
|
47
71
|
/**
|
|
48
72
|
* Self-reference an instance sets on `this` so its own methods can recover
|
|
49
73
|
* the underlying object even when `this` is a Proxy wrapper. Used by
|
|
@@ -51,7 +75,7 @@ const $childType = Symbol("$childType");
|
|
|
51
75
|
* once at the top of hot methods and then access fields directly without
|
|
52
76
|
* paying the Proxy.get cost on every read.
|
|
53
77
|
*/
|
|
54
|
-
const $proxyTarget = Symbol("$proxyTarget");
|
|
78
|
+
const $proxyTarget = Symbol.for("$proxyTarget");
|
|
55
79
|
/**
|
|
56
80
|
* Optional "discard" method for custom types (ArraySchema)
|
|
57
81
|
* (Discards changes for next serialization)
|
|
@@ -70,7 +94,7 @@ const $onDecodeEnd = "~onDecodeEnd";
|
|
|
70
94
|
* which means we can drop Object.defineProperty(...{ enumerable: false })
|
|
71
95
|
* and avoid the slow-path / dictionary-mode hazards that come with it.
|
|
72
96
|
*/
|
|
73
|
-
const $values = Symbol("$values");
|
|
97
|
+
const $values = Symbol.for("$values");
|
|
74
98
|
/**
|
|
75
99
|
* Brand for FieldBuilder instances so schema() can detect them.
|
|
76
100
|
*/
|
|
@@ -5384,9 +5408,23 @@ registerType("stream", { constructor: StreamSchema });
|
|
|
5384
5408
|
/**
|
|
5385
5409
|
* Chainable field builder. Instances are produced by `t.*()` factories.
|
|
5386
5410
|
*
|
|
5387
|
-
*
|
|
5388
|
-
* `
|
|
5389
|
-
*
|
|
5411
|
+
* Generics:
|
|
5412
|
+
* - `T` is the runtime/JS type of the field (e.g. `number`, `string`,
|
|
5413
|
+
* `ArraySchema<Item>`). `.optional()` widens it to `T | undefined`
|
|
5414
|
+
* so the inferred instance/toJSON shapes reflect absence.
|
|
5415
|
+
* - `HasDefault` is a compile-time flag that the field carries a
|
|
5416
|
+
* construction-time default — either an explicit `.default(v)` or an
|
|
5417
|
+
* auto-default from a collection factory (`t.array`, `t.map`, …) or a
|
|
5418
|
+
* Schema ref whose `initialize` takes zero args.
|
|
5419
|
+
* - `IsOptional` is a compile-time brand for `.optional()`. Both
|
|
5420
|
+
* `HasDefault` and `IsOptional` make the field omittable in
|
|
5421
|
+
* `BuilderInitProps<T>`. A separate brand (rather than reading
|
|
5422
|
+
* `undefined extends V`) sidesteps a TypeScript quirk where
|
|
5423
|
+
* class-generic-inferred `V` resolves `undefined extends V` as `true`
|
|
5424
|
+
* even for non-undefined types.
|
|
5425
|
+
*
|
|
5426
|
+
* schema() reads the internal configuration via `toDefinition()` and wires
|
|
5427
|
+
* up metadata through the existing pipeline.
|
|
5390
5428
|
*/
|
|
5391
5429
|
class FieldBuilder {
|
|
5392
5430
|
[$builder] = true;
|
|
@@ -5403,6 +5441,7 @@ class FieldBuilder {
|
|
|
5403
5441
|
_deprecatedThrows = true;
|
|
5404
5442
|
_static = false;
|
|
5405
5443
|
_stream = false;
|
|
5444
|
+
_optional = false;
|
|
5406
5445
|
_streamPriority = undefined;
|
|
5407
5446
|
constructor(type) {
|
|
5408
5447
|
this._type = type;
|
|
@@ -5497,6 +5536,16 @@ class FieldBuilder {
|
|
|
5497
5536
|
this._deprecatedThrows = throws;
|
|
5498
5537
|
return this;
|
|
5499
5538
|
}
|
|
5539
|
+
/**
|
|
5540
|
+
* Mark this field as optional — inferred instance type becomes
|
|
5541
|
+
* `T | undefined` and the property becomes omittable in initialization
|
|
5542
|
+
* props. Skips the auto-instantiation of collection / Schema-ref
|
|
5543
|
+
* defaults, so the field starts as `undefined` at runtime.
|
|
5544
|
+
*/
|
|
5545
|
+
optional() {
|
|
5546
|
+
this._optional = true;
|
|
5547
|
+
return this;
|
|
5548
|
+
}
|
|
5500
5549
|
toDefinition() {
|
|
5501
5550
|
return {
|
|
5502
5551
|
type: this._type,
|
|
@@ -5510,6 +5559,7 @@ class FieldBuilder {
|
|
|
5510
5559
|
deprecatedThrows: this._deprecatedThrows,
|
|
5511
5560
|
static: this._static,
|
|
5512
5561
|
stream: this._stream,
|
|
5562
|
+
optional: this._optional,
|
|
5513
5563
|
streamPriority: this._streamPriority,
|
|
5514
5564
|
};
|
|
5515
5565
|
}
|
|
@@ -5538,9 +5588,7 @@ const streamFactory = ((child) => {
|
|
|
5538
5588
|
b._stream = true;
|
|
5539
5589
|
return b;
|
|
5540
5590
|
});
|
|
5541
|
-
|
|
5542
|
-
return new FieldBuilder(ctor);
|
|
5543
|
-
}
|
|
5591
|
+
const refFactory = ((ctor) => new FieldBuilder(ctor));
|
|
5544
5592
|
const t = Object.freeze({
|
|
5545
5593
|
// Primitives
|
|
5546
5594
|
string: primitive("string"),
|
|
@@ -5997,6 +6045,7 @@ function schema(fieldsAndMethods, name, inherits = Schema) {
|
|
|
5997
6045
|
const staticFields = [];
|
|
5998
6046
|
const streamFields = [];
|
|
5999
6047
|
const streamPriorityFields = {};
|
|
6048
|
+
const optionalFields = [];
|
|
6000
6049
|
for (const fieldName in fieldsAndMethods) {
|
|
6001
6050
|
const value = fieldsAndMethods[fieldName];
|
|
6002
6051
|
if (isBuilder(value)) {
|
|
@@ -6026,11 +6075,15 @@ function schema(fieldsAndMethods, name, inherits = Schema) {
|
|
|
6026
6075
|
if (def.streamPriority !== undefined) {
|
|
6027
6076
|
streamPriorityFields[fieldName] = def.streamPriority;
|
|
6028
6077
|
}
|
|
6078
|
+
if (def.optional) {
|
|
6079
|
+
optionalFields.push(fieldName);
|
|
6080
|
+
}
|
|
6029
6081
|
if (def.hasDefault) {
|
|
6030
6082
|
defaultValues[fieldName] = def.default;
|
|
6031
6083
|
}
|
|
6032
|
-
else {
|
|
6084
|
+
else if (!def.optional) {
|
|
6033
6085
|
// Auto-instantiate collection/Schema defaults when none is provided.
|
|
6086
|
+
// `.optional()` opts out — field starts as undefined.
|
|
6034
6087
|
const rawType = def.type;
|
|
6035
6088
|
if (rawType && typeof rawType === "object") {
|
|
6036
6089
|
if (rawType.array !== undefined) {
|
|
@@ -6140,6 +6193,12 @@ function schema(fieldsAndMethods, name, inherits = Schema) {
|
|
|
6140
6193
|
Metadata.setStreamPriority(metadata, fieldName, streamPriorityFields[fieldName]);
|
|
6141
6194
|
}
|
|
6142
6195
|
}
|
|
6196
|
+
if (optionalFields.length > 0) {
|
|
6197
|
+
const metadata = klass[Symbol.metadata];
|
|
6198
|
+
for (const fieldName of optionalFields) {
|
|
6199
|
+
metadata[metadata[fieldName]].optional = true;
|
|
6200
|
+
}
|
|
6201
|
+
}
|
|
6143
6202
|
if (name) {
|
|
6144
6203
|
Object.defineProperty(klass, "name", { value: name });
|
|
6145
6204
|
}
|