@buildplease/webkit 1.0.1 → 1.0.2

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 CHANGED
@@ -1,8 +1,8 @@
1
1
  # @buildplease/webkit
2
2
 
3
- WebKit provides the shared browser-side runtime for BuildPlease applications, including dependency injection, HTTP networking, request interceptors, web models, and L10n integration.
3
+ WebKit is the BuildPlease application kit for browser applications. It builds on Core and provides shared web application architecture and runtime primitives without depending on a specific frontend framework.
4
4
 
5
- ## Install
5
+ ## Installation
6
6
 
7
7
  ```bash
8
8
  pnpm add @buildplease/webkit
@@ -11,20 +11,20 @@ pnpm add @buildplease/webkit
11
11
  ## Usage
12
12
 
13
13
  ```ts
14
- import { HttpError, InterceptorSet, webkitAssembly } from '@buildplease/webkit';
14
+ import { webkitAssembly } from '@buildplease/webkit';
15
15
 
16
16
  const assemblies = webkitAssembly();
17
17
  ```
18
18
 
19
- WebKit re-exports the Core API, so shared BuildPlease primitives can be imported from the same package in browser applications.
19
+ ## Features
20
20
 
21
- ## What’s included
22
-
23
- - browser application assembly
24
- - Axios-based remote networking primitives
25
- - request interceptors and cookie handling
26
- - HTTP error handling
27
- - shared web models
21
+ - browser application architecture and dependency injection
22
+ - asynchronous operations and remote resources
23
+ - transport-independent HTTP primitives
24
+ - request interception and error handling
25
+ - shared web models and utilities
28
26
  - L10n integration
29
27
 
30
- Part of [BuildPlease](https://github.com/BuildPlease/buildplease).
28
+ ## License
29
+
30
+ MIT
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,s)=>(s=n==null?{}:e(i(n)),o(r||!n||!n.__esModule||!a.call(n,`default`)?t(s,`default`,{value:n,enumerable:!0}):s,n));require("reflect-metadata");let c=require("@buildplease/core"),l=require("axios");l=s(l,1);let u=require("inversify");function d(){return[]}const f={name:`buildplease`,displayName:`BuildPlease`,scope:`@buildplease`};`${f.name}`;const p={DI:{}},m=c.CoreL10nResource;var h=class extends Error{statusCode;code;details;constructor(e){super(e.message),this.name=`HttpError`,this.statusCode=e.statusCode,this.code=e.code,this.details=e.details}},g=class e{order=-10;hash(){return Symbol.for(`${f.scope}.webkit.networking.interceptor.cookie`)}equals(t){return t instanceof e}intercept(e){return{...e,withCredentials:!0}}};function _(e,t){if(typeof Reflect==`object`&&typeof Reflect.metadata==`function`)return Reflect.metadata(e,t)}function v(e,t){return function(n,r){t(n,r,e)}}function y(e,t,n,r){var i=arguments.length,a=i<3?t:r===null?r=Object.getOwnPropertyDescriptor(t,n):r,o;if(typeof Reflect==`object`&&typeof Reflect.decorate==`function`)a=Reflect.decorate(e,t,n,r);else for(var s=e.length-1;s>=0;s--)(o=e[s])&&(a=(i<3?o(a):i>3?o(t,n,a):o(t,n))||a);return i>3&&a&&Object.defineProperty(t,n,a),a}const b=`Unknown Error`;let x=class{endpoint;interceptors=new S;constructor(e){this.endpoint=e,this.use(new g)}use(...e){return this.interceptors.add(...e),this}removeInterceptor(e){return this.interceptors.remove(e),this}clearInterceptors(){return this.interceptors.clear(),this}async execute(e,t){try{let n=await this.convertOrThrow(()=>this.endpoint.convertInput(e)),r={...t};for(let e of this.interceptors.list())r=e.intercept(r);let i=await this.endpoint.makeRequest(n,r);return await this.convertOrThrow(()=>this.endpoint.convertOutput(i))}catch(e){throw this.parseError(e)}}parseError(e){if(e instanceof h||e instanceof c.TimeoutError||e instanceof c.NetworkError||e instanceof c.CanceledError||e instanceof c.ConversionError||e instanceof c.UnknownError)return e;if(l.default.isCancel?.(e)||l.default.isAxiosError(e)&&(e.code===`ERR_CANCELED`||e.message===`canceled`))return new c.CanceledError({cause:e});if(l.default.isAxiosError(e)&&e.code===`ECONNABORTED`)return new c.TimeoutError({cause:e});if(l.default.isAxiosError(e)&&!e.response)return new c.NetworkError({message:e.message,cause:e});if(l.default.isAxiosError(e)&&e.response){let{status:t,data:n}=e.response,r=n;typeof r==`string`&&(r=(0,c.ignoreError)(()=>JSON.parse(r)).orDefault(r));let i=this.isStringArrayRecord(r.details)?r.details:void 0;return new h(this.buildHttpErrorOptions(t,r,i))}let t=e instanceof Error?e.message:b;return new c.UnknownError({message:t,cause:e})}async convertOrThrow(e){try{return await e()}catch(e){throw new c.ConversionError({cause:e})}}isStringArrayRecord(e){return!(0,c.isDefinedAndNotNull)(e)||!(0,c.isPlainObject)(e)?!1:Object.values(e).every(e=>Array.isArray(e)&&e.every(e=>typeof e==`string`))}buildHttpErrorOptions(e,t,n){return{statusCode:e,code:(0,c.isNonEmptyString)(t?.code)?t.code:`UNKNOWN_ERROR`,message:(0,c.isNonEmptyString)(t?.message)?t.message:b,details:n}}};x=y([(0,u.injectable)(),v(0,(0,u.unmanaged)()),_(`design:paramtypes`,[Object])],x);var S=class{map=new Map;add(...e){for(let t of e){let e=t.hash(),n=this.map.get(e);n&&n.equals(t)||this.map.set(e,t)}return this}remove(e){return this.map.delete(e.hash()),this}clear(){return this.map.clear(),this}list(){return[...this.map.values()].sort((e,t)=>e.order-t.order)}};function C(){let e=(0,c.coreAssembly)(),t=d();return[...e,...t]}Object.defineProperty(exports,"BaseRemoteResource",{enumerable:!0,get:function(){return x}}),exports.CookieInterceptor=g,exports.HttpError=h,exports.InterceptorSet=S,exports.WebKitL10nResource=m,exports.WebKitSymbols=p,exports.webkitAssembly=C,Object.keys(c).forEach(function(e){e!=="default"&&!Object.prototype.hasOwnProperty.call(exports,e)&&Object.defineProperty(exports,e,{enumerable:!0,get:function(){return c[e]}})});
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require("reflect-metadata");let e=require("@buildplease/core"),t=require("inversify");function n(){return[]}`${{name:`buildplease`,displayName:`BuildPlease`,scope:`@buildplease`}.name}`;const r={DI:{}},i=e.CoreL10nResource;var a=class{mode;pendingEntries=[];activeEntries=new Set;interruption;isSerialOperationRunning=!1;constructor(e=`parallel`){this.mode=e}execute(t){if(this.interruption)return Promise.reject(new e.CanceledError);let n=this.createEntry(t);return this.mode===`serial`?(this.pendingEntries.push(n),this.startNextSerialOperation()):this.startEntry(n),n.promise}cancelAll(e){let t=this.pendingEntries.splice(0);for(let n of t)this.cancelEntry(n,e);for(let t of this.activeEntries)this.cancelEntry(t,e)}async interrupt(e){if(!this.interruption){let t=Promise.resolve().then(e).finally(()=>{this.interruption===t&&(this.interruption=void 0,this.startNextSerialOperation())});this.interruption=t,this.cancelAll()}await this.interruption}createEntry(e){let t,n;return{operation:e,promise:new Promise((e,r)=>{t=e,n=r}),resolve:e=>t?.(e),reject:e=>n?.(e),canceled:!1,settled:!1}}startEntry(e){if(e.canceled||this.interruption){this.cancelEntry(e);return}this.activeEntries.add(e),this.mode===`serial`&&(this.isSerialOperationRunning=!0),Promise.resolve().then(e.operation).then(t=>{e.canceled||this.resolveEntry(e,t)},t=>{e.canceled||this.rejectEntry(e,t)}).finally(()=>{this.activeEntries.delete(e),this.mode===`serial`&&(this.isSerialOperationRunning=!1,this.startNextSerialOperation())})}startNextSerialOperation(){if(this.mode!==`serial`||this.isSerialOperationRunning||this.interruption)return;let e=this.pendingEntries.shift();e&&this.startEntry(e)}cancelEntry(t,n){t.canceled||(t.canceled=!0,t.settled||this.rejectEntry(t,new e.CanceledError({cause:n})))}resolveEntry(e,t){e.settled||(e.settled=!0,e.resolve(t))}rejectEntry(e,t){e.settled||(e.settled=!0,e.reject(t))}},o=class extends Error{statusCode;code;details;constructor(e){super(e.message),this.name=`HttpError`,this.statusCode=e.statusCode,this.code=e.code,this.details=e.details,e.cause!==void 0&&(this.cause=e.cause)}},s=class{interceptors;constructor(e=[],t){this.interceptors=this.resolveInterceptors(e,t)}async intercept(e){let t=e;for(let e of this.interceptors)t=await e.intercept(t);return t}resolveInterceptors(e,t){let n=new Set,r=[];for(let i of e){if(n.has(i.identity)){t?.(`Duplicate HTTP request interceptor ignored: ${String(i.identity)}`);continue}n.add(i.identity),r.push(i)}return Object.freeze(r)}};const c={credentials:!0,headers:{}};var l=class{requestOptions;interceptorPipeline;asyncQueue;unauthorized;constructor(e={}){this.requestOptions=e.requestOptions??{},this.interceptorPipeline=e.interceptorPipeline??new s,this.asyncQueue=e.asyncQueue??new a,this.unauthorized=e.unauthorized}execute(e,t){return this.asyncQueue.execute(async()=>{let n=await this.makeRequestOptions(e,t);try{let t=this.createClient(n);return await e.execute(t)}catch(e){throw this.handleError(e)}})}handleError(t){return t instanceof o||t instanceof e.NetworkError||t instanceof e.TimeoutError||t instanceof e.CanceledError||t instanceof e.UnknownError?t:new e.UnknownError({message:t instanceof Error?t.message:void 0,cause:t})}async makeRequestOptions(e,t){let n=this.mergeRequestOptions(c,this.requestOptions);return n=await this.interceptorPipeline.intercept(n),n=this.mergeRequestOptions(n,e.options),n=this.mergeRequestOptions(n,t),n}mergeRequestOptions(e,t){return t?{credentials:t.credentials??e.credentials,headers:{...e.headers,...t.headers}}:e}};function u(e,t){if(typeof Reflect==`object`&&typeof Reflect.metadata==`function`)return Reflect.metadata(e,t)}function d(e,t){return function(n,r){t(n,r,e)}}function f(e,t,n,r){var i=arguments.length,a=i<3?t:r===null?r=Object.getOwnPropertyDescriptor(t,n):r,o;if(typeof Reflect==`object`&&typeof Reflect.decorate==`function`)a=Reflect.decorate(e,t,n,r);else for(var s=e.length-1;s>=0;s--)(o=e[s])&&(a=(i<3?o(a):i>3?o(t,n,a):o(t,n))||a);return i>3&&a&&Object.defineProperty(t,n,a),a}let p=class{endpoint;httpClient;constructor(e,t){this.endpoint=e,this.httpClient=t}async execute(e,t){let n=await this.convertOrThrow(()=>this.endpoint.convertInput(e)),r=this.endpoint.makeRequest(n),i=await this.httpClient.execute(r,t);return await this.convertOrThrow(()=>this.endpoint.convertOutput(i))}async convertOrThrow(t){try{return await t()}catch(t){throw new e.ConversionError({cause:t})}}};p=f([(0,t.injectable)(),d(0,(0,t.unmanaged)()),d(1,(0,t.unmanaged)()),u(`design:paramtypes`,[Object,Object])],p);let m=class extends p{constructor(e,t){super(e,t)}};m=f([(0,t.injectable)(),u(`design:paramtypes`,[Object,Object])],m);let h=class extends p{constructor(e,t){super(e,t)}async execute(t,n){try{return await super.execute(t,n)}catch(t){if(!(t instanceof o))throw t;let n=this.httpClient.unauthorized;throw!n||!n.statusCodes.includes(t.statusCode)?t:n.cancelAll?(await this.httpClient.asyncQueue.interrupt(()=>n.handler.handle(t)),new e.CanceledError({cause:t})):(await n.handler.handle(t),t)}}};h=f([(0,t.injectable)(),u(`design:paramtypes`,[Object,Object])],h);function g(){let t=(0,e.coreAssembly)(),r=n();return[...t,...r]}exports.AsyncQueueImpl=a,exports.HttpClient=l,exports.HttpError=o,exports.HttpRequestInterceptorPipeline=s,Object.defineProperty(exports,"PublicRemoteResource",{enumerable:!0,get:function(){return m}}),Object.defineProperty(exports,"RemoteResource",{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,"SecuredRemoteResource",{enumerable:!0,get:function(){return h}}),exports.WebKitL10nResource=i,exports.WebKitSymbols=r,exports.webkitAssembly=g,Object.keys(e).forEach(function(t){t!=="default"&&!Object.prototype.hasOwnProperty.call(exports,t)&&Object.defineProperty(exports,t,{enumerable:!0,get:function(){return e[t]}})});
@@ -1,6 +1,5 @@
1
1
  import "reflect-metadata";
2
- import { Assembly, AsyncOperation, Equatable, Hashable, Identity } from "@buildplease/core";
3
- import { AxiosRequestConfig } from "axios";
2
+ import { Assembly, AsyncOperation, Identity } from "@buildplease/core";
4
3
  export * from "@buildplease/core";
5
4
  //#region src/di/symbols.d.ts
6
5
  declare const WebKitSymbols: {
@@ -308,62 +307,123 @@ interface TablePaginationModel {
308
307
  pageSizeOptions?: number[];
309
308
  }
310
309
  //#endregion
311
- //#region src/networking/http-error.d.ts
312
- interface HttpErrorOptions {
310
+ //#region src/networking/async-queue.d.ts
311
+ /**
312
+ * Defines how queued operations are processed.
313
+ *
314
+ * `parallel` starts each operation immediately without waiting for previous operations to finish.
315
+ * `serial` starts an operation only after the previous operation has finished.
316
+ */
317
+ type AsyncQueueMode = 'parallel' | 'serial';
318
+ /**
319
+ * Executes and coordinates asynchronous operations.
320
+ */
321
+ interface AsyncQueue {
322
+ /**
323
+ * Executes an operation according to the configured queue mode.
324
+ * Operations submitted during an interruption are canceled without running.
325
+ */
326
+ execute<Output>(operation: () => Promise<Output>): Promise<Output>;
327
+ /**
328
+ * Cancels all unresolved operations. Pending serial operations are not started and results from
329
+ * already-running operations are ignored.
330
+ *
331
+ * @param cause Optional cancellation cause.
332
+ */
333
+ cancelAll(cause?: unknown): void;
334
+ /**
335
+ * Cancels all unresolved operations and executes one interruption handler.
336
+ * Concurrent interruptions wait for the same handler to complete.
337
+ */
338
+ interrupt(handler: () => Promise<void>): Promise<void>;
339
+ }
340
+ declare class AsyncQueueImpl implements AsyncQueue {
341
+ private readonly mode;
342
+ private readonly pendingEntries;
343
+ private readonly activeEntries;
344
+ private interruption?;
345
+ private isSerialOperationRunning;
346
+ constructor(mode?: AsyncQueueMode);
347
+ execute<Output>(operation: () => Promise<Output>): Promise<Output>;
348
+ cancelAll(cause?: unknown): void;
349
+ interrupt(handler: () => Promise<void>): Promise<void>;
350
+ private createEntry;
351
+ private startEntry;
352
+ private startNextSerialOperation;
353
+ private cancelEntry;
354
+ private resolveEntry;
355
+ private rejectEntry;
356
+ }
357
+ //#endregion
358
+ //#region src/networking/http-request-options.d.ts
359
+ interface HttpRequestOptions {
313
360
  /**
314
- * HTTP status code for the error response.
315
- * @example 404 // Not Found
316
- * @example 500 // Internal Server Error
361
+ * Whether browser credentials such as cookies should be included with the request,
362
+ * including cross-origin requests.
363
+ *
364
+ * @default true
317
365
  */
318
- statusCode: number;
366
+ readonly credentials?: boolean;
319
367
  /**
320
- * Machine‐readable error code for programmatic handling.
321
- * @example "UNAUTHORIZED"
322
- * @example "RESOURCE_NOT_FOUND"
368
+ * Headers included with the request.
369
+ *
370
+ * @default {}
323
371
  */
324
- code: string;
372
+ readonly headers?: Readonly<Record<string, string>>;
373
+ }
374
+ //#endregion
375
+ //#region src/networking/http-request.d.ts
376
+ interface HttpRequest<Client, Output> {
325
377
  /**
326
- * Human‐readable error description (localized or raw).
327
- * @example "Authentication required"
328
- * @example "User profile not found"
378
+ * Executes the request using the configured client.
329
379
  */
330
- message: string;
380
+ readonly execute: (client: Client) => Promise<Output>;
331
381
  /**
332
- * Optional structured details for debugging.
333
- * Each key maps to an array of error messages for that field.
382
+ * Options applied specifically to this request.
334
383
  *
335
- * @example
336
- * {
337
- * "email": ["must be a valid email address"],
338
- * "password": ["required", "must be at least 8 characters"]
339
- * }
384
+ * @default undefined
340
385
  */
341
- details?: Record<string, string[]>;
386
+ readonly options?: HttpRequestOptions;
342
387
  }
388
+ //#endregion
389
+ //#region src/networking/http-request-interceptor.d.ts
343
390
  /**
344
- * A specialized `Error` carrying an HTTP status code, machine‐readable code,
345
- * human‐readable message, and optional debug details.
346
- *
347
- * @example
348
- * // Basic usage
349
- * throw new HttpError({
350
- * statusCode: 404,
351
- * code: "NOT_FOUND",
352
- * message: "Resource not found"
353
- * });
354
- *
355
- * @example
356
- * // With structured debug details
357
- * throw new HttpError({
358
- * statusCode: 422,
359
- * code: "VALIDATION_ERROR",
360
- * message: "One or more fields are invalid",
361
- * details: {
362
- * "email": ["must be a valid email address"],
363
- * "password": ["required", "must be at least 8 characters"]
364
- * }
365
- * });
391
+ * Modifies HTTP request options before a request is executed.
366
392
  */
393
+ interface HttpRequestInterceptor {
394
+ /** Stable identity used to ignore duplicate interceptors. */
395
+ readonly identity: Identity;
396
+ /** Applies this interceptor to the current request options. */
397
+ intercept(options: HttpRequestOptions): HttpRequestOptions | Promise<HttpRequestOptions>;
398
+ }
399
+ declare class HttpRequestInterceptorPipeline {
400
+ private readonly interceptors;
401
+ constructor(interceptors?: readonly HttpRequestInterceptor[], onWarning?: (message: string) => void);
402
+ intercept(options: HttpRequestOptions): Promise<HttpRequestOptions>;
403
+ private resolveInterceptors;
404
+ }
405
+ //#endregion
406
+ //#region src/networking/http-error.d.ts
407
+ interface HttpErrorOptions {
408
+ /** HTTP status code returned by the remote system. */
409
+ readonly statusCode: number;
410
+ /** Machine-readable error code for programmatic handling. */
411
+ readonly code: string;
412
+ /** Human-readable error description. */
413
+ readonly message: string;
414
+ /**
415
+ * Structured error details.
416
+ *
417
+ * @default undefined
418
+ */
419
+ readonly details?: Readonly<Record<string, string[]>>;
420
+ /**
421
+ * Original transport error.
422
+ *
423
+ * @default undefined
424
+ */
425
+ readonly cause?: unknown;
426
+ }
367
427
  declare class HttpError extends Error {
368
428
  readonly statusCode: HttpErrorOptions['statusCode'];
369
429
  readonly code: HttpErrorOptions['code'];
@@ -371,53 +431,95 @@ declare class HttpError extends Error {
371
431
  constructor(options: HttpErrorOptions);
372
432
  }
373
433
  //#endregion
374
- //#region src/networking/cookie-interceptor.d.ts
375
- declare class CookieInterceptor implements RemoteRequestInterceptor {
376
- order: number;
377
- hash(): Identity;
378
- equals(other: unknown): boolean;
379
- intercept(config: RemoteRequestConfig): RemoteRequestConfig;
434
+ //#region src/networking/unauthorized.d.ts
435
+ interface UnauthorizedHandler {
436
+ handle(error: HttpError): Promise<void>;
437
+ }
438
+ interface UnauthorizedOptions {
439
+ /** HTTP status codes that trigger unauthorized handling. */
440
+ readonly statusCodes: readonly number[];
441
+ /** Whether unauthorized handling cancels all unresolved requests sharing the same HTTP client. */
442
+ readonly cancelAll: boolean;
443
+ /** Application-specific unauthorized handler. */
444
+ readonly handler: UnauthorizedHandler;
445
+ }
446
+ //#endregion
447
+ //#region src/networking/http-client.d.ts
448
+ interface HttpClientOptions {
449
+ /**
450
+ * Default options applied to every request before interceptors and request-specific options.
451
+ *
452
+ * @default {}
453
+ */
454
+ readonly requestOptions?: HttpRequestOptions;
455
+ /**
456
+ * Interceptors applied to every request.
457
+ *
458
+ * @default Empty `HttpRequestInterceptorPipeline`
459
+ */
460
+ readonly interceptorPipeline?: HttpRequestInterceptorPipeline;
461
+ /**
462
+ * Queue used to execute requests.
463
+ *
464
+ * @default `AsyncQueueImpl` in `parallel` mode
465
+ */
466
+ readonly asyncQueue?: AsyncQueue;
467
+ /**
468
+ * Unauthorized handling for secured requests.
469
+ *
470
+ * @default undefined
471
+ */
472
+ readonly unauthorized?: UnauthorizedOptions;
473
+ }
474
+ declare abstract class HttpClient<Client> {
475
+ private readonly requestOptions;
476
+ private readonly interceptorPipeline;
477
+ readonly asyncQueue: AsyncQueue;
478
+ readonly unauthorized?: UnauthorizedOptions;
479
+ constructor(options?: HttpClientOptions);
480
+ execute<Output>(request: HttpRequest<Client, Output>, options?: HttpRequestOptions): Promise<Output>;
481
+ /** Creates the concrete client for the resolved request options. */
482
+ protected abstract createClient(options: HttpRequestOptions): Client;
483
+ /** Maps a transport-specific failure to a BuildPlease error. */
484
+ protected handleError(error: unknown): Error;
485
+ private makeRequestOptions;
486
+ private mergeRequestOptions;
380
487
  }
381
488
  //#endregion
382
489
  //#region src/networking/remote-endpoint.d.ts
383
- interface RemoteEndpoint<Input, InputDto, Output, OutputDto> {
384
- makeRequest(input: InputDto, options?: RemoteRequestConfig): Promise<OutputDto>;
490
+ /**
491
+ * Defines conversion and request creation for a remote operation.
492
+ */
493
+ interface RemoteEndpoint<Input, InputDto, Output, OutputDto, Client> {
494
+ /** Converts operation input to the request DTO. */
385
495
  convertInput(input: Input): Promise<InputDto>;
496
+ /** Creates the HTTP request for the converted input. */
497
+ makeRequest(input: InputDto): HttpRequest<Client, OutputDto>;
498
+ /** Converts the response DTO to the operation output. */
386
499
  convertOutput(response: OutputDto): Promise<Output>;
387
500
  }
388
501
  //#endregion
389
502
  //#region src/networking/remote-resource.d.ts
390
- declare abstract class BaseRemoteResource<Input, Output, Endpoint extends RemoteEndpoint<Input, unknown, Output, unknown>> implements AsyncOperation<Input, Output> {
391
- protected readonly endpoint: Endpoint;
392
- protected readonly interceptors: InterceptorSet;
393
- constructor(endpoint: Endpoint);
394
- protected use(...items: RemoteRequestInterceptor[]): this;
395
- protected removeInterceptor(item: RemoteRequestInterceptor): this;
396
- protected clearInterceptors(): this;
397
- execute(input: Input, options?: RemoteRequestConfig): Promise<Output>;
398
- protected parseError(error: unknown): Error;
399
- protected convertOrThrow<T>(fn: () => Promise<T>): Promise<T>;
400
- private isStringArrayRecord;
401
- private buildHttpErrorOptions;
503
+ declare abstract class RemoteResource<Input, Output, Client> implements AsyncOperation<Input, Output, HttpRequestOptions> {
504
+ protected readonly endpoint: RemoteEndpoint<Input, unknown, Output, unknown, Client>;
505
+ protected readonly httpClient: HttpClient<Client>;
506
+ protected constructor(endpoint: RemoteEndpoint<Input, unknown, Output, unknown, Client>, httpClient: HttpClient<Client>);
507
+ execute(input: Input, options?: HttpRequestOptions): Promise<Output>;
508
+ private convertOrThrow;
402
509
  }
403
510
  //#endregion
404
- //#region src/networking/remote-request-config.d.ts
405
- type RemoteRequestConfig = AxiosRequestConfig;
406
- //#endregion
407
- //#region src/networking/remote-request-interceptor.d.ts
408
- interface RemoteRequestInterceptor extends Equatable, Hashable {
409
- order: number;
410
- intercept(config: RemoteRequestConfig): RemoteRequestConfig;
511
+ //#region src/networking/public-remote-resource.d.ts
512
+ declare class PublicRemoteResource<Input, Output, Client> extends RemoteResource<Input, Output, Client> {
513
+ constructor(endpoint: RemoteEndpoint<Input, unknown, Output, unknown, Client>, httpClient: HttpClient<Client>);
411
514
  }
412
- declare class InterceptorSet {
413
- private map;
414
- add(...items: RemoteRequestInterceptor[]): this;
415
- remove(item: RemoteRequestInterceptor): this;
416
- clear(): this;
417
- list(): RemoteRequestInterceptor[];
515
+ //#endregion
516
+ //#region src/networking/secured-remote-resource.d.ts
517
+ declare class SecuredRemoteResource<Input, Output, Client> extends RemoteResource<Input, Output, Client> {
518
+ constructor(endpoint: RemoteEndpoint<Input, unknown, Output, unknown, Client>, httpClient: HttpClient<Client>);
519
+ execute(input: Input, options?: HttpRequestOptions): Promise<Output>;
418
520
  }
419
521
  //#endregion
420
522
  //#region src/index.d.ts
421
523
  declare function webkitAssembly(): Assembly[];
422
524
  //#endregion
423
- export { BaseRemoteResource, CookieInterceptor, HttpError, HttpErrorOptions, InterceptorSet, RemoteEndpoint, RemoteRequestConfig, RemoteRequestInterceptor, TableDataModel, TablePaginationModel, WebKitL10nResource, WebKitSymbols, webkitAssembly };
525
+ export { AsyncQueue, AsyncQueueImpl, AsyncQueueMode, HttpClient, HttpClientOptions, HttpError, HttpErrorOptions, HttpRequest, HttpRequestInterceptor, HttpRequestInterceptorPipeline, HttpRequestOptions, PublicRemoteResource, RemoteEndpoint, RemoteResource, SecuredRemoteResource, TableDataModel, TablePaginationModel, UnauthorizedHandler, UnauthorizedOptions, WebKitL10nResource, WebKitSymbols, webkitAssembly };
@@ -1,6 +1,5 @@
1
1
  import "reflect-metadata";
2
- import { Assembly, AsyncOperation, Equatable, Hashable, Identity } from "@buildplease/core";
3
- import { AxiosRequestConfig } from "axios";
2
+ import { Assembly, AsyncOperation, Identity } from "@buildplease/core";
4
3
  export * from "@buildplease/core";
5
4
  //#region src/di/symbols.d.ts
6
5
  declare const WebKitSymbols: {
@@ -308,62 +307,123 @@ interface TablePaginationModel {
308
307
  pageSizeOptions?: number[];
309
308
  }
310
309
  //#endregion
311
- //#region src/networking/http-error.d.ts
312
- interface HttpErrorOptions {
310
+ //#region src/networking/async-queue.d.ts
311
+ /**
312
+ * Defines how queued operations are processed.
313
+ *
314
+ * `parallel` starts each operation immediately without waiting for previous operations to finish.
315
+ * `serial` starts an operation only after the previous operation has finished.
316
+ */
317
+ type AsyncQueueMode = 'parallel' | 'serial';
318
+ /**
319
+ * Executes and coordinates asynchronous operations.
320
+ */
321
+ interface AsyncQueue {
322
+ /**
323
+ * Executes an operation according to the configured queue mode.
324
+ * Operations submitted during an interruption are canceled without running.
325
+ */
326
+ execute<Output>(operation: () => Promise<Output>): Promise<Output>;
327
+ /**
328
+ * Cancels all unresolved operations. Pending serial operations are not started and results from
329
+ * already-running operations are ignored.
330
+ *
331
+ * @param cause Optional cancellation cause.
332
+ */
333
+ cancelAll(cause?: unknown): void;
334
+ /**
335
+ * Cancels all unresolved operations and executes one interruption handler.
336
+ * Concurrent interruptions wait for the same handler to complete.
337
+ */
338
+ interrupt(handler: () => Promise<void>): Promise<void>;
339
+ }
340
+ declare class AsyncQueueImpl implements AsyncQueue {
341
+ private readonly mode;
342
+ private readonly pendingEntries;
343
+ private readonly activeEntries;
344
+ private interruption?;
345
+ private isSerialOperationRunning;
346
+ constructor(mode?: AsyncQueueMode);
347
+ execute<Output>(operation: () => Promise<Output>): Promise<Output>;
348
+ cancelAll(cause?: unknown): void;
349
+ interrupt(handler: () => Promise<void>): Promise<void>;
350
+ private createEntry;
351
+ private startEntry;
352
+ private startNextSerialOperation;
353
+ private cancelEntry;
354
+ private resolveEntry;
355
+ private rejectEntry;
356
+ }
357
+ //#endregion
358
+ //#region src/networking/http-request-options.d.ts
359
+ interface HttpRequestOptions {
313
360
  /**
314
- * HTTP status code for the error response.
315
- * @example 404 // Not Found
316
- * @example 500 // Internal Server Error
361
+ * Whether browser credentials such as cookies should be included with the request,
362
+ * including cross-origin requests.
363
+ *
364
+ * @default true
317
365
  */
318
- statusCode: number;
366
+ readonly credentials?: boolean;
319
367
  /**
320
- * Machine‐readable error code for programmatic handling.
321
- * @example "UNAUTHORIZED"
322
- * @example "RESOURCE_NOT_FOUND"
368
+ * Headers included with the request.
369
+ *
370
+ * @default {}
323
371
  */
324
- code: string;
372
+ readonly headers?: Readonly<Record<string, string>>;
373
+ }
374
+ //#endregion
375
+ //#region src/networking/http-request.d.ts
376
+ interface HttpRequest<Client, Output> {
325
377
  /**
326
- * Human‐readable error description (localized or raw).
327
- * @example "Authentication required"
328
- * @example "User profile not found"
378
+ * Executes the request using the configured client.
329
379
  */
330
- message: string;
380
+ readonly execute: (client: Client) => Promise<Output>;
331
381
  /**
332
- * Optional structured details for debugging.
333
- * Each key maps to an array of error messages for that field.
382
+ * Options applied specifically to this request.
334
383
  *
335
- * @example
336
- * {
337
- * "email": ["must be a valid email address"],
338
- * "password": ["required", "must be at least 8 characters"]
339
- * }
384
+ * @default undefined
340
385
  */
341
- details?: Record<string, string[]>;
386
+ readonly options?: HttpRequestOptions;
342
387
  }
388
+ //#endregion
389
+ //#region src/networking/http-request-interceptor.d.ts
343
390
  /**
344
- * A specialized `Error` carrying an HTTP status code, machine‐readable code,
345
- * human‐readable message, and optional debug details.
346
- *
347
- * @example
348
- * // Basic usage
349
- * throw new HttpError({
350
- * statusCode: 404,
351
- * code: "NOT_FOUND",
352
- * message: "Resource not found"
353
- * });
354
- *
355
- * @example
356
- * // With structured debug details
357
- * throw new HttpError({
358
- * statusCode: 422,
359
- * code: "VALIDATION_ERROR",
360
- * message: "One or more fields are invalid",
361
- * details: {
362
- * "email": ["must be a valid email address"],
363
- * "password": ["required", "must be at least 8 characters"]
364
- * }
365
- * });
391
+ * Modifies HTTP request options before a request is executed.
366
392
  */
393
+ interface HttpRequestInterceptor {
394
+ /** Stable identity used to ignore duplicate interceptors. */
395
+ readonly identity: Identity;
396
+ /** Applies this interceptor to the current request options. */
397
+ intercept(options: HttpRequestOptions): HttpRequestOptions | Promise<HttpRequestOptions>;
398
+ }
399
+ declare class HttpRequestInterceptorPipeline {
400
+ private readonly interceptors;
401
+ constructor(interceptors?: readonly HttpRequestInterceptor[], onWarning?: (message: string) => void);
402
+ intercept(options: HttpRequestOptions): Promise<HttpRequestOptions>;
403
+ private resolveInterceptors;
404
+ }
405
+ //#endregion
406
+ //#region src/networking/http-error.d.ts
407
+ interface HttpErrorOptions {
408
+ /** HTTP status code returned by the remote system. */
409
+ readonly statusCode: number;
410
+ /** Machine-readable error code for programmatic handling. */
411
+ readonly code: string;
412
+ /** Human-readable error description. */
413
+ readonly message: string;
414
+ /**
415
+ * Structured error details.
416
+ *
417
+ * @default undefined
418
+ */
419
+ readonly details?: Readonly<Record<string, string[]>>;
420
+ /**
421
+ * Original transport error.
422
+ *
423
+ * @default undefined
424
+ */
425
+ readonly cause?: unknown;
426
+ }
367
427
  declare class HttpError extends Error {
368
428
  readonly statusCode: HttpErrorOptions['statusCode'];
369
429
  readonly code: HttpErrorOptions['code'];
@@ -371,53 +431,95 @@ declare class HttpError extends Error {
371
431
  constructor(options: HttpErrorOptions);
372
432
  }
373
433
  //#endregion
374
- //#region src/networking/cookie-interceptor.d.ts
375
- declare class CookieInterceptor implements RemoteRequestInterceptor {
376
- order: number;
377
- hash(): Identity;
378
- equals(other: unknown): boolean;
379
- intercept(config: RemoteRequestConfig): RemoteRequestConfig;
434
+ //#region src/networking/unauthorized.d.ts
435
+ interface UnauthorizedHandler {
436
+ handle(error: HttpError): Promise<void>;
437
+ }
438
+ interface UnauthorizedOptions {
439
+ /** HTTP status codes that trigger unauthorized handling. */
440
+ readonly statusCodes: readonly number[];
441
+ /** Whether unauthorized handling cancels all unresolved requests sharing the same HTTP client. */
442
+ readonly cancelAll: boolean;
443
+ /** Application-specific unauthorized handler. */
444
+ readonly handler: UnauthorizedHandler;
445
+ }
446
+ //#endregion
447
+ //#region src/networking/http-client.d.ts
448
+ interface HttpClientOptions {
449
+ /**
450
+ * Default options applied to every request before interceptors and request-specific options.
451
+ *
452
+ * @default {}
453
+ */
454
+ readonly requestOptions?: HttpRequestOptions;
455
+ /**
456
+ * Interceptors applied to every request.
457
+ *
458
+ * @default Empty `HttpRequestInterceptorPipeline`
459
+ */
460
+ readonly interceptorPipeline?: HttpRequestInterceptorPipeline;
461
+ /**
462
+ * Queue used to execute requests.
463
+ *
464
+ * @default `AsyncQueueImpl` in `parallel` mode
465
+ */
466
+ readonly asyncQueue?: AsyncQueue;
467
+ /**
468
+ * Unauthorized handling for secured requests.
469
+ *
470
+ * @default undefined
471
+ */
472
+ readonly unauthorized?: UnauthorizedOptions;
473
+ }
474
+ declare abstract class HttpClient<Client> {
475
+ private readonly requestOptions;
476
+ private readonly interceptorPipeline;
477
+ readonly asyncQueue: AsyncQueue;
478
+ readonly unauthorized?: UnauthorizedOptions;
479
+ constructor(options?: HttpClientOptions);
480
+ execute<Output>(request: HttpRequest<Client, Output>, options?: HttpRequestOptions): Promise<Output>;
481
+ /** Creates the concrete client for the resolved request options. */
482
+ protected abstract createClient(options: HttpRequestOptions): Client;
483
+ /** Maps a transport-specific failure to a BuildPlease error. */
484
+ protected handleError(error: unknown): Error;
485
+ private makeRequestOptions;
486
+ private mergeRequestOptions;
380
487
  }
381
488
  //#endregion
382
489
  //#region src/networking/remote-endpoint.d.ts
383
- interface RemoteEndpoint<Input, InputDto, Output, OutputDto> {
384
- makeRequest(input: InputDto, options?: RemoteRequestConfig): Promise<OutputDto>;
490
+ /**
491
+ * Defines conversion and request creation for a remote operation.
492
+ */
493
+ interface RemoteEndpoint<Input, InputDto, Output, OutputDto, Client> {
494
+ /** Converts operation input to the request DTO. */
385
495
  convertInput(input: Input): Promise<InputDto>;
496
+ /** Creates the HTTP request for the converted input. */
497
+ makeRequest(input: InputDto): HttpRequest<Client, OutputDto>;
498
+ /** Converts the response DTO to the operation output. */
386
499
  convertOutput(response: OutputDto): Promise<Output>;
387
500
  }
388
501
  //#endregion
389
502
  //#region src/networking/remote-resource.d.ts
390
- declare abstract class BaseRemoteResource<Input, Output, Endpoint extends RemoteEndpoint<Input, unknown, Output, unknown>> implements AsyncOperation<Input, Output> {
391
- protected readonly endpoint: Endpoint;
392
- protected readonly interceptors: InterceptorSet;
393
- constructor(endpoint: Endpoint);
394
- protected use(...items: RemoteRequestInterceptor[]): this;
395
- protected removeInterceptor(item: RemoteRequestInterceptor): this;
396
- protected clearInterceptors(): this;
397
- execute(input: Input, options?: RemoteRequestConfig): Promise<Output>;
398
- protected parseError(error: unknown): Error;
399
- protected convertOrThrow<T>(fn: () => Promise<T>): Promise<T>;
400
- private isStringArrayRecord;
401
- private buildHttpErrorOptions;
503
+ declare abstract class RemoteResource<Input, Output, Client> implements AsyncOperation<Input, Output, HttpRequestOptions> {
504
+ protected readonly endpoint: RemoteEndpoint<Input, unknown, Output, unknown, Client>;
505
+ protected readonly httpClient: HttpClient<Client>;
506
+ protected constructor(endpoint: RemoteEndpoint<Input, unknown, Output, unknown, Client>, httpClient: HttpClient<Client>);
507
+ execute(input: Input, options?: HttpRequestOptions): Promise<Output>;
508
+ private convertOrThrow;
402
509
  }
403
510
  //#endregion
404
- //#region src/networking/remote-request-config.d.ts
405
- type RemoteRequestConfig = AxiosRequestConfig;
406
- //#endregion
407
- //#region src/networking/remote-request-interceptor.d.ts
408
- interface RemoteRequestInterceptor extends Equatable, Hashable {
409
- order: number;
410
- intercept(config: RemoteRequestConfig): RemoteRequestConfig;
511
+ //#region src/networking/public-remote-resource.d.ts
512
+ declare class PublicRemoteResource<Input, Output, Client> extends RemoteResource<Input, Output, Client> {
513
+ constructor(endpoint: RemoteEndpoint<Input, unknown, Output, unknown, Client>, httpClient: HttpClient<Client>);
411
514
  }
412
- declare class InterceptorSet {
413
- private map;
414
- add(...items: RemoteRequestInterceptor[]): this;
415
- remove(item: RemoteRequestInterceptor): this;
416
- clear(): this;
417
- list(): RemoteRequestInterceptor[];
515
+ //#endregion
516
+ //#region src/networking/secured-remote-resource.d.ts
517
+ declare class SecuredRemoteResource<Input, Output, Client> extends RemoteResource<Input, Output, Client> {
518
+ constructor(endpoint: RemoteEndpoint<Input, unknown, Output, unknown, Client>, httpClient: HttpClient<Client>);
519
+ execute(input: Input, options?: HttpRequestOptions): Promise<Output>;
418
520
  }
419
521
  //#endregion
420
522
  //#region src/index.d.ts
421
523
  declare function webkitAssembly(): Assembly[];
422
524
  //#endregion
423
- export { BaseRemoteResource, CookieInterceptor, HttpError, HttpErrorOptions, InterceptorSet, RemoteEndpoint, RemoteRequestConfig, RemoteRequestInterceptor, TableDataModel, TablePaginationModel, WebKitL10nResource, WebKitSymbols, webkitAssembly };
525
+ export { AsyncQueue, AsyncQueueImpl, AsyncQueueMode, HttpClient, HttpClientOptions, HttpError, HttpErrorOptions, HttpRequest, HttpRequestInterceptor, HttpRequestInterceptorPipeline, HttpRequestOptions, PublicRemoteResource, RemoteEndpoint, RemoteResource, SecuredRemoteResource, TableDataModel, TablePaginationModel, UnauthorizedHandler, UnauthorizedOptions, WebKitL10nResource, WebKitSymbols, webkitAssembly };
package/dist/src/index.js CHANGED
@@ -1 +1 @@
1
- import"reflect-metadata";import{CanceledError as e,ConversionError as t,CoreL10nResource as n,NetworkError as r,TimeoutError as i,UnknownError as a,coreAssembly as o,ignoreError as s,isDefinedAndNotNull as c,isNonEmptyString as l,isPlainObject as u}from"@buildplease/core";import d from"axios";import{injectable as f,unmanaged as p}from"inversify";export*from"@buildplease/core";function m(){return[]}const h={name:`buildplease`,displayName:`BuildPlease`,scope:`@buildplease`};`${h.name}`;const g={DI:{}},_=n;var v=class extends Error{statusCode;code;details;constructor(e){super(e.message),this.name=`HttpError`,this.statusCode=e.statusCode,this.code=e.code,this.details=e.details}},y=class e{order=-10;hash(){return Symbol.for(`${h.scope}.webkit.networking.interceptor.cookie`)}equals(t){return t instanceof e}intercept(e){return{...e,withCredentials:!0}}};function b(e,t){if(typeof Reflect==`object`&&typeof Reflect.metadata==`function`)return Reflect.metadata(e,t)}function x(e,t){return function(n,r){t(n,r,e)}}function S(e,t,n,r){var i=arguments.length,a=i<3?t:r===null?r=Object.getOwnPropertyDescriptor(t,n):r,o;if(typeof Reflect==`object`&&typeof Reflect.decorate==`function`)a=Reflect.decorate(e,t,n,r);else for(var s=e.length-1;s>=0;s--)(o=e[s])&&(a=(i<3?o(a):i>3?o(t,n,a):o(t,n))||a);return i>3&&a&&Object.defineProperty(t,n,a),a}const C=`Unknown Error`;let w=class{endpoint;interceptors=new T;constructor(e){this.endpoint=e,this.use(new y)}use(...e){return this.interceptors.add(...e),this}removeInterceptor(e){return this.interceptors.remove(e),this}clearInterceptors(){return this.interceptors.clear(),this}async execute(e,t){try{let n=await this.convertOrThrow(()=>this.endpoint.convertInput(e)),r={...t};for(let e of this.interceptors.list())r=e.intercept(r);let i=await this.endpoint.makeRequest(n,r);return await this.convertOrThrow(()=>this.endpoint.convertOutput(i))}catch(e){throw this.parseError(e)}}parseError(n){if(n instanceof v||n instanceof i||n instanceof r||n instanceof e||n instanceof t||n instanceof a)return n;if(d.isCancel?.(n)||d.isAxiosError(n)&&(n.code===`ERR_CANCELED`||n.message===`canceled`))return new e({cause:n});if(d.isAxiosError(n)&&n.code===`ECONNABORTED`)return new i({cause:n});if(d.isAxiosError(n)&&!n.response)return new r({message:n.message,cause:n});if(d.isAxiosError(n)&&n.response){let{status:e,data:t}=n.response,r=t;typeof r==`string`&&(r=s(()=>JSON.parse(r)).orDefault(r));let i=this.isStringArrayRecord(r.details)?r.details:void 0;return new v(this.buildHttpErrorOptions(e,r,i))}let o=n instanceof Error?n.message:C;return new a({message:o,cause:n})}async convertOrThrow(e){try{return await e()}catch(e){throw new t({cause:e})}}isStringArrayRecord(e){return!c(e)||!u(e)?!1:Object.values(e).every(e=>Array.isArray(e)&&e.every(e=>typeof e==`string`))}buildHttpErrorOptions(e,t,n){return{statusCode:e,code:l(t?.code)?t.code:`UNKNOWN_ERROR`,message:l(t?.message)?t.message:C,details:n}}};w=S([f(),x(0,p()),b(`design:paramtypes`,[Object])],w);var T=class{map=new Map;add(...e){for(let t of e){let e=t.hash(),n=this.map.get(e);n&&n.equals(t)||this.map.set(e,t)}return this}remove(e){return this.map.delete(e.hash()),this}clear(){return this.map.clear(),this}list(){return[...this.map.values()].sort((e,t)=>e.order-t.order)}};function E(){let e=o(),t=m();return[...e,...t]}export{w as BaseRemoteResource,y as CookieInterceptor,v as HttpError,T as InterceptorSet,_ as WebKitL10nResource,g as WebKitSymbols,E as webkitAssembly};
1
+ import"reflect-metadata";import{CanceledError as e,ConversionError as t,CoreL10nResource as n,NetworkError as r,TimeoutError as i,UnknownError as a,coreAssembly as o}from"@buildplease/core";import{injectable as s,unmanaged as c}from"inversify";export*from"@buildplease/core";function l(){return[]}`${{name:`buildplease`,displayName:`BuildPlease`,scope:`@buildplease`}.name}`;const u={DI:{}},d=n;var f=class{mode;pendingEntries=[];activeEntries=new Set;interruption;isSerialOperationRunning=!1;constructor(e=`parallel`){this.mode=e}execute(t){if(this.interruption)return Promise.reject(new e);let n=this.createEntry(t);return this.mode===`serial`?(this.pendingEntries.push(n),this.startNextSerialOperation()):this.startEntry(n),n.promise}cancelAll(e){let t=this.pendingEntries.splice(0);for(let n of t)this.cancelEntry(n,e);for(let t of this.activeEntries)this.cancelEntry(t,e)}async interrupt(e){if(!this.interruption){let t=Promise.resolve().then(e).finally(()=>{this.interruption===t&&(this.interruption=void 0,this.startNextSerialOperation())});this.interruption=t,this.cancelAll()}await this.interruption}createEntry(e){let t,n;return{operation:e,promise:new Promise((e,r)=>{t=e,n=r}),resolve:e=>t?.(e),reject:e=>n?.(e),canceled:!1,settled:!1}}startEntry(e){if(e.canceled||this.interruption){this.cancelEntry(e);return}this.activeEntries.add(e),this.mode===`serial`&&(this.isSerialOperationRunning=!0),Promise.resolve().then(e.operation).then(t=>{e.canceled||this.resolveEntry(e,t)},t=>{e.canceled||this.rejectEntry(e,t)}).finally(()=>{this.activeEntries.delete(e),this.mode===`serial`&&(this.isSerialOperationRunning=!1,this.startNextSerialOperation())})}startNextSerialOperation(){if(this.mode!==`serial`||this.isSerialOperationRunning||this.interruption)return;let e=this.pendingEntries.shift();e&&this.startEntry(e)}cancelEntry(t,n){t.canceled||(t.canceled=!0,t.settled||this.rejectEntry(t,new e({cause:n})))}resolveEntry(e,t){e.settled||(e.settled=!0,e.resolve(t))}rejectEntry(e,t){e.settled||(e.settled=!0,e.reject(t))}},p=class extends Error{statusCode;code;details;constructor(e){super(e.message),this.name=`HttpError`,this.statusCode=e.statusCode,this.code=e.code,this.details=e.details,e.cause!==void 0&&(this.cause=e.cause)}},m=class{interceptors;constructor(e=[],t){this.interceptors=this.resolveInterceptors(e,t)}async intercept(e){let t=e;for(let e of this.interceptors)t=await e.intercept(t);return t}resolveInterceptors(e,t){let n=new Set,r=[];for(let i of e){if(n.has(i.identity)){t?.(`Duplicate HTTP request interceptor ignored: ${String(i.identity)}`);continue}n.add(i.identity),r.push(i)}return Object.freeze(r)}};const h={credentials:!0,headers:{}};var g=class{requestOptions;interceptorPipeline;asyncQueue;unauthorized;constructor(e={}){this.requestOptions=e.requestOptions??{},this.interceptorPipeline=e.interceptorPipeline??new m,this.asyncQueue=e.asyncQueue??new f,this.unauthorized=e.unauthorized}execute(e,t){return this.asyncQueue.execute(async()=>{let n=await this.makeRequestOptions(e,t);try{let t=this.createClient(n);return await e.execute(t)}catch(e){throw this.handleError(e)}})}handleError(t){return t instanceof p||t instanceof r||t instanceof i||t instanceof e||t instanceof a?t:new a({message:t instanceof Error?t.message:void 0,cause:t})}async makeRequestOptions(e,t){let n=this.mergeRequestOptions(h,this.requestOptions);return n=await this.interceptorPipeline.intercept(n),n=this.mergeRequestOptions(n,e.options),n=this.mergeRequestOptions(n,t),n}mergeRequestOptions(e,t){return t?{credentials:t.credentials??e.credentials,headers:{...e.headers,...t.headers}}:e}};function _(e,t){if(typeof Reflect==`object`&&typeof Reflect.metadata==`function`)return Reflect.metadata(e,t)}function v(e,t){return function(n,r){t(n,r,e)}}function y(e,t,n,r){var i=arguments.length,a=i<3?t:r===null?r=Object.getOwnPropertyDescriptor(t,n):r,o;if(typeof Reflect==`object`&&typeof Reflect.decorate==`function`)a=Reflect.decorate(e,t,n,r);else for(var s=e.length-1;s>=0;s--)(o=e[s])&&(a=(i<3?o(a):i>3?o(t,n,a):o(t,n))||a);return i>3&&a&&Object.defineProperty(t,n,a),a}let b=class{endpoint;httpClient;constructor(e,t){this.endpoint=e,this.httpClient=t}async execute(e,t){let n=await this.convertOrThrow(()=>this.endpoint.convertInput(e)),r=this.endpoint.makeRequest(n),i=await this.httpClient.execute(r,t);return await this.convertOrThrow(()=>this.endpoint.convertOutput(i))}async convertOrThrow(e){try{return await e()}catch(e){throw new t({cause:e})}}};b=y([s(),v(0,c()),v(1,c()),_(`design:paramtypes`,[Object,Object])],b);let x=class extends b{constructor(e,t){super(e,t)}};x=y([s(),_(`design:paramtypes`,[Object,Object])],x);let S=class extends b{constructor(e,t){super(e,t)}async execute(t,n){try{return await super.execute(t,n)}catch(t){if(!(t instanceof p))throw t;let n=this.httpClient.unauthorized;throw!n||!n.statusCodes.includes(t.statusCode)?t:n.cancelAll?(await this.httpClient.asyncQueue.interrupt(()=>n.handler.handle(t)),new e({cause:t})):(await n.handler.handle(t),t)}}};S=y([s(),_(`design:paramtypes`,[Object,Object])],S);function C(){let e=o(),t=l();return[...e,...t]}export{f as AsyncQueueImpl,g as HttpClient,p as HttpError,m as HttpRequestInterceptorPipeline,x as PublicRemoteResource,b as RemoteResource,S as SecuredRemoteResource,d as WebKitL10nResource,u as WebKitSymbols,C as webkitAssembly};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buildplease/webkit",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "keywords": [],
5
5
  "repository": {
6
6
  "type": "git",
@@ -37,8 +37,7 @@
37
37
  "resources"
38
38
  ],
39
39
  "dependencies": {
40
- "axios": "1.19.0",
41
- "@buildplease/core": "1.0.1"
40
+ "@buildplease/core": "1.0.2"
42
41
  },
43
42
  "devDependencies": {
44
43
  "@buildplease/identity": "1.0.0"