assistant-ui 0.0.90 → 0.0.92
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 +32 -108
- package/dist/commands/add.d.ts +13 -0
- package/dist/commands/add.d.ts.map +1 -1
- package/dist/commands/add.js +48 -32
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/create.d.ts +13 -7
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +83 -71
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +4 -33
- package/dist/commands/init.js.map +1 -1
- package/dist/lib/create-project.d.ts +15 -1
- package/dist/lib/create-project.d.ts.map +1 -1
- package/dist/lib/create-project.js +93 -61
- package/dist/lib/create-project.js.map +1 -1
- package/dist/lib/run-spawn.d.ts +6 -0
- package/dist/lib/run-spawn.d.ts.map +1 -0
- package/dist/lib/run-spawn.js +26 -0
- package/dist/lib/run-spawn.js.map +1 -0
- package/package.json +3 -3
- package/plugin/skills/assistant-ui/SKILL.md +2 -2
- package/src/commands/add.ts +67 -30
- package/src/commands/create.ts +116 -84
- package/src/commands/init.ts +9 -42
- package/src/lib/create-project.ts +123 -74
- package/src/lib/run-spawn.ts +32 -0
package/src/commands/add.ts
CHANGED
|
@@ -1,10 +1,49 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
|
-
import { spawn } from "cross-spawn";
|
|
3
2
|
import { logger } from "../lib/utils/logger";
|
|
4
3
|
import { hasConfig } from "../lib/utils/config";
|
|
4
|
+
import {
|
|
5
|
+
dlxCommand,
|
|
6
|
+
resolvePackageManager,
|
|
7
|
+
resolvePackageManagerForCwd,
|
|
8
|
+
type PackageManagerName,
|
|
9
|
+
} from "../lib/create-project";
|
|
10
|
+
import { runSpawn, SpawnExitError } from "../lib/run-spawn";
|
|
5
11
|
|
|
6
12
|
const REGISTRY_BASE_URL = "https://r.assistant-ui.com";
|
|
7
13
|
|
|
14
|
+
export interface AddComponentsPlan {
|
|
15
|
+
command: string;
|
|
16
|
+
args: string[];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function createAddComponentsPlan(params: {
|
|
20
|
+
components: string[];
|
|
21
|
+
packageManager: PackageManagerName;
|
|
22
|
+
yes?: boolean;
|
|
23
|
+
overwrite?: boolean;
|
|
24
|
+
cwd?: string;
|
|
25
|
+
path?: string;
|
|
26
|
+
}): AddComponentsPlan {
|
|
27
|
+
const componentsToAdd = params.components.map((c) => {
|
|
28
|
+
if (!/^[a-zA-Z0-9-/]+$/.test(c)) {
|
|
29
|
+
throw new Error(`Invalid component name: ${c}`);
|
|
30
|
+
}
|
|
31
|
+
return `${REGISTRY_BASE_URL}/${encodeURIComponent(c)}.json`;
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const [command, dlxArgs] = dlxCommand(params.packageManager);
|
|
35
|
+
const args = [...dlxArgs, "shadcn@latest", "add", ...componentsToAdd];
|
|
36
|
+
|
|
37
|
+
// For npm, dlxArgs may already include `--yes` for npx auto-install.
|
|
38
|
+
// This flag is for shadcn's own confirmation prompt.
|
|
39
|
+
if (params.yes) args.push("--yes");
|
|
40
|
+
if (params.overwrite) args.push("--overwrite");
|
|
41
|
+
if (params.cwd) args.push("--cwd", params.cwd);
|
|
42
|
+
if (params.path) args.push("--path", params.path);
|
|
43
|
+
|
|
44
|
+
return { command, args };
|
|
45
|
+
}
|
|
46
|
+
|
|
8
47
|
export const add = new Command()
|
|
9
48
|
.name("add")
|
|
10
49
|
.description("add a component to your project")
|
|
@@ -17,7 +56,11 @@ export const add = new Command()
|
|
|
17
56
|
process.cwd(),
|
|
18
57
|
)
|
|
19
58
|
.option("-p, --path <path>", "the path to add the component to.")
|
|
20
|
-
.
|
|
59
|
+
.option("--use-npm", "explicitly use npm")
|
|
60
|
+
.option("--use-pnpm", "explicitly use pnpm")
|
|
61
|
+
.option("--use-yarn", "explicitly use yarn")
|
|
62
|
+
.option("--use-bun", "explicitly use bun")
|
|
63
|
+
.action(async (components: string[], opts) => {
|
|
21
64
|
// Check if project is initialized
|
|
22
65
|
if (!hasConfig(opts.cwd)) {
|
|
23
66
|
logger.warn(
|
|
@@ -26,38 +69,32 @@ export const add = new Command()
|
|
|
26
69
|
logger.break();
|
|
27
70
|
}
|
|
28
71
|
|
|
29
|
-
const componentsToAdd = components.map((c) => {
|
|
30
|
-
if (!/^[a-zA-Z0-9-/]+$/.test(c)) {
|
|
31
|
-
throw new Error(`Invalid component name: ${c}`);
|
|
32
|
-
}
|
|
33
|
-
return `${REGISTRY_BASE_URL}/${encodeURIComponent(c)}.json`;
|
|
34
|
-
});
|
|
35
|
-
|
|
36
72
|
logger.step(`Adding ${components.length} component(s)...`);
|
|
37
73
|
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
74
|
+
const packageManager = await resolvePackageManagerForCwd(
|
|
75
|
+
opts.cwd,
|
|
76
|
+
resolvePackageManager(opts),
|
|
77
|
+
);
|
|
78
|
+
const { command, args } = createAddComponentsPlan({
|
|
79
|
+
components,
|
|
80
|
+
packageManager,
|
|
81
|
+
yes: opts.yes,
|
|
82
|
+
overwrite: opts.overwrite,
|
|
83
|
+
cwd: opts.cwd,
|
|
84
|
+
path: opts.path,
|
|
48
85
|
});
|
|
49
86
|
|
|
50
|
-
|
|
51
|
-
|
|
87
|
+
try {
|
|
88
|
+
await runSpawn(command, args, opts.cwd);
|
|
89
|
+
} catch (error) {
|
|
90
|
+
if (error instanceof SpawnExitError) {
|
|
91
|
+
logger.error(`Process exited with code ${error.code}`);
|
|
92
|
+
process.exit(error.code);
|
|
93
|
+
}
|
|
94
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
95
|
+
logger.error(`Failed to add components: ${message}`);
|
|
52
96
|
process.exit(1);
|
|
53
|
-
}
|
|
97
|
+
}
|
|
54
98
|
|
|
55
|
-
|
|
56
|
-
if (code !== 0) {
|
|
57
|
-
logger.error(`Process exited with code ${code}`);
|
|
58
|
-
process.exit(code || 1);
|
|
59
|
-
} else {
|
|
60
|
-
logger.success("Components added successfully!");
|
|
61
|
-
}
|
|
62
|
-
});
|
|
99
|
+
logger.success("Components added successfully!");
|
|
63
100
|
});
|
package/src/commands/create.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { Command } from "commander";
|
|
1
|
+
import { Command, Option } from "commander";
|
|
2
2
|
import chalk from "chalk";
|
|
3
|
-
import { spawn } from "cross-spawn";
|
|
4
3
|
import fs from "node:fs";
|
|
5
4
|
import path from "node:path";
|
|
6
5
|
import * as p from "@clack/prompts";
|
|
@@ -9,10 +8,12 @@ import {
|
|
|
9
8
|
dlxCommand,
|
|
10
9
|
downloadProject,
|
|
11
10
|
resolveLatestReleaseRef,
|
|
12
|
-
|
|
11
|
+
resolvePackageManager,
|
|
12
|
+
resolvePackageManagerForCwd,
|
|
13
|
+
scaffoldProject,
|
|
13
14
|
transformProject,
|
|
14
|
-
type PackageManagerName,
|
|
15
15
|
} from "../lib/create-project";
|
|
16
|
+
import { runSpawn, SpawnExitError } from "../lib/run-spawn";
|
|
16
17
|
|
|
17
18
|
export interface ProjectMetadata {
|
|
18
19
|
name: string;
|
|
@@ -31,7 +32,7 @@ export const PROJECT_METADATA: ProjectMetadata[] = [
|
|
|
31
32
|
description: "Default template with Vercel AI SDK",
|
|
32
33
|
category: "template",
|
|
33
34
|
path: "templates/default",
|
|
34
|
-
hasLocalComponents:
|
|
35
|
+
hasLocalComponents: false,
|
|
35
36
|
},
|
|
36
37
|
{
|
|
37
38
|
name: "minimal",
|
|
@@ -47,7 +48,7 @@ export const PROJECT_METADATA: ProjectMetadata[] = [
|
|
|
47
48
|
description: "Cloud-backed persistence starter",
|
|
48
49
|
category: "template",
|
|
49
50
|
path: "templates/cloud",
|
|
50
|
-
hasLocalComponents:
|
|
51
|
+
hasLocalComponents: false,
|
|
51
52
|
},
|
|
52
53
|
{
|
|
53
54
|
name: "cloud-clerk",
|
|
@@ -55,7 +56,7 @@ export const PROJECT_METADATA: ProjectMetadata[] = [
|
|
|
55
56
|
description: "Cloud-backed starter with Clerk auth",
|
|
56
57
|
category: "template",
|
|
57
58
|
path: "templates/cloud-clerk",
|
|
58
|
-
hasLocalComponents:
|
|
59
|
+
hasLocalComponents: false,
|
|
59
60
|
},
|
|
60
61
|
{
|
|
61
62
|
name: "langgraph",
|
|
@@ -63,15 +64,15 @@ export const PROJECT_METADATA: ProjectMetadata[] = [
|
|
|
63
64
|
description: "LangGraph starter template",
|
|
64
65
|
category: "template",
|
|
65
66
|
path: "templates/langgraph",
|
|
66
|
-
hasLocalComponents:
|
|
67
|
+
hasLocalComponents: false,
|
|
67
68
|
},
|
|
68
69
|
{
|
|
69
70
|
name: "mcp",
|
|
70
71
|
label: "MCP",
|
|
71
|
-
description: "MCP starter
|
|
72
|
+
description: "MCP tools + MCP Apps renderer starter",
|
|
72
73
|
category: "template",
|
|
73
74
|
path: "templates/mcp",
|
|
74
|
-
hasLocalComponents:
|
|
75
|
+
hasLocalComponents: false,
|
|
75
76
|
},
|
|
76
77
|
// Examples
|
|
77
78
|
{
|
|
@@ -276,7 +277,7 @@ export async function resolveProject(params: {
|
|
|
276
277
|
isCancel = p.isCancel,
|
|
277
278
|
} = params;
|
|
278
279
|
|
|
279
|
-
if (template) {
|
|
280
|
+
if (template !== undefined) {
|
|
280
281
|
const meta = PROJECT_METADATA.find(
|
|
281
282
|
(m) => m.name === template && m.category === "template",
|
|
282
283
|
);
|
|
@@ -288,7 +289,7 @@ export async function resolveProject(params: {
|
|
|
288
289
|
return meta;
|
|
289
290
|
}
|
|
290
291
|
|
|
291
|
-
if (example) {
|
|
292
|
+
if (example !== undefined) {
|
|
292
293
|
const meta = PROJECT_METADATA.find(
|
|
293
294
|
(m) => m.name === example && m.category === "example",
|
|
294
295
|
);
|
|
@@ -342,37 +343,6 @@ export async function resolveProject(params: {
|
|
|
342
343
|
return meta;
|
|
343
344
|
}
|
|
344
345
|
|
|
345
|
-
class SpawnExitError extends Error {
|
|
346
|
-
code: number;
|
|
347
|
-
|
|
348
|
-
constructor(code: number) {
|
|
349
|
-
super(`Process exited with code ${code}`);
|
|
350
|
-
this.code = code;
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
async function runSpawn(
|
|
355
|
-
command: string,
|
|
356
|
-
args: string[],
|
|
357
|
-
cwd?: string,
|
|
358
|
-
): Promise<void> {
|
|
359
|
-
return new Promise((resolve, reject) => {
|
|
360
|
-
const child = spawn(command, args, {
|
|
361
|
-
stdio: "inherit",
|
|
362
|
-
cwd,
|
|
363
|
-
});
|
|
364
|
-
|
|
365
|
-
child.on("error", (error) => reject(error));
|
|
366
|
-
child.on("close", (code) => {
|
|
367
|
-
if (code !== 0) {
|
|
368
|
-
reject(new SpawnExitError(code || 1));
|
|
369
|
-
} else {
|
|
370
|
-
resolve();
|
|
371
|
-
}
|
|
372
|
-
});
|
|
373
|
-
});
|
|
374
|
-
}
|
|
375
|
-
|
|
376
346
|
export function resolveCreateProjectDirectory(params: {
|
|
377
347
|
projectDirectory?: string;
|
|
378
348
|
stdinIsTTY?: boolean;
|
|
@@ -384,19 +354,6 @@ export function resolveCreateProjectDirectory(params: {
|
|
|
384
354
|
return undefined;
|
|
385
355
|
}
|
|
386
356
|
|
|
387
|
-
export function resolvePackageManager(opts: {
|
|
388
|
-
useNpm?: boolean;
|
|
389
|
-
usePnpm?: boolean;
|
|
390
|
-
useYarn?: boolean;
|
|
391
|
-
useBun?: boolean;
|
|
392
|
-
}): PackageManagerName | undefined {
|
|
393
|
-
if (opts.useNpm) return "npm";
|
|
394
|
-
if (opts.usePnpm) return "pnpm";
|
|
395
|
-
if (opts.useYarn) return "yarn";
|
|
396
|
-
if (opts.useBun) return "bun";
|
|
397
|
-
return undefined;
|
|
398
|
-
}
|
|
399
|
-
|
|
400
357
|
const PLAYGROUND_PRESET_BASE_URL =
|
|
401
358
|
"https://www.assistant-ui.com/playground/init";
|
|
402
359
|
|
|
@@ -407,6 +364,68 @@ export function resolvePresetUrl(preset: string): string {
|
|
|
407
364
|
return `${PLAYGROUND_PRESET_BASE_URL}?preset=${encodeURIComponent(preset)}`;
|
|
408
365
|
}
|
|
409
366
|
|
|
367
|
+
export interface ScaffoldSelectorOptions {
|
|
368
|
+
template?: string;
|
|
369
|
+
example?: string;
|
|
370
|
+
preset?: string;
|
|
371
|
+
native?: boolean;
|
|
372
|
+
ink?: boolean;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
export interface ResolvedScaffoldSelector {
|
|
376
|
+
template?: string;
|
|
377
|
+
example?: string;
|
|
378
|
+
preset?: string;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
const scaffoldSelectorHelp =
|
|
382
|
+
"Choose one scaffold selector: --template <name>, --example <name>, --native, or --ink. --preset <name-or-url> can be used with --template or by itself.";
|
|
383
|
+
|
|
384
|
+
function getPresetConflict(opts: ScaffoldSelectorOptions): string | undefined {
|
|
385
|
+
if (opts.example !== undefined) return "--example";
|
|
386
|
+
if (opts.native) return "--native";
|
|
387
|
+
if (opts.ink) return "--ink";
|
|
388
|
+
return undefined;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
export function resolveScaffoldSelector(
|
|
392
|
+
opts: ScaffoldSelectorOptions,
|
|
393
|
+
): ResolvedScaffoldSelector {
|
|
394
|
+
const hasPreset = opts.preset !== undefined;
|
|
395
|
+
const presetConflict = getPresetConflict(opts);
|
|
396
|
+
const selectors = [
|
|
397
|
+
opts.template !== undefined ? "--template" : undefined,
|
|
398
|
+
opts.example !== undefined ? "--example" : undefined,
|
|
399
|
+
opts.native ? "--native" : undefined,
|
|
400
|
+
opts.ink ? "--ink" : undefined,
|
|
401
|
+
].filter((selector): selector is string => selector !== undefined);
|
|
402
|
+
|
|
403
|
+
if (selectors.length > 1) {
|
|
404
|
+
throw new Error(
|
|
405
|
+
`Only one scaffold selector can be provided (${selectors.join(", ")}). ${scaffoldSelectorHelp}`,
|
|
406
|
+
);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
if (hasPreset && presetConflict) {
|
|
410
|
+
throw new Error(
|
|
411
|
+
`Cannot use --preset with ${presetConflict}. ${scaffoldSelectorHelp}`,
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
if (opts.native) return { example: "with-expo" };
|
|
416
|
+
if (opts.ink) return { example: "with-react-ink" };
|
|
417
|
+
|
|
418
|
+
if (opts.preset !== undefined && opts.template === undefined) {
|
|
419
|
+
return { template: "default", preset: opts.preset };
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
return {
|
|
423
|
+
...(opts.template !== undefined && { template: opts.template }),
|
|
424
|
+
...(opts.example !== undefined && { example: opts.example }),
|
|
425
|
+
...(hasPreset && { preset: opts.preset }),
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
|
|
410
429
|
export const create = new Command()
|
|
411
430
|
.name("create")
|
|
412
431
|
.description("create a new project")
|
|
@@ -431,27 +450,30 @@ export const create = new Command()
|
|
|
431
450
|
.option("--native", "create an Expo / React Native project")
|
|
432
451
|
.option("--ink", "create a React Ink terminal project")
|
|
433
452
|
.option("--skip-install", "skip installing packages")
|
|
453
|
+
.addOption(
|
|
454
|
+
new Option(
|
|
455
|
+
"--debug-source-root <path>",
|
|
456
|
+
"copy templates/examples from a local assistant-ui repo root",
|
|
457
|
+
).hideHelp(),
|
|
458
|
+
)
|
|
434
459
|
.action(async (projectDirectory, opts) => {
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
if (opts.example && opts.preset) {
|
|
444
|
-
logger.error("Cannot use --preset with --example.");
|
|
460
|
+
let scaffoldSelector: ResolvedScaffoldSelector;
|
|
461
|
+
try {
|
|
462
|
+
scaffoldSelector = resolveScaffoldSelector(opts);
|
|
463
|
+
} catch (error) {
|
|
464
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
465
|
+
logger.error(message);
|
|
445
466
|
process.exit(1);
|
|
446
467
|
}
|
|
447
468
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
}
|
|
469
|
+
const localSourceRoot = opts.debugSourceRoot
|
|
470
|
+
? path.resolve(opts.debugSourceRoot)
|
|
471
|
+
: undefined;
|
|
452
472
|
|
|
453
473
|
// Start release ref resolution early (runs during user prompts)
|
|
454
|
-
const refPromise =
|
|
474
|
+
const refPromise = localSourceRoot
|
|
475
|
+
? Promise.resolve(undefined)
|
|
476
|
+
: resolveLatestReleaseRef();
|
|
455
477
|
|
|
456
478
|
// 1. Resolve project directory
|
|
457
479
|
let resolvedProjectDirectory = resolveCreateProjectDirectory({
|
|
@@ -510,10 +532,7 @@ export const create = new Command()
|
|
|
510
532
|
}
|
|
511
533
|
|
|
512
534
|
// 2. Resolve scaffold target
|
|
513
|
-
const project = await resolveProject(
|
|
514
|
-
template: opts.template,
|
|
515
|
-
example: opts.example,
|
|
516
|
-
});
|
|
535
|
+
const project = await resolveProject(scaffoldSelector);
|
|
517
536
|
if (!project) {
|
|
518
537
|
p.cancel("Project creation cancelled.");
|
|
519
538
|
process.exit(0);
|
|
@@ -522,8 +541,8 @@ export const create = new Command()
|
|
|
522
541
|
logger.info(`Creating project from ${project.category}: ${project.label}`);
|
|
523
542
|
logger.break();
|
|
524
543
|
|
|
525
|
-
const pm = await
|
|
526
|
-
absoluteProjectDir,
|
|
544
|
+
const pm = await resolvePackageManagerForCwd(
|
|
545
|
+
path.dirname(absoluteProjectDir),
|
|
527
546
|
resolvePackageManager(opts),
|
|
528
547
|
);
|
|
529
548
|
|
|
@@ -535,19 +554,32 @@ export const create = new Command()
|
|
|
535
554
|
|
|
536
555
|
try {
|
|
537
556
|
// 3. Resolve latest release ref (started before prompts)
|
|
538
|
-
|
|
557
|
+
if (!localSourceRoot) {
|
|
558
|
+
logger.step("Resolving latest release...");
|
|
559
|
+
}
|
|
539
560
|
const ref = await refPromise;
|
|
540
|
-
if (!ref) {
|
|
561
|
+
if (!localSourceRoot && !ref) {
|
|
541
562
|
logger.warn("Could not resolve latest release, downloading from HEAD");
|
|
542
563
|
}
|
|
543
564
|
|
|
544
|
-
// 4.
|
|
545
|
-
logger.step(
|
|
565
|
+
// 4. Scaffold project
|
|
566
|
+
logger.step(
|
|
567
|
+
localSourceRoot
|
|
568
|
+
? `Copying project from local source: ${localSourceRoot}`
|
|
569
|
+
: "Downloading project...",
|
|
570
|
+
);
|
|
546
571
|
try {
|
|
547
|
-
|
|
572
|
+
const source = localSourceRoot
|
|
573
|
+
? { kind: "local" as const, rootDir: localSourceRoot }
|
|
574
|
+
: {
|
|
575
|
+
kind: "github" as const,
|
|
576
|
+
ref,
|
|
577
|
+
};
|
|
578
|
+
await scaffoldProject(project.path, absoluteProjectDir, source);
|
|
548
579
|
|
|
549
580
|
// If the template didn't exist at the release tag, retry from HEAD
|
|
550
581
|
if (
|
|
582
|
+
!localSourceRoot &&
|
|
551
583
|
ref &&
|
|
552
584
|
!fs.existsSync(path.join(absoluteProjectDir, "package.json"))
|
|
553
585
|
) {
|
|
@@ -571,8 +603,8 @@ export const create = new Command()
|
|
|
571
603
|
}
|
|
572
604
|
|
|
573
605
|
// 6. Apply preset if provided
|
|
574
|
-
if (
|
|
575
|
-
const presetUrl = resolvePresetUrl(
|
|
606
|
+
if (scaffoldSelector.preset) {
|
|
607
|
+
const presetUrl = resolvePresetUrl(scaffoldSelector.preset);
|
|
576
608
|
logger.info("Applying preset configuration...");
|
|
577
609
|
logger.break();
|
|
578
610
|
const [dlxCmd, dlxArgs] = dlxCommand(pm);
|
package/src/commands/init.ts
CHANGED
|
@@ -1,23 +1,18 @@
|
|
|
1
1
|
import { Command, Option } from "commander";
|
|
2
|
-
import { spawn } from "cross-spawn";
|
|
3
2
|
import fs from "node:fs";
|
|
4
3
|
import path from "node:path";
|
|
5
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
dlxCommand,
|
|
6
|
+
resolvePackageManager,
|
|
7
|
+
resolvePackageManagerForCwd,
|
|
8
|
+
} from "../lib/create-project";
|
|
9
|
+
import { runSpawn, SpawnExitError } from "../lib/run-spawn";
|
|
6
10
|
import { logger } from "../lib/utils/logger";
|
|
7
|
-
import { create
|
|
11
|
+
import { create } from "./create";
|
|
8
12
|
|
|
9
13
|
const DEFAULT_REGISTRY_URL =
|
|
10
14
|
"https://r.assistant-ui.com/chat/b/ai-sdk-quick-start/json";
|
|
11
15
|
|
|
12
|
-
class SpawnExitError extends Error {
|
|
13
|
-
code: number;
|
|
14
|
-
|
|
15
|
-
constructor(code: number) {
|
|
16
|
-
super(`Process exited with code ${code}`);
|
|
17
|
-
this.code = code;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
16
|
interface ExistingProjectInitPlan {
|
|
22
17
|
initArgs: string[] | null;
|
|
23
18
|
addArgs: string[];
|
|
@@ -52,31 +47,6 @@ export function isNonInteractiveShell(
|
|
|
52
47
|
return !stdinIsTTY;
|
|
53
48
|
}
|
|
54
49
|
|
|
55
|
-
async function runSpawn(
|
|
56
|
-
command: string,
|
|
57
|
-
args: string[],
|
|
58
|
-
cwd: string,
|
|
59
|
-
): Promise<void> {
|
|
60
|
-
return new Promise((resolve, reject) => {
|
|
61
|
-
const child = spawn(command, args, {
|
|
62
|
-
stdio: "inherit",
|
|
63
|
-
cwd,
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
child.on("error", (error) => {
|
|
67
|
-
reject(error);
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
child.on("close", (code) => {
|
|
71
|
-
if (code !== 0) {
|
|
72
|
-
reject(new SpawnExitError(code || 1));
|
|
73
|
-
} else {
|
|
74
|
-
resolve();
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
|
|
80
50
|
export const init = new Command()
|
|
81
51
|
.name("init")
|
|
82
52
|
.description("initialize assistant-ui in an existing project")
|
|
@@ -152,11 +122,8 @@ export const init = new Command()
|
|
|
152
122
|
}
|
|
153
123
|
|
|
154
124
|
try {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
// For init, targetDir IS the project root, so append a dummy segment.
|
|
158
|
-
const pm = await resolvePackageManagerName(
|
|
159
|
-
path.join(targetDir, "_"),
|
|
125
|
+
const pm = await resolvePackageManagerForCwd(
|
|
126
|
+
targetDir,
|
|
160
127
|
resolvePackageManager(opts),
|
|
161
128
|
);
|
|
162
129
|
const [dlxCmd, dlxArgs] = dlxCommand(pm);
|