@dbx-tools/cli 0.3.44 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env -S npx tsx
2
+ export {};
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env -S npx tsx
2
+ /**
3
+ * `dbx-tools` bootstraps uninitialized workspaces, then forwards to projen.
4
+ */
5
+ import { runCli } from "../src/cli.js";
6
+ runCli(process.argv).catch((err) => {
7
+ console.error(err);
8
+ process.exit(1);
9
+ });
10
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGJ4LXRvb2xzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vYmluL2RieC10b29scy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQ0E7O0dBRUc7QUFDSCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBRXBDLE1BQU0sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBWSxFQUFFLEVBQUU7SUFDMUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNuQixPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ2xCLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiIyEvdXNyL2Jpbi9lbnYgLVMgbnB4IHRzeFxuLyoqXG4gKiBgZGJ4LXRvb2xzYCBib290c3RyYXBzIHVuaW5pdGlhbGl6ZWQgd29ya3NwYWNlcywgdGhlbiBmb3J3YXJkcyB0byBwcm9qZW4uXG4gKi9cbmltcG9ydCB7IHJ1bkNsaSB9IGZyb20gXCIuLi9zcmMvY2xpXCI7XG5cbnJ1bkNsaShwcm9jZXNzLmFyZ3YpLmNhdGNoKChlcnI6IHVua25vd24pID0+IHtcbiAgY29uc29sZS5lcnJvcihlcnIpO1xuICBwcm9jZXNzLmV4aXQoMSk7XG59KTtcbiJdfQ==
package/lib/index.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ export * as bootstrap from "./src/bootstrap.js";
2
+ export * as cli from "./src/cli.js";
3
+ export * as pnpm from "./src/pnpm.js";
4
+ export * as root from "./src/root.js";
5
+ export { ensureEngineCurrent, bootstrapWorkspace, seedToolchain, runInitialSynth } from "./src/bootstrap.js";
6
+ export { runCli } from "./src/cli.js";
7
+ export { resolvePnpmArgv, runPnpm, ensureWorkspaceReady, runProjen } from "./src/pnpm.js";
8
+ export { findWorkspaceRoot, needsBootstrap, needsInstall, needsToolchain, workspaceRoot, rootLabel } from "./src/root.js";
package/lib/index.js ADDED
@@ -0,0 +1,12 @@
1
+ // GENERATED by projen watch - DO NOT EDIT.
2
+ // Regenerated from the exporting modules in ./src.
3
+ // Hand edits are overwritten on the next watch; this file is read-only.
4
+ export * as bootstrap from "./src/bootstrap.js";
5
+ export * as cli from "./src/cli.js";
6
+ export * as pnpm from "./src/pnpm.js";
7
+ export * as root from "./src/root.js";
8
+ export { ensureEngineCurrent, bootstrapWorkspace, seedToolchain, runInitialSynth } from "./src/bootstrap.js";
9
+ export { runCli } from "./src/cli.js";
10
+ export { resolvePnpmArgv, runPnpm, ensureWorkspaceReady, runProjen } from "./src/pnpm.js";
11
+ export { findWorkspaceRoot, needsBootstrap, needsInstall, needsToolchain, workspaceRoot, rootLabel } from "./src/root.js";
12
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxPQUFPLEtBQUssU0FBUyxNQUFNLGlCQUFpQixDQUFDO0FBQzdDLE9BQU8sS0FBSyxHQUFHLE1BQU0sV0FBVyxDQUFDO0FBQ2pDLE9BQU8sS0FBSyxJQUFJLE1BQU0sWUFBWSxDQUFDO0FBQ25DLE9BQU8sS0FBSyxJQUFJLE1BQU0sWUFBWSxDQUFDO0FBQ25DLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxrQkFBa0IsRUFBRSxhQUFhLEVBQUUsZUFBZSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDMUcsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNuQyxPQUFPLEVBQUUsZUFBZSxFQUFFLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxTQUFTLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDdkYsT0FBTyxFQUFFLGlCQUFpQixFQUFFLGNBQWMsRUFBRSxZQUFZLEVBQUUsY0FBYyxFQUFFLGFBQWEsRUFBRSxTQUFTLEVBQUUsTUFBTSxZQUFZLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBHRU5FUkFURUQgYnkgcHJvamVuIHdhdGNoIC0gRE8gTk9UIEVESVQuXG4vLyBSZWdlbmVyYXRlZCBmcm9tIHRoZSBleHBvcnRpbmcgbW9kdWxlcyBpbiAuL3NyYy5cbi8vIEhhbmQgZWRpdHMgYXJlIG92ZXJ3cml0dGVuIG9uIHRoZSBuZXh0IHdhdGNoOyB0aGlzIGZpbGUgaXMgcmVhZC1vbmx5LlxuXG5leHBvcnQgKiBhcyBib290c3RyYXAgZnJvbSBcIi4vc3JjL2Jvb3RzdHJhcFwiO1xuZXhwb3J0ICogYXMgY2xpIGZyb20gXCIuL3NyYy9jbGlcIjtcbmV4cG9ydCAqIGFzIHBucG0gZnJvbSBcIi4vc3JjL3BucG1cIjtcbmV4cG9ydCAqIGFzIHJvb3QgZnJvbSBcIi4vc3JjL3Jvb3RcIjtcbmV4cG9ydCB7IGVuc3VyZUVuZ2luZUN1cnJlbnQsIGJvb3RzdHJhcFdvcmtzcGFjZSwgc2VlZFRvb2xjaGFpbiwgcnVuSW5pdGlhbFN5bnRoIH0gZnJvbSBcIi4vc3JjL2Jvb3RzdHJhcFwiO1xuZXhwb3J0IHsgcnVuQ2xpIH0gZnJvbSBcIi4vc3JjL2NsaVwiO1xuZXhwb3J0IHsgcmVzb2x2ZVBucG1Bcmd2LCBydW5QbnBtLCBlbnN1cmVXb3Jrc3BhY2VSZWFkeSwgcnVuUHJvamVuIH0gZnJvbSBcIi4vc3JjL3BucG1cIjtcbmV4cG9ydCB7IGZpbmRXb3Jrc3BhY2VSb290LCBuZWVkc0Jvb3RzdHJhcCwgbmVlZHNJbnN0YWxsLCBuZWVkc1Rvb2xjaGFpbiwgd29ya3NwYWNlUm9vdCwgcm9vdExhYmVsIH0gZnJvbSBcIi4vc3JjL3Jvb3RcIjtcbiJdfQ==
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Upgrade an established workspace whose installed engine predates this CLI.
3
+ *
4
+ * Bootstrapping pins the engine once, and nothing afterwards revisits it - so a
5
+ * workspace created months ago kept resolving its original engine no matter how
6
+ * current the CLI invoking it was, and failed inside the OLD engine's code
7
+ * (`sync --watch` dying on a `concurrently` that engine never declared). The two
8
+ * are released in lockstep, so this CLI's version is exactly the engine it
9
+ * expects.
10
+ *
11
+ * Only ever moves FORWARD: an engine at or ahead of this CLI is left alone, so
12
+ * an older CLI cannot downgrade a workspace.
13
+ */
14
+ export declare function ensureEngineCurrent(root: string): void;
15
+ /**
16
+ * Turn a folder into a functioning dbx-tools workspace: `pnpm init`, seed
17
+ * `pnpm-workspace.yaml`, add `projen`/`typescript`/`tsx` + the engine package,
18
+ * write a minimal `.projenrc.ts`, synth once (with `PROJEN_DISABLE_POST`), then
19
+ * install. Does not run barrels - run `pnpm run barrels` or a full projen synth
20
+ * post-install to generate package barrels.
21
+ *
22
+ * Every step is idempotent and self-guarded, so this is safe to run against a
23
+ * folder that ALREADY has a hand-authored `.projenrc.ts` (and even a committed
24
+ * `package.json`) but is missing the installed toolchain - e.g. a freshly copied
25
+ * project whose generated files (including manifests) are gitignored. In that
26
+ * case `pnpm init` and the `.projenrc.ts` scaffold are skipped, but the engine +
27
+ * projen + tsx are (re)installed so the subsequent synth can regenerate
28
+ * everything. See {@link seedToolchain}.
29
+ */
30
+ export declare function bootstrapWorkspace(root: string, projenSpecifier?: string): void;
31
+ /**
32
+ * Install the toolchain a synth needs (`projen`, `typescript`, `tsx`, and the
33
+ * dbx-tools engine), seeding a `package.json` and `pnpm-workspace.yaml` first
34
+ * when absent. Idempotent: run it whenever the engine is missing, so a copied
35
+ * project with a `.projenrc.ts` but no `node_modules`/manifests can be brought
36
+ * up to a synth-ready state without full bootstrapping.
37
+ */
38
+ export declare function seedToolchain(root: string, projenSpecifier?: string): void;
39
+ /**
40
+ * Run the initial synth by executing `.projenrc.ts` directly with tsx (with
41
+ * `PROJEN_DISABLE_POST` set), NOT `projen <task>`. Use right after seeding a
42
+ * fresh workspace: the projen TASKS (`sync`, `barrels`, ...) only exist once
43
+ * `.projenrc.ts` has run once, so `projen sync` can't be the bootstrapping step.
44
+ */
45
+ export declare function runInitialSynth(root: string): void;
@@ -0,0 +1,186 @@
1
+ /**
2
+ * Bootstrap a brand-new folder into a working dbx-tools workspace before projen runs.
3
+ *
4
+ * @module
5
+ */
6
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
7
+ import { join } from "node:path";
8
+ import { fileURLToPath } from "node:url";
9
+ import { intro, outro } from "@clack/prompts";
10
+ import { exec } from "@dbx-tools/core";
11
+ import { json } from "@dbx-tools/shared-core";
12
+ import { resolvePnpmArgv, runPnpm } from "./pnpm.js";
13
+ import { rootLabel } from "./root.js";
14
+ /** Fallback when this CLI's own version isn't a real release (an in-repo `0.0.0`). */
15
+ const FALLBACK_PROJEN_SPECIFIER = "@dbx-tools/projen@latest";
16
+ /**
17
+ * Install the engine at THIS CLI's own version. The two are released together by
18
+ * the root `bump`, so the matching engine always exists on the registry.
19
+ *
20
+ * Not `@latest`, and not a bare `@dbx-tools/projen`. A bare specifier can land on
21
+ * a stray `0.0.0`, whose `^0.0.0` caret then reaches no real release. `@latest`
22
+ * has a subtler failure: pnpm 11 applies a `minimumReleaseAge` delay, so for the
23
+ * first day after a release it deliberately resolves a dist-tag to the newest
24
+ * version OLDER than the threshold and merely notes the newer one
25
+ * (`+ @dbx-tools/projen 0.1.24 (0.3.42 is available)`). A bootstrap run right
26
+ * after a release therefore installed a months-old engine against a current CLI,
27
+ * which is how `sync --watch` died on an engine predating its `concurrently`
28
+ * dependency. An explicit range admits only the version we want, so the age
29
+ * heuristic has nothing older to fall back to.
30
+ */
31
+ function defaultProjenSpecifier() {
32
+ const version = ownVersion();
33
+ return version ? `@dbx-tools/projen@^${version}` : FALLBACK_PROJEN_SPECIFIER;
34
+ }
35
+ /** This CLI's own released version, or `undefined` for an in-repo `0.0.0` build. */
36
+ function ownVersion() {
37
+ try {
38
+ const manifestPath = fileURLToPath(new URL("../package.json", import.meta.url));
39
+ const version = json.parseRecord(readFileSync(manifestPath, "utf8"))?.version;
40
+ return typeof version === "string" && version !== "0.0.0" ? version : undefined;
41
+ }
42
+ catch {
43
+ return undefined;
44
+ }
45
+ }
46
+ /** Compare `x.y.z` triples; returns <0, 0, or >0. Missing parts count as 0. */
47
+ function compareVersions(a, b) {
48
+ const parts = (v) => v.split(".").map((p) => Number.parseInt(p, 10) || 0);
49
+ const [x, y] = [parts(a), parts(b)];
50
+ return x[0] - y[0] || x[1] - y[1] || x[2] - y[2];
51
+ }
52
+ /** Version of the engine currently installed at `root`, if any. */
53
+ function installedEngineVersion(root) {
54
+ try {
55
+ const manifest = join(root, "node_modules", "@dbx-tools", "projen", "package.json");
56
+ const version = json.parseRecord(readFileSync(manifest, "utf8"))?.version;
57
+ return typeof version === "string" ? version : undefined;
58
+ }
59
+ catch {
60
+ return undefined;
61
+ }
62
+ }
63
+ /**
64
+ * Upgrade an established workspace whose installed engine predates this CLI.
65
+ *
66
+ * Bootstrapping pins the engine once, and nothing afterwards revisits it - so a
67
+ * workspace created months ago kept resolving its original engine no matter how
68
+ * current the CLI invoking it was, and failed inside the OLD engine's code
69
+ * (`sync --watch` dying on a `concurrently` that engine never declared). The two
70
+ * are released in lockstep, so this CLI's version is exactly the engine it
71
+ * expects.
72
+ *
73
+ * Only ever moves FORWARD: an engine at or ahead of this CLI is left alone, so
74
+ * an older CLI cannot downgrade a workspace.
75
+ */
76
+ export function ensureEngineCurrent(root) {
77
+ const expected = ownVersion();
78
+ if (!expected)
79
+ return;
80
+ const installed = installedEngineVersion(root);
81
+ if (installed && compareVersions(installed, expected) >= 0)
82
+ return;
83
+ runPnpm(["add", "-D", defaultProjenSpecifier()], root);
84
+ }
85
+ // Reach the class through its module NAMESPACE. Current engines also hoist it
86
+ // flat, but every engine ever published exports the namespace, and this template
87
+ // is resolved against `@latest` - a flat import dies on an older one with
88
+ // "does not provide an export named 'DBXToolsNodeProject'".
89
+ const PROJENRC_TEMPLATE = `import { project as projectApi } from "@dbx-tools/projen";
90
+
91
+ const project = new projectApi.DBXToolsNodeProject();
92
+ project.synth();
93
+ `;
94
+ /** Seed `pnpm-workspace.yaml` so the first \`pnpm add\` can allow esbuild non-interactively. */
95
+ const WORKSPACE_SEED = `packages: []
96
+ allowBuilds:
97
+ esbuild: true
98
+ `;
99
+ /**
100
+ * Turn a folder into a functioning dbx-tools workspace: `pnpm init`, seed
101
+ * `pnpm-workspace.yaml`, add `projen`/`typescript`/`tsx` + the engine package,
102
+ * write a minimal `.projenrc.ts`, synth once (with `PROJEN_DISABLE_POST`), then
103
+ * install. Does not run barrels - run `pnpm run barrels` or a full projen synth
104
+ * post-install to generate package barrels.
105
+ *
106
+ * Every step is idempotent and self-guarded, so this is safe to run against a
107
+ * folder that ALREADY has a hand-authored `.projenrc.ts` (and even a committed
108
+ * `package.json`) but is missing the installed toolchain - e.g. a freshly copied
109
+ * project whose generated files (including manifests) are gitignored. In that
110
+ * case `pnpm init` and the `.projenrc.ts` scaffold are skipped, but the engine +
111
+ * projen + tsx are (re)installed so the subsequent synth can regenerate
112
+ * everything. See {@link seedToolchain}.
113
+ */
114
+ export function bootstrapWorkspace(root, projenSpecifier = defaultProjenSpecifier()) {
115
+ intro(`Bootstrapping dbx-tools workspace in ${rootLabel(root)}`);
116
+ seedToolchain(root, projenSpecifier);
117
+ const projenrc = join(root, ".projenrc.ts");
118
+ if (!existsSync(projenrc)) {
119
+ writeFileSync(projenrc, PROJENRC_TEMPLATE);
120
+ }
121
+ runInitialSynth(root);
122
+ runPnpm(["install", "--no-frozen-lockfile", "--force"], root);
123
+ outro("Workspace ready - re-run dbx-tools or add packages under packages/");
124
+ }
125
+ /**
126
+ * Install the toolchain a synth needs (`projen`, `typescript`, `tsx`, and the
127
+ * dbx-tools engine), seeding a `package.json` and `pnpm-workspace.yaml` first
128
+ * when absent. Idempotent: run it whenever the engine is missing, so a copied
129
+ * project with a `.projenrc.ts` but no `node_modules`/manifests can be brought
130
+ * up to a synth-ready state without full bootstrapping.
131
+ */
132
+ export function seedToolchain(root, projenSpecifier = defaultProjenSpecifier()) {
133
+ const manifestPath = join(root, "package.json");
134
+ if (!existsSync(manifestPath)) {
135
+ runPnpm(["init"], root);
136
+ normalizeSeedManifest(manifestPath);
137
+ }
138
+ const workspaceFile = join(root, "pnpm-workspace.yaml");
139
+ if (!existsSync(workspaceFile)) {
140
+ writeFileSync(workspaceFile, WORKSPACE_SEED);
141
+ }
142
+ runPnpm(["add", "-D", "projen", "typescript@^5.9.3", "tsx@^4.23.0", projenSpecifier], root);
143
+ }
144
+ /**
145
+ * Make what `pnpm init` produced safe to synth against. Two corrections, both
146
+ * because that output varies by pnpm version:
147
+ *
148
+ * - drop `devEngines`, which pnpm 11 seeds as `packageManager: { name: "pnpm",
149
+ * onFail: "download" }`. Any npm-based tool later in the chain (an
150
+ * `npx`/dlx fallback) then refuses with EBADDEVENGINES, its runner being npm;
151
+ * - force `type: "module"`, which pnpm 11 writes and pnpm 10 does not. tsx
152
+ * picks the entry's format from the nearest manifest, so without it
153
+ * `.projenrc.ts` loads as CJS and the first dependency using top-level await
154
+ * dies on "not supported with the cjs output format".
155
+ *
156
+ * projen regenerates the whole manifest at synth, so this only has to hold the
157
+ * seed together long enough to get there.
158
+ */
159
+ function normalizeSeedManifest(manifestPath) {
160
+ try {
161
+ const manifest = json.parseRecord(readFileSync(manifestPath, "utf8"));
162
+ if (!manifest)
163
+ return;
164
+ delete manifest.devEngines;
165
+ manifest.type = "module";
166
+ writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
167
+ }
168
+ catch {
169
+ // A malformed/absent manifest here just means the later `pnpm add` recreates it.
170
+ }
171
+ }
172
+ /**
173
+ * Run the initial synth by executing `.projenrc.ts` directly with tsx (with
174
+ * `PROJEN_DISABLE_POST` set), NOT `projen <task>`. Use right after seeding a
175
+ * fresh workspace: the projen TASKS (`sync`, `barrels`, ...) only exist once
176
+ * `.projenrc.ts` has run once, so `projen sync` can't be the bootstrapping step.
177
+ */
178
+ export function runInitialSynth(root) {
179
+ const [command, ...prefix] = resolvePnpmArgv();
180
+ exec.spawnSync(command, [...prefix, "exec", "tsx", ".projenrc.ts"], {
181
+ cwd: root,
182
+ env: { ...process.env, PROJEN_DISABLE_POST: "true" },
183
+ check: true,
184
+ });
185
+ }
186
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYm9vdHN0cmFwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2Jvb3RzdHJhcC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHO0FBQ0gsT0FBTyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsYUFBYSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ2xFLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDakMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUN6QyxPQUFPLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN2QyxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDOUMsT0FBTyxFQUFFLGVBQWUsRUFBRSxPQUFPLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFDbEQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLFFBQVEsQ0FBQztBQUVuQyxzRkFBc0Y7QUFDdEYsTUFBTSx5QkFBeUIsR0FBRywwQkFBMEIsQ0FBQztBQUU3RDs7Ozs7Ozs7Ozs7Ozs7R0FjRztBQUNILFNBQVMsc0JBQXNCO0lBQzdCLE1BQU0sT0FBTyxHQUFHLFVBQVUsRUFBRSxDQUFDO0lBQzdCLE9BQU8sT0FBTyxDQUFDLENBQUMsQ0FBQyxzQkFBc0IsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDLHlCQUF5QixDQUFDO0FBQy9FLENBQUM7QUFFRCxvRkFBb0Y7QUFDcEYsU0FBUyxVQUFVO0lBQ2pCLElBQUksQ0FBQztRQUNILE1BQU0sWUFBWSxHQUFHLGFBQWEsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxpQkFBaUIsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDaEYsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxZQUFZLENBQUMsWUFBWSxFQUFFLE1BQU0sQ0FBQyxDQUFDLEVBQUUsT0FBTyxDQUFDO1FBQzlFLE9BQU8sT0FBTyxPQUFPLEtBQUssUUFBUSxJQUFJLE9BQU8sS0FBSyxPQUFPLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0lBQ2xGLENBQUM7SUFBQyxNQUFNLENBQUM7UUFDUCxPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0FBQ0gsQ0FBQztBQUVELCtFQUErRTtBQUMvRSxTQUFTLGVBQWUsQ0FBQyxDQUFTLEVBQUUsQ0FBUztJQUMzQyxNQUFNLEtBQUssR0FBRyxDQUFDLENBQVMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ2xGLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDcEMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUNuRCxDQUFDO0FBRUQsbUVBQW1FO0FBQ25FLFNBQVMsc0JBQXNCLENBQUMsSUFBWTtJQUMxQyxJQUFJLENBQUM7UUFDSCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsSUFBSSxFQUFFLGNBQWMsRUFBRSxZQUFZLEVBQUUsUUFBUSxFQUFFLGNBQWMsQ0FBQyxDQUFDO1FBQ3BGLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsWUFBWSxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQztRQUMxRSxPQUFPLE9BQU8sT0FBTyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7SUFDM0QsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7QUFDSCxDQUFDO0FBRUQ7Ozs7Ozs7Ozs7OztHQVlHO0FBQ0gsTUFBTSxVQUFVLG1CQUFtQixDQUFDLElBQVk7SUFDOUMsTUFBTSxRQUFRLEdBQUcsVUFBVSxFQUFFLENBQUM7SUFDOUIsSUFBSSxDQUFDLFFBQVE7UUFBRSxPQUFPO0lBQ3RCLE1BQU0sU0FBUyxHQUFHLHNCQUFzQixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQy9DLElBQUksU0FBUyxJQUFJLGVBQWUsQ0FBQyxTQUFTLEVBQUUsUUFBUSxDQUFDLElBQUksQ0FBQztRQUFFLE9BQU87SUFDbkUsT0FBTyxDQUFDLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxzQkFBc0IsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7QUFDekQsQ0FBQztBQUVELDhFQUE4RTtBQUM5RSxpRkFBaUY7QUFDakYsMEVBQTBFO0FBQzFFLDREQUE0RDtBQUM1RCxNQUFNLGlCQUFpQixHQUFHOzs7O0NBSXpCLENBQUM7QUFFRixnR0FBZ0c7QUFDaEcsTUFBTSxjQUFjLEdBQUc7OztDQUd0QixDQUFDO0FBRUY7Ozs7Ozs7Ozs7Ozs7O0dBY0c7QUFDSCxNQUFNLFVBQVUsa0JBQWtCLENBQ2hDLElBQVksRUFDWixrQkFBMEIsc0JBQXNCLEVBQUU7SUFFbEQsS0FBSyxDQUFDLHdDQUF3QyxTQUFTLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBRWpFLGFBQWEsQ0FBQyxJQUFJLEVBQUUsZUFBZSxDQUFDLENBQUM7SUFFckMsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLElBQUksRUFBRSxjQUFjLENBQUMsQ0FBQztJQUM1QyxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7UUFDMUIsYUFBYSxDQUFDLFFBQVEsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO0lBQzdDLENBQUM7SUFFRCxlQUFlLENBQUMsSUFBSSxDQUFDLENBQUM7SUFFdEIsT0FBTyxDQUFDLENBQUMsU0FBUyxFQUFFLHNCQUFzQixFQUFFLFNBQVMsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQzlELEtBQUssQ0FBQyxvRUFBb0UsQ0FBQyxDQUFDO0FBQzlFLENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxNQUFNLFVBQVUsYUFBYSxDQUMzQixJQUFZLEVBQ1osa0JBQTBCLHNCQUFzQixFQUFFO0lBRWxELE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxJQUFJLEVBQUUsY0FBYyxDQUFDLENBQUM7SUFDaEQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDO1FBQzlCLE9BQU8sQ0FBQyxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ3hCLHFCQUFxQixDQUFDLFlBQVksQ0FBQyxDQUFDO0lBQ3RDLENBQUM7SUFFRCxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsSUFBSSxFQUFFLHFCQUFxQixDQUFDLENBQUM7SUFDeEQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFDO1FBQy9CLGFBQWEsQ0FBQyxhQUFhLEVBQUUsY0FBYyxDQUFDLENBQUM7SUFDL0MsQ0FBQztJQUVELE9BQU8sQ0FBQyxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLG1CQUFtQixFQUFFLGFBQWEsRUFBRSxlQUFlLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztBQUM5RixDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7O0dBY0c7QUFDSCxTQUFTLHFCQUFxQixDQUFDLFlBQW9CO0lBQ2pELElBQUksQ0FBQztRQUNILE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsWUFBWSxDQUFDLFlBQVksRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO1FBQ3RFLElBQUksQ0FBQyxRQUFRO1lBQUUsT0FBTztRQUN0QixPQUFPLFFBQVEsQ0FBQyxVQUFVLENBQUM7UUFDM0IsUUFBUSxDQUFDLElBQUksR0FBRyxRQUFRLENBQUM7UUFDekIsYUFBYSxDQUFDLFlBQVksRUFBRSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDeEUsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLGlGQUFpRjtJQUNuRixDQUFDO0FBQ0gsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLGVBQWUsQ0FBQyxJQUFZO0lBQzFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsR0FBRyxNQUFNLENBQUMsR0FBRyxlQUFlLEVBQUUsQ0FBQztJQUMvQyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFBRSxDQUFDLEdBQUcsTUFBTSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsY0FBYyxDQUFDLEVBQUU7UUFDbEUsR0FBRyxFQUFFLElBQUk7UUFDVCxHQUFHLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxHQUFHLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxFQUFFO1FBQ3BELEtBQUssRUFBRSxJQUFJO0tBQ1osQ0FBQyxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQm9vdHN0cmFwIGEgYnJhbmQtbmV3IGZvbGRlciBpbnRvIGEgd29ya2luZyBkYngtdG9vbHMgd29ya3NwYWNlIGJlZm9yZSBwcm9qZW4gcnVucy5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cbmltcG9ydCB7IGV4aXN0c1N5bmMsIHJlYWRGaWxlU3luYywgd3JpdGVGaWxlU3luYyB9IGZyb20gXCJub2RlOmZzXCI7XG5pbXBvcnQgeyBqb2luIH0gZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0IHsgZmlsZVVSTFRvUGF0aCB9IGZyb20gXCJub2RlOnVybFwiO1xuaW1wb3J0IHsgaW50cm8sIG91dHJvIH0gZnJvbSBcIkBjbGFjay9wcm9tcHRzXCI7XG5pbXBvcnQgeyBleGVjIH0gZnJvbSBcIkBkYngtdG9vbHMvY29yZVwiO1xuaW1wb3J0IHsganNvbiB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5pbXBvcnQgeyByZXNvbHZlUG5wbUFyZ3YsIHJ1blBucG0gfSBmcm9tIFwiLi9wbnBtXCI7XG5pbXBvcnQgeyByb290TGFiZWwgfSBmcm9tIFwiLi9yb290XCI7XG5cbi8qKiBGYWxsYmFjayB3aGVuIHRoaXMgQ0xJJ3Mgb3duIHZlcnNpb24gaXNuJ3QgYSByZWFsIHJlbGVhc2UgKGFuIGluLXJlcG8gYDAuMC4wYCkuICovXG5jb25zdCBGQUxMQkFDS19QUk9KRU5fU1BFQ0lGSUVSID0gXCJAZGJ4LXRvb2xzL3Byb2plbkBsYXRlc3RcIjtcblxuLyoqXG4gKiBJbnN0YWxsIHRoZSBlbmdpbmUgYXQgVEhJUyBDTEkncyBvd24gdmVyc2lvbi4gVGhlIHR3byBhcmUgcmVsZWFzZWQgdG9nZXRoZXIgYnlcbiAqIHRoZSByb290IGBidW1wYCwgc28gdGhlIG1hdGNoaW5nIGVuZ2luZSBhbHdheXMgZXhpc3RzIG9uIHRoZSByZWdpc3RyeS5cbiAqXG4gKiBOb3QgYEBsYXRlc3RgLCBhbmQgbm90IGEgYmFyZSBgQGRieC10b29scy9wcm9qZW5gLiBBIGJhcmUgc3BlY2lmaWVyIGNhbiBsYW5kIG9uXG4gKiBhIHN0cmF5IGAwLjAuMGAsIHdob3NlIGBeMC4wLjBgIGNhcmV0IHRoZW4gcmVhY2hlcyBubyByZWFsIHJlbGVhc2UuIGBAbGF0ZXN0YFxuICogaGFzIGEgc3VidGxlciBmYWlsdXJlOiBwbnBtIDExIGFwcGxpZXMgYSBgbWluaW11bVJlbGVhc2VBZ2VgIGRlbGF5LCBzbyBmb3IgdGhlXG4gKiBmaXJzdCBkYXkgYWZ0ZXIgYSByZWxlYXNlIGl0IGRlbGliZXJhdGVseSByZXNvbHZlcyBhIGRpc3QtdGFnIHRvIHRoZSBuZXdlc3RcbiAqIHZlcnNpb24gT0xERVIgdGhhbiB0aGUgdGhyZXNob2xkIGFuZCBtZXJlbHkgbm90ZXMgdGhlIG5ld2VyIG9uZVxuICogKGArIEBkYngtdG9vbHMvcHJvamVuIDAuMS4yNCAoMC4zLjQyIGlzIGF2YWlsYWJsZSlgKS4gQSBib290c3RyYXAgcnVuIHJpZ2h0XG4gKiBhZnRlciBhIHJlbGVhc2UgdGhlcmVmb3JlIGluc3RhbGxlZCBhIG1vbnRocy1vbGQgZW5naW5lIGFnYWluc3QgYSBjdXJyZW50IENMSSxcbiAqIHdoaWNoIGlzIGhvdyBgc3luYyAtLXdhdGNoYCBkaWVkIG9uIGFuIGVuZ2luZSBwcmVkYXRpbmcgaXRzIGBjb25jdXJyZW50bHlgXG4gKiBkZXBlbmRlbmN5LiBBbiBleHBsaWNpdCByYW5nZSBhZG1pdHMgb25seSB0aGUgdmVyc2lvbiB3ZSB3YW50LCBzbyB0aGUgYWdlXG4gKiBoZXVyaXN0aWMgaGFzIG5vdGhpbmcgb2xkZXIgdG8gZmFsbCBiYWNrIHRvLlxuICovXG5mdW5jdGlvbiBkZWZhdWx0UHJvamVuU3BlY2lmaWVyKCk6IHN0cmluZyB7XG4gIGNvbnN0IHZlcnNpb24gPSBvd25WZXJzaW9uKCk7XG4gIHJldHVybiB2ZXJzaW9uID8gYEBkYngtdG9vbHMvcHJvamVuQF4ke3ZlcnNpb259YCA6IEZBTExCQUNLX1BST0pFTl9TUEVDSUZJRVI7XG59XG5cbi8qKiBUaGlzIENMSSdzIG93biByZWxlYXNlZCB2ZXJzaW9uLCBvciBgdW5kZWZpbmVkYCBmb3IgYW4gaW4tcmVwbyBgMC4wLjBgIGJ1aWxkLiAqL1xuZnVuY3Rpb24gb3duVmVyc2lvbigpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICB0cnkge1xuICAgIGNvbnN0IG1hbmlmZXN0UGF0aCA9IGZpbGVVUkxUb1BhdGgobmV3IFVSTChcIi4uL3BhY2thZ2UuanNvblwiLCBpbXBvcnQubWV0YS51cmwpKTtcbiAgICBjb25zdCB2ZXJzaW9uID0ganNvbi5wYXJzZVJlY29yZChyZWFkRmlsZVN5bmMobWFuaWZlc3RQYXRoLCBcInV0ZjhcIikpPy52ZXJzaW9uO1xuICAgIHJldHVybiB0eXBlb2YgdmVyc2lvbiA9PT0gXCJzdHJpbmdcIiAmJiB2ZXJzaW9uICE9PSBcIjAuMC4wXCIgPyB2ZXJzaW9uIDogdW5kZWZpbmVkO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59XG5cbi8qKiBDb21wYXJlIGB4LnkuemAgdHJpcGxlczsgcmV0dXJucyA8MCwgMCwgb3IgPjAuIE1pc3NpbmcgcGFydHMgY291bnQgYXMgMC4gKi9cbmZ1bmN0aW9uIGNvbXBhcmVWZXJzaW9ucyhhOiBzdHJpbmcsIGI6IHN0cmluZyk6IG51bWJlciB7XG4gIGNvbnN0IHBhcnRzID0gKHY6IHN0cmluZykgPT4gdi5zcGxpdChcIi5cIikubWFwKChwKSA9PiBOdW1iZXIucGFyc2VJbnQocCwgMTApIHx8IDApO1xuICBjb25zdCBbeCwgeV0gPSBbcGFydHMoYSksIHBhcnRzKGIpXTtcbiAgcmV0dXJuIHhbMF0gLSB5WzBdIHx8IHhbMV0gLSB5WzFdIHx8IHhbMl0gLSB5WzJdO1xufVxuXG4vKiogVmVyc2lvbiBvZiB0aGUgZW5naW5lIGN1cnJlbnRseSBpbnN0YWxsZWQgYXQgYHJvb3RgLCBpZiBhbnkuICovXG5mdW5jdGlvbiBpbnN0YWxsZWRFbmdpbmVWZXJzaW9uKHJvb3Q6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIHRyeSB7XG4gICAgY29uc3QgbWFuaWZlc3QgPSBqb2luKHJvb3QsIFwibm9kZV9tb2R1bGVzXCIsIFwiQGRieC10b29sc1wiLCBcInByb2plblwiLCBcInBhY2thZ2UuanNvblwiKTtcbiAgICBjb25zdCB2ZXJzaW9uID0ganNvbi5wYXJzZVJlY29yZChyZWFkRmlsZVN5bmMobWFuaWZlc3QsIFwidXRmOFwiKSk/LnZlcnNpb247XG4gICAgcmV0dXJuIHR5cGVvZiB2ZXJzaW9uID09PSBcInN0cmluZ1wiID8gdmVyc2lvbiA6IHVuZGVmaW5lZDtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufVxuXG4vKipcbiAqIFVwZ3JhZGUgYW4gZXN0YWJsaXNoZWQgd29ya3NwYWNlIHdob3NlIGluc3RhbGxlZCBlbmdpbmUgcHJlZGF0ZXMgdGhpcyBDTEkuXG4gKlxuICogQm9vdHN0cmFwcGluZyBwaW5zIHRoZSBlbmdpbmUgb25jZSwgYW5kIG5vdGhpbmcgYWZ0ZXJ3YXJkcyByZXZpc2l0cyBpdCAtIHNvIGFcbiAqIHdvcmtzcGFjZSBjcmVhdGVkIG1vbnRocyBhZ28ga2VwdCByZXNvbHZpbmcgaXRzIG9yaWdpbmFsIGVuZ2luZSBubyBtYXR0ZXIgaG93XG4gKiBjdXJyZW50IHRoZSBDTEkgaW52b2tpbmcgaXQgd2FzLCBhbmQgZmFpbGVkIGluc2lkZSB0aGUgT0xEIGVuZ2luZSdzIGNvZGVcbiAqIChgc3luYyAtLXdhdGNoYCBkeWluZyBvbiBhIGBjb25jdXJyZW50bHlgIHRoYXQgZW5naW5lIG5ldmVyIGRlY2xhcmVkKS4gVGhlIHR3b1xuICogYXJlIHJlbGVhc2VkIGluIGxvY2tzdGVwLCBzbyB0aGlzIENMSSdzIHZlcnNpb24gaXMgZXhhY3RseSB0aGUgZW5naW5lIGl0XG4gKiBleHBlY3RzLlxuICpcbiAqIE9ubHkgZXZlciBtb3ZlcyBGT1JXQVJEOiBhbiBlbmdpbmUgYXQgb3IgYWhlYWQgb2YgdGhpcyBDTEkgaXMgbGVmdCBhbG9uZSwgc29cbiAqIGFuIG9sZGVyIENMSSBjYW5ub3QgZG93bmdyYWRlIGEgd29ya3NwYWNlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZW5zdXJlRW5naW5lQ3VycmVudChyb290OiBzdHJpbmcpOiB2b2lkIHtcbiAgY29uc3QgZXhwZWN0ZWQgPSBvd25WZXJzaW9uKCk7XG4gIGlmICghZXhwZWN0ZWQpIHJldHVybjtcbiAgY29uc3QgaW5zdGFsbGVkID0gaW5zdGFsbGVkRW5naW5lVmVyc2lvbihyb290KTtcbiAgaWYgKGluc3RhbGxlZCAmJiBjb21wYXJlVmVyc2lvbnMoaW5zdGFsbGVkLCBleHBlY3RlZCkgPj0gMCkgcmV0dXJuO1xuICBydW5QbnBtKFtcImFkZFwiLCBcIi1EXCIsIGRlZmF1bHRQcm9qZW5TcGVjaWZpZXIoKV0sIHJvb3QpO1xufVxuXG4vLyBSZWFjaCB0aGUgY2xhc3MgdGhyb3VnaCBpdHMgbW9kdWxlIE5BTUVTUEFDRS4gQ3VycmVudCBlbmdpbmVzIGFsc28gaG9pc3QgaXRcbi8vIGZsYXQsIGJ1dCBldmVyeSBlbmdpbmUgZXZlciBwdWJsaXNoZWQgZXhwb3J0cyB0aGUgbmFtZXNwYWNlLCBhbmQgdGhpcyB0ZW1wbGF0ZVxuLy8gaXMgcmVzb2x2ZWQgYWdhaW5zdCBgQGxhdGVzdGAgLSBhIGZsYXQgaW1wb3J0IGRpZXMgb24gYW4gb2xkZXIgb25lIHdpdGhcbi8vIFwiZG9lcyBub3QgcHJvdmlkZSBhbiBleHBvcnQgbmFtZWQgJ0RCWFRvb2xzTm9kZVByb2plY3QnXCIuXG5jb25zdCBQUk9KRU5SQ19URU1QTEFURSA9IGBpbXBvcnQgeyBwcm9qZWN0IGFzIHByb2plY3RBcGkgfSBmcm9tIFwiQGRieC10b29scy9wcm9qZW5cIjtcblxuY29uc3QgcHJvamVjdCA9IG5ldyBwcm9qZWN0QXBpLkRCWFRvb2xzTm9kZVByb2plY3QoKTtcbnByb2plY3Quc3ludGgoKTtcbmA7XG5cbi8qKiBTZWVkIGBwbnBtLXdvcmtzcGFjZS55YW1sYCBzbyB0aGUgZmlyc3QgXFxgcG5wbSBhZGRcXGAgY2FuIGFsbG93IGVzYnVpbGQgbm9uLWludGVyYWN0aXZlbHkuICovXG5jb25zdCBXT1JLU1BBQ0VfU0VFRCA9IGBwYWNrYWdlczogW11cbmFsbG93QnVpbGRzOlxuICBlc2J1aWxkOiB0cnVlXG5gO1xuXG4vKipcbiAqIFR1cm4gYSBmb2xkZXIgaW50byBhIGZ1bmN0aW9uaW5nIGRieC10b29scyB3b3Jrc3BhY2U6IGBwbnBtIGluaXRgLCBzZWVkXG4gKiBgcG5wbS13b3Jrc3BhY2UueWFtbGAsIGFkZCBgcHJvamVuYC9gdHlwZXNjcmlwdGAvYHRzeGAgKyB0aGUgZW5naW5lIHBhY2thZ2UsXG4gKiB3cml0ZSBhIG1pbmltYWwgYC5wcm9qZW5yYy50c2AsIHN5bnRoIG9uY2UgKHdpdGggYFBST0pFTl9ESVNBQkxFX1BPU1RgKSwgdGhlblxuICogaW5zdGFsbC4gRG9lcyBub3QgcnVuIGJhcnJlbHMgLSBydW4gYHBucG0gcnVuIGJhcnJlbHNgIG9yIGEgZnVsbCBwcm9qZW4gc3ludGhcbiAqIHBvc3QtaW5zdGFsbCB0byBnZW5lcmF0ZSBwYWNrYWdlIGJhcnJlbHMuXG4gKlxuICogRXZlcnkgc3RlcCBpcyBpZGVtcG90ZW50IGFuZCBzZWxmLWd1YXJkZWQsIHNvIHRoaXMgaXMgc2FmZSB0byBydW4gYWdhaW5zdCBhXG4gKiBmb2xkZXIgdGhhdCBBTFJFQURZIGhhcyBhIGhhbmQtYXV0aG9yZWQgYC5wcm9qZW5yYy50c2AgKGFuZCBldmVuIGEgY29tbWl0dGVkXG4gKiBgcGFja2FnZS5qc29uYCkgYnV0IGlzIG1pc3NpbmcgdGhlIGluc3RhbGxlZCB0b29sY2hhaW4gLSBlLmcuIGEgZnJlc2hseSBjb3BpZWRcbiAqIHByb2plY3Qgd2hvc2UgZ2VuZXJhdGVkIGZpbGVzIChpbmNsdWRpbmcgbWFuaWZlc3RzKSBhcmUgZ2l0aWdub3JlZC4gSW4gdGhhdFxuICogY2FzZSBgcG5wbSBpbml0YCBhbmQgdGhlIGAucHJvamVucmMudHNgIHNjYWZmb2xkIGFyZSBza2lwcGVkLCBidXQgdGhlIGVuZ2luZSArXG4gKiBwcm9qZW4gKyB0c3ggYXJlIChyZSlpbnN0YWxsZWQgc28gdGhlIHN1YnNlcXVlbnQgc3ludGggY2FuIHJlZ2VuZXJhdGVcbiAqIGV2ZXJ5dGhpbmcuIFNlZSB7QGxpbmsgc2VlZFRvb2xjaGFpbn0uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBib290c3RyYXBXb3Jrc3BhY2UoXG4gIHJvb3Q6IHN0cmluZyxcbiAgcHJvamVuU3BlY2lmaWVyOiBzdHJpbmcgPSBkZWZhdWx0UHJvamVuU3BlY2lmaWVyKCksXG4pOiB2b2lkIHtcbiAgaW50cm8oYEJvb3RzdHJhcHBpbmcgZGJ4LXRvb2xzIHdvcmtzcGFjZSBpbiAke3Jvb3RMYWJlbChyb290KX1gKTtcblxuICBzZWVkVG9vbGNoYWluKHJvb3QsIHByb2plblNwZWNpZmllcik7XG5cbiAgY29uc3QgcHJvamVucmMgPSBqb2luKHJvb3QsIFwiLnByb2plbnJjLnRzXCIpO1xuICBpZiAoIWV4aXN0c1N5bmMocHJvamVucmMpKSB7XG4gICAgd3JpdGVGaWxlU3luYyhwcm9qZW5yYywgUFJPSkVOUkNfVEVNUExBVEUpO1xuICB9XG5cbiAgcnVuSW5pdGlhbFN5bnRoKHJvb3QpO1xuXG4gIHJ1blBucG0oW1wiaW5zdGFsbFwiLCBcIi0tbm8tZnJvemVuLWxvY2tmaWxlXCIsIFwiLS1mb3JjZVwiXSwgcm9vdCk7XG4gIG91dHJvKFwiV29ya3NwYWNlIHJlYWR5IC0gcmUtcnVuIGRieC10b29scyBvciBhZGQgcGFja2FnZXMgdW5kZXIgcGFja2FnZXMvXCIpO1xufVxuXG4vKipcbiAqIEluc3RhbGwgdGhlIHRvb2xjaGFpbiBhIHN5bnRoIG5lZWRzIChgcHJvamVuYCwgYHR5cGVzY3JpcHRgLCBgdHN4YCwgYW5kIHRoZVxuICogZGJ4LXRvb2xzIGVuZ2luZSksIHNlZWRpbmcgYSBgcGFja2FnZS5qc29uYCBhbmQgYHBucG0td29ya3NwYWNlLnlhbWxgIGZpcnN0XG4gKiB3aGVuIGFic2VudC4gSWRlbXBvdGVudDogcnVuIGl0IHdoZW5ldmVyIHRoZSBlbmdpbmUgaXMgbWlzc2luZywgc28gYSBjb3BpZWRcbiAqIHByb2plY3Qgd2l0aCBhIGAucHJvamVucmMudHNgIGJ1dCBubyBgbm9kZV9tb2R1bGVzYC9tYW5pZmVzdHMgY2FuIGJlIGJyb3VnaHRcbiAqIHVwIHRvIGEgc3ludGgtcmVhZHkgc3RhdGUgd2l0aG91dCBmdWxsIGJvb3RzdHJhcHBpbmcuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZWVkVG9vbGNoYWluKFxuICByb290OiBzdHJpbmcsXG4gIHByb2plblNwZWNpZmllcjogc3RyaW5nID0gZGVmYXVsdFByb2plblNwZWNpZmllcigpLFxuKTogdm9pZCB7XG4gIGNvbnN0IG1hbmlmZXN0UGF0aCA9IGpvaW4ocm9vdCwgXCJwYWNrYWdlLmpzb25cIik7XG4gIGlmICghZXhpc3RzU3luYyhtYW5pZmVzdFBhdGgpKSB7XG4gICAgcnVuUG5wbShbXCJpbml0XCJdLCByb290KTtcbiAgICBub3JtYWxpemVTZWVkTWFuaWZlc3QobWFuaWZlc3RQYXRoKTtcbiAgfVxuXG4gIGNvbnN0IHdvcmtzcGFjZUZpbGUgPSBqb2luKHJvb3QsIFwicG5wbS13b3Jrc3BhY2UueWFtbFwiKTtcbiAgaWYgKCFleGlzdHNTeW5jKHdvcmtzcGFjZUZpbGUpKSB7XG4gICAgd3JpdGVGaWxlU3luYyh3b3Jrc3BhY2VGaWxlLCBXT1JLU1BBQ0VfU0VFRCk7XG4gIH1cblxuICBydW5QbnBtKFtcImFkZFwiLCBcIi1EXCIsIFwicHJvamVuXCIsIFwidHlwZXNjcmlwdEBeNS45LjNcIiwgXCJ0c3hAXjQuMjMuMFwiLCBwcm9qZW5TcGVjaWZpZXJdLCByb290KTtcbn1cblxuLyoqXG4gKiBNYWtlIHdoYXQgYHBucG0gaW5pdGAgcHJvZHVjZWQgc2FmZSB0byBzeW50aCBhZ2FpbnN0LiBUd28gY29ycmVjdGlvbnMsIGJvdGhcbiAqIGJlY2F1c2UgdGhhdCBvdXRwdXQgdmFyaWVzIGJ5IHBucG0gdmVyc2lvbjpcbiAqXG4gKiAgIC0gZHJvcCBgZGV2RW5naW5lc2AsIHdoaWNoIHBucG0gMTEgc2VlZHMgYXMgYHBhY2thZ2VNYW5hZ2VyOiB7IG5hbWU6IFwicG5wbVwiLFxuICogICAgIG9uRmFpbDogXCJkb3dubG9hZFwiIH1gLiBBbnkgbnBtLWJhc2VkIHRvb2wgbGF0ZXIgaW4gdGhlIGNoYWluIChhblxuICogICAgIGBucHhgL2RseCBmYWxsYmFjaykgdGhlbiByZWZ1c2VzIHdpdGggRUJBRERFVkVOR0lORVMsIGl0cyBydW5uZXIgYmVpbmcgbnBtO1xuICogICAtIGZvcmNlIGB0eXBlOiBcIm1vZHVsZVwiYCwgd2hpY2ggcG5wbSAxMSB3cml0ZXMgYW5kIHBucG0gMTAgZG9lcyBub3QuIHRzeFxuICogICAgIHBpY2tzIHRoZSBlbnRyeSdzIGZvcm1hdCBmcm9tIHRoZSBuZWFyZXN0IG1hbmlmZXN0LCBzbyB3aXRob3V0IGl0XG4gKiAgICAgYC5wcm9qZW5yYy50c2AgbG9hZHMgYXMgQ0pTIGFuZCB0aGUgZmlyc3QgZGVwZW5kZW5jeSB1c2luZyB0b3AtbGV2ZWwgYXdhaXRcbiAqICAgICBkaWVzIG9uIFwibm90IHN1cHBvcnRlZCB3aXRoIHRoZSBjanMgb3V0cHV0IGZvcm1hdFwiLlxuICpcbiAqIHByb2plbiByZWdlbmVyYXRlcyB0aGUgd2hvbGUgbWFuaWZlc3QgYXQgc3ludGgsIHNvIHRoaXMgb25seSBoYXMgdG8gaG9sZCB0aGVcbiAqIHNlZWQgdG9nZXRoZXIgbG9uZyBlbm91Z2ggdG8gZ2V0IHRoZXJlLlxuICovXG5mdW5jdGlvbiBub3JtYWxpemVTZWVkTWFuaWZlc3QobWFuaWZlc3RQYXRoOiBzdHJpbmcpOiB2b2lkIHtcbiAgdHJ5IHtcbiAgICBjb25zdCBtYW5pZmVzdCA9IGpzb24ucGFyc2VSZWNvcmQocmVhZEZpbGVTeW5jKG1hbmlmZXN0UGF0aCwgXCJ1dGY4XCIpKTtcbiAgICBpZiAoIW1hbmlmZXN0KSByZXR1cm47XG4gICAgZGVsZXRlIG1hbmlmZXN0LmRldkVuZ2luZXM7XG4gICAgbWFuaWZlc3QudHlwZSA9IFwibW9kdWxlXCI7XG4gICAgd3JpdGVGaWxlU3luYyhtYW5pZmVzdFBhdGgsIGAke0pTT04uc3RyaW5naWZ5KG1hbmlmZXN0LCBudWxsLCAyKX1cXG5gKTtcbiAgfSBjYXRjaCB7XG4gICAgLy8gQSBtYWxmb3JtZWQvYWJzZW50IG1hbmlmZXN0IGhlcmUganVzdCBtZWFucyB0aGUgbGF0ZXIgYHBucG0gYWRkYCByZWNyZWF0ZXMgaXQuXG4gIH1cbn1cblxuLyoqXG4gKiBSdW4gdGhlIGluaXRpYWwgc3ludGggYnkgZXhlY3V0aW5nIGAucHJvamVucmMudHNgIGRpcmVjdGx5IHdpdGggdHN4ICh3aXRoXG4gKiBgUFJPSkVOX0RJU0FCTEVfUE9TVGAgc2V0KSwgTk9UIGBwcm9qZW4gPHRhc2s+YC4gVXNlIHJpZ2h0IGFmdGVyIHNlZWRpbmcgYVxuICogZnJlc2ggd29ya3NwYWNlOiB0aGUgcHJvamVuIFRBU0tTIChgc3luY2AsIGBiYXJyZWxzYCwgLi4uKSBvbmx5IGV4aXN0IG9uY2VcbiAqIGAucHJvamVucmMudHNgIGhhcyBydW4gb25jZSwgc28gYHByb2plbiBzeW5jYCBjYW4ndCBiZSB0aGUgYm9vdHN0cmFwcGluZyBzdGVwLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcnVuSW5pdGlhbFN5bnRoKHJvb3Q6IHN0cmluZyk6IHZvaWQge1xuICBjb25zdCBbY29tbWFuZCwgLi4ucHJlZml4XSA9IHJlc29sdmVQbnBtQXJndigpO1xuICBleGVjLnNwYXduU3luYyhjb21tYW5kLCBbLi4ucHJlZml4LCBcImV4ZWNcIiwgXCJ0c3hcIiwgXCIucHJvamVucmMudHNcIl0sIHtcbiAgICBjd2Q6IHJvb3QsXG4gICAgZW52OiB7IC4uLnByb2Nlc3MuZW52LCBQUk9KRU5fRElTQUJMRV9QT1NUOiBcInRydWVcIiB9LFxuICAgIGNoZWNrOiB0cnVlLFxuICB9KTtcbn1cbiJdfQ==
@@ -0,0 +1,2 @@
1
+ /** Parse `argv` with commander and forward remaining args to projen. */
2
+ export declare function runCli(argv: string[]): Promise<void>;
package/lib/src/cli.js ADDED
@@ -0,0 +1,52 @@
1
+ /**
2
+ * `dbx-tools` commander entry: detect root, bootstrap or install, forward to projen.
3
+ *
4
+ * @module
5
+ */
6
+ import { Command } from "commander";
7
+ import { bootstrapWorkspace, ensureEngineCurrent, runInitialSynth, seedToolchain, } from "./bootstrap.js";
8
+ import { ensureWorkspaceReady, runPnpm, runProjen } from "./pnpm.js";
9
+ import { findWorkspaceRoot, needsBootstrap, needsToolchain } from "./root.js";
10
+ /**
11
+ * Prepare the workspace at `root`, then run `pnpm exec projen` with `projenArgs`.
12
+ *
13
+ * Three cases, in order:
14
+ * - no `.projenrc.ts` at all -> full bootstrap (scaffold + install + synth),
15
+ * which already runs the initial synth; nothing more to forward.
16
+ * - a `.projenrc.ts` but the engine/toolchain isn't installed (e.g. a freshly
17
+ * copied project whose generated files + manifests are gitignored) -> seed
18
+ * the toolchain, then run the INITIAL synth directly (the projen tasks the
19
+ * args would name, like `sync`, don't exist until `.projenrc.ts` has run
20
+ * once), and install. Don't forward `projenArgs` - the synth is the work.
21
+ * - otherwise (established workspace) -> ensure deps, bring the engine up to
22
+ * this CLI's version, then forward to projen.
23
+ */
24
+ async function prepareAndRunProjen(projenArgs, startDir) {
25
+ const root = await findWorkspaceRoot(startDir);
26
+ if (needsBootstrap(root)) {
27
+ bootstrapWorkspace(root);
28
+ return;
29
+ }
30
+ if (needsToolchain(root)) {
31
+ seedToolchain(root);
32
+ runInitialSynth(root);
33
+ runPnpm(["install", "--no-frozen-lockfile", "--force"], root);
34
+ return;
35
+ }
36
+ ensureWorkspaceReady(root);
37
+ ensureEngineCurrent(root);
38
+ runProjen(projenArgs, root);
39
+ }
40
+ /** Parse `argv` with commander and forward remaining args to projen. */
41
+ export async function runCli(argv) {
42
+ const program = new Command()
43
+ .name("dbx-tools")
44
+ .description("Bootstrap dbx-tools workspaces and forward to projen")
45
+ .allowUnknownOption()
46
+ .allowExcessArguments()
47
+ .showHelpAfterError()
48
+ .helpOption("-h, --help", "Show dbx-tools help");
49
+ program.parse(argv);
50
+ await prepareAndRunProjen(program.args);
51
+ }
52
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NsaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHO0FBQ0gsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNwQyxPQUFPLEVBQ0wsa0JBQWtCLEVBQ2xCLG1CQUFtQixFQUNuQixlQUFlLEVBQ2YsYUFBYSxHQUNkLE1BQU0sYUFBYSxDQUFDO0FBQ3JCLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBQ2xFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxjQUFjLEVBQUUsY0FBYyxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBRTNFOzs7Ozs7Ozs7Ozs7O0dBYUc7QUFDSCxLQUFLLFVBQVUsbUJBQW1CLENBQUMsVUFBb0IsRUFBRSxRQUFpQjtJQUN4RSxNQUFNLElBQUksR0FBRyxNQUFNLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQy9DLElBQUksY0FBYyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7UUFDekIsa0JBQWtCLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDekIsT0FBTztJQUNULENBQUM7SUFDRCxJQUFJLGNBQWMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQ3pCLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNwQixlQUFlLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDdEIsT0FBTyxDQUFDLENBQUMsU0FBUyxFQUFFLHNCQUFzQixFQUFFLFNBQVMsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQzlELE9BQU87SUFDVCxDQUFDO0lBQ0Qsb0JBQW9CLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDM0IsbUJBQW1CLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDMUIsU0FBUyxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsQ0FBQztBQUM5QixDQUFDO0FBRUQsd0VBQXdFO0FBQ3hFLE1BQU0sQ0FBQyxLQUFLLFVBQVUsTUFBTSxDQUFDLElBQWM7SUFDekMsTUFBTSxPQUFPLEdBQUcsSUFBSSxPQUFPLEVBQUU7U0FDMUIsSUFBSSxDQUFDLFdBQVcsQ0FBQztTQUNqQixXQUFXLENBQUMsc0RBQXNELENBQUM7U0FDbkUsa0JBQWtCLEVBQUU7U0FDcEIsb0JBQW9CLEVBQUU7U0FDdEIsa0JBQWtCLEVBQUU7U0FDcEIsVUFBVSxDQUFDLFlBQVksRUFBRSxxQkFBcUIsQ0FBQyxDQUFDO0lBRW5ELE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDcEIsTUFBTSxtQkFBbUIsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDMUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogYGRieC10b29sc2AgY29tbWFuZGVyIGVudHJ5OiBkZXRlY3Qgcm9vdCwgYm9vdHN0cmFwIG9yIGluc3RhbGwsIGZvcndhcmQgdG8gcHJvamVuLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuaW1wb3J0IHsgQ29tbWFuZCB9IGZyb20gXCJjb21tYW5kZXJcIjtcbmltcG9ydCB7XG4gIGJvb3RzdHJhcFdvcmtzcGFjZSxcbiAgZW5zdXJlRW5naW5lQ3VycmVudCxcbiAgcnVuSW5pdGlhbFN5bnRoLFxuICBzZWVkVG9vbGNoYWluLFxufSBmcm9tIFwiLi9ib290c3RyYXBcIjtcbmltcG9ydCB7IGVuc3VyZVdvcmtzcGFjZVJlYWR5LCBydW5QbnBtLCBydW5Qcm9qZW4gfSBmcm9tIFwiLi9wbnBtXCI7XG5pbXBvcnQgeyBmaW5kV29ya3NwYWNlUm9vdCwgbmVlZHNCb290c3RyYXAsIG5lZWRzVG9vbGNoYWluIH0gZnJvbSBcIi4vcm9vdFwiO1xuXG4vKipcbiAqIFByZXBhcmUgdGhlIHdvcmtzcGFjZSBhdCBgcm9vdGAsIHRoZW4gcnVuIGBwbnBtIGV4ZWMgcHJvamVuYCB3aXRoIGBwcm9qZW5BcmdzYC5cbiAqXG4gKiBUaHJlZSBjYXNlcywgaW4gb3JkZXI6XG4gKiAgIC0gbm8gYC5wcm9qZW5yYy50c2AgYXQgYWxsIC0+IGZ1bGwgYm9vdHN0cmFwIChzY2FmZm9sZCArIGluc3RhbGwgKyBzeW50aCksXG4gKiAgICAgd2hpY2ggYWxyZWFkeSBydW5zIHRoZSBpbml0aWFsIHN5bnRoOyBub3RoaW5nIG1vcmUgdG8gZm9yd2FyZC5cbiAqICAgLSBhIGAucHJvamVucmMudHNgIGJ1dCB0aGUgZW5naW5lL3Rvb2xjaGFpbiBpc24ndCBpbnN0YWxsZWQgKGUuZy4gYSBmcmVzaGx5XG4gKiAgICAgY29waWVkIHByb2plY3Qgd2hvc2UgZ2VuZXJhdGVkIGZpbGVzICsgbWFuaWZlc3RzIGFyZSBnaXRpZ25vcmVkKSAtPiBzZWVkXG4gKiAgICAgdGhlIHRvb2xjaGFpbiwgdGhlbiBydW4gdGhlIElOSVRJQUwgc3ludGggZGlyZWN0bHkgKHRoZSBwcm9qZW4gdGFza3MgdGhlXG4gKiAgICAgYXJncyB3b3VsZCBuYW1lLCBsaWtlIGBzeW5jYCwgZG9uJ3QgZXhpc3QgdW50aWwgYC5wcm9qZW5yYy50c2AgaGFzIHJ1blxuICogICAgIG9uY2UpLCBhbmQgaW5zdGFsbC4gRG9uJ3QgZm9yd2FyZCBgcHJvamVuQXJnc2AgLSB0aGUgc3ludGggaXMgdGhlIHdvcmsuXG4gKiAgIC0gb3RoZXJ3aXNlIChlc3RhYmxpc2hlZCB3b3Jrc3BhY2UpIC0+IGVuc3VyZSBkZXBzLCBicmluZyB0aGUgZW5naW5lIHVwIHRvXG4gKiAgICAgdGhpcyBDTEkncyB2ZXJzaW9uLCB0aGVuIGZvcndhcmQgdG8gcHJvamVuLlxuICovXG5hc3luYyBmdW5jdGlvbiBwcmVwYXJlQW5kUnVuUHJvamVuKHByb2plbkFyZ3M6IHN0cmluZ1tdLCBzdGFydERpcj86IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCByb290ID0gYXdhaXQgZmluZFdvcmtzcGFjZVJvb3Qoc3RhcnREaXIpO1xuICBpZiAobmVlZHNCb290c3RyYXAocm9vdCkpIHtcbiAgICBib290c3RyYXBXb3Jrc3BhY2Uocm9vdCk7XG4gICAgcmV0dXJuO1xuICB9XG4gIGlmIChuZWVkc1Rvb2xjaGFpbihyb290KSkge1xuICAgIHNlZWRUb29sY2hhaW4ocm9vdCk7XG4gICAgcnVuSW5pdGlhbFN5bnRoKHJvb3QpO1xuICAgIHJ1blBucG0oW1wiaW5zdGFsbFwiLCBcIi0tbm8tZnJvemVuLWxvY2tmaWxlXCIsIFwiLS1mb3JjZVwiXSwgcm9vdCk7XG4gICAgcmV0dXJuO1xuICB9XG4gIGVuc3VyZVdvcmtzcGFjZVJlYWR5KHJvb3QpO1xuICBlbnN1cmVFbmdpbmVDdXJyZW50KHJvb3QpO1xuICBydW5Qcm9qZW4ocHJvamVuQXJncywgcm9vdCk7XG59XG5cbi8qKiBQYXJzZSBgYXJndmAgd2l0aCBjb21tYW5kZXIgYW5kIGZvcndhcmQgcmVtYWluaW5nIGFyZ3MgdG8gcHJvamVuLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJ1bkNsaShhcmd2OiBzdHJpbmdbXSk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBwcm9ncmFtID0gbmV3IENvbW1hbmQoKVxuICAgIC5uYW1lKFwiZGJ4LXRvb2xzXCIpXG4gICAgLmRlc2NyaXB0aW9uKFwiQm9vdHN0cmFwIGRieC10b29scyB3b3Jrc3BhY2VzIGFuZCBmb3J3YXJkIHRvIHByb2plblwiKVxuICAgIC5hbGxvd1Vua25vd25PcHRpb24oKVxuICAgIC5hbGxvd0V4Y2Vzc0FyZ3VtZW50cygpXG4gICAgLnNob3dIZWxwQWZ0ZXJFcnJvcigpXG4gICAgLmhlbHBPcHRpb24oXCItaCwgLS1oZWxwXCIsIFwiU2hvdyBkYngtdG9vbHMgaGVscFwiKTtcblxuICBwcm9ncmFtLnBhcnNlKGFyZ3YpO1xuICBhd2FpdCBwcmVwYXJlQW5kUnVuUHJvamVuKHByb2dyYW0uYXJncyk7XG59XG4iXX0=
@@ -0,0 +1,8 @@
1
+ /** Memoized `[command, ...prefix]` argv prefix to run pnpm (resolved install, else corepack, else npx). */
2
+ export declare const resolvePnpmArgv: () => string[];
3
+ /** Run pnpm with inherited stdio from `cwd`. */
4
+ export declare function runPnpm(args: string[], cwd: string): void;
5
+ /** Install workspace dependencies when `node_modules` or projen is missing. */
6
+ export declare function ensureWorkspaceReady(root: string): void;
7
+ /** Run `pnpm exec projen` with the given args from `root`. */
8
+ export declare function runProjen(args: string[], root: string): void;
@@ -0,0 +1,81 @@
1
+ /**
2
+ * pnpm discovery, workspace install, and projen forwarding for the `dbx-tools` CLI.
3
+ *
4
+ * @module
5
+ */
6
+ import { createRequire } from "node:module";
7
+ import { dirname, join } from "node:path";
8
+ import { exec } from "@dbx-tools/core";
9
+ import { functionModule } from "@dbx-tools/shared-core";
10
+ import { needsInstall } from "./root.js";
11
+ /** True when `pnpm --version` runs, i.e. pnpm is already on PATH. */
12
+ function pnpmOnPath() {
13
+ try {
14
+ exec.spawnSync("pnpm", ["--version"], {
15
+ stderr: "ignore",
16
+ stdin: "ignore",
17
+ stdout: "ignore",
18
+ check: true,
19
+ });
20
+ return true;
21
+ }
22
+ catch {
23
+ return false;
24
+ }
25
+ }
26
+ function resolvePnpmArgvImpl() {
27
+ // 1. A resolvable `pnpm` dependency (the normal in-workspace case): run its
28
+ // bin directly with the current node - no PATH or package-manager shim.
29
+ try {
30
+ const require = createRequire(import.meta.url);
31
+ const pkgJsonPath = require.resolve("pnpm/package.json");
32
+ const pkg = require(pkgJsonPath);
33
+ const bin = typeof pkg.bin === "string" ? pkg.bin : pkg.bin.pnpm;
34
+ return [process.execPath, join(dirname(pkgJsonPath), bin)];
35
+ }
36
+ catch {
37
+ // fall through
38
+ }
39
+ // 2. A bare `pnpm` already on PATH (e.g. running under `pnpm dlx`). Prefer
40
+ // this over the corepack/npx fallbacks so we never shell through npm -
41
+ // `npx -y pnpm` runs under npm, which rejects a bootstrapped
42
+ // `devEngines.packageManager: pnpm` manifest with EBADDEVENGINES.
43
+ if (pnpmOnPath())
44
+ return ["pnpm"];
45
+ // 3. Try to enable pnpm via corepack, then use it.
46
+ try {
47
+ exec.spawnSync("corepack", ["enable", "pnpm"], {
48
+ stderr: "ignore",
49
+ stdin: "ignore",
50
+ stdout: "ignore",
51
+ check: true,
52
+ });
53
+ if (pnpmOnPath())
54
+ return ["pnpm"];
55
+ }
56
+ catch {
57
+ // fall through
58
+ }
59
+ // 4. Last resort: fetch pnpm on demand via npx. Pass `--engine-strict=false`
60
+ // (and skip npm's devEngines gate) so npm doesn't refuse to run just
61
+ // because the target manifest declares `devEngines.packageManager: pnpm`.
62
+ return ["npx", "-y", "--engine-strict=false", "pnpm"];
63
+ }
64
+ /** Memoized `[command, ...prefix]` argv prefix to run pnpm (resolved install, else corepack, else npx). */
65
+ export const resolvePnpmArgv = functionModule.memoize(resolvePnpmArgvImpl);
66
+ /** Run pnpm with inherited stdio from `cwd`. */
67
+ export function runPnpm(args, cwd) {
68
+ const [command, ...prefix] = resolvePnpmArgv();
69
+ exec.spawnSync(command, [...prefix, ...args], { cwd, check: true });
70
+ }
71
+ /** Install workspace dependencies when `node_modules` or projen is missing. */
72
+ export function ensureWorkspaceReady(root) {
73
+ if (needsInstall(root)) {
74
+ runPnpm(["install", "--no-frozen-lockfile"], root);
75
+ }
76
+ }
77
+ /** Run `pnpm exec projen` with the given args from `root`. */
78
+ export function runProjen(args, root) {
79
+ runPnpm(["exec", "projen", ...args], root);
80
+ }
81
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG5wbS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wbnBtLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7O0dBSUc7QUFDSCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQzVDLE9BQU8sRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQzFDLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN2QyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDeEQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLFFBQVEsQ0FBQztBQUt0QyxxRUFBcUU7QUFDckUsU0FBUyxVQUFVO0lBQ2pCLElBQUksQ0FBQztRQUNILElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLENBQUMsV0FBVyxDQUFDLEVBQUU7WUFDcEMsTUFBTSxFQUFFLFFBQVE7WUFDaEIsS0FBSyxFQUFFLFFBQVE7WUFDZixNQUFNLEVBQUUsUUFBUTtZQUNoQixLQUFLLEVBQUUsSUFBSTtTQUNaLENBQUMsQ0FBQztRQUNILE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztBQUNILENBQUM7QUFFRCxTQUFTLG1CQUFtQjtJQUMxQiw0RUFBNEU7SUFDNUUsMkVBQTJFO0lBQzNFLElBQUksQ0FBQztRQUNILE1BQU0sT0FBTyxHQUFHLGFBQWEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQy9DLE1BQU0sV0FBVyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUN6RCxNQUFNLEdBQUcsR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFzQixDQUFDO1FBQ3RELE1BQU0sR0FBRyxHQUFHLE9BQU8sR0FBRyxDQUFDLEdBQUcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDO1FBQ2pFLE9BQU8sQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUM3RCxDQUFDO0lBQUMsTUFBTSxDQUFDO1FBQ1AsZUFBZTtJQUNqQixDQUFDO0lBRUQsMkVBQTJFO0lBQzNFLDBFQUEwRTtJQUMxRSxnRUFBZ0U7SUFDaEUscUVBQXFFO0lBQ3JFLElBQUksVUFBVSxFQUFFO1FBQUUsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRWxDLG1EQUFtRDtJQUNuRCxJQUFJLENBQUM7UUFDSCxJQUFJLENBQUMsU0FBUyxDQUFDLFVBQVUsRUFBRSxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsRUFBRTtZQUM3QyxNQUFNLEVBQUUsUUFBUTtZQUNoQixLQUFLLEVBQUUsUUFBUTtZQUNmLE1BQU0sRUFBRSxRQUFRO1lBQ2hCLEtBQUssRUFBRSxJQUFJO1NBQ1osQ0FBQyxDQUFDO1FBQ0gsSUFBSSxVQUFVLEVBQUU7WUFBRSxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDcEMsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLGVBQWU7SUFDakIsQ0FBQztJQUVELDZFQUE2RTtJQUM3RSx3RUFBd0U7SUFDeEUsNkVBQTZFO0lBQzdFLE9BQU8sQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLHVCQUF1QixFQUFFLE1BQU0sQ0FBQyxDQUFDO0FBQ3hELENBQUM7QUFFRCwyR0FBMkc7QUFDM0csTUFBTSxDQUFDLE1BQU0sZUFBZSxHQUFHLGNBQWMsQ0FBQyxPQUFPLENBQUMsbUJBQW1CLENBQUMsQ0FBQztBQUUzRSxnREFBZ0Q7QUFDaEQsTUFBTSxVQUFVLE9BQU8sQ0FBQyxJQUFjLEVBQUUsR0FBVztJQUNqRCxNQUFNLENBQUMsT0FBTyxFQUFFLEdBQUcsTUFBTSxDQUFDLEdBQUcsZUFBZSxFQUFFLENBQUM7SUFDL0MsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxHQUFHLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxFQUFFLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0FBQ3RFLENBQUM7QUFFRCwrRUFBK0U7QUFDL0UsTUFBTSxVQUFVLG9CQUFvQixDQUFDLElBQVk7SUFDL0MsSUFBSSxZQUFZLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztRQUN2QixPQUFPLENBQUMsQ0FBQyxTQUFTLEVBQUUsc0JBQXNCLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNyRCxDQUFDO0FBQ0gsQ0FBQztBQUVELDhEQUE4RDtBQUM5RCxNQUFNLFVBQVUsU0FBUyxDQUFDLElBQWMsRUFBRSxJQUFZO0lBQ3BELE9BQU8sQ0FBQyxDQUFDLE1BQU0sRUFBRSxRQUFRLEVBQUUsR0FBRyxJQUFJLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztBQUM3QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBwbnBtIGRpc2NvdmVyeSwgd29ya3NwYWNlIGluc3RhbGwsIGFuZCBwcm9qZW4gZm9yd2FyZGluZyBmb3IgdGhlIGBkYngtdG9vbHNgIENMSS5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cbmltcG9ydCB7IGNyZWF0ZVJlcXVpcmUgfSBmcm9tIFwibm9kZTptb2R1bGVcIjtcbmltcG9ydCB7IGRpcm5hbWUsIGpvaW4gfSBmcm9tIFwibm9kZTpwYXRoXCI7XG5pbXBvcnQgeyBleGVjIH0gZnJvbSBcIkBkYngtdG9vbHMvY29yZVwiO1xuaW1wb3J0IHsgZnVuY3Rpb25Nb2R1bGUgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHsgbmVlZHNJbnN0YWxsIH0gZnJvbSBcIi4vcm9vdFwiO1xuXG4vKiogQSBwYWNrYWdlLmpzb24gYGJpbmAgZmllbGQ6IGVpdGhlciBhIHNpbmdsZSBjb21tYW5kIHN0cmluZywgb3IgYSBuYW1lIC0+IHBhdGggbWFwLiAqL1xudHlwZSBCaW5GaWVsZCA9IHN0cmluZyB8IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG5cbi8qKiBUcnVlIHdoZW4gYHBucG0gLS12ZXJzaW9uYCBydW5zLCBpLmUuIHBucG0gaXMgYWxyZWFkeSBvbiBQQVRILiAqL1xuZnVuY3Rpb24gcG5wbU9uUGF0aCgpOiBib29sZWFuIHtcbiAgdHJ5IHtcbiAgICBleGVjLnNwYXduU3luYyhcInBucG1cIiwgW1wiLS12ZXJzaW9uXCJdLCB7XG4gICAgICBzdGRlcnI6IFwiaWdub3JlXCIsXG4gICAgICBzdGRpbjogXCJpZ25vcmVcIixcbiAgICAgIHN0ZG91dDogXCJpZ25vcmVcIixcbiAgICAgIGNoZWNrOiB0cnVlLFxuICAgIH0pO1xuICAgIHJldHVybiB0cnVlO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVBucG1Bcmd2SW1wbCgpOiBzdHJpbmdbXSB7XG4gIC8vIDEuIEEgcmVzb2x2YWJsZSBgcG5wbWAgZGVwZW5kZW5jeSAodGhlIG5vcm1hbCBpbi13b3Jrc3BhY2UgY2FzZSk6IHJ1biBpdHNcbiAgLy8gICAgYmluIGRpcmVjdGx5IHdpdGggdGhlIGN1cnJlbnQgbm9kZSAtIG5vIFBBVEggb3IgcGFja2FnZS1tYW5hZ2VyIHNoaW0uXG4gIHRyeSB7XG4gICAgY29uc3QgcmVxdWlyZSA9IGNyZWF0ZVJlcXVpcmUoaW1wb3J0Lm1ldGEudXJsKTtcbiAgICBjb25zdCBwa2dKc29uUGF0aCA9IHJlcXVpcmUucmVzb2x2ZShcInBucG0vcGFja2FnZS5qc29uXCIpO1xuICAgIGNvbnN0IHBrZyA9IHJlcXVpcmUocGtnSnNvblBhdGgpIGFzIHsgYmluOiBCaW5GaWVsZCB9O1xuICAgIGNvbnN0IGJpbiA9IHR5cGVvZiBwa2cuYmluID09PSBcInN0cmluZ1wiID8gcGtnLmJpbiA6IHBrZy5iaW4ucG5wbTtcbiAgICByZXR1cm4gW3Byb2Nlc3MuZXhlY1BhdGgsIGpvaW4oZGlybmFtZShwa2dKc29uUGF0aCksIGJpbildO1xuICB9IGNhdGNoIHtcbiAgICAvLyBmYWxsIHRocm91Z2hcbiAgfVxuXG4gIC8vIDIuIEEgYmFyZSBgcG5wbWAgYWxyZWFkeSBvbiBQQVRIIChlLmcuIHJ1bm5pbmcgdW5kZXIgYHBucG0gZGx4YCkuIFByZWZlclxuICAvLyAgICB0aGlzIG92ZXIgdGhlIGNvcmVwYWNrL25weCBmYWxsYmFja3Mgc28gd2UgbmV2ZXIgc2hlbGwgdGhyb3VnaCBucG0gLVxuICAvLyAgICBgbnB4IC15IHBucG1gIHJ1bnMgdW5kZXIgbnBtLCB3aGljaCByZWplY3RzIGEgYm9vdHN0cmFwcGVkXG4gIC8vICAgIGBkZXZFbmdpbmVzLnBhY2thZ2VNYW5hZ2VyOiBwbnBtYCBtYW5pZmVzdCB3aXRoIEVCQURERVZFTkdJTkVTLlxuICBpZiAocG5wbU9uUGF0aCgpKSByZXR1cm4gW1wicG5wbVwiXTtcblxuICAvLyAzLiBUcnkgdG8gZW5hYmxlIHBucG0gdmlhIGNvcmVwYWNrLCB0aGVuIHVzZSBpdC5cbiAgdHJ5IHtcbiAgICBleGVjLnNwYXduU3luYyhcImNvcmVwYWNrXCIsIFtcImVuYWJsZVwiLCBcInBucG1cIl0sIHtcbiAgICAgIHN0ZGVycjogXCJpZ25vcmVcIixcbiAgICAgIHN0ZGluOiBcImlnbm9yZVwiLFxuICAgICAgc3Rkb3V0OiBcImlnbm9yZVwiLFxuICAgICAgY2hlY2s6IHRydWUsXG4gICAgfSk7XG4gICAgaWYgKHBucG1PblBhdGgoKSkgcmV0dXJuIFtcInBucG1cIl07XG4gIH0gY2F0Y2gge1xuICAgIC8vIGZhbGwgdGhyb3VnaFxuICB9XG5cbiAgLy8gNC4gTGFzdCByZXNvcnQ6IGZldGNoIHBucG0gb24gZGVtYW5kIHZpYSBucHguIFBhc3MgYC0tZW5naW5lLXN0cmljdD1mYWxzZWBcbiAgLy8gICAgKGFuZCBza2lwIG5wbSdzIGRldkVuZ2luZXMgZ2F0ZSkgc28gbnBtIGRvZXNuJ3QgcmVmdXNlIHRvIHJ1biBqdXN0XG4gIC8vICAgIGJlY2F1c2UgdGhlIHRhcmdldCBtYW5pZmVzdCBkZWNsYXJlcyBgZGV2RW5naW5lcy5wYWNrYWdlTWFuYWdlcjogcG5wbWAuXG4gIHJldHVybiBbXCJucHhcIiwgXCIteVwiLCBcIi0tZW5naW5lLXN0cmljdD1mYWxzZVwiLCBcInBucG1cIl07XG59XG5cbi8qKiBNZW1vaXplZCBgW2NvbW1hbmQsIC4uLnByZWZpeF1gIGFyZ3YgcHJlZml4IHRvIHJ1biBwbnBtIChyZXNvbHZlZCBpbnN0YWxsLCBlbHNlIGNvcmVwYWNrLCBlbHNlIG5weCkuICovXG5leHBvcnQgY29uc3QgcmVzb2x2ZVBucG1Bcmd2ID0gZnVuY3Rpb25Nb2R1bGUubWVtb2l6ZShyZXNvbHZlUG5wbUFyZ3ZJbXBsKTtcblxuLyoqIFJ1biBwbnBtIHdpdGggaW5oZXJpdGVkIHN0ZGlvIGZyb20gYGN3ZGAuICovXG5leHBvcnQgZnVuY3Rpb24gcnVuUG5wbShhcmdzOiBzdHJpbmdbXSwgY3dkOiBzdHJpbmcpOiB2b2lkIHtcbiAgY29uc3QgW2NvbW1hbmQsIC4uLnByZWZpeF0gPSByZXNvbHZlUG5wbUFyZ3YoKTtcbiAgZXhlYy5zcGF3blN5bmMoY29tbWFuZCwgWy4uLnByZWZpeCwgLi4uYXJnc10sIHsgY3dkLCBjaGVjazogdHJ1ZSB9KTtcbn1cblxuLyoqIEluc3RhbGwgd29ya3NwYWNlIGRlcGVuZGVuY2llcyB3aGVuIGBub2RlX21vZHVsZXNgIG9yIHByb2plbiBpcyBtaXNzaW5nLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVuc3VyZVdvcmtzcGFjZVJlYWR5KHJvb3Q6IHN0cmluZyk6IHZvaWQge1xuICBpZiAobmVlZHNJbnN0YWxsKHJvb3QpKSB7XG4gICAgcnVuUG5wbShbXCJpbnN0YWxsXCIsIFwiLS1uby1mcm96ZW4tbG9ja2ZpbGVcIl0sIHJvb3QpO1xuICB9XG59XG5cbi8qKiBSdW4gYHBucG0gZXhlYyBwcm9qZW5gIHdpdGggdGhlIGdpdmVuIGFyZ3MgZnJvbSBgcm9vdGAuICovXG5leHBvcnQgZnVuY3Rpb24gcnVuUHJvamVuKGFyZ3M6IHN0cmluZ1tdLCByb290OiBzdHJpbmcpOiB2b2lkIHtcbiAgcnVuUG5wbShbXCJleGVjXCIsIFwicHJvamVuXCIsIC4uLmFyZ3NdLCByb290KTtcbn1cbiJdfQ==
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Walk upward from `startDir` for `.projenrc.ts`. If none is found, try git
3
+ * top-level only when that directory also contains `.projenrc.ts`; otherwise return
4
+ * `resolve(startDir)` (which may not be a workspace root).
5
+ */
6
+ export declare function findWorkspaceRoot(startDir?: string): Promise<string>;
7
+ /**
8
+ * True when the folder has no `.projenrc.ts` yet and needs full bootstrapping.
9
+ * Keying off `.projenrc.ts` (not `package.json`) avoids clobbering a cleaned
10
+ * workspace that still has a hand-authored projenrc.
11
+ */
12
+ export declare function needsBootstrap(root: string): boolean;
13
+ /** True when `node_modules` or projen itself is missing under `root`. */
14
+ export declare function needsInstall(root: string): boolean;
15
+ /**
16
+ * True when the synth TOOLCHAIN isn't installed yet: no `node_modules`, or the
17
+ * dbx-tools engine / `projen` aren't resolvable under it. Distinct from a full
18
+ * bootstrap (which keys off a MISSING `.projenrc.ts`): here the projenrc exists
19
+ * but its dependencies don't - e.g. a copied project whose generated manifests
20
+ * and `node_modules` are gitignored. Seeding the toolchain (not scaffolding)
21
+ * makes it synth-ready without touching the hand-authored `.projenrc.ts`.
22
+ */
23
+ export declare function needsToolchain(root: string): boolean;
24
+ /** Async, memoized root lookup from the process cwd at first use. */
25
+ export declare const workspaceRoot: () => Promise<string>;
26
+ /** Short label for log output (`basename` of the resolved root). */
27
+ export declare function rootLabel(root: string): string;
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Workspace root detection for the `dbx-tools` CLI.
3
+ *
4
+ * @module
5
+ */
6
+ import { existsSync } from "node:fs";
7
+ import { basename, dirname, join, resolve } from "node:path";
8
+ import { exec } from "@dbx-tools/core";
9
+ import { functionModule } from "@dbx-tools/shared-core";
10
+ async function gitToplevel() {
11
+ const { exitCode, stdout } = await exec.spawn("git", ["rev-parse", "--show-toplevel"], {
12
+ stdout: "capture",
13
+ stderr: "ignore",
14
+ stdin: "ignore",
15
+ });
16
+ if (exitCode !== 0)
17
+ return undefined;
18
+ return stdout || undefined;
19
+ }
20
+ /**
21
+ * Walk upward from `startDir` for `.projenrc.ts`. If none is found, try git
22
+ * top-level only when that directory also contains `.projenrc.ts`; otherwise return
23
+ * `resolve(startDir)` (which may not be a workspace root).
24
+ */
25
+ export async function findWorkspaceRoot(startDir = process.cwd()) {
26
+ let dir = resolve(startDir);
27
+ while (true) {
28
+ if (existsSync(join(dir, ".projenrc.ts")))
29
+ return dir;
30
+ const parent = dirname(dir);
31
+ if (parent === dir)
32
+ break;
33
+ dir = parent;
34
+ }
35
+ const fromGit = await gitToplevel();
36
+ if (fromGit && existsSync(join(fromGit, ".projenrc.ts")))
37
+ return fromGit;
38
+ return resolve(startDir);
39
+ }
40
+ /**
41
+ * True when the folder has no `.projenrc.ts` yet and needs full bootstrapping.
42
+ * Keying off `.projenrc.ts` (not `package.json`) avoids clobbering a cleaned
43
+ * workspace that still has a hand-authored projenrc.
44
+ */
45
+ export function needsBootstrap(root) {
46
+ return !existsSync(join(root, ".projenrc.ts"));
47
+ }
48
+ /** True when `node_modules` or projen itself is missing under `root`. */
49
+ export function needsInstall(root) {
50
+ if (!existsSync(join(root, "node_modules")))
51
+ return true;
52
+ if (existsSync(join(root, ".projenrc.ts")) && !existsSync(join(root, "node_modules", "projen"))) {
53
+ return true;
54
+ }
55
+ return false;
56
+ }
57
+ /**
58
+ * True when the synth TOOLCHAIN isn't installed yet: no `node_modules`, or the
59
+ * dbx-tools engine / `projen` aren't resolvable under it. Distinct from a full
60
+ * bootstrap (which keys off a MISSING `.projenrc.ts`): here the projenrc exists
61
+ * but its dependencies don't - e.g. a copied project whose generated manifests
62
+ * and `node_modules` are gitignored. Seeding the toolchain (not scaffolding)
63
+ * makes it synth-ready without touching the hand-authored `.projenrc.ts`.
64
+ */
65
+ export function needsToolchain(root) {
66
+ const modules = join(root, "node_modules");
67
+ if (!existsSync(modules))
68
+ return true;
69
+ return !existsSync(join(modules, "projen")) || !existsSync(join(modules, "@dbx-tools", "projen"));
70
+ }
71
+ /** Async, memoized root lookup from the process cwd at first use. */
72
+ export const workspaceRoot = functionModule.memoize(() => findWorkspaceRoot());
73
+ /** Short label for log output (`basename` of the resolved root). */
74
+ export function rootLabel(root) {
75
+ return basename(root) || root;
76
+ }
77
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm9vdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9yb290LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7O0dBSUc7QUFDSCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ3JDLE9BQU8sRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDN0QsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3ZDLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUV4RCxLQUFLLFVBQVUsV0FBVztJQUN4QixNQUFNLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxHQUFHLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQyxXQUFXLEVBQUUsaUJBQWlCLENBQUMsRUFBRTtRQUNyRixNQUFNLEVBQUUsU0FBUztRQUNqQixNQUFNLEVBQUUsUUFBUTtRQUNoQixLQUFLLEVBQUUsUUFBUTtLQUNoQixDQUFDLENBQUM7SUFDSCxJQUFJLFFBQVEsS0FBSyxDQUFDO1FBQUUsT0FBTyxTQUFTLENBQUM7SUFDckMsT0FBTyxNQUFNLElBQUksU0FBUyxDQUFDO0FBQzdCLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxpQkFBaUIsQ0FBQyxXQUFtQixPQUFPLENBQUMsR0FBRyxFQUFFO0lBQ3RFLElBQUksR0FBRyxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUM1QixPQUFPLElBQUksRUFBRSxDQUFDO1FBQ1osSUFBSSxVQUFVLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxjQUFjLENBQUMsQ0FBQztZQUFFLE9BQU8sR0FBRyxDQUFDO1FBQ3RELE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUM1QixJQUFJLE1BQU0sS0FBSyxHQUFHO1lBQUUsTUFBTTtRQUMxQixHQUFHLEdBQUcsTUFBTSxDQUFDO0lBQ2YsQ0FBQztJQUVELE1BQU0sT0FBTyxHQUFHLE1BQU0sV0FBVyxFQUFFLENBQUM7SUFDcEMsSUFBSSxPQUFPLElBQUksVUFBVSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsY0FBYyxDQUFDLENBQUM7UUFBRSxPQUFPLE9BQU8sQ0FBQztJQUV6RSxPQUFPLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUMzQixDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILE1BQU0sVUFBVSxjQUFjLENBQUMsSUFBWTtJQUN6QyxPQUFPLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsY0FBYyxDQUFDLENBQUMsQ0FBQztBQUNqRCxDQUFDO0FBRUQseUVBQXlFO0FBQ3pFLE1BQU0sVUFBVSxZQUFZLENBQUMsSUFBWTtJQUN2QyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsY0FBYyxDQUFDLENBQUM7UUFBRSxPQUFPLElBQUksQ0FBQztJQUN6RCxJQUFJLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLGNBQWMsQ0FBQyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxjQUFjLEVBQUUsUUFBUSxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ2hHLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUNELE9BQU8sS0FBSyxDQUFDO0FBQ2YsQ0FBQztBQUVEOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLFVBQVUsY0FBYyxDQUFDLElBQVk7SUFDekMsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLElBQUksRUFBRSxjQUFjLENBQUMsQ0FBQztJQUMzQyxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQztRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQ3RDLE9BQU8sQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxRQUFRLENBQUMsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsWUFBWSxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUM7QUFDcEcsQ0FBQztBQUVELHFFQUFxRTtBQUNyRSxNQUFNLENBQUMsTUFBTSxhQUFhLEdBQUcsY0FBYyxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDLENBQUM7QUFFL0Usb0VBQW9FO0FBQ3BFLE1BQU0sVUFBVSxTQUFTLENBQUMsSUFBWTtJQUNwQyxPQUFPLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUM7QUFDaEMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogV29ya3NwYWNlIHJvb3QgZGV0ZWN0aW9uIGZvciB0aGUgYGRieC10b29sc2AgQ0xJLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuaW1wb3J0IHsgZXhpc3RzU3luYyB9IGZyb20gXCJub2RlOmZzXCI7XG5pbXBvcnQgeyBiYXNlbmFtZSwgZGlybmFtZSwgam9pbiwgcmVzb2x2ZSB9IGZyb20gXCJub2RlOnBhdGhcIjtcbmltcG9ydCB7IGV4ZWMgfSBmcm9tIFwiQGRieC10b29scy9jb3JlXCI7XG5pbXBvcnQgeyBmdW5jdGlvbk1vZHVsZSB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5cbmFzeW5jIGZ1bmN0aW9uIGdpdFRvcGxldmVsKCk6IFByb21pc2U8c3RyaW5nIHwgdW5kZWZpbmVkPiB7XG4gIGNvbnN0IHsgZXhpdENvZGUsIHN0ZG91dCB9ID0gYXdhaXQgZXhlYy5zcGF3bihcImdpdFwiLCBbXCJyZXYtcGFyc2VcIiwgXCItLXNob3ctdG9wbGV2ZWxcIl0sIHtcbiAgICBzdGRvdXQ6IFwiY2FwdHVyZVwiLFxuICAgIHN0ZGVycjogXCJpZ25vcmVcIixcbiAgICBzdGRpbjogXCJpZ25vcmVcIixcbiAgfSk7XG4gIGlmIChleGl0Q29kZSAhPT0gMCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgcmV0dXJuIHN0ZG91dCB8fCB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogV2FsayB1cHdhcmQgZnJvbSBgc3RhcnREaXJgIGZvciBgLnByb2plbnJjLnRzYC4gSWYgbm9uZSBpcyBmb3VuZCwgdHJ5IGdpdFxuICogdG9wLWxldmVsIG9ubHkgd2hlbiB0aGF0IGRpcmVjdG9yeSBhbHNvIGNvbnRhaW5zIGAucHJvamVucmMudHNgOyBvdGhlcndpc2UgcmV0dXJuXG4gKiBgcmVzb2x2ZShzdGFydERpcilgICh3aGljaCBtYXkgbm90IGJlIGEgd29ya3NwYWNlIHJvb3QpLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZmluZFdvcmtzcGFjZVJvb3Qoc3RhcnREaXI6IHN0cmluZyA9IHByb2Nlc3MuY3dkKCkpOiBQcm9taXNlPHN0cmluZz4ge1xuICBsZXQgZGlyID0gcmVzb2x2ZShzdGFydERpcik7XG4gIHdoaWxlICh0cnVlKSB7XG4gICAgaWYgKGV4aXN0c1N5bmMoam9pbihkaXIsIFwiLnByb2plbnJjLnRzXCIpKSkgcmV0dXJuIGRpcjtcbiAgICBjb25zdCBwYXJlbnQgPSBkaXJuYW1lKGRpcik7XG4gICAgaWYgKHBhcmVudCA9PT0gZGlyKSBicmVhaztcbiAgICBkaXIgPSBwYXJlbnQ7XG4gIH1cblxuICBjb25zdCBmcm9tR2l0ID0gYXdhaXQgZ2l0VG9wbGV2ZWwoKTtcbiAgaWYgKGZyb21HaXQgJiYgZXhpc3RzU3luYyhqb2luKGZyb21HaXQsIFwiLnByb2plbnJjLnRzXCIpKSkgcmV0dXJuIGZyb21HaXQ7XG5cbiAgcmV0dXJuIHJlc29sdmUoc3RhcnREaXIpO1xufVxuXG4vKipcbiAqIFRydWUgd2hlbiB0aGUgZm9sZGVyIGhhcyBubyBgLnByb2plbnJjLnRzYCB5ZXQgYW5kIG5lZWRzIGZ1bGwgYm9vdHN0cmFwcGluZy5cbiAqIEtleWluZyBvZmYgYC5wcm9qZW5yYy50c2AgKG5vdCBgcGFja2FnZS5qc29uYCkgYXZvaWRzIGNsb2JiZXJpbmcgYSBjbGVhbmVkXG4gKiB3b3Jrc3BhY2UgdGhhdCBzdGlsbCBoYXMgYSBoYW5kLWF1dGhvcmVkIHByb2plbnJjLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbmVlZHNCb290c3RyYXAocm9vdDogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiAhZXhpc3RzU3luYyhqb2luKHJvb3QsIFwiLnByb2plbnJjLnRzXCIpKTtcbn1cblxuLyoqIFRydWUgd2hlbiBgbm9kZV9tb2R1bGVzYCBvciBwcm9qZW4gaXRzZWxmIGlzIG1pc3NpbmcgdW5kZXIgYHJvb3RgLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG5lZWRzSW5zdGFsbChyb290OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgaWYgKCFleGlzdHNTeW5jKGpvaW4ocm9vdCwgXCJub2RlX21vZHVsZXNcIikpKSByZXR1cm4gdHJ1ZTtcbiAgaWYgKGV4aXN0c1N5bmMoam9pbihyb290LCBcIi5wcm9qZW5yYy50c1wiKSkgJiYgIWV4aXN0c1N5bmMoam9pbihyb290LCBcIm5vZGVfbW9kdWxlc1wiLCBcInByb2plblwiKSkpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICByZXR1cm4gZmFsc2U7XG59XG5cbi8qKlxuICogVHJ1ZSB3aGVuIHRoZSBzeW50aCBUT09MQ0hBSU4gaXNuJ3QgaW5zdGFsbGVkIHlldDogbm8gYG5vZGVfbW9kdWxlc2AsIG9yIHRoZVxuICogZGJ4LXRvb2xzIGVuZ2luZSAvIGBwcm9qZW5gIGFyZW4ndCByZXNvbHZhYmxlIHVuZGVyIGl0LiBEaXN0aW5jdCBmcm9tIGEgZnVsbFxuICogYm9vdHN0cmFwICh3aGljaCBrZXlzIG9mZiBhIE1JU1NJTkcgYC5wcm9qZW5yYy50c2ApOiBoZXJlIHRoZSBwcm9qZW5yYyBleGlzdHNcbiAqIGJ1dCBpdHMgZGVwZW5kZW5jaWVzIGRvbid0IC0gZS5nLiBhIGNvcGllZCBwcm9qZWN0IHdob3NlIGdlbmVyYXRlZCBtYW5pZmVzdHNcbiAqIGFuZCBgbm9kZV9tb2R1bGVzYCBhcmUgZ2l0aWdub3JlZC4gU2VlZGluZyB0aGUgdG9vbGNoYWluIChub3Qgc2NhZmZvbGRpbmcpXG4gKiBtYWtlcyBpdCBzeW50aC1yZWFkeSB3aXRob3V0IHRvdWNoaW5nIHRoZSBoYW5kLWF1dGhvcmVkIGAucHJvamVucmMudHNgLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbmVlZHNUb29sY2hhaW4ocm9vdDogc3RyaW5nKTogYm9vbGVhbiB7XG4gIGNvbnN0IG1vZHVsZXMgPSBqb2luKHJvb3QsIFwibm9kZV9tb2R1bGVzXCIpO1xuICBpZiAoIWV4aXN0c1N5bmMobW9kdWxlcykpIHJldHVybiB0cnVlO1xuICByZXR1cm4gIWV4aXN0c1N5bmMoam9pbihtb2R1bGVzLCBcInByb2plblwiKSkgfHwgIWV4aXN0c1N5bmMoam9pbihtb2R1bGVzLCBcIkBkYngtdG9vbHNcIiwgXCJwcm9qZW5cIikpO1xufVxuXG4vKiogQXN5bmMsIG1lbW9pemVkIHJvb3QgbG9va3VwIGZyb20gdGhlIHByb2Nlc3MgY3dkIGF0IGZpcnN0IHVzZS4gKi9cbmV4cG9ydCBjb25zdCB3b3Jrc3BhY2VSb290ID0gZnVuY3Rpb25Nb2R1bGUubWVtb2l6ZSgoKSA9PiBmaW5kV29ya3NwYWNlUm9vdCgpKTtcblxuLyoqIFNob3J0IGxhYmVsIGZvciBsb2cgb3V0cHV0IChgYmFzZW5hbWVgIG9mIHRoZSByZXNvbHZlZCByb290KS4gKi9cbmV4cG9ydCBmdW5jdGlvbiByb290TGFiZWwocm9vdDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGJhc2VuYW1lKHJvb3QpIHx8IHJvb3Q7XG59XG4iXX0=
@@ -0,0 +1 @@
1
+ {"root":["../src/bootstrap.ts","../src/cli.ts","../src/pnpm.ts","../src/root.ts","../index.ts","../bin/dbx-tools.ts"],"version":"5.9.3"}
package/package.json CHANGED
@@ -18,29 +18,45 @@
18
18
  "commander": "^15.0.0",
