From 1886b43235e50bd2e070350d258f0a3145c19bbc Mon Sep 17 00:00:00 2001 From: Mitchell Hamilton Date: Tue, 6 Apr 2021 10:36:47 +1000 Subject: [PATCH] Next-lite example project (#5341) --- .changeset/proud-hotels-agree.md | 6 ++ .changeset/six-feet-exercise.md | 5 ++ docs-next/pages/apis/config.mdx | 4 + examples-next/next-lite/keystone.ts | 12 +++ examples-next/next-lite/next-env.d.ts | 2 + examples-next/next-lite/next.config.js | 3 + examples-next/next-lite/package.json | 27 +++++++ examples-next/next-lite/pages/api/graphql.js | 2 + examples-next/next-lite/pages/index.js | 26 ++++++ examples-next/next-lite/pages/post/[slug].js | 33 ++++++++ examples-next/next-lite/schema.ts | 10 +++ examples-next/next-lite/tsconfig.json | 19 +++++ .../next-graphql/package.json | 4 + .../node-api/package.json | 4 + packages-next/keystone/next/package.json | 4 + packages-next/keystone/package.json | 3 + .../next-graphql.ts | 22 +++++ .../node-api.ts | 9 +++ packages-next/keystone/src/artifacts.ts | 81 ++++++++++++++++++- packages-next/keystone/src/next.ts | 55 +++++++++++++ .../keystone/src/scripts/build/build.ts | 2 +- .../keystone/src/scripts/postinstall.ts | 2 +- packages-next/keystone/src/scripts/prisma.ts | 2 +- packages-next/keystone/src/scripts/run/dev.ts | 2 +- packages-next/types/src/config/index.ts | 4 + packages/test-utils/src/index.ts | 2 +- 26 files changed, 336 insertions(+), 9 deletions(-) create mode 100644 .changeset/proud-hotels-agree.md create mode 100644 .changeset/six-feet-exercise.md create mode 100644 examples-next/next-lite/keystone.ts create mode 100644 examples-next/next-lite/next-env.d.ts create mode 100644 examples-next/next-lite/next.config.js create mode 100644 examples-next/next-lite/package.json create mode 100644 examples-next/next-lite/pages/api/graphql.js create mode 100644 examples-next/next-lite/pages/index.js create mode 100644 examples-next/next-lite/pages/post/[slug].js create mode 100644 examples-next/next-lite/schema.ts create mode 100644 examples-next/next-lite/tsconfig.json create mode 100644 packages-next/keystone/___internal-do-not-use-will-break-in-patch/next-graphql/package.json create mode 100644 packages-next/keystone/___internal-do-not-use-will-break-in-patch/node-api/package.json create mode 100644 packages-next/keystone/next/package.json create mode 100644 packages-next/keystone/src/___internal-do-not-use-will-break-in-patch/next-graphql.ts create mode 100644 packages-next/keystone/src/___internal-do-not-use-will-break-in-patch/node-api.ts create mode 100644 packages-next/keystone/src/next.ts diff --git a/.changeset/proud-hotels-agree.md b/.changeset/proud-hotels-agree.md new file mode 100644 index 00000000000..98d8b011f80 --- /dev/null +++ b/.changeset/proud-hotels-agree.md @@ -0,0 +1,6 @@ +--- +'@keystone-next/keystone': minor +'@keystone-next/types': minor +--- + +Added `generateNextGraphqlAPI` and `generateNodeAPI` experimental options diff --git a/.changeset/six-feet-exercise.md b/.changeset/six-feet-exercise.md new file mode 100644 index 00000000000..5fcb1a42f5c --- /dev/null +++ b/.changeset/six-feet-exercise.md @@ -0,0 +1,5 @@ +--- +'@keystone-next/keystone': minor +--- + +Added `withKeystone` in `next` entrypoint diff --git a/docs-next/pages/apis/config.mdx b/docs-next/pages/apis/config.mdx index 1ca3b3dab6b..6d8e0aabe87 100644 --- a/docs-next/pages/apis/config.mdx +++ b/docs-next/pages/apis/config.mdx @@ -262,6 +262,8 @@ import { config } from '@keystone-next/keystone/schema'; export default config({ experimental: { enableNextJsGraphqlApiEndpoint: true, + generateNextGraphqlAPI: true, + generateNodeAPI: true, } /* ... */ }); @@ -270,5 +272,7 @@ export default config({ Options: - `enableNextJsGraphqlApiEndpoint`: (coming soon) +- `generateNextGraphqlAPI`: Creates a file at `node_modules/.keystone/next/graphql-api` with `default` and `config` exports that can be re-exported in a Next API route +- `generateNodeAPI`: Creates a file at `node_modules/.keystone/api` with a `lists` export export default ({ children }) => {children}; diff --git a/examples-next/next-lite/keystone.ts b/examples-next/next-lite/keystone.ts new file mode 100644 index 00000000000..e0e150676a4 --- /dev/null +++ b/examples-next/next-lite/keystone.ts @@ -0,0 +1,12 @@ +import { config } from '@keystone-next/keystone/schema'; + +import { Post } from './schema'; + +export default config({ + db: { adapter: 'prisma_sqlite', url: 'file:./app.db' }, + experimental: { + generateNextGraphqlAPI: true, + generateNodeAPI: true, + }, + lists: { Post }, +}); diff --git a/examples-next/next-lite/next-env.d.ts b/examples-next/next-lite/next-env.d.ts new file mode 100644 index 00000000000..7b7aa2c7727 --- /dev/null +++ b/examples-next/next-lite/next-env.d.ts @@ -0,0 +1,2 @@ +/// +/// diff --git a/examples-next/next-lite/next.config.js b/examples-next/next-lite/next.config.js new file mode 100644 index 00000000000..213a0a842d1 --- /dev/null +++ b/examples-next/next-lite/next.config.js @@ -0,0 +1,3 @@ +const { withKeystone } = require('@keystone-next/keystone/next'); + +module.exports = withKeystone(); diff --git a/examples-next/next-lite/package.json b/examples-next/next-lite/package.json new file mode 100644 index 00000000000..e61d0630835 --- /dev/null +++ b/examples-next/next-lite/package.json @@ -0,0 +1,27 @@ +{ + "name": "@keystone-next/example-next-lite", + "version": "1.0.3", + "private": true, + "license": "MIT", + "scripts": { + "dev": "next dev", + "start": "next start", + "build": "next build" + }, + "dependencies": { + "@keystone-next/admin-ui": "^12.0.0", + "@keystone-next/fields": "^5.3.0", + "@keystone-next/keystone": "^14.0.0", + "dotenv": "^8.2.0", + "next": "^10.0.9", + "react": "^17.0.2", + "react-dom": "^17.0.2" + }, + "devDependencies": { + "typescript": "^4.2.3" + }, + "engines": { + "node": ">=10.0.0" + }, + "repository": "https://github.com/keystonejs/keystone/tree/master/examples-next/next-lite" +} diff --git a/examples-next/next-lite/pages/api/graphql.js b/examples-next/next-lite/pages/api/graphql.js new file mode 100644 index 00000000000..aa43c92eee1 --- /dev/null +++ b/examples-next/next-lite/pages/api/graphql.js @@ -0,0 +1,2 @@ +// eslint-disable-next-line import/no-unresolved +export { default, config } from '.keystone/graphql'; diff --git a/examples-next/next-lite/pages/index.js b/examples-next/next-lite/pages/index.js new file mode 100644 index 00000000000..0e039e71756 --- /dev/null +++ b/examples-next/next-lite/pages/index.js @@ -0,0 +1,26 @@ +import React from 'react'; +import Link from 'next/link'; +// eslint-disable-next-line import/no-unresolved +import { lists } from '.keystone/api'; + +export default function HomePage({ posts }) { + return ( +
+

Welcome to my blog

+
    + {posts.map((post, i) => ( +
  • + + {post.title} + +
  • + ))} +
+
+ ); +} + +export async function getStaticProps() { + const posts = await lists.Post.findMany({ resolveFields: 'slug title' }); + return { props: { posts } }; +} diff --git a/examples-next/next-lite/pages/post/[slug].js b/examples-next/next-lite/pages/post/[slug].js new file mode 100644 index 00000000000..54f6fc9adf5 --- /dev/null +++ b/examples-next/next-lite/pages/post/[slug].js @@ -0,0 +1,33 @@ +import React from 'react'; + +// eslint-disable-next-line import/no-unresolved +import { lists } from '.keystone/api'; + +export default function PostPage({ post }) { + return ( +
+

