UNPKG

prisma-frontend

Version:

A Prisma generator for creating frontend-friendly exports (types and enums).

104 lines (88 loc) 3.44 kB
import {extractErrorMessage, log} from '@augment-vir/common'; import {createReadStream, createWriteStream} from 'node:fs'; import {mkdir} from 'node:fs/promises'; import {dirname, join} from 'node:path'; import {createInterface} from 'node:readline'; enum ParseMode { Models = 'models', Enum = 'enum', } async function openFileWriteStream(filePath: string) { await mkdir(dirname(filePath), {recursive: true}); const writeStream = createWriteStream(filePath); writeStream.on('error', (error: unknown) => { log.error(`Stream to types file failed: ${extractErrorMessage(error)}`); process.exit(1); }); return writeStream; } async function perFileLine(filePath: string, callback: (rawLine: string) => void | true) { const readLine = createInterface({ input: createReadStream(filePath), crlfDelay: Infinity, }); for await (const rawLine of readLine) { if (callback(rawLine)) { break; } } } /** * Reads inputs from a the generated JS client and then generates and writes the frontend output. * * @category Prisma Generator */ export async function generate(jsClientPath: string, outputDir: string) { const typesStream = await openFileWriteStream(join(outputDir, 'index.d.ts')); const jsStream = await openFileWriteStream(join(outputDir, 'index.js')); const generatedComment = `// generated at ${Date.now()}\n\n`; typesStream.write(generatedComment); typesStream.write("import type {Prisma} from '../client/index'"); jsStream.write(generatedComment); let currentParseMode = ParseMode.Models; await perFileLine(join(jsClientPath, 'index.d.ts'), (rawLine): void | true => { const line = rawLine.trim(); if (currentParseMode === ParseMode.Models) { if (line.startsWith('import * as runtime')) { typesStream.write(rawLine.replace('import *', 'import type *') + '\n'); } else if ( removeLineStarts.some((removeLineStart) => line.startsWith(removeLineStart)) ) { // skip these lines return; } else if (line.startsWith('export namespace $Enums {')) { currentParseMode = ParseMode.Enum; } else { typesStream.write(rawLine.replace('$Result.', 'runtime.Types.Result.') + '\n'); } // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition } else if (currentParseMode === ParseMode.Enum) { if (line === '}') { return true; } else if (line.startsWith('export type')) { return; } else { // types enum output if (line.startsWith('export const')) { typesStream.write( rawLine.replace(' const ', ' enum ').replace(': {', ' {') + '\n', ); } else { typesStream.write(rawLine.replace(": '", " = '") + '\n'); } // js enum output jsStream.write(rawLine.replace(': {', ' = {') + '\n'); } } }); typesStream.end(); jsStream.end(); } const removeLineStarts = [ 'import $Types =', 'import $Public =', 'import $Utils =', 'import $Extensions =', 'import $Result =', 'export type PrismaPromise<T>', ];