prisma-trpc-generator
Version:
Prisma 2+ generator to emit fully implemented tRPC routers
268 lines • 11.2 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getProcedureTypeByOpName = exports.getInputTypeByOpName = exports.getRouterSchemaImportByOpName = exports.generateRouterImport = exports.generateMiddlewareImport = exports.generateShieldImport = exports.generatetRPCImport = exports.generateCreateRouterImport = void 0;
exports.generateBaseRouter = generateBaseRouter;
exports.generateProcedure = generateProcedure;
exports.generateRouterSchemaImports = generateRouterSchemaImports;
exports.resolveModelsComments = resolveModelsComments;
const internals_1 = require("@prisma/internals");
const getRelativePath_1 = __importDefault(require("./utils/getRelativePath"));
const uncapitalizeFirstLetter_1 = require("./utils/uncapitalizeFirstLetter");
const getProcedureName = (config) => {
return config.withShield
? 'shieldedProcedure'
: config.withMiddleware
? 'protectedProcedure'
: 'publicProcedure';
};
const generateCreateRouterImport = ({ sourceFile, config, }) => {
const imports = ['t'];
if (config) {
imports.push(getProcedureName(config));
}
sourceFile.addImportDeclaration({
moduleSpecifier: './helpers/createRouter',
namedImports: imports,
});
};
exports.generateCreateRouterImport = generateCreateRouterImport;
const generatetRPCImport = (sourceFile) => {
sourceFile.addImportDeclaration({
moduleSpecifier: '@trpc/server',
namespaceImport: 'trpc',
});
};
exports.generatetRPCImport = generatetRPCImport;
const generateShieldImport = (sourceFile, options, value) => {
const outputDir = (0, internals_1.parseEnvValue)(options.generator.output);
let shieldPath = (0, getRelativePath_1.default)(outputDir, 'shield/shield');
if (typeof value === 'string') {
shieldPath = (0, getRelativePath_1.default)(outputDir, value, true, options.schemaPath);
}
sourceFile.addImportDeclaration({
moduleSpecifier: shieldPath,
namedImports: ['permissions'],
});
};
exports.generateShieldImport = generateShieldImport;
const generateMiddlewareImport = (sourceFile, options) => {
const outputDir = (0, internals_1.parseEnvValue)(options.generator.output);
sourceFile.addImportDeclaration({
moduleSpecifier: (0, getRelativePath_1.default)(outputDir, 'middleware'),
namedImports: ['permissions'],
});
};
exports.generateMiddlewareImport = generateMiddlewareImport;
const generateRouterImport = (sourceFile, modelNamePlural, modelNameCamelCase) => {
sourceFile.addImportDeclaration({
moduleSpecifier: `./${modelNameCamelCase}.router`,
namedImports: [`${modelNamePlural}Router`],
});
};
exports.generateRouterImport = generateRouterImport;
function generateBaseRouter(sourceFile, config, options) {
const outputDir = (0, internals_1.parseEnvValue)(options.generator.output);
sourceFile.addStatements(/* ts */ `
import type { Context } from '${(0, getRelativePath_1.default)(outputDir, config.contextPath, true, options.schemaPath)}';
`);
if (config.trpcOptionsPath) {
sourceFile.addStatements(/* ts */ `
import trpcOptions from '${(0, getRelativePath_1.default)(outputDir, config.trpcOptionsPath, true, options.schemaPath)}';
`);
}
sourceFile.addStatements(/* ts */ `
export const t = trpc.initTRPC.context<Context>().create(${config.trpcOptionsPath ? 'trpcOptions' : ''});
`);
const middlewares = [];
if (config.withMiddleware && typeof config.withMiddleware === 'boolean') {
sourceFile.addStatements(/* ts */ `
export const globalMiddleware = t.middleware(async ({ ctx, next }) => {
// Add your middleware logic here
return next()
});`);
middlewares.push({
type: 'global',
value: /* ts */ `.use(globalMiddleware)`,
});
}
if (config.withMiddleware && typeof config.withMiddleware === 'string') {
sourceFile.addStatements(/* ts */ `
import defaultMiddleware from '${(0, getRelativePath_1.default)(outputDir, config.withMiddleware, true, options.schemaPath)}';
`);
sourceFile.addStatements(/* ts */ `
export const globalMiddleware = t.middleware(defaultMiddleware);`);
middlewares.push({
type: 'global',
value: /* ts */ `.use(globalMiddleware)`,
});
}
if (config.withShield) {
sourceFile.addStatements(/* ts */ `
export const permissionsMiddleware = t.middleware(permissions); `);
middlewares.push({
type: 'shield',
value: /* ts */ `
.use(permissions)`,
});
}
sourceFile.addStatements(/* ts */ `
export const publicProcedure = t.procedure; `);
if (middlewares.length > 0) {
const procName = getProcedureName(config);
middlewares.forEach((middleware, i) => {
if (i === 0) {
sourceFile.addStatements(/* ts */ `
export const ${procName} = t.procedure
`);
}
sourceFile.addStatements(/* ts */ `
.use(${middleware.type === 'shield'
? 'permissionsMiddleware'
: 'globalMiddleware'})
`);
});
}
}
function generateProcedure(sourceFile, name, typeName, modelName, opType, baseOpType, config) {
let input = `input${!config.withZod ? ' as any' : ''}`;
const nameWithoutModel = name.replace(modelName, '');
if (nameWithoutModel === 'groupBy' && config.withZod) {
input =
'{ where: input.where, orderBy: input.orderBy, by: input.by, having: input.having, take: input.take, skip: input.skip }';
}
sourceFile.addStatements(/* ts */ `${config.showModelNameInProcedure ? name : nameWithoutModel}: ${getProcedureName(config)}
${config.withZod ? `.input(${typeName})` : ''}.${(0, exports.getProcedureTypeByOpName)(baseOpType)}(async ({ ctx, input }) => {
const ${name} = await ctx.prisma.${(0, uncapitalizeFirstLetter_1.uncapitalizeFirstLetter)(modelName)}.${opType.replace('One', '')}(${input});
return ${name};
}),`);
}
function generateRouterSchemaImports(sourceFile, modelName, modelActions) {
sourceFile.addStatements(
/* ts */
[
// remove any duplicate import statements
...new Set(modelActions.map((opName) => (0, exports.getRouterSchemaImportByOpName)(opName, modelName))),
].join('\n'));
}
const getRouterSchemaImportByOpName = (opName, modelName) => {
const opType = opName.replace('OrThrow', '');
const inputType = (0, exports.getInputTypeByOpName)(opType, modelName);
return inputType
? `import { ${inputType} } from "../schemas/${opType}${modelName}.schema"; `
: '';
};
exports.getRouterSchemaImportByOpName = getRouterSchemaImportByOpName;
const getInputTypeByOpName = (opName, modelName) => {
let inputType;
switch (opName) {
case 'findUnique':
inputType = `${modelName}FindUniqueSchema`;
break;
case 'findFirst':
inputType = `${modelName}FindFirstSchema`;
break;
case 'findMany':
inputType = `${modelName}FindManySchema`;
break;
case 'findRaw':
inputType = `${modelName}FindRawObjectSchema`;
break;
case 'createOne':
inputType = `${modelName}CreateOneSchema`;
break;
case 'createMany':
inputType = `${modelName}CreateManySchema`;
break;
case 'deleteOne':
inputType = `${modelName}DeleteOneSchema`;
break;
case 'updateOne':
inputType = `${modelName}UpdateOneSchema`;
break;
case 'deleteMany':
inputType = `${modelName}DeleteManySchema`;
break;
case 'updateMany':
inputType = `${modelName}UpdateManySchema`;
break;
case 'upsertOne':
inputType = `${modelName}UpsertSchema`;
break;
case 'aggregate':
inputType = `${modelName}AggregateSchema`;
break;
case 'aggregateRaw':
inputType = `${modelName}AggregateRawObjectSchema`;
break;
case 'groupBy':
inputType = `${modelName}GroupBySchema`;
break;
default:
// Fallback for unknown operation types
}
return inputType;
};
exports.getInputTypeByOpName = getInputTypeByOpName;
const getProcedureTypeByOpName = (opName) => {
let procType;
switch (opName) {
case 'findUnique':
case 'findFirst':
case 'findMany':
case 'findRaw':
case 'aggregate':
case 'aggregateRaw':
case 'groupBy':
procType = 'query';
break;
case 'createOne':
case 'createMany':
case 'deleteOne':
case 'updateOne':
case 'deleteMany':
case 'updateMany':
case 'upsertOne':
procType = 'mutation';
break;
default:
// Fallback for unknown operation types
}
return procType;
};
exports.getProcedureTypeByOpName = getProcedureTypeByOpName;
function resolveModelsComments(models, hiddenModels) {
var _a, _b, _c, _d, _e, _f;
const modelAttributeRegex = /(@@Gen\.)+([A-z])+(\()+(.+)+(\))+/;
const attributeNameRegex = /(?:\.)+([A-Za-z])+(?:\()+/;
const attributeArgsRegex = /(?:\()+([A-Za-z])+:+(.+)+(?:\))+/;
for (const model of models) {
if (model.documentation) {
const attribute = (_b = (_a = model.documentation) === null || _a === void 0 ? void 0 : _a.match(modelAttributeRegex)) === null || _b === void 0 ? void 0 : _b[0];
const attributeName = (_d = (_c = attribute === null || attribute === void 0 ? void 0 : attribute.match(attributeNameRegex)) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.slice(1, -1);
if (attributeName !== 'model')
continue;
const rawAttributeArgs = (_f = (_e = attribute === null || attribute === void 0 ? void 0 : attribute.match(attributeArgsRegex)) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.slice(1, -1);
const parsedAttributeArgs = {};
if (rawAttributeArgs) {
const rawAttributeArgsParts = rawAttributeArgs
.split(':')
.map((it) => it.trim())
.map((part) => (part.startsWith('[') ? part : part.split(',')))
.flat()
.map((it) => it.trim());
for (let i = 0; i < rawAttributeArgsParts.length; i += 2) {
const key = rawAttributeArgsParts[i];
const value = rawAttributeArgsParts[i + 1];
parsedAttributeArgs[key] = JSON.parse(value);
}
}
if (parsedAttributeArgs.hide) {
hiddenModels.push(model.name);
}
}
}
}
//# sourceMappingURL=helpers.js.map