@batijs/cli 0.0.653 → 0.0.655
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/{asset-package.json-Si0Lg6sw.js → asset-package.json-B9hqkASo.js} +1 -1
- package/dist/{asset-package.json-Cr9kL--9.js → asset-package.json-BTRRukgq.js} +1 -1
- package/dist/{asset-package.json-CK8Focys.js → asset-package.json-D0F4ITHn.js} +1 -1
- package/dist/{asset-package.json-DP7v-FYq.js → asset-package.json-DbnTcIM5.js} +1 -1
- package/dist/boilerplates/@batijs/auth0/bati.config.mjs +1 -1
- package/dist/boilerplates/@batijs/authjs/bati.config.mjs +16 -2
- package/dist/boilerplates/@batijs/aws/bati.config.mjs +13 -1
- package/dist/boilerplates/@batijs/better-auth/bati.config.mjs +17 -2
- package/dist/boilerplates/@batijs/biome/bati.config.mjs +16 -2
- package/dist/boilerplates/@batijs/cloudflare/bati.config.mjs +15 -1
- package/dist/boilerplates/@batijs/compiled/bati.config.mjs +13 -1
- package/dist/boilerplates/@batijs/compiled/files/$package.json.js +1 -1
- package/dist/boilerplates/@batijs/compiled/files/asset-package.json.mjs +1 -1
- package/dist/boilerplates/@batijs/d1/bati.config.mjs +1 -1
- package/dist/boilerplates/@batijs/d1-kysely/bati.config.mjs +1 -1
- package/dist/boilerplates/@batijs/d1-sqlite/bati.config.mjs +18 -4
- package/dist/boilerplates/@batijs/docker-compose/bati.config.mjs +14 -2
- package/dist/boilerplates/@batijs/dokploy/bati.config.mjs +14 -2
- package/dist/boilerplates/@batijs/drizzle/bati.config.mjs +17 -1
- package/dist/boilerplates/@batijs/edgeone/bati.config.mjs +14 -2
- package/dist/boilerplates/@batijs/elysia/bati.config.mjs +15 -2
- package/dist/boilerplates/@batijs/elysia/files/$package.json.js +1 -1
- package/dist/boilerplates/@batijs/elysia/files/asset-package.json.mjs +1 -1
- package/dist/boilerplates/@batijs/eslint/bati.config.mjs +14 -2
- package/dist/boilerplates/@batijs/express/bati.config.mjs +15 -2
- package/dist/boilerplates/@batijs/express/files/$package.json.js +1 -1
- package/dist/boilerplates/@batijs/express/files/asset-package.json.mjs +1 -1
- package/dist/boilerplates/@batijs/fastify/bati.config.mjs +15 -2
- package/dist/boilerplates/@batijs/fastify/files/$package.json.js +1 -1
- package/dist/boilerplates/@batijs/fastify/files/asset-package.json.mjs +1 -1
- package/dist/boilerplates/@batijs/google-analytics/bati.config.mjs +14 -2
- package/dist/boilerplates/@batijs/hono/bati.config.mjs +15 -2
- package/dist/boilerplates/@batijs/hono/files/$package.json.js +1 -1
- package/dist/boilerplates/@batijs/hono/files/asset-package.json.mjs +1 -1
- package/dist/boilerplates/@batijs/kysely/bati.config.mjs +16 -2
- package/dist/boilerplates/@batijs/mantine/bati.config.mjs +14 -2
- package/dist/boilerplates/@batijs/netlify/bati.config.mjs +18 -4
- package/dist/boilerplates/@batijs/oxlint/bati.config.mjs +14 -2
- package/dist/boilerplates/@batijs/plausible.io/bati.config.mjs +18 -4
- package/dist/boilerplates/@batijs/pnpm/bati.config.mjs +1 -1
- package/dist/boilerplates/@batijs/postgres/bati.config.mjs +13 -1
- package/dist/boilerplates/@batijs/prettier/bati.config.mjs +14 -2
- package/dist/boilerplates/@batijs/prisma/bati.config.mjs +20 -2
- package/dist/boilerplates/@batijs/react/bati.config.mjs +14 -2
- package/dist/boilerplates/@batijs/react-better-auth/bati.config.mjs +1 -1
- package/dist/boilerplates/@batijs/react-sentry/bati.config.mjs +1 -1
- package/dist/boilerplates/@batijs/sentry/bati.config.mjs +14 -1
- package/dist/boilerplates/@batijs/shadcn-ui/bati.config.mjs +19 -4
- package/dist/boilerplates/@batijs/shared/bati.config.mjs +94 -1
- package/dist/boilerplates/@batijs/shared-agents/bati.config.mjs +17 -0
- package/dist/boilerplates/@batijs/shared-agents/hooks/after.mjs +15 -0
- package/dist/boilerplates/@batijs/shared-agents/hooks/asset-boilerplates/shared-agents/agents-md.mjs +70 -0
- package/dist/boilerplates/@batijs/shared-agents/hooks/asset-boilerplates/shared-agents/compose.mjs +44 -0
- package/dist/boilerplates/@batijs/shared-agents/hooks/asset-packages/features/dist/features-CStxEDu3.mjs +690 -0
- package/dist/boilerplates/@batijs/shared-agents/hooks/asset-packages/features/dist/index.mjs +160 -0
- package/dist/boilerplates/@batijs/shared-db/bati.config.mjs +1 -1
- package/dist/boilerplates/@batijs/shared-env/bati.config.mjs +1 -1
- package/dist/boilerplates/@batijs/shared-server/bati.config.mjs +1 -1
- package/dist/boilerplates/@batijs/shared-todo/bati.config.mjs +1 -1
- package/dist/boilerplates/@batijs/solid/bati.config.mjs +18 -4
- package/dist/boilerplates/@batijs/solid-better-auth/bati.config.mjs +1 -1
- package/dist/boilerplates/@batijs/solid-sentry/bati.config.mjs +1 -1
- package/dist/boilerplates/@batijs/sqlite/bati.config.mjs +13 -1
- package/dist/boilerplates/@batijs/storybook/bati.config.mjs +14 -2
- package/dist/boilerplates/@batijs/tailwindcss/bati.config.mjs +27 -2
- package/dist/boilerplates/@batijs/telefunc/bati.config.mjs +20 -4
- package/dist/boilerplates/@batijs/trpc/bati.config.mjs +19 -4
- package/dist/boilerplates/@batijs/ts-rest/bati.config.mjs +14 -2
- package/dist/boilerplates/@batijs/universal-deploy/bati.config.mjs +21 -4
- package/dist/boilerplates/@batijs/vercel/bati.config.mjs +13 -1
- package/dist/boilerplates/@batijs/vue/bati.config.mjs +14 -2
- package/dist/boilerplates/@batijs/vue-better-auth/bati.config.mjs +1 -1
- package/dist/boilerplates/@batijs/vue-sentry/bati.config.mjs +1 -1
- package/dist/boilerplates/boilerplates.json +6 -0
- package/dist/index.js +6 -2
- package/package.json +5 -5
- package/dist/{asset-package.json-uf2g2h8M.js → asset-package.json-C5reKTg3.js} +1 -1
|
@@ -3,7 +3,7 @@ function e(e, t) {
|
|
|
3
3
|
if (!e) throw Error(t);
|
|
4
4
|
}
|
|
5
5
|
function t(t) {
|
|
6
|
-
return `enforce` in t && e(t.enforce === `pre` || t.enforce === `post`, `'enforce' must be 'pre' or 'post', was ${t.enforce}`), `if` in t && e(typeof t.if == `function`, `'if' must be a function`), `nextSteps` in t && e(typeof t.nextSteps == `function`, `'nextSteps' must be a function`), `knip` in t && (e(typeof t.knip == `object` && t.knip !== null, `'knip' must be an object`), `entry` in t.knip && e(Array.isArray(t.knip.entry), `'knip.entry' must be an array`), `ignoreDependencies` in t.knip && e(Array.isArray(t.knip.ignoreDependencies), `'knip.ignoreDependencies' must be an array`), `ignore` in t.knip && e(Array.isArray(t.knip.ignore), `'knip.ignore' must be an array`), `vite` in t.knip && e(typeof t.knip.vite == `boolean`, `'knip.vite' must be a boolean`)), `env` in t && e(typeof t.env == `function`, `'env' must be a function of meta`), `deploy` in t && e(Array.isArray(t.deploy) || typeof t.deploy == `function`, `'deploy' must be an array or a function of meta`), t;
|
|
6
|
+
return `enforce` in t && e(t.enforce === `pre` || t.enforce === `post`, `'enforce' must be 'pre' or 'post', was ${t.enforce}`), `if` in t && e(typeof t.if == `function`, `'if' must be a function`), `nextSteps` in t && e(typeof t.nextSteps == `function`, `'nextSteps' must be a function`), `knip` in t && (e(typeof t.knip == `object` && t.knip !== null, `'knip' must be an object`), `entry` in t.knip && e(Array.isArray(t.knip.entry), `'knip.entry' must be an array`), `ignoreDependencies` in t.knip && e(Array.isArray(t.knip.ignoreDependencies), `'knip.ignoreDependencies' must be an array`), `ignore` in t.knip && e(Array.isArray(t.knip.ignore), `'knip.ignore' must be an array`), `vite` in t.knip && e(typeof t.knip.vite == `boolean`, `'knip.vite' must be a boolean`)), `env` in t && e(typeof t.env == `function`, `'env' must be a function of meta`), `deploy` in t && e(Array.isArray(t.deploy) || typeof t.deploy == `function`, `'deploy' must be an array or a function of meta`), `skills` in t && e(typeof t.skills == `function`, `'skills' must be a function of meta`), t;
|
|
7
7
|
}
|
|
8
8
|
//#endregion
|
|
9
9
|
//#region bati.config.ts
|
|
@@ -12,6 +12,99 @@ var bati_config_default = t({
|
|
|
12
12
|
knip: {
|
|
13
13
|
ignore: ["*.spec.ts"],
|
|
14
14
|
ignoreDependencies: ["@batijs/tests-utils", "turbo"]
|
|
15
|
+
},
|
|
16
|
+
skills(meta) {
|
|
17
|
+
const pageFile = meta.BATI.has("vue") ? "+Page.vue" : "+Page.tsx";
|
|
18
|
+
const uiPkg = meta.BATI.has("vue") ? "vike-vue" : meta.BATI.has("solid") ? "vike-solid" : "vike-react";
|
|
19
|
+
return [
|
|
20
|
+
{
|
|
21
|
+
name: "vike-routing",
|
|
22
|
+
description: "How to add pages and routes in this Vike app. Use when creating a page, adding a route, route parameters, a layout, or an error page.",
|
|
23
|
+
body: `Routing is file-based under \`pages/\`.
|
|
24
|
+
|
|
25
|
+
- A route is a directory containing a \`${pageFile}\` component, e.g. \`pages/about/${pageFile}\` → \`/about\`.
|
|
26
|
+
- The index route is \`pages/index/${pageFile}\` → \`/\`.
|
|
27
|
+
- **Parameterized routes:** add a \`+route.ts\` exporting a Route String (e.g. \`"/product/@id"\`); read the value from \`pageContext.routeParams\`.
|
|
28
|
+
- **Layouts / wrappers:** add \`+Layout.*\` (nested layout) or \`+Wrapper.*\` beside or above a page.
|
|
29
|
+
- **Error page:** \`pages/_error/+Page.*\` renders 404s and runtime errors.
|
|
30
|
+
|
|
31
|
+
See https://vike.dev/routing.`
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: "vike-data-fetching",
|
|
35
|
+
description: "How to load data for a page in this Vike app. Use when a page needs server or client data, or you're working with +data / useData.",
|
|
36
|
+
body: `- Add a \`+data.ts\` beside the page's component and export a \`data()\` function. It runs on the server (and on the client during client-side navigation) and receives \`pageContext\`.
|
|
37
|
+
- Read the result in the component with \`useData<DataType>()\` (from \`${uiPkg}\`).
|
|
38
|
+
- Only values listed in the \`passToClient\` config are serialized to the client; \`+data\` results are passed automatically.
|
|
39
|
+
- For request-time logic such as auth checks or redirects, use a \`+guard.ts\`.
|
|
40
|
+
|
|
41
|
+
See https://vike.dev/data.`
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: "vike-config",
|
|
45
|
+
description: "How Vike configuration works in this app. Use when changing global or per-route config, the page title/head, prerendering, or SSR settings.",
|
|
46
|
+
body: `- \`+config.ts\` files configure Vike. A \`+config.ts\` directly under \`pages/\` is global; one inside a route directory applies to that route and its descendants.
|
|
47
|
+
- Set the document title and meta tags via \`+Head.*\`, \`+title\`, and \`+description\`.
|
|
48
|
+
- UI-framework integration is provided by \`${uiPkg}\` (already configured).
|
|
49
|
+
- Toggle SSR / prerendering via the \`ssr\` / \`prerender\` settings in \`+config.ts\`.
|
|
50
|
+
|
|
51
|
+
See https://vike.dev/config.`
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: "vike-navigation",
|
|
55
|
+
description: "How to navigate between pages in this Vike app. Use when adding links, redirecting, navigating programmatically, or prefetching.",
|
|
56
|
+
body: `- **Links:** plain \`<a href="/...">\` works — Vike intercepts it for client-side navigation. Highlight the active link by comparing \`pageContext.urlPathname\` (see the \`vike-pagecontext\` skill).
|
|
57
|
+
- **Programmatic:** \`import { navigate } from "vike/client/router"\`, then \`await navigate("/path", { keepScrollPosition })\`.
|
|
58
|
+
- **Redirect:** in a \`+guard.ts\` or \`+data.ts\`, \`import { redirect } from "vike/abort"\`, then \`throw redirect("/login")\`.
|
|
59
|
+
- **Prefetch:** set \`+prefetchStaticAssets\` to \`"hover"\` / \`"viewport"\` in config, or call \`prefetch("/path")\` from \`vike/client/router\`.
|
|
60
|
+
|
|
61
|
+
See https://vike.dev/navigate.`
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: "vike-render-modes",
|
|
65
|
+
description: "How rendering modes work in this Vike app (SSR / SSG / SPA / streaming). Use when changing how a page is rendered or pre-rendered.",
|
|
66
|
+
body: `Set these in a \`+config.ts\` (global under \`pages/\`, or per-route):
|
|
67
|
+
- **\`ssr\`** — \`true\` (default) renders on the server then hydrates; \`false\` makes the page client-only (SPA).
|
|
68
|
+
- **\`prerender\`** — \`true\` builds the page to static HTML at build time (SSG). For parameterized routes (\`/movie/@id\`), add a \`+onBeforePrerenderStart.ts\` returning the list of URLs to pre-render.
|
|
69
|
+
- **\`stream\`** — toggle HTML streaming.
|
|
70
|
+
|
|
71
|
+
See https://vike.dev/pre-rendering.`
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
name: "vike-pagecontext",
|
|
75
|
+
description: "How to use pageContext in this Vike app. Use when reading request/route info in a component or passing custom values to the client.",
|
|
76
|
+
body: `\`pageContext\` carries request + render info — common props: \`routeParams\`, \`urlPathname\` / \`urlParsed\`, \`data\` (from \`+data\`), \`isClientSide\`.
|
|
77
|
+
- **Read it in a component:** \`import { usePageContext } from "${uiPkg}/usePageContext"\`, then \`const pageContext = usePageContext()\`.
|
|
78
|
+
- **Custom values:** set them on \`pageContext\` from a hook (\`+onBeforeRender\` or \`+data\`), and add their names to \`+passToClient\` so they reach the browser.
|
|
79
|
+
- **Types:** \`PageContext\` / \`PageContextServer\` / \`PageContextClient\` from \`vike/types\`.
|
|
80
|
+
|
|
81
|
+
See https://vike.dev/pageContext.`
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
name: "vike-hooks",
|
|
85
|
+
description: "The Vike hook system in this app. Use when you need a lifecycle hook — data orchestration, page-transition effects, post-hydration setup, or global init.",
|
|
86
|
+
body: `Hooks are \`+<name>.ts\` files (or keys in \`+config.ts\`) placed beside a page or globally under \`pages/\`. App-level hooks:
|
|
87
|
+
- **\`+onBeforeRender\`** (server) — advanced data orchestration; can set any \`pageContext\` prop.
|
|
88
|
+
- **\`+onPageTransitionStart\` / \`+onPageTransitionEnd\`** (client) — run around client-side navigation (e.g. a loading indicator); \`pageContext.isBackwardNavigation\` is available.
|
|
89
|
+
- **\`+onHydrationEnd\`** (client) — runs once after the first page hydrates; good for third-party / DOM-only init.
|
|
90
|
+
- **\`+onCreateGlobalContext\`** (server & client) — runs once when the global context is created; global / auth / store init.
|
|
91
|
+
- \`+data\` and \`+guard\` are the common data/auth hooks (see the \`vike-data-fetching\` skill); \`+onBeforePrerenderStart\` lists URLs for SSG (see \`vike-render-modes\`).
|
|
92
|
+
- \`+onRenderHtml\` / \`+onRenderClient\` / \`+onCreateApp\` are provided by \`${uiPkg}\` — you rarely write these.
|
|
93
|
+
|
|
94
|
+
See https://vike.dev/hooks.`
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: "vike-error-pages",
|
|
98
|
+
description: "How error pages work in this Vike app. Use when handling 404s, access errors, or rendering an error page by status code.",
|
|
99
|
+
body: `The error page is \`pages/_error/${pageFile}\` — Vike renders it for 404s and uncaught errors.
|
|
100
|
+
- **Trigger it:** \`import { render } from "vike/abort"\`, then \`throw render(404)\` (or \`401\` / \`403\` / \`500\`), optionally \`throw render(403, "Forbidden")\` to pass a reason. Use \`throw redirect("/login")\` (from \`vike/abort\`) to redirect instead.
|
|
101
|
+
- **Read the error** in \`_error\`: \`const { abortStatusCode, abortReason, is404 } = usePageContext()\` (from \`${uiPkg}/usePageContext\`).
|
|
102
|
+
- **Custom reason type:** augment \`Vike.PageContext\` with \`abortReason\` in a \`.d.ts\`.
|
|
103
|
+
- Pre-rendering emits the error page as \`dist/client/404.html\`.
|
|
104
|
+
|
|
105
|
+
See https://vike.dev/error-page.`
|
|
106
|
+
}
|
|
107
|
+
];
|
|
15
108
|
}
|
|
16
109
|
});
|
|
17
110
|
//#endregion
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region ../../packages/core/dist/config.js
|
|
2
|
+
function e(e, t) {
|
|
3
|
+
if (!e) throw Error(t);
|
|
4
|
+
}
|
|
5
|
+
function t(t) {
|
|
6
|
+
return `enforce` in t && e(t.enforce === `pre` || t.enforce === `post`, `'enforce' must be 'pre' or 'post', was ${t.enforce}`), `if` in t && e(typeof t.if == `function`, `'if' must be a function`), `nextSteps` in t && e(typeof t.nextSteps == `function`, `'nextSteps' must be a function`), `knip` in t && (e(typeof t.knip == `object` && t.knip !== null, `'knip' must be an object`), `entry` in t.knip && e(Array.isArray(t.knip.entry), `'knip.entry' must be an array`), `ignoreDependencies` in t.knip && e(Array.isArray(t.knip.ignoreDependencies), `'knip.ignoreDependencies' must be an array`), `ignore` in t.knip && e(Array.isArray(t.knip.ignore), `'knip.ignore' must be an array`), `vite` in t.knip && e(typeof t.knip.vite == `boolean`, `'knip.vite' must be a boolean`)), `env` in t && e(typeof t.env == `function`, `'env' must be a function of meta`), `deploy` in t && e(Array.isArray(t.deploy) || typeof t.deploy == `function`, `'deploy' must be an array or a function of meta`), `skills` in t && e(typeof t.skills == `function`, `'skills' must be a function of meta`), t;
|
|
7
|
+
}
|
|
8
|
+
//#endregion
|
|
9
|
+
//#region bati.config.ts
|
|
10
|
+
var bati_config_default = t({
|
|
11
|
+
enforce: "post",
|
|
12
|
+
if(meta) {
|
|
13
|
+
return meta.BATI.hasAiAgent;
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
//#endregion
|
|
17
|
+
export { bati_config_default as default };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { buildAgentsMd } from "./asset-boilerplates/shared-agents/agents-md.mjs";
|
|
2
|
+
import { composeAgentFiles } from "./asset-boilerplates/shared-agents/compose.mjs";
|
|
3
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
//#region hooks/after.ts
|
|
6
|
+
async function onafter(cwd, meta, { skills, env }) {
|
|
7
|
+
const agentFiles = composeAgentFiles(meta, skills, buildAgentsMd(meta, env.length > 0));
|
|
8
|
+
for (const { path, content } of agentFiles) {
|
|
9
|
+
const dest = join(cwd, path);
|
|
10
|
+
await mkdir(dirname(dest), { recursive: true });
|
|
11
|
+
await writeFile(dest, content, "utf-8");
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { onafter as default };
|
package/dist/boilerplates/@batijs/shared-agents/hooks/asset-boilerplates/shared-agents/agents-md.mjs
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { features } from "../../asset-packages/features/dist/features-CStxEDu3.mjs";
|
|
2
|
+
import { categories } from "../../asset-packages/features/dist/index.mjs";
|
|
3
|
+
//#region agents-md.ts
|
|
4
|
+
/**
|
|
5
|
+
* The canonical `AGENTS.md` body (SKILLS_PLAN.md §3/§6.A): the always-loaded project guide —
|
|
6
|
+
* orientation, commands, env, structure — composed from the resolved stack. Kept lean, pointing at
|
|
7
|
+
* `README.md` and upstream docs rather than duplicating volatile detail.
|
|
8
|
+
*/
|
|
9
|
+
function buildAgentsMd(meta, hasEnv) {
|
|
10
|
+
const run = meta.BATI.pmRun;
|
|
11
|
+
const sections = [
|
|
12
|
+
`# AGENTS.md
|
|
13
|
+
|
|
14
|
+
Guidance for AI coding agents working in this repository. This is a [Vike](https://vike.dev) app
|
|
15
|
+
scaffolded with [Bati](https://batijs.dev). Match the existing conventions and the stack below.`,
|
|
16
|
+
stackSection(meta),
|
|
17
|
+
`## Commands
|
|
18
|
+
|
|
19
|
+
- \`${run} dev\` — start the development server
|
|
20
|
+
- \`${run} build\` — build for production
|
|
21
|
+
- \`${run} preview\` — preview the production build
|
|
22
|
+
|
|
23
|
+
Use \`${meta.BATI.pm}\` for package management. See \`package.json\` for the full list of scripts.`
|
|
24
|
+
];
|
|
25
|
+
if (hasEnv) sections.push(environmentSection(meta));
|
|
26
|
+
sections.push(structureSection(meta));
|
|
27
|
+
sections.push(`## Notes for agents
|
|
28
|
+
|
|
29
|
+
- Respect the selected stack above; prefer its idioms over introducing new libraries.
|
|
30
|
+
- Task-specific how-tos are provided as skills under \`.agents/skills/\` (and \`.claude/skills/\`) — consult them when relevant.
|
|
31
|
+
- See \`README.md\` for setup and feature-specific notes.`);
|
|
32
|
+
sections.push(referencesSection(meta));
|
|
33
|
+
return `${sections.join("\n\n")}\n`;
|
|
34
|
+
}
|
|
35
|
+
/** `llms.txt` docs indexes for the selected stack (Vike is the always-present foundation). */
|
|
36
|
+
function referencesSection(meta) {
|
|
37
|
+
const refs = [];
|
|
38
|
+
for (const f of features) {
|
|
39
|
+
const { llms } = f;
|
|
40
|
+
if (llms && f.category !== "AI Agent" && (f.flag === "vike" || meta.BATI.has(f.flag))) refs.push(`- ${f.label} — ${llms}`);
|
|
41
|
+
}
|
|
42
|
+
return `## References
|
|
43
|
+
|
|
44
|
+
LLM-friendly docs (\`llms.txt\`) for this stack — fetch these for authoritative, up-to-date API details:
|
|
45
|
+
|
|
46
|
+
${refs.join("\n")}`;
|
|
47
|
+
}
|
|
48
|
+
/** Selected features grouped by category (excluding the AI agents themselves), in category order. */
|
|
49
|
+
function stackSection(meta) {
|
|
50
|
+
const byCategory = /* @__PURE__ */ new Map();
|
|
51
|
+
for (const f of features) {
|
|
52
|
+
if (f.category === "AI Agent" || !meta.BATI.has(f.flag)) continue;
|
|
53
|
+
byCategory.set(f.category, [...byCategory.get(f.category) ?? [], f.label]);
|
|
54
|
+
}
|
|
55
|
+
return `## Stack\n\n${categories.filter((c) => byCategory.has(c.label)).map((c) => `- **${c.label}:** ${byCategory.get(c.label).join(", ")}`).join("\n")}`;
|
|
56
|
+
}
|
|
57
|
+
function environmentSection(meta) {
|
|
58
|
+
const lines = ["- Client/build-time vars use the `PUBLIC_ENV__*` prefix (read via `import.meta.env`); everything else is server-only."];
|
|
59
|
+
if (meta.BATI.hasDotEnvSecrets) lines.unshift("- Environment variables are configured in `.env` (dev defaults are committed there); keep real secrets out of version control.");
|
|
60
|
+
else lines.unshift("- Non-secret vars live in `wrangler.jsonc` (`vars`); set secrets with `wrangler secret put <NAME>`. `.env` holds public/dev values only.");
|
|
61
|
+
return `## Environment\n\n${lines.join("\n")}`;
|
|
62
|
+
}
|
|
63
|
+
function structureSection(meta) {
|
|
64
|
+
const lines = ["- `pages/` — file-based routing. A route is a directory with a `+Page` file; add `+route`, `+data`, `+config`, `+guard`, or `+Layout` files beside it. See https://vike.dev.", "- `+config.ts` — Vike configuration (global under `pages/`, or per-route)."];
|
|
65
|
+
if (meta.BATI.hasServer) lines.push("- The app runs behind a server; the server entry boots Vike (see the `dev` script in `package.json`).");
|
|
66
|
+
if (meta.BATI.hasDatabase || meta.BATI.hasOrm) lines.push("- Database access lives in the project's db modules; check the schema/migration files and `package.json`.");
|
|
67
|
+
return `## Project structure\n\n${lines.join("\n")}`;
|
|
68
|
+
}
|
|
69
|
+
//#endregion
|
|
70
|
+
export { buildAgentsMd };
|
package/dist/boilerplates/@batijs/shared-agents/hooks/asset-boilerplates/shared-agents/compose.mjs
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { resolveInstructionFiles, resolveSkillDirs } from "../../asset-packages/features/dist/index.mjs";
|
|
2
|
+
//#region compose.ts
|
|
3
|
+
/**
|
|
4
|
+
* Materialize the agent files for a scaffold (SKILLS_PLAN.md §3/§4): every skill written to each
|
|
5
|
+
* minimal skills dir, plus the canonical `AGENTS.md` (= `agentsBody`) and its `@AGENTS.md` shims.
|
|
6
|
+
* Output order is deterministic (canonical agent order; skills sorted by name) for stable snapshots.
|
|
7
|
+
*/
|
|
8
|
+
function composeAgentFiles(meta, skills, agentsBody) {
|
|
9
|
+
assertUniqueNames(skills);
|
|
10
|
+
const selected = meta.BATI.aiAgents;
|
|
11
|
+
const sortedSkills = [...skills].sort((a, b) => a.name.localeCompare(b.name));
|
|
12
|
+
const files = [];
|
|
13
|
+
for (const dir of resolveSkillDirs(selected)) for (const skill of sortedSkills) files.push({
|
|
14
|
+
path: `${dir}/${skill.name}/SKILL.md`,
|
|
15
|
+
content: renderSkillMd(skill)
|
|
16
|
+
});
|
|
17
|
+
for (const target of resolveInstructionFiles(selected)) files.push({
|
|
18
|
+
path: target.path,
|
|
19
|
+
content: target.import === null ? ensureTrailingNewline(agentsBody) : `${target.import}\n`
|
|
20
|
+
});
|
|
21
|
+
return files;
|
|
22
|
+
}
|
|
23
|
+
/** Serialize a skill to a `SKILL.md` document (YAML frontmatter + body). */
|
|
24
|
+
function renderSkillMd(skill) {
|
|
25
|
+
const frontmatter = [`name: ${yamlString(skill.name)}`, `description: ${yamlString(skill.description)}`];
|
|
26
|
+
if (skill.allowedTools?.length) frontmatter.push(`allowed-tools: [${skill.allowedTools.map(yamlString).join(", ")}]`);
|
|
27
|
+
return `---\n${frontmatter.join("\n")}\n---\n\n${ensureTrailingNewline(skill.body)}`;
|
|
28
|
+
}
|
|
29
|
+
function assertUniqueNames(skills) {
|
|
30
|
+
const seen = /* @__PURE__ */ new Set();
|
|
31
|
+
for (const { name } of skills) {
|
|
32
|
+
if (seen.has(name)) throw new Error(`Duplicate skill name '${name}' — skill names must be unique.`);
|
|
33
|
+
seen.add(name);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function ensureTrailingNewline(s) {
|
|
37
|
+
return s.endsWith("\n") ? s : `${s}\n`;
|
|
38
|
+
}
|
|
39
|
+
/** Double-quote and escape so the colons/brackets common in descriptions stay YAML-safe. */
|
|
40
|
+
function yamlString(s) {
|
|
41
|
+
return `"${s.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
44
|
+
export { composeAgentFiles };
|