@justanarthur/payload-www 0.3.4 → 1.0.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 +317 -307
  2. package/dist/access.d.ts +2 -2
  3. package/dist/access.js +6 -30
  4. package/dist/blocks.d.ts +0 -10
  5. package/dist/blocks.js +8 -33
  6. package/dist/collections.d.ts +33 -225
  7. package/dist/collections.js +186 -661
  8. package/dist/config.d.ts +19 -105
  9. package/dist/config.js +263 -868
  10. package/dist/fields.d.ts +4 -46
  11. package/dist/fields.js +183 -73
  12. package/dist/imagehash.js +0 -15
  13. package/dist/import-map-provider.d.ts +0 -16
  14. package/dist/import-map-provider.js +0 -15
  15. package/dist/metadata.d.ts +24 -89
  16. package/dist/metadata.js +123 -258
  17. package/dist/pages.d.ts +37 -319
  18. package/dist/pages.js +355 -973
  19. package/dist/render-pages.d.ts +69 -564
  20. package/dist/render-pages.js +476 -1502
  21. package/dist/sitemap.d.ts +10 -0
  22. package/dist/sitemap.js +324 -0
  23. package/dist/translator.js +0 -15
  24. package/dist/utils.d.ts +4 -12
  25. package/dist/utils.js +10 -56
  26. package/package.json +75 -178
  27. package/dist/components.d.ts +0 -6
  28. package/dist/components.js +0 -39
  29. package/dist/core-access.d.ts +0 -11
  30. package/dist/core-access.js +0 -44
  31. package/dist/core-blocks.d.ts +0 -24
  32. package/dist/core-blocks.js +0 -89
  33. package/dist/core-fields.d.ts +0 -73
  34. package/dist/core-fields.js +0 -181
  35. package/dist/core-utils.d.ts +0 -16
  36. package/dist/core-utils.js +0 -73
  37. package/dist/data-collections.d.ts +0 -229
  38. package/dist/data-collections.js +0 -697
  39. package/dist/data-seed.d.ts +0 -76
  40. package/dist/data-seed.js +0 -212
  41. package/dist/data-test.d.ts +0 -30
  42. package/dist/data-test.js +0 -1134
  43. package/dist/globals.d.ts +0 -69
  44. package/dist/globals.js +0 -259
  45. package/dist/hooks.d.ts +0 -108
  46. package/dist/hooks.js +0 -228
  47. package/dist/index.d.ts +0 -6
  48. package/dist/index.js +0 -39
  49. package/dist/render-components.d.ts +0 -42
  50. package/dist/render-components.js +0 -154
  51. package/dist/render-metadata.d.ts +0 -122
  52. package/dist/render-metadata.js +0 -393
  53. package/dist/render-utils.d.ts +0 -166
  54. package/dist/render-utils.js +0 -401
  55. package/dist/seed.d.ts +0 -76
  56. package/dist/seed.js +0 -212
  57. package/dist/server.d.ts +0 -980
  58. package/dist/server.js +0 -2265
  59. package/dist/test.d.ts +0 -30
  60. package/dist/test.js +0 -1134
  61. package/dist/with-www-config.d.ts +0 -108
  62. package/dist/with-www-config.js +0 -1030
@@ -1,697 +1,222 @@
1
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
2
 
