From 0abc781500feeacf15a9aa83ba9f9cabed7f22d0 Mon Sep 17 00:00:00 2001
From: Gautam Singh <5769869+gautamsi@users.noreply.github.com>
Date: Fri, 13 Dec 2024 21:11:51 -0600
Subject: [PATCH 1/3] generate app router
---
.../website/components/Navigation.tsx | 6 +-
design-system/website/package.json | 2 +-
docs/package.json | 2 +-
examples/auth/app/(admin)/.admin/index.tsx | 21 +
.../auth/app/(admin)/[listKey]/[id]/page.tsx | 4 +
.../app/(admin)/[listKey]/create/page.tsx | 4 +
examples/auth/app/(admin)/[listKey]/page.tsx | 4 +
examples/auth/app/(admin)/init/page.tsx | 7 +
examples/auth/app/(admin)/layout.tsx | 16 +
examples/auth/app/(admin)/no-access/page.tsx | 4 +
examples/auth/app/(admin)/page.tsx | 2 +
examples/auth/app/(admin)/signin/page.tsx | 5 +
examples/auth/app/layout.tsx | 11 +
examples/auth/keystone.ts | 2 +-
examples/auth/next-env.d.ts | 5 +
examples/auth/next.config.mjs | 10 +
examples/auth/package.json | 3 +-
examples/auth/schema.graphql | 401 ++++++++++++++++++
examples/auth/schema.prisma | 51 +++
examples/auth/schema.ts | 74 +++-
examples/auth/tsconfig.json | 34 ++
.../app/(admin)/.admin/index.tsx | 18 +
.../app/(admin)/[listKey]/[id]/page.tsx | 4 +
.../app/(admin)/[listKey]/create/page.tsx | 4 +
.../app/(admin)/[listKey]/page.tsx | 4 +
.../app/(admin)/config.tsx | 1 +
.../app/(admin)/layout.tsx | 16 +
.../app/(admin)/no-access/page.tsx | 4 +
.../custom-admin-ui-logo/app/(admin)/page.tsx | 2 +
.../config}/components/CustomLogo.tsx | 0
.../config.tsx => app/config/index.tsx} | 0
examples/custom-admin-ui-logo/app/layout.tsx | 11 +
examples/custom-admin-ui-logo/next-env.d.ts | 5 +
examples/custom-admin-ui-logo/package.json | 2 +-
examples/custom-admin-ui-logo/tsconfig.json | 34 ++
.../app/(admin)/.admin/index.tsx | 18 +
.../app/(admin)/[listKey]/[id]/page.tsx | 4 +
.../app/(admin)/[listKey]/create/page.tsx | 4 +
.../app/(admin)/[listKey]/page.tsx | 4 +
.../app/(admin)/config.tsx | 1 +
.../app/(admin)/layout.tsx | 16 +
.../app/(admin)/no-access/page.tsx | 4 +
.../app/(admin)/page.tsx | 2 +
.../config}/components/CustomNavigation.tsx | 0
.../{admin/config.ts => app/config/index.ts} | 0
.../custom-admin-ui-navigation/app/layout.tsx | 11 +
.../custom-admin-ui-navigation/next-env.d.ts | 5 +
.../custom-admin-ui-navigation/tsconfig.json | 34 ++
.../app/(admin)/.admin/index.tsx | 18 +
.../app/(admin)/[listKey]/[id]/page.tsx | 4 +
.../app/(admin)/[listKey]/create/page.tsx | 4 +
.../app/(admin)/[listKey]/page.tsx | 4 +
.../app/(admin)/config.tsx | 1 +
.../(admin)/custom-page/page.tsx} | 9 +-
.../app/(admin)/layout.tsx | 16 +
.../app/(admin)/no-access/page.tsx | 4 +
.../app/(admin)/page.tsx | 2 +
.../config}/components/CustomNavigation.tsx | 0
.../{admin/config.ts => app/config/index.ts} | 0
examples/custom-admin-ui-pages/app/layout.tsx | 11 +
examples/custom-admin-ui-pages/next-env.d.ts | 5 +
examples/custom-admin-ui-pages/package.json | 2 +-
examples/custom-admin-ui-pages/tsconfig.json | 34 ++
.../app/(admin)/.admin/index.tsx | 21 +
.../app/(admin)/[listKey]/[id]/page.tsx | 4 +
.../app/(admin)/[listKey]/create/page.tsx | 4 +
.../app/(admin)/[listKey]/page.tsx | 4 +
.../custom-field-view/app/(admin)/layout.tsx | 16 +
.../app/(admin)/no-access/page.tsx | 4 +
.../custom-field-view/app/(admin)/page.tsx | 2 +
examples/custom-field-view/app/layout.tsx | 11 +
examples/custom-field-view/next-env.d.ts | 5 +
examples/custom-field-view/package.json | 2 +-
examples/custom-field-view/schema.graphql | 3 +
examples/custom-field-view/schema.prisma | 1 +
examples/custom-field-view/schema.ts | 8 +
examples/custom-field-view/tsconfig.json | 37 ++
.../custom-field/app/(admin)/.admin/index.tsx | 19 +
.../app/(admin)/[listKey]/[id]/page.tsx | 4 +
.../app/(admin)/[listKey]/create/page.tsx | 4 +
.../app/(admin)/[listKey]/page.tsx | 4 +
examples/custom-field/app/(admin)/layout.tsx | 16 +
.../app/(admin)/no-access/page.tsx | 4 +
examples/custom-field/app/(admin)/page.tsx | 2 +
examples/custom-field/app/layout.tsx | 11 +
examples/custom-field/next-env.d.ts | 5 +
examples/custom-field/tsconfig.json | 37 ++
examples/custom-output-paths/package.json | 2 +-
.../nextjs-frontend/package.json | 2 +-
examples/document-field/README.md | 10 +-
examples/document-field/next-env.d.ts | 5 +-
examples/document-field/next.config.js | 5 -
examples/document-field/next.config.mjs | 16 +
examples/document-field/package.json | 3 +-
.../src/app/(admin)/.admin/index.tsx | 18 +
.../src/app/(admin)/[listKey]/[id]/page.tsx | 4 +
.../src/app/(admin)/[listKey]/create/page.tsx | 4 +
.../src/app/(admin)/[listKey]/page.tsx | 4 +
.../src/app/(admin)/author/[id]/page.tsx | 57 +++
.../document-field/src/app/(admin)/layout.tsx | 16 +
.../src/app/(admin)/no-access/page.tsx | 4 +
.../document-field/src/app/(admin)/page.tsx | 2 +
.../(admin)/post/[slug]/page.tsx} | 74 ++--
examples/document-field/src/app/layout.tsx | 11 +
.../{pages/index.tsx => app/site/page.tsx} | 50 ++-
.../document-field/src/{ => app}/utils.tsx | 0
.../document-field/src/pages/author/[id].tsx | 59 ---
examples/document-field/tsconfig.json | 25 +-
.../package.json | 2 +-
.../package.json | 2 +-
.../nextjs-frontend/package.json | 2 +-
packages/auth/src/index.ts | 10 +-
packages/auth/src/lib/useFromRedirect.ts | 6 -
packages/auth/src/pages/InitPage.tsx | 11 +-
packages/auth/src/pages/SigninPage.tsx | 12 +-
packages/auth/src/templates/init.ts | 8 +-
packages/auth/src/templates/signin.ts | 6 +-
packages/core/package.json | 2 +-
.../admin-ui/pages/App/index.tsx | 17 +-
.../admin-ui/pages/CreateItemPage/index.tsx | 16 +-
.../admin-ui/pages/HomePage/index.tsx | 12 +-
.../admin-ui/pages/ItemPage/common.tsx | 5 +-
.../admin-ui/pages/ItemPage/index.tsx | 20 +-
.../pages/ListPage/FieldSelection.tsx | 2 +-
.../admin-ui/pages/ListPage/FilterList.tsx | 2 +-
.../admin-ui/pages/ListPage/index.tsx | 31 +-
.../admin-ui/components/CreateButtonLink.tsx | 4 +-
.../core/src/admin-ui/components/Logo.tsx | 4 +-
.../src/admin-ui/components/Navigation.tsx | 16 +-
packages/core/src/admin-ui/context.tsx | 15 +-
packages/core/src/admin-ui/router.tsx | 43 +-
.../src/admin-ui/system/generateAdminUI.ts | 110 ++---
packages/core/src/admin-ui/templates/app.ts | 74 +++-
.../src/admin-ui/templates/create-item.ts | 6 +-
packages/core/src/admin-ui/templates/home.ts | 3 +-
packages/core/src/admin-ui/templates/index.ts | 43 +-
packages/core/src/admin-ui/templates/item.tsx | 6 +-
packages/core/src/admin-ui/templates/list.tsx | 6 +-
.../src/admin-ui/templates/next-config.ts | 32 +-
.../core/src/admin-ui/templates/no-access.ts | 5 +-
.../admin-ui/utils/usePreventNavigation.tsx | 53 ++-
.../types/relationship/views/cards/index.tsx | 5 +-
.../fields/types/relationship/views/index.tsx | 14 +-
.../core/src/lib/createAdminUIMiddleware.ts | 2 +-
packages/core/src/lib/createSystem.ts | 12 +-
packages/core/src/lib/defaults.ts | 5 +-
packages/core/src/lib/id-field.ts | 3 +-
packages/core/src/schema.ts | 3 +-
packages/core/src/scripts/build.ts | 4 +-
packages/core/src/scripts/cli.ts | 6 +-
packages/core/src/scripts/dev.ts | 12 +-
packages/core/src/scripts/start.ts | 4 +-
packages/core/src/types/config/index.ts | 6 +-
pnpm-lock.yaml | 204 +++++----
tests/admin-ui-tests/live-reloading.test.ts | 4 +-
.../fields/types/relationship.test.ts | 4 +-
.../test-projects/live-reloading/keystone.ts | 5 +-
157 files changed, 1907 insertions(+), 561 deletions(-)
create mode 100644 examples/auth/app/(admin)/.admin/index.tsx
create mode 100644 examples/auth/app/(admin)/[listKey]/[id]/page.tsx
create mode 100644 examples/auth/app/(admin)/[listKey]/create/page.tsx
create mode 100644 examples/auth/app/(admin)/[listKey]/page.tsx
create mode 100644 examples/auth/app/(admin)/init/page.tsx
create mode 100644 examples/auth/app/(admin)/layout.tsx
create mode 100644 examples/auth/app/(admin)/no-access/page.tsx
create mode 100644 examples/auth/app/(admin)/page.tsx
create mode 100644 examples/auth/app/(admin)/signin/page.tsx
create mode 100644 examples/auth/app/layout.tsx
create mode 100644 examples/auth/next-env.d.ts
create mode 100644 examples/auth/next.config.mjs
create mode 100644 examples/auth/tsconfig.json
create mode 100644 examples/custom-admin-ui-logo/app/(admin)/.admin/index.tsx
create mode 100644 examples/custom-admin-ui-logo/app/(admin)/[listKey]/[id]/page.tsx
create mode 100644 examples/custom-admin-ui-logo/app/(admin)/[listKey]/create/page.tsx
create mode 100644 examples/custom-admin-ui-logo/app/(admin)/[listKey]/page.tsx
create mode 100644 examples/custom-admin-ui-logo/app/(admin)/config.tsx
create mode 100644 examples/custom-admin-ui-logo/app/(admin)/layout.tsx
create mode 100644 examples/custom-admin-ui-logo/app/(admin)/no-access/page.tsx
create mode 100644 examples/custom-admin-ui-logo/app/(admin)/page.tsx
rename examples/custom-admin-ui-logo/{admin => app/config}/components/CustomLogo.tsx (100%)
rename examples/custom-admin-ui-logo/{admin/config.tsx => app/config/index.tsx} (100%)
create mode 100644 examples/custom-admin-ui-logo/app/layout.tsx
create mode 100644 examples/custom-admin-ui-logo/next-env.d.ts
create mode 100644 examples/custom-admin-ui-logo/tsconfig.json
create mode 100644 examples/custom-admin-ui-navigation/app/(admin)/.admin/index.tsx
create mode 100644 examples/custom-admin-ui-navigation/app/(admin)/[listKey]/[id]/page.tsx
create mode 100644 examples/custom-admin-ui-navigation/app/(admin)/[listKey]/create/page.tsx
create mode 100644 examples/custom-admin-ui-navigation/app/(admin)/[listKey]/page.tsx
create mode 100644 examples/custom-admin-ui-navigation/app/(admin)/config.tsx
create mode 100644 examples/custom-admin-ui-navigation/app/(admin)/layout.tsx
create mode 100644 examples/custom-admin-ui-navigation/app/(admin)/no-access/page.tsx
create mode 100644 examples/custom-admin-ui-navigation/app/(admin)/page.tsx
rename examples/custom-admin-ui-navigation/{admin => app/config}/components/CustomNavigation.tsx (100%)
rename examples/custom-admin-ui-navigation/{admin/config.ts => app/config/index.ts} (100%)
create mode 100644 examples/custom-admin-ui-navigation/app/layout.tsx
create mode 100644 examples/custom-admin-ui-navigation/next-env.d.ts
create mode 100644 examples/custom-admin-ui-navigation/tsconfig.json
create mode 100644 examples/custom-admin-ui-pages/app/(admin)/.admin/index.tsx
create mode 100644 examples/custom-admin-ui-pages/app/(admin)/[listKey]/[id]/page.tsx
create mode 100644 examples/custom-admin-ui-pages/app/(admin)/[listKey]/create/page.tsx
create mode 100644 examples/custom-admin-ui-pages/app/(admin)/[listKey]/page.tsx
create mode 100644 examples/custom-admin-ui-pages/app/(admin)/config.tsx
rename examples/custom-admin-ui-pages/{admin/pages/custom-page.tsx => app/(admin)/custom-page/page.tsx} (87%)
create mode 100644 examples/custom-admin-ui-pages/app/(admin)/layout.tsx
create mode 100644 examples/custom-admin-ui-pages/app/(admin)/no-access/page.tsx
create mode 100644 examples/custom-admin-ui-pages/app/(admin)/page.tsx
rename examples/custom-admin-ui-pages/{admin => app/config}/components/CustomNavigation.tsx (100%)
rename examples/custom-admin-ui-pages/{admin/config.ts => app/config/index.ts} (100%)
create mode 100644 examples/custom-admin-ui-pages/app/layout.tsx
create mode 100644 examples/custom-admin-ui-pages/next-env.d.ts
create mode 100644 examples/custom-admin-ui-pages/tsconfig.json
create mode 100644 examples/custom-field-view/app/(admin)/.admin/index.tsx
create mode 100644 examples/custom-field-view/app/(admin)/[listKey]/[id]/page.tsx
create mode 100644 examples/custom-field-view/app/(admin)/[listKey]/create/page.tsx
create mode 100644 examples/custom-field-view/app/(admin)/[listKey]/page.tsx
create mode 100644 examples/custom-field-view/app/(admin)/layout.tsx
create mode 100644 examples/custom-field-view/app/(admin)/no-access/page.tsx
create mode 100644 examples/custom-field-view/app/(admin)/page.tsx
create mode 100644 examples/custom-field-view/app/layout.tsx
create mode 100644 examples/custom-field-view/next-env.d.ts
create mode 100644 examples/custom-field-view/tsconfig.json
create mode 100644 examples/custom-field/app/(admin)/.admin/index.tsx
create mode 100644 examples/custom-field/app/(admin)/[listKey]/[id]/page.tsx
create mode 100644 examples/custom-field/app/(admin)/[listKey]/create/page.tsx
create mode 100644 examples/custom-field/app/(admin)/[listKey]/page.tsx
create mode 100644 examples/custom-field/app/(admin)/layout.tsx
create mode 100644 examples/custom-field/app/(admin)/no-access/page.tsx
create mode 100644 examples/custom-field/app/(admin)/page.tsx
create mode 100644 examples/custom-field/app/layout.tsx
create mode 100644 examples/custom-field/next-env.d.ts
create mode 100644 examples/custom-field/tsconfig.json
delete mode 100644 examples/document-field/next.config.js
create mode 100644 examples/document-field/next.config.mjs
create mode 100644 examples/document-field/src/app/(admin)/.admin/index.tsx
create mode 100644 examples/document-field/src/app/(admin)/[listKey]/[id]/page.tsx
create mode 100644 examples/document-field/src/app/(admin)/[listKey]/create/page.tsx
create mode 100644 examples/document-field/src/app/(admin)/[listKey]/page.tsx
create mode 100644 examples/document-field/src/app/(admin)/author/[id]/page.tsx
create mode 100644 examples/document-field/src/app/(admin)/layout.tsx
create mode 100644 examples/document-field/src/app/(admin)/no-access/page.tsx
create mode 100644 examples/document-field/src/app/(admin)/page.tsx
rename examples/document-field/src/{pages/post/[slug].tsx => app/(admin)/post/[slug]/page.tsx} (80%)
create mode 100644 examples/document-field/src/app/layout.tsx
rename examples/document-field/src/{pages/index.tsx => app/site/page.tsx} (58%)
rename examples/document-field/src/{ => app}/utils.tsx (100%)
delete mode 100644 examples/document-field/src/pages/author/[id].tsx
delete mode 100644 packages/auth/src/lib/useFromRedirect.ts
diff --git a/design-system/website/components/Navigation.tsx b/design-system/website/components/Navigation.tsx
index f93a7e9ea14..c8e52158799 100644
--- a/design-system/website/components/Navigation.tsx
+++ b/design-system/website/components/Navigation.tsx
@@ -4,7 +4,7 @@
import { Fragment, type ReactNode } from 'react'
import { jsx, useTheme } from '@keystone-ui/core'
import Link from 'next/link'
-import { useRouter } from 'next/router'
+import { usePathname } from 'next/navigation'
const Brand = () => {
const { palette } = useTheme()
@@ -37,8 +37,8 @@ const Section = ({ label, children }: SectionProps) => {
type NavItemProps = { href: string, children: ReactNode }
const NavItem = ({ href, children }: NavItemProps) => {
const { palette, radii, spacing } = useTheme()
- const router = useRouter()
- const isSelected = router.pathname === href
+ const pathname = usePathname()
+ const isSelected = pathname === href
return (
+ {children}
+
+ )
+}
\ No newline at end of file
diff --git a/examples/auth/app/(admin)/no-access/page.tsx b/examples/auth/app/(admin)/no-access/page.tsx
new file mode 100644
index 00000000000..00571f2f9b3
--- /dev/null
+++ b/examples/auth/app/(admin)/no-access/page.tsx
@@ -0,0 +1,4 @@
+'use client'
+import { getNoAccessPage } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/NoAccessPage'
+
+export default getNoAccessPage({ sessionsEnabled: true })
diff --git a/examples/auth/app/(admin)/page.tsx b/examples/auth/app/(admin)/page.tsx
new file mode 100644
index 00000000000..5c268390b0f
--- /dev/null
+++ b/examples/auth/app/(admin)/page.tsx
@@ -0,0 +1,2 @@
+'use client'
+export { HomePage as default } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/HomePage'
diff --git a/examples/auth/app/(admin)/signin/page.tsx b/examples/auth/app/(admin)/signin/page.tsx
new file mode 100644
index 00000000000..ef30e38dcac
--- /dev/null
+++ b/examples/auth/app/(admin)/signin/page.tsx
@@ -0,0 +1,5 @@
+'use client'
+/* eslint-disable */
+import { getSigninPage } from '@keystone-6/auth/pages/SigninPage'
+
+export default getSigninPage({"identityField":"name","secretField":"password","mutationName":"authenticateUserWithPassword","successTypename":"UserAuthenticationWithPasswordSuccess","failureTypename":"UserAuthenticationWithPasswordFailure"})
diff --git a/examples/auth/app/layout.tsx b/examples/auth/app/layout.tsx
new file mode 100644
index 00000000000..38a4853e3a5
--- /dev/null
+++ b/examples/auth/app/layout.tsx
@@ -0,0 +1,11 @@
+export default function RootLayout ({
+ children,
+}: {
+ children: React.ReactNode
+}) {
+ return (
+
+ {children}
+
+ )
+}
diff --git a/examples/auth/keystone.ts b/examples/auth/keystone.ts
index ee96e919f1e..5d2b780a3f5 100644
--- a/examples/auth/keystone.ts
+++ b/examples/auth/keystone.ts
@@ -70,5 +70,5 @@ export default withAuth>(
// the session secret is used to encrypt cookie data
secret: sessionSecret,
}),
- })
+ }) as any
)
diff --git a/examples/auth/next-env.d.ts b/examples/auth/next-env.d.ts
new file mode 100644
index 00000000000..4f11a03dc6c
--- /dev/null
+++ b/examples/auth/next-env.d.ts
@@ -0,0 +1,5 @@
+///
+///
+
+// NOTE: This file should not be edited
+// see https://nextjs.org/docs/basic-features/typescript for more information.
diff --git a/examples/auth/next.config.mjs b/examples/auth/next.config.mjs
new file mode 100644
index 00000000000..8f06b183bdf
--- /dev/null
+++ b/examples/auth/next.config.mjs
@@ -0,0 +1,10 @@
+// you don't need this if you're building something outside of the Keystone repo
+
+export default {
+ eslint: {
+ ignoreDuringBuilds: true,
+ },
+ typescript: {
+ ignoreBuildErrors: true,
+ },
+}
diff --git a/examples/auth/package.json b/examples/auth/package.json
index ae92a461563..45ee13412f7 100644
--- a/examples/auth/package.json
+++ b/examples/auth/package.json
@@ -12,7 +12,8 @@
"dependencies": {
"@keystone-6/auth": "^8.1.0",
"@keystone-6/core": "^6.3.1",
- "@prisma/client": "5.19.0"
+ "@prisma/client": "5.19.0",
+ "next": "^15.0.0"
},
"devDependencies": {
"prisma": "5.19.0",
diff --git a/examples/auth/schema.graphql b/examples/auth/schema.graphql
index 246333e2b9e..da46536e183 100644
--- a/examples/auth/schema.graphql
+++ b/examples/auth/schema.graphql
@@ -67,6 +67,380 @@ input UserCreateInput {
isAdmin: Boolean
}
+type Project {
+ id: ID!
+ slug: String
+ name: String
+ createdAt: DateTime
+ updatedAt: DateTime
+ deletedAt: DateTime
+ taskRuns(where: TaskRunWhereInput! = {}, orderBy: [TaskRunOrderByInput!]! = [], take: Int, skip: Int! = 0, cursor: TaskRunWhereUniqueInput): [TaskRun!]
+ taskRunsCount(where: TaskRunWhereInput! = {}): Int
+}
+
+scalar DateTime @specifiedBy(url: "https://datatracker.ietf.org/doc/html/rfc3339#section-5.6")
+
+input ProjectWhereUniqueInput {
+ id: ID
+ slug: String
+}
+
+input ProjectWhereInput {
+ AND: [ProjectWhereInput!]
+ OR: [ProjectWhereInput!]
+ NOT: [ProjectWhereInput!]
+ id: IDFilter
+ slug: StringFilter
+ name: StringFilter
+ createdAt: DateTimeNullableFilter
+ updatedAt: DateTimeNullableFilter
+ deletedAt: DateTimeNullableFilter
+ taskRuns: TaskRunManyRelationFilter
+}
+
+input StringFilter {
+ equals: String
+ in: [String!]
+ notIn: [String!]
+ lt: String
+ lte: String
+ gt: String
+ gte: String
+ contains: String
+ startsWith: String
+ endsWith: String
+ not: NestedStringFilter
+}
+
+input NestedStringFilter {
+ equals: String
+ in: [String!]
+ notIn: [String!]
+ lt: String
+ lte: String
+ gt: String
+ gte: String
+ contains: String
+ startsWith: String
+ endsWith: String
+ not: NestedStringFilter
+}
+
+input DateTimeNullableFilter {
+ equals: DateTime
+ in: [DateTime!]
+ notIn: [DateTime!]
+ lt: DateTime
+ lte: DateTime
+ gt: DateTime
+ gte: DateTime
+ not: DateTimeNullableFilter
+}
+
+input TaskRunManyRelationFilter {
+ every: TaskRunWhereInput
+ some: TaskRunWhereInput
+ none: TaskRunWhereInput
+}
+
+input ProjectOrderByInput {
+ id: OrderDirection
+ slug: OrderDirection
+ name: OrderDirection
+ createdAt: OrderDirection
+ updatedAt: OrderDirection
+ deletedAt: OrderDirection
+}
+
+input ProjectUpdateInput {
+ slug: String
+ name: String
+ createdAt: DateTime
+ updatedAt: DateTime
+ deletedAt: DateTime
+ taskRuns: TaskRunRelateToManyForUpdateInput
+}
+
+input TaskRunRelateToManyForUpdateInput {
+ disconnect: [TaskRunWhereUniqueInput!]
+ set: [TaskRunWhereUniqueInput!]
+ create: [TaskRunCreateInput!]
+ connect: [TaskRunWhereUniqueInput!]
+}
+
+input ProjectUpdateArgs {
+ where: ProjectWhereUniqueInput!
+ data: ProjectUpdateInput!
+}
+
+input ProjectCreateInput {
+ slug: String
+ name: String
+ createdAt: DateTime
+ updatedAt: DateTime
+ deletedAt: DateTime
+ taskRuns: TaskRunRelateToManyForCreateInput
+}
+
+input TaskRunRelateToManyForCreateInput {
+ create: [TaskRunCreateInput!]
+ connect: [TaskRunWhereUniqueInput!]
+}
+
+type TaskRun {
+ id: ID!
+ number: Int
+ friendlyId: String
+ status: String
+ taskIdentifier: String
+ isTest: Boolean
+ payload: String
+ payloadType: String
+ context: JSON
+ traceId: String
+ spanId: String
+ project: Project
+ createdAt: DateTime
+ updatedAt: DateTime
+ attempts(where: TaskRunAttemptWhereInput! = {}, orderBy: [TaskRunAttemptOrderByInput!]! = [], take: Int, skip: Int! = 0, cursor: TaskRunAttemptWhereUniqueInput): [TaskRunAttempt!]
+ attemptsCount(where: TaskRunAttemptWhereInput! = {}): Int
+ startedAt: DateTime
+ completedAt: DateTime
+}
+
+input TaskRunWhereUniqueInput {
+ id: ID
+}
+
+input TaskRunWhereInput {
+ AND: [TaskRunWhereInput!]
+ OR: [TaskRunWhereInput!]
+ NOT: [TaskRunWhereInput!]
+ id: IDFilter
+ number: IntNullableFilter
+ friendlyId: StringFilter
+ status: StringNullableFilter
+ taskIdentifier: StringFilter
+ isTest: BooleanFilter
+ payload: StringFilter
+ payloadType: StringFilter
+ traceId: StringFilter
+ spanId: StringFilter
+ project: ProjectWhereInput
+ createdAt: DateTimeNullableFilter
+ updatedAt: DateTimeNullableFilter
+ attempts: TaskRunAttemptManyRelationFilter
+ startedAt: DateTimeNullableFilter
+ completedAt: DateTimeNullableFilter
+}
+
+input IntNullableFilter {
+ equals: Int
+ in: [Int!]
+ notIn: [Int!]
+ lt: Int
+ lte: Int
+ gt: Int
+ gte: Int
+ not: IntNullableFilter
+}
+
+input StringNullableFilter {
+ equals: String
+ in: [String!]
+ notIn: [String!]
+ lt: String
+ lte: String
+ gt: String
+ gte: String
+ contains: String
+ startsWith: String
+ endsWith: String
+ not: StringNullableFilter
+}
+
+input TaskRunAttemptManyRelationFilter {
+ every: TaskRunAttemptWhereInput
+ some: TaskRunAttemptWhereInput
+ none: TaskRunAttemptWhereInput
+}
+
+input TaskRunOrderByInput {
+ id: OrderDirection
+ number: OrderDirection
+ friendlyId: OrderDirection
+ status: OrderDirection
+ taskIdentifier: OrderDirection
+ isTest: OrderDirection
+ payload: OrderDirection
+ payloadType: OrderDirection
+ traceId: OrderDirection
+ spanId: OrderDirection
+ createdAt: OrderDirection
+ updatedAt: OrderDirection
+ startedAt: OrderDirection
+ completedAt: OrderDirection
+}
+
+input TaskRunUpdateInput {
+ number: Int
+ friendlyId: String
+ status: String
+ taskIdentifier: String
+ isTest: Boolean
+ payload: String
+ payloadType: String
+ context: JSON
+ traceId: String
+ spanId: String
+ project: ProjectRelateToOneForUpdateInput
+ createdAt: DateTime
+ updatedAt: DateTime
+ attempts: TaskRunAttemptRelateToManyForUpdateInput
+ startedAt: DateTime
+ completedAt: DateTime
+}
+
+input ProjectRelateToOneForUpdateInput {
+ create: ProjectCreateInput
+ connect: ProjectWhereUniqueInput
+ disconnect: Boolean
+}
+
+input TaskRunAttemptRelateToManyForUpdateInput {
+ disconnect: [TaskRunAttemptWhereUniqueInput!]
+ set: [TaskRunAttemptWhereUniqueInput!]
+ create: [TaskRunAttemptCreateInput!]
+ connect: [TaskRunAttemptWhereUniqueInput!]
+}
+
+input TaskRunUpdateArgs {
+ where: TaskRunWhereUniqueInput!
+ data: TaskRunUpdateInput!
+}
+
+input TaskRunCreateInput {
+ number: Int
+ friendlyId: String
+ status: String
+ taskIdentifier: String
+ isTest: Boolean
+ payload: String
+ payloadType: String
+ context: JSON
+ traceId: String
+ spanId: String
+ project: ProjectRelateToOneForCreateInput
+ createdAt: DateTime
+ updatedAt: DateTime
+ attempts: TaskRunAttemptRelateToManyForCreateInput
+ startedAt: DateTime
+ completedAt: DateTime
+}
+
+input ProjectRelateToOneForCreateInput {
+ create: ProjectCreateInput
+ connect: ProjectWhereUniqueInput
+}
+
+input TaskRunAttemptRelateToManyForCreateInput {
+ create: [TaskRunAttemptCreateInput!]
+ connect: [TaskRunAttemptWhereUniqueInput!]
+}
+
+type TaskRunAttempt {
+ id: ID!
+ number: Int
+ friendlyId: String
+ taskRun: TaskRun
+ status: String
+ createdAt: DateTime
+ updatedAt: DateTime
+ startedAt: DateTime
+ completedAt: DateTime
+ error: JSON
+ output: String
+ outputType: String
+}
+
+input TaskRunAttemptWhereUniqueInput {
+ id: ID
+}
+
+input TaskRunAttemptWhereInput {
+ AND: [TaskRunAttemptWhereInput!]
+ OR: [TaskRunAttemptWhereInput!]
+ NOT: [TaskRunAttemptWhereInput!]
+ id: IDFilter
+ number: IntNullableFilter
+ friendlyId: StringFilter
+ taskRun: TaskRunWhereInput
+ status: StringNullableFilter
+ createdAt: DateTimeNullableFilter
+ updatedAt: DateTimeNullableFilter
+ startedAt: DateTimeNullableFilter
+ completedAt: DateTimeNullableFilter
+ output: StringFilter
+ outputType: StringFilter
+}
+
+input TaskRunAttemptOrderByInput {
+ id: OrderDirection
+ number: OrderDirection
+ friendlyId: OrderDirection
+ status: OrderDirection
+ createdAt: OrderDirection
+ updatedAt: OrderDirection
+ startedAt: OrderDirection
+ completedAt: OrderDirection
+ output: OrderDirection
+ outputType: OrderDirection
+}
+
+input TaskRunAttemptUpdateInput {
+ number: Int
+ friendlyId: String
+ taskRun: TaskRunRelateToOneForUpdateInput
+ status: String
+ createdAt: DateTime
+ updatedAt: DateTime
+ startedAt: DateTime
+ completedAt: DateTime
+ error: JSON
+ output: String
+ outputType: String
+}
+
+input TaskRunRelateToOneForUpdateInput {
+ create: TaskRunCreateInput
+ connect: TaskRunWhereUniqueInput
+ disconnect: Boolean
+}
+
+input TaskRunAttemptUpdateArgs {
+ where: TaskRunAttemptWhereUniqueInput!
+ data: TaskRunAttemptUpdateInput!
+}
+
+input TaskRunAttemptCreateInput {
+ number: Int
+ friendlyId: String
+ taskRun: TaskRunRelateToOneForCreateInput
+ status: String
+ createdAt: DateTime
+ updatedAt: DateTime
+ startedAt: DateTime
+ completedAt: DateTime
+ error: JSON
+ output: String
+ outputType: String
+}
+
+input TaskRunRelateToOneForCreateInput {
+ create: TaskRunCreateInput
+ connect: TaskRunWhereUniqueInput
+}
+
"""
The `JSON` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf).
"""
@@ -79,6 +453,24 @@ type Mutation {
updateUsers(data: [UserUpdateArgs!]!): [User]
deleteUser(where: UserWhereUniqueInput!): User
deleteUsers(where: [UserWhereUniqueInput!]!): [User]
+ createProject(data: ProjectCreateInput!): Project
+ createProjects(data: [ProjectCreateInput!]!): [Project]
+ updateProject(where: ProjectWhereUniqueInput!, data: ProjectUpdateInput!): Project
+ updateProjects(data: [ProjectUpdateArgs!]!): [Project]
+ deleteProject(where: ProjectWhereUniqueInput!): Project
+ deleteProjects(where: [ProjectWhereUniqueInput!]!): [Project]
+ createTaskRun(data: TaskRunCreateInput!): TaskRun
+ createTaskRuns(data: [TaskRunCreateInput!]!): [TaskRun]
+ updateTaskRun(where: TaskRunWhereUniqueInput!, data: TaskRunUpdateInput!): TaskRun
+ updateTaskRuns(data: [TaskRunUpdateArgs!]!): [TaskRun]
+ deleteTaskRun(where: TaskRunWhereUniqueInput!): TaskRun
+ deleteTaskRuns(where: [TaskRunWhereUniqueInput!]!): [TaskRun]
+ createTaskRunAttempt(data: TaskRunAttemptCreateInput!): TaskRunAttempt
+ createTaskRunAttempts(data: [TaskRunAttemptCreateInput!]!): [TaskRunAttempt]
+ updateTaskRunAttempt(where: TaskRunAttemptWhereUniqueInput!, data: TaskRunAttemptUpdateInput!): TaskRunAttempt
+ updateTaskRunAttempts(data: [TaskRunAttemptUpdateArgs!]!): [TaskRunAttempt]
+ deleteTaskRunAttempt(where: TaskRunAttemptWhereUniqueInput!): TaskRunAttempt
+ deleteTaskRunAttempts(where: [TaskRunAttemptWhereUniqueInput!]!): [TaskRunAttempt]
endSession: Boolean!
authenticateUserWithPassword(name: String!, password: String!): UserAuthenticationWithPasswordResult
createInitialUser(data: CreateInitialUserInput!): UserAuthenticationWithPasswordSuccess!
@@ -104,6 +496,15 @@ type Query {
user(where: UserWhereUniqueInput!): User
users(where: UserWhereInput! = {}, orderBy: [UserOrderByInput!]! = [], take: Int, skip: Int! = 0, cursor: UserWhereUniqueInput): [User!]
usersCount(where: UserWhereInput! = {}): Int
+ projects(where: ProjectWhereInput! = {}, orderBy: [ProjectOrderByInput!]! = [], take: Int, skip: Int! = 0, cursor: ProjectWhereUniqueInput): [Project!]
+ project(where: ProjectWhereUniqueInput!): Project
+ projectsCount(where: ProjectWhereInput! = {}): Int
+ taskRuns(where: TaskRunWhereInput! = {}, orderBy: [TaskRunOrderByInput!]! = [], take: Int, skip: Int! = 0, cursor: TaskRunWhereUniqueInput): [TaskRun!]
+ taskRun(where: TaskRunWhereUniqueInput!): TaskRun
+ taskRunsCount(where: TaskRunWhereInput! = {}): Int
+ taskRunAttempts(where: TaskRunAttemptWhereInput! = {}, orderBy: [TaskRunAttemptOrderByInput!]! = [], take: Int, skip: Int! = 0, cursor: TaskRunAttemptWhereUniqueInput): [TaskRunAttempt!]
+ taskRunAttempt(where: TaskRunAttemptWhereUniqueInput!): TaskRunAttempt
+ taskRunAttemptsCount(where: TaskRunAttemptWhereInput! = {}): Int
keystone: KeystoneMeta!
authenticatedItem: AuthenticatedItem
}
diff --git a/examples/auth/schema.prisma b/examples/auth/schema.prisma
index 44c1400b78b..a711ebf4eee 100644
--- a/examples/auth/schema.prisma
+++ b/examples/auth/schema.prisma
@@ -18,3 +18,54 @@ model User {
password String
isAdmin Boolean @default(false)
}
+
+model Project {
+ id String @id @default(cuid())
+ slug String @unique @default("")
+ name String @default("")
+ createdAt DateTime? @default(now())
+ updatedAt DateTime? @default(now()) @updatedAt
+ deletedAt DateTime?
+ taskRuns TaskRun[] @relation("TaskRun_project")
+}
+
+model TaskRun {
+ id String @id @default(cuid())
+ number Int? @default(0)
+ friendlyId String @default("")
+ status String? @default("pending")
+ taskIdentifier String @default("")
+ isTest Boolean @default(false)
+ payload String @default("")
+ payloadType String @default("application/json")
+ context String?
+ traceId String @default("")
+ spanId String @default("")
+ project Project? @relation("TaskRun_project", fields: [projectId], references: [id])
+ projectId String? @map("project")
+ createdAt DateTime? @default(now())
+ updatedAt DateTime? @default(now()) @updatedAt
+ attempts TaskRunAttempt[] @relation("TaskRunAttempt_taskRun")
+ startedAt DateTime?
+ completedAt DateTime?
+
+ @@index([projectId])
+}
+
+model TaskRunAttempt {
+ id String @id @default(cuid())
+ number Int? @default(0)
+ friendlyId String @default("")
+ taskRun TaskRun? @relation("TaskRunAttempt_taskRun", fields: [taskRunId], references: [id])
+ taskRunId String? @map("taskRun")
+ status String? @default("pending")
+ createdAt DateTime? @default(now())
+ updatedAt DateTime? @default(now()) @updatedAt
+ startedAt DateTime?
+ completedAt DateTime?
+ error String?
+ output String @default("")
+ outputType String @default("application/json")
+
+ @@index([taskRunId])
+}
diff --git a/examples/auth/schema.ts b/examples/auth/schema.ts
index 2879ee9f407..a657f6863c2 100644
--- a/examples/auth/schema.ts
+++ b/examples/auth/schema.ts
@@ -1,6 +1,6 @@
import { list } from '@keystone-6/core'
import { allowAll, denyAll } from '@keystone-6/core/access'
-import { text, checkbox, password } from '@keystone-6/core/fields'
+import { text, checkbox, password, timestamp, relationship, json, select, integer } from '@keystone-6/core/fields'
import type { Lists } from '.keystone/types'
// WARNING: this example is for demonstration purposes only
@@ -153,4 +153,76 @@ export const lists = {
}),
},
}),
+ Project: list({
+ access: allowAll,
+
+ fields: {
+ slug: text({ isIndexed: 'unique' }),
+ name: text({ validation: { isRequired: true } }),
+ createdAt: timestamp({ defaultValue: { kind: 'now' } }),
+ updatedAt: timestamp({ defaultValue: { kind: 'now' }, db: { updatedAt: true } }),
+ deletedAt: timestamp({}),
+ taskRuns: relationship({ ref: 'TaskRun.project', many: true }),
+ }
+ }),
+ TaskRun: list({
+ access: allowAll,
+
+ fields: {
+ number: integer({ defaultValue: 0 }),
+ friendlyId: text({}),
+ status: select({
+ options: [
+ { label: 'Pending', value: 'pending' },
+ { label: 'Executing', value: 'executing' },
+ { label: 'Paused', value: 'paused' },
+ { label: 'Canceled', value: 'canceled' },
+ { label: 'Interrupted', value: 'interrupted' },
+ { label: 'Completed Successfully', value: 'completed_successfully' },
+ { label: 'Completed With Errors', value: 'completed_with_errors' },
+ { label: 'System Failure', value: 'system_failure' },
+ { label: 'Crashed', value: 'crashed' }],
+ defaultValue: 'pending'
+ }),
+ taskIdentifier: text({}),
+ isTest: checkbox({ defaultValue: false }),
+ payload: text({}),
+ payloadType: text({ defaultValue: 'application/json' }),
+ context: json({}),
+ traceId: text({}),
+ spanId: text({}),
+ project: relationship({ ref: 'Project.taskRuns' }),
+ createdAt: timestamp({ defaultValue: { kind: 'now' } }),
+ updatedAt: timestamp({ defaultValue: { kind: 'now' }, db: { updatedAt: true } }),
+ attempts: relationship({ ref: 'TaskRunAttempt.taskRun', many: true }),
+ startedAt: timestamp({}),
+ completedAt: timestamp({}),
+ }
+ }),
+ TaskRunAttempt: list({
+ access: allowAll,
+
+ fields: {
+ number: integer({ defaultValue: 0 }),
+ friendlyId: text({}),
+ taskRun: relationship({ ref: 'TaskRun.attempts' }),
+ status: select({
+ options: [
+ { label: 'Pending', value: 'pending' },
+ { label: 'Executing', value: 'executing' },
+ { label: 'Paused', value: 'paused' },
+ { label: 'Failed', value: 'failed' },
+ { label: 'Canceled', value: 'canceled' },
+ { label: 'Completed', value: 'completed' }],
+ defaultValue: 'pending'
+ }),
+ createdAt: timestamp({ defaultValue: { kind: 'now' } }),
+ updatedAt: timestamp({ defaultValue: { kind: 'now' }, db: { updatedAt: true } }),
+ startedAt: timestamp({}),
+ completedAt: timestamp({}),
+ error: json({}),
+ output: text({}),
+ outputType: text({ defaultValue: 'application/json' }),
+ }
+ })
} satisfies Lists
diff --git a/examples/auth/tsconfig.json b/examples/auth/tsconfig.json
new file mode 100644
index 00000000000..ccb2ed95d83
--- /dev/null
+++ b/examples/auth/tsconfig.json
@@ -0,0 +1,34 @@
+{
+ "compilerOptions": {
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": false,
+ "noEmit": true,
+ "incremental": true,
+ "module": "esnext",
+ "esModuleInterop": true,
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ]
+ },
+ "include": [
+ "next-env.d.ts",
+ ".next/types/**/*.ts",
+ "**/*.ts",
+ "**/*.tsx"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}
diff --git a/examples/custom-admin-ui-logo/app/(admin)/.admin/index.tsx b/examples/custom-admin-ui-logo/app/(admin)/.admin/index.tsx
new file mode 100644
index 00000000000..5dd11446daf
--- /dev/null
+++ b/examples/custom-admin-ui-logo/app/(admin)/.admin/index.tsx
@@ -0,0 +1,18 @@
+/* eslint-disable */
+import * as view0 from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/id-field-view'
+import * as view1 from '@keystone-6/core/fields/types/text/views'
+import * as view2 from '@keystone-6/core/fields/types/select/views'
+import * as view3 from '@keystone-6/core/fields/types/checkbox/views'
+import * as view4 from '@keystone-6/core/fields/types/relationship/views'
+import * as view5 from '@keystone-6/core/fields/types/timestamp/views'
+
+import * as adminConfig from '../config'
+
+export const config = {
+ lazyMetadataQuery: {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"keystone","loc":{"start":22,"end":30}},"arguments":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"adminMeta","loc":{"start":39,"end":48}},"arguments":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"lists","loc":{"start":59,"end":64}},"arguments":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"key","loc":{"start":77,"end":80}},"arguments":[],"directives":[],"loc":{"start":77,"end":80}},{"kind":"Field","name":{"kind":"Name","value":"isHidden","loc":{"start":91,"end":99}},"arguments":[],"directives":[],"loc":{"start":91,"end":99}},{"kind":"Field","name":{"kind":"Name","value":"fields","loc":{"start":110,"end":116}},"arguments":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"path","loc":{"start":131,"end":135}},"arguments":[],"directives":[],"loc":{"start":131,"end":135}},{"kind":"Field","name":{"kind":"Name","value":"createView","loc":{"start":148,"end":158}},"arguments":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"fieldMode","loc":{"start":175,"end":184}},"arguments":[],"directives":[],"loc":{"start":175,"end":184}}],"loc":{"start":159,"end":198}},"loc":{"start":148,"end":198}}],"loc":{"start":117,"end":210}},"loc":{"start":110,"end":210}}],"loc":{"start":65,"end":220}},"loc":{"start":59,"end":220}}],"loc":{"start":49,"end":228}},"loc":{"start":39,"end":228}}],"loc":{"start":31,"end":234}},"loc":{"start":22,"end":234}}]}}]},
+ fieldViews: [view0,view1,view2,view3,view4,view5],
+ adminMetaHash: '1mrsjib',
+ adminConfig,
+ apiPath: '/api/graphql',
+ adminPath: '',
+};
diff --git a/examples/custom-admin-ui-logo/app/(admin)/[listKey]/[id]/page.tsx b/examples/custom-admin-ui-logo/app/(admin)/[listKey]/[id]/page.tsx
new file mode 100644
index 00000000000..c5d7ea2be62
--- /dev/null
+++ b/examples/custom-admin-ui-logo/app/(admin)/[listKey]/[id]/page.tsx
@@ -0,0 +1,4 @@
+'use client'
+import { ItemPage } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ItemPage'
+
+export default ItemPage
diff --git a/examples/custom-admin-ui-logo/app/(admin)/[listKey]/create/page.tsx b/examples/custom-admin-ui-logo/app/(admin)/[listKey]/create/page.tsx
new file mode 100644
index 00000000000..d6042acaa96
--- /dev/null
+++ b/examples/custom-admin-ui-logo/app/(admin)/[listKey]/create/page.tsx
@@ -0,0 +1,4 @@
+'use client'
+import { CreateItemPage } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/CreateItemPage'
+
+export default CreateItemPage
diff --git a/examples/custom-admin-ui-logo/app/(admin)/[listKey]/page.tsx b/examples/custom-admin-ui-logo/app/(admin)/[listKey]/page.tsx
new file mode 100644
index 00000000000..f6e75f8cfab
--- /dev/null
+++ b/examples/custom-admin-ui-logo/app/(admin)/[listKey]/page.tsx
@@ -0,0 +1,4 @@
+'use client'
+import { ListPage } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ListPage'
+
+export default ListPage
diff --git a/examples/custom-admin-ui-logo/app/(admin)/config.tsx b/examples/custom-admin-ui-logo/app/(admin)/config.tsx
new file mode 100644
index 00000000000..f2b986e29ca
--- /dev/null
+++ b/examples/custom-admin-ui-logo/app/(admin)/config.tsx
@@ -0,0 +1 @@
+export { components } from '../config'
\ No newline at end of file
diff --git a/examples/custom-admin-ui-logo/app/(admin)/layout.tsx b/examples/custom-admin-ui-logo/app/(admin)/layout.tsx
new file mode 100644
index 00000000000..abb5a0f3b2c
--- /dev/null
+++ b/examples/custom-admin-ui-logo/app/(admin)/layout.tsx
@@ -0,0 +1,16 @@
+'use client'
+import { Layout } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/App'
+import { config } from './.admin'
+
+
+export default function AdminLayout ({
+ children,
+}: {
+ children: React.ReactNode
+}) {
+ return (
+
+ {children}
+
+ )
+}
\ No newline at end of file
diff --git a/examples/custom-admin-ui-logo/app/(admin)/no-access/page.tsx b/examples/custom-admin-ui-logo/app/(admin)/no-access/page.tsx
new file mode 100644
index 00000000000..70877231fee
--- /dev/null
+++ b/examples/custom-admin-ui-logo/app/(admin)/no-access/page.tsx
@@ -0,0 +1,4 @@
+'use client'
+import { getNoAccessPage } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/NoAccessPage'
+
+export default getNoAccessPage({ sessionsEnabled: false })
diff --git a/examples/custom-admin-ui-logo/app/(admin)/page.tsx b/examples/custom-admin-ui-logo/app/(admin)/page.tsx
new file mode 100644
index 00000000000..5c268390b0f
--- /dev/null
+++ b/examples/custom-admin-ui-logo/app/(admin)/page.tsx
@@ -0,0 +1,2 @@
+'use client'
+export { HomePage as default } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/HomePage'
diff --git a/examples/custom-admin-ui-logo/admin/components/CustomLogo.tsx b/examples/custom-admin-ui-logo/app/config/components/CustomLogo.tsx
similarity index 100%
rename from examples/custom-admin-ui-logo/admin/components/CustomLogo.tsx
rename to examples/custom-admin-ui-logo/app/config/components/CustomLogo.tsx
diff --git a/examples/custom-admin-ui-logo/admin/config.tsx b/examples/custom-admin-ui-logo/app/config/index.tsx
similarity index 100%
rename from examples/custom-admin-ui-logo/admin/config.tsx
rename to examples/custom-admin-ui-logo/app/config/index.tsx
diff --git a/examples/custom-admin-ui-logo/app/layout.tsx b/examples/custom-admin-ui-logo/app/layout.tsx
new file mode 100644
index 00000000000..38a4853e3a5
--- /dev/null
+++ b/examples/custom-admin-ui-logo/app/layout.tsx
@@ -0,0 +1,11 @@
+export default function RootLayout ({
+ children,
+}: {
+ children: React.ReactNode
+}) {
+ return (
+
+ {children}
+
+ )
+}
diff --git a/examples/custom-admin-ui-logo/next-env.d.ts b/examples/custom-admin-ui-logo/next-env.d.ts
new file mode 100644
index 00000000000..4f11a03dc6c
--- /dev/null
+++ b/examples/custom-admin-ui-logo/next-env.d.ts
@@ -0,0 +1,5 @@
+///
+///
+
+// NOTE: This file should not be edited
+// see https://nextjs.org/docs/basic-features/typescript for more information.
diff --git a/examples/custom-admin-ui-logo/package.json b/examples/custom-admin-ui-logo/package.json
index 17b0087d1d7..0f90e7c4d9e 100644
--- a/examples/custom-admin-ui-logo/package.json
+++ b/examples/custom-admin-ui-logo/package.json
@@ -13,7 +13,7 @@
"@keystone-6/core": "^6.3.1",
"@keystone-ui/core": "^5.0.2",
"@prisma/client": "5.19.0",
- "next": "^14.2.0",
+ "next": "^15.0.0",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
diff --git a/examples/custom-admin-ui-logo/tsconfig.json b/examples/custom-admin-ui-logo/tsconfig.json
new file mode 100644
index 00000000000..ccb2ed95d83
--- /dev/null
+++ b/examples/custom-admin-ui-logo/tsconfig.json
@@ -0,0 +1,34 @@
+{
+ "compilerOptions": {
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": false,
+ "noEmit": true,
+ "incremental": true,
+ "module": "esnext",
+ "esModuleInterop": true,
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ]
+ },
+ "include": [
+ "next-env.d.ts",
+ ".next/types/**/*.ts",
+ "**/*.ts",
+ "**/*.tsx"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}
diff --git a/examples/custom-admin-ui-navigation/app/(admin)/.admin/index.tsx b/examples/custom-admin-ui-navigation/app/(admin)/.admin/index.tsx
new file mode 100644
index 00000000000..283542749b0
--- /dev/null
+++ b/examples/custom-admin-ui-navigation/app/(admin)/.admin/index.tsx
@@ -0,0 +1,18 @@
+/* eslint-disable */
+import * as view0 from "@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/id-field-view"
+import * as view1 from "@keystone-6/core/fields/types/text/views"
+import * as view2 from "@keystone-6/core/fields/types/select/views"
+import * as view3 from "@keystone-6/core/fields/types/checkbox/views"
+import * as view4 from "@keystone-6/core/fields/types/relationship/views"
+import * as view5 from "@keystone-6/core/fields/types/timestamp/views"
+
+import * as adminConfig from '../config'
+
+export const config = {
+ lazyMetadataQuery: {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"keystone","loc":{"start":22,"end":30}},"arguments":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"adminMeta","loc":{"start":39,"end":48}},"arguments":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"lists","loc":{"start":59,"end":64}},"arguments":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"key","loc":{"start":77,"end":80}},"arguments":[],"directives":[],"loc":{"start":77,"end":80}},{"kind":"Field","name":{"kind":"Name","value":"isHidden","loc":{"start":91,"end":99}},"arguments":[],"directives":[],"loc":{"start":91,"end":99}},{"kind":"Field","name":{"kind":"Name","value":"fields","loc":{"start":110,"end":116}},"arguments":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"path","loc":{"start":131,"end":135}},"arguments":[],"directives":[],"loc":{"start":131,"end":135}},{"kind":"Field","name":{"kind":"Name","value":"createView","loc":{"start":148,"end":158}},"arguments":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"fieldMode","loc":{"start":175,"end":184}},"arguments":[],"directives":[],"loc":{"start":175,"end":184}}],"loc":{"start":159,"end":198}},"loc":{"start":148,"end":198}}],"loc":{"start":117,"end":210}},"loc":{"start":110,"end":210}}],"loc":{"start":65,"end":220}},"loc":{"start":59,"end":220}}],"loc":{"start":49,"end":228}},"loc":{"start":39,"end":228}}],"loc":{"start":31,"end":234}},"loc":{"start":22,"end":234}}]}}]},
+ fieldViews: [view0,view1,view2,view3,view4,view5],
+ adminMetaHash: '1mrsjib',
+ adminConfig,
+ apiPath: '/api/graphql',
+ adminPath: '',
+};
diff --git a/examples/custom-admin-ui-navigation/app/(admin)/[listKey]/[id]/page.tsx b/examples/custom-admin-ui-navigation/app/(admin)/[listKey]/[id]/page.tsx
new file mode 100644
index 00000000000..c5d7ea2be62
--- /dev/null
+++ b/examples/custom-admin-ui-navigation/app/(admin)/[listKey]/[id]/page.tsx
@@ -0,0 +1,4 @@
+'use client'
+import { ItemPage } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ItemPage'
+
+export default ItemPage
diff --git a/examples/custom-admin-ui-navigation/app/(admin)/[listKey]/create/page.tsx b/examples/custom-admin-ui-navigation/app/(admin)/[listKey]/create/page.tsx
new file mode 100644
index 00000000000..d6042acaa96
--- /dev/null
+++ b/examples/custom-admin-ui-navigation/app/(admin)/[listKey]/create/page.tsx
@@ -0,0 +1,4 @@
+'use client'
+import { CreateItemPage } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/CreateItemPage'
+
+export default CreateItemPage
diff --git a/examples/custom-admin-ui-navigation/app/(admin)/[listKey]/page.tsx b/examples/custom-admin-ui-navigation/app/(admin)/[listKey]/page.tsx
new file mode 100644
index 00000000000..f6e75f8cfab
--- /dev/null
+++ b/examples/custom-admin-ui-navigation/app/(admin)/[listKey]/page.tsx
@@ -0,0 +1,4 @@
+'use client'
+import { ListPage } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ListPage'
+
+export default ListPage
diff --git a/examples/custom-admin-ui-navigation/app/(admin)/config.tsx b/examples/custom-admin-ui-navigation/app/(admin)/config.tsx
new file mode 100644
index 00000000000..f2b986e29ca
--- /dev/null
+++ b/examples/custom-admin-ui-navigation/app/(admin)/config.tsx
@@ -0,0 +1 @@
+export { components } from '../config'
\ No newline at end of file
diff --git a/examples/custom-admin-ui-navigation/app/(admin)/layout.tsx b/examples/custom-admin-ui-navigation/app/(admin)/layout.tsx
new file mode 100644
index 00000000000..abb5a0f3b2c
--- /dev/null
+++ b/examples/custom-admin-ui-navigation/app/(admin)/layout.tsx
@@ -0,0 +1,16 @@
+'use client'
+import { Layout } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/App'
+import { config } from './.admin'
+
+
+export default function AdminLayout ({
+ children,
+}: {
+ children: React.ReactNode
+}) {
+ return (
+
+ {children}
+
+ )
+}
\ No newline at end of file
diff --git a/examples/custom-admin-ui-navigation/app/(admin)/no-access/page.tsx b/examples/custom-admin-ui-navigation/app/(admin)/no-access/page.tsx
new file mode 100644
index 00000000000..70877231fee
--- /dev/null
+++ b/examples/custom-admin-ui-navigation/app/(admin)/no-access/page.tsx
@@ -0,0 +1,4 @@
+'use client'
+import { getNoAccessPage } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/NoAccessPage'
+
+export default getNoAccessPage({ sessionsEnabled: false })
diff --git a/examples/custom-admin-ui-navigation/app/(admin)/page.tsx b/examples/custom-admin-ui-navigation/app/(admin)/page.tsx
new file mode 100644
index 00000000000..5c268390b0f
--- /dev/null
+++ b/examples/custom-admin-ui-navigation/app/(admin)/page.tsx
@@ -0,0 +1,2 @@
+'use client'
+export { HomePage as default } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/HomePage'
diff --git a/examples/custom-admin-ui-navigation/admin/components/CustomNavigation.tsx b/examples/custom-admin-ui-navigation/app/config/components/CustomNavigation.tsx
similarity index 100%
rename from examples/custom-admin-ui-navigation/admin/components/CustomNavigation.tsx
rename to examples/custom-admin-ui-navigation/app/config/components/CustomNavigation.tsx
diff --git a/examples/custom-admin-ui-navigation/admin/config.ts b/examples/custom-admin-ui-navigation/app/config/index.ts
similarity index 100%
rename from examples/custom-admin-ui-navigation/admin/config.ts
rename to examples/custom-admin-ui-navigation/app/config/index.ts
diff --git a/examples/custom-admin-ui-navigation/app/layout.tsx b/examples/custom-admin-ui-navigation/app/layout.tsx
new file mode 100644
index 00000000000..38a4853e3a5
--- /dev/null
+++ b/examples/custom-admin-ui-navigation/app/layout.tsx
@@ -0,0 +1,11 @@
+export default function RootLayout ({
+ children,
+}: {
+ children: React.ReactNode
+}) {
+ return (
+
+ {children}
+
+ )
+}
diff --git a/examples/custom-admin-ui-navigation/next-env.d.ts b/examples/custom-admin-ui-navigation/next-env.d.ts
new file mode 100644
index 00000000000..4f11a03dc6c
--- /dev/null
+++ b/examples/custom-admin-ui-navigation/next-env.d.ts
@@ -0,0 +1,5 @@
+///
+///
+
+// NOTE: This file should not be edited
+// see https://nextjs.org/docs/basic-features/typescript for more information.
diff --git a/examples/custom-admin-ui-navigation/tsconfig.json b/examples/custom-admin-ui-navigation/tsconfig.json
new file mode 100644
index 00000000000..ccb2ed95d83
--- /dev/null
+++ b/examples/custom-admin-ui-navigation/tsconfig.json
@@ -0,0 +1,34 @@
+{
+ "compilerOptions": {
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": false,
+ "noEmit": true,
+ "incremental": true,
+ "module": "esnext",
+ "esModuleInterop": true,
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ]
+ },
+ "include": [
+ "next-env.d.ts",
+ ".next/types/**/*.ts",
+ "**/*.ts",
+ "**/*.tsx"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}
diff --git a/examples/custom-admin-ui-pages/app/(admin)/.admin/index.tsx b/examples/custom-admin-ui-pages/app/(admin)/.admin/index.tsx
new file mode 100644
index 00000000000..5dd11446daf
--- /dev/null
+++ b/examples/custom-admin-ui-pages/app/(admin)/.admin/index.tsx
@@ -0,0 +1,18 @@
+/* eslint-disable */
+import * as view0 from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/id-field-view'
+import * as view1 from '@keystone-6/core/fields/types/text/views'
+import * as view2 from '@keystone-6/core/fields/types/select/views'
+import * as view3 from '@keystone-6/core/fields/types/checkbox/views'
+import * as view4 from '@keystone-6/core/fields/types/relationship/views'
+import * as view5 from '@keystone-6/core/fields/types/timestamp/views'
+
+import * as adminConfig from '../config'
+
+export const config = {
+ lazyMetadataQuery: {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"keystone","loc":{"start":22,"end":30}},"arguments":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"adminMeta","loc":{"start":39,"end":48}},"arguments":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"lists","loc":{"start":59,"end":64}},"arguments":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"key","loc":{"start":77,"end":80}},"arguments":[],"directives":[],"loc":{"start":77,"end":80}},{"kind":"Field","name":{"kind":"Name","value":"isHidden","loc":{"start":91,"end":99}},"arguments":[],"directives":[],"loc":{"start":91,"end":99}},{"kind":"Field","name":{"kind":"Name","value":"fields","loc":{"start":110,"end":116}},"arguments":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"path","loc":{"start":131,"end":135}},"arguments":[],"directives":[],"loc":{"start":131,"end":135}},{"kind":"Field","name":{"kind":"Name","value":"createView","loc":{"start":148,"end":158}},"arguments":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"fieldMode","loc":{"start":175,"end":184}},"arguments":[],"directives":[],"loc":{"start":175,"end":184}}],"loc":{"start":159,"end":198}},"loc":{"start":148,"end":198}}],"loc":{"start":117,"end":210}},"loc":{"start":110,"end":210}}],"loc":{"start":65,"end":220}},"loc":{"start":59,"end":220}}],"loc":{"start":49,"end":228}},"loc":{"start":39,"end":228}}],"loc":{"start":31,"end":234}},"loc":{"start":22,"end":234}}]}}]},
+ fieldViews: [view0,view1,view2,view3,view4,view5],
+ adminMetaHash: '1mrsjib',
+ adminConfig,
+ apiPath: '/api/graphql',
+ adminPath: '',
+};
diff --git a/examples/custom-admin-ui-pages/app/(admin)/[listKey]/[id]/page.tsx b/examples/custom-admin-ui-pages/app/(admin)/[listKey]/[id]/page.tsx
new file mode 100644
index 00000000000..c5d7ea2be62
--- /dev/null
+++ b/examples/custom-admin-ui-pages/app/(admin)/[listKey]/[id]/page.tsx
@@ -0,0 +1,4 @@
+'use client'
+import { ItemPage } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ItemPage'
+
+export default ItemPage
diff --git a/examples/custom-admin-ui-pages/app/(admin)/[listKey]/create/page.tsx b/examples/custom-admin-ui-pages/app/(admin)/[listKey]/create/page.tsx
new file mode 100644
index 00000000000..d6042acaa96
--- /dev/null
+++ b/examples/custom-admin-ui-pages/app/(admin)/[listKey]/create/page.tsx
@@ -0,0 +1,4 @@
+'use client'
+import { CreateItemPage } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/CreateItemPage'
+
+export default CreateItemPage
diff --git a/examples/custom-admin-ui-pages/app/(admin)/[listKey]/page.tsx b/examples/custom-admin-ui-pages/app/(admin)/[listKey]/page.tsx
new file mode 100644
index 00000000000..f6e75f8cfab
--- /dev/null
+++ b/examples/custom-admin-ui-pages/app/(admin)/[listKey]/page.tsx
@@ -0,0 +1,4 @@
+'use client'
+import { ListPage } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ListPage'
+
+export default ListPage
diff --git a/examples/custom-admin-ui-pages/app/(admin)/config.tsx b/examples/custom-admin-ui-pages/app/(admin)/config.tsx
new file mode 100644
index 00000000000..f2b986e29ca
--- /dev/null
+++ b/examples/custom-admin-ui-pages/app/(admin)/config.tsx
@@ -0,0 +1 @@
+export { components } from '../config'
\ No newline at end of file
diff --git a/examples/custom-admin-ui-pages/admin/pages/custom-page.tsx b/examples/custom-admin-ui-pages/app/(admin)/custom-page/page.tsx
similarity index 87%
rename from examples/custom-admin-ui-pages/admin/pages/custom-page.tsx
rename to examples/custom-admin-ui-pages/app/(admin)/custom-page/page.tsx
index ccf76ad67aa..346ab365520 100644
--- a/examples/custom-admin-ui-pages/admin/pages/custom-page.tsx
+++ b/examples/custom-admin-ui-pages/app/(admin)/custom-page/page.tsx
@@ -1,8 +1,7 @@
-/** @jsxRuntime classic */
-/** @jsx jsx */
+'use client'
import Link from 'next/link'
import { PageContainer } from '@keystone-6/core/admin-ui/components'
-import { jsx, Heading } from '@keystone-ui/core'
+import { Heading } from '@keystone-ui/core'
// Please note that while this capability is driven by Next.js's pages directory
// We do not currently support any of the auxillary methods that Next.js provides i.e. `getStaticProps`
// Presently the only export from the directory that is supported is the page component itself.
@@ -10,7 +9,7 @@ export default function CustomPage () {
return (
Custom Page}>
diff --git a/examples/custom-admin-ui-pages/app/(admin)/layout.tsx b/examples/custom-admin-ui-pages/app/(admin)/layout.tsx
new file mode 100644
index 00000000000..abb5a0f3b2c
--- /dev/null
+++ b/examples/custom-admin-ui-pages/app/(admin)/layout.tsx
@@ -0,0 +1,16 @@
+'use client'
+import { Layout } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/App'
+import { config } from './.admin'
+
+
+export default function AdminLayout ({
+ children,
+}: {
+ children: React.ReactNode
+}) {
+ return (
+
+ {children}
+
+ )
+}
\ No newline at end of file
diff --git a/examples/custom-admin-ui-pages/app/(admin)/no-access/page.tsx b/examples/custom-admin-ui-pages/app/(admin)/no-access/page.tsx
new file mode 100644
index 00000000000..70877231fee
--- /dev/null
+++ b/examples/custom-admin-ui-pages/app/(admin)/no-access/page.tsx
@@ -0,0 +1,4 @@
+'use client'
+import { getNoAccessPage } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/NoAccessPage'
+
+export default getNoAccessPage({ sessionsEnabled: false })
diff --git a/examples/custom-admin-ui-pages/app/(admin)/page.tsx b/examples/custom-admin-ui-pages/app/(admin)/page.tsx
new file mode 100644
index 00000000000..5c268390b0f
--- /dev/null
+++ b/examples/custom-admin-ui-pages/app/(admin)/page.tsx
@@ -0,0 +1,2 @@
+'use client'
+export { HomePage as default } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/HomePage'
diff --git a/examples/custom-admin-ui-pages/admin/components/CustomNavigation.tsx b/examples/custom-admin-ui-pages/app/config/components/CustomNavigation.tsx
similarity index 100%
rename from examples/custom-admin-ui-pages/admin/components/CustomNavigation.tsx
rename to examples/custom-admin-ui-pages/app/config/components/CustomNavigation.tsx
diff --git a/examples/custom-admin-ui-pages/admin/config.ts b/examples/custom-admin-ui-pages/app/config/index.ts
similarity index 100%
rename from examples/custom-admin-ui-pages/admin/config.ts
rename to examples/custom-admin-ui-pages/app/config/index.ts
diff --git a/examples/custom-admin-ui-pages/app/layout.tsx b/examples/custom-admin-ui-pages/app/layout.tsx
new file mode 100644
index 00000000000..38a4853e3a5
--- /dev/null
+++ b/examples/custom-admin-ui-pages/app/layout.tsx
@@ -0,0 +1,11 @@
+export default function RootLayout ({
+ children,
+}: {
+ children: React.ReactNode
+}) {
+ return (
+
+
{children}
+
+ )
+}
diff --git a/examples/custom-admin-ui-pages/next-env.d.ts b/examples/custom-admin-ui-pages/next-env.d.ts
new file mode 100644
index 00000000000..4f11a03dc6c
--- /dev/null
+++ b/examples/custom-admin-ui-pages/next-env.d.ts
@@ -0,0 +1,5 @@
+///
+///
+
+// NOTE: This file should not be edited
+// see https://nextjs.org/docs/basic-features/typescript for more information.
diff --git a/examples/custom-admin-ui-pages/package.json b/examples/custom-admin-ui-pages/package.json
index 47998487fcc..dfa15d84adb 100644
--- a/examples/custom-admin-ui-pages/package.json
+++ b/examples/custom-admin-ui-pages/package.json
@@ -13,7 +13,7 @@
"@keystone-6/core": "^6.3.1",
"@keystone-ui/core": "^5.0.2",
"@prisma/client": "5.19.0",
- "next": "^14.2.0",
+ "next": "^15.0.0",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
diff --git a/examples/custom-admin-ui-pages/tsconfig.json b/examples/custom-admin-ui-pages/tsconfig.json
new file mode 100644
index 00000000000..ccb2ed95d83
--- /dev/null
+++ b/examples/custom-admin-ui-pages/tsconfig.json
@@ -0,0 +1,34 @@
+{
+ "compilerOptions": {
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": false,
+ "noEmit": true,
+ "incremental": true,
+ "module": "esnext",
+ "esModuleInterop": true,
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ]
+ },
+ "include": [
+ "next-env.d.ts",
+ ".next/types/**/*.ts",
+ "**/*.ts",
+ "**/*.tsx"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}
diff --git a/examples/custom-field-view/app/(admin)/.admin/index.tsx b/examples/custom-field-view/app/(admin)/.admin/index.tsx
new file mode 100644
index 00000000000..7c8948ac698
--- /dev/null
+++ b/examples/custom-field-view/app/(admin)/.admin/index.tsx
@@ -0,0 +1,21 @@
+/* eslint-disable */
+import * as view0 from "@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/id-field-view"
+import * as view1 from "@keystone-6/core/fields/types/text/views"
+import * as view2 from "@keystone-6/core/fields/types/select/views"
+import * as view3 from "@keystone-6/core/fields/types/checkbox/views"
+import * as view4 from "@keystone-6/core/fields/types/relationship/views"
+import * as view5 from "@keystone-6/core/fields/types/timestamp/views"
+import * as view6 from "@keystone-6/core/fields/types/json/views"
+import * as view7 from "../../.././fields/related-links/components"
+import * as view8 from "@/fields/related-links/components"
+
+const adminConfig = {}
+
+export const config = {
+ lazyMetadataQuery: {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"keystone","loc":{"start":22,"end":30}},"arguments":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"adminMeta","loc":{"start":39,"end":48}},"arguments":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"lists","loc":{"start":59,"end":64}},"arguments":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"key","loc":{"start":77,"end":80}},"arguments":[],"directives":[],"loc":{"start":77,"end":80}},{"kind":"Field","name":{"kind":"Name","value":"isHidden","loc":{"start":91,"end":99}},"arguments":[],"directives":[],"loc":{"start":91,"end":99}},{"kind":"Field","name":{"kind":"Name","value":"fields","loc":{"start":110,"end":116}},"arguments":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"path","loc":{"start":131,"end":135}},"arguments":[],"directives":[],"loc":{"start":131,"end":135}},{"kind":"Field","name":{"kind":"Name","value":"createView","loc":{"start":148,"end":158}},"arguments":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"fieldMode","loc":{"start":175,"end":184}},"arguments":[],"directives":[],"loc":{"start":175,"end":184}}],"loc":{"start":159,"end":198}},"loc":{"start":148,"end":198}}],"loc":{"start":117,"end":210}},"loc":{"start":110,"end":210}}],"loc":{"start":65,"end":220}},"loc":{"start":59,"end":220}}],"loc":{"start":49,"end":228}},"loc":{"start":39,"end":228}}],"loc":{"start":31,"end":234}},"loc":{"start":22,"end":234}}]}}]},
+ fieldViews: [view0,view1,view2,view3,view4,view5,view6,view7,view8],
+ adminMetaHash: 'o10uod',
+ adminConfig,
+ apiPath: '/api/graphql',
+ adminPath: '',
+};
diff --git a/examples/custom-field-view/app/(admin)/[listKey]/[id]/page.tsx b/examples/custom-field-view/app/(admin)/[listKey]/[id]/page.tsx
new file mode 100644
index 00000000000..c5d7ea2be62
--- /dev/null
+++ b/examples/custom-field-view/app/(admin)/[listKey]/[id]/page.tsx
@@ -0,0 +1,4 @@
+'use client'
+import { ItemPage } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ItemPage'
+
+export default ItemPage
diff --git a/examples/custom-field-view/app/(admin)/[listKey]/create/page.tsx b/examples/custom-field-view/app/(admin)/[listKey]/create/page.tsx
new file mode 100644
index 00000000000..d6042acaa96
--- /dev/null
+++ b/examples/custom-field-view/app/(admin)/[listKey]/create/page.tsx
@@ -0,0 +1,4 @@
+'use client'
+import { CreateItemPage } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/CreateItemPage'
+
+export default CreateItemPage
diff --git a/examples/custom-field-view/app/(admin)/[listKey]/page.tsx b/examples/custom-field-view/app/(admin)/[listKey]/page.tsx
new file mode 100644
index 00000000000..f6e75f8cfab
--- /dev/null
+++ b/examples/custom-field-view/app/(admin)/[listKey]/page.tsx
@@ -0,0 +1,4 @@
+'use client'
+import { ListPage } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ListPage'
+
+export default ListPage
diff --git a/examples/custom-field-view/app/(admin)/layout.tsx b/examples/custom-field-view/app/(admin)/layout.tsx
new file mode 100644
index 00000000000..abb5a0f3b2c
--- /dev/null
+++ b/examples/custom-field-view/app/(admin)/layout.tsx
@@ -0,0 +1,16 @@
+'use client'
+import { Layout } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/App'
+import { config } from './.admin'
+
+
+export default function AdminLayout ({
+ children,
+}: {
+ children: React.ReactNode
+}) {
+ return (
+
+ {children}
+
+ )
+}
\ No newline at end of file
diff --git a/examples/custom-field-view/app/(admin)/no-access/page.tsx b/examples/custom-field-view/app/(admin)/no-access/page.tsx
new file mode 100644
index 00000000000..70877231fee
--- /dev/null
+++ b/examples/custom-field-view/app/(admin)/no-access/page.tsx
@@ -0,0 +1,4 @@
+'use client'
+import { getNoAccessPage } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/NoAccessPage'
+
+export default getNoAccessPage({ sessionsEnabled: false })
diff --git a/examples/custom-field-view/app/(admin)/page.tsx b/examples/custom-field-view/app/(admin)/page.tsx
new file mode 100644
index 00000000000..5c268390b0f
--- /dev/null
+++ b/examples/custom-field-view/app/(admin)/page.tsx
@@ -0,0 +1,2 @@
+'use client'
+export { HomePage as default } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/HomePage'
diff --git a/examples/custom-field-view/app/layout.tsx b/examples/custom-field-view/app/layout.tsx
new file mode 100644
index 00000000000..38a4853e3a5
--- /dev/null
+++ b/examples/custom-field-view/app/layout.tsx
@@ -0,0 +1,11 @@
+export default function RootLayout ({
+ children,
+}: {
+ children: React.ReactNode
+}) {
+ return (
+
+ {children}
+
+ )
+}
diff --git a/examples/custom-field-view/next-env.d.ts b/examples/custom-field-view/next-env.d.ts
new file mode 100644
index 00000000000..4f11a03dc6c
--- /dev/null
+++ b/examples/custom-field-view/next-env.d.ts
@@ -0,0 +1,5 @@
+///
+///
+
+// NOTE: This file should not be edited
+// see https://nextjs.org/docs/basic-features/typescript for more information.
diff --git a/examples/custom-field-view/package.json b/examples/custom-field-view/package.json
index 63ee8fc43b3..a808cb96dbc 100644
--- a/examples/custom-field-view/package.json
+++ b/examples/custom-field-view/package.json
@@ -17,7 +17,7 @@
"@keystone-ui/fields": "^7.2.0",
"@keystone-ui/icons": "^6.0.2",
"@prisma/client": "5.19.0",
- "next": "^14.2.0",
+ "next": "^15.0.0",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
diff --git a/examples/custom-field-view/schema.graphql b/examples/custom-field-view/schema.graphql
index e9a8913365e..a45d100f971 100644
--- a/examples/custom-field-view/schema.graphql
+++ b/examples/custom-field-view/schema.graphql
@@ -9,6 +9,7 @@ type Task {
assignedTo: Person
finishBy: DateTime
relatedLinks: JSON
+ moreLinks: JSON
}
enum TaskPriorityType {
@@ -117,6 +118,7 @@ input TaskUpdateInput {
assignedTo: PersonRelateToOneForUpdateInput
finishBy: DateTime
relatedLinks: JSON
+ moreLinks: JSON
}
input PersonRelateToOneForUpdateInput {
@@ -137,6 +139,7 @@ input TaskCreateInput {
assignedTo: PersonRelateToOneForCreateInput
finishBy: DateTime
relatedLinks: JSON
+ moreLinks: JSON
}
input PersonRelateToOneForCreateInput {
diff --git a/examples/custom-field-view/schema.prisma b/examples/custom-field-view/schema.prisma
index c4b4e68cbe0..dfea6e26130 100644
--- a/examples/custom-field-view/schema.prisma
+++ b/examples/custom-field-view/schema.prisma
@@ -21,6 +21,7 @@ model Task {
assignedToId String? @map("assignedTo")
finishBy DateTime?
relatedLinks String?
+ moreLinks String?
@@index([assignedToId])
}
diff --git a/examples/custom-field-view/schema.ts b/examples/custom-field-view/schema.ts
index 8a6516cd78d..ed877eee26f 100644
--- a/examples/custom-field-view/schema.ts
+++ b/examples/custom-field-view/schema.ts
@@ -30,6 +30,14 @@ export const lists = {
itemView: { fieldMode: 'edit' },
},
}),
+ moreLinks: json({
+ ui: {
+ views: '@/fields/related-links/components',
+ createView: { fieldMode: 'edit' },
+ listView: { fieldMode: 'hidden' },
+ itemView: { fieldMode: 'edit' },
+ },
+ }),
},
}),
Person: list({
diff --git a/examples/custom-field-view/tsconfig.json b/examples/custom-field-view/tsconfig.json
new file mode 100644
index 00000000000..3b0afd8f406
--- /dev/null
+++ b/examples/custom-field-view/tsconfig.json
@@ -0,0 +1,37 @@
+{
+ "compilerOptions": {
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": false,
+ "noEmit": true,
+ "incremental": true,
+ "module": "esnext",
+ "esModuleInterop": true,
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "paths": {
+ "@/fields/*": ["./fields/*"]
+ },
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ]
+ },
+ "include": [
+ "next-env.d.ts",
+ ".next/types/**/*.ts",
+ "**/*.ts",
+ "**/*.tsx"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}
diff --git a/examples/custom-field/app/(admin)/.admin/index.tsx b/examples/custom-field/app/(admin)/.admin/index.tsx
new file mode 100644
index 00000000000..ca1a2d962a6
--- /dev/null
+++ b/examples/custom-field/app/(admin)/.admin/index.tsx
@@ -0,0 +1,19 @@
+/* eslint-disable */
+import * as view0 from "@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/id-field-view"
+import * as view1 from "../../.././1-text-field/views"
+import * as view2 from "../../.././2-stars-field/views"
+import * as view3 from "../../.././4-conditional-field/views"
+import * as view4 from "../../.././3-pair-field/views"
+import * as view5 from "../../.././3-pair-field-nested/views"
+import * as view6 from "../../.././3-pair-field-json/views"
+
+const adminConfig = {}
+
+export const config = {
+ lazyMetadataQuery: {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"keystone","loc":{"start":22,"end":30}},"arguments":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"adminMeta","loc":{"start":39,"end":48}},"arguments":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"lists","loc":{"start":59,"end":64}},"arguments":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"key","loc":{"start":77,"end":80}},"arguments":[],"directives":[],"loc":{"start":77,"end":80}},{"kind":"Field","name":{"kind":"Name","value":"isHidden","loc":{"start":91,"end":99}},"arguments":[],"directives":[],"loc":{"start":91,"end":99}},{"kind":"Field","name":{"kind":"Name","value":"fields","loc":{"start":110,"end":116}},"arguments":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"path","loc":{"start":131,"end":135}},"arguments":[],"directives":[],"loc":{"start":131,"end":135}},{"kind":"Field","name":{"kind":"Name","value":"createView","loc":{"start":148,"end":158}},"arguments":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"fieldMode","loc":{"start":175,"end":184}},"arguments":[],"directives":[],"loc":{"start":175,"end":184}}],"loc":{"start":159,"end":198}},"loc":{"start":148,"end":198}}],"loc":{"start":117,"end":210}},"loc":{"start":110,"end":210}}],"loc":{"start":65,"end":220}},"loc":{"start":59,"end":220}}],"loc":{"start":49,"end":228}},"loc":{"start":39,"end":228}}],"loc":{"start":31,"end":234}},"loc":{"start":22,"end":234}}]}}]},
+ fieldViews: [view0,view1,view2,view3,view4,view5,view6],
+ adminMetaHash: 'fhppxz',
+ adminConfig,
+ apiPath: '/api/graphql',
+ adminPath: '',
+};
diff --git a/examples/custom-field/app/(admin)/[listKey]/[id]/page.tsx b/examples/custom-field/app/(admin)/[listKey]/[id]/page.tsx
new file mode 100644
index 00000000000..c5d7ea2be62
--- /dev/null
+++ b/examples/custom-field/app/(admin)/[listKey]/[id]/page.tsx
@@ -0,0 +1,4 @@
+'use client'
+import { ItemPage } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ItemPage'
+
+export default ItemPage
diff --git a/examples/custom-field/app/(admin)/[listKey]/create/page.tsx b/examples/custom-field/app/(admin)/[listKey]/create/page.tsx
new file mode 100644
index 00000000000..d6042acaa96
--- /dev/null
+++ b/examples/custom-field/app/(admin)/[listKey]/create/page.tsx
@@ -0,0 +1,4 @@
+'use client'
+import { CreateItemPage } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/CreateItemPage'
+
+export default CreateItemPage
diff --git a/examples/custom-field/app/(admin)/[listKey]/page.tsx b/examples/custom-field/app/(admin)/[listKey]/page.tsx
new file mode 100644
index 00000000000..f6e75f8cfab
--- /dev/null
+++ b/examples/custom-field/app/(admin)/[listKey]/page.tsx
@@ -0,0 +1,4 @@
+'use client'
+import { ListPage } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ListPage'
+
+export default ListPage
diff --git a/examples/custom-field/app/(admin)/layout.tsx b/examples/custom-field/app/(admin)/layout.tsx
new file mode 100644
index 00000000000..abb5a0f3b2c
--- /dev/null
+++ b/examples/custom-field/app/(admin)/layout.tsx
@@ -0,0 +1,16 @@
+'use client'
+import { Layout } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/App'
+import { config } from './.admin'
+
+
+export default function AdminLayout ({
+ children,
+}: {
+ children: React.ReactNode
+}) {
+ return (
+
+ {children}
+
+ )
+}
\ No newline at end of file
diff --git a/examples/custom-field/app/(admin)/no-access/page.tsx b/examples/custom-field/app/(admin)/no-access/page.tsx
new file mode 100644
index 00000000000..70877231fee
--- /dev/null
+++ b/examples/custom-field/app/(admin)/no-access/page.tsx
@@ -0,0 +1,4 @@
+'use client'
+import { getNoAccessPage } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/NoAccessPage'
+
+export default getNoAccessPage({ sessionsEnabled: false })
diff --git a/examples/custom-field/app/(admin)/page.tsx b/examples/custom-field/app/(admin)/page.tsx
new file mode 100644
index 00000000000..5c268390b0f
--- /dev/null
+++ b/examples/custom-field/app/(admin)/page.tsx
@@ -0,0 +1,2 @@
+'use client'
+export { HomePage as default } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/HomePage'
diff --git a/examples/custom-field/app/layout.tsx b/examples/custom-field/app/layout.tsx
new file mode 100644
index 00000000000..38a4853e3a5
--- /dev/null
+++ b/examples/custom-field/app/layout.tsx
@@ -0,0 +1,11 @@
+export default function RootLayout ({
+ children,
+}: {
+ children: React.ReactNode
+}) {
+ return (
+
+ {children}
+
+ )
+}
diff --git a/examples/custom-field/next-env.d.ts b/examples/custom-field/next-env.d.ts
new file mode 100644
index 00000000000..4f11a03dc6c
--- /dev/null
+++ b/examples/custom-field/next-env.d.ts
@@ -0,0 +1,5 @@
+///
+///
+
+// NOTE: This file should not be edited
+// see https://nextjs.org/docs/basic-features/typescript for more information.
diff --git a/examples/custom-field/tsconfig.json b/examples/custom-field/tsconfig.json
new file mode 100644
index 00000000000..3b0afd8f406
--- /dev/null
+++ b/examples/custom-field/tsconfig.json
@@ -0,0 +1,37 @@
+{
+ "compilerOptions": {
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": false,
+ "noEmit": true,
+ "incremental": true,
+ "module": "esnext",
+ "esModuleInterop": true,
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "paths": {
+ "@/fields/*": ["./fields/*"]
+ },
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ]
+ },
+ "include": [
+ "next-env.d.ts",
+ ".next/types/**/*.ts",
+ "**/*.ts",
+ "**/*.tsx"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}
diff --git a/examples/custom-output-paths/package.json b/examples/custom-output-paths/package.json
index b485ea7bd1d..622d4877211 100644
--- a/examples/custom-output-paths/package.json
+++ b/examples/custom-output-paths/package.json
@@ -12,7 +12,7 @@
"dependencies": {
"@keystone-6/core": "^6.3.1",
"@prisma/client": "5.19.0",
- "next": "^14.2.0",
+ "next": "^15.0.0",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
diff --git a/examples/document-field-customisation/nextjs-frontend/package.json b/examples/document-field-customisation/nextjs-frontend/package.json
index 45b399c1c36..0be6bd6ec1a 100644
--- a/examples/document-field-customisation/nextjs-frontend/package.json
+++ b/examples/document-field-customisation/nextjs-frontend/package.json
@@ -13,7 +13,7 @@
"@keystone-6/document-renderer": "^1.1.2",
"@preconstruct/next": "^4.0.0",
"graphql": "^16.8.1",
- "next": "^14.2.0",
+ "next": "^15.0.0",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
diff --git a/examples/document-field/README.md b/examples/document-field/README.md
index ffd84eb8744..8712f661bda 100644
--- a/examples/document-field/README.md
+++ b/examples/document-field/README.md
@@ -1,6 +1,6 @@
## Feature Example - Document Field
-This project demonstrates how to configure [document fields](https://keystonejs.com/docs/guides/document-fields) in your Keystone system and render their data in a frontend application.
+This project demonstrates how to configure [document fields](https://keystonejs.com/docs/guides/document-fields) in your Keystone system and render their data in a frontend.
It builds on the [Blog](../blog) starter project.
## Instructions
@@ -16,13 +16,7 @@ You can use the Admin UI to create items in your database.
You can also access a GraphQL Playground at [localhost:3000/api/graphql](http://localhost:3000/api/graphql), which allows you to directly run GraphQL queries and mutations.
-In a separate terminal, start the frontend dev server:
-
-```
-pnpm dev:site
-```
-
-This will start the frontend at [localhost:3001](http://localhost:3001).
+Go to url [localhost:3000/site](http://localhost:3000/site) tp see the page rendering document field content.
## Configuring fields
diff --git a/examples/document-field/next-env.d.ts b/examples/document-field/next-env.d.ts
index 7b7aa2c7727..4f11a03dc6c 100644
--- a/examples/document-field/next-env.d.ts
+++ b/examples/document-field/next-env.d.ts
@@ -1,2 +1,5 @@
///
-///
+///
+
+// 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/package.json b/examples/document-field/package.json
index 46b8951b01f..825fd009528 100644
--- a/examples/document-field/package.json
+++ b/examples/document-field/package.json
@@ -5,7 +5,6 @@
"license": "MIT",
"scripts": {
"dev": "keystone dev",
- "dev:site": "next dev -p 3001",
"start": "keystone start",
"build": "keystone build",
"postinstall": "keystone postinstall"
@@ -16,7 +15,7 @@
"@keystone-6/fields-document": "^9.1.1",
"@preconstruct/next": "^4.0.0",
"@prisma/client": "5.19.0",
- "next": "^14.2.0",
+ "next": "^15.0.0",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
diff --git a/examples/document-field/src/app/(admin)/.admin/index.tsx b/examples/document-field/src/app/(admin)/.admin/index.tsx
new file mode 100644
index 00000000000..e53104746f4
--- /dev/null
+++ b/examples/document-field/src/app/(admin)/.admin/index.tsx
@@ -0,0 +1,18 @@
+/* eslint-disable */
+import * as view0 from "@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/id-field-view"
+import * as view1 from "@keystone-6/core/fields/types/text/views"
+import * as view2 from "@keystone-6/core/fields/types/select/views"
+import * as view3 from "@keystone-6/fields-document/views"
+import * as view4 from "@keystone-6/core/fields/types/timestamp/views"
+import * as view5 from "@keystone-6/core/fields/types/relationship/views"
+
+const adminConfig = {}
+
+export const config = {
+ lazyMetadataQuery: {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"keystone","loc":{"start":22,"end":30}},"arguments":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"adminMeta","loc":{"start":39,"end":48}},"arguments":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"lists","loc":{"start":59,"end":64}},"arguments":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"key","loc":{"start":77,"end":80}},"arguments":[],"directives":[],"loc":{"start":77,"end":80}},{"kind":"Field","name":{"kind":"Name","value":"isHidden","loc":{"start":91,"end":99}},"arguments":[],"directives":[],"loc":{"start":91,"end":99}},{"kind":"Field","name":{"kind":"Name","value":"fields","loc":{"start":110,"end":116}},"arguments":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"path","loc":{"start":131,"end":135}},"arguments":[],"directives":[],"loc":{"start":131,"end":135}},{"kind":"Field","name":{"kind":"Name","value":"createView","loc":{"start":148,"end":158}},"arguments":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"fieldMode","loc":{"start":175,"end":184}},"arguments":[],"directives":[],"loc":{"start":175,"end":184}}],"loc":{"start":159,"end":198}},"loc":{"start":148,"end":198}}],"loc":{"start":117,"end":210}},"loc":{"start":110,"end":210}}],"loc":{"start":65,"end":220}},"loc":{"start":59,"end":220}}],"loc":{"start":49,"end":228}},"loc":{"start":39,"end":228}}],"loc":{"start":31,"end":234}},"loc":{"start":22,"end":234}}]}}]},
+ fieldViews: [view0,view1,view2,view3,view4,view5],
+ adminMetaHash: '1oos0js',
+ adminConfig,
+ apiPath: '/api/graphql',
+ adminPath: '',
+};
diff --git a/examples/document-field/src/app/(admin)/[listKey]/[id]/page.tsx b/examples/document-field/src/app/(admin)/[listKey]/[id]/page.tsx
new file mode 100644
index 00000000000..c5d7ea2be62
--- /dev/null
+++ b/examples/document-field/src/app/(admin)/[listKey]/[id]/page.tsx
@@ -0,0 +1,4 @@
+'use client'
+import { ItemPage } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ItemPage'
+
+export default ItemPage
diff --git a/examples/document-field/src/app/(admin)/[listKey]/create/page.tsx b/examples/document-field/src/app/(admin)/[listKey]/create/page.tsx
new file mode 100644
index 00000000000..d6042acaa96
--- /dev/null
+++ b/examples/document-field/src/app/(admin)/[listKey]/create/page.tsx
@@ -0,0 +1,4 @@
+'use client'
+import { CreateItemPage } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/CreateItemPage'
+
+export default CreateItemPage
diff --git a/examples/document-field/src/app/(admin)/[listKey]/page.tsx b/examples/document-field/src/app/(admin)/[listKey]/page.tsx
new file mode 100644
index 00000000000..f6e75f8cfab
--- /dev/null
+++ b/examples/document-field/src/app/(admin)/[listKey]/page.tsx
@@ -0,0 +1,4 @@
+'use client'
+import { ListPage } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ListPage'
+
+export default ListPage
diff --git a/examples/document-field/src/app/(admin)/author/[id]/page.tsx b/examples/document-field/src/app/(admin)/author/[id]/page.tsx
new file mode 100644
index 00000000000..59d033be780
--- /dev/null
+++ b/examples/document-field/src/app/(admin)/author/[id]/page.tsx
@@ -0,0 +1,57 @@
+import { type GetStaticPathsResult, type GetStaticPropsContext } from 'next'
+import Link from 'next/link'
+import React from 'react'
+import { DocumentRenderer } from '@keystone-6/document-renderer'
+import { fetchGraphQL, gql } from "../../../utils";
+
+export default async function Post ({ params }: any) {
+const data = await fetchGraphQL(
+ gql`
+ query ($id: ID!) {
+ author(where: { id: $id }) {
+ name
+ bio {
+ document
+ }
+ posts(where: { status: { equals: published } }, orderBy: { publishDate: desc }) {
+ id
+ title
+ slug
+ }
+ }
+ }
+ `,
+ { id: params!.id }
+)
+const author = data?.author
+ return (
+
+ {author.name}
+
+ Bio
+ {author.bio?.document && }
+
+ Posts
+ {author.posts.map((post: any) => (
+
+ {post.title}
+
+ ))}
+
+ )
+}
+
+// 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)/layout.tsx b/examples/document-field/src/app/(admin)/layout.tsx
new file mode 100644
index 00000000000..abb5a0f3b2c
--- /dev/null
+++ b/examples/document-field/src/app/(admin)/layout.tsx
@@ -0,0 +1,16 @@
+'use client'
+import { Layout } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/App'
+import { config } from './.admin'
+
+
+export default function AdminLayout ({
+ children,
+}: {
+ children: React.ReactNode
+}) {
+ return (
+
+ {children}
+
+ )
+}
\ No newline at end of file
diff --git a/examples/document-field/src/app/(admin)/no-access/page.tsx b/examples/document-field/src/app/(admin)/no-access/page.tsx
new file mode 100644
index 00000000000..70877231fee
--- /dev/null
+++ b/examples/document-field/src/app/(admin)/no-access/page.tsx
@@ -0,0 +1,4 @@
+'use client'
+import { getNoAccessPage } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/NoAccessPage'
+
+export default getNoAccessPage({ sessionsEnabled: false })
diff --git a/examples/document-field/src/app/(admin)/page.tsx b/examples/document-field/src/app/(admin)/page.tsx
new file mode 100644
index 00000000000..5c268390b0f
--- /dev/null
+++ b/examples/document-field/src/app/(admin)/page.tsx
@@ -0,0 +1,2 @@
+'use client'
+export { HomePage as default } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/pages/HomePage'
diff --git a/examples/document-field/src/pages/post/[slug].tsx b/examples/document-field/src/app/(admin)/post/[slug]/page.tsx
similarity index 80%
rename from examples/document-field/src/pages/post/[slug].tsx
rename to examples/document-field/src/app/(admin)/post/[slug]/page.tsx
index eaf941ad802..05edeb0631f 100644
--- a/examples/document-field/src/pages/post/[slug].tsx
+++ b/examples/document-field/src/app/(admin)/post/[slug]/page.tsx
@@ -2,7 +2,7 @@ import { type GetStaticPathsResult, type GetStaticPropsContext } from 'next'
import Link from 'next/link'
import React from 'react'
import { DocumentRenderer, type DocumentRendererProps } from '@keystone-6/document-renderer'
-import { fetchGraphQL, gql } from '../../utils'
+import { fetchGraphQL, gql } from "../../../utils";
// By default the DocumentRenderer will render unstyled html elements.
// We're customising how headings are rendered here but you can customise
@@ -39,7 +39,26 @@ const renderers: DocumentRendererProps['renderers'] = {
},
}
-export default function Post ({ post }: { post: any }) {
+export default async function Post ({ params }: { params: any }) {
+ const data = await fetchGraphQL(
+ gql`
+ query ($slug: String!) {
+ post(where: { slug: $slug }) {
+ title
+ content {
+ document(hydrateRelationships: true)
+ }
+ publishDate
+ author {
+ id
+ name
+ }
+ }
+ }
+ `,
+ { slug: params!.slug }
+ )
+ const post = data?.post
return (
{post.title}
@@ -60,40 +79,17 @@ export default function Post ({ post }: { post: 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',
- }
-}
-
-export async function getStaticProps ({ params }: GetStaticPropsContext) {
- // We use (hydrateRelationships: true) to ensure we have the data we need
- // to render the inline relationships.
- const data = await fetchGraphQL(
- gql`
- query ($slug: String!) {
- post(where: { slug: $slug }) {
- title
- content {
- document(hydrateRelationships: true)
- }
- publishDate
- author {
- id
- name
- }
- }
- }
- `,
- { slug: params!.slug }
- )
- return { props: { post: data.post }, revalidate: 60 }
-}
+// 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/examples/document-field/src/app/layout.tsx b/examples/document-field/src/app/layout.tsx
new file mode 100644
index 00000000000..38a4853e3a5
--- /dev/null
+++ b/examples/document-field/src/app/layout.tsx
@@ -0,0 +1,11 @@
+export default function RootLayout ({
+ children,
+}: {
+ children: React.ReactNode
+}) {
+ return (
+
+ {children}
+
+ )
+}
diff --git a/examples/document-field/src/pages/index.tsx b/examples/document-field/src/app/site/page.tsx
similarity index 58%
rename from examples/document-field/src/pages/index.tsx
rename to examples/document-field/src/app/site/page.tsx
index 737a083edb8..5af491efde4 100644
--- a/examples/document-field/src/pages/index.tsx
+++ b/examples/document-field/src/app/site/page.tsx
@@ -1,21 +1,44 @@
import Link from 'next/link'
import React from 'react'
-import { fetchGraphQL, gql } from '../utils'
+import { fetchGraphQL, gql } from "../utils";
-type Author = { id: string, name: string, posts: { id: string, slug: string, title: string }[] }
+type Author = {
+ id: string
+ name: string
+ posts: { id: string, slug: string, title: string }[]
+}
+
+export default async function Index () {
+ const data = await fetchGraphQL(gql`
+ query {
+ authors {
+ id
+ name
+ posts(
+ where: { status: { equals: published } }
+ orderBy: { publishDate: desc }
+ ) {
+ id
+ slug
+ title
+ }
+ }
+ }
+ `)
+
+ const authors: Author[] = data?.authors || []
-export default function Index ({ authors }: { authors: Author[] }) {
return (
<>
Keystone Blog Project - Home
- {authors.map(author => (
+ {authors.map((author) => (
-
{author.name}
- {author.posts.map(post => (
+ {author.posts.map((post) => (
-
{post.title}
@@ -27,20 +50,3 @@ export default function Index ({ authors }: { authors: Author[] }) {
>
)
}
-
-export async function getStaticProps () {
- const data = await fetchGraphQL(gql`
- query {
- authors {
- id
- name
- posts(where: { status: { equals: published } }, orderBy: { publishDate: desc }) {
- id
- slug
- title
- }
- }
- }
- `)
- return { props: { authors: data.authors }, revalidate: 30 }
-}
diff --git a/examples/document-field/src/utils.tsx b/examples/document-field/src/app/utils.tsx
similarity index 100%
rename from examples/document-field/src/utils.tsx
rename to examples/document-field/src/app/utils.tsx
diff --git a/examples/document-field/src/pages/author/[id].tsx b/examples/document-field/src/pages/author/[id].tsx
deleted file mode 100644
index f3aa3dbdf80..00000000000
--- a/examples/document-field/src/pages/author/[id].tsx
+++ /dev/null
@@ -1,59 +0,0 @@
-import { type GetStaticPathsResult, type GetStaticPropsContext } from 'next'
-import Link from 'next/link'
-import React from 'react'
-import { DocumentRenderer } from '@keystone-6/document-renderer'
-import { fetchGraphQL, gql } from '../../utils'
-
-export default function Post ({ author }: { author: any }) {
- return (
-
- {author.name}
-
- Bio
- {author.bio?.document && }
-
- Posts
- {author.posts.map((post: any) => (
- -
- {post.title}
-
- ))}
-
- )
-}
-
-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',
- }
-}
-
-export async function getStaticProps ({ params }: GetStaticPropsContext) {
- const data = await fetchGraphQL(
- gql`
- query ($id: ID!) {
- author(where: { id: $id }) {
- name
- bio {
- document
- }
- posts(where: { status: { equals: published } }, orderBy: { publishDate: desc }) {
- id
- title
- slug
- }
- }
- }
- `,
- { id: params!.id }
- )
- return { props: { author: data.author }, revalidate: 60 }
-}
diff --git a/examples/document-field/tsconfig.json b/examples/document-field/tsconfig.json
index 1ed5fb820cb..64857dc28d3 100644
--- a/examples/document-field/tsconfig.json
+++ b/examples/document-field/tsconfig.json
@@ -1,7 +1,11 @@
{
"compilerOptions": {
"target": "esnext",
- "lib": ["dom", "dom.iterable", "esnext"],
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
"allowJs": false,
"skipLibCheck": false,
"strict": true,
@@ -12,8 +16,21 @@
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
- "jsx": "preserve"
+ "jsx": "preserve",
+ "incremental": true,
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ]
},
- "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
- "exclude": ["node_modules"]
+ "include": [
+ "next-env.d.ts",
+ "**/*.ts",
+ "**/*.tsx",
+ ".next/types/**/*.ts"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
}
diff --git a/examples/framework-nextjs-app-directory/package.json b/examples/framework-nextjs-app-directory/package.json
index 49df06b4f04..39764275387 100644
--- a/examples/framework-nextjs-app-directory/package.json
+++ b/examples/framework-nextjs-app-directory/package.json
@@ -23,7 +23,7 @@
"graphql": "^16.8.1",
"graphql-request": "^5.0.0",
"graphql-yoga": "^3.1.0",
- "next": "^14.2.0",
+ "next": "^15.0.0",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
diff --git a/examples/framework-nextjs-pages-directory/package.json b/examples/framework-nextjs-pages-directory/package.json
index 96fc375ea84..0a678e80a7e 100644
--- a/examples/framework-nextjs-pages-directory/package.json
+++ b/examples/framework-nextjs-pages-directory/package.json
@@ -22,7 +22,7 @@
"graphql": "^16.8.1",
"graphql-request": "^5.0.0",
"graphql-yoga": "^3.1.0",
- "next": "^14.2.0",
+ "next": "^15.0.0",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
diff --git a/examples/framework-nextjs-two-servers/nextjs-frontend/package.json b/examples/framework-nextjs-two-servers/nextjs-frontend/package.json
index 04dbf136118..19a874230cc 100644
--- a/examples/framework-nextjs-two-servers/nextjs-frontend/package.json
+++ b/examples/framework-nextjs-two-servers/nextjs-frontend/package.json
@@ -13,7 +13,7 @@
"@keystone-6/document-renderer": "^1.1.2",
"@preconstruct/next": "^4.0.0",
"graphql": "^16.8.1",
- "next": "^14.2.0",
+ "next": "^15.0.0",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
diff --git a/packages/auth/src/index.ts b/packages/auth/src/index.ts
index 68448486a4c..3929bd4a9a0 100644
--- a/packages/auth/src/index.ts
+++ b/packages/auth/src/index.ts
@@ -99,19 +99,20 @@ export function createAuth ({
*
* The signin page is always included, and the init page is included when initFirstItem is set
*/
- const authGetAdditionalFiles = () => {
+ const authGetAdditionalFiles = ({ tsx }: { tsx: boolean }) => {
+ const ext = tsx ? 'tsx' : 'js'
const filesToWrite: AdminFileToWrite[] = [
{
mode: 'write',
src: signinTemplate({ gqlNames, identityField, secretField }),
- outputPath: 'pages/signin.js',
+ outputPath: `signin/page.${ext}`,
},
]
if (initFirstItem) {
filesToWrite.push({
mode: 'write',
src: initTemplate({ listKey, initFirstItem }),
- outputPath: 'pages/init.js',
+ outputPath: `init/page.${ext}`,
})
}
return filesToWrite
@@ -215,7 +216,6 @@ export function createAuth ({
}): Promise<{ kind: 'redirect', to: string } | void> {
const { req } = context
const { pathname } = new URL(req!.url!, 'http://_')
-
// redirect to init if initFirstItem conditions are met
if (pathname !== `${basePath}/init` && (await hasInitFirstItemConditions(context))) {
return { kind: 'redirect', to: `${basePath}/init` }
@@ -262,7 +262,7 @@ export function createAuth ({
ui = {
...ui,
publicPages: [...publicPages, ...authPublicPages],
- getAdditionalFiles: [...getAdditionalFiles, authGetAdditionalFiles],
+ getAdditionalFiles: [...getAdditionalFiles, () => authGetAdditionalFiles({ tsx: ui?.tsx ?? true })],
isAccessAllowed: async (context: KeystoneContext) => {
if (await hasInitFirstItemConditions(context)) return true
diff --git a/packages/auth/src/lib/useFromRedirect.ts b/packages/auth/src/lib/useFromRedirect.ts
deleted file mode 100644
index 6b0828e2c4f..00000000000
--- a/packages/auth/src/lib/useFromRedirect.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import { useMemo } from 'react'
-
-// TODO: remove or fix
-export function useRedirect () {
- return useMemo(() => '/', [])
-}
diff --git a/packages/auth/src/pages/InitPage.tsx b/packages/auth/src/pages/InitPage.tsx
index 2b8a3317760..fc71d85689d 100644
--- a/packages/auth/src/pages/InitPage.tsx
+++ b/packages/auth/src/pages/InitPage.tsx
@@ -22,7 +22,6 @@ import {
import { guessEmailFromValue, validEmail } from '../lib/emailHeuristics'
import { IconTwitter, IconGithub } from '../components/Icons'
import { SigninContainer } from '../components/SigninContainer'
-import { useRedirect } from '../lib/useFromRedirect'
const signupURL = 'https://endpoints.thinkmill.com.au/newsletter'
@@ -36,6 +35,7 @@ function Welcome ({ value, onContinue }: { value: any, onContinue: () => void })
const [email, setEmail] = useState(guessEmailFromValue(value))
const [error, setError] = useState(null)
const [loading, setLoading] = useState(false)
+ const { adminPath } = useKeystone()
const onSubmit = async (event: React.FormEvent) => {
event.preventDefault()
@@ -166,7 +166,7 @@ function Welcome ({ value, onContinue }: { value: any, onContinue: () => void })
{error ? 'Try again' : 'Continue'}
{error && (
-