@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.
- package/README.md +317 -307
- package/dist/access.d.ts +2 -2
- package/dist/access.js +6 -30
- package/dist/blocks.d.ts +0 -10
- package/dist/blocks.js +8 -33
- package/dist/collections.d.ts +33 -225
- package/dist/collections.js +186 -661
- package/dist/config.d.ts +19 -105
- package/dist/config.js +263 -868
- package/dist/fields.d.ts +4 -46
- package/dist/fields.js +183 -73
- 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 -258
- package/dist/pages.d.ts +37 -319
- package/dist/pages.js +355 -973
- package/dist/render-pages.d.ts +69 -564
- package/dist/render-pages.js +476 -1502
- package/dist/sitemap.d.ts +10 -0
- package/dist/sitemap.js +324 -0
- package/dist/translator.js +0 -15
- package/dist/utils.d.ts +4 -12
- package/dist/utils.js +10 -56
- package/package.json +75 -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 -44
- package/dist/core-blocks.d.ts +0 -24
- package/dist/core-blocks.js +0 -89
- package/dist/core-fields.d.ts +0 -73
- package/dist/core-fields.js +0 -181
- package/dist/core-utils.d.ts +0 -16
- package/dist/core-utils.js +0 -73
- package/dist/data-collections.d.ts +0 -229
- package/dist/data-collections.js +0 -697
- 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 -1134
- package/dist/globals.d.ts +0 -69
- package/dist/globals.js +0 -259
- 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 -393
- package/dist/render-utils.d.ts +0 -166
- package/dist/render-utils.js +0 -401
- 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 -2265
- package/dist/test.d.ts +0 -30
- package/dist/test.js +0 -1134
- package/dist/with-www-config.d.ts +0 -108
- package/dist/with-www-config.js +0 -1030
package/dist/collections.js
CHANGED
|
@@ -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
|
-
//
|
|
19
|
-
var
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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 (
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
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
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
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/
|
|
252
|
-
var
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
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/
|
|
262
|
-
var
|
|
263
|
-
var
|
|
264
|
-
var
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
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/
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
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
|
-
|
|
371
|
-
|
|
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
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
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
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
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/
|
|
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
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
};
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
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
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
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
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
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
|
|
205
|
+
return doc?.[slugField2];
|
|
670
206
|
}
|
|
671
207
|
|
|
672
208
|
// src/exports/collections.ts
|
|
673
|
-
var
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
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
|
-
|
|
217
|
+
queryDoc,
|
|
687
218
|
collections_default as default,
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
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
|
};
|