@json-render/next 0.15.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/LICENSE +201 -0
- package/README.md +103 -0
- package/dist/chunk-37T7IDU5.js +104 -0
- package/dist/chunk-37T7IDU5.js.map +1 -0
- package/dist/chunk-KWYBSJZC.mjs +104 -0
- package/dist/chunk-KWYBSJZC.mjs.map +1 -0
- package/dist/index.d.mts +314 -0
- package/dist/index.d.ts +314 -0
- package/dist/index.js +135 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +135 -0
- package/dist/index.mjs.map +1 -0
- package/dist/page-renderer-client.d.mts +25 -0
- package/dist/page-renderer-client.d.ts +25 -0
- package/dist/page-renderer-client.js +9 -0
- package/dist/page-renderer-client.js.map +1 -0
- package/dist/page-renderer-client.mjs +9 -0
- package/dist/page-renderer-client.mjs.map +1 -0
- package/dist/server.d.mts +358 -0
- package/dist/server.d.ts +358 -0
- package/dist/server.js +538 -0
- package/dist/server.js.map +1 -0
- package/dist/server.mjs +506 -0
- package/dist/server.mjs.map +1 -0
- package/package.json +71 -0
package/dist/server.js
ADDED
|
@@ -0,0 +1,538 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/server.ts
|
|
21
|
+
var server_exports = {};
|
|
22
|
+
__export(server_exports, {
|
|
23
|
+
collectStaticParams: () => collectStaticParams,
|
|
24
|
+
createNextApp: () => createNextApp,
|
|
25
|
+
matchRoute: () => matchRoute,
|
|
26
|
+
resolveMetadata: () => resolveMetadata,
|
|
27
|
+
schema: () => schema,
|
|
28
|
+
slugToPath: () => slugToPath
|
|
29
|
+
});
|
|
30
|
+
module.exports = __toCommonJS(server_exports);
|
|
31
|
+
|
|
32
|
+
// src/router.ts
|
|
33
|
+
function compileRoute(pattern) {
|
|
34
|
+
const paramNames = [];
|
|
35
|
+
let catchAll = false;
|
|
36
|
+
let optionalCatchAll = false;
|
|
37
|
+
let specificity = 0;
|
|
38
|
+
const segments = pattern === "/" ? [""] : pattern.split("/").slice(1);
|
|
39
|
+
const regexParts = [];
|
|
40
|
+
for (const segment of segments) {
|
|
41
|
+
if (segment.startsWith("[[...") && segment.endsWith("]]")) {
|
|
42
|
+
const paramName = segment.slice(5, -2);
|
|
43
|
+
paramNames.push(paramName);
|
|
44
|
+
optionalCatchAll = true;
|
|
45
|
+
regexParts.push("(?:/(.+))?");
|
|
46
|
+
} else if (segment.startsWith("[...") && segment.endsWith("]")) {
|
|
47
|
+
const paramName = segment.slice(4, -1);
|
|
48
|
+
paramNames.push(paramName);
|
|
49
|
+
catchAll = true;
|
|
50
|
+
regexParts.push("/(.+)");
|
|
51
|
+
} else if (segment.startsWith("[") && segment.endsWith("]")) {
|
|
52
|
+
const paramName = segment.slice(1, -1);
|
|
53
|
+
paramNames.push(paramName);
|
|
54
|
+
regexParts.push("/([^/]+)");
|
|
55
|
+
} else {
|
|
56
|
+
specificity++;
|
|
57
|
+
regexParts.push(`/${escapeRegExp(segment)}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const regexStr = pattern === "/" ? "^/$" : `^${regexParts.join("")}$`;
|
|
61
|
+
return {
|
|
62
|
+
pattern,
|
|
63
|
+
regex: new RegExp(regexStr),
|
|
64
|
+
paramNames,
|
|
65
|
+
catchAll,
|
|
66
|
+
optionalCatchAll,
|
|
67
|
+
specificity
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function escapeRegExp(str) {
|
|
71
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
72
|
+
}
|
|
73
|
+
function matchRoute(spec, pathname) {
|
|
74
|
+
const normalizedPath = pathname === "" ? "/" : pathname;
|
|
75
|
+
const compiled = Object.keys(spec.routes).map(compileRoute);
|
|
76
|
+
compiled.sort((a, b) => {
|
|
77
|
+
if (a.optionalCatchAll !== b.optionalCatchAll) {
|
|
78
|
+
return a.optionalCatchAll ? 1 : -1;
|
|
79
|
+
}
|
|
80
|
+
if (a.catchAll !== b.catchAll) {
|
|
81
|
+
return a.catchAll ? 1 : -1;
|
|
82
|
+
}
|
|
83
|
+
if (a.specificity !== b.specificity) {
|
|
84
|
+
return b.specificity - a.specificity;
|
|
85
|
+
}
|
|
86
|
+
return a.paramNames.length - b.paramNames.length;
|
|
87
|
+
});
|
|
88
|
+
for (const route of compiled) {
|
|
89
|
+
const match = route.regex.exec(normalizedPath);
|
|
90
|
+
if (!match) continue;
|
|
91
|
+
const params = {};
|
|
92
|
+
for (let i = 0; i < route.paramNames.length; i++) {
|
|
93
|
+
const value = match[i + 1];
|
|
94
|
+
const name = route.paramNames[i];
|
|
95
|
+
if (route.catchAll || route.optionalCatchAll) {
|
|
96
|
+
params[name] = value ? value.split("/") : [];
|
|
97
|
+
} else {
|
|
98
|
+
params[name] = value ?? "";
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
route: spec.routes[route.pattern],
|
|
103
|
+
pattern: route.pattern,
|
|
104
|
+
params
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
function slugToPath(slug) {
|
|
110
|
+
if (!slug || slug.length === 0) return "/";
|
|
111
|
+
return "/" + slug.join("/");
|
|
112
|
+
}
|
|
113
|
+
function collectStaticParams(spec) {
|
|
114
|
+
const results = [];
|
|
115
|
+
for (const [pattern, route] of Object.entries(spec.routes)) {
|
|
116
|
+
if (route.staticParams) {
|
|
117
|
+
for (const paramSet of route.staticParams) {
|
|
118
|
+
const slug = buildSlugFromPattern(pattern, paramSet);
|
|
119
|
+
if (slug) results.push({ slug });
|
|
120
|
+
}
|
|
121
|
+
} else if (!pattern.includes("[")) {
|
|
122
|
+
const slug = pattern === "/" ? [] : pattern.slice(1).split("/");
|
|
123
|
+
results.push({ slug });
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return results;
|
|
127
|
+
}
|
|
128
|
+
function buildSlugFromPattern(pattern, params) {
|
|
129
|
+
if (pattern === "/") return [];
|
|
130
|
+
const segments = pattern.split("/").slice(1);
|
|
131
|
+
const result = [];
|
|
132
|
+
for (const segment of segments) {
|
|
133
|
+
if (segment.startsWith("[[...") && segment.endsWith("]]")) {
|
|
134
|
+
const paramName = segment.slice(5, -2);
|
|
135
|
+
const value = params[paramName];
|
|
136
|
+
if (value) result.push(...value.split("/"));
|
|
137
|
+
} else if (segment.startsWith("[...") && segment.endsWith("]")) {
|
|
138
|
+
const paramName = segment.slice(4, -1);
|
|
139
|
+
const value = params[paramName];
|
|
140
|
+
if (!value) return null;
|
|
141
|
+
result.push(...value.split("/"));
|
|
142
|
+
} else if (segment.startsWith("[") && segment.endsWith("]")) {
|
|
143
|
+
const paramName = segment.slice(1, -1);
|
|
144
|
+
const value = params[paramName];
|
|
145
|
+
if (!value) return null;
|
|
146
|
+
result.push(value);
|
|
147
|
+
} else {
|
|
148
|
+
result.push(segment);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return result;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// src/metadata.ts
|
|
155
|
+
function resolveMetadata(spec, route) {
|
|
156
|
+
const globalMeta = spec.metadata;
|
|
157
|
+
const routeMeta = route?.metadata;
|
|
158
|
+
if (!globalMeta && !routeMeta) return {};
|
|
159
|
+
const result = {};
|
|
160
|
+
const mergedTitle = resolveTitle(globalMeta?.title, routeMeta?.title);
|
|
161
|
+
if (mergedTitle !== void 0) result.title = mergedTitle;
|
|
162
|
+
const description = routeMeta?.description ?? globalMeta?.description;
|
|
163
|
+
if (description) result.description = description;
|
|
164
|
+
const keywords = routeMeta?.keywords ?? globalMeta?.keywords;
|
|
165
|
+
if (keywords) result.keywords = keywords;
|
|
166
|
+
const openGraph = mergeObject(globalMeta?.openGraph, routeMeta?.openGraph);
|
|
167
|
+
if (openGraph) result.openGraph = openGraph;
|
|
168
|
+
const twitter = mergeObject(globalMeta?.twitter, routeMeta?.twitter);
|
|
169
|
+
if (twitter) result.twitter = twitter;
|
|
170
|
+
const robots = routeMeta?.robots ?? globalMeta?.robots;
|
|
171
|
+
if (robots) result.robots = robots;
|
|
172
|
+
const alternates = routeMeta?.alternates ?? globalMeta?.alternates;
|
|
173
|
+
if (alternates) result.alternates = alternates;
|
|
174
|
+
const icons = routeMeta?.icons ?? globalMeta?.icons;
|
|
175
|
+
if (icons) result.icons = icons;
|
|
176
|
+
return result;
|
|
177
|
+
}
|
|
178
|
+
function resolveTitle(globalTitle, routeTitle) {
|
|
179
|
+
if (!routeTitle && !globalTitle) return void 0;
|
|
180
|
+
if (!routeTitle) {
|
|
181
|
+
if (typeof globalTitle === "string") return globalTitle;
|
|
182
|
+
if (typeof globalTitle === "object" && globalTitle !== null) {
|
|
183
|
+
return globalTitle.default ?? void 0;
|
|
184
|
+
}
|
|
185
|
+
return void 0;
|
|
186
|
+
}
|
|
187
|
+
if (typeof routeTitle === "object" && routeTitle !== null) {
|
|
188
|
+
if (routeTitle.absolute) return routeTitle.absolute;
|
|
189
|
+
if (routeTitle.template || routeTitle.default) return routeTitle;
|
|
190
|
+
return routeTitle;
|
|
191
|
+
}
|
|
192
|
+
if (typeof globalTitle === "object" && globalTitle !== null && globalTitle.template) {
|
|
193
|
+
return globalTitle.template.replace("%s", routeTitle);
|
|
194
|
+
}
|
|
195
|
+
return routeTitle;
|
|
196
|
+
}
|
|
197
|
+
function mergeObject(base, override) {
|
|
198
|
+
if (!base && !override) return void 0;
|
|
199
|
+
if (!base) return override;
|
|
200
|
+
if (!override) return base;
|
|
201
|
+
return { ...base, ...override };
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// src/create-app.ts
|
|
205
|
+
async function resolveSpec(specOrFn) {
|
|
206
|
+
if (typeof specOrFn === "function") {
|
|
207
|
+
return await specOrFn();
|
|
208
|
+
}
|
|
209
|
+
return specOrFn;
|
|
210
|
+
}
|
|
211
|
+
function mergeState(...sources) {
|
|
212
|
+
const result = {};
|
|
213
|
+
for (const source of sources) {
|
|
214
|
+
if (source) {
|
|
215
|
+
Object.assign(result, source);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return result;
|
|
219
|
+
}
|
|
220
|
+
function createNextApp(options) {
|
|
221
|
+
const { spec: specOrFn, loaders } = options;
|
|
222
|
+
async function getPageData({
|
|
223
|
+
params
|
|
224
|
+
}) {
|
|
225
|
+
const { slug } = await params;
|
|
226
|
+
const pathname = slugToPath(slug);
|
|
227
|
+
const spec = await resolveSpec(specOrFn);
|
|
228
|
+
const matched = matchRoute(spec, pathname);
|
|
229
|
+
if (!matched) {
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
const { route } = matched;
|
|
233
|
+
let loaderData;
|
|
234
|
+
if (route.loader && loaders?.[route.loader]) {
|
|
235
|
+
loaderData = await loaders[route.loader](matched.params);
|
|
236
|
+
}
|
|
237
|
+
const initialState = mergeState(
|
|
238
|
+
spec.state,
|
|
239
|
+
route.page.state,
|
|
240
|
+
loaderData
|
|
241
|
+
);
|
|
242
|
+
const layoutSpec = route.layout && spec.layouts ? spec.layouts[route.layout] ?? null : null;
|
|
243
|
+
return {
|
|
244
|
+
spec: route.page,
|
|
245
|
+
initialState: Object.keys(initialState).length > 0 ? initialState : void 0,
|
|
246
|
+
layoutSpec
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
async function generateMetadata({
|
|
250
|
+
params
|
|
251
|
+
}) {
|
|
252
|
+
const { slug } = await params;
|
|
253
|
+
const pathname = slugToPath(slug);
|
|
254
|
+
const spec = await resolveSpec(specOrFn);
|
|
255
|
+
const matched = matchRoute(spec, pathname);
|
|
256
|
+
return resolveMetadata(spec, matched?.route ?? null);
|
|
257
|
+
}
|
|
258
|
+
async function generateStaticParams() {
|
|
259
|
+
const spec = await resolveSpec(specOrFn);
|
|
260
|
+
return collectStaticParams(spec);
|
|
261
|
+
}
|
|
262
|
+
return { getPageData, generateMetadata, generateStaticParams };
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// src/schema.ts
|
|
266
|
+
var import_core = require("@json-render/core");
|
|
267
|
+
function nextAppPromptTemplate(context) {
|
|
268
|
+
const { catalog, options, formatZodType } = context;
|
|
269
|
+
const {
|
|
270
|
+
system = "You are a Next.js application generator.",
|
|
271
|
+
customRules = []
|
|
272
|
+
} = options;
|
|
273
|
+
const lines = [];
|
|
274
|
+
lines.push(system);
|
|
275
|
+
lines.push("");
|
|
276
|
+
lines.push("OUTPUT FORMAT:");
|
|
277
|
+
lines.push(
|
|
278
|
+
"Output JSONL (one JSON object per line) with RFC 6902 JSON Patch operations to build a Next.js application spec."
|
|
279
|
+
);
|
|
280
|
+
lines.push(
|
|
281
|
+
"The spec defines routes (pages), layouts, metadata, and state for a full Next.js app."
|
|
282
|
+
);
|
|
283
|
+
lines.push("");
|
|
284
|
+
lines.push("Example output (each line is a separate JSON object):");
|
|
285
|
+
lines.push("");
|
|
286
|
+
lines.push(
|
|
287
|
+
`{"op":"add","path":"/metadata","value":{"title":{"default":"My App","template":"%s | My App"},"description":"A full Next.js application"}}`
|
|
288
|
+
);
|
|
289
|
+
lines.push(`{"op":"add","path":"/layouts","value":{}}`);
|
|
290
|
+
lines.push(
|
|
291
|
+
`{"op":"add","path":"/layouts/main","value":{"root":"shell","elements":{"shell":{"type":"AppShell","props":{},"children":["nav","slot"]},"nav":{"type":"NavBar","props":{"links":[{"href":"/","label":"Home"},{"href":"/about","label":"About"}]},"children":[]},"slot":{"type":"Slot","props":{},"children":[]}}}}`
|
|
292
|
+
);
|
|
293
|
+
lines.push(`{"op":"add","path":"/routes","value":{}}`);
|
|
294
|
+
lines.push(
|
|
295
|
+
`{"op":"add","path":"/routes/~1","value":{"layout":"main","metadata":{"title":"Home"},"page":{"root":"hero","elements":{"hero":{"type":"Card","props":{"title":"Welcome"},"children":[]}}}}}`
|
|
296
|
+
);
|
|
297
|
+
lines.push(
|
|
298
|
+
`{"op":"add","path":"/routes/~1about","value":{"layout":"main","metadata":{"title":"About"},"page":{"root":"content","elements":{"content":{"type":"Card","props":{"title":"About Us"},"children":[]}}}}}`
|
|
299
|
+
);
|
|
300
|
+
lines.push("");
|
|
301
|
+
lines.push("SPEC STRUCTURE:");
|
|
302
|
+
lines.push("The top-level spec has these fields:");
|
|
303
|
+
lines.push(
|
|
304
|
+
" - metadata: Root-level SEO metadata (title template, description, openGraph, twitter)"
|
|
305
|
+
);
|
|
306
|
+
lines.push(
|
|
307
|
+
" - layouts: Reusable layout element trees. Each layout MUST include a { type: 'Slot' } element where page content will be injected."
|
|
308
|
+
);
|
|
309
|
+
lines.push(" - routes: Route definitions keyed by URL pattern");
|
|
310
|
+
lines.push(" - state: Global initial state shared across all routes");
|
|
311
|
+
lines.push("");
|
|
312
|
+
lines.push("ROUTES:");
|
|
313
|
+
lines.push("Route keys use Next.js URL patterns:");
|
|
314
|
+
lines.push(" - '/' - home page");
|
|
315
|
+
lines.push(" - '/about' - static route");
|
|
316
|
+
lines.push(" - '/blog/[slug]' - dynamic segment");
|
|
317
|
+
lines.push(" - '/docs/[...path]' - catch-all segment");
|
|
318
|
+
lines.push(" - '/settings/[[...path]]' - optional catch-all segment");
|
|
319
|
+
lines.push("");
|
|
320
|
+
lines.push(
|
|
321
|
+
"IMPORTANT: In JSON Patch paths, forward slashes in route keys must be escaped as ~1."
|
|
322
|
+
);
|
|
323
|
+
lines.push(" - Route '/' becomes path '/routes/~1'");
|
|
324
|
+
lines.push(" - Route '/about' becomes path '/routes/~1about'");
|
|
325
|
+
lines.push(" - Route '/blog/[slug]' becomes path '/routes/~1blog~1[slug]'");
|
|
326
|
+
lines.push("");
|
|
327
|
+
lines.push("Each route has:");
|
|
328
|
+
lines.push(
|
|
329
|
+
" - page: Element tree (root + elements + optional state) \u2014 the page content"
|
|
330
|
+
);
|
|
331
|
+
lines.push(
|
|
332
|
+
" - metadata: Per-route SEO metadata (title, description, openGraph)"
|
|
333
|
+
);
|
|
334
|
+
lines.push(" - layout: Layout key referencing an entry in the layouts map");
|
|
335
|
+
lines.push(" - loading: Optional loading state element tree");
|
|
336
|
+
lines.push(" - error: Optional error state element tree");
|
|
337
|
+
lines.push(" - loader: Optional server-side data loader name");
|
|
338
|
+
lines.push("");
|
|
339
|
+
lines.push("LAYOUTS:");
|
|
340
|
+
lines.push(
|
|
341
|
+
"Layouts wrap page content. A layout element tree MUST include a component with type 'Slot' \u2014 this is where the page content will be rendered."
|
|
342
|
+
);
|
|
343
|
+
lines.push(
|
|
344
|
+
"Layouts are defined once and reused across routes via the layout field."
|
|
345
|
+
);
|
|
346
|
+
lines.push("");
|
|
347
|
+
lines.push("METADATA:");
|
|
348
|
+
lines.push("Root metadata sets defaults. Route metadata overrides per page.");
|
|
349
|
+
lines.push(
|
|
350
|
+
" - title: string or { default, template } (use %s for page title in template)"
|
|
351
|
+
);
|
|
352
|
+
lines.push(" - description: string");
|
|
353
|
+
lines.push(" - openGraph: { title, description, images, type }");
|
|
354
|
+
lines.push(" - twitter: { card, title, description }");
|
|
355
|
+
lines.push("");
|
|
356
|
+
lines.push("PAGE CONTENT:");
|
|
357
|
+
lines.push(
|
|
358
|
+
"Each page uses the standard json-render element tree format: root, elements, optional state."
|
|
359
|
+
);
|
|
360
|
+
lines.push(
|
|
361
|
+
"Elements have type, props, children, and optionally visible, on, repeat, watch fields."
|
|
362
|
+
);
|
|
363
|
+
lines.push("");
|
|
364
|
+
const catalogData = catalog;
|
|
365
|
+
if (catalogData.components) {
|
|
366
|
+
lines.push(
|
|
367
|
+
`AVAILABLE COMPONENTS (${Object.keys(catalogData.components).length}):`
|
|
368
|
+
);
|
|
369
|
+
lines.push("");
|
|
370
|
+
for (const [name, def] of Object.entries(catalogData.components)) {
|
|
371
|
+
const propsStr = def.props ? formatZodType(def.props) : "{}";
|
|
372
|
+
const hasChildren = def.slots && def.slots.length > 0;
|
|
373
|
+
const childrenStr = hasChildren ? " [accepts children]" : "";
|
|
374
|
+
const eventsStr = def.events && def.events.length > 0 ? ` [events: ${def.events.join(", ")}]` : "";
|
|
375
|
+
const descStr = def.description ? ` - ${def.description}` : "";
|
|
376
|
+
lines.push(`- ${name}: ${propsStr}${descStr}${childrenStr}${eventsStr}`);
|
|
377
|
+
}
|
|
378
|
+
lines.push("");
|
|
379
|
+
lines.push("Built-in components (always available):");
|
|
380
|
+
lines.push(
|
|
381
|
+
"- Slot: {} - Placeholder in layouts where page content is rendered. Required in every layout."
|
|
382
|
+
);
|
|
383
|
+
lines.push(
|
|
384
|
+
"- Link: { href: string } [accepts children] - Client-side navigation link (renders as next/link)."
|
|
385
|
+
);
|
|
386
|
+
lines.push("");
|
|
387
|
+
}
|
|
388
|
+
if (catalogData.actions && Object.keys(catalogData.actions).length > 0) {
|
|
389
|
+
lines.push("AVAILABLE ACTIONS:");
|
|
390
|
+
lines.push("");
|
|
391
|
+
for (const [name, def] of Object.entries(catalogData.actions)) {
|
|
392
|
+
lines.push(`- ${name}${def.description ? `: ${def.description}` : ""}`);
|
|
393
|
+
}
|
|
394
|
+
lines.push("");
|
|
395
|
+
}
|
|
396
|
+
lines.push("BUILT-IN ACTIONS:");
|
|
397
|
+
lines.push(
|
|
398
|
+
"- setState: Update a value in the state model. Params: { statePath: string, value: any }"
|
|
399
|
+
);
|
|
400
|
+
lines.push(
|
|
401
|
+
"- pushState: Append an item to an array in state. Params: { statePath: string, value: any, clearStatePath?: string }"
|
|
402
|
+
);
|
|
403
|
+
lines.push(
|
|
404
|
+
"- removeState: Remove an item from an array by index. Params: { statePath: string, index: number }"
|
|
405
|
+
);
|
|
406
|
+
lines.push("- navigate: Navigate to a route. Params: { href: string }");
|
|
407
|
+
lines.push("");
|
|
408
|
+
lines.push("RULES:");
|
|
409
|
+
const baseRules = [
|
|
410
|
+
"Output ONLY JSONL patches - one JSON object per line, no markdown, no code fences",
|
|
411
|
+
"First add /metadata with the app-level metadata including title template",
|
|
412
|
+
"Then add /layouts with reusable layout definitions (each must have a Slot component)",
|
|
413
|
+
"Then add /routes with each route's page, metadata, and layout reference",
|
|
414
|
+
"Every layout MUST include a { type: 'Slot' } element where page content is injected",
|
|
415
|
+
"ONLY use components listed in AVAILABLE COMPONENTS (plus built-in Slot and Link)",
|
|
416
|
+
"Each element needs: type, props, children (array of child keys)",
|
|
417
|
+
"Use unique keys for element map entries",
|
|
418
|
+
"Escape forward slashes in route keys as ~1 in JSON Patch paths",
|
|
419
|
+
"Include realistic sample data in state for data-driven pages",
|
|
420
|
+
"Use Link component for navigation between routes",
|
|
421
|
+
"Create a cohesive multi-page app with consistent layouts and navigation"
|
|
422
|
+
];
|
|
423
|
+
const allRules = [...baseRules, ...customRules];
|
|
424
|
+
allRules.forEach((rule, i) => {
|
|
425
|
+
lines.push(`${i + 1}. ${rule}`);
|
|
426
|
+
});
|
|
427
|
+
return lines.join("\n");
|
|
428
|
+
}
|
|
429
|
+
var schema = (0, import_core.defineSchema)(
|
|
430
|
+
(s) => ({
|
|
431
|
+
spec: s.object({
|
|
432
|
+
/** Root-level metadata applied as defaults */
|
|
433
|
+
metadata: s.object({
|
|
434
|
+
title: s.any(),
|
|
435
|
+
description: s.string(),
|
|
436
|
+
keywords: s.array(s.string()),
|
|
437
|
+
openGraph: s.any(),
|
|
438
|
+
twitter: s.any(),
|
|
439
|
+
robots: s.any(),
|
|
440
|
+
icons: s.any()
|
|
441
|
+
}),
|
|
442
|
+
/** Route definitions keyed by URL pattern */
|
|
443
|
+
routes: s.record(
|
|
444
|
+
s.object({
|
|
445
|
+
/** Page element tree */
|
|
446
|
+
page: s.object({
|
|
447
|
+
root: s.string(),
|
|
448
|
+
elements: s.record(
|
|
449
|
+
s.object({
|
|
450
|
+
type: s.ref("catalog.components"),
|
|
451
|
+
props: s.propsOf("catalog.components"),
|
|
452
|
+
children: s.array(s.string()),
|
|
453
|
+
visible: s.any()
|
|
454
|
+
})
|
|
455
|
+
),
|
|
456
|
+
state: s.any()
|
|
457
|
+
}),
|
|
458
|
+
/** Per-route metadata */
|
|
459
|
+
metadata: s.any(),
|
|
460
|
+
/** Layout key */
|
|
461
|
+
layout: s.string(),
|
|
462
|
+
/** Loading state element tree */
|
|
463
|
+
loading: s.any(),
|
|
464
|
+
/** Error state element tree */
|
|
465
|
+
error: s.any(),
|
|
466
|
+
/** Not-found element tree */
|
|
467
|
+
notFound: s.any(),
|
|
468
|
+
/** Server-side data loader name */
|
|
469
|
+
loader: s.string(),
|
|
470
|
+
/** Static params for SSG */
|
|
471
|
+
staticParams: s.any()
|
|
472
|
+
})
|
|
473
|
+
),
|
|
474
|
+
/** Reusable layout element trees */
|
|
475
|
+
layouts: s.record(
|
|
476
|
+
s.object({
|
|
477
|
+
root: s.string(),
|
|
478
|
+
elements: s.record(
|
|
479
|
+
s.object({
|
|
480
|
+
type: s.ref("catalog.components"),
|
|
481
|
+
props: s.propsOf("catalog.components"),
|
|
482
|
+
children: s.array(s.string()),
|
|
483
|
+
visible: s.any()
|
|
484
|
+
})
|
|
485
|
+
),
|
|
486
|
+
state: s.any()
|
|
487
|
+
})
|
|
488
|
+
),
|
|
489
|
+
/** Global initial state */
|
|
490
|
+
state: s.any()
|
|
491
|
+
}),
|
|
492
|
+
catalog: s.object({
|
|
493
|
+
/** Component definitions */
|
|
494
|
+
components: s.map({
|
|
495
|
+
props: s.zod(),
|
|
496
|
+
slots: s.array(s.string()),
|
|
497
|
+
description: s.string(),
|
|
498
|
+
example: s.any()
|
|
499
|
+
}),
|
|
500
|
+
/** Action definitions (optional) */
|
|
501
|
+
actions: s.map({
|
|
502
|
+
params: s.zod(),
|
|
503
|
+
description: s.string()
|
|
504
|
+
})
|
|
505
|
+
})
|
|
506
|
+
}),
|
|
507
|
+
{
|
|
508
|
+
promptTemplate: nextAppPromptTemplate,
|
|
509
|
+
builtInActions: [
|
|
510
|
+
{
|
|
511
|
+
name: "setState",
|
|
512
|
+
description: "Update a value in the state model at the given statePath. Params: { statePath: string, value: any }"
|
|
513
|
+
},
|
|
514
|
+
{
|
|
515
|
+
name: "pushState",
|
|
516
|
+
description: 'Append an item to an array in state. Params: { statePath: string, value: any, clearStatePath?: string }. Value can contain {"$state":"/path"} refs and "$id" for auto IDs.'
|
|
517
|
+
},
|
|
518
|
+
{
|
|
519
|
+
name: "removeState",
|
|
520
|
+
description: "Remove an item from an array in state by index. Params: { statePath: string, index: number }"
|
|
521
|
+
},
|
|
522
|
+
{
|
|
523
|
+
name: "navigate",
|
|
524
|
+
description: "Navigate to a route within the app. Params: { href: string }"
|
|
525
|
+
}
|
|
526
|
+
]
|
|
527
|
+
}
|
|
528
|
+
);
|
|
529
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
530
|
+
0 && (module.exports = {
|
|
531
|
+
collectStaticParams,
|
|
532
|
+
createNextApp,
|
|
533
|
+
matchRoute,
|
|
534
|
+
resolveMetadata,
|
|
535
|
+
schema,
|
|
536
|
+
slugToPath
|
|
537
|
+
});
|
|
538
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server.ts","../src/router.ts","../src/metadata.ts","../src/create-app.ts","../src/schema.ts"],"sourcesContent":["/**\n * @json-render/next/server — Server-safe exports\n *\n * This entry point does not import any client components or React hooks.\n * Safe to use in:\n * - Server Components\n * - API routes\n * - Build scripts\n * - Server Actions\n *\n * @example\n * ```ts\n * import { createNextApp, schema } from \"@json-render/next/server\";\n * ```\n */\n\n// createNextApp (main API)\nexport { createNextApp } from \"./create-app\";\n\n// Schema (Next.js app spec format)\nexport { schema, type NextSchema, type NextSpec } from \"./schema\";\n\n// Router utilities\nexport { matchRoute, slugToPath, collectStaticParams } from \"./router\";\n\n// Metadata resolution\nexport { resolveMetadata, type ResolvedMetadata } from \"./metadata\";\n\n// Types\nexport type {\n NextAppSpec,\n NextRouteSpec,\n NextMetadata,\n MatchedRoute,\n LoaderFn,\n CreateNextAppOptions,\n NextAppExports,\n PageData,\n} from \"./types\";\n\n// Catalog types (type-only, no runtime)\nexport type {\n EventHandle,\n BaseComponentProps,\n SetState,\n StateModel,\n ComponentContext,\n ComponentFn,\n Components,\n ActionFn,\n Actions,\n} from \"./catalog-types\";\n\n// Core types (re-exported for convenience)\nexport type { Spec, StateStore } from \"@json-render/core\";\n","import type { NextAppSpec, MatchedRoute } from \"./types\";\n\ninterface CompiledRoute {\n pattern: string;\n regex: RegExp;\n paramNames: string[];\n /** Whether the last segment is catch-all or optional catch-all */\n catchAll: boolean;\n optionalCatchAll: boolean;\n /** Number of static segments (higher = more specific) */\n specificity: number;\n}\n\n/**\n * Compile a Next.js route pattern into a regex matcher.\n *\n * Supports:\n * - Static segments: `/about`, `/blog`\n * - Dynamic segments: `/blog/[slug]`\n * - Catch-all segments: `/docs/[...path]`\n * - Optional catch-all segments: `/settings/[[...path]]`\n */\nfunction compileRoute(pattern: string): CompiledRoute {\n const paramNames: string[] = [];\n let catchAll = false;\n let optionalCatchAll = false;\n let specificity = 0;\n\n const segments = pattern === \"/\" ? [\"\"] : pattern.split(\"/\").slice(1);\n const regexParts: string[] = [];\n\n for (const segment of segments) {\n if (segment.startsWith(\"[[...\") && segment.endsWith(\"]]\")) {\n const paramName = segment.slice(5, -2);\n paramNames.push(paramName);\n optionalCatchAll = true;\n regexParts.push(\"(?:/(.+))?\");\n } else if (segment.startsWith(\"[...\") && segment.endsWith(\"]\")) {\n const paramName = segment.slice(4, -1);\n paramNames.push(paramName);\n catchAll = true;\n regexParts.push(\"/(.+)\");\n } else if (segment.startsWith(\"[\") && segment.endsWith(\"]\")) {\n const paramName = segment.slice(1, -1);\n paramNames.push(paramName);\n regexParts.push(\"/([^/]+)\");\n } else {\n specificity++;\n regexParts.push(`/${escapeRegExp(segment)}`);\n }\n }\n\n const regexStr = pattern === \"/\" ? \"^/$\" : `^${regexParts.join(\"\")}$`;\n\n return {\n pattern,\n regex: new RegExp(regexStr),\n paramNames,\n catchAll,\n optionalCatchAll,\n specificity,\n };\n}\n\nfunction escapeRegExp(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/**\n * Match a pathname against a spec's routes.\n *\n * Routes are matched in order of specificity:\n * 1. Exact/static matches first (most specific)\n * 2. Dynamic segment matches\n * 3. Catch-all matches (least specific)\n * 4. Optional catch-all matches (fallback)\n *\n * @returns The matched route with extracted params, or null if no match.\n */\nexport function matchRoute(\n spec: NextAppSpec,\n pathname: string,\n): MatchedRoute | null {\n const normalizedPath = pathname === \"\" ? \"/\" : pathname;\n\n const compiled = Object.keys(spec.routes).map(compileRoute);\n\n compiled.sort((a, b) => {\n if (a.optionalCatchAll !== b.optionalCatchAll) {\n return a.optionalCatchAll ? 1 : -1;\n }\n if (a.catchAll !== b.catchAll) {\n return a.catchAll ? 1 : -1;\n }\n if (a.specificity !== b.specificity) {\n return b.specificity - a.specificity;\n }\n return a.paramNames.length - b.paramNames.length;\n });\n\n for (const route of compiled) {\n const match = route.regex.exec(normalizedPath);\n if (!match) continue;\n\n const params: Record<string, string | string[]> = {};\n for (let i = 0; i < route.paramNames.length; i++) {\n const value = match[i + 1];\n const name = route.paramNames[i]!;\n\n if (route.catchAll || route.optionalCatchAll) {\n params[name] = value ? value.split(\"/\") : [];\n } else {\n params[name] = value ?? \"\";\n }\n }\n\n return {\n route: spec.routes[route.pattern]!,\n pattern: route.pattern,\n params,\n };\n }\n\n return null;\n}\n\n/**\n * Convert a Next.js catch-all slug array to a pathname.\n *\n * @example\n * slugToPath(undefined) // \"/\"\n * slugToPath([]) // \"/\"\n * slugToPath([\"blog\"]) // \"/blog\"\n * slugToPath([\"blog\",\"hi\"]) // \"/blog/hi\"\n */\nexport function slugToPath(slug: string[] | undefined): string {\n if (!slug || slug.length === 0) return \"/\";\n return \"/\" + slug.join(\"/\");\n}\n\n/**\n * Collect all static params from the spec for generateStaticParams.\n * Returns params suitable for Next.js [[...slug]] catch-all routes.\n */\nexport function collectStaticParams(spec: NextAppSpec): { slug: string[] }[] {\n const results: { slug: string[] }[] = [];\n\n for (const [pattern, route] of Object.entries(spec.routes)) {\n if (route.staticParams) {\n for (const paramSet of route.staticParams) {\n const slug = buildSlugFromPattern(pattern, paramSet);\n if (slug) results.push({ slug });\n }\n } else if (!pattern.includes(\"[\")) {\n const slug = pattern === \"/\" ? [] : pattern.slice(1).split(\"/\");\n results.push({ slug });\n }\n }\n\n return results;\n}\n\n/**\n * Build a slug array from a route pattern and a set of params.\n */\nfunction buildSlugFromPattern(\n pattern: string,\n params: Record<string, string>,\n): string[] | null {\n if (pattern === \"/\") return [];\n\n const segments = pattern.split(\"/\").slice(1);\n const result: string[] = [];\n\n for (const segment of segments) {\n if (segment.startsWith(\"[[...\") && segment.endsWith(\"]]\")) {\n const paramName = segment.slice(5, -2);\n const value = params[paramName];\n if (value) result.push(...value.split(\"/\"));\n } else if (segment.startsWith(\"[...\") && segment.endsWith(\"]\")) {\n const paramName = segment.slice(4, -1);\n const value = params[paramName];\n if (!value) return null;\n result.push(...value.split(\"/\"));\n } else if (segment.startsWith(\"[\") && segment.endsWith(\"]\")) {\n const paramName = segment.slice(1, -1);\n const value = params[paramName];\n if (!value) return null;\n result.push(value);\n } else {\n result.push(segment);\n }\n }\n\n return result;\n}\n","import type { NextMetadata, NextAppSpec, NextRouteSpec } from \"./types\";\n\n/**\n * Metadata result compatible with Next.js's Metadata type.\n * Uses plain objects to avoid importing Next.js types at runtime.\n */\nexport type ResolvedMetadata = Record<string, unknown>;\n\n/**\n * Resolve metadata for a route by merging global spec metadata\n * with route-specific metadata.\n *\n * Follows Next.js metadata merging semantics:\n * - Route metadata overrides global metadata for scalar fields\n * - Title templates from global metadata apply to route titles\n * - OpenGraph and Twitter fields are shallow-merged\n */\nexport function resolveMetadata(\n spec: NextAppSpec,\n route?: NextRouteSpec | null,\n): ResolvedMetadata {\n const globalMeta = spec.metadata;\n const routeMeta = route?.metadata;\n\n if (!globalMeta && !routeMeta) return {};\n\n const result: ResolvedMetadata = {};\n\n const mergedTitle = resolveTitle(globalMeta?.title, routeMeta?.title);\n if (mergedTitle !== undefined) result.title = mergedTitle;\n\n const description = routeMeta?.description ?? globalMeta?.description;\n if (description) result.description = description;\n\n const keywords = routeMeta?.keywords ?? globalMeta?.keywords;\n if (keywords) result.keywords = keywords;\n\n const openGraph = mergeObject(globalMeta?.openGraph, routeMeta?.openGraph);\n if (openGraph) result.openGraph = openGraph;\n\n const twitter = mergeObject(globalMeta?.twitter, routeMeta?.twitter);\n if (twitter) result.twitter = twitter;\n\n const robots = routeMeta?.robots ?? globalMeta?.robots;\n if (robots) result.robots = robots;\n\n const alternates = routeMeta?.alternates ?? globalMeta?.alternates;\n if (alternates) result.alternates = alternates;\n\n const icons = routeMeta?.icons ?? globalMeta?.icons;\n if (icons) result.icons = icons;\n\n return result;\n}\n\n/**\n * Resolve a title value considering templates.\n *\n * If global metadata defines a title template (e.g. \"%s | My App\"),\n * route titles are interpolated into it.\n */\nfunction resolveTitle(\n globalTitle: NextMetadata[\"title\"],\n routeTitle: NextMetadata[\"title\"],\n): unknown {\n if (!routeTitle && !globalTitle) return undefined;\n\n if (!routeTitle) {\n if (typeof globalTitle === \"string\") return globalTitle;\n if (typeof globalTitle === \"object\" && globalTitle !== null) {\n return globalTitle.default ?? undefined;\n }\n return undefined;\n }\n\n if (typeof routeTitle === \"object\" && routeTitle !== null) {\n if (routeTitle.absolute) return routeTitle.absolute;\n if (routeTitle.template || routeTitle.default) return routeTitle;\n return routeTitle;\n }\n\n if (\n typeof globalTitle === \"object\" &&\n globalTitle !== null &&\n globalTitle.template\n ) {\n return globalTitle.template.replace(\"%s\", routeTitle as string);\n }\n\n return routeTitle;\n}\n\nfunction mergeObject(\n base: Record<string, unknown> | undefined,\n override: Record<string, unknown> | undefined,\n): Record<string, unknown> | undefined {\n if (!base && !override) return undefined;\n if (!base) return override;\n if (!override) return base;\n return { ...base, ...override };\n}\n","import { notFound } from \"next/navigation\";\nimport type {\n NextAppSpec,\n CreateNextAppOptions,\n NextAppExports,\n PageData,\n} from \"./types\";\nimport { matchRoute, slugToPath, collectStaticParams } from \"./router\";\nimport { resolveMetadata, type ResolvedMetadata } from \"./metadata\";\n\n/**\n * Resolve the spec from the options — supports both static specs\n * and factory functions that return specs (sync or async).\n */\nasync function resolveSpec(\n specOrFn: NextAppSpec | (() => NextAppSpec | Promise<NextAppSpec>),\n): Promise<NextAppSpec> {\n if (typeof specOrFn === \"function\") {\n return await specOrFn();\n }\n return specOrFn;\n}\n\n/**\n * Merge state from multiple sources: global state, page state, and loader data.\n * Later sources override earlier ones.\n */\nfunction mergeState(\n ...sources: (Record<string, unknown> | undefined | null)[]\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const source of sources) {\n if (source) {\n Object.assign(result, source);\n }\n }\n return result;\n}\n\n/**\n * Create a fully wired Next.js application from a json-render spec.\n *\n * Returns `getPageData`, `generateMetadata`, and `generateStaticParams`\n * ready to be used in Next.js `[[...slug]]` catch-all routes.\n *\n * @example\n * ```typescript\n * // lib/app.ts\n * import { createNextApp } from \"@json-render/next/server\";\n *\n * export const { getPageData, generateMetadata, generateStaticParams } =\n * createNextApp({ spec });\n *\n * // app/[[...slug]]/page.tsx (Server Component)\n * import { notFound } from \"next/navigation\";\n * import { getPageData, generateMetadata, generateStaticParams } from \"@/lib/app\";\n * import { SiteRenderer } from \"./renderer\";\n *\n * export { generateMetadata, generateStaticParams };\n *\n * export default async function Page({ params }) {\n * const data = await getPageData({ params });\n * if (!data) notFound();\n * return <SiteRenderer {...data} />;\n * }\n *\n * // app/[[...slug]]/renderer.tsx (\"use client\")\n * import { PageRenderer } from \"@json-render/next\";\n * export function SiteRenderer(props) {\n * return <PageRenderer {...props} />;\n * }\n * ```\n */\nexport function createNextApp(options: CreateNextAppOptions): NextAppExports {\n const { spec: specOrFn, loaders } = options;\n\n /**\n * Resolve page data for a given set of route params.\n * Returns null when no route matches.\n */\n async function getPageData({\n params,\n }: {\n params: Promise<{ slug?: string[] }>;\n }): Promise<PageData | null> {\n const { slug } = await params;\n const pathname = slugToPath(slug);\n const spec = await resolveSpec(specOrFn);\n\n const matched = matchRoute(spec, pathname);\n\n if (!matched) {\n return null;\n }\n\n const { route } = matched;\n\n let loaderData: Record<string, unknown> | undefined;\n if (route.loader && loaders?.[route.loader]) {\n loaderData = await loaders[route.loader]!(matched.params);\n }\n\n const initialState = mergeState(\n spec.state,\n route.page.state as Record<string, unknown> | undefined,\n loaderData,\n );\n\n const layoutSpec =\n route.layout && spec.layouts\n ? (spec.layouts[route.layout] ?? null)\n : null;\n\n return {\n spec: route.page,\n initialState:\n Object.keys(initialState).length > 0 ? initialState : undefined,\n layoutSpec,\n };\n }\n\n /**\n * Generate metadata for the matched route.\n * Merges global spec metadata with route-specific metadata.\n */\n async function generateMetadata({\n params,\n }: {\n params: Promise<{ slug?: string[] }>;\n }): Promise<ResolvedMetadata> {\n const { slug } = await params;\n const pathname = slugToPath(slug);\n const spec = await resolveSpec(specOrFn);\n const matched = matchRoute(spec, pathname);\n return resolveMetadata(spec, matched?.route ?? null);\n }\n\n /**\n * Generate static params for all statically-known routes.\n * Used by Next.js to pre-render pages at build time.\n */\n async function generateStaticParams(): Promise<{ slug: string[] }[]> {\n const spec = await resolveSpec(specOrFn);\n return collectStaticParams(spec);\n }\n\n return { getPageData, generateMetadata, generateStaticParams };\n}\n","import { defineSchema, type PromptContext } from \"@json-render/core\";\n\n/**\n * Prompt template for Next.js app generation.\n *\n * Teaches the AI to generate multi-page applications with routes,\n * layouts, metadata, and page content using JSONL patches.\n */\nfunction nextAppPromptTemplate(context: PromptContext): string {\n const { catalog, options, formatZodType } = context;\n const {\n system = \"You are a Next.js application generator.\",\n customRules = [],\n } = options;\n\n const lines: string[] = [];\n lines.push(system);\n lines.push(\"\");\n\n lines.push(\"OUTPUT FORMAT:\");\n lines.push(\n \"Output JSONL (one JSON object per line) with RFC 6902 JSON Patch operations to build a Next.js application spec.\",\n );\n lines.push(\n \"The spec defines routes (pages), layouts, metadata, and state for a full Next.js app.\",\n );\n lines.push(\"\");\n lines.push(\"Example output (each line is a separate JSON object):\");\n lines.push(\"\");\n lines.push(\n `{\"op\":\"add\",\"path\":\"/metadata\",\"value\":{\"title\":{\"default\":\"My App\",\"template\":\"%s | My App\"},\"description\":\"A full Next.js application\"}}`,\n );\n lines.push(`{\"op\":\"add\",\"path\":\"/layouts\",\"value\":{}}`);\n lines.push(\n `{\"op\":\"add\",\"path\":\"/layouts/main\",\"value\":{\"root\":\"shell\",\"elements\":{\"shell\":{\"type\":\"AppShell\",\"props\":{},\"children\":[\"nav\",\"slot\"]},\"nav\":{\"type\":\"NavBar\",\"props\":{\"links\":[{\"href\":\"/\",\"label\":\"Home\"},{\"href\":\"/about\",\"label\":\"About\"}]},\"children\":[]},\"slot\":{\"type\":\"Slot\",\"props\":{},\"children\":[]}}}}`,\n );\n lines.push(`{\"op\":\"add\",\"path\":\"/routes\",\"value\":{}}`);\n lines.push(\n `{\"op\":\"add\",\"path\":\"/routes/~1\",\"value\":{\"layout\":\"main\",\"metadata\":{\"title\":\"Home\"},\"page\":{\"root\":\"hero\",\"elements\":{\"hero\":{\"type\":\"Card\",\"props\":{\"title\":\"Welcome\"},\"children\":[]}}}}}`,\n );\n lines.push(\n `{\"op\":\"add\",\"path\":\"/routes/~1about\",\"value\":{\"layout\":\"main\",\"metadata\":{\"title\":\"About\"},\"page\":{\"root\":\"content\",\"elements\":{\"content\":{\"type\":\"Card\",\"props\":{\"title\":\"About Us\"},\"children\":[]}}}}}`,\n );\n lines.push(\"\");\n\n lines.push(\"SPEC STRUCTURE:\");\n lines.push(\"The top-level spec has these fields:\");\n lines.push(\n \" - metadata: Root-level SEO metadata (title template, description, openGraph, twitter)\",\n );\n lines.push(\n \" - layouts: Reusable layout element trees. Each layout MUST include a { type: 'Slot' } element where page content will be injected.\",\n );\n lines.push(\" - routes: Route definitions keyed by URL pattern\");\n lines.push(\" - state: Global initial state shared across all routes\");\n lines.push(\"\");\n\n lines.push(\"ROUTES:\");\n lines.push(\"Route keys use Next.js URL patterns:\");\n lines.push(\" - '/' - home page\");\n lines.push(\" - '/about' - static route\");\n lines.push(\" - '/blog/[slug]' - dynamic segment\");\n lines.push(\" - '/docs/[...path]' - catch-all segment\");\n lines.push(\" - '/settings/[[...path]]' - optional catch-all segment\");\n lines.push(\"\");\n lines.push(\n \"IMPORTANT: In JSON Patch paths, forward slashes in route keys must be escaped as ~1.\",\n );\n lines.push(\" - Route '/' becomes path '/routes/~1'\");\n lines.push(\" - Route '/about' becomes path '/routes/~1about'\");\n lines.push(\" - Route '/blog/[slug]' becomes path '/routes/~1blog~1[slug]'\");\n lines.push(\"\");\n\n lines.push(\"Each route has:\");\n lines.push(\n \" - page: Element tree (root + elements + optional state) — the page content\",\n );\n lines.push(\n \" - metadata: Per-route SEO metadata (title, description, openGraph)\",\n );\n lines.push(\" - layout: Layout key referencing an entry in the layouts map\");\n lines.push(\" - loading: Optional loading state element tree\");\n lines.push(\" - error: Optional error state element tree\");\n lines.push(\" - loader: Optional server-side data loader name\");\n lines.push(\"\");\n\n lines.push(\"LAYOUTS:\");\n lines.push(\n \"Layouts wrap page content. A layout element tree MUST include a component with type 'Slot' — this is where the page content will be rendered.\",\n );\n lines.push(\n \"Layouts are defined once and reused across routes via the layout field.\",\n );\n lines.push(\"\");\n\n lines.push(\"METADATA:\");\n lines.push(\"Root metadata sets defaults. Route metadata overrides per page.\");\n lines.push(\n \" - title: string or { default, template } (use %s for page title in template)\",\n );\n lines.push(\" - description: string\");\n lines.push(\" - openGraph: { title, description, images, type }\");\n lines.push(\" - twitter: { card, title, description }\");\n lines.push(\"\");\n\n lines.push(\"PAGE CONTENT:\");\n lines.push(\n \"Each page uses the standard json-render element tree format: root, elements, optional state.\",\n );\n lines.push(\n \"Elements have type, props, children, and optionally visible, on, repeat, watch fields.\",\n );\n lines.push(\"\");\n\n const catalogData = catalog as {\n components?: Record<\n string,\n {\n description?: string;\n props?: unknown;\n slots?: string[];\n events?: string[];\n }\n >;\n actions?: Record<string, { description?: string }>;\n };\n\n if (catalogData.components) {\n lines.push(\n `AVAILABLE COMPONENTS (${Object.keys(catalogData.components).length}):`,\n );\n lines.push(\"\");\n for (const [name, def] of Object.entries(catalogData.components)) {\n const propsStr = def.props ? formatZodType(def.props as any) : \"{}\";\n const hasChildren = def.slots && def.slots.length > 0;\n const childrenStr = hasChildren ? \" [accepts children]\" : \"\";\n const eventsStr =\n def.events && def.events.length > 0\n ? ` [events: ${def.events.join(\", \")}]`\n : \"\";\n const descStr = def.description ? ` - ${def.description}` : \"\";\n lines.push(`- ${name}: ${propsStr}${descStr}${childrenStr}${eventsStr}`);\n }\n lines.push(\"\");\n lines.push(\"Built-in components (always available):\");\n lines.push(\n \"- Slot: {} - Placeholder in layouts where page content is rendered. Required in every layout.\",\n );\n lines.push(\n \"- Link: { href: string } [accepts children] - Client-side navigation link (renders as next/link).\",\n );\n lines.push(\"\");\n }\n\n if (catalogData.actions && Object.keys(catalogData.actions).length > 0) {\n lines.push(\"AVAILABLE ACTIONS:\");\n lines.push(\"\");\n for (const [name, def] of Object.entries(catalogData.actions)) {\n lines.push(`- ${name}${def.description ? `: ${def.description}` : \"\"}`);\n }\n lines.push(\"\");\n }\n\n lines.push(\"BUILT-IN ACTIONS:\");\n lines.push(\n \"- setState: Update a value in the state model. Params: { statePath: string, value: any }\",\n );\n lines.push(\n \"- pushState: Append an item to an array in state. Params: { statePath: string, value: any, clearStatePath?: string }\",\n );\n lines.push(\n \"- removeState: Remove an item from an array by index. Params: { statePath: string, index: number }\",\n );\n lines.push(\"- navigate: Navigate to a route. Params: { href: string }\");\n lines.push(\"\");\n\n lines.push(\"RULES:\");\n const baseRules = [\n \"Output ONLY JSONL patches - one JSON object per line, no markdown, no code fences\",\n \"First add /metadata with the app-level metadata including title template\",\n \"Then add /layouts with reusable layout definitions (each must have a Slot component)\",\n \"Then add /routes with each route's page, metadata, and layout reference\",\n \"Every layout MUST include a { type: 'Slot' } element where page content is injected\",\n \"ONLY use components listed in AVAILABLE COMPONENTS (plus built-in Slot and Link)\",\n \"Each element needs: type, props, children (array of child keys)\",\n \"Use unique keys for element map entries\",\n \"Escape forward slashes in route keys as ~1 in JSON Patch paths\",\n \"Include realistic sample data in state for data-driven pages\",\n \"Use Link component for navigation between routes\",\n \"Create a cohesive multi-page app with consistent layouts and navigation\",\n ];\n const allRules = [...baseRules, ...customRules];\n allRules.forEach((rule, i) => {\n lines.push(`${i + 1}. ${rule}`);\n });\n\n return lines.join(\"\\n\");\n}\n\n/**\n * The schema for @json-render/next.\n *\n * Defines a multi-page Next.js application structure:\n * - Spec: Routes with pages, layouts, metadata, loading/error states\n * - Catalog: Components with props schemas, and optional actions\n *\n * This schema is fundamentally different from the React element tree schema.\n * It's page-based, designed for full Next.js applications with SSR,\n * routing, and metadata generation.\n */\nexport const schema = defineSchema(\n (s) => ({\n spec: s.object({\n /** Root-level metadata applied as defaults */\n metadata: s.object({\n title: s.any(),\n description: s.string(),\n keywords: s.array(s.string()),\n openGraph: s.any(),\n twitter: s.any(),\n robots: s.any(),\n icons: s.any(),\n }),\n\n /** Route definitions keyed by URL pattern */\n routes: s.record(\n s.object({\n /** Page element tree */\n page: s.object({\n root: s.string(),\n elements: s.record(\n s.object({\n type: s.ref(\"catalog.components\"),\n props: s.propsOf(\"catalog.components\"),\n children: s.array(s.string()),\n visible: s.any(),\n }),\n ),\n state: s.any(),\n }),\n /** Per-route metadata */\n metadata: s.any(),\n /** Layout key */\n layout: s.string(),\n /** Loading state element tree */\n loading: s.any(),\n /** Error state element tree */\n error: s.any(),\n /** Not-found element tree */\n notFound: s.any(),\n /** Server-side data loader name */\n loader: s.string(),\n /** Static params for SSG */\n staticParams: s.any(),\n }),\n ),\n\n /** Reusable layout element trees */\n layouts: s.record(\n s.object({\n root: s.string(),\n elements: s.record(\n s.object({\n type: s.ref(\"catalog.components\"),\n props: s.propsOf(\"catalog.components\"),\n children: s.array(s.string()),\n visible: s.any(),\n }),\n ),\n state: s.any(),\n }),\n ),\n\n /** Global initial state */\n state: s.any(),\n }),\n\n catalog: s.object({\n /** Component definitions */\n components: s.map({\n props: s.zod(),\n slots: s.array(s.string()),\n description: s.string(),\n example: s.any(),\n }),\n /** Action definitions (optional) */\n actions: s.map({\n params: s.zod(),\n description: s.string(),\n }),\n }),\n }),\n {\n promptTemplate: nextAppPromptTemplate,\n builtInActions: [\n {\n name: \"setState\",\n description:\n \"Update a value in the state model at the given statePath. Params: { statePath: string, value: any }\",\n },\n {\n name: \"pushState\",\n description:\n 'Append an item to an array in state. Params: { statePath: string, value: any, clearStatePath?: string }. Value can contain {\"$state\":\"/path\"} refs and \"$id\" for auto IDs.',\n },\n {\n name: \"removeState\",\n description:\n \"Remove an item from an array in state by index. Params: { statePath: string, index: number }\",\n },\n {\n name: \"navigate\",\n description:\n \"Navigate to a route within the app. Params: { href: string }\",\n },\n ],\n },\n);\n\n/**\n * Type for the Next.js schema\n */\nexport type NextSchema = typeof schema;\n\n/**\n * Infer the spec type from a catalog\n */\nexport type NextSpec<TCatalog> = typeof schema extends {\n createCatalog: (catalog: TCatalog) => { _specType: infer S };\n}\n ? S\n : never;\n"],"mappings":"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","names":[]}
|