UNPKG

prisma-json-types-generator

Version:
112 lines (94 loc) 3.09 kB
import fs from 'fs/promises'; import { PrismaJsonTypesGeneratorConfig } from './config'; import { NAMESPACE_PATH } from './constants'; import { PrismaJsonTypesGeneratorError } from './error'; /** A changes made in the original file to help adjust any future coordinates of texts */ export interface TextDiff { start: number; diff: number; } /** * A class to help with reading and writing the Prisma Client types file concurrently and * converting positions indexes according with previous changes. */ export class DeclarationWriter { constructor( readonly filepath: string, private readonly options: PrismaJsonTypesGeneratorConfig ) {} /** The prisma's index.d.ts file content. */ public content = ''; private changeset: TextDiff[] = []; async template() { let namespace = await fs.readFile(NAMESPACE_PATH, 'utf-8'); // Removes trailing spaces namespace = namespace.trim(); // Replaces the namespace with the provided namespace namespace = namespace.replace(/\$\$NAMESPACE\$\$/g, this.options.namespace); // Includes previous file content return namespace + '\n' + this.content; } /** Loads the original file of sourcePath into memory. */ async load() { if (!(await fs.stat(this.filepath))) { throw new PrismaJsonTypesGeneratorError( 'Tried to load a file that does not exist', { filepath: this.filepath } ); } if (this.changeset.length) { throw new PrismaJsonTypesGeneratorError( 'Tried to load a file that has already been changed', { filepath: this.filepath, changeset: this.changeset } ); } this.content = await fs.readFile(this.filepath, 'utf-8'); } /** Save the original file of sourcePath with the content's contents */ async save() { // Resets current changeset and file content this.content = await this.template(); this.changeset = []; // Writes it into the disk await fs.writeFile(this.filepath, this.content); } /** * Replaces the coordinates with the provided text, adjusting the coords to previous * changes. * * @example * * ```txt * a 1 1 a * s 2 2 s * d 3 3 s <- (start: 1, end: 3, text: `s`) changed `s` to `ss` (start: 1, wide: 2) * 4 4 d * 5 5 * a 6 6 * s 7 7 a * d 8 8 s * 9 9 d * ``` */ replace(start: number, end: number, text: string) { // Adds a trailing space if (text[0] !== ' ') { text = ' ' + text; } // Maps the coordinates to the previous changes to adjust the position for the new text for (const change of this.changeset) { if (start > change.start) { start += change.diff; end += change.diff; } } // Replaces the file content at the correct position this.content = this.content.slice(0, start) + text + this.content.slice(end); // Adds the change to the list this.changeset.push({ start, // The difference between the old text and the new text diff: start - end + text.length }); } }