@colyseus/schema 5.0.24 → 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 +9 -9
- package/package.json +1 -1
- package/src/encoder/StateView.ts +12 -1
- package/src/types/HelperTypes.ts +20 -22
|
@@ -136,9 +136,11 @@ export type IsNever<T> = [T] extends [never] ? true : false;
|
|
|
136
136
|
* - Primitives can be assigned directly
|
|
137
137
|
* - Schema instances can be assigned from plain objects or Schema instances
|
|
138
138
|
* - Collections can be assigned from their JSON representations
|
|
139
|
+
*
|
|
140
|
+
* Keys filter through `DataKey` in the `as` clause — see THE RULE above.
|
|
139
141
|
*/
|
|
140
142
|
export type AssignableProps<T> = {
|
|
141
|
-
[K in
|
|
143
|
+
-readonly [K in keyof T as DataKey<T, K>]?: AssignableValue<T[K]>;
|
|
142
144
|
};
|
|
143
145
|
/**
|
|
144
146
|
* Value-level assignment shape shared by `AssignableProps` and
|
|
@@ -153,20 +155,18 @@ export type RefHasDefault<C> = C extends {
|
|
|
153
155
|
} ? (P extends readonly [] ? true : false) : true;
|
|
154
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;
|
|
155
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";
|
|
156
|
-
export type BuilderRequiredKeys<T> = {
|
|
157
|
-
[K in keyof T]-?: KeyClass<T, K> extends "required" ? K : never;
|
|
158
|
-
}[keyof T];
|
|
159
|
-
export type BuilderOptionalKeys<T> = {
|
|
160
|
-
[K in keyof T]-?: KeyClass<T, K> extends "optional" ? K : never;
|
|
161
|
-
}[keyof T];
|
|
162
158
|
/**
|
|
163
159
|
* Constructor/init-props type for a schema() fields map. Required fields
|
|
164
160
|
* (primitives without `.default()` or `.optional()`, and Schema refs with
|
|
165
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 `?`.
|
|
166
166
|
*/
|
|
167
167
|
export type BuilderInitProps<T> = {
|
|
168
|
-
[K in
|
|
168
|
+
-readonly [K in keyof T as KeyClass<T, K> extends "required" ? K : never]-?: AssignableValue<FieldValue<T[K]>>;
|
|
169
169
|
} & {
|
|
170
|
-
[K in
|
|
170
|
+
-readonly [K in keyof T as KeyClass<T, K> extends "optional" ? K : never]?: AssignableValue<Exclude<FieldValue<T[K]>, undefined>>;
|
|
171
171
|
};
|
|
172
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,11 +117,12 @@ 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
127
|
-readonly [K in keyof T as IsOptionalBuilderKey<T, K> extends true ? never : K]-?: T[K] extends FieldBuilder<any>
|
|
127
128
|
? InferValueType<T[K]>
|
|
@@ -170,12 +171,11 @@ 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
|
-
// branch only, once per key rather than once per half.
|
|
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
180
|
& { -readonly [K in keyof T as IsOptionalKey<T, K> extends true ? never : DataKey<T, K>]-?: ToJSONField<T[K]> }
|
|
181
181
|
& { -readonly [K in keyof T as IsOptionalKey<T, K> extends true ? DataKey<T, K> : never]?: ToJSONField<Exclude<T[K], undefined>> };
|
|
@@ -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>> };
|