@shivaedev/quality 0.19.0 → 0.20.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/CHANGELOG.md +14 -0
- package/README.md +7 -22
- package/dist/git/command.d.ts +1 -1
- package/dist/git/command.d.ts.map +1 -1
- package/dist/git/command.js +1 -1
- package/dist/git/command.js.map +1 -1
- package/dist/hooks/install.d.ts +1 -1
- package/dist/hooks/install.d.ts.map +1 -1
- package/dist/hooks/location.d.ts +1 -1
- package/dist/hooks/location.d.ts.map +1 -1
- package/dist/hooks/preCommit.d.ts +1 -1
- package/dist/hooks/preCommit.d.ts.map +1 -1
- package/dist/hooks/preCommit.js +1 -1
- package/dist/hooks/preCommit.js.map +1 -1
- package/dist/hooks/uninstall.d.ts +1 -1
- package/dist/hooks/uninstall.d.ts.map +1 -1
- package/dist/imports/isTooling.d.ts +2 -0
- package/dist/imports/isTooling.d.ts.map +1 -0
- package/dist/imports/isTooling.js +9 -0
- package/dist/imports/isTooling.js.map +1 -0
- package/dist/imports/runtime.d.ts.map +1 -1
- package/dist/imports/runtime.js +27 -2
- package/dist/imports/runtime.js.map +1 -1
- package/dist/rules/comments/no-environment-pragma.js +1 -1
- package/dist/rules/comments/no-environment-pragma.js.map +1 -1
- package/dist/rules/imports/manifest.d.ts.map +1 -1
- package/dist/rules/imports/manifest.js +2 -8
- package/dist/rules/imports/manifest.js.map +1 -1
- package/dist/rules/imports/runtime.d.ts.map +1 -1
- package/dist/rules/imports/runtime.js +7 -3
- package/dist/rules/imports/runtime.js.map +1 -1
- package/dist/testProjects.d.ts +3 -0
- package/dist/testProjects.d.ts.map +1 -0
- package/dist/testProjects.js +25 -0
- package/dist/testProjects.js.map +1 -0
- package/docs/modules.md +1 -1
- package/docs/rules.md +3 -1
- package/docs/tooling.md +2 -17
- package/package.json +11 -10
- package/src/git/command.ts +1 -1
- package/src/hooks/preCommit.ts +1 -1
- package/src/imports/isTooling.ts +11 -0
- package/src/imports/runtime.ts +28 -2
- package/src/rules/comments/no-environment-pragma.ts +1 -1
- package/src/rules/imports/manifest.ts +2 -10
- package/src/rules/imports/runtime.ts +7 -3
- package/src/testProjects.ts +30 -0
- package/dist/vitest.d.ts +0 -4
- package/dist/vitest.d.ts.map +0 -1
- package/dist/vitest.js +0 -60
- package/dist/vitest.js.map +0 -1
- package/src/vitest.ts +0 -65
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.20.0 - 2026-10-13
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- `imports/runtime` treats packages with a nonempty `bin` entry and no runtime folders as server code. Runtime folders take precedence in packages that also ship browser code.
|
|
8
|
+
- Package-root scripts, tooling folders and JavaScript or TypeScript config files are server code; client and shared code cannot import them.
|
|
9
|
+
- The runtime rule loads the browser-global checker only when shared source needs checking, avoiding DOM declaration parsing during Node-only CLI startup.
|
|
10
|
+
|
|
11
|
+
### Breaking
|
|
12
|
+
|
|
13
|
+
- Requires stable Effect 4.0.4 in place of 4.0.0-rc.112. Effect 4.0.4 moves the former `effect/unstable/*` modules to `effect/*` and renames constructors such as `Config.string` to `Config.String`. Install `@effect/platform-node` and `@effect/platform-node-shared` 4.0.4 and Vitest 5 alongside it.
|
|
14
|
+
- Removes `inheritTags`. Vitest 5 gives an inline project the tags of the config file it `extends`, so a root config passes its projects to `projects` directly.
|
|
15
|
+
- Moves `testProjects` from `@shivaedev/quality/vitest.ts` to `@shivaedev/quality/testProjects.ts`. Change the import in each `vitest.config.ts`.
|
|
16
|
+
|
|
3
17
|
## 0.19.0 - 2026-10-12
|
|
4
18
|
|
|
5
19
|
### Added
|
package/README.md
CHANGED
|
@@ -80,11 +80,13 @@ When a config exists, its folder is the root for paths and hook scripts. Without
|
|
|
80
80
|
|
|
81
81
|
### 2. When architecture needs it: describe an import boundary
|
|
82
82
|
|
|
83
|
-
An app says where its code runs through folder names. A package adopts the runtime convention by having `src/client/` or `src/server/`; no config entry is needed. In that package, `src/client/` is browser code, `src/server/` is server code, and everything else is shared. Keep shared code wherever its topic belongs; there is no required `src/shared/` folder or runtime file suffix.
|
|
83
|
+
An app says where its code runs through folder names. A package adopts the runtime convention by having `src/client/` or `src/server/`; no config entry is needed. In that package, `src/client/` is browser code, `src/server/` is server code, and everything else is shared except package-root tooling. Keep shared code wherever its topic belongs; there is no required `src/shared/` folder or runtime file suffix.
|
|
84
84
|
|
|
85
85
|
`imports/runtime` rejects client imports of server code or Node built-ins. Shared code may import neither client nor server code, use browser globals such as `window`, `document` or `localStorage`, or import Node built-ins. Both client and server code may import shared code. The check includes type imports and re-exports and resolves aliases through the shared import graph. Locally bound names and property names are not browser globals; portable web APIs such as `URL`, `fetch` and `AbortController` remain available to shared code. Test files and `test-support/` ship nowhere and are outside this runtime policy.
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
A package with a nonempty `bin` entry and no runtime folders is server code throughout. Runtime folders take precedence when a package also ships browser code. A Node library without a CLI uses `src/server/`; `engines.node` alone does not say that a package is Node-only. Packages without runtime folders or a `bin` entry retain their existing source policies. Existing explicit fences continue to run in every package. Runtime folders are detected independently of `sources`, including empty folders; `sources` still selects the code that is checked.
|
|
88
|
+
|
|
89
|
+
Tooling is server code in every package, including the workspace root: files under its top-level `script/`, `scripts/` and `tooling/` folders, and top-level JavaScript or TypeScript config files such as `vitest.config.ts`. A tooling folder or config file nested under `src/` follows the source runtime policy. Browser and shared code cannot import package-root tooling.
|
|
88
90
|
|
|
89
91
|
The manifest owns ordinary workspace dependencies. When a package promises more, put `quality.fences.config.ts` beside its `package.json`, exporting an array of fences as the default. Quality discovers this file at the repository root and in workspace packages, even when `sources` includes only their source folders. The root config does not list boundary files.
|
|
90
92
|
|
|
@@ -152,7 +154,7 @@ Import names from their defining module; there is no root entry. The package's `
|
|
|
152
154
|
| `imports/fences/dsl.ts` | `fence` |
|
|
153
155
|
| `imports/fences/selectors.ts` | `packages`, `folders`, `files`, `modules`, `scopes`, `anyOf`, `workspace`, `anything`, `external` |
|
|
154
156
|
| `imports/fences/model.ts` | `Fence`, `Target`, `Selector`, `Prohibition`, `Examples`, `Chain`, `ExampleStep`, `External` |
|
|
155
|
-
| `
|
|
157
|
+
| `testProjects.ts` | `testProjects` |
|
|
156
158
|
| `naming/testName.ts` | `testName`, `isTestCode`, `isTestSupport`, `ENVIRONMENTS`, `Environment`, `TestName` |
|
|
157
159
|
|
|
158
160
|
#### Config
|
|
@@ -206,7 +208,7 @@ quality hooks pre-commit [--config <file>]
|
|
|
206
208
|
### Install, shared tooling and limits
|
|
207
209
|
|
|
208
210
|
```sh
|
|
209
|
-
pnpm add --save-dev @shivaedev/quality @effect/platform-node@4.0.
|
|
211
|
+
pnpm add --save-dev @shivaedev/quality @effect/platform-node@4.0.4 @effect/platform-node-shared@4.0.4 effect@4.0.4
|
|
210
212
|
```
|
|
211
213
|
|
|
212
214
|
Node 24 or later is required. The CLI loads the TypeScript config through Node's native import; use erasable syntax and `.ts` extensions for relative TypeScript imports. Installing the package does not install a hook; opt in with `quality hooks install`.
|
|
@@ -216,7 +218,7 @@ The package includes `@shivaedev/quality/biome`, `@shivaedev/quality/tsconfig/ba
|
|
|
216
218
|
For Vitest, install `vitest` and `happy-dom` when the repository has DOM tests, then use:
|
|
217
219
|
|
|
218
220
|
```ts
|
|
219
|
-
import { testProjects } from "@shivaedev/quality/
|
|
221
|
+
import { testProjects } from "@shivaedev/quality/testProjects.ts";
|
|
220
222
|
import { defineConfig } from "vitest/config";
|
|
221
223
|
|
|
222
224
|
export default defineConfig({ test: testProjects() });
|
|
@@ -239,23 +241,6 @@ const integration = test.skipIf(databaseUrl === undefined);
|
|
|
239
241
|
|
|
240
242
|
`databaseUrl` is the test database URL read by the repository's environment helper. Declare the real PostgreSQL tests with `integration(name, body)`. A conditionally registered suite or Effect tester follows the same URL gate. CI must supply the URL for every such test; a green run with missing URLs gives no PostgreSQL evidence.
|
|
241
243
|
|
|
242
|
-
#### Inherited tags
|
|
243
|
-
|
|
244
|
-
A root Vitest config that gathers inline projects from package configs uses `inheritTags(projects, root)` to copy the tags of each extended config into its project:
|
|
245
|
-
|
|
246
|
-
```ts
|
|
247
|
-
import { inheritTags } from "@shivaedev/quality/vitest.ts";
|
|
248
|
-
import { defineConfig } from "vitest/config";
|
|
249
|
-
|
|
250
|
-
const bakery = { extends: "./packages/bakery/vitest.config.ts", root: "./packages/bakery", test: { name: "bakery" } };
|
|
251
|
-
|
|
252
|
-
export default defineConfig(async () => ({
|
|
253
|
-
test: { projects: await inheritTags([bakery], import.meta.dirname) },
|
|
254
|
-
}));
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
Vitest otherwise drops tags from an inline project's extended config. A project's own tag wins over an inherited tag with the same name; `extends: true`, globs and file-path projects stay unchanged. The [tooling guide](https://github.com/ShivaeDev/platform/blob/main/packages/quality/docs/tooling.md#inherited-tags) gives the config-loading limits.
|
|
258
|
-
|
|
259
244
|
#### Configuration limits
|
|
260
245
|
|
|
261
246
|
All built-in and local rules run at `error`. Config settings cannot disable a rule or downgrade it to a warning. Record existing debt in the baseline instead. Source and test line limits can only be lowered from 150 and 300, and the comment limit from 2; custom test-file patterns and inventory exclusions are rejected.
|
package/dist/git/command.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../src/git/command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAgB,mBAAmB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../src/git/command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAgB,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,WAAW,SAAS;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,GAAG,GAAG,mBAAmB,CAAC,mBAAmB,CAAC;AAE1D,eAAO,MAAM,GAAG,QAAS,MAAM,QAAQ,SAAS,MAAM,EAAE,KAAG,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,YAAY,EAAE,GAAG,CAWC,CAAC;AAEvG,eAAO,MAAM,SAAS,QAAS,MAAM,QAAQ,SAAS,MAAM,EAAE,KAAG,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,CAKtG,CAAC"}
|
package/dist/git/command.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Effect, Stream } from "effect";
|
|
2
|
-
import { ChildProcess, ChildProcessSpawner } from "effect/
|
|
2
|
+
import { ChildProcess, ChildProcessSpawner } from "effect/process";
|
|
3
3
|
import { SetupFailure } from "#failure.ts";
|
|
4
4
|
export const git = (cwd, args) => Effect.scoped(Effect.gen(function* () {
|
|
5
5
|
const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
|
package/dist/git/command.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command.js","sourceRoot":"","sources":["../../src/git/command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"command.js","sourceRoot":"","sources":["../../src/git/command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAU3C,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,GAAW,EAAE,IAAuB,EAA+C,EAAE,CACxG,MAAM,CAAC,MAAM,CACZ,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IACnB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,mBAAmB,CAAC,mBAAmB,CAAC;IAC/D,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;IAClG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAC/C,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,EACpH,EAAE,WAAW,EAAE,WAAW,EAAE,CAC5B,CAAC;IACF,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AAC/C,CAAC,CAAC,CACF,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,YAAY,CAAC,EAAE,OAAO,EAAE,mBAAmB,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;AAEvG,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAW,EAAE,IAAuB,EAA4C,EAAE,CAC3G,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CACzC,MAAM,CAAC,IAAI,KAAK,CAAC;IAChB,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;IAC/B,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,EAAE,OAAO,EAAE,OAAO,IAAI,CAAC,CAAC,CAAC,YAAY,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,aAAa,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,CAC7H,CAAC"}
|
package/dist/hooks/install.d.ts
CHANGED
|
@@ -7,5 +7,5 @@ export interface HookInstall {
|
|
|
7
7
|
readonly force: boolean;
|
|
8
8
|
readonly launch: Launch;
|
|
9
9
|
}
|
|
10
|
-
export declare const installHook: (install: HookInstall) => Effect.Effect<void, SetupFailure, import("effect/
|
|
10
|
+
export declare const installHook: (install: HookInstall) => Effect.Effect<void, SetupFailure, import("effect/process/ChildProcessSpawner").ChildProcessSpawner | FileSystem.FileSystem>;
|
|
11
11
|
//# sourceMappingURL=install.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/hooks/install.ts"],"names":[],"mappings":"AACA,OAAO,EAAW,MAAM,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAGrD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAA6B,KAAK,MAAM,EAAc,MAAM,cAAc,CAAC;AAIlF,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB;AA4BD,eAAO,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/hooks/install.ts"],"names":[],"mappings":"AACA,OAAO,EAAW,MAAM,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAGrD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAA6B,KAAK,MAAM,EAAc,MAAM,cAAc,CAAC;AAIlF,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB;AA4BD,eAAO,MAAM,WAAW,uJAyBtB,CAAC"}
|
package/dist/hooks/location.d.ts
CHANGED
|
@@ -5,5 +5,5 @@ export interface HookLocation {
|
|
|
5
5
|
readonly hooksPath: string | undefined;
|
|
6
6
|
readonly toplevel: string;
|
|
7
7
|
}
|
|
8
|
-
export declare const hookLocation: (cwd: string) => Effect.Effect<HookLocation, SetupFailure, import("effect/
|
|
8
|
+
export declare const hookLocation: (cwd: string) => Effect.Effect<HookLocation, SetupFailure, import("effect/process/ChildProcessSpawner").ChildProcessSpawner>;
|
|
9
9
|
//# sourceMappingURL=location.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"location.d.ts","sourceRoot":"","sources":["../../src/hooks/location.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC1B;AAGD,eAAO,MAAM,YAAY,
|
|
1
|
+
{"version":3,"file":"location.d.ts","sourceRoot":"","sources":["../../src/hooks/location.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC1B;AAGD,eAAO,MAAM,YAAY,8HAevB,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
|
-
import { ChildProcessSpawner } from "effect/
|
|
2
|
+
import { ChildProcessSpawner } from "effect/process";
|
|
3
3
|
import { GateFailed, SetupFailure } from "#failure.ts";
|
|
4
4
|
export declare const preCommitHook: (cwd: string, path: string | undefined) => Effect.Effect<undefined, GateFailed | SetupFailure, ChildProcessSpawner.ChildProcessSpawner | import("effect/FileSystem").FileSystem>;
|
|
5
5
|
//# sourceMappingURL=preCommit.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preCommit.d.ts","sourceRoot":"","sources":["../../src/hooks/preCommit.ts"],"names":[],"mappings":"AACA,OAAO,EAAW,MAAM,EAAU,MAAM,QAAQ,CAAC;AACjD,OAAO,EAAgB,mBAAmB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"preCommit.d.ts","sourceRoot":"","sources":["../../src/hooks/preCommit.ts"],"names":[],"mappings":"AACA,OAAO,EAAW,MAAM,EAAU,MAAM,QAAQ,CAAC;AACjD,OAAO,EAAgB,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAInE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAyCvD,eAAO,MAAM,aAAa,kLAoBxB,CAAC"}
|
package/dist/hooks/preCommit.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
2
|
import { Console, Effect, Schema } from "effect";
|
|
3
|
-
import { ChildProcess, ChildProcessSpawner } from "effect/
|
|
3
|
+
import { ChildProcess, ChildProcessSpawner } from "effect/process";
|
|
4
4
|
import { lint } from "#cli/lint.ts";
|
|
5
5
|
import { loadConfig } from "#config/load.ts";
|
|
6
6
|
import { decodeWith, validOrFail } from "#decoded.ts";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preCommit.js","sourceRoot":"","sources":["../../src/hooks/preCommit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"preCommit.js","sourceRoot":"","sources":["../../src/hooks/preCommit.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { Effect, FileSystem } from "effect";
|
|
2
2
|
import { SetupFailure } from "#failure.ts";
|
|
3
|
-
export declare const uninstallHook: (cwd: string) => Effect.Effect<void, SetupFailure, import("effect/
|
|
3
|
+
export declare const uninstallHook: (cwd: string) => Effect.Effect<void, SetupFailure, import("effect/process/ChildProcessSpawner").ChildProcessSpawner | FileSystem.FileSystem>;
|
|
4
4
|
//# sourceMappingURL=uninstall.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uninstall.d.ts","sourceRoot":"","sources":["../../src/hooks/uninstall.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,MAAM,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAK3C,eAAO,MAAM,aAAa,
|
|
1
|
+
{"version":3,"file":"uninstall.d.ts","sourceRoot":"","sources":["../../src/hooks/uninstall.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,MAAM,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAK3C,eAAO,MAAM,aAAa,8IAYxB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isTooling.d.ts","sourceRoot":"","sources":["../../src/imports/isTooling.ts"],"names":[],"mappings":"AAMA,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAIlE"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { posix } from "node:path";
|
|
2
|
+
const TOOL_FOLDERS = new Set(["script", "scripts", "tooling"]);
|
|
3
|
+
const CONFIG_FILE = /(?:^|\.)config\.[cm]?[jt]sx?$/u;
|
|
4
|
+
export function isTooling(directory, path) {
|
|
5
|
+
const local = posix.relative(directory, path);
|
|
6
|
+
const [folder = ""] = local.split("/");
|
|
7
|
+
return TOOL_FOLDERS.has(folder) || (!local.includes("/") && CONFIG_FILE.test(local));
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=isTooling.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isTooling.js","sourceRoot":"","sources":["../../src/imports/isTooling.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAElC,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;AAE/D,MAAM,WAAW,GAAG,gCAAgC,CAAC;AAErD,MAAM,UAAU,SAAS,CAAC,SAAiB,EAAE,IAAY;IACxD,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAC9C,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACvC,OAAO,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;AACtF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/imports/runtime.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/imports/runtime.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,OAAO,EAAa,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElE,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAkCrD,wBAAgB,SAAS,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,gBAAgB,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,GAAG,SAAS,CAsB1H"}
|
package/dist/imports/runtime.js
CHANGED
|
@@ -1,6 +1,27 @@
|
|
|
1
|
-
import { statSync } from "node:fs";
|
|
1
|
+
import { readFileSync, statSync } from "node:fs";
|
|
2
2
|
import { join, posix } from "node:path";
|
|
3
|
+
import { isTooling } from "./isTooling.js";
|
|
3
4
|
import { packageOf } from "./workspace.js";
|
|
5
|
+
function executablePath(value) {
|
|
6
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
7
|
+
}
|
|
8
|
+
function hasExecutable(root, directory) {
|
|
9
|
+
const path = join(root, directory, "package.json");
|
|
10
|
+
try {
|
|
11
|
+
const manifest = JSON.parse(readFileSync(path, "utf8"));
|
|
12
|
+
if (typeof manifest !== "object" || manifest === null || Array.isArray(manifest)) {
|
|
13
|
+
throw new Error("the manifest must be an object");
|
|
14
|
+
}
|
|
15
|
+
const bin = Reflect.get(manifest, "bin");
|
|
16
|
+
return executablePath(bin) || (typeof bin === "object" && bin !== null && !Array.isArray(bin) && Object.values(bin).some(executablePath));
|
|
17
|
+
}
|
|
18
|
+
catch (cause) {
|
|
19
|
+
if (cause instanceof Error && "code" in cause && cause.code === "ENOENT") {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
throw new Error(`cannot read runtime policy at ${path}`, { cause });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
4
25
|
function directoryExists(path) {
|
|
5
26
|
try {
|
|
6
27
|
return statSync(path).isDirectory();
|
|
@@ -17,10 +38,14 @@ export function runtimeOf(inputs, packages) {
|
|
|
17
38
|
const adopted = new Set(owners
|
|
18
39
|
.filter((owner) => ["client", "server"].some((folder) => directoryExists(join(inputs.root, owner.directory, "src", folder))))
|
|
19
40
|
.map((owner) => owner.directory));
|
|
41
|
+
const executable = new Set(owners.filter((owner) => hasExecutable(inputs.root, owner.directory)).map((owner) => owner.directory));
|
|
20
42
|
return (path) => {
|
|
21
43
|
const owner = packageOf(packages, path)?.directory ?? ".";
|
|
44
|
+
if (isTooling(owner, path)) {
|
|
45
|
+
return "server";
|
|
46
|
+
}
|
|
22
47
|
if (!adopted.has(owner)) {
|
|
23
|
-
return undefined;
|
|
48
|
+
return executable.has(owner) ? "server" : undefined;
|
|
24
49
|
}
|
|
25
50
|
const local = posix.relative(owner, path);
|
|
26
51
|
if (local.startsWith("src/client/")) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/imports/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/imports/runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { definePatternRule } from "./pattern-rule.js";
|
|
2
2
|
export const noEnvironmentPragma = definePatternRule({
|
|
3
|
-
description: "A test file gets its environment from its name, not from a pragma: `*.dom.test.ts` runs in a DOM, every other test in Node. `@shivaedev/quality/
|
|
3
|
+
description: "A test file gets its environment from its name, not from a pragma: `*.dom.test.ts` runs in a DOM, every other test in Node. `@shivaedev/quality/testProjects.ts` sets up the Vitest projects that read the name.",
|
|
4
4
|
id: "comments/no-environment-pragma",
|
|
5
5
|
message: (match) => `Sets the test environment with "${match}". Name the file *.dom.test.ts or *.dom.test.tsx instead.`,
|
|
6
6
|
patterns: [/^@(?:vitest|jest)-environment(?:-options)?(?=\s|$)/mu],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-environment-pragma.js","sourceRoot":"","sources":["../../../src/rules/comments/no-environment-pragma.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,MAAM,CAAC,MAAM,mBAAmB,GAAG,iBAAiB,CAAC;IACpD,WAAW,EACV,
|
|
1
|
+
{"version":3,"file":"no-environment-pragma.js","sourceRoot":"","sources":["../../../src/rules/comments/no-environment-pragma.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,MAAM,CAAC,MAAM,mBAAmB,GAAG,iBAAiB,CAAC;IACpD,WAAW,EACV,kNAAkN;IACnN,EAAE,EAAE,gCAAgC;IACpC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,mCAAmC,KAAK,2DAA2D;IACvH,QAAQ,EAAE,CAAC,sDAAsD,CAAC;CAClE,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../src/rules/imports/manifest.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../src/rules/imports/manifest.ts"],"names":[],"mappings":"AAwEA,eAAO,MAAM,eAAe,wDAmC1B,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { posix } from "node:path";
|
|
2
2
|
import { importGraph } from "#imports/graph.ts";
|
|
3
|
+
import { isTooling } from "#imports/isTooling.ts";
|
|
3
4
|
import { builtinName } from "#imports/resolve.ts";
|
|
4
5
|
import { packageOf } from "#imports/workspace.ts";
|
|
5
6
|
import { isTestCode } from "#naming/testName.ts";
|
|
@@ -45,15 +46,8 @@ async function manifestDependencies(inputs, owner, graph) {
|
|
|
45
46
|
throw new Error(`cannot read dependency policy at ${path}: ${cause instanceof Error ? cause.message : String(cause)}`, { cause });
|
|
46
47
|
}
|
|
47
48
|
}
|
|
48
|
-
const TOOL_FOLDERS = new Set(["script", "scripts", "tooling"]);
|
|
49
|
-
const CONFIG_FILE = /(?:^|\.)config\.[cm]?[jt]sx?$/u;
|
|
50
49
|
function developmentFile(owner, path) {
|
|
51
|
-
|
|
52
|
-
return true;
|
|
53
|
-
}
|
|
54
|
-
const local = posix.relative(owner.directory, path);
|
|
55
|
-
const [folder = ""] = local.split("/");
|
|
56
|
-
return TOOL_FOLDERS.has(folder) || (!local.includes("/") && CONFIG_FILE.test(local));
|
|
50
|
+
return isTestCode(path) || isTooling(owner.directory, path);
|
|
57
51
|
}
|
|
58
52
|
function developmentImport(policy, owner, path, runtime) {
|
|
59
53
|
if (runtime.has(path)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../../src/rules/imports/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAClC,OAAO,EAAoB,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAyB,MAAM,uBAAuB,CAAC;AACzE,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAmB,MAAM,UAAU,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,MAAM,KAAK,GAAG,QAAQ,CAAC;AAEvB,SAAS,WAAW,CAAC,SAAiB;IACrC,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC1C,OAAO,CACN,WAAW,CAAC,IAAI,CAAC;WACd,IAAI;aACL,KAAK,CAAC,GAAG,CAAC;aACV,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aACtC,IAAI,CAAC,GAAG,CAAC,CACX,CAAC;AACH,CAAC;AASD,SAAS,KAAK,CAAC,QAAgB,EAAE,KAAa;IAC7C,MAAM,KAAK,GAAY,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IACpD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,EAAE,CAAC;IACX,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,oBAAoB,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED,KAAK,UAAU,oBAAoB,CAAC,MAAkB,EAAE,KAAuB,EAAE,KAAkB;IAClG,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IACzD,IAAI,CAAC;QACJ,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC5C,CAAC;QACD,MAAM,QAAQ,GAAY,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3C,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YAClF,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACnD,CAAC;QACD,OAAO;YACN,GAAG,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,eAAe,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;YACzF,WAAW,EAAE,IAAI,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;YACxD,OAAO,EAAE,IAAI,GAAG,CAAC,CAAC,cAAc,EAAE,kBAAkB,EAAE,sBAAsB,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;SACzH,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,oCAAoC,IAAI,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IACnI,CAAC;AACF,CAAC;AAED,
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../../src/rules/imports/manifest.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/rules/imports/runtime.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/rules/imports/runtime.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,cAAc,uDAiCzB,CAAC"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { browserGlobals } from "#imports/browserGlobals.ts";
|
|
2
1
|
import { importGraph } from "#imports/graph.ts";
|
|
3
2
|
import { builtinName } from "#imports/resolve.ts";
|
|
4
3
|
import { runtimeOf } from "#imports/runtime.ts";
|
|
@@ -33,9 +32,14 @@ export const importsRuntime = defineRule({
|
|
|
33
32
|
},
|
|
34
33
|
];
|
|
35
34
|
});
|
|
36
|
-
|
|
35
|
+
const shared = inputs.sources.filter((file) => !isTestCode(file.path) && runtime(file.path) === "shared");
|
|
36
|
+
if (shared.length === 0) {
|
|
37
|
+
return imports;
|
|
38
|
+
}
|
|
39
|
+
const { browserGlobals } = await import("#imports/browserGlobals.ts");
|
|
40
|
+
return [...imports, ...shared.flatMap(browserGlobals)];
|
|
37
41
|
},
|
|
38
|
-
description: "
|
|
42
|
+
description: "Runtime folders define client, server and shared code. Executable packages without runtime folders and package-root tooling are server code.",
|
|
39
43
|
id: "imports/runtime",
|
|
40
44
|
});
|
|
41
45
|
//# sourceMappingURL=runtime.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../src/rules/imports/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../src/rules/imports/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAgB,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,SAAS,eAAe,CAAC,IAAa,EAAE,EAAuB,EAAE,OAAgB;IAChF,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACvB,OAAO,EAAE,KAAK,QAAQ,IAAI,EAAE,KAAK,QAAQ,IAAI,OAAO,CAAC;IACtD,CAAC;IACD,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,EAAE,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,UAAU,CAAC;IACxC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QACvB,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,MAAM,CAAC,CAAC;QACxC,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;QAClD,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;YAC5C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChC,IAAI,IAAI,KAAK,SAAS,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACjD,OAAO,EAAE,CAAC;YACX,CAAC;YACD,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YACvE,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,UAAU,IAAI,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,KAAK,SAAS,CAAC;YAC5F,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,CAAC;gBACzC,OAAO,EAAE,CAAC;YACX,CAAC;YACD,OAAO;gBACN;oBACC,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,OAAO,EAAE,GAAG,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,iBAAiB,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,GAAG,EAAE,OAAO,aAAa,IAAI,CAAC,SAAS,mHAAmH;oBAC1P,OAAO,EAAE,IAAI,CAAC,SAAS;iBACvB;aACD,CAAC;QACH,CAAC,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,QAAQ,CAAC,CAAC;QAC1G,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,OAAO,CAAC;QAChB,CAAC;QACD,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;QACtE,OAAO,CAAC,GAAG,OAAO,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC;IACxD,CAAC;IACD,WAAW,EACV,8IAA8I;IAC/I,EAAE,EAAE,iBAAiB;CACrB,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testProjects.d.ts","sourceRoot":"","sources":["../src/testProjects.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAepE,wBAAgB,YAAY,CAAC,GAAG,OAAO,EAAE,SAAS,KAAK,EAAE,GAAG,cAAc,CAczE"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { defaultExclude } from "vitest/config";
|
|
2
|
+
const EXTENSION = "?(c|m)[jt]s?(x)";
|
|
3
|
+
const TYPECHECK_ALONE = `**/typecheck.test.${EXTENSION}`;
|
|
4
|
+
function named(environment) {
|
|
5
|
+
return environment === undefined ? `**/*.@(test|spec).${EXTENSION}` : `**/*.${environment}.@(test|spec).${EXTENSION}`;
|
|
6
|
+
}
|
|
7
|
+
function excluding(...patterns) {
|
|
8
|
+
return [...defaultExclude, named("typecheck"), TYPECHECK_ALONE, ...patterns];
|
|
9
|
+
}
|
|
10
|
+
export function testProjects(...options) {
|
|
11
|
+
if (options.length > 0) {
|
|
12
|
+
throw new Error("testProjects takes no options. Remove suite exclusions; every test belongs in its named project.");
|
|
13
|
+
}
|
|
14
|
+
return {
|
|
15
|
+
project: ["unit", "dom"],
|
|
16
|
+
projects: [
|
|
17
|
+
{ extends: true, test: { environment: "node", exclude: excluding(named("dom"), named("slow")), include: [named()], name: "unit" } },
|
|
18
|
+
{ extends: true, test: { environment: "happy-dom", exclude: excluding(named("slow")), include: [named("dom")], name: "dom" } },
|
|
19
|
+
{ extends: true, test: { environment: "node", exclude: excluding(), include: [named("slow")], name: "slow" } },
|
|
20
|
+
],
|
|
21
|
+
// Tests that start real servers, browsers or CLIs need seconds on a busy CI runner, and Vitest's 5s default fails them for load, not behavior.
|
|
22
|
+
testTimeout: 30_000,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=testProjects.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testProjects.js","sourceRoot":"","sources":["../src/testProjects.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAuB,MAAM,eAAe,CAAC;AAGpE,MAAM,SAAS,GAAG,iBAAiB,CAAC;AAEpC,MAAM,eAAe,GAAG,qBAAqB,SAAS,EAAE,CAAC;AAEzD,SAAS,KAAK,CAAC,WAAyB;IACvC,OAAO,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,qBAAqB,SAAS,EAAE,CAAC,CAAC,CAAC,QAAQ,WAAW,iBAAiB,SAAS,EAAE,CAAC;AACvH,CAAC;AAED,SAAS,SAAS,CAAC,GAAG,QAA2B;IAChD,OAAO,CAAC,GAAG,cAAc,EAAE,KAAK,CAAC,WAAW,CAAC,EAAE,eAAe,EAAE,GAAG,QAAQ,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,GAAG,OAAyB;IACxD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,kGAAkG,CAAC,CAAC;IACrH,CAAC;IACD,OAAO;QACN,OAAO,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC;QACxB,QAAQ,EAAE;YACT,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;YACnI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;YAC9H,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;SAC9G;QACD,+IAA+I;QAC/I,WAAW,EAAE,MAAM;KACnB,CAAC;AACH,CAAC"}
|
package/docs/modules.md
CHANGED
|
@@ -14,7 +14,7 @@ A module link opens its source. Type and value declarations with the same name a
|
|
|
14
14
|
| [failure.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/failure.ts) | `SetupFailure`, `GateFailed` |
|
|
15
15
|
| [rule.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/rule.ts) | `Finding`, `Findings`, `SourceFile`, `RuleInputs`, `RuleContext`, `Configured`, `Rule`, `defineRule` |
|
|
16
16
|
| [standard-schema.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/standard-schema.ts) | `StandardSchemaV1`, `StandardResult`, `StandardIssue`, `describeIssue` |
|
|
17
|
-
| [
|
|
17
|
+
| [testProjects.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/testProjects.ts) | `testProjects` |
|
|
18
18
|
|
|
19
19
|
## baseline
|
|
20
20
|
|
package/docs/rules.md
CHANGED
|
@@ -187,7 +187,9 @@ When the sources hold no module at all, the graph-building rules stop the run in
|
|
|
187
187
|
|
|
188
188
|
#### Runtime folders
|
|
189
189
|
|
|
190
|
-
`imports/runtime` adopts a package automatically when it has `src/client/` or `src/server/`, including folders outside `sources`. In an adopted package, code in `src/client/` is browser code, code in `src/server/` is server code, and code anywhere else is shared. A package without
|
|
190
|
+
`imports/runtime` adopts a package automatically when it has `src/client/` or `src/server/`, including folders outside `sources`. In an adopted package, code in `src/client/` is browser code, code in `src/server/` is server code, and code anywhere else is shared except package-root tooling. A package with a nonempty `bin` entry and no runtime folders is server code throughout; runtime folders take precedence over `bin`. A Node library without a CLI uses `src/server/`. `engines.node` alone does not identify Node-only code. Other packages retain their existing source policies. Existing explicit fences keep running in either case.
|
|
191
|
+
|
|
192
|
+
Package-root tooling is server code in every package, including the workspace root: top-level `script/`, `scripts/` and `tooling/` folders and top-level JavaScript or TypeScript config files. A tooling folder or config file nested under `src/` follows the source runtime policy.
|
|
191
193
|
|
|
192
194
|
Client code may not import server code or Node built-ins. Shared code may import neither client nor server code and may neither import Node built-ins nor use browser globals. Client and server code may import shared code. The rule uses the resolved import graph, including type imports, re-exports, dynamic imports and literal `require()` calls; missing file targets still carry their runtime folder. Test files and `test-support/` are outside the shipped runtime policy.
|
|
193
195
|
|
package/docs/tooling.md
CHANGED
|
@@ -44,10 +44,10 @@ The `biome` rule runs `biome check` with the repository's config and reports eac
|
|
|
44
44
|
|
|
45
45
|
## Vitest projects
|
|
46
46
|
|
|
47
|
-
`@shivaedev/quality/
|
|
47
|
+
`@shivaedev/quality/testProjects.ts` sets up the tests of a package by file name, so no test file sets its environment with a pragma. It needs `vitest`, and `happy-dom` for DOM tests. A package's `vitest.config.ts` reads:
|
|
48
48
|
|
|
49
49
|
```ts
|
|
50
|
-
import { testProjects } from "@shivaedev/quality/
|
|
50
|
+
import { testProjects } from "@shivaedev/quality/testProjects.ts";
|
|
51
51
|
import { defineConfig } from "vitest/config";
|
|
52
52
|
|
|
53
53
|
export default defineConfig({ test: testProjects() });
|
|
@@ -63,21 +63,6 @@ Type tests (`*.typecheck.test.ts`, `*.typecheck.spec.ts` and `typecheck.test.ts`
|
|
|
63
63
|
|
|
64
64
|
`testProjects()` takes no options. Every conventionally named suite runs in its project regardless of its folder; exclusion options are rejected.
|
|
65
65
|
|
|
66
|
-
### Inherited tags
|
|
67
|
-
|
|
68
|
-
Vitest gives an inline project only the [tags](https://vitest.dev/guide/test-tags) it declares itself, never those of a config file it `extends`. A test tagged in that file then fails with `cannot apply "<tag>" tag for this test` as soon as a root config runs it. A root config that gathers the projects of several packages, or whose projects extend a shared base config, passes them through `inheritTags`:
|
|
69
|
-
|
|
70
|
-
```ts
|
|
71
|
-
import { inheritTags } from "@shivaedev/quality/vitest.ts";
|
|
72
|
-
import { defineConfig } from "vitest/config";
|
|
73
|
-
|
|
74
|
-
const bakery = { extends: "./packages/bakery/vitest.config.ts", root: "./packages/bakery", test: { name: "bakery" } };
|
|
75
|
-
|
|
76
|
-
export default defineConfig(async () => ({ test: { projects: await inheritTags([bakery], import.meta.dirname) } }));
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
`inheritTags(projects, root)` loads the config file of each inline project whose `extends` is a path, resolved against `root`, and adds the tags that file declares to the project's own, so `vitest run --tags-filter=<tag>` works across the workspace. A tag the project declares itself wins over an inherited one of the same name. Config objects and config functions are supported. A project that extends `true`, and a glob or file path, comes back unchanged. The extended files load with Node's own `import`, so each must be a module Node runs without a bundler.
|
|
80
|
-
|
|
81
66
|
## tsconfig presets
|
|
82
67
|
|
|
83
68
|
Two presets supply a shared strict TypeScript setup for type-checking and package builds.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shivaedev/quality",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
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": {
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"./tsconfig/base.json": "./tsconfig/base.json",
|
|
34
34
|
"./tsconfig/package.json": "./tsconfig/package.json",
|
|
35
35
|
"./package.json": "./package.json",
|
|
36
|
+
"./imports/isTooling.ts": null,
|
|
36
37
|
"./rules/imports/bundleInputs.ts": null
|
|
37
38
|
},
|
|
38
39
|
"bin": {
|
|
@@ -58,19 +59,19 @@
|
|
|
58
59
|
"typescript": "npm:@typescript/typescript6@6.0.2"
|
|
59
60
|
},
|
|
60
61
|
"devDependencies": {
|
|
61
|
-
"@effect/platform-node": "4.0.
|
|
62
|
-
"@effect/platform-node-shared": "4.0.
|
|
63
|
-
"@effect/vitest": "4.0.
|
|
62
|
+
"@effect/platform-node": "4.0.4",
|
|
63
|
+
"@effect/platform-node-shared": "4.0.4",
|
|
64
|
+
"@effect/vitest": "4.0.4",
|
|
64
65
|
"@types/node": "24.19.1",
|
|
65
66
|
"@typescript/native": "npm:typescript@7.0.2",
|
|
66
|
-
"effect": "4.0.
|
|
67
|
-
"vitest": "
|
|
67
|
+
"effect": "4.0.4",
|
|
68
|
+
"vitest": "5.0.3"
|
|
68
69
|
},
|
|
69
70
|
"peerDependencies": {
|
|
70
|
-
"@effect/platform-node": "4.0.
|
|
71
|
-
"@effect/platform-node-shared": "4.0.
|
|
72
|
-
"effect": "4.0.
|
|
73
|
-
"vitest": "
|
|
71
|
+
"@effect/platform-node": "4.0.4",
|
|
72
|
+
"@effect/platform-node-shared": "4.0.4",
|
|
73
|
+
"effect": "4.0.4",
|
|
74
|
+
"vitest": "5.0.3"
|
|
74
75
|
},
|
|
75
76
|
"peerDependenciesMeta": {
|
|
76
77
|
"vitest": {
|
package/src/git/command.ts
CHANGED
package/src/hooks/preCommit.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
2
|
import { Console, Effect, Schema } from "effect";
|
|
3
|
-
import { ChildProcess, ChildProcessSpawner } from "effect/
|
|
3
|
+
import { ChildProcess, ChildProcessSpawner } from "effect/process";
|
|
4
4
|
import { lint } from "#cli/lint.ts";
|
|
5
5
|
import { loadConfig } from "#config/load.ts";
|
|
6
6
|
import { decodeWith, validOrFail } from "#decoded.ts";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { posix } from "node:path";
|
|
2
|
+
|
|
3
|
+
const TOOL_FOLDERS = new Set(["script", "scripts", "tooling"]);
|
|
4
|
+
|
|
5
|
+
const CONFIG_FILE = /(?:^|\.)config\.[cm]?[jt]sx?$/u;
|
|
6
|
+
|
|
7
|
+
export function isTooling(directory: string, path: string): boolean {
|
|
8
|
+
const local = posix.relative(directory, path);
|
|
9
|
+
const [folder = ""] = local.split("/");
|
|
10
|
+
return TOOL_FOLDERS.has(folder) || (!local.includes("/") && CONFIG_FILE.test(local));
|
|
11
|
+
}
|
package/src/imports/runtime.ts
CHANGED
|
@@ -1,10 +1,32 @@
|
|
|
1
|
-
import { statSync } from "node:fs";
|
|
1
|
+
import { readFileSync, statSync } from "node:fs";
|
|
2
2
|
import { join, posix } from "node:path";
|
|
3
3
|
import type { RuleInputs } from "#rule.ts";
|
|
4
|
+
import { isTooling } from "./isTooling.ts";
|
|
4
5
|
import { packageOf, type WorkspacePackage } from "./workspace.ts";
|
|
5
6
|
|
|
6
7
|
export type Runtime = "client" | "server" | "shared";
|
|
7
8
|
|
|
9
|
+
function executablePath(value: unknown): boolean {
|
|
10
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function hasExecutable(root: string, directory: string): boolean {
|
|
14
|
+
const path = join(root, directory, "package.json");
|
|
15
|
+
try {
|
|
16
|
+
const manifest: unknown = JSON.parse(readFileSync(path, "utf8"));
|
|
17
|
+
if (typeof manifest !== "object" || manifest === null || Array.isArray(manifest)) {
|
|
18
|
+
throw new Error("the manifest must be an object");
|
|
19
|
+
}
|
|
20
|
+
const bin: unknown = Reflect.get(manifest, "bin");
|
|
21
|
+
return executablePath(bin) || (typeof bin === "object" && bin !== null && !Array.isArray(bin) && Object.values(bin).some(executablePath));
|
|
22
|
+
} catch (cause) {
|
|
23
|
+
if (cause instanceof Error && "code" in cause && cause.code === "ENOENT") {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
throw new Error(`cannot read runtime policy at ${path}`, { cause });
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
8
30
|
function directoryExists(path: string): boolean {
|
|
9
31
|
try {
|
|
10
32
|
return statSync(path).isDirectory();
|
|
@@ -23,10 +45,14 @@ export function runtimeOf(inputs: RuleInputs, packages: readonly WorkspacePackag
|
|
|
23
45
|
.filter((owner) => ["client", "server"].some((folder) => directoryExists(join(inputs.root, owner.directory, "src", folder))))
|
|
24
46
|
.map((owner) => owner.directory),
|
|
25
47
|
);
|
|
48
|
+
const executable = new Set(owners.filter((owner) => hasExecutable(inputs.root, owner.directory)).map((owner) => owner.directory));
|
|
26
49
|
return (path) => {
|
|
27
50
|
const owner = packageOf(packages, path)?.directory ?? ".";
|
|
51
|
+
if (isTooling(owner, path)) {
|
|
52
|
+
return "server";
|
|
53
|
+
}
|
|
28
54
|
if (!adopted.has(owner)) {
|
|
29
|
-
return undefined;
|
|
55
|
+
return executable.has(owner) ? "server" : undefined;
|
|
30
56
|
}
|
|
31
57
|
const local = posix.relative(owner, path);
|
|
32
58
|
if (local.startsWith("src/client/")) {
|
|
@@ -2,7 +2,7 @@ import { definePatternRule } from "./pattern-rule.ts";
|
|
|
2
2
|
|
|
3
3
|
export const noEnvironmentPragma = definePatternRule({
|
|
4
4
|
description:
|
|
5
|
-
"A test file gets its environment from its name, not from a pragma: `*.dom.test.ts` runs in a DOM, every other test in Node. `@shivaedev/quality/
|
|
5
|
+
"A test file gets its environment from its name, not from a pragma: `*.dom.test.ts` runs in a DOM, every other test in Node. `@shivaedev/quality/testProjects.ts` sets up the Vitest projects that read the name.",
|
|
6
6
|
id: "comments/no-environment-pragma",
|
|
7
7
|
message: (match) => `Sets the test environment with "${match}". Name the file *.dom.test.ts or *.dom.test.tsx instead.`,
|
|
8
8
|
patterns: [/^@(?:vitest|jest)-environment(?:-options)?(?=\s|$)/mu],
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { posix } from "node:path";
|
|
2
2
|
import { type ImportGraph, importGraph } from "#imports/graph.ts";
|
|
3
|
+
import { isTooling } from "#imports/isTooling.ts";
|
|
3
4
|
import { builtinName } from "#imports/resolve.ts";
|
|
4
5
|
import { packageOf, type WorkspacePackage } from "#imports/workspace.ts";
|
|
5
6
|
import { isTestCode } from "#naming/testName.ts";
|
|
@@ -58,17 +59,8 @@ async function manifestDependencies(inputs: RuleInputs, owner: WorkspacePackage,
|
|
|
58
59
|
}
|
|
59
60
|
}
|
|
60
61
|
|
|
61
|
-
const TOOL_FOLDERS = new Set(["script", "scripts", "tooling"]);
|
|
62
|
-
|
|
63
|
-
const CONFIG_FILE = /(?:^|\.)config\.[cm]?[jt]sx?$/u;
|
|
64
|
-
|
|
65
62
|
function developmentFile(owner: WorkspacePackage, path: string): boolean {
|
|
66
|
-
|
|
67
|
-
return true;
|
|
68
|
-
}
|
|
69
|
-
const local = posix.relative(owner.directory, path);
|
|
70
|
-
const [folder = ""] = local.split("/");
|
|
71
|
-
return TOOL_FOLDERS.has(folder) || (!local.includes("/") && CONFIG_FILE.test(local));
|
|
63
|
+
return isTestCode(path) || isTooling(owner.directory, path);
|
|
72
64
|
}
|
|
73
65
|
|
|
74
66
|
function developmentImport(policy: ManifestDependencies | undefined, owner: WorkspacePackage, path: string, runtime: ReadonlySet<string>) {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { browserGlobals } from "#imports/browserGlobals.ts";
|
|
2
1
|
import { importGraph } from "#imports/graph.ts";
|
|
3
2
|
import { builtinName } from "#imports/resolve.ts";
|
|
4
3
|
import { type Runtime, runtimeOf } from "#imports/runtime.ts";
|
|
@@ -35,9 +34,14 @@ export const importsRuntime = defineRule({
|
|
|
35
34
|
},
|
|
36
35
|
];
|
|
37
36
|
});
|
|
38
|
-
|
|
37
|
+
const shared = inputs.sources.filter((file) => !isTestCode(file.path) && runtime(file.path) === "shared");
|
|
38
|
+
if (shared.length === 0) {
|
|
39
|
+
return imports;
|
|
40
|
+
}
|
|
41
|
+
const { browserGlobals } = await import("#imports/browserGlobals.ts");
|
|
42
|
+
return [...imports, ...shared.flatMap(browserGlobals)];
|
|
39
43
|
},
|
|
40
44
|
description:
|
|
41
|
-
"
|
|
45
|
+
"Runtime folders define client, server and shared code. Executable packages without runtime folders and package-root tooling are server code.",
|
|
42
46
|
id: "imports/runtime",
|
|
43
47
|
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { defaultExclude, type TestUserConfig } from "vitest/config";
|
|
2
|
+
import type { Environment } from "#naming/testName.ts";
|
|
3
|
+
|
|
4
|
+
const EXTENSION = "?(c|m)[jt]s?(x)";
|
|
5
|
+
|
|
6
|
+
const TYPECHECK_ALONE = `**/typecheck.test.${EXTENSION}`;
|
|
7
|
+
|
|
8
|
+
function named(environment?: Environment): string {
|
|
9
|
+
return environment === undefined ? `**/*.@(test|spec).${EXTENSION}` : `**/*.${environment}.@(test|spec).${EXTENSION}`;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function excluding(...patterns: readonly string[]): string[] {
|
|
13
|
+
return [...defaultExclude, named("typecheck"), TYPECHECK_ALONE, ...patterns];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function testProjects(...options: readonly never[]): TestUserConfig {
|
|
17
|
+
if (options.length > 0) {
|
|
18
|
+
throw new Error("testProjects takes no options. Remove suite exclusions; every test belongs in its named project.");
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
project: ["unit", "dom"],
|
|
22
|
+
projects: [
|
|
23
|
+
{ extends: true, test: { environment: "node", exclude: excluding(named("dom"), named("slow")), include: [named()], name: "unit" } },
|
|
24
|
+
{ extends: true, test: { environment: "happy-dom", exclude: excluding(named("slow")), include: [named("dom")], name: "dom" } },
|
|
25
|
+
{ extends: true, test: { environment: "node", exclude: excluding(), include: [named("slow")], name: "slow" } },
|
|
26
|
+
],
|
|
27
|
+
// Tests that start real servers, browsers or CLIs need seconds on a busy CI runner, and Vitest's 5s default fails them for load, not behavior.
|
|
28
|
+
testTimeout: 30_000,
|
|
29
|
+
};
|
|
30
|
+
}
|
package/dist/vitest.d.ts
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { type TestProjectConfiguration, type TestUserConfig } from "vitest/config";
|
|
2
|
-
export declare function testProjects(...options: readonly never[]): TestUserConfig;
|
|
3
|
-
export declare function inheritTags(projects: readonly TestProjectConfiguration[], root: string): Promise<TestProjectConfiguration[]>;
|
|
4
|
-
//# sourceMappingURL=vitest.d.ts.map
|
package/dist/vitest.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"vitest.d.ts","sourceRoot":"","sources":["../src/vitest.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkB,KAAK,wBAAwB,EAA0B,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAe3H,wBAAgB,YAAY,CAAC,GAAG,OAAO,EAAE,SAAS,KAAK,EAAE,GAAG,cAAc,CAczE;AAsBD,wBAAgB,WAAW,CAAC,QAAQ,EAAE,SAAS,wBAAwB,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,EAAE,CAAC,CAW5H"}
|
package/dist/vitest.js
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
2
|
-
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3
|
-
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
-
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
-
});
|
|
6
|
-
}
|
|
7
|
-
return path;
|
|
8
|
-
};
|
|
9
|
-
import { resolve } from "node:path";
|
|
10
|
-
import { pathToFileURL } from "node:url";
|
|
11
|
-
import { defaultExclude } from "vitest/config";
|
|
12
|
-
const EXTENSION = "?(c|m)[jt]s?(x)";
|
|
13
|
-
const TYPECHECK_ALONE = `**/typecheck.test.${EXTENSION}`;
|
|
14
|
-
function named(environment) {
|
|
15
|
-
return environment === undefined ? `**/*.@(test|spec).${EXTENSION}` : `**/*.${environment}.@(test|spec).${EXTENSION}`;
|
|
16
|
-
}
|
|
17
|
-
function excluding(...patterns) {
|
|
18
|
-
return [...defaultExclude, named("typecheck"), TYPECHECK_ALONE, ...patterns];
|
|
19
|
-
}
|
|
20
|
-
export function testProjects(...options) {
|
|
21
|
-
if (options.length > 0) {
|
|
22
|
-
throw new Error("testProjects takes no options. Remove suite exclusions; every test belongs in its named project.");
|
|
23
|
-
}
|
|
24
|
-
return {
|
|
25
|
-
project: ["unit", "dom"],
|
|
26
|
-
projects: [
|
|
27
|
-
{ extends: true, test: { environment: "node", exclude: excluding(named("dom"), named("slow")), include: [named()], name: "unit" } },
|
|
28
|
-
{ extends: true, test: { environment: "happy-dom", exclude: excluding(named("slow")), include: [named("dom")], name: "dom" } },
|
|
29
|
-
{ extends: true, test: { environment: "node", exclude: excluding(), include: [named("slow")], name: "slow" } },
|
|
30
|
-
],
|
|
31
|
-
// Tests that start real servers, browsers or CLIs need seconds on a busy CI runner, and Vitest's 5s default fails them for load, not behavior.
|
|
32
|
-
testTimeout: 30_000,
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
function isConfigFunction(value) {
|
|
36
|
-
return typeof value === "function";
|
|
37
|
-
}
|
|
38
|
-
function tagsOf(config) {
|
|
39
|
-
const test = typeof config === "object" && config !== null && "test" in config ? config.test : undefined;
|
|
40
|
-
const tags = typeof test === "object" && test !== null && "tags" in test ? test.tags : undefined;
|
|
41
|
-
return Array.isArray(tags)
|
|
42
|
-
? tags.filter((tag) => typeof tag === "object" && tag !== null && typeof tag.name === "string")
|
|
43
|
-
: [];
|
|
44
|
-
}
|
|
45
|
-
async function declaredTags(configFile) {
|
|
46
|
-
const loaded = await import(__rewriteRelativeImportExtension(pathToFileURL(configFile).href));
|
|
47
|
-
return tagsOf(isConfigFunction(loaded.default) ? await loaded.default({ command: "serve", mode: "test" }) : await loaded.default);
|
|
48
|
-
}
|
|
49
|
-
// Vitest reads an inline project's tags only from the project itself, never from the config file it extends.
|
|
50
|
-
export function inheritTags(projects, root) {
|
|
51
|
-
return Promise.all(projects.map(async (project) => {
|
|
52
|
-
if (typeof project !== "object" || !("extends" in project) || typeof project.extends !== "string") {
|
|
53
|
-
return project;
|
|
54
|
-
}
|
|
55
|
-
const own = project.test?.tags ?? [];
|
|
56
|
-
const inherited = (await declaredTags(resolve(root, project.extends))).filter((tag) => !own.some((mine) => mine.name === tag.name));
|
|
57
|
-
return { ...project, test: { ...project.test, tags: [...own, ...inherited] } };
|
|
58
|
-
}));
|
|
59
|
-
}
|
|
60
|
-
//# sourceMappingURL=vitest.js.map
|
package/dist/vitest.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"vitest.js","sourceRoot":"","sources":["../src/vitest.ts"],"names":[],"mappings":"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"}
|
package/src/vitest.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { resolve } from "node:path";
|
|
2
|
-
import { pathToFileURL } from "node:url";
|
|
3
|
-
import { defaultExclude, type TestProjectConfiguration, type TestTagDefinition, type TestUserConfig } from "vitest/config";
|
|
4
|
-
import type { Environment } from "#naming/testName.ts";
|
|
5
|
-
|
|
6
|
-
const EXTENSION = "?(c|m)[jt]s?(x)";
|
|
7
|
-
|
|
8
|
-
const TYPECHECK_ALONE = `**/typecheck.test.${EXTENSION}`;
|
|
9
|
-
|
|
10
|
-
function named(environment?: Environment): string {
|
|
11
|
-
return environment === undefined ? `**/*.@(test|spec).${EXTENSION}` : `**/*.${environment}.@(test|spec).${EXTENSION}`;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function excluding(...patterns: readonly string[]): string[] {
|
|
15
|
-
return [...defaultExclude, named("typecheck"), TYPECHECK_ALONE, ...patterns];
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function testProjects(...options: readonly never[]): TestUserConfig {
|
|
19
|
-
if (options.length > 0) {
|
|
20
|
-
throw new Error("testProjects takes no options. Remove suite exclusions; every test belongs in its named project.");
|
|
21
|
-
}
|
|
22
|
-
return {
|
|
23
|
-
project: ["unit", "dom"],
|
|
24
|
-
projects: [
|
|
25
|
-
{ extends: true, test: { environment: "node", exclude: excluding(named("dom"), named("slow")), include: [named()], name: "unit" } },
|
|
26
|
-
{ extends: true, test: { environment: "happy-dom", exclude: excluding(named("slow")), include: [named("dom")], name: "dom" } },
|
|
27
|
-
{ extends: true, test: { environment: "node", exclude: excluding(), include: [named("slow")], name: "slow" } },
|
|
28
|
-
],
|
|
29
|
-
// Tests that start real servers, browsers or CLIs need seconds on a busy CI runner, and Vitest's 5s default fails them for load, not behavior.
|
|
30
|
-
testTimeout: 30_000,
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
type ConfigFunction = (env: { readonly command: "serve"; readonly mode: "test" }) => unknown;
|
|
35
|
-
|
|
36
|
-
function isConfigFunction(value: unknown): value is ConfigFunction {
|
|
37
|
-
return typeof value === "function";
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function tagsOf(config: unknown): readonly TestTagDefinition[] {
|
|
41
|
-
const test = typeof config === "object" && config !== null && "test" in config ? config.test : undefined;
|
|
42
|
-
const tags = typeof test === "object" && test !== null && "tags" in test ? test.tags : undefined;
|
|
43
|
-
return Array.isArray(tags)
|
|
44
|
-
? tags.filter((tag): tag is TestTagDefinition => typeof tag === "object" && tag !== null && typeof tag.name === "string")
|
|
45
|
-
: [];
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
async function declaredTags(configFile: string): Promise<readonly TestTagDefinition[]> {
|
|
49
|
-
const loaded: { readonly default?: unknown } = await import(pathToFileURL(configFile).href);
|
|
50
|
-
return tagsOf(isConfigFunction(loaded.default) ? await loaded.default({ command: "serve", mode: "test" }) : await loaded.default);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Vitest reads an inline project's tags only from the project itself, never from the config file it extends.
|
|
54
|
-
export function inheritTags(projects: readonly TestProjectConfiguration[], root: string): Promise<TestProjectConfiguration[]> {
|
|
55
|
-
return Promise.all(
|
|
56
|
-
projects.map(async (project) => {
|
|
57
|
-
if (typeof project !== "object" || !("extends" in project) || typeof project.extends !== "string") {
|
|
58
|
-
return project;
|
|
59
|
-
}
|
|
60
|
-
const own = project.test?.tags ?? [];
|
|
61
|
-
const inherited = (await declaredTags(resolve(root, project.extends))).filter((tag) => !own.some((mine) => mine.name === tag.name));
|
|
62
|
-
return { ...project, test: { ...project.test, tags: [...own, ...inherited] } };
|
|
63
|
-
}),
|
|
64
|
-
);
|
|
65
|
-
}
|