refactor source code
This commit is contained in:
@@ -1,82 +1,82 @@
|
||||
import { DateTimeResolver, JSONObjectResolver } from 'graphql-scalars';
|
||||
import { DateTimeResolver, JSONObjectResolver } from 'graphql-scalars'
|
||||
import PrismaPlugin, {
|
||||
PothosPrismaDatamodel,
|
||||
PrismaClient,
|
||||
} from '@pothos/plugin-prisma';
|
||||
import { Request, Response } from 'express';
|
||||
} from '@pothos/plugin-prisma'
|
||||
import { Request, Response } from 'express'
|
||||
import SmartSubscriptionPlugin, {
|
||||
subscribeOptionsFromIterator,
|
||||
} from '@pothos/plugin-smart-subscriptions';
|
||||
} from '@pothos/plugin-smart-subscriptions'
|
||||
|
||||
import AuthzPlugin from '@pothos/plugin-authz';
|
||||
import ErrorsPlugin from '@pothos/plugin-errors';
|
||||
import type { FileUpload } from 'graphql-upload/processRequest.js';
|
||||
import GraphQLUpload from 'graphql-upload/GraphQLUpload.js';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { PrismaCrudGenerator } from './graphql.generator';
|
||||
import type PrismaTypes from '../types/pothos.generated';
|
||||
import PrismaUtils from '@pothos/plugin-prisma-utils';
|
||||
import { PubSub } from 'graphql-subscriptions';
|
||||
import RelayPlugin from '@pothos/plugin-relay';
|
||||
import SchemaBuilder from '@pothos/core';
|
||||
import SimpleObjectPlugin from '@pothos/plugin-simple-objects';
|
||||
import { User } from '@prisma/client';
|
||||
import { getDatamodel } from '../types/pothos.generated';
|
||||
import AuthzPlugin from '@pothos/plugin-authz'
|
||||
import ErrorsPlugin from '@pothos/plugin-errors'
|
||||
import type { FileUpload } from 'graphql-upload/processRequest.js'
|
||||
import GraphQLUpload from 'graphql-upload/GraphQLUpload.js'
|
||||
import { Injectable } from '@nestjs/common'
|
||||
import { PrismaCrudGenerator } from './graphql.generator'
|
||||
import type PrismaTypes from '../types/pothos.generated'
|
||||
import PrismaUtils from '@pothos/plugin-prisma-utils'
|
||||
import { PubSub } from 'graphql-subscriptions'
|
||||
import RelayPlugin from '@pothos/plugin-relay'
|
||||
import SchemaBuilder from '@pothos/core'
|
||||
import SimpleObjectPlugin from '@pothos/plugin-simple-objects'
|
||||
import { User } from '@prisma/client'
|
||||
import { getDatamodel } from '../types/pothos.generated'
|
||||
|
||||
// import { rules } from '../common/graphql/common.graphql.auth-rule';
|
||||
|
||||
export type SchemaContext =
|
||||
| {
|
||||
isSubscription: true;
|
||||
isSubscription: true
|
||||
websocket: {
|
||||
pubSub: PubSub;
|
||||
me: User;
|
||||
generator: PrismaCrudGenerator<BuilderTypes>;
|
||||
};
|
||||
pubSub: PubSub
|
||||
me: User
|
||||
generator: PrismaCrudGenerator<BuilderTypes>
|
||||
}
|
||||
}
|
||||
| {
|
||||
isSubscription: false;
|
||||
isSubscription: false
|
||||
http: {
|
||||
req: Request;
|
||||
res: Response;
|
||||
me: User;
|
||||
pubSub: PubSub;
|
||||
generator: PrismaCrudGenerator<BuilderTypes>;
|
||||
};
|
||||
};
|
||||
req: Request
|
||||
res: Response
|
||||
me: User
|
||||
pubSub: PubSub
|
||||
generator: PrismaCrudGenerator<BuilderTypes>
|
||||
}
|
||||
}
|
||||
|
||||
// extend prisma types to contain string type
|
||||
export interface SchemaBuilderOption {
|
||||
Context: SchemaContext;
|
||||
PrismaTypes: PrismaTypes;
|
||||
DataModel: PothosPrismaDatamodel;
|
||||
Context: SchemaContext
|
||||
PrismaTypes: PrismaTypes
|
||||
DataModel: PothosPrismaDatamodel
|
||||
Connection: {
|
||||
totalCount: number | (() => number | Promise<number>);
|
||||
};
|
||||
totalCount: number | (() => number | Promise<number>)
|
||||
}
|
||||
// AuthZRule: keyof typeof rules;
|
||||
Scalars: {
|
||||
DateTime: {
|
||||
Input: Date;
|
||||
Output: Date;
|
||||
};
|
||||
Input: Date
|
||||
Output: Date
|
||||
}
|
||||
Json: {
|
||||
Input: JSON;
|
||||
Output: JSON;
|
||||
};
|
||||
Input: JSON
|
||||
Output: JSON
|
||||
}
|
||||
Upload: {
|
||||
Input: FileUpload;
|
||||
Output: FileUpload;
|
||||
};
|
||||
Input: FileUpload
|
||||
Output: FileUpload
|
||||
}
|
||||
Int: {
|
||||
Input: number;
|
||||
Output: number | bigint | string;
|
||||
};
|
||||
};
|
||||
Input: number
|
||||
Output: number | bigint | string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class Builder extends SchemaBuilder<SchemaBuilderOption> {
|
||||
public generator: PrismaCrudGenerator<BuilderTypes>;
|
||||
public generator: PrismaCrudGenerator<BuilderTypes>
|
||||
|
||||
constructor(private readonly prisma: PrismaClient) {
|
||||
super({
|
||||
@@ -93,9 +93,9 @@ export class Builder extends SchemaBuilder<SchemaBuilderOption> {
|
||||
debounceDelay: 1000,
|
||||
...subscribeOptionsFromIterator((name, ctx) => {
|
||||
if (ctx.isSubscription) {
|
||||
return ctx.websocket.pubSub.asyncIterator(name);
|
||||
return ctx.websocket.pubSub.asyncIterator(name)
|
||||
}
|
||||
return ctx.http.pubSub.asyncIterator(name);
|
||||
return ctx.http.pubSub.asyncIterator(name)
|
||||
}),
|
||||
},
|
||||
relay: {},
|
||||
@@ -109,15 +109,15 @@ export class Builder extends SchemaBuilder<SchemaBuilderOption> {
|
||||
errors: {
|
||||
defaultTypes: [],
|
||||
},
|
||||
});
|
||||
this.generator = new PrismaCrudGenerator<BuilderTypes>(this);
|
||||
this.addScalarType('DateTime', DateTimeResolver);
|
||||
this.addScalarType('Json', JSONObjectResolver);
|
||||
this.addScalarType('Upload', GraphQLUpload);
|
||||
})
|
||||
this.generator = new PrismaCrudGenerator<BuilderTypes>(this)
|
||||
this.addScalarType('DateTime', DateTimeResolver)
|
||||
this.addScalarType('Json', JSONObjectResolver)
|
||||
this.addScalarType('Upload', GraphQLUpload)
|
||||
|
||||
this.queryType({});
|
||||
this.mutationType({});
|
||||
this.subscriptionType({});
|
||||
this.queryType({})
|
||||
this.mutationType({})
|
||||
this.subscriptionType({})
|
||||
|
||||
this.globalConnectionField('totalCount', (t) =>
|
||||
t.int({
|
||||
@@ -127,10 +127,10 @@ export class Builder extends SchemaBuilder<SchemaBuilderOption> {
|
||||
? parent.totalCount()
|
||||
: parent.totalCount,
|
||||
}),
|
||||
);
|
||||
)
|
||||
|
||||
// test print ManagedServiceWhereUniqueInput
|
||||
}
|
||||
}
|
||||
export type BuilderTypes =
|
||||
PothosSchemaTypes.ExtendDefaultTypes<SchemaBuilderOption>;
|
||||
PothosSchemaTypes.ExtendDefaultTypes<SchemaBuilderOption>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Inject, Injectable } from '@nestjs/common'
|
||||
|
||||
import {
|
||||
type BaseEnum,
|
||||
@@ -7,14 +7,14 @@ import {
|
||||
type InputType,
|
||||
type InputTypeParam,
|
||||
type SchemaTypes,
|
||||
} from '@pothos/core';
|
||||
import { type PrismaModelTypes, getModel } from '@pothos/plugin-prisma';
|
||||
import type { FilterOps } from '@pothos/plugin-prisma-utils';
|
||||
import * as Prisma from '@prisma/client';
|
||||
import { SchemaBuilderToken } from '@smatch-corp/nestjs-pothos';
|
||||
} from '@pothos/core'
|
||||
import { type PrismaModelTypes, getModel } from '@pothos/plugin-prisma'
|
||||
import type { FilterOps } from '@pothos/plugin-prisma-utils'
|
||||
import * as Prisma from '@prisma/client'
|
||||
import { SchemaBuilderToken } from '@smatch-corp/nestjs-pothos'
|
||||
|
||||
const filterOps = ['equals', 'in', 'notIn', 'not'] as const;
|
||||
const sortableFilterProps = ['lt', 'lte', 'gt', 'gte'] as const;
|
||||
const filterOps = ['equals', 'in', 'notIn', 'not'] as const
|
||||
const sortableFilterProps = ['lt', 'lte', 'gt', 'gte'] as const
|
||||
const stringFilterOps = [
|
||||
...filterOps,
|
||||
'contains',
|
||||
@@ -22,29 +22,29 @@ const stringFilterOps = [
|
||||
'endsWith',
|
||||
'mode',
|
||||
'search',
|
||||
] as const;
|
||||
const sortableTypes = ['String', 'Int', 'Float', 'DateTime', 'BigInt'] as const;
|
||||
const listOps = ['every', 'some', 'none'] as const;
|
||||
] as const
|
||||
const sortableTypes = ['String', 'Int', 'Float', 'DateTime', 'BigInt'] as const
|
||||
const listOps = ['every', 'some', 'none'] as const
|
||||
const scalarListOps = [
|
||||
'has',
|
||||
'hasSome',
|
||||
'hasEvery',
|
||||
'isEmpty',
|
||||
'equals',
|
||||
] as const;
|
||||
const JsonFilterOps = ['equals', 'in', 'notIn', 'not'] as const;
|
||||
const EnumFilterOps = ['equals', 'not'] as const;
|
||||
] as const
|
||||
const JsonFilterOps = ['equals', 'in', 'notIn', 'not'] as const
|
||||
const EnumFilterOps = ['equals', 'not'] as const
|
||||
@Injectable()
|
||||
export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
||||
private refCache = new Map<
|
||||
InputType<Types> | string,
|
||||
Map<string, InputObjectRef<Types, unknown>>
|
||||
>();
|
||||
>()
|
||||
|
||||
private enumRefs = new Map<string, EnumRef<Types, unknown>>();
|
||||
private enumRefs = new Map<string, EnumRef<Types, unknown>>()
|
||||
|
||||
constructor(
|
||||
//
|
||||
//
|
||||
@Inject(SchemaBuilderToken)
|
||||
private builder: PothosSchemaTypes.SchemaBuilder<Types>,
|
||||
) {}
|
||||
@@ -75,7 +75,7 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
||||
type: 'Int',
|
||||
required: false,
|
||||
}),
|
||||
}));
|
||||
}))
|
||||
}
|
||||
|
||||
findUniqueArgs<Name extends string & keyof Types['PrismaTypes']>(
|
||||
@@ -86,7 +86,7 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
||||
type: this.getWhereUnique(modelName),
|
||||
required: true,
|
||||
}),
|
||||
}));
|
||||
}))
|
||||
}
|
||||
|
||||
getWhere<Name extends string & keyof Types['PrismaTypes']>(
|
||||
@@ -95,19 +95,19 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
||||
) {
|
||||
const withoutName = (without ?? [])
|
||||
.map((name) => `Without${capitalize(name)}`)
|
||||
.join('');
|
||||
const fullName = `${modelName}${withoutName}Filter`;
|
||||
.join('')
|
||||
const fullName = `${modelName}${withoutName}Filter`
|
||||
|
||||
return this.getRef(modelName, fullName, () => {
|
||||
const model = getModel(modelName, this.builder);
|
||||
const model = getModel(modelName, this.builder)
|
||||
|
||||
return this.builder.prismaWhere(modelName, {
|
||||
name: fullName,
|
||||
fields: (() => {
|
||||
const fields: Record<string, InputType<Types>> = {};
|
||||
const fields: Record<string, InputType<Types>> = {}
|
||||
const withoutFields = model.fields.filter((field) =>
|
||||
without?.includes(field.name),
|
||||
);
|
||||
)
|
||||
|
||||
model.fields
|
||||
.filter(
|
||||
@@ -119,7 +119,7 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
||||
),
|
||||
)
|
||||
.forEach((field) => {
|
||||
let type;
|
||||
let type
|
||||
switch (field.kind) {
|
||||
case 'scalar':
|
||||
type = field.isList
|
||||
@@ -128,49 +128,49 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
||||
)
|
||||
: this.getFilter(
|
||||
this.mapScalarType(field.type) as InputType<Types>,
|
||||
);
|
||||
break;
|
||||
)
|
||||
break
|
||||
case 'enum':
|
||||
type = field.isList
|
||||
? this.getScalarListFilter(this.getEnum(field.type))
|
||||
: this.getFilter(this.getEnum(field.type));
|
||||
break;
|
||||
: this.getFilter(this.getEnum(field.type))
|
||||
break
|
||||
case 'object':
|
||||
type = field.isList
|
||||
? this.getListFilter(this.getWhere(field.type as Name))
|
||||
: this.getWhere(field.type as Name);
|
||||
break;
|
||||
: this.getWhere(field.type as Name)
|
||||
break
|
||||
case 'unsupported':
|
||||
break;
|
||||
break
|
||||
default:
|
||||
throw new Error(`Unknown field kind ${field.kind}`);
|
||||
throw new Error(`Unknown field kind ${field.kind}`)
|
||||
}
|
||||
|
||||
if (!type) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
fields[field.name] = type;
|
||||
});
|
||||
fields[field.name] = type
|
||||
})
|
||||
|
||||
return fields;
|
||||
return fields
|
||||
}) as never,
|
||||
}) as InputObjectRef<
|
||||
Types,
|
||||
(PrismaModelTypes & Types['PrismaTypes'][Name])['Where']
|
||||
>;
|
||||
});
|
||||
>
|
||||
})
|
||||
}
|
||||
getWhereUnique<Name extends string & keyof Types['PrismaTypes']>(
|
||||
modelName: Name,
|
||||
) {
|
||||
const name = `${modelName}UniqueFilter`;
|
||||
const name = `${modelName}UniqueFilter`
|
||||
|
||||
return this.getRef(modelName, name, () => {
|
||||
const model = getModel(modelName, this.builder);
|
||||
const model = getModel(modelName, this.builder)
|
||||
return this.builder.prismaWhereUnique(modelName, {
|
||||
name,
|
||||
fields: (() => {
|
||||
const fields: Record<string, InputType<Types>> = {};
|
||||
const fields: Record<string, InputType<Types>> = {}
|
||||
|
||||
model.fields
|
||||
.filter(
|
||||
@@ -183,73 +183,73 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
||||
model.primaryKey?.fields.includes(field.name),
|
||||
)
|
||||
.forEach((field) => {
|
||||
let type;
|
||||
let type
|
||||
switch (field.kind) {
|
||||
case 'scalar':
|
||||
type = this.mapScalarType(field.type) as InputType<Types>;
|
||||
break;
|
||||
type = this.mapScalarType(field.type) as InputType<Types>
|
||||
break
|
||||
case 'enum':
|
||||
type = this.getEnum(field.type);
|
||||
break;
|
||||
type = this.getEnum(field.type)
|
||||
break
|
||||
case 'object':
|
||||
case 'unsupported':
|
||||
break;
|
||||
break
|
||||
default:
|
||||
throw new Error(`Unknown field kind ${field.kind}`);
|
||||
throw new Error(`Unknown field kind ${field.kind}`)
|
||||
}
|
||||
|
||||
if (!type) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
fields[field.name] = type;
|
||||
});
|
||||
fields[field.name] = type
|
||||
})
|
||||
|
||||
return fields;
|
||||
return fields
|
||||
}) as never,
|
||||
}) as InputObjectRef<
|
||||
Types,
|
||||
(PrismaModelTypes & Types['PrismaTypes'][Name])['WhereUnique']
|
||||
>;
|
||||
});
|
||||
>
|
||||
})
|
||||
}
|
||||
getOrderBy<Name extends string & keyof Types['PrismaTypes']>(
|
||||
modelName: Name,
|
||||
) {
|
||||
const name = `${modelName}OrderBy`;
|
||||
const name = `${modelName}OrderBy`
|
||||
return this.getRef(modelName, name, () => {
|
||||
const model = getModel(modelName, this.builder);
|
||||
const model = getModel(modelName, this.builder)
|
||||
|
||||
return this.builder.prismaOrderBy(modelName, {
|
||||
name,
|
||||
fields: () => {
|
||||
const fields: Record<string, InputType<Types> | boolean> = {};
|
||||
const fields: Record<string, InputType<Types> | boolean> = {}
|
||||
|
||||
model.fields.forEach((field) => {
|
||||
let type;
|
||||
let type
|
||||
switch (field.kind) {
|
||||
case 'scalar':
|
||||
case 'enum':
|
||||
type = true;
|
||||
break;
|
||||
type = true
|
||||
break
|
||||
case 'object':
|
||||
type = this.getOrderBy(field.type as Name);
|
||||
break;
|
||||
type = this.getOrderBy(field.type as Name)
|
||||
break
|
||||
case 'unsupported':
|
||||
break;
|
||||
break
|
||||
default:
|
||||
throw new Error(`Unknown field kind ${field.kind}`);
|
||||
throw new Error(`Unknown field kind ${field.kind}`)
|
||||
}
|
||||
|
||||
if (type) {
|
||||
fields[field.name] = type;
|
||||
fields[field.name] = type
|
||||
}
|
||||
});
|
||||
})
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||
return fields as {};
|
||||
return fields as {}
|
||||
},
|
||||
});
|
||||
});
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
getCreateInput<Name extends string & keyof Types['PrismaTypes']>(
|
||||
@@ -258,21 +258,21 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
||||
) {
|
||||
const withoutName = (without ?? [])
|
||||
.map((name) => `Without${capitalize(name)}`)
|
||||
.join('');
|
||||
const fullName = `${modelName}Create${withoutName}Input`;
|
||||
.join('')
|
||||
const fullName = `${modelName}Create${withoutName}Input`
|
||||
|
||||
return this.getRef(modelName, fullName, () => {
|
||||
const model = getModel(modelName, this.builder);
|
||||
const model = getModel(modelName, this.builder)
|
||||
return this.builder.prismaCreate(modelName, {
|
||||
name: fullName,
|
||||
fields: (() => {
|
||||
const fields: Record<string, InputTypeParam<Types>> = {};
|
||||
const fields: Record<string, InputTypeParam<Types>> = {}
|
||||
const withoutFields = model.fields.filter((field) =>
|
||||
without?.includes(field.name),
|
||||
);
|
||||
)
|
||||
const relationIds = model.fields.flatMap(
|
||||
(field) => field.relationFromFields ?? [],
|
||||
);
|
||||
)
|
||||
|
||||
model.fields
|
||||
.filter(
|
||||
@@ -284,35 +284,35 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
||||
) && !relationIds.includes(field.name),
|
||||
)
|
||||
.forEach((field) => {
|
||||
let type;
|
||||
let type
|
||||
switch (field.kind) {
|
||||
case 'scalar':
|
||||
type = this.mapScalarType(field.type) as InputType<Types>;
|
||||
break;
|
||||
type = this.mapScalarType(field.type) as InputType<Types>
|
||||
break
|
||||
case 'enum':
|
||||
type = this.getEnum(field.type);
|
||||
break;
|
||||
type = this.getEnum(field.type)
|
||||
break
|
||||
case 'object':
|
||||
type = this.getCreateRelationInput(modelName, field.name);
|
||||
break;
|
||||
type = this.getCreateRelationInput(modelName, field.name)
|
||||
break
|
||||
case 'unsupported':
|
||||
break;
|
||||
break
|
||||
default:
|
||||
throw new Error(`Unknown field kind ${field.kind}`);
|
||||
throw new Error(`Unknown field kind ${field.kind}`)
|
||||
}
|
||||
|
||||
if (type) {
|
||||
fields[field.name] = type;
|
||||
fields[field.name] = type
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
return fields;
|
||||
return fields
|
||||
}) as never,
|
||||
}) as InputObjectRef<
|
||||
Types,
|
||||
(PrismaModelTypes & Types['PrismaTypes'][Name])['Create']
|
||||
>;
|
||||
});
|
||||
>
|
||||
})
|
||||
}
|
||||
|
||||
getCreateRelationInput<
|
||||
@@ -327,30 +327,30 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
||||
`${modelName}${capitalize(relation)}`,
|
||||
'CreateRelationInput',
|
||||
() => {
|
||||
const model = getModel(modelName, this.builder);
|
||||
const model = getModel(modelName, this.builder)
|
||||
return this.builder.prismaCreateRelation(modelName, relation, {
|
||||
fields: () => {
|
||||
const relationField = model.fields.find(
|
||||
(field) => field.name === relation,
|
||||
)!;
|
||||
const relatedModel = getModel(relationField.type, this.builder);
|
||||
)!
|
||||
const relatedModel = getModel(relationField.type, this.builder)
|
||||
const relatedFieldName = relatedModel.fields.find(
|
||||
(field) => field.relationName === relationField.relationName,
|
||||
)!;
|
||||
)!
|
||||
|
||||
return {
|
||||
create: this.getCreateInput(relationField.type as Name, [
|
||||
relatedFieldName.name,
|
||||
]),
|
||||
connect: this.getWhereUnique(relationField.type as Name),
|
||||
};
|
||||
}
|
||||
},
|
||||
} as never) as InputObjectRef<
|
||||
Types,
|
||||
NonNullable<Model['Create'][Relation & keyof Model['Update']]>
|
||||
>;
|
||||
>
|
||||
},
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
getCreateManyInput<Name extends string & keyof Types['PrismaTypes']>(
|
||||
@@ -359,22 +359,22 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
||||
) {
|
||||
const withoutName = (without ?? [])
|
||||
.map((name) => `Without${capitalize(name)}`)
|
||||
.join('');
|
||||
const fullName = `${modelName}Create${withoutName}Input`;
|
||||
.join('')
|
||||
const fullName = `${modelName}Create${withoutName}Input`
|
||||
|
||||
return this.getRef(modelName, fullName, () => {
|
||||
const model = getModel(modelName, this.builder);
|
||||
const model = getModel(modelName, this.builder)
|
||||
|
||||
return this.builder.prismaCreateMany(modelName, {
|
||||
name: fullName,
|
||||
fields: (() => {
|
||||
const fields: Record<string, InputTypeParam<Types>> = {};
|
||||
const fields: Record<string, InputTypeParam<Types>> = {}
|
||||
const withoutFields = model.fields.filter((field) =>
|
||||
without?.includes(field.name),
|
||||
);
|
||||
)
|
||||
const relationIds = model.fields.flatMap(
|
||||
(field) => field.relationFromFields ?? [],
|
||||
);
|
||||
)
|
||||
|
||||
model.fields
|
||||
.filter(
|
||||
@@ -386,32 +386,32 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
||||
) && !relationIds.includes(field.name),
|
||||
)
|
||||
.forEach((field) => {
|
||||
let type;
|
||||
let type
|
||||
switch (field.kind) {
|
||||
case 'scalar':
|
||||
type = this.mapScalarType(field.type) as InputType<Types>;
|
||||
break;
|
||||
type = this.mapScalarType(field.type) as InputType<Types>
|
||||
break
|
||||
case 'enum':
|
||||
type = this.getEnum(field.type);
|
||||
break;
|
||||
type = this.getEnum(field.type)
|
||||
break
|
||||
case 'unsupported':
|
||||
break;
|
||||
break
|
||||
default:
|
||||
throw new Error(`Unknown field kind ${field.kind}`);
|
||||
throw new Error(`Unknown field kind ${field.kind}`)
|
||||
}
|
||||
|
||||
if (type) {
|
||||
fields[field.name] = type;
|
||||
fields[field.name] = type
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
return fields;
|
||||
return fields
|
||||
}) as never,
|
||||
}) as InputObjectRef<
|
||||
Types,
|
||||
(PrismaModelTypes & Types['PrismaTypes'][Name])['Create']
|
||||
>;
|
||||
});
|
||||
>
|
||||
})
|
||||
}
|
||||
|
||||
getUpdateInput<Name extends string & keyof Types['PrismaTypes']>(
|
||||
@@ -420,21 +420,21 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
||||
) {
|
||||
const withoutName = (without ?? [])
|
||||
.map((name) => `Without${capitalize(name)}`)
|
||||
.join('');
|
||||
const fullName = `${modelName}Update${withoutName}Input`;
|
||||
.join('')
|
||||
const fullName = `${modelName}Update${withoutName}Input`
|
||||
|
||||
return this.getRef(modelName, fullName, () => {
|
||||
const model = getModel(modelName, this.builder);
|
||||
const model = getModel(modelName, this.builder)
|
||||
return this.builder.prismaUpdate(modelName, {
|
||||
name: fullName,
|
||||
fields: (() => {
|
||||
const fields: Record<string, InputTypeParam<Types>> = {};
|
||||
const fields: Record<string, InputTypeParam<Types>> = {}
|
||||
const withoutFields = model.fields.filter((field) =>
|
||||
without?.includes(field.name),
|
||||
);
|
||||
)
|
||||
const relationIds = model.fields.flatMap(
|
||||
(field) => field.relationFromFields ?? [],
|
||||
);
|
||||
)
|
||||
|
||||
model.fields
|
||||
.filter(
|
||||
@@ -446,35 +446,35 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
||||
) && !relationIds.includes(field.name),
|
||||
)
|
||||
.forEach((field) => {
|
||||
let type;
|
||||
let type
|
||||
switch (field.kind) {
|
||||
case 'scalar':
|
||||
type = this.mapScalarType(field.type) as InputType<Types>;
|
||||
break;
|
||||
type = this.mapScalarType(field.type) as InputType<Types>
|
||||
break
|
||||
case 'enum':
|
||||
type = this.getEnum(field.type);
|
||||
break;
|
||||
type = this.getEnum(field.type)
|
||||
break
|
||||
case 'object':
|
||||
type = this.getUpdateRelationInput(modelName, field.name);
|
||||
break;
|
||||
type = this.getUpdateRelationInput(modelName, field.name)
|
||||
break
|
||||
case 'unsupported':
|
||||
break;
|
||||
break
|
||||
default:
|
||||
throw new Error(`Unknown field kind ${field.kind}`);
|
||||
throw new Error(`Unknown field kind ${field.kind}`)
|
||||
}
|
||||
|
||||
if (type) {
|
||||
fields[field.name] = type;
|
||||
fields[field.name] = type
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
return fields;
|
||||
return fields
|
||||
}) as never,
|
||||
}) as InputObjectRef<
|
||||
Types,
|
||||
(PrismaModelTypes & Types['PrismaTypes'][Name])['Update']
|
||||
>;
|
||||
});
|
||||
>
|
||||
})
|
||||
}
|
||||
getUpdateRelationInput<
|
||||
Name extends string & keyof Types['PrismaTypes'],
|
||||
@@ -488,16 +488,16 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
||||
`${modelName}${capitalize(relation)}`,
|
||||
'UpdateRelationInput',
|
||||
() => {
|
||||
const model = getModel(modelName, this.builder);
|
||||
const model = getModel(modelName, this.builder)
|
||||
return this.builder.prismaUpdateRelation(modelName, relation, {
|
||||
fields: () => {
|
||||
const relationField = model.fields.find(
|
||||
(field) => field.name === relation,
|
||||
)!;
|
||||
const relatedModel = getModel(relationField.type, this.builder);
|
||||
)!
|
||||
const relatedModel = getModel(relationField.type, this.builder)
|
||||
const relatedFieldName = relatedModel.fields.find(
|
||||
(field) => field.relationName === relationField.relationName,
|
||||
)!.name;
|
||||
)!.name
|
||||
|
||||
if (relationField.isList) {
|
||||
return {
|
||||
@@ -531,7 +531,7 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
||||
deleteMany: this.getWhere(relationField.type as Name, [
|
||||
relatedFieldName,
|
||||
]),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -544,38 +544,38 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
||||
connect: this.getWhereUnique(relationField.type as Name),
|
||||
disconnect: relationField.isRequired ? undefined : 'Boolean',
|
||||
delete: relationField.isRequired ? undefined : 'Boolean',
|
||||
};
|
||||
}
|
||||
},
|
||||
} as never) as InputObjectRef<
|
||||
Types,
|
||||
NonNullable<Model['Update'][Relation & keyof Model['Update']]>
|
||||
>;
|
||||
>
|
||||
},
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
private getFilter(type: InputType<Types>) {
|
||||
return this.getRef(type, `${String(type)}Filter`, () => {
|
||||
const ops: FilterOps[] = [...filterOps];
|
||||
const ops: FilterOps[] = [...filterOps]
|
||||
|
||||
if (type === 'String') {
|
||||
ops.push(...stringFilterOps);
|
||||
ops.push(...stringFilterOps)
|
||||
}
|
||||
if (sortableTypes.includes(type as never)) {
|
||||
ops.push(...sortableFilterProps);
|
||||
ops.push(...sortableFilterProps)
|
||||
}
|
||||
if (type === 'Json') {
|
||||
ops.push(...JsonFilterOps);
|
||||
ops.push(...JsonFilterOps)
|
||||
}
|
||||
// type enum
|
||||
if (type === 'Enum') {
|
||||
ops.push(...EnumFilterOps);
|
||||
ops.push(...EnumFilterOps)
|
||||
}
|
||||
|
||||
return this.builder.prismaFilter(type, {
|
||||
ops,
|
||||
});
|
||||
});
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
private getScalarListFilter(type: InputType<Types>) {
|
||||
@@ -583,7 +583,7 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
||||
this.builder.prismaScalarListFilter(type, {
|
||||
ops: scalarListOps,
|
||||
}),
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
private getListFilter(type: InputType<Types>) {
|
||||
@@ -591,7 +591,7 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
||||
this.builder.prismaListFilter(type, {
|
||||
ops: listOps,
|
||||
}),
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
private getEnum(name: string) {
|
||||
@@ -601,12 +601,12 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
||||
{
|
||||
name,
|
||||
},
|
||||
);
|
||||
)
|
||||
|
||||
this.enumRefs.set(name, enumRef);
|
||||
this.enumRefs.set(name, enumRef)
|
||||
}
|
||||
|
||||
return this.enumRefs.get(name)!;
|
||||
return this.enumRefs.get(name)!
|
||||
}
|
||||
|
||||
private mapScalarType(type: string) {
|
||||
@@ -617,9 +617,9 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
||||
case 'Float':
|
||||
case 'DateTime':
|
||||
case 'Json':
|
||||
return type;
|
||||
return type
|
||||
default:
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -629,24 +629,24 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
||||
create: () => T,
|
||||
): T {
|
||||
if (!this.refCache.has(key)) {
|
||||
this.refCache.set(key, new Map());
|
||||
this.refCache.set(key, new Map())
|
||||
}
|
||||
const cache = this.refCache.get(key)!;
|
||||
const cache = this.refCache.get(key)!
|
||||
|
||||
if (cache.has(name)) {
|
||||
return cache.get(name)! as T;
|
||||
return cache.get(name)! as T
|
||||
}
|
||||
|
||||
const ref = new InputObjectRef<Types, unknown>(name);
|
||||
const ref = new InputObjectRef<Types, unknown>(name)
|
||||
|
||||
cache.set(name, ref);
|
||||
cache.set(name, ref)
|
||||
|
||||
this.builder.configStore.associateParamWithRef(ref, create());
|
||||
this.builder.configStore.associateParamWithRef(ref, create())
|
||||
|
||||
return ref as T;
|
||||
return ref as T
|
||||
}
|
||||
}
|
||||
|
||||
function capitalize(str: string) {
|
||||
return str[0].toUpperCase() + str.slice(1);
|
||||
return str[0].toUpperCase() + str.slice(1)
|
||||
}
|
||||
|
||||
@@ -1,44 +1,44 @@
|
||||
import { Global, Module } from '@nestjs/common';
|
||||
import { Global, Module } from '@nestjs/common'
|
||||
|
||||
import { AdminNoteModule } from '../AdminNote/adminnote.module';
|
||||
import { ApolloDriverConfig } from '@nestjs/apollo';
|
||||
import { AppConfigModule } from '../AppConfig/appconfig.module';
|
||||
import { Builder } from './graphql.builder';
|
||||
import { CategoryModule } from '../Category/category.module';
|
||||
import { CenterMentorModule } from '../CenterMentor/centermentor.module';
|
||||
import { CenterModule } from '../Center/center.module';
|
||||
import { ChatroomModule } from '../ChatRoom/chatroom.module';
|
||||
import { CommonModule } from '../common/common.module';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
import { GraphQLModule } from '@nestjs/graphql';
|
||||
import { GraphqlService } from './graphql.service';
|
||||
import { ManagedServiceModule } from '../ManagedService/managedservice.module';
|
||||
import { MessageModule } from '../Message/message.module';
|
||||
import { MilestoneModule } from '../Milestone/milestone.module';
|
||||
import { OrderModule } from '../Order/order.module';
|
||||
import { PaymentModule } from '../Payment/payment.module';
|
||||
import { PothosApolloDriver } from '@smatch-corp/nestjs-pothos-apollo-driver';
|
||||
import { PothosModule } from '@smatch-corp/nestjs-pothos';
|
||||
import { PrismaCrudGenerator } from './graphql.generator';
|
||||
import { PrismaModule } from '../Prisma/prisma.module';
|
||||
import { PrismaService } from '../Prisma/prisma.service';
|
||||
import { RedisModule } from 'src/Redis/redis.module';
|
||||
import { RedisService } from 'src/Redis/redis.service';
|
||||
import { RefundTicketModule } from '../RefundTicket/refundticket.module';
|
||||
import { Request } from 'express';
|
||||
import { ResumeModule } from '../Resume/resume.module';
|
||||
import { ScheduleModule } from '../Schedule/schedule.module';
|
||||
import { ServiceAndCategoryModule } from '../ServiceAndCategory/serviceandcategory.module';
|
||||
import { ServiceFeedbackModule } from '../ServiceFeedback/servicefeedback.module';
|
||||
import { ServiceMeetingRoomModule } from '../ServiceMeetingRoom/servicemeetingroom.module';
|
||||
import { ServiceModule } from '../Service/service.module';
|
||||
import { UploadedFileModule } from '../UploadedFile/uploadedfile.module';
|
||||
import { UserModule } from '../User/user.module';
|
||||
import { WorkshopMeetingRoomModule } from '../WorkshopMeetingRoom/workshopmeetingroom.module';
|
||||
import { WorkshopModule } from '../Workshop/workshop.module';
|
||||
import { WorkshopOrganizationModule } from '../WorkshopOrganization/workshoporganization.module';
|
||||
import { WorkshopSubscriptionModule } from '../WorkshopSubscription/workshopsubscription.module';
|
||||
import { initContextCache } from '@pothos/core';
|
||||
import { AdminNoteModule } from '../AdminNote/adminnote.module'
|
||||
import { ApolloDriverConfig } from '@nestjs/apollo'
|
||||
import { AppConfigModule } from '../AppConfig/appconfig.module'
|
||||
import { Builder } from './graphql.builder'
|
||||
import { CategoryModule } from '../Category/category.module'
|
||||
import { CenterMentorModule } from '../CenterMentor/centermentor.module'
|
||||
import { CenterModule } from '../Center/center.module'
|
||||
import { ChatroomModule } from '../ChatRoom/chatroom.module'
|
||||
import { CommonModule } from '../common/common.module'
|
||||
import { ConfigModule } from '@nestjs/config'
|
||||
import { GraphQLModule } from '@nestjs/graphql'
|
||||
import { GraphqlService } from './graphql.service'
|
||||
import { ManagedServiceModule } from '../ManagedService/managedservice.module'
|
||||
import { MessageModule } from '../Message/message.module'
|
||||
import { MilestoneModule } from '../Milestone/milestone.module'
|
||||
import { OrderModule } from '../Order/order.module'
|
||||
import { PaymentModule } from '../Payment/payment.module'
|
||||
import { PothosApolloDriver } from '@smatch-corp/nestjs-pothos-apollo-driver'
|
||||
import { PothosModule } from '@smatch-corp/nestjs-pothos'
|
||||
import { PrismaCrudGenerator } from './graphql.generator'
|
||||
import { PrismaModule } from '../Prisma/prisma.module'
|
||||
import { PrismaService } from '../Prisma/prisma.service'
|
||||
import { RedisModule } from 'src/Redis/redis.module'
|
||||
import { RedisService } from 'src/Redis/redis.service'
|
||||
import { RefundTicketModule } from '../RefundTicket/refundticket.module'
|
||||
import { Request } from 'express'
|
||||
import { ResumeModule } from '../Resume/resume.module'
|
||||
import { ScheduleModule } from '../Schedule/schedule.module'
|
||||
import { ServiceAndCategoryModule } from '../ServiceAndCategory/serviceandcategory.module'
|
||||
import { ServiceFeedbackModule } from '../ServiceFeedback/servicefeedback.module'
|
||||
import { ServiceMeetingRoomModule } from '../ServiceMeetingRoom/servicemeetingroom.module'
|
||||
import { ServiceModule } from '../Service/service.module'
|
||||
import { UploadedFileModule } from '../UploadedFile/uploadedfile.module'
|
||||
import { UserModule } from '../User/user.module'
|
||||
import { WorkshopMeetingRoomModule } from '../WorkshopMeetingRoom/workshopmeetingroom.module'
|
||||
import { WorkshopModule } from '../Workshop/workshop.module'
|
||||
import { WorkshopOrganizationModule } from '../WorkshopOrganization/workshoporganization.module'
|
||||
import { WorkshopSubscriptionModule } from '../WorkshopSubscription/workshopsubscription.module'
|
||||
import { initContextCache } from '@pothos/core'
|
||||
|
||||
@Global()
|
||||
@Module({
|
||||
|
||||
@@ -3,13 +3,13 @@ import {
|
||||
Injectable,
|
||||
Logger,
|
||||
UnauthorizedException,
|
||||
} from '@nestjs/common';
|
||||
} from '@nestjs/common'
|
||||
|
||||
import { PrismaService } from '../Prisma/prisma.service';
|
||||
import { Request } from 'express';
|
||||
import { clerkClient } from '@clerk/express';
|
||||
import { PrismaService } from '../Prisma/prisma.service'
|
||||
import { Request } from 'express'
|
||||
import { clerkClient } from '@clerk/express'
|
||||
|
||||
import { RedisService } from '../Redis/redis.service';
|
||||
import { RedisService } from '../Redis/redis.service'
|
||||
|
||||
@Injectable()
|
||||
export class GraphqlService {
|
||||
@@ -20,37 +20,37 @@ export class GraphqlService {
|
||||
|
||||
async acquireContext(req: Request) {
|
||||
// get x-session-id from headers
|
||||
let sessionId: string;
|
||||
const disableAuth = process.env.DISABLE_AUTH === 'true';
|
||||
let sessionId: string
|
||||
const disableAuth = process.env.DISABLE_AUTH === 'true'
|
||||
try {
|
||||
sessionId = req.headers['x-session-id'] as string;
|
||||
sessionId = req.headers['x-session-id'] as string
|
||||
} catch (error) {
|
||||
Logger.error('Error acquiring context', error);
|
||||
Logger.error('Error acquiring context', error)
|
||||
if (disableAuth) {
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
throw new UnauthorizedException('Must provide a session ID');
|
||||
throw new UnauthorizedException('Must provide a session ID')
|
||||
}
|
||||
if (disableAuth) {
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
// redis context cache
|
||||
const cachedUser = await this.redis.getUser(sessionId);
|
||||
const cachedUser = await this.redis.getUser(sessionId)
|
||||
if (cachedUser) {
|
||||
return cachedUser;
|
||||
return cachedUser
|
||||
}
|
||||
// check if the token is valid
|
||||
const session = await clerkClient.sessions.getSession(sessionId as string);
|
||||
const session = await clerkClient.sessions.getSession(sessionId as string)
|
||||
if (!session) {
|
||||
throw new UnauthorizedException('Invalid session');
|
||||
throw new UnauthorizedException('Invalid session')
|
||||
}
|
||||
const user = await this.prisma.user.findUnique({
|
||||
where: { id: session.userId },
|
||||
});
|
||||
})
|
||||
if (!user) {
|
||||
throw new UnauthorizedException('User not found');
|
||||
throw new UnauthorizedException('User not found')
|
||||
}
|
||||
await this.redis.setUser(sessionId, user, session.expireAt);
|
||||
return user;
|
||||
await this.redis.setUser(sessionId, user, session.expireAt)
|
||||
return user
|
||||
}
|
||||
}
|
||||
|
||||
12262
src/Graphql/types/graphql.d.ts
vendored
12262
src/Graphql/types/graphql.d.ts
vendored
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user