├── .eslintignore ├── .prettierignore ├── .yarnrc.yml ├── src ├── utils.ts ├── index.ts ├── PrismaExcludeError.ts ├── withExclude.ts ├── prismaExclude.ts └── types.ts ├── jest.config.js ├── .prettierrc.js ├── examples ├── simple │ ├── package.json │ ├── .env.example │ ├── tsconfig.json │ ├── src │ │ ├── withExclude.ts │ │ └── prismaExclude.ts │ ├── prisma │ │ └── schema.prisma │ ├── .gitignore │ └── yarn.lock └── README.md ├── .release-it.yml ├── tests ├── utils.test.ts └── lib.test.ts ├── prisma └── schema.prisma ├── tsconfig.json ├── .github ├── renovate.json └── workflows │ ├── coverage.yml │ └── ci.yml ├── package.json ├── .gitignore ├── README.md └── .eslintrc.json /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | tests 3 | examples -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist 3 | examples -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | defaultSemverRangePrefix: "" # Pin dependencies by default 2 | 3 | yarnPath: ".yarn/releases/yarn-berry.cjs" 4 | nodeLinker: node-modules 5 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | export const capitalize = (string: T): Capitalize => { 2 | return (string[0].toUpperCase() + string.slice(1)) as any; 3 | }; 4 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ 2 | module.exports = { 3 | preset: "ts-jest", 4 | testEnvironment: "node", 5 | }; 6 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | trailingComma: "es5", 3 | tabWidth: 2, 4 | semi: true, 5 | singleQuote: false, 6 | arrowParens: "always", 7 | useTabs: false, 8 | endOfLine: "lf", 9 | }; 10 | -------------------------------------------------------------------------------- /examples/simple/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "simple", 3 | "packageManager": "yarn@3.2.0", 4 | "devDependencies": { 5 | "@prisma/client": "3.10.0", 6 | "prisma": "3.10.0", 7 | "prisma-exclude": "1.0.1" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { prismaExclude } from "./prismaExclude"; 2 | import { withExclude } from "./withExclude"; 3 | import { PrismaExcludeError } from "./PrismaExcludeError"; 4 | 5 | export { prismaExclude, withExclude, PrismaExcludeError }; 6 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Examples 2 | 3 | Running the examples is quite simple. 4 | 5 | 1. Clone the repository 6 | 2. `cd` into the desired example directory 7 | 3. Install dependencies with `yarn install` 8 | 4. Generate the Prisma Client with `yarn prisma generate` -------------------------------------------------------------------------------- /.release-it.yml: -------------------------------------------------------------------------------- 1 | git: 2 | commitMessage: "release v${version}" 3 | github: 4 | release: true 5 | hooks: 6 | before:init: 7 | - yarn lint 8 | - yarn format 9 | - yarn typecheck 10 | - yarn test 11 | - yarn clean 12 | - yarn build 13 | -------------------------------------------------------------------------------- /tests/utils.test.ts: -------------------------------------------------------------------------------- 1 | import { capitalize } from "../src/utils"; 2 | 3 | describe("test utilities", () => { 4 | describe("capitalize", () => { 5 | it("should capitalize a string", () => { 6 | expect(capitalize("foo")).toEqual("Foo"); 7 | }); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /src/PrismaExcludeError.ts: -------------------------------------------------------------------------------- 1 | import { ExcludeError } from "./types"; 2 | 3 | export class PrismaExcludeError extends Error { 4 | constructor(message: ExcludeError) { 5 | super(message); 6 | 7 | Object.setPrototypeOf(this, PrismaExcludeError.prototype); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/simple/.env.example: -------------------------------------------------------------------------------- 1 | # Environment variables declared in this file are automatically made available to Prisma. 2 | # See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema 3 | 4 | # Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB (Preview) and CockroachDB (Preview). 5 | # See the documentation for all the connection string options: https://pris.ly/d/connection-strings 6 | 7 | DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public" -------------------------------------------------------------------------------- /prisma/schema.prisma: -------------------------------------------------------------------------------- 1 | // This is your Prisma schema file, 2 | // learn more about it in the docs: https://pris.ly/d/prisma-schema 3 | 4 | generator client { 5 | provider = "prisma-client-js" 6 | } 7 | 8 | datasource db { 9 | provider = "postgresql" 10 | url = env("DATABASE_URL") 11 | } 12 | 13 | model User { 14 | id String @id @default(uuid()) 15 | firstName String 16 | lastName String? 17 | email String @unique 18 | password String 19 | lastLogin DateTime 20 | createdAt DateTime @default(now()) 21 | updatedAt DateTime @updatedAt 22 | } 23 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "declaration": true, 6 | "sourceMap": false, 7 | "outDir": "dist", 8 | "rootDir": "src", 9 | "noEmit": false, 10 | "composite": true, 11 | "lib": ["dom", "ES6"], 12 | "strict": true, 13 | "skipLibCheck": true, 14 | "esModuleInterop": true, 15 | "forceConsistentCasingInFileNames": true, 16 | "moduleResolution": "node", 17 | "isolatedModules": true, 18 | "incremental": true 19 | }, 20 | "include": ["src"], 21 | "exclude": ["node_modules", "dist"] 22 | } 23 | -------------------------------------------------------------------------------- /examples/simple/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "declaration": true, 6 | "sourceMap": false, 7 | "outDir": "dist", 8 | "rootDir": "src", 9 | "noEmit": false, 10 | "composite": true, 11 | "lib": ["dom", "ES6"], 12 | "strict": true, 13 | "skipLibCheck": true, 14 | "esModuleInterop": true, 15 | "forceConsistentCasingInFileNames": true, 16 | "moduleResolution": "node", 17 | "isolatedModules": true, 18 | "incremental": true 19 | }, 20 | "include": ["src"], 21 | "exclude": ["node_modules", "dist"] 22 | } 23 | -------------------------------------------------------------------------------- /examples/simple/src/withExclude.ts: -------------------------------------------------------------------------------- 1 | import { Prisma, PrismaClient } from "@prisma/client"; 2 | import { withExclude } from "prisma-exclude"; 3 | 4 | // Initialize the Prisma Client and wrap it with withExclude 5 | 6 | const prisma = withExclude(new PrismaClient()); 7 | 8 | // Use it in you queries 9 | 10 | (async () => { 11 | const userWithAddress = await prisma.user.findUnique({ 12 | where: { 13 | id: 1, 14 | }, 15 | select: { 16 | ...prisma.$exclude("user", ["password"]), 17 | addresses: { 18 | select: prisma.$exclude("address", ["zipCode"]), 19 | }, 20 | }, 21 | }); 22 | 23 | // With Prisma Validator 24 | 25 | const userSafeSelect = Prisma.validator()( 26 | prisma.$exclude("user", ["password", "createdAt"]) 27 | ); 28 | 29 | const userSafe = await prisma.user.findUnique({ 30 | where: { 31 | id: 1, 32 | }, 33 | select: userSafeSelect, 34 | }); 35 | })(); 36 | -------------------------------------------------------------------------------- /examples/simple/src/prismaExclude.ts: -------------------------------------------------------------------------------- 1 | import { Prisma, PrismaClient } from "@prisma/client"; 2 | import { prismaExclude } from "prisma-exclude"; 3 | 4 | // Initialize the Prisma Client 5 | const prisma = new PrismaClient(); 6 | 7 | // Initialize the exclude function 8 | const exclude = prismaExclude(prisma); 9 | 10 | // Use it in you queries 11 | 12 | (async () => { 13 | const userWithAddress = await prisma.user.findUnique({ 14 | where: { 15 | id: 1, 16 | }, 17 | select: { 18 | ...exclude("user", ["password"]), 19 | addresses: { 20 | select: exclude("address", ["zipCode"]), 21 | }, 22 | }, 23 | }); 24 | 25 | // With Prisma Validator 26 | 27 | const userSafeSelect = Prisma.validator()( 28 | exclude("user", ["password", "createdAt"]) 29 | ); 30 | 31 | const userSafe = await prisma.user.findUnique({ 32 | where: { 33 | id: 1, 34 | }, 35 | select: userSafeSelect, 36 | }); 37 | })(); 38 | -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["config:base", ":disableRateLimiting"], 3 | "schedule": ["on the first day of the week"], 4 | "baseBranches": ["main"], 5 | "rebaseWhen": "conflicted", 6 | "dependencyDashboard": true, 7 | "packageRules": [ 8 | { 9 | "groupName": "devDependencies (non-major)", 10 | "automerge": "true", 11 | "depTypeList": ["devDependencies"], 12 | "updateTypes": ["patch", "minor"], 13 | "automergeStrategy": "squash", 14 | "matchUpdateTypes": ["minor", "patch"], 15 | "matchDepTypes": ["devDependencies"] 16 | }, 17 | { 18 | "groupName": "dependencies (non-major)", 19 | "depTypeList": ["dependencies"], 20 | "updateTypes": ["patch", "minor"] 21 | }, 22 | { 23 | "groupName": "definitelyTyped", 24 | "automerge": "true", 25 | "packagePatterns": ["^@types/"], 26 | "updateTypes": ["patch", "minor"], 27 | "matchUpdateTypes": ["minor", "patch"] 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /src/withExclude.ts: -------------------------------------------------------------------------------- 1 | import { PrismaClient } from "@prisma/client"; 2 | import { PrismaExcludeError } from "./PrismaExcludeError"; 3 | import { prismaExclude } from "./prismaExclude"; 4 | import { ExcludeError, WithExclude } from "./types"; 5 | 6 | /** 7 | * Wraps the PrismaClient by adding an `$exclude` method 8 | * that works the same as the `prismaExclude` function. 9 | * 10 | * ```js 11 | * // Define the instance 12 | * const prisma = withExclude(new PrismaClient()); 13 | * 14 | * // Then use it in your queries 15 | * const users = await prisma.user.findMany({ 16 | * select: prisma.$exclude("user", ["password"]), 17 | * }); 18 | * ``` 19 | */ 20 | export const withExclude: WithExclude = (client) => { 21 | if (!client) { 22 | throw new PrismaExcludeError(ExcludeError.noClient); 23 | } 24 | 25 | if (!(client instanceof PrismaClient)) { 26 | throw new PrismaExcludeError(ExcludeError.badClient); 27 | } 28 | 29 | return Object.assign(client, { $exclude: prismaExclude(client) }); 30 | }; 31 | -------------------------------------------------------------------------------- /examples/simple/prisma/schema.prisma: -------------------------------------------------------------------------------- 1 | // This is your Prisma schema file, 2 | // learn more about it in the docs: https://pris.ly/d/prisma-schema 3 | 4 | generator client { 5 | provider = "prisma-client-js" 6 | } 7 | 8 | datasource db { 9 | provider = "postgresql" 10 | url = env("DATABASE_URL") 11 | } 12 | 13 | model User { 14 | id Int @id @default(autoincrement()) 15 | firstName String 16 | lastName String? 17 | password String 18 | createdAt DateTime @default(now()) 19 | updatedAt DateTime @updatedAt 20 | addresses Address[] 21 | } 22 | 23 | model Address { 24 | id Int @id @default(autoincrement()) 25 | user User @relation(fields: [userId], references: [id]) 26 | userId Int 27 | address1 String 28 | address2 String 29 | city String 30 | zipCode String 31 | country Country @relation(fields: [countryId], references: [id]) 32 | countryId Int 33 | } 34 | 35 | model Country { 36 | id Int @id @default(autoincrement()) 37 | name String 38 | continent Continent @relation(fields: [continentId], references: [id]) 39 | continentId Int 40 | addresses Address[] 41 | } 42 | 43 | model Continent { 44 | id Int @id @default(autoincrement()) 45 | name String 46 | countries Country[] 47 | } 48 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "prisma-exclude", 3 | "version": "1.0.2", 4 | "main": "dist/index.js", 5 | "author": "ajmnz ", 6 | "license": "MIT", 7 | "description": "Exclude fields from your Prisma queries", 8 | "files": [ 9 | "dist" 10 | ], 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/ajmnz/prisma-exclude" 14 | }, 15 | "keywords": [ 16 | "prisma", 17 | "prisma exclude", 18 | "prisma omit" 19 | ], 20 | "scripts": { 21 | "build": "tsc", 22 | "clean": "rimraf -rf dist tsconfig.tsbuildinfo", 23 | "test": "jest", 24 | "test:watch": "jest --watch", 25 | "test:coverage": "jest --coverage", 26 | "publish": "dotenv release-it --", 27 | "lint": "eslint --ext=ts src", 28 | "format": "prettier --write \"./src/**/*.ts\"", 29 | "typecheck": "tsc --noEmit" 30 | }, 31 | "devDependencies": { 32 | "@prisma/client": "3.15.2", 33 | "@types/jest": "27.5.2", 34 | "@types/node": "17.0.45", 35 | "@typescript-eslint/eslint-plugin": "5.62.0", 36 | "@typescript-eslint/parser": "5.62.0", 37 | "dotenv-cli": "5.1.0", 38 | "eslint": "8.57.1", 39 | "eslint-plugin-unused-imports": "2.0.0", 40 | "jest": "27.5.1", 41 | "prettier": "2.8.8", 42 | "prisma": "3.15.2", 43 | "release-it": "14.14.3", 44 | "rimraf": "3.0.2", 45 | "ts-jest": "27.1.5", 46 | "typescript": "4.9.5" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /.github/workflows/coverage.yml: -------------------------------------------------------------------------------- 1 | name: Coverage 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | install: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout commit 13 | uses: actions/checkout@v3 14 | - name: Use Node.js 15 | uses: actions/setup-node@v3 16 | with: 17 | node-version: 16 18 | - name: Cache yarn dependencies 19 | uses: actions/cache@v2 20 | id: cache-dependencies 21 | with: 22 | path: node_modules 23 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 24 | restore-keys: | 25 | ${{ runner.os }}-yarn- 26 | - name: Install dependencies 27 | if: steps.cache-dependencies.outputs.cache-hit != 'true' 28 | run: | 29 | yarn install 30 | test-coverage: 31 | runs-on: ubuntu-latest 32 | needs: install 33 | steps: 34 | - name: Checkout commit 35 | uses: actions/checkout@v3 36 | - name: Use Node.js 37 | uses: actions/setup-node@v3 38 | with: 39 | node-version: 16 40 | - name: Restore yarn dependencies 41 | uses: actions/cache@v2 42 | id: cache-dependencies 43 | with: 44 | path: node_modules 45 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 46 | restore-keys: | 47 | ${{ runner.os }}-yarn- 48 | - name: Run tests 49 | run: | 50 | yarn test --coverage 51 | env: 52 | DATABASE_URL: postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public 53 | - name: Upload coverage to Codecov 54 | uses: codecov/codecov-action@v2 55 | with: 56 | files: ./coverage/clover.xml 57 | fail_ci_if_error: true 58 | -------------------------------------------------------------------------------- /src/prismaExclude.ts: -------------------------------------------------------------------------------- 1 | import { Prisma, PrismaClient } from "@prisma/client"; 2 | import { PrismaExcludeError } from "./PrismaExcludeError"; 3 | import { ExcludeError, GetScalarKey, PrismaExclude } from "./types"; 4 | import { capitalize } from "./utils"; 5 | 6 | /** 7 | * Returns an exclude function based on the given 8 | * Prisma Client. 9 | * 10 | * ```ts 11 | * // Pass your client to `prismaExclude` 12 | * const prisma = new PrismaClient(); 13 | * const exclude = prismaExclude(prisma); 14 | * 15 | * // Then use it in your queries 16 | * const users = await prisma.user.findMany({ 17 | * select: exclude("user", ["password"]) 18 | * }); 19 | * ``` 20 | */ 21 | export const prismaExclude: PrismaExclude = (client) => { 22 | return (model, omit) => { 23 | if (!client) { 24 | throw new PrismaExcludeError(ExcludeError.noClient); 25 | } 26 | 27 | if (!(client instanceof PrismaClient)) { 28 | throw new PrismaExcludeError(ExcludeError.badClient); 29 | } 30 | 31 | if (!model) { 32 | throw new PrismaExcludeError(ExcludeError.noModel); 33 | } 34 | 35 | if (!(model in client)) { 36 | throw new PrismaExcludeError(ExcludeError.modelMismatch); 37 | } 38 | 39 | const modelFields = 40 | Prisma[ 41 | `${capitalize(String(model))}ScalarFieldEnum` as GetScalarKey< 42 | typeof client, 43 | typeof model 44 | > 45 | ]; 46 | 47 | // In case omit is not given 48 | const toExclude = omit || []; 49 | 50 | const result = {} as { [K in keyof typeof modelFields]: true }; 51 | 52 | for (const key in modelFields) { 53 | if (!toExclude.includes(key as any)) { 54 | result[key] = true; 55 | } 56 | } 57 | 58 | // @todo 59 | // This fails because prop names are not assignable to `string`, 60 | // but to the prop name itself (password: "password" != password: string) 61 | // Caused by the Exclude in the return type. 62 | return result as any; 63 | }; 64 | }; 65 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | .dev/** 25 | !.dev/docs 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (https://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules/ 43 | jspm_packages/ 44 | 45 | # TypeScript cache 46 | *.tsbuildinfo 47 | 48 | # Optional npm cache directory 49 | .npm 50 | 51 | # Optional eslint cache 52 | .eslintcache 53 | 54 | # Microbundle cache 55 | .rpt2_cache/ 56 | .rts2_cache_cjs/ 57 | .rts2_cache_es/ 58 | .rts2_cache_umd/ 59 | 60 | # Optional REPL history 61 | .node_repl_history 62 | 63 | # Output of 'npm pack' 64 | *.tgz 65 | 66 | # Yarn Integrity file 67 | .yarn-integrity 68 | 69 | # dotenv environment variables file 70 | .env 71 | .env.test 72 | .env.* 73 | !.env*.example 74 | 75 | 76 | # parcel-bundler cache (https://parceljs.org/) 77 | .cache 78 | 79 | # Next.js build output 80 | .next 81 | 82 | # Nuxt.js build / generate output 83 | .nuxt 84 | dist 85 | 86 | # Gatsby files 87 | .cache/ 88 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 89 | # https://nextjs.org/blog/next-9-1#public-directory-support 90 | # public 91 | 92 | # vuepress build output 93 | .vuepress/dist 94 | 95 | # Serverless directories 96 | .serverless/ 97 | 98 | # FuseBox cache 99 | .fusebox/ 100 | 101 | # DynamoDB Local files 102 | .dynamodb/ 103 | 104 | # TernJS port file 105 | .tern-port 106 | 107 | .yarn/* 108 | !.yarn/patches 109 | !.yarn/plugins 110 | !.yarn/releases 111 | !.yarn/sdks 112 | !.yarn/versions 113 | .pnp.* 114 | 115 | -------------------------------------------------------------------------------- /examples/simple/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | .dev/** 25 | !.dev/docs 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (https://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules/ 43 | jspm_packages/ 44 | 45 | # TypeScript cache 46 | *.tsbuildinfo 47 | 48 | # Optional npm cache directory 49 | .npm 50 | 51 | # Optional eslint cache 52 | .eslintcache 53 | 54 | # Microbundle cache 55 | .rpt2_cache/ 56 | .rts2_cache_cjs/ 57 | .rts2_cache_es/ 58 | .rts2_cache_umd/ 59 | 60 | # Optional REPL history 61 | .node_repl_history 62 | 63 | # Output of 'npm pack' 64 | *.tgz 65 | 66 | # Yarn Integrity file 67 | .yarn-integrity 68 | 69 | # dotenv environment variables file 70 | .env 71 | .env.test 72 | .env.* 73 | !.env*.example 74 | 75 | 76 | # parcel-bundler cache (https://parceljs.org/) 77 | .cache 78 | 79 | # Next.js build output 80 | .next 81 | 82 | # Nuxt.js build / generate output 83 | .nuxt 84 | dist 85 | 86 | # Gatsby files 87 | .cache/ 88 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 89 | # https://nextjs.org/blog/next-9-1#public-directory-support 90 | # public 91 | 92 | # vuepress build output 93 | .vuepress/dist 94 | 95 | # Serverless directories 96 | .serverless/ 97 | 98 | # FuseBox cache 99 | .fusebox/ 100 | 101 | # DynamoDB Local files 102 | .dynamodb/ 103 | 104 | # TernJS port file 105 | .tern-port 106 | 107 | .yarn/* 108 | !.yarn/patches 109 | !.yarn/plugins 110 | !.yarn/releases 111 | !.yarn/sdks 112 | !.yarn/versions 113 | .pnp.* 114 | 115 | -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | import { Prisma, PrismaClient } from "@prisma/client"; 2 | 3 | /** 4 | * Check if a string starts with `$` 5 | */ 6 | type IsDollar = T extends `$${infer ignore}` ? T : never; 7 | 8 | /** 9 | * Exclude all keys from the PrismaClient that start 10 | * with `$`, leaving only the model names. 11 | * 12 | * T = keyof PrismaClient 13 | */ 14 | export type ModelNames = Exclude>; 15 | 16 | /** 17 | * Get those keys that are compatible with `{modelName}ScalarFieldEnum`, 18 | * so we can later get all props for a model. 19 | */ 20 | type MatchKeys = 21 | `${Capitalize}ScalarFieldEnum` extends keyof typeof Prisma 22 | ? `${Capitalize}ScalarFieldEnum` 23 | : never; 24 | 25 | /** 26 | * Extract from the PrismaClient those keys that will 27 | * get us the properties for each model. 28 | */ 29 | export type GetScalarKey< 30 | T extends PrismaClient, 31 | M extends ModelNames 32 | > = Extract>; 33 | 34 | /** 35 | * Get the props for a given model name. 36 | */ 37 | export type GetModelProps< 38 | T extends PrismaClient, 39 | M extends ModelNames 40 | > = typeof Prisma[GetScalarKey]; 41 | 42 | /** 43 | * The exclude function. 44 | * 45 | * C = client 46 | * M = model 47 | * P = model props 48 | * O = props to omit 49 | */ 50 | type PrismaExcludeFunction = < 51 | M extends ModelNames, 52 | P extends GetModelProps, 53 | O extends (keyof P)[] 54 | >( 55 | model: M, 56 | omit: O 57 | ) => { 58 | [Key in Exclude]: true; 59 | }; 60 | 61 | /** 62 | * Takes a PrismaClient as the only argument and outputs 63 | * the exclude function. 64 | * 65 | * C = client 66 | */ 67 | export type PrismaExclude = ( 68 | client: C 69 | ) => PrismaExcludeFunction; 70 | 71 | /** 72 | * Wraps a PrismaClient and returns it with the extra 73 | * method `$exclude`. 74 | * 75 | * C = client 76 | */ 77 | export interface WithExclude { 78 | (client: C): C & { 79 | $exclude: PrismaExcludeFunction; 80 | }; 81 | } 82 | 83 | /** 84 | * Collection of all possible errors 85 | */ 86 | export enum ExcludeError { 87 | noClient = "A Prisma Client must be provided", 88 | badClient = "The provided client must be an instance of PrismaClient", 89 | noModel = "A model name must be provided", 90 | modelMismatch = "The model provided does not exist within this Prisma Client instance", 91 | } 92 | -------------------------------------------------------------------------------- /examples/simple/yarn.lock: -------------------------------------------------------------------------------- 1 | # This file is generated by running "yarn install" inside your project. 2 | # Manual changes might be lost - proceed with caution! 3 | 4 | __metadata: 5 | version: 6 6 | cacheKey: 8 7 | 8 | "@prisma/client@npm:3.10.0": 9 | version: 3.10.0 10 | resolution: "@prisma/client@npm:3.10.0" 11 | dependencies: 12 | "@prisma/engines-version": 3.10.0-50.73e60b76d394f8d37d8ebd1f8918c79029f0db86 13 | peerDependencies: 14 | prisma: "*" 15 | peerDependenciesMeta: 16 | prisma: 17 | optional: true 18 | checksum: c9fe863abfbcecff6b26c2fc4c93de77fd11c8209e91b8e2cba13ba3f0866d228eb5e92fac43e1f75497b652db54cb5e309320c3d51e603a4ecb4125dbf3a872 19 | languageName: node 20 | linkType: hard 21 | 22 | "@prisma/engines-version@npm:3.10.0-50.73e60b76d394f8d37d8ebd1f8918c79029f0db86": 23 | version: 3.10.0-50.73e60b76d394f8d37d8ebd1f8918c79029f0db86 24 | resolution: "@prisma/engines-version@npm:3.10.0-50.73e60b76d394f8d37d8ebd1f8918c79029f0db86" 25 | checksum: ddcb3bfdab61ac74e2df9e57562ccc7f0eb863955c8cf711f52f45572168f65e030e5070dfc9fc2e37d916b97b236576006b5cd56c813257a96b825c598e79fa 26 | languageName: node 27 | linkType: hard 28 | 29 | "@prisma/engines@npm:3.10.0-50.73e60b76d394f8d37d8ebd1f8918c79029f0db86": 30 | version: 3.10.0-50.73e60b76d394f8d37d8ebd1f8918c79029f0db86 31 | resolution: "@prisma/engines@npm:3.10.0-50.73e60b76d394f8d37d8ebd1f8918c79029f0db86" 32 | checksum: 7faa8659dd72e70f9b24be291e3660d086d5b2ee1b6557bf783100a2efaf4f7087882196191c845f96c3953a55ea8bcb03110af98a18e803b90084c0c2211444 33 | languageName: node 34 | linkType: hard 35 | 36 | "prisma-exclude@npm:1.0.1": 37 | version: 1.0.1 38 | resolution: "prisma-exclude@npm:1.0.1" 39 | peerDependencies: 40 | "@prisma/client": ^3.10.0 41 | prisma: ^3.10.0 42 | checksum: 3827d7129c649cfeca2e0dd16c153f45ac2f9aad800572779642dda49f9bc255c6af98c92723b923277ba67fcafbdc5a3a5adb3771a1a4f874952fc46d9890d4 43 | languageName: node 44 | linkType: hard 45 | 46 | "prisma@npm:3.10.0": 47 | version: 3.10.0 48 | resolution: "prisma@npm:3.10.0" 49 | dependencies: 50 | "@prisma/engines": 3.10.0-50.73e60b76d394f8d37d8ebd1f8918c79029f0db86 51 | bin: 52 | prisma: build/index.js 53 | prisma2: build/index.js 54 | checksum: da693ebd69ec5f5a8132a86f1c6e300033a5ea869016e19364f514fdda6143f0d6236982a26b431313f06fecfaa2d1bd82eac3ebbf5b58082271f1a65c8a683d 55 | languageName: node 56 | linkType: hard 57 | 58 | "simple@workspace:.": 59 | version: 0.0.0-use.local 60 | resolution: "simple@workspace:." 61 | dependencies: 62 | "@prisma/client": 3.10.0 63 | prisma: 3.10.0 64 | prisma-exclude: 1.0.1 65 | languageName: unknown 66 | linkType: soft 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Prisma Exclude

