@helloleo/plugins 0.2.5 → 0.2.7
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/dist/index.js +15 -10
- package/dist/templates/tanstack-router-2026-06-15/package.json +1 -1
- package/package.json +1 -1
- package/src/templates/tanstack-router-2026-06-15/package.json +1 -1
- package/src/tools/scaffold.ts +50 -41
- package/dist/templates/tanstack-router-2026-06-15/src/router.tsx +0 -23
- package/src/templates/tanstack-router-2026-06-15/src/router.tsx +0 -23
package/dist/index.js
CHANGED
|
@@ -24905,19 +24905,25 @@ var SCAFFOLD_TEMPLATES = {
|
|
|
24905
24905
|
"tanstack-router": "tanstack-router-2026-06-15"
|
|
24906
24906
|
};
|
|
24907
24907
|
var SCAFFOLD_VERSION = SCAFFOLD_TEMPLATES["tanstack-start"];
|
|
24908
|
+
function resolveTemplateId() {
|
|
24909
|
+
const version3 = process.env.SCAFFOLD_VERSION;
|
|
24910
|
+
const known = Object.values(SCAFFOLD_TEMPLATES);
|
|
24911
|
+
if (version3 && known.includes(version3))
|
|
24912
|
+
return version3;
|
|
24913
|
+
return SCAFFOLD_TEMPLATES["tanstack-router"];
|
|
24914
|
+
}
|
|
24908
24915
|
function projectUuidFromDir(dir) {
|
|
24909
24916
|
return path3.basename(dir);
|
|
24910
24917
|
}
|
|
24911
24918
|
var scaffoldOptionsSchema = exports_external2.object({
|
|
24912
24919
|
name: exports_external2.string().describe("Human-readable name for SEO, e.g. 'Shipping Platform'"),
|
|
24913
|
-
description: exports_external2.string().describe("One sentence describing the app. Used as the meta description.")
|
|
24914
|
-
type: exports_external2.enum(["tanstack-start", "tanstack-router"]).optional().describe("Project type. 'tanstack-router': " + "client-only SPA with no server and no database \u2014 use it only for " + "pure frontends that talk to external APIs." + "'tanstack-start': SSR app with API routes and a " + "database, KV and bucket \u2014 use it whenever the app " + "needs to persist data or run server-side code (experimental, " + "use only if the user expresses a really complexe application idea).")
|
|
24920
|
+
description: exports_external2.string().describe("One sentence describing the app. Used as the meta description.")
|
|
24915
24921
|
});
|
|
24916
24922
|
function slugify(name) {
|
|
24917
24923
|
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "leo-project";
|
|
24918
24924
|
}
|
|
24919
|
-
async function writeBaseScaffold({ name, description
|
|
24920
|
-
const templateId =
|
|
24925
|
+
async function writeBaseScaffold({ name, description }, dir) {
|
|
24926
|
+
const templateId = resolveTemplateId();
|
|
24921
24927
|
const created = await renderTemplate(templateId, {
|
|
24922
24928
|
LEO_NAME: name,
|
|
24923
24929
|
LEO_SLUG: slugify(name),
|
|
@@ -24930,18 +24936,17 @@ async function writeBaseScaffold({ name, description, type }, dir) {
|
|
|
24930
24936
|
return [...created, leoPath];
|
|
24931
24937
|
}
|
|
24932
24938
|
var scaffold = tool({
|
|
24933
|
-
description: "Scaffold a new project with React 19, file-based routing (TanStack), " + "Tailwind v4, shadcn/ui, and react-query.
|
|
24939
|
+
description: "Scaffold a new project with React 19, file-based routing (TanStack), " + "Tailwind v4, shadcn/ui, and react-query. Call this first for any new" + " project, before writing routes or components.",
|
|
24934
24940
|
args: {
|
|
24935
24941
|
name: scaffoldOptionsSchema.shape.name,
|
|
24936
|
-
description: scaffoldOptionsSchema.shape.description
|
|
24937
|
-
type: scaffoldOptionsSchema.shape.type
|
|
24942
|
+
description: scaffoldOptionsSchema.shape.description
|
|
24938
24943
|
},
|
|
24939
24944
|
async execute(args, context) {
|
|
24940
|
-
const
|
|
24945
|
+
const isStart = resolveTemplateId() === SCAFFOLD_TEMPLATES["tanstack-start"];
|
|
24941
24946
|
const created = await writeBaseScaffold(args, context.directory);
|
|
24942
24947
|
const uiComponents = created.filter((f) => f.startsWith("src/components/ui/"));
|
|
24943
24948
|
const rest = created.filter((f) => !f.startsWith("src/components/ui/"));
|
|
24944
|
-
const typeNotes =
|
|
24949
|
+
const typeNotes = isStart ? [
|
|
24945
24950
|
"- This is a TanStack Start project. The server entry is src/server.ts. There is no index.html or client entrypoint.",
|
|
24946
24951
|
"- For JSON/CRUD APIs, add server routes under src/routes/api/. Read src/routes/api/health.ts first, add routes as needed.",
|
|
24947
24952
|
"- The database schema lives in src/db/schema.ts. Migrations run automatically."
|
|
@@ -24949,7 +24954,7 @@ var scaffold = tool({
|
|
|
24949
24954
|
"- This is a TanStack Router SPA. The client entry is index.html -> src/main.tsx. There is no server: no API routes, no server functions, no database.",
|
|
24950
24955
|
"- Fetch data from external APIs only. If the app needs its own persistence or server-side code, it should have been scaffolded as tanstack-start."
|
|
24951
24956
|
];
|
|
24952
|
-
const nextSteps =
|
|
24957
|
+
const nextSteps = isStart ? [
|
|
24953
24958
|
"Next: read src/routes/index.tsx and continue with the user's request.",
|
|
24954
24959
|
"For authentication (password and/or OAuth), call setup_authentication.",
|
|
24955
24960
|
"For NetSuite projects, call setup_netsuite."
|
package/package.json
CHANGED
package/src/tools/scaffold.ts
CHANGED
|
@@ -27,6 +27,19 @@ export type ScaffoldType = keyof typeof SCAFFOLD_TEMPLATES;
|
|
|
27
27
|
/** Default template id, kept for callers that predate the `type` param. */
|
|
28
28
|
export const SCAFFOLD_VERSION = SCAFFOLD_TEMPLATES["tanstack-start"];
|
|
29
29
|
|
|
30
|
+
/**
|
|
31
|
+
* The container can pin the template via SCAFFOLD_VERSION (a versioned
|
|
32
|
+
* template id, e.g. "tanstack-start-2026-06-18"). Unset or unknown values
|
|
33
|
+
* fall back to the tanstack-router template, so a stale env var can never
|
|
34
|
+
* reproduce the ENOENT-on-missing-template failure.
|
|
35
|
+
*/
|
|
36
|
+
export function resolveTemplateId(): string {
|
|
37
|
+
const version = process.env.SCAFFOLD_VERSION;
|
|
38
|
+
const known: string[] = Object.values(SCAFFOLD_TEMPLATES);
|
|
39
|
+
if (version && known.includes(version)) return version;
|
|
40
|
+
return SCAFFOLD_TEMPLATES["tanstack-router"];
|
|
41
|
+
}
|
|
42
|
+
|
|
30
43
|
/**
|
|
31
44
|
* The project workspace directory is named after the project UUID -- the
|
|
32
45
|
* webapp generates `<slugified-name>-<uuidv4>` (actions.ts createProject)
|
|
@@ -45,18 +58,18 @@ const scaffoldOptionsSchema = z.object({
|
|
|
45
58
|
description: z
|
|
46
59
|
.string()
|
|
47
60
|
.describe("One sentence describing the app. Used as the meta description."),
|
|
48
|
-
type: z
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
61
|
+
// type: z
|
|
62
|
+
// .enum(["tanstack-start", "tanstack-router"])
|
|
63
|
+
// .optional()
|
|
64
|
+
// .describe(
|
|
65
|
+
// "Project type. 'tanstack-router': " +
|
|
66
|
+
// "client-only SPA with no server and no database — use it only for " +
|
|
67
|
+
// "pure frontends that talk to external APIs." +
|
|
68
|
+
// "'tanstack-start': SSR app with API routes and a " +
|
|
69
|
+
// "database, KV and bucket — use it whenever the app " +
|
|
70
|
+
// "needs to persist data or run server-side code (experimental, " +
|
|
71
|
+
// "use only if the user expresses a really complexe application idea).",
|
|
72
|
+
// ),
|
|
60
73
|
});
|
|
61
74
|
|
|
62
75
|
/** Kebab-case slug of the product name, for package.json. */
|
|
@@ -75,10 +88,10 @@ function slugify(name: string): string {
|
|
|
75
88
|
* not part of the template tree). Returns the relative paths written.
|
|
76
89
|
*/
|
|
77
90
|
export async function writeBaseScaffold(
|
|
78
|
-
{ name, description
|
|
91
|
+
{ name, description }: z.infer<typeof scaffoldOptionsSchema>,
|
|
79
92
|
dir: string,
|
|
80
93
|
): Promise<string[]> {
|
|
81
|
-
const templateId =
|
|
94
|
+
const templateId = resolveTemplateId();
|
|
82
95
|
const created = await renderTemplate(
|
|
83
96
|
templateId,
|
|
84
97
|
{
|
|
@@ -103,45 +116,41 @@ export async function writeBaseScaffold(
|
|
|
103
116
|
export const scaffold = tool({
|
|
104
117
|
description:
|
|
105
118
|
"Scaffold a new project with React 19, file-based routing (TanStack), " +
|
|
106
|
-
"Tailwind v4, shadcn/ui, and react-query.
|
|
107
|
-
"
|
|
108
|
-
"or 'tanstack-router' (client-only SPA, no server, no database). Call " +
|
|
109
|
-
"this first for any new project, before writing routes or components.",
|
|
119
|
+
"Tailwind v4, shadcn/ui, and react-query. Call this first for any new" +
|
|
120
|
+
" project, before writing routes or components.",
|
|
110
121
|
args: {
|
|
111
122
|
name: scaffoldOptionsSchema.shape.name,
|
|
112
123
|
description: scaffoldOptionsSchema.shape.description,
|
|
113
|
-
type: scaffoldOptionsSchema.shape.type,
|
|
114
124
|
},
|
|
115
125
|
async execute(args, context) {
|
|
116
|
-
const
|
|
126
|
+
const isStart =
|
|
127
|
+
resolveTemplateId() === SCAFFOLD_TEMPLATES["tanstack-start"];
|
|
117
128
|
const created = await writeBaseScaffold(args, context.directory);
|
|
118
129
|
const uiComponents = created.filter((f) =>
|
|
119
130
|
f.startsWith("src/components/ui/"),
|
|
120
131
|
);
|
|
121
132
|
const rest = created.filter((f) => !f.startsWith("src/components/ui/"));
|
|
122
133
|
|
|
123
|
-
const typeNotes =
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
];
|
|
134
|
+
const typeNotes = isStart
|
|
135
|
+
? [
|
|
136
|
+
"- This is a TanStack Start project. The server entry is src/server.ts. There is no index.html or client entrypoint.",
|
|
137
|
+
"- For JSON/CRUD APIs, add server routes under src/routes/api/. Read src/routes/api/health.ts first, add routes as needed.",
|
|
138
|
+
"- The database schema lives in src/db/schema.ts. Migrations run automatically.",
|
|
139
|
+
]
|
|
140
|
+
: [
|
|
141
|
+
"- This is a TanStack Router SPA. The client entry is index.html -> src/main.tsx. There is no server: no API routes, no server functions, no database.",
|
|
142
|
+
"- Fetch data from external APIs only. If the app needs its own persistence or server-side code, it should have been scaffolded as tanstack-start.",
|
|
143
|
+
];
|
|
134
144
|
|
|
135
|
-
const nextSteps =
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
];
|
|
145
|
+
const nextSteps = isStart
|
|
146
|
+
? [
|
|
147
|
+
"Next: read src/routes/index.tsx and continue with the user's request.",
|
|
148
|
+
"For authentication (password and/or OAuth), call setup_authentication.",
|
|
149
|
+
"For NetSuite projects, call setup_netsuite.",
|
|
150
|
+
]
|
|
151
|
+
: [
|
|
152
|
+
"Next: read src/routes/index.tsx and continue with the user's request.",
|
|
153
|
+
];
|
|
145
154
|
|
|
146
155
|
return [
|
|
147
156
|
`Scaffolded ${created.length} files:`,
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { QueryClient } from '@tanstack/react-query'
|
|
2
|
-
import { createRouter as createTanStackRouter } from '@tanstack/react-router'
|
|
3
|
-
import { routeTree } from './routeTree.gen'
|
|
4
|
-
|
|
5
|
-
export function getRouter() {
|
|
6
|
-
const queryClient = new QueryClient()
|
|
7
|
-
|
|
8
|
-
const router = createTanStackRouter({
|
|
9
|
-
routeTree,
|
|
10
|
-
context: { queryClient },
|
|
11
|
-
scrollRestoration: true,
|
|
12
|
-
defaultPreload: 'intent',
|
|
13
|
-
defaultPreloadStaleTime: 0,
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
return router
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
declare module '@tanstack/react-router' {
|
|
20
|
-
interface Register {
|
|
21
|
-
router: ReturnType<typeof getRouter>
|
|
22
|
-
}
|
|
23
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { QueryClient } from '@tanstack/react-query'
|
|
2
|
-
import { createRouter as createTanStackRouter } from '@tanstack/react-router'
|
|
3
|
-
import { routeTree } from './routeTree.gen'
|
|
4
|
-
|
|
5
|
-
export function getRouter() {
|
|
6
|
-
const queryClient = new QueryClient()
|
|
7
|
-
|
|
8
|
-
const router = createTanStackRouter({
|
|
9
|
-
routeTree,
|
|
10
|
-
context: { queryClient },
|
|
11
|
-
scrollRestoration: true,
|
|
12
|
-
defaultPreload: 'intent',
|
|
13
|
-
defaultPreloadStaleTime: 0,
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
return router
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
declare module '@tanstack/react-router' {
|
|
20
|
-
interface Register {
|
|
21
|
-
router: ReturnType<typeof getRouter>
|
|
22
|
-
}
|
|
23
|
-
}
|