I know this is not a new issue, but even after reading through related issues and studying the adoption guides, I cannot figure out how to successfully build a simple @nexus/schema project.
I have setup a project as described in the current tutorial docs with following relevant files:
// api/schema.ts
import { makeSchema } from '@nexus/schema'
import { nexusPrisma } from 'nexus-plugin-prisma'
import { join } from 'path'
import * as typeDefs from './graphql'
export const schema = makeSchema({
types: typeDefs,
plugins: [
nexusPrisma({
experimentalCRUD: true
}),
],
outputs: {
typegen: join(__dirname, '..', 'nexus-typegen.ts'),
schema: join(__dirname, '..', 'schema.graphql')
},
typegenAutoConfig: {
sources: [
{
source: require.resolve('.prisma/client/index.d.ts'),
alias: "prisma",
},
{
source: require.resolve("./context"),
alias: "ContextModule",
},
],
contextType: "ContextModule.Context",
},
})
// api/graphql/index.ts
export * from './User'
// api/graphql/User.ts
import { objectType, extendType } from '@nexus/schema'
export const User = objectType({
name: 'User',
definition(t) {
t.model.email()
t.model.name()
}
})
export const UserQuery = extendType({
type: 'Query',
definition(t) {
t.crud.users()
},
})
When running ts-node-dev api/schema.ts those errors are thrown:
Property 'model' does not exist on type 'ObjectDefinitionBlock
Property 'crud' does not exist on type 'OutputDefinitionBlock
Following dependencies are in use:
"@nexus/schema": "0.16.0",
"@prisma/client": "2.7.0",
"@prisma/cli": "2.7.0",
"nexus-plugin-prisma": "0.20.0",
"ts-node-dev": "^1.0.0-pre.63"
Can anyone please help?
i just was using nexus and just migrated to nexus/schema and having the same issue
After I restarted my development machine it suddenly worked! I cannot really tell why, because I also added express middleware to the server stack and then I was suddenly able to run a ts-node-dev api/schema.ts to create the required type definitions.
This actually sounds relevant to my issue as well: https://github.com/graphql-nexus/schema/issues/523
In addition to getting the "getTypeMap" issue, all of my crud/model fields are null. Let me know if you remember what (if anything) changed. I just tried a reboot...no luck
@jawosis I still haven't gotten this to work, but i have a question. When looking at your code I see:
source: require.resolve('.prisma/client/index.d.ts'),
Shouldn't this be pointing to, ../node_modules/.prisma/client/index.d.ts? Or at least that's what I think it should be haha
But yea, if you have a sudden lightbulb moment on what caused it to work, let us know :D
might be related to this error I see when running: ts-node-dev --transpile-only src/app.ts
TypeError: Cannot read property 'some' of undefined
at transformArg (/Users/arubaito/thelab/pedra/azul/node_modules/nexus-plugin-prisma/src/dmmf/transformer.ts:91:33)
I tried the fix from this PR: https://github.com/graphql-nexus/nexus-plugin-prisma/pull/876
and everything seems to be working well now. seems to be a typo in a function in the transformer.
In my case, I had "graphql": "15.3.0" in my package.json when I ran into this issue.
Downgrading back to 14.7.0, deleting node_modules, running npm install, and generating prisma/nexus again helped resolve this issue for me.
14.7.0
This does not work on my machine
@jawosis
I think the doc is a bit unclear. My problem was that ctx.db is not passed to apollo server. I solve is by passing context:
// db.tx
import { PrismaClient } from "@prisma/client";
export const db = new PrismaClient();
// app.tx
import { db } from "./db";
const apollo = new ApolloServer({
schema,
context: () => ({
db,
}),
});
Hello, any updates on this?
workaround
At the first start, the types have not yet been defined, and then the crud and the model will have any type. But after generating the types ("nexus:reflect": "NEXUS_SHOULD_EXIT_AFTER_REFLECTION=true ts-node src"), they will get the desired type.
// helper.ts
import { ObjectDefinitionBlock } from '@nexus/schema/dist/definitions/objectType';
type PickType<T, K extends string> = T extends Pick<any, K> ? T[K] : any;
type CRUD<TypeName extends string> = PickType<NexusGenCustomOutputProperties<TypeName>, 'crud'>;
type Model<TypeName extends string> = PickType<NexusGenCustomOutputProperties<TypeName>, 'model'>;
export const crud = <TypeName extends string>(t: ObjectDefinitionBlock<TypeName>): CRUD<TypeName> =>
(t as any).crud;
export const model = <TypeName extends string>(
t: ObjectDefinitionBlock<TypeName>
): Model<TypeName> => (t as any).model;
// api/graphql/User.ts
import { objectType, extendType } from '@nexus/schema'
import { crud, model } from '.../helper.ts'
export const User = objectType({
name: 'User',
definition(t) {
model(t).email()
model(t).name()
/*
model(t).email().name()
*/
}
})
export const UserQuery = extendType({
type: 'Query',
definition(t) {
crud(t).users()
},
})
// tsconfig.json
{
"compilerOptions": {},
"include": [
"./typegen.d.ts", // <------ **TYPEGEN**
"./src"
],
}
// src/index.ts
const schema = makeSchema({
typegenAutoConfig: {
sources: [
{
source: require.resolve('.prisma/client/index.d.ts'),
alias: 'prisma',
},
{
source: require.resolve('./context'),
alias: 'ContextModule',
},
],
contextType: 'ContextModule.Context',
},
outputs: {
schema: path.join(__dirname, '../schema.graphql'),
typegen: path.join(__dirname, '../typegen.d.ts'), // <--- **TYPEGEN**
},
types: [types, jsonScalar, dateTimeScalar],
shouldExitAfterGenerateArtifacts: Boolean(process.env.NEXUS_SHOULD_EXIT_AFTER_REFLECTION),
plugins: [nexusPrisma({ experimentalCRUD: true, paginationStrategy: 'prisma' })],
});
In my case, I simply could not get my builds to deploy in CI, though they worked locally, typegen simply did not alleviate these errors during deployment on Heroku.
I ended up changing the destination folders to my generated folder in src, and committing them to the repo. Git-hooks will help me keep things in sync, sure, but I couldn't find a way to properly bootstrap a build in CI.
makeSchema({
...
plugins: [
nexusPrisma({
experimentalCRUD: true,
// UPDATED TO SAVE IN MY GENERATED FOLDER
outputs: { typegen: __dirname + '/generated/nexus-prisma.d.ts' },
}),
],
outputs: {
schema: __dirname + '/../schema.graphql',
// CHANGED TO .d.ts FILE
typegen: __dirname + '/generated/nexus.d.ts',
},
...
})
I also added these files explicitly to my src in tsconfig.json but I don't think that step is necessary.
Just a quick fix dump for anyone not using ts-node-dev who is still hitting the Property 'model' does not exist on type ObjectDefinitionBlock or Property 'crud' does not exist on type ObjectDefinitionBlock...
Ensure your type generations are getting output where you think they are.
More on this here, with detailed makeSchema example.
Using versions: nexus: v1.0.0 nexus-plugin-prisma: v0.27.0 @prisma/client: v2.13.1
i had the same problem (model and crud properties do not exist on types) and @djm's solution while wasn't perfect for me pointed me to the right direction (thanks!).
my versions are:
in my understanding there are 3 different type generations in play:
yarn prisma generate provides this and the file's location is node_modules/.prisma/client/index.ts (it took some time while i figured out that .prisma is not a typo :D). this is strictly prisma related and it's useful when you manually call prisma in your resolver (e.g. prisma.yourModel.findMany()).
the nexusPrisma() plugin imported from the nexus-plugin-prisma package generates this. you can set the path by adding an outputs option to the plugin (e.g. nexusPrisma({ outputs: 'yourPath' })) but since the default path is node_modules/@types/typegen-nexus-plugin-prisma/index.d.ts typescript already knows about this so it's not necessary to set this value. the file contains the types for the _graphqlized_ prisma schema, like interfaces for the models, inputs, etc.
the makeSchema() function imported from the nexus package generates this. this is where the missing properties are. you can set the path by adding outputs or outputs/typegen option to the config (e.g. makeSchema({ outputs: true })). there are a few different scenarios now:
{ outputs: true }i went with this originally because it says true means default paths and the default path for generated types is node_modules/@types/nexus-typegen/index.d.ts. unfortunately there is no generated file in node_modules because the typegen file path is not set, it remains null.
{ outputs: { typegen: true } }same goes for this, while the interface allows using a boolean here, it gets completely ignored.
{ outputs: { typegen: 'yourPath' } }in my experience this is the only working setup to make it work. with this you can set the file name of the missing generated types.
now that we finally know how to generate those types we have different ways to make typescript discover them.
node_modules/@types directorysince typescript is aware of the content of this directory and this is what nexus would do by default according to the tsdoc tag i added this to my makeSchema config:
makeSchema({
plugins: [nexusPrisma()],
types: [/* ... */],
sourceTypes: {
modules: [
{
module: require.resolve('.prisma/client/index.d.ts'),
alias: 'prisma'
}
]
},
contextType: { /* ... */ },
outputs: {
schema: true, // means schema.graphql in the root
typegen: join(
process.cwd(),
'node_modules/@types/nexus-typegen-custom/index.d.ts'
)
}
})
i added the -custom prefix to prevent collision with the _hopefully-soon-to-be-fixed_ default path.
tsconfig.jsoni guess some people uses the official guide to make this work so here is another way to solve it:
makeSchema({
plugins: [nexusPrisma()],
types: [/* ... */],
sourceTypes: {
modules: [
{
module: require.resolve('.prisma/client/index.d.ts'),
alias: 'prisma'
}
]
},
contextType: { /* ... */ },
outputs: {
schema: true, // means schema.graphql in the root
typegen: path.join(__dirname, 'generated/nexus.d.ts')
}
})
add typeRoots to tsconfig.json under compilerOptions (your path to the generated directory can be different):
{
"compilerOptions": {
"typeRoots": ["./src/generated"]
}
}
edit: now that i checked all of this again it seems like generating the nexus.d.ts outside of node_modules/@types works without adding typeRoots to my tsconfig.json. it did not work before and i spent some time with this so i could have added something to my config (can it be the rootDir?). i'm somewhat new to typescript so please fix me if i said something stupid above.
Most helpful comment
i had the same problem (
modelandcrudproperties do not exist on types) and @djm's solution while wasn't perfect for me pointed me to the right direction (thanks!).my versions are:
in my understanding there are 3 different type generations in play:
type generation
prisma types
yarn prisma generateprovides this and the file's location isnode_modules/.prisma/client/index.ts(it took some time while i figured out that.prismais not a typo :D). this is strictly prisma related and it's useful when you manually call prisma in your resolver (e.g.prisma.yourModel.findMany()).nexus plugin prisma types
the
nexusPrisma()plugin imported from thenexus-plugin-prismapackage generates this. you can set the path by adding anoutputsoption to the plugin (e.g.nexusPrisma({ outputs: 'yourPath' })) but since the default path isnode_modules/@types/typegen-nexus-plugin-prisma/index.d.tstypescript already knows about this so it's not necessary to set this value. the file contains the types for the _graphqlized_ prisma schema, like interfaces for the models, inputs, etc.nexus types
the
makeSchema()function imported from thenexuspackage generates this. this is where the missing properties are. you can set the path by addingoutputsoroutputs/typegenoption to the config (e.g.makeSchema({ outputs: true })). there are a few different scenarios now:1.
{ outputs: true }i went with this originally because it says
truemeans default paths and the default path for generated types isnode_modules/@types/nexus-typegen/index.d.ts. unfortunately there is no generated file innode_modulesbecause the typegen file path is not set, it remainsnull.2.
{ outputs: { typegen: true } }same goes for this, while the interface allows using a
booleanhere, it gets completely ignored.3.
{ outputs: { typegen: 'yourPath' } }in my experience this is the only working setup to make it work. with this you can set the file name of the missing generated types.
solutions
now that we finally know how to generate those types we have different ways to make typescript discover them.
leverage the
node_modules/@typesdirectorysince typescript is aware of the content of this directory and this is what nexus would do by default according to the tsdoc tag i added this to my
makeSchemaconfig:i added the
-customprefix to prevent collision with the _hopefully-soon-to-be-fixed_ default path.add the generated file to
tsconfig.jsoni guess some people uses the official guide to make this work so here is another way to solve it:
add
typeRootstotsconfig.jsonundercompilerOptions(your path to the generated directory can be different):edit: now that i checked all of this again it seems like generating the
nexus.d.tsoutside ofnode_modules/@typesworks without addingtypeRootsto mytsconfig.json. it did not work before and i spent some time with this so i could have added something to my config (can it be therootDir?). i'm somewhat new to typescript so please fix me if i said something stupid above.