@justanarthur/payload-www 1.4.2 → 2.0.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/dist/sitemap.js CHANGED
@@ -1,8 +1,3 @@
1
-
2
-
3
- // src/render/pages/createCollectionPageExports.tsx
4
- import"server-only";
5
-
6
1
  // src/render/metadata/slug.ts
7
2
  var SLUG_NESTED_DIVIDER = "_";
8
3
  function paramsSlugToSlug(slug, _shape) {
@@ -22,135 +17,112 @@ function slugToPath(slug) {
22
17
  }
23
18
 
24
19
  // src/render/metadata/query.ts
20
+ import { createCacheHelpers } from "@pro-laico/payload-revalidate/cache";
21
+ import { tagsFor } from "@pro-laico/payload-revalidate";
22
+ import { cacheLife } from "next/cache";
25
23
  import { getPayload } from "payload";
26
-
27
- // src/collections/hooks/createRevalidateCollectionGlobalHook.ts
28
- import { revalidateTag } from "next/cache";
29
- function createRevalidateCollectionGlobalHook() {
30
- const afterChangeDeleteHook = async ({ doc, req, ...args }) => {
31
- const previousDoc = "previousDoc" in args ? args.previousDoc : null, locale = req.locale;
32
- function revalidate(args2) {
33
- try {
34
- revalidateTag(createCollectionCacheKey({ ...args2, locale }), "max");
35
- } catch (error) {
36
- const msg = error instanceof Error ? error.message : String(error);
37
- if (msg.includes("static generation store missing"))
38
- return;
39
- console.error(error);
40
- }
41
- }
42
- if ("collection" in args) {
43
- [
44
- doc && doc._status !== "draft" && doc.slug,
45
- previousDoc && previousDoc._status === "published" && previousDoc.slug
46
- ].filter((slug) => slug !== undefined && slug !== false).map((slug) => revalidate({ collectionSlug: args.collection.slug, slug }));
47
- } else {
48
- revalidate({ globalSlug: args.global.slug });
49
- }
50
- return doc;
51
- };
52
- return { afterChange: afterChangeDeleteHook, afterDelete: afterChangeDeleteHook };
53
- }
54
- function createCollectionCacheKey(args) {
55
- return `${"globalSlug" in args ? args.globalSlug : args.collectionSlug + args.slug}_${args.locale}`;
24
+ var _helpers = null;
25
+ var _seedPromise = null;
26
+ function seedPayloadCache({ config }) {
27
+ if (_helpers || _seedPromise)
28
+ return;
29
+ _seedPromise = (async () => {
30
+ const payload = await getPayload({ config: await config });
31
+ _helpers = createCacheHelpers(payload);
32
+ })();
56
33
  }
57
-
58
- // src/render/metadata/query.ts
59
- async function withUnstableCache(keyParts, tags, fn) {
60
- const { unstable_cache } = await import("next/cache");
61
- return unstable_cache(fn, keyParts.map(String), { tags })();
34
+ async function requireCacheHelpers() {
35
+ if (_helpers)
36
+ return _helpers;
37
+ if (_seedPromise) {
38
+ await _seedPromise;
39
+ if (_helpers)
40
+ return _helpers;
41
+ }
42
+ throw new Error("[payload-www] seedPayloadCache({ config }) must be called before any query getter. " + "Call it from createCollectionPageExports / createRootLayoutExports factory, or in your root layout.");
62
43
  }
63
- async function queryDoc(args, { config: configPromise }) {
64
- return withUnstableCache(Object.values(args), [createCollectionCacheKey(args)], async () => {
65
- if ("globalSlug" in args)
66
- return queryGlobal({ ...args, config: configPromise });
67
- else
68
- return queryDocBySlug({ ...args, config: configPromise });
44
+ async function queryDocBySlug(args) {
45
+ "use cache";
46
+ cacheLife("weeks");
47
+ const { findDoc } = await requireCacheHelpers();
48
+ const slugField = args.slugField ?? "slug";
49
+ const result = await findDoc(args.collectionSlug, {
50
+ where: { [slugField]: { equals: args.slug } },
51
+ locale: args.locale,
52
+ draft: args.draft ?? false,
53
+ depth: args.depth
69
54
  });
55
+ return result ?? null;
70
56
  }
71
- async function queryDocBySlug({
72
- collectionSlug,
73
- slug,
74
- slugField = "slug",
75
- locale,
76
- draft = false,
77
- config
78
- }) {
79
- return withUnstableCache([collectionSlug, slug, locale, draft], [createCollectionCacheKey({ collectionSlug, slug, locale })], async () => {
80
- const payload = await getPayload({ config });
81
- const result = await payload.find({
82
- collection: collectionSlug,
83
- draft,
84
- limit: 1,
85
- pagination: false,
86
- overrideAccess: draft,
87
- where: { [slugField]: { equals: slug } },
88
- locale
57
+ async function queryGlobal(args) {
58
+ "use cache";
59
+ cacheLife("weeks");
60
+ const { findGlobal } = await requireCacheHelpers();
61
+ try {
62
+ const result = await findGlobal(args.globalSlug, {
63
+ locale: args.locale,
64
+ draft: args.draft ?? false,
65
+ depth: args.depth
89
66
  });
90
- return result.docs?.[0] ?? null;
91
- });
67
+ return result ?? null;
68
+ } catch (error) {
69
+ console.warn("[WWW] queryGlobal failed", { globalSlug: args.globalSlug, locale: args.locale, error: String(error) });
70
+ return null;
71
+ }
92
72
  }
93
- async function queryGlobal({
94
- globalSlug,
95
- locale,
96
- draft = false,
97
- config
98
- }) {
99
- return withUnstableCache([globalSlug, locale, draft], [createCollectionCacheKey({ globalSlug, locale })], async () => {
100
- const payload = await getPayload({ config });
101
- try {
102
- return await payload.findGlobal({ slug: globalSlug, draft, locale });
103
- } catch (error) {
104
- console.warn("[WWW] queryGlobal failed", { globalSlug, locale, error: String(error) });
105
- return null;
106
- }
107
- });
73
+ async function queryAllDocs(args) {
74
+ "use cache";
75
+ cacheLife("weeks");
76
+ const { findIds, findDocByID } = await requireCacheHelpers();
77
+ const collection = args.collectionSlug;
78
+ const { ids } = await findIds(collection, { locale: args.locale });
79
+ if (ids.length === 0)
80
+ return [];
81
+ const docs = await Promise.all(ids.map((id) => findDocByID(collection, id, { locale: args.locale })));
82
+ return docs.filter((d) => d !== null);
108
83
  }
109
- async function queryAllDocs({
110
- collectionSlug,
111
- slugField = "slug",
112
- locale,
113
- config
114
- }) {
115
- return withUnstableCache([collectionSlug, slugField, locale], [createCollectionCacheKey({ collectionSlug, slug: "__all__", locale })], async () => {
116
- const payload = await getPayload({ config });
117
- const result = await payload.find({
118
- collection: collectionSlug,
119
- draft: false,
120
- limit: 1000,
121
- pagination: false,
122
- overrideAccess: false,
123
- select: { [slugField]: true },
124
- locale
125
- });
126
- return result.docs ?? [];
127
- });
84
+ async function queryDoc(args) {
85
+ if ("globalSlug" in args)
86
+ return queryGlobal(args);
87
+ return queryDocBySlug(args);
128
88
  }
129
- async function queryAllLocaleSlugs({
130
- collectionSlug,
131
- id,
132
- slugField = "slug",
133
- config
134
- }) {
135
- const payload = await getPayload({ config });
136
- const doc = await payload.findByID({
137
- collection: collectionSlug,
138
- id,
139
- locale: "all",
140
- select: { [slugField]: true }
89
+ async function queryAllLocaleSlugs(args) {
90
+ "use cache";
91
+ cacheLife("weeks");
92
+ const { findDocByID } = await requireCacheHelpers();
93
+ const slugField = args.slugField ?? "slug";
94
+ const doc = await findDocByID(args.collectionSlug, args.id, { locale: "all", select: { [slugField]: true } });
95
+ const localeMap = doc?.[slugField];
96
+ if (localeMap && typeof localeMap === "object")
97
+ return localeMap;
98
+ return null;
99
+ }
100
+ async function queryDocByID(args) {
101
+ "use cache";
102
+ cacheLife("weeks");
103
+ const { findDocByID } = await requireCacheHelpers();
104
+ return await findDocByID(args.collectionSlug, args.id, {
105
+ locale: args.locale,
106
+ draft: args.draft ?? false,
107
+ depth: args.depth
141
108
  });
142
- return doc?.[slugField];
143
109
  }
144
110
 
145
111
  // src/render/pages/createCollectionPageExports.tsx
146
112
  import { setRequestLocale } from "next-intl/server";
147
113
 
148
114
  // src/render/pages/utils/buildLocalizedPath.ts
115
+ function resolvePagePathPrefix(prefix, locale, routing) {
116
+ if (typeof prefix !== "object")
117
+ return prefix;
118
+ return prefix[locale] ?? prefix[routing.defaultLocale];
119
+ }
149
120
  function buildLocalizedPath(locale, prefix, slug, { routing }) {
150
121
  const path = slugToPath(slug);
122
+ const localePrefix = resolvePagePathPrefix(prefix, locale, routing);
151
123
  return `${routing.localePrefix === "never" ? "" : routing.localePrefix === "always" ? locale : routing.localePrefix === "as-needed" ? locale === routing.defaultLocale ? "" : "/" + locale : (() => {
152
124
  throw new Error("Unsupported locale prefix");
153
- })()}${prefix ? "/" + prefix : ""}${path ? "/" + path : ""}`;
125
+ })()}${localePrefix ? "/" + localePrefix : ""}${path ? "/" + path : ""}`;
154
126
  }
155
127
  function buildLocalizedPaths(localesSlug, pagePathPrefix, { routing }) {
156
128
  const blankIsHome = !localesSlug[routing.defaultLocale];
@@ -226,7 +198,7 @@ async function renderWWWDataModule(data, {
226
198
  import { jsx as jsx2, Fragment } from "react/jsx-runtime";
227
199
  function createCollectionPageExports({
228
200
  slug: collectionSlug = "pages",
229
- config: configPromise,
201
+ _payloadConfig,
230
202
  importMap,
231
203
  routing,
232
204
  slugShape = "single"
@@ -234,14 +206,13 @@ function createCollectionPageExports({
234
206
  getServerSideURL,
235
207
  pagePathPrefix
236
208
  }) {
209
+ seedPayloadCache({ config: _payloadConfig });
237
210
  const siteUrl = getServerSideURL();
238
211
  async function fetchDoc(locale, slug) {
239
212
  return queryDoc({
240
213
  slug,
241
214
  locale,
242
215
  collectionSlug
243
- }, {
244
- config: configPromise
245
216
  });
246
217
  }
247
218
  const default_ = async (props) => {
@@ -258,22 +229,25 @@ function createCollectionPageExports({
258
229
  const { notFound } = await import("next/navigation");
259
230
  notFound();
260
231
  }
261
- const rendered = renderWWWDataModule(doc, { collectionSlug, config: configPromise, importMap }, { ...props, locale });
232
+ const rendered = renderWWWDataModule(doc, { collectionSlug, config: _payloadConfig, importMap }, { ...props, locale });
262
233
  return /* @__PURE__ */ jsx2(Fragment, {
263
234
  children: rendered
264
235
  });
265
236
  };
266
237
  async function generateMetadata(props) {
267
238
  const params = await props.params;
268
- const locale = params.locale, slug = paramsSlugToSlug(params.slug, slugShape);
239
+ const locale = params.locale;
240
+ if (!routing.locales.includes(locale)) {
241
+ return {};
242
+ }
243
+ const slug = paramsSlugToSlug(params.slug, slugShape);
269
244
  const doc = await fetchDoc(locale, slug);
270
245
  const [localesSlug, siteDefaults] = await Promise.all([
271
246
  doc ? queryAllLocaleSlugs({
272
247
  id: doc.id,
273
- collectionSlug,
274
- config: configPromise
248
+ collectionSlug
275
249
  }) : Promise.resolve({}),
276
- createSiteDefaults({ config: configPromise, locale })
250
+ createSiteDefaults({ config: _payloadConfig, locale })
277
251
  ]);
278
252
  if (!doc)
279
253
  return {};
@@ -290,22 +264,23 @@ function createCollectionPageExports({
290
264
  return { ...meta, alternates };
291
265
  }
292
266
  async function generateStaticParams(props) {
293
- const locale = (await props.params).locale;
294
- const docs = await queryAllDocs({ locale, collectionSlug, config: configPromise });
295
- return docs.filter((doc) => typeof doc.slug === "string" && doc.slug.length > 0).map((doc) => ({ slug: slugToParamsSlug(doc.slug, slugShape) }));
267
+ await props.params;
268
+ const perLocaleEntries = await Promise.all(routing.locales.map(async (locale) => {
269
+ const docs = await queryAllDocs({ locale, collectionSlug });
270
+ return docs.filter((doc) => typeof doc.slug === "string" && doc.slug.length > 0).map((doc) => ({ locale, slug: slugToParamsSlug(doc.slug, slugShape) }));
271
+ }));
272
+ return perLocaleEntries.flat();
296
273
  }
297
274
  async function generateSitemap() {
298
275
  const locale = routing.defaultLocale;
299
276
  const docs = await queryAllDocs({
300
277
  collectionSlug,
301
- locale,
302
- config: configPromise
278
+ locale: routing.defaultLocale
303
279
  });
304
280
  return await Promise.all(docs.map(async (doc) => {
305
281
  const localesSlug = await queryAllLocaleSlugs({
306
282
  id: doc.id,
307
- collectionSlug,
308
- config: configPromise
283
+ collectionSlug
309
284
  }) ?? {};
310
285
  const alternates = buildAlternates(locale, localesSlug, pagePathPrefix, { routing, siteUrl });
311
286
  return {
@@ -316,7 +291,7 @@ function createCollectionPageExports({
316
291
  }));
317
292
  }
318
293
  generateSitemap.getServerSideURL = getServerSideURL;
319
- generateSitemap.pagePathPrefix = pagePathPrefix;
294
+ generateSitemap.pagePathPrefix = resolvePagePathPrefix(pagePathPrefix, routing.defaultLocale, routing);
320
295
  return {
321
296
  default: default_,
322
297
  generateMetadata,
@@ -340,8 +315,9 @@ ${sitemaps.map((url) => ` <sitemap><loc>${url}</loc></sitemap>`).join(`
340
315
  }
341
316
 
342
317
  // src/exports/sitemap.ts
343
- var sitemap_default = { createSitemapFromCollections };
318
+ var sitemap_default = { createSitemapFromCollections, seedPayloadCache };
344
319
  export {
320
+ createSitemapFromCollections,
345
321
  sitemap_default as default,
346
- createSitemapFromCollections
322
+ seedPayloadCache
347
323
  };
@@ -1,2 +1,2 @@
1
1
  import { translator } from "@justanarthur/payload-plugin-translator";
2
- export { translator, translator as default };
2
+ export { translator as default, translator };
@@ -1,9 +1,7 @@
1
-
2
-
3
1
  // src/exports/translator.ts
4
2
  import { translator } from "@justanarthur/payload-plugin-translator";
5
3
  var translator_default = translator;
6
4
  export {
7
- translator,
8
- translator_default as default
5
+ translator_default as default,
6
+ translator
9
7
  };
package/dist/utils.d.ts CHANGED
@@ -11,4 +11,4 @@ declare const utils: {
11
11
  getFromImportMap: typeof getFromImportMap;
12
12
  generateImportName: typeof generateImportName;
13
13
  };
14
- export { getFromImportMap, generateImportName, utils as default };
14
+ export { utils as default, generateImportName, getFromImportMap };
package/dist/utils.js CHANGED
@@ -1,5 +1,3 @@
1
-
2
-
3
1
  // src/render/generateImportName.ts
4
2
  function generateImportName(type, slug) {
5
3
  switch (type) {
@@ -34,7 +32,7 @@ function getFromImportMap(key, importMap) {
34
32
  var utils = { getFromImportMap, generateImportName };
35
33
  var utils_default = utils;
36
34
  export {
37
- getFromImportMap,
35
+ utils_default as default,
38
36
  generateImportName,
39
- utils_default as default
37
+ getFromImportMap
40
38
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@justanarthur/payload-www",
3
3
  "description": "Reusable Payload CMS website template — config builder, collections, globals, blocks, fields, access, hooks, metadata (JSON-LD, hreflang), page renderers, and test helpers.",
4
- "version": "1.4.2",
4
+ "version": "2.0.0",
5
5
  "type": "module",
6
6
  "private": false,
7
7
  "files": [
@@ -113,24 +113,24 @@
113
113
  "prepublishOnly": "bun run clean && bun run build"
114
114
  },
115
115
  "dependencies": {
116
- "@payloadcms/live-preview-react": "3.85.0",
117
- "@payloadcms/plugin-mcp": "3.85.0",
118
- "@payloadcms/richtext-lexical": "3.85.0",
119
- "@payloadcms/next": "3.85.0",
120
- "next": "16.2.6",
121
- "next-intl": "^4.0.0",
116
+ "@payloadcms/live-preview-react": "3.88.0",
117
+ "@payloadcms/plugin-mcp": "3.88.0",
118
+ "@payloadcms/richtext-lexical": "3.88.0",
119
+ "@payloadcms/next": "3.88.0",
120
+ "next": "16.3.4",
121
+ "next-intl": "^4.14.2",
122
122
  "server-only": "0.0.1",
123
123
  "tsx": "^4.19.2"
124
124
  },
125
125
  "devDependencies": {
126
126
  "@types/node": "22.19.9",
127
- "@types/react": "19.2.14",
128
- "@types/react-dom": "19.2.3",
127
+ "@types/react": "19.2.18",
128
+ "@types/react-dom": "19.2.7",
129
129
  "bunup": "^0.16.32",
130
- "payload": "3.85.1",
131
- "react": "19.2.6",
132
- "react-dom": "19.2.6",
133
- "typescript": "5.7.3",
130
+ "payload": "3.88.0",
131
+ "react": "19.2.8",
132
+ "react-dom": "19.2.8",
133
+ "typescript": "^7.0.2",
134
134
  "vitest": "4.0.18"
135
135
  },
136
136
  "peerDependencies": {
@@ -139,12 +139,14 @@
139
139
  "@payloadcms/richtext-lexical": "^3.85.0",
140
140
  "@payloadcms/translations": "^3.85.0",
141
141
  "@payloadcms/ui": "^3.85.0",
142
+ "@pro-laico/core": "^0.5.0",
143
+ "@pro-laico/payload-revalidate": "^0.8.5",
142
144
  "next": "^16.2.6",
143
145
  "next-intl": "^4.0.0",
144
146
  "payload": "^3.85.0",
145
147
  "react": "^19.2.6",
146
148
  "react-dom": "^19.2.6",
147
- "@justanarthur/payload-plugin-seo": "^3.0.0",
149
+ "@justanarthur/payload-plugin-seo": "^4.0.0",
148
150
  "@justanarthur/payload-plugin-translator": "^3.0.0",
149
151
  "@justanarthur/payload-imagehash-plugin": "^3.3.0"
150
152
  },