@global-cache/core 0.2.3

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 (162) hide show
  1. package/README.md +5 -0
  2. package/dist/client/api.d.ts +21 -0
  3. package/dist/client/api.d.ts.map +1 -0
  4. package/dist/client/api.js +43 -0
  5. package/dist/client/api.js.map +1 -0
  6. package/dist/client/index.d.ts +27 -0
  7. package/dist/client/index.d.ts.map +1 -0
  8. package/dist/client/index.js +135 -0
  9. package/dist/client/index.js.map +1 -0
  10. package/dist/client/types.d.ts +12 -0
  11. package/dist/client/types.d.ts.map +1 -0
  12. package/dist/client/types.js +3 -0
  13. package/dist/client/types.js.map +1 -0
  14. package/dist/client/utils/http-error.d.ts +3 -0
  15. package/dist/client/utils/http-error.d.ts.map +1 -0
  16. package/dist/client/utils/http-error.js +13 -0
  17. package/dist/client/utils/http-error.js.map +1 -0
  18. package/dist/client/utils/http-json.d.ts +14 -0
  19. package/dist/client/utils/http-json.d.ts.map +1 -0
  20. package/dist/client/utils/http-json.js +29 -0
  21. package/dist/client/utils/http-json.js.map +1 -0
  22. package/dist/client/utils/http-query.d.ts +9 -0
  23. package/dist/client/utils/http-query.d.ts.map +1 -0
  24. package/dist/client/utils/http-query.js +25 -0
  25. package/dist/client/utils/http-query.js.map +1 -0
  26. package/dist/client/utils/preview-value.d.ts +2 -0
  27. package/dist/client/utils/preview-value.d.ts.map +1 -0
  28. package/dist/client/utils/preview-value.js +16 -0
  29. package/dist/client/utils/preview-value.js.map +1 -0
  30. package/dist/config.d.ts +28 -0
  31. package/dist/config.d.ts.map +1 -0
  32. package/dist/config.js +57 -0
  33. package/dist/config.js.map +1 -0
  34. package/dist/index.d.ts +3 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +8 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/server/config.d.ts +15 -0
  39. package/dist/server/config.d.ts.map +1 -0
  40. package/dist/server/config.js +18 -0
  41. package/dist/server/config.js.map +1 -0
  42. package/dist/server/error.d.ts +3 -0
  43. package/dist/server/error.d.ts.map +1 -0
  44. package/dist/server/error.js +9 -0
  45. package/dist/server/error.js.map +1 -0
  46. package/dist/server/getter.d.ts +35 -0
  47. package/dist/server/getter.d.ts.map +1 -0
  48. package/dist/server/getter.js +109 -0
  49. package/dist/server/getter.js.map +1 -0
  50. package/dist/server/index.d.ts +14 -0
  51. package/dist/server/index.d.ts.map +1 -0
  52. package/dist/server/index.js +73 -0
  53. package/dist/server/index.js.map +1 -0
  54. package/dist/server/routes/clear.d.ts +2 -0
  55. package/dist/server/routes/clear.d.ts.map +1 -0
  56. package/dist/server/routes/clear.js +15 -0
  57. package/dist/server/routes/clear.js.map +1 -0
  58. package/dist/server/routes/get-stale-list.d.ts +7 -0
  59. package/dist/server/routes/get-stale-list.d.ts.map +1 -0
  60. package/dist/server/routes/get-stale-list.js +20 -0
  61. package/dist/server/routes/get-stale-list.js.map +1 -0
  62. package/dist/server/routes/get-stale.d.ts +7 -0
  63. package/dist/server/routes/get-stale.d.ts.map +1 -0
  64. package/dist/server/routes/get-stale.js +20 -0
  65. package/dist/server/routes/get-stale.js.map +1 -0
  66. package/dist/server/routes/get.d.ts +9 -0
  67. package/dist/server/routes/get.d.ts.map +1 -0
  68. package/dist/server/routes/get.js +23 -0
  69. package/dist/server/routes/get.js.map +1 -0
  70. package/dist/server/routes/set.d.ts +9 -0
  71. package/dist/server/routes/set.d.ts.map +1 -0
  72. package/dist/server/routes/set.js +18 -0
  73. package/dist/server/routes/set.js.map +1 -0
  74. package/dist/server/setter.d.ts +12 -0
  75. package/dist/server/setter.d.ts.map +1 -0
  76. package/dist/server/setter.js +37 -0
  77. package/dist/server/setter.js.map +1 -0
  78. package/dist/server/storage/index.d.ts +6 -0
  79. package/dist/server/storage/index.d.ts.map +1 -0
  80. package/dist/server/storage/index.js +14 -0
  81. package/dist/server/storage/index.js.map +1 -0
  82. package/dist/server/storage/multi-instance/index.d.ts +9 -0
  83. package/dist/server/storage/multi-instance/index.d.ts.map +1 -0
  84. package/dist/server/storage/multi-instance/index.js +10 -0
  85. package/dist/server/storage/multi-instance/index.js.map +1 -0
  86. package/dist/server/storage/single-instance/fs.d.ts +16 -0
  87. package/dist/server/storage/single-instance/fs.d.ts.map +1 -0
  88. package/dist/server/storage/single-instance/fs.js +59 -0
  89. package/dist/server/storage/single-instance/fs.js.map +1 -0
  90. package/dist/server/storage/single-instance/index.d.ts +11 -0
  91. package/dist/server/storage/single-instance/index.d.ts.map +1 -0
  92. package/dist/server/storage/single-instance/index.js +33 -0
  93. package/dist/server/storage/single-instance/index.js.map +1 -0
  94. package/dist/server/storage/single-instance/memory.d.ts +15 -0
  95. package/dist/server/storage/single-instance/memory.d.ts.map +1 -0
  96. package/dist/server/storage/single-instance/memory.js +41 -0
  97. package/dist/server/storage/single-instance/memory.js.map +1 -0
  98. package/dist/server/storage/types.d.ts +14 -0
  99. package/dist/server/storage/types.d.ts.map +1 -0
  100. package/dist/server/storage/types.js +3 -0
  101. package/dist/server/storage/types.js.map +1 -0
  102. package/dist/server/utils/express.d.ts +8 -0
  103. package/dist/server/utils/express.d.ts.map +1 -0
  104. package/dist/server/utils/express.js +15 -0
  105. package/dist/server/utils/express.js.map +1 -0
  106. package/dist/shared/debug.d.ts +4 -0
  107. package/dist/shared/debug.d.ts.map +1 -0
  108. package/dist/shared/debug.js +14 -0
  109. package/dist/shared/debug.js.map +1 -0
  110. package/dist/shared/logger.d.ts +2 -0
  111. package/dist/shared/logger.d.ts.map +1 -0
  112. package/dist/shared/logger.js +5 -0
  113. package/dist/shared/logger.js.map +1 -0
  114. package/dist/shared/sig.d.ts +23 -0
  115. package/dist/shared/sig.d.ts.map +1 -0
  116. package/dist/shared/sig.js +53 -0
  117. package/dist/shared/sig.js.map +1 -0
  118. package/dist/shared/ttl.d.ts +8 -0
  119. package/dist/shared/ttl.d.ts.map +1 -0
  120. package/dist/shared/ttl.js +25 -0
  121. package/dist/shared/ttl.js.map +1 -0
  122. package/dist/shared/utils/object.d.ts +2 -0
  123. package/dist/shared/utils/object.d.ts.map +1 -0
  124. package/dist/shared/utils/object.js +9 -0
  125. package/dist/shared/utils/object.js.map +1 -0
  126. package/dist/shared/value-info.d.ts +18 -0
  127. package/dist/shared/value-info.d.ts.map +1 -0
  128. package/dist/shared/value-info.js +32 -0
  129. package/dist/shared/value-info.js.map +1 -0
  130. package/package.json +41 -0
  131. package/src/client/api.ts +51 -0
  132. package/src/client/index.ts +137 -0
  133. package/src/client/types.ts +14 -0
  134. package/src/client/utils/http-error.ts +8 -0
  135. package/src/client/utils/http-json.ts +32 -0
  136. package/src/client/utils/http-query.ts +24 -0
  137. package/src/client/utils/preview-value.ts +10 -0
  138. package/src/config.ts +79 -0
  139. package/src/index.ts +2 -0
  140. package/src/server/config.ts +29 -0
  141. package/src/server/error.ts +7 -0
  142. package/src/server/getter.ts +138 -0
  143. package/src/server/index.ts +81 -0
  144. package/src/server/routes/clear.ts +15 -0
  145. package/src/server/routes/get-stale-list.ts +27 -0
  146. package/src/server/routes/get-stale.ts +27 -0
  147. package/src/server/routes/get.ts +31 -0
  148. package/src/server/routes/set.ts +27 -0
  149. package/src/server/setter.ts +35 -0
  150. package/src/server/storage/index.ts +16 -0
  151. package/src/server/storage/multi-instance/index.ts +7 -0
  152. package/src/server/storage/single-instance/fs.ts +64 -0
  153. package/src/server/storage/single-instance/index.ts +32 -0
  154. package/src/server/storage/single-instance/memory.ts +43 -0
  155. package/src/server/storage/types.ts +13 -0
  156. package/src/server/utils/express.ts +14 -0
  157. package/src/shared/debug.ts +7 -0
  158. package/src/shared/logger.ts +1 -0
  159. package/src/shared/sig.ts +84 -0
  160. package/src/shared/ttl.ts +19 -0
  161. package/src/shared/utils/object.ts +4 -0
  162. package/src/shared/value-info.ts +40 -0
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.FilesystemStorage = void 0;
7
+ /**
8
+ * File system storage implementation.
9
+ */
10
+ const node_fs_1 = __importDefault(require("node:fs"));
11
+ const node_path_1 = __importDefault(require("node:path"));
12
+ class FilesystemStorage {
13
+ constructor(basePath) {
14
+ this.basePath = basePath;
15
+ }
16
+ async load(key) {
17
+ const filePath = this.getFilePath(key);
18
+ const fileExists = node_fs_1.default.existsSync(filePath);
19
+ if (!fileExists)
20
+ return;
21
+ const content = await node_fs_1.default.promises.readFile(filePath, 'utf8');
22
+ // todo: json parse safe (with warning)
23
+ const storedInfo = JSON.parse(content);
24
+ return {
25
+ key,
26
+ state: 'computed',
27
+ persistent: true,
28
+ computedAt: storedInfo.computedAt,
29
+ value: storedInfo.value,
30
+ sig: storedInfo.sig,
31
+ };
32
+ }
33
+ async save({ key, value, sig }) {
34
+ const computedAt = Date.now();
35
+ const storedInfo = { computedAt, sig, value };
36
+ const content = JSON.stringify(storedInfo, null, 2);
37
+ const filePath = this.getFilePath(key);
38
+ await node_fs_1.default.promises.mkdir(node_path_1.default.dirname(filePath), { recursive: true });
39
+ await node_fs_1.default.promises.writeFile(filePath, content, 'utf8');
40
+ }
41
+ async delete(key) {
42
+ const filePath = this.getFilePath(key);
43
+ if (node_fs_1.default.existsSync(filePath)) {
44
+ await node_fs_1.default.promises.rm(filePath);
45
+ }
46
+ }
47
+ getFilePath(key) {
48
+ return node_path_1.default.join(this.basePath, `${filenamify(key)}.json`);
49
+ }
50
+ }
51
+ exports.FilesystemStorage = FilesystemStorage;
52
+ // eslint-disable-next-line no-control-regex
53
+ const filenameReservedRegex = /[<>:"/\\|?*\u0000-\u001F]/g;
54
+ function filenamify(s, replacement = '-') {
55
+ return s
56
+ .replace(filenameReservedRegex, replacement) // prettier-ignore
57
+ .replace(/\s+/g, replacement); // additionally replace spaces
58
+ }
59
+ //# sourceMappingURL=fs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs.js","sourceRoot":"","sources":["../../../../src/server/storage/single-instance/fs.ts"],"names":[],"mappings":";;;;;;AAAA;;GAEG;AACH,sDAAyB;AACzB,0DAA6B;AAU7B,MAAa,iBAAiB;IAC5B,YAAoB,QAAgB;QAAhB,aAAQ,GAAR,QAAQ,CAAQ;IAAG,CAAC;IAExC,KAAK,CAAC,IAAI,CAAC,GAAW;QACpB,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACvC,MAAM,UAAU,GAAG,iBAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAC3C,IAAI,CAAC,UAAU;YAAE,OAAO;QAExB,MAAM,OAAO,GAAG,MAAM,iBAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC7D,uCAAuC;QACvC,MAAM,UAAU,GAAe,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAEnD,OAAO;YACL,GAAG;YACH,KAAK,EAAE,UAAU;YACjB,UAAU,EAAE,IAAI;YAChB,UAAU,EAAE,UAAU,CAAC,UAAU;YACjC,KAAK,EAAE,UAAU,CAAC,KAAK;YACvB,GAAG,EAAE,UAAU,CAAC,GAAG;SACpB,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAoB;QAC9C,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC9B,MAAM,UAAU,GAAe,EAAE,UAAU,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;QAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACvC,MAAM,iBAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,mBAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,MAAM,iBAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACvC,IAAI,iBAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5B,MAAM,iBAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAEO,WAAW,CAAC,GAAW;QAC7B,OAAO,mBAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC7D,CAAC;CACF;AAzCD,8CAyCC;AAED,4CAA4C;AAC5C,MAAM,qBAAqB,GAAG,4BAA4B,CAAC;AAC3D,SAAS,UAAU,CAAC,CAAS,EAAE,WAAW,GAAG,GAAG;IAC9C,OAAO,CAAC;SACL,OAAO,CAAC,qBAAqB,EAAE,WAAW,CAAC,CAAC,kBAAkB;SAC9D,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,8BAA8B;AACjE,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Single-instance mode of Global Storage Server.
3
+ * - non-persistent values are stored in memory
4
+ * - presistent values are stored on file system
5
+ * - compute-listeners are implemented via memory
6
+ */
7
+ import { MemoryStorage } from './memory';
8
+ import { FilesystemStorage } from './fs';
9
+ export declare function getMemoryStorage(runId: string): MemoryStorage;
10
+ export declare function getFsStorage(basePath: string): FilesystemStorage;
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/server/storage/single-instance/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAQzC,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,iBAO7C;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,qBAO5C"}
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getMemoryStorage = getMemoryStorage;
4
+ exports.getFsStorage = getFsStorage;
5
+ /**
6
+ * Single-instance mode of Global Storage Server.
7
+ * - non-persistent values are stored in memory
8
+ * - presistent values are stored on file system
9
+ * - compute-listeners are implemented via memory
10
+ */
11
+ const memory_1 = require("./memory");
12
+ const fs_1 = require("./fs");
13
+ // In-memory storage of test runs with values
14
+ const memoryStorageMap = new Map();
15
+ const fsStorageMap = new Map();
16
+ // todo: cleanup old testRuns from the map
17
+ function getMemoryStorage(runId) {
18
+ let storage = memoryStorageMap.get(runId);
19
+ if (!storage) {
20
+ storage = new memory_1.MemoryStorage();
21
+ memoryStorageMap.set(runId, storage);
22
+ }
23
+ return storage;
24
+ }
25
+ function getFsStorage(basePath) {
26
+ let storage = fsStorageMap.get(basePath);
27
+ if (!storage) {
28
+ storage = new fs_1.FilesystemStorage(basePath);
29
+ fsStorageMap.set(basePath, storage);
30
+ }
31
+ return storage;
32
+ }
33
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/server/storage/single-instance/index.ts"],"names":[],"mappings":";;AAeA,4CAOC;AAED,oCAOC;AA/BD;;;;;GAKG;AACH,qCAAyC;AACzC,6BAAyC;AAEzC,6CAA6C;AAC7C,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAyB,CAAC;AAC1D,MAAM,YAAY,GAAG,IAAI,GAAG,EAA6B,CAAC;AAE1D,0CAA0C;AAE1C,SAAgB,gBAAgB,CAAC,KAAa;IAC5C,IAAI,OAAO,GAAG,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC1C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,GAAG,IAAI,sBAAa,EAAE,CAAC;QAC9B,gBAAgB,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAgB,YAAY,CAAC,QAAgB;IAC3C,IAAI,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACzC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,GAAG,IAAI,sBAAiB,CAAC,QAAQ,CAAC,CAAC;QAC1C,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { TestRunValueInfo } from '../../../shared/value-info';
2
+ import { ITestRunStorage } from '../types';
3
+ export declare class MemoryStorage implements ITestRunStorage {
4
+ private values;
5
+ private listeners;
6
+ load(key: string): Promise<TestRunValueInfo | undefined>;
7
+ loadByPrefix(prefix: string): Promise<TestRunValueInfo[]>;
8
+ save(valueInfo: TestRunValueInfo, { notify }?: {
9
+ notify?: boolean | undefined;
10
+ }): Promise<void>;
11
+ clear(): Promise<void>;
12
+ wait(key: string): Promise<TestRunValueInfo>;
13
+ private notify;
14
+ }
15
+ //# sourceMappingURL=memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../../../src/server/storage/single-instance/memory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAI3C,qBAAa,aAAc,YAAW,eAAe;IACnD,OAAO,CAAC,MAAM,CAAuC;IACrD,OAAO,CAAC,SAAS,CAA2C;IAEtD,IAAI,CAAC,GAAG,EAAE,MAAM;IAIhB,YAAY,CAAC,MAAM,EAAE,MAAM;IAI3B,IAAI,CAAC,SAAS,EAAE,gBAAgB,EAAE,EAAE,MAAc,EAAE;;KAAK;IAKzD,KAAK;IAIL,IAAI,CAAC,GAAG,EAAE,MAAM;IAQtB,OAAO,CAAC,MAAM;CAQf"}
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MemoryStorage = void 0;
4
+ class MemoryStorage {
5
+ constructor() {
6
+ this.values = new Map();
7
+ this.listeners = new Map();
8
+ }
9
+ async load(key) {
10
+ return this.values.get(key);
11
+ }
12
+ async loadByPrefix(prefix) {
13
+ return [...this.values.values()].filter((valueInfo) => valueInfo.key.startsWith(prefix));
14
+ }
15
+ async save(valueInfo, { notify = false } = {}) {
16
+ this.values.set(valueInfo.key, valueInfo);
17
+ if (notify)
18
+ this.notify(valueInfo);
19
+ }
20
+ async clear() {
21
+ this.values.clear();
22
+ }
23
+ async wait(key) {
24
+ return new Promise((resolve) => {
25
+ const listeners = this.listeners.get(key) || [];
26
+ listeners.push(resolve);
27
+ this.listeners.set(key, listeners);
28
+ });
29
+ }
30
+ notify(valueInfo) {
31
+ const listeners = this.listeners.get(valueInfo.key);
32
+ try {
33
+ listeners?.forEach((resolve) => resolve(valueInfo));
34
+ }
35
+ finally {
36
+ this.listeners.delete(valueInfo.key);
37
+ }
38
+ }
39
+ }
40
+ exports.MemoryStorage = MemoryStorage;
41
+ //# sourceMappingURL=memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../../src/server/storage/single-instance/memory.ts"],"names":[],"mappings":";;;AAKA,MAAa,aAAa;IAA1B;QACU,WAAM,GAAG,IAAI,GAAG,EAA4B,CAAC;QAC7C,cAAS,GAAG,IAAI,GAAG,EAAgC,CAAC;IAmC9D,CAAC;IAjCC,KAAK,CAAC,IAAI,CAAC,GAAW;QACpB,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,MAAc;QAC/B,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;IAC3F,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,SAA2B,EAAE,EAAE,MAAM,GAAG,KAAK,EAAE,GAAG,EAAE;QAC7D,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC1C,IAAI,MAAM;YAAE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,GAAW;QACpB,OAAO,IAAI,OAAO,CAAmB,CAAC,OAAO,EAAE,EAAE;YAC/C,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YAChD,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACxB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,MAAM,CAAC,SAA2B;QACxC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACpD,IAAI,CAAC;YACH,SAAS,EAAE,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;QACtD,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;CACF;AArCD,sCAqCC"}
@@ -0,0 +1,14 @@
1
+ import { TestRunValueInfo } from '../../shared/value-info';
2
+ export type ITestRunStorage = {
3
+ load(key: string): Promise<TestRunValueInfo | undefined>;
4
+ save(valueInfo: TestRunValueInfo, options?: {
5
+ notify?: boolean;
6
+ }): Promise<void>;
7
+ wait(key: string): Promise<TestRunValueInfo>;
8
+ };
9
+ export type IPersistentStorage = {
10
+ load(key: string): Promise<TestRunValueInfo | undefined>;
11
+ save(valueInfo: TestRunValueInfo): Promise<void>;
12
+ delete(key: string): Promise<void>;
13
+ };
14
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/server/storage/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAAC;IACzD,IAAI,CAAC,SAAS,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjF,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;CAC9C,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAAC;IACzD,IAAI,CAAC,SAAS,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpC,CAAC"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/server/storage/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ import express from 'express';
2
+ import http from 'node:http';
3
+ /**
4
+ * Start server.
5
+ * See: https://github.com/nodejs/node/issues/21482#issuecomment-626025579
6
+ */
7
+ export declare function startExpressServer(app: express.Express, port?: number): Promise<http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>>;
8
+ //# sourceMappingURL=express.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../../../src/server/utils/express.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,SAAI,iFAMtE"}
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.startExpressServer = startExpressServer;
4
+ /**
5
+ * Start server.
6
+ * See: https://github.com/nodejs/node/issues/21482#issuecomment-626025579
7
+ */
8
+ async function startExpressServer(app, port = 0) {
9
+ return new Promise((resolve, reject) => {
10
+ const server = app.listen(port);
11
+ server.once('listening', () => resolve(server));
12
+ server.once('error', reject);
13
+ });
14
+ }
15
+ //# sourceMappingURL=express.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express.js","sourceRoot":"","sources":["../../../src/server/utils/express.ts"],"names":[],"mappings":";;AAOA,gDAMC;AAVD;;;GAGG;AACI,KAAK,UAAU,kBAAkB,CAAC,GAAoB,EAAE,IAAI,GAAG,CAAC;IACrE,OAAO,IAAI,OAAO,CAAc,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAClD,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;QAChD,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,4 @@
1
+ import Debug from 'debug';
2
+ export declare const debug: Debug.Debugger;
3
+ export declare const debugKey: (key: string, message: string) => void;
4
+ //# sourceMappingURL=debug.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../src/shared/debug.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,eAAO,MAAM,KAAK,gBAAwB,CAAC;AAC3C,eAAO,MAAM,QAAQ,GAAI,KAAK,MAAM,EAAE,SAAS,MAAM,SAGpD,CAAC"}
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.debugKey = exports.debug = void 0;
7
+ const debug_1 = __importDefault(require("debug"));
8
+ exports.debug = (0, debug_1.default)('global-cache');
9
+ const debugKey = (key, message) => {
10
+ const debug = (0, debug_1.default)(`global-cache:${key}`);
11
+ debug(message);
12
+ };
13
+ exports.debugKey = debugKey;
14
+ //# sourceMappingURL=debug.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug.js","sourceRoot":"","sources":["../../src/shared/debug.ts"],"names":[],"mappings":";;;;;;AAAA,kDAA0B;AAEb,QAAA,KAAK,GAAG,IAAA,eAAK,EAAC,cAAc,CAAC,CAAC;AACpC,MAAM,QAAQ,GAAG,CAAC,GAAW,EAAE,OAAe,EAAE,EAAE;IACvD,MAAM,KAAK,GAAG,IAAA,eAAK,EAAC,gBAAgB,GAAG,EAAE,CAAC,CAAC;IAC3C,KAAK,CAAC,OAAO,CAAC,CAAC;AACjB,CAAC,CAAC;AAHW,QAAA,QAAQ,YAGnB"}
@@ -0,0 +1,2 @@
1
+ export declare const logger: Console;
2
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/shared/logger.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,MAAM,SAAU,CAAC"}
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.logger = void 0;
4
+ exports.logger = console;
5
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/shared/logger.ts"],"names":[],"mappings":";;;AAAa,QAAA,MAAM,GAAG,OAAO,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Calculate the calling signature for a given key:
3
+ * ttl + stack + computeFn body
4
+ *
5
+ * Signature is used to invalidate the key in case of changes in the calling code.
6
+ * Signature is computed on client and sent to the server.
7
+ * Server compares the signature with the stored one and invalidates the key if they differ.
8
+ */
9
+ import { TTL } from './ttl';
10
+ type SingatureParams = {
11
+ fn: Function;
12
+ stack: string;
13
+ ttl?: TTL;
14
+ };
15
+ export type SignatureMismatch = {
16
+ field: 'fn' | 'stack' | 'ttl' | 'sig';
17
+ value1: unknown;
18
+ value2: unknown;
19
+ };
20
+ export declare function calcSignature({ ttl, stack, fn }: SingatureParams): string;
21
+ export declare function checkSignature(key: string, storedSigStr: string, currentSigStr: string): SignatureMismatch | undefined;
22
+ export {};
23
+ //# sourceMappingURL=sig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sig.d.ts","sourceRoot":"","sources":["../../src/shared/sig.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAE5B,KAAK,eAAe,GAAG;IACrB,EAAE,EAAE,QAAQ,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,GAAG,CAAC;CACX,CAAC;AAQF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,IAAI,GAAG,OAAO,GAAG,KAAK,GAAG,KAAK,CAAC;IACtC,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,wBAAgB,aAAa,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,eAAe,UAOhE;AAGD,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,GACpB,iBAAiB,GAAG,SAAS,CAwB/B"}
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ /**
3
+ * Calculate the calling signature for a given key:
4
+ * ttl + stack + computeFn body
5
+ *
6
+ * Signature is used to invalidate the key in case of changes in the calling code.
7
+ * Signature is computed on client and sent to the server.
8
+ * Server compares the signature with the stored one and invalidates the key if they differ.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.calcSignature = calcSignature;
12
+ exports.checkSignature = checkSignature;
13
+ function calcSignature({ ttl, stack, fn }) {
14
+ // todo: use hashing?
15
+ // todo: remove spaces and newlines from stack and computeFn?
16
+ const fnBody = fn.toString().replace(/[\n\s]+/g, ' ');
17
+ const obj = { ttl, stack, fn: fnBody };
18
+ return JSON.stringify(obj);
19
+ }
20
+ // eslint-disable-next-line visual/complexity
21
+ function checkSignature(key, storedSigStr, currentSigStr) {
22
+ const storedSig = parseSignatureSafe(storedSigStr);
23
+ const currentSig = parseSignatureSafe(currentSigStr);
24
+ // fallback to string comparison if parsing failed for any of the signatures
25
+ // todo: remove in the future releases
26
+ if (!storedSig || !currentSig) {
27
+ return storedSigStr !== currentSigStr
28
+ ? createSignatureMismatch('sig', storedSigStr, currentSigStr)
29
+ : undefined;
30
+ }
31
+ // checking stack first -> allows to navigate to the code by click in IDE.
32
+ if (storedSig.stack !== currentSig.stack) {
33
+ return createSignatureMismatch('stack', storedSig.stack, currentSig.stack);
34
+ }
35
+ if (storedSig.ttl !== currentSig.ttl) {
36
+ return createSignatureMismatch('ttl', storedSig.ttl, currentSig.ttl);
37
+ }
38
+ if (storedSig.fn !== currentSig.fn) {
39
+ return createSignatureMismatch('fn', storedSig.fn, currentSig.fn);
40
+ }
41
+ }
42
+ function createSignatureMismatch(field, value1, value2) {
43
+ return { field, value1, value2 };
44
+ }
45
+ function parseSignatureSafe(sigStr) {
46
+ try {
47
+ return JSON.parse(sigStr);
48
+ }
49
+ catch {
50
+ return null;
51
+ }
52
+ }
53
+ //# sourceMappingURL=sig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sig.js","sourceRoot":"","sources":["../../src/shared/sig.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;AAsBH,sCAOC;AAGD,wCA4BC;AAtCD,SAAgB,aAAa,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAmB;IAC/D,qBAAqB;IACrB,6DAA6D;IAC7D,MAAM,MAAM,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IACtD,MAAM,GAAG,GAAiB,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC;IAErD,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;AAC7B,CAAC;AAED,6CAA6C;AAC7C,SAAgB,cAAc,CAC5B,GAAW,EACX,YAAoB,EACpB,aAAqB;IAErB,MAAM,SAAS,GAAG,kBAAkB,CAAC,YAAY,CAAC,CAAC;IACnD,MAAM,UAAU,GAAG,kBAAkB,CAAC,aAAa,CAAC,CAAC;IAErD,4EAA4E;IAC5E,sCAAsC;IACtC,IAAI,CAAC,SAAS,IAAI,CAAC,UAAU,EAAE,CAAC;QAC9B,OAAO,YAAY,KAAK,aAAa;YACnC,CAAC,CAAC,uBAAuB,CAAC,KAAK,EAAE,YAAY,EAAE,aAAa,CAAC;YAC7D,CAAC,CAAC,SAAS,CAAC;IAChB,CAAC;IAED,0EAA0E;IAC1E,IAAI,SAAS,CAAC,KAAK,KAAK,UAAU,CAAC,KAAK,EAAE,CAAC;QACzC,OAAO,uBAAuB,CAAC,OAAO,EAAE,SAAS,CAAC,KAAK,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;IAC7E,CAAC;IAED,IAAI,SAAS,CAAC,GAAG,KAAK,UAAU,CAAC,GAAG,EAAE,CAAC;QACrC,OAAO,uBAAuB,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC;IACvE,CAAC;IAED,IAAI,SAAS,CAAC,EAAE,KAAK,UAAU,CAAC,EAAE,EAAE,CAAC;QACnC,OAAO,uBAAuB,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,EAAE,UAAU,CAAC,EAAE,CAAC,CAAC;IACpE,CAAC;AACH,CAAC;AAED,SAAS,uBAAuB,CAC9B,KAAiC,EACjC,MAAe,EACf,MAAe;IAEf,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AACnC,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAc;IACxC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAiB,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { StringValue } from 'ms';
2
+ export type TTL = number | StringValue | 'infinite';
3
+ /**
4
+ * TTL can be a stringified number or a string like "1h" or "infinite".
5
+ */
6
+ export declare function parseTTL(ttl: string | number | undefined): number | undefined;
7
+ export declare function isExpired(computedAt: number | undefined, ttl: number): boolean;
8
+ //# sourceMappingURL=ttl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ttl.d.ts","sourceRoot":"","sources":["../../src/shared/ttl.ts"],"names":[],"mappings":"AAAA,OAAW,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC;AAGrC,MAAM,MAAM,GAAG,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,CAAC;AAEpD;;GAEG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,sBAKxD;AAED,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,EAAE,GAAG,EAAE,MAAM,WAGpE"}
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.parseTTL = parseTTL;
7
+ exports.isExpired = isExpired;
8
+ const ms_1 = __importDefault(require("ms"));
9
+ /**
10
+ * TTL can be a stringified number or a string like "1h" or "infinite".
11
+ */
12
+ function parseTTL(ttl) {
13
+ if (ttl === '' || ttl === undefined)
14
+ return undefined;
15
+ if (ttl === 'infinite')
16
+ return -1;
17
+ const ttlNumber = Number(ttl);
18
+ return Number.isNaN(ttlNumber) ? (0, ms_1.default)(ttl) : ttlNumber;
19
+ }
20
+ function isExpired(computedAt, ttl) {
21
+ if (!computedAt || ttl === -1)
22
+ return false;
23
+ return Date.now() > computedAt + ttl;
24
+ }
25
+ //# sourceMappingURL=ttl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ttl.js","sourceRoot":"","sources":["../../src/shared/ttl.ts"],"names":[],"mappings":";;;;;AAQA,4BAKC;AAED,8BAGC;AAlBD,4CAAqC;AAKrC;;GAEG;AACH,SAAgB,QAAQ,CAAC,GAAgC;IACvD,IAAI,GAAG,KAAK,EAAE,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACtD,IAAI,GAAG,KAAK,UAAU;QAAE,OAAO,CAAC,CAAC,CAAC;IAClC,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAC9B,OAAO,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAA,YAAE,EAAC,GAAkB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACtE,CAAC;AAED,SAAgB,SAAS,CAAC,UAA8B,EAAE,GAAW;IACnE,IAAI,CAAC,UAAU,IAAI,GAAG,KAAK,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAC5C,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,GAAG,GAAG,CAAC;AACvC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function removeUndefined<T extends Record<string, unknown>>(obj?: T): T | undefined;
2
+ //# sourceMappingURL=object.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"object.d.ts","sourceRoot":"","sources":["../../../src/shared/utils/object.ts"],"names":[],"mappings":"AAAA,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,SAAS,CAGzF"}
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.removeUndefined = removeUndefined;
4
+ function removeUndefined(obj) {
5
+ if (!obj)
6
+ return;
7
+ return Object.fromEntries(Object.entries(obj).filter(([_, value]) => value !== undefined));
8
+ }
9
+ //# sourceMappingURL=object.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"object.js","sourceRoot":"","sources":["../../../src/shared/utils/object.ts"],"names":[],"mappings":";;AAAA,0CAGC;AAHD,SAAgB,eAAe,CAAoC,GAAO;IACxE,IAAI,CAAC,GAAG;QAAE,OAAO;IACjB,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC,CAAM,CAAC;AAClG,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Value info in the scope of particular test run.
3
+ */
4
+ export type TestRunValueInfo = {
5
+ key: string;
6
+ sig: string;
7
+ state: 'computing' | 'computed' | 'error';
8
+ computedAt?: number;
9
+ value?: unknown;
10
+ persistent?: boolean;
11
+ prevValue?: unknown;
12
+ errorMessage?: string;
13
+ };
14
+ export declare function updateValueInfo(valueInfo: TestRunValueInfo, props: Partial<TestRunValueInfo>): TestRunValueInfo & Partial<TestRunValueInfo>;
15
+ export declare function setComputed(valueInfo: TestRunValueInfo, value: unknown): void;
16
+ export declare function setError(valueInfo: TestRunValueInfo, errorMessage: string): void;
17
+ export declare function getStaleValue(valueInfo?: TestRunValueInfo | null): unknown;
18
+ //# sourceMappingURL=value-info.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"value-info.d.ts","sourceRoot":"","sources":["../../src/shared/value-info.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,WAAW,GAAG,UAAU,GAAG,OAAO,CAAC;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,wBAAgB,eAAe,CAAC,SAAS,EAAE,gBAAgB,EAAE,KAAK,EAAE,OAAO,CAAC,gBAAgB,CAAC,gDAE5F;AAED,wBAAgB,WAAW,CAAC,SAAS,EAAE,gBAAgB,EAAE,KAAK,EAAE,OAAO,QAOtE;AAED,wBAAgB,QAAQ,CAAC,SAAS,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,QAOzE;AAED,wBAAgB,aAAa,CAAC,SAAS,CAAC,EAAE,gBAAgB,GAAG,IAAI,WAEhE"}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ /**
3
+ * Value info in the scope of particular test run.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.updateValueInfo = updateValueInfo;
7
+ exports.setComputed = setComputed;
8
+ exports.setError = setError;
9
+ exports.getStaleValue = getStaleValue;
10
+ function updateValueInfo(valueInfo, props) {
11
+ return Object.assign(valueInfo, props);
12
+ }
13
+ function setComputed(valueInfo, value) {
14
+ updateValueInfo(valueInfo, {
15
+ state: 'computed',
16
+ value,
17
+ computedAt: Date.now(),
18
+ errorMessage: undefined,
19
+ });
20
+ }
21
+ function setError(valueInfo, errorMessage) {
22
+ updateValueInfo(valueInfo, {
23
+ state: 'error',
24
+ errorMessage,
25
+ value: undefined,
26
+ computedAt: undefined,
27
+ });
28
+ }
29
+ function getStaleValue(valueInfo) {
30
+ return valueInfo?.persistent ? valueInfo.prevValue : valueInfo?.value;
31
+ }
32
+ //# sourceMappingURL=value-info.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"value-info.js","sourceRoot":"","sources":["../../src/shared/value-info.ts"],"names":[],"mappings":";AAAA;;GAEG;;AAaH,0CAEC;AAED,kCAOC;AAED,4BAOC;AAED,sCAEC;AAxBD,SAAgB,eAAe,CAAC,SAA2B,EAAE,KAAgC;IAC3F,OAAO,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;AACzC,CAAC;AAED,SAAgB,WAAW,CAAC,SAA2B,EAAE,KAAc;IACrE,eAAe,CAAC,SAAS,EAAE;QACzB,KAAK,EAAE,UAAU;QACjB,KAAK;QACL,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE;QACtB,YAAY,EAAE,SAAS;KACxB,CAAC,CAAC;AACL,CAAC;AAED,SAAgB,QAAQ,CAAC,SAA2B,EAAE,YAAoB;IACxE,eAAe,CAAC,SAAS,EAAE;QACzB,KAAK,EAAE,OAAO;QACd,YAAY;QACZ,KAAK,EAAE,SAAS;QAChB,UAAU,EAAE,SAAS;KACtB,CAAC,CAAC;AACL,CAAC;AAED,SAAgB,aAAa,CAAC,SAAmC;IAC/D,OAAO,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE,KAAK,CAAC;AACxE,CAAC"}
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@global-cache/core",
3
+ "description": "Key-value cache for sharing data between parallel workers.",
4
+ "version": "0.2.3",
5
+ "type": "commonjs",
6
+ "exports": {
7
+ ".": "./dist/index.js",
8
+ "./server": "./dist/server/index.js",
9
+ "./package.json": "./package.json"
10
+ },
11
+ "engines": {
12
+ "node": ">=20"
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "src",
17
+ "README.md"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsc -p tsconfig.build.json",
21
+ "test": "vitest run --no-cache --testTimeout 5000 --dir ./test",
22
+ "test:d": "DEBUG=global-cache* npm t",
23
+ "release": "release-it"
24
+ },
25
+ "release-it": {
26
+ "git": false
27
+ },
28
+ "dependencies": {
29
+ "@types/debug": "^4.1.12",
30
+ "@types/express": "^5.0.3",
31
+ "@types/ms": "^2.1.0",
32
+ "debug": "^4.4.1",
33
+ "express": "^5.1.0",
34
+ "ms": "^2.1.3"
35
+ },
36
+ "publishConfig": {
37
+ "access": "public"
38
+ },
39
+ "funding": "https://github.com/sponsors/vitalets",
40
+ "license": "MIT"
41
+ }
@@ -0,0 +1,51 @@
1
+ import type { GetValueParams, GetValueResponse } from '../server/routes/get';
2
+ import type { SetValueParams, SetValueResponse } from '../server/routes/set';
3
+ import type { GetStaleParams, SetStaleResponse } from '../server/routes/get-stale';
4
+ import type { GetStaleListParams, SetStaleListResponse } from '../server/routes/get-stale-list';
5
+ import { TTL } from '../shared/ttl';
6
+ import { HttpJson } from './utils/http-json';
7
+ import { prepareQueryParams } from './utils/http-query';
8
+ import { throwIfHttpError } from './utils/http-error';
9
+ import { getStaleValue } from '../shared/value-info';
10
+
11
+ export class StorageApi {
12
+ private http: HttpJson;
13
+
14
+ constructor(serverUrl: string, runId: string) {
15
+ const baseUrl = new URL(`/run/${runId}/`, serverUrl).toString();
16
+ this.http = new HttpJson(baseUrl);
17
+ }
18
+
19
+ async get({ key, sig, ttl }: { key: string; sig: string; ttl?: TTL }) {
20
+ const params: GetValueParams = prepareQueryParams({ key, sig, ttl });
21
+ const res = await this.http.get('get', params);
22
+ await throwIfHttpError(res, `Failed to get key "${key}":`);
23
+ return (await res.json()) as GetValueResponse;
24
+ }
25
+
26
+ async set({ key, value, error }: { key: string; value: unknown; error?: Error }) {
27
+ const body: SetValueParams = { key, value, error: error?.message };
28
+ const res = await this.http.post('set', body);
29
+ await throwIfHttpError(res, `Failed to save key "${key}":`);
30
+ return (await res.json()) as SetValueResponse;
31
+ }
32
+
33
+ async getStale({ key }: GetStaleParams) {
34
+ const res = await this.http.get('get-stale', { key });
35
+ await throwIfHttpError(res, `Failed to get stale key "${key}":`);
36
+ const valueInfo = (await res.json()) as SetStaleResponse;
37
+ return getStaleValue(valueInfo);
38
+ }
39
+
40
+ async getStaleList({ prefix }: GetStaleListParams) {
41
+ const res = await this.http.get('get-stale-list', { prefix });
42
+ await throwIfHttpError(res, `Failed to get stale list for prefix "${prefix}":`);
43
+ const valueInfoList = (await res.json()) as SetStaleListResponse;
44
+ return valueInfoList.map((valueInfo) => getStaleValue(valueInfo));
45
+ }
46
+
47
+ async clear() {
48
+ const res = await this.http.post('clear');
49
+ await throwIfHttpError(res, 'Failed to clear session:');
50
+ }
51
+ }