UNPKG

prisma-zod-generator

Version:

Prisma 2+ generator to emit Zod schemas from your Prisma schema

332 lines • 16.4 kB
"use strict"; /** * 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