2 |

Exclude fields from your Prisma queries

3 | 4 | ```ts 5 | prisma.user.findMany({ 6 | select: prisma.$exclude("user", ["password"]), 7 | }) 8 | ``` 9 | 10 | [![codecov](https://codecov.io/gh/ajmnz/prisma-exclude/branch/main/graph/badge.svg?token=4YHPCUVW75)](https://codecov.io/gh/ajmnz/prisma-exclude) 11 | 12 | --- 13 | 14 | ### ❗ This project is no longer maintained 15 | 16 | Prisma has released native exclude support, addressing exactly what this project aimed to solve. More info: 17 | 18 | - `omitApi` preview feature: https://github.com/prisma/prisma/discussions/23924 19 | 20 | Thank you! 21 | 22 |
23 | 24 | ## Table of contents 25 | - [Table of contents](#table-of-contents) 26 | - [Installation](#installation) 27 | - [Usage](#usage) 28 | - [Using `withExclude`](#using-withexclude) 29 | - [Using `prismaExclude`](#using-prismaexclude) 30 | 31 | ## Installation 32 | 33 | > It is assumed that both `prisma` and `@prisma/client` packages are installed 34 | > and that the Prisma Client has been generated. 35 | 36 | ```shell 37 | $ yarn add prisma-exclude 38 | ``` 39 | or 40 | ```shell 41 | $ npm install prisma-exclude 42 | ``` 43 | 44 | ## Usage 45 | 46 | **prisma-exclude** can be used in two different ways. You can wrap your instance of the Prisma Client with `withExclude` or directly pass your client to the `prismaExclude` function. 47 | 48 | Both ways give you access to the `exclude` function which accepts a model name and an array of fields to exclude, all while maintaining type safety. This means that both model names and fields will have access to autocompletion (depending on your IDE). 49 | 50 | #### Using `withExclude` 51 | 52 | Wrap your Prisma Client with `withExclude` when initializing your instance. 53 | 54 | ```ts 55 | import { PrismaClient } from "@prisma/client"; 56 | import { withExclude } from "prisma-exclude"; 57 | 58 | export const prisma = withExclude(new PrismaClient()); 59 | ``` 60 | 61 | Then use the new available method `$exclude` to omit fields from your queries 62 | 63 | ```ts 64 | import { prisma } from "./instance"; 65 | 66 | const users = await prisma.user.findMany({ 67 | select: prisma.$exclude("user", ["password"]); 68 | }); 69 | ``` 70 | 71 | #### Using `prismaExclude` 72 | 73 | If you don't want an extra method in your Prisma Client instance, you can initialize your own `exclude` function by providing the instance to `prismaExclude` 74 | 75 | ```ts 76 | import { PrismaClient } from "@prisma/client"; 77 | import { prismaExclude } from "prisma-exclude"; 78 | 79 | export const prisma = new PrismaClient(); 80 | export const exclude = prismaExclude(prisma); 81 | ``` 82 | 83 | Then you can use it in your queries 84 | 85 | ```ts 86 | import { prisma, exclude } from "./instance"; 87 | 88 | const addresses = await prisma.address.findMany({ 89 | where: { 90 | active: true, 91 | }, 92 | include: { 93 | user: { 94 | select: exclude("user", ["password"]); 95 | } 96 | } 97 | }); 98 | ``` 99 | 100 | 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - main 10 | 11 | jobs: 12 | install: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout commit 16 | uses: actions/checkout@v3 17 | - name: Use Node.js 18 | uses: actions/setup-node@v3 19 | with: 20 | node-version: 16 21 | - name: Cache yarn dependencies 22 | uses: actions/cache@v2 23 | id: cache-dependencies 24 | with: 25 | path: node_modules 26 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 27 | restore-keys: | 28 | ${{ runner.os }}-yarn- 29 | - name: Install dependencies 30 | if: steps.cache-dependencies.outputs.cache-hit != 'true' 31 | run: | 32 | yarn install 33 | lint-format: 34 | runs-on: ubuntu-latest 35 | needs: install 36 | steps: 37 | - name: Checkout commit 38 | uses: actions/checkout@v3 39 | - name: Use Node.js 40 | uses: actions/setup-node@v3 41 | with: 42 | node-version: 16 43 | - name: Restore yarn dependencies 44 | uses: actions/cache@v2 45 | id: cache-dependencies 46 | with: 47 | path: node_modules 48 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 49 | restore-keys: | 50 | ${{ runner.os }}-yarn- 51 | - name: Run eslint 52 | run: | 53 | yarn lint 54 | - name: Run prettier 55 | run: | 56 | yarn format 57 | - name: Typecheck 58 | run: | 59 | yarn typecheck 60 | test: 61 | runs-on: ubuntu-latest 62 | needs: install 63 | steps: 64 | - name: Checkout commit 65 | uses: actions/checkout@v3 66 | - name: Use Node.js 67 | uses: actions/setup-node@v3 68 | with: 69 | node-version: 16 70 | - name: Restore yarn dependencies 71 | uses: actions/cache@v2 72 | id: cache-dependencies 73 | with: 74 | path: node_modules 75 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 76 | restore-keys: | 77 | ${{ runner.os }}-yarn- 78 | - name: Run tests 79 | run: | 80 | yarn test 81 | env: 82 | DATABASE_URL: postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public 83 | build: 84 | runs-on: ubuntu-latest 85 | needs: 86 | - install 87 | - lint-format 88 | - test 89 | steps: 90 | - name: Checkout commit 91 | uses: actions/checkout@v3 92 | - name: Use Node.js 93 | uses: actions/setup-node@v3 94 | with: 95 | node-version: 16 96 | - name: Restore yarn dependencies 97 | uses: actions/cache@v2 98 | id: cache-dependencies 99 | with: 100 | path: node_modules 101 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 102 | restore-keys: | 103 | ${{ runner.os }}-yarn- 104 | - name: Build 105 | run: | 106 | yarn build 107 | env: 108 | DATABASE_URL: postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public 109 | -------------------------------------------------------------------------------- /tests/lib.test.ts: -------------------------------------------------------------------------------- 1 | import { Prisma, PrismaClient } from "@prisma/client"; 2 | import { prismaExclude, withExclude } from "../src"; 3 | import { ExcludeError, PrismaExclude } from "../src/types"; 4 | 5 | describe("test library", () => { 6 | let prisma: PrismaClient; 7 | let exclude: ReturnType; 8 | 9 | beforeAll(() => { 10 | prisma = new PrismaClient(); 11 | exclude = prismaExclude(prisma); 12 | }); 13 | 14 | describe("prismaExclude", () => { 15 | it("should throw if no client is provided", () => { 16 | // @ts-ignore 17 | expect(prismaExclude()).toThrow(ExcludeError.noClient); 18 | }); 19 | 20 | it("should throw if an invalid client is provided", () => { 21 | expect(prismaExclude({} as any)).toThrow(ExcludeError.badClient); 22 | }); 23 | 24 | it("should throw if no model is provided", () => { 25 | // @ts-ignore 26 | expect(() => exclude()).toThrow(ExcludeError.noModel); 27 | }); 28 | 29 | it("should throw if an invalid model is provided", () => { 30 | // @ts-ignore 31 | expect(() => exclude("nope")).toThrow(ExcludeError.modelMismatch); 32 | }); 33 | 34 | it("should return all keys if no keys to exclude are provided", () => { 35 | let validKeys = {} as { [K: string]: true }; 36 | for (const key in Prisma.UserScalarFieldEnum) { 37 | validKeys[key] = true; 38 | } 39 | 40 | expect(exclude("user", [])).toStrictEqual(validKeys); 41 | }); 42 | 43 | it("should exclude a key", () => { 44 | let validKeys = {} as { [K: string]: true }; 45 | for (const key in Prisma.UserScalarFieldEnum) { 46 | if (key !== "password") { 47 | validKeys[key] = true; 48 | } 49 | } 50 | 51 | expect(exclude("user", ["password"])).toStrictEqual(validKeys); 52 | }); 53 | 54 | it("should exclude multiple keys", () => { 55 | let validKeys = {} as { [K: string]: true }; 56 | for (const key in Prisma.UserScalarFieldEnum) { 57 | if (!["password", "email"].includes(key)) { 58 | validKeys[key] = true; 59 | } 60 | } 61 | 62 | expect(exclude("user", ["password", "email"])).toStrictEqual(validKeys); 63 | }); 64 | 65 | it("should ignore unknown keys", () => { 66 | let validKeys = {} as { [K: string]: true }; 67 | for (const key in Prisma.UserScalarFieldEnum) { 68 | if (key !== "password") { 69 | validKeys[key] = true; 70 | } 71 | } 72 | 73 | // @ts-ignore 74 | expect(exclude("user", ["password", "nope"])).toStrictEqual(validKeys); 75 | }); 76 | }); 77 | 78 | describe("withExclude", () => { 79 | it("should throw if no client is provided", () => { 80 | // @ts-ignore 81 | expect(() => withExclude()).toThrow(ExcludeError.noClient); 82 | }); 83 | 84 | it("should throw if an invalid client is provided", () => { 85 | expect(() => withExclude({} as any)).toThrow(ExcludeError.badClient); 86 | }); 87 | 88 | it("should have the $exclude method", () => { 89 | const client = withExclude(prisma); 90 | expect(client).toHaveProperty("$exclude"); 91 | }); 92 | 93 | it("should have a working $exclude method", () => { 94 | const client = withExclude(prisma); 95 | let validKeys = {} as { [K: string]: true }; 96 | for (const key in Prisma.UserScalarFieldEnum) { 97 | if (key !== "password") { 98 | validKeys[key] = true; 99 | } 100 | } 101 | 102 | expect(client.$exclude("user", ["password"])).toStrictEqual(validKeys); 103 | }); 104 | }); 105 | }); 106 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "node": true 6 | }, 7 | "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"], 8 | "parser": "@typescript-eslint/parser", 9 | "parserOptions": { 10 | "ecmaFeatures": { 11 | "jsx": true 12 | }, 13 | "ecmaVersion": 12, 14 | "sourceType": "module" 15 | }, 16 | "plugins": ["@typescript-eslint/eslint-plugin", "unused-imports"], 17 | "settings": { 18 | "html/xml-extensions": [".html"], 19 | "html/indent": "+2" 20 | }, 21 | "rules": { 22 | "@typescript-eslint/no-unused-vars": [ 23 | "warn", 24 | { 25 | "args": "all", 26 | "caughtErrors": "all", 27 | "argsIgnorePattern": "_|res|req|next", 28 | "varsIgnorePattern": "ignore", 29 | "ignoreRestSiblings": true 30 | } 31 | ], 32 | "@typescript-eslint/no-explicit-any": "off", 33 | "@typescript-eslint/no-var-requires": "off", 34 | "@typescript-eslint/no-non-null-assertion": "off", 35 | "@typescript-eslint/no-empty-interface": "off", 36 | "@typescript-eslint/explicit-module-boundary-types": "off", 37 | "@typescript-eslint/member-delimiter-style": "off", 38 | "no-empty": "off", 39 | "no-empty-pattern": "off", 40 | "accessor-pairs": "error", 41 | "array-bracket-newline": "off", 42 | "array-bracket-spacing": "error", 43 | "array-callback-return": "off", 44 | "arrow-body-style": "off", 45 | "arrow-parens": "off", 46 | "arrow-spacing": "error", 47 | "block-scoped-var": "error", 48 | "block-spacing": "error", 49 | "brace-style": "error", 50 | "camelcase": "off", 51 | "comma-dangle": "off", 52 | "comma-spacing": "error", 53 | "comma-style": "error", 54 | "complexity": "off", 55 | "computed-property-spacing": "error", 56 | "consistent-this": "error", 57 | "default-case-last": "error", 58 | "default-param-last": "error", 59 | "dot-location": ["error", "property"], 60 | "dot-notation": "error", 61 | "eol-last": "error", 62 | "eqeqeq": "error", 63 | "func-call-spacing": "off", 64 | "func-name-matching": "error", 65 | "func-names": "error", 66 | "func-style": [ 67 | "error", 68 | "declaration", 69 | { 70 | "allowArrowFunctions": true 71 | } 72 | ], 73 | "function-call-argument-newline": ["error", "consistent"], 74 | "function-paren-newline": "off", 75 | "generator-star-spacing": "error", 76 | "global-require": "error", 77 | "grouped-accessor-pairs": "error", 78 | "guard-for-in": "error", 79 | "handle-callback-err": "error", 80 | "id-blacklist": "error", 81 | "id-denylist": "error", 82 | "id-match": "error", 83 | "indent": [ 84 | "off", 85 | 2, 86 | { 87 | "offsetTernaryExpressions": true 88 | } 89 | ], 90 | "jsx-quotes": "error", 91 | "key-spacing": ["error"], 92 | "keyword-spacing": "off", 93 | "line-comment-position": "off", 94 | "linebreak-style": "error", 95 | "lines-around-comment": "off", 96 | "lines-around-directive": "error", 97 | "lines-between-class-members": "off", 98 | "max-classes-per-file": ["error", 3], 99 | "max-depth": "error", 100 | "max-len": "off", 101 | "max-lines": "off", 102 | "max-lines-per-function": "off", 103 | "max-nested-callbacks": "error", 104 | "max-statements": "off", 105 | "max-statements-per-line": "off", 106 | "multiline-comment-style": "off", 107 | "multiline-ternary": "off", 108 | "new-cap": "off", 109 | "new-parens": "error", 110 | "newline-after-var": "off", 111 | "newline-before-return": "off", 112 | "newline-per-chained-call": "off", 113 | "no-alert": "error", 114 | "no-array-constructor": "error", 115 | "no-await-in-loop": "off", 116 | "no-bitwise": "off", 117 | "no-buffer-constructor": "error", 118 | "no-caller": "error", 119 | "no-catch-shadow": "error", 120 | "no-console": "off", 121 | "no-constructor-return": "error", 122 | "no-continue": "error", 123 | "no-div-regex": "error", 124 | "no-duplicate-imports": "error", 125 | "@typescript-eslint/no-empty-function": "off", 126 | "no-eq-null": "error", 127 | "no-eval": "error", 128 | "no-extend-native": "error", 129 | "no-extra-bind": "error", 130 | "no-extra-label": "error", 131 | "no-extra-parens": "off", 132 | "no-floating-decimal": "error", 133 | "no-implicit-coercion": "off", 134 | "no-implicit-globals": "error", 135 | "no-implied-eval": "error", 136 | "no-inline-comments": "off", 137 | "no-invalid-this": "off", 138 | "@typescript-eslint/no-invalid-this": ["error"], 139 | "no-iterator": "error", 140 | "no-label-var": "error", 141 | "no-labels": "error", 142 | "no-lone-blocks": "error", 143 | "no-lonely-if": "error", 144 | "no-loop-func": "error", 145 | "no-loss-of-precision": "error", 146 | "@typescript-eslint/no-magic-numbers": "off", 147 | "no-mixed-operators": "off", 148 | "no-mixed-requires": "error", 149 | "no-multi-assign": "error", 150 | "no-multi-spaces": "error", 151 | "no-multi-str": "error", 152 | "no-multiple-empty-lines": "error", 153 | "no-native-reassign": "error", 154 | "no-negated-condition": "off", 155 | "no-negated-in-lhs": "error", 156 | "no-nested-ternary": "error", 157 | "no-new": "error", 158 | "no-new-func": "error", 159 | "no-new-object": "error", 160 | "no-new-require": "error", 161 | "no-new-wrappers": "error", 162 | "no-nonoctal-decimal-escape": "error", 163 | "no-octal-escape": "error", 164 | "no-param-reassign": "error", 165 | "no-path-concat": "error", 166 | "no-plusplus": "off", 167 | "no-process-env": "off", 168 | "no-process-exit": "error", 169 | "no-promise-executor-return": "error", 170 | "no-proto": "error", 171 | "no-restricted-exports": "error", 172 | "no-restricted-globals": "error", 173 | "no-restricted-imports": "error", 174 | "no-restricted-modules": "error", 175 | "no-restricted-properties": "error", 176 | "no-restricted-syntax": "error", 177 | "no-script-url": "error", 178 | "no-self-compare": "error", 179 | "no-sequences": "error", 180 | "@typescript-eslint/no-shadow": "error", 181 | "no-spaced-func": "off", 182 | "no-tabs": "error", 183 | "no-template-curly-in-string": "error", 184 | "no-throw-literal": "error", 185 | "no-trailing-spaces": "error", 186 | "no-undef-init": "off", 187 | "no-undefined": "off", 188 | "no-underscore-dangle": "off", 189 | "no-unmodified-loop-condition": "error", 190 | "no-unneeded-ternary": "error", 191 | "no-unreachable-loop": "error", 192 | "no-unsafe-optional-chaining": "error", 193 | "no-unused-expressions": "warn", 194 | "@typescript-eslint/no-use-before-define": "error", 195 | "no-useless-backreference": "error", 196 | "no-useless-call": "error", 197 | "no-useless-computed-key": "error", 198 | "no-useless-concat": "error", 199 | "no-useless-constructor": "off", 200 | "no-useless-rename": "error", 201 | "no-useless-return": "error", 202 | "no-var": "error", 203 | "no-void": "error", 204 | "no-whitespace-before-property": "error", 205 | "nonblock-statement-body-position": "error", 206 | "object-curly-newline": "error", 207 | "object-curly-spacing": ["error", "always"], 208 | "object-property-newline": [ 209 | "error", 210 | { 211 | "allowAllPropertiesOnSameLine": true 212 | } 213 | ], 214 | "object-shorthand": "error", 215 | "one-var": ["error", "never"], 216 | "operator-assignment": "error", 217 | "operator-linebreak": "error", 218 | "padded-blocks": ["error", "never"], 219 | "padding-line-between-statements": "off", 220 | "prefer-arrow-callback": "error", 221 | "prefer-const": "error", 222 | "prefer-destructuring": "off", 223 | "prefer-exponentiation-operator": "error", 224 | "prefer-named-capture-group": "off", 225 | "prefer-numeric-literals": "error", 226 | "prefer-object-spread": "error", 227 | "prefer-promise-reject-errors": "error", 228 | "prefer-regex-literals": "error", 229 | "prefer-rest-params": "error", 230 | "prefer-spread": "error", 231 | "prefer-template": "off", 232 | "quote-props": "off", 233 | "quotes": "off", 234 | "radix": "off", 235 | "require-await": "error", 236 | "require-unicode-regexp": "off", 237 | "rest-spread-spacing": "error", 238 | "@typescript-eslint/semi": [ 239 | "error", 240 | "always", 241 | { 242 | "omitLastInOneLineBlock": true 243 | } 244 | ], 245 | "semi-spacing": "error", 246 | "semi-style": "error", 247 | "no-extra-semi": "error", 248 | "space-before-blocks": "error", 249 | "space-before-function-paren": [ 250 | "error", 251 | { 252 | "anonymous": "never", 253 | "named": "never", 254 | "asyncArrow": "always" 255 | } 256 | ], 257 | "space-in-parens": ["error", "never"], 258 | "space-infix-ops": "error", 259 | "space-unary-ops": [ 260 | "error", 261 | { 262 | "words": true, 263 | "nonwords": false 264 | } 265 | ], 266 | "spaced-comment": "error", 267 | "strict": "error", 268 | "switch-colon-spacing": "error", 269 | "symbol-description": "error", 270 | "template-curly-spacing": "error", 271 | "template-tag-spacing": "error", 272 | "unicode-bom": "error", 273 | "valid-jsdoc": "off", 274 | "vars-on-top": "error", 275 | "wrap-iife": "error", 276 | "wrap-regex": "error", 277 | "yield-star-spacing": "error", 278 | "yoda": "error", 279 | "@typescript-eslint/ban-types": ["warn"], 280 | "unused-imports/no-unused-imports": "warn", 281 | "sort-imports": ["warn", { "ignoreDeclarationSort": true }] 282 | } 283 | } 284 | --------------------------------------------------------------------------------