jitar 0.1.0 → 0.1.1

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 (195) hide show
  1. package/dist/core/SegmentBuilder.js +0 -1
  2. package/dist/runtime/ClientId.d.ts +4 -0
  3. package/dist/runtime/ClientId.js +11 -0
  4. package/dist/runtime/LocalRepository.d.ts +2 -2
  5. package/dist/runtime/LocalRepository.js +4 -5
  6. package/dist/runtime/caching/CacheBuilder.js +3 -3
  7. package/dist/runtime/serialization/ClassSerializer.js +16 -0
  8. package/dist/runtime/serialization/MapSerializer.d.ts +1 -0
  9. package/dist/runtime/serialization/MapSerializer.js +10 -0
  10. package/dist/runtime/serialization/SetSerializer.d.ts +1 -0
  11. package/dist/runtime/serialization/SetSerializer.js +7 -0
  12. package/dist/runtime/serialization/errors/InvalidPropertyType.d.ts +3 -0
  13. package/dist/runtime/serialization/errors/InvalidPropertyType.js +6 -0
  14. package/dist/server/controllers/ModulesController.js +6 -0
  15. package/package.json +23 -4
  16. package/src/core/SegmentBuilder.ts +1 -1
  17. package/src/runtime/ClientId.ts +18 -0
  18. package/src/runtime/LocalRepository.ts +5 -8
  19. package/src/runtime/caching/CacheBuilder.ts +3 -3
  20. package/src/runtime/serialization/ClassSerializer.ts +28 -0
  21. package/src/runtime/serialization/MapSerializer.ts +17 -1
  22. package/src/runtime/serialization/SetSerializer.ts +11 -0
  23. package/src/runtime/serialization/ValueSerializer.ts +1 -1
  24. package/src/runtime/serialization/errors/InvalidPropertyType.ts +12 -0
  25. package/src/server/controllers/ModulesController.ts +11 -0
  26. package/test/runtime/ClientId.spec.ts +43 -0
  27. package/test/runtime/LocalRepository.spec.ts +2 -2
  28. package/test/runtime/serialization/ValueSerializer.spec.ts +1 -1
  29. package/coverage/clover.xml +0 -2483
  30. package/coverage/coverage-final.json +0 -56
  31. package/coverage/lcov-report/base.css +0 -224
  32. package/coverage/lcov-report/block-navigation.js +0 -87
  33. package/coverage/lcov-report/favicon.png +0 -0
  34. package/coverage/lcov-report/index.html +0 -356
  35. package/coverage/lcov-report/prettify.css +0 -1
  36. package/coverage/lcov-report/prettify.js +0 -2
  37. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  38. package/coverage/lcov-report/sorter.js +0 -196
  39. package/coverage/lcov-report/src/core/ErrorManager.ts.html +0 -139
  40. package/coverage/lcov-report/src/core/Implementation.ts.html +0 -244
  41. package/coverage/lcov-report/src/core/ImplementationBuilder.ts.html +0 -148
  42. package/coverage/lcov-report/src/core/Procedure.ts.html +0 -379
  43. package/coverage/lcov-report/src/core/Segment.ts.html +0 -271
  44. package/coverage/lcov-report/src/core/SegmentBuilder.ts.html +0 -250
  45. package/coverage/lcov-report/src/core/Version.ts.html +0 -289
  46. package/coverage/lcov-report/src/core/definitions/AccessLevel.ts.html +0 -94
  47. package/coverage/lcov-report/src/core/definitions/index.html +0 -116
  48. package/coverage/lcov-report/src/core/errors/ErrorManager.ts.html +0 -139
  49. package/coverage/lcov-report/src/core/errors/ImplementationNotFound.ts.html +0 -121
  50. package/coverage/lcov-report/src/core/errors/InvalidVersionNumber.ts.html +0 -121
  51. package/coverage/lcov-report/src/core/errors/MissingParameterValue.ts.html +0 -121
  52. package/coverage/lcov-report/src/core/errors/ProcedureNotFound.ts.html +0 -121
  53. package/coverage/lcov-report/src/core/errors/index.html +0 -161
  54. package/coverage/lcov-report/src/core/index.html +0 -191
  55. package/coverage/lcov-report/src/core/reflection/ParameterParser.ts.html +0 -307
  56. package/coverage/lcov-report/src/core/reflection/ReflectionHelper.ts.html +0 -439
  57. package/coverage/lcov-report/src/core/reflection/index.html +0 -131
  58. package/coverage/lcov-report/src/core/reflection/models/ReflectionField.ts.html +0 -151
  59. package/coverage/lcov-report/src/core/reflection/models/ReflectionParameter.ts.html +0 -139
  60. package/coverage/lcov-report/src/core/reflection/models/index.html +0 -131
  61. package/coverage/lcov-report/src/core/utils/FqnBuilder.ts.html +0 -115
  62. package/coverage/lcov-report/src/core/utils/index.html +0 -116
  63. package/coverage/lcov-report/src/hooks.ts.html +0 -88
  64. package/coverage/lcov-report/src/index.html +0 -116
  65. package/coverage/lcov-report/src/runtime/Gateway.ts.html +0 -139
  66. package/coverage/lcov-report/src/runtime/LocalGateway.ts.html +0 -364
  67. package/coverage/lcov-report/src/runtime/LocalNode.ts.html +0 -475
  68. package/coverage/lcov-report/src/runtime/LocalRepository.ts.html +0 -556
  69. package/coverage/lcov-report/src/runtime/Node.ts.html +0 -130
  70. package/coverage/lcov-report/src/runtime/NodeBalancer.ts.html +0 -268
  71. package/coverage/lcov-report/src/runtime/NodeMonitor.ts.html +0 -274
  72. package/coverage/lcov-report/src/runtime/Remote.ts.html +0 -562
  73. package/coverage/lcov-report/src/runtime/RemoteNode.ts.html +0 -232
  74. package/coverage/lcov-report/src/runtime/Repository.ts.html +0 -145
  75. package/coverage/lcov-report/src/runtime/Runtime.ts.html +0 -226
  76. package/coverage/lcov-report/src/runtime/caching/ImportRewriter.ts.html +0 -313
  77. package/coverage/lcov-report/src/runtime/caching/ModuleAppender.ts.html +0 -208
  78. package/coverage/lcov-report/src/runtime/caching/RemoteBuilder.ts.html +0 -238
  79. package/coverage/lcov-report/src/runtime/caching/SourceAppender.ts.html +0 -256
  80. package/coverage/lcov-report/src/runtime/caching/definitions/Keywords.ts.html +0 -94
  81. package/coverage/lcov-report/src/runtime/caching/definitions/index.html +0 -116
  82. package/coverage/lcov-report/src/runtime/caching/index.html +0 -146
  83. package/coverage/lcov-report/src/runtime/caching/models/ApplicationModule.ts.html +0 -175
  84. package/coverage/lcov-report/src/runtime/caching/models/Implementation.ts.html +0 -208
  85. package/coverage/lcov-report/src/runtime/caching/models/SegmentModule.ts.html +0 -163
  86. package/coverage/lcov-report/src/runtime/caching/models/index.html +0 -146
  87. package/coverage/lcov-report/src/runtime/errors/ClientNotFound.ts.html +0 -121
  88. package/coverage/lcov-report/src/runtime/errors/InvalidClientId.ts.html +0 -121
  89. package/coverage/lcov-report/src/runtime/errors/InvalidSegmentFile.ts.html +0 -121
  90. package/coverage/lcov-report/src/runtime/errors/ModuleNotLoaded.ts.html +0 -121
  91. package/coverage/lcov-report/src/runtime/errors/NoNodeAvailable.ts.html +0 -121
  92. package/coverage/lcov-report/src/runtime/errors/RepositoryNotAvaiable.ts.html +0 -121
  93. package/coverage/lcov-report/src/runtime/errors/RuntimeNotAvailable.ts.html +0 -121
  94. package/coverage/lcov-report/src/runtime/errors/index.html +0 -206
  95. package/coverage/lcov-report/src/runtime/hooks/dependencies.ts.html +0 -142
  96. package/coverage/lcov-report/src/runtime/hooks/index.html +0 -131
  97. package/coverage/lcov-report/src/runtime/hooks/runtime.ts.html +0 -160
  98. package/coverage/lcov-report/src/runtime/index.html +0 -251
  99. package/coverage/lcov-report/src/runtime/models/File.ts.html +0 -151
  100. package/coverage/lcov-report/src/runtime/models/index.html +0 -116
  101. package/coverage/lcov-report/src/runtime/serialization/ArraySerializer.ts.html +0 -166
  102. package/coverage/lcov-report/src/runtime/serialization/ClassSerializer.ts.html +0 -400
  103. package/coverage/lcov-report/src/runtime/serialization/MapSerializer.ts.html +0 -217
  104. package/coverage/lcov-report/src/runtime/serialization/ObjectSerializer.ts.html +0 -211
  105. package/coverage/lcov-report/src/runtime/serialization/SetSerializer.ts.html +0 -178
  106. package/coverage/lcov-report/src/runtime/serialization/ValueSerializer.ts.html +0 -328
  107. package/coverage/lcov-report/src/runtime/serialization/errors/ClassNotFound.ts.html +0 -121
  108. package/coverage/lcov-report/src/runtime/serialization/errors/InvalidClass.ts.html +0 -121
  109. package/coverage/lcov-report/src/runtime/serialization/errors/index.html +0 -131
  110. package/coverage/lcov-report/src/runtime/serialization/index.html +0 -191
  111. package/coverage/lcov-report/src/runtime/utils/ModuleAnalyser.ts.html +0 -265
  112. package/coverage/lcov-report/src/runtime/utils/ModuleLoader.ts.html +0 -238
  113. package/coverage/lcov-report/src/runtime/utils/UrlRewriter.ts.html +0 -262
  114. package/coverage/lcov-report/src/runtime/utils/index.html +0 -146
  115. package/coverage/lcov-report/test/_fixtures/core/Implementation.fixture.ts.html +0 -184
  116. package/coverage/lcov-report/test/_fixtures/core/Procedure.fixture.ts.html +0 -172
  117. package/coverage/lcov-report/test/_fixtures/core/Segment.fixture.ts.html +0 -193
  118. package/coverage/lcov-report/test/_fixtures/core/SegmentBuilder.fixture.ts.html +0 -220
  119. package/coverage/lcov-report/test/_fixtures/core/Version.fixture.ts.html +0 -139
  120. package/coverage/lcov-report/test/_fixtures/core/index.html +0 -176
  121. package/coverage/lcov-report/test/_fixtures/core/procedures/allDefault.ts.html +0 -100
  122. package/coverage/lcov-report/test/_fixtures/core/procedures/hasParameters.ts.html +0 -100
  123. package/coverage/lcov-report/test/_fixtures/core/procedures/hasVersion_v1_0_0.ts.html +0 -115
  124. package/coverage/lcov-report/test/_fixtures/core/procedures/hasVersion_v1_0_5.ts.html +0 -115
  125. package/coverage/lcov-report/test/_fixtures/core/procedures/hasVersion_v1_1_0.ts.html +0 -115
  126. package/coverage/lcov-report/test/_fixtures/core/procedures/hasVersion_v1_2_3.ts.html +0 -115
  127. package/coverage/lcov-report/test/_fixtures/core/procedures/inModule.ts.html +0 -115
  128. package/coverage/lcov-report/test/_fixtures/core/procedures/index.html +0 -251
  129. package/coverage/lcov-report/test/_fixtures/core/procedures/isBroken.ts.html +0 -112
  130. package/coverage/lcov-report/test/_fixtures/core/procedures/isPrivate.ts.html +0 -112
  131. package/coverage/lcov-report/test/_fixtures/core/procedures/isPublic.ts.html +0 -112
  132. package/coverage/lcov-report/test/_fixtures/core/reflection/ReflectionHelper.fixture.ts.html +0 -241
  133. package/coverage/lcov-report/test/_fixtures/core/reflection/index.html +0 -116
  134. package/coverage/lcov-report/test/_fixtures/core/segments/default.segment.ts.html +0 -94
  135. package/coverage/lcov-report/test/_fixtures/core/segments/index.html +0 -116
  136. package/coverage/lcov-report/test/_fixtures/runtime/LocalGateway.fixture.ts.html +0 -157
  137. package/coverage/lcov-report/test/_fixtures/runtime/LocalNode.fixture.ts.html +0 -133
  138. package/coverage/lcov-report/test/_fixtures/runtime/LocalRepository.fixture.ts.html +0 -304
  139. package/coverage/lcov-report/test/_fixtures/runtime/NodeBalancer.fixture.ts.html +0 -142
  140. package/coverage/lcov-report/test/_fixtures/runtime/NodeMonitor.fixture.ts.html +0 -187
  141. package/coverage/lcov-report/test/_fixtures/runtime/RemoteNode.fixture.ts.html +0 -109
  142. package/coverage/lcov-report/test/_fixtures/runtime/caching/ImportRewriter.fixture.ts.html +0 -304
  143. package/coverage/lcov-report/test/_fixtures/runtime/caching/ModuleAppender.fixture.ts.html +0 -181
  144. package/coverage/lcov-report/test/_fixtures/runtime/caching/RemoteBuilder.fixture.ts.html +0 -217
  145. package/coverage/lcov-report/test/_fixtures/runtime/caching/SourceAppender.fixture.ts.html +0 -178
  146. package/coverage/lcov-report/test/_fixtures/runtime/caching/index.html +0 -146
  147. package/coverage/lcov-report/test/_fixtures/runtime/index.html +0 -206
  148. package/coverage/lcov-report/test/_fixtures/runtime/procedures/firstPrivateTask.ts.html +0 -109
  149. package/coverage/lcov-report/test/_fixtures/runtime/procedures/firstPublicTask.ts.html +0 -118
  150. package/coverage/lcov-report/test/_fixtures/runtime/procedures/fourthPublicTask.ts.html +0 -109
  151. package/coverage/lcov-report/test/_fixtures/runtime/procedures/index.html +0 -191
  152. package/coverage/lcov-report/test/_fixtures/runtime/procedures/secondPrivateTask.ts.html +0 -109
  153. package/coverage/lcov-report/test/_fixtures/runtime/procedures/secondPublicTask.ts.html +0 -118
  154. package/coverage/lcov-report/test/_fixtures/runtime/procedures/thirdPublicTask.ts.html +0 -118
  155. package/coverage/lcov-report/test/_fixtures/runtime/segments/first.segment.files.ts.html +0 -85
  156. package/coverage/lcov-report/test/_fixtures/runtime/segments/first.segment.ts.html +0 -91
  157. package/coverage/lcov-report/test/_fixtures/runtime/segments/index.html +0 -161
  158. package/coverage/lcov-report/test/_fixtures/runtime/segments/second.segment.files.ts.html +0 -85
  159. package/coverage/lcov-report/test/_fixtures/runtime/segments/second.segment.ts.html +0 -91
  160. package/coverage/lcov-report/test/_fixtures/runtime/segments.ts.html +0 -319
  161. package/coverage/lcov-report/test/_fixtures/runtime/serialization/ValueSerializer.fixture.ts.html +0 -394
  162. package/coverage/lcov-report/test/_fixtures/runtime/serialization/index.html +0 -116
  163. package/coverage/lcov-report/test/_fixtures/runtime/utils/ModuleAnaliser.fixture.ts.html +0 -163
  164. package/coverage/lcov-report/test/_fixtures/runtime/utils/index.html +0 -116
  165. package/coverage/lcov.info +0 -3565
  166. package/dist/core/AccessLevel.d.ts +0 -5
  167. package/dist/core/AccessLevel.js +0 -6
  168. package/dist/core/ImplementationBuilder.d.ts +0 -4
  169. package/dist/core/ImplementationBuilder.js +0 -14
  170. package/dist/core/errors/ErrorManager.d.ts +0 -3
  171. package/dist/core/errors/ErrorManager.js +0 -11
  172. package/dist/runtime/RemoteNodeBuilder.d.ts +0 -4
  173. package/dist/runtime/RemoteNodeBuilder.js +0 -10
  174. package/dist/runtime/caching/CachBuilder.d.ts +0 -6
  175. package/dist/runtime/caching/CachBuilder.js +0 -150
  176. package/dist/runtime/caching/ModuleAppender.d.ts +0 -5
  177. package/dist/runtime/caching/ModuleAppender.js +0 -22
  178. package/dist/runtime/caching/errors/FunctionFilenameNotFound.d.ts +0 -3
  179. package/dist/runtime/caching/errors/FunctionFilenameNotFound.js +0 -5
  180. package/dist/runtime/caching/types/models/ApplicationModule.d.ts +0 -9
  181. package/dist/runtime/caching/types/models/ApplicationModule.js +0 -19
  182. package/dist/runtime/caching/types/models/Implementation.d.ts +0 -12
  183. package/dist/runtime/caching/types/models/Implementation.js +0 -27
  184. package/dist/runtime/caching/types/models/Procedure.d.ts +0 -9
  185. package/dist/runtime/caching/types/models/Procedure.js +0 -15
  186. package/dist/runtime/caching/types/models/Segment.d.ts +0 -10
  187. package/dist/runtime/caching/types/models/Segment.js +0 -16
  188. package/dist/runtime/caching/types/models/SegmentModule.d.ts +0 -10
  189. package/dist/runtime/caching/types/models/SegmentModule.js +0 -14
  190. package/dist/server/definitions/RuntimeMode.d.ts +0 -8
  191. package/dist/server/definitions/RuntimeMode.js +0 -9
  192. package/dist/server/models/RuntimeConfiguration.d.ts +0 -12
  193. package/dist/server/models/RuntimeConfiguration.js +0 -68
  194. package/dist/server/models/ServerOptions.d.ts +0 -4
  195. package/dist/server/models/ServerOptions.js +0 -25
