diff --git a/.eslintrc b/.eslintrc index 5debb413d..ed68158d0 100644 --- a/.eslintrc +++ b/.eslintrc @@ -14,6 +14,8 @@ ], "overrides": [], "rules": { + // They are great actually + "@typescript-eslint/no-namespace": "off", // TypeScript makes these safe & effective "no-case-declarations": "off", // Same approach used by TypeScript noUnusedLocals diff --git a/.gitignore b/.gitignore index ec401aaa1..d648379cc 100644 --- a/.gitignore +++ b/.gitignore @@ -106,5 +106,5 @@ dist # Facades scalars.d.ts scalars.js -plugin.js -plugin.d.ts +generator.d.ts +generator.js diff --git a/README.md b/README.md index 1c30399a0..cade8076e 100644 --- a/README.md +++ b/README.md @@ -24,9 +24,15 @@ Official Prisma plugin for Nexus. - [Project 1:n Relation](#project-1n-relation) - [Example: Tests](#example-tests-1) - [Example: Full 1:n](#example-full-1n) - - [Prisma ID field to GraphQL ID scalar type mapping](#prisma-id-field-to-graphql-id-scalar-type-mapping) - - [Prisma Schema docs re-used for GraphQL schema doc](#prisma-schema-docs-re-used-for-graphql-schema-doc) - - [Prisma Schema docs re-used for JSDoc](#prisma-schema-docs-re-used-for-jsdoc) + - [Runtime Settings](#runtime-settings) + - [Reference](#reference) + - [Generator Settings](#generator-settings) + - [Usage](#usage-1) + - [Reference](#reference-1) + - [Prisma String @id fields project as GraphQL ID fields](#prisma-string-id-fields-project-as-graphql-id-fields) + - [Prisma Schema Docs Propagation](#prisma-schema-docs-propagation) + - [As GraphQL schema doc](#as-graphql-schema-doc) + - [As JSDoc](#as-jsdoc) - [Refined DX](#refined-dx) - [Recipes](#recipes) - [Project relation with custom resolver logic](#project-relation-with-custom-resolver-logic) @@ -120,7 +126,7 @@ export const schema = makeSchema({ ## Features -> **Note**: ⛑ The following use abbreviated examples that skip a complete setup of passing Nexus type definition to Nexus' `makeSchema`. If you are new to Nexus, Consider reading the [official Nexus tutorial](https://nxs.li/tutorial) before jumping into Nexus Prisma. +> **Note**: ⛑ The following use abbreviated examples that skip a complete setup of passing Nexus type definition to Nexus' `makeSchema`. If you are new to Nexus, consider reading the [official Nexus tutorial](https://nxs.li/tutorial) before jumping into Nexus Prisma. ### Type-safe Generated Library Code @@ -547,9 +553,100 @@ query { } ``` -### Prisma ID field to GraphQL ID scalar type mapping +### Runtime Settings -All `@id` fields in your Prisma Schema get projected as `ID` types, not `String` types. +#### Reference + +##### `prismaClientContextField: string` + +- **@summary** The name of the GraphQL context field to get an instance of Prisma Client from. +- **@remarks** The instance of Prisma Client found here is accessed in the default resolvers for relational fields. +- **@default** `"prisma"` +- **@example** + + ```ts + // src/main.ts + + import { PrismaClient } from '@prisma/client' + import { ApolloServer } from 'apollo-server' + import { makeSchema } from 'nexus' + import { User, Post, $settings } from 'nexus-prisma' + + new ApolloServer({ + schema: makeSchema({ + types: [], + }), + context() { + return { + db: new PrismaClient(), // <-- You put Prisma client on the "db" context property + } + }, + }) + + $settings({ + prismaClientContextField = 'db', // <-- Tell Nexus Prisma + }) + ``` + +### Generator Settings + +You are able to control certain aspects of the Nexus Prisma code generation. + +#### Usage + +1. Create a configuration file named any of: + + ``` + nexusPrisma.ts / nexus-prisma.ts / nexus_prisma.ts + ``` + + In one of the following directories: + + 1. **Project Root** – The directory containing your project's package.json. Example: + + ``` + ├── nexus-prisma.ts + └── package.json + ``` + + 2. **Primsa Directory** – The directory containing your Prisma schema. Example: + + ``` + ├── prisma/nexus-prisma.ts + └── package.json + ``` + +2. Import the settings singleton and make your desired changes. Example: + + ```ts + import { settings } from 'nexus-prisma/generator' + + settings({ + projectIdIntToGraphQL: 'ID', + }) + ``` + +#### Reference + +##### `projectIdIntToGraphQL: 'ID' | 'Int'` + +- **`@summary`** Map Prisma model fields of type `Int` with attribute `@id` to `ID` or `Int`. +- **`@default`** `Int` + +##### `docPropagation.JSDoc: boolean` + +- **`@summary`** Should Prisma Schema docs propagate as JSdoc? +- **`@default`** `true` + +##### `docPropagation.GraphQLDocs: boolean` + +- **`@summary`** Should Prisma Schema docs propagate as GraphQL docs? +- **`@remarks`** When this is disabled it will force `.description` property to be `undefined`. This is for convenience, allowing you to avoid post-generation data manipulation or consumption contortions. +- **`@default`** `true` + +### Prisma String @id fields project as GraphQL ID fields + +All `String` fields with `@id` attribute in your Prisma Schema get projected as GraphQL `ID` types rather than `String` types. ```prisma model User { @@ -576,7 +673,9 @@ type User { } ``` -### Prisma Schema docs re-used for GraphQL schema doc +### Prisma Schema Docs Propagation + +#### As GraphQL schema doc ```prisma /// A user. @@ -614,7 +713,7 @@ type User { } ``` -### Prisma Schema docs re-used for JSDoc +#### As JSDoc ```prisma /// A user. @@ -676,7 +775,7 @@ Nexus Prisma generates default GraphQL resolvers for your model _relation fields resolve(...args) { // Your custom before-logic here const result = await User.posts.resolve(...args) - // Your custom afer-logic here + // Your custom after-logic here return result }, }) diff --git a/jest.config.ts b/jest.config.ts index c50057903..6f1433fa8 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -7,7 +7,7 @@ const config: InitialOptionsTsJest = { testPathIgnorePatterns: process.env.CI ? [] : ['.*e2e.*'], globals: { 'ts-jest': { - diagnostics: Boolean(process.env.CI), + diagnostics: Boolean(process.env.CI) ? { ignoreCodes: [7006, 7031] } : false, babelConfig: false, tsconfig: '/tests/tsconfig.json', }, diff --git a/package.json b/package.json index 20d9d74af..39238bbc8 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,11 @@ "plugin.js", "plugin.d.ts", "scalars.js", - "scalars.d.ts" + "scalars.d.ts", + "settings.d.ts", + "settings.js", + "generator.d.ts", + "generator.js" ], "bin": { "nexus-prisma": "./dist/cli/nexus-prisma.js", @@ -24,7 +28,7 @@ "lint:check": "eslint . --ext .ts,.tsx --max-warnings 0", "dev": "tsc --build --watch", "dev:ts": "yarn dev", - "dev:yalc": "nodemon --exec 'yalc push --no-scripts' --watch 'dist/**/*'", + "dev:yalc": "nodemon --delay 1.5 --exec 'yalc push --no-scripts' --watch 'dist/**/*'", "build:module-facades": "ts-node scripts/build-module-facades", "build": "yarn clean && yarn build:module-facades && tsc", "test": "cross-env DEBUG=e2e jest", @@ -81,9 +85,7 @@ "nexus": "^1.0.0" }, "dependencies": { - "@endemolshinegroup/cosmiconfig-typescript-loader": "^3.0.2", "@prisma/generator-helper": "^2.22.1", - "cosmiconfig": "^7.0.0", "debug": "^4.3.1", "endent": "^2.0.1", "fs-jetpack": "^4.1.0", diff --git a/scripts/build-module-facades.ts b/scripts/build-module-facades.ts index 4ac3d90d5..bb85203f4 100644 --- a/scripts/build-module-facades.ts +++ b/scripts/build-module-facades.ts @@ -23,11 +23,11 @@ import * as path from 'path' import { PackageJson } from 'type-fest' generateModuleFacades([ - ['scalars.d.ts', "export * from './dist/scalars'"], - ['scalars.js', "module.exports = require('./dist/scalars')"], + ['scalars.d.ts', "export * from './dist/entrypoints/scalars'"], + ['scalars.js', "module.exports = require('./dist/entrypoints/scalars')"], - ['plugin.d.ts', "export * from './dist/plugin'"], - ['plugin.js', "exports.plugin = reuqire('./dist/plugin')"], + ['generator.d.ts', "export * from './dist/entrypoints/generator'"], + ['generator.js', "module.exports = require('./dist/entrypoints/generator')"], ]) function generateModuleFacades(facades: ModuleFacade[]) { diff --git a/settings.d.ts b/settings.d.ts new file mode 100644 index 000000000..33cadd39a --- /dev/null +++ b/settings.d.ts @@ -0,0 +1 @@ +export * from './dist/settings' diff --git a/settings.js b/settings.js new file mode 100644 index 000000000..55f846751 --- /dev/null +++ b/settings.js @@ -0,0 +1 @@ +module.exports = require('./dist/settings') diff --git a/src/cli/nexus-prisma.ts b/src/cli/nexus-prisma.ts index 499dd0dde..fd1859cc5 100644 --- a/src/cli/nexus-prisma.ts +++ b/src/cli/nexus-prisma.ts @@ -7,10 +7,10 @@ process.env.DEBUG_HIDE_DATE = 'true' import { generatorHandler } from '@prisma/generator-helper' import * as Path from 'path' - import { generateRuntimeAndEmit } from '../generator' +import { loadUserGentimeSettings } from '../generator/gentime/settingsLoader' +import { Gentime } from '../generator/gentime/settingsSingleton' import { externalToInternalDmmf } from '../helpers/prismaExternalToInternalDMMF' -import { getConfiguration } from '../configuration' // todo by default error in ci and warn in local // enforceValidPeerDependencies({ @@ -25,10 +25,13 @@ generatorHandler({ } }, // async required by interface + // eslint-disable-next-line async onGenerate({ dmmf }) { const internalDMMF = externalToInternalDmmf(dmmf) - console.log('created internal dmmf') - const configuration = await getConfiguration() - generateRuntimeAndEmit(internalDMMF, configuration) + loadUserGentimeSettings() + generateRuntimeAndEmit(internalDMMF, Gentime.settings) + process.stdout.write( + `You can now start using Nexus Prisma in your code. Reference: https://pris.ly/d/nexus-prisma\n` + ) }, }) diff --git a/src/configuration/configuration.ts b/src/configuration/configuration.ts deleted file mode 100644 index 977f35d01..000000000 --- a/src/configuration/configuration.ts +++ /dev/null @@ -1,34 +0,0 @@ -import TypeScriptLoader from '@endemolshinegroup/cosmiconfig-typescript-loader' -import { cosmiconfig } from 'cosmiconfig' -import { Configuration } from '../generator' - -const CONFIGURATION_NAME = 'nexus-prisma' - -export async function getConfiguration(): Promise { - const explorer = cosmiconfig(CONFIGURATION_NAME, { - searchPlaces: [ - 'nexus-prisma.ts', - 'nexusPrisma.ts', - 'nexus_prisma.ts', - 'prisma/nexus-prisma.ts', - 'prisma/nexusPrisma.ts', - 'prisma/nexus_prisma.ts', - ], - loaders: { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - '.ts': TypeScriptLoader, - }, - packageProp: [], - }) - - const result = await explorer.search() - - if (!result) { - return null - } - - console.log(`Loaded configuration from ${result.filepath}`) - - // TODO runtime validation with zod - return result.config as Configuration -} diff --git a/src/configuration/index.ts b/src/configuration/index.ts deleted file mode 100644 index 126119df2..000000000 --- a/src/configuration/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './configuration' diff --git a/src/entrypoints/generator.ts b/src/entrypoints/generator.ts new file mode 100644 index 000000000..e61761616 --- /dev/null +++ b/src/entrypoints/generator.ts @@ -0,0 +1,3 @@ +import { Gentime } from '../generator/gentime/settingsSingleton' + +export const settings = Gentime.changeSettings diff --git a/src/scalars/index.ts b/src/entrypoints/scalars.ts similarity index 96% rename from src/scalars/index.ts rename to src/entrypoints/scalars.ts index 61a43aff7..4803656e1 100644 --- a/src/scalars/index.ts +++ b/src/entrypoints/scalars.ts @@ -1,5 +1,5 @@ -import { DateTime } from './DateTime' -import { Json } from './Json' +import { DateTime } from '../scalars/DateTime' +import { Json } from '../scalars/Json' /** * Predefined Nexus scalar type definitions to satisfy all custom scalars needed in GraphQL to map to the diff --git a/src/generator/generate.ts b/src/generator/generate.ts index 5cf782365..35d542b47 100644 --- a/src/generator/generate.ts +++ b/src/generator/generate.ts @@ -3,14 +3,15 @@ import * as fs from 'fs-jetpack' import * as Path from 'path' import * as pkgup from 'pkg-up' import { d } from '../helpers/debugNexusPrisma' +import { Gentime } from './gentime/settingsSingleton' import * as ModelsGenerator from './models' -import { ModuleSpec, Configuration } from './types' +import { ModuleSpec } from './types' const OUTPUT_SOURCE_DIR = getOutputSourceDir() /** Generate the Nexus Prisma runtime files and emit them into a "hole" in the internal package source tree. */ -export function generateRuntimeAndEmit(dmmf: DMMF.Document, configuration: Configuration | null): void { - d('start generateRuntime with configuration %j', configuration) +export function generateRuntimeAndEmit(dmmf: DMMF.Document, settings: Gentime.Settings): void { + d('start generateRuntime with configuration %j', settings) d('start generateRuntime') @@ -19,8 +20,8 @@ export function generateRuntimeAndEmit(dmmf: DMMF.Document, configuration: Confi } const sourceFiles: ModuleSpec[] = [ - ModelsGenerator.JS.createModuleSpec(), - ModelsGenerator.TS.createModuleSpec(dmmf), + ModelsGenerator.JS.createModuleSpec(settings), + ModelsGenerator.TS.createModuleSpec(dmmf, settings), ] fs.remove(OUTPUT_SOURCE_DIR) @@ -36,10 +37,10 @@ export function generateRuntimeAndEmit(dmmf: DMMF.Document, configuration: Confi } /** Transform the given DMMF into JS source code with accompanying TS declarations. */ -export function generateRuntime(dmmf: DMMF.Document): ModuleSpec[] { +export function generateRuntime(dmmf: DMMF.Document, settings: Gentime.Settings): ModuleSpec[] { const sourceFiles: ModuleSpec[] = [ - ModelsGenerator.JS.createModuleSpec(), - ModelsGenerator.TS.createModuleSpec(dmmf), + ModelsGenerator.JS.createModuleSpec(settings), + ModelsGenerator.TS.createModuleSpec(dmmf, settings), ] return sourceFiles diff --git a/src/generator/gentime/settingsLoader.ts b/src/generator/gentime/settingsLoader.ts new file mode 100644 index 000000000..08674e2c3 --- /dev/null +++ b/src/generator/gentime/settingsLoader.ts @@ -0,0 +1,40 @@ +import * as fs from 'fs' +import { d } from '../../helpers/debugNexusPrisma' + +export function loadUserGentimeSettings(): void { + // eslint-disable-next-line + const tsNode = require('ts-node') + + // eslint-disable-next-line + tsNode.register({ + compilerOptions: { module: 'commonjs' }, + }) + + const userSettingsModulePath = pickFirstExisting( + [ + 'nexus-prisma.ts', + 'nexusPrisma.ts', + 'nexus_prisma.ts', + 'prisma/nexus-prisma.ts', + 'prisma/nexusPrisma.ts', + 'prisma/nexus_prisma.ts', + ].map((path) => `${process.cwd()}/${path}`) + ) + + /** + * Load the user's settings module for side-effects against the setset instance. + */ + + if (userSettingsModulePath) { + d(`Loaded configuration from ${userSettingsModulePath}`) + require(userSettingsModulePath) + } +} + +function pickFirstExisting(paths: string[]): null | string { + return ( + paths.find((path) => { + return fs.existsSync(path) + }) ?? null + ) +} diff --git a/src/generator/gentime/settingsSingleton.ts b/src/generator/gentime/settingsSingleton.ts new file mode 100644 index 000000000..d5b7078d9 --- /dev/null +++ b/src/generator/gentime/settingsSingleton.ts @@ -0,0 +1,55 @@ +import * as Setset from 'setset' + +export namespace Gentime { + export type SettingsInput = { + /** + * TODO + */ + projectIdIntToGraphQL?: 'ID' | 'Int' + /** + * TODO + */ + docPropagation?: + | boolean + | { + /** + * TODO + */ + JSDoc?: boolean + /** + * TODO + */ + GraphQLDocs?: boolean + } + } + + export type SettingsData = Setset.InferDataFromInput + + export type Settings = Setset.Manager + + export const settings = Setset.create({ + fields: { + projectIdIntToGraphQL: { + initial: () => 'Int', + }, + docPropagation: { + shorthand: (enabled) => ({ + GraphQLDocs: enabled, + JSDoc: enabled, + }), + fields: { + GraphQLDocs: { + initial: () => true, + }, + JSDoc: { + initial: () => true, + }, + }, + }, + }, + }) + + export function changeSettings(input: Setset.UserInput): Settings { + return settings.change(input) + } +} diff --git a/src/generator/index.ts b/src/generator/index.ts index 9c555bfbd..f15ab2c7f 100644 --- a/src/generator/index.ts +++ b/src/generator/index.ts @@ -1,2 +1 @@ export { generateRuntimeAndEmit } from './generate' -export { Configuration } from './types' diff --git a/src/generator/models/declaration.ts b/src/generator/models/declaration.ts index affb959b1..f6cb01fcf 100644 --- a/src/generator/models/declaration.ts +++ b/src/generator/models/declaration.ts @@ -4,14 +4,15 @@ import { LiteralUnion } from 'type-fest' import { StandardGraphQLScalarType, StandardgraphQLScalarTypes } from '../../helpers/graphql' import { PrismaScalarType } from '../../helpers/prisma' import { allCasesHandled } from '../../helpers/utils' +import { Gentime } from '../gentime/settingsSingleton' import { jsDocForEnum, jsDocForField, jsDocForModel } from '../helpers/JSDocTemplates' import { ModuleSpec } from '../types' -export function createModuleSpec(dmmf: DMMF.Document): ModuleSpec { +export function createModuleSpec(dmmf: DMMF.Document, settings: Gentime.Settings): ModuleSpec { return { fileName: 'index.d.ts', content: endent` - ${renderTypeScriptDeclarationForDocumentModels(dmmf)} + ${renderTypeScriptDeclarationForDocumentModels(dmmf, settings)} `, } } @@ -24,7 +25,10 @@ const NO_MODELS_DEFINED_COMMENT = endent` // N/A –– You have not defined any enums in your Prisma schema file. ` -export function renderTypeScriptDeclarationForDocumentModels(dmmf: DMMF.Document): string { +export function renderTypeScriptDeclarationForDocumentModels( + dmmf: DMMF.Document, + settings: Gentime.Settings +): string { const models = dmmf.datamodel.models const enums = dmmf.datamodel.enums @@ -47,7 +51,7 @@ export function renderTypeScriptDeclarationForDocumentModels(dmmf: DMMF.Document ${ models.length === 0 ? NO_MODELS_DEFINED_COMMENT - : models.map(renderTypeScriptDeclarationForModel).join('\n\n') + : models.map((model) => renderTypeScriptDeclarationForModel(model, settings)).join('\n\n') } // Enums @@ -55,7 +59,7 @@ export function renderTypeScriptDeclarationForDocumentModels(dmmf: DMMF.Document ${ enums.length === 0 ? NO_ENUMS_DEFINED_COMMENT - : enums.map(renderTypeScriptDeclarationForEnum).join('\n\n') + : enums.map((enum_) => renderTypeScriptDeclarationForEnum(enum_, settings)).join('\n\n') } } @@ -83,9 +87,9 @@ export function renderTypeScriptDeclarationForDocumentModels(dmmf: DMMF.Document ? NO_MODELS_DEFINED_COMMENT : models .map((model) => { + const jsdoc = settings.data.docPropagation.JSDoc ? jsDocForModel(model) + '\n' : '' return endent` - ${jsDocForModel(model)} - export const ${model.name}: $Types.${model.name} + ${jsdoc}export const ${model.name}: $Types.${model.name} ` }) .join('\n\n') @@ -105,53 +109,65 @@ export function renderTypeScriptDeclarationForDocumentModels(dmmf: DMMF.Document ? NO_ENUMS_DEFINED_COMMENT : enums .map((enum_) => { + const jsdoc = settings.data.docPropagation.JSDoc ? jsDocForEnum(enum_) + '\n' : '' return endent` - ${jsDocForEnum(enum_)} - export const ${enum_.name}: $Types.${enum_.name} + ${jsdoc}export const ${enum_.name}: $Types.${enum_.name} ` }) .join('\n\n') } - ` } -function renderTypeScriptDeclarationForEnum(enum_: DMMF.DatamodelEnum): string { +function renderTypeScriptDeclarationForEnum(enum_: DMMF.DatamodelEnum, settings: Gentime.Settings): string { + const jsdoc = settings.data.docPropagation.JSDoc ? jsDocForEnum(enum_) + '\n' : '' + const description = `${ + enum_.documentation && settings.data.docPropagation.GraphQLDocs ? `'${enum_.documentation}'` : 'undefined' + }` return endent` - ${jsDocForEnum(enum_)} - interface ${enum_.name} { + ${jsdoc}interface ${enum_.name} { name: '${enum_.name}' - description: ${enum_.documentation ? `'${enum_.documentation}'` : 'undefined'} + description: ${description} members: [${enum_.values.map((value) => `'${value.name}'`).join(', ')}] } ` } -function renderTypeScriptDeclarationForModel(model: DMMF.Model): string { +function renderTypeScriptDeclarationForModel(model: DMMF.Model, settings: Gentime.Settings): string { + const jsdoc = settings.data.docPropagation.JSDoc ? jsDocForModel(model) + '\n' : '' + const description = `${ + model.documentation && settings.data.docPropagation.GraphQLDocs ? `'${model.documentation}'` : 'undefined' + }` return endent` - ${jsDocForModel(model)} - interface ${model.name} { + ${jsdoc}interface ${model.name} { $name: '${model.name}' - $description: ${model.documentation ? `'${model.documentation}'` : 'undefined'} - ${renderTypeScriptDeclarationForModelFields(model)} + $description: ${description} + ${renderTypeScriptDeclarationForModelFields(model, settings)} } ` } -function renderTypeScriptDeclarationForModelFields(model: DMMF.Model): string { - return model.fields.map((field) => renderTypeScriptDeclarationForField({ field, model })).join('\n') +function renderTypeScriptDeclarationForModelFields(model: DMMF.Model, settings: Gentime.Settings): string { + return model.fields + .map((field) => renderTypeScriptDeclarationForField({ field, model, settings })) + .join('\n') } function renderTypeScriptDeclarationForField({ field, model, + settings, }: { field: DMMF.Field model: DMMF.Model + settings: Gentime.Settings }): string { + const jsdoc = settings.data.docPropagation.JSDoc ? jsDocForField({ field, model }) + '\n' : '' + const description = `${ + field.documentation && settings.data.docPropagation.GraphQLDocs ? `string` : `undefined` + }` return endent` - ${jsDocForField({ field, model })} - ${field.name}: { + ${jsdoc}${field.name}: { /** * The name of this field. */ @@ -160,12 +176,12 @@ function renderTypeScriptDeclarationForField({ /** * The type of this field. */ - type: ${renderNexusType2(field)} + type: ${renderNexusType2(field, settings)} /** * The documentation of this field. */ - description: ${field.documentation ? `string` : `undefined`} + description: ${description} /** * The resolver of this field @@ -175,8 +191,8 @@ function renderTypeScriptDeclarationForField({ ` } -function renderNexusType2(field: DMMF.Field): string { - const graphqlType = fieldTypeToGraphQLType(field) +function renderNexusType2(field: DMMF.Field, settings: Gentime.Settings): string { + const graphqlType = fieldTypeToGraphQLType(field, settings.data) if (field.isList && field.isRequired) { return endent` @@ -197,17 +213,26 @@ function renderNexusType2(field: DMMF.Field): string { } } -/** Map the fields type to a GraphQL type */ -export function fieldTypeToGraphQLType(field: DMMF.Field): LiteralUnion { +/** + * Map the fields type to a GraphQL type. + * + * @remarks The `settings` param type uses settings data instead of setset instance because this helper + * is used at runtime too where we don't have a Setset instane for gentime. + */ +export function fieldTypeToGraphQLType( + field: DMMF.Field, + settings: Gentime.SettingsData +): LiteralUnion { const fieldKind = field.kind switch (fieldKind) { case 'scalar': { const typeName = field.type as PrismaScalarType - // TODO Allow user to configure this. Maybe some users want Prisma `Int @id` to be GraphQL `ID`. - if (field.isId && field.type === 'String') { - return StandardgraphQLScalarTypes.ID + if (field.isId) { + if (field.type === 'String' || (field.type === 'Int' && settings.projectIdIntToGraphQL === 'ID')) { + return StandardgraphQLScalarTypes.ID + } } switch (typeName) { diff --git a/src/generator/models/javascript.ts b/src/generator/models/javascript.ts index 672cc2b3f..06ba3f824 100644 --- a/src/generator/models/javascript.ts +++ b/src/generator/models/javascript.ts @@ -4,11 +4,13 @@ import { chain, lowerFirst } from 'lodash' import * as Nexus from 'nexus' import { NexusEnumTypeConfig, NexusListDef, NexusNonNullDef, NexusNullDef } from 'nexus/dist/core' import { MaybePromise, RecordUnknown, Resolver } from '../../helpers/utils' +import { Gentime } from '../gentime/settingsSingleton' import { buildWhereUniqueInput, findMissingUniqueIdentifiers, resolveUniqueIdentifiers, } from '../helpers/constraints' +import { Runtime } from '../runtime/settingsSingleton' import { ModuleSpec } from '../types' import { fieldTypeToGraphQLType } from './declaration' @@ -27,18 +29,42 @@ type NexusTypeDefConfigurations = Record< NexusObjectTypeDefConfiguration | NexusEnumTypeDefConfiguration > +export type Settings = { + runtime: Runtime.Settings + gentime: Gentime.SettingsData + internal: { + /** + * The import ID of prisma client. + * + * @remarks Used to get a class reference to do an instance check for runtime validation reasons. + * @default @prisma/client + */ + prismaClientImport: string + } +} + /** * Create the module specification for the JavaScript runtime. */ -export function createModuleSpec(): ModuleSpec { +export function createModuleSpec(gentimeSettings: Gentime.Settings): ModuleSpec { return { fileName: 'index.js', content: endent` const { getPrismaClientDmmf } = require('../helpers/prisma') const ModelsGenerator = require('../generator/models') + const { Runtime } = require('../generator/runtime/settingsSingleton') + + const gentimeSettings = ${JSON.stringify(gentimeSettings.data, null, 2)} const dmmf = getPrismaClientDmmf() - const models = ModelsGenerator.JS.createNexusTypeDefConfigurations(dmmf) + + const models = ModelsGenerator.JS.createNexusTypeDefConfigurations(dmmf, { + runtime: Runtime.settings, + gentime: gentimeSettings, + internal: { + prismaClientImport: '@prisma/client', + } + }) module.exports = models `, @@ -47,34 +73,14 @@ export function createModuleSpec(): ModuleSpec { export function createNexusTypeDefConfigurations( dmmf: DMMF.Document, - settings: Settings = {} + settings: Settings ): NexusTypeDefConfigurations { - const configuration = resolveSettings(settings) - return { - ...createNexusObjectTypeDefConfigurations(dmmf, configuration), - ...createNexusEnumTypeDefConfigurations(dmmf), - } -} - -function resolveSettings(settings: Settings): Configuration { return { - prismaClientImport: settings.prismaClientImport ?? '@prisma/client', + ...createNexusObjectTypeDefConfigurations(dmmf, settings), + ...createNexusEnumTypeDefConfigurations(dmmf, settings), } } -type Settings = { - /** - * The import ID of prisma client. - * - * @default @prisma/client - */ - prismaClientImport?: string -} - -type Configuration = { - prismaClientImport: string -} - type NexusObjectTypeDefConfigurations = Record type NexusObjectTypeDefConfiguration = Record< @@ -94,20 +100,20 @@ type NexusObjectTypeDefConfiguration = Record< */ function createNexusObjectTypeDefConfigurations( dmmf: DMMF.Document, - configuration: Configuration + settings: Settings ): NexusObjectTypeDefConfigurations { return chain(dmmf.datamodel.models) .map((model) => { return { $name: model.name, - $description: model.documentation, + $description: settings.gentime.docPropagation.GraphQLDocs ? model.documentation : undefined, ...chain(model.fields) .map((field) => { return { name: field.name, - type: prismaFieldToNexusType(field), - description: field.documentation, - resolve: prismaFieldToNexusResolver(model, field, configuration), + type: prismaFieldToNexusType(field, settings), + description: settings.gentime.docPropagation.GraphQLDocs ? field.documentation : undefined, + resolve: prismaFieldToNexusResolver(model, field, settings), } }) .keyBy('name') @@ -120,8 +126,8 @@ function createNexusObjectTypeDefConfigurations( // Complex return type I don't really understand how to easily work with manually. // eslint-disable-next-line -export function prismaFieldToNexusType(field: DMMF.Field) { - const graphqlType = fieldTypeToGraphQLType(field) +export function prismaFieldToNexusType(field: DMMF.Field, settings: Settings) { + const graphqlType = fieldTypeToGraphQLType(field, settings.gentime) if (field.isList) { return Nexus.nonNull(Nexus.list(Nexus.nonNull(graphqlType))) @@ -135,7 +141,7 @@ export function prismaFieldToNexusType(field: DMMF.Field) { export function prismaFieldToNexusResolver( model: DMMF.Model, field: DMMF.Field, - configuration: Configuration + settings: Settings ): undefined | Resolver { /** * Allow Nexus default resolver to handle resolving scalars. @@ -184,19 +190,19 @@ export function prismaFieldToNexusResolver( } // eslint-disable-next-line - const PrismaClientPackage = require(configuration.prismaClientImport) + const PrismaClientPackage = require(settings.internal.prismaClientImport) // eslint-disable-next-line - if (!(ctx.prisma instanceof PrismaClientPackage.PrismaClient)) { + if (!(ctx[settings.runtime.data.prismaClientContextField] instanceof PrismaClientPackage.PrismaClient)) { // TODO rich errors throw new Error( - `The GraphQL context.prisma value is not an instance of the Prisma Client (imported from ${configuration.prismaClientImport}).` + `The GraphQL context.${settings.runtime.data.prismaClientContextField} value is not an instance of the Prisma Client (class reference for check imported from ${settings.internal.prismaClientImport}).` ) } const propertyModelName = lowerFirst(model.name) // eslint-disable-next-line @typescript-eslint/no-explicit-any - const prisma: any = ctx.prisma + const prisma: any = ctx[settings.runtime.data.prismaClientContextField] // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access const prismaModel = prisma[propertyModelName] @@ -228,13 +234,16 @@ type NexusEnumTypeDefConfiguration = AnyNexusEnumTypeConfig /** * Create Nexus enum type definition configurations for Prisma enums found in the given DMMF. */ -function createNexusEnumTypeDefConfigurations(dmmf: DMMF.Document): NexusEnumTypeDefConfigurations { +function createNexusEnumTypeDefConfigurations( + dmmf: DMMF.Document, + settings: Settings +): NexusEnumTypeDefConfigurations { return chain(dmmf.datamodel.enums) .map( (enum_): AnyNexusEnumTypeConfig => { return { name: enum_.name, - description: enum_.documentation, + description: settings.gentime.docPropagation.GraphQLDocs ? enum_.documentation : undefined, members: enum_.values.map((val) => val.name), } } diff --git a/src/generator/runtime/settingsSingleton.ts b/src/generator/runtime/settingsSingleton.ts new file mode 100644 index 000000000..8c83667ad --- /dev/null +++ b/src/generator/runtime/settingsSingleton.ts @@ -0,0 +1,30 @@ +import * as Setset from 'setset' + +export namespace Runtime { + export type SettingsInput = { + /** + * The name of the GraphQL context field to get an instance of Prisma Client from. + * + * This instance of Prisma Client is accessed in the default resolvers for relational fields. + * + * @default prisma + */ + prismaClientContextField?: string + } + + export type SettingsData = Setset.InferDataFromInput + + export type Settings = Setset.Manager + + export const settings = Setset.create({ + fields: { + prismaClientContextField: { + initial: () => 'prisma', + }, + }, + }) + + export function changeSettings(input: Setset.UserInput): Settings { + return settings.change(input) + } +} diff --git a/src/generator/types.ts b/src/generator/types.ts index a089fef7b..0ae9e2360 100644 --- a/src/generator/types.ts +++ b/src/generator/types.ts @@ -2,6 +2,3 @@ export type ModuleSpec = { fileName: string content: string } - -// eslint-disable-next-line @typescript-eslint/ban-types -export type Configuration = {} diff --git a/src/plugin.ts b/src/plugin.ts deleted file mode 100644 index 07c703acd..000000000 --- a/src/plugin.ts +++ /dev/null @@ -1,25 +0,0 @@ -import {} from '@prisma/generator-helper' -import endent from 'endent' -import { PrismaClient } from '@prisma/client' -import * as Nexus from 'nexus' -import { d } from './helpers/debugNexusPrisma' -import { SettingsInput, change } from './settings' - -throw new Error(endent` - Nexus Prisma is currently only available as a Prisma generator. -`) - -export function plugin(settingsInput?: SettingsInput): Nexus.core.NexusPlugin { - return Nexus.plugin({ - name: 'nexus-prisma', - onInstall() { - d('nexus plugin onInstall') - const settingsData = change({ - ...settingsInput, - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call - prisma: new PrismaClient(), - }).data - settingsData - }, - }) -} diff --git a/src/settings.ts b/src/settings.ts deleted file mode 100644 index 7fc05603a..000000000 --- a/src/settings.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { PrismaClient } from '@prisma/client' -import * as Setset from 'setset' - -export type SettingsInput = { - prisma?: PrismaClient -} - -export type SettingsData = Setset.InferDataFromInput - -export type Settings = Setset.Manager - -export const settings = Setset.create({ - fields: {}, -}) - -export const change = (input: Setset.UserInput): Settings => { - return settings.change(input) -} diff --git a/tests/__helpers__/helpers.ts b/tests/__helpers__/helpers.ts new file mode 100644 index 000000000..92b051dc7 --- /dev/null +++ b/tests/__helpers__/helpers.ts @@ -0,0 +1,7 @@ +import * as fs from 'fs-jetpack' + +export function assertBuildPresent() { + if (fs.exists('../../dist')) { + throw new Error(`Please build package before running this test`) + } +} diff --git a/tests/__helpers__/testProject.ts b/tests/__helpers__/testProject.ts new file mode 100644 index 000000000..7f7fda600 --- /dev/null +++ b/tests/__helpers__/testProject.ts @@ -0,0 +1,121 @@ +import execa from 'execa' +import * as fs from 'fs-jetpack' +import { FSJetpack } from 'fs-jetpack/types' +import { GraphQLClient } from 'graphql-request' +import { merge } from 'lodash' +import { PackageJson, TsConfigJson } from 'type-fest' + +export interface TestProject { + fs: FSJetpack + info: TestProjectInfo + run(command: string, options?: execa.SyncOptions): execa.ExecaSyncReturnValue + runAsync(command: string, options?: execa.SyncOptions): execa.ExecaChildProcess + runOrThrow(command: string, options?: execa.SyncOptions): execa.ExecaSyncReturnValue + client: GraphQLClient +} + +export class TestProjectInfo { + isReusing: boolean + isReusingEnabled: boolean + + private settings = { + infoFilPath: 'node_modules/.testProject/data.json', + } + + constructor() { + this.isReusingEnabled = Boolean(process.env.test_project_reuse) + this.isReusing = this.isReusingEnabled && fs.exists(this.settings.infoFilPath) !== false + } + + get(): { dir: string } | null { + if (!process.env.test_project_reuse) return null + return fs.read(this.settings.infoFilPath, 'json') ?? null + } + + getOrSetGet(): { dir: string } { + const testProjectInfo = this.get() + if (testProjectInfo) { + return testProjectInfo + } else { + const info = { dir: fs.tmpDir().cwd() } + this.set(info) + return info + } + } + + set(info: { dir: string }): void { + fs.write(this.settings.infoFilPath, info, { jsonIndent: 2 }) + } +} + +export function setupTestProject({ + packageJson, + tsconfigJson, +}: { + packageJson?: PackageJson + tsconfigJson?: TsConfigJson +} = {}): TestProject { + const tpi = new TestProjectInfo() + + /** + * Allow reusing a test project directory. This can be helpful when debugging things. + */ + let fs_ = tpi.isReusingEnabled ? fs.cwd(tpi.getOrSetGet().dir) : fs.tmpDir() + + fs_.write( + 'package.json', + merge( + { + name: 'some-test-project', + version: '1.0.0', + }, + packageJson + ) + ) + + fs_.write( + 'tsconfig.json', + merge( + { + compilerOptions: { + strict: true, + target: 'ES2018', + module: 'CommonJS', + moduleResolution: 'node', + rootDir: 'src', + outDir: 'build', + esModuleInterop: true, // for ApolloServer b/c ws dep :( + }, + include: ['src'], + } as TsConfigJson, + tsconfigJson + ) + ) + + const api: TestProject = { + fs: fs_, + info: tpi, + run(command, options) { + return execa.commandSync(command, { + reject: false, + ...options, + cwd: fs_.cwd(), + }) + }, + runOrThrow(command, options) { + return execa.commandSync(command, { + ...options, + cwd: fs_.cwd(), + }) + }, + runAsync(command, options) { + return execa.command(command, { + ...options, + cwd: fs_.cwd(), + }) + }, + client: new GraphQLClient('http://localhost:4000'), + } + + return api +} diff --git a/tests/__helpers__.ts b/tests/__helpers__/testers.ts similarity index 64% rename from tests/__helpers__.ts rename to tests/__helpers__/testers.ts index 1efe28099..158e1ab43 100644 --- a/tests/__helpers__.ts +++ b/tests/__helpers__/testers.ts @@ -2,16 +2,21 @@ import * as PrismaSDK from '@prisma/sdk' import endent from 'endent' import execa from 'execa' import * as fs from 'fs-jetpack' -import { FSJetpack } from 'fs-jetpack/types' import { DocumentNode, execute, printSchema } from 'graphql' -import { GraphQLClient } from 'graphql-request' -import { merge } from 'lodash' import { core } from 'nexus' import { AllNexusTypeDefs } from 'nexus/dist/core' -import { PackageJson, TsConfigJson } from 'type-fest' -import { generateRuntime } from '../src/generator/generate' -import * as ModelsGenerator from '../src/generator/models' -import { ModuleSpec } from '../src/generator/types' +import { generateRuntime } from '../../src/generator/generate' +import { Gentime } from '../../src/generator/gentime/settingsSingleton' +import * as ModelsGenerator from '../../src/generator/models' +import { Settings } from '../../src/generator/models/javascript' +import { Runtime } from '../../src/generator/runtime/settingsSingleton' +import { ModuleSpec } from '../../src/generator/types' + +const settingsDefaults: Settings = { + gentime: Gentime.settings.data, + internal: { prismaClientImport: '@prisma/client' }, + runtime: Runtime.settings, +} /** * Define Nexus type definitions based on the Nexus Prisma configurations @@ -87,7 +92,7 @@ export function testGraphqlSchema(params: { datamodel: createPrismaSchema({ content: params.datasourceSchema }), }) - const nexusPrisma = ModelsGenerator.JS.createNexusTypeDefConfigurations(dmmf) as any + const nexusPrisma = ModelsGenerator.JS.createNexusTypeDefConfigurations(dmmf, settingsDefaults) as any const { schema } = await core.generateSchema.withArtifacts({ types: params.apiSchema(nexusPrisma), @@ -173,7 +178,10 @@ export async function integrationTest({ }) const nexusPrisma = ModelsGenerator.JS.createNexusTypeDefConfigurations(dmmf, { - prismaClientImport: prismaClientImportId, + ...settingsDefaults, + internal: { + prismaClientImport: prismaClientImportId, + }, }) as any const { schema } = await core.generateSchema.withArtifacts({ @@ -227,131 +235,10 @@ export async function generateModules(content: string): Promise<{ indexjs: strin datamodel: prismaSchemaContents, }) - const [indexjs, indexdts] = generateRuntime(dmmf) as [ModuleSpec, ModuleSpec] + const [indexjs, indexdts] = generateRuntime(dmmf, Gentime.settings) as [ModuleSpec, ModuleSpec] return { indexdts: indexdts.content, indexjs: indexjs.content, } } - -export class TestProjectInfo { - isReusing: boolean - isReusingEnabled: boolean - - private settings = { - infoFilPath: 'node_modules/.testProject/data.json', - } - - constructor() { - this.isReusingEnabled = Boolean(process.env.test_project_reuse) - this.isReusing = this.isReusingEnabled && fs.exists(this.settings.infoFilPath) !== false - } - - get(): { dir: string } | null { - if (!process.env.test_project_reuse) return null - return fs.read(this.settings.infoFilPath, 'json') ?? null - } - - getOrSetGet(): { dir: string } { - const testProjectInfo = this.get() - if (testProjectInfo) { - return testProjectInfo - } else { - const info = { dir: fs.tmpDir().cwd() } - this.set(info) - return info - } - } - - set(info: { dir: string }): void { - fs.write(this.settings.infoFilPath, info, { jsonIndent: 2 }) - } -} - -export function setupTestProject({ - packageJson, - tsconfigJson, -}: { - packageJson?: PackageJson - tsconfigJson?: TsConfigJson -} = {}): TestProject { - const tpi = new TestProjectInfo() - - /** - * Allow reusing a test project directory. This can be helpful when debugging things. - */ - let fs_ = tpi.isReusingEnabled ? fs.cwd(tpi.getOrSetGet().dir) : fs.tmpDir() - - fs_.write( - 'package.json', - merge( - { - name: 'some-test-project', - version: '1.0.0', - }, - packageJson - ) - ) - - fs_.write( - 'tsconfig.json', - merge( - { - compilerOptions: { - strict: true, - target: 'ES2018', - module: 'CommonJS', - moduleResolution: 'node', - rootDir: 'src', - outDir: 'build', - esModuleInterop: true, // for ApolloServer b/c ws dep :( - }, - include: ['src'], - } as TsConfigJson, - tsconfigJson - ) - ) - - const api: TestProject = { - fs: fs_, - info: tpi, - run(command, options) { - return execa.commandSync(command, { - reject: false, - ...options, - cwd: fs_.cwd(), - }) - }, - runOrThrow(command, options) { - return execa.commandSync(command, { - ...options, - cwd: fs_.cwd(), - }) - }, - runAsync(command, options) { - return execa.command(command, { - ...options, - cwd: fs_.cwd(), - }) - }, - client: new GraphQLClient('http://localhost:4000'), - } - - return api -} - -export interface TestProject { - fs: FSJetpack - info: TestProjectInfo - run(command: string, options?: execa.SyncOptions): execa.ExecaSyncReturnValue - runAsync(command: string, options?: execa.SyncOptions): execa.ExecaChildProcess - runOrThrow(command: string, options?: execa.SyncOptions): execa.ExecaSyncReturnValue - client: GraphQLClient -} - -export function assertBuildPresent() { - if (fs.exists('../../dist')) { - throw new Error(`Please build package before running this test`) - } -} diff --git a/tests/e2e/e2e.test.ts b/tests/e2e/e2e.test.ts index 80e4b1564..c670bf4a4 100644 --- a/tests/e2e/e2e.test.ts +++ b/tests/e2e/e2e.test.ts @@ -4,7 +4,9 @@ import * as Execa from 'execa' import { gql } from 'graphql-request' import stripAnsi from 'strip-ansi' import { inspect } from 'util' -import { assertBuildPresent, createPrismaSchema, setupTestProject, TestProject } from '../__helpers__' +import { assertBuildPresent } from '../__helpers__/helpers' +import { createPrismaSchema } from '../__helpers__/testers' +import { setupTestProject, TestProject } from '../__helpers__/testProject' const d = debug('e2e') diff --git a/tests/integration/json.test.ts b/tests/integration/json.test.ts index 8ab374a80..da1fea878 100644 --- a/tests/integration/json.test.ts +++ b/tests/integration/json.test.ts @@ -2,7 +2,7 @@ import endent from 'endent' import gql from 'graphql-tag' import { list, objectType, queryType } from 'nexus' import NexusPrismaScalars from '../../scalars' -import { testIntegration } from '../__helpers__' +import { testIntegration } from '../__helpers__/testers' testIntegration({ skip: true, // integration test currently only works against SQLite which doesn't support JSON diff --git a/tests/integration/relation1To1.test.ts b/tests/integration/relation1To1.test.ts index ccc600243..5fd5a04ee 100644 --- a/tests/integration/relation1To1.test.ts +++ b/tests/integration/relation1To1.test.ts @@ -1,6 +1,6 @@ import { gql } from 'graphql-tag' import { nonNull, objectType, queryType } from 'nexus' -import { testIntegration } from '../__helpers__' +import { testIntegration } from '../__helpers__/testers' testIntegration({ description: 'can project user-to-profile relationship', diff --git a/tests/integration/relation1ToN.test.ts b/tests/integration/relation1ToN.test.ts index 6a197835c..f4b16e6db 100644 --- a/tests/integration/relation1ToN.test.ts +++ b/tests/integration/relation1ToN.test.ts @@ -1,7 +1,7 @@ import { gql } from 'graphql-tag' import { objectType, queryType } from 'nexus' import { Specs } from '../specs' -import { testIntegration } from '../__helpers__' +import { testIntegration } from '../__helpers__/testers' testIntegration({ description: 'can project user-to-posts relationship', diff --git a/tests/lib/peerDepValidator.test.ts b/tests/lib/peerDepValidator.test.ts index 0fc6e75cc..1456a6a95 100644 --- a/tests/lib/peerDepValidator.test.ts +++ b/tests/lib/peerDepValidator.test.ts @@ -2,7 +2,8 @@ import endent from 'endent' import * as Execa from 'execa' import { merge, omit } from 'lodash' import { PackageJson } from 'type-fest' -import { assertBuildPresent, setupTestProject, TestProject } from '../__helpers__' +import { assertBuildPresent } from '../__helpers__/helpers' +import { setupTestProject, TestProject } from '../__helpers__/testProject' /** Setup */ diff --git a/tests/specs.ts b/tests/specs.ts index 04053aeef..1dad12a88 100644 --- a/tests/specs.ts +++ b/tests/specs.ts @@ -1,6 +1,6 @@ import gql from 'graphql-tag' import { objectType, queryType } from 'nexus' -import { IntegrationTestSpec } from './__helpers__' +import { IntegrationTestSpec } from './__helpers__/testers' export namespace Specs { export const relation1ToNReverse: IntegrationTestSpec = { diff --git a/tests/unit/customScalarsModule.test.ts b/tests/unit/customScalarsModule.test.ts index 109b2c56b..55f8d936f 100644 --- a/tests/unit/customScalarsModule.test.ts +++ b/tests/unit/customScalarsModule.test.ts @@ -1,5 +1,5 @@ -import NexusPrismaScalars, * as NexusPrismaScalarsNS from '../../scalars' -import { assertBuildPresent } from '../__helpers__' +import NexusPrismaScalars, * as NexusPrismaScalarsNS from '../../src/entrypoints/scalars' +import { assertBuildPresent } from '../__helpers__/helpers' assertBuildPresent() diff --git a/tests/unit/graphqlSchema/enum.test.ts b/tests/unit/graphqlSchema/enum.test.ts index 8b5153ddc..566db545e 100644 --- a/tests/unit/graphqlSchema/enum.test.ts +++ b/tests/unit/graphqlSchema/enum.test.ts @@ -1,6 +1,6 @@ import endent from 'endent' import { enumType } from 'nexus' -import { testGraphqlSchema } from '../../__helpers__' +import { testGraphqlSchema } from '../../__helpers__/testers' testGraphqlSchema({ description: 'When an enum is defined in the Prisma schema it can be projected into the GraphQL API', diff --git a/tests/unit/graphqlSchema/json.test.ts b/tests/unit/graphqlSchema/json.test.ts index 22f9a83c8..820a6e345 100644 --- a/tests/unit/graphqlSchema/json.test.ts +++ b/tests/unit/graphqlSchema/json.test.ts @@ -1,7 +1,7 @@ import endent from 'endent' import { objectType } from 'nexus' import NexusPrismaScalars from '../../../scalars' -import { testGraphqlSchema } from '../../__helpers__' +import { testGraphqlSchema } from '../../__helpers__/testers' testGraphqlSchema({ description: 'When a JSON field is defined in the Prisma schema it can be projected into the GraphQL API', diff --git a/tests/unit/graphqlSchema/relation1ToN.test.ts b/tests/unit/graphqlSchema/relation1ToN.test.ts index 2aa8329ea..d028d55a7 100644 --- a/tests/unit/graphqlSchema/relation1ToN.test.ts +++ b/tests/unit/graphqlSchema/relation1ToN.test.ts @@ -1,5 +1,5 @@ import { Specs } from '../../specs' -import { testGraphqlSchema } from '../../__helpers__' +import { testGraphqlSchema } from '../../__helpers__/testers' testGraphqlSchema(Specs.relation1ToNReverse) testGraphqlSchema(Specs.relation1ToNReverseAndOptional) diff --git a/tests/unit/typescriptDeclarationFile/enum.test.ts b/tests/unit/typescriptDeclarationFile/enum.test.ts index 63b2b0cfd..e2a58a9f3 100644 --- a/tests/unit/typescriptDeclarationFile/enum.test.ts +++ b/tests/unit/typescriptDeclarationFile/enum.test.ts @@ -1,5 +1,5 @@ import endent from 'endent' -import { testGeneratedModules } from '../../__helpers__' +import { testGeneratedModules } from '../../__helpers__/testers' testGeneratedModules({ description: 'An enum maps to a Nexus enum type definition', diff --git a/tests/unit/typescriptDeclarationFile/enumDoc.test.ts b/tests/unit/typescriptDeclarationFile/enumDoc.test.ts index f102142aa..6df077907 100644 --- a/tests/unit/typescriptDeclarationFile/enumDoc.test.ts +++ b/tests/unit/typescriptDeclarationFile/enumDoc.test.ts @@ -1,5 +1,5 @@ import endent from 'endent' -import { testGeneratedModules } from '../../__helpers__' +import { testGeneratedModules } from '../../__helpers__/testers' testGeneratedModules({ description: diff --git a/tests/unit/typescriptDeclarationFile/modelDocumentation.test.ts b/tests/unit/typescriptDeclarationFile/modelDocumentation.test.ts index 5720b17c9..87c926bfc 100644 --- a/tests/unit/typescriptDeclarationFile/modelDocumentation.test.ts +++ b/tests/unit/typescriptDeclarationFile/modelDocumentation.test.ts @@ -1,4 +1,4 @@ -import { testGeneratedModules } from '../../__helpers__' +import { testGeneratedModules } from '../../__helpers__/testers' testGeneratedModules({ description: diff --git a/tests/unit/typescriptDeclarationFile/modelRelationFields.test.ts b/tests/unit/typescriptDeclarationFile/modelRelationFields.test.ts index 1bca682ed..936762054 100644 --- a/tests/unit/typescriptDeclarationFile/modelRelationFields.test.ts +++ b/tests/unit/typescriptDeclarationFile/modelRelationFields.test.ts @@ -1,4 +1,4 @@ -import { testGeneratedModules } from '../../__helpers__' +import { testGeneratedModules } from '../../__helpers__/testers' testGeneratedModules({ description: 'A model relation field projects a default resolve function', diff --git a/tests/unit/typescriptDeclarationFile/modelScalarFields.test.ts b/tests/unit/typescriptDeclarationFile/modelScalarFields.test.ts index 9b932716e..cc602b097 100644 --- a/tests/unit/typescriptDeclarationFile/modelScalarFields.test.ts +++ b/tests/unit/typescriptDeclarationFile/modelScalarFields.test.ts @@ -1,4 +1,4 @@ -import { testGeneratedModules } from '../../__helpers__' +import { testGeneratedModules } from '../../__helpers__/testers' testGeneratedModules({ description: 'A model field with type String, attribute @id, maps to GraphQL ID scalar', diff --git a/yarn.lock b/yarn.lock index d4d88e7cf..8a4266561 100644 --- a/yarn.lock +++ b/yarn.lock @@ -302,16 +302,6 @@ exec-sh "^0.3.2" minimist "^1.2.0" -"@endemolshinegroup/cosmiconfig-typescript-loader@^3.0.2": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@endemolshinegroup/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-3.0.2.tgz#eea4635828dde372838b0909693ebd9aafeec22d" - integrity sha512-QRVtqJuS1mcT56oHpVegkKBlgtWjXw/gHNWO3eL9oyB5Sc7HBoc2OLG/nYpVfT/Jejvo3NUrD0Udk7XgoyDKkA== - dependencies: - lodash.get "^4" - make-error "^1" - ts-node "^9" - tslib "^2" - "@eslint/eslintrc@^0.4.0": version "0.4.0" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.0.tgz#99cc0a0584d72f1df38b900fb062ba995f395547" @@ -1024,11 +1014,6 @@ dependencies: "@types/node" "*" -"@types/parse-json@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" - integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== - "@types/pluralize@^0.0.29": version "0.0.29" resolved "https://registry.yarnpkg.com/@types/pluralize/-/pluralize-0.0.29.tgz#6ffa33ed1fc8813c469b859681d09707eb40d03c" @@ -1969,17 +1954,6 @@ core-util-is@1.0.2, core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= -cosmiconfig@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.0.tgz#ef9b44d773959cae63ddecd122de23853b60f8d3" - integrity sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA== - dependencies: - "@types/parse-json" "^4.0.0" - import-fresh "^3.2.1" - parse-json "^5.0.0" - path-type "^4.0.0" - yaml "^1.10.0" - crc-32@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.0.tgz#cb2db6e29b88508e32d9dd0ec1693e7b41a18208" @@ -4254,11 +4228,6 @@ lodash.flatten@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8= -lodash.get@^4: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" - integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= - lodash.isplainobject@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" @@ -4318,7 +4287,7 @@ make-dir@3.1.0, make-dir@^3.0.0, make-dir@^3.0.2: dependencies: semver "^6.0.0" -make-error@1.x, make-error@^1, make-error@^1.1.1: +make-error@1.x, make-error@^1.1.1: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== @@ -6006,7 +5975,7 @@ ts-jest@26.5.6: semver "7.x" yargs-parser "20.x" -ts-node@^9, ts-node@^9.1.1: +ts-node@^9.1.1: version "9.1.1" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d" integrity sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg== @@ -6023,7 +5992,7 @@ tslib@^1.8.1, tslib@^1.9.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2, tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0, tslib@~2.2.0: +tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0, tslib@~2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.2.0.tgz#fb2c475977e35e241311ede2693cee1ec6698f5c" integrity sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w== @@ -6409,11 +6378,6 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml@^1.10.0: - version "1.10.2" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" - integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== - yargs-parser@20.x: version "20.2.7" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.7.tgz#61df85c113edfb5a7a4e36eb8aa60ef423cbc90a"