@webpieces/http-client-browser 0.4.863 → 0.4.865
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 +1 -1
- package/package.json +3 -3
- package/src/BrowserProxyClient.d.ts +6 -5
- package/src/BrowserProxyClient.js +14 -35
- package/src/BrowserProxyClient.js.map +1 -1
- package/src/ClientHttpBrowserFactory.d.ts +1 -1
- package/src/ClientHttpBrowserFactory.js +1 -1
- package/src/ClientHttpBrowserFactory.js.map +1 -1
- package/src/index.d.ts +1 -1
- package/src/index.js +10 -5
- package/src/index.js.map +1 -1
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ store.set(WebpiecesCoreHeaders.AUTHORIZATION, token);
|
|
|
21
21
|
store.set(CompanyHeaders.TENANT_ID, tenantId);
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
A browser cannot hold service credentials, so a contract with an
|
|
24
|
+
A browser cannot hold service credentials, so a contract with an `oidc(...)` endpoint fails fast at
|
|
25
25
|
`createRpcClient`. The server twin is [@webpieces/http-client-node](../http-client-node).
|
|
26
26
|
|
|
27
27
|
Calls have a **30-second default timeout**, including reading the response body. Configure
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webpieces/http-client-browser",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.865",
|
|
4
4
|
"description": "Browser HTTP client for webpieces: DI-free (React or Angular), app-managed context store, no AsyncLocalStorage",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"access": "public"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@webpieces/core-util": "0.4.
|
|
26
|
-
"@webpieces/http-client-core": "0.4.
|
|
25
|
+
"@webpieces/core-util": "0.4.865",
|
|
26
|
+
"@webpieces/http-client-core": "0.4.865"
|
|
27
27
|
}
|
|
28
28
|
}
|
|
@@ -15,6 +15,7 @@ import { RequestLifecycleListener } from './RequestLifecycleListener';
|
|
|
15
15
|
export declare class BrowserProxyClient extends ProxyClient {
|
|
16
16
|
private readonly contextMgr;
|
|
17
17
|
private readonly lifecycleListener?;
|
|
18
|
+
protected selectAuthMethod(route: RouteMetadata): import('@webpieces/core-util').AuthMode;
|
|
18
19
|
private config;
|
|
19
20
|
constructor(contextMgr: ContextMgr, lifecycleListener?: RequestLifecycleListener | undefined);
|
|
20
21
|
/** Bind this client to one API contract + base URL. */
|
|
@@ -36,8 +37,8 @@ export declare class BrowserProxyClient extends ProxyClient {
|
|
|
36
37
|
protected sendStreamingTransport(_request: ClientRequest, _signal: AbortSignal, _body: ByteReadableStream): Promise<Response>;
|
|
37
38
|
/**
|
|
38
39
|
* `destination` is always the un-verifying kind here — {@link assertEndpointSupported} below
|
|
39
|
-
* refuses to bind an
|
|
40
|
-
*
|
|
40
|
+
* refuses to bind an oidc(...) / sharedSecret(...) contract, so every browser destination is
|
|
41
|
+
* jwt() or @WpAuthPublic — which means a browser never puts a trusted context key on the wire. It is
|
|
41
42
|
* still threaded rather than short-circuited: the rule lives in ContextMgr, one place, for both
|
|
42
43
|
* environments.
|
|
43
44
|
*/
|
|
@@ -59,10 +60,10 @@ export declare class BrowserProxyClient extends ProxyClient {
|
|
|
59
60
|
protected onRequestEnd(route: RouteMetadata, outcome: RequestOutcome): void;
|
|
60
61
|
/**
|
|
61
62
|
* Reject a contract this browser cannot satisfy, at bind time rather than on the first call.
|
|
62
|
-
* Both service-to-service modes need credentials only a server has:
|
|
63
|
-
* service account to mint a token,
|
|
63
|
+
* Both service-to-service modes need credentials only a server has: oidc(...) needs a runtime
|
|
64
|
+
* service account to mint a token, sharedSecret(...) needs a secret no browser may ship.
|
|
64
65
|
*
|
|
65
|
-
* @
|
|
66
|
+
* @WpLocalOnly is deliberately NOT rejected: a browser calling a dev-only endpoint on the
|
|
66
67
|
* developer's own server is the motivating case for that mode (shipping browser logs into the
|
|
67
68
|
* server log). It needs no credential — the server refuses it off-local by not having the route.
|
|
68
69
|
*
|
|
@@ -17,6 +17,14 @@ const http_client_core_1 = require("@webpieces/http-client-core");
|
|
|
17
17
|
class BrowserProxyClient extends http_client_core_1.ProxyClient {
|
|
18
18
|
contextMgr;
|
|
19
19
|
lifecycleListener;
|
|
20
|
+
selectAuthMethod(route) {
|
|
21
|
+
const selected = route.authMeta?.methods.find((method) => method.kind === 'jwt' || method.kind === 'public');
|
|
22
|
+
if (!selected) {
|
|
23
|
+
const methods = route.authMeta?.methods.map((method) => method.kind === 'apikey' ? `apiKey('${method.regime}', credentials)` : method.kind).join(', ');
|
|
24
|
+
throw new Error(`Endpoint ${route.apiName}.${route.methodName} declares ${methods}. A browser cannot hold these credentials; call it from a server-side client with the configured verifier credentials.`);
|
|
25
|
+
}
|
|
26
|
+
return selected;
|
|
27
|
+
}
|
|
20
28
|
config;
|
|
21
29
|
constructor(contextMgr, lifecycleListener) {
|
|
22
30
|
// The browser's ApiCallContext, constructed here rather than installed at startup: its store
|
|
@@ -56,8 +64,8 @@ class BrowserProxyClient extends http_client_core_1.ProxyClient {
|
|
|
56
64
|
}
|
|
57
65
|
/**
|
|
58
66
|
* `destination` is always the un-verifying kind here — {@link assertEndpointSupported} below
|
|
59
|
-
* refuses to bind an
|
|
60
|
-
*
|
|
67
|
+
* refuses to bind an oidc(...) / sharedSecret(...) contract, so every browser destination is
|
|
68
|
+
* jwt() or @WpAuthPublic — which means a browser never puts a trusted context key on the wire. It is
|
|
61
69
|
* still threaded rather than short-circuited: the rule lives in ContextMgr, one place, for both
|
|
62
70
|
* environments.
|
|
63
71
|
*/
|
|
@@ -87,10 +95,10 @@ class BrowserProxyClient extends http_client_core_1.ProxyClient {
|
|
|
87
95
|
}
|
|
88
96
|
/**
|
|
89
97
|
* Reject a contract this browser cannot satisfy, at bind time rather than on the first call.
|
|
90
|
-
* Both service-to-service modes need credentials only a server has:
|
|
91
|
-
* service account to mint a token,
|
|
98
|
+
* Both service-to-service modes need credentials only a server has: oidc(...) needs a runtime
|
|
99
|
+
* service account to mint a token, sharedSecret(...) needs a secret no browser may ship.
|
|
92
100
|
*
|
|
93
|
-
* @
|
|
101
|
+
* @WpLocalOnly is deliberately NOT rejected: a browser calling a dev-only endpoint on the
|
|
94
102
|
* developer's own server is the motivating case for that mode (shipping browser logs into the
|
|
95
103
|
* server log). It needs no credential — the server refuses it off-local by not having the route.
|
|
96
104
|
*
|
|
@@ -106,36 +114,7 @@ class BrowserProxyClient extends http_client_core_1.ProxyClient {
|
|
|
106
114
|
if (route.streaming && route.streaming.direction !== core_util_1.StreamDirection.RESPONSE) {
|
|
107
115
|
throw new http_client_core_1.StreamingCapabilityError('browser', `Browser Fetch supports only @WpStream(StreamDirection.RESPONSE); ${methodName} is ${route.streaming.direction}.`);
|
|
108
116
|
}
|
|
109
|
-
|
|
110
|
-
if (mode === undefined) {
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
switch (mode.kind) {
|
|
114
|
-
case 'public':
|
|
115
|
-
case 'jwt':
|
|
116
|
-
case 'local-only':
|
|
117
|
-
return;
|
|
118
|
-
case 'oidc':
|
|
119
|
-
case 'shared-secret':
|
|
120
|
-
throw new Error(`Endpoint ${methodName} is @${mode.kind === 'oidc' ? 'WpAuthOidc' : 'WpAuthSharedSecret'} — a browser ` +
|
|
121
|
-
`cannot hold service credentials. Call it server-side with ClientHttpFactory from ` +
|
|
122
|
-
`@webpieces/http-client-node.`);
|
|
123
|
-
// @WpAuthWebhook is not "a credential a browser lacks" — it is an endpoint whose ONLY
|
|
124
|
-
// legitimate caller is the outside vendor that signs the request in its own scheme.
|
|
125
|
-
// NOTHING in this repo can call it, browser or server, so it is refused at bind time
|
|
126
|
-
// rather than failing as a 401 on the first call.
|
|
127
|
-
case 'webhook':
|
|
128
|
-
throw new Error(`Endpoint ${methodName} is @WpAuthWebhook('${mode.name}') — only ${mode.name} can call it, ` +
|
|
129
|
-
`because only ${mode.name} can produce the signature its WebhookAuthCallback verifies. It is not ` +
|
|
130
|
-
`callable from a webpieces client.`);
|
|
131
|
-
// @WpAuthApiKey is the same shape of refusal for a different reason: the credential is a
|
|
132
|
-
// CUSTOMER-held api key whose header names the app's ApiKeyHook chooses, so no webpieces
|
|
133
|
-
// client knows what to send — and a browser must not ship a customer's key at all.
|
|
134
|
-
case 'apikey':
|
|
135
|
-
throw new Error(`Endpoint ${methodName} is @WpAuthApiKey('${mode.regime}') — its credential is a customer-held ` +
|
|
136
|
-
`api key that a browser must never ship, and the header carrying it is the app's ApiKeyHook's ` +
|
|
137
|
-
`choice, so no webpieces client can build the call. Only the partner holding the key calls it.`);
|
|
138
|
-
}
|
|
117
|
+
this.selectAuthMethod(route);
|
|
139
118
|
}
|
|
140
119
|
}
|
|
141
120
|
exports.BrowserProxyClient = BrowserProxyClient;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BrowserProxyClient.js","sourceRoot":"","sources":["../../../../../packages/http/http-client-browser/src/BrowserProxyClient.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ContextMgr,\n ClientRegistry,\n DestinationTrust,\n LogApiCallImpl,\n RouteMetadata,\n StreamDirection,\n} from '@webpieces/core-util';\nimport { BrowserApiCallContext } from './BrowserApiCallContext';\nimport {\n ApiPrototype,\n ByteReadableStream,\n ClientRequest,\n ProxyClient,\n RequestOutcome,\n StreamingCapabilityError,\n} from '@webpieces/http-client-core';\nimport { ClientConfig } from './ClientConfig';\nimport { RequestLifecycleListener } from './RequestLifecycleListener';\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(\n private readonly contextMgr: ContextMgr,\n private readonly lifecycleListener?: RequestLifecycleListener,\n ) {\n // The browser's ApiCallContext, constructed here rather than installed at startup: its store\n // is static, so every instance stamps into the one slot BrowserApiCallContext.snapshot()\n // reads — which is how a browser logger folds the `api` tag into each line.\n super(new LogApiCallImpl(new BrowserApiCallContext()));\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 // The browser factory does not take app filters yet, so this client runs the framework\n // built-ins only (today: none). The chain itself is isomorphic and ready for them.\n this.initRoutes(apiPrototype, []);\n }\n\n /**\n * The same chain every client runs — a ClientRegistry mapping, else the installed deriver — but\n * with the BROWSER's fallback: `''`, which makes the URL RELATIVE (`/auth/oauth`) and therefore\n * same-origin, by definition. A browser app almost always calls the backend that served it, so\n * that is the default, and an unregistered svcName must NEVER throw the way it used to — a\n * forgotten registration silently killed sign-in, the request never leaving the page.\n *\n * A mapping still wins, which is exactly how an Angular dev server on :4201 reaches its backend\n * on :8201, while the same bundle served BY that backend in prod registers nothing and goes\n * relative. No `window` access, so this stays SSR-safe and testable.\n */\n protected override async resolveBaseUrl(): Promise<string> {\n return (await ClientRegistry.tryResolve(this.config.svcName)) ?? '';\n }\n\n /** Browser Fetch request streaming is specified as half-duplex, not concurrent duplex. */\n protected override supportsConcurrentDuplexFetch(): boolean {\n return false;\n }\n\n protected override sendStreamingTransport(\n _request: ClientRequest,\n _signal: AbortSignal,\n _body: ByteReadableStream,\n ): Promise<Response> {\n return Promise.reject(\n new StreamingCapabilityError(\n 'browser',\n 'Fetch request streaming is half-duplex and has no safe bidirectional fallback.',\n ),\n );\n }\n\n /**\n * `destination` is always the un-verifying kind here — {@link assertEndpointSupported} below\n * refuses to bind an @WpAuthOidc / @WpAuthSharedSecret contract, so every browser destination is\n * @WpAuthJwt or @WpAuthPublic — which means a browser never puts a trusted context key on the wire. It is\n * still threaded rather than short-circuited: the rule lives in ContextMgr, one place, for both\n * environments.\n */\n protected override outboundContextHeaders(destination: DestinationTrust): Map<string, string> {\n return this.contextMgr.buildOutboundHeaders(destination);\n }\n\n /**\n * Into the app-held store, via the same {@link ContextMgr} that owns the outbound direction — so\n * a value a server set reaches the page without the page naming a header.\n *\n * TRUSTED response keys are dropped there, by type: a browser store holds only untrusted values.\n * `destination` is threaded anyway rather than short-circuited here, for the reason the outbound\n * direction gives — the rule lives in ContextMgr, one place, for both environments.\n */\n protected override acceptResponseContext(\n headers: Headers,\n destination: DestinationTrust,\n ): void {\n this.contextMgr.acceptResponseHeaders(headers, destination);\n }\n\n /**\n * Forward the call's lifecycle to the app's listener, if one was registered on the factory. The\n * optional chain makes both a no-op when no listener is present — the default browser case.\n */\n protected override onRequestStart(route: RouteMetadata): void {\n this.lifecycleListener?.onRequestStart(route);\n }\n\n protected override onRequestEnd(route: RouteMetadata, outcome: RequestOutcome): void {\n this.lifecycleListener?.onRequestEnd(route, outcome);\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: @WpAuthOidc needs a runtime\n * service account to mint a token, @WpAuthSharedSecret needs a secret no browser may ship.\n *\n * @WpAuthLocalOnly is deliberately NOT rejected: a browser calling a dev-only endpoint on the\n * developer's own server is the motivating case for that mode (shipping browser logs into the\n * server log). It needs no credential — the server refuses it off-local by not having the route.\n *\n * An exhaustive switch with NO `default`, like {@link DestinationTrust.forAuthMode} and\n * `AuthFilter.verifiesCaller`. This was a NEGATIVE allow-list (`kind !== 'oidc' && kind !==\n * 'shared-secret'`), which silently WAVED THROUGH any future AuthMode kind — the browser would\n * have bound a contract it cannot satisfy and failed on the first call instead of at bind time.\n * Adding `local-only` is what surfaced it: the third reader of the union should fail to compile\n * on a NEW kind for the same reason the other two do.\n */\n protected override assertEndpointSupported(route: RouteMetadata): void {\n const methodName = route.methodName;\n if (route.streaming && route.streaming.direction !== StreamDirection.RESPONSE) {\n throw new StreamingCapabilityError(\n 'browser',\n `Browser Fetch supports only @WpStream(StreamDirection.RESPONSE); ${methodName} is ${route.streaming.direction}.`,\n );\n }\n const mode = route.authMeta?.mode;\n if (mode === undefined) {\n return;\n }\n switch (mode.kind) {\n case 'public':\n case 'jwt':\n case 'local-only':\n return;\n case 'oidc':\n case 'shared-secret':\n throw new Error(\n `Endpoint ${methodName} is @${mode.kind === 'oidc' ? 'WpAuthOidc' : 'WpAuthSharedSecret'} — a browser ` +\n `cannot hold service credentials. Call it server-side with ClientHttpFactory from ` +\n `@webpieces/http-client-node.`,\n );\n // @WpAuthWebhook is not \"a credential a browser lacks\" — it is an endpoint whose ONLY\n // legitimate caller is the outside vendor that signs the request in its own scheme.\n // NOTHING in this repo can call it, browser or server, so it is refused at bind time\n // rather than failing as a 401 on the first call.\n case 'webhook':\n throw new Error(\n `Endpoint ${methodName} is @WpAuthWebhook('${mode.name}') — only ${mode.name} can call it, ` +\n `because only ${mode.name} can produce the signature its WebhookAuthCallback verifies. It is not ` +\n `callable from a webpieces client.`,\n );\n // @WpAuthApiKey is the same shape of refusal for a different reason: the credential is a\n // CUSTOMER-held api key whose header names the app's ApiKeyHook chooses, so no webpieces\n // client knows what to send — and a browser must not ship a customer's key at all.\n case 'apikey':\n throw new Error(\n `Endpoint ${methodName} is @WpAuthApiKey('${mode.regime}') — its credential is a customer-held ` +\n `api key that a browser must never ship, and the header carrying it is the app's ApiKeyHook's ` +\n `choice, so no webpieces client can build the call. Only the partner holding the key calls it.`,\n );\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"BrowserProxyClient.js","sourceRoot":"","sources":["../../../../../packages/http/http-client-browser/src/BrowserProxyClient.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ContextMgr,\n ClientRegistry,\n DestinationTrust,\n LogApiCallImpl,\n RouteMetadata,\n StreamDirection,\n} from '@webpieces/core-util';\nimport { BrowserApiCallContext } from './BrowserApiCallContext';\nimport {\n ApiPrototype,\n ByteReadableStream,\n ClientRequest,\n ProxyClient,\n RequestOutcome,\n StreamingCapabilityError,\n} from '@webpieces/http-client-core';\nimport { ClientConfig } from './ClientConfig';\nimport { RequestLifecycleListener } from './RequestLifecycleListener';\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 protected override selectAuthMethod(route: RouteMetadata): import('@webpieces/core-util').AuthMode {\n const selected = route.authMeta?.methods.find((method: import('@webpieces/core-util').AuthMode) => method.kind === 'jwt' || method.kind === 'public');\n if (!selected) {\n const methods = route.authMeta?.methods.map((method: import('@webpieces/core-util').AuthMode) => method.kind === 'apikey' ? `apiKey('${method.regime}', credentials)` : method.kind).join(', ');\n throw new Error(`Endpoint ${route.apiName}.${route.methodName} declares ${methods}. A browser cannot hold these credentials; call it from a server-side client with the configured verifier credentials.`);\n }\n return selected;\n }\n private config!: ClientConfig;\n\n constructor(\n private readonly contextMgr: ContextMgr,\n private readonly lifecycleListener?: RequestLifecycleListener,\n ) {\n // The browser's ApiCallContext, constructed here rather than installed at startup: its store\n // is static, so every instance stamps into the one slot BrowserApiCallContext.snapshot()\n // reads — which is how a browser logger folds the `api` tag into each line.\n super(new LogApiCallImpl(new BrowserApiCallContext()));\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 // The browser factory does not take app filters yet, so this client runs the framework\n // built-ins only (today: none). The chain itself is isomorphic and ready for them.\n this.initRoutes(apiPrototype, []);\n }\n\n /**\n * The same chain every client runs — a ClientRegistry mapping, else the installed deriver — but\n * with the BROWSER's fallback: `''`, which makes the URL RELATIVE (`/auth/oauth`) and therefore\n * same-origin, by definition. A browser app almost always calls the backend that served it, so\n * that is the default, and an unregistered svcName must NEVER throw the way it used to — a\n * forgotten registration silently killed sign-in, the request never leaving the page.\n *\n * A mapping still wins, which is exactly how an Angular dev server on :4201 reaches its backend\n * on :8201, while the same bundle served BY that backend in prod registers nothing and goes\n * relative. No `window` access, so this stays SSR-safe and testable.\n */\n protected override async resolveBaseUrl(): Promise<string> {\n return (await ClientRegistry.tryResolve(this.config.svcName)) ?? '';\n }\n\n /** Browser Fetch request streaming is specified as half-duplex, not concurrent duplex. */\n protected override supportsConcurrentDuplexFetch(): boolean {\n return false;\n }\n\n protected override sendStreamingTransport(\n _request: ClientRequest,\n _signal: AbortSignal,\n _body: ByteReadableStream,\n ): Promise<Response> {\n return Promise.reject(\n new StreamingCapabilityError(\n 'browser',\n 'Fetch request streaming is half-duplex and has no safe bidirectional fallback.',\n ),\n );\n }\n\n /**\n * `destination` is always the un-verifying kind here — {@link assertEndpointSupported} below\n * refuses to bind an oidc(...) / sharedSecret(...) contract, so every browser destination is\n * jwt() or @WpAuthPublic — which means a browser never puts a trusted context key on the wire. It is\n * still threaded rather than short-circuited: the rule lives in ContextMgr, one place, for both\n * environments.\n */\n protected override outboundContextHeaders(destination: DestinationTrust): Map<string, string> {\n return this.contextMgr.buildOutboundHeaders(destination);\n }\n\n /**\n * Into the app-held store, via the same {@link ContextMgr} that owns the outbound direction — so\n * a value a server set reaches the page without the page naming a header.\n *\n * TRUSTED response keys are dropped there, by type: a browser store holds only untrusted values.\n * `destination` is threaded anyway rather than short-circuited here, for the reason the outbound\n * direction gives — the rule lives in ContextMgr, one place, for both environments.\n */\n protected override acceptResponseContext(\n headers: Headers,\n destination: DestinationTrust,\n ): void {\n this.contextMgr.acceptResponseHeaders(headers, destination);\n }\n\n /**\n * Forward the call's lifecycle to the app's listener, if one was registered on the factory. The\n * optional chain makes both a no-op when no listener is present — the default browser case.\n */\n protected override onRequestStart(route: RouteMetadata): void {\n this.lifecycleListener?.onRequestStart(route);\n }\n\n protected override onRequestEnd(route: RouteMetadata, outcome: RequestOutcome): void {\n this.lifecycleListener?.onRequestEnd(route, outcome);\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: oidc(...) needs a runtime\n * service account to mint a token, sharedSecret(...) needs a secret no browser may ship.\n *\n * @WpLocalOnly is deliberately NOT rejected: a browser calling a dev-only endpoint on the\n * developer's own server is the motivating case for that mode (shipping browser logs into the\n * server log). It needs no credential — the server refuses it off-local by not having the route.\n *\n * An exhaustive switch with NO `default`, like {@link DestinationTrust.forAuthMode} and\n * `AuthFilter.verifiesCaller`. This was a NEGATIVE allow-list (`kind !== 'oidc' && kind !==\n * 'shared-secret'`), which silently WAVED THROUGH any future AuthMode kind — the browser would\n * have bound a contract it cannot satisfy and failed on the first call instead of at bind time.\n * Adding `local-only` is what surfaced it: the third reader of the union should fail to compile\n * on a NEW kind for the same reason the other two do.\n */\n protected override assertEndpointSupported(route: RouteMetadata): void {\n const methodName = route.methodName;\n if (route.streaming && route.streaming.direction !== StreamDirection.RESPONSE) {\n throw new StreamingCapabilityError(\n 'browser',\n `Browser Fetch supports only @WpStream(StreamDirection.RESPONSE); ${methodName} is ${route.streaming.direction}.`,\n );\n }\n this.selectAuthMethod(route);\n }\n}\n"]}
|
|
@@ -27,7 +27,7 @@ import { RequestLifecycleListener } from './RequestLifecycleListener';
|
|
|
27
27
|
* store.set(CompanyHeaders.TENANT_ID, tenantId);
|
|
28
28
|
* ```
|
|
29
29
|
*
|
|
30
|
-
* A browser cannot hold service credentials, so a contract with an
|
|
30
|
+
* A browser cannot hold service credentials, so a contract with an oidc(...) or sharedSecret(...)
|
|
31
31
|
* endpoint throws in `createRpcClient`, not on the first call.
|
|
32
32
|
*/
|
|
33
33
|
export declare class ClientHttpBrowserFactory {
|
|
@@ -31,7 +31,7 @@ const MutableContextStore_1 = require("./MutableContextStore");
|
|
|
31
31
|
* store.set(CompanyHeaders.TENANT_ID, tenantId);
|
|
32
32
|
* ```
|
|
33
33
|
*
|
|
34
|
-
* A browser cannot hold service credentials, so a contract with an
|
|
34
|
+
* A browser cannot hold service credentials, so a contract with an oidc(...) or sharedSecret(...)
|
|
35
35
|
* endpoint throws in `createRpcClient`, not on the first call.
|
|
36
36
|
*/
|
|
37
37
|
let ClientHttpBrowserFactory = class ClientHttpBrowserFactory {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClientHttpBrowserFactory.js","sourceRoot":"","sources":["../../../../../packages/http/http-client-browser/src/ClientHttpBrowserFactory.ts"],"names":[],"mappings":";;;;AAAA,oDAAwF;AACxF,kEAA6E;AAC7E,6DAA0D;AAE1D,+DAA4D;AAG5D;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEI,IAAM,wBAAwB,GAA9B,MAAM,wBAAwB;IAKZ;IAJJ,UAAU,CAAa;IAExC,YACI,KAA0B,EACT,iBAA4C;QAA5C,sBAAiB,GAAjB,iBAAiB,CAA2B;QAE7D,IAAI,CAAC,UAAU,GAAG,IAAI,sBAAU,CAAC,KAAK,CAAC,CAAC;IAC5C,CAAC;IAED;;;;;OAKG;IACH,eAAe,CAAmB,YAA6B,EAAE,MAAoB;QACjF,IAAA,gCAAoB,EAAC,YAAY,EAAE,0BAA0B,CAAC,CAAC;QAC/D,MAAM,WAAW,GAAG,IAAI,uCAAkB,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC;QACpF,WAAW,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QACvC,OAAO,IAAA,mCAAgB,EAAC,YAAY,EAAE,WAAW,CAAC,CAAC;IACvD,CAAC;CACJ,CAAA;AAtBY,4DAAwB;mCAAxB,wBAAwB;IADpC,IAAA,0BAAc,GAAE;6CAKF,yCAAmB;GAJrB,wBAAwB,CAsBpC","sourcesContent":["import { assertNotInternalApi, 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';\nimport { RequestLifecycleListener } from './RequestLifecycleListener';\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.createRpcClient(SaveApi, new ClientConfig('server'));\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
|
|
1
|
+
{"version":3,"file":"ClientHttpBrowserFactory.js","sourceRoot":"","sources":["../../../../../packages/http/http-client-browser/src/ClientHttpBrowserFactory.ts"],"names":[],"mappings":";;;;AAAA,oDAAwF;AACxF,kEAA6E;AAC7E,6DAA0D;AAE1D,+DAA4D;AAG5D;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEI,IAAM,wBAAwB,GAA9B,MAAM,wBAAwB;IAKZ;IAJJ,UAAU,CAAa;IAExC,YACI,KAA0B,EACT,iBAA4C;QAA5C,sBAAiB,GAAjB,iBAAiB,CAA2B;QAE7D,IAAI,CAAC,UAAU,GAAG,IAAI,sBAAU,CAAC,KAAK,CAAC,CAAC;IAC5C,CAAC;IAED;;;;;OAKG;IACH,eAAe,CAAmB,YAA6B,EAAE,MAAoB;QACjF,IAAA,gCAAoB,EAAC,YAAY,EAAE,0BAA0B,CAAC,CAAC;QAC/D,MAAM,WAAW,GAAG,IAAI,uCAAkB,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC;QACpF,WAAW,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QACvC,OAAO,IAAA,mCAAgB,EAAC,YAAY,EAAE,WAAW,CAAC,CAAC;IACvD,CAAC;CACJ,CAAA;AAtBY,4DAAwB;mCAAxB,wBAAwB;IADpC,IAAA,0BAAc,GAAE;6CAKF,yCAAmB;GAJrB,wBAAwB,CAsBpC","sourcesContent":["import { assertNotInternalApi, 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';\nimport { RequestLifecycleListener } from './RequestLifecycleListener';\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.createRpcClient(SaveApi, new ClientConfig('server'));\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 oidc(...) or sharedSecret(...)\n * endpoint throws in `createRpcClient`, not on the first call.\n */\n@DocumentDesign()\nexport class ClientHttpBrowserFactory {\n private readonly contextMgr: ContextMgr;\n\n constructor(\n store: MutableContextStore,\n private readonly lifecycleListener?: RequestLifecycleListener,\n ) {\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 createRpcClient<T extends object>(apiPrototype: ApiPrototype<T>, config: ClientConfig): T {\n assertNotInternalApi(apiPrototype, 'ClientHttpBrowserFactory');\n const proxyClient = new BrowserProxyClient(this.contextMgr, this.lifecycleListener);\n proxyClient.init(apiPrototype, config);\n return buildClientProxy(apiPrototype, proxyClient);\n }\n}\n"]}
|
package/src/index.d.ts
CHANGED
|
@@ -35,7 +35,7 @@ export { StreamingCapabilityError } from '@webpieces/http-client-core';
|
|
|
35
35
|
export { ContextMgr } from '@webpieces/core-util';
|
|
36
36
|
export { ContextReader, ContextWriter, ContextStore, ContextKey, HeaderRegistry, ClientRegistry, templateDeriver, WebpiecesCoreHeaders, } from '@webpieces/core-util';
|
|
37
37
|
export type { ServiceUrlDeriver } from '@webpieces/core-util';
|
|
38
|
-
export { ApiPath, Endpoint, PathParam, QueryParam, WpAuthPublic,
|
|
38
|
+
export { ApiPath, Endpoint, PathParam, QueryParam, WpAuthPublic, WpAuth, WpAuthorization, AuthorizationType, WpLocalOnly, jwt, oidc, sharedSecret, webhook, apiKey, Rpc, PubSub, Queue, ValidateImplementation, } from '@webpieces/core-util';
|
|
39
39
|
export { BrowserWiring } from './BrowserWiring';
|
|
40
40
|
export { RpcClientProvider, provideRpcClient } from './RpcClientProvider';
|
|
41
41
|
export { rpcTarget } from '@webpieces/http-client-core';
|
package/src/index.js
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
* The server twin is @webpieces/http-client-node.
|
|
26
26
|
*/
|
|
27
27
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
-
exports.rpcTarget = exports.provideRpcClient = exports.RpcClientProvider = exports.BrowserWiring = exports.Queue = exports.PubSub = exports.Rpc = exports.
|
|
28
|
+
exports.rpcTarget = exports.provideRpcClient = exports.RpcClientProvider = exports.BrowserWiring = exports.Queue = exports.PubSub = exports.Rpc = exports.apiKey = exports.webhook = exports.sharedSecret = exports.oidc = exports.jwt = exports.WpLocalOnly = exports.AuthorizationType = exports.WpAuthorization = exports.WpAuth = exports.WpAuthPublic = exports.QueryParam = exports.PathParam = exports.Endpoint = exports.ApiPath = exports.WebpiecesCoreHeaders = exports.templateDeriver = exports.ClientRegistry = exports.HeaderRegistry = exports.ContextKey = exports.ContextMgr = exports.StreamingCapabilityError = exports.RequestOutcome = exports.ClientErrorTranslator = exports.ProxyClient = exports.MutableContextStore = exports.ClientConfig = exports.BrowserApiCallContext = exports.BrowserProxyClient = exports.ClientHttpBrowserFactory = void 0;
|
|
29
29
|
var ClientHttpBrowserFactory_1 = require("./ClientHttpBrowserFactory");
|
|
30
30
|
Object.defineProperty(exports, "ClientHttpBrowserFactory", { enumerable: true, get: function () { return ClientHttpBrowserFactory_1.ClientHttpBrowserFactory; } });
|
|
31
31
|
var BrowserProxyClient_1 = require("./BrowserProxyClient");
|
|
@@ -64,10 +64,15 @@ Object.defineProperty(exports, "Endpoint", { enumerable: true, get: function ()
|
|
|
64
64
|
Object.defineProperty(exports, "PathParam", { enumerable: true, get: function () { return core_util_3.PathParam; } });
|
|
65
65
|
Object.defineProperty(exports, "QueryParam", { enumerable: true, get: function () { return core_util_3.QueryParam; } });
|
|
66
66
|
Object.defineProperty(exports, "WpAuthPublic", { enumerable: true, get: function () { return core_util_3.WpAuthPublic; } });
|
|
67
|
-
Object.defineProperty(exports, "
|
|
68
|
-
Object.defineProperty(exports, "
|
|
69
|
-
Object.defineProperty(exports, "
|
|
70
|
-
Object.defineProperty(exports, "
|
|
67
|
+
Object.defineProperty(exports, "WpAuth", { enumerable: true, get: function () { return core_util_3.WpAuth; } });
|
|
68
|
+
Object.defineProperty(exports, "WpAuthorization", { enumerable: true, get: function () { return core_util_3.WpAuthorization; } });
|
|
69
|
+
Object.defineProperty(exports, "AuthorizationType", { enumerable: true, get: function () { return core_util_3.AuthorizationType; } });
|
|
70
|
+
Object.defineProperty(exports, "WpLocalOnly", { enumerable: true, get: function () { return core_util_3.WpLocalOnly; } });
|
|
71
|
+
Object.defineProperty(exports, "jwt", { enumerable: true, get: function () { return core_util_3.jwt; } });
|
|
72
|
+
Object.defineProperty(exports, "oidc", { enumerable: true, get: function () { return core_util_3.oidc; } });
|
|
73
|
+
Object.defineProperty(exports, "sharedSecret", { enumerable: true, get: function () { return core_util_3.sharedSecret; } });
|
|
74
|
+
Object.defineProperty(exports, "webhook", { enumerable: true, get: function () { return core_util_3.webhook; } });
|
|
75
|
+
Object.defineProperty(exports, "apiKey", { enumerable: true, get: function () { return core_util_3.apiKey; } });
|
|
71
76
|
Object.defineProperty(exports, "Rpc", { enumerable: true, get: function () { return core_util_3.Rpc; } });
|
|
72
77
|
Object.defineProperty(exports, "PubSub", { enumerable: true, get: function () { return core_util_3.PubSub; } });
|
|
73
78
|
Object.defineProperty(exports, "Queue", { enumerable: true, get: function () { return core_util_3.Queue; } });
|
package/src/index.js.map
CHANGED
|
@@ -1 +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,4FAA4F;AAC5F,kGAAkG;AAClG,8BAA8B;AAC9B,iEAAgE;AAAvD,8HAAA,qBAAqB,OAAA;AAC9B,+CAA8C;AAArC,4GAAA,YAAY,OAAA;AACrB,6DAA4D;AAAnD,0HAAA,mBAAmB,OAAA;AAG5B,wEAAwE;AACxE,gEAAiG;AAAxF,+GAAA,WAAW,OAAA;AAAE,yHAAA,qBAAqB,OAAA;AAAE,kHAAA,cAAc,OAAA;AAE3D,gEAAuE;AAA9D,4HAAA,wBAAwB,OAAA;AAEjC,iGAAiG;AACjG,mGAAmG;AACnG,kDAAkD;AAAzC,uGAAA,UAAU,OAAA;AAEnB,yFAAyF;AACzF,kDAS8B;AAL1B,uGAAA,UAAU,OAAA;AACV,2GAAA,cAAc,OAAA;AACd,2GAAA,cAAc,OAAA;AACd,4GAAA,eAAe,OAAA;AACf,iHAAA,oBAAoB,OAAA;AAIxB,uEAAuE;AACvE,
|
|
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,4FAA4F;AAC5F,kGAAkG;AAClG,8BAA8B;AAC9B,iEAAgE;AAAvD,8HAAA,qBAAqB,OAAA;AAC9B,+CAA8C;AAArC,4GAAA,YAAY,OAAA;AACrB,6DAA4D;AAAnD,0HAAA,mBAAmB,OAAA;AAG5B,wEAAwE;AACxE,gEAAiG;AAAxF,+GAAA,WAAW,OAAA;AAAE,yHAAA,qBAAqB,OAAA;AAAE,kHAAA,cAAc,OAAA;AAE3D,gEAAuE;AAA9D,4HAAA,wBAAwB,OAAA;AAEjC,iGAAiG;AACjG,mGAAmG;AACnG,kDAAkD;AAAzC,uGAAA,UAAU,OAAA;AAEnB,yFAAyF;AACzF,kDAS8B;AAL1B,uGAAA,UAAU,OAAA;AACV,2GAAA,cAAc,OAAA;AACd,2GAAA,cAAc,OAAA;AACd,4GAAA,eAAe,OAAA;AACf,iHAAA,oBAAoB,OAAA;AAIxB,uEAAuE;AACvE,kDAmB8B;AAlB1B,oGAAA,OAAO,OAAA;AACP,qGAAA,QAAQ,OAAA;AACR,sGAAA,SAAS,OAAA;AACT,uGAAA,UAAU,OAAA;AACV,yGAAA,YAAY,OAAA;AACZ,mGAAA,MAAM,OAAA;AACN,4GAAA,eAAe,OAAA;AACf,8GAAA,iBAAiB,OAAA;AACjB,wGAAA,WAAW,OAAA;AACX,gGAAA,GAAG,OAAA;AACH,iGAAA,IAAI,OAAA;AACJ,yGAAA,YAAY,OAAA;AACZ,oGAAA,OAAO,OAAA;AACP,mGAAA,MAAM,OAAA;AACN,gGAAA,GAAG,OAAA;AACH,mGAAA,MAAM,OAAA;AACN,kGAAA,KAAK,OAAA;AAIT,iDAAgD;AAAvC,8GAAA,aAAa,OAAA;AACtB,yDAA0E;AAAjE,sHAAA,iBAAiB,OAAA;AAAE,qHAAA,gBAAgB,OAAA;AAC5C,gEAAwD;AAA/C,6GAAA,SAAS,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(CompanyHeaders.ALL_HEADERS, true);\n * const store = new MutableContextStore();\n * const factory = new ClientHttpBrowserFactory(store);\n *\n * const client = factory.createRpcClient(SaveApi, new ClientConfig('save-svc'));\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';\n// Browser impl of the ApiCallContext seam, constructed by BrowserProxyClient. Exported so a\n// browser/Angular logger can read the current tag via the STATIC BrowserApiCallContext.snapshot()\n// and fold it into log lines.\nexport { BrowserApiCallContext } from './BrowserApiCallContext';\nexport { ClientConfig } from './ClientConfig';\nexport { MutableContextStore } from './MutableContextStore';\nexport type { RequestLifecycleListener } from './RequestLifecycleListener';\n\n// The isomorphic engine, re-exported so a browser app needs one import.\nexport { ProxyClient, ClientErrorTranslator, RequestOutcome } from '@webpieces/http-client-core';\nexport type { ApiPrototype } from '@webpieces/http-client-core';\nexport { StreamingCapabilityError } 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 ContextWriter,\n ContextStore,\n ContextKey,\n HeaderRegistry,\n ClientRegistry,\n templateDeriver,\n WebpiecesCoreHeaders,\n} from '@webpieces/core-util';\nexport type { ServiceUrlDeriver } from '@webpieces/core-util';\n\n// Re-export API decorators for convenience (same as http-routing does)\nexport {\n ApiPath,\n Endpoint,\n PathParam,\n QueryParam,\n WpAuthPublic,\n WpAuth,\n WpAuthorization,\n AuthorizationType,\n WpLocalOnly,\n jwt,\n oidc,\n sharedSecret,\n webhook,\n apiKey,\n Rpc,\n PubSub,\n Queue,\n ValidateImplementation,\n} from '@webpieces/core-util';\n\nexport { BrowserWiring } from './BrowserWiring';\nexport { RpcClientProvider, provideRpcClient } from './RpcClientProvider';\nexport { rpcTarget } from '@webpieces/http-client-core';\nexport type { RpcTarget } from '@webpieces/http-client-core';\n"]}
|