@colyseus/schema 1.1.0-alpha.0 → 2.0.0

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 (103) hide show
  1. package/README.md +1 -4
  2. package/build/cjs/index.js +1194 -1001
  3. package/build/cjs/index.js.map +1 -1
  4. package/build/esm/index.mjs +350 -311
  5. package/build/esm/index.mjs.map +1 -1
  6. package/build/umd/index.js +371 -335
  7. package/lib/Reflection.d.ts +21 -0
  8. package/lib/Reflection.js +198 -0
  9. package/lib/Reflection.js.map +1 -0
  10. package/lib/Schema.d.ts +66 -0
  11. package/lib/Schema.js +853 -0
  12. package/lib/Schema.js.map +1 -0
  13. package/lib/annotations.d.ts +96 -0
  14. package/lib/annotations.js +316 -0
  15. package/lib/annotations.js.map +1 -0
  16. package/lib/changes/ChangeTree.d.ts +53 -0
  17. package/lib/changes/ChangeTree.js +209 -0
  18. package/lib/changes/ChangeTree.js.map +1 -0
  19. package/lib/changes/ReferenceTracker.d.ts +14 -0
  20. package/lib/changes/ReferenceTracker.js +77 -0
  21. package/lib/changes/ReferenceTracker.js.map +1 -0
  22. package/lib/codegen/api.d.ts +7 -0
  23. package/lib/codegen/api.js +36 -0
  24. package/lib/codegen/api.js.map +1 -0
  25. package/lib/codegen/argv.d.ts +6 -0
  26. package/lib/codegen/argv.js +41 -0
  27. package/lib/codegen/argv.js.map +1 -0
  28. package/lib/codegen/cli.d.ts +1 -0
  29. package/lib/codegen/cli.js +49 -0
  30. package/lib/codegen/cli.js.map +1 -0
  31. package/lib/codegen/languages/cpp.d.ts +3 -0
  32. package/lib/codegen/languages/cpp.js +213 -0
  33. package/lib/codegen/languages/cpp.js.map +1 -0
  34. package/lib/codegen/languages/csharp.d.ts +4 -0
  35. package/lib/codegen/languages/csharp.js +130 -0
  36. package/lib/codegen/languages/csharp.js.map +1 -0
  37. package/lib/codegen/languages/haxe.d.ts +3 -0
  38. package/lib/codegen/languages/haxe.js +93 -0
  39. package/lib/codegen/languages/haxe.js.map +1 -0
  40. package/lib/codegen/languages/java.d.ts +6 -0
  41. package/lib/codegen/languages/java.js +92 -0
  42. package/lib/codegen/languages/java.js.map +1 -0
  43. package/lib/codegen/languages/js.d.ts +3 -0
  44. package/lib/codegen/languages/js.js +89 -0
  45. package/lib/codegen/languages/js.js.map +1 -0
  46. package/lib/codegen/languages/lua.d.ts +3 -0
  47. package/lib/codegen/languages/lua.js +97 -0
  48. package/lib/codegen/languages/lua.js.map +1 -0
  49. package/lib/codegen/languages/ts.d.ts +3 -0
  50. package/lib/codegen/languages/ts.js +125 -0
  51. package/lib/codegen/languages/ts.js.map +1 -0
  52. package/lib/codegen/parser.d.ts +5 -0
  53. package/lib/codegen/parser.js +196 -0
  54. package/lib/codegen/parser.js.map +1 -0
  55. package/lib/codegen/types.d.ts +44 -0
  56. package/lib/codegen/types.js +122 -0
  57. package/lib/codegen/types.js.map +1 -0
  58. package/lib/encoding/decode.d.ts +48 -0
  59. package/lib/encoding/decode.js +267 -0
  60. package/lib/encoding/decode.js.map +1 -0
  61. package/lib/encoding/encode.d.ts +38 -0
  62. package/lib/encoding/encode.js +281 -0
  63. package/lib/encoding/encode.js.map +1 -0
  64. package/lib/events/EventEmitter.d.ts +13 -0
  65. package/lib/events/EventEmitter.js +62 -0
  66. package/lib/events/EventEmitter.js.map +1 -0
  67. package/lib/filters/index.d.ts +8 -0
  68. package/lib/filters/index.js +25 -0
  69. package/lib/filters/index.js.map +1 -0
  70. package/lib/index.d.ts +19 -0
  71. package/lib/index.js +46 -0
  72. package/lib/index.js.map +1 -0
  73. package/lib/spec.d.ts +13 -0
  74. package/lib/spec.js +42 -0
  75. package/lib/spec.js.map +1 -0
  76. package/lib/types/ArraySchema.d.ts +230 -0
  77. package/lib/types/ArraySchema.js +559 -0
  78. package/lib/types/ArraySchema.js.map +1 -0
  79. package/lib/types/CollectionSchema.d.ts +35 -0
  80. package/lib/types/CollectionSchema.js +158 -0
  81. package/lib/types/CollectionSchema.js.map +1 -0
  82. package/lib/types/HelperTypes.d.ts +28 -0
  83. package/lib/types/HelperTypes.js +3 -0
  84. package/lib/types/HelperTypes.js.map +1 -0
  85. package/lib/types/MapSchema.d.ts +37 -0
  86. package/lib/types/MapSchema.js +214 -0
  87. package/lib/types/MapSchema.js.map +1 -0
  88. package/lib/types/SetSchema.d.ts +32 -0
  89. package/lib/types/SetSchema.js +171 -0
  90. package/lib/types/SetSchema.js.map +1 -0
  91. package/lib/types/index.d.ts +6 -0
  92. package/lib/types/index.js +13 -0
  93. package/lib/types/index.js.map +1 -0
  94. package/lib/types/typeRegistry.d.ts +5 -0
  95. package/lib/types/typeRegistry.js +13 -0
  96. package/lib/types/typeRegistry.js.map +1 -0
  97. package/lib/types/utils.d.ts +9 -0
  98. package/lib/types/utils.js +50 -0
  99. package/lib/types/utils.js.map +1 -0
  100. package/lib/utils.d.ts +2 -0
  101. package/lib/utils.js +26 -0
  102. package/lib/utils.js.map +1 -0
  103. package/package.json +4 -8
