@colyseus/schema 5.0.20 → 5.0.22

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.
@@ -76,7 +76,7 @@ export declare const ReflectionField: import("./annotations.js").SchemaWithExten
76
76
  max: number;
77
77
  bits: number;
78
78
  mode: number;
79
- } & {} & Schema<any> & Schema<unknown>, false, true>;
79
+ } & {} & Schema<any> & Schema<unknown>, true, true>;
80
80
  }, import("./index.js").BuilderInitProps<{
81
81
  name: FieldBuilder<string, false, false>;
82
82
  type: FieldBuilder<string, false, false>;
@@ -91,7 +91,7 @@ export declare const ReflectionField: import("./annotations.js").SchemaWithExten
91
91
  max: number;
92
92
  bits: number;
93
93
  mode: number;
94
- } & {} & Schema<any> & Schema<unknown>, false, true>;
94
+ } & {} & Schema<any> & Schema<unknown>, true, true>;
95
95
  }>, typeof Schema>;
96
96
  export type ReflectionField = SchemaType<typeof ReflectionField>;
97
97
  export declare const ReflectionType: import("./annotations.js").SchemaWithExtendsConstructor<{
@@ -161,13 +161,14 @@ export interface SchemaWithExtendsConstructor<T, InitProps, P extends typeof Sch
161
161
  new (...args: [
162
162
  InitProps
163
163
  ] extends [never] ? [] : InitProps extends readonly any[] ? InitProps : HasExplicitInit<T> extends true ? [InitProps] : IsInitPropsRequired<T> extends true ? ([] | [InitProps]) : [InitProps?]): SchemaInstance<T, P>;
164
- prototype: SchemaInstance<T, P> & {
165
- initialize(...args: [InitProps] extends [never] ? [] : InitProps extends readonly any[] ? InitProps : [InitProps]): void;
166
- };
164
+ prototype: SchemaInstance<T, P>;
167
165
  }
168
166
  /**
169
167
  * Define a Schema class declaratively.
170
168
  *
169
+ * `initialize()` acts as the constructor: a class created with `.extend()`
170
+ * inherits the parent's unless it defines its own.
171
+ *
171
172
  * @example
172
173
  * import { schema, t } from '@colyseus/schema';
173
174
  *
package/build/index.cjs CHANGED
@@ -1411,6 +1411,10 @@ const Metadata = {
1411
1411
  });
1412
1412
  }
1413
1413
  for (const field in fields) {
1414
+ // metadata inherits the parent's, so this also catches a redeclared parent field
1415
+ if (metadata[field] !== undefined) {
1416
+ throw new Error(`@colyseus/schema: Duplicate '${field}' definition on '${constructor.name || "(anonymous)"}'.`);
1417
+ }
1414
1418
  Metadata.defineField(constructor, metadata, fieldIndex, field, fields[field]);
1415
1419
  fieldIndex++;
1416
1420
  }
@@ -7275,6 +7279,9 @@ function makeAutoDefaultFactory(rawType) {
7275
7279
  /**
7276
7280
  * Define a Schema class declaratively.
7277
7281
  *
7282
+ * `initialize()` acts as the constructor: a class created with `.extend()`
7283
+ * inherits the parent's unless it defines its own.
7284
+ *
7278
7285
  * @example
7279
7286
  * import { schema, t } from '@colyseus/schema';
7280
7287
  *
@@ -7435,8 +7442,11 @@ function schema(fieldsAndMethods, name, inherits = Schema) {
7435
7442
  return parentProps;
7436
7443
  };
7437
7444
  const hasInitialize = typeof methods.initialize === "function";
7438
- /** @codegen-ignore */
7439
- const klass = Metadata.setFields(class extends inherits {
7445
+ // Like a constructor: the most-derived initialize() runs once, own or
7446
+ // inherited from a schema() parent. A custom base's initialize() is not
7447
+ // picked up — the constructor type only sees the fields map.
7448
+ const initialize = methods.initialize ?? inherits._initialize;
7449
+ const klass = class extends inherits {
7440
7450
  constructor(...args) {
7441
7451
  const props = args[0];
7442
7452
  if (props === undefined) {
@@ -7451,13 +7461,20 @@ function schema(fieldsAndMethods, name, inherits = Schema) {
7451
7461
  // `initialize()` owns the schema fields, so only parent props flow up.
7452
7462
  super(Object.assign(getDefaultValues(), hasInitialize ? getParentProps(props) : props));
7453
7463
  }
7454
- // Only call initialize() on the exact target class, not parents.
7455
- if (hasInitialize && new.target === klass) {
7456
- methods.initialize.apply(this, args);
7464
+ // Only on the exact target class parents' constructors skip it.
7465
+ if (initialize && new.target === klass) {
7466
+ initialize.apply(this, args);
7457
7467
  }
7458
7468
  }
7459
- }, fields);
7469
+ };
7470
+ // named before setFields so a duplicate-field error can say which class
7471
+ if (name) {
7472
+ Object.defineProperty(klass, "name", { value: name });
7473
+ }
7474
+ /** @codegen-ignore */
7475
+ Metadata.setFields(klass, fields);
7460
7476
  klass._getDefaultValues = getDefaultValues;
7477
+ klass._initialize = initialize;
7461
7478
  Object.assign(klass.prototype, methods);
7462
7479
  for (const fieldName in viewTagFields) {
7463
7480
  view(viewTagFields[fieldName])(klass.prototype, fieldName);
@@ -7489,9 +7506,6 @@ function schema(fieldsAndMethods, name, inherits = Schema) {
7489
7506
  metadata[metadata[fieldName]].optional = true;
7490
7507
  }
7491
7508
  }
7492
- if (name) {
7493
- Object.defineProperty(klass, "name", { value: name });
7494
- }
7495
7509
  klass.extend = (childFields, childName) => schema(childFields, childName, klass);
7496
7510
  return klass;
7497
7511
  }