@colyseus/schema 3.0.52 → 3.0.54

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.
@@ -2,7 +2,7 @@ import "./symbol.shim";
2
2
  import { Schema } from './Schema';
3
3
  import { ArraySchema } from './types/custom/ArraySchema';
4
4
  import { MapSchema } from './types/custom/MapSchema';
5
- import { Metadata } from "./Metadata";
5
+ import { getNormalizedType, Metadata } from "./Metadata";
6
6
  import { $changes, $childType, $descriptors, $numFields, $track } from "./types/symbols";
7
7
  import { TypeDefinition, getType } from "./types/registry";
8
8
  import { OPERATION } from "./encoding/spec";
@@ -10,8 +10,8 @@ import { TypeContext } from "./types/TypeContext";
10
10
  import { assertInstanceType, assertType } from "./encoding/assert";
11
11
  import type { Ref } from "./encoder/ChangeTree";
12
12
  import type { DefinedSchemaType, InferValueType } from "./types/HelperTypes";
13
- import type { CollectionSchema } from "./types/custom/CollectionSchema";
14
- import type { SetSchema } from "./types/custom/SetSchema";
13
+ import { CollectionSchema } from "./types/custom/CollectionSchema";
14
+ import { SetSchema } from "./types/custom/SetSchema";
15
15
 
16
16
  export type RawPrimitiveType = "string" |
17
17
  "number" |
@@ -285,6 +285,9 @@ export function type (
285
285
  throw new Error(`${constructor.name}: @type() reference provided for "${field}" is undefined. Make sure you don't have any circular dependencies.`);
286
286
  }
287
287
 
288
+ // Normalize type (enum/collection/etc)
289
+ type = getNormalizedType(type);
290
+
288
291
  // for inheritance support
289
292
  TypeContext.register(constructor);
290
293
 
@@ -339,9 +342,7 @@ export function type (
339
342
  );
340
343
 
