@dbx-tools/core 0.9.60 → 0.9.64

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/index.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  // Hand edits are overwritten on the next watch; this file is read-only.
4
4
 
5
5
  export const PACKAGE_IDENTIFIER = "@dbx-tools/core";
6
- export const PACKAGE_VERSION = "0.9.60";
6
+ export const PACKAGE_VERSION = "0.9.64";
7
7
  export * as bin from "./src/bin.ts";
8
8
  export * as brandFiles from "./src/brand-files.ts";
9
9
  export * as bundle from "./src/bundle.ts";
@@ -14,7 +14,7 @@ export * as file from "./src/file.ts";
14
14
  export * as fileLock from "./src/file-lock.ts";
15
15
  export * as processLock from "./src/process-lock.ts";
16
16
  export * as projectUtils from "./src/project-utils.ts";
17
- export type { BinContext, BinSelectionContext, BinSelector, BinVersionOutput, BinVersionParser, BinOptions, BinUrlResolveContext, BinSource, BinUrl } from "./src/bin.ts";
17
+ export type { BinContext, BinSelectionContext, BinSelector, BinVersionOutput, BinVersionParser, BinOptions, BinPackageOptions, BinUrlResolveContext, BinSource, BinUrl } from "./src/bin.ts";
18
18
  export { BrandContextSchema, defaultBrandContext, parseBrandContext, brandContextJsonSchema, brandContextPrompt } from "./src/brand-files.ts";
19
19
  export type { BrandContext, BrandContextInput } from "./src/brand-files.ts";
20
20
  export { MAX_TCP_PORT, ENV_ONLY, valueSchema, bundleResourceSchema, bundleEnvEntrySchema, bundleAppSchema, appEnvEntrySchema, appSchema } from "./src/config-utils.ts";
package/lib/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export declare const PACKAGE_IDENTIFIER = "@dbx-tools/core";
2
- export declare const PACKAGE_VERSION = "0.9.60";
2
+ export declare const PACKAGE_VERSION = "0.9.64";
3
3
  export * as bin from "./src/bin.ts";
4
4
  export * as brandFiles from "./src/brand-files.ts";
5
5
  export * as bundle from "./src/bundle.ts";
@@ -10,7 +10,7 @@ export * as file from "./src/file.ts";
10
10
  export * as fileLock from "./src/file-lock.ts";
11
11
  export * as processLock from "./src/process-lock.ts";
12
12
  export * as projectUtils from "./src/project-utils.ts";
13
- export type { BinContext, BinSelectionContext, BinSelector, BinVersionOutput, BinVersionParser, BinOptions, BinUrlResolveContext, BinSource, BinUrl } from "./src/bin.ts";
13
+ export type { BinContext, BinSelectionContext, BinSelector, BinVersionOutput, BinVersionParser, BinOptions, BinPackageOptions, BinUrlResolveContext, BinSource, BinUrl } from "./src/bin.ts";
14
14
  export { BrandContextSchema, defaultBrandContext, parseBrandContext, brandContextJsonSchema, brandContextPrompt } from "./src/brand-files.ts";
15
15
  export type { BrandContext, BrandContextInput } from "./src/brand-files.ts";
16
16
  export { MAX_TCP_PORT, ENV_ONLY, valueSchema, bundleResourceSchema, bundleEnvEntrySchema, bundleAppSchema, appEnvEntrySchema, appSchema } from "./src/config-utils.ts";
package/lib/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  // Regenerated from the exporting modules in ./src.
3
3
  // Hand edits are overwritten on the next watch; this file is read-only.
4
4
  export const PACKAGE_IDENTIFIER = "@dbx-tools/core";
5
- export const PACKAGE_VERSION = "0.9.60";
5
+ export const PACKAGE_VERSION = "0.9.64";
6
6
  export * as bin from "./src/bin.js";
7
7
  export * as brandFiles from "./src/brand-files.js";
8
8
  export * as bundle from "./src/bundle.js";
@@ -16,4 +16,4 @@ export * as projectUtils from "./src/project-utils.js";
16
16
  export { BrandContextSchema, defaultBrandContext, parseBrandContext, brandContextJsonSchema, brandContextPrompt } from "./src/brand-files.js";
17
17
  export { MAX_TCP_PORT, ENV_ONLY, valueSchema, bundleResourceSchema, bundleEnvEntrySchema, bundleAppSchema, appEnvEntrySchema, appSchema } from "./src/config-utils.js";
18
18
  export { COMMAND_NOT_FOUND_EXIT_CODE } from "./src/exec.js";
19
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxpQkFBaUIsQ0FBQztBQUNwRCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsUUFBUSxDQUFDO0FBQ3hDLE9BQU8sS0FBSyxHQUFHLE1BQU0sY0FBYyxDQUFDO0FBQ3BDLE9BQU8sS0FBSyxVQUFVLE1BQU0sc0JBQXNCLENBQUM7QUFDbkQsT0FBTyxLQUFLLE1BQU0sTUFBTSxpQkFBaUIsQ0FBQztBQUMxQyxPQUFPLEtBQUssV0FBVyxNQUFNLHVCQUF1QixDQUFDO0FBQ3JELE9BQU8sS0FBSyxrQkFBa0IsTUFBTSw4QkFBOEIsQ0FBQztBQUNuRSxPQUFPLEtBQUssSUFBSSxNQUFNLGVBQWUsQ0FBQztBQUN0QyxPQUFPLEtBQUssSUFBSSxNQUFNLGVBQWUsQ0FBQztBQUN0QyxPQUFPLEtBQUssUUFBUSxNQUFNLG9CQUFvQixDQUFDO0FBQy9DLE9BQU8sS0FBSyxXQUFXLE1BQU0sdUJBQXVCLENBQUM7QUFDckQsT0FBTyxLQUFLLFlBQVksTUFBTSx3QkFBd0IsQ0FBQztBQUV2RCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsbUJBQW1CLEVBQUUsaUJBQWlCLEVBQUUsc0JBQXNCLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUU5SSxPQUFPLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxXQUFXLEVBQUUsb0JBQW9CLEVBQUUsb0JBQW9CLEVBQUUsZUFBZSxFQUFFLGlCQUFpQixFQUFFLFNBQVMsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBR3ZLLE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxNQUFNLGVBQWUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEdFTkVSQVRFRCBieSBwcm9qZW4gd2F0Y2ggLSBETyBOT1QgRURJVC5cbi8vIFJlZ2VuZXJhdGVkIGZyb20gdGhlIGV4cG9ydGluZyBtb2R1bGVzIGluIC4vc3JjLlxuLy8gSGFuZCBlZGl0cyBhcmUgb3ZlcndyaXR0ZW4gb24gdGhlIG5leHQgd2F0Y2g7IHRoaXMgZmlsZSBpcyByZWFkLW9ubHkuXG5cbmV4cG9ydCBjb25zdCBQQUNLQUdFX0lERU5USUZJRVIgPSBcIkBkYngtdG9vbHMvY29yZVwiO1xuZXhwb3J0IGNvbnN0IFBBQ0tBR0VfVkVSU0lPTiA9IFwiMC45LjYwXCI7XG5leHBvcnQgKiBhcyBiaW4gZnJvbSBcIi4vc3JjL2Jpbi50c1wiO1xuZXhwb3J0ICogYXMgYnJhbmRGaWxlcyBmcm9tIFwiLi9zcmMvYnJhbmQtZmlsZXMudHNcIjtcbmV4cG9ydCAqIGFzIGJ1bmRsZSBmcm9tIFwiLi9zcmMvYnVuZGxlLnRzXCI7XG5leHBvcnQgKiBhcyBjb25maWdVdGlscyBmcm9tIFwiLi9zcmMvY29uZmlnLXV0aWxzLnRzXCI7XG5leHBvcnQgKiBhcyBkZXBlbmRlbmN5UmVzb2x2ZXIgZnJvbSBcIi4vc3JjL2RlcGVuZGVuY3ktcmVzb2x2ZXIudHNcIjtcbmV4cG9ydCAqIGFzIGV4ZWMgZnJvbSBcIi4vc3JjL2V4ZWMudHNcIjtcbmV4cG9ydCAqIGFzIGZpbGUgZnJvbSBcIi4vc3JjL2ZpbGUudHNcIjtcbmV4cG9ydCAqIGFzIGZpbGVMb2NrIGZyb20gXCIuL3NyYy9maWxlLWxvY2sudHNcIjtcbmV4cG9ydCAqIGFzIHByb2Nlc3NMb2NrIGZyb20gXCIuL3NyYy9wcm9jZXNzLWxvY2sudHNcIjtcbmV4cG9ydCAqIGFzIHByb2plY3RVdGlscyBmcm9tIFwiLi9zcmMvcHJvamVjdC11dGlscy50c1wiO1xuZXhwb3J0IHR5cGUgeyBCaW5Db250ZXh0LCBCaW5TZWxlY3Rpb25Db250ZXh0LCBCaW5TZWxlY3RvciwgQmluVmVyc2lvbk91dHB1dCwgQmluVmVyc2lvblBhcnNlciwgQmluT3B0aW9ucywgQmluVXJsUmVzb2x2ZUNvbnRleHQsIEJpblNvdXJjZSwgQmluVXJsIH0gZnJvbSBcIi4vc3JjL2Jpbi50c1wiO1xuZXhwb3J0IHsgQnJhbmRDb250ZXh0U2NoZW1hLCBkZWZhdWx0QnJhbmRDb250ZXh0LCBwYXJzZUJyYW5kQ29udGV4dCwgYnJhbmRDb250ZXh0SnNvblNjaGVtYSwgYnJhbmRDb250ZXh0UHJvbXB0IH0gZnJvbSBcIi4vc3JjL2JyYW5kLWZpbGVzLnRzXCI7XG5leHBvcnQgdHlwZSB7IEJyYW5kQ29udGV4dCwgQnJhbmRDb250ZXh0SW5wdXQgfSBmcm9tIFwiLi9zcmMvYnJhbmQtZmlsZXMudHNcIjtcbmV4cG9ydCB7IE1BWF9UQ1BfUE9SVCwgRU5WX09OTFksIHZhbHVlU2NoZW1hLCBidW5kbGVSZXNvdXJjZVNjaGVtYSwgYnVuZGxlRW52RW50cnlTY2hlbWEsIGJ1bmRsZUFwcFNjaGVtYSwgYXBwRW52RW50cnlTY2hlbWEsIGFwcFNjaGVtYSB9IGZyb20gXCIuL3NyYy9jb25maWctdXRpbHMudHNcIjtcbmV4cG9ydCB0eXBlIHsgQ29uZmlnTWFwVmFsdWUsIENvbmZpZ0RhdGEsIENvbmZpZ1NvdXJjZSwgQ29uZmlnT3B0aW9ucywgQ29uZmlnRmlsZSB9IGZyb20gXCIuL3NyYy9jb25maWctdXRpbHMudHNcIjtcbmV4cG9ydCB0eXBlIHsgRGVwZW5kZW5jeVJlc29sdmVyT3B0aW9ucywgRGVwZW5kZW5jeUluZm8sIFJlc29sdmVkTnBtVmVyc2lvbiwgTnBtU3BlY2lmaWVySW5wdXQsIFJlc29sdmVkTnBtRGVwZW5kZW5jaWVzLCBNaXNzaW5nRGVwZW5kZW5jeUluZm8gfSBmcm9tIFwiLi9zcmMvZGVwZW5kZW5jeS1yZXNvbHZlci50c1wiO1xuZXhwb3J0IHsgQ09NTUFORF9OT1RfRk9VTkRfRVhJVF9DT0RFIH0gZnJvbSBcIi4vc3JjL2V4ZWMudHNcIjtcbmV4cG9ydCB0eXBlIHsgRXhlY1N0ZGlvLCBMaW5lSGFuZGxlciwgTGluZU91dHB1dE9wdGlvbnMsIFN0ZGlvT3B0aW9uLCBFeGVjUmVzdWx0LCBDaGlsZFByb2Nlc3NSZXN1bHQsIEV4ZWNPcHRpb25zLCBTeW5jRXhlY1N0ZGlvLCBTeW5jRXhlY09wdGlvbnMsIFNwYXduQXJncyB9IGZyb20gXCIuL3NyYy9leGVjLnRzXCI7XG5leHBvcnQgdHlwZSB7IEZpbGVMb2NrQmFja2VuZCwgRmlsZUxvY2tBY3F1aXNpdGlvbiwgRmlsZUxvY2tPcHRpb25zLCBGaWxlTG9ja0xlYXNlIH0gZnJvbSBcIi4vc3JjL2ZpbGUtbG9jay50c1wiO1xuZXhwb3J0IHR5cGUgeyBQcm9qZWN0Q29udGV4dCwgTnBtUmVnaXN0cnlPcHRpb25zIH0gZnJvbSBcIi4vc3JjL3Byb2plY3QtdXRpbHMudHNcIjtcbiJdfQ==
19
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxpQkFBaUIsQ0FBQztBQUNwRCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsUUFBUSxDQUFDO0FBQ3hDLE9BQU8sS0FBSyxHQUFHLE1BQU0sY0FBYyxDQUFDO0FBQ3BDLE9BQU8sS0FBSyxVQUFVLE1BQU0sc0JBQXNCLENBQUM7QUFDbkQsT0FBTyxLQUFLLE1BQU0sTUFBTSxpQkFBaUIsQ0FBQztBQUMxQyxPQUFPLEtBQUssV0FBVyxNQUFNLHVCQUF1QixDQUFDO0FBQ3JELE9BQU8sS0FBSyxrQkFBa0IsTUFBTSw4QkFBOEIsQ0FBQztBQUNuRSxPQUFPLEtBQUssSUFBSSxNQUFNLGVBQWUsQ0FBQztBQUN0QyxPQUFPLEtBQUssSUFBSSxNQUFNLGVBQWUsQ0FBQztBQUN0QyxPQUFPLEtBQUssUUFBUSxNQUFNLG9CQUFvQixDQUFDO0FBQy9DLE9BQU8sS0FBSyxXQUFXLE1BQU0sdUJBQXVCLENBQUM7QUFDckQsT0FBTyxLQUFLLFlBQVksTUFBTSx3QkFBd0IsQ0FBQztBQUV2RCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsbUJBQW1CLEVBQUUsaUJBQWlCLEVBQUUsc0JBQXNCLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUU5SSxPQUFPLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxXQUFXLEVBQUUsb0JBQW9CLEVBQUUsb0JBQW9CLEVBQUUsZUFBZSxFQUFFLGlCQUFpQixFQUFFLFNBQVMsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBR3ZLLE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxNQUFNLGVBQWUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEdFTkVSQVRFRCBieSBwcm9qZW4gd2F0Y2ggLSBETyBOT1QgRURJVC5cbi8vIFJlZ2VuZXJhdGVkIGZyb20gdGhlIGV4cG9ydGluZyBtb2R1bGVzIGluIC4vc3JjLlxuLy8gSGFuZCBlZGl0cyBhcmUgb3ZlcndyaXR0ZW4gb24gdGhlIG5leHQgd2F0Y2g7IHRoaXMgZmlsZSBpcyByZWFkLW9ubHkuXG5cbmV4cG9ydCBjb25zdCBQQUNLQUdFX0lERU5USUZJRVIgPSBcIkBkYngtdG9vbHMvY29yZVwiO1xuZXhwb3J0IGNvbnN0IFBBQ0tBR0VfVkVSU0lPTiA9IFwiMC45LjY0XCI7XG5leHBvcnQgKiBhcyBiaW4gZnJvbSBcIi4vc3JjL2Jpbi50c1wiO1xuZXhwb3J0ICogYXMgYnJhbmRGaWxlcyBmcm9tIFwiLi9zcmMvYnJhbmQtZmlsZXMudHNcIjtcbmV4cG9ydCAqIGFzIGJ1bmRsZSBmcm9tIFwiLi9zcmMvYnVuZGxlLnRzXCI7XG5leHBvcnQgKiBhcyBjb25maWdVdGlscyBmcm9tIFwiLi9zcmMvY29uZmlnLXV0aWxzLnRzXCI7XG5leHBvcnQgKiBhcyBkZXBlbmRlbmN5UmVzb2x2ZXIgZnJvbSBcIi4vc3JjL2RlcGVuZGVuY3ktcmVzb2x2ZXIudHNcIjtcbmV4cG9ydCAqIGFzIGV4ZWMgZnJvbSBcIi4vc3JjL2V4ZWMudHNcIjtcbmV4cG9ydCAqIGFzIGZpbGUgZnJvbSBcIi4vc3JjL2ZpbGUudHNcIjtcbmV4cG9ydCAqIGFzIGZpbGVMb2NrIGZyb20gXCIuL3NyYy9maWxlLWxvY2sudHNcIjtcbmV4cG9ydCAqIGFzIHByb2Nlc3NMb2NrIGZyb20gXCIuL3NyYy9wcm9jZXNzLWxvY2sudHNcIjtcbmV4cG9ydCAqIGFzIHByb2plY3RVdGlscyBmcm9tIFwiLi9zcmMvcHJvamVjdC11dGlscy50c1wiO1xuZXhwb3J0IHR5cGUgeyBCaW5Db250ZXh0LCBCaW5TZWxlY3Rpb25Db250ZXh0LCBCaW5TZWxlY3RvciwgQmluVmVyc2lvbk91dHB1dCwgQmluVmVyc2lvblBhcnNlciwgQmluT3B0aW9ucywgQmluUGFja2FnZU9wdGlvbnMsIEJpblVybFJlc29sdmVDb250ZXh0LCBCaW5Tb3VyY2UsIEJpblVybCB9IGZyb20gXCIuL3NyYy9iaW4udHNcIjtcbmV4cG9ydCB7IEJyYW5kQ29udGV4dFNjaGVtYSwgZGVmYXVsdEJyYW5kQ29udGV4dCwgcGFyc2VCcmFuZENvbnRleHQsIGJyYW5kQ29udGV4dEpzb25TY2hlbWEsIGJyYW5kQ29udGV4dFByb21wdCB9IGZyb20gXCIuL3NyYy9icmFuZC1maWxlcy50c1wiO1xuZXhwb3J0IHR5cGUgeyBCcmFuZENvbnRleHQsIEJyYW5kQ29udGV4dElucHV0IH0gZnJvbSBcIi4vc3JjL2JyYW5kLWZpbGVzLnRzXCI7XG5leHBvcnQgeyBNQVhfVENQX1BPUlQsIEVOVl9PTkxZLCB2YWx1ZVNjaGVtYSwgYnVuZGxlUmVzb3VyY2VTY2hlbWEsIGJ1bmRsZUVudkVudHJ5U2NoZW1hLCBidW5kbGVBcHBTY2hlbWEsIGFwcEVudkVudHJ5U2NoZW1hLCBhcHBTY2hlbWEgfSBmcm9tIFwiLi9zcmMvY29uZmlnLXV0aWxzLnRzXCI7XG5leHBvcnQgdHlwZSB7IENvbmZpZ01hcFZhbHVlLCBDb25maWdEYXRhLCBDb25maWdTb3VyY2UsIENvbmZpZ09wdGlvbnMsIENvbmZpZ0ZpbGUgfSBmcm9tIFwiLi9zcmMvY29uZmlnLXV0aWxzLnRzXCI7XG5leHBvcnQgdHlwZSB7IERlcGVuZGVuY3lSZXNvbHZlck9wdGlvbnMsIERlcGVuZGVuY3lJbmZvLCBSZXNvbHZlZE5wbVZlcnNpb24sIE5wbVNwZWNpZmllcklucHV0LCBSZXNvbHZlZE5wbURlcGVuZGVuY2llcywgTWlzc2luZ0RlcGVuZGVuY3lJbmZvIH0gZnJvbSBcIi4vc3JjL2RlcGVuZGVuY3ktcmVzb2x2ZXIudHNcIjtcbmV4cG9ydCB7IENPTU1BTkRfTk9UX0ZPVU5EX0VYSVRfQ09ERSB9IGZyb20gXCIuL3NyYy9leGVjLnRzXCI7XG5leHBvcnQgdHlwZSB7IEV4ZWNTdGRpbywgTGluZUhhbmRsZXIsIExpbmVPdXRwdXRPcHRpb25zLCBTdGRpb09wdGlvbiwgRXhlY1Jlc3VsdCwgQ2hpbGRQcm9jZXNzUmVzdWx0LCBFeGVjT3B0aW9ucywgU3luY0V4ZWNTdGRpbywgU3luY0V4ZWNPcHRpb25zLCBTcGF3bkFyZ3MgfSBmcm9tIFwiLi9zcmMvZXhlYy50c1wiO1xuZXhwb3J0IHR5cGUgeyBGaWxlTG9ja0JhY2tlbmQsIEZpbGVMb2NrQWNxdWlzaXRpb24sIEZpbGVMb2NrT3B0aW9ucywgRmlsZUxvY2tMZWFzZSB9IGZyb20gXCIuL3NyYy9maWxlLWxvY2sudHNcIjtcbmV4cG9ydCB0eXBlIHsgUHJvamVjdENvbnRleHQsIE5wbVJlZ2lzdHJ5T3B0aW9ucyB9IGZyb20gXCIuL3NyYy9wcm9qZWN0LXV0aWxzLnRzXCI7XG4iXX0=
package/lib/src/bin.d.ts CHANGED
@@ -25,6 +25,8 @@ export type BinVersionParser = (output: BinVersionOutput) => string | undefined;
25
25
  /** Options for {@link ensure}. */
