@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/pages.d.ts CHANGED
@@ -22,21 +22,29 @@ type NextPageProps = {
22
22
  };
23
23
  import { RoutingConfig as GenericRoutingConfig } from "next-intl/routing";
24
24
  type RoutingConfig = GenericRoutingConfig<string[], any, any, any>;
25
+ /**
26
+ * URL segment a collection is mounted under. A string is used for every locale; a record
27
+ * localizes it (`{ en: 'posts', sk: 'prispevky' }`), so a host serving localized routes
28
+ * gets canonical/hreflang URLs that match the URLs it actually serves. Locales missing
29
+ * from the record fall back to the default locale.
30
+ */
31
+ type PagePathPrefix = string | Record<string, string>;
25
32
  type CreateCollectionPageExportsArgs<S extends string = "pages"> = {
26
33
  slug?: S;
27
- config: Promise<SanitizedConfig2>;
34
+ _payloadConfig: Promise<SanitizedConfig2>;
28
35
  importMap: ImportMap3;
29
36
  routing: RoutingConfig;
30
37
  slugShape?: SlugShape;
31
38
  };
32
39
  type CreateCollectionPageExportsDeps<S extends string> = {
33
40
  getServerSideURL: () => string;
34
- pagePathPrefix?: string;
41
+ pagePathPrefix?: PagePathPrefix;
35
42
  };
