@outfoxx/sunday 2.0.0-beta.18 → 2.0.0-beta.19
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 +191 -30
- package/build/client-settings.d.ts +6 -7
- package/build/client-settings.js +58 -28
- package/build/client-settings.js.map +1 -1
- package/build/event-parser.d.ts +21 -8
- package/build/event-parser.js +93 -121
- package/build/event-parser.js.map +1 -1
- package/build/fetch-copy.d.ts +15 -0
- package/build/fetch-copy.js +70 -0
- package/build/fetch-copy.js.map +1 -0
- package/build/fetch-event-source.d.ts +6 -5
- package/build/fetch-event-source.js +168 -137
- package/build/fetch-event-source.js.map +1 -1
- package/build/fetch-oauth-token-provider.js +61 -19
- package/build/fetch-oauth-token-provider.js.map +1 -1
- package/build/fetch-transport.d.ts +14 -6
- package/build/fetch-transport.js +126 -168
- package/build/fetch-transport.js.map +1 -1
- package/build/fetch.js +5 -0
- package/build/fetch.js.map +1 -1
- package/build/index.d.ts +7 -2
- package/build/index.js +6 -2
- package/build/index.js.map +1 -1
- package/build/request-adapter.d.ts +8 -0
- package/build/{token-manager-factory.js → request-adapter.js} +1 -1
- package/build/request-adapter.js.map +1 -0
- package/build/request-adapters.d.ts +25 -8
- package/build/request-adapters.js +126 -14
- package/build/request-adapters.js.map +1 -1
- package/build/request-body.d.ts +24 -0
- package/build/request-body.js +104 -0
- package/build/request-body.js.map +1 -0
- package/build/request-cancellation-error.d.ts +13 -0
- package/build/request-cancellation-error.js +43 -0
- package/build/request-cancellation-error.js.map +1 -0
- package/build/request-execution.d.ts +18 -0
- package/build/request-execution.js +108 -0
- package/build/request-execution.js.map +1 -0
- package/build/request-security.d.ts +9 -3
- package/build/request-security.js +101 -36
- package/build/request-security.js.map +1 -1
- package/build/response-adapter.d.ts +10 -0
- package/build/response-adapter.js +15 -0
- package/build/response-adapter.js.map +1 -0
- package/build/response-adapters.d.ts +13 -0
- package/build/response-adapters.js +75 -0
- package/build/response-adapters.js.map +1 -0
- package/build/token-manager.d.ts +13 -4
- package/build/token-manager.js +110 -33
- package/build/token-manager.js.map +1 -1
- package/build/token-provider.d.ts +8 -1
- package/build/token-provider.js +71 -0
- package/build/token-provider.js.map +1 -1
- package/build/transport.d.ts +3 -3
- package/build/util/abort.d.ts +3 -0
- package/build/util/abort.js +42 -0
- package/build/util/abort.js.map +1 -0
- package/build/util/native-fetch.d.ts +2 -0
- package/build/util/native-fetch.js +39 -0
- package/build/util/native-fetch.js.map +1 -0
- package/build/util/owned-body.d.ts +12 -0
- package/build/util/owned-body.js +243 -0
- package/build/util/owned-body.js.map +1 -0
- package/package.json +9 -6
- package/build/token-manager-factory.d.ts +0 -9
- package/build/token-manager-factory.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
Sunday 🙏 The framework of REST for TypeScript/JavaScript
|
|
2
|
-
===
|
|
1
|
+
# Sunday 🙏 The framework of REST for TypeScript/JavaScript
|
|
3
2
|
|
|
4
3
|

|
|
5
4
|

