Last active
November 7, 2023 14:52
-
-
Save stevenaanen/51788591ca8fc38fd40f54f8a2e6373f to your computer and use it in GitHub Desktop.
Transform Prisma Schema to js-friendly names
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// @ts-check | |
/* | |
* Run using `node convert-casing-after-prisma-pull.mjs` after installing `change-case` in your workspace. | |
* Then pipe your schema into it. | |
* | |
* Script will normalize the model names, field names and enums. | |
* It should not affect your database schema, only the generated js client from Prisma. | |
* | |
* Tip: after processing, run `prisma format` on the file. | |
*/ | |
import { camelCase, pascalCase } from "change-case"; | |
import fs from "node:fs"; | |
// read command line input stream and store in variable | |
const input = fs.readFileSync(0, "utf-8"); | |
// multiline split code blocks | |
const blocks = input.matchAll(/^.+\{\n[\S\s]*?\}/gm); | |
const PrismaScalars = [ | |
"String", | |
"Boolean", | |
"Int", | |
"BigInt", | |
"Float", | |
"Decimal", | |
"DateTime", | |
"Json", | |
"Bytes", | |
"Unsupported", | |
"String?", | |
"Boolean?", | |
"Int?", | |
"BigInt?", | |
"Float?", | |
"Decimal?", | |
"DateTime?", | |
"Json?", | |
"Bytes?", | |
"Unsupported?", | |
]; | |
// loop over iterator | |
for (const blockMatch of blocks) { | |
const block = blockMatch[0]; | |
const modelReg = /(?<type>model|enum) (?<modelName>\S+) \{/; | |
const modelName = modelReg.exec(block)?.groups?.modelName; | |
const lines = block.split("\n"); | |
const updatedLines = lines.map((line) => { | |
return ( | |
line | |
// Replace model name | |
.replace(modelReg, (_, modelType, modelName) => { | |
return `${modelType} ${pascalCase(modelName)} {`; | |
}) | |
// Replace field names and handle @map | |
.replace( | |
/^\s{2}(?<field>\w+_?[\w_]+)\s+(?<fieldType>[\w?]+)/, | |
(_, field, fieldType) => { | |
if (!PrismaScalars.includes(fieldType)) { | |
// these are relations | |
const isOptional = fieldType.endsWith("?"); | |
return ` ${pascalCase(field)} ${pascalCase(fieldType)}${ | |
isOptional ? "?" : "" | |
}`; | |
} | |
return ` ${camelCase(field)} ${fieldType} @map("${field}")`; | |
} | |
) | |
// Handle @relations | |
.replace( | |
/^\s{2}(?<field>\w+)\s+(?<relationName>[\w?]+)\s+@relation/, | |
(_, field, relationName) => { | |
const isOptional = relationName.endsWith("?"); | |
return ` ${pascalCase(field)} ${pascalCase(relationName)}${ | |
isOptional ? "?" : "" | |
} @relation`; | |
} | |
) | |
.replace( | |
/fields: \[(?<relationField>\w_?\w+)\]/, | |
(_, relationField) => { | |
return `fields: [${camelCase(relationField)}]`; | |
} | |
) | |
.replace( | |
/references: \[(?<referencesField>\w_?\w+)\]/, | |
(_, referencesField) => { | |
return `references: [${camelCase(referencesField)}]`; | |
} | |
) | |
.replace( | |
/references: \[(?<referencesField>\w_?\w+)\]/, | |
(_, referencesField) => { | |
return `references: [${camelCase(referencesField)}]`; | |
} | |
) | |
.replace( | |
/@@(?<type>id|index|unique)\(\[(?<relationships>[^\]]*)/, | |
(_, type, relationships) => { | |
const relations = relationships | |
.split(",") | |
.map((/** @type {string} */ r) => { | |
const relation = r.trim(); | |
if (relation.includes("(length: ")) { | |
return relation.replace( | |
/(?<key>\w+)(?<params>\([^\)]*)\)/, | |
(_, key, params) => { | |
return `${camelCase(key)} ${params})`; | |
} | |
); | |
} else { | |
return camelCase(relation); | |
} | |
}); | |
return `@@${type}([${relations.join(", ")}`; | |
} | |
) | |
// Handle constants | |
.replace(/^\s{2}(?<constant>[\w_]+)$/, (_, constant) => { | |
return ` ${pascalCase(constant)} @map("${constant}")`; | |
}) | |
.replace(/^\}/, "") | |
); | |
}); | |
const suffix = modelName ? `\n @@map("${modelName}")\n` : ""; | |
process.stdout.write(`${updatedLines.join("\n")}${suffix}}\n\n`); | |
} |
Nice! This helps a lot when pulling the schema from an old database.
I added a few things so that relationships are always CamelCase'd and relations and indexes keep working correctly.
Great improvements @DannyStreur! Updated the gist
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Nice! This helps a lot when pulling the schema from an old database.
I added a few things so that relationships are always CamelCase'd and relations and indexes keep working correctly.