@zerotal/client 1.6.3 → 1.7.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.
Files changed (2) hide show
  1. package/api-surface.md +367 -0
  2. package/package.json +3 -2
package/api-surface.md ADDED
@@ -0,0 +1,367 @@
1
+ # @zerotal/client — public API surface
2
+
3
+ <!-- AUTO-GENERATED by scripts/api-surface.ts. Do not edit by hand.
4
+ Run `bun run api:surface` to regenerate after an intentional API change. -->
5
+
6
+ ## . `(./src/index.ts)`
7
+
8
+ class ApiClient = {
9
+ new <Routes extends ApiRouteMap>(config?: ApiClientConfig): ApiClient<Routes>
10
+ delete: <Path extends PathsFor<Routes, 'DELETE'>>(path: Path, params?: ParamRecord<Path & string>, options?: RequestOptions) => Promise<ResponseOf<Routes, 'DELETE', Path & string>>
11
+ get: <Path extends PathsFor<Routes, 'GET'>>(path: Path, params?: ParamRecord<Path & string>, options?: GetOptions<QueryOf<Routes, 'GET', Path & string>>) => Promise<ResponseOf<Routes, 'GET', Path & string>>
12
+ patch: <Path extends PathsFor<Routes, 'PATCH'>>(path: Path, body?: BodyOf<Routes, 'PATCH', Path & string>, options?: MutationOptions<QueryOf<Routes, 'PATCH', Path & string>>) => Promise<ResponseOf<Routes, 'PATCH', Path & string>>
13
+ post: <Path extends PathsFor<Routes, 'POST'>>(path: Path, body?: BodyOf<Routes, 'POST', Path & string>, options?: MutationOptions<QueryOf<Routes, 'POST', Path & string>>) => Promise<ResponseOf<Routes, 'POST', Path & string>>
14
+ put: <Path extends PathsFor<Routes, 'PUT'>>(path: Path, body?: BodyOf<Routes, 'PUT', Path & string>, options?: MutationOptions<QueryOf<Routes, 'PUT', Path & string>>) => Promise<ResponseOf<Routes, 'PUT', Path & string>>
15
+ setToken: (token: TokenSource | null) => void
16
+ }
17
+
18
+ class ApiClientError = {
19
+ new (status: number, statusText: string, body: string, headers?: Headers): ApiClientError
20
+ readonly body: string
21
+ readonly code: string
22
+ readonly context?: Record<string, unknown> | undefined
23
+ readonly headers: Headers | undefined
24
+ readonly status: number
25
+ readonly statusText: string
26
+ retryAfterMs: number | null
27
+ }
28
+
29
+ class Channel = {
30
+ new (name: string, _socket: Socket): Channel
31
+ _dispatch: (frame: ServerFrame) => void
32
+ error: (cb: Listener) => Channel
33
+ listen: (event: string, cb: Listener) => Channel
34
+ readonly name: string
35
+ stopListening: (event: string, cb?: Listener) => Channel
36
+ subscribed: (cb: Listener) => Channel
37
+ unsubscribe: () => void
38
+ }
39
+
40
+ class CircuitBreaker = {
41
+ new (options?: CircuitBreakerOptions): CircuitBreaker
42
+ call: <T>(fn: () => Promise<T>) => Promise<T>
43
+ failures: number
44
+ reset: () => void
45
+ state: CircuitState
46
+ }
47
+
48
+ class CircuitBreakerOpenError = {
49
+ new (): CircuitBreakerOpenError
50
+ readonly code: string
51
+ readonly context?: Record<string, unknown> | undefined
52
+ readonly status: number
53
+ }
54
+
55
+ class ClientProvider = {
56
+ new (app: Application): ClientProvider
57
+ static dependsOn?: (new (app: Application) => ServiceProvider)[]
58
+ static environments: AppEnvironment[]
59
+ static priority?: number
60
+ static provides: readonly ['client']
61
+ devProcesses: () => DevProcessDefinition[]
62
+ doctorChecks: () => DoctorCheck[]
63
+ onBooted: () => Promise<void>
64
+ onBooting: () => Promise<void>
65
+ onRegister: () => void
66
+ onRequestProcessed: (_ctx: HttpContext) => Promise<void>
67
+ onRequestReceived: (_ctx: HttpContext) => Promise<void>
68
+ onResponseSent: (_ctx: HttpContext) => Promise<void>
69
+ onStarted: () => Promise<void>
70
+ onStarting: () => Promise<void>
71
+ onStopped: () => Promise<void>
72
+ onStopping: () => Promise<void>
73
+ replContext: () => Record<string, unknown>
74
+ }
75
+
76
+ class PresenceChannel = {
77
+ new (name: string, _socket: Socket): PresenceChannel
78
+ _dispatch: (frame: ServerFrame) => void
79
+ error: (cb: Listener) => PresenceChannel
80
+ here: (cb: (members: PresenceMember[]) => void) => PresenceChannel
81
+ joining: (cb: (member: PresenceMember) => void) => PresenceChannel
82
+ leaving: (cb: (member: PresenceMember) => void) => PresenceChannel
83
+ listen: (event: string, cb: Listener) => PresenceChannel
84
+ readonly name: string
85
+ stopListening: (event: string, cb?: Listener) => PresenceChannel
86
+ subscribed: (cb: Listener) => PresenceChannel
87
+ unsubscribe: () => void
88
+ }
89
+
90
+ class Socket = {
91
+ new (options?: SocketOptions): Socket
92
+ channel: (name: string) => Channel
93
+ channels: () => Channel[]
94
+ connect: () => void
95
+ disconnect: () => void
96
+ join: (name: string) => PresenceChannel
97
+ leave: (name: string) => void
98
+ leaveChannel: (wireName: string) => void
99
+ on: (state: SocketState, cb: (detail?: unknown) => void) => () => void
100
+ presence: (name: string) => PresenceChannel
101
+ private: (name: string) => Channel
102
+ socketId: () => string | null
103
+ state: SocketState
104
+ }
105
+
106
+ class ValidationError = {
107
+ new (statusText: string, body: string, errors: Record<string, string[]>, validationMessage: string, headers?: Headers): ValidationError
108
+ all: () => Record<string, string[]>
109
+ fields: () => string[]
110
+ first: (field: string) => string | undefined
111
+ has: (field: string) => boolean
112
+ readonly body: string
113
+ readonly code: string
114
+ readonly context?: Record<string, unknown> | undefined
115
+ readonly errors: Record<string, string[]>
116
+ readonly headers: Headers | undefined
117
+ readonly status: number
118
+ readonly statusText: string
119
+ readonly validationMessage: string
120
+ retryAfterMs: number | null
121
+ }
122
+
123
+ const Client = ApiClient<Partial<Record<`GET ${string}` | `POST ${string}` | `PUT ${string}` | `PATCH ${string}` | `DELETE ${string}`, RouteShape>>>
124
+
125
+ function ClientConfig = (options?: Partial<ClientConfigShape>) => Partial<ClientConfigShape>
126
+
127
+ function createApiClient = <Routes extends ApiRouteMap>(config?: ApiClientConfig) => ApiClient<Routes>
128
+
129
+ interface ApiClientConfig = {
130
+ baseUrl?: string
131
+ circuitBreaker?: CircuitBreaker | CircuitBreakerOptions
132
+ csrf?: boolean | { cookie?: string; header?: string;}
133
+ headers?: Record<string, string>
134
+ onError?: (error: ApiClientError) => void | Promise<void>
135
+ onForbidden?: (error: ApiClientError) => void | Promise<void>
136
+ onRequest?: RequestInterceptor | RequestInterceptor[]
137
+ onResponse?: ResponseInterceptor | ResponseInterceptor[]
138
+ onUnauthorized?: (error: ApiClientError, retry: (headerOverrides?: Record<string, string>) => Promise<unknown>) => Promise<unknown> | void
139
+ retry?: number | RetryOptions
140
+ timeout?: number
141
+ token?: TokenSource
142
+ withCredentials?: boolean
143
+ }
144
+
145
+ interface CircuitBreakerOptions = {
146
+ isFailure?: (error: unknown) => boolean
147
+ resetTimeout?: number
148
+ threshold?: number
149
+ }
150
+
151
+ interface ClientConfigShape = {
152
+ baseUrl?: string
153
+ circuitBreaker?: CircuitBreaker | CircuitBreakerOptions
154
+ csrf?: boolean | { cookie?: string; header?: string;}
155
+ headers?: Record<string, string>
156
+ onError?: (error: ApiClientError) => void | Promise<void>
157
+ onForbidden?: (error: ApiClientError) => void | Promise<void>
158
+ onRequest?: RequestInterceptor | RequestInterceptor[]
159
+ onResponse?: ResponseInterceptor | ResponseInterceptor[]
160
+ onUnauthorized?: (error: ApiClientError, retry: (headerOverrides?: Record<string, string>) => Promise<unknown>) => Promise<unknown> | void
161
+ retry?: number | RetryOptions
162
+ timeout?: number
163
+ token?: TokenSource
164
+ withCredentials?: boolean
165
+ }
166
+
167
+ interface GetOptions = {
168
+ headers?: Record<string, string>
169
+ init?: Omit<RequestInit, 'method' | 'headers' | 'body'>
170
+ meta?: (meta: ResponseMeta) => void
171
+ query?: Q
172
+ responseType?: 'text' | 'json' | 'auto' | 'blob' | 'arrayBuffer'
173
+ retry?: number | false | RetryOptions
174
+ signal?: AbortSignal
175
+ timeout?: number
176
+ }
177
+
178
+ interface MutationOptions = {
179
+ headers?: Record<string, string>
180
+ init?: Omit<RequestInit, 'method' | 'headers' | 'body'>
181
+ meta?: (meta: ResponseMeta) => void
182
+ params?: Record<string, string | number>
183
+ query?: Q
184
+ responseType?: 'text' | 'json' | 'auto' | 'blob' | 'arrayBuffer'
185
+ retry?: number | false | RetryOptions
186
+ signal?: AbortSignal
187
+ timeout?: number
188
+ }
189
+
190
+ interface PresenceMember = {
191
+ id: string | number
192
+ info: Record<string, unknown>
193
+ }
194
+
195
+ interface RequestConfig = {
196
+ body: BodyInit | undefined
197
+ headers: Record<string, string>
198
+ method: string
199
+ url: string
200
+ }
201
+
202
+ interface RequestOptions = {
203
+ headers?: Record<string, string>
204
+ init?: Omit<RequestInit, 'method' | 'headers' | 'body'>
205
+ meta?: (meta: ResponseMeta) => void
206
+ responseType?: 'text' | 'json' | 'auto' | 'blob' | 'arrayBuffer'
207
+ retry?: number | false | RetryOptions
208
+ signal?: AbortSignal
209
+ timeout?: number
210
+ }
211
+
212
+ interface ResponseContext = {
213
+ data: unknown
214
+ headers: Headers
215
+ request: RequestConfig
216
+ status: number
217
+ }
218
+
219
+ interface ResponseMeta = {
220
+ headers: Headers
221
+ status: number
222
+ }
223
+
224
+ interface RetryOptions = {
225
+ attempts?: number
226
+ backoff?: (attempt: number, retryAfterMs: number | null) => number
227
+ methods?: string[]
228
+ respectRetryAfter?: boolean
229
+ statuses?: number[]
230
+ }
231
+
232
+ interface RouteShape = {
233
+ body?: Record<string, unknown>
234
+ params?: Record<string, string | number>
235
+ query?: Record<string, string | number | boolean | undefined>
236
+ response?: unknown
237
+ }
238
+
239
+ interface SocketLike = {
240
+ close: (code?: number, reason?: string) => void
241
+ onclose: ((ev: { code?: number; reason?: string;}) => void) | null
242
+ onerror: ((ev: unknown) => void) | null
243
+ onmessage: ((ev: { data: unknown;}) => void) | null
244
+ onopen: ((ev: unknown) => void) | null
245
+ readyState: number
246
+ send: (data: string) => void
247
+ }
248
+
249
+ interface SocketOptions = {
250
+ WebSocket?: new (url: string) => SocketLike
251
+ auth?: { params?: Record<string, string>; headers?: Record<string, string>;}
252
+ authEndpoint?: string | false
253
+ autoConnect?: boolean
254
+ fetch?: typeof fetch
255
+ host?: string
256
+ maxReconnectDelay?: number
257
+ path?: string
258
+ pingInterval?: number
259
+ port?: string | number
260
+ reconnect?: boolean
261
+ reconnectDelay?: number
262
+ scheme?: 'ws' | 'wss'
263
+ url?: string
264
+ }
265
+
266
+ type ApiRouteMap = { [x: `GET ${string}`]: RouteShape | undefined; [x: `POST ${string}`]: RouteShape | undefined; [x: `PUT ${string}`]: RouteShape | undefined; [x: `PATCH ${string}`]: RouteShape | undefined; [x: `DELETE ${string}`]: RouteShape | undefined;}
267
+
268
+ type BodyOf = `${Method} ${Path}` extends keyof Routes ? Routes[`${Method} ${Path}`] extends { body: infer B;} ? B : Record<string, unknown> : Record<string, unknown>
269
+
270
+ type CircuitState = 'closed' | 'open' | 'half-open'
271
+
272
+ type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'
273
+
274
+ type ParamRecord = [PathParams<Path>] extends [never] ? undefined : { [K in PathParams<Path>]: string | number; }
275
+
276
+ type PathParams = Path extends `${string}{${infer Param}}${infer Tail}` ? Param | PathParams<Tail> : never
277
+
278
+ type PathsFor = { [K in keyof Routes & string]: K extends `${Method} ${infer Path}` ? Path : never; }[keyof Routes & string]
279
+
280
+ type QueryOf = `${Method} ${Path}` extends keyof Routes ? Routes[`${Method} ${Path}`] extends { query: infer Q;} ? Q : Record<string, string | number | boolean | undefined> : Record<string, string | number | boolean | undefined>
281
+
282
+ type RequestInterceptor = (config: RequestConfig) => RequestConfig | Promise<RequestConfig>
283
+
284
+ type ResponseInterceptor = (ctx: ResponseContext) => ResponseContext | Promise<ResponseContext>
285
+
286
+ type ResponseOf = `${Method} ${Path}` extends keyof Routes ? Routes[`${Method} ${Path}`] extends { response: infer R;} ? R : unknown : unknown
287
+
288
+ type SocketState = 'error' | 'connecting' | 'connected' | 'disconnected' | 'reconnecting'
289
+
290
+ type TokenSource = string | (() => string | null | undefined | Promise<string | null | undefined>)
291
+
292
+ ## ./Socket `(./src/Socket.ts)`
293
+
294
+ class Channel = {
295
+ new (name: string, _socket: Socket): Channel
296
+ _dispatch: (frame: ServerFrame) => void
297
+ error: (cb: Listener) => Channel
298
+ listen: (event: string, cb: Listener) => Channel
299
+ readonly name: string
300
+ stopListening: (event: string, cb?: Listener) => Channel
301
+ subscribed: (cb: Listener) => Channel
302
+ unsubscribe: () => void
303
+ }
304
+
305
+ class PresenceChannel = {
306
+ new (name: string, _socket: Socket): PresenceChannel
307
+ _dispatch: (frame: ServerFrame) => void
308
+ error: (cb: Listener) => PresenceChannel
309
+ here: (cb: (members: PresenceMember[]) => void) => PresenceChannel
310
+ joining: (cb: (member: PresenceMember) => void) => PresenceChannel
311
+ leaving: (cb: (member: PresenceMember) => void) => PresenceChannel
312
+ listen: (event: string, cb: Listener) => PresenceChannel
313
+ readonly name: string
314
+ stopListening: (event: string, cb?: Listener) => PresenceChannel
315
+ subscribed: (cb: Listener) => PresenceChannel
316
+ unsubscribe: () => void
317
+ }
318
+
319
+ class Socket = {
320
+ new (options?: SocketOptions): Socket
321
+ channel: (name: string) => Channel
322
+ channels: () => Channel[]
323
+ connect: () => void
324
+ disconnect: () => void
325
+ join: (name: string) => PresenceChannel
326
+ leave: (name: string) => void
327
+ leaveChannel: (wireName: string) => void
328
+ on: (state: SocketState, cb: (detail?: unknown) => void) => () => void
329
+ presence: (name: string) => PresenceChannel
330
+ private: (name: string) => Channel
331
+ socketId: () => string | null
332
+ state: SocketState
333
+ }
334
+
335
+ interface PresenceMember = {
336
+ id: string | number
337
+ info: Record<string, unknown>
338
+ }
339
+
340
+ interface SocketLike = {
341
+ close: (code?: number, reason?: string) => void
342
+ onclose: ((ev: { code?: number; reason?: string;}) => void) | null
343
+ onerror: ((ev: unknown) => void) | null
344
+ onmessage: ((ev: { data: unknown;}) => void) | null
345
+ onopen: ((ev: unknown) => void) | null
346
+ readyState: number
347
+ send: (data: string) => void
348
+ }
349
+
350
+ interface SocketOptions = {
351
+ WebSocket?: new (url: string) => SocketLike
352
+ auth?: { params?: Record<string, string>; headers?: Record<string, string>;}
353
+ authEndpoint?: string | false
354
+ autoConnect?: boolean
355
+ fetch?: typeof fetch
356
+ host?: string
357
+ maxReconnectDelay?: number
358
+ path?: string
359
+ pingInterval?: number
360
+ port?: string | number
361
+ reconnect?: boolean
362
+ reconnectDelay?: number
363
+ scheme?: 'ws' | 'wss'
364
+ url?: string
365
+ }
366
+
367
+ type SocketState = 'error' | 'connecting' | 'connected' | 'disconnected' | 'reconnecting'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zerotal/client",
3
- "version": "1.6.3",
3
+ "version": "1.7.0",
4
4
  "license": "MIT",
5
5
  "maturity": "stable",
6
6
  "private": false,
@@ -13,6 +13,7 @@
13
13
  },
14
14
  "files": [
15
15
  "CHANGELOG.md",
16
+ "api-surface.md",
16
17
  "src",
17
18
  "!src/**/*.test.ts",
18
19
  "!src/**/*.test.tsx",
@@ -30,7 +31,7 @@
30
31
  "typecheck": "tsc --noEmit"
31
32
  },
32
33
  "dependencies": {
33
- "@zerotal/core": "1.6.3"
34
+ "@zerotal/core": "1.7.0"
34
35
  },
35
36
  "devDependencies": {
36
37
  "typescript": "^5.8.0"