@colyseus/schema 4.0.20 → 5.0.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.
Files changed (96) hide show
  1. package/README.md +2 -0
  2. package/build/Metadata.d.ts +56 -2
  3. package/build/Reflection.d.ts +28 -34
  4. package/build/Schema.d.ts +70 -9
  5. package/build/annotations.d.ts +64 -17
  6. package/build/codegen/cli.cjs +84 -67
  7. package/build/codegen/cli.cjs.map +1 -1
  8. package/build/decoder/DecodeOperation.d.ts +48 -5
  9. package/build/decoder/Decoder.d.ts +2 -2
  10. package/build/decoder/strategy/Callbacks.d.ts +1 -1
  11. package/build/encoder/ChangeRecorder.d.ts +107 -0
  12. package/build/encoder/ChangeTree.d.ts +218 -69
  13. package/build/encoder/EncodeDescriptor.d.ts +63 -0
  14. package/build/encoder/EncodeOperation.d.ts +25 -2
  15. package/build/encoder/Encoder.d.ts +59 -3
  16. package/build/encoder/MapJournal.d.ts +62 -0
  17. package/build/encoder/RefIdAllocator.d.ts +35 -0
  18. package/build/encoder/Root.d.ts +94 -13
  19. package/build/encoder/StateView.d.ts +116 -8
  20. package/build/encoder/changeTree/inheritedFlags.d.ts +34 -0
  21. package/build/encoder/changeTree/liveIteration.d.ts +3 -0
  22. package/build/encoder/changeTree/parentChain.d.ts +24 -0
  23. package/build/encoder/changeTree/treeAttachment.d.ts +13 -0
  24. package/build/encoder/streaming.d.ts +73 -0
  25. package/build/encoder/subscriptions.d.ts +25 -0
  26. package/build/index.cjs +5258 -1549
  27. package/build/index.cjs.map +1 -1
  28. package/build/index.d.ts +7 -3
  29. package/build/index.js +5258 -1549
  30. package/build/index.mjs +5249 -1549
  31. package/build/index.mjs.map +1 -1
  32. package/build/input/InputDecoder.d.ts +32 -0
  33. package/build/input/InputEncoder.d.ts +117 -0
  34. package/build/input/index.cjs +7453 -0
  35. package/build/input/index.cjs.map +1 -0
  36. package/build/input/index.d.ts +3 -0
  37. package/build/input/index.mjs +7450 -0
  38. package/build/input/index.mjs.map +1 -0
  39. package/build/types/HelperTypes.d.ts +67 -9
  40. package/build/types/TypeContext.d.ts +9 -0
  41. package/build/types/builder.d.ts +192 -0
  42. package/build/types/custom/ArraySchema.d.ts +25 -4
  43. package/build/types/custom/CollectionSchema.d.ts +30 -2
  44. package/build/types/custom/MapSchema.d.ts +52 -3
  45. package/build/types/custom/SetSchema.d.ts +32 -2
  46. package/build/types/custom/StreamSchema.d.ts +114 -0
  47. package/build/types/symbols.d.ts +48 -5
  48. package/package.json +9 -3
  49. package/src/Metadata.ts +259 -31
  50. package/src/Reflection.ts +15 -13
  51. package/src/Schema.ts +176 -134
  52. package/src/annotations.ts +365 -252
  53. package/src/bench_bloat.ts +173 -0
  54. package/src/bench_decode.ts +221 -0
  55. package/src/bench_decode_mem.ts +165 -0
  56. package/src/bench_encode.ts +108 -0
  57. package/src/bench_init.ts +150 -0
  58. package/src/bench_static.ts +109 -0
  59. package/src/bench_stream.ts +295 -0
  60. package/src/bench_view_cmp.ts +142 -0
  61. package/src/codegen/languages/csharp.ts +0 -24
  62. package/src/codegen/parser.ts +83 -61
  63. package/src/decoder/DecodeOperation.ts +168 -63
  64. package/src/decoder/Decoder.ts +20 -10
  65. package/src/decoder/ReferenceTracker.ts +4 -0
  66. package/src/decoder/strategy/Callbacks.ts +30 -26
  67. package/src/decoder/strategy/getDecoderStateCallbacks.ts +16 -13
  68. package/src/encoder/ChangeRecorder.ts +276 -0
  69. package/src/encoder/ChangeTree.ts +674 -519
  70. package/src/encoder/EncodeDescriptor.ts +213 -0
  71. package/src/encoder/EncodeOperation.ts +107 -65
  72. package/src/encoder/Encoder.ts +630 -119
  73. package/src/encoder/MapJournal.ts +124 -0
  74. package/src/encoder/RefIdAllocator.ts +68 -0
  75. package/src/encoder/Root.ts +247 -120
  76. package/src/encoder/StateView.ts +592 -121
  77. package/src/encoder/changeTree/inheritedFlags.ts +217 -0
  78. package/src/encoder/changeTree/liveIteration.ts +74 -0
  79. package/src/encoder/changeTree/parentChain.ts +131 -0
  80. package/src/encoder/changeTree/treeAttachment.ts +171 -0
  81. package/src/encoder/streaming.ts +232 -0
  82. package/src/encoder/subscriptions.ts +71 -0
  83. package/src/index.ts +15 -3
  84. package/src/input/InputDecoder.ts +57 -0
  85. package/src/input/InputEncoder.ts +303 -0
  86. package/src/input/index.ts +3 -0
  87. package/src/types/HelperTypes.ts +121 -24
  88. package/src/types/TypeContext.ts +14 -2
  89. package/src/types/builder.ts +331 -0
  90. package/src/types/custom/ArraySchema.ts +210 -197
  91. package/src/types/custom/CollectionSchema.ts +115 -35
  92. package/src/types/custom/MapSchema.ts +162 -58
  93. package/src/types/custom/SetSchema.ts +128 -39
  94. package/src/types/custom/StreamSchema.ts +310 -0
  95. package/src/types/symbols.ts +93 -6
  96. package/src/utils.ts +4 -6
