@justanarthur/payload-www 1.0.1 → 1.2.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/blocks.d.ts CHANGED
@@ -1,11 +1,16 @@
1
1
  import { FC } from "react";
2
- import { ImportMap, SanitizedConfig } from "payload";
2
+ import { ImportMap as ImportMap2, SanitizedConfig } from "payload";
3
+ import { ComponentType } from "react";
4
+ type AsyncImportMapEntry<T = ComponentType> = T | (() => Promise<{
5
+ default: T;
6
+ } | T>);
7
+ type AsyncImportMap = Record<string, AsyncImportMapEntry>;
3
8
  type RenderBlocksProps = {
4
9
  blocks: Array<{
5
10
  blockType: string;
6
11
  } & Record<string, unknown>>;
7
12
  blockProps?: Record<string, unknown>;
8
- importMap: ImportMap;
13
+ importMap: ImportMap2 | AsyncImportMap;
9
14
  config: SanitizedConfig;
10
15
  locale: string;
11
16
  searchParams?: Record<string, string | string[] | undefined>;
package/dist/blocks.js CHANGED
@@ -2,47 +2,43 @@
2
2
 
3
3
  // src/render/getFromImportMap.ts
4
4
  function getFromImportMap(key, importMap) {
5
- return key && importMap[key.includes("#") ? key : key + "#default"];
6
- }
7
-
8
- // src/render/generateImportName.ts
9
- function generateImportName(type, slug) {
10
- switch (type) {
11
- case "block":
12
- return `Block${slug.replace(/(^\w|-\w)/g, (m) => m.replace("-", "").toUpperCase())}#default`;
13
- case "page":
14
- return `Page${slug.replace(/(^\w|-\w)/g, (m) => m.replace("-", "").toUpperCase())}#default`;
15
- default:
16
- throw new Error(`Unknown type: ${type}`);
5
+ if (!key)
6
+ return;
7
+ const entry = importMap[key.includes("#") ? key : `${key}#default`];
8
+ if (entry == null)
9
+ return;
10
+ if (typeof entry === "function") {
11
+ return entry().then((mod) => {
12
+ if (typeof mod === "function")
13
+ return mod;
14
+ const modObj = mod;
15
+ return modObj.default ?? mod;
16
+ });
17
17
  }
18
+ return entry;
18
19
  }
19
20
 
21
+ // package.json
22
+ var name = "@justanarthur/payload-www";
23
+
20
24
  // src/render/blocks/renderBlocks.tsx
21
25
  import { jsx, Fragment } from "react/jsx-runtime";
22
- var RenderBlocks = ({
23
- blocks,
24
- blockProps,
25
- config,
26
- importMap,
27
- locale,
28
- searchParams
29
- }) => {
30
- if (!blocks || !Array.isArray(blocks) || blocks.length === 0) {
31
- console.log("[WWW] render/blocks:RenderBlocks no blocks (locale=", locale, ")");
26
+ var DEFAULT_BLOCK_PATH_PREFIX = "@/components/blocks";
27
+ var RenderBlocks = async ({ blocks, blockProps, config, importMap, locale, searchParams }) => {
28
+ if (!blocks || !Array.isArray(blocks) || blocks.length === 0)
32
29
  return null;
33
- }
34
- console.log("[WWW] render/blocks:RenderBlocks rendering count=", blocks.length, "locale=", locale);
35
30
  const rendered = [];
36
31
  for (let i = 0;i < blocks.length; i++) {
37
32
  const block = blocks[i];
38
33
  const { blockType } = block;
39
- const importMapPath = config.admin?.dependencies?.[blockType]?.path || generateImportName("block", blockType);
40
- const Block = getFromImportMap(importMapPath, importMap);
34
+ const blockConfig = (config.blocks ?? []).find((b) => b.slug === blockType);
35
+ const customPath = blockConfig?.custom?.[name]?.path;
36
+ const importMapPath = (typeof customPath === "string" ? customPath : null) ?? `${DEFAULT_BLOCK_PATH_PREFIX}/${blockType}`;
37
+ const Block = await getFromImportMap(importMapPath, importMap);
41
38
  if (!Block) {
42
39
  console.warn(`[WWW] render/blocks:RenderBlocks no block for type=${blockType} importMapPath=${importMapPath} (locale=${locale})`);
43
40
  continue;
44
41
  }
45
- console.log("[WWW] render/blocks:RenderBlocks [", i, "] blockType=", blockType, "importMapPath=", importMapPath);
46
42
  rendered.push(/* @__PURE__ */ jsx(Block, {
47
43
  index: i,
48
44
  ...blockProps,
package/dist/cli.js ADDED
@@ -0,0 +1,201 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire } from "node:module";
3
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
4
+
5
+ // src/cli/index.ts
6
+ import { register } from "tsx/esm/api";
7
+ import path from "node:path";
8
+ import { existsSync } from "node:fs";
9
+ import { pathToFileURL } from "node:url";
10
+
11
+ // package.json
12
+ var name = "@justanarthur/payload-www";
13
+
14
+ // src/cli/generateAsyncImportmap.ts
15
+ function getCustomPath(custom, pkg) {
16
+ const v = custom?.[pkg]?.path;
17
+ return typeof v === "string" ? v : undefined;
18
+ }
19
+ function splitKey(key) {
20
+ const hashIdx = key.indexOf("#");
21
+ if (hashIdx >= 0) {
22
+ return {
23
+ filePath: key.slice(0, hashIdx),
24
+ exportName: key.slice(hashIdx + 1) || "default",
25
+ fullKey: key
26
+ };
27
+ }
28
+ return {
29
+ filePath: key,
30
+ exportName: "default",
31
+ fullKey: `${key}#default`
32
+ };
33
+ }
34
+ function defaultBlockPath(slug) {
35
+ return `@/components/blocks/${slug}#default`;
36
+ }
37
+ async function generateAsyncImportmap(config, options) {
38
+ const pkg = options.packageName ?? name;
39
+ const blocks = config.blocks ?? [] ?? [];
40
+ const collections = config.collections ?? [] ?? [];
41
+ const globals = config.globals ?? [] ?? [];
42
+ const keys = new Set;
43
+ for (const block of blocks) {
44
+ if (!block.slug)
45
+ continue;
46
+ const explicit = getCustomPath(block.custom, pkg);
47
+ const key = explicit ?? defaultBlockPath(block.slug);
48
+ keys.add(key);
49
+ }
50
+ for (const item of [...collections, ...globals]) {
51
+ const explicit = getCustomPath(item.custom, pkg);
52
+ if (explicit)
53
+ keys.add(explicit);
54
+ }
55
+ const sortedKeys = [...keys].sort();
56
+ const lines = [];
57
+ lines.push("// This file is generated by `payload-www generate:async-importmap`.");
58
+ lines.push("// Do not edit by hand — re-run the generator after Payload config changes.");
59
+ lines.push("");
60
+ lines.push("/** @type import('payload').ImportMap */");
61
+ lines.push("export const asyncImportMap = {");
62
+ for (const key of sortedKeys) {
63
+ const { filePath, exportName, fullKey } = splitKey(key);
64
+ const jsonKey = JSON.stringify(fullKey);
65
+ lines.push(` ${jsonKey}: () => import(${JSON.stringify(filePath)}).then((m) => ({ default: m.${exportName} })),`);
66
+ }
67
+ lines.push("}");
68
+ lines.push("");
69
+ const output = lines.join(`
70
+ `);
71
+ const { writeFile, mkdir } = await import("node:fs/promises");
72
+ const { dirname } = await import("node:path");
73
+ await mkdir(dirname(options.output), { recursive: true });
74
+ await writeFile(options.output, output, "utf-8");
75
+ return {
76
+ entries: sortedKeys.length,
77
+ output: options.output
78
+ };
79
+ }
80
+
81
+ // src/cli/index.ts
82
+ register();
83
+ function printHelp() {
84
+ console.log(`payload-www generate:async-importmap
85
+
86
+ Generate an async-importMap.ts containing only the render-path dependencies
87
+ (blocks + collection/global renderers) used by the public render path.
88
+
89
+ Usage:
90
+ payload-www generate:async-importmap --config-path <path> --output <path>
91
+
92
+ Options:
93
+ --config-path <path> Path to the Payload config file (TS or JS).
94
+ Resolved relative to the current working directory.
95
+ --output <path> Output file path. Created if missing.
96
+ --package-name <name> Custom-package key for the render-dependency lookup.
97
+ Defaults to "@justanarthur/payload-www".
98
+ --help, -h Show this help.
99
+
100
+ Example:
101
+ payload-www generate:async-importmap \\
102
+ --config-path apps/www/payload.config.ts \\
103
+ --output apps/www/app/\\(payload\\)/admin/asyncImportMap.ts
104
+ `);
105
+ }
106
+ function parseArgs(argv) {
107
+ const args = {
108
+ configPath: "",
109
+ output: "",
110
+ help: false
111
+ };
112
+ for (let i = 0;i < argv.length; i++) {
113
+ const a = argv[i];
114
+ if (a === "--help" || a === "-h") {
115
+ args.help = true;
116
+ continue;
117
+ }
118
+ if (a === "--config-path") {
119
+ args.configPath = argv[++i] ?? "";
120
+ continue;
121
+ }
122
+ if (a === "--output") {
123
+ args.output = argv[++i] ?? "";
124
+ continue;
125
+ }
126
+ if (a === "--package-name") {
127
+ args.packageName = argv[++i] ?? "";
128
+ continue;
129
+ }
130
+ if (a?.startsWith("--config-path=")) {
131
+ args.configPath = a.slice("--config-path=".length);
132
+ continue;
133
+ }
134
+ if (a?.startsWith("--output=")) {
135
+ args.output = a.slice("--output=".length);
136
+ continue;
137
+ }
138
+ if (a?.startsWith("--package-name=")) {
139
+ args.packageName = a.slice("--package-name=".length);
140
+ continue;
141
+ }
142
+ }
143
+ return args;
144
+ }
145
+ async function main() {
146
+ const args = parseArgs(process.argv.slice(2));
147
+ if (args.help) {
148
+ printHelp();
149
+ process.exit(0);
150
+ }
151
+ if (!args.configPath || !args.output) {
152
+ console.error(`[payload-www] --config-path and --output are required.
153
+ `);
154
+ printHelp();
155
+ process.exit(1);
156
+ }
157
+ const cwd = process.cwd();
158
+ const absoluteConfigPath = path.isAbsolute(args.configPath) ? args.configPath : path.resolve(cwd, args.configPath);
159
+ if (!existsSync(absoluteConfigPath)) {
160
+ console.error(`[payload-www] config file not found: ${absoluteConfigPath}`);
161
+ process.exit(1);
162
+ }
163
+ let configModule;
164
+ try {
165
+ configModule = await import(pathToFileURL(absoluteConfigPath).href);
166
+ } catch (err) {
167
+ console.error(`[payload-www] failed to load config at ${absoluteConfigPath}:`);
168
+ console.error(err);
169
+ process.exit(1);
170
+ }
171
+ let config = configModule.default ?? configModule;
172
+ config = await config;
173
+ if (!config || typeof config !== "object") {
174
+ console.error("[payload-www] loaded config is empty or not an object.");
175
+ process.exit(1);
176
+ }
177
+ if (process.env.PAYLOAD_WWW_DEBUG === "1") {
178
+ const { writeFileSync } = await import("node:fs");
179
+ writeFileSync("/tmp/payload-config-dump.json", JSON.stringify(config, (k, v) => typeof v === "function" ? "[function]" : v, 2).slice(0, 200000));
180
+ const cfg = config;
181
+ console.error("[payload-www DEBUG] blocks:", cfg.blocks?.length ?? 0);
182
+ console.error("[payload-www DEBUG] collections:", cfg.collections?.length ?? 0);
183
+ console.error("[payload-www DEBUG] globals:", cfg.globals?.length ?? 0);
184
+ console.error("[payload-www DEBUG] keys:", Object.keys(config).slice(0, 30).join(","));
185
+ const firstBlock = cfg.blocks?.[0] ?? null;
186
+ if (firstBlock) {
187
+ console.error("[payload-www DEBUG] first block slug:", firstBlock.slug);
188
+ console.error("[payload-www DEBUG] first block custom:", JSON.stringify(firstBlock.custom));
189
+ }
190
+ }
191
+ const result = await generateAsyncImportmap(config, {
192
+ output: path.isAbsolute(args.output) ? args.output : path.resolve(cwd, args.output),
193
+ ...args.packageName ? { packageName: args.packageName } : {}
194
+ });
195
+ console.log(`[payload-www] wrote ${result.entries} entries to ${result.output}`);
196
+ }
197
+ main().catch((err) => {
198
+ console.error("[payload-www] unhandled error:");
199
+ console.error(err);
200
+ process.exit(1);
201
+ });
package/dist/config.js CHANGED
@@ -1,11 +1,11 @@
1
1
 
2
2
 
3
- // package.json
4
- var name = "@justanarthur/payload-www";
5
-
6
3
  // src/createWWWConfig.ts
7
4
  import openAIResolver from "@justanarthur/payload-plugin-translator/resolvers/openAI";
8
5
 
6
+ // package.json
7
+ var name = "@justanarthur/payload-www";
8
+
9
9
  // src/collections/hooks/populatePublishedAt.ts
10
10
  var populatePublishedAt = ({ data, operation, req }) => {
11
11
  if (operation === "create" || operation === "update") {
@@ -358,18 +358,7 @@ function createWWWConfig() {
358
358
  createHeaderGlobal(),
359
359
  createFooterGlobal()
360
360
  ], config.globals);
361
- const renderDependencies = {};
362
- for (const { slug, custom } of blocks) {
363
- const path = custom?.[name]?.path;
364
- if (typeof path === "string" && slug)
365
- renderDependencies[slug] = { path, type: "component" };
366
- }
367
- for (const { custom } of [...collections, ...globals]) {
368
- const path = custom?.[name]?.path;
369
- if (typeof path === "string")
370
- renderDependencies[path] = { path, type: "component" };
371
- }
372
- const plugins = mergeOrOverride([
361
+ const defaultPlugins = [
373
362
  seoPlugin(mergeOrOverride({
374
363
  collections: [PAGES_SLUG, POSTS_SLUG],
375
364
  openaiApiKey: process.env.OPENAI_API_KEY,
@@ -392,19 +381,13 @@ function createWWWConfig() {
392
381
  })
393
382
  ]
394
383
  }, defaultPluginsConfigs?.translator))
395
- ], config.plugins);
384
+ ];
385
+ const plugins = mergeOrOverride(defaultPlugins, config.plugins);
396
386
  return {
397
387
  ...config,
398
388
  collections,
399
389
  globals,
400
- plugins,
401
- admin: {
402
- ...config.admin ?? {},
403
- dependencies: {
404
- ...renderDependencies,
405
- ...config.admin?.dependencies ?? {}
406
- }
407
- }
390
+ plugins
408
391
  };
409
392
  }
410
393
  return { withWWWConfig };
package/dist/pages.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { ReactElement } from "react";
2
- import { ImportMap, SanitizedConfig } from "payload";
2
+ import { ImportMap as ImportMap2, SanitizedConfig } from "payload";
3
3
  type RenderedWWWModule<Data = any> = {
4
4
  config: SanitizedConfig;
5
- importMap: ImportMap;
5
+ importMap: ImportMap2;
6
6
  data: Data;
7
7
  } & Record<string, any>;
8
8
  declare function FooterPage({ data }: RenderedWWWModule): ReactElement;
@@ -11,7 +11,7 @@ declare function HeaderPage({ data }: RenderedWWWModule): ReactElement2;
11
11
  import { ReactElement as ReactElement3 } from "react";
12
12
  declare function PagesPage({ data, locale,...props }: RenderedWWWModule): Promise<ReactElement3>;
13
13
  import { Metadata, MetadataRoute } from "next";
14
- import { ImportMap as ImportMap2, SanitizedConfig as SanitizedConfig2 } from "payload";
14
+ import { ImportMap as ImportMap3, SanitizedConfig as SanitizedConfig2 } from "payload";
15
15
  import { ReactNode as ReactNode2 } from "react";
16
16
  type SlugShape = "single" | "catch-all";
17
17
  type NextPageProps = {
@@ -25,7 +25,7 @@ type RoutingConfig = GenericRoutingConfig<string[], any, any, any>;
25
25
  type CreateCollectionPageExportsArgs<S extends string = "pages"> = {
26
26
  slug?: S;
27
27
  config: Promise<SanitizedConfig2>;
28
- importMap: ImportMap2;
28
+ importMap: ImportMap3;
29
29
  routing: RoutingConfig;
30
30
  slugShape?: SlugShape;
31
31
  };
package/dist/pages.js CHANGED
@@ -116,47 +116,43 @@ function HeaderPage({ data }) {
116
116
 
117
117
  // src/render/getFromImportMap.ts
118
118
  function getFromImportMap(key, importMap) {
119
- return key && importMap[key.includes("#") ? key : key + "#default"];
120
- }
121
-
122
- // src/render/generateImportName.ts
123
- function generateImportName(type, slug) {
124
- switch (type) {
125
- case "block":
126
- return `Block${slug.replace(/(^\w|-\w)/g, (m) => m.replace("-", "").toUpperCase())}#default`;
127
- case "page":
128
- return `Page${slug.replace(/(^\w|-\w)/g, (m) => m.replace("-", "").toUpperCase())}#default`;
129
- default:
130
- throw new Error(`Unknown type: ${type}`);
119
+ if (!key)
120
+ return;
121
+ const entry = importMap[key.includes("#") ? key : `${key}#default`];
122
+ if (entry == null)
123
+ return;
124
+ if (typeof entry === "function") {
125
+ return entry().then((mod) => {
126
+ if (typeof mod === "function")
127
+ return mod;
128
+ const modObj = mod;
129
+ return modObj.default ?? mod;
130
+ });
131
131
  }
132
+ return entry;
132
133
  }
133
134
 
135
+ // package.json
136
+ var name = "@justanarthur/payload-www";
137
+
134
138
  // src/render/blocks/renderBlocks.tsx
135
139
  import { jsx as jsx3, Fragment } from "react/jsx-runtime";
136
- var RenderBlocks = ({
137
- blocks,
138
- blockProps,
139
- config,
140
- importMap,
141
- locale,
142
- searchParams
143
- }) => {
144
- if (!blocks || !Array.isArray(blocks) || blocks.length === 0) {
145
- console.log("[WWW] render/blocks:RenderBlocks no blocks (locale=", locale, ")");
140
+ var DEFAULT_BLOCK_PATH_PREFIX = "@/components/blocks";
141
+ var RenderBlocks = async ({ blocks, blockProps, config, importMap, locale, searchParams }) => {
142
+ if (!blocks || !Array.isArray(blocks) || blocks.length === 0)
146
143
  return null;
147
- }
148
- console.log("[WWW] render/blocks:RenderBlocks rendering count=", blocks.length, "locale=", locale);
149
144
  const rendered = [];
150
145
  for (let i = 0;i < blocks.length; i++) {
151
146
  const block = blocks[i];
152
147
  const { blockType } = block;
153
- const importMapPath = config.admin?.dependencies?.[blockType]?.path || generateImportName("block", blockType);
154
- const Block = getFromImportMap(importMapPath, importMap);
148
+ const blockConfig = (config.blocks ?? []).find((b) => b.slug === blockType);
149
+ const customPath = blockConfig?.custom?.[name]?.path;
150
+ const importMapPath = (typeof customPath === "string" ? customPath : null) ?? `${DEFAULT_BLOCK_PATH_PREFIX}/${blockType}`;
151
+ const Block = await getFromImportMap(importMapPath, importMap);
155
152
  if (!Block) {
156
153
  console.warn(`[WWW] render/blocks:RenderBlocks no block for type=${blockType} importMapPath=${importMapPath} (locale=${locale})`);
157
154
  continue;
158
155
  }
159
- console.log("[WWW] render/blocks:RenderBlocks [", i, "] blockType=", blockType, "importMapPath=", importMapPath);
160
156
  rendered.push(/* @__PURE__ */ jsx3(Block, {
161
157
  index: i,
162
158
  ...blockProps,
@@ -348,9 +344,6 @@ function buildAlternates(locale, ...args) {
348
344
  // src/render/pages/createCollectionPageExports.tsx
349
345
  import { createSiteDefaults, generateMeta } from "@justanarthur/payload-plugin-seo/next-metadata";
350
346
 
351
- // package.json
352
- var name = "@justanarthur/payload-www";
353
-
354
347
  // src/render/renderWWWModule.tsx
355
348
  import { jsx as jsx5 } from "react/jsx-runtime";
356
349
  async function renderWWWDataModule(data, {
@@ -361,7 +354,7 @@ async function renderWWWDataModule(data, {
361
354
  }, props) {
362
355
  const config = await configPromise;
363
356
  const renderPath = config[configPath]?.find((c) => c.slug === collectionSlug)?.custom?.[name]?.path;
364
- const RenderModule = getFromImportMap(renderPath, importMap);
357
+ const RenderModule = await getFromImportMap(renderPath, importMap);
365
358
  if (!RenderModule) {
366
359
  if (false) {}
367
360
  return null;
@@ -1,8 +1,8 @@
1
1
  import { ReactElement } from "react";
2
- import { ImportMap, SanitizedConfig } from "payload";
2
+ import { ImportMap as ImportMap2, SanitizedConfig } from "payload";
3
3
  type RenderedWWWModule<Data = any> = {
4
4
  config: SanitizedConfig;
5
- importMap: ImportMap;
5
+ importMap: ImportMap2;
6
6
  data: Data;
7
7
  } & Record<string, any>;
8
8
  declare function FooterPage({ data }: RenderedWWWModule): ReactElement;
@@ -13,7 +13,7 @@ declare function PagesPage({ data, locale,...props }: RenderedWWWModule): Promis
13
13
  import { ReactElement as ReactElement4 } from "react";
14
14
  declare function PostsPage({ doc, locale,...props }: RenderedWWWModule): Promise<ReactElement4>;
15
15
  import { Metadata, MetadataRoute } from "next";
16
- import { ImportMap as ImportMap2, SanitizedConfig as SanitizedConfig2 } from "payload";
16
+ import { ImportMap as ImportMap3, SanitizedConfig as SanitizedConfig2 } from "payload";
17
17
  import { ReactNode as ReactNode2 } from "react";
18
18
  type SlugShape = "single" | "catch-all";
19
19
  import { ReactNode } from "react";
@@ -34,7 +34,7 @@ type RoutingConfig = GenericRoutingConfig<string[], any, any, any>;
34
34
  type CreateCollectionPageExportsArgs<S extends string = "pages"> = {
35
35
  slug?: S;
36
36
  config: Promise<SanitizedConfig2>;
37
- importMap: ImportMap2;
37
+ importMap: ImportMap3;
38
38
  routing: RoutingConfig;
39
39
  slugShape?: SlugShape;
40
40
  };
@@ -54,12 +54,12 @@ declare function createCollectionPageExports<S extends string = "pages">({ slug:
54
54
  pagePathPrefix: string | undefined;
55
55
  };
56
56
  };
57
- import { ImportMap as ImportMap3, SanitizedConfig as SanitizedConfig3 } from "payload";
57
+ import { ImportMap as ImportMap4, SanitizedConfig as SanitizedConfig3 } from "payload";
58
58
  import { HTMLAttributes, ReactNode as ReactNode3 } from "react";
59
59
  import { JSX as JSX_1kxb2 } from "react/jsx-runtime";
60
60
  type CreateRootLayoutExportsArgs = {
61
61
  config: Promise<SanitizedConfig3>;
62
- importMap: ImportMap3;
62
+ importMap: ImportMap4;
63
63
  routing: RoutingConfig;
64
64
  };
65
65
  type CreateRootLayoutProvidersArgs = {
@@ -116,47 +116,43 @@ function HeaderPage({ data }) {
116
116
 
117
117
  // src/render/getFromImportMap.ts
118
118
  function getFromImportMap(key, importMap) {
119
- return key && importMap[key.includes("#") ? key : key + "#default"];
120
- }
121
-
122
- // src/render/generateImportName.ts
123
- function generateImportName(type, slug) {
124
- switch (type) {
125
- case "block":
126
- return `Block${slug.replace(/(^\w|-\w)/g, (m) => m.replace("-", "").toUpperCase())}#default`;
127
- case "page":
128
- return `Page${slug.replace(/(^\w|-\w)/g, (m) => m.replace("-", "").toUpperCase())}#default`;
129
- default:
130
- throw new Error(`Unknown type: ${type}`);
119
+ if (!key)
120
+ return;
121
+ const entry = importMap[key.includes("#") ? key : `${key}#default`];
122
+ if (entry == null)
123
+ return;
124
+ if (typeof entry === "function") {
125
+ return entry().then((mod) => {
126
+ if (typeof mod === "function")
127
+ return mod;
128
+ const modObj = mod;
129
+ return modObj.default ?? mod;
130
+ });
131
131
  }
132
+ return entry;
132
133
  }
133
134
 
135
+ // package.json
136
+ var name = "@justanarthur/payload-www";
137
+
134
138
  // src/render/blocks/renderBlocks.tsx
135
139
  import { jsx as jsx3, Fragment } from "react/jsx-runtime";
136
- var RenderBlocks = ({
137
- blocks,
138
- blockProps,
139
- config,
140
- importMap,
141
- locale,
142
- searchParams
143
- }) => {
144
- if (!blocks || !Array.isArray(blocks) || blocks.length === 0) {
145
- console.log("[WWW] render/blocks:RenderBlocks no blocks (locale=", locale, ")");
140
+ var DEFAULT_BLOCK_PATH_PREFIX = "@/components/blocks";
141
+ var RenderBlocks = async ({ blocks, blockProps, config, importMap, locale, searchParams }) => {
142
+ if (!blocks || !Array.isArray(blocks) || blocks.length === 0)
146
143
  return null;
147
- }
148
- console.log("[WWW] render/blocks:RenderBlocks rendering count=", blocks.length, "locale=", locale);
149
144
  const rendered = [];
150
145
  for (let i = 0;i < blocks.length; i++) {
151
146
  const block = blocks[i];
152
147
  const { blockType } = block;
153
- const importMapPath = config.admin?.dependencies?.[blockType]?.path || generateImportName("block", blockType);
154
- const Block = getFromImportMap(importMapPath, importMap);
148
+ const blockConfig = (config.blocks ?? []).find((b) => b.slug === blockType);
149
+ const customPath = blockConfig?.custom?.[name]?.path;
150
+ const importMapPath = (typeof customPath === "string" ? customPath : null) ?? `${DEFAULT_BLOCK_PATH_PREFIX}/${blockType}`;
151
+ const Block = await getFromImportMap(importMapPath, importMap);
155
152
  if (!Block) {
156
153
  console.warn(`[WWW] render/blocks:RenderBlocks no block for type=${blockType} importMapPath=${importMapPath} (locale=${locale})`);
157
154
  continue;
158
155
  }
159
- console.log("[WWW] render/blocks:RenderBlocks [", i, "] blockType=", blockType, "importMapPath=", importMapPath);
160
156
  rendered.push(/* @__PURE__ */ jsx3(Block, {
161
157
  index: i,
162
158
  ...blockProps,
@@ -378,9 +374,6 @@ function buildAlternates(locale, ...args) {
378
374
  // src/render/pages/createCollectionPageExports.tsx
379
375
  import { createSiteDefaults, generateMeta } from "@justanarthur/payload-plugin-seo/next-metadata";
380
376
 
381
- // package.json
382
- var name = "@justanarthur/payload-www";
383
-
384
377
  // src/render/renderWWWModule.tsx
385
378
  import { jsx as jsx6 } from "react/jsx-runtime";
386
379
  async function renderWWWDataModule(data, {
@@ -391,7 +384,7 @@ async function renderWWWDataModule(data, {
391
384
  }, props) {
392
385
  const config = await configPromise;
393
386
  const renderPath = config[configPath]?.find((c) => c.slug === collectionSlug)?.custom?.[name]?.path;
394
- const RenderModule = getFromImportMap(renderPath, importMap);
387
+ const RenderModule = await getFromImportMap(renderPath, importMap);
395
388
  if (!RenderModule) {
396
389
  if (false) {}
397
390
  return null;
package/dist/sitemap.js CHANGED
@@ -172,7 +172,20 @@ var name = "@justanarthur/payload-www";
172
172
 
173
173
  // src/render/getFromImportMap.ts
174
174
  function getFromImportMap(key, importMap) {
175
- return key && importMap[key.includes("#") ? key : key + "#default"];
175
+ if (!key)
176
+ return;
177
+ const entry = importMap[key.includes("#") ? key : `${key}#default`];
178
+ if (entry == null)
179
+ return;
180
+ if (typeof entry === "function") {
181
+ return entry().then((mod) => {
182
+ if (typeof mod === "function")
183
+ return mod;
184
+ const modObj = mod;
185
+ return modObj.default ?? mod;
186
+ });
187
+ }
188
+ return entry;
176
189
  }
177
190
 
178
191
  // src/render/renderWWWModule.tsx
@@ -185,7 +198,7 @@ async function renderWWWDataModule(data, {
185
198
  }, props) {
186
199
  const config = await configPromise;
187
200
  const renderPath = config[configPath]?.find((c) => c.slug === collectionSlug)?.custom?.[name]?.path;
188
- const RenderModule = getFromImportMap(renderPath, importMap);
201
+ const RenderModule = await getFromImportMap(renderPath, importMap);
189
202
  if (!RenderModule) {
190
203
  if (false) {}
191
204
  return null;
package/dist/utils.d.ts CHANGED
@@ -1,6 +1,12 @@
1
1
  declare function generateImportName(type: "block" | "page", slug: string): string;
2
+ import { ComponentType } from "react";
2
3
  import { ImportMap } from "payload";
3
- declare function getFromImportMap(key: string | undefined, importMap: ImportMap): any;
4
+ type AsyncImportMapEntry<T = ComponentType> = T | (() => Promise<{
5
+ default: T;
6
+ } | T>);
7
+ type AsyncImportMap = Record<string, AsyncImportMapEntry>;
8
+ type ResolvedImportMapEntry<T = ComponentType> = T | Promise<T>;
9
+ declare function getFromImportMap<T = ComponentType>(key: string | undefined, importMap: ImportMap | AsyncImportMap): ResolvedImportMapEntry<T> | undefined;
4
10
  declare const utils: {
5
11
  getFromImportMap: typeof getFromImportMap;
6
12
  generateImportName: typeof generateImportName;
package/dist/utils.js CHANGED
@@ -14,7 +14,20 @@ function generateImportName(type, slug) {
14
14
 
15
15
  // src/render/getFromImportMap.ts
16
16
  function getFromImportMap(key, importMap) {
17
- return key && importMap[key.includes("#") ? key : key + "#default"];
17
+ if (!key)
18
+ return;
19
+ const entry = importMap[key.includes("#") ? key : `${key}#default`];
20
+ if (entry == null)
21
+ return;
22
+ if (typeof entry === "function") {
23
+ return entry().then((mod) => {
24
+ if (typeof mod === "function")
25
+ return mod;
26
+ const modObj = mod;
27
+ return modObj.default ?? mod;
28
+ });
29
+ }
30
+ return entry;
18
31
  }
19
32
 
20
33
  // src/exports/utils.ts
package/package.json CHANGED
@@ -1,13 +1,16 @@
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.0.1",
4
+ "version": "1.2.0",
5
5
  "type": "module",
6
6
  "private": false,
7
7
  "files": [
8
8
  "dist",
9
9
  "README.md"
10
10
  ],
11
+ "bin": {
12
+ "payload-www": "./dist/cli.js"
13
+ },
11
14
  "exports": {
12
15
  "./translator": {
13
16
  "import": {
@@ -94,7 +97,9 @@
94
97
  "node": ">=20"
95
98
  },
96
99
  "scripts": {
97
- "build": "NODE_ENV=production bunup && node scripts/strip-createRequire.mjs",
100
+ "build": "NODE_ENV=production bunup && node scripts/strip-createRequire.mjs && bun run build:cli",
101
+ "build:lib": "NODE_ENV=production bunup",
102
+ "build:cli": "bun build src/cli/index.ts --target node --format esm --outfile dist/cli.js --external tsx --external 'tsx/esm/api'",
98
103
  "clean": "rm -rf dist .tsbuildinfo",
99
104
  "test": "vitest run",
100
105
  "test:watch": "vitest",
@@ -108,14 +113,15 @@
108
113
  "@payloadcms/next": "3.85.0",
109
114
  "next": "16.2.6",
110
115
  "next-intl": "^4.0.0",
111
- "server-only": "0.0.1"
116
+ "server-only": "0.0.1",
117
+ "tsx": "^4.19.2"
112
118
  },
113
119
  "devDependencies": {
114
120
  "@types/node": "22.19.9",
115
121
  "@types/react": "19.2.14",
116
122
  "@types/react-dom": "19.2.3",
117
123
  "bunup": "^0.16.32",
118
- "payload": "3.85.0",
124
+ "payload": "3.85.1",
119
125
  "react": "19.2.6",
120
126
  "react-dom": "19.2.6",
121
127
  "typescript": "5.7.3",