@colyseus/schema 3.0.0-alpha.37 → 3.0.0-alpha.39

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.
Files changed (45) hide show
  1. package/build/cjs/index.js +142 -32
  2. package/build/cjs/index.js.map +1 -1
  3. package/build/esm/index.mjs +142 -33
  4. package/build/esm/index.mjs.map +1 -1
  5. package/build/umd/index.js +142 -32
  6. package/lib/Metadata.d.ts +3 -2
  7. package/lib/Metadata.js +57 -15
  8. package/lib/Metadata.js.map +1 -1
  9. package/lib/Reflection.d.ts +4 -3
  10. package/lib/Reflection.js +36 -11
  11. package/lib/Reflection.js.map +1 -1
  12. package/lib/Schema.d.ts +2 -2
  13. package/lib/Schema.js.map +1 -1
  14. package/lib/annotations.d.ts +29 -12
  15. package/lib/annotations.js +36 -3
  16. package/lib/annotations.js.map +1 -1
  17. package/lib/codegen/parser.js +83 -0
  18. package/lib/codegen/parser.js.map +1 -1
  19. package/lib/codegen/types.js +3 -0
  20. package/lib/codegen/types.js.map +1 -1
  21. package/lib/decoder/DecodeOperation.js +4 -0
  22. package/lib/decoder/DecodeOperation.js.map +1 -1
  23. package/lib/decoder/strategy/StateCallbacks.js.map +1 -1
  24. package/lib/encoder/EncodeOperation.js +2 -2
  25. package/lib/encoder/EncodeOperation.js.map +1 -1
  26. package/lib/index.d.ts +1 -1
  27. package/lib/index.js +2 -1
  28. package/lib/index.js.map +1 -1
  29. package/lib/types/HelperTypes.d.ts +34 -2
  30. package/lib/types/HelperTypes.js.map +1 -1
  31. package/lib/types/TypeContext.js +9 -1
  32. package/lib/types/TypeContext.js.map +1 -1
  33. package/package.json +1 -1
  34. package/src/Metadata.ts +62 -16
  35. package/src/Reflection.ts +43 -16
  36. package/src/Schema.ts +2 -3
  37. package/src/annotations.ts +68 -18
  38. package/src/codegen/parser.ts +107 -0
  39. package/src/codegen/types.ts +1 -0
  40. package/src/decoder/DecodeOperation.ts +4 -0
  41. package/src/decoder/strategy/StateCallbacks.ts +1 -1
  42. package/src/encoder/EncodeOperation.ts +4 -2
  43. package/src/index.ts +1 -1
  44. package/src/types/HelperTypes.ts +54 -2
  45. package/src/types/TypeContext.ts +11 -1
