@webpieces/http-client-browser 0.0.0-dev
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 +25 -0
- package/package.json +28 -0
- package/src/BrowserProxyClient.d.ts +28 -0
- package/src/BrowserProxyClient.js +48 -0
- package/src/BrowserProxyClient.js.map +1 -0
- package/src/ClientConfig.d.ts +22 -0
- package/src/ClientConfig.js +28 -0
- package/src/ClientConfig.js.map +1 -0
- package/src/ClientHttpBrowserFactory.d.ts +42 -0
- package/src/ClientHttpBrowserFactory.js +59 -0
- package/src/ClientHttpBrowserFactory.js.map +1 -0
- package/src/MutableContextStore.d.ts +32 -0
- package/src/MutableContextStore.js +44 -0
- package/src/MutableContextStore.js.map +1 -0
- package/src/index.d.ts +34 -0
- package/src/index.js +63 -0
- package/src/index.js.map +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# @webpieces/http-client-browser
|
|
2
|
+
|
|
3
|
+
The browser HTTP client. The client and the server share ONE API contract; calling a method on the
|
|
4
|
+
client makes the HTTP request the server's controller answers.
|
|
5
|
+
|
|
6
|
+
DI-free on purpose — this may be bundled by React or Angular, so it ships no inversify and no
|
|
7
|
+
`@webpieces/core-context`. Browsers have no ambient request scope, so the app holds a
|
|
8
|
+
`MutableContextStore` and sets values as they become known; every outbound call transfers them.
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
HeaderRegistry.configure(AppHeaders.getAllHeaders(), CompanyHeaders.getAllHeaders(), true);
|
|
12
|
+
|
|
13
|
+
const store = new MutableContextStore();
|
|
14
|
+
const factory = new ClientHttpBrowserFactory(store);
|
|
15
|
+
const saveApi = factory.createClient(SaveApi, new ClientConfig(env.apiBaseUrl));
|
|
16
|
+
|
|
17
|
+
const res = await saveApi.save({ query: 'test' }); // type-safe
|
|
18
|
+
|
|
19
|
+
// later, after login — every subsequent call carries these
|
|
20
|
+
store.set(WebpiecesCoreHeaders.AUTHORIZATION, token);
|
|
21
|
+
store.set(CompanyHeaders.TENANT_ID, tenantId);
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
A browser cannot hold service credentials, so a contract with an `@AuthOidc` endpoint fails fast at
|
|
25
|
+
`createClient`. The server twin is [@webpieces/http-client-node](../http-client-node).
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@webpieces/http-client-browser",
|
|
3
|
+
"version": "0.0.0-dev",
|
|
4
|
+
"description": "Browser HTTP client for webpieces: DI-free (React or Angular), app-managed context store, no AsyncLocalStorage",
|
|
5
|
+
"type": "commonjs",
|
|
6
|
+
"main": "./src/index.js",
|
|
7
|
+
"types": "./src/index.d.ts",
|
|
8
|
+
"author": "Dean Hiller",
|
|
9
|
+
"license": "Apache-2.0",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/deanhiller/webpieces-ts.git",
|
|
13
|
+
"directory": "packages/http/http-client-browser"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"webpieces",
|
|
17
|
+
"http",
|
|
18
|
+
"client",
|
|
19
|
+
"browser"
|
|
20
|
+
],
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@webpieces/core-util": "workspace:*",
|
|
26
|
+
"@webpieces/http-client-core": "workspace:*"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { AuthMeta, ContextMgr } from '@webpieces/core-util';
|
|
2
|
+
import { ApiPrototype, ProxyClient } from '@webpieces/http-client-core';
|
|
3
|
+
import { ClientConfig } from './ClientConfig';
|
|
4
|
+
/**
|
|
5
|
+
* The browser {@link ProxyClient}. Reads context from the app-held store (via {@link ContextMgr}),
|
|
6
|
+
* because a browser has no ambient request scope.
|
|
7
|
+
*
|
|
8
|
+
* It attaches NO outbound credential and does NO recording — both inherit the base's no-ops. A
|
|
9
|
+
* browser cannot mint an OIDC token and must never hold a shared secret; the user's JWT travels as
|
|
10
|
+
* an ordinary transferred context key, set on the store at login.
|
|
11
|
+
*
|
|
12
|
+
* This is the ONLY class in webpieces that names ContextMgr.
|
|
13
|
+
*/
|
|
14
|
+
export declare class BrowserProxyClient extends ProxyClient {
|
|
15
|
+
private readonly contextMgr;
|
|
16
|
+
private config;
|
|
17
|
+
constructor(contextMgr: ContextMgr);
|
|
18
|
+
/** Bind this client to one API contract + base URL. */
|
|
19
|
+
init(apiPrototype: ApiPrototype<object>, config: ClientConfig): void;
|
|
20
|
+
protected resolveBaseUrl(): Promise<string>;
|
|
21
|
+
protected outboundHeaders(): Map<string, string>;
|
|
22
|
+
/**
|
|
23
|
+
* Reject a contract this browser cannot satisfy, at bind time rather than on the first call.
|
|
24
|
+
* Both service-to-service modes need credentials only a server has: @AuthOidc needs a runtime
|
|
25
|
+
* service account to mint a token, @AuthSharedSecret needs a secret no browser may ship.
|
|
26
|
+
*/
|
|
27
|
+
protected assertEndpointSupported(authMeta: AuthMeta | undefined, methodName: string): void;
|
|
28
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BrowserProxyClient = void 0;
|
|
4
|
+
const http_client_core_1 = require("@webpieces/http-client-core");
|
|
5
|
+
/**
|
|
6
|
+
* The browser {@link ProxyClient}. Reads context from the app-held store (via {@link ContextMgr}),
|
|
7
|
+
* because a browser has no ambient request scope.
|
|
8
|
+
*
|
|
9
|
+
* It attaches NO outbound credential and does NO recording — both inherit the base's no-ops. A
|
|
10
|
+
* browser cannot mint an OIDC token and must never hold a shared secret; the user's JWT travels as
|
|
11
|
+
* an ordinary transferred context key, set on the store at login.
|
|
12
|
+
*
|
|
13
|
+
* This is the ONLY class in webpieces that names ContextMgr.
|
|
14
|
+
*/
|
|
15
|
+
class BrowserProxyClient extends http_client_core_1.ProxyClient {
|
|
16
|
+
contextMgr;
|
|
17
|
+
config;
|
|
18
|
+
constructor(contextMgr) {
|
|
19
|
+
super();
|
|
20
|
+
this.contextMgr = contextMgr;
|
|
21
|
+
}
|
|
22
|
+
/** Bind this client to one API contract + base URL. */
|
|
23
|
+
init(apiPrototype, config) {
|
|
24
|
+
this.config = config;
|
|
25
|
+
this.initRoutes(apiPrototype);
|
|
26
|
+
}
|
|
27
|
+
resolveBaseUrl() {
|
|
28
|
+
return Promise.resolve(this.config.baseUrl);
|
|
29
|
+
}
|
|
30
|
+
outboundHeaders() {
|
|
31
|
+
return this.contextMgr.buildOutboundHeaders();
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Reject a contract this browser cannot satisfy, at bind time rather than on the first call.
|
|
35
|
+
* Both service-to-service modes need credentials only a server has: @AuthOidc needs a runtime
|
|
36
|
+
* service account to mint a token, @AuthSharedSecret needs a secret no browser may ship.
|
|
37
|
+
*/
|
|
38
|
+
assertEndpointSupported(authMeta, methodName) {
|
|
39
|
+
const kind = authMeta?.mode.kind;
|
|
40
|
+
if (kind !== 'oidc' && kind !== 'shared-secret') {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
throw new Error(`Endpoint ${methodName} is @${kind === 'oidc' ? 'AuthOidc' : 'AuthSharedSecret'} — a browser cannot ` +
|
|
44
|
+
`hold service credentials. Call it server-side with ClientHttpFactory from @webpieces/http-client-node.`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
exports.BrowserProxyClient = BrowserProxyClient;
|
|
48
|
+
//# sourceMappingURL=BrowserProxyClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BrowserProxyClient.js","sourceRoot":"","sources":["../../../../../packages/http/http-client-browser/src/BrowserProxyClient.ts"],"names":[],"mappings":";;;AACA,kEAAwE;AAGxE;;;;;;;;;GASG;AACH,MAAa,kBAAmB,SAAQ,8BAAW;IAGlB;IAFrB,MAAM,CAAgB;IAE9B,YAA6B,UAAsB;QAC/C,KAAK,EAAE,CAAC;QADiB,eAAU,GAAV,UAAU,CAAY;IAEnD,CAAC;IAED,uDAAuD;IACvD,IAAI,CAAC,YAAkC,EAAE,MAAoB;QACzD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;IAClC,CAAC;IAEkB,cAAc;QAC7B,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAChD,CAAC;IAEkB,eAAe;QAC9B,OAAO,IAAI,CAAC,UAAU,CAAC,oBAAoB,EAAE,CAAC;IAClD,CAAC;IAED;;;;OAIG;IACgB,uBAAuB,CAAC,QAA8B,EAAE,UAAkB;QACzF,MAAM,IAAI,GAAG,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC;QACjC,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,eAAe,EAAE,CAAC;YAC9C,OAAO;QACX,CAAC;QACD,MAAM,IAAI,KAAK,CACX,YAAY,UAAU,QAAQ,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,kBAAkB,sBAAsB;YACrG,wGAAwG,CAC3G,CAAC;IACN,CAAC;CACJ;AApCD,gDAoCC","sourcesContent":["import { AuthMeta, ContextMgr } from '@webpieces/core-util';\nimport { ApiPrototype, ProxyClient } from '@webpieces/http-client-core';\nimport { ClientConfig } from './ClientConfig';\n\n/**\n * The browser {@link ProxyClient}. Reads context from the app-held store (via {@link ContextMgr}),\n * because a browser has no ambient request scope.\n *\n * It attaches NO outbound credential and does NO recording — both inherit the base's no-ops. A\n * browser cannot mint an OIDC token and must never hold a shared secret; the user's JWT travels as\n * an ordinary transferred context key, set on the store at login.\n *\n * This is the ONLY class in webpieces that names ContextMgr.\n */\nexport class BrowserProxyClient extends ProxyClient {\n private config!: ClientConfig;\n\n constructor(private readonly contextMgr: ContextMgr) {\n super();\n }\n\n /** Bind this client to one API contract + base URL. */\n init(apiPrototype: ApiPrototype<object>, config: ClientConfig): void {\n this.config = config;\n this.initRoutes(apiPrototype);\n }\n\n protected override resolveBaseUrl(): Promise<string> {\n return Promise.resolve(this.config.baseUrl);\n }\n\n protected override outboundHeaders(): Map<string, string> {\n return this.contextMgr.buildOutboundHeaders();\n }\n\n /**\n * Reject a contract this browser cannot satisfy, at bind time rather than on the first call.\n * Both service-to-service modes need credentials only a server has: @AuthOidc needs a runtime\n * service account to mint a token, @AuthSharedSecret needs a secret no browser may ship.\n */\n protected override assertEndpointSupported(authMeta: AuthMeta | undefined, methodName: string): void {\n const kind = authMeta?.mode.kind;\n if (kind !== 'oidc' && kind !== 'shared-secret') {\n return;\n }\n throw new Error(\n `Endpoint ${methodName} is @${kind === 'oidc' ? 'AuthOidc' : 'AuthSharedSecret'} — a browser cannot ` +\n `hold service credentials. Call it server-side with ClientHttpFactory from @webpieces/http-client-node.`,\n );\n }\n}\n"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-client STATE for a browser HTTP client — nothing else. A plain class; it extends nothing and
|
|
3
|
+
* is unrelated to the server package's ClientConfig.
|
|
4
|
+
*
|
|
5
|
+
* A browser is simply handed the base URL of the API it calls (usually from an environment config),
|
|
6
|
+
* because it has no container metadata to derive one from. That is the only difference from
|
|
7
|
+
* http-client-node's ClientConfig, which names a Cloud Run service and resolves the URL from it.
|
|
8
|
+
*
|
|
9
|
+
* The context store is NOT config: it is a dependency of {@link ClientHttpBrowserFactory}, shared
|
|
10
|
+
* by every client it builds.
|
|
11
|
+
*/
|
|
12
|
+
export declare class ClientConfig {
|
|
13
|
+
/** Base URL for all requests (e.g., 'http://localhost:3000') */
|
|
14
|
+
readonly baseUrl: string;
|
|
15
|
+
/** The callee's name for logging. Defaults to the baseUrl. */
|
|
16
|
+
readonly svcName: string;
|
|
17
|
+
constructor(
|
|
18
|
+
/** Base URL for all requests (e.g., 'http://localhost:3000') */
|
|
19
|
+
baseUrl: string,
|
|
20
|
+
/** The callee's name for logging. Defaults to the baseUrl. */
|
|
21
|
+
svcName?: string);
|
|
22
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ClientConfig = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Per-client STATE for a browser HTTP client — nothing else. A plain class; it extends nothing and
|
|
6
|
+
* is unrelated to the server package's ClientConfig.
|
|
7
|
+
*
|
|
8
|
+
* A browser is simply handed the base URL of the API it calls (usually from an environment config),
|
|
9
|
+
* because it has no container metadata to derive one from. That is the only difference from
|
|
10
|
+
* http-client-node's ClientConfig, which names a Cloud Run service and resolves the URL from it.
|
|
11
|
+
*
|
|
12
|
+
* The context store is NOT config: it is a dependency of {@link ClientHttpBrowserFactory}, shared
|
|
13
|
+
* by every client it builds.
|
|
14
|
+
*/
|
|
15
|
+
class ClientConfig {
|
|
16
|
+
baseUrl;
|
|
17
|
+
svcName;
|
|
18
|
+
constructor(
|
|
19
|
+
/** Base URL for all requests (e.g., 'http://localhost:3000') */
|
|
20
|
+
baseUrl,
|
|
21
|
+
/** The callee's name for logging. Defaults to the baseUrl. */
|
|
22
|
+
svcName = baseUrl) {
|
|
23
|
+
this.baseUrl = baseUrl;
|
|
24
|
+
this.svcName = svcName;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.ClientConfig = ClientConfig;
|
|
28
|
+
//# sourceMappingURL=ClientConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClientConfig.js","sourceRoot":"","sources":["../../../../../packages/http/http-client-browser/src/ClientConfig.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;GAUG;AACH,MAAa,YAAY;IAGD;IAGA;IALpB;IACI,gEAAgE;IAChD,OAAe;IAE/B,8DAA8D;IAC9C,UAAkB,OAAO;QAHzB,YAAO,GAAP,OAAO,CAAQ;QAGf,YAAO,GAAP,OAAO,CAAkB;IAC1C,CAAC;CACP;AARD,oCAQC","sourcesContent":["/**\n * Per-client STATE for a browser HTTP client — nothing else. A plain class; it extends nothing and\n * is unrelated to the server package's ClientConfig.\n *\n * A browser is simply handed the base URL of the API it calls (usually from an environment config),\n * because it has no container metadata to derive one from. That is the only difference from\n * http-client-node's ClientConfig, which names a Cloud Run service and resolves the URL from it.\n *\n * The context store is NOT config: it is a dependency of {@link ClientHttpBrowserFactory}, shared\n * by every client it builds.\n */\nexport class ClientConfig {\n constructor(\n /** Base URL for all requests (e.g., 'http://localhost:3000') */\n public readonly baseUrl: string,\n\n /** The callee's name for logging. Defaults to the baseUrl. */\n public readonly svcName: string = baseUrl,\n ) {}\n}\n"]}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { ApiPrototype } from '@webpieces/http-client-core';
|
|
2
|
+
import { ClientConfig } from './ClientConfig';
|
|
3
|
+
import { MutableContextStore } from './MutableContextStore';
|
|
4
|
+
/**
|
|
5
|
+
* ClientHttpBrowserFactory - builds type-safe HTTP clients for a BROWSER from API prototypes
|
|
6
|
+
* carrying @ApiPath/@Endpoint decorators.
|
|
7
|
+
*
|
|
8
|
+
* Deliberately a plain class with NO decorators and NO inversify: this package may be bundled by
|
|
9
|
+
* React just as easily as by Angular, and neither should be forced to adopt a Node DI container.
|
|
10
|
+
* The app provides it through whatever DI it already has — Angular's `useFactory`, a React context,
|
|
11
|
+
* or a module-level `const`.
|
|
12
|
+
*
|
|
13
|
+
* The factory holds the ONE collaborator every browser client shares (the app's
|
|
14
|
+
* {@link MutableContextStore}); each {@link ClientConfig} holds only that one client's base URL.
|
|
15
|
+
*
|
|
16
|
+
* ```typescript
|
|
17
|
+
* // once, at startup (after HeaderRegistry.configure(...)):
|
|
18
|
+
* const store = new MutableContextStore();
|
|
19
|
+
* const factory = new ClientHttpBrowserFactory(store);
|
|
20
|
+
*
|
|
21
|
+
* const saveApi = factory.createClient(SaveApi, new ClientConfig(env.apiBaseUrl));
|
|
22
|
+
* const response = await saveApi.save({ query: 'test' }); // type-safe
|
|
23
|
+
*
|
|
24
|
+
* // later, when the user logs in / picks a tenant — every subsequent call carries them:
|
|
25
|
+
* store.set(AppHeaders.AUTHORIZATION, token); // an app-defined key, if it wants auto-attach
|
|
26
|
+
* store.set(CompanyHeaders.TENANT_ID, tenantId);
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* A browser cannot hold service credentials, so a contract with an @AuthOidc or @AuthSharedSecret
|
|
30
|
+
* endpoint throws in `createClient`, not on the first call.
|
|
31
|
+
*/
|
|
32
|
+
export declare class ClientHttpBrowserFactory {
|
|
33
|
+
private readonly contextMgr;
|
|
34
|
+
constructor(store: MutableContextStore);
|
|
35
|
+
/**
|
|
36
|
+
* Create a type-safe HTTP client for one API contract.
|
|
37
|
+
*
|
|
38
|
+
* @param apiPrototype - The API prototype class with @ApiPath/@Endpoint decorators
|
|
39
|
+
* @param config - This client's state (its baseUrl)
|
|
40
|
+
*/
|
|
41
|
+
createClient<T extends object>(apiPrototype: ApiPrototype<T>, config: ClientConfig): T;
|
|
42
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ClientHttpBrowserFactory = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const core_util_1 = require("@webpieces/core-util");
|
|
6
|
+
const http_client_core_1 = require("@webpieces/http-client-core");
|
|
7
|
+
const BrowserProxyClient_1 = require("./BrowserProxyClient");
|
|
8
|
+
const MutableContextStore_1 = require("./MutableContextStore");
|
|
9
|
+
/**
|
|
10
|
+
* ClientHttpBrowserFactory - builds type-safe HTTP clients for a BROWSER from API prototypes
|
|
11
|
+
* carrying @ApiPath/@Endpoint decorators.
|
|
12
|
+
*
|
|
13
|
+
* Deliberately a plain class with NO decorators and NO inversify: this package may be bundled by
|
|
14
|
+
* React just as easily as by Angular, and neither should be forced to adopt a Node DI container.
|
|
15
|
+
* The app provides it through whatever DI it already has — Angular's `useFactory`, a React context,
|
|
16
|
+
* or a module-level `const`.
|
|
17
|
+
*
|
|
18
|
+
* The factory holds the ONE collaborator every browser client shares (the app's
|
|
19
|
+
* {@link MutableContextStore}); each {@link ClientConfig} holds only that one client's base URL.
|
|
20
|
+
*
|
|
21
|
+
* ```typescript
|
|
22
|
+
* // once, at startup (after HeaderRegistry.configure(...)):
|
|
23
|
+
* const store = new MutableContextStore();
|
|
24
|
+
* const factory = new ClientHttpBrowserFactory(store);
|
|
25
|
+
*
|
|
26
|
+
* const saveApi = factory.createClient(SaveApi, new ClientConfig(env.apiBaseUrl));
|
|
27
|
+
* const response = await saveApi.save({ query: 'test' }); // type-safe
|
|
28
|
+
*
|
|
29
|
+
* // later, when the user logs in / picks a tenant — every subsequent call carries them:
|
|
30
|
+
* store.set(AppHeaders.AUTHORIZATION, token); // an app-defined key, if it wants auto-attach
|
|
31
|
+
* store.set(CompanyHeaders.TENANT_ID, tenantId);
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* A browser cannot hold service credentials, so a contract with an @AuthOidc or @AuthSharedSecret
|
|
35
|
+
* endpoint throws in `createClient`, not on the first call.
|
|
36
|
+
*/
|
|
37
|
+
let ClientHttpBrowserFactory = class ClientHttpBrowserFactory {
|
|
38
|
+
contextMgr;
|
|
39
|
+
constructor(store) {
|
|
40
|
+
this.contextMgr = new core_util_1.ContextMgr(store);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Create a type-safe HTTP client for one API contract.
|
|
44
|
+
*
|
|
45
|
+
* @param apiPrototype - The API prototype class with @ApiPath/@Endpoint decorators
|
|
46
|
+
* @param config - This client's state (its baseUrl)
|
|
47
|
+
*/
|
|
48
|
+
createClient(apiPrototype, config) {
|
|
49
|
+
const proxyClient = new BrowserProxyClient_1.BrowserProxyClient(this.contextMgr);
|
|
50
|
+
proxyClient.init(apiPrototype, config);
|
|
51
|
+
return (0, http_client_core_1.buildClientProxy)(apiPrototype, proxyClient);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
exports.ClientHttpBrowserFactory = ClientHttpBrowserFactory;
|
|
55
|
+
exports.ClientHttpBrowserFactory = ClientHttpBrowserFactory = tslib_1.__decorate([
|
|
56
|
+
(0, core_util_1.DocumentDesign)(),
|
|
57
|
+
tslib_1.__metadata("design:paramtypes", [MutableContextStore_1.MutableContextStore])
|
|
58
|
+
], ClientHttpBrowserFactory);
|
|
59
|
+
//# sourceMappingURL=ClientHttpBrowserFactory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClientHttpBrowserFactory.js","sourceRoot":"","sources":["../../../../../packages/http/http-client-browser/src/ClientHttpBrowserFactory.ts"],"names":[],"mappings":";;;;AAAA,oDAAkE;AAClE,kEAA6E;AAC7E,6DAA0D;AAE1D,+DAA4D;AAE5D;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEI,IAAM,wBAAwB,GAA9B,MAAM,wBAAwB;IAChB,UAAU,CAAa;IAExC,YAAY,KAA0B;QAClC,IAAI,CAAC,UAAU,GAAG,IAAI,sBAAU,CAAC,KAAK,CAAC,CAAC;IAC5C,CAAC;IAED;;;;;OAKG;IACH,YAAY,CAAmB,YAA6B,EAAE,MAAoB;QAC9E,MAAM,WAAW,GAAG,IAAI,uCAAkB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC5D,WAAW,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QACvC,OAAO,IAAA,mCAAgB,EAAC,YAAY,EAAE,WAAW,CAAC,CAAC;IACvD,CAAC;CACJ,CAAA;AAlBY,4DAAwB;mCAAxB,wBAAwB;IADpC,IAAA,0BAAc,GAAE;6CAIM,yCAAmB;GAH7B,wBAAwB,CAkBpC","sourcesContent":["import { ContextMgr, DocumentDesign } from '@webpieces/core-util';\nimport { ApiPrototype, buildClientProxy } from '@webpieces/http-client-core';\nimport { BrowserProxyClient } from './BrowserProxyClient';\nimport { ClientConfig } from './ClientConfig';\nimport { MutableContextStore } from './MutableContextStore';\n\n/**\n * ClientHttpBrowserFactory - builds type-safe HTTP clients for a BROWSER from API prototypes\n * carrying @ApiPath/@Endpoint decorators.\n *\n * Deliberately a plain class with NO decorators and NO inversify: this package may be bundled by\n * React just as easily as by Angular, and neither should be forced to adopt a Node DI container.\n * The app provides it through whatever DI it already has — Angular's `useFactory`, a React context,\n * or a module-level `const`.\n *\n * The factory holds the ONE collaborator every browser client shares (the app's\n * {@link MutableContextStore}); each {@link ClientConfig} holds only that one client's base URL.\n *\n * ```typescript\n * // once, at startup (after HeaderRegistry.configure(...)):\n * const store = new MutableContextStore();\n * const factory = new ClientHttpBrowserFactory(store);\n *\n * const saveApi = factory.createClient(SaveApi, new ClientConfig(env.apiBaseUrl));\n * const response = await saveApi.save({ query: 'test' }); // type-safe\n *\n * // later, when the user logs in / picks a tenant — every subsequent call carries them:\n * store.set(AppHeaders.AUTHORIZATION, token); // an app-defined key, if it wants auto-attach\n * store.set(CompanyHeaders.TENANT_ID, tenantId);\n * ```\n *\n * A browser cannot hold service credentials, so a contract with an @AuthOidc or @AuthSharedSecret\n * endpoint throws in `createClient`, not on the first call.\n */\n@DocumentDesign()\nexport class ClientHttpBrowserFactory {\n private readonly contextMgr: ContextMgr;\n\n constructor(store: MutableContextStore) {\n this.contextMgr = new ContextMgr(store);\n }\n\n /**\n * Create a type-safe HTTP client for one API contract.\n *\n * @param apiPrototype - The API prototype class with @ApiPath/@Endpoint decorators\n * @param config - This client's state (its baseUrl)\n */\n createClient<T extends object>(apiPrototype: ApiPrototype<T>, config: ClientConfig): T {\n const proxyClient = new BrowserProxyClient(this.contextMgr);\n proxyClient.init(apiPrototype, config);\n return buildClientProxy(apiPrototype, proxyClient);\n }\n}\n"]}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ContextKey, ContextReader } from '@webpieces/core-util';
|
|
2
|
+
/**
|
|
3
|
+
* MutableContextStore - the BROWSER ContextReader.
|
|
4
|
+
*
|
|
5
|
+
* Browsers have no AsyncLocalStorage, so apps (Angular/React) hold one of these
|
|
6
|
+
* (e.g. as an Angular service / React context value) and set values as they become
|
|
7
|
+
* known (login token, selected tenant, ...). The ContextMgr then reads from it on
|
|
8
|
+
* every outbound request.
|
|
9
|
+
*
|
|
10
|
+
* Example (Angular):
|
|
11
|
+
* ```typescript
|
|
12
|
+
* const store = new MutableContextStore();
|
|
13
|
+
* // startup:
|
|
14
|
+
* HeaderRegistry.configure(AppHeaders.getAllHeaders(), CompanyHeaders.getAllHeaders(), true);
|
|
15
|
+
* const factory = new ClientHttpFactory(new ContextMgr(store));
|
|
16
|
+
* const client = factory.createClient(SaveApi, new ClientConfig(baseUrl));
|
|
17
|
+
*
|
|
18
|
+
* // later, when the user logs in / picks a tenant:
|
|
19
|
+
* store.set(AppHeaders.AUTHORIZATION, token); // an app-defined key, if it wants auto-attach
|
|
20
|
+
* store.set(CompanyHeaders.TENANT_ID, tenantId);
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare class MutableContextStore implements ContextReader {
|
|
24
|
+
private values;
|
|
25
|
+
/** Set (or overwrite) the current value for a context key. */
|
|
26
|
+
set(key: ContextKey, value: string): void;
|
|
27
|
+
/** Remove the current value for a context key (e.g. on logout). */
|
|
28
|
+
remove(key: ContextKey): void;
|
|
29
|
+
/** Clear all stored values. */
|
|
30
|
+
clear(): void;
|
|
31
|
+
read(key: ContextKey): string | undefined;
|
|
32
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MutableContextStore = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* MutableContextStore - the BROWSER ContextReader.
|
|
6
|
+
*
|
|
7
|
+
* Browsers have no AsyncLocalStorage, so apps (Angular/React) hold one of these
|
|
8
|
+
* (e.g. as an Angular service / React context value) and set values as they become
|
|
9
|
+
* known (login token, selected tenant, ...). The ContextMgr then reads from it on
|
|
10
|
+
* every outbound request.
|
|
11
|
+
*
|
|
12
|
+
* Example (Angular):
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const store = new MutableContextStore();
|
|
15
|
+
* // startup:
|
|
16
|
+
* HeaderRegistry.configure(AppHeaders.getAllHeaders(), CompanyHeaders.getAllHeaders(), true);
|
|
17
|
+
* const factory = new ClientHttpFactory(new ContextMgr(store));
|
|
18
|
+
* const client = factory.createClient(SaveApi, new ClientConfig(baseUrl));
|
|
19
|
+
*
|
|
20
|
+
* // later, when the user logs in / picks a tenant:
|
|
21
|
+
* store.set(AppHeaders.AUTHORIZATION, token); // an app-defined key, if it wants auto-attach
|
|
22
|
+
* store.set(CompanyHeaders.TENANT_ID, tenantId);
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
class MutableContextStore {
|
|
26
|
+
values = new Map();
|
|
27
|
+
/** Set (or overwrite) the current value for a context key. */
|
|
28
|
+
set(key, value) {
|
|
29
|
+
this.values.set(key.name, value);
|
|
30
|
+
}
|
|
31
|
+
/** Remove the current value for a context key (e.g. on logout). */
|
|
32
|
+
remove(key) {
|
|
33
|
+
this.values.delete(key.name);
|
|
34
|
+
}
|
|
35
|
+
/** Clear all stored values. */
|
|
36
|
+
clear() {
|
|
37
|
+
this.values.clear();
|
|
38
|
+
}
|
|
39
|
+
read(key) {
|
|
40
|
+
return this.values.get(key.name);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
exports.MutableContextStore = MutableContextStore;
|
|
44
|
+
//# sourceMappingURL=MutableContextStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MutableContextStore.js","sourceRoot":"","sources":["../../../../../packages/http/http-client-browser/src/MutableContextStore.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAa,mBAAmB;IACpB,MAAM,GAAwB,IAAI,GAAG,EAAE,CAAC;IAEhD,8DAA8D;IAC9D,GAAG,CAAC,GAAe,EAAE,KAAa;QAC9B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACrC,CAAC;IAED,mEAAmE;IACnE,MAAM,CAAC,GAAe;QAClB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,+BAA+B;IAC/B,KAAK;QACD,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;IAED,IAAI,CAAC,GAAe;QAChB,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC;CACJ;AArBD,kDAqBC","sourcesContent":["import { ContextKey, ContextReader } from '@webpieces/core-util';\n\n/**\n * MutableContextStore - the BROWSER ContextReader.\n *\n * Browsers have no AsyncLocalStorage, so apps (Angular/React) hold one of these\n * (e.g. as an Angular service / React context value) and set values as they become\n * known (login token, selected tenant, ...). The ContextMgr then reads from it on\n * every outbound request.\n *\n * Example (Angular):\n * ```typescript\n * const store = new MutableContextStore();\n * // startup:\n * HeaderRegistry.configure(AppHeaders.getAllHeaders(), CompanyHeaders.getAllHeaders(), true);\n * const factory = new ClientHttpFactory(new ContextMgr(store));\n * const client = factory.createClient(SaveApi, new ClientConfig(baseUrl));\n *\n * // later, when the user logs in / picks a tenant:\n * store.set(AppHeaders.AUTHORIZATION, token); // an app-defined key, if it wants auto-attach\n * store.set(CompanyHeaders.TENANT_ID, tenantId);\n * ```\n */\nexport class MutableContextStore implements ContextReader {\n private values: Map<string, string> = new Map();\n\n /** Set (or overwrite) the current value for a context key. */\n set(key: ContextKey, value: string): void {\n this.values.set(key.name, value);\n }\n\n /** Remove the current value for a context key (e.g. on logout). */\n remove(key: ContextKey): void {\n this.values.delete(key.name);\n }\n\n /** Clear all stored values. */\n clear(): void {\n this.values.clear();\n }\n\n read(key: ContextKey): string | undefined {\n return this.values.get(key.name);\n }\n}\n"]}
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @webpieces/http-client-browser
|
|
3
|
+
*
|
|
4
|
+
* The BROWSER HTTP client. Reads an API contract's decorators and generates type-safe HTTP
|
|
5
|
+
* clients from it — the same contract the server implements.
|
|
6
|
+
*
|
|
7
|
+
* DI-free on purpose: this may be bundled by React or Angular, so it ships no inversify and no
|
|
8
|
+
* @webpieces/core-context (which is AsyncLocalStorage-backed and Node-only). Browsers have no
|
|
9
|
+
* ambient request scope, so the app holds a {@link MutableContextStore} and sets context values
|
|
10
|
+
* as they become known; every outbound call then transfers them as headers.
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* ```typescript
|
|
14
|
+
* import { ClientHttpBrowserFactory, ClientConfig, MutableContextStore } from '@webpieces/http-client-browser';
|
|
15
|
+
*
|
|
16
|
+
* HeaderRegistry.configure(AppHeaders.getAllHeaders(), CompanyHeaders.getAllHeaders(), true);
|
|
17
|
+
* const store = new MutableContextStore();
|
|
18
|
+
* const factory = new ClientHttpBrowserFactory(store);
|
|
19
|
+
*
|
|
20
|
+
* const client = factory.createClient(SaveApi, new ClientConfig('http://localhost:3000'));
|
|
21
|
+
* const response = await client.save({ query: 'test' });
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* The server twin is @webpieces/http-client-node.
|
|
25
|
+
*/
|
|
26
|
+
export { ClientHttpBrowserFactory } from './ClientHttpBrowserFactory';
|
|
27
|
+
export { BrowserProxyClient } from './BrowserProxyClient';
|
|
28
|
+
export { ClientConfig } from './ClientConfig';
|
|
29
|
+
export { MutableContextStore } from './MutableContextStore';
|
|
30
|
+
export { ProxyClient, ClientErrorTranslator } from '@webpieces/http-client-core';
|
|
31
|
+
export type { ApiPrototype } from '@webpieces/http-client-core';
|
|
32
|
+
export { ContextMgr } from '@webpieces/core-util';
|
|
33
|
+
export { ContextReader, ContextKey, HeaderRegistry, WebpiecesCoreHeaders, } from '@webpieces/core-util';
|
|
34
|
+
export { ApiPath, Endpoint, Authentication, AuthenticationConfig, Public, AuthJwt, AuthOidc, AuthSharedSecret, Rpc, PubSub, Queue, ValidateImplementation, } from '@webpieces/core-util';
|
package/src/index.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @webpieces/http-client-browser
|
|
4
|
+
*
|
|
5
|
+
* The BROWSER HTTP client. Reads an API contract's decorators and generates type-safe HTTP
|
|
6
|
+
* clients from it — the same contract the server implements.
|
|
7
|
+
*
|
|
8
|
+
* DI-free on purpose: this may be bundled by React or Angular, so it ships no inversify and no
|
|
9
|
+
* @webpieces/core-context (which is AsyncLocalStorage-backed and Node-only). Browsers have no
|
|
10
|
+
* ambient request scope, so the app holds a {@link MutableContextStore} and sets context values
|
|
11
|
+
* as they become known; every outbound call then transfers them as headers.
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import { ClientHttpBrowserFactory, ClientConfig, MutableContextStore } from '@webpieces/http-client-browser';
|
|
16
|
+
*
|
|
17
|
+
* HeaderRegistry.configure(AppHeaders.getAllHeaders(), CompanyHeaders.getAllHeaders(), true);
|
|
18
|
+
* const store = new MutableContextStore();
|
|
19
|
+
* const factory = new ClientHttpBrowserFactory(store);
|
|
20
|
+
*
|
|
21
|
+
* const client = factory.createClient(SaveApi, new ClientConfig('http://localhost:3000'));
|
|
22
|
+
* const response = await client.save({ query: 'test' });
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* The server twin is @webpieces/http-client-node.
|
|
26
|
+
*/
|
|
27
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
+
exports.Queue = exports.PubSub = exports.Rpc = exports.AuthSharedSecret = exports.AuthOidc = exports.AuthJwt = exports.Public = exports.AuthenticationConfig = exports.Authentication = exports.Endpoint = exports.ApiPath = exports.WebpiecesCoreHeaders = exports.HeaderRegistry = exports.ContextKey = exports.ContextMgr = exports.ClientErrorTranslator = exports.ProxyClient = exports.MutableContextStore = exports.ClientConfig = exports.BrowserProxyClient = exports.ClientHttpBrowserFactory = void 0;
|
|
29
|
+
var ClientHttpBrowserFactory_1 = require("./ClientHttpBrowserFactory");
|
|
30
|
+
Object.defineProperty(exports, "ClientHttpBrowserFactory", { enumerable: true, get: function () { return ClientHttpBrowserFactory_1.ClientHttpBrowserFactory; } });
|
|
31
|
+
var BrowserProxyClient_1 = require("./BrowserProxyClient");
|
|
32
|
+
Object.defineProperty(exports, "BrowserProxyClient", { enumerable: true, get: function () { return BrowserProxyClient_1.BrowserProxyClient; } });
|
|
33
|
+
var ClientConfig_1 = require("./ClientConfig");
|
|
34
|
+
Object.defineProperty(exports, "ClientConfig", { enumerable: true, get: function () { return ClientConfig_1.ClientConfig; } });
|
|
35
|
+
var MutableContextStore_1 = require("./MutableContextStore");
|
|
36
|
+
Object.defineProperty(exports, "MutableContextStore", { enumerable: true, get: function () { return MutableContextStore_1.MutableContextStore; } });
|
|
37
|
+
// The isomorphic engine, re-exported so a browser app needs one import.
|
|
38
|
+
var http_client_core_1 = require("@webpieces/http-client-core");
|
|
39
|
+
Object.defineProperty(exports, "ProxyClient", { enumerable: true, get: function () { return http_client_core_1.ProxyClient; } });
|
|
40
|
+
Object.defineProperty(exports, "ClientErrorTranslator", { enumerable: true, get: function () { return http_client_core_1.ClientErrorTranslator; } });
|
|
41
|
+
// ContextMgr is the BROWSER's outbound-header propagation. This is the only package that may use
|
|
42
|
+
// it; the server reads RequestContext directly (RequestContextHeaders in @webpieces/core-context).
|
|
43
|
+
var core_util_1 = require("@webpieces/core-util");
|
|
44
|
+
Object.defineProperty(exports, "ContextMgr", { enumerable: true, get: function () { return core_util_1.ContextMgr; } });
|
|
45
|
+
// Re-export the context-key contract from core-util for convenience (browser one-import)
|
|
46
|
+
var core_util_2 = require("@webpieces/core-util");
|
|
47
|
+
Object.defineProperty(exports, "ContextKey", { enumerable: true, get: function () { return core_util_2.ContextKey; } });
|
|
48
|
+
Object.defineProperty(exports, "HeaderRegistry", { enumerable: true, get: function () { return core_util_2.HeaderRegistry; } });
|
|
49
|
+
Object.defineProperty(exports, "WebpiecesCoreHeaders", { enumerable: true, get: function () { return core_util_2.WebpiecesCoreHeaders; } });
|
|
50
|
+
// Re-export API decorators for convenience (same as http-routing does)
|
|
51
|
+
var core_util_3 = require("@webpieces/core-util");
|
|
52
|
+
Object.defineProperty(exports, "ApiPath", { enumerable: true, get: function () { return core_util_3.ApiPath; } });
|
|
53
|
+
Object.defineProperty(exports, "Endpoint", { enumerable: true, get: function () { return core_util_3.Endpoint; } });
|
|
54
|
+
Object.defineProperty(exports, "Authentication", { enumerable: true, get: function () { return core_util_3.Authentication; } });
|
|
55
|
+
Object.defineProperty(exports, "AuthenticationConfig", { enumerable: true, get: function () { return core_util_3.AuthenticationConfig; } });
|
|
56
|
+
Object.defineProperty(exports, "Public", { enumerable: true, get: function () { return core_util_3.Public; } });
|
|
57
|
+
Object.defineProperty(exports, "AuthJwt", { enumerable: true, get: function () { return core_util_3.AuthJwt; } });
|
|
58
|
+
Object.defineProperty(exports, "AuthOidc", { enumerable: true, get: function () { return core_util_3.AuthOidc; } });
|
|
59
|
+
Object.defineProperty(exports, "AuthSharedSecret", { enumerable: true, get: function () { return core_util_3.AuthSharedSecret; } });
|
|
60
|
+
Object.defineProperty(exports, "Rpc", { enumerable: true, get: function () { return core_util_3.Rpc; } });
|
|
61
|
+
Object.defineProperty(exports, "PubSub", { enumerable: true, get: function () { return core_util_3.PubSub; } });
|
|
62
|
+
Object.defineProperty(exports, "Queue", { enumerable: true, get: function () { return core_util_3.Queue; } });
|
|
63
|
+
//# sourceMappingURL=index.js.map
|
package/src/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/http/http-client-browser/src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;;;AAEH,uEAAsE;AAA7D,oIAAA,wBAAwB,OAAA;AACjC,2DAA0D;AAAjD,wHAAA,kBAAkB,OAAA;AAC3B,+CAA8C;AAArC,4GAAA,YAAY,OAAA;AACrB,6DAA4D;AAAnD,0HAAA,mBAAmB,OAAA;AAE5B,wEAAwE;AACxE,gEAAiF;AAAxE,+GAAA,WAAW,OAAA;AAAE,yHAAA,qBAAqB,OAAA;AAG3C,iGAAiG;AACjG,mGAAmG;AACnG,kDAAkD;AAAzC,uGAAA,UAAU,OAAA;AAEnB,yFAAyF;AACzF,kDAK8B;AAH1B,uGAAA,UAAU,OAAA;AACV,2GAAA,cAAc,OAAA;AACd,iHAAA,oBAAoB,OAAA;AAGxB,uEAAuE;AACvE,kDAa8B;AAZ1B,oGAAA,OAAO,OAAA;AACP,qGAAA,QAAQ,OAAA;AACR,2GAAA,cAAc,OAAA;AACd,iHAAA,oBAAoB,OAAA;AACpB,mGAAA,MAAM,OAAA;AACN,oGAAA,OAAO,OAAA;AACP,qGAAA,QAAQ,OAAA;AACR,6GAAA,gBAAgB,OAAA;AAChB,gGAAA,GAAG,OAAA;AACH,mGAAA,MAAM,OAAA;AACN,kGAAA,KAAK,OAAA","sourcesContent":["/**\n * @webpieces/http-client-browser\n *\n * The BROWSER HTTP client. Reads an API contract's decorators and generates type-safe HTTP\n * clients from it — the same contract the server implements.\n *\n * DI-free on purpose: this may be bundled by React or Angular, so it ships no inversify and no\n * @webpieces/core-context (which is AsyncLocalStorage-backed and Node-only). Browsers have no\n * ambient request scope, so the app holds a {@link MutableContextStore} and sets context values\n * as they become known; every outbound call then transfers them as headers.\n *\n * Usage:\n * ```typescript\n * import { ClientHttpBrowserFactory, ClientConfig, MutableContextStore } from '@webpieces/http-client-browser';\n *\n * HeaderRegistry.configure(AppHeaders.getAllHeaders(), CompanyHeaders.getAllHeaders(), true);\n * const store = new MutableContextStore();\n * const factory = new ClientHttpBrowserFactory(store);\n *\n * const client = factory.createClient(SaveApi, new ClientConfig('http://localhost:3000'));\n * const response = await client.save({ query: 'test' });\n * ```\n *\n * The server twin is @webpieces/http-client-node.\n */\n\nexport { ClientHttpBrowserFactory } from './ClientHttpBrowserFactory';\nexport { BrowserProxyClient } from './BrowserProxyClient';\nexport { ClientConfig } from './ClientConfig';\nexport { MutableContextStore } from './MutableContextStore';\n\n// The isomorphic engine, re-exported so a browser app needs one import.\nexport { ProxyClient, ClientErrorTranslator } from '@webpieces/http-client-core';\nexport type { ApiPrototype } from '@webpieces/http-client-core';\n\n// ContextMgr is the BROWSER's outbound-header propagation. This is the only package that may use\n// it; the server reads RequestContext directly (RequestContextHeaders in @webpieces/core-context).\nexport { ContextMgr } from '@webpieces/core-util';\n\n// Re-export the context-key contract from core-util for convenience (browser one-import)\nexport {\n ContextReader,\n ContextKey,\n HeaderRegistry,\n WebpiecesCoreHeaders,\n} from '@webpieces/core-util';\n\n// Re-export API decorators for convenience (same as http-routing does)\nexport {\n ApiPath,\n Endpoint,\n Authentication,\n AuthenticationConfig,\n Public,\n AuthJwt,\n AuthOidc,\n AuthSharedSecret,\n Rpc,\n PubSub,\n Queue,\n ValidateImplementation,\n} from '@webpieces/core-util';\n"]}
|