nest-prisma_doc-gen 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config.type.js +16 -0
- package/dist/entities/dto-generator.js +7 -5
- package/dist/entities/entity-generator.js +4 -4
- package/dist/entities/field.js +8 -6
- package/dist/index.js +0 -1
- package/dist/main.js +8 -6
- package/dist/rules.js +1 -1
- package/dist/schemas/config.schema.json +79 -0
- package/dist/static.js +0 -22
- package/dist/testes.js +21 -0
- package/dist/types.js +1 -17
- package/dist/utils/config-loader.js +33 -0
- package/dist/utils/copy-schemas.js +10 -0
- package/dist/utils/loader.js +47 -0
- package/package.json +12 -8
- package/dist/entities/dto-generator.d.ts +0 -13
- package/dist/entities/entity-generator.d.ts +0 -12
- package/dist/entities/enum.d.ts +0 -22
- package/dist/entities/field.d.ts +0 -24
- package/dist/entities/model.d.ts +0 -11
- package/dist/field.type.d.ts +0 -7
- package/dist/file.d.ts +0 -11
- package/dist/helpers/helpers.d.ts +0 -14
- package/dist/helpers/loader.d.ts +0 -4
- package/dist/helpers/loader.js +0 -50
- package/dist/helpers/propeties.static.d.ts +0 -2
- package/dist/index.d.ts +0 -2
- package/dist/main.d.ts +0 -13
- package/dist/rules.d.ts +0 -11
- package/dist/static.d.ts +0 -6
- package/dist/types.d.ts +0 -79
- package/src/entities/dto-generator.ts +0 -61
- package/src/entities/entity-generator.ts +0 -55
- package/src/entities/enum.ts +0 -47
- package/src/entities/field.ts +0 -188
- package/src/entities/model.ts +0 -23
- package/src/entities/validator.ts +0 -17
- package/src/field.type.ts +0 -27
- package/src/file.ts +0 -34
- package/src/helpers/helpers.ts +0 -152
- package/src/helpers/loader.ts +0 -60
- package/src/helpers/propeties.static.ts +0 -3
- package/src/index.ts +0 -2
- package/src/main.ts +0 -68
- package/src/rules.ts +0 -31
- package/src/static.ts +0 -28
- package/src/types/global.d.ts +0 -1
- package/src/types.ts +0 -109
- package/tsconfig.build.json +0 -5
- package/tsconfig.json +0 -15
- /package/dist/{helpers → utils}/helpers.js +0 -0
- /package/dist/{helpers → utils}/propeties.static.js +0 -0
package/dist/static.d.ts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
export declare class Static {
|
|
2
|
-
static readonly AUTO_GENERATED_COMMENT: "// AUTO-GERADO: N\u00C3O EDITAR MANUALMENTE. SUJEITO A PAULADAS!";
|
|
3
|
-
static readonly STATIC_NAMES: readonly ["Alessandro", "Pablo", "Cláudio", "Thiago", "Guilherme", "Dalton", "Kaio", "Gustavo", "Cadu", "Neyanne", "John", "Matheus", "Davi"];
|
|
4
|
-
static getRandomString(values: string[]): string;
|
|
5
|
-
static getRandomNumber(min?: number, max?: number): number;
|
|
6
|
-
}
|
package/dist/types.d.ts
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
export type FieldKind = "scalar" | "object" | "enum";
|
|
2
|
-
type FieldDefaultName = "now" | "autoincrement" | "cuid";
|
|
3
|
-
export type FieldType = "entity" | "dto";
|
|
4
|
-
export type DbName = string | null;
|
|
5
|
-
export type Scalar = "String" | "Int" | "BigInt" | "Float" | "Decimal" | "Boolean" | "DateTime" | "Json" | "Bytes";
|
|
6
|
-
export type Field = {
|
|
7
|
-
name: string;
|
|
8
|
-
dbName: string;
|
|
9
|
-
kind: FieldKind;
|
|
10
|
-
isList: boolean;
|
|
11
|
-
isRequired: boolean;
|
|
12
|
-
isUnique: boolean;
|
|
13
|
-
isId: boolean;
|
|
14
|
-
isReadOnly: boolean;
|
|
15
|
-
hasDefaultValue: boolean;
|
|
16
|
-
type: Scalar;
|
|
17
|
-
isGenerated: boolean;
|
|
18
|
-
isUpdatedAt: boolean;
|
|
19
|
-
nativeType: any;
|
|
20
|
-
default?: FieldDefault | string;
|
|
21
|
-
};
|
|
22
|
-
export interface FieldDefault {
|
|
23
|
-
name: FieldDefaultName;
|
|
24
|
-
args: number[];
|
|
25
|
-
}
|
|
26
|
-
export type DocGenModel = {
|
|
27
|
-
name: string | null;
|
|
28
|
-
dbName: string | null;
|
|
29
|
-
schema: string | null;
|
|
30
|
-
readonly fields: Field[];
|
|
31
|
-
uniqueFields: string[][];
|
|
32
|
-
uniqueIndexes: ModelUniqueIndexes[];
|
|
33
|
-
primaryKey: null;
|
|
34
|
-
documentation?: string;
|
|
35
|
-
isGenerated?: boolean;
|
|
36
|
-
};
|
|
37
|
-
export type ModelUniqueIndexes = {
|
|
38
|
-
name: string | null;
|
|
39
|
-
fields: any[];
|
|
40
|
-
};
|
|
41
|
-
export declare class ValidatorBuilder {
|
|
42
|
-
decorator: ValidatorFactory | PropertyDecorator;
|
|
43
|
-
fields: string[];
|
|
44
|
-
constructor(decorator: PropertyDecorator, fields: string[]);
|
|
45
|
-
}
|
|
46
|
-
export declare class ApiExampleBuilder {
|
|
47
|
-
fields: string[];
|
|
48
|
-
example: string | boolean | number;
|
|
49
|
-
constructor(fields: string[], example: string | boolean | number);
|
|
50
|
-
}
|
|
51
|
-
export type Rules = {
|
|
52
|
-
ignore: string[];
|
|
53
|
-
examples: ApiExampleBuilder[];
|
|
54
|
-
validators: ValidatorBuilder[];
|
|
55
|
-
};
|
|
56
|
-
type ValidatorFactory = (...args: any[]) => PropertyDecorator;
|
|
57
|
-
export type Model = {
|
|
58
|
-
name: string;
|
|
59
|
-
dbName: string | null;
|
|
60
|
-
schema: string | null;
|
|
61
|
-
readonly fields: Field[];
|
|
62
|
-
uniqueFields: string[][];
|
|
63
|
-
uniqueIndexes: ModelUniqueIndexes[];
|
|
64
|
-
primaryKey: null;
|
|
65
|
-
documentation?: string;
|
|
66
|
-
isGenerated?: boolean;
|
|
67
|
-
};
|
|
68
|
-
export type ModelParams = {
|
|
69
|
-
model: Model;
|
|
70
|
-
examples: Map<string, ApiExampleBuilder>;
|
|
71
|
-
validators: Map<string, string[]>;
|
|
72
|
-
};
|
|
73
|
-
export type FieldParams = {
|
|
74
|
-
examples: Map<string, ApiExampleBuilder>;
|
|
75
|
-
validators: Map<string, string[]>;
|
|
76
|
-
field: Field;
|
|
77
|
-
fieldType: FieldType;
|
|
78
|
-
};
|
|
79
|
-
export {};
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { DocGenFile } from "../file.js";
|
|
2
|
-
import { Helper } from "../helpers/helpers.js";
|
|
3
|
-
import { Static } from "../static.js";
|
|
4
|
-
import { Model } from "../types.js";
|
|
5
|
-
import { DocGenField } from "./field.js";
|
|
6
|
-
|
|
7
|
-
export class DocGenDto {
|
|
8
|
-
name: string;
|
|
9
|
-
file: DocGenFile;
|
|
10
|
-
fields: DocGenField[] = [];
|
|
11
|
-
imports = new Set([`${Static.AUTO_GENERATED_COMMENT}`, `import { ApiProperty } from '@nestjs/swagger'`]);
|
|
12
|
-
classValidators = new Set<string>();
|
|
13
|
-
enums = new Set<string>();
|
|
14
|
-
|
|
15
|
-
constructor(model: Model) {
|
|
16
|
-
this.name = model.name;
|
|
17
|
-
|
|
18
|
-
model.fields.forEach((field) => {
|
|
19
|
-
if (field.isUpdatedAt || field.isId || field.name === "createdAt" || field.kind === "object") return;
|
|
20
|
-
|
|
21
|
-
this.fields.push(new DocGenField(field, "dto"));
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
this.file = new DocGenFile({
|
|
25
|
-
dir: "/dto",
|
|
26
|
-
fileName: `${Helper.toKebab(this.name)}.dto.ts`,
|
|
27
|
-
data: this.build(),
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
build() {
|
|
32
|
-
const sanitizedFields = this.fields
|
|
33
|
-
.map((field) => {
|
|
34
|
-
field.validators.forEach((v) => this.classValidators.add(v.name));
|
|
35
|
-
|
|
36
|
-
if (field.isEntity) {
|
|
37
|
-
this.imports.add(`import { ${field.type} } from '../entities/${Helper.toKebab(field.scalarType)}.entity'`);
|
|
38
|
-
this.imports.add(`import { generateExample } from 'src/utils/functions/reflect'`);
|
|
39
|
-
} else if (field.isEnum) {
|
|
40
|
-
this.enums.add(field.type);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return field.build();
|
|
44
|
-
})
|
|
45
|
-
.join("\n\n");
|
|
46
|
-
|
|
47
|
-
if (this.enums.size > 0) {
|
|
48
|
-
this.classValidators.add("IsEnum");
|
|
49
|
-
this.imports.add(`import { ${Array.from(this.enums)} } from '../enums';`);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
this.imports.add(`import { ${Array.from(this.classValidators)} } from 'class-validator';`);
|
|
53
|
-
|
|
54
|
-
return [
|
|
55
|
-
`${Array.from(this.imports).join("\n")}`,
|
|
56
|
-
`export class ${this.name}Dto {
|
|
57
|
-
${sanitizedFields}
|
|
58
|
-
}`,
|
|
59
|
-
].join("\n\n");
|
|
60
|
-
}
|
|
61
|
-
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { DocGenFile } from "../file.js";
|
|
2
|
-
import { Helper } from "../helpers/helpers.js";
|
|
3
|
-
import { Static } from "../static.js";
|
|
4
|
-
import { Model } from "../types.js";
|
|
5
|
-
import { DocGenField } from "./field.js";
|
|
6
|
-
|
|
7
|
-
export class DocGenEntity {
|
|
8
|
-
name: string;
|
|
9
|
-
file: DocGenFile;
|
|
10
|
-
fields: DocGenField[] = [];
|
|
11
|
-
imports = new Set([`${Static.AUTO_GENERATED_COMMENT}`, `import { ApiProperty } from '@nestjs/swagger'`]);
|
|
12
|
-
enums = new Set<string>();
|
|
13
|
-
|
|
14
|
-
constructor(model: Model) {
|
|
15
|
-
this.name = model.name;
|
|
16
|
-
|
|
17
|
-
model.fields.forEach((field) => {
|
|
18
|
-
if (field.kind === "object") return;
|
|
19
|
-
|
|
20
|
-
this.fields.push(new DocGenField(field, "entity"));
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
this.file = new DocGenFile({
|
|
24
|
-
dir: "/entity",
|
|
25
|
-
fileName: `${Helper.toKebab(this.name)}.entity.ts`,
|
|
26
|
-
data: this.build(),
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
build() {
|
|
31
|
-
const sanitizedFields = this.fields
|
|
32
|
-
.map((field) => {
|
|
33
|
-
if (field.isEntity) {
|
|
34
|
-
this.imports.add(`import { ${field.type} } from './${Helper.toKebab(field.scalarType)}.entity'`);
|
|
35
|
-
this.imports.add(`import { generateExample } from 'src/utils/functions/reflect'`);
|
|
36
|
-
} else if (field.isEnum) {
|
|
37
|
-
this.enums.add(field.type);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return field.build();
|
|
41
|
-
})
|
|
42
|
-
.join("\n\n");
|
|
43
|
-
|
|
44
|
-
if (this.enums.size > 0) {
|
|
45
|
-
this.imports.add(`import { ${Array.from(this.enums)} } from '../enums';`);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return [
|
|
49
|
-
`${Array.from(this.imports).join("\n")}`,
|
|
50
|
-
`export class ${this.name}Entity {
|
|
51
|
-
${sanitizedFields}
|
|
52
|
-
}`,
|
|
53
|
-
].join("\n\n");
|
|
54
|
-
}
|
|
55
|
-
}
|
package/src/entities/enum.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { DocGenFile } from "../file.js";
|
|
2
|
-
import { DbName } from "../types.js";
|
|
3
|
-
|
|
4
|
-
export type EnumValue = { name: string; dbName: DbName };
|
|
5
|
-
|
|
6
|
-
export class DocGenEnum {
|
|
7
|
-
name: string;
|
|
8
|
-
values: EnumValue[];
|
|
9
|
-
dbName: DbName;
|
|
10
|
-
|
|
11
|
-
constructor(params: { name: string; values: EnumValue[]; dbName: DbName }) {
|
|
12
|
-
const { dbName, name, values } = params;
|
|
13
|
-
this.dbName = dbName;
|
|
14
|
-
this.name = name;
|
|
15
|
-
this.values = values;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export class DocEnums {
|
|
20
|
-
enums: DocGenEnum[];
|
|
21
|
-
file: DocGenFile;
|
|
22
|
-
|
|
23
|
-
constructor(enums: DocGenEnum[]) {
|
|
24
|
-
this.enums = enums;
|
|
25
|
-
|
|
26
|
-
this.file = new DocGenFile({
|
|
27
|
-
dir: "/",
|
|
28
|
-
fileName: "enums.ts",
|
|
29
|
-
data: this.build(),
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
build() {
|
|
34
|
-
const enums = this.enums.map((en) => {
|
|
35
|
-
const enumName = en.name;
|
|
36
|
-
return `
|
|
37
|
-
export const ${enumName} = [${en.values.map((n) => `'${n.name}'`)}] as const;
|
|
38
|
-
export type ${enumName} = typeof ${enumName}[number];
|
|
39
|
-
`;
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
return `
|
|
43
|
-
// AUTO-GERADO: NÃO EDITAR MANUALMENTE. SUJEITO A PAULADAS!
|
|
44
|
-
${enums.join("\n")}
|
|
45
|
-
`;
|
|
46
|
-
}
|
|
47
|
-
}
|
package/src/entities/field.ts
DELETED
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
import { Helper } from "../helpers/helpers.js";
|
|
2
|
-
import { config } from "../helpers/loader.js";
|
|
3
|
-
import { Static } from "../static.js";
|
|
4
|
-
import { FieldDefault, Scalar, FieldKind, FieldType, Field } from "../types.js";
|
|
5
|
-
import { Validator } from "./validator.js";
|
|
6
|
-
|
|
7
|
-
const helpers = new Helper();
|
|
8
|
-
const rules = config;
|
|
9
|
-
|
|
10
|
-
export class DocGenField {
|
|
11
|
-
name: string;
|
|
12
|
-
isList: boolean;
|
|
13
|
-
default?: FieldDefault | string;
|
|
14
|
-
scalarType: Scalar;
|
|
15
|
-
kind: FieldKind;
|
|
16
|
-
|
|
17
|
-
type!: string;
|
|
18
|
-
fieldType: FieldType;
|
|
19
|
-
|
|
20
|
-
isEnum: boolean = false;
|
|
21
|
-
isEntity: boolean = false;
|
|
22
|
-
isUpdatedAt: boolean = false;
|
|
23
|
-
isRequired: boolean;
|
|
24
|
-
validators = new Set<Validator>();
|
|
25
|
-
|
|
26
|
-
readonly scalarField: Field;
|
|
27
|
-
|
|
28
|
-
constructor(field: Field, fieldType: FieldType) {
|
|
29
|
-
const { name, isList, type, kind, isRequired, isUpdatedAt } = field;
|
|
30
|
-
|
|
31
|
-
this.name = name;
|
|
32
|
-
this.isList = isList;
|
|
33
|
-
this.scalarType = type;
|
|
34
|
-
this.kind = kind;
|
|
35
|
-
this.isRequired = isRequired;
|
|
36
|
-
this.scalarField = field;
|
|
37
|
-
this.isUpdatedAt = isUpdatedAt;
|
|
38
|
-
this.fieldType = fieldType;
|
|
39
|
-
|
|
40
|
-
this.setType();
|
|
41
|
-
this.setValidators();
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
private processValidator(name: string) {
|
|
45
|
-
const validator = new Validator({ name });
|
|
46
|
-
if (this.isList) validator.content = "{ each: true }";
|
|
47
|
-
|
|
48
|
-
this.validators.add(validator);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
private setValidators() {
|
|
52
|
-
if (this.scalarType === "String" || this.scalarType === "DateTime" || this.scalarType === "Json") {
|
|
53
|
-
this.processValidator("IsString");
|
|
54
|
-
|
|
55
|
-
if (this.isRequired) {
|
|
56
|
-
this.processValidator("IsNotEmpty");
|
|
57
|
-
}
|
|
58
|
-
} else if (this.scalarType === "Boolean") {
|
|
59
|
-
this.processValidator("IsBoolean");
|
|
60
|
-
} else if (
|
|
61
|
-
this.scalarType === "Int" ||
|
|
62
|
-
this.scalarType === "BigInt" ||
|
|
63
|
-
this.scalarType === "Float" ||
|
|
64
|
-
this.scalarType === "Decimal"
|
|
65
|
-
) {
|
|
66
|
-
this.processValidator("IsNumber");
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (this.isList) {
|
|
70
|
-
const validator = new Validator({ name: "IsArray" });
|
|
71
|
-
this.validators.add(validator);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (!this.isRequired) this.processValidator("IsOptional");
|
|
75
|
-
|
|
76
|
-
if (this.isEnum) {
|
|
77
|
-
this.validators.add(
|
|
78
|
-
new Validator({
|
|
79
|
-
name: "IsEnum",
|
|
80
|
-
content: this.type,
|
|
81
|
-
})
|
|
82
|
-
);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const findedDecorators = rules.validators.get(this.name);
|
|
86
|
-
|
|
87
|
-
if (findedDecorators) {
|
|
88
|
-
findedDecorators.forEach((name) => {
|
|
89
|
-
this.processValidator(name);
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
private setType() {
|
|
95
|
-
if (this.kind === "enum") {
|
|
96
|
-
this.isEnum = true;
|
|
97
|
-
this.type = this.scalarType;
|
|
98
|
-
} else if (this.kind === "object") {
|
|
99
|
-
this.isEntity = true;
|
|
100
|
-
this.type = `${this.scalarType}Entity`;
|
|
101
|
-
} else if (this.kind === "scalar") {
|
|
102
|
-
this.type = Helper.prismaScalarToTs(this.scalarType);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
private buildApiExample(): string[] {
|
|
107
|
-
const fieldName = this.scalarField.name;
|
|
108
|
-
const props: string[] = [];
|
|
109
|
-
const scalarDbName = this.scalarField.dbName ?? "genericDbName";
|
|
110
|
-
|
|
111
|
-
if (this.isEntity) {
|
|
112
|
-
if (this.isList) {
|
|
113
|
-
props.push(`example: [generateExample(${this.type})]`);
|
|
114
|
-
} else {
|
|
115
|
-
props.push(`example: generateExample(${this.type})`);
|
|
116
|
-
}
|
|
117
|
-
} else if (rules.examples.has(fieldName)) {
|
|
118
|
-
props.push(`example: '${rules.examples.get(fieldName)?.example}'`);
|
|
119
|
-
} else if (helpers.isDate(this.scalarField)) {
|
|
120
|
-
props.push(`example: '2025-09-03T03:00:00.000Z'`);
|
|
121
|
-
} else if (this.scalarField.isId || (this.scalarField.isReadOnly && scalarDbName.split("_").includes("id"))) {
|
|
122
|
-
props.push(`example: 'cmfxu4njg000008l52v7t8qze'`);
|
|
123
|
-
} else if (this.scalarField.type === "Boolean") {
|
|
124
|
-
props.push(`example: true`);
|
|
125
|
-
} else if (this.scalarField.kind === "enum") {
|
|
126
|
-
props.push(`example: ${this.scalarField.type}[0]`);
|
|
127
|
-
} else if (this.scalarField.type === "Int") {
|
|
128
|
-
props.push(`example: ${Static.getRandomNumber()}`);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
props.push(`required: ${this.scalarField.isRequired}`);
|
|
132
|
-
return props;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
private sanitizeValidators() {
|
|
136
|
-
const sanitizedValidators = Array.from(this.validators).map((validator) => {
|
|
137
|
-
return validator.build();
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
return sanitizedValidators;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
private buildInfos() {
|
|
144
|
-
const key = this.isEnum ? "enum" : "type";
|
|
145
|
-
|
|
146
|
-
const apiType = () => {
|
|
147
|
-
if (this.type === "Date") return `'string'`;
|
|
148
|
-
|
|
149
|
-
if (this.isList && this.isEntity) {
|
|
150
|
-
return `[${this.type}]`;
|
|
151
|
-
} else if (this.isEnum) {
|
|
152
|
-
return this.type;
|
|
153
|
-
} else if (this.isEntity) {
|
|
154
|
-
return `() => ${this.type}`;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
return `'${this.type}'`;
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
const fieldType = () => {
|
|
161
|
-
if (this.isList) {
|
|
162
|
-
return `${this.type}[]`;
|
|
163
|
-
} else {
|
|
164
|
-
return this.type;
|
|
165
|
-
}
|
|
166
|
-
};
|
|
167
|
-
const optionalFlag = this.isRequired ? "" : "?";
|
|
168
|
-
|
|
169
|
-
const validators = this.sanitizeValidators();
|
|
170
|
-
const apiExample = this.buildApiExample().join(", ");
|
|
171
|
-
|
|
172
|
-
return {
|
|
173
|
-
apiProperty: `@ApiProperty({ ${key}: ${apiType()}, ${apiExample} })`,
|
|
174
|
-
validators,
|
|
175
|
-
atributes: `${this.name}${optionalFlag}: ${fieldType()};`,
|
|
176
|
-
};
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
build() {
|
|
180
|
-
const { apiProperty, atributes, validators } = this.buildInfos();
|
|
181
|
-
|
|
182
|
-
if (this.fieldType === "dto") {
|
|
183
|
-
return [apiProperty, ...validators, atributes].join("\n");
|
|
184
|
-
} else {
|
|
185
|
-
return [apiProperty, atributes].join("\n");
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
package/src/entities/model.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { Field, Model } from "../types.js";
|
|
2
|
-
import { DocGenDto } from "./dto-generator.js";
|
|
3
|
-
import { DocGenEntity } from "./entity-generator.js";
|
|
4
|
-
|
|
5
|
-
export class DocGenModel {
|
|
6
|
-
name: string;
|
|
7
|
-
entitie: DocGenEntity;
|
|
8
|
-
createDtos: DocGenDto;
|
|
9
|
-
fields: Field[];
|
|
10
|
-
|
|
11
|
-
constructor(model: Model) {
|
|
12
|
-
this.name = model.name;
|
|
13
|
-
this.fields = model.fields;
|
|
14
|
-
|
|
15
|
-
this.entitie = new DocGenEntity(model);
|
|
16
|
-
this.createDtos = new DocGenDto(model);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
save() {
|
|
20
|
-
this.entitie.file.save();
|
|
21
|
-
this.createDtos.file.save();
|
|
22
|
-
}
|
|
23
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { Scalar } from "../types.js";
|
|
2
|
-
|
|
3
|
-
export class Validator {
|
|
4
|
-
name: string;
|
|
5
|
-
content: string;
|
|
6
|
-
|
|
7
|
-
constructor(params: { name: string; content?: string }) {
|
|
8
|
-
const { content, name } = params;
|
|
9
|
-
|
|
10
|
-
this.name = name;
|
|
11
|
-
this.content = content ?? "";
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
build() {
|
|
15
|
-
return `@${this.name}(${this.content})`;
|
|
16
|
-
}
|
|
17
|
-
}
|
package/src/field.type.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { DocGenFile } from "./file.js";
|
|
2
|
-
import { Static } from "./static.js";
|
|
3
|
-
|
|
4
|
-
export class DocFields {
|
|
5
|
-
fields: string;
|
|
6
|
-
file: DocGenFile;
|
|
7
|
-
|
|
8
|
-
constructor(fields: string) {
|
|
9
|
-
this.fields = fields;
|
|
10
|
-
|
|
11
|
-
this.file = new DocGenFile({
|
|
12
|
-
dir: "/",
|
|
13
|
-
fileName: "fields.ts",
|
|
14
|
-
data: this.build(),
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
build() {
|
|
19
|
-
const content = `
|
|
20
|
-
${Static.AUTO_GENERATED_COMMENT}
|
|
21
|
-
export const FIELD_NAMES = [${this.fields}] as const
|
|
22
|
-
export type FieldName = (typeof FIELD_NAMES)[number];
|
|
23
|
-
`;
|
|
24
|
-
|
|
25
|
-
return content;
|
|
26
|
-
}
|
|
27
|
-
}
|
package/src/file.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { promises as fs } from "node:fs";
|
|
2
|
-
import * as path from "node:path";
|
|
3
|
-
import * as prettier from "prettier";
|
|
4
|
-
|
|
5
|
-
const ROOT = process.cwd();
|
|
6
|
-
const OUT_DIR = path.join(ROOT, "src/types/docgen");
|
|
7
|
-
|
|
8
|
-
export class DocGenFile {
|
|
9
|
-
outDir: string;
|
|
10
|
-
data: string;
|
|
11
|
-
|
|
12
|
-
constructor(params: { fileName: string; dir: string; data: string; customDir?: string }) {
|
|
13
|
-
const { fileName, dir, data, customDir } = params;
|
|
14
|
-
|
|
15
|
-
this.outDir = path.join(OUT_DIR, dir, fileName);
|
|
16
|
-
this.data = data;
|
|
17
|
-
|
|
18
|
-
if (customDir) this.outDir = customDir;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
async save() {
|
|
22
|
-
const dir = path.dirname(this.outDir);
|
|
23
|
-
await fs.mkdir(dir, { recursive: true });
|
|
24
|
-
|
|
25
|
-
const prettierConfig = await prettier.resolveConfig(this.outDir);
|
|
26
|
-
|
|
27
|
-
const formatted = await prettier.format(this.data, {
|
|
28
|
-
...prettierConfig,
|
|
29
|
-
filepath: this.outDir,
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
await fs.writeFile(this.outDir, formatted, "utf-8");
|
|
33
|
-
}
|
|
34
|
-
}
|
package/src/helpers/helpers.ts
DELETED
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
import { promises as fs } from "node:fs";
|
|
2
|
-
import * as path from "node:path";
|
|
3
|
-
import { Scalar, Field, DocGenModel } from "../types.js";
|
|
4
|
-
|
|
5
|
-
export class Helper {
|
|
6
|
-
static prismaScalarToTs(s: Scalar): string {
|
|
7
|
-
switch (s) {
|
|
8
|
-
case "String":
|
|
9
|
-
return "string";
|
|
10
|
-
case "Int":
|
|
11
|
-
return "number";
|
|
12
|
-
case "BigInt":
|
|
13
|
-
return "bigint";
|
|
14
|
-
case "Float":
|
|
15
|
-
case "Decimal":
|
|
16
|
-
return "number";
|
|
17
|
-
case "Boolean":
|
|
18
|
-
return "boolean";
|
|
19
|
-
case "DateTime":
|
|
20
|
-
return "Date";
|
|
21
|
-
case "Json":
|
|
22
|
-
return "any";
|
|
23
|
-
case "Bytes":
|
|
24
|
-
return "Buffer";
|
|
25
|
-
default: {
|
|
26
|
-
return "any";
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
static validatorForScalar(s: Scalar): string {
|
|
32
|
-
switch (s) {
|
|
33
|
-
case "String":
|
|
34
|
-
return "IsString";
|
|
35
|
-
case "Int":
|
|
36
|
-
return "IsInt";
|
|
37
|
-
case "BigInt":
|
|
38
|
-
return "IsNumber"; // class-validator não tem IsBigInt
|
|
39
|
-
case "Float":
|
|
40
|
-
case "Decimal":
|
|
41
|
-
return "IsNumber";
|
|
42
|
-
case "Boolean":
|
|
43
|
-
return "IsBoolean";
|
|
44
|
-
case "DateTime":
|
|
45
|
-
return "IsDate";
|
|
46
|
-
case "Json":
|
|
47
|
-
return ""; // costuma ser livre
|
|
48
|
-
case "Bytes":
|
|
49
|
-
return ""; // Buffer não tem decorador nativo
|
|
50
|
-
default:
|
|
51
|
-
return "";
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
static swaggerType(field: Field): string | undefined {
|
|
56
|
-
// mapeia para Swagger 'type' básico quando possível
|
|
57
|
-
if (field.kind === "scalar") {
|
|
58
|
-
const t = field.type;
|
|
59
|
-
|
|
60
|
-
switch (t) {
|
|
61
|
-
case "String":
|
|
62
|
-
return "string";
|
|
63
|
-
case "Int":
|
|
64
|
-
case "Float":
|
|
65
|
-
case "Decimal":
|
|
66
|
-
return "number";
|
|
67
|
-
case "BigInt":
|
|
68
|
-
return "integer";
|
|
69
|
-
case "Boolean":
|
|
70
|
-
return "boolean";
|
|
71
|
-
case "DateTime":
|
|
72
|
-
return "string"; // format date-time
|
|
73
|
-
case "Json":
|
|
74
|
-
return "object";
|
|
75
|
-
case "Bytes":
|
|
76
|
-
return "string"; // base64
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
return undefined;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
static toKebab(s: string): string {
|
|
83
|
-
return s.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
importsForModel(model: DocGenModel): {
|
|
87
|
-
enums: boolean;
|
|
88
|
-
hasDate: boolean;
|
|
89
|
-
} {
|
|
90
|
-
const needsEnum = model.fields.some((field) => field.kind === "enum");
|
|
91
|
-
return {
|
|
92
|
-
enums: needsEnum,
|
|
93
|
-
hasDate: model.fields.some((field) => field.kind === "scalar" && field.type === "DateTime"),
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
static async readPrismaFolderDatamodel(dir: string): Promise<string> {
|
|
98
|
-
const files: string[] = [];
|
|
99
|
-
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
100
|
-
|
|
101
|
-
const mainSchemaPath = path.join(dir, "schema.prisma");
|
|
102
|
-
try {
|
|
103
|
-
const mainStat = await fs.stat(mainSchemaPath);
|
|
104
|
-
if (mainStat.isFile()) files.push(mainSchemaPath);
|
|
105
|
-
} catch {}
|
|
106
|
-
|
|
107
|
-
// varrer demais itens (exceto migrations e o schema.prisma já incluído)
|
|
108
|
-
for (const entry of entries) {
|
|
109
|
-
if (entry.name === "migrations") continue;
|
|
110
|
-
const full = path.join(dir, entry.name);
|
|
111
|
-
|
|
112
|
-
if (entry.isDirectory()) {
|
|
113
|
-
const nested = await this.readPrismaFolderDatamodel(full);
|
|
114
|
-
if (nested.trim()) files.push(`\n// ---- ${full} ----\n${nested}`);
|
|
115
|
-
} else if (entry.isFile() && entry.name.endsWith(".prisma") && full !== mainSchemaPath) {
|
|
116
|
-
const content = await fs.readFile(full, "utf-8");
|
|
117
|
-
files.push(`\n// ---- ${full} ----\n${content}`);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// se não houver nada além de subpastas, retorna o que juntou nelas
|
|
122
|
-
if (!files.length) return "";
|
|
123
|
-
|
|
124
|
-
// quando schema.prisma existe, ele já está no topo do array
|
|
125
|
-
if (files[0] === mainSchemaPath) {
|
|
126
|
-
const head = await fs.readFile(mainSchemaPath, "utf-8");
|
|
127
|
-
const tail = files.slice(1).join("\n");
|
|
128
|
-
return `${head}\n${tail}`;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// caso não exista schema.prisma, apenas concatena
|
|
132
|
-
const contents = await Promise.all(files.map(async (f) => (f.startsWith("\n// ---- ") ? f : fs.readFile(f, "utf-8"))));
|
|
133
|
-
return contents.join("\n");
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
findTypeForField(field: Field): string {
|
|
137
|
-
if (field.kind === "scalar") {
|
|
138
|
-
const base = Helper.prismaScalarToTs(field.type);
|
|
139
|
-
return field.isList ? `${base}[]` : base;
|
|
140
|
-
} else if (field.kind === "enum") {
|
|
141
|
-
const base = field.type;
|
|
142
|
-
return field.isList ? `${base}[]` : base;
|
|
143
|
-
} else if (field.kind === "object") {
|
|
144
|
-
const base = "any";
|
|
145
|
-
return field.isList ? `${base}[]` : base;
|
|
146
|
-
} else return "any";
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
isDate(field: Field): boolean {
|
|
150
|
-
return field.kind === "scalar" && field.type === "DateTime";
|
|
151
|
-
}
|
|
152
|
-
}
|