18
- // src/core/access/index.ts
19
- var anyone = () => {
20
- console.log("[WWW] core/access:anyone -> true");
21
- return true;
22
- };
23
- var authenticated = ({ req: { user } }) => {
24
- const result = Boolean(user);
25
- console.log("[WWW] core/access:authenticated ->", result);
26
- return result;
27
- };
28
- var authenticatedOrPublished = ({ req: { user } }) => {
29
- if (user) {
30
- console.log("[WWW] core/access:authenticatedOrPublished -> true (authenticated)");
31
- return true;
32
- }
33
- console.log('[WWW] core/access:authenticatedOrPublished -> { _status: { equals: "published" } }');
34
- return { _status: { equals: "published" } };
35
- };
36
-
37
- // src/core/fields/slug.ts
38
- var FLAT_PATTERN = /^[a-z0-9-]+$/;
39
- var NESTED_PATTERN = /^[a-z0-9_-]+$/;
40
- var slugField = (options = {}) => {
41
- const { name = "slug", nested = false, localized = true } = options;
42
- const pattern = nested ? NESTED_PATTERN : FLAT_PATTERN;
43
- const invalidMessage = nested ? "Slug must be lowercase, with hyphens or the `_` nesting divider (no spaces or other special characters)" : "Slug must be lowercase, with hyphens (no spaces or special characters)";
44
- console.log("[WWW] core/fields:slugField options=", JSON.stringify({ name, nested, localized }));
45
- return {
46
- name,
47
- type: "text",
48
- required: true,
49
- unique: true,
50
- index: true,
51
- localized,
52
- admin: {
53
- position: "sidebar",
54
- ...nested ? { description: "Lowercase, hyphens for words. Use the `_` divider for nesting, e.g. `about_us` → `/about/us`." } : {}
55
- },
56
- validate: (value) => {
57
- if (typeof value !== "string")
58
- return "Slug must be a string";
59
- if (value !== "" && !pattern.test(value)) {
60
- console.warn("[WWW] core/fields:slugField invalid slug value=", JSON.stringify(value));
61
- return invalidMessage;
62
- }
63
- return true;
64
- }
65
- };
66
- };
67
-
68
- // src/render/_locale.ts
69
- function prefixFor(locale, defaultLocale, mode) {
70
- let result;
71
- if (mode === "never")
72
- result = "";
73
- else if (mode === "as-needed" && locale === defaultLocale)
74
- result = "";
75
- else
76
- result = `/${locale}`;
77
- console.log("[WWW] render/_locale:prefixFor locale=", locale, "default=", defaultLocale, "mode=", mode, "->", JSON.stringify(result));
78
- return result;
79
- }
80
- function resolveLocale(req) {
81
- if (!req || typeof req !== "object") {
82
- console.log('[WWW] render/_locale:resolveLocale -> "" (no req)');
83
- return "";
84
- }
85
- const r = req;
86
- if (typeof r.locale === "string" && r.locale.length > 0) {
87
- console.log("[WWW] render/_locale:resolveLocale ->", r.locale, "(from req.locale)");
88
- return r.locale;
89
- }
90
- const fallback = r.payload?.config?.localization?.defaultLocale;
91
- if (typeof fallback === "string" && fallback.length > 0) {
92
- console.log("[WWW] render/_locale:resolveLocale ->", fallback, "(from config.localization.defaultLocale)");
93
- return fallback;
94
- }
95
- console.log('[WWW] render/_locale:resolveLocale -> "" (no locale anywhere)');
96
- return "";
97
- }
98
- function allLocales(req) {
99
- if (!req || typeof req !== "object") {
100
- console.log("[WWW] render/_locale:allLocales -> [] (no req)");
101
- return [];
102
- }
103
- const r = req;
104
- const list = r.payload?.config?.localization?.locales;
105
- if (!Array.isArray(list) || list.length === 0) {
106
- console.log("[WWW] render/_locale:allLocales -> [] (no locales declared)");
107
- return [];
108
- }
109
- const out = [];
110
- for (const entry of list) {
111
- if (typeof entry === "string" && entry.length > 0) {
112
- out.push(entry);
113
- } else if (entry && typeof entry === "object" && "code" in entry) {
114
- const code = entry.code;
115
- if (typeof code === "string" && code.length > 0)
116
- out.push(code);
3
+ // package.json
4
+ var name = "@justanarthur/payload-www";
5
+
6
+ // src/collections/hooks/populatePublishedAt.ts
7
+ var populatePublishedAt = ({ data, operation, req }) => {
8
+ if (operation === "create" || operation === "update") {
9
+ if (req.data && !req.data.publishedAt) {
10
+ const now = new Date;
11
+ return {
12
+ ...data,
13
+ publishedAt: now
14
+ };
117
15
  }
118
16
  }
119
- console.log("[WWW] render/_locale:allLocales ->", JSON.stringify(out));
120
- return out;
121
- }
122
-
123
- // src/render/hooks/_shared.ts
124
- var cachePromise = null;
125
- function nextCacheImport() {
126
- return cachePromise ??= import("next/cache");
127
- }
128
- function shouldSkipRevalidate(context) {
129
- const skip = Boolean(context?.disableRevalidate);
130
- if (skip)
131
- console.log("[WWW] render/hooks:_shared:shouldSkipRevalidate -> skip");
132
- return skip;
133
- }
134
- async function safeRevalidatePath(payload, path) {
135
- console.log("[WWW] render/hooks:_shared:safeRevalidatePath path=", path);
136
- try {
137
- const { revalidatePath } = await nextCacheImport();
138
- revalidatePath(path);
139
- } catch (error) {
140
- console.error("[WWW] render/hooks:_shared:safeRevalidatePath failed path=", path, "err=", String(error));
141
- payload.logger.error(`revalidatePath("${path}") failed: ${String(error)}`);
142
- }
143
- }
144
- async function safeRevalidateTag(payload, tag, profile = "max") {
145
- console.log("[WWW] render/hooks:_shared:safeRevalidateTag tag=", tag, "profile=", profile);
146
- try {
147
- const { revalidateTag } = await nextCacheImport();
148
- revalidateTag(tag, profile);
149
- } catch (error) {
150
- console.error("[WWW] render/hooks:_shared:safeRevalidateTag failed tag=", tag, "err=", String(error));
151
- payload.logger.error(`revalidateTag("${tag}") failed: ${String(error)}`);
152
- }
153
- }
154
-
155
- // src/render/hooks/revalidateCollection.ts
156
- function createRevalidateCollectionHook(options) {
157
- const {
158
- collectionSlug,
159
- urlPathPrefix = "",
160
- sitemapTag,
161
- localePrefix: modeOption,
162
- defaultLocale: defaultLocaleOption,
163
- pathMode = "url"
164
- } = options;
165
- const resolvedSitemapTag = sitemapTag === false ? false : sitemapTag ?? `${collectionSlug}-sitemap`;
166
- console.log("[WWW] render/hooks:createRevalidateCollectionHook collectionSlug=", collectionSlug, "urlPathPrefix=", urlPathPrefix, "sitemapTag=", resolvedSitemapTag, "pathMode=", pathMode);
167
- const resolveDefaults = (req) => {
168
- const mode = modeOption ?? "always";
169
- const defaultLocale = defaultLocaleOption ?? req?.payload?.config?.localization?.defaultLocale ?? "";
170
- return { mode, defaultLocale };
171
- };
172
- const localesToFanOut = (req) => {
173
- const all = allLocales(req);
174
- if (all.length > 0)
175
- return all;
176
- const single = resolveLocale(req);
177
- return single ? [single] : [];
178
- };
179
- const collectionPath = (slug, locale, mode, defaultLocale) => {
180
- const prefix = prefixFor(locale, defaultLocale, mode);
181
- if (!slug)
182
- return `${prefix}${urlPathPrefix}` || "/";
183
- return `${prefix}${urlPathPrefix}/${slug}`;
184
- };
185
- const fanOutPaths = async (payload, req, slug, label) => {
186
- const { mode, defaultLocale } = resolveDefaults(req);
187
- const locales = localesToFanOut(req);
188
- for (const locale of locales) {
189
- const path = collectionPath(slug, locale, mode, defaultLocale);
190
- payload.logger.info?.(`${label} ${path}`);
191
- await safeRevalidatePath(payload, path);
192
- }
193
- };
194
- const fireCollectionTags = async (payload, docId, req) => {
195
- console.log("[WWW] render/hooks:fireCollectionTags collectionSlug=", collectionSlug, "docId=", docId);
196
- if (typeof docId === "string" || typeof docId === "number") {
197
- await safeRevalidateTag(payload, `collection_${collectionSlug}_${docId}`);
198
- }
199
- if (resolvedSitemapTag !== false) {
200
- await safeRevalidateTag(payload, resolvedSitemapTag);
201
- }
202
- };
203
- const afterChange = async ({ doc, previousDoc, req }) => {
204
- if (shouldSkipRevalidate(req.context))
205
- return doc;
206
- const { payload } = req;
207
- const typed = doc;
208
- const prev = previousDoc;
209
- console.log("[WWW] render/hooks:afterChange collectionSlug=", collectionSlug, "id=", typed.id, "slug=", typed.slug, "prevSlug=", prev?.slug);
210
- const isPublished = typed._status === "published";
211
- const wasPublished = prev?._status === "published";
212
- const prevSlugIsString = typeof prev?.slug === "string";
213
- const slugChanged = prevSlugIsString && prev?.slug !== typed.slug;
214
- if (isPublished) {
215
- if (pathMode !== "tag-only") {
216
- await fanOutPaths(payload, req, typed.slug, `Revalidating ${collectionSlug} at path:`);
17
+ return data;
18
+ };
19
+
20
+ // src/collections/hooks/createRevalidateCollectionGlobalHook.ts
21
+ import { revalidateTag } from "next/cache";
22
+ function createRevalidateCollectionGlobalHook() {
23
+ const afterChangeDeleteHook = async ({ doc, req, ...args }) => {
24
+ const previousDoc = "previousDoc" in args ? args.previousDoc : null, locale = req.locale;
25
+ function revalidate(args2) {
26
+ try {
27
+ revalidateTag(createCollectionCacheKey({ ...args2, locale }), "max");
28
+ } catch (error) {
29
+ const msg = error instanceof Error ? error.message : String(error);
30
+ if (msg.includes("static generation store missing"))
31
+ return;
32
+ console.error(error);
217
33
  }
218
- await fireCollectionTags(payload, typed.id, req);
219
34
  }
220
- if (wasPublished && (!isPublished || slugChanged)) {
221
- if (pathMode !== "tag-only") {
222
- await fanOutPaths(payload, req, prev?.slug, `Revalidating old ${collectionSlug} at path:`);
223
- }
224
- await fireCollectionTags(payload, typed.id, req);
35
+ if ("collection" in args) {
36
+ [
37
+ doc && doc._status !== "draft" && doc.slug,
38
+ previousDoc && previousDoc._status === "published" && previousDoc.slug
39
+ ].filter((slug) => slug !== undefined && slug !== false).map((slug) => revalidate({ collectionSlug: args.collection.slug, slug }));
40
+ } else {
41
+ revalidate({ globalSlug: args.global.slug });
225
42
  }
226
43
  return doc;
227
44
  };
228
- const afterDelete = async ({ doc, req }) => {
229
- if (shouldSkipRevalidate(req.context))
230
- return doc ?? null;
231
- const { payload } = req;
232
- const typed = doc;
233
- console.log("[WWW] render/hooks:afterDelete collectionSlug=", collectionSlug, "id=", typed?.id, "slug=", typed?.slug);
234
- if (pathMode !== "tag-only") {
235
- await fanOutPaths(payload, req, typed?.slug, `Revalidating deleted ${collectionSlug} at path:`);
236
- }
237
- await fireCollectionTags(payload, typed?.id, req);
238
- return doc ?? null;
239
- };
240
- return { afterChange, afterDelete };
45
+ return { afterChange: afterChangeDeleteHook, afterDelete: afterChangeDeleteHook };
46
+ }
47
+ function createCollectionCacheKey(args) {
48
+ return `${"globalSlug" in args ? args.globalSlug : args.collectionSlug + args.slug}_${args.locale}`;
241
49
  }
242
- var createRevalidatePageHooks = (opts = {}) => {
243
- console.log("[WWW] render/hooks:createRevalidatePageHooks (deprecated alias) opts=", JSON.stringify(opts));
244
- return createRevalidateCollectionHook({
245
- collectionSlug: "pages",
246
- urlPathPrefix: "",
247
- ...opts
248
- });
249
- };
250
50
 
251
- // src/config/constants.ts
252
- var PAGES_RENDER_PATH = "@justanarthur/payload-www/render-pages#PagesPage";
253
- var POSTS_RENDER_PATH = "@justanarthur/payload-www/render-pages#PostsPage";
254
- var HEADER_RENDER_PATH = "@justanarthur/payload-www/render-pages#HeaderPage";
255
- var FOOTER_RENDER_PATH = "@justanarthur/payload-www/render-pages#FooterPage";
256
- var LIVE_PREVIEW_LISTENER_PATH = "@justanarthur/payload-www/render-components#LivePreviewListener";
257
- var PAGES_SLUG = "pages";
258
- var POSTS_SLUG = "posts";
259
- var STATIC_PAGES_SLUG = "staticPages";
51
+ // src/collections/fields/slug.ts
52
+ var slugField = () => ({
53
+ name: "slug",
54
+ type: "text",
55
+ required: true,
56
+ unique: true,
57
+ index: true,
58
+ localized: true,
59
+ admin: {
60
+ position: "sidebar",
61
+ description: "Lowercase, hyphens for words. Use the `_` divider for nesting, e.g. `about_us` → `/about/us`."
62
+ },
63
+ validate: (value) => {
64
+ if (typeof value !== "string")
65
+ return "Slug must be a string";
66
+ if (value !== "" && !/^[a-z0-9_-]+$/.test(value))
67
+ return "Slug must be lowercase, with hyphens (no spaces or special characters).";
68
+ return true;
69
+ }
70
+ });
260
71
 
261
- // src/data/collections/Pages/index.ts
262
- var HOME_PAGE_SLUG = "";
263
- var PAGES_SLUG2 = PAGES_SLUG;
264
- var createPagesCollection = (blocks, options = {}) => {
265
- const {
266
- renderPath = PAGES_RENDER_PATH,
267
- slug: collectionSlug = PAGES_SLUG2,
268
- localePrefix,
269
- defaultLocale,
270
- nested = false
271
- } = options;
272
- const baseFields = [
273
- {
274
- name: "title",
275
- type: "text",
276
- required: true,
277
- localized: true
278
- },
279
- {
280
- type: "tabs",
281
- tabs: [
282
- {
283
- fields: [
284
- {
285
- name: "blocks",
286
- type: "blocks",
287
- blocks,
288
- required: true,
289
- admin: { initCollapsed: true }
290
- }
291
- ],
292
- label: "Content"
293
- }
294
- ]
295
- },
296
- {
297
- name: "publishedAt",
298
- type: "date",
299
- admin: { position: "sidebar" }
300
- },
301
- slugField({ nested })
302
- ];
303
- const { afterChange: revalidateAfterChange, afterDelete: revalidateAfterDelete } = createRevalidateCollectionHook({
304
- collectionSlug,
305
- urlPathPrefix: "",
306
- localePrefix,
307
- defaultLocale
308
- });
309
- return {
310
- slug: collectionSlug,
311
- custom: { path: renderPath },
312
- access: {
313
- create: authenticated,
314
- delete: authenticated,
315
- read: authenticatedOrPublished,
316
- update: authenticated
317
- },
318
- fields: baseFields,
319
- hooks: {
320
- afterChange: [revalidateAfterChange],
321
- afterDelete: [revalidateAfterDelete]
322
- },
323
- versions: { drafts: { autosave: { interval: 1000 } } }
324
- };
72
+ // src/collections/access/index.ts
73
+ var anyone = () => true;
74
+ var authenticated = ({ req: { user } }) => Boolean(user);
75
+ var authenticatedOrPublished = ({ req: { user } }) => {
76
+ if (user)
77
+ return true;
78
+ return { _status: { equals: "published" } };
325
79
  };
326
80
 
327
- // src/data/collections/Posts/index.ts
328
- var POSTS_SLUG2 = "posts";
329
- var createPostsCollection = (options = {}) => {
330
- const {
331
- renderPath = POSTS_RENDER_PATH,
332
- slug: collectionSlug = POSTS_SLUG2,
333
- localePrefix,
334
- defaultLocale
335
- } = options;
336
- const baseFields = [
337
- {
338
- name: "title",
339
- type: "text",
340
- required: true,
341
- localized: true
342
- },
343
- {
344
- name: "excerpt",
345
- type: "text",
346
- required: false,
347
- localized: true
348
- },
349
- {
350
- name: "content",
351
- type: "richText",
352
- required: false,
353
- localized: true
354
- },
355
- {
356
- name: "publishedAt",
357
- type: "date",
358
- admin: { position: "sidebar" }
359
- },
360
- slugField()
361
- ];
362
- const { afterChange, afterDelete } = createRevalidateCollectionHook({
363
- collectionSlug,
364
- urlPathPrefix: "/posts",
365
- localePrefix,
366
- defaultLocale
367
- });
81
+ // src/collections/createWWWCollectionGlobal.ts
82
+ function createWWWCollectionGlobal(fields, {
83
+ slug: collectionSlug,
84
+ renderPath,
85
+ isGlobalConfig = false,
86
+ isDraft = true
87
+ }) {
368
88
  return {
369
89
  slug: collectionSlug,
370
- custom: { path: renderPath },
371
- access: {
372
- create: authenticated,
373
- delete: authenticated,
374
- read: authenticatedOrPublished,
375
- update: authenticated
376
- },
377
- fields: baseFields,
378
- hooks: {
379
- afterChange: [afterChange],
380
- afterDelete: [afterDelete]
381
- },
382
- versions: { drafts: { autosave: { interval: 1000 } } }
383
- };
384
- };
385
-
386
- // src/data/collections/StaticPages/index.ts
387
- var createStaticPagesCollection = (blocks) => {
388
- const { afterChange, afterDelete } = createRevalidateCollectionHook({
389
- collectionSlug: STATIC_PAGES_SLUG,
390
- pathMode: "tag-only",
391
- sitemapTag: "static-pages"
392
- });
393
- return {
394
- slug: STATIC_PAGES_SLUG,
395
- dbName: "sp",
396
- admin: { group: "System", useAsTitle: "title" },
397
- access: {
398
- create: authenticated,
399
- delete: authenticated,
400
- read: authenticatedOrPublished,
401
- update: authenticated
402
- },
403
- fields: [
404
- {
405
- name: "kind",
406
- type: "select",
407
- required: true,
408
- unique: true,
409
- index: true,
410
- options: [
411
- { label: "Not found (404)", value: "not-found" },
412
- { label: "Server error (500)", value: "server-error" },
413
- { label: "Search empty", value: "search-empty" },
414
- { label: "Offline", value: "offline" }
415
- ],
416
- admin: {
417
- position: "sidebar",
418
- description: "Which system page this row powers. One row per kind."
419
- }
420
- },
421
- {
422
- name: "title",
423
- type: "text",
424
- required: true,
425
- localized: true,
426
- admin: { description: "Admin-only label. Not rendered." }
427
- },
428
- {
429
- type: "tabs",
430
- tabs: [
431
- {
432
- fields: [
433
- {
434
- name: "blocks",
435
- type: "blocks",
436
- localized: true,
437
- blocks,
438
- admin: { initCollapsed: true },
439
- dbName: "b"
440
- }
441
- ],
442
- label: "Content"
443
- }
444
- ]
445
- },
90
+ fields: isGlobalConfig ? fields : [
91
+ slugField(),
446
92
  {
447
93
  name: "publishedAt",
448
94
  type: "date",
449
95
  admin: { position: "sidebar" }
450
- }
96
+ },
97
+ ...fields
451
98
  ],
452
- hooks: {
453
- afterChange: [afterChange],
454
- afterDelete: [afterDelete]
455
- },
456
- versions: { drafts: { autosave: { interval: 1000 } } }
457
- };
458
- };
459
-
460
- // src/core/fields/link.ts
461
- var appearanceOptions = {
462
- default: { label: "Default", value: "default" },
463
- outline: { label: "Outline", value: "outline" }
464
- };
465
- var link = (options = {}) => {
466
- const {
467
- appearances,
468
- disableLabel = false,
469
- relationTo = [PAGES_SLUG],
470
- localized = false,
471
- overrides = {},
472
- extraFields = []
473
- } = options;
474
- console.log("[WWW] core/fields:link options=", JSON.stringify({
475
- appearances: appearances === false ? false : appearances ?? "default-set",
476
- disableLabel,
477
- relationTo,
478
- localized,
479
- extraFieldsCount: extraFields.length
480
- }));
481
- const result = {
482
- name: "link",
483
- type: "group",
484
- admin: { hideGutter: true },
485
- fields: [
486
- {
487
- type: "row",
488
- fields: [
489
- {
490
- name: "type",
491
- type: "radio",
492
- admin: { layout: "horizontal", width: "50%" },
493
- defaultValue: "reference",
494
- options: [
495
- { label: "Internal link", value: "reference" },
496
- { label: "Custom URL", value: "custom" }
497
- ]
498
- },
499
- {
500
- name: "newTab",
501
- type: "checkbox",
502
- admin: { style: { alignSelf: "flex-end" }, width: "50%" },
503
- label: "Open in new tab"
504
- }
505
- ]
506
- }
507
- ]
508
- };
509
- const linkTypes = [
510
- {
511
- name: "reference",
512
- type: "relationship",
513
- admin: { condition: (_, siblingData) => siblingData?.type === "reference" },
514
- label: "Document to link to",
515
- relationTo,
516
- required: true,
517
- localized
99
+ custom: { [name]: { path: renderPath } },
100
+ access: {
101
+ create: authenticated,
102
+ delete: authenticated,
103
+ read: isDraft ? authenticatedOrPublished : anyone,
104
+ update: authenticated
518
105
  },
519
- {
520
- name: "url",
521
- type: "text",
522
- admin: { condition: (_, siblingData) => siblingData?.type === "custom" },
523
- label: "Custom URL",
524
- required: true,
525
- localized
106
+ hooks: (() => {
107
+ const { afterChange, afterDelete } = createRevalidateCollectionGlobalHook();
108
+ return {
109
+ afterChange: [afterChange],
110
+ beforeChange: [populatePublishedAt],
111
+ afterDelete: [afterDelete]
112
+ };
113
+ })(),
114
+ ...isDraft && {
115
+ versions: { drafts: { autosave: { interval: 3000 } } }
526
116
  }
527
- ];
528
- if (!disableLabel) {
529
- result.fields.push({
530
- type: "row",
531
- fields: [
532
- ...linkTypes,
533
- {
534
- name: "label",
535
- type: "text",
536
- admin: { width: "50%" },
537
- label: "Label",
538
- required: true,
539
- localized
540
- }
541
- ]
542
- });
543
- } else {
544
- result.fields = [...result.fields, ...linkTypes];
545
- }
546
- if (appearances !== false) {
547
- const opts = appearances ? appearances.map((a) => appearanceOptions[a]) : [appearanceOptions.default, appearanceOptions.outline];
548
- result.fields.push({
549
- name: "appearance",
550
- type: "select",
551
- admin: { description: "Choose how the link should be rendered." },
552
- defaultValue: "default",
553
- options: opts
554
- });
555
- }
556
- if (extraFields.length) {
557
- result.fields.push(...extraFields);
558
- }
559
- console.log("[WWW] core/fields:link built fieldsCount=", result.fields.length);
560
- return { ...result, ...overrides };
561
- };
562
-
563
- // src/render/hooks/revalidateGlobal.ts
564
- function createRevalidateGlobalHook(slug) {
565
- console.log("[WWW] render/hooks:createRevalidateGlobalHook slug=", slug);
566
- return async ({ doc, req: { payload, context, locale } }) => {
567
- if (shouldSkipRevalidate(context))
568
- return doc;
569
- const tags = [`global_${slug}`, `global_${slug}_${locale}`];
570
- console.log("[WWW] render/hooks:revalidateGlobal slug=", slug, "locale=", locale, "tags=", JSON.stringify(tags));
571
- payload.logger.info?.(`Revalidating global: ${tags.join(", ")}`);
572
- for (const tag of tags) {
573
- await safeRevalidateTag(payload, tag);
574
- }
575
- return doc;
576
117
  };
577
118
  }
578
119
 
579
- // src/data/collections/globals/Header/config.ts
580
- var createHeaderGlobal = (options = {}) => {
581
- const {
582
- renderPath = HEADER_RENDER_PATH,
583
- linkRelationTo = [PAGES_SLUG],
584
- navColumnLinkFields = [],
585
- navItemLinkFields = []
586
- } = options;
587
- const navColumnBlock = {
588
- slug: "navColumn",
589
- fields: [
590
- { name: "title", type: "text", required: true, localized: true },
591
- { name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navColumnLinkFields })] }
592
- ]
593
- };
594
- const navItemBlock = {
595
- slug: "navItem",
596
- fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navItemLinkFields })]
597
- };
598
- return {
599
- slug: "header",
600
- custom: { path: renderPath },
601
- access: { read: () => true },
602
- fields: [
603
- {
604
- name: "nav",
605
- type: "blocks",
606
- required: true,
607
- blocks: [navColumnBlock, navItemBlock]
608
- }
609
- ],
610
- hooks: {
611
- afterChange: [createRevalidateGlobalHook("header")]
612
- }
613
- };
614
- };
615
-
616
- // src/data/collections/globals/Footer/config.ts
617
- var createFooterGlobal = (options = {}) => {
618
- const {
619
- renderPath = FOOTER_RENDER_PATH,
620
- linkRelationTo = [PAGES_SLUG],
621
- navColumnLinkFields = [],
622
- navItemLinkFields = []
623
- } = options;
624
- const navColumnBlock = {
625
- slug: "navColumn",
626
- fields: [
627
- { name: "title", type: "text", required: true, localized: true },
628
- { name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navColumnLinkFields })] }
629
- ]
630
- };
631
- const navItemBlock = {
632
- slug: "navItem",
633
- fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navItemLinkFields })]
634
- };
635
- return {
636
- slug: "footer",
637
- custom: { path: renderPath },
638
- access: { read: () => true },
639
- fields: [
640
- {
641
- name: "nav",
642
- type: "blocks",
643
- required: true,
644
- blocks: [navColumnBlock, navItemBlock]
645
- }
646
- ],
647
- hooks: {
648
- afterChange: [createRevalidateGlobalHook("footer")]
120
+ // src/render/metadata/query.ts
121
+ import { getPayload } from "payload";
122
+ async function withUnstableCache(keyParts, tags, fn) {
123
+ const { unstable_cache } = await import("next/cache");
124
+ return unstable_cache(fn, keyParts.map(String), { tags })();
125
+ }
126
+ async function queryDoc(args, { config: configPromise }) {
127
+ return withUnstableCache(Object.values(args), [createCollectionCacheKey(args)], async () => {
128
+ if ("globalSlug" in args)
129
+ return queryGlobal({ ...args, config: configPromise });
130
+ else
131
+ return queryDocBySlug({ ...args, config: configPromise });
132
+ });
133
+ }
134
+ async function queryDocBySlug({
135
+ collectionSlug,
136
+ slug,
137
+ slugField: slugField2 = "slug",
138
+ locale,
139
+ draft = false,
140
+ config
141
+ }) {
142
+ return withUnstableCache([collectionSlug, slug, locale, draft], [createCollectionCacheKey({ collectionSlug, slug, locale })], async () => {
143
+ const payload = await getPayload({ config });
144
+ const result = await payload.find({
145
+ collection: collectionSlug,
146
+ draft,
147
+ limit: 1,
148
+ pagination: false,
149
+ overrideAccess: draft,
150
+ where: { [slugField2]: { equals: slug } },
151
+ locale
152
+ });
153
+ return result.docs?.[0] ?? null;
154
+ });
155
+ }
156
+ async function queryGlobal({
157
+ globalSlug,
158
+ locale,
159
+ draft = false,
160
+ config
161
+ }) {
162
+ return withUnstableCache([globalSlug, locale, draft], [createCollectionCacheKey({ globalSlug, locale })], async () => {
163
+ const payload = await getPayload({ config });
164
+ try {
165
+ return await payload.findGlobal({ slug: globalSlug, draft, locale });
166
+ } catch (error) {
167
+ console.warn("[WWW] queryGlobal failed", { globalSlug, locale, error: String(error) });
168
+ return null;
649
169
  }
650
- };
651
- };
652
-
653
- // src/data/collections/previewPath.ts
654
- var collectionPrefixMap = {
655
- posts: "/posts",
656
- pages: ""
657
- };
658
- function generatePreviewPath({
659
- collection,
660
- slug
170
+ });
171
+ }
172
+ async function queryAllDocs({
173
+ collectionSlug,
174
+ slugField: slugField2 = "slug",
175
+ locale,
176
+ config
177
+ }) {
178
+ return withUnstableCache([collectionSlug, slugField2, locale], [createCollectionCacheKey({ collectionSlug, slug: "__all__", locale })], async () => {
179
+ const payload = await getPayload({ config });
180
+ const result = await payload.find({
181
+ collection: collectionSlug,
182
+ draft: false,
183
+ limit: 1000,
184
+ pagination: false,
185
+ overrideAccess: false,
186
+ select: { [slugField2]: true },
187
+ locale
188
+ });
189
+ return result.docs ?? [];
190
+ });
191
+ }
192
+ async function queryAllLocaleSlugs({
193
+ collectionSlug,
194
+ id,
195
+ slugField: slugField2 = "slug",
196
+ config
661
197
  }) {
662
- if (slug === undefined || slug === null)
663
- return null;
664
- const encodedSlug = encodeURIComponent(slug);
665
- const params = new URLSearchParams({
666
- path: `${collectionPrefixMap[collection] ?? ""}/${encodedSlug}`,
667
- previewSecret: process.env.PREVIEW_SECRET || ""
198
+ const payload = await getPayload({ config });
199
+ const doc = await payload.findByID({
200
+ collection: collectionSlug,
201
+ id,
202
+ locale: "all",
203
+ select: { [slugField2]: true }
668
204
  });
669
- return `/next/preview?${params.toString()}`;
205
+ return doc?.[slugField2];
670
206
  }
671
207
 
672
208
  // src/exports/collections.ts
673
- var collections_default = {
674
- createPagesCollection,
675
- createPostsCollection,
676
- createStaticPagesCollection,
677
- createHeaderGlobal,
678
- createFooterGlobal,
679
- generatePreviewPath,
680
- HOME_PAGE_SLUG,
681
- PAGES_SLUG: PAGES_SLUG2,
682
- POSTS_SLUG: POSTS_SLUG2,
683
- STATIC_PAGES_SLUG
209
+ var collections = {
210
+ createWWWCollectionGlobal,
211
+ createRevalidateCollectionGlobalHook,
212
+ createCollectionCacheKey,
213
+ queryDoc
684
214
  };
215
+ var collections_default = collections;
685
216
  export {
686
- generatePreviewPath,
217
+ queryDoc,
687
218
  collections_default as default,
688
- createStaticPagesCollection,
689
- createPostsCollection,
690
- createPagesCollection,
691
- createHeaderGlobal,
692
- createFooterGlobal,
693
- STATIC_PAGES_SLUG,
694
- POSTS_SLUG2 as POSTS_SLUG,
695
- PAGES_SLUG2 as PAGES_SLUG,
696
- HOME_PAGE_SLUG
219
+ createWWWCollectionGlobal,
220
+ createRevalidateCollectionGlobalHook,
221
+ createCollectionCacheKey
697
222
  };