@decohere/create 0.0.1-dev.20 → 0.0.1-dev.20261105.110

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +255 -0
  3. package/es6/src/cli.js +1 -34
  4. package/es6/src/index.js +2 -0
  5. package/es6/src/resolve-launch.js +87 -0
  6. package/es6/src/runner.js +67 -24
  7. package/es6/src/version.js +14 -6
  8. package/pack-builder-tgz.mjs +177 -0
  9. package/package.json +23 -11
  10. package/types/src/index.d.ts +3 -0
  11. package/types/src/resolve-launch.d.ts +20 -0
  12. package/types/src/runner.d.ts +3 -11
  13. package/types/src/version.d.ts +1 -1
  14. package/commonjs/src/cli.js +0 -40
  15. package/commonjs/src/domain/prompt.js +0 -55
  16. package/commonjs/src/models/compose.model.js +0 -82
  17. package/commonjs/src/models/config-yaml.model.js +0 -34
  18. package/commonjs/src/models/const.js +0 -29
  19. package/commonjs/src/models/container-image.model.js +0 -88
  20. package/commonjs/src/models/dev-container.model.js +0 -73
  21. package/commonjs/src/models/env-file.model.js +0 -33
  22. package/commonjs/src/models/gitignore.model.js +0 -32
  23. package/commonjs/src/models/launch-json.model.js +0 -52
  24. package/commonjs/src/models/package-json.model.js +0 -64
  25. package/commonjs/src/models/project.model.js +0 -126
  26. package/commonjs/src/models/source-file.js +0 -6
  27. package/commonjs/src/models/tsconfig.model.js +0 -34
  28. package/commonjs/src/models/vscode-settings.model.js +0 -31
  29. package/commonjs/src/runner.js +0 -56
  30. package/commonjs/src/services/scaffold.service.js +0 -62
  31. package/commonjs/src/version.js +0 -32
  32. package/commonjs/src/webapi/create-api.js +0 -169
  33. package/commonjs/src/webapi/features/auth.feature.js +0 -166
  34. package/commonjs/src/webapi/features/auth0-cli.js +0 -151
  35. package/commonjs/src/webapi/features/database.feature.js +0 -151
  36. package/commonjs/src/webapi/features/finalize.feature.js +0 -51
  37. package/commonjs/src/webapi/features/postman.feature.js +0 -309
  38. package/commonjs/src/webapi/models/api-package-json.model.js +0 -57
  39. package/commonjs/src/webapi/models/auth-config.model.js +0 -23
  40. package/commonjs/src/webapi/models/controller-source-file.model.js +0 -180
  41. package/commonjs/src/webapi/models/main-source-file.model.js +0 -132
  42. package/commonjs/src/webapi/models/sample-files.model.js +0 -60
  43. package/es6/src/domain/prompt.js +0 -37
  44. package/es6/src/models/compose.model.js +0 -77
  45. package/es6/src/models/config-yaml.model.js +0 -30
  46. package/es6/src/models/const.js +0 -19
  47. package/es6/src/models/container-image.model.js +0 -84
  48. package/es6/src/models/dev-container.model.js +0 -68
  49. package/es6/src/models/env-file.model.js +0 -29
  50. package/es6/src/models/gitignore.model.js +0 -22
  51. package/es6/src/models/launch-json.model.js +0 -42
  52. package/es6/src/models/package-json.model.js +0 -60
  53. package/es6/src/models/project.model.js +0 -111
  54. package/es6/src/models/source-file.js +0 -3
  55. package/es6/src/models/tsconfig.model.js +0 -24
  56. package/es6/src/models/vscode-settings.model.js +0 -21
  57. package/es6/src/services/scaffold.service.js +0 -52
  58. package/es6/src/webapi/create-api.js +0 -151
  59. package/es6/src/webapi/features/auth.feature.js +0 -115
  60. package/es6/src/webapi/features/auth0-cli.js +0 -116
  61. package/es6/src/webapi/features/database.feature.js +0 -141
  62. package/es6/src/webapi/features/finalize.feature.js +0 -41
  63. package/es6/src/webapi/features/postman.feature.js +0 -258
  64. package/es6/src/webapi/models/api-package-json.model.js +0 -52
  65. package/es6/src/webapi/models/auth-config.model.js +0 -19
  66. package/es6/src/webapi/models/controller-source-file.model.js +0 -171
  67. package/es6/src/webapi/models/main-source-file.model.js +0 -128
  68. package/es6/src/webapi/models/sample-files.model.js +0 -42
  69. package/types/src/domain/prompt.d.ts +0 -2
  70. package/types/src/models/compose.model.d.ts +0 -32
  71. package/types/src/models/config-yaml.model.d.ts +0 -16
  72. package/types/src/models/const.d.ts +0 -17
  73. package/types/src/models/container-image.model.d.ts +0 -15
  74. package/types/src/models/dev-container.model.d.ts +0 -21
  75. package/types/src/models/env-file.model.d.ts +0 -14
  76. package/types/src/models/gitignore.model.d.ts +0 -6
  77. package/types/src/models/launch-json.model.d.ts +0 -5
  78. package/types/src/models/package-json.model.d.ts +0 -18
  79. package/types/src/models/project.model.d.ts +0 -55
  80. package/types/src/models/source-file.d.ts +0 -11
  81. package/types/src/models/tsconfig.model.d.ts +0 -5
  82. package/types/src/models/vscode-settings.model.d.ts +0 -7
  83. package/types/src/services/scaffold.service.d.ts +0 -22
  84. package/types/src/webapi/create-api.d.ts +0 -7
  85. package/types/src/webapi/features/auth.feature.d.ts +0 -7
  86. package/types/src/webapi/features/auth0-cli.d.ts +0 -22
  87. package/types/src/webapi/features/database.feature.d.ts +0 -5
  88. package/types/src/webapi/features/finalize.feature.d.ts +0 -2
  89. package/types/src/webapi/features/postman.feature.d.ts +0 -7
  90. package/types/src/webapi/models/api-package-json.model.d.ts +0 -17
  91. package/types/src/webapi/models/auth-config.model.d.ts +0 -18
  92. package/types/src/webapi/models/controller-source-file.model.d.ts +0 -42
  93. package/types/src/webapi/models/main-source-file.model.d.ts +0 -36
  94. package/types/src/webapi/models/sample-files.model.d.ts +0 -7
