@outfoxx/sunday 2.0.0-beta.17 → 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.
Files changed (66) hide show
  1. package/README.md +191 -30
  2. package/build/client-settings.d.ts +6 -7
  3. package/build/client-settings.js +58 -28
  4. package/build/client-settings.js.map +1 -1
  5. package/build/event-parser.d.ts +21 -8
  6. package/build/event-parser.js +93 -121
  7. package/build/event-parser.js.map +1 -1
  8. package/build/fetch-copy.d.ts +15 -0
  9. package/build/fetch-copy.js +70 -0
  10. package/build/fetch-copy.js.map +1 -0
  11. package/build/fetch-event-source.d.ts +6 -5
  12. package/build/fetch-event-source.js +168 -137
  13. package/build/fetch-event-source.js.map +1 -1
  14. package/build/fetch-oauth-token-provider.js +61 -19
  15. package/build/fetch-oauth-token-provider.js.map +1 -1
  16. package/build/fetch-transport.d.ts +14 -6
  17. package/build/fetch-transport.js +126 -168
  18. package/build/fetch-transport.js.map +1 -1
  19. package/build/fetch.js +5 -0
  20. package/build/fetch.js.map +1 -1
  21. package/build/index.d.ts +7 -2
  22. package/build/index.js +6 -2
  23. package/build/index.js.map +1 -1
  24. package/build/request-adapter.d.ts +8 -0
  25. package/build/{token-manager-factory.js → request-adapter.js} +1 -1
  26. package/build/request-adapter.js.map +1 -0
  27. package/build/request-adapters.d.ts +25 -8
  28. package/build/request-adapters.js +126 -14
  29. package/build/request-adapters.js.map +1 -1
  30. package/build/request-body.d.ts +24 -0
  31. package/build/request-body.js +104 -0
  32. package/build/request-body.js.map +1 -0
  33. package/build/request-cancellation-error.d.ts +13 -0
  34. package/build/request-cancellation-error.js +43 -0
  35. package/build/request-cancellation-error.js.map +1 -0
  36. package/build/request-execution.d.ts +18 -0
  37. package/build/request-execution.js +108 -0
  38. package/build/request-execution.js.map +1 -0
  39. package/build/request-security.d.ts +9 -3
  40. package/build/request-security.js +101 -36
  41. package/build/request-security.js.map +1 -1
  42. package/build/response-adapter.d.ts +10 -0
  43. package/build/response-adapter.js +15 -0
  44. package/build/response-adapter.js.map +1 -0
  45. package/build/response-adapters.d.ts +13 -0
  46. package/build/response-adapters.js +75 -0
  47. package/build/response-adapters.js.map +1 -0
  48. package/build/token-manager.d.ts +13 -4
  49. package/build/token-manager.js +110 -33
  50. package/build/token-manager.js.map +1 -1
  51. package/build/token-provider.d.ts +8 -1
  52. package/build/token-provider.js +71 -0
  53. package/build/token-provider.js.map +1 -1
  54. package/build/transport.d.ts +3 -3
  55. package/build/util/abort.d.ts +3 -0
  56. package/build/util/abort.js +42 -0
  57. package/build/util/abort.js.map +1 -0
  58. package/build/util/native-fetch.d.ts +2 -0
  59. package/build/util/native-fetch.js +39 -0
  60. package/build/util/native-fetch.js.map +1 -0
  61. package/build/util/owned-body.d.ts +12 -0
  62. package/build/util/owned-body.js +243 -0
  63. package/build/util/owned-body.js.map +1 -0
  64. package/package.json +9 -6
  65. package/build/token-manager-factory.d.ts +0 -9
  66. 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
  ![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/outfoxx/sunday-js/ci.yml?branch=main)
