-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
362 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
## Optimistic Locking | ||
|
||
This project implements a basic **Blog**, with `Posts` and `Authors`. | ||
|
||
Use it as a starting place for learning how to use Keystone. | ||
|
||
## Instructions | ||
|
||
To run this project, clone the Keystone repository locally, run `yarn` at the root of this repository, then navigate to this directory and run: | ||
|
||
```shell | ||
yarn dev | ||
``` | ||
|
||
This will start the Admin UI at [localhost:3000](http://localhost:3000). | ||
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. | ||
|
||
Congratulations, you're now up and running with Keystone! 🚀 | ||
|
||
### Optional: add sample data | ||
|
||
This example includes sample data. To add it to your database: | ||
|
||
1. Ensure you’ve initialised your project with `yarn dev` at least once. | ||
2. Run `yarn seed-data`. This will populate your database with sample content. | ||
3. Run `yarn dev` again to startup Admin UI with sample data in place. | ||
|
||
## Try it out in CodeSandbox 🧪 | ||
|
||
You can play with this example online in a web browser using the free [codesandbox.io](https://codesandbox.io/) service. To launch this example, open the URL <https://githubbox.com/keystonejs/keystone/tree/main/examples/blog>. You can also fork this sandbox to make your own changes. | ||
|
||
## Next steps | ||
|
||
Experiment with the code in this example to see how Keystone works, familiarise yourself with the Admin UI, and learn about the GraphQL Playground. | ||
|
||
When you’ve got the hang of this base project, try a [feature project](../) to learn Keystone’s advanced features and take your knowledge to the next level. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { config } from '@keystone-6/core'; | ||
import { lists } from './schema'; | ||
import { Context } from '.keystone/types'; | ||
|
||
async function seed (context: Context) { | ||
for (const data of [ | ||
{ | ||
title: 'The Adventures of Sherlock Holmes', | ||
content: | ||
'One night—it was on the 20th of March, 1888—I was returning from a journey to a patient (for I had now returned to civil practice), when my way led me through Baker-street. As I passed the well-remembered door, which must always be associated in my mind with my wooing, and with the dark incidents of the Study in Scarlet, I was seized with a keen desire to see Holmes again, and to know how he was employing his extraordinary powers. His rooms were brilliantly lit, and, even as I looked up, I saw his tall spare figure pass twice in a dark silhouette against the blind. He was pacing the room swiftly, eagerly, with his head sunk upon his chest and his hands clasped behind him. To me, who knew his every mood and habit, his attitude and manner told their own story. He was at work again. He had risen out of his drug-created dreams and was hot upon the scent of some new problem. I rang the bell, and was shown up to the chamber which had formerly been in part my own. ', | ||
version: 1 | ||
}, | ||
] as const) { | ||
await context.query.Post.createOne({ | ||
data | ||
}); | ||
} | ||
} | ||
|
||
export default config({ | ||
db: { | ||
provider: 'sqlite', | ||
url: process.env.DATABASE_URL || 'file:./keystone-example.db', | ||
async onConnect(context: Context) { | ||
if (process.argv.includes('--seed-data')) { | ||
await seed(context); | ||
} | ||
}, | ||
}, | ||
lists, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
{ | ||
"name": "@keystone-6/example-versioning", | ||
"version": "0.0.1", | ||
"private": true, | ||
"license": "MIT", | ||
"scripts": { | ||
"dev": "keystone dev", | ||
"start": "keystone start", | ||
"build": "keystone build", | ||
"seed-data": "keystone --seed-data" | ||
}, | ||
"dependencies": { | ||
"@keystone-6/core": "^2.0.0" | ||
}, | ||
"devDependencies": { | ||
"typescript": "^4.7.4" | ||
}, | ||
"engines": { | ||
"node": "^14.15 || ^16.13" | ||
}, | ||
"repository": "https://github.com/keystonejs/keystone/tree/main/examples/versioning" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"template": "node", | ||
"container": { | ||
"startScript": "keystone dev", | ||
"node": "14" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,219 @@ | ||
# This file is automatically generated by Keystone, do not modify it manually. | ||
# Modify your Keystone config when you want to change this. | ||
|
||
type Post { | ||
id: ID! | ||
title: String | ||
content: String | ||
version: Int | ||
} | ||
|
||
input PostWhereUniqueInput { | ||
id: ID | ||
} | ||
|
||
input PostWhereInput { | ||
AND: [PostWhereInput!] | ||
OR: [PostWhereInput!] | ||
NOT: [PostWhereInput!] | ||
id: IDFilter | ||
title: StringFilter | ||
content: StringFilter | ||
version: IntFilter | ||
} | ||
|
||
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 IntFilter { | ||
equals: Int | ||
in: [Int!] | ||
notIn: [Int!] | ||
lt: Int | ||
lte: Int | ||
gt: Int | ||
gte: Int | ||
not: IntFilter | ||
} | ||
|
||
input PostOrderByInput { | ||
id: OrderDirection | ||
title: OrderDirection | ||
content: OrderDirection | ||
version: OrderDirection | ||
} | ||
|
||
enum OrderDirection { | ||
asc | ||
desc | ||
} | ||
|
||
input PostUpdateInput { | ||
title: String | ||
content: String | ||
version: Int | ||
} | ||
|
||
input PostUpdateArgs { | ||
where: PostWhereUniqueInput! | ||
data: PostUpdateInput! | ||
} | ||
|
||
input PostCreateInput { | ||
title: String | ||
content: String | ||
version: Int | ||
} | ||
|
||
""" | ||
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 { | ||
createPost(data: PostCreateInput!): Post | ||
createPosts(data: [PostCreateInput!]!): [Post] | ||
updatePost(where: PostWhereUniqueInput!, data: PostUpdateInput!): Post | ||
updatePosts(data: [PostUpdateArgs!]!): [Post] | ||
deletePost(where: PostWhereUniqueInput!): Post | ||
deletePosts(where: [PostWhereUniqueInput!]!): [Post] | ||
} | ||
|
||
type Query { | ||
posts( | ||
where: PostWhereInput! = {} | ||
orderBy: [PostOrderByInput!]! = [] | ||
take: Int | ||
skip: Int! = 0 | ||
): [Post!] | ||
post(where: PostWhereUniqueInput!): Post | ||
postsCount(where: PostWhereInput! = {}): Int | ||
keystone: KeystoneMeta! | ||
} | ||
|
||
type KeystoneMeta { | ||
adminMeta: KeystoneAdminMeta! | ||
} | ||
|
||
type KeystoneAdminMeta { | ||
enableSignout: Boolean! | ||
enableSessionItem: Boolean! | ||
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!]! | ||
initialSort: KeystoneAdminUISort | ||
isHidden: Boolean! | ||
} | ||
|
||
type KeystoneAdminUIFieldMeta { | ||
path: String! | ||
label: String! | ||
description: String | ||
isOrderable: Boolean! | ||
isFilterable: Boolean! | ||
fieldMeta: JSON | ||
viewsIndex: Int! | ||
customViewsIndex: Int | ||
createView: KeystoneAdminUIFieldMetaCreateView! | ||
listView: KeystoneAdminUIFieldMetaListView! | ||
itemView(id: ID): KeystoneAdminUIFieldMetaItemView | ||
search: QueryMode | ||
} | ||
|
||
type KeystoneAdminUIFieldMetaCreateView { | ||
fieldMode: KeystoneAdminUIFieldMetaCreateViewFieldMode! | ||
} | ||
|
||
enum KeystoneAdminUIFieldMetaCreateViewFieldMode { | ||
edit | ||
hidden | ||
} | ||
|
||
type KeystoneAdminUIFieldMetaListView { | ||
fieldMode: KeystoneAdminUIFieldMetaListViewFieldMode! | ||
} | ||
|
||
enum KeystoneAdminUIFieldMetaListViewFieldMode { | ||
read | ||
hidden | ||
} | ||
|
||
type KeystoneAdminUIFieldMetaItemView { | ||
fieldMode: KeystoneAdminUIFieldMetaItemViewFieldMode | ||
} | ||
|
||
enum KeystoneAdminUIFieldMetaItemViewFieldMode { | ||
edit | ||
read | ||
hidden | ||
} | ||
|
||
enum QueryMode { | ||
default | ||
insensitive | ||
} | ||
|
||
type KeystoneAdminUISort { | ||
field: String! | ||
direction: KeystoneAdminUISortDirection! | ||
} | ||
|
||
enum KeystoneAdminUISortDirection { | ||
ASC | ||
DESC | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// 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/.prisma/client" | ||
} | ||
|
||
model Post { | ||
id String @id @default(cuid()) | ||
title String @default("") | ||
content String @default("") | ||
version Int @default(0) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { list } from '@keystone-6/core'; | ||
import { integer, text } from '@keystone-6/core/fields'; | ||
import { Lists } from '.keystone/types'; | ||
|
||
export const lists: Lists = { | ||
Post: list({ | ||
fields: { | ||
title: text({ validation: { isRequired: true } }), | ||
content: text(), | ||
version: integer({ | ||
defaultValue: 0, | ||
validation: { isRequired: true }, | ||
db: { isNullable: false }, | ||
hooks: { | ||
resolveInput: async ({ resolvedData, operation, item }) => { | ||
if (operation === 'create') return resolvedData.version; | ||
if (resolvedData.version !== item.version) throw new Error('Out of sync'); | ||
|
||
return item.version + 1; | ||
} | ||
}, | ||
}) | ||
}, | ||
}), | ||
}; |