@projitect/blueprint-vitest 0.0.0-stage → 1.0.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/LICENSE +21 -0
- package/dist/package.json +48 -0
- package/dist/src/index.d.ts +49 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +129 -0
- package/dist/src/index.js.map +1 -0
- package/package.json +45 -3
- package/src/index.ts +174 -0
- package/README.md +0 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kapil Easwar
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@projitect/blueprint-vitest",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Vitest scaffolding blueprint for projitect — owns vitest.config.ts, package.json scripts/devDeps, and the .gitignore coverage entry.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/projitect/projitect.git",
|
|
8
|
+
"directory": "packages/blueprint-vitest"
|
|
9
|
+
},
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"type": "module",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/src/index.d.ts",
|
|
15
|
+
"import": "./dist/src/index.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"src",
|
|
21
|
+
"!**/*.tsbuildinfo"
|
|
22
|
+
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "tsc --build",
|
|
25
|
+
"build:clean": "tsc --build --clean",
|
|
26
|
+
"tc": "tsc --build"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@projitect/blueprint": "workspace:*",
|
|
30
|
+
"@projitect/core": "workspace:*",
|
|
31
|
+
"@projitect/test-kit": "workspace:*",
|
|
32
|
+
"effect": "4.0.0-rc.111",
|
|
33
|
+
"typescript": "5.9.3"
|
|
34
|
+
},
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"@projitect/blueprint": "workspace:*",
|
|
37
|
+
"@projitect/core": "workspace:*",
|
|
38
|
+
"effect": "4.0.0-rc.111"
|
|
39
|
+
},
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=22.12.0"
|
|
42
|
+
},
|
|
43
|
+
"projitect": {
|
|
44
|
+
"type": "blueprint",
|
|
45
|
+
"import": "import { vitest } from \"@projitect/blueprint-vitest\"",
|
|
46
|
+
"call": "vitest()"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @projitect/blueprint-vitest
|
|
3
|
+
*
|
|
4
|
+
* One composite blueprint that wires vitest into a project:
|
|
5
|
+
*
|
|
6
|
+
* 1. Adds `vitest` and (optionally) `@vitest/coverage-v8` to `package.json`'s `devDependencies`,
|
|
7
|
+
* plus `test` / `test:watch` scripts. Merge mode — non-conflicting with whatever else lives
|
|
8
|
+
* in `package.json`.
|
|
9
|
+
* 2. Owns `vitest.config.ts` with sensible defaults (NodeNext-friendly, v8 coverage). Owned
|
|
10
|
+
* mode — projitect rewrites this file from scratch on every `remodel` so the user can't
|
|
11
|
+
* accidentally drift it. If the user wants project-specific overrides, they should compose
|
|
12
|
+
* this blueprint with their own `ownFile` blueprint at a different path.
|
|
13
|
+
* 3. Adds `coverage/` to `.gitignore`. Region mode — coexists with whatever else is in the file
|
|
14
|
+
* (including other projitect blueprints like `@projitect/blueprint-gitignore`).
|
|
15
|
+
*
|
|
16
|
+
* This is the smallest framework blueprint we ship after gitignore. It validates merge mode +
|
|
17
|
+
* owned mode + region mode in one move, and it's the first time the projitect blueprint won't
|
|
18
|
+
* be the *only* merge-mode consumer in a real project.
|
|
19
|
+
*/
|
|
20
|
+
import type { Blueprint } from "@projitect/core";
|
|
21
|
+
/**
|
|
22
|
+
* Options for the vitest blueprint. All optional; defaults give a working setup.
|
|
23
|
+
*/
|
|
24
|
+
export interface VitestOptions {
|
|
25
|
+
/**
|
|
26
|
+
* Coverage provider. Defaults to `"v8"`. Set to `null` to skip the coverage devDep and the
|
|
27
|
+
* `.gitignore` coverage entry (you'll get vitest without coverage configured).
|
|
28
|
+
*/
|
|
29
|
+
readonly coverage?: "v8" | null;
|
|
30
|
+
/**
|
|
31
|
+
* Override the script name for the one-shot test runner. Defaults to `"test"`.
|
|
32
|
+
* The watch variant is always `<scriptName>:watch`.
|
|
33
|
+
*/
|
|
34
|
+
readonly scriptName?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Test environment. Defaults to `"node"` (matches vitest's default). Set to `"jsdom"` if you
|
|
37
|
+
* want DOM globals — you'll also need to install `jsdom` separately; this blueprint does not
|
|
38
|
+
* add it because not every consumer needs it.
|
|
39
|
+
*/
|
|
40
|
+
readonly environment?: "node" | "jsdom";
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Build the composite vitest blueprint. The returned `Blueprint` emits three to four operations
|
|
44
|
+
* depending on options; the planner / lockfile track each separately so the user gets fine-
|
|
45
|
+
* grained drift reporting (e.g. "package.json merge drift on devDependencies.vitest" rather than
|
|
46
|
+
* a vague "blueprint drift").
|
|
47
|
+
*/
|
|
48
|
+
export declare const vitest: (options?: VitestOptions) => Blueprint.Blueprint;
|
|
49
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAWhD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,IAAI,GAAG,IAAI,CAAA;IAC/B;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CACxC;AAED;;;;;GAKG;AACH,eAAO,MAAM,MAAM,GAAI,UAAS,aAAkB,KAAG,SAAS,CAAC,SA+E9D,CAAA"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @projitect/blueprint-vitest
|
|
3
|
+
*
|
|
4
|
+
* One composite blueprint that wires vitest into a project:
|
|
5
|
+
*
|
|
6
|
+
* 1. Adds `vitest` and (optionally) `@vitest/coverage-v8` to `package.json`'s `devDependencies`,
|
|
7
|
+
* plus `test` / `test:watch` scripts. Merge mode — non-conflicting with whatever else lives
|
|
8
|
+
* in `package.json`.
|
|
9
|
+
* 2. Owns `vitest.config.ts` with sensible defaults (NodeNext-friendly, v8 coverage). Owned
|
|
10
|
+
* mode — projitect rewrites this file from scratch on every `remodel` so the user can't
|
|
11
|
+
* accidentally drift it. If the user wants project-specific overrides, they should compose
|
|
12
|
+
* this blueprint with their own `ownFile` blueprint at a different path.
|
|
13
|
+
* 3. Adds `coverage/` to `.gitignore`. Region mode — coexists with whatever else is in the file
|
|
14
|
+
* (including other projitect blueprints like `@projitect/blueprint-gitignore`).
|
|
15
|
+
*
|
|
16
|
+
* This is the smallest framework blueprint we ship after gitignore. It validates merge mode +
|
|
17
|
+
* owned mode + region mode in one move, and it's the first time the projitect blueprint won't
|
|
18
|
+
* be the *only* merge-mode consumer in a real project.
|
|
19
|
+
*/
|
|
20
|
+
import { Effect } from "effect";
|
|
21
|
+
import { regionFile, jsonMerge, ownFile } from "@projitect/blueprint";
|
|
22
|
+
import { ChangeSet as CS } from "@projitect/core";
|
|
23
|
+
import manifest from "../package.json" with { type: "json" };
|
|
24
|
+
// Read the version from the package manifest (emitted next to `dist/src`) so a release bump
|
|
25
|
+
// reaches `.pjt.lock` without a hand-edited constant. JSON import keeps this runtime-pure.
|
|
26
|
+
const PACKAGE_VERSION = manifest.version;
|
|
27
|
+
const VITEST_DEP_RANGE = "^4.0.0";
|
|
28
|
+
const COVERAGE_V8_DEP_RANGE = "^4.0.0";
|
|
29
|
+
/**
|
|
30
|
+
* Build the composite vitest blueprint. The returned `Blueprint` emits three to four operations
|
|
31
|
+
* depending on options; the planner / lockfile track each separately so the user gets fine-
|
|
32
|
+
* grained drift reporting (e.g. "package.json merge drift on devDependencies.vitest" rather than
|
|
33
|
+
* a vague "blueprint drift").
|
|
34
|
+
*/
|
|
35
|
+
export const vitest = (options = {}) => {
|
|
36
|
+
const coverage = options.coverage === undefined ? "v8" : options.coverage;
|
|
37
|
+
const scriptName = options.scriptName ?? "test";
|
|
38
|
+
const watchScript = `${scriptName}:watch`;
|
|
39
|
+
const environment = options.environment ?? "node";
|
|
40
|
+
const id = "pjt:vitest";
|
|
41
|
+
// We compose four constructor blueprints inline rather than handing four separate Blueprint
|
|
42
|
+
// entries to the user — that way `pjt add @projitect/blueprint-vitest` adds one call line, and
|
|
43
|
+
// every drift / removal is attributed to `pjt:vitest`. The composite plan just `Effect.all`s
|
|
44
|
+
// their `plan` Effects and concatenates the resulting ChangeSets.
|
|
45
|
+
const packageJsonMerge = jsonMerge({
|
|
46
|
+
id,
|
|
47
|
+
version: PACKAGE_VERSION,
|
|
48
|
+
description: "vitest devDependencies and test scripts",
|
|
49
|
+
path: "package.json",
|
|
50
|
+
ownedKeys: [
|
|
51
|
+
`scripts.${scriptName}`,
|
|
52
|
+
`scripts.${watchScript}`,
|
|
53
|
+
"devDependencies.vitest",
|
|
54
|
+
...(coverage === "v8" ? ["devDependencies.@vitest/coverage-v8"] : []),
|
|
55
|
+
],
|
|
56
|
+
value: {
|
|
57
|
+
scripts: {
|
|
58
|
+
[scriptName]: "vitest run",
|
|
59
|
+
[watchScript]: "vitest",
|
|
60
|
+
},
|
|
61
|
+
devDependencies: {
|
|
62
|
+
vitest: VITEST_DEP_RANGE,
|
|
63
|
+
...(coverage === "v8" && { "@vitest/coverage-v8": COVERAGE_V8_DEP_RANGE }),
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
const vitestConfig = ownFile({
|
|
68
|
+
id,
|
|
69
|
+
version: PACKAGE_VERSION,
|
|
70
|
+
description: "vitest configuration",
|
|
71
|
+
path: "vitest.config.ts",
|
|
72
|
+
content: renderVitestConfig({ coverage, environment }),
|
|
73
|
+
});
|
|
74
|
+
const gitignoreCoverage = coverage === "v8"
|
|
75
|
+
? regionFile({
|
|
76
|
+
id,
|
|
77
|
+
version: PACKAGE_VERSION,
|
|
78
|
+
description: "ignore vitest coverage output",
|
|
79
|
+
path: ".gitignore",
|
|
80
|
+
commentPrefix: "#",
|
|
81
|
+
content: "coverage/\n",
|
|
82
|
+
})
|
|
83
|
+
: null;
|
|
84
|
+
const composite = {
|
|
85
|
+
id,
|
|
86
|
+
version: PACKAGE_VERSION,
|
|
87
|
+
description: "vitest scaffolding (config + scripts + devDeps + coverage gitignore)",
|
|
88
|
+
permissions: [
|
|
89
|
+
{ kind: "read", glob: "package.json" },
|
|
90
|
+
{ kind: "write", glob: "package.json" },
|
|
91
|
+
{ kind: "write", glob: "vitest.config.ts" },
|
|
92
|
+
{ kind: "read", glob: ".gitignore" },
|
|
93
|
+
{ kind: "write", glob: ".gitignore" },
|
|
94
|
+
],
|
|
95
|
+
plan: Effect.gen(function* () {
|
|
96
|
+
const parts = [
|
|
97
|
+
packageJsonMerge,
|
|
98
|
+
vitestConfig,
|
|
99
|
+
...(gitignoreCoverage === null ? [] : [gitignoreCoverage]),
|
|
100
|
+
];
|
|
101
|
+
const changeSets = yield* Effect.forEach(parts, (b) => b.plan);
|
|
102
|
+
return CS.Reducer.combineAll(changeSets);
|
|
103
|
+
}),
|
|
104
|
+
};
|
|
105
|
+
return composite;
|
|
106
|
+
};
|
|
107
|
+
const renderVitestConfig = (params) => {
|
|
108
|
+
const lines = [
|
|
109
|
+
'import { defineConfig } from "vitest/config"',
|
|
110
|
+
"",
|
|
111
|
+
"/**",
|
|
112
|
+
" * vitest configuration scaffolded by `@projitect/blueprint-vitest`.",
|
|
113
|
+
" *",
|
|
114
|
+
" * Owned mode — projitect rewrites this file on every `pjt remodel`. If you need overrides,",
|
|
115
|
+
" * compose another `ownFile` blueprint at a different path (e.g. `vitest.config.local.ts`)",
|
|
116
|
+
" * and merge it into this config via vitest's own `mergeConfig` helper at runtime.",
|
|
117
|
+
" */",
|
|
118
|
+
"export default defineConfig({",
|
|
119
|
+
" test: {",
|
|
120
|
+
` environment: "${params.environment}",`,
|
|
121
|
+
" passWithNoTests: true,",
|
|
122
|
+
];
|
|
123
|
+
if (params.coverage === "v8") {
|
|
124
|
+
lines.push(" coverage: {", ' provider: "v8",', ' reporter: ["text", "html"],', " },");
|
|
125
|
+
}
|
|
126
|
+
lines.push(" },", "})", "");
|
|
127
|
+
return lines.join("\n");
|
|
128
|
+
};
|
|
129
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,48 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@projitect/blueprint-vitest",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Vitest scaffolding blueprint for projitect — owns vitest.config.ts, package.json scripts/devDeps, and the .gitignore coverage entry.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/projitect/projitect.git",
|
|
8
|
+
"directory": "packages/blueprint-vitest"
|
|
9
|
+
},
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"type": "module",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/src/index.d.ts",
|
|
15
|
+
"import": "./dist/src/index.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"src",
|
|
21
|
+
"!**/*.tsbuildinfo"
|
|
22
|
+
],
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"effect": "4.0.0-rc.111",
|
|
25
|
+
"typescript": "5.9.3",
|
|
26
|
+
"@projitect/blueprint": "1.0.1",
|
|
27
|
+
"@projitect/core": "1.0.1",
|
|
28
|
+
"@projitect/test-kit": "1.0.1"
|
|
29
|
+
},
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"effect": "4.0.0-rc.111",
|
|
32
|
+
"@projitect/blueprint": "1.0.1",
|
|
33
|
+
"@projitect/core": "1.0.1"
|
|
34
|
+
},
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=22.12.0"
|
|
37
|
+
},
|
|
38
|
+
"projitect": {
|
|
39
|
+
"type": "blueprint",
|
|
40
|
+
"import": "import { vitest } from \"@projitect/blueprint-vitest\"",
|
|
41
|
+
"call": "vitest()"
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "tsc --build",
|
|
45
|
+
"build:clean": "tsc --build --clean",
|
|
46
|
+
"tc": "tsc --build"
|
|
47
|
+
}
|
|
6
48
|
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @projitect/blueprint-vitest
|
|
3
|
+
*
|
|
4
|
+
* One composite blueprint that wires vitest into a project:
|
|
5
|
+
*
|
|
6
|
+
* 1. Adds `vitest` and (optionally) `@vitest/coverage-v8` to `package.json`'s `devDependencies`,
|
|
7
|
+
* plus `test` / `test:watch` scripts. Merge mode — non-conflicting with whatever else lives
|
|
8
|
+
* in `package.json`.
|
|
9
|
+
* 2. Owns `vitest.config.ts` with sensible defaults (NodeNext-friendly, v8 coverage). Owned
|
|
10
|
+
* mode — projitect rewrites this file from scratch on every `remodel` so the user can't
|
|
11
|
+
* accidentally drift it. If the user wants project-specific overrides, they should compose
|
|
12
|
+
* this blueprint with their own `ownFile` blueprint at a different path.
|
|
13
|
+
* 3. Adds `coverage/` to `.gitignore`. Region mode — coexists with whatever else is in the file
|
|
14
|
+
* (including other projitect blueprints like `@projitect/blueprint-gitignore`).
|
|
15
|
+
*
|
|
16
|
+
* This is the smallest framework blueprint we ship after gitignore. It validates merge mode +
|
|
17
|
+
* owned mode + region mode in one move, and it's the first time the projitect blueprint won't
|
|
18
|
+
* be the *only* merge-mode consumer in a real project.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { Effect } from "effect"
|
|
22
|
+
import { regionFile, jsonMerge, ownFile } from "@projitect/blueprint"
|
|
23
|
+
import type { Blueprint } from "@projitect/core"
|
|
24
|
+
import { ChangeSet as CS } from "@projitect/core"
|
|
25
|
+
import manifest from "../package.json" with { type: "json" }
|
|
26
|
+
|
|
27
|
+
// Read the version from the package manifest (emitted next to `dist/src`) so a release bump
|
|
28
|
+
// reaches `.pjt.lock` without a hand-edited constant. JSON import keeps this runtime-pure.
|
|
29
|
+
const PACKAGE_VERSION = manifest.version
|
|
30
|
+
|
|
31
|
+
const VITEST_DEP_RANGE = "^4.0.0"
|
|
32
|
+
const COVERAGE_V8_DEP_RANGE = "^4.0.0"
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Options for the vitest blueprint. All optional; defaults give a working setup.
|
|
36
|
+
*/
|
|
37
|
+
export interface VitestOptions {
|
|
38
|
+
/**
|
|
39
|
+
* Coverage provider. Defaults to `"v8"`. Set to `null` to skip the coverage devDep and the
|
|
40
|
+
* `.gitignore` coverage entry (you'll get vitest without coverage configured).
|
|
41
|
+
*/
|
|
42
|
+
readonly coverage?: "v8" | null
|
|
43
|
+
/**
|
|
44
|
+
* Override the script name for the one-shot test runner. Defaults to `"test"`.
|
|
45
|
+
* The watch variant is always `<scriptName>:watch`.
|
|
46
|
+
*/
|
|
47
|
+
readonly scriptName?: string
|
|
48
|
+
/**
|
|
49
|
+
* Test environment. Defaults to `"node"` (matches vitest's default). Set to `"jsdom"` if you
|
|
50
|
+
* want DOM globals — you'll also need to install `jsdom` separately; this blueprint does not
|
|
51
|
+
* add it because not every consumer needs it.
|
|
52
|
+
*/
|
|
53
|
+
readonly environment?: "node" | "jsdom"
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Build the composite vitest blueprint. The returned `Blueprint` emits three to four operations
|
|
58
|
+
* depending on options; the planner / lockfile track each separately so the user gets fine-
|
|
59
|
+
* grained drift reporting (e.g. "package.json merge drift on devDependencies.vitest" rather than
|
|
60
|
+
* a vague "blueprint drift").
|
|
61
|
+
*/
|
|
62
|
+
export const vitest = (options: VitestOptions = {}): Blueprint.Blueprint => {
|
|
63
|
+
const coverage = options.coverage === undefined ? "v8" : options.coverage
|
|
64
|
+
const scriptName = options.scriptName ?? "test"
|
|
65
|
+
const watchScript = `${scriptName}:watch`
|
|
66
|
+
const environment = options.environment ?? "node"
|
|
67
|
+
|
|
68
|
+
const id = "pjt:vitest"
|
|
69
|
+
|
|
70
|
+
// We compose four constructor blueprints inline rather than handing four separate Blueprint
|
|
71
|
+
// entries to the user — that way `pjt add @projitect/blueprint-vitest` adds one call line, and
|
|
72
|
+
// every drift / removal is attributed to `pjt:vitest`. The composite plan just `Effect.all`s
|
|
73
|
+
// their `plan` Effects and concatenates the resulting ChangeSets.
|
|
74
|
+
|
|
75
|
+
const packageJsonMerge = jsonMerge({
|
|
76
|
+
id,
|
|
77
|
+
version: PACKAGE_VERSION,
|
|
78
|
+
description: "vitest devDependencies and test scripts",
|
|
79
|
+
path: "package.json",
|
|
80
|
+
ownedKeys: [
|
|
81
|
+
`scripts.${scriptName}`,
|
|
82
|
+
`scripts.${watchScript}`,
|
|
83
|
+
"devDependencies.vitest",
|
|
84
|
+
...(coverage === "v8" ? ["devDependencies.@vitest/coverage-v8" as const] : []),
|
|
85
|
+
],
|
|
86
|
+
value: {
|
|
87
|
+
scripts: {
|
|
88
|
+
[scriptName]: "vitest run",
|
|
89
|
+
[watchScript]: "vitest",
|
|
90
|
+
},
|
|
91
|
+
devDependencies: {
|
|
92
|
+
vitest: VITEST_DEP_RANGE,
|
|
93
|
+
...(coverage === "v8" && { "@vitest/coverage-v8": COVERAGE_V8_DEP_RANGE }),
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
const vitestConfig = ownFile({
|
|
99
|
+
id,
|
|
100
|
+
version: PACKAGE_VERSION,
|
|
101
|
+
description: "vitest configuration",
|
|
102
|
+
path: "vitest.config.ts",
|
|
103
|
+
content: renderVitestConfig({ coverage, environment }),
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
const gitignoreCoverage =
|
|
107
|
+
coverage === "v8"
|
|
108
|
+
? regionFile({
|
|
109
|
+
id,
|
|
110
|
+
version: PACKAGE_VERSION,
|
|
111
|
+
description: "ignore vitest coverage output",
|
|
112
|
+
path: ".gitignore",
|
|
113
|
+
commentPrefix: "#",
|
|
114
|
+
content: "coverage/\n",
|
|
115
|
+
})
|
|
116
|
+
: null
|
|
117
|
+
|
|
118
|
+
const composite: Blueprint.Blueprint = {
|
|
119
|
+
id,
|
|
120
|
+
version: PACKAGE_VERSION,
|
|
121
|
+
description: "vitest scaffolding (config + scripts + devDeps + coverage gitignore)",
|
|
122
|
+
permissions: [
|
|
123
|
+
{ kind: "read", glob: "package.json" },
|
|
124
|
+
{ kind: "write", glob: "package.json" },
|
|
125
|
+
{ kind: "write", glob: "vitest.config.ts" },
|
|
126
|
+
{ kind: "read", glob: ".gitignore" },
|
|
127
|
+
{ kind: "write", glob: ".gitignore" },
|
|
128
|
+
],
|
|
129
|
+
plan: Effect.gen(function* () {
|
|
130
|
+
const parts = [
|
|
131
|
+
packageJsonMerge,
|
|
132
|
+
vitestConfig,
|
|
133
|
+
...(gitignoreCoverage === null ? [] : [gitignoreCoverage]),
|
|
134
|
+
]
|
|
135
|
+
const changeSets = yield* Effect.forEach(parts, (b) => b.plan)
|
|
136
|
+
return CS.Reducer.combineAll(changeSets)
|
|
137
|
+
}),
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return composite
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const renderVitestConfig = (params: {
|
|
144
|
+
readonly coverage: "v8" | null
|
|
145
|
+
readonly environment: "node" | "jsdom"
|
|
146
|
+
}): string => {
|
|
147
|
+
const lines: string[] = [
|
|
148
|
+
'import { defineConfig } from "vitest/config"',
|
|
149
|
+
"",
|
|
150
|
+
"/**",
|
|
151
|
+
" * vitest configuration scaffolded by `@projitect/blueprint-vitest`.",
|
|
152
|
+
" *",
|
|
153
|
+
" * Owned mode — projitect rewrites this file on every `pjt remodel`. If you need overrides,",
|
|
154
|
+
" * compose another `ownFile` blueprint at a different path (e.g. `vitest.config.local.ts`)",
|
|
155
|
+
" * and merge it into this config via vitest's own `mergeConfig` helper at runtime.",
|
|
156
|
+
" */",
|
|
157
|
+
"export default defineConfig({",
|
|
158
|
+
" test: {",
|
|
159
|
+
` environment: "${params.environment}",`,
|
|
160
|
+
" passWithNoTests: true,",
|
|
161
|
+
]
|
|
162
|
+
|
|
163
|
+
if (params.coverage === "v8") {
|
|
164
|
+
lines.push(
|
|
165
|
+
" coverage: {",
|
|
166
|
+
' provider: "v8",',
|
|
167
|
+
' reporter: ["text", "html"],',
|
|
168
|
+
" },",
|
|
169
|
+
)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
lines.push(" },", "})", "")
|
|
173
|
+
return lines.join("\n")
|
|
174
|
+
}
|
package/README.md
DELETED