diff --git a/docs/pages/docs/apis/access-control.mdx b/docs/pages/docs/apis/access-control.mdx index 5c35e8722cb..0eb868ae858 100644 --- a/docs/pages/docs/apis/access-control.mdx +++ b/docs/pages/docs/apis/access-control.mdx @@ -56,7 +56,7 @@ If access is **denied** due to any of the access control methods, the following Operation-level access control lets you control which operations can be accessed by a user based on the `session` and `context`. Individual functions can be provided for each of the operations. -?> Each operation type *defaults to public* unless configured. +?> Each operation type _defaults to public_ unless configured. !> These functions must return `true` if the operation is allowed, or `false` if it is not allowed. @@ -93,7 +93,7 @@ Filter-level access control lets you restrict which items can be operated on by In general, the filter access control functions will return GraphQL filters. They can also return boolean values `true` or `false` to match or exclude all items. -?> Each `filter` type *defaults to an empty filter*, unless configured. +?> Each `filter` type _defaults to an empty filter_, unless configured. ```typescript import { config, list } from '@keystone-6/core'; @@ -138,7 +138,7 @@ Individual functions can be provided for each of the operations, with each funct - the **input data** of the mutation (for `create` and `update` operations), and/or - the **existing item** in the database (for `update` and `delete` operations). -?> Each `item` access type *defaults to public* unless configured. +?> Each `item` access type _defaults to public_ unless configured. !> These functions must return `true` if the operation is allowed, or `false` if it is not allowed. diff --git a/docs/pages/docs/apis/config.mdx b/docs/pages/docs/apis/config.mdx index 0c9af3d2561..ad0b1b71a50 100644 --- a/docs/pages/docs/apis/config.mdx +++ b/docs/pages/docs/apis/config.mdx @@ -447,7 +447,7 @@ S3 options: - `pathPrefix`: The prefix for the file, used to set the subfolder of your bucket files will be stored in. - `endpoint`: The endpoint to use - if provided, this endpoint will be used instead of the default amazon s3 endpoint - `forcePathStyle`: Force the old pathstyle of using the bucket name after the host -- `signed.expiry`: Use S3 URL signing to keep S3 assets private. `expiry` is in seconds +- `signed.expiry`: Use S3 URL signing to keep S3 assets private. `expiry` is in seconds ```typescript import { config } from '@keystone-6/core'; diff --git a/docs/pages/releases/2022-06-30.mdx b/docs/pages/releases/2022-06-30.mdx index fe4aba3b383..64301bda07b 100644 --- a/docs/pages/releases/2022-06-30.mdx +++ b/docs/pages/releases/2022-06-30.mdx @@ -31,6 +31,7 @@ Keystone now supports MySQL by setting `mysql` in your `db.provider` [see pull r - Fixes the generation of an invalid Prisma schema when `{field}.isIndexed: true` and `{field}.db.map` are set - [#7666](https://github.com/keystonejs/keystone/pull/7666) Thanks [@TonnyORG](https://github.com/TonnyORG)! ## Acknowledgements + Big shoutout to the following community members for their help in improving our documentation with their contributions: - [#7665](https://github.com/keystonejs/keystone/pull/7665) - [@EvonuX](https://github.com/EvonuX) diff --git a/docs/pages/why-keystone.tsx b/docs/pages/why-keystone.tsx index 1e627e3c8c8..6c16705cfa3 100644 --- a/docs/pages/why-keystone.tsx +++ b/docs/pages/why-keystone.tsx @@ -608,7 +608,7 @@ export default function WhyKeystonePage() { diff --git a/examples-staging/README.md b/examples-staging/README.md deleted file mode 100644 index 83293f7f029..00000000000 --- a/examples-staging/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# Examples - Staging Area - -Hello, you have found the staging area for our examples. 👋 - -This is where we keep example projects which are still work-in-progress. -Feel free to take a look around, there might be something useful for you in here. -Be careful though, these projects might not be working right now, or they might not demonstrate best practices. - -If you want to see completed, tested, and documented examples, head on over to our curated [examples](../examples) directory. diff --git a/examples-staging/ecommerce/lib/formatMoney.ts b/examples-staging/ecommerce/lib/formatMoney.ts deleted file mode 100644 index 4d072161603..00000000000 --- a/examples-staging/ecommerce/lib/formatMoney.ts +++ /dev/null @@ -1,9 +0,0 @@ -const formatter = new Intl.NumberFormat('en-US', { - style: 'currency', - currency: 'USD', -}); - -export default function formatMoney(cents: number) { - const dollars = cents / 100; - return formatter.format(dollars); -} diff --git a/examples-staging/auth/CHANGELOG.md b/examples/auth/CHANGELOG.md similarity index 100% rename from examples-staging/auth/CHANGELOG.md rename to examples/auth/CHANGELOG.md diff --git a/examples-staging/auth/keystone.ts b/examples/auth/keystone.ts similarity index 100% rename from examples-staging/auth/keystone.ts rename to examples/auth/keystone.ts diff --git a/examples-staging/auth/package.json b/examples/auth/package.json similarity index 95% rename from examples-staging/auth/package.json rename to examples/auth/package.json index 2d506a92be4..4d240d1dbea 100644 --- a/examples-staging/auth/package.json +++ b/examples/auth/package.json @@ -21,5 +21,5 @@ "engines": { "node": "^14.15 || ^16.13" }, - "repository": "https://github.com/keystonejs/keystone/tree/main/examples-staging/auth" + "repository": "https://github.com/keystonejs/keystone/tree/main/examples/auth" } diff --git a/examples-staging/auth/sandbox.config.json b/examples/auth/sandbox.config.json similarity index 100% rename from examples-staging/auth/sandbox.config.json rename to examples/auth/sandbox.config.json diff --git a/examples-staging/auth/schema.graphql b/examples/auth/schema.graphql similarity index 100% rename from examples-staging/auth/schema.graphql rename to examples/auth/schema.graphql diff --git a/examples-staging/auth/schema.prisma b/examples/auth/schema.prisma similarity index 100% rename from examples-staging/auth/schema.prisma rename to examples/auth/schema.prisma diff --git a/examples-staging/auth/schema.ts b/examples/auth/schema.ts similarity index 100% rename from examples-staging/auth/schema.ts rename to examples/auth/schema.ts diff --git a/examples-staging/basic/.gitignore b/examples/basic/.gitignore similarity index 100% rename from examples-staging/basic/.gitignore rename to examples/basic/.gitignore diff --git a/examples-staging/basic/CHANGELOG.md b/examples/basic/CHANGELOG.md similarity index 100% rename from examples-staging/basic/CHANGELOG.md rename to examples/basic/CHANGELOG.md diff --git a/examples-staging/basic/admin/config.tsx b/examples/basic/admin/config.tsx similarity index 100% rename from examples-staging/basic/admin/config.tsx rename to examples/basic/admin/config.tsx diff --git a/examples-staging/basic/admin/fieldViews/Test.tsx b/examples/basic/admin/fieldViews/Test.tsx similarity index 100% rename from examples-staging/basic/admin/fieldViews/Test.tsx rename to examples/basic/admin/fieldViews/Test.tsx diff --git a/examples-staging/basic/admin/lists/posts.tsx b/examples/basic/admin/lists/posts.tsx similarity index 100% rename from examples-staging/basic/admin/lists/posts.tsx rename to examples/basic/admin/lists/posts.tsx diff --git a/examples-staging/basic/admin/pages/report.js b/examples/basic/admin/pages/report.js similarity index 100% rename from examples-staging/basic/admin/pages/report.js rename to examples/basic/admin/pages/report.js diff --git a/examples-staging/basic/keystone.ts b/examples/basic/keystone.ts similarity index 100% rename from examples-staging/basic/keystone.ts rename to examples/basic/keystone.ts diff --git a/examples-staging/basic/package.json b/examples/basic/package.json similarity index 97% rename from examples-staging/basic/package.json rename to examples/basic/package.json index 05c9271f373..2b043f27349 100644 --- a/examples-staging/basic/package.json +++ b/examples/basic/package.json @@ -32,5 +32,5 @@ "engines": { "node": "^14.15 || ^16.13" }, - "repository": "https://github.com/keystonejs/keystone/tree/main/examples-staging/basic" + "repository": "https://github.com/keystonejs/keystone/tree/main/examples/basic" } diff --git a/examples-staging/basic/sandbox.config.json b/examples/basic/sandbox.config.json similarity index 100% rename from examples-staging/basic/sandbox.config.json rename to examples/basic/sandbox.config.json diff --git a/examples-staging/basic/schema.graphql b/examples/basic/schema.graphql similarity index 100% rename from examples-staging/basic/schema.graphql rename to examples/basic/schema.graphql diff --git a/examples-staging/basic/schema.prisma b/examples/basic/schema.prisma similarity index 100% rename from examples-staging/basic/schema.prisma rename to examples/basic/schema.prisma diff --git a/examples-staging/basic/schema.ts b/examples/basic/schema.ts similarity index 100% rename from examples-staging/basic/schema.ts rename to examples/basic/schema.ts diff --git a/examples/blog/keystone.ts b/examples/blog/keystone.ts index c5cdbb11144..163766aaa97 100644 --- a/examples/blog/keystone.ts +++ b/examples/blog/keystone.ts @@ -1,12 +1,13 @@ import { config } from '@keystone-6/core'; import { lists } from './schema'; import { insertSeedData } from './seed-data'; +import { Context } from '.keystone/types'; export default config({ db: { provider: 'sqlite', url: process.env.DATABASE_URL || 'file:./keystone-example.db', - async onConnect(context) { + async onConnect(context: Context) { if (process.argv.includes('--seed-data')) { await insertSeedData(context); } diff --git a/examples/blog/seed-data/data.ts b/examples/blog/seed-data/data.ts index 1060fda1276..08789579431 100644 --- a/examples/blog/seed-data/data.ts +++ b/examples/blog/seed-data/data.ts @@ -74,4 +74,4 @@ export const posts = [ content: 'Dorothy lived in the midst of the great Kansas prairies, with Uncle Henry, who was a farmer, and Aunt Em, who was the farmer’s wife. Their house was small, for the lumber to build it had to be carried by wagon many miles. There were four walls, a floor and a roof, which made one room; and this room contained a rusty looking cookstove, a cupboard for the dishes, a table, three or four chairs, and the beds. Uncle Henry and Aunt Em had a big bed in one corner, and Dorothy a little bed in another corner. There was no garret at all, and no cellar—except a small hole dug in the ground, called a cyclone cellar, where the family could go in case one of those great whirlwinds arose, mighty enough to crush any building in its path. It was reached by a trap door in the middle of the floor, from which a ladder led down into the small, dark hole.', }, -]; +] as const; diff --git a/examples/blog/seed-data/index.ts b/examples/blog/seed-data/index.ts index 6d9b762b196..747ca56aa88 100644 --- a/examples/blog/seed-data/index.ts +++ b/examples/blog/seed-data/index.ts @@ -1,5 +1,5 @@ -import { KeystoneContext } from '@keystone-6/core/types'; import { authors, posts } from './data'; +import { Context } from '.keystone/types'; type AuthorProps = { name: string; @@ -8,13 +8,13 @@ type AuthorProps = { type PostProps = { title: string; - status: string; + status: 'draft' | 'published'; publishDate: string; - author: Object; + author: string; content: string; }; -export async function insertSeedData(context: KeystoneContext) { +export async function insertSeedData(context: Context) { console.log(`🌱 Inserting seed data`); const createAuthor = async (authorData: AuthorProps) => { @@ -37,9 +37,8 @@ export async function insertSeedData(context: KeystoneContext) { query: 'id', }); - postData.author = { connect: { id: authors[0].id } }; await context.query.Post.createOne({ - data: postData, + data: { ...postData, author: { connect: { id: authors[0].id } } }, query: 'id', }); }; diff --git a/examples/custom-session-validation/README.md b/examples/custom-session-validation/README.md index 074a869ab15..51a6e233270 100644 --- a/examples/custom-session-validation/README.md +++ b/examples/custom-session-validation/README.md @@ -137,4 +137,4 @@ export default myAuth( ## 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/custom-session-validation. You can also fork this sandbox to make your own changes. +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 . You can also fork this sandbox to make your own changes. diff --git a/examples/default-values/schema.ts b/examples/default-values/schema.ts index 69ebbff025b..854e2edec51 100644 --- a/examples/default-values/schema.ts +++ b/examples/default-values/schema.ts @@ -1,8 +1,9 @@ import { list } from '@keystone-6/core'; import { checkbox, relationship, text, timestamp } from '@keystone-6/core/fields'; import { select } from '@keystone-6/core/fields'; +import { Lists } from '.keystone/types'; -export const lists = { +export const lists: Lists = { Task: list({ fields: { label: text({ validation: { isRequired: true } }), diff --git a/examples-staging/ecommerce/CHANGELOG.md b/examples/ecommerce/CHANGELOG.md similarity index 100% rename from examples-staging/ecommerce/CHANGELOG.md rename to examples/ecommerce/CHANGELOG.md diff --git a/examples-staging/ecommerce/README.md b/examples/ecommerce/README.md similarity index 100% rename from examples-staging/ecommerce/README.md rename to examples/ecommerce/README.md diff --git a/examples-staging/ecommerce/access.ts b/examples/ecommerce/access.ts similarity index 100% rename from examples-staging/ecommerce/access.ts rename to examples/ecommerce/access.ts diff --git a/examples-staging/ecommerce/keystone.ts b/examples/ecommerce/keystone.ts similarity index 100% rename from examples-staging/ecommerce/keystone.ts rename to examples/ecommerce/keystone.ts diff --git a/examples-staging/ecommerce/lib/mail.ts b/examples/ecommerce/lib/mail.ts similarity index 100% rename from examples-staging/ecommerce/lib/mail.ts rename to examples/ecommerce/lib/mail.ts diff --git a/examples-staging/ecommerce/lib/stripe.ts b/examples/ecommerce/lib/stripe.ts similarity index 100% rename from examples-staging/ecommerce/lib/stripe.ts rename to examples/ecommerce/lib/stripe.ts diff --git a/examples-staging/ecommerce/mutations/addToCart.ts b/examples/ecommerce/mutations/addToCart.ts similarity index 93% rename from examples-staging/ecommerce/mutations/addToCart.ts rename to examples/ecommerce/mutations/addToCart.ts index a088ccaca8c..08756d4cf90 100644 --- a/examples-staging/ecommerce/mutations/addToCart.ts +++ b/examples/ecommerce/mutations/addToCart.ts @@ -1,10 +1,10 @@ -import { KeystoneContext } from '@keystone-6/core/types'; import { Session } from '../types'; +import { Context } from '.keystone/types'; async function addToCart( root: any, { productId }: { productId: string }, - context: KeystoneContext + context: Context ): Promise { console.log('ADDING TO CART!'); // 1. Query the current user see if they are signed in diff --git a/examples-staging/ecommerce/mutations/checkout.ts b/examples/ecommerce/mutations/checkout.ts similarity index 96% rename from examples-staging/ecommerce/mutations/checkout.ts rename to examples/ecommerce/mutations/checkout.ts index df0b103fceb..0e7b0819983 100644 --- a/examples-staging/ecommerce/mutations/checkout.ts +++ b/examples/ecommerce/mutations/checkout.ts @@ -1,4 +1,4 @@ -import { KeystoneContext } from '@keystone-6/core/types'; +import { Context } from '.keystone/types'; // import stripeConfig from '../lib/stripe'; @@ -8,7 +8,7 @@ interface Arguments { token: string; } -async function checkout(root: any, { token }: Arguments, context: KeystoneContext): Promise { +async function checkout(root: any, { token }: Arguments, context: Context): Promise { // 1. Make sure they are signed in const userId = context.session.itemId; if (!userId) { diff --git a/examples-staging/ecommerce/mutations/index.ts b/examples/ecommerce/mutations/index.ts similarity index 100% rename from examples-staging/ecommerce/mutations/index.ts rename to examples/ecommerce/mutations/index.ts diff --git a/examples-staging/ecommerce/package.json b/examples/ecommerce/package.json similarity index 97% rename from examples-staging/ecommerce/package.json rename to examples/ecommerce/package.json index 9fe9c6f3487..f682e7c0ee4 100644 --- a/examples-staging/ecommerce/package.json +++ b/examples/ecommerce/package.json @@ -33,5 +33,5 @@ "engines": { "node": "^14.15 || ^16.13" }, - "repository": "https://github.com/keystonejs/keystone/tree/main/examples-staging/ecommerce" + "repository": "https://github.com/keystonejs/keystone/tree/main/examples/ecommerce" } diff --git a/examples-staging/ecommerce/sample.env b/examples/ecommerce/sample.env similarity index 100% rename from examples-staging/ecommerce/sample.env rename to examples/ecommerce/sample.env diff --git a/examples-staging/ecommerce/sandbox.config.json b/examples/ecommerce/sandbox.config.json similarity index 100% rename from examples-staging/ecommerce/sandbox.config.json rename to examples/ecommerce/sandbox.config.json diff --git a/examples-staging/ecommerce/schema.graphql b/examples/ecommerce/schema.graphql similarity index 100% rename from examples-staging/ecommerce/schema.graphql rename to examples/ecommerce/schema.graphql diff --git a/examples-staging/ecommerce/schema.prisma b/examples/ecommerce/schema.prisma similarity index 100% rename from examples-staging/ecommerce/schema.prisma rename to examples/ecommerce/schema.prisma diff --git a/examples-staging/ecommerce/schemas/CartItem.ts b/examples/ecommerce/schemas/CartItem.ts similarity index 100% rename from examples-staging/ecommerce/schemas/CartItem.ts rename to examples/ecommerce/schemas/CartItem.ts diff --git a/examples-staging/ecommerce/schemas/Order.ts b/examples/ecommerce/schemas/Order.ts similarity index 59% rename from examples-staging/ecommerce/schemas/Order.ts rename to examples/ecommerce/schemas/Order.ts index 05b9c0e323e..8f5f3d96d83 100644 --- a/examples-staging/ecommerce/schemas/Order.ts +++ b/examples/ecommerce/schemas/Order.ts @@ -1,9 +1,21 @@ import { integer, text, relationship, virtual } from '@keystone-6/core/fields'; import { list, graphql } from '@keystone-6/core'; import { isSignedIn, rules } from '../access'; -import formatMoney from '../lib/formatMoney'; +import { Lists } from '.keystone/types'; -export const Order = list({ +const formatter = new Intl.NumberFormat('en-US', { + style: 'currency', + currency: 'USD', +}); + +export default function formatMoney(cents: number | null) { + if (cents === null) return 'Unset'; + const dollars = cents / 100; + return formatter.format(dollars); +} + +// we add the type here, so `item` below is typed +export const Order: Lists.Order = list({ access: { operation: { create: isSignedIn, @@ -17,7 +29,7 @@ export const Order = list({ field: graphql.field({ type: graphql.String, resolve(item) { - return `${formatMoney((item as any).total)}`; + return formatMoney(item.total); }, }), }), diff --git a/examples-staging/ecommerce/schemas/OrderItem.ts b/examples/ecommerce/schemas/OrderItem.ts similarity index 100% rename from examples-staging/ecommerce/schemas/OrderItem.ts rename to examples/ecommerce/schemas/OrderItem.ts diff --git a/examples-staging/ecommerce/schemas/Product.ts b/examples/ecommerce/schemas/Product.ts similarity index 100% rename from examples-staging/ecommerce/schemas/Product.ts rename to examples/ecommerce/schemas/Product.ts diff --git a/examples-staging/ecommerce/schemas/ProductImage.ts b/examples/ecommerce/schemas/ProductImage.ts similarity index 100% rename from examples-staging/ecommerce/schemas/ProductImage.ts rename to examples/ecommerce/schemas/ProductImage.ts diff --git a/examples-staging/ecommerce/schemas/Role.ts b/examples/ecommerce/schemas/Role.ts similarity index 100% rename from examples-staging/ecommerce/schemas/Role.ts rename to examples/ecommerce/schemas/Role.ts diff --git a/examples-staging/ecommerce/schemas/User.ts b/examples/ecommerce/schemas/User.ts similarity index 100% rename from examples-staging/ecommerce/schemas/User.ts rename to examples/ecommerce/schemas/User.ts diff --git a/examples-staging/ecommerce/schemas/fields.ts b/examples/ecommerce/schemas/fields.ts similarity index 100% rename from examples-staging/ecommerce/schemas/fields.ts rename to examples/ecommerce/schemas/fields.ts diff --git a/examples-staging/ecommerce/seed-data/data.ts b/examples/ecommerce/seed-data/data.ts similarity index 100% rename from examples-staging/ecommerce/seed-data/data.ts rename to examples/ecommerce/seed-data/data.ts diff --git a/examples-staging/ecommerce/seed-data/index.ts b/examples/ecommerce/seed-data/index.ts similarity index 100% rename from examples-staging/ecommerce/seed-data/index.ts rename to examples/ecommerce/seed-data/index.ts diff --git a/examples-staging/ecommerce/tests/mutations.test.ts b/examples/ecommerce/tests/mutations.test.ts similarity index 98% rename from examples-staging/ecommerce/tests/mutations.test.ts rename to examples/ecommerce/tests/mutations.test.ts index 708fa9f9b51..12758703d8c 100644 --- a/examples-staging/ecommerce/tests/mutations.test.ts +++ b/examples/ecommerce/tests/mutations.test.ts @@ -1,13 +1,11 @@ -import { KeystoneContext } from '@keystone-6/core/types'; import { setupTestRunner } from '@keystone-6/core/testing'; import config from '../keystone'; +import { Context } from '.keystone/types'; const FAKE_ID = 'cinjfgbkjnfg'; -const asUser = (context: KeystoneContext, itemId?: string) => - context.withSession({ itemId, data: {} }); - -const runner = setupTestRunner({ config }); +const asUser = (context: Context, itemId?: string) => context.withSession({ itemId, data: {} }); +const runner = setupTestRunner({ config }); describe(`Custom mutations`, () => { describe('checkout(token)', () => { diff --git a/examples-staging/ecommerce/types.ts b/examples/ecommerce/types.ts similarity index 100% rename from examples-staging/ecommerce/types.ts rename to examples/ecommerce/types.ts diff --git a/examples-staging/embedded-nextjs/CHANGELOG.md b/examples/embedded-nextjs/CHANGELOG.md similarity index 100% rename from examples-staging/embedded-nextjs/CHANGELOG.md rename to examples/embedded-nextjs/CHANGELOG.md diff --git a/examples-staging/embedded-nextjs/keystone.ts b/examples/embedded-nextjs/keystone.ts similarity index 100% rename from examples-staging/embedded-nextjs/keystone.ts rename to examples/embedded-nextjs/keystone.ts diff --git a/examples-staging/embedded-nextjs/next-env.d.ts b/examples/embedded-nextjs/next-env.d.ts similarity index 100% rename from examples-staging/embedded-nextjs/next-env.d.ts rename to examples/embedded-nextjs/next-env.d.ts diff --git a/examples-staging/embedded-nextjs/next.config.js b/examples/embedded-nextjs/next.config.js similarity index 100% rename from examples-staging/embedded-nextjs/next.config.js rename to examples/embedded-nextjs/next.config.js diff --git a/examples-staging/embedded-nextjs/package.json b/examples/embedded-nextjs/package.json similarity index 93% rename from examples-staging/embedded-nextjs/package.json rename to examples/embedded-nextjs/package.json index 1f0ac19f743..6d8bc945a7d 100644 --- a/examples-staging/embedded-nextjs/package.json +++ b/examples/embedded-nextjs/package.json @@ -21,5 +21,5 @@ "engines": { "node": "^14.15 || ^16.13" }, - "repository": "https://github.com/keystonejs/keystone/tree/main/examples-staging/embedded-nextjs" + "repository": "https://github.com/keystonejs/keystone/tree/main/examples/embedded-nextjs" } diff --git a/examples-staging/embedded-nextjs/pages/api/graphql.js b/examples/embedded-nextjs/pages/api/graphql.js similarity index 100% rename from examples-staging/embedded-nextjs/pages/api/graphql.js rename to examples/embedded-nextjs/pages/api/graphql.js diff --git a/examples-staging/embedded-nextjs/pages/index.js b/examples/embedded-nextjs/pages/index.js similarity index 100% rename from examples-staging/embedded-nextjs/pages/index.js rename to examples/embedded-nextjs/pages/index.js diff --git a/examples-staging/embedded-nextjs/pages/post/[slug].js b/examples/embedded-nextjs/pages/post/[slug].js similarity index 100% rename from examples-staging/embedded-nextjs/pages/post/[slug].js rename to examples/embedded-nextjs/pages/post/[slug].js diff --git a/examples-staging/embedded-nextjs/sandbox.config.json b/examples/embedded-nextjs/sandbox.config.json similarity index 100% rename from examples-staging/embedded-nextjs/sandbox.config.json rename to examples/embedded-nextjs/sandbox.config.json diff --git a/examples-staging/embedded-nextjs/schema.graphql b/examples/embedded-nextjs/schema.graphql similarity index 100% rename from examples-staging/embedded-nextjs/schema.graphql rename to examples/embedded-nextjs/schema.graphql diff --git a/examples-staging/embedded-nextjs/schema.prisma b/examples/embedded-nextjs/schema.prisma similarity index 100% rename from examples-staging/embedded-nextjs/schema.prisma rename to examples/embedded-nextjs/schema.prisma diff --git a/examples-staging/embedded-nextjs/schema.ts b/examples/embedded-nextjs/schema.ts similarity index 100% rename from examples-staging/embedded-nextjs/schema.ts rename to examples/embedded-nextjs/schema.ts diff --git a/examples-staging/embedded-nextjs/tsconfig.json b/examples/embedded-nextjs/tsconfig.json similarity index 100% rename from examples-staging/embedded-nextjs/tsconfig.json rename to examples/embedded-nextjs/tsconfig.json diff --git a/examples/extend-graphql-schema-graphql-ts/custom-schema.ts b/examples/extend-graphql-schema-graphql-ts/custom-schema.ts index f9932fb0d9e..8e9557c9ed3 100644 --- a/examples/extend-graphql-schema-graphql-ts/custom-schema.ts +++ b/examples/extend-graphql-schema-graphql-ts/custom-schema.ts @@ -1,4 +1,5 @@ import { graphql } from '@keystone-6/core'; +import { Context } from '.keystone/types'; export const extendGraphqlSchema = graphql.extend(base => { const Statistics = graphql.object<{ authorId: string }>()({ @@ -6,7 +7,8 @@ export const extendGraphqlSchema = graphql.extend(base => { fields: { draft: graphql.field({ type: graphql.Int, - resolve({ authorId }, args, context) { + resolve({ authorId }, args, _context) { + const context = _context as Context; return context.query.Post.count({ where: { author: { id: { equals: authorId } }, status: { equals: 'draft' } }, }); @@ -14,7 +16,8 @@ export const extendGraphqlSchema = graphql.extend(base => { }), published: graphql.field({ type: graphql.Int, - resolve({ authorId }, args, context) { + resolve({ authorId }, args, _context) { + const context = _context as Context; return context.query.Post.count({ where: { author: { id: { equals: authorId } }, status: { equals: 'published' } }, }); @@ -22,7 +25,8 @@ export const extendGraphqlSchema = graphql.extend(base => { }), latest: graphql.field({ type: base.object('Post'), - async resolve({ authorId }, args, context) { + async resolve({ authorId }, args, _context) { + const context = _context as Context; const [post] = await context.db.Post.findMany({ take: 1, orderBy: { publishDate: 'desc' }, @@ -40,7 +44,8 @@ export const extendGraphqlSchema = graphql.extend(base => { // with the name provided or throw if it doesn't exist type: base.object('Post'), args: { id: graphql.arg({ type: graphql.nonNull(graphql.ID) }) }, - resolve(source, { id }, context) { + resolve(source, { id }, _context) { + const context = _context as Context; // Note we use `context.db.Post` here as we have a return type // of Post, and this API provides results in the correct format. // If you accidentally use `context.query.Post` here you can expect problems @@ -59,7 +64,8 @@ export const extendGraphqlSchema = graphql.extend(base => { id: graphql.arg({ type: graphql.nonNull(graphql.ID) }), days: graphql.arg({ type: graphql.nonNull(graphql.Int), defaultValue: 7 }), }, - resolve(source, { id, days }, context) { + resolve(source, { id, days }, _context) { + const context = _context as Context; // Create a date string in the past from now() const cutoff = new Date( new Date().setUTCDate(new Date().getUTCDate() - days) diff --git a/examples/extend-graphql-schema-nexus/nexus/index.ts b/examples/extend-graphql-schema-nexus/nexus/index.ts index a7cd045967d..ed551e59c02 100644 --- a/examples/extend-graphql-schema-nexus/nexus/index.ts +++ b/examples/extend-graphql-schema-nexus/nexus/index.ts @@ -15,6 +15,6 @@ export const nexusSchema = makeSchema({ // Keystone `db` and `query` args, as well as the prisma client contextType: { module: path.join(process.cwd(), 'node_modules', '.keystone', 'types.d.ts'), - export: 'KeystoneContext', + export: 'Context', }, }); diff --git a/examples-staging/graphql-api-endpoint/CHANGELOG.md b/examples/graphql-api-endpoint/CHANGELOG.md similarity index 100% rename from examples-staging/graphql-api-endpoint/CHANGELOG.md rename to examples/graphql-api-endpoint/CHANGELOG.md diff --git a/examples-staging/graphql-api-endpoint/keystone.ts b/examples/graphql-api-endpoint/keystone.ts similarity index 100% rename from examples-staging/graphql-api-endpoint/keystone.ts rename to examples/graphql-api-endpoint/keystone.ts diff --git a/examples-staging/graphql-api-endpoint/package.json b/examples/graphql-api-endpoint/package.json similarity index 92% rename from examples-staging/graphql-api-endpoint/package.json rename to examples/graphql-api-endpoint/package.json index ff1eae4daf4..36527cbaccc 100644 --- a/examples-staging/graphql-api-endpoint/package.json +++ b/examples/graphql-api-endpoint/package.json @@ -16,5 +16,5 @@ "@keystone-6/core": "^2.1.0", "@keystone-6/fields-document": "^4.0.0" }, - "repository": "https://github.com/keystonejs/keystone/tree/main/examples-staging/graphql-api-endpoint" + "repository": "https://github.com/keystonejs/keystone/tree/main/examples/graphql-api-endpoint" } diff --git a/examples-staging/graphql-api-endpoint/sandbox.config.json b/examples/graphql-api-endpoint/sandbox.config.json similarity index 100% rename from examples-staging/graphql-api-endpoint/sandbox.config.json rename to examples/graphql-api-endpoint/sandbox.config.json diff --git a/examples-staging/graphql-api-endpoint/schema.graphql b/examples/graphql-api-endpoint/schema.graphql similarity index 100% rename from examples-staging/graphql-api-endpoint/schema.graphql rename to examples/graphql-api-endpoint/schema.graphql diff --git a/examples-staging/graphql-api-endpoint/schema.prisma b/examples/graphql-api-endpoint/schema.prisma similarity index 100% rename from examples-staging/graphql-api-endpoint/schema.prisma rename to examples/graphql-api-endpoint/schema.prisma diff --git a/examples-staging/graphql-api-endpoint/schema.ts b/examples/graphql-api-endpoint/schema.ts similarity index 100% rename from examples-staging/graphql-api-endpoint/schema.ts rename to examples/graphql-api-endpoint/schema.ts diff --git a/examples/rest-api/keystone.ts b/examples/rest-api/keystone.ts index 07c1fe7a1b8..b317c45d539 100644 --- a/examples/rest-api/keystone.ts +++ b/examples/rest-api/keystone.ts @@ -2,6 +2,7 @@ import { config } from '@keystone-6/core'; import { lists } from './schema'; import { insertSeedData } from './seed-data'; import { getTasks } from './routes/tasks'; +import { Context } from '.keystone/types'; /* A quick note on types: normally if you're adding custom properties to your @@ -14,7 +15,7 @@ export default config({ db: { provider: 'sqlite', url: process.env.DATABASE_URL || 'file:./keystone-example.db', - async onConnect(context) { + async onConnect(context: Context) { if (process.argv.includes('--seed-data')) { await insertSeedData(context); } @@ -35,6 +36,7 @@ export default config({ (req as any).context = await createContext(req, res); next(); }); + app.get('/rest/tasks', getTasks); }, }, diff --git a/examples/rest-api/routes/tasks.ts b/examples/rest-api/routes/tasks.ts index 08e5cf335de..d800f2e445f 100644 --- a/examples/rest-api/routes/tasks.ts +++ b/examples/rest-api/routes/tasks.ts @@ -1,5 +1,5 @@ import type { Request, Response } from 'express'; -import type { KeystoneContext } from '@keystone-6/core/types'; +import type { Context } from '.keystone/types'; /* This example route handler gets all the tasks in the database and returns @@ -13,7 +13,8 @@ import type { KeystoneContext } from '@keystone-6/core/types'; export async function getTasks(req: Request, res: Response) { // This was added by the context middleware in ../keystone.ts - const context = (req as any).context as KeystoneContext; + const { context } = req as typeof req & { context: Context }; + // Let's map the `complete` query param to a where filter let isComplete; if (req.query.complete === 'true') { diff --git a/examples/rest-api/seed-data/index.ts b/examples/rest-api/seed-data/index.ts index 739054f9550..a36b032f4fc 100644 --- a/examples/rest-api/seed-data/index.ts +++ b/examples/rest-api/seed-data/index.ts @@ -1,5 +1,5 @@ -import { KeystoneContext } from '@keystone-6/core/types'; import { persons, tasks } from './data'; +import { Context } from '.keystone/types'; type PersonProps = { name: string; @@ -7,13 +7,12 @@ type PersonProps = { type TaskProps = { label: string; - isComplete: Boolean; + isComplete: boolean; finishBy: string; - assignedTo: Object; - person?: Object; + assignedTo: string; }; -export async function insertSeedData(context: KeystoneContext) { +export async function insertSeedData(context: Context) { console.log(`🌱 Inserting seed data`); const createPerson = async (personData: PersonProps) => { @@ -23,7 +22,7 @@ export async function insertSeedData(context: KeystoneContext) { }); if (!person) { - await context.query.Person.createOne({ + person = await context.query.Person.createOne({ data: personData, query: 'id', }); @@ -36,9 +35,8 @@ export async function insertSeedData(context: KeystoneContext) { query: 'id', }); - taskData.assignedTo = { connect: { id: persons[0].id } }; await context.query.Task.createOne({ - data: taskData, + data: { ...taskData, assignedTo: { connect: { id: persons[0].id } } }, query: 'id', }); }; diff --git a/examples-staging/roles/CHANGELOG.md b/examples/roles/CHANGELOG.md similarity index 100% rename from examples-staging/roles/CHANGELOG.md rename to examples/roles/CHANGELOG.md diff --git a/examples-staging/roles/README.md b/examples/roles/README.md similarity index 100% rename from examples-staging/roles/README.md rename to examples/roles/README.md diff --git a/examples-staging/roles/access.ts b/examples/roles/access.ts similarity index 100% rename from examples-staging/roles/access.ts rename to examples/roles/access.ts diff --git a/examples-staging/roles/keystone.ts b/examples/roles/keystone.ts similarity index 100% rename from examples-staging/roles/keystone.ts rename to examples/roles/keystone.ts diff --git a/examples-staging/roles/package.json b/examples/roles/package.json similarity index 95% rename from examples-staging/roles/package.json rename to examples/roles/package.json index fb38c6b0e1c..40e2198ac58 100644 --- a/examples-staging/roles/package.json +++ b/examples/roles/package.json @@ -21,5 +21,5 @@ "engines": { "node": "^14.15 || ^16.13" }, - "repository": "https://github.com/keystonejs/keystone/tree/main/examples-staging/roles" + "repository": "https://github.com/keystonejs/keystone/tree/main/examples/roles" } diff --git a/examples-staging/roles/sandbox.config.json b/examples/roles/sandbox.config.json similarity index 100% rename from examples-staging/roles/sandbox.config.json rename to examples/roles/sandbox.config.json diff --git a/examples-staging/roles/schema.graphql b/examples/roles/schema.graphql similarity index 100% rename from examples-staging/roles/schema.graphql rename to examples/roles/schema.graphql diff --git a/examples-staging/roles/schema.prisma b/examples/roles/schema.prisma similarity index 100% rename from examples-staging/roles/schema.prisma rename to examples/roles/schema.prisma diff --git a/examples-staging/roles/schema.ts b/examples/roles/schema.ts similarity index 100% rename from examples-staging/roles/schema.ts rename to examples/roles/schema.ts diff --git a/examples-staging/roles/types.ts b/examples/roles/types.ts similarity index 100% rename from examples-staging/roles/types.ts rename to examples/roles/types.ts diff --git a/examples/task-manager/keystone.ts b/examples/task-manager/keystone.ts index c5cdbb11144..163766aaa97 100644 --- a/examples/task-manager/keystone.ts +++ b/examples/task-manager/keystone.ts @@ -1,12 +1,13 @@ import { config } from '@keystone-6/core'; import { lists } from './schema'; import { insertSeedData } from './seed-data'; +import { Context } from '.keystone/types'; export default config({ db: { provider: 'sqlite', url: process.env.DATABASE_URL || 'file:./keystone-example.db', - async onConnect(context) { + async onConnect(context: Context) { if (process.argv.includes('--seed-data')) { await insertSeedData(context); } diff --git a/examples/task-manager/seed-data/index.ts b/examples/task-manager/seed-data/index.ts index af044f2d447..a36b032f4fc 100644 --- a/examples/task-manager/seed-data/index.ts +++ b/examples/task-manager/seed-data/index.ts @@ -1,5 +1,5 @@ -import { KeystoneContext } from '@keystone-6/core/types'; import { persons, tasks } from './data'; +import { Context } from '.keystone/types'; type PersonProps = { name: string; @@ -7,13 +7,12 @@ type PersonProps = { type TaskProps = { label: string; - isComplete: Boolean; + isComplete: boolean; finishBy: string; - assignedTo: Object; - person?: Object; + assignedTo: string; }; -export async function insertSeedData(context: KeystoneContext) { +export async function insertSeedData(context: Context) { console.log(`🌱 Inserting seed data`); const createPerson = async (personData: PersonProps) => { @@ -36,10 +35,8 @@ export async function insertSeedData(context: KeystoneContext) { query: 'id', }); - taskData.assignedTo = { connect: { id: persons[0].id } }; - await context.query.Task.createOne({ - data: taskData, + data: { ...taskData, assignedTo: { connect: { id: persons[0].id } } }, query: 'id', }); }; diff --git a/examples/testing/example.test.ts b/examples/testing/example.test.ts index 6ff829e49a6..0d056d13ac8 100644 --- a/examples/testing/example.test.ts +++ b/examples/testing/example.test.ts @@ -1,10 +1,10 @@ -import { KeystoneContext } from '@keystone-6/core/types'; import { setupTestEnv, setupTestRunner, TestEnv } from '@keystone-6/core/testing'; import config from './keystone'; +import { Context } from '.keystone/types'; // Setup a test runner which will provide a clean test environment // with access to our GraphQL API for each test. -const runner = setupTestRunner({ config }); +const runner = setupTestRunner({ config }); describe('Example tests using test runner', () => { test( @@ -163,10 +163,10 @@ describe('Example tests using test environment', () => { // // This gives us the opportunity to seed test data once up front and use it in // multiple tests. - let testEnv: TestEnv, context: KeystoneContext; + let testEnv: TestEnv, context: Context; let person: { id: string }; beforeAll(async () => { - testEnv = await setupTestEnv({ config }); + testEnv = await setupTestEnv({ config }); context = testEnv.testArgs.context; await testEnv.connect(); diff --git a/examples/testing/schema.ts b/examples/testing/schema.ts index 057af90ee76..12e8aae72ca 100644 --- a/examples/testing/schema.ts +++ b/examples/testing/schema.ts @@ -1,8 +1,9 @@ import { list } from '@keystone-6/core'; import { checkbox, password, relationship, text, timestamp } from '@keystone-6/core/fields'; import { select } from '@keystone-6/core/fields'; +import { Lists } from '.keystone/types'; -export const lists = { +export const lists: Lists = { Task: list({ fields: { label: text({ validation: { isRequired: true } }), diff --git a/examples/virtual-field/schema.ts b/examples/virtual-field/schema.ts index 4ecb210bb58..23391e07173 100644 --- a/examples/virtual-field/schema.ts +++ b/examples/virtual-field/schema.ts @@ -1,6 +1,6 @@ import { list, graphql } from '@keystone-6/core'; import { select, relationship, text, timestamp, virtual } from '@keystone-6/core/fields'; -import { Lists } from '.keystone/types'; +import { Lists, Context } from '.keystone/types'; export const lists: Lists = { Post: list({ @@ -63,7 +63,7 @@ export const lists: Lists = { if (!item.content) { return null; } - const content = item.content as string; + const content = item.content; if (content.length <= length) { return content; } else { @@ -79,7 +79,8 @@ export const lists: Lists = { authorName: virtual({ field: graphql.field({ type: graphql.String, - async resolve(item, args, context) { + async resolve(item, args, _context) { + const context = _context as Context; const { author } = await context.query.Post.findOne({ where: { id: item.id.toString() }, query: 'author { name }', @@ -100,7 +101,8 @@ export const lists: Lists = { field: lists => graphql.field({ type: lists.Post.types.output, - async resolve(item, args, context) { + async resolve(item, args, _context) { + const context = _context as Context; const { posts } = await context.query.Author.findOne({ where: { id: item.id.toString() }, query: `posts( diff --git a/package.json b/package.json index 5d864158473..7faf5a44cc2 100644 --- a/package.json +++ b/package.json @@ -112,7 +112,6 @@ "design-system/packages/*", "design-system/website", "docs", - "examples-staging/*", "examples/*", "packages/*", "tests/admin-ui-tests", diff --git a/packages/core/src/testing.ts b/packages/core/src/testing.ts index f0484fdf771..407b627b997 100644 --- a/packages/core/src/testing.ts +++ b/packages/core/src/testing.ts @@ -21,28 +21,28 @@ export type GraphQLRequest = (arg: { operationName?: string; }) => Test; -export type TestArgs = { - context: KeystoneContext; +export type TestArgs = { + context: Context; graphQLRequest: GraphQLRequest; app: express.Express; server: Server; }; -export type TestEnv = { +export type TestEnv = { connect: () => Promise; disconnect: () => Promise; - testArgs: TestArgs; + testArgs: TestArgs; }; const _hashPrismaSchema = memoizeOne(prismaSchema => crypto.createHash('md5').update(prismaSchema).digest('hex') ); const _alreadyGeneratedProjects = new Set(); -export async function setupTestEnv({ +export async function setupTestEnv({ config: _config, }: { config: KeystoneConfig; -}): Promise { +}): Promise> { // Force the UI to always be disabled. const config = initConfig({ ..._config, ui: { ..._config.ui, isDisabled: true } }); const { graphQLSchema, getKeystone } = createSystem(config); @@ -85,15 +85,32 @@ export async function setupTestEnv({ disconnect: async () => { await Promise.all([disconnect(), apolloServer.stop()]); }, - testArgs: { context: createContext(), graphQLRequest, app, server }, + testArgs: { + context: createContext() as Context, + graphQLRequest, + app, + server, + }, }; } -export function setupTestRunner({ config }: { config: KeystoneConfig }) { +export function setupTestRunner({ + config, +}: { + config: KeystoneConfig; +}) { + type TestArgs = { + context: Context; + graphQLRequest: GraphQLRequest; + app: express.Express; + server: Server; + }; + return (testFn: (testArgs: TestArgs) => Promise) => async () => { // Reset the database to be empty for every test. - const { connect, disconnect, testArgs } = await setupTestEnv({ config }); + const { connect, disconnect, testArgs } = await setupTestEnv({ config }); await connect(); + try { return await testFn(testArgs); } finally { diff --git a/scripts/generate-artifacts-for-projects/src/index.ts b/scripts/generate-artifacts-for-projects/src/index.ts index 8a8a2d69f04..da9b055df67 100644 --- a/scripts/generate-artifacts-for-projects/src/index.ts +++ b/scripts/generate-artifacts-for-projects/src/index.ts @@ -33,7 +33,6 @@ async function main() { const repoRoot = path.resolve(__dirname, '../../../'); const directoriesOfProjects = [ path.join(repoRoot, 'examples'), - path.join(repoRoot, 'examples-staging'), path.join(repoRoot, 'tests/test-projects'), ]; const projectDirectories = ( diff --git a/tests/examples-smoke-tests/auth.test.ts b/tests/examples-smoke-tests/auth.test.ts index d2fbbd77e3f..fcb4b952027 100644 --- a/tests/examples-smoke-tests/auth.test.ts +++ b/tests/examples-smoke-tests/auth.test.ts @@ -2,7 +2,7 @@ import fetch from 'node-fetch'; import { Browser, Page } from 'playwright'; import { exampleProjectTests, initFirstItemTest, loadIndex } from './utils'; -exampleProjectTests('../examples-staging/auth', browserType => { +exampleProjectTests('../examples/auth', browserType => { let browser: Browser = undefined as any; let page: Page = undefined as any; beforeAll(async () => { diff --git a/tests/examples-smoke-tests/basic.test.ts b/tests/examples-smoke-tests/basic.test.ts index 0a972f05933..92d73f6a8d5 100644 --- a/tests/examples-smoke-tests/basic.test.ts +++ b/tests/examples-smoke-tests/basic.test.ts @@ -2,7 +2,7 @@ import { Browser, Page } from 'playwright'; import fetch from 'node-fetch'; import { exampleProjectTests, initFirstItemTest, loadIndex } from './utils'; -exampleProjectTests('../examples-staging/basic', (browserType, mode) => { +exampleProjectTests('../examples/basic', (browserType, mode) => { let browser: Browser = undefined as any; let page: Page = undefined as any; beforeAll(async () => { diff --git a/tests/examples-smoke-tests/roles.test.ts b/tests/examples-smoke-tests/roles.test.ts index f6779ea39be..641a817f667 100644 --- a/tests/examples-smoke-tests/roles.test.ts +++ b/tests/examples-smoke-tests/roles.test.ts @@ -1,7 +1,7 @@ import { Browser, Page } from 'playwright'; import { exampleProjectTests, initFirstItemTest, loadIndex } from './utils'; -exampleProjectTests('../examples-staging/roles', browserType => { +exampleProjectTests('../examples/roles', browserType => { let browser: Browser = undefined as any; let page: Page = undefined as any; beforeAll(async () => {