@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.
Files changed (41) hide show
  1. package/lib/errors/app-errors.d.ts +4 -2
  2. package/lib/errors/app-errors.js +6 -4
  3. package/lib/helpers/content-disposition.d.ts +14 -0
  4. package/lib/helpers/content-disposition.js +22 -0
  5. package/lib/helpers/index.d.ts +1 -0
  6. package/lib/helpers/index.js +2 -1
  7. package/lib/services/index.d.ts +1 -1
  8. package/lib/services/index.js +2 -2
  9. package/lib/services/leader-lock.d.ts +56 -3
  10. package/lib/services/leader-lock.js +60 -4
  11. package/lib/services/scheduler.d.ts +20 -4
  12. package/lib/services/scheduler.js +36 -6
  13. package/lib/services/service-keys.d.ts +0 -4
  14. package/lib/services/service-keys.js +1 -14
  15. package/lib/types/catalog-metadata.d.ts +0 -6
  16. package/lib/types/catalog-metadata.js +1 -1
  17. package/lib/types/ecosystem.d.ts +0 -1
  18. package/lib/types/ecosystem.js +1 -1
  19. package/lib/types/feature-flags.d.ts +1 -1
  20. package/lib/types/feature-flags.js +6 -1
  21. package/lib/types/index.d.ts +3 -2
  22. package/lib/types/index.js +3 -2
  23. package/lib/types/permissions.d.ts +16 -1
  24. package/lib/types/permissions.js +23 -2
  25. package/lib/types/plugin-scan.d.ts +26 -0
  26. package/lib/types/plugin-scan.js +1 -1
  27. package/lib/types/remote-audit-actions.d.ts +1 -1
  28. package/lib/types/remote-audit-actions.js +35 -1
  29. package/lib/types/reserved-tags.d.ts +28 -0
  30. package/lib/types/reserved-tags.js +37 -0
  31. package/lib/utils/index.d.ts +1 -1
  32. package/lib/utils/index.js +2 -2
  33. package/lib/utils/params.d.ts +33 -1
  34. package/lib/utils/params.js +54 -2
  35. package/lib/utils/secret-encryption.d.ts +0 -2
  36. package/lib/utils/secret-encryption.js +1 -5
  37. package/lib/validation/message-schemas.d.ts +0 -7
  38. package/lib/validation/message-schemas.js +2 -1
  39. package/lib/validation/pipeline-schemas.d.ts +6 -0
  40. package/lib/validation/pipeline-schemas.js +32 -2
  41. 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
  }
