zenstack
Version:
FullStack enhancement for Prisma ORM: seamless integration from database to UI
147 lines • 8 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.description = exports.name = void 0;
exports.trackPrismaSchemaError = trackPrismaSchemaError;
const sdk_1 = require("@zenstackhq/sdk");
const ast_1 = require("@zenstackhq/sdk/ast");
const prisma_1 = require("@zenstackhq/sdk/prisma");
const colors_1 = __importDefault(require("colors"));
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const strip_color_1 = __importDefault(require("strip-color"));
const telemetry_1 = __importDefault(require("../../telemetry"));
const exec_utils_1 = require("../../utils/exec-utils");
const pkg_utils_1 = require("../../utils/pkg-utils");
const schema_generator_1 = require("./schema-generator");
exports.name = 'Prisma';
exports.description = 'Generating Prisma schema';
const run = (model, options, _dmmf, _globalOptions) => __awaiter(void 0, void 0, void 0, function* () {
// deal with calculation of the default output location
const output = options.output
? (0, sdk_1.resolvePath)(options.output, options)
: getDefaultPrismaOutputFile(options.schemaPath);
const mergedOptions = Object.assign(Object.assign({}, options), { output });
const { warnings, shortNameMap } = yield new schema_generator_1.PrismaSchemaGenerator(model).generate(mergedOptions);
// the path to import the prisma client from
let prismaClientPath = '@prisma/client';
// the real path where the prisma client was generated
let clientOutputDir = '.prisma/client';
// the path to the prisma client dts file
let prismaClientDtsPath = undefined;
if (options.generateClient !== false) {
let generateCmd = `prisma generate --schema "${output}"`;
if (typeof options.generateArgs === 'string') {
generateCmd += ` ${options.generateArgs}`;
}
try {
// run 'prisma generate'
yield (0, exec_utils_1.execPackage)(generateCmd, { stdio: 'ignore' });
}
catch (_a) {
yield trackPrismaSchemaError(output);
try {
// run 'prisma generate' again with output to the console
yield (0, exec_utils_1.execPackage)(generateCmd);
}
catch (_b) {
// noop
}
throw new sdk_1.PluginError(exports.name, `Failed to run "prisma generate"`);
}
// extract user-provided prisma client output path
const generator = model.declarations.find((d) => (0, ast_1.isGeneratorDecl)(d) &&
d.fields.some((f) => f.name === 'provider' && (0, sdk_1.getLiteral)(f.value) === 'prisma-client-js'));
const clientOutputField = generator === null || generator === void 0 ? void 0 : generator.fields.find((f) => f.name === 'output');
const clientOutput = (0, sdk_1.getLiteral)(clientOutputField === null || clientOutputField === void 0 ? void 0 : clientOutputField.value);
if (clientOutput) {
if (path_1.default.isAbsolute(clientOutput)) {
prismaClientPath = clientOutput;
}
else {
// first get absolute path based on prisma schema location
const absPath = path_1.default.resolve(path_1.default.dirname(output), clientOutput);
// then make it relative to the zmodel schema location
prismaClientPath = (0, sdk_1.normalizedRelative)(path_1.default.dirname(options.schemaPath), absPath);
}
// record custom location where the prisma client was generated
clientOutputDir = prismaClientPath;
}
// get PrismaClient dts path
if (clientOutput) {
// if a custom prisma client output path is configured, first try treating
// clientOutputDir as a relative path and locate the index.d.ts file
prismaClientDtsPath = path_1.default.resolve(path_1.default.dirname(options.schemaPath), clientOutputDir, 'index.d.ts');
}
if (!prismaClientDtsPath || !fs_1.default.existsSync(prismaClientDtsPath)) {
// if the file does not exist, try node module resolution
try {
// the resolution is relative to the schema path by default
let resolveBase = path_1.default.dirname(options.schemaPath);
if (!clientOutput) {
// PrismaClient is generated into the default location, considering symlinked
// environments like pnpm, we need to first resolve "@prisma/client",and then
// resolve the ".prisma/client/index.d.ts" file relative to that
resolveBase = path_1.default.dirname(require.resolve('@prisma/client', { paths: [resolveBase] }));
}
const prismaClientResolvedPath = require.resolve(clientOutputDir, { paths: [resolveBase] });
prismaClientDtsPath = path_1.default.join(path_1.default.dirname(prismaClientResolvedPath), 'index.d.ts');
}
catch (err) {
console.warn(colors_1.default.yellow(`Could not resolve PrismaClient type declaration path. This may break plugins that depend on it.`));
}
}
}
else {
console.warn(colors_1.default.yellow('Skipping prisma client generation because "generateClient" is set to false. This may break plugins that depend on the prisma client.'));
}
// load the result DMMF
const dmmf = yield (0, prisma_1.getDMMF)({
datamodel: fs_1.default.readFileSync(output, 'utf-8'),
});
return { warnings, dmmf, prismaClientPath, prismaClientDtsPath, shortNameMap };
});
function getDefaultPrismaOutputFile(schemaPath) {
var _a;
// handle override from package.json
const pkgJsonPath = (0, pkg_utils_1.findUp)(['package.json'], path_1.default.dirname(schemaPath));
if (pkgJsonPath) {
const pkgJson = JSON.parse(fs_1.default.readFileSync(pkgJsonPath, 'utf-8'));
if (typeof ((_a = pkgJson === null || pkgJson === void 0 ? void 0 : pkgJson.zenstack) === null || _a === void 0 ? void 0 : _a.prisma) === 'string') {
if (path_1.default.isAbsolute(pkgJson.zenstack.prisma)) {
return pkgJson.zenstack.prisma;
}
else {
// resolve relative to package.json
return path_1.default.resolve(path_1.default.dirname(pkgJsonPath), pkgJson.zenstack.prisma);
}
}
}
return (0, sdk_1.resolvePath)('./prisma/schema.prisma', { schemaPath });
}
function trackPrismaSchemaError(schema) {
return __awaiter(this, void 0, void 0, function* () {
try {
yield (0, prisma_1.getDMMF)({ datamodel: fs_1.default.readFileSync(schema, 'utf-8') });
}
catch (err) {
if (err instanceof Error) {
// eslint-disable-next-line @typescript-eslint/no-var-requires
telemetry_1.default.track('prisma:error', { command: 'generate', message: (0, strip_color_1.default)(err.message) });
}
}
});
}
exports.default = run;
//# sourceMappingURL=index.js.map
;