@justanarthur/payload-www 1.4.2 → 2.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/dist/pages.d.ts CHANGED
@@ -22,21 +22,31 @@ 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;
42
+ /** Rendered while the document streams. Defaults to nothing. */
43
+ fallback?: ReactNode2;
35
44
  };
36
- declare function createCollectionPageExports<S extends string = "pages">({ slug: collectionSlug, config: configPromise, importMap, routing, slugShape }: CreateCollectionPageExportsArgs<S>, { getServerSideURL, pagePathPrefix }: CreateCollectionPageExportsDeps<S>): {
37
- default: (props: NextPageProps) => Promise<ReactNode2>;
45
+ declare function createCollectionPageExports<S extends string = "pages">({ slug: collectionSlug, _payloadConfig, importMap, routing, slugShape }: CreateCollectionPageExportsArgs<S>, { getServerSideURL, pagePathPrefix, fallback }: CreateCollectionPageExportsDeps<S>): {
46
+ default: (props: NextPageProps) => ReactNode2;
38
47
  generateMetadata: (props: NextPageProps) => Promise<Metadata>;
39
48
  generateStaticParams: (props: NextPageProps) => Promise<{
49
+ locale: string;
40
50
  slug: string | string[];
41
51
  }[]>;
42
52
  generateSitemap: {
@@ -51,4 +61,4 @@ declare const pages: {
51
61
  HeaderPage: typeof HeaderPage;
52
62
  FooterPage: typeof FooterPage;
53
63
  };
54
- export { pages as default, createCollectionPageExports, PagesPage, HeaderPage, FooterPage, CreateCollectionPageExportsDeps, CreateCollectionPageExportsArgs };
64
+ 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 ?? [];
@@ -178,7 +174,7 @@ async function PagesPage({ data, locale, ...props }) {
178
174
  }
179
175
 
180
176
  // src/render/pages/createCollectionPageExports.tsx
181
- import"server-only";
177
+ import * as React from "react";
182
178
 
183
179
  // src/render/metadata/slug.ts
184
180
  var SLUG_NESTED_DIVIDER = "_";
@@ -199,135 +195,112 @@ function slugToPath(slug) {
199
195
  }
200
196
 
201
197
  // src/render/metadata/query.ts
198
+ import { createCacheHelpers } from "@pro-laico/payload-revalidate/cache";
199
+ import { tagsFor } from "@pro-laico/payload-revalidate";
200
+ import { cacheLife } from "next/cache";
202
201
  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}`;
202
+ var _helpers = null;
203
+ var _seedPromise = null;
204
+ function seedPayloadCache({ config }) {
205
+ if (_helpers || _seedPromise)
206
+ return;
207
+ _seedPromise = (async () => {
208
+ const payload = await getPayload({ config: await config });
209
+ _helpers = createCacheHelpers(payload);
210
+ })();
233
211
  }
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 })();
212
+ async function requireCacheHelpers() {
213
+ if (_helpers)
214
+ return _helpers;
215
+ if (_seedPromise) {
216
+ await _seedPromise;
217
+ if (_helpers)
218
+ return _helpers;
219
+ }
220
+ 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
221
  }
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 });
222
+ async function queryDocBySlug(args) {
223
+ "use cache";
224
+ cacheLife("weeks");
225
+ const { findDoc } = await requireCacheHelpers();
226
+ const slugField = args.slugField ?? "slug";
227
+ const result = await findDoc(args.collectionSlug, {
228
+ where: { [slugField]: { equals: args.slug } },
229
+ locale: args.locale,
230
+ draft: args.draft ?? false,
231
+ depth: args.depth
246
232
  });
233
+ return result ?? null;
247
234
  }
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
235
+ async function queryGlobal(args) {
236
+ "use cache";
237
+ cacheLife("weeks");
238
+ const { findGlobal } = await requireCacheHelpers();
239
+ try {
240
+ const result = await findGlobal(args.globalSlug, {
241
+ locale: args.locale,
242
+ draft: args.draft ?? false,
243
+ depth: args.depth
266
244
  });
267
- return result.docs?.[0] ?? null;
268
- });
245
+ return result ?? null;
246
+ } catch (error) {
247
+ console.warn("[WWW] queryGlobal failed", { globalSlug: args.globalSlug, locale: args.locale, error: String(error) });
248
+ return null;
249
+ }
269
250
  }
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
- });
251
+ async function queryAllDocs(args) {
252
+ "use cache";
253
+ cacheLife("weeks");
254
+ const { findIds, findDocByID } = await requireCacheHelpers();
255
+ const collection = args.collectionSlug;
256
+ const { ids } = await findIds(collection, { locale: args.locale });
257
+ if (ids.length === 0)
258
+ return [];
259
+ const docs = await Promise.all(ids.map((id) => findDocByID(collection, id, { locale: args.locale })));
260
+ return docs.filter((d) => d !== null);
285
261
  }
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
- });
262
+ async function queryDoc(args) {
263
+ if ("globalSlug" in args)
264
+ return queryGlobal(args);
265
+ return queryDocBySlug(args);
305
266
  }
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 }
267
+ async function queryAllLocaleSlugs(args) {
268
+ "use cache";
269
+ cacheLife("weeks");
270
+ const { findDocByID } = await requireCacheHelpers();
271
+ const slugField = args.slugField ?? "slug";
272
+ const doc = await findDocByID(args.collectionSlug, args.id, { locale: "all", select: { [slugField]: true } });
273
+ const localeMap = doc?.[slugField];
274
+ if (localeMap && typeof localeMap === "object")
275
+ return localeMap;
276
+ return null;
277
+ }
278
+ async function queryDocByID(args) {
279
+ "use cache";
280
+ cacheLife("weeks");
281
+ const { findDocByID } = await requireCacheHelpers();
282
+ return await findDocByID(args.collectionSlug, args.id, {
283
+ locale: args.locale,
284
+ draft: args.draft ?? false,
285
+ depth: args.depth
318
286
  });
319
- return doc?.[slugField];
320
287
  }
321
288
 
322
289
  // src/render/pages/createCollectionPageExports.tsx
323
290
  import { setRequestLocale } from "next-intl/server";
324
291
 
325
292
  // src/render/pages/utils/buildLocalizedPath.ts
293
+ function resolvePagePathPrefix(prefix, locale, routing) {
294
+ if (typeof prefix !== "object")
295
+ return prefix;
296
+ return prefix[locale] ?? prefix[routing.defaultLocale];
297
+ }
326
298
  function buildLocalizedPath(locale, prefix, slug, { routing }) {
327
299
  const path = slugToPath(slug);
300
+ const localePrefix = resolvePagePathPrefix(prefix, locale, routing);
328
301
  return `${routing.localePrefix === "never" ? "" : routing.localePrefix === "always" ? locale : routing.localePrefix === "as-needed" ? locale === routing.defaultLocale ? "" : "/" + locale : (() => {
329
302
  throw new Error("Unsupported locale prefix");
330
- })()}${prefix ? "/" + prefix : ""}${path ? "/" + path : ""}`;
303
+ })()}${localePrefix ? "/" + localePrefix : ""}${path ? "/" + path : ""}`;
331
304
  }
332
305
  function buildLocalizedPaths(localesSlug, pagePathPrefix, { routing }) {
333
306
  const blankIsHome = !localesSlug[routing.defaultLocale];
@@ -382,25 +355,31 @@ async function renderWWWDataModule(data, {
382
355
  import { jsx as jsx6, Fragment as Fragment2 } from "react/jsx-runtime";
383
356
  function createCollectionPageExports({
384
357
  slug: collectionSlug = "pages",
385
- config: configPromise,
358
+ _payloadConfig,
386
359
  importMap,
387
360
  routing,
388
361
  slugShape = "single"
389
362
  }, {
390
363
  getServerSideURL,
391
- pagePathPrefix
364
+ pagePathPrefix,
365
+ fallback
392
366
  }) {
367
+ seedPayloadCache({ config: _payloadConfig });
393
368
  const siteUrl = getServerSideURL();
394
369
  async function fetchDoc(locale, slug) {
395
370
  return queryDoc({
396
371
  slug,
397
372
  locale,
398
373
  collectionSlug
399
- }, {
400
- config: configPromise
401
374
  });
402
375
  }
403
- const default_ = async (props) => {
376
+ const default_ = (props) => /* @__PURE__ */ jsx6(React.Suspense, {
377
+ fallback: fallback ?? null,
378
+ children: /* @__PURE__ */ jsx6(CollectionDocument, {
379
+ ...props
380
+ })
381
+ });
382
+ const CollectionDocument = async (props) => {
404
383
  const params = await props.params;
405
384
  const locale = params.locale;
406
385
  if (!routing.locales.includes(locale)) {
@@ -414,22 +393,25 @@ function createCollectionPageExports({
414
393
  const { notFound } = await import("next/navigation");
415
394
  notFound();
416
395
  }
417
- const rendered = renderWWWDataModule(doc, { collectionSlug, config: configPromise, importMap }, { ...props, locale });
396
+ const rendered = renderWWWDataModule(doc, { collectionSlug, config: _payloadConfig, importMap }, { ...props, locale });
418
397
  return /* @__PURE__ */ jsx6(Fragment2, {
419
398
  children: rendered
420
399
  });
421
400
  };
422
401
  async function generateMetadata(props) {
423
402
  const params = await props.params;
424
- const locale = params.locale, slug = paramsSlugToSlug(params.slug, slugShape);
403
+ const locale = params.locale;
404
+ if (!routing.locales.includes(locale)) {
405
+ return {};
406
+ }
407
+ const slug = paramsSlugToSlug(params.slug, slugShape);
425
408
  const doc = await fetchDoc(locale, slug);
426
409
  const [localesSlug, siteDefaults] = await Promise.all([
427
410
  doc ? queryAllLocaleSlugs({
428
411
  id: doc.id,
429
- collectionSlug,
430
- config: configPromise
412
+ collectionSlug
431
413
  }) : Promise.resolve({}),
432
- createSiteDefaults({ config: configPromise, locale })
414
+ createSiteDefaults({ config: _payloadConfig, locale })
433
415
  ]);
434
416
  if (!doc)
435
417
  return {};
@@ -446,22 +428,23 @@ function createCollectionPageExports({
446
428
  return { ...meta, alternates };
447
429
  }
448
430
  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) }));
431
+ await props.params;
432
+ const perLocaleEntries = await Promise.all(routing.locales.map(async (locale) => {
433
+ const docs = await queryAllDocs({ locale, collectionSlug });
434
+ return docs.filter((doc) => typeof doc.slug === "string" && doc.slug.length > 0).map((doc) => ({ locale, slug: slugToParamsSlug(doc.slug, slugShape) }));
435
+ }));
436
+ return perLocaleEntries.flat();
452
437
  }
453
438
  async function generateSitemap() {
454
439
  const locale = routing.defaultLocale;
455
440
  const docs = await queryAllDocs({
456
441
  collectionSlug,
457
- locale,
458
- config: configPromise
442
+ locale: routing.defaultLocale
459
443
  });
460
444
  return await Promise.all(docs.map(async (doc) => {
461
445
  const localesSlug = await queryAllLocaleSlugs({
462
446
  id: doc.id,
463
- collectionSlug,
464
- config: configPromise
447
+ collectionSlug
465
448
  }) ?? {};
466
449
  const alternates = buildAlternates(locale, localesSlug, pagePathPrefix, { routing, siteUrl });
467
450
  return {
@@ -472,7 +455,7 @@ function createCollectionPageExports({
472
455
  }));
473
456
  }
474
457
  generateSitemap.getServerSideURL = getServerSideURL;
475
- generateSitemap.pagePathPrefix = pagePathPrefix;
458
+ generateSitemap.pagePathPrefix = resolvePagePathPrefix(pagePathPrefix, routing.defaultLocale, routing);
476
459
  return {
477
460
  default: default_,
478
461
  generateMetadata,
@@ -499,9 +482,9 @@ ${sitemaps.map((url) => ` <sitemap><loc>${url}</loc></sitemap>`).join(`
499
482
  var pages = { createCollectionPageExports, PagesPage, HeaderPage, FooterPage };
500
483
  var pages_default = pages;
501
484
  export {
502
- pages_default as default,
503
- createCollectionPageExports,
504
- PagesPage,
485
+ FooterPage,
505
486
  HeaderPage,
506
- FooterPage
487
+ PagesPage,
488
+ createCollectionPageExports,
489
+ pages_default as default
507
490
  };
@@ -31,21 +31,31 @@ 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;
51
+ /** Rendered while the document streams. Defaults to nothing. */
52
+ fallback?: ReactNode2;
44
53
  };
45
- declare function createCollectionPageExports<S extends string = "pages">({ slug: collectionSlug, config: configPromise, importMap, routing, slugShape }: CreateCollectionPageExportsArgs<S>, { getServerSideURL, pagePathPrefix }: CreateCollectionPageExportsDeps<S>): {
46
- default: (props: NextPageProps) => Promise<ReactNode2>;
54
+ declare function createCollectionPageExports<S extends string = "pages">({ slug: collectionSlug, _payloadConfig, importMap, routing, slugShape }: CreateCollectionPageExportsArgs<S>, { getServerSideURL, pagePathPrefix, fallback }: CreateCollectionPageExportsDeps<S>): {
55
+ default: (props: NextPageProps) => ReactNode2;
47
56
  generateMetadata: (props: NextPageProps) => Promise<Metadata>;
48
57
  generateStaticParams: (props: NextPageProps) => Promise<{
58
+ locale: string;
49
59
  slug: string | string[];
50
60
  }[]>;
51
61
  generateSitemap: {
@@ -56,9 +66,9 @@ declare function createCollectionPageExports<S extends string = "pages">({ slug:
56
66
  };
57
67
  import { ImportMap as ImportMap4, SanitizedConfig as SanitizedConfig3 } from "payload";
58
68
  import { HTMLAttributes, ReactNode as ReactNode3 } from "react";
59
- import { JSX as JSX_1kxb2 } from "react/jsx-runtime";
69
+ import { JSX as JSX_1kxb2 } from "react";
60
70
  type CreateRootLayoutExportsArgs = {
61
- config: Promise<SanitizedConfig3>;
71
+ _payloadConfig: Promise<SanitizedConfig3>;
62
72
  importMap: ImportMap4;
63
73
  routing: RoutingConfig;
64
74
  };
@@ -72,7 +82,7 @@ type CreateRootLayoutExportsDeps = {
72
82
  getServerSideURL?: () => string;
73
83
  };
74
84
  type Element_12xgc2 = JSX_1kxb2["Element"];
75
- declare function createRootLayoutExports({ config: configPromise, importMap, routing }: CreateRootLayoutExportsArgs, { providers, htmlAttrs, getServerSideURL }?: CreateRootLayoutExportsDeps): {
85
+ declare function createRootLayoutExports({ _payloadConfig, importMap, routing }: CreateRootLayoutExportsArgs, { providers, htmlAttrs, getServerSideURL }?: CreateRootLayoutExportsDeps): {
76
86
  default: (props: NextLayoutProps) => Promise<Element_12xgc2>;
77
87
  generateStaticParams: () => {
78
88
  locale: string;
@@ -89,4 +99,4 @@ declare const renderPages: {
89
99
  FooterPage: typeof FooterPage;
90
100
  RootJsonLd: any;
91
101
  };
92
- export { renderPages as default, createRootLayoutExports, createCollectionPageExports, RootJsonLdProps, RootJsonLd, PostsPage, PagesPage, HeaderPage, FooterPage, CreateRootLayoutProvidersArgs, CreateRootLayoutExportsDeps, CreateRootLayoutExportsArgs, CreateCollectionPageExportsDeps, CreateCollectionPageExportsArgs };
102
+ export { CreateCollectionPageExportsArgs, CreateCollectionPageExportsDeps, CreateRootLayoutExportsArgs, CreateRootLayoutExportsDeps, CreateRootLayoutProvidersArgs, FooterPage, HeaderPage, PagesPage, PostsPage, RootJsonLd, RootJsonLdProps, createCollectionPageExports, createRootLayoutExports, renderPages as default };