prisma-docs-generator
Version:
Documentation reference generator for Prisma Schema
149 lines (135 loc) • 3.93 kB
text/typescript
import { Generatable, isScalarType } from './helpers';
import { DMMFDocument } from './transformDMMF';
import { DMMF } from '@prisma/generator-helper';
type TypesGeneratorStructure = {
inputTypes: TGType[];
outputTypes: TGType[];
// TODO: evaluate calling them enums as that can be ambigious
//enums: any;
};
type TGType = {
name: string;
fields: TGTypeField[];
};
type TGTypeField = {
name: string;
type: DMMF.SchemaArgInputType[];
nullable: boolean;
};
class TypesGenerator implements Generatable<TypesGeneratorStructure> {
data: TypesGeneratorStructure;
constructor(d: DMMFDocument) {
this.data = this.getData(d);
}
getTypeFieldHTML(
field: TGTypeField,
kind: 'inputType' | 'outputType'
): string {
return `
<tr>
<td class="px-4 py-2 border">
${field.name} </td>
<td class="px-4 py-2 border">
${field.type
.map((f) =>
isScalarType(f.type as string)
? f.type
: `<a href="#type-${kind}-${f.type}">${f.type}${
f.isList ? '[]' : ''
}</a>`
)
.join(' | ')}
</td>
<td class="px-4 py-2 border">
${field.nullable ? '<strong>Yes</strong>' : 'No'}
</td>
</tr>
`;
}
getTypeHTML(type: TGType, kind: 'inputType' | 'outputType'): string {
return `
<div>
<h3 class="mb-2 text-xl" id="type-${kind}-${type.name}">${
type.name
}</h3>
<table class="table-auto">
<thead>
<tr>
<th class="px-4 py-2 border">Name</th>
<th class="px-4 py-2 border">Type</th>
<th class="px-4 py-2 border">Nullable</th>
</tr>
</thead>
<tbody>
${type.fields
.map((field) => this.getTypeFieldHTML(field, kind))
.join('')}
</tbody>
</table>
</div>
`;
}
toHTML() {
return `<div>
<h1 class="text-3xl" id="types">Types</h1>
<div>
<div class="ml-4">
<h3 class="mb-2 text-2xl font-normal" id="input-types">Input Types</h3>
<div class="ml-4">
${this.data.inputTypes
.map((inputType) => this.getTypeHTML(inputType, 'inputType'))
.join(`<hr class="my-4" />`)}
</div>
</div>
<div class="ml-4">
<h3 class="mb-2 text-2xl font-normal" id="output-types">Output Types</h3>
<div class="ml-4">
${this.data.outputTypes
.map((outputType) => this.getTypeHTML(outputType, 'outputType'))
.join(`<hr class="my-4" />`)}
</div>
</div>
</div>
</div>
`;
}
getInputTypes(dmmfInputType: DMMF.InputType[]): TGType[] {
return dmmfInputType.map((inputType) => ({
name: inputType.name,
fields: inputType.fields.map((ip) => ({
name: ip.name,
nullable: ip.isNullable,
type: ip.inputTypes,
})),
}));
}
getOutputTypes(dmmfOutputTypes: DMMF.OutputType[]): TGType[] {
return dmmfOutputTypes.map((outputType) => ({
name: outputType.name,
fields: outputType.fields.map((op) => ({
name: op.name,
nullable: !op.isNullable,
list: (op.outputType as any).isList,
type: [
{
isList: op.outputType.isList,
type: op.outputType.type as string,
location: op.outputType.location,
},
],
})),
}));
}
getData(d: DMMFDocument) {
return {
inputTypes: this.getInputTypes(d.schema.inputObjectTypes.prisma),
outputTypes: this.getOutputTypes([
...d.schema.outputObjectTypes.model,
...d.schema.outputObjectTypes.prisma.filter(
(op) => op.name !== 'Query' && op.name !== 'Mutation'
),
]),
};
}
}
export default TypesGenerator;