@justanarthur/payload-www 1.4.1 → 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,142 +192,118 @@ 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
- if (!localesSlug[routing.defaultLocale])
334
- return {};
303
+ const blankIsHome = !localesSlug[routing.defaultLocale];
335
304
  return routing.locales.reduce((paths, locale) => {
336
305
  const slug = localesSlug[locale];
337
- if (!slug)
306
+ if (!slug && !blankIsHome)
338
307
  return paths;
339
308
  paths[locale] = buildLocalizedPath(locale, pagePathPrefix, slug, { routing });
340
309
  return paths;
@@ -383,7 +352,7 @@ async function renderWWWDataModule(data, {
383
352
  import { jsx as jsx6, Fragment as Fragment2 } from "react/jsx-runtime";
384
353
  function createCollectionPageExports({
385
354
  slug: collectionSlug = "pages",
386
- config: configPromise,
355
+ _payloadConfig,
387
356
  importMap,
388
357
  routing,
389
358
  slugShape = "single"
@@ -391,14 +360,13 @@ function createCollectionPageExports({
391
360
  getServerSideURL,
392
361
  pagePathPrefix
393
362
  }) {
363
+ seedPayloadCache({ config: _payloadConfig });
394
364
  const siteUrl = getServerSideURL();
395
365
  async function fetchDoc(locale, slug) {
396
366
  return queryDoc({
397
367
  slug,
398
368
  locale,
399
369
  collectionSlug
400
- }, {
401
- config: configPromise
402
370
  });
403
371
  }
404
372
  const default_ = async (props) => {
@@ -415,22 +383,25 @@ function createCollectionPageExports({
415
383
  const { notFound } = await import("next/navigation");
416
384
  notFound();
417
385
  }
418
- const rendered = renderWWWDataModule(doc, { collectionSlug, config: configPromise, importMap }, { ...props, locale });
386
+ const rendered = renderWWWDataModule(doc, { collectionSlug, config: _payloadConfig, importMap }, { ...props, locale });
419
387
  return /* @__PURE__ */ jsx6(Fragment2, {
420
388
  children: rendered
421
389
  });
422
390
  };
423
391
  async function generateMetadata(props) {
424
392
  const params = await props.params;
425
- 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);
426
398
  const doc = await fetchDoc(locale, slug);
427
399
  const [localesSlug, siteDefaults] = await Promise.all([
428
400
  doc ? queryAllLocaleSlugs({
429
401
  id: doc.id,
430
- collectionSlug,
431
- config: configPromise
402
+ collectionSlug
432
403
  }) : Promise.resolve({}),
433
- createSiteDefaults({ config: configPromise, locale })
404
+ createSiteDefaults({ config: _payloadConfig, locale })
434
405
  ]);
435
406
  if (!doc)
436
407
  return {};
@@ -447,22 +418,23 @@ function createCollectionPageExports({
447
418
  return { ...meta, alternates };
448
419
  }
449
420
  async function generateStaticParams(props) {
450
- const locale = (await props.params).locale;
451
- const docs = await queryAllDocs({ locale, collectionSlug, config: configPromise });
452
- 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();
453
427
  }
454
428
  async function generateSitemap() {
455
429
  const locale = routing.defaultLocale;
456
430
  const docs = await queryAllDocs({
457
431
  collectionSlug,
458
- locale,
459
- config: configPromise
432
+ locale: routing.defaultLocale
460
433
  });
461
434
  return await Promise.all(docs.map(async (doc) => {
462
435
  const localesSlug = await queryAllLocaleSlugs({
463
436
  id: doc.id,
464
- collectionSlug,
465
- config: configPromise
437
+ collectionSlug
466
438
  }) ?? {};
467
439
  const alternates = buildAlternates(locale, localesSlug, pagePathPrefix, { routing, siteUrl });
468
440
  return {
@@ -473,7 +445,7 @@ function createCollectionPageExports({
473
445
  }));
474
446
  }
475
447
  generateSitemap.getServerSideURL = getServerSideURL;
476
- generateSitemap.pagePathPrefix = pagePathPrefix;
448
+ generateSitemap.pagePathPrefix = resolvePagePathPrefix(pagePathPrefix, routing.defaultLocale, routing);
477
449
  return {
478
450
  default: default_,
479
451
  generateMetadata,
@@ -500,9 +472,9 @@ ${sitemaps.map((url) => ` <sitemap><loc>${url}</loc></sitemap>`).join(`
500
472
  var pages = { createCollectionPageExports, PagesPage, HeaderPage, FooterPage };
501
473
  var pages_default = pages;
502
474
  export {
503
- pages_default as default,
504
- createCollectionPageExports,
505
- PagesPage,
475
+ FooterPage,
506
476
  HeaderPage,
507
- FooterPage
477
+ PagesPage,
478
+ createCollectionPageExports,
479
+ pages_default as default
508
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 };