@justanarthur/payload-www 1.3.0 → 1.4.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/README.md +2 -1
- package/dist/blocks.js +2 -4
- package/dist/collections.js +17 -89
- package/dist/config.js +12 -1
- package/dist/mcp.d.ts +3 -0
- package/dist/mcp.js +9 -0
- package/dist/metadata.js +22 -89
- package/dist/pages.d.ts +4 -16
- package/dist/pages.js +38 -104
- package/dist/render-pages.d.ts +4 -16
- package/dist/render-pages.js +38 -104
- package/dist/sitemap.d.ts +0 -2
- package/dist/sitemap.js +36 -100
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -318,8 +318,8 @@ the matching component from the host's `importMap`.
|
|
|
318
318
|
```ts
|
|
319
319
|
import { imageHashPlugin } from '@justanarthur/payload-www/imagehash'
|
|
320
320
|
import { translator } from '@justanarthur/payload-www/translator'
|
|
321
|
+
import { mcpPlugin } from '@justanarthur/payload-www/mcp'
|
|
321
322
|
import { seoPlugin } from '@justanarthur/payload-plugin-seo' // no re-export here, import directly
|
|
322
|
-
import { mcpPlugin } from '@payloadcms/plugin-mcp' // no re-export here, import directly
|
|
323
323
|
```
|
|
324
324
|
|
|
325
325
|
Use these if you want to compose the default plugin set manually outside `createWWWConfig`. Full
|
|
@@ -347,6 +347,7 @@ The package's `package.json#exports` map:
|
|
|
347
347
|
| `@justanarthur/payload-www/utils` | `generateImportName`, `getFromImportMap` |
|
|
348
348
|
| `@justanarthur/payload-www/imagehash` | `imageHashPlugin`, `BlurhashPluginOptions` (re-export of `@justanarthur/payload-imagehash-plugin`) |
|
|
349
349
|
| `@justanarthur/payload-www/translator` | `translator` (re-export of `@justanarthur/payload-plugin-translator`) |
|
|
350
|
+
| `@justanarthur/payload-www/mcp` | `mcpPlugin`, `MCPPluginConfig` (re-export of `@payloadcms/plugin-mcp`) |
|
|
350
351
|
| `@justanarthur/payload-www/import-map-provider` | `setImportMapProvider`, `getImportMap` (stubs in the current build — reserved for future use) |
|
|
351
352
|
|
|
352
353
|
There is **no root import** (`.`) and **no `/server`, `/with-www-config`, `/globals`, `/hooks`,
|
package/dist/blocks.js
CHANGED
|
@@ -32,9 +32,7 @@ var RenderBlocks = async ({ blocks, blockProps, config, importMap, locale, searc
|
|
|
32
32
|
const block = blocks[i];
|
|
33
33
|
const { blockType } = block;
|
|
34
34
|
const blockConfig = (config.blocks ?? []).find((b) => b.slug === blockType);
|
|
35
|
-
const
|
|
36
|
-
const customPath = blockCustom?.path;
|
|
37
|
-
const wantsSearchParams = blockCustom?.searchParams === true;
|
|
35
|
+
const customPath = blockConfig?.custom?.[name]?.path;
|
|
38
36
|
const importMapPath = (typeof customPath === "string" ? customPath : null) ?? `${DEFAULT_BLOCK_PATH_PREFIX}/${blockType}`;
|
|
39
37
|
const Block = await getFromImportMap(importMapPath, importMap);
|
|
40
38
|
if (!Block) {
|
|
@@ -46,7 +44,7 @@ var RenderBlocks = async ({ blocks, blockProps, config, importMap, locale, searc
|
|
|
46
44
|
...blockProps,
|
|
47
45
|
...block,
|
|
48
46
|
locale,
|
|
49
|
-
|
|
47
|
+
searchParams
|
|
50
48
|
}, i));
|
|
51
49
|
}
|
|
52
50
|
return /* @__PURE__ */ jsx(Fragment, {
|
package/dist/collections.js
CHANGED
|
@@ -177,55 +177,16 @@ async function queryAllDocs({
|
|
|
177
177
|
}) {
|
|
178
178
|
return withUnstableCache([collectionSlug, slugField2, locale], [createCollectionCacheKey({ collectionSlug, slug: "__all__", locale })], async () => {
|
|
179
179
|
const payload = await getPayload({ config });
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
limit: 1000,
|
|
191
|
-
pagination: false,
|
|
192
|
-
overrideAccess: true
|
|
193
|
-
});
|
|
194
|
-
return (result2.docs ?? []).map((d) => ({ [slugField2]: d[slugField2] }));
|
|
195
|
-
}
|
|
196
|
-
const hasVersions = Boolean(collectionConfig.versions);
|
|
197
|
-
const isSlugLocalized = (() => {
|
|
198
|
-
const fields = collectionConfig.fields;
|
|
199
|
-
if (!Array.isArray(fields))
|
|
200
|
-
return false;
|
|
201
|
-
const found = fields.find((f) => f.name === slugField2);
|
|
202
|
-
return Boolean(found?.localized);
|
|
203
|
-
})();
|
|
204
|
-
const hasLocales = Boolean(collectionConfig.custom?._isLocalized) || Boolean(payload.config.localization?.locales?.length);
|
|
205
|
-
const localesTableName = `${tableName}_locales`;
|
|
206
|
-
let sqlText;
|
|
207
|
-
const safeLocale = locale.replace(/'/g, "''");
|
|
208
|
-
if (isSlugLocalized && hasLocales) {
|
|
209
|
-
const statusFilter = hasVersions ? ` AND "${tableName}"."_status" = 'published'` : "";
|
|
210
|
-
sqlText = `
|
|
211
|
-
SELECT DISTINCT ON ("${tableName}"."id")
|
|
212
|
-
"${tableName}"."id" AS "id",
|
|
213
|
-
"${localesTableName}"."${snakeSlugField}" AS "${snakeSlugField}",
|
|
214
|
-
"${tableName}"."updated_at" AS "updated_at"
|
|
215
|
-
FROM "${tableName}"
|
|
216
|
-
JOIN "${localesTableName}" ON "${localesTableName}"."_parent_id" = "${tableName}"."id"
|
|
217
|
-
WHERE "${localesTableName}"."_locale" = '${safeLocale}'${statusFilter}
|
|
218
|
-
ORDER BY "${tableName}"."id", "${tableName}"."created_at" DESC
|
|
219
|
-
LIMIT 1000
|
|
220
|
-
`;
|
|
221
|
-
} else {
|
|
222
|
-
const statusFilter = hasVersions ? ` WHERE "_status" = 'published'` : "";
|
|
223
|
-
sqlText = `SELECT id, "${snakeSlugField}", "updated_at" FROM "${tableName}"${statusFilter} ORDER BY "created_at" DESC LIMIT 1000`;
|
|
224
|
-
}
|
|
225
|
-
const { sql: drizzleSql } = await import("drizzle-orm");
|
|
226
|
-
const result = await drizzleDb.execute(drizzleSql.raw(sqlText));
|
|
227
|
-
const rows = result.rows ?? [];
|
|
228
|
-
return rows.map((r) => ({ [slugField2]: r[snakeSlugField], id: r.id, updatedAt: r.updated_at }));
|
|
180
|
+
const result = await payload.find({
|
|
181
|
+
collection: collectionSlug,
|
|
182
|
+
draft: false,
|
|
183
|
+
limit: 1000,
|
|
184
|
+
pagination: false,
|
|
185
|
+
overrideAccess: false,
|
|
186
|
+
select: { [slugField2]: true },
|
|
187
|
+
locale
|
|
188
|
+
});
|
|
189
|
+
return result.docs ?? [];
|
|
229
190
|
});
|
|
230
191
|
}
|
|
231
192
|
async function queryAllLocaleSlugs({
|
|
@@ -235,46 +196,13 @@ async function queryAllLocaleSlugs({
|
|
|
235
196
|
config
|
|
236
197
|
}) {
|
|
237
198
|
const payload = await getPayload({ config });
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
if (!drizzleDb?.execute) {
|
|
246
|
-
const doc = await payload.findByID({
|
|
247
|
-
collection: collectionSlug,
|
|
248
|
-
id,
|
|
249
|
-
locale: "all",
|
|
250
|
-
select: { [slugField2]: true }
|
|
251
|
-
});
|
|
252
|
-
return doc?.[slugField2] ?? null;
|
|
253
|
-
}
|
|
254
|
-
const { sql: drizzleSql } = await import("drizzle-orm");
|
|
255
|
-
const slugFieldConfig = collectionConfig.fields?.find((f) => f && f.name === slugField2);
|
|
256
|
-
const slugIsLocalized = Boolean(slugFieldConfig?.localized);
|
|
257
|
-
if (!slugIsLocalized) {
|
|
258
|
-
const result2 = await drizzleDb.execute(drizzleSql`SELECT ${drizzleSql.identifier(snakeSlugField)} FROM ${drizzleSql.identifier(tableName)} WHERE "id" = ${id}`);
|
|
259
|
-
const rows2 = result2.rows ?? [];
|
|
260
|
-
const slugValue = rows2[0]?.[snakeSlugField];
|
|
261
|
-
if (typeof slugValue !== "string")
|
|
262
|
-
return null;
|
|
263
|
-
const localization = payload.config.localization;
|
|
264
|
-
const localeCodes = localization ? localization.localeCodes ?? localization.locales.map((l) => l.code) : [];
|
|
265
|
-
if (localeCodes.length === 0)
|
|
266
|
-
return null;
|
|
267
|
-
return Object.fromEntries(localeCodes.map((code) => [code, slugValue]));
|
|
268
|
-
}
|
|
269
|
-
const result = await drizzleDb.execute(drizzleSql`SELECT _locale, ${drizzleSql.identifier(snakeSlugField)} FROM ${drizzleSql.identifier(localesTableName)} WHERE "_parent_id" = ${id}`);
|
|
270
|
-
const rows = result.rows ?? [];
|
|
271
|
-
const out = {};
|
|
272
|
-
for (const r of rows) {
|
|
273
|
-
if (typeof r._locale === "string" && typeof r[snakeSlugField] === "string") {
|
|
274
|
-
out[r._locale] = r[snakeSlugField];
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
return out;
|
|
199
|
+
const doc = await payload.findByID({
|
|
200
|
+
collection: collectionSlug,
|
|
201
|
+
id,
|
|
202
|
+
locale: "all",
|
|
203
|
+
select: { [slugField2]: true }
|
|
204
|
+
});
|
|
205
|
+
return doc?.[slugField2];
|
|
278
206
|
}
|
|
279
207
|
|
|
280
208
|
// src/exports/collections.ts
|
package/dist/config.js
CHANGED
|
@@ -346,6 +346,7 @@ var createHeaderGlobal = () => createWWWCollectionGlobal([
|
|
|
346
346
|
import { seoPlugin } from "@justanarthur/payload-plugin-seo";
|
|
347
347
|
import { imageHashPlugin } from "@justanarthur/payload-imagehash-plugin";
|
|
348
348
|
import { translator } from "@justanarthur/payload-plugin-translator";
|
|
349
|
+
import { mcpPlugin } from "@payloadcms/plugin-mcp";
|
|
349
350
|
function createWWWConfig() {
|
|
350
351
|
function withWWWConfig(input) {
|
|
351
352
|
const { defaultPluginsConfigs, ...config } = input;
|
|
@@ -380,7 +381,17 @@ function createWWWConfig() {
|
|
|
380
381
|
model: "gpt-5.4-mini"
|
|
381
382
|
})
|
|
382
383
|
]
|
|
383
|
-
}, defaultPluginsConfigs?.translator))
|
|
384
|
+
}, defaultPluginsConfigs?.translator)),
|
|
385
|
+
mcpPlugin(mergeOrOverride({
|
|
386
|
+
collections: Object.fromEntries(collections.map(({ slug, admin }) => [slug, {
|
|
387
|
+
enabled: { find: true, create: true, update: true, delete: true },
|
|
388
|
+
description: typeof admin?.description === "string" ? admin.description : undefined
|
|
389
|
+
}])),
|
|
390
|
+
globals: Object.fromEntries(globals.map(({ slug, admin }) => [slug, {
|
|
391
|
+
enabled: { find: true, update: true },
|
|
392
|
+
description: typeof admin?.description === "string" ? admin.description : undefined
|
|
393
|
+
}]))
|
|
394
|
+
}, defaultPluginsConfigs?.mcp))
|
|
384
395
|
];
|
|
385
396
|
const plugins = mergeOrOverride(defaultPlugins, config.plugins);
|
|
386
397
|
return {
|
package/dist/mcp.d.ts
ADDED
package/dist/mcp.js
ADDED
package/dist/metadata.js
CHANGED
|
@@ -105,6 +105,11 @@ function slugToParamsSlug(slug, shape) {
|
|
|
105
105
|
return shape === "catch-all" ? [] : "";
|
|
106
106
|
return shape === "catch-all" ? slug.split(SLUG_NESTED_DIVIDER) : slug;
|
|
107
107
|
}
|
|
108
|
+
function slugToPath(slug) {
|
|
109
|
+
if (!slug)
|
|
110
|
+
return "";
|
|
111
|
+
return slug.split(SLUG_NESTED_DIVIDER).join("/");
|
|
112
|
+
}
|
|
108
113
|
|
|
109
114
|
// src/render/metadata/query.ts
|
|
110
115
|
import { getPayload } from "payload";
|
|
@@ -199,55 +204,16 @@ async function queryAllDocs({
|
|
|
199
204
|
}) {
|
|
200
205
|
return withUnstableCache([collectionSlug, slugField, locale], [createCollectionCacheKey({ collectionSlug, slug: "__all__", locale })], async () => {
|
|
201
206
|
const payload = await getPayload({ config });
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
limit: 1000,
|
|
213
|
-
pagination: false,
|
|
214
|
-
overrideAccess: true
|
|
215
|
-
});
|
|
216
|
-
return (result2.docs ?? []).map((d) => ({ [slugField]: d[slugField] }));
|
|
217
|
-
}
|
|
218
|
-
const hasVersions = Boolean(collectionConfig.versions);
|
|
219
|
-
const isSlugLocalized = (() => {
|
|
220
|
-
const fields = collectionConfig.fields;
|
|
221
|
-
if (!Array.isArray(fields))
|
|
222
|
-
return false;
|
|
223
|
-
const found = fields.find((f) => f.name === slugField);
|
|
224
|
-
return Boolean(found?.localized);
|
|
225
|
-
})();
|
|
226
|
-
const hasLocales = Boolean(collectionConfig.custom?._isLocalized) || Boolean(payload.config.localization?.locales?.length);
|
|
227
|
-
const localesTableName = `${tableName}_locales`;
|
|
228
|
-
let sqlText;
|
|
229
|
-
const safeLocale = locale.replace(/'/g, "''");
|
|
230
|
-
if (isSlugLocalized && hasLocales) {
|
|
231
|
-
const statusFilter = hasVersions ? ` AND "${tableName}"."_status" = 'published'` : "";
|
|
232
|
-
sqlText = `
|
|
233
|
-
SELECT DISTINCT ON ("${tableName}"."id")
|
|
234
|
-
"${tableName}"."id" AS "id",
|
|
235
|
-
"${localesTableName}"."${snakeSlugField}" AS "${snakeSlugField}",
|
|
236
|
-
"${tableName}"."updated_at" AS "updated_at"
|
|
237
|
-
FROM "${tableName}"
|
|
238
|
-
JOIN "${localesTableName}" ON "${localesTableName}"."_parent_id" = "${tableName}"."id"
|
|
239
|
-
WHERE "${localesTableName}"."_locale" = '${safeLocale}'${statusFilter}
|
|
240
|
-
ORDER BY "${tableName}"."id", "${tableName}"."created_at" DESC
|
|
241
|
-
LIMIT 1000
|
|
242
|
-
`;
|
|
243
|
-
} else {
|
|
244
|
-
const statusFilter = hasVersions ? ` WHERE "_status" = 'published'` : "";
|
|
245
|
-
sqlText = `SELECT id, "${snakeSlugField}", "updated_at" FROM "${tableName}"${statusFilter} ORDER BY "created_at" DESC LIMIT 1000`;
|
|
246
|
-
}
|
|
247
|
-
const { sql: drizzleSql } = await import("drizzle-orm");
|
|
248
|
-
const result = await drizzleDb.execute(drizzleSql.raw(sqlText));
|
|
249
|
-
const rows = result.rows ?? [];
|
|
250
|
-
return rows.map((r) => ({ [slugField]: r[snakeSlugField], id: r.id, updatedAt: r.updated_at }));
|
|
207
|
+
const result = await payload.find({
|
|
208
|
+
collection: collectionSlug,
|
|
209
|
+
draft: false,
|
|
210
|
+
limit: 1000,
|
|
211
|
+
pagination: false,
|
|
212
|
+
overrideAccess: false,
|
|
213
|
+
select: { [slugField]: true },
|
|
214
|
+
locale
|
|
215
|
+
});
|
|
216
|
+
return result.docs ?? [];
|
|
251
217
|
});
|
|
252
218
|
}
|
|
253
219
|
async function queryAllLocaleSlugs({
|
|
@@ -257,46 +223,13 @@ async function queryAllLocaleSlugs({
|
|
|
257
223
|
config
|
|
258
224
|
}) {
|
|
259
225
|
const payload = await getPayload({ config });
|
|
260
|
-
const
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
if (!drizzleDb?.execute) {
|
|
268
|
-
const doc = await payload.findByID({
|
|
269
|
-
collection: collectionSlug,
|
|
270
|
-
id,
|
|
271
|
-
locale: "all",
|
|
272
|
-
select: { [slugField]: true }
|
|
273
|
-
});
|
|
274
|
-
return doc?.[slugField] ?? null;
|
|
275
|
-
}
|
|
276
|
-
const { sql: drizzleSql } = await import("drizzle-orm");
|
|
277
|
-
const slugFieldConfig = collectionConfig.fields?.find((f) => f && f.name === slugField);
|
|
278
|
-
const slugIsLocalized = Boolean(slugFieldConfig?.localized);
|
|
279
|
-
if (!slugIsLocalized) {
|
|
280
|
-
const result2 = await drizzleDb.execute(drizzleSql`SELECT ${drizzleSql.identifier(snakeSlugField)} FROM ${drizzleSql.identifier(tableName)} WHERE "id" = ${id}`);
|
|
281
|
-
const rows2 = result2.rows ?? [];
|
|
282
|
-
const slugValue = rows2[0]?.[snakeSlugField];
|
|
283
|
-
if (typeof slugValue !== "string")
|
|
284
|
-
return null;
|
|
285
|
-
const localization = payload.config.localization;
|
|
286
|
-
const localeCodes = localization ? localization.localeCodes ?? localization.locales.map((l) => l.code) : [];
|
|
287
|
-
if (localeCodes.length === 0)
|
|
288
|
-
return null;
|
|
289
|
-
return Object.fromEntries(localeCodes.map((code) => [code, slugValue]));
|
|
290
|
-
}
|
|
291
|
-
const result = await drizzleDb.execute(drizzleSql`SELECT _locale, ${drizzleSql.identifier(snakeSlugField)} FROM ${drizzleSql.identifier(localesTableName)} WHERE "_parent_id" = ${id}`);
|
|
292
|
-
const rows = result.rows ?? [];
|
|
293
|
-
const out = {};
|
|
294
|
-
for (const r of rows) {
|
|
295
|
-
if (typeof r._locale === "string" && typeof r[snakeSlugField] === "string") {
|
|
296
|
-
out[r._locale] = r[snakeSlugField];
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
return out;
|
|
226
|
+
const doc = await payload.findByID({
|
|
227
|
+
collection: collectionSlug,
|
|
228
|
+
id,
|
|
229
|
+
locale: "all",
|
|
230
|
+
select: { [slugField]: true }
|
|
231
|
+
});
|
|
232
|
+
return doc?.[slugField];
|
|
300
233
|
}
|
|
301
234
|
|
|
302
235
|
// src/exports/metadata.ts
|
package/dist/pages.d.ts
CHANGED
|
@@ -15,23 +15,13 @@ import { ImportMap as ImportMap3, SanitizedConfig as SanitizedConfig2 } from "pa
|
|
|
15
15
|
import { ReactNode as ReactNode2 } from "react";
|
|
16
16
|
type SlugShape = "single" | "catch-all";
|
|
17
17
|
type NextPageProps = {
|
|
18
|
-
params: {
|
|
18
|
+
params: Promise<{
|
|
19
19
|
locale: string;
|
|
20
20
|
slug?: string | string[];
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
type RoutingConfig = {
|
|
24
|
-
locales: readonly string[];
|
|
25
|
-
defaultLocale: string;
|
|
26
|
-
localePrefix?: "always" | "as-needed" | "never" | {
|
|
27
|
-
mode: "always" | "as-needed" | "never";
|
|
28
|
-
prefixes?: Partial<Record<string, string>>;
|
|
29
|
-
};
|
|
30
|
-
localeDetection?: boolean;
|
|
31
|
-
domains?: unknown;
|
|
32
|
-
localeCookie?: unknown;
|
|
33
|
-
alternateLinks?: boolean;
|
|
21
|
+
}>;
|
|
34
22
|
};
|
|
23
|
+
import { RoutingConfig as GenericRoutingConfig } from "next-intl/routing";
|
|
24
|
+
type RoutingConfig = GenericRoutingConfig<string[], any, any, any>;
|
|
35
25
|
type CreateCollectionPageExportsArgs<S extends string = "pages"> = {
|
|
36
26
|
slug?: S;
|
|
37
27
|
config: Promise<SanitizedConfig2>;
|
|
@@ -42,8 +32,6 @@ type CreateCollectionPageExportsArgs<S extends string = "pages"> = {
|
|
|
42
32
|
type CreateCollectionPageExportsDeps<S extends string> = {
|
|
43
33
|
getServerSideURL: () => string;
|
|
44
34
|
pagePathPrefix?: string;
|
|
45
|
-
generateMeta?: (...args: any[]) => any;
|
|
46
|
-
metadataType?: "website" | "article";
|
|
47
35
|
};
|
|
48
36
|
declare function createCollectionPageExports<S extends string = "pages">({ slug: collectionSlug, config: configPromise, importMap, routing, slugShape }: CreateCollectionPageExportsArgs<S>, { getServerSideURL, pagePathPrefix }: CreateCollectionPageExportsDeps<S>): {
|
|
49
37
|
default: (props: NextPageProps) => Promise<ReactNode2>;
|
package/dist/pages.js
CHANGED
|
@@ -146,9 +146,7 @@ var RenderBlocks = async ({ blocks, blockProps, config, importMap, locale, searc
|
|
|
146
146
|
const block = blocks[i];
|
|
147
147
|
const { blockType } = block;
|
|
148
148
|
const blockConfig = (config.blocks ?? []).find((b) => b.slug === blockType);
|
|
149
|
-
const
|
|
150
|
-
const customPath = blockCustom?.path;
|
|
151
|
-
const wantsSearchParams = blockCustom?.searchParams === true;
|
|
149
|
+
const customPath = blockConfig?.custom?.[name]?.path;
|
|
152
150
|
const importMapPath = (typeof customPath === "string" ? customPath : null) ?? `${DEFAULT_BLOCK_PATH_PREFIX}/${blockType}`;
|
|
153
151
|
const Block = await getFromImportMap(importMapPath, importMap);
|
|
154
152
|
if (!Block) {
|
|
@@ -160,7 +158,7 @@ var RenderBlocks = async ({ blocks, blockProps, config, importMap, locale, searc
|
|
|
160
158
|
...blockProps,
|
|
161
159
|
...block,
|
|
162
160
|
locale,
|
|
163
|
-
|
|
161
|
+
searchParams
|
|
164
162
|
}, i));
|
|
165
163
|
}
|
|
166
164
|
return /* @__PURE__ */ jsx3(Fragment, {
|
|
@@ -194,6 +192,11 @@ function slugToParamsSlug(slug, shape) {
|
|
|
194
192
|
return shape === "catch-all" ? [] : "";
|
|
195
193
|
return shape === "catch-all" ? slug.split(SLUG_NESTED_DIVIDER) : slug;
|
|
196
194
|
}
|
|
195
|
+
function slugToPath(slug) {
|
|
196
|
+
if (!slug)
|
|
197
|
+
return "";
|
|
198
|
+
return slug.split(SLUG_NESTED_DIVIDER).join("/");
|
|
199
|
+
}
|
|
197
200
|
|
|
198
201
|
// src/render/metadata/query.ts
|
|
199
202
|
import { getPayload } from "payload";
|
|
@@ -288,55 +291,16 @@ async function queryAllDocs({
|
|
|
288
291
|
}) {
|
|
289
292
|
return withUnstableCache([collectionSlug, slugField, locale], [createCollectionCacheKey({ collectionSlug, slug: "__all__", locale })], async () => {
|
|
290
293
|
const payload = await getPayload({ config });
|
|
291
|
-
const
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
limit: 1000,
|
|
302
|
-
pagination: false,
|
|
303
|
-
overrideAccess: true
|
|
304
|
-
});
|
|
305
|
-
return (result2.docs ?? []).map((d) => ({ [slugField]: d[slugField] }));
|
|
306
|
-
}
|
|
307
|
-
const hasVersions = Boolean(collectionConfig.versions);
|
|
308
|
-
const isSlugLocalized = (() => {
|
|
309
|
-
const fields = collectionConfig.fields;
|
|
310
|
-
if (!Array.isArray(fields))
|
|
311
|
-
return false;
|
|
312
|
-
const found = fields.find((f) => f.name === slugField);
|
|
313
|
-
return Boolean(found?.localized);
|
|
314
|
-
})();
|
|
315
|
-
const hasLocales = Boolean(collectionConfig.custom?._isLocalized) || Boolean(payload.config.localization?.locales?.length);
|
|
316
|
-
const localesTableName = `${tableName}_locales`;
|
|
317
|
-
let sqlText;
|
|
318
|
-
const safeLocale = locale.replace(/'/g, "''");
|
|
319
|
-
if (isSlugLocalized && hasLocales) {
|
|
320
|
-
const statusFilter = hasVersions ? ` AND "${tableName}"."_status" = 'published'` : "";
|
|
321
|
-
sqlText = `
|
|
322
|
-
SELECT DISTINCT ON ("${tableName}"."id")
|
|
323
|
-
"${tableName}"."id" AS "id",
|
|
324
|
-
"${localesTableName}"."${snakeSlugField}" AS "${snakeSlugField}",
|
|
325
|
-
"${tableName}"."updated_at" AS "updated_at"
|
|
326
|
-
FROM "${tableName}"
|
|
327
|
-
JOIN "${localesTableName}" ON "${localesTableName}"."_parent_id" = "${tableName}"."id"
|
|
328
|
-
WHERE "${localesTableName}"."_locale" = '${safeLocale}'${statusFilter}
|
|
329
|
-
ORDER BY "${tableName}"."id", "${tableName}"."created_at" DESC
|
|
330
|
-
LIMIT 1000
|
|
331
|
-
`;
|
|
332
|
-
} else {
|
|
333
|
-
const statusFilter = hasVersions ? ` WHERE "_status" = 'published'` : "";
|
|
334
|
-
sqlText = `SELECT id, "${snakeSlugField}", "updated_at" FROM "${tableName}"${statusFilter} ORDER BY "created_at" DESC LIMIT 1000`;
|
|
335
|
-
}
|
|
336
|
-
const { sql: drizzleSql } = await import("drizzle-orm");
|
|
337
|
-
const result = await drizzleDb.execute(drizzleSql.raw(sqlText));
|
|
338
|
-
const rows = result.rows ?? [];
|
|
339
|
-
return rows.map((r) => ({ [slugField]: r[snakeSlugField], id: r.id, updatedAt: r.updated_at }));
|
|
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 ?? [];
|
|
340
304
|
});
|
|
341
305
|
}
|
|
342
306
|
async function queryAllLocaleSlugs({
|
|
@@ -346,46 +310,13 @@ async function queryAllLocaleSlugs({
|
|
|
346
310
|
config
|
|
347
311
|
}) {
|
|
348
312
|
const payload = await getPayload({ config });
|
|
349
|
-
const
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
if (!drizzleDb?.execute) {
|
|
357
|
-
const doc = await payload.findByID({
|
|
358
|
-
collection: collectionSlug,
|
|
359
|
-
id,
|
|
360
|
-
locale: "all",
|
|
361
|
-
select: { [slugField]: true }
|
|
362
|
-
});
|
|
363
|
-
return doc?.[slugField] ?? null;
|
|
364
|
-
}
|
|
365
|
-
const { sql: drizzleSql } = await import("drizzle-orm");
|
|
366
|
-
const slugFieldConfig = collectionConfig.fields?.find((f) => f && f.name === slugField);
|
|
367
|
-
const slugIsLocalized = Boolean(slugFieldConfig?.localized);
|
|
368
|
-
if (!slugIsLocalized) {
|
|
369
|
-
const result2 = await drizzleDb.execute(drizzleSql`SELECT ${drizzleSql.identifier(snakeSlugField)} FROM ${drizzleSql.identifier(tableName)} WHERE "id" = ${id}`);
|
|
370
|
-
const rows2 = result2.rows ?? [];
|
|
371
|
-
const slugValue = rows2[0]?.[snakeSlugField];
|
|
372
|
-
if (typeof slugValue !== "string")
|
|
373
|
-
return null;
|
|
374
|
-
const localization = payload.config.localization;
|
|
375
|
-
const localeCodes = localization ? localization.localeCodes ?? localization.locales.map((l) => l.code) : [];
|
|
376
|
-
if (localeCodes.length === 0)
|
|
377
|
-
return null;
|
|
378
|
-
return Object.fromEntries(localeCodes.map((code) => [code, slugValue]));
|
|
379
|
-
}
|
|
380
|
-
const result = await drizzleDb.execute(drizzleSql`SELECT _locale, ${drizzleSql.identifier(snakeSlugField)} FROM ${drizzleSql.identifier(localesTableName)} WHERE "_parent_id" = ${id}`);
|
|
381
|
-
const rows = result.rows ?? [];
|
|
382
|
-
const out = {};
|
|
383
|
-
for (const r of rows) {
|
|
384
|
-
if (typeof r._locale === "string" && typeof r[snakeSlugField] === "string") {
|
|
385
|
-
out[r._locale] = r[snakeSlugField];
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
return out;
|
|
313
|
+
const doc = await payload.findByID({
|
|
314
|
+
collection: collectionSlug,
|
|
315
|
+
id,
|
|
316
|
+
locale: "all",
|
|
317
|
+
select: { [slugField]: true }
|
|
318
|
+
});
|
|
319
|
+
return doc?.[slugField];
|
|
389
320
|
}
|
|
390
321
|
|
|
391
322
|
// src/render/pages/createCollectionPageExports.tsx
|
|
@@ -393,25 +324,32 @@ import { setRequestLocale } from "next-intl/server";
|
|
|
393
324
|
|
|
394
325
|
// src/render/pages/utils/buildLocalizedPath.ts
|
|
395
326
|
function buildLocalizedPath(locale, prefix, slug, { routing }) {
|
|
327
|
+
const path = slugToPath(slug);
|
|
396
328
|
return `${routing.localePrefix === "never" ? "" : routing.localePrefix === "always" ? locale : routing.localePrefix === "as-needed" ? locale === routing.defaultLocale ? "" : "/" + locale : (() => {
|
|
397
329
|
throw new Error("Unsupported locale prefix");
|
|
398
|
-
})()}${prefix ? "/" + prefix : ""}${
|
|
330
|
+
})()}${prefix ? "/" + prefix : ""}${path ? "/" + path : ""}`;
|
|
399
331
|
}
|
|
400
332
|
function buildLocalizedPaths(localesSlug, pagePathPrefix, { routing }) {
|
|
333
|
+
if (!localesSlug[routing.defaultLocale])
|
|
334
|
+
return {};
|
|
401
335
|
return routing.locales.reduce((paths, locale) => {
|
|
402
336
|
const slug = localesSlug[locale];
|
|
337
|
+
if (!slug)
|
|
338
|
+
return paths;
|
|
403
339
|
paths[locale] = buildLocalizedPath(locale, pagePathPrefix, slug, { routing });
|
|
404
340
|
return paths;
|
|
405
341
|
}, {});
|
|
406
342
|
}
|
|
407
343
|
function buildAlternates(locale, ...args) {
|
|
408
|
-
const siteUrl = args
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
344
|
+
const [localesSlug, pagePathPrefix, { routing, siteUrl }] = args;
|
|
345
|
+
const localizedPaths = buildLocalizedPaths(...args);
|
|
346
|
+
const defaultPath = localizedPaths[routing.defaultLocale];
|
|
347
|
+
if (defaultPath !== undefined)
|
|
348
|
+
localizedPaths["x-default"] = defaultPath;
|
|
349
|
+
const canonical = localizedPaths[locale] ?? buildLocalizedPath(locale, pagePathPrefix, localesSlug[locale], { routing });
|
|
412
350
|
return {
|
|
413
|
-
languages: localizedPaths,
|
|
414
|
-
canonical:
|
|
351
|
+
languages: Object.fromEntries(Object.entries(localizedPaths).map(([key, value]) => [key, siteUrl + value])),
|
|
352
|
+
canonical: siteUrl + canonical
|
|
415
353
|
};
|
|
416
354
|
}
|
|
417
355
|
|
|
@@ -464,10 +402,6 @@ function createCollectionPageExports({
|
|
|
464
402
|
});
|
|
465
403
|
}
|
|
466
404
|
const default_ = async (props) => {
|
|
467
|
-
if (!props || !props.params) {
|
|
468
|
-
const { notFound } = await import("next/navigation");
|
|
469
|
-
notFound();
|
|
470
|
-
}
|
|
471
405
|
const params = await props.params;
|
|
472
406
|
const locale = params.locale;
|
|
473
407
|
if (!routing.locales.includes(locale)) {
|
package/dist/render-pages.d.ts
CHANGED
|
@@ -18,10 +18,10 @@ import { ReactNode as ReactNode2 } from "react";
|
|
|
18
18
|
type SlugShape = "single" | "catch-all";
|
|
19
19
|
import { ReactNode } from "react";
|
|
20
20
|
type NextPageProps = {
|
|
21
|
-
params: {
|
|
21
|
+
params: Promise<{
|
|
22
22
|
locale: string;
|
|
23
23
|
slug?: string | string[];
|
|
24
|
-
}
|
|
24
|
+
}>;
|
|
25
25
|
};
|
|
26
26
|
type NextLayoutProps = {
|
|
27
27
|
params: Promise<{
|
|
@@ -29,18 +29,8 @@ type NextLayoutProps = {
|
|
|
29
29
|
}>;
|
|
30
30
|
children: ReactNode;
|
|
31
31
|
};
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
defaultLocale: string;
|
|
35
|
-
localePrefix?: "always" | "as-needed" | "never" | {
|
|
36
|
-
mode: "always" | "as-needed" | "never";
|
|
37
|
-
prefixes?: Partial<Record<string, string>>;
|
|
38
|
-
};
|
|
39
|
-
localeDetection?: boolean;
|
|
40
|
-
domains?: unknown;
|
|
41
|
-
localeCookie?: unknown;
|
|
42
|
-
alternateLinks?: boolean;
|
|
43
|
-
};
|
|
32
|
+
import { RoutingConfig as GenericRoutingConfig } from "next-intl/routing";
|
|
33
|
+
type RoutingConfig = GenericRoutingConfig<string[], any, any, any>;
|
|
44
34
|
type CreateCollectionPageExportsArgs<S extends string = "pages"> = {
|
|
45
35
|
slug?: S;
|
|
46
36
|
config: Promise<SanitizedConfig2>;
|
|
@@ -51,8 +41,6 @@ type CreateCollectionPageExportsArgs<S extends string = "pages"> = {
|
|
|
51
41
|
type CreateCollectionPageExportsDeps<S extends string> = {
|
|
52
42
|
getServerSideURL: () => string;
|
|
53
43
|
pagePathPrefix?: string;
|
|
54
|
-
generateMeta?: (...args: any[]) => any;
|
|
55
|
-
metadataType?: "website" | "article";
|
|
56
44
|
};
|
|
57
45
|
declare function createCollectionPageExports<S extends string = "pages">({ slug: collectionSlug, config: configPromise, importMap, routing, slugShape }: CreateCollectionPageExportsArgs<S>, { getServerSideURL, pagePathPrefix }: CreateCollectionPageExportsDeps<S>): {
|
|
58
46
|
default: (props: NextPageProps) => Promise<ReactNode2>;
|
package/dist/render-pages.js
CHANGED
|
@@ -146,9 +146,7 @@ var RenderBlocks = async ({ blocks, blockProps, config, importMap, locale, searc
|
|
|
146
146
|
const block = blocks[i];
|
|
147
147
|
const { blockType } = block;
|
|
148
148
|
const blockConfig = (config.blocks ?? []).find((b) => b.slug === blockType);
|
|
149
|
-
const
|
|
150
|
-
const customPath = blockCustom?.path;
|
|
151
|
-
const wantsSearchParams = blockCustom?.searchParams === true;
|
|
149
|
+
const customPath = blockConfig?.custom?.[name]?.path;
|
|
152
150
|
const importMapPath = (typeof customPath === "string" ? customPath : null) ?? `${DEFAULT_BLOCK_PATH_PREFIX}/${blockType}`;
|
|
153
151
|
const Block = await getFromImportMap(importMapPath, importMap);
|
|
154
152
|
if (!Block) {
|
|
@@ -160,7 +158,7 @@ var RenderBlocks = async ({ blocks, blockProps, config, importMap, locale, searc
|
|
|
160
158
|
...blockProps,
|
|
161
159
|
...block,
|
|
162
160
|
locale,
|
|
163
|
-
|
|
161
|
+
searchParams
|
|
164
162
|
}, i));
|
|
165
163
|
}
|
|
166
164
|
return /* @__PURE__ */ jsx3(Fragment, {
|
|
@@ -224,6 +222,11 @@ function slugToParamsSlug(slug, shape) {
|
|
|
224
222
|
return shape === "catch-all" ? [] : "";
|
|
225
223
|
return shape === "catch-all" ? slug.split(SLUG_NESTED_DIVIDER) : slug;
|
|
226
224
|
}
|
|
225
|
+
function slugToPath(slug) {
|
|
226
|
+
if (!slug)
|
|
227
|
+
return "";
|
|
228
|
+
return slug.split(SLUG_NESTED_DIVIDER).join("/");
|
|
229
|
+
}
|
|
227
230
|
|
|
228
231
|
// src/render/metadata/query.ts
|
|
229
232
|
import { getPayload } from "payload";
|
|
@@ -318,55 +321,16 @@ async function queryAllDocs({
|
|
|
318
321
|
}) {
|
|
319
322
|
return withUnstableCache([collectionSlug, slugField, locale], [createCollectionCacheKey({ collectionSlug, slug: "__all__", locale })], async () => {
|
|
320
323
|
const payload = await getPayload({ config });
|
|
321
|
-
const
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
limit: 1000,
|
|
332
|
-
pagination: false,
|
|
333
|
-
overrideAccess: true
|
|
334
|
-
});
|
|
335
|
-
return (result2.docs ?? []).map((d) => ({ [slugField]: d[slugField] }));
|
|
336
|
-
}
|
|
337
|
-
const hasVersions = Boolean(collectionConfig.versions);
|
|
338
|
-
const isSlugLocalized = (() => {
|
|
339
|
-
const fields = collectionConfig.fields;
|
|
340
|
-
if (!Array.isArray(fields))
|
|
341
|
-
return false;
|
|
342
|
-
const found = fields.find((f) => f.name === slugField);
|
|
343
|
-
return Boolean(found?.localized);
|
|
344
|
-
})();
|
|
345
|
-
const hasLocales = Boolean(collectionConfig.custom?._isLocalized) || Boolean(payload.config.localization?.locales?.length);
|
|
346
|
-
const localesTableName = `${tableName}_locales`;
|
|
347
|
-
let sqlText;
|
|
348
|
-
const safeLocale = locale.replace(/'/g, "''");
|
|
349
|
-
if (isSlugLocalized && hasLocales) {
|
|
350
|
-
const statusFilter = hasVersions ? ` AND "${tableName}"."_status" = 'published'` : "";
|
|
351
|
-
sqlText = `
|
|
352
|
-
SELECT DISTINCT ON ("${tableName}"."id")
|
|
353
|
-
"${tableName}"."id" AS "id",
|
|
354
|
-
"${localesTableName}"."${snakeSlugField}" AS "${snakeSlugField}",
|
|
355
|
-
"${tableName}"."updated_at" AS "updated_at"
|
|
356
|
-
FROM "${tableName}"
|
|
357
|
-
JOIN "${localesTableName}" ON "${localesTableName}"."_parent_id" = "${tableName}"."id"
|
|
358
|
-
WHERE "${localesTableName}"."_locale" = '${safeLocale}'${statusFilter}
|
|
359
|
-
ORDER BY "${tableName}"."id", "${tableName}"."created_at" DESC
|
|
360
|
-
LIMIT 1000
|
|
361
|
-
`;
|
|
362
|
-
} else {
|
|
363
|
-
const statusFilter = hasVersions ? ` WHERE "_status" = 'published'` : "";
|
|
364
|
-
sqlText = `SELECT id, "${snakeSlugField}", "updated_at" FROM "${tableName}"${statusFilter} ORDER BY "created_at" DESC LIMIT 1000`;
|
|
365
|
-
}
|
|
366
|
-
const { sql: drizzleSql } = await import("drizzle-orm");
|
|
367
|
-
const result = await drizzleDb.execute(drizzleSql.raw(sqlText));
|
|
368
|
-
const rows = result.rows ?? [];
|
|
369
|
-
return rows.map((r) => ({ [slugField]: r[snakeSlugField], id: r.id, updatedAt: r.updated_at }));
|
|
324
|
+
const result = await payload.find({
|
|
325
|
+
collection: collectionSlug,
|
|
326
|
+
draft: false,
|
|
327
|
+
limit: 1000,
|
|
328
|
+
pagination: false,
|
|
329
|
+
overrideAccess: false,
|
|
330
|
+
select: { [slugField]: true },
|
|
331
|
+
locale
|
|
332
|
+
});
|
|
333
|
+
return result.docs ?? [];
|
|
370
334
|
});
|
|
371
335
|
}
|
|
372
336
|
async function queryAllLocaleSlugs({
|
|
@@ -376,46 +340,13 @@ async function queryAllLocaleSlugs({
|
|
|
376
340
|
config
|
|
377
341
|
}) {
|
|
378
342
|
const payload = await getPayload({ config });
|
|
379
|
-
const
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
if (!drizzleDb?.execute) {
|
|
387
|
-
const doc = await payload.findByID({
|
|
388
|
-
collection: collectionSlug,
|
|
389
|
-
id,
|
|
390
|
-
locale: "all",
|
|
391
|
-
select: { [slugField]: true }
|
|
392
|
-
});
|
|
393
|
-
return doc?.[slugField] ?? null;
|
|
394
|
-
}
|
|
395
|
-
const { sql: drizzleSql } = await import("drizzle-orm");
|
|
396
|
-
const slugFieldConfig = collectionConfig.fields?.find((f) => f && f.name === slugField);
|
|
397
|
-
const slugIsLocalized = Boolean(slugFieldConfig?.localized);
|
|
398
|
-
if (!slugIsLocalized) {
|
|
399
|
-
const result2 = await drizzleDb.execute(drizzleSql`SELECT ${drizzleSql.identifier(snakeSlugField)} FROM ${drizzleSql.identifier(tableName)} WHERE "id" = ${id}`);
|
|
400
|
-
const rows2 = result2.rows ?? [];
|
|
401
|
-
const slugValue = rows2[0]?.[snakeSlugField];
|
|
402
|
-
if (typeof slugValue !== "string")
|
|
403
|
-
return null;
|
|
404
|
-
const localization = payload.config.localization;
|
|
405
|
-
const localeCodes = localization ? localization.localeCodes ?? localization.locales.map((l) => l.code) : [];
|
|
406
|
-
if (localeCodes.length === 0)
|
|
407
|
-
return null;
|
|
408
|
-
return Object.fromEntries(localeCodes.map((code) => [code, slugValue]));
|
|
409
|
-
}
|
|
410
|
-
const result = await drizzleDb.execute(drizzleSql`SELECT _locale, ${drizzleSql.identifier(snakeSlugField)} FROM ${drizzleSql.identifier(localesTableName)} WHERE "_parent_id" = ${id}`);
|
|
411
|
-
const rows = result.rows ?? [];
|
|
412
|
-
const out = {};
|
|
413
|
-
for (const r of rows) {
|
|
414
|
-
if (typeof r._locale === "string" && typeof r[snakeSlugField] === "string") {
|
|
415
|
-
out[r._locale] = r[snakeSlugField];
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
return out;
|
|
343
|
+
const doc = await payload.findByID({
|
|
344
|
+
collection: collectionSlug,
|
|
345
|
+
id,
|
|
346
|
+
locale: "all",
|
|
347
|
+
select: { [slugField]: true }
|
|
348
|
+
});
|
|
349
|
+
return doc?.[slugField];
|
|
419
350
|
}
|
|
420
351
|
|
|
421
352
|
// src/render/pages/createCollectionPageExports.tsx
|
|
@@ -423,25 +354,32 @@ import { setRequestLocale } from "next-intl/server";
|
|
|
423
354
|
|
|
424
355
|
// src/render/pages/utils/buildLocalizedPath.ts
|
|
425
356
|
function buildLocalizedPath(locale, prefix, slug, { routing }) {
|
|
357
|
+
const path = slugToPath(slug);
|
|
426
358
|
return `${routing.localePrefix === "never" ? "" : routing.localePrefix === "always" ? locale : routing.localePrefix === "as-needed" ? locale === routing.defaultLocale ? "" : "/" + locale : (() => {
|
|
427
359
|
throw new Error("Unsupported locale prefix");
|
|
428
|
-
})()}${prefix ? "/" + prefix : ""}${
|
|
360
|
+
})()}${prefix ? "/" + prefix : ""}${path ? "/" + path : ""}`;
|
|
429
361
|
}
|
|
430
362
|
function buildLocalizedPaths(localesSlug, pagePathPrefix, { routing }) {
|
|
363
|
+
if (!localesSlug[routing.defaultLocale])
|
|
364
|
+
return {};
|
|
431
365
|
return routing.locales.reduce((paths, locale) => {
|
|
432
366
|
const slug = localesSlug[locale];
|
|
367
|
+
if (!slug)
|
|
368
|
+
return paths;
|
|
433
369
|
paths[locale] = buildLocalizedPath(locale, pagePathPrefix, slug, { routing });
|
|
434
370
|
return paths;
|
|
435
371
|
}, {});
|
|
436
372
|
}
|
|
437
373
|
function buildAlternates(locale, ...args) {
|
|
438
|
-
const siteUrl = args
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
374
|
+
const [localesSlug, pagePathPrefix, { routing, siteUrl }] = args;
|
|
375
|
+
const localizedPaths = buildLocalizedPaths(...args);
|
|
376
|
+
const defaultPath = localizedPaths[routing.defaultLocale];
|
|
377
|
+
if (defaultPath !== undefined)
|
|
378
|
+
localizedPaths["x-default"] = defaultPath;
|
|
379
|
+
const canonical = localizedPaths[locale] ?? buildLocalizedPath(locale, pagePathPrefix, localesSlug[locale], { routing });
|
|
442
380
|
return {
|
|
443
|
-
languages: localizedPaths,
|
|
444
|
-
canonical:
|
|
381
|
+
languages: Object.fromEntries(Object.entries(localizedPaths).map(([key, value]) => [key, siteUrl + value])),
|
|
382
|
+
canonical: siteUrl + canonical
|
|
445
383
|
};
|
|
446
384
|
}
|
|
447
385
|
|
|
@@ -494,10 +432,6 @@ function createCollectionPageExports({
|
|
|
494
432
|
});
|
|
495
433
|
}
|
|
496
434
|
const default_ = async (props) => {
|
|
497
|
-
if (!props || !props.params) {
|
|
498
|
-
const { notFound } = await import("next/navigation");
|
|
499
|
-
notFound();
|
|
500
|
-
}
|
|
501
435
|
const params = await props.params;
|
|
502
436
|
const locale = params.locale;
|
|
503
437
|
if (!routing.locales.includes(locale)) {
|
package/dist/sitemap.d.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
type CreateCollectionPageExportsDeps<S extends string> = {
|
|
2
2
|
getServerSideURL: () => string;
|
|
3
3
|
pagePathPrefix?: string;
|
|
4
|
-
generateMeta?: (...args: any[]) => any;
|
|
5
|
-
metadataType?: "website" | "article";
|
|
6
4
|
};
|
|
7
5
|
type GenerateSitemapPageExportsArgs = CreateCollectionPageExportsDeps<any>;
|
|
8
6
|
declare function createSitemapFromCollections(...args: GenerateSitemapPageExportsArgs[]): () => Response;
|
package/dist/sitemap.js
CHANGED
|
@@ -15,6 +15,11 @@ function slugToParamsSlug(slug, shape) {
|
|
|
15
15
|
return shape === "catch-all" ? [] : "";
|
|
16
16
|
return shape === "catch-all" ? slug.split(SLUG_NESTED_DIVIDER) : slug;
|
|
17
17
|
}
|
|
18
|
+
function slugToPath(slug) {
|
|
19
|
+
if (!slug)
|
|
20
|
+
return "";
|
|
21
|
+
return slug.split(SLUG_NESTED_DIVIDER).join("/");
|
|
22
|
+
}
|
|
18
23
|
|
|
19
24
|
// src/render/metadata/query.ts
|
|
20
25
|
import { getPayload } from "payload";
|
|
@@ -109,55 +114,16 @@ async function queryAllDocs({
|
|
|
109
114
|
}) {
|
|
110
115
|
return withUnstableCache([collectionSlug, slugField, locale], [createCollectionCacheKey({ collectionSlug, slug: "__all__", locale })], async () => {
|
|
111
116
|
const payload = await getPayload({ config });
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
limit: 1000,
|
|
123
|
-
pagination: false,
|
|
124
|
-
overrideAccess: true
|
|
125
|
-
});
|
|
126
|
-
return (result2.docs ?? []).map((d) => ({ [slugField]: d[slugField] }));
|
|
127
|
-
}
|
|
128
|
-
const hasVersions = Boolean(collectionConfig.versions);
|
|
129
|
-
const isSlugLocalized = (() => {
|
|
130
|
-
const fields = collectionConfig.fields;
|
|
131
|
-
if (!Array.isArray(fields))
|
|
132
|
-
return false;
|
|
133
|
-
const found = fields.find((f) => f.name === slugField);
|
|
134
|
-
return Boolean(found?.localized);
|
|
135
|
-
})();
|
|
136
|
-
const hasLocales = Boolean(collectionConfig.custom?._isLocalized) || Boolean(payload.config.localization?.locales?.length);
|
|
137
|
-
const localesTableName = `${tableName}_locales`;
|
|
138
|
-
let sqlText;
|
|
139
|
-
const safeLocale = locale.replace(/'/g, "''");
|
|
140
|
-
if (isSlugLocalized && hasLocales) {
|
|
141
|
-
const statusFilter = hasVersions ? ` AND "${tableName}"."_status" = 'published'` : "";
|
|
142
|
-
sqlText = `
|
|
143
|
-
SELECT DISTINCT ON ("${tableName}"."id")
|
|
144
|
-
"${tableName}"."id" AS "id",
|
|
145
|
-
"${localesTableName}"."${snakeSlugField}" AS "${snakeSlugField}",
|
|
146
|
-
"${tableName}"."updated_at" AS "updated_at"
|
|
147
|
-
FROM "${tableName}"
|
|
148
|
-
JOIN "${localesTableName}" ON "${localesTableName}"."_parent_id" = "${tableName}"."id"
|
|
149
|
-
WHERE "${localesTableName}"."_locale" = '${safeLocale}'${statusFilter}
|
|
150
|
-
ORDER BY "${tableName}"."id", "${tableName}"."created_at" DESC
|
|
151
|
-
LIMIT 1000
|
|
152
|
-
`;
|
|
153
|
-
} else {
|
|
154
|
-
const statusFilter = hasVersions ? ` WHERE "_status" = 'published'` : "";
|
|
155
|
-
sqlText = `SELECT id, "${snakeSlugField}", "updated_at" FROM "${tableName}"${statusFilter} ORDER BY "created_at" DESC LIMIT 1000`;
|
|
156
|
-
}
|
|
157
|
-
const { sql: drizzleSql } = await import("drizzle-orm");
|
|
158
|
-
const result = await drizzleDb.execute(drizzleSql.raw(sqlText));
|
|
159
|
-
const rows = result.rows ?? [];
|
|
160
|
-
return rows.map((r) => ({ [slugField]: r[snakeSlugField], id: r.id, updatedAt: r.updated_at }));
|
|
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 ?? [];
|
|
161
127
|
});
|
|
162
128
|
}
|
|
163
129
|
async function queryAllLocaleSlugs({
|
|
@@ -167,46 +133,13 @@ async function queryAllLocaleSlugs({
|
|
|
167
133
|
config
|
|
168
134
|
}) {
|
|
169
135
|
const payload = await getPayload({ config });
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
if (!drizzleDb?.execute) {
|
|
178
|
-
const doc = await payload.findByID({
|
|
179
|
-
collection: collectionSlug,
|
|
180
|
-
id,
|
|
181
|
-
locale: "all",
|
|
182
|
-
select: { [slugField]: true }
|
|
183
|
-
});
|
|
184
|
-
return doc?.[slugField] ?? null;
|
|
185
|
-
}
|
|
186
|
-
const { sql: drizzleSql } = await import("drizzle-orm");
|
|
187
|
-
const slugFieldConfig = collectionConfig.fields?.find((f) => f && f.name === slugField);
|
|
188
|
-
const slugIsLocalized = Boolean(slugFieldConfig?.localized);
|
|
189
|
-
if (!slugIsLocalized) {
|
|
190
|
-
const result2 = await drizzleDb.execute(drizzleSql`SELECT ${drizzleSql.identifier(snakeSlugField)} FROM ${drizzleSql.identifier(tableName)} WHERE "id" = ${id}`);
|
|
191
|
-
const rows2 = result2.rows ?? [];
|
|
192
|
-
const slugValue = rows2[0]?.[snakeSlugField];
|
|
193
|
-
if (typeof slugValue !== "string")
|
|
194
|
-
return null;
|
|
195
|
-
const localization = payload.config.localization;
|
|
196
|
-
const localeCodes = localization ? localization.localeCodes ?? localization.locales.map((l) => l.code) : [];
|
|
197
|
-
if (localeCodes.length === 0)
|
|
198
|
-
return null;
|
|
199
|
-
return Object.fromEntries(localeCodes.map((code) => [code, slugValue]));
|
|
200
|
-
}
|
|
201
|
-
const result = await drizzleDb.execute(drizzleSql`SELECT _locale, ${drizzleSql.identifier(snakeSlugField)} FROM ${drizzleSql.identifier(localesTableName)} WHERE "_parent_id" = ${id}`);
|
|
202
|
-
const rows = result.rows ?? [];
|
|
203
|
-
const out = {};
|
|
204
|
-
for (const r of rows) {
|
|
205
|
-
if (typeof r._locale === "string" && typeof r[snakeSlugField] === "string") {
|
|
206
|
-
out[r._locale] = r[snakeSlugField];
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
return out;
|
|
136
|
+
const doc = await payload.findByID({
|
|
137
|
+
collection: collectionSlug,
|
|
138
|
+
id,
|
|
139
|
+
locale: "all",
|
|
140
|
+
select: { [slugField]: true }
|
|
141
|
+
});
|
|
142
|
+
return doc?.[slugField];
|
|
210
143
|
}
|
|
211
144
|
|
|
212
145
|
// src/render/pages/createCollectionPageExports.tsx
|
|
@@ -214,25 +147,32 @@ import { setRequestLocale } from "next-intl/server";
|
|
|
214
147
|
|
|
215
148
|
// src/render/pages/utils/buildLocalizedPath.ts
|
|
216
149
|
function buildLocalizedPath(locale, prefix, slug, { routing }) {
|
|
150
|
+
const path = slugToPath(slug);
|
|
217
151
|
return `${routing.localePrefix === "never" ? "" : routing.localePrefix === "always" ? locale : routing.localePrefix === "as-needed" ? locale === routing.defaultLocale ? "" : "/" + locale : (() => {
|
|
218
152
|
throw new Error("Unsupported locale prefix");
|
|
219
|
-
})()}${prefix ? "/" + prefix : ""}${
|
|
153
|
+
})()}${prefix ? "/" + prefix : ""}${path ? "/" + path : ""}`;
|
|
220
154
|
}
|
|
221
155
|
function buildLocalizedPaths(localesSlug, pagePathPrefix, { routing }) {
|
|
156
|
+
if (!localesSlug[routing.defaultLocale])
|
|
157
|
+
return {};
|
|
222
158
|
return routing.locales.reduce((paths, locale) => {
|
|
223
159
|
const slug = localesSlug[locale];
|
|
160
|
+
if (!slug)
|
|
161
|
+
return paths;
|
|
224
162
|
paths[locale] = buildLocalizedPath(locale, pagePathPrefix, slug, { routing });
|
|
225
163
|
return paths;
|
|
226
164
|
}, {});
|
|
227
165
|
}
|
|
228
166
|
function buildAlternates(locale, ...args) {
|
|
229
|
-
const siteUrl = args
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
167
|
+
const [localesSlug, pagePathPrefix, { routing, siteUrl }] = args;
|
|
168
|
+
const localizedPaths = buildLocalizedPaths(...args);
|
|
169
|
+
const defaultPath = localizedPaths[routing.defaultLocale];
|
|
170
|
+
if (defaultPath !== undefined)
|
|
171
|
+
localizedPaths["x-default"] = defaultPath;
|
|
172
|
+
const canonical = localizedPaths[locale] ?? buildLocalizedPath(locale, pagePathPrefix, localesSlug[locale], { routing });
|
|
233
173
|
return {
|
|
234
|
-
languages: localizedPaths,
|
|
235
|
-
canonical:
|
|
174
|
+
languages: Object.fromEntries(Object.entries(localizedPaths).map(([key, value]) => [key, siteUrl + value])),
|
|
175
|
+
canonical: siteUrl + canonical
|
|
236
176
|
};
|
|
237
177
|
}
|
|
238
178
|
|
|
@@ -306,10 +246,6 @@ function createCollectionPageExports({
|
|
|
306
246
|
});
|
|
307
247
|
}
|
|
308
248
|
const default_ = async (props) => {
|
|
309
|
-
if (!props || !props.params) {
|
|
310
|
-
const { notFound } = await import("next/navigation");
|
|
311
|
-
notFound();
|
|
312
|
-
}
|
|
313
249
|
const params = await props.params;
|
|
314
250
|
const locale = params.locale;
|
|
315
251
|
if (!routing.locales.includes(locale)) {
|
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
|
+
"version": "1.4.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
7
7
|
"files": [
|
|
@@ -42,6 +42,12 @@
|
|
|
42
42
|
"default": "./dist/imagehash.js"
|
|
43
43
|
}
|
|
44
44
|
},
|
|
45
|
+
"./mcp": {
|
|
46
|
+
"import": {
|
|
47
|
+
"types": "./dist/mcp.d.ts",
|
|
48
|
+
"default": "./dist/mcp.js"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
45
51
|
"./blocks": {
|
|
46
52
|
"import": {
|
|
47
53
|
"types": "./dist/blocks.d.ts",
|
|
@@ -109,7 +115,6 @@
|
|
|
109
115
|
"dependencies": {
|
|
110
116
|
"@payloadcms/live-preview-react": "3.85.0",
|
|
111
117
|
"@payloadcms/plugin-mcp": "3.85.0",
|
|
112
|
-
"drizzle-orm": "0.45.2",
|
|
113
118
|
"@payloadcms/richtext-lexical": "3.85.0",
|
|
114
119
|
"@payloadcms/next": "3.85.0",
|
|
115
120
|
"next": "16.2.6",
|