@workflow/world-local 5.0.0-beta.2 → 5.0.0-beta.20
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.
- package/dist/config.d.ts +6 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -1
- package/dist/fs.d.ts +64 -5
- package/dist/fs.d.ts.map +1 -1
- package/dist/fs.js +148 -19
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +26 -9
- package/dist/init.js +1 -1
- package/dist/instrumentObject.d.ts.map +1 -1
- package/dist/instrumentObject.js +69 -3
- package/dist/queue.d.ts +2 -2
- package/dist/queue.d.ts.map +1 -1
- package/dist/queue.js +64 -12
- package/dist/storage/events-storage.d.ts.map +1 -1
- package/dist/storage/events-storage.js +1393 -601
- package/dist/storage/filters.js +1 -1
- package/dist/storage/helpers.d.ts +13 -0
- package/dist/storage/helpers.d.ts.map +1 -1
- package/dist/storage/helpers.js +23 -1
- package/dist/storage/hooks-storage.d.ts.map +1 -1
- package/dist/storage/hooks-storage.js +11 -4
- package/dist/storage/index.d.ts +10 -1
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +9 -11
- package/dist/storage/legacy.d.ts.map +1 -1
- package/dist/storage/legacy.js +10 -5
- package/dist/storage/runs-storage.d.ts +29 -3
- package/dist/storage/runs-storage.d.ts.map +1 -1
- package/dist/storage/runs-storage.js +76 -4
- package/dist/storage/steps-storage.d.ts.map +1 -1
- package/dist/storage/steps-storage.js +5 -2
- package/dist/storage.js +1 -1
- package/dist/streamer.d.ts.map +1 -1
- package/dist/streamer.js +45 -32
- package/dist/telemetry.d.ts +8 -0
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +5 -1
- package/dist/test-helpers.d.ts +1 -0
- package/dist/test-helpers.d.ts.map +1 -1
- package/dist/test-helpers.js +1 -1
- package/dist/util.js +1 -1
- package/package.json +6 -6
- package/dist/config.js.map +0 -1
- package/dist/fs.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/init.js.map +0 -1
- package/dist/instrumentObject.js.map +0 -1
- package/dist/queue.js.map +0 -1
- package/dist/storage/events-storage.js.map +0 -1
- package/dist/storage/filters.js.map +0 -1
- package/dist/storage/helpers.js.map +0 -1
- package/dist/storage/hooks-storage.js.map +0 -1
- package/dist/storage/index.js.map +0 -1
- package/dist/storage/legacy.js.map +0 -1
- package/dist/storage/runs-storage.js.map +0 -1
- package/dist/storage/steps-storage.js.map +0 -1
- package/dist/storage.js.map +0 -1
- package/dist/streamer.js.map +0 -1
- package/dist/telemetry.js.map +0 -1
- package/dist/test-helpers.js.map +0 -1
- package/dist/util.js.map +0 -1
package/dist/config.d.ts
CHANGED
|
@@ -3,6 +3,12 @@ export type Config = {
|
|
|
3
3
|
dataDir: string;
|
|
4
4
|
port?: number;
|
|
5
5
|
baseUrl?: string;
|
|
6
|
+
/**
|
|
7
|
+
* Whether start() should re-enqueue pending/running runs from storage.
|
|
8
|
+
* Defaults to true. Test harnesses that always start from a clean slate can
|
|
9
|
+
* disable recovery to avoid replaying stale runs.
|
|
10
|
+
*/
|
|
11
|
+
recoverActiveRuns?: boolean;
|
|
6
12
|
/**
|
|
7
13
|
* Optional tag to scope filesystem operations.
|
|
8
14
|
* When set, files are written as `{id}.{tag}.json` and `clear()` only deletes
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,2BAA2B,QAAQ,CAAC;AAMjD,MAAM,MAAM,MAAM,GAAG;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC,CAAC;AAEF,eAAO,MAAM,MAAM;;CAKjB,CAAC;AAEH;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAyB7E"}
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,2BAA2B,QAAQ,CAAC;AAMjD,MAAM,MAAM,MAAM,GAAG;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;OAKG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC,CAAC;AAEF,eAAO,MAAM,MAAM;;CAKjB,CAAC;AAEH;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAyB7E"}
|
package/dist/config.js
CHANGED
|
@@ -41,4 +41,4 @@ export async function resolveBaseUrl(config) {
|
|
|
41
41
|
}
|
|
42
42
|
throw new Error('Unable to resolve base URL for workflow queue.');
|
|
43
43
|
}
|
|
44
|
-
//# sourceMappingURL=
|
|
44
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDM0QsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUVqQyxNQUFNLGlCQUFpQixHQUFHLEdBQUcsRUFBRTtJQUM3QixPQUFPLE9BQU8sQ0FBQyxHQUFHLENBQUMsdUJBQXVCLElBQUksZ0JBQWdCLENBQUM7QUFDakUsQ0FBQyxDQUFDO0FBRUYsTUFBTSxDQUFDLE1BQU0sMkJBQTJCLEdBQUcsS0FBSyxDQUFDO0FBRWpELE1BQU0saUJBQWlCLEdBQUcsR0FBRyxFQUFFO0lBQzdCLE9BQU8sT0FBTyxDQUFDLEdBQUcsQ0FBQyx1QkFBdUIsQ0FBQztBQUM3QyxDQUFDLENBQUM7QUEwQkYsTUFBTSxDQUFDLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBUyxHQUFHLEVBQUU7SUFDdEMsTUFBTSxPQUFPLEdBQUcsaUJBQWlCLEVBQUUsQ0FBQztJQUNwQyxNQUFNLE9BQU8sR0FBRyxpQkFBaUIsRUFBRSxDQUFDO0lBRXBDLE9BQU8sRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLENBQUM7QUFDOUIsQ0FBQyxDQUFDLENBQUM7QUFFSDs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxjQUFjLENBQUMsTUFBdUI7SUFDMUQsSUFBSSxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDbkIsT0FBTyxNQUFNLENBQUMsT0FBTyxDQUFDO0lBQ3hCLENBQUM7SUFFRCx3RUFBd0U7SUFDeEUsMkVBQTJFO0lBQzNFLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyx1QkFBdUIsRUFBRSxDQUFDO1FBQ3hDLE9BQU8sT0FBTyxDQUFDLEdBQUcsQ0FBQyx1QkFBdUIsQ0FBQztJQUM3QyxDQUFDO0lBRUQsSUFBSSxPQUFPLE1BQU0sQ0FBQyxJQUFJLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDcEMsT0FBTyxvQkFBb0IsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQzNDLENBQUM7SUFFRCxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDckIsT0FBTyxvQkFBb0IsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNoRCxDQUFDO0lBRUQsTUFBTSxZQUFZLEdBQUcsTUFBTSxlQUFlLEVBQUUsQ0FBQztJQUM3QyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBQ2pCLE9BQU8sb0JBQW9CLFlBQVksRUFBRSxDQUFDO0lBQzVDLENBQUM7SUFFRCxNQUFNLElBQUksS0FBSyxDQUFDLGdEQUFnRCxDQUFDLENBQUM7QUFDcEUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGdldFdvcmtmbG93UG9ydCB9IGZyb20gJ0B3b3JrZmxvdy91dGlscy9nZXQtcG9ydCc7XG5pbXBvcnQgeyBvbmNlIH0gZnJvbSAnLi91dGlsLmpzJztcblxuY29uc3QgZ2V0RGF0YURpckZyb21FbnYgPSAoKSA9PiB7XG4gIHJldHVybiBwcm9jZXNzLmVudi5XT1JLRkxPV19MT0NBTF9EQVRBX0RJUiB8fCAnLndvcmtmbG93LWRhdGEnO1xufTtcblxuZXhwb3J0IGNvbnN0IERFRkFVTFRfUkVTT0xWRV9EQVRBX09QVElPTiA9ICdhbGwnO1xuXG5jb25zdCBnZXRCYXNlVXJsRnJvbUVudiA9ICgpID0+IHtcbiAgcmV0dXJuIHByb2Nlc3MuZW52LldPUktGTE9XX0xPQ0FMX0JBU0VfVVJMO1xufTtcblxuZXhwb3J0IHR5cGUgQ29uZmlnID0ge1xuICBkYXRhRGlyOiBzdHJpbmc7XG4gIHBvcnQ/OiBudW1iZXI7XG4gIGJhc2VVcmw/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBXaGV0aGVyIHN0YXJ0KCkgc2hvdWxkIHJlLWVucXVldWUgcGVuZGluZy9ydW5uaW5nIHJ1bnMgZnJvbSBzdG9yYWdlLlxuICAgKiBEZWZhdWx0cyB0byB0cnVlLiBUZXN0IGhhcm5lc3NlcyB0aGF0IGFsd2F5cyBzdGFydCBmcm9tIGEgY2xlYW4gc2xhdGUgY2FuXG4gICAqIGRpc2FibGUgcmVjb3ZlcnkgdG8gYXZvaWQgcmVwbGF5aW5nIHN0YWxlIHJ1bnMuXG4gICAqL1xuICByZWNvdmVyQWN0aXZlUnVucz86IGJvb2xlYW47XG4gIC8qKlxuICAgKiBPcHRpb25hbCB0YWcgdG8gc2NvcGUgZmlsZXN5c3RlbSBvcGVyYXRpb25zLlxuICAgKiBXaGVuIHNldCwgZmlsZXMgYXJlIHdyaXR0ZW4gYXMgYHtpZH0ue3RhZ30uanNvbmAgYW5kIGBjbGVhcigpYCBvbmx5IGRlbGV0ZXNcbiAgICogZmlsZXMgbWF0Y2hpbmcgdGhpcyB0YWcuIFVzZWQgYnkgdml0ZXN0IHRvIGlzb2xhdGUgdGVzdCBkYXRhIGluIHRoZSBzaGFyZWRcbiAgICogYC53b3JrZmxvdy1kYXRhYCBkaXJlY3RvcnkuXG4gICAqL1xuICB0YWc/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBPdmVycmlkZSB0aGUgZmx1c2ggaW50ZXJ2YWwgKGluIG1zKSBmb3IgYnVmZmVyZWQgc3RyZWFtIHdyaXRlcy5cbiAgICogRGVmYXVsdCBpcyAxMG1zLiBTZXQgdG8gMCBmb3IgaW1tZWRpYXRlIGZsdXNoaW5nLlxuICAgKi9cbiAgc3RyZWFtRmx1c2hJbnRlcnZhbE1zPzogbnVtYmVyO1xufTtcblxuZXhwb3J0IGNvbnN0IGNvbmZpZyA9IG9uY2U8Q29uZmlnPigoKSA9PiB7XG4gIGNvbnN0IGRhdGFEaXIgPSBnZXREYXRhRGlyRnJvbUVudigpO1xuICBjb25zdCBiYXNlVXJsID0gZ2V0QmFzZVVybEZyb21FbnYoKTtcblxuICByZXR1cm4geyBkYXRhRGlyLCBiYXNlVXJsIH07XG59KTtcblxuLyoqXG4gKiBSZXNvbHZlcyB0aGUgYmFzZSBVUkwgZm9yIHF1ZXVlIHJlcXVlc3RzIGZvbGxvd2luZyB0aGUgcHJpb3JpdHkgb3JkZXI6XG4gKiAxLiBjb25maWcuYmFzZVVybCAoaGlnaGVzdCBwcmlvcml0eSAtIGZ1bGwgb3ZlcnJpZGUgZnJvbSBhcmdzKVxuICogMi4gV09SS0ZMT1dfTE9DQUxfQkFTRV9VUkwgZW52IHZhciAoY2hlY2tlZCBkaXJlY3RseSB0byBoYW5kbGUgbGF0ZSBlbnYgdmFyIHNldHRpbmcpXG4gKiAzLiBjb25maWcucG9ydCAoZXhwbGljaXQgcG9ydCBvdmVycmlkZSBmcm9tIGFyZ3MpXG4gKiA0LiBQT1JUIGVudiB2YXIgKGV4cGxpY2l0IGNvbmZpZ3VyYXRpb24pXG4gKiA1LiBBdXRvLWRldGVjdGVkIHBvcnQgdmlhIGdldFBvcnQgKGRldGVjdCBhY3R1YWwgbGlzdGVuaW5nIHBvcnQpXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXNvbHZlQmFzZVVybChjb25maWc6IFBhcnRpYWw8Q29uZmlnPik6IFByb21pc2U8c3RyaW5nPiB7XG4gIGlmIChjb25maWcuYmFzZVVybCkge1xuICAgIHJldHVybiBjb25maWcuYmFzZVVybDtcbiAgfVxuXG4gIC8vIENoZWNrIGVudiB2YXIgZGlyZWN0bHkgaW4gY2FzZSBpdCB3YXMgc2V0IGFmdGVyIHRoZSBjb25maWcgd2FzIGNhY2hlZFxuICAvLyBUaGlzIGlzIGltcG9ydGFudCBmb3IgQ0xJIHRvb2xzIHRoYXQgc2V0IHRoZSBlbnYgdmFyIGFmdGVyIG1vZHVsZSBpbXBvcnRcbiAgaWYgKHByb2Nlc3MuZW52LldPUktGTE9XX0xPQ0FMX0JBU0VfVVJMKSB7XG4gICAgcmV0dXJuIHByb2Nlc3MuZW52LldPUktGTE9XX0xPQ0FMX0JBU0VfVVJMO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBjb25maWcucG9ydCA9PT0gJ251bWJlcicpIHtcbiAgICByZXR1cm4gYGh0dHA6Ly9sb2NhbGhvc3Q6JHtjb25maWcucG9ydH1gO1xuICB9XG5cbiAgaWYgKHByb2Nlc3MuZW52LlBPUlQpIHtcbiAgICByZXR1cm4gYGh0dHA6Ly9sb2NhbGhvc3Q6JHtwcm9jZXNzLmVudi5QT1JUfWA7XG4gIH1cblxuICBjb25zdCBkZXRlY3RlZFBvcnQgPSBhd2FpdCBnZXRXb3JrZmxvd1BvcnQoKTtcbiAgaWYgKGRldGVjdGVkUG9ydCkge1xuICAgIHJldHVybiBgaHR0cDovL2xvY2FsaG9zdDoke2RldGVjdGVkUG9ydH1gO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKCdVbmFibGUgdG8gcmVzb2x2ZSBiYXNlIFVSTCBmb3Igd29ya2Zsb3cgcXVldWUuJyk7XG59XG4iXX0=
|
package/dist/fs.d.ts
CHANGED
|
@@ -1,5 +1,47 @@
|
|
|
1
|
+
import { WorkflowWorldError } from '@workflow/errors';
|
|
1
2
|
import type { PaginatedResponse } from '@workflow/world';
|
|
2
3
|
import { z } from 'zod';
|
|
4
|
+
/**
|
|
5
|
+
* Thrown when a caller-supplied entity ID contains characters that would
|
|
6
|
+
* escape the storage root (path traversal) or otherwise produce an unsafe
|
|
7
|
+
* filename. Extends {@link WorkflowWorldError} so the platform's standard
|
|
8
|
+
* error-to-HTTP mapping handles it alongside other world-layer errors.
|
|
9
|
+
*/
|
|
10
|
+
export declare class UnsafeEntityIdError extends WorkflowWorldError {
|
|
11
|
+
constructor(kind: string, value: string);
|
|
12
|
+
static is(value: unknown): value is UnsafeEntityIdError;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Validate that a string is safe to embed in a filesystem path as a single
|
|
16
|
+
* path component. Rejects values that are:
|
|
17
|
+
* - empty
|
|
18
|
+
* - starting with `.` (blocks `.`, `..`, `.locks`, `.tmp`, and other
|
|
19
|
+
* hidden or reserved filenames)
|
|
20
|
+
* - containing `.` (would collide with the `.tag` / `.json` suffix the
|
|
21
|
+
* tagging logic strips from filenames; see {@link stripTag} /
|
|
22
|
+
* {@link getObjectCreatedAt})
|
|
23
|
+
* - containing `/`, `\`, or a NUL byte
|
|
24
|
+
*
|
|
25
|
+
* This is the primary defense against path-traversal attacks where a
|
|
26
|
+
* request body supplies a `runId` / `stepId` / `correlationId` containing
|
|
27
|
+
* `../` sequences to read or write files outside the storage root.
|
|
28
|
+
* {@link resolveWithinBase} provides a belt-and-suspenders containment
|
|
29
|
+
* check at the point of `path.join` for defense in depth.
|
|
30
|
+
*
|
|
31
|
+
* @param kind - Human-readable label used in the error message (e.g. "runId")
|
|
32
|
+
* @param value - The value to validate; throws {@link UnsafeEntityIdError}
|
|
33
|
+
* if the value is not safe.
|
|
34
|
+
*/
|
|
35
|
+
export declare function assertSafeEntityId(kind: string, value: string): void;
|
|
36
|
+
/**
|
|
37
|
+
* Join `basedir` with an entity-relative path and assert the result stays
|
|
38
|
+
* inside `basedir`. Complements {@link assertSafeEntityId}: per-entry-point
|
|
39
|
+
* validation is the primary defense, and this final check catches any path
|
|
40
|
+
* escape that slipped past (e.g. a new call site that forgot to validate,
|
|
41
|
+
* or an unusual character combination on a future filesystem). Throws
|
|
42
|
+
* {@link UnsafeEntityIdError} if the joined path escapes `basedir`.
|
|
43
|
+
*/
|
|
44
|
+
export declare function resolveWithinBase(basedir: string, ...segments: string[]): string;
|
|
3
45
|
/**
|
|
4
46
|
* Clear the created files cache. Useful for testing or when files are deleted externally.
|
|
5
47
|
*/
|
|
@@ -11,10 +53,21 @@ export { ulidToDate } from '@workflow/world';
|
|
|
11
53
|
* `wrun_ABC` → `wrun_ABC` (no-op if no tag)
|
|
12
54
|
*/
|
|
13
55
|
export declare function stripTag(fileId: string): string;
|
|
56
|
+
/**
|
|
57
|
+
* Check whether a fileId belongs to a specific tag.
|
|
58
|
+
* `wrun_ABC.vitest-0` belongs to `vitest-0`.
|
|
59
|
+
* Untagged fileIds never match a tag-scoped lookup.
|
|
60
|
+
*/
|
|
61
|
+
export declare function hasTag(fileId: string, tag: string): boolean;
|
|
14
62
|
/**
|
|
15
63
|
* Build the file path for an entity, with optional tag embedded in the filename.
|
|
16
|
-
* `taggedPath('runs', 'wrun_ABC', 'vitest-0')` →
|
|
17
|
-
* `taggedPath('runs', 'wrun_ABC')` →
|
|
64
|
+
* `taggedPath('/data', 'runs', 'wrun_ABC', 'vitest-0')` → `/data/runs/wrun_ABC.vitest-0.json`
|
|
65
|
+
* `taggedPath('/data', 'runs', 'wrun_ABC')` → `/data/runs/wrun_ABC.json`
|
|
66
|
+
*
|
|
67
|
+
* The `fileId` and `tag` are validated with {@link assertSafeEntityId} and
|
|
68
|
+
* the result is containment-checked with {@link resolveWithinBase} to
|
|
69
|
+
* prevent path-traversal attacks when values are derived from untrusted
|
|
70
|
+
* request input.
|
|
18
71
|
*/
|
|
19
72
|
export declare function taggedPath(basedir: string, entityDir: string, fileId: string, tag?: string): string;
|
|
20
73
|
/**
|
|
@@ -59,11 +112,16 @@ export declare function writeJSON(filePath: string, data: any, opts?: WriteOptio
|
|
|
59
112
|
export declare function write(filePath: string, data: string | Buffer, opts?: WriteOptions): Promise<void>;
|
|
60
113
|
export declare function readJSON<T>(filePath: string, decoder: z.ZodType<T>): Promise<T | null>;
|
|
61
114
|
export declare function readBuffer(filePath: string): Promise<Buffer>;
|
|
115
|
+
export declare function readFirstByte(filePath: string): Promise<number | undefined>;
|
|
62
116
|
export declare function deleteJSON(filePath: string): Promise<void>;
|
|
63
117
|
/**
|
|
64
|
-
* Atomically
|
|
65
|
-
*
|
|
66
|
-
*
|
|
118
|
+
* Atomically publish a fully-written file without overwriting an existing one.
|
|
119
|
+
*
|
|
120
|
+
* Writing directly with O_CREAT | O_EXCL makes the destination visible before
|
|
121
|
+
* its contents are complete, so concurrent readers can observe a partial file.
|
|
122
|
+
* Instead, write to a unique file in the same directory, then hard-link it into
|
|
123
|
+
* place. Creating the link is atomic and fails with EEXIST if another writer
|
|
124
|
+
* published the destination first.
|
|
67
125
|
*/
|
|
68
126
|
export declare function writeExclusive(filePath: string, data: string): Promise<boolean>;
|
|
69
127
|
export declare function listJSONFiles(dirPath: string): Promise<string[]>;
|
|
@@ -72,6 +130,7 @@ interface PaginatedFileSystemQueryConfig<T> {
|
|
|
72
130
|
directory: string;
|
|
73
131
|
schema: z.ZodType<T>;
|
|
74
132
|
filePrefix?: string;
|
|
133
|
+
fileIdFilter?: (fileId: string) => boolean;
|
|
75
134
|
filter?: (item: T) => boolean;
|
|
76
135
|
sortOrder?: 'asc' | 'desc';
|
|
77
136
|
limit?: number;
|
package/dist/fs.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../src/fs.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../src/fs.ts"],"names":[],"mappings":"AAEA,OAAO,EAAuB,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAgBxB;;;;;GAKG;AACH,qBAAa,mBAAoB,SAAQ,kBAAkB;gBAC7C,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAOvC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,mBAAmB;CAGxD;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAWpE;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,GAAG,QAAQ,EAAE,MAAM,EAAE,GACpB,MAAM,CAOR;AAuCD;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C;AAED,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAW7C;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CACxB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,GAAG,CAAC,EAAE,MAAM,GACX,MAAM,CAKR;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CAAC,CAAC,EAC1C,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EACpB,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAcnB;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,EAAE,CAAC,CASnB;AAED;;;GAGG;AACH,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,EAAE,CAAC,CASnB;AAED,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM9D;AAED,UAAU,YAAY;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAQlE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAUjE;AAED,wBAAsB,SAAS,CAC7B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,GAAG,EACT,IAAI,CAAC,EAAE,YAAY,GAClB,OAAO,CAAC,IAAI,CAAC,CAEf;AAED;;;;;;;;GAQG;AACH,wBAAsB,KAAK,CACzB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,IAAI,CAAC,EAAE,YAAY,GAClB,OAAO,CAAC,IAAI,CAAC,CA0Cf;AAED,wBAAsB,QAAQ,CAAC,CAAC,EAC9B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GACpB,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAQnB;AAED,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGlE;AAED,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAS7B;AAED,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMhE;AAED;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,OAAO,CAAC,CAuBlB;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAEtE;AAED,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,EAAE,CAAC,CAUnB;AAED,UAAU,8BAA8B,CAAC,CAAC;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAC3C,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC;IAC9B,SAAS,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;IAC5C,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,MAAM,CAAC;CACzB;AAqBD,wBAAsB,wBAAwB,CAAC,CAAC,SAAS;IAAE,SAAS,EAAE,IAAI,CAAA;CAAE,EAC1E,MAAM,EAAE,8BAA8B,CAAC,CAAC,CAAC,GACxC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CA4J/B"}
|
package/dist/fs.js
CHANGED
|
@@ -1,9 +1,82 @@
|
|
|
1
1
|
import { promises as fs } from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import { EntityConflictError } from '@workflow/errors';
|
|
3
|
+
import { EntityConflictError, WorkflowWorldError } from '@workflow/errors';
|
|
4
4
|
import { monotonicFactory } from 'ulid';
|
|
5
5
|
import { z } from 'zod';
|
|
6
6
|
const ulid = monotonicFactory(() => Math.random());
|
|
7
|
+
/**
|
|
8
|
+
* Truncate a possibly-untrusted value for inclusion in an error message.
|
|
9
|
+
* Keeps error output actionable for developers in dev mode while limiting
|
|
10
|
+
* the amount of attacker-controlled data reflected back if a `world-local`
|
|
11
|
+
* backend is ever run in a context that surfaces these messages to clients.
|
|
12
|
+
*/
|
|
13
|
+
function truncateForError(value) {
|
|
14
|
+
const s = typeof value === 'string' ? value : String(value);
|
|
15
|
+
const MAX = 48;
|
|
16
|
+
return s.length > MAX ? `${s.slice(0, MAX)}…` : s;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Thrown when a caller-supplied entity ID contains characters that would
|
|
20
|
+
* escape the storage root (path traversal) or otherwise produce an unsafe
|
|
21
|
+
* filename. Extends {@link WorkflowWorldError} so the platform's standard
|
|
22
|
+
* error-to-HTTP mapping handles it alongside other world-layer errors.
|
|
23
|
+
*/
|
|
24
|
+
export class UnsafeEntityIdError extends WorkflowWorldError {
|
|
25
|
+
constructor(kind, value) {
|
|
26
|
+
super(`Unsafe ${kind} "${truncateForError(value)}": must not be empty, contain ".", "/", "\\", or null bytes`);
|
|
27
|
+
this.name = 'UnsafeEntityIdError';
|
|
28
|
+
}
|
|
29
|
+
static is(value) {
|
|
30
|
+
return value instanceof Error && value.name === 'UnsafeEntityIdError';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Validate that a string is safe to embed in a filesystem path as a single
|
|
35
|
+
* path component. Rejects values that are:
|
|
36
|
+
* - empty
|
|
37
|
+
* - starting with `.` (blocks `.`, `..`, `.locks`, `.tmp`, and other
|
|
38
|
+
* hidden or reserved filenames)
|
|
39
|
+
* - containing `.` (would collide with the `.tag` / `.json` suffix the
|
|
40
|
+
* tagging logic strips from filenames; see {@link stripTag} /
|
|
41
|
+
* {@link getObjectCreatedAt})
|
|
42
|
+
* - containing `/`, `\`, or a NUL byte
|
|
43
|
+
*
|
|
44
|
+
* This is the primary defense against path-traversal attacks where a
|
|
45
|
+
* request body supplies a `runId` / `stepId` / `correlationId` containing
|
|
46
|
+
* `../` sequences to read or write files outside the storage root.
|
|
47
|
+
* {@link resolveWithinBase} provides a belt-and-suspenders containment
|
|
48
|
+
* check at the point of `path.join` for defense in depth.
|
|
49
|
+
*
|
|
50
|
+
* @param kind - Human-readable label used in the error message (e.g. "runId")
|
|
51
|
+
* @param value - The value to validate; throws {@link UnsafeEntityIdError}
|
|
52
|
+
* if the value is not safe.
|
|
53
|
+
*/
|
|
54
|
+
export function assertSafeEntityId(kind, value) {
|
|
55
|
+
if (value.length === 0 ||
|
|
56
|
+
value.startsWith('.') ||
|
|
57
|
+
value.includes('/') ||
|
|
58
|
+
value.includes('\\') ||
|
|
59
|
+
value.includes('\0') ||
|
|
60
|
+
value.includes('.')) {
|
|
61
|
+
throw new UnsafeEntityIdError(kind, value);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Join `basedir` with an entity-relative path and assert the result stays
|
|
66
|
+
* inside `basedir`. Complements {@link assertSafeEntityId}: per-entry-point
|
|
67
|
+
* validation is the primary defense, and this final check catches any path
|
|
68
|
+
* escape that slipped past (e.g. a new call site that forgot to validate,
|
|
69
|
+
* or an unusual character combination on a future filesystem). Throws
|
|
70
|
+
* {@link UnsafeEntityIdError} if the joined path escapes `basedir`.
|
|
71
|
+
*/
|
|
72
|
+
export function resolveWithinBase(basedir, ...segments) {
|
|
73
|
+
const resolvedBase = path.resolve(basedir);
|
|
74
|
+
const joined = path.resolve(basedir, ...segments);
|
|
75
|
+
if (joined !== resolvedBase && !joined.startsWith(resolvedBase + path.sep)) {
|
|
76
|
+
throw new UnsafeEntityIdError('path', segments.join('/'));
|
|
77
|
+
}
|
|
78
|
+
return joined;
|
|
79
|
+
}
|
|
7
80
|
const isWindows = process.platform === 'win32';
|
|
8
81
|
/**
|
|
9
82
|
* Execute a filesystem operation with retry logic on Windows.
|
|
@@ -58,14 +131,30 @@ const TAG_PATTERN = /\.[a-zA-Z][a-zA-Z0-9-]*$/;
|
|
|
58
131
|
export function stripTag(fileId) {
|
|
59
132
|
return fileId.replace(TAG_PATTERN, '');
|
|
60
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Check whether a fileId belongs to a specific tag.
|
|
136
|
+
* `wrun_ABC.vitest-0` belongs to `vitest-0`.
|
|
137
|
+
* Untagged fileIds never match a tag-scoped lookup.
|
|
138
|
+
*/
|
|
139
|
+
export function hasTag(fileId, tag) {
|
|
140
|
+
return fileId.endsWith(`.${tag}`);
|
|
141
|
+
}
|
|
61
142
|
/**
|
|
62
143
|
* Build the file path for an entity, with optional tag embedded in the filename.
|
|
63
|
-
* `taggedPath('runs', 'wrun_ABC', 'vitest-0')` →
|
|
64
|
-
* `taggedPath('runs', 'wrun_ABC')` →
|
|
144
|
+
* `taggedPath('/data', 'runs', 'wrun_ABC', 'vitest-0')` → `/data/runs/wrun_ABC.vitest-0.json`
|
|
145
|
+
* `taggedPath('/data', 'runs', 'wrun_ABC')` → `/data/runs/wrun_ABC.json`
|
|
146
|
+
*
|
|
147
|
+
* The `fileId` and `tag` are validated with {@link assertSafeEntityId} and
|
|
148
|
+
* the result is containment-checked with {@link resolveWithinBase} to
|
|
149
|
+
* prevent path-traversal attacks when values are derived from untrusted
|
|
150
|
+
* request input.
|
|
65
151
|
*/
|
|
66
152
|
export function taggedPath(basedir, entityDir, fileId, tag) {
|
|
153
|
+
assertSafeEntityId('fileId', fileId);
|
|
154
|
+
if (tag !== undefined)
|
|
155
|
+
assertSafeEntityId('tag', tag);
|
|
67
156
|
const filename = tag ? `${fileId}.${tag}.json` : `${fileId}.json`;
|
|
68
|
-
return
|
|
157
|
+
return resolveWithinBase(basedir, entityDir, filename);
|
|
69
158
|
}
|
|
70
159
|
/**
|
|
71
160
|
* Read a JSON entity with tagged fallback.
|
|
@@ -73,12 +162,15 @@ export function taggedPath(basedir, entityDir, fileId, tag) {
|
|
|
73
162
|
* untagged path (so a tagged world can read entities written without a tag).
|
|
74
163
|
*/
|
|
75
164
|
export async function readJSONWithFallback(basedir, entityDir, fileId, schema, tag) {
|
|
165
|
+
assertSafeEntityId('fileId', fileId);
|
|
166
|
+
if (tag !== undefined)
|
|
167
|
+
assertSafeEntityId('tag', tag);
|
|
76
168
|
if (tag) {
|
|
77
|
-
const result = await readJSON(
|
|
169
|
+
const result = await readJSON(resolveWithinBase(basedir, entityDir, `${fileId}.${tag}.json`), schema);
|
|
78
170
|
if (result !== null)
|
|
79
171
|
return result;
|
|
80
172
|
}
|
|
81
|
-
return readJSON(
|
|
173
|
+
return readJSON(resolveWithinBase(basedir, entityDir, `${fileId}.json`), schema);
|
|
82
174
|
}
|
|
83
175
|
/**
|
|
84
176
|
* List all filenames in a directory that have a specific tag.
|
|
@@ -211,6 +303,17 @@ export async function readBuffer(filePath) {
|
|
|
211
303
|
const content = await fs.readFile(filePath);
|
|
212
304
|
return content;
|
|
213
305
|
}
|
|
306
|
+
export async function readFirstByte(filePath) {
|
|
307
|
+
const file = await fs.open(filePath, 'r');
|
|
308
|
+
try {
|
|
309
|
+
const byte = Buffer.allocUnsafe(1);
|
|
310
|
+
const { bytesRead } = await file.read(byte, 0, 1, 0);
|
|
311
|
+
return bytesRead === 0 ? undefined : byte[0];
|
|
312
|
+
}
|
|
313
|
+
finally {
|
|
314
|
+
await file.close();
|
|
315
|
+
}
|
|
316
|
+
}
|
|
214
317
|
export async function deleteJSON(filePath) {
|
|
215
318
|
try {
|
|
216
319
|
await fs.unlink(filePath);
|
|
@@ -221,21 +324,36 @@ export async function deleteJSON(filePath) {
|
|
|
221
324
|
}
|
|
222
325
|
}
|
|
223
326
|
/**
|
|
224
|
-
* Atomically
|
|
225
|
-
*
|
|
226
|
-
*
|
|
327
|
+
* Atomically publish a fully-written file without overwriting an existing one.
|
|
328
|
+
*
|
|
329
|
+
* Writing directly with O_CREAT | O_EXCL makes the destination visible before
|
|
330
|
+
* its contents are complete, so concurrent readers can observe a partial file.
|
|
331
|
+
* Instead, write to a unique file in the same directory, then hard-link it into
|
|
332
|
+
* place. Creating the link is atomic and fails with EEXIST if another writer
|
|
333
|
+
* published the destination first.
|
|
227
334
|
*/
|
|
228
335
|
export async function writeExclusive(filePath, data) {
|
|
229
336
|
await ensureDir(path.dirname(filePath));
|
|
337
|
+
const tempPath = `${filePath}.tmp.${ulid()}`;
|
|
338
|
+
let tempFileCreated = false;
|
|
230
339
|
try {
|
|
231
|
-
await fs.writeFile(
|
|
232
|
-
|
|
340
|
+
await fs.writeFile(tempPath, data, { flag: 'wx' });
|
|
341
|
+
tempFileCreated = true;
|
|
342
|
+
try {
|
|
343
|
+
await withWindowsRetry(() => fs.link(tempPath, filePath));
|
|
344
|
+
return true;
|
|
345
|
+
}
|
|
346
|
+
catch (error) {
|
|
347
|
+
if (error.code === 'EEXIST') {
|
|
348
|
+
return false;
|
|
349
|
+
}
|
|
350
|
+
throw error;
|
|
351
|
+
}
|
|
233
352
|
}
|
|
234
|
-
|
|
235
|
-
if (
|
|
236
|
-
|
|
353
|
+
finally {
|
|
354
|
+
if (tempFileCreated) {
|
|
355
|
+
await withWindowsRetry(() => fs.unlink(tempPath), 3).catch(() => { });
|
|
237
356
|
}
|
|
238
|
-
throw error;
|
|
239
357
|
}
|
|
240
358
|
}
|
|
241
359
|
export async function listJSONFiles(dirPath) {
|
|
@@ -267,18 +385,29 @@ function createCursor(timestamp, id) {
|
|
|
267
385
|
return id ? `${timestamp.toISOString()}|${id}` : timestamp.toISOString();
|
|
268
386
|
}
|
|
269
387
|
export async function paginatedFileSystemQuery(config) {
|
|
270
|
-
const { directory, schema, filePrefix, filter, sortOrder = 'desc', limit = 20, cursor, getCreatedAt, getId, } = config;
|
|
388
|
+
const { directory, schema, filePrefix, fileIdFilter, filter, sortOrder = 'desc', limit = 20, cursor, getCreatedAt, getId, } = config;
|
|
389
|
+
// Validate filePrefix (typically `${runId}-`) so request-derived prefixes
|
|
390
|
+
// consistently reject unsafe characters. filePrefix is only used below to
|
|
391
|
+
// filter readdir() results by prefix — it doesn't participate in path
|
|
392
|
+
// construction — but keeping the validation rule uniform across the
|
|
393
|
+
// storage layer avoids special cases and catches bad values earlier.
|
|
394
|
+
if (filePrefix !== undefined) {
|
|
395
|
+
assertSafeEntityId('filePrefix', filePrefix);
|
|
396
|
+
}
|
|
271
397
|
// 1. Get all JSON files in directory
|
|
272
398
|
const fileIds = await listJSONFiles(directory);
|
|
273
399
|
// 2. Filter by prefix if provided
|
|
274
400
|
const relevantFileIds = filePrefix
|
|
275
401
|
? fileIds.filter((fileId) => fileId.startsWith(filePrefix))
|
|
276
402
|
: fileIds;
|
|
403
|
+
const filteredFileIds = fileIdFilter
|
|
404
|
+
? relevantFileIds.filter(fileIdFilter)
|
|
405
|
+
: relevantFileIds;
|
|
277
406
|
// 3. ULID Optimization: Filter by cursor using filename timestamps before loading JSON
|
|
278
407
|
const parsedCursor = parseCursor(cursor);
|
|
279
|
-
let candidateFileIds =
|
|
408
|
+
let candidateFileIds = filteredFileIds;
|
|
280
409
|
if (parsedCursor) {
|
|
281
|
-
candidateFileIds =
|
|
410
|
+
candidateFileIds = filteredFileIds.filter((fileId) => {
|
|
282
411
|
const filenameDate = getCreatedAt(`${fileId}.json`);
|
|
283
412
|
if (filenameDate) {
|
|
284
413
|
// Use filename timestamp for cursor filtering
|
|
@@ -386,4 +515,4 @@ export async function paginatedFileSystemQuery(config) {
|
|
|
386
515
|
hasMore,
|
|
387
516
|
};
|
|
388
517
|
}
|
|
389
|
-
//# sourceMappingURL=fs.js.map
|
|
518
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvZnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsSUFBSSxFQUFFLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDekMsT0FBTyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBQzdCLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRTNFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUN4QyxPQUFPLEVBQUUsQ0FBQyxFQUFFLE1BQU0sS0FBSyxDQUFDO0FBRXhCLE1BQU0sSUFBSSxHQUFHLGdCQUFnQixDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO0FBRW5EOzs7OztHQUtHO0FBQ0gsU0FBUyxnQkFBZ0IsQ0FBQyxLQUFjO0lBQ3RDLE1BQU0sQ0FBQyxHQUFHLE9BQU8sS0FBSyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDNUQsTUFBTSxHQUFHLEdBQUcsRUFBRSxDQUFDO0lBQ2YsT0FBTyxDQUFDLENBQUMsTUFBTSxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDcEQsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxPQUFPLG1CQUFvQixTQUFRLGtCQUFrQjtJQUN6RCxZQUFZLElBQVksRUFBRSxLQUFhO1FBQ3JDLEtBQUssQ0FDSCxVQUFVLElBQUksS0FBSyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsNkRBQTZELENBQ3hHLENBQUM7UUFDRixJQUFJLENBQUMsSUFBSSxHQUFHLHFCQUFxQixDQUFDO0lBQ3BDLENBQUM7SUFF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RUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDO0lBQ2hFLE1BQU0sVUFBVSxHQUNkLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQztRQUNkLENBQUMsQ0FBQyxZQUFZLENBQ1YsS0FBSyxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsU0FBUyxFQUNqQyxLQUFLLEVBQUUsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUNqQztRQUNILENBQUMsQ0FBQyxJQUFJLENBQUM7SUFFWCxPQUFPO1FBQ0wsSUFBSSxFQUFFLEtBQUs7UUFDWCxNQUFNLEVBQUUsVUFBVTtRQUNsQixPQUFPO0tBQ1IsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBwcm9taXNlcyBhcyBmcyB9IGZyb20gJ25vZGU6ZnMnO1xuaW1wb3J0IHBhdGggZnJvbSAnbm9kZTpwYXRoJztcbmltcG9ydCB7IEVudGl0eUNvbmZsaWN0RXJyb3IsIFdvcmtmbG93V29ybGRFcnJvciB9IGZyb20gJ0B3b3JrZmxvdy9lcnJvcnMnO1xuaW1wb3J0IHR5cGUgeyBQYWdpbmF0ZWRSZXNwb25zZSB9IGZyb20gJ0B3b3JrZmxvdy93b3JsZCc7XG5pbXBvcnQgeyBtb25vdG9uaWNGYWN0b3J5IH0gZnJvbSAndWxpZCc7XG5pbXBvcnQgeyB6IH0gZnJvbSAnem9kJztcblxuY29uc3QgdWxpZCA9IG1vbm90b25pY0ZhY3RvcnkoKCkgPT4gTWF0aC5yYW5kb20oKSk7XG5cbi8qKlxuICogVHJ1bmNhdGUgYSBwb3NzaWJseS11bnRydXN0ZWQgdmFsdWUgZm9yIGluY2x1c2lvbiBpbiBhbiBlcnJvciBtZXNzYWdlLlxuICogS2VlcHMgZXJyb3Igb3V0cHV0IGFjdGlvbmFibGUgZm9yIGRldmVsb3BlcnMgaW4gZGV2IG1vZGUgd2hpbGUgbGltaXRpbmdcbiAqIHRoZSBhbW91bnQgb2YgYXR0YWNrZXItY29udHJvbGxlZCBkYXRhIHJlZmxlY3RlZCBiYWNrIGlmIGEgYHdvcmxkLWxvY2FsYFxuICogYmFja2VuZCBpcyBldmVyIHJ1biBpbiBhIGNvbnRleHQgdGhhdCBzdXJmYWNlcyB0aGVzZSBtZXNzYWdlcyB0byBjbGllbnRzLlxuICovXG5mdW5jdGlvbiB0cnVuY2F0ZUZvckVycm9yKHZhbHVlOiB1bmtub3duKTogc3RyaW5nIHtcbiAgY29uc3QgcyA9IHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgPyB2YWx1ZSA6IFN0cmluZyh2YWx1ZSk7XG4gIGNvbnN0IE1BWCA9IDQ4O1xuICByZXR1cm4gcy5sZW5ndGggPiBNQVggPyBgJHtzLnNsaWNlKDAsIE1BWCl94oCmYCA6IHM7XG59XG5cbi8qKlxuICogVGhyb3duIHdoZW4gYSBjYWxsZXItc3VwcGxpZWQgZW50aXR5IElEIGNvbnRhaW5zIGNoYXJhY3RlcnMgdGhhdCB3b3VsZFxuICogZXNjYXBlIHRoZSBzdG9yYWdlIHJvb3QgKHBhdGggdHJhdmVyc2FsKSBvciBvdGhlcndpc2UgcHJvZHVjZSBhbiB1bnNhZmVcbiAqIGZpbGVuYW1lLiBFeHRlbmRzIHtAbGluayBXb3JrZmxvd1dvcmxkRXJyb3J9IHNvIHRoZSBwbGF0Zm9ybSdzIHN0YW5kYXJkXG4gKiBlcnJvci10by1IVFRQIG1hcHBpbmcgaGFuZGxlcyBpdCBhbG9uZ3NpZGUgb3RoZXIgd29ybGQtbGF5ZXIgZXJyb3JzLlxuICovXG5leHBvcnQgY2xhc3MgVW5zYWZlRW50aXR5SWRFcnJvciBleHRlbmRzIFdvcmtmbG93V29ybGRFcnJvciB7XG4gIGNvbnN0cnVjdG9yKGtpbmQ6IHN0cmluZywgdmFsdWU6IHN0cmluZykge1xuICAgIHN1cGVyKFxuICAgICAgYFVuc2FmZSAke2tpbmR9IFwiJHt0cnVuY2F0ZUZvckVycm9yKHZhbHVlKX1cIjogbXVzdCBub3QgYmUgZW1wdHksIGNvbnRhaW4gXCIuXCIsIFwiL1wiLCBcIlxcXFxcIiwgb3IgbnVsbCBieXRlc2BcbiAgICApO1xuICAgIHRoaXMubmFtZSA9ICdVbnNhZmVFbnRpdHlJZEVycm9yJztcbiAgfVxuXG4gIHN0YXRpYyBpcyh2YWx1ZTogdW5rbm93bik6IHZhbHVlIGlzIFVuc2FmZUVudGl0eUlkRXJyb3Ige1xuICAgIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEVycm9yICYmIHZhbHVlLm5hbWUgPT09ICdVbnNhZmVFbnRpdHlJZEVycm9yJztcbiAgfVxufVxuXG4vKipcbiAqIFZhbGlkYXRlIHRoYXQgYSBzdHJpbmcgaXMgc2FmZSB0byBlbWJlZCBpbiBhIGZpbGVzeXN0ZW0gcGF0aCBhcyBhIHNpbmdsZVxuICogcGF0aCBjb21wb25lbnQuIFJlamVjdHMgdmFsdWVzIHRoYXQgYXJlOlxuICogICAtIGVtcHR5XG4gKiAgIC0gc3RhcnRpbmcgd2l0aCBgLmAgKGJsb2NrcyBgLmAsIGAuLmAsIGAubG9ja3NgLCBgLnRtcGAsIGFuZCBvdGhlclxuICogICAgIGhpZGRlbiBvciByZXNlcnZlZCBmaWxlbmFtZXMpXG4gKiAgIC0gY29udGFpbmluZyBgLmAgKHdvdWxkIGNvbGxpZGUgd2l0aCB0aGUgYC50YWdgIC8gYC5qc29uYCBzdWZmaXggdGhlXG4gKiAgICAgdGFnZ2luZyBsb2dpYyBzdHJpcHMgZnJvbSBmaWxlbmFtZXM7IHNlZSB7QGxpbmsgc3RyaXBUYWd9IC9cbiAqICAgICB7QGxpbmsgZ2V0T2JqZWN0Q3JlYXRlZEF0fSlcbiAqICAgLSBjb250YWluaW5nIGAvYCwgYFxcYCwgb3IgYSBOVUwgYnl0ZVxuICpcbiAqIFRoaXMgaXMgdGhlIHByaW1hcnkgZGVmZW5zZSBhZ2FpbnN0IHBhdGgtdHJhdmVyc2FsIGF0dGFja3Mgd2hlcmUgYVxuICogcmVxdWVzdCBib2R5IHN1cHBsaWVzIGEgYHJ1bklkYCAvIGBzdGVwSWRgIC8gYGNvcnJlbGF0aW9uSWRgIGNvbnRhaW5pbmdcbiAqIGAuLi9gIHNlcXVlbmNlcyB0byByZWFkIG9yIHdyaXRlIGZpbGVzIG91dHNpZGUgdGhlIHN0b3JhZ2Ugcm9vdC5cbiAqIHtAbGluayByZXNvbHZlV2l0aGluQmFzZX0gcHJvdmlkZXMgYSBiZWx0LWFuZC1zdXNwZW5kZXJzIGNvbnRhaW5tZW50XG4gKiBjaGVjayBhdCB0aGUgcG9pbnQgb2YgYHBhdGguam9pbmAgZm9yIGRlZmVuc2UgaW4gZGVwdGguXG4gKlxuICogQHBhcmFtIGtpbmQgLSBIdW1hbi1yZWFkYWJsZSBsYWJlbCB1c2VkIGluIHRoZSBlcnJvciBtZXNzYWdlIChlLmcuIFwicnVuSWRcIilcbiAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWx1ZSB0byB2YWxpZGF0ZTsgdGhyb3dzIHtAbGluayBVbnNhZmVFbnRpdHlJZEVycm9yfVxuICogICBpZiB0aGUgdmFsdWUgaXMgbm90IHNhZmUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhc3NlcnRTYWZlRW50aXR5SWQoa2luZDogc3RyaW5nLCB2YWx1ZTogc3RyaW5nKTogdm9pZCB7XG4gIGlmIChcbiAgICB2YWx1ZS5sZW5ndGggPT09IDAgfHxcbiAgICB2YWx1ZS5zdGFydHNXaXRoKCcuJykgfHxcbiAgICB2YWx1ZS5pbmNsdWRlcygnLycpIHx8XG4gICAgdmFsdWUuaW5jbHVkZXMoJ1xcXFwnKSB8fFxuICAgIHZhbHVlLmluY2x1ZGVzKCdcXDAnKSB8fFxuICAgIHZhbHVlLmluY2x1ZGVzKCcuJylcbiAgKSB7XG4gICAgdGhyb3cgbmV3IFVuc2FmZUVudGl0eUlkRXJyb3Ioa2luZCwgdmFsdWUpO1xuICB9XG59XG5cbi8qKlxuICogSm9pbiBgYmFzZWRpcmAgd2l0aCBhbiBlbnRpdHktcmVsYXRpdmUgcGF0aCBhbmQgYXNzZXJ0IHRoZSByZXN1bHQgc3RheXNcbiAqIGluc2lkZSBgYmFzZWRpcmAuIENvbXBsZW1lbnRzIHtAbGluayBhc3NlcnRTYWZlRW50aXR5SWR9OiBwZXItZW50cnktcG9pbnRcbiAqIHZhbGlkYXRpb24gaXMgdGhlIHByaW1hcnkgZGVmZW5zZSwgYW5kIHRoaXMgZmluYWwgY2hlY2sgY2F0Y2hlcyBhbnkgcGF0aFxuICogZXNjYXBlIHRoYXQgc2xpcHBlZCBwYXN0IChlLmcuIGEgbmV3IGNhbGwgc2l0ZSB0aGF0IGZvcmdvdCB0byB2YWxpZGF0ZSxcbiAqIG9yIGFuIHVudXN1YWwgY2hhcmFjdGVyIGNvbWJpbmF0aW9uIG9uIGEgZnV0dXJlIGZpbGVzeXN0ZW0pLiBUaHJvd3NcbiAqIHtAbGluayBVbnNhZmVFbnRpdHlJZEVycm9yfSBpZiB0aGUgam9pbmVkIHBhdGggZXNjYXBlcyBgYmFzZWRpcmAuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlV2l0aGluQmFzZShcbiAgYmFzZWRpcjogc3RyaW5nLFxuICAuLi5zZWdtZW50czogc3RyaW5nW11cbik6IHN0cmluZyB7XG4gIGNvbnN0IHJlc29sdmVkQmFzZSA9IHBhdGgucmVzb2x2ZShiYXNlZGlyKTtcbiAgY29uc3Qgam9pbmVkID0gcGF0aC5yZXNvbHZlKGJhc2VkaXIsIC4uLnNlZ21lbnRzKTtcbiAgaWYgKGpvaW5lZCAhPT0gcmVzb2x2ZWRCYXNlICYmICFqb2luZWQuc3RhcnRzV2l0aChyZXNvbHZlZEJhc2UgKyBwYXRoLnNlcCkpIHtcbiAgICB0aHJvdyBuZXcgVW5zYWZlRW50aXR5SWRFcnJvcigncGF0aCcsIHNlZ21lbnRzLmpvaW4oJy8nKSk7XG4gIH1cbiAgcmV0dXJuIGpvaW5lZDtcbn1cblxuY29uc3QgaXNXaW5kb3dzID0gcHJvY2Vzcy5wbGF0Zm9ybSA9PT0gJ3dpbjMyJztcblxuLyoqXG4gKiBFeGVjdXRlIGEgZmlsZXN5c3RlbSBvcGVyYXRpb24gd2l0aCByZXRyeSBsb2dpYyBvbiBXaW5kb3dzLlxuICogT24gV2luZG93cywgZmlsZSBvcGVyYXRpb25zIGNhbiBmYWlsIHdpdGggRVBFUk0vRUJVU1kvRUFDQ0VTIHdoZW4gZmlsZXNcbiAqIGFyZSBicmllZmx5IGxvY2tlZCBieSBhbm90aGVyIHByb2Nlc3Mgb3IgYW50aXZpcnVzLiBUaGlzIHdyYXBwZXIgYWRkc1xuICogZXhwb25lbnRpYWwgYmFja29mZiByZXRyeSBsb2dpYy4gT24gbm9uLVdpbmRvd3MgcGxhdGZvcm1zLCBleGVjdXRlcyBkaXJlY3RseS5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gd2l0aFdpbmRvd3NSZXRyeTxUPihcbiAgZm46ICgpID0+IFByb21pc2U8VD4sXG4gIG1heFJldHJpZXMgPSA1XG4pOiBQcm9taXNlPFQ+IHtcbiAgaWYgKCFpc1dpbmRvd3MpIHJldHVybiBmbigpO1xuXG4gIGNvbnN0IHJldHJ5YWJsZUVycm9ycyA9IFsnRVBFUk0nLCAnRUJVU1knLCAnRUFDQ0VTJ107XG4gIGNvbnN0IGJhc2VEZWxheU1zID0gMTA7XG5cbiAgZm9yIChsZXQgYXR0ZW1wdCA9IDA7IGF0dGVtcHQgPD0gbWF4UmV0cmllczsgYXR0ZW1wdCsrKSB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBhd2FpdCBmbigpO1xuICAgIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcbiAgICAgIGNvbnN0IGlzUmV0cnlhYmxlID1cbiAgICAgICAgYXR0ZW1wdCA8IG1heFJldHJpZXMgJiYgcmV0cnlhYmxlRXJyb3JzLmluY2x1ZGVzKGVycm9yLmNvZGUpO1xuICAgICAgaWYgKCFpc1JldHJ5YWJsZSkgdGhyb3cgZXJyb3I7XG4gICAgICAvLyBFeHBvbmVudGlhbCBiYWNrb2ZmIHdpdGggaml0dGVyXG4gICAgICBjb25zdCBkZWxheSA9IGJhc2VEZWxheU1zICogMiAqKiBhdHRlbXB0ICsgTWF0aC5yYW5kb20oKSAqIGJhc2VEZWxheU1zO1xuICAgICAgYXdhaXQgbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgZGVsYXkpKTtcbiAgICB9XG4gIH1cbiAgLy8gVHlwZVNjcmlwdDogdW5yZWFjaGFibGUsIGJ1dCBzYXRpc2ZpZXMgcmV0dXJuIHR5cGVcbiAgdGhyb3cgbmV3IEVycm9yKCdSZXRyeSBsb29wIGV4aXRlZCB1bmV4cGVjdGVkbHknKTtcbn1cblxuLy8gSW4tbWVtb3J5IGNhY2hlIG9mIGNyZWF0ZWQgZmlsZXMgdG8gYXZvaWQgZXhwZW5zaXZlIGZzLmFjY2VzcygpIGNhbGxzXG4vLyBUaGlzIGlzIHNhZmUgYmVjYXVzZSB3ZSBvbmx5IHdyaXRlIG9uY2UgcGVyIGZpbGUgcGF0aCAobm8gb3ZlcndyaXRlcyB3aXRob3V0IGV4cGxpY2l0IGZsYWcpXG5jb25zdCBjcmVhdGVkRmlsZXNDYWNoZSA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG4vKipcbiAqIENsZWFyIHRoZSBjcmVhdGVkIGZpbGVzIGNhY2hlLiBVc2VmdWwgZm9yIHRlc3Rpbmcgb3Igd2hlbiBmaWxlcyBhcmUgZGVsZXRlZCBleHRlcm5hbGx5LlxuICovXG5leHBvcnQgZnVuY3Rpb24gY2xlYXJDcmVhdGVkRmlsZXNDYWNoZSgpOiB2b2lkIHtcbiAgY3JlYXRlZEZpbGVzQ2FjaGUuY2xlYXIoKTtcbn1cblxuZXhwb3J0IHsgdWxpZFRvRGF0ZSB9IGZyb20gJ0B3b3JrZmxvdy93b3JsZCc7XG5cbi8qKlxuICogUmVnZXggbWF0Y2hpbmcgYSB0YWcgc3VmZml4IG9uIGEgZmlsZUlkIChhZnRlciBgLmpzb25gIGhhcyBiZWVuIHN0cmlwcGVkKS5cbiAqIEUuZy4sIGB3cnVuX0FCQy52aXRlc3QtMGAg4oaSIHRoZSBgLnZpdGVzdC0wYCBwYXJ0LlxuICogVGFncyBzdGFydCB3aXRoIGEgbGV0dGVyIGFuZCBjb250YWluIGFscGhhbnVtZXJpYyBjaGFycyBhbmQgaHlwaGVucy5cbiAqIEVudGl0eSBJRHMgKFVMSURzLCBzdGVwX04sIGV0Yy4pIG5ldmVyIGNvbnRhaW4gZG90cywgc28gdGhlIGZpcnN0IGRvdFxuICogYWx3YXlzIG1hcmtzIHRoZSB0YWcgYm91bmRhcnkuXG4gKi9cbmNvbnN0IFRBR19QQVRURVJOID0gL1xcLlthLXpBLVpdW2EtekEtWjAtOS1dKiQvO1xuXG4vKipcbiAqIFN0cmlwIGEgdGFnIHN1ZmZpeCBmcm9tIGEgZmlsZUlkLlxuICogYHdydW5fQUJDLnZpdGVzdC0wYCDihpIgYHdydW5fQUJDYFxuICogYHdydW5fQUJDYCDihpIgYHdydW5fQUJDYCAobm8tb3AgaWYgbm8gdGFnKVxuICovXG5leHBvcnQgZnVuY3Rpb24gc3RyaXBUYWcoZmlsZUlkOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gZmlsZUlkLnJlcGxhY2UoVEFHX1BBVFRFUk4sICcnKTtcbn1cblxuLyoqXG4gKiBDaGVjayB3aGV0aGVyIGEgZmlsZUlkIGJlbG9uZ3MgdG8gYSBzcGVjaWZpYyB0YWcuXG4gKiBgd3J1bl9BQkMudml0ZXN0LTBgIGJlbG9uZ3MgdG8gYHZpdGVzdC0wYC5cbiAqIFVudGFnZ2VkIGZpbGVJZHMgbmV2ZXIgbWF0Y2ggYSB0YWctc2NvcGVkIGxvb2t1cC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhhc1RhZyhmaWxlSWQ6IHN0cmluZywgdGFnOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgcmV0dXJuIGZpbGVJZC5lbmRzV2l0aChgLiR7dGFnfWApO1xufVxuXG4vKipcbiAqIEJ1aWxkIHRoZSBmaWxlIHBhdGggZm9yIGFuIGVudGl0eSwgd2l0aCBvcHRpb25hbCB0YWcgZW1iZWRkZWQgaW4gdGhlIGZpbGVuYW1lLlxuICogYHRhZ2dlZFBhdGgoJy9kYXRhJywgJ3J1bnMnLCAnd3J1bl9BQkMnLCAndml0ZXN0LTAnKWAg4oaSIGAvZGF0YS9ydW5zL3dydW5fQUJDLnZpdGVzdC0wLmpzb25gXG4gKiBgdGFnZ2VkUGF0aCgnL2RhdGEnLCAncnVucycsICd3cnVuX0FCQycpYCDihpIgYC9kYXRhL3J1bnMvd3J1bl9BQkMuanNvbmBcbiAqXG4gKiBUaGUgYGZpbGVJZGAgYW5kIGB0YWdgIGFyZSB2YWxpZGF0ZWQgd2l0aCB7QGxpbmsgYXNzZXJ0U2FmZUVudGl0eUlkfSBhbmRcbiAqIHRoZSByZXN1bHQgaXMgY29udGFpbm1lbnQtY2hlY2tlZCB3aXRoIHtAbGluayByZXNvbHZlV2l0aGluQmFzZX0gdG9cbiAqIHByZXZlbnQgcGF0aC10cmF2ZXJzYWwgYXR0YWNrcyB3aGVuIHZhbHVlcyBhcmUgZGVyaXZlZCBmcm9tIHVudHJ1c3RlZFxuICogcmVxdWVzdCBpbnB1dC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRhZ2dlZFBhdGgoXG4gIGJhc2VkaXI6IHN0cmluZyxcbiAgZW50aXR5RGlyOiBzdHJpbmcsXG4gIGZpbGVJZDogc3RyaW5nLFxuICB0YWc/OiBzdHJpbmdcbik6IHN0cmluZyB7XG4gIGFzc2VydFNhZmVFbnRpdHlJZCgnZmlsZUlkJywgZmlsZUlkKTtcbiAgaWYgKHRhZyAhPT0gdW5kZWZpbmVkKSBhc3NlcnRTYWZlRW50aXR5SWQoJ3RhZycsIHRhZyk7XG4gIGNvbnN0IGZpbGVuYW1lID0gdGFnID8gYCR7ZmlsZUlkfS4ke3RhZ30uanNvbmAgOiBgJHtmaWxlSWR9Lmpzb25gO1xuICByZXR1cm4gcmVzb2x2ZVdpdGhpbkJhc2UoYmFzZWRpciwgZW50aXR5RGlyLCBmaWxlbmFtZSk7XG59XG5cbi8qKlxuICogUmVhZCBhIEpTT04gZW50aXR5IHdpdGggdGFnZ2VkIGZhbGxiYWNrLlxuICogV2hlbiBhIHRhZyBpcyBzZXQsIHRyaWVzIHRoZSB0YWdnZWQgcGF0aCBmaXJzdCwgdGhlbiBmYWxscyBiYWNrIHRvIHRoZVxuICogdW50YWdnZWQgcGF0aCAoc28gYSB0YWdnZWQgd29ybGQgY2FuIHJlYWQgZW50aXRpZXMgd3JpdHRlbiB3aXRob3V0IGEgdGFnKS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlYWRKU09OV2l0aEZhbGxiYWNrPFQ+KFxuICBiYXNlZGlyOiBzdHJpbmcsXG4gIGVudGl0eURpcjogc3RyaW5nLFxuICBmaWxlSWQ6IHN0cmluZyxcbiAgc2NoZW1hOiB6LlpvZFR5cGU8VD4sXG4gIHRhZz86IHN0cmluZ1xuKTogUHJvbWlzZTxUIHwgbnVsbD4ge1xuICBhc3NlcnRTYWZlRW50aXR5SWQoJ2ZpbGVJZCcsIGZpbGVJZCk7XG4gIGlmICh0YWcgIT09IHVuZGVmaW5lZCkgYXNzZXJ0U2FmZUVudGl0eUlkKCd0YWcnLCB0YWcpO1xuICBpZiAodGFnKSB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcmVhZEpTT04oXG4gICAgICByZXNvbHZlV2l0aGluQmFzZShiYXNlZGlyLCBlbnRpdHlEaXIsIGAke2ZpbGVJZH0uJHt0YWd9Lmpzb25gKSxcbiAgICAgIHNjaGVtYVxuICAgICk7XG4gICAgaWYgKHJlc3VsdCAhPT0gbnVsbCkgcmV0dXJuIHJlc3VsdDtcbiAgfVxuICByZXR1cm4gcmVhZEpTT04oXG4gICAgcmVzb2x2ZVdpdGhpbkJhc2UoYmFzZWRpciwgZW50aXR5RGlyLCBgJHtmaWxlSWR9Lmpzb25gKSxcbiAgICBzY2hlbWFcbiAgKTtcbn1cblxuLyoqXG4gKiBMaXN0IGFsbCBmaWxlbmFtZXMgaW4gYSBkaXJlY3RvcnkgdGhhdCBoYXZlIGEgc3BlY2lmaWMgdGFnLlxuICogUmV0dXJucyBmdWxsIGZpbGVuYW1lcyAoZS5nLiwgYHdydW5fQUJDLnZpdGVzdC0wLmpzb25gKS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGxpc3RUYWdnZWRGaWxlcyhcbiAgZGlyUGF0aDogc3RyaW5nLFxuICB0YWc6IHN0cmluZ1xuKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICBjb25zdCBzdWZmaXggPSBgLiR7dGFnfS5qc29uYDtcbiAgdHJ5IHtcbiAgICBjb25zdCBmaWxlcyA9IGF3YWl0IGZzLnJlYWRkaXIoZGlyUGF0aCk7XG4gICAgcmV0dXJuIGZpbGVzLmZpbHRlcigoZikgPT4gZi5lbmRzV2l0aChzdWZmaXgpKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBpZiAoKGVycm9yIGFzIGFueSkuY29kZSA9PT0gJ0VOT0VOVCcpIHJldHVybiBbXTtcbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxufVxuXG4vKipcbiAqIExpc3QgYWxsIGZpbGVuYW1lcyBpbiBhIGRpcmVjdG9yeSB0aGF0IGhhdmUgYSBzcGVjaWZpYyB0YWcgYW5kIGV4dGVuc2lvbi5cbiAqIFJldHVybnMgZnVsbCBmaWxlbmFtZXMgKGUuZy4sIGBzdHJlYW0tY2hua19BQkMudml0ZXN0LTAuYmluYCkuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBsaXN0VGFnZ2VkRmlsZXNCeUV4dGVuc2lvbihcbiAgZGlyUGF0aDogc3RyaW5nLFxuICB0YWc6IHN0cmluZyxcbiAgZXh0ZW5zaW9uOiBzdHJpbmdcbik6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgY29uc3Qgc3VmZml4ID0gYC4ke3RhZ30ke2V4dGVuc2lvbn1gO1xuICB0cnkge1xuICAgIGNvbnN0IGZpbGVzID0gYXdhaXQgZnMucmVhZGRpcihkaXJQYXRoKTtcbiAgICByZXR1cm4gZmlsZXMuZmlsdGVyKChmKSA9PiBmLmVuZHNXaXRoKHN1ZmZpeCkpO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGlmICgoZXJyb3IgYXMgYW55KS5jb2RlID09PSAnRU5PRU5UJykgcmV0dXJuIFtdO1xuICAgIHRocm93IGVycm9yO1xuICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBlbnN1cmVEaXIoZGlyUGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gIHRyeSB7XG4gICAgYXdhaXQgZnMubWtkaXIoZGlyUGF0aCwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gIH0gY2F0Y2ggKF9lcnJvcikge1xuICAgIC8vIElnbm9yZSBpZiBhbHJlYWR5IGV4aXN0c1xuICB9XG59XG5cbmludGVyZmFjZSBXcml0ZU9wdGlvbnMge1xuICBvdmVyd3JpdGU/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIEN1c3RvbSBKU09OIHJlcGxhY2VyIHRoYXQgZW5jb2RlcyBVaW50OEFycmF5IGFzIGJhc2U2NCBzdHJpbmdzLlxuICogRm9ybWF0OiB7IF9fdHlwZTogJ1VpbnQ4QXJyYXknLCBkYXRhOiAnPGJhc2U2ND4nIH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGpzb25SZXBsYWNlcihfa2V5OiBzdHJpbmcsIHZhbHVlOiB1bmtub3duKTogdW5rbm93biB7XG4gIGlmICh2YWx1ZSBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpIHtcbiAgICByZXR1cm4ge1xuICAgICAgX190eXBlOiAnVWludDhBcnJheScsXG4gICAgICBkYXRhOiBCdWZmZXIuZnJvbSh2YWx1ZSkudG9TdHJpbmcoJ2Jhc2U2NCcpLFxuICAgIH07XG4gIH1cbiAgcmV0dXJuIHZhbHVlO1xufVxuXG4vKipcbiAqIEN1c3RvbSBKU09OIHJldml2ZXIgdGhhdCBkZWNvZGVzIGJhc2U2NCBzdHJpbmdzIGJhY2sgdG8gVWludDhBcnJheS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGpzb25SZXZpdmVyKF9rZXk6IHN0cmluZywgdmFsdWU6IHVua25vd24pOiB1bmtub3duIHtcbiAgaWYgKFxuICAgIHZhbHVlICE9PSBudWxsICYmXG4gICAgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJlxuICAgICh2YWx1ZSBhcyBhbnkpLl9fdHlwZSA9PT0gJ1VpbnQ4QXJyYXknICYmXG4gICAgdHlwZW9mICh2YWx1ZSBhcyBhbnkpLmRhdGEgPT09ICdzdHJpbmcnXG4gICkge1xuICAgIHJldHVybiBuZXcgVWludDhBcnJheShCdWZmZXIuZnJvbSgodmFsdWUgYXMgYW55KS5kYXRhLCAnYmFzZTY0JykpO1xuICB9XG4gIHJldHVybiB2YWx1ZTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHdyaXRlSlNPTihcbiAgZmlsZVBhdGg6IHN0cmluZyxcbiAgZGF0YTogYW55LFxuICBvcHRzPzogV3JpdGVPcHRpb25zXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgcmV0dXJuIHdyaXRlKGZpbGVQYXRoLCBKU09OLnN0cmluZ2lmeShkYXRhLCBqc29uUmVwbGFjZXIsIDIpLCBvcHRzKTtcbn1cblxuLyoqXG4gKiBXcml0ZXMgZGF0YSB0byBhIGZpbGUgdXNpbmcgYXRvbWljIHdyaXRlLXJlbmFtZSBwYXR0ZXJuLlxuICpcbiAqIE5vdGU6IFdoaWxlIHRoaXMgZnVuY3Rpb24gdXNlcyB0ZW1wIGZpbGVzIHRvIGF2b2lkIHBhcnRpYWwgd3JpdGVzLFxuICogaXQgZG9lcyBub3QgcHJvdmlkZSBwcm90ZWN0aW9uIGFnYWluc3QgY29uY3VycmVudCB3cml0ZXMgZnJvbSBtdWx0aXBsZVxuICogcHJvY2Vzc2VzLiBJbiBhIG11bHRpLXdyaXRlciBzY2VuYXJpbywgdGhlIGxhc3Qgd3JpdGVyIHdpbnMuXG4gKiBGb3IgcHJvZHVjdGlvbiB1c2Ugd2l0aCBtdWx0aXBsZSB3cml0ZXJzLCBjb25zaWRlciB1c2luZyBhIHByb3BlclxuICogZGF0YWJhc2Ugb3IgbG9ja2luZyBtZWNoYW5pc20uXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB3cml0ZShcbiAgZmlsZVBhdGg6IHN0cmluZyxcbiAgZGF0YTogc3RyaW5nIHwgQnVmZmVyLFxuICBvcHRzPzogV3JpdGVPcHRpb25zXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgaWYgKCFvcHRzPy5vdmVyd3JpdGUpIHtcbiAgICAvLyBGYXN0IHBhdGg6IGNoZWNrIGluLW1lbW9yeSBjYWNoZSBmaXJzdCB0byBhdm9pZCBleHBlbnNpdmUgZnMuYWNjZXNzKCkgY2FsbHNcbiAgICAvLyBUaGlzIHByb3ZpZGVzIHNpZ25pZmljYW50IHBlcmZvcm1hbmNlIGltcHJvdmVtZW50IHdoZW4gY3JlYXRpbmcgbWFueSBmaWxlc1xuICAgIGlmIChjcmVhdGVkRmlsZXNDYWNoZS5oYXMoZmlsZVBhdGgpKSB7XG4gICAgICB0aHJvdyBuZXcgRW50aXR5Q29uZmxpY3RFcnJvcihcbiAgICAgICAgYEZpbGUgJHtmaWxlUGF0aH0gYWxyZWFkeSBleGlzdHMgYW5kICdvdmVyd3JpdGUnIGlzIGZhbHNlYFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBTbG93IHBhdGg6IGNoZWNrIGZpbGVzeXN0ZW0gZm9yIGZpbGVzIGNyZWF0ZWQgYmVmb3JlIHRoaXMgcHJvY2VzcyBzdGFydGVkXG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGZzLmFjY2VzcyhmaWxlUGF0aCk7XG4gICAgICAvLyBGaWxlIGV4aXN0cyBvbiBkaXNrLCBhZGQgdG8gY2FjaGUgZm9yIGZ1dHVyZSBjaGVja3NcbiAgICAgIGNyZWF0ZWRGaWxlc0NhY2hlLmFkZChmaWxlUGF0aCk7XG4gICAgICB0aHJvdyBuZXcgRW50aXR5Q29uZmxpY3RFcnJvcihcbiAgICAgICAgYEZpbGUgJHtmaWxlUGF0aH0gYWxyZWFkeSBleGlzdHMgYW5kICdvdmVyd3JpdGUnIGlzIGZhbHNlYFxuICAgICAgKTtcbiAgICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgICAvLyBJZiBmaWxlIGRvZXNuJ3QgZXhpc3QgKEVOT0VOVCksIGNvbnRpbnVlIHdpdGggd3JpdGVcbiAgICAgIGlmIChlcnJvci5jb2RlICE9PSAnRU5PRU5UJykge1xuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBjb25zdCB0ZW1wUGF0aCA9IGAke2ZpbGVQYXRofS50bXAuJHt1bGlkKCl9YDtcbiAgbGV0IHRlbXBGaWxlQ3JlYXRlZCA9IGZhbHNlO1xuICB0cnkge1xuICAgIGF3YWl0IGVuc3VyZURpcihwYXRoLmRpcm5hbWUoZmlsZVBhdGgpKTtcbiAgICBhd2FpdCBmcy53cml0ZUZpbGUodGVtcFBhdGgsIGRhdGEpO1xuICAgIHRlbXBGaWxlQ3JlYXRlZCA9IHRydWU7XG4gICAgYXdhaXQgd2l0aFdpbmRvd3NSZXRyeSgoKSA9PiBmcy5yZW5hbWUodGVtcFBhdGgsIGZpbGVQYXRoKSk7XG4gICAgLy8gVHJhY2sgdGhpcyBmaWxlIGluIGNhY2hlIHNvIGZ1dHVyZSB3cml0ZXMga25vdyBpdCBleGlzdHNcbiAgICBjcmVhdGVkRmlsZXNDYWNoZS5hZGQoZmlsZVBhdGgpO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIC8vIE9ubHkgdHJ5IHRvIGNsZWFuIHVwIHRlbXAgZmlsZSBpZiBpdCB3YXMgYWN0dWFsbHkgY3JlYXRlZFxuICAgIGlmICh0ZW1wRmlsZUNyZWF0ZWQpIHtcbiAgICAgIGF3YWl0IHdpdGhXaW5kb3dzUmV0cnkoKCkgPT4gZnMudW5saW5rKHRlbXBQYXRoKSwgMykuY2F0Y2goKCkgPT4ge30pO1xuICAgIH1cbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVhZEpTT048VD4oXG4gIGZpbGVQYXRoOiBzdHJpbmcsXG4gIGRlY29kZXI6IHouWm9kVHlwZTxUPlxuKTogUHJvbWlzZTxUIHwgbnVsbD4ge1xuICB0cnkge1xuICAgIGNvbnN0IGNvbnRlbnQgPSBhd2FpdCBmcy5yZWFkRmlsZShmaWxlUGF0aCwgJ3V0Zi04Jyk7XG4gICAgcmV0dXJuIGRlY29kZXIucGFyc2UoSlNPTi5wYXJzZShjb250ZW50LCBqc29uUmV2aXZlcikpO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGlmICgoZXJyb3IgYXMgYW55KS5jb2RlID09PSAnRU5PRU5UJykgcmV0dXJuIG51bGw7XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlYWRCdWZmZXIoZmlsZVBhdGg6IHN0cmluZyk6IFByb21pc2U8QnVmZmVyPiB7XG4gIGNvbnN0IGNvbnRlbnQgPSBhd2FpdCBmcy5yZWFkRmlsZShmaWxlUGF0aCk7XG4gIHJldHVybiBjb250ZW50O1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVhZEZpcnN0Qnl0ZShcbiAgZmlsZVBhdGg6IHN0cmluZ1xuKTogUHJvbWlzZTxudW1iZXIgfCB1bmRlZmluZWQ+IHtcbiAgY29uc3QgZmlsZSA9IGF3YWl0IGZzLm9wZW4oZmlsZVBhdGgsICdyJyk7XG4gIHRyeSB7XG4gICAgY29uc3QgYnl0ZSA9IEJ1ZmZlci5hbGxvY1Vuc2FmZSgxKTtcbiAgICBjb25zdCB7IGJ5dGVzUmVhZCB9ID0gYXdhaXQgZmlsZS5yZWFkKGJ5dGUsIDAsIDEsIDApO1xuICAgIHJldHVybiBieXRlc1JlYWQgPT09IDAgPyB1bmRlZmluZWQgOiBieXRlWzBdO1xuICB9IGZpbmFsbHkge1xuICAgIGF3YWl0IGZpbGUuY2xvc2UoKTtcbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZGVsZXRlSlNPTihmaWxlUGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gIHRyeSB7XG4gICAgYXdhaXQgZnMudW5saW5rKGZpbGVQYXRoKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBpZiAoKGVycm9yIGFzIGFueSkuY29kZSAhPT0gJ0VOT0VOVCcpIHRocm93IGVycm9yO1xuICB9XG59XG5cbi8qKlxuICogQXRvbWljYWxseSBwdWJsaXNoIGEgZnVsbHktd3JpdHRlbiBmaWxlIHdpdGhvdXQgb3ZlcndyaXRpbmcgYW4gZXhpc3Rpbmcgb25lLlxuICpcbiAqIFdyaXRpbmcgZGlyZWN0bHkgd2l0aCBPX0NSRUFUIHwgT19FWENMIG1ha2VzIHRoZSBkZXN0aW5hdGlvbiB2aXNpYmxlIGJlZm9yZVxuICogaXRzIGNvbnRlbnRzIGFyZSBjb21wbGV0ZSwgc28gY29uY3VycmVudCByZWFkZXJzIGNhbiBvYnNlcnZlIGEgcGFydGlhbCBmaWxlLlxuICogSW5zdGVhZCwgd3JpdGUgdG8gYSB1bmlxdWUgZmlsZSBpbiB0aGUgc2FtZSBkaXJlY3RvcnksIHRoZW4gaGFyZC1saW5rIGl0IGludG9cbiAqIHBsYWNlLiBDcmVhdGluZyB0aGUgbGluayBpcyBhdG9taWMgYW5kIGZhaWxzIHdpdGggRUVYSVNUIGlmIGFub3RoZXIgd3JpdGVyXG4gKiBwdWJsaXNoZWQgdGhlIGRlc3RpbmF0aW9uIGZpcnN0LlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gd3JpdGVFeGNsdXNpdmUoXG4gIGZpbGVQYXRoOiBzdHJpbmcsXG4gIGRhdGE6IHN0cmluZ1xuKTogUHJvbWlzZTxib29sZWFuPiB7XG4gIGF3YWl0IGVuc3VyZURpcihwYXRoLmRpcm5hbWUoZmlsZVBhdGgpKTtcbiAgY29uc3QgdGVtcFBhdGggPSBgJHtmaWxlUGF0aH0udG1wLiR7dWxpZCgpfWA7XG4gIGxldCB0ZW1wRmlsZUNyZWF0ZWQgPSBmYWxzZTtcblxuICB0cnkge1xuICAgIGF3YWl0IGZzLndyaXRlRmlsZSh0ZW1wUGF0aCwgZGF0YSwgeyBmbGFnOiAnd3gnIH0pO1xuICAgIHRlbXBGaWxlQ3JlYXRlZCA9IHRydWU7XG5cbiAgICB0cnkge1xuICAgICAgYXdhaXQgd2l0aFdpbmRvd3NSZXRyeSgoKSA9PiBmcy5saW5rKHRlbXBQYXRoLCBmaWxlUGF0aCkpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBjYXRjaCAoZXJyb3I6IGFueSkge1xuICAgICAgaWYgKGVycm9yLmNvZGUgPT09ICdFRVhJU1QnKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIHRocm93IGVycm9yO1xuICAgIH1cbiAgfSBmaW5hbGx5IHtcbiAgICBpZiAodGVtcEZpbGVDcmVhdGVkKSB7XG4gICAgICBhd2FpdCB3aXRoV2luZG93c1JldHJ5KCgpID0+IGZzLnVubGluayh0ZW1wUGF0aCksIDMpLmNhdGNoKCgpID0+IHt9KTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGxpc3RKU09ORmlsZXMoZGlyUGF0aDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICByZXR1cm4gbGlzdEZpbGVzQnlFeHRlbnNpb24oZGlyUGF0aCwgJy5qc29uJyk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBsaXN0RmlsZXNCeUV4dGVuc2lvbihcbiAgZGlyUGF0aDogc3RyaW5nLFxuICBleHRlbnNpb246IHN0cmluZ1xuKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICB0cnkge1xuICAgIGNvbnN0IGZpbGVzID0gYXdhaXQgZnMucmVhZGRpcihkaXJQYXRoKTtcbiAgICByZXR1cm4gZmlsZXNcbiAgICAgIC5maWx0ZXIoKGYpID0+IGYuZW5kc1dpdGgoZXh0ZW5zaW9uKSlcbiAgICAgIC5tYXAoKGYpID0+IGYuc2xpY2UoMCwgLWV4dGVuc2lvbi5sZW5ndGgpKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBpZiAoKGVycm9yIGFzIGFueSkuY29kZSA9PT0gJ0VOT0VOVCcpIHJldHVybiBbXTtcbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxufVxuXG5pbnRlcmZhY2UgUGFnaW5hdGVkRmlsZVN5c3RlbVF1ZXJ5Q29uZmlnPFQ+IHtcbiAgZGlyZWN0b3J5OiBzdHJpbmc7XG4gIHNjaGVtYTogei5ab2RUeXBlPFQ+O1xuICBmaWxlUHJlZml4Pzogc3RyaW5nO1xuICBmaWxlSWRGaWx0ZXI/OiAoZmlsZUlkOiBzdHJpbmcpID0+IGJvb2xlYW47XG4gIGZpbHRlcj86IChpdGVtOiBUKSA9PiBib29sZWFuO1xuICBzb3J0T3JkZXI/OiAnYXNjJyB8ICdkZXNjJztcbiAgbGltaXQ/OiBudW1iZXI7XG4gIGN1cnNvcj86IHN0cmluZztcbiAgZ2V0Q3JlYXRlZEF0KGZpbGVuYW1lOiBzdHJpbmcpOiBEYXRlIHwgbnVsbDtcbiAgZ2V0SWQ/KGl0ZW06IFQpOiBzdHJpbmc7XG59XG4vLyBDdXJzb3IgZm9ybWF0OiBcInRpbWVzdGFtcHxpZFwiIGZvciB0aWUtYnJlYWtpbmdcbmludGVyZmFjZSBQYXJzZWRDdXJzb3Ige1xuICB0aW1lc3RhbXA6IERhdGU7XG4gIGlkOiBzdHJpbmcgfCBudWxsO1xufVxuXG5mdW5jdGlvbiBwYXJzZUN1cnNvcihjdXJzb3I6IHN0cmluZyB8IHVuZGVmaW5lZCk6IFBhcnNlZEN1cnNvciB8IG51bGwge1xuICBpZiAoIWN1cnNvcikgcmV0dXJuIG51bGw7XG5cbiAgY29uc3QgcGFydHMgPSBjdXJzb3Iuc3BsaXQoJ3wnKTtcbiAgcmV0dXJuIHtcbiAgICB0aW1lc3RhbXA6IG5ldyBEYXRlKHBhcnRzWzBdKSxcbiAgICBpZDogcGFydHNbMV0gfHwgbnVsbCxcbiAgfTtcbn1cblxuZnVuY3Rpb24gY3JlYXRlQ3Vyc29yKHRpbWVzdGFtcDogRGF0ZSwgaWQ6IHN0cmluZyB8IHVuZGVmaW5lZCk6IHN0cmluZyB7XG4gIHJldHVybiBpZCA/IGAke3RpbWVzdGFtcC50b0lTT1N0cmluZygpfXwke2lkfWAgOiB0aW1lc3RhbXAudG9JU09TdHJpbmcoKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHBhZ2luYXRlZEZpbGVTeXN0ZW1RdWVyeTxUIGV4dGVuZHMgeyBjcmVhdGVkQXQ6IERhdGUgfT4oXG4gIGNvbmZpZzogUGFnaW5hdGVkRmlsZVN5c3RlbVF1ZXJ5Q29uZmlnPFQ+XG4pOiBQcm9taXNlPFBhZ2luYXRlZFJlc3BvbnNlPFQ+PiB7XG4gIGNvbnN0IHtcbiAgICBkaXJlY3RvcnksXG4gICAgc2NoZW1hLFxuICAgIGZpbGVQcmVmaXgsXG4gICAgZmlsZUlkRmlsdGVyLFxuICAgIGZpbHRlcixcbiAgICBzb3J0T3JkZXIgPSAnZGVzYycsXG4gICAgbGltaXQgPSAyMCxcbiAgICBjdXJzb3IsXG4gICAgZ2V0Q3JlYXRlZEF0LFxuICAgIGdldElkLFxuICB9ID0gY29uZmlnO1xuXG4gIC8vIFZhbGlkYXRlIGZpbGVQcmVmaXggKHR5cGljYWxseSBgJHtydW5JZH0tYCkgc28gcmVxdWVzdC1kZXJpdmVkIHByZWZpeGVzXG4gIC8vIGNvbnNpc3RlbnRseSByZWplY3QgdW5zYWZlIGNoYXJhY3RlcnMuIGZpbGVQcmVmaXggaXMgb25seSB1c2VkIGJlbG93IHRvXG4gIC8vIGZpbHRlciByZWFkZGlyKCkgcmVzdWx0cyBieSBwcmVmaXgg4oCUIGl0IGRvZXNuJ3QgcGFydGljaXBhdGUgaW4gcGF0aFxuICAvLyBjb25zdHJ1Y3Rpb24g4oCUIGJ1dCBrZWVwaW5nIHRoZSB2YWxpZGF0aW9uIHJ1bGUgdW5pZm9ybSBhY3Jvc3MgdGhlXG4gIC8vIHN0b3JhZ2UgbGF5ZXIgYXZvaWRzIHNwZWNpYWwgY2FzZXMgYW5kIGNhdGNoZXMgYmFkIHZhbHVlcyBlYXJsaWVyLlxuICBpZiAoZmlsZVByZWZpeCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgYXNzZXJ0U2FmZUVudGl0eUlkKCdmaWxlUHJlZml4JywgZmlsZVByZWZpeCk7XG4gIH1cblxuICAvLyAxLiBHZXQgYWxsIEpTT04gZmlsZXMgaW4gZGlyZWN0b3J5XG4gIGNvbnN0IGZpbGVJZHMgPSBhd2FpdCBsaXN0SlNPTkZpbGVzKGRpcmVjdG9yeSk7XG5cbiAgLy8gMi4gRmlsdGVyIGJ5IHByZWZpeCBpZiBwcm92aWRlZFxuICBjb25zdCByZWxldmFudEZpbGVJZHMgPSBmaWxlUHJlZml4XG4gICAgPyBmaWxlSWRzLmZpbHRlcigoZmlsZUlkKSA9PiBmaWxlSWQuc3RhcnRzV2l0aChmaWxlUHJlZml4KSlcbiAgICA6IGZpbGVJZHM7XG4gIGNvbnN0IGZpbHRlcmVkRmlsZUlkcyA9IGZpbGVJZEZpbHRlclxuICAgID8gcmVsZXZhbnRGaWxlSWRzLmZpbHRlcihmaWxlSWRGaWx0ZXIpXG4gICAgOiByZWxldmFudEZpbGVJZHM7XG5cbiAgLy8gMy4gVUxJRCBPcHRpbWl6YXRpb246IEZpbHRlciBieSBjdXJzb3IgdXNpbmcgZmlsZW5hbWUgdGltZXN0YW1wcyBiZWZvcmUgbG9hZGluZyBKU09OXG4gIGNvbnN0IHBhcnNlZEN1cnNvciA9IHBhcnNlQ3Vyc29yKGN1cnNvcik7XG4gIGxldCBjYW5kaWRhdGVGaWxlSWRzID0gZmlsdGVyZWRGaWxlSWRzO1xuXG4gIGlmIChwYXJzZWRDdXJzb3IpIHtcbiAgICBjYW5kaWRhdGVGaWxlSWRzID0gZmlsdGVyZWRGaWxlSWRzLmZpbHRlcigoZmlsZUlkKSA9PiB7XG4gICAgICBjb25zdCBmaWxlbmFtZURhdGUgPSBnZXRDcmVhdGVkQXQoYCR7ZmlsZUlkfS5qc29uYCk7XG4gICAgICBpZiAoZmlsZW5hbWVEYXRlKSB7XG4gICAgICAgIC8vIFVzZSBmaWxlbmFtZSB0aW1lc3RhbXAgZm9yIGN1cnNvciBmaWx0ZXJpbmdcbiAgICAgICAgLy8gV2UgbmVlZCB0byBiZSBjYXJlZnVsIGhlcmU6IGlmIHBhcnNlZEN1cnNvciBoYXMgYW4gSUQgKGZvciB0aWUtYnJlYWtpbmcpLFxuICAgICAgICAvLyB3ZSBuZWVkIHRvIGluY2x1ZGUgaXRlbXMgd2l0aCB0aGUgc2FtZSB0aW1lc3RhbXAgZm9yIGxhdGVyIElELWJhc2VkIGZpbHRlcmluZy5cbiAgICAgICAgLy8gSWYgbm8gSUQsIHdlIGNhbiB1c2Ugc3RyaWN0IGluZXF1YWxpdHkgZm9yIG9wdGltaXphdGlvbi5cbiAgICAgICAgY29uc3QgY3Vyc29yVGltZSA9IHBhcnNlZEN1cnNvci50aW1lc3RhbXAuZ2V0VGltZSgpO1xuICAgICAgICBjb25zdCBmaWxlVGltZSA9IGZpbGVuYW1lRGF0ZS5nZXRUaW1lKCk7XG5cbiAgICAgICAgaWYgKHBhcnNlZEN1cnNvci5pZCkge1xuICAgICAgICAgIC8vIFRpZS1icmVha2luZyBtb2RlOiBpbmNsdWRlIGl0ZW1zIGF0IG9yIG5lYXIgY3Vyc29yIHRpbWVzdGFtcFxuICAgICAgICAgIHJldHVybiBzb3J0T3JkZXIgPT09ICdkZXNjJ1xuICAgICAgICAgICAgPyBmaWxlVGltZSA8PSBjdXJzb3JUaW1lXG4gICAgICAgICAgICA6IGZpbGVUaW1lID49IGN1cnNvclRpbWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gTm8gdGllLWJyZWFraW5nOiBzdHJpY3QgaW5lcXVhbGl0eVxuICAgICAgICAgIHJldHVybiBzb3J0T3JkZXIgPT09ICdkZXNjJ1xuICAgICAgICAgICAgPyBmaWxlVGltZSA8IGN1cnNvclRpbWVcbiAgICAgICAgICAgIDogZmlsZVRpbWUgPiBjdXJzb3JUaW1lO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvLyBDYW4ndCBleHRyYWN0IHRpbWVzdGFtcCBmcm9tIGZpbGVuYW1lIChlLmcuLCBzdGVwcyB1c2Ugc2VxdWVudGlhbCBJRHMpLlxuICAgICAgLy8gSW5jbHVkZSB0aGUgZmlsZSBhbmQgZGVmZXIgdG8gSlNPTi1iYXNlZCBmaWx0ZXJpbmcgYmVsb3cuXG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIDQuIExvYWQgZmlsZXMgaW5kaXZpZHVhbGx5IGFuZCBjb2xsZWN0IHZhbGlkIGl0ZW1zXG4gIGNvbnN0IHZhbGlkSXRlbXM6IFRbXSA9IFtdO1xuXG4gIGZvciAoY29uc3QgZmlsZUlkIG9mIGNhbmRpZGF0ZUZpbGVJZHMpIHtcbiAgICBjb25zdCBmaWxlUGF0aCA9IHBhdGguam9pbihkaXJlY3RvcnksIGAke2ZpbGVJZH0uanNvbmApO1xuICAgIGxldCBpdGVtOiBUIHwgbnVsbCA9IG51bGw7XG4gICAgdHJ5IHtcbiAgICAgIGl0ZW0gPSBhd2FpdCByZWFkSlNPTihmaWxlUGF0aCwgc2NoZW1hKTtcbiAgICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgICAgLy8gV2UgZG9uJ3QgZXhwZWN0IHpvZCBlcnJvcnMgdG8gaGFwcGVuLCBidXQgaWYgdGhlIEpTT04gZG9lcyBnZXQgbWFsZm9ybWVkLFxuICAgICAgLy8gd2Ugc2tpcCB0aGUgaXRlbS4gUHJlZmVyYWJseSwgd2UnZCBoYXZlIGEgd2F5IHRvIG1hcmsgaXRlbXMgYXMgbWFsZm9ybWVkLFxuICAgICAgLy8gc28gdGhhdCB0aGUgVUkgY2FuIGRpc3BsYXkgdGhlbSBhcyBzdWNoLCB3aXRoIHJpY2hlciBtZXNzYWdpbmcuIEluIHRoZSBtZWFudGltZSxcbiAgICAgIC8vIHdlIGp1c3QgbG9nIGEgd2FybmluZyBhbmQgc2tpcCB0aGUgaXRlbS5cbiAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIHouWm9kRXJyb3IpIHtcbiAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgIGBTa2lwcGluZyBpdGVtICR7ZmlsZUlkfSBkdWUgdG8gbWFsZm9ybWVkIEpTT046ICR7ZXJyb3IubWVzc2FnZX1gXG4gICAgICAgICk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuXG4gICAgaWYgKGl0ZW0pIHtcbiAgICAgIC8vIEFwcGx5IGN1c3RvbSBmaWx0ZXIgZWFybHkgaWYgcHJvdmlkZWRcbiAgICAgIGlmIChmaWx0ZXIgJiYgIWZpbHRlcihpdGVtKSkgY29udGludWU7XG5cbiAgICAgIC8vIERvdWJsZS1jaGVjayBjdXJzb3IgZmlsdGVyaW5nIHdpdGggYWN0dWFsIGNyZWF0ZWRBdCBmcm9tIEpTT05cbiAgICAgIC8vIChpbiBjYXNlIFVMSUQgdGltZXN0YW1wIGRpZmZlcnMgZnJvbSBzdG9yZWQgY3JlYXRlZEF0KVxuICAgICAgaWYgKHBhcnNlZEN1cnNvcikge1xuICAgICAgICBjb25zdCBpdGVtVGltZSA9IGl0ZW0uY3JlYXRlZEF0LmdldFRpbWUoKTtcbiAgICAgICAgY29uc3QgY3Vyc29yVGltZSA9IHBhcnNlZEN1cnNvci50aW1lc3RhbXAuZ2V0VGltZSgpO1xuXG4gICAgICAgIGlmIChzb3J0T3JkZXIgPT09ICdkZXNjJykge1xuICAgICAgICAgIC8vIEZvciBkZXNjZW5kaW5nIG9yZGVyLCBza2lwIGl0ZW1zID49IGN1cnNvclxuICAgICAgICAgIGlmIChpdGVtVGltZSA+IGN1cnNvclRpbWUpIGNvbnRpbnVlO1xuICAgICAgICAgIC8vIElmIHRpbWVzdGFtcHMgYXJlIGVxdWFsLCB1c2UgSUQgZm9yIHRpZS1icmVha2luZyAoc2tpcCBpZiBJRCA+PSBjdXJzb3JJZClcbiAgICAgICAgICBpZiAoaXRlbVRpbWUgPT09IGN1cnNvclRpbWUgJiYgcGFyc2VkQ3Vyc29yLmlkICYmIGdldElkKSB7XG4gICAgICAgICAgICBjb25zdCBpdGVtSWQgPSBnZXRJZChpdGVtKTtcbiAgICAgICAgICAgIGlmIChpdGVtSWQgPj0gcGFyc2VkQ3Vyc29yLmlkKSBjb250aW51ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gRm9yIGFzY2VuZGluZyBvcmRlciwgc2tpcCBpdGVtcyA8PSBjdXJzb3JcbiAgICAgICAgICBpZiAoaXRlbVRpbWUgPCBjdXJzb3JUaW1lKSBjb250aW51ZTtcbiAgICAgICAgICAvLyBJZiB0aW1lc3RhbXBzIGFyZSBlcXVhbCwgdXNlIElEIGZvciB0aWUtYnJlYWtpbmcgKHNraXAgaWYgSUQgPD0gY3Vyc29ySWQpXG4gICAgICAgICAgaWYgKGl0ZW1UaW1lID09PSBjdXJzb3JUaW1lICYmIHBhcnNlZEN1cnNvci5pZCAmJiBnZXRJZCkge1xuICAgICAgICAgICAgY29uc3QgaXRlbUlkID0gZ2V0SWQoaXRlbSk7XG4gICAgICAgICAgICBpZiAoaXRlbUlkIDw9IHBhcnNlZEN1cnNvci5pZCkgY29udGludWU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHZhbGlkSXRlbXMucHVzaChpdGVtKTtcbiAgICB9XG4gIH1cblxuICAvLyA1LiBTb3J0IGJ5IGNyZWF0ZWRBdCAoYW5kIGJ5IElEIGZvciB0aWUtYnJlYWtpbmcgaWYgZ2V0SWQgaXMgcHJvdmlkZWQpXG4gIHZhbGlkSXRlbXMuc29ydCgoYSwgYikgPT4ge1xuICAgIGNvbnN0IGFUaW1lID0gYS5jcmVhdGVkQXQuZ2V0VGltZSgpO1xuICAgIGNvbnN0IGJUaW1lID0gYi5jcmVhdGVkQXQuZ2V0VGltZSgpO1xuICAgIGNvbnN0IHRpbWVDb21wYXJpc29uID0gc29ydE9yZGVyID09PSAnYXNjJyA/IGFUaW1lIC0gYlRpbWUgOiBiVGltZSAtIGFUaW1lO1xuXG4gICAgLy8gSWYgdGltZXN0YW1wcyBhcmUgZXF1YWwgYW5kIHdlIGhhdmUgZ2V0SWQsIHVzZSBJRCBmb3Igc3RhYmxlIHNvcnRpbmdcbiAgICBpZiAodGltZUNvbXBhcmlzb24gPT09IDAgJiYgZ2V0SWQpIHtcbiAgICAgIGNvbnN0IGFJZCA9IGdldElkKGEpO1xuICAgICAgY29uc3QgYklkID0gZ2V0SWQoYik7XG4gICAgICByZXR1cm4gc29ydE9yZGVyID09PSAnYXNjJ1xuICAgICAgICA/IGFJZC5sb2NhbGVDb21wYXJlKGJJZClcbiAgICAgICAgOiBiSWQubG9jYWxlQ29tcGFyZShhSWQpO1xuICAgIH1cblxuICAgIHJldHVybiB0aW1lQ29tcGFyaXNvbjtcbiAgfSk7XG5cbiAgLy8gNi4gQXBwbHkgcGFnaW5hdGlvblxuICBjb25zdCBoYXNNb3JlID0gdmFsaWRJdGVtcy5sZW5ndGggPiBsaW1pdDtcbiAgY29uc3QgaXRlbXMgPSBoYXNNb3JlID8gdmFsaWRJdGVtcy5zbGljZSgwLCBsaW1pdCkgOiB2YWxpZEl0ZW1zO1xuICBjb25zdCBuZXh0Q3Vyc29yID1cbiAgICBpdGVtcy5sZW5ndGggPiAwXG4gICAgICA/IGNyZWF0ZUN1cnNvcihcbiAgICAgICAgICBpdGVtc1tpdGVtcy5sZW5ndGggLSAxXS5jcmVhdGVkQXQsXG4gICAgICAgICAgZ2V0SWQ/LihpdGVtc1tpdGVtcy5sZW5ndGggLSAxXSlcbiAgICAgICAgKVxuICAgICAgOiBudWxsO1xuXG4gIHJldHVybiB7XG4gICAgZGF0YTogaXRlbXMsXG4gICAgY3Vyc29yOiBuZXh0Q3Vyc29yLFxuICAgIGhhc01vcmUsXG4gIH07XG59XG4iXX0=
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type { World } from '@workflow/world';
|
|
1
|
+
import type { QueuePrefix, World } from '@workflow/world';
|
|
2
2
|
import type { Config } from './config.js';
|
|
3
3
|
import { type DirectHandler } from './queue.js';
|
|
4
4
|
export { DataDirAccessError, DataDirVersionError, ensureDataDir, initDataDir, type ParsedVersion, parseVersion, } from './init.js';
|
|
5
5
|
export type { DirectHandler } from './queue.js';
|
|
6
6
|
export type LocalWorld = World & {
|
|
7
7
|
/** Register a direct in-process handler for a queue prefix, bypassing HTTP. */
|
|
8
|
-
registerHandler(prefix:
|
|
8
|
+
registerHandler(prefix: QueuePrefix, handler: DirectHandler): void;
|
|
9
9
|
/** Clear all workflow data (runs, steps, events, hooks, streams). */
|
|
10
10
|
clear(): Promise<void>;
|
|
11
11
|
};
|
|
@@ -16,6 +16,7 @@ export type LocalWorld = World & {
|
|
|
16
16
|
* @param args.dataDir - Directory for storing workflow data (default: `.workflow-data/`)
|
|
17
17
|
* @param args.port - Port override for queue transport (default: auto-detected)
|
|
18
18
|
* @param args.baseUrl - Full base URL override for queue transport (default: `http://localhost:{port}`)
|
|
19
|
+
* @param args.recoverActiveRuns - Whether `start()` should re-enqueue pending/running runs from storage (default: `true`)
|
|
19
20
|
* @param args.tag - Optional tag to scope files (e.g., `vitest-0`). When set, files are written
|
|
20
21
|
* as `{id}.{tag}.json` and `clear()` only deletes files matching this tag.
|
|
21
22
|
* @throws {DataDirAccessError} If the data directory cannot be created or accessed
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAE1D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAY1C,OAAO,EAAe,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAM7D,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,aAAa,EACb,WAAW,EACX,KAAK,aAAa,EAClB,YAAY,GACb,MAAM,WAAW,CAAC;AAEnB,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG;IAC/B,+EAA+E;IAC/E,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,GAAG,IAAI,CAAC;IACnE,qEAAqE;IACrE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,UAAU,CAuHnE"}
|