sequant 1.1.3 → 1.2.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.
Files changed (52) hide show
  1. package/README.md +112 -10
  2. package/dist/bin/cli.js +1 -0
  3. package/dist/bin/cli.js.map +1 -1
  4. package/dist/src/commands/doctor.d.ts.map +1 -1
  5. package/dist/src/commands/doctor.js +33 -2
  6. package/dist/src/commands/doctor.js.map +1 -1
  7. package/dist/src/commands/doctor.test.js +63 -1
  8. package/dist/src/commands/doctor.test.js.map +1 -1
  9. package/dist/src/commands/init.d.ts +1 -0
  10. package/dist/src/commands/init.d.ts.map +1 -1
  11. package/dist/src/commands/init.js +40 -10
  12. package/dist/src/commands/init.js.map +1 -1
  13. package/dist/src/commands/init.test.js +100 -1
  14. package/dist/src/commands/init.test.js.map +1 -1
  15. package/dist/src/commands/logs.js +1 -1
  16. package/dist/src/commands/logs.js.map +1 -1
  17. package/dist/src/commands/run.d.ts +16 -0
  18. package/dist/src/commands/run.d.ts.map +1 -1
  19. package/dist/src/commands/run.js +395 -37
  20. package/dist/src/commands/run.js.map +1 -1
  21. package/dist/src/commands/run.test.d.ts +2 -0
  22. package/dist/src/commands/run.test.d.ts.map +1 -0
  23. package/dist/src/commands/run.test.js +155 -0
  24. package/dist/src/commands/run.test.js.map +1 -0
  25. package/dist/src/commands/update.d.ts.map +1 -1
  26. package/dist/src/commands/update.js +9 -5
  27. package/dist/src/commands/update.js.map +1 -1
  28. package/dist/src/lib/manifest.d.ts +3 -1
  29. package/dist/src/lib/manifest.d.ts.map +1 -1
  30. package/dist/src/lib/manifest.js +2 -1
  31. package/dist/src/lib/manifest.js.map +1 -1
  32. package/dist/src/lib/stacks.d.ts +27 -0
  33. package/dist/src/lib/stacks.d.ts.map +1 -1
  34. package/dist/src/lib/stacks.js +154 -17
  35. package/dist/src/lib/stacks.js.map +1 -1
  36. package/dist/src/lib/stacks.test.js +343 -1
  37. package/dist/src/lib/stacks.test.js.map +1 -1
  38. package/dist/src/lib/system.d.ts +8 -0
  39. package/dist/src/lib/system.d.ts.map +1 -1
  40. package/dist/src/lib/system.js +23 -0
  41. package/dist/src/lib/system.js.map +1 -1
  42. package/dist/src/lib/tty.d.ts +31 -0
  43. package/dist/src/lib/tty.d.ts.map +1 -0
  44. package/dist/src/lib/tty.js +81 -0
  45. package/dist/src/lib/tty.js.map +1 -0
  46. package/dist/src/lib/tty.test.d.ts +2 -0
  47. package/dist/src/lib/tty.test.d.ts.map +1 -0
  48. package/dist/src/lib/tty.test.js +227 -0
  49. package/dist/src/lib/tty.test.js.map +1 -0
  50. package/package.json +1 -1
  51. package/templates/hooks/post-tool.sh +4 -2
  52. package/templates/scripts/new-feature.sh +33 -9
@@ -2,6 +2,70 @@
2
2
  * Stack detection and configuration
3
3
  */
4
4
  import { fileExists, readFile } from "./fs.js";
