@sprintup-cms/sdk 1.0.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,557 @@
1
+ 'use strict';
2
+
3
+ var server = require('next/server');
4
+ var cache = require('next/cache');
5
+ var headers = require('next/headers');
6
+ var navigation = require('next/navigation');
7
+ var React = require('react');
8
+ var jsxRuntime = require('react/jsx-runtime');
9
+
10
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
+
12
+ var React__default = /*#__PURE__*/_interopDefault(React);
13
+
14
+ /* @sprintup-cms/sdk — https://forgecms.io */
15
+
16
+ function createRevalidateHandler(options) {
17
+ return async function POST2(request) {
18
+ try {
19
+ const secret = options?.secret ?? process.env.CMS_WEBHOOK_SECRET;
20
+ const incomingSecret = request.headers.get("x-cms-webhook-secret");
21
+ if (secret && incomingSecret !== secret) {
22
+ return server.NextResponse.json({ error: "Unauthorized" }, { status: 401 });
23
+ }
24
+ const body = await request.json();
25
+ const { slug, tag } = body;
26
+ if (!slug) {
27
+ return server.NextResponse.json({ error: "Missing slug in payload" }, { status: 400 });
28
+ }
29
+ cache.revalidatePath(`/${slug}`);
30
+ cache.revalidateTag(`cms-page-${slug}`);
31
+ cache.revalidateTag("cms-pages");
32
+ if (tag) cache.revalidateTag(tag);
33
+ if (body.event === "published" || body.tag?.startsWith("site-structure")) {
34
+ cache.revalidatePath("/", "layout");
35
+ }
36
+ await options?.onRevalidate?.(body);
37
+ return server.NextResponse.json({
38
+ revalidated: true,
39
+ slug,
40
+ event: body.event,
41
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
42
+ });
43
+ } catch (err) {
44
+ console.error("[sprintup-cms] revalidate error:", err);
45
+ return server.NextResponse.json({ error: err.message }, { status: 500 });
46
+ }
47
+ };
48
+ }
49
+ var POST = createRevalidateHandler();
50
+ function createPreviewExitHandler(options) {
51
+ return async function GET2(request) {
52
+ const draft = await headers.draftMode();
53
+ draft.disable();
54
+ const cookieStore = await headers.cookies();
55
+ cookieStore.delete("cms_preview_token");
56
+ cookieStore.delete("cms_preview_content_id");
57
+ const redirectTo = options?.redirectTo ?? "/";
58
+ const url = new URL(request.url);
59
+ return server.NextResponse.redirect(new URL(redirectTo, url.origin));
60
+ };
61
+ }
62
+ var GET = createPreviewExitHandler();
63
+
64
+ // src/client.ts
65
+ function createCMSClient(options) {
66
+ function cfg() {
67
+ return {
68
+ baseUrl: (process.env.NEXT_PUBLIC_CMS_URL ?? process.env.CMS_BASE_URL ?? "").replace(/\/$/, ""),
69
+ apiKey: process.env.CMS_API_KEY ?? "",
70
+ appId: process.env.CMS_APP_ID ?? ""
71
+ };
72
+ }
73
+ function headers() {
74
+ return { "X-CMS-API-Key": cfg().apiKey, "Content-Type": "application/json" };
75
+ }
76
+ async function getPages(params) {
77
+ const { baseUrl, apiKey, appId } = cfg();
78
+ if (!baseUrl || !apiKey || !appId) {
79
+ console.warn("[sprintup-cms] Missing CMS_BASE_URL / CMS_API_KEY / CMS_APP_ID \u2014 returning []");
80
+ return [];
81
+ }
82
+ try {
83
+ const qs = new URLSearchParams();
84
+ if (params?.type) qs.set("type", params.type);
85
+ if (params?.group) qs.set("group", params.group);
86
+ if (params?.page) qs.set("page", String(params.page));
87
+ if (params?.perPage) qs.set("perPage", String(params.perPage));
88
+ const url = `${baseUrl}/api/v1/${appId}/pages${qs.size ? `?${qs}` : ""}`;
89
+ const res = await fetch(url, {
90
+ headers: headers(),
91
+ next: { revalidate: 60, tags: [`cms-pages-${appId}`] }
92
+ });
93
+ if (!res.ok) {
94
+ console.error(`[sprintup-cms] getPages (${res.status})`);
95
+ return [];
96
+ }
97
+ const json = await res.json();
98
+ return json.data ?? [];
99
+ } catch (err) {
100
+ console.error("[sprintup-cms] getPages error:", err);
101
+ return [];
102
+ }
103
+ }
104
+ async function getPage(slug) {
105
+ const { baseUrl, apiKey, appId } = cfg();
106
+ if (!baseUrl || !apiKey || !appId) {
107
+ console.warn("[sprintup-cms] Missing config \u2014 returning null");
108
+ return null;
109
+ }
110
+ try {
111
+ const res = await fetch(`${baseUrl}/api/v1/${appId}/pages/${slug}`, {
112
+ headers: headers(),
113
+ next: { revalidate: 60, tags: [`cms-page-${slug}`, `cms-pages-${appId}`] }
114
+ });
115
+ if (res.status === 404) return null;
116
+ if (!res.ok) {
117
+ console.error(`[sprintup-cms] getPage "${slug}" (${res.status})`);
118
+ return null;
119
+ }
120
+ const json = await res.json();
121
+ return json.data ?? null;
122
+ } catch (err) {
123
+ console.error(`[sprintup-cms] getPage "${slug}" error:`, err);
124
+ return null;
125
+ }
126
+ }
127
+ async function getBlogPosts() {
128
+ return getPages({ type: "blog-post" });
129
+ }
130
+ async function getEvents() {
131
+ return getPages({ type: "event-page" });
132
+ }
133
+ async function getAnnouncements() {
134
+ return getPages({ type: "announcement-page" });
135
+ }
136
+ async function getPreviewPage(token) {
137
+ const { baseUrl, appId } = cfg();
138
+ if (!baseUrl || !appId) return null;
139
+ try {
140
+ const res = await fetch(`${baseUrl}/api/v1/${appId}/preview?token=${encodeURIComponent(token)}`, {
141
+ cache: "no-store"
142
+ });
143
+ if (!res.ok) return null;
144
+ const json = await res.json();
145
+ return json.data ?? null;
146
+ } catch {
147
+ return null;
148
+ }
149
+ }
150
+ async function getPageWithPreview(slug, previewToken) {
151
+ if (previewToken) {
152
+ const preview = await getPreviewPage(previewToken);
153
+ if (preview?.slug === slug) return preview;
154
+ }
155
+ return getPage(slug);
156
+ }
157
+ async function getPageType(pageTypeId) {
158
+ const { baseUrl, apiKey, appId } = cfg();
159
+ if (!baseUrl || !apiKey || !appId || !pageTypeId) return null;
160
+ try {
161
+ const res = await fetch(`${baseUrl}/api/v1/${appId}/page-types/${pageTypeId}`, {
162
+ headers: headers(),
163
+ next: { revalidate: 3600, tags: [`cms-page-type-${pageTypeId}`] }
164
+ });
165
+ if (!res.ok) return null;
166
+ const json = await res.json();
167
+ return json.data ?? null;
168
+ } catch {
169
+ return null;
170
+ }
171
+ }
172
+ async function getPageTypes() {
173
+ const { baseUrl, apiKey, appId } = cfg();
174
+ if (!baseUrl || !apiKey || !appId) return [];
175
+ try {
176
+ const res = await fetch(`${baseUrl}/api/v1/${appId}/page-types`, {
177
+ headers: headers(),
178
+ next: { revalidate: 3600, tags: [`cms-page-types-${appId}`] }
179
+ });
180
+ if (!res.ok) return [];
181
+ const json = await res.json();
182
+ return json.data ?? [];
183
+ } catch {
184
+ return [];
185
+ }
186
+ }
187
+ async function getSiteStructure() {
188
+ const { baseUrl, apiKey, appId } = cfg();
189
+ if (!baseUrl || !apiKey || !appId) return null;
190
+ try {
191
+ const res = await fetch(`${baseUrl}/api/v1/${appId}/site-structure`, {
192
+ headers: headers(),
193
+ next: {
194
+ revalidate: 300,
195
+ tags: [`site-structure-${appId}`]
196
+ }
197
+ });
198
+ if (!res.ok) return null;
199
+ const json = await res.json();
200
+ return json.data ?? null;
201
+ } catch {
202
+ return null;
203
+ }
204
+ }
205
+ return {
206
+ getPages,
207
+ getPage,
208
+ getBlogPosts,
209
+ getEvents,
210
+ getAnnouncements,
211
+ getPreviewPage,
212
+ getPageWithPreview,
213
+ getPageType,
214
+ getPageTypes,
215
+ getSiteStructure
216
+ };
217
+ }
218
+ function getData(block) {
219
+ return block.data ?? block.content ?? {};
220
+ }
221
+ function HeadingBlock({ block }) {
222
+ const d = getData(block);
223
+ const text = d.text || d.heading || d.title || "";
224
+ const level = Number(d.level) || 2;
225
+ const cls = {
226
+ 1: "text-4xl font-bold tracking-tight",
227
+ 2: "text-2xl font-bold mt-8",
228
+ 3: "text-xl font-semibold mt-6",
229
+ 4: "text-lg font-medium mt-4"
230
+ }[level] ?? "text-2xl font-bold";
231
+ return React__default.default.createElement(`h${level}`, { className: cls }, text);
232
+ }
233
+ function TextBlock({ block }) {
234
+ const d = getData(block);
235
+ return /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-base leading-relaxed text-muted-foreground", children: d.text || d.content || "" });
236
+ }
237
+ function RichTextBlock({ block }) {
238
+ const d = getData(block);
239
+ const html = d.content || d.richtext || d.text || "";
240
+ if (!html) return null;
241
+ return /* @__PURE__ */ jsxRuntime.jsx(
242
+ "div",
243
+ {
244
+ className: "prose prose-neutral dark:prose-invert max-w-none",
245
+ dangerouslySetInnerHTML: { __html: html }
246
+ }
247
+ );
248
+ }
249
+ function ImageBlock({ block }) {
250
+ const d = getData(block);
251
+ const src = d.src || d.url || d.image || "";
252
+ if (!src) return null;
253
+ return /* @__PURE__ */ jsxRuntime.jsxs("figure", { className: "my-6", children: [
254
+ /* @__PURE__ */ jsxRuntime.jsx("img", { src, alt: d.alt || "", className: "w-full rounded-lg border object-cover" }),
255
+ d.caption && /* @__PURE__ */ jsxRuntime.jsx("figcaption", { className: "mt-2 text-sm text-muted-foreground text-center", children: d.caption })
256
+ ] });
257
+ }
258
+ function HeroBlock({ block }) {
259
+ const d = getData(block);
260
+ return /* @__PURE__ */ jsxRuntime.jsx("section", { className: "py-12 md:py-20", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-3xl", children: [
261
+ d.badge && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-block px-3 py-1 text-xs font-semibold rounded-full bg-secondary text-secondary-foreground mb-4", children: d.badge }),
262
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-4xl md:text-5xl font-bold tracking-tight mb-4 text-balance", children: d.title }),
263
+ d.subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xl text-muted-foreground mb-8", children: d.subtitle }),
264
+ (d.primaryButton || d.cta) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-4 flex-wrap", children: [
265
+ (d.primaryButton || d.cta) && /* @__PURE__ */ jsxRuntime.jsx(
266
+ "a",
267
+ {
268
+ href: d.primaryUrl || d.ctaUrl || "#",
269
+ className: "inline-flex items-center px-6 py-3 rounded-lg bg-primary text-primary-foreground font-semibold hover:opacity-90 transition-opacity",
270
+ children: d.primaryButton || d.cta
271
+ }
272
+ ),
273
+ d.secondaryButton && /* @__PURE__ */ jsxRuntime.jsx(
274
+ "a",
275
+ {
276
+ href: d.secondaryUrl || "#",
277
+ className: "inline-flex items-center px-6 py-3 rounded-lg border border-border font-semibold hover:bg-muted transition-colors",
278
+ children: d.secondaryButton
279
+ }
280
+ )
281
+ ] })
282
+ ] }) });
283
+ }
284
+ function CTABlock({ block }) {
285
+ const d = getData(block);
286
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "py-12 px-8 rounded-xl bg-primary text-primary-foreground text-center", children: [
287
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-2xl md:text-3xl font-bold mb-4", children: d.title }),
288
+ d.subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-primary-foreground/80 mb-6 max-w-2xl mx-auto", children: d.subtitle }),
289
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-4 justify-center flex-wrap", children: [
290
+ d.primaryButton && /* @__PURE__ */ jsxRuntime.jsx(
291
+ "a",
292
+ {
293
+ href: d.primaryUrl || "#",
294
+ className: "px-6 py-3 rounded-lg bg-background text-foreground font-semibold hover:opacity-90 transition-opacity",
295
+ children: d.primaryButton
296
+ }
297
+ ),
298
+ d.secondaryButton && /* @__PURE__ */ jsxRuntime.jsx(
299
+ "a",
300
+ {
301
+ href: d.secondaryUrl || "#",
302
+ className: "px-6 py-3 rounded-lg border border-primary-foreground/20 text-primary-foreground font-semibold hover:bg-primary-foreground/10 transition-colors",
303
+ children: d.secondaryButton
304
+ }
305
+ )
306
+ ] })
307
+ ] });
308
+ }
309
+ function FAQBlock({ block }) {
310
+ const d = getData(block);
311
+ const items = d.items || [];
312
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "py-8", children: [
313
+ d.title && /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-2xl font-bold mb-6", children: d.title }),
314
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-4", children: items.map((item, i) => /* @__PURE__ */ jsxRuntime.jsxs("details", { className: "group border border-border rounded-lg", children: [
315
+ /* @__PURE__ */ jsxRuntime.jsxs("summary", { className: "flex items-center justify-between p-4 cursor-pointer font-medium select-none", children: [
316
+ item.question,
317
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "transition-transform group-open:rotate-45 text-lg leading-none", children: "+" })
318
+ ] }),
319
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 pb-4 text-muted-foreground", children: item.answer })
320
+ ] }, i)) })
321
+ ] });
322
+ }
323
+ function StatsBlock({ block }) {
324
+ const d = getData(block);
325
+ const items = d.items || d.stats || [];
326
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "py-8", children: [
327
+ d.title && /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-2xl font-bold mb-6 text-center", children: d.title }),
328
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `grid gap-6 grid-cols-2 md:grid-cols-${Math.min(items.length, 4)}`, children: items.map((s, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center p-6 rounded-lg border bg-card", children: [
329
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-3xl font-bold text-primary", children: s.value }),
330
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-muted-foreground mt-1", children: s.label })
331
+ ] }, i)) })
332
+ ] });
333
+ }
334
+ function TestimonialBlock({ block }) {
335
+ const d = getData(block);
336
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border border-border rounded-xl p-6 bg-card", children: [
337
+ /* @__PURE__ */ jsxRuntime.jsxs("blockquote", { className: "text-lg italic mb-4 text-foreground", children: [
338
+ '"',
339
+ d.quote,
340
+ '"'
341
+ ] }),
342
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
343
+ d.avatar && /* @__PURE__ */ jsxRuntime.jsx("img", { src: d.avatar, alt: "", className: "w-10 h-10 rounded-full object-cover" }),
344
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
345
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-semibold", children: d.author }),
346
+ d.role && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-muted-foreground", children: d.role })
347
+ ] })
348
+ ] })
349
+ ] });
350
+ }
351
+ function QuoteBlock({ block }) {
352
+ const d = getData(block);
353
+ return /* @__PURE__ */ jsxRuntime.jsxs("blockquote", { className: "border-l-4 border-primary pl-6 py-2 italic text-lg", children: [
354
+ d.text,
355
+ d.author && /* @__PURE__ */ jsxRuntime.jsxs("footer", { className: "mt-2 text-sm text-muted-foreground not-italic", children: [
356
+ "\u2014 ",
357
+ d.author
358
+ ] })
359
+ ] });
360
+ }
361
+ function AlertBlock({ block }) {
362
+ const d = getData(block);
363
+ const colors = {
364
+ info: "bg-blue-50 border-blue-200 text-blue-800 dark:bg-blue-950 dark:border-blue-800 dark:text-blue-200",
365
+ success: "bg-green-50 border-green-200 text-green-800 dark:bg-green-950 dark:border-green-800 dark:text-green-200",
366
+ warning: "bg-yellow-50 border-yellow-200 text-yellow-800 dark:bg-yellow-950 dark:border-yellow-800 dark:text-yellow-200",
367
+ error: "bg-red-50 border-red-200 text-red-800 dark:bg-red-950 dark:border-red-800 dark:text-red-200"
368
+ };
369
+ const variant = d.variant || d.type || "info";
370
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `p-4 rounded-lg border ${colors[variant] ?? colors.info}`, children: [
371
+ d.title && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-semibold mb-1", children: d.title }),
372
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: d.message || d.text || "" })
373
+ ] });
374
+ }
375
+ function DividerBlock() {
376
+ return /* @__PURE__ */ jsxRuntime.jsx("hr", { className: "my-8 border-border" });
377
+ }
378
+ function SpacerBlock({ block }) {
379
+ const d = getData(block);
380
+ const sizes = { sm: "h-4", md: "h-8", lg: "h-16", xl: "h-24" };
381
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: sizes[d.size] ?? "h-8" });
382
+ }
383
+ function VideoBlock({ block }) {
384
+ const d = getData(block);
385
+ const url = d.url || d.embed || "";
386
+ if (!url) return null;
387
+ const embedUrl = url.replace("youtube.com/watch?v=", "youtube.com/embed/").replace("youtu.be/", "youtube.com/embed/").replace("vimeo.com/", "player.vimeo.com/video/");
388
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "aspect-video rounded-lg overflow-hidden border bg-muted", children: /* @__PURE__ */ jsxRuntime.jsx("iframe", { src: embedUrl, allow: "autoplay; fullscreen", allowFullScreen: true, className: "w-full h-full", title: d.title || "Video" }) });
389
+ }
390
+ function SectionBlock({ block, pageType }) {
391
+ const d = getData(block);
392
+ const section = pageType?.sections.find((s) => s.name === block.type);
393
+ if (section) {
394
+ const filledFields = section.fields.filter((f) => d[f.name] !== void 0 && d[f.name] !== "" && d[f.name] !== null);
395
+ if (filledFields.length === 0) return null;
396
+ return /* @__PURE__ */ jsxRuntime.jsx("section", { className: "py-4 space-y-4 border-b border-border last:border-0", children: filledFields.map((field) => {
397
+ const value = d[field.name];
398
+ if (!value && value !== 0 && value !== false) return null;
399
+ if (field.fieldType === "richtext") {
400
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
401
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wide mb-1", children: field.label }),
402
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "prose prose-neutral dark:prose-invert max-w-none text-sm", dangerouslySetInnerHTML: { __html: String(value) } })
403
+ ] }, field.id);
404
+ }
405
+ if (field.fieldType === "image") {
406
+ return /* @__PURE__ */ jsxRuntime.jsx("figure", { children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: String(value), alt: field.label, className: "rounded-lg border max-h-96 object-cover" }) }, field.id);
407
+ }
408
+ if (field.fieldType === "boolean") {
409
+ return /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm", children: [
410
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-medium", children: [
411
+ field.label,
412
+ ":"
413
+ ] }),
414
+ " ",
415
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: value ? "Yes" : "No" })
416
+ ] }, field.id);
417
+ }
418
+ if (field.fieldType === "url") {
419
+ return /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm", children: [
420
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-medium", children: [
421
+ field.label,
422
+ ":"
423
+ ] }),
424
+ " ",
425
+ /* @__PURE__ */ jsxRuntime.jsx("a", { href: String(value), className: "text-primary underline underline-offset-2 break-all", children: String(value) })
426
+ ] }, field.id);
427
+ }
428
+ return /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm", children: [
429
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-medium", children: [
430
+ field.label,
431
+ ":"
432
+ ] }),
433
+ " ",
434
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: String(value) })
435
+ ] }, field.id);
436
+ }) });
437
+ }
438
+ const entries = Object.entries(d).filter(([, v]) => v !== "" && v !== null && v !== void 0);
439
+ if (entries.length === 0) return null;
440
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "py-4 space-y-2 border-b border-border last:border-0", children: [
441
+ block.label && /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "font-semibold text-sm text-muted-foreground uppercase tracking-wide", children: block.label }),
442
+ entries.map(([key, value]) => /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm", children: [
443
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-medium capitalize", children: [
444
+ key.replace(/_/g, " "),
445
+ ":"
446
+ ] }),
447
+ " ",
448
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: String(value) })
449
+ ] }, key))
450
+ ] });
451
+ }
452
+ var BUILT_IN = {
453
+ heading: (b) => /* @__PURE__ */ jsxRuntime.jsx(HeadingBlock, { block: b }),
454
+ text: (b) => /* @__PURE__ */ jsxRuntime.jsx(TextBlock, { block: b }),
455
+ richtext: (b) => /* @__PURE__ */ jsxRuntime.jsx(RichTextBlock, { block: b }),
456
+ image: (b) => /* @__PURE__ */ jsxRuntime.jsx(ImageBlock, { block: b }),
457
+ hero: (b) => /* @__PURE__ */ jsxRuntime.jsx(HeroBlock, { block: b }),
458
+ "hero-section": (b) => /* @__PURE__ */ jsxRuntime.jsx(HeroBlock, { block: b }),
459
+ cta: (b) => /* @__PURE__ */ jsxRuntime.jsx(CTABlock, { block: b }),
460
+ faq: (b) => /* @__PURE__ */ jsxRuntime.jsx(FAQBlock, { block: b }),
461
+ stats: (b) => /* @__PURE__ */ jsxRuntime.jsx(StatsBlock, { block: b }),
462
+ testimonial: (b) => /* @__PURE__ */ jsxRuntime.jsx(TestimonialBlock, { block: b }),
463
+ quote: (b) => /* @__PURE__ */ jsxRuntime.jsx(QuoteBlock, { block: b }),
464
+ alert: (b) => /* @__PURE__ */ jsxRuntime.jsx(AlertBlock, { block: b }),
465
+ divider: () => /* @__PURE__ */ jsxRuntime.jsx(DividerBlock, {}),
466
+ spacer: (b) => /* @__PURE__ */ jsxRuntime.jsx(SpacerBlock, { block: b }),
467
+ video: (b) => /* @__PURE__ */ jsxRuntime.jsx(VideoBlock, { block: b })
468
+ };
469
+ function CMSBlocks({ blocks, pageType, className = "", custom = {} }) {
470
+ if (!blocks?.length) return null;
471
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `space-y-8 ${className}`, children: blocks.map((block) => {
472
+ if (custom[block.type]) return /* @__PURE__ */ jsxRuntime.jsx(React__default.default.Fragment, { children: custom[block.type](block) }, block.id);
473
+ if (BUILT_IN[block.type]) return /* @__PURE__ */ jsxRuntime.jsx(React__default.default.Fragment, { children: BUILT_IN[block.type](block, pageType) }, block.id);
474
+ return /* @__PURE__ */ jsxRuntime.jsx(SectionBlock, { block, pageType }, block.id);
475
+ }) });
476
+ }
477
+ var client = createCMSClient();
478
+ async function generateMetadata({ params }) {
479
+ const { slug } = await params;
480
+ const page = await client.getPage(slug.join("/"));
481
+ if (!page) return { title: "Not Found" };
482
+ return {
483
+ title: page.seo?.title || page.title,
484
+ description: page.seo?.description || "",
485
+ keywords: page.seo?.keywords?.join(", "),
486
+ robots: page.seo?.noIndex ? "noindex,nofollow" : void 0,
487
+ openGraph: {
488
+ title: page.seo?.title || page.title,
489
+ description: page.seo?.description,
490
+ images: page.seo?.ogImage ? [page.seo.ogImage] : void 0
491
+ }
492
+ };
493
+ }
494
+ async function CMSCatchAllPage({ params }) {
495
+ const { slug } = await params;
496
+ const slugStr = slug.join("/");
497
+ const draft = await headers.draftMode();
498
+ const cookieStore = await headers.cookies();
499
+ let page = null;
500
+ let isPreview = false;
501
+ if (draft.isEnabled) {
502
+ const token = cookieStore.get("cms_preview_token")?.value;
503
+ if (token) {
504
+ page = await client.getPreviewPage(token);
505
+ isPreview = !!page;
506
+ }
507
+ if (!page) page = await client.getPage(slugStr);
508
+ } else {
509
+ page = await client.getPage(slugStr);
510
+ }
511
+ if (!page) navigation.notFound();
512
+ let pageType = null;
513
+ if (page.pageTypeId) {
514
+ pageType = await client.getPageType(page.pageTypeId);
515
+ }
516
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-h-screen bg-background", children: [
517
+ isPreview && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "sticky top-0 z-50 flex items-center justify-between px-4 py-2.5 bg-amber-500 text-white text-sm font-medium shadow", children: [
518
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
519
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Draft Preview" }),
520
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "opacity-60 mx-1", children: "\xB7" }),
521
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "opacity-75 capitalize", children: page.status }),
522
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "opacity-60 mx-1", children: "\xB7" }),
523
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "opacity-75 font-normal", children: [
524
+ "/",
525
+ page.slug
526
+ ] })
527
+ ] }),
528
+ /* @__PURE__ */ jsxRuntime.jsx(
529
+ "a",
530
+ {
531
+ href: "/api/cms-preview/exit",
532
+ className: "px-3 py-1 rounded bg-white/20 hover:bg-white/30 transition-colors text-xs",
533
+ children: "Exit Preview"
534
+ }
535
+ )
536
+ ] }),
537
+ /* @__PURE__ */ jsxRuntime.jsxs("article", { className: "max-w-5xl mx-auto px-6 py-12", children: [
538
+ /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "mb-10", children: [
539
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-4xl font-bold text-foreground leading-tight", style: { textWrap: "balance" }, children: page.title }),
540
+ page.seo?.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-3 text-lg text-muted-foreground leading-relaxed", children: page.seo.description })
541
+ ] }),
542
+ page.blocks?.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(CMSBlocks, { blocks: page.blocks, pageType }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center py-24 text-muted-foreground border-2 border-dashed border-border rounded-xl", children: [
543
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm", children: "No content added yet." }),
544
+ isPreview && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs mt-1 opacity-60", children: "Add blocks in the CMS editor to see them here." })
545
+ ] })
546
+ ] })
547
+ ] });
548
+ }
549
+
550
+ exports.CMSCatchAllPage = CMSCatchAllPage;
551
+ exports.POST = POST;
552
+ exports.createPreviewExitHandler = createPreviewExitHandler;
553
+ exports.createRevalidateHandler = createRevalidateHandler;
554
+ exports.generateMetadata = generateMetadata;
555
+ exports.previewExitGET = GET;
556
+ //# sourceMappingURL=index.cjs.map
557
+ //# sourceMappingURL=index.cjs.map