@projitect/cli-internals 1.0.0 → 1.0.1

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.
@@ -15,7 +15,8 @@ export interface InitResult {
15
15
  * `.pjt.ts` with the marker structure if absent, then delegates to `remodel` which runs the
16
16
  * standard plan/apply/lockfile-write pipeline. The projitect blueprint (prepended automatically
17
17
  * by `@projitect/cli`'s `pjt()`) writes the package.json entries and the `.pjt.ts` import region
18
- * on its first apply.
18
+ * on its first apply. Before seeding or loading the config, missing local CLI and Effect
19
+ * dependencies are installed so an ephemeral dlx invocation can resolve those imports.
19
20
  *
20
21
  * With `yes: true`, both prerequisites are auto-bootstrapped instead of erroring:
21
22
  * - Missing `.git/` → `git init -q` shell-out.
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AACxC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAEjD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAA;IACrC,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAA;IACjC,QAAQ,CAAC,uBAAuB,EAAE,OAAO,CAAA;IACzC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAA;CAChC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,IAAI,GAAI,QAAQ;IAC3B,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC,eAAe,CAAA;IAChD,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CACvB,KAAG,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,cAAc,CAqB/C,CAAA"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAIA,OAAO,EAAS,MAAM,EAAkB,MAAM,QAAQ,CAAA;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AACxC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAGtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AASjD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAA;IACrC,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAA;IACjC,QAAQ,CAAC,uBAAuB,EAAE,OAAO,CAAA;IACzC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAA;CAChC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,IAAI,GAAI,QAAQ;IAC3B,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC,eAAe,CAAA;IAChD,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CACvB,KAAG,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,cAAc,CA2B/C,CAAA"}
@@ -1,9 +1,15 @@
1
1
  import { promises as fs } from "node:fs";
2
2
  import { spawn } from "node:child_process";
3
+ import { createRequire } from "node:module";
3
4
  import path from "node:path";
4
- import { Effect } from "effect";
5
+ import { Array, Effect, Option, Schema } from "effect";
5
6
  import { Errors } from "@projitect/core";
7
+ import { detect, installDev as installDevelopment, installProject } from "../pm.js";
6
8
  import { remodel } from "./remodel.js";
9
+ const manifest = Schema.decodeUnknownSync(Schema.Struct({
10
+ version: Schema.String,
11
+ peerDependencies: Schema.Struct({ effect: Schema.String }),
12
+ }))(createRequire(import.meta.url)("../../package.json"));
7
13
  /**
8
14
  * `pjt init` — bootstrap projitect in the current project.
9
15
  *
@@ -11,7 +17,8 @@ import { remodel } from "./remodel.js";
11
17
  * `.pjt.ts` with the marker structure if absent, then delegates to `remodel` which runs the
12
18
  * standard plan/apply/lockfile-write pipeline. The projitect blueprint (prepended automatically
13
19
  * by `@projitect/cli`'s `pjt()`) writes the package.json entries and the `.pjt.ts` import region
14
- * on its first apply.
20
+ * on its first apply. Before seeding or loading the config, missing local CLI and Effect
21
+ * dependencies are installed so an ephemeral dlx invocation can resolve those imports.
15
22
  *
16
23
  * With `yes: true`, both prerequisites are auto-bootstrapped instead of erroring:
17
24
  * - Missing `.git/` → `git init -q` shell-out.
@@ -25,8 +32,13 @@ import { remodel } from "./remodel.js";
25
32
  export const init = (params) => Effect.gen(function* () {
26
33
  const bootstrappedGit = yield* ensureGit(params.config.projectRoot, params.yes ?? false);
27
34
  const bootstrappedPackageJson = yield* ensurePackageJson(params.config.projectRoot, params.yes ?? false);
35
+ const bootstrapPm = yield* ensureBootstrapDependencies(params.config.projectRoot);
28
36
  const seededBlueprintFile = yield* seedBlueprintFileIfAbsent(params.config.projectRoot, params.config.blueprintFile);
29
37
  const remodelResult = yield* remodel({ config: params.config });
38
+ yield* Option.match(bootstrapPm, {
39
+ onNone: () => Effect.void,
40
+ onSome: (pm) => installProject({ projectRoot: params.config.projectRoot, pm }),
41
+ });
30
42
  return {
31
43
  seededBlueprintFile,
32
44
  bootstrappedGit,
@@ -34,6 +46,19 @@ export const init = (params) => Effect.gen(function* () {
34
46
  remodel: remodelResult,
35
47
  };
36
48
  });
49
+ /** A dlx runner lives outside the project; generated imports must resolve locally first. */
50
+ const ensureBootstrapDependencies = (projectRoot) => Effect.forEach([
51
+ { name: "@projitect/cli", spec: `@projitect/cli@${manifest.version}` },
52
+ { name: "effect", spec: `effect@${manifest.peerDependencies.effect}` },
53
+ ], ({ name, spec }) => Effect.gen(function* () {
54
+ const installed = yield* Effect.promise(() => fs.access(path.join(projectRoot, "node_modules", name, "package.json")).then(() => true, () => false));
55
+ if (installed) {
56
+ return Option.none();
57
+ }
58
+ const pm = yield* detect({ projectRoot });
59
+ yield* installDevelopment({ projectRoot, pm, pkg: spec });
60
+ return Option.some(pm);
61
+ })).pipe(Effect.map((results) => Array.head(Array.getSomes(results))));
37
62
  const ensureGit = (projectRoot, yes) => Effect.gen(function* () {
38
63
  const ok = yield* Effect.promise(() => fs.access(path.join(projectRoot, ".git")).then(() => true, () => false));
39
64
  if (ok) {
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
package/dist/pm.d.ts CHANGED
@@ -3,9 +3,9 @@ import { Errors } from "@projitect/core";
3
3
  import type { ProjitectPackageMetadata } from "@projitect/blueprint";
4
4
  export type PackageManager = "pnpm" | "npm" | "yarn" | "bun";
5
5
  /**
6
- * Detect the user's package manager by walking up from `projectRoot` looking for known
7
- * lockfiles. Falls back to `npm` if nothing is found. Used by `pjt add` to decide which install
8
- * command to shell out to.
6
+ * Detect the user's package manager from known lockfiles in `projectRoot`.
7
+ * Without a lockfile, uses the invoking package manager's user-agent, then `npm`.
8
+ * Used by `pjt add` and first-run bootstrap to select the install command.
9
9
  */
10
10
  export declare const detect: (params: {
11
11
  readonly projectRoot: string;
@@ -19,6 +19,11 @@ export declare const installDev: (params: {
19
19
  readonly pm: PackageManager;
20
20
  readonly pkg: string;
21
21
  }) => Effect.Effect<void, Errors.PmInstallFailed>;
22
+ /** Synchronize the lockfile after bootstrap has applied its managed manifest ranges. */
23
+ export declare const installProject: (params: {
24
+ readonly projectRoot: string;
25
+ readonly pm: PackageManager;
26
+ }) => Effect.Effect<void, Errors.PmInstallFailed>;
22
27
  /**
23
28
  * Read the installed package's `package.json` and return its `"projitect"` metadata, if any.
24
29
  * Returns null if the package doesn't have the field; `pjt add` falls back to install-only
package/dist/pm.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"pm.d.ts","sourceRoot":"","sources":["../src/pm.ts"],"names":[],"mappings":"AAGA,OAAO,EAAS,MAAM,EAA4B,MAAM,QAAQ,CAAA;AAEhE,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AACxC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAA;AAEpE,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,CAAA;AAS5D;;;;GAIG;AACH,eAAO,MAAM,MAAM,GAAI,QAAQ;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAC7B,KAAG,MAAM,CAAC,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,aAAa,CAcnD,CAAA;AAEH;;;GAGG;AACH,eAAO,MAAM,UAAU,GAAI,QAAQ;IACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,EAAE,EAAE,cAAc,CAAA;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACrB,KAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,eAAe,CA2B7C,CAAA;AAUD;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,GAAI,QAAQ;IAC5C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACrB,KAAG,MAAM,CAAC,MAAM,CAAC,wBAAwB,GAAG,IAAI,CAqC7C,CAAA"}
1
+ {"version":3,"file":"pm.d.ts","sourceRoot":"","sources":["../src/pm.ts"],"names":[],"mappings":"AAGA,OAAO,EAAS,MAAM,EAA4B,MAAM,QAAQ,CAAA;AAEhE,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AACxC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAA;AAEpE,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,CAAA;AAS5D;;;;GAIG;AACH,eAAO,MAAM,MAAM,GAAI,QAAQ;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAC7B,KAAG,MAAM,CAAC,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,aAAa,CA6BnD,CAAA;AAEH;;;GAGG;AACH,eAAO,MAAM,UAAU,GAAI,QAAQ;IACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,EAAE,EAAE,cAAc,CAAA;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACrB,KAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,eAAe,CAC4B,CAAA;AAE1E,wFAAwF;AACxF,eAAO,MAAM,cAAc,GAAI,QAAQ;IACrC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,EAAE,EAAE,cAAc,CAAA;CAC5B,KAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,eAAe,CAK1C,CAAA;AA0CJ;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,GAAI,QAAQ;IAC5C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACrB,KAAG,MAAM,CAAC,MAAM,CAAC,wBAAwB,GAAG,IAAI,CAqC7C,CAAA"}
package/dist/pm.js CHANGED
@@ -11,45 +11,49 @@ const LOCKFILES = [
11
11
  ["package-lock.json", "npm"],
12
12
  ];
13
13
  /**
14
- * Detect the user's package manager by walking up from `projectRoot` looking for known
15
- * lockfiles. Falls back to `npm` if nothing is found. Used by `pjt add` to decide which install
16
- * command to shell out to.
14
+ * Detect the user's package manager from known lockfiles in `projectRoot`.
15
+ * Without a lockfile, uses the invoking package manager's user-agent, then `npm`.
16
+ * Used by `pjt add` and first-run bootstrap to select the install command.
17
17
  */
18
18
  export const detect = (params) => Effect.map(Effect.findFirst(LOCKFILES, ([filename]) => Effect.promise(() => fs.access(path.join(params.projectRoot, filename)).then(() => true, () => false))), Option.match({
19
19
  onSome: ([, pm]) => pm,
20
- onNone: () => "npm",
20
+ onNone: () => Match.value(process.env["npm_config_user_agent"] ?? "").pipe(Match.when((agent) => agent.startsWith("pnpm/"), () => "pnpm"), Match.when((agent) => agent.startsWith("yarn/"), () => "yarn"), Match.when((agent) => agent.startsWith("bun/"), () => "bun"), Match.orElse(() => "npm")),
21
21
  }));
22
22
  /**
23
23
  * Run `<pm> add -D <pkg>` in `projectRoot`. Wraps spawn failures (non-zero exit, PM not
24
24
  * installed) as `pjt.pm.install-failed`.
25
25
  */
26
- export const installDev = (params) => {
27
- const args = installArgs(params.pm, params.pkg);
28
- return Effect.tryPromise({
29
- try: () => new Promise((resolve, reject) => {
30
- const child = spawn(params.pm, args, {
31
- cwd: params.projectRoot,
32
- stdio: "inherit",
33
- });
34
- child.on("error", reject);
35
- child.on("close", (code) => {
36
- if (code === 0) {
37
- resolve();
38
- }
39
- else {
40
- reject(new Error(`${params.pm} ${args.join(" ")} exited with ${String(code)}`));
41
- }
42
- });
43
- }),
44
- catch: (e) => new Errors.PmInstallFailed({
45
- id: "pjt.pm.install-failed",
46
- packageManager: params.pm,
47
- pkg: params.pkg,
48
- cause: e instanceof Error ? e.message : String(e),
49
- message: `Failed to install \`${params.pkg}\` via ${params.pm}`,
50
- }),
51
- });
52
- };
26
+ export const installDev = (params) => runInstallation({ ...params, args: installArgs(params.pm, params.pkg) });
27
+ /** Synchronize the lockfile after bootstrap has applied its managed manifest ranges. */
28
+ export const installProject = (params) => runInstallation({
29
+ ...params,
30
+ pkg: "project dependencies",
31
+ args: params.pm === "pnpm" ? ["install", "--no-frozen-lockfile"] : ["install"],
32
+ });
33
+ const runInstallation = (params) => Effect.tryPromise({
34
+ try: () => new Promise((resolve, reject) => {
35
+ const child = spawn(params.pm, params.args, {
36
+ cwd: params.projectRoot,
37
+ stdio: "inherit",
38
+ });
39
+ child.on("error", reject);
40
+ child.on("close", (code) => {
41
+ if (code === 0) {
42
+ resolve();
43
+ }
44
+ else {
45
+ reject(new Error(`${params.pm} ${params.args.join(" ")} exited with ${String(code)}`));
46
+ }
47
+ });
48
+ }),
49
+ catch: (e) => new Errors.PmInstallFailed({
50
+ id: "pjt.pm.install-failed",
51
+ packageManager: params.pm,
52
+ pkg: params.pkg,
53
+ cause: e instanceof Error ? e.message : String(e),
54
+ message: `Failed to install \`${params.pkg}\` via ${params.pm}`,
55
+ }),
56
+ });
53
57
  const installArgs = (pm, pkg) => Match.value(pm).pipe(Match.whenOr("pnpm", "yarn", () => ["add", "-D", pkg]), Match.when("bun", () => ["add", "-d", pkg]), Match.when("npm", () => ["install", "-D", pkg]), Match.exhaustive);
54
58
  /**
55
59
  * Read the installed package's `package.json` and return its `"projitect"` metadata, if any.
package/dist/pm.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"pm.js","sourceRoot":"","sources":["../src/pm.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pm.js","sourceRoot":"","sources":["../src/pm.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@projitect/cli-internals",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Engine for the projitect CLI — loader, planner, differ, applier, and command dispatchers.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -31,18 +31,18 @@
31
31
  "@types/node": "22.19.19",
32
32
  "effect": "4.0.0-rc.111",
33
33
  "typescript": "5.9.3",
34
- "@projitect/blueprint": "1.0.0",
35
- "@projitect/blueprint-gitignore": "1.0.0",
36
- "@projitect/blueprint-markdown": "1.0.0",
37
- "@projitect/blueprint-next": "1.0.0",
38
- "@projitect/blueprint-react": "1.0.0",
39
- "@projitect/core": "1.0.0",
40
- "@projitect/test-kit": "1.0.0"
34
+ "@projitect/blueprint": "1.0.1",
35
+ "@projitect/blueprint-gitignore": "1.0.1",
36
+ "@projitect/blueprint-markdown": "1.0.1",
37
+ "@projitect/blueprint-next": "1.0.1",
38
+ "@projitect/blueprint-react": "1.0.1",
39
+ "@projitect/core": "1.0.1",
40
+ "@projitect/test-kit": "1.0.1"
41
41
  },
42
42
  "peerDependencies": {
43
43
  "effect": "4.0.0-rc.111",
44
- "@projitect/blueprint": "1.0.0",
45
- "@projitect/core": "1.0.0"
44
+ "@projitect/blueprint": "1.0.1",
45
+ "@projitect/core": "1.0.1"
46
46
  },
47
47
  "engines": {
48
48
  "node": ">=22.12.0"
@@ -1,12 +1,21 @@
1
1
  import { promises as fs } from "node:fs"
2
2
  import { spawn } from "node:child_process"
3
+ import { createRequire } from "node:module"
3
4
  import path from "node:path"
4
- import { Effect } from "effect"
5
+ import { Array, Effect, Option, Schema } from "effect"
5
6
  import { Errors } from "@projitect/core"
6
7
  import type { ProjitectConfig } from "@projitect/core"
8
+ import { detect, installDev as installDevelopment, installProject } from "../pm.js"
7
9
  import { remodel } from "./remodel.js"
8
10
  import type { RemodelResult } from "./remodel.js"
9
11
 
12
+ const manifest = Schema.decodeUnknownSync(
13
+ Schema.Struct({
14
+ version: Schema.String,
15
+ peerDependencies: Schema.Struct({ effect: Schema.String }),
16
+ }),
17
+ )(createRequire(import.meta.url)("../../package.json"))
18
+
10
19
  export interface InitResult {
11
20
  readonly seededBlueprintFile: boolean
12
21
  readonly bootstrappedGit: boolean
@@ -21,7 +30,8 @@ export interface InitResult {
21
30
  * `.pjt.ts` with the marker structure if absent, then delegates to `remodel` which runs the
22
31
  * standard plan/apply/lockfile-write pipeline. The projitect blueprint (prepended automatically
23
32
  * by `@projitect/cli`'s `pjt()`) writes the package.json entries and the `.pjt.ts` import region
24
- * on its first apply.
33
+ * on its first apply. Before seeding or loading the config, missing local CLI and Effect
34
+ * dependencies are installed so an ephemeral dlx invocation can resolve those imports.
25
35
  *
26
36
  * With `yes: true`, both prerequisites are auto-bootstrapped instead of erroring:
27
37
  * - Missing `.git/` → `git init -q` shell-out.
@@ -43,12 +53,18 @@ export const init = (params: {
43
53
  params.yes ?? false,
44
54
  )
45
55
 
56
+ const bootstrapPm = yield* ensureBootstrapDependencies(params.config.projectRoot)
57
+
46
58
  const seededBlueprintFile = yield* seedBlueprintFileIfAbsent(
47
59
  params.config.projectRoot,
48
60
  params.config.blueprintFile,
49
61
  )
50
62
 
51
63
  const remodelResult = yield* remodel({ config: params.config })
64
+ yield* Option.match(bootstrapPm, {
65
+ onNone: () => Effect.void,
66
+ onSome: (pm) => installProject({ projectRoot: params.config.projectRoot, pm }),
67
+ })
52
68
 
53
69
  return {
54
70
  seededBlueprintFile,
@@ -58,6 +74,30 @@ export const init = (params: {
58
74
  }
59
75
  })
60
76
 
77
+ /** A dlx runner lives outside the project; generated imports must resolve locally first. */
78
+ const ensureBootstrapDependencies = (projectRoot: string) =>
79
+ Effect.forEach(
80
+ [
81
+ { name: "@projitect/cli", spec: `@projitect/cli@${manifest.version}` },
82
+ { name: "effect", spec: `effect@${manifest.peerDependencies.effect}` },
83
+ ],
84
+ ({ name, spec }) =>
85
+ Effect.gen(function* () {
86
+ const installed = yield* Effect.promise(() =>
87
+ fs.access(path.join(projectRoot, "node_modules", name, "package.json")).then(
88
+ () => true,
89
+ () => false,
90
+ ),
91
+ )
92
+ if (installed) {
93
+ return Option.none()
94
+ }
95
+ const pm = yield* detect({ projectRoot })
96
+ yield* installDevelopment({ projectRoot, pm, pkg: spec })
97
+ return Option.some(pm)
98
+ }),
99
+ ).pipe(Effect.map((results) => Array.head(Array.getSomes(results))))
100
+
61
101
  const ensureGit = (
62
102
  projectRoot: string,
63
103
  yes: boolean,
package/src/pm.ts CHANGED
@@ -16,9 +16,9 @@ const LOCKFILES: readonly (readonly [string, PackageManager])[] = [
16
16
  ]
17
17
 
18
18
  /**
19
- * Detect the user's package manager by walking up from `projectRoot` looking for known
20
- * lockfiles. Falls back to `npm` if nothing is found. Used by `pjt add` to decide which install
21
- * command to shell out to.
19
+ * Detect the user's package manager from known lockfiles in `projectRoot`.
20
+ * Without a lockfile, uses the invoking package manager's user-agent, then `npm`.
21
+ * Used by `pjt add` and first-run bootstrap to select the install command.
22
22
  */
23
23
  export const detect = (params: {
24
24
  readonly projectRoot: string
@@ -34,7 +34,22 @@ export const detect = (params: {
34
34
  ),
35
35
  Option.match({
36
36
  onSome: ([, pm]) => pm,
37
- onNone: (): PackageManager => "npm",
37
+ onNone: (): PackageManager =>
38
+ Match.value(process.env["npm_config_user_agent"] ?? "").pipe(
39
+ Match.when(
40
+ (agent) => agent.startsWith("pnpm/"),
41
+ () => "pnpm" as const,
42
+ ),
43
+ Match.when(
44
+ (agent) => agent.startsWith("yarn/"),
45
+ () => "yarn" as const,
46
+ ),
47
+ Match.when(
48
+ (agent) => agent.startsWith("bun/"),
49
+ () => "bun" as const,
50
+ ),
51
+ Match.orElse(() => "npm" as const),
52
+ ),
38
53
  }),
39
54
  )
40
55
 
@@ -46,12 +61,30 @@ export const installDev = (params: {
46
61
  readonly projectRoot: string
47
62
  readonly pm: PackageManager
48
63
  readonly pkg: string
49
- }): Effect.Effect<void, Errors.PmInstallFailed> => {
50
- const args = installArgs(params.pm, params.pkg)
51
- return Effect.tryPromise({
64
+ }): Effect.Effect<void, Errors.PmInstallFailed> =>
65
+ runInstallation({ ...params, args: installArgs(params.pm, params.pkg) })
66
+
67
+ /** Synchronize the lockfile after bootstrap has applied its managed manifest ranges. */
68
+ export const installProject = (params: {
69
+ readonly projectRoot: string
70
+ readonly pm: PackageManager
71
+ }): Effect.Effect<void, Errors.PmInstallFailed> =>
72
+ runInstallation({
73
+ ...params,
74
+ pkg: "project dependencies",
75
+ args: params.pm === "pnpm" ? ["install", "--no-frozen-lockfile"] : ["install"],
76
+ })
77
+
78
+ const runInstallation = (params: {
79
+ readonly projectRoot: string
80
+ readonly pm: PackageManager
81
+ readonly pkg: string
82
+ readonly args: readonly string[]
83
+ }): Effect.Effect<void, Errors.PmInstallFailed> =>
84
+ Effect.tryPromise({
52
85
  try: () =>
53
86
  new Promise<void>((resolve, reject) => {
54
- const child = spawn(params.pm, args, {
87
+ const child = spawn(params.pm, params.args, {
55
88
  cwd: params.projectRoot,
56
89
  stdio: "inherit",
57
90
  })
@@ -60,7 +93,7 @@ export const installDev = (params: {
60
93
  if (code === 0) {
61
94
  resolve()
62
95
  } else {
63
- reject(new Error(`${params.pm} ${args.join(" ")} exited with ${String(code)}`))
96
+ reject(new Error(`${params.pm} ${params.args.join(" ")} exited with ${String(code)}`))
64
97
  }
65
98
  })
66
99
  }),
@@ -73,7 +106,6 @@ export const installDev = (params: {
73
106
  message: `Failed to install \`${params.pkg}\` via ${params.pm}`,
74
107
  }),
75
108
  })
76
- }
77
109
 
78
110
  const installArgs = (pm: PackageManager, pkg: string): readonly string[] =>
79
111
  Match.value(pm).pipe(