Skip to content

Commit 33a3693

Browse files
authored
Merge pull request #28 from lydell/updates
2 parents 44383ed + e252cbb commit 33a3693

24 files changed

+2243
-7677
lines changed

.eslintrc.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const warn = process.argv.includes("--report-unused-disable-directives")
55

66
module.exports = {
77
root: true,
8-
plugins: ["@typescript-eslint", "simple-import-sort", "jest"],
8+
plugins: ["@typescript-eslint", "simple-import-sort", "vitest"],
99
parser: "@typescript-eslint/parser",
1010
parserOptions: {
1111
sourceType: "module",
@@ -44,7 +44,7 @@ module.exports = {
4444
"@typescript-eslint/no-base-to-string": error,
4545
"@typescript-eslint/no-confusing-void-expression": error,
4646
"@typescript-eslint/no-dupe-class-members": error,
47-
"@typescript-eslint/no-duplicate-imports": warn,
47+
"@typescript-eslint/no-duplicate-type-constituents": error,
4848
"@typescript-eslint/no-empty-function": warn,
4949
"@typescript-eslint/no-empty-interface": warn,
5050
"@typescript-eslint/no-explicit-any": warn,
@@ -104,7 +104,7 @@ module.exports = {
104104
"@typescript-eslint/restrict-plus-operands": error,
105105
"@typescript-eslint/restrict-template-expressions": error,
106106
"@typescript-eslint/return-await": error,
107-
"@typescript-eslint/sort-type-union-intersection-members": warn,
107+
"@typescript-eslint/sort-type-constituents": warn,
108108
"@typescript-eslint/strict-boolean-expressions": [
109109
error,
110110
{
@@ -202,15 +202,15 @@ module.exports = {
202202
},
203203
{
204204
files: "tests/**/*.ts",
205-
extends: ["plugin:jest/recommended", "plugin:jest/style"],
205+
extends: "plugin:vitest/recommended",
206206
parserOptions: {
207207
tsconfigRootDir: __dirname,
208208
project: ["./tests/tsconfig.json"],
209209
},
210210
},
211211
{
212212
files: "examples/**/*.ts",
213-
extends: ["plugin:jest/recommended", "plugin:jest/style"],
213+
extends: "plugin:vitest/recommended",
214214
parserOptions: {
215215
tsconfigRootDir: __dirname,
216216
project: ["./examples/tsconfig.json"],

.github/workflows/check.yml

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
strategy:
1414
matrix:
1515
os: [ubuntu-latest]
16-
node-version: [18.x]
16+
node-version: [20.x]
1717

1818
steps:
1919
- uses: actions/checkout@v3
@@ -22,19 +22,15 @@ jobs:
2222
with:
2323
node-version: "${{ matrix.node-version }}"
2424

25-
- name: Cache node_modules
26-
id: cache-node_modules
25+
- id: cache-node_modules
2726
uses: actions/cache@v3
2827
with:
2928
path: node_modules
3029
key: node_modules-${{ matrix.os }}-${{ matrix.node-version }}-${{ hashFiles('package.json', 'package-lock.json') }}
3130

32-
- name: npm ci
33-
if: steps.cache-node_modules.outputs.cache-hit != 'true'
34-
run: npm ci
31+
- if: steps.cache-node_modules.outputs.cache-hit != 'true'
32+
run: npm ci --no-audit
3533

36-
- name: ESLint
37-
run: npx eslint --report-unused-disable-directives .
34+
- run: npx eslint --report-unused-disable-directives .
3835

39-
- name: Prettier
40-
run: npx prettier --check .
36+
- run: npx prettier --check .

.github/workflows/test.yml

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
strategy:
1414
matrix:
1515
os: [ubuntu-latest, macOS-latest, windows-latest]
16-
node-version: [14.x, 16.x, 18.x]
16+
node-version: [16.x, 18.x, 20.x]
1717

1818
steps:
1919
- uses: actions/checkout@v3
@@ -22,19 +22,15 @@ jobs:
2222
with:
2323
node-version: "${{ matrix.node-version }}"
2424

25-
- name: Cache node_modules
26-
id: cache-node_modules
25+
- id: cache-node_modules
2726
uses: actions/cache@v3
2827
with:
2928
path: node_modules
3029
key: node_modules-${{ matrix.os }}-${{ matrix.node-version }}-${{ hashFiles('package.json', 'package-lock.json') }}
3130

32-
- name: npm ci
33-
if: steps.cache-node_modules.outputs.cache-hit != 'true'
34-
run: npm ci
31+
- if: steps.cache-node_modules.outputs.cache-hit != 'true'
32+
run: npm ci --no-audit
3533

36-
- name: Jest
37-
run: npx jest --coverage
34+
- run: npx vitest
3835

39-
- name: Build
40-
run: npm run build
36+
- run: npm run build

README.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ const userDecoder = fields(
4444
active: field("is_active", boolean),
4545
age: field("age", optional(number)),
4646
interests: field("interests", array(string)),
47-
})
47+
}),
4848
);
4949

5050
const payload: unknown = getSomeJSON();
@@ -299,7 +299,7 @@ Decodes a JSON string into a TypeScript `string`.
299299

300300
```ts
301301
function stringUnion<T extends [string, ...Array<string>]>(
302-
variants: T
302+
variants: T,
303303
): Decoder<T[number]>;
304304
```
305305

@@ -347,15 +347,15 @@ For example, `record(number)` decodes an object where the keys can be anything a
347347
function fields<T>(
348348
callback: (
349349
field: <U>(key: string, decoder: Decoder<U>) => U,
350-
object: Record<string, unknown>
350+
object: Record<string, unknown>,
351351
) => T,
352352
{
353353
exact = "allow extra",
354354
allow = "object",
355355
}: {
356356
exact?: "allow extra" | "throw";
357357
allow?: "array" | "object";
358-
} = {}
358+
} = {},
359359
): Decoder<T>;
360360
```
361361

@@ -386,7 +386,7 @@ const userDecoder = fields(
386386
description: field("description", optional(string)),
387387
// Hardcoded field:
388388
version: 1,
389-
})
389+
}),
390390
);
391391

392392
// Plucking a single field out of an object:
@@ -460,7 +460,7 @@ type Values<T> = T[keyof T];
460460

461461
function fieldsUnion<T extends Record<string, Decoder<unknown>>>(
462462
key: string,
463-
mapping: T
463+
mapping: T,
464464
): Decoder<
465465
Values<{ [P in keyof T]: T[P] extends Decoder<infer U, infer _> ? U : never }>
466466
>;
@@ -498,7 +498,7 @@ See also the [renaming union field example](examples/renaming-union-field.test.t
498498
499499
```ts
500500
function tuple<T extends Array<unknown>>(
501-
mapping: readonly [...{ [P in keyof T]: Decoder<T[P]> }]
501+
mapping: readonly [...{ [P in keyof T]: Decoder<T[P]> }],
502502
): Decoder<[...T]>;
503503
```
504504
@@ -524,7 +524,7 @@ function multi<
524524
T4 = never,
525525
T5 = never,
526526
T6 = never,
527-
T7 = never
527+
T7 = never,
528528
>(mapping: {
529529
undefined?: Decoder<T1, undefined>;
530530
null?: Decoder<T2, null>;
@@ -590,7 +590,7 @@ Example:
590590
```ts
591591
const numberSetDecoder: Decoder<Set<number>> = chain(
592592
array(number),
593-
(arr) => new Set(arr)
593+
(arr) => new Set(arr),
594594
);
595595
```
596596
@@ -658,7 +658,7 @@ class DecoderError extends TypeError {
658658
constructor(
659659
params:
660660
| { message: string; value: unknown; key?: Key }
661-
| (DecoderErrorVariant & { key?: Key })
661+
| (DecoderErrorVariant & { key?: Key }),
662662
);
663663

664664
static MISSING_VALUE: symbol;
@@ -714,7 +714,7 @@ const decoder: Decoder<Array<[RegExp, number]>> = Decode.chain(
714714
} catch (error) {
715715
throw Decode.DecoderError.at(error, key);
716716
}
717-
})
717+
}),
718718
);
719719
```
720720
@@ -752,7 +752,7 @@ function repr(
752752
maxLength = 100,
753753
recurseMaxLength = 20,
754754
sensitive = false,
755-
}: ReprOptions = {}
755+
}: ReprOptions = {},
756756
): string;
757757
```
758758
@@ -819,7 +819,7 @@ const personDecoder = fields(
819819
(field): Person => ({
820820
name: field("name", string),
821821
age: field("age", optional(number)),
822-
})
822+
}),
823823
);
824824

825825
// Annotate the generic.
@@ -897,7 +897,7 @@ This decoder would ignore its input and always “succeed” with a given value.
897897
```ts
898898
export function either<T, U>(
899899
decoder1: Decoder<T>,
900-
decoder2: Decoder<U>
900+
decoder2: Decoder<U>,
901901
): Decoder<T | U>;
902902
```
903903

examples/chain.test.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { expect, test } from "vitest";
2+
13
import {
24
array,
35
chain,
@@ -60,7 +62,7 @@ test("decoding to a Set", () => {
6062
id: field("id", string),
6163
numbers: field(
6264
"numbers",
63-
optional(chain(array(number), (arr) => new Set(arr)))
65+
optional(chain(array(number), (arr) => new Set(arr))),
6466
),
6567
}));
6668
expect(objDecoder2(obj)).toEqual(objDecoder1(obj));

examples/extra-fields.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { expect, test } from "vitest";
2+
13
import { chain, Decoder, fields, fieldsAuto, number, string } from "..";
24

35
test("adding extra fields to records", () => {
@@ -17,7 +19,7 @@ test("adding extra fields to records", () => {
1719
name: field("name", string),
1820
price: field("price", number),
1921
version: 1,
20-
})
22+
}),
2123
);
2224

2325
expect(productDecoder1(data)).toMatchInlineSnapshot(`
@@ -58,7 +60,7 @@ test("adding extra fields to records", () => {
5860
name: string,
5961
price: number,
6062
}),
61-
(props) => ({ ...props, version: 1 })
63+
(props) => ({ ...props, version: 1 }),
6264
);
6365

