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