Skip to content

Commit

Permalink
feat(hide field): Allow hide field in type matching by pattern
Browse files Browse the repository at this point in the history
close: #37
  • Loading branch information
unlight committed Jul 2, 2021
1 parent 00412d2 commit 6c05123
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 14 deletions.
1 change: 1 addition & 0 deletions .cz-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ module.exports = {
],

scopes: [
{ name: 'hide field' },
{ name: 'configuration' },
{ name: 'custom decorators' },
{ name: 'compatibility' },
Expand Down
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,11 +237,15 @@ Removes field from GraphQL schema.
Alias: `@TypeGraphQL.omit(output: true)`

By default (without arguments) field will be decorated for hide only in output types (type in schema).
To hide input types add `input: true`.
To hide field in input types add `input: true`.
To hide field in specific type you can use glob pattern `match: string | string[]`
see [outmatch](https://github.com/axtgr/outmatch#usage) for details.

Examples:

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

```prisma
model User {
Expand All @@ -250,6 +254,8 @@ model User {
password String
/// @HideField({ output: true, input: true })
secret String
/// @HideField({ match: '@(User|Comment)Create*Input' })
createdAt DateTime @default(now())
}
```

Expand All @@ -262,6 +268,8 @@ export class User {
password: string;
@HideField()
secret: string;
@Field(() => Date, { nullable: false })
createdAt: Date;
}
```

Expand All @@ -272,6 +280,8 @@ export class UserCreateInput {
password: string;
@HideField()
secret: string;
@HideField()
createdAt: Date;
}
```

Expand Down
2 changes: 2 additions & 0 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ model Article {
description String
body String
tags Tag[]
/// @HideField({ match: '*Create*Input' })
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
favoritesCount Int @default(0)
Expand All @@ -72,6 +73,7 @@ model Article {
model Comment {
id String @id @default(cuid())
createdAt DateTime @default(now())
/// @HideField({ match: '*Update*Input' })
updatedAt DateTime @updatedAt
body String
author User @relation(fields: [authorId], references: [id])
Expand Down
2 changes: 1 addition & 1 deletion src/handlers/input-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ export function inputType(
// });
// }

if (settings?.hideInput) {
if (settings?.shouldHideField({ name: inputType.name, input: true })) {
importDeclarations.add('HideField', '@nestjs/graphql');
property.decorators?.push({ name: 'HideField', arguments: [] });
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/handlers/model-output-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ export function modelOutputType(outputType: OutputType, args: EventArguments) {
importDeclarations.add(customType.fieldType, customType.fieldModule);
}

if (settings?.hideOutput) {
if (settings?.shouldHideField({ name: outputType.name, output: true })) {
importDeclarations.add('HideField', nestjsGraphql);
property.decorators?.push({ name: 'HideField', arguments: [] });
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/handlers/output-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ export function outputType(outputType: OutputType, args: EventArguments) {
importDeclarations.add(customType.fieldType, customType.fieldModule);
}

if (settings?.hideOutput) {
if (settings?.shouldHideField({ name: outputType.name, output: true })) {
importDeclarations.add('HideField', nestjsGraphql);
property.decorators?.push({ name: 'HideField', arguments: [] });
} else {
Expand Down
42 changes: 33 additions & 9 deletions src/helpers/field-settings.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import JSON5 from 'json5';
import { merge, trim } from 'lodash';
import outmatch from 'outmatch';

import { GeneratorConfiguration } from '../types';

Expand All @@ -12,6 +13,7 @@ export type FieldSetting = {
arguments?: string[];
input: boolean;
output: boolean;
match?: (test: string) => boolean;
from: string;
namespace?: string;
defaultImport?: string | true;
Expand All @@ -20,12 +22,22 @@ export type FieldSetting = {
};

export class FieldSettings extends Array<FieldSetting> {
get hideInput() {
return this.some(s => s.name === 'HideField' && s.input);
}
shouldHideField({
name,
input = false,
output = false,
}: {
name: string;
input?: boolean;
output?: boolean;
}): boolean {
const hideField = this.find(s => s.name === 'HideField');

get hideOutput() {
return this.some(s => s.name === 'HideField' && s.output);
return Boolean(
(hideField?.input && input) ||
(hideField?.output && output) ||
hideField?.match?.(name),
);
}

getFieldType() {
Expand All @@ -46,7 +58,7 @@ export function createFieldSettings(args: {
const textLines = text.split('\n');
const documentationLines: string[] = [];
for (const line of textLines) {
const match = /^@(?<name>\w+(\.(\w+))?)\((?<args>.*?)\)/.exec(line);
const match = /^@(?<name>\w+(\.(\w+))?)\((?<args>.*)\)/.exec(line);
const name = match?.groups?.name;
if (!match || !name) {
documentationLines.push(line);
Expand Down Expand Up @@ -113,17 +125,29 @@ function hideFieldDecorator(match: RegExpExecArray) {
from: '@nestjs/graphql',
defaultImport: undefined,
namespaceImport: undefined,
match: undefined,
};
if (match.groups?.args) {
if (!match.groups?.args) {
result.output = true;
return result;
}

if (match.groups.args.includes('{') && match.groups.args.includes('}')) {
const options = parseArgs(match.groups.args) as Record<string, unknown>;
result.output = Boolean(options.output);
result.input = Boolean(options.input);
if (typeof options.match === 'string' || Array.isArray(options.match)) {
result.match = outmatch(options.match, { separator: false });
}
} else {
if (/output:\s*true/.test(match.groups.args)) {
result.output = true;
}
if (/input:\s*true/.test(match.groups.args)) {
result.input = true;
}
} else {
result.output = true;
}

return result;
}

Expand Down
62 changes: 62 additions & 0 deletions src/test/generate.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1291,6 +1291,61 @@ describe('hide field', () => {
// it('^', () => console.log(sourceFile.getText()));
});
});

describe('hide field using match', () => {
before(async () => {
({ project, sourceFiles } = await testGenerate({
schema: `
model User {
id String @id
/// @HideField({ match: '@(User|Comment)Create*Input' })
createdAt DateTime @default(now())
/// @HideField( { match: '*Update*Input' } )
updatedAt DateTime @updatedAt
}
`,
options: [`outputFilePattern = "{name}.{type}.ts"`],
}));
});

it('in model nothing should be hidden', () => {
setSourceFile('user.model.ts');
expect(p('createdAt')?.decorators).toHaveLength(1);
expect(d('createdAt')).toEqual(expect.objectContaining({ name: 'Field' }));
});

it('user-create-many.input', () => {
setSourceFile('user-create-many.input.ts');
expect(p('createdAt')?.decorators).toHaveLength(1);
expect(d('createdAt')).toEqual(
expect.objectContaining({ name: 'HideField' }),
);
});

it('user-create.input', () => {
setSourceFile('user-create.input.ts');
expect(p('createdAt')?.decorators).toHaveLength(1);
expect(d('createdAt')).toEqual(
expect.objectContaining({ name: 'HideField' }),
);
});

it('user-update-many-mutation.input', () => {
setSourceFile('user-update-many-mutation.input.ts');
expect(p('updatedAt')?.decorators).toHaveLength(1);
expect(d('updatedAt')).toEqual(
expect.objectContaining({ name: 'HideField' }),
);
});

it('user-update.input', () => {
setSourceFile('user-update.input.ts');
expect(p('updatedAt')?.decorators).toHaveLength(1);
expect(d('updatedAt')).toEqual(
expect.objectContaining({ name: 'HideField' }),
);
});
});
});

it('model with prisma keyword output', async () => {
Expand Down Expand Up @@ -1808,3 +1863,10 @@ describe('output without fields', () => {
expect(t('comments')).toEqual('() => Int');
});
});

// it('filePaths', () => {
// console.log(
// 'filePaths',
// sourceFiles.map(s => s.getBaseName()),
// );
// });

0 comments on commit 6c05123

Please sign in to comment.