@colyseus/schema 3.0.62 → 3.0.63

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 (100) hide show
  1. package/build/cjs/index.js +24 -79
  2. package/build/cjs/index.js.map +1 -1
  3. package/build/esm/index.mjs +24 -79
  4. package/build/esm/index.mjs.map +1 -1
  5. package/build/umd/index.js +24 -79
  6. package/lib/Metadata.d.ts +2 -2
  7. package/lib/Metadata.js.map +1 -1
  8. package/lib/Reflection.js +2 -1
  9. package/lib/Reflection.js.map +1 -1
  10. package/lib/Schema.d.ts +14 -14
  11. package/lib/Schema.js +4 -7
  12. package/lib/Schema.js.map +1 -1
  13. package/lib/annotations.d.ts +37 -5
  14. package/lib/annotations.js +17 -7
  15. package/lib/annotations.js.map +1 -1
  16. package/lib/codegen/api.js.map +1 -1
  17. package/lib/codegen/argv.d.ts +1 -1
  18. package/lib/codegen/argv.js.map +1 -1
  19. package/lib/codegen/cli.js.map +1 -1
  20. package/lib/codegen/languages/cpp.js.map +1 -1
  21. package/lib/codegen/languages/csharp.js.map +1 -1
  22. package/lib/codegen/languages/haxe.js.map +1 -1
  23. package/lib/codegen/languages/java.js.map +1 -1
  24. package/lib/codegen/languages/js.js.map +1 -1
  25. package/lib/codegen/languages/lua.js.map +1 -1
  26. package/lib/codegen/languages/ts.js.map +1 -1
  27. package/lib/codegen/parser.js +11 -0
  28. package/lib/codegen/parser.js.map +1 -1
  29. package/lib/codegen/types.d.ts +1 -1
  30. package/lib/codegen/types.js.map +1 -1
  31. package/lib/decoder/DecodeOperation.d.ts +2 -2
  32. package/lib/decoder/DecodeOperation.js.map +1 -1
  33. package/lib/decoder/Decoder.js.map +1 -1
  34. package/lib/decoder/ReferenceTracker.js.map +1 -1
  35. package/lib/decoder/strategy/StateCallbacks.js.map +1 -1
  36. package/lib/encoder/ChangeTree.d.ts +6 -1
  37. package/lib/encoder/ChangeTree.js.map +1 -1
  38. package/lib/encoder/EncodeOperation.js.map +1 -1
  39. package/lib/encoder/Encoder.d.ts +0 -1
  40. package/lib/encoder/Encoder.js +0 -21
  41. package/lib/encoder/Encoder.js.map +1 -1
  42. package/lib/encoder/StateView.js.map +1 -1
  43. package/lib/encoding/decode.js +1 -22
  44. package/lib/encoding/decode.js.map +1 -1
  45. package/lib/encoding/encode.d.ts +1 -23
  46. package/lib/encoding/encode.js +1 -22
  47. package/lib/encoding/encode.js.map +1 -1
  48. package/lib/index.d.ts +3 -2
  49. package/lib/index.js.map +1 -1
  50. package/lib/types/HelperTypes.d.ts +14 -5
  51. package/lib/types/HelperTypes.js.map +1 -1
  52. package/lib/types/TypeContext.js.map +1 -1
  53. package/lib/types/custom/ArraySchema.d.ts +9 -5
  54. package/lib/types/custom/ArraySchema.js.map +1 -1
  55. package/lib/types/custom/CollectionSchema.d.ts +8 -4
  56. package/lib/types/custom/CollectionSchema.js.map +1 -1
  57. package/lib/types/custom/MapSchema.d.ts +8 -6
  58. package/lib/types/custom/MapSchema.js.map +1 -1
  59. package/lib/types/custom/SetSchema.d.ts +8 -4
  60. package/lib/types/custom/SetSchema.js.map +1 -1
  61. package/lib/types/registry.js.map +1 -1
  62. package/lib/utils.js.map +1 -1
  63. package/lib/v3_bench.js.map +1 -1
  64. package/package.json +2 -2
  65. package/src/Metadata.ts +2 -2
  66. package/src/Reflection.ts +5 -4
  67. package/src/Schema.ts +35 -37
  68. package/src/annotations.ts +93 -30
  69. package/src/codegen/api.ts +1 -1
  70. package/src/codegen/argv.ts +5 -5
  71. package/src/codegen/cli.ts +1 -1
  72. package/src/codegen/languages/cpp.ts +5 -4
  73. package/src/codegen/languages/csharp.ts +2 -2
  74. package/src/codegen/languages/haxe.ts +2 -2
  75. package/src/codegen/languages/java.ts +2 -2
  76. package/src/codegen/languages/js.ts +3 -2
  77. package/src/codegen/languages/lua.ts +3 -2
  78. package/src/codegen/languages/ts.ts +3 -2
  79. package/src/codegen/parser.ts +12 -0
  80. package/src/codegen/types.ts +2 -2
  81. package/src/decoder/DecodeOperation.ts +21 -21
  82. package/src/decoder/Decoder.ts +3 -3
  83. package/src/decoder/ReferenceTracker.ts +7 -5
  84. package/src/decoder/strategy/StateCallbacks.ts +10 -10
  85. package/src/encoder/ChangeTree.ts +21 -15
  86. package/src/encoder/EncodeOperation.ts +4 -4
  87. package/src/encoder/Encoder.ts +0 -24
  88. package/src/encoder/StateView.ts +3 -2
  89. package/src/encoding/decode.ts +2 -0
  90. package/src/encoding/encode.ts +3 -1
  91. package/src/index.ts +5 -2
  92. package/src/types/HelperTypes.ts +29 -7
  93. package/src/types/TypeContext.ts +1 -1
  94. package/src/types/custom/ArraySchema.ts +12 -10
  95. package/src/types/custom/CollectionSchema.ts +9 -6
  96. package/src/types/custom/MapSchema.ts +8 -8
  97. package/src/types/custom/SetSchema.ts +9 -6
  98. package/src/types/registry.ts +2 -2
  99. package/src/utils.ts +2 -4
  100. package/src/v3_bench.ts +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"v3_bench.js","sourceRoot":"","sources":["../src/v3_bench.ts"],"names":[],"mappings":"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","sourcesContent":["import { Schema, type, MapSchema, ArraySchema, Reflection, Encoder, Decoder } from \"./index\";\n\n// globalThis.interval = setInterval(() => {}, 1000);\n\n// class Item extends Schema {\n// @type(\"string\") name: string;\n// }\n\n// class RootState extends Schema {\n// @type([Item]) items = new ArraySchema<Item>();\n// }\n// const state = new RootState();\n// state.items.push(new Item().assign({ name: \"hello\" }));\n\n// console.log(\"Encoded:\", state.encode());\n\nclass Vec3 extends Schema {\n @type(\"number\") x: number;\n @type(\"number\") y: number;\n @type(\"number\") z: number;\n}\n\nclass Base extends Schema {}\n\nclass Entity extends Schema {\n @type(Vec3) position = new Vec3().assign({ x: 0, y: 0, z: 0 });\n}\n\nclass Player extends Entity {\n @type(Vec3) rotation = new Vec3().assign({ x: 0, y: 0, z: 0 });\n @type(\"string\") secret: string = \"private info only for this player\";\n}\n\nclass State extends Schema {\n // @type({ map: Base }) players = new MapSchema<Entity>();\n @type(\"number\") num: number = 0;\n @type(\"string\") str = \"Hello world!\";\n // @type(Entity) entity = new Player().assign({\n // position: new Vec3().assign({ x: 1, y: 2, z: 3 }),\n // rotation: new Vec3().assign({ x: 4, y: 5, z: 6 }),\n // });\n @type({ map: Entity }) entities = new MapSchema();\n}\n\nconst state = new State();\n\nstate.entities.set(\"one\", new Player().assign({\n position: new Vec3().assign({ x: 1, y: 2, z: 3 }),\n rotation: new Vec3().assign({ x: 1, y: 2, z: 3 }),\n}));\n\nstate.entities.set(\"two\", new Player().assign({\n position: new Vec3().assign({ x: 4, y: 5, z: 6 }),\n rotation: new Vec3().assign({ x: 7, y: 8, z: 9 }),\n}));\n\nconst encoder = new Encoder(state);\nlet encoded = encoder.encode();\nconsole.log(`(${encoded.length})`, [...encoded]);\n\nglobalThis.perform = function() {\n for (let i = 0; i < 500000; i++) {\n encoder.encodeAll();\n }\n}\n\nfunction logTime(label: string, callback: Function) {\n const time = Date.now();\n for (let i = 0; i < 500000; i++) {\n callback();\n }\n console.log(`${label}:`, Date.now() - time);\n}\nlogTime(\"encode time\", () => encoder.encodeAll());\n\nconst decoder = new Decoder(new State());\nlogTime(\"decode time\", () => decoder.decode(encoded));\n\n// const time = Date.now();\n// console.profile();\n// for (let i = 0; i < 300000; i++) {\n// state.encodeAll();\n// }\n// console.profileEnd();\n// console.log(\"encode time:\", Date.now() - time);\n\n// const decoded = Reflection.decode(Reflection.encode(state));\n// decoded.decode(encoded);\n//\n// console.log(decoded.toJSON());\n//\n// const rotation = state.entity.rotation;\n// rotation.x = 100;\n//\n// encoded = state.encode();\n// console.log({encoded});\n//\n// decoded.decode(encoded);\n// console.log(decoded.toJSON());\n\n// const time = Date.now();\n// for (let i = 0; i < 300000; i++) {\n// const state = new State();\n// state.encode();\n// }\n// console.log(\"encode time:\", Date.now() - time);\n\n"]}
