@justanarthur/payload-www 2.2.9 → 2.4.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/README.md CHANGED
@@ -20,7 +20,7 @@ The composition root is `createWWWConfig()` — see [Quick start](#quick-start)
20
20
  | Fields | [`/fields`](#fields) | `link`, `linkGroup` (with `disableLabel` / `appearances` / `localized` / `relationTo` / `extraFields`), `slugField`, `appearanceOptions`. |
21
21
  | Access | [`/access`](#access) | `anyone`, `authenticated`, `authenticatedOrPublished`. |
22
22
  | Caching | [`Caching`](#caching) | Cached query getters wrap `@pro-laico/payload-revalidate` finders; tag-based invalidation via `revalidatePlugin()`; `seedPayloadCache` singleton seed. |
23
- | Metadata | [`/metadata`](#metadata) | `buildArticleLd`, `buildBreadcrumbsLd`, `buildOrganizationLd`, `buildWebSiteLd`, `buildProductLd`, `buildRootJsonLd`; slug transforms; `queryDocBySlug`, `queryDocByID`, `queryGlobal`, `queryAllDocs`, `queryAllLocaleSlugs`; `seedPayloadCache`, `tagsFor`. |
23
+ | Metadata | [`/metadata`](#metadata) | `buildArticleLd`, `buildBreadcrumbsLd`, `buildOrganizationLd`, `buildWebSiteLd`, `buildProductLd`, `buildRootJsonLd`; slug transforms; `queryDocBySlug`, `queryDocByID`, `queryGlobal`, `queryDocs`, `queryAllDocs`, `queryAllLocaleSlugs`; `seedPayloadCache`, `tagsFor`. |
24
24
  | Next.js page renderers | [`/render-pages`](#render-pages) | `createCollectionPageExports`, `createRootLayoutExports`; default render components `PagesPage`, `PostsPage`, `HeaderPage`, `FooterPage`, `RootJsonLd`. |
25
25
  | Sitemap | [`/sitemap`](#sitemap) | `createSitemapFromCollections` (Next.js file-convention helper). |
26
26
  | Plugin re-exports | [`/imagehash`](#plugin-re-exports), [`/translator`](#plugin-re-exports) | Drop-in for hosts that don't want to import the sibling packages directly. |
@@ -255,8 +255,8 @@ in the host's `revalidatePlugin()` registration (see [Caching](#caching) below).
255
255
 
256
256
  ### Caching
257
257
 
258
- The lib's cached query layer (`queryDocBySlug`, `queryGlobal`, `queryAllDocs`, `queryAllLocaleSlugs`,
259
- `queryDocByID`) wraps `@pro-laico/payload-revalidate`'s finders in `'use cache'` + `cacheLife('weeks')`
258
+ The lib's cached query layer (`queryDocBySlug`, `queryGlobal`, `queryDocs`, `queryAllDocs`,
259
+ `queryAllLocaleSlugs`, `queryDocByID`) wraps `@pro-laico/payload-revalidate`'s finders in `'use cache'` + `cacheLife('weeks')`
260
260
  scopes. Setup:
261
261
 
262
262
  1. **Install the peer deps at the workspace root** (not in the lib's `dependencies` — `file:` links
@@ -303,6 +303,30 @@ scopes. Setup:
303
303
  seedPayloadCache({ config })
304
304
  ```
305
305
 
306
+ 6. **List with `queryDocs`, never a raw `payload.find`** — a read inside `'use cache'` that
307
+ doesn't go through the finders carries no tags, so nothing the admin does can bust it.
308
+ `queryDocs` tags a per-collection `content` list plus every returned doc and what is
309
+ populated into it:
310
+
311
+ ```ts
312
+ import { queryDocs } from '@justanarthur/payload-www/metadata'
313
+
314
+ const { docs, totalPages } = await queryDocs({
315
+ collectionSlug: 'posts',
316
+ locale,
317
+ sort: '-publishedAt',
318
+ limit: 10,
319
+ depth: 1
320
+ })
321
+ ```
322
+
323
+ `createWWWConfig` declares that `content` scope on every collection over all its top-level
324
+ fields, so creating, publishing, unpublishing, deleting or really changing any doc refreshes
325
+ every listing of its collection — a moved date or category reorders an archive even when that
326
+ post wasn't on the page. Saves that change nothing and draft saves leave it alone. For a
327
+ narrower listing, declare a scope through `defaultPluginsConfigs.revalidate` and pass it as
328
+ `list`.
329
+
306
330
  The cached profile is `cacheLife('weeks')` — Next 16's built-in long-tail profile (5 m stale,
307
331
  1 w revalidate, 30 d expire). No custom `cacheLife` config entry needed. Invalidations are
308
332
  purely tag-based: `revalidatePlugin()` fires the same tags the finders emit, so every save /
@@ -346,6 +370,7 @@ import {
346
370
  queryDocBySlug, // cached collection fetch
347
371
  queryDocByID, // cached collection fetch by id
348
372
  queryGlobal, // cached global fetch
373
+ queryDocs, // cached, tagged listing (where / sort / limit / page)
349
374
  queryAllDocs, // for generateStaticParams
350
375
  queryAllLocaleSlugs, // for hreflang alternates
351
376
  seedPayloadCache, // one-time seed for the pro-laico cache helpers
@@ -398,7 +423,7 @@ The package's `package.json#exports` map:
398
423
  | `@justanarthur/payload-www/collections` | `createWWWCollectionGlobal`, `queryDoc` |
399
424
  | `@justanarthur/payload-www/fields` | `link`, `linkGroup`, `appearanceOptions`, `slugField`, `LinkAppearances`, `LinkOptions` |
400
425
  | `@justanarthur/payload-www/access` | `anyone`, `authenticated`, `authenticatedOrPublished` |
401
- | `@justanarthur/payload-www/metadata` | `buildArticleLd`, `buildBreadcrumbsLd`, `buildOrganizationLd`, `buildWebSiteLd`, `buildProductLd`, `buildRootJsonLd`, `queryDocBySlug`, `queryDocByID`, `queryGlobal`, `queryAllDocs`, `queryAllLocaleSlugs`, `seedPayloadCache`, `tagsFor`, `paramsSlugToSlug`, `slugToParamsSlug` + types |
426
+ | `@justanarthur/payload-www/metadata` | `buildArticleLd`, `buildBreadcrumbsLd`, `buildOrganizationLd`, `buildWebSiteLd`, `buildProductLd`, `buildRootJsonLd`, `queryDocBySlug`, `queryDocByID`, `queryGlobal`, `queryDocs`, `queryAllDocs`, `queryAllLocaleSlugs`, `seedPayloadCache`, `tagsFor`, `paramsSlugToSlug`, `slugToParamsSlug` + types |
402
427
  | `@justanarthur/payload-www/utils` | `generateImportName`, `getFromImportMap` |
403
428
  | `@justanarthur/payload-www/imagehash` | `imageHashPlugin`, `BlurhashPluginOptions` (re-export of `@justanarthur/payload-imagehash-plugin`) |
404
429
  | `@justanarthur/payload-www/translator` | `translator` (re-export of `@justanarthur/payload-plugin-translator`) |
@@ -111,6 +111,27 @@ function slugToPath(slug) {
111
111
  return slug.split(SLUG_NESTED_DIVIDER).join("/");
112
112
  }
113
113
 
114
+ // src/revalidate/contentLists.ts
115
+ import { revalidatePlugin } from "@pro-laico/payload-revalidate";
116
+ import { flattenTopLevelFields } from "payload";
117
+ var CONTENT_LIST = "content";
118
+ function revalidateWithContentLists(options) {
119
+ return (config) => revalidatePlugin({
120
+ ...options,
121
+ collections: { ...options.collections, ...contentLists(config.collections ?? [], options.collections ?? {}) }
122
+ })(config);
123
+ }
124
+ function contentLists(collections, overrides) {
125
+ return Object.fromEntries(collections.flatMap(({ slug, fields, custom }) => {
126
+ const marker = custom?.revalidate;
127
+ const override = overrides[slug];
128
+ if (override === false || marker === false && override === undefined)
129
+ return [];
130
+ const lists = { [CONTENT_LIST]: flattenTopLevelFields(fields).map(({ name }) => name), ...marker?.lists, ...override?.lists };
131
+ return [[slug, { ...override, lists }]];
132
+ }));
133
+ }
134
+
114
135
  // src/render/metadata/query.ts
115
136
  var _helpers = null;
116
137
  var _seedPromise = null;
@@ -119,7 +140,7 @@ function seedPayloadCache({ config }) {
119
140
  return;
120
141
  _seedPromise = (async () => {
121
142
  const payload = await getPayload({ config: await config });
122
- _helpers = createCacheHelpers(payload);
143
+ _helpers = { ...createCacheHelpers(payload), payload };
123
144
  })();
124
145
  }
125
146
  async function requireCacheHelpers() {
@@ -176,6 +197,28 @@ async function queryAllDocs(args) {
176
197
  const docs = await Promise.all(ids.map((id) => findDocByID(collection, id, { locale: args.locale, overrideAccess: false, depth: 0 })));
177
198
  return docs.filter((d) => d !== null);
178
199
  }
200
+ async function queryDocs({
201
+ collectionSlug,
202
+ list = CONTENT_LIST,
203
+ draft = false,
204
+ depth = RENDER_DEPTH,
205
+ ...find
206
+ }) {
207
+ "use cache";
208
+ cacheLife("weeks");
209
+ const { payload, cacheIds, cacheDoc } = await requireCacheHelpers();
210
+ const collection = collectionSlug;
211
+ const result = await payload.find({ ...find, collection, draft, depth, overrideAccess: draft });
212
+ await cacheIds(result, collection, { list, draft });
213
+ for (const doc of result.docs)
214
+ await cacheDoc(doc, collection, { draft });
215
+ return {
216
+ docs: result.docs,
217
+ totalDocs: result.totalDocs,
218
+ totalPages: result.totalPages,
219
+ page: result.page ?? 1
220
+ };
221
+ }
179
222
  async function queryDoc(args) {
180
223
  if ("globalSlug" in args)
181
224
  return queryGlobal(args);
package/dist/config.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { CollectionConfig, Config, GlobalConfig, Plugin } from "payload";
2
2
  import { MCPPluginConfig } from "@payloadcms/plugin-mcp";
3
+ import { RevalidatePluginOptions } from "@pro-laico/payload-revalidate";
3
4
  import { SEOPluginConfig } from "@justanarthur/payload-plugin-seo/types";
4
5
  import { BlurhashPluginOptions } from "@justanarthur/payload-imagehash-plugin/types";
5
6
  import { TranslatorConfig } from "@justanarthur/payload-plugin-translator/types";
@@ -15,7 +16,7 @@ type WWWInputConfig = Omit<Config, "collections" | "globals" | "plugins"> & {
15
16
  imageHash?: MergeOrOverride<BlurhashPluginOptions>;
16
17
  translator?: MergeOrOverride<TranslatorConfig>;
17
18
  mcp?: MergeOrOverride<MCPPluginConfig>;
18
- revalidate?: false | (<D>(d: D) => D);
19
+ revalidate?: false | MergeOrOverride<RevalidatePluginOptions>;
19
20
  };
20
21
  };
21
22
  declare function createWWWConfig(): WWWConfigApi;
package/dist/config.js CHANGED
@@ -313,10 +313,33 @@ import { seoPlugin } from "@justanarthur/payload-plugin-seo";
313
313
  import { imageHashPlugin } from "@justanarthur/payload-imagehash-plugin";
314
314
  import { translator } from "@justanarthur/payload-plugin-translator";
315
315
  import { mcpPlugin } from "@payloadcms/plugin-mcp";
316
+
317
+ // src/revalidate/contentLists.ts
316
318
  import { revalidatePlugin } from "@pro-laico/payload-revalidate";
319
+ import { flattenTopLevelFields } from "payload";
320
+ var CONTENT_LIST = "content";
321
+ function revalidateWithContentLists(options) {
322
+ return (config) => revalidatePlugin({
323
+ ...options,
324
+ collections: { ...options.collections, ...contentLists(config.collections ?? [], options.collections ?? {}) }
325
+ })(config);
326
+ }
327
+ function contentLists(collections, overrides) {
328
+ return Object.fromEntries(collections.flatMap(({ slug, fields, custom }) => {
329
+ const marker = custom?.revalidate;
330
+ const override = overrides[slug];
331
+ if (override === false || marker === false && override === undefined)
332
+ return [];
333
+ const lists = { [CONTENT_LIST]: flattenTopLevelFields(fields).map(({ name }) => name), ...marker?.lists, ...override?.lists };
334
+ return [[slug, { ...override, lists }]];
335
+ }));
336
+ }
337
+
338
+ // src/createWWWConfig.ts
317
339
  function createWWWConfig() {
318
340
  function withWWWConfig(input) {
319
341
  const { defaultPluginsConfigs, ...config } = input;
342
+ const revalidate = defaultPluginsConfigs?.revalidate;
320
343
  const blocks = config.blocks || [];
321
344
  const collections = mergeOrOverride([
322
345
  createPagesCollection(blocks),
@@ -362,7 +385,7 @@ function createWWWConfig() {
362
385
  ];
363
386
  const plugins = [
364
387
  ...mergeOrOverride(defaultPlugins, config.plugins),
365
- revalidatePlugin()
388
+ revalidateWithContentLists(revalidate === false ? { enabled: false } : mergeOrOverride({}, revalidate))
366
389
  ];
367
390
  return {
368
391
  ...config,
@@ -22,7 +22,7 @@ declare function paramsSlugToSlug(slug: string | string[] | undefined, _shape: S
22
22
  declare function slugToParamsSlug(slug: string, shape: SlugShape): string | string[];
23
23
  declare function isIndexSlug(slug: string | null | undefined): boolean;
24
24
  declare function shapeHasIndexPath(shape: SlugShape): boolean;
25
- import { DataFromCollectionSlug, DataFromGlobalSlug, SanitizedConfig } from "payload";
25
+ import { DataFromCollectionSlug, DataFromGlobalSlug, SanitizedConfig, SelectType, Sort, Where } from "payload";
26
26
  import { tagsFor } from "@pro-laico/payload-revalidate";
27
27
  type SeedPayloadCacheArgs = {
28
28
  config: SanitizedConfig | Promise<SanitizedConfig>;
@@ -47,9 +47,28 @@ type QueryListArgs<S extends string> = {
47
47
  slugField?: string;
48
48
  locale: string;
49
49
  };
50
+ type QueryDocsArgs<S extends string> = {
51
+ collectionSlug: S;
52
+ locale: string;
53
+ where?: Where;
54
+ sort?: Sort;
55
+ limit?: number;
56
+ page?: number;
57
+ depth?: number;
58
+ select?: SelectType;
59
+ draft?: boolean;
60
+ list?: string;
61
+ };
62
+ type QueryDocsResult<S extends string> = {
63
+ docs: DataFromCollectionSlug<S>[];
64
+ totalDocs: number;
65
+ totalPages: number;
66
+ page: number;
67
+ };
50
68
  declare function queryDocBySlug<S extends string>(args: QueryCollectionArgs<S>): Promise<DataFromCollectionSlug<S> | null>;
51
69
  declare function queryGlobal<G extends string>(args: QueryGlobalArgs<G>): Promise<DataFromGlobalSlug<G> | null>;
52
70
  declare function queryAllDocs<S extends string = string>(args: QueryListArgs<S>): Promise<DataFromCollectionSlug<S>[]>;
71
+ declare function queryDocs<S extends string>({ collectionSlug, list, draft, depth,...find }: QueryDocsArgs<S>): Promise<QueryDocsResult<S>>;
53
72
  declare function queryAllLocaleSlugs(args: {
54
73
  collectionSlug: string;
55
74
  id: number | string;
@@ -74,6 +93,7 @@ declare const metadata: {
74
93
  queryDocBySlug: typeof queryDocBySlug;
75
94
  queryDocByID: typeof queryDocByID;
76
95
  queryGlobal: typeof queryGlobal;
96
+ queryDocs: typeof queryDocs;
77
97
  queryAllDocs: typeof queryAllDocs;
78
98
  queryAllLocaleSlugs: typeof queryAllLocaleSlugs;
79
99
  paramsSlugToSlug: typeof paramsSlugToSlug;
@@ -83,4 +103,4 @@ declare const metadata: {
83
103
  seedPayloadCache: typeof seedPayloadCache;
84
104
  tagsFor: (payload: Payload_eipjla) => Tags_1jpdl;
85
105
  };
86
- export { ArticleLdOptions, BreadcrumbItem, BuildOrganizationLdOptions, BuildProductLdOptions, BuildRootJsonLdOptions, BuildWebSiteLdOptions, SeedPayloadCacheArgs, SlugShape, buildArticleLd, buildBreadcrumbsLd, buildOrganizationLd, buildProductLd, buildRootJsonLd, buildWebSiteLd, metadata as default, isIndexSlug, paramsSlugToSlug, queryAllDocs, queryAllLocaleSlugs, queryDocByID, queryDocBySlug, queryGlobal, seedPayloadCache, shapeHasIndexPath, slugToParamsSlug, tagsFor };
106
+ export { ArticleLdOptions, BreadcrumbItem, BuildOrganizationLdOptions, BuildProductLdOptions, BuildRootJsonLdOptions, BuildWebSiteLdOptions, QueryDocsArgs, QueryDocsResult, SeedPayloadCacheArgs, SlugShape, buildArticleLd, buildBreadcrumbsLd, buildOrganizationLd, buildProductLd, buildRootJsonLd, buildWebSiteLd, metadata as default, isIndexSlug, paramsSlugToSlug, queryAllDocs, queryAllLocaleSlugs, queryDocByID, queryDocBySlug, queryDocs, queryGlobal, seedPayloadCache, shapeHasIndexPath, slugToParamsSlug, tagsFor };
package/dist/metadata.js CHANGED
@@ -120,6 +120,29 @@ import { createCacheHelpers } from "@pro-laico/payload-revalidate/cache";
120
120
  import { tagsFor } from "@pro-laico/payload-revalidate";
121
121
  import { cacheLife } from "next/cache";
122
122
  import { getPayload } from "payload";
123
+
124
+ // src/revalidate/contentLists.ts
125
+ import { revalidatePlugin } from "@pro-laico/payload-revalidate";
126
+ import { flattenTopLevelFields } from "payload";
127
+ var CONTENT_LIST = "content";
128
+ function revalidateWithContentLists(options) {
129
+ return (config) => revalidatePlugin({
130
+ ...options,
131
+ collections: { ...options.collections, ...contentLists(config.collections ?? [], options.collections ?? {}) }
132
+ })(config);
133
+ }
134
+ function contentLists(collections, overrides) {
135
+ return Object.fromEntries(collections.flatMap(({ slug, fields, custom }) => {
136
+ const marker = custom?.revalidate;
137
+ const override = overrides[slug];
138
+ if (override === false || marker === false && override === undefined)
139
+ return [];
140
+ const lists = { [CONTENT_LIST]: flattenTopLevelFields(fields).map(({ name }) => name), ...marker?.lists, ...override?.lists };
141
+ return [[slug, { ...override, lists }]];
142
+ }));
143
+ }
144
+
145
+ // src/render/metadata/query.ts
123
146
  var _helpers = null;
124
147
  var _seedPromise = null;
125
148
  function seedPayloadCache({ config }) {
@@ -127,7 +150,7 @@ function seedPayloadCache({ config }) {
127
150
  return;
128
151
  _seedPromise = (async () => {
129
152
  const payload = await getPayload({ config: await config });
130
- _helpers = createCacheHelpers(payload);
153
+ _helpers = { ...createCacheHelpers(payload), payload };
131
154
  })();
132
155
  }
133
156
  async function requireCacheHelpers() {
@@ -184,6 +207,28 @@ async function queryAllDocs(args) {
184
207
  const docs = await Promise.all(ids.map((id) => findDocByID(collection, id, { locale: args.locale, overrideAccess: false, depth: 0 })));
185
208
  return docs.filter((d) => d !== null);
186
209
  }
210
+ async function queryDocs({
211
+ collectionSlug,
212
+ list = CONTENT_LIST,
213
+ draft = false,
214
+ depth = RENDER_DEPTH,
215
+ ...find
216
+ }) {
217
+ "use cache";
218
+ cacheLife("weeks");
219
+ const { payload, cacheIds, cacheDoc } = await requireCacheHelpers();
220
+ const collection = collectionSlug;
221
+ const result = await payload.find({ ...find, collection, draft, depth, overrideAccess: draft });
222
+ await cacheIds(result, collection, { list, draft });
223
+ for (const doc of result.docs)
224
+ await cacheDoc(doc, collection, { draft });
225
+ return {
226
+ docs: result.docs,
227
+ totalDocs: result.totalDocs,
228
+ totalPages: result.totalPages,
229
+ page: result.page ?? 1
230
+ };
231
+ }
187
232
  async function queryDoc(args) {
188
233
  if ("globalSlug" in args)
189
234
  return queryGlobal(args);
@@ -223,6 +268,7 @@ var metadata = {
223
268
  queryDocBySlug,
224
269
  queryDocByID,
225
270
  queryGlobal,
271
+ queryDocs,
226
272
  queryAllDocs,
227
273
  queryAllLocaleSlugs,
228
274
  paramsSlugToSlug,
@@ -247,6 +293,7 @@ export {
247
293
  queryAllLocaleSlugs,
248
294
  queryDocByID,
249
295
  queryDocBySlug,
296
+ queryDocs,
250
297
  queryGlobal,
251
298
  seedPayloadCache,
252
299
  shapeHasIndexPath,
package/dist/pages.js CHANGED
@@ -205,6 +205,29 @@ import { createCacheHelpers } from "@pro-laico/payload-revalidate/cache";
205
205
  import { tagsFor } from "@pro-laico/payload-revalidate";
206
206
  import { cacheLife } from "next/cache";
207
207
  import { getPayload } from "payload";
208
+
209
+ // src/revalidate/contentLists.ts
210
+ import { revalidatePlugin } from "@pro-laico/payload-revalidate";
211
+ import { flattenTopLevelFields } from "payload";
212
+ var CONTENT_LIST = "content";
213
+ function revalidateWithContentLists(options) {
214
+ return (config) => revalidatePlugin({
215
+ ...options,
216
+ collections: { ...options.collections, ...contentLists(config.collections ?? [], options.collections ?? {}) }
217
+ })(config);
218
+ }
219
+ function contentLists(collections, overrides) {
220
+ return Object.fromEntries(collections.flatMap(({ slug, fields, custom }) => {
221
+ const marker = custom?.revalidate;
222
+ const override = overrides[slug];
223
+ if (override === false || marker === false && override === undefined)
224
+ return [];
225
+ const lists = { [CONTENT_LIST]: flattenTopLevelFields(fields).map(({ name }) => name), ...marker?.lists, ...override?.lists };
226
+ return [[slug, { ...override, lists }]];
227
+ }));
228
+ }
229
+
230
+ // src/render/metadata/query.ts
208
231
  var _helpers = null;
209
232
  var _seedPromise = null;
210
233
  function seedPayloadCache({ config }) {
@@ -212,7 +235,7 @@ function seedPayloadCache({ config }) {
212
235
  return;
213
236
  _seedPromise = (async () => {
214
237
  const payload = await getPayload({ config: await config });
215
- _helpers = createCacheHelpers(payload);
238
+ _helpers = { ...createCacheHelpers(payload), payload };
216
239
  })();
217
240
  }
218
241
  async function requireCacheHelpers() {
@@ -269,6 +292,28 @@ async function queryAllDocs(args) {
269
292
  const docs = await Promise.all(ids.map((id) => findDocByID(collection, id, { locale: args.locale, overrideAccess: false, depth: 0 })));
270
293
  return docs.filter((d) => d !== null);
271
294
  }
295
+ async function queryDocs({
296
+ collectionSlug,
297
+ list = CONTENT_LIST,
298
+ draft = false,
299
+ depth = RENDER_DEPTH,
300
+ ...find
301
+ }) {
302
+ "use cache";
303
+ cacheLife("weeks");
304
+ const { payload, cacheIds, cacheDoc } = await requireCacheHelpers();
305
+ const collection = collectionSlug;
306
+ const result = await payload.find({ ...find, collection, draft, depth, overrideAccess: draft });
307
+ await cacheIds(result, collection, { list, draft });
308
+ for (const doc of result.docs)
309
+ await cacheDoc(doc, collection, { draft });
310
+ return {
311
+ docs: result.docs,
312
+ totalDocs: result.totalDocs,
313
+ totalPages: result.totalPages,
314
+ page: result.page ?? 1
315
+ };
316
+ }
272
317
  async function queryDoc(args) {
273
318
  if ("globalSlug" in args)
274
319
  return queryGlobal(args);
@@ -235,6 +235,29 @@ import { createCacheHelpers } from "@pro-laico/payload-revalidate/cache";
235
235
  import { tagsFor } from "@pro-laico/payload-revalidate";
236
236
  import { cacheLife } from "next/cache";
237
237
  import { getPayload } from "payload";
238
+
239
+ // src/revalidate/contentLists.ts
240
+ import { revalidatePlugin } from "@pro-laico/payload-revalidate";
241
+ import { flattenTopLevelFields } from "payload";
242
+ var CONTENT_LIST = "content";
243
+ function revalidateWithContentLists(options) {
244
+ return (config) => revalidatePlugin({
245
+ ...options,
246
+ collections: { ...options.collections, ...contentLists(config.collections ?? [], options.collections ?? {}) }
247
+ })(config);
248
+ }
249
+ function contentLists(collections, overrides) {
250
+ return Object.fromEntries(collections.flatMap(({ slug, fields, custom }) => {
251
+ const marker = custom?.revalidate;
252
+ const override = overrides[slug];
253
+ if (override === false || marker === false && override === undefined)
254
+ return [];
255
+ const lists = { [CONTENT_LIST]: flattenTopLevelFields(fields).map(({ name }) => name), ...marker?.lists, ...override?.lists };
256
+ return [[slug, { ...override, lists }]];
257
+ }));
258
+ }
259
+
260
+ // src/render/metadata/query.ts
238
261
  var _helpers = null;
239
262
  var _seedPromise = null;
240
263
  function seedPayloadCache({ config }) {
@@ -242,7 +265,7 @@ function seedPayloadCache({ config }) {
242
265
  return;
243
266
  _seedPromise = (async () => {
244
267
  const payload = await getPayload({ config: await config });
245
- _helpers = createCacheHelpers(payload);
268
+ _helpers = { ...createCacheHelpers(payload), payload };
246
269
  })();
247
270
  }
248
271
  async function requireCacheHelpers() {
@@ -299,6 +322,28 @@ async function queryAllDocs(args) {
299
322
  const docs = await Promise.all(ids.map((id) => findDocByID(collection, id, { locale: args.locale, overrideAccess: false, depth: 0 })));
300
323
  return docs.filter((d) => d !== null);
301
324
  }
325
+ async function queryDocs({
326
+ collectionSlug,
327
+ list = CONTENT_LIST,
328
+ draft = false,
329
+ depth = RENDER_DEPTH,
330
+ ...find
331
+ }) {
332
+ "use cache";
333
+ cacheLife("weeks");
334
+ const { payload, cacheIds, cacheDoc } = await requireCacheHelpers();
335
+ const collection = collectionSlug;
336
+ const result = await payload.find({ ...find, collection, draft, depth, overrideAccess: draft });
337
+ await cacheIds(result, collection, { list, draft });
338
+ for (const doc of result.docs)
339
+ await cacheDoc(doc, collection, { draft });
340
+ return {
341
+ docs: result.docs,
342
+ totalDocs: result.totalDocs,
343
+ totalPages: result.totalPages,
344
+ page: result.page ?? 1
345
+ };
346
+ }
302
347
  async function queryDoc(args) {
303
348
  if ("globalSlug" in args)
304
349
  return queryGlobal(args);
package/dist/sitemap.js CHANGED
@@ -30,6 +30,29 @@ import { createCacheHelpers } from "@pro-laico/payload-revalidate/cache";
30
30
  import { tagsFor } from "@pro-laico/payload-revalidate";
31
31
  import { cacheLife } from "next/cache";
32
32
  import { getPayload } from "payload";
33
+
34
+ // src/revalidate/contentLists.ts
35
+ import { revalidatePlugin } from "@pro-laico/payload-revalidate";
36
+ import { flattenTopLevelFields } from "payload";
37
+ var CONTENT_LIST = "content";
38
+ function revalidateWithContentLists(options) {
39
+ return (config) => revalidatePlugin({
40
+ ...options,
41
+ collections: { ...options.collections, ...contentLists(config.collections ?? [], options.collections ?? {}) }
42
+ })(config);
43
+ }
44
+ function contentLists(collections, overrides) {
45
+ return Object.fromEntries(collections.flatMap(({ slug, fields, custom }) => {
46
+ const marker = custom?.revalidate;
47
+ const override = overrides[slug];
48
+ if (override === false || marker === false && override === undefined)
49
+ return [];
50
+ const lists = { [CONTENT_LIST]: flattenTopLevelFields(fields).map(({ name }) => name), ...marker?.lists, ...override?.lists };
51
+ return [[slug, { ...override, lists }]];
52
+ }));
53
+ }
54
+
55
+ // src/render/metadata/query.ts
33
56
  var _helpers = null;
34
57
  var _seedPromise = null;
35
58
  function seedPayloadCache({ config }) {
@@ -37,7 +60,7 @@ function seedPayloadCache({ config }) {
37
60
  return;
38
61
  _seedPromise = (async () => {
39
62
  const payload = await getPayload({ config: await config });
40
- _helpers = createCacheHelpers(payload);
63
+ _helpers = { ...createCacheHelpers(payload), payload };
41
64
  })();
42
65
  }
43
66
  async function requireCacheHelpers() {
@@ -94,6 +117,28 @@ async function queryAllDocs(args) {
94
117
  const docs = await Promise.all(ids.map((id) => findDocByID(collection, id, { locale: args.locale, overrideAccess: false, depth: 0 })));
95
118
  return docs.filter((d) => d !== null);
96
119
  }
120
+ async function queryDocs({
121
+ collectionSlug,
122
+ list = CONTENT_LIST,
123
+ draft = false,
124
+ depth = RENDER_DEPTH,
125
+ ...find
126
+ }) {
127
+ "use cache";
128
+ cacheLife("weeks");
129
+ const { payload, cacheIds, cacheDoc } = await requireCacheHelpers();
130
+ const collection = collectionSlug;
131
+ const result = await payload.find({ ...find, collection, draft, depth, overrideAccess: draft });
132
+ await cacheIds(result, collection, { list, draft });
133
+ for (const doc of result.docs)
134
+ await cacheDoc(doc, collection, { draft });
135
+ return {
136
+ docs: result.docs,
137
+ totalDocs: result.totalDocs,
138
+ totalPages: result.totalPages,
139
+ page: result.page ?? 1
140
+ };
141
+ }
97
142
  async function queryDoc(args) {
98
143
  if ("globalSlug" in args)
99
144
  return queryGlobal(args);
package/package.json CHANGED
@@ -1,7 +1,8 @@
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": "2.2.9",
4
+ "version": "2.4.0",
5
+ "license": "MIT",
5
6
  "type": "module",
6
7
  "private": false,
7
8
  "files": [