@justanarthur/payload-www 0.1.1

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.
Files changed (62) hide show
  1. package/README.md +381 -0
  2. package/dist/access.d.ts +11 -0
  3. package/dist/access.js +34 -0
  4. package/dist/blocks.d.ts +24 -0
  5. package/dist/blocks.js +75 -0
  6. package/dist/collections.d.ts +200 -0
  7. package/dist/collections.js +625 -0
  8. package/dist/components.d.ts +6 -0
  9. package/dist/components.js +38 -0
  10. package/dist/config.d.ts +100 -0
  11. package/dist/config.js +914 -0
  12. package/dist/core-access.d.ts +11 -0
  13. package/dist/core-access.js +34 -0
  14. package/dist/core-blocks.d.ts +24 -0
  15. package/dist/core-blocks.js +75 -0
  16. package/dist/core-fields.d.ts +36 -0
  17. package/dist/core-fields.js +134 -0
  18. package/dist/core-utils.d.ts +16 -0
  19. package/dist/core-utils.js +59 -0
  20. package/dist/data-collections.d.ts +200 -0
  21. package/dist/data-collections.js +625 -0
  22. package/dist/data-seed.d.ts +76 -0
  23. package/dist/data-seed.js +212 -0
  24. package/dist/data-test.d.ts +30 -0
  25. package/dist/data-test.js +1018 -0
  26. package/dist/fields.d.ts +36 -0
  27. package/dist/fields.js +134 -0
  28. package/dist/globals.d.ts +48 -0
  29. package/dist/globals.js +228 -0
  30. package/dist/hooks.d.ts +108 -0
  31. package/dist/hooks.js +196 -0
  32. package/dist/imagehash.d.ts +3 -0
  33. package/dist/imagehash.js +24 -0
  34. package/dist/import-map-provider.d.ts +20 -0
  35. package/dist/import-map-provider.js +26 -0
  36. package/dist/index.d.ts +6 -0
  37. package/dist/index.js +38 -0
  38. package/dist/metadata.d.ts +122 -0
  39. package/dist/metadata.js +335 -0
  40. package/dist/pages.d.ts +323 -0
  41. package/dist/pages.js +1016 -0
  42. package/dist/render-components.d.ts +42 -0
  43. package/dist/render-components.js +144 -0
  44. package/dist/render-metadata.d.ts +122 -0
  45. package/dist/render-metadata.js +335 -0
  46. package/dist/render-pages.d.ts +574 -0
  47. package/dist/render-pages.js +1450 -0
  48. package/dist/render-utils.d.ts +158 -0
  49. package/dist/render-utils.js +341 -0
  50. package/dist/seed.d.ts +76 -0
  51. package/dist/seed.js +212 -0
  52. package/dist/server.d.ts +922 -0
  53. package/dist/server.js +2055 -0
  54. package/dist/test.d.ts +30 -0
  55. package/dist/test.js +1018 -0
  56. package/dist/translator.d.ts +2 -0
  57. package/dist/translator.js +24 -0
  58. package/dist/utils.d.ts +16 -0
  59. package/dist/utils.js +59 -0
  60. package/dist/with-www-config.d.ts +100 -0
  61. package/dist/with-www-config.js +914 -0
  62. package/package.json +246 -0
