@hotmeshio/hotmesh 0.0.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 (263) hide show
  1. package/LICENSE +214 -0
  2. package/README.md +241 -0
  3. package/build/index.d.ts +4 -0
  4. package/build/index.js +7 -0
  5. package/build/modules/errors.d.ts +28 -0
  6. package/build/modules/errors.js +50 -0
  7. package/build/modules/key.d.ts +75 -0
  8. package/build/modules/key.js +116 -0
  9. package/build/modules/utils.d.ts +34 -0
  10. package/build/modules/utils.js +173 -0
  11. package/build/package.json +73 -0
  12. package/build/services/activities/activity.d.ts +59 -0
  13. package/build/services/activities/activity.js +396 -0
  14. package/build/services/activities/await.d.ts +16 -0
  15. package/build/services/activities/await.js +143 -0
  16. package/build/services/activities/emit.d.ts +9 -0
  17. package/build/services/activities/emit.js +13 -0
  18. package/build/services/activities/index.d.ts +15 -0
  19. package/build/services/activities/index.js +16 -0
  20. package/build/services/activities/iterate.d.ts +9 -0
  21. package/build/services/activities/iterate.js +13 -0
  22. package/build/services/activities/trigger.d.ts +22 -0
  23. package/build/services/activities/trigger.js +161 -0
  24. package/build/services/activities/worker.d.ts +17 -0
  25. package/build/services/activities/worker.js +164 -0
  26. package/build/services/collator/index.d.ts +54 -0
  27. package/build/services/collator/index.js +171 -0
  28. package/build/services/compiler/deployer.d.ts +35 -0
  29. package/build/services/compiler/deployer.js +412 -0
  30. package/build/services/compiler/index.d.ts +30 -0
  31. package/build/services/compiler/index.js +111 -0
  32. package/build/services/compiler/validator.d.ts +32 -0
  33. package/build/services/compiler/validator.js +134 -0
  34. package/build/services/connector/clients/ioredis.d.ts +13 -0
  35. package/build/services/connector/clients/ioredis.js +50 -0
  36. package/build/services/connector/clients/redis.d.ts +13 -0
  37. package/build/services/connector/clients/redis.js +62 -0
  38. package/build/services/connector/index.d.ts +5 -0
  39. package/build/services/connector/index.js +31 -0
  40. package/build/services/dimension/index.d.ts +29 -0
  41. package/build/services/dimension/index.js +35 -0
  42. package/build/services/durable/asyncLocalStorage.d.ts +3 -0
  43. package/build/services/durable/asyncLocalStorage.js +5 -0
  44. package/build/services/durable/client.d.ts +15 -0
  45. package/build/services/durable/client.js +108 -0
  46. package/build/services/durable/connection.d.ts +4 -0
  47. package/build/services/durable/connection.js +51 -0
  48. package/build/services/durable/factory.d.ts +3 -0
  49. package/build/services/durable/factory.js +123 -0
  50. package/build/services/durable/handle.d.ts +8 -0
  51. package/build/services/durable/handle.js +38 -0
  52. package/build/services/durable/index.d.ts +57 -0
  53. package/build/services/durable/index.js +58 -0
  54. package/build/services/durable/native.d.ts +4 -0
  55. package/build/services/durable/native.js +47 -0
  56. package/build/services/durable/worker.d.ts +36 -0
  57. package/build/services/durable/worker.js +266 -0
  58. package/build/services/durable/workflow.d.ts +6 -0
  59. package/build/services/durable/workflow.js +135 -0
  60. package/build/services/engine/index.d.ts +82 -0
  61. package/build/services/engine/index.js +511 -0
  62. package/build/services/hotmesh/index.d.ts +45 -0
  63. package/build/services/hotmesh/index.js +134 -0
  64. package/build/services/logger/index.d.ts +17 -0
  65. package/build/services/logger/index.js +73 -0
  66. package/build/services/mapper/index.d.ts +24 -0
  67. package/build/services/mapper/index.js +72 -0
  68. package/build/services/pipe/functions/array.d.ts +24 -0
  69. package/build/services/pipe/functions/array.js +69 -0
  70. package/build/services/pipe/functions/bitwise.d.ts +9 -0
  71. package/build/services/pipe/functions/bitwise.js +24 -0
  72. package/build/services/pipe/functions/conditional.d.ts +10 -0
  73. package/build/services/pipe/functions/conditional.js +27 -0
  74. package/build/services/pipe/functions/date.d.ts +57 -0
  75. package/build/services/pipe/functions/date.js +167 -0
  76. package/build/services/pipe/functions/index.d.ts +25 -0
  77. package/build/services/pipe/functions/index.js +26 -0
  78. package/build/services/pipe/functions/json.d.ts +5 -0
  79. package/build/services/pipe/functions/json.js +12 -0
  80. package/build/services/pipe/functions/math.d.ts +38 -0
  81. package/build/services/pipe/functions/math.js +111 -0
  82. package/build/services/pipe/functions/number.d.ts +25 -0
  83. package/build/services/pipe/functions/number.js +133 -0
  84. package/build/services/pipe/functions/object.d.ts +22 -0
  85. package/build/services/pipe/functions/object.js +63 -0
  86. package/build/services/pipe/functions/string.d.ts +23 -0
  87. package/build/services/pipe/functions/string.js +69 -0
  88. package/build/services/pipe/functions/symbol.d.ts +12 -0
  89. package/build/services/pipe/functions/symbol.js +33 -0
  90. package/build/services/pipe/functions/unary.d.ts +7 -0
  91. package/build/services/pipe/functions/unary.js +18 -0
  92. package/build/services/pipe/index.d.ts +30 -0
  93. package/build/services/pipe/index.js +128 -0
  94. package/build/services/quorum/index.d.ts +34 -0
  95. package/build/services/quorum/index.js +147 -0
  96. package/build/services/reporter/index.d.ts +47 -0
  97. package/build/services/reporter/index.js +330 -0
  98. package/build/services/serializer/index.d.ts +36 -0
  99. package/build/services/serializer/index.js +222 -0
  100. package/build/services/signaler/store.d.ts +15 -0
  101. package/build/services/signaler/store.js +53 -0
  102. package/build/services/signaler/stream.d.ts +43 -0
  103. package/build/services/signaler/stream.js +317 -0
  104. package/build/services/store/cache.d.ts +66 -0
  105. package/build/services/store/cache.js +127 -0
  106. package/build/services/store/clients/ioredis.d.ts +27 -0
  107. package/build/services/store/clients/ioredis.js +96 -0
  108. package/build/services/store/clients/redis.d.ts +29 -0
  109. package/build/services/store/clients/redis.js +143 -0
  110. package/build/services/store/index.d.ts +88 -0
  111. package/build/services/store/index.js +657 -0
  112. package/build/services/stream/clients/ioredis.d.ts +23 -0
  113. package/build/services/stream/clients/ioredis.js +115 -0
  114. package/build/services/stream/clients/redis.d.ts +23 -0
  115. package/build/services/stream/clients/redis.js +119 -0
  116. package/build/services/stream/index.d.ts +21 -0
  117. package/build/services/stream/index.js +9 -0
  118. package/build/services/sub/clients/ioredis.d.ts +20 -0
  119. package/build/services/sub/clients/ioredis.js +72 -0
  120. package/build/services/sub/clients/redis.d.ts +20 -0
  121. package/build/services/sub/clients/redis.js +63 -0
  122. package/build/services/sub/index.d.ts +18 -0
  123. package/build/services/sub/index.js +9 -0
  124. package/build/services/task/index.d.ts +18 -0
  125. package/build/services/task/index.js +73 -0
  126. package/build/services/telemetry/index.d.ts +49 -0
  127. package/build/services/telemetry/index.js +223 -0
  128. package/build/services/worker/index.d.ts +30 -0
  129. package/build/services/worker/index.js +105 -0
  130. package/build/types/activity.d.ts +86 -0
  131. package/build/types/activity.js +2 -0
  132. package/build/types/app.d.ts +16 -0
  133. package/build/types/app.js +2 -0
  134. package/build/types/async.d.ts +5 -0
  135. package/build/types/async.js +2 -0
  136. package/build/types/cache.d.ts +1 -0
  137. package/build/types/cache.js +2 -0
  138. package/build/types/collator.d.ts +8 -0
  139. package/build/types/collator.js +11 -0
  140. package/build/types/durable.d.ts +59 -0
  141. package/build/types/durable.js +2 -0
  142. package/build/types/hook.d.ts +31 -0
  143. package/build/types/hook.js +9 -0
  144. package/build/types/hotmesh.d.ts +82 -0
  145. package/build/types/hotmesh.js +2 -0
  146. package/build/types/index.d.ts +20 -0
  147. package/build/types/index.js +21 -0
  148. package/build/types/ioredisclient.d.ts +5 -0
  149. package/build/types/ioredisclient.js +5 -0
  150. package/build/types/job.d.ts +50 -0
  151. package/build/types/job.js +2 -0
  152. package/build/types/logger.d.ts +6 -0
  153. package/build/types/logger.js +2 -0
  154. package/build/types/map.d.ts +4 -0
  155. package/build/types/map.js +2 -0
  156. package/build/types/pipe.d.ts +4 -0
  157. package/build/types/pipe.js +2 -0
  158. package/build/types/quorum.d.ts +46 -0
  159. package/build/types/quorum.js +2 -0
  160. package/build/types/redis.d.ts +8 -0
  161. package/build/types/redis.js +2 -0
  162. package/build/types/redisclient.d.ts +25 -0
  163. package/build/types/redisclient.js +2 -0
  164. package/build/types/serializer.d.ts +33 -0
  165. package/build/types/serializer.js +2 -0
  166. package/build/types/stats.d.ts +83 -0
  167. package/build/types/stats.js +2 -0
  168. package/build/types/stream.d.ts +67 -0
  169. package/build/types/stream.js +25 -0
  170. package/build/types/telemetry.d.ts +1 -0
  171. package/build/types/telemetry.js +11 -0
  172. package/build/types/transition.d.ts +17 -0
  173. package/build/types/transition.js +2 -0
  174. package/index.ts +5 -0
  175. package/modules/errors.ts +55 -0
  176. package/modules/key.ts +129 -0
  177. package/modules/utils.ts +170 -0
  178. package/package.json +73 -0
  179. package/services/activities/activity.ts +473 -0
  180. package/services/activities/await.ts +172 -0
  181. package/services/activities/emit.ts +25 -0
  182. package/services/activities/index.ts +15 -0
  183. package/services/activities/iterate.ts +26 -0
  184. package/services/activities/trigger.ts +196 -0
  185. package/services/activities/worker.ts +190 -0
  186. package/services/collator/README.md +102 -0
  187. package/services/collator/index.ts +182 -0
  188. package/services/compiler/deployer.ts +432 -0
  189. package/services/compiler/index.ts +98 -0
  190. package/services/compiler/validator.ts +154 -0
  191. package/services/connector/clients/ioredis.ts +57 -0
  192. package/services/connector/clients/redis.ts +72 -0
  193. package/services/connector/index.ts +44 -0
  194. package/services/dimension/README.md +73 -0
  195. package/services/dimension/index.ts +39 -0
  196. package/services/durable/asyncLocalStorage.ts +3 -0
  197. package/services/durable/client.ts +116 -0
  198. package/services/durable/connection.ts +50 -0
  199. package/services/durable/factory.ts +124 -0
  200. package/services/durable/handle.ts +43 -0
  201. package/services/durable/index.ts +60 -0
  202. package/services/durable/native.ts +46 -0
  203. package/services/durable/worker.ts +254 -0
  204. package/services/durable/workflow.ts +136 -0
  205. package/services/engine/index.ts +615 -0
  206. package/services/hotmesh/index.ts +182 -0
  207. package/services/logger/index.ts +79 -0
  208. package/services/mapper/index.ts +84 -0
  209. package/services/pipe/functions/array.ts +87 -0
  210. package/services/pipe/functions/bitwise.ts +27 -0
  211. package/services/pipe/functions/conditional.ts +31 -0
  212. package/services/pipe/functions/date.ts +214 -0
  213. package/services/pipe/functions/index.ts +25 -0
  214. package/services/pipe/functions/json.ts +11 -0
  215. package/services/pipe/functions/math.ts +143 -0
  216. package/services/pipe/functions/number.ts +150 -0
  217. package/services/pipe/functions/object.ts +79 -0
  218. package/services/pipe/functions/string.ts +86 -0
  219. package/services/pipe/functions/symbol.ts +39 -0
  220. package/services/pipe/functions/unary.ts +19 -0
  221. package/services/pipe/index.ts +138 -0
  222. package/services/quorum/index.ts +200 -0
  223. package/services/reporter/index.ts +379 -0
  224. package/services/serializer/README.md +10 -0
  225. package/services/serializer/index.ts +243 -0
  226. package/services/signaler/store.ts +61 -0
  227. package/services/signaler/stream.ts +354 -0
  228. package/services/store/cache.ts +172 -0
  229. package/services/store/clients/ioredis.ts +123 -0
  230. package/services/store/clients/redis.ts +169 -0
  231. package/services/store/index.ts +757 -0
  232. package/services/stream/clients/ioredis.ts +148 -0
  233. package/services/stream/clients/redis.ts +144 -0
  234. package/services/stream/index.ts +57 -0
  235. package/services/sub/clients/ioredis.ts +83 -0
  236. package/services/sub/clients/redis.ts +74 -0
  237. package/services/sub/index.ts +25 -0
  238. package/services/task/index.ts +86 -0
  239. package/services/telemetry/index.ts +267 -0
  240. package/services/worker/index.ts +165 -0
  241. package/types/activity.ts +115 -0
  242. package/types/app.ts +20 -0
  243. package/types/async.ts +7 -0
  244. package/types/cache.ts +1 -0
  245. package/types/collator.ts +9 -0
  246. package/types/durable.ts +81 -0
  247. package/types/hook.ts +32 -0
  248. package/types/hotmesh.ts +102 -0
  249. package/types/index.ts +138 -0
  250. package/types/ioredisclient.ts +10 -0
  251. package/types/job.ts +59 -0
  252. package/types/logger.ts +6 -0
  253. package/types/map.ts +5 -0
  254. package/types/ms.d.ts +7 -0
  255. package/types/pipe.ts +7 -0
  256. package/types/quorum.ts +59 -0
  257. package/types/redis.ts +27 -0
  258. package/types/redisclient.ts +29 -0
  259. package/types/serializer.ts +38 -0
  260. package/types/stats.ts +100 -0
  261. package/types/stream.ts +75 -0
  262. package/types/telemetry.ts +15 -0
  263. package/types/transition.ts +20 -0
