kvalita 1.22.0 → 1.24.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/README.md +48 -1
- package/configs/biome/no-await-expect-rejects.grit +5 -0
- package/configs/biome/no-double-cast.grit +5 -0
- package/configs/biome/no-expected-alias.grit +6 -0
- package/configs/biome/no-expected-boolean.grit +9 -0
- package/configs/biome/no-inline-each-table.grit +11 -0
- package/configs/biome/no-literal-equality-chain.grit +13 -0
- package/configs/biome/no-object-cast.grit +7 -0
- package/configs/biome/no-promise-catch.grit +6 -0
- package/configs/{biome.json → biome/shared.json} +35 -0
- package/configs/biome/use-regex-suffix.grit +11 -0
- package/configs/biome/use-should-title.grit +17 -0
- package/configs/biome/use-throwing-const.grit +13 -0
- package/configs/biome/use-to-be-undefined.grit +10 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -30,6 +30,26 @@ Create a `biome.json` file in your project root:
|
|
|
30
30
|
}
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
+
The config also runs GritQL plugins. Most of them target Bun tests:
|
|
34
|
+
|
|
35
|
+
- `await` before `expect(...).rejects`, since Bun tracks that assertion on its own.
|
|
36
|
+
- A callback written inline in `expect(() => fn()).toThrow()`, which reads better as `const throwing = () => fn()`.
|
|
37
|
+
- `const expected = value`, where asserting against `value` says the input comes back unchanged.
|
|
38
|
+
- `const expected = true` or `false`, where the boolean reads better inline in `toBe()`.
|
|
39
|
+
- `toBe(undefined)` and `toEqual(undefined)`, where `toBeUndefined()` says it directly.
|
|
40
|
+
- A test title that doesn't start with "should".
|
|
41
|
+
- A table written inline in `it.each(...)`, which reads better as a typed const above the call.
|
|
42
|
+
|
|
43
|
+
The rest apply to all code:
|
|
44
|
+
|
|
45
|
+
- `as unknown as`, which skips the type check entirely.
|
|
46
|
+
- An object literal cast with `as Type`, where an annotation checks every field. `as const` is fine.
|
|
47
|
+
- `.catch()` chained on a promise, where try/catch around an `await` is the house style. A fire-and-forget call behind `void` keeps its `.catch()`.
|
|
48
|
+
- Two or more `===` comparisons against literals in one condition, which read better as a named array and `.includes()`.
|
|
49
|
+
- A regex constant whose name doesn't end with `Regex`.
|
|
50
|
+
|
|
51
|
+
The plugins load from `node_modules/kvalita`, so the config expects kvalita installed at the project root.
|
|
52
|
+
|
|
33
53
|
### [Commitlint](https://github.com/conventional-changelog/commitlint) Configuration
|
|
34
54
|
|
|
35
55
|
Create a `commitlint.json` file in your project root:
|
|
@@ -111,7 +131,34 @@ jobs:
|
|
|
111
131
|
secrets: inherit
|
|
112
132
|
```
|
|
113
133
|
|
|
114
|
-
`shared-release` takes `branch`, `build`, `config` and `bun-version`; `shared-test` takes `bun-version`. Every one has a default, so a repo on the common setup passes nothing.
|
|
134
|
+
`shared-release` takes `branch`, `build`, `config` and `bun-version`; `shared-test` takes `bun-version` and `ref`. Every one has a default, so a repo on the common setup passes nothing. Start every release from `main` and pick the branch with `branch`: `shared-release` checks it out and tells semantic-release to release it. Pass the same branch as `ref` when a release job waits on `shared-test`, or the tests check `main` instead of the branch being released.
|
|
135
|
+
|
|
136
|
+
`shared-package` checks the package the way a consumer gets it. It builds the package, installs it into an empty project with `npm install --install-links`, so only the published files land there, and loads every entry point in `exports`: through `import`, and through `require()` where a `require` condition exists. It does that on every even Node.js major from the floor in `engines.node`, or 18 when it isn't set, up to the latest release. On the latest one, it also turns off syntax detection and `require()` of ESM files, which older versions don't have. Optional peers get installed too, since an entry point built on one needs it.
|
|
137
|
+
|
|
138
|
+
A second job checks the same entry points the way TypeScript and bundler users reach them. It type-checks them from an ESM and a CommonJS project under each module resolution (`node10`, `node16`, `nodenext` and `bundler`) with `strict` and `skipLibCheck: false`, and fails only on errors in the package's own types. It also bundles them with Vite as a server build. With `browser: true`, it bundles them for the browser as well. Every setup only imports what the package claims: CommonJS files only use entry points with a `require` condition, and `node10` only checks the root entry, when the package has a top-level `types`.
|
|
139
|
+
|
|
140
|
+
It takes `ref`, `bun-version` and `browser`:
|
|
141
|
+
|
|
142
|
+
```yaml
|
|
143
|
+
# .github/workflows/package.yml
|
|
144
|
+
name: Package
|
|
145
|
+
on:
|
|
146
|
+
push:
|
|
147
|
+
branches: [main, alpha, beta, rc]
|
|
148
|
+
pull_request:
|
|
149
|
+
workflow_call:
|
|
150
|
+
inputs:
|
|
151
|
+
ref:
|
|
152
|
+
type: string
|
|
153
|
+
default: ''
|
|
154
|
+
jobs:
|
|
155
|
+
package:
|
|
156
|
+
uses: macieklamberski/kvalita/.github/workflows/shared-package.yml@main
|
|
157
|
+
with:
|
|
158
|
+
ref: ${{ inputs.ref }}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
The `workflow_call` trigger lets the release workflow run it as a gate with `ref: ${{ inputs.branch }}`, next to `shared-test`.
|
|
115
162
|
|
|
116
163
|
### Ignore File Templates
|
|
117
164
|
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
language js
|
|
2
|
+
|
|
3
|
+
`await expect($value).rejects.$matcher($args)` where {
|
|
4
|
+
register_diagnostic(span=$value, message="Drop the await: Bun tracks an expect(...).rejects assertion on its own. Name the call as `const throwing = () => fn()` and assert `expect(throwing()).rejects...`.")
|
|
5
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
language js
|
|
2
|
+
|
|
3
|
+
`$left === $first || $left === $second` where {
|
|
4
|
+
$first <: or {
|
|
5
|
+
string(),
|
|
6
|
+
number()
|
|
7
|
+
},
|
|
8
|
+
$second <: or {
|
|
9
|
+
string(),
|
|
10
|
+
number()
|
|
11
|
+
},
|
|
12
|
+
register_diagnostic(span=$left, message="Put the literals in a named array and check membership with `.includes()`.")
|
|
13
|
+
}
|
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://biomejs.dev/schemas/latest/schema.json",
|
|
3
3
|
"root": false,
|
|
4
|
+
"plugins": [
|
|
5
|
+
"./node_modules/kvalita/configs/biome/no-await-expect-rejects.grit",
|
|
6
|
+
"./node_modules/kvalita/configs/biome/no-double-cast.grit",
|
|
7
|
+
"./node_modules/kvalita/configs/biome/no-expected-alias.grit",
|
|
8
|
+
"./node_modules/kvalita/configs/biome/no-expected-boolean.grit",
|
|
9
|
+
"./node_modules/kvalita/configs/biome/no-inline-each-table.grit",
|
|
10
|
+
"./node_modules/kvalita/configs/biome/no-literal-equality-chain.grit",
|
|
11
|
+
"./node_modules/kvalita/configs/biome/no-object-cast.grit",
|
|
12
|
+
"./node_modules/kvalita/configs/biome/no-promise-catch.grit",
|
|
13
|
+
"./node_modules/kvalita/configs/biome/use-throwing-const.grit",
|
|
14
|
+
"./node_modules/kvalita/configs/biome/use-regex-suffix.grit",
|
|
15
|
+
"./node_modules/kvalita/configs/biome/use-should-title.grit",
|
|
16
|
+
"./node_modules/kvalita/configs/biome/use-to-be-undefined.grit"
|
|
17
|
+
],
|
|
4
18
|
"vcs": {
|
|
5
19
|
"enabled": true,
|
|
6
20
|
"clientKind": "git",
|
|
@@ -45,7 +59,9 @@
|
|
|
45
59
|
"noMultiAssign": "error",
|
|
46
60
|
"noMultilineString": "error",
|
|
47
61
|
"noNestedTernary": "error",
|
|
62
|
+
"noNonNullAssertion": "error",
|
|
48
63
|
"noParameterAssign": "error",
|
|
64
|
+
"noProcessEnv": "error",
|
|
49
65
|
"noSubstr": "error",
|
|
50
66
|
"noUnusedTemplateLiteral": "error",
|
|
51
67
|
"noUselessElse": "error",
|
|
@@ -78,6 +94,7 @@
|
|
|
78
94
|
"useShorthandAssign": "error",
|
|
79
95
|
"useSingleVarDeclarator": "error",
|
|
80
96
|
"useSpreadOverApply": "error",
|
|
97
|
+
"useTemplate": "error",
|
|
81
98
|
"useThrowNewError": "error",
|
|
82
99
|
"useThrowOnlyError": "error",
|
|
83
100
|
"useTrimStartEnd": "error"
|
|
@@ -101,10 +118,13 @@
|
|
|
101
118
|
"suspicious": {
|
|
102
119
|
"noDuplicatedSpreadProps": "error",
|
|
103
120
|
"noEmptySource": "error",
|
|
121
|
+
"noFocusedTests": "error",
|
|
104
122
|
"noForIn": "error",
|
|
123
|
+
"noMisplacedAssertion": "error",
|
|
105
124
|
"noParametersOnlyUsedInRecursion": "error",
|
|
106
125
|
"noProto": "error",
|
|
107
126
|
"noReturnAssign": "error",
|
|
127
|
+
"noSkippedTests": "error",
|
|
108
128
|
"noVar": "error",
|
|
109
129
|
"useArraySortCompare": "error",
|
|
110
130
|
"useAwait": "error",
|
|
@@ -117,6 +137,21 @@
|
|
|
117
137
|
},
|
|
118
138
|
"security": {
|
|
119
139
|
"noScriptUrl": "error"
|
|
140
|
+
},
|
|
141
|
+
"nursery": {
|
|
142
|
+
"noConditionalExpect": "error",
|
|
143
|
+
"noFloatingPromises": "error",
|
|
144
|
+
"noIdenticalTestTitle": "error",
|
|
145
|
+
"useConsistentFunctionStyle": {
|
|
146
|
+
"level": "error",
|
|
147
|
+
"options": {
|
|
148
|
+
"style": "expression"
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
"useConsistentTestIt": "error",
|
|
152
|
+
"useNullishCoalescing": "error",
|
|
153
|
+
"useTestHooksOnTop": "error",
|
|
154
|
+
"useValidTestTitle": "error"
|
|
120
155
|
}
|
|
121
156
|
}
|
|
122
157
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
language js
|
|
2
|
+
|
|
3
|
+
`const $name = $value` where {
|
|
4
|
+
$value <: or {
|
|
5
|
+
r"^/.+/[dgimsuvy]*$",
|
|
6
|
+
`new RegExp($pattern)`,
|
|
7
|
+
`new RegExp($pattern, $flags)`
|
|
8
|
+
},
|
|
9
|
+
not $name <: r".*Regex$",
|
|
10
|
+
register_diagnostic(span=$name, message="End a regex constant's name with `Regex`.")
|
|
11
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
language js
|
|
2
|
+
|
|
3
|
+
`$test($title, $callback)` where {
|
|
4
|
+
$test <: or {
|
|
5
|
+
`it`,
|
|
6
|
+
`test`,
|
|
7
|
+
`it.todo`,
|
|
8
|
+
`it.skip`,
|
|
9
|
+
`it.only`,
|
|
10
|
+
`test.todo`,
|
|
11
|
+
`test.skip`,
|
|
12
|
+
`test.only`
|
|
13
|
+
},
|
|
14
|
+
$title <: r"^['\"`].*",
|
|
15
|
+
not $title <: r"^['\"`]should .*",
|
|
16
|
+
register_diagnostic(span=$title, message="Start the test title with \"should\".")
|
|
17
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
language js
|
|
2
|
+
|
|
3
|
+
`expect($callback).$matcher($args)` where {
|
|
4
|
+
$callback <: or {
|
|
5
|
+
`() => $body`,
|
|
6
|
+
`async () => $body`
|
|
7
|
+
},
|
|
8
|
+
$matcher <: or {
|
|
9
|
+
`toThrow`,
|
|
10
|
+
`toThrowError`
|
|
11
|
+
},
|
|
12
|
+
register_diagnostic(span=$callback, message="Name the throwing call: `const throwing = () => fn()`, then `expect(throwing).toThrow(...)`.")
|
|
13
|
+
}
|
package/package.json
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"configs"
|
|
16
16
|
],
|
|
17
17
|
"exports": {
|
|
18
|
-
"./biome": "./configs/biome.json",
|
|
18
|
+
"./biome": "./configs/biome/shared.json",
|
|
19
19
|
"./commitlint": "./configs/commitlint.json",
|
|
20
20
|
"./semantic-release": "./configs/semantic-release.json",
|
|
21
21
|
"./semantic-release-dry-run": "./configs/semantic-release-dry-run.json"
|
|
@@ -37,9 +37,10 @@
|
|
|
37
37
|
"@commitlint/cli": "^21.2.2",
|
|
38
38
|
"@commitlint/config-conventional": "^21.2.2",
|
|
39
39
|
"conventional-changelog-conventionalcommits": "^9.3.1",
|
|
40
|
+
"kvalita": "file:.",
|
|
40
41
|
"lefthook": "^2.1.14",
|
|
41
42
|
"semantic-release": "^25.0.9",
|
|
42
43
|
"typescript": "^7.0.2"
|
|
43
44
|
},
|
|
44
|
-
"version": "1.
|
|
45
|
+
"version": "1.24.0"
|
|
45
46
|
}
|