@prismalyst/core 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (168) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +209 -2
  3. package/dist/ast/parser/create-ast-parser.d.ts +8 -0
  4. package/dist/ast/parser/create-ast-parser.d.ts.map +1 -0
  5. package/dist/ast/parser/create-ast-parser.js +41 -0
  6. package/dist/ast/parser/create-ast-parser.js.map +1 -0
  7. package/dist/ast/prisma/convert-to-prisma-expression.d.ts +5 -0
  8. package/dist/ast/prisma/convert-to-prisma-expression.d.ts.map +1 -0
  9. package/dist/ast/prisma/convert-to-prisma-expression.js +58 -0
  10. package/dist/ast/prisma/convert-to-prisma-expression.js.map +1 -0
  11. package/dist/ast/prisma/is-prisma-expression.d.ts +5 -0
  12. package/dist/ast/prisma/is-prisma-expression.d.ts.map +1 -0
  13. package/dist/ast/prisma/is-prisma-expression.js +52 -0
  14. package/dist/ast/prisma/is-prisma-expression.js.map +1 -0
  15. package/dist/ast/prisma/utils/define-method.d.ts +4 -0
  16. package/dist/ast/prisma/utils/define-method.d.ts.map +1 -0
  17. package/dist/ast/prisma/utils/define-method.js +18 -0
  18. package/dist/ast/prisma/utils/define-method.js.map +1 -0
  19. package/dist/ast/prisma/utils/remove-quotes.d.ts +2 -0
  20. package/dist/ast/prisma/utils/remove-quotes.d.ts.map +1 -0
  21. package/dist/ast/prisma/utils/remove-quotes.js +9 -0
  22. package/dist/ast/prisma/utils/remove-quotes.js.map +1 -0
  23. package/dist/ast/utils/create-ast-utils.d.ts +30 -0
  24. package/dist/ast/utils/create-ast-utils.d.ts.map +1 -0
  25. package/dist/ast/utils/create-ast-utils.js +9 -0
  26. package/dist/ast/utils/create-ast-utils.js.map +1 -0
  27. package/dist/ast/utils/create-node-utils.d.ts +21 -0
  28. package/dist/ast/utils/create-node-utils.d.ts.map +1 -0
  29. package/dist/ast/utils/create-node-utils.js +315 -0
  30. package/dist/ast/utils/create-node-utils.js.map +1 -0
  31. package/dist/ast/utils/create-prisma-utils.d.ts +12 -0
  32. package/dist/ast/utils/create-prisma-utils.d.ts.map +1 -0
  33. package/dist/ast/utils/create-prisma-utils.js +130 -0
  34. package/dist/ast/utils/create-prisma-utils.js.map +1 -0
  35. package/dist/ast/utils/get-property.d.ts +34 -0
  36. package/dist/ast/utils/get-property.d.ts.map +1 -0
  37. package/dist/ast/utils/get-property.js +61 -0
  38. package/dist/ast/utils/get-property.js.map +1 -0
  39. package/dist/constants/prisma-methods.constants.d.ts +14 -0
  40. package/dist/constants/prisma-methods.constants.d.ts.map +1 -0
  41. package/dist/constants/prisma-methods.constants.js +43 -0
  42. package/dist/constants/prisma-methods.constants.js.map +1 -0
  43. package/dist/index.cjs +1261 -0
  44. package/dist/index.d.ts +8 -0
  45. package/dist/index.d.ts.map +1 -0
  46. package/dist/index.js +7 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/rules/list/limit-relation-loading.d.ts +4 -0
  49. package/dist/rules/list/limit-relation-loading.d.ts.map +1 -0
  50. package/dist/rules/list/limit-relation-loading.js +60 -0
  51. package/dist/rules/list/limit-relation-loading.js.map +1 -0
  52. package/dist/rules/list/max-take.d.ts +7 -0
  53. package/dist/rules/list/max-take.d.ts.map +1 -0
  54. package/dist/rules/list/max-take.js +32 -0
  55. package/dist/rules/list/max-take.js.map +1 -0
  56. package/dist/rules/list/no-deep-offset-pagination.d.ts +8 -0
  57. package/dist/rules/list/no-deep-offset-pagination.d.ts.map +1 -0
  58. package/dist/rules/list/no-deep-offset-pagination.js +26 -0
  59. package/dist/rules/list/no-deep-offset-pagination.js.map +1 -0
  60. package/dist/rules/list/no-disconnect-in-request-flow.d.ts +8 -0
  61. package/dist/rules/list/no-disconnect-in-request-flow.d.ts.map +1 -0
  62. package/dist/rules/list/no-disconnect-in-request-flow.js +17 -0
  63. package/dist/rules/list/no-disconnect-in-request-flow.js.map +1 -0
  64. package/dist/rules/list/no-dynamic-raw-query.d.ts +4 -0
  65. package/dist/rules/list/no-dynamic-raw-query.d.ts.map +1 -0
  66. package/dist/rules/list/no-dynamic-raw-query.js +13 -0
  67. package/dist/rules/list/no-dynamic-raw-query.js.map +1 -0
  68. package/dist/rules/list/no-floating-prisma-promise.d.ts +4 -0
  69. package/dist/rules/list/no-floating-prisma-promise.d.ts.map +1 -0
  70. package/dist/rules/list/no-floating-prisma-promise.js +10 -0
  71. package/dist/rules/list/no-floating-prisma-promise.js.map +1 -0
  72. package/dist/rules/list/no-prisma-client-in-function.d.ts +9 -0
  73. package/dist/rules/list/no-prisma-client-in-function.d.ts.map +1 -0
  74. package/dist/rules/list/no-prisma-client-in-function.js +30 -0
  75. package/dist/rules/list/no-prisma-client-in-function.js.map +1 -0
  76. package/dist/rules/list/no-query-in-loop.d.ts +4 -0
  77. package/dist/rules/list/no-query-in-loop.d.ts.map +1 -0
  78. package/dist/rules/list/no-query-in-loop.js +9 -0
  79. package/dist/rules/list/no-query-in-loop.js.map +1 -0
  80. package/dist/rules/list/no-root-client-in-transaction.d.ts +4 -0
  81. package/dist/rules/list/no-root-client-in-transaction.d.ts.map +1 -0
  82. package/dist/rules/list/no-root-client-in-transaction.js +12 -0
  83. package/dist/rules/list/no-root-client-in-transaction.js.map +1 -0
  84. package/dist/rules/list/no-unindexed-filter.d.ts +4 -0
  85. package/dist/rules/list/no-unindexed-filter.d.ts.map +1 -0
  86. package/dist/rules/list/no-unindexed-filter.js +62 -0
  87. package/dist/rules/list/no-unindexed-filter.js.map +1 -0
  88. package/dist/rules/list/no-unsafe-prisma-raw.d.ts +4 -0
  89. package/dist/rules/list/no-unsafe-prisma-raw.d.ts.map +1 -0
  90. package/dist/rules/list/no-unsafe-prisma-raw.js +19 -0
  91. package/dist/rules/list/no-unsafe-prisma-raw.js.map +1 -0
  92. package/dist/rules/list/no-unsafe-raw-sql.d.ts +4 -0
  93. package/dist/rules/list/no-unsafe-raw-sql.d.ts.map +1 -0
  94. package/dist/rules/list/no-unsafe-raw-sql.js +7 -0
  95. package/dist/rules/list/no-unsafe-raw-sql.js.map +1 -0
  96. package/dist/rules/list/require-where-delete-many.d.ts +4 -0
  97. package/dist/rules/list/require-where-delete-many.d.ts.map +1 -0
  98. package/dist/rules/list/require-where-delete-many.js +25 -0
  99. package/dist/rules/list/require-where-delete-many.js.map +1 -0
  100. package/dist/rules/list/require-where-update-many.d.ts +4 -0
  101. package/dist/rules/list/require-where-update-many.d.ts.map +1 -0
  102. package/dist/rules/list/require-where-update-many.js +25 -0
  103. package/dist/rules/list/require-where-update-many.js.map +1 -0
  104. package/dist/rules/list/unstable-pagination.d.ts +4 -0
  105. package/dist/rules/list/unstable-pagination.d.ts.map +1 -0
  106. package/dist/rules/list/unstable-pagination.js +59 -0
  107. package/dist/rules/list/unstable-pagination.js.map +1 -0
  108. package/dist/rules/list/warn-cascade-delete.d.ts +4 -0
  109. package/dist/rules/list/warn-cascade-delete.d.ts.map +1 -0
  110. package/dist/rules/list/warn-cascade-delete.js +24 -0
  111. package/dist/rules/list/warn-cascade-delete.js.map +1 -0
  112. package/dist/rules/rules-list.d.ts +3 -0
  113. package/dist/rules/rules-list.d.ts.map +1 -0
  114. package/dist/rules/rules-list.js +133 -0
  115. package/dist/rules/rules-list.js.map +1 -0
  116. package/dist/rules/types/rules-options.types.d.ts +34 -0
  117. package/dist/rules/types/rules-options.types.d.ts.map +1 -0
  118. package/dist/rules/types/rules-options.types.js +2 -0
  119. package/dist/rules/types/rules-options.types.js.map +1 -0
  120. package/dist/rules/utils/is-array.d.ts +2 -0
  121. package/dist/rules/utils/is-array.d.ts.map +1 -0
  122. package/dist/rules/utils/is-array.js +4 -0
  123. package/dist/rules/utils/is-array.js.map +1 -0
  124. package/dist/rules/utils/is-expression-in-allowed-function.d.ts +3 -0
  125. package/dist/rules/utils/is-expression-in-allowed-function.d.ts.map +1 -0
  126. package/dist/rules/utils/is-expression-in-allowed-function.js +5 -0
  127. package/dist/rules/utils/is-expression-in-allowed-function.js.map +1 -0
  128. package/dist/rules/utils/is-expression-in-ignored-files.d.ts +2 -0
  129. package/dist/rules/utils/is-expression-in-ignored-files.d.ts.map +1 -0
  130. package/dist/rules/utils/is-expression-in-ignored-files.js +5 -0
  131. package/dist/rules/utils/is-expression-in-ignored-files.js.map +1 -0
  132. package/dist/rules/utils/is-expression-in-test-file.d.ts +2 -0
  133. package/dist/rules/utils/is-expression-in-test-file.d.ts.map +1 -0
  134. package/dist/rules/utils/is-expression-in-test-file.js +4 -0
  135. package/dist/rules/utils/is-expression-in-test-file.js.map +1 -0
  136. package/dist/rules/utils/is-expression-inside-constructor.d.ts +3 -0
  137. package/dist/rules/utils/is-expression-inside-constructor.d.ts.map +1 -0
  138. package/dist/rules/utils/is-expression-inside-constructor.js +4 -0
  139. package/dist/rules/utils/is-expression-inside-constructor.js.map +1 -0
  140. package/dist/rules/utils/is-expression-inside-function-like.d.ts +3 -0
  141. package/dist/rules/utils/is-expression-inside-function-like.d.ts.map +1 -0
  142. package/dist/rules/utils/is-expression-inside-function-like.js +4 -0
  143. package/dist/rules/utils/is-expression-inside-function-like.js.map +1 -0
  144. package/dist/rules/utils/is-object-empty.d.ts +2 -0
  145. package/dist/rules/utils/is-object-empty.d.ts.map +1 -0
  146. package/dist/rules/utils/is-object-empty.js +4 -0
  147. package/dist/rules/utils/is-object-empty.js.map +1 -0
  148. package/dist/rules/utils/is-object.d.ts +2 -0
  149. package/dist/rules/utils/is-object.d.ts.map +1 -0
  150. package/dist/rules/utils/is-object.js +4 -0
  151. package/dist/rules/utils/is-object.js.map +1 -0
  152. package/dist/rules/utils/is-template-node.d.ts +3 -0
  153. package/dist/rules/utils/is-template-node.d.ts.map +1 -0
  154. package/dist/rules/utils/is-template-node.js +9 -0
  155. package/dist/rules/utils/is-template-node.js.map +1 -0
  156. package/dist/types/ast.types.d.ts +35 -0
  157. package/dist/types/ast.types.d.ts.map +1 -0
  158. package/dist/types/ast.types.js +2 -0
  159. package/dist/types/ast.types.js.map +1 -0
  160. package/dist/types/prisma.types.d.ts +46 -0
  161. package/dist/types/prisma.types.d.ts.map +1 -0
  162. package/dist/types/prisma.types.js +2 -0
  163. package/dist/types/prisma.types.js.map +1 -0
  164. package/dist/types/rule.eslint.types.d.ts +22 -0
  165. package/dist/types/rule.eslint.types.d.ts.map +1 -0
  166. package/dist/types/rule.eslint.types.js +2 -0
  167. package/dist/types/rule.eslint.types.js.map +1 -0
  168. package/package.json +57 -3
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Prismalyst
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,210 @@
1
- # Temporary Holding Version
1
+ # Prismalyst Core
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Internal analysis engine and shared TypeScript contracts for the
4
+ [Prismalyst ESLint plugin](https://github.com/Prismalyst/eslint-plugin).
5
+
6
+ The core identifies Prisma calls and client construction through the TypeScript compiler API,
7
+ extracts their arguments and context, and evaluates rules. Analysis does not execute Prisma queries
8
+ or require a database connection.
9
+
10
+ ## Responsibilities
11
+
12
+ | Core | ESLint plugin |
13
+ | ----------------------------------------------------------- | -------------------------------------------------------------------- |
14
+ | Recognize Prisma expressions using type information. | Obtain the TypeScript program from ESLint parser services. |
15
+ | Parse arguments, source locations, and expression context. | Map between TypeScript and ESLint AST nodes. |
16
+ | Define rule behavior, option types, and registration. | Define messages, severity, option validation, defaults, and presets. |
17
+ | Return whether a rule triggers and which node to highlight. | Load schema metadata and report diagnostics through ESLint. |
18
+
19
+ The package exports ESM, CommonJS, and TypeScript declarations from `dist`. Changes to exported
20
+ contracts must be coordinated with the plugin.
21
+
22
+ ## Development setup
23
+
24
+ Use **Node.js 24** and **npm** to match [CI](.github/workflows/ci.yml). Run these commands from
25
+ `prismalyst-core`:
26
+
27
+ ```sh
28
+ npm ci
29
+ npm run prisma:v7:generate
30
+ ```
31
+
32
+ The generation step creates the ignored test client in `src/tests/schemas/v7/generated/prisma`.
33
+ Repeat it after changing the [test schema](src/tests/schemas/v7/schema.prisma). Tests analyze source
34
+ fixtures and use in-memory schema metadata; database setup and migrations are not required.
35
+
36
+ The declared TypeScript peer range is `>=5.0.0 <7`. The current development dependency is TypeScript
37
+ 6, and the AST fixtures cover Prisma 7. The peer range alone does not establish compatibility with
38
+ every Prisma generator or TypeScript version.
39
+
40
+ ## Checks and commands
41
+
42
+ Run the same checks as CI before submitting a change:
43
+
44
+ ```sh
45
+ npm run lint
46
+ npm run typecheck
47
+ npm run test:ci
48
+ npm run build
49
+ ```
50
+
51
+ `typecheck` checks production source; `tsconfig.json` excludes the tests. The build emits declarations
52
+ and ESM files through TypeScript, then creates the CommonJS entry with Rollup.
53
+
54
+ | Command | Purpose |
55
+ | ----------------------------------------- | -------------------------------------------------------- |
56
+ | `npm run test:watch` | Run Vitest in watch mode. |
57
+ | `npm run test:ci -- src/tests/unit/rules` | Run rule unit tests. |
58
+ | `npm run test:ci -- src/tests/ast/v7` | Run Prisma expression and parser fixture tests. |
59
+ | `npm run watch` | Recompile TypeScript on source changes. |
60
+ | `npm run pack:check` | Preview the package contents without creating a tarball. |
61
+
62
+ ## Project structure
63
+
64
+ ```text
65
+ src/
66
+ ast/ Prisma expression detection, conversion, and parsing helpers
67
+ constants/ Shared Prisma method groups
68
+ rules/
69
+ list/ Rule implementations
70
+ types/ Rule names and their option types
71
+ utils/ Shared rule helpers
72
+ rules-list.ts Rule registration and dispatch metadata
73
+ tests/
74
+ unit/ Isolated rule and utility tests
75
+ ast/v7/ Type-aware tests backed by TypeScript fixtures
76
+ schemas/v7/ Prisma schema and generated test client
77
+ types/ AST, Prisma expression, and rule contracts
78
+ index.ts Package exports
79
+ documentation/ One Markdown page per rule
80
+ ```
81
+
82
+ ## Core API
83
+
84
+ The public entry point is [`src/index.ts`](src/index.ts).
85
+
86
+ | Export | Purpose |
87
+ | ---------------------------------------------------- | -------------------------------------------------------------------------------- |
88
+ | `createAstUtils(ts, checker)` | Create node and Prisma helpers for a TypeScript analysis context. |
89
+ | `isPrismaExpression(node, program, astUtils)` | Identify a supported Prisma call or client construction. |
90
+ | `convertToPrismaExpression(node, program, astUtils)` | Extract arguments, locations, method, model, and context from a recognized node. |
91
+ | `getProperty(argument, path)` | Read a nested parsed value while preserving its source node. |
92
+ | `RULES_LIST` | Access registered rules, their functions, and dispatch metadata. |
93
+ | `ParsedValue` | Type for a parsed value and its source nodes. |
94
+ | `OptionsByRuleName` | Type mapping rule names to their option objects. |
95
+ | `RegisteredRule` | Type linking a registered rule name to its function and options. |
96
+
97
+ ### Example: evaluating one rule
98
+
99
+ This fragment assumes `program` is the host's `ts.Program` and `node` comes from that program's AST
100
+ traversal. Create `astUtils` once per analysis context and reuse it while visiting nodes.
101
+
102
+ ```ts
103
+ import {
104
+ RULES_LIST,
105
+ convertToPrismaExpression,
106
+ createAstUtils,
107
+ isPrismaExpression,
108
+ } from '@prismalyst/core';
109
+ import * as ts from 'typescript';
110
+
111
+ const astUtils = createAstUtils(ts, program.getTypeChecker());
112
+ const rule = RULES_LIST.find((candidate) => candidate.name === 'max-take');
113
+
114
+ if (
115
+ rule?.name === 'max-take' &&
116
+ ts.isCallExpression(node) &&
117
+ isPrismaExpression(node, program, astUtils)
118
+ ) {
119
+ const expression = convertToPrismaExpression(node, program, astUtils);
120
+ const result = rule.function(expression, rule, { max: 100 });
121
+
122
+ if (result.isTriggered) {
123
+ console.log(rule.name, result.nodeToHighlight.getText());
124
+ }
125
+ }
126
+ ```
127
+
128
+ Call `convertToPrismaExpression` only after recognition. For general rule dispatch, use each rule's
129
+ `astType`, `methods`, and `requireSchema` metadata. Match `callExpression` rules to call nodes and
130
+ `newExpression` rules to construction nodes.
131
+
132
+ Rules return `{ isTriggered: false }` or `{ isTriggered: true, nodeToHighlight }`. The host turns the
133
+ reported TypeScript node into its own diagnostic. The core does not supply diagnostic messages or
134
+ autofixes.
135
+
136
+ Pass the complete option object as the third argument to a rule function, or `{}` for a rule without
137
+ options. The core provides no option defaults or runtime validation. Schema-dependent rules accept
138
+ Prisma's Data Model Meta Format (DMMF) document as the fourth argument and return no report when it is
139
+ absent. Schema discovery and loading belong to the host integration.
140
+
141
+ ## Rules
142
+
143
+ Each page documents the shipped behavior, reported and accepted examples, options, schema
144
+ requirements, and known limits.
145
+
146
+ | Rule | Purpose | Requires schema |
147
+ | ------------------------------------------------------------------------------- | ---------------------------------------------------------------- | --------------- |
148
+ | [limit-relation-loading](documentation/limit-relation-loading.md) | Require a separate `take` for each loaded list relation. | Yes |
149
+ | [max-take](documentation/max-take.md) | Require `take` and enforce its upper bound on `findMany`. | No |
150
+ | [no-deep-offset-pagination](documentation/no-deep-offset-pagination.md) | Keep `skip` within a configured range. | No |
151
+ | [no-disconnect-in-request-flow](documentation/no-disconnect-in-request-flow.md) | Restrict `$disconnect` to explicitly allowed files. | No |
152
+ | [no-dynamic-raw-query](documentation/no-dynamic-raw-query.md) | Report interpolated templates passed to unsafe raw SQL methods. | No |
153
+ | [no-floating-prisma-promise](documentation/no-floating-prisma-promise.md) | Report Prisma promises without a recognized await or return. | No |
154
+ | [no-prisma-client-in-function](documentation/no-prisma-client-in-function.md) | Restrict client creation inside functions and methods. | No |
155
+ | [no-query-in-loop](documentation/no-query-in-loop.md) | Report Prisma calls inside loops and selected array callbacks. | No |
156
+ | [no-root-client-in-transaction](documentation/no-root-client-in-transaction.md) | Require the transaction client inside interactive transactions. | No |
157
+ | [no-unindexed-filter](documentation/no-unindexed-filter.md) | Check top-level filter keys against schema indexes. | Yes |
158
+ | [no-unsafe-prisma-raw](documentation/no-unsafe-prisma-raw.md) | Restrict `Prisma.raw` arguments to resolved strings. | No |
159
+ | [no-unsafe-raw-sql](documentation/no-unsafe-raw-sql.md) | Report all calls to unsafe raw SQL methods. | No |
160
+ | [require-where-delete-many](documentation/require-where-delete-many.md) | Require a nonempty `where` for `deleteMany`. | No |
161
+ | [require-where-update-many](documentation/require-where-update-many.md) | Require a nonempty `where` for `updateMany`. | No |
162
+ | [unstable-pagination](documentation/unstable-pagination.md) | Require a unique ordering when `take` and `orderBy` are present. | Yes |
163
+ | [warn-cascade-delete](documentation/warn-cascade-delete.md) | Warn when deleting a model with incoming cascade relations. | Yes |
164
+
165
+ Examples in the rule pages are TypeScript fragments. They assume a configured `prisma` client,
166
+ generated Prisma exports where used, and models with the shown fields. `clientOptions` represents
167
+ the application's client construction options. “Not reported” refers only to that page's rule;
168
+ another rule or Prisma's types may still reject the code.
169
+
170
+ ### Adding or changing a rule
171
+
172
+ 1. Implement the behavior in `src/rules/list/<rule-name>.ts`. Keep parsing helpers in `src/ast` and
173
+ shared rule helpers in `src/rules/utils`.
174
+ 2. Add the rule's option contract in `src/rules/types/rules-options.types.ts`, including an entry for
175
+ rules with no options.
176
+ 3. Register the rule in `src/rules/rules-list.ts` with its name, AST type, methods, and schema
177
+ requirement. Add shared method names to `src/constants` if needed.
178
+ 4. Add focused tests in `src/tests/unit/rules`. Cover reports, accepted cases, method filtering,
179
+ options, and the highlighted node. For parser changes, add or update a fixture and its tests in
180
+ `src/tests/ast/v7`.
181
+ 5. Write or update `documentation/<rule-name>.md` and this rule table. Describe current behavior and
182
+ limits, and link the implementation and tests.
183
+ 6. Coordinate the plugin changes: messages, option schemas and defaults in `src/rules/rules.map.ts`,
184
+ preset entries in `src/config/create-configs.ts`, and integration tests in the plugin repository.
185
+
186
+ ## Core behavior
187
+
188
+ Method groups come from
189
+ [`prisma-methods.constants.ts`](src/constants/prisma-methods.constants.ts):
190
+
191
+ - **CRUD methods:** `create`, `createMany`, `createManyAndReturn`, `findUnique`, `findUniqueOrThrow`,
192
+ `findFirst`, `findFirstOrThrow`, `findMany`, `update`, `updateMany`, `updateManyAndReturn`, `upsert`,
193
+ `delete`, and `deleteMany`.
194
+ - **Read methods:** `findUnique`, `findUniqueOrThrow`, `findFirst`, `findFirstOrThrow`, and `findMany`.
195
+ - **All registered Prisma methods:** CRUD methods plus `count`, `aggregate`, `groupBy`, `$queryRaw`,
196
+ `$executeRaw`, `$queryRawUnsafe`, `$executeRawUnsafe`, `$transaction`, `raw`, `sql`, `join`, `empty`,
197
+ `$db`, `$connect`, and `$disconnect`.
198
+
199
+ Recognition depends on declarations from generated Prisma files. The current detection checks for
200
+ `.prisma/client` or `generated/prisma` in declaration paths. Model resolution also depends on generated
201
+ files under a `prisma/models` directory. Custom output layouts can therefore affect detection.
202
+
203
+ The core handles TypeScript call and construction expressions. Tagged template expressions are not
204
+ recognized directly. Parsed values can come from syntax, declarations, or types, and can remain
205
+ unknown. Individual rules decide how to handle those values; analysis does not prove runtime query
206
+ safety or database performance.
207
+
208
+ ## License
209
+
210
+ [MIT](LICENSE).
@@ -0,0 +1,8 @@
1
+ import type * as TS from 'typescript';
2
+ export declare function createAstParser(ts: typeof TS): {
3
+ findVariableStatements: (sourceFile: TS.SourceFile) => TS.VariableStatement[];
4
+ findCallExpressions: (sourceFile: TS.SourceFile) => TS.CallExpression[];
5
+ findNewExpressions: (sourceFile: TS.SourceFile) => TS.NewExpression[];
6
+ };
7
+ export type AstParser = ReturnType<typeof createAstParser>;
8
+ //# sourceMappingURL=create-ast-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-ast-parser.d.ts","sourceRoot":"","sources":["../../../src/ast/parser/create-ast-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAEtC,wBAAgB,eAAe,CAAC,EAAE,EAAE,OAAO,EAAE;yCACC,EAAE,CAAC,UAAU,KAAG,EAAE,CAAC,iBAAiB,EAAE;sCAgBzC,EAAE,CAAC,UAAU,KAAG,EAAE,CAAC,cAAc,EAAE;qCAgBpC,EAAE,CAAC,UAAU,KAAG,EAAE,CAAC,aAAa,EAAE;EAqB3E;AAED,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC"}
@@ -0,0 +1,41 @@
1
+ export function createAstParser(ts) {
2
+ function findVariableStatements(sourceFile) {
3
+ const statements = [];
4
+ function visit(node) {
5
+ if (ts.isVariableStatement(node)) {
6
+ statements.push(node);
7
+ }
8
+ ts.forEachChild(node, visit);
9
+ }
10
+ visit(sourceFile);
11
+ return statements;
12
+ }
13
+ function findCallExpressions(sourceFile) {
14
+ const calls = [];
15
+ function visit(node) {
16
+ if (ts.isCallExpression(node)) {
17
+ calls.push(node);
18
+ }
19
+ ts.forEachChild(node, visit);
20
+ }
21
+ visit(sourceFile);
22
+ return calls;
23
+ }
24
+ function findNewExpressions(sourceFile) {
25
+ const calls = [];
26
+ function visit(node) {
27
+ if (ts.isNewExpression(node)) {
28
+ calls.push(node);
29
+ }
30
+ ts.forEachChild(node, visit);
31
+ }
32
+ visit(sourceFile);
33
+ return calls;
34
+ }
35
+ return {
36
+ findVariableStatements,
37
+ findCallExpressions,
38
+ findNewExpressions,
39
+ };
40
+ }
41
+ //# sourceMappingURL=create-ast-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-ast-parser.js","sourceRoot":"","sources":["../../../src/ast/parser/create-ast-parser.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,eAAe,CAAC,EAAa;IAC3C,SAAS,sBAAsB,CAAC,UAAyB;QACvD,MAAM,UAAU,GAA2B,EAAE,CAAC;QAE9C,SAAS,KAAK,CAAC,IAAa;YAC1B,IAAI,EAAE,CAAC,mBAAmB,CAAC,IAAI,CAAC,EAAE,CAAC;gBACjC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACxB,CAAC;YAED,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC/B,CAAC;QAED,KAAK,CAAC,UAAU,CAAC,CAAC;QAElB,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,SAAS,mBAAmB,CAAC,UAAyB;QACpD,MAAM,KAAK,GAAwB,EAAE,CAAC;QAEtC,SAAS,KAAK,CAAC,IAAa;YAC1B,IAAI,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC9B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnB,CAAC;YAED,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC/B,CAAC;QAED,KAAK,CAAC,UAAU,CAAC,CAAC;QAElB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,SAAS,kBAAkB,CAAC,UAAyB;QACnD,MAAM,KAAK,GAAuB,EAAE,CAAC;QAErC,SAAS,KAAK,CAAC,IAAa;YAC1B,IAAI,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC7B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnB,CAAC;YAED,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC/B,CAAC;QAED,KAAK,CAAC,UAAU,CAAC,CAAC;QAElB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO;QACL,sBAAsB;QACtB,mBAAmB;QACnB,kBAAkB;KACnB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type * as TS from 'typescript';
2
+ import { PrismaExpression, PrismaNodeExpression } from '../../types/prisma.types.js';
3
+ import { AstUtils } from '../utils/create-ast-utils.js';
4
+ export declare function convertToPrismaExpression(node: PrismaNodeExpression, program: TS.Program, { node: nodeUtils, prisma: prismaUtils }: AstUtils): PrismaExpression;
5
+ //# sourceMappingURL=convert-to-prisma-expression.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convert-to-prisma-expression.d.ts","sourceRoot":"","sources":["../../../src/ast/prisma/convert-to-prisma-expression.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAErF,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAGxD,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,oBAAoB,EAC1B,OAAO,EAAE,EAAE,CAAC,OAAO,EACnB,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,QAAQ,GACjD,gBAAgB,CA+DlB"}
@@ -0,0 +1,58 @@
1
+ import { defineMethod } from './utils/define-method.js';
2
+ export function convertToPrismaExpression(node, program, { node: nodeUtils, prisma: prismaUtils }) {
3
+ const method = defineMethod(node, nodeUtils);
4
+ const { line: startLine, character: startCharacter } = node
5
+ .getSourceFile()
6
+ .getLineAndCharacterOfPosition(node.getStart());
7
+ const { line: endLine, character: endCharacter } = node
8
+ .getSourceFile()
9
+ .getLineAndCharacterOfPosition(node.getEnd());
10
+ const nodeLength = node.getWidth();
11
+ const filename = node.getSourceFile().fileName;
12
+ const args = node.arguments ?? [];
13
+ const checker = program.getTypeChecker();
14
+ const isFloatingPrismaPromise = prismaUtils.isFloatingPrismaPromise(node, node.parent, checker);
15
+ const isExpressionInsideTransaction = prismaUtils.isInsidePrismaTransaction(node);
16
+ const transactionType = prismaUtils.resolveTransactionType(node);
17
+ const clientType = prismaUtils.resolveClientType(node, checker);
18
+ const model = prismaUtils.resolveModelName(node, checker);
19
+ const isExpressionInsideLoop = nodeUtils.isInsideLoop(node);
20
+ const isExpressionInsideFunction = nodeUtils.isInsideFunction(node);
21
+ const isExpressionInsideClassMethod = nodeUtils.isInsideClassMethod(node);
22
+ const isExpressionInsideAwaitExpression = nodeUtils.isInsideAwaitExpression(node);
23
+ const parentFunctionName = nodeUtils.getParentFunctionName(node);
24
+ const parentMethodName = nodeUtils.getParentMethodName(node);
25
+ return {
26
+ node: node,
27
+ range: {
28
+ start: {
29
+ line: startLine,
30
+ character: startCharacter,
31
+ },
32
+ end: {
33
+ line: endLine,
34
+ character: endCharacter,
35
+ },
36
+ length: nodeLength,
37
+ },
38
+ filename,
39
+ expressionContext: {
40
+ isExpressionInsideLoop,
41
+ isExpressionInsideFunction,
42
+ isExpressionInsideClassMethod,
43
+ isExpressionInsideAwaitExpression,
44
+ parentFunctionName,
45
+ parentMethodName,
46
+ },
47
+ prismaContext: {
48
+ isFloatingPrismaPromise,
49
+ isExpressionInsideTransaction,
50
+ transactionType,
51
+ clientType,
52
+ model,
53
+ },
54
+ method,
55
+ args: args.map((argument) => nodeUtils.parseValue(argument, checker)),
56
+ };
57
+ }
58
+ //# sourceMappingURL=convert-to-prisma-expression.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convert-to-prisma-expression.js","sourceRoot":"","sources":["../../../src/ast/prisma/convert-to-prisma-expression.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAExD,MAAM,UAAU,yBAAyB,CACvC,IAA0B,EAC1B,OAAmB,EACnB,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAY;IAElD,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAE7C,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,EAAE,GAAG,IAAI;SACxD,aAAa,EAAE;SACf,6BAA6B,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IAElD,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,IAAI;SACpD,aAAa,EAAE;SACf,6BAA6B,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IAEhD,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;IACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC,QAAQ,CAAC;IAE/C,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC;IAElC,MAAM,OAAO,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAEzC,MAAM,uBAAuB,GAAG,WAAW,CAAC,uBAAuB,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChG,MAAM,6BAA6B,GAAG,WAAW,CAAC,yBAAyB,CAAC,IAAI,CAAC,CAAC;IAClF,MAAM,eAAe,GAAG,WAAW,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC;IACjE,MAAM,UAAU,GAAG,WAAW,CAAC,iBAAiB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAChE,MAAM,KAAK,GAAG,WAAW,CAAC,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAE1D,MAAM,sBAAsB,GAAG,SAAS,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IAC5D,MAAM,0BAA0B,GAAG,SAAS,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACpE,MAAM,6BAA6B,GAAG,SAAS,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAC1E,MAAM,iCAAiC,GAAG,SAAS,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC;IAClF,MAAM,kBAAkB,GAAG,SAAS,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC;IACjE,MAAM,gBAAgB,GAAG,SAAS,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAE7D,OAAO;QACL,IAAI,EAAE,IAAI;QACV,KAAK,EAAE;YACL,KAAK,EAAE;gBACL,IAAI,EAAE,SAAS;gBACf,SAAS,EAAE,cAAc;aAC1B;YACD,GAAG,EAAE;gBACH,IAAI,EAAE,OAAO;gBACb,SAAS,EAAE,YAAY;aACxB;YACD,MAAM,EAAE,UAAU;SACnB;QACD,QAAQ;QACR,iBAAiB,EAAE;YACjB,sBAAsB;YACtB,0BAA0B;YAC1B,6BAA6B;YAC7B,iCAAiC;YACjC,kBAAkB;YAClB,gBAAgB;SACjB;QACD,aAAa,EAAE;YACb,uBAAuB;YACvB,6BAA6B;YAC7B,eAAe;YACf,UAAU;YACV,KAAK;SACN;QACD,MAAM;QACN,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;KACtE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type * as TS from 'typescript';
2
+ import { PrismaNodeExpression } from '../../types/prisma.types.js';
3
+ import { AstUtils } from '../utils/create-ast-utils.js';
4
+ export declare function isPrismaExpression(node: TS.Node, program: TS.Program, { node: nodeUtils, prisma: prismaUtils }: AstUtils): node is PrismaNodeExpression;
5
+ //# sourceMappingURL=is-prisma-expression.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-prisma-expression.d.ts","sourceRoot":"","sources":["../../../src/ast/prisma/is-prisma-expression.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAEnE,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAKxD,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,OAAO,EAAE,EAAE,CAAC,OAAO,EACnB,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,QAAQ,GACjD,IAAI,IAAI,oBAAoB,CAgE9B"}
@@ -0,0 +1,52 @@
1
+ import { removeQuotes } from './utils/remove-quotes.js';
2
+ import { PRISMA_METHODS } from '../../constants/prisma-methods.constants.js';
3
+ export function isPrismaExpression(node, program, { node: nodeUtils, prisma: prismaUtils }) {
4
+ if (nodeUtils.isCallExpression(node)) {
5
+ const isPropertyAccess = nodeUtils.isPropertyAccessExpression(node.expression);
6
+ const isElementAccess = nodeUtils.isElementAccessExpression(node.expression);
7
+ if (isPropertyAccess) {
8
+ const methodNode = node.expression.name;
9
+ const method = methodNode.text;
10
+ if (!PRISMA_METHODS.has(method)) {
11
+ return false;
12
+ }
13
+ const checker = program.getTypeChecker();
14
+ const symbol = checker.getSymbolAtLocation(methodNode);
15
+ const declarations = symbol?.getDeclarations() ?? [];
16
+ const isGeneratedPrismaMethod = prismaUtils.isGeneratedPrismaFile(declarations);
17
+ if (isGeneratedPrismaMethod)
18
+ return true;
19
+ }
20
+ if (isElementAccess) {
21
+ const methodNode = node.expression.argumentExpression;
22
+ const method = removeQuotes(methodNode.getText());
23
+ if (!PRISMA_METHODS.has(method)) {
24
+ return false;
25
+ }
26
+ const checker = program.getTypeChecker();
27
+ const symbol = checker.getSymbolAtLocation(methodNode);
28
+ const declarations = symbol?.getDeclarations() ?? [];
29
+ const isGeneratedPrismaMethod = prismaUtils.isGeneratedPrismaFile(declarations);
30
+ if (isGeneratedPrismaMethod)
31
+ return true;
32
+ }
33
+ }
34
+ if (nodeUtils.isNewExpression(node)) {
35
+ const checker = program.getTypeChecker();
36
+ const symbolLocation = nodeUtils.isPropertyAccessExpression(node.expression)
37
+ ? node.expression.name
38
+ : node.expression;
39
+ const symbol = checker.getSymbolAtLocation(symbolLocation);
40
+ if (!symbol)
41
+ return false;
42
+ const resolvedSymbol = nodeUtils.resolveAliasedSymbol(symbol, checker);
43
+ if (resolvedSymbol.getName() !== 'PrismaClient')
44
+ return false;
45
+ const declarations = resolvedSymbol.getDeclarations() ?? [];
46
+ const isGeneratedPrismaClient = prismaUtils.isGeneratedPrismaFile(declarations);
47
+ if (isGeneratedPrismaClient)
48
+ return true;
49
+ }
50
+ return false;
51
+ }
52
+ //# sourceMappingURL=is-prisma-expression.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-prisma-expression.js","sourceRoot":"","sources":["../../../src/ast/prisma/is-prisma-expression.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { PrismaNodeExpression } from '../../../types/prisma.types.js';
2
+ import { AstUtils } from '../../utils/create-ast-utils.js';
3
+ export declare function defineMethod(node: PrismaNodeExpression, nodeUtils: AstUtils['node']): string;
4
+ //# sourceMappingURL=define-method.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-method.d.ts","sourceRoot":"","sources":["../../../../src/ast/prisma/utils/define-method.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAEtE,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAkB3D,wBAAgB,YAAY,CAAC,IAAI,EAAE,oBAAoB,EAAE,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,UAUnF"}
@@ -0,0 +1,18 @@
1
+ import { removeQuotes } from './remove-quotes.js';
2
+ function isPropertyAccess(expression, nodeUtils) {
3
+ return nodeUtils.isPropertyAccessExpression(expression);
4
+ }
5
+ function isElementAccess(expression, nodeUtils) {
6
+ return nodeUtils.isElementAccessExpression(expression);
7
+ }
8
+ export function defineMethod(node, nodeUtils) {
9
+ const isNewExpression = nodeUtils.isNewExpression(node);
10
+ if (isNewExpression)
11
+ return 'PrismaClient';
12
+ if (isPropertyAccess(node.expression, nodeUtils))
13
+ return node.expression.name.text;
14
+ if (isElementAccess(node.expression, nodeUtils))
15
+ return removeQuotes(node.expression.argumentExpression.getText());
16
+ return 'unknown';
17
+ }
18
+ //# sourceMappingURL=define-method.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-method.js","sourceRoot":"","sources":["../../../../src/ast/prisma/utils/define-method.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,SAAS,gBAAgB,CACvB,UAAoE,EACpE,SAA2B;IAE3B,OAAO,SAAS,CAAC,0BAA0B,CAAC,UAAU,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,eAAe,CACtB,UAAoE,EACpE,SAA2B;IAE3B,OAAO,SAAS,CAAC,yBAAyB,CAAC,UAAU,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAA0B,EAAE,SAA2B;IAClF,MAAM,eAAe,GAAG,SAAS,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IAExD,IAAI,eAAe;QAAE,OAAO,cAAc,CAAC;IAE3C,IAAI,gBAAgB,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;IACnF,IAAI,eAAe,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC;QAC7C,OAAO,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,kBAAkB,CAAC,OAAO,EAAE,CAAC,CAAC;IAEpE,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function removeQuotes(value: string): string;
2
+ //# sourceMappingURL=remove-quotes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remove-quotes.d.ts","sourceRoot":"","sources":["../../../../src/ast/prisma/utils/remove-quotes.ts"],"names":[],"mappings":"AAAA,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAUlD"}
@@ -0,0 +1,9 @@
1
+ export function removeQuotes(value) {
2
+ if ((value.startsWith('"') && value.endsWith('"')) ||
3
+ (value.startsWith("'") && value.endsWith("'")) ||
4
+ (value.startsWith('`') && value.endsWith('`'))) {
5
+ return value.slice(1, -1);
6
+ }
7
+ return value;
8
+ }
9
+ //# sourceMappingURL=remove-quotes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remove-quotes.js","sourceRoot":"","sources":["../../../../src/ast/prisma/utils/remove-quotes.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,IACE,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC9C,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC9C,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAC9C,CAAC;QACD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,30 @@
1
+ import type * as TS from 'typescript';
2
+ export declare function createAstUtils(ts: typeof TS, checker: TS.TypeChecker): {
3
+ node: {
4
+ isCallExpression: (node: TS.Node) => node is TS.CallExpression;
5
+ isPropertyAccessExpression: (node: TS.Node) => node is TS.PropertyAccessExpression;
6
+ isElementAccessExpression: (node: TS.Node) => node is TS.ElementAccessExpression;
7
+ isNewExpression: (node: TS.Node) => node is TS.NewExpression;
8
+ getPropertyName: (name: TS.PropertyName) => string;
9
+ resolveAliasedSymbol: (symbol: TS.Symbol, checker: TS.TypeChecker) => TS.Symbol;
10
+ getParentFunctionName: (node: TS.Node) => string | null;
11
+ getParentMethodName: (node: TS.Node) => string | null;
12
+ isInsideLoop: (node: TS.Node) => boolean;
13
+ isInsideFunction: (node: TS.Node) => boolean;
14
+ isInsideClassMethod: (node: TS.Node) => boolean;
15
+ isInsideAwaitExpression: (node: TS.Node) => boolean;
16
+ parseArgument: (node: TS.CallExpression | TS.NewExpression, index?: number) => import("../../index.js").ParsedValue | undefined;
17
+ parseObject: (node: TS.ObjectLiteralExpression) => import("../../index.js").ParsedValue<import("../../types/ast.types.js").AstObject>;
18
+ parseValue: (node: TS.Expression, checker: TS.TypeChecker) => import("../../index.js").ParsedValue;
19
+ };
20
+ prisma: {
21
+ resolveTransactionType: (node: TS.Node) => import("../../types/prisma.types.js").TransactionType | null;
22
+ resolveClientType: (node: TS.Node, checker: TS.TypeChecker) => import("../../types/prisma.types.js").ClientType;
23
+ isGeneratedPrismaFile: (declarations: TS.Declaration[]) => boolean;
24
+ isFloatingPrismaPromise: (node: TS.Node, parent: TS.Node, checker: TS.TypeChecker) => boolean;
25
+ isInsidePrismaTransaction: (node: TS.Node) => boolean;
26
+ resolveModelName: (node: import("../../types/prisma.types.js").PrismaNodeExpression, checker: TS.TypeChecker) => string | null;
27
+ };
28
+ };
29
+ export type AstUtils = ReturnType<typeof createAstUtils>;
30
+ //# sourceMappingURL=create-ast-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-ast-utils.d.ts","sourceRoot":"","sources":["../../../src/ast/utils/create-ast-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAKtC,wBAAgB,cAAc,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,WAAW;IAEjE,IAAI;;;;;;;;;;;;;;;;;IACJ,MAAM;;;;;;;;EAET;AAED,MAAM,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { createNodeUtils } from './create-node-utils.js';
2
+ import { createPrismaUtils } from './create-prisma-utils.js';
3
+ export function createAstUtils(ts, checker) {
4
+ return {
5
+ node: createNodeUtils(ts, checker),
6
+ prisma: createPrismaUtils(ts),
7
+ };
8
+ }
9
+ //# sourceMappingURL=create-ast-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-ast-utils.js","sourceRoot":"","sources":["../../../src/ast/utils/create-ast-utils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,MAAM,UAAU,cAAc,CAAC,EAAa,EAAE,OAAuB;IACnE,OAAO;QACL,IAAI,EAAE,eAAe,CAAC,EAAE,EAAE,OAAO,CAAC;QAClC,MAAM,EAAE,iBAAiB,CAAC,EAAE,CAAC;KAC9B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type * as TS from 'typescript';
2
+ import { AstObject, ParsedValue } from '../../types/ast.types.js';
3
+ export declare function createNodeUtils(ts: typeof TS, checker: TS.TypeChecker): {
4
+ isCallExpression: (node: TS.Node) => node is TS.CallExpression;
5
+ isPropertyAccessExpression: (node: TS.Node) => node is TS.PropertyAccessExpression;
6
+ isElementAccessExpression: (node: TS.Node) => node is TS.ElementAccessExpression;
7
+ isNewExpression: (node: TS.Node) => node is TS.NewExpression;
8
+ getPropertyName: (name: TS.PropertyName) => string;
9
+ resolveAliasedSymbol: (symbol: TS.Symbol, checker: TS.TypeChecker) => TS.Symbol;
10
+ getParentFunctionName: (node: TS.Node) => string | null;
11
+ getParentMethodName: (node: TS.Node) => string | null;
12
+ isInsideLoop: (node: TS.Node) => boolean;
13
+ isInsideFunction: (node: TS.Node) => boolean;
14
+ isInsideClassMethod: (node: TS.Node) => boolean;
15
+ isInsideAwaitExpression: (node: TS.Node) => boolean;
16
+ parseArgument: (node: TS.CallExpression | TS.NewExpression, index?: number) => ParsedValue | undefined;
17
+ parseObject: (node: TS.ObjectLiteralExpression) => ParsedValue<AstObject>;
18
+ parseValue: (node: TS.Expression, checker: TS.TypeChecker) => ParsedValue;
19
+ };
20
+ export type NodeUtils = ReturnType<typeof createNodeUtils>;
21
+ //# sourceMappingURL=create-node-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-node-utils.d.ts","sourceRoot":"","sources":["../../../src/ast/utils/create-node-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,EAAE,SAAS,EAAgB,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAIhF,wBAAgB,eAAe,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,WAAW;6BAGpC,EAAE,CAAC,IAAI;uCAIG,EAAE,CAAC,IAAI;sCAIR,EAAE,CAAC,IAAI;4BAIjB,EAAE,CAAC,IAAI;4BAIP,EAAE,CAAC,YAAY,KAAG,MAAM;mCAQjB,EAAE,CAAC,MAAM,WAAW,EAAE,CAAC,WAAW,KAAG,EAAE,CAAC,MAAM;kCAI/C,EAAE,CAAC,IAAI,KAAG,MAAM,GAAG,IAAI;gCAczB,EAAE,CAAC,IAAI,KAAG,MAAM,GAAG,IAAI;yBAc9B,EAAE,CAAC,IAAI,KAAG,OAAO;6BAmCb,EAAE,CAAC,IAAI,KAAG,OAAO;gCAiBd,EAAE,CAAC,IAAI,KAAG,OAAO;oCAiBb,EAAE,CAAC,IAAI,KAAG,OAAO;0BAehD,EAAE,CAAC,cAAc,GAAG,EAAE,CAAC,aAAa,qBAEzC,WAAW,GAAG,SAAS;wBAUC,EAAE,CAAC,uBAAuB,KAAG,WAAW,CAAC,SAAS,CAAC;uBAwKpD,EAAE,CAAC,UAAU,WAAW,EAAE,CAAC,WAAW,KAAG,WAAW;EAoG/E;AAED,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC"}