19
19
  "pnpm": "^11.0.6",
20
20
  "tsx": "^4.23.0",
21
- "@dbx-tools/core": "0.3.44",
22
- "@dbx-tools/shared-core": "0.3.44"
21
+ "@dbx-tools/core": "0.4.0",
22
+ "@dbx-tools/shared-core": "0.4.0"
23
23
  },
24
- "main": "index.ts",
24
+ "main": "./lib/index.js",
25
25
  "license": "UNLICENSED",
26
26
  "publishConfig": {
27
27
  "access": "public"
28
28
  },
29
- "version": "0.3.44",
30
- "types": "index.ts",
29
+ "version": "0.4.0",
30
+ "types": "./lib/index.d.ts",
31
31
  "type": "module",
32
32
  "exports": {
33
- ".": "./index.ts",
34
- "./bootstrap": "./src/bootstrap.ts",
35
- "./cli": "./src/cli.ts",
36
- "./pnpm": "./src/pnpm.ts",
37
- "./root": "./src/root.ts",
33
+ ".": {
34
+ "types": "./lib/index.d.ts",
35
+ "default": "./lib/index.js"
36
+ },
37
+ "./bootstrap": {
38
+ "types": "./lib/src/bootstrap.d.ts",
39
+ "default": "./lib/src/bootstrap.js"
40
+ },
41
+ "./cli": {
42
+ "types": "./lib/src/cli.d.ts",
43
+ "default": "./lib/src/cli.js"
44
+ },
45
+ "./pnpm": {
46
+ "types": "./lib/src/pnpm.d.ts",
47
+ "default": "./lib/src/pnpm.js"
48
+ },
49
+ "./root": {
50
+ "types": "./lib/src/root.d.ts",
51
+ "default": "./lib/src/root.js"
52
+ },
38
53
  "./package.json": "./package.json"
39
54
  },
40
55
  "files": [
41
56
  "index.ts",
42
57
  "src",
43
- "bin"
58
+ "bin",
59
+ "lib"
44
60
  ],
45
61
  "dbxToolsConfig": {
46
62
  "tags": [