robodev 0.43.0 → 0.44.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/package.json +1 -1
- package/src/index.ts +38 -13
- package/templates/auth-chat/apps/fe/vite.config.ts +29 -2
- package/templates/auth-chat/package.json +1 -1
- package/templates/backend/package.json +1 -1
- package/templates/empty/README.md +1 -1
- package/templates/empty/package.json +1 -1
- package/templates/marketplace/apps/fe/vite.config.ts +29 -2
- package/templates/marketplace/package.json +1 -1
- package/templates/space/apps/fe/vite.config.ts +29 -2
- package/templates/space/package.json +1 -1
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -489,7 +489,31 @@ async function assertCreatable(root: string): Promise<void> {
|
|
|
489
489
|
}
|
|
490
490
|
}
|
|
491
491
|
|
|
492
|
-
|
|
492
|
+
const CREATE_PNPM_VERSION = "10.14.0";
|
|
493
|
+
|
|
494
|
+
async function spawnInherit(command: string, args: string[], cwd?: string): Promise<void> {
|
|
495
|
+
await new Promise<void>((resolve, reject) => {
|
|
496
|
+
const child = spawn(command, args, { cwd, stdio: "inherit" });
|
|
497
|
+
child.on("error", reject);
|
|
498
|
+
child.on("exit", (code) => {
|
|
499
|
+
if (code === 0) resolve();
|
|
500
|
+
else reject(new Error(`${command} ${args.join(" ")} failed (${code})`));
|
|
501
|
+
});
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
async function ensurePnpm(): Promise<{ command: string; prefix: string[] }> {
|
|
506
|
+
if (await commandAvailable("pnpm")) return { command: "pnpm", prefix: [] };
|
|
507
|
+
if (!(await commandAvailable("corepack"))) {
|
|
508
|
+
throw new Error("pnpm is not available. Enable it with Corepack (Node 22) or install pnpm.");
|
|
509
|
+
}
|
|
510
|
+
await spawnInherit("corepack", ["enable"]);
|
|
511
|
+
await spawnInherit("corepack", ["prepare", `pnpm@${CREATE_PNPM_VERSION}`, "--activate"]);
|
|
512
|
+
if (await commandAvailable("pnpm")) return { command: "pnpm", prefix: [] };
|
|
513
|
+
return { command: "corepack", prefix: ["pnpm"] };
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
async function pnpmInstallRobodevDeps(root: string): Promise<void> {
|
|
493
517
|
const pkgPath = join(root, "robodev", "package.json");
|
|
494
518
|
let raw: string;
|
|
495
519
|
try {
|
|
@@ -506,18 +530,19 @@ async function npmInstallRobodevDeps(root: string): Promise<void> {
|
|
|
506
530
|
const deps = pkg.dependencies ?? {};
|
|
507
531
|
const extra = Object.keys(deps).filter((name) => name !== "@robodev-ai/sdk");
|
|
508
532
|
if (extra.length === 0) return;
|
|
509
|
-
console.log("Installing robodev/
|
|
510
|
-
await
|
|
533
|
+
console.log("Installing robodev/ packages…");
|
|
534
|
+
await pnpmInstall(join(root, "robodev"));
|
|
511
535
|
}
|
|
512
536
|
|
|
513
|
-
async function
|
|
514
|
-
console.log("Installing
|
|
537
|
+
async function pnpmInstall(root: string): Promise<void> {
|
|
538
|
+
console.log("Installing packages…");
|
|
539
|
+
const pnpm = await ensurePnpm();
|
|
515
540
|
await new Promise<void>((resolve, reject) => {
|
|
516
|
-
const child = spawn(
|
|
541
|
+
const child = spawn(pnpm.command, [...pnpm.prefix, "install"], { cwd: root, stdio: "inherit" });
|
|
517
542
|
child.on("error", reject);
|
|
518
543
|
child.on("exit", (code) => {
|
|
519
544
|
if (code === 0) resolve();
|
|
520
|
-
else reject(new Error(`
|
|
545
|
+
else reject(new Error(`pnpm install failed (${code})`));
|
|
521
546
|
});
|
|
522
547
|
});
|
|
523
548
|
}
|
|
@@ -607,20 +632,20 @@ async function runCreate(args: string[]): Promise<void> {
|
|
|
607
632
|
const liveUrl = await runDeploy(false, { root, frontendFiles, skipFrontendBuild });
|
|
608
633
|
|
|
609
634
|
try {
|
|
610
|
-
await
|
|
611
|
-
await
|
|
635
|
+
await pnpmInstall(root);
|
|
636
|
+
await pnpmInstallRobodevDeps(root);
|
|
612
637
|
} catch (error) {
|
|
613
638
|
console.log(error instanceof Error ? error.message : error);
|
|
614
639
|
if (starter.kind === "backend") {
|
|
615
640
|
console.log(
|
|
616
|
-
"
|
|
641
|
+
"pnpm install failed. Copy the API URL printed above into Lovable, Bolt, or v0 as VITE_API_URL.",
|
|
617
642
|
);
|
|
618
643
|
console.log("https://robodev.povio.dev/docs/frontend");
|
|
619
644
|
} else if (await hasAppsFe(root)) {
|
|
620
|
-
console.log("Run `
|
|
645
|
+
console.log("Run `pnpm install` in the project folder.");
|
|
621
646
|
console.log("bun is required for apps/fe. APIs are already deployed.");
|
|
622
647
|
} else {
|
|
623
|
-
console.log("Run `
|
|
648
|
+
console.log("Run `pnpm install` in the project folder, then `pnpm run dev`.");
|
|
624
649
|
}
|
|
625
650
|
if (liveUrl) {
|
|
626
651
|
printLiveUrl(liveUrl);
|
|
@@ -650,7 +675,7 @@ async function runCreate(args: string[]): Promise<void> {
|
|
|
650
675
|
console.log(" The project App URL serves the hosted Welcome page.");
|
|
651
676
|
console.log(" Edit index.html and src/, then robodev deploy (or Code + Save).");
|
|
652
677
|
console.log(" robodev dev # local APIs");
|
|
653
|
-
console.log("
|
|
678
|
+
console.log(" pnpm run dev:fe # optional local Vite");
|
|
654
679
|
}
|
|
655
680
|
if (liveUrl) {
|
|
656
681
|
printLiveUrl(liveUrl);
|
|
@@ -4,13 +4,39 @@ import tailwindCSS from "@tailwindcss/vite";
|
|
|
4
4
|
import { devtools } from "@tanstack/devtools-vite";
|
|
5
5
|
import { tanstackRouter } from "@tanstack/router-plugin/vite";
|
|
6
6
|
import viteReact from "@vitejs/plugin-react";
|
|
7
|
-
import { readFileSync } from "node:fs";
|
|
7
|
+
import { copyFileSync, existsSync, readdirSync, readFileSync } from "node:fs";
|
|
8
8
|
import { join } from "node:path";
|
|
9
|
-
import { defineConfig as defineViteConfig, mergeConfig } from "vite";
|
|
9
|
+
import { defineConfig as defineViteConfig, mergeConfig, type Plugin } from "vite";
|
|
10
10
|
import devtoolsJson from "vite-plugin-devtools-json";
|
|
11
11
|
import { defineConfig as defineVitestConfig } from "vitest/config";
|
|
12
12
|
import { reactIconsSprite } from "react-icons-sprite/vite";
|
|
13
13
|
|
|
14
|
+
/** react-icons-sprite maps Trash2 → trash2.mjs and MenuIcon → menu-icon.mjs; lucide ships trash-2.mjs / menu.mjs. */
|
|
15
|
+
function lucideSpriteIconAliases(): Plugin {
|
|
16
|
+
return {
|
|
17
|
+
name: "lucide-sprite-icon-aliases",
|
|
18
|
+
enforce: "pre",
|
|
19
|
+
apply: "build",
|
|
20
|
+
buildStart() {
|
|
21
|
+
const iconsDir = join(process.cwd(), "node_modules", "lucide-react", "dist", "esm", "icons");
|
|
22
|
+
if (!existsSync(iconsDir)) return;
|
|
23
|
+
for (const file of readdirSync(iconsDir)) {
|
|
24
|
+
if (!file.endsWith(".mjs")) continue;
|
|
25
|
+
const src = join(iconsDir, file);
|
|
26
|
+
const digit = /^(.+)-(\d+)\.mjs$/.exec(file);
|
|
27
|
+
if (digit) {
|
|
28
|
+
const dest = join(iconsDir, `${digit[1]}${digit[2]}.mjs`);
|
|
29
|
+
if (!existsSync(dest)) copyFileSync(src, dest);
|
|
30
|
+
}
|
|
31
|
+
if (!file.endsWith("-icon.mjs")) {
|
|
32
|
+
const dest = join(iconsDir, file.replace(/\.mjs$/, "-icon.mjs"));
|
|
33
|
+
if (!existsSync(dest)) copyFileSync(src, dest);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
14
40
|
const repoRoot = new URL("../..", import.meta.url).pathname;
|
|
15
41
|
|
|
16
42
|
function readDotEnvKey(root: string, key: string): string | undefined {
|
|
@@ -71,6 +97,7 @@ const createViteConfig = (isDevServer: boolean) => ({
|
|
|
71
97
|
devtools({
|
|
72
98
|
eventBusConfig: { enabled: false },
|
|
73
99
|
}),
|
|
100
|
+
lucideSpriteIconAliases(),
|
|
74
101
|
iconsSpritePlugin,
|
|
75
102
|
viteReact({
|
|
76
103
|
babel: {
|
|
@@ -7,7 +7,7 @@ The project App URL serves the hosted Welcome page. Edit `index.html` and `src/`
|
|
|
7
7
|
```bash
|
|
8
8
|
robodev create my-app
|
|
9
9
|
robodev dev # local APIs
|
|
10
|
-
|
|
10
|
+
pnpm run dev:fe # optional local Vite
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
`robodev create` (TTY and non-TTY) uses this starter by default. Pass `--template space` for Space. Lovable, Bolt, or v0 should use `--template backend`.
|
|
@@ -4,13 +4,39 @@ import tailwindCSS from "@tailwindcss/vite";
|
|
|
4
4
|
import { devtools } from "@tanstack/devtools-vite";
|
|
5
5
|
import { tanstackRouter } from "@tanstack/router-plugin/vite";
|
|
6
6
|
import viteReact from "@vitejs/plugin-react";
|
|
7
|
-
import { readFileSync } from "node:fs";
|
|
7
|
+
import { copyFileSync, existsSync, readdirSync, readFileSync } from "node:fs";
|
|
8
8
|
import { join } from "node:path";
|
|
9
|
-
import { defineConfig as defineViteConfig, mergeConfig } from "vite";
|
|
9
|
+
import { defineConfig as defineViteConfig, mergeConfig, type Plugin } from "vite";
|
|
10
10
|
import devtoolsJson from "vite-plugin-devtools-json";
|
|
11
11
|
import { defineConfig as defineVitestConfig } from "vitest/config";
|
|
12
12
|
import { reactIconsSprite } from "react-icons-sprite/vite";
|
|
13
13
|
|
|
14
|
+
/** react-icons-sprite maps Trash2 → trash2.mjs and MenuIcon → menu-icon.mjs; lucide ships trash-2.mjs / menu.mjs. */
|
|
15
|
+
function lucideSpriteIconAliases(): Plugin {
|
|
16
|
+
return {
|
|
17
|
+
name: "lucide-sprite-icon-aliases",
|
|
18
|
+
enforce: "pre",
|
|
19
|
+
apply: "build",
|
|
20
|
+
buildStart() {
|
|
21
|
+
const iconsDir = join(process.cwd(), "node_modules", "lucide-react", "dist", "esm", "icons");
|
|
22
|
+
if (!existsSync(iconsDir)) return;
|
|
23
|
+
for (const file of readdirSync(iconsDir)) {
|
|
24
|
+
if (!file.endsWith(".mjs")) continue;
|
|
25
|
+
const src = join(iconsDir, file);
|
|
26
|
+
const digit = /^(.+)-(\d+)\.mjs$/.exec(file);
|
|
27
|
+
if (digit) {
|
|
28
|
+
const dest = join(iconsDir, `${digit[1]}${digit[2]}.mjs`);
|
|
29
|
+
if (!existsSync(dest)) copyFileSync(src, dest);
|
|
30
|
+
}
|
|
31
|
+
if (!file.endsWith("-icon.mjs")) {
|
|
32
|
+
const dest = join(iconsDir, file.replace(/\.mjs$/, "-icon.mjs"));
|
|
33
|
+
if (!existsSync(dest)) copyFileSync(src, dest);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
14
40
|
const repoRoot = new URL("../..", import.meta.url).pathname;
|
|
15
41
|
|
|
16
42
|
function readDotEnvKey(root: string, key: string): string | undefined {
|
|
@@ -71,6 +97,7 @@ const createViteConfig = (isDevServer: boolean) => ({
|
|
|
71
97
|
devtools({
|
|
72
98
|
eventBusConfig: { enabled: false },
|
|
73
99
|
}),
|
|
100
|
+
lucideSpriteIconAliases(),
|
|
74
101
|
iconsSpritePlugin,
|
|
75
102
|
viteReact({
|
|
76
103
|
babel: {
|
|
@@ -4,13 +4,39 @@ import tailwindCSS from "@tailwindcss/vite";
|
|
|
4
4
|
import { devtools } from "@tanstack/devtools-vite";
|
|
5
5
|
import { tanstackRouter } from "@tanstack/router-plugin/vite";
|
|
6
6
|
import viteReact from "@vitejs/plugin-react";
|
|
7
|
-
import { readFileSync } from "node:fs";
|
|
7
|
+
import { copyFileSync, existsSync, readdirSync, readFileSync } from "node:fs";
|
|
8
8
|
import { join } from "node:path";
|
|
9
|
-
import { defineConfig as defineViteConfig, mergeConfig } from "vite";
|
|
9
|
+
import { defineConfig as defineViteConfig, mergeConfig, type Plugin } from "vite";
|
|
10
10
|
import devtoolsJson from "vite-plugin-devtools-json";
|
|
11
11
|
import { defineConfig as defineVitestConfig } from "vitest/config";
|
|
12
12
|
import { reactIconsSprite } from "react-icons-sprite/vite";
|
|
13
13
|
|
|
14
|
+
/** react-icons-sprite maps Trash2 → trash2.mjs and MenuIcon → menu-icon.mjs; lucide ships trash-2.mjs / menu.mjs. */
|
|
15
|
+
function lucideSpriteIconAliases(): Plugin {
|
|
16
|
+
return {
|
|
17
|
+
name: "lucide-sprite-icon-aliases",
|
|
18
|
+
enforce: "pre",
|
|
19
|
+
apply: "build",
|
|
20
|
+
buildStart() {
|
|
21
|
+
const iconsDir = join(process.cwd(), "node_modules", "lucide-react", "dist", "esm", "icons");
|
|
22
|
+
if (!existsSync(iconsDir)) return;
|
|
23
|
+
for (const file of readdirSync(iconsDir)) {
|
|
24
|
+
if (!file.endsWith(".mjs")) continue;
|
|
25
|
+
const src = join(iconsDir, file);
|
|
26
|
+
const digit = /^(.+)-(\d+)\.mjs$/.exec(file);
|
|
27
|
+
if (digit) {
|
|
28
|
+
const dest = join(iconsDir, `${digit[1]}${digit[2]}.mjs`);
|
|
29
|
+
if (!existsSync(dest)) copyFileSync(src, dest);
|
|
30
|
+
}
|
|
31
|
+
if (!file.endsWith("-icon.mjs")) {
|
|
32
|
+
const dest = join(iconsDir, file.replace(/\.mjs$/, "-icon.mjs"));
|
|
33
|
+
if (!existsSync(dest)) copyFileSync(src, dest);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
14
40
|
const repoRoot = new URL("../..", import.meta.url).pathname;
|
|
15
41
|
|
|
16
42
|
function readDotEnvKey(root: string, key: string): string | undefined {
|
|
@@ -71,6 +97,7 @@ const createViteConfig = (isDevServer: boolean) => ({
|
|
|
71
97
|
devtools({
|
|
72
98
|
eventBusConfig: { enabled: false },
|
|
73
99
|
}),
|
|
100
|
+
lucideSpriteIconAliases(),
|
|
74
101
|
iconsSpritePlugin,
|
|
75
102
|
viteReact({
|
|
76
103
|
babel: {
|