26
26
  export interface BinOptions {
27
27
  autoUnpackage?: boolean;
28
+ /** Preserve an unpacked multi-file package rooted at {@link BinContext.root}. */
29
+ package?: BinPackageOptions;
28
30
  selector?: BinSelector;
29
31
  homeDir?: string;
30
32
  /** Exact installation paths. Omission keeps `$HOME/.<name>/bin/<name>`. */
@@ -40,6 +42,13 @@ export interface BinOptions {
40
42
  /** Reinstall even when the destination already passes validation. */
41
43
  force?: boolean;
42
44
  }
45
+ /** Multi-file archive layout retained beside its executable entrypoint. */
46
+ export interface BinPackageOptions {
47
+ /** Executable path relative to the unpacked package root. */
48
+ entrypoint: string;
49
+ /** Companion files or directories required before an installation can be reused. */
50
+ requiredPaths?: readonly string[];
51
+ }
43
52
  /** Temporary directory created for one `ensure` attempt after the install lock. */
44
53
  export interface BinUrlResolveContext {
45
54
  readonly tempDir: string;
@@ -61,9 +70,9 @@ export declare function parseVersion({ stdout, stderr }: BinVersionOutput): stri
61
70
  export declare function isVersionAtLeast(version: string, minVersion: string): boolean;
62
71
  /**
63
72
  * Return an existing executable or install it atomically under
64
- * `$HOME/.<name>/bin/<name>`. Installation uses a check-lock-check-load
65
- * sequence so concurrent callers resolve and download the binary only once.
66
- * The downloaded candidate and final renamed executable must both pass the
67
- * same executable and version checks.
73
+ * `$HOME/.<name>/bin/<name>`. Multi-file package mode atomically preserves the
74
+ * unpacked package at an explicit destination root. Installation uses a
75
+ * check-lock-check-load sequence so concurrent callers resolve and download
76
+ * only once. Candidates and final destinations must pass the same checks.
68
77
  */
69
78
  export declare function ensure(name: string, url: BinUrl, options?: BinOptions): Promise<BinContext>;
package/lib/src/bin.js CHANGED
@@ -5,9 +5,9 @@
5
5
  */
6
6
  import { execFile } from "node:child_process";
7
7
  import { createHash, randomUUID } from "node:crypto";
8
- import { chmod, copyFile, mkdir, mkdtemp, readdir, rename, rm, stat, writeFile, } from "node:fs/promises";
8
+ import { chmod, cp, copyFile, mkdir, mkdtemp, readdir, rename, rm, stat, writeFile, } from "node:fs/promises";
9
9
  import { homedir, tmpdir } from "node:os";
10
- import { basename, join } from "node:path";
10
+ import { basename, dirname, isAbsolute, join, resolve, sep } from "node:path";
11
11
  import { fileURLToPath } from "node:url";
12
12
  import { promisify } from "node:util";
13
13
  import * as errorUtils from "@dbx-tools/shared-core/error-utils";
@@ -28,6 +28,28 @@ function context(name, homeDir, destination) {
28
28
  const binDir = join(root, "bin");
29
29
  return { root, binDir, path: join(binDir, name) };
30
30
  }
31
+ function packagePath(root, path) {
32
+ if (!path || isAbsolute(path)) {
33
+ throw new TypeError(`invalid binary package path: ${path}`);
34
+ }
35
+ const packageRoot = resolve(root);
36
+ const resolved = resolve(packageRoot, path);
37
+ if (resolved === packageRoot || !resolved.startsWith(`${packageRoot}${sep}`)) {
38
+ throw new TypeError(`binary package path escapes its root: ${path}`);
39
+ }
40
+ return resolved;
41
+ }
42
+ function packageDestination(destination, options) {
43
+ if (!options.package)
44
+ return;
45
+ const entrypoint = packagePath(destination.root, options.package.entrypoint);
46
+ if (resolve(destination.path) !== entrypoint) {
47
+ throw new TypeError("binary package destination path must match its entrypoint");
48
+ }
49
+ for (const path of options.package.requiredPaths ?? []) {
50
+ packagePath(destination.root, path);
51
+ }
52
+ }
31
53
  function displayUrl(raw) {
32
54
  try {
33
55
  const url = new URL(raw);
@@ -145,6 +167,24 @@ async function isValidBin(path, options) {
145
167
  });
146
168
  return valid;
147
169
  }
170
+ async function pathExists(path) {
171
+ try {
172
+ await stat(path);
173
+ return true;
174
+ }
175
+ catch {
176
+ return false;
177
+ }
178
+ }
179
+ async function isValidInstall(destination, options) {
180
+ if (!(await isValidBin(destination.path, options)))
181
+ return false;
182
+ if (!options.package)
183
+ return true;
184
+ const required = [options.package.entrypoint, ...(options.package.requiredPaths ?? [])];
185
+ const available = await Promise.all(required.map((path) => pathExists(packagePath(destination.root, path))));
186
+ return available.every(Boolean);
187
+ }
148
188
  function downloadName(url, name) {
149
189
  try {
150
190
  const candidate = basename(decodeURIComponent(new URL(url).pathname));
@@ -202,44 +242,53 @@ function fileUrlPath(url) {
202
242
  async function selectedBin(destination, source, temp, options) {
203
243
  const { url } = source;
204
244
  const localPath = fileUrlPath(url);
245
+ let downloadPath;
205
246
  if (localPath) {
206
247
  const access = await accessContext(localPath);
207
248
  if (!access.file) {
208
249
  throw new Error(`binary file URL does not exist: ${displayUrl(url)}`);
209
250
  }
210
251
  logger.debug("using local binary", { from: displayUrl(url), path: localPath });
211
- return localPath;
252
+ downloadPath = localPath;
212
253
  }
213
- const name = downloadName(url, basename(destination.path));
214
- const downloadPath = join(temp, name);
215
- logger.debug("downloading binary", {
216
- from: displayUrl(url),
217
- to: downloadPath,
218
- });
219
- const response = await fetch(url);
220
- if (!response.ok) {
221
- throw new Error(`binary download failed (${response.status})`);
222
- }
223
- const downloaded = Buffer.from(await response.arrayBuffer());
224
- if (source.sha256) {
225
- if (!/^[0-9a-f]{64}$/i.test(source.sha256)) {
226
- throw new TypeError("binary download SHA-256 digest must contain 64 hexadecimal characters");
254
+ else {
255
+ const name = downloadName(url, basename(destination.path));
256
+ downloadPath = join(temp, name);
257
+ const download = {
258
+ from: displayUrl(url),
259
+ to: downloadPath,
260
+ };
261
+ if (download.from === "data:")
262
+ logger.debug("downloading binary", download);
263
+ else
264
+ logger.info("downloading binary", download);
265
+ const response = await fetch(url);
266
+ if (!response.ok) {
267
+ throw new Error(`binary download failed (${response.status})`);
227
268
  }
228
- const actual = createHash("sha256").update(downloaded).digest("hex");
229
- if (actual.toLowerCase() !== source.sha256.toLowerCase()) {
230
- throw new Error(`binary download digest mismatch: ${displayUrl(url)}`);
269
+ const downloaded = Buffer.from(await response.arrayBuffer());
270
+ if (source.sha256) {
271
+ if (!/^[0-9a-f]{64}$/i.test(source.sha256)) {
272
+ throw new TypeError("binary download SHA-256 digest must contain 64 hexadecimal characters");
273
+ }
274
+ const actual = createHash("sha256").update(downloaded).digest("hex");
275
+ if (actual.toLowerCase() !== source.sha256.toLowerCase()) {
276
+ throw new Error(`binary download digest mismatch: ${displayUrl(url)}`);
277
+ }
231
278
  }
279
+ await writeFile(downloadPath, downloaded, { mode: 0o755 });
232
280
  }
233
- await writeFile(downloadPath, downloaded, { mode: 0o755 });
234
281
  let selectedSource = downloadPath;
235
- if (options.autoUnpackage) {
282
+ let unpacked = false;
283
+ if (options.package || (options.autoUnpackage && !localPath)) {
236
284
  selectedSource = join(temp, `unpacked-${randomUUID()}`);
237
285
  await mkdir(selectedSource);
238
- logger.debug("unpacking binary archive", {
286
+ logger.info("unpacking binary archive", {
239
287
  archive: downloadPath,
240
288
  to: selectedSource,
241
289
  });
242
290
  await unpack(downloadPath, selectedSource);
291
+ unpacked = true;
243
292
  }
244
293
  if (options.selector) {
245
294
  const selected = await options.selector({
@@ -248,31 +297,84 @@ async function selectedBin(destination, source, temp, options) {
248
297
  source: selectedSource,
249
298
  });
250
299
  logger.debug("selected binary", { path: selected });
251
- return selected;
300
+ return { path: selected, ...(options.package ? { packageRoot: selectedSource } : {}) };
252
301
  }
253
- const selected = options.autoUnpackage ? await selectSingleFile(selectedSource) : selectedSource;
302
+ if (options.package) {
303
+ const selected = packagePath(selectedSource, options.package.entrypoint);
304
+ logger.debug("selected binary package entrypoint", { path: selected });
305
+ return { path: selected, packageRoot: selectedSource };
306
+ }
307
+ const selected = unpacked ? await selectSingleFile(selectedSource) : selectedSource;
254
308
  logger.debug("selected binary", { path: selected });
255
- return selected;
309
+ return { path: selected };
310
+ }
311
+ async function installPackage(source, destination, options) {
312
+ if (!options.package)
313
+ throw new Error("binary package options are required");
314
+ const parent = dirname(destination.root);
315
+ const name = basename(destination.root);
316
+ const stagedRoot = join(parent, `.${name}-staged-${randomUUID()}`);
317
+ const backupRoot = join(parent, `.${name}-backup-${randomUUID()}`);
318
+ await mkdir(parent, { recursive: true });
319
+ logger.info("staging binary package", {
320
+ from: source,
321
+ to: destination.root,
322
+ });
323
+ await cp(source, stagedRoot, { recursive: true });
324
+ const stagedPath = packagePath(stagedRoot, options.package.entrypoint);
325
+ await chmod(stagedPath, 0o755);
326
+ const staged = {
327
+ root: stagedRoot,
328
+ binDir: dirname(stagedPath),
329
+ path: stagedPath,
330
+ };
331
+ if (!(await isValidInstall(staged, options))) {
332
+ await rm(stagedRoot, { recursive: true, force: true });
333
+ throw new Error(`selected binary package is invalid: ${source}`);
334
+ }
335
+ let backedUp = false;
336
+ try {
337
+ if (await pathExists(destination.root)) {
338
+ await rename(destination.root, backupRoot);
339
+ backedUp = true;
340
+ }
341
+ await rename(stagedRoot, destination.root);
342
+ if (!(await isValidInstall(destination, options))) {
343
+ throw new Error(`installed binary package is invalid after rename: ${destination.root}`);
344
+ }
345
+ if (backedUp)
346
+ await rm(backupRoot, { recursive: true, force: true });
347
+ }
348
+ catch (error) {
349
+ await rm(destination.root, { recursive: true, force: true });
350
+ if (backedUp)
351
+ await rename(backupRoot, destination.root);
352
+ throw error;
353
+ }
354
+ finally {
355
+ await rm(stagedRoot, { recursive: true, force: true });
356
+ }
256
357
  }
257
358
  /**
258
359
  * Return an existing executable or install it atomically under
259
- * `$HOME/.<name>/bin/<name>`. Installation uses a check-lock-check-load
260
- * sequence so concurrent callers resolve and download the binary only once.
261
- * The downloaded candidate and final renamed executable must both pass the
262
- * same executable and version checks.
360
+ * `$HOME/.<name>/bin/<name>`. Multi-file package mode atomically preserves the
361
+ * unpacked package at an explicit destination root. Installation uses a
362
+ * check-lock-check-load sequence so concurrent callers resolve and download
363
+ * only once. Candidates and final destinations must pass the same checks.
263
364
  */
264
365
  export async function ensure(name, url, options = {}) {
265
366
  if (options.minVersion && !minimumSemVer(options.minVersion)) {
266
367
  throw new TypeError(`invalid minimum binary version: ${options.minVersion}`);
267
368
  }
268
369
  const destination = context(name, options.homeDir ?? homedir(), options.destination);
269
- if (!options.force && (await isValidBin(destination.path, options))) {
370
+ packageDestination(destination, options);
371
+ if (!options.force && (await isValidInstall(destination, options))) {
270
372
  logger.debug("using installed binary", { name, path: destination.path });
271
373
  return destination;
272
374
  }
273
375
  logger.debug("waiting for binary install lock", { name, path: destination.path });
274
376
  return withFileLock(["bin.ensure", destination.path], async () => {
275
- if (!options.force && (await isValidBin(destination.path, options))) {
377
+ if (!options.force && (await isValidInstall(destination, options))) {
276
378
  logger.debug("using binary installed by another caller", {
277
379
  name,
278
380
  path: destination.path,
@@ -292,18 +394,25 @@ export async function ensure(name, url, options = {}) {
292
394
  const from = displayUrl(source.url);
293
395
  logger.debug("resolved binary source", { name, from });
294
396
  const selected = await selectedBin(destination, source, temp, options);
295
- await chmod(selected, 0o755);
296
- if (!(await isValidBin(selected, options))) {
297
- throw new Error(`selected binary has no acceptable version: ${selected}`);
397
+ await chmod(selected.path, 0o755);
398
+ if (!(await isValidBin(selected.path, options))) {
399
+ throw new Error(`selected binary has no acceptable version: ${selected.path}`);
400
+ }
401
+ if (options.package) {
402
+ if (!selected.packageRoot)
403
+ throw new Error("binary package root was not selected");
404
+ await installPackage(selected.packageRoot, destination, options);
298
405
  }
299
- await mkdir(destination.binDir, { recursive: true });
300
- staged = join(destination.binDir, `.${name}-${randomUUID()}`);
301
- await copyFile(selected, staged);
302
- await chmod(staged, 0o755);
303
- await rename(staged, destination.path);
304
- staged = undefined;
305
- if (!(await isValidBin(destination.path, options))) {
306
- throw new Error(`installed binary is invalid after rename: ${destination.path}`);
406
+ else {
407
+ await mkdir(destination.binDir, { recursive: true });
408
+ staged = join(destination.binDir, `.${name}-${randomUUID()}`);
409
+ await copyFile(selected.path, staged);
410
+ await chmod(staged, 0o755);
411
+ await rename(staged, destination.path);
412
+ staged = undefined;
413
+ if (!(await isValidInstall(destination, options))) {
414
+ throw new Error(`installed binary is invalid after rename: ${destination.path}`);
415
+ }
307
416
  }
308
417
  logger.info("installed binary", {
309
418
  name,
@@ -319,4 +428,4 @@ export async function ensure(name, url, options = {}) {
319
428
  }
320
429
  });
321
430
  }
322
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmluLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2Jpbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHO0FBQ0gsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3JELE9BQU8sRUFDTCxLQUFLLEVBQ0wsUUFBUSxFQUNSLEtBQUssRUFDTCxPQUFPLEVBQ1AsT0FBTyxFQUNQLE1BQU0sRUFDTixFQUFFLEVBQ0YsSUFBSSxFQUNKLFNBQVMsR0FDVixNQUFNLGtCQUFrQixDQUFDO0FBQzFCLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQzFDLE9BQU8sRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQzNDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDekMsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUV0QyxPQUFPLEtBQUssVUFBVSxNQUFNLG9DQUFvQyxDQUFDO0FBQ2pFLE9BQU8sS0FBSyxHQUFHLE1BQU0sNEJBQTRCLENBQUM7QUFDbEQsT0FBTyxVQUFVLE1BQU0sYUFBYSxDQUFDO0FBQ3JDLE9BQU8sRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFlLE1BQU0sUUFBUSxDQUFDO0FBQ2xELE9BQU8sRUFBRSxDQUFDLElBQUksVUFBVSxFQUFFLE1BQU0sS0FBSyxDQUFDO0FBRXRDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUU5QyxNQUFNLGFBQWEsR0FBRyxTQUFTLENBQUMsUUFBUSxDQUFDLENBQUM7QUFDMUMsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQztBQTZFdEMsU0FBUyxPQUFPLENBQUMsSUFBWSxFQUFFLE9B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QixJQUFJO2dCQUNKLElBQUk7Z0JBQ0osRUFBRSxFQUFFLFdBQVcsQ0FBQyxJQUFJO2FBQ3JCLENBQUMsQ0FBQztZQUNILE9BQU8sV0FBVyxDQUFDO1FBQ3JCLENBQUM7Z0JBQVMsQ0FBQztZQUNULElBQUksTUFBTTtnQkFBRSxNQUFNLEVBQUUsQ0FBQyxNQUFNLEVBQUUsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztZQUM5QyxNQUFNLEVBQUUsQ0FBQyxJQUFJLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ25ELENBQUM7SUFDSCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEluc3RhbGwgYW5kIHJldXNlIGV4ZWN1dGFibGUgYmluYXJpZXMgdW5kZXIgYSBwZXItdG9vbCBob21lIGRpcmVjdG9yeS5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cbmltcG9ydCB7IGV4ZWNGaWxlIH0gZnJvbSBcIm5vZGU6Y2hpbGRfcHJvY2Vzc1wiO1xuaW1wb3J0IHsgY3JlYXRlSGFzaCwgcmFuZG9tVVVJRCB9IGZyb20gXCJub2RlOmNyeXB0b1wiO1xuaW1wb3J0IHtcbiAgY2htb2QsXG4gIGNvcHlGaWxlLFxuICBta2RpcixcbiAgbWtkdGVtcCxcbiAgcmVhZGRpcixcbiAgcmVuYW1lLFxuICBybSxcbiAgc3RhdCxcbiAgd3JpdGVGaWxlLFxufSBmcm9tIFwibm9kZTpmcy9wcm9taXNlc1wiO1xuaW1wb3J0IHsgaG9tZWRpciwgdG1wZGlyIH0gZnJvbSBcIm5vZGU6b3NcIjtcbmltcG9ydCB7IGJhc2VuYW1lLCBqb2luIH0gZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0IHsgZmlsZVVSTFRvUGF0aCB9IGZyb20gXCJub2RlOnVybFwiO1xuaW1wb3J0IHsgcHJvbWlzaWZ5IH0gZnJvbSBcIm5vZGU6dXRpbFwiO1xuXG5pbXBvcnQgKiBhcyBlcnJvclV0aWxzIGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlL2Vycm9yLXV0aWxzXCI7XG5pbXBvcnQgKiBhcyBsb2cgZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmUvbG9nXCI7XG5pbXBvcnQgZXh0cmFjdFppcCBmcm9tIFwiZXh0cmFjdC16aXBcIjtcbmltcG9ydCB7IGNvZXJjZSwgZ3RlLCB0eXBlIFNlbVZlciB9IGZyb20gXCJzZW12ZXJcIjtcbmltcG9ydCB7IHggYXMgZXh0cmFjdFRhciB9IGZyb20gXCJ0YXJcIjtcblxuaW1wb3J0IHsgd2l0aEZpbGVMb2NrIH0gZnJvbSBcIi4vZmlsZS1sb2NrLnRzXCI7XG5cbmNvbnN0IGV4ZWNGaWxlQXN5bmMgPSBwcm9taXNpZnkoZXhlY0ZpbGUpO1xuY29uc3QgbG9nZ2VyID0gbG9nLmxvZ2dlcihcImNvcmU6YmluXCIpO1xuXG5pbnRlcmZhY2UgUGFyc2VkVmVyc2lvbiB7XG4gIHJhdzogc3RyaW5nO1xuICBwYXJ0czogbnVtYmVyW107XG59XG5cbmludGVyZmFjZSBCaW5BY2Nlc3NDb250ZXh0IHtcbiAgZmlsZTogYm9vbGVhbjtcbiAgZXhlY3V0YWJsZTogYm9vbGVhbjtcbn1cblxuLyoqIFN0YWJsZSBwYXRocyBmb3IgYW4gaW5zdGFsbGVkIGJpbmFyeS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQmluQ29udGV4dCB7XG4gIHJvb3Q6IHN0cmluZztcbiAgYmluRGlyOiBzdHJpbmc7XG4gIHBhdGg6IHN0cmluZztcbn1cblxuLyoqIFRlbXBvcmFyeSBkb3dubG9hZCBhbmQgZXh0cmFjdGlvbiBwYXRocyBzdXBwbGllZCB0byBhIGN1c3RvbSBzZWxlY3Rvci4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQmluU2VsZWN0aW9uQ29udGV4dCB7XG4gIGRlc3RpbmF0aW9uOiBCaW5Db250ZXh0O1xuICBkb3dubG9hZFBhdGg6IHN0cmluZztcbiAgc291cmNlOiBzdHJpbmc7XG59XG5cbi8qKlxuICogU2VsZWN0IHRoZSBleGVjdXRhYmxlIGZyb20gYSBkb3dubG9hZCBvciB1bnBhY2tlZCBhcmNoaXZlLiBBIHNlbGVjdG9yIG1heVxuICogYWxzbyBwcmVwYXJlIHRoZSBmaWxlLCBzdWNoIGFzIGFwcGx5aW5nIGl0cyBleGVjdXRhYmxlIG1vZGUuXG4gKi9cbmV4cG9ydCB0eXBlIEJpblNlbGVjdG9yID0gKGNvbnRleHQ6IEJpblNlbGVjdGlvbkNvbnRleHQpID0+IHN0cmluZyB8IFByb21pc2U8c3RyaW5nPjtcblxuLyoqIENhcHR1cmVkIG91dHB1dCBwYXNzZWQgdG8gYSBjdXN0b20gYmluYXJ5IHZlcnNpb24gcGFyc2VyLiAqL1xuZXhwb3J0IGludGVyZmFjZSBCaW5WZXJzaW9uT3V0cHV0IHtcbiAgc3Rkb3V0OiBzdHJpbmc7XG4gIHN0ZGVycjogc3RyaW5nO1xufVxuXG4vKiogRXh0cmFjdCBhIHZlcnNpb24gc3RyaW5nIGZyb20gYSBzdWNjZXNzZnVsIHZlcnNpb24tY29tbWFuZCByZXN1bHQuICovXG5leHBvcnQgdHlwZSBCaW5WZXJzaW9uUGFyc2VyID0gKG91dHB1dDogQmluVmVyc2lvbk91dHB1dCkgPT4gc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4vKiogT3B0aW9ucyBmb3Ige0BsaW5rIGVuc3VyZX0uICovXG5leHBvcnQgaW50ZXJmYWNlIEJpbk9wdGlvbnMge1xuICBhdXRvVW5wYWNrYWdlPzogYm9vbGVhbjtcbiAgc2VsZWN0b3I/OiBCaW5TZWxlY3RvcjtcbiAgaG9tZURpcj86IHN0cmluZztcbiAgLyoqIEV4YWN0IGluc3RhbGxhdGlvbiBwYXRocy4gT21pc3Npb24ga2VlcHMgYCRIT01FLy48bmFtZT4vYmluLzxuYW1lPmAuICovXG4gIGRlc3RpbmF0aW9uPzogQmluQ29udGV4dDtcbiAgLyoqIE1pbmltdW0gYWNjZXB0ZWQgbnVtZXJpYyB2ZXJzaW9uLCB3aXRoIG9uZSB0byB0aHJlZSBjb21wb25lbnRzLiAqL1xuICBtaW5WZXJzaW9uPzogc3RyaW5nO1xuICAvKiogQXJndW1lbnQgcGFzc2VkIHRvIHRoZSBiaW5hcnkgZm9yIHZlcnNpb24gZGV0ZWN0aW9uLiBEZWZhdWx0cyB0byBgLS12ZXJzaW9uYC4gKi9cbiAgdmVyc2lvbkFyZ3VtZW50Pzogc3RyaW5nO1xuICAvKiogVmVyc2lvbiBvdXRwdXQgcGFyc2VyLiBEZWZhdWx0cyB0byB7QGxpbmsgcGFyc2VWZXJzaW9ufS4gKi9cbiAgdmVyc2lvblBhcnNlcj86IEJpblZlcnNpb25QYXJzZXI7XG4gIC8qKiBTa2lwIGAtLXZlcnNpb25gIGFuZCB0cmVhdCBhbiBleGVjdXRhYmxlIGZpbGUgYXMgYWNjZXB0YWJsZS4gKi9cbiAgc2tpcFZlcnNpb25DaGVjaz86IGJvb2xlYW47XG4gIC8qKiBSZWluc3RhbGwgZXZlbiB3aGVuIHRoZSBkZXN0aW5hdGlvbiBhbHJlYWR5IHBhc3NlcyB2YWxpZGF0aW9uLiAqL1xuICBmb3JjZT86IGJvb2xlYW47XG59XG5cbi8qKiBUZW1wb3JhcnkgZGlyZWN0b3J5IGNyZWF0ZWQgZm9yIG9uZSBgZW5zdXJlYCBhdHRlbXB0IGFmdGVyIHRoZSBpbnN0YWxsIGxvY2suICovXG5leHBvcnQgaW50ZXJmYWNlIEJpblVybFJlc29sdmVDb250ZXh0IHtcbiAgcmVhZG9ubHkgdGVtcERpcjogc3RyaW5nO1xufVxuXG4vKiogRG93bmxvYWQgc291cmNlIHJlc29sdmVkIG9ubHkgd2hlbiB0aGUgZXhlY3V0YWJsZSBpcyBub3QgYWxyZWFkeSBpbnN0YWxsZWQuICovXG5leHBvcnQgaW50ZXJmYWNlIEJpblNvdXJjZSB7XG4gIHVybDogc3RyaW5nO1xuICBzaGEyNTY/OiBzdHJpbmc7XG59XG5cbi8qKiBBIGRvd25sb2FkIHNvdXJjZSByZXNvbHZlZCBvbmx5IHdoZW4gdGhlIGV4ZWN1dGFibGUgaXMgbm90IGFscmVhZHkgaW5zdGFsbGVkLiAqL1xuZXhwb3J0IHR5cGUgQmluVXJsID1cbiAgfCBzdHJpbmdcbiAgfCBCaW5Tb3VyY2VcbiAgfCAoKGNvbnRleHQ6IEJpblVybFJlc29sdmVDb250ZXh0KSA9PiBzdHJpbmcgfCBCaW5Tb3VyY2UgfCBQcm9taXNlPHN0cmluZyB8IEJpblNvdXJjZT4pO1xuXG5mdW5jdGlvbiBjb250ZXh0KG5hbWU6IHN0cmluZywgaG9tZURpcjogc3RyaW5nLCBkZXN0aW5hdGlvbj86IEJpbkNvbnRleHQpOiBCaW5Db250ZXh0IHtcbiAgaWYgKCFuYW1lIHx8IGJhc2VuYW1lKG5hbWUpICE9PSBuYW1lIHx8IG5hbWUgPT09IFwiLlwiIHx8IG5hbWUgPT09IFwiLi5cIikge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYGludmFsaWQgYmluYXJ5IG5hbWU6ICR7bmFtZX1gKTtcbiAgfVxuICBpZiAoZGVzdGluYXRpb24pIHJldHVybiBkZXN0aW5hdGlvbjtcbiAgY29uc3Qgcm9vdCA9IGpvaW4oaG9tZURpciwgYC4ke25hbWV9YCk7XG4gIGNvbnN0IGJpbkRpciA9IGpvaW4ocm9vdCwgXCJiaW5cIik7XG4gIHJldHVybiB7IHJvb3QsIGJpbkRpciwgcGF0aDogam9pbihiaW5EaXIsIG5hbWUpIH07XG59XG5cbmZ1bmN0aW9uIGRpc3BsYXlVcmwocmF3OiBzdHJpbmcpOiBzdHJpbmcge1xuICB0cnkge1xuICAgIGNvbnN0IHVybCA9IG5ldyBVUkwocmF3KTtcbiAgICBpZiAodXJsLnByb3RvY29sID09PSBcImRhdGE6XCIpIHJldHVybiBcImRhdGE6XCI7XG4gICAgdXJsLnVzZXJuYW1lID0gXCJcIjtcbiAgICB1cmwucGFzc3dvcmQgPSBcIlwiO1xuICAgIHVybC5zZWFyY2ggPSBcIlwiO1xuICAgIHVybC5oYXNoID0gXCJcIjtcbiAgICByZXR1cm4gdXJsLnRvU3RyaW5nKCk7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiByYXc7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gYWNjZXNzQ29udGV4dChwYXRoOiBzdHJpbmcpOiBQcm9taXNlPEJpbkFjY2Vzc0NvbnRleHQ+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCBlbnRyeSA9IGF3YWl0IHN0YXQocGF0aCk7XG4gICAgY29uc3QgZmlsZSA9IGVudHJ5LmlzRmlsZSgpO1xuICAgIHJldHVybiB7XG4gICAgICBmaWxlLFxuICAgICAgZXhlY3V0YWJsZTogZmlsZSAmJiAocHJvY2Vzcy5wbGF0Zm9ybSA9PT0gXCJ3aW4zMlwiIHx8IChlbnRyeS5tb2RlICYgMG8xMTEpICE9PSAwKSxcbiAgICB9O1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4geyBmaWxlOiBmYWxzZSwgZXhlY3V0YWJsZTogZmFsc2UgfTtcbiAgfVxufVxuXG5mdW5jdGlvbiBkZXRlY3RlZFZlcnNpb25zKG91dHB1dDogc3RyaW5nKTogUGFyc2VkVmVyc2lvbltdIHtcbiAgY29uc3QgdmVyc2lvbnM6IFBhcnNlZFZlcnNpb25bXSA9IFtdO1xuICBjb25zdCBwYXR0ZXJuID0gL1xcYnY/KFxcZCsoPzpcXC5cXGQrKXswLDJ9KSg/OlstKy5fXT9bYS16XVswLTlhLXouK18tXSopPy9naTtcbiAgZm9yIChjb25zdCBtYXRjaCBvZiBvdXRwdXQubWF0Y2hBbGwocGF0dGVybikpIHtcbiAgICBjb25zdCByYXcgPSBtYXRjaFswXS5yZXBsYWNlKC9edi9pLCBcIlwiKTtcbiAgICBjb25zdCBwYXJ0cyA9IG1hdGNoWzFdPy5zcGxpdChcIi5cIikubWFwKE51bWJlcik7XG4gICAgaWYgKHBhcnRzPy5ldmVyeShOdW1iZXIuaXNGaW5pdGUpKSB2ZXJzaW9ucy5wdXNoKHsgcmF3LCBwYXJ0cyB9KTtcbiAgfVxuICByZXR1cm4gdmVyc2lvbnMuc29ydCgoYSwgYikgPT4ge1xuICAgIGlmIChhLnBhcnRzLmxlbmd0aCAhPT0gYi5wYXJ0cy5sZW5ndGgpIHJldHVybiBiLnBhcnRzLmxlbmd0aCAtIGEucGFydHMubGVuZ3RoO1xuICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBhLnBhcnRzLmxlbmd0aDsgaW5kZXggKz0gMSkge1xuICAgICAgY29uc3Qgb3JkZXIgPSAoYi5wYXJ0c1tpbmRleF0gPz8gMCkgLSAoYS5wYXJ0c1tpbmRleF0gPz8gMCk7XG4gICAgICBpZiAob3JkZXIgIT09IDApIHJldHVybiBvcmRlcjtcbiAgICB9XG4gICAgcmV0dXJuIDA7XG4gIH0pO1xufVxuXG4vKipcbiAqIFBhcnNlIHRoZSBkZWVwZXN0LCBoaWdoZXN0IHZlcnNpb24gZnJvbSBzdGRvdXQsIGZhbGxpbmcgYmFjayB0byBzdGRlcnIgb25seVxuICogd2hlbiBzdGRvdXQgY29udGFpbnMgbm8gdmVyc2lvbi4gU3VwcG9ydHMgb25lIHRvIHRocmVlIG51bWVyaWMgY29tcG9uZW50c1xuICogYW5kIGNvbW1vbiBzdWZmaXhlcyBzdWNoIGFzIGByYzFgLCBgLnBvc3QxYCwgYW5kIGAtZGV2LjJgLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VWZXJzaW9uKHsgc3Rkb3V0LCBzdGRlcnIgfTogQmluVmVyc2lvbk91dHB1dCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIHJldHVybiBkZXRlY3RlZFZlcnNpb25zKHN0ZG91dCkuYXQoMCk/LnJhdyA/PyBkZXRlY3RlZFZlcnNpb25zKHN0ZGVycikuYXQoMCk/LnJhdztcbn1cblxuZnVuY3Rpb24gbWluaW11bVNlbVZlcih2ZXJzaW9uOiBzdHJpbmcpOiBTZW1WZXIgfCB1bmRlZmluZWQge1xuICBpZiAoIS9eXFxzKnY/XFxkKyg/OlxcLlxcZCspezAsMn1cXHMqJC9pLnRlc3QodmVyc2lvbikpIHJldHVybiB1bmRlZmluZWQ7XG4gIHJldHVybiBjb2VyY2UodmVyc2lvbiwgeyBsb29zZTogdHJ1ZSB9KSA/PyB1bmRlZmluZWQ7XG59XG5cbi8qKiBDb21wYXJlIGEgZGV0ZWN0ZWQgdG9vbCB2ZXJzaW9uIGFnYWluc3QgYSBvbmUtdG8tdGhyZWUtY29tcG9uZW50IG1pbmltdW0uICovXG5leHBvcnQgZnVuY3Rpb24gaXNWZXJzaW9uQXRMZWFzdCh2ZXJzaW9uOiBzdHJpbmcsIG1pblZlcnNpb246IHN0cmluZyk6IGJvb2xlYW4ge1xuICBjb25zdCBtaW5pbXVtID0gbWluaW11bVNlbVZlcihtaW5WZXJzaW9uKTtcbiAgaWYgKCFtaW5pbXVtKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgaW52YWxpZCBtaW5pbXVtIGJpbmFyeSB2ZXJzaW9uOiAke21pblZlcnNpb259YCk7XG4gIH1cbiAgY29uc3QgYWN0dWFsID0gY29lcmNlKHZlcnNpb24sIHsgbG9vc2U6IHRydWUgfSk7XG4gIGlmICghYWN0dWFsKSByZXR1cm4gZmFsc2U7XG4gIHJldHVybiBndGUoYWN0dWFsLCBtaW5pbXVtKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gaXNWYWxpZEJpbihwYXRoOiBzdHJpbmcsIG9wdGlvbnM6IEJpbk9wdGlvbnMpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgbG9nZ2VyLmRlYnVnKFwiY2hlY2tpbmcgYmluYXJ5XCIsIHtcbiAgICBwYXRoLFxuICAgIG1pblZlcnNpb246IG9wdGlvbnMubWluVmVyc2lvbixcbiAgICB2ZXJzaW9uQXJndW1lbnQ6IG9wdGlvbnMudmVyc2lvbkFyZ3VtZW50ID8/IFwiLS12ZXJzaW9uXCIsXG4gIH0pO1xuICBjb25zdCBhY2Nlc3MgPSBhd2FpdCBhY2Nlc3NDb250ZXh0KHBhdGgpO1xuICBpZiAoIWFjY2Vzcy5maWxlIHx8ICFhY2Nlc3MuZXhlY3V0YWJsZSkge1xuICAgIGxvZ2dlci5kZWJ1ZyhcImJpbmFyeSBhY2Nlc3MgY2hlY2sgZmFpbGVkXCIsIHsgcGF0aCwgLi4uYWNjZXNzIH0pO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBpZiAob3B0aW9ucy5za2lwVmVyc2lvbkNoZWNrKSB7XG4gICAgbG9nZ2VyLmRlYnVnKFwiYmluYXJ5IHZlcnNpb24gY2hlY2sgc2tpcHBlZFwiLCB7IHBhdGggfSk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgbGV0IHN0ZG91dDogc3RyaW5nO1xuICBsZXQgc3RkZXJyOiBzdHJpbmc7XG4gIHRyeSB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZXhlY0ZpbGVBc3luYyhwYXRoLCBbb3B0aW9ucy52ZXJzaW9uQXJndW1lbnQgPz8gXCItLXZlcnNpb25cIl0sIHtcbiAgICAgIGVuY29kaW5nOiBcInV0ZjhcIixcbiAgICB9KTtcbiAgICBzdGRvdXQgPSByZXN1bHQuc3Rkb3V0O1xuICAgIHN0ZGVyciA9IHJlc3VsdC5zdGRlcnI7XG4gIH0gY2F0Y2ggKGNhdXNlKSB7XG4gICAgbG9nZ2VyLmRlYnVnKFwiYmluYXJ5IHZlcnNpb24gY29tbWFuZCBmYWlsZWRcIiwge1xuICAgICAgcGF0aCxcbiAgICAgIGVycm9yOiBlcnJvclV0aWxzLmVycm9yTWVzc2FnZShjYXVzZSksXG4gICAgfSk7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGNvbnN0IHZlcnNpb24gPSAob3B0aW9ucy52ZXJzaW9uUGFyc2VyID8/IHBhcnNlVmVyc2lvbikoe1xuICAgIHN0ZG91dCxcbiAgICBzdGRlcnIsXG4gIH0pO1xuICBjb25zdCB2YWxpZCA9XG4gICAgdmVyc2lvbiAhPT0gdW5kZWZpbmVkICYmXG4gICAgKG9wdGlvbnMubWluVmVyc2lvbiA9PT0gdW5kZWZpbmVkIHx8IGlzVmVyc2lvbkF0TGVhc3QodmVyc2lvbiwgb3B0aW9ucy5taW5WZXJzaW9uKSk7XG4gIGxvZ2dlci5kZWJ1ZyhcImJpbmFyeSB2ZXJzaW9uIGNoZWNrZWRcIiwge1xuICAgIHBhdGgsXG4gICAgdmVyc2lvbixcbiAgICBtaW5WZXJzaW9uOiBvcHRpb25zLm1pblZlcnNpb24sXG4gICAgdmFsaWQsXG4gIH0pO1xuICByZXR1cm4gdmFsaWQ7XG59XG5cbmZ1bmN0aW9uIGRvd25sb2FkTmFtZSh1cmw6IHN0cmluZywgbmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgdHJ5IHtcbiAgICBjb25zdCBjYW5kaWRhdGUgPSBiYXNlbmFtZShkZWNvZGVVUklDb21wb25lbnQobmV3IFVSTCh1cmwpLnBhdGhuYW1lKSk7XG4gICAgcmV0dXJuIGNhbmRpZGF0ZSAmJiBCdWZmZXIuYnl0ZUxlbmd0aChjYW5kaWRhdGUpIDw9IDIwMCA/IGNhbmRpZGF0ZSA6IG5hbWU7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBuYW1lO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHVucGFjayhhcmNoaXZlOiBzdHJpbmcsIGRlc3RpbmF0aW9uOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgZmlsZW5hbWUgPSBhcmNoaXZlLnRvTG93ZXJDYXNlKCk7XG4gIGlmIChmaWxlbmFtZS5lbmRzV2l0aChcIi56aXBcIikpIHtcbiAgICBhd2FpdCBleHRyYWN0WmlwKGFyY2hpdmUsIHsgZGlyOiBkZXN0aW5hdGlvbiB9KTtcbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKGZpbGVuYW1lLmVuZHNXaXRoKFwiLnRhclwiKSB8fCBmaWxlbmFtZS5lbmRzV2l0aChcIi50YXIuZ3pcIikgfHwgZmlsZW5hbWUuZW5kc1dpdGgoXCIudGd6XCIpKSB7XG4gICAgYXdhaXQgZXh0cmFjdFRhcih7IGZpbGU6IGFyY2hpdmUsIGN3ZDogZGVzdGluYXRpb24gfSk7XG4gICAgcmV0dXJuO1xuICB9XG4gIHRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgYmluYXJ5IGFyY2hpdmU6ICR7YmFzZW5hbWUoYXJjaGl2ZSl9YCk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGZpbGVzVW5kZXIocm9vdDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICBjb25zdCBlbnRyaWVzID0gYXdhaXQgcmVhZGRpcihyb290LCB7IHdpdGhGaWxlVHlwZXM6IHRydWUgfSk7XG4gIGNvbnN0IGZpbGVzOiBzdHJpbmdbXSA9IFtdO1xuICBmb3IgKGNvbnN0IGVudHJ5IG9mIGVudHJpZXMpIHtcbiAgICBjb25zdCBwYXRoID0gam9pbihyb290LCBlbnRyeS5uYW1lKTtcbiAgICBpZiAoZW50cnkuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgZmlsZXMucHVzaCguLi4oYXdhaXQgZmlsZXNVbmRlcihwYXRoKSkpO1xuICAgIH0gZWxzZSBpZiAoZW50cnkuaXNGaWxlKCkpIHtcbiAgICAgIGZpbGVzLnB1c2gocGF0aCk7XG4gICAgfVxuICB9XG4gIHJldHVybiBmaWxlcztcbn1cblxuYXN5bmMgZnVuY3Rpb24gc2VsZWN0U2luZ2xlRmlsZShzb3VyY2U6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IGZpbGVzID0gYXdhaXQgZmlsZXNVbmRlcihzb3VyY2UpO1xuICBjb25zdCBzZWxlY3RlZCA9IGZpbGVzLmF0KDApO1xuICBpZiAoZmlsZXMubGVuZ3RoICE9PSAxIHx8ICFzZWxlY3RlZCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgYmluYXJ5IGFyY2hpdmUgbXVzdCBjb250YWluIG9uZSBmaWxlLCBmb3VuZCAke2ZpbGVzLmxlbmd0aH1gKTtcbiAgfVxuICByZXR1cm4gc2VsZWN0ZWQ7XG59XG5cbmZ1bmN0aW9uIGZpbGVVcmxQYXRoKHVybDogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgdHJ5IHtcbiAgICBjb25zdCBwYXJzZWQgPSBuZXcgVVJMKHVybCk7XG4gICAgaWYgKHBhcnNlZC5wcm90b2NvbCAhPT0gXCJmaWxlOlwiKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIHJldHVybiBmaWxlVVJMVG9QYXRoKHBhcnNlZCk7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gc2VsZWN0ZWRCaW4oXG4gIGRlc3RpbmF0aW9uOiBCaW5Db250ZXh0LFxuICBzb3VyY2U6IEJpblNvdXJjZSxcbiAgdGVtcDogc3RyaW5nLFxuICBvcHRpb25zOiBCaW5PcHRpb25zLFxuKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgY29uc3QgeyB1cmwgfSA9IHNvdXJjZTtcbiAgY29uc3QgbG9jYWxQYXRoID0gZmlsZVVybFBhdGgodXJsKTtcbiAgaWYgKGxvY2FsUGF0aCkge1xuICAgIGNvbnN0IGFjY2VzcyA9IGF3YWl0IGFjY2Vzc0NvbnRleHQobG9jYWxQYXRoKTtcbiAgICBpZiAoIWFjY2Vzcy5maWxlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGJpbmFyeSBmaWxlIFVSTCBkb2VzIG5vdCBleGlzdDogJHtkaXNwbGF5VXJsKHVybCl9YCk7XG4gICAgfVxuICAgIGxvZ2dlci5kZWJ1ZyhcInVzaW5nIGxvY2FsIGJpbmFyeVwiLCB7IGZyb206IGRpc3BsYXlVcmwodXJsKSwgcGF0aDogbG9jYWxQYXRoIH0pO1xuICAgIHJldHVybiBsb2NhbFBhdGg7XG4gIH1cbiAgY29uc3QgbmFtZSA9IGRvd25sb2FkTmFtZSh1cmwsIGJhc2VuYW1lKGRlc3RpbmF0aW9uLnBhdGgpKTtcbiAgY29uc3QgZG93bmxvYWRQYXRoID0gam9pbih0ZW1wLCBuYW1lKTtcbiAgbG9nZ2VyLmRlYnVnKFwiZG93bmxvYWRpbmcgYmluYXJ5XCIsIHtcbiAgICBmcm9tOiBkaXNwbGF5VXJsKHVybCksXG4gICAgdG86IGRvd25sb2FkUGF0aCxcbiAgfSk7XG4gIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2godXJsKTtcbiAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgIHRocm93IG5ldyBFcnJvcihgYmluYXJ5IGRvd25sb2FkIGZhaWxlZCAoJHtyZXNwb25zZS5zdGF0dXN9KWApO1xuICB9XG4gIGNvbnN0IGRvd25sb2FkZWQgPSBCdWZmZXIuZnJvbShhd2FpdCByZXNwb25zZS5hcnJheUJ1ZmZlcigpKTtcbiAgaWYgKHNvdXJjZS5zaGEyNTYpIHtcbiAgICBpZiAoIS9eWzAtOWEtZl17NjR9JC9pLnRlc3Qoc291cmNlLnNoYTI1NikpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJiaW5hcnkgZG93bmxvYWQgU0hBLTI1NiBkaWdlc3QgbXVzdCBjb250YWluIDY0IGhleGFkZWNpbWFsIGNoYXJhY3RlcnNcIik7XG4gICAgfVxuICAgIGNvbnN0IGFjdHVhbCA9IGNyZWF0ZUhhc2goXCJzaGEyNTZcIikudXBkYXRlKGRvd25sb2FkZWQpLmRpZ2VzdChcImhleFwiKTtcbiAgICBpZiAoYWN0dWFsLnRvTG93ZXJDYXNlKCkgIT09IHNvdXJjZS5zaGEyNTYudG9Mb3dlckNhc2UoKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBiaW5hcnkgZG93bmxvYWQgZGlnZXN0IG1pc21hdGNoOiAke2Rpc3BsYXlVcmwodXJsKX1gKTtcbiAgICB9XG4gIH1cbiAgYXdhaXQgd3JpdGVGaWxlKGRvd25sb2FkUGF0aCwgZG93bmxvYWRlZCwgeyBtb2RlOiAwbzc1NSB9KTtcblxuICBsZXQgc2VsZWN0ZWRTb3VyY2UgPSBkb3dubG9hZFBhdGg7XG4gIGlmIChvcHRpb25zLmF1dG9VbnBhY2thZ2UpIHtcbiAgICBzZWxlY3RlZFNvdXJjZSA9IGpvaW4odGVtcCwgYHVucGFja2VkLSR7cmFuZG9tVVVJRCgpfWApO1xuICAgIGF3YWl0IG1rZGlyKHNlbGVjdGVkU291cmNlKTtcbiAgICBsb2dnZXIuZGVidWcoXCJ1bnBhY2tpbmcgYmluYXJ5IGFyY2hpdmVcIiwge1xuICAgICAgYXJjaGl2ZTogZG93bmxvYWRQYXRoLFxuICAgICAgdG86IHNlbGVjdGVkU291cmNlLFxuICAgIH0pO1xuICAgIGF3YWl0IHVucGFjayhkb3dubG9hZFBhdGgsIHNlbGVjdGVkU291cmNlKTtcbiAgfVxuXG4gIGlmIChvcHRpb25zLnNlbGVjdG9yKSB7XG4gICAgY29uc3Qgc2VsZWN0ZWQgPSBhd2FpdCBvcHRpb25zLnNlbGVjdG9yKHtcbiAgICAgIGRlc3RpbmF0aW9uLFxuICAgICAgZG93bmxvYWRQYXRoLFxuICAgICAgc291cmNlOiBzZWxlY3RlZFNvdXJjZSxcbiAgICB9KTtcbiAgICBsb2dnZXIuZGVidWcoXCJzZWxlY3RlZCBiaW5hcnlcIiwgeyBwYXRoOiBzZWxlY3RlZCB9KTtcbiAgICByZXR1cm4gc2VsZWN0ZWQ7XG4gIH1cbiAgY29uc3Qgc2VsZWN0ZWQgPSBvcHRpb25zLmF1dG9VbnBhY2thZ2UgPyBhd2FpdCBzZWxlY3RTaW5nbGVGaWxlKHNlbGVjdGVkU291cmNlKSA6IHNlbGVjdGVkU291cmNlO1xuICBsb2dnZXIuZGVidWcoXCJzZWxlY3RlZCBiaW5hcnlcIiwgeyBwYXRoOiBzZWxlY3RlZCB9KTtcbiAgcmV0dXJuIHNlbGVjdGVkO1xufVxuXG4vKipcbiAqIFJldHVybiBhbiBleGlzdGluZyBleGVjdXRhYmxlIG9yIGluc3RhbGwgaXQgYXRvbWljYWxseSB1bmRlclxuICogYCRIT01FLy48bmFtZT4vYmluLzxuYW1lPmAuIEluc3RhbGxhdGlvbiB1c2VzIGEgY2hlY2stbG9jay1jaGVjay1sb2FkXG4gKiBzZXF1ZW5jZSBzbyBjb25jdXJyZW50IGNhbGxlcnMgcmVzb2x2ZSBhbmQgZG93bmxvYWQgdGhlIGJpbmFyeSBvbmx5IG9uY2UuXG4gKiBUaGUgZG93bmxvYWRlZCBjYW5kaWRhdGUgYW5kIGZpbmFsIHJlbmFtZWQgZXhlY3V0YWJsZSBtdXN0IGJvdGggcGFzcyB0aGVcbiAqIHNhbWUgZXhlY3V0YWJsZSBhbmQgdmVyc2lvbiBjaGVja3MuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBlbnN1cmUoXG4gIG5hbWU6IHN0cmluZyxcbiAgdXJsOiBCaW5VcmwsXG4gIG9wdGlvbnM6IEJpbk9wdGlvbnMgPSB7fSxcbik6IFByb21pc2U8QmluQ29udGV4dD4ge1xuICBpZiAob3B0aW9ucy5taW5WZXJzaW9uICYmICFtaW5pbXVtU2VtVmVyKG9wdGlvbnMubWluVmVyc2lvbikpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBpbnZhbGlkIG1pbmltdW0gYmluYXJ5IHZlcnNpb246ICR7b3B0aW9ucy5taW5WZXJzaW9ufWApO1xuICB9XG4gIGNvbnN0IGRlc3RpbmF0aW9uID0gY29udGV4dChuYW1lLCBvcHRpb25zLmhvbWVEaXIgPz8gaG9tZWRpcigpLCBvcHRpb25zLmRlc3RpbmF0aW9uKTtcbiAgaWYgKCFvcHRpb25zLmZvcmNlICYmIChhd2FpdCBpc1ZhbGlkQmluKGRlc3RpbmF0aW9uLnBhdGgsIG9wdGlvbnMpKSkge1xuICAgIGxvZ2dlci5kZWJ1ZyhcInVzaW5nIGluc3RhbGxlZCBiaW5hcnlcIiwgeyBuYW1lLCBwYXRoOiBkZXN0aW5hdGlvbi5wYXRoIH0pO1xuICAgIHJldHVybiBkZXN0aW5hdGlvbjtcbiAgfVxuXG4gIGxvZ2dlci5kZWJ1ZyhcIndhaXRpbmcgZm9yIGJpbmFyeSBpbnN0YWxsIGxvY2tcIiwgeyBuYW1lLCBwYXRoOiBkZXN0aW5hdGlvbi5wYXRoIH0pO1xuICByZXR1cm4gd2l0aEZpbGVMb2NrKFtcImJpbi5lbnN1cmVcIiwgZGVzdGluYXRpb24ucGF0aF0sIGFzeW5jICgpID0+IHtcbiAgICBpZiAoIW9wdGlvbnMuZm9yY2UgJiYgKGF3YWl0IGlzVmFsaWRCaW4oZGVzdGluYXRpb24ucGF0aCwgb3B0aW9ucykpKSB7XG4gICAgICBsb2dnZXIuZGVidWcoXCJ1c2luZyBiaW5hcnkgaW5zdGFsbGVkIGJ5IGFub3RoZXIgY2FsbGVyXCIsIHtcbiAgICAgICAgbmFtZSxcbiAgICAgICAgcGF0aDogZGVzdGluYXRpb24ucGF0aCxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIGRlc3RpbmF0aW9uO1xuICAgIH1cblxuICAgIGxvZ2dlci5kZWJ1ZyhcImluc3RhbGxpbmcgYmluYXJ5XCIsIHtcbiAgICAgIG5hbWUsXG4gICAgICB0bzogZGVzdGluYXRpb24ucGF0aCxcbiAgICAgIG1pblZlcnNpb246IG9wdGlvbnMubWluVmVyc2lvbixcbiAgICB9KTtcbiAgICBjb25zdCB0ZW1wID0gYXdhaXQgbWtkdGVtcChqb2luKHRtcGRpcigpLCBgJHtuYW1lfS1gKSk7XG4gICAgbGV0IHN0YWdlZDogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXNvbHZlZCA9IHR5cGVvZiB1cmwgPT09IFwiZnVuY3Rpb25cIiA/IGF3YWl0IHVybCh7IHRlbXBEaXI6IHRlbXAgfSkgOiB1cmw7XG4gICAgICBjb25zdCBzb3VyY2UgPSB0eXBlb2YgcmVzb2x2ZWQgPT09IFwic3RyaW5nXCIgPyB7IHVybDogcmVzb2x2ZWQgfSA6IHJlc29sdmVkO1xuICAgICAgY29uc3QgZnJvbSA9IGRpc3BsYXlVcmwoc291cmNlLnVybCk7XG4gICAgICBsb2dnZXIuZGVidWcoXCJyZXNvbHZlZCBiaW5hcnkgc291cmNlXCIsIHsgbmFtZSwgZnJvbSB9KTtcbiAgICAgIGNvbnN0IHNlbGVjdGVkID0gYXdhaXQgc2VsZWN0ZWRCaW4oZGVzdGluYXRpb24sIHNvdXJjZSwgdGVtcCwgb3B0aW9ucyk7XG4gICAgICBhd2FpdCBjaG1vZChzZWxlY3RlZCwgMG83NTUpO1xuICAgICAgaWYgKCEoYXdhaXQgaXNWYWxpZEJpbihzZWxlY3RlZCwgb3B0aW9ucykpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgc2VsZWN0ZWQgYmluYXJ5IGhhcyBubyBhY2NlcHRhYmxlIHZlcnNpb246ICR7c2VsZWN0ZWR9YCk7XG4gICAgICB9XG5cbiAgICAgIGF3YWl0IG1rZGlyKGRlc3RpbmF0aW9uLmJpbkRpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgICBzdGFnZWQgPSBqb2luKGRlc3RpbmF0aW9uLmJpbkRpciwgYC4ke25hbWV9LSR7cmFuZG9tVVVJRCgpfWApO1xuICAgICAgYXdhaXQgY29weUZpbGUoc2VsZWN0ZWQsIHN0YWdlZCk7XG4gICAgICBhd2FpdCBjaG1vZChzdGFnZWQsIDBvNzU1KTtcbiAgICAgIGF3YWl0IHJlbmFtZShzdGFnZWQsIGRlc3RpbmF0aW9uLnBhdGgpO1xuICAgICAgc3RhZ2VkID0gdW5kZWZpbmVkO1xuICAgICAgaWYgKCEoYXdhaXQgaXNWYWxpZEJpbihkZXN0aW5hdGlvbi5wYXRoLCBvcHRpb25zKSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBpbnN0YWxsZWQgYmluYXJ5IGlzIGludmFsaWQgYWZ0ZXIgcmVuYW1lOiAke2Rlc3RpbmF0aW9uLnBhdGh9YCk7XG4gICAgICB9XG4gICAgICBsb2dnZXIuaW5mbyhcImluc3RhbGxlZCBiaW5hcnlcIiwge1xuICAgICAgICBuYW1lLFxuICAgICAgICBmcm9tLFxuICAgICAgICB0bzogZGVzdGluYXRpb24ucGF0aCxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIGRlc3RpbmF0aW9uO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBpZiAoc3RhZ2VkKSBhd2FpdCBybShzdGFnZWQsIHsgZm9yY2U6IHRydWUgfSk7XG4gICAgICBhd2FpdCBybSh0ZW1wLCB7IHJlY3Vyc2l2ZTogdHJ1ZSwgZm9yY2U6IHRydWUgfSk7XG4gICAgfVxuICB9KTtcbn1cbiJdfQ==
431
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmluLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2Jpbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHO0FBQ0gsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3JELE9BQU8sRUFDTCxLQUFLLEVBQ0wsRUFBRSxFQUNGLFFBQVEsRUFDUixLQUFLLEVBQ0wsT0FBTyxFQUNQLE9BQU8sRUFDUCxNQUFNLEVBQ04sRUFBRSxFQUNGLElBQUksRUFDSixTQUFTLEdBQ1YsTUFBTSxrQkFBa0IsQ0FBQztBQUMxQixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUMxQyxPQUFPLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDOUUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUN6QyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBRXRDLE9BQU8sS0FBSyxVQUFVLE1BQU0sb0NBQW9DLENBQUM7QUFDakUsT0FBTyxLQUFLLEdBQUcsTUFBTSw0QkFBNEIsQ0FBQztBQUNsRCxPQUFPLFVBQVUsTUFBTSxhQUFhLENBQUM7QUFDckMsT0FBTyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQWUsTUFBTSxRQUFRLENBQUM7QUFDbEQsT0FBTyxFQUFFLENBQUMsSUFBSSxVQUFVLEVBQUUsTUFBTSxLQUFLLENBQUM7QUFFdEMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRTlDLE1BQU0sYUFBYSxHQUFHLFNBQVMsQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUMxQyxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFD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QUFXLENBQUMsSUFBSTthQUNyQixDQUFDLENBQUM7WUFDSCxPQUFPLFdBQVcsQ0FBQztRQUNyQixDQUFDO2dCQUFTLENBQUM7WUFDVCxJQUFJLE1BQU07Z0JBQUUsTUFBTSxFQUFFLENBQUMsTUFBTSxFQUFFLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7WUFDOUMsTUFBTSxFQUFFLENBQUMsSUFBSSxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUNuRCxDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBJbnN0YWxsIGFuZCByZXVzZSBleGVjdXRhYmxlIGJpbmFyaWVzIHVuZGVyIGEgcGVyLXRvb2wgaG9tZSBkaXJlY3RvcnkuXG4gKlxuICogQG1vZHVsZVxuICovXG5pbXBvcnQgeyBleGVjRmlsZSB9IGZyb20gXCJub2RlOmNoaWxkX3Byb2Nlc3NcIjtcbmltcG9ydCB7IGNyZWF0ZUhhc2gsIHJhbmRvbVVVSUQgfSBmcm9tIFwibm9kZTpjcnlwdG9cIjtcbmltcG9ydCB7XG4gIGNobW9kLFxuICBjcCxcbiAgY29weUZpbGUsXG4gIG1rZGlyLFxuICBta2R0ZW1wLFxuICByZWFkZGlyLFxuICByZW5hbWUsXG4gIHJtLFxuICBzdGF0LFxuICB3cml0ZUZpbGUsXG59IGZyb20gXCJub2RlOmZzL3Byb21pc2VzXCI7XG5pbXBvcnQgeyBob21lZGlyLCB0bXBkaXIgfSBmcm9tIFwibm9kZTpvc1wiO1xuaW1wb3J0IHsgYmFzZW5hbWUsIGRpcm5hbWUsIGlzQWJzb2x1dGUsIGpvaW4sIHJlc29sdmUsIHNlcCB9IGZyb20gXCJub2RlOnBhdGhcIjtcbmltcG9ydCB7IGZpbGVVUkxUb1BhdGggfSBmcm9tIFwibm9kZTp1cmxcIjtcbmltcG9ydCB7IHByb21pc2lmeSB9IGZyb20gXCJub2RlOnV0aWxcIjtcblxuaW1wb3J0ICogYXMgZXJyb3JVdGlscyBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZS9lcnJvci11dGlsc1wiO1xuaW1wb3J0ICogYXMgbG9nIGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlL2xvZ1wiO1xuaW1wb3J0IGV4dHJhY3RaaXAgZnJvbSBcImV4dHJhY3QtemlwXCI7XG5pbXBvcnQgeyBjb2VyY2UsIGd0ZSwgdHlwZSBTZW1WZXIgfSBmcm9tIFwic2VtdmVyXCI7XG5pbXBvcnQgeyB4IGFzIGV4dHJhY3RUYXIgfSBmcm9tIFwidGFyXCI7XG5cbmltcG9ydCB7IHdpdGhGaWxlTG9jayB9IGZyb20gXCIuL2ZpbGUtbG9jay50c1wiO1xuXG5jb25zdCBleGVjRmlsZUFzeW5jID0gcHJvbWlzaWZ5KGV4ZWNGaWxlKTtcbmNvbnN0IGxvZ2dlciA9IGxvZy5sb2dnZXIoXCJjb3JlOmJpblwiKTtcblxuaW50ZXJmYWNlIFBhcnNlZFZlcnNpb24ge1xuICByYXc6IHN0cmluZztcbiAgcGFydHM6IG51bWJlcltdO1xufVxuXG5pbnRlcmZhY2UgQmluQWNjZXNzQ29udGV4dCB7XG4gIGZpbGU6IGJvb2xlYW47XG4gIGV4ZWN1dGFibGU6IGJvb2xlYW47XG59XG5cbi8qKiBTdGFibGUgcGF0aHMgZm9yIGFuIGluc3RhbGxlZCBiaW5hcnkuICovXG5leHBvcnQgaW50ZXJmYWNlIEJpbkNvbnRleHQge1xuICByb290OiBzdHJpbmc7XG4gIGJpbkRpcjogc3RyaW5nO1xuICBwYXRoOiBzdHJpbmc7XG59XG5cbi8qKiBUZW1wb3JhcnkgZG93bmxvYWQgYW5kIGV4dHJhY3Rpb24gcGF0aHMgc3VwcGxpZWQgdG8gYSBjdXN0b20gc2VsZWN0b3IuICovXG5leHBvcnQgaW50ZXJmYWNlIEJpblNlbGVjdGlvbkNvbnRleHQge1xuICBkZXN0aW5hdGlvbjogQmluQ29udGV4dDtcbiAgZG93bmxvYWRQYXRoOiBzdHJpbmc7XG4gIHNvdXJjZTogc3RyaW5nO1xufVxuXG4vKipcbiAqIFNlbGVjdCB0aGUgZXhlY3V0YWJsZSBmcm9tIGEgZG93bmxvYWQgb3IgdW5wYWNrZWQgYXJjaGl2ZS4gQSBzZWxlY3RvciBtYXlcbiAqIGFsc28gcHJlcGFyZSB0aGUgZmlsZSwgc3VjaCBhcyBhcHBseWluZyBpdHMgZXhlY3V0YWJsZSBtb2RlLlxuICovXG5leHBvcnQgdHlwZSBCaW5TZWxlY3RvciA9IChjb250ZXh0OiBCaW5TZWxlY3Rpb25Db250ZXh0KSA9PiBzdHJpbmcgfCBQcm9taXNlPHN0cmluZz47XG5cbi8qKiBDYXB0dXJlZCBvdXRwdXQgcGFzc2VkIHRvIGEgY3VzdG9tIGJpbmFyeSB2ZXJzaW9uIHBhcnNlci4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQmluVmVyc2lvbk91dHB1dCB7XG4gIHN0ZG91dDogc3RyaW5nO1xuICBzdGRlcnI6IHN0cmluZztcbn1cblxuLyoqIEV4dHJhY3QgYSB2ZXJzaW9uIHN0cmluZyBmcm9tIGEgc3VjY2Vzc2Z1bCB2ZXJzaW9uLWNvbW1hbmQgcmVzdWx0LiAqL1xuZXhwb3J0IHR5cGUgQmluVmVyc2lvblBhcnNlciA9IChvdXRwdXQ6IEJpblZlcnNpb25PdXRwdXQpID0+IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuLyoqIE9wdGlvbnMgZm9yIHtAbGluayBlbnN1cmV9LiAqL1xuZXhwb3J0IGludGVyZmFjZSBCaW5PcHRpb25zIHtcbiAgYXV0b1VucGFja2FnZT86IGJvb2xlYW47XG4gIC8qKiBQcmVzZXJ2ZSBhbiB1bnBhY2tlZCBtdWx0aS1maWxlIHBhY2thZ2Ugcm9vdGVkIGF0IHtAbGluayBCaW5Db250ZXh0LnJvb3R9LiAqL1xuICBwYWNrYWdlPzogQmluUGFja2FnZU9wdGlvbnM7XG4gIHNlbGVjdG9yPzogQmluU2VsZWN0b3I7XG4gIGhvbWVEaXI/OiBzdHJpbmc7XG4gIC8qKiBFeGFjdCBpbnN0YWxsYXRpb24gcGF0aHMuIE9taXNzaW9uIGtlZXBzIGAkSE9NRS8uPG5hbWU+L2Jpbi88bmFtZT5gLiAqL1xuICBkZXN0aW5hdGlvbj86IEJpbkNvbnRleHQ7XG4gIC8qKiBNaW5pbXVtIGFjY2VwdGVkIG51bWVyaWMgdmVyc2lvbiwgd2l0aCBvbmUgdG8gdGhyZWUgY29tcG9uZW50cy4gKi9cbiAgbWluVmVyc2lvbj86IHN0cmluZztcbiAgLyoqIEFyZ3VtZW50IHBhc3NlZCB0byB0aGUgYmluYXJ5IGZvciB2ZXJzaW9uIGRldGVjdGlvbi4gRGVmYXVsdHMgdG8gYC0tdmVyc2lvbmAuICovXG4gIHZlcnNpb25Bcmd1bWVudD86IHN0cmluZztcbiAgLyoqIFZlcnNpb24gb3V0cHV0IHBhcnNlci4gRGVmYXVsdHMgdG8ge0BsaW5rIHBhcnNlVmVyc2lvbn0uICovXG4gIHZlcnNpb25QYXJzZXI/OiBCaW5WZXJzaW9uUGFyc2VyO1xuICAvKiogU2tpcCBgLS12ZXJzaW9uYCBhbmQgdHJlYXQgYW4gZXhlY3V0YWJsZSBmaWxlIGFzIGFjY2VwdGFibGUuICovXG4gIHNraXBWZXJzaW9uQ2hlY2s/OiBib29sZWFuO1xuICAvKiogUmVpbnN0YWxsIGV2ZW4gd2hlbiB0aGUgZGVzdGluYXRpb24gYWxyZWFkeSBwYXNzZXMgdmFsaWRhdGlvbi4gKi9cbiAgZm9yY2U/OiBib29sZWFuO1xufVxuXG4vKiogTXVsdGktZmlsZSBhcmNoaXZlIGxheW91dCByZXRhaW5lZCBiZXNpZGUgaXRzIGV4ZWN1dGFibGUgZW50cnlwb2ludC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQmluUGFja2FnZU9wdGlvbnMge1xuICAvKiogRXhlY3V0YWJsZSBwYXRoIHJlbGF0aXZlIHRvIHRoZSB1bnBhY2tlZCBwYWNrYWdlIHJvb3QuICovXG4gIGVudHJ5cG9pbnQ6IHN0cmluZztcbiAgLyoqIENvbXBhbmlvbiBmaWxlcyBvciBkaXJlY3RvcmllcyByZXF1aXJlZCBiZWZvcmUgYW4gaW5zdGFsbGF0aW9uIGNhbiBiZSByZXVzZWQuICovXG4gIHJlcXVpcmVkUGF0aHM/OiByZWFkb25seSBzdHJpbmdbXTtcbn1cblxuLyoqIFRlbXBvcmFyeSBkaXJlY3RvcnkgY3JlYXRlZCBmb3Igb25lIGBlbnN1cmVgIGF0dGVtcHQgYWZ0ZXIgdGhlIGluc3RhbGwgbG9jay4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQmluVXJsUmVzb2x2ZUNvbnRleHQge1xuICByZWFkb25seSB0ZW1wRGlyOiBzdHJpbmc7XG59XG5cbi8qKiBEb3dubG9hZCBzb3VyY2UgcmVzb2x2ZWQgb25seSB3aGVuIHRoZSBleGVjdXRhYmxlIGlzIG5vdCBhbHJlYWR5IGluc3RhbGxlZC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQmluU291cmNlIHtcbiAgdXJsOiBzdHJpbmc7XG4gIHNoYTI1Nj86IHN0cmluZztcbn1cblxuLyoqIEEgZG93bmxvYWQgc291cmNlIHJlc29sdmVkIG9ubHkgd2hlbiB0aGUgZXhlY3V0YWJsZSBpcyBub3QgYWxyZWFkeSBpbnN0YWxsZWQuICovXG5leHBvcnQgdHlwZSBCaW5VcmwgPVxuICB8IHN0cmluZ1xuICB8IEJpblNvdXJjZVxuICB8ICgoY29udGV4dDogQmluVXJsUmVzb2x2ZUNvbnRleHQpID0+IHN0cmluZyB8IEJpblNvdXJjZSB8IFByb21pc2U8c3RyaW5nIHwgQmluU291cmNlPik7XG5cbmZ1bmN0aW9uIGNvbnRleHQobmFtZTogc3RyaW5nLCBob21lRGlyOiBzdHJpbmcsIGRlc3RpbmF0aW9uPzogQmluQ29udGV4dCk6IEJpbkNvbnRleHQge1xuICBpZiAoIW5hbWUgfHwgYmFzZW5hbWUobmFtZSkgIT09IG5hbWUgfHwgbmFtZSA9PT0gXCIuXCIgfHwgbmFtZSA9PT0gXCIuLlwiKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgaW52YWxpZCBiaW5hcnkgbmFtZTogJHtuYW1lfWApO1xuICB9XG4gIGlmIChkZXN0aW5hdGlvbikgcmV0dXJuIGRlc3RpbmF0aW9uO1xuICBjb25zdCByb290ID0gam9pbihob21lRGlyLCBgLiR7bmFtZX1gKTtcbiAgY29uc3QgYmluRGlyID0gam9pbihyb290LCBcImJpblwiKTtcbiAgcmV0dXJuIHsgcm9vdCwgYmluRGlyLCBwYXRoOiBqb2luKGJpbkRpciwgbmFtZSkgfTtcbn1cblxuZnVuY3Rpb24gcGFja2FnZVBhdGgocm9vdDogc3RyaW5nLCBwYXRoOiBzdHJpbmcpOiBzdHJpbmcge1xuICBpZiAoIXBhdGggfHwgaXNBYnNvbHV0ZShwYXRoKSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYGludmFsaWQgYmluYXJ5IHBhY2thZ2UgcGF0aDogJHtwYXRofWApO1xuICB9XG4gIGNvbnN0IHBhY2thZ2VSb290ID0gcmVzb2x2ZShyb290KTtcbiAgY29uc3QgcmVzb2x2ZWQgPSByZXNvbHZlKHBhY2thZ2VSb290LCBwYXRoKTtcbiAgaWYgKHJlc29sdmVkID09PSBwYWNrYWdlUm9vdCB8fCAhcmVzb2x2ZWQuc3RhcnRzV2l0aChgJHtwYWNrYWdlUm9vdH0ke3NlcH1gKSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYGJpbmFyeSBwYWNrYWdlIHBhdGggZXNjYXBlcyBpdHMgcm9vdDogJHtwYXRofWApO1xuICB9XG4gIHJldHVybiByZXNvbHZlZDtcbn1cblxuZnVuY3Rpb24gcGFja2FnZURlc3RpbmF0aW9uKGRlc3RpbmF0aW9uOiBCaW5Db250ZXh0LCBvcHRpb25zOiBCaW5PcHRpb25zKTogdm9pZCB7XG4gIGlmICghb3B0aW9ucy5wYWNrYWdlKSByZXR1cm47XG4gIGNvbnN0IGVudHJ5cG9pbnQgPSBwYWNrYWdlUGF0aChkZXN0aW5hdGlvbi5yb290LCBvcHRpb25zLnBhY2thZ2UuZW50cnlwb2ludCk7XG4gIGlmIChyZXNvbHZlKGRlc3RpbmF0aW9uLnBhdGgpICE9PSBlbnRyeXBvaW50KSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcImJpbmFyeSBwYWNrYWdlIGRlc3RpbmF0aW9uIHBhdGggbXVzdCBtYXRjaCBpdHMgZW50cnlwb2ludFwiKTtcbiAgfVxuICBmb3IgKGNvbnN0IHBhdGggb2Ygb3B0aW9ucy5wYWNrYWdlLnJlcXVpcmVkUGF0aHMgPz8gW10pIHtcbiAgICBwYWNrYWdlUGF0aChkZXN0aW5hdGlvbi5yb290LCBwYXRoKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBkaXNwbGF5VXJsKHJhdzogc3RyaW5nKTogc3RyaW5nIHtcbiAgdHJ5IHtcbiAgICBjb25zdCB1cmwgPSBuZXcgVVJMKHJhdyk7XG4gICAgaWYgKHVybC5wcm90b2NvbCA9PT0gXCJkYXRhOlwiKSByZXR1cm4gXCJkYXRhOlwiO1xuICAgIHVybC51c2VybmFtZSA9IFwiXCI7XG4gICAgdXJsLnBhc3N3b3JkID0gXCJcIjtcbiAgICB1cmwuc2VhcmNoID0gXCJcIjtcbiAgICB1cmwuaGFzaCA9IFwiXCI7XG4gICAgcmV0dXJuIHVybC50b1N0cmluZygpO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gcmF3O1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGFjY2Vzc0NvbnRleHQocGF0aDogc3RyaW5nKTogUHJvbWlzZTxCaW5BY2Nlc3NDb250ZXh0PiB7XG4gIHRyeSB7XG4gICAgY29uc3QgZW50cnkgPSBhd2FpdCBzdGF0KHBhdGgpO1xuICAgIGNvbnN0IGZpbGUgPSBlbnRyeS5pc0ZpbGUoKTtcbiAgICByZXR1cm4ge1xuICAgICAgZmlsZSxcbiAgICAgIGV4ZWN1dGFibGU6IGZpbGUgJiYgKHByb2Nlc3MucGxhdGZvcm0gPT09IFwid2luMzJcIiB8fCAoZW50cnkubW9kZSAmIDBvMTExKSAhPT0gMCksXG4gICAgfTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIHsgZmlsZTogZmFsc2UsIGV4ZWN1dGFibGU6IGZhbHNlIH07XG4gIH1cbn1cblxuZnVuY3Rpb24gZGV0ZWN0ZWRWZXJzaW9ucyhvdXRwdXQ6IHN0cmluZyk6IFBhcnNlZFZlcnNpb25bXSB7XG4gIGNvbnN0IHZlcnNpb25zOiBQYXJzZWRWZXJzaW9uW10gPSBbXTtcbiAgY29uc3QgcGF0dGVybiA9IC9cXGJ2PyhcXGQrKD86XFwuXFxkKyl7MCwyfSkoPzpbLSsuX10/W2Etel1bMC05YS16LitfLV0qKT8vZ2k7XG4gIGZvciAoY29uc3QgbWF0Y2ggb2Ygb3V0cHV0Lm1hdGNoQWxsKHBhdHRlcm4pKSB7XG4gICAgY29uc3QgcmF3ID0gbWF0Y2hbMF0ucmVwbGFjZSgvXnYvaSwgXCJcIik7XG4gICAgY29uc3QgcGFydHMgPSBtYXRjaFsxXT8uc3BsaXQoXCIuXCIpLm1hcChOdW1iZXIpO1xuICAgIGlmIChwYXJ0cz8uZXZlcnkoTnVtYmVyLmlzRmluaXRlKSkgdmVyc2lvbnMucHVzaCh7IHJhdywgcGFydHMgfSk7XG4gIH1cbiAgcmV0dXJuIHZlcnNpb25zLnNvcnQoKGEsIGIpID0+IHtcbiAgICBpZiAoYS5wYXJ0cy5sZW5ndGggIT09IGIucGFydHMubGVuZ3RoKSByZXR1cm4gYi5wYXJ0cy5sZW5ndGggLSBhLnBhcnRzLmxlbmd0aDtcbiAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgYS5wYXJ0cy5sZW5ndGg7IGluZGV4ICs9IDEpIHtcbiAgICAgIGNvbnN0IG9yZGVyID0gKGIucGFydHNbaW5kZXhdID8/IDApIC0gKGEucGFydHNbaW5kZXhdID8/IDApO1xuICAgICAgaWYgKG9yZGVyICE9PSAwKSByZXR1cm4gb3JkZXI7XG4gICAgfVxuICAgIHJldHVybiAwO1xuICB9KTtcbn1cblxuLyoqXG4gKiBQYXJzZSB0aGUgZGVlcGVzdCwgaGlnaGVzdCB2ZXJzaW9uIGZyb20gc3Rkb3V0LCBmYWxsaW5nIGJhY2sgdG8gc3RkZXJyIG9ubHlcbiAqIHdoZW4gc3Rkb3V0IGNvbnRhaW5zIG5vIHZlcnNpb24uIFN1cHBvcnRzIG9uZSB0byB0aHJlZSBudW1lcmljIGNvbXBvbmVudHNcbiAqIGFuZCBjb21tb24gc3VmZml4ZXMgc3VjaCBhcyBgcmMxYCwgYC5wb3N0MWAsIGFuZCBgLWRldi4yYC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlVmVyc2lvbih7IHN0ZG91dCwgc3RkZXJyIH06IEJpblZlcnNpb25PdXRwdXQpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICByZXR1cm4gZGV0ZWN0ZWRWZXJzaW9ucyhzdGRvdXQpLmF0KDApPy5yYXcgPz8gZGV0ZWN0ZWRWZXJzaW9ucyhzdGRlcnIpLmF0KDApPy5yYXc7XG59XG5cbmZ1bmN0aW9uIG1pbmltdW1TZW1WZXIodmVyc2lvbjogc3RyaW5nKTogU2VtVmVyIHwgdW5kZWZpbmVkIHtcbiAgaWYgKCEvXlxccyp2P1xcZCsoPzpcXC5cXGQrKXswLDJ9XFxzKiQvaS50ZXN0KHZlcnNpb24pKSByZXR1cm4gdW5kZWZpbmVkO1xuICByZXR1cm4gY29lcmNlKHZlcnNpb24sIHsgbG9vc2U6IHRydWUgfSkgPz8gdW5kZWZpbmVkO1xufVxuXG4vKiogQ29tcGFyZSBhIGRldGVjdGVkIHRvb2wgdmVyc2lvbiBhZ2FpbnN0IGEgb25lLXRvLXRocmVlLWNvbXBvbmVudCBtaW5pbXVtLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVmVyc2lvbkF0TGVhc3QodmVyc2lvbjogc3RyaW5nLCBtaW5WZXJzaW9uOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgY29uc3QgbWluaW11bSA9IG1pbmltdW1TZW1WZXIobWluVmVyc2lvbik7XG4gIGlmICghbWluaW11bSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYGludmFsaWQgbWluaW11bSBiaW5hcnkgdmVyc2lvbjogJHttaW5WZXJzaW9ufWApO1xuICB9XG4gIGNvbnN0IGFjdHVhbCA9IGNvZXJjZSh2ZXJzaW9uLCB7IGxvb3NlOiB0cnVlIH0pO1xuICBpZiAoIWFjdHVhbCkgcmV0dXJuIGZhbHNlO1xuICByZXR1cm4gZ3RlKGFjdHVhbCwgbWluaW11bSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGlzVmFsaWRCaW4ocGF0aDogc3RyaW5nLCBvcHRpb25zOiBCaW5PcHRpb25zKTogUHJvbWlzZTxib29sZWFuPiB7XG4gIGxvZ2dlci5kZWJ1ZyhcImNoZWNraW5nIGJpbmFyeVwiLCB7XG4gICAgcGF0aCxcbiAgICBtaW5WZXJzaW9uOiBvcHRpb25zLm1pblZlcnNpb24sXG4gICAgdmVyc2lvbkFyZ3VtZW50OiBvcHRpb25zLnZlcnNpb25Bcmd1bWVudCA/PyBcIi0tdmVyc2lvblwiLFxuICB9KTtcbiAgY29uc3QgYWNjZXNzID0gYXdhaXQgYWNjZXNzQ29udGV4dChwYXRoKTtcbiAgaWYgKCFhY2Nlc3MuZmlsZSB8fCAhYWNjZXNzLmV4ZWN1dGFibGUpIHtcbiAgICBsb2dnZXIuZGVidWcoXCJiaW5hcnkgYWNjZXNzIGNoZWNrIGZhaWxlZFwiLCB7IHBhdGgsIC4uLmFjY2VzcyB9KTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgaWYgKG9wdGlvbnMuc2tpcFZlcnNpb25DaGVjaykge1xuICAgIGxvZ2dlci5kZWJ1ZyhcImJpbmFyeSB2ZXJzaW9uIGNoZWNrIHNraXBwZWRcIiwgeyBwYXRoIH0pO1xuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIGxldCBzdGRvdXQ6IHN0cmluZztcbiAgbGV0IHN0ZGVycjogc3RyaW5nO1xuICB0cnkge1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGV4ZWNGaWxlQXN5bmMocGF0aCwgW29wdGlvbnMudmVyc2lvbkFyZ3VtZW50ID8/IFwiLS12ZXJzaW9uXCJdLCB7XG4gICAgICBlbmNvZGluZzogXCJ1dGY4XCIsXG4gICAgfSk7XG4gICAgc3Rkb3V0ID0gcmVzdWx0LnN0ZG91dDtcbiAgICBzdGRlcnIgPSByZXN1bHQuc3RkZXJyO1xuICB9IGNhdGNoIChjYXVzZSkge1xuICAgIGxvZ2dlci5kZWJ1ZyhcImJpbmFyeSB2ZXJzaW9uIGNvbW1hbmQgZmFpbGVkXCIsIHtcbiAgICAgIHBhdGgsXG4gICAgICBlcnJvcjogZXJyb3JVdGlscy5lcnJvck1lc3NhZ2UoY2F1c2UpLFxuICAgIH0pO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBjb25zdCB2ZXJzaW9uID0gKG9wdGlvbnMudmVyc2lvblBhcnNlciA/PyBwYXJzZVZlcnNpb24pKHtcbiAgICBzdGRvdXQsXG4gICAgc3RkZXJyLFxuICB9KTtcbiAgY29uc3QgdmFsaWQgPVxuICAgIHZlcnNpb24gIT09IHVuZGVmaW5lZCAmJlxuICAgIChvcHRpb25zLm1pblZlcnNpb24gPT09IHVuZGVmaW5lZCB8fCBpc1ZlcnNpb25BdExlYXN0KHZlcnNpb24sIG9wdGlvbnMubWluVmVyc2lvbikpO1xuICBsb2dnZXIuZGVidWcoXCJiaW5hcnkgdmVyc2lvbiBjaGVja2VkXCIsIHtcbiAgICBwYXRoLFxuICAgIHZlcnNpb24sXG4gICAgbWluVmVyc2lvbjogb3B0aW9ucy5taW5WZXJzaW9uLFxuICAgIHZhbGlkLFxuICB9KTtcbiAgcmV0dXJuIHZhbGlkO1xufVxuXG5hc3luYyBmdW5jdGlvbiBwYXRoRXhpc3RzKHBhdGg6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICB0cnkge1xuICAgIGF3YWl0IHN0YXQocGF0aCk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBpc1ZhbGlkSW5zdGFsbChkZXN0aW5hdGlvbjogQmluQ29udGV4dCwgb3B0aW9uczogQmluT3B0aW9ucyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICBpZiAoIShhd2FpdCBpc1ZhbGlkQmluKGRlc3RpbmF0aW9uLnBhdGgsIG9wdGlvbnMpKSkgcmV0dXJuIGZhbHNlO1xuICBpZiAoIW9wdGlvbnMucGFja2FnZSkgcmV0dXJuIHRydWU7XG4gIGNvbnN0IHJlcXVpcmVkID0gW29wdGlvbnMucGFja2FnZS5lbnRyeXBvaW50LCAuLi4ob3B0aW9ucy5wYWNrYWdlLnJlcXVpcmVkUGF0aHMgPz8gW10pXTtcbiAgY29uc3QgYXZhaWxhYmxlID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgcmVxdWlyZWQubWFwKChwYXRoKSA9PiBwYXRoRXhpc3RzKHBhY2thZ2VQYXRoKGRlc3RpbmF0aW9uLnJvb3QsIHBhdGgpKSksXG4gICk7XG4gIHJldHVybiBhdmFpbGFibGUuZXZlcnkoQm9vbGVhbik7XG59XG5cbmZ1bmN0aW9uIGRvd25sb2FkTmFtZSh1cmw6IHN0cmluZywgbmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgdHJ5IHtcbiAgICBjb25zdCBjYW5kaWRhdGUgPSBiYXNlbmFtZShkZWNvZGVVUklDb21wb25lbnQobmV3IFVSTCh1cmwpLnBhdGhuYW1lKSk7XG4gICAgcmV0dXJuIGNhbmRpZGF0ZSAmJiBCdWZmZXIuYnl0ZUxlbmd0aChjYW5kaWRhdGUpIDw9IDIwMCA/IGNhbmRpZGF0ZSA6IG5hbWU7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBuYW1lO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHVucGFjayhhcmNoaXZlOiBzdHJpbmcsIGRlc3RpbmF0aW9uOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgZmlsZW5hbWUgPSBhcmNoaXZlLnRvTG93ZXJDYXNlKCk7XG4gIGlmIChmaWxlbmFtZS5lbmRzV2l0aChcIi56aXBcIikpIHtcbiAgICBhd2FpdCBleHRyYWN0WmlwKGFyY2hpdmUsIHsgZGlyOiBkZXN0aW5hdGlvbiB9KTtcbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKGZpbGVuYW1lLmVuZHNXaXRoKFwiLnRhclwiKSB8fCBmaWxlbmFtZS5lbmRzV2l0aChcIi50YXIuZ3pcIikgfHwgZmlsZW5hbWUuZW5kc1dpdGgoXCIudGd6XCIpKSB7XG4gICAgYXdhaXQgZXh0cmFjdFRhcih7IGZpbGU6IGFyY2hpdmUsIGN3ZDogZGVzdGluYXRpb24gfSk7XG4gICAgcmV0dXJuO1xuICB9XG4gIHRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgYmluYXJ5IGFyY2hpdmU6ICR7YmFzZW5hbWUoYXJjaGl2ZSl9YCk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGZpbGVzVW5kZXIocm9vdDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICBjb25zdCBlbnRyaWVzID0gYXdhaXQgcmVhZGRpcihyb290LCB7IHdpdGhGaWxlVHlwZXM6IHRydWUgfSk7XG4gIGNvbnN0IGZpbGVzOiBzdHJpbmdbXSA9IFtdO1xuICBmb3IgKGNvbnN0IGVudHJ5IG9mIGVudHJpZXMpIHtcbiAgICBjb25zdCBwYXRoID0gam9pbihyb290LCBlbnRyeS5uYW1lKTtcbiAgICBpZiAoZW50cnkuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgZmlsZXMucHVzaCguLi4oYXdhaXQgZmlsZXNVbmRlcihwYXRoKSkpO1xuICAgIH0gZWxzZSBpZiAoZW50cnkuaXNGaWxlKCkpIHtcbiAgICAgIGZpbGVzLnB1c2gocGF0aCk7XG4gICAgfVxuICB9XG4gIHJldHVybiBmaWxlcztcbn1cblxuYXN5bmMgZnVuY3Rpb24gc2VsZWN0U2luZ2xlRmlsZShzb3VyY2U6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IGZpbGVzID0gYXdhaXQgZmlsZXNVbmRlcihzb3VyY2UpO1xuICBjb25zdCBzZWxlY3RlZCA9IGZpbGVzLmF0KDApO1xuICBpZiAoZmlsZXMubGVuZ3RoICE9PSAxIHx8ICFzZWxlY3RlZCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgYmluYXJ5IGFyY2hpdmUgbXVzdCBjb250YWluIG9uZSBmaWxlLCBmb3VuZCAke2ZpbGVzLmxlbmd0aH1gKTtcbiAgfVxuICByZXR1cm4gc2VsZWN0ZWQ7XG59XG5cbmZ1bmN0aW9uIGZpbGVVcmxQYXRoKHVybDogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgdHJ5IHtcbiAgICBjb25zdCBwYXJzZWQgPSBuZXcgVVJMKHVybCk7XG4gICAgaWYgKHBhcnNlZC5wcm90b2NvbCAhPT0gXCJmaWxlOlwiKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIHJldHVybiBmaWxlVVJMVG9QYXRoKHBhcnNlZCk7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbn1cblxuaW50ZXJmYWNlIFNlbGVjdGVkQmluIHtcbiAgcGF0aDogc3RyaW5nO1xuICBwYWNrYWdlUm9vdD86IHN0cmluZztcbn1cblxuYXN5bmMgZnVuY3Rpb24gc2VsZWN0ZWRCaW4oXG4gIGRlc3RpbmF0aW9uOiBCaW5Db250ZXh0LFxuICBzb3VyY2U6IEJpblNvdXJjZSxcbiAgdGVtcDogc3RyaW5nLFxuICBvcHRpb25zOiBCaW5PcHRpb25zLFxuKTogUHJvbWlzZTxTZWxlY3RlZEJpbj4ge1xuICBjb25zdCB7IHVybCB9ID0gc291cmNlO1xuICBjb25zdCBsb2NhbFBhdGggPSBmaWxlVXJsUGF0aCh1cmwpO1xuICBsZXQgZG93bmxvYWRQYXRoOiBzdHJpbmc7XG4gIGlmIChsb2NhbFBhdGgpIHtcbiAgICBjb25zdCBhY2Nlc3MgPSBhd2FpdCBhY2Nlc3NDb250ZXh0KGxvY2FsUGF0aCk7XG4gICAgaWYgKCFhY2Nlc3MuZmlsZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBiaW5hcnkgZmlsZSBVUkwgZG9lcyBub3QgZXhpc3Q6ICR7ZGlzcGxheVVybCh1cmwpfWApO1xuICAgIH1cbiAgICBsb2dnZXIuZGVidWcoXCJ1c2luZyBsb2NhbCBiaW5hcnlcIiwgeyBmcm9tOiBkaXNwbGF5VXJsKHVybCksIHBhdGg6IGxvY2FsUGF0aCB9KTtcbiAgICBkb3dubG9hZFBhdGggPSBsb2NhbFBhdGg7XG4gIH0gZWxzZSB7XG4gICAgY29uc3QgbmFtZSA9IGRvd25sb2FkTmFtZSh1cmwsIGJhc2VuYW1lKGRlc3RpbmF0aW9uLnBhdGgpKTtcbiAgICBkb3dubG9hZFBhdGggPSBqb2luKHRlbXAsIG5hbWUpO1xuICAgIGNvbnN0IGRvd25sb2FkID0ge1xuICAgICAgZnJvbTogZGlzcGxheVVybCh1cmwpLFxuICAgICAgdG86IGRvd25sb2FkUGF0aCxcbiAgICB9O1xuICAgIGlmIChkb3dubG9hZC5mcm9tID09PSBcImRhdGE6XCIpIGxvZ2dlci5kZWJ1ZyhcImRvd25sb2FkaW5nIGJpbmFyeVwiLCBkb3dubG9hZCk7XG4gICAgZWxzZSBsb2dnZXIuaW5mbyhcImRvd25sb2FkaW5nIGJpbmFyeVwiLCBkb3dubG9hZCk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaCh1cmwpO1xuICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgYmluYXJ5IGRvd25sb2FkIGZhaWxlZCAoJHtyZXNwb25zZS5zdGF0dXN9KWApO1xuICAgIH1cbiAgICBjb25zdCBkb3dubG9hZGVkID0gQnVmZmVyLmZyb20oYXdhaXQgcmVzcG9uc2UuYXJyYXlCdWZmZXIoKSk7XG4gICAgaWYgKHNvdXJjZS5zaGEyNTYpIHtcbiAgICAgIGlmICghL15bMC05YS1mXXs2NH0kL2kudGVzdChzb3VyY2Uuc2hhMjU2KSkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgICAgIFwiYmluYXJ5IGRvd25sb2FkIFNIQS0yNTYgZGlnZXN0IG11c3QgY29udGFpbiA2NCBoZXhhZGVjaW1hbCBjaGFyYWN0ZXJzXCIsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBjb25zdCBhY3R1YWwgPSBjcmVhdGVIYXNoKFwic2hhMjU2XCIpLnVwZGF0ZShkb3dubG9hZGVkKS5kaWdlc3QoXCJoZXhcIik7XG4gICAgICBpZiAoYWN0dWFsLnRvTG93ZXJDYXNlKCkgIT09IHNvdXJjZS5zaGEyNTYudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGJpbmFyeSBkb3dubG9hZCBkaWdlc3QgbWlzbWF0Y2g6ICR7ZGlzcGxheVVybCh1cmwpfWApO1xuICAgICAgfVxuICAgIH1cbiAgICBhd2FpdCB3cml0ZUZpbGUoZG93bmxvYWRQYXRoLCBkb3dubG9hZGVkLCB7IG1vZGU6IDBvNzU1IH0pO1xuICB9XG5cbiAgbGV0IHNlbGVjdGVkU291cmNlID0gZG93bmxvYWRQYXRoO1xuICBsZXQgdW5wYWNrZWQgPSBmYWxzZTtcbiAgaWYgKG9wdGlvbnMucGFja2FnZSB8fCAob3B0aW9ucy5hdXRvVW5wYWNrYWdlICYmICFsb2NhbFBhdGgpKSB7XG4gICAgc2VsZWN0ZWRTb3VyY2UgPSBqb2luKHRlbXAsIGB1bnBhY2tlZC0ke3JhbmRvbVVVSUQoKX1gKTtcbiAgICBhd2FpdCBta2RpcihzZWxlY3RlZFNvdXJjZSk7XG4gICAgbG9nZ2VyLmluZm8oXCJ1bnBhY2tpbmcgYmluYXJ5IGFyY2hpdmVcIiwge1xuICAgICAgYXJjaGl2ZTogZG93bmxvYWRQYXRoLFxuICAgICAgdG86IHNlbGVjdGVkU291cmNlLFxuICAgIH0pO1xuICAgIGF3YWl0IHVucGFjayhkb3dubG9hZFBhdGgsIHNlbGVjdGVkU291cmNlKTtcbiAgICB1bnBhY2tlZCA9IHRydWU7XG4gIH1cblxuICBpZiAob3B0aW9ucy5zZWxlY3Rvcikge1xuICAgIGNvbnN0IHNlbGVjdGVkID0gYXdhaXQgb3B0aW9ucy5zZWxlY3Rvcih7XG4gICAgICBkZXN0aW5hdGlvbixcbiAgICAgIGRvd25sb2FkUGF0aCxcbiAgICAgIHNvdXJjZTogc2VsZWN0ZWRTb3VyY2UsXG4gICAgfSk7XG4gICAgbG9nZ2VyLmRlYnVnKFwic2VsZWN0ZWQgYmluYXJ5XCIsIHsgcGF0aDogc2VsZWN0ZWQgfSk7XG4gICAgcmV0dXJuIHsgcGF0aDogc2VsZWN0ZWQsIC4uLihvcHRpb25zLnBhY2thZ2UgPyB7IHBhY2thZ2VSb290OiBzZWxlY3RlZFNvdXJjZSB9IDoge30pIH07XG4gIH1cbiAgaWYgKG9wdGlvbnMucGFja2FnZSkge1xuICAgIGNvbnN0IHNlbGVjdGVkID0gcGFja2FnZVBhdGgoc2VsZWN0ZWRTb3VyY2UsIG9wdGlvbnMucGFja2FnZS5lbnRyeXBvaW50KTtcbiAgICBsb2dnZXIuZGVidWcoXCJzZWxlY3RlZCBiaW5hcnkgcGFja2FnZSBlbnRyeXBvaW50XCIsIHsgcGF0aDogc2VsZWN0ZWQgfSk7XG4gICAgcmV0dXJuIHsgcGF0aDogc2VsZWN0ZWQsIHBhY2thZ2VSb290OiBzZWxlY3RlZFNvdXJjZSB9O1xuICB9XG4gIGNvbnN0IHNlbGVjdGVkID0gdW5wYWNrZWQgPyBhd2FpdCBzZWxlY3RTaW5nbGVGaWxlKHNlbGVjdGVkU291cmNlKSA6IHNlbGVjdGVkU291cmNlO1xuICBsb2dnZXIuZGVidWcoXCJzZWxlY3RlZCBiaW5hcnlcIiwgeyBwYXRoOiBzZWxlY3RlZCB9KTtcbiAgcmV0dXJuIHsgcGF0aDogc2VsZWN0ZWQgfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gaW5zdGFsbFBhY2thZ2UoXG4gIHNvdXJjZTogc3RyaW5nLFxuICBkZXN0aW5hdGlvbjogQmluQ29udGV4dCxcbiAgb3B0aW9uczogQmluT3B0aW9ucyxcbik6IFByb21pc2U8dm9pZD4ge1xuICBpZiAoIW9wdGlvbnMucGFja2FnZSkgdGhyb3cgbmV3IEVycm9yKFwiYmluYXJ5IHBhY2thZ2Ugb3B0aW9ucyBhcmUgcmVxdWlyZWRcIik7XG4gIGNvbnN0IHBhcmVudCA9IGRpcm5hbWUoZGVzdGluYXRpb24ucm9vdCk7XG4gIGNvbnN0IG5hbWUgPSBiYXNlbmFtZShkZXN0aW5hdGlvbi5yb290KTtcbiAgY29uc3Qgc3RhZ2VkUm9vdCA9IGpvaW4ocGFyZW50LCBgLiR7bmFtZX0tc3RhZ2VkLSR7cmFuZG9tVVVJRCgpfWApO1xuICBjb25zdCBiYWNrdXBSb290ID0gam9pbihwYXJlbnQsIGAuJHtuYW1lfS1iYWNrdXAtJHtyYW5kb21VVUlEKCl9YCk7XG4gIGF3YWl0IG1rZGlyKHBhcmVudCwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gIGxvZ2dlci5pbmZvKFwic3RhZ2luZyBiaW5hcnkgcGFja2FnZVwiLCB7XG4gICAgZnJvbTogc291cmNlLFxuICAgIHRvOiBkZXN0aW5hdGlvbi5yb290LFxuICB9KTtcbiAgYXdhaXQgY3Aoc291cmNlLCBzdGFnZWRSb290LCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgY29uc3Qgc3RhZ2VkUGF0aCA9IHBhY2thZ2VQYXRoKHN0YWdlZFJvb3QsIG9wdGlvbnMucGFja2FnZS5lbnRyeXBvaW50KTtcbiAgYXdhaXQgY2htb2Qoc3RhZ2VkUGF0aCwgMG83NTUpO1xuICBjb25zdCBzdGFnZWQ6IEJpbkNvbnRleHQgPSB7XG4gICAgcm9vdDogc3RhZ2VkUm9vdCxcbiAgICBiaW5EaXI6IGRpcm5hbWUoc3RhZ2VkUGF0aCksXG4gICAgcGF0aDogc3RhZ2VkUGF0aCxcbiAgfTtcbiAgaWYgKCEoYXdhaXQgaXNWYWxpZEluc3RhbGwoc3RhZ2VkLCBvcHRpb25zKSkpIHtcbiAgICBhd2FpdCBybShzdGFnZWRSb290LCB7IHJlY3Vyc2l2ZTogdHJ1ZSwgZm9yY2U6IHRydWUgfSk7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBzZWxlY3RlZCBiaW5hcnkgcGFja2FnZSBpcyBpbnZhbGlkOiAke3NvdXJjZX1gKTtcbiAgfVxuXG4gIGxldCBiYWNrZWRVcCA9IGZhbHNlO1xuICB0cnkge1xuICAgIGlmIChhd2FpdCBwYXRoRXhpc3RzKGRlc3RpbmF0aW9uLnJvb3QpKSB7XG4gICAgICBhd2FpdCByZW5hbWUoZGVzdGluYXRpb24ucm9vdCwgYmFja3VwUm9vdCk7XG4gICAgICBiYWNrZWRVcCA9IHRydWU7XG4gICAgfVxuICAgIGF3YWl0IHJlbmFtZShzdGFnZWRSb290LCBkZXN0aW5hdGlvbi5yb290KTtcbiAgICBpZiAoIShhd2FpdCBpc1ZhbGlkSW5zdGFsbChkZXN0aW5hdGlvbiwgb3B0aW9ucykpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGluc3RhbGxlZCBiaW5hcnkgcGFja2FnZSBpcyBpbnZhbGlkIGFmdGVyIHJlbmFtZTogJHtkZXN0aW5hdGlvbi5yb290fWApO1xuICAgIH1cbiAgICBpZiAoYmFja2VkVXApIGF3YWl0IHJtKGJhY2t1cFJvb3QsIHsgcmVjdXJzaXZlOiB0cnVlLCBmb3JjZTogdHJ1ZSB9KTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBhd2FpdCBybShkZXN0aW5hdGlvbi5yb290LCB7IHJlY3Vyc2l2ZTogdHJ1ZSwgZm9yY2U6IHRydWUgfSk7XG4gICAgaWYgKGJhY2tlZFVwKSBhd2FpdCByZW5hbWUoYmFja3VwUm9vdCwgZGVzdGluYXRpb24ucm9vdCk7XG4gICAgdGhyb3cgZXJyb3I7XG4gIH0gZmluYWxseSB7XG4gICAgYXdhaXQgcm0oc3RhZ2VkUm9vdCwgeyByZWN1cnNpdmU6IHRydWUsIGZvcmNlOiB0cnVlIH0pO1xuICB9XG59XG5cbi8qKlxuICogUmV0dXJuIGFuIGV4aXN0aW5nIGV4ZWN1dGFibGUgb3IgaW5zdGFsbCBpdCBhdG9taWNhbGx5IHVuZGVyXG4gKiBgJEhPTUUvLjxuYW1lPi9iaW4vPG5hbWU+YC4gTXVsdGktZmlsZSBwYWNrYWdlIG1vZGUgYXRvbWljYWxseSBwcmVzZXJ2ZXMgdGhlXG4gKiB1bnBhY2tlZCBwYWNrYWdlIGF0IGFuIGV4cGxpY2l0IGRlc3RpbmF0aW9uIHJvb3QuIEluc3RhbGxhdGlvbiB1c2VzIGFcbiAqIGNoZWNrLWxvY2stY2hlY2stbG9hZCBzZXF1ZW5jZSBzbyBjb25jdXJyZW50IGNhbGxlcnMgcmVzb2x2ZSBhbmQgZG93bmxvYWRcbiAqIG9ubHkgb25jZS4gQ2FuZGlkYXRlcyBhbmQgZmluYWwgZGVzdGluYXRpb25zIG11c3QgcGFzcyB0aGUgc2FtZSBjaGVja3MuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBlbnN1cmUoXG4gIG5hbWU6IHN0cmluZyxcbiAgdXJsOiBCaW5VcmwsXG4gIG9wdGlvbnM6IEJpbk9wdGlvbnMgPSB7fSxcbik6IFByb21pc2U8QmluQ29udGV4dD4ge1xuICBpZiAob3B0aW9ucy5taW5WZXJzaW9uICYmICFtaW5pbXVtU2VtVmVyKG9wdGlvbnMubWluVmVyc2lvbikpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBpbnZhbGlkIG1pbmltdW0gYmluYXJ5IHZlcnNpb246ICR7b3B0aW9ucy5taW5WZXJzaW9ufWApO1xuICB9XG4gIGNvbnN0IGRlc3RpbmF0aW9uID0gY29udGV4dChuYW1lLCBvcHRpb25zLmhvbWVEaXIgPz8gaG9tZWRpcigpLCBvcHRpb25zLmRlc3RpbmF0aW9uKTtcbiAgcGFja2FnZURlc3RpbmF0aW9uKGRlc3RpbmF0aW9uLCBvcHRpb25zKTtcbiAgaWYgKCFvcHRpb25zLmZvcmNlICYmIChhd2FpdCBpc1ZhbGlkSW5zdGFsbChkZXN0aW5hdGlvbiwgb3B0aW9ucykpKSB7XG4gICAgbG9nZ2VyLmRlYnVnKFwidXNpbmcgaW5zdGFsbGVkIGJpbmFyeVwiLCB7IG5hbWUsIHBhdGg6IGRlc3RpbmF0aW9uLnBhdGggfSk7XG4gICAgcmV0dXJuIGRlc3RpbmF0aW9uO1xuICB9XG5cbiAgbG9nZ2VyLmRlYnVnKFwid2FpdGluZyBmb3IgYmluYXJ5IGluc3RhbGwgbG9ja1wiLCB7IG5hbWUsIHBhdGg6IGRlc3RpbmF0aW9uLnBhdGggfSk7XG4gIHJldHVybiB3aXRoRmlsZUxvY2soW1wiYmluLmVuc3VyZVwiLCBkZXN0aW5hdGlvbi5wYXRoXSwgYXN5bmMgKCkgPT4ge1xuICAgIGlmICghb3B0aW9ucy5mb3JjZSAmJiAoYXdhaXQgaXNWYWxpZEluc3RhbGwoZGVzdGluYXRpb24sIG9wdGlvbnMpKSkge1xuICAgICAgbG9nZ2VyLmRlYnVnKFwidXNpbmcgYmluYXJ5IGluc3RhbGxlZCBieSBhbm90aGVyIGNhbGxlclwiLCB7XG4gICAgICAgIG5hbWUsXG4gICAgICAgIHBhdGg6IGRlc3RpbmF0aW9uLnBhdGgsXG4gICAgICB9KTtcbiAgICAgIHJldHVybiBkZXN0aW5hdGlvbjtcbiAgICB9XG5cbiAgICBsb2dnZXIuZGVidWcoXCJpbnN0YWxsaW5nIGJpbmFyeVwiLCB7XG4gICAgICBuYW1lLFxuICAgICAgdG86IGRlc3RpbmF0aW9uLnBhdGgsXG4gICAgICBtaW5WZXJzaW9uOiBvcHRpb25zLm1pblZlcnNpb24sXG4gICAgfSk7XG4gICAgY29uc3QgdGVtcCA9IGF3YWl0IG1rZHRlbXAoam9pbih0bXBkaXIoKSwgYCR7bmFtZX0tYCkpO1xuICAgIGxldCBzdGFnZWQ6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzb2x2ZWQgPSB0eXBlb2YgdXJsID09PSBcImZ1bmN0aW9uXCIgPyBhd2FpdCB1cmwoeyB0ZW1wRGlyOiB0ZW1wIH0pIDogdXJsO1xuICAgICAgY29uc3Qgc291cmNlID0gdHlwZW9mIHJlc29sdmVkID09PSBcInN0cmluZ1wiID8geyB1cmw6IHJlc29sdmVkIH0gOiByZXNvbHZlZDtcbiAgICAgIGNvbnN0IGZyb20gPSBkaXNwbGF5VXJsKHNvdXJjZS51cmwpO1xuICAgICAgbG9nZ2VyLmRlYnVnKFwicmVzb2x2ZWQgYmluYXJ5IHNvdXJjZVwiLCB7IG5hbWUsIGZyb20gfSk7XG4gICAgICBjb25zdCBzZWxlY3RlZCA9IGF3YWl0IHNlbGVjdGVkQmluKGRlc3RpbmF0aW9uLCBzb3VyY2UsIHRlbXAsIG9wdGlvbnMpO1xuICAgICAgYXdhaXQgY2htb2Qoc2VsZWN0ZWQucGF0aCwgMG83NTUpO1xuICAgICAgaWYgKCEoYXdhaXQgaXNWYWxpZEJpbihzZWxlY3RlZC5wYXRoLCBvcHRpb25zKSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBzZWxlY3RlZCBiaW5hcnkgaGFzIG5vIGFjY2VwdGFibGUgdmVyc2lvbjogJHtzZWxlY3RlZC5wYXRofWApO1xuICAgICAgfVxuICAgICAgaWYgKG9wdGlvbnMucGFja2FnZSkge1xuICAgICAgICBpZiAoIXNlbGVjdGVkLnBhY2thZ2VSb290KSB0aHJvdyBuZXcgRXJyb3IoXCJiaW5hcnkgcGFja2FnZSByb290IHdhcyBub3Qgc2VsZWN0ZWRcIik7XG4gICAgICAgIGF3YWl0IGluc3RhbGxQYWNrYWdlKHNlbGVjdGVkLnBhY2thZ2VSb290LCBkZXN0aW5hdGlvbiwgb3B0aW9ucyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhd2FpdCBta2RpcihkZXN0aW5hdGlvbi5iaW5EaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgICAgICBzdGFnZWQgPSBqb2luKGRlc3RpbmF0aW9uLmJpbkRpciwgYC4ke25hbWV9LSR7cmFuZG9tVVVJRCgpfWApO1xuICAgICAgICBhd2FpdCBjb3B5RmlsZShzZWxlY3RlZC5wYXRoLCBzdGFnZWQpO1xuICAgICAgICBhd2FpdCBjaG1vZChzdGFnZWQsIDBvNzU1KTtcbiAgICAgICAgYXdhaXQgcmVuYW1lKHN0YWdlZCwgZGVzdGluYXRpb24ucGF0aCk7XG4gICAgICAgIHN0YWdlZCA9IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKCEoYXdhaXQgaXNWYWxpZEluc3RhbGwoZGVzdGluYXRpb24sIG9wdGlvbnMpKSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgaW5zdGFsbGVkIGJpbmFyeSBpcyBpbnZhbGlkIGFmdGVyIHJlbmFtZTogJHtkZXN0aW5hdGlvbi5wYXRofWApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBsb2dnZXIuaW5mbyhcImluc3RhbGxlZCBiaW5hcnlcIiwge1xuICAgICAgICBuYW1lLFxuICAgICAgICBmcm9tLFxuICAgICAgICB0bzogZGVzdGluYXRpb24ucGF0aCxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIGRlc3RpbmF0aW9uO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBpZiAoc3RhZ2VkKSBhd2FpdCBybShzdGFnZWQsIHsgZm9yY2U6IHRydWUgfSk7XG4gICAgICBhd2FpdCBybSh0ZW1wLCB7IHJlY3Vyc2l2ZTogdHJ1ZSwgZm9yY2U6IHRydWUgfSk7XG4gICAgfVxuICB9KTtcbn1cbiJdfQ==
package/package.json CHANGED
@@ -25,7 +25,7 @@
25
25
  "typescript": "^5.9.3"
26
26
  },
27
27
  "dependencies": {
28
- "@dbx-tools/shared-core": "^0.9.60",
28
+ "@dbx-tools/shared-core": "^0.9.64",
29
29
  "extract-zip": "^2.0.1",
30
30
  "proper-lockfile": "^4.1.2",
31
31
  "semver": "^7.7.3",
@@ -87,7 +87,7 @@
87
87
  "./package.json": "./package.json"
88
88
  }
89
89
  },
90
- "version": "0.9.60",
90
+ "version": "0.9.64",
91
91
  "types": "./lib/index.d.ts",
92
92
  "dbxToolsConfig": {
93
93
  "tags": [
package/src/bin.ts CHANGED
@@ -7,6 +7,7 @@ import { execFile } from "node:child_process";
7
7
  import { createHash, randomUUID } from "node:crypto";
8
8
  import {
9
9
  chmod,
10
+ cp,
10
11
  copyFile,
11
12
  mkdir,
12
13
  mkdtemp,
@@ -17,7 +18,7 @@ import {
17
18
  writeFile,
18
19
  } from "node:fs/promises";
19
20
  import { homedir, tmpdir } from "node:os";
20
- import { basename, join } from "node:path";
21
+ import { basename, dirname, isAbsolute, join, resolve, sep } from "node:path";
21
22
  import { fileURLToPath } from "node:url";
22
23
  import { promisify } from "node:util";
23
24
 
@@ -74,6 +75,8 @@ export type BinVersionParser = (output: BinVersionOutput) => string | undefined;
74
75
  /** Options for {@link ensure}. */
75
76
  export interface BinOptions {
76
77
  autoUnpackage?: boolean;
78
+ /** Preserve an unpacked multi-file package rooted at {@link BinContext.root}. */
79
+ package?: BinPackageOptions;
77
80
  selector?: BinSelector;
78
81
  homeDir?: string;
79
82
  /** Exact installation paths. Omission keeps `$HOME/.<name>/bin/<name>`. */
@@ -90,6 +93,14 @@ export interface BinOptions {
90
93
  force?: boolean;
91
94
  }
92
95
 
96
+ /** Multi-file archive layout retained beside its executable entrypoint. */
97
+ export interface BinPackageOptions {
98
+ /** Executable path relative to the unpacked package root. */
99
+ entrypoint: string;
100
+ /** Companion files or directories required before an installation can be reused. */
101
+ requiredPaths?: readonly string[];
102
+ }
103
+
93
104
  /** Temporary directory created for one `ensure` attempt after the install lock. */
94
105
  export interface BinUrlResolveContext {
95
106
  readonly tempDir: string;
@@ -117,6 +128,29 @@ function context(name: string, homeDir: string, destination?: BinContext): BinCo
117
128
  return { root, binDir, path: join(binDir, name) };
118
129
  }
119
130
 
131
+ function packagePath(root: string, path: string): string {
132
+ if (!path || isAbsolute(path)) {
133
+ throw new TypeError(`invalid binary package path: ${path}`);
134
+ }
135
+ const packageRoot = resolve(root);
136
+ const resolved = resolve(packageRoot, path);
137
+ if (resolved === packageRoot || !resolved.startsWith(`${packageRoot}${sep}`)) {
138
+ throw new TypeError(`binary package path escapes its root: ${path}`);
139
+ }
140
+ return resolved;
141
+ }
142
+
143
+ function packageDestination(destination: BinContext, options: BinOptions): void {
144
+ if (!options.package) return;
145
+ const entrypoint = packagePath(destination.root, options.package.entrypoint);
146
+ if (resolve(destination.path) !== entrypoint) {
147
+ throw new TypeError("binary package destination path must match its entrypoint");
148
+ }
149
+ for (const path of options.package.requiredPaths ?? []) {
150
+ packagePath(destination.root, path);
151
+ }
152
+ }
153
+
120
154
  function displayUrl(raw: string): string {
121
155
  try {
122
156
  const url = new URL(raw);
@@ -233,6 +267,25 @@ async function isValidBin(path: string, options: BinOptions): Promise<boolean> {
233
267
  return valid;
234
268
  }
235
269
 
270
+ async function pathExists(path: string): Promise<boolean> {
271
+ try {
272
+ await stat(path);
273
+ return true;
274
+ } catch {
275
+ return false;
276
+ }
277
+ }
278
+
279
+ async function isValidInstall(destination: BinContext, options: BinOptions): Promise<boolean> {
280
+ if (!(await isValidBin(destination.path, options))) return false;
281
+ if (!options.package) return true;
282
+ const required = [options.package.entrypoint, ...(options.package.requiredPaths ?? [])];
283
+ const available = await Promise.all(
284
+ required.map((path) => pathExists(packagePath(destination.root, path))),
285
+ );
286
+ return available.every(Boolean);
287
+ }
288
+
236
289
  function downloadName(url: string, name: string): string {
237
290
  try {
238
291
  const candidate = basename(decodeURIComponent(new URL(url).pathname));
@@ -288,53 +341,66 @@ function fileUrlPath(url: string): string | undefined {
288
341
  }
289
342
  }
290
343
 
344
+ interface SelectedBin {
345
+ path: string;
346
+ packageRoot?: string;
347
+ }
348
+
291
349
  async function selectedBin(
292
350
  destination: BinContext,
293
351
  source: BinSource,
294
352
  temp: string,
295
353
  options: BinOptions,
296
- ): Promise<string> {
354
+ ): Promise<SelectedBin> {
297
355
  const { url } = source;
298
356
  const localPath = fileUrlPath(url);
357
+ let downloadPath: string;
299
358
  if (localPath) {
300
359
  const access = await accessContext(localPath);
301
360
  if (!access.file) {
302
361
  throw new Error(`binary file URL does not exist: ${displayUrl(url)}`);
303
362
  }
304
363
  logger.debug("using local binary", { from: displayUrl(url), path: localPath });
305
- return localPath;
306
- }
307
- const name = downloadName(url, basename(destination.path));
308
- const downloadPath = join(temp, name);
309
- logger.debug("downloading binary", {
310
- from: displayUrl(url),
311
- to: downloadPath,
312
- });
313
- const response = await fetch(url);
314
- if (!response.ok) {
315
- throw new Error(`binary download failed (${response.status})`);
316
- }
317
- const downloaded = Buffer.from(await response.arrayBuffer());
318
- if (source.sha256) {
319
- if (!/^[0-9a-f]{64}$/i.test(source.sha256)) {
320
- throw new TypeError("binary download SHA-256 digest must contain 64 hexadecimal characters");
364
+ downloadPath = localPath;
365
+ } else {
366
+ const name = downloadName(url, basename(destination.path));
367
+ downloadPath = join(temp, name);
368
+ const download = {
369
+ from: displayUrl(url),
370
+ to: downloadPath,
371
+ };
372
+ if (download.from === "data:") logger.debug("downloading binary", download);
373
+ else logger.info("downloading binary", download);
374
+ const response = await fetch(url);
375
+ if (!response.ok) {
376
+ throw new Error(`binary download failed (${response.status})`);
321
377
  }
322
- const actual = createHash("sha256").update(downloaded).digest("hex");
323
- if (actual.toLowerCase() !== source.sha256.toLowerCase()) {
324
- throw new Error(`binary download digest mismatch: ${displayUrl(url)}`);
378
+ const downloaded = Buffer.from(await response.arrayBuffer());
379
+ if (source.sha256) {
380
+ if (!/^[0-9a-f]{64}$/i.test(source.sha256)) {
381
+ throw new TypeError(
382
+ "binary download SHA-256 digest must contain 64 hexadecimal characters",
383
+ );
384
+ }
385
+ const actual = createHash("sha256").update(downloaded).digest("hex");
386
+ if (actual.toLowerCase() !== source.sha256.toLowerCase()) {
387
+ throw new Error(`binary download digest mismatch: ${displayUrl(url)}`);
388
+ }
325
389
  }
390
+ await writeFile(downloadPath, downloaded, { mode: 0o755 });
326
391
  }
327
- await writeFile(downloadPath, downloaded, { mode: 0o755 });
328
392
 
329
393
  let selectedSource = downloadPath;
330
- if (options.autoUnpackage) {
394
+ let unpacked = false;
395
+ if (options.package || (options.autoUnpackage && !localPath)) {
331
396
  selectedSource = join(temp, `unpacked-${randomUUID()}`);
332
397
  await mkdir(selectedSource);
333
- logger.debug("unpacking binary archive", {
398
+ logger.info("unpacking binary archive", {
334
399
  archive: downloadPath,
335
400
  to: selectedSource,
336
401
  });
337
402
  await unpack(downloadPath, selectedSource);
403
+ unpacked = true;
338
404
  }
339
405
 
340
406
  if (options.selector) {
@@ -344,19 +410,72 @@ async function selectedBin(
344
410
  source: selectedSource,
345
411
  });
346
412
  logger.debug("selected binary", { path: selected });
347
- return selected;
413
+ return { path: selected, ...(options.package ? { packageRoot: selectedSource } : {}) };
414
+ }
415
+ if (options.package) {
416
+ const selected = packagePath(selectedSource, options.package.entrypoint);
417
+ logger.debug("selected binary package entrypoint", { path: selected });
418
+ return { path: selected, packageRoot: selectedSource };
348
419
  }
349
- const selected = options.autoUnpackage ? await selectSingleFile(selectedSource) : selectedSource;
420
+ const selected = unpacked ? await selectSingleFile(selectedSource) : selectedSource;
350
421
  logger.debug("selected binary", { path: selected });
351
- return selected;
422
+ return { path: selected };
423
+ }
424
+
425
+ async function installPackage(
426
+ source: string,
427
+ destination: BinContext,
428
+ options: BinOptions,
429
+ ): Promise<void> {
430
+ if (!options.package) throw new Error("binary package options are required");
431
+ const parent = dirname(destination.root);
432
+ const name = basename(destination.root);
433
+ const stagedRoot = join(parent, `.${name}-staged-${randomUUID()}`);
434
+ const backupRoot = join(parent, `.${name}-backup-${randomUUID()}`);
435
+ await mkdir(parent, { recursive: true });
436
+ logger.info("staging binary package", {
437
+ from: source,
438
+ to: destination.root,
439
+ });
440
+ await cp(source, stagedRoot, { recursive: true });
441
+ const stagedPath = packagePath(stagedRoot, options.package.entrypoint);
442
+ await chmod(stagedPath, 0o755);
443
+ const staged: BinContext = {
444
+ root: stagedRoot,
445
+ binDir: dirname(stagedPath),
446
+ path: stagedPath,
447
+ };
448
+ if (!(await isValidInstall(staged, options))) {
449
+ await rm(stagedRoot, { recursive: true, force: true });
450
+ throw new Error(`selected binary package is invalid: ${source}`);
451
+ }
452
+
453
+ let backedUp = false;
454
+ try {
455
+ if (await pathExists(destination.root)) {
456
+ await rename(destination.root, backupRoot);
457
+ backedUp = true;
458
+ }
459
+ await rename(stagedRoot, destination.root);
460
+ if (!(await isValidInstall(destination, options))) {
461
+ throw new Error(`installed binary package is invalid after rename: ${destination.root}`);
462
+ }
463
+ if (backedUp) await rm(backupRoot, { recursive: true, force: true });
464
+ } catch (error) {
465
+ await rm(destination.root, { recursive: true, force: true });
466
+ if (backedUp) await rename(backupRoot, destination.root);
467
+ throw error;
468
+ } finally {
469
+ await rm(stagedRoot, { recursive: true, force: true });
470
+ }
352
471
  }
353
472
 
354
473
  /**
355
474
  * Return an existing executable or install it atomically under
356
- * `$HOME/.<name>/bin/<name>`. Installation uses a check-lock-check-load
357
- * sequence so concurrent callers resolve and download the binary only once.
358
- * The downloaded candidate and final renamed executable must both pass the
359
- * same executable and version checks.
475
+ * `$HOME/.<name>/bin/<name>`. Multi-file package mode atomically preserves the
476
+ * unpacked package at an explicit destination root. Installation uses a
477
+ * check-lock-check-load sequence so concurrent callers resolve and download
478
+ * only once. Candidates and final destinations must pass the same checks.
360
479
  */
361
480
  export async function ensure(
362
481
  name: string,
@@ -367,14 +486,15 @@ export async function ensure(
367
486
  throw new TypeError(`invalid minimum binary version: ${options.minVersion}`);
368
487
  }
369
488
  const destination = context(name, options.homeDir ?? homedir(), options.destination);
370
- if (!options.force && (await isValidBin(destination.path, options))) {
489
+ packageDestination(destination, options);
490
+ if (!options.force && (await isValidInstall(destination, options))) {
371
491
  logger.debug("using installed binary", { name, path: destination.path });
372
492
  return destination;
373
493
  }
374
494
 
375
495
  logger.debug("waiting for binary install lock", { name, path: destination.path });
376
496
  return withFileLock(["bin.ensure", destination.path], async () => {
377
- if (!options.force && (await isValidBin(destination.path, options))) {
497
+ if (!options.force && (await isValidInstall(destination, options))) {
378
498
  logger.debug("using binary installed by another caller", {
379
499
  name,
380
500
  path: destination.path,
@@ -395,19 +515,23 @@ export async function ensure(
395
515
  const from = displayUrl(source.url);
396
516
  logger.debug("resolved binary source", { name, from });
397
517
  const selected = await selectedBin(destination, source, temp, options);
398
- await chmod(selected, 0o755);
399
- if (!(await isValidBin(selected, options))) {
400
- throw new Error(`selected binary has no acceptable version: ${selected}`);
518
+ await chmod(selected.path, 0o755);
519
+ if (!(await isValidBin(selected.path, options))) {
520
+ throw new Error(`selected binary has no acceptable version: ${selected.path}`);
401
521
  }
402
-
403
- await mkdir(destination.binDir, { recursive: true });
404
- staged = join(destination.binDir, `.${name}-${randomUUID()}`);
405
- await copyFile(selected, staged);
406
- await chmod(staged, 0o755);
407
- await rename(staged, destination.path);
408
- staged = undefined;
409
- if (!(await isValidBin(destination.path, options))) {
410
- throw new Error(`installed binary is invalid after rename: ${destination.path}`);
522
+ if (options.package) {
523
+ if (!selected.packageRoot) throw new Error("binary package root was not selected");
524
+ await installPackage(selected.packageRoot, destination, options);
525
+ } else {
526
+ await mkdir(destination.binDir, { recursive: true });
527
+ staged = join(destination.binDir, `.${name}-${randomUUID()}`);
528
+ await copyFile(selected.path, staged);
529
+ await chmod(staged, 0o755);
530
+ await rename(staged, destination.path);
531
+ staged = undefined;
532
+ if (!(await isValidInstall(destination, options))) {
533
+ throw new Error(`installed binary is invalid after rename: ${destination.path}`);
534
+ }
411
535
  }
412
536
  logger.info("installed binary", {
413
537
  name,