package/dist/server.js ADDED
@@ -0,0 +1,2055 @@
1
+
2
+ var __defProp = Object.defineProperty;
3
+ var __returnValue = (v) => v;
4
+ function __exportSetter(name, newValue) {
5
+ this[name] = __returnValue.bind(null, newValue);
6
+ }
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, {
10
+ get: all[name],
11
+ enumerable: true,
12
+ configurable: true,
13
+ set: __exportSetter.bind(all, name)
14
+ });
15
+ };
16
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
17
+
18
+ // src/render/components/PageShowcase.tsx
19
+ var exports_PageShowcase = {};
20
+ __export(exports_PageShowcase, {
21
+ PageShowcase: () => PageShowcase
22
+ });
23
+ import * as React from "react";
24
+ import { jsx as jsx5, jsxs } from "react/jsx-runtime";
25
+ function PageShowcase({
26
+ children,
27
+ metadata,
28
+ jsonLd,
29
+ localeSwitcher,
30
+ metadataHeading = "Page metadata",
31
+ jsonLdHeading = "JSON-LD"
32
+ }) {
33
+ const og = metadata.openGraph;
34
+ const twitter = metadata.twitter;
35
+ const rows = [
36
+ ["Title", resolveTitle(metadata.title)],
37
+ ["Description", metadata.description],
38
+ ["Canonical", metadata.alternates?.canonical],
39
+ [
40
+ "Languages",
41
+ metadata.alternates?.languages ? Object.entries(metadata.alternates.languages).map(([locale, url]) => `${locale}: ${url}`).join(`
42
+ `) : undefined
43
+ ],
44
+ ["Open Graph title", og?.title],
45
+ ["Open Graph description", og?.description],
46
+ ["Open Graph type", og?.type],
47
+ ["Open Graph url", og?.url],
48
+ ["Open Graph site name", og?.siteName],
49
+ ["Twitter card", twitter?.card],
50
+ ["Twitter title", twitter?.title],
51
+ ["Twitter description", twitter?.description],
52
+ ["Twitter site", twitter?.site],
53
+ ["Twitter creator", twitter?.creator]
54
+ ];
55
+ return /* @__PURE__ */ jsxs("div", {
56
+ className: "page-showcase grid gap-8 lg:grid-cols-[1fr_320px]",
57
+ children: [
58
+ /* @__PURE__ */ jsx5("main", {
59
+ className: "page-showcase__main",
60
+ children
61
+ }),
62
+ /* @__PURE__ */ jsxs("aside", {
63
+ className: "page-showcase__sidebar flex flex-col gap-6 text-sm",
64
+ children: [
65
+ /* @__PURE__ */ jsxs("section", {
66
+ className: "page-showcase__locale",
67
+ children: [
68
+ /* @__PURE__ */ jsx5("h2", {
69
+ className: "m-0 mb-2 text-xs font-semibold uppercase tracking-wide text-muted-foreground",
70
+ children: "Language"
71
+ }),
72
+ localeSwitcher
73
+ ]
74
+ }),
75
+ /* @__PURE__ */ jsxs("section", {
76
+ className: "page-showcase__metadata",
77
+ children: [
78
+ /* @__PURE__ */ jsx5("h2", {
79
+ className: "m-0 mb-2 text-xs font-semibold uppercase tracking-wide text-muted-foreground",
80
+ children: metadataHeading
81
+ }),
82
+ /* @__PURE__ */ jsx5("dl", {
83
+ className: "m-0 grid grid-cols-[max-content_1fr] gap-x-3 gap-y-1.5",
84
+ children: rows.filter(([, value]) => value !== undefined && value !== "").map(([label, value]) => /* @__PURE__ */ jsxs(React.Fragment, {
85
+ children: [
86
+ /* @__PURE__ */ jsx5("dt", {
87
+ className: "font-medium text-muted-foreground",
88
+ children: label
89
+ }),
90
+ /* @__PURE__ */ jsx5("dd", {
91
+ className: "m-0 whitespace-pre-wrap break-words font-mono text-xs",
92
+ children: value
93
+ })
94
+ ]
95
+ }, label))
96
+ })
97
+ ]
98
+ }),
99
+ jsonLd.length > 0 ? /* @__PURE__ */ jsxs("section", {
100
+ className: "page-showcase__jsonld",
101
+ children: [
102
+ /* @__PURE__ */ jsx5("h2", {
103
+ className: "m-0 mb-2 text-xs font-semibold uppercase tracking-wide text-muted-foreground",
104
+ children: jsonLdHeading
105
+ }),
106
+ jsonLd.map(({ id, schema }) => /* @__PURE__ */ jsxs("details", {
107
+ className: "mb-2 rounded border border-border bg-muted/30 p-2",
108
+ children: [
109
+ /* @__PURE__ */ jsx5("summary", {
110
+ className: "cursor-pointer font-mono text-xs",
111
+ children: id
112
+ }),
113
+ /* @__PURE__ */ jsx5("pre", {
114
+ className: "mt-2 overflow-x-auto whitespace-pre-wrap break-words font-mono text-[10px] leading-snug",
115
+ children: JSON.stringify(schema, null, 2)
116
+ })
117
+ ]
118
+ }, id))
119
+ ]
120
+ }) : null
121
+ ]
122
+ })
123
+ ]
124
+ });
125
+ }
126
+ function resolveTitle(title) {
127
+ if (!title)
128
+ return;
129
+ if (typeof title === "string")
130
+ return title;
131
+ if (title === null)
132
+ return;
133
+ const t = title;
134
+ return t.absolute ?? t.template ?? t.default;
135
+ }
136
+ var init_PageShowcase = () => {};
137
+
138
+ // src/render/components/LocaleSwitcher.tsx
139
+ var exports_LocaleSwitcher = {};
140
+ __export(exports_LocaleSwitcher, {
141
+ LocaleSwitcher: () => LocaleSwitcher
142
+ });
143
+ import { jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
144
+ function LocaleSwitcher({
145
+ currentLocale,
146
+ hreflangAlternates,
147
+ labels
148
+ }) {
149
+ const locales = Object.keys(hreflangAlternates).filter((k) => k !== "x-default");
150
+ return /* @__PURE__ */ jsx6("nav", {
151
+ "aria-label": "Language",
152
+ className: "locale-switcher",
153
+ children: /* @__PURE__ */ jsxs2("ul", {
154
+ className: "flex flex-wrap gap-2 list-none p-0 m-0",
155
+ children: [
156
+ locales.map((locale) => {
157
+ const href = hreflangAlternates[locale];
158
+ if (!href)
159
+ return null;
160
+ const isCurrent = locale === currentLocale;
161
+ return /* @__PURE__ */ jsx6("li", {
162
+ children: /* @__PURE__ */ jsx6("a", {
163
+ href,
164
+ "aria-current": isCurrent ? "true" : undefined,
165
+ hrefLang: locale,
166
+ className: "locale-switcher__link",
167
+ "data-locale": locale,
168
+ children: labels?.[locale] ?? locale.toUpperCase()
169
+ })
170
+ }, locale);
171
+ }),
172
+ hreflangAlternates["x-default"] ? /* @__PURE__ */ jsx6("li", {
173
+ children: /* @__PURE__ */ jsx6("a", {
174
+ href: hreflangAlternates["x-default"],
175
+ hrefLang: "x-default",
176
+ className: "locale-switcher__link",
177
+ "data-locale": "x-default",
178
+ children: labels?.["x-default"] ?? "Default"
179
+ })
180
+ }, "x-default") : null
181
+ ]
182
+ })
183
+ });
184
+ }
185
+ var init_LocaleSwitcher = () => {};
186
+
187
+ // src/core/access/index.ts
188
+ var anyone = () => true;
189
+ var authenticated = ({ req: { user } }) => Boolean(user);
190
+ var authenticatedOrPublished = ({ req: { user } }) => {
191
+ if (user)
192
+ return true;
193
+ return { _status: { equals: "published" } };
194
+ };
195
+
196
+ // src/render/_locale.ts
197
+ function prefixFor(locale, defaultLocale, mode) {
198
+ if (mode === "never")
199
+ return "";
200
+ if (mode === "as-needed" && locale === defaultLocale)
201
+ return "";
202
+ return `/${locale}`;
203
+ }
204
+ function resolveLocale(req) {
205
+ if (!req || typeof req !== "object")
206
+ return "";
207
+ const r = req;
208
+ if (typeof r.locale === "string" && r.locale.length > 0)
209
+ return r.locale;
210
+ const fallback = r.payload?.config?.localization?.defaultLocale;
211
+ if (typeof fallback === "string" && fallback.length > 0)
212
+ return fallback;
213
+ return "";
214
+ }
215
+ function allLocales(req) {
216
+ if (!req || typeof req !== "object")
217
+ return [];
218
+ const r = req;
219
+ const list = r.payload?.config?.localization?.locales;
220
+ if (!Array.isArray(list) || list.length === 0)
221
+ return [];
222
+ const out = [];
223
+ for (const entry of list) {
224
+ if (typeof entry === "string" && entry.length > 0) {
225
+ out.push(entry);
226
+ } else if (entry && typeof entry === "object" && "code" in entry) {
227
+ const code = entry.code;
228
+ if (typeof code === "string" && code.length > 0)
229
+ out.push(code);
230
+ }
231
+ }
232
+ return out;
233
+ }
234
+
235
+ // src/render/hooks/_shared.ts
236
+ var cachePromise = null;
237
+ function nextCacheImport() {
238
+ return cachePromise ??= import("next/cache");
239
+ }
240
+ function shouldSkipRevalidate(context) {
241
+ return Boolean(context?.disableRevalidate);
242
+ }
243
+ async function safeRevalidatePath(payload, path) {
244
+ try {
245
+ const { revalidatePath } = await nextCacheImport();
246
+ revalidatePath(path);
247
+ } catch (error) {
248
+ payload.logger.error(`revalidatePath("${path}") failed: ${String(error)}`);
249
+ }
250
+ }
251
+ async function safeRevalidateTag(payload, tag, profile = "max") {
252
+ try {
253
+ const { revalidateTag } = await nextCacheImport();
254
+ revalidateTag(tag, profile);
255
+ } catch (error) {
256
+ payload.logger.error(`revalidateTag("${tag}") failed: ${String(error)}`);
257
+ }
258
+ }
259
+
260
+ // src/render/hooks/revalidateCollection.ts
261
+ function createRevalidateCollectionHook(options) {
262
+ const {
263
+ collectionSlug,
264
+ urlPathPrefix = "",
265
+ sitemapTag,
266
+ localePrefix: modeOption,
267
+ defaultLocale: defaultLocaleOption,
268
+ pathMode = "url"
269
+ } = options;
270
+ const resolvedSitemapTag = sitemapTag === false ? false : sitemapTag ?? `${collectionSlug}-sitemap`;
271
+ const resolveDefaults = (req) => {
272
+ const mode = modeOption ?? "always";
273
+ const defaultLocale = defaultLocaleOption ?? req?.payload?.config?.localization?.defaultLocale ?? "";
274
+ return { mode, defaultLocale };
275
+ };
276
+ const localesToFanOut = (req) => {
277
+ const all = allLocales(req);
278
+ if (all.length > 0)
279
+ return all;
280
+ const single = resolveLocale(req);
281
+ return single ? [single] : [];
282
+ };
283
+ const collectionPath = (slug, locale, mode, defaultLocale) => {
284
+ const prefix = prefixFor(locale, defaultLocale, mode);
285
+ if (!slug)
286
+ return `${prefix}${urlPathPrefix}` || "/";
287
+ return `${prefix}${urlPathPrefix}/${slug}`;
288
+ };
289
+ const fanOutPaths = async (payload, req, slug, label) => {
290
+ const { mode, defaultLocale } = resolveDefaults(req);
291
+ const locales = localesToFanOut(req);
292
+ for (const locale of locales) {
293
+ const path = collectionPath(slug, locale, mode, defaultLocale);
294
+ payload.logger.info?.(`${label} ${path}`);
295
+ await safeRevalidatePath(payload, path);
296
+ }
297
+ };
298
+ const fireCollectionTags = async (payload, docId, req) => {
299
+ if (typeof docId === "string" || typeof docId === "number") {
300
+ await safeRevalidateTag(payload, `collection_${collectionSlug}_${docId}`);
301
+ }
302
+ if (resolvedSitemapTag !== false) {
303
+ await safeRevalidateTag(payload, resolvedSitemapTag);
304
+ }
305
+ };
306
+ const afterChange = async ({ doc, previousDoc, req }) => {
307
+ if (shouldSkipRevalidate(req.context))
308
+ return doc;
309
+ const { payload } = req;
310
+ const typed = doc;
311
+ const prev = previousDoc;
312
+ const isPublished = typed._status === "published";
313
+ const wasPublished = prev?._status === "published";
314
+ const prevSlugIsString = typeof prev?.slug === "string";
315
+ const slugChanged = prevSlugIsString && prev?.slug !== typed.slug;
316
+ if (isPublished) {
317
+ if (pathMode !== "tag-only") {
318
+ await fanOutPaths(payload, req, typed.slug, `Revalidating ${collectionSlug} at path:`);
319
+ }
320
+ await fireCollectionTags(payload, typed.id, req);
321
+ }
322
+ if (wasPublished && (!isPublished || slugChanged)) {
323
+ if (pathMode !== "tag-only") {
324
+ await fanOutPaths(payload, req, prev?.slug, `Revalidating old ${collectionSlug} at path:`);
325
+ }
326
+ await fireCollectionTags(payload, typed.id, req);
327
+ }
328
+ return doc;
329
+ };
330
+ const afterDelete = async ({ doc, req }) => {
331
+ if (shouldSkipRevalidate(req.context))
332
+ return doc ?? null;
333
+ const { payload } = req;
334
+ const typed = doc;
335
+ if (pathMode !== "tag-only") {
336
+ await fanOutPaths(payload, req, typed?.slug, `Revalidating deleted ${collectionSlug} at path:`);
337
+ }
338
+ await fireCollectionTags(payload, typed?.id, req);
339
+ return doc ?? null;
340
+ };
341
+ return { afterChange, afterDelete };
342
+ }
343
+ var createRevalidatePageHooks = (opts = {}) => createRevalidateCollectionHook({
344
+ collectionSlug: "pages",
345
+ urlPathPrefix: "",
346
+ ...opts
347
+ });
348
+
349
+ // src/config/constants.ts
350
+ var PAGES_RENDER_PATH = "@justanarthur/payload-www/render-pages#PagesPage";
351
+ var POSTS_RENDER_PATH = "@justanarthur/payload-www/render-pages#PostsPage";
352
+ var HEADER_RENDER_PATH = "@justanarthur/payload-www/render-pages#HeaderPage";
353
+ var FOOTER_RENDER_PATH = "@justanarthur/payload-www/render-pages#FooterPage";
354
+ var LIVE_PREVIEW_LISTENER_PATH = "@justanarthur/payload-www/render-components#LivePreviewListener";
355
+ var PAGES_SLUG = "pages";
356
+ var POSTS_SLUG = "posts";
357
+ var STATIC_PAGES_SLUG = "staticPages";
358
+
359
+ // src/data/collections/Pages/index.ts
360
+ var HOME_PAGE_SLUG = "";
361
+ var PAGES_SLUG2 = PAGES_SLUG;
362
+ var createPagesCollection = (blocks, options = {}) => {
363
+ const {
364
+ renderPath = PAGES_RENDER_PATH,
365
+ slug: collectionSlug = PAGES_SLUG2,
366
+ localePrefix,
367
+ defaultLocale
368
+ } = options;
369
+ const slugField = {
370
+ name: "slug",
371
+ type: "text",
372
+ required: true,
373
+ unique: true,
374
+ index: true,
375
+ admin: { position: "sidebar" },
376
+ validate: (value) => {
377
+ if (typeof value !== "string")
378
+ return "Slug must be a string";
379
+ if (value !== "" && !/^[a-z0-9-]+$/.test(value)) {
380
+ return "Slug must be lowercase, with hyphens (no spaces or special characters)";
381
+ }
382
+ return true;
383
+ }
384
+ };
385
+ const baseFields = [
386
+ {
387
+ name: "title",
388
+ type: "text",
389
+ required: true,
390
+ localized: true
391
+ },
392
+ {
393
+ type: "tabs",
394
+ tabs: [
395
+ {
396
+ fields: [
397
+ {
398
+ name: "blocks",
399
+ type: "blocks",
400
+ blocks,
401
+ required: true,
402
+ admin: { initCollapsed: true }
403
+ }
404
+ ],
405
+ label: "Content"
406
+ }
407
+ ]
408
+ },
409
+ {
410
+ name: "publishedAt",
411
+ type: "date",
412
+ admin: { position: "sidebar" }
413
+ },
414
+ slugField
415
+ ];
416
+ const { afterChange: revalidateAfterChange, afterDelete: revalidateAfterDelete } = createRevalidateCollectionHook({
417
+ collectionSlug,
418
+ urlPathPrefix: "",
419
+ localePrefix,
420
+ defaultLocale
421
+ });
422
+ return {
423
+ slug: collectionSlug,
424
+ custom: { path: renderPath },
425
+ access: {
426
+ create: authenticated,
427
+ delete: authenticated,
428
+ read: authenticatedOrPublished,
429
+ update: authenticated
430
+ },
431
+ fields: baseFields,
432
+ hooks: {
433
+ afterChange: [revalidateAfterChange],
434
+ afterDelete: [revalidateAfterDelete]
435
+ },
436
+ versions: { drafts: { autosave: { interval: 1000 } } }
437
+ };
438
+ };
439
+
440
+ // src/data/collections/Posts/index.ts
441
+ var POSTS_SLUG2 = "posts";
442
+ var createPostsCollection = (options = {}) => {
443
+ const {
444
+ renderPath = POSTS_RENDER_PATH,
445
+ slug: collectionSlug = POSTS_SLUG2,
446
+ localePrefix,
447
+ defaultLocale
448
+ } = options;
449
+ const slugField = {
450
+ name: "slug",
451
+ type: "text",
452
+ required: true,
453
+ unique: true,
454
+ index: true,
455
+ admin: { position: "sidebar" }
456
+ };
457
+ const baseFields = [
458
+ {
459
+ name: "title",
460
+ type: "text",
461
+ required: true,
462
+ localized: true
463
+ },
464
+ {
465
+ name: "excerpt",
466
+ type: "text",
467
+ required: false,
468
+ localized: true
469
+ },
470
+ {
471
+ name: "content",
472
+ type: "richText",
473
+ required: false,
474
+ localized: true
475
+ },
476
+ {
477
+ name: "publishedAt",
478
+ type: "date",
479
+ admin: { position: "sidebar" }
480
+ },
481
+ slugField
482
+ ];
483
+ const { afterChange, afterDelete } = createRevalidateCollectionHook({
484
+ collectionSlug,
485
+ urlPathPrefix: "/posts",
486
+ localePrefix,
487
+ defaultLocale
488
+ });
489
+ return {
490
+ slug: collectionSlug,
491
+ custom: { path: renderPath },
492
+ access: {
493
+ create: authenticated,
494
+ delete: authenticated,
495
+ read: authenticatedOrPublished,
496
+ update: authenticated
497
+ },
498
+ fields: baseFields,
499
+ hooks: {
500
+ afterChange: [afterChange],
501
+ afterDelete: [afterDelete]
502
+ },
503
+ versions: { drafts: { autosave: { interval: 1000 } } }
504
+ };
505
+ };
506
+
507
+ // src/data/collections/StaticPages/index.ts
508
+ var createStaticPagesCollection = (blocks) => {
509
+ const { afterChange, afterDelete } = createRevalidateCollectionHook({
510
+ collectionSlug: STATIC_PAGES_SLUG,
511
+ pathMode: "tag-only",
512
+ sitemapTag: "static-pages"
513
+ });
514
+ return {
515
+ slug: STATIC_PAGES_SLUG,
516
+ dbName: "sp",
517
+ admin: { group: "System", useAsTitle: "title" },
518
+ access: {
519
+ create: authenticated,
520
+ delete: authenticated,
521
+ read: authenticatedOrPublished,
522
+ update: authenticated
523
+ },
524
+ fields: [
525
+ {
526
+ name: "kind",
527
+ type: "select",
528
+ required: true,
529
+ unique: true,
530
+ index: true,
531
+ options: [
532
+ { label: "Not found (404)", value: "not-found" },
533
+ { label: "Server error (500)", value: "server-error" },
534
+ { label: "Search empty", value: "search-empty" },
535
+ { label: "Offline", value: "offline" }
536
+ ],
537
+ admin: {
538
+ position: "sidebar",
539
+ description: "Which system page this row powers. One row per kind."
540
+ }
541
+ },
542
+ {
543
+ name: "title",
544
+ type: "text",
545
+ required: true,
546
+ localized: true,
547
+ admin: { description: "Admin-only label. Not rendered." }
548
+ },
549
+ {
550
+ type: "tabs",
551
+ tabs: [
552
+ {
553
+ fields: [
554
+ {
555
+ name: "blocks",
556
+ type: "blocks",
557
+ localized: true,
558
+ blocks,
559
+ admin: { initCollapsed: true },
560
+ dbName: "b"
561
+ }
562
+ ],
563
+ label: "Content"
564
+ }
565
+ ]
566
+ },
567
+ {
568
+ name: "publishedAt",
569
+ type: "date",
570
+ admin: { position: "sidebar" }
571
+ }
572
+ ],
573
+ hooks: {
574
+ afterChange: [afterChange],
575
+ afterDelete: [afterDelete]
576
+ },
577
+ versions: { drafts: { autosave: { interval: 1000 } } }
578
+ };
579
+ };
580
+
581
+ // src/core/fields/link.ts
582
+ var appearanceOptions = {
583
+ default: { label: "Default", value: "default" },
584
+ outline: { label: "Outline", value: "outline" }
585
+ };
586
+ var link = (options = {}) => {
587
+ const {
588
+ appearances,
589
+ disableLabel = false,
590
+ relationTo = [PAGES_SLUG],
591
+ localized = false,
592
+ overrides = {}
593
+ } = options;
594
+ const result = {
595
+ name: "link",
596
+ type: "group",
597
+ admin: { hideGutter: true },
598
+ fields: [
599
+ {
600
+ type: "row",
601
+ fields: [
602
+ {
603
+ name: "type",
604
+ type: "radio",
605
+ admin: { layout: "horizontal", width: "50%" },
606
+ defaultValue: "reference",
607
+ options: [
608
+ { label: "Internal link", value: "reference" },
609
+ { label: "Custom URL", value: "custom" }
610
+ ]
611
+ },
612
+ {
613
+ name: "newTab",
614
+ type: "checkbox",
615
+ admin: { style: { alignSelf: "flex-end" }, width: "50%" },
616
+ label: "Open in new tab"
617
+ }
618
+ ]
619
+ }
620
+ ]
621
+ };
622
+ const linkTypes = [
623
+ {
624
+ name: "reference",
625
+ type: "relationship",
626
+ admin: { condition: (_, siblingData) => siblingData?.type === "reference" },
627
+ label: "Document to link to",
628
+ relationTo,
629
+ required: true,
630
+ localized
631
+ },
632
+ {
633
+ name: "url",
634
+ type: "text",
635
+ admin: { condition: (_, siblingData) => siblingData?.type === "custom" },
636
+ label: "Custom URL",
637
+ required: true,
638
+ localized
639
+ }
640
+ ];
641
+ if (!disableLabel) {
642
+ result.fields.push({
643
+ type: "row",
644
+ fields: [
645
+ ...linkTypes,
646
+ {
647
+ name: "label",
648
+ type: "text",
649
+ admin: { width: "50%" },
650
+ label: "Label",
651
+ required: true,
652
+ localized
653
+ }
654
+ ]
655
+ });
656
+ } else {
657
+ result.fields = [...result.fields, ...linkTypes];
658
+ }
659
+ if (appearances !== false) {
660
+ const opts = appearances ? appearances.map((a) => appearanceOptions[a]) : [appearanceOptions.default, appearanceOptions.outline];
661
+ result.fields.push({
662
+ name: "appearance",
663
+ type: "select",
664
+ admin: { description: "Choose how the link should be rendered." },
665
+ defaultValue: "default",
666
+ options: opts
667
+ });
668
+ }
669
+ return { ...result, ...overrides };
670
+ };
671
+
672
+ // src/render/hooks/revalidateGlobal.ts
673
+ function createRevalidateGlobalHook(slug) {
674
+ return async ({ doc, req: { payload, context, locale } }) => {
675
+ if (shouldSkipRevalidate(context))
676
+ return doc;
677
+ const tags = [`global_${slug}`, `global_${slug}_${locale}`];
678
+ payload.logger.info?.(`Revalidating global: ${tags.join(", ")}`);
679
+ for (const tag of tags) {
680
+ await safeRevalidateTag(payload, tag);
681
+ }
682
+ return doc;
683
+ };
684
+ }
685
+
686
+ // src/data/collections/globals/Header/config.ts
687
+ var createHeaderGlobal = (options = {}) => {
688
+ const { renderPath = HEADER_RENDER_PATH, linkRelationTo = [PAGES_SLUG] } = options;
689
+ const navColumnBlock = {
690
+ slug: "navColumn",
691
+ fields: [
692
+ { name: "title", type: "text", required: true, localized: true },
693
+ { name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })] }
694
+ ]
695
+ };
696
+ const navItemBlock = {
697
+ slug: "navItem",
698
+ fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })]
699
+ };
700
+ return {
701
+ slug: "header",
702
+ custom: { path: renderPath },
703
+ access: { read: () => true },
704
+ fields: [
705
+ {
706
+ name: "nav",
707
+ type: "blocks",
708
+ required: true,
709
+ blocks: [navColumnBlock, navItemBlock]
710
+ }
711
+ ],
712
+ hooks: {
713
+ afterChange: [createRevalidateGlobalHook("header")]
714
+ }
715
+ };
716
+ };
717
+
718
+ // src/data/collections/globals/Footer/config.ts
719
+ var createFooterGlobal = (options = {}) => {
720
+ const { renderPath = FOOTER_RENDER_PATH, linkRelationTo = [PAGES_SLUG] } = options;
721
+ const navColumnBlock = {
722
+ slug: "navColumn",
723
+ fields: [
724
+ { name: "title", type: "text", required: true, localized: true },
725
+ { name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })] }
726
+ ]
727
+ };
728
+ const navItemBlock = {
729
+ slug: "navItem",
730
+ fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })]
731
+ };
732
+ return {
733
+ slug: "footer",
734
+ custom: { path: renderPath },
735
+ access: { read: () => true },
736
+ fields: [
737
+ {
738
+ name: "nav",
739
+ type: "blocks",
740
+ required: true,
741
+ blocks: [navColumnBlock, navItemBlock]
742
+ }
743
+ ],
744
+ hooks: {
745
+ afterChange: [createRevalidateGlobalHook("footer")]
746
+ }
747
+ };
748
+ };
749
+
750
+ // src/config/createWWWConfig.ts
751
+ import openAIResolver from "@justanarthur/payload-plugin-translator/resolvers/openAI";
752
+
753
+ // src/render/preview/createPreviewHandler.ts
754
+ function createPreviewHandler(options) {
755
+ const { getServerSideURL: _getServerSideURL, secret, enableDraftMode = true } = options;
756
+ return async function GET(req) {
757
+ const { draftMode } = await import("next/headers");
758
+ const { redirect } = await import("next/navigation");
759
+ const url = new URL(req.url);
760
+ const path = url.searchParams.get("path") ?? "/";
761
+ const previewSecret = url.searchParams.get("previewSecret");
762
+ if (!previewSecret || previewSecret !== secret) {
763
+ return new Response("Invalid preview secret", { status: 401 });
764
+ }
765
+ if (enableDraftMode) {
766
+ (await draftMode()).enable();
767
+ }
768
+ redirect(path);
769
+ return new Response(null, { status: 204 });
770
+ };
771
+ }
772
+ // src/render/metadata/hreflang.ts
773
+ async function buildHreflangAlternates({
774
+ siteUrl,
775
+ locale,
776
+ urlPrefix,
777
+ storedSlug,
778
+ queryAllLocaleSlugs,
779
+ nested,
780
+ homeSlug,
781
+ defaultLocale,
782
+ locales,
783
+ localePrefix = "always"
784
+ }) {
785
+ const allLocaleSlugs = await queryAllLocaleSlugs(storedSlug, locale);
786
+ const languages = {};
787
+ const urlFor = (l, slug) => {
788
+ const trimmedPrefix = urlPrefix.replace(/^\/|\/$/g, "");
789
+ const prefixSegment = trimmedPrefix ? `/${trimmedPrefix}` : "";
790
+ const urlPath = slug === homeSlug ? "/" : nested ? "/" + slug.replaceAll("_", "/") : "/" + slug;
791
+ const localeSegment = localePrefix === "never" ? "" : localePrefix === "as-needed" && l === defaultLocale ? "" : `/${l}`;
792
+ return `${siteUrl}${localeSegment}${prefixSegment}${urlPath}`;
793
+ };
794
+ for (const l of locales) {
795
+ const slugForLocale = allLocaleSlugs?.[l];
796
+ if (!slugForLocale)
797
+ continue;
798
+ languages[l] = urlFor(l, slugForLocale);
799
+ }
800
+ if (allLocaleSlugs?.[defaultLocale]) {
801
+ languages["x-default"] = urlFor(defaultLocale, allLocaleSlugs[defaultLocale]);
802
+ }
803
+ return languages;
804
+ }
805
+
806
+ // src/render/metadata/query.ts
807
+ import { getPayload } from "payload";
808
+ import { cache } from "react";
809
+
810
+ // src/core/utils/getFromImportMap.ts
811
+ function getFromImportMap(key, importMap) {
812
+ return importMap[key.includes("#") ? key : key + "#default"];
813
+ }
814
+
815
+ // src/render/metadata/query.ts
816
+ var queryDocBySlug = cache(async function queryDocBySlug2({
817
+ collectionSlug,
818
+ slug,
819
+ slugField = "slug",
820
+ locale,
821
+ draft = false,
822
+ config
823
+ }) {
824
+ const payload = await getPayload({ config });
825
+ const result = await payload.find({
826
+ collection: collectionSlug,
827
+ draft,
828
+ limit: 1,
829
+ pagination: false,
830
+ overrideAccess: draft,
831
+ where: { [slugField]: { equals: slug } },
832
+ locale
833
+ });
834
+ return result.docs?.[0] ?? null;
835
+ });
836
+ var queryAllDocs = cache(async function queryAllDocs2({
837
+ collectionSlug,
838
+ slugField = "slug",
839
+ locale,
840
+ config
841
+ }) {
842
+ const payload = await getPayload({ config });
843
+ const result = await payload.find({
844
+ collection: collectionSlug,
845
+ draft: false,
846
+ limit: 1000,
847
+ pagination: false,
848
+ overrideAccess: false,
849
+ select: { [slugField]: true },
850
+ locale
851
+ });
852
+ return result.docs ?? [];
853
+ });
854
+ var queryAllLocaleSlugs = cache(async function queryAllLocaleSlugs2({
855
+ collectionSlug,
856
+ slug,
857
+ slugField = "slug",
858
+ locale,
859
+ config
860
+ }) {
861
+ const payload = await getPayload({ config });
862
+ const result = await payload.find({
863
+ collection: collectionSlug,
864
+ draft: false,
865
+ limit: 1,
866
+ pagination: false,
867
+ overrideAccess: false,
868
+ locale,
869
+ where: { [slugField]: { equals: slug } },
870
+ select: { [slugField]: true }
871
+ });
872
+ const doc = result.docs?.[0];
873
+ if (!doc)
874
+ return;
875
+ const fieldValue = doc?.[slugField];
876
+ if (fieldValue && typeof fieldValue === "object") {
877
+ return fieldValue;
878
+ }
879
+ const resolved = await config;
880
+ const rawLocales = Array.isArray(resolved?.localization?.localeCodes) ? resolved.localization.localeCodes : resolved?.localization?.locales?.map((l) => l.code) ?? [];
881
+ const out = {};
882
+ for (const l of rawLocales)
883
+ out[l] = String(fieldValue ?? slug);
884
+ return out;
885
+ });
886
+ var queryGlobal = cache(async function queryGlobal2({
887
+ globalSlug,
888
+ locale,
889
+ depth = 0,
890
+ draft = false,
891
+ config
892
+ }) {
893
+ const payload = await getPayload({ config });
894
+ try {
895
+ const global = await payload.findGlobal({
896
+ slug: globalSlug,
897
+ depth,
898
+ draft,
899
+ locale
900
+ });
901
+ return global;
902
+ } catch {
903
+ return null;
904
+ }
905
+ });
906
+ function getRenderModuleExports(exportName, collection, importMap) {
907
+ const path = collection?.custom?.path;
908
+ if (!path)
909
+ return;
910
+ const mod = getFromImportMap(path, importMap);
911
+ return mod?.[exportName];
912
+ }
913
+
914
+ // src/render/sitemap/createSitemapFile.ts
915
+ function createSitemapFile(options) {
916
+ const { collections } = options;
917
+ return async function sitemap() {
918
+ const cfg = await options.config;
919
+ const allLocales2 = Array.isArray(cfg.localization?.locales) ? cfg.localization.locales.map((l) => typeof l === "string" ? l : l.code) : [cfg.localization?.defaultLocale ?? "en"];
920
+ const defaultLocale = cfg.localization?.defaultLocale ?? allLocales2[0];
921
+ const activeLocales = Array.isArray(options.locales) && options.locales.length > 0 ? options.locales.filter((l) => allLocales2.includes(l)) : allLocales2;
922
+ const entries = [];
923
+ const seen = new Set;
924
+ for (const collectionSlug of collections) {
925
+ const collectionDefaults = options.perCollection?.[collectionSlug] ?? {};
926
+ const urlPrefix = (options.urlPrefixes?.[collectionSlug] ?? "").replace(/\/$/, "");
927
+ const siteUrl = options.getServerSideURL().replace(/\/$/, "");
928
+ for (const locale of activeLocales) {
929
+ const docs = await queryAllDocs({
930
+ collectionSlug,
931
+ slugField: "slug",
932
+ locale,
933
+ config: options.config
934
+ });
935
+ for (const doc of docs) {
936
+ const storedSlug = doc.slug;
937
+ if (typeof storedSlug !== "string" || storedSlug === "")
938
+ continue;
939
+ const dedupeKey = `${collectionSlug}:${locale}:${storedSlug}`;
940
+ if (seen.has(dedupeKey))
941
+ continue;
942
+ seen.add(dedupeKey);
943
+ const url = `${siteUrl}${prefixFor(locale, defaultLocale, options.localePrefix ?? "always")}${urlPrefix}/${storedSlug}`;
944
+ const languages = await buildHreflangAlternates({
945
+ siteUrl,
946
+ locale,
947
+ urlPrefix,
948
+ storedSlug,
949
+ nested: false,
950
+ homeSlug: "",
951
+ defaultLocale,
952
+ locales: activeLocales,
953
+ localePrefix: options.localePrefix,
954
+ queryAllLocaleSlugs: async (s, l) => {
955
+ const result = await queryAllLocaleSlugs({
956
+ collectionSlug,
957
+ slug: s,
958
+ slugField: "slug",
959
+ locale: l,
960
+ config: options.config
961
+ });
962
+ return result ?? undefined;
963
+ }
964
+ });
965
+ entries.push({
966
+ url,
967
+ lastModified: doc.updatedAt ? new Date(doc.updatedAt) : undefined,
968
+ changeFrequency: collectionDefaults.changefreq ?? "weekly",
969
+ priority: collectionDefaults.priority ?? 0.5,
970
+ alternates: { languages }
971
+ });
972
+ }
973
+ }
974
+ }
975
+ return entries;
976
+ };
977
+ }
978
+ // src/config/createWWWConfig.ts
979
+ function createWWWConfig(options) {
980
+ const { locales, routing, blocks, linkRelationTo, registerPosts = true, defaultPlugins } = options;
981
+ const defaultLocale = routing?.defaultLocale ?? locales[0] ?? "";
982
+ const localePrefixMode = (() => {
983
+ const raw = routing?.localePrefix;
984
+ if (typeof raw === "string")
985
+ return raw;
986
+ return raw?.mode ?? "always";
987
+ })();
988
+ if (locales.length === 0) {
989
+ throw new Error("createWWWConfig: `locales` must contain at least one entry.");
990
+ }
991
+ const buildPagesCollection = () => createPagesCollection(blocks, {
992
+ localePrefix: localePrefixMode,
993
+ defaultLocale
994
+ });
995
+ const buildPostsCollection = () => createPostsCollection({
996
+ localePrefix: localePrefixMode,
997
+ defaultLocale
998
+ });
999
+ const buildStaticPagesCollection = () => createStaticPagesCollection(blocks);
1000
+ const buildHeaderGlobal = () => createHeaderGlobal({ linkRelationTo });
1001
+ const buildFooterGlobal = () => createFooterGlobal({ linkRelationTo });
1002
+ async function withWWWConfig(config) {
1003
+ const baseDefaults = [
1004
+ buildPagesCollection(),
1005
+ buildStaticPagesCollection()
1006
+ ];
1007
+ if (registerPosts)
1008
+ baseDefaults.push(buildPostsCollection());
1009
+ const defaultCollections = baseDefaults;
1010
+ const collections = typeof config.collections === "function" ? config.collections({ defaultCollections }) : [...defaultCollections, ...config.collections || []];
1011
+ const defaultGlobals = [buildHeaderGlobal(), buildFooterGlobal()];
1012
+ const globals = typeof config.globals === "function" ? config.globals({ defaultGlobals }) : [...defaultGlobals, ...config.globals || []];
1013
+ const renderDependencies = {
1014
+ [PAGES_RENDER_PATH]: { path: PAGES_RENDER_PATH, type: "component" },
1015
+ [POSTS_RENDER_PATH]: { path: POSTS_RENDER_PATH, type: "component" },
1016
+ [HEADER_RENDER_PATH]: { path: HEADER_RENDER_PATH, type: "component" },
1017
+ [FOOTER_RENDER_PATH]: { path: FOOTER_RENDER_PATH, type: "component" },
1018
+ [LIVE_PREVIEW_LISTENER_PATH]: {
1019
+ path: LIVE_PREVIEW_LISTENER_PATH,
1020
+ type: "component"
1021
+ }
1022
+ };
1023
+ for (const { slug, admin } of blocks) {
1024
+ const path = admin?.custom?.path;
1025
+ if (typeof path === "string" && slug)
1026
+ renderDependencies[slug] = { path, type: "component" };
1027
+ }
1028
+ for (const entry of [...collections, ...globals]) {
1029
+ const path = entry.custom?.path;
1030
+ if (typeof path === "string")
1031
+ renderDependencies[path] = { path, type: "component" };
1032
+ }
1033
+ const [
1034
+ { seoPlugin },
1035
+ { imageHashPlugin },
1036
+ { translator }
1037
+ ] = await Promise.all([
1038
+ import("@justanarthur/payload-plugin-seo"),
1039
+ import("@justanarthur/payload-imagehash-plugin"),
1040
+ import("@justanarthur/payload-plugin-translator")
1041
+ ]);
1042
+ const defaultPluginList = [
1043
+ seoPlugin({
1044
+ collections: ["pages", "posts", "static-pages"],
1045
+ autoGenerate: { mode: "onCreate", deriveFrom: "allScalars" }
1046
+ }),
1047
+ imageHashPlugin({ algorithm: "lqip-modern" }),
1048
+ translator({
1049
+ collections: ["pages", "posts", "static-pages"],
1050
+ globals: ["header", "footer"],
1051
+ resolvers: [
1052
+ openAIResolver({
1053
+ apiKey: process.env.OPENAI_API_KEY,
1054
+ chunkLength: 31,
1055
+ model: "gpt-5-mini"
1056
+ })
1057
+ ]
1058
+ })
1059
+ ];
1060
+ const mergedPlugins = defaultPlugins ? defaultPlugins(defaultPluginList) : defaultPluginList;
1061
+ return {
1062
+ ...config,
1063
+ collections,
1064
+ globals,
1065
+ plugins: mergedPlugins,
1066
+ admin: {
1067
+ ...config.admin ?? {},
1068
+ dependencies: {
1069
+ ...renderDependencies,
1070
+ ...config.admin?.dependencies ?? {}
1071
+ }
1072
+ }
1073
+ };
1074
+ }
1075
+ return { withWWWConfig };
1076
+ }
1077
+
1078
+ // src/core/fields/linkGroup.ts
1079
+ var linkGroup = (options = {}) => ({
1080
+ name: "links",
1081
+ type: "array",
1082
+ fields: [link(options)],
1083
+ admin: { initCollapsed: true }
1084
+ });
1085
+
1086
+ // src/core/utils/generateImportName.ts
1087
+ function generateImportName(type, slug) {
1088
+ switch (type) {
1089
+ case "block":
1090
+ return `Block${slug.replace(/(^\w|-\w)/g, (m) => m.replace("-", "").toUpperCase())}#default`;
1091
+ case "page":
1092
+ return `Page${slug.replace(/(^\w|-\w)/g, (m) => m.replace("-", "").toUpperCase())}#default`;
1093
+ default:
1094
+ throw new Error(`Unknown type: ${type}`);
1095
+ }
1096
+ }
1097
+
1098
+ // src/render/utils/renderCollectionModule.tsx
1099
+ import { jsx } from "react/jsx-runtime";
1100
+ function renderCollectionModule(collection = [], slug, importMap, props) {
1101
+ const renderPath = collection?.find((c) => c.slug === slug)?.custom?.path;
1102
+ if (!renderPath)
1103
+ return null;
1104
+ const CollectionRenderModule = getFromImportMap(renderPath, importMap);
1105
+ if (!CollectionRenderModule) {
1106
+ if (false) {}
1107
+ return null;
1108
+ }
1109
+ return /* @__PURE__ */ jsx(CollectionRenderModule, {
1110
+ importMap,
1111
+ ...props
1112
+ });
1113
+ }
1114
+
1115
+ // src/render/utils/renderGlobalModule.tsx
1116
+ import { jsx as jsx2 } from "react/jsx-runtime";
1117
+ function renderGlobalModule(globals = [], slug, importMap, props) {
1118
+ const renderPath = globals?.find((g) => g.slug === slug)?.custom?.path;
1119
+ if (!renderPath)
1120
+ return null;
1121
+ const GlobalRenderModule = getFromImportMap(renderPath, importMap);
1122
+ if (!GlobalRenderModule) {
1123
+ if (false) {}
1124
+ return null;
1125
+ }
1126
+ return /* @__PURE__ */ jsx2(GlobalRenderModule, {
1127
+ importMap,
1128
+ ...props
1129
+ });
1130
+ }
1131
+
1132
+ // src/render/utils/getCachedGlobal.ts
1133
+ import { unstable_cache } from "next/cache";
1134
+ var getCachedGlobal = (config, slug, depth = 0) => unstable_cache(async () => queryGlobal({
1135
+ globalSlug: slug,
1136
+ locale: "__ALL__",
1137
+ depth,
1138
+ config
1139
+ }), [slug], { tags: [`global_${slug}`] });
1140
+
1141
+ // src/render/metadata/jsonld.ts
1142
+ function getImageUrl(doc, siteUrl) {
1143
+ const img = doc?.meta?.image ?? doc?.heroImage ?? doc?.image;
1144
+ if (!img)
1145
+ return null;
1146
+ if (typeof img === "string")
1147
+ return img;
1148
+ if (img?.url)
1149
+ return img.url.startsWith("http") ? img.url : `${siteUrl}${img.url}`;
1150
+ return null;
1151
+ }
1152
+ function resolveLocalizedField(value, locale) {
1153
+ if (value == null)
1154
+ return "";
1155
+ if (typeof value === "string") {
1156
+ if (!value.startsWith("{"))
1157
+ return value;
1158
+ try {
1159
+ const parsed = JSON.parse(value);
1160
+ return resolveLocalizedField(parsed, locale);
1161
+ } catch {
1162
+ return value;
1163
+ }
1164
+ }
1165
+ if (typeof value !== "object")
1166
+ return "";
1167
+ const obj = value;
1168
+ if (typeof obj[locale] === "string" && obj[locale].length > 0) {
1169
+ return obj[locale];
1170
+ }
1171
+ return Object.values(obj).filter((v) => typeof v === "string" && v.length > 0).join(" / ");
1172
+ }
1173
+ function buildArticleLd({
1174
+ doc,
1175
+ url,
1176
+ locale,
1177
+ siteUrl,
1178
+ type = "BlogPosting",
1179
+ publisherName,
1180
+ publisherLogo
1181
+ }) {
1182
+ const name = publisherName ?? new URL(siteUrl).hostname;
1183
+ const ld = {
1184
+ "@context": "https://schema.org",
1185
+ "@type": type,
1186
+ "@id": `${url}#article`,
1187
+ headline: resolveLocalizedField(doc.title, locale),
1188
+ description: resolveLocalizedField(doc.meta?.description ?? doc.description ?? doc.excerpt, locale),
1189
+ inLanguage: locale,
1190
+ url,
1191
+ dateModified: doc.updatedAt ? new Date(doc.updatedAt).toISOString() : undefined
1192
+ };
1193
+ const datePublished = doc.publishedAt ?? doc.createdAt;
1194
+ if (datePublished)
1195
+ ld.datePublished = new Date(datePublished).toISOString();
1196
+ const imgUrl = getImageUrl(doc, siteUrl);
1197
+ if (imgUrl)
1198
+ ld.image = imgUrl;
1199
+ ld.author = { "@type": "Organization", name, url: siteUrl };
1200
+ const publisher = { "@type": "Organization", name };
1201
+ if (publisherLogo !== undefined) {
1202
+ if (publisherLogo !== null)
1203
+ publisher.logo = { "@type": "ImageObject", url: publisherLogo };
1204
+ }
1205
+ ld.publisher = publisher;
1206
+ return ld;
1207
+ }
1208
+ function buildBreadcrumbsLd({
1209
+ items,
1210
+ currentUrl
1211
+ }) {
1212
+ return {
1213
+ "@context": "https://schema.org",
1214
+ "@type": "BreadcrumbList",
1215
+ itemListElement: items.map((item, index) => ({
1216
+ "@type": "ListItem",
1217
+ position: index + 1,
1218
+ name: item.label,
1219
+ item: index === items.length - 1 ? currentUrl : item.url
1220
+ }))
1221
+ };
1222
+ }
1223
+ function buildOrganizationLd({
1224
+ siteUrl,
1225
+ name,
1226
+ logo,
1227
+ sameAs
1228
+ }) {
1229
+ const org = {
1230
+ "@context": "https://schema.org",
1231
+ "@type": "Organization",
1232
+ "@id": `${siteUrl}#organization`,
1233
+ url: siteUrl,
1234
+ ...name && { name },
1235
+ ...logo && { logo: { "@type": "ImageObject", url: logo } },
1236
+ ...sameAs && sameAs.length > 0 && { sameAs }
1237
+ };
1238
+ return org;
1239
+ }
1240
+
1241
+ // src/render/metadata/slug.ts
1242
+ var SLUG_NESTED_DIVIDER = "_";
1243
+ function segmentsToStoredSlug(segments, nested) {
1244
+ if (!Array.isArray(segments))
1245
+ return segments;
1246
+ if (nested)
1247
+ return segments.join(SLUG_NESTED_DIVIDER);
1248
+ return segments[0] ?? "";
1249
+ }
1250
+ function segmentsToUrlPath(segments, nested) {
1251
+ if (!Array.isArray(segments))
1252
+ return "/" + segments;
1253
+ if (nested)
1254
+ return "/" + segments.join("/");
1255
+ return "/" + (segments[0] ?? "");
1256
+ }
1257
+ function storedSlugToSegments(storedSlug, nested) {
1258
+ if (nested)
1259
+ return storedSlug.split(SLUG_NESTED_DIVIDER);
1260
+ return storedSlug;
1261
+ }
1262
+ function buildCanonicalUrl({
1263
+ siteUrl,
1264
+ locale,
1265
+ urlPrefix,
1266
+ urlPath
1267
+ }) {
1268
+ const trimmedPrefix = urlPrefix.replace(/^\/|\/$/g, "");
1269
+ const prefixSegment = trimmedPrefix ? `/${trimmedPrefix}` : "";
1270
+ return `${siteUrl}/${locale}${prefixSegment}${urlPath}`;
1271
+ }
1272
+ function getUrlPath(segments, nested, homeSlug) {
1273
+ const urlPath = segmentsToUrlPath(segments, nested);
1274
+ if (nested && !Array.isArray(segments)) {
1275
+ if (segments === homeSlug)
1276
+ return "/";
1277
+ } else if (nested && Array.isArray(segments)) {
1278
+ const stored = segments.join(SLUG_NESTED_DIVIDER);
1279
+ if (stored === homeSlug)
1280
+ return "/";
1281
+ }
1282
+ return urlPath;
1283
+ }
1284
+
1285
+ // src/render/blocks/renderBlocks.tsx
1286
+ import { jsx as jsx3, Fragment } from "react/jsx-runtime";
1287
+ var RenderBlocks = ({
1288
+ blocks,
1289
+ blockProps,
1290
+ config,
1291
+ importMap,
1292
+ locale,
1293
+ searchParams
1294
+ }) => {
1295
+ if (!blocks || !Array.isArray(blocks) || blocks.length === 0)
1296
+ return null;
1297
+ const rendered = [];
1298
+ for (let i = 0;i < blocks.length; i++) {
1299
+ const block = blocks[i];
1300
+ const { blockType } = block;
1301
+ const importMapPath = config.admin?.dependencies?.[blockType]?.path ?? generateImportName("block", blockType);
1302
+ const Block = getFromImportMap(importMapPath, importMap);
1303
+ if (!Block) {
1304
+ console.warn(`No block found for type: ${blockType}, config.admin?.dependencies?.[blockType]: ${config.admin?.dependencies?.[blockType]}`);
1305
+ continue;
1306
+ }
1307
+ rendered.push(/* @__PURE__ */ jsx3(Block, {
1308
+ index: i,
1309
+ ...blockProps,
1310
+ ...block,
1311
+ locale,
1312
+ searchParams
1313
+ }, i));
1314
+ }
1315
+ return /* @__PURE__ */ jsx3(Fragment, {
1316
+ children: rendered
1317
+ });
1318
+ };
1319
+
1320
+ // src/data/seed/createBaseSeed.ts
1321
+ var simpleRichText = (text) => ({
1322
+ root: {
1323
+ type: "root",
1324
+ format: "",
1325
+ indent: 0,
1326
+ version: 1,
1327
+ direction: "ltr",
1328
+ children: [
1329
+ {
1330
+ type: "paragraph",
1331
+ format: "",
1332
+ indent: 0,
1333
+ version: 1,
1334
+ direction: "ltr",
1335
+ textFormat: 0,
1336
+ children: [
1337
+ { mode: "normal", text, type: "text", style: "", detail: 0, format: 0, version: 1 }
1338
+ ]
1339
+ }
1340
+ ]
1341
+ }
1342
+ });
1343
+ async function createBaseSeed(payload, options = {}) {
1344
+ const localization = payload.config.localization;
1345
+ const defaultLocale = options.defaultLocale ?? (typeof localization === "object" && localization ? typeof localization.defaultLocale === "string" ? localization.defaultLocale : "en" : "en");
1346
+ const configLocales = typeof localization === "object" && localization ? (localization.locales ?? []).map((l) => typeof l === "string" ? l : l.code) : [];
1347
+ const locales = options.locales ?? (configLocales.length > 0 ? configLocales : [defaultLocale]);
1348
+ const result = { users: [], categories: [], pages: [], posts: [] };
1349
+ const pagesCollection = payload.collections["pages"];
1350
+ if (!pagesCollection) {
1351
+ throw new Error("createBaseSeed: no `pages` collection registered with this payload instance");
1352
+ }
1353
+ const findBlocksField = (fields) => {
1354
+ for (const f of fields) {
1355
+ if (f.name === "blocks" && Array.isArray(f.blocks))
1356
+ return f;
1357
+ if (Array.isArray(f.fields)) {
1358
+ const found = findBlocksField(f.fields);
1359
+ if (found)
1360
+ return found;
1361
+ }
1362
+ if (Array.isArray(f.tabs)) {
1363
+ for (const t of f.tabs) {
1364
+ if (Array.isArray(t.fields)) {
1365
+ const found = findBlocksField(t.fields);
1366
+ if (found)
1367
+ return found;
1368
+ }
1369
+ }
1370
+ }
1371
+ }
1372
+ return;
1373
+ };
1374
+ const layoutField = findBlocksField(pagesCollection.config.fields);
1375
+ const validBlockSlugs = new Set((layoutField?.blocks ?? []).map((b) => b.slug));
1376
+ for (const page of options.pages ?? []) {
1377
+ for (const block of page.blocks ?? []) {
1378
+ const slug = block.blockType;
1379
+ if (!slug) {
1380
+ throw new Error(`createBaseSeed: page "${page.slug}" has a block without blockType`);
1381
+ }
1382
+ if (!validBlockSlugs.has(slug)) {
1383
+ throw new Error(`createBaseSeed: page "${page.slug}" references unknown block slug "${slug}". Allowed: ${[...validBlockSlugs].join(", ")}`);
1384
+ }
1385
+ }
1386
+ }
1387
+ if (options.dryRun)
1388
+ return result;
1389
+ for (const user of options.users ?? [{ email: "dev@payloadcms.com", password: "test", name: "Dev User" }]) {
1390
+ const existing = await payload.find({
1391
+ collection: "users",
1392
+ where: { email: { equals: user.email } },
1393
+ limit: 1,
1394
+ overrideAccess: true
1395
+ });
1396
+ let id;
1397
+ if (existing.docs.length > 0) {
1398
+ id = existing.docs[0].id;
1399
+ } else {
1400
+ const created = await payload.create({
1401
+ collection: "users",
1402
+ data: { email: user.email, password: user.password ?? "test", name: user.name ?? "" },
1403
+ overrideAccess: true
1404
+ });
1405
+ id = created.id;
1406
+ }
1407
+ result.users.push({ id, email: user.email });
1408
+ }
1409
+ for (const cat of options.categories ?? []) {
1410
+ const slug = cat.slug ?? cat.title.toLowerCase().replace(/\s+/g, "-");
1411
+ const existing = await payload.find({
1412
+ collection: "categories",
1413
+ where: { title: { equals: cat.title } },
1414
+ limit: 1,
1415
+ overrideAccess: true
1416
+ });
1417
+ let id;
1418
+ if (existing.docs.length > 0) {
1419
+ id = existing.docs[0].id;
1420
+ } else {
1421
+ const created = await payload.create({
1422
+ collection: "categories",
1423
+ data: { title: cat.title, slug },
1424
+ overrideAccess: true
1425
+ });
1426
+ id = created.id;
1427
+ }
1428
+ result.categories.push({ id, title: cat.title, slug });
1429
+ }
1430
+ for (const page of options.pages ?? []) {
1431
+ const existing = await payload.find({
1432
+ collection: "pages",
1433
+ where: { slug: { equals: page.slug } },
1434
+ limit: 1,
1435
+ overrideAccess: true
1436
+ });
1437
+ const data = {
1438
+ slug: page.slug,
1439
+ title: { ...page.title },
1440
+ blocks: page.blocks ?? [],
1441
+ publishedAt: page.publishedAt ?? new Date().toISOString(),
1442
+ _status: page.status === "draft" ? "draft" : "published"
1443
+ };
1444
+ if (page.meta)
1445
+ data.meta = { ...page.meta };
1446
+ let id;
1447
+ if (existing.docs.length === 0) {
1448
+ const created = await payload.create({
1449
+ collection: "pages",
1450
+ data,
1451
+ overrideAccess: true,
1452
+ draft: page.status === "draft"
1453
+ });
1454
+ id = created.id;
1455
+ } else {
1456
+ id = existing.docs[0].id;
1457
+ await payload.update({
1458
+ collection: "pages",
1459
+ id,
1460
+ data,
1461
+ overrideAccess: true,
1462
+ draft: page.status === "draft"
1463
+ });
1464
+ }
1465
+ for (const locale of locales)
1466
+ result.pages.push({ id, slug: page.slug, locale });
1467
+ }
1468
+ for (const post of options.posts ?? []) {
1469
+ const existing = await payload.find({
1470
+ collection: "posts",
1471
+ where: { slug: { equals: post.slug } },
1472
+ limit: 1,
1473
+ overrideAccess: true
1474
+ });
1475
+ const data = {
1476
+ slug: post.slug,
1477
+ title: { ...post.title },
1478
+ ...post.excerpt ? { excerpt: { ...post.excerpt } } : {},
1479
+ content: post.content ?? simpleRichText("Hello world"),
1480
+ publishedAt: post.publishedAt ?? new Date().toISOString(),
1481
+ authors: result.users.length > 0 ? [result.users[0].id] : [],
1482
+ _status: post.status === "draft" ? "draft" : "published"
1483
+ };
1484
+ let id;
1485
+ if (existing.docs.length === 0) {
1486
+ const created = await payload.create({
1487
+ collection: "posts",
1488
+ data,
1489
+ overrideAccess: true,
1490
+ draft: post.status === "draft"
1491
+ });
1492
+ id = created.id;
1493
+ } else {
1494
+ id = existing.docs[0].id;
1495
+ await payload.update({
1496
+ collection: "posts",
1497
+ id,
1498
+ data,
1499
+ overrideAccess: true,
1500
+ draft: post.status === "draft"
1501
+ });
1502
+ }
1503
+ for (const locale of locales)
1504
+ result.posts.push({ id, slug: post.slug, locale });
1505
+ }
1506
+ return result;
1507
+ }
1508
+
1509
+ // src/data/test/createTestPayload.ts
1510
+ import { sqliteAdapter } from "@payloadcms/db-sqlite";
1511
+ import { flattenAllFields, getPayload as getPayload2, inMemoryKVAdapter } from "payload";
1512
+ import path from "node:path";
1513
+ import { fileURLToPath } from "node:url";
1514
+ async function createTestPayload(options = {}) {
1515
+ const filename = fileURLToPath(import.meta.url);
1516
+ const dirname = path.dirname(filename);
1517
+ const databaseFile = options.databaseFile ?? path.join(dirname, `.test-${Date.now()}-${Math.random().toString(36).slice(2)}.db`);
1518
+ const locales = options.locales ?? ["en", "uk"];
1519
+ const defaultLocale = locales[0] ?? "en";
1520
+ const blocks = options.blocks ?? [];
1521
+ const { withWWWConfig } = createWWWConfig({ locales: [...locales], blocks });
1522
+ const config = await withWWWConfig({
1523
+ admin: { user: "users" },
1524
+ blocks: [],
1525
+ collections: [
1526
+ {
1527
+ slug: "posts",
1528
+ access: { read: () => true },
1529
+ fields: [{ name: "title", type: "text" }]
1530
+ }
1531
+ ],
1532
+ globals: [],
1533
+ db: sqliteAdapter({
1534
+ client: { url: `file:${databaseFile}` },
1535
+ push: false
1536
+ }),
1537
+ secret: "test-secret-do-not-use-in-prod",
1538
+ sharp: (await import("sharp")).default,
1539
+ editor: {},
1540
+ localization: { locales: [...locales], defaultLocale },
1541
+ kv: inMemoryKVAdapter(),
1542
+ typescript: { outputFile: "./payload-types.ts" }
1543
+ });
1544
+ const registered = new Set([
1545
+ ...(config.collections ?? []).map((c) => c.slug),
1546
+ ...(config.globals ?? []).map((g) => g.slug)
1547
+ ]);
1548
+ const findMissing = (fields) => {
1549
+ const out = [];
1550
+ const walk = (f) => {
1551
+ if (Array.isArray(f)) {
1552
+ for (const child of f)
1553
+ walk(child);
1554
+ return;
1555
+ }
1556
+ if (f.relationTo) {
1557
+ const rels = Array.isArray(f.relationTo) ? f.relationTo : [f.relationTo];
1558
+ for (const r of rels) {
1559
+ if (typeof r === "string" && !registered.has(r))
1560
+ out.push(r);
1561
+ }
1562
+ }
1563
+ if (Array.isArray(f.fields))
1564
+ walk(f.fields);
1565
+ };
1566
+ for (const f of fields)
1567
+ walk(f);
1568
+ return out;
1569
+ };
1570
+ for (const c of config.collections ?? []) {
1571
+ const missing = findMissing(c.fields ?? []);
1572
+ if (missing.length)
1573
+ console.log("collection", c.slug, "missing relations:", missing);
1574
+ }
1575
+ for (const g of config.globals ?? []) {
1576
+ const missing = findMissing(g.fields ?? []);
1577
+ if (missing.length)
1578
+ console.log("global", g.slug, "missing relations:", missing);
1579
+ }
1580
+ for (const c of config.collections ?? []) {
1581
+ if (c.fields) {
1582
+ c.flattenedFields = flattenAllFields({ fields: c.fields });
1583
+ }
1584
+ if (c.upload === undefined)
1585
+ c.upload = false;
1586
+ c.sanitizedIndexes = c.sanitizedIndexes ?? [];
1587
+ c.polymorphicJoins = c.polymorphicJoins ?? [];
1588
+ if (options.overridePagesVersions && c.slug === "pages") {
1589
+ c.versions = false;
1590
+ }
1591
+ }
1592
+ for (const g of config.globals ?? []) {
1593
+ if (g.fields) {
1594
+ g.flattenedFields = flattenAllFields({ fields: g.fields });
1595
+ }
1596
+ g.sanitizedIndexes = g.sanitizedIndexes ?? [];
1597
+ }
1598
+ const payload = await getPayload2({ config });
1599
+ let destroyed = false;
1600
+ const destroy = async () => {
1601
+ if (destroyed)
1602
+ return;
1603
+ destroyed = true;
1604
+ try {
1605
+ await payload.destroy();
1606
+ } catch {}
1607
+ };
1608
+ return { payload, databaseFile, destroy };
1609
+ }
1610
+
1611
+ // src/render/pages/createCollectionPageExports.tsx
1612
+ import"server-only";
1613
+ import { Suspense } from "react";
1614
+ import { RichText } from "@payloadcms/richtext-lexical/react";
1615
+
1616
+ // src/render/pages/PagesPage.tsx
1617
+ import { jsx as jsx4, Fragment as Fragment2 } from "react/jsx-runtime";
1618
+ async function PagesPage({ doc, ...props }) {
1619
+ if (!doc)
1620
+ return /* @__PURE__ */ jsx4(Fragment2, {});
1621
+ const blocks = doc.blocks ?? [];
1622
+ return /* @__PURE__ */ jsx4(Fragment2, {
1623
+ children: /* @__PURE__ */ jsx4(RenderBlocks, {
1624
+ blocks,
1625
+ ...props
1626
+ })
1627
+ });
1628
+ }
1629
+
1630
+ // src/render/pages/createCollectionPageExports.tsx
1631
+ import { jsx as jsx7, jsxs as jsxs3, Fragment as Fragment4 } from "react/jsx-runtime";
1632
+ var HOME_SLUG = "";
1633
+ function createCollectionPageExports({
1634
+ slug = "pages",
1635
+ config: configPromise,
1636
+ routing,
1637
+ importMap: importMapArg,
1638
+ renderPath
1639
+ }, deps, options = {}) {
1640
+ const importMap = importMapArg ?? {};
1641
+ const { jsonLd: jsonLdOption = true, changefreq = "weekly", priority = 0.5, websiteName } = options;
1642
+ const {
1643
+ getServerSideURL,
1644
+ generateMeta,
1645
+ metadataType: metadataTypeOverride,
1646
+ showcase: showcaseOption,
1647
+ homeExtras
1648
+ } = deps;
1649
+ const showcaseEnabled = showcaseOption?.enabled === true;
1650
+ const { metadataHeading, jsonLdHeading } = showcaseOption ?? {};
1651
+ const locales = routing.locales;
1652
+ const defaultLocale = routing.defaultLocale;
1653
+ const metadataType = metadataTypeOverride ?? (slug === POSTS_SLUG ? "article" : "website");
1654
+ const defaultRenderPath = slug === POSTS_SLUG ? POSTS_RENDER_PATH : PAGES_RENDER_PATH;
1655
+ const localePrefixMode = typeof routing.localePrefix === "string" ? routing.localePrefix : routing.localePrefix?.mode ?? "always";
1656
+ const buildLocalePath = (locale, storedSlug) => {
1657
+ const urlPath = getUrlPath(storedSlug, false, HOME_SLUG);
1658
+ if (localePrefixMode === "never")
1659
+ return urlPath;
1660
+ if (localePrefixMode === "as-needed" && locale === defaultLocale)
1661
+ return urlPath;
1662
+ return `/${locale}${urlPath}`;
1663
+ };
1664
+ async function fetchDoc(locale, storedSlug, draft = false) {
1665
+ return queryDocBySlug({
1666
+ collectionSlug: slug,
1667
+ slug: storedSlug,
1668
+ locale,
1669
+ draft,
1670
+ config: configPromise
1671
+ });
1672
+ }
1673
+ async function resolveHreflangAlternates(locale, storedSlug) {
1674
+ const siteUrl = getServerSideURL();
1675
+ const urlPath = buildLocalePath(locale, storedSlug);
1676
+ const canonical = `${siteUrl}${urlPath}`;
1677
+ const languages = await buildHreflangAlternates({
1678
+ siteUrl,
1679
+ locale,
1680
+ urlPrefix: "",
1681
+ storedSlug,
1682
+ nested: false,
1683
+ homeSlug: HOME_SLUG,
1684
+ defaultLocale,
1685
+ locales,
1686
+ localePrefix: localePrefixMode,
1687
+ queryAllLocaleSlugs: (s, l) => queryAllLocaleSlugs({ collectionSlug: slug, slug: s, slugField: "slug", locale: l, config: configPromise })
1688
+ });
1689
+ const alternates = {};
1690
+ for (const [key, url] of Object.entries(languages)) {
1691
+ alternates[key] = url;
1692
+ }
1693
+ return { alternates, canonical };
1694
+ }
1695
+ const default_ = async (props) => {
1696
+ const { slug: rawSlugSegments, locale: incomingLocale } = await props.params ?? {};
1697
+ const slugSegments = Array.isArray(rawSlugSegments) ? rawSlugSegments : [];
1698
+ const locale = typeof incomingLocale === "string" ? incomingLocale : defaultLocale;
1699
+ if (!locales.includes(locale)) {
1700
+ const { notFound } = await import("next/navigation");
1701
+ notFound();
1702
+ }
1703
+ const { setRequestLocale } = await import("next-intl/server");
1704
+ setRequestLocale(locale);
1705
+ const { draftMode } = await import("next/headers");
1706
+ const { isEnabled: draft } = await draftMode();
1707
+ const storedSlug = segmentsToStoredSlug(slugSegments, false);
1708
+ const doc = await fetchDoc(locale, storedSlug, draft);
1709
+ if (!doc) {
1710
+ const { notFound } = await import("next/navigation");
1711
+ notFound();
1712
+ }
1713
+ const cfg = await configPromise;
1714
+ const collectionCustomPath = cfg.collections.find((c) => c.slug === slug)?.custom?.path;
1715
+ const effectivePath = renderPath ?? collectionCustomPath ?? defaultRenderPath;
1716
+ const render = effectivePath === PAGES_RENDER_PATH ? /* @__PURE__ */ jsx7(PagesPage, {
1717
+ doc,
1718
+ importMap,
1719
+ config: cfg,
1720
+ locale
1721
+ }) : effectivePath === POSTS_RENDER_PATH ? doc ? await renderPostBody(doc, locale) : null : renderCollectionModule(cfg.collections, slug, importMap, {
1722
+ ...props,
1723
+ config: cfg,
1724
+ locale,
1725
+ searchParams: props.searchParams,
1726
+ doc
1727
+ });
1728
+ const jsonLdNodes = doc ? await generateJsonLd(slugSegments, doc, locale) : [];
1729
+ const { alternates: hreflangAlternates, canonical } = await resolveHreflangAlternates(locale, storedSlug);
1730
+ console.log("render", { render, doc });
1731
+ const inner = /* @__PURE__ */ jsxs3(Fragment4, {
1732
+ children: [
1733
+ jsonLdNodes.map(({ id, schema }) => /* @__PURE__ */ jsx7("script", {
1734
+ type: "application/ld+json",
1735
+ dangerouslySetInnerHTML: { __html: JSON.stringify(schema) }
1736
+ }, id)),
1737
+ render,
1738
+ draft ? (() => {
1739
+ const ResolvedListener = importMap?.[LIVE_PREVIEW_LISTENER_PATH];
1740
+ if (!ResolvedListener)
1741
+ return null;
1742
+ return /* @__PURE__ */ jsx7(Suspense, {
1743
+ fallback: null,
1744
+ children: /* @__PURE__ */ jsx7(ResolvedListener, {})
1745
+ });
1746
+ })() : null,
1747
+ storedSlug === HOME_SLUG && homeExtras ? await homeExtras({ locale, doc }) : null
1748
+ ]
1749
+ });
1750
+ if (!showcaseEnabled || !doc)
1751
+ return inner;
1752
+ const { PageShowcase: PageShowcase2 } = await Promise.resolve().then(() => (init_PageShowcase(), exports_PageShowcase));
1753
+ const { LocaleSwitcher: LocaleSwitcher2 } = await Promise.resolve().then(() => (init_LocaleSwitcher(), exports_LocaleSwitcher));
1754
+ const meta = await generateMeta({
1755
+ doc,
1756
+ url: canonical,
1757
+ type: metadataType,
1758
+ locale
1759
+ });
1760
+ return /* @__PURE__ */ jsx7(PageShowcase2, {
1761
+ metadata: meta,
1762
+ metadataHeading,
1763
+ jsonLdHeading,
1764
+ jsonLd: jsonLdNodes,
1765
+ localeSwitcher: /* @__PURE__ */ jsx7(LocaleSwitcher2, {
1766
+ currentLocale: locale,
1767
+ hreflangAlternates,
1768
+ labels: routing.labels
1769
+ }),
1770
+ children: inner
1771
+ });
1772
+ };
1773
+ async function generateMetadata(props) {
1774
+ const cfg = await configPromise;
1775
+ const { slug: rawSlugSegments, locale: incomingLocale } = await props.params ?? {};
1776
+ const slugSegments = Array.isArray(rawSlugSegments) ? rawSlugSegments : [];
1777
+ const locale = typeof incomingLocale === "string" ? incomingLocale : defaultLocale;
1778
+ if (!locales.includes(locale))
1779
+ return { title: "Not found", robots: { index: false, follow: false } };
1780
+ const storedSlug = segmentsToStoredSlug(slugSegments, false);
1781
+ const doc = await fetchDoc(locale, storedSlug);
1782
+ if (!doc)
1783
+ return { title: "Not found", robots: { index: false, follow: false } };
1784
+ const collection = cfg.collections.find((c) => c.slug === slug);
1785
+ if (!collection)
1786
+ return {};
1787
+ const { canonical, alternates } = await resolveHreflangAlternates(locale, storedSlug);
1788
+ const meta = await generateMeta({
1789
+ doc,
1790
+ url: canonical,
1791
+ type: metadataType,
1792
+ locale
1793
+ });
1794
+ meta.alternates = {
1795
+ canonical,
1796
+ languages: Object.keys(alternates).length ? alternates : undefined
1797
+ };
1798
+ return meta;
1799
+ }
1800
+ async function generateJsonLd(slugSegments, doc, locale) {
1801
+ if (jsonLdOption === false || !doc)
1802
+ return [];
1803
+ const siteUrl = getServerSideURL();
1804
+ const storedSlug = segmentsToStoredSlug(slugSegments, false);
1805
+ const urlPath = buildLocalePath(locale, storedSlug);
1806
+ const canonical = `${siteUrl}${urlPath}`;
1807
+ const entries = Array.isArray(jsonLdOption) ? jsonLdOption : metadataType === "article" ? [{ type: "article" }] : [{ type: "website" }];
1808
+ const outputs = [];
1809
+ for (const entry of entries) {
1810
+ const id = entry.id ?? `jsonld-${entry.type}-${outputs.length}`;
1811
+ let schema = null;
1812
+ switch (entry.type) {
1813
+ case "article": {
1814
+ const articleOpts = {
1815
+ doc,
1816
+ url: canonical,
1817
+ locale,
1818
+ siteUrl,
1819
+ type: entry.schemaType ?? "BlogPosting"
1820
+ };
1821
+ if (entry.publisherName !== undefined)
1822
+ articleOpts.publisherName = entry.publisherName;
1823
+ if (entry.publisherLogo !== undefined)
1824
+ articleOpts.publisherLogo = entry.publisherLogo;
1825
+ schema = buildArticleLd(articleOpts);
1826
+ break;
1827
+ }
1828
+ case "website": {
1829
+ schema = {
1830
+ "@context": "https://schema.org",
1831
+ "@type": "WebSite",
1832
+ "@id": `${siteUrl}#website`,
1833
+ url: siteUrl,
1834
+ name: entry.name ?? websiteName ?? new URL(siteUrl).hostname,
1835
+ ...entry.alternateName ? { alternateName: entry.alternateName } : {},
1836
+ inLanguage: locale
1837
+ };
1838
+ break;
1839
+ }
1840
+ case "organization": {
1841
+ schema = buildOrganizationLd({
1842
+ siteUrl,
1843
+ name: entry.name,
1844
+ logo: entry.logo,
1845
+ sameAs: entry.sameAs
1846
+ });
1847
+ break;
1848
+ }
1849
+ case "breadcrumbs": {
1850
+ let items = entry.items ?? [];
1851
+ if (!items.length && entry.buildItems)
1852
+ items = entry.buildItems(doc, canonical);
1853
+ if (items.length > 0)
1854
+ schema = buildBreadcrumbsLd({ items, currentUrl: canonical });
1855
+ break;
1856
+ }
1857
+ case "custom": {
1858
+ schema = entry.build({ doc, url: canonical, locale, siteUrl });
1859
+ break;
1860
+ }
1861
+ }
1862
+ if (schema)
1863
+ outputs.push({ id, schema });
1864
+ }
1865
+ return outputs;
1866
+ }
1867
+ async function generateStaticParams() {
1868
+ const params = [];
1869
+ for (const locale of locales) {
1870
+ const docs = await queryAllDocs({ collectionSlug: slug, slugField: "slug", locale, config: configPromise });
1871
+ for (const doc of docs) {
1872
+ const slugVal = doc.slug;
1873
+ if (typeof slugVal !== "string" || slugVal === "")
1874
+ continue;
1875
+ const segments = storedSlugToSegments(slugVal, false);
1876
+ params.push({ slug: Array.isArray(segments) ? segments : [segments], locale });
1877
+ }
1878
+ }
1879
+ return params;
1880
+ }
1881
+ async function generateSitemap() {
1882
+ const docs = await queryAllDocs({
1883
+ collectionSlug: slug,
1884
+ slugField: "slug",
1885
+ locale: defaultLocale,
1886
+ config: configPromise
1887
+ });
1888
+ const siteUrl = getServerSideURL().replace(/\/$/, "");
1889
+ const urls = [];
1890
+ for (const doc of docs) {
1891
+ const slugVal = doc.slug;
1892
+ if (typeof slugVal !== "string" || slugVal === "")
1893
+ continue;
1894
+ for (const locale of locales) {
1895
+ const urlPath = buildLocalePath(locale, slugVal);
1896
+ const updatedAt = doc.updatedAt;
1897
+ const lastmod = typeof updatedAt === "string" ? new Date(updatedAt).toISOString() : undefined;
1898
+ urls.push({ url: `${siteUrl}${urlPath}`, lastModified: lastmod, changeFrequency: changefreq, priority });
1899
+ }
1900
+ }
1901
+ return urls;
1902
+ }
1903
+ return {
1904
+ default: default_,
1905
+ generateMetadata,
1906
+ generateStaticParams,
1907
+ generateSitemap,
1908
+ generateJsonLd
1909
+ };
1910
+ }
1911
+ function addCollectionsToSitemap(exports) {
1912
+ async function buildSitemap() {
1913
+ const all = await Promise.all(exports.map((e) => e.generateSitemap()));
1914
+ return all.flat();
1915
+ }
1916
+ return { default: buildSitemap, generateSitemap: buildSitemap };
1917
+ }
1918
+ async function renderPostBody(doc, locale) {
1919
+ const typedDoc = doc;
1920
+ const title = typedDoc.title ?? "";
1921
+ const excerpt = typedDoc.excerpt ?? null;
1922
+ const content = typedDoc.content;
1923
+ return /* @__PURE__ */ jsxs3("article", {
1924
+ className: "posts-page prose prose-neutral dark:prose-invert mx-auto max-w-3xl py-10",
1925
+ children: [
1926
+ /* @__PURE__ */ jsxs3("header", {
1927
+ className: "posts-page__header not-prose mb-8",
1928
+ children: [
1929
+ /* @__PURE__ */ jsx7("h1", {
1930
+ className: "posts-page__title text-4xl font-semibold tracking-tight",
1931
+ children: title
1932
+ }),
1933
+ excerpt ? /* @__PURE__ */ jsx7("p", {
1934
+ className: "posts-page__excerpt mt-3 text-lg text-muted-foreground",
1935
+ children: excerpt
1936
+ }) : null
1937
+ ]
1938
+ }),
1939
+ content ? /* @__PURE__ */ jsx7("div", {
1940
+ className: "posts-page__content",
1941
+ children: /* @__PURE__ */ jsx7(RichText, {
1942
+ data: content
1943
+ })
1944
+ }) : null
1945
+ ]
1946
+ });
1947
+ }
1948
+
1949
+ // src/render/pages/createStaticPageExports.tsx
1950
+ import"server-only";
1951
+ import { jsx as jsx8 } from "react/jsx-runtime";
1952
+ function createStaticPageExports({
1953
+ kind = "not-found",
1954
+ config: configPromise,
1955
+ importMap: importMapArg
1956
+ }) {
1957
+ const importMap = importMapArg ?? {};
1958
+ const default_ = async () => {
1959
+ const { getLocale } = await import("next-intl/server");
1960
+ const locale = await getLocale();
1961
+ const doc = await queryDocBySlug({
1962
+ collectionSlug: STATIC_PAGES_SLUG,
1963
+ slug: kind,
1964
+ slugField: "kind",
1965
+ locale,
1966
+ config: configPromise
1967
+ });
1968
+ if (!doc) {
1969
+ console.warn("[createStaticPageExports] !doc: STATIC_PAGES_SLUG=", STATIC_PAGES_SLUG, "slug:" + kind);
1970
+ return /* @__PURE__ */ jsx8("section", {
1971
+ children: /* @__PURE__ */ jsx8("h1", {
1972
+ children: "404"
1973
+ })
1974
+ });
1975
+ }
1976
+ const cfg = await configPromise;
1977
+ return /* @__PURE__ */ jsx8(PagesPage, {
1978
+ doc,
1979
+ locale,
1980
+ importMap,
1981
+ config: cfg
1982
+ });
1983
+ };
1984
+ return { default: default_ };
1985
+ }
1986
+
1987
+ // src/data/collections/previewPath.ts
1988
+ var collectionPrefixMap = {
1989
+ posts: "/posts",
1990
+ pages: ""
1991
+ };
1992
+ function generatePreviewPath({
1993
+ collection,
1994
+ slug
1995
+ }) {
1996
+ if (slug === undefined || slug === null)
1997
+ return null;
1998
+ const encodedSlug = encodeURIComponent(slug);
1999
+ const params = new URLSearchParams({
2000
+ path: `${collectionPrefixMap[collection] ?? ""}/${encodedSlug}`,
2001
+ previewSecret: process.env.PREVIEW_SECRET || ""
2002
+ });
2003
+ return `/next/preview?${params.toString()}`;
2004
+ }
2005
+
2006
+ // src/exports/server.ts
2007
+ var server_default = createWWWConfig;
2008
+ export {
2009
+ storedSlugToSegments,
2010
+ segmentsToUrlPath,
2011
+ segmentsToStoredSlug,
2012
+ renderGlobalModule,
2013
+ renderCollectionModule,
2014
+ queryGlobal,
2015
+ queryDocBySlug,
2016
+ queryAllLocaleSlugs,
2017
+ queryAllDocs,
2018
+ linkGroup,
2019
+ link,
2020
+ getUrlPath,
2021
+ getRenderModuleExports,
2022
+ getFromImportMap,
2023
+ getCachedGlobal,
2024
+ generatePreviewPath,
2025
+ generateImportName,
2026
+ server_default as default,
2027
+ createWWWConfig,
2028
+ createTestPayload,
2029
+ createStaticPagesCollection,
2030
+ createStaticPageExports,
2031
+ createRevalidatePageHooks,
2032
+ createRevalidateGlobalHook,
2033
+ createRevalidateCollectionHook,
2034
+ createPostsCollection,
2035
+ createPagesCollection,
2036
+ createHeaderGlobal,
2037
+ createFooterGlobal,
2038
+ createCollectionPageExports,
2039
+ createBaseSeed,
2040
+ buildOrganizationLd,
2041
+ buildHreflangAlternates,
2042
+ buildCanonicalUrl,
2043
+ buildBreadcrumbsLd,
2044
+ buildArticleLd,
2045
+ authenticatedOrPublished,
2046
+ authenticated,
2047
+ appearanceOptions,
2048
+ anyone,
2049
+ addCollectionsToSitemap,
2050
+ STATIC_PAGES_SLUG,
2051
+ RenderBlocks,
2052
+ POSTS_SLUG2 as POSTS_SLUG,
2053
+ PAGES_SLUG2 as PAGES_SLUG,
2054
+ HOME_PAGE_SLUG
2055
+ };