@@ -0,0 +1,53 @@
1
+ import { OPERATION } from "../spec";
2
+ import { Schema } from "../Schema";
3
+ import { FilterChildrenCallback } from "../annotations";
4
+ import { MapSchema } from "../types/MapSchema";
5
+ import { ArraySchema } from "../types/ArraySchema";
6
+ import { CollectionSchema } from "../types/CollectionSchema";
7
+ import { SetSchema } from "../types/SetSchema";
8
+ import { ReferenceTracker } from "./ReferenceTracker";
9
+ export declare type Ref = Schema | ArraySchema | MapSchema | CollectionSchema | SetSchema;
10
+ export interface ChangeOperation {
11
+ op: OPERATION;
12
+ index: number;
13
+ }
14
+ export interface FieldCache {
15
+ beginIndex: number;
16
+ endIndex: number;
17
+ }
18
+ export declare class ChangeTree {
19
+ ref: Ref;
20
+ refId: number;
21
+ root?: ReferenceTracker;
22
+ parent?: Ref;
23
+ parentIndex?: number;
24
+ indexes: {
25
+ [index: string]: any;
26
+ };
27
+ changed: boolean;
28
+ changes: Map<number, ChangeOperation>;
29
+ allChanges: Set<number>;
30
+ caches: {
31
+ [field: number]: number[];
32
+ };
33
+ currentCustomOperation: number;
34
+ constructor(ref: Ref, parent?: Ref, root?: ReferenceTracker);
35
+ setParent(parent: Ref, root?: ReferenceTracker, parentIndex?: number): void;
36
+ operation(op: ChangeOperation): void;
37
+ change(fieldName: string | number, operation?: OPERATION): void;
38
+ touch(fieldName: string | number): void;
39
+ touchParents(): void;
40
+ getType(index?: number): any;
41
+ getChildrenFilter(): FilterChildrenCallback;
42
+ getValue(index: number): any;
43
+ delete(fieldName: string | number): void;
44
+ discard(changed?: boolean, discardAll?: boolean): void;
45
+ /**
46
+ * Recursively discard all changes from this, and child structures.
47
+ */
48
+ discardAll(): void;
49
+ cache(field: number, cachedBytes: number[]): void;
50
+ clone(): ChangeTree;
51
+ ensureRefId(): void;
52
+ protected assertValidIndex(index: number, fieldName: string | number): void;
53
+ }
@@ -0,0 +1,209 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ChangeTree = void 0;
4
+ var spec_1 = require("../spec");
5
+ var Schema_1 = require("../Schema");
6
+ var ChangeTree = /** @class */ (function () {
7
+ function ChangeTree(ref, parent, root) {
8
+ this.changed = false;
9
+ this.changes = new Map();
10
+ this.allChanges = new Set();
11
+ // cached indexes for filtering
12
+ this.caches = {};
13
+ this.currentCustomOperation = 0;
14
+ this.ref = ref;
15
+ this.setParent(parent, root);
16
+ }
17
+ ChangeTree.prototype.setParent = function (parent, root, parentIndex) {
18
+ var _this = this;
19
+ if (!this.indexes) {
20
+ this.indexes = (this.ref instanceof Schema_1.Schema)
21
+ ? this.ref['_definition'].indexes
22
+ : {};
23
+ }
24
+ this.parent = parent;
25
+ this.parentIndex = parentIndex;
26
+ // avoid setting parents with empty `root`
27
+ if (!root) {
28
+ return;
29
+ }
30
+ this.root = root;
31
+ //
32
+ // assign same parent on child structures
33
+ //
34
+ if (this.ref instanceof Schema_1.Schema) {
35
+ var definition = this.ref['_definition'];
36
+ for (var field in definition.schema) {
37
+ var value = this.ref[field];
38
+ if (value && value['$changes']) {
39
+ var parentIndex_1 = definition.indexes[field];
40
+ value['$changes'].setParent(this.ref, root, parentIndex_1);
41
+ }
42
+ }
43
+ }
44
+ else if (typeof (this.ref) === "object") {
45
+ this.ref.forEach(function (value, key) {
46
+ if (value instanceof Schema_1.Schema) {
47
+ var changeTreee = value['$changes'];
48
+ var parentIndex_2 = _this.ref['$changes'].indexes[key];
49
+ changeTreee.setParent(_this.ref, _this.root, parentIndex_2);
50
+ }
51
+ });
52
+ }
53
+ };
54
+ ChangeTree.prototype.operation = function (op) {
55
+ this.changes.set(--this.currentCustomOperation, op);
56
+ };
57
+ ChangeTree.prototype.change = function (fieldName, operation) {
58
+ if (operation === void 0) { operation = spec_1.OPERATION.ADD; }
59
+ var index = (typeof (fieldName) === "number")
60
+ ? fieldName
61
+ : this.indexes[fieldName];
62
+ this.assertValidIndex(index, fieldName);
63
+ var previousChange = this.changes.get(index);
64
+ if (!previousChange ||
65
+ previousChange.op === spec_1.OPERATION.DELETE ||
66
+ previousChange.op === spec_1.OPERATION.TOUCH // (mazmorra.io's BattleAction issue)
67
+ ) {
68
+ this.changes.set(index, {
69
+ op: (!previousChange)
70
+ ? operation
71
+ : (previousChange.op === spec_1.OPERATION.DELETE)
72
+ ? spec_1.OPERATION.DELETE_AND_ADD
73
+ : operation,
74
+ // : OPERATION.REPLACE,
75
+ index: index
76
+ });
77
+ }
78
+ this.allChanges.add(index);
79
+ this.changed = true;
80
+ this.touchParents();
81
+ };
82
+ ChangeTree.prototype.touch = function (fieldName) {
83
+ var index = (typeof (fieldName) === "number")
84
+ ? fieldName
85
+ : this.indexes[fieldName];
86
+ this.assertValidIndex(index, fieldName);
87
+ if (!this.changes.has(index)) {
88
+ this.changes.set(index, { op: spec_1.OPERATION.TOUCH, index: index });
89
+ }
90
+ this.allChanges.add(index);
91
+ // ensure touch is placed until the $root is found.
92
+ this.touchParents();
93
+ };
94
+ ChangeTree.prototype.touchParents = function () {
95
+ if (this.parent) {
96
+ this.parent['$changes'].touch(this.parentIndex);
97
+ }
98
+ };
99
+ ChangeTree.prototype.getType = function (index) {
100
+ if (this.ref['_definition']) {
101
+ var definition = this.ref['_definition'];
102
+ return definition.schema[definition.fieldsByIndex[index]];
103
+ }
104
+ else {
105
+ var definition = this.parent['_definition'];
106
+ var parentType = definition.schema[definition.fieldsByIndex[this.parentIndex]];
107
+ //
108
+ // Get the child type from parent structure.
109
+ // - ["string"] => "string"
110
+ // - { map: "string" } => "string"
111
+ // - { set: "string" } => "string"
112
+ //
113
+ return Object.values(parentType)[0];
114
+ }
115
+ };
116
+ ChangeTree.prototype.getChildrenFilter = function () {
117
+ var childFilters = this.parent['_definition'].childFilters;
118
+ return childFilters && childFilters[this.parentIndex];
119
+ };
120
+ //
121
+ // used during `.encode()`
122
+ //
123
+ ChangeTree.prototype.getValue = function (index) {
124
+ return this.ref['getByIndex'](index);
125
+ };
126
+ ChangeTree.prototype.delete = function (fieldName) {
127
+ var index = (typeof (fieldName) === "number")
128
+ ? fieldName
129
+ : this.indexes[fieldName];
130
+ if (index === undefined) {
131
+ console.warn("@colyseus/schema " + this.ref.constructor.name + ": trying to delete non-existing index: " + fieldName + " (" + index + ")");
132
+ return;
133
+ }
134
+ var previousValue = this.getValue(index);
135
+ // console.log("$changes.delete =>", { fieldName, index, previousValue });
136
+ this.changes.set(index, { op: spec_1.OPERATION.DELETE, index: index });
137
+ this.allChanges.delete(index);
138
+ // delete cache
139
+ delete this.caches[index];
140
+ // remove `root` reference
141
+ if (previousValue && previousValue['$changes']) {
142
+ previousValue['$changes'].parent = undefined;
143
+ }
144
+ this.changed = true;
145
+ this.touchParents();
146
+ };
147
+ ChangeTree.prototype.discard = function (changed, discardAll) {
148
+ var _this = this;
149
+ if (changed === void 0) { changed = false; }
150
+ if (discardAll === void 0) { discardAll = false; }
151
+ //
152
+ // Map, Array, etc:
153
+ // Remove cached key to ensure ADD operations is unsed instead of
154
+ // REPLACE in case same key is used on next patches.
155
+ //
156
+ // TODO: refactor this. this is not relevant for Collection and Set.
157
+ //
158
+ if (!(this.ref instanceof Schema_1.Schema)) {
159
+ this.changes.forEach(function (change) {
160
+ if (change.op === spec_1.OPERATION.DELETE) {
161
+ var index = _this.ref['getIndex'](change.index);
162
+ delete _this.indexes[index];
163
+ }
164
+ });
165
+ }
166
+ this.changes.clear();
167
+ this.changed = changed;
168
+ if (discardAll) {
169
+ this.allChanges.clear();
170
+ }
171
+ // re-set `currentCustomOperation`
172
+ this.currentCustomOperation = 0;
173
+ };
174
+ /**
175
+ * Recursively discard all changes from this, and child structures.
176
+ */
177
+ ChangeTree.prototype.discardAll = function () {
178
+ var _this = this;
179
+ this.changes.forEach(function (change) {
180
+ var value = _this.getValue(change.index);
181
+ if (value && value['$changes']) {
182
+ value['$changes'].discardAll();
183
+ }
184
+ });
185
+ this.discard();
186
+ };
187
+ // cache(field: number, beginIndex: number, endIndex: number) {
188
+ ChangeTree.prototype.cache = function (field, cachedBytes) {
189
+ this.caches[field] = cachedBytes;
190
+ };
191
+ ChangeTree.prototype.clone = function () {
192
+ return new ChangeTree(this.ref, this.parent, this.root);
193
+ };
194
+ ChangeTree.prototype.ensureRefId = function () {
195
+ // skip if refId is already set.
196
+ if (this.refId !== undefined) {
197
+ return;
198
+ }
199
+ this.refId = this.root.getNextUniqueId();
200
+ };
201
+ ChangeTree.prototype.assertValidIndex = function (index, fieldName) {
202
+ if (index === undefined) {
203
+ throw new Error("ChangeTree: missing index for field \"" + fieldName + "\"");
204
+ }
205
+ };
206
+ return ChangeTree;
207
+ }());
208
+ exports.ChangeTree = ChangeTree;
209
+ //# sourceMappingURL=ChangeTree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChangeTree.js","sourceRoot":"","sources":["../../src/changes/ChangeTree.ts"],"names":[],"mappings":"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","sourcesContent":["import { OPERATION } from \"../spec\";\nimport { Schema } from \"../Schema\";\nimport { SchemaDefinition, FilterChildrenCallback } from \"../annotations\";\n\nimport { MapSchema } from \"../types/MapSchema\";\nimport { ArraySchema } from \"../types/ArraySchema\";\nimport { CollectionSchema } from \"../types/CollectionSchema\";\nimport { SetSchema } from \"../types/SetSchema\";\nimport { ReferenceTracker } from \"./ReferenceTracker\";\n\nexport type Ref = Schema\n | ArraySchema\n | MapSchema\n | CollectionSchema\n | SetSchema;\n\nexport interface ChangeOperation {\n op: OPERATION,\n index: number,\n}\n\n//\n// FieldCache is used for @filter()\n//\nexport interface FieldCache {\n beginIndex: number;\n endIndex: number;\n}\n\n\nexport class ChangeTree {\n ref: Ref;\n refId: number;\n\n root?: ReferenceTracker;\n\n parent?: Ref;\n parentIndex?: number;\n\n indexes: {[index: string]: any};\n\n changed: boolean = false;\n changes = new Map<number, ChangeOperation>();\n allChanges = new Set<number>();\n\n // cached indexes for filtering\n caches: {[field: number]: number[]} = {};\n\n currentCustomOperation: number = 0;\n\n constructor(ref: Ref, parent?: Ref, root?: ReferenceTracker) {\n this.ref = ref;\n this.setParent(parent, root);\n }\n\n setParent(\n parent: Ref,\n root?: ReferenceTracker,\n parentIndex?: number,\n ) {\n if (!this.indexes) {\n this.indexes = (this.ref instanceof Schema)\n ? this.ref['_definition'].indexes\n : {};\n }\n\n this.parent = parent;\n this.parentIndex = parentIndex;\n\n // avoid setting parents with empty `root`\n if (!root) { return; }\n this.root = root;\n\n //\n // assign same parent on child structures\n //\n if (this.ref instanceof Schema) {\n const definition: SchemaDefinition = this.ref['_definition'];\n\n for (let field in definition.schema) {\n const value = this.ref[field];\n\n if (value && value['$changes']) {\n const parentIndex = definition.indexes[field];\n\n (value['$changes'] as ChangeTree).setParent(\n this.ref,\n root,\n parentIndex,\n );\n }\n }\n\n } else if (typeof (this.ref) === \"object\") {\n this.ref.forEach((value, key) => {\n if (value instanceof Schema) {\n const changeTreee = value['$changes'];\n const parentIndex = this.ref['$changes'].indexes[key];\n\n changeTreee.setParent(\n this.ref,\n this.root,\n parentIndex,\n );\n }\n });\n }\n }\n\n operation(op: ChangeOperation) {\n this.changes.set(--this.currentCustomOperation, op);\n }\n\n change(fieldName: string | number, operation: OPERATION = OPERATION.ADD) {\n const index = (typeof (fieldName) === \"number\")\n ? fieldName\n : this.indexes[fieldName];\n\n this.assertValidIndex(index, fieldName);\n\n const previousChange = this.changes.get(index);\n\n if (\n !previousChange ||\n previousChange.op === OPERATION.DELETE ||\n previousChange.op === OPERATION.TOUCH // (mazmorra.io's BattleAction issue)\n ) {\n this.changes.set(index, {\n op: (!previousChange)\n ? operation\n : (previousChange.op === OPERATION.DELETE)\n ? OPERATION.DELETE_AND_ADD\n : operation,\n // : OPERATION.REPLACE,\n index\n });\n }\n\n this.allChanges.add(index);\n\n this.changed = true;\n this.touchParents();\n }\n\n touch(fieldName: string | number) {\n const index = (typeof (fieldName) === \"number\")\n ? fieldName\n : this.indexes[fieldName];\n\n this.assertValidIndex(index, fieldName);\n\n if (!this.changes.has(index)) {\n this.changes.set(index, { op: OPERATION.TOUCH, index });\n }\n\n this.allChanges.add(index);\n\n // ensure touch is placed until the $root is found.\n this.touchParents();\n }\n\n touchParents() {\n if (this.parent) {\n (this.parent['$changes'] as ChangeTree).touch(this.parentIndex);\n }\n }\n\n getType(index?: number) {\n if (this.ref['_definition']) {\n const definition = (this.ref as Schema)['_definition'];\n return definition.schema[ definition.fieldsByIndex[index] ];\n\n } else {\n const definition = (this.parent as Schema)['_definition'];\n const parentType = definition.schema[ definition.fieldsByIndex[this.parentIndex] ];\n\n //\n // Get the child type from parent structure.\n // - [\"string\"] => \"string\"\n // - { map: \"string\" } => \"string\"\n // - { set: \"string\" } => \"string\"\n //\n return Object.values(parentType)[0];\n }\n }\n\n getChildrenFilter(): FilterChildrenCallback {\n const childFilters = (this.parent as Schema)['_definition'].childFilters;\n return childFilters && childFilters[this.parentIndex];\n }\n\n //\n // used during `.encode()`\n //\n getValue(index: number) {\n return this.ref['getByIndex'](index);\n }\n\n delete(fieldName: string | number) {\n const index = (typeof (fieldName) === \"number\")\n ? fieldName\n : this.indexes[fieldName];\n\n if (index === undefined) {\n console.warn(`@colyseus/schema ${this.ref.constructor.name}: trying to delete non-existing index: ${fieldName} (${index})`);\n return;\n }\n\n const previousValue = this.getValue(index);\n // console.log(\"$changes.delete =>\", { fieldName, index, previousValue });\n\n this.changes.set(index, { op: OPERATION.DELETE, index });\n\n this.allChanges.delete(index);\n\n // delete cache\n delete this.caches[index];\n\n // remove `root` reference\n if (previousValue && previousValue['$changes']) {\n previousValue['$changes'].parent = undefined;\n }\n\n this.changed = true;\n this.touchParents();\n }\n\n discard(changed: boolean = false, discardAll: boolean = false) {\n //\n // Map, Array, etc:\n // Remove cached key to ensure ADD operations is unsed instead of\n // REPLACE in case same key is used on next patches.\n //\n // TODO: refactor this. this is not relevant for Collection and Set.\n //\n if (!(this.ref instanceof Schema)) {\n this.changes.forEach((change) => {\n if (change.op === OPERATION.DELETE) {\n const index = this.ref['getIndex'](change.index)\n delete this.indexes[index];\n }\n });\n }\n\n this.changes.clear();\n this.changed = changed;\n\n if (discardAll) {\n this.allChanges.clear();\n }\n\n // re-set `currentCustomOperation`\n this.currentCustomOperation = 0;\n }\n\n /**\n * Recursively discard all changes from this, and child structures.\n */\n discardAll() {\n this.changes.forEach((change) => {\n const value = this.getValue(change.index);\n\n if (value && value['$changes']) {\n value['$changes'].discardAll();\n }\n });\n\n this.discard();\n }\n\n // cache(field: number, beginIndex: number, endIndex: number) {\n cache(field: number, cachedBytes: number[]) {\n this.caches[field] = cachedBytes;\n }\n\n clone() {\n return new ChangeTree(this.ref, this.parent, this.root);\n }\n\n ensureRefId() {\n // skip if refId is already set.\n if (this.refId !== undefined) {\n return;\n }\n\n this.refId = this.root.getNextUniqueId();\n }\n\n protected assertValidIndex(index: number, fieldName: string | number) {\n if (index === undefined) {\n throw new Error(`ChangeTree: missing index for field \"${fieldName}\"`);\n }\n }\n\n}\n"]}
@@ -0,0 +1,14 @@
1
+ import { Ref } from "./ChangeTree";
2
+ export declare class ReferenceTracker {
3
+ refs: Map<number, Ref>;
4
+ refCounts: {
5
+ [refId: number]: number;
6
+ };
7
+ deletedRefs: Set<number>;
8
+ protected nextUniqueId: number;
9
+ getNextUniqueId(): number;
10
+ addRef(refId: number, ref: Ref, incrementCount?: boolean): void;
11
+ removeRef(refId: any): void;
12
+ clearRefs(): void;
13
+ garbageCollectDeletedRefs(): void;
14
+ }
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ReferenceTracker = void 0;
4
+ var Schema_1 = require("../Schema");
5
+ var ReferenceTracker = /** @class */ (function () {
6
+ function ReferenceTracker() {
7
+ //
8
+ // Relation of refId => Schema structure
9
+ // For direct access of structures during decoding time.
10
+ //
11
+ this.refs = new Map();
12
+ this.refCounts = {};
13
+ this.deletedRefs = new Set();
14
+ this.nextUniqueId = 0;
15
+ }
16
+ ReferenceTracker.prototype.getNextUniqueId = function () {
17
+ return this.nextUniqueId++;
18
+ };
19
+ // for decoding
20
+ ReferenceTracker.prototype.addRef = function (refId, ref, incrementCount) {
21
+ if (incrementCount === void 0) { incrementCount = true; }
22
+ this.refs.set(refId, ref);
23
+ if (incrementCount) {
24
+ this.refCounts[refId] = (this.refCounts[refId] || 0) + 1;
25
+ }
26
+ };
27
+ // for decoding
28
+ ReferenceTracker.prototype.removeRef = function (refId) {
29
+ this.refCounts[refId] = this.refCounts[refId] - 1;
30
+ this.deletedRefs.add(refId);
31
+ };
32
+ ReferenceTracker.prototype.clearRefs = function () {
33
+ this.refs.clear();
34
+ this.deletedRefs.clear();
35
+ this.refCounts = {};
36
+ };
37
+ // for decoding
38
+ ReferenceTracker.prototype.garbageCollectDeletedRefs = function () {
39
+ var _this = this;
40
+ this.deletedRefs.forEach(function (refId) {
41
+ //
42
+ // Skip active references.
43
+ //
44
+ if (_this.refCounts[refId] > 0) {
45
+ return;
46
+ }
47
+ var ref = _this.refs.get(refId);
48
+ //
49
+ // Ensure child schema instances have their references removed as well.
50
+ //
51
+ if (ref instanceof Schema_1.Schema) {
52
+ for (var fieldName in ref['_definition'].schema) {
53
+ if (typeof (ref['_definition'].schema[fieldName]) !== "string" &&
54
+ ref[fieldName] &&
55
+ ref[fieldName]['$changes']) {
56
+ _this.removeRef(ref[fieldName]['$changes'].refId);
57
+ }
58
+ }
59
+ }
60
+ else {
61
+ var definition = ref['$changes'].parent._definition;
62
+ var type = definition.schema[definition.fieldsByIndex[ref['$changes'].parentIndex]];
63
+ if (typeof (Object.values(type)[0]) === "function") {
64
+ Array.from(ref.values())
65
+ .forEach(function (child) { return _this.removeRef(child['$changes'].refId); });
66
+ }
67
+ }
68
+ _this.refs.delete(refId);
69
+ delete _this.refCounts[refId];
70
+ });
71
+ // clear deleted refs.
72
+ this.deletedRefs.clear();
73
+ };
74
+ return ReferenceTracker;
75
+ }());
76
+ exports.ReferenceTracker = ReferenceTracker;
77
+ //# sourceMappingURL=ReferenceTracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReferenceTracker.js","sourceRoot":"","sources":["../../src/changes/ReferenceTracker.ts"],"names":[],"mappings":"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","sourcesContent":["import { Schema } from \"../Schema\";\nimport { Ref } from \"./ChangeTree\";\nimport type { SchemaDefinition } from \"../annotations\";\n\nexport class ReferenceTracker {\n //\n // Relation of refId => Schema structure\n // For direct access of structures during decoding time.\n //\n public refs = new Map<number, Ref>();\n public refCounts: { [refId: number]: number; } = {};\n public deletedRefs = new Set<number>();\n\n protected nextUniqueId: number = 0;\n\n getNextUniqueId() {\n return this.nextUniqueId++;\n }\n\n // for decoding\n addRef(refId: number, ref: Ref, incrementCount: boolean = true) {\n this.refs.set(refId, ref);\n\n if (incrementCount) {\n this.refCounts[refId] = (this.refCounts[refId] || 0) + 1;\n }\n }\n\n // for decoding\n removeRef(refId) {\n this.refCounts[refId] = this.refCounts[refId] - 1;\n this.deletedRefs.add(refId);\n }\n\n clearRefs() {\n this.refs.clear();\n this.deletedRefs.clear();\n this.refCounts = {};\n }\n\n // for decoding\n garbageCollectDeletedRefs() {\n this.deletedRefs.forEach((refId) => {\n //\n // Skip active references.\n //\n if (this.refCounts[refId] > 0) { return; }\n\n const ref = this.refs.get(refId);\n\n //\n // Ensure child schema instances have their references removed as well.\n //\n if (ref instanceof Schema) {\n for (const fieldName in ref['_definition'].schema) {\n if (typeof (ref['_definition'].schema[fieldName]) !== \"string\" &&\n ref[fieldName] &&\n ref[fieldName]['$changes']) {\n this.removeRef(ref[fieldName]['$changes'].refId);\n }\n }\n\n } else {\n const definition: SchemaDefinition = ref['$changes'].parent._definition;\n const type = definition.schema[definition.fieldsByIndex[ref['$changes'].parentIndex]];\n\n if (typeof (Object.values(type)[0]) === \"function\") {\n Array.from(ref.values())\n .forEach((child) => this.removeRef(child['$changes'].refId));\n }\n }\n\n this.refs.delete(refId);\n delete this.refCounts[refId];\n });\n\n // clear deleted refs.\n this.deletedRefs.clear();\n }\n\n}\n"]}
@@ -0,0 +1,7 @@
1
+ export interface GenerateOptions {
2
+ files: string[];
3
+ output: string;
4
+ decorator?: string;
5
+ namespace?: string;
6
+ }
7
+ export declare function generate(targetId: string, options: GenerateOptions): void;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generate = void 0;
4
+ var fs = require("fs");
5
+ var path = require("path");
6
+ var parser_1 = require("./parser");
7
+ function generate(targetId, options) {
8
+ var generator;
9
+ try {
10
+ generator = require('./languages/' + targetId).generate;
11
+ }
12
+ catch (e) {
13
+ throw new Error("You must provide a valid generator as argument, such as: --csharp, --haxe or --cpp");
14
+ }
15
+ if (!fs.existsSync(options.output)) {
16
+ console.log("Creating", options.output, "directory");
17
+ fs.mkdirSync(options.output);
18
+ }
19
+ /**
20
+ * Default `@type()` decorator name
21
+ */
22
+ if (!options.decorator) {
23
+ options.decorator = "type";
24
+ }
25
+ var structures = parser_1.parseFiles(options.files, options.decorator);
26
+ // Post-process classes before generating
27
+ structures.classes.forEach(function (klass) { return klass.postProcessing(); });
28
+ var files = generator(structures, options);
29
+ files.forEach(function (file) {
30
+ var outputPath = path.resolve(options.output, file.name);
31
+ fs.writeFileSync(outputPath, file.content);
32
+ console.log("generated:", file.name);
33
+ });
34
+ }
35
+ exports.generate = generate;
36
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/codegen/api.ts"],"names":[],"mappings":";;;AAAA,uBAAyB;AACzB,2BAA6B;AAG7B,mCAAsC;AAStC,SAAgB,QAAQ,CAAC,QAAgB,EAAE,OAAwB;IAC/D,IAAI,SAAmB,CAAC;IAExB,IAAI;QACA,SAAS,GAAG,OAAO,CAAC,cAAc,GAAG,QAAQ,CAAC,CAAC,QAAQ,CAAC;KAE3D;IAAC,OAAO,CAAC,EAAE;QACR,MAAM,IAAI,KAAK,CAAC,oFAAoF,CAAC,CAAC;KACzG;IAED,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;QAChC,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QACrD,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;KAChC;IAED;;OAEG;IACH,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE;QAAE,OAAO,CAAC,SAAS,GAAG,MAAM,CAAC;KAAE;IAEvD,IAAM,UAAU,GAAG,mBAAU,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhE,yCAAyC;IACzC,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,UAAA,KAAK,IAAI,OAAA,KAAK,CAAC,cAAc,EAAE,EAAtB,CAAsB,CAAC,CAAC;IAE5D,IAAM,KAAK,GAAG,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAE7C,KAAK,CAAC,OAAO,CAAC,UAAC,IAAU;QACrB,IAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3D,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;AACP,CAAC;AAhCD,4BAgCC","sourcesContent":["import * as fs from \"fs\";\nimport * as path from \"path\";\n\nimport { File } from \"./types\";\nimport { parseFiles } from \"./parser\";\n\nexport interface GenerateOptions {\n files: string[],\n output: string;\n decorator?: string;\n namespace?: string;\n}\n\nexport function generate(targetId: string, options: GenerateOptions) {\n let generator: Function;\n\n try {\n generator = require('./languages/' + targetId).generate;\n\n } catch (e) {\n throw new Error(\"You must provide a valid generator as argument, such as: --csharp, --haxe or --cpp\");\n }\n\n if (!fs.existsSync(options.output)) {\n console.log(\"Creating\", options.output, \"directory\");\n fs.mkdirSync(options.output);\n }\n\n /**\n * Default `@type()` decorator name\n */\n if (!options.decorator) { options.decorator = \"type\"; }\n\n const structures = parseFiles(options.files, options.decorator);\n\n // Post-process classes before generating\n structures.classes.forEach(klass => klass.postProcessing());\n\n const files = generator(structures, options);\n\n files.forEach((file: File) => {\n const outputPath = path.resolve(options.output, file.name);\n fs.writeFileSync(outputPath, file.content);\n console.log(\"generated:\", file.name);\n });\n}\n"]}
@@ -0,0 +1,6 @@
1
+ declare const _default: (sargs: any) => any;
2
+ /**
3
+ * @author Ethan Davis
4
+ * https://github.com/ethanent/gar
5
+ */
6
+ export default _default;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /**
4
+ * @author Ethan Davis
5
+ * https://github.com/ethanent/gar
6
+ */
7
+ exports.default = (function (sargs) {
8
+ var props = {};
9
+ var lones = [];
10
+ var convertIfApplicable = function (value) { return (isNaN(value) ? (value.toString().toLowerCase() === 'true' ? true : (value.toString().toLowerCase() === 'false' ? false : value)) : Number(value)); };
11
+ var removeStartHyphens = function (value) { return value.replace(/^\-+/g, ''); };
12
+ for (var i = 0; i < sargs.length; i++) {
13
+ var equalsIndex = sargs[i].indexOf('=');
14
+ var isNextRefProp = sargs[i].charAt(0) === '-' && sargs.length - 1 >= i + 1 && sargs[i + 1].indexOf('=') === -1 && sargs[i + 1].charAt(0) !== '-';
15
+ var argName = equalsIndex === -1 ? removeStartHyphens(sargs[i]) : removeStartHyphens(sargs[i].slice(0, equalsIndex));
16
+ if (equalsIndex !== -1) {
17
+ props[argName] = convertIfApplicable(sargs[i].slice(equalsIndex + 1));
18
+ }
19
+ else if (isNextRefProp) {
20
+ props[argName] = convertIfApplicable(sargs[i + 1]);
21
+ i++;
22
+ }
23
+ else if (sargs[i].charAt(0) === '-') {
24
+ if (sargs[i].charAt(1) === '-') {
25
+ props[argName] = true;
26
+ }
27
+ else {
28
+ for (var b = 0; b < argName.length; b++) {
29
+ props[argName.charAt(b)] = true;
30
+ }
31
+ }
32
+ }
33
+ else {
34
+ lones.push(convertIfApplicable(argName));
35
+ }
36
+ }
37
+ return Object.assign(props, {
38
+ '_': lones
39
+ });
40
+ });
41
+ //# sourceMappingURL=argv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"argv.js","sourceRoot":"","sources":["../../src/codegen/argv.ts"],"names":[],"mappings":";;AAAA;;;GAGG;AACH,mBAAe,UAAC,KAAK;IACpB,IAAI,KAAK,GAAG,EAAE,CAAA;IACd,IAAI,KAAK,GAAG,EAAE,CAAA;IAEd,IAAM,mBAAmB,GAAG,UAAC,KAAK,IAAK,OAAA,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAlJ,CAAkJ,CAAA;IACzL,IAAM,kBAAkB,GAAG,UAAC,KAAK,IAAK,OAAA,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,EAA1B,CAA0B,CAAA;IAEhE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACtC,IAAM,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QACzC,IAAM,aAAa,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,CAAA;QACnJ,IAAM,OAAO,GAAG,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAA;QAEtH,IAAI,WAAW,KAAK,CAAC,CAAC,EAAE;YACvB,KAAK,CAAC,OAAO,CAAC,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,CAAA;SACrE;aACI,IAAI,aAAa,EAAE;YACvB,KAAK,CAAC,OAAO,CAAC,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;YAClD,CAAC,EAAE,CAAA;SACH;aAAM,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE;YACtC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE;gBAC/B,KAAK,CAAC,OAAO,CAAC,GAAG,IAAI,CAAA;aACrB;iBACI;gBACJ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;oBACxC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;iBAC/B;aACD;SACD;aAAM;YACN,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,CAAA;SACxC;KACD;IAED,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE;QAC3B,GAAG,EAAE,KAAK;KACV,CAAC,CAAA;AACH,CAAC,EAAA","sourcesContent":["/**\n * @author Ethan Davis\n * https://github.com/ethanent/gar\n */\nexport default (sargs): any => {\n\tlet props = {}\n\tlet lones = []\n\n\tconst convertIfApplicable = (value) => (isNaN(value) ? (value.toString().toLowerCase() === 'true' ? true : (value.toString().toLowerCase() === 'false' ? false : value)) : Number(value))\n\tconst removeStartHyphens = (value) => value.replace(/^\\-+/g, '')\n\n\tfor (let i = 0; i < sargs.length; i++) {\n\t\tconst equalsIndex = sargs[i].indexOf('=')\n\t\tconst isNextRefProp = sargs[i].charAt(0) === '-' && sargs.length - 1 >= i + 1 && sargs[i + 1].indexOf('=') === -1 && sargs[i + 1].charAt(0) !== '-'\n\t\tconst argName = equalsIndex === -1 ? removeStartHyphens(sargs[i]) : removeStartHyphens(sargs[i].slice(0, equalsIndex))\n\n\t\tif (equalsIndex !== -1) {\n\t\t\tprops[argName] = convertIfApplicable(sargs[i].slice(equalsIndex + 1))\n\t\t}\n\t\telse if (isNextRefProp) {\n\t\t\tprops[argName] = convertIfApplicable(sargs[i + 1])\n\t\t\ti++\n\t\t} else if (sargs[i].charAt(0) === '-') {\n\t\t\tif (sargs[i].charAt(1) === '-') {\n\t\t\t\tprops[argName] = true\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfor (let b = 0; b < argName.length; b++) {\n\t\t\t\t\tprops[argName.charAt(b)] = true\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tlones.push(convertIfApplicable(argName))\n\t\t}\n\t}\n\n\treturn Object.assign(props, {\n\t\t'_': lones\n\t})\n}\n"]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ var argv_1 = require("./argv");
4
+ var api_1 = require("./api");
5
+ var supportedTargets = {
6
+ csharp: 'generate for C#/Unity',
7
+ cpp: 'generate for C++',
8
+ haxe: 'generate for Haxe',
9
+ ts: 'generate for TypeScript',
10
+ js: 'generate for JavaScript',
11
+ java: 'generate for Java',
12
+ lua: 'generate for LUA',
13
+ };
14
+ function displayHelp() {
15
+ console.log("\nschema-codegen [path/to/Schema.ts]\n\nUsage (C#/Unity)\n schema-codegen src/Schema.ts --output client-side/ --csharp --namespace MyGame.Schema\n\nValid options:\n --output: the output directory for generated client-side schema files\n" + Object.
16
+ keys(supportedTargets).
17
+ map(function (targetId) { return (" --" + targetId + ": " + supportedTargets[targetId]); }).
18
+ join("\n") + "\n\nOptional:\n --namespace: generate namespace on output code\n --decorator: custom name for @type decorator to scan for");
19
+ process.exit();
20
+ }
21
+ var args = argv_1.default(process.argv.slice(2));
22
+ if (args.help) {
23
+ displayHelp();
24
+ }
25
+ var targetId;
26
+ for (var target in supportedTargets) {
27
+ if (args[target]) {
28
+ targetId = target;
29
+ }
30
+ }
31
+ if (!args.output) {
32
+ console.error("You must provide a valid --output directory.");
33
+ displayHelp();
34
+ }
35
+ try {
36
+ args.files = args._;
37
+ api_1.generate(targetId, {
38
+ files: args._,
39
+ decorator: args.decorator,
40
+ output: args.output,
41
+ namespace: args.namespace
42
+ });
43
+ }
44
+ catch (e) {
45
+ console.error(e.message);
46
+ console.error(e.stack);
47
+ displayHelp();
48
+ }
49
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/codegen/cli.ts"],"names":[],"mappings":";;AAAA,+BAA0B;AAC1B,6BAAiC;AAEjC,IAAM,gBAAgB,GAAG;IACrB,MAAM,EAAE,uBAAuB;IAC/B,GAAG,EAAE,kBAAkB;IACvB,IAAI,EAAE,mBAAmB;IACzB,EAAE,EAAE,yBAAyB;IAC7B,EAAE,EAAE,yBAAyB;IAC7B,IAAI,EAAE,mBAAmB;IACzB,GAAG,EAAE,kBAAkB;CAC1B,CAAA;AAED,SAAS,WAAW;IAChB,OAAO,CAAC,GAAG,CAAC,uPAOd,MAAM;QACJ,IAAI,CAAC,gBAAgB,CAAC;QACtB,GAAG,CAAC,UAAC,QAAQ,IAAK,OAAA,CACtB,WAAS,QAAQ,UAAK,gBAAgB,CAAC,QAAQ,CAAG,CAC7C,EAFiB,CAEjB,CAAC;QACF,IAAI,CAAC,IAAI,CAAC,oIAI+C,CAAC,CAAC;IAC3D,OAAO,CAAC,IAAI,EAAE,CAAC;AACnB,CAAC;AAED,IAAM,IAAI,GAAG,cAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACzC,IAAI,IAAI,CAAC,IAAI,EAAE;IACX,WAAW,EAAE,CAAC;CACjB;AAED,IAAI,QAAgB,CAAC;AACrB,KAAK,IAAI,MAAM,IAAI,gBAAgB,EAAE;IACjC,IAAI,IAAI,CAAC,MAAM,CAAC,EAAE;QACd,QAAQ,GAAG,MAAM,CAAC;KACrB;CACJ;AAED,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;IACd,OAAO,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAC9D,WAAW,EAAE,CAAC;CACjB;AAED,IAAI;IACA,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC;IACpB,cAAQ,CAAC,QAAQ,EAAE;QACf,KAAK,EAAE,IAAI,CAAC,CAAC;QACb,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,SAAS,EAAE,IAAI,CAAC,SAAS;KAC5B,CAAC,CAAC;CAEN;AAAC,OAAO,CAAC,EAAE;IACR,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IACzB,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IACvB,WAAW,EAAE,CAAC;CACjB","sourcesContent":["import argv from \"./argv\";\nimport { generate } from \"./api\";\n\nconst supportedTargets = {\n csharp: 'generate for C#/Unity',\n cpp: 'generate for C++',\n haxe: 'generate for Haxe',\n ts: 'generate for TypeScript',\n js: 'generate for JavaScript',\n java: 'generate for Java',\n lua: 'generate for LUA',\n}\n\nfunction displayHelp() {\n console.log(`\\nschema-codegen [path/to/Schema.ts]\n\nUsage (C#/Unity)\n schema-codegen src/Schema.ts --output client-side/ --csharp --namespace MyGame.Schema\n\nValid options:\n --output: the output directory for generated client-side schema files\n${Object.\n keys(supportedTargets).\n map((targetId) => (\n` --${targetId}: ${supportedTargets[targetId]}`\n )).\n join(\"\\n\")}\n\nOptional:\n --namespace: generate namespace on output code\n --decorator: custom name for @type decorator to scan for`);\n process.exit();\n}\n\nconst args = argv(process.argv.slice(2));\nif (args.help) {\n displayHelp();\n}\n\nlet targetId: string;\nfor (let target in supportedTargets) {\n if (args[target]) {\n targetId = target;\n }\n}\n\nif (!args.output) {\n console.error(\"You must provide a valid --output directory.\");\n displayHelp();\n}\n\ntry {\n args.files = args._;\n generate(targetId, {\n files: args._,\n decorator: args.decorator,\n output: args.output,\n namespace: args.namespace\n });\n\n} catch (e) {\n console.error(e.message);\n console.error(e.stack);\n displayHelp();\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import { File, Context } from "../types";
2
+ import { GenerateOptions } from "../api";
3
+ export declare function generate(context: Context, options: GenerateOptions): File[];