{post.title}

+
{post.content}
+
+ ); +} + +export async function getStaticPaths() { + const posts = await lists.Post.findMany({ + resolveFields: 'slug', + }); + + const paths = posts.map(post => post.slug).map(slug => `/post/${slug}`); + return { + paths, + fallback: false, + }; +} + +export async function getStaticProps({ params: { slug } }) { + const [post] = await lists.Post.findMany({ + where: { slug: slug }, + resolveFields: 'title content', + }); + return { props: { post } }; +} diff --git a/examples-next/next-lite/schema.ts b/examples-next/next-lite/schema.ts new file mode 100644 index 00000000000..dfae7606ec5 --- /dev/null +++ b/examples-next/next-lite/schema.ts @@ -0,0 +1,10 @@ +import { list } from '@keystone-next/keystone/schema'; +import { text } from '@keystone-next/fields'; + +export const Post = list({ + fields: { + title: text({ isRequired: true }), + slug: text(), + content: text(), + }, +}); diff --git a/examples-next/next-lite/tsconfig.json b/examples-next/next-lite/tsconfig.json new file mode 100644 index 00000000000..401ede34467 --- /dev/null +++ b/examples-next/next-lite/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "esnext", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": false, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve" + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], + "exclude": ["node_modules"] +} diff --git a/packages-next/keystone/___internal-do-not-use-will-break-in-patch/next-graphql/package.json b/packages-next/keystone/___internal-do-not-use-will-break-in-patch/next-graphql/package.json new file mode 100644 index 00000000000..6cbbe144d0c --- /dev/null +++ b/packages-next/keystone/___internal-do-not-use-will-break-in-patch/next-graphql/package.json @@ -0,0 +1,4 @@ +{ + "main": "dist/keystone.cjs.js", + "module": "dist/keystone.esm.js" +} diff --git a/packages-next/keystone/___internal-do-not-use-will-break-in-patch/node-api/package.json b/packages-next/keystone/___internal-do-not-use-will-break-in-patch/node-api/package.json new file mode 100644 index 00000000000..6cbbe144d0c --- /dev/null +++ b/packages-next/keystone/___internal-do-not-use-will-break-in-patch/node-api/package.json @@ -0,0 +1,4 @@ +{ + "main": "dist/keystone.cjs.js", + "module": "dist/keystone.esm.js" +} diff --git a/packages-next/keystone/next/package.json b/packages-next/keystone/next/package.json new file mode 100644 index 00000000000..6cbbe144d0c --- /dev/null +++ b/packages-next/keystone/next/package.json @@ -0,0 +1,4 @@ +{ + "main": "dist/keystone.cjs.js", + "module": "dist/keystone.esm.js" +} diff --git a/packages-next/keystone/package.json b/packages-next/keystone/package.json index 68fe5e1d57d..908278f0258 100644 --- a/packages-next/keystone/package.json +++ b/packages-next/keystone/package.json @@ -21,6 +21,7 @@ "@keystone-next/keystone-legacy": "^22.0.0", "@keystone-next/server-side-graphql-client-legacy": "3.0.0", "@keystone-next/types": "^15.0.1", + "@preconstruct/next": "^2.0.0", "@prisma/client": "2.19.0", "@prisma/migrate": "2.19.0", "@prisma/sdk": "2.19.0", @@ -67,6 +68,8 @@ "preconstruct": { "entrypoints": [ "index.ts", + "next.ts", + "___internal-do-not-use-will-break-in-patch/{node-api,next-graphql}.ts", "artifacts.ts", "migrations.ts", "schema/index.ts", diff --git a/packages-next/keystone/src/___internal-do-not-use-will-break-in-patch/next-graphql.ts b/packages-next/keystone/src/___internal-do-not-use-will-break-in-patch/next-graphql.ts new file mode 100644 index 00000000000..c638fdffd49 --- /dev/null +++ b/packages-next/keystone/src/___internal-do-not-use-will-break-in-patch/next-graphql.ts @@ -0,0 +1,22 @@ +import { KeystoneConfig } from '@keystone-next/types'; +import { initConfig } from '../lib/initConfig'; +import { createSystem } from '../lib/createSystem'; +import { createApolloServerMicro } from '../lib/createApolloServer'; + +export function nextGraphQLAPIRoute(keystoneConfig: KeystoneConfig, prismaClient: any) { + const initializedKeystoneConfig = initConfig(keystoneConfig); + const { graphQLSchema, keystone, createContext } = createSystem( + initializedKeystoneConfig, + prismaClient + ); + + const apolloServer = createApolloServerMicro({ + graphQLSchema, + createContext, + sessionStrategy: initializedKeystoneConfig.session?.(), + apolloConfig: initializedKeystoneConfig.graphql?.apolloConfig, + connectionPromise: keystone.connect(), + }); + + return apolloServer.createHandler({ path: '/api/graphql' }); +} diff --git a/packages-next/keystone/src/___internal-do-not-use-will-break-in-patch/node-api.ts b/packages-next/keystone/src/___internal-do-not-use-will-break-in-patch/node-api.ts new file mode 100644 index 00000000000..0fe048b13da --- /dev/null +++ b/packages-next/keystone/src/___internal-do-not-use-will-break-in-patch/node-api.ts @@ -0,0 +1,9 @@ +import { KeystoneConfig } from '@keystone-next/types'; +import { createSystem } from '../lib/createSystem'; +import { initConfig } from '../lib/initConfig'; + +export function createListsAPI(config: KeystoneConfig, prismaClient: any) { + const { createContext, keystone } = createSystem(initConfig(config), prismaClient); + keystone.connect(); + return createContext().sudo().lists; +} diff --git a/packages-next/keystone/src/artifacts.ts b/packages-next/keystone/src/artifacts.ts index 65719876c48..a4a4ace2a28 100644 --- a/packages-next/keystone/src/artifacts.ts +++ b/packages-next/keystone/src/artifacts.ts @@ -1,7 +1,7 @@ import path from 'path'; import { printSchema, GraphQLSchema } from 'graphql'; import * as fs from 'fs-extra'; -import type { BaseKeystone } from '@keystone-next/types'; +import type { BaseKeystone, KeystoneConfig } from '@keystone-next/types'; import { getGenerator, formatSchema } from '@prisma/sdk'; import { confirmPrompt } from './lib/prompts'; import { printGeneratedTypes } from './lib/schema-type-printer'; @@ -105,20 +105,93 @@ export async function generateCommittedArtifacts( return artifacts; } +const nodeAPIJS = ( + cwd: string, + config: KeystoneConfig +) => `import keystoneConfig from '../../keystone'; +import { PrismaClient } from '.prisma/client'; +import { createListsAPI } from '@keystone-next/keystone/___internal-do-not-use-will-break-in-patch/node-api'; +${makeVercelIncludeTheSQLiteDB(cwd, path.join(cwd, 'node_modules/.keystone/next'), config)} + +export const lists = createListsAPI(keystoneConfig, PrismaClient); +`; + +const nodeAPIDTS = `import { KeystoneListsAPI } from '@keystone-next/types'; +import { KeystoneListsTypeInfo } from './types'; + +export const lists: KeystoneListsAPI;`; + +const makeVercelIncludeTheSQLiteDB = ( + cwd: string, + directoryOfFileToBeWritten: string, + config: KeystoneConfig +) => { + if (config.db.adapter === 'prisma_sqlite') { + const sqliteDbAbsolutePath = path.resolve(cwd, config.db.url.replace('file:', '')); + + return `import path from 'path'; + + path.join(__dirname, ${JSON.stringify( + path.relative(directoryOfFileToBeWritten, sqliteDbAbsolutePath) + )}); + path.join(process.cwd(), ${JSON.stringify(path.relative(cwd, sqliteDbAbsolutePath))}); + `; + } + return ''; +}; + +const nextGraphQLAPIJS = ( + cwd: string, + config: KeystoneConfig +) => `import keystoneConfig from '../../../keystone'; +import { PrismaClient } from '.prisma/client'; +import { nextGraphQLAPIRoute } from '@keystone-next/keystone/___internal-do-not-use-will-break-in-patch/next-graphql'; +${makeVercelIncludeTheSQLiteDB(cwd, path.join(cwd, 'node_modules/.keystone/next'), config)} + +export const config = { + api: { + bodyParser: false, + }, +}; + +export default nextGraphQLAPIRoute(keystoneConfig, PrismaClient); +`; + +// note the export default config is just a lazy way of going "this is also any" +const nextGraphQLAPIDTS = `export const config: any; +export default config; +`; + export async function generateNodeModulesArtifacts( graphQLSchema: GraphQLSchema, keystone: BaseKeystone, + config: KeystoneConfig, cwd: string ) { const printedSchema = printSchema(graphQLSchema); - + const dotKeystoneDir = path.join(cwd, 'node_modules/.keystone'); await Promise.all([ generatePrismaClient(cwd), fs.outputFile( - path.join(cwd, 'node_modules/.keystone/types.d.ts'), + path.join(dotKeystoneDir, 'types.d.ts'), printGeneratedTypes(printedSchema, keystone, graphQLSchema) ), - fs.outputFile(path.join(cwd, 'node_modules/.keystone/types.js'), ''), + fs.outputFile(path.join(dotKeystoneDir, 'types.js'), ''), + ...(config.experimental?.generateNodeAPI + ? [ + fs.outputFile(path.join(dotKeystoneDir, 'api.js'), nodeAPIJS(cwd, config)), + fs.outputFile(path.join(dotKeystoneDir, 'api.d.ts'), nodeAPIDTS), + ] + : []), + ...(config.experimental?.generateNextGraphqlAPI + ? [ + fs.outputFile( + path.join(dotKeystoneDir, 'next/graphql-api.js'), + nextGraphQLAPIJS(cwd, config) + ), + fs.outputFile(path.join(dotKeystoneDir, 'next/graphql-api.d.ts'), nextGraphQLAPIDTS), + ] + : []), ]); } diff --git a/packages-next/keystone/src/next.ts b/packages-next/keystone/src/next.ts new file mode 100644 index 00000000000..cb63a43ad9e --- /dev/null +++ b/packages-next/keystone/src/next.ts @@ -0,0 +1,55 @@ +import execa from 'execa'; +// @ts-ignore +import withPreconstruct from '@preconstruct/next'; + +let hasAlreadyStarted = false; + +export const withKeystone = (internalConfig: any = {}) => ( + phase: + | 'phase-export' + | 'phase-production-build' + | 'phase-production-server' + | 'phase-development-server', + thing: any +) => { + if (phase === 'phase-production-build') { + execa.sync('node', [require.resolve('@keystone-next/keystone/bin/cli.js'), 'postinstall'], { + stdio: 'inherit', + }); + } + if (phase === 'phase-development-server' && !hasAlreadyStarted) { + hasAlreadyStarted = true; + + const cliPath = require.resolve('@keystone-next/keystone/bin/cli.js'); + + execa.sync('node', [cliPath, 'postinstall', '--fix'], { + stdio: 'inherit', + }); + // for some reason things blow up with EADDRINUSE if the dev call happens synchronously here + // so we wait a sec and then do it + setTimeout(() => { + execa('node', [cliPath], { + stdio: 'inherit', + env: { ...process.env, PORT: process.env.PORT || '8000' }, + }); + }, 100); + } + let internalConfigObj = + typeof internalConfig === 'function' ? internalConfig(phase, thing) : internalConfig; + + let originalWebpack = internalConfigObj.webpack; + internalConfigObj.webpack = (webpackConfig: any, options: any) => { + if (options.isServer) { + webpackConfig.externals = [ + ...webpackConfig.externals, + '@keystone-next/keystone/___internal-do-not-use-will-break-in-patch/api', + '@keystone-next/keystone/___internal-do-not-use-will-break-in-patch/next-graphql', + '@keystone-next/keystone/next', + '@keystone-next/keystone', + '.prisma/client', + ]; + } + return originalWebpack ? originalWebpack(webpackConfig, options) : webpackConfig; + }; + return withPreconstruct(internalConfigObj); +}; diff --git a/packages-next/keystone/src/scripts/build/build.ts b/packages-next/keystone/src/scripts/build/build.ts index c31349cb628..8d9460436c5 100644 --- a/packages-next/keystone/src/scripts/build/build.ts +++ b/packages-next/keystone/src/scripts/build/build.ts @@ -94,7 +94,7 @@ export async function build(cwd: string) { console.log('✨ Generating database client'); // FIXME: This needs to generate clients for the correct build target using binaryTarget // https://www.prisma.io/docs/reference/api-reference/prisma-schema-reference#binarytargets-options - await generateNodeModulesArtifacts(graphQLSchema, keystone, cwd); + await generateNodeModulesArtifacts(graphQLSchema, keystone, config, cwd); if (config.ui?.isDisabled) { console.log('✨ Skipping Admin UI code generation'); diff --git a/packages-next/keystone/src/scripts/postinstall.ts b/packages-next/keystone/src/scripts/postinstall.ts index 79105db2f35..c539451e721 100644 --- a/packages-next/keystone/src/scripts/postinstall.ts +++ b/packages-next/keystone/src/scripts/postinstall.ts @@ -20,5 +20,5 @@ export async function postinstall(cwd: string, shouldFix: boolean) { await validateCommittedArtifacts(graphQLSchema, keystone, cwd); console.log('✨ GraphQL and Prisma schemas are up to date'); } - await generateNodeModulesArtifacts(graphQLSchema, keystone, cwd); + await generateNodeModulesArtifacts(graphQLSchema, keystone, config, cwd); } diff --git a/packages-next/keystone/src/scripts/prisma.ts b/packages-next/keystone/src/scripts/prisma.ts index 1218386cb1c..607648d21a4 100644 --- a/packages-next/keystone/src/scripts/prisma.ts +++ b/packages-next/keystone/src/scripts/prisma.ts @@ -11,7 +11,7 @@ export async function prisma(cwd: string, args: string[]) { const { keystone, graphQLSchema } = createSystem(config); await validateCommittedArtifacts(graphQLSchema, keystone, cwd); - await generateNodeModulesArtifacts(graphQLSchema, keystone, cwd); + await generateNodeModulesArtifacts(graphQLSchema, keystone, config, cwd); await execa('node', [require.resolve('prisma'), ...args], { cwd, diff --git a/packages-next/keystone/src/scripts/run/dev.ts b/packages-next/keystone/src/scripts/run/dev.ts index ed3d264fcf9..7a166bc9a80 100644 --- a/packages-next/keystone/src/scripts/run/dev.ts +++ b/packages-next/keystone/src/scripts/run/dev.ts @@ -35,7 +35,7 @@ export const dev = async (cwd: string, shouldDropDatabase: boolean) => { console.log('✨ Generating GraphQL and Prisma schemas'); const prismaSchema = (await generateCommittedArtifacts(graphQLSchema, keystone, cwd)).prisma; - await generateNodeModulesArtifacts(graphQLSchema, keystone, cwd); + await generateNodeModulesArtifacts(graphQLSchema, keystone, config, cwd); if (config.db.useMigrations) { await devMigrations( diff --git a/packages-next/types/src/config/index.ts b/packages-next/types/src/config/index.ts index 47e42c58cb1..f60aff2c98c 100644 --- a/packages-next/types/src/config/index.ts +++ b/packages-next/types/src/config/index.ts @@ -34,6 +34,10 @@ export type KeystoneConfig = { experimental?: { /** Enables nextjs graphql api route mode */ enableNextJsGraphqlApiEndpoint?: boolean; + /** Creates a file at `node_modules/.keystone/api` with a `lists` export */ + generateNodeAPI?: boolean; + /** Creates a file at `node_modules/.keystone/next/graphql-api` with `default` and `config` exports that can be re-exported in a Next API route */ + generateNextGraphqlAPI?: boolean; }; }; diff --git a/packages/test-utils/src/index.ts b/packages/test-utils/src/index.ts index 8a976a30598..9ca4dde8509 100644 --- a/packages/test-utils/src/index.ts +++ b/packages/test-utils/src/index.ts @@ -74,7 +74,7 @@ async function setupFromConfig({ alreadyGeneratedProjects.add(hash); fs.mkdirSync(cwd, { recursive: true }); await writeCommittedArtifacts(artifacts, cwd); - await generateNodeModulesArtifacts(graphQLSchema, keystone, cwd); + await generateNodeModulesArtifacts(graphQLSchema, keystone, config, cwd); } await pushPrismaSchemaToDatabase( config.db.url,