eslint-plugin-slonik 1.6.1 → 1.7.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.
- package/README.md +37 -28
- package/dist/index.cjs +3 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -9
- package/dist/index.d.mts +1 -9
- package/dist/index.d.ts +1 -9
- package/dist/index.mjs +3 -9
- package/dist/index.mjs.map +1 -1
- package/dist/shared/{eslint-plugin-slonik.uSZXmGoY.d.cts → eslint-plugin-slonik.ZtKj5lnb.d.cts} +0 -14
- package/dist/shared/{eslint-plugin-slonik.uSZXmGoY.d.mts → eslint-plugin-slonik.ZtKj5lnb.d.mts} +0 -14
- package/dist/shared/{eslint-plugin-slonik.uSZXmGoY.d.ts → eslint-plugin-slonik.ZtKj5lnb.d.ts} +0 -14
- package/dist/workers/check-sql.worker.cjs +133 -37
- package/dist/workers/check-sql.worker.cjs.map +1 -1
- package/dist/workers/check-sql.worker.d.cts +11 -4
- package/dist/workers/check-sql.worker.d.mts +11 -4
- package/dist/workers/check-sql.worker.d.ts +11 -4
- package/dist/workers/check-sql.worker.mjs +132 -37
- package/dist/workers/check-sql.worker.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -42,24 +42,23 @@ export default [
|
|
|
42
42
|
overrides: {
|
|
43
43
|
types: {
|
|
44
44
|
// Map PostgreSQL types to Slonik token types
|
|
45
|
-
date:
|
|
46
|
-
timestamp:
|
|
47
|
-
interval:
|
|
48
|
-
json:
|
|
49
|
-
jsonb:
|
|
50
|
-
uuid:
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
45
|
+
date: 'DateSqlToken',
|
|
46
|
+
timestamp: 'TimestampSqlToken',
|
|
47
|
+
interval: 'IntervalSqlToken',
|
|
48
|
+
json: 'JsonSqlToken',
|
|
49
|
+
jsonb: 'JsonBinarySqlToken',
|
|
50
|
+
uuid: 'UuidSqlToken',
|
|
51
|
+
'int4[]': 'ArraySqlToken<"int4">',
|
|
52
|
+
'text[]': 'ArraySqlToken<"text">',
|
|
53
|
+
'uuid[]': 'ArraySqlToken<"uuid">',
|
|
54
|
+
'numeric[]': 'ArraySqlToken<"numeric">',
|
|
55
|
+
'real[]': 'VectorSqlToken',
|
|
56
56
|
},
|
|
57
57
|
},
|
|
58
58
|
targets: [
|
|
59
59
|
{
|
|
60
60
|
// Match Slonik's typed query methods
|
|
61
|
-
tag:
|
|
62
|
-
skipTypeAnnotations: true,
|
|
61
|
+
tag: 'sql.+(type\\(*\\)|typeAlias\\(*\\)|unsafe)',
|
|
63
62
|
},
|
|
64
63
|
],
|
|
65
64
|
}),
|
|
@@ -131,14 +130,14 @@ When using Slonik, you'll want to map PostgreSQL types to Slonik's token types:
|
|
|
131
130
|
overrides: {
|
|
132
131
|
types: {
|
|
133
132
|
// Date/Time types
|
|
134
|
-
date:
|
|
135
|
-
timestamp:
|
|
133
|
+
date: 'DateSqlToken',
|
|
134
|
+
timestamp: 'TimestampSqlToken',
|
|
136
135
|
timestamptz: "TimestampSqlToken",
|
|
137
|
-
interval:
|
|
136
|
+
interval: 'IntervalSqlToken',
|
|
138
137
|
|
|
139
138
|
// JSON types
|
|
140
|
-
json:
|
|
141
|
-
jsonb:
|
|
139
|
+
json: 'JsonSqlToken',
|
|
140
|
+
jsonb: 'JsonBinarySqlToken',
|
|
142
141
|
|
|
143
142
|
// UUID
|
|
144
143
|
uuid: "UuidSqlToken",
|
|
@@ -167,7 +166,6 @@ targets: [
|
|
|
167
166
|
{
|
|
168
167
|
// Matches: sql.type(...)``, sql.typeAlias(...)``, sql.unsafe``
|
|
169
168
|
tag: "sql.+(type\\(*\\)|typeAlias\\(*\\)|unsafe)",
|
|
170
|
-
skipTypeAnnotations: true,
|
|
171
169
|
},
|
|
172
170
|
]
|
|
173
171
|
```
|
|
@@ -209,19 +207,18 @@ export default tseslint.config(
|
|
|
209
207
|
databaseUrl: process.env.DATABASE_URL,
|
|
210
208
|
overrides: {
|
|
211
209
|
types: {
|
|
212
|
-
date:
|
|
213
|
-
timestamp:
|
|
214
|
-
json:
|
|
215
|
-
jsonb:
|
|
216
|
-
uuid:
|
|
217
|
-
|
|
218
|
-
|
|
210
|
+
date: 'DateSqlToken',
|
|
211
|
+
timestamp: 'TimestampSqlToken',
|
|
212
|
+
json: 'JsonSqlToken',
|
|
213
|
+
jsonb: 'JsonBinarySqlToken',
|
|
214
|
+
uuid: 'UuidSqlToken',
|
|
215
|
+
'int4[]': 'ArraySqlToken<"int4">',
|
|
216
|
+
'text[]': 'ArraySqlToken<"text">',
|
|
219
217
|
},
|
|
220
218
|
},
|
|
221
219
|
targets: [
|
|
222
220
|
{
|
|
223
|
-
tag:
|
|
224
|
-
skipTypeAnnotations: true,
|
|
221
|
+
tag: 'sql.+(type\\(*\\)|typeAlias\\(*\\)|unsafe)',
|
|
225
222
|
},
|
|
226
223
|
],
|
|
227
224
|
})
|
|
@@ -273,6 +270,18 @@ This plugin is specifically designed for Slonik and includes:
|
|
|
273
270
|
4. **Identifier support** — Converts `sql.identifier()` to quoted identifiers
|
|
274
271
|
5. **Graceful degradation** — Skips validation for runtime-dependent constructs instead of erroring
|
|
275
272
|
|
|
273
|
+
## How It Works
|
|
274
|
+
|
|
275
|
+
ESLint rules must be synchronous, but SQL validation requires async operations like database connections. This plugin solves this using [`synckit`](https://github.com/un-ts/synckit), which enables synchronous calls to async worker threads.
|
|
276
|
+
|
|
277
|
+
The architecture:
|
|
278
|
+
|
|
279
|
+
1. **Worker Thread** — Runs all async operations (database connections, migrations, type generation) in a separate thread
|
|
280
|
+
2. **Synchronous Bridge** — Uses `synckit` to block the main thread until the worker completes, making async operations appear synchronous to ESLint
|
|
281
|
+
3. **Connection Pooling** — Reuses database connections across lint runs for performance
|
|
282
|
+
|
|
283
|
+
Under the hood, `synckit` uses Node.js Worker Threads with `Atomics.wait()` to block the main thread until the worker signals completion via `Atomics.notify()`.
|
|
284
|
+
|
|
276
285
|
## Development
|
|
277
286
|
|
|
278
287
|
### Prerequisites
|
package/dist/index.cjs
CHANGED
|
@@ -1108,11 +1108,7 @@ const zBaseTarget = z__default.object({
|
|
|
1108
1108
|
* - `"pascal"` - `user_id` → `UserId`
|
|
1109
1109
|
* - `"screaming snake"` - `user_id` → `USER_ID`
|
|
1110
1110
|
*/
|
|
1111
|
-
fieldTransform: z__default.enum(["snake", "pascal", "camel", "screaming snake"]).optional()
|
|
1112
|
-
/**
|
|
1113
|
-
* Whether or not to skip type annotation.
|
|
1114
|
-
*/
|
|
1115
|
-
skipTypeAnnotations: z__default.boolean().optional()
|
|
1111
|
+
fieldTransform: z__default.enum(["snake", "pascal", "camel", "screaming snake"]).optional()
|
|
1116
1112
|
});
|
|
1117
1113
|
const zWrapperTarget = z__default.object({ wrapper: zStringOrRegex, maxDepth: z__default.number().optional() }).merge(zBaseTarget);
|
|
1118
1114
|
const zTagTarget = z__default.object({ tag: zStringOrRegex }).merge(zBaseTarget);
|
|
@@ -1309,16 +1305,14 @@ function reportCheck(params) {
|
|
|
1309
1305
|
If you believe this query should be supported, please open an issue at https://github.com/gajus/eslint-plugin-slonik/issues`
|
|
1310
1306
|
);
|
|
1311
1307
|
return;
|
|
1308
|
+
}).with({ _tag: "ConnectionFailedError" }, () => {
|
|
1309
|
+
return;
|
|
1312
1310
|
}).exhaustive();
|
|
1313
1311
|
},
|
|
1314
1312
|
({ result, checker, parser }) => {
|
|
1315
1313
|
if (result === null) {
|
|
1316
1314
|
return;
|
|
1317
1315
|
}
|
|
1318
|
-
const shouldSkipTypeAnnotations = target.skipTypeAnnotations === true;
|
|
1319
|
-
if (shouldSkipTypeAnnotations) {
|
|
1320
|
-
return;
|
|
1321
|
-
}
|
|
1322
1316
|
const isMissingTypeAnnotations = typeParameter === void 0;
|
|
1323
1317
|
if (isMissingTypeAnnotations) {
|
|
1324
1318
|
if (result.output === null) {
|