5
4
  ![Coverage](https://sonarcloud.io/api/project_badges/measure?project=outfoxx_sunday-js&metric=coverage)
@@ -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
- one shared `TokenManager` and pass it as `new FetchTransport(baseUrl, {tokenManager})`. Client secrets,
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 persistence
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 settings = ClientSettings.resolve(baseUrl, alternatives, credentials, {}, {},
109
- providers => new TokenManager(providers, {
110
- store: applicationStore, expirySkewMs: 30_000, now: applicationClock,
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
- The same optional `TokenManagerFactory` is the fourth constructor argument. The last two resolver
115
- arguments before it are scheme selections and alternative-index selections. Clock values and expiry
116
- skew are milliseconds. The native manager has no close/reset method: cancel application requests with
117
- their abort signals, await completion, and discard the manager at session end. The factory does not
118
- change cancellation behavior or take ownership of application resources.
119
-
120
- The hook is invoked once with the resolved provider map, after security validation, and is skipped
121
- when no providers are selected. It must only construct a manager: do not acquire tokens or read
122
- storage in the hook. Omitting it keeps the existing in-memory default. Settings retain the returned
123
- manager, not the factory. All operations on those settings share it; generated aggregate children
124
- therefore retain the same cache and single-flight renewal. Independently created managers do not
125
- coordinate concurrent refreshes, even if their stores are the same. Reuse a client/aggregate within
126
- an active session; use successive managers to reopen saved sessions.
127
-
128
- The application owns persistence, encryption, store access and session boundaries. Provider/client,
129
- grant, profile and endpoint identities must distinguish environments and users; the API base URL
130
- alone is not an implicit store namespace. Use a new grant identity for a fresh authorization session.
131
- For logout, stop requests and wait for pending refresh/persistence to finish before removing the
132
- session's store entries, then construct fresh settings. `invalidate` expires an access token for
133
- renewal; it is not logout and deliberately retains refresh state. No disk storage is enabled automatically.
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 { TokenManager } from './token-manager.js';
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
- /** Prepared manager shared by this configuration's operations; construction never acquires tokens. */
10
- readonly tokenManager: TokenManager | undefined;
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>>, tokenManagerFactory?: TokenManagerFactory);
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>>, tokenManagerFactory?: TokenManagerFactory): ClientSettings;
21
- private prepareTokenManager;
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
  }
@@ -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
- /** Prepared manager shared by this configuration's operations; construction never acquires tokens. */
20
- tokenManager;
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 = {}, tokenManagerFactory) {
23
+ constructor(baseUrl, bindings = {}, credentials = {}) {
25
24
  const url = new URL(baseUrl);
26
- if (!['https:', 'http:'].includes(url.protocol) || url.username || url.password || url.href.includes('?') || url.href.includes('#'))
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]) => [operation, Object.freeze(values.map(value => Object.freeze({
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(['discoveryUrl', 'authorizationUrl', 'tokenUrl', 'refreshUrl'].flatMap(key => {
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]), transport: Object.freeze({ ...value.transport }),
40
- })))])));
41
- this.#credentials = new Map(Object.entries(credentials).map(([scheme, value]) => [scheme, Object.freeze({ ...value, ...(value.kind === 'oauth' && value.endpoints
42
- ? { endpoints: Object.freeze(Object.fromEntries(Object.entries(value.endpoints).map(([key, endpoint]) => {
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.tokenManager = this.prepareTokenManager(tokenManagerFactory);
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) || url.username || url.password || url.search || url.hash) {
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 = {}, tokenManagerFactory) {
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) ? selection[operation] : undefined;
82
- const selectedIndex = Object.hasOwn(alternativeSelection, operation) ? alternativeSelection[operation] : undefined;
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 && (selected.length !== candidate.length || candidate.some(binding => !selected.includes(binding.scheme))))
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) ? credentials[binding.scheme] : undefined;
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, tokenManagerFactory);
138
+ return new ClientSettings(baseUrl, bindings, credentials);
106
139
  }
107
- prepareTokenManager(factory) {
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
- if (!providers.size)
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":"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"}
1
+ {"version":3,"file":"client-settings.js","sourceRoot":"","sources":["../src/client-settings.ts"],"names":[],"mappings":"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"}
@@ -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 unprocessedBuffer?;
12
- process(buffer: ArrayBuffer, dispatcher: (eventInfo: EventInfo) => void): void;
13
- private buildAvailableBuffer;
14
- private extractEventStringsFromBuffer;
15
- private static findEventSeparator;
16
- private static parseAndDispatchEvents;
17
- private static parseEvent;
18
- private static trimFieldValue;
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;