@colyseus/schema 5.0.20 → 5.0.21

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.js CHANGED
@@ -1415,6 +1415,10 @@
1415
1415
  });
1416
1416
  }
1417
1417
  for (const field in fields) {
1418
+ // metadata inherits the parent's, so this also catches a redeclared parent field
1419
+ if (metadata[field] !== undefined) {
1420
+ throw new Error(`@colyseus/schema: Duplicate '${field}' definition on '${constructor.name || "(anonymous)"}'.`);
1421
+ }
1418
1422
  Metadata.defineField(constructor, metadata, fieldIndex, field, fields[field]);
1419
1423
  fieldIndex++;
1420
1424
  }
@@ -7279,6 +7283,9 @@
7279
7283
  /**
7280
7284
  * Define a Schema class declaratively.
7281
7285
  *
7286
+ * `initialize()` acts as the constructor: a class created with `.extend()`
7287
+ * inherits the parent's unless it defines its own.
7288
+ *
7282
7289
  * @example
7283
7290
  * import { schema, t } from '@colyseus/schema';
7284
7291
  *
@@ -7439,8 +7446,11 @@
7439
7446
  return parentProps;
7440
7447
  };
7441
7448
  const hasInitialize = typeof methods.initialize === "function";
7442
- /** @codegen-ignore */
7443
- const klass = Metadata.setFields(class extends inherits {
7449
+ // Like a constructor: the most-derived initialize() runs once, own or
7450
+ // inherited from a schema() parent. A custom base's initialize() is not
7451
+ // picked up — the constructor type only sees the fields map.
7452
+ const initialize = methods.initialize ?? inherits._initialize;
7453
+ const klass = class extends inherits {
7444
7454
  constructor(...args) {
7445
7455
  const props = args[0];
7446
7456
  if (props === undefined) {
@@ -7455,13 +7465,20 @@
7455
7465
  // `initialize()` owns the schema fields, so only parent props flow up.
7456
7466
  super(Object.assign(getDefaultValues(), hasInitialize ? getParentProps(props) : props));
7457
7467
  }
7458
- // Only call initialize() on the exact target class, not parents.
7459
- if (hasInitialize && new.target === klass) {
7460
- methods.initialize.apply(this, args);
7468
+ // Only on the exact target class parents' constructors skip it.
7469
+ if (initialize && new.target === klass) {
7470
+ initialize.apply(this, args);
7461
7471
  }
7462
7472
  }
7463
- }, fields);
7473
+ };
7474
+ // named before setFields so a duplicate-field error can say which class
7475
+ if (name) {
7476
+ Object.defineProperty(klass, "name", { value: name });
7477
+ }
7478
+ /** @codegen-ignore */
7479
+ Metadata.setFields(klass, fields);
7464
7480
  klass._getDefaultValues = getDefaultValues;
7481
+ klass._initialize = initialize;
7465
7482
  Object.assign(klass.prototype, methods);
7466
7483
  for (const fieldName in viewTagFields) {
7467
7484
  view(viewTagFields[fieldName])(klass.prototype, fieldName);
@@ -7493,9 +7510,6 @@
7493
7510
  metadata[metadata[fieldName]].optional = true;
7494
7511
  }
7495
7512
  }
7496
- if (name) {
7497
- Object.defineProperty(klass, "name", { value: name });
7498
- }
7499
7513
  klass.extend = (childFields, childName) => schema(childFields, childName, klass);
7500
7514
  return klass;
7501
7515
  }
package/build/index.mjs CHANGED
@@ -1409,6 +1409,10 @@ const Metadata = {
1409
1409
  });
1410
1410
  }
1411
1411
  for (const field in fields) {
1412
+ // metadata inherits the parent's, so this also catches a redeclared parent field
1413
+ if (metadata[field] !== undefined) {
1414
+ throw new Error(`@colyseus/schema: Duplicate '${field}' definition on '${constructor.name || "(anonymous)"}'.`);
1415
+ }
1412
1416
  Metadata.defineField(constructor, metadata, fieldIndex, field, fields[field]);
1413
1417
  fieldIndex++;
1414
1418
  }
@@ -7273,6 +7277,9 @@ function makeAutoDefaultFactory(rawType) {
7273
7277
  /**
7274
7278
  * Define a Schema class declaratively.
7275
7279
  *
7280
+ * `initialize()` acts as the constructor: a class created with `.extend()`
7281
+ * inherits the parent's unless it defines its own.
7282
+ *
7276
7283
  * @example
7277
7284
  * import { schema, t } from '@colyseus/schema';
7278
7285
  *
@@ -7433,8 +7440,11 @@ function schema(fieldsAndMethods, name, inherits = Schema) {
7433
7440
  return parentProps;
7434
7441
  };
7435
7442
  const hasInitialize = typeof methods.initialize === "function";
7436
- /** @codegen-ignore */
7437
- const klass = Metadata.setFields(class extends inherits {
7443
+ // Like a constructor: the most-derived initialize() runs once, own or
7444
+ // inherited from a schema() parent. A custom base's initialize() is not
7445
+ // picked up — the constructor type only sees the fields map.
7446
+ const initialize = methods.initialize ?? inherits._initialize;
7447
+ const klass = class extends inherits {
7438
7448
  constructor(...args) {
7439
7449
  const props = args[0];
7440
7450
  if (props === undefined) {
@@ -7449,13 +7459,20 @@ function schema(fieldsAndMethods, name, inherits = Schema) {
7449
7459
  // `initialize()` owns the schema fields, so only parent props flow up.
7450
7460
  super(Object.assign(getDefaultValues(), hasInitialize ? getParentProps(props) : props));
7451
7461
  }
7452
- // Only call initialize() on the exact target class, not parents.
7453
- if (hasInitialize && new.target === klass) {
7454
- methods.initialize.apply(this, args);
7462
+ // Only on the exact target class parents' constructors skip it.
7463
+ if (initialize && new.target === klass) {
7464
+ initialize.apply(this, args);
7455
7465
  }
7456
7466
  }
7457
- }, fields);
7467
+ };
7468
+ // named before setFields so a duplicate-field error can say which class
7469
+ if (name) {
7470
+ Object.defineProperty(klass, "name", { value: name });
7471
+ }
7472
+ /** @codegen-ignore */
7473
+ Metadata.setFields(klass, fields);
7458
7474
  klass._getDefaultValues = getDefaultValues;
7475
+ klass._initialize = initialize;
7459
7476
  Object.assign(klass.prototype, methods);
7460
7477
  for (const fieldName in viewTagFields) {
7461
7478
  view(viewTagFields[fieldName])(klass.prototype, fieldName);
@@ -7487,9 +7504,6 @@ function schema(fieldsAndMethods, name, inherits = Schema) {
7487
7504
  metadata[metadata[fieldName]].optional = true;
7488
7505
  }
7489
7506
  }
7490
- if (name) {
7491
- Object.defineProperty(klass, "name", { value: name });
7492
- }
7493
7507
  klass.extend = (childFields, childName) => schema(childFields, childName, klass);
7494
7508
  return klass;
7495
7509
  }