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.
- package/README.md +112 -10
- package/dist/bin/cli.js +1 -0
- package/dist/bin/cli.js.map +1 -1
- package/dist/src/commands/doctor.d.ts.map +1 -1
- package/dist/src/commands/doctor.js +33 -2
- package/dist/src/commands/doctor.js.map +1 -1
- package/dist/src/commands/doctor.test.js +63 -1
- package/dist/src/commands/doctor.test.js.map +1 -1
- package/dist/src/commands/init.d.ts +1 -0
- package/dist/src/commands/init.d.ts.map +1 -1
- package/dist/src/commands/init.js +40 -10
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/init.test.js +100 -1
- package/dist/src/commands/init.test.js.map +1 -1
- package/dist/src/commands/logs.js +1 -1
- package/dist/src/commands/logs.js.map +1 -1
- package/dist/src/commands/run.d.ts +16 -0
- package/dist/src/commands/run.d.ts.map +1 -1
- package/dist/src/commands/run.js +395 -37
- package/dist/src/commands/run.js.map +1 -1
- package/dist/src/commands/run.test.d.ts +2 -0
- package/dist/src/commands/run.test.d.ts.map +1 -0
- package/dist/src/commands/run.test.js +155 -0
- package/dist/src/commands/run.test.js.map +1 -0
- package/dist/src/commands/update.d.ts.map +1 -1
- package/dist/src/commands/update.js +9 -5
- package/dist/src/commands/update.js.map +1 -1
- package/dist/src/lib/manifest.d.ts +3 -1
- package/dist/src/lib/manifest.d.ts.map +1 -1
- package/dist/src/lib/manifest.js +2 -1
- package/dist/src/lib/manifest.js.map +1 -1
- package/dist/src/lib/stacks.d.ts +27 -0
- package/dist/src/lib/stacks.d.ts.map +1 -1
- package/dist/src/lib/stacks.js +154 -17
- package/dist/src/lib/stacks.js.map +1 -1
- package/dist/src/lib/stacks.test.js +343 -1
- package/dist/src/lib/stacks.test.js.map +1 -1
- package/dist/src/lib/system.d.ts +8 -0
- package/dist/src/lib/system.d.ts.map +1 -1
- package/dist/src/lib/system.js +23 -0
- package/dist/src/lib/system.js.map +1 -1
- package/dist/src/lib/tty.d.ts +31 -0
- package/dist/src/lib/tty.d.ts.map +1 -0
- package/dist/src/lib/tty.js +81 -0
- package/dist/src/lib/tty.js.map +1 -0
- package/dist/src/lib/tty.test.d.ts +2 -0
- package/dist/src/lib/tty.test.d.ts.map +1 -0
- package/dist/src/lib/tty.test.js +227 -0
- package/dist/src/lib/tty.test.js.map +1 -0
- package/package.json +1 -1
- package/templates/hooks/post-tool.sh +4 -2
- package/templates/scripts/new-feature.sh +33 -9
package/dist/src/lib/stacks.js
CHANGED
|
@@ -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
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
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
|
-
|
|
135
|
-
|
|
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
|
|
139
|
-
for (const file of STACKS.
|
|
261
|
+
// Check for Remix config files
|
|
262
|
+
for (const file of STACKS.remix.detection.files || []) {
|
|
140
263
|
if (await fileExists(file)) {
|
|
141
|
-
return "
|
|
264
|
+
return "remix";
|
|
142
265
|
}
|
|
143
266
|
}
|
|
144
|
-
// Check
|
|
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.
|
|
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":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;
|
|
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
|