5
+ /**
6
+ * Package manager configurations
7
+ */
8
+ export const PM_CONFIG = {
9
+ npm: {
10
+ run: "npm run",
11
+ exec: "npx",
12
+ install: "npm install",
13
+ installSilent: "npm install --silent",
14
+ },
15
+ bun: {
16
+ run: "bun run",
17
+ exec: "bunx",
18
+ install: "bun install",
19
+ installSilent: "bun install --silent",
20
+ },
21
+ yarn: {
22
+ run: "yarn",
23
+ exec: "yarn dlx",
24
+ install: "yarn install",
25
+ installSilent: "yarn install --silent",
26
+ },
27
+ pnpm: {
28
+ run: "pnpm run",
29
+ exec: "pnpm dlx",
30
+ install: "pnpm install",
31
+ installSilent: "pnpm install --silent",
32
+ },
33
+ };
34
+ /**
35
+ * Lockfile to package manager mapping (priority order: bun > yarn > pnpm > npm)
36
+ */
37
+ const LOCKFILE_PRIORITY = [
38
+ { file: "bun.lockb", pm: "bun" },
39
+ { file: "bun.lock", pm: "bun" },
40
+ { file: "yarn.lock", pm: "yarn" },
41
+ { file: "pnpm-lock.yaml", pm: "pnpm" },
42
+ { file: "package-lock.json", pm: "npm" },
43
+ ];
44
+ /**
45
+ * Detect package manager from lockfiles
46
+ * Priority: bun > yarn > pnpm > npm
47
+ * Falls back to npm if no lockfile found but package.json exists
48
+ */
49
+ export async function detectPackageManager() {
50
+ // Check lockfiles in priority order
51
+ for (const { file, pm } of LOCKFILE_PRIORITY) {
52
+ if (await fileExists(file)) {
53
+ return pm;
54
+ }
55
+ }
56
+ // Fallback to npm if package.json exists
57
+ if (await fileExists("package.json")) {
58
+ return "npm";
59
+ }
60
+ // Not a Node.js project
61
+ return null;
62
+ }
63
+ /**
64
+ * Get package manager command configuration
65
+ */
66
+ export function getPackageManagerCommands(pm) {
67
+ return PM_CONFIG[pm];
68
+ }
5
69
  export const STACKS = {
6
70
  nextjs: {
7
71
  name: "nextjs",
@@ -98,6 +162,66 @@ export const STACKS = {
98
162
  },
99
163
  devUrl: "http://localhost:4321",
100
164
  },
165
+ sveltekit: {
166
+ name: "sveltekit",
167
+ displayName: "SvelteKit",
168
+ detection: {
169
+ files: ["svelte.config.js", "svelte.config.ts"],
170
+ packageDeps: ["@sveltejs/kit"],
171
+ },
172
+ commands: {
173
+ test: "npm test",
174
+ build: "npm run build",
175
+ lint: "npm run lint",
176
+ dev: "npm run dev",
177
+ },
178
+ variables: {
179
+ TEST_COMMAND: "npm test",
180
+ BUILD_COMMAND: "npm run build",
181
+ LINT_COMMAND: "npm run lint",
182
+ },
183
+ devUrl: "http://localhost:5173",
184
+ },
185
+ remix: {
186
+ name: "remix",
187
+ displayName: "Remix",
188
+ detection: {
189
+ files: ["remix.config.js", "remix.config.ts"],
190
+ packageDeps: ["@remix-run/react"],
191
+ },
192
+ commands: {
193
+ test: "npm test",
194
+ build: "npm run build",
195
+ lint: "npm run lint",
196
+ dev: "npm run dev",
197
+ },
198
+ variables: {
199
+ TEST_COMMAND: "npm test",
200
+ BUILD_COMMAND: "npm run build",
201
+ LINT_COMMAND: "npm run lint",
202
+ },
203
+ devUrl: "http://localhost:5173",
204
+ },
205
+ nuxt: {
206
+ name: "nuxt",
207
+ displayName: "Nuxt",
208
+ detection: {
209
+ files: ["nuxt.config.ts", "nuxt.config.js"],
210
+ packageDeps: ["nuxt"],
211
+ },
212
+ commands: {
213
+ test: "npm test",
214
+ build: "npm run build",
215
+ lint: "npm run lint",
216
+ dev: "npm run dev",
217
+ },
218
+ variables: {
219
+ TEST_COMMAND: "npm test",
220
+ BUILD_COMMAND: "npm run build",
221
+ LINT_COMMAND: "npm run lint",
222
+ },
223
+ devUrl: "http://localhost:3000",
224
+ },
101
225
  generic: {
102
226
  name: "generic",
103
227
  displayName: "Generic",
@@ -116,39 +240,52 @@ export const STACKS = {
116
240
  },
117
241
  };
118
242
  export async function detectStack() {
119
- // Check for Next.js
243
+ // Check for Next.js config files
120
244
  for (const file of STACKS.nextjs.detection.files || []) {
121
245
  if (await fileExists(file)) {
122
246
  return "nextjs";
123
247
  }
124
248
  }
125
- // Check package.json for Next.js dependency
126
- if (await fileExists("package.json")) {
127
- try {
128
- const pkg = JSON.parse(await readFile("package.json"));
129
- const deps = { ...pkg.dependencies, ...pkg.devDependencies };
130
- if (deps.next) {
131
- return "nextjs";
132
- }
249
+ // Check for Astro config files
250
+ for (const file of STACKS.astro.detection.files || []) {
251
+ if (await fileExists(file)) {
252
+ return "astro";
133
253
  }
134
- catch {
135
- // Ignore parse errors
254
+ }
255
+ // Check for SvelteKit config files
256
+ for (const file of STACKS.sveltekit.detection.files || []) {
257
+ if (await fileExists(file)) {
258
+ return "sveltekit";
136
259
  }
137
260
  }
138
- // Check for Astro
139
- for (const file of STACKS.astro.detection.files || []) {
261
+ // Check for Remix config files
262
+ for (const file of STACKS.remix.detection.files || []) {
140
263
  if (await fileExists(file)) {
141
- return "astro";
264
+ return "remix";
142
265
  }
143
266
  }
144
- // Check package.json for Astro dependency
267
+ // Check for Nuxt config files
268
+ for (const file of STACKS.nuxt.detection.files || []) {
269
+ if (await fileExists(file)) {
270
+ return "nuxt";
271
+ }
272
+ }
273
+ // Check package.json for all JS framework dependencies (read once)
274
+ // Priority order: Next.js > Astro > SvelteKit > Remix > Nuxt
145
275
  if (await fileExists("package.json")) {
146
276
  try {
147
277
  const pkg = JSON.parse(await readFile("package.json"));
148
278
  const deps = { ...pkg.dependencies, ...pkg.devDependencies };
149
- if (deps.astro) {
279
+ if (deps.next)
280
+ return "nextjs";
281
+ if (deps.astro)
150
282
  return "astro";
151
- }
283
+ if (deps["@sveltejs/kit"])
284
+ return "sveltekit";
285
+ if (deps["@remix-run/react"])
286
+ return "remix";
287
+ if (deps.nuxt)
288
+ return "nuxt";
152
289
  }
153
290
  catch {
154
291
  // Ignore parse errors
@@ -1 +1 @@
1
- {"version":3,"file":"stacks.js","sourceRoot":"","sources":["../../../src/lib/stacks.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"stacks.js","sourceRoot":"","sources":["../../../src/lib/stacks.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { describe, it, expect, vi, beforeEach } from "vitest";
2
- import { detectStack, getStackConfig, STACKS } from "./stacks.js";
2
+ import { detectStack, getStackConfig, STACKS, detectPackageManager, getPackageManagerCommands, PM_CONFIG, } from "./stacks.js";
3
3
  // Mock the fs module
4
4
  vi.mock("./fs.js", () => ({
5
5
  fileExists: vi.fn(),
@@ -27,6 +27,66 @@ describe("STACKS", () => {
27
27
  expect(STACKS.astro.commands.lint).toBe("npm run lint");
28
28
  });
29
29
  });
30
+ describe("sveltekit config", () => {
31
+ it("has correct detection files", () => {
32
+ expect(STACKS.sveltekit.detection.files).toEqual([
33
+ "svelte.config.js",
34
+ "svelte.config.ts",
35
+ ]);
36
+ });
37
+ it("has @sveltejs/kit in packageDeps", () => {
38
+ expect(STACKS.sveltekit.detection.packageDeps).toContain("@sveltejs/kit");
39
+ });
40
+ it("has correct commands", () => {
41
+ expect(STACKS.sveltekit.commands.build).toBe("npm run build");
42
+ expect(STACKS.sveltekit.commands.dev).toBe("npm run dev");
43
+ expect(STACKS.sveltekit.commands.test).toBe("npm test");
44
+ expect(STACKS.sveltekit.commands.lint).toBe("npm run lint");
45
+ });
46
+ it("has correct devUrl for Vite-based server", () => {
47
+ expect(STACKS.sveltekit.devUrl).toBe("http://localhost:5173");
48
+ });
49
+ });
50
+ describe("remix config", () => {
51
+ it("has correct detection files", () => {
52
+ expect(STACKS.remix.detection.files).toEqual([
53
+ "remix.config.js",
54
+ "remix.config.ts",
55
+ ]);
56
+ });
57
+ it("has @remix-run/react in packageDeps", () => {
58
+ expect(STACKS.remix.detection.packageDeps).toContain("@remix-run/react");
59
+ });
60
+ it("has correct commands", () => {
61
+ expect(STACKS.remix.commands.build).toBe("npm run build");
62
+ expect(STACKS.remix.commands.dev).toBe("npm run dev");
63
+ expect(STACKS.remix.commands.test).toBe("npm test");
64
+ expect(STACKS.remix.commands.lint).toBe("npm run lint");
65
+ });
66
+ it("has correct devUrl for Vite-based server", () => {
67
+ expect(STACKS.remix.devUrl).toBe("http://localhost:5173");
68
+ });
69
+ });
70
+ describe("nuxt config", () => {
71
+ it("has correct detection files", () => {
72
+ expect(STACKS.nuxt.detection.files).toEqual([
73
+ "nuxt.config.ts",
74
+ "nuxt.config.js",
75
+ ]);
76
+ });
77
+ it("has nuxt in packageDeps", () => {
78
+ expect(STACKS.nuxt.detection.packageDeps).toContain("nuxt");
79
+ });
80
+ it("has correct commands", () => {
81
+ expect(STACKS.nuxt.commands.build).toBe("npm run build");
82
+ expect(STACKS.nuxt.commands.dev).toBe("npm run dev");
83
+ expect(STACKS.nuxt.commands.test).toBe("npm test");
84
+ expect(STACKS.nuxt.commands.lint).toBe("npm run lint");
85
+ });
86
+ it("has correct devUrl", () => {
87
+ expect(STACKS.nuxt.devUrl).toBe("http://localhost:3000");
88
+ });
89
+ });
30
90
  });
31
91
  describe("detectStack", () => {
32
92
  beforeEach(() => {
@@ -77,6 +137,114 @@ describe("detectStack", () => {
77
137
  expect(result).toBe("astro");
78
138
  });
79
139
  });
140
+ describe("SvelteKit detection", () => {
141
+ it("detects svelte.config.js", async () => {
142
+ mockFileExists.mockImplementation(async (path) => {
143
+ return path === "svelte.config.js";
144
+ });
145
+ const result = await detectStack();
146
+ expect(result).toBe("sveltekit");
147
+ });
148
+ it("detects svelte.config.ts", async () => {
149
+ mockFileExists.mockImplementation(async (path) => {
150
+ return path === "svelte.config.ts";
151
+ });
152
+ const result = await detectStack();
153
+ expect(result).toBe("sveltekit");
154
+ });
155
+ it("detects @sveltejs/kit in dependencies via package.json", async () => {
156
+ mockFileExists.mockImplementation(async (path) => {
157
+ return path === "package.json";
158
+ });
159
+ mockReadFile.mockResolvedValue(JSON.stringify({
160
+ dependencies: { "@sveltejs/kit": "^2.0.0" },
161
+ }));
162
+ const result = await detectStack();
163
+ expect(result).toBe("sveltekit");
164
+ });
165
+ it("detects @sveltejs/kit in devDependencies via package.json", async () => {
166
+ mockFileExists.mockImplementation(async (path) => {
167
+ return path === "package.json";
168
+ });
169
+ mockReadFile.mockResolvedValue(JSON.stringify({
170
+ devDependencies: { "@sveltejs/kit": "^2.0.0" },
171
+ }));
172
+ const result = await detectStack();
173
+ expect(result).toBe("sveltekit");
174
+ });
175
+ });
176
+ describe("Remix detection", () => {
177
+ it("detects remix.config.js", async () => {
178
+ mockFileExists.mockImplementation(async (path) => {
179
+ return path === "remix.config.js";
180
+ });
181
+ const result = await detectStack();
182
+ expect(result).toBe("remix");
183
+ });
184
+ it("detects remix.config.ts", async () => {
185
+ mockFileExists.mockImplementation(async (path) => {
186
+ return path === "remix.config.ts";
187
+ });
188
+ const result = await detectStack();
189
+ expect(result).toBe("remix");
190
+ });
191
+ it("detects @remix-run/react in dependencies via package.json", async () => {
192
+ mockFileExists.mockImplementation(async (path) => {
193
+ return path === "package.json";
194
+ });
195
+ mockReadFile.mockResolvedValue(JSON.stringify({
196
+ dependencies: { "@remix-run/react": "^2.0.0" },
197
+ }));
198
+ const result = await detectStack();
199
+ expect(result).toBe("remix");
200
+ });
201
+ it("detects @remix-run/react in devDependencies via package.json", async () => {
202
+ mockFileExists.mockImplementation(async (path) => {
203
+ return path === "package.json";
204
+ });
205
+ mockReadFile.mockResolvedValue(JSON.stringify({
206
+ devDependencies: { "@remix-run/react": "^2.0.0" },
207
+ }));
208
+ const result = await detectStack();
209
+ expect(result).toBe("remix");
210
+ });
211
+ });
212
+ describe("Nuxt detection", () => {
213
+ it("detects nuxt.config.ts", async () => {
214
+ mockFileExists.mockImplementation(async (path) => {
215
+ return path === "nuxt.config.ts";
216
+ });
217
+ const result = await detectStack();
218
+ expect(result).toBe("nuxt");
219
+ });
220
+ it("detects nuxt.config.js", async () => {
221
+ mockFileExists.mockImplementation(async (path) => {
222
+ return path === "nuxt.config.js";
223
+ });
224
+ const result = await detectStack();
225
+ expect(result).toBe("nuxt");
226
+ });
227
+ it("detects nuxt in dependencies via package.json", async () => {
228
+ mockFileExists.mockImplementation(async (path) => {
229
+ return path === "package.json";
230
+ });
231
+ mockReadFile.mockResolvedValue(JSON.stringify({
232
+ dependencies: { nuxt: "^3.0.0" },
233
+ }));
234
+ const result = await detectStack();
235
+ expect(result).toBe("nuxt");
236
+ });
237
+ it("detects nuxt in devDependencies via package.json", async () => {
238
+ mockFileExists.mockImplementation(async (path) => {
239
+ return path === "package.json";
240
+ });
241
+ mockReadFile.mockResolvedValue(JSON.stringify({
242
+ devDependencies: { nuxt: "^3.0.0" },
243
+ }));
244
+ const result = await detectStack();
245
+ expect(result).toBe("nuxt");
246
+ });
247
+ });
80
248
  describe("priority", () => {
81
249
  it("Next.js takes priority over Astro when both present", async () => {
82
250
  mockFileExists.mockImplementation(async (path) => {
@@ -102,6 +270,47 @@ describe("detectStack", () => {
102
270
  const result = await detectStack();
103
271
  expect(result).toBe("astro");
104
272
  });
273
+ it("Astro takes priority over SvelteKit when both present", async () => {
274
+ mockFileExists.mockImplementation(async (path) => {
275
+ return path === "astro.config.mjs" || path === "svelte.config.js";
276
+ });
277
+ const result = await detectStack();
278
+ expect(result).toBe("astro");
279
+ });
280
+ it("SvelteKit takes priority over Remix when both present", async () => {
281
+ mockFileExists.mockImplementation(async (path) => {
282
+ return path === "svelte.config.js" || path === "remix.config.js";
283
+ });
284
+ const result = await detectStack();
285
+ expect(result).toBe("sveltekit");
286
+ });
287
+ it("Remix takes priority over Nuxt when both present", async () => {
288
+ mockFileExists.mockImplementation(async (path) => {
289
+ return path === "remix.config.js" || path === "nuxt.config.ts";
290
+ });
291
+ const result = await detectStack();
292
+ expect(result).toBe("remix");
293
+ });
294
+ it("SvelteKit dep takes priority over Remix dep", async () => {
295
+ mockFileExists.mockImplementation(async (path) => {
296
+ return path === "package.json";
297
+ });
298
+ mockReadFile.mockResolvedValue(JSON.stringify({
299
+ dependencies: {
300
+ "@sveltejs/kit": "^2.0.0",
301
+ "@remix-run/react": "^2.0.0",
302
+ },
303
+ }));
304
+ const result = await detectStack();
305
+ expect(result).toBe("sveltekit");
306
+ });
307
+ it("Nuxt config file takes priority over Rust", async () => {
308
+ mockFileExists.mockImplementation(async (path) => {
309
+ return path === "nuxt.config.ts" || path === "Cargo.toml";
310
+ });
311
+ const result = await detectStack();
312
+ expect(result).toBe("nuxt");
313
+ });
105
314
  });
106
315
  describe("edge cases", () => {
107
316
  it("returns null when no stack detected", async () => {
@@ -133,6 +342,21 @@ describe("getStackConfig", () => {
133
342
  expect(config.name).toBe("astro");
134
343
  expect(config.displayName).toBe("Astro");
135
344
  });
345
+ it("returns sveltekit config for sveltekit stack", () => {
346
+ const config = getStackConfig("sveltekit");
347
+ expect(config.name).toBe("sveltekit");
348
+ expect(config.displayName).toBe("SvelteKit");
349
+ });
350
+ it("returns remix config for remix stack", () => {
351
+ const config = getStackConfig("remix");
352
+ expect(config.name).toBe("remix");
353
+ expect(config.displayName).toBe("Remix");
354
+ });
355
+ it("returns nuxt config for nuxt stack", () => {
356
+ const config = getStackConfig("nuxt");
357
+ expect(config.name).toBe("nuxt");
358
+ expect(config.displayName).toBe("Nuxt");
359
+ });
136
360
  it("returns generic config for unknown stack", () => {
137
361
  const config = getStackConfig("unknown-stack");
138
362
  expect(config.name).toBe("generic");
@@ -142,4 +366,122 @@ describe("getStackConfig", () => {
142
366
  expect(config.name).toBe("generic");
143
367
  });
144
368
  });
369
+ describe("detectPackageManager", () => {
370
+ beforeEach(() => {
371
+ vi.resetAllMocks();
372
+ mockFileExists.mockResolvedValue(false);
373
+ });
374
+ describe("lockfile detection", () => {
375
+ it("detects bun.lockb", async () => {
376
+ mockFileExists.mockImplementation(async (path) => {
377
+ return path === "bun.lockb";
378
+ });
379
+ const result = await detectPackageManager();
380
+ expect(result).toBe("bun");
381
+ });
382
+ it("detects bun.lock", async () => {
383
+ mockFileExists.mockImplementation(async (path) => {
384
+ return path === "bun.lock";
385
+ });
386
+ const result = await detectPackageManager();
387
+ expect(result).toBe("bun");
388
+ });
389
+ it("detects yarn.lock", async () => {
390
+ mockFileExists.mockImplementation(async (path) => {
391
+ return path === "yarn.lock";
392
+ });
393
+ const result = await detectPackageManager();
394
+ expect(result).toBe("yarn");
395
+ });
396
+ it("detects pnpm-lock.yaml", async () => {
397
+ mockFileExists.mockImplementation(async (path) => {
398
+ return path === "pnpm-lock.yaml";
399
+ });
400
+ const result = await detectPackageManager();
401
+ expect(result).toBe("pnpm");
402
+ });
403
+ it("detects package-lock.json", async () => {
404
+ mockFileExists.mockImplementation(async (path) => {
405
+ return path === "package-lock.json";
406
+ });
407
+ const result = await detectPackageManager();
408
+ expect(result).toBe("npm");
409
+ });
410
+ });
411
+ describe("priority", () => {
412
+ it("bun takes priority over yarn", async () => {
413
+ mockFileExists.mockImplementation(async (path) => {
414
+ return path === "bun.lockb" || path === "yarn.lock";
415
+ });
416
+ const result = await detectPackageManager();
417
+ expect(result).toBe("bun");
418
+ });
419
+ it("yarn takes priority over pnpm", async () => {
420
+ mockFileExists.mockImplementation(async (path) => {
421
+ return path === "yarn.lock" || path === "pnpm-lock.yaml";
422
+ });
423
+ const result = await detectPackageManager();
424
+ expect(result).toBe("yarn");
425
+ });
426
+ it("pnpm takes priority over npm", async () => {
427
+ mockFileExists.mockImplementation(async (path) => {
428
+ return path === "pnpm-lock.yaml" || path === "package-lock.json";
429
+ });
430
+ const result = await detectPackageManager();
431
+ expect(result).toBe("pnpm");
432
+ });
433
+ });
434
+ describe("fallback behavior", () => {
435
+ it("falls back to npm when only package.json exists", async () => {
436
+ mockFileExists.mockImplementation(async (path) => {
437
+ return path === "package.json";
438
+ });
439
+ const result = await detectPackageManager();
440
+ expect(result).toBe("npm");
441
+ });
442
+ it("returns null when no package.json exists", async () => {
443
+ mockFileExists.mockResolvedValue(false);
444
+ const result = await detectPackageManager();
445
+ expect(result).toBeNull();
446
+ });
447
+ });
448
+ });
449
+ describe("getPackageManagerCommands", () => {
450
+ it("returns correct npm commands", () => {
451
+ const config = getPackageManagerCommands("npm");
452
+ expect(config.run).toBe("npm run");
453
+ expect(config.exec).toBe("npx");
454
+ expect(config.install).toBe("npm install");
455
+ expect(config.installSilent).toBe("npm install --silent");
456
+ });
457
+ it("returns correct bun commands", () => {
458
+ const config = getPackageManagerCommands("bun");
459
+ expect(config.run).toBe("bun run");
460
+ expect(config.exec).toBe("bunx");
461
+ expect(config.install).toBe("bun install");
462
+ expect(config.installSilent).toBe("bun install --silent");
463
+ });
464
+ it("returns correct yarn commands", () => {
465
+ const config = getPackageManagerCommands("yarn");
466
+ expect(config.run).toBe("yarn");
467
+ expect(config.exec).toBe("yarn dlx");
468
+ expect(config.install).toBe("yarn install");
469
+ expect(config.installSilent).toBe("yarn install --silent");
470
+ });
471
+ it("returns correct pnpm commands", () => {
472
+ const config = getPackageManagerCommands("pnpm");
473
+ expect(config.run).toBe("pnpm run");
474
+ expect(config.exec).toBe("pnpm dlx");
475
+ expect(config.install).toBe("pnpm install");
476
+ expect(config.installSilent).toBe("pnpm install --silent");
477
+ });
478
+ });
479
+ describe("PM_CONFIG", () => {
480
+ it("has all supported package managers", () => {
481
+ expect(PM_CONFIG).toHaveProperty("npm");
482
+ expect(PM_CONFIG).toHaveProperty("bun");
483
+ expect(PM_CONFIG).toHaveProperty("yarn");
484
+ expect(PM_CONFIG).toHaveProperty("pnpm");
485
+ });
486
+ });
145
487
  //# sourceMappingURL=stacks.test.js.map