@zgeoff/oxlint-config 0.2.8 → 0.2.9
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 +11 -7
- package/import-zones.js +38 -1
- package/package.json +1 -1
- package/resolve-import-target.js +8 -1
package/README.md
CHANGED
|
@@ -122,17 +122,21 @@ the boundaries between them. A file belongs to every zone its path matches, so z
|
|
|
122
122
|
Each entry has a `name`, which starts its report, an optional `reason`, which ends it, and optional
|
|
123
123
|
`from` zones and `ignore` globs that limit which importing files it judges.
|
|
124
124
|
|
|
125
|
-
- `edges` judge an import that resolves to a file: relative,
|
|
126
|
-
through its `exports` under `conditions` plus
|
|
127
|
-
|
|
128
|
-
target in
|
|
129
|
-
must match), and `allowWithin: "src/*"` exempts an
|
|
125
|
+
- `edges` judge an import that resolves to a file: relative, with any bundler query such as `?url`
|
|
126
|
+
dropped, or the package's own name resolved through its `exports` under `conditions` plus
|
|
127
|
+
`default`. A target in a `to` zone fails unless it is also in an `allow` zone; with `allow` alone,
|
|
128
|
+
a target in none of the `allow` zones fails, a target in no zone included. `allowTypeOnly` exempts
|
|
129
|
+
type-only imports (`true`, or globs the target must match), and `allowWithin: "src/*"` exempts an
|
|
130
|
+
import inside the importer's own `src/<name>/`.
|
|
130
131
|
- `modules` restrict a package or builtin (`node:` prefix optional, subpaths included) to the
|
|
131
|
-
`allow` zones; `allowTypeOnly: true` exempts type-only imports.
|
|
132
|
+
`allow` zones; `allowTypeOnly: true` exempts type-only imports. A name that ends in `*` restricts
|
|
133
|
+
every specifier that starts with the text before it, such as `@scope/*`, and `node:*` restricts
|
|
134
|
+
every builtin.
|
|
132
135
|
- `globals` restrict a call to a global, bare or through `globalThis`, `self` or `window`.
|
|
133
136
|
- `unzoned` reports a file in a `from` zone that belongs to none of `zones`.
|
|
134
137
|
- `unresolved` reports a relative or self-referencing import that resolves to no file, and a dynamic
|
|
135
|
-
`import()` or `require()` whose specifier is computed.
|
|
138
|
+
`import()`, `require()` or `import.meta.require()` whose specifier is computed. Bun's
|
|
139
|
+
`import.meta.require` used as a value counts as computed too.
|
|
136
140
|
|
|
137
141
|
```jsonc
|
|
138
142
|
{
|
package/import-zones.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isBuiltin } from 'node:module';
|
|
1
2
|
import { relative, sep } from 'node:path';
|
|
2
3
|
import findRepoRoot from './find-repo-root.js';
|
|
3
4
|
import importZonesSchema from './import-zones-schema.js';
|
|
@@ -114,12 +115,25 @@ function isRestrictedModule(entry, specifier) {
|
|
|
114
115
|
const name = toModuleName(specifier);
|
|
115
116
|
|
|
116
117
|
return entry.modules.some((module) => {
|
|
118
|
+
if (module.endsWith('*')) {
|
|
119
|
+
return isPrefixMatch(module.slice(0, -1), specifier);
|
|
120
|
+
}
|
|
121
|
+
|
|
117
122
|
const restricted = toModuleName(module);
|
|
118
123
|
|
|
119
124
|
return name === restricted || name.startsWith(`${restricted}/`);
|
|
120
125
|
});
|
|
121
126
|
}
|
|
122
127
|
|
|
128
|
+
// `node:*` names every builtin, which a specifier may write without the prefix
|
|
129
|
+
function isPrefixMatch(prefix, specifier) {
|
|
130
|
+
if (specifier.startsWith(prefix)) {
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return prefix === 'node:' && isBuiltin(specifier);
|
|
135
|
+
}
|
|
136
|
+
|
|
123
137
|
function toModuleName(specifier) {
|
|
124
138
|
return specifier.replace(/^node:/u, '');
|
|
125
139
|
}
|
|
@@ -235,6 +249,18 @@ function isTypeOnlyExport(node) {
|
|
|
235
249
|
);
|
|
236
250
|
}
|
|
237
251
|
|
|
252
|
+
function isImportMetaRequire(node) {
|
|
253
|
+
return (
|
|
254
|
+
node.type === 'MemberExpression' &&
|
|
255
|
+
!node.computed &&
|
|
256
|
+
node.object.type === 'MetaProperty' &&
|
|
257
|
+
node.object.meta.name === 'import' &&
|
|
258
|
+
node.object.property.name === 'meta' &&
|
|
259
|
+
node.property.type === 'Identifier' &&
|
|
260
|
+
node.property.name === 'require'
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
|
|
238
264
|
const importZones = {
|
|
239
265
|
meta: {
|
|
240
266
|
type: 'problem',
|
|
@@ -284,10 +310,21 @@ const importZones = {
|
|
|
284
310
|
CallExpression(node) {
|
|
285
311
|
checkGlobalCall(file, node);
|
|
286
312
|
|
|
287
|
-
if (
|
|
313
|
+
if (
|
|
314
|
+
(node.callee.type === 'Identifier' && node.callee.name === 'require') ||
|
|
315
|
+
isImportMetaRequire(node.callee)
|
|
316
|
+
) {
|
|
288
317
|
checkImport(file, { node, source: node.arguments[0], typeOnly: false });
|
|
289
318
|
}
|
|
290
319
|
},
|
|
320
|
+
|
|
321
|
+
// Bun's import.meta.require used as a value, such as `const load =
|
|
322
|
+
// import.meta.require`, loads modules no specifier names
|
|
323
|
+
MemberExpression(node) {
|
|
324
|
+
if (isImportMetaRequire(node) && node.parent?.callee !== node) {
|
|
325
|
+
emitUnresolved(file, node, { messageId: 'computed', data: {} });
|
|
326
|
+
}
|
|
327
|
+
},
|
|
291
328
|
};
|
|
292
329
|
},
|
|
293
330
|
};
|
package/package.json
CHANGED
package/resolve-import-target.js
CHANGED
|
@@ -9,7 +9,7 @@ const sourceExtensions = { '.js': ['.ts', '.tsx'], '.mjs': ['.mts'], '.cjs': ['.
|
|
|
9
9
|
// own name resolves through its `exports`, and `#` names through its `imports`.
|
|
10
10
|
export default function resolveImportTarget(filename, specifier, settings) {
|
|
11
11
|
if (isPathSpecifier(specifier)) {
|
|
12
|
-
return toTarget(findImportedFile(filename, specifier, settings.extensions));
|
|
12
|
+
return toTarget(findImportedFile(filename, toFileSpecifier(specifier), settings.extensions));
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
const manifest = findPackageManifest(dirname(filename), settings.root);
|
|
@@ -40,6 +40,13 @@ function resolveManifestTarget(manifest, specifier, conditions) {
|
|
|
40
40
|
return { kind: 'module', specifier };
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
// a bundler query such as Vite's `./styles.css?url` names the file before it
|
|
44
|
+
function toFileSpecifier(specifier) {
|
|
45
|
+
const query = specifier.indexOf('?');
|
|
46
|
+
|
|
47
|
+
return query === -1 ? specifier : specifier.slice(0, query);
|
|
48
|
+
}
|
|
49
|
+
|
|
43
50
|
function toTarget(path) {
|
|
44
51
|
return path === null ? { kind: 'missing' } : { kind: 'file', path };
|
|
45
52
|
}
|