@rexezuge/tooling 0.0.0-stage → 1.0.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/LICENSE +21 -0
- package/README.md +297 -2
- package/dist/eslint.d.ts +120 -0
- package/dist/eslint.d.ts.map +1 -0
- package/dist/eslint.js +551 -0
- package/dist/eslint.js.map +1 -0
- package/dist/functions/pages-proxy.d.ts +113 -0
- package/dist/functions/pages-proxy.d.ts.map +1 -0
- package/dist/functions/pages-proxy.js +131 -0
- package/dist/functions/pages-proxy.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/scripts/backup/d1-target.d.ts +35 -0
- package/dist/scripts/backup/d1-target.d.ts.map +1 -0
- package/dist/scripts/backup/d1-target.js +31 -0
- package/dist/scripts/backup/d1-target.js.map +1 -0
- package/dist/scripts/backup/destination-config.d.ts +61 -0
- package/dist/scripts/backup/destination-config.d.ts.map +1 -0
- package/dist/scripts/backup/destination-config.js +57 -0
- package/dist/scripts/backup/destination-config.js.map +1 -0
- package/dist/scripts/backup/encrypt-backup.d.ts +35 -0
- package/dist/scripts/backup/encrypt-backup.d.ts.map +1 -0
- package/dist/scripts/backup/encrypt-backup.js +98 -0
- package/dist/scripts/backup/encrypt-backup.js.map +1 -0
- package/dist/scripts/backup/naming.d.ts +44 -0
- package/dist/scripts/backup/naming.d.ts.map +1 -0
- package/dist/scripts/backup/naming.js +58 -0
- package/dist/scripts/backup/naming.js.map +1 -0
- package/dist/scripts/check-god-files.d.ts +164 -0
- package/dist/scripts/check-god-files.d.ts.map +1 -0
- package/dist/scripts/check-god-files.js +271 -0
- package/dist/scripts/check-god-files.js.map +1 -0
- package/dist/scripts/ensure-spa-shell-stub.d.ts +3 -0
- package/dist/scripts/ensure-spa-shell-stub.d.ts.map +1 -0
- package/dist/scripts/ensure-spa-shell-stub.js +30 -0
- package/dist/scripts/ensure-spa-shell-stub.js.map +1 -0
- package/dist/scripts/init-secrets.d.ts +63 -0
- package/dist/scripts/init-secrets.d.ts.map +1 -0
- package/dist/scripts/init-secrets.js +240 -0
- package/dist/scripts/init-secrets.js.map +1 -0
- package/dist/scripts/lib/cli-args.d.ts +78 -0
- package/dist/scripts/lib/cli-args.d.ts.map +1 -0
- package/dist/scripts/lib/cli-args.js +116 -0
- package/dist/scripts/lib/cli-args.js.map +1 -0
- package/dist/scripts/lib/github-actions.d.ts +26 -0
- package/dist/scripts/lib/github-actions.d.ts.map +1 -0
- package/dist/scripts/lib/github-actions.js +38 -0
- package/dist/scripts/lib/github-actions.js.map +1 -0
- package/dist/scripts/lib/wrangler-table.d.ts +46 -0
- package/dist/scripts/lib/wrangler-table.d.ts.map +1 -0
- package/dist/scripts/lib/wrangler-table.js +99 -0
- package/dist/scripts/lib/wrangler-table.js.map +1 -0
- package/dist/scripts/migrations-lock.d.ts +3 -0
- package/dist/scripts/migrations-lock.d.ts.map +1 -0
- package/dist/scripts/migrations-lock.js +46 -0
- package/dist/scripts/migrations-lock.js.map +1 -0
- package/dist/scripts/prepare-wrangler-config.d.ts +3 -0
- package/dist/scripts/prepare-wrangler-config.d.ts.map +1 -0
- package/dist/scripts/prepare-wrangler-config.js +50 -0
- package/dist/scripts/prepare-wrangler-config.js.map +1 -0
- package/dist/scripts/spa-shell.d.ts +41 -0
- package/dist/scripts/spa-shell.d.ts.map +1 -0
- package/dist/scripts/spa-shell.js +155 -0
- package/dist/scripts/spa-shell.js.map +1 -0
- package/dist/scripts/validate-locales.d.ts +26 -0
- package/dist/scripts/validate-locales.d.ts.map +1 -0
- package/dist/scripts/validate-locales.js +350 -0
- package/dist/scripts/validate-locales.js.map +1 -0
- package/dist/scripts/verify-migrations.d.ts +62 -0
- package/dist/scripts/verify-migrations.d.ts.map +1 -0
- package/dist/scripts/verify-migrations.js +302 -0
- package/dist/scripts/verify-migrations.js.map +1 -0
- package/dist/scripts/verify-spa-shell.d.ts +3 -0
- package/dist/scripts/verify-spa-shell.d.ts.map +1 -0
- package/dist/scripts/verify-spa-shell.js +53 -0
- package/dist/scripts/verify-spa-shell.js.map +1 -0
- package/dist/scripts/wrangler-config/cli.d.ts +22 -0
- package/dist/scripts/wrangler-config/cli.d.ts.map +1 -0
- package/dist/scripts/wrangler-config/cli.js +51 -0
- package/dist/scripts/wrangler-config/cli.js.map +1 -0
- package/dist/scripts/wrangler-config/patches.d.ts +51 -0
- package/dist/scripts/wrangler-config/patches.d.ts.map +1 -0
- package/dist/scripts/wrangler-config/patches.js +140 -0
- package/dist/scripts/wrangler-config/patches.js.map +1 -0
- package/dist/scripts/wrangler-config/resources.d.ts +70 -0
- package/dist/scripts/wrangler-config/resources.d.ts.map +1 -0
- package/dist/scripts/wrangler-config/resources.js +290 -0
- package/dist/scripts/wrangler-config/resources.js.map +1 -0
- package/dist/scripts/wrangler-config/types.d.ts +103 -0
- package/dist/scripts/wrangler-config/types.d.ts.map +1 -0
- package/dist/scripts/wrangler-config/types.js +49 -0
- package/dist/scripts/wrangler-config/types.js.map +1 -0
- package/dist/test/integration-migrations.d.ts +167 -0
- package/dist/test/integration-migrations.d.ts.map +1 -0
- package/dist/test/integration-migrations.js +171 -0
- package/dist/test/integration-migrations.js.map +1 -0
- package/dist/test/mocks/cloudflare-workers.d.ts +106 -0
- package/dist/test/mocks/cloudflare-workers.d.ts.map +1 -0
- package/dist/test/mocks/cloudflare-workers.js +90 -0
- package/dist/test/mocks/cloudflare-workers.js.map +1 -0
- package/dist/vite.d.ts +117 -0
- package/dist/vite.d.ts.map +1 -0
- package/dist/vite.js +125 -0
- package/dist/vite.js.map +1 -0
- package/dist/vitest-web.d.ts +73 -0
- package/dist/vitest-web.d.ts.map +1 -0
- package/dist/vitest-web.js +72 -0
- package/dist/vitest-web.js.map +1 -0
- package/dist/vitest.d.ts +92 -0
- package/dist/vitest.d.ts.map +1 -0
- package/dist/vitest.js +128 -0
- package/dist/vitest.js.map +1 -0
- package/package.json +58 -3
- package/src/eslint.test.ts +175 -0
- package/src/eslint.ts +640 -0
- package/src/functions/pages-proxy.test.ts +72 -0
- package/src/functions/pages-proxy.ts +187 -0
- package/src/github/actions/retry-step/action.yml +39 -0
- package/src/github/actions/setup-env/action.yml +20 -0
- package/src/github/dependabot.yml +30 -0
- package/src/github/workflows/backup-main.yml +46 -0
- package/src/github/workflows/continuous-deployment.yml +188 -0
- package/src/github/workflows/continuous-integration.yml +259 -0
- package/src/github/workflows/scheduled-version-update.yml +38 -0
- package/src/github/workflows/upstream-sync.yml +56 -0
- package/src/index.ts +42 -0
- package/src/scripts/backup/backup-rules.test.ts +105 -0
- package/src/scripts/backup/d1-target.ts +54 -0
- package/src/scripts/backup/destination-config.ts +92 -0
- package/src/scripts/backup/encrypt-backup.ts +107 -0
- package/src/scripts/backup/naming.ts +62 -0
- package/src/scripts/check-god-files.test.ts +131 -0
- package/src/scripts/check-god-files.ts +327 -0
- package/src/scripts/ensure-spa-shell-stub.ts +34 -0
- package/src/scripts/init-secrets.ts +265 -0
- package/src/scripts/lib/cli-args.ts +154 -0
- package/src/scripts/lib/github-actions.ts +41 -0
- package/src/scripts/lib/wrangler-table.ts +105 -0
- package/src/scripts/migrations-lock.ts +52 -0
- package/src/scripts/prepare-wrangler-config.ts +51 -0
- package/src/scripts/spa-shell.test.ts +91 -0
- package/src/scripts/spa-shell.ts +179 -0
- package/src/scripts/validate-locales.test.ts +89 -0
- package/src/scripts/validate-locales.ts +380 -0
- package/src/scripts/verify-migrations.test.ts +71 -0
- package/src/scripts/verify-migrations.ts +364 -0
- package/src/scripts/verify-spa-shell.ts +56 -0
- package/src/scripts/wrangler-config/cli.ts +51 -0
- package/src/scripts/wrangler-config/patches.ts +157 -0
- package/src/scripts/wrangler-config/resources.ts +330 -0
- package/src/scripts/wrangler-config/types.ts +113 -0
- package/src/test/integration-migrations.test.ts +169 -0
- package/src/test/integration-migrations.ts +267 -0
- package/src/test/mocks/cloudflare-workers.ts +115 -0
- package/src/vite.test.ts +83 -0
- package/src/vite.ts +202 -0
- package/src/vitest-web.ts +109 -0
- package/src/vitest.ts +185 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The SPA's test and coverage gate.
|
|
3
|
+
*
|
|
4
|
+
* Provenance: converged from Durable-DAV-Router's and Mail-Otter's
|
|
5
|
+
* `vitest.web.config.mts`, which are the two repos that gave the frontend its own
|
|
6
|
+
* suite. Durable-DAV-Router's is the canonical shape — it is the one that records
|
|
7
|
+
* *why* the split exists; Mail-Otter's contributes the React plugin and the
|
|
8
|
+
* `apps/web/**` include.
|
|
9
|
+
*
|
|
10
|
+
* Canonical decisions:
|
|
11
|
+
*
|
|
12
|
+
* 1. **It is a separate config, not a `projects` entry in one.** With a single
|
|
13
|
+
* config the SPA suites ran under `node` and the worker suites under `jsdom`
|
|
14
|
+
* in the same pass, so a test could pass in one environment and fail in the
|
|
15
|
+
* other with neither run noticing.
|
|
16
|
+
* 2. **`pool: 'threads'`, bounded, rather than one forked worker per file.** Each
|
|
17
|
+
* jsdom document is a whole browser environment; a fork per file exhausts
|
|
18
|
+
* memory on a constrained machine, and when it does the run dies partway with
|
|
19
|
+
* a bare "Worker exited unexpectedly" and no test reports a failure — which
|
|
20
|
+
* reads as a flaky suite rather than as an out-of-memory kill.
|
|
21
|
+
* 3. **jsdom is set here for every file**, rather than a `@vitest-environment`
|
|
22
|
+
* pragma per file: these are the tests that need a DOM, and the pragma is one
|
|
23
|
+
* more place to forget.
|
|
24
|
+
* 4. **`include` covers both shapes the repos use** — the root-suite `web-*`
|
|
25
|
+
* naming convention and suites bundled under `apps/web` — and the same globs
|
|
26
|
+
* are what `defineUnitVitestConfig()` excludes.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import { defineConfig, type Plugin } from 'vitest/config';
|
|
30
|
+
import { fileURLToPath } from 'node:url';
|
|
31
|
+
import type { CoverageThresholds, VitestAlias } from './vitest';
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* What `defineWebVitestConfig` accepts.
|
|
35
|
+
*/
|
|
36
|
+
export interface WebVitestConfigOptions {
|
|
37
|
+
/**
|
|
38
|
+
* Vite plugins the SPA needs — `@vitejs/plugin-react` for a React app. Passed
|
|
39
|
+
* by the consumer rather than imported here, because the kit must stay
|
|
40
|
+
* zero-dependency and the plugin belongs to the app, not the harness.
|
|
41
|
+
*/
|
|
42
|
+
readonly plugins?: readonly Plugin[];
|
|
43
|
+
/**
|
|
44
|
+
* Extra resolver entries.
|
|
45
|
+
*/
|
|
46
|
+
readonly aliases?: readonly VitestAlias[];
|
|
47
|
+
/**
|
|
48
|
+
* The repo root, as a file URL.
|
|
49
|
+
*/
|
|
50
|
+
readonly root?: string;
|
|
51
|
+
/**
|
|
52
|
+
* Which suites to collect. Defaults to both shapes the source repos use.
|
|
53
|
+
*/
|
|
54
|
+
readonly include?: readonly string[];
|
|
55
|
+
/**
|
|
56
|
+
* Coverage floors. Omitted by default; see `defineUnitVitestConfig`.
|
|
57
|
+
*/
|
|
58
|
+
readonly thresholds?: CoverageThresholds;
|
|
59
|
+
/**
|
|
60
|
+
* Where the coverage report is written. Separate from the unit config's, so
|
|
61
|
+
* the two gates never overwrite each other's report.
|
|
62
|
+
*/
|
|
63
|
+
readonly reportsDirectory?: string;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* The default suite globs: the root-suite `web-*` convention and the
|
|
68
|
+
* bundled-under-`apps/web` convention, so either layout works unchanged.
|
|
69
|
+
*/
|
|
70
|
+
const DEFAULT_INCLUDE: readonly string[] = ['test/**/web-*.test.{ts,tsx}', 'apps/web/**/*.test.{ts,tsx}'];
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Build the SPA's test config.
|
|
74
|
+
*
|
|
75
|
+
* ```ts
|
|
76
|
+
* // vitest.web.config.mts
|
|
77
|
+
* import react from '@vitejs/plugin-react';
|
|
78
|
+
* import { defineWebVitestConfig } from '@rexezuge/tooling/vitest-web';
|
|
79
|
+
* export default defineWebVitestConfig({ plugins: [react()] });
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
export function defineWebVitestConfig(options: WebVitestConfigOptions = {}): ReturnType<typeof defineConfig> {
|
|
83
|
+
const root = options.root ?? new URL('.', import.meta.url).href;
|
|
84
|
+
const webSrc = fileURLToPath(new URL('apps/web/src', root));
|
|
85
|
+
const aliases: VitestAlias[] = [{ find: /^@\//, replacement: `${webSrc}/` }, ...(options.aliases ?? [])];
|
|
86
|
+
|
|
87
|
+
return defineConfig({
|
|
88
|
+
...(options.plugins !== undefined && { plugins: [...options.plugins] }),
|
|
89
|
+
resolve: { alias: aliases },
|
|
90
|
+
test: {
|
|
91
|
+
globals: true,
|
|
92
|
+
environment: 'jsdom',
|
|
93
|
+
include: [...(options.include ?? DEFAULT_INCLUDE)],
|
|
94
|
+
// Threads, bounded, rather than one forked worker per file — see the
|
|
95
|
+
// header. A custom `exclude` replaces Vitest's defaults, so `node_modules`
|
|
96
|
+
// must be re-listed.
|
|
97
|
+
pool: 'threads',
|
|
98
|
+
exclude: ['**/node_modules/**', '**/dist/**', 'test/integration/**'],
|
|
99
|
+
coverage: {
|
|
100
|
+
provider: 'v8',
|
|
101
|
+
reporter: ['text', 'lcov'],
|
|
102
|
+
reportsDirectory: options.reportsDirectory ?? './coverage-spa',
|
|
103
|
+
include: ['apps/web/src/**/*.{ts,tsx}'],
|
|
104
|
+
exclude: ['**/*.test.{ts,tsx}', '**/*.d.ts', '**/types.ts', '**/generated/**'],
|
|
105
|
+
...(options.thresholds !== undefined && { thresholds: { ...options.thresholds } }),
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
}
|
package/src/vitest.ts
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The unit-test Vitest config for the worker-and-packages half of the suite.
|
|
3
|
+
*
|
|
4
|
+
* Provenance: converged from the eight repos' `vitest.config.mts`. The coverage
|
|
5
|
+
* block is Durable-DAV-Router's (the most complete: v8 provider, explicit
|
|
6
|
+
* include/exclude patterns, thresholds with the reasoning for why they sit just
|
|
7
|
+
* under the measured value); the alias block is Durable-DAV's, which is the only
|
|
8
|
+
* one that also aliases `cloudflare:workers` and `cloudflare:sockets` to the
|
|
9
|
+
* Node mocks.
|
|
10
|
+
*
|
|
11
|
+
* Canonical decisions:
|
|
12
|
+
*
|
|
13
|
+
* 1. **Every file matching `include` is reported** — Vitest 4 removed
|
|
14
|
+
* `coverage.all`, and an explicit `include` now covers files no test
|
|
15
|
+
* imported. That is the behaviour the source repos configured `all: true` for,
|
|
16
|
+
* and the reason it mattered: without it a brand-new module with no test is
|
|
17
|
+
* invisible rather than counted as zero, which is the exact regression this
|
|
18
|
+
* gate exists to catch.
|
|
19
|
+
* 2. **The SPA is excluded here**, so this config and `defineWebVitestConfig()`
|
|
20
|
+
* partition the suite rather than each running all of it. Every SPA suite is
|
|
21
|
+
* named `web-*`. One number could not honestly describe both halves: the SPA's
|
|
22
|
+
* presentational modules pulled a shared floor down 16 points, so a change
|
|
23
|
+
* adding legitimate code in `apps/api` could fail the gate on the strength of
|
|
24
|
+
* files two directories away.
|
|
25
|
+
* 3. **A custom `exclude` re-lists `node_modules`** — `test/` is a workspace
|
|
26
|
+
* project and therefore has its own, so without the re-list the glob reaches
|
|
27
|
+
* into `test/node_modules` and tries to run other packages' suites.
|
|
28
|
+
* 4. **Thresholds are a consumer argument**, not a kit default. A floor is a
|
|
29
|
+
* per-repo ratchet measured against that repo's suite; the kit cannot know a
|
|
30
|
+
* number, and guessing one is how floors get lowered.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
import { defineConfig } from 'vitest/config';
|
|
34
|
+
import { fileURLToPath } from 'node:url';
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* One `{ find, replacement }` pair for Vitest's resolver.
|
|
38
|
+
*/
|
|
39
|
+
export interface VitestAlias {
|
|
40
|
+
readonly find: string | RegExp;
|
|
41
|
+
readonly replacement: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Coverage thresholds, in the four figures Vitest gates on.
|
|
46
|
+
*/
|
|
47
|
+
export interface CoverageThresholds {
|
|
48
|
+
readonly statements?: number;
|
|
49
|
+
readonly branches?: number;
|
|
50
|
+
readonly functions?: number;
|
|
51
|
+
readonly lines?: number;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* What `defineUnitVitestConfig` accepts. Every field is optional: the defaults
|
|
56
|
+
* cover the canonical monorepo layout, and a consumer overrides only what its
|
|
57
|
+
* tree actually differs in.
|
|
58
|
+
*/
|
|
59
|
+
export interface UnitVitestConfigOptions {
|
|
60
|
+
/**
|
|
61
|
+
* Extra resolver entries, applied after the canonical ones.
|
|
62
|
+
*/
|
|
63
|
+
readonly aliases?: readonly VitestAlias[];
|
|
64
|
+
/**
|
|
65
|
+
* Where the repo root is, as a file URL. Defaults to the directory this
|
|
66
|
+
* factory is *called* from, which is the repo root's `vitest.config.mts`.
|
|
67
|
+
*/
|
|
68
|
+
readonly root?: string;
|
|
69
|
+
/**
|
|
70
|
+
* Coverage `include` globs. Defaults to the worker plus every workspace
|
|
71
|
+
* package's `src`.
|
|
72
|
+
*/
|
|
73
|
+
readonly coverageInclude?: readonly string[];
|
|
74
|
+
/**
|
|
75
|
+
* Coverage `exclude` globs, merged with the canonical set.
|
|
76
|
+
*/
|
|
77
|
+
readonly coverageExclude?: readonly string[];
|
|
78
|
+
/**
|
|
79
|
+
* Coverage floors. Omitted by default; a repo that wants them sets them.
|
|
80
|
+
*/
|
|
81
|
+
readonly thresholds?: CoverageThresholds;
|
|
82
|
+
/**
|
|
83
|
+
* Where the coverage report is written.
|
|
84
|
+
*/
|
|
85
|
+
readonly reportsDirectory?: string;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* The SPA's suites, excluded here so the two configs partition the suite.
|
|
90
|
+
*
|
|
91
|
+
* Every SPA suite is named `web-*`. `defineWebVitestConfig()` includes the same
|
|
92
|
+
* glob, so a file is collected by exactly one config.
|
|
93
|
+
*/
|
|
94
|
+
const SPA_FILES = 'test/**/web-*.test.{ts,tsx}';
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* The canonical alias set.
|
|
98
|
+
*
|
|
99
|
+
* Built relative to the consumer's repo root rather than the kit's directory,
|
|
100
|
+
* so the factory describes *their* layout. A Vitest config is a standalone file
|
|
101
|
+
* with no module graph to share through, and a suite resolving a workspace
|
|
102
|
+
* import differently from its sibling fails in a way that looks like a product
|
|
103
|
+
* bug — which is why these are stated once, here, rather than duplicated.
|
|
104
|
+
*/
|
|
105
|
+
function canonicalAliases(root: string): VitestAlias[] {
|
|
106
|
+
const at = (relative: string): string => fileURLToPath(new URL(relative, root));
|
|
107
|
+
return [
|
|
108
|
+
{ find: 'cloudflare:workers', replacement: at('test/mocks/cloudflare-workers.ts') },
|
|
109
|
+
{ find: 'cloudflare:sockets', replacement: at('test/mocks/cloudflare-sockets.ts') },
|
|
110
|
+
{ find: /^@\//, replacement: `${at('apps/api/src')}/` },
|
|
111
|
+
{ find: /^~\//, replacement: `${at('apps/web/src')}/` },
|
|
112
|
+
];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Coverage `exclude` globs converged from the source repos.
|
|
117
|
+
*
|
|
118
|
+
* The categories: build and test tooling (`scripts/` grows with project surface,
|
|
119
|
+
* not complexity, and the god-file guard excludes it for the same reason), test
|
|
120
|
+
* files, declarations, re-export barrels (`index.ts` carries no logic of its
|
|
121
|
+
* own), model records, generated files (the SPA shell is a one-line HTML blob
|
|
122
|
+
* with no logic to exercise), and type-only modules.
|
|
123
|
+
*/
|
|
124
|
+
const CANONICAL_COVERAGE_EXCLUDE: readonly string[] = [
|
|
125
|
+
'scripts/**',
|
|
126
|
+
'**/*.test.ts',
|
|
127
|
+
'**/*.d.ts',
|
|
128
|
+
'**/index.ts',
|
|
129
|
+
'**/types.d.ts',
|
|
130
|
+
'**/model/**',
|
|
131
|
+
'**/generated/**',
|
|
132
|
+
'**/D1Types.ts',
|
|
133
|
+
'**/ServiceEnv.ts',
|
|
134
|
+
'**/env.d.ts',
|
|
135
|
+
];
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Build the unit-test config.
|
|
139
|
+
*
|
|
140
|
+
* ```ts
|
|
141
|
+
* // vitest.config.mts
|
|
142
|
+
* import { defineUnitVitestConfig } from '@rexezuge/tooling/vitest';
|
|
143
|
+
* export default defineUnitVitestConfig();
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
export function defineUnitVitestConfig(options: UnitVitestConfigOptions = {}): ReturnType<typeof defineConfig> {
|
|
147
|
+
const root = options.root ?? new URL('.', import.meta.url).href;
|
|
148
|
+
const coverageInclude = options.coverageInclude ?? ['apps/api/src/**/*.ts', 'apps/background/src/**/*.ts', 'packages/**/src/**/*.ts'];
|
|
149
|
+
const coverageExclude = [...CANONICAL_COVERAGE_EXCLUDE, ...(options.coverageExclude ?? [])];
|
|
150
|
+
const aliases = [...canonicalAliases(root), ...(options.aliases ?? [])];
|
|
151
|
+
|
|
152
|
+
return defineConfig({
|
|
153
|
+
resolve: { alias: aliases },
|
|
154
|
+
test: {
|
|
155
|
+
globals: true,
|
|
156
|
+
environment: 'node',
|
|
157
|
+
include: ['test/**/*.test.{ts,tsx}'],
|
|
158
|
+
// `test` is a workspace project and therefore has its own node_modules;
|
|
159
|
+
// without the re-list, the glob reaches into it.
|
|
160
|
+
exclude: ['**/node_modules/**', '**/dist/**', 'test/integration/**', SPA_FILES],
|
|
161
|
+
server: {
|
|
162
|
+
deps: {
|
|
163
|
+
// A `node_modules` dependency is externalized by default, so Node's
|
|
164
|
+
// own ESM loader resolves a `cloudflare:workers` specifier and rejects
|
|
165
|
+
// the scheme before `resolve.alias` is ever consulted. Inlining routes
|
|
166
|
+
// it back through Vite, where the alias applies.
|
|
167
|
+
inline: ['dofs'],
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
coverage: {
|
|
171
|
+
provider: 'v8',
|
|
172
|
+
// Vitest 4 removed `coverage.all`; an explicit `include` now reports
|
|
173
|
+
// every matching file whether or not a test imported it, which is the
|
|
174
|
+
// behaviour the source repos' `all: true` was there to get: a brand-new
|
|
175
|
+
// module with no test is counted as zero rather than being invisible,
|
|
176
|
+
// which is the exact regression this gate exists to catch.
|
|
177
|
+
reporter: ['text', 'lcov', 'html'],
|
|
178
|
+
reportsDirectory: options.reportsDirectory ?? './coverage',
|
|
179
|
+
include: [...coverageInclude],
|
|
180
|
+
exclude: coverageExclude,
|
|
181
|
+
...(options.thresholds !== undefined && { thresholds: { ...options.thresholds } }),
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
}
|