payload 4.0.0-internal.d927017 → 4.0.0-internal.e387174
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/admin/adapters/router.d.ts +8 -0
- package/dist/admin/adapters/router.d.ts.map +1 -1
- package/dist/admin/adapters/router.js.map +1 -1
- package/dist/bin/build.d.ts +34 -10
- package/dist/bin/build.d.ts.map +1 -1
- package/dist/bin/build.js +175 -29
- package/dist/bin/build.js.map +1 -1
- package/dist/bin/build.spec.js +336 -1
- package/dist/bin/build.spec.js.map +1 -1
- package/dist/bin/frameworkConventions.d.ts +8 -0
- package/dist/bin/frameworkConventions.d.ts.map +1 -0
- package/dist/bin/frameworkConventions.js +8 -0
- package/dist/bin/frameworkConventions.js.map +1 -0
- package/dist/bin/generateImportMap/utilities/resolveImportMapFilePath.d.ts.map +1 -1
- package/dist/bin/generateImportMap/utilities/resolveImportMapFilePath.js +5 -4
- package/dist/bin/generateImportMap/utilities/resolveImportMapFilePath.js.map +1 -1
- package/dist/index.bundled.d.ts +8 -0
- package/package.json +2 -2
|
@@ -44,6 +44,14 @@ export type RouterAdapterRouter = {
|
|
|
44
44
|
replace: (path: string, options?: {
|
|
45
45
|
scroll?: boolean;
|
|
46
46
|
}) => void;
|
|
47
|
+
/**
|
|
48
|
+
* Use this property to standardize behaviors across different router implementations.
|
|
49
|
+
* Set it up to sync client state to the URL without triggering a second server load.
|
|
50
|
+
*
|
|
51
|
+
* In Next.js, calling `window.history.replaceState` directly is sufficient, as Next.js does not observe history mutations.
|
|
52
|
+
* In TanStack Router, however, `history.replaceState` is monkeypatched to notify the router of changes.
|
|
53
|
+
*/
|
|
54
|
+
replaceState?: (url: string) => void;
|
|
47
55
|
};
|
|
48
56
|
export type LinkAdapterProps = {
|
|
49
57
|
children?: React.ReactNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../../src/admin/adapters/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,MAAM,sBAAsB,GAAG,KAAK,CAAC,aAAa,CAAC;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,CAAC,CAAA;AAEvF,MAAM,MAAM,mBAAmB,GAAG;IAChC;;OAEG;IACH,IAAI,EAAE,MAAM,IAAI,CAAA;IAChB;;OAEG;IACH,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAA;IAC5D;;OAEG;IACH,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB;;OAEG;IACH,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../../src/admin/adapters/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,MAAM,sBAAsB,GAAG,KAAK,CAAC,aAAa,CAAC;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,CAAC,CAAA;AAEvF,MAAM,MAAM,mBAAmB,GAAG;IAChC;;OAEG;IACH,IAAI,EAAE,MAAM,IAAI,CAAA;IAChB;;OAEG;IACH,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAA;IAC5D;;OAEG;IACH,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB;;OAEG;IACH,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAA;IAC/D;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;CACrC,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAA;IAClC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,GAAG,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/admin/adapters/router.ts"],"sourcesContent":["import type React from 'react'\n\n/**\n * Client-side router adapter to abstract away framework-specific routing implementations.\n * This way plugins and server components can use server-only APIs without directly importing any framework-specific modules.\n *\n * @example\n * ```tsx\n * // Next.js router adapter (simplified):\n * import { useRouter as useNextRouter, usePathname as useNextPathname } from 'next/navigation'\n *\n * const NextRouterAdapter: RouterAdapterComponent = ({ children }) => {\n * const router = useNextRouter()\n * const pathname = useNextPathname()\n *\n * return (\n * <RouterAdapterContext value={{ router, pathname, ... }}>\n * {children}\n * </RouterAdapterContext>\n * )\n * }\n * ```\n */\nexport type RouterAdapterComponent = React.ComponentType<{ children: React.ReactNode }>\n\nexport type RouterAdapterRouter = {\n /**\n * Navigate back to the previous page in the history stack.\n */\n back: () => void\n /**\n * Navigate to a new path.\n */\n push: (path: string, options?: { scroll?: boolean }) => void\n /**\n * Refresh the current route.\n */\n refresh: () => void\n /**\n * Replace the current path with a new one.\n */\n replace: (path: string, options?: { scroll?: boolean }) => void\n}\n\nexport type LinkAdapterProps = {\n children?: React.ReactNode\n href: string\n prefetch?: boolean\n ref?: React.Ref<HTMLAnchorElement>\n replace?: boolean\n scroll?: boolean\n} & Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'href'>\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/admin/adapters/router.ts"],"sourcesContent":["import type React from 'react'\n\n/**\n * Client-side router adapter to abstract away framework-specific routing implementations.\n * This way plugins and server components can use server-only APIs without directly importing any framework-specific modules.\n *\n * @example\n * ```tsx\n * // Next.js router adapter (simplified):\n * import { useRouter as useNextRouter, usePathname as useNextPathname } from 'next/navigation'\n *\n * const NextRouterAdapter: RouterAdapterComponent = ({ children }) => {\n * const router = useNextRouter()\n * const pathname = useNextPathname()\n *\n * return (\n * <RouterAdapterContext value={{ router, pathname, ... }}>\n * {children}\n * </RouterAdapterContext>\n * )\n * }\n * ```\n */\nexport type RouterAdapterComponent = React.ComponentType<{ children: React.ReactNode }>\n\nexport type RouterAdapterRouter = {\n /**\n * Navigate back to the previous page in the history stack.\n */\n back: () => void\n /**\n * Navigate to a new path.\n */\n push: (path: string, options?: { scroll?: boolean }) => void\n /**\n * Refresh the current route.\n */\n refresh: () => void\n /**\n * Replace the current path with a new one.\n */\n replace: (path: string, options?: { scroll?: boolean }) => void\n /**\n * Use this property to standardize behaviors across different router implementations.\n * Set it up to sync client state to the URL without triggering a second server load.\n *\n * In Next.js, calling `window.history.replaceState` directly is sufficient, as Next.js does not observe history mutations.\n * In TanStack Router, however, `history.replaceState` is monkeypatched to notify the router of changes.\n */\n replaceState?: (url: string) => void\n}\n\nexport type LinkAdapterProps = {\n children?: React.ReactNode\n href: string\n prefetch?: boolean\n ref?: React.Ref<HTMLAnchorElement>\n replace?: boolean\n scroll?: boolean\n} & Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'href'>\n"],"names":[],"mappings":"AAoDA,WAO+D"}
|
package/dist/bin/build.d.ts
CHANGED
|
@@ -1,25 +1,49 @@
|
|
|
1
1
|
import type { SanitizedConfig } from '../config/types.js';
|
|
2
|
+
type Framework = 'next' | 'tanstack-start';
|
|
2
3
|
/**
|
|
3
4
|
* `payload build` — generate the import map (and types) so they are on disk
|
|
4
|
-
* before
|
|
5
|
-
* build, forwarding any extra
|
|
5
|
+
* before the framework build statically imports them, then detect the project's
|
|
6
|
+
* framework (Next.js or TanStack Start) and run its build, forwarding any extra
|
|
7
|
+
* CLI args verbatim.
|
|
6
8
|
*
|
|
7
|
-
* Owns its own process lifecycle: it exits with
|
|
8
|
-
* exits 1 if pre-build generation fails (never builds
|
|
9
|
+
* Owns its own process lifecycle: it exits with the framework build's exit code,
|
|
10
|
+
* or exits 1 if pre-build generation or framework detection fails (never builds
|
|
11
|
+
* against a stale map or the wrong bundler).
|
|
9
12
|
*/
|
|
10
13
|
export declare function build({ config }: {
|
|
11
14
|
config: SanitizedConfig;
|
|
12
15
|
}): Promise<void>;
|
|
13
16
|
/**
|
|
14
|
-
*
|
|
15
|
-
* `
|
|
16
|
-
*
|
|
17
|
+
* Determine whether the project builds with Next.js or TanStack Start. An explicit
|
|
18
|
+
* `PAYLOAD_FRAMEWORK` env wins; otherwise tries the most intentional signals first
|
|
19
|
+
* — declared dependencies, then framework config files, then Payload's
|
|
20
|
+
* admin-route folder conventions — falling through when a layer is inconclusive.
|
|
21
|
+
* Throws with guidance for an unsupported override or when no single framework can
|
|
22
|
+
* be determined.
|
|
17
23
|
*/
|
|
24
|
+
export declare function detectFramework(cwd?: string): Framework;
|
|
25
|
+
/** Resolve the project's `next` binary — see {@link resolveBin}. */
|
|
18
26
|
export declare function resolveNextBin(cwd?: string): string;
|
|
27
|
+
/** Resolve the project's `vite` binary — see {@link resolveBin}. */
|
|
28
|
+
export declare function resolveViteBin(cwd?: string): string;
|
|
19
29
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
|
|
30
|
+
* Map a detected framework to the resolved binary and argument list to spawn.
|
|
31
|
+
* Both frameworks take the `build` subcommand followed by the forwarded args.
|
|
32
|
+
*/
|
|
33
|
+
export declare function resolveBuildCommand({ cwd, forwardedArgs, framework, }: {
|
|
34
|
+
cwd?: string;
|
|
35
|
+
forwardedArgs: string[];
|
|
36
|
+
framework: Framework;
|
|
37
|
+
}): {
|
|
38
|
+
args: string[];
|
|
39
|
+
bin: string;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Forward the raw args that follow the `build` subcommand to the framework build
|
|
43
|
+
* (`next build` / `vite build`), dropping payload-only flags. Uses raw argv (not
|
|
44
|
+
* minimist) so flags like `--turbopack` (Next) or `--mode staging` (Vite) pass
|
|
45
|
+
* through verbatim.
|
|
23
46
|
*/
|
|
24
47
|
export declare function getForwardedArgs(argv?: string[]): string[];
|
|
48
|
+
export {};
|
|
25
49
|
//# sourceMappingURL=build.d.ts.map
|
package/dist/bin/build.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/bin/build.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/bin/build.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAMzD,KAAK,SAAS,GAAG,MAAM,GAAG,gBAAgB,CAAA;AAY1C;;;;;;;;;GASG;AACH,wBAAsB,KAAK,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,eAAe,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuClF;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,GAAG,GAAE,MAAsB,GAAG,SAAS,CAuDtE;AAED,oEAAoE;AACpE,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,CAElE;AAED,oEAAoE;AACpE,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,CAElE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,GAAmB,EACnB,aAAa,EACb,SAAS,GACV,EAAE;IACD,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,SAAS,EAAE,SAAS,CAAA;CACrB,GAAG;IAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAGlC;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,MAAM,EAAE,CAIjF"}
|
package/dist/bin/build.js
CHANGED
|
@@ -1,16 +1,33 @@
|
|
|
1
1
|
/* eslint-disable no-console */ import { spawn } from 'node:child_process';
|
|
2
|
-
import { readFileSync } from 'node:fs';
|
|
2
|
+
import fs, { readFileSync } from 'node:fs';
|
|
3
3
|
import { createRequire } from 'node:module';
|
|
4
4
|
import path from 'node:path';
|
|
5
|
+
import { NEXT_PAYLOAD_ROUTE_GROUP, TANSTACK_PAYLOAD_DIR } from './frameworkConventions.js';
|
|
5
6
|
import { generateImportMap } from './generateImportMap/index.js';
|
|
6
7
|
import { generateTypes } from './generateTypes.js';
|
|
8
|
+
const NEXT_CONFIG_FILES = [
|
|
9
|
+
'next.config.js',
|
|
10
|
+
'next.config.ts',
|
|
11
|
+
'next.config.mjs',
|
|
12
|
+
'next.config.cjs'
|
|
13
|
+
];
|
|
14
|
+
const VITE_CONFIG_FILES = [
|
|
15
|
+
'vite.config.js',
|
|
16
|
+
'vite.config.ts',
|
|
17
|
+
'vite.config.mjs',
|
|
18
|
+
'vite.config.cjs',
|
|
19
|
+
'vite.config.cts',
|
|
20
|
+
'vite.config.mts'
|
|
21
|
+
];
|
|
7
22
|
/**
|
|
8
23
|
* `payload build` — generate the import map (and types) so they are on disk
|
|
9
|
-
* before
|
|
10
|
-
* build, forwarding any extra
|
|
24
|
+
* before the framework build statically imports them, then detect the project's
|
|
25
|
+
* framework (Next.js or TanStack Start) and run its build, forwarding any extra
|
|
26
|
+
* CLI args verbatim.
|
|
11
27
|
*
|
|
12
|
-
* Owns its own process lifecycle: it exits with
|
|
13
|
-
* exits 1 if pre-build generation fails (never builds
|
|
28
|
+
* Owns its own process lifecycle: it exits with the framework build's exit code,
|
|
29
|
+
* or exits 1 if pre-build generation or framework detection fails (never builds
|
|
30
|
+
* against a stale map or the wrong bundler).
|
|
14
31
|
*/ export async function build({ config }) {
|
|
15
32
|
const skipTypes = process.argv.includes('--no-types');
|
|
16
33
|
try {
|
|
@@ -27,18 +44,27 @@ import { generateTypes } from './generateTypes.js';
|
|
|
27
44
|
console.error(err);
|
|
28
45
|
return process.exit(1);
|
|
29
46
|
}
|
|
30
|
-
|
|
31
|
-
|
|
47
|
+
let bin;
|
|
48
|
+
let args;
|
|
49
|
+
try {
|
|
50
|
+
const framework = detectFramework();
|
|
51
|
+
({ args, bin } = resolveBuildCommand({
|
|
52
|
+
forwardedArgs: getForwardedArgs(),
|
|
53
|
+
framework
|
|
54
|
+
}));
|
|
55
|
+
} catch (err) {
|
|
56
|
+
console.error(err instanceof Error ? err.message : err);
|
|
57
|
+
return process.exit(1);
|
|
58
|
+
}
|
|
32
59
|
const exitCode = await new Promise((resolve)=>{
|
|
33
60
|
const child = spawn(process.execPath, [
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
...forwardedArgs
|
|
61
|
+
bin,
|
|
62
|
+
...args
|
|
37
63
|
], {
|
|
38
64
|
stdio: 'inherit'
|
|
39
65
|
});
|
|
40
66
|
child.on('error', (err)=>{
|
|
41
|
-
console.error('Failed to run
|
|
67
|
+
console.error('Failed to run build:');
|
|
42
68
|
console.error(err);
|
|
43
69
|
resolve(1);
|
|
44
70
|
});
|
|
@@ -49,32 +75,152 @@ import { generateTypes } from './generateTypes.js';
|
|
|
49
75
|
process.exit(exitCode);
|
|
50
76
|
}
|
|
51
77
|
/**
|
|
52
|
-
*
|
|
53
|
-
* `
|
|
54
|
-
*
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
78
|
+
* Determine whether the project builds with Next.js or TanStack Start. An explicit
|
|
79
|
+
* `PAYLOAD_FRAMEWORK` env wins; otherwise tries the most intentional signals first
|
|
80
|
+
* — declared dependencies, then framework config files, then Payload's
|
|
81
|
+
* admin-route folder conventions — falling through when a layer is inconclusive.
|
|
82
|
+
* Throws with guidance for an unsupported override or when no single framework can
|
|
83
|
+
* be determined.
|
|
84
|
+
*/ export function detectFramework(cwd = process.cwd()) {
|
|
85
|
+
const override = process.env.PAYLOAD_FRAMEWORK;
|
|
86
|
+
if (override) {
|
|
87
|
+
if (isFramework(override)) {
|
|
88
|
+
return override;
|
|
89
|
+
}
|
|
90
|
+
throw new Error(`PAYLOAD_FRAMEWORK is set to "${override}", which is not supported. Use one of: next, tanstack-start.`);
|
|
62
91
|
}
|
|
63
|
-
const
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
92
|
+
const deps = readProjectDependencies(cwd);
|
|
93
|
+
const hasNextDep = Boolean(deps.next);
|
|
94
|
+
const hasTanstackDep = Boolean(deps['@tanstack/react-start']);
|
|
95
|
+
if (hasNextDep && !hasTanstackDep) {
|
|
96
|
+
return 'next';
|
|
67
97
|
}
|
|
68
|
-
|
|
98
|
+
if (hasTanstackDep && !hasNextDep) {
|
|
99
|
+
return 'tanstack-start';
|
|
100
|
+
}
|
|
101
|
+
const hasNextConfig = NEXT_CONFIG_FILES.some((file)=>fs.existsSync(path.join(cwd, file)));
|
|
102
|
+
const hasViteConfig = VITE_CONFIG_FILES.some((file)=>fs.existsSync(path.join(cwd, file)));
|
|
103
|
+
if (hasNextConfig && !hasViteConfig) {
|
|
104
|
+
return 'next';
|
|
105
|
+
}
|
|
106
|
+
if (hasViteConfig && !hasNextConfig) {
|
|
107
|
+
return 'tanstack-start';
|
|
108
|
+
}
|
|
109
|
+
const hasNextFolder = [
|
|
110
|
+
path.join(cwd, 'app', NEXT_PAYLOAD_ROUTE_GROUP),
|
|
111
|
+
path.join(cwd, 'src', 'app', NEXT_PAYLOAD_ROUTE_GROUP)
|
|
112
|
+
].some((dir)=>fs.existsSync(dir));
|
|
113
|
+
const hasTanstackFolder = [
|
|
114
|
+
path.join(cwd, 'app', TANSTACK_PAYLOAD_DIR),
|
|
115
|
+
path.join(cwd, 'src', 'app', TANSTACK_PAYLOAD_DIR)
|
|
116
|
+
].some((dir)=>fs.existsSync(dir));
|
|
117
|
+
if (hasNextFolder && !hasTanstackFolder) {
|
|
118
|
+
return 'next';
|
|
119
|
+
}
|
|
120
|
+
if (hasTanstackFolder && !hasNextFolder) {
|
|
121
|
+
return 'tanstack-start';
|
|
122
|
+
}
|
|
123
|
+
throw new Error(buildDetectionError({
|
|
124
|
+
hasNextConfig,
|
|
125
|
+
hasNextDep,
|
|
126
|
+
hasNextFolder,
|
|
127
|
+
hasTanstackDep,
|
|
128
|
+
hasTanstackFolder,
|
|
129
|
+
hasViteConfig
|
|
130
|
+
}));
|
|
131
|
+
}
|
|
132
|
+
/** Resolve the project's `next` binary — see {@link resolveBin}. */ export function resolveNextBin(cwd = process.cwd()) {
|
|
133
|
+
return resolveBin({
|
|
134
|
+
cwd,
|
|
135
|
+
displayName: 'Next.js',
|
|
136
|
+
packageName: 'next'
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
/** Resolve the project's `vite` binary — see {@link resolveBin}. */ export function resolveViteBin(cwd = process.cwd()) {
|
|
140
|
+
return resolveBin({
|
|
141
|
+
cwd,
|
|
142
|
+
displayName: 'Vite',
|
|
143
|
+
packageName: 'vite'
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Map a detected framework to the resolved binary and argument list to spawn.
|
|
148
|
+
* Both frameworks take the `build` subcommand followed by the forwarded args.
|
|
149
|
+
*/ export function resolveBuildCommand({ cwd = process.cwd(), forwardedArgs, framework }) {
|
|
150
|
+
const bin = framework === 'next' ? resolveNextBin(cwd) : resolveViteBin(cwd);
|
|
151
|
+
return {
|
|
152
|
+
args: [
|
|
153
|
+
'build',
|
|
154
|
+
...forwardedArgs
|
|
155
|
+
],
|
|
156
|
+
bin
|
|
157
|
+
};
|
|
69
158
|
}
|
|
70
159
|
/**
|
|
71
|
-
* Forward the raw args that follow the `build` subcommand to
|
|
72
|
-
* dropping payload-only flags. Uses raw argv (not
|
|
73
|
-
* `--turbopack` or `--
|
|
160
|
+
* Forward the raw args that follow the `build` subcommand to the framework build
|
|
161
|
+
* (`next build` / `vite build`), dropping payload-only flags. Uses raw argv (not
|
|
162
|
+
* minimist) so flags like `--turbopack` (Next) or `--mode staging` (Vite) pass
|
|
163
|
+
* through verbatim.
|
|
74
164
|
*/ export function getForwardedArgs(argv = process.argv.slice(2)) {
|
|
75
165
|
const buildIndex = argv.indexOf('build');
|
|
76
166
|
const rest = buildIndex === -1 ? argv : argv.slice(buildIndex + 1);
|
|
77
167
|
return rest.filter((arg)=>arg !== '--no-types');
|
|
78
168
|
}
|
|
169
|
+
function isFramework(value) {
|
|
170
|
+
return value === 'next' || value === 'tanstack-start';
|
|
171
|
+
}
|
|
172
|
+
function readProjectDependencies(cwd) {
|
|
173
|
+
try {
|
|
174
|
+
const pkg = JSON.parse(readFileSync(path.join(cwd, 'package.json'), 'utf8'));
|
|
175
|
+
return {
|
|
176
|
+
...pkg.dependencies,
|
|
177
|
+
...pkg.devDependencies
|
|
178
|
+
};
|
|
179
|
+
} catch {
|
|
180
|
+
return {};
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
function buildDetectionError(signals) {
|
|
184
|
+
const conflicts = [];
|
|
185
|
+
if (signals.hasNextDep && signals.hasTanstackDep) {
|
|
186
|
+
conflicts.push('dependencies (`next` and `@tanstack/react-start`)');
|
|
187
|
+
}
|
|
188
|
+
if (signals.hasNextConfig && signals.hasViteConfig) {
|
|
189
|
+
conflicts.push('config files (next.config.* and vite.config.*)');
|
|
190
|
+
}
|
|
191
|
+
if (signals.hasNextFolder && signals.hasTanstackFolder) {
|
|
192
|
+
conflicts.push('app folders (app/(payload) and app/_payload)');
|
|
193
|
+
}
|
|
194
|
+
if (conflicts.length) {
|
|
195
|
+
return `Could not determine your framework for \`payload build\`: conflicting signals found in ${conflicts.join(', ')}. Resolve the conflict so only one framework is indicated.`;
|
|
196
|
+
}
|
|
197
|
+
return [
|
|
198
|
+
'Could not determine your framework for `payload build`.',
|
|
199
|
+
'Checked:',
|
|
200
|
+
' • dependencies: no `next` or `@tanstack/react-start` in package.json',
|
|
201
|
+
' • config files: no next.config.* or vite.config.*',
|
|
202
|
+
' • app folders: no app/(payload) or app/_payload',
|
|
203
|
+
'Install your framework (Next.js or TanStack Start) and try again.'
|
|
204
|
+
].join('\n');
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Resolve a framework's binary path from its own package manifest, robust to a
|
|
208
|
+
* future `exports` field and to internal layout changes. Resolving from `cwd`
|
|
209
|
+
* (not PATH) works whether `payload build` runs via an npm script or `npx`.
|
|
210
|
+
*/ function resolveBin({ cwd, displayName, packageName }) {
|
|
211
|
+
const require = createRequire(path.join(cwd, 'package.json'));
|
|
212
|
+
let pkgPath;
|
|
213
|
+
try {
|
|
214
|
+
pkgPath = require.resolve(`${packageName}/package.json`);
|
|
215
|
+
} catch {
|
|
216
|
+
throw new Error(`Could not resolve "${packageName}" from the current project. Is ${displayName} installed?`);
|
|
217
|
+
}
|
|
218
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
|
|
219
|
+
const binField = typeof pkg.bin === 'string' ? pkg.bin : pkg.bin?.[packageName];
|
|
220
|
+
if (!binField) {
|
|
221
|
+
throw new Error(`Could not determine the "${packageName}" binary path from ${packageName}/package.json.`);
|
|
222
|
+
}
|
|
223
|
+
return path.join(path.dirname(pkgPath), binField);
|
|
224
|
+
}
|
|
79
225
|
|
|
80
226
|
//# sourceMappingURL=build.js.map
|
package/dist/bin/build.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/bin/build.ts"],"sourcesContent":["/* eslint-disable no-console */\nimport { spawn } from 'node:child_process'\nimport { readFileSync } from 'node:fs'\nimport { createRequire } from 'node:module'\nimport path from 'node:path'\n\nimport type { SanitizedConfig } from '../config/types.js'\n\nimport { generateImportMap } from './generateImportMap/index.js'\nimport { generateTypes } from './generateTypes.js'\n\n/**\n * `payload build` — generate the import map (and types) so they are on disk\n * before `next build` statically imports them, then run the project's Next.js\n * build, forwarding any extra CLI args verbatim.\n *\n * Owns its own process lifecycle: it exits with `next build`'s exit code, or\n * exits 1 if pre-build generation fails (never builds against a stale map).\n */\nexport async function build({ config }: { config: SanitizedConfig }): Promise<void> {\n const skipTypes = process.argv.includes('--no-types')\n\n try {\n await generateImportMap(config, { log: true })\n if (!skipTypes) {\n await generateTypes(config, { log: true })\n }\n } catch (err) {\n console.error('Pre-build generation failed:')\n console.error(err)\n return process.exit(1)\n }\n\n const nextBin = resolveNextBin()\n const forwardedArgs = getForwardedArgs()\n\n const exitCode = await new Promise<number>((resolve) => {\n const child = spawn(process.execPath, [nextBin, 'build', ...forwardedArgs], {\n stdio: 'inherit',\n })\n child.on('error', (err) => {\n console.error('Failed to run next build:')\n console.error(err)\n resolve(1)\n })\n child.on('exit', (code) => {\n resolve(code ?? 0)\n })\n })\n\n process.exit(exitCode)\n}\n\n/**\n * Resolve the project's `next` binary from its own manifest, robust to a future\n * `exports` field and to internal layout changes. Resolving from `cwd` (not\n * PATH) works whether `payload build` runs via an npm script or `npx`.\n */\nexport function resolveNextBin(cwd: string = process.cwd()): string {\n const require = createRequire(path.join(cwd, 'package.json'))\n\n let nextPkgPath: string\n try {\n nextPkgPath = require.resolve('next/package.json')\n } catch {\n throw new Error('Could not resolve \"next\" from the current project. Is Next.js installed?')\n }\n\n const nextPkg = JSON.parse(readFileSync(nextPkgPath, 'utf8')) as {\n bin?: Record<string, string> | string\n }\n const binField = typeof nextPkg.bin === 'string' ? nextPkg.bin : nextPkg.bin?.next\n if (!binField) {\n throw new Error('Could not determine the \"next\" binary path from next/package.json.')\n }\n\n return path.join(path.dirname(nextPkgPath), binField)\n}\n\n/**\n * Forward the raw args that follow the `build` subcommand to `next build`,\n * dropping payload-only flags. Uses raw argv (not minimist) so flags like\n * `--turbopack` or `--experimental-build-mode` pass through verbatim.\n */\nexport function getForwardedArgs(argv: string[] = process.argv.slice(2)): string[] {\n const buildIndex = argv.indexOf('build')\n const rest = buildIndex === -1 ? argv : argv.slice(buildIndex + 1)\n return rest.filter((arg) => arg !== '--no-types')\n}\n"],"names":["spawn","readFileSync","createRequire","path","generateImportMap","generateTypes","build","config","skipTypes","process","argv","includes","log","err","console","error","exit","nextBin","resolveNextBin","forwardedArgs","getForwardedArgs","exitCode","Promise","resolve","child","execPath","stdio","on","code","cwd","require","join","nextPkgPath","Error","nextPkg","JSON","parse","binField","bin","next","dirname","slice","buildIndex","indexOf","rest","filter","arg"],"mappings":"AAAA,6BAA6B,GAC7B,SAASA,KAAK,QAAQ,qBAAoB;AAC1C,SAASC,YAAY,QAAQ,UAAS;AACtC,SAASC,aAAa,QAAQ,cAAa;AAC3C,OAAOC,UAAU,YAAW;AAI5B,SAASC,iBAAiB,QAAQ,+BAA8B;AAChE,SAASC,aAAa,QAAQ,qBAAoB;AAElD;;;;;;;CAOC,GACD,OAAO,eAAeC,MAAM,EAAEC,MAAM,EAA+B;IACjE,MAAMC,YAAYC,QAAQC,IAAI,CAACC,QAAQ,CAAC;IAExC,IAAI;QACF,MAAMP,kBAAkBG,QAAQ;YAAEK,KAAK;QAAK;QAC5C,IAAI,CAACJ,WAAW;YACd,MAAMH,cAAcE,QAAQ;gBAAEK,KAAK;YAAK;QAC1C;IACF,EAAE,OAAOC,KAAK;QACZC,QAAQC,KAAK,CAAC;QACdD,QAAQC,KAAK,CAACF;QACd,OAAOJ,QAAQO,IAAI,CAAC;IACtB;IAEA,MAAMC,UAAUC;IAChB,MAAMC,gBAAgBC;IAEtB,MAAMC,WAAW,MAAM,IAAIC,QAAgB,CAACC;QAC1C,MAAMC,QAAQxB,MAAMS,QAAQgB,QAAQ,EAAE;YAACR;YAAS;eAAYE;SAAc,EAAE;YAC1EO,OAAO;QACT;QACAF,MAAMG,EAAE,CAAC,SAAS,CAACd;YACjBC,QAAQC,KAAK,CAAC;YACdD,QAAQC,KAAK,CAACF;YACdU,QAAQ;QACV;QACAC,MAAMG,EAAE,CAAC,QAAQ,CAACC;YAChBL,QAAQK,QAAQ;QAClB;IACF;IAEAnB,QAAQO,IAAI,CAACK;AACf;AAEA;;;;CAIC,GACD,OAAO,SAASH,eAAeW,MAAcpB,QAAQoB,GAAG,EAAE;IACxD,MAAMC,UAAU5B,cAAcC,KAAK4B,IAAI,CAACF,KAAK;IAE7C,IAAIG;IACJ,IAAI;QACFA,cAAcF,QAAQP,OAAO,CAAC;IAChC,EAAE,OAAM;QACN,MAAM,IAAIU,MAAM;IAClB;IAEA,MAAMC,UAAUC,KAAKC,KAAK,CAACnC,aAAa+B,aAAa;IAGrD,MAAMK,WAAW,OAAOH,QAAQI,GAAG,KAAK,WAAWJ,QAAQI,GAAG,GAAGJ,QAAQI,GAAG,EAAEC;IAC9E,IAAI,CAACF,UAAU;QACb,MAAM,IAAIJ,MAAM;IAClB;IAEA,OAAO9B,KAAK4B,IAAI,CAAC5B,KAAKqC,OAAO,CAACR,cAAcK;AAC9C;AAEA;;;;CAIC,GACD,OAAO,SAASjB,iBAAiBV,OAAiBD,QAAQC,IAAI,CAAC+B,KAAK,CAAC,EAAE;IACrE,MAAMC,aAAahC,KAAKiC,OAAO,CAAC;IAChC,MAAMC,OAAOF,eAAe,CAAC,IAAIhC,OAAOA,KAAK+B,KAAK,CAACC,aAAa;IAChE,OAAOE,KAAKC,MAAM,CAAC,CAACC,MAAQA,QAAQ;AACtC"}
|
|
1
|
+
{"version":3,"sources":["../../src/bin/build.ts"],"sourcesContent":["/* eslint-disable no-console */\nimport { spawn } from 'node:child_process'\nimport fs, { readFileSync } from 'node:fs'\nimport { createRequire } from 'node:module'\nimport path from 'node:path'\n\nimport type { SanitizedConfig } from '../config/types.js'\n\nimport { NEXT_PAYLOAD_ROUTE_GROUP, TANSTACK_PAYLOAD_DIR } from './frameworkConventions.js'\nimport { generateImportMap } from './generateImportMap/index.js'\nimport { generateTypes } from './generateTypes.js'\n\ntype Framework = 'next' | 'tanstack-start'\n\nconst NEXT_CONFIG_FILES = ['next.config.js', 'next.config.ts', 'next.config.mjs', 'next.config.cjs']\nconst VITE_CONFIG_FILES = [\n 'vite.config.js',\n 'vite.config.ts',\n 'vite.config.mjs',\n 'vite.config.cjs',\n 'vite.config.cts',\n 'vite.config.mts',\n]\n\n/**\n * `payload build` — generate the import map (and types) so they are on disk\n * before the framework build statically imports them, then detect the project's\n * framework (Next.js or TanStack Start) and run its build, forwarding any extra\n * CLI args verbatim.\n *\n * Owns its own process lifecycle: it exits with the framework build's exit code,\n * or exits 1 if pre-build generation or framework detection fails (never builds\n * against a stale map or the wrong bundler).\n */\nexport async function build({ config }: { config: SanitizedConfig }): Promise<void> {\n const skipTypes = process.argv.includes('--no-types')\n\n try {\n await generateImportMap(config, { log: true })\n if (!skipTypes) {\n await generateTypes(config, { log: true })\n }\n } catch (err) {\n console.error('Pre-build generation failed:')\n console.error(err)\n return process.exit(1)\n }\n\n let bin: string\n let args: string[]\n try {\n const framework = detectFramework()\n ;({ args, bin } = resolveBuildCommand({ forwardedArgs: getForwardedArgs(), framework }))\n } catch (err) {\n console.error(err instanceof Error ? err.message : err)\n return process.exit(1)\n }\n\n const exitCode = await new Promise<number>((resolve) => {\n const child = spawn(process.execPath, [bin, ...args], {\n stdio: 'inherit',\n })\n child.on('error', (err) => {\n console.error('Failed to run build:')\n console.error(err)\n resolve(1)\n })\n child.on('exit', (code) => {\n resolve(code ?? 0)\n })\n })\n\n process.exit(exitCode)\n}\n\n/**\n * Determine whether the project builds with Next.js or TanStack Start. An explicit\n * `PAYLOAD_FRAMEWORK` env wins; otherwise tries the most intentional signals first\n * — declared dependencies, then framework config files, then Payload's\n * admin-route folder conventions — falling through when a layer is inconclusive.\n * Throws with guidance for an unsupported override or when no single framework can\n * be determined.\n */\nexport function detectFramework(cwd: string = process.cwd()): Framework {\n const override = process.env.PAYLOAD_FRAMEWORK\n if (override) {\n if (isFramework(override)) {\n return override\n }\n throw new Error(\n `PAYLOAD_FRAMEWORK is set to \"${override}\", which is not supported. Use one of: next, tanstack-start.`,\n )\n }\n\n const deps = readProjectDependencies(cwd)\n const hasNextDep = Boolean(deps.next)\n const hasTanstackDep = Boolean(deps['@tanstack/react-start'])\n if (hasNextDep && !hasTanstackDep) {\n return 'next'\n }\n if (hasTanstackDep && !hasNextDep) {\n return 'tanstack-start'\n }\n\n const hasNextConfig = NEXT_CONFIG_FILES.some((file) => fs.existsSync(path.join(cwd, file)))\n const hasViteConfig = VITE_CONFIG_FILES.some((file) => fs.existsSync(path.join(cwd, file)))\n if (hasNextConfig && !hasViteConfig) {\n return 'next'\n }\n if (hasViteConfig && !hasNextConfig) {\n return 'tanstack-start'\n }\n\n const hasNextFolder = [\n path.join(cwd, 'app', NEXT_PAYLOAD_ROUTE_GROUP),\n path.join(cwd, 'src', 'app', NEXT_PAYLOAD_ROUTE_GROUP),\n ].some((dir) => fs.existsSync(dir))\n const hasTanstackFolder = [\n path.join(cwd, 'app', TANSTACK_PAYLOAD_DIR),\n path.join(cwd, 'src', 'app', TANSTACK_PAYLOAD_DIR),\n ].some((dir) => fs.existsSync(dir))\n if (hasNextFolder && !hasTanstackFolder) {\n return 'next'\n }\n if (hasTanstackFolder && !hasNextFolder) {\n return 'tanstack-start'\n }\n\n throw new Error(\n buildDetectionError({\n hasNextConfig,\n hasNextDep,\n hasNextFolder,\n hasTanstackDep,\n hasTanstackFolder,\n hasViteConfig,\n }),\n )\n}\n\n/** Resolve the project's `next` binary — see {@link resolveBin}. */\nexport function resolveNextBin(cwd: string = process.cwd()): string {\n return resolveBin({ cwd, displayName: 'Next.js', packageName: 'next' })\n}\n\n/** Resolve the project's `vite` binary — see {@link resolveBin}. */\nexport function resolveViteBin(cwd: string = process.cwd()): string {\n return resolveBin({ cwd, displayName: 'Vite', packageName: 'vite' })\n}\n\n/**\n * Map a detected framework to the resolved binary and argument list to spawn.\n * Both frameworks take the `build` subcommand followed by the forwarded args.\n */\nexport function resolveBuildCommand({\n cwd = process.cwd(),\n forwardedArgs,\n framework,\n}: {\n cwd?: string\n forwardedArgs: string[]\n framework: Framework\n}): { args: string[]; bin: string } {\n const bin = framework === 'next' ? resolveNextBin(cwd) : resolveViteBin(cwd)\n return { args: ['build', ...forwardedArgs], bin }\n}\n\n/**\n * Forward the raw args that follow the `build` subcommand to the framework build\n * (`next build` / `vite build`), dropping payload-only flags. Uses raw argv (not\n * minimist) so flags like `--turbopack` (Next) or `--mode staging` (Vite) pass\n * through verbatim.\n */\nexport function getForwardedArgs(argv: string[] = process.argv.slice(2)): string[] {\n const buildIndex = argv.indexOf('build')\n const rest = buildIndex === -1 ? argv : argv.slice(buildIndex + 1)\n return rest.filter((arg) => arg !== '--no-types')\n}\n\nfunction isFramework(value: string): value is Framework {\n return value === 'next' || value === 'tanstack-start'\n}\n\nfunction readProjectDependencies(cwd: string): Record<string, string> {\n try {\n const pkg = JSON.parse(readFileSync(path.join(cwd, 'package.json'), 'utf8')) as {\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n }\n return { ...pkg.dependencies, ...pkg.devDependencies }\n } catch {\n return {}\n }\n}\n\nfunction buildDetectionError(signals: {\n hasNextConfig: boolean\n hasNextDep: boolean\n hasNextFolder: boolean\n hasTanstackDep: boolean\n hasTanstackFolder: boolean\n hasViteConfig: boolean\n}): string {\n const conflicts: string[] = []\n if (signals.hasNextDep && signals.hasTanstackDep) {\n conflicts.push('dependencies (`next` and `@tanstack/react-start`)')\n }\n if (signals.hasNextConfig && signals.hasViteConfig) {\n conflicts.push('config files (next.config.* and vite.config.*)')\n }\n if (signals.hasNextFolder && signals.hasTanstackFolder) {\n conflicts.push('app folders (app/(payload) and app/_payload)')\n }\n\n if (conflicts.length) {\n return `Could not determine your framework for \\`payload build\\`: conflicting signals found in ${conflicts.join(', ')}. Resolve the conflict so only one framework is indicated.`\n }\n\n return [\n 'Could not determine your framework for `payload build`.',\n 'Checked:',\n ' • dependencies: no `next` or `@tanstack/react-start` in package.json',\n ' • config files: no next.config.* or vite.config.*',\n ' • app folders: no app/(payload) or app/_payload',\n 'Install your framework (Next.js or TanStack Start) and try again.',\n ].join('\\n')\n}\n\n/**\n * Resolve a framework's binary path from its own package manifest, robust to a\n * future `exports` field and to internal layout changes. Resolving from `cwd`\n * (not PATH) works whether `payload build` runs via an npm script or `npx`.\n */\nfunction resolveBin({\n cwd,\n displayName,\n packageName,\n}: {\n cwd: string\n displayName: string\n packageName: string\n}): string {\n const require = createRequire(path.join(cwd, 'package.json'))\n\n let pkgPath: string\n try {\n pkgPath = require.resolve(`${packageName}/package.json`)\n } catch {\n throw new Error(\n `Could not resolve \"${packageName}\" from the current project. Is ${displayName} installed?`,\n )\n }\n\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) as {\n bin?: Record<string, string> | string\n }\n const binField = typeof pkg.bin === 'string' ? pkg.bin : pkg.bin?.[packageName]\n if (!binField) {\n throw new Error(\n `Could not determine the \"${packageName}\" binary path from ${packageName}/package.json.`,\n )\n }\n\n return path.join(path.dirname(pkgPath), binField)\n}\n"],"names":["spawn","fs","readFileSync","createRequire","path","NEXT_PAYLOAD_ROUTE_GROUP","TANSTACK_PAYLOAD_DIR","generateImportMap","generateTypes","NEXT_CONFIG_FILES","VITE_CONFIG_FILES","build","config","skipTypes","process","argv","includes","log","err","console","error","exit","bin","args","framework","detectFramework","resolveBuildCommand","forwardedArgs","getForwardedArgs","Error","message","exitCode","Promise","resolve","child","execPath","stdio","on","code","cwd","override","env","PAYLOAD_FRAMEWORK","isFramework","deps","readProjectDependencies","hasNextDep","Boolean","next","hasTanstackDep","hasNextConfig","some","file","existsSync","join","hasViteConfig","hasNextFolder","dir","hasTanstackFolder","buildDetectionError","resolveNextBin","resolveBin","displayName","packageName","resolveViteBin","slice","buildIndex","indexOf","rest","filter","arg","value","pkg","JSON","parse","dependencies","devDependencies","signals","conflicts","push","length","require","pkgPath","binField","dirname"],"mappings":"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"}
|
package/dist/bin/build.spec.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
1
4
|
import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest';
|
|
2
5
|
// Default fake child auto-fires `exit(0)` synchronously so ordering/generation
|
|
3
6
|
// tests resolve. Specific tests override via `mockReturnValueOnce` to drive the
|
|
@@ -22,7 +25,7 @@ vi.mock('./generateTypes.js', ()=>({
|
|
|
22
25
|
generateTypes: generateTypesMock
|
|
23
26
|
}));
|
|
24
27
|
// Imported after mocks are registered
|
|
25
|
-
const { build, getForwardedArgs, resolveNextBin } = await import('./build.js');
|
|
28
|
+
const { build, detectFramework, getForwardedArgs, resolveBuildCommand, resolveNextBin, resolveViteBin } = await import('./build.js');
|
|
26
29
|
const fakeConfig = {};
|
|
27
30
|
describe('getForwardedArgs', ()=>{
|
|
28
31
|
it('returns args after the build token and strips --no-types', ()=>{
|
|
@@ -52,9 +55,73 @@ describe('resolveNextBin', ()=>{
|
|
|
52
55
|
expect(()=>resolveNextBin('/nonexistent-project-root')).toThrow(/next/i);
|
|
53
56
|
});
|
|
54
57
|
});
|
|
58
|
+
describe('resolveViteBin', ()=>{
|
|
59
|
+
it('resolves the vite bin from the current project', ()=>{
|
|
60
|
+
// vite is installed at the repo root; resolving from cwd must succeed
|
|
61
|
+
const binPath = resolveViteBin(process.cwd());
|
|
62
|
+
expect(binPath).toMatch(/vite[\\/].*bin[\\/]vite\.js$/);
|
|
63
|
+
});
|
|
64
|
+
it('throws a clear error when vite cannot be resolved', async ()=>{
|
|
65
|
+
// Vitest injects its own transitive `vite` dep onto NODE_PATH, so resolving
|
|
66
|
+
// "vite" from any cwd would otherwise succeed in this test process even
|
|
67
|
+
// when the project under test has no vite installed. Mock module
|
|
68
|
+
// resolution itself to simulate a real "vite not installed" project.
|
|
69
|
+
vi.resetModules();
|
|
70
|
+
vi.doMock('node:module', async (importOriginal)=>{
|
|
71
|
+
const actual = await importOriginal();
|
|
72
|
+
return {
|
|
73
|
+
...actual,
|
|
74
|
+
createRequire: ()=>({
|
|
75
|
+
resolve: ()=>{
|
|
76
|
+
throw new Error('Cannot find module');
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
};
|
|
80
|
+
});
|
|
81
|
+
const { resolveViteBin: resolveViteBinWithoutVite } = await import('./build.js');
|
|
82
|
+
expect(()=>resolveViteBinWithoutVite('/nonexistent-project-root')).toThrow(/vite/i);
|
|
83
|
+
vi.doUnmock('node:module');
|
|
84
|
+
vi.resetModules();
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
describe('resolveBuildCommand', ()=>{
|
|
88
|
+
it('maps next to the next bin and build args', ()=>{
|
|
89
|
+
const { args, bin } = resolveBuildCommand({
|
|
90
|
+
cwd: process.cwd(),
|
|
91
|
+
forwardedArgs: [
|
|
92
|
+
'--turbopack'
|
|
93
|
+
],
|
|
94
|
+
framework: 'next'
|
|
95
|
+
});
|
|
96
|
+
expect(bin).toMatch(/next[\\/].*bin[\\/]next$/);
|
|
97
|
+
expect(args).toEqual([
|
|
98
|
+
'build',
|
|
99
|
+
'--turbopack'
|
|
100
|
+
]);
|
|
101
|
+
});
|
|
102
|
+
it('maps tanstack-start to the vite bin and build args', ()=>{
|
|
103
|
+
const { args, bin } = resolveBuildCommand({
|
|
104
|
+
cwd: process.cwd(),
|
|
105
|
+
forwardedArgs: [
|
|
106
|
+
'--mode',
|
|
107
|
+
'staging'
|
|
108
|
+
],
|
|
109
|
+
framework: 'tanstack-start'
|
|
110
|
+
});
|
|
111
|
+
expect(bin).toMatch(/vite[\\/].*bin[\\/]vite\.js$/);
|
|
112
|
+
expect(args).toEqual([
|
|
113
|
+
'build',
|
|
114
|
+
'--mode',
|
|
115
|
+
'staging'
|
|
116
|
+
]);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
55
119
|
describe('build', ()=>{
|
|
56
120
|
let exitMock;
|
|
57
121
|
let originalArgv;
|
|
122
|
+
let originalFrameworkEnv;
|
|
123
|
+
let cwdSpy;
|
|
124
|
+
const buildTempDirs = [];
|
|
58
125
|
beforeEach(()=>{
|
|
59
126
|
spawnMock.mockClear();
|
|
60
127
|
generateImportMapMock.mockClear();
|
|
@@ -66,10 +133,30 @@ describe('build', ()=>{
|
|
|
66
133
|
'build'
|
|
67
134
|
];
|
|
68
135
|
exitMock = vi.spyOn(process, 'exit').mockImplementation(()=>undefined);
|
|
136
|
+
originalFrameworkEnv = process.env.PAYLOAD_FRAMEWORK;
|
|
137
|
+
// Force next for the legacy tests so they don't depend on the repo-root
|
|
138
|
+
// package.json's ambient `next` dependency for auto-detection.
|
|
139
|
+
process.env.PAYLOAD_FRAMEWORK = 'next';
|
|
69
140
|
});
|
|
70
141
|
afterEach(()=>{
|
|
71
142
|
process.argv = originalArgv;
|
|
72
143
|
exitMock.mockRestore();
|
|
144
|
+
if (originalFrameworkEnv === undefined) {
|
|
145
|
+
delete process.env.PAYLOAD_FRAMEWORK;
|
|
146
|
+
} else {
|
|
147
|
+
process.env.PAYLOAD_FRAMEWORK = originalFrameworkEnv;
|
|
148
|
+
}
|
|
149
|
+
if (cwdSpy) {
|
|
150
|
+
cwdSpy.mockRestore();
|
|
151
|
+
cwdSpy = undefined;
|
|
152
|
+
}
|
|
153
|
+
for (const dir of buildTempDirs){
|
|
154
|
+
rmSync(dir, {
|
|
155
|
+
force: true,
|
|
156
|
+
recursive: true
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
buildTempDirs.length = 0;
|
|
73
160
|
});
|
|
74
161
|
it('generates the import map before spawning, and generates types by default', async ()=>{
|
|
75
162
|
await build({
|
|
@@ -165,6 +252,254 @@ describe('build', ()=>{
|
|
|
165
252
|
expect(resolved).toBe(true);
|
|
166
253
|
expect(exitMock).toHaveBeenCalledWith(3);
|
|
167
254
|
});
|
|
255
|
+
it('spawns vite build for a detected tanstack project', async ()=>{
|
|
256
|
+
delete process.env.PAYLOAD_FRAMEWORK;
|
|
257
|
+
process.argv = [
|
|
258
|
+
'node',
|
|
259
|
+
'payload',
|
|
260
|
+
'build',
|
|
261
|
+
'--mode',
|
|
262
|
+
'staging'
|
|
263
|
+
];
|
|
264
|
+
const tanstackDir = mkdtempSync(path.join(os.tmpdir(), 'payload-build-ts-'));
|
|
265
|
+
buildTempDirs.push(tanstackDir);
|
|
266
|
+
writeFileSync(path.join(tanstackDir, 'package.json'), JSON.stringify({
|
|
267
|
+
dependencies: {
|
|
268
|
+
'@tanstack/react-start': '1.168.26'
|
|
269
|
+
}
|
|
270
|
+
}));
|
|
271
|
+
cwdSpy = vi.spyOn(process, 'cwd').mockReturnValue(tanstackDir);
|
|
272
|
+
await build({
|
|
273
|
+
config: fakeConfig
|
|
274
|
+
});
|
|
275
|
+
expect(spawnMock).toHaveBeenCalledTimes(1);
|
|
276
|
+
const [, spawnArgs] = spawnMock.mock.calls[0];
|
|
277
|
+
expect(spawnArgs[0]).toMatch(/vite[\\/].*bin[\\/]vite\.js$/);
|
|
278
|
+
expect(spawnArgs.slice(1)).toEqual([
|
|
279
|
+
'build',
|
|
280
|
+
'--mode',
|
|
281
|
+
'staging'
|
|
282
|
+
]);
|
|
283
|
+
});
|
|
284
|
+
it('exits 1 and does not spawn when the framework cannot be detected', async ()=>{
|
|
285
|
+
delete process.env.PAYLOAD_FRAMEWORK;
|
|
286
|
+
const emptyDir = mkdtempSync(path.join(os.tmpdir(), 'payload-build-empty-'));
|
|
287
|
+
buildTempDirs.push(emptyDir);
|
|
288
|
+
writeFileSync(path.join(emptyDir, 'package.json'), JSON.stringify({}));
|
|
289
|
+
cwdSpy = vi.spyOn(process, 'cwd').mockReturnValue(emptyDir);
|
|
290
|
+
await build({
|
|
291
|
+
config: fakeConfig
|
|
292
|
+
});
|
|
293
|
+
expect(exitMock).toHaveBeenCalledWith(1);
|
|
294
|
+
expect(spawnMock).not.toHaveBeenCalled();
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
describe('detectFramework', ()=>{
|
|
298
|
+
const createdDirs = [];
|
|
299
|
+
let originalFrameworkEnv;
|
|
300
|
+
const makeProject = (files)=>{
|
|
301
|
+
const dir = mkdtempSync(path.join(os.tmpdir(), 'payload-build-'));
|
|
302
|
+
createdDirs.push(dir);
|
|
303
|
+
for (const file of files){
|
|
304
|
+
const full = path.join(dir, file.path);
|
|
305
|
+
mkdirSync(path.dirname(full), {
|
|
306
|
+
recursive: true
|
|
307
|
+
});
|
|
308
|
+
writeFileSync(full, file.contents ?? '');
|
|
309
|
+
}
|
|
310
|
+
return dir;
|
|
311
|
+
};
|
|
312
|
+
const pkg = (deps)=>JSON.stringify({
|
|
313
|
+
dependencies: deps
|
|
314
|
+
});
|
|
315
|
+
beforeEach(()=>{
|
|
316
|
+
originalFrameworkEnv = process.env.PAYLOAD_FRAMEWORK;
|
|
317
|
+
delete process.env.PAYLOAD_FRAMEWORK;
|
|
318
|
+
});
|
|
319
|
+
afterEach(()=>{
|
|
320
|
+
if (originalFrameworkEnv === undefined) {
|
|
321
|
+
delete process.env.PAYLOAD_FRAMEWORK;
|
|
322
|
+
} else {
|
|
323
|
+
process.env.PAYLOAD_FRAMEWORK = originalFrameworkEnv;
|
|
324
|
+
}
|
|
325
|
+
for (const dir of createdDirs){
|
|
326
|
+
rmSync(dir, {
|
|
327
|
+
force: true,
|
|
328
|
+
recursive: true
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
createdDirs.length = 0;
|
|
332
|
+
});
|
|
333
|
+
it('honors PAYLOAD_FRAMEWORK=tanstack-start over auto-detection', ()=>{
|
|
334
|
+
process.env.PAYLOAD_FRAMEWORK = 'tanstack-start';
|
|
335
|
+
const dir = makeProject([
|
|
336
|
+
{
|
|
337
|
+
contents: pkg({
|
|
338
|
+
next: '15.0.0'
|
|
339
|
+
}),
|
|
340
|
+
path: 'package.json'
|
|
341
|
+
}
|
|
342
|
+
]);
|
|
343
|
+
expect(detectFramework(dir)).toBe('tanstack-start');
|
|
344
|
+
});
|
|
345
|
+
it('honors PAYLOAD_FRAMEWORK=next over auto-detection', ()=>{
|
|
346
|
+
process.env.PAYLOAD_FRAMEWORK = 'next';
|
|
347
|
+
const dir = makeProject([
|
|
348
|
+
{
|
|
349
|
+
contents: pkg({
|
|
350
|
+
'@tanstack/react-start': '1.168.26'
|
|
351
|
+
}),
|
|
352
|
+
path: 'package.json'
|
|
353
|
+
}
|
|
354
|
+
]);
|
|
355
|
+
expect(detectFramework(dir)).toBe('next');
|
|
356
|
+
});
|
|
357
|
+
it('throws when PAYLOAD_FRAMEWORK is an unsupported value', ()=>{
|
|
358
|
+
process.env.PAYLOAD_FRAMEWORK = 'svelte';
|
|
359
|
+
const dir = makeProject([
|
|
360
|
+
{
|
|
361
|
+
contents: pkg({
|
|
362
|
+
next: '15.0.0'
|
|
363
|
+
}),
|
|
364
|
+
path: 'package.json'
|
|
365
|
+
}
|
|
366
|
+
]);
|
|
367
|
+
expect(()=>detectFramework(dir)).toThrow(/PAYLOAD_FRAMEWORK/);
|
|
368
|
+
});
|
|
369
|
+
it('detects next from the next dependency', ()=>{
|
|
370
|
+
const dir = makeProject([
|
|
371
|
+
{
|
|
372
|
+
contents: pkg({
|
|
373
|
+
next: '15.0.0'
|
|
374
|
+
}),
|
|
375
|
+
path: 'package.json'
|
|
376
|
+
}
|
|
377
|
+
]);
|
|
378
|
+
expect(detectFramework(dir)).toBe('next');
|
|
379
|
+
});
|
|
380
|
+
it('detects tanstack-start from the @tanstack/react-start dependency', ()=>{
|
|
381
|
+
const dir = makeProject([
|
|
382
|
+
{
|
|
383
|
+
contents: pkg({
|
|
384
|
+
'@tanstack/react-start': '1.168.26'
|
|
385
|
+
}),
|
|
386
|
+
path: 'package.json'
|
|
387
|
+
}
|
|
388
|
+
]);
|
|
389
|
+
expect(detectFramework(dir)).toBe('tanstack-start');
|
|
390
|
+
});
|
|
391
|
+
it('falls back to next.config when deps are inconclusive', ()=>{
|
|
392
|
+
const dir = makeProject([
|
|
393
|
+
{
|
|
394
|
+
contents: pkg({}),
|
|
395
|
+
path: 'package.json'
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
path: 'next.config.ts'
|
|
399
|
+
}
|
|
400
|
+
]);
|
|
401
|
+
expect(detectFramework(dir)).toBe('next');
|
|
402
|
+
});
|
|
403
|
+
it('falls back to vite.config when deps are inconclusive', ()=>{
|
|
404
|
+
const dir = makeProject([
|
|
405
|
+
{
|
|
406
|
+
contents: pkg({}),
|
|
407
|
+
path: 'package.json'
|
|
408
|
+
},
|
|
409
|
+
{
|
|
410
|
+
path: 'vite.config.ts'
|
|
411
|
+
}
|
|
412
|
+
]);
|
|
413
|
+
expect(detectFramework(dir)).toBe('tanstack-start');
|
|
414
|
+
});
|
|
415
|
+
it('falls back to the (payload) folder convention', ()=>{
|
|
416
|
+
const dir = makeProject([
|
|
417
|
+
{
|
|
418
|
+
path: 'app/(payload)/admin/page.tsx'
|
|
419
|
+
}
|
|
420
|
+
]);
|
|
421
|
+
expect(detectFramework(dir)).toBe('next');
|
|
422
|
+
});
|
|
423
|
+
it('falls back to the _payload folder convention', ()=>{
|
|
424
|
+
const dir = makeProject([
|
|
425
|
+
{
|
|
426
|
+
path: 'app/_payload/route.tsx'
|
|
427
|
+
}
|
|
428
|
+
]);
|
|
429
|
+
expect(detectFramework(dir)).toBe('tanstack-start');
|
|
430
|
+
});
|
|
431
|
+
it('resolves ambiguous deps using the config-file layer', ()=>{
|
|
432
|
+
const dir = makeProject([
|
|
433
|
+
{
|
|
434
|
+
contents: pkg({
|
|
435
|
+
'@tanstack/react-start': '1.168.26',
|
|
436
|
+
next: '15.0.0'
|
|
437
|
+
}),
|
|
438
|
+
path: 'package.json'
|
|
439
|
+
},
|
|
440
|
+
{
|
|
441
|
+
path: 'next.config.ts'
|
|
442
|
+
}
|
|
443
|
+
]);
|
|
444
|
+
expect(detectFramework(dir)).toBe('next');
|
|
445
|
+
});
|
|
446
|
+
it('resolves ambiguous deps to tanstack-start via the config-file layer', ()=>{
|
|
447
|
+
const dir = makeProject([
|
|
448
|
+
{
|
|
449
|
+
contents: pkg({
|
|
450
|
+
'@tanstack/react-start': '1.168.26',
|
|
451
|
+
next: '15.0.0'
|
|
452
|
+
}),
|
|
453
|
+
path: 'package.json'
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
path: 'vite.config.ts'
|
|
457
|
+
}
|
|
458
|
+
]);
|
|
459
|
+
expect(detectFramework(dir)).toBe('tanstack-start');
|
|
460
|
+
});
|
|
461
|
+
it('resolves ambiguous deps and configs via the folder-convention layer', ()=>{
|
|
462
|
+
const dir = makeProject([
|
|
463
|
+
{
|
|
464
|
+
contents: pkg({
|
|
465
|
+
'@tanstack/react-start': '1.168.26',
|
|
466
|
+
next: '15.0.0'
|
|
467
|
+
}),
|
|
468
|
+
path: 'package.json'
|
|
469
|
+
},
|
|
470
|
+
{
|
|
471
|
+
path: 'app/_payload/route.tsx'
|
|
472
|
+
}
|
|
473
|
+
]);
|
|
474
|
+
expect(detectFramework(dir)).toBe('tanstack-start');
|
|
475
|
+
});
|
|
476
|
+
it('throws a no-framework error when nothing is detected', ()=>{
|
|
477
|
+
const dir = makeProject([
|
|
478
|
+
{
|
|
479
|
+
contents: pkg({}),
|
|
480
|
+
path: 'package.json'
|
|
481
|
+
}
|
|
482
|
+
]);
|
|
483
|
+
expect(()=>detectFramework(dir)).toThrow(/Could not determine your framework/);
|
|
484
|
+
});
|
|
485
|
+
it('throws a conflict error when signals stay ambiguous', ()=>{
|
|
486
|
+
const dir = makeProject([
|
|
487
|
+
{
|
|
488
|
+
contents: pkg({
|
|
489
|
+
'@tanstack/react-start': '1.168.26',
|
|
490
|
+
next: '15.0.0'
|
|
491
|
+
}),
|
|
492
|
+
path: 'package.json'
|
|
493
|
+
},
|
|
494
|
+
{
|
|
495
|
+
path: 'next.config.ts'
|
|
496
|
+
},
|
|
497
|
+
{
|
|
498
|
+
path: 'vite.config.ts'
|
|
499
|
+
}
|
|
500
|
+
]);
|
|
501
|
+
expect(()=>detectFramework(dir)).toThrow(/conflicting signals/);
|
|
502
|
+
});
|
|
168
503
|
});
|
|
169
504
|
|
|
170
505
|
//# sourceMappingURL=build.spec.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/bin/build.spec.ts"],"sourcesContent":["import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest'\n\n// Default fake child auto-fires `exit(0)` synchronously so ordering/generation\n// tests resolve. Specific tests override via `mockReturnValueOnce` to drive the\n// exit/error handlers manually.\nconst spawnMock = vi.fn(() => ({\n on(event: string, cb: (arg?: never) => void) {\n if (event === 'exit') {\n cb(0 as never)\n }\n return this\n },\n}))\nconst generateImportMapMock = vi.fn(async () => {})\nconst generateTypesMock = vi.fn(async () => {})\n\nvi.mock('node:child_process', () => ({ spawn: spawnMock }))\nvi.mock('./generateImportMap/index.js', () => ({ generateImportMap: generateImportMapMock }))\nvi.mock('./generateTypes.js', () => ({ generateTypes: generateTypesMock }))\n\n// Imported after mocks are registered\nconst { build, getForwardedArgs, resolveNextBin } = await import('./build.js')\n\nconst fakeConfig = {} as never\n\ndescribe('getForwardedArgs', () => {\n it('returns args after the build token and strips --no-types', () => {\n expect(getForwardedArgs(['build', '--turbopack', '--no-types', 'foo'])).toEqual([\n '--turbopack',\n 'foo',\n ])\n })\n\n it('returns empty array when only build is present', () => {\n expect(getForwardedArgs(['build'])).toEqual([])\n })\n})\n\ndescribe('resolveNextBin', () => {\n it('resolves next bin from the current project', () => {\n // next is installed at the repo root; resolving from cwd must succeed\n const binPath = resolveNextBin(process.cwd())\n expect(binPath).toMatch(/next[\\\\/].*bin[\\\\/]next$/)\n })\n\n it('throws a clear error when next cannot be resolved', () => {\n expect(() => resolveNextBin('/nonexistent-project-root')).toThrow(/next/i)\n })\n})\n\ndescribe('build', () => {\n let exitMock: ReturnType<typeof vi.spyOn>\n let originalArgv: string[]\n\n beforeEach(() => {\n spawnMock.mockClear()\n generateImportMapMock.mockClear()\n generateTypesMock.mockClear()\n originalArgv = process.argv\n process.argv = ['node', 'payload', 'build']\n exitMock = vi.spyOn(process, 'exit').mockImplementation((() => undefined) as never)\n })\n\n afterEach(() => {\n process.argv = originalArgv\n exitMock.mockRestore()\n })\n\n it('generates the import map before spawning, and generates types by default', async () => {\n await build({ config: fakeConfig })\n\n expect(generateImportMapMock).toHaveBeenCalledTimes(1)\n expect(generateTypesMock).toHaveBeenCalledTimes(1)\n expect(spawnMock).toHaveBeenCalledTimes(1)\n expect(generateImportMapMock.mock.invocationCallOrder[0]).toBeLessThan(\n spawnMock.mock.invocationCallOrder[0],\n )\n })\n\n it('skips type generation with --no-types', async () => {\n process.argv = ['node', 'payload', 'build', '--no-types']\n\n await build({ config: fakeConfig })\n\n expect(generateImportMapMock).toHaveBeenCalledTimes(1)\n expect(generateTypesMock).not.toHaveBeenCalled()\n expect(spawnMock).toHaveBeenCalledTimes(1)\n })\n\n it('exits 1 and does not spawn when generation fails', async () => {\n generateImportMapMock.mockRejectedValueOnce(new Error('boom'))\n\n await build({ config: fakeConfig })\n\n expect(exitMock).toHaveBeenCalledWith(1)\n expect(spawnMock).not.toHaveBeenCalled()\n })\n\n it('spawns next build with forwarded args and propagates the child exit code', async () => {\n process.argv = ['node', 'payload', 'build', '--turbopack']\n let exitCb: ((code: number | null) => void) | undefined\n spawnMock.mockReturnValueOnce({\n on(event: string, cb: (code: number | null) => void) {\n if (event === 'exit') {\n exitCb = cb\n }\n return this\n },\n })\n\n const buildPromise = build({ config: fakeConfig })\n\n // generation awaits before spawn; let those microtasks settle\n await vi.waitFor(() => expect(spawnMock).toHaveBeenCalledTimes(1))\n const [execPath, spawnArgs, opts] = spawnMock.mock.calls[0]\n expect(execPath).toBe(process.execPath)\n expect(spawnArgs[1]).toBe('build')\n expect(spawnArgs).toContain('--turbopack')\n expect(opts).toEqual({ stdio: 'inherit' })\n\n // Simulate the child exiting with a non-zero code\n exitCb?.(2)\n await buildPromise\n expect(exitMock).toHaveBeenCalledWith(2)\n })\n\n it('does not exit until the spawned child exits, then propagates its code', async () => {\n let exitCb: ((code: number | null) => void) | undefined\n spawnMock.mockReturnValueOnce({\n on(event: string, cb: (code: number | null) => void) {\n if (event === 'exit') {\n exitCb = cb\n }\n return this\n },\n })\n\n let resolved = false\n const buildPromise = build({ config: fakeConfig }).then(() => {\n resolved = true\n })\n\n // Wait for generation to settle and the child to be spawned. build() must\n // still be pending because the child has not exited yet.\n await vi.waitFor(() => expect(exitCb).toBeDefined())\n // Flush all pending microtasks; the OLD (buggy) build() resolved here\n // without awaiting the child, so this assertion catches the race.\n await new Promise((r) => setTimeout(r, 0))\n expect(resolved).toBe(false)\n expect(exitMock).not.toHaveBeenCalled()\n\n // Child exits non-zero -> build() must exit with that exact code\n exitCb?.(3)\n await buildPromise\n expect(resolved).toBe(true)\n expect(exitMock).toHaveBeenCalledWith(3)\n })\n})\n"],"names":["describe","expect","it","vi","beforeEach","afterEach","spawnMock","fn","on","event","cb","generateImportMapMock","generateTypesMock","mock","spawn","generateImportMap","generateTypes","build","getForwardedArgs","resolveNextBin","fakeConfig","toEqual","binPath","process","cwd","toMatch","toThrow","exitMock","originalArgv","mockClear","argv","spyOn","mockImplementation","undefined","mockRestore","config","toHaveBeenCalledTimes","invocationCallOrder","toBeLessThan","not","toHaveBeenCalled","mockRejectedValueOnce","Error","toHaveBeenCalledWith","exitCb","mockReturnValueOnce","buildPromise","waitFor","execPath","spawnArgs","opts","calls","toBe","toContain","stdio","resolved","then","toBeDefined","Promise","r","setTimeout"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/bin/build.spec.ts"],"sourcesContent":["import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\n\nimport { describe, expect, it, vi, beforeEach, afterEach } from 'vitest'\n\n// Default fake child auto-fires `exit(0)` synchronously so ordering/generation\n// tests resolve. Specific tests override via `mockReturnValueOnce` to drive the\n// exit/error handlers manually.\nconst spawnMock = vi.fn(() => ({\n on(event: string, cb: (arg?: never) => void) {\n if (event === 'exit') {\n cb(0 as never)\n }\n return this\n },\n}))\nconst generateImportMapMock = vi.fn(async () => {})\nconst generateTypesMock = vi.fn(async () => {})\n\nvi.mock('node:child_process', () => ({ spawn: spawnMock }))\nvi.mock('./generateImportMap/index.js', () => ({ generateImportMap: generateImportMapMock }))\nvi.mock('./generateTypes.js', () => ({ generateTypes: generateTypesMock }))\n\n// Imported after mocks are registered\nconst {\n build,\n detectFramework,\n getForwardedArgs,\n resolveBuildCommand,\n resolveNextBin,\n resolveViteBin,\n} = await import('./build.js')\n\nconst fakeConfig = {} as never\n\ndescribe('getForwardedArgs', () => {\n it('returns args after the build token and strips --no-types', () => {\n expect(getForwardedArgs(['build', '--turbopack', '--no-types', 'foo'])).toEqual([\n '--turbopack',\n 'foo',\n ])\n })\n\n it('returns empty array when only build is present', () => {\n expect(getForwardedArgs(['build'])).toEqual([])\n })\n})\n\ndescribe('resolveNextBin', () => {\n it('resolves next bin from the current project', () => {\n // next is installed at the repo root; resolving from cwd must succeed\n const binPath = resolveNextBin(process.cwd())\n expect(binPath).toMatch(/next[\\\\/].*bin[\\\\/]next$/)\n })\n\n it('throws a clear error when next cannot be resolved', () => {\n expect(() => resolveNextBin('/nonexistent-project-root')).toThrow(/next/i)\n })\n})\n\ndescribe('resolveViteBin', () => {\n it('resolves the vite bin from the current project', () => {\n // vite is installed at the repo root; resolving from cwd must succeed\n const binPath = resolveViteBin(process.cwd())\n expect(binPath).toMatch(/vite[\\\\/].*bin[\\\\/]vite\\.js$/)\n })\n\n it('throws a clear error when vite cannot be resolved', async () => {\n // Vitest injects its own transitive `vite` dep onto NODE_PATH, so resolving\n // \"vite\" from any cwd would otherwise succeed in this test process even\n // when the project under test has no vite installed. Mock module\n // resolution itself to simulate a real \"vite not installed\" project.\n vi.resetModules()\n vi.doMock('node:module', async (importOriginal) => {\n const actual = await importOriginal<typeof import('node:module')>()\n return {\n ...actual,\n createRequire: () => ({\n resolve: () => {\n throw new Error('Cannot find module')\n },\n }),\n }\n })\n\n const { resolveViteBin: resolveViteBinWithoutVite } = await import('./build.js')\n expect(() => resolveViteBinWithoutVite('/nonexistent-project-root')).toThrow(/vite/i)\n\n vi.doUnmock('node:module')\n vi.resetModules()\n })\n})\n\ndescribe('resolveBuildCommand', () => {\n it('maps next to the next bin and build args', () => {\n const { args, bin } = resolveBuildCommand({\n cwd: process.cwd(),\n forwardedArgs: ['--turbopack'],\n framework: 'next',\n })\n expect(bin).toMatch(/next[\\\\/].*bin[\\\\/]next$/)\n expect(args).toEqual(['build', '--turbopack'])\n })\n\n it('maps tanstack-start to the vite bin and build args', () => {\n const { args, bin } = resolveBuildCommand({\n cwd: process.cwd(),\n forwardedArgs: ['--mode', 'staging'],\n framework: 'tanstack-start',\n })\n expect(bin).toMatch(/vite[\\\\/].*bin[\\\\/]vite\\.js$/)\n expect(args).toEqual(['build', '--mode', 'staging'])\n })\n})\n\ndescribe('build', () => {\n let exitMock: ReturnType<typeof vi.spyOn>\n let originalArgv: string[]\n let originalFrameworkEnv: string | undefined\n let cwdSpy: ReturnType<typeof vi.spyOn> | undefined\n const buildTempDirs: string[] = []\n\n beforeEach(() => {\n spawnMock.mockClear()\n generateImportMapMock.mockClear()\n generateTypesMock.mockClear()\n originalArgv = process.argv\n process.argv = ['node', 'payload', 'build']\n exitMock = vi.spyOn(process, 'exit').mockImplementation((() => undefined) as never)\n originalFrameworkEnv = process.env.PAYLOAD_FRAMEWORK\n // Force next for the legacy tests so they don't depend on the repo-root\n // package.json's ambient `next` dependency for auto-detection.\n process.env.PAYLOAD_FRAMEWORK = 'next'\n })\n\n afterEach(() => {\n process.argv = originalArgv\n exitMock.mockRestore()\n if (originalFrameworkEnv === undefined) {\n delete process.env.PAYLOAD_FRAMEWORK\n } else {\n process.env.PAYLOAD_FRAMEWORK = originalFrameworkEnv\n }\n if (cwdSpy) {\n cwdSpy.mockRestore()\n cwdSpy = undefined\n }\n for (const dir of buildTempDirs) {\n rmSync(dir, { force: true, recursive: true })\n }\n buildTempDirs.length = 0\n })\n\n it('generates the import map before spawning, and generates types by default', async () => {\n await build({ config: fakeConfig })\n\n expect(generateImportMapMock).toHaveBeenCalledTimes(1)\n expect(generateTypesMock).toHaveBeenCalledTimes(1)\n expect(spawnMock).toHaveBeenCalledTimes(1)\n expect(generateImportMapMock.mock.invocationCallOrder[0]).toBeLessThan(\n spawnMock.mock.invocationCallOrder[0],\n )\n })\n\n it('skips type generation with --no-types', async () => {\n process.argv = ['node', 'payload', 'build', '--no-types']\n\n await build({ config: fakeConfig })\n\n expect(generateImportMapMock).toHaveBeenCalledTimes(1)\n expect(generateTypesMock).not.toHaveBeenCalled()\n expect(spawnMock).toHaveBeenCalledTimes(1)\n })\n\n it('exits 1 and does not spawn when generation fails', async () => {\n generateImportMapMock.mockRejectedValueOnce(new Error('boom'))\n\n await build({ config: fakeConfig })\n\n expect(exitMock).toHaveBeenCalledWith(1)\n expect(spawnMock).not.toHaveBeenCalled()\n })\n\n it('spawns next build with forwarded args and propagates the child exit code', async () => {\n process.argv = ['node', 'payload', 'build', '--turbopack']\n let exitCb: ((code: number | null) => void) | undefined\n spawnMock.mockReturnValueOnce({\n on(event: string, cb: (code: number | null) => void) {\n if (event === 'exit') {\n exitCb = cb\n }\n return this\n },\n })\n\n const buildPromise = build({ config: fakeConfig })\n\n // generation awaits before spawn; let those microtasks settle\n await vi.waitFor(() => expect(spawnMock).toHaveBeenCalledTimes(1))\n const [execPath, spawnArgs, opts] = spawnMock.mock.calls[0]\n expect(execPath).toBe(process.execPath)\n expect(spawnArgs[1]).toBe('build')\n expect(spawnArgs).toContain('--turbopack')\n expect(opts).toEqual({ stdio: 'inherit' })\n\n // Simulate the child exiting with a non-zero code\n exitCb?.(2)\n await buildPromise\n expect(exitMock).toHaveBeenCalledWith(2)\n })\n\n it('does not exit until the spawned child exits, then propagates its code', async () => {\n let exitCb: ((code: number | null) => void) | undefined\n spawnMock.mockReturnValueOnce({\n on(event: string, cb: (code: number | null) => void) {\n if (event === 'exit') {\n exitCb = cb\n }\n return this\n },\n })\n\n let resolved = false\n const buildPromise = build({ config: fakeConfig }).then(() => {\n resolved = true\n })\n\n // Wait for generation to settle and the child to be spawned. build() must\n // still be pending because the child has not exited yet.\n await vi.waitFor(() => expect(exitCb).toBeDefined())\n // Flush all pending microtasks; the OLD (buggy) build() resolved here\n // without awaiting the child, so this assertion catches the race.\n await new Promise((r) => setTimeout(r, 0))\n expect(resolved).toBe(false)\n expect(exitMock).not.toHaveBeenCalled()\n\n // Child exits non-zero -> build() must exit with that exact code\n exitCb?.(3)\n await buildPromise\n expect(resolved).toBe(true)\n expect(exitMock).toHaveBeenCalledWith(3)\n })\n\n it('spawns vite build for a detected tanstack project', async () => {\n delete process.env.PAYLOAD_FRAMEWORK\n process.argv = ['node', 'payload', 'build', '--mode', 'staging']\n const tanstackDir = mkdtempSync(path.join(os.tmpdir(), 'payload-build-ts-'))\n buildTempDirs.push(tanstackDir)\n writeFileSync(\n path.join(tanstackDir, 'package.json'),\n JSON.stringify({ dependencies: { '@tanstack/react-start': '1.168.26' } }),\n )\n cwdSpy = vi.spyOn(process, 'cwd').mockReturnValue(tanstackDir)\n\n await build({ config: fakeConfig })\n\n expect(spawnMock).toHaveBeenCalledTimes(1)\n const [, spawnArgs] = spawnMock.mock.calls[0]\n expect(spawnArgs[0]).toMatch(/vite[\\\\/].*bin[\\\\/]vite\\.js$/)\n expect(spawnArgs.slice(1)).toEqual(['build', '--mode', 'staging'])\n })\n\n it('exits 1 and does not spawn when the framework cannot be detected', async () => {\n delete process.env.PAYLOAD_FRAMEWORK\n const emptyDir = mkdtempSync(path.join(os.tmpdir(), 'payload-build-empty-'))\n buildTempDirs.push(emptyDir)\n writeFileSync(path.join(emptyDir, 'package.json'), JSON.stringify({}))\n cwdSpy = vi.spyOn(process, 'cwd').mockReturnValue(emptyDir)\n\n await build({ config: fakeConfig })\n\n expect(exitMock).toHaveBeenCalledWith(1)\n expect(spawnMock).not.toHaveBeenCalled()\n })\n})\n\ndescribe('detectFramework', () => {\n const createdDirs: string[] = []\n let originalFrameworkEnv: string | undefined\n\n const makeProject = (files: { contents?: string; path: string }[]): string => {\n const dir = mkdtempSync(path.join(os.tmpdir(), 'payload-build-'))\n createdDirs.push(dir)\n for (const file of files) {\n const full = path.join(dir, file.path)\n mkdirSync(path.dirname(full), { recursive: true })\n writeFileSync(full, file.contents ?? '')\n }\n return dir\n }\n\n const pkg = (deps: Record<string, string>): string => JSON.stringify({ dependencies: deps })\n\n beforeEach(() => {\n originalFrameworkEnv = process.env.PAYLOAD_FRAMEWORK\n delete process.env.PAYLOAD_FRAMEWORK\n })\n\n afterEach(() => {\n if (originalFrameworkEnv === undefined) {\n delete process.env.PAYLOAD_FRAMEWORK\n } else {\n process.env.PAYLOAD_FRAMEWORK = originalFrameworkEnv\n }\n for (const dir of createdDirs) {\n rmSync(dir, { force: true, recursive: true })\n }\n createdDirs.length = 0\n })\n\n it('honors PAYLOAD_FRAMEWORK=tanstack-start over auto-detection', () => {\n process.env.PAYLOAD_FRAMEWORK = 'tanstack-start'\n const dir = makeProject([{ contents: pkg({ next: '15.0.0' }), path: 'package.json' }])\n expect(detectFramework(dir)).toBe('tanstack-start')\n })\n\n it('honors PAYLOAD_FRAMEWORK=next over auto-detection', () => {\n process.env.PAYLOAD_FRAMEWORK = 'next'\n const dir = makeProject([\n { contents: pkg({ '@tanstack/react-start': '1.168.26' }), path: 'package.json' },\n ])\n expect(detectFramework(dir)).toBe('next')\n })\n\n it('throws when PAYLOAD_FRAMEWORK is an unsupported value', () => {\n process.env.PAYLOAD_FRAMEWORK = 'svelte'\n const dir = makeProject([{ contents: pkg({ next: '15.0.0' }), path: 'package.json' }])\n expect(() => detectFramework(dir)).toThrow(/PAYLOAD_FRAMEWORK/)\n })\n\n it('detects next from the next dependency', () => {\n const dir = makeProject([{ contents: pkg({ next: '15.0.0' }), path: 'package.json' }])\n expect(detectFramework(dir)).toBe('next')\n })\n\n it('detects tanstack-start from the @tanstack/react-start dependency', () => {\n const dir = makeProject([\n { contents: pkg({ '@tanstack/react-start': '1.168.26' }), path: 'package.json' },\n ])\n expect(detectFramework(dir)).toBe('tanstack-start')\n })\n\n it('falls back to next.config when deps are inconclusive', () => {\n const dir = makeProject([\n { contents: pkg({}), path: 'package.json' },\n { path: 'next.config.ts' },\n ])\n expect(detectFramework(dir)).toBe('next')\n })\n\n it('falls back to vite.config when deps are inconclusive', () => {\n const dir = makeProject([\n { contents: pkg({}), path: 'package.json' },\n { path: 'vite.config.ts' },\n ])\n expect(detectFramework(dir)).toBe('tanstack-start')\n })\n\n it('falls back to the (payload) folder convention', () => {\n const dir = makeProject([{ path: 'app/(payload)/admin/page.tsx' }])\n expect(detectFramework(dir)).toBe('next')\n })\n\n it('falls back to the _payload folder convention', () => {\n const dir = makeProject([{ path: 'app/_payload/route.tsx' }])\n expect(detectFramework(dir)).toBe('tanstack-start')\n })\n\n it('resolves ambiguous deps using the config-file layer', () => {\n const dir = makeProject([\n {\n contents: pkg({ '@tanstack/react-start': '1.168.26', next: '15.0.0' }),\n path: 'package.json',\n },\n { path: 'next.config.ts' },\n ])\n expect(detectFramework(dir)).toBe('next')\n })\n\n it('resolves ambiguous deps to tanstack-start via the config-file layer', () => {\n const dir = makeProject([\n {\n contents: pkg({ '@tanstack/react-start': '1.168.26', next: '15.0.0' }),\n path: 'package.json',\n },\n { path: 'vite.config.ts' },\n ])\n expect(detectFramework(dir)).toBe('tanstack-start')\n })\n\n it('resolves ambiguous deps and configs via the folder-convention layer', () => {\n const dir = makeProject([\n {\n contents: pkg({ '@tanstack/react-start': '1.168.26', next: '15.0.0' }),\n path: 'package.json',\n },\n { path: 'app/_payload/route.tsx' },\n ])\n expect(detectFramework(dir)).toBe('tanstack-start')\n })\n\n it('throws a no-framework error when nothing is detected', () => {\n const dir = makeProject([{ contents: pkg({}), path: 'package.json' }])\n expect(() => detectFramework(dir)).toThrow(/Could not determine your framework/)\n })\n\n it('throws a conflict error when signals stay ambiguous', () => {\n const dir = makeProject([\n {\n contents: pkg({ '@tanstack/react-start': '1.168.26', next: '15.0.0' }),\n path: 'package.json',\n },\n { path: 'next.config.ts' },\n { path: 'vite.config.ts' },\n ])\n expect(() => detectFramework(dir)).toThrow(/conflicting signals/)\n })\n})\n"],"names":["mkdirSync","mkdtempSync","rmSync","writeFileSync","os","path","describe","expect","it","vi","beforeEach","afterEach","spawnMock","fn","on","event","cb","generateImportMapMock","generateTypesMock","mock","spawn","generateImportMap","generateTypes","build","detectFramework","getForwardedArgs","resolveBuildCommand","resolveNextBin","resolveViteBin","fakeConfig","toEqual","binPath","process","cwd","toMatch","toThrow","resetModules","doMock","importOriginal","actual","createRequire","resolve","Error","resolveViteBinWithoutVite","doUnmock","args","bin","forwardedArgs","framework","exitMock","originalArgv","originalFrameworkEnv","cwdSpy","buildTempDirs","mockClear","argv","spyOn","mockImplementation","undefined","env","PAYLOAD_FRAMEWORK","mockRestore","dir","force","recursive","length","config","toHaveBeenCalledTimes","invocationCallOrder","toBeLessThan","not","toHaveBeenCalled","mockRejectedValueOnce","toHaveBeenCalledWith","exitCb","mockReturnValueOnce","buildPromise","waitFor","execPath","spawnArgs","opts","calls","toBe","toContain","stdio","resolved","then","toBeDefined","Promise","r","setTimeout","tanstackDir","join","tmpdir","push","JSON","stringify","dependencies","mockReturnValue","slice","emptyDir","createdDirs","makeProject","files","file","full","dirname","contents","pkg","deps","next"],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Folder-name markers that distinguish the supported framework conventions.
|
|
3
|
+
* Shared between import-map resolution and `payload build` framework detection so
|
|
4
|
+
* the two cannot drift.
|
|
5
|
+
*/
|
|
6
|
+
export declare const NEXT_PAYLOAD_ROUTE_GROUP = "(payload)";
|
|
7
|
+
export declare const TANSTACK_PAYLOAD_DIR = "_payload";
|
|
8
|
+
//# sourceMappingURL=frameworkConventions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frameworkConventions.d.ts","sourceRoot":"","sources":["../../src/bin/frameworkConventions.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,cAAc,CAAA;AACnD,eAAO,MAAM,oBAAoB,aAAa,CAAA"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Folder-name markers that distinguish the supported framework conventions.
|
|
3
|
+
* Shared between import-map resolution and `payload build` framework detection so
|
|
4
|
+
* the two cannot drift.
|
|
5
|
+
*/ export const NEXT_PAYLOAD_ROUTE_GROUP = '(payload)';
|
|
6
|
+
export const TANSTACK_PAYLOAD_DIR = '_payload';
|
|
7
|
+
|
|
8
|
+
//# sourceMappingURL=frameworkConventions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/bin/frameworkConventions.ts"],"sourcesContent":["/**\n * Folder-name markers that distinguish the supported framework conventions.\n * Shared between import-map resolution and `payload build` framework detection so\n * the two cannot drift.\n */\nexport const NEXT_PAYLOAD_ROUTE_GROUP = '(payload)'\nexport const TANSTACK_PAYLOAD_DIR = '_payload'\n"],"names":["NEXT_PAYLOAD_ROUTE_GROUP","TANSTACK_PAYLOAD_DIR"],"mappings":"AAAA;;;;CAIC,GACD,OAAO,MAAMA,2BAA2B,YAAW;AACnD,OAAO,MAAMC,uBAAuB,WAAU"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolveImportMapFilePath.d.ts","sourceRoot":"","sources":["../../../../src/bin/generateImportMap/utilities/resolveImportMapFilePath.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"resolveImportMapFilePath.d.ts","sourceRoot":"","sources":["../../../../src/bin/generateImportMap/utilities/resolveImportMapFilePath.ts"],"names":[],"mappings":"AA+BA;;;;;GAKG;AACH,wBAAsB,wBAAwB,CAAC,EAC7C,UAAqB,EACrB,oBAAoB,EACpB,aAAa,EACb,OAAO,GACR,EAAE;IACD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;CAChB,GAAG,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,CAkC1B"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs from 'fs/promises';
|
|
2
2
|
import path from 'path';
|
|
3
|
+
import { NEXT_PAYLOAD_ROUTE_GROUP, TANSTACK_PAYLOAD_DIR } from '../../frameworkConventions.js';
|
|
3
4
|
async function pathOrFileExists(path) {
|
|
4
5
|
try {
|
|
5
6
|
await fs.access(path);
|
|
@@ -17,11 +18,11 @@ async function pathOrFileExists(path) {
|
|
|
17
18
|
* Adapters with a bespoke layout can still bypass this via `candidateDirectories`.
|
|
18
19
|
*/ const defaultCandidateDirectories = (rootDir, adminRoute)=>[
|
|
19
20
|
// Next.js App Router: `(payload)` route group nested under the admin route
|
|
20
|
-
path.resolve(rootDir, `app
|
|
21
|
-
path.resolve(rootDir, `src/app
|
|
21
|
+
path.resolve(rootDir, `app/${NEXT_PAYLOAD_ROUTE_GROUP}${adminRoute}/`),
|
|
22
|
+
path.resolve(rootDir, `src/app/${NEXT_PAYLOAD_ROUTE_GROUP}${adminRoute}/`),
|
|
22
23
|
// TanStack Start: `_payload` pathless route folder at the app root
|
|
23
|
-
path.resolve(rootDir, `app
|
|
24
|
-
path.resolve(rootDir, `src/app
|
|
24
|
+
path.resolve(rootDir, `app/${TANSTACK_PAYLOAD_DIR}/`),
|
|
25
|
+
path.resolve(rootDir, `src/app/${TANSTACK_PAYLOAD_DIR}/`)
|
|
25
26
|
];
|
|
26
27
|
/**
|
|
27
28
|
* Returns the path to the import map file. If the import map file is not found, it throws an error.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/bin/generateImportMap/utilities/resolveImportMapFilePath.ts"],"sourcesContent":["import fs from 'fs/promises'\nimport path from 'path'\n\nasync function pathOrFileExists(path: string): Promise<boolean> {\n try {\n await fs.access(path)\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Default directory patterns for import map resolution, covering the supported\n * framework conventions. Directories are probed in order and the first existing\n * one wins; the conventions are mutually exclusive in practice, so a Next.js app\n * never matches the TanStack patterns and vice versa.\n *\n * Adapters with a bespoke layout can still bypass this via `candidateDirectories`.\n */\nconst defaultCandidateDirectories = (rootDir: string, adminRoute: string): string[] => [\n // Next.js App Router: `(payload)` route group nested under the admin route\n path.resolve(rootDir, `app
|
|
1
|
+
{"version":3,"sources":["../../../../src/bin/generateImportMap/utilities/resolveImportMapFilePath.ts"],"sourcesContent":["import fs from 'fs/promises'\nimport path from 'path'\n\nimport { NEXT_PAYLOAD_ROUTE_GROUP, TANSTACK_PAYLOAD_DIR } from '../../frameworkConventions.js'\n\nasync function pathOrFileExists(path: string): Promise<boolean> {\n try {\n await fs.access(path)\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Default directory patterns for import map resolution, covering the supported\n * framework conventions. Directories are probed in order and the first existing\n * one wins; the conventions are mutually exclusive in practice, so a Next.js app\n * never matches the TanStack patterns and vice versa.\n *\n * Adapters with a bespoke layout can still bypass this via `candidateDirectories`.\n */\nconst defaultCandidateDirectories = (rootDir: string, adminRoute: string): string[] => [\n // Next.js App Router: `(payload)` route group nested under the admin route\n path.resolve(rootDir, `app/${NEXT_PAYLOAD_ROUTE_GROUP}${adminRoute}/`),\n path.resolve(rootDir, `src/app/${NEXT_PAYLOAD_ROUTE_GROUP}${adminRoute}/`),\n // TanStack Start: `_payload` pathless route folder at the app root\n path.resolve(rootDir, `app/${TANSTACK_PAYLOAD_DIR}/`),\n path.resolve(rootDir, `src/app/${TANSTACK_PAYLOAD_DIR}/`),\n]\n\n/**\n * Returns the path to the import map file. If the import map file is not found, it throws an error.\n *\n * @param candidateDirectories - Optional array of directory paths to search for the import map.\n * Defaults to Next.js app directory convention. Framework adapters can provide their own.\n */\nexport async function resolveImportMapFilePath({\n adminRoute = '/admin',\n candidateDirectories,\n importMapFile,\n rootDir,\n}: {\n adminRoute?: string\n candidateDirectories?: string[]\n importMapFile?: string\n rootDir: string\n}): Promise<Error | string> {\n let importMapFilePath: string | undefined = undefined\n\n if (importMapFile?.length) {\n if (!(await pathOrFileExists(importMapFile))) {\n try {\n await fs.writeFile(importMapFile, '', { flag: 'wx' })\n } catch (err) {\n return new Error(\n `Could not find the import map file at ${importMapFile}${err instanceof Error && err?.message ? `: ${err.message}` : ''}`,\n )\n }\n }\n importMapFilePath = importMapFile\n } else {\n const directories = candidateDirectories ?? defaultCandidateDirectories(rootDir, adminRoute)\n\n for (const dir of directories) {\n if (await pathOrFileExists(dir)) {\n importMapFilePath = path.resolve(dir, 'importMap.js')\n if (!(await pathOrFileExists(importMapFilePath))) {\n await fs.writeFile(importMapFilePath, '', { flag: 'wx' })\n }\n break\n }\n }\n\n if (!importMapFilePath) {\n return new Error(\n `Could not find Payload import map folder. Looked in ${directories.join(' and ')}`,\n )\n }\n }\n return importMapFilePath\n}\n"],"names":["fs","path","NEXT_PAYLOAD_ROUTE_GROUP","TANSTACK_PAYLOAD_DIR","pathOrFileExists","access","defaultCandidateDirectories","rootDir","adminRoute","resolve","resolveImportMapFilePath","candidateDirectories","importMapFile","importMapFilePath","undefined","length","writeFile","flag","err","Error","message","directories","dir","join"],"mappings":"AAAA,OAAOA,QAAQ,cAAa;AAC5B,OAAOC,UAAU,OAAM;AAEvB,SAASC,wBAAwB,EAAEC,oBAAoB,QAAQ,gCAA+B;AAE9F,eAAeC,iBAAiBH,IAAY;IAC1C,IAAI;QACF,MAAMD,GAAGK,MAAM,CAACJ;QAChB,OAAO;IACT,EAAE,OAAM;QACN,OAAO;IACT;AACF;AAEA;;;;;;;CAOC,GACD,MAAMK,8BAA8B,CAACC,SAAiBC,aAAiC;QACrF,2EAA2E;QAC3EP,KAAKQ,OAAO,CAACF,SAAS,CAAC,IAAI,EAAEL,2BAA2BM,WAAW,CAAC,CAAC;QACrEP,KAAKQ,OAAO,CAACF,SAAS,CAAC,QAAQ,EAAEL,2BAA2BM,WAAW,CAAC,CAAC;QACzE,mEAAmE;QACnEP,KAAKQ,OAAO,CAACF,SAAS,CAAC,IAAI,EAAEJ,qBAAqB,CAAC,CAAC;QACpDF,KAAKQ,OAAO,CAACF,SAAS,CAAC,QAAQ,EAAEJ,qBAAqB,CAAC,CAAC;KACzD;AAED;;;;;CAKC,GACD,OAAO,eAAeO,yBAAyB,EAC7CF,aAAa,QAAQ,EACrBG,oBAAoB,EACpBC,aAAa,EACbL,OAAO,EAMR;IACC,IAAIM,oBAAwCC;IAE5C,IAAIF,eAAeG,QAAQ;QACzB,IAAI,CAAE,MAAMX,iBAAiBQ,gBAAiB;YAC5C,IAAI;gBACF,MAAMZ,GAAGgB,SAAS,CAACJ,eAAe,IAAI;oBAAEK,MAAM;gBAAK;YACrD,EAAE,OAAOC,KAAK;gBACZ,OAAO,IAAIC,MACT,CAAC,sCAAsC,EAAEP,gBAAgBM,eAAeC,SAASD,KAAKE,UAAU,CAAC,EAAE,EAAEF,IAAIE,OAAO,EAAE,GAAG,IAAI;YAE7H;QACF;QACAP,oBAAoBD;IACtB,OAAO;QACL,MAAMS,cAAcV,wBAAwBL,4BAA4BC,SAASC;QAEjF,KAAK,MAAMc,OAAOD,YAAa;YAC7B,IAAI,MAAMjB,iBAAiBkB,MAAM;gBAC/BT,oBAAoBZ,KAAKQ,OAAO,CAACa,KAAK;gBACtC,IAAI,CAAE,MAAMlB,iBAAiBS,oBAAqB;oBAChD,MAAMb,GAAGgB,SAAS,CAACH,mBAAmB,IAAI;wBAAEI,MAAM;oBAAK;gBACzD;gBACA;YACF;QACF;QAEA,IAAI,CAACJ,mBAAmB;YACtB,OAAO,IAAIM,MACT,CAAC,oDAAoD,EAAEE,YAAYE,IAAI,CAAC,UAAU;QAEtF;IACF;IACA,OAAOV;AACT"}
|
package/dist/index.bundled.d.ts
CHANGED
|
@@ -10382,6 +10382,14 @@ type RouterAdapterRouter = {
|
|
|
10382
10382
|
replace: (path: string, options?: {
|
|
10383
10383
|
scroll?: boolean;
|
|
10384
10384
|
}) => void;
|
|
10385
|
+
/**
|
|
10386
|
+
* Use this property to standardize behaviors across different router implementations.
|
|
10387
|
+
* Set it up to sync client state to the URL without triggering a second server load.
|
|
10388
|
+
*
|
|
10389
|
+
* In Next.js, calling `window.history.replaceState` directly is sufficient, as Next.js does not observe history mutations.
|
|
10390
|
+
* In TanStack Router, however, `history.replaceState` is monkeypatched to notify the router of changes.
|
|
10391
|
+
*/
|
|
10392
|
+
replaceState?: (url: string) => void;
|
|
10385
10393
|
};
|
|
10386
10394
|
type LinkAdapterProps = {
|
|
10387
10395
|
children?: React$1.ReactNode;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "payload",
|
|
3
|
-
"version": "4.0.0-internal.
|
|
3
|
+
"version": "4.0.0-internal.e387174",
|
|
4
4
|
"description": "Node, React, Headless CMS and Application Framework built on Next.js",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"admin panel",
|
|
@@ -118,7 +118,7 @@
|
|
|
118
118
|
"undici": "7.28.0",
|
|
119
119
|
"uuid": "14.0.0",
|
|
120
120
|
"ws": "^8.16.0",
|
|
121
|
-
"@payloadcms/translations": "4.0.0-internal.
|
|
121
|
+
"@payloadcms/translations": "4.0.0-internal.e387174"
|
|
122
122
|
},
|
|
123
123
|
"devDependencies": {
|
|
124
124
|
"@hyrious/esbuild-plugin-commonjs": "0.2.6",
|