@@ -10,7 +10,6 @@ export default class SegmentBuilder {
10
10
  const procedure = this.#buildProcedure(definition);
11
11
  segment.addProcedure(procedure);
12
12
  }
13
- ;
14
13
  return segment;
15
14
  }
16
15
  static #buildProcedure(definition) {
@@ -0,0 +1,4 @@
1
+ export default class ClientId {
2
+ static generate(): string;
3
+ static validate(clientId: string): boolean;
4
+ }
@@ -0,0 +1,11 @@
1
+ const CLIENT_ID_PREFIX = 'CLIENT_';
2
+ const CLIENT_ID_REGEX = /^CLIENT_\d+$/;
3
+ let lastClientId = 0;
4
+ export default class ClientId {
5
+ static generate() {
6
+ return `${CLIENT_ID_PREFIX}${lastClientId++}`;
7
+ }
8
+ static validate(clientId) {
9
+ return CLIENT_ID_REGEX.test(clientId);
10
+ }
11
+ }
@@ -1,8 +1,8 @@
1
1
  import Module from '../core/types/Module.js';
2
- import FileManager from './interfaces/FileManager.js';
3
2
  import LocalNode from './LocalNode.js';
4
- import File from './models/File.js';
5
3
  import Repository from './Repository.js';
4
+ import FileManager from './interfaces/FileManager.js';
5
+ import File from './models/File.js';
6
6
  export default class LocalRepository extends Repository {
7
7
  #private;
8
8
  constructor(fileManager: FileManager, url?: string);
@@ -1,12 +1,11 @@
1
- import File from './models/File.js';
1
+ import ClientId from './ClientId.js';
2
2
  import Repository from './Repository.js';
3
+ import File from './models/File.js';
3
4
  import ModuleLoader from './utils/ModuleLoader.js';
4
5
  import ClientNotFound from './errors/ClientNotFound.js';
5
6
  import InvalidClientId from './errors/InvalidClientId.js';
6
7
  import InvalidSegmentFile from './errors/InvalidSegmentFile.js';
7
8
  import { setRuntime } from '../hooks.js';
8
- let lastClientId = 0;
9
- const CLIENT_ID_PREFIX = 'CLIENT_';
10
9
  export default class LocalRepository extends Repository {
11
10
  #fileManager;
12
11
  #segments = new Map();
@@ -29,7 +28,7 @@ export default class LocalRepository extends Repository {
29
28
  files.forEach((file) => this.#segments.set(file, name));
30
29
  }
31
30
  async registerClient(segmentFilenames) {
32
- const clientId = `${CLIENT_ID_PREFIX}${lastClientId++}`;
31
+ const clientId = ClientId.generate();
33
32
  this.#clients.set(clientId, segmentFilenames);
34
33
  return clientId;
35
34
  }
@@ -57,7 +56,7 @@ export default class LocalRepository extends Repository {
57
56
  return ModuleLoader.import(location);
58
57
  }
59
58
  #validateClientId(clientId) {
60
- if (clientId.startsWith(CLIENT_ID_PREFIX) === false) {
59
+ if (ClientId.validate(clientId) === false) {
61
60
  throw new InvalidClientId(clientId);
62
61
  }
63
62
  if (this.#clients.has(clientId) === false) {
@@ -175,12 +175,12 @@ export default class CacheBuilder {
175
175
  return `${importCode}\n\n${modelCode}`;
176
176
  }
177
177
  #createSegmentImportCode(segment) {
178
- let codes = [];
178
+ const codes = [];
179
179
  for (const module of segment.modules) {
180
180
  const relativeLocation = this.#sourceManager.getRelativeLocation(module.filename);
181
181
  const imports = [];
182
182
  for (const [importKey, implementation] of module.implementations) {
183
- imports.push(`${importKey} as \$${implementation.id}`);
183
+ imports.push(`${importKey} as $${implementation.id}`);
184
184
  }
185
185
  codes.push(`import { ${imports.join(',')} } from "./${relativeLocation}";`);
186
186
  }
@@ -191,7 +191,7 @@ export default class CacheBuilder {
191
191
  for (const procedure of segment.procedures.values()) {
192
192
  const implementationCode = [];
193
193
  for (const implementation of procedure.implementations) {
194
- implementationCode.push(`{ access: "${implementation.access}", version: "${implementation.version}", executable: \$${implementation.id} }`);
194
+ implementationCode.push(`{ access: "${implementation.access}", version: "${implementation.version}", executable: $${implementation.id} }`);
195
195
  }
196
196
  procedureCode.push(`{ module: "${procedure.module}", name: "${procedure.name}", implementations: [\n\t\t${implementationCode.join(',\n\t\t')}\n\t]}`);
197
197
  }
@@ -2,6 +2,7 @@ import ReflectionHelper from '../../core/reflection/ReflectionHelper.js';
2
2
  import ModuleLoader from '../utils/ModuleLoader.js';
3
3
  import ClassNotFound from './errors/ClassNotFound.js';
4
4
  import InvalidClass from './errors/InvalidClass.js';
5
+ import InvalidPropertyType from './errors/InvalidPropertyType.js';
5
6
  import ValueSerializer from './ValueSerializer.js';
6
7
  class ClassSerializer {
7
8
  serialize(object) {
@@ -30,6 +31,7 @@ class ClassSerializer {
30
31
  return { serialized: true, name: name, source: source, args: args, fields: fields };
31
32
  }
32
33
  async deserialize(object) {
34
+ this.#validateSerializedClass(object);
33
35
  const clazz = await this.#loadClass(object.source, object.name);
34
36
  if (clazz === undefined) {
35
37
  throw new ClassNotFound(object.name);
@@ -45,6 +47,20 @@ class ClassSerializer {
45
47
  }
46
48
  return instance;
47
49
  }
50
+ #validateSerializedClass(object) {
51
+ if (typeof object.name !== 'string') {
52
+ throw new InvalidPropertyType('class', 'name', 'string');
53
+ }
54
+ if (object.source !== null && typeof object.source !== 'string') {
55
+ throw new InvalidPropertyType(`class '${object.name}'`, 'source', 'string | null');
56
+ }
57
+ if ((object.args instanceof Array) === false) {
58
+ throw new InvalidPropertyType(`class '${object.name}'`, 'args', 'Array');
59
+ }
60
+ if ((object.fields instanceof Object) === false) {
61
+ throw new InvalidPropertyType(`class '${object.name}'`, 'fields', 'Object');
62
+ }
63
+ }
48
64
  async #loadClass(source, name) {
49
65
  if (source === null) {
50
66
  const system = typeof window !== 'undefined' ? window : global;
@@ -1,6 +1,7 @@
1
1
  import Serializer from './interfaces/Serializer.js';
2
2
  import SerializedMap from './types/SerializedMap.js';
3
3
  declare class MapSerializer implements Serializer {
4
+ #private;
4
5
  serialize(map: Map<unknown, unknown>): SerializedMap;
5
6
  deserialize(object: SerializedMap): Promise<Map<unknown, unknown>>;
6
7
  }
@@ -1,3 +1,4 @@
1
+ import InvalidPropertyType from './errors/InvalidPropertyType.js';
1
2
  import ValueSerializer from './ValueSerializer.js';
2
3
  class MapSerializer {
3
4
  serialize(map) {
@@ -10,6 +11,7 @@ class MapSerializer {
10
11
  return { serialized: true, name: 'Map', entries: { keys: keys, values: values } };
11
12
  }
12
13
  async deserialize(object) {
14
+ this.#validateSerializedMap(object);
13
15
  const keys = object.entries.keys;
14
16
  const values = object.entries.values;
15
17
  const result = new Map();
@@ -20,6 +22,14 @@ class MapSerializer {
20
22
  }
21
23
  return result;
22
24
  }
25
+ #validateSerializedMap(object) {
26
+ if ((object.entries?.keys instanceof Array) === false) {
27
+ throw new InvalidPropertyType('map', 'entries.keys', 'Array');
28
+ }
29
+ if ((object.entries?.values instanceof Array) === false) {
30
+ throw new InvalidPropertyType('map', 'entries.values', 'Array');
31
+ }
32
+ }
23
33
  }
24
34
  const instance = new MapSerializer();
25
35
  export default instance;
@@ -1,6 +1,7 @@
1
1
  import Serializer from './interfaces/Serializer.js';
2
2
  import SerializedSet from './types/SerializedSet.js';
3
3
  declare class SetSerializer implements Serializer {
4
+ #private;
4
5
  serialize(set: Set<unknown>): SerializedSet;
5
6
  deserialize(object: SerializedSet): Promise<Set<unknown>>;
6
7
  }
@@ -1,3 +1,4 @@
1
+ import InvalidPropertyType from './errors/InvalidPropertyType.js';
1
2
  import ValueSerializer from './ValueSerializer.js';
2
3
  class SetSerializer {
3
4
  serialize(set) {
@@ -8,9 +9,15 @@ class SetSerializer {
8
9
  return { serialized: true, name: 'Set', values: values };
9
10
  }
10
11
  async deserialize(object) {
12
+ this.#validateSerializedSet(object);
11
13
  const values = await Promise.all(object.values.map(async (value) => await ValueSerializer.deserialize(value)));
12
14
  return new Set([...values]);
13
15
  }
16
+ #validateSerializedSet(object) {
17
+ if ((object.values instanceof Array) === false) {
18
+ throw new InvalidPropertyType('set', 'values', 'Array');
19
+ }
20
+ }
14
21
  }
15
22
  const instance = new SetSerializer();
16
23
  export default instance;
@@ -0,0 +1,3 @@
1
+ export default class InvalidPropertyType extends Error {
2
+ constructor(typeName: string, propertyName: string, expectedType: string);
3
+ }
@@ -0,0 +1,6 @@
1
+ export default class InvalidPropertyType extends Error {
2
+ constructor(typeName, propertyName, expectedType) {
3
+ super(`The ${typeName} property '${propertyName}' has an invalid type (expected '${expectedType}')`);
4
+ }
5
+ }
6
+ InvalidPropertyType.source = '/jitar/runtime/serialization/errors/InvalidPropertyType.js';
@@ -9,6 +9,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
9
9
  };
10
10
  import { Controller, Get, Post } from '@overnightjs/core';
11
11
  import { Logger } from 'tslog';
12
+ import ClientId from '../../runtime/ClientId.js';
12
13
  import ValueSerializer from '../../runtime/serialization/ValueSerializer.js';
13
14
  let ModulesController = class ModulesController {
14
15
  #repository;
@@ -18,6 +19,8 @@ let ModulesController = class ModulesController {
18
19
  this.#logger = logger;
19
20
  }
20
21
  async registerClient(request, response) {
22
+ if ((request.body instanceof Array) === false) {
23
+ }
21
24
  const segmentFiles = request.body;
22
25
  const clientId = await this.#repository.registerClient(segmentFiles);
23
26
  this.#logger.info(`Registered client -> ${clientId} [${segmentFiles.join(',')}]`);
@@ -25,6 +28,9 @@ let ModulesController = class ModulesController {
25
28
  }
26
29
  async getModule(request, response) {
27
30
  const clientId = request.params.clientId;
31
+ if (typeof clientId !== 'string' || ClientId.validate(clientId) === false) {
32
+ return response.status(400).send('Invalid client id.');
33
+ }
28
34
  const pathKey = `/${clientId}/`;
29
35
  const pathIndex = request.path.indexOf(pathKey) + pathKey.length;
30
36
  const filename = request.path.substring(pathIndex);
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "jitar",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
+ "description": "Distributed runtime for JavaScript and TypeScript to chop monolithic applications into micros.",
4
5
  "author": "Masking Technology <info@masking.tech> (https://jitar.dev)",
5
6
  "license": "MIT",
6
7
  "type": "module",
@@ -30,7 +31,7 @@
30
31
  "glob-promise": "^5.0.0",
31
32
  "mime-types": "^2.1.35",
32
33
  "tslog": "^3.3.3",
33
- "yargs": "^17.5.1"
34
+ "yargs": "^17.6.0"
34
35
  },
35
36
  "devDependencies": {
36
37
  "@types/express": "^4.17.13",
@@ -38,11 +39,29 @@
38
39
  "@types/fs-extra": "^9.0.13",
39
40
  "@types/jest": "^28.1.3",
40
41
  "@types/mime-types": "^2.1.1",
41
- "@types/yargs": "^17.0.10",
42
+ "@types/yargs": "^17.0.13",
42
43
  "@typescript-eslint/eslint-plugin": "^5.29.0",
43
44
  "@typescript-eslint/parser": "^5.29.0",
44
45
  "eslint": "^8.18.0",
45
46
  "jest": "^28.1.3",
46
47
  "ts-jest": "^28.0.8"
47
- }
48
+ },
49
+ "repository": {
50
+ "type": "git",
51
+ "url": "https://github.com/MaskingTechnology/jitar"
52
+ },
53
+ "bugs": {
54
+ "url": "https://github.com/MaskingTechnology/jitar/issues"
55
+ },
56
+ "homepage": "https://jitar.dev",
57
+ "keywords": [
58
+ "distributed",
59
+ "runtime",
60
+ "javascript",
61
+ "typescript",
62
+ "microservices",
63
+ "monolith",
64
+ "full stack",
65
+ "web applications"
66
+ ]
48
67
  }
@@ -21,7 +21,7 @@ export default class SegmentBuilder
21
21
  const procedure = this.#buildProcedure(definition);
22
22
 
23
23
  segment.addProcedure(procedure);
24
- };
24
+ }
25
25
 
26
26
  return segment;
27
27
  }
@@ -0,0 +1,18 @@
1
+
2
+ const CLIENT_ID_PREFIX = 'CLIENT_';
3
+ const CLIENT_ID_REGEX = /^CLIENT_\d+$/;
4
+
5
+ let lastClientId = 0;
6
+
7
+ export default class ClientId
8
+ {
9
+ static generate(): string
10
+ {
11
+ return `${CLIENT_ID_PREFIX}${lastClientId++}`;
12
+ }
13
+
14
+ static validate(clientId: string): boolean
15
+ {
16
+ return CLIENT_ID_REGEX.test(clientId);
17
+ }
18
+ }
@@ -1,10 +1,11 @@
1
1
 
2
2
  import Module from '../core/types/Module.js';
3
3
 
4
- import FileManager from './interfaces/FileManager.js';
4
+ import ClientId from './ClientId.js';
5
5
  import LocalNode from './LocalNode.js';
6
- import File from './models/File.js';
7
6
  import Repository from './Repository.js';
7
+ import FileManager from './interfaces/FileManager.js';
8
+ import File from './models/File.js';
8
9
  import ModuleLoader from './utils/ModuleLoader.js';
9
10
 
10
11
  import ClientNotFound from './errors/ClientNotFound.js';
@@ -13,10 +14,6 @@ import InvalidSegmentFile from './errors/InvalidSegmentFile.js';
13
14
 
14
15
  import { setRuntime } from '../hooks.js';
15
16
 
16
- let lastClientId = 0;
17
-
18
- const CLIENT_ID_PREFIX = 'CLIENT_';
19
-
20
17
  export default class LocalRepository extends Repository
21
18
  {
22
19
  #fileManager: FileManager;
@@ -52,7 +49,7 @@ export default class LocalRepository extends Repository
52
49
 
53
50
  async registerClient(segmentFilenames: string[]): Promise<string>
54
51
  {
55
- const clientId = `${CLIENT_ID_PREFIX}${lastClientId++}`;
52
+ const clientId = ClientId.generate();
56
53
 
57
54
  this.#clients.set(clientId, segmentFilenames);
58
55
 
@@ -105,7 +102,7 @@ export default class LocalRepository extends Repository
105
102
 
106
103
  #validateClientId(clientId: string): void
107
104
  {
108
- if (clientId.startsWith(CLIENT_ID_PREFIX) === false)
105
+ if (ClientId.validate(clientId) === false)
109
106
  {
110
107
  throw new InvalidClientId(clientId);
111
108
  }
@@ -297,7 +297,7 @@ export default class CacheBuilder
297
297
 
298
298
  #createSegmentImportCode(segment: Segment): string
299
299
  {
300
- let codes: string[] = [];
300
+ const codes: string[] = [];
301
301
 
302
302
  for (const module of segment.modules)
303
303
  {
@@ -306,7 +306,7 @@ export default class CacheBuilder
306
306
 
307
307
  for (const [importKey, implementation] of module.implementations)
308
308
  {
309
- imports.push(`${importKey} as \$${implementation.id}`);
309
+ imports.push(`${importKey} as $${implementation.id}`);
310
310
  }
311
311
 
312
312
  codes.push(`import { ${imports.join(',')} } from "./${relativeLocation}";`);
@@ -325,7 +325,7 @@ export default class CacheBuilder
325
325
 
326
326
  for (const implementation of procedure.implementations)
327
327
  {
328
- implementationCode.push(`{ access: "${implementation.access}", version: "${implementation.version}", executable: \$${implementation.id} }`);
328
+ implementationCode.push(`{ access: "${implementation.access}", version: "${implementation.version}", executable: $${implementation.id} }`);
329
329
  }
330
330
 
331
331
  procedureCode.push(`{ module: "${procedure.module}", name: "${procedure.name}", implementations: [\n\t\t${implementationCode.join(',\n\t\t')}\n\t]}`);
@@ -7,10 +7,13 @@ import Module from '../../core/types/Module.js';
7
7
  import ModuleLoader from '../utils/ModuleLoader.js';
8
8
  import ClassNotFound from './errors/ClassNotFound.js';
9
9
  import InvalidClass from './errors/InvalidClass.js';
10
+ import InvalidPropertyType from './errors/InvalidPropertyType.js';
10
11
 
11
12
  import Serializer from './interfaces/Serializer.js';
13
+
12
14
  import SerializableObject from './types/SerializableObject.js';
13
15
  import SerializedClass from './types/SerializedClass.js';
16
+
14
17
  import ValueSerializer from './ValueSerializer.js';
15
18
 
16
19
  class ClassSerializer implements Serializer
@@ -59,6 +62,8 @@ class ClassSerializer implements Serializer
59
62
 
60
63
  async deserialize(object: SerializedClass): Promise<SerializableObject>
61
64
  {
65
+ this.#validateSerializedClass(object);
66
+
62
67
  const clazz = await this.#loadClass(object.source, object.name);
63
68
 
64
69
  if (clazz === undefined)
@@ -85,6 +90,29 @@ class ClassSerializer implements Serializer
85
90
  return instance;
86
91
  }
87
92
 
93
+ #validateSerializedClass(object: SerializedClass): void
94
+ {
95
+ if (typeof object.name !== 'string')
96
+ {
97
+ throw new InvalidPropertyType('class', 'name', 'string');
98
+ }
99
+
100
+ if (object.source !== null && typeof object.source !== 'string')
101
+ {
102
+ throw new InvalidPropertyType(`class '${object.name}'`, 'source', 'string | null');
103
+ }
104
+
105
+ if ((object.args instanceof Array) === false)
106
+ {
107
+ throw new InvalidPropertyType(`class '${object.name}'`, 'args', 'Array');
108
+ }
109
+
110
+ if ((object.fields instanceof Object) === false)
111
+ {
112
+ throw new InvalidPropertyType(`class '${object.name}'`, 'fields', 'Object');
113
+ }
114
+ }
115
+
88
116
  async #loadClass(source: string | null, name: string): Promise<unknown>
89
117
  {
90
118
  if (source === null)
@@ -1,7 +1,8 @@
1
1
 
2
+ import InvalidPropertyType from './errors/InvalidPropertyType.js';
2
3
  import Serializer from './interfaces/Serializer.js';
3
-
4
4
  import SerializedMap from './types/SerializedMap.js';
5
+
5
6
  import ValueSerializer from './ValueSerializer.js';
6
7
 
7
8
  class MapSerializer implements Serializer
@@ -22,6 +23,8 @@ class MapSerializer implements Serializer
22
23
 
23
24
  async deserialize(object: SerializedMap): Promise<Map<unknown, unknown>>
24
25
  {
26
+ this.#validateSerializedMap(object);
27
+
25
28
  const keys = object.entries.keys;
26
29
  const values = object.entries.values;
27
30
 
@@ -37,6 +40,19 @@ class MapSerializer implements Serializer
37
40
 
38
41
  return result;
39
42
  }
43
+
44
+ #validateSerializedMap(object: SerializedMap): void
45
+ {
46
+ if ((object.entries?.keys instanceof Array) === false)
47
+ {
48
+ throw new InvalidPropertyType('map', 'entries.keys', 'Array');
49
+ }
50
+
51
+ if ((object.entries?.values instanceof Array) === false)
52
+ {
53
+ throw new InvalidPropertyType('map', 'entries.values', 'Array');
54
+ }
55
+ }
40
56
  }
41
57
 
42
58
  const instance = new MapSerializer();
@@ -1,4 +1,5 @@
1
1
 
2
+ import InvalidPropertyType from './errors/InvalidPropertyType.js';
2
3
  import Serializer from './interfaces/Serializer.js';
3
4
  import SerializedSet from './types/SerializedSet.js';
4
5
 
@@ -20,10 +21,20 @@ class SetSerializer implements Serializer
20
21
 
21
22
  async deserialize(object: SerializedSet): Promise<Set<unknown>>
22
23
  {
24
+ this.#validateSerializedSet(object);
25
+
23
26
  const values = await Promise.all(object.values.map(async (value: unknown) => await ValueSerializer.deserialize(value)));
24
27
 
25
28
  return new Set([...values]);
26
29
  }
30
+
31
+ #validateSerializedSet(object: SerializedSet): void
32
+ {
33
+ if ((object.values instanceof Array) === false)
34
+ {
35
+ throw new InvalidPropertyType('set', 'values', 'Array');
36
+ }
37
+ }
27
38
  }
28
39
 
29
40
  const instance = new SetSerializer();
@@ -35,7 +35,7 @@ class ValueSerializer implements Serializer
35
35
  {
36
36
  // The error class is like Array, Map and Set in that it's a native class.
37
37
  // Native classes cannot be defined as a class object by the reflection helper.
38
- // Unlike Array, Map and Set, the error class can be serialzed by the class serializer.
38
+ // Unlike Array, Map and Set, the error class can be serialized by the class serializer.
39
39
 
40
40
  // The type casting below isn't pretty, but works for now...
41
41
  return ClassSerializer.serialize(value as unknown as SerializableObject);
@@ -0,0 +1,12 @@
1
+
2
+ import Component from '../../../core/types/Component.js';
3
+
4
+ export default class InvalidPropertyType extends Error
5
+ {
6
+ constructor(typeName: string, propertyName: string, expectedType: string)
7
+ {
8
+ super(`The ${typeName} property '${propertyName}' has an invalid type (expected '${expectedType}')`);
9
+ }
10
+ }
11
+
12
+ (InvalidPropertyType as Component).source = '/jitar/runtime/serialization/errors/InvalidPropertyType.js';
@@ -3,6 +3,7 @@ import { Controller, Get, Post } from '@overnightjs/core';
3
3
  import { Request, Response } from 'express';
4
4
  import { Logger } from 'tslog';
5
5
 
6
+ import ClientId from '../../runtime/ClientId.js';
6
7
  import LocalRepository from '../../runtime/LocalRepository.js';
7
8
  import Proxy from '../../runtime/Proxy.js';
8
9
  import ValueSerializer from '../../runtime/serialization/ValueSerializer.js';
@@ -22,6 +23,11 @@ export default class ModulesController
22
23
  @Post()
23
24
  async registerClient(request: Request, response: Response): Promise<Response>
24
25
  {
26
+ if ((request.body instanceof Array) === false)
27
+ {
28
+ // TODO: Throw error.
29
+ }
30
+
25
31
  const segmentFiles = request.body as string[];
26
32
 
27
33
  const clientId = await this.#repository.registerClient(segmentFiles);
@@ -36,6 +42,11 @@ export default class ModulesController
36
42
  {
37
43
  const clientId = request.params.clientId;
38
44
 
45
+ if (typeof clientId !== 'string' || ClientId.validate(clientId) === false)
46
+ {
47
+ return response.status(400).send('Invalid client id.');
48
+ }
49
+
39
50
  const pathKey = `/${clientId}/`;
40
51
  const pathIndex = request.path.indexOf(pathKey) + pathKey.length;
41
52
  const filename = request.path.substring(pathIndex);
@@ -0,0 +1,43 @@
1
+
2
+ import ClientId from '../../src/runtime/ClientId';
3
+
4
+ describe('runtime/ClientId', () =>
5
+ {
6
+ describe('.generate()', () =>
7
+ {
8
+ it('should generate a client id', () =>
9
+ {
10
+ const clientId = ClientId.generate();
11
+
12
+ expect(clientId).toMatch(/^CLIENT_\d+$/);
13
+ });
14
+
15
+ it('should generate a different client id each time', () =>
16
+ {
17
+ const clientId1 = ClientId.generate();
18
+ const clientId2 = ClientId.generate();
19
+
20
+ expect(clientId1).not.toBe(clientId2);
21
+ });
22
+ });
23
+
24
+ describe('.validate(clientId)', () =>
25
+ {
26
+ it('should return true if the client id is valid', () =>
27
+ {
28
+ expect(ClientId.validate('CLIENT_0')).toBe(true);
29
+ expect(ClientId.validate('CLIENT_42')).toBe(true);
30
+ expect(ClientId.validate('CLIENT_007')).toBe(true);
31
+ });
32
+
33
+ it('should return false if the client id is invalid', () =>
34
+ {
35
+ expect(ClientId.validate('CLIENT_')).toBe(false);
36
+ expect(ClientId.validate('CLIENT_X')).toBe(false);
37
+ expect(ClientId.validate('CLIENT_0a')).toBe(false);
38
+ expect(ClientId.validate('CLIENT_0.1')).toBe(false);
39
+ expect(ClientId.validate('Client_0')).toBe(false);
40
+ expect(ClientId.validate('SERVER_0')).toBe(false);
41
+ });
42
+ });
43
+ });
@@ -21,9 +21,9 @@ describe('runtime/LocalRepository', () =>
21
21
 
22
22
  it('should not accept an unknown client id', () =>
23
23
  {
24
- const run = async () => await repository.loadModule('CLIENT_X', '/some/file');
24
+ const run = async () => await repository.loadModule('CLIENT_9999', '/some/file');
25
25
 
26
- expect(run).rejects.toEqual(new ClientNotFound('CLIENT_X'));
26
+ expect(run).rejects.toEqual(new ClientNotFound('CLIENT_9999'));
27
27
  });
28
28
 
29
29
  it('should return an unsegmented module file', async () =>
@@ -81,7 +81,7 @@ describe('serialization/ValueSerializer', () =>
81
81
 
82
82
  it('should serialize error', () =>
83
83
  {
84
- const error = ValueSerializer.serialize(errorClass) as any;
84
+ const error = ValueSerializer.serialize(errorClass) as unknown;
85
85
 
86
86
  expect(error).toEqual(serializedError);
87
87
  });