Comments (23)
I'll start with the inline // prisma-case-format:disable ... // prisma-case-format:disable-end
feature, but I think an .prisma-case-format
file could be a reasonable introduction:
# alternative to specifying cmd line args
defaults:
table: pascal,plural
field: camel
enum: pascal
mapTable: snake
mapField: snake
mapEnum: snake
uses_next_auth: true # optional: apply default conventions for "next-auth" models
overrides:
ModelX:
defaults: # specify overridden defaults for this scope
table: snake,singular
mapTable: pascal
fields: # apply element-wise overrides
# alternate short-hand; note this works in model-wise defaults & global defaults
userId: field=pascal;mapField=pascal,plural
other_model: disable # shut it off entirely
from prisma-case-format.
Btw. tried and it works! Thanks so much!
from prisma-case-format.
Great suggestion, I think somebody else had previously requested this feature but didn't do a great job of explaining it
from prisma-case-format.
I had to look it up because I wasn't sure but it doesn't seem to be an official project made by Vercel: https://opencollective.com/nextauth. The package name sounds official but it is made by the community at large.
I'm myself not too familiar with Next.js and its community, I couldn't tell you if this schema weirdness is something people push back against or if it seen as normal. I literally learned about next-auth 2 days ago when doing changes to tables used by a Next.js application and broke signin/signup after renaming some specific columns used by next-auth's Github provider (they aren't documented anywhere on next-auth website or GitHub repo, I only found out about it thanks to Prisma having really good error messages). So, not really a fan :)
That's why I've been looking for a linter/auto-formatter.
because we're seizing control of the inline comment, which might clash with other functionality put forth by prisma or other 3rd parties
Yes I agree, that's a fair point.
from prisma-case-format.
I found this comment:
Thanks, but this looks correct to me. NextAuth.js provided properties are camelCase while the ones based on the OAuth standard are following snake_case
from prisma-case-format.
😄 it's override
not overrides
. Should it be either? To make matters worse, I told you it was overrides
, so sorry about that.
Anyway, renaming it to override
should fix the problem, but even simpler is just specifying --uses-next-auth
or setting uses_next_auth: true
in the .prisma-case-format
file.
from prisma-case-format.
Hey @igeligel, thanks for the suggestion. What is next-auth
, is that part of the nextjs
ecosystem? If you don't mind me asking, what is the existing problem that you're facing, which these annotations would solve?
from prisma-case-format.
Hi @iiian,
you're correct next-auth is part of the next.js ecosystem. It is a package that makes it fairly simple to setup authentication for a website. It supports various providers, and Prisma is one of them. You can check the provider documentation here, the expected schema has strict requirements for casing, some fields of the generated Prisma client are expected to be snake_case (such as token_type
, expires_at
), while other need to be camelCase (providerAccountId
, userId
).
We faced the same issue as @igeligel, I've myself been bitten by the casing while cleaning up our DB schema. I now would like to rely on a tool such as prisma-case-format
as a linter to ensure we use consistent names. But that would require to either be able to disable prisma-case-format
for next-auth's models, or a way to specify (via comments?) the case to use for a specific column.
from prisma-case-format.
Got it, thanks for motivating the need--the problem makes sense to me now. Just commenting, seems like the disable feature is useful, and simultaneously the same could be achieved if just overrides for syntax expectations were allowed:
// prisma-case-format:override
// --field-case=camel
// --map-field-case=snake
model GotchaNextAuthModel {
// now fields are forced to format as camel, with snake @map anno's
tokenType String @map('token_type')
expiresAt String @map('expires_at')
}
// prisma-case-format:end-override
That way, prisma-case-format
can enforce the case-convention deviation.
from prisma-case-format.
I like comments as the trigger, but we'll probably end up wanting to do a commandline arg as well, I'll have to think on that.
Ultimately, I think I hope to support this feature by the end of the year--is that soon enough?
from prisma-case-format.
The override syntax is a neat idea, that would make it nicer to handle models that require a specific casing.
Looking at next-auth models, I would say that Account
is the most problematic one, because it expects a mix of casing, that makes it a good test case to try out different strategies.
An idea would be to support override comments on the same line, in addition to an override block like the one you suggested.
// 👇 set a default case for the model, for both the Prisma client and columns @map()
//
// prisma-case-format:override(field-case=camel,map-field-case=snake)
model Account {
id String @id @default(cuid())
userId String
type String
provider String
providerAccountId String
// 👇 override some columns, only --field-case
refresh_token String? @db.Text // prisma-case-format:override(field-case=snake)
access_token String? @db.Text // prisma-case-format:override(field-case=snake)
expires_at Int? // prisma-case-format:override(field-case=snake)
token_type String? // prisma-case-format:override(field-case=snake)
scope String?
id_token String? @db.Text // prisma-case-format:override(field-case=snake)
session_state String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([provider, providerAccountId])
}
// prisma-case-format:end-override
Here the logic would be straight forward:
- if a line starts with
prisma-case-format:override
, start an override block - if an inlined comment starts with
prisma-case-format:override
, override only for that specific line - if a line starts with
prisma-case-format:end-override
, stop the override block
I don't think something more complicated such as nested override blocks would make too much sense here, that wouldn't be too readable.
What do you think? I slightly changed your override syntax to make it simpler to use inlined, but that's just a suggestion and my personal preference 😄.
Ultimately, I think I hope to support this feature by the end of the year--is that soon enough?
Oh for sure, yes!
from prisma-case-format.
Yep sounds good to me -- I guess we'll just have to say "it has to be the first part of a comment", because we're seizing control of the inline comment, which might clash with other functionality put forth by prisma
or other 3rd parties (why I'm generally opposed to adding control flags directly within the file, but in this case it seemed harmless as far as we were going with disable
stuff.
I'm almost wondering if there's not value in just creating a --has-next-auth
flag, that applies a pre-defined set of case-conventions.
Are there any comments pushing back against @vercel
doing this to y'all? Seems arbitrary and poorly published
from prisma-case-format.
Okay, so I ended up not going for the //prisma-case-format:disable
comments at all, since its manageable from the .prisma-case-format
file.
The next PR will contain updates for the README.md
, but here's an example of the syntax:
# file: .prisma-case-format
uses_next_auth: false
default: ...
override: #edited -- not overrides!
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 the above example is strictly equivalent to
# file: .prisma-case-format
uses_next_auth: true
or to specifying the commandline argument --uses-next-auth
.
from prisma-case-format.
[email protected]
is available for download, can you give it a spin and let me know if it looks okay?
from prisma-case-format.
Hey @iiian,
This looks great! Will try out today! I might also add some documentation around it if not existing already. Thanks so much for doing these changes so quickly!
from prisma-case-format.
That was fast! Thanks so much, I will try it out right away :)
from prisma-case-format.
Ok, I tried the beta version.
Here is the diff I get after running prisma-case-format -f services/shared/prisma/schema.prisma -c services/shared/prisma/.prisma-case-format
:
--- a/services/shared/prisma/schema.prisma
+++ b/services/shared/prisma/schema.prisma
@@ -12,24 +12,24 @@ generator client {
/// Table required by Next-Auth
model Account {
/// Columns required by Next-Auth
- id String @id @default(cuid())
- userId String @map("user_id")
- user User @relation(fields: [userId], references: [id], onDelete: Cascade)
- type String
- provider String
- providerAccountId String @map("provider_account_id")
- refresh_token_expires_in Int?
- refresh_token String? @db.Text
- access_token String? @db.Text
- expires_at Int?
- token_type String?
- scope String?
- id_token String? @db.Text
- session_state String?
+ id String @id @default(cuid())
+ userId String @map("user_id")
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
+ type String
+ provider String
+ providerAccountId String @map("provider_account_id")
+ refreshTokenExpiresIn Int? @map("refresh_token_expires_in")
+ refreshToken String? @map("refresh_token") @db.Text
+ accessToken String? @map("access_token") @db.Text
+ expiresAt Int? @map("expires_at")
+ tokenType String? @map("token_type")
+ scope String?
+ idToken String? @map("id_token") @db.Text
+ sessionState String? @map("session_state")
My config file:
# file: .prisma-case-format
default: 'table=pascal; mapTable=snake,plural; field=camel; mapField=snake;'
overrides:
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_expires_in: 'field=snake; mapField=snake'
refresh_token: 'field=snake; mapField=snake'
access_token: 'field=snake; mapField=snake'
expires: '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'
Looking at fields such as session_state
, id_token
, token_type
, the snake case overrides don't seem to be applied.
I also noticed an issue for fields mapping to a DB column with a different name (not just a different case):
@@ -73,121 +73,121 @@ model User {
/// Table required by Next-Auth
model VerificationToken {
/// Columns required by Next-Auth
identifier String
token String @unique
- expires DateTime @map("expires_at") @db.Timestamptz(3)
+ expires DateTime @db.Timestamptz(3)
@@unique([identifier, token])
@@map("verification_tokens")
}
Here the DB column is expires_at
, and the field next-auth expects is expires
, but prisma-case-format
removes the @map
.
from prisma-case-format.
Did you try it with --uses-next-auth
as well? I swear I tested that earlier and it worked. In any case, I'll check if this was a regression, thanks for feedback
from prisma-case-format.
Okay, bizarre. It seems to be working when you use --uses-next-auth
, but not the equivalent config I provided above.
from prisma-case-format.
Thanks @iiian for the quick implementation 🙏. And updates to the readme are clear and easy to follow, that's appreciated!
from prisma-case-format.
Some bug report:
npm run prisma-case-format
> [email protected] prisma-case-format
se=snake
E:\programming\get-ready-app\apps\web\node_modules\prisma-case-format\bin\convention-store.js:270
return this.children[(0, change_case_1.snakeCase)(next)]._recurse(k, rest);
^
TypeError: Cannot read properties of undefined (reading '_recurse')
at ConventionStore._recurse (E:\programming\get-ready-app\apps\web\node_modules\prisma-case-format\bin\convention-store.js:270:74)
at ConventionStore._recurse (E:\programming\get-ready-app\apps\web\node_modules\prisma-case-format\bin\convention-store.js:249:40)
at ConventionStore.isDisabled (E:\programming\get-ready-app\apps\web\node_modules\prisma-case-format\bin\convention-store.js:213:27)
at ConventionTransformer.reshapeModelFields (E:\programming\get-ready-app\apps\web\node_modules\prisma-case-format\bin\convention-transformer.js:209:31)
at ConventionTransformer.migrateCaseConventions (E:\programming\get-ready-app\apps\web\node_modules\prisma-case-format\bin\convention-transformer.js:46:67)
at E:\programming\get-ready-app\apps\web\node_modules\prisma-case-format\bin\cli.js:126:87
at Generator.next (<anonymous>)
at E:\programming\get-ready-app\apps\web\node_modules\prisma-case-format\bin\cli.js:9:71
at new Promise (<anonymous>)
at __awaiter (E:\programming\get-ready-app\apps\web\node_modules\prisma-case-format\bin\cli.js:5:12)
Node.js v20.8.1
npm ERR! Lifecycle script `prisma-case-format` failed with error:
npm ERR! Error: command failed
npm ERR! in workspace: [email protected]
npm ERR! at location: E:\programming\get-ready-app\apps\web
config:
# file: .prisma-case-format
uses_next_auth: true
schema:
model Account {
id String @id @default(cuid())
userId String @map("user_id")
providerType String @map("provider_type")
providerId String @map("provider_id")
providerAccountId String
refreshToken String? @map("refresh_token")
accessToken String? @map("access_token")
accessTokenExpires DateTime? @map("access_token_expires")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
user User @relation(fields: [userId], references: [id])
@@unique([providerId, providerAccountId])
@@map("account")
}
If the @map
parameter already existed on the schema definition, the error will be thrown. I think most of the people will not get into this state. Just wanted to highlight this!
from prisma-case-format.
Thanks @igeligel ! I was actually trying to replicate this.
from prisma-case-format.
Where is providerType String @map("provider_type")
coming from? Is that a real next-auth
thing or are we just trying to see what we can break (which would be appreciated, btw)
from prisma-case-format.
Related Issues (20)
- `Unsupported` fields are parsed incorrectly HOT 5
- Enums are not mapped HOT 5
- Add a LICENSE file HOT 4
- Ignore Command & Excluding Enums HOT 4
- Any way to keep enums singular when table names are plural? HOT 3
- Broken output for pascal case HOT 4
- New version of package have old content HOT 1
- No @@map created for enums HOT 5
- Q. How to use this tool ? HOT 8
- Retain @map annotations for fields with distinct DB column names HOT 6
- Add option to ignore pluralize option per field HOT 8
- [Feature request] Obtain default schema location from package.json
- [Feature request] Enable configuration via package.json HOT 1
- Allow programmatic usage of library (example: vscode formatter extension) HOT 2
- Run Prisma's `formatSchema` before AND after the case formatting to automatically add missing relations HOT 2
- MongoDB ID field issue HOT 4
- Invalid `--uses-next-auth` cli option HOT 1
- Config file does not load before `tryGetFileContents` HOT 2
- Camel case not working as expected for fields with numbers
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from prisma-case-format.