@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.
@@ -0,0 +1,358 @@
1
+ import * as _json_render_core from '@json-render/core';
2
+ import { Spec } from '@json-render/core';
3
+ export { Spec, StateStore } from '@json-render/core';
4
+ export { ActionFn, Actions, BaseComponentProps, ComponentContext, ComponentFn, Components, EventHandle, SetState, StateModel } from '@json-render/react';
5
+
6
+ /**
7
+ * Metadata for Next.js pages and layouts.
8
+ * Maps to Next.js's Metadata type.
9
+ */
10
+ interface NextMetadata {
11
+ /** Page title — string or template config */
12
+ title?: string | {
13
+ /** Default title when no child overrides */
14
+ default: string;
15
+ /** Template string, use %s for the page title (e.g. "%s | My App") */
16
+ template?: string;
17
+ /** Absolute title that ignores parent templates */
18
+ absolute?: string;
19
+ };
20
+ /** Meta description */
21
+ description?: string;
22
+ /** Keywords for SEO */
23
+ keywords?: string[];
24
+ /** Open Graph metadata */
25
+ openGraph?: {
26
+ title?: string;
27
+ description?: string;
28
+ images?: string | string[];
29
+ type?: string;
30
+ url?: string;
31
+ siteName?: string;
32
+ locale?: string;
33
+ };
34
+ /** Twitter card metadata */
35
+ twitter?: {
36
+ card?: "summary" | "summary_large_image" | "app" | "player";
37
+ title?: string;
38
+ description?: string;
39
+ images?: string | string[];
40
+ creator?: string;
41
+ site?: string;
42
+ };
43
+ /** Robots directives */
44
+ robots?: string | {
45
+ index?: boolean;
46
+ follow?: boolean;
47
+ };
48
+ /** Canonical URL */
49
+ alternates?: {
50
+ canonical?: string;
51
+ };
52
+ /** Favicon and icons */
53
+ icons?: string | {
54
+ icon?: string;
55
+ apple?: string;
56
+ shortcut?: string;
57
+ };
58
+ }
59
+ /**
60
+ * A route definition within a NextAppSpec.
61
+ */
62
+ interface NextRouteSpec {
63
+ /** Page content — standard json-render element tree */
64
+ page: Spec;
65
+ /** Per-route metadata for SEO */
66
+ metadata?: NextMetadata;
67
+ /** Layout key referencing an entry in NextAppSpec.layouts */
68
+ layout?: string;
69
+ /** Loading state element tree (rendered during Suspense) */
70
+ loading?: Spec;
71
+ /** Error state element tree */
72
+ error?: Spec;
73
+ /** Not-found element tree (for dynamic routes that don't match data) */
74
+ notFound?: Spec;
75
+ /** Server-side data loader name (references loaders in createNextApp) */
76
+ loader?: string;
77
+ /** Static params for generateStaticParams */
78
+ staticParams?: Record<string, string>[];
79
+ }
80
+ /**
81
+ * The full application spec for @json-render/next.
82
+ *
83
+ * Describes an entire Next.js application: routes, pages, layouts,
84
+ * metadata, and server-side data loading.
85
+ *
86
+ * Routes are keyed by URL patterns using Next.js conventions:
87
+ * - `"/"` — exact match
88
+ * - `"/blog/[slug]"` — dynamic segment
89
+ * - `"/docs/[...path]"` — catch-all segment
90
+ * - `"/settings/[[...path]]"` — optional catch-all segment
91
+ */
92
+ interface NextAppSpec {
93
+ /** Root-level metadata applied to all routes (layouts can override) */
94
+ metadata?: NextMetadata;
95
+ /** Route definitions keyed by URL pattern */
96
+ routes: Record<string, NextRouteSpec>;
97
+ /**
98
+ * Reusable layout element trees. Each layout spec must include a
99
+ * `Slot` component type where page content will be injected.
100
+ */
101
+ layouts?: Record<string, Spec>;
102
+ /** Global initial state shared across all routes */
103
+ state?: Record<string, unknown>;
104
+ }
105
+ /**
106
+ * Result of matching a pathname against the spec's routes.
107
+ */
108
+ interface MatchedRoute {
109
+ /** The matched route spec */
110
+ route: NextRouteSpec;
111
+ /** The URL pattern that matched (e.g. "/blog/[slug]") */
112
+ pattern: string;
113
+ /** Extracted route parameters (e.g. { slug: "hello-world" }) */
114
+ params: Record<string, string | string[]>;
115
+ }
116
+ /**
117
+ * Server-side data loader function signature.
118
+ * Receives route params and returns data to merge into initial state.
119
+ */
120
+ type LoaderFn = (params: Record<string, string | string[]>) => Promise<Record<string, unknown>> | Record<string, unknown>;
121
+ /**
122
+ * Options for createNextApp.
123
+ */
124
+ interface CreateNextAppOptions {
125
+ /** The application spec */
126
+ spec: NextAppSpec | (() => NextAppSpec | Promise<NextAppSpec>);
127
+ /** Server-side data loaders keyed by name */
128
+ loaders?: Record<string, LoaderFn>;
129
+ }
130
+ /**
131
+ * Data returned by getPageData for client-side rendering.
132
+ */
133
+ interface PageData {
134
+ /** Page element tree spec */
135
+ spec: Spec;
136
+ /** Initial state (merged from spec.state, global state, and loader data) */
137
+ initialState?: Record<string, unknown>;
138
+ /** Optional layout element tree spec */
139
+ layoutSpec?: Spec | null;
140
+ }
141
+ /**
142
+ * The result of createNextApp — exports for Next.js route files.
143
+ */
144
+ interface NextAppExports {
145
+ /**
146
+ * Resolve page data for a given set of params.
147
+ * Returns null if no route matches (caller should call notFound()).
148
+ *
149
+ * Use this in your Server Component page.tsx alongside a client wrapper
150
+ * that renders PageRenderer:
151
+ *
152
+ * ```tsx
153
+ * // app/[[...slug]]/page.tsx
154
+ * import { getPageData, generateMetadata, generateStaticParams } from "@/lib/app";
155
+ * import { WebsiteRenderer } from "./renderer";
156
+ *
157
+ * export { generateMetadata, generateStaticParams };
158
+ *
159
+ * export default async function Page({ params }) {
160
+ * const data = await getPageData({ params });
161
+ * if (!data) notFound();
162
+ * return <WebsiteRenderer {...data} />;
163
+ * }
164
+ * ```
165
+ */
166
+ getPageData: (props: {
167
+ params: Promise<{
168
+ slug?: string[];
169
+ }>;
170
+ }) => Promise<PageData | null>;
171
+ /** generateMetadata function for page.tsx */
172
+ generateMetadata: (props: {
173
+ params: Promise<{
174
+ slug?: string[];
175
+ }>;
176
+ }) => Promise<Record<string, unknown>>;
177
+ /** generateStaticParams function for page.tsx */
178
+ generateStaticParams: () => Promise<{
179
+ slug: string[];
180
+ }[]>;
181
+ }
182
+
183
+ /**
184
+ * Create a fully wired Next.js application from a json-render spec.
185
+ *
186
+ * Returns `getPageData`, `generateMetadata`, and `generateStaticParams`
187
+ * ready to be used in Next.js `[[...slug]]` catch-all routes.
188
+ *
189
+ * @example
190
+ * ```typescript
191
+ * // lib/app.ts
192
+ * import { createNextApp } from "@json-render/next/server";
193
+ *
194
+ * export const { getPageData, generateMetadata, generateStaticParams } =
195
+ * createNextApp({ spec });
196
+ *
197
+ * // app/[[...slug]]/page.tsx (Server Component)
198
+ * import { notFound } from "next/navigation";
199
+ * import { getPageData, generateMetadata, generateStaticParams } from "@/lib/app";
200
+ * import { SiteRenderer } from "./renderer";
201
+ *
202
+ * export { generateMetadata, generateStaticParams };
203
+ *
204
+ * export default async function Page({ params }) {
205
+ * const data = await getPageData({ params });
206
+ * if (!data) notFound();
207
+ * return <SiteRenderer {...data} />;
208
+ * }
209
+ *
210
+ * // app/[[...slug]]/renderer.tsx ("use client")
211
+ * import { PageRenderer } from "@json-render/next";
212
+ * export function SiteRenderer(props) {
213
+ * return <PageRenderer {...props} />;
214
+ * }
215
+ * ```
216
+ */
217
+ declare function createNextApp(options: CreateNextAppOptions): NextAppExports;
218
+
219
+ /**
220
+ * The schema for @json-render/next.
221
+ *
222
+ * Defines a multi-page Next.js application structure:
223
+ * - Spec: Routes with pages, layouts, metadata, loading/error states
224
+ * - Catalog: Components with props schemas, and optional actions
225
+ *
226
+ * This schema is fundamentally different from the React element tree schema.
227
+ * It's page-based, designed for full Next.js applications with SSR,
228
+ * routing, and metadata generation.
229
+ */
230
+ declare const schema: _json_render_core.Schema<{
231
+ spec: _json_render_core.SchemaType<"object", {
232
+ /** Root-level metadata applied as defaults */
233
+ metadata: _json_render_core.SchemaType<"object", {
234
+ title: _json_render_core.SchemaType<"any", unknown>;
235
+ description: _json_render_core.SchemaType<"string", unknown>;
236
+ keywords: _json_render_core.SchemaType<"array", _json_render_core.SchemaType<"string", unknown>>;
237
+ openGraph: _json_render_core.SchemaType<"any", unknown>;
238
+ twitter: _json_render_core.SchemaType<"any", unknown>;
239
+ robots: _json_render_core.SchemaType<"any", unknown>;
240
+ icons: _json_render_core.SchemaType<"any", unknown>;
241
+ }>;
242
+ /** Route definitions keyed by URL pattern */
243
+ routes: _json_render_core.SchemaType<"record", _json_render_core.SchemaType<"object", {
244
+ /** Page element tree */
245
+ page: _json_render_core.SchemaType<"object", {
246
+ root: _json_render_core.SchemaType<"string", unknown>;
247
+ elements: _json_render_core.SchemaType<"record", _json_render_core.SchemaType<"object", {
248
+ type: _json_render_core.SchemaType<"ref", string>;
249
+ props: _json_render_core.SchemaType<"propsOf", string>;
250
+ children: _json_render_core.SchemaType<"array", _json_render_core.SchemaType<"string", unknown>>;
251
+ visible: _json_render_core.SchemaType<"any", unknown>;
252
+ }>>;
253
+ state: _json_render_core.SchemaType<"any", unknown>;
254
+ }>;
255
+ /** Per-route metadata */
256
+ metadata: _json_render_core.SchemaType<"any", unknown>;
257
+ /** Layout key */
258
+ layout: _json_render_core.SchemaType<"string", unknown>;
259
+ /** Loading state element tree */
260
+ loading: _json_render_core.SchemaType<"any", unknown>;
261
+ /** Error state element tree */
262
+ error: _json_render_core.SchemaType<"any", unknown>;
263
+ /** Not-found element tree */
264
+ notFound: _json_render_core.SchemaType<"any", unknown>;
265
+ /** Server-side data loader name */
266
+ loader: _json_render_core.SchemaType<"string", unknown>;
267
+ /** Static params for SSG */
268
+ staticParams: _json_render_core.SchemaType<"any", unknown>;
269
+ }>>;
270
+ /** Reusable layout element trees */
271
+ layouts: _json_render_core.SchemaType<"record", _json_render_core.SchemaType<"object", {
272
+ root: _json_render_core.SchemaType<"string", unknown>;
273
+ elements: _json_render_core.SchemaType<"record", _json_render_core.SchemaType<"object", {
274
+ type: _json_render_core.SchemaType<"ref", string>;
275
+ props: _json_render_core.SchemaType<"propsOf", string>;
276
+ children: _json_render_core.SchemaType<"array", _json_render_core.SchemaType<"string", unknown>>;
277
+ visible: _json_render_core.SchemaType<"any", unknown>;
278
+ }>>;
279
+ state: _json_render_core.SchemaType<"any", unknown>;
280
+ }>>;
281
+ /** Global initial state */
282
+ state: _json_render_core.SchemaType<"any", unknown>;
283
+ }>;
284
+ catalog: _json_render_core.SchemaType<"object", {
285
+ /** Component definitions */
286
+ components: _json_render_core.SchemaType<"map", {
287
+ props: _json_render_core.SchemaType<"zod", unknown>;
288
+ slots: _json_render_core.SchemaType<"array", _json_render_core.SchemaType<"string", unknown>>;
289
+ description: _json_render_core.SchemaType<"string", unknown>;
290
+ example: _json_render_core.SchemaType<"any", unknown>;
291
+ }>;
292
+ /** Action definitions (optional) */
293
+ actions: _json_render_core.SchemaType<"map", {
294
+ params: _json_render_core.SchemaType<"zod", unknown>;
295
+ description: _json_render_core.SchemaType<"string", unknown>;
296
+ }>;
297
+ }>;
298
+ }>;
299
+ /**
300
+ * Type for the Next.js schema
301
+ */
302
+ type NextSchema = typeof schema;
303
+ /**
304
+ * Infer the spec type from a catalog
305
+ */
306
+ type NextSpec<TCatalog> = typeof schema extends {
307
+ createCatalog: (catalog: TCatalog) => {
308
+ _specType: infer S;
309
+ };
310
+ } ? S : never;
311
+
312
+ /**
313
+ * Match a pathname against a spec's routes.
314
+ *
315
+ * Routes are matched in order of specificity:
316
+ * 1. Exact/static matches first (most specific)
317
+ * 2. Dynamic segment matches
318
+ * 3. Catch-all matches (least specific)
319
+ * 4. Optional catch-all matches (fallback)
320
+ *
321
+ * @returns The matched route with extracted params, or null if no match.
322
+ */
323
+ declare function matchRoute(spec: NextAppSpec, pathname: string): MatchedRoute | null;
324
+ /**
325
+ * Convert a Next.js catch-all slug array to a pathname.
326
+ *
327
+ * @example
328
+ * slugToPath(undefined) // "/"
329
+ * slugToPath([]) // "/"
330
+ * slugToPath(["blog"]) // "/blog"
331
+ * slugToPath(["blog","hi"]) // "/blog/hi"
332
+ */
333
+ declare function slugToPath(slug: string[] | undefined): string;
334
+ /**
335
+ * Collect all static params from the spec for generateStaticParams.
336
+ * Returns params suitable for Next.js [[...slug]] catch-all routes.
337
+ */
338
+ declare function collectStaticParams(spec: NextAppSpec): {
339
+ slug: string[];
340
+ }[];
341
+
342
+ /**
343
+ * Metadata result compatible with Next.js's Metadata type.
344
+ * Uses plain objects to avoid importing Next.js types at runtime.
345
+ */
346
+ type ResolvedMetadata = Record<string, unknown>;
347
+ /**
348
+ * Resolve metadata for a route by merging global spec metadata
349
+ * with route-specific metadata.
350
+ *
351
+ * Follows Next.js metadata merging semantics:
352
+ * - Route metadata overrides global metadata for scalar fields
353
+ * - Title templates from global metadata apply to route titles
354
+ * - OpenGraph and Twitter fields are shallow-merged
355
+ */
356
+ declare function resolveMetadata(spec: NextAppSpec, route?: NextRouteSpec | null): ResolvedMetadata;
357
+
358
+ export { type CreateNextAppOptions, type LoaderFn, type MatchedRoute, type NextAppExports, type NextAppSpec, type NextMetadata, type NextRouteSpec, type NextSchema, type NextSpec, type PageData, type ResolvedMetadata, collectStaticParams, createNextApp, matchRoute, resolveMetadata, schema, slugToPath };