Document that package.json aliases may target only direct subfolders of src (#21)
Follow-up to #20, which was merged before this landed. bot-agents has no `package.json` `imports` aliases (`src/` is flat and everything imports relatively), so no code changes. This records the new rule in the docs: - `.agents/memory/imports-aliases-barrels.md`: aliases may target only a direct subfolder of `src/` (its `index.ts` or a `#x/*` pattern); nothing outside `src/`, not `src/` itself, not deeper folders; such code imports relatively. - `.agents/memory/tests-layout-vitest.md`: `tests/` reach the public entry through a relative import, not a `#plugin` alias. - `.agents/skills/migrate-deno-repo/SKILL.md` and `AGENTS.md`: same rule. `vp check`, `vp test`, and `damem doctor` pass. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Reviewed-on: #21 Reviewed-by: bot <noreply@capsulizers.com> Co-authored-by: Danny Kim <temeddix@gmail.com> Co-committed-by: Danny Kim <temeddix@gmail.com>
This commit was merged in pull request #21.
This commit is contained in:
+65
-31
@@ -1,8 +1,7 @@
|
||||
/**
|
||||
* `project` — lint rules this repository holds its own source to. Deno lint
|
||||
* ran here with its `recommended` rules and no plugins; the Oxlint categories
|
||||
* in `vite.config.ts` plus the rule list below keep at least that coverage.
|
||||
* Its rules of its own are `no-disable-comments` and `no-non-ts-imports`.
|
||||
* `project` — lint rules this repository holds its own source to, on top of
|
||||
* the Oxlint categories in `vite.config.ts`. Its rules of its own are
|
||||
* `no-disable-comments` and `no-asset-imports`.
|
||||
*
|
||||
* Loaded by `vite.config.ts` as an Oxlint `jsPlugins` entry.
|
||||
*
|
||||
@@ -10,7 +9,7 @@
|
||||
*/
|
||||
|
||||
import type { LanguageOptions, RuleDefinition, RuleVisitor, TextSourceCode } from "@eslint/core";
|
||||
import type { TSESTree } from "@typescript-eslint/types";
|
||||
import { AST_NODE_TYPES, type TSESTree } from "@typescript-eslint/types";
|
||||
import type { DummyRuleMap } from "vite-plus/lint";
|
||||
|
||||
/** The source code both hosts hand a rule, with the comment list. */
|
||||
@@ -73,11 +72,19 @@ const noDisableCommentsRule: ProjectRule = {
|
||||
const PATH_SPECIFIER_PATTERN: RegExp = /^[./#]/u;
|
||||
|
||||
/**
|
||||
* Whether `source` names something other than a `.ts` module: a query string
|
||||
* such as `?raw`, or a final path segment with any other extension. Bare
|
||||
* package names are left alone, dots and all, as are extensionless paths.
|
||||
* Script module extensions an import may name: our `.ts` files and `.js`,
|
||||
* `.mts`, or `.mjs` package subpaths. `.cts`, `.cjs`, `.tsx`, and `.jsx` are
|
||||
* not among them.
|
||||
*/
|
||||
function isNonTsSource(source: string): boolean {
|
||||
const SCRIPT_EXTENSIONS: ReadonlySet<string> = new Set([".ts", ".js", ".mts", ".mjs"]);
|
||||
|
||||
/**
|
||||
* Whether `source` names an asset rather than a script module: a query string
|
||||
* such as `?raw`, or a final path segment whose extension, from its last dot,
|
||||
* is not `.ts`, `.js`, `.mts`, or `.mjs`. Bare package names are left alone,
|
||||
* dots and all, as are extensionless paths.
|
||||
*/
|
||||
function isAssetSource(source: string): boolean {
|
||||
if (source.includes("?")) {
|
||||
return true;
|
||||
}
|
||||
@@ -92,30 +99,34 @@ function isNonTsSource(source: string): boolean {
|
||||
if (lastSegment === "." || lastSegment === ".." || !lastSegment.includes(".")) {
|
||||
return false;
|
||||
}
|
||||
return !lastSegment.endsWith(".ts");
|
||||
const extension: string = lastSegment.slice(lastSegment.lastIndexOf("."));
|
||||
return !SCRIPT_EXTENSIONS.has(extension);
|
||||
}
|
||||
|
||||
/**
|
||||
* `no-non-ts-imports` — rejects importing anything but a `.ts` module: a
|
||||
* `no-asset-imports` — rejects importing anything but a script module: a
|
||||
* source path, static or a dynamic `import()` with a string literal, ending in
|
||||
* another extension (`.css`, `.json`, `.svg`, `.js`, `.tsx`) or carrying a
|
||||
* query string (`?raw`, `?url`), and any import or export with import
|
||||
* attributes. Bare package names, `#` aliases, and `node:` builtins without an
|
||||
* extension pass; package subpaths are checked like paths.
|
||||
* an extension other than `.ts`, `.js`, `.mts`, or `.mjs` (`.css`, `.json`,
|
||||
* `.svg`, `.jsx`, `.tsx`, `.cjs`) or carrying a query string (`?raw`, `?url`),
|
||||
* and any import or export with import attributes. `.js`, `.mts`, and `.mjs`
|
||||
* cover package subpaths such as `lit/decorators.js` or
|
||||
* `pdfjs-dist/legacy/build/pdf.mjs`; our own files are still `.ts` only. Bare
|
||||
* package names, `#` aliases, and `node:` builtins
|
||||
* without an extension pass; package subpaths are checked like paths.
|
||||
*/
|
||||
const noNonTsImportsRule: ProjectRule = {
|
||||
const noAssetImportsRule: ProjectRule = {
|
||||
meta: {
|
||||
type: "problem",
|
||||
docs: { description: "Disallow importing modules other than .ts files" },
|
||||
docs: { description: "Disallow importing assets instead of .ts, .js, .mts, or .mjs modules" },
|
||||
schema: [],
|
||||
messages: {
|
||||
extension: "Only .ts modules may be imported.",
|
||||
extension: "Only .ts, .js, .mts and .mjs modules may be imported.",
|
||||
attributes: "Import attributes are not allowed.",
|
||||
},
|
||||
},
|
||||
create(context) {
|
||||
function checkSource(source: TSESTree.StringLiteral): void {
|
||||
if (isNonTsSource(source.value)) {
|
||||
if (isAssetSource(source.value)) {
|
||||
context.report({ node: source, messageId: "extension" });
|
||||
}
|
||||
}
|
||||
@@ -138,7 +149,7 @@ const noNonTsImportsRule: ProjectRule = {
|
||||
ExportNamedDeclaration: checkDeclaration,
|
||||
ExportAllDeclaration: checkDeclaration,
|
||||
ImportExpression(node: TSESTree.ImportExpression): void {
|
||||
if (node.source.type === "Literal" && typeof node.source.value === "string") {
|
||||
if (node.source.type === AST_NODE_TYPES.Literal && typeof node.source.value === "string") {
|
||||
checkSource(node.source);
|
||||
}
|
||||
if (node.options !== null) {
|
||||
@@ -150,10 +161,9 @@ const noNonTsImportsRule: ProjectRule = {
|
||||
};
|
||||
|
||||
/**
|
||||
* This repository's own rule list, spread by `vite.config.ts`: Deno's
|
||||
* `recommended` rules that sit outside the Oxlint categories, plus the
|
||||
* template's extras. Built-in Oxlint rule ids sit here too, so
|
||||
* `vite.config.ts` lists no rule by name.
|
||||
* This repository's own rule list, spread by `vite.config.ts`: rules that
|
||||
* sit outside the Oxlint categories, plus the template's extras. Built-in
|
||||
* Oxlint rule ids sit here too, so `vite.config.ts` lists no rule by name.
|
||||
*/
|
||||
const rules: DummyRuleMap = {
|
||||
// The explicit-types template's `camelcase` stand-in: no `_` inside a name
|
||||
@@ -164,7 +174,7 @@ const rules: DummyRuleMap = {
|
||||
"^_*[^_]*_*$|^[^a-z]*$",
|
||||
{ properties: false, classFields: false, onlyDeclarations: false, ignoreDestructuring: true },
|
||||
],
|
||||
// Deno's `recommended` rules outside the categories.
|
||||
// Rules outside the categories.
|
||||
"no-array-constructor": "error",
|
||||
"no-case-declarations": "error",
|
||||
"no-empty": "error",
|
||||
@@ -189,8 +199,7 @@ const rules: DummyRuleMap = {
|
||||
"typescript/prefer-as-const": "error",
|
||||
"typescript/prefer-namespace-keyword": "error",
|
||||
"typescript/triple-slash-reference": "error",
|
||||
// Deno's `no-window`, `no-process-global`, and `no-node-globals`: on Node,
|
||||
// these come from an explicit `node:` import instead of the global scope.
|
||||
// On Node, these come from an explicit `node:` import instead of the global scope.
|
||||
"no-restricted-globals": [
|
||||
"error",
|
||||
"window",
|
||||
@@ -202,14 +211,39 @@ const rules: DummyRuleMap = {
|
||||
],
|
||||
// The explicit-types template's extras.
|
||||
"import/no-cycle": "error",
|
||||
// `../` is banned in every file; anything above a file needs a `#` alias.
|
||||
"import/no-relative-parent-imports": "error",
|
||||
"typescript/consistent-type-imports": "error",
|
||||
"typescript/no-import-type-side-effects": "error",
|
||||
"typescript/no-non-null-assertion": "error",
|
||||
// Deno's `ban-untagged-ignore` and `ban-unused-ignore`, made stricter: no
|
||||
// disable comments at all.
|
||||
// No disable comments at all.
|
||||
"project/no-disable-comments": "error",
|
||||
"project/no-non-ts-imports": "error",
|
||||
"project/no-asset-imports": "error",
|
||||
"unicorn/no-abusive-eslint-disable": "error",
|
||||
// Size and complexity limits match Deno's: this repo's `deno lint` ran the
|
||||
// `recommended` set with no config file, so no size or complexity rule
|
||||
// applied and none applies here. Each Oxlint limit rule, from a category or
|
||||
// not, is off:
|
||||
// - `complexity`: Deno had no `max-complexity`.
|
||||
// - `max-lines`: Deno had no `max-file-lines`.
|
||||
// - `max-params`: Deno had no `max-params`.
|
||||
// - `id-length`: Deno had no `max-identifier-length`.
|
||||
// - `no-nested-ternary`: Deno had no `max-nest-ternaries`.
|
||||
// - `max-lines-per-function`, `max-classes-per-file`, `max-depth`,
|
||||
// `max-nested-callbacks`, `max-statements`, `import/max-dependencies`,
|
||||
// `unicorn/max-nested-calls`: Deno had none of these.
|
||||
complexity: "off",
|
||||
"max-lines": "off",
|
||||
"max-params": "off",
|
||||
"id-length": "off",
|
||||
"no-nested-ternary": "off",
|
||||
"max-lines-per-function": "off",
|
||||
"max-classes-per-file": "off",
|
||||
"max-depth": "off",
|
||||
"max-nested-callbacks": "off",
|
||||
"max-statements": "off",
|
||||
"import/max-dependencies": "off",
|
||||
"unicorn/max-nested-calls": "off",
|
||||
// Pedantic, but Node's and the web's own types (`Response`, `Stats`,
|
||||
// `RequestInit`) are mutable, so no parameter of theirs can pass; the
|
||||
// explicit-types template and the app repos turn it off too.
|
||||
@@ -224,7 +258,7 @@ const plugin = {
|
||||
meta: { name: "project" },
|
||||
rules: {
|
||||
"no-disable-comments": noDisableCommentsRule,
|
||||
"no-non-ts-imports": noNonTsImportsRule,
|
||||
"no-asset-imports": noAssetImportsRule,
|
||||
},
|
||||
configs: { project: { rules } },
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user