@workflow/world-local 5.0.0-beta.10 → 5.0.0-beta.12

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 (63) hide show
  1. package/dist/config.d.ts +23 -5
  2. package/dist/config.d.ts.map +1 -1
  3. package/dist/config.js +19 -14
  4. package/dist/fs.d.ts +113 -2
  5. package/dist/fs.d.ts.map +1 -1
  6. package/dist/fs.js +321 -28
  7. package/dist/index.d.ts +16 -2
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +97 -6
  10. package/dist/init.d.ts +91 -0
  11. package/dist/init.d.ts.map +1 -0
  12. package/dist/init.js +268 -0
  13. package/dist/instrumentObject.d.ts +8 -0
  14. package/dist/instrumentObject.d.ts.map +1 -0
  15. package/dist/instrumentObject.js +66 -0
  16. package/dist/queue.d.ts +8 -1
  17. package/dist/queue.d.ts.map +1 -1
  18. package/dist/queue.js +195 -54
  19. package/dist/storage/events-storage.d.ts +7 -0
  20. package/dist/storage/events-storage.d.ts.map +1 -0
  21. package/dist/storage/events-storage.js +898 -0
  22. package/dist/storage/filters.d.ts +22 -0
  23. package/dist/storage/filters.d.ts.map +1 -0
  24. package/dist/storage/filters.js +33 -0
  25. package/dist/storage/helpers.d.ts +18 -0
  26. package/dist/storage/helpers.d.ts.map +1 -0
  27. package/dist/storage/helpers.js +44 -0
  28. package/dist/storage/hooks-storage.d.ts +12 -0
  29. package/dist/storage/hooks-storage.d.ts.map +1 -0
  30. package/dist/storage/hooks-storage.js +93 -0
  31. package/dist/storage/index.d.ts +21 -0
  32. package/dist/storage/index.d.ts.map +1 -0
  33. package/dist/storage/index.js +30 -0
  34. package/dist/storage/legacy.d.ts +13 -0
  35. package/dist/storage/legacy.d.ts.map +1 -0
  36. package/dist/storage/legacy.js +78 -0
  37. package/dist/storage/runs-storage.d.ts +33 -0
  38. package/dist/storage/runs-storage.d.ts.map +1 -0
  39. package/dist/storage/runs-storage.js +130 -0
  40. package/dist/storage/steps-storage.d.ts +7 -0
  41. package/dist/storage/steps-storage.d.ts.map +1 -0
  42. package/dist/storage/steps-storage.js +52 -0
  43. package/dist/storage.d.ts +9 -2
  44. package/dist/storage.d.ts.map +1 -1
  45. package/dist/storage.js +9 -456
  46. package/dist/streamer.d.ts +4 -2
  47. package/dist/streamer.d.ts.map +1 -1
  48. package/dist/streamer.js +467 -107
  49. package/dist/telemetry.d.ts +28 -0
  50. package/dist/telemetry.d.ts.map +1 -0
  51. package/dist/telemetry.js +71 -0
  52. package/dist/test-helpers.d.ts +54 -0
  53. package/dist/test-helpers.d.ts.map +1 -0
  54. package/dist/test-helpers.js +118 -0
  55. package/dist/util.js +1 -1
  56. package/package.json +12 -11
  57. package/dist/config.js.map +0 -1
  58. package/dist/fs.js.map +0 -1
  59. package/dist/index.js.map +0 -1
  60. package/dist/queue.js.map +0 -1
  61. package/dist/storage.js.map +0 -1
  62. package/dist/streamer.js.map +0 -1
  63. package/dist/util.js.map +0 -1
