@hotmeshio/hotmesh 0.0.54 → 0.0.56

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 (182) hide show
  1. package/README.md +0 -3
  2. package/build/modules/enums.js +1 -10
  3. package/build/modules/key.d.ts +0 -38
  4. package/build/modules/key.js +4 -46
  5. package/build/modules/utils.d.ts +0 -8
  6. package/build/modules/utils.js +0 -14
  7. package/build/package.json +11 -4
  8. package/build/services/activities/activity.d.ts +0 -28
  9. package/build/services/activities/activity.js +1 -46
  10. package/build/services/activities/await.js +0 -4
  11. package/build/services/activities/cycle.d.ts +0 -7
  12. package/build/services/activities/cycle.js +1 -16
  13. package/build/services/activities/hook.d.ts +0 -6
  14. package/build/services/activities/hook.js +2 -12
  15. package/build/services/activities/interrupt.js +0 -8
  16. package/build/services/activities/signal.d.ts +0 -6
  17. package/build/services/activities/signal.js +0 -15
  18. package/build/services/activities/trigger.d.ts +0 -4
  19. package/build/services/activities/trigger.js +1 -7
  20. package/build/services/activities/worker.js +0 -4
  21. package/build/services/collator/index.d.ts +0 -70
  22. package/build/services/collator/index.js +1 -91
  23. package/build/services/compiler/deployer.js +6 -38
  24. package/build/services/compiler/index.d.ts +0 -15
  25. package/build/services/compiler/index.js +0 -20
  26. package/build/services/compiler/validator.d.ts +0 -3
  27. package/build/services/compiler/validator.js +0 -25
  28. package/build/services/connector/clients/ioredis.d.ts +2 -2
  29. package/build/services/connector/clients/ioredis.js +0 -2
  30. package/build/services/connector/clients/redis.d.ts +4 -4
  31. package/build/services/connector/clients/redis.js +1 -3
  32. package/build/services/connector/index.d.ts +1 -1
  33. package/build/services/connector/index.js +0 -2
  34. package/build/services/durable/client.d.ts +1 -26
  35. package/build/services/durable/client.js +0 -56
  36. package/build/services/durable/exporter.d.ts +0 -22
  37. package/build/services/durable/exporter.js +1 -30
  38. package/build/services/durable/handle.d.ts +0 -36
  39. package/build/services/durable/handle.js +0 -46
  40. package/build/services/durable/index.d.ts +0 -4
  41. package/build/services/durable/index.js +0 -4
  42. package/build/services/durable/schemas/factory.d.ts +0 -29
  43. package/build/services/durable/schemas/factory.js +0 -29
  44. package/build/services/durable/search.d.ts +1 -36
  45. package/build/services/durable/search.js +57 -56
  46. package/build/services/durable/worker.js +2 -22
  47. package/build/services/durable/workflow.d.ts +0 -114
  48. package/build/services/durable/workflow.js +4 -144
  49. package/build/services/engine/index.d.ts +1 -6
  50. package/build/services/engine/index.js +1 -43
  51. package/build/services/exporter/index.d.ts +0 -27
  52. package/build/services/exporter/index.js +0 -33
  53. package/build/services/hotmesh/index.d.ts +2 -2
  54. package/build/services/hotmesh/index.js +1 -9
  55. package/build/services/logger/index.js +0 -2
  56. package/build/services/mapper/index.d.ts +0 -14
  57. package/build/services/mapper/index.js +0 -14
  58. package/build/services/pipe/functions/date.d.ts +0 -7
  59. package/build/services/pipe/functions/date.js +0 -7
  60. package/build/services/pipe/functions/math.js +0 -2
  61. package/build/services/pipe/index.d.ts +0 -15
  62. package/build/services/pipe/index.js +2 -23
  63. package/build/services/quorum/index.d.ts +0 -7
  64. package/build/services/quorum/index.js +0 -21
  65. package/build/services/reporter/index.d.ts +0 -5
  66. package/build/services/reporter/index.js +0 -9
  67. package/build/services/router/index.d.ts +0 -9
  68. package/build/services/router/index.js +2 -38
  69. package/build/services/serializer/index.js +7 -26
  70. package/build/services/store/cache.d.ts +0 -18
  71. package/build/services/store/cache.js +0 -18
  72. package/build/services/store/clients/ioredis.d.ts +1 -1
  73. package/build/services/store/clients/ioredis.js +0 -1
  74. package/build/services/store/clients/redis.d.ts +1 -1
  75. package/build/services/store/index.d.ts +0 -55
  76. package/build/services/store/index.js +5 -81
  77. package/build/services/stream/clients/ioredis.d.ts +1 -1
  78. package/build/services/stream/clients/ioredis.js +1 -4
  79. package/build/services/stream/clients/redis.d.ts +1 -1
  80. package/build/services/sub/clients/ioredis.d.ts +1 -1
  81. package/build/services/sub/clients/redis.d.ts +1 -1
  82. package/build/services/task/index.d.ts +0 -9
  83. package/build/services/task/index.js +0 -31
  84. package/build/services/telemetry/index.d.ts +0 -7
  85. package/build/services/telemetry/index.js +1 -13
  86. package/build/services/worker/index.d.ts +0 -4
  87. package/build/services/worker/index.js +2 -6
  88. package/build/types/activity.d.ts +0 -81
  89. package/build/types/durable.d.ts +25 -177
  90. package/build/types/exporter.d.ts +0 -13
  91. package/build/types/hotmesh.d.ts +4 -16
  92. package/build/types/hotmesh.js +0 -3
  93. package/build/types/index.d.ts +4 -6
  94. package/build/types/index.js +4 -3
  95. package/build/types/job.d.ts +1 -86
  96. package/build/types/pipe.d.ts +0 -65
  97. package/build/types/quorum.d.ts +15 -10
  98. package/build/types/redis.d.ts +225 -7
  99. package/build/types/redis.js +9 -0
  100. package/build/types/stream.d.ts +0 -58
  101. package/build/types/stream.js +0 -4
  102. package/package.json +11 -4
  103. package/types/durable.ts +121 -3
  104. package/types/hotmesh.ts +3 -6
  105. package/types/index.ts +23 -10
  106. package/types/job.ts +1 -1
  107. package/types/quorum.ts +22 -0
  108. package/types/redis.ts +267 -18
  109. package/build/types/ioredisclient.d.ts +0 -5
  110. package/build/types/ioredisclient.js +0 -5
  111. package/build/types/redisclient.d.ts +0 -26
  112. package/build/types/redisclient.js +0 -2
  113. package/modules/enums.ts +0 -62
  114. package/modules/errors.ts +0 -280
  115. package/modules/key.ts +0 -101
  116. package/modules/storage.ts +0 -3
  117. package/modules/utils.ts +0 -242
  118. package/services/activities/activity.ts +0 -589
  119. package/services/activities/await.ts +0 -113
  120. package/services/activities/cycle.ts +0 -115
  121. package/services/activities/hook.ts +0 -197
  122. package/services/activities/index.ts +0 -19
  123. package/services/activities/interrupt.ts +0 -172
  124. package/services/activities/signal.ts +0 -148
  125. package/services/activities/trigger.ts +0 -295
  126. package/services/activities/worker.ts +0 -107
  127. package/services/collator/README.md +0 -102
  128. package/services/collator/index.ts +0 -291
  129. package/services/compiler/deployer.ts +0 -504
  130. package/services/compiler/index.ts +0 -98
  131. package/services/compiler/validator.ts +0 -158
  132. package/services/connector/clients/ioredis.ts +0 -57
  133. package/services/connector/clients/redis.ts +0 -72
  134. package/services/connector/index.ts +0 -42
  135. package/services/durable/client.ts +0 -266
  136. package/services/durable/connection.ts +0 -10
  137. package/services/durable/exporter.ts +0 -232
  138. package/services/durable/handle.ts +0 -160
  139. package/services/durable/index.ts +0 -27
  140. package/services/durable/schemas/factory.ts +0 -2358
  141. package/services/durable/search.ts +0 -196
  142. package/services/durable/worker.ts +0 -401
  143. package/services/durable/workflow.ts +0 -557
  144. package/services/engine/index.ts +0 -761
  145. package/services/exporter/index.ts +0 -146
  146. package/services/hotmesh/index.ts +0 -237
  147. package/services/logger/index.ts +0 -79
  148. package/services/mapper/index.ts +0 -89
  149. package/services/pipe/functions/array.ts +0 -78
  150. package/services/pipe/functions/bitwise.ts +0 -27
  151. package/services/pipe/functions/conditional.ts +0 -35
  152. package/services/pipe/functions/date.ts +0 -220
  153. package/services/pipe/functions/index.ts +0 -27
  154. package/services/pipe/functions/json.ts +0 -11
  155. package/services/pipe/functions/logical.ts +0 -11
  156. package/services/pipe/functions/math.ts +0 -217
  157. package/services/pipe/functions/number.ts +0 -75
  158. package/services/pipe/functions/object.ts +0 -98
  159. package/services/pipe/functions/string.ts +0 -86
  160. package/services/pipe/functions/symbol.ts +0 -39
  161. package/services/pipe/functions/unary.ts +0 -19
  162. package/services/pipe/index.ts +0 -216
  163. package/services/quorum/index.ts +0 -319
  164. package/services/reporter/index.ts +0 -387
  165. package/services/router/index.ts +0 -426
  166. package/services/serializer/README.md +0 -10
  167. package/services/serializer/index.ts +0 -285
  168. package/services/store/cache.ts +0 -172
  169. package/services/store/clients/ioredis.ts +0 -145
  170. package/services/store/clients/redis.ts +0 -191
  171. package/services/store/index.ts +0 -1091
  172. package/services/stream/clients/ioredis.ts +0 -157
  173. package/services/stream/clients/redis.ts +0 -158
  174. package/services/stream/index.ts +0 -58
  175. package/services/sub/clients/ioredis.ts +0 -83
  176. package/services/sub/clients/redis.ts +0 -74
  177. package/services/sub/index.ts +0 -25
  178. package/services/task/index.ts +0 -250
  179. package/services/telemetry/index.ts +0 -273
  180. package/services/worker/index.ts +0 -248
  181. package/types/ioredisclient.ts +0 -10
  182. package/types/redisclient.ts +0 -30