1
+ {"version":3,"file":"v3_bench.js","sourceRoot":"","sources":["../src/v3_bench.ts"],"names":[],"mappings":"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","sourcesContent":["import { Schema, type, MapSchema, ArraySchema, Reflection, Encoder, Decoder } from \"./index\";\n\n// globalThis.interval = setInterval(() => {}, 1000);\n\n// class Item extends Schema {\n// @type(\"string\") name: string;\n// }\n\n// class RootState extends Schema {\n// @type([Item]) items = new ArraySchema<Item>();\n// }\n// const state = new RootState();\n// state.items.push(new Item().assign({ name: \"hello\" }));\n\n// console.log(\"Encoded:\", state.encode());\n\nclass Vec3 extends Schema {\n @type(\"number\") x: number;\n @type(\"number\") y: number;\n @type(\"number\") z: number;\n}\n\nclass Base extends Schema {}\n\nclass Entity extends Schema {\n @type(Vec3) position = new Vec3().assign({ x: 0, y: 0, z: 0 });\n}\n\nclass Player extends Entity {\n @type(Vec3) rotation = new Vec3().assign({ x: 0, y: 0, z: 0 });\n @type(\"string\") secret: string = \"private info only for this player\";\n}\n\nclass State extends Schema {\n // @type({ map: Base }) players = new MapSchema<Entity>();\n @type(\"number\") num: number = 0;\n @type(\"string\") str = \"Hello world!\";\n // @type(Entity) entity = new Player().assign({\n // position: new Vec3().assign({ x: 1, y: 2, z: 3 }),\n // rotation: new Vec3().assign({ x: 4, y: 5, z: 6 }),\n // });\n @type({ map: Entity }) entities = new MapSchema();\n}\n\nconst state = new State();\n\nstate.entities.set(\"one\", new Player().assign({\n position: new Vec3().assign({ x: 1, y: 2, z: 3 }),\n rotation: new Vec3().assign({ x: 1, y: 2, z: 3 }),\n}));\n\nstate.entities.set(\"two\", new Player().assign({\n position: new Vec3().assign({ x: 4, y: 5, z: 6 }),\n rotation: new Vec3().assign({ x: 7, y: 8, z: 9 }),\n}));\n\nconst encoder = new Encoder(state);\nlet encoded = encoder.encode();\nconsole.log(`(${encoded.length})`, [...encoded]);\n\n(globalThis as any).perform = function(): void {\n for (let i = 0; i < 500000; i++) {\n encoder.encodeAll();\n }\n}\n\nfunction logTime(label: string, callback: Function) {\n const time = Date.now();\n for (let i = 0; i < 500000; i++) {\n callback();\n }\n console.log(`${label}:`, Date.now() - time);\n}\nlogTime(\"encode time\", () => encoder.encodeAll());\n\nconst decoder = new Decoder(new State());\nlogTime(\"decode time\", () => decoder.decode(encoded));\n\n// const time = Date.now();\n// console.profile();\n// for (let i = 0; i < 300000; i++) {\n// state.encodeAll();\n// }\n// console.profileEnd();\n// console.log(\"encode time:\", Date.now() - time);\n\n// const decoded = Reflection.decode(Reflection.encode(state));\n// decoded.decode(encoded);\n//\n// console.log(decoded.toJSON());\n//\n// const rotation = state.entity.rotation;\n// rotation.x = 100;\n//\n// encoded = state.encode();\n// console.log({encoded});\n//\n// decoded.decode(encoded);\n// console.log(decoded.toJSON());\n\n// const time = Date.now();\n// for (let i = 0; i < 300000; i++) {\n// const state = new State();\n// state.encode();\n// }\n// console.log(\"encode time:\", Date.now() - time);\n\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@colyseus/schema",
3
- "version": "3.0.62",
3
+ "version": "3.0.63",
4
4
  "description": "Binary state serializer with delta encoding for games",
5
5
  "bin": {
6
6
  "schema-codegen": "bin/schema-codegen",
@@ -81,7 +81,7 @@
81
81
  "ts-node": "^10.9.2",
82
82
  "tslib": "^2.1.0",
83
83
  "tsx": "^3.13.0",
84
- "typescript": "^5.4.5"
84
+ "typescript": "^5.9.3"
85
85
  },
86
86
  "nyc": {
87
87
  "extension": [
package/src/Metadata.ts CHANGED
@@ -22,7 +22,7 @@ export type Metadata =
22
22
  { [field: string]: number; } & // field name => field metadata
23
23
  { [$descriptors]: { [field: string]: PropertyDescriptor } } // property descriptors
24
24
 
25
- export function getNormalizedType(type: DefinitionType): DefinitionType {
25
+ export function getNormalizedType(type: any): DefinitionType {
26
26
  if (Array.isArray(type)) {
27
27
  return { array: getNormalizedType(type[0]) };
28
28
 
@@ -308,7 +308,7 @@ export const Metadata = {
308
308
 
309
309
  getFields(klass: any) {
310
310
  const metadata: Metadata = klass[Symbol.metadata];
311
- const fields = {};
311
+ const fields: any = {};
312
312
  for (let i = 0; i <= metadata[$numFields]; i++) {
313
313
  fields[metadata[i].name] = metadata[i].type;
314
314
  }
package/src/Reflection.ts CHANGED
@@ -117,11 +117,11 @@ export class Reflection extends Schema {
117
117
  } else {
118
118
  fieldType = Object.keys(field.type)[0];
119
119
 
120
- if (typeof (field.type[fieldType]) === "string") {
121
- fieldType += ":" + field.type[fieldType]; // array:string
120
+ if (typeof (field.type[fieldType as keyof typeof field.type]) === "string") {
121
+ fieldType += ":" + field.type[fieldType as keyof typeof field.type]; // array:string
122
122
 
123
123
  } else {
124
- childTypeSchema = field.type[fieldType];
124
+ childTypeSchema = field.type[fieldType as keyof typeof field.type];
125
125
  }
126
126
  }
127
127
 
@@ -145,7 +145,8 @@ export class Reflection extends Schema {
145
145
  }
146
146
 
147
147
  const buf = reflectionEncoder.encodeAll(it);
148
- return Buffer.from(buf, 0, it.offset);
148
+ return buf.slice(0, it.offset)
149
+ // return Buffer.from(buf, 0, it.offset);
149
150
  }
150
151
 
151
152
  /**
package/src/Schema.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { OPERATION } from './encoding/spec';
2
2
  import { DEFAULT_VIEW_TAG, type DefinitionType } from "./annotations";
3
3
 
4
- import { NonFunctionPropNames, ToJSON } from './types/HelperTypes';
4
+ import { AssignableProps, NonFunctionPropNames, ToJSON } from './types/HelperTypes';
5
5
 
6
- import { ChangeSet, ChangeSetName, ChangeTree, Ref } from './encoder/ChangeTree';
6
+ import { ChangeSet, ChangeSetName, ChangeTree, IRef, Ref } from './encoder/ChangeTree';
7
7
  import { $changes, $decoder, $deleteByIndex, $descriptors, $encoder, $filter, $getByIndex, $track } from './types/symbols';
8
8
  import { StateView } from './encoder/StateView';
9
9
 
@@ -11,13 +11,14 @@ import { encodeSchemaOperation } from './encoder/EncodeOperation';
11
11
  import { decodeSchemaOperation } from './decoder/DecodeOperation';
12
12
 
13
13
  import type { Decoder } from './decoder/Decoder';
14
- import type { Metadata } from './Metadata';
14
+ import type { Metadata, MetadataField } from './Metadata';
15
15
  import { getIndent } from './utils';
16
16
 
17
17
  /**
18
18
  * Schema encoder / decoder
19
19
  */
20
- export class Schema {
20
+ export class Schema<C = any> implements IRef {
21
+ static [Symbol.metadata]: Metadata;
21
22
  static [$encoder] = encodeSchemaOperation;
22
23
  static [$decoder] = decodeSchemaOperation;
23
24
 
@@ -36,9 +37,7 @@ export class Schema {
36
37
  }
37
38
 
38
39
  static is(type: DefinitionType) {
39
- return typeof(type[Symbol.metadata]) === "object";
40
- // const metadata = type[Symbol.metadata];
41
- // return metadata && Object.prototype.hasOwnProperty.call(metadata, -1);
40
+ return typeof((type as typeof Schema)[Symbol.metadata]) === "object";
42
41
  }
43
42
 
44
43
  /**
@@ -58,7 +57,7 @@ export class Schema {
58
57
  * - Then, the encoder iterates over all "owned" properties per instance and encodes them.
59
58
  */
60
59
  static [$filter] (ref: Schema, index: number, view: StateView) {
61
- const metadata: Metadata = ref.constructor[Symbol.metadata];
60
+ const metadata: Metadata = (ref.constructor as typeof Schema)[Symbol.metadata];
62
61
  const tag = metadata[index]?.tag;
63
62
 
64
63
  if (view === undefined) {
@@ -81,7 +80,7 @@ export class Schema {
81
80
  }
82
81
 
83
82
  // allow inherited classes to have a constructor
84
- constructor(...args: any[]) {
83
+ constructor(arg?: C) {
85
84
  //
86
85
  // inline
87
86
  // Schema.initialize(this);
@@ -91,14 +90,14 @@ export class Schema {
91
90
  //
92
91
  // Assign initial values
93
92
  //
94
- if (args[0]) {
95
- Object.assign(this, args[0]);
93
+ if (arg) {
94
+ Object.assign(this, arg);
96
95
  }
97
96
  }
98
97
 
99
- public assign(
100
- props: { [prop in NonFunctionPropNames<this>]?: this[prop] } | ToJSON<this>,
101
- ) {
98
+ public assign<T extends Partial<this>>(
99
+ props: AssignableProps<T>,
100
+ ): this {
102
101
  Object.assign(this, props);
103
102
  return this;
104
103
  }
@@ -110,7 +109,7 @@ export class Schema {
110
109
  * @param operation OPERATION to perform (detected automatically)
111
110
  */
112
111
  public setDirty<K extends NonFunctionPropNames<this>>(property: K | number, operation?: OPERATION) {
113
- const metadata: Metadata = this.constructor[Symbol.metadata];
112
+ const metadata: Metadata = (this.constructor as typeof Schema)[Symbol.metadata];
114
113
  this[$changes].change(
115
114
  metadata[metadata[property as string]].index,
116
115
  operation
@@ -119,22 +118,21 @@ export class Schema {
119
118
 
120
119
  clone (): this {
121
120
  const cloned = new ((this as any).constructor);
122
- const metadata: Metadata = this.constructor[Symbol.metadata];
121
+ const metadata: Metadata = (this.constructor as typeof Schema)[Symbol.metadata];
123
122
 
124
123
  //
125
124
  // TODO: clone all properties, not only annotated ones
126
125
  //
127
126
  // for (const field in this) {
128
127
  for (const fieldIndex in metadata) {
129
- // const field = metadata[metadata[fieldIndex]].name;
130
- const field = metadata[fieldIndex as any as number].name;
128
+ const field = metadata[fieldIndex as any as number].name as keyof this;
131
129
 
132
130
  if (
133
131
  typeof (this[field]) === "object" &&
134
- typeof (this[field]?.clone) === "function"
132
+ typeof ((this[field] as any)?.clone) === "function"
135
133
  ) {
136
134
  // deep clone
137
- cloned[field] = this[field].clone();
135
+ cloned[field] = (this[field] as any).clone();
138
136
 
139
137
  } else {
140
138
  // primitive values
@@ -145,11 +143,11 @@ export class Schema {
145
143
  return cloned;
146
144
  }
147
145
 
148
- toJSON () {
149
- const obj: unknown = {};
146
+ toJSON (this: any) {
147
+ const obj: any = {};
150
148
  const metadata = this.constructor[Symbol.metadata];
151
149
  for (const index in metadata) {
152
- const field = metadata[index];
150
+ const field = metadata[index] as MetadataField;
153
151
  const fieldName = field.name;
154
152
  if (!field.deprecated && this[fieldName] !== null && typeof (this[fieldName]) !== "undefined") {
155
153
  obj[fieldName] = (typeof (this[fieldName]['toJSON']) === "function")
@@ -168,14 +166,14 @@ export class Schema {
168
166
  this[$changes].discardAll();
169
167
  }
170
168
 
171
- protected [$getByIndex](index: number) {
172
- const metadata: Metadata = this.constructor[Symbol.metadata];
173
- return this[metadata[index].name];
169
+ [$getByIndex](index: number): any {
170
+ const metadata: Metadata = (this.constructor as typeof Schema)[Symbol.metadata];
171
+ return this[metadata[index].name as keyof this];
174
172
  }
175
173
 
176
- protected [$deleteByIndex](index: number) {
177
- const metadata: Metadata = this.constructor[Symbol.metadata];
178
- this[metadata[index].name] = undefined;
174
+ [$deleteByIndex](index: number): void {
175
+ const metadata: Metadata = (this.constructor as typeof Schema)[Symbol.metadata];
176
+ this[metadata[index].name as keyof this] = undefined;
179
177
  }
180
178
 
181
179
  /**
@@ -185,7 +183,7 @@ export class Schema {
185
183
  * @param showContents display JSON contents of the instance
186
184
  * @returns
187
185
  */
188
- static debugRefIds(ref: Ref, showContents: boolean = false, level: number = 0, decoder?: Decoder, keyPrefix: string = "") {
186
+ static debugRefIds<T extends Schema>(ref: T, showContents: boolean = false, level: number = 0, decoder?: Decoder, keyPrefix: string = "") {
189
187
  const contents = (showContents) ? ` - ${JSON.stringify(ref.toJSON())}` : "";
190
188
  const changeTree: ChangeTree = ref[$changes];
191
189
 
@@ -201,18 +199,18 @@ export class Schema {
201
199
 
202
200
  changeTree.forEachChild((childChangeTree, indexOrKey) => {
203
201
  let key = indexOrKey;
204
- if (typeof indexOrKey === 'number' && ref['$indexes']) {
202
+ if (typeof indexOrKey === 'number' && (ref as any)['$indexes']) {
205
203
  // MapSchema
206
- key = ref['$indexes'].get(indexOrKey) ?? indexOrKey;
204
+ key = (ref as any)['$indexes'].get(indexOrKey) ?? indexOrKey;
207
205
  }
208
- const keyPrefix = (ref['forEach'] !== undefined && key !== undefined) ? `["${key}"]: ` : "";
206
+ const keyPrefix = ((ref as any)['forEach'] !== undefined && key !== undefined) ? `["${key}"]: ` : "";
209
207
  output += this.debugRefIds(childChangeTree.ref, showContents, level + 1, decoder, keyPrefix);
210
208
  });
211
209
 
212
210
  return output;
213
211
  }
214
212
 
215
- static debugRefIdEncodingOrder(ref: Ref, changeSet: ChangeSetName = 'allChanges') {
213
+ static debugRefIdEncodingOrder<T extends Ref>(ref: T, changeSet: ChangeSetName = 'allChanges') {
216
214
  let encodeOrder: number[] = [];
217
215
  let current = ref[$changes].root[changeSet].next;
218
216
  while (current) {
@@ -236,7 +234,7 @@ export class Schema {
236
234
  * @param isEncodeAll Return "full encode" instead of current change set.
237
235
  * @returns
238
236
  */
239
- static debugChanges(instance: Ref, isEncodeAll: boolean = false) {
237
+ static debugChanges<T extends Ref>(instance: T, isEncodeAll: boolean = false) {
240
238
  const changeTree: ChangeTree = instance[$changes];
241
239
 
242
240
  const changeSet = (isEncodeAll) ? changeTree.allChanges : changeTree.changes;
@@ -278,7 +276,7 @@ export class Schema {
278
276
  return output;
279
277
  }
280
278
 
281
- static debugChangesDeep(ref: Ref, changeSetName: "changes" | "allChanges" | "allFilteredChanges" | "filteredChanges" = "changes") {
279
+ static debugChangesDeep<T extends Schema>(ref: T, changeSetName: "changes" | "allChanges" | "allFilteredChanges" | "filteredChanges" = "changes") {
282
280
  let output = "";
283
281
 
284
282
  const rootChangeTree: ChangeTree = ref[$changes];
@@ -290,7 +288,7 @@ export class Schema {
290
288
 
291
289
  // TODO: FIXME: this method is not working as expected
292
290
  for (const [refId, changes] of Object.entries(root[changeSetName])) {
293
- const changeTree = root.changeTrees[refId];
291
+ const changeTree = root.changeTrees[refId as any as number];
294
292
  if (!changeTree) { continue; }
295
293
 
296
294
  let includeChangeTree = false;
@@ -8,8 +8,7 @@ import { TypeDefinition, getType } from "./types/registry";
8
8
  import { OPERATION } from "./encoding/spec";
9
9
  import { TypeContext } from "./types/TypeContext";
10
10
  import { assertInstanceType, assertType } from "./encoding/assert";
11
- import type { Ref } from "./encoder/ChangeTree";
12
- import type { DefinedSchemaType, InferValueType } from "./types/HelperTypes";
11
+ import type { InferValueType, InferSchemaInstanceType, AssignableProps, IsNever } from "./types/HelperTypes";
13
12
  import { CollectionSchema } from "./types/custom/CollectionSchema";
14
13
  import { SetSchema } from "./types/custom/SetSchema";
15
14
 
@@ -48,8 +47,8 @@ export interface TypeOptions {
48
47
 
49
48
  export const DEFAULT_VIEW_TAG = -1;
50
49
 
51
- export function entity(constructor) {
52
- TypeContext.register(constructor);
50
+ export function entity(constructor: any): any {
51
+ TypeContext.register(constructor as typeof Schema);
53
52
  return constructor;
54
53
  }
55
54
 
@@ -366,9 +365,9 @@ export function getPropertyDescriptor(
366
365
  complexTypeKlass: TypeDefinition,
367
366
  ) {
368
367
  return {
369
- get: function () { return this[fieldCached]; },
368
+ get: function (this: Schema) { return this[fieldCached as keyof Schema]; },
370
369
  set: function (this: Schema, value: any) {
371
- const previousValue = this[fieldCached] ?? undefined;
370
+ const previousValue = this[fieldCached as keyof Schema] ?? undefined;
372
371
 
373
372
  // skip if value is the same as cached.
374
373
  if (value === previousValue) { return; }
@@ -388,6 +387,11 @@ export function getPropertyDescriptor(
388
387
  value = new MapSchema(value);
389
388
  }
390
389
 
390
+ // // automaticallty transform Array into SetSchema
391
+ // if (complexTypeKlass.constructor === SetSchema && !(value instanceof SetSchema)) {
392
+ // value = new SetSchema(value);
393
+ // }
394
+
391
395
  value[$childType] = type;
392
396
 
393
397
  } else if (typeof (type) !== "string") {
@@ -404,17 +408,17 @@ export function getPropertyDescriptor(
404
408
  //
405
409
  if (previousValue !== undefined && previousValue[$changes]) {
406
410
  changeTree.root?.remove(previousValue[$changes]);
407
- this.constructor[$track](changeTree, fieldIndex, OPERATION.DELETE_AND_ADD);
411
+ (this.constructor as typeof Schema)[$track](changeTree, fieldIndex, OPERATION.DELETE_AND_ADD);
408
412
 
409
413
  } else {
410
- this.constructor[$track](changeTree, fieldIndex, OPERATION.ADD);
414
+ (this.constructor as typeof Schema)[$track](changeTree, fieldIndex, OPERATION.ADD);
411
415
  }
412
416
 
413
417
  //
414
418
  // call setParent() recursively for this and its child
415
419
  // structures.
416
420
  //
417
- (value as Ref)[$changes]?.setParent(this, changeTree.root, fieldIndex);
421
+ value[$changes]?.setParent(this, changeTree.root, fieldIndex);
418
422
 
419
423
  } else if (previousValue !== undefined) {
420
424
  //
@@ -423,7 +427,7 @@ export function getPropertyDescriptor(
423
427
  this[$changes].delete(fieldIndex);
424
428
  }
425
429
 
426
- this[fieldCached] = value;
430
+ this[fieldCached as keyof Schema] = value;
427
431
  },
428
432
 
429
433
  enumerable: true,
@@ -492,18 +496,67 @@ export function defineTypes(
492
496
  return target;
493
497
  }
494
498
 
495
- export interface SchemaWithExtends<T extends Definition, P extends typeof Schema> extends DefinedSchemaType<T, P> {
496
- extends: <T2 extends Definition>(
497
- fields: T2,
499
+ // Helper type to extract InitProps from initialize method
500
+ // Supports both single object parameter and multiple parameters
501
+ // If no initialize method is specified, use AssignableProps for field initialization
502
+ type ExtractInitProps<T> = T extends { initialize: (props: infer P) => void }
503
+ ? P extends object
504
+ ? P
505
+ : never
506
+ : T extends { initialize: (...args: infer P) => void }
507
+ ? P extends readonly []
508
+ ? never
509
+ : P
510
+ : T extends Definition
511
+ ? AssignableProps<InferSchemaInstanceType<T>>
512
+ : never;
513
+
514
+ // Helper type to determine if InitProps should be required
515
+ type IsInitPropsRequired<T> = T extends { initialize: (props: any) => void }
516
+ ? true
517
+ : T extends { initialize: (...args: any[]) => void }
518
+ ? true
519
+ : false;
520
+
521
+ export interface SchemaWithExtends<T extends Definition, P extends typeof Schema, > {
522
+ extends: <T2 extends Definition = Definition>(
523
+ fields: T2 & ThisType<InferSchemaInstanceType<T & T2>>,
498
524
  name?: string
499
- ) => SchemaWithExtends<T & T2, typeof this>;
525
+ ) => SchemaWithExtendsConstructor<T & T2, ExtractInitProps<T2>, P>;
526
+ }
527
+
528
+ /**
529
+ * Get the type of the schema defined via `schema({...})` method.
530
+ *
531
+ * @example
532
+ * const Entity = schema({
533
+ * x: "number",
534
+ * y: "number",
535
+ * });
536
+ * type Entity = SchemaType<typeof Entity>;
537
+ */
538
+ export type SchemaType<T extends {'~type': any}> = T['~type'];
539
+
540
+ export interface SchemaWithExtendsConstructor<
541
+ T extends Definition,
542
+ InitProps,
543
+ P extends typeof Schema
544
+ > extends SchemaWithExtends<T, P> {
545
+ '~type': InferSchemaInstanceType<T>;
546
+ new (...args: [InitProps] extends [never] ? [] : InitProps extends readonly any[] ? InitProps : IsInitPropsRequired<T> extends true ? [InitProps] : [InitProps?]): InferSchemaInstanceType<T> & InstanceType<P>;
547
+ prototype: InferSchemaInstanceType<T> & InstanceType<P> & {
548
+ initialize(...args: [InitProps] extends [never] ? [] : InitProps extends readonly any[] ? InitProps : [InitProps]): void;
549
+ };
500
550
  }
501
551
 
502
- export function schema<T extends Definition, P extends typeof Schema = typeof Schema>(
503
- fieldsAndMethods: T,
552
+ export function schema<
553
+ T extends Record<string, DefinitionType>,
554
+ P extends typeof Schema = typeof Schema
555
+ >(
556
+ fieldsAndMethods: T & ThisType<InferSchemaInstanceType<T>>,
504
557
  name?: string,
505
558
  inherits: P = Schema as P
506
- ): SchemaWithExtends<T, P> {
559
+ ): SchemaWithExtendsConstructor<T, ExtractInitProps<T>, P> {
507
560
  const fields: any = {};
508
561
  const methods: any = {};
509
562
 
@@ -511,7 +564,7 @@ export function schema<T extends Definition, P extends typeof Schema = typeof Sc
511
564
  const viewTagFields: any = {};
512
565
 
513
566
  for (let fieldName in fieldsAndMethods) {
514
- const value = fieldsAndMethods[fieldName] as DefinitionType;
567
+ const value: any = fieldsAndMethods[fieldName] as DefinitionType;
515
568
  if (typeof (value) === "object") {
516
569
  if (value['view'] !== undefined) {
517
570
  viewTagFields[fieldName] = (typeof (value['view']) === "boolean")
@@ -565,39 +618,49 @@ export function schema<T extends Definition, P extends typeof Schema = typeof Sc
565
618
 
566
619
  const getDefaultValues = () => {
567
620
  const defaults: any = {};
621
+
622
+ // use current class default values
568
623
  for (const fieldName in defaultValues) {
569
624
  const defaultValue = defaultValues[fieldName];
570
- // If the default value has a clone method, use it to get a fresh instance
571
625
  if (defaultValue && typeof defaultValue.clone === 'function') {
626
+ // complex, cloneable values, e.g. Schema, ArraySchema, MapSchema, CollectionSchema, SetSchema
572
627
  defaults[fieldName] = defaultValue.clone();
573
628
  } else {
574
- // Otherwise, use the value as-is (for primitives and non-cloneable objects)
629
+ // primitives and non-cloneable values
575
630
  defaults[fieldName] = defaultValue;
576
631
  }
577
632
  }
578
633
  return defaults;
579
634
  };
580
635
 
581
- const klass = Metadata.setFields<any>(class extends inherits {
582
- constructor (...args: any[]) {
583
- args[0] = Object.assign({}, getDefaultValues(), args[0]);
584
- super(...args);
636
+ /** @codegen-ignore */
637
+ const klass = Metadata.setFields<any>(class extends (inherits as any) {
638
+ constructor(...args: any[]) {
639
+ super(Object.assign({}, getDefaultValues(), args[0] || {}));
640
+
641
+ // call initialize method
642
+ if (methods.initialize && typeof methods.initialize === 'function') {
643
+ methods.initialize.apply(this, args);
644
+ }
585
645
  }
586
- }, fields) as SchemaWithExtends<T, P>;
646
+ }, fields) as SchemaWithExtendsConstructor<T, ExtractInitProps<T>, P>;
647
+
648
+ // Store the getDefaultValues function on the class for inheritance
649
+ (klass as any)._getDefaultValues = getDefaultValues;
650
+
651
+ // Add methods to the prototype
652
+ Object.assign(klass.prototype, methods);
587
653
 
588
654
  for (let fieldName in viewTagFields) {
589
655
  view(viewTagFields[fieldName])(klass.prototype, fieldName);
590
656
  }
591
657
 
592
- for (let methodName in methods) {
593
- klass.prototype[methodName] = methods[methodName];
594
- }
595
-
596
658
  if (name) {
597
659
  Object.defineProperty(klass, "name", { value: name });
598
660
  }
599
661
 
600
- klass.extends = (fields, name) => schema(fields, name, klass);
662
+ klass.extends = <T2 extends Definition = Definition>(fields: T2, name?: string) =>
663
+ schema<T2>(fields, name, klass as any) as SchemaWithExtendsConstructor<T & T2, ExtractInitProps<T2>, P>;
601
664
 
602
665
  return klass;
603
666
  }
@@ -57,7 +57,7 @@ export function generate(targetId: string, options: GenerateOptions) {
57
57
 
58
58
  function recursiveFiles(dir: string): string[] {
59
59
  const files = fs.readdirSync(dir, { withFileTypes: true });
60
- let collect = [];
60
+ let collect: string[] = [];
61
61
  files.forEach(file => {
62
62
  const filename = path.resolve(dir, file.name);
63
63
  file.isDirectory() ? collect.push(...recursiveFiles(filename)) : collect.push(filename);
@@ -2,12 +2,12 @@
2
2
  * @author Ethan Davis
3
3
  * https://github.com/ethanent/gar
4
4
  */
5
- export default (sargs): any => {
6
- let props = {}
7
- let lones = []
5
+ export default (sargs: string[]): any => {
6
+ let props: any = {}
7
+ let lones: any = []
8
8
 
9
- const convertIfApplicable = (value) => (isNaN(value) ? (value.toString().toLowerCase() === 'true' ? true : (value.toString().toLowerCase() === 'false' ? false : value)) : Number(value))
10
- const removeStartHyphens = (value) => value.replace(/^\-+/g, '')
9
+ const convertIfApplicable = (value: any) => (isNaN(value) ? (value.toString().toLowerCase() === 'true' ? true : (value.toString().toLowerCase() === 'false' ? false : value)) : Number(value))
10
+ const removeStartHyphens = (value: string) => value.replace(/^\-+/g, '')
11
11
 
12
12
  for (let i = 0; i < sargs.length; i++) {
13
13
  const equalsIndex = sargs[i].indexOf('=')
@@ -1,7 +1,7 @@
1
1
  import argv from "./argv";
2
2
  import { generate } from "./api";
3
3
 
4
- const supportedTargets = {
4
+ const supportedTargets: Record<string, string> = {
5
5
  csharp: 'generate for C#/Unity',
6
6
  cpp: 'generate for C++',
7
7
  haxe: 'generate for Haxe',
@@ -1,7 +1,7 @@
1
1
  import { Class, Property, File, getCommentHeader, getInheritanceTree, Context } from "../types";
2
2
  import { GenerateOptions } from "../api";
3
3
 
4
- const typeMaps = {
4
+ const typeMaps: { [key: string]: string } = {
5
5
  "string": "string",
6
6
  "number": "varint_t",
7
7
  "boolean": "bool",
@@ -17,7 +17,7 @@ const typeMaps = {
17
17
  "float64": "float64_t",
18
18
  }
19
19
 
20
- const typeInitializer = {
20
+ const typeInitializer: { [key: string]: string } = {
21
21
  "string": '""',
22
22
  "number": "0",
23
23
  "boolean": "false",
@@ -37,11 +37,12 @@ const typeInitializer = {
37
37
  * C++ Code Generator
38
38
  */
39
39
 
40
- const capitalize = (s) => {
40
+ const capitalize = (s: string) => {
41
41
  if (typeof s !== 'string') return ''
42
42
  return s.charAt(0).toUpperCase() + s.slice(1);
43
43
  }
44
- const distinct = (value, index, self) => self.indexOf(value) === index;
44
+ const distinct = (value: string, index: number, self: string[]) =>
45
+ self.indexOf(value) === index;
45
46
 
46
47
  export function generate (context: Context, options: GenerateOptions): File[] {
47
48
  return context.classes.map(klass => ({
@@ -9,7 +9,7 @@ import {
9
9
  import { GenerateOptions } from "../api";
10
10
  import { Context } from "../types";
11
11
 
12
- const typeMaps = {
12
+ const typeMaps: { [key: string]: string } = {
13
13
  "string": "string",
14
14
  "number": "float",
15
15
  "boolean": "bool",
@@ -28,7 +28,7 @@ const typeMaps = {
28
28
  /**
29
29
  * C# Code Generator
30
30
  */
31
- const capitalize = (s) => {
31
+ const capitalize = (s: string) => {
32
32
  if (typeof s !== 'string') return ''
33
33
  return s.charAt(0).toUpperCase() + s.slice(1);
34
34
  }
@@ -1,7 +1,7 @@
1
1
  import { Class, Property, File, getCommentHeader, Context } from "../types";
2
2
  import { GenerateOptions } from "../api";
3
3
 
4
- const typeMaps = {
4
+ const typeMaps: { [key: string]: string } = {
5
5
  "string": "String",
6
6
  "number": "Dynamic",
7
7
  "boolean": "Bool",
@@ -17,7 +17,7 @@ const typeMaps = {
17
17
  "float64": "Float",
18
18
  }
19
19
 
20
- const typeInitializer = {
20
+ const typeInitializer: { [key: string]: string } = {
21
21
  "string": '""',
22
22
  "number": "0",
23
23
  "boolean": "false",
@@ -1,7 +1,7 @@
1
1
  import { Class, Property, File, getCommentHeader, Context } from "../types";
2
2
  import { GenerateOptions } from "../api";
3
3
 
4
- const typeMaps = {
4
+ const typeMaps: { [key: string]: string } = {
5
5
  "string": "String",
6
6
  "number": "float",
7
7
  "boolean": "boolean",
@@ -17,7 +17,7 @@ const typeMaps = {
17
17
  "float64": "double",
18
18
  }
19
19
 
20
- const typeInitializer = {
20
+ const typeInitializer: { [key: string]: string } = {
21
21
  "string": '""',
22
22
  "number": "0",
23
23
  "boolean": "false",