@shivaedev/quality 0.27.1 → 0.28.1
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/CHANGELOG.md +12 -0
- package/README.md +22 -2
- package/biome/declarations.json +5 -0
- package/biome/preset.json +3 -0
- package/dist/biome/exceptionConfig.js +1 -1
- package/dist/biome/exceptionConfig.js.map +1 -1
- package/dist/biome/report.js +1 -1
- package/dist/biome/report.js.map +1 -1
- package/dist/inventory/walk.js +1 -1
- package/dist/inventory/walk.js.map +1 -1
- package/dist/rules/builtIn.d.ts +7 -1
- package/dist/rules/builtIn.d.ts.map +1 -1
- package/dist/rules/builtIn.js +16 -0
- package/dist/rules/builtIn.js.map +1 -1
- package/dist/rules/stories/authSql.d.ts +4 -0
- package/dist/rules/stories/authSql.d.ts.map +1 -0
- package/dist/rules/stories/authSql.js +102 -0
- package/dist/rules/stories/authSql.js.map +1 -0
- package/dist/rules/stories/httpStatus.d.ts +4 -0
- package/dist/rules/stories/httpStatus.d.ts.map +1 -0
- package/dist/rules/stories/httpStatus.js +47 -0
- package/dist/rules/stories/httpStatus.js.map +1 -0
- package/dist/rules/stories/matchesAny.d.ts +2 -0
- package/dist/rules/stories/matchesAny.d.ts.map +1 -0
- package/dist/rules/stories/matchesAny.js +5 -0
- package/dist/rules/stories/matchesAny.js.map +1 -0
- package/dist/rules/stories/namedValues.d.ts +2 -0
- package/dist/rules/stories/namedValues.d.ts.map +1 -0
- package/dist/rules/stories/namedValues.js +15 -0
- package/dist/rules/stories/namedValues.js.map +1 -0
- package/dist/rules/stories/noExpect.d.ts +2 -0
- package/dist/rules/stories/noExpect.d.ts.map +1 -0
- package/dist/rules/stories/noExpect.js +33 -0
- package/dist/rules/stories/noExpect.js.map +1 -0
- package/dist/rules/stories/noLimitImports.d.ts +2 -0
- package/dist/rules/stories/noLimitImports.d.ts.map +1 -0
- package/dist/rules/stories/noLimitImports.js +66 -0
- package/dist/rules/stories/noLimitImports.js.map +1 -0
- package/dist/rules/stories/queueSql.d.ts +2 -0
- package/dist/rules/stories/queueSql.d.ts.map +1 -0
- package/dist/rules/stories/queueSql.js +15 -0
- package/dist/rules/stories/queueSql.js.map +1 -0
- package/dist/rules/stories/specHelpers.d.ts +2 -0
- package/dist/rules/stories/specHelpers.d.ts.map +1 -0
- package/dist/rules/stories/specHelpers.js +9 -0
- package/dist/rules/stories/specHelpers.js.map +1 -0
- package/dist/rules/stories/sqlText.d.ts +8 -0
- package/dist/rules/stories/sqlText.d.ts.map +1 -0
- package/dist/rules/stories/sqlText.js +86 -0
- package/dist/rules/stories/sqlText.js.map +1 -0
- package/dist/rules/stories/supportImports.d.ts +4 -0
- package/dist/rules/stories/supportImports.d.ts.map +1 -0
- package/dist/rules/stories/supportImports.js +28 -0
- package/dist/rules/stories/supportImports.js.map +1 -0
- package/dist/rules/stories/syntax.d.ts +11 -0
- package/dist/rules/stories/syntax.d.ts.map +1 -0
- package/dist/rules/stories/syntax.js +71 -0
- package/dist/rules/stories/syntax.js.map +1 -0
- package/dist/testProjects.js +1 -1
- package/dist/testProjects.js.map +1 -1
- package/package.json +1 -1
- package/src/biome/exceptionConfig.ts +1 -1
- package/src/biome/report.ts +1 -1
- package/src/inventory/walk.ts +1 -1
- package/src/rules/builtIn.ts +16 -0
- package/src/rules/stories/authSql.ts +117 -0
- package/src/rules/stories/httpStatus.ts +56 -0
- package/src/rules/stories/matchesAny.ts +5 -0
- package/src/rules/stories/namedValues.ts +21 -0
- package/src/rules/stories/noExpect.ts +39 -0
- package/src/rules/stories/noLimitImports.ts +80 -0
- package/src/rules/stories/queueSql.ts +18 -0
- package/src/rules/stories/specHelpers.ts +10 -0
- package/src/rules/stories/sqlText.ts +100 -0
- package/src/rules/stories/supportImports.ts +31 -0
- package/src/rules/stories/syntax.ts +80 -0
- package/src/testProjects.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.28.1 - 2026-10-19
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Exclude `.worktrees` directories from all Vitest projects, repository discovery and Biome checks so worktree copies are not tested or linted from the parent checkout.
|
|
8
|
+
|
|
9
|
+
## 0.28.0 - 2026-10-18
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Enforce story boundaries: queue and Better Auth SQL ownership, expectations outside test-support, helpers outside specs, an allowlist of public modules for test-support, HTTP error translation at named edge modules, named numeric expectations and stories independent of implementation caps. Configure `boundaries/auth-sql.options.owners`, `boundaries/http-status.options.edge` and `tests/support-imports.options.modules` with repository paths or glob patterns.
|
|
14
|
+
|
|
3
15
|
## 0.27.1 - 2026-10-18
|
|
4
16
|
|
|
5
17
|
### Changed
|
package/README.md
CHANGED
|
@@ -74,7 +74,7 @@ import { defineConfig } from "@shivaedev/quality/config.ts";
|
|
|
74
74
|
export default defineConfig({ sources: ["src"] });
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
-
When a config exists, its folder is the root for paths and hook scripts. Without one, the current directory is the root. `sources` chooses the files the source rules read; a missing source stops the run. Directory discovery skips untracked files ignored by git and the `.git` and `node_modules` directories. Tracked files remain checked even when an ignore pattern matches them; a folder named `generated/` does not exempt authored code. Some repository rules, such as manifest sorting, inspect the whole repository even when `sources` names only `src`.
|
|
77
|
+
When a config exists, its folder is the root for paths and hook scripts. Without one, the current directory is the root. `sources` chooses the files the source rules read; a missing source stops the run. Directory discovery skips untracked files ignored by git and the `.git`, `.worktrees` and `node_modules` directories. Tracked files remain checked even when an ignore pattern matches them; a folder named `generated/` does not exempt authored code. Some repository rules, such as manifest sorting, inspect the whole repository even when `sources` names only `src`.
|
|
78
78
|
|
|
79
79
|
Quality discovers each app’s `components.json` and resolves `aliases.ui` through its TypeScript paths or package imports. That folder belongs to the shadcn CLI: source rules and Biome lint, formatting and fixes skip it by default. Neighbouring authored folders stay checked. This leaves TypeScript’s inputs unchanged, so type checking still covers the stock components.
|
|
80
80
|
|
|
@@ -134,6 +134,26 @@ Every package tests its real engine through its own story kit, so setup and acti
|
|
|
134
134
|
|
|
135
135
|
Quality's `tests/story-setup` rule reports top-level test functions named with the words `seed`, `make`, `build` or `setup`, and fixture-writing calls imported from Node's `fs` or `fs/promises`. It leaves source and `test-support/` files alone. This is a check for those syntax patterns; a passing test file still needs review of what it tests.
|
|
136
136
|
|
|
137
|
+
Specs keep expectations visible. `tests/spec-helpers` moves all module-level helper functions out of specs and into the kit; `tests/no-expect-in-support` moves `expect` calls into the spec. `tests/named-values` rejects numeric literals passed to `toBe` or `toHaveLength` in specs: assert the observed items or give the value a domain name. `tests/no-limit-imports` rejects importing `MAX_*` constants from a `limits` module into specs, so a story proves behavior instead of copying an implementation cap.
|
|
138
|
+
|
|
139
|
+
`tests/support-imports` checks resolved repository imports from `test-support/` against `options.modules`, an allowlist of repository-relative module paths or glob patterns. Imports within test-support and imports of external packages remain available for the harness. Name only the public surface the kit drives, such as the host, schemas and queue definitions. The default empty list allows no production repository modules; aliases, dynamic imports and re-exports resolve through the same import graph as the other import rules.
|
|
140
|
+
|
|
141
|
+
`boundaries/queue-sql` rejects SQL mentioning the private `pgboss.` schema. Apps use their queue definitions and let workers process jobs; there is no queue-purge API by design. `boundaries/auth-sql` rejects SQL accessing Better Auth's `user`, `account`, `session` and `verification` tables. Apps use platform's auth API; `options.owners` names platform's own auth implementation and its migrations. These rules inspect SQL templates, literal query calls and query variables, and inventoried `.sql` files. They do not evaluate arbitrary runtime SQL construction.
|
|
142
|
+
|
|
143
|
+
`boundaries/http-status` rejects comparisons with HTTP error status numbers, switch cases and literal status-list membership outside `options.edge`. Domain code handles typed errors; the named HTTP edge translates them into transport responses. Process exit codes remain ordinary domain values.
|
|
144
|
+
|
|
145
|
+
Declare these architectural facts in the repository's quality config; paths and patterns are relative to that config's directory:
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
export default defineConfig({
|
|
149
|
+
rules: {
|
|
150
|
+
"boundaries/auth-sql": { options: { owners: ["platform/auth/**", "platform/auth-migrations/**"] } },
|
|
151
|
+
"boundaries/http-status": { options: { edge: ["src/http/**"] } },
|
|
152
|
+
"tests/support-imports": { options: { modules: ["src/host.ts", "src/schemas.ts", "src/queues.ts"] } },
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
```
|
|
156
|
+
|
|
137
157
|
### 3. Every day: repair findings and keep debt current
|
|
138
158
|
|
|
139
159
|
```sh
|
|
@@ -272,7 +292,7 @@ import { defineConfig } from "vitest/config";
|
|
|
272
292
|
export default defineConfig({ test: testProjects() });
|
|
273
293
|
```
|
|
274
294
|
|
|
275
|
-
`testProjects` runs unit tests and specs in Node and `.dom` tests and specs in test-story's DOM environment by default. The DOM environment keeps Node's host constructors separate from the happy-dom window, so DOM specs need no project remap. Each test gets 30 seconds instead of Vitest's 5, because tests that start servers, browsers or CLIs take seconds on a busy CI runner. `.slow` tests run only when `--project slow` asks for them. Type tests are excluded from Vitest and belong in the compiler's input.
|
|
295
|
+
`testProjects` runs unit tests and specs in Node and `.dom` tests and specs in test-story's DOM environment by default. The DOM environment keeps Node's host constructors separate from the happy-dom window, so DOM specs need no project remap. Each test gets 30 seconds instead of Vitest's 5, because tests that start servers, browsers or CLIs take seconds on a busy CI runner. `.slow` tests run only when `--project slow` asks for them. Type tests are excluded from Vitest and belong in the compiler's input. Every project excludes `**/.worktrees/**` so a checkout does not collect specs from its worktrees.
|
|
276
296
|
|
|
277
297
|
Coverage is opt-in: `testProjects({ coverage: true })` enables Vitest's V8 provider across the selected projects. Install `@vitest/coverage-v8` at the same version as Vitest. The report includes unvisited `src/**/*.ts` and `src/**/*.tsx` files and excludes declarations, tests, specs and `test-support`. To customize it, pass native Vitest coverage options, for example `testProjects({ coverage: { reporter: ["lcov", "text-summary"] } })`. No separate coverage config is needed.
|
|
278
298
|
|
package/biome/declarations.json
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"includes": ["**", "!**/.worktrees"],
|
|
4
|
+
"reason": "Worktrees are independent checkouts checked from their own roots; walking them from the parent repeats findings and fixes.",
|
|
5
|
+
"rule": "files/includes"
|
|
6
|
+
},
|
|
2
7
|
{
|
|
3
8
|
"includes": ["**"],
|
|
4
9
|
"reason": "TypeScript reports unused variables through noUnusedLocals in the shared tsconfig, so Biome would report each one twice.",
|
package/biome/preset.json
CHANGED
|
@@ -40,7 +40,7 @@ export async function withExceptionConfig(root, declarations, run) {
|
|
|
40
40
|
const previousOverrides = Array.isArray(own.overrides) ? own.overrides : [];
|
|
41
41
|
const generated = {
|
|
42
42
|
...own,
|
|
43
|
-
files: { ...files, includes: [...previousIncludes, ...includes.filter((pattern) => pattern !== "**"), `!${name}`] },
|
|
43
|
+
files: { ...files, includes: [...previousIncludes, ...includes.filter((pattern) => pattern !== "**"), "!**/.worktrees", `!${name}`] },
|
|
44
44
|
overrides: [...previousOverrides, ...overrides],
|
|
45
45
|
};
|
|
46
46
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exceptionConfig.js","sourceRoot":"","sources":["../../src/biome/exceptionConfig.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"exceptionConfig.js","sourceRoot":"","sources":["../../src/biome/exceptionConfig.ts"],"names":[],"mappings":"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"}
|
package/dist/biome/report.js
CHANGED
|
@@ -31,7 +31,7 @@ export async function biomeReport(root, args, exceptions = []) {
|
|
|
31
31
|
const [report, tracked] = await Promise.all([reportFor(root, args, ["."], exceptions), ignoredTrackedPaths(root)]);
|
|
32
32
|
const paths = tracked
|
|
33
33
|
.map((path) => relative(root, path))
|
|
34
|
-
.filter((path) => !path.split(sep).some((part) => part === ".git" || part === "node_modules"));
|
|
34
|
+
.filter((path) => !path.split(sep).some((part) => part === ".git" || part === ".worktrees" || part === "node_modules"));
|
|
35
35
|
const extra = paths.length === 0 ? undefined : await reportFor(root, [...args, "--vcs-enabled=false"], paths, exceptions);
|
|
36
36
|
const diagnostics = [...report.diagnostics, ...(extra?.diagnostics ?? [])];
|
|
37
37
|
const unique = [...new Map(diagnostics.map((diagnostic) => [JSON.stringify(diagnostic), diagnostic])).values()];
|
package/dist/biome/report.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/biome/report.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/biome/report.ts"],"names":[],"mappings":"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"}
|
package/dist/inventory/walk.js
CHANGED
|
@@ -3,7 +3,7 @@ import { Effect, FileSystem } from "effect";
|
|
|
3
3
|
import { FilesystemFailure, orWhenAbsent, readOptionalText } from "./filesystem.js";
|
|
4
4
|
import { emptyScope, insideKept, verdictFor, withIgnoreFile } from "./ignoreScope.js";
|
|
5
5
|
import { trackedPaths } from "./trackedPaths.js";
|
|
6
|
-
const SKIPPED = new Set([".git", "node_modules"]);
|
|
6
|
+
const SKIPPED = new Set([".git", ".worktrees", "node_modules"]);
|
|
7
7
|
export function ignoreScopeAt(dir, inherited = emptyScope) {
|
|
8
8
|
return Effect.map(readOptionalText(join(dir, ".gitignore")), (contents) => contents === undefined || contents === "" ? inherited : withIgnoreFile(inherited, dir, contents));
|
|
9
9
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"walk.js","sourceRoot":"","sources":["../../src/inventory/walk.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACpF,OAAO,EAAE,UAAU,EAAoB,UAAU,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACxG,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"walk.js","sourceRoot":"","sources":["../../src/inventory/walk.ts"],"names":[],"mappings":"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"}
|
package/dist/rules/builtIn.d.ts
CHANGED
|
@@ -28,5 +28,11 @@ export declare const builtInRules: readonly [import("../rule.ts").Rule<"structur
|
|
|
28
28
|
readonly suites?: readonly string[];
|
|
29
29
|
}>, import("../rule.ts").Rule<"tests/colocated", {
|
|
30
30
|
readonly suites?: readonly string[];
|
|
31
|
-
}>, import("../rule.ts").Rule<"tests/story-setup", undefined>, import("../rule.ts").Rule<"tests/story-specs", undefined
|
|
31
|
+
}>, import("../rule.ts").Rule<"tests/story-setup", undefined>, import("../rule.ts").Rule<"tests/story-specs", undefined>, import("../rule.ts").Rule<"boundaries/queue-sql", undefined>, import("../rule.ts").Rule<"boundaries/auth-sql", {
|
|
32
|
+
readonly owners?: readonly string[];
|
|
33
|
+
}>, import("../rule.ts").Rule<"tests/no-expect-in-support", undefined>, import("../rule.ts").Rule<"tests/spec-helpers", undefined>, import("../rule.ts").Rule<"tests/support-imports", {
|
|
34
|
+
readonly modules?: readonly string[];
|
|
35
|
+
}>, import("../rule.ts").Rule<"boundaries/http-status", {
|
|
36
|
+
readonly edge?: readonly string[];
|
|
37
|
+
}>, import("../rule.ts").Rule<"tests/named-values", undefined>, import("../rule.ts").Rule<"tests/no-limit-imports", undefined>];
|
|
32
38
|
//# sourceMappingURL=builtIn.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builtIn.d.ts","sourceRoot":"","sources":["../../src/rules/builtIn.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"builtIn.d.ts","sourceRoot":"","sources":["../../src/rules/builtIn.ts"],"names":[],"mappings":"AA0CA,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+HA0Cf,CAAC"}
|
package/dist/rules/builtIn.js
CHANGED
|
@@ -16,8 +16,16 @@ import { importsManifest } from "#rules/imports/manifest.ts";
|
|
|
16
16
|
import { noTestCode } from "#rules/imports/noTestCode.ts";
|
|
17
17
|
import { importsResolvable } from "#rules/imports/resolvable.ts";
|
|
18
18
|
import { importsRuntime } from "#rules/imports/runtime.ts";
|
|
19
|
+
import { authSql } from "#rules/stories/authSql.ts";
|
|
20
|
+
import { httpStatus } from "#rules/stories/httpStatus.ts";
|
|
21
|
+
import { namedValues } from "#rules/stories/namedValues.ts";
|
|
22
|
+
import { noExpect } from "#rules/stories/noExpect.ts";
|
|
23
|
+
import { noLimitImports } from "#rules/stories/noLimitImports.ts";
|
|
24
|
+
import { queueSql } from "#rules/stories/queueSql.ts";
|
|
19
25
|
import { storySetup } from "#rules/stories/setup.ts";
|
|
26
|
+
import { specHelpers } from "#rules/stories/specHelpers.ts";
|
|
20
27
|
import { storySpecs } from "#rules/stories/specs.ts";
|
|
28
|
+
import { supportImports } from "#rules/stories/supportImports.ts";
|
|
21
29
|
import { biomeOverrides } from "#rules/suppressions/biomeOverrides.ts";
|
|
22
30
|
import { biomeRecommended } from "#rules/suppressions/biomeRecommended.ts";
|
|
23
31
|
import { noDoubleCast } from "#rules/suppressions/noDoubleCast.ts";
|
|
@@ -65,5 +73,13 @@ export const builtInRules = [
|
|
|
65
73
|
testsColocated,
|
|
66
74
|
storySetup,
|
|
67
75
|
storySpecs,
|
|
76
|
+
queueSql,
|
|
77
|
+
authSql,
|
|
78
|
+
noExpect,
|
|
79
|
+
specHelpers,
|
|
80
|
+
supportImports,
|
|
81
|
+
httpStatus,
|
|
82
|
+
namedValues,
|
|
83
|
+
noLimitImports,
|
|
68
84
|
];
|
|
69
85
|
//# sourceMappingURL=builtIn.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builtIn.js","sourceRoot":"","sources":["../../src/rules/builtIn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AACjE,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6CAA6C,CAAC;AACnF,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,MAAM,CAAC,MAAM,YAAY,GAAG;IAC3B,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,eAAe;IACf,aAAa;IACb,QAAQ;IACR,MAAM;IACN,mBAAmB;IACnB,UAAU;IACV,QAAQ;IACR,YAAY;IACZ,oBAAoB;IACpB,cAAc;IACd,gBAAgB;IAChB,KAAK;IACL,YAAY;IACZ,YAAY;IACZ,cAAc;IACd,iBAAiB;IACjB,eAAe;IACf,cAAc;IACd,UAAU;IACV,eAAe;IACf,oBAAoB;IACpB,gBAAgB;IAChB,WAAW;IACX,YAAY;IACZ,UAAU;IACV,WAAW;IACX,cAAc;IACd,UAAU;IACV,UAAU;
|
|
1
|
+
{"version":3,"file":"builtIn.js","sourceRoot":"","sources":["../../src/rules/builtIn.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authSql.d.ts","sourceRoot":"","sources":["../../../src/rules/stories/authSql.ts"],"names":[],"mappings":"AAuGA,eAAO,MAAM,OAAO;;EAalB,CAAC"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
2
|
+
import { defineRule } from "#rule.ts";
|
|
3
|
+
import { matchesAny } from "./matchesAny.js";
|
|
4
|
+
import { sqlTexts } from "./sqlText.js";
|
|
5
|
+
const AuthSqlOptions = Schema.Struct({
|
|
6
|
+
owners: Schema.Array(Schema.String).pipe(Schema.withDecodingDefaultKey(Effect.succeed([]))),
|
|
7
|
+
});
|
|
8
|
+
const TOKENS = /--[^\n]*|\/\*[\s\S]*?\*\/|'(?:''|[^'])*'|"(?:""|[^"])*"|[\w$]+|[.,;()]/gu;
|
|
9
|
+
const TABLE_START = new Set(["from", "join", "update", "into", "table", "truncate", "references", "using"]);
|
|
10
|
+
const TABLE_END = new Set(["where", "group", "order", "having", "limit", "returning", "set", "values", "on", ";"]);
|
|
11
|
+
const SKIP = new Set(["if", "not", "exists", "only", "table"]);
|
|
12
|
+
const AUTH_TABLES = new Set(["user", "account", "session", "verification"]);
|
|
13
|
+
const EXPRESSION_FROM = new Set(["extract", "overlay", "substring", "trim"]);
|
|
14
|
+
const NON_TABLE_TARGETS = new Set([
|
|
15
|
+
"all",
|
|
16
|
+
"database",
|
|
17
|
+
"domain",
|
|
18
|
+
"foreign",
|
|
19
|
+
"function",
|
|
20
|
+
"language",
|
|
21
|
+
"large",
|
|
22
|
+
"parameter",
|
|
23
|
+
"procedure",
|
|
24
|
+
"routine",
|
|
25
|
+
"schema",
|
|
26
|
+
"sequence",
|
|
27
|
+
"tablespace",
|
|
28
|
+
"type",
|
|
29
|
+
]);
|
|
30
|
+
function tableAt(tokens, index) {
|
|
31
|
+
let next = index;
|
|
32
|
+
while (SKIP.has(tokens[next]?.toLowerCase() ?? "")) {
|
|
33
|
+
const only = tokens[next]?.toLowerCase() === "only";
|
|
34
|
+
next += 1;
|
|
35
|
+
if (only && tokens[next] === "(") {
|
|
36
|
+
next += 1;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
while (tokens[next + 1] === ".") {
|
|
40
|
+
next += 2;
|
|
41
|
+
}
|
|
42
|
+
return (tokens[next] ?? "").replaceAll('"', "").toLowerCase();
|
|
43
|
+
}
|
|
44
|
+
function tableBoundary(tokens, index, statementStart, fromIsTable) {
|
|
45
|
+
const word = tokens[index]?.toLowerCase() ?? "";
|
|
46
|
+
const permissions = ["grant", "revoke"].includes(tokens[statementStart]?.toLowerCase() ?? "");
|
|
47
|
+
const roleTarget = permissions && (word === "to" || word === "from");
|
|
48
|
+
const permissionTarget = permissions && word === "on" && !NON_TABLE_TARGETS.has(tokens[index + 1]?.toLowerCase() ?? "");
|
|
49
|
+
const indexTarget = word === "on" && tokens.slice(statementStart, index).some((part) => part.toLowerCase() === "index");
|
|
50
|
+
const tableClause = TABLE_START.has(word) && (word !== "from" || fromIsTable);
|
|
51
|
+
return {
|
|
52
|
+
ends: TABLE_END.has(word) || roleTarget,
|
|
53
|
+
starts: !roleTarget && (tableClause || indexTarget || permissionTarget),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function advanceContext(context, token, index, previous) {
|
|
57
|
+
if (token === ";") {
|
|
58
|
+
context.statementStart = index + 1;
|
|
59
|
+
context.expressionFromDepths.clear();
|
|
60
|
+
}
|
|
61
|
+
if (token === "(") {
|
|
62
|
+
context.depth += 1;
|
|
63
|
+
if (EXPRESSION_FROM.has(previous?.toLowerCase() ?? "")) {
|
|
64
|
+
context.expressionFromDepths.add(context.depth);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (token === ")") {
|
|
68
|
+
context.tablesAtDepth.delete(context.depth);
|
|
69
|
+
context.expressionFromDepths.delete(context.depth);
|
|
70
|
+
context.depth -= 1;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function authTableIn(text) {
|
|
74
|
+
const tokens = [...text.matchAll(TOKENS)]
|
|
75
|
+
.map(([token]) => token)
|
|
76
|
+
.filter((token) => !(token.startsWith("--") || token.startsWith("/*") || token.startsWith("'")));
|
|
77
|
+
const context = { depth: 0, expressionFromDepths: new Set(), statementStart: 0, tablesAtDepth: new Set() };
|
|
78
|
+
return tokens.some((token, index) => {
|
|
79
|
+
advanceContext(context, token, index, tokens[index - 1]);
|
|
80
|
+
const boundary = tableBoundary(tokens, index, context.statementStart, !context.expressionFromDepths.has(context.depth));
|
|
81
|
+
if (boundary.ends) {
|
|
82
|
+
context.tablesAtDepth.delete(context.depth);
|
|
83
|
+
}
|
|
84
|
+
if (boundary.starts) {
|
|
85
|
+
context.tablesAtDepth.add(context.depth);
|
|
86
|
+
}
|
|
87
|
+
return (boundary.starts || (token === "," && context.tablesAtDepth.has(context.depth))) && AUTH_TABLES.has(tableAt(tokens, index + 1));
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
export const authSql = defineRule({
|
|
91
|
+
check: async ({ options, ...inputs }) => (await sqlTexts(inputs))
|
|
92
|
+
.filter((query) => !matchesAny(query.file, options.owners) && authTableIn(query.text))
|
|
93
|
+
.map((query) => ({
|
|
94
|
+
file: query.file,
|
|
95
|
+
line: query.line,
|
|
96
|
+
message: "SQL accesses a Better Auth table (user, account, session or verification). Use platform's auth API; only platform's auth implementation and its migrations, named in the repository's auth-sql owners, own those tables.",
|
|
97
|
+
})),
|
|
98
|
+
description: "Apps use platform's auth API instead of querying or modifying Better Auth's tables.",
|
|
99
|
+
id: "boundaries/auth-sql",
|
|
100
|
+
options: Schema.toStandardSchemaV1(AuthSqlOptions, { parseOptions: { errors: "all", onExcessProperty: "error" } }),
|
|
101
|
+
});
|
|
102
|
+
//# sourceMappingURL=authSql.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authSql.js","sourceRoot":"","sources":["../../../src/rules/stories/authSql.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"httpStatus.d.ts","sourceRoot":"","sources":["../../../src/rules/stories/httpStatus.ts"],"names":[],"mappings":"AA+CA,eAAO,MAAM,UAAU;;EAQrB,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
2
|
+
import ts from "typescript";
|
|
3
|
+
import { defineRule } from "#rule.ts";
|
|
4
|
+
import { matchesAny } from "./matchesAny.js";
|
|
5
|
+
import { memberName, nodesWhere, numericValue, syntaxFindings, unwrapped } from "./syntax.js";
|
|
6
|
+
const MESSAGE = "Branches on an HTTP error status outside the HTTP edge. Handle the typed domain error here and translate it to an HTTP status in the configured edge module.";
|
|
7
|
+
const HttpStatusOptions = Schema.Struct({
|
|
8
|
+
edge: Schema.Array(Schema.String).pipe(Schema.withDecodingDefaultKey(Effect.succeed([]))),
|
|
9
|
+
});
|
|
10
|
+
const COMPARISONS = new Set([
|
|
11
|
+
ts.SyntaxKind.EqualsEqualsToken,
|
|
12
|
+
ts.SyntaxKind.EqualsEqualsEqualsToken,
|
|
13
|
+
ts.SyntaxKind.ExclamationEqualsToken,
|
|
14
|
+
ts.SyntaxKind.ExclamationEqualsEqualsToken,
|
|
15
|
+
ts.SyntaxKind.LessThanToken,
|
|
16
|
+
ts.SyntaxKind.LessThanEqualsToken,
|
|
17
|
+
ts.SyntaxKind.GreaterThanToken,
|
|
18
|
+
ts.SyntaxKind.GreaterThanEqualsToken,
|
|
19
|
+
]);
|
|
20
|
+
function isErrorStatus(node) {
|
|
21
|
+
const number = numericValue(node);
|
|
22
|
+
return number !== undefined && number >= 400 && number <= 599;
|
|
23
|
+
}
|
|
24
|
+
function statusBranch(node) {
|
|
25
|
+
if (ts.isBinaryExpression(node) && COMPARISONS.has(node.operatorToken.kind)) {
|
|
26
|
+
return (memberName(node.left) === "status" && isErrorStatus(node.right)) || (memberName(node.right) === "status" && isErrorStatus(node.left));
|
|
27
|
+
}
|
|
28
|
+
if (ts.isCaseClause(node) && isErrorStatus(node.expression) && ts.isCaseBlock(node.parent) && ts.isSwitchStatement(node.parent.parent)) {
|
|
29
|
+
return memberName(node.parent.parent.expression) === "status";
|
|
30
|
+
}
|
|
31
|
+
if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && node.expression.name.text === "includes") {
|
|
32
|
+
const receiver = unwrapped(node.expression.expression);
|
|
33
|
+
return (ts.isArrayLiteralExpression(receiver)
|
|
34
|
+
&& receiver.elements.some(isErrorStatus)
|
|
35
|
+
&& node.arguments.some((argument) => memberName(argument) === "status"));
|
|
36
|
+
}
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
export const httpStatus = defineRule({
|
|
40
|
+
check: ({ sources, options }) => sources
|
|
41
|
+
.filter((file) => !matchesAny(file.path, options.edge))
|
|
42
|
+
.flatMap((file) => syntaxFindings(file, (source) => nodesWhere(source, statusBranch), MESSAGE)),
|
|
43
|
+
description: "HTTP status numbers belong at the repository's HTTP edge; domain code handles typed errors.",
|
|
44
|
+
id: "boundaries/http-status",
|
|
45
|
+
options: Schema.toStandardSchemaV1(HttpStatusOptions, { parseOptions: { errors: "all", onExcessProperty: "error" } }),
|
|
46
|
+
});
|
|
47
|
+
//# sourceMappingURL=httpStatus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"httpStatus.js","sourceRoot":"","sources":["../../../src/rules/stories/httpStatus.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matchesAny.d.ts","sourceRoot":"","sources":["../../../src/rules/stories/matchesAny.ts"],"names":[],"mappings":"AAEA,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAE7E"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matchesAny.js","sourceRoot":"","sources":["../../../src/rules/stories/matchesAny.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,QAA2B;IACnE,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;AAC/D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"namedValues.d.ts","sourceRoot":"","sources":["../../../src/rules/stories/namedValues.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,WAAW,0DAKtB,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
import { defineRule } from "#rule.ts";
|
|
3
|
+
import { isSpec, memberName, nodesWhere, numericValue, syntaxFindings } from "./syntax.js";
|
|
4
|
+
const MESSAGE = "Passes a numeric literal to toBe or toHaveLength. Assert the observed items, or give the expected value a domain name before asserting it.";
|
|
5
|
+
function numericAssertion(node) {
|
|
6
|
+
return (ts.isCallExpression(node)
|
|
7
|
+
&& ["toBe", "toHaveLength"].includes(memberName(node.expression) ?? "")
|
|
8
|
+
&& node.arguments.some((argument) => numericValue(argument) !== undefined));
|
|
9
|
+
}
|
|
10
|
+
export const namedValues = defineRule({
|
|
11
|
+
check: ({ sources }) => sources.filter((file) => isSpec(file.path)).flatMap((file) => syntaxFindings(file, (source) => nodesWhere(source, numericAssertion), MESSAGE)),
|
|
12
|
+
description: "Stories assert observed items or named values instead of bare counts and numbers.",
|
|
13
|
+
id: "tests/named-values",
|
|
14
|
+
});
|
|
15
|
+
//# sourceMappingURL=namedValues.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"namedValues.js","sourceRoot":"","sources":["../../../src/rules/stories/namedValues.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE3F,MAAM,OAAO,GACZ,4IAA4I,CAAC;AAE9I,SAAS,gBAAgB,CAAC,IAAa;IACtC,OAAO,CACN,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC;WACtB,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;WACpE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,KAAK,SAAS,CAAC,CAC1E,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,UAAU,CAAC;IACrC,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CACtB,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,EAAE,gBAAgB,CAAC,EAAE,OAAO,CAAC,CAAC;IAC/I,WAAW,EAAE,mFAAmF;IAChG,EAAE,EAAE,oBAAoB;CACxB,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"noExpect.d.ts","sourceRoot":"","sources":["../../../src/rules/stories/noExpect.ts"],"names":[],"mappings":"AAkCA,eAAO,MAAM,QAAQ,kEAInB,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
import { isTestSupport } from "#naming/testName.ts";
|
|
3
|
+
import { defineRule } from "#rule.ts";
|
|
4
|
+
import { memberName, nodesWhere, syntaxFindings, unwrapped } from "./syntax.js";
|
|
5
|
+
const MESSAGE = "Calls expect in test-support. Return the engine's observed state from the verb and put the expectation in the spec; throw if an action cannot run.";
|
|
6
|
+
function assertionReference(expression, names) {
|
|
7
|
+
const node = unwrapped(expression);
|
|
8
|
+
if (ts.isIdentifier(node)) {
|
|
9
|
+
return names.has(node.text);
|
|
10
|
+
}
|
|
11
|
+
return (memberName(node) === "expect"
|
|
12
|
+
|| ((ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node)) && assertionReference(node.expression, names)));
|
|
13
|
+
}
|
|
14
|
+
function assertionsIn(source) {
|
|
15
|
+
const names = new Set(["expect"]);
|
|
16
|
+
for (const statement of source.statements) {
|
|
17
|
+
const bindings = ts.isImportDeclaration(statement) ? statement.importClause?.namedBindings : undefined;
|
|
18
|
+
if (bindings !== undefined && ts.isNamedImports(bindings)) {
|
|
19
|
+
for (const element of bindings.elements) {
|
|
20
|
+
if ((element.propertyName ?? element.name).text === "expect") {
|
|
21
|
+
names.add(element.name.text);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return nodesWhere(source, (node) => ts.isCallExpression(node) && assertionReference(node.expression, names));
|
|
27
|
+
}
|
|
28
|
+
export const noExpect = defineRule({
|
|
29
|
+
check: ({ sources }) => sources.filter((file) => isTestSupport(file.path)).flatMap((file) => syntaxFindings(file, assertionsIn, MESSAGE)),
|
|
30
|
+
description: "Test-support performs actions and exposes observations; specs own expectations.",
|
|
31
|
+
id: "tests/no-expect-in-support",
|
|
32
|
+
});
|
|
33
|
+
//# sourceMappingURL=noExpect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"noExpect.js","sourceRoot":"","sources":["../../../src/rules/stories/noExpect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAEhF,MAAM,OAAO,GACZ,oJAAoJ,CAAC;AAEtJ,SAAS,kBAAkB,CAAC,UAAyB,EAAE,KAA0B;IAChF,MAAM,IAAI,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC;IACnC,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,CACN,UAAU,CAAC,IAAI,CAAC,KAAK,QAAQ;WAC1B,CAAC,CAAC,EAAE,CAAC,0BAA0B,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,yBAAyB,CAAC,IAAI,CAAC,CAAC,IAAI,kBAAkB,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,CAC9H,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,MAAqB;IAC1C,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;IAClC,KAAK,MAAM,SAAS,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QAC3C,MAAM,QAAQ,GAAG,EAAE,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC;QACvG,IAAI,QAAQ,KAAK,SAAS,IAAI,EAAE,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC3D,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;gBACzC,IAAI,CAAC,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBAC9D,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC9B,CAAC;YACF,CAAC;QACF,CAAC;IACF,CAAC;IACD,OAAO,UAAU,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,kBAAkB,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC;AAC9G,CAAC;AAED,MAAM,CAAC,MAAM,QAAQ,GAAG,UAAU,CAAC;IAClC,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;IACzI,WAAW,EAAE,iFAAiF;IAC9F,EAAE,EAAE,4BAA4B;CAChC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"noLimitImports.d.ts","sourceRoot":"","sources":["../../../src/rules/stories/noLimitImports.ts"],"names":[],"mappings":"AA2EA,eAAO,MAAM,cAAc,8DAIzB,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
import { defineRule } from "#rule.ts";
|
|
3
|
+
import { isSpec, memberName, nodesWhere, syntaxFindings, unwrapped } from "./syntax.js";
|
|
4
|
+
const MESSAGE = "Imports a MAX_* constant from a limits module. Tell a story about the observed behavior instead of asserting a copy of the implementation's cap.";
|
|
5
|
+
const LIMITS_MODULE = /(?:^|[/#])limits(?:\.[cm]?[jt]s)?(?:\/|$)/u;
|
|
6
|
+
const MAX_CONSTANT = /^MAX_/u;
|
|
7
|
+
function literalLimitsImport(expression) {
|
|
8
|
+
const node = unwrapped(expression);
|
|
9
|
+
if (ts.isAwaitExpression(node)) {
|
|
10
|
+
return literalLimitsImport(node.expression);
|
|
11
|
+
}
|
|
12
|
+
return (ts.isCallExpression(node)
|
|
13
|
+
&& node.expression.kind === ts.SyntaxKind.ImportKeyword
|
|
14
|
+
&& node.arguments[0] !== undefined
|
|
15
|
+
&& ts.isStringLiteralLike(node.arguments[0])
|
|
16
|
+
&& LIMITS_MODULE.test(node.arguments[0].text));
|
|
17
|
+
}
|
|
18
|
+
function capBinding(binding) {
|
|
19
|
+
if (binding.dotDotDotToken !== undefined) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
const name = binding.propertyName ?? binding.name;
|
|
23
|
+
if (ts.isComputedPropertyName(name)) {
|
|
24
|
+
return ts.isStringLiteralLike(name.expression) && MAX_CONSTANT.test(name.expression.text);
|
|
25
|
+
}
|
|
26
|
+
return (ts.isIdentifier(name) || ts.isStringLiteralLike(name)) && MAX_CONSTANT.test(name.text);
|
|
27
|
+
}
|
|
28
|
+
function capImports(source) {
|
|
29
|
+
const namespaces = new Set();
|
|
30
|
+
const imports = source.statements.flatMap((statement) => {
|
|
31
|
+
if (!(ts.isImportDeclaration(statement) && ts.isStringLiteralLike(statement.moduleSpecifier) && LIMITS_MODULE.test(statement.moduleSpecifier.text))) {
|
|
32
|
+
return [];
|
|
33
|
+
}
|
|
34
|
+
const bindings = statement.importClause?.namedBindings;
|
|
35
|
+
if (bindings !== undefined && ts.isNamespaceImport(bindings)) {
|
|
36
|
+
namespaces.add(bindings.name.text);
|
|
37
|
+
}
|
|
38
|
+
return bindings !== undefined && ts.isNamedImports(bindings)
|
|
39
|
+
? bindings.elements.filter((element) => MAX_CONSTANT.test((element.propertyName ?? element.name).text))
|
|
40
|
+
: [];
|
|
41
|
+
});
|
|
42
|
+
const dynamic = nodesWhere(source, ts.isVariableDeclaration).flatMap((node) => {
|
|
43
|
+
if (!ts.isVariableDeclaration(node) || node.initializer === undefined || !literalLimitsImport(node.initializer)) {
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
if (ts.isIdentifier(node.name)) {
|
|
47
|
+
namespaces.add(node.name.text);
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
return ts.isObjectBindingPattern(node.name) ? node.name.elements.filter(capBinding) : [];
|
|
51
|
+
});
|
|
52
|
+
return [
|
|
53
|
+
...imports,
|
|
54
|
+
...dynamic,
|
|
55
|
+
...nodesWhere(source, (node) => (ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node))
|
|
56
|
+
&& ts.isIdentifier(node.expression)
|
|
57
|
+
&& namespaces.has(node.expression.text)
|
|
58
|
+
&& MAX_CONSTANT.test(memberName(node) ?? "")),
|
|
59
|
+
];
|
|
60
|
+
}
|
|
61
|
+
export const noLimitImports = defineRule({
|
|
62
|
+
check: ({ sources }) => sources.filter((file) => isSpec(file.path)).flatMap((file) => syntaxFindings(file, capImports, MESSAGE)),
|
|
63
|
+
description: "Stories prove behavior instead of importing implementation caps from limits modules.",
|
|
64
|
+
id: "tests/no-limit-imports",
|
|
65
|
+
});
|
|
66
|
+
//# sourceMappingURL=noLimitImports.js.map
|