package/modules/key.ts DELETED
@@ -1,101 +0,0 @@
1
- import { KeyStoreParams, KeyType } from '../types/hotmesh';
2
-
3
- /**
4
- * Keys
5
- *
6
- * hmsh -> {hash} hotmesh config {version: "0.0.1", namespace: "hmsh"}
7
- * hmsh:a:<appid> -> {hash} app profile { "id": "appid", "version": "2", "versions/1": "GMT", "versions/2": "GMT"}
8
- * hmsh:<appid>:e:<engineId> -> {string} setnx to ensure only one engine of given id
9
- * hmsh:<appid>:w: -> {zset} work items/tasks an engine must do like garbage collect or hook a set of matching records (hookAll)
10
- * hmsh:<appid>:t: -> {zset} an ordered set of list (work lists) ids
11
- * hmsh:<appid>:t:<timeValue?> -> {list} a worklist of `jobId+activityId` items that should be awakened
12
- * hmsh:<appid>:q: -> {hash} quorum-wide messages
13
- * hmsh:<appid>:q:<ngnid> -> {hash} engine-targeted messages (targeted quorum-oriented message)
14
- * hmsh:<appid>:j:<jobid> -> {hash} job data
15
- * hmsh:<appid>:j:<jobid>:<activityid> -> {hash} job activity data (a1)
16
- * hmsh:<appid>:s:<jobkey>:<dateTime> -> {hash} job stats (general)
17
- * hmsh:<appid>:s:<jobkey>:<dateTime>:mdn:<field/path>:<fieldvalue> -> {zset} job stats (median)
18
- * hmsh:<appid>:s:<jobkey>:<dateTime>:index:<field/path>:<fieldvalue> -> {list} job stats (index of jobid[])
19
- * hmsh:<appid>:v:<version>:activities -> {hash} schemas [cache]
20
- * hmsh:<appid>:v:<version>:transitions -> {hash} transitions [cache]
21
- * hmsh:<appid>:v:<version>:subscriptions -> {hash} subscriptions [cache]
22
- * hmsh:<appid>:x: -> {xstream} when an engine is sent or reads a buffered task (engines read from their custom topic)
23
- * hmsh:<appid>:x:<topic> -> {xstream} when a worker is sent or reads a buffered task (workers read from their custom topic)
24
- * hmsh:<appid>:hooks -> {hash} hook patterns/rules; set at compile time
25
- * hmsh:<appid>:signals -> {hash} dynamic hook signals (hget/hdel) when resolving (always self-clean); added/removed at runtime
26
- * hmsh:<appid>:sym:keys: -> {hash} list of symbol ranges and :cursor assigned at version deploy time for job keys
27
- * hmsh:<appid>:sym:keys:<activityid|$subscribes> -> {hash} list of symbols based upon schema enums (initially) and adaptively optimized (later) during runtime; if '$subscribes' is used as the activityid, it is a top-level `job` symbol set (for job keys)
28
- * hmsh:<appid>:sym:vals: -> {hash} list of symbols for job values across all app versions
29
- */
30
-
31
- const HMNS = "hmsh";
32
-
33
- const KEYSEP = ':'; //default delimiter for keys
34
- const VALSEP = '::'; //default delimiter for vals
35
- const WEBSEP = '::'; //default delimiter for webhook vals
36
- const TYPSEP = '::'; //delimiter for ZSET task typing (how should a list be used?)
37
-
38
- class KeyService {
39
-
40
- /**
41
- * returns a key that can be used to access a value in the key/value store
42
- * appropriate for the given key type; the keys have an implicit hierarchy
43
- * and are used to organize data in the store in a tree-like structure
44
- * via the use of colons as separators. The top-level entity is the hmsh manifest.
45
- * This file will reveal the full scope of what is on the server (apps, versions, etc)
46
- * @param namespace
47
- * @param keyType
48
- * @param params
49
- * @returns {string}
50
- */
51
- static mintKey(namespace: string, keyType: KeyType, params: KeyStoreParams): string {
52
- switch (keyType) {
53
- case KeyType.HOTMESH:
54
- return namespace;
55
- case KeyType.ENGINE_ID:
56
- return `${namespace}:${params.appId}:e:${params.engineId}`;
57
- case KeyType.WORK_ITEMS:
58
- return `${namespace}:${params.appId}:w:${params.scoutType || ''}`;
59
- case KeyType.TIME_RANGE:
60
- return `${namespace}:${params.appId}:t:${params.timeValue || ''}`;
61
- case KeyType.APP:
62
- return `${namespace}:a:${params.appId || ''}`;
63
- case KeyType.QUORUM:
64
- return `${namespace}:${params.appId}:q:${params.engineId || ''}`;
65
- case KeyType.JOB_STATE:
66
- return `${namespace}:${params.appId}:j:${params.jobId}`;
67
- case KeyType.JOB_DEPENDENTS:
68
- return `${namespace}:${params.appId}:d:${params.jobId}`;
69
- case KeyType.JOB_STATS_GENERAL:
70
- return `${namespace}:${params.appId}:s:${params.jobKey}:${params.dateTime}`;
71
- case KeyType.JOB_STATS_MEDIAN:
72
- return `${namespace}:${params.appId}:s:${params.jobKey}:${params.dateTime}:${params.facet}`;
73
- case KeyType.JOB_STATS_INDEX:
74
- return `${namespace}:${params.appId}:s:${params.jobKey}:${params.dateTime}:${params.facet}`;
75
- case KeyType.SCHEMAS:
76
- return `${namespace}:${params.appId}:v:${params.appVersion}:schemas`;
77
- case KeyType.SUBSCRIPTIONS:
78
- return `${namespace}:${params.appId}:v:${params.appVersion}:subscriptions`;
79
- case KeyType.SUBSCRIPTION_PATTERNS:
80
- return `${namespace}:${params.appId}:v:${params.appVersion}:transitions`;
81
- case KeyType.HOOKS:
82
- //`hooks` provide the pattern to resolve a value
83
- return `${namespace}:${params.appId}:hooks`;
84
- case KeyType.SIGNALS:
85
- //`signals` provide the registry of resolved values that link back to paused jobs
86
- return `${namespace}:${params.appId}:signals`;
87
- case KeyType.SYMKEYS:
88
- //`symbol keys` provide the registry of replacement values for job keys
89
- return `${namespace}:${params.appId}:sym:keys:${params.activityId || ''}`;
90
- case KeyType.SYMVALS:
91
- //`symbol vals` provide the registry of replacement values for job vals
92
- return `${namespace}:${params.appId}:sym:vals:`;
93
- case KeyType.STREAMS:
94
- return `${namespace}:${params.appId || ''}:x:${params.topic || ''}`;
95
- default:
96
- throw new Error("Invalid key type.");
97
- }
98
- }
99
- }
100
-
101
- export { KeyService, KeyType, KeyStoreParams, HMNS, KEYSEP, TYPSEP, WEBSEP, VALSEP };
@@ -1,3 +0,0 @@
1
- import { AsyncLocalStorage } from 'async_hooks';
2
-
3
- export const asyncLocalStorage = new AsyncLocalStorage<Map<string, any>>();
package/modules/utils.ts DELETED
@@ -1,242 +0,0 @@
1
- import os from 'os';
2
- import si from 'systeminformation';
3
- import { nanoid } from "nanoid";
4
- import { StoreService } from "../services/store";
5
- import { AppSubscriptions, AppTransitions, AppVID } from "../types/app";
6
- import { RedisClient, RedisMulti } from "../types/redis";
7
- import { StringAnyType } from "../types/serializer";
8
- import { StreamCode, StreamStatus } from "../types/stream";
9
- import { SystemHealth } from '../types/quorum';
10
-
11
- async function safeExecute<T>(operation: Promise<T>, defaultValue: T): Promise<T> {
12
- try {
13
- return await operation;
14
- } catch (error) {
15
- console.error(`Operation Error: ${error}`);
16
- return defaultValue;
17
- }
18
- }
19
-
20
- export async function getSystemHealth(): Promise<SystemHealth> {
21
- const totalMemory = os.totalmem();
22
- const freeMemory = os.freemem();
23
- const usedMemory = totalMemory - freeMemory;
24
- const cpus = os.cpus();
25
-
26
- // CPU load calculation remains unchanged
27
- const cpuLoad = cpus.map((cpu, i) => {
28
- const total = Object.values(cpu.times).reduce((acc, tv) => acc + tv, 0);
29
- const idle = cpu.times.idle;
30
- const usage = ((total - idle) / total) * 100;
31
- return { [`CPU ${i} Usage`]: `${usage.toFixed(2)}%` };
32
- });
33
-
34
- // Wrap each systeminformation call with safeExecute
35
- const networkStats = await safeExecute(si.networkStats(), []);
36
-
37
- // Construct the system health object with error handling in mind
38
- const systemHealth = {
39
- TotalMemoryGB: `${(totalMemory / 1024 / 1024 / 1024).toFixed(2)} GB`,
40
- FreeMemoryGB: `${(freeMemory / 1024 / 1024 / 1024).toFixed(2)} GB`,
41
- UsedMemoryGB: `${(usedMemory / 1024 / 1024 / 1024).toFixed(2)} GB`,
42
- CPULoad: cpuLoad,
43
- NetworkStats: networkStats,
44
- };
45
-
46
- return systemHealth as SystemHealth;
47
- }
48
-
49
- export async function sleepFor(ms: number) {
50
- return new Promise((resolve) => setTimeout(resolve, ms));
51
- }
52
-
53
- export function guid(): string {
54
- return nanoid().replace(/[_-]/g, '0');
55
- }
56
-
57
- export function deterministicRandom(seed: number): number {
58
- let x = Math.sin(seed) * 10000;
59
- return x - Math.floor(x);
60
- }
61
-
62
- export function identifyRedisType(redisInstance: any): 'redis' | 'ioredis' | null {
63
- const prototype = Object.getPrototypeOf(redisInstance);
64
- if ('defineCommand' in prototype || Object.keys(prototype).includes('multi')) {
65
- return 'ioredis';
66
- } else if (Object.keys(prototype).includes('Multi')) {
67
- return 'redis';
68
- }
69
- if (redisInstance.constructor) {
70
- if (redisInstance.constructor.name === 'Redis' || redisInstance.constructor.name === 'EventEmitter') {
71
- if ('hset' in redisInstance) {
72
- return 'ioredis';
73
- }
74
- } else if (redisInstance.constructor.name === 'RedisClient' || redisInstance.constructor.name === 'Commander') {
75
- if ('HSET' in redisInstance) {
76
- return 'redis';
77
- }
78
- }
79
- }
80
- return null;
81
- }
82
-
83
- //todo: the polyfill methods will all be deleted in the `beta` release.
84
- export const polyfill = {
85
- resolveActivityType(activityType: string): string {
86
- if (activityType === 'activity') {
87
- return 'hook';
88
- }
89
- return activityType;
90
- }
91
- }
92
-
93
-
94
- export function identifyRedisTypeFromClass(redisClass: any): 'redis' | 'ioredis' | null {
95
- if (redisClass && redisClass.name === 'Redis' || redisClass.name === 'EventEmitter') {
96
- return 'ioredis';
97
- } else if (redisClass && 'createClient' in redisClass) {
98
- return 'redis';
99
- }
100
- return null;
101
- }
102
-
103
- export function matchesStatusCode(code: StreamCode, pattern: string | RegExp): boolean {
104
- if (typeof pattern === 'string') {
105
- // Convert '*' wildcard to its regex equivalent (\d)
106
- const regexPattern = `^${pattern.replace(/\*/g, "\\d")}$`;
107
- return new RegExp(regexPattern).test(code.toString());
108
- }
109
- return pattern.test(code.toString());
110
- }
111
-
112
- export function matchesStatus(status: StreamStatus, targetStatus: StreamStatus): boolean {
113
- return status === targetStatus;
114
- }
115
-
116
- export function XSleepFor(ms: number): { promise: Promise<unknown>, timerId: NodeJS.Timeout } {
117
- //can be interrupted with `clearTimeout`
118
- let timerId: NodeJS.Timeout;
119
- let promise = new Promise((resolve) => {
120
- timerId = setTimeout(resolve, ms);
121
- });
122
- return { promise, timerId };
123
- }
124
-
125
- export function findTopKey(obj: AppTransitions, input: string): string | null {
126
- for (const [key, value] of Object.entries(obj)) {
127
- if (value.hasOwnProperty(input)) {
128
- const parentKey = findTopKey(obj, key.replace(/^\./, ''));
129
- return (parentKey || key).replace(/^\./, '');
130
- }
131
- }
132
- return null;
133
- }
134
-
135
- export function findSubscriptionForTrigger(obj: AppSubscriptions, value: string): string | null {
136
- for (const [key, itemValue] of Object.entries(obj)) {
137
- if (itemValue === value) {
138
- return key;
139
- }
140
- }
141
- return null;
142
- }
143
-
144
- /**
145
- * Get the subscription topic for the flow to which @activityId belongs.
146
- * TODO: resolve this value in the compiler...do not call this at runtime
147
- */
148
- export async function getSubscriptionTopic(activityId: string, store: StoreService<RedisClient, RedisMulti>, appVID: AppVID): Promise<string | undefined> {
149
- const appTransitions = await store.getTransitions(appVID);
150
- const appSubscriptions = await store.getSubscriptions(appVID);
151
- const triggerId = findTopKey(appTransitions, activityId);
152
- const topic = findSubscriptionForTrigger(appSubscriptions, triggerId);
153
- return topic;
154
- }
155
-
156
- /**
157
- * returns the 12-digit format of the iso timestamp (e.g, 202101010000); returns
158
- * an empty string if overridden by the user to not segment by time (infinity).
159
- */
160
- export function getTimeSeries(granularity: string): string {
161
- if (granularity.toString() === 'infinity') {
162
- return '0';
163
- }
164
- const now = new Date();
165
- const granularityUnit = granularity.slice(-1);
166
- const granularityValue = parseInt(granularity.slice(0, -1), 10);
167
- if (granularityUnit === 'm') {
168
- const minute = Math.floor(now.getMinutes() / granularityValue) * granularityValue;
169
- now.setUTCMinutes(minute, 0, 0);
170
- } else if (granularityUnit === 'h') {
171
- now.setUTCMinutes(0, 0, 0);
172
- }
173
- return now.toISOString().replace(/:\d\d\..+|-|T/g, '').replace(':','');
174
- }
175
-
176
- export function formatISODate(input: Date | string): string {
177
- const date = input instanceof Date ? input : new Date(input);
178
- return date.toISOString().replace(/[:TZ-]/g, '');
179
- }
180
-
181
- export function getSymKey(number: number): string {
182
- const alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
183
- const base = alphabet.length;
184
- if (number < 0 || number >= Math.pow(base, 3)) {
185
- throw new Error('Number out of range');
186
- }
187
- let [q1, r1] = divmod(number, base);
188
- let [q2, r2] = divmod(q1, base);
189
- return alphabet[q2] + alphabet[r1] + alphabet[r2];
190
- }
191
-
192
- export function getSymVal(number: number): string {
193
- const alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
194
- const base = alphabet.length;
195
- if (number < 0 || number >= Math.pow(base, 2)) {
196
- throw new Error('Number out of range');
197
- }
198
- let [q, r] = divmod(number, base);
199
- return alphabet[q] + alphabet[r];
200
- }
201
-
202
- function divmod(m: number, n: number): number[] {
203
- return [Math.floor(m / n), m % n];
204
- }
205
-
206
- export function getIndexedHash<T>(hash: T, target: string): [number, T] {
207
- const index = hash[target] as number || 0;
208
- const newHash = { ...hash };
209
- delete newHash[target];
210
- return [index, newHash as T];
211
- }
212
-
213
- export function getValueByPath(obj: { [key: string]: any }, path: string): any {
214
- const pathParts = path.split('/');
215
- let currentValue = obj;
216
- for (const part of pathParts) {
217
- if (currentValue[part] !== undefined) {
218
- currentValue = currentValue[part];
219
- } else {
220
- return undefined;
221
- }
222
- }
223
- return currentValue;
224
- }
225
-
226
- export function restoreHierarchy(obj: StringAnyType): StringAnyType {
227
- const result: StringAnyType = {};
228
- for (const key in obj) {
229
- if (obj[key] === undefined) continue;
230
- const keys = key.split('/');
231
- let current = result;
232
- for (let i = 0; i < keys.length; i++) {
233
- if (i === keys.length - 1) {
234
- current[keys[i]] = obj[key];
235
- } else {
236
- current[keys[i]] = current[keys[i]] || {};
237
- current = current[keys[i]];
238
- }
239
- }
240
- }
241
- return result;
242
- }