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 CHANGED
@@ -42,24 +42,23 @@ export default [
42
42
  overrides: {
43
43
  types: {
44
44
  // Map PostgreSQL types to Slonik token types
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",
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: "sql.+(type\\(*\\)|typeAlias\\(*\\)|unsafe)",
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: "DateSqlToken",
135
- timestamp: "TimestampSqlToken",
133
+ date: 'DateSqlToken',
134
+ timestamp: 'TimestampSqlToken',
136
135
  timestamptz: "TimestampSqlToken",
137
- interval: "IntervalSqlToken",
136
+ interval: 'IntervalSqlToken',
138
137
 
139
138
  // JSON types
140
- json: "JsonSqlToken",
141
- jsonb: "JsonBinarySqlToken",
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: "DateSqlToken",
213
- timestamp: "TimestampSqlToken",
214
- json: "JsonSqlToken",
215
- jsonb: "JsonBinarySqlToken",
216
- uuid: "UuidSqlToken",
217
- "int4[]": 'ArraySqlToken<"int4">',
218
- "text[]": 'ArraySqlToken<"text">',
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: "sql.+(type\\(*\\)|typeAlias\\(*\\)|unsafe)",
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) {