@payloadcms/tanstack-start 4.0.0-internal.2fddfc0 → 4.0.0-internal.43ccea7
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/LICENSE.md +1 -1
- package/dist/elements/RouterAdapter/index.d.ts.map +1 -1
- package/dist/elements/RouterAdapter/index.js +18 -2
- package/dist/elements/RouterAdapter/index.js.map +1 -1
- package/dist/exports/client.d.ts +1 -0
- package/dist/exports/client.d.ts.map +1 -1
- package/dist/exports/client.js +1 -0
- package/dist/exports/client.js.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -2
- package/dist/index.js.map +1 -1
- package/dist/layouts/Root/getLayoutData.js.map +1 -1
- package/dist/layouts/Root/index.d.ts +2 -2
- package/dist/layouts/Root/index.d.ts.map +1 -1
- package/dist/layouts/Root/index.js.map +1 -1
- package/dist/routes/adminRoutes.d.ts +13 -7
- package/dist/routes/adminRoutes.d.ts.map +1 -1
- package/dist/routes/adminRoutes.js +31 -20
- package/dist/routes/adminRoutes.js.map +1 -1
- package/dist/routes/apiRoute.d.ts +24 -28
- package/dist/routes/apiRoute.d.ts.map +1 -1
- package/dist/routes/apiRoute.js +25 -14
- package/dist/routes/apiRoute.js.map +1 -1
- package/dist/routes/layoutRoute.d.ts +4 -1
- package/dist/routes/layoutRoute.d.ts.map +1 -1
- package/dist/routes/layoutRoute.js +7 -1
- package/dist/routes/layoutRoute.js.map +1 -1
- package/dist/utilities/importMap.server.d.ts +4 -5
- package/dist/utilities/importMap.server.d.ts.map +1 -1
- package/dist/utilities/importMap.server.js +5 -6
- package/dist/utilities/importMap.server.js.map +1 -1
- package/dist/utilities/loadAdminPage.d.ts.map +1 -1
- package/dist/utilities/loadAdminPage.js +13 -0
- package/dist/utilities/loadAdminPage.js.map +1 -1
- package/dist/vite/plugin.d.ts.map +1 -1
- package/dist/vite/plugin.js +1 -3
- package/dist/vite/plugin.js.map +1 -1
- package/dist/vite/plugins/stripDistStyleImports.d.ts.map +1 -1
- package/dist/vite/plugins/stripDistStyleImports.js +37 -4
- package/dist/vite/plugins/stripDistStyleImports.js.map +1 -1
- package/package.json +7 -7
- package/dist/@types/assets.d.js +0 -2
- package/dist/@types/assets.d.js.map +0 -1
package/LICENSE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2018-
|
|
3
|
+
Copyright (c) 2018-2026 Payload CMS, LLC <info@payloadcms.com>
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
6
|
a copy of this software and associated documentation files (the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/elements/RouterAdapter/index.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAoB,sBAAsB,EAAE,MAAM,SAAS,CAAA;AAuDvE,eAAO,MAAM,qBAAqB,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/elements/RouterAdapter/index.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAoB,sBAAsB,EAAE,MAAM,SAAS,CAAA;AAuDvE,eAAO,MAAM,qBAAqB,EAAE,sBAyGnC,CAAA"}
|
|
@@ -102,16 +102,32 @@ export const TanStackRouterAdapter = ({ children })=>{
|
|
|
102
102
|
router,
|
|
103
103
|
toNavOptions
|
|
104
104
|
]);
|
|
105
|
+
// Mirror Next.js' router behavior to allow syncing client state to the URL without triggering a second server load.
|
|
106
|
+
// TanStack's browser history monkeypatches `window.history.replaceState` and notifies `router.load` on every call.
|
|
107
|
+
// Use `_ignoreSubscribers` to suppresses that notification — the same flag TanStack uses internally when flushing history.
|
|
108
|
+
const replaceState = useCallback((url)=>{
|
|
109
|
+
const { history } = router;
|
|
110
|
+
history._ignoreSubscribers = true;
|
|
111
|
+
try {
|
|
112
|
+
window.history.replaceState(null, '', url);
|
|
113
|
+
} finally{
|
|
114
|
+
history._ignoreSubscribers = false;
|
|
115
|
+
}
|
|
116
|
+
}, [
|
|
117
|
+
router
|
|
118
|
+
]);
|
|
105
119
|
const adaptedRouter = useMemo(()=>({
|
|
106
120
|
back,
|
|
107
121
|
push,
|
|
108
122
|
refresh,
|
|
109
|
-
replace
|
|
123
|
+
replace,
|
|
124
|
+
replaceState
|
|
110
125
|
}), [
|
|
111
126
|
back,
|
|
112
127
|
push,
|
|
113
128
|
refresh,
|
|
114
|
-
replace
|
|
129
|
+
replace,
|
|
130
|
+
replaceState
|
|
115
131
|
]);
|
|
116
132
|
// `location.searchStr` is the serialized query string; `location.search` is
|
|
117
133
|
// the parsed object (a nested structure once the router uses `qs` for search
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/elements/RouterAdapter/index.tsx"],"sourcesContent":["'use client'\n\nimport type { RouterAdapterContextValue } from '@payloadcms/ui'\nimport type { LinkAdapterProps, RouterAdapterComponent } from 'payload'\n\nimport { RouterAdapterContext } from '@payloadcms/ui'\nimport { Link as TanStackLink, useLocation, useParams, useRouter } from '@tanstack/react-router'\nimport * as qs from 'qs-esm'\nimport React, { useCallback, useMemo } from 'react'\n\nconst normalizeNavigationTarget = ({\n path,\n pathname,\n search,\n}: {\n path: string\n pathname: string\n search: string\n}) => {\n if (path.startsWith('http')) {\n const url = new URL(path)\n return `${url.pathname}${url.search}${url.hash}`\n }\n\n if (path.startsWith('?')) {\n return `${pathname}${path}`\n }\n\n if (path.startsWith('#')) {\n return `${pathname}${search}${path}`\n }\n\n return path\n}\n\nconst TanStackLinkAdapter: React.FC<LinkAdapterProps> = ({\n children,\n href,\n prefetch,\n ref,\n replace,\n scroll,\n ...rest\n}) => {\n return (\n <TanStackLink\n preload={prefetch === false ? false : 'intent'}\n ref={ref}\n replace={replace}\n resetScroll={scroll}\n to={href}\n {...rest}\n >\n {children}\n </TanStackLink>\n )\n}\n\nexport const TanStackRouterAdapter: RouterAdapterComponent = ({ children }) => {\n const router = useRouter()\n const location = useLocation()\n const params = useParams({ strict: false })\n\n const adaptedParams = useMemo(() => {\n const adapted: Record<string, string | string[]> = { ...params }\n if ('_splat' in params && typeof params._splat === 'string') {\n adapted.segments = params._splat.split('/').filter(Boolean)\n }\n return adapted\n }, [params])\n\n // Split a target into `to` (pathname) + a parsed `search` object, so the\n // router serializes the query via its `stringifySearch` (qs, bracket-encoded)\n // rather than embedding the raw string in `to`. Navigating with a string `to`\n // leaves the search *unencoded* in `window.location.search`\n // (e.g. `where[or][0]…`), which then never matches Payload's `qs.stringify`\n // output (`where%5Bor%5D…`) — breaking the list-view `syncPropsToURL` guard,\n // which compares the two and would otherwise clobber optimistic query state\n // (e.g. an in-progress filter condition) on every navigation.\n const toNavOptions = useCallback((path: string) => {\n const relativePath = normalizeNavigationTarget({\n path,\n pathname: window.location.pathname,\n search: window.location.search,\n })\n const queryIndex = relativePath.indexOf('?')\n if (queryIndex === -1) {\n return { to: relativePath }\n }\n const searchObject = qs.parse(relativePath.slice(queryIndex + 1), {\n depth: 10,\n ignoreQueryPrefix: true,\n })\n // Function form replaces the search entirely (no merge with current search).\n return { search: () => searchObject, to: relativePath.slice(0, queryIndex) }\n }, [])\n\n const back = useCallback(() => router.history.back(), [router])\n const push = useCallback(\n (path: string, options?: { scroll?: boolean }) => {\n void router.navigate({ ...toNavOptions(path), resetScroll: options?.scroll })\n },\n [router, toNavOptions],\n )\n const refresh = useCallback(() => {\n void router.invalidate()\n }, [router])\n const replace = useCallback(\n (path: string, options?: { scroll?: boolean }) => {\n void router.navigate({ ...toNavOptions(path), replace: true, resetScroll: options?.scroll })\n },\n [router, toNavOptions],\n )\n\n const adaptedRouter = useMemo(\n () => ({ back, push, refresh, replace }),\n [back, push, refresh, replace],\n )\n\n // `location.searchStr` is the serialized query string; `location.search` is\n // the parsed object (a nested structure once the router uses `qs` for search\n // serialization), which `URLSearchParams` cannot consume. Build from the\n // string so Payload's `parseSearchParams` re-parses the bracket notation.\n const searchParams = useMemo(() => new URLSearchParams(location.searchStr), [location.searchStr])\n\n const value: RouterAdapterContextValue = useMemo(\n () => ({\n Link: TanStackLinkAdapter,\n params: adaptedParams,\n pathname: location.pathname,\n router: adaptedRouter,\n searchParams,\n }),\n [adaptedParams, location.pathname, adaptedRouter, searchParams],\n )\n\n return <RouterAdapterContext value={value}>{children}</RouterAdapterContext>\n}\n"],"names":["RouterAdapterContext","Link","TanStackLink","useLocation","useParams","useRouter","qs","React","useCallback","useMemo","normalizeNavigationTarget","path","pathname","search","startsWith","url","URL","hash","TanStackLinkAdapter","children","href","prefetch","ref","replace","scroll","rest","preload","resetScroll","to","TanStackRouterAdapter","router","location","params","strict","adaptedParams","adapted","_splat","segments","split","filter","Boolean","toNavOptions","relativePath","window","queryIndex","indexOf","searchObject","parse","slice","depth","ignoreQueryPrefix","back","history","push","options","navigate","refresh","invalidate","adaptedRouter","searchParams","URLSearchParams","searchStr","value"],"mappings":"AAAA;;AAKA,SAASA,oBAAoB,QAAQ,iBAAgB;AACrD,SAASC,QAAQC,YAAY,EAAEC,WAAW,EAAEC,SAAS,EAAEC,SAAS,QAAQ,yBAAwB;AAChG,YAAYC,QAAQ,SAAQ;AAC5B,OAAOC,SAASC,WAAW,EAAEC,OAAO,QAAQ,QAAO;AAEnD,MAAMC,4BAA4B,CAAC,EACjCC,IAAI,EACJC,QAAQ,EACRC,MAAM,EAKP;IACC,IAAIF,KAAKG,UAAU,CAAC,SAAS;QAC3B,MAAMC,MAAM,IAAIC,IAAIL;QACpB,OAAO,GAAGI,IAAIH,QAAQ,GAAGG,IAAIF,MAAM,GAAGE,IAAIE,IAAI,EAAE;IAClD;IAEA,IAAIN,KAAKG,UAAU,CAAC,MAAM;QACxB,OAAO,GAAGF,WAAWD,MAAM;IAC7B;IAEA,IAAIA,KAAKG,UAAU,CAAC,MAAM;QACxB,OAAO,GAAGF,WAAWC,SAASF,MAAM;IACtC;IAEA,OAAOA;AACT;AAEA,MAAMO,sBAAkD,CAAC,EACvDC,QAAQ,EACRC,IAAI,EACJC,QAAQ,EACRC,GAAG,EACHC,OAAO,EACPC,MAAM,EACN,GAAGC,MACJ;IACC,qBACE,KAACvB;QACCwB,SAASL,aAAa,QAAQ,QAAQ;QACtCC,KAAKA;QACLC,SAASA;QACTI,aAAaH;QACbI,IAAIR;QACH,GAAGK,IAAI;kBAEPN;;AAGP;AAEA,OAAO,MAAMU,wBAAgD,CAAC,EAAEV,QAAQ,EAAE;IACxE,MAAMW,SAASzB;IACf,MAAM0B,WAAW5B;IACjB,MAAM6B,SAAS5B,UAAU;QAAE6B,QAAQ;IAAM;IAEzC,MAAMC,gBAAgBzB,QAAQ;QAC5B,MAAM0B,UAA6C;YAAE,GAAGH,MAAM;QAAC;
|
|
1
|
+
{"version":3,"sources":["../../../src/elements/RouterAdapter/index.tsx"],"sourcesContent":["'use client'\n\nimport type { RouterAdapterContextValue } from '@payloadcms/ui'\nimport type { LinkAdapterProps, RouterAdapterComponent } from 'payload'\n\nimport { RouterAdapterContext } from '@payloadcms/ui'\nimport { Link as TanStackLink, useLocation, useParams, useRouter } from '@tanstack/react-router'\nimport * as qs from 'qs-esm'\nimport React, { useCallback, useMemo } from 'react'\n\nconst normalizeNavigationTarget = ({\n path,\n pathname,\n search,\n}: {\n path: string\n pathname: string\n search: string\n}) => {\n if (path.startsWith('http')) {\n const url = new URL(path)\n return `${url.pathname}${url.search}${url.hash}`\n }\n\n if (path.startsWith('?')) {\n return `${pathname}${path}`\n }\n\n if (path.startsWith('#')) {\n return `${pathname}${search}${path}`\n }\n\n return path\n}\n\nconst TanStackLinkAdapter: React.FC<LinkAdapterProps> = ({\n children,\n href,\n prefetch,\n ref,\n replace,\n scroll,\n ...rest\n}) => {\n return (\n <TanStackLink\n preload={prefetch === false ? false : 'intent'}\n ref={ref}\n replace={replace}\n resetScroll={scroll}\n to={href}\n {...rest}\n >\n {children}\n </TanStackLink>\n )\n}\n\nexport const TanStackRouterAdapter: RouterAdapterComponent = ({ children }) => {\n const router = useRouter()\n const location = useLocation()\n const params = useParams({ strict: false })\n\n const adaptedParams = useMemo(() => {\n const adapted: Record<string, string | string[]> = { ...params }\n\n if ('_splat' in params && typeof params._splat === 'string') {\n adapted.segments = params._splat.split('/').filter(Boolean)\n }\n\n return adapted\n }, [params])\n\n // Split a target into `to` (pathname) + a parsed `search` object, so the\n // router serializes the query via its `stringifySearch` (qs, bracket-encoded)\n // rather than embedding the raw string in `to`. Navigating with a string `to`\n // leaves the search *unencoded* in `window.location.search`\n // (e.g. `where[or][0]…`), which then never matches Payload's `qs.stringify`\n // output (`where%5Bor%5D…`) — breaking the list-view `syncPropsToURL` guard,\n // which compares the two and would otherwise clobber optimistic query state\n // (e.g. an in-progress filter condition) on every navigation.\n const toNavOptions = useCallback((path: string) => {\n const relativePath = normalizeNavigationTarget({\n path,\n pathname: window.location.pathname,\n search: window.location.search,\n })\n\n const queryIndex = relativePath.indexOf('?')\n\n if (queryIndex === -1) {\n return { to: relativePath }\n }\n\n const searchObject = qs.parse(relativePath.slice(queryIndex + 1), {\n depth: 10,\n ignoreQueryPrefix: true,\n })\n\n // Function form replaces the search entirely (no merge with current search).\n return { search: () => searchObject, to: relativePath.slice(0, queryIndex) }\n }, [])\n\n const back = useCallback(() => router.history.back(), [router])\n\n const push = useCallback(\n (path: string, options?: { scroll?: boolean }) => {\n void router.navigate({ ...toNavOptions(path), resetScroll: options?.scroll })\n },\n [router, toNavOptions],\n )\n\n const refresh = useCallback(() => {\n void router.invalidate()\n }, [router])\n\n const replace = useCallback(\n (path: string, options?: { scroll?: boolean }) => {\n void router.navigate({ ...toNavOptions(path), replace: true, resetScroll: options?.scroll })\n },\n [router, toNavOptions],\n )\n\n // Mirror Next.js' router behavior to allow syncing client state to the URL without triggering a second server load.\n // TanStack's browser history monkeypatches `window.history.replaceState` and notifies `router.load` on every call.\n // Use `_ignoreSubscribers` to suppresses that notification — the same flag TanStack uses internally when flushing history.\n const replaceState = useCallback(\n (url: string) => {\n const { history } = router\n history._ignoreSubscribers = true\n\n try {\n window.history.replaceState(null, '', url)\n } finally {\n history._ignoreSubscribers = false\n }\n },\n [router],\n )\n\n const adaptedRouter = useMemo(\n () => ({ back, push, refresh, replace, replaceState }),\n [back, push, refresh, replace, replaceState],\n )\n\n // `location.searchStr` is the serialized query string; `location.search` is\n // the parsed object (a nested structure once the router uses `qs` for search\n // serialization), which `URLSearchParams` cannot consume. Build from the\n // string so Payload's `parseSearchParams` re-parses the bracket notation.\n const searchParams = useMemo(() => new URLSearchParams(location.searchStr), [location.searchStr])\n\n const value: RouterAdapterContextValue = useMemo(\n () => ({\n Link: TanStackLinkAdapter,\n params: adaptedParams,\n pathname: location.pathname,\n router: adaptedRouter,\n searchParams,\n }),\n [adaptedParams, location.pathname, adaptedRouter, searchParams],\n )\n\n return <RouterAdapterContext value={value}>{children}</RouterAdapterContext>\n}\n"],"names":["RouterAdapterContext","Link","TanStackLink","useLocation","useParams","useRouter","qs","React","useCallback","useMemo","normalizeNavigationTarget","path","pathname","search","startsWith","url","URL","hash","TanStackLinkAdapter","children","href","prefetch","ref","replace","scroll","rest","preload","resetScroll","to","TanStackRouterAdapter","router","location","params","strict","adaptedParams","adapted","_splat","segments","split","filter","Boolean","toNavOptions","relativePath","window","queryIndex","indexOf","searchObject","parse","slice","depth","ignoreQueryPrefix","back","history","push","options","navigate","refresh","invalidate","replaceState","_ignoreSubscribers","adaptedRouter","searchParams","URLSearchParams","searchStr","value"],"mappings":"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"}
|
package/dist/exports/client.d.ts
CHANGED
|
@@ -4,4 +4,5 @@ export { buildThemeInitScript, PayloadAdminShell, type PayloadAdminShellProps, T
|
|
|
4
4
|
export { type AdminLoad, payloadAdminIndexRoute, payloadAdminSplatRoute, } from '../routes/adminRoutes.js';
|
|
5
5
|
export { type LayoutLoad, payloadLayoutRoute } from '../routes/layoutRoute.js';
|
|
6
6
|
export { viteDevReloadStrategy } from '../utilities/devReloadStrategy.js';
|
|
7
|
+
export { createServerFunctionClient, stripUnserializable, } from '../utilities/serverFunctionClient.js';
|
|
7
8
|
//# sourceMappingURL=client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/exports/client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAA;AAChF,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAA;AAC1E,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,KAAK,sBAAsB,EAC3B,iBAAiB,EACjB,eAAe,EACf,KAAK,sBAAsB,GAC5B,MAAM,oCAAoC,CAAA;AAC3C,OAAO,EACL,KAAK,SAAS,EACd,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,0BAA0B,CAAA;AACjC,OAAO,EAAE,KAAK,UAAU,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAA;AAC9E,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAA"}
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/exports/client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAA;AAChF,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAA;AAC1E,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,KAAK,sBAAsB,EAC3B,iBAAiB,EACjB,eAAe,EACf,KAAK,sBAAsB,GAC5B,MAAM,oCAAoC,CAAA;AAC3C,OAAO,EACL,KAAK,SAAS,EACd,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,0BAA0B,CAAA;AACjC,OAAO,EAAE,KAAK,UAAU,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAA;AAC9E,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAA;AACzE,OAAO,EACL,0BAA0B,EAC1B,mBAAmB,GACpB,MAAM,sCAAsC,CAAA"}
|
package/dist/exports/client.js
CHANGED
|
@@ -5,5 +5,6 @@ export { buildThemeInitScript, PayloadAdminShell, THEME_INIT_SCRIPT, withPayload
|
|
|
5
5
|
export { payloadAdminIndexRoute, payloadAdminSplatRoute } from '../routes/adminRoutes.js';
|
|
6
6
|
export { payloadLayoutRoute } from '../routes/layoutRoute.js';
|
|
7
7
|
export { viteDevReloadStrategy } from '../utilities/devReloadStrategy.js';
|
|
8
|
+
export { createServerFunctionClient, stripUnserializable } from '../utilities/serverFunctionClient.js';
|
|
8
9
|
|
|
9
10
|
//# sourceMappingURL=client.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/exports/client.ts"],"sourcesContent":["'use client'\n\nexport { TanStackComponentRenderer } from '../elements/RenderComponent/index.js'\nexport { TanStackRouterAdapter } from '../elements/RouterAdapter/index.js'\nexport {\n buildThemeInitScript,\n PayloadAdminShell,\n type PayloadAdminShellProps,\n THEME_INIT_SCRIPT,\n withPayloadRoot,\n type WithPayloadRootOptions,\n} from '../layouts/Root/withPayloadRoot.js'\nexport {\n type AdminLoad,\n payloadAdminIndexRoute,\n payloadAdminSplatRoute,\n} from '../routes/adminRoutes.js'\nexport { type LayoutLoad, payloadLayoutRoute } from '../routes/layoutRoute.js'\nexport { viteDevReloadStrategy } from '../utilities/devReloadStrategy.js'\n"],"names":["TanStackComponentRenderer","TanStackRouterAdapter","buildThemeInitScript","PayloadAdminShell","THEME_INIT_SCRIPT","withPayloadRoot","payloadAdminIndexRoute","payloadAdminSplatRoute","payloadLayoutRoute","viteDevReloadStrategy"],"mappings":"AAAA;AAEA,SAASA,yBAAyB,QAAQ,uCAAsC;AAChF,SAASC,qBAAqB,QAAQ,qCAAoC;AAC1E,SACEC,oBAAoB,EACpBC,iBAAiB,EAEjBC,iBAAiB,EACjBC,eAAe,QAEV,qCAAoC;AAC3C,SAEEC,sBAAsB,EACtBC,sBAAsB,QACjB,2BAA0B;AACjC,SAA0BC,kBAAkB,QAAQ,2BAA0B;AAC9E,SAASC,qBAAqB,QAAQ,oCAAmC"}
|
|
1
|
+
{"version":3,"sources":["../../src/exports/client.ts"],"sourcesContent":["'use client'\n\nexport { TanStackComponentRenderer } from '../elements/RenderComponent/index.js'\nexport { TanStackRouterAdapter } from '../elements/RouterAdapter/index.js'\nexport {\n buildThemeInitScript,\n PayloadAdminShell,\n type PayloadAdminShellProps,\n THEME_INIT_SCRIPT,\n withPayloadRoot,\n type WithPayloadRootOptions,\n} from '../layouts/Root/withPayloadRoot.js'\nexport {\n type AdminLoad,\n payloadAdminIndexRoute,\n payloadAdminSplatRoute,\n} from '../routes/adminRoutes.js'\nexport { type LayoutLoad, payloadLayoutRoute } from '../routes/layoutRoute.js'\nexport { viteDevReloadStrategy } from '../utilities/devReloadStrategy.js'\nexport {\n createServerFunctionClient,\n stripUnserializable,\n} from '../utilities/serverFunctionClient.js'\n"],"names":["TanStackComponentRenderer","TanStackRouterAdapter","buildThemeInitScript","PayloadAdminShell","THEME_INIT_SCRIPT","withPayloadRoot","payloadAdminIndexRoute","payloadAdminSplatRoute","payloadLayoutRoute","viteDevReloadStrategy","createServerFunctionClient","stripUnserializable"],"mappings":"AAAA;AAEA,SAASA,yBAAyB,QAAQ,uCAAsC;AAChF,SAASC,qBAAqB,QAAQ,qCAAoC;AAC1E,SACEC,oBAAoB,EACpBC,iBAAiB,EAEjBC,iBAAiB,EACjBC,eAAe,QAEV,qCAAoC;AAC3C,SAEEC,sBAAsB,EACtBC,sBAAsB,QACjB,2BAA0B;AACjC,SAA0BC,kBAAkB,QAAQ,2BAA0B;AAC9E,SAASC,qBAAqB,QAAQ,oCAAmC;AACzE,SACEC,0BAA0B,EAC1BC,mBAAmB,QACd,uCAAsC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export { TanStackComponentRenderer } from './elements/RenderComponent/index.js';
|
|
2
2
|
export { TanStackRouterAdapter } from './elements/RouterAdapter/index.js';
|
|
3
|
-
export {
|
|
3
|
+
export { payloadApiHandlers } from './routes/apiRoute.js';
|
|
4
4
|
export { viteDevReloadStrategy } from './utilities/devReloadStrategy.js';
|
|
5
5
|
export { type AdminPageMetadata, getAdminMeta } from './utilities/meta.js';
|
|
6
|
-
export { createServerFunctionClient, stripUnserializable, } from './utilities/serverFunctionClient.js';
|
|
7
6
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,qCAAqC,CAAA;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAA;AACzE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,qCAAqC,CAAA;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAA;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAA;AACxE,OAAO,EAAE,KAAK,iBAAiB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
export { TanStackComponentRenderer } from './elements/RenderComponent/index.js';
|
|
2
2
|
export { TanStackRouterAdapter } from './elements/RouterAdapter/index.js';
|
|
3
|
-
export {
|
|
3
|
+
export { payloadApiHandlers } from './routes/apiRoute.js';
|
|
4
4
|
export { viteDevReloadStrategy } from './utilities/devReloadStrategy.js';
|
|
5
5
|
export { getAdminMeta } from './utilities/meta.js';
|
|
6
|
-
export { createServerFunctionClient, stripUnserializable } from './utilities/serverFunctionClient.js';
|
|
7
6
|
|
|
8
7
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export { TanStackComponentRenderer } from './elements/RenderComponent/index.js'\nexport { TanStackRouterAdapter } from './elements/RouterAdapter/index.js'\nexport {
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export { TanStackComponentRenderer } from './elements/RenderComponent/index.js'\nexport { TanStackRouterAdapter } from './elements/RouterAdapter/index.js'\nexport { payloadApiHandlers } from './routes/apiRoute.js'\nexport { viteDevReloadStrategy } from './utilities/devReloadStrategy.js'\nexport { type AdminPageMetadata, getAdminMeta } from './utilities/meta.js'\n"],"names":["TanStackComponentRenderer","TanStackRouterAdapter","payloadApiHandlers","viteDevReloadStrategy","getAdminMeta"],"mappings":"AAAA,SAASA,yBAAyB,QAAQ,sCAAqC;AAC/E,SAASC,qBAAqB,QAAQ,oCAAmC;AACzE,SAASC,kBAAkB,QAAQ,uBAAsB;AACzD,SAASC,qBAAqB,QAAQ,mCAAkC;AACxE,SAAiCC,YAAY,QAAQ,sBAAqB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/layouts/Root/getLayoutData.ts"],"sourcesContent":["import type { AcceptedLanguages } from '@payloadcms/translations'\nimport type { ImportMap, LanguageOptions, SanitizedConfig, ServerProps } from 'payload'\n\nimport { getNavPrefs } from '@payloadcms/ui/elements/Nav/getNavPrefs'\nimport { RenderServerComponent } from '@payloadcms/ui/elements/RenderServerComponent'\nimport { getClientConfig } from '@payloadcms/ui/utilities/getClientConfig'\nimport { Outlet } from '@tanstack/react-router'\nimport { applyLocaleFiltering } from 'payload/shared'\nimport { createElement } from 'react'\n\nimport type { RootLayoutData } from './index.js'\n\nimport { getRequestTheme } from '../../utilities/getRequestTheme.js'\nimport { initReq } from '../../utilities/initReq.server.js'\n\nexport type GetLayoutDataArgs = {\n configPromise: Promise<SanitizedConfig> | SanitizedConfig\n importMap: ImportMap\n}\n\n/**\n * Fetches all data needed by the root admin layout.\n * Call this in your TanStack Start root route loader.\n */\nexport async function getLayoutData({\n configPromise,\n importMap,\n}: GetLayoutDataArgs): Promise<RootLayoutData> {\n const {\n cookies,\n headers,\n languageCode,\n permissions,\n req,\n req: {\n payload: { config },\n },\n } = await initReq({ configPromise, importMap })\n\n const theme = getRequestTheme({ config, cookies, headers })\n\n const languageOptions: LanguageOptions = Object.entries(\n config.i18n.supportedLanguages || {},\n ).reduce((acc, [language, languageConfig]) => {\n if (Object.keys(config.i18n.supportedLanguages).includes(language)) {\n acc.push({\n label: languageConfig.translations.general.thisLanguage,\n value: language as AcceptedLanguages,\n })\n }\n return acc\n }, [] as LanguageOptions)\n\n const navPrefs = await getNavPrefs(req)\n\n const clientConfig = getClientConfig({\n config,\n i18n: req.i18n,\n importMap,\n user: req.user ?? true,\n })\n\n await applyLocaleFiltering({ clientConfig, config, req })\n\n // Build the custom admin provider tree (`config.admin.components.providers`)\n // nested around the router `<Outlet />`, mirroring the Next adapter's\n // `NestProviders`. Returned as an unrendered element; the caller's server\n // function renders it to an RSC payload (so server-component providers run\n // server-side and client providers wrap the live Outlet). `undefined` when\n // no custom providers are configured — the caller falls back to `<Outlet />`.\n const providerPaths = config.admin?.components?.providers\n let providers: React.ReactNode = undefined\n if (Array.isArray(providerPaths) && providerPaths.length > 0) {\n const serverProps: ServerProps = {\n i18n: req.i18n,\n params: {},\n payload: req.payload,\n permissions,\n searchParams: {},\n server: req.server
|
|
1
|
+
{"version":3,"sources":["../../../src/layouts/Root/getLayoutData.ts"],"sourcesContent":["import type { AcceptedLanguages } from '@payloadcms/translations'\nimport type { ImportMap, LanguageOptions, SanitizedConfig, ServerProps } from 'payload'\n\nimport { getNavPrefs } from '@payloadcms/ui/elements/Nav/getNavPrefs'\nimport { RenderServerComponent } from '@payloadcms/ui/elements/RenderServerComponent'\nimport { getClientConfig } from '@payloadcms/ui/utilities/getClientConfig'\nimport { Outlet } from '@tanstack/react-router'\nimport { applyLocaleFiltering } from 'payload/shared'\nimport { createElement } from 'react'\n\nimport type { RootLayoutData } from './index.js'\n\nimport { getRequestTheme } from '../../utilities/getRequestTheme.js'\nimport { initReq } from '../../utilities/initReq.server.js'\n\nexport type GetLayoutDataArgs = {\n configPromise: Promise<SanitizedConfig> | SanitizedConfig\n importMap: ImportMap\n}\n\n/**\n * Fetches all data needed by the root admin layout.\n * Call this in your TanStack Start root route loader.\n */\nexport async function getLayoutData({\n configPromise,\n importMap,\n}: GetLayoutDataArgs): Promise<RootLayoutData> {\n const {\n cookies,\n headers,\n languageCode,\n permissions,\n req,\n req: {\n payload: { config },\n },\n } = await initReq({ configPromise, importMap })\n\n const theme = getRequestTheme({ config, cookies, headers })\n\n const languageOptions: LanguageOptions = Object.entries(\n config.i18n.supportedLanguages || {},\n ).reduce((acc, [language, languageConfig]) => {\n if (Object.keys(config.i18n.supportedLanguages).includes(language)) {\n acc.push({\n label: languageConfig.translations.general.thisLanguage,\n value: language as AcceptedLanguages,\n })\n }\n return acc\n }, [] as LanguageOptions)\n\n const navPrefs = await getNavPrefs(req)\n\n const clientConfig = getClientConfig({\n config,\n i18n: req.i18n,\n importMap,\n user: req.user ?? true,\n })\n\n await applyLocaleFiltering({ clientConfig, config, req })\n\n // Build the custom admin provider tree (`config.admin.components.providers`)\n // nested around the router `<Outlet />`, mirroring the Next adapter's\n // `NestProviders`. Returned as an unrendered element; the caller's server\n // function renders it to an RSC payload (so server-component providers run\n // server-side and client providers wrap the live Outlet). `undefined` when\n // no custom providers are configured — the caller falls back to `<Outlet />`.\n const providerPaths = config.admin?.components?.providers\n let providers: React.ReactNode = undefined\n if (Array.isArray(providerPaths) && providerPaths.length > 0) {\n const serverProps: ServerProps = {\n i18n: req.i18n,\n params: {},\n payload: req.payload,\n permissions,\n searchParams: {},\n server: req.server!,\n user: req.user ?? undefined,\n }\n // Mirror the Next adapter's `NestProviders`: render each configured provider\n // via `RenderServerComponent` so the entry's own `clientProps`/`serverProps`\n // (e.g. plugin-multi-tenant's `userHasAccessToAllTenants`) are merged in, and\n // server components receive `serverProps` while client components get only\n // `clientProps`. Nested around the router `<Outlet />` instead of `children`.\n providers = providerPaths.reduceRight<React.ReactNode>(\n (children, provider) =>\n RenderServerComponent({\n clientProps: { children },\n Component: provider,\n importMap,\n serverProps,\n }),\n createElement(Outlet),\n )\n }\n\n return {\n clientConfig,\n dateFNSKey: req.i18n.dateFNSKey,\n fallbackLang: config.i18n.fallbackLanguage,\n isNavOpen: navPrefs?.open ?? true,\n languageCode,\n languageOptions,\n locale: req.locale ?? undefined,\n permissions,\n providers,\n theme,\n translations: req.i18n.translations,\n user: req.user,\n }\n}\n"],"names":["getNavPrefs","RenderServerComponent","getClientConfig","Outlet","applyLocaleFiltering","createElement","getRequestTheme","initReq","getLayoutData","configPromise","importMap","cookies","headers","languageCode","permissions","req","payload","config","theme","languageOptions","Object","entries","i18n","supportedLanguages","reduce","acc","language","languageConfig","keys","includes","push","label","translations","general","thisLanguage","value","navPrefs","clientConfig","user","providerPaths","admin","components","providers","undefined","Array","isArray","length","serverProps","params","searchParams","server","reduceRight","children","provider","clientProps","Component","dateFNSKey","fallbackLang","fallbackLanguage","isNavOpen","open","locale"],"mappings":"AAGA,SAASA,WAAW,QAAQ,0CAAyC;AACrE,SAASC,qBAAqB,QAAQ,gDAA+C;AACrF,SAASC,eAAe,QAAQ,2CAA0C;AAC1E,SAASC,MAAM,QAAQ,yBAAwB;AAC/C,SAASC,oBAAoB,QAAQ,iBAAgB;AACrD,SAASC,aAAa,QAAQ,QAAO;AAIrC,SAASC,eAAe,QAAQ,qCAAoC;AACpE,SAASC,OAAO,QAAQ,oCAAmC;AAO3D;;;CAGC,GACD,OAAO,eAAeC,cAAc,EAClCC,aAAa,EACbC,SAAS,EACS;IAClB,MAAM,EACJC,OAAO,EACPC,OAAO,EACPC,YAAY,EACZC,WAAW,EACXC,GAAG,EACHA,KAAK,EACHC,SAAS,EAAEC,MAAM,EAAE,EACpB,EACF,GAAG,MAAMV,QAAQ;QAAEE;QAAeC;IAAU;IAE7C,MAAMQ,QAAQZ,gBAAgB;QAAEW;QAAQN;QAASC;IAAQ;IAEzD,MAAMO,kBAAmCC,OAAOC,OAAO,CACrDJ,OAAOK,IAAI,CAACC,kBAAkB,IAAI,CAAC,GACnCC,MAAM,CAAC,CAACC,KAAK,CAACC,UAAUC,eAAe;QACvC,IAAIP,OAAOQ,IAAI,CAACX,OAAOK,IAAI,CAACC,kBAAkB,EAAEM,QAAQ,CAACH,WAAW;YAClED,IAAIK,IAAI,CAAC;gBACPC,OAAOJ,eAAeK,YAAY,CAACC,OAAO,CAACC,YAAY;gBACvDC,OAAOT;YACT;QACF;QACA,OAAOD;IACT,GAAG,EAAE;IAEL,MAAMW,WAAW,MAAMpC,YAAYe;IAEnC,MAAMsB,eAAenC,gBAAgB;QACnCe;QACAK,MAAMP,IAAIO,IAAI;QACdZ;QACA4B,MAAMvB,IAAIuB,IAAI,IAAI;IACpB;IAEA,MAAMlC,qBAAqB;QAAEiC;QAAcpB;QAAQF;IAAI;IAEvD,6EAA6E;IAC7E,sEAAsE;IACtE,0EAA0E;IAC1E,2EAA2E;IAC3E,2EAA2E;IAC3E,8EAA8E;IAC9E,MAAMwB,gBAAgBtB,OAAOuB,KAAK,EAAEC,YAAYC;IAChD,IAAIA,YAA6BC;IACjC,IAAIC,MAAMC,OAAO,CAACN,kBAAkBA,cAAcO,MAAM,GAAG,GAAG;QAC5D,MAAMC,cAA2B;YAC/BzB,MAAMP,IAAIO,IAAI;YACd0B,QAAQ,CAAC;YACThC,SAASD,IAAIC,OAAO;YACpBF;YACAmC,cAAc,CAAC;YACfC,QAAQnC,IAAImC,MAAM;YAClBZ,MAAMvB,IAAIuB,IAAI,IAAIK;QACpB;QACA,6EAA6E;QAC7E,6EAA6E;QAC7E,8EAA8E;QAC9E,2EAA2E;QAC3E,8EAA8E;QAC9ED,YAAYH,cAAcY,WAAW,CACnC,CAACC,UAAUC,WACTpD,sBAAsB;gBACpBqD,aAAa;oBAAEF;gBAAS;gBACxBG,WAAWF;gBACX3C;gBACAqC;YACF,IACF1C,cAAcF;IAElB;IAEA,OAAO;QACLkC;QACAmB,YAAYzC,IAAIO,IAAI,CAACkC,UAAU;QAC/BC,cAAcxC,OAAOK,IAAI,CAACoC,gBAAgB;QAC1CC,WAAWvB,UAAUwB,QAAQ;QAC7B/C;QACAM;QACA0C,QAAQ9C,IAAI8C,MAAM,IAAIlB;QACtB7B;QACA4B;QACAxB;QACAc,cAAcjB,IAAIO,IAAI,CAACU,YAAY;QACnCM,MAAMvB,IAAIuB,IAAI;IAChB;AACF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { I18nClient } from '@payloadcms/translations';
|
|
2
2
|
import type { Theme } from '@payloadcms/ui';
|
|
3
|
-
import type { ClientConfig, LanguageOptions, SanitizedPermissions, ServerFunctionClient,
|
|
3
|
+
import type { ClientConfig, LanguageOptions, SanitizedPermissions, ServerFunctionClient, User } from 'payload';
|
|
4
4
|
import React from 'react';
|
|
5
5
|
import '@payloadcms/ui/scss/app.scss';
|
|
6
6
|
export type RootLayoutData = {
|
|
@@ -21,7 +21,7 @@ export type RootLayoutData = {
|
|
|
21
21
|
providers?: React.ReactNode;
|
|
22
22
|
theme: Theme;
|
|
23
23
|
translations: I18nClient['translations'];
|
|
24
|
-
user: null |
|
|
24
|
+
user: null | User;
|
|
25
25
|
};
|
|
26
26
|
export type RootLayoutProps = {
|
|
27
27
|
readonly children: React.ReactNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/layouts/Root/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAqB,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAC7E,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAC3C,OAAO,KAAK,EACV,YAAY,EACZ,eAAe,EACf,oBAAoB,EACpB,oBAAoB,EACpB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/layouts/Root/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAqB,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAC7E,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAC3C,OAAO,KAAK,EACV,YAAY,EACZ,eAAe,EACf,oBAAoB,EACpB,oBAAoB,EACpB,IAAI,EACL,MAAM,SAAS,CAAA;AAIhB,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,8BAA8B,CAAA;AAIrC,MAAM,MAAM,cAAc,GAAG;IAC3B,YAAY,EAAE,YAAY,CAAA;IAC1B,UAAU,EAAE,UAAU,CAAC,YAAY,CAAC,CAAA;IACpC,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,OAAO,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,eAAe,EAAE,eAAe,CAAA;IAChC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,oBAAoB,CAAA;IACjC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC3B,KAAK,EAAE,KAAK,CAAA;IACZ,YAAY,EAAE,UAAU,CAAC,cAAc,CAAC,CAAA;IACxC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IAClC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAA;IAC7B,QAAQ,CAAC,cAAc,EAAE,oBAAoB,CAAA;CAC9C,CAAA;AAED,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE,eAAe,qBAgC7E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/layouts/Root/index.tsx"],"sourcesContent":["import type { AcceptedLanguages, I18nClient } from '@payloadcms/translations'\nimport type { Theme } from '@payloadcms/ui'\nimport type {\n ClientConfig,\n LanguageOptions,\n SanitizedPermissions,\n ServerFunctionClient,\n
|
|
1
|
+
{"version":3,"sources":["../../../src/layouts/Root/index.tsx"],"sourcesContent":["import type { AcceptedLanguages, I18nClient } from '@payloadcms/translations'\nimport type { Theme } from '@payloadcms/ui'\nimport type {\n ClientConfig,\n LanguageOptions,\n SanitizedPermissions,\n ServerFunctionClient,\n User,\n} from 'payload'\n\nimport { rtlLanguages } from '@payloadcms/translations'\nimport { ProgressBar, RootProvider } from '@payloadcms/ui'\nimport React from 'react'\nimport '@payloadcms/ui/scss/app.scss'\n\nimport { TanStackRouterAdapter } from '../../elements/RouterAdapter/index.js'\n\nexport type RootLayoutData = {\n clientConfig: ClientConfig\n dateFNSKey: I18nClient['dateFNSKey']\n fallbackLang: string\n isNavOpen: boolean\n languageCode: string\n languageOptions: LanguageOptions\n locale?: string\n permissions: SanitizedPermissions\n /**\n * Custom admin provider tree (`config.admin.components.providers`) nested\n * around the router `<Outlet />`. Built unrendered by `getLayoutData`; the\n * layout server function renders it to an RSC payload before it reaches the\n * client. `undefined` when no custom providers are configured.\n */\n providers?: React.ReactNode\n theme: Theme\n translations: I18nClient['translations']\n user: null | User\n}\n\nexport type RootLayoutProps = {\n readonly children: React.ReactNode\n readonly data: RootLayoutData\n readonly serverFunction: ServerFunctionClient\n}\n\nexport function RootLayout({ children, data, serverFunction }: RootLayoutProps) {\n const dir = (rtlLanguages as unknown as string[]).includes(data.languageCode) ? 'RTL' : 'LTR'\n\n return (\n <html data-theme={data.theme} dir={dir} lang={data.languageCode} suppressHydrationWarning>\n <head>\n <style>{`@layer payload-default, payload;`}</style>\n </head>\n <body>\n <RootProvider\n config={data.clientConfig}\n dateFNSKey={data.dateFNSKey}\n fallbackLang={data.fallbackLang as AcceptedLanguages}\n highContrastMode={false}\n isNavOpen={data.isNavOpen}\n languageCode={data.languageCode}\n languageOptions={data.languageOptions}\n locale={data.locale}\n permissions={(data.user ? data.permissions : null) as unknown as SanitizedPermissions}\n RouterAdapter={TanStackRouterAdapter}\n serverFunction={serverFunction}\n theme={data.theme}\n translations={data.translations}\n user={data.user}\n >\n <ProgressBar />\n {children}\n </RootProvider>\n <div id=\"portal\" />\n </body>\n </html>\n )\n}\n"],"names":["rtlLanguages","ProgressBar","RootProvider","React","TanStackRouterAdapter","RootLayout","children","data","serverFunction","dir","includes","languageCode","html","data-theme","theme","lang","suppressHydrationWarning","head","style","body","config","clientConfig","dateFNSKey","fallbackLang","highContrastMode","isNavOpen","languageOptions","locale","permissions","user","RouterAdapter","translations","div","id"],"mappings":";AAUA,SAASA,YAAY,QAAQ,2BAA0B;AACvD,SAASC,WAAW,EAAEC,YAAY,QAAQ,iBAAgB;AAC1D,OAAOC,WAAW,QAAO;AACzB,OAAO,+BAA8B;AAErC,SAASC,qBAAqB,QAAQ,wCAAuC;AA6B7E,OAAO,SAASC,WAAW,EAAEC,QAAQ,EAAEC,IAAI,EAAEC,cAAc,EAAmB;IAC5E,MAAMC,MAAM,AAACT,aAAqCU,QAAQ,CAACH,KAAKI,YAAY,IAAI,QAAQ;IAExF,qBACE,MAACC;QAAKC,cAAYN,KAAKO,KAAK;QAAEL,KAAKA;QAAKM,MAAMR,KAAKI,YAAY;QAAEK,wBAAwB;;0BACvF,KAACC;0BACC,cAAA,KAACC;8BAAO,CAAC,gCAAgC,CAAC;;;0BAE5C,MAACC;;kCACC,MAACjB;wBACCkB,QAAQb,KAAKc,YAAY;wBACzBC,YAAYf,KAAKe,UAAU;wBAC3BC,cAAchB,KAAKgB,YAAY;wBAC/BC,kBAAkB;wBAClBC,WAAWlB,KAAKkB,SAAS;wBACzBd,cAAcJ,KAAKI,YAAY;wBAC/Be,iBAAiBnB,KAAKmB,eAAe;wBACrCC,QAAQpB,KAAKoB,MAAM;wBACnBC,aAAcrB,KAAKsB,IAAI,GAAGtB,KAAKqB,WAAW,GAAG;wBAC7CE,eAAe1B;wBACfI,gBAAgBA;wBAChBM,OAAOP,KAAKO,KAAK;wBACjBiB,cAAcxB,KAAKwB,YAAY;wBAC/BF,MAAMtB,KAAKsB,IAAI;;0CAEf,KAAC5B;4BACAK;;;kCAEH,KAAC0B;wBAAIC,IAAG;;;;;;AAIhB"}
|
|
@@ -49,10 +49,13 @@ export declare function payloadAdminSplatRoute({ load }: {
|
|
|
49
49
|
title: string;
|
|
50
50
|
})[];
|
|
51
51
|
};
|
|
52
|
-
loader:
|
|
53
|
-
location:
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
loader: {
|
|
53
|
+
handler: ({ location, params }: {
|
|
54
|
+
location: any;
|
|
55
|
+
params: any;
|
|
56
|
+
}) => Promise<any>;
|
|
57
|
+
staleReloadMode: string;
|
|
58
|
+
};
|
|
56
59
|
loaderDeps: ({ search }: {
|
|
57
60
|
search: Record<string, unknown>;
|
|
58
61
|
}) => {
|
|
@@ -91,9 +94,12 @@ export declare function payloadAdminIndexRoute({ load }: {
|
|
|
91
94
|
title: string;
|
|
92
95
|
})[];
|
|
93
96
|
};
|
|
94
|
-
loader:
|
|
95
|
-
location:
|
|
96
|
-
|
|
97
|
+
loader: {
|
|
98
|
+
handler: ({ location }: {
|
|
99
|
+
location: any;
|
|
100
|
+
}) => Promise<any>;
|
|
101
|
+
staleReloadMode: string;
|
|
102
|
+
};
|
|
97
103
|
loaderDeps: ({ search }: {
|
|
98
104
|
search: Record<string, unknown>;
|
|
99
105
|
}) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adminRoutes.d.ts","sourceRoot":"","sources":["../../src/routes/adminRoutes.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAIhD;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,IAAI,EAAE;IAC7B,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAA;KAAE,CAAA;CACpE,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;AAclB,iBAAS,SAAS,gCAQjB;AAED,iBAAS,aAAa,CAAC,KAAK,EAAE;IAAE,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,SAAS,CAAA;KAAE,CAAA;CAAE,+BAMrF;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE;;2BAGzC;QAAE,UAAU,CAAC,EAAE,GAAG,CAAA;KAAE
|
|
1
|
+
{"version":3,"file":"adminRoutes.d.ts","sourceRoot":"","sources":["../../src/routes/adminRoutes.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAIhD;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,IAAI,EAAE;IAC7B,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAA;KAAE,CAAA;CACpE,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;AAclB,iBAAS,SAAS,gCAQjB;AAED,iBAAS,aAAa,CAAC,KAAK,EAAE;IAAE,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,SAAS,CAAA;KAAE,CAAA;CAAE,+BAMrF;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE;;2BAGzC;QAAE,UAAU,CAAC,EAAE,GAAG,CAAA;KAAE;;;;;;;;;;;;;;;;;;;;;wCAOH;YAAE,QAAQ,EAAE,GAAG,CAAC;YAAC,MAAM,EAAE,GAAG,CAAA;SAAE;;;6BAW7C;QAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE;;;;6BAInC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;EAEnD;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE;;2BAGzC;QAAE,UAAU,CAAC,EAAE,GAAG,CAAA;KAAE;;;;;;;;;;;;;;;;;;;;;gCAEX;YAAE,QAAQ,EAAE,GAAG,CAAA;SAAE;;;6BAUxB;QAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE;;;6BAGnC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;EAEnD"}
|
|
@@ -51,20 +51,28 @@ function AdminNotFound(props) {
|
|
|
51
51
|
return {
|
|
52
52
|
component: AdminPage,
|
|
53
53
|
head: ({ loaderData })=>getAdminMeta(loaderData?.metadata),
|
|
54
|
-
//
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
54
|
+
// `staleReloadMode: 'blocking'` (a property of the loader *object*, not a
|
|
55
|
+
// sibling route option — router-core only reads it off a non-function loader)
|
|
56
|
+
// makes stale-match revalidation await the fresh loader before committing,
|
|
57
|
+
// instead of the default background SWR that flashes the pre-navigation list
|
|
58
|
+
// (e.g. a just-created doc missing) until the reload lands.
|
|
59
|
+
loader: {
|
|
60
|
+
handler: async ({ location, params })=>{
|
|
61
|
+
const data = await runLoader(load, params._splat ?? '', location.searchStr);
|
|
62
|
+
if (data?._notFound) {
|
|
63
|
+
// eslint-disable-next-line @typescript-eslint/only-throw-error -- TanStack Router requires throwing notFound objects
|
|
64
|
+
throw notFound({
|
|
65
|
+
data: {
|
|
66
|
+
routeKey: data.routeKey,
|
|
67
|
+
rscPayload: data.rscPayload
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return data;
|
|
72
|
+
},
|
|
73
|
+
staleReloadMode: 'blocking'
|
|
67
74
|
},
|
|
75
|
+
// Surface query params in `loaderDeps` so `?locale=es` re-runs the loader.
|
|
68
76
|
loaderDeps: ({ search })=>({
|
|
69
77
|
searchKey: JSON.stringify(search)
|
|
70
78
|
}),
|
|
@@ -79,13 +87,16 @@ function AdminNotFound(props) {
|
|
|
79
87
|
return {
|
|
80
88
|
component: AdminPage,
|
|
81
89
|
head: ({ loaderData })=>getAdminMeta(loaderData?.metadata),
|
|
82
|
-
loader:
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
90
|
+
loader: {
|
|
91
|
+
handler: async ({ location })=>{
|
|
92
|
+
const data = await runLoader(load, '', location.searchStr);
|
|
93
|
+
if (data?._notFound) {
|
|
94
|
+
// eslint-disable-next-line @typescript-eslint/only-throw-error -- TanStack Router requires throwing notFound objects
|
|
95
|
+
throw notFound();
|
|
96
|
+
}
|
|
97
|
+
return data;
|
|
98
|
+
},
|
|
99
|
+
staleReloadMode: 'blocking'
|
|
89
100
|
},
|
|
90
101
|
loaderDeps: ({ search })=>({
|
|
91
102
|
searchKey: JSON.stringify(search)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/routes/adminRoutes.tsx"],"sourcesContent":["'use client'\n\nimport { NotFoundClient } from '@payloadcms/ui'\nimport { notFound, redirect, useLoaderData } from '@tanstack/react-router'\nimport { Fragment, type ReactNode } from 'react'\n\nimport { getAdminMeta } from '../utilities/meta.js'\n\n/**\n * Loader supplied by the app — a TanStack Start `createServerFn` that delegates\n * to `loadAdminPage`. Typed loosely because the server-fn's call signature is\n * generated by the Start compiler.\n */\nexport type AdminLoad = (opts: {\n data: { _splat: string; search: Record<string, string | string[]> }\n}) => Promise<any>\n\nconst searchToRecord = (searchStr: string): Record<string, string | string[]> =>\n Object.fromEntries(new URLSearchParams(searchStr)) as Record<string, string | string[]>\n\nconst runLoader = async (load: AdminLoad, splat: string, searchStr: string) => {\n const data = await load({ data: { _splat: splat, search: searchToRecord(searchStr) } })\n if (data?._redirect) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error -- TanStack Router requires throwing redirect objects\n throw redirect({ to: data._redirect })\n }\n return data\n}\n\nfunction AdminPage() {\n // RSC Flight payload — render directly. Key by the loader-derived `routeKey`\n // (not `location.pathname`, which updates before `useLoaderData` during a\n // transition and would remount with the previous payload) so navigating to a\n // different admin page remounts the view, mirroring Next route-segment\n // semantics. Search params are excluded so search-only changes reconcile in place.\n const data = useLoaderData({ strict: false })\n return <Fragment key={data?.routeKey}>{data?.rscPayload}</Fragment>\n}\n\nfunction AdminNotFound(props: { data?: { routeKey?: string; rscPayload?: ReactNode } }) {\n const rscPayload = props?.data?.rscPayload\n if (!rscPayload) {\n return <NotFoundClient />\n }\n return <Fragment key={props?.data?.routeKey}>{rscPayload}</Fragment>\n}\n\n/**\n * Route options for the admin splat route (`/_payload/admin/$`). Renders Payload's\n * server-built NotFound page (shipped via the `notFound()` error's\n * `data.rscPayload`) for unknown/access-denied routes, falling back to the bare\n * client view.\n */\nexport function payloadAdminSplatRoute({ load }: { load: AdminLoad }) {\n return {\n component: AdminPage,\n head: ({ loaderData }: { loaderData?: any }) => getAdminMeta(loaderData?.metadata),\n //
|
|
1
|
+
{"version":3,"sources":["../../src/routes/adminRoutes.tsx"],"sourcesContent":["'use client'\n\nimport { NotFoundClient } from '@payloadcms/ui'\nimport { notFound, redirect, useLoaderData } from '@tanstack/react-router'\nimport { Fragment, type ReactNode } from 'react'\n\nimport { getAdminMeta } from '../utilities/meta.js'\n\n/**\n * Loader supplied by the app — a TanStack Start `createServerFn` that delegates\n * to `loadAdminPage`. Typed loosely because the server-fn's call signature is\n * generated by the Start compiler.\n */\nexport type AdminLoad = (opts: {\n data: { _splat: string; search: Record<string, string | string[]> }\n}) => Promise<any>\n\nconst searchToRecord = (searchStr: string): Record<string, string | string[]> =>\n Object.fromEntries(new URLSearchParams(searchStr)) as Record<string, string | string[]>\n\nconst runLoader = async (load: AdminLoad, splat: string, searchStr: string) => {\n const data = await load({ data: { _splat: splat, search: searchToRecord(searchStr) } })\n if (data?._redirect) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error -- TanStack Router requires throwing redirect objects\n throw redirect({ to: data._redirect })\n }\n return data\n}\n\nfunction AdminPage() {\n // RSC Flight payload — render directly. Key by the loader-derived `routeKey`\n // (not `location.pathname`, which updates before `useLoaderData` during a\n // transition and would remount with the previous payload) so navigating to a\n // different admin page remounts the view, mirroring Next route-segment\n // semantics. Search params are excluded so search-only changes reconcile in place.\n const data = useLoaderData({ strict: false })\n return <Fragment key={data?.routeKey}>{data?.rscPayload}</Fragment>\n}\n\nfunction AdminNotFound(props: { data?: { routeKey?: string; rscPayload?: ReactNode } }) {\n const rscPayload = props?.data?.rscPayload\n if (!rscPayload) {\n return <NotFoundClient />\n }\n return <Fragment key={props?.data?.routeKey}>{rscPayload}</Fragment>\n}\n\n/**\n * Route options for the admin splat route (`/_payload/admin/$`). Renders Payload's\n * server-built NotFound page (shipped via the `notFound()` error's\n * `data.rscPayload`) for unknown/access-denied routes, falling back to the bare\n * client view.\n */\nexport function payloadAdminSplatRoute({ load }: { load: AdminLoad }) {\n return {\n component: AdminPage,\n head: ({ loaderData }: { loaderData?: any }) => getAdminMeta(loaderData?.metadata),\n // `staleReloadMode: 'blocking'` (a property of the loader *object*, not a\n // sibling route option — router-core only reads it off a non-function loader)\n // makes stale-match revalidation await the fresh loader before committing,\n // instead of the default background SWR that flashes the pre-navigation list\n // (e.g. a just-created doc missing) until the reload lands.\n loader: {\n handler: async ({ location, params }: { location: any; params: any }) => {\n const data = await runLoader(load, params._splat ?? '', location.searchStr)\n if (data?._notFound) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error -- TanStack Router requires throwing notFound objects\n throw notFound({ data: { routeKey: data.routeKey, rscPayload: data.rscPayload } })\n }\n return data\n },\n staleReloadMode: 'blocking',\n },\n // Surface query params in `loaderDeps` so `?locale=es` re-runs the loader.\n loaderDeps: ({ search }: { search: Record<string, unknown> }) => ({\n searchKey: JSON.stringify(search),\n }),\n notFoundComponent: AdminNotFound,\n validateSearch: (search: Record<string, unknown>) => search,\n }\n}\n\n/**\n * Route options for the admin index route (`/_payload/admin/`). Same loader as the\n * splat route but throws a bare `notFound()` (no rscPayload) on miss.\n */\nexport function payloadAdminIndexRoute({ load }: { load: AdminLoad }) {\n return {\n component: AdminPage,\n head: ({ loaderData }: { loaderData?: any }) => getAdminMeta(loaderData?.metadata),\n loader: {\n handler: async ({ location }: { location: any }) => {\n const data = await runLoader(load, '', location.searchStr)\n if (data?._notFound) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error -- TanStack Router requires throwing notFound objects\n throw notFound()\n }\n return data\n },\n staleReloadMode: 'blocking',\n },\n loaderDeps: ({ search }: { search: Record<string, unknown> }) => ({\n searchKey: JSON.stringify(search),\n }),\n validateSearch: (search: Record<string, unknown>) => search,\n }\n}\n"],"names":["NotFoundClient","notFound","redirect","useLoaderData","Fragment","getAdminMeta","searchToRecord","searchStr","Object","fromEntries","URLSearchParams","runLoader","load","splat","data","_splat","search","_redirect","to","AdminPage","strict","rscPayload","routeKey","AdminNotFound","props","payloadAdminSplatRoute","component","head","loaderData","metadata","loader","handler","location","params","_notFound","staleReloadMode","loaderDeps","searchKey","JSON","stringify","notFoundComponent","validateSearch","payloadAdminIndexRoute"],"mappings":"AAAA;;AAEA,SAASA,cAAc,QAAQ,iBAAgB;AAC/C,SAASC,QAAQ,EAAEC,QAAQ,EAAEC,aAAa,QAAQ,yBAAwB;AAC1E,SAASC,QAAQ,QAAwB,QAAO;AAEhD,SAASC,YAAY,QAAQ,uBAAsB;AAWnD,MAAMC,iBAAiB,CAACC,YACtBC,OAAOC,WAAW,CAAC,IAAIC,gBAAgBH;AAEzC,MAAMI,YAAY,OAAOC,MAAiBC,OAAeN;IACvD,MAAMO,OAAO,MAAMF,KAAK;QAAEE,MAAM;YAAEC,QAAQF;YAAOG,QAAQV,eAAeC;QAAW;IAAE;IACrF,IAAIO,MAAMG,WAAW;QACnB,qHAAqH;QACrH,MAAMf,SAAS;YAAEgB,IAAIJ,KAAKG,SAAS;QAAC;IACtC;IACA,OAAOH;AACT;AAEA,SAASK;IACP,6EAA6E;IAC7E,0EAA0E;IAC1E,6EAA6E;IAC7E,uEAAuE;IACvE,mFAAmF;IACnF,MAAML,OAAOX,cAAc;QAAEiB,QAAQ;IAAM;IAC3C,qBAAO,KAAChB;kBAA+BU,MAAMO;OAAvBP,MAAMQ;AAC9B;AAEA,SAASC,cAAcC,KAA+D;IACpF,MAAMH,aAAaG,OAAOV,MAAMO;IAChC,IAAI,CAACA,YAAY;QACf,qBAAO,KAACrB;IACV;IACA,qBAAO,KAACI;kBAAsCiB;OAAxBG,OAAOV,MAAMQ;AACrC;AAEA;;;;;CAKC,GACD,OAAO,SAASG,uBAAuB,EAAEb,IAAI,EAAuB;IAClE,OAAO;QACLc,WAAWP;QACXQ,MAAM,CAAC,EAAEC,UAAU,EAAwB,GAAKvB,aAAauB,YAAYC;QACzE,0EAA0E;QAC1E,8EAA8E;QAC9E,2EAA2E;QAC3E,6EAA6E;QAC7E,4DAA4D;QAC5DC,QAAQ;YACNC,SAAS,OAAO,EAAEC,QAAQ,EAAEC,MAAM,EAAkC;gBAClE,MAAMnB,OAAO,MAAMH,UAAUC,MAAMqB,OAAOlB,MAAM,IAAI,IAAIiB,SAASzB,SAAS;gBAC1E,IAAIO,MAAMoB,WAAW;oBACnB,qHAAqH;oBACrH,MAAMjC,SAAS;wBAAEa,MAAM;4BAAEQ,UAAUR,KAAKQ,QAAQ;4BAAED,YAAYP,KAAKO,UAAU;wBAAC;oBAAE;gBAClF;gBACA,OAAOP;YACT;YACAqB,iBAAiB;QACnB;QACA,2EAA2E;QAC3EC,YAAY,CAAC,EAAEpB,MAAM,EAAuC,GAAM,CAAA;gBAChEqB,WAAWC,KAAKC,SAAS,CAACvB;YAC5B,CAAA;QACAwB,mBAAmBjB;QACnBkB,gBAAgB,CAACzB,SAAoCA;IACvD;AACF;AAEA;;;CAGC,GACD,OAAO,SAAS0B,uBAAuB,EAAE9B,IAAI,EAAuB;IAClE,OAAO;QACLc,WAAWP;QACXQ,MAAM,CAAC,EAAEC,UAAU,EAAwB,GAAKvB,aAAauB,YAAYC;QACzEC,QAAQ;YACNC,SAAS,OAAO,EAAEC,QAAQ,EAAqB;gBAC7C,MAAMlB,OAAO,MAAMH,UAAUC,MAAM,IAAIoB,SAASzB,SAAS;gBACzD,IAAIO,MAAMoB,WAAW;oBACnB,qHAAqH;oBACrH,MAAMjC;gBACR;gBACA,OAAOa;YACT;YACAqB,iBAAiB;QACnB;QACAC,YAAY,CAAC,EAAEpB,MAAM,EAAuC,GAAM,CAAA;gBAChEqB,WAAWC,KAAKC,SAAS,CAACvB;YAC5B,CAAA;QACAyB,gBAAgB,CAACzB,SAAoCA;IACvD;AACF"}
|
|
@@ -1,33 +1,29 @@
|
|
|
1
1
|
import type { SanitizedConfig } from 'payload';
|
|
2
|
+
type ApiRouteHandler = (ctx: {
|
|
3
|
+
request: Request;
|
|
4
|
+
}) => Promise<Response>;
|
|
2
5
|
/**
|
|
3
|
-
*
|
|
4
|
-
* app supplies `getConfig` (an `@payload-config`
|
|
5
|
-
* resolve the consumer's config.
|
|
6
|
+
* Builds the method handlers for the Payload REST/GraphQL catch-all
|
|
7
|
+
* (`/_payload/api/$`). The app supplies `getConfig` (an `@payload-config`
|
|
8
|
+
* import) since the package cannot resolve the consumer's config.
|
|
9
|
+
*
|
|
10
|
+
* Spread the result into a literal `server.handlers` key so TanStack Start's
|
|
11
|
+
* client compiler can statically see — and prune — the server-only route:
|
|
12
|
+
*
|
|
13
|
+
* ```ts
|
|
14
|
+
* export const Route = createFileRoute('/_payload/api/$')({
|
|
15
|
+
* server: {
|
|
16
|
+
* handlers: payloadApiHandlers({ getConfig: async () => (await import('@payload-config')).default }),
|
|
17
|
+
* },
|
|
18
|
+
* })
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* The compiler only strips a literal `server:` key from a route-options object
|
|
22
|
+
* expression; wrapping the whole options object in a factory call hides the
|
|
23
|
+
* key, leaking the config graph into the client bundle.
|
|
6
24
|
*/
|
|
7
|
-
export declare function
|
|
25
|
+
export declare function payloadApiHandlers({ getConfig, }: {
|
|
8
26
|
getConfig: () => Promise<SanitizedConfig>;
|
|
9
|
-
}):
|
|
10
|
-
|
|
11
|
-
handlers: {
|
|
12
|
-
DELETE: ({ request }: {
|
|
13
|
-
request: Request;
|
|
14
|
-
}) => Promise<Response>;
|
|
15
|
-
GET: ({ request }: {
|
|
16
|
-
request: Request;
|
|
17
|
-
}) => Promise<Response>;
|
|
18
|
-
OPTIONS: ({ request }: {
|
|
19
|
-
request: Request;
|
|
20
|
-
}) => Promise<Response>;
|
|
21
|
-
PATCH: ({ request }: {
|
|
22
|
-
request: Request;
|
|
23
|
-
}) => Promise<Response>;
|
|
24
|
-
POST: ({ request }: {
|
|
25
|
-
request: Request;
|
|
26
|
-
}) => Promise<Response>;
|
|
27
|
-
PUT: ({ request }: {
|
|
28
|
-
request: Request;
|
|
29
|
-
}) => Promise<Response>;
|
|
30
|
-
};
|
|
31
|
-
};
|
|
32
|
-
};
|
|
27
|
+
}): Record<'DELETE' | 'GET' | 'OPTIONS' | 'PATCH' | 'POST' | 'PUT', ApiRouteHandler>;
|
|
28
|
+
export {};
|
|
33
29
|
//# sourceMappingURL=apiRoute.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apiRoute.d.ts","sourceRoot":"","sources":["../../src/routes/apiRoute.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAE9C
|
|
1
|
+
{"version":3,"file":"apiRoute.d.ts","sourceRoot":"","sources":["../../src/routes/apiRoute.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAE9C,KAAK,eAAe,GAAG,CAAC,GAAG,EAAE;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;AAEvE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,SAAS,GACV,EAAE;IACD,SAAS,EAAE,MAAM,OAAO,CAAC,eAAe,CAAC,CAAA;CAC1C,GAAG,MAAM,CAAC,QAAQ,GAAG,KAAK,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,EAAE,eAAe,CAAC,CAcnF"}
|
package/dist/routes/apiRoute.js
CHANGED
|
@@ -1,8 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* app supplies `getConfig` (an `@payload-config`
|
|
4
|
-
* resolve the consumer's config.
|
|
5
|
-
|
|
2
|
+
* Builds the method handlers for the Payload REST/GraphQL catch-all
|
|
3
|
+
* (`/_payload/api/$`). The app supplies `getConfig` (an `@payload-config`
|
|
4
|
+
* import) since the package cannot resolve the consumer's config.
|
|
5
|
+
*
|
|
6
|
+
* Spread the result into a literal `server.handlers` key so TanStack Start's
|
|
7
|
+
* client compiler can statically see — and prune — the server-only route:
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* export const Route = createFileRoute('/_payload/api/$')({
|
|
11
|
+
* server: {
|
|
12
|
+
* handlers: payloadApiHandlers({ getConfig: async () => (await import('@payload-config')).default }),
|
|
13
|
+
* },
|
|
14
|
+
* })
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* The compiler only strips a literal `server:` key from a route-options object
|
|
18
|
+
* expression; wrapping the whole options object in a factory call hides the
|
|
19
|
+
* key, leaking the config graph into the client bundle.
|
|
20
|
+
*/ export function payloadApiHandlers({ getConfig }) {
|
|
6
21
|
const handler = async ({ request })=>{
|
|
7
22
|
const { handleAPIRoute } = await import('../utilities/handleAPIRoute.js');
|
|
8
23
|
return handleAPIRoute({
|
|
@@ -11,16 +26,12 @@
|
|
|
11
26
|
});
|
|
12
27
|
};
|
|
13
28
|
return {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
POST: handler,
|
|
21
|
-
PUT: handler
|
|
22
|
-
}
|
|
23
|
-
}
|
|
29
|
+
DELETE: handler,
|
|
30
|
+
GET: handler,
|
|
31
|
+
OPTIONS: handler,
|
|
32
|
+
PATCH: handler,
|
|
33
|
+
POST: handler,
|
|
34
|
+
PUT: handler
|
|
24
35
|
};
|
|
25
36
|
}
|
|
26
37
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/routes/apiRoute.ts"],"sourcesContent":["import type { SanitizedConfig } from 'payload'\n\n/**\n *
|
|
1
|
+
{"version":3,"sources":["../../src/routes/apiRoute.ts"],"sourcesContent":["import type { SanitizedConfig } from 'payload'\n\ntype ApiRouteHandler = (ctx: { request: Request }) => Promise<Response>\n\n/**\n * Builds the method handlers for the Payload REST/GraphQL catch-all\n * (`/_payload/api/$`). The app supplies `getConfig` (an `@payload-config`\n * import) since the package cannot resolve the consumer's config.\n *\n * Spread the result into a literal `server.handlers` key so TanStack Start's\n * client compiler can statically see — and prune — the server-only route:\n *\n * ```ts\n * export const Route = createFileRoute('/_payload/api/$')({\n * server: {\n * handlers: payloadApiHandlers({ getConfig: async () => (await import('@payload-config')).default }),\n * },\n * })\n * ```\n *\n * The compiler only strips a literal `server:` key from a route-options object\n * expression; wrapping the whole options object in a factory call hides the\n * key, leaking the config graph into the client bundle.\n */\nexport function payloadApiHandlers({\n getConfig,\n}: {\n getConfig: () => Promise<SanitizedConfig>\n}): Record<'DELETE' | 'GET' | 'OPTIONS' | 'PATCH' | 'POST' | 'PUT', ApiRouteHandler> {\n const handler: ApiRouteHandler = async ({ request }) => {\n const { handleAPIRoute } = await import('../utilities/handleAPIRoute.js')\n return handleAPIRoute({ config: await getConfig(), request })\n }\n\n return {\n DELETE: handler,\n GET: handler,\n OPTIONS: handler,\n PATCH: handler,\n POST: handler,\n PUT: handler,\n }\n}\n"],"names":["payloadApiHandlers","getConfig","handler","request","handleAPIRoute","config","DELETE","GET","OPTIONS","PATCH","POST","PUT"],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;CAmBC,GACD,OAAO,SAASA,mBAAmB,EACjCC,SAAS,EAGV;IACC,MAAMC,UAA2B,OAAO,EAAEC,OAAO,EAAE;QACjD,MAAM,EAAEC,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC;QACxC,OAAOA,eAAe;YAAEC,QAAQ,MAAMJ;YAAaE;QAAQ;IAC7D;IAEA,OAAO;QACLG,QAAQJ;QACRK,KAAKL;QACLM,SAASN;QACTO,OAAOP;QACPQ,MAAMR;QACNS,KAAKT;IACP;AACF"}
|
|
@@ -18,6 +18,9 @@ export declare function payloadLayoutRoute({ load, serverFunction, }: {
|
|
|
18
18
|
serverFunction: ComponentProps<typeof RootProvider>['serverFunction'];
|
|
19
19
|
}): {
|
|
20
20
|
component: () => import("react").JSX.Element;
|
|
21
|
-
loader:
|
|
21
|
+
loader: {
|
|
22
|
+
handler: () => Promise<Record<string, unknown>>;
|
|
23
|
+
staleReloadMode: string;
|
|
24
|
+
};
|
|
22
25
|
};
|
|
23
26
|
//# sourceMappingURL=layoutRoute.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layoutRoute.d.ts","sourceRoot":"","sources":["../../src/routes/layoutRoute.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAA;AAE3C,OAAO,EAAe,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAK1D;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;AAE/D;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,IAAI,EACJ,cAAc,GACf,EAAE;IACD,IAAI,EAAE,UAAU,CAAA;IAChB,cAAc,EAAE,cAAc,CAAC,OAAO,YAAY,CAAC,CAAC,gBAAgB,CAAC,CAAA;CACtE
|
|
1
|
+
{"version":3,"file":"layoutRoute.d.ts","sourceRoot":"","sources":["../../src/routes/layoutRoute.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAA;AAE3C,OAAO,EAAe,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAK1D;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;AAE/D;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,IAAI,EACJ,cAAc,GACf,EAAE;IACD,IAAI,EAAE,UAAU,CAAA;IAChB,cAAc,EAAE,cAAc,CAAC,OAAO,YAAY,CAAC,CAAC,gBAAgB,CAAC,CAAA;CACtE;;;;;;EAwCA"}
|
|
@@ -42,9 +42,15 @@ import { TanStackRouterAdapter } from '../elements/RouterAdapter/index.js';
|
|
|
42
42
|
]
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
|
+
// `staleReloadMode` lives on the loader *object* — router-core only reads it
|
|
46
|
+
// off a non-function loader — so stale-match revalidation blocks on the fresh
|
|
47
|
+
// loader instead of flashing stale layout data via the default background SWR.
|
|
45
48
|
return {
|
|
46
49
|
component: PayloadLayout,
|
|
47
|
-
loader:
|
|
50
|
+
loader: {
|
|
51
|
+
handler: ()=>load(),
|
|
52
|
+
staleReloadMode: 'blocking'
|
|
53
|
+
}
|
|
48
54
|
};
|
|
49
55
|
}
|
|
50
56
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/routes/layoutRoute.tsx"],"sourcesContent":["'use client'\n\nimport type { ComponentProps } from 'react'\n\nimport { ProgressBar, RootProvider } from '@payloadcms/ui'\nimport { Outlet, useLoaderData } from '@tanstack/react-router'\n\nimport { TanStackRouterAdapter } from '../elements/RouterAdapter/index.js'\n\n/**\n * Loader supplied by the app — a TanStack Start `createServerFn` that delegates\n * to `loadLayoutData`. Typed loosely because the server-fn's call signature is\n * generated by the Start compiler.\n */\nexport type LayoutLoad = () => Promise<Record<string, unknown>>\n\n/**\n * Route options for the Payload admin layout (`/_payload`). Maps the layout\n * loader data onto `RootProvider` and renders the admin chrome (progress bar,\n * custom-provider tree or router `<Outlet />`, portal mount). The app supplies\n * `load` (the layout-data server fn) and `serverFunction` (the server-function\n * client wired into `RootProvider`); everything else is adapter-owned.\n */\nexport function payloadLayoutRoute({\n load,\n serverFunction,\n}: {\n load: LayoutLoad\n serverFunction: ComponentProps<typeof RootProvider>['serverFunction']\n}) {\n function PayloadLayout() {\n const data = useLoaderData({ strict: false })\n\n return (\n <>\n <RootProvider\n config={data.clientConfig}\n dateFNSKey={data.dateFNSKey}\n fallbackLang={data.fallbackLang}\n highContrastMode={false}\n isNavOpen={data.isNavOpen}\n languageCode={data.languageCode}\n languageOptions={data.languageOptions}\n locale={data.locale}\n permissions={data.user ? data.permissions : null}\n RouterAdapter={TanStackRouterAdapter}\n serverFunction={serverFunction}\n theme={data.theme}\n translations={data.translations}\n user={data.user}\n >\n <ProgressBar />\n {/* `data.providers` is the custom-provider tree (config.admin.components.providers)\n already wrapping the router <Outlet />; falls back to a bare <Outlet /> when\n no custom providers are configured. */}\n {data.providers ?? <Outlet />}\n </RootProvider>\n <div id=\"portal\" />\n </>\n )\n }\n\n return {
|
|
1
|
+
{"version":3,"sources":["../../src/routes/layoutRoute.tsx"],"sourcesContent":["'use client'\n\nimport type { ComponentProps } from 'react'\n\nimport { ProgressBar, RootProvider } from '@payloadcms/ui'\nimport { Outlet, useLoaderData } from '@tanstack/react-router'\n\nimport { TanStackRouterAdapter } from '../elements/RouterAdapter/index.js'\n\n/**\n * Loader supplied by the app — a TanStack Start `createServerFn` that delegates\n * to `loadLayoutData`. Typed loosely because the server-fn's call signature is\n * generated by the Start compiler.\n */\nexport type LayoutLoad = () => Promise<Record<string, unknown>>\n\n/**\n * Route options for the Payload admin layout (`/_payload`). Maps the layout\n * loader data onto `RootProvider` and renders the admin chrome (progress bar,\n * custom-provider tree or router `<Outlet />`, portal mount). The app supplies\n * `load` (the layout-data server fn) and `serverFunction` (the server-function\n * client wired into `RootProvider`); everything else is adapter-owned.\n */\nexport function payloadLayoutRoute({\n load,\n serverFunction,\n}: {\n load: LayoutLoad\n serverFunction: ComponentProps<typeof RootProvider>['serverFunction']\n}) {\n function PayloadLayout() {\n const data = useLoaderData({ strict: false })\n\n return (\n <>\n <RootProvider\n config={data.clientConfig}\n dateFNSKey={data.dateFNSKey}\n fallbackLang={data.fallbackLang}\n highContrastMode={false}\n isNavOpen={data.isNavOpen}\n languageCode={data.languageCode}\n languageOptions={data.languageOptions}\n locale={data.locale}\n permissions={data.user ? data.permissions : null}\n RouterAdapter={TanStackRouterAdapter}\n serverFunction={serverFunction}\n theme={data.theme}\n translations={data.translations}\n user={data.user}\n >\n <ProgressBar />\n {/* `data.providers` is the custom-provider tree (config.admin.components.providers)\n already wrapping the router <Outlet />; falls back to a bare <Outlet /> when\n no custom providers are configured. */}\n {data.providers ?? <Outlet />}\n </RootProvider>\n <div id=\"portal\" />\n </>\n )\n }\n\n // `staleReloadMode` lives on the loader *object* — router-core only reads it\n // off a non-function loader — so stale-match revalidation blocks on the fresh\n // loader instead of flashing stale layout data via the default background SWR.\n return {\n component: PayloadLayout,\n loader: { handler: () => load(), staleReloadMode: 'blocking' },\n }\n}\n"],"names":["ProgressBar","RootProvider","Outlet","useLoaderData","TanStackRouterAdapter","payloadLayoutRoute","load","serverFunction","PayloadLayout","data","strict","config","clientConfig","dateFNSKey","fallbackLang","highContrastMode","isNavOpen","languageCode","languageOptions","locale","permissions","user","RouterAdapter","theme","translations","providers","div","id","component","loader","handler","staleReloadMode"],"mappings":"AAAA;;AAIA,SAASA,WAAW,EAAEC,YAAY,QAAQ,iBAAgB;AAC1D,SAASC,MAAM,EAAEC,aAAa,QAAQ,yBAAwB;AAE9D,SAASC,qBAAqB,QAAQ,qCAAoC;AAS1E;;;;;;CAMC,GACD,OAAO,SAASC,mBAAmB,EACjCC,IAAI,EACJC,cAAc,EAIf;IACC,SAASC;QACP,MAAMC,OAAON,cAAc;YAAEO,QAAQ;QAAM;QAE3C,qBACE;;8BACE,MAACT;oBACCU,QAAQF,KAAKG,YAAY;oBACzBC,YAAYJ,KAAKI,UAAU;oBAC3BC,cAAcL,KAAKK,YAAY;oBAC/BC,kBAAkB;oBAClBC,WAAWP,KAAKO,SAAS;oBACzBC,cAAcR,KAAKQ,YAAY;oBAC/BC,iBAAiBT,KAAKS,eAAe;oBACrCC,QAAQV,KAAKU,MAAM;oBACnBC,aAAaX,KAAKY,IAAI,GAAGZ,KAAKW,WAAW,GAAG;oBAC5CE,eAAelB;oBACfG,gBAAgBA;oBAChBgB,OAAOd,KAAKc,KAAK;oBACjBC,cAAcf,KAAKe,YAAY;oBAC/BH,MAAMZ,KAAKY,IAAI;;sCAEf,KAACrB;wBAIAS,KAAKgB,SAAS,kBAAI,KAACvB;;;8BAEtB,KAACwB;oBAAIC,IAAG;;;;IAGd;IAEA,6EAA6E;IAC7E,8EAA8E;IAC9E,+EAA+E;IAC/E,OAAO;QACLC,WAAWpB;QACXqB,QAAQ;YAAEC,SAAS,IAAMxB;YAAQyB,iBAAiB;QAAW;IAC/D;AACF"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Returns the default output path for the generated import map file
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* so the import map is placed there.
|
|
2
|
+
* Returns the default output path for the generated import map file in a
|
|
3
|
+
* TanStack Start project. Matches the `app/_payload/` convention that Payload's
|
|
4
|
+
* import map auto-discovery probes, so the file is found without a custom
|
|
5
|
+
* `admin.importMap.importMapFile` override.
|
|
7
6
|
*/
|
|
8
7
|
export declare function getImportMapOutputPath(rootDir?: string): string;
|
|
9
8
|
//# sourceMappingURL=importMap.server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"importMap.server.d.ts","sourceRoot":"","sources":["../../src/utilities/importMap.server.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"importMap.server.d.ts","sourceRoot":"","sources":["../../src/utilities/importMap.server.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAE/D"}
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
/**
|
|
3
|
-
* Returns the default output path for the generated import map file
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* so the import map is placed there.
|
|
3
|
+
* Returns the default output path for the generated import map file in a
|
|
4
|
+
* TanStack Start project. Matches the `app/_payload/` convention that Payload's
|
|
5
|
+
* import map auto-discovery probes, so the file is found without a custom
|
|
6
|
+
* `admin.importMap.importMapFile` override.
|
|
8
7
|
*/ export function getImportMapOutputPath(rootDir) {
|
|
9
|
-
return path.resolve(rootDir || process.cwd(), '
|
|
8
|
+
return path.resolve(rootDir || process.cwd(), 'app', '_payload', 'importMap.js');
|
|
10
9
|
}
|
|
11
10
|
|
|
12
11
|
//# sourceMappingURL=importMap.server.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utilities/importMap.server.ts"],"sourcesContent":["import path from 'node:path'\n\n/**\n * Returns the default output path for the generated import map file
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/importMap.server.ts"],"sourcesContent":["import path from 'node:path'\n\n/**\n * Returns the default output path for the generated import map file in a\n * TanStack Start project. Matches the `app/_payload/` convention that Payload's\n * import map auto-discovery probes, so the file is found without a custom\n * `admin.importMap.importMapFile` override.\n */\nexport function getImportMapOutputPath(rootDir?: string): string {\n return path.resolve(rootDir || process.cwd(), 'app', '_payload', 'importMap.js')\n}\n"],"names":["path","getImportMapOutputPath","rootDir","resolve","process","cwd"],"mappings":"AAAA,OAAOA,UAAU,YAAW;AAE5B;;;;;CAKC,GACD,OAAO,SAASC,uBAAuBC,OAAgB;IACrD,OAAOF,KAAKG,OAAO,CAACD,WAAWE,QAAQC,GAAG,IAAI,OAAO,YAAY;AACnE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadAdminPage.d.ts","sourceRoot":"","sources":["../../src/utilities/loadAdminPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAc,eAAe,EAAE,MAAM,SAAS,CAAA;AAIrE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAMlD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,eAAe,CAAA;IACvB,SAAS,EAAE,SAAS,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAA;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,mBAAmB,GAC3B;IAAE,SAAS,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,GACpE;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,GACrB;IACE,QAAQ,EAAE,iBAAiB,CAAA;IAC3B;;;;;;;;;;OAUG;IACH,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,KAAK,CAAC,SAAS,CAAA;CAC5B,CAAA;AA0FL;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,aAAa,CAAC,EAClC,MAAM,EACN,SAAS,EACT,MAAM,EACN,KAAK,GACN,EAAE,iBAAiB,GAAG,OAAO,CAAC,mBAAmB,CAAC,
|
|
1
|
+
{"version":3,"file":"loadAdminPage.d.ts","sourceRoot":"","sources":["../../src/utilities/loadAdminPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAc,eAAe,EAAE,MAAM,SAAS,CAAA;AAIrE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAMlD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,eAAe,CAAA;IACvB,SAAS,EAAE,SAAS,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAA;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,mBAAmB,GAC3B;IAAE,SAAS,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,GACpE;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,GACrB;IACE,QAAQ,EAAE,iBAAiB,CAAA;IAC3B;;;;;;;;;;OAUG;IACH,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,KAAK,CAAC,SAAS,CAAA;CAC5B,CAAA;AA0FL;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,aAAa,CAAC,EAClC,MAAM,EACN,SAAS,EACT,MAAM,EACN,KAAK,GACN,EAAE,iBAAiB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAoJlD"}
|
|
@@ -169,6 +169,19 @@ const resolveTitle = (title)=>{
|
|
|
169
169
|
searchParams: Promise.resolve(searchParams)
|
|
170
170
|
});
|
|
171
171
|
const rscPayload = await renderServerComponent(node);
|
|
172
|
+
// The server-function (client-nav RPC) path returns the flight stream unread —
|
|
173
|
+
// unlike the router/SSR path, which awaits a decode that drives the render to
|
|
174
|
+
// completion. So streamed side effects (e.g. DocumentView's autosave-create
|
|
175
|
+
// `server.redirect()`) haven't run yet and `nav` is empty. Buffer the stream to
|
|
176
|
+
// completion to force the render (populating `nav`), then hand the client a fresh
|
|
177
|
+
// replayable stream from that buffer.
|
|
178
|
+
if (!nav.type) {
|
|
179
|
+
const wrapper = rscPayload[Symbol.for('tanstack.rsc.stream')];
|
|
180
|
+
if (typeof wrapper?.createReplayStream === 'function') {
|
|
181
|
+
const buffer = await new Response(wrapper.createReplayStream()).arrayBuffer();
|
|
182
|
+
wrapper.createReplayStream = ()=>new Response(buffer).body;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
172
185
|
// Navigation thrown deep inside a streamed view component (e.g. access
|
|
173
186
|
// denied → notFound, already-authenticated → redirect) is swallowed into
|
|
174
187
|
// the RSC stream and never rejects the render. Honor it from the holder,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utilities/loadAdminPage.tsx"],"sourcesContent":["import type { ImportMap, MetaConfig, SanitizedConfig } from 'payload'\n\nimport { renderServerComponent } from '@tanstack/react-start/rsc'\n\nimport type { AdminPageMetadata } from './meta.js'\n\nimport { getRequestI18n } from './getRequestI18n.server.js'\nimport { initReq } from './initReq.server.js'\nimport { createPageRenderServerAdapter } from './serverAdapter.server.js'\n\nexport type LoadAdminPageArgs = {\n config: SanitizedConfig\n importMap: ImportMap\n search?: Record<string, string | string[]>\n splat?: string\n}\n\nexport type LoadAdminPageResult =\n | { _notFound: true; routeKey?: string; rscPayload?: React.ReactNode }\n | { _redirect: string }\n | {\n metadata: AdminPageMetadata\n /**\n * Stable identity for this rendered route (the splat, i.e. the path\n * after `/admin/`). The client keys the rendered subtree by this so the\n * view remounts exactly when a new payload arrives. Keying by\n * `location.pathname` instead races: the pathname updates before\n * `useLoaderData()` during a transition, so the subtree would remount\n * with the *previous* payload and then reconcile the fresh payload in\n * place — leaving client providers (DocumentInfo, etc.) holding stale\n * `useState` values from the prior document. Search params are excluded\n * so search-only changes (e.g. list-view filtering) reconcile in place.\n */\n routeKey: string\n rscPayload: React.ReactNode\n }\n\nconst resolveTitle = (title: MetaConfig['title']): string | undefined => {\n if (!title) {\n return undefined\n }\n if (typeof title === 'string') {\n return title\n }\n if ('absolute' in title) {\n return title.absolute\n }\n return title.default\n}\n\n/**\n * Flattens the framework-agnostic `MetaConfig` (Next.js `Metadata` shape) into\n * the plain, serializable `AdminPageMetadata` the route loader ships to the\n * client. The full `MetaConfig` carries a `URL` `metadataBase`, functions and\n * other non-serializable values that seroval cannot cross the wire, so only the\n * fields `getAdminMeta` renders are extracted.\n */\nconst toAdminPageMetadata = (meta: MetaConfig): AdminPageMetadata => {\n const og = meta.openGraph as\n | {\n description?: unknown\n images?: unknown\n siteName?: unknown\n title?: unknown\n }\n | undefined\n\n const rawImages = og?.images\n const imagesArray = rawImages ? (Array.isArray(rawImages) ? rawImages : [rawImages]) : []\n const images = imagesArray\n .map((image: any) =>\n typeof image === 'string'\n ? { url: image }\n : image?.url\n ? { alt: image.alt, height: image.height, url: String(image.url), width: image.width }\n : undefined,\n )\n .filter(Boolean) as NonNullable<AdminPageMetadata['openGraph']>['images']\n\n const rawIcons = meta.icons as any\n const iconList = Array.isArray(rawIcons)\n ? rawIcons\n : rawIcons && typeof rawIcons === 'object' && Array.isArray(rawIcons.icon)\n ? rawIcons.icon\n : []\n const icons = iconList\n .map((icon: any) =>\n typeof icon === 'string'\n ? { rel: 'icon', url: icon }\n : icon?.url\n ? {\n type: icon.type,\n media: icon.media,\n rel: icon.rel ?? 'icon',\n sizes: icon.sizes,\n url: String(icon.url),\n }\n : undefined,\n )\n .filter(Boolean) as AdminPageMetadata['icons']\n\n const keywords = meta.keywords\n\n return {\n description: typeof meta.description === 'string' ? meta.description : undefined,\n icons: icons?.length ? icons : undefined,\n keywords:\n typeof keywords === 'string'\n ? keywords\n : Array.isArray(keywords)\n ? keywords.join(', ')\n : undefined,\n openGraph: og\n ? {\n description: typeof og.description === 'string' ? og.description : undefined,\n images: images?.length ? images : undefined,\n siteName: typeof og.siteName === 'string' ? og.siteName : undefined,\n title: typeof og.title === 'string' ? og.title : undefined,\n }\n : undefined,\n robots: typeof meta.robots === 'string' ? meta.robots : undefined,\n title: resolveTitle(meta.title),\n }\n}\n\n/**\n * Renders an admin page for TanStack Start and returns a serializable loader\n * result. The framework adapter wraps this in a `createServerFn` that supplies\n * the app's `config` and generated `importMap`.\n *\n * 1. Initializes the Payload request via the shared `renderRoot` orchestrator\n * from `@payloadcms/ui`, passing a TanStack-bound `initReq`. The injected\n * page-render `ServerAdapter` records navigation intent and throws the\n * framework-agnostic error contract.\n * 2. Pipes the resulting React server tree through `renderServerComponent`\n * to produce a Flight payload the client consumes directly.\n * 3. Resolves page metadata via the same shared `generatePageMetadata`\n * Next.js uses, returning plain serializable strings for `head()`.\n *\n * Navigation surfaces two ways and both become a `_notFound` / `_redirect`\n * sentinel the route loader re-throws as native TanStack nav:\n * - thrown during `renderRoot` orchestration (e.g. the login redirect) → caught\n * by the try/catch below;\n * - thrown deep inside a streamed view component (e.g. `DocumentView` access\n * denied, `LoginView` already-authenticated) → swallowed into the RSC stream,\n * so it's read from the `nav` holder after `renderServerComponent` resolves.\n */\nexport async function loadAdminPage({\n config,\n importMap,\n search,\n splat,\n}: LoadAdminPageArgs): Promise<LoadAdminPageResult> {\n const { renderRoot } = await import('@payloadcms/ui/views/Root')\n const { defaultAdminViews } = await import('@payloadcms/ui/views/Root/adminViews')\n const { generatePageMetadata } = await import('@payloadcms/ui/views/Root/generatePageMetadata')\n\n const splatSegments = splat ? splat.split('/').filter(Boolean) : []\n // Match Next's optional-catch-all behavior: the admin root (`/admin`) has no\n // segments. Passing an empty array makes the shared `renderRoot` build\n // `currentRoute` as `/admin/` (trailing slash), which no longer equals\n // `adminRoute` and causes `handleAuthRedirect` to append `?redirect=/admin/`.\n // Passing `undefined` yields `currentRoute = /admin`, so the unauthenticated\n // redirect lands on a clean `/admin/login`.\n const segments = splatSegments.length > 0 ? splatSegments : undefined\n const searchParams = search ?? {}\n\n // Records navigation requested via `req.server.*` (including throws swallowed\n // by RSC streaming deep inside view components). Read after the render.\n const nav: { type?: 'notFound' | 'redirect'; url?: string } = {}\n const pageServerAdapter = createPageRenderServerAdapter(nav)\n\n // `renderRoot` calls `initReq` itself with its own overrides (query\n // re-nesting, `urlSuffix`, `fallbackLocale`). Forward them, injecting the\n // page-render `ServerAdapter` so `req.server.redirect()` / `.notFound()`\n // is recorded + thrown rather than escaping as raw TanStack nav.\n const boundInitReq: Parameters<typeof renderRoot>[0]['initReq'] = (args) =>\n initReq({\n configPromise: args.configPromise,\n importMap: args.importMap,\n overrides: args.overrides,\n serverAdapter: pageServerAdapter,\n })\n\n const notFound = (): never => {\n nav.type = 'notFound'\n throw new Error('not-found')\n }\n const redirect = (url: string): never => {\n nav.type = 'redirect'\n nav.url = url\n throw new Error(`redirect:${url}`)\n }\n\n // Build the 404 result the route loader re-throws as TanStack `notFound()`.\n //\n // Throwing `notFound()` is the only way to set the SSR document status to 404\n // (it's read from `router.stores.statusCode`, set by a not-found match — NOT\n // from `setResponseStatus`, which only affects the RSC RPC response). But the\n // matching `notFoundComponent` is a client component with no access to the\n // Payload `req`, so it can't build the admin chrome on its own. To match Next\n // (whose not-found route renders the full admin layout — nav sidebar, etc. —\n // around the NotFound body, see `renderNotFoundPage`), we render that same\n // shared `renderNotFoundPage` tree here, server-side, and ship its Flight\n // payload through the `notFound()` error so the client renders it verbatim.\n // For users without admin access `renderNotFoundPage` returns the bare\n // `NotFoundClient`, preserving the access-denied behavior.\n const renderNotFound = async (): Promise<LoadAdminPageResult> => {\n const { renderNotFoundPage } = await import('@payloadcms/ui/views/NotFound/page')\n\n const notFoundNode = await renderNotFoundPage({\n config: Promise.resolve(config),\n importMap,\n initReq: (args) =>\n initReq({\n configPromise: args.configPromise,\n importMap: args.importMap,\n overrides: args.overrides,\n }),\n params: Promise.resolve({ segments: splatSegments }),\n searchParams: Promise.resolve(searchParams),\n })\n\n const rscPayload = await renderServerComponent(notFoundNode as React.ReactElement)\n\n return { _notFound: true, routeKey: splat ?? '', rscPayload }\n }\n\n try {\n const node = await renderRoot({\n adminViews: defaultAdminViews,\n config: Promise.resolve(config),\n importMap,\n initReq: boundInitReq,\n notFound,\n // `segments` is intentionally `undefined` for the admin root (`/admin`),\n // matching Next's optional catch-all; `renderRoot` handles it at runtime.\n params: Promise.resolve({ segments }) as Parameters<typeof renderRoot>[0]['params'],\n redirect,\n searchParams: Promise.resolve(searchParams),\n })\n\n const rscPayload = await renderServerComponent(node as React.ReactElement)\n\n // Navigation thrown deep inside a streamed view component (e.g. access\n // denied → notFound, already-authenticated → redirect) is swallowed into\n // the RSC stream and never rejects the render. Honor it from the holder,\n // discarding the (broken) payload from the aborted render.\n if (nav.type === 'redirect' && nav.url) {\n return { _redirect: nav.url }\n }\n if (nav.type === 'notFound') {\n return await renderNotFound()\n }\n\n // Resolve metadata through the same shared generator Next.js uses. Only\n // plain strings cross the wire (the full `MetaConfig` carries a `URL`\n // `metadataBase` and icons that seroval cannot serialize).\n const i18n = await getRequestI18n({ config })\n const meta = await generatePageMetadata({\n adminViews: defaultAdminViews as Parameters<typeof generatePageMetadata>[0]['adminViews'],\n config,\n i18n,\n params: { segments },\n })\n\n return {\n metadata: toAdminPageMetadata(meta),\n routeKey: splat ?? '',\n rscPayload,\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n if (nav.type === 'notFound' || message === 'not-found') {\n return await renderNotFound()\n }\n if (nav.type === 'redirect' || message.startsWith('redirect:')) {\n return { _redirect: nav.url ?? message.slice('redirect:'.length) }\n }\n throw err\n }\n}\n"],"names":["renderServerComponent","getRequestI18n","initReq","createPageRenderServerAdapter","resolveTitle","title","undefined","absolute","default","toAdminPageMetadata","meta","og","openGraph","rawImages","images","imagesArray","Array","isArray","map","image","url","alt","height","String","width","filter","Boolean","rawIcons","icons","iconList","icon","rel","type","media","sizes","keywords","description","length","join","siteName","robots","loadAdminPage","config","importMap","search","splat","renderRoot","defaultAdminViews","generatePageMetadata","splatSegments","split","segments","searchParams","nav","pageServerAdapter","boundInitReq","args","configPromise","overrides","serverAdapter","notFound","Error","redirect","renderNotFound","renderNotFoundPage","notFoundNode","Promise","resolve","params","rscPayload","_notFound","routeKey","node","adminViews","_redirect","i18n","metadata","err","message","startsWith","slice"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/loadAdminPage.tsx"],"sourcesContent":["import type { ImportMap, MetaConfig, SanitizedConfig } from 'payload'\n\nimport { renderServerComponent } from '@tanstack/react-start/rsc'\n\nimport type { AdminPageMetadata } from './meta.js'\n\nimport { getRequestI18n } from './getRequestI18n.server.js'\nimport { initReq } from './initReq.server.js'\nimport { createPageRenderServerAdapter } from './serverAdapter.server.js'\n\nexport type LoadAdminPageArgs = {\n config: SanitizedConfig\n importMap: ImportMap\n search?: Record<string, string | string[]>\n splat?: string\n}\n\nexport type LoadAdminPageResult =\n | { _notFound: true; routeKey?: string; rscPayload?: React.ReactNode }\n | { _redirect: string }\n | {\n metadata: AdminPageMetadata\n /**\n * Stable identity for this rendered route (the splat, i.e. the path\n * after `/admin/`). The client keys the rendered subtree by this so the\n * view remounts exactly when a new payload arrives. Keying by\n * `location.pathname` instead races: the pathname updates before\n * `useLoaderData()` during a transition, so the subtree would remount\n * with the *previous* payload and then reconcile the fresh payload in\n * place — leaving client providers (DocumentInfo, etc.) holding stale\n * `useState` values from the prior document. Search params are excluded\n * so search-only changes (e.g. list-view filtering) reconcile in place.\n */\n routeKey: string\n rscPayload: React.ReactNode\n }\n\nconst resolveTitle = (title: MetaConfig['title']): string | undefined => {\n if (!title) {\n return undefined\n }\n if (typeof title === 'string') {\n return title\n }\n if ('absolute' in title) {\n return title.absolute\n }\n return title.default\n}\n\n/**\n * Flattens the framework-agnostic `MetaConfig` (Next.js `Metadata` shape) into\n * the plain, serializable `AdminPageMetadata` the route loader ships to the\n * client. The full `MetaConfig` carries a `URL` `metadataBase`, functions and\n * other non-serializable values that seroval cannot cross the wire, so only the\n * fields `getAdminMeta` renders are extracted.\n */\nconst toAdminPageMetadata = (meta: MetaConfig): AdminPageMetadata => {\n const og = meta.openGraph as\n | {\n description?: unknown\n images?: unknown\n siteName?: unknown\n title?: unknown\n }\n | undefined\n\n const rawImages = og?.images\n const imagesArray = rawImages ? (Array.isArray(rawImages) ? rawImages : [rawImages]) : []\n const images = imagesArray\n .map((image: any) =>\n typeof image === 'string'\n ? { url: image }\n : image?.url\n ? { alt: image.alt, height: image.height, url: String(image.url), width: image.width }\n : undefined,\n )\n .filter(Boolean) as NonNullable<AdminPageMetadata['openGraph']>['images']\n\n const rawIcons = meta.icons as any\n const iconList = Array.isArray(rawIcons)\n ? rawIcons\n : rawIcons && typeof rawIcons === 'object' && Array.isArray(rawIcons.icon)\n ? rawIcons.icon\n : []\n const icons = iconList\n .map((icon: any) =>\n typeof icon === 'string'\n ? { rel: 'icon', url: icon }\n : icon?.url\n ? {\n type: icon.type,\n media: icon.media,\n rel: icon.rel ?? 'icon',\n sizes: icon.sizes,\n url: String(icon.url),\n }\n : undefined,\n )\n .filter(Boolean) as AdminPageMetadata['icons']\n\n const keywords = meta.keywords\n\n return {\n description: typeof meta.description === 'string' ? meta.description : undefined,\n icons: icons?.length ? icons : undefined,\n keywords:\n typeof keywords === 'string'\n ? keywords\n : Array.isArray(keywords)\n ? keywords.join(', ')\n : undefined,\n openGraph: og\n ? {\n description: typeof og.description === 'string' ? og.description : undefined,\n images: images?.length ? images : undefined,\n siteName: typeof og.siteName === 'string' ? og.siteName : undefined,\n title: typeof og.title === 'string' ? og.title : undefined,\n }\n : undefined,\n robots: typeof meta.robots === 'string' ? meta.robots : undefined,\n title: resolveTitle(meta.title),\n }\n}\n\n/**\n * Renders an admin page for TanStack Start and returns a serializable loader\n * result. The framework adapter wraps this in a `createServerFn` that supplies\n * the app's `config` and generated `importMap`.\n *\n * 1. Initializes the Payload request via the shared `renderRoot` orchestrator\n * from `@payloadcms/ui`, passing a TanStack-bound `initReq`. The injected\n * page-render `ServerAdapter` records navigation intent and throws the\n * framework-agnostic error contract.\n * 2. Pipes the resulting React server tree through `renderServerComponent`\n * to produce a Flight payload the client consumes directly.\n * 3. Resolves page metadata via the same shared `generatePageMetadata`\n * Next.js uses, returning plain serializable strings for `head()`.\n *\n * Navigation surfaces two ways and both become a `_notFound` / `_redirect`\n * sentinel the route loader re-throws as native TanStack nav:\n * - thrown during `renderRoot` orchestration (e.g. the login redirect) → caught\n * by the try/catch below;\n * - thrown deep inside a streamed view component (e.g. `DocumentView` access\n * denied, `LoginView` already-authenticated) → swallowed into the RSC stream,\n * so it's read from the `nav` holder after `renderServerComponent` resolves.\n */\nexport async function loadAdminPage({\n config,\n importMap,\n search,\n splat,\n}: LoadAdminPageArgs): Promise<LoadAdminPageResult> {\n const { renderRoot } = await import('@payloadcms/ui/views/Root')\n const { defaultAdminViews } = await import('@payloadcms/ui/views/Root/adminViews')\n const { generatePageMetadata } = await import('@payloadcms/ui/views/Root/generatePageMetadata')\n\n const splatSegments = splat ? splat.split('/').filter(Boolean) : []\n // Match Next's optional-catch-all behavior: the admin root (`/admin`) has no\n // segments. Passing an empty array makes the shared `renderRoot` build\n // `currentRoute` as `/admin/` (trailing slash), which no longer equals\n // `adminRoute` and causes `handleAuthRedirect` to append `?redirect=/admin/`.\n // Passing `undefined` yields `currentRoute = /admin`, so the unauthenticated\n // redirect lands on a clean `/admin/login`.\n const segments = splatSegments.length > 0 ? splatSegments : undefined\n const searchParams = search ?? {}\n\n // Records navigation requested via `req.server.*` (including throws swallowed\n // by RSC streaming deep inside view components). Read after the render.\n const nav: { type?: 'notFound' | 'redirect'; url?: string } = {}\n const pageServerAdapter = createPageRenderServerAdapter(nav)\n\n // `renderRoot` calls `initReq` itself with its own overrides (query\n // re-nesting, `urlSuffix`, `fallbackLocale`). Forward them, injecting the\n // page-render `ServerAdapter` so `req.server.redirect()` / `.notFound()`\n // is recorded + thrown rather than escaping as raw TanStack nav.\n const boundInitReq: Parameters<typeof renderRoot>[0]['initReq'] = (args) =>\n initReq({\n configPromise: args.configPromise,\n importMap: args.importMap,\n overrides: args.overrides,\n serverAdapter: pageServerAdapter,\n })\n\n const notFound = (): never => {\n nav.type = 'notFound'\n throw new Error('not-found')\n }\n const redirect = (url: string): never => {\n nav.type = 'redirect'\n nav.url = url\n throw new Error(`redirect:${url}`)\n }\n\n // Build the 404 result the route loader re-throws as TanStack `notFound()`.\n //\n // Throwing `notFound()` is the only way to set the SSR document status to 404\n // (it's read from `router.stores.statusCode`, set by a not-found match — NOT\n // from `setResponseStatus`, which only affects the RSC RPC response). But the\n // matching `notFoundComponent` is a client component with no access to the\n // Payload `req`, so it can't build the admin chrome on its own. To match Next\n // (whose not-found route renders the full admin layout — nav sidebar, etc. —\n // around the NotFound body, see `renderNotFoundPage`), we render that same\n // shared `renderNotFoundPage` tree here, server-side, and ship its Flight\n // payload through the `notFound()` error so the client renders it verbatim.\n // For users without admin access `renderNotFoundPage` returns the bare\n // `NotFoundClient`, preserving the access-denied behavior.\n const renderNotFound = async (): Promise<LoadAdminPageResult> => {\n const { renderNotFoundPage } = await import('@payloadcms/ui/views/NotFound/page')\n\n const notFoundNode = await renderNotFoundPage({\n config: Promise.resolve(config),\n importMap,\n initReq: (args) =>\n initReq({\n configPromise: args.configPromise,\n importMap: args.importMap,\n overrides: args.overrides,\n }),\n params: Promise.resolve({ segments: splatSegments }),\n searchParams: Promise.resolve(searchParams),\n })\n\n const rscPayload = await renderServerComponent(notFoundNode as React.ReactElement)\n\n return { _notFound: true, routeKey: splat ?? '', rscPayload }\n }\n\n try {\n const node = await renderRoot({\n adminViews: defaultAdminViews,\n config: Promise.resolve(config),\n importMap,\n initReq: boundInitReq,\n notFound,\n // `segments` is intentionally `undefined` for the admin root (`/admin`),\n // matching Next's optional catch-all; `renderRoot` handles it at runtime.\n params: Promise.resolve({ segments }) as Parameters<typeof renderRoot>[0]['params'],\n redirect,\n searchParams: Promise.resolve(searchParams),\n })\n\n const rscPayload = await renderServerComponent(node as React.ReactElement)\n\n // The server-function (client-nav RPC) path returns the flight stream unread —\n // unlike the router/SSR path, which awaits a decode that drives the render to\n // completion. So streamed side effects (e.g. DocumentView's autosave-create\n // `server.redirect()`) haven't run yet and `nav` is empty. Buffer the stream to\n // completion to force the render (populating `nav`), then hand the client a fresh\n // replayable stream from that buffer.\n if (!nav.type) {\n const wrapper = (\n rscPayload as unknown as Record<\n symbol,\n { createReplayStream?: () => ReadableStream<Uint8Array> } | undefined\n >\n )[Symbol.for('tanstack.rsc.stream')]\n if (typeof wrapper?.createReplayStream === 'function') {\n const buffer = await new Response(wrapper.createReplayStream()).arrayBuffer()\n wrapper.createReplayStream = () => new Response(buffer).body as ReadableStream<Uint8Array>\n }\n }\n\n // Navigation thrown deep inside a streamed view component (e.g. access\n // denied → notFound, already-authenticated → redirect) is swallowed into\n // the RSC stream and never rejects the render. Honor it from the holder,\n // discarding the (broken) payload from the aborted render.\n if (nav.type === 'redirect' && nav.url) {\n return { _redirect: nav.url }\n }\n if (nav.type === 'notFound') {\n return await renderNotFound()\n }\n\n // Resolve metadata through the same shared generator Next.js uses. Only\n // plain strings cross the wire (the full `MetaConfig` carries a `URL`\n // `metadataBase` and icons that seroval cannot serialize).\n const i18n = await getRequestI18n({ config })\n const meta = await generatePageMetadata({\n adminViews: defaultAdminViews as Parameters<typeof generatePageMetadata>[0]['adminViews'],\n config,\n i18n,\n params: { segments },\n })\n\n return {\n metadata: toAdminPageMetadata(meta),\n routeKey: splat ?? '',\n rscPayload,\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n if (nav.type === 'notFound' || message === 'not-found') {\n return await renderNotFound()\n }\n if (nav.type === 'redirect' || message.startsWith('redirect:')) {\n return { _redirect: nav.url ?? message.slice('redirect:'.length) }\n }\n throw err\n }\n}\n"],"names":["renderServerComponent","getRequestI18n","initReq","createPageRenderServerAdapter","resolveTitle","title","undefined","absolute","default","toAdminPageMetadata","meta","og","openGraph","rawImages","images","imagesArray","Array","isArray","map","image","url","alt","height","String","width","filter","Boolean","rawIcons","icons","iconList","icon","rel","type","media","sizes","keywords","description","length","join","siteName","robots","loadAdminPage","config","importMap","search","splat","renderRoot","defaultAdminViews","generatePageMetadata","splatSegments","split","segments","searchParams","nav","pageServerAdapter","boundInitReq","args","configPromise","overrides","serverAdapter","notFound","Error","redirect","renderNotFound","renderNotFoundPage","notFoundNode","Promise","resolve","params","rscPayload","_notFound","routeKey","node","adminViews","wrapper","Symbol","for","createReplayStream","buffer","Response","arrayBuffer","body","_redirect","i18n","metadata","err","message","startsWith","slice"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/vite/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,MAAM,CAAA;AAsB5D,MAAM,WAAW,oBAAoB;IACnC,iCAAiC;IACjC,iBAAiB,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACzE,4DAA4D;IAC5D,yBAAyB,CAAC,EAAE,MAAM,EAAE,CAAA;IACpC,yCAAyC;IACzC,6BAA6B,CAAC,EAAE,MAAM,EAAE,CAAA;IACxC,iCAAiC;IACjC,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAA;IAChC,sDAAsD;IACtD,iBAAiB,EAAE,MAAM,CAAA;IACzB,oCAAoC;IACpC,OAAO,CAAC,EAAE,YAAY,EAAE,CAAA;IACxB,8FAA8F;IAC9F,WAAW,EAAE,YAAY,CAAA;IACzB,mFAAmF;IACnF,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,yFAAyF;IACzF,SAAS,EAAE,YAAY,CAAA;IACvB,mDAAmD;IACnD,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,uHAAuH;IACvH,aAAa,EAAE,cAAc,mCAAmC,EAAE,aAAa,CAAA;CAChF;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,kBAAkB,
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/vite/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,MAAM,CAAA;AAsB5D,MAAM,WAAW,oBAAoB;IACnC,iCAAiC;IACjC,iBAAiB,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACzE,4DAA4D;IAC5D,yBAAyB,CAAC,EAAE,MAAM,EAAE,CAAA;IACpC,yCAAyC;IACzC,6BAA6B,CAAC,EAAE,MAAM,EAAE,CAAA;IACxC,iCAAiC;IACjC,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAA;IAChC,sDAAsD;IACtD,iBAAiB,EAAE,MAAM,CAAA;IACzB,oCAAoC;IACpC,OAAO,CAAC,EAAE,YAAY,EAAE,CAAA;IACxB,8FAA8F;IAC9F,WAAW,EAAE,YAAY,CAAA;IACzB,mFAAmF;IACnF,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,yFAAyF;IACzF,SAAS,EAAE,YAAY,CAAA;IACvB,mDAAmD;IACnD,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,uHAAuH;IACvH,aAAa,EAAE,cAAc,mCAAmC,EAAE,aAAa,CAAA;CAChF;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,kBAAkB,CA+H/E"}
|
package/dist/vite/plugin.js
CHANGED
|
@@ -15,7 +15,6 @@ import { wrapCjsForClient } from './plugins/wrapCjsForClient.js';
|
|
|
15
15
|
* deleted individually once the corresponding upstream fix lands.
|
|
16
16
|
*/ export function payloadPlugin(options) {
|
|
17
17
|
const { additionalAliases = [], additionalIgnoreImporters = [], additionalOptimizeDepsInclude = [], additionalSsrExternal = [], payloadConfigPath, plugins: extraPlugins = [], reactPlugin, routesDirectory = 'app', rscPlugin, srcDirectory = 'src', tanstackStart } = options;
|
|
18
|
-
process.env.PAYLOAD_FRAMEWORK_RSC_ENABLED = 'true';
|
|
19
18
|
return (_env)=>({
|
|
20
19
|
css: {
|
|
21
20
|
preprocessorOptions: {
|
|
@@ -28,8 +27,7 @@ import { wrapCjsForClient } from './plugins/wrapCjsForClient.js';
|
|
|
28
27
|
}
|
|
29
28
|
},
|
|
30
29
|
define: {
|
|
31
|
-
global: 'globalThis'
|
|
32
|
-
'process.env.PAYLOAD_FRAMEWORK_RSC_ENABLED': JSON.stringify('true')
|
|
30
|
+
global: 'globalThis'
|
|
33
31
|
},
|
|
34
32
|
environments: {
|
|
35
33
|
rsc: {
|
package/dist/vite/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/vite/plugin.ts"],"sourcesContent":["import type { PluginOption, UserConfigFnObject } from 'vite'\n\nimport path from 'node:path'\n\nimport {\n optimizeDepsExcludeDefaults,\n optimizeDepsIncludeDefaults,\n payloadNoExternalPatterns,\n payloadRscNoExternalPatterns,\n ssrExternalPackages,\n} from './constants.js'\nimport {\n defaultImportProtectionIgnoreImporters,\n onImportProtectionViolation,\n serverOnlyClientSpecifiers,\n} from './importProtection.js'\nimport { clientModuleResolution } from './plugins/clientModuleResolution.js'\nimport { payloadDevTransforms } from './plugins/devTransforms.js'\nimport { reactDomServerInRsc } from './plugins/reactDomServerInRsc.js'\nimport { ssrStripDistStyleImports } from './plugins/stripDistStyleImports.js'\nimport { wrapCjsForClient } from './plugins/wrapCjsForClient.js'\n\nexport interface PayloadPluginOptions {\n /** Additional resolve aliases */\n additionalAliases?: Array<{ find: RegExp | string; replacement: string }>\n /** Additional import protection ignoreImporters patterns */\n additionalIgnoreImporters?: RegExp[]\n /** Extra optimizeDeps.include entries */\n additionalOptimizeDepsInclude?: string[]\n /** Extra ssr.external entries */\n additionalSsrExternal?: string[]\n /** Path to the user's payload.config.ts (required) */\n payloadConfigPath: string\n /** Extra Vite plugins to include */\n plugins?: PluginOption[]\n /** @vitejs/plugin-react instance — must be passed by consumer to ensure correct resolution */\n reactPlugin: PluginOption\n /** TanStack router routes directory relative to srcDirectory. Defaults to 'app' */\n routesDirectory?: string\n /** @vitejs/plugin-rsc instance — required for RSC support, must be passed by consumer */\n rscPlugin: PluginOption\n /** TanStack source directory. Defaults to 'src' */\n srcDirectory?: string\n /** tanstackStart from '@tanstack/react-start/plugin/vite' — must be passed by consumer to ensure correct resolution */\n tanstackStart: typeof import('@tanstack/react-start/plugin/vite').tanstackStart\n}\n\n/**\n * Vite plugin for Payload + TanStack Start. The Vite-side counterpart to\n * `withPayload` for Next.js: it configures the Vite environment so the Payload\n * admin can run, then composes the TanStack Start plugin with two small\n * Payload-specific workarounds (dev HMR injection, SSR style stripping). Each\n * remaining workaround lives in its own file under `./plugins/` so it can be\n * deleted individually once the corresponding upstream fix lands.\n */\nexport function payloadPlugin(options: PayloadPluginOptions): UserConfigFnObject {\n const {\n additionalAliases = [],\n additionalIgnoreImporters = [],\n additionalOptimizeDepsInclude = [],\n additionalSsrExternal = [],\n payloadConfigPath,\n plugins: extraPlugins = [],\n reactPlugin,\n routesDirectory = 'app',\n rscPlugin,\n srcDirectory = 'src',\n tanstackStart,\n } = options\n\n process.env.PAYLOAD_FRAMEWORK_RSC_ENABLED = 'true'\n\n return (_env) => ({\n css: {\n preprocessorOptions: {\n scss: {\n silenceDeprecations: ['import', 'global-builtin'],\n } as any,\n },\n },\n define: {\n global: 'globalThis',\n 'process.env.PAYLOAD_FRAMEWORK_RSC_ENABLED': JSON.stringify('true'),\n },\n environments: {\n rsc: { resolve: { noExternal: payloadRscNoExternalPatterns } },\n ssr: { resolve: { noExternal: payloadNoExternalPatterns } },\n } as any,\n optimizeDeps: {\n exclude: optimizeDepsExcludeDefaults,\n include: [...optimizeDepsIncludeDefaults, ...additionalOptimizeDepsInclude],\n },\n plugins: [\n clientModuleResolution(),\n wrapCjsForClient(),\n ssrStripDistStyleImports(),\n reactDomServerInRsc(),\n payloadDevTransforms(),\n rscPlugin,\n tanstackStart({\n importProtection: {\n client: { excludeFiles: [], specifiers: serverOnlyClientSpecifiers },\n ignoreImporters: [\n ...defaultImportProtectionIgnoreImporters,\n ...additionalIgnoreImporters,\n ],\n include: ['**/*'],\n mockAccess: 'warn',\n onViolation: onImportProtectionViolation,\n // Disable TanStack Start's default `**/*.client.*` file-based denial in\n // the SSR environment. Payload uses the `.client.tsx` filename suffix\n // for React Client Components (with a `'use client'` directive) that\n // MUST be server-rendered to HTML during SSR. The default rule would\n // otherwise replace those files with an `import-protection mock` Proxy\n // during SSR, which crashes React (TypeError: Cannot convert object to\n // primitive value) the moment React tries to format a warning that\n // mentions one of these components.\n server: { files: [] },\n },\n // Disable TanStack Router's automatic per-route code-splitting.\n //\n // With splitting enabled each route's `component` is fetched lazily\n // via `?tsr-split=component` after the initial SSR HTML is streamed.\n // Until that lazy chunk lands the rendered admin tree has no client\n // React attached, so any button clicks (e.g. the\n // `#toggle-list-filters` chevron in `<ListControls />`) hit a static\n // DOM, the click is dropped, and once the chunk finally loads the\n // component re-mounts with its initial `useState` instead of the\n // toggled value. That single behaviour was the root cause of the\n // \"page renders but nothing is interactive\" tanstack-start E2E\n // failures (`#list-controls-where`, `[data-lexical-editor]`, etc.) -\n // playwright traces show \"Download the React DevTools\" landing\n // *after* the playwright click, confirming late hydration.\n //\n // We pass BOTH knobs because `tanstackStart`'s schema silently\n // strips the user-supplied `autoCodeSplitting` (its `tsrConfig`\n // does `configSchema.omit({ autoCodeSplitting: true, target: true\n // })`) and then leaves the value `undefined` — which is fine for\n // the conditional inside `unpluginRouterComposedFactory`, but the\n // TanStack Start vite plugin *unconditionally* installs the router\n // code-splitter via `tanStackRouterCodeSplitter(...)` regardless.\n // The only knob that survives all of that and is honoured by the\n // splitter is `router.codeSplittingOptions.defaultBehavior` — set\n // to an empty array, the splitter still walks each `createFileRoute`\n // file but produces no virtual `?tsr-split=...` modules, so every\n // route component ships in the initial bundle and hydration starts\n // immediately on first paint. We keep `autoCodeSplitting: false` as\n // a belt-and-braces signal in case the start plugin ever stops\n // dropping it.\n //\n // Eager-loading routes ships a slightly larger initial bundle but\n // makes the admin actually interactive on first paint.\n router: {\n autoCodeSplitting: false,\n codeSplittingOptions: { defaultBehavior: [] },\n // Exclude generated importMap files and colocated server-function\n // modules (`*.functions.ts`). Admin form saves are dispatched via\n // `runPayloadServerFn` (a TanStack Start `createServerFn`) rather than\n // a hand-rolled route, so there is no longer an `api.server-function.ts`\n // to special-case here. The `*.functions.ts` shims live next to the\n // routes that use them (e.g. `app/_payload/*.functions.ts`); they\n // define `createServerFn`s, not routes, so they must not be scanned.\n routeFileIgnorePattern: 'importMap\\\\.(?:js|server\\\\.ts)$|\\\\.functions\\\\.',\n routesDirectory,\n } as any,\n rsc: { enabled: true },\n srcDirectory,\n }),\n reactPlugin,\n ...extraPlugins,\n ],\n resolve: {\n alias: [\n { find: '@payload-config', replacement: path.resolve(payloadConfigPath) },\n ...additionalAliases,\n ],\n dedupe: ['react', 'react-dom', 'scheduler', '@payloadcms/ui', '@payloadcms/richtext-lexical'],\n extensions: ['.mjs', '.js', '.mts', '.ts', '.jsx', '.tsx', '.json'],\n tsconfigPaths: true,\n } as any,\n ssr: {\n external: [...ssrExternalPackages, ...additionalSsrExternal],\n noExternal: payloadNoExternalPatterns,\n },\n })\n}\n"],"names":["path","optimizeDepsExcludeDefaults","optimizeDepsIncludeDefaults","payloadNoExternalPatterns","payloadRscNoExternalPatterns","ssrExternalPackages","defaultImportProtectionIgnoreImporters","onImportProtectionViolation","serverOnlyClientSpecifiers","clientModuleResolution","payloadDevTransforms","reactDomServerInRsc","ssrStripDistStyleImports","wrapCjsForClient","payloadPlugin","options","additionalAliases","additionalIgnoreImporters","additionalOptimizeDepsInclude","additionalSsrExternal","payloadConfigPath","plugins","extraPlugins","reactPlugin","routesDirectory","rscPlugin","srcDirectory","tanstackStart","process","env","PAYLOAD_FRAMEWORK_RSC_ENABLED","_env","css","preprocessorOptions","scss","silenceDeprecations","define","global","JSON","stringify","environments","rsc","resolve","noExternal","ssr","optimizeDeps","exclude","include","importProtection","client","excludeFiles","specifiers","ignoreImporters","mockAccess","onViolation","server","files","router","autoCodeSplitting","codeSplittingOptions","defaultBehavior","routeFileIgnorePattern","enabled","alias","find","replacement","dedupe","extensions","tsconfigPaths","external"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/vite/plugin.ts"],"sourcesContent":["import type { PluginOption, UserConfigFnObject } from 'vite'\n\nimport path from 'node:path'\n\nimport {\n optimizeDepsExcludeDefaults,\n optimizeDepsIncludeDefaults,\n payloadNoExternalPatterns,\n payloadRscNoExternalPatterns,\n ssrExternalPackages,\n} from './constants.js'\nimport {\n defaultImportProtectionIgnoreImporters,\n onImportProtectionViolation,\n serverOnlyClientSpecifiers,\n} from './importProtection.js'\nimport { clientModuleResolution } from './plugins/clientModuleResolution.js'\nimport { payloadDevTransforms } from './plugins/devTransforms.js'\nimport { reactDomServerInRsc } from './plugins/reactDomServerInRsc.js'\nimport { ssrStripDistStyleImports } from './plugins/stripDistStyleImports.js'\nimport { wrapCjsForClient } from './plugins/wrapCjsForClient.js'\n\nexport interface PayloadPluginOptions {\n /** Additional resolve aliases */\n additionalAliases?: Array<{ find: RegExp | string; replacement: string }>\n /** Additional import protection ignoreImporters patterns */\n additionalIgnoreImporters?: RegExp[]\n /** Extra optimizeDeps.include entries */\n additionalOptimizeDepsInclude?: string[]\n /** Extra ssr.external entries */\n additionalSsrExternal?: string[]\n /** Path to the user's payload.config.ts (required) */\n payloadConfigPath: string\n /** Extra Vite plugins to include */\n plugins?: PluginOption[]\n /** @vitejs/plugin-react instance — must be passed by consumer to ensure correct resolution */\n reactPlugin: PluginOption\n /** TanStack router routes directory relative to srcDirectory. Defaults to 'app' */\n routesDirectory?: string\n /** @vitejs/plugin-rsc instance — required for RSC support, must be passed by consumer */\n rscPlugin: PluginOption\n /** TanStack source directory. Defaults to 'src' */\n srcDirectory?: string\n /** tanstackStart from '@tanstack/react-start/plugin/vite' — must be passed by consumer to ensure correct resolution */\n tanstackStart: typeof import('@tanstack/react-start/plugin/vite').tanstackStart\n}\n\n/**\n * Vite plugin for Payload + TanStack Start. The Vite-side counterpart to\n * `withPayload` for Next.js: it configures the Vite environment so the Payload\n * admin can run, then composes the TanStack Start plugin with two small\n * Payload-specific workarounds (dev HMR injection, SSR style stripping). Each\n * remaining workaround lives in its own file under `./plugins/` so it can be\n * deleted individually once the corresponding upstream fix lands.\n */\nexport function payloadPlugin(options: PayloadPluginOptions): UserConfigFnObject {\n const {\n additionalAliases = [],\n additionalIgnoreImporters = [],\n additionalOptimizeDepsInclude = [],\n additionalSsrExternal = [],\n payloadConfigPath,\n plugins: extraPlugins = [],\n reactPlugin,\n routesDirectory = 'app',\n rscPlugin,\n srcDirectory = 'src',\n tanstackStart,\n } = options\n\n return (_env) => ({\n css: {\n preprocessorOptions: {\n scss: {\n silenceDeprecations: ['import', 'global-builtin'],\n } as any,\n },\n },\n define: {\n global: 'globalThis',\n },\n environments: {\n rsc: { resolve: { noExternal: payloadRscNoExternalPatterns } },\n ssr: { resolve: { noExternal: payloadNoExternalPatterns } },\n } as any,\n optimizeDeps: {\n exclude: optimizeDepsExcludeDefaults,\n include: [...optimizeDepsIncludeDefaults, ...additionalOptimizeDepsInclude],\n },\n plugins: [\n clientModuleResolution(),\n wrapCjsForClient(),\n ssrStripDistStyleImports(),\n reactDomServerInRsc(),\n payloadDevTransforms(),\n rscPlugin,\n tanstackStart({\n importProtection: {\n client: { excludeFiles: [], specifiers: serverOnlyClientSpecifiers },\n ignoreImporters: [\n ...defaultImportProtectionIgnoreImporters,\n ...additionalIgnoreImporters,\n ],\n include: ['**/*'],\n mockAccess: 'warn',\n onViolation: onImportProtectionViolation,\n // Disable TanStack Start's default `**/*.client.*` file-based denial in\n // the SSR environment. Payload uses the `.client.tsx` filename suffix\n // for React Client Components (with a `'use client'` directive) that\n // MUST be server-rendered to HTML during SSR. The default rule would\n // otherwise replace those files with an `import-protection mock` Proxy\n // during SSR, which crashes React (TypeError: Cannot convert object to\n // primitive value) the moment React tries to format a warning that\n // mentions one of these components.\n server: { files: [] },\n },\n // Disable TanStack Router's automatic per-route code-splitting.\n //\n // With splitting enabled each route's `component` is fetched lazily\n // via `?tsr-split=component` after the initial SSR HTML is streamed.\n // Until that lazy chunk lands the rendered admin tree has no client\n // React attached, so any button clicks (e.g. the\n // `#toggle-list-filters` chevron in `<ListControls />`) hit a static\n // DOM, the click is dropped, and once the chunk finally loads the\n // component re-mounts with its initial `useState` instead of the\n // toggled value. That single behaviour was the root cause of the\n // \"page renders but nothing is interactive\" tanstack-start E2E\n // failures (`#list-controls-where`, `[data-lexical-editor]`, etc.) -\n // playwright traces show \"Download the React DevTools\" landing\n // *after* the playwright click, confirming late hydration.\n //\n // We pass BOTH knobs because `tanstackStart`'s schema silently\n // strips the user-supplied `autoCodeSplitting` (its `tsrConfig`\n // does `configSchema.omit({ autoCodeSplitting: true, target: true\n // })`) and then leaves the value `undefined` — which is fine for\n // the conditional inside `unpluginRouterComposedFactory`, but the\n // TanStack Start vite plugin *unconditionally* installs the router\n // code-splitter via `tanStackRouterCodeSplitter(...)` regardless.\n // The only knob that survives all of that and is honoured by the\n // splitter is `router.codeSplittingOptions.defaultBehavior` — set\n // to an empty array, the splitter still walks each `createFileRoute`\n // file but produces no virtual `?tsr-split=...` modules, so every\n // route component ships in the initial bundle and hydration starts\n // immediately on first paint. We keep `autoCodeSplitting: false` as\n // a belt-and-braces signal in case the start plugin ever stops\n // dropping it.\n //\n // Eager-loading routes ships a slightly larger initial bundle but\n // makes the admin actually interactive on first paint.\n router: {\n autoCodeSplitting: false,\n codeSplittingOptions: { defaultBehavior: [] },\n // Exclude generated importMap files and colocated server-function\n // modules (`*.functions.ts`). Admin form saves are dispatched via\n // `runPayloadServerFn` (a TanStack Start `createServerFn`) rather than\n // a hand-rolled route, so there is no longer an `api.server-function.ts`\n // to special-case here. The `*.functions.ts` shims live next to the\n // routes that use them (e.g. `app/_payload/*.functions.ts`); they\n // define `createServerFn`s, not routes, so they must not be scanned.\n routeFileIgnorePattern: 'importMap\\\\.(?:js|server\\\\.ts)$|\\\\.functions\\\\.',\n routesDirectory,\n } as any,\n rsc: { enabled: true },\n srcDirectory,\n }),\n reactPlugin,\n ...extraPlugins,\n ],\n resolve: {\n alias: [\n { find: '@payload-config', replacement: path.resolve(payloadConfigPath) },\n ...additionalAliases,\n ],\n dedupe: ['react', 'react-dom', 'scheduler', '@payloadcms/ui', '@payloadcms/richtext-lexical'],\n extensions: ['.mjs', '.js', '.mts', '.ts', '.jsx', '.tsx', '.json'],\n tsconfigPaths: true,\n } as any,\n ssr: {\n external: [...ssrExternalPackages, ...additionalSsrExternal],\n noExternal: payloadNoExternalPatterns,\n },\n })\n}\n"],"names":["path","optimizeDepsExcludeDefaults","optimizeDepsIncludeDefaults","payloadNoExternalPatterns","payloadRscNoExternalPatterns","ssrExternalPackages","defaultImportProtectionIgnoreImporters","onImportProtectionViolation","serverOnlyClientSpecifiers","clientModuleResolution","payloadDevTransforms","reactDomServerInRsc","ssrStripDistStyleImports","wrapCjsForClient","payloadPlugin","options","additionalAliases","additionalIgnoreImporters","additionalOptimizeDepsInclude","additionalSsrExternal","payloadConfigPath","plugins","extraPlugins","reactPlugin","routesDirectory","rscPlugin","srcDirectory","tanstackStart","_env","css","preprocessorOptions","scss","silenceDeprecations","define","global","environments","rsc","resolve","noExternal","ssr","optimizeDeps","exclude","include","importProtection","client","excludeFiles","specifiers","ignoreImporters","mockAccess","onViolation","server","files","router","autoCodeSplitting","codeSplittingOptions","defaultBehavior","routeFileIgnorePattern","enabled","alias","find","replacement","dedupe","extensions","tsconfigPaths","external"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stripDistStyleImports.d.ts","sourceRoot":"","sources":["../../../src/vite/plugins/stripDistStyleImports.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"stripDistStyleImports.d.ts","sourceRoot":"","sources":["../../../src/vite/plugins/stripDistStyleImports.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,MAAM,CAAA;AAsDxC;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,wBAAwB,IAAI,YAAY,CAyEvD"}
|
|
@@ -14,6 +14,34 @@ const STYLE_EXTENSION_RE = /\.(?:s?css|less)$/i;
|
|
|
14
14
|
* (not a published `dist`), so the `dist/` rule below doesn't cover them and
|
|
15
15
|
* their `.css` side-effect imports survive into the SSR/RSC graph.
|
|
16
16
|
*/ const PAYLOAD_PKG_SRC_RE = /\/packages\/[^/]+\/src\//;
|
|
17
|
+
/**
|
|
18
|
+
* The version-diff component trees — matched in either published `dist/` or
|
|
19
|
+
* workspace `src/` form. The `.css` side-effect imports of these must be
|
|
20
|
+
* stripped in the RSC env (the rest of `@payloadcms/ui` must NOT be — see the
|
|
21
|
+
* note in `resolveId`/`transform` below), for two reasons rooted in the same
|
|
22
|
+
* `@vitejs/plugin-rsc` behaviour: it wraps every exported CSS-importing
|
|
23
|
+
* component with an async CSS-collector child
|
|
24
|
+
* (`__vite_rsc_wrap_css__` → `await import('virtual:vite-rsc/css?…')`).
|
|
25
|
+
*
|
|
26
|
+
* 1. Correctness: the diff converters render `CheckIcon` (`icons/*`) and `File`
|
|
27
|
+
* (`graphics/*`) through the SYNCHRONOUS `renderToStaticMarkup` (see
|
|
28
|
+
* `reactDomServerInRsc`). The async wrapper suspends, crashing that render
|
|
29
|
+
* with "A component suspended while responding to synchronous input" and
|
|
30
|
+
* taking down the entire field-diffs tree.
|
|
31
|
+
* 2. Performance: the diff view (`views/Version/*` — `RenderFieldsToDiff` and
|
|
32
|
+
* its per-field components, `DiffCollapser`, `SelectComparison`, the
|
|
33
|
+
* `Default` template — plus the `HTMLDiff`/`FieldDiffContainer`/
|
|
34
|
+
* `FieldDiffLabel` elements and lexical's `field/Diff/*`) renders dozens of
|
|
35
|
+
* these wrapped components in the Flight stream. Each async CSS import
|
|
36
|
+
* serializes a round-trip, ballooning the render from ~3s to ~25s and
|
|
37
|
+
* blowing past the e2e waits. Stripping them collapses it back to ~3s.
|
|
38
|
+
*
|
|
39
|
+
* Safe because every one of these components' styles also ship in the global
|
|
40
|
+
* `@payloadcms/ui/scss/app.scss` the admin imports, so dropping the per-module
|
|
41
|
+
* RSC collection here changes nothing visually (verified: diff + Nav stay
|
|
42
|
+
* styled). The admin `Nav` etc. are deliberately excluded — they rely on the
|
|
43
|
+
* RSC collection and a broad strip leaves them unstyled.
|
|
44
|
+
*/ const DIFF_VIEW_COMPONENT_RE = /@payloadcms\/ui\/(?:dist|src)\/(?:icons|graphics|views\/Version|elements\/(?:HTMLDiff|FieldDiffContainer|FieldDiffLabel))\/|@payloadcms\/richtext-lexical\/(?:dist|src)\/field\/Diff\//;
|
|
17
45
|
/**
|
|
18
46
|
* Stops Vite (and the underlying Node ESM loader) from trying to load
|
|
19
47
|
* SCSS/CSS/LESS during SSR/RSC when the importer lives inside a built
|
|
@@ -73,9 +101,11 @@ const STYLE_EXTENSION_RE = /\.(?:s?css|less)$/i;
|
|
|
73
101
|
if (!isServerEnv) {
|
|
74
102
|
return;
|
|
75
103
|
}
|
|
76
|
-
//
|
|
77
|
-
//
|
|
78
|
-
|
|
104
|
+
// In the RSC env, only strip from the version-diff component trees (see
|
|
105
|
+
// `DIFF_VIEW_COMPONENT_RE`). Every other server component (the admin
|
|
106
|
+
// `Nav`, etc.) must keep its `.css` import so plugin-rsc can collect it —
|
|
107
|
+
// see the matching note in `resolveId` above.
|
|
108
|
+
if (envName === 'rsc' && !DIFF_VIEW_COMPONENT_RE.test(id)) {
|
|
79
109
|
return;
|
|
80
110
|
}
|
|
81
111
|
// Only touch Payload dependency files: published `node_modules/.../dist/`
|
|
@@ -87,7 +117,10 @@ const STYLE_EXTENSION_RE = /\.(?:s?css|less)$/i;
|
|
|
87
117
|
if (!isPayloadDistFile && !isPayloadSrcFile) {
|
|
88
118
|
return;
|
|
89
119
|
}
|
|
90
|
-
|
|
120
|
+
// Allow a trailing query (`?v=…`, `?t=…`): Vite appends version/timestamp
|
|
121
|
+
// queries to module ids, especially in the RSC graph, so a strict `$`
|
|
122
|
+
// anchor would skip e.g. `icons/Check/index.js?v=83de8543`.
|
|
123
|
+
if (!/\.[mc]?[jt]sx?(?:$|\?)/.test(id)) {
|
|
91
124
|
return;
|
|
92
125
|
}
|
|
93
126
|
if (!STATIC_STYLE_IMPORT_RE.test(code)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/vite/plugins/stripDistStyleImports.ts"],"sourcesContent":["import type { PluginOption } from 'vite'\n\nconst STYLE_EXTENSION_RE = /\\.(?:s?css|less)$/i\n\n/**\n * Static `import './foo.css'` (or .scss/.less) — top-level only.\n * Captures the entire statement so we can replace it with an empty line.\n *\n * Matches:\n * import './foo.css';\n * import \"../bar.scss\"\n * import './baz.less' ;\n */\nconst STATIC_STYLE_IMPORT_RE = /^[ \\t]*import\\s+['\"][^'\"]+\\.(?:s?css|less)['\"]\\s*(?:;[ \\t]*)?$/gm\n\n/**\n * Monorepo Payload package source, e.g. `…/packages/ui/src/…`. In the\n * core-dev / test setup Payload packages resolve to their workspace `src`\n * (not a published `dist`), so the `dist/` rule below doesn't cover them and\n * their `.css` side-effect imports survive into the SSR/RSC graph.\n */\nconst PAYLOAD_PKG_SRC_RE = /\\/packages\\/[^/]+\\/src\\//\n\n/**\n * Stops Vite (and the underlying Node ESM loader) from trying to load\n * SCSS/CSS/LESS during SSR/RSC when the importer lives inside a built\n * `dist/` directory or when the specifier is a bare package name.\n *\n * We do this two ways, because either layer can fail:\n *\n * 1. `resolveId` redirects style specifiers to a virtual empty module —\n * handles cases where Vite asks us to resolve them.\n * 2. `transform` strips top-level `import './x.css'` statements out of any\n * JS/TS file living under `node_modules/.../dist/` for non-client envs.\n * This is the bulletproof path for prod-packed `@payloadcms/ui` (and\n * similar) dependencies that get pre-bundled by Vite's SSR/RSC dep\n * optimizer (esbuild). Esbuild preserves `.css` import statements as-is,\n * and Node's native ESM loader then crashes with\n * `Unknown file extension \".css\"`. Removing them at the source avoids\n * that entirely.\n */\nexport function ssrStripDistStyleImports(): PluginOption {\n return {\n name: 'payload:ssr-strip-dist-style-imports',\n enforce: 'pre',\n load(id) {\n if (id === '\\0ssr-empty-style') {\n return ''\n }\n },\n resolveId(id, importer, options) {\n const envName = (this as any).environment?.name as string | undefined\n const isServerEnv = options?.ssr || (envName && envName !== 'client')\n if (!isServerEnv) {\n return\n }\n // Do NOT strip in the RSC environment. Server components (e.g. the admin\n // `Nav`, a non-'use client' component that `import './index.css'`) render\n // in the RSC graph, and `@vitejs/plugin-rsc` must SEE their `.css` imports\n // there to collect them as client stylesheets. Stripping them here means\n // their CSS is never emitted and the admin renders unstyled (broken nav\n // scroll/layout, etc.). The Node-side `.css` no-op is handled by\n // `cssLoader.mjs` (dev) and by Vite's CSS extraction (build), so the\n // crash this plugin guards against does not require touching the RSC env.\n if (envName === 'rsc') {\n return\n }\n if (!STYLE_EXTENSION_RE.test(id)) {\n return\n }\n if (importer && (/\\/dist\\//.test(importer) || PAYLOAD_PKG_SRC_RE.test(importer))) {\n return '\\0ssr-empty-style'\n }\n if (/^@?[a-z]/.test(id) && !id.startsWith('.') && !id.startsWith('/')) {\n return '\\0ssr-empty-style'\n }\n },\n transform(code, id) {\n const envName = (this as any).environment?.name as string | undefined\n const isServerEnv = envName && envName !== 'client'\n if (!isServerEnv) {\n return\n }\n //
|
|
1
|
+
{"version":3,"sources":["../../../src/vite/plugins/stripDistStyleImports.ts"],"sourcesContent":["import type { PluginOption } from 'vite'\n\nconst STYLE_EXTENSION_RE = /\\.(?:s?css|less)$/i\n\n/**\n * Static `import './foo.css'` (or .scss/.less) — top-level only.\n * Captures the entire statement so we can replace it with an empty line.\n *\n * Matches:\n * import './foo.css';\n * import \"../bar.scss\"\n * import './baz.less' ;\n */\nconst STATIC_STYLE_IMPORT_RE = /^[ \\t]*import\\s+['\"][^'\"]+\\.(?:s?css|less)['\"]\\s*(?:;[ \\t]*)?$/gm\n\n/**\n * Monorepo Payload package source, e.g. `…/packages/ui/src/…`. In the\n * core-dev / test setup Payload packages resolve to their workspace `src`\n * (not a published `dist`), so the `dist/` rule below doesn't cover them and\n * their `.css` side-effect imports survive into the SSR/RSC graph.\n */\nconst PAYLOAD_PKG_SRC_RE = /\\/packages\\/[^/]+\\/src\\//\n\n/**\n * The version-diff component trees — matched in either published `dist/` or\n * workspace `src/` form. The `.css` side-effect imports of these must be\n * stripped in the RSC env (the rest of `@payloadcms/ui` must NOT be — see the\n * note in `resolveId`/`transform` below), for two reasons rooted in the same\n * `@vitejs/plugin-rsc` behaviour: it wraps every exported CSS-importing\n * component with an async CSS-collector child\n * (`__vite_rsc_wrap_css__` → `await import('virtual:vite-rsc/css?…')`).\n *\n * 1. Correctness: the diff converters render `CheckIcon` (`icons/*`) and `File`\n * (`graphics/*`) through the SYNCHRONOUS `renderToStaticMarkup` (see\n * `reactDomServerInRsc`). The async wrapper suspends, crashing that render\n * with \"A component suspended while responding to synchronous input\" and\n * taking down the entire field-diffs tree.\n * 2. Performance: the diff view (`views/Version/*` — `RenderFieldsToDiff` and\n * its per-field components, `DiffCollapser`, `SelectComparison`, the\n * `Default` template — plus the `HTMLDiff`/`FieldDiffContainer`/\n * `FieldDiffLabel` elements and lexical's `field/Diff/*`) renders dozens of\n * these wrapped components in the Flight stream. Each async CSS import\n * serializes a round-trip, ballooning the render from ~3s to ~25s and\n * blowing past the e2e waits. Stripping them collapses it back to ~3s.\n *\n * Safe because every one of these components' styles also ship in the global\n * `@payloadcms/ui/scss/app.scss` the admin imports, so dropping the per-module\n * RSC collection here changes nothing visually (verified: diff + Nav stay\n * styled). The admin `Nav` etc. are deliberately excluded — they rely on the\n * RSC collection and a broad strip leaves them unstyled.\n */\nconst DIFF_VIEW_COMPONENT_RE =\n /@payloadcms\\/ui\\/(?:dist|src)\\/(?:icons|graphics|views\\/Version|elements\\/(?:HTMLDiff|FieldDiffContainer|FieldDiffLabel))\\/|@payloadcms\\/richtext-lexical\\/(?:dist|src)\\/field\\/Diff\\//\n\n/**\n * Stops Vite (and the underlying Node ESM loader) from trying to load\n * SCSS/CSS/LESS during SSR/RSC when the importer lives inside a built\n * `dist/` directory or when the specifier is a bare package name.\n *\n * We do this two ways, because either layer can fail:\n *\n * 1. `resolveId` redirects style specifiers to a virtual empty module —\n * handles cases where Vite asks us to resolve them.\n * 2. `transform` strips top-level `import './x.css'` statements out of any\n * JS/TS file living under `node_modules/.../dist/` for non-client envs.\n * This is the bulletproof path for prod-packed `@payloadcms/ui` (and\n * similar) dependencies that get pre-bundled by Vite's SSR/RSC dep\n * optimizer (esbuild). Esbuild preserves `.css` import statements as-is,\n * and Node's native ESM loader then crashes with\n * `Unknown file extension \".css\"`. Removing them at the source avoids\n * that entirely.\n */\nexport function ssrStripDistStyleImports(): PluginOption {\n return {\n name: 'payload:ssr-strip-dist-style-imports',\n enforce: 'pre',\n load(id) {\n if (id === '\\0ssr-empty-style') {\n return ''\n }\n },\n resolveId(id, importer, options) {\n const envName = (this as any).environment?.name as string | undefined\n const isServerEnv = options?.ssr || (envName && envName !== 'client')\n if (!isServerEnv) {\n return\n }\n // Do NOT strip in the RSC environment. Server components (e.g. the admin\n // `Nav`, a non-'use client' component that `import './index.css'`) render\n // in the RSC graph, and `@vitejs/plugin-rsc` must SEE their `.css` imports\n // there to collect them as client stylesheets. Stripping them here means\n // their CSS is never emitted and the admin renders unstyled (broken nav\n // scroll/layout, etc.). The Node-side `.css` no-op is handled by\n // `cssLoader.mjs` (dev) and by Vite's CSS extraction (build), so the\n // crash this plugin guards against does not require touching the RSC env.\n if (envName === 'rsc') {\n return\n }\n if (!STYLE_EXTENSION_RE.test(id)) {\n return\n }\n if (importer && (/\\/dist\\//.test(importer) || PAYLOAD_PKG_SRC_RE.test(importer))) {\n return '\\0ssr-empty-style'\n }\n if (/^@?[a-z]/.test(id) && !id.startsWith('.') && !id.startsWith('/')) {\n return '\\0ssr-empty-style'\n }\n },\n transform(code, id) {\n const envName = (this as any).environment?.name as string | undefined\n const isServerEnv = envName && envName !== 'client'\n if (!isServerEnv) {\n return\n }\n // In the RSC env, only strip from the version-diff component trees (see\n // `DIFF_VIEW_COMPONENT_RE`). Every other server component (the admin\n // `Nav`, etc.) must keep its `.css` import so plugin-rsc can collect it —\n // see the matching note in `resolveId` above.\n if (envName === 'rsc' && !DIFF_VIEW_COMPONENT_RE.test(id)) {\n return\n }\n // Only touch Payload dependency files: published `node_modules/.../dist/`\n // builds, or workspace `…/packages/<pkg>/src/…` sources in the core-dev /\n // test setup. Don't strip from the consumer's own app source — devs may\n // legitimately want SSR-rendered <link>s from their own CSS imports.\n const isPayloadDistFile = /\\/node_modules\\//.test(id) && /\\/dist\\//.test(id)\n const isPayloadSrcFile = PAYLOAD_PKG_SRC_RE.test(id)\n if (!isPayloadDistFile && !isPayloadSrcFile) {\n return\n }\n // Allow a trailing query (`?v=…`, `?t=…`): Vite appends version/timestamp\n // queries to module ids, especially in the RSC graph, so a strict `$`\n // anchor would skip e.g. `icons/Check/index.js?v=83de8543`.\n if (!/\\.[mc]?[jt]sx?(?:$|\\?)/.test(id)) {\n return\n }\n if (!STATIC_STYLE_IMPORT_RE.test(code)) {\n STATIC_STYLE_IMPORT_RE.lastIndex = 0\n return\n }\n STATIC_STYLE_IMPORT_RE.lastIndex = 0\n const stripped = code.replace(STATIC_STYLE_IMPORT_RE, '')\n return { code: stripped, map: null }\n },\n }\n}\n"],"names":["STYLE_EXTENSION_RE","STATIC_STYLE_IMPORT_RE","PAYLOAD_PKG_SRC_RE","DIFF_VIEW_COMPONENT_RE","ssrStripDistStyleImports","name","enforce","load","id","resolveId","importer","options","envName","environment","isServerEnv","ssr","test","startsWith","transform","code","isPayloadDistFile","isPayloadSrcFile","lastIndex","stripped","replace","map"],"mappings":"AAEA,MAAMA,qBAAqB;AAE3B;;;;;;;;CAQC,GACD,MAAMC,yBAAyB;AAE/B;;;;;CAKC,GACD,MAAMC,qBAAqB;AAE3B;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BC,GACD,MAAMC,yBACJ;AAEF;;;;;;;;;;;;;;;;;CAiBC,GACD,OAAO,SAASC;IACd,OAAO;QACLC,MAAM;QACNC,SAAS;QACTC,MAAKC,EAAE;YACL,IAAIA,OAAO,qBAAqB;gBAC9B,OAAO;YACT;QACF;QACAC,WAAUD,EAAE,EAAEE,QAAQ,EAAEC,OAAO;YAC7B,MAAMC,UAAU,AAAC,IAAI,CAASC,WAAW,EAAER;YAC3C,MAAMS,cAAcH,SAASI,OAAQH,WAAWA,YAAY;YAC5D,IAAI,CAACE,aAAa;gBAChB;YACF;YACA,yEAAyE;YACzE,0EAA0E;YAC1E,2EAA2E;YAC3E,yEAAyE;YACzE,wEAAwE;YACxE,iEAAiE;YACjE,qEAAqE;YACrE,0EAA0E;YAC1E,IAAIF,YAAY,OAAO;gBACrB;YACF;YACA,IAAI,CAACZ,mBAAmBgB,IAAI,CAACR,KAAK;gBAChC;YACF;YACA,IAAIE,YAAa,CAAA,WAAWM,IAAI,CAACN,aAAaR,mBAAmBc,IAAI,CAACN,SAAQ,GAAI;gBAChF,OAAO;YACT;YACA,IAAI,WAAWM,IAAI,CAACR,OAAO,CAACA,GAAGS,UAAU,CAAC,QAAQ,CAACT,GAAGS,UAAU,CAAC,MAAM;gBACrE,OAAO;YACT;QACF;QACAC,WAAUC,IAAI,EAAEX,EAAE;YAChB,MAAMI,UAAU,AAAC,IAAI,CAASC,WAAW,EAAER;YAC3C,MAAMS,cAAcF,WAAWA,YAAY;YAC3C,IAAI,CAACE,aAAa;gBAChB;YACF;YACA,wEAAwE;YACxE,qEAAqE;YACrE,0EAA0E;YAC1E,8CAA8C;YAC9C,IAAIF,YAAY,SAAS,CAACT,uBAAuBa,IAAI,CAACR,KAAK;gBACzD;YACF;YACA,0EAA0E;YAC1E,0EAA0E;YAC1E,wEAAwE;YACxE,qEAAqE;YACrE,MAAMY,oBAAoB,mBAAmBJ,IAAI,CAACR,OAAO,WAAWQ,IAAI,CAACR;YACzE,MAAMa,mBAAmBnB,mBAAmBc,IAAI,CAACR;YACjD,IAAI,CAACY,qBAAqB,CAACC,kBAAkB;gBAC3C;YACF;YACA,0EAA0E;YAC1E,sEAAsE;YACtE,4DAA4D;YAC5D,IAAI,CAAC,yBAAyBL,IAAI,CAACR,KAAK;gBACtC;YACF;YACA,IAAI,CAACP,uBAAuBe,IAAI,CAACG,OAAO;gBACtClB,uBAAuBqB,SAAS,GAAG;gBACnC;YACF;YACArB,uBAAuBqB,SAAS,GAAG;YACnC,MAAMC,WAAWJ,KAAKK,OAAO,CAACvB,wBAAwB;YACtD,OAAO;gBAAEkB,MAAMI;gBAAUE,KAAK;YAAK;QACrC;IACF;AACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@payloadcms/tanstack-start",
|
|
3
|
-
"version": "4.0.0-internal.
|
|
3
|
+
"version": "4.0.0-internal.43ccea7",
|
|
4
4
|
"description": "TanStack Start framework adapter for Payload",
|
|
5
5
|
"homepage": "https://payloadcms.com",
|
|
6
6
|
"repository": {
|
|
@@ -58,28 +58,28 @@
|
|
|
58
58
|
],
|
|
59
59
|
"dependencies": {
|
|
60
60
|
"qs-esm": "^7.0.2",
|
|
61
|
-
"@payloadcms/
|
|
62
|
-
"@payloadcms/
|
|
61
|
+
"@payloadcms/translations": "4.0.0-internal.43ccea7",
|
|
62
|
+
"@payloadcms/ui": "4.0.0-internal.43ccea7"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
65
|
"@tanstack/react-router": "^1.120.0",
|
|
66
|
-
"@tanstack/react-start": "^1.
|
|
66
|
+
"@tanstack/react-start": "^1.168.26",
|
|
67
67
|
"@types/react": "^19.0.0",
|
|
68
68
|
"@types/react-dom": "^19.0.0",
|
|
69
69
|
"@vitejs/plugin-react": "^6.0.0",
|
|
70
70
|
"react": "^19.0.0",
|
|
71
71
|
"react-dom": "^19.0.0",
|
|
72
72
|
"vite": ">=8.0.0",
|
|
73
|
-
"payload": "4.0.0-internal.
|
|
73
|
+
"payload": "4.0.0-internal.43ccea7"
|
|
74
74
|
},
|
|
75
75
|
"peerDependencies": {
|
|
76
76
|
"@tanstack/react-router": "^1.120.0",
|
|
77
|
-
"@tanstack/react-start": "^1.
|
|
77
|
+
"@tanstack/react-start": "^1.168.26",
|
|
78
78
|
"@vitejs/plugin-react": "^6.0.0",
|
|
79
79
|
"react": "^19.0.0",
|
|
80
80
|
"react-dom": "^19.0.0",
|
|
81
81
|
"vite": ">=8.0.0",
|
|
82
|
-
"payload": "4.0.0-internal.
|
|
82
|
+
"payload": "4.0.0-internal.43ccea7"
|
|
83
83
|
},
|
|
84
84
|
"peerDependenciesMeta": {
|
|
85
85
|
"@vitejs/plugin-react": {
|
package/dist/@types/assets.d.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/@types/assets.d.ts"],"names":[],"mappings":""}
|