@inspecto-dev/cli 0.2.0-alpha.0 → 0.2.0-alpha.2
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 +20 -19
- package/.turbo/turbo-test.log +5 -5
- package/CHANGELOG.md +22 -0
- package/README.md +6 -6
- package/dist/bin.js +50 -68
- package/dist/{chunk-4RR7PTRN.js → chunk-V57BJXGZ.js} +615 -435
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -1
- package/package.json +3 -2
- package/src/bin.ts +84 -70
- package/src/commands/doctor.ts +41 -28
- package/src/commands/init.ts +106 -226
- package/src/commands/teardown.ts +13 -23
- package/src/detect/build-tool.ts +89 -21
- package/src/detect/ide.ts +42 -21
- package/src/detect/package-manager.ts +10 -3
- package/src/detect/provider.ts +151 -0
- package/src/inject/ast-injector.ts +70 -231
- package/src/inject/extension.ts +49 -34
- package/src/inject/gitignore.ts +1 -1
- package/src/inject/strategies/esbuild.ts +35 -0
- package/src/inject/strategies/index.ts +16 -0
- package/src/inject/strategies/rollup.ts +35 -0
- package/src/inject/strategies/rsbuild.ts +29 -0
- package/src/inject/strategies/rspack.ts +34 -0
- package/src/inject/strategies/types.ts +35 -0
- package/src/inject/strategies/vite.ts +30 -0
- package/src/inject/strategies/webpack.ts +36 -0
- package/src/instructions.ts +55 -0
- package/src/prompts.ts +115 -0
- package/src/types.ts +4 -1
- package/tests/ide.test.ts +3 -3
- package/src/detect/ai-tool.ts +0 -127
package/dist/index.d.ts
CHANGED
|
@@ -7,9 +7,10 @@ interface InitOptions {
|
|
|
7
7
|
shared: boolean;
|
|
8
8
|
skipInstall: boolean;
|
|
9
9
|
dryRun: boolean;
|
|
10
|
-
|
|
10
|
+
provider?: string;
|
|
11
11
|
noExtension: boolean;
|
|
12
12
|
packages?: string[];
|
|
13
|
+
force: boolean;
|
|
13
14
|
}
|
|
14
15
|
/** A single mutation recorded in install.lock */
|
|
15
16
|
interface Mutation {
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inspecto-dev/cli",
|
|
3
|
-
"version": "0.2.0-alpha.
|
|
3
|
+
"version": "0.2.0-alpha.2",
|
|
4
4
|
"description": "CLI tools for Inspecto onboarding and lifecycle management",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"inspecto",
|
|
@@ -16,9 +16,10 @@
|
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"cac": "^6.7.14",
|
|
19
|
+
"magicast": "^0.5.2",
|
|
19
20
|
"picocolors": "^1.0.0",
|
|
20
21
|
"prompts": "^2.4.2",
|
|
21
|
-
"@inspecto-dev/types": "0.2.0-alpha.
|
|
22
|
+
"@inspecto-dev/types": "0.2.0-alpha.2"
|
|
22
23
|
},
|
|
23
24
|
"devDependencies": {
|
|
24
25
|
"@types/node": "^20.0.0",
|
package/src/bin.ts
CHANGED
|
@@ -3,87 +3,101 @@
|
|
|
3
3
|
//
|
|
4
4
|
// v1 scope: VS Code | React + Vue | Vite + Webpack + Rspack + esbuild + Rollup
|
|
5
5
|
// ============================================================
|
|
6
|
-
import {
|
|
6
|
+
import { cac, type CAC } from 'cac'
|
|
7
|
+
import { createRequire } from 'node:module'
|
|
7
8
|
import { init } from './commands/init.js'
|
|
8
9
|
import { doctor } from './commands/doctor.js'
|
|
9
10
|
import { teardown } from './commands/teardown.js'
|
|
10
11
|
import { log } from './utils/logger.js'
|
|
11
12
|
|
|
12
|
-
const
|
|
13
|
-
|
|
13
|
+
const require = createRequire(import.meta.url)
|
|
14
|
+
const { version } = require('../package.json')
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
// cac object
|
|
17
|
+
const cli: CAC = cac('inspecto')
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
inspecto teardown Remove Inspecto from your project
|
|
21
|
-
|
|
22
|
-
Init Options:
|
|
23
|
-
--shared Share .inspecto/settings.json with your team via Git
|
|
24
|
-
--skip-install Skip npm dependency installation
|
|
25
|
-
--dry-run Preview changes without modifying files
|
|
26
|
-
--prefer <tool> Set default AI tool (e.g. github-copilot, claude-code)
|
|
27
|
-
--no-extension Skip VS Code extension installation
|
|
28
|
-
--packages <names> (Monorepo) Comma-separated list of packages to inject
|
|
19
|
+
interface GlobalOptions {
|
|
20
|
+
debug?: boolean
|
|
21
|
+
}
|
|
29
22
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
23
|
+
interface InitCommandOptions extends GlobalOptions {
|
|
24
|
+
shared?: boolean
|
|
25
|
+
skipInstall?: boolean
|
|
26
|
+
dryRun?: boolean
|
|
27
|
+
provider?: string
|
|
28
|
+
noExtension?: boolean
|
|
29
|
+
packages?: string
|
|
30
|
+
force?: boolean
|
|
31
|
+
}
|
|
37
32
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
33
|
+
cli
|
|
34
|
+
.command('init', 'Set up Inspecto in your project')
|
|
35
|
+
.option('--shared', 'Share .inspecto/settings.json with your team via Git', { default: false })
|
|
36
|
+
.option('--skip-install', 'Skip npm dependency installation', { default: false })
|
|
37
|
+
.option('--dry-run', 'Preview changes without modifying files', { default: false })
|
|
38
|
+
.option('--provider <provider>', 'Set default provider (e.g. copilot, claude-code)')
|
|
39
|
+
.option('--no-extension', 'Skip VS Code extension installation', { default: false })
|
|
40
|
+
.option('--packages <names>', '(Monorepo) Comma-separated list of packages to inject')
|
|
41
|
+
.option('--force', 'Force initialization even if environment is unsupported', { default: false })
|
|
42
|
+
.option('--debug', 'Enable debug mode to show full error traces', { default: false })
|
|
43
|
+
.action(async (options: InitCommandOptions) => {
|
|
44
|
+
try {
|
|
45
|
+
await init({
|
|
46
|
+
shared: options.shared ?? false,
|
|
47
|
+
skipInstall: options.skipInstall ?? false,
|
|
48
|
+
dryRun: options.dryRun ?? false,
|
|
49
|
+
...(options.provider && { provider: options.provider }), // Changed from prefer to provider
|
|
50
|
+
noExtension: options.noExtension ?? false,
|
|
51
|
+
...(options.packages && {
|
|
52
|
+
packages: options.packages.split(',').map((s: string) => s.trim()),
|
|
53
|
+
}),
|
|
54
|
+
force: options.force ?? false,
|
|
55
|
+
})
|
|
56
|
+
} catch (err) {
|
|
57
|
+
log.error(err instanceof Error ? err.message : String(err))
|
|
58
|
+
if (options.debug && err instanceof Error && err.stack) {
|
|
59
|
+
console.error(err.stack)
|
|
60
|
+
}
|
|
61
|
+
process.exit(1)
|
|
62
|
+
}
|
|
63
|
+
})
|
|
41
64
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
65
|
+
cli
|
|
66
|
+
.command('doctor', 'Diagnose your Inspecto installation')
|
|
67
|
+
.option('--debug', 'Enable debug mode to show full error traces', { default: false })
|
|
68
|
+
.action(async (options: GlobalOptions) => {
|
|
69
|
+
try {
|
|
70
|
+
await doctor()
|
|
71
|
+
} catch (err) {
|
|
72
|
+
log.error(err instanceof Error ? err.message : String(err))
|
|
73
|
+
if (options.debug && err instanceof Error && err.stack) {
|
|
74
|
+
console.error(err.stack)
|
|
75
|
+
}
|
|
76
|
+
process.exit(1)
|
|
77
|
+
}
|
|
78
|
+
})
|
|
46
79
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
'no-extension': { type: 'boolean', default: false },
|
|
58
|
-
packages: { type: 'string' },
|
|
59
|
-
},
|
|
60
|
-
strict: true,
|
|
61
|
-
})
|
|
62
|
-
await init({
|
|
63
|
-
shared: values.shared ?? false,
|
|
64
|
-
skipInstall: values['skip-install'] ?? false,
|
|
65
|
-
dryRun: values['dry-run'] ?? false,
|
|
66
|
-
...(values.prefer && { prefer: values.prefer }),
|
|
67
|
-
noExtension: values['no-extension'] ?? false,
|
|
68
|
-
...(values.packages && { packages: values.packages.split(',').map(s => s.trim()) }),
|
|
69
|
-
})
|
|
70
|
-
break
|
|
80
|
+
cli
|
|
81
|
+
.command('teardown', 'Remove Inspecto from your project')
|
|
82
|
+
.option('--debug', 'Enable debug mode to show full error traces', { default: false })
|
|
83
|
+
.action(async (options: GlobalOptions) => {
|
|
84
|
+
try {
|
|
85
|
+
await teardown()
|
|
86
|
+
} catch (err) {
|
|
87
|
+
log.error(err instanceof Error ? err.message : String(err))
|
|
88
|
+
if (options.debug && err instanceof Error && err.stack) {
|
|
89
|
+
console.error(err.stack)
|
|
71
90
|
}
|
|
72
|
-
|
|
73
|
-
await doctor()
|
|
74
|
-
break
|
|
75
|
-
case 'teardown':
|
|
76
|
-
await teardown()
|
|
77
|
-
break
|
|
78
|
-
default:
|
|
79
|
-
log.error(`Unknown command: ${command}`)
|
|
80
|
-
console.log(HELP)
|
|
81
|
-
process.exit(1)
|
|
91
|
+
process.exit(1)
|
|
82
92
|
}
|
|
83
|
-
}
|
|
84
|
-
log.error(err instanceof Error ? err.message : String(err))
|
|
85
|
-
process.exit(1)
|
|
86
|
-
}
|
|
87
|
-
}
|
|
93
|
+
})
|
|
88
94
|
|
|
89
|
-
|
|
95
|
+
cli.help()
|
|
96
|
+
cli.version(version)
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
cli.parse()
|
|
100
|
+
} catch (err) {
|
|
101
|
+
log.error(err instanceof Error ? err.message : String(err))
|
|
102
|
+
process.exit(1)
|
|
103
|
+
}
|
package/src/commands/doctor.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { detectPackageManager, getInstallCommand } from '../detect/package-manag
|
|
|
8
8
|
import { detectBuildTools } from '../detect/build-tool.js'
|
|
9
9
|
import { detectFrameworks } from '../detect/framework.js'
|
|
10
10
|
import { detectIDE } from '../detect/ide.js'
|
|
11
|
-
import {
|
|
11
|
+
import { detectProviders } from '../detect/provider.js'
|
|
12
12
|
import { isExtensionInstalled } from '../inject/extension.js'
|
|
13
13
|
|
|
14
14
|
interface DiagResult {
|
|
@@ -29,8 +29,18 @@ export async function doctor(): Promise<void> {
|
|
|
29
29
|
return
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
// Run detections concurrently
|
|
33
|
+
const [ideProbe, frameworkResult, providerProbe, pm, buildResult, extInstalled] =
|
|
34
|
+
await Promise.all([
|
|
35
|
+
detectIDE(root),
|
|
36
|
+
detectFrameworks(root),
|
|
37
|
+
detectProviders(root),
|
|
38
|
+
detectPackageManager(root),
|
|
39
|
+
detectBuildTools(root),
|
|
40
|
+
isExtensionInstalled(),
|
|
41
|
+
])
|
|
42
|
+
|
|
32
43
|
// Check 2: IDE
|
|
33
|
-
const ideProbe = await detectIDE(root)
|
|
34
44
|
if (ideProbe.detected.length === 0) {
|
|
35
45
|
log.warn('IDE: not detected')
|
|
36
46
|
result.warnings++
|
|
@@ -46,13 +56,12 @@ export async function doctor(): Promise<void> {
|
|
|
46
56
|
)
|
|
47
57
|
} else {
|
|
48
58
|
const names = ideProbe.detected.map(d => d.ide).join(', ')
|
|
49
|
-
log.warn(`IDE: ${names} (not supported in v1, VS Code only)`)
|
|
59
|
+
log.warn(`IDE: ${names} (not supported in v1, VS Code, Cursor, Trae only)`)
|
|
50
60
|
result.warnings++
|
|
51
61
|
}
|
|
52
62
|
}
|
|
53
63
|
|
|
54
64
|
// Check 3: Supported framework
|
|
55
|
-
const frameworkResult = await detectFrameworks(root)
|
|
56
65
|
if (frameworkResult.supported.length > 0) {
|
|
57
66
|
log.success(`Framework: ${frameworkResult.supported.join(', ')}`)
|
|
58
67
|
} else if (frameworkResult.unsupported.length > 0) {
|
|
@@ -64,26 +73,25 @@ export async function doctor(): Promise<void> {
|
|
|
64
73
|
result.warnings++
|
|
65
74
|
}
|
|
66
75
|
|
|
67
|
-
// Check 3.5:
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
log.warn('AI Tool: none detected')
|
|
76
|
+
// Check 3.5: Providers
|
|
77
|
+
if (providerProbe.detected.length === 0) {
|
|
78
|
+
log.warn('Provider: none detected')
|
|
71
79
|
log.hint('Inspecto works best with Claude Code, Trae CLI, or GitHub Copilot')
|
|
72
80
|
result.warnings++
|
|
73
81
|
} else {
|
|
74
|
-
const aiNames =
|
|
82
|
+
const aiNames = providerProbe.detected
|
|
75
83
|
.map(d => {
|
|
76
|
-
const modeLabels = d.
|
|
77
|
-
mode === '
|
|
84
|
+
const modeLabels = d.providerModes.map(mode =>
|
|
85
|
+
mode === 'extension' ? 'VS Code Extension' : 'Terminal CLI',
|
|
78
86
|
)
|
|
79
87
|
return `${d.label} (${modeLabels.join(' & ')})`
|
|
80
88
|
})
|
|
81
89
|
.join(', ')
|
|
82
|
-
log.success(`
|
|
90
|
+
log.success(`Provider: ${aiNames}`)
|
|
83
91
|
}
|
|
84
92
|
|
|
85
93
|
// Check 4: @inspecto-dev/plugin installed
|
|
86
|
-
const pluginPath = path.join(root, 'node_modules', '@inspecto', 'plugin')
|
|
94
|
+
const pluginPath = path.join(root, 'node_modules', '@inspecto-dev', 'plugin')
|
|
87
95
|
if (await exists(pluginPath)) {
|
|
88
96
|
const pkgJson = await readJSON<{ version?: string }>(path.join(pluginPath, 'package.json'))
|
|
89
97
|
const version = pkgJson?.version ?? 'unknown'
|
|
@@ -96,26 +104,25 @@ export async function doctor(): Promise<void> {
|
|
|
96
104
|
}
|
|
97
105
|
|
|
98
106
|
// Check 5: Plugin injected in build config
|
|
99
|
-
const buildResult = await detectBuildTools(root)
|
|
100
107
|
if (buildResult.supported.length > 0) {
|
|
101
108
|
let injected = false
|
|
102
109
|
for (const bt of buildResult.supported) {
|
|
103
110
|
const content = await readFile(path.join(root, bt.configPath))
|
|
104
111
|
if (content && content.includes('@inspecto-dev/plugin')) {
|
|
105
|
-
log.success(`Plugin
|
|
112
|
+
log.success(`Plugin configured in ${bt.configPath}`)
|
|
106
113
|
injected = true
|
|
107
114
|
break
|
|
108
115
|
}
|
|
109
116
|
}
|
|
110
117
|
if (!injected) {
|
|
111
|
-
log.error('Plugin not
|
|
112
|
-
log.hint('Fix: npx inspecto init')
|
|
118
|
+
log.error('Plugin not configured in any build config')
|
|
119
|
+
log.hint('Fix: npx @inspecto-dev/cli init')
|
|
113
120
|
result.errors++
|
|
114
121
|
}
|
|
115
122
|
} else if (buildResult.unsupported.length > 0) {
|
|
116
123
|
const names = buildResult.unsupported.join(', ')
|
|
117
124
|
log.warn(`Build tool: ${names} (not supported in v1)`)
|
|
118
|
-
log.hint('
|
|
125
|
+
log.hint('current version supports: Vite, Webpack, Rspack, esbuild, Rollup')
|
|
119
126
|
result.warnings++
|
|
120
127
|
} else {
|
|
121
128
|
log.warn('No recognized build config found')
|
|
@@ -123,7 +130,6 @@ export async function doctor(): Promise<void> {
|
|
|
123
130
|
}
|
|
124
131
|
|
|
125
132
|
// Check 6: VS Code extension
|
|
126
|
-
const extInstalled = await isExtensionInstalled()
|
|
127
133
|
if (extInstalled) {
|
|
128
134
|
log.success('VS Code extension detected')
|
|
129
135
|
} else {
|
|
@@ -138,22 +144,29 @@ export async function doctor(): Promise<void> {
|
|
|
138
144
|
}
|
|
139
145
|
}
|
|
140
146
|
|
|
141
|
-
// Check 7: settings
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
147
|
+
// Check 7: settings
|
|
148
|
+
const settingsJsonPath = path.join(root, '.inspecto', 'settings.json')
|
|
149
|
+
const settingsLocalPath = path.join(root, '.inspecto', 'settings.local.json')
|
|
150
|
+
|
|
151
|
+
const hasSettingsJson = await exists(settingsJsonPath)
|
|
152
|
+
const hasSettingsLocal = await exists(settingsLocalPath)
|
|
153
|
+
|
|
154
|
+
if (hasSettingsJson || hasSettingsLocal) {
|
|
155
|
+
const targetPath = hasSettingsLocal ? settingsLocalPath : settingsJsonPath
|
|
156
|
+
const fileName = hasSettingsLocal ? 'settings.local.json' : 'settings.json'
|
|
157
|
+
const settings = await readJSON(targetPath)
|
|
145
158
|
if (settings) {
|
|
146
|
-
log.success(
|
|
159
|
+
log.success(`.inspecto/${fileName} valid`)
|
|
147
160
|
} else {
|
|
148
|
-
log.error(
|
|
161
|
+
log.error(`.inspecto/${fileName} has invalid JSON`)
|
|
149
162
|
log.hint(
|
|
150
|
-
'Fix: Manually correct the syntax errors, or delete the file and re-run npx inspecto init',
|
|
163
|
+
'Fix: Manually correct the syntax errors, or delete the file and re-run npx @inspecto-dev/cli init',
|
|
151
164
|
)
|
|
152
165
|
result.errors++
|
|
153
166
|
}
|
|
154
167
|
} else {
|
|
155
|
-
log.warn('.inspecto/settings.json
|
|
156
|
-
log.hint('Optional: npx inspecto init')
|
|
168
|
+
log.warn('No .inspecto/settings.json or settings.local.json found (using defaults)')
|
|
169
|
+
log.hint('Optional: npx @inspecto-dev/cli init')
|
|
157
170
|
result.warnings++
|
|
158
171
|
}
|
|
159
172
|
|