diff --git a/examples/document-field/next-env.d copy.ts b/examples/document-field/next-env.d copy.ts
deleted file mode 100644
index 4f11a03dc6c..00000000000
--- a/examples/document-field/next-env.d copy.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-///
-///
-
-// NOTE: This file should not be edited
-// see https://nextjs.org/docs/basic-features/typescript for more information.
diff --git a/examples/document-field/next.config.js b/examples/document-field/next.config.js
deleted file mode 100644
index 00184d61daa..00000000000
--- a/examples/document-field/next.config.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// you don't need this if you're building something outside of the Keystone repo
-
-const withPreconstruct = require('@preconstruct/next')
-
-module.exports = withPreconstruct()
diff --git a/examples/document-field/next.config.mjs b/examples/document-field/next.config.mjs
new file mode 100644
index 00000000000..da3eee2060e
--- /dev/null
+++ b/examples/document-field/next.config.mjs
@@ -0,0 +1,16 @@
+export default {
+ experimental: {
+ // Experimental ESM Externals
+ // https://nextjs.org/docs/messages/import-esm-externals
+ // required to fix build admin ui issues related to "react-day-picker" and "date-fn"
+ esmExternals: 'loose',
+ // without this, 'Error: Expected Upload to be a GraphQL nullable type.'
+ serverComponentsExternalPackages: ['graphql'],
+ },
+ typescript: {
+ ignoreBuildErrors: true,
+ },
+ eslint: {
+ ignoreDuringBuilds: true,
+ },
+}
diff --git a/examples/document-field/src/app/(admin)/author/[id]/page.tsx b/examples/document-field/src/app/(admin)/author/[id]/page.tsx
index 8b44a9869f5..86b4d126459 100644
--- a/examples/document-field/src/app/(admin)/author/[id]/page.tsx
+++ b/examples/document-field/src/app/(admin)/author/[id]/page.tsx
@@ -41,16 +41,17 @@ const author = data?.author
)
}
-export async function getStaticPaths (): Promise {
- const data = await fetchGraphQL(gql`
- query {
- authors {
- id
- }
- }
- `)
- return {
- paths: data.authors.map((post: any) => ({ params: { id: post.id } })),
- fallback: 'blocking',
- }
-}
+// TODO - CAN NOT use this in app router properly
+// export async function getStaticPaths (): Promise {
+// const data = await fetchGraphQL(gql`
+// query {
+// authors {
+// id
+// }
+// }
+// `)
+// return {
+// paths: data.authors.map((post: any) => ({ params: { id: post.id } })),
+// fallback: 'blocking',
+// }
+// }
diff --git a/examples/document-field/src/app/(admin)/post/[slug]/page.tsx b/examples/document-field/src/app/(admin)/post/[slug]/page.tsx
index ab476cde41d..f132603ad6f 100644
--- a/examples/document-field/src/app/(admin)/post/[slug]/page.tsx
+++ b/examples/document-field/src/app/(admin)/post/[slug]/page.tsx
@@ -79,16 +79,17 @@ export default async function Post ({ params }: { params: any }) {
)
}
-export async function getStaticPaths (): Promise {
- const data = await fetchGraphQL(gql`
- query {
- posts {
- slug
- }
- }
- `)
- return {
- paths: data.posts.map((post: any) => ({ params: { slug: post.slug } })),
- fallback: 'blocking',
- }
-}
+// TODO - CAN NOT use this in app router properly
+// export async function getStaticPaths (): Promise {
+// const data = await fetchGraphQL(gql`
+// query {
+// posts {
+// slug
+// }
+// }
+// `)
+// return {
+// paths: data.posts.map((post: any) => ({ params: { slug: post.slug } })),
+// fallback: 'blocking',
+// }
+// }
diff --git a/packages/core/src/admin-ui/context.tsx b/packages/core/src/admin-ui/context.tsx
index cf0df247597..eff7cff037c 100644
--- a/packages/core/src/admin-ui/context.tsx
+++ b/packages/core/src/admin-ui/context.tsx
@@ -1,3 +1,4 @@
+import { notFound } from 'next/navigation'
import React, { type ReactNode, createContext, useContext, useMemo } from 'react'
import { Center } from '@keystone-ui/core'
import { ToastProvider } from '@keystone-ui/toast'
@@ -164,6 +165,6 @@ export const useList = (key: string) => {
if (lists[key]) {
return lists[key]
} else {
- throw new Error(`Invalid list key provided to useList: ${key}`)
+ return notFound()
}
}
diff --git a/packages/core/src/admin-ui/system/generateAdminUI.ts b/packages/core/src/admin-ui/system/generateAdminUI.ts
index 3ce9d4c074a..9d9984b06f7 100644
--- a/packages/core/src/admin-ui/system/generateAdminUI.ts
+++ b/packages/core/src/admin-ui/system/generateAdminUI.ts
@@ -64,6 +64,7 @@ export async function generateAdminUI (
graphQLSchema: GraphQLSchema,
adminMeta: AdminMetaRootVal,
projectAdminPath: string,
+ hasSrc: boolean,
isLiveReload: boolean
) {
// Write out the files configured by the user
@@ -76,7 +77,7 @@ export async function generateAdminUI (
// Write out the built-in admin UI files. Don't overwrite any user-defined pages.
const configFileExists = getDoesAdminConfigExist(projectAdminPath)
- let adminFiles = writeAdminFiles(config, graphQLSchema, adminMeta, configFileExists)
+ let adminFiles = writeAdminFiles(config, graphQLSchema, adminMeta, configFileExists, hasSrc)
adminFiles = adminFiles.filter(
x => !uniqueFiles.has(Path.normalize(Path.join(projectAdminPath, x.outputPath)))
diff --git a/packages/core/src/admin-ui/templates/index.ts b/packages/core/src/admin-ui/templates/index.ts
index cdf8e2ce5b2..4a64ce87688 100644
--- a/packages/core/src/admin-ui/templates/index.ts
+++ b/packages/core/src/admin-ui/templates/index.ts
@@ -16,14 +16,15 @@ export const writeAdminFiles = (
config: __ResolvedKeystoneConfig,
graphQLSchema: GraphQLSchema,
adminMeta: AdminMetaRootVal,
- configFileExists: boolean
+ configFileExists: boolean,
+ srcExists: boolean,
): AdminFileToWrite[] => {
const ext = config.ui?.tsx ? 'tsx' : 'js'
return [
{
mode: 'write',
- src: nextConfigTemplate(config.ui?.basePath),
- outputPath: '../../next.config.mjs',
+ src: nextConfigTemplate(),
+ outputPath: `${srcExists ? '../' : ''}../../next.config.mjs`,
},
{ mode: 'write', src: noAccessTemplate(config.session), outputPath: `no-access/page.${ext}` },
{ mode: 'write', src: adminLayoutTemplate(), outputPath: `layout.${ext}` },
diff --git a/packages/core/src/admin-ui/templates/next-config.ts b/packages/core/src/admin-ui/templates/next-config.ts
index 8d098b72858..054f1b39c63 100644
--- a/packages/core/src/admin-ui/templates/next-config.ts
+++ b/packages/core/src/admin-ui/templates/next-config.ts
@@ -1,4 +1,4 @@
-export const nextConfigTemplate = (basePath?: string) =>
+export const nextConfigTemplate = () =>
`export default {
experimental: {
// Experimental ESM Externals
diff --git a/packages/core/src/lib/createSystem.ts b/packages/core/src/lib/createSystem.ts
index 789d92a3b03..b4e2ac7a748 100644
--- a/packages/core/src/lib/createSystem.ts
+++ b/packages/core/src/lib/createSystem.ts
@@ -68,6 +68,7 @@ export function getSystemPaths (cwd: string, config: KeystoneConfig | __Resolved
prisma: builtPrismaPath,
graphql: builtGraphqlPath,
},
+ hasSrc,
}
}
diff --git a/packages/core/src/scripts/build.ts b/packages/core/src/scripts/build.ts
index d32f5d8312e..850546c6398 100644
--- a/packages/core/src/scripts/build.ts
+++ b/packages/core/src/scripts/build.ts
@@ -39,7 +39,7 @@ export async function build (
console.log('✨ Generating Admin UI code')
const paths = system.getPaths(cwd)
- await generateAdminUI(system.config, system.graphQLSchema, system.adminMeta, paths.admin, false)
+ await generateAdminUI(system.config, system.graphQLSchema, system.adminMeta, paths.admin, paths.hasSrc, false)
console.log('✨ Building Admin UI')
await nextBuild(
diff --git a/packages/core/src/scripts/dev.ts b/packages/core/src/scripts/dev.ts
index 1d472bc65b9..75b75e52e9a 100644
--- a/packages/core/src/scripts/dev.ts
+++ b/packages/core/src/scripts/dev.ts
@@ -269,7 +269,7 @@ export async function dev (
}
console.log('✨ Generating Admin UI code')
- await generateAdminUI(system.config, system.graphQLSchema, system.adminMeta, paths.admin, false)
+ await generateAdminUI(system.config, system.graphQLSchema, system.adminMeta, paths.admin, paths.hasSrc, false)
console.log('✨ Preparing Admin UI app')
nextApp = next({ dev: true, dir: cwd })
@@ -338,7 +338,7 @@ export async function dev (
}
await generateTypes(cwd, newSystem)
- await generateAdminUI(newSystem.config, newSystem.graphQLSchema, newSystem.adminMeta, paths.admin, true)
+ await generateAdminUI(newSystem.config, newSystem.graphQLSchema, newSystem.adminMeta, paths.admin, paths.hasSrc, true)
if (prismaClientModule) {
if (server && lastApolloServer) {
const { context: newContext } = newSystem.getKeystone(prismaClientModule)
diff --git a/tests/admin-ui-tests/live-reloading.test.ts b/tests/admin-ui-tests/live-reloading.test.ts
index 7b98a5147f1..92c5534e085 100644
--- a/tests/admin-ui-tests/live-reloading.test.ts
+++ b/tests/admin-ui-tests/live-reloading.test.ts
@@ -21,6 +21,8 @@ let ksProcess: ExecaChildProcess = undefined as any
let page: Page = undefined as any
let browser: Browser = undefined as any
+jest.setTimeout(300000) // testing why this one fail
+
test('start keystone', async () => {
// just in case a previous failing test run messed things up, let's reset it
await replaceSchema('initial.ts');
@@ -54,7 +56,7 @@ test('Creating an item with the GraphQL API and navigating to the item page for
expect(value).toBe('blah')
})
-test('api routes written with getAdditionalFiles containing [...rest] work', async () => {
+test.only('api routes written with getAdditionalFiles containing [...rest] work', async () => {
expect(
await fetch('http://localhost:3000/api/blah/asdasdas/das/da/sdad').then(x => x.text())
).toEqual('something')
diff --git a/tests/test-projects/live-reloading/keystone.ts b/tests/test-projects/live-reloading/keystone.ts
index 62b86624edb..43b9d02523e 100644
--- a/tests/test-projects/live-reloading/keystone.ts
+++ b/tests/test-projects/live-reloading/keystone.ts
@@ -19,8 +19,9 @@ export default config({
() => [
{
mode: 'write',
- src: "export default function(req,res) {res.send('something')}",
- outputPath: 'pages/api/blah/[...rest].js',
+ src: "export async function GET() { return new Response('something')}",
+ overwrite: true,
+ outputPath: 'api/blah/[...rest]/route.js',
},
],
],