6466
expect(productDecoder4(data)).toEqual(productDecoder3(data));

examples/readme.test.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { expect, test } from "vitest";
2+
13
import {
24
array,
35
boolean,
@@ -15,7 +17,7 @@ import {
1517
function run<T>(
1618
decoder: Decoder<T>,
1719
value: unknown,
18-
options?: ReprOptions
20+
options?: ReprOptions,
1921
): T | string {
2022
try {
2123
return decoder(value);
@@ -47,7 +49,7 @@ test("the main readme example", () => {
4749
active: field("is_active", boolean),
4850
age: field("age", optional(number)),
4951
interests: field("interests", array(string)),
50-
})
52+
}),
5153
);
5254

5355
const payload: unknown = getSomeJSON();
@@ -186,7 +188,7 @@ test("fields", () => {
186188
description: field("description", optional(string)),
187189
// Hardcoded field:
188190
version: 1,
189-
})
191+
}),
190192
);
191193

192194
expect(
@@ -195,7 +197,7 @@ test("fields", () => {
195197
is_active: true,
196198
first_name: "John",
197199
last_name: "Doe",
198-
})
200+
}),
199201
).toStrictEqual({
200202
active: true,
201203
age: 30,
@@ -221,7 +223,7 @@ test("type annotations", () => {
221223
(field): Person => ({
222224
name: field("name", string),
223225
age: field("age", optional(number)),
224-
})
226+
}),
225227
);
226228

227229
// Annotate the generic.

examples/recursive.test.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { expect, test, vi } from "vitest";
2+
13
import { array, Decoder, fields, multi, record, string } from "../";
24

35
test("recursive data structure", () => {
@@ -12,7 +14,7 @@ test("recursive data structure", () => {
1214
(field): Person => ({
1315
name: field("name", string),
1416
friends: field("friends", array(personDecoder1)),
15-
})
17+
}),
1618
);
1719

1820
// But when using `fieldsAuto` you’d run into problems.
@@ -78,7 +80,7 @@ test("recurse non-record", () => {
7880
object: (value) => dictDecoder(value),
7981
// Writing just `object: dictDecoder` would result in an error:
8082
// ReferenceError: Cannot access 'dictDecoder' before initialization
81-
})
83+
}),
8284
);
8385

8486
const data: unknown = {
@@ -120,7 +122,7 @@ test("circular objects", () => {
120122
(field): Person => ({
121123
name: field("name", string),
122124
likes: field("likes", personDecoder),
123-
})
125+
}),
124126
);
125127

126128
const alice: Record<string, unknown> = {
@@ -138,8 +140,8 @@ test("circular objects", () => {
138140

139141
// Calling the decoder would cause infinite recursion!
140142
// So be careful when working with recursive data!
141-
const wouldCauseInfiniteRecursion1: () => Person = jest.fn(() =>
142-
personDecoder(alice)
143+
const wouldCauseInfiniteRecursion1: () => Person = vi.fn(() =>
144+
personDecoder(alice),
143145
);
144146

145147
expect(wouldCauseInfiniteRecursion1).not.toHaveBeenCalled();

0 commit comments

Comments
 (0)