From 87caf3840dc47a216c51635f6c7918766be072ba Mon Sep 17 00:00:00 2001 From: Kennedy Baird Date: Tue, 13 Aug 2024 10:34:58 +1200 Subject: [PATCH 01/12] embed seed data in seed-data file + commit example db + fix prisma path --- .gitignore | 1 + examples/usecase-todo/keystone.example.db | Bin 0 -> 28672 bytes examples/usecase-todo/keystone.ts | 5 +- examples/usecase-todo/seed-data.ts | 74 +++++++++++++++++++++- 4 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 examples/usecase-todo/keystone.example.db diff --git a/.gitignore b/.gitignore index 9a1df743cce..88fc027f3ef 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ dist/ node_modules/ *.db +!*.example.db # ts-gql __generated__ diff --git a/examples/usecase-todo/keystone.example.db b/examples/usecase-todo/keystone.example.db new file mode 100644 index 0000000000000000000000000000000000000000..39636861ee470a2434eb1b4f181e9f8a05eeedf6 GIT binary patch literal 28672 zcmeI3-)kI29Kdh0m)j&XS<@0iKxMc-q-VtDa<)m4vb`qT_Uz>@$=%hqqQ~CeTz7N( z)zbu ze>m_&>E}W5k3eYOpMjyg_~qaSLsNt2$O9B000e*l5C8%|00;m9AOHk_z<);IVkk5^ zF~(iits<^3V8^wsyrq~pU&f90qcFQ9$FnlZr4oxd86{G4@_7{AAsR;MRJSsGC`>hk zBhU8=qp=ZgjcX~-DsDNixUPQ5!o{qe*Nb&p73!$(=-oxCt(!Iw&07k>ktQ#Uj*W3^ zX-_E_xZR`nZ?K~@8$X$p@AL~D8bG9k^OrnLQ#C&||0y-;Sc)Tss z@?eM5oO~*tOJ>pd_&{VL7#fwvxIoJ_cf}yf$GlSY?ACL>Lnqq)?|sqagwc@^?#l62 zPpK>P>e=4QmWO|*kA_mf#!gqZI@$50;^?-cdyTeWr&4!kZL?xv4~NmobUG==Q(H8; zDoTps;?4^U_ZF2-bxF5$S360R&yhKjP0Y*fhS_u~lU<4@QdtzHez5~zB2z1jPNkRR z#OV}8jqAVH$`da`=QH22M0eM%zlT=)FVl|_A$>ZuT-+oCe_X$#-Rf~yOfy$XH(R#^UuFTlO z+;BbH!lUtu z1YLld*z#Jsa|u+$G&q2C3#oPy6Q^!`Wa6S;H9LNpO`;-3RWw!eSf!y%a`oqKrZhDq zND0Q2P5nPc(^h|W@I;bnfV*q#a=-= zexU!(nApq2$P6_y?M*iwV^UwJ77Vf&Zh6x+wYmPv&Gl6f&Q=2CPYOrL83-2(RcO!G??a#l(oFFZ-nhQkplT@>_ zygXH3HjXAN*Ha8*YtEACW7w)?01yBIKmZ5;0U!VbfB+Bx0zd!={GSOt!b{wq;iZ1I)fXk|V_SV; z9f4`}M`A*3t1pDo%eMN0AVH?pAI0F=R$l<3=V4yz@Azx^f(Uf~KPYAb;@9GP;$?CJ z1qc8EAOHk_01yBIKmZ5;0U!VbfB+D<7Xpt3c`34I;>HVKWHUGpR>pZ=I@p!< zr7>jnQVBh+G>X`Y^zhPnSJ0PCF{@!0#f!M0G;C*rxZ|9f!|WPkt=00KY&2mk>f00e*l5C8%|00;nq`y{~Z;rmZ}u>1d}FHFGh z|ND;1f1Z~&A4e~V=Ple~X&4xmiV0UW+hKj1YW00e*l5C8%|00;m9AOHk_01yBI z4+a5drR`r2v-$u2RyP0Nze;EG|NZZ>`Tzb^I-CFRU*WUsf4}B`y8aJ}8v*ef00e*l5C8%|00;m9AV3N1=Of(qqXa>bKgcmB2KZrqoZEIV Npl3fn(Z3`A|1Wc%T($rJ literal 0 HcmV?d00001 diff --git a/examples/usecase-todo/keystone.ts b/examples/usecase-todo/keystone.ts index a735710d7a0..90db89c4a6f 100644 --- a/examples/usecase-todo/keystone.ts +++ b/examples/usecase-todo/keystone.ts @@ -1,15 +1,14 @@ import { config } from '@keystone-6/core' -import { fixPrismaPath } from '../example-utils' import { lists } from './schema' import type { TypeInfo } from '.keystone/types' export default config({ db: { provider: 'sqlite', - url: process.env.DATABASE_URL || 'file:./keystone-example.db', + url: process.env.DATABASE_URL || 'file:./keystone.example.db', // WARNING: this is only needed for our monorepo examples, dont do this - ...fixPrismaPath, + prismaClientPath: 'node_modules/.myprisma/client', }, lists, }) diff --git a/examples/usecase-todo/seed-data.ts b/examples/usecase-todo/seed-data.ts index e1199dd5f7f..7b1e95f70e2 100644 --- a/examples/usecase-todo/seed-data.ts +++ b/examples/usecase-todo/seed-data.ts @@ -1,19 +1,91 @@ import { getContext } from '@keystone-6/core/context' -import { persons, tasks } from '../example-data' import config from './keystone' import * as PrismaModule from '.myprisma/client' type PersonProps = { name: string } +const persons: PersonProps[] = [ + { name: 'Lucy Wroblewski' }, + { name: 'Ches Adebayor' }, + { name: 'Tiff Jayden' }, + { name: 'Henrique Urrea' }, +] type TaskProps = { label: string isComplete: boolean finishBy: string assignedTo: string + priority: 'low' | 'medium' | 'high' } +const tasks: TaskProps[] = [ + { + label: 'Install Keystone in local dev 🧪', + isComplete: true, + finishBy: '2021-01-01T02:30:00.000Z', + assignedTo: 'Lucy Wroblewski', + priority: 'high', + }, + { + label: 'Model the content💡', + isComplete: true, + finishBy: '2021-01-22T05:43:51.000Z', + assignedTo: 'Ches Adebayor', + priority: 'high', + }, + { + label: 'Architect the data schema 🔗', + isComplete: true, + finishBy: '2021-02-02T20:02:37.000Z', + assignedTo: 'Lucy Wroblewski', + priority: 'high', + }, + { + label: 'Design the UI 💅🏼', + isComplete: true, + finishBy: '2021-02-24T22:17:07.000Z', + assignedTo: 'Tiff Jayden', + priority: 'medium', + }, + { + label: 'Publish the content 📝', + isComplete: true, + finishBy: '2021-03-01T05:41:37.000Z', + assignedTo: 'Ches Adebayor', + priority: 'low', + }, + { + label: 'Query content over GraphQL🔎', + isComplete: false, + finishBy: '2021-03-21T05:41:37.000Z', + assignedTo: 'Lucy Wroblewski', + priority: 'medium', + }, + { + label: 'Implement the UI design in code 🖼', + isComplete: false, + finishBy: '2021-03-23T05:41:37.000Z', + assignedTo: 'Henrique Urrea', + priority: 'medium', + }, + { + label: 'Deploy Keystone backend to the web ☁️', + isComplete: false, + finishBy: '2021-03-30T05:41:37.000Z', + assignedTo: 'Lucy Wroblewski', + priority: 'low', + }, + { + label: 'Launch project 🚀', + isComplete: false, + finishBy: '2021-04-01T05:41:37.000Z', + assignedTo: 'Lucy Wroblewski', + priority: 'low', + }, +] + export async function main () { const context = getContext(config, PrismaModule) From b3a70468b767d1b105532ce6cdae2b178f635bfb Mon Sep 17 00:00:00 2001 From: Kennedy Baird Date: Tue, 13 Aug 2024 10:35:31 +1200 Subject: [PATCH 02/12] move to new codesandbox schema + remove explicit prisma deps --- examples/usecase-todo/.codesandbox/tasks.json | 15 +++++++++++++++ .../usecase-todo/.devcontainer/devcontainer.json | 4 ++++ examples/usecase-todo/package.json | 7 ++----- examples/usecase-todo/sandbox.config.json | 7 ------- pnpm-lock.yaml | 8 +------- 5 files changed, 22 insertions(+), 19 deletions(-) create mode 100644 examples/usecase-todo/.codesandbox/tasks.json create mode 100644 examples/usecase-todo/.devcontainer/devcontainer.json delete mode 100644 examples/usecase-todo/sandbox.config.json diff --git a/examples/usecase-todo/.codesandbox/tasks.json b/examples/usecase-todo/.codesandbox/tasks.json new file mode 100644 index 00000000000..be4c9957034 --- /dev/null +++ b/examples/usecase-todo/.codesandbox/tasks.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://codesandbox.io/schemas/tasks.json", + "setupTasks": [ + { + "name": "Installing Dependencies", + "command": "yarn install" + } + ], + "tasks": { + "start": { + "name": "Start Development", + "command": "yarn dev" + } + } +} \ No newline at end of file diff --git a/examples/usecase-todo/.devcontainer/devcontainer.json b/examples/usecase-todo/.devcontainer/devcontainer.json new file mode 100644 index 00000000000..8017d492b37 --- /dev/null +++ b/examples/usecase-todo/.devcontainer/devcontainer.json @@ -0,0 +1,4 @@ +{ + "name": "Node.js", + "image": "mcr.microsoft.com/devcontainers/javascript-node:20" +} \ No newline at end of file diff --git a/examples/usecase-todo/package.json b/examples/usecase-todo/package.json index 97a2e1763ac..d1f85b89a53 100644 --- a/examples/usecase-todo/package.json +++ b/examples/usecase-todo/package.json @@ -7,16 +7,13 @@ "dev": "keystone dev", "start": "keystone start", "build": "keystone build", - "postinstall": "keystone postinstall", "seed-data": "tsx seed-data.ts" }, "dependencies": { - "@keystone-6/core": "^6.2.0", - "@prisma/client": "5.17.0" + "@keystone-6/core": "^6.2.0" }, "devDependencies": { - "prisma": "5.17.0", - "tsx": "^4.0.0", + "tsx": "^4.16.0", "typescript": "^5.5.0" } } diff --git a/examples/usecase-todo/sandbox.config.json b/examples/usecase-todo/sandbox.config.json deleted file mode 100644 index 7a34682ee45..00000000000 --- a/examples/usecase-todo/sandbox.config.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "template": "node", - "container": { - "startScript": "keystone dev", - "node": "16" - } -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 97a038288ba..ecd6a5dd3b0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1827,15 +1827,9 @@ importers: '@keystone-6/core': specifier: ^6.2.0 version: link:../../packages/core - '@prisma/client': - specifier: 5.17.0 - version: 5.17.0(prisma@5.17.0) devDependencies: - prisma: - specifier: 5.17.0 - version: 5.17.0 tsx: - specifier: ^4.0.0 + specifier: ^4.16.0 version: 4.17.0 typescript: specifier: ^5.5.0 From d3fe2a972d3aec2bc75a3093153b36a55182126c Mon Sep 17 00:00:00 2001 From: Kennedy Baird Date: Tue, 13 Aug 2024 10:52:17 +1200 Subject: [PATCH 03/12] add explicit setup start command for first run --- examples/usecase-todo/.codesandbox/tasks.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/usecase-todo/.codesandbox/tasks.json b/examples/usecase-todo/.codesandbox/tasks.json index be4c9957034..5e07b2840de 100644 --- a/examples/usecase-todo/.codesandbox/tasks.json +++ b/examples/usecase-todo/.codesandbox/tasks.json @@ -4,6 +4,10 @@ { "name": "Installing Dependencies", "command": "yarn install" + }, + { + "name": "Start Dev Server", + "command": "yarn dev" } ], "tasks": { From cf82ada7243825e7feb07359dc76483c18c75a68 Mon Sep 17 00:00:00 2001 From: Kennedy Baird Date: Tue, 13 Aug 2024 11:33:47 +1200 Subject: [PATCH 04/12] remove schemas + add examples schema files to gitignore --- .gitignore | 3 + examples/usecase-todo/schema.graphql | 366 --------------------------- examples/usecase-todo/schema.prisma | 31 --- 3 files changed, 3 insertions(+), 397 deletions(-) delete mode 100644 examples/usecase-todo/schema.graphql delete mode 100644 examples/usecase-todo/schema.prisma diff --git a/.gitignore b/.gitignore index 88fc027f3ef..b34387f1d97 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,6 @@ __generated__ # system .DS_Store *.vscode + +examples/**/*/schema.prisma +examples/**/*/schema.graphql \ No newline at end of file diff --git a/examples/usecase-todo/schema.graphql b/examples/usecase-todo/schema.graphql deleted file mode 100644 index ff520d54195..00000000000 --- a/examples/usecase-todo/schema.graphql +++ /dev/null @@ -1,366 +0,0 @@ -# This file is automatically generated by Keystone, do not modify it manually. -# Modify your Keystone config when you want to change this. - -type Task { - id: ID! - label: String - priority: TaskPriorityType - isComplete: Boolean - assignedTo: Person - finishBy: DateTime -} - -enum TaskPriorityType { - low - medium - high -} - -scalar DateTime @specifiedBy(url: "https://datatracker.ietf.org/doc/html/rfc3339#section-5.6") - -input TaskWhereUniqueInput { - id: ID -} - -input TaskWhereInput { - AND: [TaskWhereInput!] - OR: [TaskWhereInput!] - NOT: [TaskWhereInput!] - id: IDFilter - label: StringFilter - priority: TaskPriorityTypeNullableFilter - isComplete: BooleanFilter - assignedTo: PersonWhereInput - finishBy: DateTimeNullableFilter -} - -input IDFilter { - equals: ID - in: [ID!] - notIn: [ID!] - lt: ID - lte: ID - gt: ID - gte: ID - not: IDFilter -} - -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 TaskPriorityTypeNullableFilter { - equals: TaskPriorityType - in: [TaskPriorityType!] - notIn: [TaskPriorityType!] - not: TaskPriorityTypeNullableFilter -} - -input BooleanFilter { - equals: Boolean - not: BooleanFilter -} - -input DateTimeNullableFilter { - equals: DateTime - in: [DateTime!] - notIn: [DateTime!] - lt: DateTime - lte: DateTime - gt: DateTime - gte: DateTime - not: DateTimeNullableFilter -} - -input TaskOrderByInput { - id: OrderDirection - label: OrderDirection - priority: OrderDirection - isComplete: OrderDirection - finishBy: OrderDirection -} - -enum OrderDirection { - asc - desc -} - -input TaskUpdateInput { - label: String - priority: TaskPriorityType - isComplete: Boolean - assignedTo: PersonRelateToOneForUpdateInput - finishBy: DateTime -} - -input PersonRelateToOneForUpdateInput { - create: PersonCreateInput - connect: PersonWhereUniqueInput - disconnect: Boolean -} - -input TaskUpdateArgs { - where: TaskWhereUniqueInput! - data: TaskUpdateInput! -} - -input TaskCreateInput { - label: String - priority: TaskPriorityType - isComplete: Boolean - assignedTo: PersonRelateToOneForCreateInput - finishBy: DateTime -} - -input PersonRelateToOneForCreateInput { - create: PersonCreateInput - connect: PersonWhereUniqueInput -} - -type Person { - id: ID! - name: String - tasks(where: TaskWhereInput! = {}, orderBy: [TaskOrderByInput!]! = [], take: Int, skip: Int! = 0, cursor: TaskWhereUniqueInput): [Task!] - tasksCount(where: TaskWhereInput! = {}): Int -} - -input PersonWhereUniqueInput { - id: ID - name: String -} - -input PersonWhereInput { - AND: [PersonWhereInput!] - OR: [PersonWhereInput!] - NOT: [PersonWhereInput!] - id: IDFilter - name: StringFilter - tasks: TaskManyRelationFilter -} - -input TaskManyRelationFilter { - every: TaskWhereInput - some: TaskWhereInput - none: TaskWhereInput -} - -input PersonOrderByInput { - id: OrderDirection - name: OrderDirection -} - -input PersonUpdateInput { - name: String - tasks: TaskRelateToManyForUpdateInput -} - -input TaskRelateToManyForUpdateInput { - disconnect: [TaskWhereUniqueInput!] - set: [TaskWhereUniqueInput!] - create: [TaskCreateInput!] - connect: [TaskWhereUniqueInput!] -} - -input PersonUpdateArgs { - where: PersonWhereUniqueInput! - data: PersonUpdateInput! -} - -input PersonCreateInput { - name: String - tasks: TaskRelateToManyForCreateInput -} - -input TaskRelateToManyForCreateInput { - create: [TaskCreateInput!] - connect: [TaskWhereUniqueInput!] -} - -""" -The `JSON` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). -""" -scalar JSON @specifiedBy(url: "http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf") - -type Mutation { - createTask(data: TaskCreateInput!): Task - createTasks(data: [TaskCreateInput!]!): [Task] - updateTask(where: TaskWhereUniqueInput!, data: TaskUpdateInput!): Task - updateTasks(data: [TaskUpdateArgs!]!): [Task] - deleteTask(where: TaskWhereUniqueInput!): Task - deleteTasks(where: [TaskWhereUniqueInput!]!): [Task] - createPerson(data: PersonCreateInput!): Person - createPeople(data: [PersonCreateInput!]!): [Person] - updatePerson(where: PersonWhereUniqueInput!, data: PersonUpdateInput!): Person - updatePeople(data: [PersonUpdateArgs!]!): [Person] - deletePerson(where: PersonWhereUniqueInput!): Person - deletePeople(where: [PersonWhereUniqueInput!]!): [Person] -} - -type Query { - task(where: TaskWhereUniqueInput!): Task - tasks(where: TaskWhereInput! = {}, orderBy: [TaskOrderByInput!]! = [], take: Int, skip: Int! = 0, cursor: TaskWhereUniqueInput): [Task!] - tasksCount(where: TaskWhereInput! = {}): Int - person(where: PersonWhereUniqueInput!): Person - people(where: PersonWhereInput! = {}, orderBy: [PersonOrderByInput!]! = [], take: Int, skip: Int! = 0, cursor: PersonWhereUniqueInput): [Person!] - peopleCount(where: PersonWhereInput! = {}): Int - keystone: KeystoneMeta! -} - -type KeystoneMeta { - adminMeta: KeystoneAdminMeta! -} - -type KeystoneAdminMeta { - lists: [KeystoneAdminUIListMeta!]! - list(key: String!): KeystoneAdminUIListMeta -} - -type KeystoneAdminUIListMeta { - key: String! - itemQueryName: String! - listQueryName: String! - hideCreate: Boolean! - hideDelete: Boolean! - path: String! - label: String! - singular: String! - plural: String! - description: String - initialColumns: [String!]! - pageSize: Int! - labelField: String! - fields: [KeystoneAdminUIFieldMeta!]! - groups: [KeystoneAdminUIFieldGroupMeta!]! - graphql: KeystoneAdminUIGraphQL! - initialSort: KeystoneAdminUISort - isHidden: Boolean! - isSingleton: Boolean! -} - -type KeystoneAdminUIFieldMeta { - path: String! - label: String! - description: String - isOrderable: Boolean! - isFilterable: Boolean! - isNonNull: [KeystoneAdminUIFieldMetaIsNonNull!] - fieldMeta: JSON - viewsIndex: Int! - customViewsIndex: Int - createView: KeystoneAdminUIFieldMetaCreateView! - listView: KeystoneAdminUIFieldMetaListView! - itemView(id: ID): KeystoneAdminUIFieldMetaItemView - search: QueryMode -} - -enum KeystoneAdminUIFieldMetaIsNonNull { - read - create - update -} - -type KeystoneAdminUIFieldMetaCreateView { - fieldMode: KeystoneAdminUIFieldMetaCreateViewFieldMode! -} - -enum KeystoneAdminUIFieldMetaCreateViewFieldMode { - edit - hidden -} - -type KeystoneAdminUIFieldMetaListView { - fieldMode: KeystoneAdminUIFieldMetaListViewFieldMode! -} - -enum KeystoneAdminUIFieldMetaListViewFieldMode { - read - hidden -} - -type KeystoneAdminUIFieldMetaItemView { - fieldMode: KeystoneAdminUIFieldMetaItemViewFieldMode - fieldPosition: KeystoneAdminUIFieldMetaItemViewFieldPosition -} - -enum KeystoneAdminUIFieldMetaItemViewFieldMode { - edit - read - hidden -} - -enum KeystoneAdminUIFieldMetaItemViewFieldPosition { - form - sidebar -} - -enum QueryMode { - default - insensitive -} - -type KeystoneAdminUIFieldGroupMeta { - label: String! - description: String - fields: [KeystoneAdminUIFieldMeta!]! -} - -type KeystoneAdminUIGraphQL { - names: KeystoneAdminUIGraphQLNames! -} - -type KeystoneAdminUIGraphQLNames { - outputTypeName: String! - whereInputName: String! - whereUniqueInputName: String! - createInputName: String! - createMutationName: String! - createManyMutationName: String! - relateToOneForCreateInputName: String! - relateToManyForCreateInputName: String! - itemQueryName: String! - listOrderName: String! - listQueryCountName: String! - listQueryName: String! - updateInputName: String! - updateMutationName: String! - updateManyInputName: String! - updateManyMutationName: String! - relateToOneForUpdateInputName: String! - relateToManyForUpdateInputName: String! - deleteMutationName: String! - deleteManyMutationName: String! -} - -type KeystoneAdminUISort { - field: String! - direction: KeystoneAdminUISortDirection! -} - -enum KeystoneAdminUISortDirection { - ASC - DESC -} diff --git a/examples/usecase-todo/schema.prisma b/examples/usecase-todo/schema.prisma deleted file mode 100644 index 3d39c2e0c4e..00000000000 --- a/examples/usecase-todo/schema.prisma +++ /dev/null @@ -1,31 +0,0 @@ -// This file is automatically generated by Keystone, do not modify it manually. -// Modify your Keystone config when you want to change this. - -datasource sqlite { - url = env("DATABASE_URL") - shadowDatabaseUrl = env("SHADOW_DATABASE_URL") - provider = "sqlite" -} - -generator client { - provider = "prisma-client-js" - output = "node_modules/.myprisma/client" -} - -model Task { - id String @id @default(cuid()) - label String @default("") - priority String? - isComplete Boolean @default(false) - assignedTo Person? @relation("Task_assignedTo", fields: [assignedToId], references: [id]) - assignedToId String? @map("assignedTo") - finishBy DateTime? - - @@index([assignedToId]) -} - -model Person { - id String @id @default(cuid()) - name String @unique @default("") - tasks Task[] @relation("Task_assignedTo") -} From 706600d4a301d4bfcc3b7e79758baef18a8f3fce Mon Sep 17 00:00:00 2001 From: Kennedy Baird Date: Tue, 13 Aug 2024 11:39:47 +1200 Subject: [PATCH 05/12] fix - prisma needs to be defined or it can install a later version --- examples/usecase-todo/package.json | 4 +++- pnpm-lock.yaml | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/examples/usecase-todo/package.json b/examples/usecase-todo/package.json index d1f85b89a53..1f36e88cc0d 100644 --- a/examples/usecase-todo/package.json +++ b/examples/usecase-todo/package.json @@ -10,9 +10,11 @@ "seed-data": "tsx seed-data.ts" }, "dependencies": { - "@keystone-6/core": "^6.2.0" + "@keystone-6/core": "^6.2.0", + "@prisma/client": "*" }, "devDependencies": { + "prisma": "*", "tsx": "^4.16.0", "typescript": "^5.5.0" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ecd6a5dd3b0..c642dbdca6c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1827,7 +1827,13 @@ importers: '@keystone-6/core': specifier: ^6.2.0 version: link:../../packages/core + '@prisma/client': + specifier: '*' + version: 5.17.0(prisma@5.17.0) devDependencies: + prisma: + specifier: '*' + version: 5.17.0 tsx: specifier: ^4.16.0 version: 4.17.0 From f24320c3d1c4b43d57e1b53fb2a03060a7907f08 Mon Sep 17 00:00:00 2001 From: kennedybaird <103093254+kennedybaird@users.noreply.github.com> Date: Tue, 13 Aug 2024 14:29:20 +1200 Subject: [PATCH 06/12] simplify example db file name Co-authored-by: Daniel Cousens <413395+dcousens@users.noreply.github.com> --- examples/usecase-todo/keystone.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/usecase-todo/keystone.ts b/examples/usecase-todo/keystone.ts index 90db89c4a6f..41bc8f7b39b 100644 --- a/examples/usecase-todo/keystone.ts +++ b/examples/usecase-todo/keystone.ts @@ -5,7 +5,7 @@ import type { TypeInfo } from '.keystone/types' export default config({ db: { provider: 'sqlite', - url: process.env.DATABASE_URL || 'file:./keystone.example.db', + url: process.env.DATABASE_URL ?? 'file:./example.db', // WARNING: this is only needed for our monorepo examples, dont do this prismaClientPath: 'node_modules/.myprisma/client', From b63324996392859e2714aa696bc9359b95800b63 Mon Sep 17 00:00:00 2001 From: Kennedy Baird Date: Tue, 13 Aug 2024 14:31:27 +1200 Subject: [PATCH 07/12] prefer pnpm over yarn --- examples/usecase-todo/.codesandbox/tasks.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/usecase-todo/.codesandbox/tasks.json b/examples/usecase-todo/.codesandbox/tasks.json index 5e07b2840de..c5c782f8594 100644 --- a/examples/usecase-todo/.codesandbox/tasks.json +++ b/examples/usecase-todo/.codesandbox/tasks.json @@ -3,17 +3,17 @@ "setupTasks": [ { "name": "Installing Dependencies", - "command": "yarn install" + "command": "pnpm install" }, { "name": "Start Dev Server", - "command": "yarn dev" + "command": "pnpm dev" } ], "tasks": { "start": { "name": "Start Development", - "command": "yarn dev" + "command": "pnpm dev" } } } \ No newline at end of file From a8b4c20ac26f0d306f6782b4cc9fbb59c5eaa3c1 Mon Sep 17 00:00:00 2001 From: Kennedy Baird Date: Tue, 13 Aug 2024 14:31:47 +1200 Subject: [PATCH 08/12] change to example.db --- .gitignore | 2 +- .../{keystone.example.db => example.db} | Bin 2 files changed, 1 insertion(+), 1 deletion(-) rename examples/usecase-todo/{keystone.example.db => example.db} (100%) diff --git a/.gitignore b/.gitignore index b34387f1d97..4e8d9def902 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ dist/ node_modules/ *.db -!*.example.db +!example.db # ts-gql __generated__ diff --git a/examples/usecase-todo/keystone.example.db b/examples/usecase-todo/example.db similarity index 100% rename from examples/usecase-todo/keystone.example.db rename to examples/usecase-todo/example.db From 3bca6a19133de6d9a4dddeb7b80f23ebbdd420d4 Mon Sep 17 00:00:00 2001 From: Kennedy Baird Date: Tue, 20 Aug 2024 09:13:18 +1200 Subject: [PATCH 09/12] add custom examples script, add targeted postinstall to root package json --- examples/usecase-todo/package.json | 1 + package.json | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/usecase-todo/package.json b/examples/usecase-todo/package.json index 1f36e88cc0d..0946af5198c 100644 --- a/examples/usecase-todo/package.json +++ b/examples/usecase-todo/package.json @@ -7,6 +7,7 @@ "dev": "keystone dev", "start": "keystone start", "build": "keystone build", + "monorepo:example-fixed-build-test": "keystone build --no-ui --frozen", "seed-data": "tsx seed-data.ts" }, "dependencies": { diff --git a/package.json b/package.json index 777f882d7dd..8ab855abdd7 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,8 @@ "test:debug": "node --inspect-brk ./node_modules/.bin/jest", "test:admin-ui": "jest tests/admin-ui-tests", "build": "preconstruct build", - "prepare": "preconstruct dev" + "prepare": "preconstruct dev", + "postinstall": "pnpm -F './examples/**' run monorepo:example-fixed-build-test" }, "devDependencies": { "@babel/core": "^7.24.7", From dc819b4e34c237053a224ef63039e0e0fddd1190 Mon Sep 17 00:00:00 2001 From: Kennedy Baird Date: Tue, 20 Aug 2024 09:13:37 +1200 Subject: [PATCH 10/12] re-add schemas, remove from ignore --- .gitignore | 5 +- examples/usecase-todo/schema.graphql | 366 +++++++++++++++++++++++++++ examples/usecase-todo/schema.prisma | 31 +++ 3 files changed, 398 insertions(+), 4 deletions(-) create mode 100644 examples/usecase-todo/schema.graphql create mode 100644 examples/usecase-todo/schema.prisma diff --git a/.gitignore b/.gitignore index 4e8d9def902..a0f2c3ad56e 100644 --- a/.gitignore +++ b/.gitignore @@ -10,7 +10,4 @@ __generated__ # system .DS_Store -*.vscode - -examples/**/*/schema.prisma -examples/**/*/schema.graphql \ No newline at end of file +*.vscode \ No newline at end of file diff --git a/examples/usecase-todo/schema.graphql b/examples/usecase-todo/schema.graphql new file mode 100644 index 00000000000..ff520d54195 --- /dev/null +++ b/examples/usecase-todo/schema.graphql @@ -0,0 +1,366 @@ +# This file is automatically generated by Keystone, do not modify it manually. +# Modify your Keystone config when you want to change this. + +type Task { + id: ID! + label: String + priority: TaskPriorityType + isComplete: Boolean + assignedTo: Person + finishBy: DateTime +} + +enum TaskPriorityType { + low + medium + high +} + +scalar DateTime @specifiedBy(url: "https://datatracker.ietf.org/doc/html/rfc3339#section-5.6") + +input TaskWhereUniqueInput { + id: ID +} + +input TaskWhereInput { + AND: [TaskWhereInput!] + OR: [TaskWhereInput!] + NOT: [TaskWhereInput!] + id: IDFilter + label: StringFilter + priority: TaskPriorityTypeNullableFilter + isComplete: BooleanFilter + assignedTo: PersonWhereInput + finishBy: DateTimeNullableFilter +} + +input IDFilter { + equals: ID + in: [ID!] + notIn: [ID!] + lt: ID + lte: ID + gt: ID + gte: ID + not: IDFilter +} + +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 TaskPriorityTypeNullableFilter { + equals: TaskPriorityType + in: [TaskPriorityType!] + notIn: [TaskPriorityType!] + not: TaskPriorityTypeNullableFilter +} + +input BooleanFilter { + equals: Boolean + not: BooleanFilter +} + +input DateTimeNullableFilter { + equals: DateTime + in: [DateTime!] + notIn: [DateTime!] + lt: DateTime + lte: DateTime + gt: DateTime + gte: DateTime + not: DateTimeNullableFilter +} + +input TaskOrderByInput { + id: OrderDirection + label: OrderDirection + priority: OrderDirection + isComplete: OrderDirection + finishBy: OrderDirection +} + +enum OrderDirection { + asc + desc +} + +input TaskUpdateInput { + label: String + priority: TaskPriorityType + isComplete: Boolean + assignedTo: PersonRelateToOneForUpdateInput + finishBy: DateTime +} + +input PersonRelateToOneForUpdateInput { + create: PersonCreateInput + connect: PersonWhereUniqueInput + disconnect: Boolean +} + +input TaskUpdateArgs { + where: TaskWhereUniqueInput! + data: TaskUpdateInput! +} + +input TaskCreateInput { + label: String + priority: TaskPriorityType + isComplete: Boolean + assignedTo: PersonRelateToOneForCreateInput + finishBy: DateTime +} + +input PersonRelateToOneForCreateInput { + create: PersonCreateInput + connect: PersonWhereUniqueInput +} + +type Person { + id: ID! + name: String + tasks(where: TaskWhereInput! = {}, orderBy: [TaskOrderByInput!]! = [], take: Int, skip: Int! = 0, cursor: TaskWhereUniqueInput): [Task!] + tasksCount(where: TaskWhereInput! = {}): Int +} + +input PersonWhereUniqueInput { + id: ID + name: String +} + +input PersonWhereInput { + AND: [PersonWhereInput!] + OR: [PersonWhereInput!] + NOT: [PersonWhereInput!] + id: IDFilter + name: StringFilter + tasks: TaskManyRelationFilter +} + +input TaskManyRelationFilter { + every: TaskWhereInput + some: TaskWhereInput + none: TaskWhereInput +} + +input PersonOrderByInput { + id: OrderDirection + name: OrderDirection +} + +input PersonUpdateInput { + name: String + tasks: TaskRelateToManyForUpdateInput +} + +input TaskRelateToManyForUpdateInput { + disconnect: [TaskWhereUniqueInput!] + set: [TaskWhereUniqueInput!] + create: [TaskCreateInput!] + connect: [TaskWhereUniqueInput!] +} + +input PersonUpdateArgs { + where: PersonWhereUniqueInput! + data: PersonUpdateInput! +} + +input PersonCreateInput { + name: String + tasks: TaskRelateToManyForCreateInput +} + +input TaskRelateToManyForCreateInput { + create: [TaskCreateInput!] + connect: [TaskWhereUniqueInput!] +} + +""" +The `JSON` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). +""" +scalar JSON @specifiedBy(url: "http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf") + +type Mutation { + createTask(data: TaskCreateInput!): Task + createTasks(data: [TaskCreateInput!]!): [Task] + updateTask(where: TaskWhereUniqueInput!, data: TaskUpdateInput!): Task + updateTasks(data: [TaskUpdateArgs!]!): [Task] + deleteTask(where: TaskWhereUniqueInput!): Task + deleteTasks(where: [TaskWhereUniqueInput!]!): [Task] + createPerson(data: PersonCreateInput!): Person + createPeople(data: [PersonCreateInput!]!): [Person] + updatePerson(where: PersonWhereUniqueInput!, data: PersonUpdateInput!): Person + updatePeople(data: [PersonUpdateArgs!]!): [Person] + deletePerson(where: PersonWhereUniqueInput!): Person + deletePeople(where: [PersonWhereUniqueInput!]!): [Person] +} + +type Query { + task(where: TaskWhereUniqueInput!): Task + tasks(where: TaskWhereInput! = {}, orderBy: [TaskOrderByInput!]! = [], take: Int, skip: Int! = 0, cursor: TaskWhereUniqueInput): [Task!] + tasksCount(where: TaskWhereInput! = {}): Int + person(where: PersonWhereUniqueInput!): Person + people(where: PersonWhereInput! = {}, orderBy: [PersonOrderByInput!]! = [], take: Int, skip: Int! = 0, cursor: PersonWhereUniqueInput): [Person!] + peopleCount(where: PersonWhereInput! = {}): Int + keystone: KeystoneMeta! +} + +type KeystoneMeta { + adminMeta: KeystoneAdminMeta! +} + +type KeystoneAdminMeta { + lists: [KeystoneAdminUIListMeta!]! + list(key: String!): KeystoneAdminUIListMeta +} + +type KeystoneAdminUIListMeta { + key: String! + itemQueryName: String! + listQueryName: String! + hideCreate: Boolean! + hideDelete: Boolean! + path: String! + label: String! + singular: String! + plural: String! + description: String + initialColumns: [String!]! + pageSize: Int! + labelField: String! + fields: [KeystoneAdminUIFieldMeta!]! + groups: [KeystoneAdminUIFieldGroupMeta!]! + graphql: KeystoneAdminUIGraphQL! + initialSort: KeystoneAdminUISort + isHidden: Boolean! + isSingleton: Boolean! +} + +type KeystoneAdminUIFieldMeta { + path: String! + label: String! + description: String + isOrderable: Boolean! + isFilterable: Boolean! + isNonNull: [KeystoneAdminUIFieldMetaIsNonNull!] + fieldMeta: JSON + viewsIndex: Int! + customViewsIndex: Int + createView: KeystoneAdminUIFieldMetaCreateView! + listView: KeystoneAdminUIFieldMetaListView! + itemView(id: ID): KeystoneAdminUIFieldMetaItemView + search: QueryMode +} + +enum KeystoneAdminUIFieldMetaIsNonNull { + read + create + update +} + +type KeystoneAdminUIFieldMetaCreateView { + fieldMode: KeystoneAdminUIFieldMetaCreateViewFieldMode! +} + +enum KeystoneAdminUIFieldMetaCreateViewFieldMode { + edit + hidden +} + +type KeystoneAdminUIFieldMetaListView { + fieldMode: KeystoneAdminUIFieldMetaListViewFieldMode! +} + +enum KeystoneAdminUIFieldMetaListViewFieldMode { + read + hidden +} + +type KeystoneAdminUIFieldMetaItemView { + fieldMode: KeystoneAdminUIFieldMetaItemViewFieldMode + fieldPosition: KeystoneAdminUIFieldMetaItemViewFieldPosition +} + +enum KeystoneAdminUIFieldMetaItemViewFieldMode { + edit + read + hidden +} + +enum KeystoneAdminUIFieldMetaItemViewFieldPosition { + form + sidebar +} + +enum QueryMode { + default + insensitive +} + +type KeystoneAdminUIFieldGroupMeta { + label: String! + description: String + fields: [KeystoneAdminUIFieldMeta!]! +} + +type KeystoneAdminUIGraphQL { + names: KeystoneAdminUIGraphQLNames! +} + +type KeystoneAdminUIGraphQLNames { + outputTypeName: String! + whereInputName: String! + whereUniqueInputName: String! + createInputName: String! + createMutationName: String! + createManyMutationName: String! + relateToOneForCreateInputName: String! + relateToManyForCreateInputName: String! + itemQueryName: String! + listOrderName: String! + listQueryCountName: String! + listQueryName: String! + updateInputName: String! + updateMutationName: String! + updateManyInputName: String! + updateManyMutationName: String! + relateToOneForUpdateInputName: String! + relateToManyForUpdateInputName: String! + deleteMutationName: String! + deleteManyMutationName: String! +} + +type KeystoneAdminUISort { + field: String! + direction: KeystoneAdminUISortDirection! +} + +enum KeystoneAdminUISortDirection { + ASC + DESC +} diff --git a/examples/usecase-todo/schema.prisma b/examples/usecase-todo/schema.prisma new file mode 100644 index 00000000000..3d39c2e0c4e --- /dev/null +++ b/examples/usecase-todo/schema.prisma @@ -0,0 +1,31 @@ +// This file is automatically generated by Keystone, do not modify it manually. +// Modify your Keystone config when you want to change this. + +datasource sqlite { + url = env("DATABASE_URL") + shadowDatabaseUrl = env("SHADOW_DATABASE_URL") + provider = "sqlite" +} + +generator client { + provider = "prisma-client-js" + output = "node_modules/.myprisma/client" +} + +model Task { + id String @id @default(cuid()) + label String @default("") + priority String? + isComplete Boolean @default(false) + assignedTo Person? @relation("Task_assignedTo", fields: [assignedToId], references: [id]) + assignedToId String? @map("assignedTo") + finishBy DateTime? + + @@index([assignedToId]) +} + +model Person { + id String @id @default(cuid()) + name String @unique @default("") + tasks Task[] @relation("Task_assignedTo") +} From 4bc94f75861e88ff7535c0ee3610e5ad241a6967 Mon Sep 17 00:00:00 2001 From: Kennedy Baird Date: Tue, 20 Aug 2024 09:39:36 +1200 Subject: [PATCH 11/12] move away from root postinstall --- .github/workflows/tests_ci.yml | 10 ++++++++++ package.json | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests_ci.yml b/.github/workflows/tests_ci.yml index 9a3d129ab0a..b47d4a3c748 100644 --- a/.github/workflows/tests_ci.yml +++ b/.github/workflows/tests_ci.yml @@ -41,6 +41,16 @@ jobs: - name: Unit tests run: DATABASE_URL=file:./test.db pnpm jest --ci --testPathIgnorePatterns=admin-ui-tests --testPathIgnorePatterns=api-tests --testPathIgnorePatterns=examples-smoke-tests --testPathIgnorePatterns=examples/testing + examples_snapshot_tests: + name: Examples Snapshot Tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - uses: ./.github/actions/ci-setup-examples + + - name: Schema snapshot tests + run: pnpm run examples:snapshot-tests + graphql_api_tests_postgresql: name: API Tests PostgreSQL runs-on: ubuntu-latest diff --git a/package.json b/package.json index 8ab855abdd7..352c600d76c 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "test:admin-ui": "jest tests/admin-ui-tests", "build": "preconstruct build", "prepare": "preconstruct dev", - "postinstall": "pnpm -F './examples/**' run monorepo:example-fixed-build-test" + "examples:snapshot-tests": "pnpm -F './examples/**' run monorepo:example-fixed-build-test" }, "devDependencies": { "@babel/core": "^7.24.7", From 72ee18d5b3b55fe1fa57fa38d7dadfc0c29e4d16 Mon Sep 17 00:00:00 2001 From: Kennedy Baird Date: Tue, 20 Aug 2024 11:30:27 +1200 Subject: [PATCH 12/12] update readme to clarify new seed data approach --- examples/usecase-todo/README.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/examples/usecase-todo/README.md b/examples/usecase-todo/README.md index 3cbf1e9ab36..2ff9546341a 100644 --- a/examples/usecase-todo/README.md +++ b/examples/usecase-todo/README.md @@ -12,19 +12,20 @@ To run this project, clone the Keystone repository locally, run `pnpm install` a pnpm dev ``` -This will start Keystone’s Admin UI at [localhost:3000](http://localhost:3000), where you can add items to an empty database. +This will start Keystone’s Admin UI at [localhost:3000](http://localhost:3000), where you will see Keystone with minimal sample data. You can also access Keystone’s GraphQL Playground at [localhost:3000/api/graphql](http://localhost:3000/api/graphql) to explore the GraphQL API, and run [queries](https://keystonejs.com/docs/guides/filters) and [mutations](https://keystonejs.com/docs/graphql/overview#mutations) on your data. Congratulations, you’re now up and running with Keystone! 🚀 -### Optional: add sample data +### Sample data -This example includes sample data. To add it to your database: +This example includes sample data in `example.db` - deleting this file and restarting the dev server will leave you with an empty database. -1. Ensure you’ve initialised your project with `pnpm dev` at least once. -2. Run `pnpm seed-data`. This will populate your database with sample content. -3. Run `pnpm dev` again to startup Admin UI with sample data in place. +To re-seed the sample data: +1. Stop the server +2. Run `pnpm seed-data` +3. Restart the server with `pnpm dev` ## Try it out in CodeSandbox 🧪