@inspecto-dev/cli 0.2.0-alpha.6 → 0.3.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/.turbo/turbo-build.log +19 -20
- package/CHANGELOG.md +16 -0
- package/README.md +44 -9
- package/dist/bin.d.ts +1 -1
- package/dist/bin.js +448 -6
- package/dist/{chunk-PDDFPQJS.js → chunk-IBYH7QZM.js} +624 -85
- package/dist/index.d.ts +106 -1
- package/dist/index.js +3 -1
- package/package.json +2 -2
- package/src/bin.ts +148 -0
- package/src/commands/apply.ts +5 -1
- package/src/commands/init.ts +60 -23
- package/src/commands/integration-install.ts +452 -0
- package/src/commands/onboard.ts +62 -0
- package/src/index.ts +4 -0
- package/src/inject/ast-injector.ts +15 -4
- package/src/inject/extension.ts +40 -24
- package/src/inject/gitignore.ts +10 -3
- package/src/onboarding/apply.ts +48 -9
- package/src/onboarding/planner.ts +6 -0
- package/src/onboarding/session.ts +434 -0
- package/src/onboarding/target-resolution.ts +116 -0
- package/src/types.ts +89 -0
- package/tests/apply.test.ts +47 -1
- package/tests/init.test.ts +31 -0
- package/tests/install-wrapper.test.ts +76 -0
- package/tests/integration-install.test.ts +294 -0
- package/tests/onboard.test.ts +352 -0
- package/.turbo/turbo-test.log +0 -16
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,8 @@ type PackageManager = 'bun' | 'pnpm' | 'yarn' | 'npm';
|
|
|
4
4
|
type BuildTool = 'vite' | 'webpack' | 'rspack' | 'rsbuild' | 'esbuild' | 'rollup';
|
|
5
5
|
/** Machine-readable status for onboarding commands */
|
|
6
6
|
type CommandStatus = 'ok' | 'warning' | 'blocked' | 'error';
|
|
7
|
+
/** Assistant-facing status for single-entry onboarding */
|
|
8
|
+
type OnboardStatus = 'success' | 'partial_success' | 'needs_target_selection' | 'needs_confirmation' | 'error';
|
|
7
9
|
/** Structured message emitted by onboarding commands */
|
|
8
10
|
interface CommandMessage {
|
|
9
11
|
code: string;
|
|
@@ -28,6 +30,98 @@ interface BuildToolDetection {
|
|
|
28
30
|
/** Relative package path when using --packages */
|
|
29
31
|
packagePath?: string;
|
|
30
32
|
}
|
|
33
|
+
/** Normalized onboarding context shared by detection/planning */
|
|
34
|
+
interface OnboardingContext {
|
|
35
|
+
root: string;
|
|
36
|
+
packageManager: PackageManager;
|
|
37
|
+
buildTools: {
|
|
38
|
+
supported: BuildToolDetection[];
|
|
39
|
+
unsupported: string[];
|
|
40
|
+
};
|
|
41
|
+
frameworks: {
|
|
42
|
+
supported: string[];
|
|
43
|
+
unsupported: string[];
|
|
44
|
+
};
|
|
45
|
+
ides: Array<{
|
|
46
|
+
ide: string;
|
|
47
|
+
supported: boolean;
|
|
48
|
+
}>;
|
|
49
|
+
providers: OnboardingProvider[];
|
|
50
|
+
}
|
|
51
|
+
interface OnboardingTargetCandidate {
|
|
52
|
+
packagePath: string;
|
|
53
|
+
configPath: string;
|
|
54
|
+
buildTool: BuildTool;
|
|
55
|
+
frameworks: string[];
|
|
56
|
+
automaticInjection: boolean;
|
|
57
|
+
}
|
|
58
|
+
interface OnboardingTargetResolution {
|
|
59
|
+
status: 'resolved' | 'needs_selection';
|
|
60
|
+
selected?: OnboardingTargetCandidate;
|
|
61
|
+
candidates: OnboardingTargetCandidate[];
|
|
62
|
+
reason: string;
|
|
63
|
+
}
|
|
64
|
+
interface OnboardingSummary {
|
|
65
|
+
headline: string;
|
|
66
|
+
changes: string[];
|
|
67
|
+
risks: string[];
|
|
68
|
+
manualFollowUp: string[];
|
|
69
|
+
}
|
|
70
|
+
interface OnboardingConfirmation {
|
|
71
|
+
required: boolean;
|
|
72
|
+
reason?: string;
|
|
73
|
+
question?: string;
|
|
74
|
+
}
|
|
75
|
+
interface OnboardingExecutionResult {
|
|
76
|
+
changedFiles: string[];
|
|
77
|
+
installedDependencies: string[];
|
|
78
|
+
selectedProviderDefault?: string;
|
|
79
|
+
selectedIDE?: string;
|
|
80
|
+
mutations: Mutation[];
|
|
81
|
+
}
|
|
82
|
+
interface OnboardingDiagnostics {
|
|
83
|
+
warnings: string[];
|
|
84
|
+
errors: string[];
|
|
85
|
+
nextSteps: string[];
|
|
86
|
+
}
|
|
87
|
+
interface OnboardingIdeExtensionStatus {
|
|
88
|
+
required: boolean;
|
|
89
|
+
installed: boolean;
|
|
90
|
+
manualRequired: boolean;
|
|
91
|
+
installCommand?: string;
|
|
92
|
+
marketplaceUrl?: string;
|
|
93
|
+
openVsxUrl?: string;
|
|
94
|
+
}
|
|
95
|
+
interface OnboardingVerification {
|
|
96
|
+
available: boolean;
|
|
97
|
+
devCommand?: string;
|
|
98
|
+
message: string;
|
|
99
|
+
}
|
|
100
|
+
interface ResolvedOnboardingSession {
|
|
101
|
+
status: OnboardStatus;
|
|
102
|
+
target: OnboardingTargetResolution;
|
|
103
|
+
summary: OnboardingSummary;
|
|
104
|
+
confirmation: OnboardingConfirmation;
|
|
105
|
+
verification: OnboardingVerification;
|
|
106
|
+
context: OnboardingContext;
|
|
107
|
+
plan: PlanResult;
|
|
108
|
+
projectRoot: string;
|
|
109
|
+
selectedIDE?: {
|
|
110
|
+
ide: string;
|
|
111
|
+
supported: boolean;
|
|
112
|
+
} | null;
|
|
113
|
+
providerDefault?: string;
|
|
114
|
+
}
|
|
115
|
+
interface OnboardCommandResult {
|
|
116
|
+
status: OnboardStatus;
|
|
117
|
+
target: OnboardingTargetResolution;
|
|
118
|
+
summary: OnboardingSummary;
|
|
119
|
+
confirmation: OnboardingConfirmation;
|
|
120
|
+
ideExtension?: OnboardingIdeExtensionStatus;
|
|
121
|
+
verification?: OnboardingVerification;
|
|
122
|
+
result?: OnboardingExecutionResult;
|
|
123
|
+
diagnostics?: OnboardingDiagnostics;
|
|
124
|
+
}
|
|
31
125
|
/** Machine-readable detection output for skill-first onboarding */
|
|
32
126
|
interface DetectionResult {
|
|
33
127
|
status: CommandStatus;
|
|
@@ -151,6 +245,17 @@ interface DoctorCommandOptions {
|
|
|
151
245
|
declare function collectDoctorResult(root?: string): Promise<DoctorResult>;
|
|
152
246
|
declare function doctor(options?: DoctorCommandOptions | boolean): Promise<DoctorResult>;
|
|
153
247
|
|
|
248
|
+
interface OnboardCommandOptions {
|
|
249
|
+
json?: boolean;
|
|
250
|
+
target?: string;
|
|
251
|
+
yes?: boolean;
|
|
252
|
+
shared?: boolean;
|
|
253
|
+
skipInstall?: boolean;
|
|
254
|
+
dryRun?: boolean;
|
|
255
|
+
noExtension?: boolean;
|
|
256
|
+
}
|
|
257
|
+
declare function onboard(options?: OnboardCommandOptions): Promise<OnboardCommandResult>;
|
|
258
|
+
|
|
154
259
|
declare function plan(json?: boolean): Promise<PlanResult>;
|
|
155
260
|
|
|
156
261
|
declare function teardown(): Promise<void>;
|
|
@@ -164,4 +269,4 @@ declare function reportCommandError(error: unknown, options?: ReportCommandError
|
|
|
164
269
|
|
|
165
270
|
type Framework = 'react' | 'vue';
|
|
166
271
|
|
|
167
|
-
export { type BuildTool, type DoctorDiagnostic, type DoctorResult, type Framework, type InitOptions, type InstallLock, type PackageManager, apply, collectDoctorResult, detect, doctor, init, plan, reportCommandError, teardown, writeCommandOutput };
|
|
272
|
+
export { type BuildTool, type DoctorDiagnostic, type DoctorResult, type Framework, type InitOptions, type InstallLock, type OnboardCommandResult, type OnboardStatus, type PackageManager, type ResolvedOnboardingSession, apply, collectDoctorResult, detect, doctor, init, onboard, plan, reportCommandError, teardown, writeCommandOutput };
|
package/dist/index.js
CHANGED
|
@@ -4,17 +4,19 @@ import {
|
|
|
4
4
|
detect,
|
|
5
5
|
doctor,
|
|
6
6
|
init,
|
|
7
|
+
onboard,
|
|
7
8
|
plan,
|
|
8
9
|
reportCommandError,
|
|
9
10
|
teardown,
|
|
10
11
|
writeCommandOutput
|
|
11
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-IBYH7QZM.js";
|
|
12
13
|
export {
|
|
13
14
|
apply,
|
|
14
15
|
collectDoctorResult,
|
|
15
16
|
detect,
|
|
16
17
|
doctor,
|
|
17
18
|
init,
|
|
19
|
+
onboard,
|
|
18
20
|
plan,
|
|
19
21
|
reportCommandError,
|
|
20
22
|
teardown,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inspecto-dev/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "CLI tools for Inspecto onboarding and lifecycle management",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"inspecto",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"ora": "^9.3.0",
|
|
21
21
|
"picocolors": "^1.0.0",
|
|
22
22
|
"prompts": "^2.4.2",
|
|
23
|
-
"@inspecto-dev/types": "0.
|
|
23
|
+
"@inspecto-dev/types": "0.3.0"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"@types/node": "^20.0.0",
|
package/src/bin.ts
CHANGED
|
@@ -10,8 +10,15 @@ import { apply } from './commands/apply.js'
|
|
|
10
10
|
import { detect } from './commands/detect.js'
|
|
11
11
|
import { init } from './commands/init.js'
|
|
12
12
|
import { doctor } from './commands/doctor.js'
|
|
13
|
+
import { onboard } from './commands/onboard.js'
|
|
13
14
|
import { plan } from './commands/plan.js'
|
|
14
15
|
import { teardown } from './commands/teardown.js'
|
|
16
|
+
import {
|
|
17
|
+
type InstallIntegrationOptions,
|
|
18
|
+
installIntegration,
|
|
19
|
+
printIntegrationList,
|
|
20
|
+
printIntegrationPath,
|
|
21
|
+
} from './commands/integration-install.js'
|
|
15
22
|
import { reportCommandError } from './utils/output.js'
|
|
16
23
|
|
|
17
24
|
const require = createRequire(import.meta.url)
|
|
@@ -42,6 +49,24 @@ interface ApplyCommandOptions extends JsonCommandOptions {
|
|
|
42
49
|
extension?: boolean
|
|
43
50
|
}
|
|
44
51
|
|
|
52
|
+
interface OnboardCliOptions extends JsonCommandOptions {
|
|
53
|
+
target?: string
|
|
54
|
+
yes?: boolean
|
|
55
|
+
shared?: boolean
|
|
56
|
+
skipInstall?: boolean
|
|
57
|
+
dryRun?: boolean
|
|
58
|
+
extension?: boolean
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
interface IntegrationCommandOptions extends GlobalOptions {
|
|
62
|
+
scope?: string
|
|
63
|
+
mode?: string
|
|
64
|
+
force?: boolean
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const integrationScopes = ['project', 'user'] as const
|
|
68
|
+
const integrationModes = ['instructions', 'agents', 'rules'] as const
|
|
69
|
+
|
|
45
70
|
function exitWithError(error: unknown, options: JsonCommandOptions = {}): never {
|
|
46
71
|
reportCommandError(error, {
|
|
47
72
|
debug: options.debug ?? false,
|
|
@@ -95,6 +120,32 @@ export function createCli(_argv: readonly string[] = process.argv): CAC {
|
|
|
95
120
|
}
|
|
96
121
|
})
|
|
97
122
|
|
|
123
|
+
cli
|
|
124
|
+
.command('onboard', 'Run assistant-oriented Inspecto onboarding in one structured flow')
|
|
125
|
+
.option('--json', 'Print machine-readable JSON output', { default: false })
|
|
126
|
+
.option('--target <packagePath>', 'Select a monorepo target package explicitly')
|
|
127
|
+
.option('--yes', 'Accept a lightweight confirmation gate automatically', { default: false })
|
|
128
|
+
.option('--shared', 'Write shared Inspecto settings instead of local-only settings')
|
|
129
|
+
.option('--skip-install', 'Skip npm dependency installation')
|
|
130
|
+
.option('--dry-run', 'Preview changes without modifying files')
|
|
131
|
+
.option('--no-extension', 'Skip IDE extension installation')
|
|
132
|
+
.option('--debug', 'Enable debug mode to show full error traces', { default: false })
|
|
133
|
+
.action(async (options: OnboardCliOptions) => {
|
|
134
|
+
try {
|
|
135
|
+
await onboard({
|
|
136
|
+
json: options.json ?? false,
|
|
137
|
+
...(options.target && { target: options.target }),
|
|
138
|
+
yes: options.yes ?? false,
|
|
139
|
+
...(options.shared !== undefined && { shared: options.shared }),
|
|
140
|
+
...(options.skipInstall !== undefined && { skipInstall: options.skipInstall }),
|
|
141
|
+
...(options.dryRun !== undefined && { dryRun: options.dryRun }),
|
|
142
|
+
...(options.extension === false && { noExtension: true }),
|
|
143
|
+
})
|
|
144
|
+
} catch (error) {
|
|
145
|
+
exitWithError(error, options)
|
|
146
|
+
}
|
|
147
|
+
})
|
|
148
|
+
|
|
98
149
|
cli
|
|
99
150
|
.command('detect', 'Detect whether the current project can be onboarded automatically')
|
|
100
151
|
.option('--json', 'Print machine-readable JSON output', { default: false })
|
|
@@ -152,12 +203,109 @@ export function createCli(_argv: readonly string[] = process.argv): CAC {
|
|
|
152
203
|
}
|
|
153
204
|
})
|
|
154
205
|
|
|
206
|
+
cli
|
|
207
|
+
.command('integrations [...args]', 'Manage assistant integration assets')
|
|
208
|
+
.option(
|
|
209
|
+
'--scope <scope>',
|
|
210
|
+
'Set install scope for supported assistants (e.g. claude-code: project|user)',
|
|
211
|
+
)
|
|
212
|
+
.option(
|
|
213
|
+
'--mode <mode>',
|
|
214
|
+
'Set install mode for supported assistants (e.g. copilot: instructions|agents)',
|
|
215
|
+
)
|
|
216
|
+
.option('--force', 'Overwrite existing integration files', { default: false })
|
|
217
|
+
.option('--debug', 'Enable debug mode to show full error traces', { default: false })
|
|
218
|
+
.action(async (args: string[], options: IntegrationCommandOptions) => {
|
|
219
|
+
try {
|
|
220
|
+
const [subcommand, assistant, ...rest] = args
|
|
221
|
+
const integrationOptions = buildIntegrationOptions(options)
|
|
222
|
+
|
|
223
|
+
if (subcommand === 'list') {
|
|
224
|
+
if (assistant || rest.length > 0 || options.scope || options.mode || options.force) {
|
|
225
|
+
throw new Error(
|
|
226
|
+
'The `list` subcommand does not accept assistant names, --scope, --mode, or --force.',
|
|
227
|
+
)
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
printIntegrationList()
|
|
231
|
+
return
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (subcommand === 'path' && assistant) {
|
|
235
|
+
if (rest.length > 0) {
|
|
236
|
+
throw new Error('The `path` subcommand accepts exactly one assistant argument.')
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (options.force) {
|
|
240
|
+
throw new Error('The `path` subcommand does not support `--force`.')
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
printIntegrationPath(assistant, integrationOptions)
|
|
244
|
+
return
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (subcommand !== 'install' || !assistant) {
|
|
248
|
+
throw new Error(
|
|
249
|
+
[
|
|
250
|
+
'Usage:',
|
|
251
|
+
' inspecto integrations list',
|
|
252
|
+
' inspecto integrations path <assistant> [--scope <scope>] [--mode <mode>]',
|
|
253
|
+
' inspecto integrations install <assistant> [--scope <scope>] [--mode <mode>] [--force]',
|
|
254
|
+
].join('\n'),
|
|
255
|
+
)
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (rest.length > 0) {
|
|
259
|
+
throw new Error('The `install` subcommand accepts exactly one assistant argument.')
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
await installIntegration(assistant, {
|
|
263
|
+
...integrationOptions,
|
|
264
|
+
force: options.force ?? false,
|
|
265
|
+
})
|
|
266
|
+
} catch (error) {
|
|
267
|
+
exitWithError(error, options)
|
|
268
|
+
}
|
|
269
|
+
})
|
|
270
|
+
|
|
155
271
|
cli.help()
|
|
156
272
|
cli.version(version)
|
|
157
273
|
|
|
158
274
|
return cli
|
|
159
275
|
}
|
|
160
276
|
|
|
277
|
+
function buildIntegrationOptions(options: IntegrationCommandOptions): InstallIntegrationOptions {
|
|
278
|
+
const resolved: InstallIntegrationOptions = {}
|
|
279
|
+
|
|
280
|
+
if (options.scope) {
|
|
281
|
+
if (isIntegrationScope(options.scope)) {
|
|
282
|
+
resolved.scope = options.scope
|
|
283
|
+
} else {
|
|
284
|
+
throw new Error(`Unknown integration scope: ${options.scope}`)
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (options.mode) {
|
|
289
|
+
if (isIntegrationMode(options.mode)) {
|
|
290
|
+
resolved.mode = options.mode
|
|
291
|
+
} else {
|
|
292
|
+
throw new Error(`Unknown integration mode: ${options.mode}`)
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
return resolved
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function isIntegrationScope(
|
|
300
|
+
value: string,
|
|
301
|
+
): value is NonNullable<InstallIntegrationOptions['scope']> {
|
|
302
|
+
return (integrationScopes as readonly string[]).includes(value)
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function isIntegrationMode(value: string): value is NonNullable<InstallIntegrationOptions['mode']> {
|
|
306
|
+
return (integrationModes as readonly string[]).includes(value)
|
|
307
|
+
}
|
|
308
|
+
|
|
161
309
|
export async function runCli(argv: readonly string[] = process.argv): Promise<void> {
|
|
162
310
|
const cli = createCli(argv)
|
|
163
311
|
const parsedArgv = [...argv]
|
package/src/commands/apply.ts
CHANGED
|
@@ -74,7 +74,11 @@ function printApplyResult(result: ApplyCommandResult): void {
|
|
|
74
74
|
return
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
log.ready('Ready!
|
|
77
|
+
log.ready('Ready! Inspecto is set up.')
|
|
78
|
+
log.info('Next:')
|
|
79
|
+
log.hint('1. Start or restart your dev server.')
|
|
80
|
+
log.hint('2. Open your app in the browser.')
|
|
81
|
+
log.hint('3. Hold Alt + Click any element to inspect.')
|
|
78
82
|
}
|
|
79
83
|
|
|
80
84
|
export async function apply(options: ApplyCommandOptions = {}): Promise<ApplyCommandResult> {
|
package/src/commands/init.ts
CHANGED
|
@@ -16,6 +16,7 @@ import { detectIDE } from '../detect/ide.js'
|
|
|
16
16
|
import { detectProviders, type ProviderDetection } from '../detect/provider.js'
|
|
17
17
|
import { applyOnboardingPlan } from '../onboarding/apply.js'
|
|
18
18
|
import type { InitOptions, Mutation, BuildToolDetection } from '../types.js'
|
|
19
|
+
import { resolveOnboardingTarget } from '../onboarding/target-resolution.js'
|
|
19
20
|
import {
|
|
20
21
|
promptIDEChoice,
|
|
21
22
|
promptProviderChoice,
|
|
@@ -70,29 +71,42 @@ export async function init(options: InitOptions): Promise<void> {
|
|
|
70
71
|
)
|
|
71
72
|
|
|
72
73
|
if (verifiedPackages.length === 0) {
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
74
|
+
const monorepoCandidates = buildResult.supported.filter(detection => !!detection.packagePath)
|
|
75
|
+
if (monorepoCandidates.length > 0) {
|
|
76
|
+
const frameworkSupportByPackage = await detectFrameworkSupportByPackage(
|
|
77
|
+
repoRoot,
|
|
78
|
+
monorepoCandidates,
|
|
79
|
+
)
|
|
80
|
+
const targetResolution = resolveOnboardingTarget({
|
|
81
|
+
repoRoot,
|
|
82
|
+
buildTools: monorepoCandidates,
|
|
83
|
+
frameworkSupportByPackage,
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
if (targetResolution.status === 'needs_selection') {
|
|
87
|
+
log.warn('Monorepo root detected with multiple candidate apps.')
|
|
88
|
+
const selectedPackage = await promptMonorepoPackageChoice(
|
|
89
|
+
monorepoCandidates.filter(detection =>
|
|
90
|
+
targetResolution.candidates.some(
|
|
91
|
+
candidate => candidate.packagePath === (detection.packagePath ?? ''),
|
|
92
|
+
),
|
|
93
|
+
),
|
|
94
|
+
)
|
|
95
|
+
if (!selectedPackage) {
|
|
96
|
+
log.hint('Run `inspecto init` inside the target app, or pass --packages <app-path>.')
|
|
97
|
+
return
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
projectRoot = path.join(repoRoot, selectedPackage)
|
|
101
|
+
buildResult = await detectBuildTools(repoRoot, [selectedPackage])
|
|
102
|
+
log.info(`Continuing initialization in ${selectedPackage}`)
|
|
103
|
+
} else if (targetResolution.selected?.packagePath) {
|
|
104
|
+
const selectedPackage = targetResolution.selected.packagePath
|
|
105
|
+
projectRoot = path.join(repoRoot, selectedPackage)
|
|
106
|
+
buildResult = await detectBuildTools(repoRoot, [selectedPackage])
|
|
107
|
+
log.warn(`Monorepo root detected. Using the only candidate app: ${selectedPackage}`)
|
|
108
|
+
log.hint('Run `inspecto init` inside that app next time to skip this prompt.')
|
|
85
109
|
}
|
|
86
|
-
|
|
87
|
-
projectRoot = path.join(repoRoot, selectedPackage)
|
|
88
|
-
buildResult = await detectBuildTools(repoRoot, [selectedPackage])
|
|
89
|
-
log.info(`Continuing initialization in ${selectedPackage}`)
|
|
90
|
-
} else if (monorepoTargets.length === 1) {
|
|
91
|
-
const [selectedPackage] = monorepoTargets
|
|
92
|
-
projectRoot = path.join(repoRoot, selectedPackage!)
|
|
93
|
-
buildResult = await detectBuildTools(repoRoot, [selectedPackage!])
|
|
94
|
-
log.warn(`Monorepo root detected. Using the only candidate app: ${selectedPackage}`)
|
|
95
|
-
log.hint('Run `inspecto init` inside that app next time to skip this prompt.')
|
|
96
110
|
}
|
|
97
111
|
}
|
|
98
112
|
|
|
@@ -310,7 +324,11 @@ export async function init(options: InitOptions): Promise<void> {
|
|
|
310
324
|
log.hint('Complete the items above.')
|
|
311
325
|
log.blank()
|
|
312
326
|
} else {
|
|
313
|
-
log.ready('Ready!
|
|
327
|
+
log.ready('Ready! Inspecto is set up.')
|
|
328
|
+
log.info('Next:')
|
|
329
|
+
log.hint('1. Start or restart your dev server.')
|
|
330
|
+
log.hint('2. Open your app in the browser.')
|
|
331
|
+
log.hint('3. Hold Alt + Click any element to inspect.')
|
|
314
332
|
}
|
|
315
333
|
}
|
|
316
334
|
}
|
|
@@ -344,3 +362,22 @@ function matchesAnyPackage(detection: BuildToolDetection, packages: string[]): b
|
|
|
344
362
|
if (packages.length === 0) return true
|
|
345
363
|
return packages.some(pkg => matchesPackage(detection, pkg))
|
|
346
364
|
}
|
|
365
|
+
|
|
366
|
+
async function detectFrameworkSupportByPackage(
|
|
367
|
+
repoRoot: string,
|
|
368
|
+
buildTools: BuildToolDetection[],
|
|
369
|
+
): Promise<Record<string, string[]>> {
|
|
370
|
+
const packagePaths = Array.from(
|
|
371
|
+
new Set(buildTools.map(buildTool => buildTool.packagePath).filter((value): value is string => !!value)),
|
|
372
|
+
)
|
|
373
|
+
const supportByPackage: Record<string, string[]> = {}
|
|
374
|
+
|
|
375
|
+
await Promise.all(
|
|
376
|
+
packagePaths.map(async packagePath => {
|
|
377
|
+
const result = await detectFrameworks(path.join(repoRoot, packagePath))
|
|
378
|
+
supportByPackage[packagePath] = result.supported
|
|
379
|
+
}),
|
|
380
|
+
)
|
|
381
|
+
|
|
382
|
+
return supportByPackage
|
|
383
|
+
}
|