package/README.md CHANGED
@@ -260,6 +260,8 @@ up-to-date version of the schema definitions.
260
260
  ## Limitations and best practices
261
261
 
262
262
  - Each `Schema` structure can hold up to `64` fields. If you need more fields, use nested structures.
263
+ - Fields tagged with `@view`, `@unreliable`, or `@static` at field indexes `≥ 32` use a slower per-mutation classification path (linear scan over the tagged-field list instead of a single bitwise op). For schemas with more than 32 fields, declare frequently-mutated tagged fields earlier so they fall in the bitmask fast path.
264
+ - Schemas with `≤ 8` fields store per-field operation bytes inline in two numbers (no allocation per instance). Schemas with `> 8` fields allocate a small `Uint8Array` per instance for op storage. The difference is only material when allocating thousands of instances per tick — prefer narrower nested structures in that regime.
263
265
  - `NaN` or `null` numbers are encoded as `0`
264
266
  - `null` strings are encoded as `""`
265
267
  - `Infinity` numbers are encoded as `Number.MAX_SAFE_INTEGER`
@@ -1,12 +1,18 @@
1
1
  import { DefinitionType } from "./annotations.js";
2
- import { $descriptors, $fieldIndexesByViewTag, $numFields, $refTypeFieldIndexes, $viewFieldIndexes } from "./types/symbols.js";
2
+ import { TypeDefinition } from "./types/registry.js";
3
+ import { $descriptors, $encoders, $fieldIndexesByViewTag, $numFields, $refTypeFieldIndexes, $staticFieldIndexes, $streamFieldIndexes, $streamPriorities, $transientFieldIndexes, $unreliableFieldIndexes, $viewFieldIndexes } from "./types/symbols.js";
3
4
  export type MetadataField = {
4
5
  type: DefinitionType;
5
6
  name: string;
6
7
  index: number;
7
8
  tag?: number;
8
9
  unreliable?: boolean;
10
+ transient?: boolean;
9
11
  deprecated?: boolean;
12
+ owned?: boolean;
13
+ static?: boolean;
14
+ stream?: boolean;
15
+ optional?: boolean;
10
16
  };
