From 7f0f8bfc0e8e583c402fc38350f512f1327cdd78 Mon Sep 17 00:00:00 2001 From: Max Heinritz Date: Wed, 3 Apr 2024 12:17:24 -0500 Subject: [PATCH 1/6] init --- CHANGELOG.md | 2 ++ .../field-name-mapping-snake-case.test.ts | 28 ++++++++++++++----- src/rules/field-name-mapping-snake-case.ts | 28 +++++++++++-------- 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad36b047..88246905 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +- [#330](https://github.com/loop-payments/prisma-lint/issues/330) Remove `requirePrefix` option and add `requireUnderscorePrefixForIds` to `field-name-mapping-snake-case` to actually support MongoDB naming conventions. + ## 0.2.0 (2024-03-29) - [#354](https://github.com/loop-payments/prisma-lint/issues/354) Add `allowlist` to `model-name-grammatical-number`. diff --git a/src/rules/field-name-mapping-snake-case.test.ts b/src/rules/field-name-mapping-snake-case.test.ts index cb733c2d..67ff86f3 100644 --- a/src/rules/field-name-mapping-snake-case.test.ts +++ b/src/rules/field-name-mapping-snake-case.test.ts @@ -15,17 +15,18 @@ describe('field-name-mapping-snake-case', () => { ruleDefinitions: [fieldNameMappingSnakeCase], }); - describe('with requirePrefix', () => { - const run = getRunner({ requirePrefix: '_' }); + describe('with requireUnderscorePrefixForId', () => { + const run = getRunner({ requireUnderscorePrefixForIds: true }); describe('valid with mapping', () => { it('returns no violations', async () => { const violations = await run(` model User { - fooBar String @map(name: "_foo_bar") + id String @id @map(name: "_id") + otherField String @map(name: "other_field") } `); - expect(violations.length).toEqual(0); + expect(violations.map((v) => v.message)).toEqual([]); }); }); @@ -33,10 +34,10 @@ describe('field-name-mapping-snake-case', () => { it('returns violation', async () => { const violations = await run(` model User { - fooBar String + idFoo String @id } `); - expect(violations.length).toEqual(1); + expect(violations).toHaveLength(1); }); }); @@ -44,7 +45,20 @@ describe('field-name-mapping-snake-case', () => { it('returns violation', async () => { const violations = await run(` model user { - fooBar String @map(name: "foo_bar") + id String @id @map(name: "id") + } + `); + expect(violations.map((v) => v.message)).toEqual([ + 'Field name must be mapped to "_id".', + ]); + }); + }); + + describe('with wrong mapping', () => { + it('returns violation', async () => { + const violations = await run(` + model user { + idTwo String @id @map(name: "_id_one") } `); expect(violations.length).toEqual(1); diff --git a/src/rules/field-name-mapping-snake-case.ts b/src/rules/field-name-mapping-snake-case.ts index 247d0f7c..0900fc7d 100644 --- a/src/rules/field-name-mapping-snake-case.ts +++ b/src/rules/field-name-mapping-snake-case.ts @@ -11,7 +11,7 @@ const RULE_NAME = 'field-name-mapping-snake-case'; const Config = z .object({ compoundWords: z.array(z.string()).optional(), - requirePrefix: z.string().optional(), + requireUnderscorePrefixForIds: z.boolean().optional(), }) .strict() .optional(); @@ -51,15 +51,17 @@ const Config = z * graphQLId String @map(name: "graph_q_l_id") * } * - * @example { requirePrefix: ["_"] } + * @example { requireUnderscorePrefixForId: ["_"] } * // good * model PersistedQuery { - * fooId String @map(name: "_foo_id") + * id String @id @map(name: "_id") + * otherField String @map(name: "other_field") * } * * // bad * model PersistedQuery { - * fooId String @map(name: "foo_id") + * id String @id @map(name: "id") + * otherField String @map(name: "other_field") * } * */ @@ -67,7 +69,7 @@ export default { ruleName: RULE_NAME, configSchema: Config, create: (config, context) => { - const { compoundWords, requirePrefix } = config ?? {}; + const { compoundWords, requireUnderscorePrefixForIds } = config ?? {}; return { Field: (model, field) => { if (isAssociation(field.fieldType)) { @@ -78,12 +80,12 @@ export default { const report = (message: string) => context.report({ model, field, message }); - const { name, attributes } = field; - const expectedSnakeCase = toSnakeCase(name, { - compoundWords, - requirePrefix, - }); - const isMappingRequired = !isAllLowerCase(name); + const { attributes, name: fieldName } = field; + const isIdWithRequiredPrefix = + requireUnderscorePrefixForIds && + attributes?.find((a) => a.name === 'id'); + const isMappingRequired = + !isAllLowerCase(fieldName) || isIdWithRequiredPrefix; if (!attributes) { if (isMappingRequired) { @@ -105,6 +107,10 @@ export default { } return; } + let expectedSnakeCase = toSnakeCase(fieldName, { compoundWords }); + if (isIdWithRequiredPrefix) { + expectedSnakeCase = `_${expectedSnakeCase}`; + } if (mappedName !== expectedSnakeCase) { report(`Field name must be mapped to "${expectedSnakeCase}".`); } From 2a1ab32cae187d067c8ee03dc44d128116bc2fe6 Mon Sep 17 00:00:00 2001 From: Max Heinritz Date: Wed, 3 Apr 2024 12:18:07 -0500 Subject: [PATCH 2/6] Bump version to 0.3.0 --- CHANGELOG.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 88246905..511127e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 0.3.0 (2024-04-03) + - [#330](https://github.com/loop-payments/prisma-lint/issues/330) Remove `requirePrefix` option and add `requireUnderscorePrefixForIds` to `field-name-mapping-snake-case` to actually support MongoDB naming conventions. ## 0.2.0 (2024-03-29) diff --git a/package.json b/package.json index 3e168c3b..75ff0fbd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prisma-lint", - "version": "0.2.0", + "version": "0.3.0", "description": "A linter for Prisma schema files.", "repository": { "type": "git", From 722272bd58b55d04ec16fd8eb2d7c6c571b95636 Mon Sep 17 00:00:00 2001 From: Max Heinritz Date: Wed, 3 Apr 2024 12:18:33 -0500 Subject: [PATCH 3/6] test nit --- src/rules/field-name-mapping-snake-case.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rules/field-name-mapping-snake-case.test.ts b/src/rules/field-name-mapping-snake-case.test.ts index 67ff86f3..48ccb19a 100644 --- a/src/rules/field-name-mapping-snake-case.test.ts +++ b/src/rules/field-name-mapping-snake-case.test.ts @@ -15,7 +15,7 @@ describe('field-name-mapping-snake-case', () => { ruleDefinitions: [fieldNameMappingSnakeCase], }); - describe('with requireUnderscorePrefixForId', () => { + describe('with requireUnderscorePrefixForIds', () => { const run = getRunner({ requireUnderscorePrefixForIds: true }); describe('valid with mapping', () => { From f07f486a2898efc5b93715c02a663d50f4ecbd1f Mon Sep 17 00:00:00 2001 From: Max Heinritz Date: Wed, 3 Apr 2024 12:20:35 -0500 Subject: [PATCH 4/6] dcs --- RULES.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/RULES.md b/RULES.md index 7f724e13..96aa9773 100644 --- a/RULES.md +++ b/RULES.md @@ -25,7 +25,7 @@ Checks that the mapped name of a field is the expected snake case. ```ts z.object({ compoundWords: z.array(z.string()).optional(), - requirePrefix: z.string().optional(), + requireUnderscorePrefixForIds: z.boolean().optional(), }) .strict() .optional(); @@ -70,17 +70,19 @@ model PersistedQuery { } ``` -#### With `{ requirePrefix: ["_"] }` +#### With `{ requireUnderscorePrefixForId: ["_"] }` ```prisma // good model PersistedQuery { - fooId String @map(name: "_foo_id") + id String @id @map(name: "_id") + otherField String @map(name: "other_field") } // bad model PersistedQuery { - fooId String @map(name: "foo_id") + id String @id @map(name: "id") + otherField String @map(name: "other_field") } ``` From 593680bcb3d47f8d8b63b7ffb36e7a07933ad52e Mon Sep 17 00:00:00 2001 From: Max Heinritz Date: Wed, 3 Apr 2024 13:06:24 -0500 Subject: [PATCH 5/6] fix docs --- RULES.md | 2 +- src/rules/field-name-mapping-snake-case.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/RULES.md b/RULES.md index 96aa9773..ce720b51 100644 --- a/RULES.md +++ b/RULES.md @@ -70,7 +70,7 @@ model PersistedQuery { } ``` -#### With `{ requireUnderscorePrefixForId: ["_"] }` +#### With `{ requireUnderscorePrefixForId: true }` ```prisma // good diff --git a/src/rules/field-name-mapping-snake-case.ts b/src/rules/field-name-mapping-snake-case.ts index 0900fc7d..b626e2f6 100644 --- a/src/rules/field-name-mapping-snake-case.ts +++ b/src/rules/field-name-mapping-snake-case.ts @@ -51,7 +51,7 @@ const Config = z * graphQLId String @map(name: "graph_q_l_id") * } * - * @example { requireUnderscorePrefixForId: ["_"] } + * @example { requireUnderscorePrefixForId: true } * // good * model PersistedQuery { * id String @id @map(name: "_id") From 489d6c6197d700590da6e00633f04d2939822b00 Mon Sep 17 00:00:00 2001 From: Max Heinritz Date: Wed, 3 Apr 2024 13:06:58 -0500 Subject: [PATCH 6/6] fix docs --- RULES.md | 2 +- src/rules/field-name-mapping-snake-case.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/RULES.md b/RULES.md index ce720b51..0e396d70 100644 --- a/RULES.md +++ b/RULES.md @@ -70,7 +70,7 @@ model PersistedQuery { } ``` -#### With `{ requireUnderscorePrefixForId: true }` +#### With `{ requireUnderscorePrefixForIds: true }` ```prisma // good diff --git a/src/rules/field-name-mapping-snake-case.ts b/src/rules/field-name-mapping-snake-case.ts index b626e2f6..b935c038 100644 --- a/src/rules/field-name-mapping-snake-case.ts +++ b/src/rules/field-name-mapping-snake-case.ts @@ -51,7 +51,7 @@ const Config = z * graphQLId String @map(name: "graph_q_l_id") * } * - * @example { requireUnderscorePrefixForId: true } + * @example { requireUnderscorePrefixForIds: true } * // good * model PersistedQuery { * id String @id @map(name: "_id")