|
|
@@ -13,8 +12,7 @@ TypeScript/JavaScript framework for generated REST clients.
|
|
|
13
12
|
|
|
14
13
|
---
|
|
15
14
|
|
|
16
|
-
NPM
|
|
17
|
-
---
|
|
15
|
+
## NPM
|
|
18
16
|
|
|
19
17
|
Sunday is delivered as a standard NPM package.
|
|
20
18
|
|
|
@@ -41,7 +39,7 @@ Package Name:
|
|
|
41
39
|
## Profiled credentials
|
|
42
40
|
|
|
43
41
|
Generated request specifications select `SecurityBinding` entries. Register application providers with
|
|
44
|
-
|
|
42
|
+
named providers directly as `new FetchTransport(baseUrl, {tokenProviders: {external: provider}})`. Client secrets,
|
|
45
43
|
authorization codes, token storage, and interactive login remain application bindings.
|
|
46
44
|
|
|
47
45
|
`FetchOAuthTokenProvider` exchanges `clientCredentials` and application-authorized `authorizationCode`
|
|
@@ -102,35 +100,198 @@ undefined `id` produces `/items`. An empty collection is undefined; a list conta
|
|
|
102
100
|
an empty string has a defined member. Per-call values override stored template parameters,
|
|
103
101
|
including explicit null or undefined values that remove a stored value for that expansion.
|
|
104
102
|
|
|
105
|
-
## Application-owned token
|
|
103
|
+
## Application-owned token lifecycle
|
|
104
|
+
|
|
105
|
+
Transports accept named `TokenProvider` instances directly. Settings preserve supplied providers and
|
|
106
|
+
never add a token cache. Every managed network attempt asks its provider for current credentials.
|
|
107
|
+
An external framework (for example Auth0) remains responsible for storage, renewal and logout.
|
|
108
|
+
Return only its access token and optional expiry; keep its refresh token inside that framework.
|
|
109
|
+
|
|
110
|
+
For Sunday's caching and refresh lifecycle, explicitly supply a `TokenManager` as the provider:
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
const tokens = new TokenManager(oauthProvider, {
|
|
114
|
+
store: applicationStore,
|
|
115
|
+
expirySkewMs: 30_000,
|
|
116
|
+
now: applicationClock,
|
|
117
|
+
});
|
|
118
|
+
const settings = ClientSettings.resolve(baseUrl, alternatives, {
|
|
119
|
+
identity: { kind: 'provider', provider: tokens },
|
|
120
|
+
});
|
|
121
|
+
// Supply an external framework's provider directly instead to keep its lifecycle authoritative.
|
|
122
|
+
const transport = FetchTransport.fromSettings(settings);
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Managers retain expiry skew, coalesced renewal, refresh rotation and application-selected persistence.
|
|
126
|
+
Cancel and await outstanding requests before discarding a manager.
|
|
127
|
+
Transport closure does not erase the store or close a shared provider. Separate managers do not
|
|
128
|
+
coordinate refreshes merely because they share a store. Reuse the same manager across clients that
|
|
129
|
+
share a credential lifecycle, and distinguish users/environments with provider and grant identities.
|
|
130
|
+
|
|
131
|
+
Providers can implement `reject` to handle an invalid bearer token. It receives the original request
|
|
132
|
+
context and rejected access token, and returns whether recovery can proceed. Compare the rejected
|
|
133
|
+
credential with the current session before renewing: a late rejection must not invalidate a newer token
|
|
134
|
+
or a new login. Providers without this capability do not automatically retry. Acquisition and rejection
|
|
135
|
+
must not start interactive login automatically; return an authorization-required failure to the caller.
|
|
136
|
+
For an Auth0 adapter, retrieve through its credentials manager and force renewal through that same
|
|
137
|
+
manager on rejection, serializing concurrent rejection handling without maintaining a second token cache.
|
|
138
|
+
|
|
139
|
+
Request export materializes an optionally authorized native request once and hands its lifecycle to
|
|
140
|
+
the consumer. Exported requests retain no Sunday-managed recovery state. Executing an operation through
|
|
141
|
+
Sunday acquires once per attempt and retains the bounded safe-request recovery and SSE reconnect budget.
|
|
142
|
+
|
|
143
|
+
Migration: replace transport `tokenManager`/`token_manager` arguments with named
|
|
144
|
+
`tokenProviders`/`token_providers` maps. Replace `TokenManagerFactory` hooks with explicitly constructed
|
|
145
|
+
managers supplied through provider credentials. Direct built-in OAuth providers are not implicitly cached;
|
|
146
|
+
wrap them explicitly when Sunday should retain and refresh their tokens. For logout, stop outstanding
|
|
147
|
+
requests and settle refresh commits before clearing the owning framework's or application's storage.
|
|
148
|
+
|
|
149
|
+
## Request and response adapters
|
|
150
|
+
|
|
151
|
+
`FetchTransport` accepts independent `requestAdapter` and `responseAdapter` options. Each is a
|
|
152
|
+
structural interface with an `adapt` method returning a native Fetch value or a promise:
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
const transport = new FetchTransport('https://api.example', {
|
|
156
|
+
requestAdapter: chainRequestAdapters(auth, {
|
|
157
|
+
adapt(request) {
|
|
158
|
+
const headers = new Headers(request.headers);
|
|
159
|
+
headers.set('X-Client', 'example');
|
|
160
|
+
return copyRequest(request, { headers });
|
|
161
|
+
},
|
|
162
|
+
}),
|
|
163
|
+
responseAdapter: chainResponseAdapters(auth, {
|
|
164
|
+
adapt(response, request) {
|
|
165
|
+
console.log(request.method, response.status);
|
|
166
|
+
return response;
|
|
167
|
+
},
|
|
168
|
+
}),
|
|
169
|
+
});
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Here `auth` explicitly implements both capabilities, for example a
|
|
173
|
+
`RefreshingHeaderTokenAuthorizingAdapter`. Installing only its request capability does not install
|
|
174
|
+
its response capability. `RequestAdapters` and `ResponseAdapters` also provide `chainTo`; composition
|
|
175
|
+
flattens existing chains. Plain objects need no inheritance or prototype extensions.
|
|
176
|
+
|
|
177
|
+
Adapters run once per Sunday-managed Fetch call, with response adaptation before validation or body
|
|
178
|
+
consumption. Authentication receipts and retry budgets remain local to the operation. Provider rejection
|
|
179
|
+
runs for every matching `401 invalid_token`, including unsafe methods and exhausted retry budgets; a
|
|
180
|
+
provider declining recovery raises `RequestCancellationError`. Sunday permits one authentication retry
|
|
181
|
+
for a bodyless GET, HEAD, or OPTIONS, reapplying request adapters. An SSE subscription shares that budget
|
|
182
|
+
across reconnects. GET and HEAD are intrinsically bodyless; OPTIONS recovery requires an inspectable
|
|
183
|
+
empty body, so it remains disabled where `Request.body` is unavailable. `TokenProvider` implementations
|
|
184
|
+
own their cache and refresh behavior; wrapping one in `TokenManager` explicitly opts into Sunday's caching.
|
|
185
|
+
|
|
186
|
+
Fetch retains its native redirects and recovery. Adapters cannot observe hidden intermediate responses
|
|
187
|
+
or wire-level changes from service workers/custom Fetch implementations. The response adapter receives
|
|
188
|
+
the request submitted to Fetch. Changing response status or Location afterward does not initiate a new
|
|
189
|
+
native redirect. Credentialed calls use manual redirects and omit ambient credentials; browsers expose
|
|
190
|
+
manual redirect responses as `opaqueredirect`, without readable status or Location. An adapter may handle
|
|
191
|
+
that response, but Sunday does not emulate browser redirect internals.
|
|
192
|
+
|
|
193
|
+
Throw `RequestCancellationError`, subclass it, or brand an existing application Error with
|
|
194
|
+
`[requestCancellation]: true` to stop without retry or SSE reconnection. Sunday preserves that stop
|
|
195
|
+
instance, including when native Fetch carries it as an error cause. Sunday does not inspect causes
|
|
196
|
+
of errors thrown by adapters, decoders, or supplied Fetch callbacks. Native aborts also stop; `AbortSignal.any`
|
|
197
|
+
preserves cancellation from the invocation and adapter-provided signals, including the original abort
|
|
198
|
+
reason. Async adapters should observe `request.signal`. Sunday stops awaiting an aborted adapter and
|
|
199
|
+
cleans up late returned resources; JavaScript cannot forcibly terminate arbitrary application promises.
|
|
200
|
+
Cancellation also reaches owned upload and replacement-response streams while an adapter or native
|
|
201
|
+
body reader is consuming them. Cleanup releases readers without waiting for a producer's cleanup
|
|
202
|
+
promise. Late adapter results receive the original cancellation reason.
|
|
203
|
+
Event-source handler properties and EventTarget listeners are observers. Thrown exceptions and rejected
|
|
204
|
+
callback promises follow the runtime's native event-error reporting; they do not request retries or
|
|
205
|
+
cancellation, even when the error carries a stop marker. Use `close()` or an abort signal to stop a
|
|
206
|
+
subscription. Registered listeners run before the handler property and can suppress it with
|
|
207
|
+
`stopImmediatePropagation()`. `onmessage` continues to receive named SSE messages as well as default
|
|
208
|
+
messages.
|
|
209
|
+
|
|
210
|
+
A failed parallel credential acquisition cancels its siblings. `RefreshingHeaderTokenAuthorizingAdapter`
|
|
211
|
+
uses `TokenManager` to coalesce refreshes and prevent invalidated tokens from returning to the cache.
|
|
212
|
+
|
|
213
|
+
An adapter consuming a body must return a replacement. Use `copyRequest` / `copyResponse` to preserve
|
|
214
|
+
known body ownership through native constructors. Sunday does not call `clone()` or add a stream tee;
|
|
215
|
+
native Request copying may create branches, and Sunday immediately cancels the obsolete input branch
|
|
216
|
+
without waiting for its cleanup. The active body retains native streaming and replay behavior.
|
|
217
|
+
Prepare new upload streams with `prepareRequestBody` before constructing a Request.
|
|
218
|
+
These helpers share/transfer the existing body; do not subsequently consume it through the old value.
|
|
219
|
+
`copyResponse` preserves URL/type/redirect metadata for inspectable responses; opaque/error responses
|
|
220
|
+
cannot be reconstructed by Fetch's Response constructor. URL-changing request copies transfer the body
|
|
221
|
+
as a stream, so provide a fresh BodyInit if native replayability is needed. Same-URL copies retain
|
|
222
|
+
native body sources on all supported platforms.
|
|
223
|
+
|
|
224
|
+
No-op and header-only response adapters retain native Fetch body capabilities, including BYOB readers
|
|
225
|
+
where the platform provides them. Independent replacement streams share one source owner for
|
|
226
|
+
cancellation and source-error capture. Original errors are restored only around native body reads or
|
|
227
|
+
Fetch itself; errors deliberately thrown by adapters are never classified as substituted body errors.
|
|
228
|
+
|
|
229
|
+
`transportRequest()` exports an optionally authorized, adapted request exactly once. Its consumer owns
|
|
230
|
+
execution (`fetch(exportedRequest)`), response processing, and retry policy. Passing a native Request to
|
|
231
|
+
`transportResponse()` instead starts a new managed invocation. Migrate old `adapt(transport, request)`
|
|
232
|
+
implementations to `adapt(request)` and pass `requestAdapter`; `adapter` remains a deprecated constructor
|
|
233
|
+
option accepting the new signature.
|
|
234
|
+
|
|
235
|
+
Bun execution requires Bun 1.4 or newer for UTF-8 SSE reconnect IDs: older Bun releases
|
|
236
|
+
re-encode Fetch header bytes and corrupt `Last-Event-ID`. Development and CI use Bun 1.4.4.
|
|
237
|
+
|
|
238
|
+
The standard `bun run check` includes native-socket Node/Bun checks and Chromium, Firefox, and WebKit
|
|
239
|
+
adapter regressions. Install browsers with `bunx playwright install chromium firefox webkit` (CI uses
|
|
240
|
+
`--with-deps`). The HTTP/2 upload fixture also requires Node and OpenSSL; it creates a temporary,
|
|
241
|
+
self-signed loopback certificate and removes it after testing. Tests cover buffered and streaming
|
|
242
|
+
execution, cancellation, body ownership, exception identity, and native redirects.
|
|
243
|
+
|
|
244
|
+
Browser request streaming is a separate capability from response streaming. Verified with Playwright
|
|
245
|
+
1.65.0 on macOS: Chromium 158.0.8127.18 and WebKit 27.2 upload copied request streams over HTTPS/HTTP/2,
|
|
246
|
+
including bytes produced before the stream closes. Firefox 159.0 still stringifies streams passed
|
|
247
|
+
directly to native Request. Sunday now buffers unsupported upload streams into a Blob **before**
|
|
248
|
+
constructing the request, preserving their bytes. Supported runtimes retain native streaming.
|
|
249
|
+
|
|
250
|
+
The fallback buffers at most **16 MiB** by default. Set `maxBufferedRequestBytes` on `FetchTransport`
|
|
251
|
+
to change this bound; it does not limit native streaming uploads. Buffering waits for the producer to
|
|
252
|
+
finish before transmission. An oversized body fails with RangeError and cancels its source. Aborts and
|
|
253
|
+
source errors retain their original identity, and cancellation does not wait for source cleanup.
|
|
254
|
+
Existing Blob/string/form bodies are unchanged, and buffering does not add Sunday retries or caches.
|
|
255
|
+
|
|
256
|
+
Adapters that introduce a stream use the same exported helper before constructing their replacement
|
|
257
|
+
request. For example, an adapter supplying the body of an initially bodyless POST can use:
|
|
106
258
|
|
|
107
259
|
```typescript
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
260
|
+
const body = await prepareRequestBody(makeUploadStream(), {
|
|
261
|
+
signal: request.signal,
|
|
262
|
+
maxBytes: 16 * 1024 * 1024,
|
|
263
|
+
});
|
|
264
|
+
return copyRequest(request, { body, duplex: 'half' });
|
|
112
265
|
```
|
|
113
266
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
267
|
+
`prepareRequestBody` passes through supported streams and other BodyInit values unchanged; its
|
|
268
|
+
`maxBytes` applies only to the fallback. `bufferToBlob(stream, options)` explicitly buffers on any
|
|
269
|
+
runtime with the same cancellation and limit behavior. These helpers consume the source when buffering
|
|
270
|
+
and must run before native Request construction: an already-stringified Firefox request cannot be
|
|
271
|
+
recovered. When changing a request URL with `copyRequest`, also normalize and pass its existing body
|
|
272
|
+
explicitly: rebuilding a native Request at a new URL exposes that body as a stream again. On engines
|
|
273
|
+
without `Request.body` (including Firefox 159), retrieve an existing body with `request.blob()` instead.
|
|
274
|
+
Sunday preserves the body through both paths when adding query credentials.
|
|
275
|
+
Adapters remain responsible for replacing/discarding resources they consume.
|
|
276
|
+
|
|
277
|
+
`supportsStreamingUploads()` caches a runtime capability probe without network requests. It does not
|
|
278
|
+
check the destination's HTTP version or server behavior, and Sunday never retries a failed transmission
|
|
279
|
+
to select the fallback. Bun supports uploads without reading `duplex`, which the probe accounts for.
|
|
280
|
+
The browser tests compare native and Sunday request copying explicitly and save the exact engine
|
|
281
|
+
versions and observed upload outcomes in `reports/browser-streaming-*.json`. Shared buffer contract
|
|
282
|
+
checks run in Chromium, Firefox, WebKit, Node, and Bun. The same async execution contracts run in all
|
|
283
|
+
five engines, covering replacement-body cleanup, original error identity, credential acquisition and
|
|
284
|
+
recovery, refresh coordination, and concurrent SSE iterator reads. The ownership matrix also checks
|
|
285
|
+
native byte-stream capabilities, adapter-selected errors, upload failures, and late resource cleanup.
|
|
286
|
+
The lifecycle matrix also checks atomic credential setup, unhandled rejections, nested application
|
|
287
|
+
errors, truncated SSE reconnections, and suppression of callbacks after termination.
|
|
288
|
+
CI runs WebKit on macOS to exercise Safari's network implementation; Chromium, Firefox, Node, and Bun
|
|
289
|
+
run on Linux. Playwright's Linux WebKit backend advertises streaming uploads but cannot send them,
|
|
290
|
+
and reports remote HTTP/2 resets as aborts. The constructor-only capability probe cannot detect those
|
|
291
|
+
backend limitations. Applications targeting that backend can explicitly use `bufferToBlob` for uploads.
|
|
292
|
+
`SUNDAY_TEST_BROWSERS=webkit` selects a browser suite locally (a comma-separated list is also accepted).
|
|
293
|
+
See the [ownership and failure audit](documentation/adapter-ownership-audit.md) for the recurring causes,
|
|
294
|
+
pre-existing defects versus refactor regressions, and the checks to carry into other runtimes.
|
|
134
295
|
|
|
135
296
|
## Binary downloads
|
|
136
297
|
|
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
import { Credentials } from './credentials.js';
|
|
2
2
|
import { SecurityBinding } from './security-binding.js';
|
|
3
|
-
import {
|
|
4
|
-
import { TokenManagerFactory } from './token-manager-factory.js';
|
|
3
|
+
import { TokenProvider } from './token-provider.js';
|
|
5
4
|
/** Resolved, transport-independent inputs supplied to an application's transport factory. */
|
|
6
5
|
export declare class ClientSettings {
|
|
7
6
|
#private;
|
|
8
7
|
readonly baseUrl: string;
|
|
9
|
-
/**
|
|
10
|
-
readonly
|
|
8
|
+
/** Providers shared by this configuration's operations; caching requires an explicit TokenManager. */
|
|
9
|
+
readonly tokenProviders: Readonly<Record<string, TokenProvider>>;
|
|
11
10
|
readonly bindings: Readonly<Record<string, readonly SecurityBinding[]>>;
|
|
12
11
|
/** Snapshots operation bindings and credentials without acquiring tokens or making requests. */
|
|
13
|
-
constructor(baseUrl: string, bindings?: Readonly<Record<string, readonly SecurityBinding[]>>, credentials?: Readonly<Record<string, Credentials
|
|
12
|
+
constructor(baseUrl: string, bindings?: Readonly<Record<string, readonly SecurityBinding[]>>, credentials?: Readonly<Record<string, Credentials>>);
|
|
14
13
|
/** Expands server variables once and resolves relative servers against their document location. */
|
|
15
14
|
static serverUrl(template: string, variables: Readonly<Record<string, string>>, documentBaseUrl?: string): string;
|
|
16
15
|
/**
|
|
17
16
|
* Chooses one complete alternative per operation using credentials and optional explicit scheme sets.
|
|
18
17
|
* `alternativeSelection` selects a zero-based candidate index, including its scopes and endpoint metadata.
|
|
19
18
|
*/
|
|
20
|
-
static resolve(baseUrl: string, alternatives: Readonly<Record<string, readonly (readonly SecurityBinding[])[]>>, credentials: Readonly<Record<string, Credentials>>, selection?: Readonly<Record<string, readonly string[]>>, alternativeSelection?: Readonly<Record<string, number
|
|
21
|
-
private
|
|
19
|
+
static resolve(baseUrl: string, alternatives: Readonly<Record<string, readonly (readonly SecurityBinding[])[]>>, credentials: Readonly<Record<string, Credentials>>, selection?: Readonly<Record<string, readonly string[]>>, alternativeSelection?: Readonly<Record<string, number>>): ClientSettings;
|
|
20
|
+
private prepareTokenProviders;
|
|
22
21
|
private prepareProvider;
|
|
23
22
|
}
|
package/build/client-settings.js
CHANGED
|
@@ -12,23 +12,33 @@
|
|
|
12
12
|
// See the License for the specific language governing permissions and
|
|
13
13
|
// limitations under the License.
|
|
14
14
|
import { validateCredentials } from './credentials.js';
|
|
15
|
-
import { TokenManager } from './token-manager.js';
|
|
16
15
|
/** Resolved, transport-independent inputs supplied to an application's transport factory. */
|
|
17
16
|
export class ClientSettings {
|
|
18
17
|
baseUrl;
|
|
19
|
-
/**
|
|
20
|
-
|
|
18
|
+
/** Providers shared by this configuration's operations; caching requires an explicit TokenManager. */
|
|
19
|
+
tokenProviders;
|
|
21
20
|
bindings;
|
|
22
21
|
#credentials;
|
|
23
22
|
/** Snapshots operation bindings and credentials without acquiring tokens or making requests. */
|
|
24
|
-
constructor(baseUrl, bindings = {}, credentials = {}
|
|
23
|
+
constructor(baseUrl, bindings = {}, credentials = {}) {
|
|
25
24
|
const url = new URL(baseUrl);
|
|
26
|
-
if (!['https:', 'http:'].includes(url.protocol) ||
|
|
25
|
+
if (!['https:', 'http:'].includes(url.protocol) ||
|
|
26
|
+
url.username ||
|
|
27
|
+
url.password ||
|
|
28
|
+
url.href.includes('?') ||
|
|
29
|
+
url.href.includes('#'))
|
|
27
30
|
throw new TypeError('Client endpoint must be HTTP or HTTPS');
|
|
28
31
|
this.baseUrl = url.href;
|
|
29
|
-
this.bindings = Object.freeze(Object.fromEntries(Object.entries(bindings).map(([operation, values]) => [
|
|
32
|
+
this.bindings = Object.freeze(Object.fromEntries(Object.entries(bindings).map(([operation, values]) => [
|
|
33
|
+
operation,
|
|
34
|
+
Object.freeze(values.map((value) => Object.freeze({
|
|
30
35
|
...value,
|
|
31
|
-
...Object.fromEntries([
|
|
36
|
+
...Object.fromEntries([
|
|
37
|
+
'discoveryUrl',
|
|
38
|
+
'authorizationUrl',
|
|
39
|
+
'tokenUrl',
|
|
40
|
+
'refreshUrl',
|
|
41
|
+
].flatMap((key) => {
|
|
32
42
|
const endpoint = value[key];
|
|
33
43
|
if (typeof endpoint !== 'string')
|
|
34
44
|
return [];
|
|
@@ -36,23 +46,34 @@ export class ClientSettings {
|
|
|
36
46
|
throw new TypeError('Security endpoint URLs do not support server variables');
|
|
37
47
|
return [[key, new URL(endpoint, baseUrl).href]];
|
|
38
48
|
})),
|
|
39
|
-
scopes: Object.freeze([...value.scopes]),
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
49
|
+
scopes: Object.freeze([...value.scopes]),
|
|
50
|
+
transport: Object.freeze({ ...value.transport }),
|
|
51
|
+
}))),
|
|
52
|
+
])));
|
|
53
|
+
this.#credentials = new Map(Object.entries(credentials).map(([scheme, value]) => [
|
|
54
|
+
scheme,
|
|
55
|
+
Object.freeze({
|
|
56
|
+
...value,
|
|
57
|
+
...(value.kind === 'oauth' && value.endpoints
|
|
58
|
+
? {
|
|
59
|
+
endpoints: Object.freeze(Object.fromEntries(Object.entries(value.endpoints).map(([key, endpoint]) => {
|
|
43
60
|
if (endpoint === undefined)
|
|
44
61
|
return [key, undefined];
|
|
45
62
|
if (/[{}]/.test(endpoint))
|
|
46
63
|
throw new TypeError('Security endpoint URLs do not support server variables');
|
|
47
64
|
return [key, new URL(endpoint, baseUrl).href];
|
|
48
|
-
})))
|
|
65
|
+
}))),
|
|
66
|
+
}
|
|
67
|
+
: {}),
|
|
68
|
+
}),
|
|
69
|
+
]));
|
|
49
70
|
for (const binding of Object.values(this.bindings).flat()) {
|
|
50
71
|
const credential = this.#credentials.get(binding.scheme);
|
|
51
72
|
if (!credential)
|
|
52
73
|
throw new TypeError(`Missing credentials for scheme '${binding.scheme}'`);
|
|
53
74
|
validateCredentials(credential, binding);
|
|
54
75
|
}
|
|
55
|
-
this.
|
|
76
|
+
this.tokenProviders = this.prepareTokenProviders();
|
|
56
77
|
Object.freeze(this);
|
|
57
78
|
}
|
|
58
79
|
/** Expands server variables once and resolves relative servers against their document location. */
|
|
@@ -63,7 +84,11 @@ export class ClientSettings {
|
|
|
63
84
|
return variables[name];
|
|
64
85
|
});
|
|
65
86
|
const url = new URL(expanded, documentBaseUrl);
|
|
66
|
-
if (!['http:', 'https:'].includes(url.protocol) ||
|
|
87
|
+
if (!['http:', 'https:'].includes(url.protocol) ||
|
|
88
|
+
url.username ||
|
|
89
|
+
url.password ||
|
|
90
|
+
url.search ||
|
|
91
|
+
url.hash) {
|
|
67
92
|
throw new TypeError('Invalid HTTP server endpoint');
|
|
68
93
|
}
|
|
69
94
|
return url.href;
|
|
@@ -72,21 +97,29 @@ export class ClientSettings {
|
|
|
72
97
|
* Chooses one complete alternative per operation using credentials and optional explicit scheme sets.
|
|
73
98
|
* `alternativeSelection` selects a zero-based candidate index, including its scopes and endpoint metadata.
|
|
74
99
|
*/
|
|
75
|
-
static resolve(baseUrl, alternatives, credentials, selection = {}, alternativeSelection = {}
|
|
76
|
-
if ([...Object.keys(selection), ...Object.keys(alternativeSelection)].some(operation => !Object.hasOwn(alternatives, operation))) {
|
|
100
|
+
static resolve(baseUrl, alternatives, credentials, selection = {}, alternativeSelection = {}) {
|
|
101
|
+
if ([...Object.keys(selection), ...Object.keys(alternativeSelection)].some((operation) => !Object.hasOwn(alternatives, operation))) {
|
|
77
102
|
throw new TypeError('Unknown operation selection');
|
|
78
103
|
}
|
|
79
104
|
const bindings = Object.create(null);
|
|
80
105
|
for (const [operation, candidates] of Object.entries(alternatives)) {
|
|
81
|
-
const selected = Object.hasOwn(selection, operation)
|
|
82
|
-
|
|
106
|
+
const selected = Object.hasOwn(selection, operation)
|
|
107
|
+
? selection[operation]
|
|
108
|
+
: undefined;
|
|
109
|
+
const selectedIndex = Object.hasOwn(alternativeSelection, operation)
|
|
110
|
+
? alternativeSelection[operation]
|
|
111
|
+
: undefined;
|
|
83
112
|
const usable = candidates.filter((candidate, index) => {
|
|
84
113
|
if (selectedIndex !== undefined && selectedIndex !== index)
|
|
85
114
|
return false;
|
|
86
|
-
if (selected &&
|
|
115
|
+
if (selected &&
|
|
116
|
+
(selected.length !== candidate.length ||
|
|
117
|
+
candidate.some((binding) => !selected.includes(binding.scheme))))
|
|
87
118
|
return false;
|
|
88
|
-
return candidate.every(binding => {
|
|
89
|
-
const credential = Object.hasOwn(credentials, binding.scheme)
|
|
119
|
+
return candidate.every((binding) => {
|
|
120
|
+
const credential = Object.hasOwn(credentials, binding.scheme)
|
|
121
|
+
? credentials[binding.scheme]
|
|
122
|
+
: undefined;
|
|
90
123
|
if (!credential)
|
|
91
124
|
return false;
|
|
92
125
|
try {
|
|
@@ -102,9 +135,9 @@ export class ClientSettings {
|
|
|
102
135
|
throw new TypeError(`Operation '${operation}' requires one complete security alternative`);
|
|
103
136
|
bindings[operation] = usable[0];
|
|
104
137
|
}
|
|
105
|
-
return new ClientSettings(baseUrl, bindings, credentials
|
|
138
|
+
return new ClientSettings(baseUrl, bindings, credentials);
|
|
106
139
|
}
|
|
107
|
-
|
|
140
|
+
prepareTokenProviders() {
|
|
108
141
|
const providers = new Map();
|
|
109
142
|
const owners = new Map();
|
|
110
143
|
for (const binding of Object.values(this.bindings).flat()) {
|
|
@@ -117,10 +150,7 @@ export class ClientSettings {
|
|
|
117
150
|
owners.set(binding.provider, binding.scheme);
|
|
118
151
|
providers.set(binding.provider, this.prepareProvider(this.#credentials.get(binding.scheme)));
|
|
119
152
|
}
|
|
120
|
-
|
|
121
|
-
return undefined;
|
|
122
|
-
const resolved = Object.freeze(Object.fromEntries(providers));
|
|
123
|
-
return factory ? factory(resolved) : new TokenManager(resolved);
|
|
153
|
+
return Object.freeze(Object.fromEntries(providers));
|
|
124
154
|
}
|
|
125
155
|
prepareProvider(credentials) {
|
|
126
156
|
if (credentials.kind === 'provider')
|
|
@@ -137,7 +167,7 @@ export class ClientSettings {
|
|
|
137
167
|
token = credentials.key;
|
|
138
168
|
break;
|
|
139
169
|
case 'basic':
|
|
140
|
-
token = btoa(Array.from(new TextEncoder().encode(`${credentials.username}:${credentials.password}`), byte => String.fromCodePoint(byte)).join(''));
|
|
170
|
+
token = btoa(Array.from(new TextEncoder().encode(`${credentials.username}:${credentials.password}`), (byte) => String.fromCodePoint(byte)).join(''));
|
|
141
171
|
break;
|
|
142
172
|
}
|
|
143
173
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-settings.js","sourceRoot":"","sources":["../src/client-settings.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,EAAE;AACF,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,gDAAgD;AAChD,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC,OAAO,EAAe,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"client-settings.js","sourceRoot":"","sources":["../src/client-settings.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,EAAE;AACF,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,gDAAgD;AAChD,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC,OAAO,EAAe,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAIpE,6FAA6F;AAC7F,MAAM,OAAO,cAAc;IAChB,OAAO,CAAS;IACzB,sGAAsG;IAC7F,cAAc,CAA0C;IACxD,QAAQ,CAAuD;IAC/D,YAAY,CAAmC;IAExD,gGAAgG;IAChG,YACE,OAAe,EACf,WAAiE,EAAE,EACnE,cAAqD,EAAE;QAEvD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;QAC7B,IACE,CAAC,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC;YAC3C,GAAG,CAAC,QAAQ;YACZ,GAAG,CAAC,QAAQ;YACZ,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;YACtB,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;YAEtB,MAAM,IAAI,SAAS,CAAC,uCAAuC,CAAC,CAAC;QAC/D,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC;QACxB,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,CAC3B,MAAM,CAAC,WAAW,CAChB,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;YACpD,SAAS;YACT,MAAM,CAAC,MAAM,CACX,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CACnB,MAAM,CAAC,MAAM,CAAC;gBACZ,GAAG,KAAK;gBACR,GAAG,MAAM,CAAC,WAAW,CACnB;oBACE,cAAc;oBACd,kBAAkB;oBAClB,UAAU;oBACV,YAAY;iBACb,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;oBAChB,MAAM,QAAQ,GAAG,KAAK,CAAC,GAA4B,CAAC,CAAC;oBACrD,IAAI,OAAO,QAAQ,KAAK,QAAQ;wBAAE,OAAO,EAAE,CAAC;oBAC5C,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC;wBACvB,MAAM,IAAI,SAAS,CACjB,wDAAwD,CACzD,CAAC;oBACJ,OAAO,CAAC,CAAC,GAAG,EAAE,IAAI,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;gBAClD,CAAC,CAAC,CACH;gBACD,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;gBACxC,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;aACjD,CAAC,CACH,CACF;SACF,CAAC,CACH,CACF,CAAC;QACF,IAAI,CAAC,YAAY,GAAG,IAAI,GAAG,CACzB,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC;YACnD,MAAM;YACN,MAAM,CAAC,MAAM,CAAC;gBACZ,GAAG,KAAK;gBACR,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,SAAS;oBAC3C,CAAC,CAAC;wBACE,SAAS,EAAE,MAAM,CAAC,MAAM,CACtB,MAAM,CAAC,WAAW,CAChB,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,QAAQ,CAAC,EAAE,EAAE;4BACtD,IAAI,QAAQ,KAAK,SAAS;gCAAE,OAAO,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;4BACpD,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC;gCACvB,MAAM,IAAI,SAAS,CACjB,wDAAwD,CACzD,CAAC;4BACJ,OAAO,CAAC,GAAG,EAAE,IAAI,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC;wBAChD,CAAC,CAAC,CACH,CACF;qBACF;oBACH,CAAC,CAAC,EAAE,CAAC;aACR,CAAC;SACH,CAAC,CACH,CAAC;QACF,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;YAC1D,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YACzD,IAAI,CAAC,UAAU;gBACb,MAAM,IAAI,SAAS,CACjB,mCAAmC,OAAO,CAAC,MAAM,GAAG,CACrD,CAAC;YACJ,mBAAmB,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAC3C,CAAC;QACD,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,qBAAqB,EAAE,CAAC;QACnD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC;IAED,mGAAmG;IACnG,MAAM,CAAC,SAAS,CACd,QAAgB,EAChB,SAA2C,EAC3C,eAAwB;QAExB,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAC/B,eAAe,EACf,CAAC,MAAM,EAAE,IAAY,EAAE,EAAE;YACvB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC;gBACjC,MAAM,IAAI,SAAS,CAAC,4BAA4B,IAAI,GAAG,CAAC,CAAC;YAC3D,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC;QACzB,CAAC,CACF,CAAC;QACF,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;QAC/C,IACE,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC;YAC3C,GAAG,CAAC,QAAQ;YACZ,GAAG,CAAC,QAAQ;YACZ,GAAG,CAAC,MAAM;YACV,GAAG,CAAC,IAAI,EACR,CAAC;YACD,MAAM,IAAI,SAAS,CAAC,8BAA8B,CAAC,CAAC;QACtD,CAAC;QACD,OAAO,GAAG,CAAC,IAAI,CAAC;IAClB,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,OAAO,CACZ,OAAe,EACf,YAEC,EACD,WAAkD,EAClD,YAAyD,EAAE,EAC3D,uBAAyD,EAAE;QAE3D,IACE,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,CACpE,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,SAAS,CAAC,CACvD,EACD,CAAC;YACD,MAAM,IAAI,SAAS,CAAC,6BAA6B,CAAC,CAAC;QACrD,CAAC;QACD,MAAM,QAAQ,GACZ,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACtB,KAAK,MAAM,CAAC,SAAS,EAAE,UAAU,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;YACnE,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC;gBAClD,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC;gBACtB,CAAC,CAAC,SAAS,CAAC;YACd,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,oBAAoB,EAAE,SAAS,CAAC;gBAClE,CAAC,CAAC,oBAAoB,CAAC,SAAS,CAAC;gBACjC,CAAC,CAAC,SAAS,CAAC;YACd,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,EAAE;gBACpD,IAAI,aAAa,KAAK,SAAS,IAAI,aAAa,KAAK,KAAK;oBACxD,OAAO,KAAK,CAAC;gBACf,IACE,QAAQ;oBACR,CAAC,QAAQ,CAAC,MAAM,KAAK,SAAS,CAAC,MAAM;wBACnC,SAAS,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;oBAElE,OAAO,KAAK,CAAC;gBACf,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE;oBACjC,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC;wBAC3D,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;wBAC7B,CAAC,CAAC,SAAS,CAAC;oBACd,IAAI,CAAC,UAAU;wBAAE,OAAO,KAAK,CAAC;oBAC9B,IAAI,CAAC;wBACH,mBAAmB,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;wBACzC,OAAO,IAAI,CAAC;oBACd,CAAC;oBAAC,MAAM,CAAC;wBACP,OAAO,KAAK,CAAC;oBACf,CAAC;gBACH,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;YACH,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;gBACrB,MAAM,IAAI,SAAS,CACjB,cAAc,SAAS,8CAA8C,CACtE,CAAC;YACJ,QAAQ,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QAClC,CAAC;QACD,OAAO,IAAI,cAAc,CAAC,OAAO,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;IAC5D,CAAC;IAEO,qBAAqB;QAC3B,MAAM,SAAS,GAAG,IAAI,GAAG,EAAyB,CAAC;QACnD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;QACzC,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;YAC1D,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YAC9C,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;gBAC1D,MAAM,IAAI,SAAS,CACjB,gEAAgE,CACjE,CAAC;YACJ,CAAC;YACD,IAAI,QAAQ,KAAK,SAAS;gBAAE,SAAS;YACrC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;YAC7C,SAAS,CAAC,GAAG,CACX,OAAO,CAAC,QAAQ,EAChB,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAE,CAAC,CAC7D,CAAC;QACJ,CAAC;QACD,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC;IACtD,CAAC;IAEO,eAAe,CAAC,WAAwB;QAC9C,IAAI,WAAW,CAAC,IAAI,KAAK,UAAU;YAAE,OAAO,WAAW,CAAC,QAAQ,CAAC;QACjE,IAAI,WAAW,CAAC,IAAI,KAAK,OAAO;YAC9B,OAAO,WAAW,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;QAClD,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;QACrC,IAAI,KAAa,CAAC;QAClB,QAAQ,WAAW,CAAC,IAAI,EAAE,CAAC;YACzB,KAAK,QAAQ;gBACX,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC;gBAC1B,MAAM;YACR,KAAK,QAAQ;gBACX,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC;gBACxB,MAAM;YACR,KAAK,OAAO;gBACV,KAAK,GAAG,IAAI,CACV,KAAK,CAAC,IAAI,CACR,IAAI,WAAW,EAAE,CAAC,MAAM,CACtB,GAAG,WAAW,CAAC,QAAQ,IAAI,WAAW,CAAC,QAAQ,EAAE,CAClD,EACD,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CACrC,CAAC,IAAI,CAAC,EAAE,CAAC,CACX,CAAC;gBACF,MAAM;QACV,CAAC;QACD,OAAO;YACL,QAAQ;YACR,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC;YAC/C,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;SACvD,CAAC;IACJ,CAAC;CACF"}
|
package/build/event-parser.d.ts
CHANGED
|
@@ -1,19 +1,32 @@
|
|
|
1
|
+
/** Message fields dispatched at a blank line; ID-only frames update the reconnect cursor. */
|
|
1
2
|
export interface EventInfo {
|
|
3
|
+
/** Last valid ID in this frame; NUL-containing fields are ignored. */
|
|
2
4
|
id?: string;
|
|
3
5
|
event?: string;
|
|
4
6
|
data?: string;
|
|
7
|
+
}
|
|
8
|
+
/** Connection controls reported immediately, independently of message boundaries. */
|
|
9
|
+
export interface EventControl {
|
|
10
|
+
/** A valid non-negative safe integer, retaining its wire representation. */
|
|
5
11
|
retry?: string;
|
|
6
12
|
keepalive?: string;
|
|
7
13
|
'retry-max'?: string;
|
|
8
14
|
}
|
|
15
|
+
/** Incremental UTF-8 SSE parser. Create one instance per connection; incomplete events end with it. */
|
|
9
16
|
export declare class EventParser {
|
|
17
|
+
private readonly control;
|
|
10
18
|
private readonly decoder;
|
|
11
|
-
private
|
|
12
|
-
|
|
13
|
-
private
|
|
14
|
-
private
|
|
15
|
-
private
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
private atStart;
|
|
20
|
+
private readonly lineParts;
|
|
21
|
+
private event;
|
|
22
|
+
private readonly data;
|
|
23
|
+
private skipLF;
|
|
24
|
+
/** Receives each completed control line, even when EOF discards the unfinished message. */
|
|
25
|
+
constructor(control?: (control: EventControl) => void);
|
|
26
|
+
/** Parses complete lines and events, discarding the rest of a chunk when the signal aborts. */
|
|
27
|
+
process(buffer: ArrayBuffer | ArrayBufferView, dispatcher: (eventInfo: EventInfo) => void, signal?: AbortSignal): void;
|
|
28
|
+
private discard;
|
|
29
|
+
private processLine;
|
|
19
30
|
}
|
|
31
|
+
/** @internal Parses bounded SSE millisecond values without accepting partial numbers. */
|
|
32
|
+
export declare function parseEventMilliseconds(value: string): number | undefined;
|