@@ -0,0 +1,177 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Vendor `@decohere/scaffold` for the builder image: resolve `@decohere/*` from
4
+ * dist/release via `file:` (not `overrides`), `npm install --install-links`,
5
+ * then tar the installed tree including `node_modules`. `--install-links`
6
+ * materializes `file:` packages (and their deps) instead of leaving symlinks
7
+ * whose nested installs live outside the packed directory.
8
+ */
9
+ import { spawnSync } from "node:child_process";
10
+ import { readdirSync, readFileSync, writeFileSync } from "node:fs";
11
+ import { dirname, join, relative, resolve } from "node:path";
12
+ import { fileURLToPath } from "node:url";
13
+
14
+ /**
15
+ * @typedef {{ name: string, dir: string }} WorkspacePackage
16
+ */
17
+
18
+ /**
19
+ * @param {string} rootDir
20
+ * @returns {WorkspacePackage[]}
21
+ */
22
+ export function collectWorkspacePackages(rootDir) {
23
+ /** @type {WorkspacePackage[]} */
24
+ const found = [];
25
+ const walk = (dir) => {
26
+ let entries;
27
+ try {
28
+ entries = readdirSync(dir, { withFileTypes: true });
29
+ } catch {
30
+ return;
31
+ }
32
+ for (const entry of entries) {
33
+ if (entry.name === "node_modules" || entry.name === ".git") continue;
34
+ const path = join(dir, entry.name);
35
+ if (entry.isDirectory()) {
36
+ walk(path);
37
+ continue;
38
+ }
39
+ if (entry.name !== "package.json") continue;
40
+ const pkg = JSON.parse(readFileSync(path, "utf8"));
41
+ if (typeof pkg.name === "string" && pkg.name.startsWith("@decohere/")) {
42
+ found.push({ name: pkg.name, dir });
43
+ }
44
+ }
45
+ };
46
+ walk(rootDir);
47
+ return found;
48
+ }
49
+
50
+ /**
51
+ * @param {string} fromDir
52
+ * @param {string} pkgDir
53
+ */
54
+ export function fileSpec(fromDir, pkgDir) {
55
+ let rel = relative(fromDir, pkgDir) || ".";
56
+ rel = rel.replaceAll("\\", "/");
57
+ if (!rel.startsWith(".")) rel = `./${rel}`;
58
+ return `file:${rel}`;
59
+ }
60
+
61
+ /**
62
+ * Rewrite `@decohere/*` dependency specs to local `file:` paths.
63
+ * Must mutate `dependencies` (not `overrides`) — npm throws EOVERRIDE when an
64
+ * override conflicts with a direct dependency.
65
+ *
66
+ * @param {Record<string, unknown>} pkg
67
+ * @param {string} fromDir
68
+ * @param {WorkspacePackage[]} packages
69
+ */
70
+ export function rewriteDecohereDepsToFile(pkg, fromDir, packages) {
71
+ const byName = new Map(packages.map((item) => [item.name, item.dir]));
72
+ const from = resolve(fromDir);
73
+ const rewrite = (deps) => {
74
+ if (deps == null || typeof deps !== "object" || Array.isArray(deps)) return deps;
75
+ const next = { .../** @type {Record<string, unknown>} */ (deps) };
76
+ for (const name of Object.keys(next)) {
77
+ const dir = byName.get(name);
78
+ if (dir == null || resolve(dir) === from) continue;
79
+ next[name] = fileSpec(fromDir, dir);
80
+ }
81
+ return next;
82
+ };
83
+ return {
84
+ ...pkg,
85
+ dependencies: rewrite(pkg.dependencies),
86
+ optionalDependencies: rewrite(pkg.optionalDependencies),
87
+ };
88
+ }
89
+
90
+ function writeJson(path, value) {
91
+ writeFileSync(path, `${JSON.stringify(value, null, 2)}\n`);
92
+ }
93
+
94
+ function runNpm(cwd, args) {
95
+ const result = spawnSync("npm", args, { cwd, encoding: "utf8" });
96
+ if (result.status !== 0) {
97
+ throw new Error(
98
+ `npm ${args.join(" ")} failed (exit ${result.status}):\n${result.stderr}${result.stdout}`,
99
+ );
100
+ }
101
+ return result.stdout.trim();
102
+ }
103
+
104
+ function packInstalledTree(outDir, dest) {
105
+ const result = spawnSync(
106
+ "tar",
107
+ ["--create", "--gzip", "--dereference", "--file", dest, "-C", outDir, "."],
108
+ { encoding: "utf8" },
109
+ );
110
+ if (result.status !== 0) {
111
+ throw new Error(`tar failed (exit ${result.status}):\n${result.stderr}${result.stdout}`);
112
+ }
113
+ }
114
+
115
+ export function packBuilderTgz(options) {
116
+ const outDir = resolve(options.outDir);
117
+ const workspaceOut = resolve(options.workspaceOut);
118
+ const dest = resolve(options.dest);
119
+ const packageJsonPath = join(outDir, "package.json");
120
+ const packages = collectWorkspacePackages(workspaceOut);
121
+ const originals = packages.map((pkg) => {
122
+ const path = join(pkg.dir, "package.json");
123
+ return { path, original: JSON.parse(readFileSync(path, "utf8")) };
124
+ });
125
+ const createOriginal = originals.find((entry) => entry.path === packageJsonPath)?.original;
126
+ if (createOriginal == null) {
127
+ throw new Error(`No @decohere package.json at ${packageJsonPath}`);
128
+ }
129
+
130
+ try {
131
+ for (const { path, original } of originals) {
132
+ writeJson(path, rewriteDecohereDepsToFile(original, dirname(path), packages));
133
+ }
134
+ runNpm(outDir, ["install", "--omit=dev", "--ignore-scripts", "--install-links"]);
135
+ } finally {
136
+ for (const { path, original } of originals) {
137
+ writeJson(path, original);
138
+ }
139
+ }
140
+
141
+ packInstalledTree(outDir, dest);
142
+ return dest;
143
+ }
144
+
145
+ function parseArgs(argv) {
146
+ /** @type {Record<string, string>} */
147
+ const parsed = {};
148
+ for (let i = 0; i < argv.length; i++) {
149
+ const arg = argv[i];
150
+ if (arg == null || !arg.startsWith("--")) continue;
151
+ const key = arg.slice(2);
152
+ const value = argv[i + 1];
153
+ if (value == null || value.startsWith("--")) {
154
+ throw new Error(`Missing value for --${key}`);
155
+ }
156
+ parsed[key] = value;
157
+ i++;
158
+ }
159
+ return parsed;
160
+ }
161
+
162
+ function main() {
163
+ const args = parseArgs(process.argv.slice(2));
164
+ const outDir = args["out-dir"];
165
+ const workspaceOut = args["workspace-out"];
166
+ const dest = args.dest;
167
+ if (outDir == null || workspaceOut == null || dest == null) {
168
+ throw new Error(
169
+ "Usage: pack-builder-tgz.mjs --out-dir <dir> --workspace-out <dir> --dest <create.tgz>",
170
+ );
171
+ }
172
+ packBuilderTgz({ outDir, workspaceOut, dest });
173
+ }
174
+
175
+ if (process.argv[1] != null && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
176
+ main();
177
+ }
package/package.json CHANGED
@@ -1,28 +1,40 @@
1
1
  {
2
2
  "name": "@decohere/create",
3
- "version": "0.0.1-dev.20",
4
- "description": "Scaffold a new Decohere project — build with Forge, serve with Flux",
3
+ "version": "0.0.1-dev.20261105.110",
4
+ "description": "Download the Decohere scaffolder image and run it (npm create @decohere)",
5
5
  "keywords": [
6
6
  "decohere",
7
7
  "create",
8
8
  "scaffold",
9
- "cli",
10
- "forge",
11
- "flux",
12
- "typescript"
9
+ "cli"
13
10
  ],
11
+ "homepage": "https://github.com/typesmiths/decohere/tree/main/projects/create#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/typesmiths/decohere/issues"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/typesmiths/decohere.git",
18
+ "directory": "projects/create"
19
+ },
14
20
  "license": "ISC",
15
21
  "author": "Typesmiths",
16
22
  "type": "module",
23
+ "exports": {
24
+ ".": {
25
+ "types": "./types/src/index.d.ts",
26
+ "import": "./es6/src/index.js"
27
+ }
28
+ },
17
29
  "bin": {
18
30
  "create-decohere": "./es6/src/cli.js"
19
31
  },
20
32
  "scripts": {
21
33
  "test": "echo \"Error: no test specified\" && exit 1"
22
34
  },
23
- "dependencies": {
24
- "@decohere/nexus": "0.0.1-dev.20",
25
- "commander": "^13.1.0"
26
- },
27
- "devDependencies": {}
35
+ "dependencies": {},
36
+ "devDependencies": {},
37
+ "decohere": {
38
+ "dockerImageRepository": "ghcr.io/typesmiths/decohere/create"
39
+ }
28
40
  }
@@ -0,0 +1,3 @@
1
+ export type { LaunchKind, LaunchPlan } from "./resolve-launch.js";
2
+ export { containerArgvFromHost, resolveLaunch, toProductArgv } from "./resolve-launch.js";
3
+ export { runInBuilder } from "./runner.js";
@@ -0,0 +1,20 @@
1
+ export type LaunchKind = "scaffold" | "auth0";
2
+ export type LaunchPlan = {
3
+ targetDir: string;
4
+ containerArgv: string[];
5
+ projectName: string;
6
+ kind: LaunchKind;
7
+ };
8
+ /**
9
+ * Map host / npm-create argv onto the product CLI (`create webapi` / `add api`).
10
+ * `npm create @decohere webapi` already says “create”, so we prepend `create`
11
+ * rather than making users type `create create webapi`.
12
+ */
13
+ export declare function toProductArgv(tokens: string[]): string[];
14
+ export declare function containerArgvFromHost(argv: string[]): string[];
15
+ /**
16
+ * Host argv → directory to mount and argv for the in-image `decohere` entrypoint.
17
+ * Positional `webapi my-app` / `create webapi my-app` wins over `-d` (npm treats `-d`
18
+ * as its own loglevel).
19
+ */
20
+ export declare function resolveLaunch(argv: string[], cwd?: string): LaunchPlan;
@@ -1,13 +1,5 @@
1
1
  /**
2
- * Run the scaffold inside a pre-built Docker builder image.
3
- *
4
- * Called when `DECOHERE_BUILDER` is not set — i.e. the CLI is running on the
5
- * host, outside the container. Mounts the target directory as `/workspace` so
6
- * the scaffolded files are written back to the host filesystem.
7
- *
8
- * If `~/.config/auth0` exists on the host the directory is also mounted so
9
- * the auth0 CLI inside the container can reuse existing credentials silently.
2
+ * Pull/run the Decohere scaffolder image. Host `@decohere/create` does not load
3
+ * the `@decohere/scaffold` dependency tree — that lives in the image only.
10
4
  */
11
- export declare function runInBuilder(opts: {
12
- d?: string;
13
- }): never;
5
+ export declare function runInBuilder(argv: string[]): never;
@@ -1,2 +1,2 @@
1
- /** Version of @decohere/create, used to pin scaffolded @decohere/* dependencies. */
2
1
  export declare const CREATE_VERSION: string;
