@durable-streams/client 0.1.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/src/utils.ts ADDED
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Shared utility functions for the Durable Streams client.
3
+ */
4
+
5
+ import { DurableStreamError } from "./error"
6
+ import type { HeadersRecord, MaybePromise } from "./types"
7
+
8
+ /**
9
+ * Resolve headers from HeadersRecord (supports async functions).
10
+ * Unified implementation used by both stream() and DurableStream.
11
+ */
12
+ export async function resolveHeaders(
13
+ headers?: HeadersRecord
14
+ ): Promise<Record<string, string>> {
15
+ const resolved: Record<string, string> = {}
16
+
17
+ if (!headers) {
18
+ return resolved
19
+ }
20
+
21
+ for (const [key, value] of Object.entries(headers)) {
22
+ if (typeof value === `function`) {
23
+ resolved[key] = await value()
24
+ } else {
25
+ resolved[key] = value
26
+ }
27
+ }
28
+
29
+ return resolved
30
+ }
31
+
32
+ /**
33
+ * Handle error responses from the server.
34
+ * Throws appropriate DurableStreamError based on status code.
35
+ */
36
+ export async function handleErrorResponse(
37
+ response: Response,
38
+ url: string,
39
+ context?: { operation?: string }
40
+ ): Promise<never> {
41
+ const status = response.status
42
+
43
+ if (status === 404) {
44
+ throw new DurableStreamError(`Stream not found: ${url}`, `NOT_FOUND`, 404)
45
+ }
46
+
47
+ if (status === 409) {
48
+ // Context-specific 409 messages
49
+ const message =
50
+ context?.operation === `create`
51
+ ? `Stream already exists: ${url}`
52
+ : `Sequence conflict: seq is lower than last appended`
53
+ const code =
54
+ context?.operation === `create` ? `CONFLICT_EXISTS` : `CONFLICT_SEQ`
55
+ throw new DurableStreamError(message, code, 409)
56
+ }
57
+
58
+ if (status === 400) {
59
+ throw new DurableStreamError(
60
+ `Bad request (possibly content-type mismatch)`,
61
+ `BAD_REQUEST`,
62
+ 400
63
+ )
64
+ }
65
+
66
+ throw await DurableStreamError.fromResponse(response, url)
67
+ }
68
+
69
+ /**
70
+ * Resolve params from ParamsRecord (supports async functions).
71
+ */
72
+ export async function resolveParams(
73
+ params?: Record<string, string | (() => MaybePromise<string>) | undefined>
74
+ ): Promise<Record<string, string>> {
75
+ const resolved: Record<string, string> = {}
76
+
77
+ if (!params) {
78
+ return resolved
79
+ }
80
+
81
+ for (const [key, value] of Object.entries(params)) {
82
+ if (value !== undefined) {
83
+ if (typeof value === `function`) {
84
+ resolved[key] = await value()
85
+ } else {
86
+ resolved[key] = value
87
+ }
88
+ }
89
+ }
90
+
91
+ return resolved
92
+ }
93
+
94
+ /**
95
+ * Resolve a value that may be a function returning a promise.
96
+ */
97
+ export async function resolveValue<T>(
98
+ value: T | (() => MaybePromise<T>)
99
+ ): Promise<T> {
100
+ if (typeof value === `function`) {
101
+ return (value as () => MaybePromise<T>)()
102
+ }
103
+ return value
104
+ }