@@ -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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwLWVycm9ycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9lcnJvcnMvYXBwLWVycm9ycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBRXRDLE9BQU8sRUFBRSxTQUFTLEVBQUUscUJBQXFCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUUzRTs7O0dBR0c7QUFDSCxNQUFNLE9BQU8sUUFBUyxTQUFRLEtBQUs7SUFFZixVQUFVO0lBQ1YsSUFBSTtJQUdKLE9BQU87SUFMekIsWUFDa0IsVUFBa0IsRUFDbEIsSUFBZSxFQUMvQixPQUFlO0lBQ2YsZ0ZBQWdGO0lBQ2hFLE9BQWlDO1FBRWpELEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQzswQkFOQyxVQUFVO29CQUNWLElBQUk7dUJBR0osT0FBTztRQUd2QixJQUFJLENBQUMsSUFBSSxHQUFHLFVBQVUsQ0FBQztJQUN6QixDQUFDO0NBQ0Y7QUFFRCxnQ0FBZ0M7QUFDaEMsTUFBTSxPQUFPLGFBQWMsU0FBUSxRQUFRO0lBQ3pDLFlBQVksT0FBZTtRQUN6QixLQUFLLENBQUMscUJBQXFCLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxTQUFTLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDaEYsSUFBSSxDQUFDLElBQUksR0FBRyxlQUFlLENBQUM7SUFDOUIsQ0FBQztDQUNGO0FBRUQsc0NBQXNDO0FBQ3RDLE1BQU0sT0FBTyxjQUFlLFNBQVEsUUFBUTtJQUMxQyxZQUFZLE9BQWU7UUFDekIsS0FBSyxDQUFDLHFCQUFxQixDQUFDLFNBQVMsQ0FBQyx3QkFBd0IsQ0FBQyxFQUFFLFNBQVMsQ0FBQyx3QkFBd0IsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUM5RyxJQUFJLENBQUMsSUFBSSxHQUFHLGdCQUFnQixDQUFDO0lBQy9CLENBQUM7Q0FDRjtBQUVELHNDQUFzQztBQUN0QyxNQUFNLE9BQU8sZUFBZ0IsU0FBUSxRQUFRO0lBQzNDLFlBQVksT0FBZTtRQUN6QixLQUFLLENBQUMscUJBQXFCLENBQUMsU0FBUyxDQUFDLGdCQUFnQixDQUFDLEVBQUUsU0FBUyxDQUFDLGdCQUFnQixFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQzlGLElBQUksQ0FBQyxJQUFJLEdBQUcsaUJBQWlCLENBQUM7SUFDaEMsQ0FBQztDQUNGO0FBRUQ7b0VBQ29FO0FBQ3BFLE1BQU0sT0FBTyxhQUFjLFNBQVEsUUFBUTtJQUN6QyxZQUFZLE9BQWUsRUFBRSxJQUFJLEdBQWMsU0FBUyxDQUFDLFFBQVE7UUFDL0QsS0FBSyxDQUFDLHFCQUFxQixDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsRUFBRSxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDaEUsSUFBSSxDQUFDLElBQUksR0FBRyxlQUFlLENBQUM7SUFDOUIsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCB7IEVycm9yQ29kZSwgZ2V0U3RhdHVzRm9yRXJyb3JDb2RlIH0gZnJvbSAnLi4vdHlwZXMvZXJyb3ItY29kZXMuanMnO1xuXG4vKipcbiAqIEJhc2UgYXBwbGljYXRpb24gZXJyb3Igd2l0aCBIVFRQIHN0YXR1cyBjb2RlIGFuZCBlcnJvciBjb2RlLlxuICogRXh0ZW5kIHRoaXMgZm9yIGRvbWFpbi1zcGVjaWZpYyBlcnJvciB0eXBlcy5cbiAqL1xuZXhwb3J0IGNsYXNzIEFwcEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihcbiAgICBwdWJsaWMgcmVhZG9ubHkgc3RhdHVzQ29kZTogbnVtYmVyLFxuICAgIHB1YmxpYyByZWFkb25seSBjb2RlOiBFcnJvckNvZGUsXG4gICAgbWVzc2FnZTogc3RyaW5nLFxuICAgIC8qKiBTdHJ1Y3R1cmVkIGNvbnRleHQgc2VudCB3aXRoIHRoZSBlcnJvciByZXNwb25zZSAoZS5nLiB0aGUgZmFpbGluZyBnYXRlcykuICovXG4gICAgcHVibGljIHJlYWRvbmx5IGRldGFpbHM/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgKSB7XG4gICAgc3VwZXIobWVzc2FnZSk7XG4gICAgdGhpcy5uYW1lID0gJ0FwcEVycm9yJztcbiAgfVxufVxuXG4vKiogNDA0IOKAlCBSZXNvdXJjZSBub3QgZm91bmQuICovXG5leHBvcnQgY2xhc3MgTm90Rm91bmRFcnJvciBleHRlbmRzIEFwcEVycm9yIHtcbiAgY29uc3RydWN0b3IobWVzc2FnZTogc3RyaW5nKSB7XG4gICAgc3VwZXIoZ2V0U3RhdHVzRm9yRXJyb3JDb2RlKEVycm9yQ29kZS5OT1RfRk9VTkQpLCBFcnJvckNvZGUuTk9UX0ZPVU5ELCBtZXNzYWdlKTtcbiAgICB0aGlzLm5hbWUgPSAnTm90Rm91bmRFcnJvcic7XG4gIH1cbn1cblxuLyoqIDQwMyDigJQgSW5zdWZmaWNpZW50IHBlcm1pc3Npb25zLiAqL1xuZXhwb3J0IGNsYXNzIEZvcmJpZGRlbkVycm9yIGV4dGVuZHMgQXBwRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihtZXNzYWdlOiBzdHJpbmcpIHtcbiAgICBzdXBlcihnZXRTdGF0dXNGb3JFcnJvckNvZGUoRXJyb3JDb2RlLklOU1VGRklDSUVOVF9QRVJNSVNTSU9OUyksIEVycm9yQ29kZS5JTlNVRkZJQ0lFTlRfUEVSTUlTU0lPTlMsIG1lc3NhZ2UpO1xuICAgIHRoaXMubmFtZSA9ICdGb3JiaWRkZW5FcnJvcic7XG4gIH1cbn1cblxuLyoqIDQwMCDigJQgVmFsaWRhdGlvbiAvIGJhZCByZXF1ZXN0LiAqL1xuZXhwb3J0IGNsYXNzIFZhbGlkYXRpb25FcnJvciBleHRlbmRzIEFwcEVycm9yIHtcbiAgY29uc3RydWN0b3IobWVzc2FnZTogc3RyaW5nKSB7XG4gICAgc3VwZXIoZ2V0U3RhdHVzRm9yRXJyb3JDb2RlKEVycm9yQ29kZS5WQUxJREFUSU9OX0VSUk9SKSwgRXJyb3JDb2RlLlZBTElEQVRJT05fRVJST1IsIG1lc3NhZ2UpO1xuICAgIHRoaXMubmFtZSA9ICdWYWxpZGF0aW9uRXJyb3InO1xuICB9XG59XG5cbi8qKiA0MDkg4oCUIENvbmZsaWN0IC8gZHVwbGljYXRlLiBgY29kZWAgbmFycm93cyB0aGUgY29uZmxpY3QgZm9yIGNsaWVudHNcbiAqICAoZS5nLiBgUExVR0lOX1ZFUlNJT05fRlJPWkVOYCk7IGl0IG11c3QgYmUgYSA0MDktbWFwcGVkIGNvZGUuICovXG5leHBvcnQgY2xhc3MgQ29uZmxpY3RFcnJvciBleHRlbmRzIEFwcEVycm9yIHtcbiAgY29uc3RydWN0b3IobWVzc2FnZTogc3RyaW5nLCBjb2RlOiBFcnJvckNvZGUgPSBFcnJvckNvZGUuQ09ORkxJQ1QpIHtcbiAgICBzdXBlcihnZXRTdGF0dXNGb3JFcnJvckNvZGUoRXJyb3JDb2RlLkNPTkZMSUNUKSwgY29kZSwgbWVzc2FnZSk7XG4gICAgdGhpcy5uYW1lID0gJ0NvbmZsaWN0RXJyb3InO1xuICB9XG59XG4iXX0=
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==
@@ -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';
@@ -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
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaGVscGVycy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBRXRDLGNBQWMsbUJBQW1CLENBQUM7QUFDbEMsT0FBTyxFQUNMLDRCQUE0QixFQUM1QiwwQkFBMEIsRUFDMUIsZ0JBQWdCLEVBQ2hCLHVCQUF1QixFQUN2QixpQkFBaUIsR0FLbEIsTUFBTSxxQkFBcUIsQ0FBQztBQUM3QixPQUFPLEVBQ0wsY0FBYyxFQUNkLFlBQVksR0FLYixNQUFNLHNCQUFzQixDQUFDO0FBQzlCLGNBQWMsa0JBQWtCLENBQUM7QUFDakMsY0FBYyxvQkFBb0IsQ0FBQztBQUNuQyxPQUFPLEVBQ0wsZ0JBQWdCLEVBQ2hCLG1CQUFtQixFQUNuQixhQUFhLEVBQ2Isa0JBQWtCLEdBQ25CLE1BQU0seUJBQXlCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuZXhwb3J0ICogZnJvbSAnLi9jcnVkLWhlbHBlcnMuanMnO1xuZXhwb3J0IHtcbiAgcmVxdWlyZVZpc2liaWxpdHlXcml0ZUFjY2VzcyxcbiAgY2hlY2tWaXNpYmlsaXR5V3JpdGVBY2Nlc3MsXG4gIGNoZWNrV3JpdGVBY2Nlc3MsXG4gIHJlamVjdEZvcmJpZGRlbkJ1bGtSb3dzLFxuICByZXNvbHZlVmlzaWJpbGl0eSxcbiAgdHlwZSBWaXNpYmlsaXR5V3JpdGVUYXJnZXQsXG4gIHR5cGUgVmlzaWJpbGl0eVdyaXRlVmVyZGljdCxcbiAgdHlwZSBXcml0ZUFjY2VzcyxcbiAgdHlwZSBCdWxrV3JpdGVSb3csXG59IGZyb20gJy4vYWNjZXNzLWhlbHBlcnMuanMnO1xuZXhwb3J0IHtcbiAgbG9hZEFuZFJlc3RvcmUsXG4gIGxvYWRBbmRQdXJnZSxcbiAgdHlwZSBSZXN0b3JhYmxlU2VydmljZSxcbiAgdHlwZSBQdXJnZWFibGVTZXJ2aWNlLFxuICB0eXBlIFRvbWJzdG9uZUF1dGhvcml6ZXIsXG4gIHR5cGUgVG9tYnN0b25lUm91dGVPcHRpb25zLFxufSBmcm9tICcuL3Jlc3RvcmUtaGVscGVycy5qcyc7XG5leHBvcnQgKiBmcm9tICcuL3NzZS1oZWxwZXJzLmpzJztcbmV4cG9ydCAqIGZyb20gJy4vb3JnLWhpZXJhcmNoeS5qcyc7XG5leHBvcnQge1xuICBmZXRjaFBhcmVudE9yZ0lkLFxuICBmZXRjaE9yZ0Rlc2NlbmRhbnRzLFxuICBmZXRjaE9yZ05hbWVzLFxuICBmZXRjaE9yZ01lbWJlcnNoaXAsXG59IGZyb20gJy4vb3JnLWhpZXJhcmNoeS1odHRwLmpzJztcbiJdfQ==
9
+ export * from './content-disposition.js';
10
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaGVscGVycy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBRXRDLGNBQWMsbUJBQW1CLENBQUM7QUFDbEMsT0FBTyxFQUNMLDRCQUE0QixFQUM1QiwwQkFBMEIsRUFDMUIsZ0JBQWdCLEVBQ2hCLHVCQUF1QixFQUN2QixpQkFBaUIsR0FLbEIsTUFBTSxxQkFBcUIsQ0FBQztBQUM3QixPQUFPLEVBQ0wsY0FBYyxFQUNkLFlBQVksR0FLYixNQUFNLHNCQUFzQixDQUFDO0FBQzlCLGNBQWMsa0JBQWtCLENBQUM7QUFDakMsY0FBYyxvQkFBb0IsQ0FBQztBQUNuQyxPQUFPLEVBQ0wsZ0JBQWdCLEVBQ2hCLG1CQUFtQixFQUNuQixhQUFhLEVBQ2Isa0JBQWtCLEdBQ25CLE1BQU0seUJBQXlCLENBQUM7QUFDakMsY0FBYywwQkFBMEIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5leHBvcnQgKiBmcm9tICcuL2NydWQtaGVscGVycy5qcyc7XG5leHBvcnQge1xuICByZXF1aXJlVmlzaWJpbGl0eVdyaXRlQWNjZXNzLFxuICBjaGVja1Zpc2liaWxpdHlXcml0ZUFjY2VzcyxcbiAgY2hlY2tXcml0ZUFjY2VzcyxcbiAgcmVqZWN0Rm9yYmlkZGVuQnVsa1Jvd3MsXG4gIHJlc29sdmVWaXNpYmlsaXR5LFxuICB0eXBlIFZpc2liaWxpdHlXcml0ZVRhcmdldCxcbiAgdHlwZSBWaXNpYmlsaXR5V3JpdGVWZXJkaWN0LFxuICB0eXBlIFdyaXRlQWNjZXNzLFxuICB0eXBlIEJ1bGtXcml0ZVJvdyxcbn0gZnJvbSAnLi9hY2Nlc3MtaGVscGVycy5qcyc7XG5leHBvcnQge1xuICBsb2FkQW5kUmVzdG9yZSxcbiAgbG9hZEFuZFB1cmdlLFxuICB0eXBlIFJlc3RvcmFibGVTZXJ2aWNlLFxuICB0eXBlIFB1cmdlYWJsZVNlcnZpY2UsXG4gIHR5cGUgVG9tYnN0b25lQXV0aG9yaXplcixcbiAgdHlwZSBUb21ic3RvbmVSb3V0ZU9wdGlvbnMsXG59IGZyb20gJy4vcmVzdG9yZS1oZWxwZXJzLmpzJztcbmV4cG9ydCAqIGZyb20gJy4vc3NlLWhlbHBlcnMuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9vcmctaGllcmFyY2h5LmpzJztcbmV4cG9ydCB7XG4gIGZldGNoUGFyZW50T3JnSWQsXG4gIGZldGNoT3JnRGVzY2VuZGFudHMsXG4gIGZldGNoT3JnTmFtZXMsXG4gIGZldGNoT3JnTWVtYmVyc2hpcCxcbn0gZnJvbSAnLi9vcmctaGllcmFyY2h5LWh0dHAuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9jb250ZW50LWRpc3Bvc2l0aW9uLmpzJztcbiJdfQ==
@@ -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';
@@ -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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VydmljZXMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0QyxPQUFPLEVBQ0wsY0FBYyxFQUNkLHdCQUF3QixFQUN4QixtQkFBbUIsRUFDbkIsOEJBQThCLEdBQy9CLE1BQU0sdUJBQXVCLENBQUM7QUFDL0IsT0FBTyxFQUNMLGtCQUFrQixFQUtsQixZQUFZLEdBQ2IsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QixPQUFPLEVBQ0wsY0FBYyxFQUNkLGtCQUFrQixHQUVuQixNQUFNLGtCQUFrQixDQUFDO0FBQzFCLE9BQU8sRUFDTCxzQkFBc0IsRUFDdEIsa0JBQWtCLEdBRW5CLE1BQU0sMEJBQTBCLENBQUM7QUFDbEMsT0FBTyxFQUNMLGVBQWUsR0FHaEIsTUFBTSxnQkFBZ0IsQ0FBQztBQUN4QixPQUFPLEVBQ0wsc0JBQXNCLEdBR3ZCLE1BQU0sd0JBQXdCLENBQUM7QUFDaEMsT0FBTyxFQUNMLGtCQUFrQixFQUNsQixvQkFBb0IsRUFDcEIsMkJBQTJCLEVBRTNCLDhCQUE4QixHQUUvQixNQUFNLCtCQUErQixDQUFDO0FBQ3ZDLGNBQWMsa0NBQWtDLENBQUM7QUFDakQsT0FBTyxFQUdMLFlBQVksR0FDYixNQUFNLG9CQUFvQixDQUFDO0FBQzVCLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsZ0JBQWdCLEVBQ2hCLHFCQUFxQixFQUNyQixrQkFBa0IsR0FDbkIsTUFBTSxrQkFBa0IsQ0FBQztBQUMxQixPQUFPLEVBQ0wsb0JBQW9CLEVBQ3BCLG9CQUFvQixFQUNwQixlQUFlLEVBQ2YsU0FBUyxHQUNWLE1BQU0saUJBQWlCLENBQUM7QUFDekIsaUZBQWlGO0FBQ2pGLDhFQUE4RTtBQUM5RSxpRkFBaUY7QUFDakYsK0RBQStEO0FBQy9ELE9BQU8sRUFDTCxZQUFZLEVBQ1osZUFBZSxFQUNmLGdCQUFnQixHQUNqQixNQUFNLG1CQUFtQixDQUFDO0FBQzNCLCtFQUErRTtBQUMvRSx5REFBeUQ7QUFDekQsT0FBTyxFQUNMLG9CQUFvQixHQUNyQixNQUFNLHNCQUFzQixDQUFDO0FBQzlCLE9BQU8sRUFDTCw2QkFBNkIsR0FHOUIsTUFBTSx3QkFBd0IsQ0FBQztBQUNoQyxPQUFPLEVBQ0wscUJBQXFCLEdBQ3RCLE1BQU0scUJBQXFCLENBQUM7QUFJN0IsT0FBTyxFQUNMLGFBQWEsRUFDYixZQUFZLEdBQ2IsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QixPQUFPLEVBQ0wseUJBQXlCLEVBQ3pCLGtCQUFrQixFQUNsQixjQUFjLEVBQ2QsWUFBWSxFQUNaLHNCQUFzQixFQUN0QixjQUFjLEdBR2YsTUFBTSxZQUFZLENBQUM7QUFDcEIsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixzQkFBc0IsRUFDdEIsV0FBVyxHQUdaLE1BQU0sMEJBQTBCLENBQUM7QUFDbEMsT0FBTyxFQUNMLGFBQWEsRUFDYix3QkFBd0IsR0FFekIsTUFBTSxrQkFBa0IsQ0FBQztBQUMxQixPQUFPLEVBQ0wsc0JBQXNCLEVBQ3RCLHVCQUF1QixFQUN2QixpQkFBaUIsRUFDakIsb0JBQW9CLEVBQ3BCLG9CQUFvQixFQUNwQixVQUFVLEVBQ1YsZ0JBQWdCLEdBRWpCLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEIsT0FBTyxFQUNMLCtCQUErQixFQUMvQixrQ0FBa0MsRUFDbEMsc0JBQXNCLEVBQ3RCLHdCQUF3QixFQUN4QiwyQkFBMkIsR0FDNUIsTUFBTSx1QkFBdUIsQ0FBQztBQUMvQixPQUFPLEVBQ0wsMEJBQTBCLEVBQzFCLHVCQUF1QixFQUN2QixnQkFBZ0IsR0FJakIsTUFBTSx1QkFBdUIsQ0FBQztBQUMvQixPQUFPLEVBQ0wsbUJBQW1CLEdBQ3BCLE1BQU0sbUJBQW1CLENBQUM7QUFDM0IsT0FBTyxFQUNMLG9CQUFvQixFQUNwQixrQkFBa0IsRUFDbEIscUJBQXFCLEdBTXRCLE1BQU0sNEJBQTRCLENBQUM7QUFDcEMsT0FBTyxFQUNMLDJCQUEyQixFQUMzQixxQkFBcUIsR0FFdEIsTUFBTSw4QkFBOEIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5leHBvcnQge1xuICBleGNoYW5nZUFwaUtleSxcbiAgcmVzZXRBcGlLZXlFeGNoYW5nZUNhY2hlLFxuICBBcGlLZXlSZWplY3RlZEVycm9yLFxuICBBcGlLZXlFeGNoYW5nZVVuYXZhaWxhYmxlRXJyb3IsXG59IGZyb20gJy4vYXBpLWtleS1leGNoYW5nZS5qcyc7XG5leHBvcnQge1xuICBjcmVhdGVDYWNoZVNlcnZpY2UsXG4gIHR5cGUgUmVkaXNDYWNoZUNsaWVudCxcbiAgdHlwZSBDYWNoZUludmFsaWRhdGlvbk1lc3NhZ2UsXG4gIHR5cGUgQ2FjaGVJbnZhbGlkYXRpb25CdXMsXG4gIHR5cGUgUmVkaXNJbnZhbGlkYXRpb25DbGllbnQsXG4gIENhY2hlU2VydmljZSxcbn0gZnJvbSAnLi9jYWNoZS1zZXJ2aWNlLmpzJztcbmV4cG9ydCB7XG4gIHdpdGhMZWFkZXJMb2NrLFxuICBjcmVhdGVFbnZSZWRpc0xvY2ssXG4gIHR5cGUgTG9ja1JlZGlzLFxufSBmcm9tICcuL2xlYWRlci1sb2NrLmpzJztcbmV4cG9ydCB7XG4gIHNlbmRTeXN0ZW1Ob3RpZmljYXRpb24sXG4gIFNZU1RFTV9OT1RJRllfUEFUSCxcbiAgdHlwZSBTeXN0ZW1Ob3RpZmljYXRpb24sXG59IGZyb20gJy4vc3lzdGVtLW5vdGlmaWNhdGlvbi5qcyc7XG5leHBvcnQge1xuICBjcmVhdGVTY2hlZHVsZXIsXG4gIHR5cGUgU2NoZWR1bGVyT3B0aW9ucyxcbiAgdHlwZSBTY2hlZHVsZXIsXG59IGZyb20gJy4vc2NoZWR1bGVyLmpzJztcbmV4cG9ydCB7XG4gIGNyZWF0ZUNvbXBsaWFuY2VDbGllbnQsXG4gIHR5cGUgQ29tcGxpYW5jZUNoZWNrUmVzdWx0LFxuICB0eXBlIENvbXBsaWFuY2VWaW9sYXRpb24sXG59IGZyb20gJy4vY29tcGxpYW5jZS1jbGllbnQuanMnO1xuZXhwb3J0IHtcbiAgcGx1Z2luUnVuc093bkltYWdlLFxuICBwbHVnaW5Db21wbGlhbmNlVGFncyxcbiAgZGVyaXZlUGx1Z2luSW1hZ2VDb21wbGlhbmNlLFxuICB0eXBlIFBsdWdpbkNvbXBsaWFuY2VBdHRyaWJ1dGVzLFxuICBQTFVHSU5fSU1BR0VfQ09NUExJQU5DRV9GSUVMRFMsXG4gIHR5cGUgUGx1Z2luSW1hZ2VSb3csXG59IGZyb20gJy4uL3V0aWxzL3BsdWdpbi1jb21wbGlhbmNlLmpzJztcbmV4cG9ydCAqIGZyb20gJy4vY29tcGxpYW5jZS1ldmVudC1zdWJzY3JpYmVyLmpzJztcbmV4cG9ydCB7XG4gIHR5cGUgRW50aXR5RXZlbnQsXG4gIHR5cGUgRW50aXR5RXZlbnRTdWJzY3JpYmVyLFxuICBlbnRpdHlFdmVudHMsXG59IGZyb20gJy4vZW50aXR5LWV2ZW50cy5qcyc7XG5leHBvcnQge1xuICBkZXN0cm95U2hhcmVkSHR0cEFnZW50cyxcbiAgY3JlYXRlU2FmZUNsaWVudCxcbiAgUmVzcG9uc2VUb29MYXJnZUVycm9yLFxuICBJbnRlcm5hbEh0dHBDbGllbnQsXG59IGZyb20gJy4vaHR0cC1jbGllbnQuanMnO1xuZXhwb3J0IHtcbiAgc2V0UGxhdGZvcm1Kd2tzQ2FjaGUsXG4gIEp3a3NVbmF2YWlsYWJsZUVycm9yLFxuICBVbmtub3duS2lkRXJyb3IsXG4gIEp3a3NDYWNoZSxcbn0gZnJvbSAnLi9qd2tzLWNhY2hlLmpzJztcbi8vIFNlcnZpY2Uta2V5IGludGVybmFscyBzdGF5IGludGVybmFsLiBUaGUgcGFja2FnZSBzdXJmYWNlIGlzIHRoZSB2ZXJpZnkvaW5zcGVjdFxuLy8gc2lkZSB0aGF0IHBsYXRmb3JtJ3MgSldUIG9wdGlvbnMgYW5kIHRoZSBhdXRoIG1pZGRsZXdhcmUgbmVlZDsga2V5IE1BVEVSSUFMXG4vLyBoYW5kbGluZyAoYHNpZ25TZXJ2aWNlSnd0YCwgdGhlIGJ1bmRsZSwgdGhlIHRlc3QgcmVzZXQgaG9vaykgaXMgcmVhY2hhYmxlIG9ubHlcbi8vIGJ5IGRlZXAgaW1wb3J0IGZyb20gaW5zaWRlIGFwaS1jb3JlIGFuZCBpdHMgdGVzdGluZyBoZWxwZXJzLlxuZXhwb3J0IHtcbiAgaXNTZXJ2aWNlS2lkLFxuICBzZXJ2aWNlSWRlbnRpdHksXG4gIHZlcmlmeVNlcnZpY2VKd3QsXG59IGZyb20gJy4vc2VydmljZS1rZXlzLmpzJztcbi8vIFRoZSBicmVha2VyIGlzIHdpcmVkIGJ5IHRoZSBzaGFyZWQgSFRUUCBjbGllbnQ7IHNlcnZpY2VzIGNvbnN1bWUgaXRzIEVGRkVDVCxcbi8vIG5vdCB0aGUgY2xhc3MuIE9ubHkgdGhlIG9wZXJhdGlvbmFsIHN1cmZhY2UgaXMgcHVibGljLlxuZXhwb3J0IHtcbiAgcmVzZXRDaXJjdWl0QnJlYWtlcnMsXG59IGZyb20gJy4vY2lyY3VpdC1icmVha2VyLmpzJztcbmV4cG9ydCB7XG4gIGNyZWF0ZUVudlJlZGlzRHVyYWJsZUV2ZW50QnVzLFxuICB0eXBlIEV2ZW50U3Vic2NyaXB0aW9uLFxuICB0eXBlIER1cmFibGVFdmVudEJ1cyxcbn0gZnJvbSAnLi9kdXJhYmxlLWV2ZW50LWJ1cy5qcyc7XG5leHBvcnQge1xuICBnZXRFcnJvclJldHJ5RGVjaXNpb24sXG59IGZyb20gJy4vcmV0cnktc3RyYXRlZ3kuanMnO1xuZXhwb3J0IHR5cGUge1xuICBSZXRyeUNvbmZpZyxcbn0gZnJvbSAnLi9yZXRyeS1zdHJhdGVneS5qcyc7XG5leHBvcnQge1xuICBuZXh0QmFja29mZk1zLFxuICByZXRyeUZvcmV2ZXIsXG59IGZyb20gJy4vcmV0cnktZm9yZXZlci5qcyc7XG5leHBvcnQge1xuICBnZXRRdW90YVNlcnZpY2VBdXRoSGVhZGVyLFxuICBjcmVhdGVRdW90YVNlcnZpY2UsXG4gIGluY3JlbWVudFF1b3RhLFxuICByZXNlcnZlUXVvdGEsXG4gIHNlbmRRdW90YVJlc2VydmVEZW5pZWQsXG4gIGRlY3JlbWVudFF1b3RhLFxuICB0eXBlIFF1b3RhUmVzZXJ2ZVJlc3VsdCxcbiAgdHlwZSBRdW90YVNlcnZpY2UsXG59IGZyb20gJy4vcXVvdGEuanMnO1xuZXhwb3J0IHtcbiAgY3JlYXRlUmVtb3RlQXVkaXRDbGllbnQsXG4gIHdpcmVBdXRoekRlbmlhbEF1ZGl0b3IsXG4gIHJlY29yZEF1ZGl0LFxuICB0eXBlIFJlbW90ZUF1ZGl0RXZlbnQsXG4gIHR5cGUgUmVtb3RlQXVkaXRDbGllbnQsXG59IGZyb20gJy4vcmVtb3RlLWF1ZGl0LWNsaWVudC5qcyc7XG5leHBvcnQge1xuICBhdWRpdFNwb29sS2V5LFxuICBjcmVhdGVFbnZSZWRpc0F1ZGl0U3Bvb2wsXG4gIHR5cGUgQXVkaXRTcG9vbCxcbn0gZnJvbSAnLi9hdWRpdC1zcG9vbC5qcyc7XG5leHBvcnQge1xuICByZXNvbHZlUmVkaXNDb25uZWN0aW9uLFxuICBkZXNjcmliZVJlZGlzQ29ubmVjdGlvbixcbiAgY3JlYXRlUmVkaXNDbGllbnQsXG4gIGNyZWF0ZUVudlJlZGlzQ2xpZW50LFxuICBjcmVhdGVSZWRpc1JlYWR5R2F0ZSxcbiAgaW5jcldpbmRvdyxcbiAgUmVkaXNDb25maWdFcnJvcixcbiAgdHlwZSBSZWRpc0V2YWxDbGllbnQsXG59IGZyb20gJy4vZW52LXJlZGlzLmpzJztcbmV4cG9ydCB7XG4gIGNyZWF0ZVJlZGlzVG9rZW5SZXZvY2F0aW9uU3RvcmUsXG4gIGNyZWF0ZUVudlJlZGlzVG9rZW5SZXZvY2F0aW9uU3RvcmUsXG4gIHB1Ymxpc2hUb2tlblJldm9jYXRpb24sXG4gIHB1Ymxpc2hTZXNzaW9uUmV2b2NhdGlvbixcbiAgcHVibGlzaENyZWRlbnRpYWxSZXZvY2F0aW9uLFxufSBmcm9tICcuL3Rva2VuLXJldm9jYXRpb24uanMnO1xuZXhwb3J0IHtcbiAgY3JlYXRlTWVtb3J5U3NlVGlja2V0U3RvcmUsXG4gIGNyZWF0ZUVudlNzZVRpY2tldFN0b3JlLFxuICBlbnZTc2VUaWNrZXRDYXBzLFxuICB0eXBlIEVudlNzZVRpY2tldFN0b3JlQ29uZmlnLFxuICB0eXBlIFNzZVRpY2tldFN0b3JlLFxuICB0eXBlIFNzZVRpY2tldFN0b3JlQ29uZmlnLFxufSBmcm9tICcuL3NzZS10aWNrZXQtc3RvcmUuanMnO1xuZXhwb3J0IHtcbiAgd2lyZVNlcnZpY2VTZWN1cml0eSxcbn0gZnJvbSAnLi9zZXJ2aWNlLWJvb3QuanMnO1xuZXhwb3J0IHtcbiAgY3JlYXRlV2ViaG9va0NoYW5uZWwsXG4gIGNyZWF0ZUVtYWlsQ2hhbm5lbCxcbiAgY3JlYXRlQ2hhbm5lbFJlZ2lzdHJ5LFxuICB0eXBlIE5vdGlmaWNhdGlvblByaW9yaXR5LFxuICB0eXBlIE5vdGlmaWNhdGlvbk1lc3NhZ2UsXG4gIHR5cGUgQ2hhbm5lbFRhcmdldCxcbiAgdHlwZSBEZWxpdmVyeVJlc3VsdCxcbiAgdHlwZSBOb3RpZmljYXRpb25DaGFubmVsLFxufSBmcm9tICcuL25vdGlmaWNhdGlvbi1jaGFubmVscy5qcyc7XG5leHBvcnQge1xuICBjcmVhdGVFY29zeXN0ZW1Ob3RpZnlDbGllbnQsXG4gIEVDT1NZU1RFTV9OT1RJRllfUEFUSCxcbiAgdHlwZSBFY29zeXN0ZW1Ob3RpZnlDbGllbnQsXG59IGZyb20gJy4vZWNvc3lzdGVtLW5vdGlmeS1jbGllbnQuanMnO1xuIl19
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). Long runs should check it between units of work and stop —
30
- * past that point another pod may be doing the same work.
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>): Promise<boolean>;
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGVhZGVyLWxvY2suanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VydmljZXMvbGVhZGVyLWxvY2sudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0QyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBQ3BDLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxjQUFjLEVBQXdCLE1BQU0sZ0JBQWdCLENBQUM7QUFDNUYsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFFcEQsTUFBTSxVQUFVLEdBQUcsWUFBWSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0FBb0IvQzs7OztHQUlHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxlQUFlLENBQUMsS0FBbUM7SUFDdkUsSUFBSSxDQUFDLEtBQUs7UUFBRSxPQUFPO0lBQ25CLElBQUksQ0FBQztRQUNILElBQUksT0FBTyxLQUFLLENBQUMsSUFBSSxLQUFLLFVBQVUsRUFBRSxDQUFDO1lBQUMsTUFBTSxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7WUFBQyxPQUFPO1FBQUMsQ0FBQztJQUN2RSxDQUFDO0lBQUMsTUFBTSxDQUFDO1FBQ1AsNkJBQTZCO0lBQy9CLENBQUM7SUFDRCxJQUFJLENBQUM7UUFBQyxLQUFLLENBQUMsVUFBVSxFQUFFLEVBQUUsQ0FBQztJQUFDLENBQUM7SUFBQyxNQUFNLENBQUMsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0FBQzNELENBQUM7QUFFRDtpRUFDaUU7QUFDakUsTUFBTSxnQkFBZ0IsR0FDcEIsbUdBQW1HLENBQUM7QUFFdEcsOERBQThEO0FBQzlELE1BQU0sZUFBZSxHQUNuQixnSEFBZ0gsQ0FBQztBQUVuSCxxRkFBcUY7QUFDckYs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LGVBQWUsR0FBRyxDQUFDO1FBQUUsT0FBTztJQUNoQyxNQUFNLE1BQU0sR0FBRyxVQUFVLENBQUM7SUFDMUIsVUFBVSxHQUFHLFNBQVMsQ0FBQztJQUN2QixNQUFNLGVBQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUNoQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCB7IHJhbmRvbVVVSUQgfSBmcm9tICdjcnlwdG8nO1xuaW1wb3J0IHsgY3JlYXRlRW52UmVkaXNDbGllbnQsIHdoZW5SZWRpc1JlYWR5LCB0eXBlIFJlYWR5QXdhcmVSZWRpcyB9IGZyb20gJy4vZW52LXJlZGlzLmpzJztcbmltcG9ydCB7IGNyZWF0ZUxvZ2dlciB9IGZyb20gJy4uL3V0aWxzL2xvZ2dlci5qcyc7XG5pbXBvcnQgeyBlbWl0Q291bnRlciB9IGZyb20gJy4uL3V0aWxzL21ldHJpYy1lbWl0dGVyLmpzJztcbmltcG9ydCB7IGVycm9yTWVzc2FnZSB9IGZyb20gJy4uL3V0aWxzL3Jlc3BvbnNlLmpzJztcblxuY29uc3QgbG9ja0xvZ2dlciA9IGNyZWF0ZUxvZ2dlcignbGVhZGVyLWxvY2snKTtcblxuLyoqXG4gKiBNaW5pbWFsIFJlZGlzIGNsaWVudCBzdXJmYWNlIG5lZWRlZCBmb3IgYSBsZWFkZXIgbG9jayAoYSBzdWJzZXQgb2YgaW9yZWRpcykuXG4gKiBgc2V0YCBpcyB2YXJpYWRpYyBzbyBjYWxsZXJzIGNhbiBwYXNzIGAnUFgnLCB0dGwsICdOWCdgLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIExvY2tSZWRpcyBleHRlbmRzIFJlYWR5QXdhcmVSZWRpcyB7XG4gIHNldChrZXk6IHN0cmluZywgdmFsdWU6IHN0cmluZywgLi4uYXJnczogdW5rbm93bltdKTogUHJvbWlzZTx1bmtub3duPjtcbiAgZ2V0KGtleTogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPjtcbiAgZGVsKC4uLmtleXM6IHN0cmluZ1tdKTogUHJvbWlzZTxudW1iZXI+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
- /** The work to run each cycle. Errors are caught + logged, never thrown. */
20
- run: () => Promise<void>;
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
- /** Stop the timer (and cancel a pending startup delay). Safe before start. */
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
  /**