brustjs 0.1.24-alpha → 0.1.26-alpha

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.
@@ -0,0 +1,69 @@
1
+ // Isolated TYPE TEST for the B2 typed treaty client. Not executed — every
2
+ // assertion is a pure type check inside an un-called async function. Run via:
3
+ // bun run typecheck:treaty → tsc -p tsconfig.typecheck.json --noEmit
4
+ //
5
+ // It exercises: (1) static-path methods are fully typed (output + error union),
6
+ // (2) the discriminated error union narrows on `code`, (3) accessing a
7
+ // non-existent output field is a type error, (4) a wrong error code / field is a
8
+ // type error, (5) param paths stay permissive (no type error, the fallback).
9
+ import { z } from 'zod'
10
+ import { defineActions } from './define-actions.ts'
11
+ import { client } from './treaty.ts'
12
+
13
+ const actions = defineActions()
14
+ .get('/team', () => ({ team: [{ id: 1 }], max: 6 }))
15
+ .post('/team', ({ body }: { body: { id: number } }) => ({ team: [{ id: body.id }], max: 6 }), {
16
+ body: z.object({ id: z.number() }),
17
+ errors: {
18
+ TEAM_FULL: z.object({ max: z.number() }),
19
+ DUPLICATE: z.object({ existingId: z.number() }),
20
+ },
21
+ })
22
+ .delete('/team/{id}', () => ({ ok: true }))
23
+
24
+ const api = client<typeof actions>()
25
+
26
+ // Never called — purely for type checking.
27
+ export async function _typeTest() {
28
+ // (1) static POST → output typed.
29
+ const r = await api.team.post({ id: 5 })
30
+ if (r.data) {
31
+ const max: number = r.data.max
32
+ void max
33
+ // (3) non-existent output field → must be a type error.
34
+ // @ts-expect-error `nope` is not a field of the typed output
35
+ void r.data.nope
36
+ }
37
+
38
+ // (2) error union narrows on the discriminant `code` to the SPECIFIC branch,
39
+ // and that branch's `data` is typed (multi-member union: TEAM_FULL | DUPLICATE).
40
+ if (r.error && r.error.value.code === 'TEAM_FULL') {
41
+ const m: number = r.error.value.data.max
42
+ void m
43
+ // (4a) non-existent error-data field → must be a type error.
44
+ // @ts-expect-error `min` is not a field of the TEAM_FULL error data
45
+ void r.error.value.data.min
46
+ // (4c) narrowing is per-branch: DUPLICATE's `existingId` is NOT on TEAM_FULL.
47
+ // @ts-expect-error `existingId` belongs to the DUPLICATE branch, not TEAM_FULL
48
+ void r.error.value.data.existingId
49
+ }
50
+ if (r.error && r.error.value.code === 'DUPLICATE') {
51
+ const e: number = r.error.value.data.existingId
52
+ void e
53
+ }
54
+ // (4b) comparing against an undeclared error code → must be a type error.
55
+ if (r.error) {
56
+ // @ts-expect-error 'NOPE' is not a declared error code
57
+ void (r.error.value.code === 'NOPE')
58
+ }
59
+
60
+ // GET → output typed.
61
+ const g = await api.team.get()
62
+ if (g.data) {
63
+ const max2: number = g.data.max
64
+ void max2
65
+ }
66
+
67
+ // (5) param path stays permissive — MUST NOT error (locks the fallback).
68
+ await api.team({ id: '5' }).delete()
69
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "compilerOptions": {
3
+ "strict": true,
4
+ "skipLibCheck": true,
5
+ "target": "ES2022",
6
+ "lib": ["ES2022", "DOM"],
7
+ "module": "ESNext",
8
+ "moduleResolution": "bundler",
9
+ "allowImportingTsExtensions": true,
10
+ "noEmit": true,
11
+ "jsx": "react-jsx",
12
+ "types": []
13
+ },
14
+ "files": [
15
+ "treaty.ts",
16
+ "define-actions.ts",
17
+ "standard-schema.ts",
18
+ "treaty.type-test.ts",
19
+ "navigation/index.ts",
20
+ "navigation/store.ts",
21
+ "navigation/active-nav.ts"
22
+ ]
23
+ }