prisma-zod-generator
Version:
Prisma 2+ generator to emit Zod schemas from your Prisma schema
332 lines ⢠16.4 kB
JavaScript
;
/**
* PZG Pro Generator Implementation
*
* This matches the main prisma-zod-generator pattern but loads Pro feature
* modules lazily so the OSS build compiles without the private submodule.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PRO_HELP_MESSAGE = void 0;
exports.generateProFeatures = generateProFeatures;
const internals_1 = require("@prisma/internals");
const fs_1 = require("fs");
const path_1 = __importDefault(require("path"));
const license_1 = require("../license");
exports.PRO_HELP_MESSAGE = [
'PZG Pro modules are not available in this repository.',
'To enable Pro features:',
' 1. Purchase a PZG Pro license',
' 2. Initialize the private submodule:',
' git submodule update --init --recursive',
' 3. Re-run your command',
'Docs & pricing: https://omar-dulaimi.github.io/prisma-zod-generator/pricing',
].join('\n');
async function generateProFeatures(options) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
try {
console.log('š Starting PZG Pro Generator...');
const licenseStatus = await (0, license_1.getLicenseStatus)();
if (!licenseStatus.valid) {
throwProMissing();
}
if (licenseStatus.plan) {
console.log(`ā
Valid PZG Pro license (${(0, license_1.describePlan)(licenseStatus.plan)} (${licenseStatus.plan}))`);
}
else {
console.log('ā
Valid PZG Pro license');
}
const prismaClientGeneratorConfig = options.otherGenerators.find((gen) => (0, internals_1.parseEnvValue)(gen.provider) === 'prisma-client-js' ||
(0, internals_1.parseEnvValue)(gen.provider) === 'prisma-client');
if (!prismaClientGeneratorConfig) {
throw new Error('prisma-client-js or prisma-client generator is required');
}
const dmmf = await (0, internals_1.getDMMF)({
datamodel: options.datamodel,
previewFeatures: prismaClientGeneratorConfig.previewFeatures,
});
console.log(`š Analyzed schema: ${dmmf.datamodel.models.length} models, ${dmmf.schema.enumTypes.prisma.length + (((_a = dmmf.schema.enumTypes.model) === null || _a === void 0 ? void 0 : _a.length) || 0)} enums`);
const config = await parseProConfig(options);
const outputPath = config.outputPath || path_1.default.join(path_1.default.dirname(options.schemaPath), 'generated', 'pro');
await fs_1.promises.mkdir(outputPath, { recursive: true });
const dataSource = (_b = options.datasources) === null || _b === void 0 ? void 0 : _b[0];
const provider = (dataSource === null || dataSource === void 0 ? void 0 : dataSource.provider) || 'postgresql';
const previewFeatures = prismaClientGeneratorConfig.previewFeatures;
const prismaClientPath = getPrismaClientPath(prismaClientGeneratorConfig);
console.log(`š Output directory: ${outputPath}`);
console.log(`š§ Database provider: ${provider}`);
const features = loadFeatureModules();
const enabledFeatures = [];
const featurePromises = [];
if (config.enablePolicies) {
enabledFeatures.push('Policies & Redaction');
featurePromises.push(features
.generatePoliciesFromDMMF(dmmf, {}, options.schemaPath, path_1.default.join(outputPath, 'policies'), prismaClientPath, provider, (_c = config.policies) !== null && _c !== void 0 ? _c : {}, previewFeatures)
.catch((error) => handleFeatureError('Policies generation failed', error)));
}
if (config.enableServerActions) {
enabledFeatures.push('Server Actions');
featurePromises.push(features
.generateServerActionsFromDMMF(dmmf, {}, options.schemaPath, path_1.default.join(outputPath, 'server-actions'), prismaClientPath, provider, (_d = config.serverActions) !== null && _d !== void 0 ? _d : {}, previewFeatures)
.catch((error) => handleFeatureError('Server Actions generation failed', error)));
}
if (config.enableSDK) {
enabledFeatures.push('Client SDK');
featurePromises.push(features
.generateSDKFromDMMF(dmmf, {}, options.schemaPath, path_1.default.join(outputPath, 'sdk'), prismaClientPath, provider, (_e = config.sdk) !== null && _e !== void 0 ? _e : {}, previewFeatures)
.catch((error) => handleFeatureError('SDK generation failed', error)));
}
if (config.enableContracts) {
enabledFeatures.push('Contract Testing');
featurePromises.push(features
.generateContractTestsFromDMMF(dmmf, {}, options.schemaPath, path_1.default.join(outputPath, 'contracts'), prismaClientPath, provider, (_f = config.contracts) !== null && _f !== void 0 ? _f : {}, previewFeatures)
.catch((error) => handleFeatureError('Contract Testing generation failed', error)));
}
if (config.enablePostgresRLS) {
enabledFeatures.push('PostgreSQL RLS');
featurePromises.push(features
.generatePostgresRLSFromDMMF(dmmf, {}, options.schemaPath, path_1.default.join(outputPath, 'postgres-rls'), prismaClientPath, provider, (_g = config.postgresRls) !== null && _g !== void 0 ? _g : {}, previewFeatures)
.catch((error) => handleFeatureError('PostgreSQL RLS generation failed', error)));
}
if (config.enableForms) {
enabledFeatures.push('Form UX');
featurePromises.push(features
.generateFormUXFromDMMF(dmmf, {}, options.schemaPath, path_1.default.join(outputPath, 'forms'), prismaClientPath, provider, (_h = config.forms) !== null && _h !== void 0 ? _h : {}, previewFeatures)
.catch((error) => handleFeatureError('Form UX generation failed', error)));
}
if (config.enableApiDocs) {
enabledFeatures.push('API Documentation');
featurePromises.push(features
.generateAPIDocsFromDMMF(dmmf, {}, options.schemaPath, path_1.default.join(outputPath, 'api-docs'), prismaClientPath, provider, (_j = config.apiDocs) !== null && _j !== void 0 ? _j : {}, previewFeatures)
.catch((error) => handleFeatureError('API Documentation generation failed', error)));
}
if (config.enableMultiTenant) {
enabledFeatures.push('Multi-Tenant Kit');
featurePromises.push(features
.generateMultiTenantKitFromDMMF(dmmf, {}, options.schemaPath, path_1.default.join(outputPath, 'multi-tenant'), prismaClientPath, provider, (_k = config.multiTenant) !== null && _k !== void 0 ? _k : {}, previewFeatures)
.catch((error) => handleFeatureError('Multi-Tenant Kit generation failed', error)));
}
if (config.enablePerformance) {
enabledFeatures.push('Performance Pack');
featurePromises.push(features
.generatePerformancePack(options.schemaPath, {
outputPath: path_1.default.join(outputPath, 'performance'),
...((_l = config.performance) !== null && _l !== void 0 ? _l : {}),
})
.catch((error) => handleFeatureError('Performance Pack generation failed', error)));
}
if (config.enableFactories) {
enabledFeatures.push('Data Factories');
featurePromises.push(features
.generateDataFactories(options.schemaPath, {
outputPath: path_1.default.join(outputPath, 'factories'),
...((_m = config.factories) !== null && _m !== void 0 ? _m : {}),
})
.catch((error) => handleFeatureError('Data Factories generation failed', error)));
}
await Promise.allSettled(featurePromises);
console.log('\nā
PZG Pro Generation Complete!');
if (enabledFeatures.length > 0) {
console.log(`š¦ Generated features: ${enabledFeatures.join(', ')}`);
}
else {
console.log('ā ļø No features enabled. Configure features in your generator config.');
console.log('\nExample configuration:');
console.log('generator pzgPro {');
console.log(' provider = "node ./node_modules/prisma-zod-generator/lib/cli/pzg-pro.js"');
console.log(' output = "./generated/pro"');
console.log(' enablePolicies = true');
console.log(' enableServerActions = true');
console.log('}');
}
}
catch (error) {
console.error('\nā PZG Pro Generation Failed:');
if (error instanceof Error) {
console.error(error.message);
if (error.stack) {
console.error(error.stack);
}
}
else {
console.error('Unknown error occurred');
}
process.exit(1);
}
}
function loadFeatureModules() {
return {
generatePoliciesFromDMMF: loadProExport('features/policies/policies', 'generatePoliciesFromDMMF'),
generateServerActionsFromDMMF: loadProExport('features/server-actions/server-actions', 'generateServerActionsFromDMMF'),
generateSDKFromDMMF: loadProExport('features/sdk-publisher/sdk-publisher', 'generateSDKFromDMMF'),
generateContractTestsFromDMMF: loadProExport('features/contract-testing/contract-testing', 'generateContractTestsFromDMMF'),
generatePostgresRLSFromDMMF: loadProExport('features/postgres-rls/postgres-rls', 'generatePostgresRLSFromDMMF'),
generateFormUXFromDMMF: loadProExport('features/form-ux/form-ux', 'generateFormUXFromDMMF'),
generateAPIDocsFromDMMF: loadProExport('features/api-docs/api-docs', 'generateAPIDocsFromDMMF'),
generateMultiTenantKitFromDMMF: loadProExport('features/multi-tenant-kit/multi-tenant-kit', 'generateMultiTenantKitFromDMMF'),
generatePerformancePack: loadProExport('features/performance-pack/performance-pack', 'generatePerformancePack'),
generateDataFactories: loadProExport('features/data-factories/data-factories', 'generateDataFactories'),
};
}
function loadProExport(moduleSuffix, exportName) {
const modulePath = ['..', 'pro', ...moduleSuffix.split('/')].join('/');
try {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const mod = require(modulePath);
if (!(exportName in mod)) {
throw new Error(`Missing export "${exportName}" in ${modulePath}`);
}
return mod[exportName];
}
catch (error) {
if (isMissingProModuleError(error, modulePath)) {
throwProMissing();
}
throw error;
}
}
function isMissingProModuleError(error, modulePath) {
var _a;
if (!(error instanceof Error)) {
return false;
}
const nodeError = error;
if (nodeError.code !== 'MODULE_NOT_FOUND') {
return false;
}
const normalized = modulePath.replace(/\\/g, '/');
const message = (_a = nodeError.message) === null || _a === void 0 ? void 0 : _a.replace(/\\/g, '/');
return (message === null || message === void 0 ? void 0 : message.includes('/pro/')) || (message === null || message === void 0 ? void 0 : message.includes(normalized)) || false;
}
function throwProMissing() {
throw new Error(exports.PRO_HELP_MESSAGE);
}
function handleFeatureError(context, error) {
const detail = error instanceof Error ? error.message : String(error);
console.error(`ā ${context}: ${detail}`);
if (error instanceof Error && error.stack) {
console.error(error.stack);
}
}
async function parseProConfig(options) {
const config = {
enablePolicies: false,
enableServerActions: false,
enableSDK: false,
enableContracts: false,
enablePostgresRLS: false,
enableForms: false,
enableApiDocs: false,
enableMultiTenant: false,
enablePerformance: false,
enableFactories: false,
};
const generatorConfig = options.generator.config;
const booleanFlags = [
'enablePolicies',
'enableServerActions',
'enableSDK',
'enableContracts',
'enablePostgresRLS',
'enableForms',
'enableApiDocs',
'enableMultiTenant',
'enablePerformance',
'enableFactories',
];
for (const flag of booleanFlags) {
if (generatorConfig[flag] !== undefined) {
config[flag] = String(generatorConfig[flag]) === 'true';
}
}
if (generatorConfig.outputPath) {
config.outputPath = String(generatorConfig.outputPath);
}
const contractConfigKeys = [];
for (const key in generatorConfig) {
if (key.startsWith('contracts') && key !== 'enableContracts') {
contractConfigKeys.push(key);
}
}
if (contractConfigKeys.length > 0) {
config.contracts = {};
for (const key of contractConfigKeys) {
const contractKey = key.replace('contracts', '').charAt(0).toLowerCase() +
key.replace('contracts', '').slice(1);
let value = generatorConfig[key];
if (contractKey === 'providers' || contractKey === 'consumers') {
value = String(value)
.split(',')
.map((s) => s.trim())
.filter((s) => s);
}
config.contracts[contractKey] = value;
}
}
if (generatorConfig.configPath) {
config.configPath = String(generatorConfig.configPath);
try {
const schemaBaseDir = path_1.default.dirname(options.schemaPath);
const configFilePath = path_1.default.isAbsolute(config.configPath)
? config.configPath
: path_1.default.resolve(schemaBaseDir, config.configPath);
const externalConfig = JSON.parse(await fs_1.promises.readFile(configFilePath, 'utf-8'));
Object.assign(config, externalConfig);
}
catch (error) {
const detail = error instanceof Error ? error.message : String(error);
console.warn(`ā ļø Failed to load external config: ${detail}`);
}
}
const featureKeys = [
'policies',
'serverActions',
'sdk',
'contracts',
'postgresRls',
'forms',
'apiDocs',
'multiTenant',
'performance',
'factories',
];
for (const key of featureKeys) {
if (generatorConfig[key] !== undefined) {
try {
config[key] =
typeof generatorConfig[key] === 'string'
? JSON.parse(String(generatorConfig[key]))
: generatorConfig[key];
}
catch {
config[key] = generatorConfig[key];
}
}
}
return config;
}
function getPrismaClientPath(prismaClientGeneratorConfig) {
var _a;
if ((_a = prismaClientGeneratorConfig === null || prismaClientGeneratorConfig === void 0 ? void 0 : prismaClientGeneratorConfig.output) === null || _a === void 0 ? void 0 : _a.value) {
const rawValue = (0, internals_1.parseEnvValue)(prismaClientGeneratorConfig.output);
const looksLikeNodeModules = rawValue === null || rawValue === void 0 ? void 0 : rawValue.includes('node_modules');
if (!prismaClientGeneratorConfig.isCustomOutput || looksLikeNodeModules) {
return '@prisma/client';
}
const provider = (prismaClientGeneratorConfig === null || prismaClientGeneratorConfig === void 0 ? void 0 : prismaClientGeneratorConfig.provider)
? (0, internals_1.parseEnvValue)(prismaClientGeneratorConfig.provider)
: undefined;
let outputValue = rawValue;
if (provider === 'prisma-client') {
const hasExtension = path_1.default.extname(outputValue) !== '';
if (!hasExtension && outputValue && !/\/?client(?:\.[a-z]+)?$/i.test(outputValue)) {
outputValue = path_1.default.join(outputValue, 'client');
}
}
return outputValue || '@prisma/client';
}
return '@prisma/client';
}
//# sourceMappingURL=pzg-pro-generator.js.map