prisma-case-format
prisma introspect
names its model 1:1 with your database's conventions. Most of the time that is probably fine, however you may want or need different conventions in the generated client library. prisma-case-format
makes it simple and direct to get the case conventions you want, applied across an entire schema.prisma
with optional overrides per model
or field
.
Use Cases
As a one-time migration assistant
Did prisma introspect
on your huge database schema mis-case all your tables & fields? Is it wrecking your hope of using duck-types? Use --dry-run
in combination with --(map)?-(table|field|enum)-case
to figure out which case conventions are correct for your project. Once things look correct, drop the flag to save changes to the specified --file
, which is your local root schema.prisma
by default.
As a dedicated linter for your schema.prisma
prisma-case-format
aims to be idempotent, so you can use it to confirm that case conventions in your schema.prisma
have not accidentally drifted. prisma-case-format
can be applied on-commit or on-push, either in a git commit-hook package or as a CI/CD step. Use --dry-run
to diff changes with the original file, or backup the original and compare to the edit.
With NextAuth.js
If your team is using NextAuth.js
, you may have encountered an issue where prisma-case-format
steam rolls the strict data contract expected by the NextAuth.js
integration. Specify the --uses-next-auth
flag in order to protect your NextAuth.js
tables from your specified conventions.
With varying conventions
If you inherited or were forced to produce a database schema that has deviations in case conventions, prisma-case-format
can ensure these conventions remain stable. See the config file section below.
Usage
❯ prisma-case-format --help
Usage: prisma-case-format [options]
Give your schema.prisma sane naming conventions
Options:
-f, --file <file> cwd-relative path to `schema.prisma` file (default: "schema.prisma")
-c, --config-file <cfgFile> cwd-relative path to `.prisma-case-format` config file (default: ".prisma-case-format")
-D, --dry-run print changes to console, rather than back to file (default: false)
--table-case <tableCase> case convention for table names (SEE BOTTOM) (default: "pascal")
--field-case <fieldCase> case convention for field names (default: "camel")
--enum-case <enumCase> case convention for enum names. In case of not declared, uses value of “--table-case”. (default: "pascal")
--map-table-case <mapTableCase> case convention for @@map() annotations (SEE BOTTOM)
--map-field-case <mapFieldCase> case convention for @map() annotations
--map-enum-case <mapEnumCase> case convention for @map() annotations of enums. In case of not declared, uses value of “--map-table-case”.
-p, --pluralize optionally pluralize array type fields (default: false)
--uses-next-auth guarantee next-auth models (Account, User, Session, etc) uphold their data-contracts
-V, --version hint: you have v2.1.0
-h, --help display help for command
-------------------------
Supported case conventions: ["pascal", "camel", "snake"].
Additionally, append ',plural' after any case-convention selection to mark case convention as pluralized.
> For instance:
--map-table-case=snake,plural
will append `@@map("users")` to `model User`.
Append ',singular' after any case-convention selection to mark case convention as singularized.
> For instance,
--map-table-case=snake,singular
will append `@@map("user")` to `model Users`
Deviant case conventions altogether:
> If one or more of your models or fields needs to opt out of case conventions, either to be a fixed name or to disable it,
use the `.prisma-case-format` file and read the documentation on "deviant name mappings".
Example
// schema.prisma before
...
model house_rating {
id Int @id @default(autoincrement())
house_id String
house house @relation(fields: [house_id], references: [id])
...
}
...
model house {
id String @id @default(uuid())
house_rating house_rating[]
...
}
...
❯ prisma-case-format
✨ Done.
// schema.prisma after
...
model HouseRating {
id Int @id @default(autoincrement())
houseId String @map("house_id")
house House @relation(fields: [houseId], references: [id])
...
@@map("house_rating")
}
...
model House {
id String @id @default(uuid())
houseRating HouseRating[]
...
@@map("house")
}
...
Drift Protection
prisma-case-format
lets you manage three case conventions: table
, field
, and enum
.
table
model Example { // <- controlled by `--table-case`
id String @id
value1 String @map("value_1")
@@map("example") // <- controlled by `--map-table-case`
}
Table conventions are controlled by the --table-case
& --map-table-case
flags. --table-case
specifies the case convention for the models in the generated prisma client library. --map-table-case
will manage the database name case convention. table
args manage models & views.
field
model Example {
id String @id
// r-- controlled by `--field-case`
// | r-- controlled by `--map-field-case`
// v v
value1 String @map("value_1")
}
Field conventions are controlled by the --field-case
& --map-field-case
flags. --field-case
specifies the case convention for the fields in models within the generated prisma client library. --map-field-case
will manage the case convention for the field in the database. field
args do not apply to enums.
enum
enum Example { // <- controlled by --enum-case
Value1
Value2
@@map("example") // <- controlled by --map-enum-case
}
Enum conventions are controlled by the --enum-case
& --map-enum-case
flags. --enum-case
specifies the case convention for the enums in the generated prisma client library. --map-enum-case
will manage the case convention for the enum within the database. enum
args do not apply to enum values, just the model & database names.
Config file
prisma-case-format
supports a config file, which primarily exists as a means to override case conventions per model or per field. This can be especially useful if you are coming from an existing database that doesn't have perfect naming convention consistency. For example, some of your model fields are snake_case
, others are camelCase
.
By default, this file is located at .prisma-case-format
. The file is expected to be yaml
internally. The following section details the config file format.
Config file format
Property: default?: string
:
An alternative to specifying the commandline arguments. The format is a simple ;
-delimited list, white space allowed.
Example:
default: 'table=pascal; mapTable=snake; field=pascal; mapField=snake; enum=pascal; mapEnum=pascal'
uses_next_auth: false
Property: override?: Dictionary<string, { default?: string, field?: Field }>
Type: Field=Dictionary<string, string>
Controls overrides on a per-model & per-field basis. Works for models
, views
and enums
, in the same scope as the table
/field
/enum
argument groups when running in commandline mode. Each key in override
& subkey in field
is allowed to be a regex, in which case it will attempt to match based on the specified pattern. This can be useful if you have several fields with prefixes or suffixes.
Example
default: 'table=pascal; mapTable=snake; field=pascal; mapField=snake; enum=pascal; mapEnum=pascal'
override:
MyTable:
default: 'table=snake;mapTable=camel;field=snake;mapField=snake;enum=snake;mapEnum=snake'
field:
fooFieldOnMyTable: 'field=pascal;mapField=pascal'
'my_prefix.*': 'mapField=pascal;'
Results in:
model my_table {
id String @id
FooFieldOnMyTable Integer
my_prefix_prop_a Json @map("MyPrefixPropA")
@@map("myTable")
}
Disabling case convention management
The .prisma-case-format
file supports specifying that a particular model or field has its case convention management "disabled". This is achieved by setting the key under override
or subkey under field
to 'disable'
.
Example:
default: ...
override:
mYTaBlE: 'disable'
...
YourTable:
default: '...'
field:
unmanaged_property: 'disable'
Results in:
model mYTaBlE {
nowican String @id
cAnFAlL_iNtO_UtTeR__DiSrePaiR String @map("lol")
iN_T0T4L_p34C3 Integer @map("great")
@map("myspace")
}
The other tables surrounding mYTaBlE
will remain managed.
Deviant name mappings
In some cases, some users will want to let certain model or field names deviate out of using case-conventions. Primarily, this is useful if you're
inheriting ill-named tables in an at least partialy database-first workflow.
Overriding case-convention use on a specific target name can be achieved in a .prisma-case-format
file by using the syntax map(Table|Field|Enum)=!<name>
,
where <name>
is your precise case-sensitive name that you want to map.
Example
default: ...
override:
MyAmazingModel:
default: 'mapTable=!Amaze_o'
field:
fuzz: 'mapField=!fizz_buzz'
MySuperDuperEnum:
default: 'mapTable=!myenum'
Results in:
model MyAmazingModel {
id Int @id
fuzz String @map("fizz_buzz")
@@map("Amaze_o")
}
enum MySuperDuperEnum {
Opt1
Opt2
@@map("myenum")
}
Property: uses_next_auth?: boolean
If =true
, then the models added by NextAuth.js
will not have their case conventions rewritten by user's selected case conventions, preserving the expected contract. If you are not using NextAuth.js
, it is suggested to keep this unspecified or false
.
This property is equivalent to the following configuration:
uses_next_auth: false
default: ...
override:
Account:
default: 'table=pascal; mapTable=pascal;'
field:
id: 'field=camel; mapField=camel'
userId: 'field=camel; mapField=camel'
type: 'field=camel; mapField=camel'
provider: 'field=camel; mapField=camel'
providerAccountId: 'field=camel; mapField=camel'
refresh_token: 'field=snake; mapField=snake'
access_token: 'field=snake; mapField=snake'
expires_at: 'field=snake; mapField=snake'
token_type: 'field=snake; mapField=snake'
scope: 'field=snake; mapField=snake'
id_token: 'field=snake; mapField=snake'
session_state: 'field=snake; mapField=snake'
user: 'field=snake; mapField=snake'
Session:
default: 'table=pascal; mapTable=pascal; field=camel; mapField=camel'
User:
default: 'table=pascal; mapTable=pascal; field=camel; mapField=camel'
VerificationToken:
default: 'table=pascal; mapTable=pascal; field=camel; mapField=camel'
Note that if uses_next_auth: true
and your overrides
section contains conflicting specifications for any of the above model names (Account
, Session
, User
, or VerificationToken
), uses_next_auth
will blow away your configuration rules for those models and use the above rules.
Pluralization
Supply the -p
or --pluralize
argument to get array pluralizations.
❯ prisma-case-format -p
✨ Done.
// schema.prisma after pluralization
...
model House {
...
houseRatings HouseRating[]
ownerContacts String[] @map("owner_contact")
...
}
...