@shivaedev/quality 0.32.1 → 0.33.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 +2 -5
- package/biome/declarations.json +5 -0
- package/biome/preset.json +10 -0
- package/dist/rules/builtIn.d.ts +1 -3
- package/dist/rules/builtIn.d.ts.map +1 -1
- package/dist/rules/builtIn.js +0 -2
- package/dist/rules/builtIn.js.map +1 -1
- package/package.json +1 -1
- package/src/rules/builtIn.ts +0 -2
- package/dist/imports/publicModules.d.ts +0 -4
- package/dist/imports/publicModules.d.ts.map +0 -1
- package/dist/imports/publicModules.js +0 -21
- package/dist/imports/publicModules.js.map +0 -1
- package/dist/rules/stories/supportImports.d.ts +0 -4
- package/dist/rules/stories/supportImports.d.ts.map +0 -1
- package/dist/rules/stories/supportImports.js +0 -34
- package/dist/rules/stories/supportImports.js.map +0 -1
- package/src/imports/publicModules.ts +0 -27
- package/src/rules/stories/supportImports.ts +0 -38
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.33.1 - 2026-10-21
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- The Biome preset lets numbered migration files in `src/server/migrations/`, including in nested apps, default-export their migration Effect, so applications drop their `noDefaultExport` exception for Effect's migration loader. Other files still may not default-export.
|
|
8
|
+
|
|
9
|
+
## 0.33.0 - 2026-10-21
|
|
10
|
+
|
|
11
|
+
### Breaking
|
|
12
|
+
|
|
13
|
+
- Remove the `tests/support-imports` rule and its module allowlist. Delete the `tests/support-imports` block from your quality config; configs that still name it fail validation. Story kits may import any workspace module; how tests use those modules belongs to testing guidance and review.
|
|
14
|
+
|
|
3
15
|
## 0.32.1 - 2026-10-21
|
|
4
16
|
|
|
5
17
|
### Changed
|
package/README.md
CHANGED
|
@@ -78,7 +78,7 @@ When a config exists, its folder is the root for paths and hook scripts. Without
|
|
|
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
|
|
|
81
|
-
Naming rules treat numbered migration files such as `src/server/migrations/0001_create_notes.ts` as tool-owned, including in nested apps. The file must sit directly in that folder and match `NNNN_snake_case.ts`: four digits, an underscore and a lowercase name starting with a letter. Files elsewhere, files with other names and subfolders remain checked.
|
|
81
|
+
Naming rules treat numbered migration files such as `src/server/migrations/0001_create_notes.ts` as tool-owned, including in nested apps. The file must sit directly in that folder and match `NNNN_snake_case.ts`: four digits, an underscore and a lowercase name starting with a letter. Files elsewhere, files with other names and subfolders remain checked. The Biome preset lets `.ts` files directly in that folder whose names start with four digits and an underscore default-export their migration Effect, because Effect's migration loader imports the default export; Biome globs cannot spell the rest of the pattern, so the naming rules still report a malformed name.
|
|
82
82
|
|
|
83
83
|
`defineConfig` checks the config's types. The CLI also validates it: a broken config, unknown rule id or invalid options fails before checks run. An explicit `--config` path must exist.
|
|
84
84
|
|
|
@@ -126,7 +126,7 @@ export default defineConfig({
|
|
|
126
126
|
|
|
127
127
|
### Story tests
|
|
128
128
|
|
|
129
|
-
|
|
129
|
+
Keep story kits and fixtures in `src/test-support` and keep each spec specific to its story. [`@shivaedev/test-story`](https://github.com/ShivaeDev/platform/tree/main/packages/test-story#readme) explains how to build the kit, traits and verbs over a real engine.
|
|
130
130
|
|
|
131
131
|
Quality's `tests/story-specs` rule reports a test file that declares tests without a kit's `it`, including plain Vitest `it` and `test` declarations mixed with stories. Typecheck tests are exempt, as are test-story itself and its transitive workspace dependencies, including development, optional and peer dependencies: requiring those packages to depend on test-story would create a cycle.
|
|
132
132
|
|
|
@@ -140,8 +140,6 @@ Quality's `tests/story-setup` rule reports top-level test functions named with t
|
|
|
140
140
|
|
|
141
141
|
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.
|
|
142
142
|
|
|
143
|
-
`tests/support-imports` lets a kit drive any workspace package's exported modules, including its own package's exports through package names or `#` aliases. Export blocks keep internal modules closed. `options.modules` opens additional repository-relative module paths or glob patterns, such as an app's host, schemas and queue definitions. Packages without exports still need that allowlist. Imports within test-support and imports of external packages remain available for the harness; aliases, dynamic imports and re-exports resolve through the same import graph as the other import rules.
|
|
144
|
-
|
|
145
143
|
`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.
|
|
146
144
|
|
|
147
145
|
`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.
|
|
@@ -153,7 +151,6 @@ export default defineConfig({
|
|
|
153
151
|
rules: {
|
|
154
152
|
"boundaries/auth-sql": { options: { owners: ["platform/auth/**", "platform/auth-migrations/**"] } },
|
|
155
153
|
"boundaries/http-status": { options: { edge: ["src/http/**"] } },
|
|
156
|
-
"tests/support-imports": { options: { modules: ["src/host.ts", "src/schemas.ts", "src/queues.ts"] } },
|
|
157
154
|
},
|
|
158
155
|
});
|
|
159
156
|
```
|
package/biome/declarations.json
CHANGED
|
@@ -19,6 +19,11 @@
|
|
|
19
19
|
"reason": "Tools load their config files through the default export.",
|
|
20
20
|
"rule": "lint/style/noDefaultExport"
|
|
21
21
|
},
|
|
22
|
+
{
|
|
23
|
+
"includes": ["**/src/server/migrations/{0,1,2,3,4,5,6,7,8,9}{0,1,2,3,4,5,6,7,8,9}{0,1,2,3,4,5,6,7,8,9}{0,1,2,3,4,5,6,7,8,9}_*.ts"],
|
|
24
|
+
"reason": "Effect's migration loader imports each numbered migration file through its default export.",
|
|
25
|
+
"rule": "lint/style/noDefaultExport"
|
|
26
|
+
},
|
|
22
27
|
{
|
|
23
28
|
"includes": ["**/*.test.*", "**/*.spec.*"],
|
|
24
29
|
"reason": "A test defines the helper and harness components it renders, and no test module is hot-reloaded, so the rule's fast-refresh boundary does not apply.",
|
package/biome/preset.json
CHANGED
|
@@ -637,6 +637,16 @@
|
|
|
637
637
|
}
|
|
638
638
|
}
|
|
639
639
|
},
|
|
640
|
+
{
|
|
641
|
+
"includes": ["**/src/server/migrations/{0,1,2,3,4,5,6,7,8,9}{0,1,2,3,4,5,6,7,8,9}{0,1,2,3,4,5,6,7,8,9}{0,1,2,3,4,5,6,7,8,9}_*.ts"],
|
|
642
|
+
"linter": {
|
|
643
|
+
"rules": {
|
|
644
|
+
"style": {
|
|
645
|
+
"noDefaultExport": "off"
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
},
|
|
640
650
|
{
|
|
641
651
|
"includes": ["**/*.test.*", "**/*.spec.*"],
|
|
642
652
|
"linter": {
|
package/dist/rules/builtIn.d.ts
CHANGED
|
@@ -30,9 +30,7 @@ export declare const builtInRules: readonly [import("../rule.ts").Rule<"structur
|
|
|
30
30
|
readonly suites?: readonly string[];
|
|
31
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
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<"
|
|
34
|
-
readonly modules?: readonly string[];
|
|
35
|
-
}>, import("../rule.ts").Rule<"boundaries/http-status", {
|
|
33
|
+
}>, import("../rule.ts").Rule<"tests/no-expect-in-support", undefined>, import("../rule.ts").Rule<"tests/spec-helpers", undefined>, import("../rule.ts").Rule<"boundaries/http-status", {
|
|
36
34
|
readonly edge?: readonly string[];
|
|
37
35
|
}>, import("../rule.ts").Rule<"tests/named-values", undefined>, import("../rule.ts").Rule<"tests/no-limit-imports", undefined>];
|
|
38
36
|
//# 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
|
@@ -25,7 +25,6 @@ import { queueSql } from "#rules/stories/queueSql.ts";
|
|
|
25
25
|
import { storySetup } from "#rules/stories/setup.ts";
|
|
26
26
|
import { specHelpers } from "#rules/stories/specHelpers.ts";
|
|
27
27
|
import { storySpecs } from "#rules/stories/specs.ts";
|
|
28
|
-
import { supportImports } from "#rules/stories/supportImports.ts";
|
|
29
28
|
import { biomeOverrides } from "#rules/suppressions/biomeOverrides.ts";
|
|
30
29
|
import { biomeRecommended } from "#rules/suppressions/biomeRecommended.ts";
|
|
31
30
|
import { noDoubleCast } from "#rules/suppressions/noDoubleCast.ts";
|
|
@@ -79,7 +78,6 @@ export const builtInRules = [
|
|
|
79
78
|
authSql,
|
|
80
79
|
noExpect,
|
|
81
80
|
specHelpers,
|
|
82
|
-
supportImports,
|
|
83
81
|
httpStatus,
|
|
84
82
|
namedValues,
|
|
85
83
|
noLimitImports,
|
|
@@ -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,OAAO,EAAE,MAAM,2BAA2B,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"builtIn.js","sourceRoot":"","sources":["../../src/rules/builtIn.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shivaedev/quality",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.33.1",
|
|
4
4
|
"description": "Repository quality gate with typed rules, a baseline of existing debt and a registry of reasoned exceptions",
|
|
5
5
|
"homepage": "https://github.com/ShivaeDev/platform/tree/main/packages/quality#readme",
|
|
6
6
|
"bugs": {
|
package/src/rules/builtIn.ts
CHANGED
|
@@ -25,7 +25,6 @@ import { queueSql } from "#rules/stories/queueSql.ts";
|
|
|
25
25
|
import { storySetup } from "#rules/stories/setup.ts";
|
|
26
26
|
import { specHelpers } from "#rules/stories/specHelpers.ts";
|
|
27
27
|
import { storySpecs } from "#rules/stories/specs.ts";
|
|
28
|
-
import { supportImports } from "#rules/stories/supportImports.ts";
|
|
29
28
|
import { biomeOverrides } from "#rules/suppressions/biomeOverrides.ts";
|
|
30
29
|
import { biomeRecommended } from "#rules/suppressions/biomeRecommended.ts";
|
|
31
30
|
import { noDoubleCast } from "#rules/suppressions/noDoubleCast.ts";
|
|
@@ -80,7 +79,6 @@ export const builtInRules = [
|
|
|
80
79
|
authSql,
|
|
81
80
|
noExpect,
|
|
82
81
|
specHelpers,
|
|
83
|
-
supportImports,
|
|
84
82
|
httpStatus,
|
|
85
83
|
namedValues,
|
|
86
84
|
noLimitImports,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"publicModules.d.ts","sourceRoot":"","sources":["../../src/imports/publicModules.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAI9C,wBAAsB,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAoBxG"}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { posix } from "node:path";
|
|
2
|
-
import { exportedModule } from "./packageExports.js";
|
|
3
|
-
import { packageOf } from "./workspace.js";
|
|
4
|
-
export async function publicModules(inputs, graph) {
|
|
5
|
-
const exports = new Map(await Promise.all(graph.packages.map(async (owner) => {
|
|
6
|
-
const manifest = JSON.parse((await inputs.readText(posix.join(owner.directory, "package.json"))) ?? "");
|
|
7
|
-
return [owner, manifest.exports];
|
|
8
|
-
})));
|
|
9
|
-
const modules = new Set();
|
|
10
|
-
for (const edge of graph.edges) {
|
|
11
|
-
if (edge.to.kind !== "file") {
|
|
12
|
-
continue;
|
|
13
|
-
}
|
|
14
|
-
const owner = packageOf(graph.packages, edge.to.path);
|
|
15
|
-
if (owner !== undefined && exportedModule(exports.get(owner), posix.relative(owner.directory, edge.to.path))) {
|
|
16
|
-
modules.add(edge.to.path);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
return modules;
|
|
20
|
-
}
|
|
21
|
-
//# sourceMappingURL=publicModules.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"publicModules.js","sourceRoot":"","sources":["../../src/imports/publicModules.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAGlC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAkB,EAAE,KAAkB;IACzE,MAAM,OAAO,GAAG,IAAI,GAAG,CACtB,MAAM,OAAO,CAAC,GAAG,CAChB,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QAClC,MAAM,QAAQ,GAAmC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACxI,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAU,CAAC;IAC3C,CAAC,CAAC,CACF,CACD,CAAC;IACF,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAChC,IAAI,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC7B,SAAS;QACV,CAAC;QACD,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;QACtD,IAAI,KAAK,KAAK,SAAS,IAAI,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YAC9G,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;IACF,CAAC;IACD,OAAO,OAAO,CAAC;AAChB,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"supportImports.d.ts","sourceRoot":"","sources":["../../../src/rules/stories/supportImports.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,cAAc;;EA0BzB,CAAC"}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { Effect, Schema } from "effect";
|
|
2
|
-
import { importGraph } from "#imports/graph.ts";
|
|
3
|
-
import { publicModules } from "#imports/publicModules.ts";
|
|
4
|
-
import { isTestSupport } from "#naming/testName.ts";
|
|
5
|
-
import { defineRule } from "#rule.ts";
|
|
6
|
-
import { matchesAny } from "./matchesAny.js";
|
|
7
|
-
const SupportImportsOptions = Schema.Struct({
|
|
8
|
-
modules: Schema.Array(Schema.String).pipe(Schema.withDecodingDefaultKey(Effect.succeed([]))),
|
|
9
|
-
});
|
|
10
|
-
export const supportImports = defineRule({
|
|
11
|
-
check: async ({ options, ...inputs }) => {
|
|
12
|
-
if (!inputs.sources.some((file) => isTestSupport(file.path))) {
|
|
13
|
-
return [];
|
|
14
|
-
}
|
|
15
|
-
const graph = await importGraph(inputs);
|
|
16
|
-
const exported = await publicModules(inputs, graph);
|
|
17
|
-
return graph.edges
|
|
18
|
-
.filter((edge) => isTestSupport(edge.from)
|
|
19
|
-
&& edge.to.kind === "file"
|
|
20
|
-
&& !isTestSupport(edge.to.path)
|
|
21
|
-
&& !exported.has(edge.to.path)
|
|
22
|
-
&& !matchesAny(edge.to.path, options.modules))
|
|
23
|
-
.map((edge) => ({
|
|
24
|
-
file: edge.from,
|
|
25
|
-
line: edge.line,
|
|
26
|
-
message: `Test-support imports "${edge.specifier}" outside its allowed public surface. Drive the app through its host, schemas or queue definitions, or a workspace package's exports; list additional internal module paths in tests/support-imports.options.modules in the repository's quality config.`,
|
|
27
|
-
subject: edge.specifier,
|
|
28
|
-
}));
|
|
29
|
-
},
|
|
30
|
-
description: "Test-support reaches repository modules through workspace package exports and the repository's additional module allowlist.",
|
|
31
|
-
id: "tests/support-imports",
|
|
32
|
-
options: Schema.toStandardSchemaV1(SupportImportsOptions, { parseOptions: { errors: "all", onExcessProperty: "error" } }),
|
|
33
|
-
});
|
|
34
|
-
//# sourceMappingURL=supportImports.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"supportImports.js","sourceRoot":"","sources":["../../../src/rules/stories/supportImports.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,MAAM,qBAAqB,GAAG,MAAM,CAAC,MAAM,CAAC;IAC3C,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,sBAAsB,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;CAC5F,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG,UAAU,CAAC;IACxC,KAAK,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,GAAG,MAAM,EAAE,EAAE,EAAE;QACvC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YAC9D,OAAO,EAAE,CAAC;QACX,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,MAAM,CAAC,CAAC;QACxC,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACpD,OAAO,KAAK,CAAC,KAAK;aAChB,MAAM,CACN,CAAC,IAAI,EAAE,EAAE,CACR,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC;eACrB,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,MAAM;eACvB,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;eAC5B,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;eAC3B,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAC9C;aACA,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,yBAAyB,IAAI,CAAC,SAAS,0PAA0P;YAC1S,OAAO,EAAE,IAAI,CAAC,SAAS;SACvB,CAAC,CAAC,CAAC;IACN,CAAC;IACD,WAAW,EAAE,6HAA6H;IAC1I,EAAE,EAAE,uBAAuB;IAC3B,OAAO,EAAE,MAAM,CAAC,kBAAkB,CAAC,qBAAqB,EAAE,EAAE,YAAY,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,EAAE,CAAC;CACzH,CAAC,CAAC"}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { posix } from "node:path";
|
|
2
|
-
import type { RuleInputs } from "#rule.ts";
|
|
3
|
-
import type { ImportGraph } from "./graph.ts";
|
|
4
|
-
import { exportedModule } from "./packageExports.ts";
|
|
5
|
-
import { packageOf } from "./workspace.ts";
|
|
6
|
-
|
|
7
|
-
export async function publicModules(inputs: RuleInputs, graph: ImportGraph): Promise<ReadonlySet<string>> {
|
|
8
|
-
const exports = new Map(
|
|
9
|
-
await Promise.all(
|
|
10
|
-
graph.packages.map(async (owner) => {
|
|
11
|
-
const manifest: { readonly exports?: unknown } = JSON.parse((await inputs.readText(posix.join(owner.directory, "package.json"))) ?? "");
|
|
12
|
-
return [owner, manifest.exports] as const;
|
|
13
|
-
}),
|
|
14
|
-
),
|
|
15
|
-
);
|
|
16
|
-
const modules = new Set<string>();
|
|
17
|
-
for (const edge of graph.edges) {
|
|
18
|
-
if (edge.to.kind !== "file") {
|
|
19
|
-
continue;
|
|
20
|
-
}
|
|
21
|
-
const owner = packageOf(graph.packages, edge.to.path);
|
|
22
|
-
if (owner !== undefined && exportedModule(exports.get(owner), posix.relative(owner.directory, edge.to.path))) {
|
|
23
|
-
modules.add(edge.to.path);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
return modules;
|
|
27
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { Effect, Schema } from "effect";
|
|
2
|
-
import { importGraph } from "#imports/graph.ts";
|
|
3
|
-
import { publicModules } from "#imports/publicModules.ts";
|
|
4
|
-
import { isTestSupport } from "#naming/testName.ts";
|
|
5
|
-
import { defineRule } from "#rule.ts";
|
|
6
|
-
import { matchesAny } from "./matchesAny.ts";
|
|
7
|
-
|
|
8
|
-
const SupportImportsOptions = Schema.Struct({
|
|
9
|
-
modules: Schema.Array(Schema.String).pipe(Schema.withDecodingDefaultKey(Effect.succeed([]))),
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
export const supportImports = defineRule({
|
|
13
|
-
check: async ({ options, ...inputs }) => {
|
|
14
|
-
if (!inputs.sources.some((file) => isTestSupport(file.path))) {
|
|
15
|
-
return [];
|
|
16
|
-
}
|
|
17
|
-
const graph = await importGraph(inputs);
|
|
18
|
-
const exported = await publicModules(inputs, graph);
|
|
19
|
-
return graph.edges
|
|
20
|
-
.filter(
|
|
21
|
-
(edge) =>
|
|
22
|
-
isTestSupport(edge.from)
|
|
23
|
-
&& edge.to.kind === "file"
|
|
24
|
-
&& !isTestSupport(edge.to.path)
|
|
25
|
-
&& !exported.has(edge.to.path)
|
|
26
|
-
&& !matchesAny(edge.to.path, options.modules),
|
|
27
|
-
)
|
|
28
|
-
.map((edge) => ({
|
|
29
|
-
file: edge.from,
|
|
30
|
-
line: edge.line,
|
|
31
|
-
message: `Test-support imports "${edge.specifier}" outside its allowed public surface. Drive the app through its host, schemas or queue definitions, or a workspace package's exports; list additional internal module paths in tests/support-imports.options.modules in the repository's quality config.`,
|
|
32
|
-
subject: edge.specifier,
|
|
33
|
-
}));
|
|
34
|
-
},
|
|
35
|
-
description: "Test-support reaches repository modules through workspace package exports and the repository's additional module allowlist.",
|
|
36
|
-
id: "tests/support-imports",
|
|
37
|
-
options: Schema.toStandardSchemaV1(SupportImportsOptions, { parseOptions: { errors: "all", onExcessProperty: "error" } }),
|
|
38
|
-
});
|