@dbx-tools/cli 0.6.40 → 0.6.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/dbx-tools.ts +0 -0
- package/index.ts +2 -2
- package/lib/bin/dbx-tools.js +0 -0
- package/lib/index.d.ts +2 -2
- package/lib/index.js +3 -3
- package/lib/src/bootstrap.d.ts +17 -14
- package/lib/src/bootstrap.js +42 -68
- package/lib/src/bun.d.ts +24 -0
- package/lib/src/bun.js +126 -0
- package/lib/src/cli.js +4 -4
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +58 -44
- package/src/bootstrap.ts +41 -72
- package/src/bun.ts +136 -0
- package/src/cli.ts +3 -3
- package/lib/src/pnpm.d.ts +0 -23
- package/lib/src/pnpm.js +0 -190
- package/src/pnpm.ts +0 -203
package/package.json
CHANGED
|
@@ -6,50 +6,75 @@
|
|
|
6
6
|
"directory": "packages/cli/dbx-tools"
|
|
7
7
|
},
|
|
8
8
|
"bin": {
|
|
9
|
-
"dbx-tools": "./
|
|
10
|
-
"dbxt": "./
|
|
9
|
+
"dbx-tools": "./bin/dbx-tools.ts",
|
|
10
|
+
"dbxt": "./bin/dbx-tools.ts"
|
|
11
|
+
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "projen build",
|
|
14
|
+
"compile": "projen compile",
|
|
15
|
+
"default": "projen default",
|
|
16
|
+
"package": "projen package",
|
|
17
|
+
"post-compile": "projen post-compile",
|
|
18
|
+
"pre-compile": "projen pre-compile",
|
|
19
|
+
"prepack": "projen prepack",
|
|
20
|
+
"test": "projen test",
|
|
21
|
+
"watch": "projen watch",
|
|
22
|
+
"projen": "projen"
|
|
11
23
|
},
|
|
12
24
|
"devDependencies": {
|
|
25
|
+
"@types/bun": "^1.3.14",
|
|
13
26
|
"@types/node": "^24.6.0",
|
|
14
|
-
"tsx": "^4.23.0",
|
|
15
27
|
"typescript": "^5.9.3"
|
|
16
28
|
},
|
|
17
29
|
"dependencies": {
|
|
18
30
|
"@clack/prompts": "^1.7.0",
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"@dbx-tools/shared-core": "0.6.40"
|
|
31
|
+
"@dbx-tools/core": "0.6.42",
|
|
32
|
+
"@dbx-tools/shared-core": "0.6.42",
|
|
33
|
+
"commander": "^15.0.0"
|
|
23
34
|
},
|
|
24
|
-
"main": "
|
|
35
|
+
"main": "index.ts",
|
|
25
36
|
"license": "UNLICENSED",
|
|
26
37
|
"publishConfig": {
|
|
27
|
-
"access": "public"
|
|
38
|
+
"access": "public",
|
|
39
|
+
"main": "./lib/index.js",
|
|
40
|
+
"types": "./lib/index.d.ts",
|
|
41
|
+
"bin": {
|
|
42
|
+
"dbx-tools": "./lib/bin/dbx-tools.js",
|
|
43
|
+
"dbxt": "./lib/bin/dbx-tools.js"
|
|
44
|
+
},
|
|
45
|
+
"exports": {
|
|
46
|
+
".": {
|
|
47
|
+
"types": "./lib/index.d.ts",
|
|
48
|
+
"default": "./lib/index.js"
|
|
49
|
+
},
|
|
50
|
+
"./bootstrap": {
|
|
51
|
+
"types": "./lib/src/bootstrap.d.ts",
|
|
52
|
+
"default": "./lib/src/bootstrap.js"
|
|
53
|
+
},
|
|
54
|
+
"./bun": {
|
|
55
|
+
"types": "./lib/src/bun.d.ts",
|
|
56
|
+
"default": "./lib/src/bun.js"
|
|
57
|
+
},
|
|
58
|
+
"./cli": {
|
|
59
|
+
"types": "./lib/src/cli.d.ts",
|
|
60
|
+
"default": "./lib/src/cli.js"
|
|
61
|
+
},
|
|
62
|
+
"./root": {
|
|
63
|
+
"types": "./lib/src/root.d.ts",
|
|
64
|
+
"default": "./lib/src/root.js"
|
|
65
|
+
},
|
|
66
|
+
"./package.json": "./package.json"
|
|
67
|
+
}
|
|
28
68
|
},
|
|
29
|
-
"version": "0.6.
|
|
30
|
-
"types": "
|
|
69
|
+
"version": "0.6.42",
|
|
70
|
+
"types": "index.ts",
|
|
31
71
|
"type": "module",
|
|
32
72
|
"exports": {
|
|
33
|
-
".":
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"./
|
|
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
|
-
},
|
|
73
|
+
".": "./index.ts",
|
|
74
|
+
"./bootstrap": "./src/bootstrap.ts",
|
|
75
|
+
"./bun": "./src/bun.ts",
|
|
76
|
+
"./cli": "./src/cli.ts",
|
|
77
|
+
"./root": "./src/root.ts",
|
|
53
78
|
"./package.json": "./package.json"
|
|
54
79
|
},
|
|
55
80
|
"files": [
|
|
@@ -63,16 +88,5 @@
|
|
|
63
88
|
"cli"
|
|
64
89
|
]
|
|
65
90
|
},
|
|
66
|
-
"//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"
|
|
67
|
-
|
|
68
|
-
"build": "projen build",
|
|
69
|
-
"compile": "projen compile",
|
|
70
|
-
"default": "projen default",
|
|
71
|
-
"package": "projen package",
|
|
72
|
-
"post-compile": "projen post-compile",
|
|
73
|
-
"pre-compile": "projen pre-compile",
|
|
74
|
-
"test": "projen test",
|
|
75
|
-
"watch": "projen watch",
|
|
76
|
-
"projen": "projen"
|
|
77
|
-
}
|
|
78
|
-
}
|
|
91
|
+
"//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"bunx projen\"."
|
|
92
|
+
}
|
package/src/bootstrap.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { join } from "node:path";
|
|
|
9
9
|
import { intro, outro } from "@clack/prompts";
|
|
10
10
|
import { exec, project } from "@dbx-tools/core";
|
|
11
11
|
import { json, log } from "@dbx-tools/shared-core";
|
|
12
|
-
import { childEnv,
|
|
12
|
+
import { childEnv, resolveBunArgv, runBun } from "./bun.ts";
|
|
13
13
|
import { rootLabel } from "./root.ts";
|
|
14
14
|
|
|
15
15
|
const logger = log.logger("dbx-tools:bootstrap");
|
|
@@ -25,15 +25,10 @@ const FALLBACK_PROJEN_SPECIFIER = "@dbx-tools/projen@latest";
|
|
|
25
25
|
* the root `bump`, so the matching engine always exists on the registry.
|
|
26
26
|
*
|
|
27
27
|
* Not `@latest`, and not a bare `@dbx-tools/projen`. A bare specifier can land on
|
|
28
|
-
* a stray `0.0.0`, whose `^0.0.0` caret then reaches no real release.
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* (`+ @dbx-tools/projen 0.1.24 (0.3.42 is available)`). A bootstrap run right
|
|
33
|
-
* after a release therefore installed a months-old engine against a current CLI,
|
|
34
|
-
* which is how `sync --watch` died on an engine predating its `concurrently`
|
|
35
|
-
* dependency. An explicit range admits only the version we want, so the age
|
|
36
|
-
* heuristic has nothing older to fall back to.
|
|
28
|
+
* a stray `0.0.0`, whose `^0.0.0` caret then reaches no real release. An explicit
|
|
29
|
+
* range pinned to this CLI's own version admits only the matching engine, so the
|
|
30
|
+
* CLI and the engine it drives never drift across a release (they are cut
|
|
31
|
+
* together by the root `bump`).
|
|
37
32
|
*/
|
|
38
33
|
function defaultProjenSpecifier(): string {
|
|
39
34
|
const version = ownVersion();
|
|
@@ -92,7 +87,7 @@ export function ensureEngineCurrent(root: string): void {
|
|
|
92
87
|
if (!expected) return;
|
|
93
88
|
const installed = installedEngineVersion(root);
|
|
94
89
|
if (installed && compareVersions(installed, expected) >= 0) return;
|
|
95
|
-
|
|
90
|
+
runBun(["add", "-D", defaultProjenSpecifier()], root);
|
|
96
91
|
}
|
|
97
92
|
|
|
98
93
|
// Reach the class through its module NAMESPACE. Current engines also hoist it
|
|
@@ -105,26 +100,21 @@ const project = new projectApi.DBXToolsNodeProject();
|
|
|
105
100
|
project.synth();
|
|
106
101
|
`;
|
|
107
102
|
|
|
108
|
-
/** Seed `pnpm-workspace.yaml` so the first \`pnpm add\` can allow esbuild non-interactively. */
|
|
109
|
-
const WORKSPACE_SEED = `packages: []
|
|
110
|
-
allowBuilds:
|
|
111
|
-
esbuild: true
|
|
112
|
-
`;
|
|
113
|
-
|
|
114
103
|
/**
|
|
115
|
-
* Turn a folder into a functioning dbx-tools workspace: `
|
|
116
|
-
* `
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
104
|
+
* Turn a folder into a functioning dbx-tools workspace: `bun init`, seed the
|
|
105
|
+
* `package.json` workspace fields (bun reads `workspaces`/`trustedDependencies`
|
|
106
|
+
* from the manifest), add `projen`/`typescript` + the engine package, write a
|
|
107
|
+
* minimal `.projenrc.ts`, synth once (with `PROJEN_DISABLE_POST`), then install.
|
|
108
|
+
* Does not run barrels - run `bun run barrels` or a full projen synth post-install
|
|
109
|
+
* to generate package barrels.
|
|
120
110
|
*
|
|
121
111
|
* Every step is idempotent and self-guarded, so this is safe to run against a
|
|
122
112
|
* folder that ALREADY has a hand-authored `.projenrc.ts` (and even a committed
|
|
123
113
|
* `package.json`) but is missing the installed toolchain - e.g. a freshly copied
|
|
124
114
|
* project whose generated files (including manifests) are gitignored. In that
|
|
125
|
-
* case `
|
|
126
|
-
* projen
|
|
127
|
-
*
|
|
115
|
+
* case `bun init` and the `.projenrc.ts` scaffold are skipped, but the engine +
|
|
116
|
+
* projen are (re)installed so the subsequent synth can regenerate everything.
|
|
117
|
+
* See {@link seedToolchain}.
|
|
128
118
|
*/
|
|
129
119
|
export function bootstrapWorkspace(
|
|
130
120
|
root: string,
|
|
@@ -141,16 +131,18 @@ export function bootstrapWorkspace(
|
|
|
141
131
|
|
|
142
132
|
runInitialSynth(root);
|
|
143
133
|
|
|
144
|
-
|
|
134
|
+
runBun(["install"], root);
|
|
145
135
|
outro("Workspace ready - re-run dbx-tools or add packages under packages/");
|
|
146
136
|
}
|
|
147
137
|
|
|
148
138
|
/**
|
|
149
|
-
* Install the toolchain a synth needs (`projen`, `typescript`,
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
139
|
+
* Install the toolchain a synth needs (`projen`, `typescript`, and the dbx-tools
|
|
140
|
+
* engine), seeding a `package.json` first when absent. bun reads its workspace
|
|
141
|
+
* config (`workspaces`/`trustedDependencies`) from the manifest, so there is no
|
|
142
|
+
* separate workspace file to seed - the engine writes `pnpm-workspace.yaml` at
|
|
143
|
+
* synth for the Databricks Apps platform. Idempotent: run it whenever the engine
|
|
144
|
+
* is missing, so a copied project with a `.projenrc.ts` but no
|
|
145
|
+
* `node_modules`/manifest can be brought up to a synth-ready state.
|
|
154
146
|
*/
|
|
155
147
|
export function seedToolchain(
|
|
156
148
|
root: string,
|
|
@@ -158,15 +150,10 @@ export function seedToolchain(
|
|
|
158
150
|
): void {
|
|
159
151
|
const manifestPath = join(root, "package.json");
|
|
160
152
|
if (!existsSync(manifestPath)) {
|
|
161
|
-
|
|
153
|
+
runBun(["init", "-y"], root);
|
|
162
154
|
normalizeSeedManifest(manifestPath);
|
|
163
155
|
}
|
|
164
156
|
|
|
165
|
-
const workspaceFile = join(root, "pnpm-workspace.yaml");
|
|
166
|
-
if (!existsSync(workspaceFile)) {
|
|
167
|
-
writeFileSync(workspaceFile, WORKSPACE_SEED);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
157
|
seedRegistry(root);
|
|
171
158
|
|
|
172
159
|
const kernelArch = exec.spawnSync("uname", ["-m"], {
|
|
@@ -176,31 +163,21 @@ export function seedToolchain(
|
|
|
176
163
|
}).stdout;
|
|
177
164
|
logger.info("seeding toolchain", {
|
|
178
165
|
node: process.version,
|
|
166
|
+
bun: process.versions.bun,
|
|
179
167
|
platform: process.platform,
|
|
180
168
|
arch: process.arch,
|
|
181
169
|
kernelArch: kernelArch || "unknown",
|
|
182
170
|
engine: projenSpecifier,
|
|
183
171
|
});
|
|
184
|
-
|
|
185
|
-
[
|
|
186
|
-
"add",
|
|
187
|
-
"--reporter=append-only",
|
|
188
|
-
"-D",
|
|
189
|
-
"projen",
|
|
190
|
-
"typescript@^5.9.3",
|
|
191
|
-
"tsx@^4.23.0",
|
|
192
|
-
projenSpecifier,
|
|
193
|
-
],
|
|
194
|
-
root,
|
|
195
|
-
);
|
|
172
|
+
runBun(["add", "-D", "projen", "typescript@^5.9.3", "@types/bun", projenSpecifier], root);
|
|
196
173
|
}
|
|
197
174
|
|
|
198
175
|
/**
|
|
199
176
|
* Pin a non-default registry into the new root's `.npmrc`.
|
|
200
177
|
*
|
|
201
|
-
* The CLI already forces `--registry` onto the
|
|
202
|
-
* but a bootstrapped workspace outlives this process: every later `
|
|
203
|
-
* the developer (or projen's post-synth step) runs is on its own.
|
|
178
|
+
* The CLI already forces `--registry` onto the bun invocations it makes itself,
|
|
179
|
+
* but a bootstrapped workspace outlives this process: every later `bun install`
|
|
180
|
+
* the developer (or projen's post-synth step) runs is on its own. bun ignores
|
|
204
181
|
* `npm_config_registry` from the environment, so without a file on disk those
|
|
205
182
|
* runs revert to `https://registry.npmjs.org/` - which is a hard failure where
|
|
206
183
|
* the custom registry was the only reachable one.
|
|
@@ -217,44 +194,36 @@ function seedRegistry(root: string): void {
|
|
|
217
194
|
}
|
|
218
195
|
|
|
219
196
|
/**
|
|
220
|
-
* Make what `
|
|
221
|
-
*
|
|
222
|
-
*
|
|
223
|
-
*
|
|
224
|
-
*
|
|
225
|
-
* `npx`/dlx fallback) then refuses with EBADDEVENGINES, its runner being npm;
|
|
226
|
-
* - force `type: "module"`, which pnpm 11 writes and pnpm 10 does not. tsx
|
|
227
|
-
* picks the entry's format from the nearest manifest, so without it
|
|
228
|
-
* `.projenrc.ts` loads as CJS and the first dependency using top-level await
|
|
229
|
-
* dies on "not supported with the cjs output format".
|
|
230
|
-
*
|
|
231
|
-
* projen regenerates the whole manifest at synth, so this only has to hold the
|
|
232
|
-
* seed together long enough to get there.
|
|
197
|
+
* Make what `bun init` produced safe to synth against: force `type: "module"`
|
|
198
|
+
* (bun runs `.projenrc.ts` fine either way, but projen's ESM sources and the
|
|
199
|
+
* emitted config assume module type) and drop any `packageManager`/`devEngines`
|
|
200
|
+
* field that would pin a different manager. projen regenerates the whole manifest
|
|
201
|
+
* at synth, so this only has to hold the seed together long enough to get there.
|
|
233
202
|
*/
|
|
234
203
|
function normalizeSeedManifest(manifestPath: string): void {
|
|
235
204
|
try {
|
|
236
205
|
const manifest = json.parseRecord(readFileSync(manifestPath, "utf8"));
|
|
237
206
|
if (!manifest) return;
|
|
238
207
|
delete manifest.devEngines;
|
|
208
|
+
delete manifest.packageManager;
|
|
239
209
|
manifest.type = "module";
|
|
240
210
|
writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
|
|
241
211
|
} catch {
|
|
242
|
-
// A malformed/absent manifest here just means the later `
|
|
212
|
+
// A malformed/absent manifest here just means the later `bun add` recreates it.
|
|
243
213
|
}
|
|
244
214
|
}
|
|
245
215
|
|
|
246
216
|
/**
|
|
247
|
-
* Run the initial synth by executing `.projenrc.ts` directly with
|
|
217
|
+
* Run the initial synth by executing `.projenrc.ts` directly with bun (with
|
|
248
218
|
* `PROJEN_DISABLE_POST` set), NOT `projen <task>`. Use right after seeding a
|
|
249
219
|
* fresh workspace: the projen TASKS (`sync`, `barrels`, ...) only exist once
|
|
250
220
|
* `.projenrc.ts` has run once, so `projen sync` can't be the bootstrapping step.
|
|
251
221
|
*/
|
|
252
222
|
export function runInitialSynth(root: string): void {
|
|
253
|
-
const [command, ...prefix] =
|
|
254
|
-
//
|
|
255
|
-
//
|
|
256
|
-
|
|
257
|
-
exec.spawnSync(command, [...prefix, "exec", "tsx", ".projenrc.ts"], {
|
|
223
|
+
const [command, ...prefix] = resolveBunArgv();
|
|
224
|
+
// bun runs the `.ts` directly. The registry reaches anything nested through
|
|
225
|
+
// `childEnv` and the seeded `.npmrc`.
|
|
226
|
+
exec.spawnSync(command, [...prefix, ".projenrc.ts"], {
|
|
258
227
|
cwd: root,
|
|
259
228
|
env: childEnv({ PROJEN_DISABLE_POST: "true" }),
|
|
260
229
|
check: true,
|
package/src/bun.ts
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* bun discovery, workspace install, and projen forwarding for the `dbx-tools` CLI.
|
|
3
|
+
*
|
|
4
|
+
* ## Forcing a custom registry
|
|
5
|
+
*
|
|
6
|
+
* bun honors a `--registry <url>` flag on `bun install`/`bun add` and a project
|
|
7
|
+
* `.npmrc`, but (like pnpm) ignores the `npm_config_registry` env var for its own
|
|
8
|
+
* resolution. So a custom registry is forced through TWO channels, each where it
|
|
9
|
+
* applies:
|
|
10
|
+
*
|
|
11
|
+
* - {@link bunRegistryArgs} passes `--registry` to the package-resolving
|
|
12
|
+
* subcommands (`install`/`add`/`update`), never to `bun run`/`bunx`, whose
|
|
13
|
+
* trailing args belong to the script.
|
|
14
|
+
* - {@link childEnv} keeps `.npmrc`-style env aliases set for any nested
|
|
15
|
+
* npm-based tool, and (critically) puts the bun/node executable dir on PATH so
|
|
16
|
+
* a lifecycle script can invoke the runtime by bare name.
|
|
17
|
+
*
|
|
18
|
+
* `@dbx-tools/core`'s `npmRegistry({ overrideOnly: true })` returns nothing when
|
|
19
|
+
* the effective registry IS npmjs, so none of this touches a default install.
|
|
20
|
+
*
|
|
21
|
+
* @module
|
|
22
|
+
*/
|
|
23
|
+
import { existsSync } from "node:fs";
|
|
24
|
+
import { delimiter, dirname, join } from "node:path";
|
|
25
|
+
import { exec, project } from "@dbx-tools/core";
|
|
26
|
+
import { functionModule, log } from "@dbx-tools/shared-core";
|
|
27
|
+
import { needsInstall } from "./root.ts";
|
|
28
|
+
|
|
29
|
+
const logger = log.logger("dbx-tools:bun");
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* bun subcommands that resolve packages from a registry, and therefore accept a
|
|
33
|
+
* meaningful `--registry`. Everything else (`run`, `x`, `pm`, ...) is left alone:
|
|
34
|
+
* `run`/`x` forward trailing arguments to the script they run.
|
|
35
|
+
*/
|
|
36
|
+
const REGISTRY_SUBCOMMANDS = new Set(["add", "install", "i", "update", "up"]);
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The registry to force onto child installs, or `undefined` when the effective
|
|
40
|
+
* one is already the public default.
|
|
41
|
+
*
|
|
42
|
+
* `envVars: true` also consults `npm_config_registry` directly, because a
|
|
43
|
+
* container may export it without any `.npmrc` for lookup. Memoized: resolution
|
|
44
|
+
* shells out.
|
|
45
|
+
*/
|
|
46
|
+
const registryOverride = functionModule.memoize((): string | undefined =>
|
|
47
|
+
project.npmRegistry(null, { overrideOnly: true, envVars: true })?.toString(),
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
/** `--registry <url>` for a bun invocation, or `[]` when the subcommand doesn't resolve. */
|
|
51
|
+
export function bunRegistryArgs(args: readonly string[]): string[] {
|
|
52
|
+
const url = registryOverride();
|
|
53
|
+
if (!url) return [];
|
|
54
|
+
return bunUsesRegistry(args) ? ["--registry", url] : [];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Whether the first bun subcommand resolves packages and accepts `--registry`. */
|
|
58
|
+
export function bunUsesRegistry(args: readonly string[]): boolean {
|
|
59
|
+
const subcommand = args.find((arg) => !arg.startsWith("-"));
|
|
60
|
+
return subcommand !== undefined && REGISTRY_SUBCOMMANDS.has(subcommand);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* `process.env` plus the runtime executable directory and registry aliases.
|
|
65
|
+
*
|
|
66
|
+
* The executable directory matters when this CLI was launched by absolute path:
|
|
67
|
+
* bun runs, but a lifecycle script that invokes `bun`/`node` by bare name would
|
|
68
|
+
* otherwise fail with `command not found`. Prepending `dirname(process.execPath)`
|
|
69
|
+
* (the running bun binary's dir) puts the runtime back on PATH.
|
|
70
|
+
*/
|
|
71
|
+
export function childEnv(extra?: Record<string, string>): NodeJS.ProcessEnv {
|
|
72
|
+
const env: NodeJS.ProcessEnv = { ...process.env, ...extra };
|
|
73
|
+
const runtimeBin = dirname(process.execPath);
|
|
74
|
+
const pathEntries = (env.PATH ?? "").split(delimiter).filter(Boolean);
|
|
75
|
+
if (!pathEntries.includes(runtimeBin)) {
|
|
76
|
+
env.PATH = [runtimeBin, ...pathEntries].join(delimiter);
|
|
77
|
+
}
|
|
78
|
+
const url = registryOverride();
|
|
79
|
+
if (url) {
|
|
80
|
+
// Both cases: env is case-sensitive on POSIX, and npm lowercases when reading.
|
|
81
|
+
env.npm_config_registry = url;
|
|
82
|
+
env.NPM_CONFIG_REGISTRY = url;
|
|
83
|
+
}
|
|
84
|
+
return env;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Resolve the argv prefix to run bun: the `bun` package's own bin when this CLI
|
|
89
|
+
* is itself running under bun (`process.execPath` is the bun binary), else a bare
|
|
90
|
+
* `bun` on PATH. No corepack/npx fallback - bun is the ambient runtime this
|
|
91
|
+
* toolchain requires.
|
|
92
|
+
*/
|
|
93
|
+
function resolveBunArgvImpl(): string[] {
|
|
94
|
+
// The running process IS bun in every supported path (the bin is `bun <file>`),
|
|
95
|
+
// so reuse it directly - no PATH lookup, no package-manager shim.
|
|
96
|
+
if (/\bbun\b/.test(process.execPath)) return [process.execPath];
|
|
97
|
+
return ["bun"];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** Memoized `[command, ...prefix]` argv prefix to run bun. */
|
|
101
|
+
export const resolveBunArgv = functionModule.memoize(resolveBunArgvImpl);
|
|
102
|
+
|
|
103
|
+
/** Run bun with inherited stdio from `cwd`, forcing the resolved registry. */
|
|
104
|
+
export function runBun(args: string[], cwd: string): void {
|
|
105
|
+
const [command, ...prefix] = resolveBunArgv();
|
|
106
|
+
const registryArgs = bunRegistryArgs(args);
|
|
107
|
+
if (registryArgs.length > 0) {
|
|
108
|
+
logger.info(`running bun with registry: ${registryArgs[1]}`);
|
|
109
|
+
}
|
|
110
|
+
exec.spawnSync(command, [...prefix, ...args, ...registryArgs], {
|
|
111
|
+
cwd,
|
|
112
|
+
check: true,
|
|
113
|
+
env: childEnv(),
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** Install workspace dependencies when `node_modules` or projen is missing. */
|
|
118
|
+
export function ensureWorkspaceReady(root: string): void {
|
|
119
|
+
if (needsInstall(root)) {
|
|
120
|
+
runBun(["install"], root);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Run projen with the given args from `root`. Prefers the installed `projen` bin
|
|
126
|
+
* via `bun run`, so the workspace's own engine + tasks are used.
|
|
127
|
+
*/
|
|
128
|
+
export function runProjen(args: string[], root: string): void {
|
|
129
|
+
const projenBin = join(root, "node_modules", ".bin", "projen");
|
|
130
|
+
if (existsSync(projenBin)) {
|
|
131
|
+
runBun([projenBin, ...args], root);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
// Fallback: resolve projen through bun's package runner.
|
|
135
|
+
runBun(["x", "projen", ...args], root);
|
|
136
|
+
}
|
package/src/cli.ts
CHANGED
|
@@ -10,11 +10,11 @@ import {
|
|
|
10
10
|
runInitialSynth,
|
|
11
11
|
seedToolchain,
|
|
12
12
|
} from "./bootstrap.ts";
|
|
13
|
-
import { ensureWorkspaceReady,
|
|
13
|
+
import { ensureWorkspaceReady, runBun, runProjen } from "./bun.ts";
|
|
14
14
|
import { findWorkspaceRoot, needsBootstrap, needsToolchain } from "./root.ts";
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
* Prepare the workspace at `root`, then run
|
|
17
|
+
* Prepare the workspace at `root`, then run projen (via bun) with `projenArgs`.
|
|
18
18
|
*
|
|
19
19
|
* Three cases, in order:
|
|
20
20
|
* - no `.projenrc.ts` at all -> full bootstrap (scaffold + install + synth),
|
|
@@ -36,7 +36,7 @@ async function prepareAndRunProjen(projenArgs: string[], startDir?: string): Pro
|
|
|
36
36
|
if (needsToolchain(root)) {
|
|
37
37
|
seedToolchain(root);
|
|
38
38
|
runInitialSynth(root);
|
|
39
|
-
|
|
39
|
+
runBun(["install"], root);
|
|
40
40
|
return;
|
|
41
41
|
}
|
|
42
42
|
ensureWorkspaceReady(root);
|
package/lib/src/pnpm.d.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/** `--registry <url>` for npx, or `[]`. Placed BEFORE the package name by callers. */
|
|
2
|
-
export declare function npxRegistryArgs(): string[];
|
|
3
|
-
/** `--registry <url>` for a pnpm invocation, or `[]` when the subcommand does not resolve. */
|
|
4
|
-
export declare function pnpmRegistryArgs(args: readonly string[]): string[];
|
|
5
|
-
/** Whether the first pnpm subcommand resolves packages and accepts `--registry`. */
|
|
6
|
-
export declare function pnpmUsesRegistry(args: readonly string[]): boolean;
|
|
7
|
-
/**
|
|
8
|
-
* `process.env` plus the current Node executable directory and registry aliases.
|
|
9
|
-
*
|
|
10
|
-
* The executable directory matters when this CLI was launched by absolute path
|
|
11
|
-
* (for example from QuickJS or mise activation that was not exported): pnpm
|
|
12
|
-
* itself runs, but lifecycle scripts invoke `node` by name and otherwise fail
|
|
13
|
-
* with `sh: node: not found`.
|
|
14
|
-
*/
|
|
15
|
-
export declare function childEnv(extra?: Record<string, string>): NodeJS.ProcessEnv;
|
|
16
|
-
/** Memoized `[command, ...prefix]` argv prefix to run pnpm (resolved install, else corepack, else npx). */
|
|
17
|
-
export declare const resolvePnpmArgv: () => string[];
|
|
18
|
-
/** Run pnpm with inherited stdio from `cwd`, forcing the resolved registry. */
|
|
19
|
-
export declare function runPnpm(args: string[], cwd: string): void;
|
|
20
|
-
/** Install workspace dependencies when `node_modules` or projen is missing. */
|
|
21
|
-
export declare function ensureWorkspaceReady(root: string): void;
|
|
22
|
-
/** Run `pnpm exec projen` with the given args from `root`. */
|
|
23
|
-
export declare function runProjen(args: string[], root: string): void;
|