341
344
  } else {
342
- const complexTypeKlass = (Array.isArray(type))
343
- ? getType("array")
344
- : (typeof(Object.keys(type)[0]) === "string") && getType(Object.keys(type)[0]);
345
+ const complexTypeKlass = typeof(Object.keys(type)[0]) === "string" && getType(Object.keys(type)[0]);
345
346
 
346
347
  const childType = (complexTypeKlass)
347
348
  ? Object.values(type)[0]
@@ -512,27 +513,74 @@ export function schema<T extends Definition, P extends typeof Schema = typeof Sc
512
513
  for (let fieldName in fieldsAndMethods) {
513
514
  const value = fieldsAndMethods[fieldName] as DefinitionType;
514
515
  if (typeof (value) === "object") {
515
- if (value['default'] !== undefined) {
516
- defaultValues[fieldName] = value['default'];
517
- }
518
516
  if (value['view'] !== undefined) {
519
517
  viewTagFields[fieldName] = (typeof (value['view']) === "boolean")
520
518
  ? DEFAULT_VIEW_TAG
521
519
  : value['view'];
522
520
  }
523
- fields[fieldName] = value;
521
+
522
+ fields[fieldName] = getNormalizedType(value);
523
+
524
+ // If no explicit default provided, handle automatic instantiation for collection types
525
+ if (!Object.prototype.hasOwnProperty.call(value, 'default')) {
526
+ // TODO: remove Array.isArray() check. Use ['array'] !== undefined only.
527
+ if (Array.isArray(value) || value['array'] !== undefined) {
528
+ // Collection: Array → new ArraySchema()
529
+ defaultValues[fieldName] = new ArraySchema();
530
+
531
+ } else if (value['map'] !== undefined) {
532
+ // Collection: Map → new MapSchema()
533
+ defaultValues[fieldName] = new MapSchema();
534
+
535
+ } else if (value['collection'] !== undefined) {
536
+ // Collection: Collection → new CollectionSchema()
537
+ defaultValues[fieldName] = new CollectionSchema();
538
+
539
+ } else if (value['set'] !== undefined) {
540
+ // Collection: Set → new SetSchema()
541
+ defaultValues[fieldName] = new SetSchema();
542
+
543
+ } else if (value['type'] !== undefined && Schema.is(value['type'])) {
544
+ // Direct Schema type: Type → new Type()
545
+ defaultValues[fieldName] = new value['type']();
546
+ }
547
+ } else {
548
+ defaultValues[fieldName] = value['default'];
549
+ }
550
+
524
551
 
525
552
  } else if (typeof (value) === "function") {
526
- methods[fieldName] = value;
553
+ if (Schema.is(value)) {
554
+ // Direct Schema type: Type → new Type()
555
+ defaultValues[fieldName] = new value();
556
+ fields[fieldName] = getNormalizedType(value);
557
+ } else {
558
+ methods[fieldName] = value;
559
+ }
527
560
 
528
561
  } else {
529
- fields[fieldName] = value;
562
+ fields[fieldName] = getNormalizedType(value);
530
563
  }
531
564
  }
532
565
 
566
+ const getDefaultValues = () => {
567
+ const defaults: any = {};
568
+ for (const fieldName in defaultValues) {
569
+ const defaultValue = defaultValues[fieldName];
570
+ // If the default value has a clone method, use it to get a fresh instance
571
+ if (defaultValue && typeof defaultValue.clone === 'function') {
572
+ defaults[fieldName] = defaultValue.clone();
573
+ } else {
574
+ // Otherwise, use the value as-is (for primitives and non-cloneable objects)
575
+ defaults[fieldName] = defaultValue;
576
+ }
577
+ }
578
+ return defaults;
579
+ };
580
+
533
581
  const klass = Metadata.setFields<any>(class extends inherits {
534
582
  constructor (...args: any[]) {
535
- args[0] = Object.assign({}, defaultValues, args[0]);
583
+ args[0] = Object.assign({}, getDefaultValues(), args[0]);
536
584
  super(...args);
537
585
  }
538
586
  }, fields) as SchemaWithExtends<T, P>;
@@ -28,25 +28,34 @@ export type InferValueType<T extends DefinitionType> =
28
28
  : T extends "float64" ? number
29
29
  : T extends "boolean" ? boolean
30
30
 
31
+ // Handle { type: ... } patterns
31
32
  : T extends { type: infer ChildType extends Constructor } ? InstanceType<ChildType>
32
- : T extends { type: infer ChildType extends PrimitiveType } ? ChildType
33
+ : T extends { type: Array<infer ChildType> } ? (ChildType extends Record<string | number, string | number> ? ChildType[keyof ChildType][] : ChildType[]) // TS ENUM
34
+ : T extends { type: { map: infer ChildType } } ? (ChildType extends Record<string | number, string | number> ? MapSchema<ChildType[keyof ChildType]> : MapSchema<ChildType>) // TS ENUM
35
+ : T extends { type: { set: infer ChildType } } ? (ChildType extends Record<string | number, string | number> ? SetSchema<ChildType[keyof ChildType]> : SetSchema<ChildType>) // TS ENUM
36
+ : T extends { type: { collection: infer ChildType } } ? (ChildType extends Record<string | number, string | number> ? CollectionSchema<ChildType[keyof ChildType]> : CollectionSchema<ChildType>) // TS ENUM
37
+ : T extends { type: infer ChildType } ? (ChildType extends Record<string | number, string | number> ? ChildType[keyof ChildType] : ChildType) // TS ENUM
33
38
 
39
+ // Handle direct array patterns
34
40
  : T extends Array<infer ChildType extends Constructor> ? InstanceType<ChildType>[]
35
- : T extends Array<infer ChildType extends RawPrimitiveType> ? ChildType[]
41
+ : T extends Array<infer ChildType> ? (ChildType extends Record<string | number, string | number> ? ChildType[keyof ChildType][] : ChildType[]) // TS ENUM
36
42
 
43
+ // Handle collection object patterns
37
44
  : T extends { array: infer ChildType extends Constructor } ? InstanceType<ChildType>[]
38
- : T extends { array: infer ChildType extends PrimitiveType } ? ChildType[]
45
+ : T extends { array: infer ChildType } ? (ChildType extends Record<string | number, string | number> ? ChildType[keyof ChildType][] : ChildType[]) // TS ENUM
39
46
 
40
47
  : T extends { map: infer ChildType extends Constructor } ? MapSchema<InstanceType<ChildType>>
41
- : T extends { map: infer ChildType extends PrimitiveType } ? MapSchema<ChildType>
48
+ : T extends { map: infer ChildType } ? (ChildType extends Record<string | number, string | number> ? MapSchema<ChildType[keyof ChildType]> : MapSchema<ChildType>) // TS ENUM
42
49
 
43
50
  : T extends { set: infer ChildType extends Constructor } ? SetSchema<InstanceType<ChildType>>
44
- : T extends { set: infer ChildType extends PrimitiveType } ? SetSchema<ChildType>
51
+ : T extends { set: infer ChildType } ? (ChildType extends Record<string | number, string | number> ? SetSchema<ChildType[keyof ChildType]> : SetSchema<ChildType>) // TS ENUM
45
52
 
46
53
  : T extends { collection: infer ChildType extends Constructor } ? CollectionSchema<InstanceType<ChildType>>
47
- : T extends { collection: infer ChildType extends PrimitiveType } ? CollectionSchema<ChildType>
54
+ : T extends { collection: infer ChildType } ? (ChildType extends Record<string | number, string | number> ? CollectionSchema<ChildType[keyof ChildType]> : CollectionSchema<ChildType>) // TS ENUM
48
55
 
56
+ // Handle direct types
49
57
  : T extends Constructor ? InstanceType<T>
58
+ : T extends Record<string | number, string | number> ? T[keyof T] // TS ENUM
50
59
  : T extends PrimitiveType ? T
51
60
 
52
61
  : never;
@@ -114,17 +114,7 @@ export class TypeContext {
114
114
  continue;
115
115
  }
116
116
 
117
- if (Array.isArray(fieldType)) {
118
- const type = fieldType[0];
119
-
120
- // skip primitive types
121
- if (type === "string") {
122
- continue;
123
- }
124
-
125
- this.discoverTypes(type as typeof Schema, klass, index, parentHasViewTag || fieldHasViewTag);
126
-
127
- } else if (typeof (fieldType) === "function") {
117
+ if (typeof (fieldType) === "function") {
128
118
  this.discoverTypes(fieldType as typeof Schema, klass, index, parentHasViewTag || fieldHasViewTag);
129
119
 
130
120
  } else {
@@ -362,7 +362,7 @@ export class ArraySchema<V = any> implements Array<V>, Collection<number, V> {
362
362
  changeTree.delete(index, OPERATION.DELETE, allChangesIndex);
363
363
  changeTree.shiftAllChangeIndexes(-1, allChangesIndex);
364
364
 
365
- // this.deletedIndexes[index] = true;
365
+ this.deletedIndexes[index] = true;
366
366
 
367
367
  return this.items.shift();
368
368
  }
@@ -8,7 +8,8 @@ export interface TypeDefinition {
8
8
  decode?: (bytes: BufferLike, it: Iterator) => any;
9
9
  }
10
10
 
11
- const registeredTypes: {[identifier: string] : TypeDefinition} = {};
11
+ export const registeredTypes: {[identifier: string] : TypeDefinition} = {};
12
+
12
13
  const identifiers = new Map<any, string>();
13
14
 
14
15
  export function registerType(identifier: string, definition: TypeDefinition) {