@colyseus/schema 5.0.23 → 5.0.25
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/index.cjs +12 -1
- package/build/index.cjs.map +1 -1
- package/build/index.js +12 -1
- package/build/index.mjs +12 -1
- package/build/index.mjs.map +1 -1
- package/build/types/HelperTypes.d.ts +13 -25
- package/package.json +1 -1
- package/src/encoder/StateView.ts +12 -1
- package/src/types/HelperTypes.ts +24 -26
|
@@ -89,16 +89,10 @@ export type CodecFor<T> = {
|
|
|
89
89
|
[K in RawPrimitiveType]: [T] extends [InferValueType<K>] ? K : never;
|
|
90
90
|
}[RawPrimitiveType];
|
|
91
91
|
type IsOptionalBuilderKey<T, K extends keyof T> = T[K] extends FieldBuilder<unknown, boolean, infer O extends boolean> ? O : false;
|
|
92
|
-
type OptionalBuilderKeys<T> = {
|
|
93
|
-
[K in keyof T]-?: IsOptionalBuilderKey<T, K> extends true ? K : never;
|
|
94
|
-
}[keyof T];
|
|
95
|
-
type RequiredBuilderKeys<T> = {
|
|
96
|
-
[K in keyof T]-?: IsOptionalBuilderKey<T, K> extends true ? never : K;
|
|
97
|
-
}[keyof T];
|
|
98
92
|
export type InferSchemaInstanceType<T> = {
|
|
99
|
-
[K in
|
|
93
|
+
-readonly [K in keyof T as IsOptionalBuilderKey<T, K> extends true ? never : K]-?: 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]>;
|
|
100
94
|
} & {
|
|
101
|
-
[K in
|
|
95
|
+
-readonly [K in keyof T as IsOptionalBuilderKey<T, K> extends true ? K : never]?: T[K] extends FieldBuilder<infer V> ? V : never;
|
|
102
96
|
} & Schema;
|
|
103
97
|
type DataKey<T, K extends keyof T> = K extends keyof Schema ? never : T[K] extends Function ? never : K;
|
|
104
98
|
export type NonFunctionPropNames<T> = {
|
|
@@ -110,16 +104,10 @@ export type NonFunctionNonPrimitivePropNames<T> = {
|
|
|
110
104
|
type ToJSONValue<U> = U extends Schema ? ToJSON<U> : PrimitiveStringToType<U>;
|
|
111
105
|
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;
|
|
112
106
|
type IsOptionalKey<T, K extends keyof T> = undefined extends {} ? ({} extends Pick<T, K> ? true : false) : (undefined extends T[K] ? true : false);
|
|
113
|
-
type ToJSONRequiredKeys<T> = {
|
|
114
|
-
[K in keyof T]-?: [DataKey<T, K>] extends [never] ? never : IsOptionalKey<T, K> extends true ? never : K;
|
|
115
|
-
}[keyof T];
|
|
116
|
-
type ToJSONOptionalKeys<T> = {
|
|
117
|
-
[K in keyof T]-?: [DataKey<T, K>] extends [never] ? never : IsOptionalKey<T, K> extends true ? K : never;
|
|
118
|
-
}[keyof T];
|
|
119
107
|
export type ToJSON<T> = {
|
|
120
|
-
[K in
|
|
108
|
+
-readonly [K in keyof T as IsOptionalKey<T, K> extends true ? never : DataKey<T, K>]-?: ToJSONField<T[K]>;
|
|
121
109
|
} & {
|
|
122
|
-
[K in
|
|
110
|
+
-readonly [K in keyof T as IsOptionalKey<T, K> extends true ? DataKey<T, K> : never]?: ToJSONField<Exclude<T[K], undefined>>;
|
|
123
111
|
};
|
|
124
112
|
/**
|
|
125
113
|
* The plain DATA shape of a Schema instance type `T`: its synchronized fields
|
|
@@ -148,9 +136,11 @@ export type IsNever<T> = [T] extends [never] ? true : false;
|
|
|
148
136
|
* - Primitives can be assigned directly
|
|
149
137
|
* - Schema instances can be assigned from plain objects or Schema instances
|
|
150
138
|
* - Collections can be assigned from their JSON representations
|
|
139
|
+
*
|
|
140
|
+
* Keys filter through `DataKey` in the `as` clause — see THE RULE above.
|
|
151
141
|
*/
|
|
152
142
|
export type AssignableProps<T> = {
|
|
153
|
-
[K in
|
|
143
|
+
-readonly [K in keyof T as DataKey<T, K>]?: AssignableValue<T[K]>;
|
|
154
144
|
};
|
|
155
145
|
/**
|
|
156
146
|
* Value-level assignment shape shared by `AssignableProps` and
|
|
@@ -165,20 +155,18 @@ export type RefHasDefault<C> = C extends {
|
|
|
165
155
|
} ? (P extends readonly [] ? true : false) : true;
|
|
166
156
|
type FieldValue<F> = F extends FieldBuilder<infer V, boolean, boolean> ? V : F extends new (...args: any[]) => infer I ? (I extends Schema ? I : never) : never;
|
|
167
157
|
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";
|
|
168
|
-
export type BuilderRequiredKeys<T> = {
|
|
169
|
-
[K in keyof T]-?: KeyClass<T, K> extends "required" ? K : never;
|
|
170
|
-
}[keyof T];
|
|
171
|
-
export type BuilderOptionalKeys<T> = {
|
|
172
|
-
[K in keyof T]-?: KeyClass<T, K> extends "optional" ? K : never;
|
|
173
|
-
}[keyof T];
|
|
174
158
|
/**
|
|
175
159
|
* Constructor/init-props type for a schema() fields map. Required fields
|
|
176
160
|
* (primitives without `.default()` or `.optional()`, and Schema refs with
|
|
177
161
|
* non-zero-arg `initialize()`) are `:`; everything else is `?:`.
|
|
162
|
+
*
|
|
163
|
+
* Split by `KeyClass` in the `as` clause — see THE RULE above. `-?` matters
|
|
164
|
+
* under `strictNullChecks: false`: an optional key in the fields map still
|
|
165
|
+
* classifies as "required" there, and would otherwise inherit the `?`.
|
|
178
166
|
*/
|
|
179
167
|
export type BuilderInitProps<T> = {
|
|
180
|
-
[K in
|
|
168
|
+
-readonly [K in keyof T as KeyClass<T, K> extends "required" ? K : never]-?: AssignableValue<FieldValue<T[K]>>;
|
|
181
169
|
} & {
|
|
182
|
-
[K in
|
|
170
|
+
-readonly [K in keyof T as KeyClass<T, K> extends "optional" ? K : never]?: AssignableValue<Exclude<FieldValue<T[K]>, undefined>>;
|
|
183
171
|
};
|
|
184
172
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@colyseus/schema",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.25",
|
|
4
4
|
"description": "Automatic state replication for multiplayer games. Mutate plain objects, and every client gets a live, typed mirror through delta encoding.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/src/encoder/StateView.ts
CHANGED
|
@@ -619,7 +619,18 @@ export class StateView {
|
|
|
619
619
|
this.changes.set(changeTree.ref[$refId], changes);
|
|
620
620
|
}
|
|
621
621
|
|
|
622
|
-
|
|
622
|
+
// Grant the tag on the parent only when the field pointing at
|
|
623
|
+
// the child carries an overlapping tag — that field is the sole
|
|
624
|
+
// reason the parent needs it. Granting unconditionally handed
|
|
625
|
+
// the view every OTHER same-tag field on the parent, which then
|
|
626
|
+
// rode out on its next mutation (never at add() time, so it read
|
|
627
|
+
// as "the field only shows up after it changes").
|
|
628
|
+
const parentFieldTag = changeTree.encDescriptor.tags[parentIndex];
|
|
629
|
+
if (parentFieldTag !== undefined &&
|
|
630
|
+
parentFieldTag !== DEFAULT_VIEW_TAG &&
|
|
631
|
+
(parentFieldTag & tag) !== 0) {
|
|
632
|
+
this.addTag(changeTree, tag);
|
|
633
|
+
}
|
|
623
634
|
|
|
624
635
|
// ArraySchema parents: key by the child's identity, not the wire
|
|
625
636
|
// slot it holds right now — a same-tick unshift()/reverse()/move()
|
package/src/types/HelperTypes.ts
CHANGED
|
@@ -117,19 +117,20 @@ export type CodecFor<T> = {
|
|
|
117
117
|
type IsOptionalBuilderKey<T, K extends keyof T> =
|
|
118
118
|
T[K] extends FieldBuilder<unknown, boolean, infer O extends boolean> ? O : false;
|
|
119
119
|
|
|
120
|
-
//
|
|
121
|
-
//
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
120
|
+
// THE RULE for every mapped type below that projects a user's declared fields:
|
|
121
|
+
// split in the `as` clause, never over a precomputed key union. Only a
|
|
122
|
+
// homomorphic mapping carries each key back to its declaration, and that link
|
|
123
|
+
// is what go-to-definition and rename resolve through — losing it leaves rename
|
|
124
|
+
// silently touching just the cursor (colyseus/colyseus#958). The `-readonly`
|
|
125
|
+
// and `-?` that follow drop the modifiers such a mapping inherits from `T`.
|
|
125
126
|
export type InferSchemaInstanceType<T> = {
|
|
126
|
-
[K in
|
|
127
|
+
-readonly [K in keyof T as IsOptionalBuilderKey<T, K> extends true ? never : K]-?: T[K] extends FieldBuilder<any>
|
|
127
128
|
? InferValueType<T[K]>
|
|
128
129
|
: T[K] extends (...args: any[]) => any
|
|
129
130
|
? (T[K] extends new (...args: any[]) => any ? InferValueType<T[K]> : T[K])
|
|
130
131
|
: InferValueType<T[K]>
|
|
131
132
|
} & {
|
|
132
|
-
[K in
|
|
133
|
+
-readonly [K in keyof T as IsOptionalBuilderKey<T, K> extends true ? K : never]?: T[K] extends FieldBuilder<infer V>
|
|
133
134
|
? V
|
|
134
135
|
: never
|
|
135
136
|
} & Schema;
|
|
@@ -170,15 +171,14 @@ type IsOptionalKey<T, K extends keyof T> = undefined extends {}
|
|
|
170
171
|
? ({} extends Pick<T, K> ? true : false)
|
|
171
172
|
: (undefined extends T[K] ? true : false);
|
|
172
173
|
|
|
173
|
-
// `
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
//
|
|
178
|
-
// exceeds TypeScript 7's instantiation depth.
|
|
174
|
+
// Beyond THE RULE, the `as` clause is load-bearing here for a second reason: it
|
|
175
|
+
// runs before the value type, so `ToJSONField` never reaches the machinery,
|
|
176
|
+
// where it would recurse through `restore(json: ToJSON<this>)` past TypeScript
|
|
177
|
+
// 7's instantiation limit. Probing `IsOptionalKey` first is deliberate too —
|
|
178
|
+
// `DataKey` then runs in the taken branch only, once per key not once per half.
|
|
179
179
|
export type ToJSON<T> =
|
|
180
|
-
& { [K in
|
|
181
|
-
& { [K in
|
|
180
|
+
& { -readonly [K in keyof T as IsOptionalKey<T, K> extends true ? never : DataKey<T, K>]-?: ToJSONField<T[K]> }
|
|
181
|
+
& { -readonly [K in keyof T as IsOptionalKey<T, K> extends true ? DataKey<T, K> : never]?: ToJSONField<Exclude<T[K], undefined>> };
|
|
182
182
|
|
|
183
183
|
/**
|
|
184
184
|
* The plain DATA shape of a Schema instance type `T`: its synchronized fields
|
|
@@ -210,9 +210,11 @@ export type IsNever<T> = [T] extends [never] ? true : false;
|
|
|
210
210
|
* - Primitives can be assigned directly
|
|
211
211
|
* - Schema instances can be assigned from plain objects or Schema instances
|
|
212
212
|
* - Collections can be assigned from their JSON representations
|
|
213
|
+
*
|
|
214
|
+
* Keys filter through `DataKey` in the `as` clause — see THE RULE above.
|
|
213
215
|
*/
|
|
214
216
|
export type AssignableProps<T> = {
|
|
215
|
-
[K in
|
|
217
|
+
-readonly [K in keyof T as DataKey<T, K>]?: AssignableValue<T[K]>
|
|
216
218
|
};
|
|
217
219
|
|
|
218
220
|
/**
|
|
@@ -267,19 +269,15 @@ type KeyClass<T, K extends keyof T> =
|
|
|
267
269
|
? (RefHasDefault<T[K]> extends true ? "optional" : "required")
|
|
268
270
|
: "none";
|
|
269
271
|
|
|
270
|
-
export type BuilderRequiredKeys<T> = {
|
|
271
|
-
[K in keyof T]-?: KeyClass<T, K> extends "required" ? K : never
|
|
272
|
-
}[keyof T];
|
|
273
|
-
|
|
274
|
-
export type BuilderOptionalKeys<T> = {
|
|
275
|
-
[K in keyof T]-?: KeyClass<T, K> extends "optional" ? K : never
|
|
276
|
-
}[keyof T];
|
|
277
|
-
|
|
278
272
|
/**
|
|
279
273
|
* Constructor/init-props type for a schema() fields map. Required fields
|
|
280
274
|
* (primitives without `.default()` or `.optional()`, and Schema refs with
|
|
281
275
|
* non-zero-arg `initialize()`) are `:`; everything else is `?:`.
|
|
276
|
+
*
|
|
277
|
+
* Split by `KeyClass` in the `as` clause — see THE RULE above. `-?` matters
|
|
278
|
+
* under `strictNullChecks: false`: an optional key in the fields map still
|
|
279
|
+
* classifies as "required" there, and would otherwise inherit the `?`.
|
|
282
280
|
*/
|
|
283
281
|
export type BuilderInitProps<T> =
|
|
284
|
-
& { [K in
|
|
285
|
-
& { [K in
|
|
282
|
+
& { -readonly [K in keyof T as KeyClass<T, K> extends "required" ? K : never]-?: AssignableValue<FieldValue<T[K]>> }
|
|
283
|
+
& { -readonly [K in keyof T as KeyClass<T, K> extends "optional" ? K : never]?: AssignableValue<Exclude<FieldValue<T[K]>, undefined>> };
|