resultar 3.3.0 → 3.4.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 +55 -16
- package/dist/index.d.ts +898 -112
- package/dist/index.js +267 -10
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -71,21 +71,6 @@ import type { StrictResult } from 'resultar'
|
|
|
71
71
|
|
|
72
72
|
CommonJS `require('resultar')` is not exported.
|
|
73
73
|
|
|
74
|
-
## Mutation Testing
|
|
75
|
-
|
|
76
|
-
The core runtime package has a scoped Stryker setup for mutation testing:
|
|
77
|
-
|
|
78
|
-
```sh
|
|
79
|
-
pnpm --filter resultar test:mutation
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
The setup lives in [`stryker.conf.json`](./stryker.conf.json) and is intentionally separate from
|
|
83
|
-
`check:full`. It mutates the central runtime files under `src/`, uses the Vitest runner with
|
|
84
|
-
per-test coverage, stores incremental state under `reports/`, and keeps baseline thresholds
|
|
85
|
-
report-only while the mutation score is established. The dedicated
|
|
86
|
-
[`vitest-stryker.config.ts`](./vitest-stryker.config.ts) maps `vite-plus/test` to `vitest` so
|
|
87
|
-
Stryker can run the same tests without the `vp test` bootstrap.
|
|
88
|
-
|
|
89
74
|
## Why Teams Use It
|
|
90
75
|
|
|
91
76
|
This signature hides an expected failure:
|
|
@@ -174,6 +159,31 @@ const getPosts = (
|
|
|
174
159
|
)
|
|
175
160
|
```
|
|
176
161
|
|
|
162
|
+
The same flow can be written linearly with `safeTry` when the chain gets harder to scan:
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
const getPostsLinear = (
|
|
166
|
+
url: string,
|
|
167
|
+
): StrictResultAsync<Post[], FetchPostsError | HttpClientError | ParsePostsError> =>
|
|
168
|
+
safeTry(async function* () {
|
|
169
|
+
const response = yield* tryResultAsync(
|
|
170
|
+
fetch(url),
|
|
171
|
+
(cause) => new FetchPostsError({ cause }),
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
if (response.status >= 400) {
|
|
175
|
+
return HttpClientError.err({ status: response.status })
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const posts = yield* tryResultAsync(
|
|
179
|
+
response.json() as Promise<Post[]>,
|
|
180
|
+
(cause) => new ParsePostsError({ cause }),
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
return ok(posts)
|
|
184
|
+
})
|
|
185
|
+
```
|
|
186
|
+
|
|
177
187
|
## Async Control Without A Runtime
|
|
178
188
|
|
|
179
189
|
The 3.1 async helpers cover common production workflows while keeping plain `Promise` and
|
|
@@ -826,6 +836,27 @@ Use `fromPromise` when you already have a promise and need to map rejection into
|
|
|
826
836
|
const user = fromPromise(loadUserFromRemote(id), (cause) => new FetchUserError({ cause, id }))
|
|
827
837
|
```
|
|
828
838
|
|
|
839
|
+
Use `tryResultAsync` when the async boundary is the thing you want to name and document. The object
|
|
840
|
+
form is useful for infrastructure helpers because the task and error mapper stay together:
|
|
841
|
+
|
|
842
|
+
```ts
|
|
843
|
+
import { createTaggedError, tryResultAsync } from 'resultar'
|
|
844
|
+
import type { StrictResultAsync } from 'resultar'
|
|
845
|
+
|
|
846
|
+
type AsyncTask = () => Promise<void>
|
|
847
|
+
|
|
848
|
+
class TaskError extends createTaggedError({
|
|
849
|
+
name: 'TaskError',
|
|
850
|
+
message: 'Task failed: $label',
|
|
851
|
+
}) {}
|
|
852
|
+
|
|
853
|
+
const tryTask = (label: string, task: AsyncTask): StrictResultAsync<void, TaskError> =>
|
|
854
|
+
tryResultAsync({
|
|
855
|
+
try: task,
|
|
856
|
+
catch: (cause) => new TaskError({ cause, label }),
|
|
857
|
+
})
|
|
858
|
+
```
|
|
859
|
+
|
|
829
860
|
After that edge conversion, keep your own domain functions returning `Result` values instead of
|
|
830
861
|
throwing expected failures.
|
|
831
862
|
|
|
@@ -952,11 +983,13 @@ Add a check script:
|
|
|
952
983
|
```json
|
|
953
984
|
{
|
|
954
985
|
"scripts": {
|
|
955
|
-
"check": "resultar-check
|
|
986
|
+
"check": "resultar-check"
|
|
956
987
|
}
|
|
957
988
|
}
|
|
958
989
|
```
|
|
959
990
|
|
|
991
|
+
`resultar-check` defaults to `tsconfig.json` and runs TypeScript with no emit.
|
|
992
|
+
|
|
960
993
|
These fail in the default `must-use` mode:
|
|
961
994
|
|
|
962
995
|
```ts
|
|
@@ -980,15 +1013,21 @@ Configure Resultar rules in `tsconfig.json`:
|
|
|
980
1013
|
|
|
981
1014
|
```json
|
|
982
1015
|
{
|
|
1016
|
+
"$schema": "./node_modules/resultar-check/schema.json",
|
|
983
1017
|
"compilerOptions": {
|
|
984
1018
|
"plugins": [{ "name": "resultar-check", "noDiscard": "error" }]
|
|
985
1019
|
}
|
|
986
1020
|
}
|
|
987
1021
|
```
|
|
988
1022
|
|
|
1023
|
+
The package-local schema provides editor completion and validation for `resultar-check` plugin
|
|
1024
|
+
options.
|
|
1025
|
+
|
|
989
1026
|
Oxlint is intentionally not part of the Resultar rules path; use it only for general linting if your
|
|
990
1027
|
project wants it.
|
|
991
1028
|
|
|
1029
|
+
For VS Code and Zed setup, use the editor integration section in the `resultar-check` package guide.
|
|
1030
|
+
|
|
992
1031
|
## API Decision Guide
|
|
993
1032
|
|
|
994
1033
|
| Need | Use |
|