@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/config.js
CHANGED
|
@@ -1,463 +1,185 @@
|
|
|
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
|
-
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
|
-
};
|
|
3
|
+
// package.json
|
|
4
|
+
var name = "@justanarthur/payload-www";
|
|
36
5
|
|
|
37
|
-
// src/
|
|
38
|
-
|
|
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
|
-
};
|
|
6
|
+
// src/createWWWConfig.ts
|
|
7
|
+
import openAIResolver from "@justanarthur/payload-plugin-translator/resolvers/openAI";
|
|
67
8
|
|
|
68
|
-
// src/
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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);
|
|
9
|
+
// src/collections/hooks/populatePublishedAt.ts
|
|
10
|
+
var populatePublishedAt = ({ data, operation, req }) => {
|
|
11
|
+
if (operation === "create" || operation === "update") {
|
|
12
|
+
if (req.data && !req.data.publishedAt) {
|
|
13
|
+
const now = new Date;
|
|
14
|
+
return {
|
|
15
|
+
...data,
|
|
16
|
+
publishedAt: now
|
|
17
|
+
};
|
|
117
18
|
}
|
|
118
19
|
}
|
|
119
|
-
|
|
120
|
-
|
|
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
|
-
}
|
|
20
|
+
return data;
|
|
21
|
+
};
|
|
154
22
|
|
|
155
|
-
// src/
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
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:`);
|
|
23
|
+
// src/collections/hooks/createRevalidateCollectionGlobalHook.ts
|
|
24
|
+
import { revalidateTag } from "next/cache";
|
|
25
|
+
function createRevalidateCollectionGlobalHook() {
|
|
26
|
+
const afterChangeDeleteHook = async ({ doc, req, ...args }) => {
|
|
27
|
+
const previousDoc = "previousDoc" in args ? args.previousDoc : null, locale = req.locale;
|
|
28
|
+
function revalidate(args2) {
|
|
29
|
+
try {
|
|
30
|
+
revalidateTag(createCollectionCacheKey({ ...args2, locale }), "max");
|
|
31
|
+
} catch (error) {
|
|
32
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
33
|
+
if (msg.includes("static generation store missing"))
|
|
34
|
+
return;
|
|
35
|
+
console.error(error);
|
|
217
36
|
}
|
|
218
|
-
await fireCollectionTags(payload, typed.id, req);
|
|
219
37
|
}
|
|
220
|
-
if (
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
38
|
+
if ("collection" in args) {
|
|
39
|
+
[
|
|
40
|
+
doc && doc._status !== "draft" && doc.slug,
|
|
41
|
+
previousDoc && previousDoc._status === "published" && previousDoc.slug
|
|
42
|
+
].filter((slug) => slug !== undefined && slug !== false).map((slug) => revalidate({ collectionSlug: args.collection.slug, slug }));
|
|
43
|
+
} else {
|
|
44
|
+
revalidate({ globalSlug: args.global.slug });
|
|
225
45
|
}
|
|
226
46
|
return doc;
|
|
227
47
|
};
|
|
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 };
|
|
48
|
+
return { afterChange: afterChangeDeleteHook, afterDelete: afterChangeDeleteHook };
|
|
49
|
+
}
|
|
50
|
+
function createCollectionCacheKey(args) {
|
|
51
|
+
return `${"globalSlug" in args ? args.globalSlug : args.collectionSlug + args.slug}_${args.locale}`;
|
|
241
52
|
}
|
|
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
53
|
|
|
251
|
-
// src/
|
|
252
|
-
var
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
54
|
+
// src/collections/fields/slug.ts
|
|
55
|
+
var slugField = () => ({
|
|
56
|
+
name: "slug",
|
|
57
|
+
type: "text",
|
|
58
|
+
required: true,
|
|
59
|
+
unique: true,
|
|
60
|
+
index: true,
|
|
61
|
+
localized: true,
|
|
62
|
+
admin: {
|
|
63
|
+
position: "sidebar",
|
|
64
|
+
description: "Lowercase, hyphens for words. Use the `_` divider for nesting, e.g. `about_us` → `/about/us`."
|
|
65
|
+
},
|
|
66
|
+
validate: (value) => {
|
|
67
|
+
if (typeof value !== "string")
|
|
68
|
+
return "Slug must be a string";
|
|
69
|
+
if (value !== "" && !/^[a-z0-9_-]+$/.test(value))
|
|
70
|
+
return "Slug must be lowercase, with hyphens (no spaces or special characters).";
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
});
|
|
260
74
|
|
|
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
|
-
};
|
|
75
|
+
// src/collections/access/index.ts
|
|
76
|
+
var anyone = () => true;
|
|
77
|
+
var authenticated = ({ req: { user } }) => Boolean(user);
|
|
78
|
+
var authenticatedOrPublished = ({ req: { user } }) => {
|
|
79
|
+
if (user)
|
|
80
|
+
return true;
|
|
81
|
+
return { _status: { equals: "published" } };
|
|
325
82
|
};
|
|
326
83
|
|
|
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
|
-
});
|
|
84
|
+
// src/collections/createWWWCollectionGlobal.ts
|
|
85
|
+
function createWWWCollectionGlobal(fields, {
|
|
86
|
+
slug: collectionSlug,
|
|
87
|
+
renderPath,
|
|
88
|
+
isGlobalConfig = false,
|
|
89
|
+
isDraft = true
|
|
90
|
+
}) {
|
|
368
91
|
return {
|
|
369
92
|
slug: collectionSlug,
|
|
370
|
-
|
|
93
|
+
fields: isGlobalConfig ? fields : [
|
|
94
|
+
slugField(),
|
|
95
|
+
{
|
|
96
|
+
name: "publishedAt",
|
|
97
|
+
type: "date",
|
|
98
|
+
admin: { position: "sidebar" }
|
|
99
|
+
},
|
|
100
|
+
...fields
|
|
101
|
+
],
|
|
102
|
+
custom: { [name]: { path: renderPath } },
|
|
371
103
|
access: {
|
|
372
104
|
create: authenticated,
|
|
373
105
|
delete: authenticated,
|
|
374
|
-
read: authenticatedOrPublished,
|
|
106
|
+
read: isDraft ? authenticatedOrPublished : anyone,
|
|
375
107
|
update: authenticated
|
|
376
108
|
},
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
109
|
+
hooks: (() => {
|
|
110
|
+
const { afterChange, afterDelete } = createRevalidateCollectionGlobalHook();
|
|
111
|
+
return {
|
|
112
|
+
afterChange: [afterChange],
|
|
113
|
+
beforeChange: [populatePublishedAt],
|
|
114
|
+
afterDelete: [afterDelete]
|
|
115
|
+
};
|
|
116
|
+
})(),
|
|
117
|
+
...isDraft && {
|
|
118
|
+
versions: { drafts: { autosave: { interval: 3000 } } }
|
|
119
|
+
}
|
|
383
120
|
};
|
|
384
|
-
}
|
|
121
|
+
}
|
|
385
122
|
|
|
386
|
-
// src/
|
|
387
|
-
var
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
admin: { description: "Admin-only label. Not rendered." }
|
|
427
|
-
},
|
|
123
|
+
// src/collections/createPostsCollection.ts
|
|
124
|
+
var POSTS_SLUG = "posts";
|
|
125
|
+
var POSTS_RENDER_PATH = "@justanarthur/payload-www/render-pages#PostsPage";
|
|
126
|
+
var createPostsCollection = () => createWWWCollectionGlobal([
|
|
127
|
+
{
|
|
128
|
+
name: "title",
|
|
129
|
+
type: "text",
|
|
130
|
+
required: true,
|
|
131
|
+
localized: true
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
name: "excerpt",
|
|
135
|
+
type: "text",
|
|
136
|
+
required: false,
|
|
137
|
+
localized: true
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
name: "content",
|
|
141
|
+
type: "richText",
|
|
142
|
+
required: false,
|
|
143
|
+
localized: true
|
|
144
|
+
}
|
|
145
|
+
], {
|
|
146
|
+
slug: POSTS_SLUG,
|
|
147
|
+
renderPath: POSTS_RENDER_PATH
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
// src/collections/createPagesCollection.ts
|
|
151
|
+
var PAGES_SLUG = "pages";
|
|
152
|
+
var PAGES_RENDER_PATH = "@justanarthur/payload-www/render-pages#PagesPage";
|
|
153
|
+
var createPagesCollection = (blocks) => createWWWCollectionGlobal([
|
|
154
|
+
{
|
|
155
|
+
name: "title",
|
|
156
|
+
type: "text",
|
|
157
|
+
required: true,
|
|
158
|
+
localized: true
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
type: "tabs",
|
|
162
|
+
tabs: [
|
|
428
163
|
{
|
|
429
|
-
|
|
430
|
-
tabs: [
|
|
164
|
+
fields: [
|
|
431
165
|
{
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
blocks,
|
|
438
|
-
admin: { initCollapsed: true },
|
|
439
|
-
dbName: "b"
|
|
440
|
-
}
|
|
441
|
-
],
|
|
442
|
-
label: "Content"
|
|
166
|
+
name: "blocks",
|
|
167
|
+
type: "blocks",
|
|
168
|
+
blocks,
|
|
169
|
+
required: true,
|
|
170
|
+
admin: { initCollapsed: true }
|
|
443
171
|
}
|
|
444
|
-
]
|
|
445
|
-
|
|
446
|
-
{
|
|
447
|
-
name: "publishedAt",
|
|
448
|
-
type: "date",
|
|
449
|
-
admin: { position: "sidebar" }
|
|
172
|
+
],
|
|
173
|
+
label: "Content"
|
|
450
174
|
}
|
|
451
|
-
]
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
};
|
|
458
|
-
};
|
|
175
|
+
]
|
|
176
|
+
}
|
|
177
|
+
], {
|
|
178
|
+
slug: PAGES_SLUG,
|
|
179
|
+
renderPath: PAGES_RENDER_PATH
|
|
180
|
+
});
|
|
459
181
|
|
|
460
|
-
// src/
|
|
182
|
+
// src/collections/fields/link.ts
|
|
461
183
|
var appearanceOptions = {
|
|
462
184
|
default: { label: "Default", value: "default" },
|
|
463
185
|
outline: { label: "Outline", value: "outline" }
|
|
@@ -466,18 +188,11 @@ var link = (options = {}) => {
|
|
|
466
188
|
const {
|
|
467
189
|
appearances,
|
|
468
190
|
disableLabel = false,
|
|
469
|
-
relationTo = [PAGES_SLUG],
|
|
470
|
-
localized =
|
|
191
|
+
relationTo = [PAGES_SLUG, POSTS_SLUG],
|
|
192
|
+
localized = true,
|
|
471
193
|
overrides = {},
|
|
472
194
|
extraFields = []
|
|
473
195
|
} = 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
196
|
const result = {
|
|
482
197
|
name: "link",
|
|
483
198
|
type: "group",
|
|
@@ -556,460 +271,133 @@ var link = (options = {}) => {
|
|
|
556
271
|
if (extraFields.length) {
|
|
557
272
|
result.fields.push(...extraFields);
|
|
558
273
|
}
|
|
559
|
-
console.log("[WWW] core/fields:link built fieldsCount=", result.fields.length);
|
|
560
274
|
return { ...result, ...overrides };
|
|
561
275
|
};
|
|
562
276
|
|
|
563
|
-
// src/
|
|
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
|
-
{ 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")]
|
|
649
|
-
}
|
|
650
|
-
};
|
|
651
|
-
};
|
|
652
|
-
|
|
653
|
-
// src/config/createWWWConfig.ts
|
|
654
|
-
import openAIResolver from "@justanarthur/payload-plugin-translator/resolvers/openAI";
|
|
655
|
-
|
|
656
|
-
// src/render/preview/createPreviewHandler.ts
|
|
657
|
-
function createPreviewHandler(options) {
|
|
658
|
-
const { getServerSideURL: _getServerSideURL, secret, enableDraftMode = true } = options;
|
|
659
|
-
return async function GET(req) {
|
|
660
|
-
const { draftMode } = await import("next/headers");
|
|
661
|
-
const { redirect } = await import("next/navigation");
|
|
662
|
-
const url = new URL(req.url);
|
|
663
|
-
const path = url.searchParams.get("path") ?? "/";
|
|
664
|
-
const previewSecret = url.searchParams.get("previewSecret");
|
|
665
|
-
console.log("[WWW] render/preview:createPreviewHandler:GET path=", path, "hasSecret=", Boolean(previewSecret), "enableDraftMode=", enableDraftMode);
|
|
666
|
-
if (!previewSecret || previewSecret !== secret) {
|
|
667
|
-
console.warn("[WWW] render/preview:createPreviewHandler:GET invalid preview secret (401)");
|
|
668
|
-
return new Response("Invalid preview secret", { status: 401 });
|
|
669
|
-
}
|
|
670
|
-
if (enableDraftMode) {
|
|
671
|
-
(await draftMode()).enable();
|
|
672
|
-
console.log("[WWW] render/preview:createPreviewHandler:GET draftMode enabled");
|
|
673
|
-
}
|
|
674
|
-
redirect(path);
|
|
675
|
-
return new Response(null, { status: 204 });
|
|
676
|
-
};
|
|
677
|
-
}
|
|
678
|
-
// src/render/metadata/hreflang.ts
|
|
679
|
-
async function buildHreflangAlternates({
|
|
680
|
-
siteUrl,
|
|
681
|
-
locale,
|
|
682
|
-
urlPrefix,
|
|
683
|
-
storedSlug,
|
|
684
|
-
queryAllLocaleSlugs,
|
|
685
|
-
nested,
|
|
686
|
-
homeSlug,
|
|
687
|
-
defaultLocale,
|
|
688
|
-
locales,
|
|
689
|
-
localePrefix = "always"
|
|
690
|
-
}) {
|
|
691
|
-
const allLocaleSlugs = await queryAllLocaleSlugs(storedSlug, locale);
|
|
692
|
-
console.log("[WWW] render/metadata:buildHreflangAlternates storedSlug=", storedSlug, "locale=", locale, "allLocaleSlugs=", JSON.stringify(allLocaleSlugs));
|
|
693
|
-
const languages = {};
|
|
694
|
-
const urlFor = (l, slug) => {
|
|
695
|
-
const trimmedPrefix = urlPrefix.replace(/^\/|\/$/g, "");
|
|
696
|
-
const prefixSegment = trimmedPrefix ? `/${trimmedPrefix}` : "";
|
|
697
|
-
const urlPath = slug === homeSlug ? "/" : nested ? "/" + slug.replaceAll("_", "/") : "/" + slug;
|
|
698
|
-
const localeSegment = localePrefix === "never" ? "" : localePrefix === "as-needed" && l === defaultLocale ? "" : `/${l}`;
|
|
699
|
-
return `${siteUrl}${localeSegment}${prefixSegment}${urlPath}`;
|
|
700
|
-
};
|
|
701
|
-
for (const l of locales) {
|
|
702
|
-
const slugForLocale = allLocaleSlugs?.[l];
|
|
703
|
-
if (!slugForLocale)
|
|
704
|
-
continue;
|
|
705
|
-
languages[l] = urlFor(l, slugForLocale);
|
|
706
|
-
}
|
|
707
|
-
if (allLocaleSlugs?.[defaultLocale]) {
|
|
708
|
-
languages["x-default"] = urlFor(defaultLocale, allLocaleSlugs[defaultLocale]);
|
|
709
|
-
}
|
|
710
|
-
console.log("[WWW] render/metadata:buildHreflangAlternates ->", JSON.stringify(languages));
|
|
711
|
-
return languages;
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
// src/render/metadata/query.ts
|
|
715
|
-
import { getPayload } from "payload";
|
|
716
|
-
import { cache } from "react";
|
|
717
|
-
|
|
718
|
-
// src/core/utils/getFromImportMap.ts
|
|
719
|
-
function getFromImportMap(key, importMap) {
|
|
720
|
-
const resolvedKey = key.includes("#") ? key : key + "#default";
|
|
721
|
-
const value = importMap[resolvedKey];
|
|
722
|
-
console.log("[WWW] core/utils:getFromImportMap key=", key, "resolved=", resolvedKey, "hit=", Boolean(value));
|
|
723
|
-
return value;
|
|
724
|
-
}
|
|
725
|
-
|
|
726
|
-
// src/render/metadata/query.ts
|
|
727
|
-
var queryDocBySlug = cache(async function queryDocBySlug2({
|
|
728
|
-
collectionSlug,
|
|
729
|
-
slug,
|
|
730
|
-
slugField: slugField2 = "slug",
|
|
731
|
-
locale,
|
|
732
|
-
draft = false,
|
|
733
|
-
config
|
|
734
|
-
}) {
|
|
735
|
-
console.log("[WWW] render/metadata:queryDocBySlug collection=", collectionSlug, "slug=", slug, "slugField=", slugField2, "locale=", locale, "draft=", draft);
|
|
736
|
-
const payload = await getPayload({ config });
|
|
737
|
-
const result = await payload.find({
|
|
738
|
-
collection: collectionSlug,
|
|
739
|
-
draft,
|
|
740
|
-
limit: 1,
|
|
741
|
-
pagination: false,
|
|
742
|
-
overrideAccess: draft,
|
|
743
|
-
where: { [slugField2]: { equals: slug } },
|
|
744
|
-
locale
|
|
745
|
-
});
|
|
746
|
-
const doc = result.docs?.[0] ?? null;
|
|
747
|
-
console.log("[WWW] render/metadata:queryDocBySlug ->", doc ? "hit" : "miss");
|
|
748
|
-
return doc;
|
|
749
|
-
});
|
|
750
|
-
var queryAllDocs = cache(async function queryAllDocs2({
|
|
751
|
-
collectionSlug,
|
|
752
|
-
slugField: slugField2 = "slug",
|
|
753
|
-
locale,
|
|
754
|
-
config
|
|
755
|
-
}) {
|
|
756
|
-
console.log("[WWW] render/metadata:queryAllDocs collection=", collectionSlug, "locale=", locale);
|
|
757
|
-
const payload = await getPayload({ config });
|
|
758
|
-
const result = await payload.find({
|
|
759
|
-
collection: collectionSlug,
|
|
760
|
-
draft: false,
|
|
761
|
-
limit: 1000,
|
|
762
|
-
pagination: false,
|
|
763
|
-
overrideAccess: false,
|
|
764
|
-
select: { [slugField2]: true },
|
|
765
|
-
locale
|
|
766
|
-
});
|
|
767
|
-
const docs = result.docs ?? [];
|
|
768
|
-
console.log("[WWW] render/metadata:queryAllDocs -> count=", docs.length);
|
|
769
|
-
return docs;
|
|
770
|
-
});
|
|
771
|
-
var queryAllLocaleSlugs = cache(async function queryAllLocaleSlugs2({
|
|
772
|
-
collectionSlug,
|
|
773
|
-
slug,
|
|
774
|
-
slugField: slugField2 = "slug",
|
|
775
|
-
locale,
|
|
776
|
-
config
|
|
777
|
-
}) {
|
|
778
|
-
console.log("[WWW] render/metadata:queryAllLocaleSlugs collection=", collectionSlug, "slug=", slug, "locale=", locale);
|
|
779
|
-
const payload = await getPayload({ config });
|
|
780
|
-
const result = await payload.find({
|
|
781
|
-
collection: collectionSlug,
|
|
782
|
-
draft: false,
|
|
783
|
-
limit: 1,
|
|
784
|
-
pagination: false,
|
|
785
|
-
overrideAccess: false,
|
|
786
|
-
locale,
|
|
787
|
-
where: { [slugField2]: { equals: slug } },
|
|
788
|
-
select: { [slugField2]: true }
|
|
789
|
-
});
|
|
790
|
-
const doc = result.docs?.[0];
|
|
791
|
-
if (!doc) {
|
|
792
|
-
console.log("[WWW] render/metadata:queryAllLocaleSlugs -> undefined (no doc)");
|
|
793
|
-
return;
|
|
794
|
-
}
|
|
795
|
-
let fieldValue = doc[slugField2];
|
|
796
|
-
if (doc.id != null) {
|
|
797
|
-
const allLocales2 = await payload.findByID({
|
|
798
|
-
collection: collectionSlug,
|
|
799
|
-
id: doc.id,
|
|
800
|
-
locale: "all",
|
|
801
|
-
draft: false,
|
|
802
|
-
overrideAccess: false,
|
|
803
|
-
select: { [slugField2]: true }
|
|
804
|
-
}).catch(() => null);
|
|
805
|
-
if (allLocales2)
|
|
806
|
-
fieldValue = allLocales2[slugField2];
|
|
807
|
-
}
|
|
808
|
-
if (fieldValue && typeof fieldValue === "object") {
|
|
809
|
-
console.log("[WWW] render/metadata:queryAllLocaleSlugs -> localized map=", JSON.stringify(fieldValue));
|
|
810
|
-
return fieldValue;
|
|
811
|
-
}
|
|
812
|
-
const resolved = await config;
|
|
813
|
-
const rawLocales = Array.isArray(resolved?.localization?.localeCodes) ? resolved.localization.localeCodes : resolved?.localization?.locales?.map((l) => l.code) ?? [];
|
|
814
|
-
const out = {};
|
|
815
|
-
for (const l of rawLocales)
|
|
816
|
-
out[l] = String(fieldValue ?? slug);
|
|
817
|
-
console.log("[WWW] render/metadata:queryAllLocaleSlugs -> flat-fanout locales=", rawLocales.length, "slug=", JSON.stringify(fieldValue ?? slug));
|
|
818
|
-
return out;
|
|
819
|
-
});
|
|
820
|
-
var queryGlobal = cache(async function queryGlobal2({
|
|
821
|
-
globalSlug,
|
|
822
|
-
locale,
|
|
823
|
-
depth = 0,
|
|
824
|
-
draft = false,
|
|
825
|
-
config
|
|
826
|
-
}) {
|
|
827
|
-
console.log("[WWW] render/metadata:queryGlobal global=", globalSlug, "locale=", locale, "depth=", depth, "draft=", draft);
|
|
828
|
-
const payload = await getPayload({ config });
|
|
829
|
-
try {
|
|
830
|
-
const global = await payload.findGlobal({
|
|
831
|
-
slug: globalSlug,
|
|
832
|
-
depth,
|
|
833
|
-
draft,
|
|
834
|
-
locale
|
|
835
|
-
});
|
|
836
|
-
console.log("[WWW] render/metadata:queryGlobal -> hit");
|
|
837
|
-
return global;
|
|
838
|
-
} catch (error) {
|
|
839
|
-
console.warn("[WWW] render/metadata:queryGlobal failed for slug=", globalSlug, "err=", String(error));
|
|
840
|
-
return null;
|
|
277
|
+
// src/collections/createFooterGlobal.ts
|
|
278
|
+
var FOOTER_SLUG = "footer";
|
|
279
|
+
var FOOTER_RENDER_PATH = "@justanarthur/payload-www/render-pages#FooterPage";
|
|
280
|
+
var createFooterGlobal = () => createWWWCollectionGlobal([
|
|
281
|
+
{
|
|
282
|
+
name: "nav",
|
|
283
|
+
type: "blocks",
|
|
284
|
+
required: true,
|
|
285
|
+
blocks: [{
|
|
286
|
+
slug: "navColumn",
|
|
287
|
+
fields: [
|
|
288
|
+
{
|
|
289
|
+
name: "title",
|
|
290
|
+
type: "text",
|
|
291
|
+
required: true,
|
|
292
|
+
localized: true
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
name: "links",
|
|
296
|
+
type: "array",
|
|
297
|
+
fields: [link({ appearances: false })]
|
|
298
|
+
}
|
|
299
|
+
]
|
|
300
|
+
}, {
|
|
301
|
+
slug: "navItem",
|
|
302
|
+
fields: [link({ appearances: false })]
|
|
303
|
+
}]
|
|
841
304
|
}
|
|
305
|
+
], {
|
|
306
|
+
slug: FOOTER_SLUG,
|
|
307
|
+
renderPath: FOOTER_RENDER_PATH,
|
|
308
|
+
isGlobalConfig: true
|
|
842
309
|
});
|
|
843
|
-
function getRenderModuleExports(exportName, collection, importMap) {
|
|
844
|
-
const path = collection?.custom?.path;
|
|
845
|
-
if (!path) {
|
|
846
|
-
console.log("[WWW] render/metadata:getRenderModuleExports no custom.path exportName=", exportName);
|
|
847
|
-
return;
|
|
848
|
-
}
|
|
849
|
-
const mod = getFromImportMap(path, importMap);
|
|
850
|
-
const value = mod?.[exportName];
|
|
851
|
-
console.log("[WWW] render/metadata:getRenderModuleExports exportName=", exportName, "path=", path, "hit=", Boolean(value));
|
|
852
|
-
return value;
|
|
853
|
-
}
|
|
854
310
|
|
|
855
|
-
// src/
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
for (const doc of docs) {
|
|
880
|
-
const storedSlug = doc.slug;
|
|
881
|
-
if (typeof storedSlug !== "string" || storedSlug === "")
|
|
882
|
-
continue;
|
|
883
|
-
const dedupeKey = `${collectionSlug}:${locale}:${storedSlug}`;
|
|
884
|
-
if (seen.has(dedupeKey))
|
|
885
|
-
continue;
|
|
886
|
-
seen.add(dedupeKey);
|
|
887
|
-
const slugPath = isNested ? storedSlug.replaceAll("_", "/") : storedSlug;
|
|
888
|
-
const url = `${siteUrl}${prefixFor(locale, defaultLocale, options.localePrefix ?? "always")}${urlPrefix}/${slugPath}`;
|
|
889
|
-
const languages = await buildHreflangAlternates({
|
|
890
|
-
siteUrl,
|
|
891
|
-
locale,
|
|
892
|
-
urlPrefix,
|
|
893
|
-
storedSlug,
|
|
894
|
-
nested: isNested,
|
|
895
|
-
homeSlug: "",
|
|
896
|
-
defaultLocale,
|
|
897
|
-
locales: activeLocales,
|
|
898
|
-
localePrefix: options.localePrefix,
|
|
899
|
-
queryAllLocaleSlugs: async (s, l) => {
|
|
900
|
-
const result = await queryAllLocaleSlugs({
|
|
901
|
-
collectionSlug,
|
|
902
|
-
slug: s,
|
|
903
|
-
slugField: "slug",
|
|
904
|
-
locale: l,
|
|
905
|
-
config: options.config
|
|
906
|
-
});
|
|
907
|
-
return result ?? undefined;
|
|
908
|
-
}
|
|
909
|
-
});
|
|
910
|
-
entries.push({
|
|
911
|
-
url,
|
|
912
|
-
lastModified: doc.updatedAt ? new Date(doc.updatedAt) : undefined,
|
|
913
|
-
changeFrequency: collectionDefaults.changefreq ?? "weekly",
|
|
914
|
-
priority: collectionDefaults.priority ?? 0.5,
|
|
915
|
-
alternates: { languages }
|
|
916
|
-
});
|
|
311
|
+
// src/collections/createHeaderGlobal.ts
|
|
312
|
+
var HEADER_SLUG = "header";
|
|
313
|
+
var HEADER_RENDER_PATH = "@justanarthur/payload-www/render-pages#HeaderPage";
|
|
314
|
+
var createHeaderGlobal = () => createWWWCollectionGlobal([
|
|
315
|
+
{
|
|
316
|
+
name: "nav",
|
|
317
|
+
type: "blocks",
|
|
318
|
+
required: true,
|
|
319
|
+
blocks: [{
|
|
320
|
+
slug: "navItem",
|
|
321
|
+
fields: [link({ appearances: false })]
|
|
322
|
+
}, {
|
|
323
|
+
slug: "navColumn",
|
|
324
|
+
fields: [
|
|
325
|
+
{
|
|
326
|
+
name: "title",
|
|
327
|
+
type: "text",
|
|
328
|
+
required: true,
|
|
329
|
+
localized: true
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
name: "links",
|
|
333
|
+
type: "array",
|
|
334
|
+
fields: [link({ appearances: false, localized: true })]
|
|
917
335
|
}
|
|
918
|
-
|
|
919
|
-
}
|
|
920
|
-
console.log("[WWW] render/sitemap:createSitemapFile:sitemap -> entries=", entries.length);
|
|
921
|
-
return entries;
|
|
922
|
-
};
|
|
923
|
-
}
|
|
924
|
-
// src/config/createWWWConfig.ts
|
|
925
|
-
function createWWWConfig(options) {
|
|
926
|
-
const { locales, routing, blocks, linkRelationTo, registerPosts = true, nested = false, defaultPlugins } = options;
|
|
927
|
-
const defaultLocale = routing?.defaultLocale ?? locales[0] ?? "";
|
|
928
|
-
const localePrefixMode = (() => {
|
|
929
|
-
const raw = routing?.localePrefix;
|
|
930
|
-
if (typeof raw === "string")
|
|
931
|
-
return raw;
|
|
932
|
-
return raw?.mode ?? "always";
|
|
933
|
-
})();
|
|
934
|
-
if (locales.length === 0) {
|
|
935
|
-
throw new Error("createWWWConfig: `locales` must contain at least one entry.");
|
|
336
|
+
]
|
|
337
|
+
}]
|
|
936
338
|
}
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
const
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
const
|
|
960
|
-
const
|
|
961
|
-
|
|
962
|
-
[POSTS_RENDER_PATH]: { path: POSTS_RENDER_PATH, type: "component" },
|
|
963
|
-
[HEADER_RENDER_PATH]: { path: HEADER_RENDER_PATH, type: "component" },
|
|
964
|
-
[FOOTER_RENDER_PATH]: { path: FOOTER_RENDER_PATH, type: "component" },
|
|
965
|
-
[LIVE_PREVIEW_LISTENER_PATH]: {
|
|
966
|
-
path: LIVE_PREVIEW_LISTENER_PATH,
|
|
967
|
-
type: "component"
|
|
968
|
-
}
|
|
969
|
-
};
|
|
970
|
-
for (const { slug, custom, admin } of blocks) {
|
|
971
|
-
const path = custom?.path ?? admin?.custom?.path;
|
|
339
|
+
], {
|
|
340
|
+
slug: HEADER_SLUG,
|
|
341
|
+
renderPath: HEADER_RENDER_PATH,
|
|
342
|
+
isGlobalConfig: true
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
// src/createWWWConfig.ts
|
|
346
|
+
import { seoPlugin } from "@justanarthur/payload-plugin-seo";
|
|
347
|
+
import { imageHashPlugin } from "@justanarthur/payload-imagehash-plugin";
|
|
348
|
+
import { translator } from "@justanarthur/payload-plugin-translator";
|
|
349
|
+
function createWWWConfig() {
|
|
350
|
+
function withWWWConfig(input) {
|
|
351
|
+
const { defaultPluginsConfigs, ...config } = input;
|
|
352
|
+
const blocks = config.blocks || [];
|
|
353
|
+
const collections = mergeOrOverride([
|
|
354
|
+
createPagesCollection(blocks),
|
|
355
|
+
createPostsCollection()
|
|
356
|
+
], config.collections);
|
|
357
|
+
const globals = mergeOrOverride([
|
|
358
|
+
createHeaderGlobal(),
|
|
359
|
+
createFooterGlobal()
|
|
360
|
+
], config.globals);
|
|
361
|
+
const renderDependencies = {};
|
|
362
|
+
for (const { slug, custom } of blocks) {
|
|
363
|
+
const path = custom?.[name]?.path;
|
|
972
364
|
if (typeof path === "string" && slug)
|
|
973
365
|
renderDependencies[slug] = { path, type: "component" };
|
|
974
366
|
}
|
|
975
|
-
for (const
|
|
976
|
-
const path =
|
|
367
|
+
for (const { custom } of [...collections, ...globals]) {
|
|
368
|
+
const path = custom?.[name]?.path;
|
|
977
369
|
if (typeof path === "string")
|
|
978
370
|
renderDependencies[path] = { path, type: "component" };
|
|
979
371
|
}
|
|
980
|
-
const [
|
|
981
|
-
{
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
translator({
|
|
996
|
-
collections: ["pages", "posts", "static-pages"],
|
|
997
|
-
globals: ["header", "footer"],
|
|
372
|
+
const plugins = mergeOrOverride([
|
|
373
|
+
seoPlugin(mergeOrOverride({
|
|
374
|
+
collections: [PAGES_SLUG, POSTS_SLUG],
|
|
375
|
+
openaiApiKey: process.env.OPENAI_API_KEY,
|
|
376
|
+
autoGenerate: {
|
|
377
|
+
mode: "onCreateOrUpdate",
|
|
378
|
+
deriveFrom: "allScalars"
|
|
379
|
+
}
|
|
380
|
+
}, defaultPluginsConfigs?.seo)),
|
|
381
|
+
imageHashPlugin(mergeOrOverride({
|
|
382
|
+
algorithm: "lqip-modern"
|
|
383
|
+
}, defaultPluginsConfigs?.imageHash)),
|
|
384
|
+
translator(mergeOrOverride({
|
|
385
|
+
collections: [PAGES_SLUG, POSTS_SLUG],
|
|
386
|
+
globals: [HEADER_SLUG, FOOTER_SLUG],
|
|
998
387
|
resolvers: [
|
|
999
388
|
openAIResolver({
|
|
1000
389
|
apiKey: process.env.OPENAI_API_KEY,
|
|
1001
390
|
chunkLength: 31,
|
|
1002
|
-
model: "gpt-5-mini"
|
|
391
|
+
model: "gpt-5.4-mini"
|
|
1003
392
|
})
|
|
1004
393
|
]
|
|
1005
|
-
})
|
|
1006
|
-
];
|
|
1007
|
-
const mergedPlugins = defaultPlugins ? defaultPlugins(defaultPluginList) : defaultPluginList;
|
|
394
|
+
}, defaultPluginsConfigs?.translator))
|
|
395
|
+
], config.plugins);
|
|
1008
396
|
return {
|
|
1009
397
|
...config,
|
|
1010
398
|
collections,
|
|
1011
399
|
globals,
|
|
1012
|
-
plugins
|
|
400
|
+
plugins,
|
|
1013
401
|
admin: {
|
|
1014
402
|
...config.admin ?? {},
|
|
1015
403
|
dependencies: {
|
|
@@ -1021,6 +409,13 @@ function createWWWConfig(options) {
|
|
|
1021
409
|
}
|
|
1022
410
|
return { withWWWConfig };
|
|
1023
411
|
}
|
|
412
|
+
function mergeOrOverride(defaultValue, overrideValue) {
|
|
413
|
+
if (typeof overrideValue === "function")
|
|
414
|
+
return overrideValue(defaultValue);
|
|
415
|
+
if (overrideValue !== undefined)
|
|
416
|
+
return overrideValue;
|
|
417
|
+
return defaultValue;
|
|
418
|
+
}
|
|
1024
419
|
|
|
1025
420
|
// src/exports/config.ts
|
|
1026
421
|
var config_default = createWWWConfig;
|