36
- declare function createCollectionPageExports<S extends string = "pages">({ slug: collectionSlug, config: configPromise, importMap, routing, slugShape }: CreateCollectionPageExportsArgs<S>, { getServerSideURL, pagePathPrefix }: CreateCollectionPageExportsDeps<S>): {
43
+ declare function createCollectionPageExports<S extends string = "pages">({ slug: collectionSlug, _payloadConfig, importMap, routing, slugShape }: CreateCollectionPageExportsArgs<S>, { getServerSideURL, pagePathPrefix }: CreateCollectionPageExportsDeps<S>): {
37
44
  default: (props: NextPageProps) => Promise<ReactNode2>;
38
45
  generateMetadata: (props: NextPageProps) => Promise<Metadata>;
39
46
  generateStaticParams: (props: NextPageProps) => Promise<{
47
+ locale: string;
40
48
  slug: string | string[];
41
49
  }[]>;
42
50
  generateSitemap: {
@@ -51,4 +59,4 @@ declare const pages: {
51
59
  HeaderPage: typeof HeaderPage;
52
60
  FooterPage: typeof FooterPage;
53
61
  };
54
- export { pages as default, createCollectionPageExports, PagesPage, HeaderPage, FooterPage, CreateCollectionPageExportsDeps, CreateCollectionPageExportsArgs };
62
+ export { CreateCollectionPageExportsArgs, CreateCollectionPageExportsDeps, FooterPage, HeaderPage, PagesPage, createCollectionPageExports, pages as default };
package/dist/pages.js CHANGED
@@ -1,7 +1,4 @@
1
-
2
-
3
1
  // src/render/pages/FooterPage.tsx
4
- import"server-only";
5
2
  import { jsx, jsxs } from "react/jsx-runtime";
6
3
  function FooterPage({ data }) {
7
4
  const nav = data.nav ?? [];
@@ -59,7 +56,6 @@ function FooterPage({ data }) {
59
56
  }
60
57
 
61
58
  // src/render/pages/HeaderPage.tsx
62
- import"server-only";
63
59
  import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
64
60
  function HeaderPage({ data }) {
65
61
  const nav = data.nav ?? [];
@@ -177,9 +173,6 @@ async function PagesPage({ data, locale, ...props }) {
177
173
  });
178
174
  }
179
175
 
180
- // src/render/pages/createCollectionPageExports.tsx
181
- import"server-only";
182
-
183
176
  // src/render/metadata/slug.ts
184
177
  var SLUG_NESTED_DIVIDER = "_";
185
178
  function paramsSlugToSlug(slug, _shape) {
@@ -199,135 +192,112 @@ function slugToPath(slug) {
199
192
  }
200
193
 
201
194
  // src/render/metadata/query.ts
195
+ import { createCacheHelpers } from "@pro-laico/payload-revalidate/cache";
196
+ import { tagsFor } from "@pro-laico/payload-revalidate";
197
+ import { cacheLife } from "next/cache";
202
198
  import { getPayload } from "payload";
203
-
204
- // src/collections/hooks/createRevalidateCollectionGlobalHook.ts
205
- import { revalidateTag } from "next/cache";
206
- function createRevalidateCollectionGlobalHook() {
207
- const afterChangeDeleteHook = async ({ doc, req, ...args }) => {
208
- const previousDoc = "previousDoc" in args ? args.previousDoc : null, locale = req.locale;
209
- function revalidate(args2) {
210
- try {
211
- revalidateTag(createCollectionCacheKey({ ...args2, locale }), "max");
212
- } catch (error) {
213
- const msg = error instanceof Error ? error.message : String(error);
214
- if (msg.includes("static generation store missing"))
215
- return;
216
- console.error(error);
217
- }
218
- }
219
- if ("collection" in args) {
220
- [
221
- doc && doc._status !== "draft" && doc.slug,
222
- previousDoc && previousDoc._status === "published" && previousDoc.slug
223
- ].filter((slug) => slug !== undefined && slug !== false).map((slug) => revalidate({ collectionSlug: args.collection.slug, slug }));
224
- } else {
225
- revalidate({ globalSlug: args.global.slug });
226
- }
227
- return doc;
228
- };
229
- return { afterChange: afterChangeDeleteHook, afterDelete: afterChangeDeleteHook };
230
- }
231
- function createCollectionCacheKey(args) {
232
- return `${"globalSlug" in args ? args.globalSlug : args.collectionSlug + args.slug}_${args.locale}`;
199
+ var _helpers = null;
200
+ var _seedPromise = null;
201
+ function seedPayloadCache({ config }) {
202
+ if (_helpers || _seedPromise)
203
+ return;
204
+ _seedPromise = (async () => {
205
+ const payload = await getPayload({ config: await config });
206
+ _helpers = createCacheHelpers(payload);
207
+ })();
233
208
  }
234
-
235
- // src/render/metadata/query.ts
236
- async function withUnstableCache(keyParts, tags, fn) {
237
- const { unstable_cache } = await import("next/cache");
238
- return unstable_cache(fn, keyParts.map(String), { tags })();
209
+ async function requireCacheHelpers() {
210
+ if (_helpers)
211
+ return _helpers;
212
+ if (_seedPromise) {
213
+ await _seedPromise;
214
+ if (_helpers)
215
+ return _helpers;
216
+ }
217
+ 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.");
239
218
  }
240
- async function queryDoc(args, { config: configPromise }) {
241
- return withUnstableCache(Object.values(args), [createCollectionCacheKey(args)], async () => {
242
- if ("globalSlug" in args)
243
- return queryGlobal({ ...args, config: configPromise });
244
- else
245
- return queryDocBySlug({ ...args, config: configPromise });
219
+ async function queryDocBySlug(args) {
220
+ "use cache";
221
+ cacheLife("weeks");
222
+ const { findDoc } = await requireCacheHelpers();
223
+ const slugField = args.slugField ?? "slug";
224
+ const result = await findDoc(args.collectionSlug, {
225
+ where: { [slugField]: { equals: args.slug } },
226
+ locale: args.locale,
227
+ draft: args.draft ?? false,
228
+ depth: args.depth
246
229
  });
230
+ return result ?? null;
247
231
  }
248
- async function queryDocBySlug({
249
- collectionSlug,
250
- slug,
251
- slugField = "slug",
252
- locale,
253
- draft = false,
254
- config
255
- }) {
256
- return withUnstableCache([collectionSlug, slug, locale, draft], [createCollectionCacheKey({ collectionSlug, slug, locale })], async () => {
257
- const payload = await getPayload({ config });
258
- const result = await payload.find({
259
- collection: collectionSlug,
260
- draft,
261
- limit: 1,
262
- pagination: false,
263
- overrideAccess: draft,
264
- where: { [slugField]: { equals: slug } },
265
- locale
232
+ async function queryGlobal(args) {
233
+ "use cache";
234
+ cacheLife("weeks");
235
+ const { findGlobal } = await requireCacheHelpers();
236
+ try {
237
+ const result = await findGlobal(args.globalSlug, {
238
+ locale: args.locale,
239
+ draft: args.draft ?? false,
240
+ depth: args.depth
266
241
  });
267
- return result.docs?.[0] ?? null;
268
- });
242
+ return result ?? null;
243
+ } catch (error) {
244
+ console.warn("[WWW] queryGlobal failed", { globalSlug: args.globalSlug, locale: args.locale, error: String(error) });
245
+ return null;
246
+ }
269
247
  }
270
- async function queryGlobal({
271
- globalSlug,
272
- locale,
273
- draft = false,
274
- config
275
- }) {
276
- return withUnstableCache([globalSlug, locale, draft], [createCollectionCacheKey({ globalSlug, locale })], async () => {
277
- const payload = await getPayload({ config });
278
- try {
279
- return await payload.findGlobal({ slug: globalSlug, draft, locale });
280
- } catch (error) {
281
- console.warn("[WWW] queryGlobal failed", { globalSlug, locale, error: String(error) });
282
- return null;
283
- }
284
- });
248
+ async function queryAllDocs(args) {
249
+ "use cache";
250
+ cacheLife("weeks");
251
+ const { findIds, findDocByID } = await requireCacheHelpers();
252
+ const collection = args.collectionSlug;
253
+ const { ids } = await findIds(collection, { locale: args.locale });
254
+ if (ids.length === 0)
255
+ return [];
256
+ const docs = await Promise.all(ids.map((id) => findDocByID(collection, id, { locale: args.locale })));
257
+ return docs.filter((d) => d !== null);
285
258
  }
286
- async function queryAllDocs({
287
- collectionSlug,
288
- slugField = "slug",
289
- locale,
290
- config
291
- }) {
292
- return withUnstableCache([collectionSlug, slugField, locale], [createCollectionCacheKey({ collectionSlug, slug: "__all__", locale })], async () => {
293
- const payload = await getPayload({ config });
294
- const result = await payload.find({
295
- collection: collectionSlug,
296
- draft: false,
297
- limit: 1000,
298
- pagination: false,
299
- overrideAccess: false,
300
- select: { [slugField]: true },
301
- locale
302
- });
303
- return result.docs ?? [];
304
- });
259
+ async function queryDoc(args) {
260
+ if ("globalSlug" in args)
261
+ return queryGlobal(args);
262
+ return queryDocBySlug(args);
305
263
  }
306
- async function queryAllLocaleSlugs({
307
- collectionSlug,
308
- id,
309
- slugField = "slug",
310
- config
311
- }) {
312
- const payload = await getPayload({ config });
313
- const doc = await payload.findByID({
314
- collection: collectionSlug,
315
- id,
316
- locale: "all",
317
- select: { [slugField]: true }
264
+ async function queryAllLocaleSlugs(args) {
265
+ "use cache";
266
+ cacheLife("weeks");
267
+ const { findDocByID } = await requireCacheHelpers();
268
+ const slugField = args.slugField ?? "slug";
269
+ const doc = await findDocByID(args.collectionSlug, args.id, { locale: "all", select: { [slugField]: true } });
270
+ const localeMap = doc?.[slugField];
271
+ if (localeMap && typeof localeMap === "object")
272
+ return localeMap;
273
+ return null;
274
+ }
275
+ async function queryDocByID(args) {
276
+ "use cache";
277
+ cacheLife("weeks");
278
+ const { findDocByID } = await requireCacheHelpers();
279
+ return await findDocByID(args.collectionSlug, args.id, {
280
+ locale: args.locale,
281
+ draft: args.draft ?? false,
282
+ depth: args.depth
318
283
  });
319
- return doc?.[slugField];
320
284
  }
321
285
 
322
286
  // src/render/pages/createCollectionPageExports.tsx
323
287
  import { setRequestLocale } from "next-intl/server";
324
288
 
325
289
  // src/render/pages/utils/buildLocalizedPath.ts
290
+ function resolvePagePathPrefix(prefix, locale, routing) {
291
+ if (typeof prefix !== "object")
292
+ return prefix;
293
+ return prefix[locale] ?? prefix[routing.defaultLocale];
294
+ }
326
295
  function buildLocalizedPath(locale, prefix, slug, { routing }) {
327
296
  const path = slugToPath(slug);
297
+ const localePrefix = resolvePagePathPrefix(prefix, locale, routing);
328
298
  return `${routing.localePrefix === "never" ? "" : routing.localePrefix === "always" ? locale : routing.localePrefix === "as-needed" ? locale === routing.defaultLocale ? "" : "/" + locale : (() => {
329
299
  throw new Error("Unsupported locale prefix");
330
- })()}${prefix ? "/" + prefix : ""}${path ? "/" + path : ""}`;
300
+ })()}${localePrefix ? "/" + localePrefix : ""}${path ? "/" + path : ""}`;
331
301
  }
332
302
  function buildLocalizedPaths(localesSlug, pagePathPrefix, { routing }) {
333
303
  const blankIsHome = !localesSlug[routing.defaultLocale];
@@ -382,7 +352,7 @@ async function renderWWWDataModule(data, {
382
352
  import { jsx as jsx6, Fragment as Fragment2 } from "react/jsx-runtime";
383
353
  function createCollectionPageExports({
384
354
  slug: collectionSlug = "pages",
385
- config: configPromise,
355
+ _payloadConfig,
386
356
  importMap,
387
357
  routing,
388
358
  slugShape = "single"
@@ -390,14 +360,13 @@ function createCollectionPageExports({
390
360
  getServerSideURL,
391
361
  pagePathPrefix
392
362
  }) {
363
+ seedPayloadCache({ config: _payloadConfig });
393
364
  const siteUrl = getServerSideURL();
394
365
  async function fetchDoc(locale, slug) {
395
366
  return queryDoc({
396
367
  slug,
397
368
  locale,
398
369
  collectionSlug
399
- }, {
400
- config: configPromise
401
370
  });
402
371
  }
403
372
  const default_ = async (props) => {
@@ -414,22 +383,25 @@ function createCollectionPageExports({
414
383
  const { notFound } = await import("next/navigation");
415
384
  notFound();
416
385
  }
417
- const rendered = renderWWWDataModule(doc, { collectionSlug, config: configPromise, importMap }, { ...props, locale });
386
+ const rendered = renderWWWDataModule(doc, { collectionSlug, config: _payloadConfig, importMap }, { ...props, locale });
418
387
  return /* @__PURE__ */ jsx6(Fragment2, {
419
388
  children: rendered
420
389
  });
421
390
  };
422
391
  async function generateMetadata(props) {
423
392
  const params = await props.params;
424
- const locale = params.locale, slug = paramsSlugToSlug(params.slug, slugShape);
393
+ const locale = params.locale;
394
+ if (!routing.locales.includes(locale)) {
395
+ return {};
396
+ }
397
+ const slug = paramsSlugToSlug(params.slug, slugShape);
425
398
  const doc = await fetchDoc(locale, slug);
426
399
  const [localesSlug, siteDefaults] = await Promise.all([
427
400
  doc ? queryAllLocaleSlugs({
428
401
  id: doc.id,
429
- collectionSlug,
430
- config: configPromise
402
+ collectionSlug
431
403
  }) : Promise.resolve({}),
432
- createSiteDefaults({ config: configPromise, locale })
404
+ createSiteDefaults({ config: _payloadConfig, locale })
433
405
  ]);
434
406
  if (!doc)
435
407
  return {};
@@ -446,22 +418,23 @@ function createCollectionPageExports({
446
418
  return { ...meta, alternates };
447
419
  }
448
420
  async function generateStaticParams(props) {
449
- const locale = (await props.params).locale;
450
- const docs = await queryAllDocs({ locale, collectionSlug, config: configPromise });
451
- return docs.filter((doc) => typeof doc.slug === "string" && doc.slug.length > 0).map((doc) => ({ slug: slugToParamsSlug(doc.slug, slugShape) }));
421
+ await props.params;
422
+ const perLocaleEntries = await Promise.all(routing.locales.map(async (locale) => {
423
+ const docs = await queryAllDocs({ locale, collectionSlug });
424
+ return docs.filter((doc) => typeof doc.slug === "string" && doc.slug.length > 0).map((doc) => ({ locale, slug: slugToParamsSlug(doc.slug, slugShape) }));
425
+ }));
426
+ return perLocaleEntries.flat();
452
427
  }
453
428
  async function generateSitemap() {
454
429
  const locale = routing.defaultLocale;
455
430
  const docs = await queryAllDocs({
456
431
  collectionSlug,
457
- locale,
458
- config: configPromise
432
+ locale: routing.defaultLocale
459
433
  });
460
434
  return await Promise.all(docs.map(async (doc) => {
461
435
  const localesSlug = await queryAllLocaleSlugs({
462
436
  id: doc.id,
463
- collectionSlug,
464
- config: configPromise
437
+ collectionSlug
465
438
  }) ?? {};
466
439
  const alternates = buildAlternates(locale, localesSlug, pagePathPrefix, { routing, siteUrl });
467
440
  return {
@@ -472,7 +445,7 @@ function createCollectionPageExports({
472
445
  }));
473
446
  }
474
447
  generateSitemap.getServerSideURL = getServerSideURL;
475
- generateSitemap.pagePathPrefix = pagePathPrefix;
448
+ generateSitemap.pagePathPrefix = resolvePagePathPrefix(pagePathPrefix, routing.defaultLocale, routing);
476
449
  return {
477
450
  default: default_,
478
451
  generateMetadata,
@@ -499,9 +472,9 @@ ${sitemaps.map((url) => ` <sitemap><loc>${url}</loc></sitemap>`).join(`
499
472
  var pages = { createCollectionPageExports, PagesPage, HeaderPage, FooterPage };
500
473
  var pages_default = pages;
501
474
  export {
502
- pages_default as default,
503
- createCollectionPageExports,
504
- PagesPage,
475
+ FooterPage,
505
476
  HeaderPage,
506
- FooterPage
477
+ PagesPage,
478
+ createCollectionPageExports,
479
+ pages_default as default
507
480
  };
@@ -31,21 +31,29 @@ type NextLayoutProps = {
31
31
  };
32
32
  import { RoutingConfig as GenericRoutingConfig } from "next-intl/routing";
33
33
  type RoutingConfig = GenericRoutingConfig<string[], any, any, any>;
34
+ /**
35
+ * URL segment a collection is mounted under. A string is used for every locale; a record
36
+ * localizes it (`{ en: 'posts', sk: 'prispevky' }`), so a host serving localized routes
37
+ * gets canonical/hreflang URLs that match the URLs it actually serves. Locales missing
38
+ * from the record fall back to the default locale.
39
+ */
40
+ type PagePathPrefix = string | Record<string, string>;
34
41
  type CreateCollectionPageExportsArgs<S extends string = "pages"> = {
35
42
  slug?: S;
36
- config: Promise<SanitizedConfig2>;
43
+ _payloadConfig: Promise<SanitizedConfig2>;
37
44
  importMap: ImportMap3;
38
45
  routing: RoutingConfig;
39
46
  slugShape?: SlugShape;
40
47
  };
41
48
  type CreateCollectionPageExportsDeps<S extends string> = {
42
49
  getServerSideURL: () => string;
43
- pagePathPrefix?: string;
50
+ pagePathPrefix?: PagePathPrefix;
44
51
  };
45
- declare function createCollectionPageExports<S extends string = "pages">({ slug: collectionSlug, config: configPromise, importMap, routing, slugShape }: CreateCollectionPageExportsArgs<S>, { getServerSideURL, pagePathPrefix }: CreateCollectionPageExportsDeps<S>): {
52
+ declare function createCollectionPageExports<S extends string = "pages">({ slug: collectionSlug, _payloadConfig, importMap, routing, slugShape }: CreateCollectionPageExportsArgs<S>, { getServerSideURL, pagePathPrefix }: CreateCollectionPageExportsDeps<S>): {
46
53
  default: (props: NextPageProps) => Promise<ReactNode2>;
47
54
  generateMetadata: (props: NextPageProps) => Promise<Metadata>;
48
55
  generateStaticParams: (props: NextPageProps) => Promise<{
56
+ locale: string;
49
57
  slug: string | string[];
50
58
  }[]>;
51
59
  generateSitemap: {
@@ -56,9 +64,9 @@ declare function createCollectionPageExports<S extends string = "pages">({ slug:
56
64
  };
57
65
  import { ImportMap as ImportMap4, SanitizedConfig as SanitizedConfig3 } from "payload";
58
66
  import { HTMLAttributes, ReactNode as ReactNode3 } from "react";
59
- import { JSX as JSX_1kxb2 } from "react/jsx-runtime";
67
+ import { JSX as JSX_1kxb2 } from "react";
60
68
  type CreateRootLayoutExportsArgs = {
61
- config: Promise<SanitizedConfig3>;
69
+ _payloadConfig: Promise<SanitizedConfig3>;
62
70
  importMap: ImportMap4;
63
71
  routing: RoutingConfig;
64
72
  };
@@ -72,7 +80,7 @@ type CreateRootLayoutExportsDeps = {
72
80
  getServerSideURL?: () => string;
73
81
  };
74
82
  type Element_12xgc2 = JSX_1kxb2["Element"];
75
- declare function createRootLayoutExports({ config: configPromise, importMap, routing }: CreateRootLayoutExportsArgs, { providers, htmlAttrs, getServerSideURL }?: CreateRootLayoutExportsDeps): {
83
+ declare function createRootLayoutExports({ _payloadConfig, importMap, routing }: CreateRootLayoutExportsArgs, { providers, htmlAttrs, getServerSideURL }?: CreateRootLayoutExportsDeps): {
76
84
  default: (props: NextLayoutProps) => Promise<Element_12xgc2>;
77
85
  generateStaticParams: () => {
78
86
  locale: string;
@@ -89,4 +97,4 @@ declare const renderPages: {
89
97
  FooterPage: typeof FooterPage;
90
98
  RootJsonLd: any;
91
99
  };
92
- export { renderPages as default, createRootLayoutExports, createCollectionPageExports, RootJsonLdProps, RootJsonLd, PostsPage, PagesPage, HeaderPage, FooterPage, CreateRootLayoutProvidersArgs, CreateRootLayoutExportsDeps, CreateRootLayoutExportsArgs, CreateCollectionPageExportsDeps, CreateCollectionPageExportsArgs };
100
+ export { CreateCollectionPageExportsArgs, CreateCollectionPageExportsDeps, CreateRootLayoutExportsArgs, CreateRootLayoutExportsDeps, CreateRootLayoutProvidersArgs, FooterPage, HeaderPage, PagesPage, PostsPage, RootJsonLd, RootJsonLdProps, createCollectionPageExports, createRootLayoutExports, renderPages as default };