11
17
  export type Metadata = {
12
18
  [$numFields]: number;
@@ -22,6 +28,26 @@ export type Metadata = {
22
28
  {
23
29
  [$refTypeFieldIndexes]: number[];
24
30
  } & // all field indexes containing Ref types (Schema, ArraySchema, MapSchema, etc)
31
+ {
32
+ [$unreliableFieldIndexes]: number[];
33
+ } & // all field indexes tagged with @unreliable
34
+ {
35
+ [$transientFieldIndexes]: number[];
36
+ } & // all field indexes tagged with @transient (not persisted to snapshots)
37
+ {
38
+ [$staticFieldIndexes]: number[];
39
+ } & // all field indexes tagged with @static (not tracked after assignment)
40
+ {
41
+ [$streamFieldIndexes]: number[];
42
+ } & // all field indexes holding a t.stream(...) collection
43
+ {
44
+ [$streamPriorities]: {
45
+ [field: number]: (view: any, element: any) => number;
46
+ };
47
+ } & // per-stream-field priority callback declared at schema definition time
48
+ {
49
+ [$encoders]: Array<(bytes: Uint8Array, value: any, it: any) => void>;
50
+ } & // pre-computed encoder fn per primitive field
25
51
  {
26
52
  [field: number]: MetadataField;
27
53
  } & // index => field name
@@ -33,17 +59,45 @@ export type Metadata = {
33
59
  [field: string]: PropertyDescriptor;
34
60
  };
35
61
  };
62
+ /**
63
+ * Given a normalized field type (`"number"`, `{ map: Foo }`, `Player`,
64
+ * etc.), split into the collection-type descriptor (`{ constructor:
65
+ * MapSchema, ... }`) if applicable and the inner child type. Shared by
66
+ * `@type()` decoration and `Metadata.setFields` — both need to build a
67
+ * property accessor that knows whether the slot holds a collection.
68
+ */
69
+ export declare function resolveFieldType(type: any): {
70
+ complexTypeKlass: TypeDefinition | false;
71
+ childType: any;
72
+ };
36
73
  export declare function getNormalizedType(type: any): DefinitionType;
37
74
  export declare const Metadata: {
38
75
  addField(metadata: any, index: number, name: string, type: DefinitionType, descriptor?: PropertyDescriptor): void;
39
76
  setTag(metadata: Metadata, fieldName: string, tag: number): void;
77
+ setUnreliable(metadata: Metadata, fieldName: string): void;
78
+ setTransient(metadata: Metadata, fieldName: string): void;
79
+ setStatic(metadata: Metadata, fieldName: string): void;
80
+ setStream(metadata: Metadata, fieldName: string): void;
81
+ /**
82
+ * Attach a declaration-scope priority callback to a stream field.
83
+ * Called at schema definition time (via `t.stream(X).priority(fn)` or
84
+ * `@type({ stream: X, priority: fn })`), looked up at stream-attach
85
+ * time to seed the instance's `_stream.priority` slot. The callback
86
+ * signature is `(view: StateView, element: V) => number` — only fires
87
+ * during `encodeView`, broadcast mode emits FIFO regardless.
88
+ */
89
+ setStreamPriority(metadata: Metadata, fieldName: string, fn: (view: any, element: any) => number): void;
90
+ getStreamPriority(metadata: Metadata | undefined, index: number): (view: any, element: any) => number;
40
91
  setFields<T extends {
41
92
  new (...args: any[]): InstanceType<T>;
42
93
  } = any>(target: T, fields: { [field in keyof InstanceType<T>]?: DefinitionType; }): T;
43
94
  isDeprecated(metadata: any, field: string): boolean;
44
- init(klass: any): void;
45
95
  initialize(constructor: any): Metadata;
46
96
  isValidInstance(klass: any): boolean;
47
97
  getFields(klass: any): any;
48
98
  hasViewTagAtIndex(metadata: Metadata, index: number): boolean;
99
+ hasUnreliableAtIndex(metadata: Metadata, index: number): boolean;
100
+ hasTransientAtIndex(metadata: Metadata, index: number): boolean;
101
+ hasStaticAtIndex(metadata: Metadata, index: number): boolean;
102
+ hasStreamAtIndex(metadata: Metadata, index: number): boolean;
49
103
  };
@@ -3,6 +3,8 @@ import { Iterator } from "./encoding/decode.js";
3
3
  import { Encoder } from "./encoder/Encoder.js";
4
4
  import { Decoder } from "./decoder/Decoder.js";
5
5
  import { Schema } from "./Schema.js";
6
+ import { FieldBuilder } from "./types/builder.js";
7
+ import { ArraySchema } from "./types/custom/ArraySchema.js";
6
8
  /**
7
9
  * Static methods available on Reflection
8
10
  */
@@ -28,44 +30,36 @@ interface ReflectionStatic {
28
30
  * Reflection
29
31
  */
30
32
  export declare const ReflectionField: import("./annotations.js").SchemaWithExtendsConstructor<{
31
- name: "string";
32
- type: "string";
33
- referencedType: "number";
34
- }, import("./index.js").AssignableProps<import("./index.js").InferSchemaInstanceType<{
35
- name: "string";
36
- type: "string";
37
- referencedType: "number";
38
- }>>, typeof Schema>;
33
+ name: FieldBuilder<string, false, false>;
34
+ type: FieldBuilder<string, false, false>;
35
+ referencedType: FieldBuilder<number, false, false>;
36
+ }, import("./types/HelperTypes.js").BuilderInitProps<{
37
+ name: FieldBuilder<string, false, false>;
38
+ type: FieldBuilder<string, false, false>;
39
+ referencedType: FieldBuilder<number, false, false>;
40
+ }>, typeof Schema>;
39
41
  export type ReflectionField = SchemaType<typeof ReflectionField>;
40
42
  export declare const ReflectionType: import("./annotations.js").SchemaWithExtendsConstructor<{
41
- id: "number";
42
- extendsId: "number";
43
- fields: import("./annotations.js").SchemaWithExtendsConstructor<{
44
- name: "string";
45
- type: "string";
46
- referencedType: "number";
47
- }, import("./index.js").AssignableProps<import("./index.js").InferSchemaInstanceType<{
48
- name: "string";
49
- type: "string";
50
- referencedType: "number";
51
- }>>, typeof Schema>[];
52
- }, import("./index.js").AssignableProps<import("./index.js").InferSchemaInstanceType<{
53
- id: "number";
54
- extendsId: "number";
55
- fields: import("./annotations.js").SchemaWithExtendsConstructor<{
56
- name: "string";
57
- type: "string";
58
- referencedType: "number";
59
- }, import("./index.js").AssignableProps<import("./index.js").InferSchemaInstanceType<{
60
- name: "string";
61
- type: "string";
62
- referencedType: "number";
63
- }>>, typeof Schema>[];
64
- }>>, typeof Schema>;
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("./types/HelperTypes.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>;
65
59
  export type ReflectionType = SchemaType<typeof ReflectionType>;
66
60
  export declare const Reflection: ReturnType<typeof schema<{
67
- types: [typeof ReflectionType];
68
- rootType: "number";
61
+ types: FieldBuilder<ArraySchema<ReflectionType>, true, false>;
62
+ rootType: FieldBuilder<number, false, false>;
69
63
  }>> & ReflectionStatic;
70
64
  export type Reflection = SchemaType<typeof Reflection>;
71
65
  export {};
package/build/Schema.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { OPERATION } from './encoding/spec.js';
2
2
  import { type DefinitionType } from "./annotations.js";
3
3
  import { AssignableProps, NonFunctionPropNames, ToJSON } from './types/HelperTypes.js';
4
- import { ChangeSetName, ChangeTree, IRef, Ref } from './encoder/ChangeTree.js';
5
- import { $decoder, $deleteByIndex, $encoder, $filter, $getByIndex, $refId, $track } from './types/symbols.js';
4
+ import { ChangeTree, IRef, Ref } from './encoder/ChangeTree.js';
5
+ import { $decoder, $deleteByIndex, $encoder, $filter, $getByIndex, $refId, $track, $values } from './types/symbols.js';
6
6
  import { StateView } from './encoder/StateView.js';
7
7
  import type { Decoder } from './decoder/Decoder.js';
8
8
  import type { Metadata } from './Metadata.js';
@@ -14,21 +14,58 @@ export declare class Schema<C = any> implements IRef {
14
14
  static [$encoder]: import("./encoder/EncodeOperation.js").EncodeOperation<any>;
15
15
  static [$decoder]: import("./decoder/DecodeOperation.js").DecodeOperation<any>;
16
16
  [$refId]?: number;
17
+ [$values]: any[];
17
18
  /**
18
- * Assign the property descriptors required to track changes on this instance.
19
- * @param instance
19
+ * Initialize change tracking on this instance.
20
+ * Field accessor descriptors (getter/setter) live on the prototype,
21
+ * installed once at class-definition time. Per-instance work is limited
22
+ * to allocating a ChangeTree and a values array.
20
23
  */
21
24
  static initialize(instance: any): void;
25
+ /**
26
+ * Decoder-side factory. Skips the user subclass ctor entirely —
27
+ * decoder-built instances are passive mirrors of server state, so any
28
+ * field initializer / ctor body work would be overwritten by the
29
+ * decoded ADDs immediately after. Assignment order matches
30
+ * {@link Schema.initialize} so V8 assigns the same hidden class
31
+ * ($changes, then $values), keeping decode-path ICs monomorphic even
32
+ * when tracked and untracked instances coexist.
33
+ *
34
+ * The `this:` constraint pins the return type to the concrete subclass
35
+ * when called as `Player.initializeForDecoder()`, not the base Schema.
36
+ */
37
+ static initializeForDecoder<T extends Schema = Schema>(this: {
38
+ prototype: T;
39
+ } & typeof Schema): T;
40
+ /**
41
+ * Check whether `type` describes a Schema *class* (a subclass
42
+ * constructor carrying `Symbol.metadata`, as installed by `@type`).
43
+ * Returns false for primitive type strings like `"number"`, descriptor
44
+ * objects like `{ map: Player }`, and Schema *instances*.
45
+ *
46
+ * For the instance-level check — "is this value a Schema instance?" —
47
+ * see {@link Schema.isSchema}.
48
+ */
22
49
  static is(type: DefinitionType): boolean;
23
50
  /**
24
- * Check if a value is an instance of Schema.
25
- * This method uses duck-typing to avoid issues with multiple @colyseus/schema versions.
51
+ * Check if a value is an *instance* of Schema. Uses duck-typing on
52
+ * `.assign` to work across multiple `@colyseus/schema` versions that
53
+ * may be loaded in the same process (e.g. bundled server types vs.
54
+ * client types in a p2p setup).
55
+ *
56
+ * For the class-level check — "is this type a Schema subclass?" —
57
+ * see {@link Schema.is}.
58
+ *
26
59
  * @param obj Value to check
27
60
  * @returns true if the value is a Schema instance
28
61
  */
29
62
  static isSchema(obj: any): obj is Schema;
30
63
  /**
31
- * Track property changes
64
+ * Track property changes. Exposed as an override point so downstream
65
+ * tools (debuggers, transparent proxies, custom instrumentation) can
66
+ * intercept per-field writes. Hot-path code in `annotations.ts` calls
67
+ * `(this.constructor as typeof Schema)[$track](...)` rather than
68
+ * `changeTree.change(...)` directly so any subclass override wins.
32
69
  */
33
70
  static [$track](changeTree: ChangeTree, index: number, operation?: OPERATION): void;
34
71
  /**
@@ -48,6 +85,12 @@ export declare class Schema<C = any> implements IRef {
48
85
  * @returns
49
86
  */
50
87
  assign<T extends Partial<this>>(props: AssignableProps<T>): this;
88
+ /**
89
+ * Metadata-driven property assignment.
90
+ * Reads tracked fields via property access (works with prototype accessors),
91
+ * then copies any remaining own properties for non-tracked fields.
92
+ */
93
+ protected static assignProps(target: any, source: any): void;
51
94
  /**
52
95
  * Restore the instance from JSON data.
53
96
  * @param jsonData JSON data to restore the instance from
@@ -61,6 +104,17 @@ export declare class Schema<C = any> implements IRef {
61
104
  * @param operation OPERATION to perform (detected automatically)
62
105
  */
63
106
  setDirty<K extends NonFunctionPropNames<this>>(property: K | number, operation?: OPERATION): void;
107
+ /** Stop recording mutations until resumeTracking() is called. */
108
+ pauseTracking(): void;
109
+ /** Re-enable automatic change tracking. */
110
+ resumeTracking(): void;
111
+ /**
112
+ * Run `fn` with change tracking paused, then resume.
113
+ * Returns the function's return value. Safe to nest.
114
+ */
115
+ untracked<T>(fn: () => T): T;
116
+ /** True while tracking is paused. */
117
+ get isTrackingPaused(): boolean;
64
118
  clone(): this;
65
119
  toJSON(this: any): ToJSON<this>;
66
120
  /**
@@ -78,7 +132,15 @@ export declare class Schema<C = any> implements IRef {
78
132
  * @returns
79
133
  */
80
134
  static debugRefIds<T extends Schema>(ref: T, showContents?: boolean, level?: number, decoder?: Decoder, keyPrefix?: string): string;
81
- static debugRefIdEncodingOrder<T extends Ref>(ref: T, changeSet?: ChangeSetName): number[];
135
+ /**
136
+ * @param changeSet
137
+ * - "changes": iterate the current-tick dirty queue (per-tick encode order)
138
+ * - "allChanges" / "allFilteredChanges" (legacy): structurally walk the
139
+ * tree in DFS preorder (matches the order in which full-sync emits
140
+ * trees). The two legacy modes differ by which side of the filter
141
+ * split they include.
142
+ */
143
+ static debugRefIdEncodingOrder<T extends Ref>(ref: T, changeSet?: "changes" | "allChanges" | "allFilteredChanges"): number[];
82
144
  static debugRefIdsFromDecoder(decoder: Decoder): string;
83
145
  /**
84
146
  * Return a string representation of the changes on a Schema instance.
@@ -89,5 +151,4 @@ export declare class Schema<C = any> implements IRef {
89
151
  * @returns
90
152
  */
91
153
  static debugChanges<T extends Ref>(instance: T, isEncodeAll?: boolean): string;
92
- static debugChangesDeep<T extends Schema>(ref: T, changeSetName?: "changes" | "allChanges" | "allFilteredChanges" | "filteredChanges"): string;
93
154
  }
@@ -3,10 +3,11 @@ 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 { OPERATION } from "./encoding/spec.js";
7
- import type { InferValueType, InferSchemaInstanceType, AssignableProps } from "./types/HelperTypes.js";
6
+ import type { InferValueType, InferSchemaInstanceType, BuilderInitProps } from "./types/HelperTypes.js";
8
7
  import { CollectionSchema } from "./types/custom/CollectionSchema.js";
9
8
  import { SetSchema } from "./types/custom/SetSchema.js";
9
+ import { StreamSchema } from "./types/custom/StreamSchema.js";
10
+ import { FieldBuilder } from "./types/builder.js";
10
11
  export type RawPrimitiveType = "string" | "number" | "boolean" | "int8" | "uint8" | "int16" | "uint16" | "int32" | "uint32" | "int64" | "uint64" | "float32" | "float64" | "bigint64" | "biguint64";
11
12
  export type PrimitiveType = RawPrimitiveType | typeof Schema | object;
12
13
  export type DefinitionType<T extends PrimitiveType = PrimitiveType> = T | T[] | {
@@ -14,26 +15,38 @@ export type DefinitionType<T extends PrimitiveType = PrimitiveType> = T | T[] |
14
15
  default?: InferValueType<T>;
15
16
  view?: boolean | number;
16
17
  sync?: boolean;
18
+ owned?: boolean;
17
19
  } | {
18
20
  array: T;
19
21
  default?: ArraySchema<InferValueType<T>>;
20
22
  view?: boolean | number;
21
23
  sync?: boolean;
24
+ owned?: boolean;
22
25
  } | {
23
26
  map: T;
24
27
  default?: MapSchema<InferValueType<T>>;
25
28
  view?: boolean | number;
26
29
  sync?: boolean;
30
+ owned?: boolean;
27
31
  } | {
28
32
  collection: T;
29
33
  default?: CollectionSchema<InferValueType<T>>;
30
34
  view?: boolean | number;
31
35
  sync?: boolean;
36
+ owned?: boolean;
32
37
  } | {
33
38
  set: T;
34
39
  default?: SetSchema<InferValueType<T>>;
35
40
  view?: boolean | number;
36
41
  sync?: boolean;
42
+ owned?: boolean;
43
+ } | {
44
+ stream: T;
45
+ default?: StreamSchema<InferValueType<T>>;
46
+ view?: boolean | number;
47
+ sync?: boolean;
48
+ owned?: boolean;
49
+ priority?: (view: any, element: InferValueType<T>) => number;
37
50
  };
38
51
  export type Definition = {
39
52
  [field: string]: DefinitionType;
@@ -60,10 +73,20 @@ export declare function entity(constructor: any): any;
60
73
  * ```
61
74
  */
62
75
  export declare function view<T>(tag?: number): (target: T, fieldName: string) => void;
76
+ export declare function owned<T>(target: T, field: string): void;
63
77
  export declare function unreliable<T>(target: T, field: string): void;
78
+ /**
79
+ * @transient — mark a field as not persisted to snapshots (encodeAll /
80
+ * encodeAllView). Transient fields are still emitted on per-tick patches
81
+ * (reliable or unreliable), but late-joining clients won't see them until
82
+ * the next mutation.
83
+ *
84
+ * Orthogonal to @unreliable: a field can be either, both, or neither.
85
+ */
86
+ export declare function transient<T>(target: T, field: string): void;
64
87
  export declare function type(type: DefinitionType, options?: TypeOptions): PropertyDecorator;
65
- export declare function getPropertyDescriptor(fieldCached: string, fieldIndex: number, type: DefinitionType, complexTypeKlass: TypeDefinition): {
66
- get: (this: Schema) => number | ((index: number) => any) | ((index: number) => void) | (() => Schema<any>) | (<T extends Partial<Schema<any>>>(props: AssignableProps<T>) => Schema<any>) | ((jsonData: import("./index.js").ToJSON<Schema<any>>) => Schema<any>) | (<K extends "~refId">(property: number | K, operation?: OPERATION) => void) | ((this: any) => import("./index.js").ToJSON<Schema<any>>) | (() => void);
88
+ export declare function getPropertyDescriptor(fieldName: string, fieldIndex: number, type: DefinitionType, complexTypeKlass: TypeDefinition | false): {
89
+ get: (this: Schema) => any;
67
90
  set: (this: Schema, value: any) => void;
68
91
  enumerable: boolean;
69
92
  configurable: boolean;
@@ -73,37 +96,61 @@ export declare function getPropertyDescriptor(fieldCached: string, fieldIndex: n
73
96
  * The previous `@type()` annotation should remain along with this one.
74
97
  */
75
98
  export declare function deprecated(throws?: boolean): PropertyDecorator;
76
- export declare function defineTypes(target: typeof Schema, fields: Definition, options?: TypeOptions): typeof Schema;
77
99
  type ExtractInitProps<T> = T extends {
78
100
  initialize: (...args: infer P) => void;
79
- } ? P extends readonly [] ? never : P extends readonly [infer First] ? First extends object ? First : P : P : T extends Definition ? AssignableProps<InferSchemaInstanceType<T>> : never;
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;
80
103
  type IsInitPropsRequired<T> = T extends {
81
- initialize: (props: any) => void;
82
- } ? true : T extends {
104
+ initialize: (...args: infer P) => void;
105
+ } ? P extends readonly [] ? false : true : HasRequiredKeys<BuilderInitProps<T>>;
106
+ type HasExplicitInit<T> = T extends {
83
107
  initialize: (...args: infer P) => void;
84
108
  } ? P extends readonly [] ? false : true : false;
85
- export interface SchemaWithExtends<T extends Definition, P extends typeof Schema> {
86
- extends: <T2 extends Definition = Definition>(fields: T2 & ThisType<InferSchemaInstanceType<T & T2>>, name?: string) => SchemaWithExtendsConstructor<T & T2, ExtractInitProps<T2>, P>;
109
+ /**
110
+ * A `schema()` field definition accepts a FieldBuilder, a Schema subclass
111
+ * (shorthand for `t.ref(Class)`), or a method (attached to the prototype).
112
+ */
113
+ export type FieldsAndMethods = Record<string, FieldBuilder<any, boolean, boolean> | (new (...args: any[]) => Schema) | Function>;
114
+ export interface SchemaWithExtends<T, P extends typeof Schema> {
115
+ extend: <T2 extends FieldsAndMethods = FieldsAndMethods>(fields: T2 & ThisType<InferSchemaInstanceType<T & T2>>, name?: string) => SchemaWithExtendsConstructor<T & T2, ExtractInitProps<T & T2>, P>;
87
116
  }
88
117
  /**
89
- * Get the type of the schema defined via `schema({...})` method.
118
+ * Get the type of the schema defined via `schema('Name', {...})` method.
90
119
  *
91
120
  * @example
92
- * const Entity = schema({
93
- * x: "number",
94
- * y: "number",
121
+ * const Entity = schema('Entity', {
122
+ * x: t.number(),
123
+ * y: t.number(),
95
124
  * });
96
125
  * type Entity = SchemaType<typeof Entity>;
97
126
  */
98
127
  export type SchemaType<T extends {
99
128
  '~type': any;
100
129
  }> = T['~type'];
101
- export interface SchemaWithExtendsConstructor<T extends Definition, InitProps, P extends typeof Schema> extends SchemaWithExtends<T, P> {
130
+ export interface SchemaWithExtendsConstructor<T, InitProps, P extends typeof Schema> extends SchemaWithExtends<T, P> {
102
131
  '~type': InferSchemaInstanceType<T>;
103
- new (...args: [InitProps] extends [never] ? [] : InitProps extends readonly any[] ? InitProps : IsInitPropsRequired<T> extends true ? [InitProps] : [InitProps?]): InferSchemaInstanceType<T> & InstanceType<P>;
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>;
104
135
  prototype: InferSchemaInstanceType<T> & InstanceType<P> & {
105
136
  initialize(...args: [InitProps] extends [never] ? [] : InitProps extends readonly any[] ? InitProps : [InitProps]): void;
106
137
  };
107
138
  }
108
- export declare function schema<T extends Record<string, DefinitionType>, P extends typeof Schema = typeof Schema>(fieldsAndMethods: T & ThisType<InferSchemaInstanceType<T>>, name?: string, inherits?: P): SchemaWithExtendsConstructor<T, ExtractInitProps<T>, P>;
139
+ /**
140
+ * Define a Schema class declaratively.
141
+ *
142
+ * @example
143
+ * import { schema, t } from '@colyseus/schema';
144
+ *
145
+ * const Player = schema({
146
+ * hp: t.uint8().default(100),
147
+ * name: t.string().view(),
148
+ * takeDamage(n: number) { this.hp -= n; },
149
+ * }, 'Player');
150
+ *
151
+ * const Warrior = Player.extend({
152
+ * weapon: t.string(),
153
+ * }, 'Warrior');
154
+ */
155
+ export declare function schema<T extends FieldsAndMethods, P extends typeof Schema = typeof Schema>(fieldsAndMethods: T & ThisType<InferSchemaInstanceType<T>>, name?: string, inherits?: P): SchemaWithExtendsConstructor<T, ExtractInitProps<T>, P>;
109
156
  export {};