@pipeline-builder/api-core 4.1.21 → 5.0.0
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/lib/errors/app-errors.d.ts +4 -2
- package/lib/errors/app-errors.js +6 -4
- package/lib/helpers/content-disposition.d.ts +14 -0
- package/lib/helpers/content-disposition.js +22 -0
- package/lib/helpers/index.d.ts +1 -0
- package/lib/helpers/index.js +2 -1
- package/lib/services/index.d.ts +1 -1
- package/lib/services/index.js +2 -2
- package/lib/services/leader-lock.d.ts +56 -3
- package/lib/services/leader-lock.js +60 -4
- package/lib/services/scheduler.d.ts +20 -4
- package/lib/services/scheduler.js +36 -6
- package/lib/services/service-keys.d.ts +0 -4
- package/lib/services/service-keys.js +1 -14
- package/lib/types/catalog-metadata.d.ts +0 -6
- package/lib/types/catalog-metadata.js +1 -1
- package/lib/types/ecosystem.d.ts +0 -1
- package/lib/types/ecosystem.js +1 -1
- package/lib/types/feature-flags.d.ts +1 -1
- package/lib/types/feature-flags.js +6 -1
- package/lib/types/index.d.ts +3 -2
- package/lib/types/index.js +3 -2
- package/lib/types/permissions.d.ts +16 -1
- package/lib/types/permissions.js +23 -2
- package/lib/types/plugin-scan.d.ts +26 -0
- package/lib/types/plugin-scan.js +1 -1
- package/lib/types/remote-audit-actions.d.ts +1 -1
- package/lib/types/remote-audit-actions.js +35 -1
- package/lib/types/reserved-tags.d.ts +28 -0
- package/lib/types/reserved-tags.js +37 -0
- package/lib/utils/index.d.ts +1 -1
- package/lib/utils/index.js +2 -2
- package/lib/utils/params.d.ts +33 -1
- package/lib/utils/params.js +54 -2
- package/lib/utils/secret-encryption.d.ts +0 -2
- package/lib/utils/secret-encryption.js +1 -5
- package/lib/validation/message-schemas.d.ts +0 -7
- package/lib/validation/message-schemas.js +2 -1
- package/lib/validation/pipeline-schemas.d.ts +6 -0
- package/lib/validation/pipeline-schemas.js +32 -2
- package/package.json +3 -2
|
@@ -25,7 +25,9 @@ export declare class ValidationError extends AppError {
|
|
|
25
25
|
constructor(message: string);
|
|
26
26
|
}
|
|
27
27
|
/** 409 — Conflict / duplicate. `code` narrows the conflict for clients
|
|
28
|
-
* (e.g. `PLUGIN_VERSION_FROZEN`); it must be a 409-mapped code.
|
|
28
|
+
* (e.g. `PLUGIN_VERSION_FROZEN`); it must be a 409-mapped code. `details`
|
|
29
|
+
* carries what the client needs to resolve it — for a taken pipeline slot,
|
|
30
|
+
* the NORMALIZED names that collided and the id to PUT instead. */
|
|
29
31
|
export declare class ConflictError extends AppError {
|
|
30
|
-
constructor(message: string, code?: ErrorCode);
|
|
32
|
+
constructor(message: string, code?: ErrorCode, details?: Record<string, unknown>);
|
|
31
33
|
}
|
package/lib/errors/app-errors.js
CHANGED
|
@@ -41,11 +41,13 @@ export class ValidationError extends AppError {
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
/** 409 — Conflict / duplicate. `code` narrows the conflict for clients
|
|
44
|
-
* (e.g. `PLUGIN_VERSION_FROZEN`); it must be a 409-mapped code.
|
|
44
|
+
* (e.g. `PLUGIN_VERSION_FROZEN`); it must be a 409-mapped code. `details`
|
|
45
|
+
* carries what the client needs to resolve it — for a taken pipeline slot,
|
|
46
|
+
* the NORMALIZED names that collided and the id to PUT instead. */
|
|
45
47
|
export class ConflictError extends AppError {
|
|
46
|
-
constructor(message, code = ErrorCode.CONFLICT) {
|
|
47
|
-
super(getStatusForErrorCode(ErrorCode.CONFLICT), code, message);
|
|
48
|
+
constructor(message, code = ErrorCode.CONFLICT, details) {
|
|
49
|
+
super(getStatusForErrorCode(ErrorCode.CONFLICT), code, message, details);
|
|
48
50
|
this.name = 'ConflictError';
|
|
49
51
|
}
|
|
50
52
|
}
|
|
51
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
53
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwLWVycm9ycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9lcnJvcnMvYXBwLWVycm9ycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBRXRDLE9BQU8sRUFBRSxTQUFTLEVBQUUscUJBQXFCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUUzRTs7O0dBR0c7QUFDSCxNQUFNLE9BQU8sUUFBUyxTQUFRLEtBQUs7SUFFZixVQUFVO0lBQ1YsSUFBSTtJQUdKLE9BQU87SUFMekIsWUFDa0IsVUFBa0IsRUFDbEIsSUFBZSxFQUMvQixPQUFlO0lBQ2YsZ0ZBQWdGO0lBQ2hFLE9BQWlDO1FBRWpELEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQzswQkFOQyxVQUFVO29CQUNWLElBQUk7dUJBR0osT0FBTztRQUd2QixJQUFJLENBQUMsSUFBSSxHQUFHLFVBQVUsQ0FBQztJQUN6QixDQUFDO0NBQ0Y7QUFFRCxnQ0FBZ0M7QUFDaEMsTUFBTSxPQUFPLGFBQWMsU0FBUSxRQUFRO0lBQ3pDLFlBQVksT0FBZTtRQUN6QixLQUFLLENBQUMscUJBQXFCLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxTQUFTLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDaEYsSUFBSSxDQUFDLElBQUksR0FBRyxlQUFlLENBQUM7SUFDOUIsQ0FBQztDQUNGO0FBRUQsc0NBQXNDO0FBQ3RDLE1BQU0sT0FBTyxjQUFlLFNBQVEsUUFBUTtJQUMxQyxZQUFZLE9BQWU7UUFDekIsS0FBSyxDQUFDLHFCQUFxQixDQUFDLFNBQVMsQ0FBQyx3QkFBd0IsQ0FBQyxFQUFFLFNBQVMsQ0FBQyx3QkFBd0IsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUM5RyxJQUFJLENBQUMsSUFBSSxHQUFHLGdCQUFnQixDQUFDO0lBQy9CLENBQUM7Q0FDRjtBQUVELHNDQUFzQztBQUN0QyxNQUFNLE9BQU8sZUFBZ0IsU0FBUSxRQUFRO0lBQzNDLFlBQVksT0FBZTtRQUN6QixLQUFLLENBQUMscUJBQXFCLENBQUMsU0FBUyxDQUFDLGdCQUFnQixDQUFDLEVBQUUsU0FBUyxDQUFDLGdCQUFnQixFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQzlGLElBQUksQ0FBQyxJQUFJLEdBQUcsaUJBQWlCLENBQUM7SUFDaEMsQ0FBQztDQUNGO0FBRUQ7OztvRUFHb0U7QUFDcEUsTUFBTSxPQUFPLGFBQWMsU0FBUSxRQUFRO0lBQ3pDLFlBQVksT0FBZSxFQUFFLElBQUksR0FBYyxTQUFTLENBQUMsUUFBUSxFQUFFLE9BQWlDO1FBQ2xHLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztRQUN6RSxJQUFJLENBQUMsSUFBSSxHQUFHLGVBQWUsQ0FBQztJQUM5QixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHsgRXJyb3JDb2RlLCBnZXRTdGF0dXNGb3JFcnJvckNvZGUgfSBmcm9tICcuLi90eXBlcy9lcnJvci1jb2Rlcy5qcyc7XG5cbi8qKlxuICogQmFzZSBhcHBsaWNhdGlvbiBlcnJvciB3aXRoIEhUVFAgc3RhdHVzIGNvZGUgYW5kIGVycm9yIGNvZGUuXG4gKiBFeHRlbmQgdGhpcyBmb3IgZG9tYWluLXNwZWNpZmljIGVycm9yIHR5cGVzLlxuICovXG5leHBvcnQgY2xhc3MgQXBwRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyByZWFkb25seSBzdGF0dXNDb2RlOiBudW1iZXIsXG4gICAgcHVibGljIHJlYWRvbmx5IGNvZGU6IEVycm9yQ29kZSxcbiAgICBtZXNzYWdlOiBzdHJpbmcsXG4gICAgLyoqIFN0cnVjdHVyZWQgY29udGV4dCBzZW50IHdpdGggdGhlIGVycm9yIHJlc3BvbnNlIChlLmcuIHRoZSBmYWlsaW5nIGdhdGVzKS4gKi9cbiAgICBwdWJsaWMgcmVhZG9ubHkgZGV0YWlscz86IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICApIHtcbiAgICBzdXBlcihtZXNzYWdlKTtcbiAgICB0aGlzLm5hbWUgPSAnQXBwRXJyb3InO1xuICB9XG59XG5cbi8qKiA0MDQg4oCUIFJlc291cmNlIG5vdCBmb3VuZC4gKi9cbmV4cG9ydCBjbGFzcyBOb3RGb3VuZEVycm9yIGV4dGVuZHMgQXBwRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihtZXNzYWdlOiBzdHJpbmcpIHtcbiAgICBzdXBlcihnZXRTdGF0dXNGb3JFcnJvckNvZGUoRXJyb3JDb2RlLk5PVF9GT1VORCksIEVycm9yQ29kZS5OT1RfRk9VTkQsIG1lc3NhZ2UpO1xuICAgIHRoaXMubmFtZSA9ICdOb3RGb3VuZEVycm9yJztcbiAgfVxufVxuXG4vKiogNDAzIOKAlCBJbnN1ZmZpY2llbnQgcGVybWlzc2lvbnMuICovXG5leHBvcnQgY2xhc3MgRm9yYmlkZGVuRXJyb3IgZXh0ZW5kcyBBcHBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1lc3NhZ2U6IHN0cmluZykge1xuICAgIHN1cGVyKGdldFN0YXR1c0ZvckVycm9yQ29kZShFcnJvckNvZGUuSU5TVUZGSUNJRU5UX1BFUk1JU1NJT05TKSwgRXJyb3JDb2RlLklOU1VGRklDSUVOVF9QRVJNSVNTSU9OUywgbWVzc2FnZSk7XG4gICAgdGhpcy5uYW1lID0gJ0ZvcmJpZGRlbkVycm9yJztcbiAgfVxufVxuXG4vKiogNDAwIOKAlCBWYWxpZGF0aW9uIC8gYmFkIHJlcXVlc3QuICovXG5leHBvcnQgY2xhc3MgVmFsaWRhdGlvbkVycm9yIGV4dGVuZHMgQXBwRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihtZXNzYWdlOiBzdHJpbmcpIHtcbiAgICBzdXBlcihnZXRTdGF0dXNGb3JFcnJvckNvZGUoRXJyb3JDb2RlLlZBTElEQVRJT05fRVJST1IpLCBFcnJvckNvZGUuVkFMSURBVElPTl9FUlJPUiwgbWVzc2FnZSk7XG4gICAgdGhpcy5uYW1lID0gJ1ZhbGlkYXRpb25FcnJvcic7XG4gIH1cbn1cblxuLyoqIDQwOSDigJQgQ29uZmxpY3QgLyBkdXBsaWNhdGUuIGBjb2RlYCBuYXJyb3dzIHRoZSBjb25mbGljdCBmb3IgY2xpZW50c1xuICogIChlLmcuIGBQTFVHSU5fVkVSU0lPTl9GUk9aRU5gKTsgaXQgbXVzdCBiZSBhIDQwOS1tYXBwZWQgY29kZS4gYGRldGFpbHNgXG4gKiAgY2FycmllcyB3aGF0IHRoZSBjbGllbnQgbmVlZHMgdG8gcmVzb2x2ZSBpdCDigJQgZm9yIGEgdGFrZW4gcGlwZWxpbmUgc2xvdCxcbiAqICB0aGUgTk9STUFMSVpFRCBuYW1lcyB0aGF0IGNvbGxpZGVkIGFuZCB0aGUgaWQgdG8gUFVUIGluc3RlYWQuICovXG5leHBvcnQgY2xhc3MgQ29uZmxpY3RFcnJvciBleHRlbmRzIEFwcEVycm9yIHtcbiAgY29uc3RydWN0b3IobWVzc2FnZTogc3RyaW5nLCBjb2RlOiBFcnJvckNvZGUgPSBFcnJvckNvZGUuQ09ORkxJQ1QsIGRldGFpbHM/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikge1xuICAgIHN1cGVyKGdldFN0YXR1c0ZvckVycm9yQ29kZShFcnJvckNvZGUuQ09ORkxJQ1QpLCBjb2RlLCBtZXNzYWdlLCBkZXRhaWxzKTtcbiAgICB0aGlzLm5hbWUgPSAnQ29uZmxpY3RFcnJvcic7XG4gIH1cbn1cbiJdfQ==
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `Content-Disposition: attachment` for a download whose file name is built
|
|
3
|
+
* from stored or request data (a plugin name, a version, a report period). Every
|
|
4
|
+
* character outside `[A-Za-z0-9._-]` becomes `_`, so a quote, a CR/LF or a
|
|
5
|
+
* path separator can never break out of the header or the file name.
|
|
6
|
+
*
|
|
7
|
+
* In api-core rather than in one service because it is a header-injection guard with
|
|
8
|
+
* several callers (plugin's SBOM and scan downloads, reporting's report PDFs). A second
|
|
9
|
+
* copy of a sanitizer is a copy that gets a fix the other one does not.
|
|
10
|
+
*/
|
|
11
|
+
/** A header-safe file name (at most 200 characters, never empty). */
|
|
12
|
+
export declare function safeFileName(name: string): string;
|
|
13
|
+
/** The full header value for downloading `name` as an attachment. */
|
|
14
|
+
export declare function attachmentDisposition(name: string): string;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* `Content-Disposition: attachment` for a download whose file name is built
|
|
5
|
+
* from stored or request data (a plugin name, a version, a report period). Every
|
|
6
|
+
* character outside `[A-Za-z0-9._-]` becomes `_`, so a quote, a CR/LF or a
|
|
7
|
+
* path separator can never break out of the header or the file name.
|
|
8
|
+
*
|
|
9
|
+
* In api-core rather than in one service because it is a header-injection guard with
|
|
10
|
+
* several callers (plugin's SBOM and scan downloads, reporting's report PDFs). A second
|
|
11
|
+
* copy of a sanitizer is a copy that gets a fix the other one does not.
|
|
12
|
+
*/
|
|
13
|
+
/** A header-safe file name (at most 200 characters, never empty). */
|
|
14
|
+
export function safeFileName(name) {
|
|
15
|
+
const cleaned = name.replace(/[^A-Za-z0-9._-]/g, '_').replace(/^\.+/, '_').slice(0, 200);
|
|
16
|
+
return cleaned || 'download';
|
|
17
|
+
}
|
|
18
|
+
/** The full header value for downloading `name` as an attachment. */
|
|
19
|
+
export function attachmentDisposition(name) {
|
|
20
|
+
return `attachment; filename="${safeFileName(name)}"`;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udGVudC1kaXNwb3NpdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9oZWxwZXJzL2NvbnRlbnQtZGlzcG9zaXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0Qzs7Ozs7Ozs7O0dBU0c7QUFFSCxxRUFBcUU7QUFDckUsTUFBTSxVQUFVLFlBQVksQ0FBQyxJQUFZO0lBQ3ZDLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsa0JBQWtCLEVBQUUsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ3pGLE9BQU8sT0FBTyxJQUFJLFVBQVUsQ0FBQztBQUMvQixDQUFDO0FBRUQscUVBQXFFO0FBQ3JFLE1BQU0sVUFBVSxxQkFBcUIsQ0FBQyxJQUFZO0lBQ2hELE9BQU8seUJBQXlCLFlBQVksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDO0FBQ3hELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuLyoqXG4gKiBgQ29udGVudC1EaXNwb3NpdGlvbjogYXR0YWNobWVudGAgZm9yIGEgZG93bmxvYWQgd2hvc2UgZmlsZSBuYW1lIGlzIGJ1aWx0XG4gKiBmcm9tIHN0b3JlZCBvciByZXF1ZXN0IGRhdGEgKGEgcGx1Z2luIG5hbWUsIGEgdmVyc2lvbiwgYSByZXBvcnQgcGVyaW9kKS4gRXZlcnlcbiAqIGNoYXJhY3RlciBvdXRzaWRlIGBbQS1aYS16MC05Ll8tXWAgYmVjb21lcyBgX2AsIHNvIGEgcXVvdGUsIGEgQ1IvTEYgb3IgYVxuICogcGF0aCBzZXBhcmF0b3IgY2FuIG5ldmVyIGJyZWFrIG91dCBvZiB0aGUgaGVhZGVyIG9yIHRoZSBmaWxlIG5hbWUuXG4gKlxuICogSW4gYXBpLWNvcmUgcmF0aGVyIHRoYW4gaW4gb25lIHNlcnZpY2UgYmVjYXVzZSBpdCBpcyBhIGhlYWRlci1pbmplY3Rpb24gZ3VhcmQgd2l0aFxuICogc2V2ZXJhbCBjYWxsZXJzIChwbHVnaW4ncyBTQk9NIGFuZCBzY2FuIGRvd25sb2FkcywgcmVwb3J0aW5nJ3MgcmVwb3J0IFBERnMpLiBBIHNlY29uZFxuICogY29weSBvZiBhIHNhbml0aXplciBpcyBhIGNvcHkgdGhhdCBnZXRzIGEgZml4IHRoZSBvdGhlciBvbmUgZG9lcyBub3QuXG4gKi9cblxuLyoqIEEgaGVhZGVyLXNhZmUgZmlsZSBuYW1lIChhdCBtb3N0IDIwMCBjaGFyYWN0ZXJzLCBuZXZlciBlbXB0eSkuICovXG5leHBvcnQgZnVuY3Rpb24gc2FmZUZpbGVOYW1lKG5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IGNsZWFuZWQgPSBuYW1lLnJlcGxhY2UoL1teQS1aYS16MC05Ll8tXS9nLCAnXycpLnJlcGxhY2UoL15cXC4rLywgJ18nKS5zbGljZSgwLCAyMDApO1xuICByZXR1cm4gY2xlYW5lZCB8fCAnZG93bmxvYWQnO1xufVxuXG4vKiogVGhlIGZ1bGwgaGVhZGVyIHZhbHVlIGZvciBkb3dubG9hZGluZyBgbmFtZWAgYXMgYW4gYXR0YWNobWVudC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhdHRhY2htZW50RGlzcG9zaXRpb24obmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGBhdHRhY2htZW50OyBmaWxlbmFtZT1cIiR7c2FmZUZpbGVOYW1lKG5hbWUpfVwiYDtcbn1cbiJdfQ==
|
package/lib/helpers/index.d.ts
CHANGED
|
@@ -4,3 +4,4 @@ export { loadAndRestore, loadAndPurge, type RestorableService, type PurgeableSer
|
|
|
4
4
|
export * from './sse-helpers.js';
|
|
5
5
|
export * from './org-hierarchy.js';
|
|
6
6
|
export { fetchParentOrgId, fetchOrgDescendants, fetchOrgNames, fetchOrgMembership, } from './org-hierarchy-http.js';
|
|
7
|
+
export * from './content-disposition.js';
|
package/lib/helpers/index.js
CHANGED
|
@@ -6,4 +6,5 @@ export { loadAndRestore, loadAndPurge, } from './restore-helpers.js';
|
|
|
6
6
|
export * from './sse-helpers.js';
|
|
7
7
|
export * from './org-hierarchy.js';
|
|
8
8
|
export { fetchParentOrgId, fetchOrgDescendants, fetchOrgNames, fetchOrgMembership, } from './org-hierarchy-http.js';
|
|
9
|
-
|
|
9
|
+
export * from './content-disposition.js';
|
|
10
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaGVscGVycy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBRXRDLGNBQWMsbUJBQW1CLENBQUM7QUFDbEMsT0FBTyxFQUNMLDRCQUE0QixFQUM1QiwwQkFBMEIsRUFDMUIsZ0JBQWdCLEVBQ2hCLHVCQUF1QixFQUN2QixpQkFBaUIsR0FLbEIsTUFBTSxxQkFBcUIsQ0FBQztBQUM3QixPQUFPLEVBQ0wsY0FBYyxFQUNkLFlBQVksR0FLYixNQUFNLHNCQUFzQixDQUFDO0FBQzlCLGNBQWMsa0JBQWtCLENBQUM7QUFDakMsY0FBYyxvQkFBb0IsQ0FBQztBQUNuQyxPQUFPLEVBQ0wsZ0JBQWdCLEVBQ2hCLG1CQUFtQixFQUNuQixhQUFhLEVBQ2Isa0JBQWtCLEdBQ25CLE1BQU0seUJBQXlCLENBQUM7QUFDakMsY0FBYywwQkFBMEIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5leHBvcnQgKiBmcm9tICcuL2NydWQtaGVscGVycy5qcyc7XG5leHBvcnQge1xuICByZXF1aXJlVmlzaWJpbGl0eVdyaXRlQWNjZXNzLFxuICBjaGVja1Zpc2liaWxpdHlXcml0ZUFjY2VzcyxcbiAgY2hlY2tXcml0ZUFjY2VzcyxcbiAgcmVqZWN0Rm9yYmlkZGVuQnVsa1Jvd3MsXG4gIHJlc29sdmVWaXNpYmlsaXR5LFxuICB0eXBlIFZpc2liaWxpdHlXcml0ZVRhcmdldCxcbiAgdHlwZSBWaXNpYmlsaXR5V3JpdGVWZXJkaWN0LFxuICB0eXBlIFdyaXRlQWNjZXNzLFxuICB0eXBlIEJ1bGtXcml0ZVJvdyxcbn0gZnJvbSAnLi9hY2Nlc3MtaGVscGVycy5qcyc7XG5leHBvcnQge1xuICBsb2FkQW5kUmVzdG9yZSxcbiAgbG9hZEFuZFB1cmdlLFxuICB0eXBlIFJlc3RvcmFibGVTZXJ2aWNlLFxuICB0eXBlIFB1cmdlYWJsZVNlcnZpY2UsXG4gIHR5cGUgVG9tYnN0b25lQXV0aG9yaXplcixcbiAgdHlwZSBUb21ic3RvbmVSb3V0ZU9wdGlvbnMsXG59IGZyb20gJy4vcmVzdG9yZS1oZWxwZXJzLmpzJztcbmV4cG9ydCAqIGZyb20gJy4vc3NlLWhlbHBlcnMuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9vcmctaGllcmFyY2h5LmpzJztcbmV4cG9ydCB7XG4gIGZldGNoUGFyZW50T3JnSWQsXG4gIGZldGNoT3JnRGVzY2VuZGFudHMsXG4gIGZldGNoT3JnTmFtZXMsXG4gIGZldGNoT3JnTWVtYmVyc2hpcCxcbn0gZnJvbSAnLi9vcmctaGllcmFyY2h5LWh0dHAuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9jb250ZW50LWRpc3Bvc2l0aW9uLmpzJztcbiJdfQ==
|
package/lib/services/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { exchangeApiKey, resetApiKeyExchangeCache, ApiKeyRejectedError, ApiKeyExchangeUnavailableError, } from './api-key-exchange.js';
|
|
2
2
|
export { createCacheService, type RedisCacheClient, type CacheInvalidationMessage, type CacheInvalidationBus, type RedisInvalidationClient, CacheService, } from './cache-service.js';
|
|
3
|
-
export { withLeaderLock, createEnvRedisLock, type LockRedis, } from './leader-lock.js';
|
|
3
|
+
export { withLeaderLock, createEnvRedisLock, leaderLockKey, DEFAULT_LEADER_LOCK_TTL_MS, type LockRedis, type LeaderLockRun, type LeaderLockOptions, type LeaderLockAbortReason, } from './leader-lock.js';
|
|
4
4
|
export { sendSystemNotification, SYSTEM_NOTIFY_PATH, type SystemNotification, } from './system-notification.js';
|
|
5
5
|
export { createScheduler, type SchedulerOptions, type Scheduler, } from './scheduler.js';
|
|
6
6
|
export { createComplianceClient, type ComplianceCheckResult, type ComplianceViolation, } from './compliance-client.js';
|
package/lib/services/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
export { exchangeApiKey, resetApiKeyExchangeCache, ApiKeyRejectedError, ApiKeyExchangeUnavailableError, } from './api-key-exchange.js';
|
|
4
4
|
export { createCacheService, CacheService, } from './cache-service.js';
|
|
5
|
-
export { withLeaderLock, createEnvRedisLock, } from './leader-lock.js';
|
|
5
|
+
export { withLeaderLock, createEnvRedisLock, leaderLockKey, DEFAULT_LEADER_LOCK_TTL_MS, } from './leader-lock.js';
|
|
6
6
|
export { sendSystemNotification, SYSTEM_NOTIFY_PATH, } from './system-notification.js';
|
|
7
7
|
export { createScheduler, } from './scheduler.js';
|
|
8
8
|
export { createComplianceClient, } from './compliance-client.js';
|
|
@@ -31,4 +31,4 @@ export { createMemorySseTicketStore, createEnvSseTicketStore, envSseTicketCaps,
|
|
|
31
31
|
export { wireServiceSecurity, } from './service-boot.js';
|
|
32
32
|
export { createWebhookChannel, createEmailChannel, createChannelRegistry, } from './notification-channels.js';
|
|
33
33
|
export { createEcosystemNotifyClient, ECOSYSTEM_NOTIFY_PATH, } from './ecosystem-notify-client.js';
|
|
34
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
34
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VydmljZXMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0QyxPQUFPLEVBQ0wsY0FBYyxFQUNkLHdCQUF3QixFQUN4QixtQkFBbUIsRUFDbkIsOEJBQThCLEdBQy9CLE1BQU0sdUJBQXVCLENBQUM7QUFDL0IsT0FBTyxFQUNMLGtCQUFrQixFQUtsQixZQUFZLEdBQ2IsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QixPQUFPLEVBQ0wsY0FBYyxFQUNkLGtCQUFrQixFQUNsQixhQUFhLEVBQ2IsMEJBQTBCLEdBSzNCLE1BQU0sa0JBQWtCLENBQUM7QUFDMUIsT0FBTyxFQUNMLHNCQUFzQixFQUN0QixrQkFBa0IsR0FFbkIsTUFBTSwwQkFBMEIsQ0FBQztBQUNsQyxPQUFPLEVBQ0wsZUFBZSxHQUdoQixNQUFNLGdCQUFnQixDQUFDO0FBQ3hCLE9BQU8sRUFDTCxzQkFBc0IsR0FHdkIsTUFBTSx3QkFBd0IsQ0FBQztBQUNoQyxPQUFPLEVBQ0wsa0JBQWtCLEVBQ2xCLG9CQUFvQixFQUNwQiwyQkFBMkIsRUFFM0IsOEJBQThCLEdBRS9CLE1BQU0sK0JBQStCLENBQUM7QUFDdkMsY0FBYyxrQ0FBa0MsQ0FBQztBQUNqRCxPQUFPLEVBR0wsWUFBWSxHQUNiLE1BQU0sb0JBQW9CLENBQUM7QUFDNUIsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixnQkFBZ0IsRUFDaEIscUJBQXFCLEVBQ3JCLGtCQUFrQixHQUNuQixNQUFNLGtCQUFrQixDQUFDO0FBQzFCLE9BQU8sRUFDTCxvQkFBb0IsRUFDcEIsb0JBQW9CLEVBQ3BCLGVBQWUsRUFDZixTQUFTLEdBQ1YsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QixpRkFBaUY7QUFDakYsOEVBQThFO0FBQzlFLGlGQUFpRjtBQUNqRiwrREFBK0Q7QUFDL0QsT0FBTyxFQUNMLFlBQVksRUFDWixlQUFlLEVBQ2YsZ0JBQWdCLEdBQ2pCLE1BQU0sbUJBQW1CLENBQUM7QUFDM0IsK0VBQStFO0FBQy9FLHlEQUF5RDtBQUN6RCxPQUFPLEVBQ0wsb0JBQW9CLEdBQ3JCLE1BQU0sc0JBQXNCLENBQUM7QUFDOUIsT0FBTyxFQUNMLDZCQUE2QixHQUc5QixNQUFNLHdCQUF3QixDQUFDO0FBQ2hDLE9BQU8sRUFDTCxxQkFBcUIsR0FDdEIsTUFBTSxxQkFBcUIsQ0FBQztBQUk3QixPQUFPLEVBQ0wsYUFBYSxFQUNiLFlBQVksR0FDYixNQUFNLG9CQUFvQixDQUFDO0FBQzVCLE9BQU8sRUFDTCx5QkFBeUIsRUFDekIsa0JBQWtCLEVBQ2xCLGNBQWMsRUFDZCxZQUFZLEVBQ1osc0JBQXNCLEVBQ3RCLGNBQWMsR0FHZixNQUFNLFlBQVksQ0FBQztBQUNwQixPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLHNCQUFzQixFQUN0QixXQUFXLEdBR1osTUFBTSwwQkFBMEIsQ0FBQztBQUNsQyxPQUFPLEVBQ0wsYUFBYSxFQUNiLHdCQUF3QixHQUV6QixNQUFNLGtCQUFrQixDQUFDO0FBQzFCLE9BQU8sRUFDTCxzQkFBc0IsRUFDdEIsdUJBQXVCLEVBQ3ZCLGlCQUFpQixFQUNqQixvQkFBb0IsRUFDcEIsb0JBQW9CLEVBQ3BCLFVBQVUsRUFDVixnQkFBZ0IsR0FFakIsTUFBTSxnQkFBZ0IsQ0FBQztBQUN4QixPQUFPLEVBQ0wsK0JBQStCLEVBQy9CLGtDQUFrQyxFQUNsQyxzQkFBc0IsRUFDdEIsd0JBQXdCLEVBQ3hCLDJCQUEyQixHQUM1QixNQUFNLHVCQUF1QixDQUFDO0FBQy9CLE9BQU8sRUFDTCwwQkFBMEIsRUFDMUIsdUJBQXVCLEVBQ3ZCLGdCQUFnQixHQUlqQixNQUFNLHVCQUF1QixDQUFDO0FBQy9CLE9BQU8sRUFDTCxtQkFBbUIsR0FDcEIsTUFBTSxtQkFBbUIsQ0FBQztBQUMzQixPQUFPLEVBQ0wsb0JBQW9CLEVBQ3BCLGtCQUFrQixFQUNsQixxQkFBcUIsR0FNdEIsTUFBTSw0QkFBNEIsQ0FBQztBQUNwQyxPQUFPLEVBQ0wsMkJBQTJCLEVBQzNCLHFCQUFxQixHQUV0QixNQUFNLDhCQUE4QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmV4cG9ydCB7XG4gIGV4Y2hhbmdlQXBpS2V5LFxuICByZXNldEFwaUtleUV4Y2hhbmdlQ2FjaGUsXG4gIEFwaUtleVJlamVjdGVkRXJyb3IsXG4gIEFwaUtleUV4Y2hhbmdlVW5hdmFpbGFibGVFcnJvcixcbn0gZnJvbSAnLi9hcGkta2V5LWV4Y2hhbmdlLmpzJztcbmV4cG9ydCB7XG4gIGNyZWF0ZUNhY2hlU2VydmljZSxcbiAgdHlwZSBSZWRpc0NhY2hlQ2xpZW50LFxuICB0eXBlIENhY2hlSW52YWxpZGF0aW9uTWVzc2FnZSxcbiAgdHlwZSBDYWNoZUludmFsaWRhdGlvbkJ1cyxcbiAgdHlwZSBSZWRpc0ludmFsaWRhdGlvbkNsaWVudCxcbiAgQ2FjaGVTZXJ2aWNlLFxufSBmcm9tICcuL2NhY2hlLXNlcnZpY2UuanMnO1xuZXhwb3J0IHtcbiAgd2l0aExlYWRlckxvY2ssXG4gIGNyZWF0ZUVudlJlZGlzTG9jayxcbiAgbGVhZGVyTG9ja0tleSxcbiAgREVGQVVMVF9MRUFERVJfTE9DS19UVExfTVMsXG4gIHR5cGUgTG9ja1JlZGlzLFxuICB0eXBlIExlYWRlckxvY2tSdW4sXG4gIHR5cGUgTGVhZGVyTG9ja09wdGlvbnMsXG4gIHR5cGUgTGVhZGVyTG9ja0Fib3J0UmVhc29uLFxufSBmcm9tICcuL2xlYWRlci1sb2NrLmpzJztcbmV4cG9ydCB7XG4gIHNlbmRTeXN0ZW1Ob3RpZmljYXRpb24sXG4gIFNZU1RFTV9OT1RJRllfUEFUSCxcbiAgdHlwZSBTeXN0ZW1Ob3RpZmljYXRpb24sXG59IGZyb20gJy4vc3lzdGVtLW5vdGlmaWNhdGlvbi5qcyc7XG5leHBvcnQge1xuICBjcmVhdGVTY2hlZHVsZXIsXG4gIHR5cGUgU2NoZWR1bGVyT3B0aW9ucyxcbiAgdHlwZSBTY2hlZHVsZXIsXG59IGZyb20gJy4vc2NoZWR1bGVyLmpzJztcbmV4cG9ydCB7XG4gIGNyZWF0ZUNvbXBsaWFuY2VDbGllbnQsXG4gIHR5cGUgQ29tcGxpYW5jZUNoZWNrUmVzdWx0LFxuICB0eXBlIENvbXBsaWFuY2VWaW9sYXRpb24sXG59IGZyb20gJy4vY29tcGxpYW5jZS1jbGllbnQuanMnO1xuZXhwb3J0IHtcbiAgcGx1Z2luUnVuc093bkltYWdlLFxuICBwbHVnaW5Db21wbGlhbmNlVGFncyxcbiAgZGVyaXZlUGx1Z2luSW1hZ2VDb21wbGlhbmNlLFxuICB0eXBlIFBsdWdpbkNvbXBsaWFuY2VBdHRyaWJ1dGVzLFxuICBQTFVHSU5fSU1BR0VfQ09NUExJQU5DRV9GSUVMRFMsXG4gIHR5cGUgUGx1Z2luSW1hZ2VSb3csXG59IGZyb20gJy4uL3V0aWxzL3BsdWdpbi1jb21wbGlhbmNlLmpzJztcbmV4cG9ydCAqIGZyb20gJy4vY29tcGxpYW5jZS1ldmVudC1zdWJzY3JpYmVyLmpzJztcbmV4cG9ydCB7XG4gIHR5cGUgRW50aXR5RXZlbnQsXG4gIHR5cGUgRW50aXR5RXZlbnRTdWJzY3JpYmVyLFxuICBlbnRpdHlFdmVudHMsXG59IGZyb20gJy4vZW50aXR5LWV2ZW50cy5qcyc7XG5leHBvcnQge1xuICBkZXN0cm95U2hhcmVkSHR0cEFnZW50cyxcbiAgY3JlYXRlU2FmZUNsaWVudCxcbiAgUmVzcG9uc2VUb29MYXJnZUVycm9yLFxuICBJbnRlcm5hbEh0dHBDbGllbnQsXG59IGZyb20gJy4vaHR0cC1jbGllbnQuanMnO1xuZXhwb3J0IHtcbiAgc2V0UGxhdGZvcm1Kd2tzQ2FjaGUsXG4gIEp3a3NVbmF2YWlsYWJsZUVycm9yLFxuICBVbmtub3duS2lkRXJyb3IsXG4gIEp3a3NDYWNoZSxcbn0gZnJvbSAnLi9qd2tzLWNhY2hlLmpzJztcbi8vIFNlcnZpY2Uta2V5IGludGVybmFscyBzdGF5IGludGVybmFsLiBUaGUgcGFja2FnZSBzdXJmYWNlIGlzIHRoZSB2ZXJpZnkvaW5zcGVjdFxuLy8gc2lkZSB0aGF0IHBsYXRmb3JtJ3MgSldUIG9wdGlvbnMgYW5kIHRoZSBhdXRoIG1pZGRsZXdhcmUgbmVlZDsga2V5IE1BVEVSSUFMXG4vLyBoYW5kbGluZyAoYHNpZ25TZXJ2aWNlSnd0YCwgdGhlIGJ1bmRsZSwgdGhlIHRlc3QgcmVzZXQgaG9vaykgaXMgcmVhY2hhYmxlIG9ubHlcbi8vIGJ5IGRlZXAgaW1wb3J0IGZyb20gaW5zaWRlIGFwaS1jb3JlIGFuZCBpdHMgdGVzdGluZyBoZWxwZXJzLlxuZXhwb3J0IHtcbiAgaXNTZXJ2aWNlS2lkLFxuICBzZXJ2aWNlSWRlbnRpdHksXG4gIHZlcmlmeVNlcnZpY2VKd3QsXG59IGZyb20gJy4vc2VydmljZS1rZXlzLmpzJztcbi8vIFRoZSBicmVha2VyIGlzIHdpcmVkIGJ5IHRoZSBzaGFyZWQgSFRUUCBjbGllbnQ7IHNlcnZpY2VzIGNvbnN1bWUgaXRzIEVGRkVDVCxcbi8vIG5vdCB0aGUgY2xhc3MuIE9ubHkgdGhlIG9wZXJhdGlvbmFsIHN1cmZhY2UgaXMgcHVibGljLlxuZXhwb3J0IHtcbiAgcmVzZXRDaXJjdWl0QnJlYWtlcnMsXG59IGZyb20gJy4vY2lyY3VpdC1icmVha2VyLmpzJztcbmV4cG9ydCB7XG4gIGNyZWF0ZUVudlJlZGlzRHVyYWJsZUV2ZW50QnVzLFxuICB0eXBlIEV2ZW50U3Vic2NyaXB0aW9uLFxuICB0eXBlIER1cmFibGVFdmVudEJ1cyxcbn0gZnJvbSAnLi9kdXJhYmxlLWV2ZW50LWJ1cy5qcyc7XG5leHBvcnQge1xuICBnZXRFcnJvclJldHJ5RGVjaXNpb24sXG59IGZyb20gJy4vcmV0cnktc3RyYXRlZ3kuanMnO1xuZXhwb3J0IHR5cGUge1xuICBSZXRyeUNvbmZpZyxcbn0gZnJvbSAnLi9yZXRyeS1zdHJhdGVneS5qcyc7XG5leHBvcnQge1xuICBuZXh0QmFja29mZk1zLFxuICByZXRyeUZvcmV2ZXIsXG59IGZyb20gJy4vcmV0cnktZm9yZXZlci5qcyc7XG5leHBvcnQge1xuICBnZXRRdW90YVNlcnZpY2VBdXRoSGVhZGVyLFxuICBjcmVhdGVRdW90YVNlcnZpY2UsXG4gIGluY3JlbWVudFF1b3RhLFxuICByZXNlcnZlUXVvdGEsXG4gIHNlbmRRdW90YVJlc2VydmVEZW5pZWQsXG4gIGRlY3JlbWVudFF1b3RhLFxuICB0eXBlIFF1b3RhUmVzZXJ2ZVJlc3VsdCxcbiAgdHlwZSBRdW90YVNlcnZpY2UsXG59IGZyb20gJy4vcXVvdGEuanMnO1xuZXhwb3J0IHtcbiAgY3JlYXRlUmVtb3RlQXVkaXRDbGllbnQsXG4gIHdpcmVBdXRoekRlbmlhbEF1ZGl0b3IsXG4gIHJlY29yZEF1ZGl0LFxuICB0eXBlIFJlbW90ZUF1ZGl0RXZlbnQsXG4gIHR5cGUgUmVtb3RlQXVkaXRDbGllbnQsXG59IGZyb20gJy4vcmVtb3RlLWF1ZGl0LWNsaWVudC5qcyc7XG5leHBvcnQge1xuICBhdWRpdFNwb29sS2V5LFxuICBjcmVhdGVFbnZSZWRpc0F1ZGl0U3Bvb2wsXG4gIHR5cGUgQXVkaXRTcG9vbCxcbn0gZnJvbSAnLi9hdWRpdC1zcG9vbC5qcyc7XG5leHBvcnQge1xuICByZXNvbHZlUmVkaXNDb25uZWN0aW9uLFxuICBkZXNjcmliZVJlZGlzQ29ubmVjdGlvbixcbiAgY3JlYXRlUmVkaXNDbGllbnQsXG4gIGNyZWF0ZUVudlJlZGlzQ2xpZW50LFxuICBjcmVhdGVSZWRpc1JlYWR5R2F0ZSxcbiAgaW5jcldpbmRvdyxcbiAgUmVkaXNDb25maWdFcnJvcixcbiAgdHlwZSBSZWRpc0V2YWxDbGllbnQsXG59IGZyb20gJy4vZW52LXJlZGlzLmpzJztcbmV4cG9ydCB7XG4gIGNyZWF0ZVJlZGlzVG9rZW5SZXZvY2F0aW9uU3RvcmUsXG4gIGNyZWF0ZUVudlJlZGlzVG9rZW5SZXZvY2F0aW9uU3RvcmUsXG4gIHB1Ymxpc2hUb2tlblJldm9jYXRpb24sXG4gIHB1Ymxpc2hTZXNzaW9uUmV2b2NhdGlvbixcbiAgcHVibGlzaENyZWRlbnRpYWxSZXZvY2F0aW9uLFxufSBmcm9tICcuL3Rva2VuLXJldm9jYXRpb24uanMnO1xuZXhwb3J0IHtcbiAgY3JlYXRlTWVtb3J5U3NlVGlja2V0U3RvcmUsXG4gIGNyZWF0ZUVudlNzZVRpY2tldFN0b3JlLFxuICBlbnZTc2VUaWNrZXRDYXBzLFxuICB0eXBlIEVudlNzZVRpY2tldFN0b3JlQ29uZmlnLFxuICB0eXBlIFNzZVRpY2tldFN0b3JlLFxuICB0eXBlIFNzZVRpY2tldFN0b3JlQ29uZmlnLFxufSBmcm9tICcuL3NzZS10aWNrZXQtc3RvcmUuanMnO1xuZXhwb3J0IHtcbiAgd2lyZVNlcnZpY2VTZWN1cml0eSxcbn0gZnJvbSAnLi9zZXJ2aWNlLWJvb3QuanMnO1xuZXhwb3J0IHtcbiAgY3JlYXRlV2ViaG9va0NoYW5uZWwsXG4gIGNyZWF0ZUVtYWlsQ2hhbm5lbCxcbiAgY3JlYXRlQ2hhbm5lbFJlZ2lzdHJ5LFxuICB0eXBlIE5vdGlmaWNhdGlvblByaW9yaXR5LFxuICB0eXBlIE5vdGlmaWNhdGlvbk1lc3NhZ2UsXG4gIHR5cGUgQ2hhbm5lbFRhcmdldCxcbiAgdHlwZSBEZWxpdmVyeVJlc3VsdCxcbiAgdHlwZSBOb3RpZmljYXRpb25DaGFubmVsLFxufSBmcm9tICcuL25vdGlmaWNhdGlvbi1jaGFubmVscy5qcyc7XG5leHBvcnQge1xuICBjcmVhdGVFY29zeXN0ZW1Ob3RpZnlDbGllbnQsXG4gIEVDT1NZU1RFTV9OT1RJRllfUEFUSCxcbiAgdHlwZSBFY29zeXN0ZW1Ob3RpZnlDbGllbnQsXG59IGZyb20gJy4vZWNvc3lzdGVtLW5vdGlmeS1jbGllbnQuanMnO1xuIl19
|
|
@@ -22,15 +22,58 @@ export interface LockRedis extends ReadyAwareRedis {
|
|
|
22
22
|
* either method. Never throws.
|
|
23
23
|
*/
|
|
24
24
|
export declare function closeLeaderLock(redis: LockRedis | null | undefined): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Default lock lifetime — a CRASH-RECOVERY window, not a run-duration cover.
|
|
27
|
+
*
|
|
28
|
+
* The holder heartbeats (compare-and-PEXPIRE every `ttlMs / 3`) for as long as
|
|
29
|
+
* `fn` runs, so a six-hour job holds a two-minute lock perfectly well. What the
|
|
30
|
+
* TTL actually decides is how long a job stays BLOCKED after the pod holding it
|
|
31
|
+
* dies without releasing — the key simply sits there until it expires. Sizing the
|
|
32
|
+
* TTL to the expected run time (which is what several callers used to do) turned a
|
|
33
|
+
* crashed pod into hours of silent inactivity.
|
|
34
|
+
*
|
|
35
|
+
* Two minutes leaves three missed heartbeats of slack, so an event-loop stall or a
|
|
36
|
+
* brief Redis blip does not hand the lock to a second pod mid-run, while recovery
|
|
37
|
+
* after a real crash is bounded at two minutes.
|
|
38
|
+
*/
|
|
39
|
+
export declare const DEFAULT_LEADER_LOCK_TTL_MS = 120000;
|
|
40
|
+
/**
|
|
41
|
+
* The one way to build a leader-lock key: `<service>:<job>:leader`.
|
|
42
|
+
*
|
|
43
|
+
* Four conventions had grown up — `plugin:vuln-rescan:leader`,
|
|
44
|
+
* `platform:leader:org-purge`, a bare `ecosystem-stats:leader`, and billing's
|
|
45
|
+
* unnamespaced `subscription-lifecycle` — which meant no single glob found every
|
|
46
|
+
* lock. `KEYS '*:leader'` missed billing's three entirely, so an operator asking
|
|
47
|
+
* "what is held right now" got a partial answer. The env Redis client sets no
|
|
48
|
+
* `keyPrefix`, so these share one flat keyspace with cache, BullMQ and spool keys;
|
|
49
|
+
* the `<service>:` segment is what keeps them apart.
|
|
50
|
+
*/
|
|
51
|
+
export declare function leaderLockKey(service: string, job: string): string;
|
|
52
|
+
/** Why a leader-locked run was told to stop. */
|
|
53
|
+
export type LeaderLockAbortReason = 'lock-lost' | 'shutdown';
|
|
25
54
|
/** What a leader-locked run is told while it runs. */
|
|
26
55
|
export interface LeaderLockRun {
|
|
27
56
|
/**
|
|
28
57
|
* Aborted when the lock is LOST mid-run (a heartbeat found another holder, or
|
|
29
|
-
* the key gone)
|
|
30
|
-
* past
|
|
58
|
+
* the key gone), or when the caller is SHUTTING DOWN. Long runs must check it
|
|
59
|
+
* between units of work and return: past a lock loss another pod may be doing
|
|
60
|
+
* the same work, and on shutdown returning promptly is what releases the lock
|
|
61
|
+
* instead of leaving it to expire.
|
|
62
|
+
*
|
|
63
|
+
* `signal.reason` is a {@link LeaderLockAbortReason}.
|
|
31
64
|
*/
|
|
32
65
|
signal: AbortSignal;
|
|
33
66
|
}
|
|
67
|
+
/** Caller-supplied controls for {@link withLeaderLock}. */
|
|
68
|
+
export interface LeaderLockOptions {
|
|
69
|
+
/**
|
|
70
|
+
* Aborted by the caller to ask a running job to stop — a scheduler's `stop()`
|
|
71
|
+
* on shutdown. Merged into {@link LeaderLockRun.signal}, so a signal-aware `fn`
|
|
72
|
+
* returns and the lock is released in the `finally` rather than lingering for
|
|
73
|
+
* the rest of the TTL.
|
|
74
|
+
*/
|
|
75
|
+
signal?: AbortSignal;
|
|
76
|
+
}
|
|
34
77
|
/**
|
|
35
78
|
* Run `fn` only if this process wins a short-lived distributed lock — the
|
|
36
79
|
* across-pods "single runner" guard for periodic jobs (digest flushes, etc.).
|
|
@@ -46,10 +89,20 @@ export interface LeaderLockRun {
|
|
|
46
89
|
* If Redis can't be reached the run is skipped (returns false) rather than
|
|
47
90
|
* rejecting — callers are timers, and a Redis blip must not crash the process.
|
|
48
91
|
*
|
|
92
|
+
* EVERY outcome is counted, because they mean very different things and the
|
|
93
|
+
* difference used to be visible only in a log line:
|
|
94
|
+
* - `leader_lock_acquired_total` — this pod ran the window. A job whose count
|
|
95
|
+
* stays flat is not running ANYWHERE, which is the condition worth alerting on.
|
|
96
|
+
* - `leader_lock_contended_total` — another pod holds it. Healthy and expected
|
|
97
|
+
* with replicas > 1; exactly one acquire per window across the fleet.
|
|
98
|
+
* - `leader_lock_unavailable_total` — Redis unreachable, so NOBODY ran this
|
|
99
|
+
* window. A Redis blip silently stopping every sweep fleet-wide was previously
|
|
100
|
+
* a WARN log and nothing else.
|
|
101
|
+
*
|
|
49
102
|
* @returns true if we held the lock and ran `fn`; false if another holder did or
|
|
50
103
|
* the lock couldn't be taken.
|
|
51
104
|
*/
|
|
52
|
-
export declare function withLeaderLock(redis: LockRedis, key: string, ttlMs: number, fn: (run: LeaderLockRun) => Promise<void
|
|
105
|
+
export declare function withLeaderLock(redis: LockRedis, key: string, ttlMs: number, fn: (run: LeaderLockRun) => Promise<void>, opts?: LeaderLockOptions): Promise<boolean>;
|
|
53
106
|
/**
|
|
54
107
|
* A `LockRedis` backed by the shared env Redis client (see env-redis.ts) — the leader-lock counterpart to `createEnvRedisAuditSpool` /
|
|
55
108
|
* `createEnvRedisTokenRevocationStore`, for a service that has no BullMQ client to
|
|
@@ -35,6 +35,35 @@ const RELEASE_IF_OWNER = 'if redis.call("get", KEYS[1]) == ARGV[1] then return r
|
|
|
35
35
|
const EXTEND_IF_OWNER = 'if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("pexpire", KEYS[1], ARGV[2]) else return 0 end';
|
|
36
36
|
/** Longest a run waits for a not-yet-connected client before skipping the window. */
|
|
37
37
|
const LOCK_READY_TIMEOUT_MS = 10_000;
|
|
38
|
+
/**
|
|
39
|
+
* Default lock lifetime — a CRASH-RECOVERY window, not a run-duration cover.
|
|
40
|
+
*
|
|
41
|
+
* The holder heartbeats (compare-and-PEXPIRE every `ttlMs / 3`) for as long as
|
|
42
|
+
* `fn` runs, so a six-hour job holds a two-minute lock perfectly well. What the
|
|
43
|
+
* TTL actually decides is how long a job stays BLOCKED after the pod holding it
|
|
44
|
+
* dies without releasing — the key simply sits there until it expires. Sizing the
|
|
45
|
+
* TTL to the expected run time (which is what several callers used to do) turned a
|
|
46
|
+
* crashed pod into hours of silent inactivity.
|
|
47
|
+
*
|
|
48
|
+
* Two minutes leaves three missed heartbeats of slack, so an event-loop stall or a
|
|
49
|
+
* brief Redis blip does not hand the lock to a second pod mid-run, while recovery
|
|
50
|
+
* after a real crash is bounded at two minutes.
|
|
51
|
+
*/
|
|
52
|
+
export const DEFAULT_LEADER_LOCK_TTL_MS = 120_000;
|
|
53
|
+
/**
|
|
54
|
+
* The one way to build a leader-lock key: `<service>:<job>:leader`.
|
|
55
|
+
*
|
|
56
|
+
* Four conventions had grown up — `plugin:vuln-rescan:leader`,
|
|
57
|
+
* `platform:leader:org-purge`, a bare `ecosystem-stats:leader`, and billing's
|
|
58
|
+
* unnamespaced `subscription-lifecycle` — which meant no single glob found every
|
|
59
|
+
* lock. `KEYS '*:leader'` missed billing's three entirely, so an operator asking
|
|
60
|
+
* "what is held right now" got a partial answer. The env Redis client sets no
|
|
61
|
+
* `keyPrefix`, so these share one flat keyspace with cache, BullMQ and spool keys;
|
|
62
|
+
* the `<service>:` segment is what keeps them apart.
|
|
63
|
+
*/
|
|
64
|
+
export function leaderLockKey(service, job) {
|
|
65
|
+
return `${service}:${job}:leader`;
|
|
66
|
+
}
|
|
38
67
|
/**
|
|
39
68
|
* Run `fn` only if this process wins a short-lived distributed lock — the
|
|
40
69
|
* across-pods "single runner" guard for periodic jobs (digest flushes, etc.).
|
|
@@ -50,10 +79,23 @@ const LOCK_READY_TIMEOUT_MS = 10_000;
|
|
|
50
79
|
* If Redis can't be reached the run is skipped (returns false) rather than
|
|
51
80
|
* rejecting — callers are timers, and a Redis blip must not crash the process.
|
|
52
81
|
*
|
|
82
|
+
* EVERY outcome is counted, because they mean very different things and the
|
|
83
|
+
* difference used to be visible only in a log line:
|
|
84
|
+
* - `leader_lock_acquired_total` — this pod ran the window. A job whose count
|
|
85
|
+
* stays flat is not running ANYWHERE, which is the condition worth alerting on.
|
|
86
|
+
* - `leader_lock_contended_total` — another pod holds it. Healthy and expected
|
|
87
|
+
* with replicas > 1; exactly one acquire per window across the fleet.
|
|
88
|
+
* - `leader_lock_unavailable_total` — Redis unreachable, so NOBODY ran this
|
|
89
|
+
* window. A Redis blip silently stopping every sweep fleet-wide was previously
|
|
90
|
+
* a WARN log and nothing else.
|
|
91
|
+
*
|
|
53
92
|
* @returns true if we held the lock and ran `fn`; false if another holder did or
|
|
54
93
|
* the lock couldn't be taken.
|
|
55
94
|
*/
|
|
56
|
-
export async function withLeaderLock(redis, key, ttlMs, fn) {
|
|
95
|
+
export async function withLeaderLock(redis, key, ttlMs, fn, opts = {}) {
|
|
96
|
+
// Asked to stop before we even tried: don't take a lock we are about to drop.
|
|
97
|
+
if (opts.signal?.aborted)
|
|
98
|
+
return false;
|
|
57
99
|
const token = randomUUID();
|
|
58
100
|
let acquired;
|
|
59
101
|
try {
|
|
@@ -70,11 +112,24 @@ export async function withLeaderLock(redis, key, ttlMs, fn) {
|
|
|
70
112
|
lockLogger.warn('Leader lock unavailable; skipping this run', {
|
|
71
113
|
key, error: errorMessage(err),
|
|
72
114
|
});
|
|
115
|
+
emitCounter('leader_lock_unavailable_total', { key });
|
|
73
116
|
return false;
|
|
74
117
|
}
|
|
75
|
-
if (acquired !== 'OK')
|
|
118
|
+
if (acquired !== 'OK') {
|
|
119
|
+
emitCounter('leader_lock_contended_total', { key });
|
|
76
120
|
return false;
|
|
121
|
+
}
|
|
122
|
+
emitCounter('leader_lock_acquired_total', { key });
|
|
77
123
|
const lost = new AbortController();
|
|
124
|
+
// Shutdown is merged into the SAME signal a lock loss uses: from `fn`'s point of
|
|
125
|
+
// view both mean "stop between units of work and return". `signal.reason` says
|
|
126
|
+
// which. Registered with `once` so a long-lived caller signal doesn't retain
|
|
127
|
+
// this controller after the run.
|
|
128
|
+
const onExternalAbort = () => {
|
|
129
|
+
if (!lost.signal.aborted)
|
|
130
|
+
lost.abort('shutdown');
|
|
131
|
+
};
|
|
132
|
+
opts.signal?.addEventListener('abort', onExternalAbort, { once: true });
|
|
78
133
|
let heartbeat;
|
|
79
134
|
if (typeof redis.eval === 'function') {
|
|
80
135
|
const evalFn = redis.eval.bind(redis);
|
|
@@ -83,7 +138,7 @@ export async function withLeaderLock(redis, key, ttlMs, fn) {
|
|
|
83
138
|
if (Number(extended) !== 1 && !lost.signal.aborted) {
|
|
84
139
|
lockLogger.warn('Leader lock lost mid-run (another holder, or the key expired)', { key });
|
|
85
140
|
emitCounter('leader_lock_lost_total', { key });
|
|
86
|
-
lost.abort();
|
|
141
|
+
lost.abort('lock-lost');
|
|
87
142
|
}
|
|
88
143
|
}).catch((err) => {
|
|
89
144
|
// A blip: the next beat retries; the TTL still covers this interval.
|
|
@@ -98,6 +153,7 @@ export async function withLeaderLock(redis, key, ttlMs, fn) {
|
|
|
98
153
|
finally {
|
|
99
154
|
if (heartbeat)
|
|
100
155
|
clearInterval(heartbeat);
|
|
156
|
+
opts.signal?.removeEventListener('abort', onExternalAbort);
|
|
101
157
|
// Release only if the lock is still ours — if our run overran the TTL and
|
|
102
158
|
// another holder took over, releasing here would free their lock early.
|
|
103
159
|
// Prefer an atomic CAS (Lua); fall back to get-then-del for clients without
|
|
@@ -153,4 +209,4 @@ export async function releaseSharedEnvLock() {
|
|
|
153
209
|
sharedLock = undefined;
|
|
154
210
|
await closeLeaderLock(client);
|
|
155
211
|
}
|
|
156
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGVhZGVyLWxvY2suanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VydmljZXMvbGVhZGVyLWxvY2sudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0QyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBQ3BDLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxjQUFjLEVBQXdCLE1BQU0sZ0JBQWdCLENBQUM7QUFDNUYsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFFcEQsTUFBTSxVQUFVLEdBQUcsWUFBWSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0FBb0IvQzs7OztHQUlHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxlQUFlLENBQUMsS0FBbUM7SUFDdkUsSUFBSSxDQUFDLEtBQUs7UUFBRSxPQUFPO0lBQ25CLElBQUksQ0FBQztRQUNILElBQUksT0FBTyxLQUFLLENBQUMsSUFBSSxLQUFLLFVBQVUsRUFBRSxDQUFDO1lBQUMsTUFBTSxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7WUFBQyxPQUFPO1FBQUMsQ0FBQztJQUN2RSxDQUFDO0lBQUMsTUFBTSxDQUFDO1FBQ1AsNkJBQTZCO0lBQy9CLENBQUM7SUFDRCxJQUFJLENBQUM7UUFBQyxLQUFLLENBQUMsVUFBVSxFQUFFLEVBQUUsQ0FBQztJQUFDLENBQUM7SUFBQyxNQUFNLENBQUMsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0FBQzNELENBQUM7QUFFRDtpRUFDaUU7QUFDakUsTUFBTSxnQkFBZ0IsR0FDcEIsbUdBQW1HLENBQUM7QUFFdEcsOERBQThEO0FBQzlELE1BQU0sZUFBZSxHQUNuQixnSEFBZ0gsQ0FBQztBQUVuSCxxRkFBcUY7QUFDckYsTUFBTSxxQkFBcUIsR0FBRyxNQUFNLENBQUM7QUFZckM7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBaUJHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxjQUFjLENBQ2xDLEtBQWdCLEVBQ2hCLEdBQVcsRUFDWCxLQUFhLEVBQ2IsRUFBeUM7SUFFekMsTUFBTSxLQUFLLEdBQUcsVUFBVSxFQUFFLENBQUM7SUFDM0IsSUFBSSxRQUFpQixDQUFDO0lBQ3RCLElBQUksQ0FBQztRQUNILHlFQUF5RTtRQUN6RSxzRUFBc0U7UUFDdEUsdURBQXVEO1FBQ3ZELE1BQU0sY0FBYyxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLHFCQUFxQixFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNqRixRQUFRLEdBQUcsTUFBTSxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQztJQUM1RCxDQUFDO0lBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUNiLDBFQUEwRTtRQUMxRSx5RUFBeUU7UUFDekUsNkVBQTZFO1FBQzdFLFVBQVUsQ0FBQyxJQUFJLENBQUMsNENBQTRDLEVBQUU7WUFDNUQsR0FBRyxFQUFFLEtBQUssRUFBRSxZQUFZLENBQUMsR0FBRyxDQUFDO1NBQzlCLENBQUMsQ0FBQztRQUNILE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUNELElBQUksUUFBUSxLQUFLLElBQUk7UUFBRSxPQUFPLEtBQUssQ0FBQztJQUVwQyxNQUFNLElBQUksR0FBRyxJQUFJLGVBQWUsRUFBRSxDQUFDO0lBQ25DLElBQUksU0FBcUMsQ0FBQztJQUMxQyxJQUFJLE9BQU8sS0FBSyxDQUFDLElBQUksS0FBSyxVQUFVLEVBQUUsQ0FBQztRQUNyQyxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN0QyxTQUFTLEdBQUcsV0FBVyxDQUFDLEdBQUcsRUFBRTtZQUMzQixNQUFNLENBQUMsZUFBZSxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFO2dCQUM5RCxJQUFJLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO29CQUNuRCxVQUFVLENBQUMsSUFBSSxDQUFDLCtEQUErRCxFQUFFLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztvQkFDMUYsV0FBVyxDQUFDLHdCQUF3QixFQUFFLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztvQkFDL0MsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUNmLENBQUM7WUFDSCxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRTtnQkFDZixxRUFBcUU7Z0JBQ3JFLFVBQVUsQ0FBQyxLQUFLLENBQUMsOEJBQThCLEVBQUUsRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLFlBQVksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDdEYsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3ZDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDO0lBQ3RCLENBQUM7SUFFRCxJQUFJLENBQUM7UUFDSCxNQUFNLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztJQUNwQyxDQUFDO1lBQVMsQ0FBQztRQUNULElBQUksU0FBUztZQUFFLGFBQWEsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUN4QywwRUFBMEU7UUFDMUUsd0VBQXdFO1FBQ3hFLDRFQUE0RTtRQUM1RSxxREFBcUQ7UUFDckQsSUFBSSxDQUFDO1lBQ0gsSUFBSSxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssVUFBVSxFQUFFLENBQUM7Z0JBQ3JDLE1BQU0sS0FBSyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQ3BELENBQUM7aUJBQU0sSUFBSSxDQUFDLE1BQU0sS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEtBQUssRUFBRSxDQUFDO2dCQUM1QyxNQUFNLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDdkIsQ0FBQztRQUNILENBQUM7UUFBQyxNQUFNLENBQUM7WUFDUCxvREFBb0Q7UUFDdEQsQ0FBQztJQUNILENBQUM7SUFDRCxPQUFPLElBQUksQ0FBQztBQUNkLENBQUM7QUFFRDs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxVQUFVLGtCQUFrQjtJQUNoQyxNQUFNLElBQUksR0FBRyxvQkFBb0IsQ0FBWSxhQUFhLENBQUMsQ0FBQztJQUM1RCxJQUFJLElBQUk7UUFBRSxVQUFVLENBQUMsSUFBSSxDQUFDLHNDQUFzQyxDQUFDLENBQUM7SUFDbEUsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDO0FBRUQsNkVBQTZFO0FBQzdFLDZFQUE2RTtBQUM3RSwyREFBMkQ7QUFDM0QsSUFBSSxVQUF3QyxDQUFDO0FBQzdDLElBQUksZUFBZSxHQUFHLENBQUMsQ0FBQztBQUV4QiwyRkFBMkY7QUFDM0YsTUFBTSxVQUFVLG9CQUFvQjtJQUNsQyxJQUFJLFVBQVUsS0FBSyxTQUFTO1FBQUUsVUFBVSxHQUFHLGtCQUFrQixFQUFFLENBQUM7SUFDaEUsZUFBZSxFQUFFLENBQUM7SUFDbEIsT0FBTyxVQUFVLENBQUM7QUFDcEIsQ0FBQztBQUVELDhGQUE4RjtBQUM5RixNQUFNLENBQUMsS0FBSyxVQUFVLG9CQUFvQjtJQUN4QyxJQUFJLGVBQWUsS0FBSyxDQUFDO1FBQUUsT0FBTztJQUNsQyxlQUFlLEVBQUUsQ0FBQztJQUNsQixJQUFJLGVBQWUsR0FBRyxDQUFDO1FBQUUsT0FBTztJQUNoQyxNQUFNLE1BQU0sR0FBRyxVQUFVLENBQUM7SUFDMUIsVUFBVSxHQUFHLFNBQVMsQ0FBQztJQUN2QixNQUFNLGVBQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUNoQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCB7IHJhbmRvbVVVSUQgfSBmcm9tICdjcnlwdG8nO1xuaW1wb3J0IHsgY3JlYXRlRW52UmVkaXNDbGllbnQsIHdoZW5SZWRpc1JlYWR5LCB0eXBlIFJlYWR5QXdhcmVSZWRpcyB9IGZyb20gJy4vZW52LXJlZGlzLmpzJztcbmltcG9ydCB7IGNyZWF0ZUxvZ2dlciB9IGZyb20gJy4uL3V0aWxzL2xvZ2dlci5qcyc7XG5pbXBvcnQgeyBlbWl0Q291bnRlciB9IGZyb20gJy4uL3V0aWxzL21ldHJpYy1lbWl0dGVyLmpzJztcbmltcG9ydCB7IGVycm9yTWVzc2FnZSB9IGZyb20gJy4uL3V0aWxzL3Jlc3BvbnNlLmpzJztcblxuY29uc3QgbG9ja0xvZ2dlciA9IGNyZWF0ZUxvZ2dlcignbGVhZGVyLWxvY2snKTtcblxuLyoqXG4gKiBNaW5pbWFsIFJlZGlzIGNsaWVudCBzdXJmYWNlIG5lZWRlZCBmb3IgYSBsZWFkZXIgbG9jayAoYSBzdWJzZXQgb2YgaW9yZWRpcykuXG4gKiBgc2V0YCBpcyB2YXJpYWRpYyBzbyBjYWxsZXJzIGNhbiBwYXNzIGAnUFgnLCB0dGwsICdOWCdgLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIExvY2tSZWRpcyBleHRlbmRzIFJlYWR5QXdhcmVSZWRpcyB7XG4gIHNldChrZXk6IHN0cmluZywgdmFsdWU6IHN0cmluZywgLi4uYXJnczogdW5rbm93bltdKTogUHJvbWlzZTx1bmtub3duPjtcbiAgZ2V0KGtleTogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPjtcbiAgZGVsKC4uLmtleXM6IHN0cmluZ1tdKTogUHJvbWlzZTxudW1iZXI+O1xuICAvKiogT3B0aW9uYWwgTHVhIGV2YWwgKGlvcmVkaXMgaGFzIGl0KS4gV2hlbiBwcmVzZW50LCByZWxlYXNlIHVzZXMgYW4gYXRvbWljXG4gICAqICBjb21wYXJlLWFuZC1kZWxldGUgc28gYSBsYXBzZWQgaG9sZGVyIGNhbid0IGZyZWUgYSBzdWNjZXNzb3IncyBsb2NrLiAqL1xuICBldmFsPyhzY3JpcHQ6IHN0cmluZywgbnVtS2V5czogbnVtYmVyLCAuLi5hcmdzOiB1bmtub3duW10pOiBQcm9taXNlPHVua25vd24+O1xuICAvKiogR3JhY2VmdWwgY2xvc2UgKGlvcmVkaXMgYHF1aXRgKSDigJQgY2FsbGVkIG9uIHNodXRkb3duIHNvIHRoZSBjb25uZWN0aW9uXG4gICAqICBkb2Vzbid0IGtlZXAgdGhlIGV2ZW50IGxvb3AgYWxpdmUuICovXG4gIHF1aXQ/KCk6IFByb21pc2U8dW5rbm93bj47XG4gIC8qKiBJbW1lZGlhdGUgY2xvc2UgKGlvcmVkaXMgYGRpc2Nvbm5lY3RgKSDigJQgdGhlIGZhbGxiYWNrIGlmIGBxdWl0YCBmYWlscy4gKi9cbiAgZGlzY29ubmVjdD8oKTogdm9pZDtcbn1cblxuLyoqXG4gKiBCZXN0LWVmZm9ydCBjbG9zZSBvZiBhIGxlYWRlci1sb2NrIFJlZGlzIGNsaWVudCBvbiBzaHV0ZG93bi4gUHJlZmVycyBncmFjZWZ1bFxuICogYHF1aXRgOyBmYWxscyBiYWNrIHRvIGBkaXNjb25uZWN0YC4gTm8tb3AgZm9yIGEgbnVsbCBjbGllbnQgLyBvbmUgd2l0aG91dFxuICogZWl0aGVyIG1ldGhvZC4gTmV2ZXIgdGhyb3dzLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY2xvc2VMZWFkZXJMb2NrKHJlZGlzOiBMb2NrUmVkaXMgfCBudWxsIHwgdW5kZWZpbmVkKTogUHJvbWlzZTx2b2lkPiB7XG4gIGlmICghcmVkaXMpIHJldHVybjtcbiAgdHJ5IHtcbiAgICBpZiAodHlwZW9mIHJlZGlzLnF1aXQgPT09ICdmdW5jdGlvbicpIHsgYXdhaXQgcmVkaXMucXVpdCgpOyByZXR1cm47IH1cbiAgfSBjYXRjaCB7XG4gICAgLy8gZmFsbCB0aHJvdWdoIHRvIGRpc2Nvbm5lY3RcbiAgfVxuICB0cnkgeyByZWRpcy5kaXNjb25uZWN0Py4oKTsgfSBjYXRjaCB7IC8qIGJlc3QtZWZmb3J0ICovIH1cbn1cblxuLyoqIEF0b21pYyBcImRlbGV0ZSBvbmx5IGlmIEkgc3RpbGwgb3duIGl0XCIg4oCUIGNsb3NlcyB0aGUgZ2V0LXRoZW4tZGVsIHJhY2Ugd2hlcmVcbiAqICB0aGUgbG9jayBleHBpcmVzIGFuZCBpcyByZS1hY3F1aXJlZCBiZXR3ZWVuIHRoZSB0d28gY2FsbHMuICovXG5jb25zdCBSRUxFQVNFX0lGX09XTkVSID1cbiAgJ2lmIHJlZGlzLmNhbGwoXCJnZXRcIiwgS0VZU1sxXSkgPT0gQVJHVlsxXSB0aGVuIHJldHVybiByZWRpcy5jYWxsKFwiZGVsXCIsIEtFWVNbMV0pIGVsc2UgcmV0dXJuIDAgZW5kJztcblxuLyoqIEF0b21pYyBcImV4dGVuZCBvbmx5IGlmIEkgc3RpbGwgb3duIGl0XCIg4oCUIHRoZSBoZWFydGJlYXQuICovXG5jb25zdCBFWFRFTkRfSUZfT1dORVIgPVxuICAnaWYgcmVkaXMuY2FsbChcImdldFwiLCBLRVlTWzFdKSA9PSBBUkdWWzFdIHRoZW4gcmV0dXJuIHJlZGlzLmNhbGwoXCJwZXhwaXJlXCIsIEtFWVNbMV0sIEFSR1ZbMl0pIGVsc2UgcmV0dXJuIDAgZW5kJztcblxuLyoqIExvbmdlc3QgYSBydW4gd2FpdHMgZm9yIGEgbm90LXlldC1jb25uZWN0ZWQgY2xpZW50IGJlZm9yZSBza2lwcGluZyB0aGUgd2luZG93LiAqL1xuY29uc3QgTE9DS19SRUFEWV9USU1FT1VUX01TID0gMTBfMDAwO1xuXG4vKiogV2hhdCBhIGxlYWRlci1sb2NrZWQgcnVuIGlzIHRvbGQgd2hpbGUgaXQgcnVucy4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTGVhZGVyTG9ja1J1biB7XG4gIC8qKlxuICAgKiBBYm9ydGVkIHdoZW4gdGhlIGxvY2sgaXMgTE9TVCBtaWQtcnVuIChhIGhlYXJ0YmVhdCBmb3VuZCBhbm90aGVyIGhvbGRlciwgb3JcbiAgICogdGhlIGtleSBnb25lKS4gTG9uZyBydW5zIHNob3VsZCBjaGVjayBpdCBiZXR3ZWVuIHVuaXRzIG9mIHdvcmsgYW5kIHN0b3Ag4oCUXG4gICAqIHBhc3QgdGhhdCBwb2ludCBhbm90aGVyIHBvZCBtYXkgYmUgZG9pbmcgdGhlIHNhbWUgd29yay5cbiAgICovXG4gIHNpZ25hbDogQWJvcnRTaWduYWw7XG59XG5cbi8qKlxuICogUnVuIGBmbmAgb25seSBpZiB0aGlzIHByb2Nlc3Mgd2lucyBhIHNob3J0LWxpdmVkIGRpc3RyaWJ1dGVkIGxvY2sg4oCUIHRoZVxuICogYWNyb3NzLXBvZHMgXCJzaW5nbGUgcnVubmVyXCIgZ3VhcmQgZm9yIHBlcmlvZGljIGpvYnMgKGRpZ2VzdCBmbHVzaGVzLCBldGMuKS5cbiAqXG4gKiBVc2VzIGBTRVQga2V5IHRva2VuIE5YIFBYIHR0bGAsIHNvIGV4YWN0bHkgb25lIGhvbGRlciBydW5zIHBlciB3aW5kb3cgYW5kIHRoZVxuICogbG9jayBhdXRvLWV4cGlyZXMgaWYgdGhhdCBob2xkZXIgZGllcyBtaWQtcnVuIChubyBzdHVjayBsb2NrKS4gV2hpbGUgYGZuYFxuICogcnVucywgdGhlIGhvbGRlciBIRUFSVEJFQVRTIChjb21wYXJlLWFuZC1QRVhQSVJFIGV2ZXJ5IGB0dGxNcyAvIDNgKSwgc28gYSBydW5cbiAqIHRoYXQgb3V0bGFzdHMgYHR0bE1zYCBrZWVwcyB0aGUgbG9jayBpbnN0ZWFkIG9mIHNpbGVudGx5IGxldHRpbmcgYSBzZWNvbmQgcG9kXG4gKiBzdGFydCB0aGUgc2FtZSB3b3JrOyBhIGhlYXJ0YmVhdCB0aGF0IGZpbmRzIHRoZSBsb2NrIGdvbmUgYWJvcnRzXG4gKiBgcnVuLnNpZ25hbGAuIFRoZSBsb2NrIGlzIHJlbGVhc2VkIG9uIGNvbXBsZXRpb24sIGJ1dCBvbmx5IGlmIHdlIHN0aWxsIG93blxuICogaXQg4oCUIGEgc2xvd2VyIHByZWRlY2Vzc29yIG5ldmVyIGRlbGV0ZXMgYSBzdWNjZXNzb3IncyBsb2NrLlxuICpcbiAqIElmIFJlZGlzIGNhbid0IGJlIHJlYWNoZWQgdGhlIHJ1biBpcyBza2lwcGVkIChyZXR1cm5zIGZhbHNlKSByYXRoZXIgdGhhblxuICogcmVqZWN0aW5nIOKAlCBjYWxsZXJzIGFyZSB0aW1lcnMsIGFuZCBhIFJlZGlzIGJsaXAgbXVzdCBub3QgY3Jhc2ggdGhlIHByb2Nlc3MuXG4gKlxuICogQHJldHVybnMgdHJ1ZSBpZiB3ZSBoZWxkIHRoZSBsb2NrIGFuZCByYW4gYGZuYDsgZmFsc2UgaWYgYW5vdGhlciBob2xkZXIgZGlkIG9yXG4gKiAgIHRoZSBsb2NrIGNvdWxkbid0IGJlIHRha2VuLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gd2l0aExlYWRlckxvY2soXG4gIHJlZGlzOiBMb2NrUmVkaXMsXG4gIGtleTogc3RyaW5nLFxuICB0dGxNczogbnVtYmVyLFxuICBmbjogKHJ1bjogTGVhZGVyTG9ja1J1bikgPT4gUHJvbWlzZTx2b2lkPixcbik6IFByb21pc2U8Ym9vbGVhbj4ge1xuICBjb25zdCB0b2tlbiA9IHJhbmRvbVVVSUQoKTtcbiAgbGV0IGFjcXVpcmVkOiB1bmtub3duO1xuICB0cnkge1xuICAgIC8vIFRoZSBlbnYgY2xpZW50IGhhcyBubyBvZmZsaW5lIHF1ZXVlOiBhIFNFVCBiZWZvcmUgdGhlIGZpcnN0IGNvbm5lY3Rpb25cbiAgICAvLyBjb21wbGV0ZXMgaXMgcmVqZWN0ZWQsIHdoaWNoIG1hZGUgdGhlIEZJUlNUIHRpY2sgYWZ0ZXIgZXZlcnkgYm9vdCBhXG4gICAgLy8gZ3VhcmFudGVlZCBza2lwLiBXYWl0IChib3VuZGVkKSBmb3IgcmVhZGluZXNzIGZpcnN0LlxuICAgIGF3YWl0IHdoZW5SZWRpc1JlYWR5KHJlZGlzLCBNYXRoLm1pbihMT0NLX1JFQURZX1RJTUVPVVRfTVMsIE1hdGgubWF4KDEsIHR0bE1zKSkpO1xuICAgIGFjcXVpcmVkID0gYXdhaXQgcmVkaXMuc2V0KGtleSwgdG9rZW4sICdQWCcsIHR0bE1zLCAnTlgnKTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgLy8gUmVkaXMgdW5yZWFjaGFibGUgKGluY2x1ZGluZyBiZWZvcmUgdGhlIGZpcnN0IGNvbm5lY3Rpb24gY29tcGxldGVzKTogbm9cbiAgICAvLyBwb2QgY2FuIHByb3ZlIGl0J3MgdGhlIGxlYWRlciwgc28gbm9ib2R5IHJ1bnMgdGhpcyB3aW5kb3cuIFNraXBwaW5nIGlzXG4gICAgLy8gdGhlIHNhZmUgc2lkZSDigJQgcnVubmluZyBoZXJlIGNvdWxkIGR1cGxpY2F0ZSBkZXN0cnVjdGl2ZSB3b3JrIGFjcm9zcyBwb2RzLlxuICAgIGxvY2tMb2dnZXIud2FybignTGVhZGVyIGxvY2sgdW5hdmFpbGFibGU7IHNraXBwaW5nIHRoaXMgcnVuJywge1xuICAgICAga2V5LCBlcnJvcjogZXJyb3JNZXNzYWdlKGVyciksXG4gICAgfSk7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGlmIChhY3F1aXJlZCAhPT0gJ09LJykgcmV0dXJuIGZhbHNlO1xuXG4gIGNvbnN0IGxvc3QgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG4gIGxldCBoZWFydGJlYXQ6IE5vZGVKUy5UaW1lb3V0IHwgdW5kZWZpbmVkO1xuICBpZiAodHlwZW9mIHJlZGlzLmV2YWwgPT09ICdmdW5jdGlvbicpIHtcbiAgICBjb25zdCBldmFsRm4gPSByZWRpcy5ldmFsLmJpbmQocmVkaXMpO1xuICAgIGhlYXJ0YmVhdCA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgIGV2YWxGbihFWFRFTkRfSUZfT1dORVIsIDEsIGtleSwgdG9rZW4sIHR0bE1zKS50aGVuKChleHRlbmRlZCkgPT4ge1xuICAgICAgICBpZiAoTnVtYmVyKGV4dGVuZGVkKSAhPT0gMSAmJiAhbG9zdC5zaWduYWwuYWJvcnRlZCkge1xuICAgICAgICAgIGxvY2tMb2dnZXIud2FybignTGVhZGVyIGxvY2sgbG9zdCBtaWQtcnVuIChhbm90aGVyIGhvbGRlciwgb3IgdGhlIGtleSBleHBpcmVkKScsIHsga2V5IH0pO1xuICAgICAgICAgIGVtaXRDb3VudGVyKCdsZWFkZXJfbG9ja19sb3N0X3RvdGFsJywgeyBrZXkgfSk7XG4gICAgICAgICAgbG9zdC5hYm9ydCgpO1xuICAgICAgICB9XG4gICAgICB9KS5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICAgIC8vIEEgYmxpcDogdGhlIG5leHQgYmVhdCByZXRyaWVzOyB0aGUgVFRMIHN0aWxsIGNvdmVycyB0aGlzIGludGVydmFsLlxuICAgICAgICBsb2NrTG9nZ2VyLmRlYnVnKCdMZWFkZXIgbG9jayBoZWFydGJlYXQgZmFpbGVkJywgeyBrZXksIGVycm9yOiBlcnJvck1lc3NhZ2UoZXJyKSB9KTtcbiAgICAgIH0pO1xuICAgIH0sIE1hdGgubWF4KDEsIE1hdGguZmxvb3IodHRsTXMgLyAzKSkpO1xuICAgIGhlYXJ0YmVhdC51bnJlZj8uKCk7XG4gIH1cblxuICB0cnkge1xuICAgIGF3YWl0IGZuKHsgc2lnbmFsOiBsb3N0LnNpZ25hbCB9KTtcbiAgfSBmaW5hbGx5IHtcbiAgICBpZiAoaGVhcnRiZWF0KSBjbGVhckludGVydmFsKGhlYXJ0YmVhdCk7XG4gICAgLy8gUmVsZWFzZSBvbmx5IGlmIHRoZSBsb2NrIGlzIHN0aWxsIG91cnMg4oCUIGlmIG91ciBydW4gb3ZlcnJhbiB0aGUgVFRMIGFuZFxuICAgIC8vIGFub3RoZXIgaG9sZGVyIHRvb2sgb3ZlciwgcmVsZWFzaW5nIGhlcmUgd291bGQgZnJlZSB0aGVpciBsb2NrIGVhcmx5LlxuICAgIC8vIFByZWZlciBhbiBhdG9taWMgQ0FTIChMdWEpOyBmYWxsIGJhY2sgdG8gZ2V0LXRoZW4tZGVsIGZvciBjbGllbnRzIHdpdGhvdXRcbiAgICAvLyBldmFsICh0aGUgc21hbGwgbm9uLWF0b21pYyB3aW5kb3cgaXMgVFRMLWJvdW5kZWQpLlxuICAgIHRyeSB7XG4gICAgICBpZiAodHlwZW9mIHJlZGlzLmV2YWwgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgYXdhaXQgcmVkaXMuZXZhbChSRUxFQVNFX0lGX09XTkVSLCAxLCBrZXksIHRva2VuKTtcbiAgICAgIH0gZWxzZSBpZiAoKGF3YWl0IHJlZGlzLmdldChrZXkpKSA9PT0gdG9rZW4pIHtcbiAgICAgICAgYXdhaXQgcmVkaXMuZGVsKGtleSk7XG4gICAgICB9XG4gICAgfSBjYXRjaCB7XG4gICAgICAvLyBCZXN0LWVmZm9ydDogdGhlIFRUTCBleHBpcmVzIHRoZSBsb2NrIHJlZ2FyZGxlc3MuXG4gICAgfVxuICB9XG4gIHJldHVybiB0cnVlO1xufVxuXG4vKipcbiAqIEEgYExvY2tSZWRpc2AgYmFja2VkIGJ5IHRoZSBzaGFyZWQgZW52IFJlZGlzIGNsaWVudCAoc2VlIGVudi1yZWRpcy50cykg4oCUIHRoZSBsZWFkZXItbG9jayBjb3VudGVycGFydCB0byBgY3JlYXRlRW52UmVkaXNBdWRpdFNwb29sYCAvXG4gKiBgY3JlYXRlRW52UmVkaXNUb2tlblJldm9jYXRpb25TdG9yZWAsIGZvciBhIHNlcnZpY2UgdGhhdCBoYXMgbm8gQnVsbE1RIGNsaWVudCB0b1xuICogYm9ycm93LiBSZXR1cm5zIGBudWxsYCB3aGVuIFJlZGlzIGlzbid0IGNvbmZpZ3VyZWQsIHNvIGEgY2FsbGVyIGNhbiBkZWdyYWRlIHRvXG4gKiBydW5uaW5nIG9uIGV2ZXJ5IHBvZCAodGhlIGF0b21pYyBndWFyZHMgaXQgd3JhcHMgbXVzdCBzdGlsbCBtYWtlIHRoYXQgc2FmZSkuXG4gKiBUaGUgY2xpZW50IGlzIGEgcmVhbCBpb3JlZGlzIGluc3RhbmNlOyBpb3JlZGlzIGV4cG9zZXMgYHNldGAvYGdldGAvYGRlbGAvYGV2YWxgLFxuICogc2F0aXNmeWluZyBgTG9ja1JlZGlzYCBpbmNsdWRpbmcgdGhlIGF0b21pYyBDQVMgcmVsZWFzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUVudlJlZGlzTG9jaygpOiBMb2NrUmVkaXMgfCBudWxsIHtcbiAgY29uc3QgaW5zdCA9IGNyZWF0ZUVudlJlZGlzQ2xpZW50PExvY2tSZWRpcz4oJ2xlYWRlci1sb2NrJyk7XG4gIGlmIChpbnN0KSBsb2NrTG9nZ2VyLmluZm8oJ1JlZGlzIGxlYWRlci1sb2NrIGNsaWVudCBpbml0aWFsaXplZCcpO1xuICByZXR1cm4gaW5zdDtcbn1cblxuLy8gT25lIGVudi1jb25maWd1cmVkIGxvY2sgY2xpZW50IHBlciBwcm9jZXNzLCBzaGFyZWQgYnkgZXZlcnkgc2NoZWR1bGVyIHRoYXRcbi8vIGFza3MgZm9yIGEgbG9jayB3aXRob3V0IHN1cHBseWluZyBpdHMgb3duIGNsaWVudC4gUmVmZXJlbmNlLWNvdW50ZWQgc28gdGhlXG4vLyBjb25uZWN0aW9uIGlzIGNsb3NlZCB3aGVuIHRoZSBsYXN0IHN1Y2ggc2NoZWR1bGVyIHN0b3BzLlxubGV0IHNoYXJlZExvY2s6IExvY2tSZWRpcyB8IG51bGwgfCB1bmRlZmluZWQ7XG5sZXQgc2hhcmVkTG9ja1VzZXJzID0gMDtcblxuLyoqIFRha2UgYSByZWZlcmVuY2Ugb24gdGhlIHNoYXJlZCBlbnYgbG9jayBjbGllbnQgKGBudWxsYCB3aGVuIFJlZGlzIGlzbid0IGNvbmZpZ3VyZWQpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFjcXVpcmVTaGFyZWRFbnZMb2NrKCk6IExvY2tSZWRpcyB8IG51bGwge1xuICBpZiAoc2hhcmVkTG9jayA9PT0gdW5kZWZpbmVkKSBzaGFyZWRMb2NrID0gY3JlYXRlRW52UmVkaXNMb2NrKCk7XG4gIHNoYXJlZExvY2tVc2VycysrO1xuICByZXR1cm4gc2hhcmVkTG9jaztcbn1cblxuLyoqIERyb3AgYSByZWZlcmVuY2UgdGFrZW4gYnkge0BsaW5rIGFjcXVpcmVTaGFyZWRFbnZMb2NrfTsgdGhlIGxhc3Qgb25lIGNsb3NlcyB0aGUgY2xpZW50LiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlbGVhc2VTaGFyZWRFbnZMb2NrKCk6IFByb21pc2U8dm9pZD4ge1xuICBpZiAoc2hhcmVkTG9ja1VzZXJzID09PSAwKSByZXR1cm47XG4gIHNoYXJlZExvY2tVc2Vycy0tO1xuICBpZiAoc2hhcmVkTG9ja1VzZXJzID4gMCkgcmV0dXJuO1xuICBjb25zdCBjbGllbnQgPSBzaGFyZWRMb2NrO1xuICBzaGFyZWRMb2NrID0gdW5kZWZpbmVkO1xuICBhd2FpdCBjbG9zZUxlYWRlckxvY2soY2xpZW50KTtcbn1cbiJdfQ==
|
|
212
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGVhZGVyLWxvY2suanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VydmljZXMvbGVhZGVyLWxvY2sudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0QyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBQ3BDLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxjQUFjLEVBQXdCLE1BQU0sZ0JBQWdCLENBQUM7QUFDNUYsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFFcEQsTUFBTSxVQUFVLEdBQUcsWUFBWSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0FBb0IvQzs7OztHQUlHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxlQUFlLENBQUMsS0FBbUM7SUFDdkUsSUFBSSxDQUFDLEtBQUs7UUFBRSxPQUFPO0lBQ25CLElBQUksQ0FBQztRQUNILElBQUksT0FBTyxLQUFLLENBQUMsSUFBSSxLQUFLLFVBQVUsRUFBRSxDQUFDO1lBQUMsTUFBTSxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7WUFBQyxPQUFPO1FBQUMsQ0FBQztJQUN2RSxDQUFDO0lBQUMsTUFBTSxDQUFDO1FBQ1AsNkJBQTZCO0lBQy9CLENBQUM7SUFDRCxJQUFJLENBQUM7UUFBQyxLQUFLLENBQUMsVUFBVSxFQUFFLEVBQUUsQ0FBQztJQUFDLENBQUM7SUFBQyxNQUFNLENBQUMsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0FBQzNELENBQUM7QUFFRDtpRUFDaUU7QUFDakUsTUFBTSxnQkFBZ0IsR0FDcEIsbUdBQW1HLENBQUM7QUFFdEcsOERBQThEO0FBQzlELE1BQU0sZUFBZSxHQUNuQixnSEFBZ0gsQ0FBQztBQUVuSCxxRkFBcUY7QUFDckYs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QUFlLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDaEMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgeyByYW5kb21VVUlEIH0gZnJvbSAnY3J5cHRvJztcbmltcG9ydCB7IGNyZWF0ZUVudlJlZGlzQ2xpZW50LCB3aGVuUmVkaXNSZWFkeSwgdHlwZSBSZWFkeUF3YXJlUmVkaXMgfSBmcm9tICcuL2Vudi1yZWRpcy5qcyc7XG5pbXBvcnQgeyBjcmVhdGVMb2dnZXIgfSBmcm9tICcuLi91dGlscy9sb2dnZXIuanMnO1xuaW1wb3J0IHsgZW1pdENvdW50ZXIgfSBmcm9tICcuLi91dGlscy9tZXRyaWMtZW1pdHRlci5qcyc7XG5pbXBvcnQgeyBlcnJvck1lc3NhZ2UgfSBmcm9tICcuLi91dGlscy9yZXNwb25zZS5qcyc7XG5cbmNvbnN0IGxvY2tMb2dnZXIgPSBjcmVhdGVMb2dnZXIoJ2xlYWRlci1sb2NrJyk7XG5cbi8qKlxuICogTWluaW1hbCBSZWRpcyBjbGllbnQgc3VyZmFjZSBuZWVkZWQgZm9yIGEgbGVhZGVyIGxvY2sgKGEgc3Vic2V0IG9mIGlvcmVkaXMpLlxuICogYHNldGAgaXMgdmFyaWFkaWMgc28gY2FsbGVycyBjYW4gcGFzcyBgJ1BYJywgdHRsLCAnTlgnYC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBMb2NrUmVkaXMgZXh0ZW5kcyBSZWFkeUF3YXJlUmVkaXMge1xuICBzZXQoa2V5OiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcsIC4uLmFyZ3M6IHVua25vd25bXSk6IFByb21pc2U8dW5rbm93bj47XG4gIGdldChrZXk6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nIHwgbnVsbD47XG4gIGRlbCguLi5rZXlzOiBzdHJpbmdbXSk6IFByb21pc2U8bnVtYmVyPjtcbiAgLyoqIE9wdGlvbmFsIEx1YSBldmFsIChpb3JlZGlzIGhhcyBpdCkuIFdoZW4gcHJlc2VudCwgcmVsZWFzZSB1c2VzIGFuIGF0b21pY1xuICAgKiAgY29tcGFyZS1hbmQtZGVsZXRlIHNvIGEgbGFwc2VkIGhvbGRlciBjYW4ndCBmcmVlIGEgc3VjY2Vzc29yJ3MgbG9jay4gKi9cbiAgZXZhbD8oc2NyaXB0OiBzdHJpbmcsIG51bUtleXM6IG51bWJlciwgLi4uYXJnczogdW5rbm93bltdKTogUHJvbWlzZTx1bmtub3duPjtcbiAgLyoqIEdyYWNlZnVsIGNsb3NlIChpb3JlZGlzIGBxdWl0YCkg4oCUIGNhbGxlZCBvbiBzaHV0ZG93biBzbyB0aGUgY29ubmVjdGlvblxuICAgKiAgZG9lc24ndCBrZWVwIHRoZSBldmVudCBsb29wIGFsaXZlLiAqL1xuICBxdWl0PygpOiBQcm9taXNlPHVua25vd24+O1xuICAvKiogSW1tZWRpYXRlIGNsb3NlIChpb3JlZGlzIGBkaXNjb25uZWN0YCkg4oCUIHRoZSBmYWxsYmFjayBpZiBgcXVpdGAgZmFpbHMuICovXG4gIGRpc2Nvbm5lY3Q/KCk6IHZvaWQ7XG59XG5cbi8qKlxuICogQmVzdC1lZmZvcnQgY2xvc2Ugb2YgYSBsZWFkZXItbG9jayBSZWRpcyBjbGllbnQgb24gc2h1dGRvd24uIFByZWZlcnMgZ3JhY2VmdWxcbiAqIGBxdWl0YDsgZmFsbHMgYmFjayB0byBgZGlzY29ubmVjdGAuIE5vLW9wIGZvciBhIG51bGwgY2xpZW50IC8gb25lIHdpdGhvdXRcbiAqIGVpdGhlciBtZXRob2QuIE5ldmVyIHRocm93cy5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNsb3NlTGVhZGVyTG9jayhyZWRpczogTG9ja1JlZGlzIHwgbnVsbCB8IHVuZGVmaW5lZCk6IFByb21pc2U8dm9pZD4ge1xuICBpZiAoIXJlZGlzKSByZXR1cm47XG4gIHRyeSB7XG4gICAgaWYgKHR5cGVvZiByZWRpcy5xdWl0ID09PSAnZnVuY3Rpb24nKSB7IGF3YWl0IHJlZGlzLnF1aXQoKTsgcmV0dXJuOyB9XG4gIH0gY2F0Y2gge1xuICAgIC8vIGZhbGwgdGhyb3VnaCB0byBkaXNjb25uZWN0XG4gIH1cbiAgdHJ5IHsgcmVkaXMuZGlzY29ubmVjdD8uKCk7IH0gY2F0Y2ggeyAvKiBiZXN0LWVmZm9ydCAqLyB9XG59XG5cbi8qKiBBdG9taWMgXCJkZWxldGUgb25seSBpZiBJIHN0aWxsIG93biBpdFwiIOKAlCBjbG9zZXMgdGhlIGdldC10aGVuLWRlbCByYWNlIHdoZXJlXG4gKiAgdGhlIGxvY2sgZXhwaXJlcyBhbmQgaXMgcmUtYWNxdWlyZWQgYmV0d2VlbiB0aGUgdHdvIGNhbGxzLiAqL1xuY29uc3QgUkVMRUFTRV9JRl9PV05FUiA9XG4gICdpZiByZWRpcy5jYWxsKFwiZ2V0XCIsIEtFWVNbMV0pID09IEFSR1ZbMV0gdGhlbiByZXR1cm4gcmVkaXMuY2FsbChcImRlbFwiLCBLRVlTWzFdKSBlbHNlIHJldHVybiAwIGVuZCc7XG5cbi8qKiBBdG9taWMgXCJleHRlbmQgb25seSBpZiBJIHN0aWxsIG93biBpdFwiIOKAlCB0aGUgaGVhcnRiZWF0LiAqL1xuY29uc3QgRVhURU5EX0lGX09XTkVSID1cbiAgJ2lmIHJlZGlzLmNhbGwoXCJnZXRcIiwgS0VZU1sxXSkgPT0gQVJHVlsxXSB0aGVuIHJldHVybiByZWRpcy5jYWxsKFwicGV4cGlyZVwiLCBLRVlTWzFdLCBBUkdWWzJdKSBlbHNlIHJldHVybiAwIGVuZCc7XG5cbi8qKiBMb25nZXN0IGEgcnVuIHdhaXRzIGZvciBhIG5vdC15ZXQtY29ubmVjdGVkIGNsaWVudCBiZWZvcmUgc2tpcHBpbmcgdGhlIHdpbmRvdy4gKi9cbmNvbnN0IExPQ0tfUkVBRFlfVElNRU9VVF9NUyA9IDEwXzAwMDtcblxuLyoqXG4gKiBEZWZhdWx0IGxvY2sgbGlmZXRpbWUg4oCUIGEgQ1JBU0gtUkVDT1ZFUlkgd2luZG93LCBub3QgYSBydW4tZHVyYXRpb24gY292ZXIuXG4gKlxuICogVGhlIGhvbGRlciBoZWFydGJlYXRzIChjb21wYXJlLWFuZC1QRVhQSVJFIGV2ZXJ5IGB0dGxNcyAvIDNgKSBmb3IgYXMgbG9uZyBhc1xuICogYGZuYCBydW5zLCBzbyBhIHNpeC1ob3VyIGpvYiBob2xkcyBhIHR3by1taW51dGUgbG9jayBwZXJmZWN0bHkgd2VsbC4gV2hhdCB0aGVcbiAqIFRUTCBhY3R1YWxseSBkZWNpZGVzIGlzIGhvdyBsb25nIGEgam9iIHN0YXlzIEJMT0NLRUQgYWZ0ZXIgdGhlIHBvZCBob2xkaW5nIGl0XG4gKiBkaWVzIHdpdGhvdXQgcmVsZWFzaW5nIOKAlCB0aGUga2V5IHNpbXBseSBzaXRzIHRoZXJlIHVudGlsIGl0IGV4cGlyZXMuIFNpemluZyB0aGVcbiAqIFRUTCB0byB0aGUgZXhwZWN0ZWQgcnVuIHRpbWUgKHdoaWNoIGlzIHdoYXQgc2V2ZXJhbCBjYWxsZXJzIHVzZWQgdG8gZG8pIHR1cm5lZCBhXG4gKiBjcmFzaGVkIHBvZCBpbnRvIGhvdXJzIG9mIHNpbGVudCBpbmFjdGl2aXR5LlxuICpcbiAqIFR3byBtaW51dGVzIGxlYXZlcyB0aHJlZSBtaXNzZWQgaGVhcnRiZWF0cyBvZiBzbGFjaywgc28gYW4gZXZlbnQtbG9vcCBzdGFsbCBvciBhXG4gKiBicmllZiBSZWRpcyBibGlwIGRvZXMgbm90IGhhbmQgdGhlIGxvY2sgdG8gYSBzZWNvbmQgcG9kIG1pZC1ydW4sIHdoaWxlIHJlY292ZXJ5XG4gKiBhZnRlciBhIHJlYWwgY3Jhc2ggaXMgYm91bmRlZCBhdCB0d28gbWludXRlcy5cbiAqL1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfTEVBREVSX0xPQ0tfVFRMX01TID0gMTIwXzAwMDtcblxuLyoqXG4gKiBUaGUgb25lIHdheSB0byBidWlsZCBhIGxlYWRlci1sb2NrIGtleTogYDxzZXJ2aWNlPjo8am9iPjpsZWFkZXJgLlxuICpcbiAqIEZvdXIgY29udmVudGlvbnMgaGFkIGdyb3duIHVwIOKAlCBgcGx1Z2luOnZ1bG4tcmVzY2FuOmxlYWRlcmAsXG4gKiBgcGxhdGZvcm06bGVhZGVyOm9yZy1wdXJnZWAsIGEgYmFyZSBgZWNvc3lzdGVtLXN0YXRzOmxlYWRlcmAsIGFuZCBiaWxsaW5nJ3NcbiAqIHVubmFtZXNwYWNlZCBgc3Vic2NyaXB0aW9uLWxpZmVjeWNsZWAg4oCUIHdoaWNoIG1lYW50IG5vIHNpbmdsZSBnbG9iIGZvdW5kIGV2ZXJ5XG4gKiBsb2NrLiBgS0VZUyAnKjpsZWFkZXInYCBtaXNzZWQgYmlsbGluZydzIHRocmVlIGVudGlyZWx5LCBzbyBhbiBvcGVyYXRvciBhc2tpbmdcbiAqIFwid2hhdCBpcyBoZWxkIHJpZ2h0IG5vd1wiIGdvdCBhIHBhcnRpYWwgYW5zd2VyLiBUaGUgZW52IFJlZGlzIGNsaWVudCBzZXRzIG5vXG4gKiBga2V5UHJlZml4YCwgc28gdGhlc2Ugc2hhcmUgb25lIGZsYXQga2V5c3BhY2Ugd2l0aCBjYWNoZSwgQnVsbE1RIGFuZCBzcG9vbCBrZXlzO1xuICogdGhlIGA8c2VydmljZT46YCBzZWdtZW50IGlzIHdoYXQga2VlcHMgdGhlbSBhcGFydC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxlYWRlckxvY2tLZXkoc2VydmljZTogc3RyaW5nLCBqb2I6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBgJHtzZXJ2aWNlfToke2pvYn06bGVhZGVyYDtcbn1cblxuLyoqIFdoeSBhIGxlYWRlci1sb2NrZWQgcnVuIHdhcyB0b2xkIHRvIHN0b3AuICovXG5leHBvcnQgdHlwZSBMZWFkZXJMb2NrQWJvcnRSZWFzb24gPSAnbG9jay1sb3N0JyB8ICdzaHV0ZG93bic7XG5cbi8qKiBXaGF0IGEgbGVhZGVyLWxvY2tlZCBydW4gaXMgdG9sZCB3aGlsZSBpdCBydW5zLiAqL1xuZXhwb3J0IGludGVyZmFjZSBMZWFkZXJMb2NrUnVuIHtcbiAgLyoqXG4gICAqIEFib3J0ZWQgd2hlbiB0aGUgbG9jayBpcyBMT1NUIG1pZC1ydW4gKGEgaGVhcnRiZWF0IGZvdW5kIGFub3RoZXIgaG9sZGVyLCBvclxuICAgKiB0aGUga2V5IGdvbmUpLCBvciB3aGVuIHRoZSBjYWxsZXIgaXMgU0hVVFRJTkcgRE9XTi4gTG9uZyBydW5zIG11c3QgY2hlY2sgaXRcbiAgICogYmV0d2VlbiB1bml0cyBvZiB3b3JrIGFuZCByZXR1cm46IHBhc3QgYSBsb2NrIGxvc3MgYW5vdGhlciBwb2QgbWF5IGJlIGRvaW5nXG4gICAqIHRoZSBzYW1lIHdvcmssIGFuZCBvbiBzaHV0ZG93biByZXR1cm5pbmcgcHJvbXB0bHkgaXMgd2hhdCByZWxlYXNlcyB0aGUgbG9ja1xuICAgKiBpbnN0ZWFkIG9mIGxlYXZpbmcgaXQgdG8gZXhwaXJlLlxuICAgKlxuICAgKiBgc2lnbmFsLnJlYXNvbmAgaXMgYSB7QGxpbmsgTGVhZGVyTG9ja0Fib3J0UmVhc29ufS5cbiAgICovXG4gIHNpZ25hbDogQWJvcnRTaWduYWw7XG59XG5cbi8qKiBDYWxsZXItc3VwcGxpZWQgY29udHJvbHMgZm9yIHtAbGluayB3aXRoTGVhZGVyTG9ja30uICovXG5leHBvcnQgaW50ZXJmYWNlIExlYWRlckxvY2tPcHRpb25zIHtcbiAgLyoqXG4gICAqIEFib3J0ZWQgYnkgdGhlIGNhbGxlciB0byBhc2sgYSBydW5uaW5nIGpvYiB0byBzdG9wIOKAlCBhIHNjaGVkdWxlcidzIGBzdG9wKClgXG4gICAqIG9uIHNodXRkb3duLiBNZXJnZWQgaW50byB7QGxpbmsgTGVhZGVyTG9ja1J1bi5zaWduYWx9LCBzbyBhIHNpZ25hbC1hd2FyZSBgZm5gXG4gICAqIHJldHVybnMgYW5kIHRoZSBsb2NrIGlzIHJlbGVhc2VkIGluIHRoZSBgZmluYWxseWAgcmF0aGVyIHRoYW4gbGluZ2VyaW5nIGZvclxuICAgKiB0aGUgcmVzdCBvZiB0aGUgVFRMLlxuICAgKi9cbiAgc2lnbmFsPzogQWJvcnRTaWduYWw7XG59XG5cbi8qKlxuICogUnVuIGBmbmAgb25seSBpZiB0aGlzIHByb2Nlc3Mgd2lucyBhIHNob3J0LWxpdmVkIGRpc3RyaWJ1dGVkIGxvY2sg4oCUIHRoZVxuICogYWNyb3NzLXBvZHMgXCJzaW5nbGUgcnVubmVyXCIgZ3VhcmQgZm9yIHBlcmlvZGljIGpvYnMgKGRpZ2VzdCBmbHVzaGVzLCBldGMuKS5cbiAqXG4gKiBVc2VzIGBTRVQga2V5IHRva2VuIE5YIFBYIHR0bGAsIHNvIGV4YWN0bHkgb25lIGhvbGRlciBydW5zIHBlciB3aW5kb3cgYW5kIHRoZVxuICogbG9jayBhdXRvLWV4cGlyZXMgaWYgdGhhdCBob2xkZXIgZGllcyBtaWQtcnVuIChubyBzdHVjayBsb2NrKS4gV2hpbGUgYGZuYFxuICogcnVucywgdGhlIGhvbGRlciBIRUFSVEJFQVRTIChjb21wYXJlLWFuZC1QRVhQSVJFIGV2ZXJ5IGB0dGxNcyAvIDNgKSwgc28gYSBydW5cbiAqIHRoYXQgb3V0bGFzdHMgYHR0bE1zYCBrZWVwcyB0aGUgbG9jayBpbnN0ZWFkIG9mIHNpbGVudGx5IGxldHRpbmcgYSBzZWNvbmQgcG9kXG4gKiBzdGFydCB0aGUgc2FtZSB3b3JrOyBhIGhlYXJ0YmVhdCB0aGF0IGZpbmRzIHRoZSBsb2NrIGdvbmUgYWJvcnRzXG4gKiBgcnVuLnNpZ25hbGAuIFRoZSBsb2NrIGlzIHJlbGVhc2VkIG9uIGNvbXBsZXRpb24sIGJ1dCBvbmx5IGlmIHdlIHN0aWxsIG93blxuICogaXQg4oCUIGEgc2xvd2VyIHByZWRlY2Vzc29yIG5ldmVyIGRlbGV0ZXMgYSBzdWNjZXNzb3IncyBsb2NrLlxuICpcbiAqIElmIFJlZGlzIGNhbid0IGJlIHJlYWNoZWQgdGhlIHJ1biBpcyBza2lwcGVkIChyZXR1cm5zIGZhbHNlKSByYXRoZXIgdGhhblxuICogcmVqZWN0aW5nIOKAlCBjYWxsZXJzIGFyZSB0aW1lcnMsIGFuZCBhIFJlZGlzIGJsaXAgbXVzdCBub3QgY3Jhc2ggdGhlIHByb2Nlc3MuXG4gKlxuICogRVZFUlkgb3V0Y29tZSBpcyBjb3VudGVkLCBiZWNhdXNlIHRoZXkgbWVhbiB2ZXJ5IGRpZmZlcmVudCB0aGluZ3MgYW5kIHRoZVxuICogZGlmZmVyZW5jZSB1c2VkIHRvIGJlIHZpc2libGUgb25seSBpbiBhIGxvZyBsaW5lOlxuICogIC0gYGxlYWRlcl9sb2NrX2FjcXVpcmVkX3RvdGFsYCDigJQgdGhpcyBwb2QgcmFuIHRoZSB3aW5kb3cuIEEgam9iIHdob3NlIGNvdW50XG4gKiAgICBzdGF5cyBmbGF0IGlzIG5vdCBydW5uaW5nIEFOWVdIRVJFLCB3aGljaCBpcyB0aGUgY29uZGl0aW9uIHdvcnRoIGFsZXJ0aW5nIG9uLlxuICogIC0gYGxlYWRlcl9sb2NrX2NvbnRlbmRlZF90b3RhbGAg4oCUIGFub3RoZXIgcG9kIGhvbGRzIGl0LiBIZWFsdGh5IGFuZCBleHBlY3RlZFxuICogICAgd2l0aCByZXBsaWNhcyA+IDE7IGV4YWN0bHkgb25lIGFjcXVpcmUgcGVyIHdpbmRvdyBhY3Jvc3MgdGhlIGZsZWV0LlxuICogIC0gYGxlYWRlcl9sb2NrX3VuYXZhaWxhYmxlX3RvdGFsYCDigJQgUmVkaXMgdW5yZWFjaGFibGUsIHNvIE5PQk9EWSByYW4gdGhpc1xuICogICAgd2luZG93LiBBIFJlZGlzIGJsaXAgc2lsZW50bHkgc3RvcHBpbmcgZXZlcnkgc3dlZXAgZmxlZXQtd2lkZSB3YXMgcHJldmlvdXNseVxuICogICAgYSBXQVJOIGxvZyBhbmQgbm90aGluZyBlbHNlLlxuICpcbiAqIEByZXR1cm5zIHRydWUgaWYgd2UgaGVsZCB0aGUgbG9jayBhbmQgcmFuIGBmbmA7IGZhbHNlIGlmIGFub3RoZXIgaG9sZGVyIGRpZCBvclxuICogICB0aGUgbG9jayBjb3VsZG4ndCBiZSB0YWtlbi5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHdpdGhMZWFkZXJMb2NrKFxuICByZWRpczogTG9ja1JlZGlzLFxuICBrZXk6IHN0cmluZyxcbiAgdHRsTXM6IG51bWJlcixcbiAgZm46IChydW46IExlYWRlckxvY2tSdW4pID0+IFByb21pc2U8dm9pZD4sXG4gIG9wdHM6IExlYWRlckxvY2tPcHRpb25zID0ge30sXG4pOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgLy8gQXNrZWQgdG8gc3RvcCBiZWZvcmUgd2UgZXZlbiB0cmllZDogZG9uJ3QgdGFrZSBhIGxvY2sgd2UgYXJlIGFib3V0IHRvIGRyb3AuXG4gIGlmIChvcHRzLnNpZ25hbD8uYWJvcnRlZCkgcmV0dXJuIGZhbHNlO1xuXG4gIGNvbnN0IHRva2VuID0gcmFuZG9tVVVJRCgpO1xuICBsZXQgYWNxdWlyZWQ6IHVua25vd247XG4gIHRyeSB7XG4gICAgLy8gVGhlIGVudiBjbGllbnQgaGFzIG5vIG9mZmxpbmUgcXVldWU6IGEgU0VUIGJlZm9yZSB0aGUgZmlyc3QgY29ubmVjdGlvblxuICAgIC8vIGNvbXBsZXRlcyBpcyByZWplY3RlZCwgd2hpY2ggbWFkZSB0aGUgRklSU1QgdGljayBhZnRlciBldmVyeSBib290IGFcbiAgICAvLyBndWFyYW50ZWVkIHNraXAuIFdhaXQgKGJvdW5kZWQpIGZvciByZWFkaW5lc3MgZmlyc3QuXG4gICAgYXdhaXQgd2hlblJlZGlzUmVhZHkocmVkaXMsIE1hdGgubWluKExPQ0tfUkVBRFlfVElNRU9VVF9NUywgTWF0aC5tYXgoMSwgdHRsTXMpKSk7XG4gICAgYWNxdWlyZWQgPSBhd2FpdCByZWRpcy5zZXQoa2V5LCB0b2tlbiwgJ1BYJywgdHRsTXMsICdOWCcpO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICAvLyBSZWRpcyB1bnJlYWNoYWJsZSAoaW5jbHVkaW5nIGJlZm9yZSB0aGUgZmlyc3QgY29ubmVjdGlvbiBjb21wbGV0ZXMpOiBub1xuICAgIC8vIHBvZCBjYW4gcHJvdmUgaXQncyB0aGUgbGVhZGVyLCBzbyBub2JvZHkgcnVucyB0aGlzIHdpbmRvdy4gU2tpcHBpbmcgaXNcbiAgICAvLyB0aGUgc2FmZSBzaWRlIOKAlCBydW5uaW5nIGhlcmUgY291bGQgZHVwbGljYXRlIGRlc3RydWN0aXZlIHdvcmsgYWNyb3NzIHBvZHMuXG4gICAgbG9ja0xvZ2dlci53YXJuKCdMZWFkZXIgbG9jayB1bmF2YWlsYWJsZTsgc2tpcHBpbmcgdGhpcyBydW4nLCB7XG4gICAgICBrZXksIGVycm9yOiBlcnJvck1lc3NhZ2UoZXJyKSxcbiAgICB9KTtcbiAgICBlbWl0Q291bnRlcignbGVhZGVyX2xvY2tfdW5hdmFpbGFibGVfdG90YWwnLCB7IGtleSB9KTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgaWYgKGFjcXVpcmVkICE9PSAnT0snKSB7XG4gICAgZW1pdENvdW50ZXIoJ2xlYWRlcl9sb2NrX2NvbnRlbmRlZF90b3RhbCcsIHsga2V5IH0pO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBlbWl0Q291bnRlcignbGVhZGVyX2xvY2tfYWNxdWlyZWRfdG90YWwnLCB7IGtleSB9KTtcblxuICBjb25zdCBsb3N0ID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICAvLyBTaHV0ZG93biBpcyBtZXJnZWQgaW50byB0aGUgU0FNRSBzaWduYWwgYSBsb2NrIGxvc3MgdXNlczogZnJvbSBgZm5gJ3MgcG9pbnQgb2ZcbiAgLy8gdmlldyBib3RoIG1lYW4gXCJzdG9wIGJldHdlZW4gdW5pdHMgb2Ygd29yayBhbmQgcmV0dXJuXCIuIGBzaWduYWwucmVhc29uYCBzYXlzXG4gIC8vIHdoaWNoLiBSZWdpc3RlcmVkIHdpdGggYG9uY2VgIHNvIGEgbG9uZy1saXZlZCBjYWxsZXIgc2lnbmFsIGRvZXNuJ3QgcmV0YWluXG4gIC8vIHRoaXMgY29udHJvbGxlciBhZnRlciB0aGUgcnVuLlxuICBjb25zdCBvbkV4dGVybmFsQWJvcnQgPSAoKTogdm9pZCA9PiB7XG4gICAgaWYgKCFsb3N0LnNpZ25hbC5hYm9ydGVkKSBsb3N0LmFib3J0KCdzaHV0ZG93bicgc2F0aXNmaWVzIExlYWRlckxvY2tBYm9ydFJlYXNvbik7XG4gIH07XG4gIG9wdHMuc2lnbmFsPy5hZGRFdmVudExpc3RlbmVyKCdhYm9ydCcsIG9uRXh0ZXJuYWxBYm9ydCwgeyBvbmNlOiB0cnVlIH0pO1xuXG4gIGxldCBoZWFydGJlYXQ6IE5vZGVKUy5UaW1lb3V0IHwgdW5kZWZpbmVkO1xuICBpZiAodHlwZW9mIHJlZGlzLmV2YWwgPT09ICdmdW5jdGlvbicpIHtcbiAgICBjb25zdCBldmFsRm4gPSByZWRpcy5ldmFsLmJpbmQocmVkaXMpO1xuICAgIGhlYXJ0YmVhdCA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgIGV2YWxGbihFWFRFTkRfSUZfT1dORVIsIDEsIGtleSwgdG9rZW4sIHR0bE1zKS50aGVuKChleHRlbmRlZCkgPT4ge1xuICAgICAgICBpZiAoTnVtYmVyKGV4dGVuZGVkKSAhPT0gMSAmJiAhbG9zdC5zaWduYWwuYWJvcnRlZCkge1xuICAgICAgICAgIGxvY2tMb2dnZXIud2FybignTGVhZGVyIGxvY2sgbG9zdCBtaWQtcnVuIChhbm90aGVyIGhvbGRlciwgb3IgdGhlIGtleSBleHBpcmVkKScsIHsga2V5IH0pO1xuICAgICAgICAgIGVtaXRDb3VudGVyKCdsZWFkZXJfbG9ja19sb3N0X3RvdGFsJywgeyBrZXkgfSk7XG4gICAgICAgICAgbG9zdC5hYm9ydCgnbG9jay1sb3N0JyBzYXRpc2ZpZXMgTGVhZGVyTG9ja0Fib3J0UmVhc29uKTtcbiAgICAgICAgfVxuICAgICAgfSkuY2F0Y2goKGVycikgPT4ge1xuICAgICAgICAvLyBBIGJsaXA6IHRoZSBuZXh0IGJlYXQgcmV0cmllczsgdGhlIFRUTCBzdGlsbCBjb3ZlcnMgdGhpcyBpbnRlcnZhbC5cbiAgICAgICAgbG9ja0xvZ2dlci5kZWJ1ZygnTGVhZGVyIGxvY2sgaGVhcnRiZWF0IGZhaWxlZCcsIHsga2V5LCBlcnJvcjogZXJyb3JNZXNzYWdlKGVycikgfSk7XG4gICAgICB9KTtcbiAgICB9LCBNYXRoLm1heCgxLCBNYXRoLmZsb29yKHR0bE1zIC8gMykpKTtcbiAgICBoZWFydGJlYXQudW5yZWY/LigpO1xuICB9XG5cbiAgdHJ5IHtcbiAgICBhd2FpdCBmbih7IHNpZ25hbDogbG9zdC5zaWduYWwgfSk7XG4gIH0gZmluYWxseSB7XG4gICAgaWYgKGhlYXJ0YmVhdCkgY2xlYXJJbnRlcnZhbChoZWFydGJlYXQpO1xuICAgIG9wdHMuc2lnbmFsPy5yZW1vdmVFdmVudExpc3RlbmVyKCdhYm9ydCcsIG9uRXh0ZXJuYWxBYm9ydCk7XG4gICAgLy8gUmVsZWFzZSBvbmx5IGlmIHRoZSBsb2NrIGlzIHN0aWxsIG91cnMg4oCUIGlmIG91ciBydW4gb3ZlcnJhbiB0aGUgVFRMIGFuZFxuICAgIC8vIGFub3RoZXIgaG9sZGVyIHRvb2sgb3ZlciwgcmVsZWFzaW5nIGhlcmUgd291bGQgZnJlZSB0aGVpciBsb2NrIGVhcmx5LlxuICAgIC8vIFByZWZlciBhbiBhdG9taWMgQ0FTIChMdWEpOyBmYWxsIGJhY2sgdG8gZ2V0LXRoZW4tZGVsIGZvciBjbGllbnRzIHdpdGhvdXRcbiAgICAvLyBldmFsICh0aGUgc21hbGwgbm9uLWF0b21pYyB3aW5kb3cgaXMgVFRMLWJvdW5kZWQpLlxuICAgIHRyeSB7XG4gICAgICBpZiAodHlwZW9mIHJlZGlzLmV2YWwgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgYXdhaXQgcmVkaXMuZXZhbChSRUxFQVNFX0lGX09XTkVSLCAxLCBrZXksIHRva2VuKTtcbiAgICAgIH0gZWxzZSBpZiAoKGF3YWl0IHJlZGlzLmdldChrZXkpKSA9PT0gdG9rZW4pIHtcbiAgICAgICAgYXdhaXQgcmVkaXMuZGVsKGtleSk7XG4gICAgICB9XG4gICAgfSBjYXRjaCB7XG4gICAgICAvLyBCZXN0LWVmZm9ydDogdGhlIFRUTCBleHBpcmVzIHRoZSBsb2NrIHJlZ2FyZGxlc3MuXG4gICAgfVxuICB9XG4gIHJldHVybiB0cnVlO1xufVxuXG4vKipcbiAqIEEgYExvY2tSZWRpc2AgYmFja2VkIGJ5IHRoZSBzaGFyZWQgZW52IFJlZGlzIGNsaWVudCAoc2VlIGVudi1yZWRpcy50cykg4oCUIHRoZSBsZWFkZXItbG9jayBjb3VudGVycGFydCB0byBgY3JlYXRlRW52UmVkaXNBdWRpdFNwb29sYCAvXG4gKiBgY3JlYXRlRW52UmVkaXNUb2tlblJldm9jYXRpb25TdG9yZWAsIGZvciBhIHNlcnZpY2UgdGhhdCBoYXMgbm8gQnVsbE1RIGNsaWVudCB0b1xuICogYm9ycm93LiBSZXR1cm5zIGBudWxsYCB3aGVuIFJlZGlzIGlzbid0IGNvbmZpZ3VyZWQsIHNvIGEgY2FsbGVyIGNhbiBkZWdyYWRlIHRvXG4gKiBydW5uaW5nIG9uIGV2ZXJ5IHBvZCAodGhlIGF0b21pYyBndWFyZHMgaXQgd3JhcHMgbXVzdCBzdGlsbCBtYWtlIHRoYXQgc2FmZSkuXG4gKiBUaGUgY2xpZW50IGlzIGEgcmVhbCBpb3JlZGlzIGluc3RhbmNlOyBpb3JlZGlzIGV4cG9zZXMgYHNldGAvYGdldGAvYGRlbGAvYGV2YWxgLFxuICogc2F0aXNmeWluZyBgTG9ja1JlZGlzYCBpbmNsdWRpbmcgdGhlIGF0b21pYyBDQVMgcmVsZWFzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUVudlJlZGlzTG9jaygpOiBMb2NrUmVkaXMgfCBudWxsIHtcbiAgY29uc3QgaW5zdCA9IGNyZWF0ZUVudlJlZGlzQ2xpZW50PExvY2tSZWRpcz4oJ2xlYWRlci1sb2NrJyk7XG4gIGlmIChpbnN0KSBsb2NrTG9nZ2VyLmluZm8oJ1JlZGlzIGxlYWRlci1sb2NrIGNsaWVudCBpbml0aWFsaXplZCcpO1xuICByZXR1cm4gaW5zdDtcbn1cblxuLy8gT25lIGVudi1jb25maWd1cmVkIGxvY2sgY2xpZW50IHBlciBwcm9jZXNzLCBzaGFyZWQgYnkgZXZlcnkgc2NoZWR1bGVyIHRoYXRcbi8vIGFza3MgZm9yIGEgbG9jayB3aXRob3V0IHN1cHBseWluZyBpdHMgb3duIGNsaWVudC4gUmVmZXJlbmNlLWNvdW50ZWQgc28gdGhlXG4vLyBjb25uZWN0aW9uIGlzIGNsb3NlZCB3aGVuIHRoZSBsYXN0IHN1Y2ggc2NoZWR1bGVyIHN0b3BzLlxubGV0IHNoYXJlZExvY2s6IExvY2tSZWRpcyB8IG51bGwgfCB1bmRlZmluZWQ7XG5sZXQgc2hhcmVkTG9ja1VzZXJzID0gMDtcblxuLyoqIFRha2UgYSByZWZlcmVuY2Ugb24gdGhlIHNoYXJlZCBlbnYgbG9jayBjbGllbnQgKGBudWxsYCB3aGVuIFJlZGlzIGlzbid0IGNvbmZpZ3VyZWQpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFjcXVpcmVTaGFyZWRFbnZMb2NrKCk6IExvY2tSZWRpcyB8IG51bGwge1xuICBpZiAoc2hhcmVkTG9jayA9PT0gdW5kZWZpbmVkKSBzaGFyZWRMb2NrID0gY3JlYXRlRW52UmVkaXNMb2NrKCk7XG4gIHNoYXJlZExvY2tVc2VycysrO1xuICByZXR1cm4gc2hhcmVkTG9jaztcbn1cblxuLyoqIERyb3AgYSByZWZlcmVuY2UgdGFrZW4gYnkge0BsaW5rIGFjcXVpcmVTaGFyZWRFbnZMb2NrfTsgdGhlIGxhc3Qgb25lIGNsb3NlcyB0aGUgY2xpZW50LiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlbGVhc2VTaGFyZWRFbnZMb2NrKCk6IFByb21pc2U8dm9pZD4ge1xuICBpZiAoc2hhcmVkTG9ja1VzZXJzID09PSAwKSByZXR1cm47XG4gIHNoYXJlZExvY2tVc2Vycy0tO1xuICBpZiAoc2hhcmVkTG9ja1VzZXJzID4gMCkgcmV0dXJuO1xuICBjb25zdCBjbGllbnQgPSBzaGFyZWRMb2NrO1xuICBzaGFyZWRMb2NrID0gdW5kZWZpbmVkO1xuICBhd2FpdCBjbG9zZUxlYWRlckxvY2soY2xpZW50KTtcbn1cbiJdfQ==
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type LockRedis } from './leader-lock.js';
|
|
1
|
+
import { type LeaderLockRun, type LockRedis } from './leader-lock.js';
|
|
2
2
|
/**
|
|
3
3
|
* Optional cross-pod single-runner lock for a scheduler's cycle. Without
|
|
4
4
|
* `redis` the scheduler uses the process's shared env-configured lock client
|
|
@@ -16,8 +16,17 @@ export interface SchedulerOptions {
|
|
|
16
16
|
name: string;
|
|
17
17
|
/** Interval between cycles (ms). */
|
|
18
18
|
intervalMs: number;
|
|
19
|
-
/**
|
|
20
|
-
|
|
19
|
+
/**
|
|
20
|
+
* The work to run each cycle. Errors are caught + logged, never thrown.
|
|
21
|
+
*
|
|
22
|
+
* `run.signal` is aborted when a leader-locked cycle LOSES its lock mid-run, or
|
|
23
|
+
* when `stop()` is called. A job that iterates over units of work (orgs, repos,
|
|
24
|
+
* entities) must check it between units and return: past a lock loss another pod
|
|
25
|
+
* may be doing the same work, and on shutdown returning promptly is what
|
|
26
|
+
* releases the lock instead of leaving it to expire. Unlocked schedulers get a
|
|
27
|
+
* signal too — it fires on `stop()` only.
|
|
28
|
+
*/
|
|
29
|
+
run: (run: LeaderLockRun) => Promise<void>;
|
|
21
30
|
/** Run a cycle immediately when started. Default true. */
|
|
22
31
|
runOnStart?: boolean;
|
|
23
32
|
/** Delay before the first cycle (and before the interval begins), ms.
|
|
@@ -30,7 +39,14 @@ export interface SchedulerOptions {
|
|
|
30
39
|
export interface Scheduler {
|
|
31
40
|
/** Start the timer. Idempotent — repeated calls are no-ops. */
|
|
32
41
|
start(): void;
|
|
33
|
-
/**
|
|
42
|
+
/**
|
|
43
|
+
* Stop the timer (and cancel a pending startup delay). Safe before start.
|
|
44
|
+
*
|
|
45
|
+
* Also ABORTS an in-flight cycle's `run.signal` and defers closing the shared
|
|
46
|
+
* lock client until that cycle settles: a running cycle used to keep its lock
|
|
47
|
+
* key until the TTL lapsed, so a rolling deploy mid-run parked the job for the
|
|
48
|
+
* rest of the TTL. A signal-aware `run` returns and the lock is released.
|
|
49
|
+
*/
|
|
34
50
|
stop(): void;
|
|
35
51
|
}
|
|
36
52
|
/**
|