@@ -0,0 +1,182 @@
1
+ import { nanoid } from 'nanoid';
2
+ import { PSNS } from '../../modules/key';
3
+ import { EngineService } from '../engine';
4
+ import { LoggerService, ILogger } from '../logger';
5
+ import { StreamSignaler } from '../signaler/stream';
6
+ import { QuorumService } from '../quorum';
7
+ import { WorkerService } from '../worker';
8
+ import {
9
+ JobState,
10
+ JobData,
11
+ JobOutput,
12
+ JobStatus } from '../../types/job';
13
+ import {
14
+ HotMeshConfig,
15
+ HotMeshManifest } from '../../types/hotmesh';
16
+ import { JobMessageCallback } from '../../types/quorum';
17
+ import {
18
+ JobStatsInput,
19
+ GetStatsOptions,
20
+ IdsResponse,
21
+ StatsResponse } from '../../types/stats';
22
+ import { ConnectorService } from '../connector';
23
+ import { StreamData, StreamDataResponse } from '../../types/stream';
24
+
25
+ class HotMeshService {
26
+ namespace: string;
27
+ appId: string;
28
+ guid: string;
29
+ engine: EngineService | null = null;
30
+ quorum: QuorumService | null = null;
31
+ workers: WorkerService[] = [];
32
+ logger: ILogger;
33
+
34
+ verifyAndSetNamespace(namespace?: string) {
35
+ if (!namespace) {
36
+ this.namespace = PSNS;
37
+ } else if (!namespace.match(/^[A-Za-z0-9-]+$/)) {
38
+ throw new Error(`config.namespace [${namespace}] is invalid`);
39
+ } else {
40
+ this.namespace = namespace;
41
+ }
42
+ }
43
+
44
+ verifyAndSetAppId(appId: string) {
45
+ if (!appId?.match(/^[A-Za-z0-9-]+$/)) {
46
+ throw new Error(`config.appId [${appId}] is invalid`);
47
+ } else if (appId === 'a') {
48
+ throw new Error(`config.appId [${appId}] is reserved`);
49
+ } else {
50
+ this.appId = appId;
51
+ }
52
+ }
53
+
54
+ static async init(config: HotMeshConfig) {
55
+ const instance = new HotMeshService();
56
+ instance.guid = nanoid();
57
+ instance.verifyAndSetNamespace(config.namespace);
58
+ instance.verifyAndSetAppId(config.appId);
59
+ instance.logger = new LoggerService(config.appId, instance.guid, config.name || '', config.logLevel);
60
+ await instance.initEngine(config, instance.logger);
61
+ await instance.initQuorum(config, instance.engine, instance.logger);
62
+ await instance.initWorkers(config, instance.logger);
63
+ return instance;
64
+ }
65
+
66
+ async initEngine(config: HotMeshConfig, logger: ILogger): Promise<void> {
67
+ if (config.engine) {
68
+ await ConnectorService.initRedisClients(
69
+ config.engine.redis?.class,
70
+ config.engine.redis?.options,
71
+ config.engine,
72
+ );
73
+ this.engine = await EngineService.init(
74
+ this.namespace,
75
+ this.appId,
76
+ this.guid,
77
+ config,
78
+ logger,
79
+ );
80
+ }
81
+ }
82
+
83
+ async initQuorum(config: HotMeshConfig, engine: EngineService, logger: ILogger): Promise<void> {
84
+ if (engine) {
85
+ this.quorum = await QuorumService.init(
86
+ this.namespace,
87
+ this.appId,
88
+ this.guid,
89
+ config,
90
+ engine,
91
+ logger
92
+ );
93
+ }
94
+ }
95
+
96
+ async initWorkers(config: HotMeshConfig, logger: ILogger) {
97
+ this.workers = await WorkerService.init(
98
+ this.namespace,
99
+ this.appId,
100
+ this.guid,
101
+ config,
102
+ logger
103
+ );
104
+ }
105
+
106
+ // ************* PUB/SUB METHODS *************
107
+ async pub(topic: string, data: JobData = {}, context?: JobState) {
108
+ return await this.engine?.pub(topic, data, context);
109
+ }
110
+ async sub(topic: string, callback: JobMessageCallback): Promise<void> {
111
+ return await this.engine?.sub(topic, callback);
112
+ }
113
+ async unsub(topic: string): Promise<void> {
114
+ return await this.engine?.unsub(topic);
115
+ }
116
+ async psub(wild: string, callback: JobMessageCallback): Promise<void> {
117
+ return await this.engine?.psub(wild, callback);
118
+ }
119
+ async punsub(wild: string): Promise<void> {
120
+ return await this.engine?.punsub(wild);
121
+ }
122
+ async pubsub(topic: string, data: JobData = {}, context?: JobState | null, timeout?: number): Promise<JobOutput> {
123
+ return await this.engine?.pubsub(topic, data, context, timeout);
124
+ }
125
+ async add(streamData: StreamData|StreamDataResponse): Promise<string> {
126
+ return await this.engine.add(streamData) as string;
127
+ }
128
+
129
+ // ************* COMPILER METHODS *************
130
+ async plan(path: string): Promise<HotMeshManifest> {
131
+ return await this.engine?.plan(path);
132
+ }
133
+ async deploy(pathOrYAML: string): Promise<HotMeshManifest> {
134
+ return await this.engine?.deploy(pathOrYAML);
135
+ }
136
+ async activate(version: string, delay?: number): Promise<boolean> {
137
+ //activation is a quorum operation
138
+ return await this.quorum?.activate(version, delay);
139
+ }
140
+
141
+ // ************* REPORTER METHODS *************
142
+ async getStats(topic: string, query: JobStatsInput): Promise<StatsResponse> {
143
+ return await this.engine?.getStats(topic, query);
144
+ }
145
+ async getStatus(jobId: string): Promise<JobStatus> {
146
+ return this.engine?.getStatus(jobId);
147
+ }
148
+ async getState(topic: string, jobId: string) {
149
+ return this.engine?.getState(topic, jobId);
150
+ }
151
+ async getIds(topic: string, query: JobStatsInput, queryFacets = []): Promise<IdsResponse> {
152
+ return await this.engine?.getIds(topic, query, queryFacets);
153
+ }
154
+ async resolveQuery(topic: string, query: JobStatsInput): Promise<GetStatsOptions> {
155
+ return await this.engine?.resolveQuery(topic, query);
156
+ }
157
+
158
+ // ****************** `SCRUB` CLEAN COMPLETED JOBS *****************
159
+ async scrub(jobId: string) {
160
+ await this.engine?.scrub(jobId);
161
+ }
162
+
163
+ // ****** `HOOK` ACTIVITY RE-ENTRY POINT ******
164
+ async hook(topic: string, data: JobData): Promise<JobStatus | void> {
165
+ //return collation int
166
+ return await this.engine?.hook(topic, data);
167
+ }
168
+ async hookAll(hookTopic: string, data: JobData, query: JobStatsInput, queryFacets: string[] = []): Promise<string[]> {
169
+ return await this.engine?.hookAll(hookTopic, data, query, queryFacets);
170
+ }
171
+
172
+ async stop() {
173
+ await StreamSignaler.stopConsuming();
174
+ this.engine?.task.cancelCleanup();
175
+ }
176
+
177
+ async compress(terms: string[]): Promise<boolean> {
178
+ return await this.engine?.compress(terms);
179
+ }
180
+ }
181
+
182
+ export { HotMeshService };
@@ -0,0 +1,79 @@
1
+ import { Logger, createLogger, transports, format } from 'winston';
2
+ import { ILogger } from '../../types/logger';
3
+
4
+ class LoggerService implements ILogger {
5
+ private logger: Logger;
6
+
7
+ constructor(private appId: string = 'appId', private instanceId: string = 'instanceId', private name: string = 'name', private logLevel: string = 'info', customLogger?: Logger) {
8
+ this.logger = customLogger || this.createDefaultLogger();
9
+ }
10
+
11
+ private createDefaultLogger(): Logger {
12
+ return createLogger({
13
+ level: this.logLevel,
14
+ format: format.combine(
15
+ format.colorize(),
16
+ format.timestamp(),
17
+ format.printf((info) => {
18
+ const { timestamp, level, message } = info;
19
+ // Extract the object from the `info` object's `Symbol(splat)` field
20
+ const symbols = Object.getOwnPropertySymbols(info);
21
+ const splatSymbol = symbols.find(symbol => symbol.toString() === 'Symbol(splat)');
22
+ let splatData = {};
23
+ if (splatSymbol) {
24
+ splatData = info[splatSymbol][0] || {};
25
+ }
26
+ // Pass it to the `tagify` method
27
+ const tags = this.tagify(splatData);
28
+
29
+ return `${timestamp} [${level}] [${this.name || this.appId}:${this.instanceId}] ${message} ${tags}`;
30
+ }),
31
+ ),
32
+ transports: [new transports.Console()],
33
+ });
34
+ }
35
+
36
+ info(message: string, ...meta: any[]): void {
37
+ this.logger.info(message, ...meta);
38
+ }
39
+
40
+ error(message: string, ...meta: any[]): void {
41
+ this.logger.error(message, ...meta);
42
+ }
43
+
44
+ warn(message: string, ...meta: any[]): void {
45
+ this.logger.warn(message, ...meta);
46
+ }
47
+
48
+ debug(message: string, ...meta: any[]): void {
49
+ this.logger.debug(message, ...meta);
50
+ }
51
+
52
+ tagify(obj: Record<string, unknown>): string {
53
+ if (!obj) {
54
+ return '';
55
+ }
56
+ const tags: string[] = [];
57
+ try {
58
+ Object.entries(obj).forEach(([key, val]) => {
59
+ let value: any = val;
60
+ if (typeof val === 'function') {
61
+ val = val();
62
+ }
63
+ if (val instanceof Date) {
64
+ value = val.toISOString();
65
+ } else if (typeof val === 'object' && val !== null) {
66
+ value = JSON.stringify(val);
67
+ } else {
68
+ value = value ? value.toString() : value;
69
+ }
70
+ tags.push(`${key}:${value}`);
71
+ });
72
+ } catch (err) {
73
+ this.error('tagify-error', err);
74
+ }
75
+ return tags.join(' ');
76
+ }
77
+ }
78
+
79
+ export { LoggerService, ILogger };
@@ -0,0 +1,84 @@
1
+ import { matchesStatus, matchesStatusCode } from "../../modules/utils";
2
+ import { Pipe } from "../pipe";
3
+ import { JobState } from "../../types/job";
4
+ import { Pipe as PipeType } from "../../types/pipe";
5
+ import { TransitionMatch, TransitionRule } from "../../types/transition";
6
+ import { StreamCode, StreamStatus } from "../../types";
7
+
8
+ type RuleType = null | undefined | boolean | string | number | Date | Record<string, any>;
9
+
10
+ class MapperService {
11
+ private rules: Record<string, unknown>;
12
+ private data: JobState;
13
+
14
+ constructor(rules: Record<string, unknown>, data: JobState) {
15
+ this.rules = rules;
16
+ this.data = data;
17
+ }
18
+
19
+ public mapRules(): Record<string, unknown> {
20
+ return this.traverseRules(this.rules);
21
+ }
22
+
23
+ private traverseRules(rules: RuleType): Record<string, unknown> {
24
+ if (typeof rules === 'object' && '@pipe' in rules) {
25
+ return this.pipe(rules['@pipe'] as PipeType);
26
+ } if (typeof rules === 'object' && rules !== null) {
27
+ const mappedRules: Record<string, any> = {};
28
+ for (const key in rules) {
29
+ if (Object.prototype.hasOwnProperty.call(rules, key)) {
30
+ mappedRules[key] = this.traverseRules(rules[key]);
31
+ }
32
+ }
33
+ return mappedRules;
34
+ } else {
35
+ return this.resolve(rules);
36
+ }
37
+ }
38
+
39
+ /**
40
+ * resolve a pipe expression of the form: { @pipe: [["{data.foo.bar}", 2, false, "hello world"]] }
41
+ * @param value
42
+ * @returns
43
+ */
44
+ private pipe(value: PipeType): any {
45
+ const pipe = new Pipe(value, this.data);
46
+ return pipe.process();
47
+ }
48
+
49
+ /**
50
+ * resolve a simple mapping expression in the form: "{data.foo.bar}" or 2 or false or "hello world"
51
+ * @param value
52
+ * @returns
53
+ */
54
+ private resolve(value: any): any {
55
+ const pipe = new Pipe([[value]], this.data);
56
+ return pipe.process();
57
+ }
58
+
59
+ static evaluate(transitionRule: TransitionRule | boolean, context: JobState, code: StreamCode): boolean {
60
+ if (typeof transitionRule === 'boolean') {
61
+ return transitionRule;
62
+ }
63
+ if (code.toString() === (transitionRule.code || 200).toString()) {
64
+ const orGate = transitionRule.gate === 'or';
65
+ let allAreTrue = true;
66
+ let someAreTrue = false;
67
+ transitionRule.match.forEach(({ expected, actual }: TransitionMatch) => {
68
+ if ((orGate && !someAreTrue) || (!orGate && allAreTrue)) {
69
+ const result = Pipe.resolve(actual, context) === expected;
70
+ if (orGate && result) {
71
+ someAreTrue = true;
72
+ } else if(!orGate && !result) {
73
+ allAreTrue = false;
74
+ }
75
+ }
76
+ });
77
+ return orGate ? someAreTrue : allAreTrue;
78
+ }
79
+ return false;
80
+ }
81
+ }
82
+
83
+
84
+ export { MapperService }
@@ -0,0 +1,87 @@
1
+ class ArrayHandler {
2
+ get(array: any[], index: number): any {
3
+ return array[index];
4
+ }
5
+
6
+ concat(array1: any[], array2: any[]): any[] {
7
+ return array1.concat(array2);
8
+ }
9
+
10
+ every(array: any[], callback: (value: any, index: number, array: any[]) => boolean): boolean {
11
+ return array.every(callback);
12
+ }
13
+
14
+ filter(array: any[], callback: (value: any, index: number, array: any[]) => boolean): any[] {
15
+ return array.filter(callback);
16
+ }
17
+
18
+ find(array: any[], callback: (value: any, index: number, array: any[]) => boolean): any {
19
+ return array.find(callback);
20
+ }
21
+
22
+ findIndex(array: any[], callback: (value: any, index: number, array: any[]) => boolean): number {
23
+ return array.findIndex(callback);
24
+ }
25
+
26
+ forEach(array: any[], callback: (value: any, index: number, array: any[]) => void): void {
27
+ array.forEach(callback);
28
+ }
29
+
30
+ indexOf(array: any[], searchElement: any, fromIndex?: number): number {
31
+ return array.indexOf(searchElement, fromIndex);
32
+ }
33
+
34
+ join(array: any[], separator: string): string {
35
+ return array.join(separator);
36
+ }
37
+
38
+ lastIndexOf(array: any[], searchElement: any, fromIndex?: number): number {
39
+ return array.lastIndexOf(searchElement, fromIndex);
40
+ }
41
+
42
+ map(array: any[], callback: (value: any, index: number, array: any[]) => any): any[] {
43
+ return array.map(callback);
44
+ }
45
+
46
+ pop(array: any[]): any {
47
+ return array.pop();
48
+ }
49
+
50
+ push(array: any[], ...items: any[]): number {
51
+ return array.push(...items);
52
+ }
53
+
54
+ reduce(array: any[], callback: (accumulator: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue?: any): any {
55
+ return array.reduce(callback, initialValue);
56
+ }
57
+
58
+ reverse(array: any[]): any[] {
59
+ return array.reverse();
60
+ }
61
+
62
+ shift(array: any[]): any {
63
+ return array.shift();
64
+ }
65
+
66
+ slice(array: any[], start?: number, end?: number): any[] {
67
+ return array.slice(start, end);
68
+ }
69
+
70
+ some(array: any[], callback: (value: any, index: number, array: any[]) => boolean): boolean {
71
+ return array.some(callback);
72
+ }
73
+
74
+ sort(array: any[], compareFunction?: (a: any, b: any) => number): any[] {
75
+ return array.sort(compareFunction);
76
+ }
77
+
78
+ splice(array: any[], start: number, deleteCount?: number, ...items: any[]): any[] {
79
+ return array.splice(start, deleteCount, ...items);
80
+ }
81
+
82
+ unshift(array: any[], ...items: any[]): number {
83
+ return array.unshift(...items);
84
+ }
85
+ }
86
+
87
+ export { ArrayHandler };
@@ -0,0 +1,27 @@
1
+ class BitwiseHandler {
2
+ and(a: number, b: number): number {
3
+ return a & b;
4
+ }
5
+
6
+ or(a: number, b: number): number {
7
+ return a | b;
8
+ }
9
+
10
+ xor(a: number, b: number): number {
11
+ return a ^ b;
12
+ }
13
+
14
+ leftShift(a: number, b: number): number {
15
+ return a << b;
16
+ }
17
+
18
+ rightShift(a: number, b: number): number {
19
+ return a >> b;
20
+ }
21
+
22
+ unsignedRightShift(a: number, b: number): number {
23
+ return a >>> b;
24
+ }
25
+ }
26
+
27
+ export { BitwiseHandler };
@@ -0,0 +1,31 @@
1
+ class ConditionalHandler {
2
+ ternary(condition: boolean, valueIfTrue: any, valueIfFalse: any): any {
3
+ return condition ? valueIfTrue : valueIfFalse;
4
+ }
5
+
6
+ equality(value1: any, value2: any): boolean {
7
+ return value1 == value2;
8
+ }
9
+
10
+ strict_equality(value1: any, value2: any): boolean {
11
+ return value1 === value2;
12
+ }
13
+
14
+ greater_than(value1: number, value2: number): boolean {
15
+ return value1 > value2;
16
+ }
17
+
18
+ less_than(value1: number, value2: number): boolean {
19
+ return value1 < value2;
20
+ }
21
+
22
+ greater_than_or_equal(value1: number, value2: number): boolean {
23
+ return value1 >= value2;
24
+ }
25
+
26
+ less_than_or_equal(value1: number, value2: number): boolean {
27
+ return value1 <= value2;
28
+ }
29
+ }
30
+
31
+ export { ConditionalHandler };
@@ -0,0 +1,214 @@
1
+ type DateInput = Date | string | number;
2
+
3
+ class DateHandler {
4
+
5
+ /**
6
+ * It is so common in mapping operations to use a string (ISO) date as input. This helper
7
+ * method allows for a more-concise mapping ruleset by avoiding date initialization boilerplate
8
+ * code and instead handles the ISO, Milliseconds, and ECMAScript Date input types.
9
+ * @param input
10
+ * @returns
11
+ */
12
+ static getDateInstance(input: DateInput): Date {
13
+ const ISO_REGEX = /^\d{4}-\d{2}-\d{2}(?:T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z)?$/;
14
+
15
+ if (typeof input === 'string') {
16
+ if (ISO_REGEX.test(input)) {
17
+ return new Date(input);
18
+ }
19
+
20
+ const milliseconds = parseInt(input, 10);
21
+ if (!isNaN(milliseconds)) {
22
+ return new Date(milliseconds);
23
+ }
24
+ } else if (input instanceof Date) {
25
+ return input;
26
+ } else if (typeof input === 'number') {
27
+ return new Date(input);
28
+ }
29
+
30
+ throw new Error("Invalid date format");
31
+ }
32
+
33
+ fromISOString(isoString: string): Date {
34
+ return new Date(isoString);
35
+ }
36
+
37
+ now(): number {
38
+ return Date.now();
39
+ }
40
+
41
+ parse(dateString: string): number {
42
+ return Date.parse(dateString);
43
+ }
44
+
45
+ getDate(date: DateInput): number {
46
+ return DateHandler.getDateInstance(date).getDate();
47
+ }
48
+
49
+ getDay(date: DateInput): number {
50
+ return DateHandler.getDateInstance(date).getDay();
51
+ }
52
+
53
+ getFullYear(date: DateInput): number {
54
+ return DateHandler.getDateInstance(date).getFullYear();
55
+ }
56
+
57
+ getHours(date: DateInput): number {
58
+ return DateHandler.getDateInstance(date).getHours();
59
+ }
60
+
61
+ getMilliseconds(date: DateInput): number {
62
+ return DateHandler.getDateInstance(date).getMilliseconds();
63
+ }
64
+
65
+ getMinutes(date: DateInput): number {
66
+ return DateHandler.getDateInstance(date).getMinutes();
67
+ }
68
+
69
+ getMonth(date: DateInput): number {
70
+ return DateHandler.getDateInstance(date).getMonth();
71
+ }
72
+
73
+ getSeconds(date: DateInput): number {
74
+ return DateHandler.getDateInstance(date).getSeconds();
75
+ }
76
+
77
+ getTime(date: DateInput): number {
78
+ return DateHandler.getDateInstance(date).getTime();
79
+ }
80
+
81
+ getTimezoneOffset(date: DateInput): number {
82
+ return DateHandler.getDateInstance(date).getTimezoneOffset();
83
+ }
84
+
85
+ getUTCDate(date: DateInput): number {
86
+ return DateHandler.getDateInstance(date).getUTCDate();
87
+ }
88
+
89
+ getUTCDay(date: DateInput): number {
90
+ return DateHandler.getDateInstance(date).getUTCDay();
91
+ }
92
+
93
+ getUTCFullYear(date: DateInput): number {
94
+ return DateHandler.getDateInstance(date).getUTCFullYear();
95
+ }
96
+
97
+ getUTCHours(date: DateInput): number {
98
+ return DateHandler.getDateInstance(date).getUTCHours();
99
+ }
100
+
101
+ getUTCMilliseconds(date: DateInput): number {
102
+ return DateHandler.getDateInstance(date).getUTCMilliseconds();
103
+ }
104
+
105
+ getUTCMinutes(date: DateInput): number {
106
+ return DateHandler.getDateInstance(date).getUTCMinutes();
107
+ }
108
+
109
+ getUTCMonth(date: DateInput): number {
110
+ return DateHandler.getDateInstance(date).getUTCMonth();
111
+ }
112
+
113
+ getUTCSeconds(date: DateInput): number {
114
+ return DateHandler.getDateInstance(date).getUTCSeconds();
115
+ }
116
+
117
+ setMilliseconds(date: DateInput, ms: number): number {
118
+ return DateHandler.getDateInstance(date).setMilliseconds(ms);
119
+ }
120
+
121
+ setMinutes(date: DateInput, minutes: number, seconds?: number, ms?: number): number {
122
+ return DateHandler.getDateInstance(date).setMinutes(minutes, seconds, ms);
123
+ }
124
+
125
+ setMonth(date: DateInput, month: number, day?: number): number {
126
+ return DateHandler.getDateInstance(date).setMonth(month, day);
127
+ }
128
+
129
+ setSeconds(date: DateInput, seconds: number, ms?: number): number {
130
+ return DateHandler.getDateInstance(date).setSeconds(seconds, ms);
131
+ }
132
+
133
+ setTime(date: DateInput, time: number): number {
134
+ return DateHandler.getDateInstance(date).setTime(time);
135
+ }
136
+
137
+ setUTCDate(date: DateInput, day: number): number {
138
+ return DateHandler.getDateInstance(date).setUTCDate(day);
139
+ }
140
+
141
+ setUTCFullYear(date: DateInput, year: number, month?: number, day?: number): number {
142
+ return DateHandler.getDateInstance(date).setUTCFullYear(year, month, day);
143
+ }
144
+
145
+ setUTCHours(date: DateInput, hours: number, minutes?: number, seconds?: number, ms?: number): number {
146
+ return DateHandler.getDateInstance(date).setUTCHours(hours, minutes, seconds, ms);
147
+ }
148
+
149
+ setUTCMilliseconds(date: DateInput, ms: number): number {
150
+ return DateHandler.getDateInstance(date).setUTCMilliseconds(ms);
151
+ }
152
+
153
+ setUTCMinutes(date: DateInput, minutes: number, seconds?: number, ms?: number): number {
154
+ return DateHandler.getDateInstance(date).setUTCMinutes(minutes, seconds, ms);
155
+ }
156
+
157
+ setUTCMonth(date: DateInput, month: number, day?: number): number {
158
+ return DateHandler.getDateInstance(date).setUTCMonth(month, day);
159
+ }
160
+
161
+ setUTCSeconds(date: DateInput, seconds: number, ms?: number): number {
162
+ return DateHandler.getDateInstance(date).setUTCSeconds(seconds, ms);
163
+ }
164
+
165
+ setDate(date: DateInput, day: number): number {
166
+ return DateHandler.getDateInstance(date).setDate(day);
167
+ }
168
+
169
+ setFullYear(date: DateInput, year: number, month?: number, day?: number): number {
170
+ return DateHandler.getDateInstance(date).setFullYear(year, month, day);
171
+ }
172
+
173
+ setHours(date: DateInput, hours: number, minutes?: number, seconds?: number, ms?: number): number {
174
+ return DateHandler.getDateInstance(date).setHours(hours, minutes, seconds, ms);
175
+ }
176
+ toDateString(date: DateInput): string {
177
+ return DateHandler.getDateInstance(date).toDateString();
178
+ }
179
+
180
+ toISOString(date: DateInput): string {
181
+ return DateHandler.getDateInstance(date).toISOString();
182
+ }
183
+
184
+ toJSON(date: DateInput): string {
185
+ return DateHandler.getDateInstance(date).toJSON();
186
+ }
187
+
188
+ toLocaleDateString(date: DateInput, locales?: string | string[], options?: Intl.DateTimeFormatOptions): string {
189
+ return DateHandler.getDateInstance(date).toLocaleDateString(locales, options);
190
+ }
191
+
192
+ toLocaleString(date: DateInput, locales?: string | string[], options?: Intl.DateTimeFormatOptions): string {
193
+ return DateHandler.getDateInstance(date).toLocaleString(locales, options);
194
+ }
195
+
196
+ toLocaleTimeString(date: DateInput, locales?: string | string[], options?: Intl.DateTimeFormatOptions): string {
197
+ return DateHandler.getDateInstance(date).toLocaleTimeString(locales, options);
198
+ }
199
+
200
+ toString(date: DateInput): string {
201
+ return DateHandler.getDateInstance(date).toString();
202
+ }
203
+
204
+ UTC(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): number {
205
+ return Date.UTC(year, month, date, hours, minutes, seconds, ms);
206
+ }
207
+
208
+ valueOf(date: DateInput): number {
209
+ return DateHandler.getDateInstance(date).valueOf();
210
+ }
211
+
212
+ }
213
+
214
+ export { DateHandler };