@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
@@ -1,9 +1,11 @@
1
- import type { Definition, DefinitionType, PrimitiveType, RawPrimitiveType } from "../annotations.js";
1
+ import type { PrimitiveType, RawPrimitiveType } from "../annotations.js";
2
2
  import type { Schema } from "../Schema.js";
3
3
  import type { ArraySchema } from "./custom/ArraySchema.js";
4
4
  import type { CollectionSchema } from "./custom/CollectionSchema.js";
5
5
  import type { MapSchema } from "./custom/MapSchema.js";
6
6
  import type { SetSchema } from "./custom/SetSchema.js";
7
+ import type { StreamSchema } from "./custom/StreamSchema.js";
8
+ import type { FieldBuilder } from "./builder.js";
7
9
  export type Constructor<T = {}> = new (...args: any[]) => T;
8
10
  type PrimitiveStringToType<T> = T extends "string" ? string : T extends "number" | "int8" | "uint8" | "int16" | "uint16" | "int32" | "uint32" | "int64" | "uint64" | "float32" | "float64" ? number : T extends "boolean" ? boolean : T;
9
11
  export interface Collection<K = any, V = any, IT = V> {
@@ -11,7 +13,7 @@ export interface Collection<K = any, V = any, IT = V> {
11
13
  forEach(callback: Function): void;
12
14
  entries(): IterableIterator<[K, V]>;
13
15
  }
14
- export type InferValueType<T extends DefinitionType> = T extends "string" ? string : T extends "number" ? number : T extends "int8" ? number : T extends "uint8" ? number : T extends "int16" ? number : T extends "uint16" ? number : T extends "int32" ? number : T extends "uint32" ? number : T extends "int64" ? number : T extends "uint64" ? number : T extends "float32" ? number : T extends "float64" ? number : T extends "boolean" ? boolean : T extends {
16
+ export type InferValueType<T> = T extends FieldBuilder<infer V> ? V : T extends "string" ? string : T extends "number" ? number : T extends "int8" ? number : T extends "uint8" ? number : T extends "int16" ? number : T extends "uint16" ? number : T extends "int32" ? number : T extends "uint32" ? number : T extends "int64" ? number : T extends "uint64" ? number : T extends "float32" ? number : T extends "float64" ? number : T extends "boolean" ? boolean : T extends {
15
17
  type: infer ChildType extends PrimitiveType;
16
18
  } ? InferValueType<ChildType> : T extends {
17
19
  type: infer ChildType extends Constructor;
@@ -30,6 +32,14 @@ export type InferValueType<T extends DefinitionType> = T extends "string" ? stri
30
32
  collection: infer ChildType;
31
33
  };
32
34
  } ? (ChildType extends Record<string | number, string | number> ? CollectionSchema<ChildType[keyof ChildType]> : CollectionSchema<ChildType>) : T extends {
35
+ type: {
36
+ stream: infer ChildType extends Constructor;
37
+ };
38
+ } ? StreamSchema<InstanceType<ChildType>> : T extends {
39
+ type: {
40
+ stream: infer ChildType;
41
+ };
42
+ } ? StreamSchema<ChildType> : T extends {
33
43
  type: infer ChildType;
34
44
  } ? (ChildType extends Record<string | number, string | number> ? ChildType[keyof ChildType] : ChildType) : T extends Array<infer ChildType extends Constructor> ? ArraySchema<InstanceType<ChildType>> : T extends Array<infer ChildType> ? (ChildType extends Record<string | number, string | number> ? ArraySchema<ChildType[keyof ChildType]> : ArraySchema<PrimitiveStringToType<ChildType>>) : T extends {
35
45
  array: infer ChildType extends Constructor;
@@ -51,9 +61,19 @@ export type InferValueType<T extends DefinitionType> = T extends "string" ? stri
51
61
  collection: infer ChildType extends RawPrimitiveType;
52
62
  } ? CollectionSchema<InferValueType<ChildType>> : T extends {
53
63
  collection: infer ChildType;
54
- } ? (ChildType extends Record<string | number, string | number> ? CollectionSchema<ChildType[keyof ChildType]> : CollectionSchema<ChildType>) : T extends Constructor ? InstanceType<T> : T extends Record<string | number, string | number> ? T[keyof T] : T extends PrimitiveType ? T : never;
55
- export type InferSchemaInstanceType<T extends Definition> = {
56
- [K in keyof T]: T[K] extends (...args: any[]) => any ? (T[K] extends new (...args: any[]) => any ? InferValueType<T[K]> : T[K]) : InferValueType<T[K]>;
64
+ } ? (ChildType extends Record<string | number, string | number> ? CollectionSchema<ChildType[keyof ChildType]> : CollectionSchema<ChildType>) : T extends {
65
+ stream: infer ChildType extends Constructor;
66
+ } ? StreamSchema<InstanceType<ChildType>> : T extends {
67
+ stream: infer ChildType;
68
+ } ? StreamSchema<ChildType> : T extends Constructor ? InstanceType<T> : T extends Record<string | number, string | number> ? T[keyof T] : T extends PrimitiveType ? T : never;
69
+ type OptionalBuilderKeys<T> = {
70
+ [K in keyof T]: T[K] extends FieldBuilder<infer V> ? (undefined extends V ? K : never) : never;
71
+ }[keyof T];
72
+ type RequiredBuilderKeys<T> = Exclude<keyof T, OptionalBuilderKeys<T>>;
73
+ export type InferSchemaInstanceType<T> = {
74
+ [K in RequiredBuilderKeys<T>]: T[K] extends FieldBuilder<any> ? InferValueType<T[K]> : T[K] extends (...args: any[]) => any ? (T[K] extends new (...args: any[]) => any ? InferValueType<T[K]> : T[K]) : InferValueType<T[K]>;
75
+ } & {
76
+ [K in OptionalBuilderKeys<T>]?: T[K] extends FieldBuilder<infer V> ? V : never;
57
77
  } & Schema;
58
78
  export type NonFunctionProps<T> = Omit<T, {
59
79
  [K in keyof T]: T[K] extends Function ? K : never;
@@ -65,9 +85,18 @@ export type NonFunctionNonPrimitivePropNames<T> = {
65
85
  [K in keyof T]: T[K] extends Function ? never : T[K] extends number | string | boolean ? never : K;
66
86
  }[keyof T];
67
87
  type ToJSONValue<U> = U extends Schema ? ToJSON<U> : PrimitiveStringToType<U>;
68
- export type ToJSON<T> = {
69
- [K in keyof T as T[K] extends Function ? never : K]: T[K] extends MapSchema<infer U> ? Record<string, ToJSONValue<U>> : T[K] extends Map<string, infer U> ? Record<string, ToJSONValue<U>> : T[K] extends ArraySchema<infer U> ? ToJSONValue<U>[] : T[K] extends SetSchema<infer U> ? ToJSONValue<U>[] : T[K] extends CollectionSchema<infer U> ? ToJSONValue<U>[] : T[K] extends Schema ? ToJSON<T[K]> : T[K];
70
- };
88
+ type ToJSONField<X> = X extends MapSchema<infer U> ? Record<string, ToJSONValue<U>> : X extends Map<string, infer U> ? Record<string, ToJSONValue<U>> : X extends ArraySchema<infer U> ? ToJSONValue<U>[] : X extends SetSchema<infer U> ? ToJSONValue<U>[] : X extends CollectionSchema<infer U> ? ToJSONValue<U>[] : X extends Schema ? ToJSON<X> : X;
89
+ type ToJSONRequiredKeys<T> = {
90
+ [K in keyof T]-?: undefined extends T[K] ? never : K;
91
+ }[keyof T];
92
+ type ToJSONOptionalKeys<T> = {
93
+ [K in keyof T]-?: undefined extends T[K] ? K : never;
94
+ }[keyof T];
95
+ export type ToJSON<T> = NonFunctionProps<{
96
+ [K in ToJSONRequiredKeys<T>]: ToJSONField<T[K]>;
97
+ } & {
98
+ [K in ToJSONOptionalKeys<T>]?: ToJSONField<Exclude<T[K], undefined>>;
99
+ }>;
71
100
  export type IsNever<T> = [T] extends [never] ? true : false;
72
101
  /**
73
102
  * Type helper for .assign() method - allows assigning values in a flexible way
@@ -76,6 +105,35 @@ export type IsNever<T> = [T] extends [never] ? true : false;
76
105
  * - Collections can be assigned from their JSON representations
77
106
  */
78
107
  export type AssignableProps<T> = {
79
- [K in NonFunctionPropNames<T>]?: T[K] extends MapSchema<infer U> ? MapSchema<U> | Record<string, U extends Schema ? (U | AssignableProps<U>) : U> : T[K] extends ArraySchema<infer U> ? ArraySchema<U> | (U extends Schema ? (U | AssignableProps<U>)[] : U[]) : T[K] extends SetSchema<infer U> ? SetSchema<U> | Set<U> | (U extends Schema ? (U | AssignableProps<U>)[] : U[]) : T[K] extends CollectionSchema<infer U> ? CollectionSchema<U> | (U extends Schema ? (U | AssignableProps<U>)[] : U[]) : T[K] extends Schema ? T[K] | AssignableProps<T[K]> : T[K];
108
+ [K in NonFunctionPropNames<T>]?: AssignableValue<T[K]>;
109
+ };
110
+ /**
111
+ * Value-level assignment shape shared by `AssignableProps` and
112
+ * `BuilderInitProps`. Captures the "you can pass the real instance, or the
113
+ * plain-object / array shape" pattern.
114
+ */
115
+ export type AssignableValue<V> = V extends MapSchema<infer U> ? MapSchema<U> | Record<string, U extends Schema ? (U | AssignableProps<U>) : U> : V extends ArraySchema<infer U> ? ArraySchema<U> | (U extends Schema ? (U | AssignableProps<U>)[] : U[]) : V extends SetSchema<infer U> ? SetSchema<U> | Set<U> | (U extends Schema ? (U | AssignableProps<U>)[] : U[]) : V extends CollectionSchema<infer U> ? CollectionSchema<U> | (U extends Schema ? (U | AssignableProps<U>)[] : U[]) : V extends Schema ? V | AssignableProps<V> : V;
116
+ export type RefHasDefault<C> = C extends {
117
+ prototype: {
118
+ initialize(...args: infer P): any;
119
+ };
120
+ } ? (P extends readonly [] ? true : false) : true;
121
+ type FieldValue<F> = F extends FieldBuilder<infer V, boolean, boolean> ? V : F extends new (...args: any[]) => infer I ? (I extends Schema ? I : never) : never;
122
+ type KeyClass<T, K extends keyof T> = T[K] extends FieldBuilder<unknown, infer D extends boolean, infer O extends boolean> ? (D extends true ? "optional" : O extends true ? "optional" : "required") : T[K] extends new (...args: any[]) => Schema ? (RefHasDefault<T[K]> extends true ? "optional" : "required") : "none";
123
+ export type BuilderRequiredKeys<T> = {
124
+ [K in keyof T]-?: KeyClass<T, K> extends "required" ? K : never;
125
+ }[keyof T];
126
+ export type BuilderOptionalKeys<T> = {
127
+ [K in keyof T]-?: KeyClass<T, K> extends "optional" ? K : never;
128
+ }[keyof T];
129
+ /**
130
+ * Constructor/init-props type for a schema() fields map. Required fields
131
+ * (primitives without `.default()` or `.optional()`, and Schema refs with
132
+ * non-zero-arg `initialize()`) are `:`; everything else is `?:`.
133
+ */
134
+ export type BuilderInitProps<T> = {
135
+ [K in BuilderRequiredKeys<T>]: AssignableValue<FieldValue<T[K]>>;
136
+ } & {
137
+ [K in BuilderOptionalKeys<T>]?: AssignableValue<Exclude<FieldValue<T[K]>, undefined>>;
80
138
  };
81
139
  export {};
@@ -8,6 +8,15 @@ export declare class TypeContext {
8
8
  parentFiltered: {
9
9
  [typeIdAndParentIndex: string]: boolean;
10
10
  };
11
+ /**
12
+ * True iff `parentFiltered` has at least one entry. Flipped on by
13
+ * `registerFilteredByParent` and read in `checkInheritedFlags` as a
14
+ * cheap gate to skip the string-keyed `parentFiltered[key]` lookup
15
+ * when no class has registered filter inheritance via ancestry — the
16
+ * common case when @view tags exist only on sibling fields, not
17
+ * along any attachment chain.
18
+ */
19
+ hasParentFilteredEntries: boolean;
11
20
  /**
12
21
  * For inheritance support
13
22
  * Keeps track of which classes extends which. (parent -> children)
@@ -0,0 +1,192 @@
1
+ import type { ArraySchema } from "./custom/ArraySchema.js";
2
+ import type { MapSchema } from "./custom/MapSchema.js";
3
+ import type { SetSchema } from "./custom/SetSchema.js";
4
+ import type { CollectionSchema } from "./custom/CollectionSchema.js";
5
+ import type { StreamSchema } from "./custom/StreamSchema.js";
6
+ import type { Schema } from "../Schema.js";
7
+ import type { DefinitionType, RawPrimitiveType } from "../annotations.js";
8
+ import type { InferValueType, Constructor } from "./HelperTypes.js";
9
+ import { $builder } from "./symbols.js";
10
+ /**
11
+ * Internal record produced by FieldBuilder#toDefinition() and consumed by schema().
12
+ */
13
+ export interface BuilderDefinition {
14
+ type: DefinitionType;
15
+ default?: any;
16
+ hasDefault: boolean;
17
+ view?: number;
18
+ owned?: boolean;
19
+ unreliable?: boolean;
20
+ transient?: boolean;
21
+ deprecated?: boolean;
22
+ deprecatedThrows?: boolean;
23
+ static?: boolean;
24
+ stream?: boolean;
25
+ optional?: boolean;
26
+ /** Declaration-scope priority callback for `.stream()` fields. */
27
+ streamPriority?: (view: any, element: any) => number;
28
+ }
29
+ /**
30
+ * Type-function that infers the instance value for a builder.
31
+ */
32
+ export type BuilderOf<T> = FieldBuilder<T>;
33
+ /**
34
+ * Chainable field builder. Instances are produced by `t.*()` factories.
35
+ *
36
+ * Generics:
37
+ * - `T` is the runtime/JS type of the field (e.g. `number`, `string`,
38
+ * `ArraySchema<Item>`). `.optional()` widens it to `T | undefined`
39
+ * so the inferred instance/toJSON shapes reflect absence.
40
+ * - `HasDefault` is a compile-time flag that the field carries a
41
+ * construction-time default — either an explicit `.default(v)` or an
42
+ * auto-default from a collection factory (`t.array`, `t.map`, …) or a
43
+ * Schema ref whose `initialize` takes zero args.
44
+ * - `IsOptional` is a compile-time brand for `.optional()`. Both
45
+ * `HasDefault` and `IsOptional` make the field omittable in
46
+ * `BuilderInitProps<T>`. A separate brand (rather than reading
47
+ * `undefined extends V`) sidesteps a TypeScript quirk where
48
+ * class-generic-inferred `V` resolves `undefined extends V` as `true`
49
+ * even for non-undefined types.
50
+ *
51
+ * schema() reads the internal configuration via `toDefinition()` and wires
52
+ * up metadata through the existing pipeline.
53
+ */
54
+ export declare class FieldBuilder<T = unknown, HasDefault extends boolean = false, IsOptional extends boolean = false> {
55
+ readonly [$builder]: true;
56
+ _type: DefinitionType;
57
+ _default: any;
58
+ _hasDefault: boolean;
59
+ _view: number | undefined;
60
+ _owned: boolean;
61
+ _unreliable: boolean;
62
+ _transient: boolean;
63
+ _deprecated: boolean;
64
+ _deprecatedThrows: boolean;
65
+ _static: boolean;
66
+ _stream: boolean;
67
+ _optional: boolean;
68
+ _streamPriority: ((view: any, element: any) => number) | undefined;
69
+ constructor(type: DefinitionType);
70
+ /** Provide a default value for this field. */
71
+ default(value: T): FieldBuilder<T, true, IsOptional>;
72
+ /** Tag this field with a view tag (DEFAULT_VIEW_TAG when called without arg). */
73
+ view(tag?: number): this;
74
+ /** Mark this field as owned (encoder-side ownership filtering). */
75
+ owned(): this;
76
+ /**
77
+ * Mark this field as unreliable — tick patches emit it on the unreliable
78
+ * transport channel. Still persisted to full-sync snapshots unless also
79
+ * tagged with `.transient()`.
80
+ */
81
+ unreliable(): this;
82
+ /**
83
+ * Mark this field as transient — NOT persisted to full-sync snapshots
84
+ * (`encodeAll` / `encodeAllView`). Late-joining clients see the field
85
+ * only after its next mutation is emitted on a tick patch. Orthogonal
86
+ * to `.unreliable()`.
87
+ */
88
+ transient(): this;
89
+ /**
90
+ * Mark this field as static.
91
+ * - Primitive / Schema fields: synchronized once, skips change tracking.
92
+ * - Stream fields (`t.stream(X).static()`): child elements are frozen
93
+ * after add — post-add field mutations on elements become no-ops.
94
+ */
95
+ static(): this;
96
+ /**
97
+ * Opt a collection field into priority-batched streaming delivery —
98
+ * ADDs drain at most `maxPerTick` per tick per view (or per broadcast
99
+ * tick without a view). Applies to `t.map(X)` / `t.set(X)` /
100
+ * `t.collection(X)`. Redundant on `t.stream(X)` (the factory already
101
+ * sets this flag).
102
+ *
103
+ * **Not supported on `t.array(X)`.** Array positional operations
104
+ * (`splice`, `unshift`, `reverse`) shift every subsequent index —
105
+ * holding some ADDs back for a later tick while indexes mutate
106
+ * underneath would produce a decoder-side state that doesn't match
107
+ * the server. Use `t.stream(X)` (stable monotonic positions) or
108
+ * `t.map(X).stream()` (keys never shift) instead.
109
+ */
110
+ stream(): this;
111
+ /**
112
+ * Attach a priority callback for per-view `encodeView` delivery. The
113
+ * callback receives the client's StateView and the candidate element;
114
+ * higher return values emit first. Does nothing in broadcast mode
115
+ * (shared `encode()` drains FIFO). Only meaningful on stream fields.
116
+ *
117
+ * ```ts
118
+ * t.stream(Enemy).priority((view, enemy) =>
119
+ * -dist2(view.anchor, enemy)
120
+ * )
121
+ * ```
122
+ */
123
+ priority<V = any>(fn: (view: any, element: V) => number): this;
124
+ /** Mark this field as deprecated. Pass `false` to silence the access error. */
125
+ deprecated(throws?: boolean): this;
126
+ /**
127
+ * Mark this field as optional — inferred instance type becomes
128
+ * `T | undefined` and the property becomes omittable in initialization
129
+ * props. Skips the auto-instantiation of collection / Schema-ref
130
+ * defaults, so the field starts as `undefined` at runtime.
131
+ */
132
+ optional(): FieldBuilder<T | undefined, HasDefault, true>;
133
+ toDefinition(): BuilderDefinition;
134
+ }
135
+ export declare function isBuilder(value: any): value is FieldBuilder<any>;
136
+ export type ChildType = RawPrimitiveType | Constructor<Schema> | FieldBuilder<any>;
137
+ interface ArrayFactory {
138
+ <C extends Constructor<Schema>>(child: C): FieldBuilder<ArraySchema<InstanceType<C>>, true, false>;
139
+ <P extends RawPrimitiveType>(child: P): FieldBuilder<ArraySchema<InferValueType<P>>, true, false>;
140
+ <V>(child: FieldBuilder<V>): FieldBuilder<ArraySchema<V>, true, false>;
141
+ }
142
+ interface MapFactory {
143
+ <C extends Constructor<Schema>>(child: C): FieldBuilder<MapSchema<InstanceType<C>>, true, false>;
144
+ <P extends RawPrimitiveType>(child: P): FieldBuilder<MapSchema<InferValueType<P>>, true, false>;
145
+ <V>(child: FieldBuilder<V>): FieldBuilder<MapSchema<V>, true, false>;
146
+ }
147
+ interface SetFactory {
148
+ <C extends Constructor<Schema>>(child: C): FieldBuilder<SetSchema<InstanceType<C>>, true, false>;
149
+ <P extends RawPrimitiveType>(child: P): FieldBuilder<SetSchema<InferValueType<P>>, true, false>;
150
+ <V>(child: FieldBuilder<V>): FieldBuilder<SetSchema<V>, true, false>;
151
+ }
152
+ interface CollectionFactory {
153
+ <C extends Constructor<Schema>>(child: C): FieldBuilder<CollectionSchema<InstanceType<C>>, true, false>;
154
+ <P extends RawPrimitiveType>(child: P): FieldBuilder<CollectionSchema<InferValueType<P>>, true, false>;
155
+ <V>(child: FieldBuilder<V>): FieldBuilder<CollectionSchema<V>, true, false>;
156
+ }
157
+ interface StreamFactory {
158
+ <C extends Constructor<Schema>>(child: C): FieldBuilder<StreamSchema<InstanceType<C>>, true, false>;
159
+ }
160
+ type RefHasDefault<C> = C extends {
161
+ prototype: {
162
+ initialize(...args: infer P): any;
163
+ };
164
+ } ? (P extends readonly [] ? true : false) : true;
165
+ interface RefFactory {
166
+ <C extends Constructor<Schema>>(ctor: C): FieldBuilder<InstanceType<C>, RefHasDefault<C>, false>;
167
+ }
168
+ export declare const t: Readonly<{
169
+ string: () => FieldBuilder<string, false, false>;
170
+ number: () => FieldBuilder<number, false, false>;
171
+ boolean: () => FieldBuilder<boolean, false, false>;
172
+ int8: () => FieldBuilder<number, false, false>;
173
+ uint8: () => FieldBuilder<number, false, false>;
174
+ int16: () => FieldBuilder<number, false, false>;
175
+ uint16: () => FieldBuilder<number, false, false>;
176
+ int32: () => FieldBuilder<number, false, false>;
177
+ uint32: () => FieldBuilder<number, false, false>;
178
+ int64: () => FieldBuilder<number, false, false>;
179
+ uint64: () => FieldBuilder<number, false, false>;
180
+ float32: () => FieldBuilder<number, false, false>;
181
+ float64: () => FieldBuilder<number, false, false>;
182
+ bigint64: () => FieldBuilder<bigint, false, false>;
183
+ biguint64: () => FieldBuilder<bigint, false, false>;
184
+ /** Reference to a Schema subtype. `t.array(Item)` usually reads better, but this is available when a plain ref is needed. */
185
+ ref: RefFactory;
186
+ array: ArrayFactory;
187
+ map: MapFactory;
188
+ set: SetFactory;
189
+ collection: CollectionFactory;
190
+ stream: StreamFactory;
191
+ }>;
192
+ export {};
@@ -1,4 +1,4 @@
1
- import { $changes, $childType, $decoder, $deleteByIndex, $onEncodeEnd, $encoder, $filter, $getByIndex, $onDecodeEnd, $refId } from "../symbols.js";
1
+ import { $changes, $childType, $decoder, $deleteByIndex, $onEncodeEnd, $encoder, $filter, $getByIndex, $onDecodeEnd, $proxyTarget, $refId } from "../symbols.js";
2
2
  import type { Schema } from "../../Schema.js";
3
3
  import { type IRef, ChangeTree } from "../../encoder/ChangeTree.js";
4
4
  import { OPERATION } from "../../encoding/spec.js";
@@ -8,15 +8,16 @@ export declare class ArraySchema<V = any> implements Array<V>, Collection<number
8
8
  [n: number]: V;
9
9
  [$changes]: ChangeTree;
10
10
  [$refId]?: number;
11
+ [$proxyTarget]: this;
11
12
  protected [$childType]: string | typeof Schema;
12
13
  protected items: V[];
13
14
  protected tmpItems: V[];
14
- protected deletedIndexes: {
15
- [index: number]: boolean;
16
- };
15
+ protected deletedIndexes: boolean[];
17
16
  protected isMovingItems: boolean;
18
17
  static [$encoder]: import("../../encoder/EncodeOperation.js").EncodeOperation<any>;
19
18
  static [$decoder]: import("../../decoder/DecodeOperation.js").DecodeOperation<any>;
19
+ /** Integer tag read by `decodeKeyValueOperation` — see `CollectionKind`. */
20
+ static readonly COLLECTION_KIND: 2;
20
21
  /**
21
22
  * Determine if a property must be filtered.
22
23
  * - If returns false, the property is NOT going to be encoded.
@@ -30,8 +31,22 @@ export declare class ArraySchema<V = any> implements Array<V>, Collection<number
30
31
  static is(type: any): boolean;
31
32
  static from<T>(iterable: Iterable<T> | ArrayLike<T>): ArraySchema<T>;
32
33
  constructor(...items: V[]);
34
+ /**
35
+ * Decoder-side factory. Skips the `ChangeTree` allocation and
36
+ * replicates the class-field initializers by hand (since `Object.create`
37
+ * bypasses them). Must stay in sync with the class-field declarations
38
+ * and the constructor body above.
39
+ *
40
+ * Pass the Proxy to `installUntrackedChangeTree` as the public identity
41
+ * so children set their parent to the Proxy, not the raw target.
42
+ */
43
+ static initializeForDecoder<V = any>(): ArraySchema<V>;
33
44
  set length(newLength: number);
34
45
  get length(): number;
46
+ pauseTracking(): void;
47
+ resumeTracking(): void;
48
+ untracked<T>(fn: () => T): T;
49
+ get isTrackingPaused(): boolean;
35
50
  push(...values: V[]): number;
36
51
  /**
37
52
  * Removes the last element from an array and returns it.
@@ -260,6 +275,12 @@ export declare class ArraySchema<V = any> implements Array<V>, Collection<number
260
275
  * @returns
261
276
  */
262
277
  move(cb: (arr: this) => void): this;
278
+ /**
279
+ * Encoder-only. Reads the staged-snapshot (`tmpItems`) so the encoder can
280
+ * resolve a wire-index even after the user has mutated `items` mid-tick.
281
+ * The decoder reads `items[index]` directly — see `decodeArray` and
282
+ * `$deleteByIndex` below.
283
+ */
263
284
  [$getByIndex](index: number, isEncodeAll?: boolean): any;
264
285
  [$deleteByIndex](index: number): void;
265
286
  protected [$onEncodeEnd](): void;
@@ -1,6 +1,7 @@
1
1
  import { $changes, $childType, $decoder, $deleteByIndex, $encoder, $filter, $getByIndex, $onEncodeEnd, $refId } from "../symbols.js";
2
2
  import { ChangeTree, type IRef } from "../../encoder/ChangeTree.js";
3
3
  import { Collection } from "../HelperTypes.js";
4
+ import { type StreamableState } from "../../encoder/streaming.js";
4
5
  import type { StateView } from "../../encoder/StateView.js";
5
6
  import type { Schema } from "../../Schema.js";
6
7
  type K = number;
@@ -8,14 +9,28 @@ export declare class CollectionSchema<V = any> implements Collection<K, V>, IRef
8
9
  [$changes]: ChangeTree;
9
10
  [$refId]?: number;
10
11
  protected [$childType]: string | typeof Schema;
12
+ /** The user-visible data, keyed directly by the wire-protocol index. */
11
13
  protected $items: Map<number, V>;
12
- protected $indexes: Map<number, number>;
14
+ /** Snapshots of values that were deleted this tick (for filter visibility). */
13
15
  protected deletedItems: {
14
16
  [field: string]: V;
15
17
  };
18
+ /** Monotonic counter for assigning indexes to newly-added items. */
16
19
  protected $refId: number;
20
+ /**
21
+ * Streamable state — lazily allocated when the field is opted into
22
+ * streaming via `t.collection(X).stream()`. See MapSchema for the
23
+ * same pattern / rationale.
24
+ */
25
+ _stream?: StreamableState;
26
+ get maxPerTick(): number;
27
+ set maxPerTick(n: number);
28
+ get priority(): ((view: any, element: V) => number) | undefined;
29
+ set priority(fn: ((view: any, element: V) => number) | undefined);
17
30
  static [$encoder]: import("../../encoder/EncodeOperation.js").EncodeOperation<any>;
18
31
  static [$decoder]: import("../../decoder/DecodeOperation.js").DecodeOperation<any>;
32
+ /** Integer tag read by `decodeKeyValueOperation` — see `CollectionKind`. */
33
+ static readonly COLLECTION_KIND: 4;
19
34
  /**
20
35
  * Determine if a property must be filtered.
21
36
  * - If returns false, the property is NOT going to be encoded.
@@ -28,6 +43,13 @@ export declare class CollectionSchema<V = any> implements Collection<K, V>, IRef
28
43
  static [$filter](ref: CollectionSchema, index: number, view: StateView): boolean;
29
44
  static is(type: any): boolean;
30
45
  constructor(initialValues?: Array<V>);
46
+ /**
47
+ * Decoder-side factory. Skips the tracking `ChangeTree` allocation;
48
+ * `Object.create` also bypasses the class-field initializers, so we
49
+ * replicate the minimum slot init here. Must stay in sync with the
50
+ * class-field declarations above.
51
+ */
52
+ static initializeForDecoder<V = any>(): CollectionSchema<V>;
31
53
  add(value: V): number;
32
54
  at(index: number): V | undefined;
33
55
  entries(): MapIterator<[number, V]>;
@@ -37,13 +59,19 @@ export declare class CollectionSchema<V = any> implements Collection<K, V>, IRef
37
59
  forEach(callbackfn: (value: V, key: K, collection: CollectionSchema<V>) => void): void;
38
60
  values(): MapIterator<V>;
39
61
  get size(): number;
62
+ pauseTracking(): void;
63
+ resumeTracking(): void;
64
+ untracked<T>(fn: () => T): T;
65
+ get isTrackingPaused(): boolean;
40
66
  /** Iterator */
41
67
  [Symbol.iterator](): IterableIterator<V>;
42
- protected setIndex(index: number, key: number): void;
68
+ protected setIndex(_index: number, _key: number): void;
43
69
  protected getIndex(index: number): number;
44
70
  [$getByIndex](index: number): any;
45
71
  [$deleteByIndex](index: number): void;
46
72
  protected [$onEncodeEnd](): void;
73
+ _dropView(viewId: number): void;
74
+ _unregister(): void;
47
75
  toArray(): V[];
48
76
  toJSON(): V[];
49
77
  clone(isDecoding?: boolean): CollectionSchema<V>;
@@ -1,6 +1,8 @@
1
1
  import { $changes, $childType, $decoder, $deleteByIndex, $onEncodeEnd, $encoder, $filter, $getByIndex, $refId } from "../symbols.js";
2
2
  import { ChangeTree, IRef } from "../../encoder/ChangeTree.js";
3
3
  import { Collection } from "../HelperTypes.js";
4
+ import { MapJournal } from "../../encoder/MapJournal.js";
5
+ import { type StreamableState } from "../../encoder/streaming.js";
4
6
  import type { StateView } from "../../encoder/StateView.js";
5
7
  import type { Schema } from "../../Schema.js";
6
8
  export declare class MapSchema<V = any, K extends string = string> implements Map<K, V>, Collection<K, V, [K, V]>, IRef {
@@ -9,12 +11,46 @@ export declare class MapSchema<V = any, K extends string = string> implements Ma
9
11
  protected childType: new () => V;
10
12
  protected [$childType]: string | typeof Schema;
11
13
  protected $items: Map<K, V>;
12
- protected $indexes: Map<number, K>;
13
- protected deletedItems: {
14
- [index: string]: V;
14
+ /**
15
+ * Wire-protocol identity + change-tracking metadata for this map.
16
+ *
17
+ * Owns: index↔key mapping, monotonic index counter, snapshots of removed
18
+ * values for filter visibility checks. Replaces what used to live as three
19
+ * separate fields on this class ($indexes, _collectionIndexes, deletedItems).
20
+ */
21
+ protected journal: MapJournal<K>;
22
+ /**
23
+ * Streamable state — lazily allocated by `inheritedFlags` (or the
24
+ * `maxPerTick` setter) when streaming actually activates. `undefined`
25
+ * on every non-streaming MapSchema so the common case pays zero
26
+ * Map/Set allocation. Single slot → hidden-class shape stays stable
27
+ * across streaming and non-streaming instances.
28
+ */
29
+ _stream?: StreamableState;
30
+ /** Max ADD ops emitted per tick per view. Ignored outside streaming mode. */
31
+ get maxPerTick(): number;
32
+ set maxPerTick(n: number);
33
+ /**
34
+ * Per-view priority callback for `.stream()` maps. Initialized from the
35
+ * schema declaration (`t.map(X).stream().priority(fn)` or `@type({ map,
36
+ * priority })`); assigning here overrides for this instance. Only fires
37
+ * during `encodeView` — broadcast mode drains FIFO.
38
+ */
39
+ get priority(): ((view: any, element: V) => number) | undefined;
40
+ set priority(fn: ((view: any, element: V) => number) | undefined);
41
+ /** Backwards-compat alias for `journal.keyByIndex`. */
42
+ get $indexes(): Map<number, K>;
43
+ /**
44
+ * Backwards-compat alias for `journal.indexByKey`. Plain object so
45
+ * polymorphic call sites like `ref._collectionIndexes?.[key]` keep working.
46
+ */
47
+ get _collectionIndexes(): {
48
+ [key: string]: number;
15
49
  };
16
50
  static [$encoder]: import("../../encoder/EncodeOperation.js").EncodeOperation<any>;
17
51
  static [$decoder]: import("../../decoder/DecodeOperation.js").DecodeOperation<any>;
52
+ /** Integer tag read by `decodeKeyValueOperation` — see `CollectionKind`. */
53
+ static readonly COLLECTION_KIND: 1;
18
54
  /**
19
55
  * Determine if a property must be filtered.
20
56
  * - If returns false, the property is NOT going to be encoded.
@@ -27,6 +63,13 @@ export declare class MapSchema<V = any, K extends string = string> implements Ma
27
63
  static [$filter](ref: MapSchema, index: number, view: StateView): boolean;
28
64
  static is(type: any): boolean;
29
65
  constructor(initialValues?: Map<K, V> | Record<K, V>);
66
+ /**
67
+ * Decoder-side factory. Skips the tracking `ChangeTree` allocation;
68
+ * `Object.create` also bypasses the class-field initializers, so we
69
+ * replicate the minimum slot init here. Must stay in sync with the
70
+ * class-field declarations above and with the constructor body.
71
+ */
72
+ static initializeForDecoder<V = any, K extends string = string>(): MapSchema<V, K>;
30
73
  /** Iterator */
31
74
  [Symbol.iterator](): IterableIterator<[K, V]>;
32
75
  get [Symbol.toStringTag](): string;
@@ -41,11 +84,17 @@ export declare class MapSchema<V = any, K extends string = string> implements Ma
41
84
  keys(): MapIterator<K>;
42
85
  values(): MapIterator<V>;
43
86
  get size(): number;
87
+ pauseTracking(): void;
88
+ resumeTracking(): void;
89
+ untracked<T>(fn: () => T): T;
90
+ get isTrackingPaused(): boolean;
44
91
  protected setIndex(index: number, key: K): void;
45
92
  protected getIndex(index: number): K;
46
93
  [$getByIndex](index: number): V | undefined;
47
94
  [$deleteByIndex](index: number): void;
48
95
  protected [$onEncodeEnd](): void;
96
+ _dropView(viewId: number): void;
97
+ _unregister(): void;
49
98
  toJSON(): any;
50
99
  clone(isDecoding?: boolean): MapSchema<V>;
51
100
  }
@@ -1,20 +1,37 @@
1
1
  import { $changes, $childType, $decoder, $deleteByIndex, $encoder, $filter, $getByIndex, $onEncodeEnd, $refId } from "../symbols.js";
2
2
  import { Collection } from "../HelperTypes.js";
3
3
  import { ChangeTree, type IRef } from "../../encoder/ChangeTree.js";
4
+ import { type StreamableState } from "../../encoder/streaming.js";
4
5
  import type { StateView } from "../../encoder/StateView.js";
5
6
  import type { Schema } from "../../Schema.js";
6
7
  export declare class SetSchema<V = any> implements Collection<number, V>, IRef {
7
8
  [$changes]: ChangeTree;
8
9
  [$refId]?: number;
9
10
  protected [$childType]: string | typeof Schema;
11
+ /** The user-visible data, keyed directly by the wire-protocol index. */
10
12
  protected $items: Map<number, V>;
11
- protected $indexes: Map<number, number>;
13
+ /** Snapshots of values that were deleted this tick (for filter visibility). */
12
14
  protected deletedItems: {
13
15
  [field: string]: V;
14
16
  };
17
+ /** Monotonic counter for assigning indexes to newly-added items. */
15
18
  protected $refId: number;
19
+ /**
20
+ * Streamable state — lazily allocated when the field is opted into
21
+ * streaming via `t.set(X).stream()`. See MapSchema for the same
22
+ * pattern / rationale.
23
+ */
24
+ _stream?: StreamableState;
25
+ /** Max ADD ops emitted per tick per view. Ignored outside streaming mode. */
26
+ get maxPerTick(): number;
27
+ set maxPerTick(n: number);
28
+ /** Per-view priority callback — see StreamSchema / MapSchema. */
29
+ get priority(): ((view: any, element: V) => number) | undefined;
30
+ set priority(fn: ((view: any, element: V) => number) | undefined);
16
31
  static [$encoder]: import("../../encoder/EncodeOperation.js").EncodeOperation<any>;
17
32
  static [$decoder]: import("../../decoder/DecodeOperation.js").DecodeOperation<any>;
33
+ /** Integer tag read by `decodeKeyValueOperation` — see `CollectionKind`. */
34
+ static readonly COLLECTION_KIND: 3;
18
35
  /**
19
36
  * Determine if a property must be filtered.
20
37
  * - If returns false, the property is NOT going to be encoded.
@@ -27,6 +44,13 @@ export declare class SetSchema<V = any> implements Collection<number, V>, IRef {
27
44
  static [$filter](ref: SetSchema, index: number, view: StateView): boolean;
28
45
  static is(type: any): boolean;
29
46
  constructor(initialValues?: Array<V>);
47
+ /**
48
+ * Decoder-side factory. Skips the tracking `ChangeTree` allocation;
49
+ * `Object.create` also bypasses the class-field initializers, so we
50
+ * replicate the minimum slot init here. Must stay in sync with the
51
+ * class-field declarations above.
52
+ */
53
+ static initializeForDecoder<V = any>(): SetSchema<V>;
30
54
  add(value: V): number | false;
31
55
  entries(): MapIterator<[number, V]>;
32
56
  delete(item: V): boolean;
@@ -35,13 +59,19 @@ export declare class SetSchema<V = any> implements Collection<number, V>, IRef {
35
59
  forEach(callbackfn: (value: V, key: number, collection: SetSchema<V>) => void): void;
36
60
  values(): MapIterator<V>;
37
61
  get size(): number;
62
+ pauseTracking(): void;
63
+ resumeTracking(): void;
64
+ untracked<T>(fn: () => T): T;
65
+ get isTrackingPaused(): boolean;
38
66
  /** Iterator */
39
67
  [Symbol.iterator](): IterableIterator<V>;
40
- protected setIndex(index: number, key: number): void;
68
+ protected setIndex(_index: number, _key: number): void;
41
69
  protected getIndex(index: number): number;
42
70
  [$getByIndex](index: number): any;
43
71
  [$deleteByIndex](index: number): void;
44
72
  protected [$onEncodeEnd](): void;
73
+ _dropView(viewId: number): void;
74
+ _unregister(): void;
45
75
  toArray(): V[];
46
76
  toJSON(): V[];
47
77
  clone(isDecoding?: boolean): SetSchema<V>;