@pipeline-builder/api-core 4.1.13 → 4.1.15
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/README.md +3 -2
- package/lib/constants/index.d.ts +0 -1
- package/lib/constants/index.js +1 -2
- package/lib/errors/app-errors.d.ts +8 -3
- package/lib/errors/app-errors.js +10 -5
- package/lib/helpers/access-helpers.d.ts +4 -6
- package/lib/helpers/access-helpers.js +6 -8
- package/lib/helpers/index.d.ts +3 -3
- package/lib/helpers/index.js +4 -4
- package/lib/helpers/org-hierarchy-http.d.ts +11 -10
- package/lib/helpers/org-hierarchy-http.js +24 -35
- package/lib/helpers/org-hierarchy.d.ts +37 -3
- package/lib/helpers/org-hierarchy.js +45 -4
- package/lib/helpers/restore-helpers.d.ts +44 -24
- package/lib/helpers/restore-helpers.js +41 -52
- package/lib/helpers/sse-helpers.d.ts +29 -7
- package/lib/helpers/sse-helpers.js +36 -9
- package/lib/index.d.ts +16 -14
- package/lib/index.js +17 -15
- package/lib/middleware/assurance.d.ts +116 -0
- package/lib/middleware/assurance.js +176 -0
- package/lib/middleware/auth.d.ts +5 -427
- package/lib/middleware/auth.js +36 -789
- package/lib/middleware/ecosystem-guard.d.ts +47 -0
- package/lib/middleware/ecosystem-guard.js +60 -0
- package/lib/middleware/index.d.ts +11 -4
- package/lib/middleware/index.js +12 -5
- package/lib/middleware/jwt-verify.d.ts +52 -0
- package/lib/middleware/jwt-verify.js +105 -0
- package/lib/middleware/permission-gates.d.ts +133 -0
- package/lib/middleware/permission-gates.js +260 -0
- package/lib/middleware/revocation.d.ts +96 -0
- package/lib/middleware/revocation.js +162 -0
- package/lib/middleware/route-table.d.ts +11 -0
- package/lib/middleware/route-table.js +4 -1
- package/lib/middleware/service-tokens.d.ts +83 -0
- package/lib/middleware/service-tokens.js +158 -0
- package/lib/middleware/step-up.d.ts +2 -2
- package/lib/middleware/step-up.js +8 -7
- package/lib/middleware/system-org.d.ts +20 -0
- package/lib/middleware/system-org.js +25 -0
- package/lib/openapi/routes/plugin-routes.js +133 -10
- package/lib/openapi/schema-registry.js +2 -5
- package/lib/routes/index.d.ts +1 -1
- package/lib/routes/index.js +2 -2
- package/lib/services/api-key-exchange.js +7 -5
- package/lib/services/audit-spool.d.ts +34 -10
- package/lib/services/audit-spool.js +75 -34
- package/lib/services/cache-service.d.ts +7 -0
- package/lib/services/cache-service.js +1 -1
- package/lib/services/circuit-breaker.d.ts +14 -1
- package/lib/services/circuit-breaker.js +36 -10
- package/lib/services/compliance-client.d.ts +10 -2
- package/lib/services/compliance-client.js +17 -10
- package/lib/services/compliance-event-subscriber.js +6 -6
- package/lib/services/durable-event-bus.js +8 -11
- package/lib/services/ecosystem-notify-client.d.ts +32 -0
- package/lib/services/ecosystem-notify-client.js +71 -0
- package/lib/services/env-redis.d.ts +4 -1
- package/lib/services/env-redis.js +32 -3
- package/lib/services/http-client.d.ts +19 -0
- package/lib/services/http-client.js +98 -19
- package/lib/services/index.d.ts +25 -24
- package/lib/services/index.js +25 -22
- package/lib/services/jwks-cache.js +5 -4
- package/lib/services/leader-lock.d.ts +22 -5
- package/lib/services/leader-lock.js +61 -6
- package/lib/services/quota.d.ts +9 -4
- package/lib/services/quota.js +34 -40
- package/lib/services/remote-audit-client.d.ts +28 -32
- package/lib/services/remote-audit-client.js +166 -49
- package/lib/services/retry-forever.js +5 -11
- package/lib/services/retry-strategy.d.ts +1 -1
- package/lib/services/retry-strategy.js +5 -4
- package/lib/services/scheduler.d.ts +8 -3
- package/lib/services/scheduler.js +17 -5
- package/lib/services/service-boot.d.ts +14 -13
- package/lib/services/service-boot.js +18 -15
- package/lib/services/service-keys.d.ts +1 -1
- package/lib/services/service-keys.js +12 -18
- package/lib/services/sse-ticket-store.d.ts +9 -1
- package/lib/services/sse-ticket-store.js +24 -9
- package/lib/services/system-notification.d.ts +27 -0
- package/lib/services/system-notification.js +50 -0
- package/lib/services/token-revocation.d.ts +50 -1
- package/lib/services/token-revocation.js +103 -3
- package/lib/types/audit-events.d.ts +6 -6
- package/lib/types/audit-events.js +1 -1
- package/lib/types/common.d.ts +32 -13
- package/lib/types/common.js +2 -1
- package/lib/types/ecosystem-notifications.d.ts +142 -0
- package/lib/types/ecosystem-notifications.js +210 -0
- package/lib/types/ecosystem.d.ts +77 -0
- package/lib/types/ecosystem.js +119 -0
- package/lib/types/error-codes.d.ts +81 -0
- package/lib/types/error-codes.js +108 -1
- package/lib/types/feature-flags.d.ts +21 -1
- package/lib/types/feature-flags.js +36 -2
- package/lib/types/index.d.ts +14 -9
- package/lib/types/index.js +15 -10
- package/lib/types/permissions.d.ts +46 -8
- package/lib/types/permissions.js +75 -12
- package/lib/types/plugin-catalog.d.ts +35 -0
- package/lib/types/plugin-catalog.js +39 -0
- package/lib/types/plugin-health.d.ts +102 -0
- package/lib/types/plugin-health.js +184 -0
- package/lib/types/quota-tiers.d.ts +15 -0
- package/lib/types/quota-tiers.js +23 -3
- package/lib/types/wire-vocabulary.d.ts +102 -0
- package/lib/types/wire-vocabulary.js +94 -0
- package/lib/utils/alias-resolver.js +2 -2
- package/lib/utils/audit.d.ts +5 -2
- package/lib/utils/audit.js +6 -3
- package/lib/utils/compliance-attributes.js +3 -4
- package/lib/utils/concurrency.d.ts +7 -0
- package/lib/utils/concurrency.js +13 -1
- package/lib/utils/env.d.ts +3 -4
- package/lib/utils/env.js +4 -5
- package/lib/utils/identity.d.ts +13 -4
- package/lib/utils/identity.js +18 -10
- package/lib/utils/index.d.ts +13 -10
- package/lib/utils/index.js +13 -10
- package/lib/utils/jwk.d.ts +4 -0
- package/lib/utils/jwk.js +13 -1
- package/lib/utils/logger.d.ts +1 -1
- package/lib/utils/logger.js +1 -1
- package/lib/utils/object.d.ts +11 -0
- package/lib/utils/object.js +24 -1
- package/lib/utils/params.d.ts +8 -22
- package/lib/utils/params.js +15 -43
- package/lib/utils/plugin-compliance.d.ts +98 -0
- package/lib/utils/plugin-compliance.js +78 -0
- package/lib/utils/proof-of-work.d.ts +69 -0
- package/lib/utils/proof-of-work.js +139 -0
- package/lib/utils/response.d.ts +16 -6
- package/lib/utils/response.js +18 -15
- package/lib/utils/retention.d.ts +17 -0
- package/lib/utils/retention.js +30 -0
- package/lib/utils/secret-encryption.d.ts +7 -7
- package/lib/utils/secret-encryption.js +9 -10
- package/lib/utils/secret-rotation.js +2 -2
- package/lib/utils/sensitive-patterns.js +4 -5
- package/lib/utils/service-registry.d.ts +15 -0
- package/lib/utils/service-registry.js +24 -0
- package/lib/utils/ssrf.d.ts +11 -2
- package/lib/utils/ssrf.js +112 -33
- package/lib/validation/ai-schemas.js +3 -2
- package/lib/validation/common-schemas.d.ts +0 -9
- package/lib/validation/common-schemas.js +1 -7
- package/lib/validation/dockerfile-static.d.ts +26 -0
- package/lib/validation/dockerfile-static.js +210 -0
- package/lib/validation/index.d.ts +13 -4
- package/lib/validation/index.js +14 -5
- package/lib/validation/message-schemas.js +6 -4
- package/lib/validation/pipeline-schemas.d.ts +8 -2
- package/lib/validation/pipeline-schemas.js +30 -4
- package/lib/validation/plugin-base-images.d.ts +20 -0
- package/lib/validation/plugin-base-images.js +17 -0
- package/lib/validation/plugin-catalog-detect.d.ts +86 -0
- package/lib/validation/plugin-catalog-detect.js +237 -0
- package/lib/validation/plugin-catalog-metadata.d.ts +141 -0
- package/lib/validation/plugin-catalog-metadata.js +162 -0
- package/lib/validation/plugin-heuristics.d.ts +41 -0
- package/lib/validation/plugin-heuristics.js +211 -0
- package/lib/validation/plugin-lint.d.ts +18 -0
- package/lib/validation/plugin-lint.js +136 -0
- package/lib/validation/plugin-name-confusable.d.ts +15 -0
- package/lib/validation/plugin-name-confusable.js +81 -0
- package/lib/validation/plugin-schemas.d.ts +40 -26
- package/lib/validation/plugin-schemas.js +26 -23
- package/lib/validation/plugin-spec-schema.d.ts +112 -0
- package/lib/validation/plugin-spec-schema.js +163 -0
- package/lib/validation/plugin-template-contract.d.ts +64 -0
- package/lib/validation/plugin-template-contract.js +113 -0
- package/package.json +69 -4
- package/lib/testing/mock-api-core.d.ts +0 -150
- package/lib/testing/mock-api-core.js +0 -246
- package/lib/testing/mock-drizzle.d.ts +0 -6
- package/lib/testing/mock-drizzle.js +0 -57
- package/lib/testing/route-coverage.d.ts +0 -64
- package/lib/testing/route-coverage.js +0 -183
- package/lib/testing/service-tokens.d.ts +0 -66
- package/lib/testing/service-tokens.js +0 -137
- package/lib/testing/tier-mock.d.ts +0 -44
- package/lib/testing/tier-mock.js +0 -65
- package/lib/testing/user-tokens.d.ts +0 -75
- package/lib/testing/user-tokens.js +0 -115
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin compliance attributes: what the plugin service tells compliance about
|
|
3
|
+
* an uploaded plugin and its pushed image, derived from the stored plugin row.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* The attributes the plugin service sends to `/compliance/validate/plugin`.
|
|
7
|
+
*
|
|
8
|
+
* The spec/config fields describe the plugin as uploaded. The image fields
|
|
9
|
+
* describe what the platform itself established about the pushed image — the
|
|
10
|
+
* facts the curated SOC2/PCI/CIS plugin rules evaluate:
|
|
11
|
+
*
|
|
12
|
+
* - `signed`: the image digest carries the platform's cosign signature.
|
|
13
|
+
* - `scanned`: a vulnerability scan completed (`scannedAt` is set); the
|
|
14
|
+
* `vuln*` counts are present only then — an unscanned image sends no counts,
|
|
15
|
+
* so a numeric rule like `vulnCritical lt 1` cannot pass on a missing value.
|
|
16
|
+
* - `runAsRoot`: the image config's effective USER is root (empty, `0`, `root`).
|
|
17
|
+
* - `packages`: package names from the signed SBOM.
|
|
18
|
+
* - `tags`: the plugin's keywords plus `key=value` labels (CIS 2.1 inventory).
|
|
19
|
+
*
|
|
20
|
+
* Image fields are unknown until the build worker has pushed, signed and
|
|
21
|
+
* scanned the image; the upload-time check lists them in `deferredFields`
|
|
22
|
+
* and the worker re-validates once they are real.
|
|
23
|
+
*/
|
|
24
|
+
export interface PluginComplianceAttributes {
|
|
25
|
+
name?: string;
|
|
26
|
+
version?: string;
|
|
27
|
+
pluginType?: string;
|
|
28
|
+
computeType?: string;
|
|
29
|
+
timeout?: number | null;
|
|
30
|
+
failureBehavior?: string;
|
|
31
|
+
env?: Record<string, string>;
|
|
32
|
+
buildArgs?: Record<string, string>;
|
|
33
|
+
installCommands?: string[];
|
|
34
|
+
commands?: string[];
|
|
35
|
+
visibility?: string;
|
|
36
|
+
secrets?: unknown[];
|
|
37
|
+
metadata?: Record<string, unknown>;
|
|
38
|
+
keywords?: string[];
|
|
39
|
+
buildType?: string;
|
|
40
|
+
tags?: string[];
|
|
41
|
+
signed?: boolean;
|
|
42
|
+
scanned?: boolean;
|
|
43
|
+
vulnCritical?: number;
|
|
44
|
+
vulnHigh?: number;
|
|
45
|
+
vulnMedium?: number;
|
|
46
|
+
vulnLow?: number;
|
|
47
|
+
runAsRoot?: boolean;
|
|
48
|
+
packages?: string[];
|
|
49
|
+
[key: string]: unknown;
|
|
50
|
+
}
|
|
51
|
+
/** Plugin attributes only the build worker can establish (see {@link PluginComplianceAttributes}). */
|
|
52
|
+
export declare const PLUGIN_IMAGE_COMPLIANCE_FIELDS: readonly ['signed', 'scanned', 'vulnCritical', 'vulnHigh', 'vulnMedium', 'vulnLow', 'runAsRoot', 'packages'];
|
|
53
|
+
export type PluginImageComplianceField = typeof PLUGIN_IMAGE_COMPLIANCE_FIELDS[number];
|
|
54
|
+
/** The stored plugin-row columns the image facts derive from (any subset). */
|
|
55
|
+
export interface PluginImageRow {
|
|
56
|
+
buildType?: unknown;
|
|
57
|
+
pluginType?: unknown;
|
|
58
|
+
imageDigest?: unknown;
|
|
59
|
+
scannedAt?: unknown;
|
|
60
|
+
vulnCritical?: unknown;
|
|
61
|
+
vulnHigh?: unknown;
|
|
62
|
+
vulnMedium?: unknown;
|
|
63
|
+
vulnLow?: unknown;
|
|
64
|
+
runAsRoot?: unknown;
|
|
65
|
+
keywords?: unknown;
|
|
66
|
+
labels?: unknown;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Whether a plugin runs on its own image: `metadata_only` builds none and a
|
|
70
|
+
* `ManualApprovalStep` never runs one. Same rule as the plugin worker's skip.
|
|
71
|
+
*/
|
|
72
|
+
export declare function pluginRunsOwnImage(row: Pick<PluginImageRow, 'buildType' | 'pluginType'>): boolean;
|
|
73
|
+
/** CIS 2.1 inventory tags: the plugin's keywords plus its labels as `key=value`. */
|
|
74
|
+
export declare function pluginComplianceTags(keywords: unknown, labels?: unknown): string[];
|
|
75
|
+
/**
|
|
76
|
+
* The image-derived compliance attributes of a STORED plugin row (the plugin
|
|
77
|
+
* service's update re-check, the build worker's post-build check, and the
|
|
78
|
+
* compliance service's scans and entity events all derive them here, so the
|
|
79
|
+
* rules see one definition of `signed`/`scanned`).
|
|
80
|
+
*
|
|
81
|
+
* - `signed`: the row carries a well-formed digest. The worker stores a digest
|
|
82
|
+
* only after image-registry signed it (a signing failure fails the build), so
|
|
83
|
+
* a digest on the row IS a platform signature.
|
|
84
|
+
* - `scanned` + `vuln*`: counts only when `scannedAt` is set.
|
|
85
|
+
* - `runAsRoot`: only when known.
|
|
86
|
+
* - `packages`: not a row column. Pass the SBOM's names when you have them,
|
|
87
|
+
* `null` when the SBOM could not be read (attribute omitted, so a
|
|
88
|
+
* `$count(packages)` rule sees 0), or leave it `undefined` on a path that
|
|
89
|
+
* never reads SBOMs — it is then returned in `deferredFields` (it was
|
|
90
|
+
* evaluated by the post-build check and cannot change without a rebuild).
|
|
91
|
+
*
|
|
92
|
+
* A plugin that runs no image of its own is honestly unsigned and unscanned
|
|
93
|
+
* with no packages; nothing is deferred for it.
|
|
94
|
+
*/
|
|
95
|
+
export declare function derivePluginImageCompliance(row: PluginImageRow, packages?: string[] | null): {
|
|
96
|
+
attributes: PluginComplianceAttributes;
|
|
97
|
+
deferredFields: PluginImageComplianceField[];
|
|
98
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/** Plugin attributes only the build worker can establish (see {@link PluginComplianceAttributes}). */
|
|
4
|
+
export const PLUGIN_IMAGE_COMPLIANCE_FIELDS = [
|
|
5
|
+
'signed', 'scanned', 'vulnCritical', 'vulnHigh', 'vulnMedium', 'vulnLow', 'runAsRoot', 'packages',
|
|
6
|
+
];
|
|
7
|
+
const SIGNED_DIGEST_RE = /^sha256:[0-9a-f]{64}$/;
|
|
8
|
+
/**
|
|
9
|
+
* Whether a plugin runs on its own image: `metadata_only` builds none and a
|
|
10
|
+
* `ManualApprovalStep` never runs one. Same rule as the plugin worker's skip.
|
|
11
|
+
*/
|
|
12
|
+
export function pluginRunsOwnImage(row) {
|
|
13
|
+
return row.buildType !== 'metadata_only' && row.pluginType !== 'ManualApprovalStep';
|
|
14
|
+
}
|
|
15
|
+
/** CIS 2.1 inventory tags: the plugin's keywords plus its labels as `key=value`. */
|
|
16
|
+
export function pluginComplianceTags(keywords, labels) {
|
|
17
|
+
const tags = new Set();
|
|
18
|
+
if (Array.isArray(keywords)) {
|
|
19
|
+
for (const k of keywords)
|
|
20
|
+
if (typeof k === 'string' && k.trim())
|
|
21
|
+
tags.add(k.trim());
|
|
22
|
+
}
|
|
23
|
+
if (labels && typeof labels === 'object' && !Array.isArray(labels)) {
|
|
24
|
+
for (const [k, v] of Object.entries(labels)) {
|
|
25
|
+
if (typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean')
|
|
26
|
+
tags.add(`${k}=${String(v)}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return [...tags];
|
|
30
|
+
}
|
|
31
|
+
const finiteCount = (v) => typeof v === 'number' && Number.isFinite(v) ? v : undefined;
|
|
32
|
+
/**
|
|
33
|
+
* The image-derived compliance attributes of a STORED plugin row (the plugin
|
|
34
|
+
* service's update re-check, the build worker's post-build check, and the
|
|
35
|
+
* compliance service's scans and entity events all derive them here, so the
|
|
36
|
+
* rules see one definition of `signed`/`scanned`).
|
|
37
|
+
*
|
|
38
|
+
* - `signed`: the row carries a well-formed digest. The worker stores a digest
|
|
39
|
+
* only after image-registry signed it (a signing failure fails the build), so
|
|
40
|
+
* a digest on the row IS a platform signature.
|
|
41
|
+
* - `scanned` + `vuln*`: counts only when `scannedAt` is set.
|
|
42
|
+
* - `runAsRoot`: only when known.
|
|
43
|
+
* - `packages`: not a row column. Pass the SBOM's names when you have them,
|
|
44
|
+
* `null` when the SBOM could not be read (attribute omitted, so a
|
|
45
|
+
* `$count(packages)` rule sees 0), or leave it `undefined` on a path that
|
|
46
|
+
* never reads SBOMs — it is then returned in `deferredFields` (it was
|
|
47
|
+
* evaluated by the post-build check and cannot change without a rebuild).
|
|
48
|
+
*
|
|
49
|
+
* A plugin that runs no image of its own is honestly unsigned and unscanned
|
|
50
|
+
* with no packages; nothing is deferred for it.
|
|
51
|
+
*/
|
|
52
|
+
export function derivePluginImageCompliance(row, packages) {
|
|
53
|
+
const tags = pluginComplianceTags(row.keywords, row.labels);
|
|
54
|
+
if (!pluginRunsOwnImage(row)) {
|
|
55
|
+
return { attributes: { tags, signed: false, scanned: false, packages: [] }, deferredFields: [] };
|
|
56
|
+
}
|
|
57
|
+
const scanned = row.scannedAt !== null && row.scannedAt !== undefined;
|
|
58
|
+
const attributes = {
|
|
59
|
+
tags,
|
|
60
|
+
signed: typeof row.imageDigest === 'string' && SIGNED_DIGEST_RE.test(row.imageDigest),
|
|
61
|
+
scanned,
|
|
62
|
+
};
|
|
63
|
+
if (scanned) {
|
|
64
|
+
attributes.vulnCritical = finiteCount(row.vulnCritical);
|
|
65
|
+
attributes.vulnHigh = finiteCount(row.vulnHigh);
|
|
66
|
+
attributes.vulnMedium = finiteCount(row.vulnMedium);
|
|
67
|
+
attributes.vulnLow = finiteCount(row.vulnLow);
|
|
68
|
+
}
|
|
69
|
+
if (typeof row.runAsRoot === 'boolean')
|
|
70
|
+
attributes.runAsRoot = row.runAsRoot;
|
|
71
|
+
if (Array.isArray(packages))
|
|
72
|
+
attributes.packages = packages;
|
|
73
|
+
for (const k of Object.keys(attributes))
|
|
74
|
+
if (attributes[k] === undefined)
|
|
75
|
+
delete attributes[k];
|
|
76
|
+
return { attributes, deferredFields: packages === undefined ? ['packages'] : [] };
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLWNvbXBsaWFuY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvcGx1Z2luLWNvbXBsaWFuY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQXNEdEMsc0dBQXNHO0FBQ3RHLE1BQU0sQ0FBQyxNQUFNLDhCQUE4QixHQUFHO0lBQzVDLFFBQVEsRUFBRSxTQUFTLEVBQUUsY0FBYyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsU0FBUyxFQUFFLFdBQVcsRUFBRSxVQUFVO0NBQ3pGLENBQUM7QUFrQlgsTUFBTSxnQkFBZ0IsR0FBRyx1QkFBdUIsQ0FBQztBQUVqRDs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsa0JBQWtCLENBQUMsR0FBcUQ7SUFDdEYsT0FBTyxHQUFHLENBQUMsU0FBUyxLQUFLLGVBQWUsSUFBSSxHQUFHLENBQUMsVUFBVSxLQUFLLG9CQUFvQixDQUFDO0FBQ3RGLENBQUM7QUFFRCxvRkFBb0Y7QUFDcEYsTUFBTSxVQUFVLG9CQUFvQixDQUFDLFFBQWlCLEVBQUUsTUFBZ0I7SUFDdEUsTUFBTSxJQUFJLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztJQUMvQixJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztRQUM1QixLQUFLLE1BQU0sQ0FBQyxJQUFJLFFBQVE7WUFBRSxJQUFJLE9BQU8sQ0FBQyxLQUFLLFFBQVEsSUFBSSxDQUFDLENBQUMsSUFBSSxFQUFFO2dCQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7SUFDdEYsQ0FBQztJQUNELElBQUksTUFBTSxJQUFJLE9BQU8sTUFBTSxLQUFLLFFBQVEsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztRQUNuRSxLQUFLLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxNQUFpQyxDQUFDLEVBQUUsQ0FBQztZQUN2RSxJQUFJLE9BQU8sQ0FBQyxLQUFLLFFBQVEsSUFBSSxPQUFPLENBQUMsS0FBSyxRQUFRLElBQUksT0FBTyxDQUFDLEtBQUssU0FBUztnQkFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDOUcsQ0FBQztJQUNILENBQUM7SUFDRCxPQUFPLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQztBQUNuQixDQUFDO0FBRUQsTUFBTSxXQUFXLEdBQUcsQ0FBQyxDQUFVLEVBQXNCLEVBQUUsQ0FDckQsT0FBTyxDQUFDLEtBQUssUUFBUSxJQUFJLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0FBRTlEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbUJHO0FBQ0gsTUFBTSxVQUFVLDJCQUEyQixDQUN6QyxHQUFtQixFQUNuQixRQUEwQjtJQUUxQixNQUFNLElBQUksR0FBRyxvQkFBb0IsQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUM1RCxJQUFJLENBQUMsa0JBQWtCLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUM3QixPQUFPLEVBQUUsVUFBVSxFQUFFLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsRUFBRSxFQUFFLEVBQUUsY0FBYyxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ25HLENBQUM7SUFDRCxNQUFNLE9BQU8sR0FBRyxHQUFHLENBQUMsU0FBUyxLQUFLLElBQUksSUFBSSxHQUFHLENBQUMsU0FBUyxLQUFLLFNBQVMsQ0FBQztJQUN0RSxNQUFNLFVBQVUsR0FBK0I7UUFDN0MsSUFBSTtRQUNKLE1BQU0sRUFBRSxPQUFPLEdBQUcsQ0FBQyxXQUFXLEtBQUssUUFBUSxJQUFJLGdCQUFnQixDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDO1FBQ3JGLE9BQU87S0FDUixDQUFDO0lBQ0YsSUFBSSxPQUFPLEVBQUUsQ0FBQztRQUNaLFVBQVUsQ0FBQyxZQUFZLEdBQUcsV0FBVyxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUN4RCxVQUFVLENBQUMsUUFBUSxHQUFHLFdBQVcsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDaEQsVUFBVSxDQUFDLFVBQVUsR0FBRyxXQUFXLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ3BELFVBQVUsQ0FBQyxPQUFPLEdBQUcsV0FBVyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNoRCxDQUFDO0lBQ0QsSUFBSSxPQUFPLEdBQUcsQ0FBQyxTQUFTLEtBQUssU0FBUztRQUFFLFVBQVUsQ0FBQyxTQUFTLEdBQUcsR0FBRyxDQUFDLFNBQVMsQ0FBQztJQUM3RSxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDO1FBQUUsVUFBVSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUM7SUFDNUQsS0FBSyxNQUFNLENBQUMsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQztRQUFFLElBQUksVUFBVSxDQUFDLENBQUMsQ0FBQyxLQUFLLFNBQVM7WUFBRSxPQUFPLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMvRixPQUFPLEVBQUUsVUFBVSxFQUFFLGNBQWMsRUFBRSxRQUFRLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQztBQUNwRixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbi8qKlxuICogUGx1Z2luIGNvbXBsaWFuY2UgYXR0cmlidXRlczogd2hhdCB0aGUgcGx1Z2luIHNlcnZpY2UgdGVsbHMgY29tcGxpYW5jZSBhYm91dFxuICogYW4gdXBsb2FkZWQgcGx1Z2luIGFuZCBpdHMgcHVzaGVkIGltYWdlLCBkZXJpdmVkIGZyb20gdGhlIHN0b3JlZCBwbHVnaW4gcm93LlxuICovXG5cbi8qKlxuICogVGhlIGF0dHJpYnV0ZXMgdGhlIHBsdWdpbiBzZXJ2aWNlIHNlbmRzIHRvIGAvY29tcGxpYW5jZS92YWxpZGF0ZS9wbHVnaW5gLlxuICpcbiAqIFRoZSBzcGVjL2NvbmZpZyBmaWVsZHMgZGVzY3JpYmUgdGhlIHBsdWdpbiBhcyB1cGxvYWRlZC4gVGhlIGltYWdlIGZpZWxkc1xuICogZGVzY3JpYmUgd2hhdCB0aGUgcGxhdGZvcm0gaXRzZWxmIGVzdGFibGlzaGVkIGFib3V0IHRoZSBwdXNoZWQgaW1hZ2Ug4oCUIHRoZVxuICogZmFjdHMgdGhlIGN1cmF0ZWQgU09DMi9QQ0kvQ0lTIHBsdWdpbiBydWxlcyBldmFsdWF0ZTpcbiAqXG4gKiAtIGBzaWduZWRgOiB0aGUgaW1hZ2UgZGlnZXN0IGNhcnJpZXMgdGhlIHBsYXRmb3JtJ3MgY29zaWduIHNpZ25hdHVyZS5cbiAqIC0gYHNjYW5uZWRgOiBhIHZ1bG5lcmFiaWxpdHkgc2NhbiBjb21wbGV0ZWQgKGBzY2FubmVkQXRgIGlzIHNldCk7IHRoZVxuICogICBgdnVsbipgIGNvdW50cyBhcmUgcHJlc2VudCBvbmx5IHRoZW4g4oCUIGFuIHVuc2Nhbm5lZCBpbWFnZSBzZW5kcyBubyBjb3VudHMsXG4gKiAgIHNvIGEgbnVtZXJpYyBydWxlIGxpa2UgYHZ1bG5Dcml0aWNhbCBsdCAxYCBjYW5ub3QgcGFzcyBvbiBhIG1pc3NpbmcgdmFsdWUuXG4gKiAtIGBydW5Bc1Jvb3RgOiB0aGUgaW1hZ2UgY29uZmlnJ3MgZWZmZWN0aXZlIFVTRVIgaXMgcm9vdCAoZW1wdHksIGAwYCwgYHJvb3RgKS5cbiAqIC0gYHBhY2thZ2VzYDogcGFja2FnZSBuYW1lcyBmcm9tIHRoZSBzaWduZWQgU0JPTS5cbiAqIC0gYHRhZ3NgOiB0aGUgcGx1Z2luJ3Mga2V5d29yZHMgcGx1cyBga2V5PXZhbHVlYCBsYWJlbHMgKENJUyAyLjEgaW52ZW50b3J5KS5cbiAqXG4gKiBJbWFnZSBmaWVsZHMgYXJlIHVua25vd24gdW50aWwgdGhlIGJ1aWxkIHdvcmtlciBoYXMgcHVzaGVkLCBzaWduZWQgYW5kXG4gKiBzY2FubmVkIHRoZSBpbWFnZTsgdGhlIHVwbG9hZC10aW1lIGNoZWNrIGxpc3RzIHRoZW0gaW4gYGRlZmVycmVkRmllbGRzYFxuICogYW5kIHRoZSB3b3JrZXIgcmUtdmFsaWRhdGVzIG9uY2UgdGhleSBhcmUgcmVhbC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBQbHVnaW5Db21wbGlhbmNlQXR0cmlidXRlcyB7XG4gIG5hbWU/OiBzdHJpbmc7XG4gIHZlcnNpb24/OiBzdHJpbmc7XG4gIHBsdWdpblR5cGU/OiBzdHJpbmc7XG4gIGNvbXB1dGVUeXBlPzogc3RyaW5nO1xuICB0aW1lb3V0PzogbnVtYmVyIHwgbnVsbDtcbiAgZmFpbHVyZUJlaGF2aW9yPzogc3RyaW5nO1xuICBlbnY/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICBidWlsZEFyZ3M/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICBpbnN0YWxsQ29tbWFuZHM/OiBzdHJpbmdbXTtcbiAgY29tbWFuZHM/OiBzdHJpbmdbXTtcbiAgdmlzaWJpbGl0eT86IHN0cmluZztcbiAgc2VjcmV0cz86IHVua25vd25bXTtcbiAgbWV0YWRhdGE/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAga2V5d29yZHM/OiBzdHJpbmdbXTtcbiAgYnVpbGRUeXBlPzogc3RyaW5nO1xuICB0YWdzPzogc3RyaW5nW107XG4gIHNpZ25lZD86IGJvb2xlYW47XG4gIHNjYW5uZWQ/OiBib29sZWFuO1xuICB2dWxuQ3JpdGljYWw/OiBudW1iZXI7XG4gIHZ1bG5IaWdoPzogbnVtYmVyO1xuICB2dWxuTWVkaXVtPzogbnVtYmVyO1xuICB2dWxuTG93PzogbnVtYmVyO1xuICBydW5Bc1Jvb3Q/OiBib29sZWFuO1xuICBwYWNrYWdlcz86IHN0cmluZ1tdO1xuICBba2V5OiBzdHJpbmddOiB1bmtub3duO1xufVxuXG4vKiogUGx1Z2luIGF0dHJpYnV0ZXMgb25seSB0aGUgYnVpbGQgd29ya2VyIGNhbiBlc3RhYmxpc2ggKHNlZSB7QGxpbmsgUGx1Z2luQ29tcGxpYW5jZUF0dHJpYnV0ZXN9KS4gKi9cbmV4cG9ydCBjb25zdCBQTFVHSU5fSU1BR0VfQ09NUExJQU5DRV9GSUVMRFMgPSBbXG4gICdzaWduZWQnLCAnc2Nhbm5lZCcsICd2dWxuQ3JpdGljYWwnLCAndnVsbkhpZ2gnLCAndnVsbk1lZGl1bScsICd2dWxuTG93JywgJ3J1bkFzUm9vdCcsICdwYWNrYWdlcycsXG5dIGFzIGNvbnN0O1xuZXhwb3J0IHR5cGUgUGx1Z2luSW1hZ2VDb21wbGlhbmNlRmllbGQgPSB0eXBlb2YgUExVR0lOX0lNQUdFX0NPTVBMSUFOQ0VfRklFTERTW251bWJlcl07XG5cbi8qKiBUaGUgc3RvcmVkIHBsdWdpbi1yb3cgY29sdW1ucyB0aGUgaW1hZ2UgZmFjdHMgZGVyaXZlIGZyb20gKGFueSBzdWJzZXQpLiAqL1xuZXhwb3J0IGludGVyZmFjZSBQbHVnaW5JbWFnZVJvdyB7XG4gIGJ1aWxkVHlwZT86IHVua25vd247XG4gIHBsdWdpblR5cGU/OiB1bmtub3duO1xuICBpbWFnZURpZ2VzdD86IHVua25vd247XG4gIHNjYW5uZWRBdD86IHVua25vd247XG4gIHZ1bG5Dcml0aWNhbD86IHVua25vd247XG4gIHZ1bG5IaWdoPzogdW5rbm93bjtcbiAgdnVsbk1lZGl1bT86IHVua25vd247XG4gIHZ1bG5Mb3c/OiB1bmtub3duO1xuICBydW5Bc1Jvb3Q/OiB1bmtub3duO1xuICBrZXl3b3Jkcz86IHVua25vd247XG4gIGxhYmVscz86IHVua25vd247XG59XG5cbmNvbnN0IFNJR05FRF9ESUdFU1RfUkUgPSAvXnNoYTI1NjpbMC05YS1mXXs2NH0kLztcblxuLyoqXG4gKiBXaGV0aGVyIGEgcGx1Z2luIHJ1bnMgb24gaXRzIG93biBpbWFnZTogYG1ldGFkYXRhX29ubHlgIGJ1aWxkcyBub25lIGFuZCBhXG4gKiBgTWFudWFsQXBwcm92YWxTdGVwYCBuZXZlciBydW5zIG9uZS4gU2FtZSBydWxlIGFzIHRoZSBwbHVnaW4gd29ya2VyJ3Mgc2tpcC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBsdWdpblJ1bnNPd25JbWFnZShyb3c6IFBpY2s8UGx1Z2luSW1hZ2VSb3csICdidWlsZFR5cGUnIHwgJ3BsdWdpblR5cGUnPik6IGJvb2xlYW4ge1xuICByZXR1cm4gcm93LmJ1aWxkVHlwZSAhPT0gJ21ldGFkYXRhX29ubHknICYmIHJvdy5wbHVnaW5UeXBlICE9PSAnTWFudWFsQXBwcm92YWxTdGVwJztcbn1cblxuLyoqIENJUyAyLjEgaW52ZW50b3J5IHRhZ3M6IHRoZSBwbHVnaW4ncyBrZXl3b3JkcyBwbHVzIGl0cyBsYWJlbHMgYXMgYGtleT12YWx1ZWAuICovXG5leHBvcnQgZnVuY3Rpb24gcGx1Z2luQ29tcGxpYW5jZVRhZ3Moa2V5d29yZHM6IHVua25vd24sIGxhYmVscz86IHVua25vd24pOiBzdHJpbmdbXSB7XG4gIGNvbnN0IHRhZ3MgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgaWYgKEFycmF5LmlzQXJyYXkoa2V5d29yZHMpKSB7XG4gICAgZm9yIChjb25zdCBrIG9mIGtleXdvcmRzKSBpZiAodHlwZW9mIGsgPT09ICdzdHJpbmcnICYmIGsudHJpbSgpKSB0YWdzLmFkZChrLnRyaW0oKSk7XG4gIH1cbiAgaWYgKGxhYmVscyAmJiB0eXBlb2YgbGFiZWxzID09PSAnb2JqZWN0JyAmJiAhQXJyYXkuaXNBcnJheShsYWJlbHMpKSB7XG4gICAgZm9yIChjb25zdCBbaywgdl0gb2YgT2JqZWN0LmVudHJpZXMobGFiZWxzIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KSkge1xuICAgICAgaWYgKHR5cGVvZiB2ID09PSAnc3RyaW5nJyB8fCB0eXBlb2YgdiA9PT0gJ251bWJlcicgfHwgdHlwZW9mIHYgPT09ICdib29sZWFuJykgdGFncy5hZGQoYCR7a309JHtTdHJpbmcodil9YCk7XG4gICAgfVxuICB9XG4gIHJldHVybiBbLi4udGFnc107XG59XG5cbmNvbnN0IGZpbml0ZUNvdW50ID0gKHY6IHVua25vd24pOiBudW1iZXIgfCB1bmRlZmluZWQgPT5cbiAgdHlwZW9mIHYgPT09ICdudW1iZXInICYmIE51bWJlci5pc0Zpbml0ZSh2KSA/IHYgOiB1bmRlZmluZWQ7XG5cbi8qKlxuICogVGhlIGltYWdlLWRlcml2ZWQgY29tcGxpYW5jZSBhdHRyaWJ1dGVzIG9mIGEgU1RPUkVEIHBsdWdpbiByb3cgKHRoZSBwbHVnaW5cbiAqIHNlcnZpY2UncyB1cGRhdGUgcmUtY2hlY2ssIHRoZSBidWlsZCB3b3JrZXIncyBwb3N0LWJ1aWxkIGNoZWNrLCBhbmQgdGhlXG4gKiBjb21wbGlhbmNlIHNlcnZpY2UncyBzY2FucyBhbmQgZW50aXR5IGV2ZW50cyBhbGwgZGVyaXZlIHRoZW0gaGVyZSwgc28gdGhlXG4gKiBydWxlcyBzZWUgb25lIGRlZmluaXRpb24gb2YgYHNpZ25lZGAvYHNjYW5uZWRgKS5cbiAqXG4gKiAtIGBzaWduZWRgOiB0aGUgcm93IGNhcnJpZXMgYSB3ZWxsLWZvcm1lZCBkaWdlc3QuIFRoZSB3b3JrZXIgc3RvcmVzIGEgZGlnZXN0XG4gKiAgIG9ubHkgYWZ0ZXIgaW1hZ2UtcmVnaXN0cnkgc2lnbmVkIGl0IChhIHNpZ25pbmcgZmFpbHVyZSBmYWlscyB0aGUgYnVpbGQpLCBzb1xuICogICBhIGRpZ2VzdCBvbiB0aGUgcm93IElTIGEgcGxhdGZvcm0gc2lnbmF0dXJlLlxuICogLSBgc2Nhbm5lZGAgKyBgdnVsbipgOiBjb3VudHMgb25seSB3aGVuIGBzY2FubmVkQXRgIGlzIHNldC5cbiAqIC0gYHJ1bkFzUm9vdGA6IG9ubHkgd2hlbiBrbm93bi5cbiAqIC0gYHBhY2thZ2VzYDogbm90IGEgcm93IGNvbHVtbi4gUGFzcyB0aGUgU0JPTSdzIG5hbWVzIHdoZW4geW91IGhhdmUgdGhlbSxcbiAqICAgYG51bGxgIHdoZW4gdGhlIFNCT00gY291bGQgbm90IGJlIHJlYWQgKGF0dHJpYnV0ZSBvbWl0dGVkLCBzbyBhXG4gKiAgIGAkY291bnQocGFja2FnZXMpYCBydWxlIHNlZXMgMCksIG9yIGxlYXZlIGl0IGB1bmRlZmluZWRgIG9uIGEgcGF0aCB0aGF0XG4gKiAgIG5ldmVyIHJlYWRzIFNCT01zIOKAlCBpdCBpcyB0aGVuIHJldHVybmVkIGluIGBkZWZlcnJlZEZpZWxkc2AgKGl0IHdhc1xuICogICBldmFsdWF0ZWQgYnkgdGhlIHBvc3QtYnVpbGQgY2hlY2sgYW5kIGNhbm5vdCBjaGFuZ2Ugd2l0aG91dCBhIHJlYnVpbGQpLlxuICpcbiAqIEEgcGx1Z2luIHRoYXQgcnVucyBubyBpbWFnZSBvZiBpdHMgb3duIGlzIGhvbmVzdGx5IHVuc2lnbmVkIGFuZCB1bnNjYW5uZWRcbiAqIHdpdGggbm8gcGFja2FnZXM7IG5vdGhpbmcgaXMgZGVmZXJyZWQgZm9yIGl0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVyaXZlUGx1Z2luSW1hZ2VDb21wbGlhbmNlKFxuICByb3c6IFBsdWdpbkltYWdlUm93LFxuICBwYWNrYWdlcz86IHN0cmluZ1tdIHwgbnVsbCxcbik6IHsgYXR0cmlidXRlczogUGx1Z2luQ29tcGxpYW5jZUF0dHJpYnV0ZXM7IGRlZmVycmVkRmllbGRzOiBQbHVnaW5JbWFnZUNvbXBsaWFuY2VGaWVsZFtdIH0ge1xuICBjb25zdCB0YWdzID0gcGx1Z2luQ29tcGxpYW5jZVRhZ3Mocm93LmtleXdvcmRzLCByb3cubGFiZWxzKTtcbiAgaWYgKCFwbHVnaW5SdW5zT3duSW1hZ2Uocm93KSkge1xuICAgIHJldHVybiB7IGF0dHJpYnV0ZXM6IHsgdGFncywgc2lnbmVkOiBmYWxzZSwgc2Nhbm5lZDogZmFsc2UsIHBhY2thZ2VzOiBbXSB9LCBkZWZlcnJlZEZpZWxkczogW10gfTtcbiAgfVxuICBjb25zdCBzY2FubmVkID0gcm93LnNjYW5uZWRBdCAhPT0gbnVsbCAmJiByb3cuc2Nhbm5lZEF0ICE9PSB1bmRlZmluZWQ7XG4gIGNvbnN0IGF0dHJpYnV0ZXM6IFBsdWdpbkNvbXBsaWFuY2VBdHRyaWJ1dGVzID0ge1xuICAgIHRhZ3MsXG4gICAgc2lnbmVkOiB0eXBlb2Ygcm93LmltYWdlRGlnZXN0ID09PSAnc3RyaW5nJyAmJiBTSUdORURfRElHRVNUX1JFLnRlc3Qocm93LmltYWdlRGlnZXN0KSxcbiAgICBzY2FubmVkLFxuICB9O1xuICBpZiAoc2Nhbm5lZCkge1xuICAgIGF0dHJpYnV0ZXMudnVsbkNyaXRpY2FsID0gZmluaXRlQ291bnQocm93LnZ1bG5Dcml0aWNhbCk7XG4gICAgYXR0cmlidXRlcy52dWxuSGlnaCA9IGZpbml0ZUNvdW50KHJvdy52dWxuSGlnaCk7XG4gICAgYXR0cmlidXRlcy52dWxuTWVkaXVtID0gZmluaXRlQ291bnQocm93LnZ1bG5NZWRpdW0pO1xuICAgIGF0dHJpYnV0ZXMudnVsbkxvdyA9IGZpbml0ZUNvdW50KHJvdy52dWxuTG93KTtcbiAgfVxuICBpZiAodHlwZW9mIHJvdy5ydW5Bc1Jvb3QgPT09ICdib29sZWFuJykgYXR0cmlidXRlcy5ydW5Bc1Jvb3QgPSByb3cucnVuQXNSb290O1xuICBpZiAoQXJyYXkuaXNBcnJheShwYWNrYWdlcykpIGF0dHJpYnV0ZXMucGFja2FnZXMgPSBwYWNrYWdlcztcbiAgZm9yIChjb25zdCBrIG9mIE9iamVjdC5rZXlzKGF0dHJpYnV0ZXMpKSBpZiAoYXR0cmlidXRlc1trXSA9PT0gdW5kZWZpbmVkKSBkZWxldGUgYXR0cmlidXRlc1trXTtcbiAgcmV0dXJuIHsgYXR0cmlidXRlcywgZGVmZXJyZWRGaWVsZHM6IHBhY2thZ2VzID09PSB1bmRlZmluZWQgPyBbJ3BhY2thZ2VzJ10gOiBbXSB9O1xufVxuIl19
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/** Default leading-zero-bit difficulty (≈1M hashes; a second or two in a browser). */
|
|
2
|
+
export declare const POW_DEFAULT_DIFFICULTY = 20;
|
|
3
|
+
/** Hard ceiling on a difficulty an operator can configure. */
|
|
4
|
+
export declare const POW_MAX_DIFFICULTY = 32;
|
|
5
|
+
/** How long a challenge stays solvable. */
|
|
6
|
+
export declare const POW_CHALLENGE_TTL_MS: number;
|
|
7
|
+
/** What the challenge route returns. */
|
|
8
|
+
export interface ProofOfWorkChallenge {
|
|
9
|
+
challenge: string;
|
|
10
|
+
difficulty: number;
|
|
11
|
+
expiresAt: string;
|
|
12
|
+
}
|
|
13
|
+
/** The signed body of a challenge. */
|
|
14
|
+
export interface ProofOfWorkChallengeBody {
|
|
15
|
+
nonce: string;
|
|
16
|
+
difficulty: number;
|
|
17
|
+
/** Expiry, epoch ms. */
|
|
18
|
+
exp: number;
|
|
19
|
+
}
|
|
20
|
+
/** A client's answer. */
|
|
21
|
+
export interface ProofOfWorkSolution {
|
|
22
|
+
challenge: string;
|
|
23
|
+
nonce: string;
|
|
24
|
+
}
|
|
25
|
+
export type ProofOfWorkRefusal = 'malformed' | 'bad_signature' | 'expired' | 'too_easy' | 'insufficient_work';
|
|
26
|
+
export type ProofOfWorkVerdict = {
|
|
27
|
+
ok: true;
|
|
28
|
+
key: string;
|
|
29
|
+
expiresAt: number;
|
|
30
|
+
difficulty: number;
|
|
31
|
+
} | {
|
|
32
|
+
ok: false;
|
|
33
|
+
reason: ProofOfWorkRefusal;
|
|
34
|
+
};
|
|
35
|
+
/** Number of leading zero BITS in `bytes`. */
|
|
36
|
+
export declare function leadingZeroBits(bytes: Uint8Array): number;
|
|
37
|
+
/** The hash a solution is judged on: `sha256("<challenge>:<nonce>")`. */
|
|
38
|
+
export declare function proofOfWorkHash(challenge: string, nonce: string): Buffer;
|
|
39
|
+
/** The single-use key for a challenge (hex sha256 of the challenge string). */
|
|
40
|
+
export declare function challengeKey(challenge: string): string;
|
|
41
|
+
/** Clamp a configured difficulty into [1, {@link POW_MAX_DIFFICULTY}]. */
|
|
42
|
+
export declare function clampDifficulty(difficulty: number): number;
|
|
43
|
+
/** Issue a fresh signed challenge. */
|
|
44
|
+
export declare function createProofOfWorkChallenge(secret: string, opts?: {
|
|
45
|
+
difficulty?: number;
|
|
46
|
+
ttlMs?: number;
|
|
47
|
+
now?: number;
|
|
48
|
+
}): ProofOfWorkChallenge;
|
|
49
|
+
/**
|
|
50
|
+
* Decode a challenge and check its signature. Null when it is malformed or
|
|
51
|
+
* was not signed with `secret` (expiry is NOT checked here).
|
|
52
|
+
*/
|
|
53
|
+
export declare function parseProofOfWorkChallenge(challenge: string, secret: string): ProofOfWorkChallengeBody | null;
|
|
54
|
+
/**
|
|
55
|
+
* Verify a solution: a genuine, unexpired challenge (signed with `secret`),
|
|
56
|
+
* at least `minDifficulty` hard, whose hash with `nonce` has enough leading
|
|
57
|
+
* zero bits. Does NOT enforce single use — store {@link ProofOfWorkVerdict.key}.
|
|
58
|
+
*/
|
|
59
|
+
export declare function verifyProofOfWork(solution: Partial<ProofOfWorkSolution> | null | undefined, secret: string, opts?: {
|
|
60
|
+
now?: number;
|
|
61
|
+
minDifficulty?: number;
|
|
62
|
+
}): ProofOfWorkVerdict;
|
|
63
|
+
/**
|
|
64
|
+
* Find a nonce for `challenge` (tests, the CLI). Counts up from 0; throws
|
|
65
|
+
* after `maxIterations` so a mistaken difficulty can't spin forever.
|
|
66
|
+
*/
|
|
67
|
+
export declare function solveProofOfWork(challenge: string, difficulty: number, opts?: {
|
|
68
|
+
maxIterations?: number;
|
|
69
|
+
}): string;
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Self-hosted hashcash proof-of-work for the anonymous plugin submission API
|
|
5
|
+
* (docs/plugin-publishing.md): no third-party captcha, so it
|
|
6
|
+
* works air-gapped.
|
|
7
|
+
*
|
|
8
|
+
* A CHALLENGE is `base64url(JSON{ nonce, difficulty, exp }) + '.' +
|
|
9
|
+
* base64url(HMAC-SHA256(body, secret))` — stateless, so any replica can verify
|
|
10
|
+
* one another replica issued. A SOLUTION is a decimal-string `nonce` such that
|
|
11
|
+
* `sha256("<challenge>:<nonce>")` starts with at least `difficulty` zero BITS.
|
|
12
|
+
* Single use is the caller's job (a Redis `SET NX` on {@link challengeKey}
|
|
13
|
+
* with the remaining lifetime as TTL): nothing here remembers anything.
|
|
14
|
+
*
|
|
15
|
+
* Pure and dependency-free apart from node:crypto, so the frontend can mirror
|
|
16
|
+
* the algorithm exactly (its solver runs in a Web Worker with crypto.subtle)
|
|
17
|
+
* and the CLI and tests can solve with {@link solveProofOfWork}.
|
|
18
|
+
*/
|
|
19
|
+
import { createHash, createHmac, randomBytes, timingSafeEqual } from 'crypto';
|
|
20
|
+
/** Default leading-zero-bit difficulty (≈1M hashes; a second or two in a browser). */
|
|
21
|
+
export const POW_DEFAULT_DIFFICULTY = 20;
|
|
22
|
+
/** Hard ceiling on a difficulty an operator can configure. */
|
|
23
|
+
export const POW_MAX_DIFFICULTY = 32;
|
|
24
|
+
/** How long a challenge stays solvable. */
|
|
25
|
+
export const POW_CHALLENGE_TTL_MS = 10 * 60_000;
|
|
26
|
+
/** A nonce is a decimal string of at most this many digits. */
|
|
27
|
+
const NONCE_MAX_DIGITS = 20;
|
|
28
|
+
/** A challenge string is never longer than this (bounds hashing work on garbage input). */
|
|
29
|
+
const CHALLENGE_MAX_LENGTH = 512;
|
|
30
|
+
const b64url = (buf) => buf.toString('base64url');
|
|
31
|
+
function sign(body, secret) {
|
|
32
|
+
return b64url(createHmac('sha256', secret).update(body).digest());
|
|
33
|
+
}
|
|
34
|
+
/** Number of leading zero BITS in `bytes`. */
|
|
35
|
+
export function leadingZeroBits(bytes) {
|
|
36
|
+
let bits = 0;
|
|
37
|
+
for (const byte of bytes) {
|
|
38
|
+
if (byte === 0) {
|
|
39
|
+
bits += 8;
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
// Math.clz32 counts over 32 bits; a byte occupies the low 8.
|
|
43
|
+
return bits + Math.clz32(byte) - 24;
|
|
44
|
+
}
|
|
45
|
+
return bits;
|
|
46
|
+
}
|
|
47
|
+
/** The hash a solution is judged on: `sha256("<challenge>:<nonce>")`. */
|
|
48
|
+
export function proofOfWorkHash(challenge, nonce) {
|
|
49
|
+
return createHash('sha256').update(`${challenge}:${nonce}`).digest();
|
|
50
|
+
}
|
|
51
|
+
/** The single-use key for a challenge (hex sha256 of the challenge string). */
|
|
52
|
+
export function challengeKey(challenge) {
|
|
53
|
+
return createHash('sha256').update(challenge).digest('hex');
|
|
54
|
+
}
|
|
55
|
+
/** Clamp a configured difficulty into [1, {@link POW_MAX_DIFFICULTY}]. */
|
|
56
|
+
export function clampDifficulty(difficulty) {
|
|
57
|
+
if (!Number.isFinite(difficulty))
|
|
58
|
+
return POW_DEFAULT_DIFFICULTY;
|
|
59
|
+
return Math.min(POW_MAX_DIFFICULTY, Math.max(1, Math.floor(difficulty)));
|
|
60
|
+
}
|
|
61
|
+
/** Issue a fresh signed challenge. */
|
|
62
|
+
export function createProofOfWorkChallenge(secret, opts = {}) {
|
|
63
|
+
if (!secret)
|
|
64
|
+
throw new Error('A proof-of-work secret is required');
|
|
65
|
+
const now = opts.now ?? Date.now();
|
|
66
|
+
const body = {
|
|
67
|
+
nonce: b64url(randomBytes(16)),
|
|
68
|
+
difficulty: clampDifficulty(opts.difficulty ?? POW_DEFAULT_DIFFICULTY),
|
|
69
|
+
exp: now + (opts.ttlMs ?? POW_CHALLENGE_TTL_MS),
|
|
70
|
+
};
|
|
71
|
+
const encoded = b64url(Buffer.from(JSON.stringify(body), 'utf8'));
|
|
72
|
+
return { challenge: `${encoded}.${sign(encoded, secret)}`, difficulty: body.difficulty, expiresAt: new Date(body.exp).toISOString() };
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Decode a challenge and check its signature. Null when it is malformed or
|
|
76
|
+
* was not signed with `secret` (expiry is NOT checked here).
|
|
77
|
+
*/
|
|
78
|
+
export function parseProofOfWorkChallenge(challenge, secret) {
|
|
79
|
+
if (typeof challenge !== 'string' || challenge.length === 0 || challenge.length > CHALLENGE_MAX_LENGTH)
|
|
80
|
+
return null;
|
|
81
|
+
const dot = challenge.indexOf('.');
|
|
82
|
+
if (dot <= 0 || dot !== challenge.lastIndexOf('.'))
|
|
83
|
+
return null;
|
|
84
|
+
const encoded = challenge.slice(0, dot);
|
|
85
|
+
const given = Buffer.from(challenge.slice(dot + 1), 'base64url');
|
|
86
|
+
const expected = Buffer.from(sign(encoded, secret), 'base64url');
|
|
87
|
+
if (given.length !== expected.length || !timingSafeEqual(given, expected))
|
|
88
|
+
return null;
|
|
89
|
+
try {
|
|
90
|
+
const body = JSON.parse(Buffer.from(encoded, 'base64url').toString('utf8'));
|
|
91
|
+
if (typeof body.nonce !== 'string' || typeof body.difficulty !== 'number' || typeof body.exp !== 'number')
|
|
92
|
+
return null;
|
|
93
|
+
if (!Number.isInteger(body.difficulty) || body.difficulty < 1 || body.difficulty > POW_MAX_DIFFICULTY)
|
|
94
|
+
return null;
|
|
95
|
+
return { nonce: body.nonce, difficulty: body.difficulty, exp: body.exp };
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Verify a solution: a genuine, unexpired challenge (signed with `secret`),
|
|
103
|
+
* at least `minDifficulty` hard, whose hash with `nonce` has enough leading
|
|
104
|
+
* zero bits. Does NOT enforce single use — store {@link ProofOfWorkVerdict.key}.
|
|
105
|
+
*/
|
|
106
|
+
export function verifyProofOfWork(solution, secret, opts = {}) {
|
|
107
|
+
const challenge = solution?.challenge;
|
|
108
|
+
const nonce = solution?.nonce;
|
|
109
|
+
if (typeof challenge !== 'string' || typeof nonce !== 'string')
|
|
110
|
+
return { ok: false, reason: 'malformed' };
|
|
111
|
+
if (!/^\d+$/.test(nonce) || nonce.length > NONCE_MAX_DIGITS)
|
|
112
|
+
return { ok: false, reason: 'malformed' };
|
|
113
|
+
if (!secret)
|
|
114
|
+
return { ok: false, reason: 'bad_signature' };
|
|
115
|
+
const body = parseProofOfWorkChallenge(challenge, secret);
|
|
116
|
+
if (!body)
|
|
117
|
+
return { ok: false, reason: 'bad_signature' };
|
|
118
|
+
if ((opts.now ?? Date.now()) > body.exp)
|
|
119
|
+
return { ok: false, reason: 'expired' };
|
|
120
|
+
if (opts.minDifficulty !== undefined && body.difficulty < clampDifficulty(opts.minDifficulty))
|
|
121
|
+
return { ok: false, reason: 'too_easy' };
|
|
122
|
+
if (leadingZeroBits(proofOfWorkHash(challenge, nonce)) < body.difficulty)
|
|
123
|
+
return { ok: false, reason: 'insufficient_work' };
|
|
124
|
+
return { ok: true, key: challengeKey(challenge), expiresAt: body.exp, difficulty: body.difficulty };
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Find a nonce for `challenge` (tests, the CLI). Counts up from 0; throws
|
|
128
|
+
* after `maxIterations` so a mistaken difficulty can't spin forever.
|
|
129
|
+
*/
|
|
130
|
+
export function solveProofOfWork(challenge, difficulty, opts = {}) {
|
|
131
|
+
const max = opts.maxIterations ?? 2 ** 32;
|
|
132
|
+
for (let i = 0; i < max; i++) {
|
|
133
|
+
const nonce = String(i);
|
|
134
|
+
if (leadingZeroBits(proofOfWorkHash(challenge, nonce)) >= difficulty)
|
|
135
|
+
return nonce;
|
|
136
|
+
}
|
|
137
|
+
throw new Error(`No proof-of-work solution within ${max} iterations`);
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvb2Ytb2Ytd29yay5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9wcm9vZi1vZi13b3JrLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEM7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBRUgsT0FBTyxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsV0FBVyxFQUFFLGVBQWUsRUFBRSxNQUFNLFFBQVEsQ0FBQztBQUU5RSxzRkFBc0Y7QUFDdEYsTUFBTSxDQUFDLE1BQU0sc0JBQXNCLEdBQUcsRUFBRSxDQUFDO0FBQ3pDLDhEQUE4RDtBQUM5RCxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxFQUFFLENBQUM7QUFDckMsMkNBQTJDO0FBQzNDLE1BQU0sQ0FBQyxNQUFNLG9CQUFvQixHQUFHLEVBQUUsR0FBRyxNQUFNLENBQUM7QUFDaEQsK0RBQStEO0FBQy9ELE1BQU0sZ0JBQWdCLEdBQUcsRUFBRSxDQUFDO0FBQzVCLDJGQUEyRjtBQUMzRixNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQTZCakMsTUFBTSxNQUFNLEdBQUcsQ0FBQyxHQUFXLEVBQVUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLENBQUM7QUFFbEUsU0FBUyxJQUFJLENBQUMsSUFBWSxFQUFFLE1BQWM7SUFDeEMsT0FBTyxNQUFNLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztBQUNwRSxDQUFDO0FBRUQsOENBQThDO0FBQzlDLE1BQU0sVUFBVSxlQUFlLENBQUMsS0FBaUI7SUFDL0MsSUFBSSxJQUFJLEdBQUcsQ0FBQyxDQUFDO0lBQ2IsS0FBSyxNQUFNLElBQUksSUFBSSxLQUFLLEVBQUUsQ0FBQztRQUN6QixJQUFJLElBQUksS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUNm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LENBQUMsZUFBZSxDQUFDLFNBQVMsRUFBRSxLQUFLLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxVQUFVO1FBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLG1CQUFtQixFQUFFLENBQUM7SUFDNUgsT0FBTyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLFlBQVksQ0FBQyxTQUFTLENBQUMsRUFBRSxTQUFTLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRSxVQUFVLEVBQUUsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO0FBQ3RHLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsZ0JBQWdCLENBQUMsU0FBaUIsRUFBRSxVQUFrQixFQUFFLElBQUksR0FBK0IsRUFBRTtJQUMzRyxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsYUFBYSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDMUMsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQzdCLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN4QixJQUFJLGVBQWUsQ0FBQyxlQUFlLENBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxDQUFDLElBQUksVUFBVTtZQUFFLE9BQU8sS0FBSyxDQUFDO0lBQ3JGLENBQUM7SUFDRCxNQUFNLElBQUksS0FBSyxDQUFDLG9DQUFvQyxHQUFHLGFBQWEsQ0FBQyxDQUFDO0FBQ3hFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuLyoqXG4gKiBTZWxmLWhvc3RlZCBoYXNoY2FzaCBwcm9vZi1vZi13b3JrIGZvciB0aGUgYW5vbnltb3VzIHBsdWdpbiBzdWJtaXNzaW9uIEFQSVxuICogKGRvY3MvcGx1Z2luLXB1Ymxpc2hpbmcubWQpOiBubyB0aGlyZC1wYXJ0eSBjYXB0Y2hhLCBzbyBpdFxuICogd29ya3MgYWlyLWdhcHBlZC5cbiAqXG4gKiBBIENIQUxMRU5HRSBpcyBgYmFzZTY0dXJsKEpTT057IG5vbmNlLCBkaWZmaWN1bHR5LCBleHAgfSkgKyAnLicgK1xuICogYmFzZTY0dXJsKEhNQUMtU0hBMjU2KGJvZHksIHNlY3JldCkpYCDigJQgc3RhdGVsZXNzLCBzbyBhbnkgcmVwbGljYSBjYW4gdmVyaWZ5XG4gKiBvbmUgYW5vdGhlciByZXBsaWNhIGlzc3VlZC4gQSBTT0xVVElPTiBpcyBhIGRlY2ltYWwtc3RyaW5nIGBub25jZWAgc3VjaCB0aGF0XG4gKiBgc2hhMjU2KFwiPGNoYWxsZW5nZT46PG5vbmNlPlwiKWAgc3RhcnRzIHdpdGggYXQgbGVhc3QgYGRpZmZpY3VsdHlgIHplcm8gQklUUy5cbiAqIFNpbmdsZSB1c2UgaXMgdGhlIGNhbGxlcidzIGpvYiAoYSBSZWRpcyBgU0VUIE5YYCBvbiB7QGxpbmsgY2hhbGxlbmdlS2V5fVxuICogd2l0aCB0aGUgcmVtYWluaW5nIGxpZmV0aW1lIGFzIFRUTCk6IG5vdGhpbmcgaGVyZSByZW1lbWJlcnMgYW55dGhpbmcuXG4gKlxuICogUHVyZSBhbmQgZGVwZW5kZW5jeS1mcmVlIGFwYXJ0IGZyb20gbm9kZTpjcnlwdG8sIHNvIHRoZSBmcm9udGVuZCBjYW4gbWlycm9yXG4gKiB0aGUgYWxnb3JpdGhtIGV4YWN0bHkgKGl0cyBzb2x2ZXIgcnVucyBpbiBhIFdlYiBXb3JrZXIgd2l0aCBjcnlwdG8uc3VidGxlKVxuICogYW5kIHRoZSBDTEkgYW5kIHRlc3RzIGNhbiBzb2x2ZSB3aXRoIHtAbGluayBzb2x2ZVByb29mT2ZXb3JrfS5cbiAqL1xuXG5pbXBvcnQgeyBjcmVhdGVIYXNoLCBjcmVhdGVIbWFjLCByYW5kb21CeXRlcywgdGltaW5nU2FmZUVxdWFsIH0gZnJvbSAnY3J5cHRvJztcblxuLyoqIERlZmF1bHQgbGVhZGluZy16ZXJvLWJpdCBkaWZmaWN1bHR5ICjiiYgxTSBoYXNoZXM7IGEgc2Vjb25kIG9yIHR3byBpbiBhIGJyb3dzZXIpLiAqL1xuZXhwb3J0IGNvbnN0IFBPV19ERUZBVUxUX0RJRkZJQ1VMVFkgPSAyMDtcbi8qKiBIYXJkIGNlaWxpbmcgb24gYSBkaWZmaWN1bHR5IGFuIG9wZXJhdG9yIGNhbiBjb25maWd1cmUuICovXG5leHBvcnQgY29uc3QgUE9XX01BWF9ESUZGSUNVTFRZID0gMzI7XG4vKiogSG93IGxvbmcgYSBjaGFsbGVuZ2Ugc3RheXMgc29sdmFibGUuICovXG5leHBvcnQgY29uc3QgUE9XX0NIQUxMRU5HRV9UVExfTVMgPSAxMCAqIDYwXzAwMDtcbi8qKiBBIG5vbmNlIGlzIGEgZGVjaW1hbCBzdHJpbmcgb2YgYXQgbW9zdCB0aGlzIG1hbnkgZGlnaXRzLiAqL1xuY29uc3QgTk9OQ0VfTUFYX0RJR0lUUyA9IDIwO1xuLyoqIEEgY2hhbGxlbmdlIHN0cmluZyBpcyBuZXZlciBsb25nZXIgdGhhbiB0aGlzIChib3VuZHMgaGFzaGluZyB3b3JrIG9uIGdhcmJhZ2UgaW5wdXQpLiAqL1xuY29uc3QgQ0hBTExFTkdFX01BWF9MRU5HVEggPSA1MTI7XG5cbi8qKiBXaGF0IHRoZSBjaGFsbGVuZ2Ugcm91dGUgcmV0dXJucy4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUHJvb2ZPZldvcmtDaGFsbGVuZ2Uge1xuICBjaGFsbGVuZ2U6IHN0cmluZztcbiAgZGlmZmljdWx0eTogbnVtYmVyO1xuICBleHBpcmVzQXQ6IHN0cmluZztcbn1cblxuLyoqIFRoZSBzaWduZWQgYm9keSBvZiBhIGNoYWxsZW5nZS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUHJvb2ZPZldvcmtDaGFsbGVuZ2VCb2R5IHtcbiAgbm9uY2U6IHN0cmluZztcbiAgZGlmZmljdWx0eTogbnVtYmVyO1xuICAvKiogRXhwaXJ5LCBlcG9jaCBtcy4gKi9cbiAgZXhwOiBudW1iZXI7XG59XG5cbi8qKiBBIGNsaWVudCdzIGFuc3dlci4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUHJvb2ZPZldvcmtTb2x1dGlvbiB7XG4gIGNoYWxsZW5nZTogc3RyaW5nO1xuICBub25jZTogc3RyaW5nO1xufVxuXG5leHBvcnQgdHlwZSBQcm9vZk9mV29ya1JlZnVzYWwgPSAnbWFsZm9ybWVkJyB8ICdiYWRfc2lnbmF0dXJlJyB8ICdleHBpcmVkJyB8ICd0b29fZWFzeScgfCAnaW5zdWZmaWNpZW50X3dvcmsnO1xuXG5leHBvcnQgdHlwZSBQcm9vZk9mV29ya1ZlcmRpY3QgPVxuICB8IHsgb2s6IHRydWU7IGtleTogc3RyaW5nOyBleHBpcmVzQXQ6IG51bWJlcjsgZGlmZmljdWx0eTogbnVtYmVyIH1cbiAgfCB7IG9rOiBmYWxzZTsgcmVhc29uOiBQcm9vZk9mV29ya1JlZnVzYWwgfTtcblxuY29uc3QgYjY0dXJsID0gKGJ1ZjogQnVmZmVyKTogc3RyaW5nID0+IGJ1Zi50b1N0cmluZygnYmFzZTY0dXJsJyk7XG5cbmZ1bmN0aW9uIHNpZ24oYm9keTogc3RyaW5nLCBzZWNyZXQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBiNjR1cmwoY3JlYXRlSG1hYygnc2hhMjU2Jywgc2VjcmV0KS51cGRhdGUoYm9keSkuZGlnZXN0KCkpO1xufVxuXG4vKiogTnVtYmVyIG9mIGxlYWRpbmcgemVybyBCSVRTIGluIGBieXRlc2AuICovXG5leHBvcnQgZnVuY3Rpb24gbGVhZGluZ1plcm9CaXRzKGJ5dGVzOiBVaW50OEFycmF5KTogbnVtYmVyIHtcbiAgbGV0IGJpdHMgPSAwO1xuICBmb3IgKGNvbnN0IGJ5dGUgb2YgYnl0ZXMpIHtcbiAgICBpZiAoYnl0ZSA9PT0gMCkge1xuICAgICAgYml0cyArPSA4O1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIC8vIE1hdGguY2x6MzIgY291bnRzIG92ZXIgMzIgYml0czsgYSBieXRlIG9jY3VwaWVzIHRoZSBsb3cgOC5cbiAgICByZXR1cm4gYml0cyArIE1hdGguY2x6MzIoYnl0ZSkgLSAyNDtcbiAgfVxuICByZXR1cm4gYml0cztcbn1cblxuLyoqIFRoZSBoYXNoIGEgc29sdXRpb24gaXMganVkZ2VkIG9uOiBgc2hhMjU2KFwiPGNoYWxsZW5nZT46PG5vbmNlPlwiKWAuICovXG5leHBvcnQgZnVuY3Rpb24gcHJvb2ZPZldvcmtIYXNoKGNoYWxsZW5nZTogc3RyaW5nLCBub25jZTogc3RyaW5nKTogQnVmZmVyIHtcbiAgcmV0dXJuIGNyZWF0ZUhhc2goJ3NoYTI1NicpLnVwZGF0ZShgJHtjaGFsbGVuZ2V9OiR7bm9uY2V9YCkuZGlnZXN0KCk7XG59XG5cbi8qKiBUaGUgc2luZ2xlLXVzZSBrZXkgZm9yIGEgY2hhbGxlbmdlIChoZXggc2hhMjU2IG9mIHRoZSBjaGFsbGVuZ2Ugc3RyaW5nKS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjaGFsbGVuZ2VLZXkoY2hhbGxlbmdlOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gY3JlYXRlSGFzaCgnc2hhMjU2JykudXBkYXRlKGNoYWxsZW5nZSkuZGlnZXN0KCdoZXgnKTtcbn1cblxuLyoqIENsYW1wIGEgY29uZmlndXJlZCBkaWZmaWN1bHR5IGludG8gWzEsIHtAbGluayBQT1dfTUFYX0RJRkZJQ1VMVFl9XS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjbGFtcERpZmZpY3VsdHkoZGlmZmljdWx0eTogbnVtYmVyKTogbnVtYmVyIHtcbiAgaWYgKCFOdW1iZXIuaXNGaW5pdGUoZGlmZmljdWx0eSkpIHJldHVybiBQT1dfREVGQVVMVF9ESUZGSUNVTFRZO1xuICByZXR1cm4gTWF0aC5taW4oUE9XX01BWF9ESUZGSUNVTFRZLCBNYXRoLm1heCgxLCBNYXRoLmZsb29yKGRpZmZpY3VsdHkpKSk7XG59XG5cbi8qKiBJc3N1ZSBhIGZyZXNoIHNpZ25lZCBjaGFsbGVuZ2UuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlUHJvb2ZPZldvcmtDaGFsbGVuZ2UoXG4gIHNlY3JldDogc3RyaW5nLFxuICBvcHRzOiB7IGRpZmZpY3VsdHk/OiBudW1iZXI7IHR0bE1zPzogbnVtYmVyOyBub3c/OiBudW1iZXIgfSA9IHt9LFxuKTogUHJvb2ZPZldvcmtDaGFsbGVuZ2Uge1xuICBpZiAoIXNlY3JldCkgdGhyb3cgbmV3IEVycm9yKCdBIHByb29mLW9mLXdvcmsgc2VjcmV0IGlzIHJlcXVpcmVkJyk7XG4gIGNvbnN0IG5vdyA9IG9wdHMubm93ID8/IERhdGUubm93KCk7XG4gIGNvbnN0IGJvZHk6IFByb29mT2ZXb3JrQ2hhbGxlbmdlQm9keSA9IHtcbiAgICBub25jZTogYjY0dXJsKHJhbmRvbUJ5dGVzKDE2KSksXG4gICAgZGlmZmljdWx0eTogY2xhbXBEaWZmaWN1bHR5KG9wdHMuZGlmZmljdWx0eSA/PyBQT1dfREVGQVVMVF9ESUZGSUNVTFRZKSxcbiAgICBleHA6IG5vdyArIChvcHRzLnR0bE1zID8/IFBPV19DSEFMTEVOR0VfVFRMX01TKSxcbiAgfTtcbiAgY29uc3QgZW5jb2RlZCA9IGI2NHVybChCdWZmZXIuZnJvbShKU09OLnN0cmluZ2lmeShib2R5KSwgJ3V0ZjgnKSk7XG4gIHJldHVybiB7IGNoYWxsZW5nZTogYCR7ZW5jb2RlZH0uJHtzaWduKGVuY29kZWQsIHNlY3JldCl9YCwgZGlmZmljdWx0eTogYm9keS5kaWZmaWN1bHR5LCBleHBpcmVzQXQ6IG5ldyBEYXRlKGJvZHkuZXhwKS50b0lTT1N0cmluZygpIH07XG59XG5cbi8qKlxuICogRGVjb2RlIGEgY2hhbGxlbmdlIGFuZCBjaGVjayBpdHMgc2lnbmF0dXJlLiBOdWxsIHdoZW4gaXQgaXMgbWFsZm9ybWVkIG9yXG4gKiB3YXMgbm90IHNpZ25lZCB3aXRoIGBzZWNyZXRgIChleHBpcnkgaXMgTk9UIGNoZWNrZWQgaGVyZSkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZVByb29mT2ZXb3JrQ2hhbGxlbmdlKGNoYWxsZW5nZTogc3RyaW5nLCBzZWNyZXQ6IHN0cmluZyk6IFByb29mT2ZXb3JrQ2hhbGxlbmdlQm9keSB8IG51bGwge1xuICBpZiAodHlwZW9mIGNoYWxsZW5nZSAhPT0gJ3N0cmluZycgfHwgY2hhbGxlbmdlLmxlbmd0aCA9PT0gMCB8fCBjaGFsbGVuZ2UubGVuZ3RoID4gQ0hBTExFTkdFX01BWF9MRU5HVEgpIHJldHVybiBudWxsO1xuICBjb25zdCBkb3QgPSBjaGFsbGVuZ2UuaW5kZXhPZignLicpO1xuICBpZiAoZG90IDw9IDAgfHwgZG90ICE9PSBjaGFsbGVuZ2UubGFzdEluZGV4T2YoJy4nKSkgcmV0dXJuIG51bGw7XG4gIGNvbnN0IGVuY29kZWQgPSBjaGFsbGVuZ2Uuc2xpY2UoMCwgZG90KTtcbiAgY29uc3QgZ2l2ZW4gPSBCdWZmZXIuZnJvbShjaGFsbGVuZ2Uuc2xpY2UoZG90ICsgMSksICdiYXNlNjR1cmwnKTtcbiAgY29uc3QgZXhwZWN0ZWQgPSBCdWZmZXIuZnJvbShzaWduKGVuY29kZWQsIHNlY3JldCksICdiYXNlNjR1cmwnKTtcbiAgaWYgKGdpdmVuLmxlbmd0aCAhPT0gZXhwZWN0ZWQubGVuZ3RoIHx8ICF0aW1pbmdTYWZlRXF1YWwoZ2l2ZW4sIGV4cGVjdGVkKSkgcmV0dXJuIG51bGw7XG4gIHRyeSB7XG4gICAgY29uc3QgYm9keSA9IEpTT04ucGFyc2UoQnVmZmVyLmZyb20oZW5jb2RlZCwgJ2Jhc2U2NHVybCcpLnRvU3RyaW5nKCd1dGY4JykpIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAgIGlmICh0eXBlb2YgYm9keS5ub25jZSAhPT0gJ3N0cmluZycgfHwgdHlwZW9mIGJvZHkuZGlmZmljdWx0eSAhPT0gJ251bWJlcicgfHwgdHlwZW9mIGJvZHkuZXhwICE9PSAnbnVtYmVyJykgcmV0dXJuIG51bGw7XG4gICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGJvZHkuZGlmZmljdWx0eSkgfHwgYm9keS5kaWZmaWN1bHR5IDwgMSB8fCBib2R5LmRpZmZpY3VsdHkgPiBQT1dfTUFYX0RJRkZJQ1VMVFkpIHJldHVybiBudWxsO1xuICAgIHJldHVybiB7IG5vbmNlOiBib2R5Lm5vbmNlLCBkaWZmaWN1bHR5OiBib2R5LmRpZmZpY3VsdHksIGV4cDogYm9keS5leHAgfTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbn1cblxuLyoqXG4gKiBWZXJpZnkgYSBzb2x1dGlvbjogYSBnZW51aW5lLCB1bmV4cGlyZWQgY2hhbGxlbmdlIChzaWduZWQgd2l0aCBgc2VjcmV0YCksXG4gKiBhdCBsZWFzdCBgbWluRGlmZmljdWx0eWAgaGFyZCwgd2hvc2UgaGFzaCB3aXRoIGBub25jZWAgaGFzIGVub3VnaCBsZWFkaW5nXG4gKiB6ZXJvIGJpdHMuIERvZXMgTk9UIGVuZm9yY2Ugc2luZ2xlIHVzZSDigJQgc3RvcmUge0BsaW5rIFByb29mT2ZXb3JrVmVyZGljdC5rZXl9LlxuICovXG5leHBvcnQgZnVuY3Rpb24gdmVyaWZ5UHJvb2ZPZldvcmsoXG4gIHNvbHV0aW9uOiBQYXJ0aWFsPFByb29mT2ZXb3JrU29sdXRpb24+IHwgbnVsbCB8IHVuZGVmaW5lZCxcbiAgc2VjcmV0OiBzdHJpbmcsXG4gIG9wdHM6IHsgbm93PzogbnVtYmVyOyBtaW5EaWZmaWN1bHR5PzogbnVtYmVyIH0gPSB7fSxcbik6IFByb29mT2ZXb3JrVmVyZGljdCB7XG4gIGNvbnN0IGNoYWxsZW5nZSA9IHNvbHV0aW9uPy5jaGFsbGVuZ2U7XG4gIGNvbnN0IG5vbmNlID0gc29sdXRpb24/Lm5vbmNlO1xuICBpZiAodHlwZW9mIGNoYWxsZW5nZSAhPT0gJ3N0cmluZycgfHwgdHlwZW9mIG5vbmNlICE9PSAnc3RyaW5nJykgcmV0dXJuIHsgb2s6IGZhbHNlLCByZWFzb246ICdtYWxmb3JtZWQnIH07XG4gIGlmICghL15cXGQrJC8udGVzdChub25jZSkgfHwgbm9uY2UubGVuZ3RoID4gTk9OQ0VfTUFYX0RJR0lUUykgcmV0dXJuIHsgb2s6IGZhbHNlLCByZWFzb246ICdtYWxmb3JtZWQnIH07XG4gIGlmICghc2VjcmV0KSByZXR1cm4geyBvazogZmFsc2UsIHJlYXNvbjogJ2JhZF9zaWduYXR1cmUnIH07XG4gIGNvbnN0IGJvZHkgPSBwYXJzZVByb29mT2ZXb3JrQ2hhbGxlbmdlKGNoYWxsZW5nZSwgc2VjcmV0KTtcbiAgaWYgKCFib2R5KSByZXR1cm4geyBvazogZmFsc2UsIHJlYXNvbjogJ2JhZF9zaWduYXR1cmUnIH07XG4gIGlmICgob3B0cy5ub3cgPz8gRGF0ZS5ub3coKSkgPiBib2R5LmV4cCkgcmV0dXJuIHsgb2s6IGZhbHNlLCByZWFzb246ICdleHBpcmVkJyB9O1xuICBpZiAob3B0cy5taW5EaWZmaWN1bHR5ICE9PSB1bmRlZmluZWQgJiYgYm9keS5kaWZmaWN1bHR5IDwgY2xhbXBEaWZmaWN1bHR5KG9wdHMubWluRGlmZmljdWx0eSkpIHJldHVybiB7IG9rOiBmYWxzZSwgcmVhc29uOiAndG9vX2Vhc3knIH07XG4gIGlmIChsZWFkaW5nWmVyb0JpdHMocHJvb2ZPZldvcmtIYXNoKGNoYWxsZW5nZSwgbm9uY2UpKSA8IGJvZHkuZGlmZmljdWx0eSkgcmV0dXJuIHsgb2s6IGZhbHNlLCByZWFzb246ICdpbnN1ZmZpY2llbnRfd29yaycgfTtcbiAgcmV0dXJuIHsgb2s6IHRydWUsIGtleTogY2hhbGxlbmdlS2V5KGNoYWxsZW5nZSksIGV4cGlyZXNBdDogYm9keS5leHAsIGRpZmZpY3VsdHk6IGJvZHkuZGlmZmljdWx0eSB9O1xufVxuXG4vKipcbiAqIEZpbmQgYSBub25jZSBmb3IgYGNoYWxsZW5nZWAgKHRlc3RzLCB0aGUgQ0xJKS4gQ291bnRzIHVwIGZyb20gMDsgdGhyb3dzXG4gKiBhZnRlciBgbWF4SXRlcmF0aW9uc2Agc28gYSBtaXN0YWtlbiBkaWZmaWN1bHR5IGNhbid0IHNwaW4gZm9yZXZlci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNvbHZlUHJvb2ZPZldvcmsoY2hhbGxlbmdlOiBzdHJpbmcsIGRpZmZpY3VsdHk6IG51bWJlciwgb3B0czogeyBtYXhJdGVyYXRpb25zPzogbnVtYmVyIH0gPSB7fSk6IHN0cmluZyB7XG4gIGNvbnN0IG1heCA9IG9wdHMubWF4SXRlcmF0aW9ucyA/PyAyICoqIDMyO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IG1heDsgaSsrKSB7XG4gICAgY29uc3Qgbm9uY2UgPSBTdHJpbmcoaSk7XG4gICAgaWYgKGxlYWRpbmdaZXJvQml0cyhwcm9vZk9mV29ya0hhc2goY2hhbGxlbmdlLCBub25jZSkpID49IGRpZmZpY3VsdHkpIHJldHVybiBub25jZTtcbiAgfVxuICB0aHJvdyBuZXcgRXJyb3IoYE5vIHByb29mLW9mLXdvcmsgc29sdXRpb24gd2l0aGluICR7bWF4fSBpdGVyYXRpb25zYCk7XG59XG4iXX0=
|
package/lib/utils/response.d.ts
CHANGED
|
@@ -73,11 +73,10 @@ export declare function sendPaginatedNested<T>(res: Response, dataKey: string, d
|
|
|
73
73
|
* Extracts PostgreSQL error codes, details, hints, and constraint names
|
|
74
74
|
* from database errors for better error messages.
|
|
75
75
|
*
|
|
76
|
-
* Only a genuine Postgres error yields a `dbCode
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
* Postgres logs. The transport code is not lost — callers log the error message
|
|
76
|
+
* Only a genuine Postgres error yields a `dbCode`: reporting any `.code` as one
|
|
77
|
+
* would log a transport failure (`ECONNRESET` when the pooler drops out of the
|
|
78
|
+
* Service endpoints, say) as `{"db":{"dbCode":"ECONNRESET"}}` and send readers
|
|
79
|
+
* hunting through clean Postgres logs. The transport code is not lost — callers log the error message
|
|
81
80
|
* itself alongside these details — it just stops claiming to be a DB fault.
|
|
82
81
|
*
|
|
83
82
|
* @param error - Error object from database operation
|
|
@@ -121,5 +120,16 @@ export interface PaginationParams {
|
|
|
121
120
|
sortBy: string;
|
|
122
121
|
sortOrder: 'asc' | 'desc';
|
|
123
122
|
}
|
|
124
|
-
/**
|
|
123
|
+
/** A parsed `?sortBy=&sortOrder=` (default: newest first). */
|
|
124
|
+
export interface SortParams {
|
|
125
|
+
sortBy: string;
|
|
126
|
+
sortOrder: 'asc' | 'desc';
|
|
127
|
+
}
|
|
128
|
+
/** Parse `?sortBy=&sortOrder=`; defaults to `createdAt` descending. */
|
|
129
|
+
export declare function parseSort(query: Record<string, unknown>): SortParams;
|
|
130
|
+
/**
|
|
131
|
+
* The default list-route window + sort: {@link parsePage} with a page of 10
|
|
132
|
+
* (capped at `MAX_PAGE_LIMIT`, offset capped at `MAX_PAGE_OFFSET` — deep paging
|
|
133
|
+
* uses the cursor API) plus {@link parseSort}.
|
|
134
|
+
*/
|
|
125
135
|
export declare function parsePaginationParams(query: Record<string, unknown>): PaginationParams;
|
package/lib/utils/response.js
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
import { createLogger } from './logger.js';
|
|
4
4
|
import { ErrorCode } from '../types/error-codes.js';
|
|
5
|
-
import { MAX_PAGE_LIMIT
|
|
5
|
+
import { MAX_PAGE_LIMIT } from '../validation/common-schemas.js';
|
|
6
|
+
import { parsePage } from './params.js';
|
|
6
7
|
const logger = createLogger('response');
|
|
7
8
|
/**
|
|
8
9
|
* Send a standardized success response.
|
|
@@ -149,11 +150,10 @@ const NODE_ERRNO_PATTERN = /^E/;
|
|
|
149
150
|
* Extracts PostgreSQL error codes, details, hints, and constraint names
|
|
150
151
|
* from database errors for better error messages.
|
|
151
152
|
*
|
|
152
|
-
* Only a genuine Postgres error yields a `dbCode
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
* Postgres logs. The transport code is not lost — callers log the error message
|
|
153
|
+
* Only a genuine Postgres error yields a `dbCode`: reporting any `.code` as one
|
|
154
|
+
* would log a transport failure (`ECONNRESET` when the pooler drops out of the
|
|
155
|
+
* Service endpoints, say) as `{"db":{"dbCode":"ECONNRESET"}}` and send readers
|
|
156
|
+
* hunting through clean Postgres logs. The transport code is not lost — callers log the error message
|
|
157
157
|
* itself alongside these details — it just stops claiming to be a DB fault.
|
|
158
158
|
*
|
|
159
159
|
* @param error - Error object from database operation
|
|
@@ -235,15 +235,18 @@ export function sendBadRequest(res, message, code = ErrorCode.VALIDATION_ERROR)
|
|
|
235
235
|
export function sendInternalError(res, message, details) {
|
|
236
236
|
sendError(res, 500, message, ErrorCode.INTERNAL_ERROR, details);
|
|
237
237
|
}
|
|
238
|
-
/** Parse
|
|
239
|
-
export function
|
|
240
|
-
const limit = Math.min(Math.max(parseInt(String(query.limit), 10) || 10, 1), MAX_PAGE_LIMIT);
|
|
241
|
-
// Clamp offset too — an unbounded offset forces Postgres to scan+discard huge row
|
|
242
|
-
// counts on hot list endpoints (a cheap DoS amplifier). Deep paging should use the
|
|
243
|
-
// cursor API. Ceiling = MAX_PAGE_OFFSET.
|
|
244
|
-
const offset = Math.min(Math.max(parseInt(String(query.offset), 10) || 0, 0), MAX_PAGE_OFFSET);
|
|
238
|
+
/** Parse `?sortBy=&sortOrder=`; defaults to `createdAt` descending. */
|
|
239
|
+
export function parseSort(query) {
|
|
245
240
|
const sortBy = String(query.sortBy || 'createdAt');
|
|
246
241
|
const sortOrder = String(query.sortOrder || 'desc').toLowerCase() === 'asc' ? 'asc' : 'desc';
|
|
247
|
-
return {
|
|
242
|
+
return { sortBy, sortOrder };
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* The default list-route window + sort: {@link parsePage} with a page of 10
|
|
246
|
+
* (capped at `MAX_PAGE_LIMIT`, offset capped at `MAX_PAGE_OFFSET` — deep paging
|
|
247
|
+
* uses the cursor API) plus {@link parseSort}.
|
|
248
|
+
*/
|
|
249
|
+
export function parsePaginationParams(query) {
|
|
250
|
+
return { ...parsePage(query, { def: 10, max: MAX_PAGE_LIMIT }), ...parseSort(query) };
|
|
248
251
|
}
|
|
249
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzcG9uc2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvcmVzcG9uc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUd0QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRTNDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsY0FBYyxFQUFFLGVBQWUsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBRWxGLE1BQU0sTUFBTSxHQUFHLFlBQVksQ0FBQyxVQUFVLENBQUMsQ0FBQztBQUV4Qzs7Ozs7Ozs7Ozs7OztHQWFHO0FBQ0gsTUFBTSxVQUFVLFdBQVcsQ0FDekIsR0FBYSxFQUNiLFVBQVUsR0FBVyxHQUFHLEVBQ3hCLElBQVEsRUFDUixPQUFnQjtJQUVoQixJQUFJLEdBQUcsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUNwQixNQUFNLENBQUMsSUFBSSxDQUFDLHNEQUFzRCxFQUFFLEVBQUUsVUFBVSxFQUFFLENBQUMsQ0FBQztRQUNwRixPQUFPO0lBQ1QsQ0FBQztJQUVELE1BQU0sUUFBUSxHQUtWO1FBQ0YsT0FBTyxFQUFFLElBQUk7UUFDYixVQUFVO0tBQ1gsQ0FBQztJQUVGLElBQUksSUFBSSxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQ3ZCLFFBQVEsQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO0lBQ3ZCLENBQUM7SUFFRCxJQUFJLE9BQU8sRUFBRSxDQUFDO1FBQ1osUUFBUSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7SUFDN0IsQ0FBQztJQUVELEdBQUcsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0FBQ3hDLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7R0FjRztBQUNILE1BQU0sVUFBVSxTQUFTLENBQ3ZCLEdBQWEsRUFDYixVQUFrQixFQUNsQixPQUFlLEVBQ2YsSUFBeUIsRUFDekIsT0FBaUI7SUFFakIsSUFBSSxHQUFHLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDcEIsTUFBTSxDQUFDLElBQUksQ0FBQyxvREFBb0QsRUFBRSxFQUFFLFVBQVUsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQzNGLE9BQU87SUFDVCxDQUFDO0lBRUQsTUFBTSxRQUFRLEdBTVY7UUFDRixPQUFPLEVBQUUsS0FBSztRQUNkLFVBQVU7UUFDVixPQUFPO0tBQ1IsQ0FBQztJQUVGLElBQUksSUFBSSxFQUFFLENBQUM7UUFDVCxRQUFRLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztJQUN2QixDQUFDO0lBRUQsSUFBSSxPQUFPLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDMUIsUUFBUSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7SUFDN0IsQ0FBQztJQUVELEdBQUcsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0FBQ3hDLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7O0dBWUc7QUFDSCxNQUFNLFVBQVUsaUJBQWlCLENBQy9CLEdBQWEsRUFDYixTQUFpQixFQUNqQixLQUFnQixFQUNoQixPQUFnQixFQUNoQixPQUFnQjtJQUVoQixNQUFNLFNBQVMsR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDO0lBQzNELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxTQUFTLENBQUMsT0FBTyxFQUFFLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUVsRiw0RUFBNEU7SUFDNUUsZ0ZBQWdGO0lBQ2hGLG9FQUFvRTtJQUNwRSxJQUFJLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ3JCLEdBQUcsQ0FBQyxTQUFTLENBQUMsYUFBYSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3RDLEdBQUcsQ0FBQyxTQUFTLENBQUMsZUFBZSxFQUFFLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM1QyxHQUFHLENBQUMsU0FBUyxDQUFDLGNBQWMsRUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDMUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxtQkFBbUIsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztRQUVqRSxJQUFJLE9BQU8sRUFBRSxDQUFDO1lBQ1osR0FBRyxDQUFDLFNBQVMsQ0FBQyxlQUFlLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDMUMsQ0FBQztJQUNILENBQUM7SUFFRCxTQUFTLENBQ1AsR0FBRyxFQUNILEdBQUcsRUFDSCxPQUFPLElBQUksR0FBRyxTQUFTLG9CQUFvQixLQUFLLENBQUMsSUFBSSxJQUFJLEtBQUssQ0FBQyxLQUFLLDRCQUE0QixFQUNoRyxTQUFTLENBQUMsY0FBYyxFQUN4QixFQUFFLEtBQUssRUFBRSxDQUNWLENBQUM7QUFDSixDQUFDO0FBRUQ7Ozs7Ozs7Ozs7OztHQVlHO0FBQ0gsTUFBTSxVQUFVLG1CQUFtQixDQUNqQyxHQUFhLEVBQ2IsT0FBZSxFQUNmLElBQVMsRUFDVCxPQU9DO0lBRUQsSUFBSSxHQUFHLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDcEIsTUFBTSxDQUFDLElBQUksQ0FBQyxpRUFBaUUsQ0FBQyxDQUFDO1FBQy9FLE9BQU87SUFDVCxDQUFDO0lBQ0QsTUFBTSxFQUFFLFVBQVUsR0FBRyxHQUFHLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxHQUFHLE9BQU8sQ0FBQztJQUNoRixNQUFNLFVBQVUsR0FBNEIsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxDQUFDO0lBQ3ZFLElBQUksS0FBSyxLQUFLLFNBQVM7UUFBRSxVQUFVLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztJQUNsRCxJQUFJLFVBQVU7UUFBRSxVQUFVLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQztJQUNuRCxHQUFHLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDLElBQUksQ0FBQztRQUMxQixPQUFPLEVBQUUsSUFBSTtRQUNiLFVBQVU7UUFDVixJQUFJLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUU7S0FDdEMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxnQkFBZ0IsR0FBRyxlQUFlLENBQUM7QUFFekM7Ozs7OztHQU1HO0FBQ0gsTUFBTSxrQkFBa0IsR0FBRyxJQUFJLENBQUM7QUFFaEM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBMEJHO0FBQ0gsTUFBTSxVQUFVLGNBQWMsQ0FBQyxLQUFjO0lBQzNDLElBQUksQ0FBQyxLQUFLLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDeEMsT0FBTyxFQUFFLENBQUM7SUFDWixDQUFDO0lBRUQsMkRBQTJEO0lBQzNELDZEQUE2RDtJQUM3RCxNQUFNLEdBQUcsR0FBRyxLQUFnQyxDQUFDO0lBQzdDLE1BQU0sTUFBTSxHQUFHLENBQUMsR0FBRyxDQUFDLEtBQUssSUFBSSxPQUFPLEdBQUcsQ0FBQyxLQUFLLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQTRCLENBQUM7SUFDekcsTUFBTSxPQUFPLEdBQTRCLEVBQUUsQ0FBQztJQUU1QyxJQUFJLE9BQU8sTUFBTSxDQUFDLElBQUksS0FBSyxRQUFRO1dBQzlCLGdCQUFnQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDO1dBQ2xDLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQzNDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQztJQUMvQixDQUFDO0lBQ0QsSUFBSSxNQUFNLENBQUMsTUFBTTtRQUFFLE9BQU8sQ0FBQyxRQUFRLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQztJQUNwRCxJQUFJLE1BQU0sQ0FBQyxJQUFJO1FBQUUsT0FBTyxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDO0lBQzlDLElBQUksTUFBTSxDQUFDLFVBQVU7UUFBRSxPQUFPLENBQUMsVUFBVSxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUM7SUFDOUQsSUFBSSxNQUFNLENBQUMsS0FBSztRQUFFLE9BQU8sQ0FBQyxLQUFLLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQztJQUMvQyxJQUFJLE1BQU0sQ0FBQyxNQUFNO1FBQUUsT0FBTyxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDO0lBRWxELE9BQU8sT0FBTyxDQUFDO0FBQ2pCLENBQUM7QUFFRCx1RUFBdUU7QUFFdkU7Ozs7Ozs7Ozs7Ozs7R0FhRztBQUNILE1BQU0sVUFBVSxZQUFZLENBQUMsS0FBYztJQUN6QyxJQUFJLENBQUMsQ0FBQyxLQUFLLFlBQVksS0FBSyxDQUFDO1FBQUUsT0FBTyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDcEQsSUFBSSxLQUFLLENBQUMsT0FBTztRQUFFLE9BQU8sS0FBSyxDQUFDLE9BQU8sQ0FBQztJQUV4QyxNQUFNLElBQUksR0FBSSxLQUEyQixDQUFDLElBQUksQ0FBQztJQUMvQyxJQUFJLElBQUk7UUFBRSxPQUFPLElBQUksQ0FBQztJQUV0QixNQUFNLEtBQUssR0FBSSxLQUFnQyxDQUFDLE1BQU0sQ0FBQztJQUN2RCxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUM3QyxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDbEUsSUFBSSxNQUFNO1lBQUUsT0FBTyxNQUFNLENBQUM7SUFDNUIsQ0FBQztJQUVELE9BQU8sS0FBSyxDQUFDLElBQUksSUFBSSxlQUFlLENBQUM7QUFDdkMsQ0FBQztBQUVELHVDQUF1QztBQUN2QyxNQUFNLFVBQVUsY0FBYyxDQUM1QixHQUFhLEVBQ2IsT0FBZSxFQUNmLElBQUksR0FBdUIsU0FBUyxDQUFDLGdCQUFnQjtJQUVyRCxTQUFTLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUM7QUFDckMsQ0FBQztBQUVELDBDQUEwQztBQUMxQyxNQUFNLFVBQVUsaUJBQWlCLENBQy9CLEdBQWEsRUFDYixPQUFlLEVBQ2YsT0FBaUM7SUFFakMsU0FBUyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsT0FBTyxFQUFFLFNBQVMsQ0FBQyxjQUFjLEVBQUUsT0FBTyxDQUFDLENBQUM7QUFDbEUsQ0FBQztBQVlELGlGQUFpRjtBQUNqRixNQUFNLFVBQVUscUJBQXFCLENBQUMsS0FBOEI7SUFDbEUsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxjQUFjLENBQUMsQ0FBQztJQUM3RixrRkFBa0Y7SUFDbEYsbUZBQW1GO0lBQ25GLHlDQUF5QztJQUN6QyxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLGVBQWUsQ0FBQyxDQUFDO0lBQy9GLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxJQUFJLFdBQVcsQ0FBQyxDQUFDO0lBQ25ELE1BQU0sU0FBUyxHQUNiLE1BQU0sQ0FBQyxLQUFLLENBQUMsU0FBUyxJQUFJLE1BQU0sQ0FBQyxDQUFDLFdBQVcsRUFBRSxLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUM7SUFFN0UsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxDQUFDO0FBQzlDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHR5cGUgeyBSZXNwb25zZSB9IGZyb20gJ2V4cHJlc3MnO1xuaW1wb3J0IHsgY3JlYXRlTG9nZ2VyIH0gZnJvbSAnLi9sb2dnZXIuanMnO1xuaW1wb3J0IHR5cGUgeyBRdW90YUluZm8gfSBmcm9tICcuLi90eXBlcy9jb21tb24uanMnO1xuaW1wb3J0IHsgRXJyb3JDb2RlIH0gZnJvbSAnLi4vdHlwZXMvZXJyb3ItY29kZXMuanMnO1xuaW1wb3J0IHsgTUFYX1BBR0VfTElNSVQsIE1BWF9QQUdFX09GRlNFVCB9IGZyb20gJy4uL3ZhbGlkYXRpb24vY29tbW9uLXNjaGVtYXMuanMnO1xuXG5jb25zdCBsb2dnZXIgPSBjcmVhdGVMb2dnZXIoJ3Jlc3BvbnNlJyk7XG5cbi8qKlxuICogU2VuZCBhIHN0YW5kYXJkaXplZCBzdWNjZXNzIHJlc3BvbnNlLlxuICpcbiAqIEBwYXJhbSByZXMgLSBFeHByZXNzIHJlc3BvbnNlIG9iamVjdFxuICogQHBhcmFtIHN0YXR1c0NvZGUgLSBIVFRQIHN0YXR1cyBjb2RlIChkZWZhdWx0OiAyMDApXG4gKiBAcGFyYW0gZGF0YSAtIFJlc3BvbnNlIGRhdGFcbiAqIEBwYXJhbSBtZXNzYWdlIC0gT3B0aW9uYWwgc3VjY2VzcyBtZXNzYWdlXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIHNlbmRTdWNjZXNzKHJlcywgMjAwLCB7IHBsdWdpbjogcGx1Z2luRGF0YSB9KTtcbiAqIHNlbmRTdWNjZXNzKHJlcywgMjAxLCB7IGlkOiBuZXdJZCB9LCAnUmVzb3VyY2UgY3JlYXRlZCcpO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZW5kU3VjY2VzczxUPihcbiAgcmVzOiBSZXNwb25zZSxcbiAgc3RhdHVzQ29kZTogbnVtYmVyID0gMjAwLFxuICBkYXRhPzogVCxcbiAgbWVzc2FnZT86IHN0cmluZyxcbik6IHZvaWQge1xuICBpZiAocmVzLmhlYWRlcnNTZW50KSB7XG4gICAgbG9nZ2VyLndhcm4oJ0F0dGVtcHRlZCB0byBzZW5kIHN1Y2Nlc3MgYWZ0ZXIgaGVhZGVycyBhbHJlYWR5IHNlbnQnLCB7IHN0YXR1c0NvZGUgfSk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgcmVzcG9uc2U6IHtcbiAgICBzdWNjZXNzOiB0cnVlO1xuICAgIHN0YXR1c0NvZGU6IG51bWJlcjtcbiAgICBkYXRhPzogVDtcbiAgICBtZXNzYWdlPzogc3RyaW5nO1xuICB9ID0ge1xuICAgIHN1Y2Nlc3M6IHRydWUsXG4gICAgc3RhdHVzQ29kZSxcbiAgfTtcblxuICBpZiAoZGF0YSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgcmVzcG9uc2UuZGF0YSA9IGRhdGE7XG4gIH1cblxuICBpZiAobWVzc2FnZSkge1xuICAgIHJlc3BvbnNlLm1lc3NhZ2UgPSBtZXNzYWdlO1xuICB9XG5cbiAgcmVzLnN0YXR1cyhzdGF0dXNDb2RlKS5qc29uKHJlc3BvbnNlKTtcbn1cblxuLyoqXG4gKiBTZW5kIGEgc3RhbmRhcmRpemVkIGVycm9yIHJlc3BvbnNlLlxuICpcbiAqIEBwYXJhbSByZXMgLSBFeHByZXNzIHJlc3BvbnNlIG9iamVjdFxuICogQHBhcmFtIHN0YXR1c0NvZGUgLSBIVFRQIHN0YXR1cyBjb2RlXG4gKiBAcGFyYW0gbWVzc2FnZSAtIEVycm9yIG1lc3NhZ2VcbiAqIEBwYXJhbSBjb2RlIC0gRXJyb3IgY29kZSBmcm9tIEVycm9yQ29kZSBlbnVtXG4gKiBAcGFyYW0gZGV0YWlscyAtIE9wdGlvbmFsIGFkZGl0aW9uYWwgZGV0YWlsc1xuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBzZW5kRXJyb3IocmVzLCA0MDQsICdQbHVnaW4gbm90IGZvdW5kJywgRXJyb3JDb2RlLk5PVF9GT1VORCk7XG4gKiBzZW5kRXJyb3IocmVzLCA0MDAsICdJbnZhbGlkIGlucHV0JywgRXJyb3JDb2RlLlZBTElEQVRJT05fRVJST1IsIHsgZmllbGQ6ICduYW1lJyB9KTtcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gc2VuZEVycm9yKFxuICByZXM6IFJlc3BvbnNlLFxuICBzdGF0dXNDb2RlOiBudW1iZXIsXG4gIG1lc3NhZ2U6IHN0cmluZyxcbiAgY29kZT86IEVycm9yQ29kZSB8IHN0cmluZyxcbiAgZGV0YWlscz86IHVua25vd24sXG4pOiB2b2lkIHtcbiAgaWYgKHJlcy5oZWFkZXJzU2VudCkge1xuICAgIGxvZ2dlci53YXJuKCdBdHRlbXB0ZWQgdG8gc2VuZCBlcnJvciBhZnRlciBoZWFkZXJzIGFscmVhZHkgc2VudCcsIHsgc3RhdHVzQ29kZSwgbWVzc2FnZSB9KTtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCByZXNwb25zZToge1xuICAgIHN1Y2Nlc3M6IGZhbHNlO1xuICAgIHN0YXR1c0NvZGU6IG51bWJlcjtcbiAgICBtZXNzYWdlOiBzdHJpbmc7XG4gICAgY29kZT86IHN0cmluZztcbiAgICBkZXRhaWxzPzogdW5rbm93bjtcbiAgfSA9IHtcbiAgICBzdWNjZXNzOiBmYWxzZSxcbiAgICBzdGF0dXNDb2RlLFxuICAgIG1lc3NhZ2UsXG4gIH07XG5cbiAgaWYgKGNvZGUpIHtcbiAgICByZXNwb25zZS5jb2RlID0gY29kZTtcbiAgfVxuXG4gIGlmIChkZXRhaWxzICE9PSB1bmRlZmluZWQpIHtcbiAgICByZXNwb25zZS5kZXRhaWxzID0gZGV0YWlscztcbiAgfVxuXG4gIHJlcy5zdGF0dXMoc3RhdHVzQ29kZSkuanNvbihyZXNwb25zZSk7XG59XG5cbi8qKlxuICogU2VuZCBhIHF1b3RhIGV4Y2VlZGVkIGVycm9yIHJlc3BvbnNlLlxuICpcbiAqIEBwYXJhbSByZXMgLSBFeHByZXNzIHJlc3BvbnNlIG9iamVjdFxuICogQHBhcmFtIHF1b3RhVHlwZSAtIFR5cGUgb2YgcXVvdGEgZXhjZWVkZWRcbiAqIEBwYXJhbSBxdW90YSAtIEN1cnJlbnQgcXVvdGEgaW5mb3JtYXRpb25cbiAqIEBwYXJhbSByZXNldEF0IC0gSVNPIHRpbWVzdGFtcCB3aGVuIHF1b3RhIHJlc2V0c1xuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBzZW5kUXVvdGFFeGNlZWRlZChyZXMsICdhcGlDYWxscycsIHsgdHlwZTogJ2FwaUNhbGxzJywgbGltaXQ6IDEwMDAwLCB1c2VkOiAxMDAwMCwgcmVtYWluaW5nOiAwIH0sIHJlc2V0QXQpO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZW5kUXVvdGFFeGNlZWRlZChcbiAgcmVzOiBSZXNwb25zZSxcbiAgcXVvdGFUeXBlOiBzdHJpbmcsXG4gIHF1b3RhOiBRdW90YUluZm8sXG4gIHJlc2V0QXQ/OiBzdHJpbmcsXG4gIG1lc3NhZ2U/OiBzdHJpbmcsXG4pOiB2b2lkIHtcbiAgY29uc3QgcmVzZXREYXRlID0gcmVzZXRBdCA/IG5ldyBEYXRlKHJlc2V0QXQpIDogbmV3IERhdGUoKTtcbiAgY29uc3QgcmVzZXRJbiA9IE1hdGgubWF4KDAsIE1hdGguY2VpbCgocmVzZXREYXRlLmdldFRpbWUoKSAtIERhdGUubm93KCkpIC8gMTAwMCkpO1xuXG4gIC8vIEd1YXJkIGxpa2UgdGhlIHNpYmxpbmcgaGVscGVyczogYHNldEhlYWRlcmAgdGhyb3dzIHN5bmNocm9ub3VzbHkgb25jZSB0aGVcbiAgLy8gcmVzcG9uc2UgaGFzIGJlZW4gc2VudCwgc28gc2tpcCB0aGUgcXVvdGEgaGVhZGVycyAoYW5kIGxldCBgc2VuZEVycm9yYCBuby1vcClcbiAgLy8gaW5zdGVhZCBvZiBjcmFzaGluZyB0aGUgaGFuZGxlciBvbiBhbiBhbHJlYWR5LWNvbW1pdHRlZCByZXNwb25zZS5cbiAgaWYgKCFyZXMuaGVhZGVyc1NlbnQpIHtcbiAgICByZXMuc2V0SGVhZGVyKCdSZXRyeS1BZnRlcicsIHJlc2V0SW4pO1xuICAgIHJlcy5zZXRIZWFkZXIoJ1gtUXVvdGEtTGltaXQnLCBxdW90YS5saW1pdCk7XG4gICAgcmVzLnNldEhlYWRlcignWC1RdW90YS1Vc2VkJywgcXVvdGEudXNlZCk7XG4gICAgcmVzLnNldEhlYWRlcignWC1RdW90YS1SZW1haW5pbmcnLCBNYXRoLm1heCgwLCBxdW90YS5yZW1haW5pbmcpKTtcblxuICAgIGlmIChyZXNldEF0KSB7XG4gICAgICByZXMuc2V0SGVhZGVyKCdYLVF1b3RhLVJlc2V0JywgcmVzZXRBdCk7XG4gICAgfVxuICB9XG5cbiAgc2VuZEVycm9yKFxuICAgIHJlcyxcbiAgICA0MjksXG4gICAgbWVzc2FnZSA/PyBgJHtxdW90YVR5cGV9IHF1b3RhIGV4Y2VlZGVkICgke3F1b3RhLnVzZWR9LyR7cXVvdGEubGltaXR9KS4gUGxlYXNlIHRyeSBhZ2FpbiBsYXRlci5gLFxuICAgIEVycm9yQ29kZS5RVU9UQV9FWENFRURFRCxcbiAgICB7IHF1b3RhIH0sXG4gICk7XG59XG5cbi8qKlxuICogU2VuZCBhIHBhZ2luYXRlZCBsaXN0IHJlc3BvbnNlIHdpdGggdGhlIGl0ZW1zIG5lc3RlZCB1bmRlciBhIG5hbWVkIGtleS5cbiAqIFVzZSB3aGVuIHRoZSBBUEkgY29udHJhY3QgaXMgYHsgPGtleT46IFsuLi5dLCBwYWdpbmF0aW9uOiB7Li4ufSB9YFxuICogKHRoZSBkb21pbmFudCBzaGFwZSBhY3Jvc3MgYXBpLyogc2VydmljZXMpLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBzZW5kUGFnaW5hdGVkTmVzdGVkKHJlcywgJ3BpcGVsaW5lcycsIGl0ZW1zLCB7XG4gKiAgIHRvdGFsOiA1MCwgbGltaXQ6IDI1LCBvZmZzZXQ6IDAsIGhhc01vcmU6IHRydWUsXG4gKiB9KTtcbiAqIC8vIOKGkiB7IHBpcGVsaW5lczogWy4uLl0sIHBhZ2luYXRpb246IHsgdG90YWw6IDUwLCBsaW1pdDogMjUsIG9mZnNldDogMCwgaGFzTW9yZTogdHJ1ZSB9IH1cbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gc2VuZFBhZ2luYXRlZE5lc3RlZDxUPihcbiAgcmVzOiBSZXNwb25zZSxcbiAgZGF0YUtleTogc3RyaW5nLFxuICBkYXRhOiBUW10sXG4gIG9wdGlvbnM6IHtcbiAgICB0b3RhbD86IG51bWJlcjtcbiAgICBsaW1pdDogbnVtYmVyO1xuICAgIG9mZnNldDogbnVtYmVyO1xuICAgIGhhc01vcmU6IGJvb2xlYW47XG4gICAgbmV4dEN1cnNvcj86IHN0cmluZztcbiAgICBzdGF0dXNDb2RlPzogbnVtYmVyO1xuICB9LFxuKTogdm9pZCB7XG4gIGlmIChyZXMuaGVhZGVyc1NlbnQpIHtcbiAgICBsb2dnZXIud2FybignQXR0ZW1wdGVkIHRvIHNlbmQgcGFnaW5hdGVkIHJlc3BvbnNlIGFmdGVyIGhlYWRlcnMgYWxyZWFkeSBzZW50Jyk7XG4gICAgcmV0dXJuO1xuICB9XG4gIGNvbnN0IHsgc3RhdHVzQ29kZSA9IDIwMCwgdG90YWwsIGxpbWl0LCBvZmZzZXQsIGhhc01vcmUsIG5leHRDdXJzb3IgfSA9IG9wdGlvbnM7XG4gIGNvbnN0IHBhZ2luYXRpb246IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0geyBsaW1pdCwgb2Zmc2V0LCBoYXNNb3JlIH07XG4gIGlmICh0b3RhbCAhPT0gdW5kZWZpbmVkKSBwYWdpbmF0aW9uLnRvdGFsID0gdG90YWw7XG4gIGlmIChuZXh0Q3Vyc29yKSBwYWdpbmF0aW9uLm5leHRDdXJzb3IgPSBuZXh0Q3Vyc29yO1xuICByZXMuc3RhdHVzKHN0YXR1c0NvZGUpLmpzb24oe1xuICAgIHN1Y2Nlc3M6IHRydWUsXG4gICAgc3RhdHVzQ29kZSxcbiAgICBkYXRhOiB7IFtkYXRhS2V5XTogZGF0YSwgcGFnaW5hdGlvbiB9LFxuICB9KTtcbn1cblxuLyoqXG4gKiBTUUxTVEFURTogZXhhY3RseSBmaXZlIGNoYXJhY3RlcnMsIGRpZ2l0cyBhbmQgdXBwZXJjYXNlIExhdGluIGxldHRlcnNcbiAqIChlLmcuIGAyMzUwNWAgdW5pcXVlX3Zpb2xhdGlvbiwgYDQyNjAxYCBzeW50YXhfZXJyb3IpLiBOb2RlJ3Mgb3duIHNvY2tldCBhbmRcbiAqIEROUyBlcnJvcnMgdXNlIHRoZSBzYW1lIGAuY29kZWAgcHJvcGVydHkgYnV0IHNwZWxsIGl0IGRpZmZlcmVudGx5XG4gKiAoYEVDT05OUkVTRVRgLCBgRVRJTUVET1VUYCwgYEVOT1RGT1VORGApLCB3aGljaCBpcyB3aGF0IHRoaXMgdGVsbHMgYXBhcnQuXG4gKi9cbmNvbnN0IFNRTFNUQVRFX1BBVFRFUk4gPSAvXlswLTlBLVpdezV9JC87XG5cbi8qKlxuICogTGVuZ3RoIGFsb25lIGlzIG5vdCBlbm91Z2g6IGBFUElQRWAgYW5kIGBFMkJJR2AgYXJlIGZpdmUgdXBwZXJjYXNlIGNoYXJhY3RlcnNcbiAqIGFuZCB3b3VsZCBwYXNzIGFzIFNRTFNUQVRFcy4gRXZlcnkgbGlidXYvTm9kZSBlcnJubyBzdGFydHMgd2l0aCBgRWAsIGFuZFxuICogUG9zdGdyZXMgZGVmaW5lcyBubyBlcnJvciBjbGFzcyB0aGF0IGRvZXMg4oCUIGl0cyBjbGFzc2VzIGFyZSAwMC0wWiwgMjAtMkYsXG4gKiAzNC0zRiwgNDAtNDQsIDUzLTU4LCA3MiwgRjAsIEhWLCBQMCBhbmQgWFggKHNlZSB0aGUgc2VydmVyJ3MgZXJyY29kZXMudHh0KS5cbiAqIFNvIGEgbGVhZGluZyBgRWAgc2V0dGxlcyBpdC5cbiAqL1xuY29uc3QgTk9ERV9FUlJOT19QQVRURVJOID0gL15FLztcblxuLyoqXG4gKiBFeHRyYWN0IGRhdGFiYXNlIGVycm9yIGRldGFpbHMgZm9yIGxvZ2dpbmcvcmVzcG9uc2UuXG4gKlxuICogRXh0cmFjdHMgUG9zdGdyZVNRTCBlcnJvciBjb2RlcywgZGV0YWlscywgaGludHMsIGFuZCBjb25zdHJhaW50IG5hbWVzXG4gKiBmcm9tIGRhdGFiYXNlIGVycm9ycyBmb3IgYmV0dGVyIGVycm9yIG1lc3NhZ2VzLlxuICpcbiAqIE9ubHkgYSBnZW51aW5lIFBvc3RncmVzIGVycm9yIHlpZWxkcyBhIGBkYkNvZGVgLiBBbnkgZXJyb3Igb2JqZWN0IGNhcnJ5aW5nIGFcbiAqIGAuY29kZWAgdXNlZCB0byBiZSByZXBvcnRlZCBhcyBvbmUsIHNvIGEgdHJhbnNwb3J0IGZhaWx1cmUgKGBFQ09OTlJFU0VUYCB3aGVuXG4gKiB0aGUgcG9vbGVyIGRyb3BzIG91dCBvZiB0aGUgU2VydmljZSBlbmRwb2ludHMsIHNheSkgbG9nZ2VkIGFzXG4gKiBge1wiZGJcIjp7XCJkYkNvZGVcIjpcIkVDT05OUkVTRVRcIn19YCBhbmQgc2VudCBldmVyeSByZWFkZXIgaHVudGluZyB0aHJvdWdoIGNsZWFuXG4gKiBQb3N0Z3JlcyBsb2dzLiBUaGUgdHJhbnNwb3J0IGNvZGUgaXMgbm90IGxvc3Qg4oCUIGNhbGxlcnMgbG9nIHRoZSBlcnJvciBtZXNzYWdlXG4gKiBpdHNlbGYgYWxvbmdzaWRlIHRoZXNlIGRldGFpbHMg4oCUIGl0IGp1c3Qgc3RvcHMgY2xhaW1pbmcgdG8gYmUgYSBEQiBmYXVsdC5cbiAqXG4gKiBAcGFyYW0gZXJyb3IgLSBFcnJvciBvYmplY3QgZnJvbSBkYXRhYmFzZSBvcGVyYXRpb25cbiAqIEByZXR1cm5zIE9iamVjdCB3aXRoIGV4dHJhY3RlZCBlcnJvciBkZXRhaWxzOyBge31gIHdoZW4gYGVycm9yYCBpcyBub3QgYVxuICogICBQb3N0Z3JlcyBlcnJvciAobm8gU1FMU1RBVEUgYW5kIG5vbmUgb2YgdGhlIHBnLXNwZWNpZmljIGZpZWxkcylcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogdHJ5IHtcbiAqICAgYXdhaXQgZGIuaW5zZXJ0KHBsdWdpbnMpLnZhbHVlcyhuZXdQbHVnaW4pO1xuICogfSBjYXRjaCAoZXJyb3IpIHtcbiAqICAgY29uc3QgZGJEZXRhaWxzID0gZXh0cmFjdERiRXJyb3IoZXJyb3IpO1xuICogICByZXR1cm4gc2VuZEVycm9yKHJlcywgNTAwLCAnRGF0YWJhc2UgZXJyb3InLCBFcnJvckNvZGUuREFUQUJBU0VfRVJST1IsIGRiRGV0YWlscyk7XG4gKiB9XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV4dHJhY3REYkVycm9yKGVycm9yOiB1bmtub3duKTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4ge1xuICBpZiAoIWVycm9yIHx8IHR5cGVvZiBlcnJvciAhPT0gJ29iamVjdCcpIHtcbiAgICByZXR1cm4ge307XG4gIH1cblxuICAvLyBEcml6emxlIE9STSB3cmFwcyB0aGUgb3JpZ2luYWwgcGcgZXJyb3IgaW4gZXJyb3IuY2F1c2Ug4oCUXG4gIC8vIGNoZWNrIHRoZSBjYXVzZSBmaXJzdCwgdGhlbiBmYWxsIGJhY2sgdG8gdGhlIGVycm9yIGl0c2VsZi5cbiAgY29uc3QgZXJyID0gZXJyb3IgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIGNvbnN0IHNvdXJjZSA9IChlcnIuY2F1c2UgJiYgdHlwZW9mIGVyci5jYXVzZSA9PT0gJ29iamVjdCcgPyBlcnIuY2F1c2UgOiBlcnIpIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBjb25zdCBkZXRhaWxzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHt9O1xuXG4gIGlmICh0eXBlb2Ygc291cmNlLmNvZGUgPT09ICdzdHJpbmcnXG4gICAgJiYgU1FMU1RBVEVfUEFUVEVSTi50ZXN0KHNvdXJjZS5jb2RlKVxuICAgICYmICFOT0RFX0VSUk5PX1BBVFRFUk4udGVzdChzb3VyY2UuY29kZSkpIHtcbiAgICBkZXRhaWxzLmRiQ29kZSA9IHNvdXJjZS5jb2RlO1xuICB9XG4gIGlmIChzb3VyY2UuZGV0YWlsKSBkZXRhaWxzLmRiRGV0YWlsID0gc291cmNlLmRldGFpbDtcbiAgaWYgKHNvdXJjZS5oaW50KSBkZXRhaWxzLmRiSGludCA9IHNvdXJjZS5oaW50O1xuICBpZiAoc291cmNlLmNvbnN0cmFpbnQpIGRldGFpbHMuY29uc3RyYWludCA9IHNvdXJjZS5jb25zdHJhaW50O1xuICBpZiAoc291cmNlLnRhYmxlKSBkZXRhaWxzLnRhYmxlID0gc291cmNlLnRhYmxlO1xuICBpZiAoc291cmNlLmNvbHVtbikgZGV0YWlscy5jb2x1bW4gPSBzb3VyY2UuY29sdW1uO1xuXG4gIHJldHVybiBkZXRhaWxzO1xufVxuXG4vLyBDb252ZW5pZW5jZSBoZWxwZXJzIChzaGFyZWQgYWNyb3NzIHBsdWdpbiwgcGlwZWxpbmUsIHF1b3RhIHNlcnZpY2VzKVxuXG4vKipcbiAqIEV4dHJhY3QgYSBodW1hbi1yZWFkYWJsZSBtZXNzYWdlIGZyb20gYW4gdW5rbm93biBjYXRjaCB2YWx1ZS5cbiAqXG4gKiBGYWxscyBiYWNrIGJleW9uZCBgLm1lc3NhZ2VgIGJlY2F1c2Ugc2V2ZXJhbCBjb21tb24gTm9kZSBlcnJvcnMgY2FycnkgYW5cbiAqIEVNUFRZIGAubWVzc2FnZWA6XG4gKiAgLSBkdWFsLXN0YWNrIChJUHY0K0lQdjYpIGNvbm5lY3QgZmFpbHVyZXMgc3VyZmFjZSBhcyBhbiBgQWdncmVnYXRlRXJyb3JgXG4gKiAgICB3aG9zZSBvd24gbWVzc2FnZSBpcyBibGFuayDigJQgdGhlIGNhdXNlIGxpdmVzIGluIGAuY29kZWAgKGUuZy5cbiAqICAgIGBFQ09OTlJFRlVTRURgL2BFVElNRURPVVRgKSBhbmQvb3IgdGhlIGAuZXJyb3JzW11gIHN1Yi1lcnJvcnM7XG4gKiAgLSByYXcgc29ja2V0IGBFcnJub0V4Y2VwdGlvbmBzIGNhbiBsaWtld2lzZSBjYXJyeSBvbmx5IGEgYC5jb2RlYC5cbiAqIFdpdGhvdXQgdGhpcywgYW4gdW5yZWFjaGFibGUgaW50ZXJuYWwgc2VydmljZSAoZS5nLiBjb21wbGlhbmNlIHN0aWxsXG4gKiBzdGFydGluZykgcHJvZHVjZWQgYmxhbmsgcGVyLWl0ZW0gZXJyb3JzIGluIGJ1bGsgcmVzcG9uc2VzIGFuZCBgZXJyb3I6XCJcImBcbiAqIGluIGxvZ3Mg4oCUIGEgc2lsZW50IGJsYWNrIGJveC4gT3JkZXI6IG1lc3NhZ2Ug4oaSIGNvZGUg4oaSIGpvaW5lZCBzdWItZXJyb3JzIOKGklxuICogZXJyb3IgbmFtZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVycm9yTWVzc2FnZShlcnJvcjogdW5rbm93bik6IHN0cmluZyB7XG4gIGlmICghKGVycm9yIGluc3RhbmNlb2YgRXJyb3IpKSByZXR1cm4gU3RyaW5nKGVycm9yKTtcbiAgaWYgKGVycm9yLm1lc3NhZ2UpIHJldHVybiBlcnJvci5tZXNzYWdlO1xuXG4gIGNvbnN0IGNvZGUgPSAoZXJyb3IgYXMgeyBjb2RlPzogc3RyaW5nIH0pLmNvZGU7XG4gIGlmIChjb2RlKSByZXR1cm4gY29kZTtcblxuICBjb25zdCBpbm5lciA9IChlcnJvciBhcyB7IGVycm9ycz86IHVua25vd25bXSB9KS5lcnJvcnM7XG4gIGlmIChBcnJheS5pc0FycmF5KGlubmVyKSAmJiBpbm5lci5sZW5ndGggPiAwKSB7XG4gICAgY29uc3Qgam9pbmVkID0gaW5uZXIubWFwKGVycm9yTWVzc2FnZSkuZmlsdGVyKEJvb2xlYW4pLmpvaW4oJzsgJyk7XG4gICAgaWYgKGpvaW5lZCkgcmV0dXJuIGpvaW5lZDtcbiAgfVxuXG4gIHJldHVybiBlcnJvci5uYW1lIHx8ICdVbmtub3duIGVycm9yJztcbn1cblxuLyoqIFNlbmQgYSA0MDAgYmFkLXJlcXVlc3QgcmVzcG9uc2UuICovXG5leHBvcnQgZnVuY3Rpb24gc2VuZEJhZFJlcXVlc3QoXG4gIHJlczogUmVzcG9uc2UsXG4gIG1lc3NhZ2U6IHN0cmluZyxcbiAgY29kZTogRXJyb3JDb2RlIHwgc3RyaW5nID0gRXJyb3JDb2RlLlZBTElEQVRJT05fRVJST1IsXG4pOiB2b2lkIHtcbiAgc2VuZEVycm9yKHJlcywgNDAwLCBtZXNzYWdlLCBjb2RlKTtcbn1cblxuLyoqIFNlbmQgYSA1MDAgaW50ZXJuYWwgZXJyb3IgcmVzcG9uc2UuICovXG5leHBvcnQgZnVuY3Rpb24gc2VuZEludGVybmFsRXJyb3IoXG4gIHJlczogUmVzcG9uc2UsXG4gIG1lc3NhZ2U6IHN0cmluZyxcbiAgZGV0YWlscz86IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuKTogdm9pZCB7XG4gIHNlbmRFcnJvcihyZXMsIDUwMCwgbWVzc2FnZSwgRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SLCBkZXRhaWxzKTtcbn1cblxuLy8gUGFnaW5hdGlvblxuXG4vKiogQ29tbW9uIHBhZ2luYXRpb24gKyBzb3J0aW5nIHBhcmFtZXRlcnMuICovXG5leHBvcnQgaW50ZXJmYWNlIFBhZ2luYXRpb25QYXJhbXMge1xuICBsaW1pdDogbnVtYmVyO1xuICBvZmZzZXQ6IG51bWJlcjtcbiAgc29ydEJ5OiBzdHJpbmc7XG4gIHNvcnRPcmRlcjogJ2FzYycgfCAnZGVzYyc7XG59XG5cbi8qKiBQYXJzZSBwYWdpbmF0aW9uL3NvcnQgcGFyYW1zIGZyb20gcXVlcnkgc3RyaW5nLCBjbGFtcGluZyB0byBzYWZlIGRlZmF1bHRzLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlUGFnaW5hdGlvblBhcmFtcyhxdWVyeTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBQYWdpbmF0aW9uUGFyYW1zIHtcbiAgY29uc3QgbGltaXQgPSBNYXRoLm1pbihNYXRoLm1heChwYXJzZUludChTdHJpbmcocXVlcnkubGltaXQpLCAxMCkgfHwgMTAsIDEpLCBNQVhfUEFHRV9MSU1JVCk7XG4gIC8vIENsYW1wIG9mZnNldCB0b28g4oCUIGFuIHVuYm91bmRlZCBvZmZzZXQgZm9yY2VzIFBvc3RncmVzIHRvIHNjYW4rZGlzY2FyZCBodWdlIHJvd1xuICAvLyBjb3VudHMgb24gaG90IGxpc3QgZW5kcG9pbnRzIChhIGNoZWFwIERvUyBhbXBsaWZpZXIpLiBEZWVwIHBhZ2luZyBzaG91bGQgdXNlIHRoZVxuICAvLyBjdXJzb3IgQVBJLiBDZWlsaW5nID0gTUFYX1BBR0VfT0ZGU0VULlxuICBjb25zdCBvZmZzZXQgPSBNYXRoLm1pbihNYXRoLm1heChwYXJzZUludChTdHJpbmcocXVlcnkub2Zmc2V0KSwgMTApIHx8IDAsIDApLCBNQVhfUEFHRV9PRkZTRVQpO1xuICBjb25zdCBzb3J0QnkgPSBTdHJpbmcocXVlcnkuc29ydEJ5IHx8ICdjcmVhdGVkQXQnKTtcbiAgY29uc3Qgc29ydE9yZGVyOiAnYXNjJyB8ICdkZXNjJyA9XG4gICAgU3RyaW5nKHF1ZXJ5LnNvcnRPcmRlciB8fCAnZGVzYycpLnRvTG93ZXJDYXNlKCkgPT09ICdhc2MnID8gJ2FzYycgOiAnZGVzYyc7XG5cbiAgcmV0dXJuIHsgbGltaXQsIG9mZnNldCwgc29ydEJ5LCBzb3J0T3JkZXIgfTtcbn1cbiJdfQ==
|
|
252
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzcG9uc2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvcmVzcG9uc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUd0QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRTNDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDakUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUV4QyxNQUFNLE1BQU0sR0FBRyxZQUFZLENBQUMsVUFBVSxDQUFDLENBQUM7QUFFeEM7Ozs7Ozs7Ozs7Ozs7R0FhRztBQUNILE1BQU0sVUFBVSxXQUFXLENBQ3pCLEdBQWEsRUFDYixVQUFVLEdBQVcsR0FBRyxFQUN4QixJQUFRLEVBQ1IsT0FBZ0I7SUFFaEIsSUFBSSxHQUFHLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDcEIsTUFBTSxDQUFDLElBQUksQ0FBQyxzREFBc0QsRUFBRSxFQUFFLFVBQVUsRUFBRSxDQUFDLENBQUM7UUFDcEYsT0FBTztJQUNULENBQUM7SUFFRCxNQUFNLFFBQVEsR0FLVjtRQUNGLE9BQU8sRUFBRSxJQUFJO1FBQ2IsVUFBVTtLQUNYLENBQUM7SUFFRixJQUFJLElBQUksS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUN2QixRQUFRLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztJQUN2QixDQUFDO0lBRUQsSUFBSSxPQUFPLEVBQUUsQ0FBQztRQUNaLFFBQVEsQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO0lBQzdCLENBQUM7SUFFRCxHQUFHLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUN4QyxDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7O0dBY0c7QUFDSCxNQUFNLFVBQVUsU0FB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QUUsR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztBQUN4RixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCB0eXBlIHsgUmVzcG9uc2UgfSBmcm9tICdleHByZXNzJztcbmltcG9ydCB7IGNyZWF0ZUxvZ2dlciB9IGZyb20gJy4vbG9nZ2VyLmpzJztcbmltcG9ydCB0eXBlIHsgUXVvdGFJbmZvIH0gZnJvbSAnLi4vdHlwZXMvY29tbW9uLmpzJztcbmltcG9ydCB7IEVycm9yQ29kZSB9IGZyb20gJy4uL3R5cGVzL2Vycm9yLWNvZGVzLmpzJztcbmltcG9ydCB7IE1BWF9QQUdFX0xJTUlUIH0gZnJvbSAnLi4vdmFsaWRhdGlvbi9jb21tb24tc2NoZW1hcy5qcyc7XG5pbXBvcnQgeyBwYXJzZVBhZ2UgfSBmcm9tICcuL3BhcmFtcy5qcyc7XG5cbmNvbnN0IGxvZ2dlciA9IGNyZWF0ZUxvZ2dlcigncmVzcG9uc2UnKTtcblxuLyoqXG4gKiBTZW5kIGEgc3RhbmRhcmRpemVkIHN1Y2Nlc3MgcmVzcG9uc2UuXG4gKlxuICogQHBhcmFtIHJlcyAtIEV4cHJlc3MgcmVzcG9uc2Ugb2JqZWN0XG4gKiBAcGFyYW0gc3RhdHVzQ29kZSAtIEhUVFAgc3RhdHVzIGNvZGUgKGRlZmF1bHQ6IDIwMClcbiAqIEBwYXJhbSBkYXRhIC0gUmVzcG9uc2UgZGF0YVxuICogQHBhcmFtIG1lc3NhZ2UgLSBPcHRpb25hbCBzdWNjZXNzIG1lc3NhZ2VcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogc2VuZFN1Y2Nlc3MocmVzLCAyMDAsIHsgcGx1Z2luOiBwbHVnaW5EYXRhIH0pO1xuICogc2VuZFN1Y2Nlc3MocmVzLCAyMDEsIHsgaWQ6IG5ld0lkIH0sICdSZXNvdXJjZSBjcmVhdGVkJyk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlbmRTdWNjZXNzPFQ+KFxuICByZXM6IFJlc3BvbnNlLFxuICBzdGF0dXNDb2RlOiBudW1iZXIgPSAyMDAsXG4gIGRhdGE/OiBULFxuICBtZXNzYWdlPzogc3RyaW5nLFxuKTogdm9pZCB7XG4gIGlmIChyZXMuaGVhZGVyc1NlbnQpIHtcbiAgICBsb2dnZXIud2FybignQXR0ZW1wdGVkIHRvIHNlbmQgc3VjY2VzcyBhZnRlciBoZWFkZXJzIGFscmVhZHkgc2VudCcsIHsgc3RhdHVzQ29kZSB9KTtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCByZXNwb25zZToge1xuICAgIHN1Y2Nlc3M6IHRydWU7XG4gICAgc3RhdHVzQ29kZTogbnVtYmVyO1xuICAgIGRhdGE/OiBUO1xuICAgIG1lc3NhZ2U/OiBzdHJpbmc7XG4gIH0gPSB7XG4gICAgc3VjY2VzczogdHJ1ZSxcbiAgICBzdGF0dXNDb2RlLFxuICB9O1xuXG4gIGlmIChkYXRhICE9PSB1bmRlZmluZWQpIHtcbiAgICByZXNwb25zZS5kYXRhID0gZGF0YTtcbiAgfVxuXG4gIGlmIChtZXNzYWdlKSB7XG4gICAgcmVzcG9uc2UubWVzc2FnZSA9IG1lc3NhZ2U7XG4gIH1cblxuICByZXMuc3RhdHVzKHN0YXR1c0NvZGUpLmpzb24ocmVzcG9uc2UpO1xufVxuXG4vKipcbiAqIFNlbmQgYSBzdGFuZGFyZGl6ZWQgZXJyb3IgcmVzcG9uc2UuXG4gKlxuICogQHBhcmFtIHJlcyAtIEV4cHJlc3MgcmVzcG9uc2Ugb2JqZWN0XG4gKiBAcGFyYW0gc3RhdHVzQ29kZSAtIEhUVFAgc3RhdHVzIGNvZGVcbiAqIEBwYXJhbSBtZXNzYWdlIC0gRXJyb3IgbWVzc2FnZVxuICogQHBhcmFtIGNvZGUgLSBFcnJvciBjb2RlIGZyb20gRXJyb3JDb2RlIGVudW1cbiAqIEBwYXJhbSBkZXRhaWxzIC0gT3B0aW9uYWwgYWRkaXRpb25hbCBkZXRhaWxzXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIHNlbmRFcnJvcihyZXMsIDQwNCwgJ1BsdWdpbiBub3QgZm91bmQnLCBFcnJvckNvZGUuTk9UX0ZPVU5EKTtcbiAqIHNlbmRFcnJvcihyZXMsIDQwMCwgJ0ludmFsaWQgaW5wdXQnLCBFcnJvckNvZGUuVkFMSURBVElPTl9FUlJPUiwgeyBmaWVsZDogJ25hbWUnIH0pO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZW5kRXJyb3IoXG4gIHJlczogUmVzcG9uc2UsXG4gIHN0YXR1c0NvZGU6IG51bWJlcixcbiAgbWVzc2FnZTogc3RyaW5nLFxuICBjb2RlPzogRXJyb3JDb2RlIHwgc3RyaW5nLFxuICBkZXRhaWxzPzogdW5rbm93bixcbik6IHZvaWQge1xuICBpZiAocmVzLmhlYWRlcnNTZW50KSB7XG4gICAgbG9nZ2VyLndhcm4oJ0F0dGVtcHRlZCB0byBzZW5kIGVycm9yIGFmdGVyIGhlYWRlcnMgYWxyZWFkeSBzZW50JywgeyBzdGF0dXNDb2RlLCBtZXNzYWdlIH0pO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IHJlc3BvbnNlOiB7XG4gICAgc3VjY2VzczogZmFsc2U7XG4gICAgc3RhdHVzQ29kZTogbnVtYmVyO1xuICAgIG1lc3NhZ2U6IHN0cmluZztcbiAgICBjb2RlPzogc3RyaW5nO1xuICAgIGRldGFpbHM/OiB1bmtub3duO1xuICB9ID0ge1xuICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgIHN0YXR1c0NvZGUsXG4gICAgbWVzc2FnZSxcbiAgfTtcblxuICBpZiAoY29kZSkge1xuICAgIHJlc3BvbnNlLmNvZGUgPSBjb2RlO1xuICB9XG5cbiAgaWYgKGRldGFpbHMgIT09IHVuZGVmaW5lZCkge1xuICAgIHJlc3BvbnNlLmRldGFpbHMgPSBkZXRhaWxzO1xuICB9XG5cbiAgcmVzLnN0YXR1cyhzdGF0dXNDb2RlKS5qc29uKHJlc3BvbnNlKTtcbn1cblxuLyoqXG4gKiBTZW5kIGEgcXVvdGEgZXhjZWVkZWQgZXJyb3IgcmVzcG9uc2UuXG4gKlxuICogQHBhcmFtIHJlcyAtIEV4cHJlc3MgcmVzcG9uc2Ugb2JqZWN0XG4gKiBAcGFyYW0gcXVvdGFUeXBlIC0gVHlwZSBvZiBxdW90YSBleGNlZWRlZFxuICogQHBhcmFtIHF1b3RhIC0gQ3VycmVudCBxdW90YSBpbmZvcm1hdGlvblxuICogQHBhcmFtIHJlc2V0QXQgLSBJU08gdGltZXN0YW1wIHdoZW4gcXVvdGEgcmVzZXRzXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIHNlbmRRdW90YUV4Y2VlZGVkKHJlcywgJ2FwaUNhbGxzJywgeyB0eXBlOiAnYXBpQ2FsbHMnLCBsaW1pdDogMTAwMDAsIHVzZWQ6IDEwMDAwLCByZW1haW5pbmc6IDAgfSwgcmVzZXRBdCk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlbmRRdW90YUV4Y2VlZGVkKFxuICByZXM6IFJlc3BvbnNlLFxuICBxdW90YVR5cGU6IHN0cmluZyxcbiAgcXVvdGE6IFF1b3RhSW5mbyxcbiAgcmVzZXRBdD86IHN0cmluZyxcbiAgbWVzc2FnZT86IHN0cmluZyxcbik6IHZvaWQge1xuICBjb25zdCByZXNldERhdGUgPSByZXNldEF0ID8gbmV3IERhdGUocmVzZXRBdCkgOiBuZXcgRGF0ZSgpO1xuICBjb25zdCByZXNldEluID0gTWF0aC5tYXgoMCwgTWF0aC5jZWlsKChyZXNldERhdGUuZ2V0VGltZSgpIC0gRGF0ZS5ub3coKSkgLyAxMDAwKSk7XG5cbiAgLy8gR3VhcmQgbGlrZSB0aGUgc2libGluZyBoZWxwZXJzOiBgc2V0SGVhZGVyYCB0aHJvd3Mgc3luY2hyb25vdXNseSBvbmNlIHRoZVxuICAvLyByZXNwb25zZSBoYXMgYmVlbiBzZW50LCBzbyBza2lwIHRoZSBxdW90YSBoZWFkZXJzIChhbmQgbGV0IGBzZW5kRXJyb3JgIG5vLW9wKVxuICAvLyBpbnN0ZWFkIG9mIGNyYXNoaW5nIHRoZSBoYW5kbGVyIG9uIGFuIGFscmVhZHktY29tbWl0dGVkIHJlc3BvbnNlLlxuICBpZiAoIXJlcy5oZWFkZXJzU2VudCkge1xuICAgIHJlcy5zZXRIZWFkZXIoJ1JldHJ5LUFmdGVyJywgcmVzZXRJbik7XG4gICAgcmVzLnNldEhlYWRlcignWC1RdW90YS1MaW1pdCcsIHF1b3RhLmxpbWl0KTtcbiAgICByZXMuc2V0SGVhZGVyKCdYLVF1b3RhLVVzZWQnLCBxdW90YS51c2VkKTtcbiAgICByZXMuc2V0SGVhZGVyKCdYLVF1b3RhLVJlbWFpbmluZycsIE1hdGgubWF4KDAsIHF1b3RhLnJlbWFpbmluZykpO1xuXG4gICAgaWYgKHJlc2V0QXQpIHtcbiAgICAgIHJlcy5zZXRIZWFkZXIoJ1gtUXVvdGEtUmVzZXQnLCByZXNldEF0KTtcbiAgICB9XG4gIH1cblxuICBzZW5kRXJyb3IoXG4gICAgcmVzLFxuICAgIDQyOSxcbiAgICBtZXNzYWdlID8/IGAke3F1b3RhVHlwZX0gcXVvdGEgZXhjZWVkZWQgKCR7cXVvdGEudXNlZH0vJHtxdW90YS5saW1pdH0pLiBQbGVhc2UgdHJ5IGFnYWluIGxhdGVyLmAsXG4gICAgRXJyb3JDb2RlLlFVT1RBX0VYQ0VFREVELFxuICAgIHsgcXVvdGEgfSxcbiAgKTtcbn1cblxuLyoqXG4gKiBTZW5kIGEgcGFnaW5hdGVkIGxpc3QgcmVzcG9uc2Ugd2l0aCB0aGUgaXRlbXMgbmVzdGVkIHVuZGVyIGEgbmFtZWQga2V5LlxuICogVXNlIHdoZW4gdGhlIEFQSSBjb250cmFjdCBpcyBgeyA8a2V5PjogWy4uLl0sIHBhZ2luYXRpb246IHsuLi59IH1gXG4gKiAodGhlIGRvbWluYW50IHNoYXBlIGFjcm9zcyBhcGkvKiBzZXJ2aWNlcykuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIHNlbmRQYWdpbmF0ZWROZXN0ZWQocmVzLCAncGlwZWxpbmVzJywgaXRlbXMsIHtcbiAqICAgdG90YWw6IDUwLCBsaW1pdDogMjUsIG9mZnNldDogMCwgaGFzTW9yZTogdHJ1ZSxcbiAqIH0pO1xuICogLy8g4oaSIHsgcGlwZWxpbmVzOiBbLi4uXSwgcGFnaW5hdGlvbjogeyB0b3RhbDogNTAsIGxpbWl0OiAyNSwgb2Zmc2V0OiAwLCBoYXNNb3JlOiB0cnVlIH0gfVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZW5kUGFnaW5hdGVkTmVzdGVkPFQ+KFxuICByZXM6IFJlc3BvbnNlLFxuICBkYXRhS2V5OiBzdHJpbmcsXG4gIGRhdGE6IFRbXSxcbiAgb3B0aW9uczoge1xuICAgIHRvdGFsPzogbnVtYmVyO1xuICAgIGxpbWl0OiBudW1iZXI7XG4gICAgb2Zmc2V0OiBudW1iZXI7XG4gICAgaGFzTW9yZTogYm9vbGVhbjtcbiAgICBuZXh0Q3Vyc29yPzogc3RyaW5nO1xuICAgIHN0YXR1c0NvZGU/OiBudW1iZXI7XG4gIH0sXG4pOiB2b2lkIHtcbiAgaWYgKHJlcy5oZWFkZXJzU2VudCkge1xuICAgIGxvZ2dlci53YXJuKCdBdHRlbXB0ZWQgdG8gc2VuZCBwYWdpbmF0ZWQgcmVzcG9uc2UgYWZ0ZXIgaGVhZGVycyBhbHJlYWR5IHNlbnQnKTtcbiAgICByZXR1cm47XG4gIH1cbiAgY29uc3QgeyBzdGF0dXNDb2RlID0gMjAwLCB0b3RhbCwgbGltaXQsIG9mZnNldCwgaGFzTW9yZSwgbmV4dEN1cnNvciB9ID0gb3B0aW9ucztcbiAgY29uc3QgcGFnaW5hdGlvbjogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7IGxpbWl0LCBvZmZzZXQsIGhhc01vcmUgfTtcbiAgaWYgKHRvdGFsICE9PSB1bmRlZmluZWQpIHBhZ2luYXRpb24udG90YWwgPSB0b3RhbDtcbiAgaWYgKG5leHRDdXJzb3IpIHBhZ2luYXRpb24ubmV4dEN1cnNvciA9IG5leHRDdXJzb3I7XG4gIHJlcy5zdGF0dXMoc3RhdHVzQ29kZSkuanNvbih7XG4gICAgc3VjY2VzczogdHJ1ZSxcbiAgICBzdGF0dXNDb2RlLFxuICAgIGRhdGE6IHsgW2RhdGFLZXldOiBkYXRhLCBwYWdpbmF0aW9uIH0sXG4gIH0pO1xufVxuXG4vKipcbiAqIFNRTFNUQVRFOiBleGFjdGx5IGZpdmUgY2hhcmFjdGVycywgZGlnaXRzIGFuZCB1cHBlcmNhc2UgTGF0aW4gbGV0dGVyc1xuICogKGUuZy4gYDIzNTA1YCB1bmlxdWVfdmlvbGF0aW9uLCBgNDI2MDFgIHN5bnRheF9lcnJvcikuIE5vZGUncyBvd24gc29ja2V0IGFuZFxuICogRE5TIGVycm9ycyB1c2UgdGhlIHNhbWUgYC5jb2RlYCBwcm9wZXJ0eSBidXQgc3BlbGwgaXQgZGlmZmVyZW50bHlcbiAqIChgRUNPTk5SRVNFVGAsIGBFVElNRURPVVRgLCBgRU5PVEZPVU5EYCksIHdoaWNoIGlzIHdoYXQgdGhpcyB0ZWxscyBhcGFydC5cbiAqL1xuY29uc3QgU1FMU1RBVEVfUEFUVEVSTiA9IC9eWzAtOUEtWl17NX0kLztcblxuLyoqXG4gKiBMZW5ndGggYWxvbmUgaXMgbm90IGVub3VnaDogYEVQSVBFYCBhbmQgYEUyQklHYCBhcmUgZml2ZSB1cHBlcmNhc2UgY2hhcmFjdGVyc1xuICogYW5kIHdvdWxkIHBhc3MgYXMgU1FMU1RBVEVzLiBFdmVyeSBsaWJ1di9Ob2RlIGVycm5vIHN0YXJ0cyB3aXRoIGBFYCwgYW5kXG4gKiBQb3N0Z3JlcyBkZWZpbmVzIG5vIGVycm9yIGNsYXNzIHRoYXQgZG9lcyDigJQgaXRzIGNsYXNzZXMgYXJlIDAwLTBaLCAyMC0yRixcbiAqIDM0LTNGLCA0MC00NCwgNTMtNTgsIDcyLCBGMCwgSFYsIFAwIGFuZCBYWCAoc2VlIHRoZSBzZXJ2ZXIncyBlcnJjb2Rlcy50eHQpLlxuICogU28gYSBsZWFkaW5nIGBFYCBzZXR0bGVzIGl0LlxuICovXG5jb25zdCBOT0RFX0VSUk5PX1BBVFRFUk4gPSAvXkUvO1xuXG4vKipcbiAqIEV4dHJhY3QgZGF0YWJhc2UgZXJyb3IgZGV0YWlscyBmb3IgbG9nZ2luZy9yZXNwb25zZS5cbiAqXG4gKiBFeHRyYWN0cyBQb3N0Z3JlU1FMIGVycm9yIGNvZGVzLCBkZXRhaWxzLCBoaW50cywgYW5kIGNvbnN0cmFpbnQgbmFtZXNcbiAqIGZyb20gZGF0YWJhc2UgZXJyb3JzIGZvciBiZXR0ZXIgZXJyb3IgbWVzc2FnZXMuXG4gKlxuICogT25seSBhIGdlbnVpbmUgUG9zdGdyZXMgZXJyb3IgeWllbGRzIGEgYGRiQ29kZWA6IHJlcG9ydGluZyBhbnkgYC5jb2RlYCBhcyBvbmVcbiAqIHdvdWxkIGxvZyBhIHRyYW5zcG9ydCBmYWlsdXJlIChgRUNPTk5SRVNFVGAgd2hlbiB0aGUgcG9vbGVyIGRyb3BzIG91dCBvZiB0aGVcbiAqIFNlcnZpY2UgZW5kcG9pbnRzLCBzYXkpIGFzIGB7XCJkYlwiOntcImRiQ29kZVwiOlwiRUNPTk5SRVNFVFwifX1gIGFuZCBzZW5kIHJlYWRlcnNcbiAqIGh1bnRpbmcgdGhyb3VnaCBjbGVhbiBQb3N0Z3JlcyBsb2dzLiBUaGUgdHJhbnNwb3J0IGNvZGUgaXMgbm90IGxvc3Qg4oCUIGNhbGxlcnMgbG9nIHRoZSBlcnJvciBtZXNzYWdlXG4gKiBpdHNlbGYgYWxvbmdzaWRlIHRoZXNlIGRldGFpbHMg4oCUIGl0IGp1c3Qgc3RvcHMgY2xhaW1pbmcgdG8gYmUgYSBEQiBmYXVsdC5cbiAqXG4gKiBAcGFyYW0gZXJyb3IgLSBFcnJvciBvYmplY3QgZnJvbSBkYXRhYmFzZSBvcGVyYXRpb25cbiAqIEByZXR1cm5zIE9iamVjdCB3aXRoIGV4dHJhY3RlZCBlcnJvciBkZXRhaWxzOyBge31gIHdoZW4gYGVycm9yYCBpcyBub3QgYVxuICogICBQb3N0Z3JlcyBlcnJvciAobm8gU1FMU1RBVEUgYW5kIG5vbmUgb2YgdGhlIHBnLXNwZWNpZmljIGZpZWxkcylcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogdHJ5IHtcbiAqICAgYXdhaXQgZGIuaW5zZXJ0KHBsdWdpbnMpLnZhbHVlcyhuZXdQbHVnaW4pO1xuICogfSBjYXRjaCAoZXJyb3IpIHtcbiAqICAgY29uc3QgZGJEZXRhaWxzID0gZXh0cmFjdERiRXJyb3IoZXJyb3IpO1xuICogICByZXR1cm4gc2VuZEVycm9yKHJlcywgNTAwLCAnRGF0YWJhc2UgZXJyb3InLCBFcnJvckNvZGUuREFUQUJBU0VfRVJST1IsIGRiRGV0YWlscyk7XG4gKiB9XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV4dHJhY3REYkVycm9yKGVycm9yOiB1bmtub3duKTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4ge1xuICBpZiAoIWVycm9yIHx8IHR5cGVvZiBlcnJvciAhPT0gJ29iamVjdCcpIHtcbiAgICByZXR1cm4ge307XG4gIH1cblxuICAvLyBEcml6emxlIE9STSB3cmFwcyB0aGUgb3JpZ2luYWwgcGcgZXJyb3IgaW4gZXJyb3IuY2F1c2Ug4oCUXG4gIC8vIGNoZWNrIHRoZSBjYXVzZSBmaXJzdCwgdGhlbiBmYWxsIGJhY2sgdG8gdGhlIGVycm9yIGl0c2VsZi5cbiAgY29uc3QgZXJyID0gZXJyb3IgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIGNvbnN0IHNvdXJjZSA9IChlcnIuY2F1c2UgJiYgdHlwZW9mIGVyci5jYXVzZSA9PT0gJ29iamVjdCcgPyBlcnIuY2F1c2UgOiBlcnIpIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBjb25zdCBkZXRhaWxzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHt9O1xuXG4gIGlmICh0eXBlb2Ygc291cmNlLmNvZGUgPT09ICdzdHJpbmcnXG4gICAgJiYgU1FMU1RBVEVfUEFUVEVSTi50ZXN0KHNvdXJjZS5jb2RlKVxuICAgICYmICFOT0RFX0VSUk5PX1BBVFRFUk4udGVzdChzb3VyY2UuY29kZSkpIHtcbiAgICBkZXRhaWxzLmRiQ29kZSA9IHNvdXJjZS5jb2RlO1xuICB9XG4gIGlmIChzb3VyY2UuZGV0YWlsKSBkZXRhaWxzLmRiRGV0YWlsID0gc291cmNlLmRldGFpbDtcbiAgaWYgKHNvdXJjZS5oaW50KSBkZXRhaWxzLmRiSGludCA9IHNvdXJjZS5oaW50O1xuICBpZiAoc291cmNlLmNvbnN0cmFpbnQpIGRldGFpbHMuY29uc3RyYWludCA9IHNvdXJjZS5jb25zdHJhaW50O1xuICBpZiAoc291cmNlLnRhYmxlKSBkZXRhaWxzLnRhYmxlID0gc291cmNlLnRhYmxlO1xuICBpZiAoc291cmNlLmNvbHVtbikgZGV0YWlscy5jb2x1bW4gPSBzb3VyY2UuY29sdW1uO1xuXG4gIHJldHVybiBkZXRhaWxzO1xufVxuXG4vLyBDb252ZW5pZW5jZSBoZWxwZXJzIChzaGFyZWQgYWNyb3NzIHBsdWdpbiwgcGlwZWxpbmUsIHF1b3RhIHNlcnZpY2VzKVxuXG4vKipcbiAqIEV4dHJhY3QgYSBodW1hbi1yZWFkYWJsZSBtZXNzYWdlIGZyb20gYW4gdW5rbm93biBjYXRjaCB2YWx1ZS5cbiAqXG4gKiBGYWxscyBiYWNrIGJleW9uZCBgLm1lc3NhZ2VgIGJlY2F1c2Ugc2V2ZXJhbCBjb21tb24gTm9kZSBlcnJvcnMgY2FycnkgYW5cbiAqIEVNUFRZIGAubWVzc2FnZWA6XG4gKiAgLSBkdWFsLXN0YWNrIChJUHY0K0lQdjYpIGNvbm5lY3QgZmFpbHVyZXMgc3VyZmFjZSBhcyBhbiBgQWdncmVnYXRlRXJyb3JgXG4gKiAgICB3aG9zZSBvd24gbWVzc2FnZSBpcyBibGFuayDigJQgdGhlIGNhdXNlIGxpdmVzIGluIGAuY29kZWAgKGUuZy5cbiAqICAgIGBFQ09OTlJFRlVTRURgL2BFVElNRURPVVRgKSBhbmQvb3IgdGhlIGAuZXJyb3JzW11gIHN1Yi1lcnJvcnM7XG4gKiAgLSByYXcgc29ja2V0IGBFcnJub0V4Y2VwdGlvbmBzIGNhbiBsaWtld2lzZSBjYXJyeSBvbmx5IGEgYC5jb2RlYC5cbiAqIFdpdGhvdXQgdGhpcywgYW4gdW5yZWFjaGFibGUgaW50ZXJuYWwgc2VydmljZSAoZS5nLiBjb21wbGlhbmNlIHN0aWxsXG4gKiBzdGFydGluZykgcHJvZHVjZWQgYmxhbmsgcGVyLWl0ZW0gZXJyb3JzIGluIGJ1bGsgcmVzcG9uc2VzIGFuZCBgZXJyb3I6XCJcImBcbiAqIGluIGxvZ3Mg4oCUIGEgc2lsZW50IGJsYWNrIGJveC4gT3JkZXI6IG1lc3NhZ2Ug4oaSIGNvZGUg4oaSIGpvaW5lZCBzdWItZXJyb3JzIOKGklxuICogZXJyb3IgbmFtZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVycm9yTWVzc2FnZShlcnJvcjogdW5rbm93bik6IHN0cmluZyB7XG4gIGlmICghKGVycm9yIGluc3RhbmNlb2YgRXJyb3IpKSByZXR1cm4gU3RyaW5nKGVycm9yKTtcbiAgaWYgKGVycm9yLm1lc3NhZ2UpIHJldHVybiBlcnJvci5tZXNzYWdlO1xuXG4gIGNvbnN0IGNvZGUgPSAoZXJyb3IgYXMgeyBjb2RlPzogc3RyaW5nIH0pLmNvZGU7XG4gIGlmIChjb2RlKSByZXR1cm4gY29kZTtcblxuICBjb25zdCBpbm5lciA9IChlcnJvciBhcyB7IGVycm9ycz86IHVua25vd25bXSB9KS5lcnJvcnM7XG4gIGlmIChBcnJheS5pc0FycmF5KGlubmVyKSAmJiBpbm5lci5sZW5ndGggPiAwKSB7XG4gICAgY29uc3Qgam9pbmVkID0gaW5uZXIubWFwKGVycm9yTWVzc2FnZSkuZmlsdGVyKEJvb2xlYW4pLmpvaW4oJzsgJyk7XG4gICAgaWYgKGpvaW5lZCkgcmV0dXJuIGpvaW5lZDtcbiAgfVxuXG4gIHJldHVybiBlcnJvci5uYW1lIHx8ICdVbmtub3duIGVycm9yJztcbn1cblxuLyoqIFNlbmQgYSA0MDAgYmFkLXJlcXVlc3QgcmVzcG9uc2UuICovXG5leHBvcnQgZnVuY3Rpb24gc2VuZEJhZFJlcXVlc3QoXG4gIHJlczogUmVzcG9uc2UsXG4gIG1lc3NhZ2U6IHN0cmluZyxcbiAgY29kZTogRXJyb3JDb2RlIHwgc3RyaW5nID0gRXJyb3JDb2RlLlZBTElEQVRJT05fRVJST1IsXG4pOiB2b2lkIHtcbiAgc2VuZEVycm9yKHJlcywgNDAwLCBtZXNzYWdlLCBjb2RlKTtcbn1cblxuLyoqIFNlbmQgYSA1MDAgaW50ZXJuYWwgZXJyb3IgcmVzcG9uc2UuICovXG5leHBvcnQgZnVuY3Rpb24gc2VuZEludGVybmFsRXJyb3IoXG4gIHJlczogUmVzcG9uc2UsXG4gIG1lc3NhZ2U6IHN0cmluZyxcbiAgZGV0YWlscz86IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuKTogdm9pZCB7XG4gIHNlbmRFcnJvcihyZXMsIDUwMCwgbWVzc2FnZSwgRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SLCBkZXRhaWxzKTtcbn1cblxuLy8gUGFnaW5hdGlvblxuXG4vKiogQ29tbW9uIHBhZ2luYXRpb24gKyBzb3J0aW5nIHBhcmFtZXRlcnMuICovXG5leHBvcnQgaW50ZXJmYWNlIFBhZ2luYXRpb25QYXJhbXMge1xuICBsaW1pdDogbnVtYmVyO1xuICBvZmZzZXQ6IG51bWJlcjtcbiAgc29ydEJ5OiBzdHJpbmc7XG4gIHNvcnRPcmRlcjogJ2FzYycgfCAnZGVzYyc7XG59XG5cbi8qKiBBIHBhcnNlZCBgP3NvcnRCeT0mc29ydE9yZGVyPWAgKGRlZmF1bHQ6IG5ld2VzdCBmaXJzdCkuICovXG5leHBvcnQgaW50ZXJmYWNlIFNvcnRQYXJhbXMge1xuICBzb3J0Qnk6IHN0cmluZztcbiAgc29ydE9yZGVyOiAnYXNjJyB8ICdkZXNjJztcbn1cblxuLyoqIFBhcnNlIGA/c29ydEJ5PSZzb3J0T3JkZXI9YDsgZGVmYXVsdHMgdG8gYGNyZWF0ZWRBdGAgZGVzY2VuZGluZy4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZVNvcnQocXVlcnk6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogU29ydFBhcmFtcyB7XG4gIGNvbnN0IHNvcnRCeSA9IFN0cmluZyhxdWVyeS5zb3J0QnkgfHwgJ2NyZWF0ZWRBdCcpO1xuICBjb25zdCBzb3J0T3JkZXI6ICdhc2MnIHwgJ2Rlc2MnID1cbiAgICBTdHJpbmcocXVlcnkuc29ydE9yZGVyIHx8ICdkZXNjJykudG9Mb3dlckNhc2UoKSA9PT0gJ2FzYycgPyAnYXNjJyA6ICdkZXNjJztcbiAgcmV0dXJuIHsgc29ydEJ5LCBzb3J0T3JkZXIgfTtcbn1cblxuLyoqXG4gKiBUaGUgZGVmYXVsdCBsaXN0LXJvdXRlIHdpbmRvdyArIHNvcnQ6IHtAbGluayBwYXJzZVBhZ2V9IHdpdGggYSBwYWdlIG9mIDEwXG4gKiAoY2FwcGVkIGF0IGBNQVhfUEFHRV9MSU1JVGAsIG9mZnNldCBjYXBwZWQgYXQgYE1BWF9QQUdFX09GRlNFVGAg4oCUIGRlZXAgcGFnaW5nXG4gKiB1c2VzIHRoZSBjdXJzb3IgQVBJKSBwbHVzIHtAbGluayBwYXJzZVNvcnR9LlxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VQYWdpbmF0aW9uUGFyYW1zKHF1ZXJ5OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IFBhZ2luYXRpb25QYXJhbXMge1xuICByZXR1cm4geyAuLi5wYXJzZVBhZ2UocXVlcnksIHsgZGVmOiAxMCwgbWF4OiBNQVhfUEFHRV9MSU1JVCB9KSwgLi4ucGFyc2VTb3J0KHF1ZXJ5KSB9O1xufVxuIl19
|