@@ -113,7 +113,7 @@ class TypeContext {
113
113
  // Workaround to allow using an empty Schema (with no `@type()` fields)
114
114
  //
115
115
  if (schema[Symbol.metadata] === undefined) {
116
- Metadata.init(schema);
116
+ Metadata.initialize(schema);
117
117
  }
118
118
  this.schemas.set(schema, typeid);
119
119
  return true;
@@ -129,6 +129,14 @@ class TypeContext {
129
129
  TypeContext.inheritedTypes.get(klass)?.forEach((child) => {
130
130
  this.discoverTypes(child, parentIndex, parentFieldViewTag);
131
131
  });
132
+ // add parent classes
133
+ let parent = klass;
134
+ while ((parent = Object.getPrototypeOf(parent)) &&
135
+ parent !== Schema && // stop at root (Schema)
136
+ parent !== Function.prototype // stop at root (non-Schema)
137
+ ) {
138
+ this.discoverTypes(parent);
139
+ }
132
140
  const metadata = (klass[Symbol.metadata] ??= {});
133
141
  // if any schema/field has filters, mark "context" as having filters.
134
142
  if (metadata[$viewFieldIndexes]) {
@@ -167,6 +175,13 @@ class TypeContext {
167
175
  }
168
176
  }
169
177
 
178
+ function getNormalizedType(type) {
179
+ return (Array.isArray(type))
180
+ ? { array: type[0] }
181
+ : (typeof (type['type']) !== "undefined")
182
+ ? type['type']
183
+ : type;
184
+ }
170
185
  const Metadata = {
171
186
  addField(metadata, index, name, type, descriptor) {
172
187
  if (index > 64) {
@@ -174,14 +189,16 @@ const Metadata = {
174
189
  }
175
190
  metadata[index] = Object.assign(metadata[index] || {}, // avoid overwriting previous field metadata (@owned / @deprecated)
176
191
  {
177
- type: (Array.isArray(type))
178
- ? { array: type[0] }
179
- : type,
192
+ type: getNormalizedType(type),
180
193
  index,
181
194
  name,
182
195
  });
183
196
  // create "descriptors" map
184
- metadata[$descriptors] ??= {};
197
+ Object.defineProperty(metadata, $descriptors, {
198
+ value: metadata[$descriptors] || {},
199
+ enumerable: false,
200
+ configurable: true,
201
+ });
185
202
  if (descriptor) {
186
203
  // for encoder
187
204
  metadata[$descriptors][name] = descriptor;
@@ -256,7 +273,7 @@ const Metadata = {
256
273
  TypeContext.register(constructor);
257
274
  const parentClass = Object.getPrototypeOf(constructor);
258
275
  const parentMetadata = parentClass && parentClass[Symbol.metadata];
259
- const metadata = Metadata.initialize(constructor, parentMetadata);
276
+ const metadata = Metadata.initialize(constructor);
260
277
  // Use Schema's methods if not defined in the class
261
278
  if (!constructor[$track]) {
262
279
  constructor[$track] = Schema[$track];
@@ -279,11 +296,15 @@ const Metadata = {
279
296
  fieldIndex++;
280
297
  for (const field in fields) {
281
298
  const type = fields[field];
299
+ const normalizedType = getNormalizedType(type);
282
300
  // FIXME: this code is duplicated from @type() annotation
283
301
  const complexTypeKlass = (Array.isArray(type))
284
302
  ? getType("array")
285
303
  : (typeof (Object.keys(type)[0]) === "string") && getType(Object.keys(type)[0]);
286
- Metadata.addField(metadata, fieldIndex, field, type, getPropertyDescriptor(`_${field}`, fieldIndex, type, complexTypeKlass));
304
+ const childType = (complexTypeKlass)
305
+ ? Object.values(type)[0]
306
+ : normalizedType;
307
+ Metadata.addField(metadata, fieldIndex, field, type, getPropertyDescriptor(`_${field}`, fieldIndex, childType, complexTypeKlass));
287
308
  fieldIndex++;
288
309
  }
289
310
  return target;
@@ -304,24 +325,52 @@ const Metadata = {
304
325
  configurable: true,
305
326
  });
306
327
  },
307
- initialize(constructor, parentMetadata) {
328
+ initialize(constructor) {
329
+ const parentClass = Object.getPrototypeOf(constructor);
330
+ const parentMetadata = parentClass[Symbol.metadata];
308
331
  let metadata = constructor[Symbol.metadata] ?? Object.create(null);
309
332
  // make sure inherited classes have their own metadata object.
310
- if (constructor[Symbol.metadata] === parentMetadata) {
333
+ if (parentClass !== Schema && metadata === parentMetadata) {
311
334
  metadata = Object.create(null);
312
335
  if (parentMetadata) {
336
+ //
313
337
  // assign parent metadata to current
314
- Object.assign(metadata, parentMetadata);
315
- for (let i = 0; i <= parentMetadata[$numFields]; i++) {
316
- const fieldName = parentMetadata[i].name;
317
- Object.defineProperty(metadata, fieldName, {
318
- value: parentMetadata[fieldName],
338
+ //
339
+ Object.setPrototypeOf(metadata, parentMetadata);
340
+ // $numFields
341
+ Object.defineProperty(metadata, $numFields, {
342
+ value: parentMetadata[$numFields],
343
+ enumerable: false,
344
+ configurable: true,
345
+ writable: true,
346
+ });
347
+ // $viewFieldIndexes / $fieldIndexesByViewTag
348
+ if (parentMetadata[$viewFieldIndexes] !== undefined) {
349
+ Object.defineProperty(metadata, $viewFieldIndexes, {
350
+ value: [...parentMetadata[$viewFieldIndexes]],
319
351
  enumerable: false,
320
352
  configurable: true,
353
+ writable: true,
354
+ });
355
+ Object.defineProperty(metadata, $fieldIndexesByViewTag, {
356
+ value: { ...parentMetadata[$fieldIndexesByViewTag] },
357
+ enumerable: false,
358
+ configurable: true,
359
+ writable: true,
321
360
  });
322
361
  }
323
- Object.defineProperty(metadata, $numFields, {
324
- value: parentMetadata[$numFields],
362
+ // $refTypeFieldIndexes
363
+ if (parentMetadata[$refTypeFieldIndexes] !== undefined) {
364
+ Object.defineProperty(metadata, $refTypeFieldIndexes, {
365
+ value: [...parentMetadata[$refTypeFieldIndexes]],
366
+ enumerable: false,
367
+ configurable: true,
368
+ writable: true,
369
+ });
370
+ }
371
+ // $descriptors
372
+ Object.defineProperty(metadata, $descriptors, {
373
+ value: { ...parentMetadata[$descriptors] },
325
374
  enumerable: false,
326
375
  configurable: true,
327
376
  writable: true,
@@ -1096,7 +1145,6 @@ const encodeSchemaOperation = function (encoder, bytes, changeTree, index, opera
1096
1145
  return;
1097
1146
  }
1098
1147
  const ref = changeTree.ref;
1099
- // const metadata: Metadata = ref.constructor[Symbol.metadata];
1100
1148
  const field = metadata[index];
1101
1149
  // TODO: inline this function call small performance gain
1102
1150
  encodeValue(encoder, bytes, metadata[index].type, ref[field.name], operation, it);
@@ -1171,7 +1219,8 @@ const encodeArray = function (encoder, bytes, changeTree, field, operation, it,
1171
1219
  // encode operation
1172
1220
  bytes[it.offset++] = operation & 255;
1173
1221
  // custom operations
1174
- if (operation === OPERATION.CLEAR) {
1222
+ if (operation === OPERATION.CLEAR ||
1223
+ operation === OPERATION.REVERSE) {
1175
1224
  return;
1176
1225
  }
1177
1226
  // encode index
@@ -1649,6 +1698,10 @@ const decodeArray = function (decoder, bytes, it, ref, allChanges) {
1649
1698
  ref.clear();
1650
1699
  return;
1651
1700
  }
1701
+ else if (operation === OPERATION.REVERSE) {
1702
+ ref.reverse();
1703
+ return;
1704
+ }
1652
1705
  else if (operation === OPERATION.DELETE_BY_REFID) {
1653
1706
  // TODO: refactor here, try to follow same flow as below
1654
1707
  const refId = number(bytes, it);
@@ -2768,13 +2821,13 @@ function type(type, options) {
2768
2821
  // for inheritance support
2769
2822
  TypeContext.register(constructor);
2770
2823
  const parentClass = Object.getPrototypeOf(constructor);
2771
- const parentMetadata = parentClass && parentClass[Symbol.metadata];
2772
- const metadata = Metadata.initialize(constructor, parentMetadata);
2824
+ const parentMetadata = parentClass[Symbol.metadata];
2825
+ const metadata = Metadata.initialize(constructor);
2773
2826
  let fieldIndex = metadata[field];
2774
2827
  /**
2775
2828
  * skip if descriptor already exists for this field (`@deprecated()`)
2776
2829
  */
2777
- if (metadata[fieldIndex]) {
2830
+ if (metadata[fieldIndex] !== undefined) {
2778
2831
  if (metadata[fieldIndex].deprecated) {
2779
2832
  // do not create accessors for deprecated properties.
2780
2833
  return;
@@ -2924,6 +2977,37 @@ function defineTypes(target, fields, options) {
2924
2977
  }
2925
2978
  return target;
2926
2979
  }
2980
+ function schema(fields, name, inherits = Schema) {
2981
+ const defaultValues = {};
2982
+ const viewTagFields = {};
2983
+ for (let fieldName in fields) {
2984
+ const field = fields[fieldName];
2985
+ if (typeof (field) === "object") {
2986
+ if (field['default'] !== undefined) {
2987
+ defaultValues[fieldName] = field['default'];
2988
+ }
2989
+ if (field['view'] !== undefined) {
2990
+ viewTagFields[fieldName] = (typeof (field['view']) === "boolean")
2991
+ ? DEFAULT_VIEW_TAG
2992
+ : field['view'];
2993
+ }
2994
+ }
2995
+ }
2996
+ const klass = Metadata.setFields(class extends inherits {
2997
+ constructor(...args) {
2998
+ args[0] = Object.assign({}, defaultValues, args[0]);
2999
+ super(...args);
3000
+ }
3001
+ }, fields);
3002
+ for (let fieldName in viewTagFields) {
3003
+ view(viewTagFields[fieldName])(klass.prototype, fieldName);
3004
+ }
3005
+ if (name) {
3006
+ Object.defineProperty(klass, "name", { value: name });
3007
+ }
3008
+ klass.extends = (fields, name) => schema(fields, name, klass);
3009
+ return klass;
3010
+ }
2927
3011
 
2928
3012
  function getIndent(level) {
2929
3013
  return (new Array(level).fill(0)).map((_, i) => (i === level - 1) ? `└─ ` : ` `).join("");
@@ -4171,13 +4255,20 @@ class Reflection extends Schema {
4171
4255
  /**
4172
4256
  * Encodes the TypeContext of an Encoder into a buffer.
4173
4257
  *
4174
- * @param context TypeContext instance
4258
+ * @param encoder Encoder instance
4175
4259
  * @param it
4176
4260
  * @returns
4177
4261
  */
4178
- static encode(context, it = { offset: 0 }) {
4262
+ static encode(encoder, it = { offset: 0 }) {
4263
+ const context = encoder.context;
4179
4264
  const reflection = new Reflection();
4180
4265
  const reflectionEncoder = new Encoder(reflection);
4266
+ // rootType is usually the first schema passed to the Encoder
4267
+ // (unless it inherits from another schema)
4268
+ const rootType = context.schemas.get(encoder.state.constructor);
4269
+ if (rootType > 0) {
4270
+ reflection.rootType = rootType;
4271
+ }
4181
4272
  const buildType = (currentType, metadata) => {
4182
4273
  for (const fieldIndex in metadata) {
4183
4274
  const index = Number(fieldIndex);
@@ -4251,18 +4342,14 @@ class Reflection extends Schema {
4251
4342
  const parentClass = typeContext.get(reflectionType.extendsId) ?? Schema;
4252
4343
  const schema = class _ extends parentClass {
4253
4344
  };
4254
- const parentMetadata = parentClass[Symbol.metadata];
4255
4345
  // register for inheritance support
4256
4346
  TypeContext.register(schema);
4257
- // for inheritance support
4258
- Metadata.initialize(schema, parentMetadata);
4347
+ // // for inheritance support
4348
+ // Metadata.initialize(schema);
4259
4349
  typeContext.add(schema, reflectionType.id);
4260
4350
  }, {});
4261
- // 2nd pass, set fields
4262
- reflection.types.forEach((reflectionType) => {
4263
- const schemaType = typeContext.get(reflectionType.id);
4264
- const metadata = schemaType[Symbol.metadata];
4265
- const parentFieldIndex = 0;
4351
+ // define fields
4352
+ const addFields = (metadata, reflectionType, parentFieldIndex) => {
4266
4353
  reflectionType.fields.forEach((field, i) => {
4267
4354
  const fieldIndex = parentFieldIndex + i;
4268
4355
  if (field.referencedType !== undefined) {
@@ -4285,14 +4372,36 @@ class Reflection extends Schema {
4285
4372
  Metadata.addField(metadata, fieldIndex, field.name, field.type);
4286
4373
  }
4287
4374
  });
4375
+ };
4376
+ // 2nd pass, set fields
4377
+ reflection.types.forEach((reflectionType) => {
4378
+ const schema = typeContext.get(reflectionType.id);
4379
+ // for inheritance support
4380
+ const metadata = Metadata.initialize(schema);
4381
+ const inheritedTypes = [];
4382
+ let parentType = reflectionType;
4383
+ do {
4384
+ inheritedTypes.push(parentType);
4385
+ parentType = reflection.types.find((t) => t.id === parentType.extendsId);
4386
+ } while (parentType);
4387
+ let parentFieldIndex = 0;
4388
+ inheritedTypes.reverse().forEach((reflectionType) => {
4389
+ // add fields from all inherited classes
4390
+ // TODO: refactor this to avoid adding fields from parent classes
4391
+ addFields(metadata, reflectionType, parentFieldIndex);
4392
+ parentFieldIndex += reflectionType.fields.length;
4393
+ });
4288
4394
  });
4289
- const state = new (typeContext.get(0))();
4395
+ const state = new (typeContext.get(reflection.rootType || 0))();
4290
4396
  return new Decoder(state, typeContext);
4291
4397
  }
4292
4398
  }
4293
4399
  __decorate([
4294
4400
  type([ReflectionType])
4295
4401
  ], Reflection.prototype, "types", void 0);
4402
+ __decorate([
4403
+ type("number")
4404
+ ], Reflection.prototype, "rootType", void 0);
4296
4405
 
4297
4406
  function getDecoderStateCallbacks(decoder) {
4298
4407
  const $root = decoder.root;
@@ -4731,5 +4840,5 @@ registerType("array", { constructor: ArraySchema });
4731
4840
  registerType("set", { constructor: SetSchema });
4732
4841
  registerType("collection", { constructor: CollectionSchema, });
4733
4842
 
4734
- export { $changes, $childType, $decoder, $deleteByIndex, $encoder, $filter, $getByIndex, $track, ArraySchema, ChangeTree, CollectionSchema, Decoder, Encoder, MapSchema, Metadata, OPERATION, Reflection, ReflectionField, ReflectionType, Schema, SetSchema, StateView, TypeContext, decode, decodeKeyValueOperation, decodeSchemaOperation, defineTypes, deprecated, dumpChanges, encode, encodeArray as encodeKeyValueOperation, encodeSchemaOperation, getDecoderStateCallbacks, getRawChangesCallback, registerType, type, view };
4843
+ export { $changes, $childType, $decoder, $deleteByIndex, $encoder, $filter, $getByIndex, $track, ArraySchema, ChangeTree, CollectionSchema, Decoder, Encoder, MapSchema, Metadata, OPERATION, Reflection, ReflectionField, ReflectionType, Schema, SetSchema, StateView, TypeContext, decode, decodeKeyValueOperation, decodeSchemaOperation, defineTypes, deprecated, dumpChanges, encode, encodeArray as encodeKeyValueOperation, encodeSchemaOperation, getDecoderStateCallbacks, getRawChangesCallback, registerType, schema, type, view };
4735
4844
  //# sourceMappingURL=index.mjs.map