@inspecto-dev/cli 0.2.0-alpha.5 → 0.3.0-alpha.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.
Files changed (49) hide show
  1. package/.turbo/turbo-build.log +19 -20
  2. package/CHANGELOG.md +22 -0
  3. package/README.md +93 -11
  4. package/bin/inspecto.js +5 -1
  5. package/dist/bin.d.ts +5 -1
  6. package/dist/bin.js +530 -49
  7. package/dist/chunk-FZS2TLXQ.js +3140 -0
  8. package/dist/index.d.ts +233 -2
  9. package/dist/index.js +17 -3
  10. package/package.json +3 -2
  11. package/src/bin.ts +286 -66
  12. package/src/commands/apply.ts +118 -0
  13. package/src/commands/detect.ts +59 -0
  14. package/src/commands/doctor.ts +225 -72
  15. package/src/commands/init.ts +143 -183
  16. package/src/commands/integration-install.ts +452 -0
  17. package/src/commands/onboard.ts +50 -0
  18. package/src/commands/plan.ts +41 -0
  19. package/src/detect/build-tool.ts +107 -3
  20. package/src/index.ts +17 -2
  21. package/src/inject/ast-injector.ts +17 -6
  22. package/src/inject/extension.ts +40 -22
  23. package/src/inject/gitignore.ts +10 -3
  24. package/src/instructions.ts +60 -46
  25. package/src/onboarding/apply.ts +364 -0
  26. package/src/onboarding/context.ts +36 -0
  27. package/src/onboarding/planner.ts +284 -0
  28. package/src/onboarding/session.ts +434 -0
  29. package/src/onboarding/target-resolution.ts +116 -0
  30. package/src/prompts.ts +54 -11
  31. package/src/types.ts +184 -0
  32. package/src/utils/fs.ts +2 -1
  33. package/src/utils/logger.ts +9 -0
  34. package/src/utils/output.ts +40 -0
  35. package/tests/apply.test.ts +583 -0
  36. package/tests/ast-injector.test.ts +50 -0
  37. package/tests/build-tool.test.ts +3 -5
  38. package/tests/detect.test.ts +94 -0
  39. package/tests/doctor.test.ts +224 -0
  40. package/tests/init.test.ts +364 -0
  41. package/tests/install-wrapper.test.ts +76 -0
  42. package/tests/instructions.test.ts +61 -0
  43. package/tests/integration-install.test.ts +294 -0
  44. package/tests/logger.test.ts +100 -0
  45. package/tests/onboard.test.ts +258 -0
  46. package/tests/plan.test.ts +713 -0
  47. package/tests/workspace-build-tool.test.ts +75 -0
  48. package/.turbo/turbo-test.log +0 -16
  49. package/dist/chunk-MIHQGC3L.js +0 -1720
