Skip to content

Commit

Permalink
feat: Allow add deprecation reason
Browse files Browse the repository at this point in the history
  • Loading branch information
unlight committed May 6, 2022
1 parent 197561b commit 432e8f1
Show file tree
Hide file tree
Showing 10 changed files with 425 additions and 189 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ module.exports = {
],
rules: {
// core
'consistent-return': [1, { treatUndefinedAsUnspecified: true }],
'consistent-return': [0, { treatUndefinedAsUnspecified: false }],
quotes: [1, 'single', { allowTemplateLiterals: true, avoidEscape: true }],
semi: [1, 'always'],
'max-lines': [1, { max: 300 }],
Expand Down
198 changes: 115 additions & 83 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ Generate object types, inputs, args, etc. from prisma schema file for usage with

## Features

- Generates only necessary imports
- Combines zoo of nested/nullable filters
- Does not generate resolvers, since it's application specific
- Generates only necessary imports
- Combines zoo of nested/nullable filters
- Does not generate resolvers, since it's application specific

## Install

Expand Down Expand Up @@ -40,8 +40,8 @@ npm install graphql-type-json prisma-graphql-type-decimal

```

- [graphql-type-json](https://github.com/taion/graphql-type-json)
- [prisma-graphql-type-decimal](https://github.com/unlight/prisma-graphql-type-decimal)
- [graphql-type-json](https://github.com/taion/graphql-type-json)
- [prisma-graphql-type-decimal](https://github.com/unlight/prisma-graphql-type-decimal)

Or write you own graphql scalar types, [read more on docs.nestjs.com](https://docs.nestjs.com/graphql/scalars).

Expand All @@ -59,10 +59,10 @@ Type: `string`
Default: `{model}/{name}.{type}.ts`
Possible tokens:

- `{model}` Model name in dashed case or 'prisma' if unknown
- `{name}` Dashed-case name of model/input/arg without suffix
- `{type}` Short type name (model, input, args, output)
- `{plural.type}` Plural short type name (models, inputs, enums)
- `{model}` Model name in dashed case or 'prisma' if unknown
- `{name}` Dashed-case name of model/input/arg without suffix
- `{type}` Short type name (model, input, args, output)
- `{plural.type}` Plural short type name (models, inputs, enums)

#### `tsConfigFilePath`

Expand Down Expand Up @@ -149,30 +149,30 @@ generator nestgraphql {

Where:

- `typeName` Full name or partial name of the class where need to choose input type.
Example: `UserCreateInput` full name, `WhereInput` partial name, matches `UserWhereInput`, `PostWhereInput`, etc.
- `property` Property of the class for which need to choose type. Special case name `ALL` means any / all properties.
- `pattern` Part of name (or full) of type which should be chosen, you can use
wild card or negate symbols, in this case pattern should starts with `match:`,
e.g. `match:*UncheckedCreateInput` see [outmatch](https://github.com/axtgr/outmatch#usage) for details.
- `typeName` Full name or partial name of the class where need to choose input type.
Example: `UserCreateInput` full name, `WhereInput` partial name, matches `UserWhereInput`, `PostWhereInput`, etc.
- `property` Property of the class for which need to choose type. Special case name `ALL` means any / all properties.
- `pattern` Part of name (or full) of type which should be chosen, you can use
wild card or negate symbols, in this case pattern should starts with `match:`,
e.g. `match:*UncheckedCreateInput` see [outmatch](https://github.com/axtgr/outmatch#usage) for details.

Example:

```ts
export type PostWhereInput = {
author?: XOR<UserRelationFilter, UserWhereInput>;
author?: XOR<UserRelationFilter, UserWhereInput>;
};
export type UserRelationFilter = {
is?: UserWhereInput;
isNot?: UserWhereInput;
is?: UserWhereInput;
isNot?: UserWhereInput;
};

export type UserWhereInput = {
AND?: Enumerable<UserWhereInput>;
OR?: Enumerable<UserWhereInput>;
NOT?: Enumerable<UserWhereInput>;
id?: StringFilter | string;
name?: StringFilter | string;
AND?: Enumerable<UserWhereInput>;
OR?: Enumerable<UserWhereInput>;
NOT?: Enumerable<UserWhereInput>;
id?: StringFilter | string;
name?: StringFilter | string;
};
```

Expand All @@ -190,8 +190,8 @@ generator nestgraphql {
```ts
@InputType()
export class PostWhereInput {
@Field(() => UserWhereInput, { nullable: true })
author?: UserWhereInput;
@Field(() => UserWhereInput, { nullable: true })
author?: UserWhereInput;
}
```

Expand All @@ -214,24 +214,24 @@ generator nestgraphql {

Where `{key}` any identifier to group values (written in [flatten](https://github.com/hughsk/flat) style)

- `decorate_{key}_type` - outmatch pattern to match class name
- `decorate_{key}_field` - outmatch pattern to match field name
- `decorate_{key}_from` - module specifier to import from (e.g `class-validator`)
- `decorate_{key}_name` - import name or name with namespace
- `decorate_{key}_defaultImport` - import as default
- `decorate_{key}_namespaceImport` - use this name as import namespace
- `decorate_{key}_namedImport` - named import (without namespace)
- `decorate_{key}_arguments` - arguments for decorator (if decorator need to be called as function)
Special tokens can be used:
- `{propertyType.0}` - field's type (TypeScript type annotation)
- `decorate_{key}_type` - outmatch pattern to match class name
- `decorate_{key}_field` - outmatch pattern to match field name
- `decorate_{key}_from` - module specifier to import from (e.g `class-validator`)
- `decorate_{key}_name` - import name or name with namespace
- `decorate_{key}_defaultImport` - import as default
- `decorate_{key}_namespaceImport` - use this name as import namespace
- `decorate_{key}_namedImport` - named import (without namespace)
- `decorate_{key}_arguments` - arguments for decorator (if decorator need to be called as function)
Special tokens can be used:
- `{propertyType.0}` - field's type (TypeScript type annotation)

Example of generated class:

```ts
@ArgsType()
export class CreateOneUserArgs {
@Field(() => UserCreateInput, { nullable: false })
data!: UserCreateInput;
@Field(() => UserCreateInput, { nullable: false })
data!: UserCreateInput;
}
```

Expand Down Expand Up @@ -259,10 +259,10 @@ import { Type } from 'class-transformer';

@ArgsType()
export class CreateOneUserArgs {
@Field(() => UserCreateInput, { nullable: false })
@ValidateNested()
@Type(() => UserCreateInput)
data!: UserCreateInput;
@Field(() => UserCreateInput, { nullable: false })
@ValidateNested()
@Type(() => UserCreateInput)
data!: UserCreateInput;
}
```

Expand Down Expand Up @@ -329,13 +329,45 @@ May generate:
import { GraphQLBigInt } from 'graphql-scalars';

export class BigIntFilter {
@Field(() => GraphQLBigInt, { nullable: true })
equals?: bigint | number;
@Field(() => GraphQLBigInt, { nullable: true })
equals?: bigint | number;
}
```

It will affect all inputs and outputs types (including models).

## Documentation and field options

Comments with double slash will projected to typescript code comments
and some `@Field()` decorator options

For example:

```prisma
model Product {
// Old description
// @deprecated Use new name instead
oldName
}
```

May produce:

```ts
@ObjectType()
export class Product {
/**
* Old description
* @deprecated Use new name instead
*/
@Field(() => String, {
description: 'Old description',
deprecationReason: 'Use new name instead',
})
oldName: string;
}
```

## Field Settings

Special directives in triple slash comments for more precise code generation.
Expand All @@ -352,9 +384,9 @@ see [outmatch](https://github.com/axtgr/outmatch#usage) for details.

Examples:

- `@HideField()` same as `@HideField({ output: true })`
- `@HideField({ input: true, output: true })`
- `@HideField({ match: 'UserCreate*Input' })`
- `@HideField()` same as `@HideField({ output: true })`
- `@HideField({ input: true, output: true })`
- `@HideField({ match: 'UserCreate*Input' })`

```prisma
model User {
Expand All @@ -373,24 +405,24 @@ May generate classes:
```ts
@ObjectType()
export class User {
@HideField()
password: string;
@HideField()
secret: string;
@Field(() => Date, { nullable: false })
createdAt: Date;
@HideField()
password: string;
@HideField()
secret: string;
@Field(() => Date, { nullable: false })
createdAt: Date;
}
```

```ts
@InputType()
export class UserCreateInput {
@Field()
password: string;
@HideField()
secret: string;
@HideField()
createdAt: Date;
@Field()
password: string;
@HideField()
secret: string;
@HideField()
createdAt: Date;
}
```

Expand Down Expand Up @@ -480,9 +512,9 @@ import * as Validator from 'class-validator';

@InputType()
export class UserCreateInput {
@Field(() => String, { nullable: false })
@Validator.MinLength(3)
name!: string;
@Field(() => String, { nullable: false })
@Validator.MinLength(3)
name!: string;
}
```

Expand Down Expand Up @@ -539,8 +571,8 @@ import * as Scalars from 'graphql-scalars';

@InputType()
export class UserCreateInput {
@Field(() => Scalars.GraphQLEmailAddress, { nullable: false })
email!: string;
@Field(() => Scalars.GraphQLEmailAddress, { nullable: false })
email!: string;
}
```
Expand Down Expand Up @@ -602,8 +634,8 @@ import * as TF from 'type-fest';

@ObjectType()
export class User {
@Field(() => GraphQLJSON)
data!: TF.JsonObject;
@Field(() => GraphQLJSON)
data!: TF.JsonObject;
}
```
Expand All @@ -629,9 +661,9 @@ May generate:
@Directive('@extends')
@Directive('@key(fields: "id")')
export class User {
@Field(() => ID, { nullable: false })
@Directive('@external')
id!: string;
@Field(() => ID, { nullable: false })
@Directive('@external')
id!: string;
}
```
Expand Down Expand Up @@ -671,21 +703,21 @@ export class User {}
## Similar Projects
- https://github.com/kimjbstar/prisma-class-generator
- https://github.com/odroe/nest-gql-mix
- https://github.com/rfermann/nestjs-prisma-graphql-generator
- https://github.com/madscience/graphql-codegen-nestjs
- https://github.com/wSedlacek/prisma-generators/tree/master/libs/nestjs
- https://github.com/EndyKaufman/typegraphql-prisma-nestjs
- https://github.com/MichalLytek/typegraphql-prisma
- https://github.com/kimjbstar/prisma-class-generator
- https://github.com/odroe/nest-gql-mix
- https://github.com/rfermann/nestjs-prisma-graphql-generator
- https://github.com/madscience/graphql-codegen-nestjs
- https://github.com/wSedlacek/prisma-generators/tree/master/libs/nestjs
- https://github.com/EndyKaufman/typegraphql-prisma-nestjs
- https://github.com/MichalLytek/typegraphql-prisma
## Resources
- Todo - https://github.com/unlight/prisma-nestjs-graphql/issues/2
- https://github.com/prisma/prisma/blob/main/packages/client/src/generation/TSClient/TSClient.ts
- https://ts-ast-viewer.com/
- https://github.com/unlight/nestjs-graphql-prisma-realworld-example-app
- https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-schema/data-model
- JSON type for the code first approach - https://github.com/nestjs/graphql/issues/111#issuecomment-631452899
- https://github.com/paljs/prisma-tools/tree/master/packages/plugins
- https://github.com/wasp-lang/wasp
- Todo - https://github.com/unlight/prisma-nestjs-graphql/issues/2
- https://github.com/prisma/prisma/blob/main/packages/client/src/generation/TSClient/TSClient.ts
- https://ts-ast-viewer.com/
- https://github.com/unlight/nestjs-graphql-prisma-realworld-example-app
- https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-schema/data-model
- JSON type for the code first approach - https://github.com/nestjs/graphql/issues/111#issuecomment-631452899
- https://github.com/paljs/prisma-tools/tree/master/packages/plugins
- https://github.com/wasp-lang/wasp
1 change: 1 addition & 0 deletions src/handlers/input-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ export function inputType(
arguments: [
isList ? `() => [${graphqlType}]` : `() => ${graphqlType}`,
JSON5.stringify({
...settings?.fieldArguments(),
nullable: !isRequired,
}),
],
Expand Down
9 changes: 6 additions & 3 deletions src/handlers/model-output-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
StatementStructures,
StructureKind,
} from 'ts-morph';
import { createComment } from '../helpers/create-comment';

import { getGraphqlImport } from '../helpers/get-graphql-import';
import { getOutputTypeName } from '../helpers/get-output-type-name';
Expand Down Expand Up @@ -67,7 +68,7 @@ export function modelOutputType(outputType: OutputType, args: EventArguments) {
});
if (documentation) {
if (!classStructure.leadingTrivia) {
classStructure.leadingTrivia = `/** ${documentation} */\n`;
classStructure.leadingTrivia = createComment(documentation);
}
objectTypeOptions.description = documentation;
}
Expand Down Expand Up @@ -147,14 +148,14 @@ export function modelOutputType(outputType: OutputType, args: EventArguments) {
});

if (typeof property.leadingTrivia === 'string' && modelField?.documentation) {
property.leadingTrivia += `/** ${modelField.documentation} */\n`;
property.leadingTrivia += createComment(modelField.documentation, settings);
}

classStructure.properties?.push(property);

if (propertySettings) {
importDeclarations.create({ ...propertySettings });
} else if (!propertySettings && propertyType.includes('Decimal')) {
} else if (propertyType.includes('Decimal')) {
importDeclarations.add('Decimal', '@prisma/client/runtime');
}

Expand All @@ -164,11 +165,13 @@ export function modelOutputType(outputType: OutputType, args: EventArguments) {
importDeclarations.add('HideField', nestjsGraphql);
property.decorators.push({ name: 'HideField', arguments: [] });
} else {
// Generate `@Field()` decorator
property.decorators.push({
name: 'Field',
arguments: [
isList ? `() => [${graphqlType}]` : `() => ${graphqlType}`,
JSON5.stringify({
...settings?.fieldArguments(),
nullable: Boolean(field.isNullable),
defaultValue: ['number', 'string', 'boolean'].includes(
typeof modelField?.default,
Expand Down
Loading

0 comments on commit 432e8f1

Please sign in to comment.