2
+ export declare const CREATE_IMAGE_REPOSITORY: string;
@@ -1,40 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- const _commander = require("commander");
7
- const _runner = require("./runner.js");
8
- const _createapi = require("./webapi/create-api.js");
9
- const program = new _commander.Command();
10
- program.name("decohere").description("Scaffold a new Decohere project").option("-d <directory>", "Target directory (default: current directory)", ".");
11
- program.command("webapi").action(async (_name, cmd)=>{
12
- const opts = cmd.optsWithGlobals();
13
- if (process.env.DECOHERE_BUILDER !== "1") {
14
- (0, _runner.runInBuilder)(opts);
15
- return;
16
- }
17
- await (0, _createapi.scaffoldApi)(opts);
18
- });
19
- // .option("-y, --yes", "Skip confirmation prompts")
20
- // .option("-t, --template <template>", "Project template: api (default) or cli")
21
- // .option("-d, --database <provider>", "Database provider to include (api only): typeorm")
22
- // .option("-i, --idp <provider>", "Identity provider to configure (api only): auth0")
23
- // .option("-p, --postman", "Configure a Postman workspace, collection, and environment")
24
- // .action(
25
- // async (
26
- // directory: string,
27
- // opts: {
28
- // yes?: boolean;
29
- // template?: "api" | "cli";
30
- // database?: "typeorm";
31
- // idp?: "auth0";
32
- // postman?: boolean;
33
- // },
34
- // ) => {
35
- // await scaffold(resolve(directory), opts);
36
- // },
37
- // );
38
- program.parse();
39
-
40
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NyZWF0ZS9zcmMvY2xpLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIiMhL3Vzci9iaW4vZW52IG5vZGVcbmltcG9ydCB7IENvbW1hbmQgfSBmcm9tIFwiY29tbWFuZGVyXCI7XG5pbXBvcnQgeyBydW5JbkJ1aWxkZXIgfSBmcm9tIFwiLi9ydW5uZXIuanNcIjtcbmltcG9ydCB7IHNjYWZmb2xkQXBpIH0gZnJvbSBcIi4vd2ViYXBpL2NyZWF0ZS1hcGkuanNcIjtcblxuY29uc3QgcHJvZ3JhbSA9IG5ldyBDb21tYW5kKCk7XG5cbnByb2dyYW1cblx0Lm5hbWUoXCJkZWNvaGVyZVwiKVxuXHQuZGVzY3JpcHRpb24oXCJTY2FmZm9sZCBhIG5ldyBEZWNvaGVyZSBwcm9qZWN0XCIpXG5cdC5vcHRpb24oXCItZCA8ZGlyZWN0b3J5PlwiLCBcIlRhcmdldCBkaXJlY3RvcnkgKGRlZmF1bHQ6IGN1cnJlbnQgZGlyZWN0b3J5KVwiLCBcIi5cIik7XG5cbnByb2dyYW0uY29tbWFuZChcIndlYmFwaVwiKS5hY3Rpb24oYXN5bmMgKF9uYW1lLCBjbWQ6IENvbW1hbmQpID0+IHtcblx0Y29uc3Qgb3B0cyA9IGNtZC5vcHRzV2l0aEdsb2JhbHMoKTtcblx0aWYgKHByb2Nlc3MuZW52LkRFQ09IRVJFX0JVSUxERVIgIT09IFwiMVwiKSB7XG5cdFx0cnVuSW5CdWlsZGVyKG9wdHMpO1xuXHRcdHJldHVybjtcblx0fVxuXHRhd2FpdCBzY2FmZm9sZEFwaShvcHRzKTtcbn0pO1xuXG4vLyAub3B0aW9uKFwiLXksIC0teWVzXCIsIFwiU2tpcCBjb25maXJtYXRpb24gcHJvbXB0c1wiKVxuLy8gLm9wdGlvbihcIi10LCAtLXRlbXBsYXRlIDx0ZW1wbGF0ZT5cIiwgXCJQcm9qZWN0IHRlbXBsYXRlOiBhcGkgKGRlZmF1bHQpIG9yIGNsaVwiKVxuLy8gLm9wdGlvbihcIi1kLCAtLWRhdGFiYXNlIDxwcm92aWRlcj5cIiwgXCJEYXRhYmFzZSBwcm92aWRlciB0byBpbmNsdWRlIChhcGkgb25seSk6IHR5cGVvcm1cIilcbi8vIC5vcHRpb24oXCItaSwgLS1pZHAgPHByb3ZpZGVyPlwiLCBcIklkZW50aXR5IHByb3ZpZGVyIHRvIGNvbmZpZ3VyZSAoYXBpIG9ubHkpOiBhdXRoMFwiKVxuLy8gLm9wdGlvbihcIi1wLCAtLXBvc3RtYW5cIiwgXCJDb25maWd1cmUgYSBQb3N0bWFuIHdvcmtzcGFjZSwgY29sbGVjdGlvbiwgYW5kIGVudmlyb25tZW50XCIpXG4vLyAuYWN0aW9uKFxuLy8gXHRhc3luYyAoXG4vLyBcdFx0ZGlyZWN0b3J5OiBzdHJpbmcsXG4vLyBcdFx0b3B0czoge1xuLy8gXHRcdFx0eWVzPzogYm9vbGVhbjtcbi8vIFx0XHRcdHRlbXBsYXRlPzogXCJhcGlcIiB8IFwiY2xpXCI7XG4vLyBcdFx0XHRkYXRhYmFzZT86IFwidHlwZW9ybVwiO1xuLy8gXHRcdFx0aWRwPzogXCJhdXRoMFwiO1xuLy8gXHRcdFx0cG9zdG1hbj86IGJvb2xlYW47XG4vLyBcdFx0fSxcbi8vIFx0KSA9PiB7XG4vLyBcdFx0YXdhaXQgc2NhZmZvbGQocmVzb2x2ZShkaXJlY3RvcnkpLCBvcHRzKTtcbi8vIFx0fSxcbi8vICk7XG5cbnByb2dyYW0ucGFyc2UoKTtcbiJdLCJuYW1lcyI6WyJwcm9ncmFtIiwiQ29tbWFuZCIsIm5hbWUiLCJkZXNjcmlwdGlvbiIsIm9wdGlvbiIsImNvbW1hbmQiLCJhY3Rpb24iLCJfbmFtZSIsImNtZCIsIm9wdHMiLCJvcHRzV2l0aEdsb2JhbHMiLCJwcm9jZXNzIiwiZW52IiwiREVDT0hFUkVfQlVJTERFUiIsInJ1bkluQnVpbGRlciIsInNjYWZmb2xkQXBpIiwicGFyc2UiXSwibWFwcGluZ3MiOiI7Ozs7OzJCQUN3Qjt3QkFDSzsyQkFDRDtBQUU1QixNQUFNQSxVQUFVLElBQUlDLGtCQUFPO0FBRTNCRCxRQUNFRSxJQUFJLENBQUMsWUFDTEMsV0FBVyxDQUFDLG1DQUNaQyxNQUFNLENBQUMsa0JBQWtCLGlEQUFpRDtBQUU1RUosUUFBUUssT0FBTyxDQUFDLFVBQVVDLE1BQU0sQ0FBQyxPQUFPQyxPQUFPQztJQUM5QyxNQUFNQyxPQUFPRCxJQUFJRSxlQUFlO0lBQ2hDLElBQUlDLFFBQVFDLEdBQUcsQ0FBQ0MsZ0JBQWdCLEtBQUssS0FBSztRQUN6Q0MsSUFBQUEsb0JBQVksRUFBQ0w7UUFDYjtJQUNEO0lBQ0EsTUFBTU0sSUFBQUEsc0JBQVcsRUFBQ047QUFDbkI7QUFFQSxvREFBb0Q7QUFDcEQsaUZBQWlGO0FBQ2pGLDJGQUEyRjtBQUMzRixzRkFBc0Y7QUFDdEYseUZBQXlGO0FBQ3pGLFdBQVc7QUFDWCxXQUFXO0FBQ1gsdUJBQXVCO0FBQ3ZCLFlBQVk7QUFDWixvQkFBb0I7QUFDcEIsK0JBQStCO0FBQy9CLDJCQUEyQjtBQUMzQixvQkFBb0I7QUFDcEIsd0JBQXdCO0FBQ3hCLE9BQU87QUFDUCxVQUFVO0FBQ1YsOENBQThDO0FBQzlDLE1BQU07QUFDTixLQUFLO0FBRUxULFFBQVFnQixLQUFLIn0=
@@ -1,55 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- function _export(target, all) {
6
- for(var name in all)Object.defineProperty(target, name, {
7
- enumerable: true,
8
- get: Object.getOwnPropertyDescriptor(all, name).get
9
- });
10
- }
11
- _export(exports, {
12
- get ask () {
13
- return ask;
14
- },
15
- get pick () {
16
- return pick;
17
- }
18
- });
19
- const _nodereadline = require("node:readline");
20
- // readline/promises rl.question() has a race condition with piped (non-TTY) stdin
21
- // in Node ≥ 22: after the first line is read, stdin emits 'end', readline closes,
22
- // and all subsequent question() calls resolve to "".
23
- // Fix: use the async-iterator API, which buffers all lines before the close event fires.
24
- let _lines = null;
25
- function getLines() {
26
- if (_lines == null) {
27
- const rl = (0, _nodereadline.createInterface)({
28
- input: process.stdin,
29
- terminal: false
30
- });
31
- _lines = rl[Symbol.asyncIterator]();
32
- }
33
- return _lines;
34
- }
35
- async function readLine(prompt) {
36
- process.stdout.write(prompt);
37
- const { value, done } = await getLines().next();
38
- return done ? "" : value.trim();
39
- }
40
- async function ask(question, fallback = "") {
41
- const answer = await readLine(question);
42
- return answer || fallback;
43
- }
44
- async function pick(label, items, display) {
45
- console.log(label.trimEnd());
46
- for (const [i, item] of items.entries()){
47
- console.log(` ${i + 1}. ${display(item)}`);
48
- }
49
- const answer = await readLine(" > ");
50
- const idx = Number.parseInt(answer, 10);
51
- if (Number.isNaN(idx) || idx < 1 || idx > items.length) return null;
52
- return items[idx - 1];
53
- }
54
-
55
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NyZWF0ZS9zcmMvZG9tYWluL3Byb21wdC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBjcmVhdGVJbnRlcmZhY2UgfSBmcm9tIFwibm9kZTpyZWFkbGluZVwiO1xuXG4vLyByZWFkbGluZS9wcm9taXNlcyBybC5xdWVzdGlvbigpIGhhcyBhIHJhY2UgY29uZGl0aW9uIHdpdGggcGlwZWQgKG5vbi1UVFkpIHN0ZGluXG4vLyBpbiBOb2RlIOKJpSAyMjogYWZ0ZXIgdGhlIGZpcnN0IGxpbmUgaXMgcmVhZCwgc3RkaW4gZW1pdHMgJ2VuZCcsIHJlYWRsaW5lIGNsb3Nlcyxcbi8vIGFuZCBhbGwgc3Vic2VxdWVudCBxdWVzdGlvbigpIGNhbGxzIHJlc29sdmUgdG8gXCJcIi5cbi8vIEZpeDogdXNlIHRoZSBhc3luYy1pdGVyYXRvciBBUEksIHdoaWNoIGJ1ZmZlcnMgYWxsIGxpbmVzIGJlZm9yZSB0aGUgY2xvc2UgZXZlbnQgZmlyZXMuXG5cbmxldCBfbGluZXM6IEFzeW5jSXRlcmF0b3I8c3RyaW5nPiB8IG51bGwgPSBudWxsO1xuXG5mdW5jdGlvbiBnZXRMaW5lcygpOiBBc3luY0l0ZXJhdG9yPHN0cmluZz4ge1xuXHRpZiAoX2xpbmVzID09IG51bGwpIHtcblx0XHRjb25zdCBybCA9IGNyZWF0ZUludGVyZmFjZSh7IGlucHV0OiBwcm9jZXNzLnN0ZGluLCB0ZXJtaW5hbDogZmFsc2UgfSk7XG5cdFx0X2xpbmVzID0gcmxbU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCk7XG5cdH1cblx0cmV0dXJuIF9saW5lcztcbn1cblxuYXN5bmMgZnVuY3Rpb24gcmVhZExpbmUocHJvbXB0OiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuXHRwcm9jZXNzLnN0ZG91dC53cml0ZShwcm9tcHQpO1xuXHRjb25zdCB7IHZhbHVlLCBkb25lIH0gPSBhd2FpdCBnZXRMaW5lcygpLm5leHQoKTtcblx0cmV0dXJuIGRvbmUgPyBcIlwiIDogdmFsdWUudHJpbSgpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gYXNrKHF1ZXN0aW9uOiBzdHJpbmcsIGZhbGxiYWNrID0gXCJcIik6IFByb21pc2U8c3RyaW5nPiB7XG5cdGNvbnN0IGFuc3dlciA9IGF3YWl0IHJlYWRMaW5lKHF1ZXN0aW9uKTtcblx0cmV0dXJuIGFuc3dlciB8fCBmYWxsYmFjaztcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHBpY2s8VD4oXG5cdGxhYmVsOiBzdHJpbmcsXG5cdGl0ZW1zOiBUW10sXG5cdGRpc3BsYXk6IChpdGVtOiBUKSA9PiBzdHJpbmcsXG4pOiBQcm9taXNlPFQgfCBudWxsPiB7XG5cdGNvbnNvbGUubG9nKGxhYmVsLnRyaW1FbmQoKSk7XG5cdGZvciAoY29uc3QgW2ksIGl0ZW1dIG9mIGl0ZW1zLmVudHJpZXMoKSkge1xuXHRcdGNvbnNvbGUubG9nKGAgICAgJHtpICsgMX0uICR7ZGlzcGxheShpdGVtKX1gKTtcblx0fVxuXHRjb25zdCBhbnN3ZXIgPSBhd2FpdCByZWFkTGluZShcIiAgPiBcIik7XG5cdGNvbnN0IGlkeCA9IE51bWJlci5wYXJzZUludChhbnN3ZXIsIDEwKTtcblx0aWYgKE51bWJlci5pc05hTihpZHgpIHx8IGlkeCA8IDEgfHwgaWR4ID4gaXRlbXMubGVuZ3RoKSByZXR1cm4gbnVsbDtcblx0cmV0dXJuIGl0ZW1zW2lkeCAtIDFdO1xufVxuIl0sIm5hbWVzIjpbImFzayIsInBpY2siLCJfbGluZXMiLCJnZXRMaW5lcyIsInJsIiwiY3JlYXRlSW50ZXJmYWNlIiwiaW5wdXQiLCJwcm9jZXNzIiwic3RkaW4iLCJ0ZXJtaW5hbCIsIlN5bWJvbCIsImFzeW5jSXRlcmF0b3IiLCJyZWFkTGluZSIsInByb21wdCIsInN0ZG91dCIsIndyaXRlIiwidmFsdWUiLCJkb25lIiwibmV4dCIsInRyaW0iLCJxdWVzdGlvbiIsImZhbGxiYWNrIiwiYW5zd2VyIiwibGFiZWwiLCJpdGVtcyIsImRpc3BsYXkiLCJjb25zb2xlIiwibG9nIiwidHJpbUVuZCIsImkiLCJpdGVtIiwiZW50cmllcyIsImlkeCIsIk51bWJlciIsInBhcnNlSW50IiwiaXNOYU4iLCJsZW5ndGgiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7O1FBdUJzQkE7ZUFBQUE7O1FBS0FDO2VBQUFBOzs7OEJBNUJVO0FBRWhDLGtGQUFrRjtBQUNsRixrRkFBa0Y7QUFDbEYscURBQXFEO0FBQ3JELHlGQUF5RjtBQUV6RixJQUFJQyxTQUF1QztBQUUzQyxTQUFTQztJQUNSLElBQUlELFVBQVUsTUFBTTtRQUNuQixNQUFNRSxLQUFLQyxJQUFBQSw2QkFBZSxFQUFDO1lBQUVDLE9BQU9DLFFBQVFDLEtBQUs7WUFBRUMsVUFBVTtRQUFNO1FBQ25FUCxTQUFTRSxFQUFFLENBQUNNLE9BQU9DLGFBQWEsQ0FBQztJQUNsQztJQUNBLE9BQU9UO0FBQ1I7QUFFQSxlQUFlVSxTQUFTQyxNQUFjO0lBQ3JDTixRQUFRTyxNQUFNLENBQUNDLEtBQUssQ0FBQ0Y7SUFDckIsTUFBTSxFQUFFRyxLQUFLLEVBQUVDLElBQUksRUFBRSxHQUFHLE1BQU1kLFdBQVdlLElBQUk7SUFDN0MsT0FBT0QsT0FBTyxLQUFLRCxNQUFNRyxJQUFJO0FBQzlCO0FBRU8sZUFBZW5CLElBQUlvQixRQUFnQixFQUFFQyxXQUFXLEVBQUU7SUFDeEQsTUFBTUMsU0FBUyxNQUFNVixTQUFTUTtJQUM5QixPQUFPRSxVQUFVRDtBQUNsQjtBQUVPLGVBQWVwQixLQUNyQnNCLEtBQWEsRUFDYkMsS0FBVSxFQUNWQyxPQUE0QjtJQUU1QkMsUUFBUUMsR0FBRyxDQUFDSixNQUFNSyxPQUFPO0lBQ3pCLEtBQUssTUFBTSxDQUFDQyxHQUFHQyxLQUFLLElBQUlOLE1BQU1PLE9BQU8sR0FBSTtRQUN4Q0wsUUFBUUMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFRSxJQUFJLEVBQUUsRUFBRSxFQUFFSixRQUFRSyxPQUFPO0lBQzdDO0lBQ0EsTUFBTVIsU0FBUyxNQUFNVixTQUFTO0lBQzlCLE1BQU1vQixNQUFNQyxPQUFPQyxRQUFRLENBQUNaLFFBQVE7SUFDcEMsSUFBSVcsT0FBT0UsS0FBSyxDQUFDSCxRQUFRQSxNQUFNLEtBQUtBLE1BQU1SLE1BQU1ZLE1BQU0sRUFBRSxPQUFPO0lBQy9ELE9BQU9aLEtBQUssQ0FBQ1EsTUFBTSxFQUFFO0FBQ3RCIn0=
@@ -1,82 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- Object.defineProperty(exports, "DockerCompose", {
6
- enumerable: true,
7
- get: function() {
8
- return DockerCompose;
9
- }
10
- });
11
- const _const = require("./const.js");
12
- class DockerCompose {
13
- key = _const.WELL_KNOWN_FILES.DOCKER_COMPOSE;
14
- _services = new Map();
15
- _volumes = new Set();
16
- addService(name, config) {
17
- this._services.set(name, config);
18
- return this;
19
- }
20
- files() {
21
- return [
22
- {
23
- filePath: ".devcontainer/docker-compose.yml",
24
- content: this.getContent()
25
- }
26
- ];
27
- }
28
- addVolume(name) {
29
- this._volumes.add(name);
30
- return this;
31
- }
32
- /** Append an env_file path to an existing service. */ addEnvFile(serviceName, filePath) {
33
- const svc = this._services.get(serviceName);
34
- if (svc) svc.env_file = [
35
- ...svc.env_file ?? [],
36
- filePath
37
- ];
38
- return this;
39
- }
40
- getContent() {
41
- const lines = [
42
- "services:"
43
- ];
44
- for (const [name, svc] of this._services){
45
- lines.push(` ${name}:`);
46
- if (svc.build) lines.push(` build: ${svc.build}`);
47
- if (svc.image) lines.push(` image: ${svc.image}`);
48
- if (svc.command) lines.push(` command: ${svc.command}`);
49
- if (svc.restart) lines.push(` restart: ${svc.restart}`);
50
- if (svc.env_file && svc.env_file.length > 0) {
51
- lines.push(" env_file:");
52
- for (const f of svc.env_file)lines.push(` - ${f}`);
53
- }
54
- if (svc.environment && Object.keys(svc.environment).length > 0) {
55
- lines.push(" environment:");
56
- for (const [k, v] of Object.entries(svc.environment)){
57
- lines.push(` ${k}: ${v}`);
58
- }
59
- }
60
- if (svc.ports && svc.ports.length > 0) {
61
- lines.push(" ports:");
62
- for (const p of svc.ports)lines.push(` - "${p}"`);
63
- }
64
- if (svc.volumes && svc.volumes.length > 0) {
65
- lines.push(" volumes:");
66
- for (const v of svc.volumes)lines.push(` - ${v}`);
67
- }
68
- if (svc.depends_on && svc.depends_on.length > 0) {
69
- lines.push(" depends_on:");
70
- for (const d of svc.depends_on)lines.push(` - ${d}`);
71
- }
72
- }
73
- if (this._volumes.size > 0) {
74
- lines.push("");
75
- lines.push("volumes:");
76
- for (const v of this._volumes)lines.push(` ${v}:`);
77
- }
78
- return `${lines.join("\n")}\n`;
79
- }
80
- }
81
-
82
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NyZWF0ZS9zcmMvbW9kZWxzL2NvbXBvc2UubW9kZWwudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgV0VMTF9LTk9XTl9GSUxFUyB9IGZyb20gXCIuL2NvbnN0LmpzXCI7XG5pbXBvcnQgdHlwZSB7IEtleWVkTW9kZWwgfSBmcm9tIFwiLi9zb3VyY2UtZmlsZS5qc1wiO1xuXG5leHBvcnQgaW50ZXJmYWNlIENvbXBvc2VTZXJ2aWNlIHtcblx0YnVpbGQ/OiBzdHJpbmc7XG5cdGltYWdlPzogc3RyaW5nO1xuXHRlbnZfZmlsZT86IHN0cmluZ1tdO1xuXHRlbnZpcm9ubWVudD86IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG5cdHBvcnRzPzogc3RyaW5nW107XG5cdHZvbHVtZXM/OiBzdHJpbmdbXTtcblx0Y29tbWFuZD86IHN0cmluZztcblx0cmVzdGFydD86IHN0cmluZztcblx0ZGVwZW5kc19vbj86IHN0cmluZ1tdO1xufVxuXG4vKipcbiAqIExpdmUgYnVpbGRlciBmb3IgYGRvY2tlci1jb21wb3NlLnltbGAuXG4gKlxuICogRmVhdHVyZXMgY2FsbCBgYWRkU2VydmljZWAgLyBgYWRkVm9sdW1lYCBpbiB0aGVpciBgY29uZmlndXJlYCBwaGFzZXMuXG4gKiBUaGUgZGV2Y29udGFpbmVyIGByZW5kZXJgIHBoYXNlIGNhbGxzIGByZW5kZXIoKWAgYW5kIHdyaXRlcyB0aGUgZmlsZS5cbiAqL1xuZXhwb3J0IGNsYXNzIERvY2tlckNvbXBvc2UgaW1wbGVtZW50cyBLZXllZE1vZGVsIHtcblx0cHVibGljIHJlYWRvbmx5IGtleSA9IFdFTExfS05PV05fRklMRVMuRE9DS0VSX0NPTVBPU0U7XG5cdHByaXZhdGUgcmVhZG9ubHkgX3NlcnZpY2VzOiBNYXA8c3RyaW5nLCBDb21wb3NlU2VydmljZT4gPSBuZXcgTWFwKCk7XG5cdHByaXZhdGUgcmVhZG9ubHkgX3ZvbHVtZXM6IFNldDxzdHJpbmc+ID0gbmV3IFNldCgpO1xuXG5cdHB1YmxpYyBhZGRTZXJ2aWNlKG5hbWU6IHN0cmluZywgY29uZmlnOiBDb21wb3NlU2VydmljZSk6IHRoaXMge1xuXHRcdHRoaXMuX3NlcnZpY2VzLnNldChuYW1lLCBjb25maWcpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0cHVibGljIGZpbGVzKCkge1xuXHRcdHJldHVybiBbXG5cdFx0XHR7XG5cdFx0XHRcdGZpbGVQYXRoOiBcIi5kZXZjb250YWluZXIvZG9ja2VyLWNvbXBvc2UueW1sXCIsXG5cdFx0XHRcdGNvbnRlbnQ6IHRoaXMuZ2V0Q29udGVudCgpLFxuXHRcdFx0fSxcblx0XHRdO1xuXHR9XG5cblx0cHVibGljIGFkZFZvbHVtZShuYW1lOiBzdHJpbmcpOiB0aGlzIHtcblx0XHR0aGlzLl92b2x1bWVzLmFkZChuYW1lKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKiBBcHBlbmQgYW4gZW52X2ZpbGUgcGF0aCB0byBhbiBleGlzdGluZyBzZXJ2aWNlLiAqL1xuXHRwdWJsaWMgYWRkRW52RmlsZShzZXJ2aWNlTmFtZTogc3RyaW5nLCBmaWxlUGF0aDogc3RyaW5nKTogdGhpcyB7XG5cdFx0Y29uc3Qgc3ZjID0gdGhpcy5fc2VydmljZXMuZ2V0KHNlcnZpY2VOYW1lKTtcblx0XHRpZiAoc3ZjKSBzdmMuZW52X2ZpbGUgPSBbLi4uKHN2Yy5lbnZfZmlsZSA/PyBbXSksIGZpbGVQYXRoXTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdHB1YmxpYyBnZXRDb250ZW50KCk6IHN0cmluZyB7XG5cdFx0Y29uc3QgbGluZXM6IHN0cmluZ1tdID0gW1wic2VydmljZXM6XCJdO1xuXG5cdFx0Zm9yIChjb25zdCBbbmFtZSwgc3ZjXSBvZiB0aGlzLl9zZXJ2aWNlcykge1xuXHRcdFx0bGluZXMucHVzaChgICAke25hbWV9OmApO1xuXHRcdFx0aWYgKHN2Yy5idWlsZCkgbGluZXMucHVzaChgICAgIGJ1aWxkOiAke3N2Yy5idWlsZH1gKTtcblx0XHRcdGlmIChzdmMuaW1hZ2UpIGxpbmVzLnB1c2goYCAgICBpbWFnZTogJHtzdmMuaW1hZ2V9YCk7XG5cdFx0XHRpZiAoc3ZjLmNvbW1hbmQpIGxpbmVzLnB1c2goYCAgICBjb21tYW5kOiAke3N2Yy5jb21tYW5kfWApO1xuXHRcdFx0aWYgKHN2Yy5yZXN0YXJ0KSBsaW5lcy5wdXNoKGAgICAgcmVzdGFydDogJHtzdmMucmVzdGFydH1gKTtcblxuXHRcdFx0aWYgKHN2Yy5lbnZfZmlsZSAmJiBzdmMuZW52X2ZpbGUubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRsaW5lcy5wdXNoKFwiICAgIGVudl9maWxlOlwiKTtcblx0XHRcdFx0Zm9yIChjb25zdCBmIG9mIHN2Yy5lbnZfZmlsZSkgbGluZXMucHVzaChgICAgICAgLSAke2Z9YCk7XG5cdFx0XHR9XG5cblx0XHRcdGlmIChzdmMuZW52aXJvbm1lbnQgJiYgT2JqZWN0LmtleXMoc3ZjLmVudmlyb25tZW50KS5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdGxpbmVzLnB1c2goXCIgICAgZW52aXJvbm1lbnQ6XCIpO1xuXHRcdFx0XHRmb3IgKGNvbnN0IFtrLCB2XSBvZiBPYmplY3QuZW50cmllcyhzdmMuZW52aXJvbm1lbnQpKSB7XG5cdFx0XHRcdFx0bGluZXMucHVzaChgICAgICAgJHtrfTogJHt2fWApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGlmIChzdmMucG9ydHMgJiYgc3ZjLnBvcnRzLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0bGluZXMucHVzaChcIiAgICBwb3J0czpcIik7XG5cdFx0XHRcdGZvciAoY29uc3QgcCBvZiBzdmMucG9ydHMpIGxpbmVzLnB1c2goYCAgICAgIC0gXCIke3B9XCJgKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKHN2Yy52b2x1bWVzICYmIHN2Yy52b2x1bWVzLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0bGluZXMucHVzaChcIiAgICB2b2x1bWVzOlwiKTtcblx0XHRcdFx0Zm9yIChjb25zdCB2IG9mIHN2Yy52b2x1bWVzKSBsaW5lcy5wdXNoKGAgICAgICAtICR7dn1gKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKHN2Yy5kZXBlbmRzX29uICYmIHN2Yy5kZXBlbmRzX29uLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0bGluZXMucHVzaChcIiAgICBkZXBlbmRzX29uOlwiKTtcblx0XHRcdFx0Zm9yIChjb25zdCBkIG9mIHN2Yy5kZXBlbmRzX29uKSBsaW5lcy5wdXNoKGAgICAgICAtICR7ZH1gKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAodGhpcy5fdm9sdW1lcy5zaXplID4gMCkge1xuXHRcdFx0bGluZXMucHVzaChcIlwiKTtcblx0XHRcdGxpbmVzLnB1c2goXCJ2b2x1bWVzOlwiKTtcblx0XHRcdGZvciAoY29uc3QgdiBvZiB0aGlzLl92b2x1bWVzKSBsaW5lcy5wdXNoKGAgICR7dn06YCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGAke2xpbmVzLmpvaW4oXCJcXG5cIil9XFxuYDtcblx0fVxufVxuIl0sIm5hbWVzIjpbIkRvY2tlckNvbXBvc2UiLCJrZXkiLCJXRUxMX0tOT1dOX0ZJTEVTIiwiRE9DS0VSX0NPTVBPU0UiLCJfc2VydmljZXMiLCJNYXAiLCJfdm9sdW1lcyIsIlNldCIsImFkZFNlcnZpY2UiLCJuYW1lIiwiY29uZmlnIiwic2V0IiwiZmlsZXMiLCJmaWxlUGF0aCIsImNvbnRlbnQiLCJnZXRDb250ZW50IiwiYWRkVm9sdW1lIiwiYWRkIiwiYWRkRW52RmlsZSIsInNlcnZpY2VOYW1lIiwic3ZjIiwiZ2V0IiwiZW52X2ZpbGUiLCJsaW5lcyIsInB1c2giLCJidWlsZCIsImltYWdlIiwiY29tbWFuZCIsInJlc3RhcnQiLCJsZW5ndGgiLCJmIiwiZW52aXJvbm1lbnQiLCJPYmplY3QiLCJrZXlzIiwiayIsInYiLCJlbnRyaWVzIiwicG9ydHMiLCJwIiwidm9sdW1lcyIsImRlcGVuZHNfb24iLCJkIiwic2l6ZSIsImpvaW4iXSwibWFwcGluZ3MiOiI7Ozs7K0JBcUJhQTs7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
@@ -1,34 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- Object.defineProperty(exports, "ConfigYaml", {
6
- enumerable: true,
7
- get: function() {
8
- return ConfigYaml;
9
- }
10
- });
11
- class ConfigYaml {
12
- key;
13
- filePath;
14
- _sections = [];
15
- constructor(key, filePath, baseContent){
16
- this.key = key;
17
- this.filePath = filePath;
18
- this._sections.push(baseContent);
19
- }
20
- addSection(yaml) {
21
- this._sections.push(yaml);
22
- return this;
23
- }
24
- files() {
25
- return [
26
- {
27
- filePath: this.filePath,
28
- content: this._sections.join("\n")
29
- }
30
- ];
31
- }
32
- }
33
-
34
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NyZWF0ZS9zcmMvbW9kZWxzL2NvbmZpZy15YW1sLm1vZGVsLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgS2V5ZWRNb2RlbCwgU291cmNlRmlsZSB9IGZyb20gXCIuL3NvdXJjZS1maWxlLmpzXCI7XG5cbi8qKlxuICogQnVpbGRlciBmb3IgYSBZQU1MIGNvbmZpZyBmaWxlIChlLmcuIGNvbmZpZy9jb25maWcueWFtbCBvciBjb25maWcvY29uZmlnLmRldi55YW1sKS5cbiAqXG4gKiBTdGFydHMgd2l0aCBhIGJhc2Ugc2VjdGlvbiBwYXNzZWQgdG8gdGhlIGNvbnN0cnVjdG9yLiBGZWF0dXJlcyBjYWxsXG4gKiBgYWRkU2VjdGlvbih5YW1sKWAgZHVyaW5nIHRoZWlyIHNjYWZmb2xkIHBoYXNlIHRvIGFwcGVuZCB0aGVpciBvd24gYmxvY2suXG4gKiBgZmlsZXMoKWAgam9pbnMgYWxsIHNlY3Rpb25zIHdpdGggYSBibGFuayBsaW5lIHNlcGFyYXRvci5cbiAqL1xuZXhwb3J0IGNsYXNzIENvbmZpZ1lhbWwgaW1wbGVtZW50cyBLZXllZE1vZGVsIHtcblx0cHJpdmF0ZSByZWFkb25seSBfc2VjdGlvbnM6IHN0cmluZ1tdID0gW107XG5cblx0cHVibGljIGNvbnN0cnVjdG9yKFxuXHRcdHB1YmxpYyByZWFkb25seSBrZXk6IHN0cmluZyxcblx0XHRwcml2YXRlIHJlYWRvbmx5IGZpbGVQYXRoOiBzdHJpbmcsXG5cdFx0YmFzZUNvbnRlbnQ6IHN0cmluZyxcblx0KSB7XG5cdFx0dGhpcy5fc2VjdGlvbnMucHVzaChiYXNlQ29udGVudCk7XG5cdH1cblxuXHRwdWJsaWMgYWRkU2VjdGlvbih5YW1sOiBzdHJpbmcpOiB0aGlzIHtcblx0XHR0aGlzLl9zZWN0aW9ucy5wdXNoKHlhbWwpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0cHVibGljIGZpbGVzKCk6IFNvdXJjZUZpbGVbXSB7XG5cdFx0cmV0dXJuIFt7IGZpbGVQYXRoOiB0aGlzLmZpbGVQYXRoLCBjb250ZW50OiB0aGlzLl9zZWN0aW9ucy5qb2luKFwiXFxuXCIpIH1dO1xuXHR9XG59XG4iXSwibmFtZXMiOlsiQ29uZmlnWWFtbCIsIl9zZWN0aW9ucyIsImtleSIsImZpbGVQYXRoIiwiYmFzZUNvbnRlbnQiLCJwdXNoIiwiYWRkU2VjdGlvbiIsInlhbWwiLCJmaWxlcyIsImNvbnRlbnQiLCJqb2luIl0sIm1hcHBpbmdzIjoiOzs7OytCQVNhQTs7O2VBQUFBOzs7QUFBTixNQUFNQTs7O0lBQ0tDLFlBQXNCLEVBQUUsQ0FBQztJQUUxQyxZQUNDLEFBQWdCQyxHQUFXLEVBQzNCLEFBQWlCQyxRQUFnQixFQUNqQ0MsV0FBbUIsQ0FDbEI7YUFIZUYsTUFBQUE7YUFDQ0MsV0FBQUE7UUFHakIsSUFBSSxDQUFDRixTQUFTLENBQUNJLElBQUksQ0FBQ0Q7SUFDckI7SUFFT0UsV0FBV0MsSUFBWSxFQUFRO1FBQ3JDLElBQUksQ0FBQ04sU0FBUyxDQUFDSSxJQUFJLENBQUNFO1FBQ3BCLE9BQU8sSUFBSTtJQUNaO0lBRU9DLFFBQXNCO1FBQzVCLE9BQU87WUFBQztnQkFBRUwsVUFBVSxJQUFJLENBQUNBLFFBQVE7Z0JBQUVNLFNBQVMsSUFBSSxDQUFDUixTQUFTLENBQUNTLElBQUksQ0FBQztZQUFNO1NBQUU7SUFDekU7QUFDRCJ9
@@ -1,29 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- Object.defineProperty(exports, "WELL_KNOWN_FILES", {
6
- enumerable: true,
7
- get: function() {
8
- return WELL_KNOWN_FILES;
9
- }
10
- });
11
- const WELL_KNOWN_FILES = {
12
- VSCODE_SETTINGS: "VSCODE_SETTINGS",
13
- LAUNCH_JSON: "LAUNCH_JSON",
14
- DOCKER_COMPOSE: "DOCKER_COMPOSE",
15
- DEVCONTAINER_JSON: "DEVCONTAINER_JSON",
16
- DOCKERFILE: "DOCKERFILE",
17
- PACKAGE_JSON: "PACKAGE_JSON",
18
- API_PACKAGE_JSON: "API_PACKAGE_JSON",
19
- TSCONFIG: "TSCONFIG",
20
- MAIN_TS: "MAIN_TS",
21
- CONTROLLER_TS: "CONTROLLER_TS",
22
- CONFIG_YAML: "CONFIG_YAML",
23
- CONFIG_DEV_YAML: "CONFIG_DEV_YAML",
24
- GITIGNORE: "GITIGNORE",
25
- AUTH_CONFIG: "AUTH_CONFIG",
26
- ENV_FILE: "ENV_FILE"
27
- };
28
-
29
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NyZWF0ZS9zcmMvbW9kZWxzL2NvbnN0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBjb25zdCBXRUxMX0tOT1dOX0ZJTEVTID0ge1xuXHRWU0NPREVfU0VUVElOR1M6IFwiVlNDT0RFX1NFVFRJTkdTXCIsXG5cdExBVU5DSF9KU09OOiBcIkxBVU5DSF9KU09OXCIsXG5cdERPQ0tFUl9DT01QT1NFOiBcIkRPQ0tFUl9DT01QT1NFXCIsXG5cdERFVkNPTlRBSU5FUl9KU09OOiBcIkRFVkNPTlRBSU5FUl9KU09OXCIsXG5cdERPQ0tFUkZJTEU6IFwiRE9DS0VSRklMRVwiLFxuXHRQQUNLQUdFX0pTT046IFwiUEFDS0FHRV9KU09OXCIsXG5cdEFQSV9QQUNLQUdFX0pTT046IFwiQVBJX1BBQ0tBR0VfSlNPTlwiLFxuXHRUU0NPTkZJRzogXCJUU0NPTkZJR1wiLFxuXHRNQUlOX1RTOiBcIk1BSU5fVFNcIixcblx0Q09OVFJPTExFUl9UUzogXCJDT05UUk9MTEVSX1RTXCIsXG5cdENPTkZJR19ZQU1MOiBcIkNPTkZJR19ZQU1MXCIsXG5cdENPTkZJR19ERVZfWUFNTDogXCJDT05GSUdfREVWX1lBTUxcIixcblx0R0lUSUdOT1JFOiBcIkdJVElHTk9SRVwiLFxuXHRBVVRIX0NPTkZJRzogXCJBVVRIX0NPTkZJR1wiLFxuXHRFTlZfRklMRTogXCJFTlZfRklMRVwiLFxufTtcbiJdLCJuYW1lcyI6WyJXRUxMX0tOT1dOX0ZJTEVTIiwiVlNDT0RFX1NFVFRJTkdTIiwiTEFVTkNIX0pTT04iLCJET0NLRVJfQ09NUE9TRSIsIkRFVkNPTlRBSU5FUl9KU09OIiwiRE9DS0VSRklMRSIsIlBBQ0tBR0VfSlNPTiIsIkFQSV9QQUNLQUdFX0pTT04iLCJUU0NPTkZJRyIsIk1BSU5fVFMiLCJDT05UUk9MTEVSX1RTIiwiQ09ORklHX1lBTUwiLCJDT05GSUdfREVWX1lBTUwiLCJHSVRJR05PUkUiLCJBVVRIX0NPTkZJRyIsIkVOVl9GSUxFIl0sIm1hcHBpbmdzIjoiOzs7OytCQUFhQTs7O2VBQUFBOzs7QUFBTixNQUFNQSxtQkFBbUI7SUFDL0JDLGlCQUFpQjtJQUNqQkMsYUFBYTtJQUNiQyxnQkFBZ0I7SUFDaEJDLG1CQUFtQjtJQUNuQkMsWUFBWTtJQUNaQyxjQUFjO0lBQ2RDLGtCQUFrQjtJQUNsQkMsVUFBVTtJQUNWQyxTQUFTO0lBQ1RDLGVBQWU7SUFDZkMsYUFBYTtJQUNiQyxpQkFBaUI7SUFDakJDLFdBQVc7SUFDWEMsYUFBYTtJQUNiQyxVQUFVO0FBQ1gifQ==
@@ -1,88 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- Object.defineProperty(exports, "DockerfileModel", {
6
- enumerable: true,
7
- get: function() {
8
- return DockerfileModel;
9
- }
10
- });
11
- const _const = require("./const.js");
12
- // Everything before the final USER instruction. Features insert RUN steps here.
13
- const DOCKERFILE_BASE = `FROM node:24
14
-
15
- ARG USERNAME=node
16
-
17
- # System tools: jq + ripgrep for scripting/search, python3 for AI tooling,
18
- # gh for GitHub workflows, curl/gnupg for package sources.
19
- RUN apt-get update \\
20
- && apt-get install -y --no-install-recommends ca-certificates curl gnupg jq ripgrep python3 \\
21
- && curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg -o /usr/share/keyrings/githubcli-archive-keyring.gpg \\
22
- && chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \\
23
- && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" > /etc/apt/sources.list.d/github-cli.list \\
24
- && apt-get update \\
25
- && apt-get install -y --no-install-recommends gh \\
26
- && rm -rf /var/lib/apt/lists/*
27
-
28
- RUN npm install --global npm@latest \\
29
- && npm add --global pnpm@10
30
-
31
- RUN mkdir -p /home/\${USERNAME}/.config/pnpm /home/\${USERNAME}/.pnpm-store \\
32
- && chown -R \${USERNAME}:\${USERNAME} /home/\${USERNAME}/.config /home/\${USERNAME}/.pnpm-store \\
33
- && printf "store-dir=/home/\${USERNAME}/.pnpm-store\\n" > /home/\${USERNAME}/.config/pnpm/rc
34
-
35
- # Pre-create workspace node_modules so the named volume mount is owned by the user
36
- RUN mkdir -p /workspace/node_modules && chown \${USERNAME}:\${USERNAME} /workspace/node_modules
37
-
38
- RUN mkdir /commandhistory && touch /commandhistory/.bash_history \\
39
- && chown -R \${USERNAME} /commandhistory
40
-
41
- RUN SNIPPET="export PROMPT_COMMAND='history -a' && export HISTFILE=/commandhistory/.bash_history" \\
42
- && echo "$SNIPPET" >> "/home/\${USERNAME}/.bashrc"
43
-
44
- # VS Code js-debug bug: bootloader.js in workspaceStorage is only created when
45
- # the user manually toggles Auto Attach settings. On a fresh container it is
46
- # missing, which crashes every Node command. Fix: if the injected path is
47
- # missing, substitute the stable bootloader from the VS Code server extension
48
- # directory (always present once the server is installed).
49
- RUN cat <<'EOF' >> "/home/\${USERNAME}/.bashrc"
50
- if [[ -n "\${NODE_OPTIONS:-}" && "\${NODE_OPTIONS}" == *"bootloader.js"* ]]; then
51
- _bootloader_path="$(printf '%s\\n' "$NODE_OPTIONS" | sed -n 's/.*--require[= ]\\([^[:space:]]*bootloader\\.js\\).*/\\1/p')"
52
- if [[ -n "\${_bootloader_path}" && ! -f "\${_bootloader_path}" ]]; then
53
- _stable_bootloader="$(find /vscode/vscode-server /home/node/.vscode-server/extensions -name "bootloader.js" -path "*/ms-vscode.js-debug/*" 2>/dev/null | head -1)"
54
- if [[ -n "\${_stable_bootloader}" ]]; then
55
- NODE_OPTIONS="\${NODE_OPTIONS//\${_bootloader_path}/\${_stable_bootloader}}"
56
- else
57
- NODE_OPTIONS="$(printf '%s\\n' "$NODE_OPTIONS" | sed -E 's#(^| )--require(=| )[[:graph:]]*bootloader\\.js( |$)# #g; s# +# #g; s#^ ##; s# $##')"
58
- unset VSCODE_INSPECTOR_OPTIONS
59
- fi
60
- export NODE_OPTIONS
61
- if [[ -z "$NODE_OPTIONS" ]]; then
62
- unset NODE_OPTIONS
63
- fi
64
- fi
65
- unset _bootloader_path _stable_bootloader
66
- fi
67
- EOF
68
- `;
69
- const DOCKERFILE_USER = `\nUSER \${USERNAME}\n`;
70
- class DockerfileModel {
71
- key = _const.WELL_KNOWN_FILES.DOCKERFILE;
72
- _runSteps = [];
73
- /** Append a RUN instruction (pass the command, not the RUN keyword). */ addRunStep(cmd) {
74
- this._runSteps.push(cmd);
75
- return this;
76
- }
77
- files() {
78
- const extras = this._runSteps.length > 0 ? `\n${this._runSteps.map((s)=>`RUN ${s}`).join("\n\n")}\n` : "";
79
- return [
80
- {
81
- filePath: ".devcontainer/Dockerfile",
82
- content: DOCKERFILE_BASE + extras + DOCKERFILE_USER
83
- }
84
- ];
85
- }
86
- }
87
-
88
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NyZWF0ZS9zcmMvbW9kZWxzL2NvbnRhaW5lci1pbWFnZS5tb2RlbC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBXRUxMX0tOT1dOX0ZJTEVTIH0gZnJvbSBcIi4vY29uc3QuanNcIjtcbmltcG9ydCB0eXBlIHsgS2V5ZWRNb2RlbCwgU291cmNlRmlsZSB9IGZyb20gXCIuL3NvdXJjZS1maWxlLmpzXCI7XG5cbi8vIEV2ZXJ5dGhpbmcgYmVmb3JlIHRoZSBmaW5hbCBVU0VSIGluc3RydWN0aW9uLiBGZWF0dXJlcyBpbnNlcnQgUlVOIHN0ZXBzIGhlcmUuXG5jb25zdCBET0NLRVJGSUxFX0JBU0UgPSBgRlJPTSBub2RlOjI0XG5cbkFSRyBVU0VSTkFNRT1ub2RlXG5cbiMgU3lzdGVtIHRvb2xzOiBqcSArIHJpcGdyZXAgZm9yIHNjcmlwdGluZy9zZWFyY2gsIHB5dGhvbjMgZm9yIEFJIHRvb2xpbmcsXG4jIGdoIGZvciBHaXRIdWIgd29ya2Zsb3dzLCBjdXJsL2dudXBnIGZvciBwYWNrYWdlIHNvdXJjZXMuXG5SVU4gYXB0LWdldCB1cGRhdGUgXFxcXFxuICAgICYmIGFwdC1nZXQgaW5zdGFsbCAteSAtLW5vLWluc3RhbGwtcmVjb21tZW5kcyBjYS1jZXJ0aWZpY2F0ZXMgY3VybCBnbnVwZyBqcSByaXBncmVwIHB5dGhvbjMgXFxcXFxuICAgICYmIGN1cmwgLWZzU0wgaHR0cHM6Ly9jbGkuZ2l0aHViLmNvbS9wYWNrYWdlcy9naXRodWJjbGktYXJjaGl2ZS1rZXlyaW5nLmdwZyAtbyAvdXNyL3NoYXJlL2tleXJpbmdzL2dpdGh1YmNsaS1hcmNoaXZlLWtleXJpbmcuZ3BnIFxcXFxcbiAgICAmJiBjaG1vZCBnbytyIC91c3Ivc2hhcmUva2V5cmluZ3MvZ2l0aHViY2xpLWFyY2hpdmUta2V5cmluZy5ncGcgXFxcXFxuICAgICYmIGVjaG8gXCJkZWIgW2FyY2g9JChkcGtnIC0tcHJpbnQtYXJjaGl0ZWN0dXJlKSBzaWduZWQtYnk9L3Vzci9zaGFyZS9rZXlyaW5ncy9naXRodWJjbGktYXJjaGl2ZS1rZXlyaW5nLmdwZ10gaHR0cHM6Ly9jbGkuZ2l0aHViLmNvbS9wYWNrYWdlcyBzdGFibGUgbWFpblwiID4gL2V0Yy9hcHQvc291cmNlcy5saXN0LmQvZ2l0aHViLWNsaS5saXN0IFxcXFxcbiAgICAmJiBhcHQtZ2V0IHVwZGF0ZSBcXFxcXG4gICAgJiYgYXB0LWdldCBpbnN0YWxsIC15IC0tbm8taW5zdGFsbC1yZWNvbW1lbmRzIGdoIFxcXFxcbiAgICAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLypcblxuUlVOIG5wbSBpbnN0YWxsIC0tZ2xvYmFsIG5wbUBsYXRlc3QgXFxcXFxuICAgICYmIG5wbSBhZGQgLS1nbG9iYWwgcG5wbUAxMFxuXG5SVU4gbWtkaXIgLXAgL2hvbWUvXFwke1VTRVJOQU1FfS8uY29uZmlnL3BucG0gL2hvbWUvXFwke1VTRVJOQU1FfS8ucG5wbS1zdG9yZSBcXFxcXG4gICAgJiYgY2hvd24gLVIgXFwke1VTRVJOQU1FfTpcXCR7VVNFUk5BTUV9IC9ob21lL1xcJHtVU0VSTkFNRX0vLmNvbmZpZyAvaG9tZS9cXCR7VVNFUk5BTUV9Ly5wbnBtLXN0b3JlIFxcXFxcbiAgICAmJiBwcmludGYgXCJzdG9yZS1kaXI9L2hvbWUvXFwke1VTRVJOQU1FfS8ucG5wbS1zdG9yZVxcXFxuXCIgPiAvaG9tZS9cXCR7VVNFUk5BTUV9Ly5jb25maWcvcG5wbS9yY1xuXG4jIFByZS1jcmVhdGUgd29ya3NwYWNlIG5vZGVfbW9kdWxlcyBzbyB0aGUgbmFtZWQgdm9sdW1lIG1vdW50IGlzIG93bmVkIGJ5IHRoZSB1c2VyXG5SVU4gbWtkaXIgLXAgL3dvcmtzcGFjZS9ub2RlX21vZHVsZXMgJiYgY2hvd24gXFwke1VTRVJOQU1FfTpcXCR7VVNFUk5BTUV9IC93b3Jrc3BhY2Uvbm9kZV9tb2R1bGVzXG5cblJVTiBta2RpciAvY29tbWFuZGhpc3RvcnkgJiYgdG91Y2ggL2NvbW1hbmRoaXN0b3J5Ly5iYXNoX2hpc3RvcnkgXFxcXFxuICAgICYmIGNob3duIC1SIFxcJHtVU0VSTkFNRX0gL2NvbW1hbmRoaXN0b3J5XG5cblJVTiBTTklQUEVUPVwiZXhwb3J0IFBST01QVF9DT01NQU5EPSdoaXN0b3J5IC1hJyAmJiBleHBvcnQgSElTVEZJTEU9L2NvbW1hbmRoaXN0b3J5Ly5iYXNoX2hpc3RvcnlcIiBcXFxcXG4gICAgJiYgZWNobyBcIiRTTklQUEVUXCIgPj4gXCIvaG9tZS9cXCR7VVNFUk5BTUV9Ly5iYXNocmNcIlxuXG4jIFZTIENvZGUganMtZGVidWcgYnVnOiBib290bG9hZGVyLmpzIGluIHdvcmtzcGFjZVN0b3JhZ2UgaXMgb25seSBjcmVhdGVkIHdoZW5cbiMgdGhlIHVzZXIgbWFudWFsbHkgdG9nZ2xlcyBBdXRvIEF0dGFjaCBzZXR0aW5ncy4gT24gYSBmcmVzaCBjb250YWluZXIgaXQgaXNcbiMgbWlzc2luZywgd2hpY2ggY3Jhc2hlcyBldmVyeSBOb2RlIGNvbW1hbmQuIEZpeDogaWYgdGhlIGluamVjdGVkIHBhdGggaXNcbiMgbWlzc2luZywgc3Vic3RpdHV0ZSB0aGUgc3RhYmxlIGJvb3Rsb2FkZXIgZnJvbSB0aGUgVlMgQ29kZSBzZXJ2ZXIgZXh0ZW5zaW9uXG4jIGRpcmVjdG9yeSAoYWx3YXlzIHByZXNlbnQgb25jZSB0aGUgc2VydmVyIGlzIGluc3RhbGxlZCkuXG5SVU4gY2F0IDw8J0VPRicgPj4gXCIvaG9tZS9cXCR7VVNFUk5BTUV9Ly5iYXNocmNcIlxuaWYgW1sgLW4gXCJcXCR7Tk9ERV9PUFRJT05TOi19XCIgJiYgXCJcXCR7Tk9ERV9PUFRJT05TfVwiID09ICpcImJvb3Rsb2FkZXIuanNcIiogXV07IHRoZW5cbiAgICBfYm9vdGxvYWRlcl9wYXRoPVwiJChwcmludGYgJyVzXFxcXG4nIFwiJE5PREVfT1BUSU9OU1wiIHwgc2VkIC1uICdzLy4qLS1yZXF1aXJlWz0gXVxcXFwoW15bOnNwYWNlOl1dKmJvb3Rsb2FkZXJcXFxcLmpzXFxcXCkuKi9cXFxcMS9wJylcIlxuICAgIGlmIFtbIC1uIFwiXFwke19ib290bG9hZGVyX3BhdGh9XCIgJiYgISAtZiBcIlxcJHtfYm9vdGxvYWRlcl9wYXRofVwiIF1dOyB0aGVuXG4gICAgICAgIF9zdGFibGVfYm9vdGxvYWRlcj1cIiQoZmluZCAvdnNjb2RlL3ZzY29kZS1zZXJ2ZXIgL2hvbWUvbm9kZS8udnNjb2RlLXNlcnZlci9leHRlbnNpb25zIC1uYW1lIFwiYm9vdGxvYWRlci5qc1wiIC1wYXRoIFwiKi9tcy12c2NvZGUuanMtZGVidWcvKlwiIDI+L2Rldi9udWxsIHwgaGVhZCAtMSlcIlxuICAgICAgICBpZiBbWyAtbiBcIlxcJHtfc3RhYmxlX2Jvb3Rsb2FkZXJ9XCIgXV07IHRoZW5cbiAgICAgICAgICAgIE5PREVfT1BUSU9OUz1cIlxcJHtOT0RFX09QVElPTlMvL1xcJHtfYm9vdGxvYWRlcl9wYXRofS9cXCR7X3N0YWJsZV9ib290bG9hZGVyfX1cIlxuICAgICAgICBlbHNlXG4gICAgICAgICAgICBOT0RFX09QVElPTlM9XCIkKHByaW50ZiAnJXNcXFxcbicgXCIkTk9ERV9PUFRJT05TXCIgfCBzZWQgLUUgJ3MjKF58ICktLXJlcXVpcmUoPXwgKVtbOmdyYXBoOl1dKmJvb3Rsb2FkZXJcXFxcLmpzKCB8JCkjICNnOyBzIyAgKyMgI2c7IHMjXiAjIzsgcyMgJCMjJylcIlxuICAgICAgICAgICAgdW5zZXQgVlNDT0RFX0lOU1BFQ1RPUl9PUFRJT05TXG4gICAgICAgIGZpXG4gICAgICAgIGV4cG9ydCBOT0RFX09QVElPTlNcbiAgICAgICAgaWYgW1sgLXogXCIkTk9ERV9PUFRJT05TXCIgXV07IHRoZW5cbiAgICAgICAgICAgIHVuc2V0IE5PREVfT1BUSU9OU1xuICAgICAgICBmaVxuICAgIGZpXG4gICAgdW5zZXQgX2Jvb3Rsb2FkZXJfcGF0aCBfc3RhYmxlX2Jvb3Rsb2FkZXJcbmZpXG5FT0ZcbmA7XG5cbmNvbnN0IERPQ0tFUkZJTEVfVVNFUiA9IGBcXG5VU0VSIFxcJHtVU0VSTkFNRX1cXG5gO1xuXG4vKipcbiAqIEJ1aWxkZXIgZm9yIGAuZGV2Y29udGFpbmVyL0RvY2tlcmZpbGVgLlxuICpcbiAqIEZlYXR1cmVzIGNhbGwgYGFkZFJ1blN0ZXAoY21kKWAgZHVyaW5nIHRoZWlyIHNjYWZmb2xkIHBoYXNlIHRvIGFwcGVuZFxuICogYWRkaXRpb25hbCBgUlVOYCBpbnN0cnVjdGlvbnMgYmVmb3JlIHRoZSBmaW5hbCBgVVNFUmAgaW5zdHJ1Y3Rpb24uXG4gKiBgZmlsZXMoKWAgYXNzZW1ibGVzIHRoZSBjb21wbGV0ZSBEb2NrZXJmaWxlIGNvbnRlbnQgYXQgcmVuZGVyIHRpbWUuXG4gKi9cbmV4cG9ydCBjbGFzcyBEb2NrZXJmaWxlTW9kZWwgaW1wbGVtZW50cyBLZXllZE1vZGVsIHtcblx0cHVibGljIHJlYWRvbmx5IGtleSA9IFdFTExfS05PV05fRklMRVMuRE9DS0VSRklMRTtcblx0cHJpdmF0ZSByZWFkb25seSBfcnVuU3RlcHM6IHN0cmluZ1tdID0gW107XG5cblx0LyoqIEFwcGVuZCBhIFJVTiBpbnN0cnVjdGlvbiAocGFzcyB0aGUgY29tbWFuZCwgbm90IHRoZSBSVU4ga2V5d29yZCkuICovXG5cdHB1YmxpYyBhZGRSdW5TdGVwKGNtZDogc3RyaW5nKTogdGhpcyB7XG5cdFx0dGhpcy5fcnVuU3RlcHMucHVzaChjbWQpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0cHVibGljIGZpbGVzKCk6IFNvdXJjZUZpbGVbXSB7XG5cdFx0Y29uc3QgZXh0cmFzID1cblx0XHRcdHRoaXMuX3J1blN0ZXBzLmxlbmd0aCA+IDBcblx0XHRcdFx0PyBgXFxuJHt0aGlzLl9ydW5TdGVwcy5tYXAoKHMpID0+IGBSVU4gJHtzfWApLmpvaW4oXCJcXG5cXG5cIil9XFxuYFxuXHRcdFx0XHQ6IFwiXCI7XG5cdFx0cmV0dXJuIFtcblx0XHRcdHtcblx0XHRcdFx0ZmlsZVBhdGg6IFwiLmRldmNvbnRhaW5lci9Eb2NrZXJmaWxlXCIsXG5cdFx0XHRcdGNvbnRlbnQ6IERPQ0tFUkZJTEVfQkFTRSArIGV4dHJhcyArIERPQ0tFUkZJTEVfVVNFUixcblx0XHRcdH0sXG5cdFx0XTtcblx0fVxufVxuIl0sIm5hbWVzIjpbIkRvY2tlcmZpbGVNb2RlbCIsIkRPQ0tFUkZJTEVfQkFTRSIsIkRPQ0tFUkZJTEVfVVNFUiIsImtleSIsIldFTExfS05PV05fRklMRVMiLCJET0NLRVJGSUxFIiwiX3J1blN0ZXBzIiwiYWRkUnVuU3RlcCIsImNtZCIsInB1c2giLCJmaWxlcyIsImV4dHJhcyIsImxlbmd0aCIsIm1hcCIsInMiLCJqb2luIiwiZmlsZVBhdGgiLCJjb250ZW50Il0sIm1hcHBpbmdzIjoiOzs7OytCQXNFYUE7OztlQUFBQTs7O3VCQXRFb0I7QUFHakMsZ0ZBQWdGO0FBQ2hGLE1BQU1DLGtCQUFrQixDQUFDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBdUR6QixDQUFDO0FBRUQsTUFBTUMsa0JBQWtCLENBQUMscUJBQXFCLENBQUM7QUFTeEMsTUFBTUY7SUFDSUcsTUFBTUMsdUJBQWdCLENBQUNDLFVBQVUsQ0FBQztJQUNqQ0MsWUFBc0IsRUFBRSxDQUFDO0lBRTFDLHNFQUFzRSxHQUN0RSxBQUFPQyxXQUFXQyxHQUFXLEVBQVE7UUFDcEMsSUFBSSxDQUFDRixTQUFTLENBQUNHLElBQUksQ0FBQ0Q7UUFDcEIsT0FBTyxJQUFJO0lBQ1o7SUFFT0UsUUFBc0I7UUFDNUIsTUFBTUMsU0FDTCxJQUFJLENBQUNMLFNBQVMsQ0FBQ00sTUFBTSxHQUFHLElBQ3JCLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQ04sU0FBUyxDQUFDTyxHQUFHLENBQUMsQ0FBQ0MsSUFBTSxDQUFDLElBQUksRUFBRUEsR0FBRyxFQUFFQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsR0FDM0Q7UUFDSixPQUFPO1lBQ047Z0JBQ0NDLFVBQVU7Z0JBQ1ZDLFNBQVNoQixrQkFBa0JVLFNBQVNUO1lBQ3JDO1NBQ0E7SUFDRjtBQUNEIn0=