@@ -0,0 +1,258 @@
1
+ import { beforeEach, describe, expect, it, vi } from 'vitest'
2
+ import { onboard } from '../src/commands/onboard.js'
3
+ import {
4
+ applyResolvedOnboardingSession,
5
+ buildDeferredOnboardResult,
6
+ resolveOnboardingSession,
7
+ } from '../src/onboarding/session.js'
8
+ import { resolveOnboardingTarget } from '../src/onboarding/target-resolution.js'
9
+ import type { OnboardCommandResult, ResolvedOnboardingSession } from '../src/types.js'
10
+
11
+ vi.mock('../src/onboarding/session.js', () => ({
12
+ resolveOnboardingSession: vi.fn(),
13
+ applyResolvedOnboardingSession: vi.fn(),
14
+ buildDeferredOnboardResult: vi.fn(),
15
+ }))
16
+
17
+ describe('target resolution', () => {
18
+ it('returns needs_selection when multiple monorepo candidates are equally plausible', () => {
19
+ const resolution = resolveOnboardingTarget({
20
+ repoRoot: '/repo',
21
+ buildTools: [
22
+ {
23
+ tool: 'vite',
24
+ configPath: 'apps/web/vite.config.ts',
25
+ label: 'Vite',
26
+ packagePath: 'apps/web',
27
+ },
28
+ {
29
+ tool: 'vite',
30
+ configPath: 'apps/admin/vite.config.ts',
31
+ label: 'Vite',
32
+ packagePath: 'apps/admin',
33
+ },
34
+ ],
35
+ frameworkSupportByPackage: {
36
+ 'apps/web': ['vue'],
37
+ 'apps/admin': ['vue'],
38
+ },
39
+ })
40
+
41
+ expect(resolution.status).toBe('needs_selection')
42
+ expect(resolution.candidates.map(item => item.packagePath)).toEqual(['apps/web', 'apps/admin'])
43
+ })
44
+
45
+ it('preselects the strongest supported app candidate', () => {
46
+ const resolution = resolveOnboardingTarget({
47
+ repoRoot: '/repo',
48
+ buildTools: [
49
+ {
50
+ tool: 'vite',
51
+ configPath: 'playground/demo/vite.config.ts',
52
+ label: 'Vite',
53
+ packagePath: 'playground/demo',
54
+ },
55
+ {
56
+ tool: 'vite',
57
+ configPath: 'apps/web/vite.config.ts',
58
+ label: 'Vite',
59
+ packagePath: 'apps/web',
60
+ },
61
+ ],
62
+ frameworkSupportByPackage: {
63
+ 'playground/demo': ['react'],
64
+ 'apps/web': ['react'],
65
+ },
66
+ })
67
+
68
+ expect(resolution.status).toBe('resolved')
69
+ expect(resolution.selected?.packagePath).toBe('apps/web')
70
+ })
71
+ })
72
+
73
+ describe('onboard command', () => {
74
+ beforeEach(() => {
75
+ vi.resetAllMocks()
76
+ vi.spyOn(process, 'cwd').mockReturnValue('/repo')
77
+ })
78
+
79
+ it('prints assistant-facing JSON for a supported happy path', async () => {
80
+ const session: ResolvedOnboardingSession = {
81
+ status: 'success',
82
+ target: {
83
+ status: 'resolved',
84
+ selected: {
85
+ packagePath: '',
86
+ configPath: 'vite.config.ts',
87
+ buildTool: 'vite',
88
+ frameworks: ['react'],
89
+ automaticInjection: true,
90
+ },
91
+ candidates: [
92
+ {
93
+ packagePath: '',
94
+ configPath: 'vite.config.ts',
95
+ buildTool: 'vite',
96
+ frameworks: ['react'],
97
+ automaticInjection: true,
98
+ },
99
+ ],
100
+ reason: 'Only one supported target was detected.',
101
+ },
102
+ summary: {
103
+ headline: 'Inspecto is ready to onboard /repo.',
104
+ changes: ['Install dependencies.'],
105
+ risks: [],
106
+ manualFollowUp: [],
107
+ },
108
+ confirmation: { required: false },
109
+ verification: {
110
+ available: true,
111
+ devCommand: 'pnpm dev',
112
+ message: 'Start the local dev server with `pnpm dev` to verify Inspecto in the browser.',
113
+ },
114
+ context: {
115
+ root: '/repo',
116
+ packageManager: 'pnpm',
117
+ buildTools: { supported: [], unsupported: [] },
118
+ frameworks: { supported: ['react'], unsupported: [] },
119
+ ides: [{ ide: 'vscode', supported: true }],
120
+ providers: [{ id: 'codex', label: 'Codex CLI', supported: true, preferredMode: 'cli' }],
121
+ },
122
+ plan: {
123
+ status: 'ok',
124
+ warnings: [],
125
+ blockers: [],
126
+ strategy: 'supported',
127
+ actions: [],
128
+ defaults: {
129
+ provider: 'codex',
130
+ ide: 'vscode',
131
+ shared: false,
132
+ extension: true,
133
+ },
134
+ },
135
+ projectRoot: '/repo',
136
+ selectedIDE: { ide: 'vscode', supported: true },
137
+ providerDefault: 'codex.cli',
138
+ }
139
+
140
+ const applied: OnboardCommandResult = {
141
+ status: 'success',
142
+ target: session.target,
143
+ summary: session.summary,
144
+ confirmation: session.confirmation,
145
+ ideExtension: {
146
+ required: true,
147
+ installed: true,
148
+ manualRequired: false,
149
+ installCommand: 'code --install-extension inspecto.inspecto',
150
+ marketplaceUrl: 'https://marketplace.visualstudio.com/items?itemName=inspecto.inspecto',
151
+ openVsxUrl: 'https://open-vsx.org/extension/inspecto/inspecto',
152
+ },
153
+ verification: session.verification,
154
+ result: {
155
+ changedFiles: ['vite.config.ts'],
156
+ installedDependencies: ['@inspecto-dev/plugin', '@inspecto-dev/core'],
157
+ selectedProviderDefault: 'codex.cli',
158
+ selectedIDE: 'vscode',
159
+ mutations: [],
160
+ },
161
+ }
162
+
163
+ vi.mocked(resolveOnboardingSession).mockResolvedValue(session)
164
+ vi.mocked(applyResolvedOnboardingSession).mockResolvedValue(applied)
165
+
166
+ const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {})
167
+ const result = await onboard({ json: true })
168
+
169
+ expect(result.status).toBe('success')
170
+ expect(consoleSpy).toHaveBeenCalledWith(JSON.stringify(result, null, 2))
171
+ expect(applyResolvedOnboardingSession).toHaveBeenCalledWith(session, { json: true })
172
+ expect(result.verification?.devCommand).toBe('pnpm dev')
173
+ })
174
+
175
+ it('returns needs_target_selection without applying when target selection is ambiguous', async () => {
176
+ const session: ResolvedOnboardingSession = {
177
+ status: 'needs_target_selection',
178
+ target: {
179
+ status: 'needs_selection',
180
+ candidates: [
181
+ {
182
+ packagePath: 'apps/web',
183
+ configPath: 'apps/web/vite.config.ts',
184
+ buildTool: 'vite',
185
+ frameworks: ['react'],
186
+ automaticInjection: true,
187
+ },
188
+ {
189
+ packagePath: 'apps/admin',
190
+ configPath: 'apps/admin/vite.config.ts',
191
+ buildTool: 'vite',
192
+ frameworks: ['react'],
193
+ automaticInjection: true,
194
+ },
195
+ ],
196
+ reason: 'Multiple supported targets look equally plausible.',
197
+ },
198
+ summary: {
199
+ headline: 'Inspecto found multiple plausible app targets and needs one selection.',
200
+ changes: [],
201
+ risks: [],
202
+ manualFollowUp: [],
203
+ },
204
+ confirmation: { required: false },
205
+ verification: {
206
+ available: true,
207
+ devCommand: 'pnpm dev',
208
+ message: 'Start the local dev server with `pnpm dev` to verify Inspecto in the browser.',
209
+ },
210
+ context: {
211
+ root: '/repo',
212
+ packageManager: 'pnpm',
213
+ buildTools: { supported: [], unsupported: [] },
214
+ frameworks: { supported: ['react'], unsupported: [] },
215
+ ides: [{ ide: 'vscode', supported: true }],
216
+ providers: [],
217
+ },
218
+ plan: {
219
+ status: 'blocked',
220
+ warnings: [],
221
+ blockers: [],
222
+ strategy: 'manual',
223
+ actions: [],
224
+ defaults: {
225
+ shared: false,
226
+ extension: true,
227
+ },
228
+ },
229
+ projectRoot: '/repo',
230
+ }
231
+
232
+ const deferred: OnboardCommandResult = {
233
+ status: 'needs_target_selection',
234
+ target: session.target,
235
+ summary: session.summary,
236
+ confirmation: session.confirmation,
237
+ ideExtension: {
238
+ required: true,
239
+ installed: false,
240
+ manualRequired: true,
241
+ installCommand: 'code --install-extension inspecto.inspecto',
242
+ marketplaceUrl: 'https://marketplace.visualstudio.com/items?itemName=inspecto.inspecto',
243
+ openVsxUrl: 'https://open-vsx.org/extension/inspecto/inspecto',
244
+ },
245
+ verification: session.verification,
246
+ }
247
+
248
+ vi.mocked(resolveOnboardingSession).mockResolvedValue(session)
249
+ vi.mocked(buildDeferredOnboardResult).mockReturnValue(deferred)
250
+
251
+ const result = await onboard({ json: true })
252
+
253
+ expect(result.status).toBe('needs_target_selection')
254
+ expect(result.result).toBeUndefined()
255
+ expect(applyResolvedOnboardingSession).not.toHaveBeenCalled()
256
+ expect(result.ideExtension?.required).toBe(true)
257
+ })
258
+ })