@inspecto-dev/cli 0.3.3 → 0.3.5
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/.turbo/turbo-build.log +7 -7
- package/.turbo/turbo-test.log +10594 -4044
- package/CHANGELOG.md +28 -0
- package/dist/bin.js +36 -2
- package/dist/{chunk-LJOKPCPD.js → chunk-7ABJRH3F.js} +1701 -182
- package/dist/index.d.ts +69 -4
- package/dist/index.js +7 -1
- package/package.json +3 -3
- package/src/bin.ts +49 -1
- package/src/commands/dev-config.ts +109 -0
- package/src/commands/doctor.ts +189 -9
- package/src/commands/init.ts +10 -3
- package/src/commands/integration-automation.ts +2 -0
- package/src/commands/integration-host-ide.ts +18 -15
- package/src/commands/integration-install.ts +100 -5
- package/src/commands/onboard.ts +80 -15
- package/src/detect/build-tool.ts +212 -15
- package/src/detect/framework.ts +3 -0
- package/src/detect/package-manager.ts +1 -1
- package/src/index.ts +1 -0
- package/src/inject/gitignore.ts +13 -2
- package/src/instructions.ts +33 -7
- package/src/onboarding/apply.ts +255 -28
- package/src/onboarding/nextjs-guidance.ts +257 -0
- package/src/onboarding/nuxt-guidance.ts +129 -0
- package/src/onboarding/planner.ts +337 -10
- package/src/onboarding/session.ts +127 -31
- package/src/onboarding/target-resolution.ts +79 -3
- package/src/onboarding/umi-guidance.ts +139 -0
- package/src/types.ts +58 -3
- package/tests/apply.test.ts +553 -0
- package/tests/build-tool.test.ts +199 -0
- package/tests/dev-config.test.ts +73 -0
- package/tests/doctor.test.ts +130 -0
- package/tests/init.test.ts +17 -0
- package/tests/install-wrapper.test.ts +56 -0
- package/tests/instructions.test.ts +10 -6
- package/tests/integration-host-ide.test.ts +20 -0
- package/tests/integration-install.test.ts +193 -0
- package/tests/nextjs-guidance.test.ts +128 -0
- package/tests/nuxt-guidance.test.ts +67 -0
- package/tests/onboard.test.ts +511 -0
- package/tests/plan.test.ts +283 -21
- package/tests/runner-script.test.ts +120 -1
- package/tests/session-resolve.test.ts +116 -0
- package/tests/session.test.ts +120 -0
package/tests/apply.test.ts
CHANGED
|
@@ -33,7 +33,9 @@ vi.mock('../src/detect/package-manager.js', async () => {
|
|
|
33
33
|
|
|
34
34
|
vi.mock('../src/utils/fs.js', () => ({
|
|
35
35
|
exists: vi.fn(),
|
|
36
|
+
readFile: vi.fn(),
|
|
36
37
|
readJSON: vi.fn(),
|
|
38
|
+
writeFile: vi.fn(),
|
|
37
39
|
writeJSON: vi.fn(),
|
|
38
40
|
}))
|
|
39
41
|
|
|
@@ -80,7 +82,9 @@ describe('apply onboarding flow', () => {
|
|
|
80
82
|
mutations: [{ type: 'file_modified', path: 'vite.config.ts' }],
|
|
81
83
|
})
|
|
82
84
|
vi.mocked(fsUtils.exists).mockResolvedValue(false)
|
|
85
|
+
vi.mocked(fsUtils.readFile).mockResolvedValue(null)
|
|
83
86
|
vi.mocked(fsUtils.readJSON).mockResolvedValue(null)
|
|
87
|
+
vi.mocked(fsUtils.writeFile).mockResolvedValue()
|
|
84
88
|
vi.mocked(gitignoreUtils.updateGitignore).mockResolvedValue()
|
|
85
89
|
vi.mocked(extensionUtils.installExtension).mockResolvedValue({
|
|
86
90
|
type: 'extension_installed',
|
|
@@ -166,6 +170,488 @@ describe('apply onboarding flow', () => {
|
|
|
166
170
|
})
|
|
167
171
|
})
|
|
168
172
|
|
|
173
|
+
it('only injects the explicitly selected build target', async () => {
|
|
174
|
+
const rspackBuild: BuildToolDetection = {
|
|
175
|
+
tool: 'rspack',
|
|
176
|
+
configPath: 'finder/rspack.config.ts',
|
|
177
|
+
label: 'Rspack (finder/rspack.config.ts)',
|
|
178
|
+
packagePath: 'finder',
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const result = await applyOnboardingPlan({
|
|
182
|
+
repoRoot: '/repo',
|
|
183
|
+
projectRoot: '/repo/finder',
|
|
184
|
+
packageManager: 'pnpm',
|
|
185
|
+
supportedBuildTargets: [rspackBuild],
|
|
186
|
+
options: {
|
|
187
|
+
shared: false,
|
|
188
|
+
skipInstall: false,
|
|
189
|
+
dryRun: false,
|
|
190
|
+
noExtension: false,
|
|
191
|
+
},
|
|
192
|
+
selectedIDE: { ide: 'vscode', supported: true },
|
|
193
|
+
providerDefault: 'codex.extension',
|
|
194
|
+
plan: {
|
|
195
|
+
status: 'ok',
|
|
196
|
+
warnings: [],
|
|
197
|
+
blockers: [],
|
|
198
|
+
strategy: 'supported',
|
|
199
|
+
actions: [],
|
|
200
|
+
defaults: {
|
|
201
|
+
shared: false,
|
|
202
|
+
extension: true,
|
|
203
|
+
provider: 'codex',
|
|
204
|
+
ide: 'vscode',
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
expect(astInjectorUtils.injectPlugin).toHaveBeenCalledTimes(1)
|
|
210
|
+
expect(astInjectorUtils.injectPlugin).toHaveBeenCalledWith('/repo', rspackBuild, false, false)
|
|
211
|
+
expect(result.postInstall.injectionFailed).toBe(false)
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
it('supports legacy rspack partial onboarding without attempting automatic injection', async () => {
|
|
215
|
+
const legacyRspackBuild: BuildToolDetection = {
|
|
216
|
+
tool: 'rspack',
|
|
217
|
+
configPath: 'finder/rspack-config/rspack.config.dev.ts',
|
|
218
|
+
label: 'Rspack (finder/rspack-config/rspack.config.dev.ts) [Legacy]',
|
|
219
|
+
packagePath: 'finder',
|
|
220
|
+
isLegacyRspack: true,
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const result = await applyOnboardingPlan({
|
|
224
|
+
repoRoot: '/repo',
|
|
225
|
+
projectRoot: '/repo/finder',
|
|
226
|
+
packageManager: 'pnpm',
|
|
227
|
+
supportedBuildTargets: [legacyRspackBuild],
|
|
228
|
+
options: {
|
|
229
|
+
shared: false,
|
|
230
|
+
skipInstall: false,
|
|
231
|
+
dryRun: false,
|
|
232
|
+
noExtension: false,
|
|
233
|
+
},
|
|
234
|
+
selectedIDE: { ide: 'trae', supported: true },
|
|
235
|
+
providerDefault: 'coco.cli',
|
|
236
|
+
plan: {
|
|
237
|
+
status: 'warning',
|
|
238
|
+
warnings: [
|
|
239
|
+
{
|
|
240
|
+
code: 'legacy-rspack-requires-manual-config',
|
|
241
|
+
message:
|
|
242
|
+
'Legacy Rspack detected at finder/rspack-config/rspack.config.dev.ts. Inspecto must use the legacy Rspack plugin entry and manual config steps.',
|
|
243
|
+
},
|
|
244
|
+
],
|
|
245
|
+
blockers: [],
|
|
246
|
+
strategy: 'manual',
|
|
247
|
+
actions: [
|
|
248
|
+
{
|
|
249
|
+
type: 'install_dependency',
|
|
250
|
+
target: '@inspecto-dev/plugin @inspecto-dev/core',
|
|
251
|
+
description: 'Install the Inspecto runtime packages with pnpm.',
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
type: 'manual_step',
|
|
255
|
+
target: 'finder/rspack-config/rspack.config.dev.ts',
|
|
256
|
+
description:
|
|
257
|
+
'Update finder/rspack-config/rspack.config.dev.ts to import `rspackPlugin` from `@inspecto-dev/plugin/legacy/rspack` and add it to the Rspack plugins array.',
|
|
258
|
+
},
|
|
259
|
+
],
|
|
260
|
+
defaults: {
|
|
261
|
+
shared: false,
|
|
262
|
+
extension: true,
|
|
263
|
+
provider: 'coco',
|
|
264
|
+
ide: 'trae',
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
allowManualPlanApply: true,
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
expect(astInjectorUtils.injectPlugin).not.toHaveBeenCalled()
|
|
271
|
+
expect(result.status).toBe('warning')
|
|
272
|
+
expect(result.postInstall.nextSteps).toContain(
|
|
273
|
+
'Update finder/rspack-config/rspack.config.dev.ts to import `rspackPlugin` from `@inspecto-dev/plugin/legacy/rspack` and add it to the Rspack plugins array.',
|
|
274
|
+
)
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
it('supports webpack 4 partial onboarding without attempting automatic injection', async () => {
|
|
278
|
+
const legacyWebpackBuild: BuildToolDetection = {
|
|
279
|
+
tool: 'webpack',
|
|
280
|
+
configPath: 'app/webpack.config.js',
|
|
281
|
+
label: 'Webpack (app/webpack.config.js) [Webpack 4]',
|
|
282
|
+
packagePath: 'app',
|
|
283
|
+
isLegacyWebpack: true,
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
const result = await applyOnboardingPlan({
|
|
287
|
+
repoRoot: '/repo',
|
|
288
|
+
projectRoot: '/repo/app',
|
|
289
|
+
packageManager: 'pnpm',
|
|
290
|
+
supportedBuildTargets: [legacyWebpackBuild],
|
|
291
|
+
options: {
|
|
292
|
+
shared: false,
|
|
293
|
+
skipInstall: false,
|
|
294
|
+
dryRun: false,
|
|
295
|
+
noExtension: false,
|
|
296
|
+
},
|
|
297
|
+
selectedIDE: { ide: 'cursor', supported: true },
|
|
298
|
+
providerDefault: 'copilot.extension',
|
|
299
|
+
plan: {
|
|
300
|
+
status: 'warning',
|
|
301
|
+
warnings: [
|
|
302
|
+
{
|
|
303
|
+
code: 'legacy-webpack4-requires-manual-config',
|
|
304
|
+
message:
|
|
305
|
+
'Webpack 4 detected at app/webpack.config.js. Inspecto must use the legacy Webpack 4 plugin entry and manual config steps.',
|
|
306
|
+
},
|
|
307
|
+
],
|
|
308
|
+
blockers: [],
|
|
309
|
+
strategy: 'manual',
|
|
310
|
+
actions: [
|
|
311
|
+
{
|
|
312
|
+
type: 'install_dependency',
|
|
313
|
+
target: '@inspecto-dev/plugin @inspecto-dev/core',
|
|
314
|
+
description: 'Install the Inspecto runtime packages with pnpm.',
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
type: 'manual_step',
|
|
318
|
+
target: 'app/webpack.config.js',
|
|
319
|
+
description:
|
|
320
|
+
'Update app/webpack.config.js to import `webpackPlugin` from `@inspecto-dev/plugin/legacy/webpack4` and add it to the Webpack plugins array.',
|
|
321
|
+
},
|
|
322
|
+
],
|
|
323
|
+
defaults: {
|
|
324
|
+
shared: false,
|
|
325
|
+
extension: true,
|
|
326
|
+
provider: 'copilot',
|
|
327
|
+
ide: 'cursor',
|
|
328
|
+
},
|
|
329
|
+
},
|
|
330
|
+
allowManualPlanApply: true,
|
|
331
|
+
})
|
|
332
|
+
|
|
333
|
+
expect(astInjectorUtils.injectPlugin).not.toHaveBeenCalled()
|
|
334
|
+
expect(result.status).toBe('warning')
|
|
335
|
+
expect(result.postInstall.nextSteps).toContain(
|
|
336
|
+
'Update app/webpack.config.js to import `webpackPlugin` from `@inspecto-dev/plugin/legacy/webpack4` and add it to the Webpack plugins array.',
|
|
337
|
+
)
|
|
338
|
+
})
|
|
339
|
+
|
|
340
|
+
it('auto-applies high-confidence Next.js config patches for guided plans', async () => {
|
|
341
|
+
vi.mocked(fsUtils.readFile).mockImplementation(async filePath => {
|
|
342
|
+
if (filePath === '/repo/next.config.mjs') {
|
|
343
|
+
return 'export default {\n reactStrictMode: true,\n}\n'
|
|
344
|
+
}
|
|
345
|
+
return null
|
|
346
|
+
})
|
|
347
|
+
|
|
348
|
+
const result = await applyOnboardingPlan({
|
|
349
|
+
repoRoot: '/repo',
|
|
350
|
+
projectRoot: '/repo',
|
|
351
|
+
packageManager: 'pnpm',
|
|
352
|
+
supportedBuildTargets: [],
|
|
353
|
+
options: {
|
|
354
|
+
shared: false,
|
|
355
|
+
skipInstall: false,
|
|
356
|
+
dryRun: false,
|
|
357
|
+
noExtension: false,
|
|
358
|
+
},
|
|
359
|
+
selectedIDE: { ide: 'vscode', supported: true },
|
|
360
|
+
providerDefault: 'codex.extension',
|
|
361
|
+
plan: {
|
|
362
|
+
status: 'warning',
|
|
363
|
+
warnings: [],
|
|
364
|
+
blockers: [],
|
|
365
|
+
strategy: 'guided',
|
|
366
|
+
actions: [
|
|
367
|
+
{
|
|
368
|
+
type: 'install_dependency',
|
|
369
|
+
target: '@inspecto-dev/plugin @inspecto-dev/core',
|
|
370
|
+
description: 'Install the Inspecto runtime packages with pnpm.',
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
type: 'generate_patch_plan',
|
|
374
|
+
target: 'next.config',
|
|
375
|
+
description:
|
|
376
|
+
'Generate a guided patch plan for the Next.js Inspecto webpack integration.',
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
type: 'manual_confirmation',
|
|
380
|
+
target: '/repo',
|
|
381
|
+
description:
|
|
382
|
+
'Complete the remaining client-side Inspecto mount step in your assistant or editor.',
|
|
383
|
+
},
|
|
384
|
+
],
|
|
385
|
+
defaults: {
|
|
386
|
+
provider: 'codex',
|
|
387
|
+
ide: 'vscode',
|
|
388
|
+
shared: false,
|
|
389
|
+
extension: true,
|
|
390
|
+
},
|
|
391
|
+
framework: 'react',
|
|
392
|
+
metaFramework: 'Next.js',
|
|
393
|
+
routerMode: 'app',
|
|
394
|
+
autoApplied: ['dependencies', 'inspecto_settings'],
|
|
395
|
+
pendingSteps: [
|
|
396
|
+
'Review the generated Next.js patch plan for next.config.mjs.',
|
|
397
|
+
'Complete the remaining client-side mount step for your App Router entry.',
|
|
398
|
+
],
|
|
399
|
+
assistantPrompt: 'Complete the remaining Inspecto onboarding for this Next.js project.',
|
|
400
|
+
patches: [
|
|
401
|
+
{
|
|
402
|
+
path: 'next.config.mjs',
|
|
403
|
+
status: 'planned',
|
|
404
|
+
reason: 'next_config_object_export',
|
|
405
|
+
confidence: 'high',
|
|
406
|
+
snippet:
|
|
407
|
+
"import { webpackPlugin as inspecto } from '@inspecto-dev/plugin'\n\nwebpack(config, { dev, isServer }) {\n if (dev && !isServer) {\n config.plugins.push(inspecto())\n }\n return config\n}",
|
|
408
|
+
},
|
|
409
|
+
],
|
|
410
|
+
},
|
|
411
|
+
allowManualPlanApply: true,
|
|
412
|
+
})
|
|
413
|
+
|
|
414
|
+
expect(astInjectorUtils.injectPlugin).not.toHaveBeenCalled()
|
|
415
|
+
expect(fsUtils.writeFile).toHaveBeenCalledWith(
|
|
416
|
+
'/repo/next.config.mjs',
|
|
417
|
+
expect.stringContaining("import { webpackPlugin as inspecto } from '@inspecto-dev/plugin'"),
|
|
418
|
+
)
|
|
419
|
+
expect(fsUtils.writeFile).toHaveBeenCalledWith(
|
|
420
|
+
'/repo/next.config.mjs',
|
|
421
|
+
expect.stringContaining('if (dev) {\n config.plugins.push(inspecto())'),
|
|
422
|
+
)
|
|
423
|
+
expect(result.mutations).toEqual(
|
|
424
|
+
expect.arrayContaining([
|
|
425
|
+
{
|
|
426
|
+
type: 'file_modified',
|
|
427
|
+
path: 'next.config.mjs',
|
|
428
|
+
description: 'Automatically configured Inspecto guided Next.js patch',
|
|
429
|
+
},
|
|
430
|
+
]),
|
|
431
|
+
)
|
|
432
|
+
expect(result.postInstall.nextSteps).toContain(
|
|
433
|
+
'Complete the remaining client-side Inspecto mount step in your assistant or editor.',
|
|
434
|
+
)
|
|
435
|
+
})
|
|
436
|
+
|
|
437
|
+
it('auto-applies high-confidence Next.js patches for exported nextConfig objects', async () => {
|
|
438
|
+
vi.mocked(fsUtils.readFile).mockImplementation(async filePath => {
|
|
439
|
+
if (filePath === '/repo/next.config.ts') {
|
|
440
|
+
return "import type { NextConfig } from 'next'\nconst nextConfig: NextConfig = {\n reactStrictMode: true,\n}\n\nexport default nextConfig\n"
|
|
441
|
+
}
|
|
442
|
+
return null
|
|
443
|
+
})
|
|
444
|
+
|
|
445
|
+
const result = await applyOnboardingPlan({
|
|
446
|
+
repoRoot: '/repo',
|
|
447
|
+
projectRoot: '/repo',
|
|
448
|
+
packageManager: 'pnpm',
|
|
449
|
+
supportedBuildTargets: [],
|
|
450
|
+
options: {
|
|
451
|
+
shared: false,
|
|
452
|
+
skipInstall: false,
|
|
453
|
+
dryRun: false,
|
|
454
|
+
noExtension: false,
|
|
455
|
+
},
|
|
456
|
+
selectedIDE: { ide: 'vscode', supported: true },
|
|
457
|
+
providerDefault: 'codex.extension',
|
|
458
|
+
plan: {
|
|
459
|
+
status: 'warning',
|
|
460
|
+
warnings: [],
|
|
461
|
+
blockers: [],
|
|
462
|
+
strategy: 'guided',
|
|
463
|
+
actions: [],
|
|
464
|
+
defaults: {
|
|
465
|
+
provider: 'codex',
|
|
466
|
+
ide: 'vscode',
|
|
467
|
+
shared: false,
|
|
468
|
+
extension: true,
|
|
469
|
+
},
|
|
470
|
+
framework: 'react',
|
|
471
|
+
metaFramework: 'Next.js',
|
|
472
|
+
routerMode: 'app',
|
|
473
|
+
autoApplied: ['dependencies', 'inspecto_settings'],
|
|
474
|
+
pendingSteps: [
|
|
475
|
+
'Review the generated Next.js patch plan for next.config.ts.',
|
|
476
|
+
'Complete the remaining client-side mount step for your App Router entry.',
|
|
477
|
+
],
|
|
478
|
+
assistantPrompt: 'Complete the remaining Inspecto onboarding for this Next.js project.',
|
|
479
|
+
patches: [
|
|
480
|
+
{
|
|
481
|
+
path: 'next.config.ts',
|
|
482
|
+
status: 'planned',
|
|
483
|
+
reason: 'next_config_object_export',
|
|
484
|
+
confidence: 'high',
|
|
485
|
+
snippet:
|
|
486
|
+
"import { webpackPlugin as inspecto } from '@inspecto-dev/plugin'\n\nwebpack(config, { dev, isServer }) {\n if (dev && !isServer) {\n config.plugins.push(inspecto())\n }\n return config\n}",
|
|
487
|
+
},
|
|
488
|
+
],
|
|
489
|
+
},
|
|
490
|
+
allowManualPlanApply: true,
|
|
491
|
+
})
|
|
492
|
+
|
|
493
|
+
expect(fsUtils.writeFile).toHaveBeenCalledWith(
|
|
494
|
+
'/repo/next.config.ts',
|
|
495
|
+
expect.stringContaining("import { webpackPlugin as inspecto } from '@inspecto-dev/plugin'"),
|
|
496
|
+
)
|
|
497
|
+
expect(fsUtils.writeFile).toHaveBeenCalledWith(
|
|
498
|
+
'/repo/next.config.ts',
|
|
499
|
+
expect.stringContaining(
|
|
500
|
+
'const nextConfig: NextConfig = {\n webpack(config, { dev, isServer }) {',
|
|
501
|
+
),
|
|
502
|
+
)
|
|
503
|
+
expect(fsUtils.writeFile).toHaveBeenCalledWith(
|
|
504
|
+
'/repo/next.config.ts',
|
|
505
|
+
expect.not.stringContaining('!isServer'),
|
|
506
|
+
)
|
|
507
|
+
expect(result.mutations).toEqual(
|
|
508
|
+
expect.arrayContaining([
|
|
509
|
+
expect.objectContaining({
|
|
510
|
+
path: 'next.config.ts',
|
|
511
|
+
description: 'Automatically configured Inspecto guided Next.js patch',
|
|
512
|
+
}),
|
|
513
|
+
]),
|
|
514
|
+
)
|
|
515
|
+
})
|
|
516
|
+
|
|
517
|
+
it('preserves manual patch follow-up for guided Next.js plans that are not auto-applicable', async () => {
|
|
518
|
+
const result = await applyOnboardingPlan({
|
|
519
|
+
repoRoot: '/repo',
|
|
520
|
+
projectRoot: '/repo',
|
|
521
|
+
packageManager: 'pnpm',
|
|
522
|
+
supportedBuildTargets: [],
|
|
523
|
+
options: {
|
|
524
|
+
shared: false,
|
|
525
|
+
skipInstall: false,
|
|
526
|
+
dryRun: false,
|
|
527
|
+
noExtension: false,
|
|
528
|
+
},
|
|
529
|
+
selectedIDE: { ide: 'vscode', supported: true },
|
|
530
|
+
providerDefault: 'codex.extension',
|
|
531
|
+
plan: {
|
|
532
|
+
status: 'warning',
|
|
533
|
+
warnings: [],
|
|
534
|
+
blockers: [],
|
|
535
|
+
strategy: 'guided',
|
|
536
|
+
actions: [
|
|
537
|
+
{
|
|
538
|
+
type: 'generate_patch_plan',
|
|
539
|
+
target: 'next.config',
|
|
540
|
+
description:
|
|
541
|
+
'Generate a guided patch plan for the Next.js Inspecto webpack integration.',
|
|
542
|
+
},
|
|
543
|
+
],
|
|
544
|
+
defaults: {
|
|
545
|
+
provider: 'codex',
|
|
546
|
+
ide: 'vscode',
|
|
547
|
+
shared: false,
|
|
548
|
+
extension: true,
|
|
549
|
+
},
|
|
550
|
+
framework: 'react',
|
|
551
|
+
metaFramework: 'Next.js',
|
|
552
|
+
routerMode: 'pages',
|
|
553
|
+
pendingSteps: ['Review the generated Next.js patch plan for next.config.js.'],
|
|
554
|
+
patches: [
|
|
555
|
+
{
|
|
556
|
+
path: 'next.config.js',
|
|
557
|
+
status: 'manual_patch_required',
|
|
558
|
+
reason: 'next_config_wrapped_export',
|
|
559
|
+
confidence: 'medium',
|
|
560
|
+
snippet: 'module.exports = withBundleAnalyzer({ /* ... */ })',
|
|
561
|
+
},
|
|
562
|
+
],
|
|
563
|
+
},
|
|
564
|
+
allowManualPlanApply: true,
|
|
565
|
+
})
|
|
566
|
+
|
|
567
|
+
expect(astInjectorUtils.injectPlugin).not.toHaveBeenCalled()
|
|
568
|
+
expect(fsUtils.writeFile).not.toHaveBeenCalledWith('/repo/next.config.js', expect.any(String))
|
|
569
|
+
expect(result.postInstall.nextSteps).toContain(
|
|
570
|
+
'Generate a guided patch plan for the Next.js Inspecto webpack integration.',
|
|
571
|
+
)
|
|
572
|
+
})
|
|
573
|
+
|
|
574
|
+
it('auto-applies high-confidence Nuxt config patches for guided plans', async () => {
|
|
575
|
+
vi.mocked(fsUtils.readFile).mockImplementation(async filePath => {
|
|
576
|
+
if (filePath === '/repo/nuxt.config.ts') {
|
|
577
|
+
return 'export default defineNuxtConfig({\n devtools: { enabled: true },\n})\n'
|
|
578
|
+
}
|
|
579
|
+
return null
|
|
580
|
+
})
|
|
581
|
+
|
|
582
|
+
const result = await applyOnboardingPlan({
|
|
583
|
+
repoRoot: '/repo',
|
|
584
|
+
projectRoot: '/repo',
|
|
585
|
+
packageManager: 'pnpm',
|
|
586
|
+
supportedBuildTargets: [],
|
|
587
|
+
options: {
|
|
588
|
+
shared: false,
|
|
589
|
+
skipInstall: false,
|
|
590
|
+
dryRun: false,
|
|
591
|
+
noExtension: false,
|
|
592
|
+
},
|
|
593
|
+
selectedIDE: { ide: 'vscode', supported: true },
|
|
594
|
+
providerDefault: 'codex.extension',
|
|
595
|
+
plan: {
|
|
596
|
+
status: 'warning',
|
|
597
|
+
warnings: [],
|
|
598
|
+
blockers: [],
|
|
599
|
+
strategy: 'guided',
|
|
600
|
+
actions: [
|
|
601
|
+
{
|
|
602
|
+
type: 'generate_patch_plan',
|
|
603
|
+
target: 'nuxt.config',
|
|
604
|
+
description: 'Generate a guided patch plan for the Nuxt Inspecto Vite integration.',
|
|
605
|
+
},
|
|
606
|
+
],
|
|
607
|
+
defaults: {
|
|
608
|
+
provider: 'codex',
|
|
609
|
+
ide: 'vscode',
|
|
610
|
+
shared: false,
|
|
611
|
+
extension: true,
|
|
612
|
+
},
|
|
613
|
+
framework: 'vue',
|
|
614
|
+
metaFramework: 'Nuxt',
|
|
615
|
+
pendingSteps: [
|
|
616
|
+
'Review the generated Nuxt patch plan for nuxt.config.ts.',
|
|
617
|
+
'Complete the remaining Nuxt client plugin mount step in plugins/inspecto.client.ts.',
|
|
618
|
+
],
|
|
619
|
+
patches: [
|
|
620
|
+
{
|
|
621
|
+
path: 'nuxt.config.ts',
|
|
622
|
+
status: 'planned',
|
|
623
|
+
reason: 'nuxt_config_object_export',
|
|
624
|
+
confidence: 'high',
|
|
625
|
+
snippet:
|
|
626
|
+
"import { vitePlugin as inspecto } from '@inspecto-dev/plugin'\n\nexport default defineNuxtConfig({\n vite: {\n plugins: [inspecto()],\n },\n})",
|
|
627
|
+
},
|
|
628
|
+
{
|
|
629
|
+
path: 'plugins/inspecto.client.ts',
|
|
630
|
+
status: 'manual_patch_required',
|
|
631
|
+
reason: 'nuxt_client_plugin_mount',
|
|
632
|
+
confidence: 'medium',
|
|
633
|
+
snippet: 'export default defineNuxtPlugin(() => {})',
|
|
634
|
+
},
|
|
635
|
+
],
|
|
636
|
+
},
|
|
637
|
+
allowManualPlanApply: true,
|
|
638
|
+
})
|
|
639
|
+
|
|
640
|
+
expect(fsUtils.writeFile).toHaveBeenCalledWith(
|
|
641
|
+
'/repo/nuxt.config.ts',
|
|
642
|
+
expect.stringContaining("import { vitePlugin as inspecto } from '@inspecto-dev/plugin'"),
|
|
643
|
+
)
|
|
644
|
+
expect(result.mutations).toEqual(
|
|
645
|
+
expect.arrayContaining([
|
|
646
|
+
{
|
|
647
|
+
type: 'file_modified',
|
|
648
|
+
path: 'nuxt.config.ts',
|
|
649
|
+
description: 'Automatically configured Inspecto guided Next.js patch',
|
|
650
|
+
},
|
|
651
|
+
]),
|
|
652
|
+
)
|
|
653
|
+
})
|
|
654
|
+
|
|
169
655
|
it('uses onboarding context and planner output and prints JSON from the apply command', async () => {
|
|
170
656
|
const context: OnboardingContext = {
|
|
171
657
|
root: '/repo',
|
|
@@ -540,6 +1026,73 @@ describe('apply onboarding flow', () => {
|
|
|
540
1026
|
expect(fsUtils.writeJSON).toHaveBeenCalledWith('/repo/.inspecto/prompts.local.json', [])
|
|
541
1027
|
})
|
|
542
1028
|
|
|
1029
|
+
it('merges missing defaults into an existing valid local settings file', async () => {
|
|
1030
|
+
vi.mocked(fsUtils.exists).mockImplementation(async filePath => {
|
|
1031
|
+
return filePath === '/repo/.inspecto/settings.local.json'
|
|
1032
|
+
})
|
|
1033
|
+
vi.mocked(fsUtils.readJSON).mockImplementation(async filePath => {
|
|
1034
|
+
if (filePath === '/repo/.inspecto/settings.local.json') {
|
|
1035
|
+
return { ide: 'trae-cn' }
|
|
1036
|
+
}
|
|
1037
|
+
return null
|
|
1038
|
+
})
|
|
1039
|
+
|
|
1040
|
+
await applyOnboardingPlan({
|
|
1041
|
+
repoRoot: '/repo',
|
|
1042
|
+
projectRoot: '/repo',
|
|
1043
|
+
packageManager: 'pnpm',
|
|
1044
|
+
supportedBuildTargets: [],
|
|
1045
|
+
options: {
|
|
1046
|
+
shared: false,
|
|
1047
|
+
skipInstall: true,
|
|
1048
|
+
dryRun: false,
|
|
1049
|
+
noExtension: true,
|
|
1050
|
+
},
|
|
1051
|
+
selectedIDE: { ide: 'trae-cn', supported: true },
|
|
1052
|
+
providerDefault: 'coco.cli',
|
|
1053
|
+
})
|
|
1054
|
+
|
|
1055
|
+
expect(fsUtils.writeJSON).toHaveBeenCalledWith('/repo/.inspecto/settings.local.json', {
|
|
1056
|
+
ide: 'trae-cn',
|
|
1057
|
+
'provider.default': 'coco.cli',
|
|
1058
|
+
})
|
|
1059
|
+
})
|
|
1060
|
+
|
|
1061
|
+
it('inherits root inspecto defaults when writing package-local settings for a selected subproject', async () => {
|
|
1062
|
+
vi.mocked(fsUtils.exists).mockImplementation(async filePath => {
|
|
1063
|
+
return filePath === '/repo/.inspecto/settings.local.json'
|
|
1064
|
+
})
|
|
1065
|
+
vi.mocked(fsUtils.readJSON).mockImplementation(async filePath => {
|
|
1066
|
+
if (filePath === '/repo/.inspecto/settings.local.json') {
|
|
1067
|
+
return {
|
|
1068
|
+
ide: 'vscode',
|
|
1069
|
+
'provider.default': 'codex.extension',
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
return null
|
|
1073
|
+
})
|
|
1074
|
+
|
|
1075
|
+
await applyOnboardingPlan({
|
|
1076
|
+
repoRoot: '/repo',
|
|
1077
|
+
projectRoot: '/repo/finder',
|
|
1078
|
+
packageManager: 'pnpm',
|
|
1079
|
+
supportedBuildTargets: [],
|
|
1080
|
+
options: {
|
|
1081
|
+
shared: false,
|
|
1082
|
+
skipInstall: true,
|
|
1083
|
+
dryRun: false,
|
|
1084
|
+
noExtension: true,
|
|
1085
|
+
},
|
|
1086
|
+
selectedIDE: { ide: 'cursor', supported: true },
|
|
1087
|
+
providerDefault: 'codex.extension',
|
|
1088
|
+
})
|
|
1089
|
+
|
|
1090
|
+
expect(fsUtils.writeJSON).toHaveBeenCalledWith('/repo/finder/.inspecto/settings.local.json', {
|
|
1091
|
+
ide: 'vscode',
|
|
1092
|
+
'provider.default': 'codex.extension',
|
|
1093
|
+
})
|
|
1094
|
+
})
|
|
1095
|
+
|
|
543
1096
|
it('prints the same short 3-step success guide when apply finishes cleanly', async () => {
|
|
544
1097
|
const context: OnboardingContext = {
|
|
545
1098
|
root: '/repo',
|