@totto2727/oxlint 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.
package/dist/index.js ADDED
@@ -0,0 +1,1613 @@
1
+ import { n as effectRuleNames, r as typescriptRuleNames, t as compatibilityRuleNames } from "./rule-groups-jUlABfyW.js";
2
+ import { Predicate, Schema, String } from "effect";
3
+ import * as fs from "node:fs";
4
+ import * as path from "node:path";
5
+ import ts from "typescript-api";
6
+ //#region src/helpers.ts
7
+ const Reportable = Schema.Struct({ range: Schema.mutable(Schema.Tuple([Schema.Number, Schema.Number])) });
8
+ const { hasProperty } = Predicate;
9
+ const isReportable = Schema.is(Reportable);
10
+ const isEqualityOperator = (op) => op === "==" || op === "!=" || op === "===" || op === "!==";
11
+ const getLiteralNumber = (node) => {
12
+ if (Predicate.isObject(node) && node["type"] === "Literal" && Predicate.isNumber(node["value"])) return node["value"];
13
+ return null;
14
+ };
15
+ const isSchemaMethodCall = (node, methodName) => {
16
+ if (Predicate.isObject(node) && node["type"] === "CallExpression" && Predicate.isObject(node["callee"]) && node["callee"]["type"] === "MemberExpression" && !Predicate.isTruthy(node["callee"]["computed"]) && Predicate.isObject(node["callee"]["object"]) && node["callee"]["object"]["type"] === "Identifier" && node["callee"]["object"]["name"] === "Schema" && Predicate.isObject(node["callee"]["property"]) && node["callee"]["property"]["type"] === "Identifier" && node["callee"]["property"]["name"] === methodName) return true;
17
+ return false;
18
+ };
19
+ const getImportSource = (node) => {
20
+ if (Predicate.isObject(node) && hasProperty(node, "source") && Predicate.isObject(node["source"]) && hasProperty(node["source"], "value") && Predicate.isString(node["source"]["value"])) return node["source"]["value"];
21
+ return null;
22
+ };
23
+ //#endregion
24
+ //#region src/rules/force-ts-extension.ts
25
+ /** Bare specifiers and absolute paths are outside this rule family's scope. */
26
+ const matchImportPath = (value) => {
27
+ const start = /^(\.+|#(?!#)[^/?#]*)(?=\/)/u.exec(value)?.[1];
28
+ if (start === void 0) return null;
29
+ const remainder = value.slice(start.length);
30
+ const suffixIndex = remainder.search(/[?#]/u);
31
+ const pathname = suffixIndex === -1 ? remainder : remainder.slice(0, suffixIndex);
32
+ const suffix = suffixIndex === -1 ? "" : remainder.slice(suffixIndex);
33
+ const basename = pathname.slice(pathname.lastIndexOf("/") + 1);
34
+ const dot = basename.lastIndexOf(".");
35
+ return {
36
+ start,
37
+ path: pathname,
38
+ suffix,
39
+ extension: dot > 0 ? basename.slice(dot) : "",
40
+ directory: basename === "" || basename === "." || basename === ".."
41
+ };
42
+ };
43
+ const importExtensionSchema = [{
44
+ additionalProperties: false,
45
+ properties: { mode: {
46
+ enum: ["js", "ts"],
47
+ type: "string"
48
+ } },
49
+ type: "object"
50
+ }];
51
+ const getImportExtensionMode = (option) => typeof option === "object" && option !== null && "mode" in option && option.mode === "js" ? "js" : "ts";
52
+ const extensionTargets = {
53
+ ".js": {
54
+ js: ".js",
55
+ ts: ".ts"
56
+ },
57
+ ".jsx": {
58
+ js: ".js",
59
+ ts: ".tsx"
60
+ },
61
+ ".ts": {
62
+ js: ".js",
63
+ ts: ".ts"
64
+ },
65
+ ".tsx": {
66
+ js: ".js",
67
+ ts: ".tsx"
68
+ },
69
+ ".mjs": {
70
+ js: ".mjs",
71
+ ts: ".mts"
72
+ },
73
+ ".mts": {
74
+ js: ".mjs",
75
+ ts: ".mts"
76
+ },
77
+ ".cjs": {
78
+ js: ".cjs",
79
+ ts: ".cts"
80
+ },
81
+ ".cts": {
82
+ js: ".cjs",
83
+ ts: ".cts"
84
+ }
85
+ };
86
+ /** Preserve explicit ESM/CommonJS families while normalizing code extensions. */
87
+ const normalizeImportExtension = (value, mode) => {
88
+ const match = matchImportPath(value);
89
+ if (match === null) return null;
90
+ const targets = extensionTargets[match.extension];
91
+ if (targets === void 0) return null;
92
+ const extension = targets[mode];
93
+ if (extension === match.extension) return null;
94
+ return `${match.start}${match.path.slice(0, -match.extension.length)}${extension}${match.suffix}`;
95
+ };
96
+ const quoteLiteral = (value, quote) => {
97
+ const encoded = JSON.stringify(value);
98
+ if (quote === "'") return `'${encoded.slice(1, -1).replace(/\\"/gu, "\"").replace(/'/gu, "\\'")}'`;
99
+ return encoded;
100
+ };
101
+ /** Shared import boundary: null ignores, unchanged text reports without an unsafe fix. */
102
+ const createImportExtensionListeners = (context, replacement, message) => {
103
+ const check = (node) => {
104
+ if (!Predicate.isObject(node) || !Predicate.isObject(node["source"])) return;
105
+ const source = node["source"];
106
+ if (source["type"] !== "Literal" || typeof source["value"] !== "string" || typeof source["raw"] !== "string" || !isReportable(source)) return;
107
+ const fixed = replacement(source["value"]);
108
+ if (fixed === null) return;
109
+ const quote = source["raw"][0] ?? "\"";
110
+ context.report({
111
+ ...fixed === source["value"] ? {} : { fix: (fixer) => fixer.replaceText(source, quoteLiteral(fixed, quote)) },
112
+ message,
113
+ node: source
114
+ });
115
+ };
116
+ return {
117
+ ExportAllDeclaration: check,
118
+ ExportNamedDeclaration: check,
119
+ ImportDeclaration: check,
120
+ ImportExpression: check
121
+ };
122
+ };
123
+ const rule$33 = {
124
+ create(context) {
125
+ const mode = getImportExtensionMode(context.options[0]);
126
+ return createImportExtensionListeners(context, (value) => {
127
+ const match = matchImportPath(value);
128
+ if (match !== null && (match.extension === "" || match.directory)) return value;
129
+ return normalizeImportExtension(value, mode);
130
+ }, mode === "js" ? "Use explicit JavaScript import extensions (.js, .mjs or .cjs) for code modules" : "Use explicit TypeScript import extensions (.ts, .tsx, .mts or .cts) for code modules");
131
+ },
132
+ meta: {
133
+ fixable: "code",
134
+ schema: importExtensionSchema,
135
+ type: "problem"
136
+ }
137
+ };
138
+ //#endregion
139
+ //#region src/rules/consistent-import-extension.ts
140
+ const rule$32 = {
141
+ create(context) {
142
+ const mode = getImportExtensionMode(context.options[0]);
143
+ return createImportExtensionListeners(context, (value) => normalizeImportExtension(value, mode), mode === "js" ? "Use JavaScript import extensions (.js, .mjs or .cjs) for code modules" : "Use TypeScript import extensions (.ts, .tsx, .mts or .cts) for code modules");
144
+ },
145
+ meta: {
146
+ fixable: "code",
147
+ schema: importExtensionSchema,
148
+ type: "problem"
149
+ }
150
+ };
151
+ //#endregion
152
+ //#region src/rules/force-array-empty.ts
153
+ const isLengthMember = (node) => Predicate.isObject(node) && node["type"] === "MemberExpression" && node["computed"] !== true && Predicate.isObject(node["property"]) && node["property"]["type"] === "Identifier" && node["property"]["name"] === "length";
154
+ const classifyAgainstZero = (operator, literalPosition) => {
155
+ if (operator === "===" || operator === "==") return "empty";
156
+ if (operator === "!==" || operator === "!=") return "non-empty";
157
+ if (operator === ">") return literalPosition === "right" ? "non-empty" : null;
158
+ if (operator === "<") return literalPosition === "right" ? null : "non-empty";
159
+ if (operator === ">=") return literalPosition === "right" ? null : "empty";
160
+ if (operator === "<=") return literalPosition === "right" ? "empty" : null;
161
+ return null;
162
+ };
163
+ const classifyAgainstOne = (operator, literalPosition) => {
164
+ if (operator === "<") return literalPosition === "right" ? "empty" : null;
165
+ if (operator === ">=") return literalPosition === "right" ? "non-empty" : null;
166
+ if (operator === ">") return literalPosition === "right" ? null : "empty";
167
+ if (operator === "<=") return literalPosition === "right" ? null : "non-empty";
168
+ return null;
169
+ };
170
+ const classifyLengthComparison = (operator, literalPosition, literal) => {
171
+ if (literal === 0) return classifyAgainstZero(operator, literalPosition);
172
+ if (literal === 1) return classifyAgainstOne(operator, literalPosition);
173
+ return null;
174
+ };
175
+ const rule$31 = {
176
+ create(context) {
177
+ return { BinaryExpression(node) {
178
+ if (!isReportable(node)) return;
179
+ if (!Predicate.isObject(node)) return;
180
+ if (!Predicate.isString(node["operator"])) return;
181
+ const leftIsLength = isLengthMember(node["left"]);
182
+ const rightIsLength = isLengthMember(node["right"]);
183
+ if (!leftIsLength && !rightIsLength) return;
184
+ const literalPosition = leftIsLength ? "right" : "left";
185
+ const literalSide = literalPosition === "right" ? node["right"] : node["left"];
186
+ const literal = getLiteralNumber(literalSide);
187
+ if (Predicate.isNullish(literal)) return;
188
+ const kind = classifyLengthComparison(node["operator"], literalPosition, literal);
189
+ if (Predicate.isNullish(kind)) return;
190
+ const message = kind === "empty" ? "Use Array.isArrayEmpty()/Array.isReadonlyArrayEmpty() instead of .length comparison" : "Use Array.isArrayNonEmpty()/Array.isReadonlyArrayNonEmpty() instead of .length comparison";
191
+ context.report({
192
+ message,
193
+ node
194
+ });
195
+ } };
196
+ },
197
+ meta: { type: "problem" }
198
+ };
199
+ //#endregion
200
+ //#region src/rules/force-iterable-empty.ts
201
+ const isIterableSizeCall = (node) => Predicate.isObject(node) && node["type"] === "CallExpression" && Predicate.isObject(node["callee"]) && node["callee"]["type"] === "MemberExpression" && node["callee"]["computed"] !== true && Predicate.isObject(node["callee"]["object"]) && node["callee"]["object"]["type"] === "Identifier" && node["callee"]["object"]["name"] === "Iterable" && Predicate.isObject(node["callee"]["property"]) && node["callee"]["property"]["type"] === "Identifier" && node["callee"]["property"]["name"] === "size";
202
+ const rule$30 = {
203
+ create(context) {
204
+ return { BinaryExpression(node) {
205
+ if (!isReportable(node)) return;
206
+ if (!Predicate.isObject(node)) return;
207
+ if (!Predicate.isString(node["operator"])) return;
208
+ const leftIsSize = isIterableSizeCall(node["left"]);
209
+ const rightIsSize = isIterableSizeCall(node["right"]);
210
+ if (!leftIsSize && !rightIsSize) return;
211
+ const literalPosition = leftIsSize ? "right" : "left";
212
+ const literalSide = literalPosition === "right" ? node["right"] : node["left"];
213
+ const literal = getLiteralNumber(literalSide);
214
+ if (Predicate.isNullish(literal)) return;
215
+ const kind = classifyLengthComparison(node["operator"], literalPosition, literal);
216
+ if (Predicate.isNullish(kind)) return;
217
+ const message = kind === "empty" ? "Use Iterable.isEmpty() instead of Iterable.size() === 0 comparison" : "Use !Iterable.isEmpty() instead of Iterable.size() comparison";
218
+ context.report({
219
+ message,
220
+ node
221
+ });
222
+ } };
223
+ },
224
+ meta: { type: "problem" }
225
+ };
226
+ //#endregion
227
+ //#region src/rules/force-predicate.ts
228
+ const typeofToPredicateMap = {
229
+ bigint: "Predicate.isBigInt",
230
+ boolean: "Predicate.isBoolean",
231
+ function: "Predicate.isFunction",
232
+ number: "Predicate.isNumber",
233
+ object: "Predicate.isObject",
234
+ string: "Predicate.isString",
235
+ symbol: "Predicate.isSymbol",
236
+ undefined: "Predicate.isUndefined"
237
+ };
238
+ const isNullLiteral = (node) => Predicate.isObject(node) && node["type"] === "Literal" && Predicate.isNullish(node["value"]);
239
+ const isUndefinedIdentifier = (node) => Predicate.isObject(node) && node["type"] === "Identifier" && node["name"] === "undefined";
240
+ const getNullishSide = (node) => {
241
+ if (isNullLiteral(node)) return "null";
242
+ if (isUndefinedIdentifier(node)) return "undefined";
243
+ return null;
244
+ };
245
+ const getTypeofType = (node) => {
246
+ if (Predicate.isObject(node) && node["type"] === "UnaryExpression" && node["operator"] === "typeof") return "typeof";
247
+ return null;
248
+ };
249
+ const getStringValue = (node) => {
250
+ if (Predicate.isObject(node) && node["type"] === "Literal" && Predicate.isString(node["value"])) return node["value"];
251
+ return null;
252
+ };
253
+ const resolveTypeStr = (leftTypeof, rightTypeof, leftStr, rightStr) => {
254
+ if (Predicate.isNotNullish(leftTypeof)) return rightStr;
255
+ if (Predicate.isNotNullish(rightTypeof)) return leftStr;
256
+ return null;
257
+ };
258
+ const rule$29 = {
259
+ create(context) {
260
+ return { BinaryExpression(node) {
261
+ if (!isReportable(node)) return;
262
+ if (Predicate.isObject(node) && isEqualityOperator(node["operator"])) {
263
+ const leftKind = getNullishSide(node["left"]);
264
+ const rightKind = getNullishSide(node["right"]);
265
+ const kind = leftKind ?? rightKind;
266
+ if (Predicate.isNotNullish(kind)) {
267
+ const predicateFn = kind === "null" ? "Predicate.isNull" : "Predicate.isUndefined";
268
+ context.report({
269
+ message: `Use ${predicateFn}() instead of direct ${kind} comparison`,
270
+ node
271
+ });
272
+ return;
273
+ }
274
+ const leftTypeof = getTypeofType(node["left"]);
275
+ const rightTypeof = getTypeofType(node["right"]);
276
+ const leftStr = getStringValue(node["left"]);
277
+ const rightStr = getStringValue(node["right"]);
278
+ const typeStr = resolveTypeStr(leftTypeof, rightTypeof, leftStr, rightStr);
279
+ if (Predicate.isNullish(typeStr)) return;
280
+ const predicateFn = typeofToPredicateMap[typeStr];
281
+ if (Predicate.isNullish(predicateFn)) return;
282
+ context.report({
283
+ message: `Use ${predicateFn}() instead of typeof comparison`,
284
+ node
285
+ });
286
+ }
287
+ } };
288
+ },
289
+ meta: { type: "problem" }
290
+ };
291
+ //#endregion
292
+ //#region src/rules/force-string-empty.ts
293
+ const isEmptyStringLiteral = (node) => Predicate.isObject(node) && node["type"] === "Literal" && Predicate.isString(node["value"]) && String.isEmpty(node["value"]);
294
+ const rule$28 = {
295
+ create(context) {
296
+ return { BinaryExpression(node) {
297
+ if (!isReportable(node)) return;
298
+ if (Predicate.isObject(node) && isEqualityOperator(node["operator"])) {
299
+ const leftEmpty = isEmptyStringLiteral(node["left"]);
300
+ const rightEmpty = isEmptyStringLiteral(node["right"]);
301
+ if (!leftEmpty && !rightEmpty) return;
302
+ const predicateFn = node["operator"] === "==" || node["operator"] === "===" ? "String.isEmpty" : "String.isNonEmpty";
303
+ context.report({
304
+ message: `Use ${predicateFn}() instead of direct empty string comparison`,
305
+ node
306
+ });
307
+ }
308
+ } };
309
+ },
310
+ meta: { type: "problem" }
311
+ };
312
+ //#endregion
313
+ //#region src/rules/no-effect-import-as.ts
314
+ const EFFECT_IMPORT_RE = /^@?effect(?:\/|$)/u;
315
+ const isEffectEcosystemImport = (sourceValue) => EFFECT_IMPORT_RE.test(sourceValue);
316
+ const checkSpecifierForAs = (spec, context, reportNode) => {
317
+ if (spec["type"] === "ImportNamespaceSpecifier") {
318
+ const localName = hasProperty(spec, "local") && Predicate.isObject(spec.local) && hasProperty(spec.local, "name") && Predicate.isString(spec.local.name) ? spec.local.name : "";
319
+ context.report({
320
+ message: `Avoid namespace import (\`import * as ${localName}\`) from the effect ecosystem. Use named imports directly.`,
321
+ node: reportNode
322
+ });
323
+ return true;
324
+ }
325
+ if (spec["type"] === "ImportSpecifier" && hasProperty(spec, "imported") && hasProperty(spec, "local") && Predicate.isObject(spec.imported) && Predicate.isObject(spec.local) && hasProperty(spec.imported, "name") && hasProperty(spec.local, "name") && Predicate.isString(spec.imported.name) && Predicate.isString(spec.local.name)) {
326
+ const { name: importedName } = spec.imported;
327
+ const { name: localName } = spec.local;
328
+ if (importedName !== localName) {
329
+ context.report({
330
+ message: `Avoid aliased import (\`${importedName} as ${localName}\`) from the effect ecosystem. Import \`${importedName}\` directly without aliasing.`,
331
+ node: reportNode
332
+ });
333
+ return true;
334
+ }
335
+ }
336
+ return false;
337
+ };
338
+ const rule$27 = {
339
+ create(context) {
340
+ return { ImportDeclaration(node) {
341
+ const sourceValue = getImportSource(node);
342
+ if (Predicate.isNullish(sourceValue) || !isEffectEcosystemImport(sourceValue) || !isReportable(node)) return;
343
+ const specifiers = Predicate.isObject(node) && hasProperty(node, "specifiers") ? node["specifiers"] : null;
344
+ if (!Array.isArray(specifiers)) return;
345
+ for (const spec of specifiers) if (Predicate.isObject(spec) && checkSpecifierForAs(spec, context, node)) return;
346
+ } };
347
+ },
348
+ meta: { type: "problem" }
349
+ };
350
+ //#endregion
351
+ //#region src/rules/no-effect-runtime-run.ts
352
+ const RUNTIME_METHODS = /* @__PURE__ */ new Set([
353
+ "runCallback",
354
+ "runFork",
355
+ "runMain",
356
+ "runPromise",
357
+ "runPromiseExit",
358
+ "runSync"
359
+ ]);
360
+ const getRuntimeMethod = (node) => {
361
+ if (Predicate.isObject(node) && node["type"] === "MemberExpression" && node["computed"] !== true && Predicate.isObject(node["property"]) && node["property"]["type"] === "Identifier" && Predicate.isString(node["property"]["name"]) && RUNTIME_METHODS.has(node["property"]["name"])) return node["property"]["name"];
362
+ return null;
363
+ };
364
+ const isRuntimeCallee = (node) => Predicate.isNotNullish(getRuntimeMethod(node));
365
+ const rule$26 = {
366
+ create(context) {
367
+ return { CallExpression(node) {
368
+ if (!isReportable(node) || !Predicate.isObject(node) || !hasProperty(node, "callee")) return;
369
+ if (!isRuntimeCallee(node["callee"])) return;
370
+ context.report({
371
+ message: "Run Effect runtimes only at workflow boundaries. Move runtime execution to the top-level entrypoint, or disable this rule with a reason for genuinely independent workflows (for example a client-side useEffect).",
372
+ node
373
+ });
374
+ } };
375
+ },
376
+ meta: { type: "problem" }
377
+ };
378
+ //#endregion
379
+ //#region src/rules/no-effect-subpath-import.ts
380
+ const EFFECT_ECOSYSTEM_RE = /^@?effect(?:\/|$)/u;
381
+ const isAllowedEffectImport = (source) => {
382
+ if (source === "effect") return true;
383
+ if (/^@effect\/[^/]+$/u.test(source)) return true;
384
+ if (/^effect\/unstable\/[^/]+$/u.test(source)) return true;
385
+ return false;
386
+ };
387
+ const rule$25 = {
388
+ create(context) {
389
+ return { ImportDeclaration(node) {
390
+ if (!isReportable(node)) return;
391
+ if (!Predicate.isObject(node)) return;
392
+ if (!hasProperty(node, "source")) return;
393
+ const { source } = node;
394
+ if (!Predicate.isObject(source)) return;
395
+ if (!hasProperty(source, "value")) return;
396
+ if (!Predicate.isString(source.value)) return;
397
+ if (!EFFECT_ECOSYSTEM_RE.test(source.value)) return;
398
+ if (isAllowedEffectImport(source.value)) return;
399
+ context.report({
400
+ message: `Avoid subpath imports from the effect ecosystem. Import from the package root instead (e.g. \`@effect/platform-node\` not \`@effect/platform-node/NodeRuntime\`).`,
401
+ node
402
+ });
403
+ } };
404
+ },
405
+ meta: { type: "problem" }
406
+ };
407
+ //#endregion
408
+ //#region src/rules/no-error-cause-option.ts
409
+ const NO_ERROR_CAUSE_OPTION_MESSAGE = "Do not pass `{ cause }` to `new Error`. Use `{ error }` instead.";
410
+ const getIdentifierName$3 = (node) => Predicate.isObject(node) && node["type"] === "Identifier" && Predicate.isString(node["name"]) ? node["name"] : null;
411
+ const getPropertyKeyName = (node) => {
412
+ if (Predicate.isObject(node) && node["type"] === "Identifier" && Predicate.isString(node["name"])) return node["name"];
413
+ if (Predicate.isObject(node) && node["type"] === "Literal" && Predicate.isString(node["value"])) return node["value"];
414
+ return null;
415
+ };
416
+ const hasCauseProperty = (node) => Predicate.isObject(node) && node["type"] === "ObjectExpression" && hasProperty(node, "properties") && Array.isArray(node["properties"]) && node["properties"]["some"]((property) => Predicate.isObject(property) && hasProperty(property, "key") ? getPropertyKeyName(property.key) === "cause" : false);
417
+ const isNewErrorWithCauseOption = (node) => Predicate.isObject(node) && node["type"] === "NewExpression" && getIdentifierName$3(node["callee"]) === "Error" && hasProperty(node, "arguments") && Array.isArray(node["arguments"]) && node["arguments"]["some"](hasCauseProperty);
418
+ const rule$24 = {
419
+ create(context) {
420
+ return { NewExpression(node) {
421
+ if (!isReportable(node) || !isNewErrorWithCauseOption(node)) return;
422
+ context.report({
423
+ message: NO_ERROR_CAUSE_OPTION_MESSAGE,
424
+ node
425
+ });
426
+ } };
427
+ },
428
+ meta: { type: "problem" }
429
+ };
430
+ //#endregion
431
+ //#region src/rules/no-error-property-access.ts
432
+ const NO_ERROR_PROPERTY_ACCESS_MESSAGE = "Do not access properties on caught error values (`e`, `error`, `c`, `cause`, or `err`). Pass the value through as `error` unchanged.";
433
+ const ERROR_VALUE_NAMES = /* @__PURE__ */ new Set([
434
+ "c",
435
+ "cause",
436
+ "e",
437
+ "err",
438
+ "error"
439
+ ]);
440
+ const getIdentifierName$2 = (node) => Predicate.isObject(node) && node["type"] === "Identifier" && Predicate.isString(node["name"]) ? node["name"] : null;
441
+ const isErrorPropertyAccess = (node) => Predicate.isObject(node) && node["type"] === "MemberExpression" && Predicate.isObject(node["object"]) && ERROR_VALUE_NAMES.has(getIdentifierName$2(node["object"]) ?? "");
442
+ const rule$23 = {
443
+ create(context) {
444
+ return { MemberExpression(node) {
445
+ if (!isReportable(node) || !isErrorPropertyAccess(node)) return;
446
+ context.report({
447
+ message: NO_ERROR_PROPERTY_ACCESS_MESSAGE,
448
+ node
449
+ });
450
+ } };
451
+ },
452
+ meta: { type: "problem" }
453
+ };
454
+ //#endregion
455
+ //#region src/rules/no-eslint-disable-comments.ts
456
+ const ESLINT_DISABLE_RE = /^\s*eslint-disable(?:-next-line|-line)?\b/gmu;
457
+ const rule$22 = {
458
+ create(context) {
459
+ return { "Program:exit"() {
460
+ const comments = context.sourceCode.getAllComments();
461
+ for (const comment of comments) {
462
+ const { value } = comment;
463
+ ESLINT_DISABLE_RE.lastIndex = 0;
464
+ if (ESLINT_DISABLE_RE.test(value)) {
465
+ const fixed = value.replaceAll("eslint-disable", "oxlint-disable");
466
+ context.report({
467
+ fix(fixer) {
468
+ const [start, end] = comment.range;
469
+ const prefix = comment.type === "Block" ? "/*" : "//";
470
+ const suffix = comment.type === "Block" ? "*/" : "";
471
+ return fixer.replaceTextRange([start, end], `${prefix}${fixed}${suffix}`);
472
+ },
473
+ message: "Use oxlint-disable instead of eslint-disable.",
474
+ node: comment
475
+ });
476
+ }
477
+ }
478
+ } };
479
+ },
480
+ meta: {
481
+ fixable: "code",
482
+ type: "problem"
483
+ }
484
+ };
485
+ //#endregion
486
+ //#region src/rules/no-fetch.ts
487
+ const FETCH_GLOBALS = /* @__PURE__ */ new Set([
488
+ "globalThis",
489
+ "self",
490
+ "window"
491
+ ]);
492
+ const FETCH_GUIDANCE_MESSAGE = "Use Effect `HttpClient` (provide the `FetchHttpClient` layer) instead of the global `fetch`. Bypass only at external-library anti-corruption layers with a documented disable reason.";
493
+ const isFetchIdentifier = (node) => Predicate.isObject(node) && node["type"] === "Identifier" && hasProperty(node, "name") && node["name"] === "fetch";
494
+ const isFetchOnGlobal = (node) => {
495
+ if (!Predicate.isObject(node) || node["type"] !== "MemberExpression" || node["computed"] === true) return false;
496
+ if (!isFetchIdentifier(node["property"])) return false;
497
+ if (!Predicate.isObject(node["object"]) || node["object"]["type"] !== "Identifier") return false;
498
+ return hasProperty(node["object"], "name") && Predicate.isString(node["object"]["name"]) && FETCH_GLOBALS.has(node["object"]["name"]);
499
+ };
500
+ const rule$21 = {
501
+ create(context) {
502
+ return { CallExpression(node) {
503
+ if (!isReportable(node) || !Predicate.isObject(node) || !hasProperty(node, "callee")) return;
504
+ const { callee } = node;
505
+ if (isFetchIdentifier(callee) || isFetchOnGlobal(callee)) context.report({
506
+ message: FETCH_GUIDANCE_MESSAGE,
507
+ node
508
+ });
509
+ } };
510
+ },
511
+ meta: { type: "problem" }
512
+ };
513
+ //#endregion
514
+ //#region src/rules/no-instanceof-error.ts
515
+ const NO_INSTANCEOF_ERROR_MESSAGE = "Do not use `instanceof Error`. Preserve caught errors as `error` and handle narrowing only in the shared fp error helper with an explicit disable comment.";
516
+ const getIdentifierName$1 = (node) => Predicate.isObject(node) && node["type"] === "Identifier" && Predicate.isString(node["name"]) ? node["name"] : null;
517
+ const isInstanceofError = (node) => Predicate.isObject(node) && node["type"] === "BinaryExpression" && node["operator"] === "instanceof" && getIdentifierName$1(node["right"]) === "Error";
518
+ const rule$20 = {
519
+ create(context) {
520
+ return { BinaryExpression(node) {
521
+ if (!isReportable(node) || !isInstanceofError(node)) return;
522
+ context.report({
523
+ message: NO_INSTANCEOF_ERROR_MESSAGE,
524
+ node
525
+ });
526
+ } };
527
+ },
528
+ meta: { type: "problem" }
529
+ };
530
+ //#endregion
531
+ //#region src/rules/no-js-date.ts
532
+ const FORBIDDEN_DATE_STATIC_METHODS = /* @__PURE__ */ new Set([
533
+ "now",
534
+ "parse",
535
+ "UTC"
536
+ ]);
537
+ const isDateIdentifier = (node) => Predicate.isObject(node) && node["type"] === "Identifier" && node["name"] === "Date";
538
+ const getForbiddenDateStaticMethod = (node) => {
539
+ if (Predicate.isObject(node) && node["type"] === "MemberExpression" && node["computed"] !== true && isDateIdentifier(node["object"]) && Predicate.isObject(node["property"]) && node["property"]["type"] === "Identifier" && Predicate.isString(node["property"]["name"]) && FORBIDDEN_DATE_STATIC_METHODS.has(node["property"]["name"])) return node["property"]["name"];
540
+ return null;
541
+ };
542
+ const rule$19 = {
543
+ create(context) {
544
+ return {
545
+ MemberExpression(node) {
546
+ if (!isReportable(node)) return;
547
+ const method = getForbiddenDateStaticMethod(node);
548
+ if (Predicate.isNotNullish(method)) context.report({
549
+ message: `Use Effect \`DateTime\` / \`Duration\` instead of \`Date.${method}()\`. Native \`Date\` is allowed only at external-API boundaries.`,
550
+ node
551
+ });
552
+ },
553
+ NewExpression(node) {
554
+ if (!isReportable(node)) return;
555
+ if (Predicate.isObject(node) && isDateIdentifier(node["callee"])) context.report({
556
+ message: "Use Effect `DateTime` / `Duration` instead of `new Date()`. Native `Date` is allowed only at external-API boundaries.",
557
+ node
558
+ });
559
+ }
560
+ };
561
+ },
562
+ meta: { type: "problem" }
563
+ };
564
+ //#endregion
565
+ //#region src/rules/no-jsx-script-tag.ts
566
+ const isScriptJsxElement = (node) => Predicate.isObject(node) && node["type"] === "JSXOpeningElement" && Predicate.isObject(node["name"]) && node["name"].type === "JSXIdentifier" && node["name"].name === "script";
567
+ const rule$18 = {
568
+ create(context) {
569
+ return { JSXOpeningElement(node) {
570
+ if (!isReportable(node)) return;
571
+ if (isScriptJsxElement(node)) context.report({
572
+ message: "Do not use <script> tags in JSX. Write client-side logic in React or Remix v3 components instead. If unavoidable (e.g. a third-party inline script), disable this rule with an oxlint-disable comment that includes the reason.",
573
+ node
574
+ });
575
+ } };
576
+ },
577
+ meta: { type: "problem" }
578
+ };
579
+ //#endregion
580
+ //#region src/rules/no-let.ts
581
+ const isLetDeclaration = (node) => Predicate.isObject(node) && node["kind"] === "let";
582
+ const rule$17 = {
583
+ create(context) {
584
+ return { VariableDeclaration(node) {
585
+ if (!isReportable(node)) return;
586
+ if (isLetDeclaration(node)) context.report({
587
+ message: "Use const with shadowing instead of let. Reassignment via let is prohibited.",
588
+ node
589
+ });
590
+ } };
591
+ },
592
+ meta: { type: "problem" }
593
+ };
594
+ //#endregion
595
+ //#region src/rules/no-node-imports.ts
596
+ const NODE_PROTOCOL = "node:";
597
+ const NODE_IMPORT_GUIDANCE_MESSAGE = "Avoid Node.js built-in imports. Prefer Effect Platform APIs from `effect` / `@effect/platform-node`; add a rule whitelist entry only for documented exceptions.";
598
+ const getNodeBuiltinSpecifier = (source) => {
599
+ if (!source.startsWith(NODE_PROTOCOL)) return null;
600
+ return source.slice(5);
601
+ };
602
+ const getStringArrayProperty = (value, key) => {
603
+ if (!Predicate.isObject(value) || !hasProperty(value, key) || !Array.isArray(value[key])) return [];
604
+ return value[key].filter(Predicate.isString);
605
+ };
606
+ const getContextOptions = (context) => {
607
+ if (!Predicate.isObject(context) || !hasProperty(context, "options")) return [];
608
+ const { options } = context;
609
+ return Array.isArray(options) ? options : [];
610
+ };
611
+ const getAllowedNodeBuiltins = (context) => {
612
+ const first = getContextOptions(context).at(0);
613
+ if (Array.isArray(first)) return new Set(first.filter(Predicate.isString));
614
+ return /* @__PURE__ */ new Set([...getStringArrayProperty(first, "allow"), ...getStringArrayProperty(first, "allowed")]);
615
+ };
616
+ const reportNodeImport = (node, context) => {
617
+ const source = getImportSource(node);
618
+ if (Predicate.isNullish(source) || !isReportable(node)) return;
619
+ const builtin = getNodeBuiltinSpecifier(source);
620
+ if (Predicate.isNullish(builtin) || getAllowedNodeBuiltins(context).has(builtin)) return;
621
+ context.report({
622
+ message: NODE_IMPORT_GUIDANCE_MESSAGE,
623
+ node
624
+ });
625
+ };
626
+ const rule$16 = {
627
+ create(context) {
628
+ return {
629
+ ExportAllDeclaration(node) {
630
+ reportNodeImport(node, context);
631
+ },
632
+ ExportNamedDeclaration(node) {
633
+ reportNodeImport(node, context);
634
+ },
635
+ ImportDeclaration(node) {
636
+ reportNodeImport(node, context);
637
+ }
638
+ };
639
+ },
640
+ meta: {
641
+ schema: [{ anyOf: [{
642
+ items: { type: "string" },
643
+ type: "array"
644
+ }, {
645
+ additionalProperties: false,
646
+ properties: {
647
+ allow: {
648
+ items: { type: "string" },
649
+ type: "array"
650
+ },
651
+ allowed: {
652
+ items: { type: "string" },
653
+ type: "array"
654
+ }
655
+ },
656
+ type: "object"
657
+ }] }],
658
+ type: "problem"
659
+ }
660
+ };
661
+ //#endregion
662
+ //#region src/rules/no-option-tag-comparison.ts
663
+ const tagToPredicateMap = {
664
+ None: "Option.isNone",
665
+ Some: "Option.isSome"
666
+ };
667
+ const getOptionTag = (node) => {
668
+ if (Predicate.isObject(node) && node["type"] === "Literal" && Predicate.isString(node["value"])) {
669
+ const { value } = node;
670
+ if (value in tagToPredicateMap) return value;
671
+ }
672
+ return null;
673
+ };
674
+ const isTagPropertyAccess = (node) => Predicate.isObject(node) && node["type"] === "MemberExpression" && node["computed"] !== true && Predicate.isObject(node["property"]) && node["property"]["type"] === "Identifier" && node["property"]["name"] === "_tag";
675
+ const isTypeofTag = (node) => Predicate.isObject(node) && node["type"] === "UnaryExpression" && node["operator"] === "typeof" && isTagPropertyAccess(node["argument"]);
676
+ const rule$15 = {
677
+ create(context) {
678
+ return { BinaryExpression(node) {
679
+ if (!isReportable(node)) return;
680
+ if (Predicate.isObject(node) && isEqualityOperator(node["operator"])) {
681
+ const leftTag = getOptionTag(node["left"]);
682
+ const rightTag = getOptionTag(node["right"]);
683
+ const tag = leftTag ?? rightTag;
684
+ if (Predicate.isNullish(tag)) return;
685
+ const otherSide = Predicate.isNotNullish(leftTag) ? node["right"] : node["left"];
686
+ if (isTagPropertyAccess(otherSide) || isTypeofTag(otherSide)) {
687
+ const predicateFn = tagToPredicateMap[tag];
688
+ const isEquality = node["operator"] === "==" || node["operator"] === "===";
689
+ context.report({
690
+ fix(fixer) {
691
+ const rawTarget = hasProperty(otherSide, "object") ? otherSide.object : otherSide;
692
+ if (!isReportable(rawTarget)) return null;
693
+ const sourceText = context.sourceCode.getText(rawTarget);
694
+ const prefix = isEquality ? "" : "!";
695
+ return fixer.replaceText(node, `${prefix}${predicateFn}(${sourceText})`);
696
+ },
697
+ message: `Use ${predicateFn}() instead of _tag === '${tag}'`,
698
+ node
699
+ });
700
+ }
701
+ }
702
+ } };
703
+ },
704
+ meta: {
705
+ fixable: "code",
706
+ type: "problem"
707
+ }
708
+ };
709
+ //#endregion
710
+ //#region src/rules/no-raw-hono-create-middleware.ts
711
+ const HONO_FACTORY_SOURCE = "hono/factory";
712
+ const CREATE_MIDDLEWARE_NAME = "createMiddleware";
713
+ const MESSAGE = "Do not use raw `createMiddleware` from `hono/factory` in application code. Use the shared `factory.createMiddleware` instance instead. Shared library code may disable this rule with a reason.";
714
+ const getIdentifierName = (node) => Predicate.isObject(node) && hasProperty(node, "name") && Predicate.isString(node["name"]) ? node["name"] : null;
715
+ const isCreateMiddlewareImportSpecifier = (node) => Predicate.isObject(node) && node["type"] === "ImportSpecifier" && hasProperty(node, "imported") && getIdentifierName(node["imported"]) === CREATE_MIDDLEWARE_NAME;
716
+ const isNamespaceCreateMiddlewareCall = (node, namespaceNames) => {
717
+ if (!Predicate.isObject(node) || node["type"] !== "CallExpression" || !hasProperty(node, "callee")) return false;
718
+ const { callee } = node;
719
+ if (!Predicate.isObject(callee) || callee["type"] !== "MemberExpression" || callee["computed"] === true) return false;
720
+ if (getIdentifierName(callee["property"]) !== CREATE_MIDDLEWARE_NAME) return false;
721
+ const objectName = getIdentifierName(callee["object"]);
722
+ return !Predicate.isNullish(objectName) && namespaceNames.has(objectName);
723
+ };
724
+ const rule$14 = {
725
+ create(context) {
726
+ const honoFactoryNamespaceNames = /* @__PURE__ */ new Set();
727
+ return {
728
+ CallExpression(node) {
729
+ if (!isReportable(node) || !isNamespaceCreateMiddlewareCall(node, honoFactoryNamespaceNames)) return;
730
+ context.report({
731
+ message: MESSAGE,
732
+ node
733
+ });
734
+ },
735
+ ImportDeclaration(node) {
736
+ if (getImportSource(node) !== HONO_FACTORY_SOURCE || !isReportable(node)) return;
737
+ const specifiers = Predicate.isObject(node) && hasProperty(node, "specifiers") ? node["specifiers"] : null;
738
+ if (!Array.isArray(specifiers)) return;
739
+ for (const specifier of specifiers) {
740
+ if (!Predicate.isObject(specifier)) continue;
741
+ if (isCreateMiddlewareImportSpecifier(specifier)) {
742
+ context.report({
743
+ message: MESSAGE,
744
+ node
745
+ });
746
+ continue;
747
+ }
748
+ if (specifier["type"] === "ImportNamespaceSpecifier" && hasProperty(specifier, "local")) {
749
+ const localName = getIdentifierName(specifier.local);
750
+ if (!Predicate.isNullish(localName)) honoFactoryNamespaceNames.add(localName);
751
+ }
752
+ }
753
+ }
754
+ };
755
+ },
756
+ meta: { type: "problem" }
757
+ };
758
+ //#endregion
759
+ //#region src/rules/no-redundant-alias.ts
760
+ const REDUNDANT_TYPE_ALIAS_MESSAGE = "Avoid type aliases that merely rename another type (e.g. `type SentEmail = SendParams`). Inline the original, or keep the alias only inside an anti-corruption layer with a documented disable reason.";
761
+ const REDUNDANT_VALUE_ALIAS_MESSAGE = "Avoid exported bindings that merely rename another value (e.g. `export const sentEmail = sendParams`). Re-export the original directly, or keep the alias only inside an anti-corruption layer with a documented disable reason.";
762
+ const hasTypeArguments = (node) => Predicate.isObject(node) && hasProperty(node, "typeArguments") && Predicate.isNotNullish(node["typeArguments"]);
763
+ const hasGenericTypeParameters = (node) => Predicate.isObject(node) && hasProperty(node, "typeParameters") && Predicate.isNotNullish(node["typeParameters"]);
764
+ const isPlainTypeReference = (node) => Predicate.isObject(node) && node["type"] === "TSTypeReference" && !hasTypeArguments(node);
765
+ const isRedundantTypeAlias = (node) => {
766
+ if (!Predicate.isObject(node) || node["type"] !== "TSTypeAliasDeclaration") return false;
767
+ if (hasGenericTypeParameters(node)) return false;
768
+ return hasProperty(node, "typeAnnotation") && isPlainTypeReference(node["typeAnnotation"]);
769
+ };
770
+ const isIdentifierInitDeclarator = (declarator) => Predicate.isObject(declarator) && hasProperty(declarator, "id") && Predicate.isObject(declarator.id) && declarator.id["type"] === "Identifier" && hasProperty(declarator, "init") && Predicate.isObject(declarator.init) && declarator.init["type"] === "Identifier";
771
+ const rule$13 = {
772
+ create(context) {
773
+ return {
774
+ ExportNamedDeclaration(node) {
775
+ if (!isReportable(node) || !Predicate.isObject(node) || !hasProperty(node, "declaration")) return;
776
+ const { declaration } = node;
777
+ if (!Predicate.isObject(declaration) || declaration["type"] !== "VariableDeclaration" || !hasProperty(declaration, "declarations") || !Array.isArray(declaration.declarations)) return;
778
+ const declarationItems = declaration.declarations;
779
+ for (const declarator of declarationItems) if (isReportable(declarator) && isIdentifierInitDeclarator(declarator)) context.report({
780
+ message: REDUNDANT_VALUE_ALIAS_MESSAGE,
781
+ node: declarator
782
+ });
783
+ },
784
+ TSTypeAliasDeclaration(node) {
785
+ if (!isReportable(node)) return;
786
+ if (isRedundantTypeAlias(node)) context.report({
787
+ message: REDUNDANT_TYPE_ALIAS_MESSAGE,
788
+ node
789
+ });
790
+ }
791
+ };
792
+ },
793
+ meta: { type: "problem" }
794
+ };
795
+ //#endregion
796
+ //#region src/rules/no-string-style.ts
797
+ const hasStringStyleValue = (node) => Predicate.isObject(node) && node["type"] === "JSXAttribute" && Predicate.isObject(node["name"]) && node["name"].name === "style" && Predicate.isObject(node["value"]) && node["value"].type === "Literal" && Predicate.isString(node["value"].value);
798
+ const rule$12 = {
799
+ create(context) {
800
+ return { JSXAttribute(node) {
801
+ if (!isReportable(node)) return;
802
+ if (hasStringStyleValue(node)) context.report({
803
+ message: "Use object-style `style={{ ... }}` instead of string `style=\"...\"`.",
804
+ node
805
+ });
806
+ } };
807
+ },
808
+ meta: { type: "problem" }
809
+ };
810
+ //#endregion
811
+ //#region src/rules/no-sync-decode.ts
812
+ const BANNED_DECODE_METHODS = {
813
+ decodePromise: "decodeEffect",
814
+ decodeSync: "decodeEffect",
815
+ decodeUnknownPromise: "decodeUnknownEffect",
816
+ decodeUnknownSync: "decodeUnknownEffect"
817
+ };
818
+ const isSchemaBannedDecodeCall = (node) => {
819
+ for (const method of Object.keys(BANNED_DECODE_METHODS)) if (isSchemaMethodCall(node, method)) return method;
820
+ return null;
821
+ };
822
+ const rule$11 = {
823
+ create(context) {
824
+ return { CallExpression(node) {
825
+ if (!isReportable(node)) return;
826
+ const method = isSchemaBannedDecodeCall(node);
827
+ if (Predicate.isNotNullish(method)) {
828
+ const recommended = BANNED_DECODE_METHODS[method];
829
+ context.report({
830
+ message: `Use Schema.${recommended} or Schema.decodeExit instead of Schema.${method}.`,
831
+ node
832
+ });
833
+ }
834
+ } };
835
+ },
836
+ meta: { type: "problem" }
837
+ };
838
+ //#endregion
839
+ //#region src/rules/no-type-predicate.ts
840
+ const NO_TYPE_PREDICATE_MESSAGE = "Do not use TypeScript type predicate annotations (`value is Type`). Model the value with Effect Schema and use `Schema.is(...)` instead.";
841
+ const isTypePredicateAnnotation = (node) => Predicate.isObject(node) && node["type"] === "TSTypePredicate";
842
+ const rule$10 = {
843
+ create(context) {
844
+ return { TSTypePredicate(node) {
845
+ if (!isReportable(node) || !isTypePredicateAnnotation(node)) return;
846
+ context.report({
847
+ message: NO_TYPE_PREDICATE_MESSAGE,
848
+ node
849
+ });
850
+ } };
851
+ },
852
+ meta: { type: "problem" }
853
+ };
854
+ //#endregion
855
+ //#region src/rules/prefer-is-nullish.ts
856
+ const NULLISH_PREDICATE_METHODS = /* @__PURE__ */ new Set([
857
+ "isNull",
858
+ "isNotNull",
859
+ "isUndefined",
860
+ "isNotUndefined"
861
+ ]);
862
+ const getNullishPredicateMember = (node) => {
863
+ if (!Predicate.isObject(node) || !Predicate.isObject(node["object"]) || node["object"]["type"] !== "Identifier" || node["object"]["name"] !== "Predicate" || !Predicate.isObject(node["property"]) || node["property"]["type"] !== "Identifier" || !Predicate.isString(node["property"]["name"])) return null;
864
+ const { name } = node["property"];
865
+ return NULLISH_PREDICATE_METHODS.has(name) ? name : null;
866
+ };
867
+ const rule$9 = {
868
+ create(context) {
869
+ return { MemberExpression(node) {
870
+ if (!isReportable(node)) return;
871
+ const method = getNullishPredicateMember(node);
872
+ if (Predicate.isNullish(method)) return;
873
+ const recommended = method.startsWith("isNot") ? "isNotNullish" : "isNullish";
874
+ context.report({
875
+ message: `Use Predicate.${recommended} to treat null and undefined uniformly. Only when distinguishing them is required, disable this rule with an oxlint-disable comment that includes the reason.`,
876
+ node
877
+ });
878
+ } };
879
+ },
880
+ meta: { type: "suggestion" }
881
+ };
882
+ //#endregion
883
+ //#region src/rules/prefer-non-unknown-decode.ts
884
+ const UNKNOWN_DECODE_METHODS = {
885
+ decodeUnknownEffect: "decodeEffect",
886
+ decodeUnknownExit: "decodeExit"
887
+ };
888
+ const isSchemaUnknownDecodeCall = (node) => {
889
+ for (const method of Object.keys(UNKNOWN_DECODE_METHODS)) if (isSchemaMethodCall(node, method)) return method;
890
+ return null;
891
+ };
892
+ const rule$8 = {
893
+ create(context) {
894
+ return { CallExpression(node) {
895
+ if (!isReportable(node)) return;
896
+ const method = isSchemaUnknownDecodeCall(node);
897
+ if (Predicate.isNotNullish(method)) {
898
+ const recommended = UNKNOWN_DECODE_METHODS[method];
899
+ context.report({
900
+ message: `Prefer Schema.${recommended} over Schema.${method}. Use unknown variants only when input type is truly unknown. Add an oxlint-disable comment if the unknown variant is required.`,
901
+ node
902
+ });
903
+ }
904
+ } };
905
+ },
906
+ meta: { type: "suggestion" }
907
+ };
908
+ //#endregion
909
+ //#region src/rules/require-disable-reason.ts
910
+ const OXLINT_DISABLE_DIRECTIVE_RE = /\boxlint-disable\b/u;
911
+ const DISABLE_REASON_RE = /\s--\s+\S/u;
912
+ const isOxlintDisableDirective = (value) => OXLINT_DISABLE_DIRECTIVE_RE.test(value);
913
+ const hasDisableReason = (value) => DISABLE_REASON_RE.test(value);
914
+ const rule$7 = {
915
+ create(context) {
916
+ return { "Program:exit"() {
917
+ const comments = context.sourceCode.getAllComments();
918
+ for (const comment of comments) {
919
+ const { value } = comment;
920
+ if (!isOxlintDisableDirective(value)) continue;
921
+ if (hasDisableReason(value)) continue;
922
+ context.report({
923
+ message: "oxlint-disable comments must include a reason in the form `<disable directive> -- <reason>`.",
924
+ node: comment
925
+ });
926
+ }
927
+ } };
928
+ },
929
+ meta: { type: "problem" }
930
+ };
931
+ //#endregion
932
+ //#region src/rules/require-import-extension.ts
933
+ const rule$6 = {
934
+ create: (context) => createImportExtensionListeners(context, (value) => {
935
+ const match = matchImportPath(value);
936
+ return match !== null && (match.extension === "" || match.directory) ? value : null;
937
+ }, "Use an explicit extension in relative and subpath imports"),
938
+ meta: {
939
+ schema: [],
940
+ type: "problem"
941
+ }
942
+ };
943
+ //#endregion
944
+ //#region src/rules/require-top-level-decoder.ts
945
+ const TOP_LEVEL_DECODER_MESSAGE = "Hoist schema decoder construction to module top level and call the cached function inside this scope. Building the decoder per call re-runs the schema compilation on every invocation.";
946
+ const matchMemberCallByPrefix = (node, namespace, prefix) => {
947
+ if (!Predicate.isObject(node) || node["type"] !== "CallExpression" || !Predicate.isObject(node["callee"]) || node["callee"]["type"] !== "MemberExpression" || Predicate.isTruthy(node["callee"]["computed"])) return false;
948
+ const { object, property } = node["callee"];
949
+ if (!Predicate.isObject(object) || object["type"] !== "Identifier" || !hasProperty(object, "name") || object.name !== namespace) return false;
950
+ if (!Predicate.isObject(property) || property["type"] !== "Identifier" || !hasProperty(property, "name") || !Predicate.isString(property.name)) return false;
951
+ return property.name.startsWith(prefix);
952
+ };
953
+ const isHoistableDecoderCall = (node) => matchMemberCallByPrefix(node, "Schema", "decode") || matchMemberCallByPrefix(node, "HttpClientResponse", "schema");
954
+ const rule$5 = {
955
+ create(context) {
956
+ const functionStack = [];
957
+ const enterFunction = () => {
958
+ functionStack.push(true);
959
+ };
960
+ const exitFunction = () => {
961
+ functionStack.pop();
962
+ };
963
+ return {
964
+ ArrowFunctionExpression: enterFunction,
965
+ "ArrowFunctionExpression:exit": exitFunction,
966
+ CallExpression(node) {
967
+ if (Predicate.isNullish(functionStack[0]) || !isReportable(node)) return;
968
+ if (isHoistableDecoderCall(node)) context.report({
969
+ message: TOP_LEVEL_DECODER_MESSAGE,
970
+ node
971
+ });
972
+ },
973
+ FunctionDeclaration: enterFunction,
974
+ "FunctionDeclaration:exit": exitFunction,
975
+ FunctionExpression: enterFunction,
976
+ "FunctionExpression:exit": exitFunction
977
+ };
978
+ },
979
+ meta: { type: "problem" }
980
+ };
981
+ //#endregion
982
+ //#region src/upstream/effect/no-bigint-literals.ts
983
+ const rule$4 = {
984
+ meta: {
985
+ type: "problem",
986
+ docs: { description: "Disallow bigint literals" },
987
+ fixable: "code"
988
+ },
989
+ create(context) {
990
+ return { Literal(node) {
991
+ if (typeof node.value === "bigint") {
992
+ const fixedSource = `BigInt("${node.value}")`;
993
+ context.report({
994
+ node,
995
+ message: "BigInt literals are not allowed",
996
+ fix: (fixer) => fixer.replaceText(node, fixedSource)
997
+ });
998
+ }
999
+ } };
1000
+ }
1001
+ };
1002
+ //#endregion
1003
+ //#region src/upstream/effect/no-import-from-barrel-package.ts
1004
+ const extensions = [
1005
+ ".ts",
1006
+ ".tsx",
1007
+ ".mts",
1008
+ ".cts",
1009
+ ".js",
1010
+ ".jsx",
1011
+ ".mjs",
1012
+ ".cjs"
1013
+ ];
1014
+ function getModuleName(specifier) {
1015
+ return specifier.imported.type === "Identifier" ? specifier.imported.name : specifier.imported.value;
1016
+ }
1017
+ function isRelativeImport$1(source) {
1018
+ return source.startsWith("./") || source.startsWith("../");
1019
+ }
1020
+ function hasIndexFile(dirPath) {
1021
+ for (const ext of extensions) if (fs.existsSync(path.join(dirPath, `index${ext}`))) return true;
1022
+ return false;
1023
+ }
1024
+ function isIndexImport(importPath) {
1025
+ const basename = path.basename(importPath);
1026
+ return basename === "index" || /^index\.(ts|tsx|js|jsx|mts|cts|mjs|cjs)$/.test(basename);
1027
+ }
1028
+ function resolvesToBarrel(importSource, currentFile) {
1029
+ const dir = path.dirname(currentFile);
1030
+ const resolved = path.resolve(dir, importSource);
1031
+ if (isIndexImport(importSource)) return true;
1032
+ if (hasIndexFile(resolved)) return true;
1033
+ return false;
1034
+ }
1035
+ function createBarrelMatcher(options) {
1036
+ const patterns = (options.checkPatterns ?? []).map((p) => new RegExp(p));
1037
+ const checkRelative = options.checkRelativeIndexImports !== false;
1038
+ return (source, currentFile) => {
1039
+ if (isRelativeImport$1(source)) return checkRelative && resolvesToBarrel(source, currentFile);
1040
+ for (const pattern of patterns) if (pattern.test(source)) return true;
1041
+ return false;
1042
+ };
1043
+ }
1044
+ const rule$3 = {
1045
+ meta: {
1046
+ type: "suggestion",
1047
+ docs: { description: "Disallow importing from barrel files (index.ts), encourage importing specific modules instead" },
1048
+ schema: [{
1049
+ type: "object",
1050
+ properties: {
1051
+ checkPatterns: {
1052
+ type: "array",
1053
+ items: { type: "string" },
1054
+ description: "Regex patterns to match barrel imports"
1055
+ },
1056
+ checkRelativeIndexImports: {
1057
+ type: "boolean",
1058
+ description: "Whether to check relative imports that resolve to index files"
1059
+ }
1060
+ },
1061
+ additionalProperties: false
1062
+ }]
1063
+ },
1064
+ create(context) {
1065
+ const currentFile = context.filename;
1066
+ const isBarrelImport = createBarrelMatcher(context.options[0] ?? {});
1067
+ return { ImportDeclaration(node) {
1068
+ if (node.importKind === "type") return;
1069
+ const importSource = node.source.value;
1070
+ if (!isBarrelImport(importSource, currentFile)) return;
1071
+ const namespaceSpecifiers = [];
1072
+ const namedValueSpecifiers = [];
1073
+ for (const specifier of node.specifiers) if (specifier.type === "ImportNamespaceSpecifier") namespaceSpecifiers.push(specifier);
1074
+ else if (specifier.type === "ImportSpecifier") {
1075
+ if (specifier.importKind !== "type") namedValueSpecifiers.push(specifier);
1076
+ }
1077
+ for (const specifier of namespaceSpecifiers) context.report({
1078
+ node: specifier,
1079
+ message: `Do not use namespace import from barrel file "${importSource}", import from specific modules instead`
1080
+ });
1081
+ for (const specifier of namedValueSpecifiers) {
1082
+ const moduleName = getModuleName(specifier);
1083
+ const localName = specifier.local.name;
1084
+ const message = isRelativeImport$1(importSource) ? `Do not import "${moduleName}" from barrel file "${importSource}", import from specific module instead` : `Use import * as ${localName} from "${importSource}/${moduleName}" instead`;
1085
+ context.report({
1086
+ node: specifier,
1087
+ message
1088
+ });
1089
+ }
1090
+ } };
1091
+ }
1092
+ };
1093
+ //#endregion
1094
+ //#region src/upstream/effect/no-js-extension-imports.ts
1095
+ const jsExtensions = [
1096
+ ".js",
1097
+ ".jsx",
1098
+ ".mjs",
1099
+ ".cjs"
1100
+ ];
1101
+ const extensionMap = {
1102
+ ".js": ".ts",
1103
+ ".jsx": ".tsx",
1104
+ ".mjs": ".mts",
1105
+ ".cjs": ".cts"
1106
+ };
1107
+ function isRelativeImport(source) {
1108
+ return source.startsWith("./") || source.startsWith("../");
1109
+ }
1110
+ function getJsExtension(source) {
1111
+ for (const ext of jsExtensions) if (source.endsWith(ext)) return ext;
1112
+ }
1113
+ const rule$2 = {
1114
+ meta: {
1115
+ type: "problem",
1116
+ docs: { description: "Disallow .js, .jsx, .mjs and .cjs extensions in relative imports, use .ts, .tsx, .mts or .cts instead" },
1117
+ fixable: "code"
1118
+ },
1119
+ create(context) {
1120
+ function checkSource(source) {
1121
+ const value = source.value;
1122
+ if (!isRelativeImport(value)) return;
1123
+ const ext = getJsExtension(value);
1124
+ if (!ext) return;
1125
+ const tsExt = extensionMap[ext];
1126
+ const fixedSource = value.slice(0, -ext.length) + tsExt;
1127
+ context.report({
1128
+ node: source,
1129
+ message: `Use "${tsExt}" extension instead of "${ext}" for relative imports`,
1130
+ fix: (fixer) => fixer.replaceTextRange(source.range, JSON.stringify(fixedSource))
1131
+ });
1132
+ }
1133
+ function handleImportDeclaration(node) {
1134
+ checkSource(node.source);
1135
+ }
1136
+ function handleExportAllDeclaration(node) {
1137
+ checkSource(node.source);
1138
+ }
1139
+ function handleExportNamedDeclaration(node) {
1140
+ if (node.source) checkSource(node.source);
1141
+ }
1142
+ return {
1143
+ ImportDeclaration: handleImportDeclaration,
1144
+ ExportAllDeclaration: handleExportAllDeclaration,
1145
+ ExportNamedDeclaration: handleExportNamedDeclaration
1146
+ };
1147
+ }
1148
+ };
1149
+ //#endregion
1150
+ //#region src/upstream/effect/no-opaque-instance-fields.ts
1151
+ const SCHEMA_SOURCES = /* @__PURE__ */ new Set(["effect", "effect/Schema"]);
1152
+ const SCHEMA_NAMESPACE_SOURCES = /* @__PURE__ */ new Set(["effect/Schema"]);
1153
+ const rule$1 = {
1154
+ meta: {
1155
+ type: "problem",
1156
+ docs: { description: "Disallow instance members in Schema.Opaque classes" }
1157
+ },
1158
+ create(context) {
1159
+ const schemaIdentifiers = /* @__PURE__ */ new Set();
1160
+ const opaqueIdentifiers = /* @__PURE__ */ new Set();
1161
+ function isSchemaOpaqueExtension(node) {
1162
+ const sc = node.superClass;
1163
+ if (!sc || sc.type !== "CallExpression") return false;
1164
+ const inner = sc.callee;
1165
+ if (!inner || inner.type !== "CallExpression") return false;
1166
+ return isOpaqueCallee(inner.callee);
1167
+ }
1168
+ function isOpaqueCallee(node) {
1169
+ if (!node) return false;
1170
+ if (node.type === "Identifier") return opaqueIdentifiers.has(node.name);
1171
+ if (node.type !== "MemberExpression") return false;
1172
+ if (node.property?.type !== "Identifier" || node.property.name !== "Opaque") return false;
1173
+ return isSchemaObject(node.object);
1174
+ }
1175
+ function isSchemaObject(node) {
1176
+ if (!node) return false;
1177
+ if (node.type === "Identifier") return schemaIdentifiers.has(node.name);
1178
+ return false;
1179
+ }
1180
+ function checkClass(node) {
1181
+ if (!isSchemaOpaqueExtension(node)) return;
1182
+ for (const element of node.body.body) if (element.type === "PropertyDefinition" && !element.static) context.report({
1183
+ node: element,
1184
+ message: "Classes extending Schema.Opaque must not have instance members"
1185
+ });
1186
+ else if (element.type === "MethodDefinition" && !element.static) context.report({
1187
+ node: element,
1188
+ message: "Classes extending Schema.Opaque must not have instance members"
1189
+ });
1190
+ }
1191
+ return {
1192
+ ImportDeclaration(node) {
1193
+ if (node.importKind === "type") return;
1194
+ const source = node.source.value;
1195
+ if (typeof source !== "string" || !SCHEMA_SOURCES.has(source)) return;
1196
+ for (const specifier of node.specifiers) if (specifier.type === "ImportNamespaceSpecifier") {
1197
+ if (SCHEMA_NAMESPACE_SOURCES.has(source)) schemaIdentifiers.add(specifier.local.name);
1198
+ } else if (specifier.type === "ImportSpecifier" && specifier.importKind !== "type") {
1199
+ if (specifier.imported.type !== "Identifier") continue;
1200
+ const importedName = specifier.imported.name;
1201
+ if (importedName === "Schema") schemaIdentifiers.add(specifier.local.name);
1202
+ else if (importedName === "Opaque") opaqueIdentifiers.add(specifier.local.name);
1203
+ }
1204
+ },
1205
+ ClassDeclaration: checkClass,
1206
+ ClassExpression: checkClass
1207
+ };
1208
+ }
1209
+ };
1210
+ //#endregion
1211
+ //#region src/upstream/effect/no-unused-internal.ts
1212
+ const cache = /* @__PURE__ */ new Map();
1213
+ const sourceExtensions = /* @__PURE__ */ new Set([".ts"]);
1214
+ function getCwd(context) {
1215
+ return context.cwd ?? context.getCwd?.() ?? process.cwd();
1216
+ }
1217
+ function normalizePathName(filename) {
1218
+ return path.resolve(filename).split(path.sep).join("/");
1219
+ }
1220
+ function rangeNode(range) {
1221
+ return { range: [range[0], range[1]] };
1222
+ }
1223
+ function isSourceFile(fileName) {
1224
+ return sourceExtensions.has(path.extname(fileName)) && !fileName.endsWith(".d.ts");
1225
+ }
1226
+ function findSourceFiles(cwd) {
1227
+ const packagesDir = path.join(cwd, "packages");
1228
+ if (!fs.existsSync(packagesDir)) return [];
1229
+ const files = [];
1230
+ const visit = (directory) => {
1231
+ for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
1232
+ const entryPath = path.join(directory, entry.name);
1233
+ if (entry.isDirectory()) {
1234
+ if (entry.name !== "dist" && entry.name !== "build" && entry.name !== "node_modules") visit(entryPath);
1235
+ } else if (entry.isFile() && isSourceFile(entryPath) && normalizePathName(entryPath).includes("/src/")) files.push(entryPath);
1236
+ }
1237
+ };
1238
+ visit(packagesDir);
1239
+ return files;
1240
+ }
1241
+ function findWorkspacePackages(cwd) {
1242
+ const packagesDir = path.join(cwd, "packages");
1243
+ const packages = /* @__PURE__ */ new Map();
1244
+ if (!fs.existsSync(packagesDir)) return packages;
1245
+ const visit = (directory) => {
1246
+ const packageJson = path.join(directory, "package.json");
1247
+ if (fs.existsSync(packageJson)) {
1248
+ try {
1249
+ const json = JSON.parse(fs.readFileSync(packageJson, "utf8"));
1250
+ if (typeof json.name === "string") packages.set(json.name, directory);
1251
+ } catch {}
1252
+ return;
1253
+ }
1254
+ for (const entry of fs.readdirSync(directory, { withFileTypes: true })) if (entry.isDirectory() && entry.name !== "node_modules" && entry.name !== "dist" && entry.name !== "build") visit(path.join(directory, entry.name));
1255
+ };
1256
+ visit(packagesDir);
1257
+ return packages;
1258
+ }
1259
+ function resolveSourceFile(basePath) {
1260
+ const candidates = path.extname(basePath) === ".ts" ? [basePath] : [
1261
+ basePath,
1262
+ `${basePath}.ts`,
1263
+ path.join(basePath, "index.ts")
1264
+ ];
1265
+ for (const candidate of candidates) if (fs.existsSync(candidate) && isSourceFile(candidate)) return normalizePathName(candidate);
1266
+ }
1267
+ function resolveModule(source, containingFile, workspacePackages) {
1268
+ if (source.startsWith("./") || source.startsWith("../")) return resolveSourceFile(path.resolve(path.dirname(containingFile), source));
1269
+ let packageName;
1270
+ for (const name of workspacePackages.keys()) if (source === name || source.startsWith(`${name}/`)) {
1271
+ if (packageName === void 0 || name.length > packageName.length) packageName = name;
1272
+ }
1273
+ if (packageName === void 0) return void 0;
1274
+ const packageRoot = workspacePackages.get(packageName);
1275
+ if (packageRoot === void 0) return void 0;
1276
+ if (source === packageName) return resolveSourceFile(path.join(packageRoot, "src", "index.ts"));
1277
+ const subpath = source.slice(packageName.length + 1);
1278
+ return resolveSourceFile(path.join(packageRoot, "src", subpath));
1279
+ }
1280
+ function hasModifier(node, kind) {
1281
+ return ts.canHaveModifiers(node) && (ts.getModifiers(node) ?? []).some((modifier) => modifier.kind === kind);
1282
+ }
1283
+ function hasExportModifier(node) {
1284
+ return hasModifier(node, ts.SyntaxKind.ExportKeyword);
1285
+ }
1286
+ function hasPrivateOrProtectedModifier(node) {
1287
+ return hasModifier(node, ts.SyntaxKind.PrivateKeyword) || hasModifier(node, ts.SyntaxKind.ProtectedKeyword);
1288
+ }
1289
+ function hasInternalJSDoc(node) {
1290
+ return ts.getJSDocTags(node).some((tag) => tag.tagName.getText() === "internal");
1291
+ }
1292
+ function hasInternalApiJSDoc(node) {
1293
+ if (hasInternalJSDoc(node)) return true;
1294
+ if (ts.isVariableDeclaration(node)) return hasInternalJSDoc(node.parent.parent);
1295
+ if (ts.isBindingElement(node) && ts.isVariableDeclaration(node.parent.parent)) return hasInternalJSDoc(node.parent.parent.parent);
1296
+ return false;
1297
+ }
1298
+ function isInternalPath(fileName) {
1299
+ return /\/src\/(?:.*\/)?internal\//.test(normalizePathName(fileName));
1300
+ }
1301
+ function collectBindingNames(name, out) {
1302
+ if (ts.isIdentifier(name)) {
1303
+ out.push(name);
1304
+ return;
1305
+ }
1306
+ for (const element of name.elements) if (ts.isBindingElement(element)) collectBindingNames(element.name, out);
1307
+ }
1308
+ function getTopLevelDeclarationNameNodes(node) {
1309
+ if ((ts.isFunctionDeclaration(node) || ts.isClassDeclaration(node) || ts.isInterfaceDeclaration(node) || ts.isTypeAliasDeclaration(node) || ts.isEnumDeclaration(node) || ts.isModuleDeclaration(node)) && node.name !== void 0 && ts.isIdentifier(node.name)) return [node.name];
1310
+ if (ts.isVariableStatement(node)) {
1311
+ const names = [];
1312
+ for (const declaration of node.declarationList.declarations) collectBindingNames(declaration.name, names);
1313
+ return names;
1314
+ }
1315
+ return [];
1316
+ }
1317
+ function getDeclarationForName(node, name) {
1318
+ if (!ts.isVariableStatement(node)) return node;
1319
+ let result = node;
1320
+ const visit = (current) => {
1321
+ if (ts.isVariableDeclaration(current) || ts.isBindingElement(current)) {
1322
+ const names = [];
1323
+ collectBindingNames(current.name, names);
1324
+ if (names.includes(name)) {
1325
+ result = current;
1326
+ return;
1327
+ }
1328
+ }
1329
+ ts.forEachChild(current, visit);
1330
+ };
1331
+ visit(node.declarationList);
1332
+ return result;
1333
+ }
1334
+ function isImportOrExportBinding(identifier) {
1335
+ const parent = identifier.parent;
1336
+ return ts.isImportSpecifier(parent) && (parent.name === identifier || parent.propertyName === identifier) || ts.isImportClause(parent) && parent.name === identifier || ts.isNamespaceImport(parent) && parent.name === identifier || ts.isExportSpecifier(parent) && (parent.name === identifier || parent.propertyName === identifier);
1337
+ }
1338
+ function isDeclarationName(identifier) {
1339
+ const parent = identifier.parent;
1340
+ return ts.isVariableDeclaration(parent) && parent.name === identifier || ts.isBindingElement(parent) && parent.name === identifier || ts.isParameter(parent) && parent.name === identifier || ts.isFunctionDeclaration(parent) && parent.name === identifier || ts.isClassDeclaration(parent) && parent.name === identifier || ts.isInterfaceDeclaration(parent) && parent.name === identifier || ts.isTypeAliasDeclaration(parent) && parent.name === identifier || ts.isEnumDeclaration(parent) && parent.name === identifier || ts.isEnumMember(parent) && parent.name === identifier || ts.isModuleDeclaration(parent) && parent.name === identifier;
1341
+ }
1342
+ function isNonReferenceName(identifier) {
1343
+ const parent = identifier.parent;
1344
+ return isImportOrExportBinding(identifier) || isDeclarationName(identifier) || ts.isPropertyAccessExpression(parent) && parent.name === identifier || ts.isPropertyAssignment(parent) && parent.name === identifier || ts.isPropertyDeclaration(parent) && parent.name === identifier || ts.isPropertySignature(parent) && parent.name === identifier || ts.isMethodDeclaration(parent) && parent.name === identifier || ts.isMethodSignature(parent) && parent.name === identifier || ts.isGetAccessorDeclaration(parent) && parent.name === identifier || ts.isSetAccessorDeclaration(parent) && parent.name === identifier;
1345
+ }
1346
+ function isInside(node, container) {
1347
+ if (node.getSourceFile() !== container.getSourceFile()) return false;
1348
+ return node.getStart() >= container.getStart() && node.getEnd() <= container.getEnd();
1349
+ }
1350
+ function getExports(fileInfos, fileName, exportName) {
1351
+ if (fileName === void 0) return [];
1352
+ return fileInfos.get(fileName)?.internalExports.get(exportName) ?? [];
1353
+ }
1354
+ function getReExportedInternals(fileInfos, fileInfo, workspacePackages, specifier) {
1355
+ const exportDeclaration = specifier.parent.parent;
1356
+ const importedName = (specifier.propertyName ?? specifier.name).text;
1357
+ if (exportDeclaration.moduleSpecifier !== void 0 && ts.isStringLiteral(exportDeclaration.moduleSpecifier)) return getExports(fileInfos, resolveModule(exportDeclaration.moduleSpecifier.text, fileInfo.sourceFile.fileName, workspacePackages), importedName);
1358
+ const imported = fileInfo.imports.get(importedName);
1359
+ return [...fileInfo.internalExports.get(importedName) ?? [], ...getExports(fileInfos, imported?.fileName, imported?.importedName ?? "")];
1360
+ }
1361
+ function markUsed(exports, node) {
1362
+ for (const internal of exports) if (!isInside(node, internal.declaration)) internal.used = true;
1363
+ }
1364
+ function addFileDiagnostic(diagnosticsByFile, diagnostic) {
1365
+ const normalized = normalizePathName(diagnostic.fileName);
1366
+ const diagnostics = diagnosticsByFile.get(normalized) ?? [];
1367
+ diagnostics.push(diagnostic);
1368
+ diagnosticsByFile.set(normalized, diagnostics);
1369
+ }
1370
+ function addInternalExport(fileInfo, internal) {
1371
+ const exports = fileInfo.internalExports.get(internal.name) ?? [];
1372
+ exports.push(internal);
1373
+ fileInfo.internalExports.set(internal.name, exports);
1374
+ }
1375
+ function collectFileInfo(sourceFile, workspacePackages) {
1376
+ const fileInfo = {
1377
+ fileName: normalizePathName(sourceFile.fileName),
1378
+ sourceFile,
1379
+ imports: /* @__PURE__ */ new Map(),
1380
+ namespaceImports: /* @__PURE__ */ new Map(),
1381
+ internalExports: /* @__PURE__ */ new Map(),
1382
+ publicDeclarations: []
1383
+ };
1384
+ const publicDeclarationSet = /* @__PURE__ */ new Set();
1385
+ const isInternalFile = isInternalPath(sourceFile.fileName);
1386
+ for (const statement of sourceFile.statements) {
1387
+ if (ts.isImportDeclaration(statement) && ts.isStringLiteral(statement.moduleSpecifier)) {
1388
+ const importedFile = resolveModule(statement.moduleSpecifier.text, sourceFile.fileName, workspacePackages);
1389
+ const importClause = statement.importClause;
1390
+ if (importedFile === void 0 || importClause === void 0) continue;
1391
+ if (importClause.name !== void 0) fileInfo.imports.set(importClause.name.text, {
1392
+ fileName: importedFile,
1393
+ importedName: "default"
1394
+ });
1395
+ const namedBindings = importClause.namedBindings;
1396
+ if (namedBindings === void 0) continue;
1397
+ if (ts.isNamespaceImport(namedBindings)) fileInfo.namespaceImports.set(namedBindings.name.text, importedFile);
1398
+ else for (const specifier of namedBindings.elements) {
1399
+ const importedName = (specifier.propertyName ?? specifier.name).text;
1400
+ fileInfo.imports.set(specifier.name.text, {
1401
+ fileName: importedFile,
1402
+ importedName
1403
+ });
1404
+ }
1405
+ continue;
1406
+ }
1407
+ if (!isInternalFile && ts.isExportDeclaration(statement) && !hasInternalApiJSDoc(statement) && statement.exportClause !== void 0 && ts.isNamedExports(statement.exportClause)) {
1408
+ fileInfo.publicDeclarations.push(statement);
1409
+ continue;
1410
+ }
1411
+ if (!hasExportModifier(statement)) continue;
1412
+ const names = getTopLevelDeclarationNameNodes(statement);
1413
+ if (names.length === 0) continue;
1414
+ const statementIsInternal = hasInternalApiJSDoc(statement);
1415
+ for (const name of names) {
1416
+ const declaration = getDeclarationForName(statement, name);
1417
+ if (statementIsInternal || hasInternalApiJSDoc(declaration)) addInternalExport(fileInfo, {
1418
+ fileName: sourceFile.fileName,
1419
+ declaration,
1420
+ name: name.text,
1421
+ range: [name.getStart(sourceFile), name.getEnd()],
1422
+ used: false
1423
+ });
1424
+ else if (!isInternalFile && !publicDeclarationSet.has(statement)) {
1425
+ fileInfo.publicDeclarations.push(statement);
1426
+ publicDeclarationSet.add(statement);
1427
+ }
1428
+ }
1429
+ }
1430
+ return fileInfo;
1431
+ }
1432
+ function markNamespaceReference(fileInfos, fileInfo, namespace, name) {
1433
+ markUsed(getExports(fileInfos, fileInfo.namespaceImports.get(namespace.text), name.text), name);
1434
+ }
1435
+ function scanUsage(fileInfos, fileInfo, workspacePackages) {
1436
+ const visit = (node) => {
1437
+ if (ts.isExportSpecifier(node)) markUsed(getReExportedInternals(fileInfos, fileInfo, workspacePackages, node), node);
1438
+ else if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.expression) && ts.isIdentifier(node.name)) markNamespaceReference(fileInfos, fileInfo, node.expression, node.name);
1439
+ else if (ts.isQualifiedName(node) && ts.isIdentifier(node.left)) markNamespaceReference(fileInfos, fileInfo, node.left, node.right);
1440
+ else if (ts.isIdentifier(node) && !isNonReferenceName(node)) {
1441
+ markUsed(fileInfo.internalExports.get(node.text) ?? [], node);
1442
+ const imported = fileInfo.imports.get(node.text);
1443
+ markUsed(getExports(fileInfos, imported?.fileName, imported?.importedName ?? ""), node);
1444
+ }
1445
+ ts.forEachChild(node, visit);
1446
+ };
1447
+ visit(fileInfo.sourceFile);
1448
+ }
1449
+ function findInternalReferences(fileInfos, fileInfo, diagnostics, node) {
1450
+ const visit = (current) => {
1451
+ if (ts.isPropertyAccessExpression(current) && ts.isIdentifier(current.expression)) {
1452
+ const importedFile = fileInfo.namespaceImports.get(current.expression.text);
1453
+ for (const internal of getExports(fileInfos, importedFile, current.name.text)) diagnostics.push({
1454
+ fileName: fileInfo.fileName,
1455
+ range: [current.name.getStart(), current.name.getEnd()],
1456
+ message: `Do not reference @internal export "${internal.name}" in a public exported type signature`
1457
+ });
1458
+ } else if (ts.isQualifiedName(current) && ts.isIdentifier(current.left)) {
1459
+ const importedFile = fileInfo.namespaceImports.get(current.left.text);
1460
+ for (const internal of getExports(fileInfos, importedFile, current.right.text)) diagnostics.push({
1461
+ fileName: fileInfo.fileName,
1462
+ range: [current.right.getStart(), current.right.getEnd()],
1463
+ message: `Do not reference @internal export "${internal.name}" in a public exported type signature`
1464
+ });
1465
+ } else if (ts.isIdentifier(current) && !isNonReferenceName(current)) {
1466
+ const localExports = fileInfo.internalExports.get(current.text) ?? [];
1467
+ const imported = fileInfo.imports.get(current.text);
1468
+ const importedExports = getExports(fileInfos, imported?.fileName, imported?.importedName ?? "");
1469
+ for (const internal of [...localExports, ...importedExports]) diagnostics.push({
1470
+ fileName: fileInfo.fileName,
1471
+ range: [current.getStart(), current.getEnd()],
1472
+ message: `Do not reference @internal export "${internal.name}" in a public exported type signature`
1473
+ });
1474
+ }
1475
+ ts.forEachChild(current, visit);
1476
+ };
1477
+ visit(node);
1478
+ }
1479
+ function scanTypeParameters(fileInfos, fileInfo, diagnostics, typeParameters) {
1480
+ if (typeParameters === void 0) return;
1481
+ for (const typeParameter of typeParameters) {
1482
+ if (typeParameter.constraint !== void 0) findInternalReferences(fileInfos, fileInfo, diagnostics, typeParameter.constraint);
1483
+ if (typeParameter.default !== void 0) findInternalReferences(fileInfos, fileInfo, diagnostics, typeParameter.default);
1484
+ }
1485
+ }
1486
+ function scanParameterTypes(fileInfos, fileInfo, diagnostics, parameters) {
1487
+ for (const parameter of parameters) if (parameter.type !== void 0) findInternalReferences(fileInfos, fileInfo, diagnostics, parameter.type);
1488
+ }
1489
+ function scanFunctionLikeSignature(fileInfos, fileInfo, diagnostics, node) {
1490
+ scanTypeParameters(fileInfos, fileInfo, diagnostics, node.typeParameters);
1491
+ scanParameterTypes(fileInfos, fileInfo, diagnostics, node.parameters);
1492
+ if (node.type !== void 0) findInternalReferences(fileInfos, fileInfo, diagnostics, node.type);
1493
+ }
1494
+ function scanClassMemberSignature(fileInfos, fileInfo, diagnostics, member) {
1495
+ if (hasInternalJSDoc(member)) return;
1496
+ if (hasPrivateOrProtectedModifier(member)) return;
1497
+ if (ts.isMethodDeclaration(member) || ts.isConstructorDeclaration(member) || ts.isGetAccessorDeclaration(member) || ts.isSetAccessorDeclaration(member)) scanFunctionLikeSignature(fileInfos, fileInfo, diagnostics, member);
1498
+ else if (ts.isPropertyDeclaration(member) && member.type !== void 0) findInternalReferences(fileInfos, fileInfo, diagnostics, member.type);
1499
+ }
1500
+ function scanInterfaceMemberSignature(fileInfos, fileInfo, diagnostics, member) {
1501
+ if (hasInternalJSDoc(member)) return;
1502
+ if (ts.isMethodSignature(member) || ts.isCallSignatureDeclaration(member) || ts.isConstructSignatureDeclaration(member)) scanFunctionLikeSignature(fileInfos, fileInfo, diagnostics, member);
1503
+ else if (ts.isPropertySignature(member) && member.type !== void 0) findInternalReferences(fileInfos, fileInfo, diagnostics, member.type);
1504
+ else if (ts.isIndexSignatureDeclaration(member)) scanFunctionLikeSignature(fileInfos, fileInfo, diagnostics, member);
1505
+ }
1506
+ function scanPublicSignature(fileInfos, fileInfo, diagnostics, node, workspacePackages) {
1507
+ if (ts.isFunctionDeclaration(node)) scanFunctionLikeSignature(fileInfos, fileInfo, diagnostics, node);
1508
+ else if (ts.isVariableStatement(node)) {
1509
+ for (const declaration of node.declarationList.declarations) if (declaration.type !== void 0) findInternalReferences(fileInfos, fileInfo, diagnostics, declaration.type);
1510
+ } else if (ts.isTypeAliasDeclaration(node)) {
1511
+ scanTypeParameters(fileInfos, fileInfo, diagnostics, node.typeParameters);
1512
+ findInternalReferences(fileInfos, fileInfo, diagnostics, node.type);
1513
+ } else if (ts.isInterfaceDeclaration(node)) {
1514
+ scanTypeParameters(fileInfos, fileInfo, diagnostics, node.typeParameters);
1515
+ for (const heritage of node.heritageClauses ?? []) for (const type of heritage.types) findInternalReferences(fileInfos, fileInfo, diagnostics, type);
1516
+ for (const member of node.members) scanInterfaceMemberSignature(fileInfos, fileInfo, diagnostics, member);
1517
+ } else if (ts.isClassDeclaration(node)) {
1518
+ scanTypeParameters(fileInfos, fileInfo, diagnostics, node.typeParameters);
1519
+ for (const heritage of node.heritageClauses ?? []) for (const type of heritage.types) findInternalReferences(fileInfos, fileInfo, diagnostics, type);
1520
+ for (const member of node.members) scanClassMemberSignature(fileInfos, fileInfo, diagnostics, member);
1521
+ } else if (ts.isExportDeclaration(node) && node.exportClause !== void 0 && ts.isNamedExports(node.exportClause)) for (const specifier of node.exportClause.elements) for (const internal of getReExportedInternals(fileInfos, fileInfo, workspacePackages, specifier)) {
1522
+ const name = specifier.propertyName ?? specifier.name;
1523
+ diagnostics.push({
1524
+ fileName: fileInfo.fileName,
1525
+ range: [name.getStart(), name.getEnd()],
1526
+ message: `Do not re-export @internal export "${internal.name}" from a public module`
1527
+ });
1528
+ }
1529
+ }
1530
+ function analyze(cwd) {
1531
+ const normalizedCwd = normalizePathName(cwd);
1532
+ const cached = cache.get(normalizedCwd);
1533
+ if (cached !== void 0) return cached;
1534
+ const workspacePackages = findWorkspacePackages(cwd);
1535
+ const fileInfos = /* @__PURE__ */ new Map();
1536
+ for (const fileName of findSourceFiles(cwd)) {
1537
+ const fileInfo = collectFileInfo(ts.createSourceFile(fileName, fs.readFileSync(fileName, "utf8"), ts.ScriptTarget.Latest, true), workspacePackages);
1538
+ fileInfos.set(fileInfo.fileName, fileInfo);
1539
+ }
1540
+ for (const fileInfo of fileInfos.values()) scanUsage(fileInfos, fileInfo, workspacePackages);
1541
+ const diagnosticsByFile = /* @__PURE__ */ new Map();
1542
+ for (const fileInfo of fileInfos.values()) {
1543
+ const diagnostics = [];
1544
+ for (const declaration of fileInfo.publicDeclarations) scanPublicSignature(fileInfos, fileInfo, diagnostics, declaration, workspacePackages);
1545
+ for (const diagnostic of diagnostics) addFileDiagnostic(diagnosticsByFile, diagnostic);
1546
+ for (const exportsForName of fileInfo.internalExports.values()) for (const internal of exportsForName) if (!internal.used) addFileDiagnostic(diagnosticsByFile, {
1547
+ fileName: internal.fileName,
1548
+ range: internal.range,
1549
+ message: `@internal export "${internal.name}" is not used by production sources`
1550
+ });
1551
+ }
1552
+ for (const diagnostics of diagnosticsByFile.values()) diagnostics.sort((self, that) => self.range[0] - that.range[0]);
1553
+ const analysis = { diagnosticsByFile };
1554
+ cache.set(normalizedCwd, analysis);
1555
+ return analysis;
1556
+ }
1557
+ //#endregion
1558
+ //#region src/index.ts
1559
+ const plugin = {
1560
+ meta: { name: "rules" },
1561
+ rules: {
1562
+ "no-bigint-literals": rule$4,
1563
+ "no-import-from-barrel-package": rule$3,
1564
+ "no-js-extension-imports": rule$2,
1565
+ "no-opaque-instance-fields": rule$1,
1566
+ "no-unused-internal": {
1567
+ meta: {
1568
+ type: "problem",
1569
+ docs: { description: "Disallow unused @internal exports, public re-exports, and references from public type signatures" }
1570
+ },
1571
+ create(context) {
1572
+ const diagnostics = analyze(getCwd(context)).diagnosticsByFile.get(normalizePathName(context.filename)) ?? [];
1573
+ return { Program() {
1574
+ for (const diagnostic of diagnostics) context.report({
1575
+ node: rangeNode(diagnostic.range),
1576
+ message: diagnostic.message
1577
+ });
1578
+ } };
1579
+ }
1580
+ },
1581
+ "consistent-import-extension": rule$32,
1582
+ "require-import-extension": rule$6,
1583
+ "force-array-empty": rule$31,
1584
+ "force-iterable-empty": rule$30,
1585
+ "force-predicate": rule$29,
1586
+ "force-string-empty": rule$28,
1587
+ "force-ts-extension": rule$33,
1588
+ "no-effect-import-as": rule$27,
1589
+ "no-effect-runtime-run": rule$26,
1590
+ "no-effect-subpath-import": rule$25,
1591
+ "no-error-cause-option": rule$24,
1592
+ "no-error-property-access": rule$23,
1593
+ "no-eslint-disable-comments": rule$22,
1594
+ "no-fetch": rule$21,
1595
+ "no-instanceof-error": rule$20,
1596
+ "no-js-date": rule$19,
1597
+ "no-jsx-script-tag": rule$18,
1598
+ "no-let": rule$17,
1599
+ "no-node-imports": rule$16,
1600
+ "no-option-tag-comparison": rule$15,
1601
+ "no-raw-hono-create-middleware": rule$14,
1602
+ "no-redundant-alias": rule$13,
1603
+ "no-string-style": rule$12,
1604
+ "no-sync-decode": rule$11,
1605
+ "no-type-predicate": rule$10,
1606
+ "prefer-is-nullish": rule$9,
1607
+ "prefer-non-unknown-decode": rule$8,
1608
+ "require-disable-reason": rule$7,
1609
+ "require-top-level-decoder": rule$5
1610
+ }
1611
+ };
1612
+ //#endregion
1613
+ export { compatibilityRuleNames, plugin as default, effectRuleNames, typescriptRuleNames };