@baeta/plugin-prisma 0.0.2
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/.eslintrc.cjs +4 -0
- package/CHANGELOG.md +8 -0
- package/index.ts +47 -0
- package/lib/context.ts +29 -0
- package/lib/dmmf.ts +8 -0
- package/lib/generator.ts +24 -0
- package/lib/model-entries.ts +57 -0
- package/lib/model-enum.ts +17 -0
- package/lib/model-inputs.ts +32 -0
- package/lib/model-list.ts +5 -0
- package/lib/model-operations.ts +65 -0
- package/lib/model-outputs.ts +15 -0
- package/lib/model-relations.ts +35 -0
- package/lib/print/directive.ts +28 -0
- package/lib/print/module-prisma.ts +13 -0
- package/lib/print/module-resolver.ts +48 -0
- package/lib/print/module.ts +65 -0
- package/lib/print/object.ts +15 -0
- package/lib/print/prisma-enum-model.ts +7 -0
- package/lib/print/prisma-enum.ts +6 -0
- package/lib/print/prisma-input.ts +45 -0
- package/lib/print/prisma-model.ts +24 -0
- package/lib/print/prisma-output.ts +86 -0
- package/lib/print/prisma-scalar.ts +46 -0
- package/lib/print/type.ts +37 -0
- package/lib/resolver-builder/index.ts +1 -0
- package/lib/resolver-builder/resolver-builder-files.ts +69 -0
- package/lib/resolver-builder/resolver-builder.ts +80 -0
- package/lib/schema-builder/index.ts +1 -0
- package/lib/schema-builder/schema-builder-files.ts +150 -0
- package/lib/schema-builder/schema-builder-utils.ts +3 -0
- package/lib/schema-builder/schema-builder.ts +186 -0
- package/lib/visitor.ts +119 -0
- package/package.json +38 -0
- package/tsconfig.json +9 -0
- package/utils/casing.ts +23 -0
- package/utils/string.ts +9 -0
package/.eslintrc.cjs
ADDED
package/CHANGELOG.md
ADDED
package/index.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { createPluginFactoryV1, GeneratorCtx } from '@baeta/plugin';
|
|
2
|
+
import { createContext, Store } from './lib/context';
|
|
3
|
+
import { generate } from './lib/generator';
|
|
4
|
+
import { Casing } from './utils/casing';
|
|
5
|
+
|
|
6
|
+
export interface PrismaPluginOptions {
|
|
7
|
+
casing?: Casing;
|
|
8
|
+
schemaNamespace?: string;
|
|
9
|
+
resolverNamespace?: string;
|
|
10
|
+
resolverExport?: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type PrismaPluginCtx = GeneratorCtx<{
|
|
14
|
+
prisma: Store;
|
|
15
|
+
}>;
|
|
16
|
+
|
|
17
|
+
export default createPluginFactoryV1<PrismaPluginOptions, PrismaPluginCtx>({
|
|
18
|
+
name: 'prisma',
|
|
19
|
+
watch: (baetaConfig, pluginConfig) => {
|
|
20
|
+
const root = baetaConfig.graphql.modulesDir || 'src/modules';
|
|
21
|
+
const modulesMatcher =
|
|
22
|
+
root + '/*/' + (pluginConfig.schemaNamespace || 'prisma-schema') + '/**';
|
|
23
|
+
|
|
24
|
+
const prismaModule = root + '/prisma' + '/**';
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
include: [],
|
|
28
|
+
ignore: [modulesMatcher, prismaModule],
|
|
29
|
+
};
|
|
30
|
+
},
|
|
31
|
+
setup: async (params) => {
|
|
32
|
+
params.ctx.prisma = await createContext();
|
|
33
|
+
return params.next();
|
|
34
|
+
},
|
|
35
|
+
generate: async (params) => {
|
|
36
|
+
const files = await generate(params.ctx.prisma, {
|
|
37
|
+
modulesDir: params.ctx.config.graphql.modulesDir || 'src/modules',
|
|
38
|
+
casing: params.config.casing || 'kebab-case',
|
|
39
|
+
schemaNamespace: params.config.schemaNamespace || 'prisma-schema',
|
|
40
|
+
resolverNamespace: params.config.resolverNamespace || 'prisma-resolver',
|
|
41
|
+
resolverExport: params.config.resolverExport ?? true,
|
|
42
|
+
});
|
|
43
|
+
params.ctx.fileManager.add(...files);
|
|
44
|
+
await params.ctx.fileManager.writeByTag('prisma-sdl');
|
|
45
|
+
return params.next();
|
|
46
|
+
},
|
|
47
|
+
});
|
package/lib/context.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { parseDMMF } from './dmmf';
|
|
2
|
+
import { createInputsModelMap } from './model-inputs';
|
|
3
|
+
import { createModelsList } from './model-list';
|
|
4
|
+
import { createModelsOperationsMaps } from './model-operations';
|
|
5
|
+
import { createOutputsModelMaps } from './model-outputs';
|
|
6
|
+
import { createModelRelationsList } from './model-relations';
|
|
7
|
+
|
|
8
|
+
export type Store = ReturnType<typeof createContext> extends Promise<infer T> ? T : never;
|
|
9
|
+
|
|
10
|
+
export async function createContext() {
|
|
11
|
+
const dmmf = await parseDMMF({
|
|
12
|
+
datamodelPath: 'schema.prisma',
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const models = createModelsList(dmmf);
|
|
16
|
+
const inputsMap = createInputsModelMap(dmmf, models);
|
|
17
|
+
const outputsMap = createOutputsModelMaps(dmmf, models);
|
|
18
|
+
const relationsMap = createModelRelationsList(dmmf);
|
|
19
|
+
const operationsMap = createModelsOperationsMaps(dmmf);
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
dmmf,
|
|
23
|
+
models,
|
|
24
|
+
inputsMap,
|
|
25
|
+
outputsMap,
|
|
26
|
+
relationsMap,
|
|
27
|
+
operationsMap,
|
|
28
|
+
};
|
|
29
|
+
}
|
package/lib/dmmf.ts
ADDED
package/lib/generator.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { PrismaPluginOptions } from '..';
|
|
2
|
+
import { Store } from './context';
|
|
3
|
+
import { createResolversBuilder } from './resolver-builder';
|
|
4
|
+
import { createSchemaBuilder } from './schema-builder';
|
|
5
|
+
import { visit } from './visitor';
|
|
6
|
+
|
|
7
|
+
export interface GenerateOptions extends Required<PrismaPluginOptions> {
|
|
8
|
+
modulesDir: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export async function generate(store: Store, options: GenerateOptions) {
|
|
12
|
+
const schemaBuilder = createSchemaBuilder(store, options);
|
|
13
|
+
const resolversBuilder = createResolversBuilder(store, options);
|
|
14
|
+
|
|
15
|
+
await visit(store.dmmf, [
|
|
16
|
+
resolversBuilder.visitor.getVisitor(),
|
|
17
|
+
schemaBuilder.visitor.getVisitor(),
|
|
18
|
+
]);
|
|
19
|
+
|
|
20
|
+
const resolverFiles = resolversBuilder.compose();
|
|
21
|
+
const schemaFiles = schemaBuilder.compose();
|
|
22
|
+
|
|
23
|
+
return [...resolverFiles, ...schemaFiles];
|
|
24
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
interface ModelEntry {
|
|
2
|
+
model: string;
|
|
3
|
+
modelScore: number;
|
|
4
|
+
operationName: string;
|
|
5
|
+
}
|
|
6
|
+
type ModelEntryMap = Record<string, ModelEntry | undefined>;
|
|
7
|
+
|
|
8
|
+
type EntryValue = {
|
|
9
|
+
model: string;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export type EntryToModelMap = Record<string, EntryValue | undefined>;
|
|
13
|
+
|
|
14
|
+
export function createEntriesModelMap(models: string[], entries: string[]) {
|
|
15
|
+
const map: ModelEntryMap = {};
|
|
16
|
+
|
|
17
|
+
for (const model of models) {
|
|
18
|
+
updateEntriesForModel(map, model, entries);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return normalizeResult(map);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function updateEntriesForModel(map: ModelEntryMap, model: string, entries: string[]) {
|
|
25
|
+
for (const input of entries) {
|
|
26
|
+
if (!input.startsWith(model) && input !== 'Aggregate' + model) {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const currentScore = model.length;
|
|
31
|
+
|
|
32
|
+
const modelInput = map[input];
|
|
33
|
+
|
|
34
|
+
if (modelInput && modelInput.modelScore > currentScore) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
map[input] = {
|
|
39
|
+
model,
|
|
40
|
+
operationName: input,
|
|
41
|
+
modelScore: currentScore,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function normalizeResult(value: ModelEntryMap) {
|
|
47
|
+
const result: EntryToModelMap = {};
|
|
48
|
+
|
|
49
|
+
for (const input of Object.values(value)) {
|
|
50
|
+
if (!input) {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
result[input.operationName] = { model: input.model };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { DMMF } from './dmmf';
|
|
2
|
+
|
|
3
|
+
export function findModelByEnum(models: string[], enumType: DMMF.SchemaEnum) {
|
|
4
|
+
for (const model of models) {
|
|
5
|
+
if (!enumType.name.startsWith(model)) {
|
|
6
|
+
continue;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
if (model + 'ScalarFieldEnum' === enumType.name) {
|
|
10
|
+
return model;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (model + 'OrderByRelevanceFieldEnum' === enumType.name) {
|
|
14
|
+
return model;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { DMMF } from './dmmf';
|
|
2
|
+
import { createEntriesModelMap, EntryToModelMap } from './model-entries';
|
|
3
|
+
|
|
4
|
+
export function createInputsModelMap(dmmf: DMMF.Document, models: string[]) {
|
|
5
|
+
const inputs = createInputsList(dmmf);
|
|
6
|
+
return createEntriesModelMap(models, inputs);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function findModelByInput(entries: EntryToModelMap, input: DMMF.InputType) {
|
|
10
|
+
return entries[input.name]?.model;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function createInputsList(dmmf: DMMF.Document) {
|
|
14
|
+
return dmmf.schema.inputObjectTypes.prisma.map((el) => el.name);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function createInputsIgnoreList(dmmf: DMMF.Document) {
|
|
18
|
+
const ignoreList: string[] = [];
|
|
19
|
+
|
|
20
|
+
const inputs = createInputsList(dmmf);
|
|
21
|
+
const uncheckedInputs = inputs.filter((input) => input.includes('Unchecked'));
|
|
22
|
+
|
|
23
|
+
uncheckedInputs.forEach((uncheckedInput) => {
|
|
24
|
+
const normalized = uncheckedInput.replace('Unchecked', '');
|
|
25
|
+
const exists = inputs.some((input) => input === normalized);
|
|
26
|
+
if (exists) {
|
|
27
|
+
ignoreList.push(uncheckedInput);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
return ignoreList;
|
|
32
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { plural, singular } from 'pluralize';
|
|
2
|
+
import { DMMF } from './dmmf';
|
|
3
|
+
|
|
4
|
+
export type ModelOperations = {
|
|
5
|
+
model: string;
|
|
6
|
+
prisma: string;
|
|
7
|
+
operation: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export type ModelsOperationsMap = Record<string, ModelOperations | undefined>;
|
|
11
|
+
|
|
12
|
+
export function createModelsOperationsMaps(dmmf: DMMF.Document) {
|
|
13
|
+
return dmmf.mappings.modelOperations
|
|
14
|
+
.map((operations) => createModelOperationsMap(operations))
|
|
15
|
+
.reduce((a, b) => ({ ...a, ...b }));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function findModelByOperationSchema(
|
|
19
|
+
map: ModelsOperationsMap,
|
|
20
|
+
schema: DMMF.SchemaField
|
|
21
|
+
) {
|
|
22
|
+
return map[schema.name]?.model;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function createModelOperationsMap(mapping: DMMF.ModelMapping) {
|
|
26
|
+
const model = mapping.model;
|
|
27
|
+
const operationMap: ModelsOperationsMap = {};
|
|
28
|
+
|
|
29
|
+
function addToMap(key: string, operation?: string) {
|
|
30
|
+
const originalName = mapping[key as keyof DMMF.ModelMapping];
|
|
31
|
+
|
|
32
|
+
if (!originalName) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
operationMap[originalName] = {
|
|
37
|
+
model,
|
|
38
|
+
prisma: key,
|
|
39
|
+
operation: operation ?? originalName,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const keys = Object.keys(mapping);
|
|
44
|
+
const modelName = model[0].toLocaleLowerCase() + model.slice(1);
|
|
45
|
+
|
|
46
|
+
for (const key of keys) {
|
|
47
|
+
if (key === 'model') {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (key === 'findUnique') {
|
|
52
|
+
addToMap(key, singular(modelName));
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (key === 'findMany') {
|
|
57
|
+
addToMap(key, plural(modelName));
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
addToMap(key);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return operationMap;
|
|
65
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { DMMF } from './dmmf';
|
|
2
|
+
import { createEntriesModelMap, EntryToModelMap } from './model-entries';
|
|
3
|
+
|
|
4
|
+
export function createOutputsModelMaps(dmmf: DMMF.Document, models: string[]) {
|
|
5
|
+
const inputs = createOutputsList(dmmf);
|
|
6
|
+
return createEntriesModelMap(models, inputs);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function findModelByOutput(entries: EntryToModelMap, output: DMMF.OutputType) {
|
|
10
|
+
return entries[output.name]?.model;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function createOutputsList(dmmf: DMMF.Document) {
|
|
14
|
+
return dmmf.schema.outputObjectTypes.prisma.map((el) => el.name);
|
|
15
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { DMMF } from './dmmf';
|
|
2
|
+
|
|
3
|
+
export interface ModelRelation {
|
|
4
|
+
with: string;
|
|
5
|
+
name: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export type ModelRelationsMap = Record<string, ModelRelation[] | undefined>;
|
|
9
|
+
|
|
10
|
+
export function createModelRelationsList(dmmf: DMMF.Document) {
|
|
11
|
+
const map: ModelRelationsMap = {};
|
|
12
|
+
|
|
13
|
+
for (const model of dmmf.datamodel.models) {
|
|
14
|
+
map[model.name] = getRelationsFromModel(model);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return map;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function getRelationsFromModel(model: DMMF.Model) {
|
|
21
|
+
const relations: ModelRelation[] = [];
|
|
22
|
+
|
|
23
|
+
for (const field of model.fields) {
|
|
24
|
+
if (field.kind !== 'object') {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
relations.push({
|
|
29
|
+
with: field.type,
|
|
30
|
+
name: field.name,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return relations;
|
|
35
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export const directives = [
|
|
2
|
+
'directive @inputConstraint(minFields: Int, maxFields: Int) on INPUT_OBJECT',
|
|
3
|
+
];
|
|
4
|
+
|
|
5
|
+
export function printDirectives() {
|
|
6
|
+
return directives.join('\n');
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function printInputConstraintDirective(
|
|
10
|
+
minNumFields?: number | null,
|
|
11
|
+
maxNumFields?: number | null
|
|
12
|
+
) {
|
|
13
|
+
const args = [];
|
|
14
|
+
|
|
15
|
+
if (minNumFields != null) {
|
|
16
|
+
args.push(`minFields: ${minNumFields}`);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (maxNumFields != null) {
|
|
20
|
+
args.push(`maxFields: ${maxNumFields}`);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (args.length === 0) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return `@inputConstraint(${args.join(', ')})`;
|
|
28
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function printPrismaModule() {
|
|
2
|
+
const imports = [
|
|
3
|
+
`import { registerPrismaModule } from "@baeta/prisma";`,
|
|
4
|
+
`import { createPrismaModule } from "./typedef";`,
|
|
5
|
+
].join('\n');
|
|
6
|
+
|
|
7
|
+
const content = [
|
|
8
|
+
`export const prismaModule = createPrismaModule();`,
|
|
9
|
+
`registerPrismaModule(prismaModule);`,
|
|
10
|
+
].join('\n');
|
|
11
|
+
|
|
12
|
+
return [imports, content].join('\n');
|
|
13
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { camelCase, upperCaseFirst } from 'change-case-all';
|
|
2
|
+
import { ModelOperations } from '../model-operations';
|
|
3
|
+
import { ModelRelation } from '../model-relations';
|
|
4
|
+
|
|
5
|
+
export function printResolver(
|
|
6
|
+
namespace: string,
|
|
7
|
+
mapping: ModelOperations,
|
|
8
|
+
prisma: string = 'ctx.prisma'
|
|
9
|
+
) {
|
|
10
|
+
const prismaModel = camelCase(mapping.model);
|
|
11
|
+
const prismaMethod = mapping.prisma.replace('One', '');
|
|
12
|
+
const expectError =
|
|
13
|
+
mapping.prisma === 'groupBy' ? '//@ts-expect-error difficult to infer\n ' : '';
|
|
14
|
+
|
|
15
|
+
const instruction = `${expectError}return ${prisma}.${prismaModel}.${prismaMethod}(args);`;
|
|
16
|
+
|
|
17
|
+
return printFunction(namespace, mapping.operation, instruction);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function printRelationResolver(
|
|
21
|
+
model: string,
|
|
22
|
+
relation: ModelRelation,
|
|
23
|
+
prisma: string = 'ctx.prisma'
|
|
24
|
+
) {
|
|
25
|
+
const prismaModel = camelCase(model);
|
|
26
|
+
const instruction = `return ${prisma}.${prismaModel}.findUnique({where: {id: root.id}}).${relation.name}(args);`;
|
|
27
|
+
|
|
28
|
+
return printFunction(model, relation.name, instruction, true);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function printFunction(
|
|
32
|
+
namespace: string,
|
|
33
|
+
func: string,
|
|
34
|
+
content: string,
|
|
35
|
+
rootArg = false
|
|
36
|
+
) {
|
|
37
|
+
const args = ['args', 'ctx'];
|
|
38
|
+
|
|
39
|
+
if (rootArg) {
|
|
40
|
+
args.unshift('root');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return [
|
|
44
|
+
`${upperCaseFirst(namespace)}.${func}(({ ${args.join(', ')} }) => {`,
|
|
45
|
+
` ${content}`,
|
|
46
|
+
`});`,
|
|
47
|
+
].join('\n');
|
|
48
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { camelCase } from 'change-case-all';
|
|
2
|
+
import { parse } from 'path';
|
|
3
|
+
import { ModuleResolvers } from '../resolver-builder';
|
|
4
|
+
import { printRelationResolver, printResolver } from './module-resolver';
|
|
5
|
+
|
|
6
|
+
export function printModule(model: ModuleResolvers) {
|
|
7
|
+
const name = model.name;
|
|
8
|
+
const moduleName = `${camelCase(name)}Module`;
|
|
9
|
+
|
|
10
|
+
const hasQueries = model.queries.length > 0;
|
|
11
|
+
const hasMutations = model.mutations.length > 0;
|
|
12
|
+
const hasRelations = model.relations.length > 0;
|
|
13
|
+
|
|
14
|
+
const queries = model.queries.map((operations) => printResolver('Query', operations));
|
|
15
|
+
|
|
16
|
+
const mutations = model.mutations.map((operations) =>
|
|
17
|
+
printResolver('Mutation', operations)
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
const relations = model.relations.map((relation) =>
|
|
21
|
+
printRelationResolver(model.name, relation)
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
return [
|
|
25
|
+
printImports(name),
|
|
26
|
+
printInit(moduleName, name),
|
|
27
|
+
printDestructure(moduleName, model.name, hasQueries, hasMutations, hasRelations),
|
|
28
|
+
queries.join('\n\n'),
|
|
29
|
+
mutations.join('\n\n'),
|
|
30
|
+
relations.join('\n\n'),
|
|
31
|
+
].join('\n\n');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function printModuleExport(filename: string) {
|
|
35
|
+
const exportFile = parse(filename).name;
|
|
36
|
+
return `export * from "./${exportFile}";`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function printImports(name: string) {
|
|
40
|
+
return [`import { create${name}Module } from "../typedef";`].join('\n');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function printInit(moduleName: string, name: string) {
|
|
44
|
+
return [`export const ${moduleName} = create${name}Module();`].join('\n');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function printDestructure(
|
|
48
|
+
moduleName: string,
|
|
49
|
+
modelName: string,
|
|
50
|
+
hasQueries: boolean,
|
|
51
|
+
hasMutations: boolean,
|
|
52
|
+
hasRelations: boolean
|
|
53
|
+
) {
|
|
54
|
+
const values = [];
|
|
55
|
+
if (hasQueries) {
|
|
56
|
+
values.push('Query');
|
|
57
|
+
}
|
|
58
|
+
if (hasMutations) {
|
|
59
|
+
values.push('Mutation');
|
|
60
|
+
}
|
|
61
|
+
if (hasRelations) {
|
|
62
|
+
values.push(modelName);
|
|
63
|
+
}
|
|
64
|
+
return `const { ${values.join(', ')} } = ${moduleName};`;
|
|
65
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { filterEmpty, indent } from '../../utils/string';
|
|
2
|
+
|
|
3
|
+
export function printObject(
|
|
4
|
+
kind: string,
|
|
5
|
+
name: string,
|
|
6
|
+
fields: Array<string | undefined>,
|
|
7
|
+
directive?: string
|
|
8
|
+
) {
|
|
9
|
+
const directiveLine = directive ? ` ${directive}` : '';
|
|
10
|
+
const firstLine = kind + ' ' + name + directiveLine + ' {';
|
|
11
|
+
const content = filterEmpty(fields).map(indent(2)).join('\n');
|
|
12
|
+
const lastLine = '}';
|
|
13
|
+
|
|
14
|
+
return [firstLine, content, lastLine].join('\n');
|
|
15
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { DMMF } from '../dmmf';
|
|
2
|
+
import { printObject } from './object';
|
|
3
|
+
|
|
4
|
+
export function printPrismaEnumModel(enumModel: DMMF.DatamodelEnum) {
|
|
5
|
+
const fields = Object.values(enumModel.values).map((value) => value.name);
|
|
6
|
+
return printObject('enum', enumModel.name, fields);
|
|
7
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { DMMF } from '../dmmf';
|
|
2
|
+
import { printInputConstraintDirective } from './directive';
|
|
3
|
+
import { printObject } from './object';
|
|
4
|
+
import { printType } from './type';
|
|
5
|
+
|
|
6
|
+
export function printPrismaInput(inputType: DMMF.InputType) {
|
|
7
|
+
const { minNumFields, maxNumFields } = inputType.constraints;
|
|
8
|
+
const requireConstraint = minNumFields === 1 && inputType.fields.length === 1;
|
|
9
|
+
|
|
10
|
+
let directive: string | undefined;
|
|
11
|
+
if (!requireConstraint) {
|
|
12
|
+
directive = printInputConstraintDirective(minNumFields, maxNumFields);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const fields = inputType.fields.map((field) =>
|
|
16
|
+
printInputField(field, requireConstraint)
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
return printObject('input', inputType.name, fields, directive);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function printInputField(field: DMMF.SchemaArg, requireConstraint: boolean) {
|
|
23
|
+
const type = printInputFieldScalar(field, requireConstraint);
|
|
24
|
+
if (!type) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
return `${field.name}: ${type}`;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function printInputFieldScalar(field: DMMF.SchemaArg, requireConstraint: boolean) {
|
|
31
|
+
const inputTypes = field.inputTypes.filter((inputType) => inputType.type !== 'Null');
|
|
32
|
+
|
|
33
|
+
if (inputTypes.length === 0) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const inputType = inputTypes[inputTypes.length - 1];
|
|
38
|
+
const inputTypeName = inputType.type.toString();
|
|
39
|
+
|
|
40
|
+
return printType(inputTypeName, {
|
|
41
|
+
kind: inputType.location,
|
|
42
|
+
list: inputType.isList,
|
|
43
|
+
required: (field.isRequired || requireConstraint) && !field.isNullable,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { DMMF } from '../dmmf';
|
|
2
|
+
import { printObject } from './object';
|
|
3
|
+
import { printType } from './type';
|
|
4
|
+
|
|
5
|
+
export function printPrismaModel(model: DMMF.Model) {
|
|
6
|
+
const fields = model.fields.map((field) => printModelField(field));
|
|
7
|
+
return printObject('type', model.name, fields);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function printModelField(field: DMMF.Field) {
|
|
11
|
+
return `${field.name}: ${printFieldScalar(field)}`;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function printFieldScalar(field: DMMF.Field) {
|
|
15
|
+
let name = field.type;
|
|
16
|
+
if (field.isId) {
|
|
17
|
+
name = 'ID';
|
|
18
|
+
}
|
|
19
|
+
return printType(name, {
|
|
20
|
+
kind: field.kind,
|
|
21
|
+
list: field.isList,
|
|
22
|
+
required: field.isRequired && field.kind !== 'object',
|
|
23
|
+
});
|
|
24
|
+
}
|