@@ -0,0 +1,22 @@
1
+ import type { Hook, Step, StepWithoutData, WorkflowRun, WorkflowRunWithoutData } from '@workflow/world';
2
+ export { stripEventDataRefs } from '@workflow/world';
3
+ /**
4
+ * Filter run data based on resolveData setting.
5
+ * When resolveData is 'none', strips input/output to reduce payload size.
6
+ */
7
+ export declare function filterRunData(run: WorkflowRun, resolveData: 'none'): WorkflowRunWithoutData;
8
+ export declare function filterRunData(run: WorkflowRun, resolveData: 'all'): WorkflowRun;
9
+ export declare function filterRunData(run: WorkflowRun, resolveData: 'none' | 'all'): WorkflowRun | WorkflowRunWithoutData;
10
+ /**
11
+ * Filter step data based on resolveData setting.
12
+ * When resolveData is 'none', strips input/output to reduce payload size.
13
+ */
14
+ export declare function filterStepData(step: Step, resolveData: 'none'): StepWithoutData;
15
+ export declare function filterStepData(step: Step, resolveData: 'all'): Step;
16
+ export declare function filterStepData(step: Step, resolveData: 'none' | 'all'): Step | StepWithoutData;
17
+ /**
18
+ * Filter hook data based on resolveData setting.
19
+ * When resolveData is 'none', strips metadata to reduce payload size.
20
+ */
21
+ export declare function filterHookData(hook: Hook, resolveData: 'none' | 'all'): Hook;
22
+ //# sourceMappingURL=filters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filters.d.ts","sourceRoot":"","sources":["../../src/storage/filters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,IAAI,EACJ,IAAI,EACJ,eAAe,EACf,WAAW,EACX,sBAAsB,EACvB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,WAAW,EAChB,WAAW,EAAE,MAAM,GAClB,sBAAsB,CAAC;AAC1B,wBAAgB,aAAa,CAC3B,GAAG,EAAE,WAAW,EAChB,WAAW,EAAE,KAAK,GACjB,WAAW,CAAC;AACf,wBAAgB,aAAa,CAC3B,GAAG,EAAE,WAAW,EAChB,WAAW,EAAE,MAAM,GAAG,KAAK,GAC1B,WAAW,GAAG,sBAAsB,CAAC;AAexC;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,IAAI,EACV,WAAW,EAAE,MAAM,GAClB,eAAe,CAAC;AACnB,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,GAAG,IAAI,CAAC;AACrE,wBAAgB,cAAc,CAC5B,IAAI,EAAE,IAAI,EACV,WAAW,EAAE,MAAM,GAAG,KAAK,GAC1B,IAAI,GAAG,eAAe,CAAC;AAe1B;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAM5E"}
@@ -0,0 +1,33 @@
1
+ export { stripEventDataRefs } from '@workflow/world';
2
+ export function filterRunData(run, resolveData) {
3
+ if (resolveData === 'none') {
4
+ return {
5
+ ...run,
6
+ input: undefined,
7
+ output: undefined,
8
+ };
9
+ }
10
+ return run;
11
+ }
12
+ export function filterStepData(step, resolveData) {
13
+ if (resolveData === 'none') {
14
+ return {
15
+ ...step,
16
+ input: undefined,
17
+ output: undefined,
18
+ };
19
+ }
20
+ return step;
21
+ }
22
+ /**
23
+ * Filter hook data based on resolveData setting.
24
+ * When resolveData is 'none', strips metadata to reduce payload size.
25
+ */
26
+ export function filterHookData(hook, resolveData) {
27
+ if (resolveData === 'none') {
28
+ const { metadata: _metadata, ...rest } = hook;
29
+ return rest;
30
+ }
31
+ return hook;
32
+ }
33
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsdGVycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zdG9yYWdlL2ZpbHRlcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBUUEsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFrQnJELE1BQU0sVUFBVSxhQUFhLENBQzNCLEdBQWdCLEVBQ2hCLFdBQTJCO0lBRTNCLElBQUksV0FBVyxLQUFLLE1BQU0sRUFBRSxDQUFDO1FBQzNCLE9BQU87WUFDTCxHQUFHLEdBQUc7WUFDTixLQUFLLEVBQUUsU0FBUztZQUNoQixNQUFNLEVBQUUsU0FBUztTQUNRLENBQUM7SUFDOUIsQ0FBQztJQUNELE9BQU8sR0FBRyxDQUFDO0FBQ2IsQ0FBQztBQWVELE1BQU0sVUFBVSxjQUFjLENBQzVCLElBQVUsRUFDVixXQUEyQjtJQUUzQixJQUFJLFdBQVcsS0FBSyxNQUFNLEVBQUUsQ0FBQztRQUMzQixPQUFPO1lBQ0wsR0FBRyxJQUFJO1lBQ1AsS0FBSyxFQUFFLFNBQVM7WUFDaEIsTUFBTSxFQUFFLFNBQVM7U0FDQyxDQUFDO0lBQ3ZCLENBQUM7SUFDRCxPQUFPLElBQUksQ0FBQztBQUNkLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsY0FBYyxDQUFDLElBQVUsRUFBRSxXQUEyQjtJQUNwRSxJQUFJLFdBQVcsS0FBSyxNQUFNLEVBQUUsQ0FBQztRQUMzQixNQUFNLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxHQUFHLElBQUksRUFBRSxHQUFHLElBQVcsQ0FBQztRQUNyRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFDRCxPQUFPLElBQUksQ0FBQztBQUNkLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7XG4gIEhvb2ssXG4gIFN0ZXAsXG4gIFN0ZXBXaXRob3V0RGF0YSxcbiAgV29ya2Zsb3dSdW4sXG4gIFdvcmtmbG93UnVuV2l0aG91dERhdGEsXG59IGZyb20gJ0B3b3JrZmxvdy93b3JsZCc7XG5cbmV4cG9ydCB7IHN0cmlwRXZlbnREYXRhUmVmcyB9IGZyb20gJ0B3b3JrZmxvdy93b3JsZCc7XG5cbi8qKlxuICogRmlsdGVyIHJ1biBkYXRhIGJhc2VkIG9uIHJlc29sdmVEYXRhIHNldHRpbmcuXG4gKiBXaGVuIHJlc29sdmVEYXRhIGlzICdub25lJywgc3RyaXBzIGlucHV0L291dHB1dCB0byByZWR1Y2UgcGF5bG9hZCBzaXplLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZmlsdGVyUnVuRGF0YShcbiAgcnVuOiBXb3JrZmxvd1J1bixcbiAgcmVzb2x2ZURhdGE6ICdub25lJ1xuKTogV29ya2Zsb3dSdW5XaXRob3V0RGF0YTtcbmV4cG9ydCBmdW5jdGlvbiBmaWx0ZXJSdW5EYXRhKFxuICBydW46IFdvcmtmbG93UnVuLFxuICByZXNvbHZlRGF0YTogJ2FsbCdcbik6IFdvcmtmbG93UnVuO1xuZXhwb3J0IGZ1bmN0aW9uIGZpbHRlclJ1bkRhdGEoXG4gIHJ1bjogV29ya2Zsb3dSdW4sXG4gIHJlc29sdmVEYXRhOiAnbm9uZScgfCAnYWxsJ1xuKTogV29ya2Zsb3dSdW4gfCBXb3JrZmxvd1J1bldpdGhvdXREYXRhO1xuZXhwb3J0IGZ1bmN0aW9uIGZpbHRlclJ1bkRhdGEoXG4gIHJ1bjogV29ya2Zsb3dSdW4sXG4gIHJlc29sdmVEYXRhOiAnbm9uZScgfCAnYWxsJ1xuKTogV29ya2Zsb3dSdW4gfCBXb3JrZmxvd1J1bldpdGhvdXREYXRhIHtcbiAgaWYgKHJlc29sdmVEYXRhID09PSAnbm9uZScpIHtcbiAgICByZXR1cm4ge1xuICAgICAgLi4ucnVuLFxuICAgICAgaW5wdXQ6IHVuZGVmaW5lZCxcbiAgICAgIG91dHB1dDogdW5kZWZpbmVkLFxuICAgIH0gYXMgV29ya2Zsb3dSdW5XaXRob3V0RGF0YTtcbiAgfVxuICByZXR1cm4gcnVuO1xufVxuXG4vKipcbiAqIEZpbHRlciBzdGVwIGRhdGEgYmFzZWQgb24gcmVzb2x2ZURhdGEgc2V0dGluZy5cbiAqIFdoZW4gcmVzb2x2ZURhdGEgaXMgJ25vbmUnLCBzdHJpcHMgaW5wdXQvb3V0cHV0IHRvIHJlZHVjZSBwYXlsb2FkIHNpemUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmaWx0ZXJTdGVwRGF0YShcbiAgc3RlcDogU3RlcCxcbiAgcmVzb2x2ZURhdGE6ICdub25lJ1xuKTogU3RlcFdpdGhvdXREYXRhO1xuZXhwb3J0IGZ1bmN0aW9uIGZpbHRlclN0ZXBEYXRhKHN0ZXA6IFN0ZXAsIHJlc29sdmVEYXRhOiAnYWxsJyk6IFN0ZXA7XG5leHBvcnQgZnVuY3Rpb24gZmlsdGVyU3RlcERhdGEoXG4gIHN0ZXA6IFN0ZXAsXG4gIHJlc29sdmVEYXRhOiAnbm9uZScgfCAnYWxsJ1xuKTogU3RlcCB8IFN0ZXBXaXRob3V0RGF0YTtcbmV4cG9ydCBmdW5jdGlvbiBmaWx0ZXJTdGVwRGF0YShcbiAgc3RlcDogU3RlcCxcbiAgcmVzb2x2ZURhdGE6ICdub25lJyB8ICdhbGwnXG4pOiBTdGVwIHwgU3RlcFdpdGhvdXREYXRhIHtcbiAgaWYgKHJlc29sdmVEYXRhID09PSAnbm9uZScpIHtcbiAgICByZXR1cm4ge1xuICAgICAgLi4uc3RlcCxcbiAgICAgIGlucHV0OiB1bmRlZmluZWQsXG4gICAgICBvdXRwdXQ6IHVuZGVmaW5lZCxcbiAgICB9IGFzIFN0ZXBXaXRob3V0RGF0YTtcbiAgfVxuICByZXR1cm4gc3RlcDtcbn1cblxuLyoqXG4gKiBGaWx0ZXIgaG9vayBkYXRhIGJhc2VkIG9uIHJlc29sdmVEYXRhIHNldHRpbmcuXG4gKiBXaGVuIHJlc29sdmVEYXRhIGlzICdub25lJywgc3RyaXBzIG1ldGFkYXRhIHRvIHJlZHVjZSBwYXlsb2FkIHNpemUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmaWx0ZXJIb29rRGF0YShob29rOiBIb29rLCByZXNvbHZlRGF0YTogJ25vbmUnIHwgJ2FsbCcpOiBIb29rIHtcbiAgaWYgKHJlc29sdmVEYXRhID09PSAnbm9uZScpIHtcbiAgICBjb25zdCB7IG1ldGFkYXRhOiBfbWV0YWRhdGEsIC4uLnJlc3QgfSA9IGhvb2sgYXMgYW55O1xuICAgIHJldHVybiByZXN0O1xuICB9XG4gIHJldHVybiBob29rO1xufVxuIl19
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Hash a hook token to produce a filesystem-safe constraint filename.
3
+ */
4
+ export declare function hashToken(token: string): string;
5
+ /**
6
+ * Create a monotonic ULID factory that ensures ULIDs are always increasing
7
+ * even when generated within the same millisecond.
8
+ */
9
+ export declare const monotonicUlid: import("ulid").ULIDFactory;
10
+ /**
11
+ * Creates a function to extract createdAt date from a filename based on ULID.
12
+ * Used for efficient pagination without reading file contents.
13
+ *
14
+ * @param idPrefix - The prefix to strip from filenames (e.g., 'wrun', 'evnt', 'step')
15
+ * @returns A function that extracts Date from filename, or null if not extractable
16
+ */
17
+ export declare const getObjectCreatedAt: (idPrefix: string) => (filename: string) => Date | null;
18
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/storage/helpers.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa,4BAAwC,CAAC;AAEnE;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,GAC5B,UAAU,MAAM,MAChB,UAAU,MAAM,KAAG,IAAI,GAAG,IAyB1B,CAAC"}
@@ -0,0 +1,44 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { monotonicFactory } from 'ulid';
3
+ import { stripTag, ulidToDate } from '../fs.js';
4
+ /**
5
+ * Hash a hook token to produce a filesystem-safe constraint filename.
6
+ */
7
+ export function hashToken(token) {
8
+ return createHash('sha256').update(token).digest('hex');
9
+ }
10
+ /**
11
+ * Create a monotonic ULID factory that ensures ULIDs are always increasing
12
+ * even when generated within the same millisecond.
13
+ */
14
+ export const monotonicUlid = monotonicFactory(() => Math.random());
15
+ /**
16
+ * Creates a function to extract createdAt date from a filename based on ULID.
17
+ * Used for efficient pagination without reading file contents.
18
+ *
19
+ * @param idPrefix - The prefix to strip from filenames (e.g., 'wrun', 'evnt', 'step')
20
+ * @returns A function that extracts Date from filename, or null if not extractable
21
+ */
22
+ export const getObjectCreatedAt = (idPrefix) => (filename) => {
23
+ // Strip tag suffix before ULID extraction
24
+ // e.g., "wrun_ABC.vitest-0.json" → "wrun_ABC.json"
25
+ const cleanName = stripTag(filename.replace(/\.json$/, '')) + '.json';
26
+ const replaceRegex = new RegExp(`^${idPrefix}_`, 'g');
27
+ const dashIndex = cleanName.indexOf('-');
28
+ if (dashIndex === -1) {
29
+ // No dash - extract ULID from the filename (e.g., wrun_ULID.json, evnt_ULID.json)
30
+ const ulid = cleanName.replace(/\.json$/, '').replace(replaceRegex, '');
31
+ return ulidToDate(ulid);
32
+ }
33
+ // For composite keys like {runId}-{stepId}, extract from the appropriate part
34
+ if (idPrefix === 'step') {
35
+ // Steps use sequential IDs (step_0, step_1, etc.) - no timestamp in filename.
36
+ // Return null to skip filename-based optimization and defer to JSON-based filtering.
37
+ return null;
38
+ }
39
+ // For events: wrun_ULID-evnt_ULID.json - extract from the eventId part
40
+ const id = cleanName.substring(dashIndex + 1).replace(/\.json$/, '');
41
+ const ulid = id.replace(replaceRegex, '');
42
+ return ulidToDate(ulid);
43
+ };
44
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVscGVycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zdG9yYWdlL2hlbHBlcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUN6QyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDeEMsT0FBTyxFQUFFLFFBQVEsRUFBRSxVQUFVLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFFaEQ7O0dBRUc7QUFDSCxNQUFNLFVBQVUsU0FBUyxDQUFDLEtBQWE7SUFDckMsT0FBTyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUMxRCxDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sYUFBYSxHQUFHLGdCQUFnQixDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO0FBRW5FOzs7Ozs7R0FNRztBQUNILE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUM3QixDQUFDLFFBQWdCLEVBQUUsRUFBRSxDQUNyQixDQUFDLFFBQWdCLEVBQWUsRUFBRTtJQUNoQywwQ0FBMEM7SUFDMUMsbURBQW1EO0lBQ25ELE1BQU0sU0FBUyxHQUFHLFFBQVEsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUMsQ0FBQyxHQUFHLE9BQU8sQ0FBQztJQUV0RSxNQUFNLFlBQVksR0FBRyxJQUFJLE1BQU0sQ0FBQyxJQUFJLFFBQVEsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ3RELE1BQU0sU0FBUyxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7SUFFekMsSUFBSSxTQUFTLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUNyQixrRkFBa0Y7UUFDbEYsTUFBTSxJQUFJLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLFlBQVksRUFBRSxFQUFFLENBQUMsQ0FBQztRQUN4RSxPQUFPLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMxQixDQUFDO0lBRUQsOEVBQThFO0lBQzlFLElBQUksUUFBUSxLQUFLLE1BQU0sRUFBRSxDQUFDO1FBQ3hCLDhFQUE4RTtRQUM5RSxxRkFBcUY7UUFDckYsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQsdUVBQXVFO0lBQ3ZFLE1BQU0sRUFBRSxHQUFHLFNBQVMsQ0FBQyxTQUFTLENBQUMsU0FBUyxHQUFHLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDckUsTUFBTSxJQUFJLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxZQUFZLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDMUMsT0FBTyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDMUIsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3JlYXRlSGFzaCB9IGZyb20gJ25vZGU6Y3J5cHRvJztcbmltcG9ydCB7IG1vbm90b25pY0ZhY3RvcnkgfSBmcm9tICd1bGlkJztcbmltcG9ydCB7IHN0cmlwVGFnLCB1bGlkVG9EYXRlIH0gZnJvbSAnLi4vZnMuanMnO1xuXG4vKipcbiAqIEhhc2ggYSBob29rIHRva2VuIHRvIHByb2R1Y2UgYSBmaWxlc3lzdGVtLXNhZmUgY29uc3RyYWludCBmaWxlbmFtZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhhc2hUb2tlbih0b2tlbjogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGNyZWF0ZUhhc2goJ3NoYTI1NicpLnVwZGF0ZSh0b2tlbikuZGlnZXN0KCdoZXgnKTtcbn1cblxuLyoqXG4gKiBDcmVhdGUgYSBtb25vdG9uaWMgVUxJRCBmYWN0b3J5IHRoYXQgZW5zdXJlcyBVTElEcyBhcmUgYWx3YXlzIGluY3JlYXNpbmdcbiAqIGV2ZW4gd2hlbiBnZW5lcmF0ZWQgd2l0aGluIHRoZSBzYW1lIG1pbGxpc2Vjb25kLlxuICovXG5leHBvcnQgY29uc3QgbW9ub3RvbmljVWxpZCA9IG1vbm90b25pY0ZhY3RvcnkoKCkgPT4gTWF0aC5yYW5kb20oKSk7XG5cbi8qKlxuICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRvIGV4dHJhY3QgY3JlYXRlZEF0IGRhdGUgZnJvbSBhIGZpbGVuYW1lIGJhc2VkIG9uIFVMSUQuXG4gKiBVc2VkIGZvciBlZmZpY2llbnQgcGFnaW5hdGlvbiB3aXRob3V0IHJlYWRpbmcgZmlsZSBjb250ZW50cy5cbiAqXG4gKiBAcGFyYW0gaWRQcmVmaXggLSBUaGUgcHJlZml4IHRvIHN0cmlwIGZyb20gZmlsZW5hbWVzIChlLmcuLCAnd3J1bicsICdldm50JywgJ3N0ZXAnKVxuICogQHJldHVybnMgQSBmdW5jdGlvbiB0aGF0IGV4dHJhY3RzIERhdGUgZnJvbSBmaWxlbmFtZSwgb3IgbnVsbCBpZiBub3QgZXh0cmFjdGFibGVcbiAqL1xuZXhwb3J0IGNvbnN0IGdldE9iamVjdENyZWF0ZWRBdCA9XG4gIChpZFByZWZpeDogc3RyaW5nKSA9PlxuICAoZmlsZW5hbWU6IHN0cmluZyk6IERhdGUgfCBudWxsID0+IHtcbiAgICAvLyBTdHJpcCB0YWcgc3VmZml4IGJlZm9yZSBVTElEIGV4dHJhY3Rpb25cbiAgICAvLyBlLmcuLCBcIndydW5fQUJDLnZpdGVzdC0wLmpzb25cIiDihpIgXCJ3cnVuX0FCQy5qc29uXCJcbiAgICBjb25zdCBjbGVhbk5hbWUgPSBzdHJpcFRhZyhmaWxlbmFtZS5yZXBsYWNlKC9cXC5qc29uJC8sICcnKSkgKyAnLmpzb24nO1xuXG4gICAgY29uc3QgcmVwbGFjZVJlZ2V4ID0gbmV3IFJlZ0V4cChgXiR7aWRQcmVmaXh9X2AsICdnJyk7XG4gICAgY29uc3QgZGFzaEluZGV4ID0gY2xlYW5OYW1lLmluZGV4T2YoJy0nKTtcblxuICAgIGlmIChkYXNoSW5kZXggPT09IC0xKSB7XG4gICAgICAvLyBObyBkYXNoIC0gZXh0cmFjdCBVTElEIGZyb20gdGhlIGZpbGVuYW1lIChlLmcuLCB3cnVuX1VMSUQuanNvbiwgZXZudF9VTElELmpzb24pXG4gICAgICBjb25zdCB1bGlkID0gY2xlYW5OYW1lLnJlcGxhY2UoL1xcLmpzb24kLywgJycpLnJlcGxhY2UocmVwbGFjZVJlZ2V4LCAnJyk7XG4gICAgICByZXR1cm4gdWxpZFRvRGF0ZSh1bGlkKTtcbiAgICB9XG5cbiAgICAvLyBGb3IgY29tcG9zaXRlIGtleXMgbGlrZSB7cnVuSWR9LXtzdGVwSWR9LCBleHRyYWN0IGZyb20gdGhlIGFwcHJvcHJpYXRlIHBhcnRcbiAgICBpZiAoaWRQcmVmaXggPT09ICdzdGVwJykge1xuICAgICAgLy8gU3RlcHMgdXNlIHNlcXVlbnRpYWwgSURzIChzdGVwXzAsIHN0ZXBfMSwgZXRjLikgLSBubyB0aW1lc3RhbXAgaW4gZmlsZW5hbWUuXG4gICAgICAvLyBSZXR1cm4gbnVsbCB0byBza2lwIGZpbGVuYW1lLWJhc2VkIG9wdGltaXphdGlvbiBhbmQgZGVmZXIgdG8gSlNPTi1iYXNlZCBmaWx0ZXJpbmcuXG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICAvLyBGb3IgZXZlbnRzOiB3cnVuX1VMSUQtZXZudF9VTElELmpzb24gLSBleHRyYWN0IGZyb20gdGhlIGV2ZW50SWQgcGFydFxuICAgIGNvbnN0IGlkID0gY2xlYW5OYW1lLnN1YnN0cmluZyhkYXNoSW5kZXggKyAxKS5yZXBsYWNlKC9cXC5qc29uJC8sICcnKTtcbiAgICBjb25zdCB1bGlkID0gaWQucmVwbGFjZShyZXBsYWNlUmVnZXgsICcnKTtcbiAgICByZXR1cm4gdWxpZFRvRGF0ZSh1bGlkKTtcbiAgfTtcbiJdfQ==
@@ -0,0 +1,12 @@
1
+ import type { Storage } from '@workflow/world';
2
+ /**
3
+ * Creates a hooks storage implementation using the filesystem.
4
+ * Implements the Storage['hooks'] interface with hook CRUD operations.
5
+ */
6
+ export declare function createHooksStorage(basedir: string, tag?: string): Storage['hooks'];
7
+ /**
8
+ * Helper function to delete all hooks associated with a workflow run.
9
+ * Called when a run reaches a terminal state.
10
+ */
11
+ export declare function deleteAllHooksForRun(basedir: string, runId: string): Promise<void>;
12
+ //# sourceMappingURL=hooks-storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks-storage.d.ts","sourceRoot":"","sources":["../../src/storage/hooks-storage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAKV,OAAO,EACR,MAAM,iBAAiB,CAAC;AAczB;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,OAAO,CAAC,CAiFlB;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAkBf"}
@@ -0,0 +1,93 @@
1
+ import path from 'node:path';
2
+ import { HookNotFoundError } from '@workflow/errors';
3
+ import { HookSchema } from '@workflow/world';
4
+ import { DEFAULT_RESOLVE_DATA_OPTION } from '../config.js';
5
+ import { assertSafeEntityId, deleteJSON, listJSONFiles, paginatedFileSystemQuery, readJSON, readJSONWithFallback, } from '../fs.js';
6
+ import { filterHookData } from './filters.js';
7
+ import { hashToken } from './helpers.js';
8
+ /**
9
+ * Creates a hooks storage implementation using the filesystem.
10
+ * Implements the Storage['hooks'] interface with hook CRUD operations.
11
+ */
12
+ export function createHooksStorage(basedir, tag) {
13
+ // Helper function to find a hook by token (shared between getByToken)
14
+ async function findHookByToken(token) {
15
+ const hooksDir = path.join(basedir, 'hooks');
16
+ const files = await listJSONFiles(hooksDir);
17
+ for (const file of files) {
18
+ const hookPath = path.join(hooksDir, `${file}.json`);
19
+ const hook = await readJSON(hookPath, HookSchema);
20
+ if (hook && hook.token === token) {
21
+ return { ...hook, isWebhook: hook.isWebhook ?? true };
22
+ }
23
+ }
24
+ return null;
25
+ }
26
+ async function get(hookId, params) {
27
+ assertSafeEntityId('hookId', hookId);
28
+ const hook = await readJSONWithFallback(basedir, 'hooks', hookId, HookSchema, tag);
29
+ if (!hook) {
30
+ throw new HookNotFoundError(hookId);
31
+ }
32
+ const resolveData = params?.resolveData || DEFAULT_RESOLVE_DATA_OPTION;
33
+ return filterHookData({ ...hook, isWebhook: hook.isWebhook ?? true }, resolveData);
34
+ }
35
+ async function getByToken(token) {
36
+ const hook = await findHookByToken(token);
37
+ if (!hook) {
38
+ throw new HookNotFoundError(token);
39
+ }
40
+ return hook;
41
+ }
42
+ async function list(params) {
43
+ const hooksDir = path.join(basedir, 'hooks');
44
+ const resolveData = params.resolveData || DEFAULT_RESOLVE_DATA_OPTION;
45
+ const result = await paginatedFileSystemQuery({
46
+ directory: hooksDir,
47
+ schema: HookSchema,
48
+ sortOrder: params.pagination?.sortOrder ?? 'asc',
49
+ limit: params.pagination?.limit,
50
+ cursor: params.pagination?.cursor,
51
+ filePrefix: undefined, // Hooks don't have ULIDs, so we can't optimize by filename
52
+ filter: (hook) => {
53
+ // Filter by runId if provided
54
+ if (params.runId && hook.runId !== params.runId) {
55
+ return false;
56
+ }
57
+ return true;
58
+ },
59
+ getCreatedAt: () => {
60
+ // Hook files don't have ULID timestamps in filename, so return null
61
+ // to skip the filename-based optimization and defer to JSON-based
62
+ // cursor filtering which uses the actual createdAt from the file.
63
+ return null;
64
+ },
65
+ getId: (hook) => hook.hookId,
66
+ });
67
+ // Transform the data after pagination
68
+ return {
69
+ ...result,
70
+ data: result.data.map((hook) => filterHookData(hook, resolveData)),
71
+ };
72
+ }
73
+ return { get, getByToken, list };
74
+ }
75
+ /**
76
+ * Helper function to delete all hooks associated with a workflow run.
77
+ * Called when a run reaches a terminal state.
78
+ */
79
+ export async function deleteAllHooksForRun(basedir, runId) {
80
+ const hooksDir = path.join(basedir, 'hooks');
81
+ const files = await listJSONFiles(hooksDir);
82
+ for (const file of files) {
83
+ const hookPath = path.join(hooksDir, `${file}.json`);
84
+ const hook = await readJSON(hookPath, HookSchema);
85
+ if (hook && hook.runId === runId) {
86
+ // Delete the token constraint file to free up the token
87
+ const constraintPath = path.join(hooksDir, 'tokens', `${hashToken(hook.token)}.json`);
88
+ await deleteJSON(constraintPath);
89
+ await deleteJSON(hookPath);
90
+ }
91
+ }
92
+ }
93
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaG9va3Mtc3RvcmFnZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zdG9yYWdlL2hvb2tzLXN0b3JhZ2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBQzdCLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBUXJELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUM3QyxPQUFPLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDM0QsT0FBTyxFQUNMLGtCQUFrQixFQUNsQixVQUFVLEVBQ1YsYUFBYSxFQUNiLHdCQUF3QixFQUN4QixRQUFRLEVBQ1Isb0JBQW9CLEdBQ3JCLE1BQU0sVUFBVSxDQUFDO0FBQ2xCLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDOUMsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUV6Qzs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsa0JBQWtCLENBQ2hDLE9BQWUsRUFDZixHQUFZO0lBRVosc0VBQXNFO0lBQ3RFLEtBQUssVUFBVSxlQUFlLENBQUMsS0FBYTtRQUMxQyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztRQUM3QyxNQUFNLEtBQUssR0FBRyxNQUFNLGFBQWEsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUU1QyxLQUFLLE1BQU0sSUFBSSxJQUFJLEtBQUssRUFBRSxDQUFDO1lBQ3pCLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLEdBQUcsSUFBSSxPQUFPLENBQUMsQ0FBQztZQUNyRCxNQUFNLElBQUksR0FBRyxNQUFNLFFBQVEsQ0FBQyxRQUFRLEVBQUUsVUFBVSxDQUFDLENBQUM7WUFDbEQsSUFBSSxJQUFJLElBQUksSUFBSSxDQUFDLEtBQUss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LE9BQWUsRUFDZixLQUFhO0lBRWIsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDN0MsTUFBTSxLQUFLLEdBQUcsTUFBTSxhQUFhLENBQUMsUUFBUSxDQUFDLENBQUM7SUFFNUMsS0FBSyxNQUFNLElBQUksSUFBSSxLQUFLLEVBQUUsQ0FBQztRQUN6QixNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxHQUFHLElBQUksT0FBTyxDQUFDLENBQUM7UUFDckQsTUFBTSxJQUFJLEdBQUcsTUFBTSxRQUFRLENBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxDQUFDO1FBQ2xELElBQUksSUFBSSxJQUFJLElBQUksQ0FBQyxLQUFLLEtBQUssS0FBSyxFQUFFLENBQUM7WUFDakMsd0RBQXdEO1lBQ3hELE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQzlCLFFBQVEsRUFDUixRQUFRLEVBQ1IsR0FBRyxTQUFTLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQ2hDLENBQUM7WUFDRixNQUFNLFVBQVUsQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUNqQyxNQUFNLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUM3QixDQUFDO0lBQ0gsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgcGF0aCBmcm9tICdub2RlOnBhdGgnO1xuaW1wb3J0IHsgSG9va05vdEZvdW5kRXJyb3IgfSBmcm9tICdAd29ya2Zsb3cvZXJyb3JzJztcbmltcG9ydCB0eXBlIHtcbiAgR2V0SG9va1BhcmFtcyxcbiAgSG9vayxcbiAgTGlzdEhvb2tzUGFyYW1zLFxuICBQYWdpbmF0ZWRSZXNwb25zZSxcbiAgU3RvcmFnZSxcbn0gZnJvbSAnQHdvcmtmbG93L3dvcmxkJztcbmltcG9ydCB7IEhvb2tTY2hlbWEgfSBmcm9tICdAd29ya2Zsb3cvd29ybGQnO1xuaW1wb3J0IHsgREVGQVVMVF9SRVNPTFZFX0RBVEFfT1BUSU9OIH0gZnJvbSAnLi4vY29uZmlnLmpzJztcbmltcG9ydCB7XG4gIGFzc2VydFNhZmVFbnRpdHlJZCxcbiAgZGVsZXRlSlNPTixcbiAgbGlzdEpTT05GaWxlcyxcbiAgcGFnaW5hdGVkRmlsZVN5c3RlbVF1ZXJ5LFxuICByZWFkSlNPTixcbiAgcmVhZEpTT05XaXRoRmFsbGJhY2ssXG59IGZyb20gJy4uL2ZzLmpzJztcbmltcG9ydCB7IGZpbHRlckhvb2tEYXRhIH0gZnJvbSAnLi9maWx0ZXJzLmpzJztcbmltcG9ydCB7IGhhc2hUb2tlbiB9IGZyb20gJy4vaGVscGVycy5qcyc7XG5cbi8qKlxuICogQ3JlYXRlcyBhIGhvb2tzIHN0b3JhZ2UgaW1wbGVtZW50YXRpb24gdXNpbmcgdGhlIGZpbGVzeXN0ZW0uXG4gKiBJbXBsZW1lbnRzIHRoZSBTdG9yYWdlWydob29rcyddIGludGVyZmFjZSB3aXRoIGhvb2sgQ1JVRCBvcGVyYXRpb25zLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlSG9va3NTdG9yYWdlKFxuICBiYXNlZGlyOiBzdHJpbmcsXG4gIHRhZz86IHN0cmluZ1xuKTogU3RvcmFnZVsnaG9va3MnXSB7XG4gIC8vIEhlbHBlciBmdW5jdGlvbiB0byBmaW5kIGEgaG9vayBieSB0b2tlbiAoc2hhcmVkIGJldHdlZW4gZ2V0QnlUb2tlbilcbiAgYXN5bmMgZnVuY3Rpb24gZmluZEhvb2tCeVRva2VuKHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPEhvb2sgfCBudWxsPiB7XG4gICAgY29uc3QgaG9va3NEaXIgPSBwYXRoLmpvaW4oYmFzZWRpciwgJ2hvb2tzJyk7XG4gICAgY29uc3QgZmlsZXMgPSBhd2FpdCBsaXN0SlNPTkZpbGVzKGhvb2tzRGlyKTtcblxuICAgIGZvciAoY29uc3QgZmlsZSBvZiBmaWxlcykge1xuICAgICAgY29uc3QgaG9va1BhdGggPSBwYXRoLmpvaW4oaG9va3NEaXIsIGAke2ZpbGV9Lmpzb25gKTtcbiAgICAgIGNvbnN0IGhvb2sgPSBhd2FpdCByZWFkSlNPTihob29rUGF0aCwgSG9va1NjaGVtYSk7XG4gICAgICBpZiAoaG9vayAmJiBob29rLnRva2VuID09PSB0b2tlbikge1xuICAgICAgICByZXR1cm4geyAuLi5ob29rLCBpc1dlYmhvb2s6IGhvb2suaXNXZWJob29rID8/IHRydWUgfTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGFzeW5jIGZ1bmN0aW9uIGdldChob29rSWQ6IHN0cmluZywgcGFyYW1zPzogR2V0SG9va1BhcmFtcyk6IFByb21pc2U8SG9vaz4ge1xuICAgIGFzc2VydFNhZmVFbnRpdHlJZCgnaG9va0lkJywgaG9va0lkKTtcbiAgICBjb25zdCBob29rID0gYXdhaXQgcmVhZEpTT05XaXRoRmFsbGJhY2soXG4gICAgICBiYXNlZGlyLFxuICAgICAgJ2hvb2tzJyxcbiAgICAgIGhvb2tJZCxcbiAgICAgIEhvb2tTY2hlbWEsXG4gICAgICB0YWdcbiAgICApO1xuICAgIGlmICghaG9vaykge1xuICAgICAgdGhyb3cgbmV3IEhvb2tOb3RGb3VuZEVycm9yKGhvb2tJZCk7XG4gICAgfVxuICAgIGNvbnN0IHJlc29sdmVEYXRhID0gcGFyYW1zPy5yZXNvbHZlRGF0YSB8fCBERUZBVUxUX1JFU09MVkVfREFUQV9PUFRJT047XG4gICAgcmV0dXJuIGZpbHRlckhvb2tEYXRhKFxuICAgICAgeyAuLi5ob29rLCBpc1dlYmhvb2s6IGhvb2suaXNXZWJob29rID8/IHRydWUgfSxcbiAgICAgIHJlc29sdmVEYXRhXG4gICAgKTtcbiAgfVxuXG4gIGFzeW5jIGZ1bmN0aW9uIGdldEJ5VG9rZW4odG9rZW46IHN0cmluZyk6IFByb21pc2U8SG9vaz4ge1xuICAgIGNvbnN0IGhvb2sgPSBhd2FpdCBmaW5kSG9va0J5VG9rZW4odG9rZW4pO1xuICAgIGlmICghaG9vaykge1xuICAgICAgdGhyb3cgbmV3IEhvb2tOb3RGb3VuZEVycm9yKHRva2VuKTtcbiAgICB9XG4gICAgcmV0dXJuIGhvb2s7XG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiBsaXN0KFxuICAgIHBhcmFtczogTGlzdEhvb2tzUGFyYW1zXG4gICk6IFByb21pc2U8UGFnaW5hdGVkUmVzcG9uc2U8SG9vaz4+IHtcbiAgICBjb25zdCBob29rc0RpciA9IHBhdGguam9pbihiYXNlZGlyLCAnaG9va3MnKTtcbiAgICBjb25zdCByZXNvbHZlRGF0YSA9IHBhcmFtcy5yZXNvbHZlRGF0YSB8fCBERUZBVUxUX1JFU09MVkVfREFUQV9PUFRJT047XG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBwYWdpbmF0ZWRGaWxlU3lzdGVtUXVlcnkoe1xuICAgICAgZGlyZWN0b3J5OiBob29rc0RpcixcbiAgICAgIHNjaGVtYTogSG9va1NjaGVtYSxcbiAgICAgIHNvcnRPcmRlcjogcGFyYW1zLnBhZ2luYXRpb24/LnNvcnRPcmRlciA/PyAnYXNjJyxcbiAgICAgIGxpbWl0OiBwYXJhbXMucGFnaW5hdGlvbj8ubGltaXQsXG4gICAgICBjdXJzb3I6IHBhcmFtcy5wYWdpbmF0aW9uPy5jdXJzb3IsXG4gICAgICBmaWxlUHJlZml4OiB1bmRlZmluZWQsIC8vIEhvb2tzIGRvbid0IGhhdmUgVUxJRHMsIHNvIHdlIGNhbid0IG9wdGltaXplIGJ5IGZpbGVuYW1lXG4gICAgICBmaWx0ZXI6IChob29rKSA9PiB7XG4gICAgICAgIC8vIEZpbHRlciBieSBydW5JZCBpZiBwcm92aWRlZFxuICAgICAgICBpZiAocGFyYW1zLnJ1bklkICYmIGhvb2sucnVuSWQgIT09IHBhcmFtcy5ydW5JZCkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0sXG4gICAgICBnZXRDcmVhdGVkQXQ6ICgpID0+IHtcbiAgICAgICAgLy8gSG9vayBmaWxlcyBkb24ndCBoYXZlIFVMSUQgdGltZXN0YW1wcyBpbiBmaWxlbmFtZSwgc28gcmV0dXJuIG51bGxcbiAgICAgICAgLy8gdG8gc2tpcCB0aGUgZmlsZW5hbWUtYmFzZWQgb3B0aW1pemF0aW9uIGFuZCBkZWZlciB0byBKU09OLWJhc2VkXG4gICAgICAgIC8vIGN1cnNvciBmaWx0ZXJpbmcgd2hpY2ggdXNlcyB0aGUgYWN0dWFsIGNyZWF0ZWRBdCBmcm9tIHRoZSBmaWxlLlxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH0sXG4gICAgICBnZXRJZDogKGhvb2spID0+IGhvb2suaG9va0lkLFxuICAgIH0pO1xuXG4gICAgLy8gVHJhbnNmb3JtIHRoZSBkYXRhIGFmdGVyIHBhZ2luYXRpb25cbiAgICByZXR1cm4ge1xuICAgICAgLi4ucmVzdWx0LFxuICAgICAgZGF0YTogcmVzdWx0LmRhdGEubWFwKChob29rKSA9PiBmaWx0ZXJIb29rRGF0YShob29rLCByZXNvbHZlRGF0YSkpLFxuICAgIH07XG4gIH1cblxuICByZXR1cm4geyBnZXQsIGdldEJ5VG9rZW4sIGxpc3QgfTtcbn1cblxuLyoqXG4gKiBIZWxwZXIgZnVuY3Rpb24gdG8gZGVsZXRlIGFsbCBob29rcyBhc3NvY2lhdGVkIHdpdGggYSB3b3JrZmxvdyBydW4uXG4gKiBDYWxsZWQgd2hlbiBhIHJ1biByZWFjaGVzIGEgdGVybWluYWwgc3RhdGUuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkZWxldGVBbGxIb29rc0ZvclJ1bihcbiAgYmFzZWRpcjogc3RyaW5nLFxuICBydW5JZDogc3RyaW5nXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgaG9va3NEaXIgPSBwYXRoLmpvaW4oYmFzZWRpciwgJ2hvb2tzJyk7XG4gIGNvbnN0IGZpbGVzID0gYXdhaXQgbGlzdEpTT05GaWxlcyhob29rc0Rpcik7XG5cbiAgZm9yIChjb25zdCBmaWxlIG9mIGZpbGVzKSB7XG4gICAgY29uc3QgaG9va1BhdGggPSBwYXRoLmpvaW4oaG9va3NEaXIsIGAke2ZpbGV9Lmpzb25gKTtcbiAgICBjb25zdCBob29rID0gYXdhaXQgcmVhZEpTT04oaG9va1BhdGgsIEhvb2tTY2hlbWEpO1xuICAgIGlmIChob29rICYmIGhvb2sucnVuSWQgPT09IHJ1bklkKSB7XG4gICAgICAvLyBEZWxldGUgdGhlIHRva2VuIGNvbnN0cmFpbnQgZmlsZSB0byBmcmVlIHVwIHRoZSB0b2tlblxuICAgICAgY29uc3QgY29uc3RyYWludFBhdGggPSBwYXRoLmpvaW4oXG4gICAgICAgIGhvb2tzRGlyLFxuICAgICAgICAndG9rZW5zJyxcbiAgICAgICAgYCR7aGFzaFRva2VuKGhvb2sudG9rZW4pfS5qc29uYFxuICAgICAgKTtcbiAgICAgIGF3YWl0IGRlbGV0ZUpTT04oY29uc3RyYWludFBhdGgpO1xuICAgICAgYXdhaXQgZGVsZXRlSlNPTihob29rUGF0aCk7XG4gICAgfVxuICB9XG59XG4iXX0=
@@ -0,0 +1,21 @@
1
+ import type { Storage } from '@workflow/world';
2
+ import { type LocalRunsStorage } from './runs-storage.js';
3
+ /**
4
+ * Storage shape used inside world-local: identical to `Storage`, but `runs`
5
+ * exposes the internal `fileIdFilter` option on `list()`. Structurally
6
+ * assignable to `Storage` at public boundaries (e.g., `reenqueueActiveRuns`).
7
+ */
8
+ export type LocalStorage = Omit<Storage, 'runs'> & {
9
+ runs: LocalRunsStorage;
10
+ };
11
+ /**
12
+ * Creates a complete storage implementation using the filesystem.
13
+ * This is the main entry point that composes all storage implementations.
14
+ *
15
+ * All storage methods are instrumented with tracing spans for observability.
16
+ *
17
+ * @param basedir - The base directory for storing workflow data
18
+ * @returns A complete Storage implementation with tracing
19
+ */
20
+ export declare function createStorage(basedir: string, tag?: string): LocalStorage;
21
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAI/C,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAG7E;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG;IAAE,IAAI,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAE9E;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,YAAY,CAezE"}
@@ -0,0 +1,30 @@
1
+ import { instrumentObject } from '../instrumentObject.js';
2
+ import { createEventsStorage } from './events-storage.js';
3
+ import { createHooksStorage } from './hooks-storage.js';
4
+ import { createRunsStorage } from './runs-storage.js';
5
+ import { createStepsStorage } from './steps-storage.js';
6
+ /**
7
+ * Creates a complete storage implementation using the filesystem.
8
+ * This is the main entry point that composes all storage implementations.
9
+ *
10
+ * All storage methods are instrumented with tracing spans for observability.
11
+ *
12
+ * @param basedir - The base directory for storing workflow data
13
+ * @returns A complete Storage implementation with tracing
14
+ */
15
+ export function createStorage(basedir, tag) {
16
+ // Create raw storage implementations
17
+ const runs = createRunsStorage(basedir, tag);
18
+ const steps = createStepsStorage(basedir, tag);
19
+ const events = createEventsStorage(basedir, tag);
20
+ const hooks = createHooksStorage(basedir, tag);
21
+ // Instrument all storage methods with tracing
22
+ // NOTE: Span names are lowercase per OTEL semantic conventions
23
+ return {
24
+ runs: instrumentObject('world.runs', runs),
25
+ steps: instrumentObject('world.steps', steps),
26
+ events: instrumentObject('world.events', events),
27
+ hooks: instrumentObject('world.hooks', hooks),
28
+ };
29
+ }
30
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc3RvcmFnZS9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUMxRCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUN4RCxPQUFPLEVBQUUsaUJBQWlCLEVBQXlCLE1BQU0sbUJBQW1CLENBQUM7QUFDN0UsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFTeEQ7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLFVBQVUsYUFBYSxDQUFDLE9BQWUsRUFBRSxHQUFZO0lBQ3pELHFDQUFxQztJQUNyQyxNQUFNLElBQUksR0FBRyxpQkFBaUIsQ0FBQyxPQUFPLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDN0MsTUFBTSxLQUFLLEdBQUcsa0JBQWtCLENBQUMsT0FBTyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQy9DLE1BQU0sTUFBTSxHQUFHLG1CQUFtQixDQUFDLE9BQU8sRUFBRSxHQUFHLENBQUMsQ0FBQztJQUNqRCxNQUFNLEtBQUssR0FBRyxrQkFBa0IsQ0FBQyxPQUFPLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFFL0MsOENBQThDO0lBQzlDLCtEQUErRDtJQUMvRCxPQUFPO1FBQ0wsSUFBSSxFQUFFLGdCQUFnQixDQUFDLFlBQVksRUFBRSxJQUFJLENBQUM7UUFDMUMsS0FBSyxFQUFFLGdCQUFnQixDQUFDLGFBQWEsRUFBRSxLQUFLLENBQUM7UUFDN0MsTUFBTSxFQUFFLGdCQUFnQixDQUFDLGNBQWMsRUFBRSxNQUFNLENBQUM7UUFDaEQsS0FBSyxFQUFFLGdCQUFnQixDQUFDLGFBQWEsRUFBRSxLQUFLLENBQUM7S0FDOUMsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IFN0b3JhZ2UgfSBmcm9tICdAd29ya2Zsb3cvd29ybGQnO1xuaW1wb3J0IHsgaW5zdHJ1bWVudE9iamVjdCB9IGZyb20gJy4uL2luc3RydW1lbnRPYmplY3QuanMnO1xuaW1wb3J0IHsgY3JlYXRlRXZlbnRzU3RvcmFnZSB9IGZyb20gJy4vZXZlbnRzLXN0b3JhZ2UuanMnO1xuaW1wb3J0IHsgY3JlYXRlSG9va3NTdG9yYWdlIH0gZnJvbSAnLi9ob29rcy1zdG9yYWdlLmpzJztcbmltcG9ydCB7IGNyZWF0ZVJ1bnNTdG9yYWdlLCB0eXBlIExvY2FsUnVuc1N0b3JhZ2UgfSBmcm9tICcuL3J1bnMtc3RvcmFnZS5qcyc7XG5pbXBvcnQgeyBjcmVhdGVTdGVwc1N0b3JhZ2UgfSBmcm9tICcuL3N0ZXBzLXN0b3JhZ2UuanMnO1xuXG4vKipcbiAqIFN0b3JhZ2Ugc2hhcGUgdXNlZCBpbnNpZGUgd29ybGQtbG9jYWw6IGlkZW50aWNhbCB0byBgU3RvcmFnZWAsIGJ1dCBgcnVuc2BcbiAqIGV4cG9zZXMgdGhlIGludGVybmFsIGBmaWxlSWRGaWx0ZXJgIG9wdGlvbiBvbiBgbGlzdCgpYC4gU3RydWN0dXJhbGx5XG4gKiBhc3NpZ25hYmxlIHRvIGBTdG9yYWdlYCBhdCBwdWJsaWMgYm91bmRhcmllcyAoZS5nLiwgYHJlZW5xdWV1ZUFjdGl2ZVJ1bnNgKS5cbiAqL1xuZXhwb3J0IHR5cGUgTG9jYWxTdG9yYWdlID0gT21pdDxTdG9yYWdlLCAncnVucyc+ICYgeyBydW5zOiBMb2NhbFJ1bnNTdG9yYWdlIH07XG5cbi8qKlxuICogQ3JlYXRlcyBhIGNvbXBsZXRlIHN0b3JhZ2UgaW1wbGVtZW50YXRpb24gdXNpbmcgdGhlIGZpbGVzeXN0ZW0uXG4gKiBUaGlzIGlzIHRoZSBtYWluIGVudHJ5IHBvaW50IHRoYXQgY29tcG9zZXMgYWxsIHN0b3JhZ2UgaW1wbGVtZW50YXRpb25zLlxuICpcbiAqIEFsbCBzdG9yYWdlIG1ldGhvZHMgYXJlIGluc3RydW1lbnRlZCB3aXRoIHRyYWNpbmcgc3BhbnMgZm9yIG9ic2VydmFiaWxpdHkuXG4gKlxuICogQHBhcmFtIGJhc2VkaXIgLSBUaGUgYmFzZSBkaXJlY3RvcnkgZm9yIHN0b3Jpbmcgd29ya2Zsb3cgZGF0YVxuICogQHJldHVybnMgQSBjb21wbGV0ZSBTdG9yYWdlIGltcGxlbWVudGF0aW9uIHdpdGggdHJhY2luZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlU3RvcmFnZShiYXNlZGlyOiBzdHJpbmcsIHRhZz86IHN0cmluZyk6IExvY2FsU3RvcmFnZSB7XG4gIC8vIENyZWF0ZSByYXcgc3RvcmFnZSBpbXBsZW1lbnRhdGlvbnNcbiAgY29uc3QgcnVucyA9IGNyZWF0ZVJ1bnNTdG9yYWdlKGJhc2VkaXIsIHRhZyk7XG4gIGNvbnN0IHN0ZXBzID0gY3JlYXRlU3RlcHNTdG9yYWdlKGJhc2VkaXIsIHRhZyk7XG4gIGNvbnN0IGV2ZW50cyA9IGNyZWF0ZUV2ZW50c1N0b3JhZ2UoYmFzZWRpciwgdGFnKTtcbiAgY29uc3QgaG9va3MgPSBjcmVhdGVIb29rc1N0b3JhZ2UoYmFzZWRpciwgdGFnKTtcblxuICAvLyBJbnN0cnVtZW50IGFsbCBzdG9yYWdlIG1ldGhvZHMgd2l0aCB0cmFjaW5nXG4gIC8vIE5PVEU6IFNwYW4gbmFtZXMgYXJlIGxvd2VyY2FzZSBwZXIgT1RFTCBzZW1hbnRpYyBjb252ZW50aW9uc1xuICByZXR1cm4ge1xuICAgIHJ1bnM6IGluc3RydW1lbnRPYmplY3QoJ3dvcmxkLnJ1bnMnLCBydW5zKSxcbiAgICBzdGVwczogaW5zdHJ1bWVudE9iamVjdCgnd29ybGQuc3RlcHMnLCBzdGVwcyksXG4gICAgZXZlbnRzOiBpbnN0cnVtZW50T2JqZWN0KCd3b3JsZC5ldmVudHMnLCBldmVudHMpLFxuICAgIGhvb2tzOiBpbnN0cnVtZW50T2JqZWN0KCd3b3JsZC5ob29rcycsIGhvb2tzKSxcbiAgfTtcbn1cbiJdfQ==
@@ -0,0 +1,13 @@
1
+ import type { EventResult, WorkflowRun } from '@workflow/world';
2
+ /**
3
+ * Handle events for legacy runs (pre-event-sourcing, specVersion < 2).
4
+ * Legacy runs use different behavior:
5
+ * - run_cancelled: Skip event storage, directly update run
6
+ * - wait_completed: Store event only (no entity mutation)
7
+ * - hook_received: Store event only (hooks exist via old system, no entity mutation)
8
+ * - Other events: Throw error (not supported for legacy runs)
9
+ */
10
+ export declare function handleLegacyEvent(basedir: string, runId: string, data: any, currentRun: WorkflowRun, params?: {
11
+ resolveData?: 'none' | 'all';
12
+ }): Promise<EventResult>;
13
+ //# sourceMappingURL=legacy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"legacy.d.ts","sourceRoot":"","sources":["../../src/storage/legacy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAS,WAAW,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAQvE;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,GAAG,EACT,UAAU,EAAE,WAAW,EACvB,MAAM,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;CAAE,GACxC,OAAO,CAAC,WAAW,CAAC,CAwEtB"}
@@ -0,0 +1,78 @@
1
+ import { SPEC_VERSION_CURRENT } from '@workflow/world';
2
+ import { DEFAULT_RESOLVE_DATA_OPTION } from '../config.js';
3
+ import { assertSafeEntityId, resolveWithinBase, writeJSON } from '../fs.js';
4
+ import { filterRunData, stripEventDataRefs } from './filters.js';
5
+ import { monotonicUlid } from './helpers.js';
6
+ import { deleteAllHooksForRun } from './hooks-storage.js';
7
+ /**
8
+ * Handle events for legacy runs (pre-event-sourcing, specVersion < 2).
9
+ * Legacy runs use different behavior:
10
+ * - run_cancelled: Skip event storage, directly update run
11
+ * - wait_completed: Store event only (no entity mutation)
12
+ * - hook_received: Store event only (hooks exist via old system, no entity mutation)
13
+ * - Other events: Throw error (not supported for legacy runs)
14
+ */
15
+ export async function handleLegacyEvent(basedir, runId, data, currentRun, params) {
16
+ // Defense in depth: events.create already validates runId before routing
17
+ // here, but handleLegacyEvent is exported and its signature doesn't
18
+ // document that invariant. Validating locally keeps the guarantee in this
19
+ // file.
20
+ assertSafeEntityId('runId', runId);
21
+ const resolveData = params?.resolveData ?? DEFAULT_RESOLVE_DATA_OPTION;
22
+ switch (data.eventType) {
23
+ case 'run_cancelled': {
24
+ // Legacy: Skip event storage, directly update run to cancelled
25
+ const now = new Date();
26
+ const run = {
27
+ runId: currentRun.runId,
28
+ deploymentId: currentRun.deploymentId,
29
+ workflowName: currentRun.workflowName,
30
+ specVersion: currentRun.specVersion,
31
+ executionContext: currentRun.executionContext,
32
+ input: currentRun.input,
33
+ createdAt: currentRun.createdAt,
34
+ expiredAt: currentRun.expiredAt,
35
+ startedAt: currentRun.startedAt,
36
+ status: 'cancelled',
37
+ output: undefined,
38
+ error: undefined,
39
+ completedAt: now,
40
+ updatedAt: now,
41
+ attributes: currentRun.attributes,
42
+ };
43
+ const runPath = resolveWithinBase(basedir, 'runs', `${runId}.json`);
44
+ await writeJSON(runPath, run, { overwrite: true });
45
+ await deleteAllHooksForRun(basedir, runId);
46
+ // Return without event (legacy behavior skips event storage)
47
+ // Type assertion: EventResult expects WorkflowRun, filterRunData may return WorkflowRunWithoutData
48
+ return {
49
+ event: undefined,
50
+ run: filterRunData(run, resolveData),
51
+ };
52
+ }
53
+ case 'wait_completed':
54
+ case 'hook_received': {
55
+ // Legacy: Store event only (no entity mutation)
56
+ // - wait_completed: for replay purposes
57
+ // - hook_received: hooks exist via old system, just record the event
58
+ const eventId = `evnt_${monotonicUlid()}`;
59
+ const now = new Date();
60
+ const event = {
61
+ ...data,
62
+ runId,
63
+ eventId,
64
+ createdAt: now,
65
+ specVersion: SPEC_VERSION_CURRENT,
66
+ };
67
+ const compositeKey = `${runId}-${eventId}`;
68
+ const eventPath = resolveWithinBase(basedir, 'events', `${compositeKey}.json`);
69
+ await writeJSON(eventPath, event);
70
+ return { event: stripEventDataRefs(event, resolveData) };
71
+ }
72
+ default:
73
+ throw new Error(`Event type '${data.eventType}' not supported for legacy runs ` +
74
+ `(specVersion: ${currentRun.specVersion || 'undefined'}). ` +
75
+ `Please upgrade 'workflow' package.`);
76
+ }
77
+ }
78
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGVnYWN5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3N0b3JhZ2UvbGVnYWN5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUMzRCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsaUJBQWlCLEVBQUUsU0FBUyxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBQzVFLE9BQU8sRUFBRSxhQUFhLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDakUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUM3QyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUUxRDs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxpQkFBaUIsQ0FDckMsT0FBZSxFQUNmLEtBQWEsRUFDYixJQUFTLEVBQ1QsVUFBdUIsRUFDdkIsTUFBeUM7SUFFekMseUVBQXlFO0lBQ3pFLG9FQUFvRTtJQUNwRSwwRUFBMEU7SUFDMUUsUUFBUTtJQUNSLGtCQUFrQixDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsQ0FBQztJQUVuQyxNQUFNLFdBQVcsR0FBRyxNQUFNLEVBQUUsV0FBVyxJQUFJLDJCQUEyQixDQUFDO0lBRXZFLFFBQVEsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ3ZCLEtBQUssZUFBZSxDQUFDLENBQUMsQ0FBQztZQUNyQiwrREFBK0Q7WUFDL0QsTUFBTSxHQUFHLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQztZQUN2QixNQUFNLEdBQUcsR0FBZ0I7Z0JBQ3ZCLEtBQUssRUFBRSxVQUFVLENBQUMsS0FBSztnQkFDdkIsWUFBWSxFQUFFLFVBQVUsQ0FBQyxZQUFZO2dCQUNyQyxZQUFZLEVBQUUsVUFBVSxDQUFDLFlBQVk7Z0JBQ3JDLFdBQVcsRUFBRSxVQUFVLENBQUMsV0FBVztnQkFDbkMsZ0JBQWdCLEVBQUUsVUFBVSxDQUFDLGdCQUFnQjtnQkFDN0MsS0FBSyxFQUFFLFVBQVUsQ0FBQyxLQUFLO2dCQUN2QixTQUFTLEVBQUUsVUFBVSxDQUFDLFNBQVM7Z0JBQy9CLFNBQVMsRUFBRSxVQUFVLENBQUMsU0FBUztnQkFDL0IsU0FBUyxFQUFFLFVBQVUsQ0FBQyxTQUFTO2dCQUMvQixNQUFNLEVBQUUsV0FBVztnQkFDbkIsTUFBTSxFQUFFLFNBQVM7Z0JBQ2pCLEtBQUssRUFBRSxTQUFTO2dCQUNoQixXQUFXLEVBQUUsR0FBRztnQkFDaEIsU0FBUyxFQUFFLEdBQUc7Z0JBQ2QsVUFBVSxFQUFFLFVBQVUsQ0FBQyxVQUFVO2FBQ2xDLENBQUM7WUFDRixNQUFNLE9BQU8sR0FBRyxpQkFBaUIsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEdBQUcsS0FBSyxPQUFPLENBQUMsQ0FBQztZQUNwRSxNQUFNLFNBQVMsQ0FBQyxPQUFPLEVBQUUsR0FBRyxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7WUFDbkQsTUFBTSxvQkFBb0IsQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDM0MsNkRBQTZEO1lBQzdELG1HQUFtRztZQUNuRyxPQUFPO2dCQUNMLEtBQUssRUFBRSxTQUFTO2dCQUNoQixHQUFHLEVBQUUsYUFBYSxDQUFDLEdBQUcsRUFBRSxXQUFXLENBQWdCO2FBQ3BELENBQUM7UUFDSixDQUFDO1FBRUQsS0FBSyxnQkFBZ0IsQ0FBQztRQUN0QixLQUFLLGVBQWUsQ0FBQyxDQUFDLENBQUM7WUFDckIsZ0RBQWdEO1lBQ2hELHdDQUF3QztZQUN4QyxxRUFBcUU7WUFDckUsTUFBTSxPQUFPLEdBQUcsUUFBUSxhQUFhLEVBQUUsRUFBRSxDQUFDO1lBQzFDLE1BQU0sR0FBRyxHQUFHLElBQUksSUFBSSxFQUFFLENBQUM7WUFDdkIsTUFBTSxLQUFLLEdBQVU7Z0JBQ25CLEdBQUcsSUFBSTtnQkFDUCxLQUFLO2dCQUNMLE9BQU87Z0JBQ1AsU0FBUyxFQUFFLEdBQUc7Z0JBQ2QsV0FBVyxFQUFFLG9CQUFvQjthQUNsQyxDQUFDO1lBQ0YsTUFBTSxZQUFZLEdBQUcsR0FBRyxLQUFLLElBQUksT0FBTyxFQUFFLENBQUM7WUFDM0MsTUFBTSxTQUFTLEdBQUcsaUJBQWlCLENBQ2pDLE9BQU8sRUFDUCxRQUFRLEVBQ1IsR0FBRyxZQUFZLE9BQU8sQ0FDdkIsQ0FBQztZQUNGLE1BQU0sU0FBUyxDQUFDLFNBQVMsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUNsQyxPQUFPLEVBQUUsS0FBSyxFQUFFLGtCQUFrQixDQUFDLEtBQUssRUFBRSxXQUFXLENBQUMsRUFBRSxDQUFDO1FBQzNELENBQUM7UUFFRDtZQUNFLE1BQU0sSUFBSSxLQUFLLENBQ2IsZUFBZSxJQUFJLENBQUMsU0FBUyxrQ0FBa0M7Z0JBQzdELGlCQUFpQixVQUFVLENBQUMsV0FBVyxJQUFJLFdBQVcsS0FBSztnQkFDM0Qsb0NBQW9DLENBQ3ZDLENBQUM7SUFDTixDQUFDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgRXZlbnQsIEV2ZW50UmVzdWx0LCBXb3JrZmxvd1J1biB9IGZyb20gJ0B3b3JrZmxvdy93b3JsZCc7XG5pbXBvcnQgeyBTUEVDX1ZFUlNJT05fQ1VSUkVOVCB9IGZyb20gJ0B3b3JrZmxvdy93b3JsZCc7XG5pbXBvcnQgeyBERUZBVUxUX1JFU09MVkVfREFUQV9PUFRJT04gfSBmcm9tICcuLi9jb25maWcuanMnO1xuaW1wb3J0IHsgYXNzZXJ0U2FmZUVudGl0eUlkLCByZXNvbHZlV2l0aGluQmFzZSwgd3JpdGVKU09OIH0gZnJvbSAnLi4vZnMuanMnO1xuaW1wb3J0IHsgZmlsdGVyUnVuRGF0YSwgc3RyaXBFdmVudERhdGFSZWZzIH0gZnJvbSAnLi9maWx0ZXJzLmpzJztcbmltcG9ydCB7IG1vbm90b25pY1VsaWQgfSBmcm9tICcuL2hlbHBlcnMuanMnO1xuaW1wb3J0IHsgZGVsZXRlQWxsSG9va3NGb3JSdW4gfSBmcm9tICcuL2hvb2tzLXN0b3JhZ2UuanMnO1xuXG4vKipcbiAqIEhhbmRsZSBldmVudHMgZm9yIGxlZ2FjeSBydW5zIChwcmUtZXZlbnQtc291cmNpbmcsIHNwZWNWZXJzaW9uIDwgMikuXG4gKiBMZWdhY3kgcnVucyB1c2UgZGlmZmVyZW50IGJlaGF2aW9yOlxuICogLSBydW5fY2FuY2VsbGVkOiBTa2lwIGV2ZW50IHN0b3JhZ2UsIGRpcmVjdGx5IHVwZGF0ZSBydW5cbiAqIC0gd2FpdF9jb21wbGV0ZWQ6IFN0b3JlIGV2ZW50IG9ubHkgKG5vIGVudGl0eSBtdXRhdGlvbilcbiAqIC0gaG9va19yZWNlaXZlZDogU3RvcmUgZXZlbnQgb25seSAoaG9va3MgZXhpc3QgdmlhIG9sZCBzeXN0ZW0sIG5vIGVudGl0eSBtdXRhdGlvbilcbiAqIC0gT3RoZXIgZXZlbnRzOiBUaHJvdyBlcnJvciAobm90IHN1cHBvcnRlZCBmb3IgbGVnYWN5IHJ1bnMpXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoYW5kbGVMZWdhY3lFdmVudChcbiAgYmFzZWRpcjogc3RyaW5nLFxuICBydW5JZDogc3RyaW5nLFxuICBkYXRhOiBhbnksXG4gIGN1cnJlbnRSdW46IFdvcmtmbG93UnVuLFxuICBwYXJhbXM/OiB7IHJlc29sdmVEYXRhPzogJ25vbmUnIHwgJ2FsbCcgfVxuKTogUHJvbWlzZTxFdmVudFJlc3VsdD4ge1xuICAvLyBEZWZlbnNlIGluIGRlcHRoOiBldmVudHMuY3JlYXRlIGFscmVhZHkgdmFsaWRhdGVzIHJ1bklkIGJlZm9yZSByb3V0aW5nXG4gIC8vIGhlcmUsIGJ1dCBoYW5kbGVMZWdhY3lFdmVudCBpcyBleHBvcnRlZCBhbmQgaXRzIHNpZ25hdHVyZSBkb2Vzbid0XG4gIC8vIGRvY3VtZW50IHRoYXQgaW52YXJpYW50LiBWYWxpZGF0aW5nIGxvY2FsbHkga2VlcHMgdGhlIGd1YXJhbnRlZSBpbiB0aGlzXG4gIC8vIGZpbGUuXG4gIGFzc2VydFNhZmVFbnRpdHlJZCgncnVuSWQnLCBydW5JZCk7XG5cbiAgY29uc3QgcmVzb2x2ZURhdGEgPSBwYXJhbXM/LnJlc29sdmVEYXRhID8/IERFRkFVTFRfUkVTT0xWRV9EQVRBX09QVElPTjtcblxuICBzd2l0Y2ggKGRhdGEuZXZlbnRUeXBlKSB7XG4gICAgY2FzZSAncnVuX2NhbmNlbGxlZCc6IHtcbiAgICAgIC8vIExlZ2FjeTogU2tpcCBldmVudCBzdG9yYWdlLCBkaXJlY3RseSB1cGRhdGUgcnVuIHRvIGNhbmNlbGxlZFxuICAgICAgY29uc3Qgbm93ID0gbmV3IERhdGUoKTtcbiAgICAgIGNvbnN0IHJ1bjogV29ya2Zsb3dSdW4gPSB7XG4gICAgICAgIHJ1bklkOiBjdXJyZW50UnVuLnJ1bklkLFxuICAgICAgICBkZXBsb3ltZW50SWQ6IGN1cnJlbnRSdW4uZGVwbG95bWVudElkLFxuICAgICAgICB3b3JrZmxvd05hbWU6IGN1cnJlbnRSdW4ud29ya2Zsb3dOYW1lLFxuICAgICAgICBzcGVjVmVyc2lvbjogY3VycmVudFJ1bi5zcGVjVmVyc2lvbixcbiAgICAgICAgZXhlY3V0aW9uQ29udGV4dDogY3VycmVudFJ1bi5leGVjdXRpb25Db250ZXh0LFxuICAgICAgICBpbnB1dDogY3VycmVudFJ1bi5pbnB1dCxcbiAgICAgICAgY3JlYXRlZEF0OiBjdXJyZW50UnVuLmNyZWF0ZWRBdCxcbiAgICAgICAgZXhwaXJlZEF0OiBjdXJyZW50UnVuLmV4cGlyZWRBdCxcbiAgICAgICAgc3RhcnRlZEF0OiBjdXJyZW50UnVuLnN0YXJ0ZWRBdCxcbiAgICAgICAgc3RhdHVzOiAnY2FuY2VsbGVkJyxcbiAgICAgICAgb3V0cHV0OiB1bmRlZmluZWQsXG4gICAgICAgIGVycm9yOiB1bmRlZmluZWQsXG4gICAgICAgIGNvbXBsZXRlZEF0OiBub3csXG4gICAgICAgIHVwZGF0ZWRBdDogbm93LFxuICAgICAgICBhdHRyaWJ1dGVzOiBjdXJyZW50UnVuLmF0dHJpYnV0ZXMsXG4gICAgICB9O1xuICAgICAgY29uc3QgcnVuUGF0aCA9IHJlc29sdmVXaXRoaW5CYXNlKGJhc2VkaXIsICdydW5zJywgYCR7cnVuSWR9Lmpzb25gKTtcbiAgICAgIGF3YWl0IHdyaXRlSlNPTihydW5QYXRoLCBydW4sIHsgb3ZlcndyaXRlOiB0cnVlIH0pO1xuICAgICAgYXdhaXQgZGVsZXRlQWxsSG9va3NGb3JSdW4oYmFzZWRpciwgcnVuSWQpO1xuICAgICAgLy8gUmV0dXJuIHdpdGhvdXQgZXZlbnQgKGxlZ2FjeSBiZWhhdmlvciBza2lwcyBldmVudCBzdG9yYWdlKVxuICAgICAgLy8gVHlwZSBhc3NlcnRpb246IEV2ZW50UmVzdWx0IGV4cGVjdHMgV29ya2Zsb3dSdW4sIGZpbHRlclJ1bkRhdGEgbWF5IHJldHVybiBXb3JrZmxvd1J1bldpdGhvdXREYXRhXG4gICAgICByZXR1cm4ge1xuICAgICAgICBldmVudDogdW5kZWZpbmVkLFxuICAgICAgICBydW46IGZpbHRlclJ1bkRhdGEocnVuLCByZXNvbHZlRGF0YSkgYXMgV29ya2Zsb3dSdW4sXG4gICAgICB9O1xuICAgIH1cblxuICAgIGNhc2UgJ3dhaXRfY29tcGxldGVkJzpcbiAgICBjYXNlICdob29rX3JlY2VpdmVkJzoge1xuICAgICAgLy8gTGVnYWN5OiBTdG9yZSBldmVudCBvbmx5IChubyBlbnRpdHkgbXV0YXRpb24pXG4gICAgICAvLyAtIHdhaXRfY29tcGxldGVkOiBmb3IgcmVwbGF5IHB1cnBvc2VzXG4gICAgICAvLyAtIGhvb2tfcmVjZWl2ZWQ6IGhvb2tzIGV4aXN0IHZpYSBvbGQgc3lzdGVtLCBqdXN0IHJlY29yZCB0aGUgZXZlbnRcbiAgICAgIGNvbnN0IGV2ZW50SWQgPSBgZXZudF8ke21vbm90b25pY1VsaWQoKX1gO1xuICAgICAgY29uc3Qgbm93ID0gbmV3IERhdGUoKTtcbiAgICAgIGNvbnN0IGV2ZW50OiBFdmVudCA9IHtcbiAgICAgICAgLi4uZGF0YSxcbiAgICAgICAgcnVuSWQsXG4gICAgICAgIGV2ZW50SWQsXG4gICAgICAgIGNyZWF0ZWRBdDogbm93LFxuICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICB9O1xuICAgICAgY29uc3QgY29tcG9zaXRlS2V5ID0gYCR7cnVuSWR9LSR7ZXZlbnRJZH1gO1xuICAgICAgY29uc3QgZXZlbnRQYXRoID0gcmVzb2x2ZVdpdGhpbkJhc2UoXG4gICAgICAgIGJhc2VkaXIsXG4gICAgICAgICdldmVudHMnLFxuICAgICAgICBgJHtjb21wb3NpdGVLZXl9Lmpzb25gXG4gICAgICApO1xuICAgICAgYXdhaXQgd3JpdGVKU09OKGV2ZW50UGF0aCwgZXZlbnQpO1xuICAgICAgcmV0dXJuIHsgZXZlbnQ6IHN0cmlwRXZlbnREYXRhUmVmcyhldmVudCwgcmVzb2x2ZURhdGEpIH07XG4gICAgfVxuXG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYEV2ZW50IHR5cGUgJyR7ZGF0YS5ldmVudFR5cGV9JyBub3Qgc3VwcG9ydGVkIGZvciBsZWdhY3kgcnVucyBgICtcbiAgICAgICAgICBgKHNwZWNWZXJzaW9uOiAke2N1cnJlbnRSdW4uc3BlY1ZlcnNpb24gfHwgJ3VuZGVmaW5lZCd9KS4gYCArXG4gICAgICAgICAgYFBsZWFzZSB1cGdyYWRlICd3b3JrZmxvdycgcGFja2FnZS5gXG4gICAgICApO1xuICB9XG59XG4iXX0=
@@ -0,0 +1,33 @@
1
+ import type { AttributeChange, ExperimentalSetAttributesResult, ListWorkflowRunsParams, PaginatedResponse, Storage, WorkflowRun, WorkflowRunWithoutData } from '@workflow/world';
2
+ /**
3
+ * Internal extension of `ListWorkflowRunsParams` that adds a `fileIdFilter`
4
+ * for scoping queries by raw filename (e.g., by tag suffix). Kept out of the
5
+ * public `Storage['runs']['list']` surface — consumers of `@workflow/world`
6
+ * must not see this option.
7
+ */
8
+ export interface LocalListWorkflowRunsParams extends ListWorkflowRunsParams {
9
+ fileIdFilter?: (fileId: string) => boolean;
10
+ }
11
+ export interface LocalRunsStorage {
12
+ get: Storage['runs']['get'];
13
+ list: {
14
+ (params: LocalListWorkflowRunsParams & {
15
+ resolveData: 'none';
16
+ }): Promise<PaginatedResponse<WorkflowRunWithoutData>>;
17
+ (params?: LocalListWorkflowRunsParams & {
18
+ resolveData?: 'all';
19
+ }): Promise<PaginatedResponse<WorkflowRun>>;
20
+ (params?: LocalListWorkflowRunsParams): Promise<PaginatedResponse<WorkflowRun | WorkflowRunWithoutData>>;
21
+ };
22
+ experimentalSetAttributes(runId: string, changes: AttributeChange[], options?: {
23
+ allowReservedAttributes?: boolean;
24
+ }): Promise<ExperimentalSetAttributesResult>;
25
+ }
26
+ export declare function withRunFileLock<T>(key: string, fn: () => Promise<T>): Promise<T>;
27
+ /**
28
+ * Creates the runs storage implementation using the filesystem.
29
+ * Implements the Storage['runs'] interface with get and list operations,
30
+ * plus an internal `fileIdFilter` on `list` for tag-scoped recovery queries.
31
+ */
32
+ export declare function createRunsStorage(basedir: string, tag?: string): LocalRunsStorage;
33
+ //# sourceMappingURL=runs-storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runs-storage.d.ts","sourceRoot":"","sources":["../../src/storage/runs-storage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,eAAe,EACf,+BAA+B,EAC/B,sBAAsB,EACtB,iBAAiB,EACjB,OAAO,EACP,WAAW,EACX,sBAAsB,EACvB,MAAM,iBAAiB,CAAC;AAkBzB;;;;;GAKG;AACH,MAAM,WAAW,2BAA4B,SAAQ,sBAAsB;IACzE,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;CAC5C;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC;IAC5B,IAAI,EAAE;QACJ,CACE,MAAM,EAAE,2BAA2B,GAAG;YAAE,WAAW,EAAE,MAAM,CAAA;SAAE,GAC5D,OAAO,CAAC,iBAAiB,CAAC,sBAAsB,CAAC,CAAC,CAAC;QACtD,CACE,MAAM,CAAC,EAAE,2BAA2B,GAAG;YAAE,WAAW,CAAC,EAAE,KAAK,CAAA;SAAE,GAC7D,OAAO,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC,CAAC;QAC3C,CACE,MAAM,CAAC,EAAE,2BAA2B,GACnC,OAAO,CAAC,iBAAiB,CAAC,WAAW,GAAG,sBAAsB,CAAC,CAAC,CAAC;KACrE,CAAC;IACF,yBAAyB,CACvB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,eAAe,EAAE,EAC1B,OAAO,CAAC,EAAE;QAAE,uBAAuB,CAAC,EAAE,OAAO,CAAA;KAAE,GAC9C,OAAO,CAAC,+BAA+B,CAAC,CAAC;CAC7C;AAiBD,wBAAgB,eAAe,CAAC,CAAC,EAC/B,GAAG,EAAE,MAAM,EACX,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,CAAC,CAAC,CAgBZ;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,GAAG,CAAC,EAAE,MAAM,GACX,gBAAgB,CAyGlB"}