@owlmeans/client-entrypoint 0.1.18-rc.46 → 0.1.18-rc.48
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 +11 -10
- package/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/client-entrypoint/SKILL.md +1 -1
- package/build/entrypoint.d.ts.map +1 -1
- package/build/entrypoint.js +6 -5
- package/build/entrypoint.js.map +1 -1
- package/build/helper/types.d.ts +10 -0
- package/build/helper/types.d.ts.map +1 -0
- package/build/helper/types.js +2 -0
- package/build/helper/types.js.map +1 -0
- package/build/helper.d.ts +4 -4
- package/build/helper.d.ts.map +1 -1
- package/build/helper.js +22 -19
- package/build/helper.js.map +1 -1
- package/build/index.d.ts +3 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +2 -1
- package/build/index.js.map +1 -1
- package/build/stab.d.ts +4 -0
- package/build/stab.d.ts.map +1 -0
- package/build/stab.js +5 -0
- package/build/stab.js.map +1 -0
- package/build/types.d.ts +2 -2
- package/build/types.d.ts.map +1 -1
- package/build/utils/handler/types.d.ts +15 -0
- package/build/utils/handler/types.d.ts.map +1 -0
- package/build/utils/handler/types.js +2 -0
- package/build/utils/handler/types.js.map +1 -0
- package/build/utils/handler.d.ts +6 -4
- package/build/utils/handler.d.ts.map +1 -1
- package/build/utils/handler.js +119 -113
- package/build/utils/handler.js.map +1 -1
- package/build/utils/index.d.ts +1 -0
- package/build/utils/index.d.ts.map +1 -1
- package/build/utils/index.js.map +1 -1
- package/package.json +11 -11
- package/src/entrypoint.ts +6 -5
- package/src/helper/types.ts +10 -0
- package/src/helper.ts +28 -23
- package/src/index.ts +3 -1
- package/src/stab.ts +6 -0
- package/src/types.ts +1 -6
- package/src/utils/handler/types.ts +15 -0
- package/src/utils/handler.ts +77 -71
- package/src/utils/index.ts +1 -0
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ re-exports of `@owlmeans/web-client` or `@owlmeans/web-panel`. Protocols are dec
|
|
|
10
10
|
## Installation
|
|
11
11
|
|
|
12
12
|
```bash
|
|
13
|
-
bun add @owlmeans/client-entrypoint@^0.1.18-rc.
|
|
13
|
+
bun add @owlmeans/client-entrypoint@^0.1.18-rc.48
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
## Concepts
|
|
@@ -116,15 +116,15 @@ so `call({ params })` is enough. Never add `{ body: {} }` as a workaround.
|
|
|
116
116
|
|
|
117
117
|
### 5. Narrowing a payload to a schema
|
|
118
118
|
|
|
119
|
-
`pickPerSchema(object, schema)` keeps only the keys the AJV schema declares and skips `null` values.
|
|
119
|
+
`clientRequestHelper.pickPerSchema(object, schema)` keeps only the keys the AJV schema declares and skips `null` values.
|
|
120
120
|
It is useful when a form model carries more fields than the contract accepts.
|
|
121
121
|
|
|
122
122
|
```ts
|
|
123
|
-
import {
|
|
123
|
+
import { clientRequestHelper } from '@owlmeans/client-entrypoint'
|
|
124
124
|
import type { ProjectUpdate } from 'my-app-common'
|
|
125
125
|
import { ProjectUpdateSchema } from 'my-app-common'
|
|
126
126
|
|
|
127
|
-
const body = pickPerSchema<typeof formValues, ProjectUpdate>(formValues, ProjectUpdateSchema)
|
|
127
|
+
const body = clientRequestHelper.pickPerSchema<typeof formValues, ProjectUpdate>(formValues, ProjectUpdateSchema)
|
|
128
128
|
await ctx.entrypoint(apiProtocols.project.update).call({ params: { id }, body })
|
|
129
129
|
```
|
|
130
130
|
|
|
@@ -138,8 +138,8 @@ await ctx.entrypoint(apiProtocols.project.update).call({ params: { id }, body })
|
|
|
138
138
|
| `bindAll(tree)` | function | Materialize every protocol in a named declaration tree |
|
|
139
139
|
| `bindScreen(protocol, handler, options?)` | function | Materialize a frontend protocol with its renderer |
|
|
140
140
|
| `stab` | const | No-op `RefedEntrypointHandler` for a URL-only frontend binding |
|
|
141
|
-
| `provideRequest(alias, path)` |
|
|
142
|
-
| `pickPerSchema(object, schema)` |
|
|
141
|
+
| `clientRequestHelper.provideRequest(alias, path)` | helper member | A minimal `AbstractRequest` for a dynamic boundary (for example a socket request) |
|
|
142
|
+
| `clientRequestHelper.pickPerSchema(object, schema)` | helper member | Keep only the non-null keys an AJV schema declares |
|
|
143
143
|
| `ClientProtocolEntrypoint<Protocol>` | type | The bound view of a protocol — see *Entrypoint members* |
|
|
144
144
|
| `ClientEntrypoint<T, R>` | type | The untyped bound entrypoint shape the protocol view is built from |
|
|
145
145
|
| `ClientEntrypointOptions` | type | `routeOptions?` (`ClientRouteOptions`), `validateOnCall?`, plus common entrypoint options |
|
|
@@ -164,9 +164,10 @@ await ctx.entrypoint(apiProtocols.project.update).call({ params: { id }, body })
|
|
|
164
164
|
|
|
165
165
|
| Symbol | Kind | Purpose |
|
|
166
166
|
|---|---|---|
|
|
167
|
-
| `
|
|
168
|
-
| `
|
|
169
|
-
| `
|
|
167
|
+
| `apiCallOf(ref)` / `makeApiCallHelper(ref)` | helper | The call mechanics bound to one entrypoint ref (one per ref through `apiCallOf`) |
|
|
168
|
+
| `apiCallOf(ref).apiInvoke(options?)` | helper member | The round trip behind `invoke()` |
|
|
169
|
+
| `apiCallOf(ref).apiHandler` | helper member | The handler that picks the transport service or the API client |
|
|
170
|
+
| `apiCallOf(ref).entrypointUrl(request?, options?)` | helper member | The address behind `url()` |
|
|
170
171
|
| `validate(ref)` | function | The filter behind `validate()` |
|
|
171
172
|
| `isEntrypoint(value)` | function | Re-export from `@owlmeans/entrypoint/utils` |
|
|
172
173
|
|
|
@@ -204,7 +205,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
|
|
|
204
205
|
your project's skill store (`.agents/skills/`):
|
|
205
206
|
|
|
206
207
|
```sh
|
|
207
|
-
npx @owlmeans/agent-skills@^0.1.18-rc.
|
|
208
|
+
npx @owlmeans/agent-skills@^0.1.18-rc.51
|
|
208
209
|
```
|
|
209
210
|
|
|
210
211
|
The embedded files are version-matched to this package release. Do not edit them
|
package/agent-meta/manifest.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
3
|
"package": "@owlmeans/client-entrypoint",
|
|
4
|
-
"version": "0.1.18-rc.
|
|
5
|
-
"generatedAt": "2026-10-
|
|
4
|
+
"version": "0.1.18-rc.48",
|
|
5
|
+
"generatedAt": "2026-10-06T11:45:57.658Z",
|
|
6
6
|
"canonicalRepo": "https://github.com/owlmeans/common",
|
|
7
7
|
"entries": [
|
|
8
8
|
{
|
|
@@ -7,7 +7,7 @@ user-invocable: false
|
|
|
7
7
|
|
|
8
8
|
# @owlmeans/client-entrypoint
|
|
9
9
|
|
|
10
|
-
**Install:** `bun add @owlmeans/client-entrypoint@^0.1.18-rc.
|
|
10
|
+
**Install:** `bun add @owlmeans/client-entrypoint@^0.1.18-rc.48`
|
|
11
11
|
|
|
12
12
|
Bind a declaration from `@owlmeans/entrypoint`; never construct or replace a contextual
|
|
13
13
|
entrypoint by alias.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entrypoint.d.ts","sourceRoot":"","sources":["../src/entrypoint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAiB,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAClH,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAO7E,qFAAqF;AACrF,eAAO,MAAM,0BAA0B,GAAI,CAAC,EAAE,CAAC,SAAS,eAAe,GAAG,eAAe,OAClF,gBAAgB,YACX,sBAAsB,CAAC,CAAC,EAAE,CAAC,CAAC,SAC/B,uBAAuB,KAC7B,gBAAgB,CAAC,CAAC,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"entrypoint.d.ts","sourceRoot":"","sources":["../src/entrypoint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAiB,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAClH,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAO7E,qFAAqF;AACrF,eAAO,MAAM,0BAA0B,GAAI,CAAC,EAAE,CAAC,SAAS,eAAe,GAAG,eAAe,OAClF,gBAAgB,YACX,sBAAsB,CAAC,CAAC,EAAE,CAAC,CAAC,SAC/B,uBAAuB,KAC7B,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAsDvB,CAAA"}
|
package/build/entrypoint.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { validate } from './utils/entrypoint.js';
|
|
2
2
|
import { route } from '@owlmeans/client-route';
|
|
3
|
-
import {
|
|
3
|
+
import { apiCallOf } from './utils/handler.js';
|
|
4
4
|
import { AppType } from '@owlmeans/context';
|
|
5
|
-
import {
|
|
5
|
+
import { clientRequestHelper } from './helper.js';
|
|
6
6
|
/** Attach client behaviour to an entrypoint already materialized from a protocol. */
|
|
7
7
|
export const bindMaterializedEntrypoint = (arg, handler, opts) => {
|
|
8
8
|
const entrypointHandle = { ref: undefined };
|
|
9
9
|
let _entrypoint;
|
|
10
|
+
const apiHandler = ref => apiCallOf(ref).apiHandler;
|
|
10
11
|
const _handler = handler ?? (arg.route.route.type === AppType.Backend ? apiHandler : undefined);
|
|
11
12
|
assertExplicitHandler(arg.route.route.type, handler);
|
|
12
13
|
const routeModel = route(arg.route, opts?.routeOptions);
|
|
@@ -17,20 +18,20 @@ export const bindMaterializedEntrypoint = (arg, handler, opts) => {
|
|
|
17
18
|
_entrypoint.filter = opts?.filter ?? arg.filter;
|
|
18
19
|
_entrypoint.gate = opts?.gate ?? arg.gate;
|
|
19
20
|
_entrypoint.gateParams = opts?.gateParams ?? arg.gateParams;
|
|
20
|
-
_entrypoint.url = ((req, urlOpts) => entrypointUrl(
|
|
21
|
+
_entrypoint.url = ((req, urlOpts) => apiCallOf(entrypointHandle).entrypointUrl(req, urlOpts));
|
|
21
22
|
// An entrypoint carrying a renderer IS a screen: it is addressed by URL, never called over the
|
|
22
23
|
// wire. Saying so here turns what used to be a URL-shaped answer from `call()` into a report.
|
|
23
24
|
_entrypoint.invoke = (handler != null
|
|
24
25
|
? (async () => {
|
|
25
26
|
throw new SyntaxError(`Entrypoint ${_entrypoint.alias} renders a screen - address it with url() instead of call()/invoke()`);
|
|
26
27
|
})
|
|
27
|
-
: apiInvoke(
|
|
28
|
+
: apiCallOf(entrypointHandle).apiInvoke(opts));
|
|
28
29
|
_entrypoint.call = (async (req) => (await _entrypoint.invoke(req)).value);
|
|
29
30
|
_entrypoint.request = ((request) => {
|
|
30
31
|
if (entrypointHandle.ref == null) {
|
|
31
32
|
throw SyntaxError(`Try to request uninitialized entrypoint ${JSON.stringify(arg)}`);
|
|
32
33
|
}
|
|
33
|
-
const _request = provideRequest(entrypointHandle.ref.alias, entrypointHandle.ref.path());
|
|
34
|
+
const _request = clientRequestHelper.provideRequest(entrypointHandle.ref.alias, entrypointHandle.ref.path());
|
|
34
35
|
request != null && Object.entries(request).forEach(([key, value]) => {
|
|
35
36
|
_request[key] = value;
|
|
36
37
|
});
|
package/build/entrypoint.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entrypoint.js","sourceRoot":"","sources":["../src/entrypoint.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AAC9C,OAAO,EAAE,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"entrypoint.js","sourceRoot":"","sources":["../src/entrypoint.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AbstractRequest } from '@owlmeans/entrypoint';
|
|
2
|
+
import type { JSONSchemaType } from 'ajv';
|
|
3
|
+
/** Builds and shapes the requests a client sends. */
|
|
4
|
+
export interface ClientRequestHelper {
|
|
5
|
+
/** A minimal cancellable `AbstractRequest` for an entrypoint alias at a path. */
|
|
6
|
+
provideRequest: <T extends {} = {}>(alias: string, path: string) => AbstractRequest<T>;
|
|
7
|
+
/** Keeps only the non-null keys of `object` the AJV schema declares. */
|
|
8
|
+
pickPerSchema: <T, R>(object: T, schema: JSONSchemaType<R>) => Partial<R>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/helper/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,KAAK,CAAA;AAEzC,qDAAqD;AACrD,MAAM,WAAW,mBAAmB;IAClC,iFAAiF;IACjF,cAAc,EAAE,CAAC,CAAC,SAAS,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,eAAe,CAAC,CAAC,CAAC,CAAA;IACtF,wEAAwE;IACxE,aAAa,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAA;CAC1E"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/helper/types.ts"],"names":[],"mappings":""}
|
package/build/helper.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { RefedEntrypointHandler } from './types.js';
|
|
2
1
|
import type { AbstractRequest } from '@owlmeans/entrypoint';
|
|
3
|
-
import type {
|
|
4
|
-
export declare const
|
|
2
|
+
import type { ClientRequestHelper } from './helper/types.js';
|
|
3
|
+
export declare const createClientRequestHelper: () => ClientRequestHelper;
|
|
4
|
+
export declare const clientRequestHelper: ClientRequestHelper;
|
|
5
|
+
/** @deprecated compat:factory-refactor — use `clientRequestHelper.provideRequest(…)` */
|
|
5
6
|
export declare const provideRequest: <T extends {} = {}>(alias: string, path: string) => AbstractRequest<T>;
|
|
6
|
-
export declare const pickPerSchema: <T, R>(object: T, schema: JSONSchemaType<R>) => Partial<R>;
|
|
7
7
|
//# sourceMappingURL=helper.d.ts.map
|
package/build/helper.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAE3D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAE5D,eAAO,MAAM,yBAAyB,QAAO,mBA0B5C,CAAA;AAED,eAAO,MAAM,mBAAmB,qBAA8B,CAAA;AAE9D,wFAAwF;AACxF,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,EAAE,GAAG,EAAE,SAAS,MAAM,QAAQ,MAAM,KAAG,eAAe,CAAC,CAAC,CAAuD,CAAA"}
|
package/build/helper.js
CHANGED
|
@@ -1,22 +1,25 @@
|
|
|
1
|
-
export const
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
export const createClientRequestHelper = () => {
|
|
2
|
+
const provideRequest = (alias, path) => {
|
|
3
|
+
const request = {
|
|
4
|
+
alias,
|
|
5
|
+
params: {},
|
|
6
|
+
headers: {},
|
|
7
|
+
query: {},
|
|
8
|
+
path,
|
|
9
|
+
canceled: false,
|
|
10
|
+
cancel: () => request.canceled = true
|
|
11
|
+
};
|
|
12
|
+
return request;
|
|
13
13
|
};
|
|
14
|
-
|
|
14
|
+
const pickPerSchema = (object, schema) => Object.keys(schema.properties).reduce((acc, key) => {
|
|
15
|
+
if (object[key] != null) {
|
|
16
|
+
acc[key] = object[key];
|
|
17
|
+
}
|
|
18
|
+
return acc;
|
|
19
|
+
}, {});
|
|
20
|
+
return { provideRequest, pickPerSchema };
|
|
15
21
|
};
|
|
16
|
-
export const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
return acc;
|
|
21
|
-
}, {});
|
|
22
|
+
export const clientRequestHelper = createClientRequestHelper();
|
|
23
|
+
/** @deprecated compat:factory-refactor — use `clientRequestHelper.provideRequest(…)` */
|
|
24
|
+
export const provideRequest = (alias, path) => clientRequestHelper.provideRequest(alias, path);
|
|
22
25
|
//# sourceMappingURL=helper.js.map
|
package/build/helper.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helper.js","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"helper.js","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,MAAM,yBAAyB,GAAG,GAAwB,EAAE;IACjE,MAAM,cAAc,GAAG,CAAoB,KAAa,EAAE,IAAY,EAAsB,EAAE;QAC5F,MAAM,OAAO,GAAG;YACd,KAAK;YACL,MAAM,EAAE,EAAE;YACV,OAAO,EAAE,EAAE;YACX,KAAK,EAAE,EAAE;YACT,IAAI;YACJ,QAAQ,EAAE,KAAK;YACf,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ,GAAG,IAAI;SACtC,CAAA;QAED,OAAO,OAAO,CAAA;IAChB,CAAC,CAAA;IAED,MAAM,aAAa,GAAG,CAAO,MAAS,EAAE,MAAyB,EAAc,EAAE,CAC/E,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,MAAM,CACnC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QACX,IAAI,MAAM,CAAC,GAAc,CAAC,IAAI,IAAI,EAAE,CAAC;YACnC,GAAG,CAAC,GAAc,CAAC,GAAG,MAAM,CAAC,GAAc,CAA0B,CAAA;QACvE,CAAC;QACD,OAAO,GAAG,CAAA;IACZ,CAAC,EAAE,EAAgB,CACpB,CAAA;IAEH,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,CAAA;AAC1C,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAG,yBAAyB,EAAE,CAAA;AAE9D,wFAAwF;AACxF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAoB,KAAa,EAAE,IAAY,EAAsB,EAAE,CAAC,mBAAmB,CAAC,cAAc,CAAI,KAAK,EAAE,IAAI,CAAC,CAAA"}
|
package/build/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export type * from './types.js';
|
|
2
|
+
export type * from './helper/types.js';
|
|
2
3
|
export * from './errors.js';
|
|
3
4
|
export * from './failure.js';
|
|
4
5
|
export * from './consts.js';
|
|
5
6
|
export * from './protocol.js';
|
|
6
|
-
export {
|
|
7
|
+
export { clientRequestHelper, createClientRequestHelper, provideRequest } from './helper.js';
|
|
8
|
+
export { stab } from './stab.js';
|
|
7
9
|
//# sourceMappingURL=index.d.ts.map
|
package/build/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,mBAAmB,YAAY,CAAA;AAC/B,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAC7B,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,mBAAmB,YAAY,CAAA;AAC/B,mBAAmB,mBAAmB,CAAA;AACtC,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAC7B,OAAO,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAC5F,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA"}
|
package/build/index.js
CHANGED
|
@@ -2,5 +2,6 @@ export * from './errors.js';
|
|
|
2
2
|
export * from './failure.js';
|
|
3
3
|
export * from './consts.js';
|
|
4
4
|
export * from './protocol.js';
|
|
5
|
-
export {
|
|
5
|
+
export { clientRequestHelper, createClientRequestHelper, provideRequest } from './helper.js';
|
|
6
|
+
export { stab } from './stab.js';
|
|
6
7
|
//# sourceMappingURL=index.js.map
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAC7B,OAAO,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAC5F,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA"}
|
package/build/stab.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stab.d.ts","sourceRoot":"","sources":["../src/stab.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAExD,wDAAwD;AACxD,eAAO,MAAM,IAAI,EAAE,sBAAsB,CAAC,EAAE,CAE3C,CAAA"}
|
package/build/stab.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stab.js","sourceRoot":"","sources":["../src/stab.ts"],"names":[],"mappings":"AAEA,wDAAwD;AACxD,MAAM,CAAC,MAAM,IAAI,GAA+B,GAAG,EAAE,CAAC,GAAG,EAAE;IACzD,OAAO,KAAK,CAAQ,CAAA;AACtB,CAAC,CAAA"}
|
package/build/types.d.ts
CHANGED
|
@@ -26,9 +26,9 @@ export interface ClientEntrypoint<T = {}, R extends ClientRequest = ClientReques
|
|
|
26
26
|
* its request and reply types are read directly from the declaration and cannot be replaced at a
|
|
27
27
|
* call site.
|
|
28
28
|
*/
|
|
29
|
-
export
|
|
29
|
+
export interface ClientProtocolEntrypoint<Protocol extends EntrypointProtocolDeclaration> extends Omit<ClientEntrypoint, 'call' | 'invoke' | 'url' | 'validate' | 'request'>, RegisteredEntrypoint<RequestOf<Protocol>, import('@owlmeans/entrypoint').ResponseOf<Protocol>> {
|
|
30
30
|
readonly protocol: Protocol;
|
|
31
|
-
}
|
|
31
|
+
}
|
|
32
32
|
export interface EntrypointCall<T, Req extends ClientRequest = ClientRequest> {
|
|
33
33
|
<Type extends T, R extends Req = Req>(req?: Partial<R>): Promise<Type>;
|
|
34
34
|
}
|
package/build/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAClF,OAAO,KAAK,EACV,eAAe,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,iBAAiB,EAC7E,iBAAiB,EAAE,6BAA6B,EAAE,oBAAoB,EAAE,SAAS,EAClF,MAAM,sBAAsB,CAAA;AAC7B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAEpD,MAAM,WAAW,gBAAgB,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,SAAS,aAAa,GAAG,aAAa,CAAE,SAAQ,gBAAgB;IACzG,KAAK,EAAE,gBAAgB,CAAA;IACvB;;;OAGG;IACH,IAAI,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAC1B;;;OAGG;IACH,MAAM,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAC9B;;;OAGG;IACH,GAAG,EAAE,aAAa,CAAC,CAAC,CAAC,CAAA;IACrB,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAA;IAC7B,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;CACrC;AAED;;;;GAIG;AACH,MAAM,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { AbstractRequest, EntrypointHandler } from '@owlmeans/entrypoint';
|
|
2
|
+
import type { ClientEntrypointOptions, EntrypointInvoke, EntrypointUrlOptions } from '../../types.js';
|
|
3
|
+
/** How a client entrypoint reaches its backend: the handler, the round trip and the address. */
|
|
4
|
+
export interface ApiCallHelper<T, R extends AbstractRequest = AbstractRequest> {
|
|
5
|
+
/**
|
|
6
|
+
* The handler that carries the entrypoint's call: the transport service bound to its route's
|
|
7
|
+
* protocol, else the API client of the web service its route answers on.
|
|
8
|
+
*/
|
|
9
|
+
apiHandler: EntrypointHandler;
|
|
10
|
+
/** The round trip behind `invoke()`: builds the request, validates it on demand and notifies failure observers. */
|
|
11
|
+
apiInvoke: (opts?: ClientEntrypointOptions) => EntrypointInvoke<T, R>;
|
|
12
|
+
/** The address behind `url()`: `:params` filled in, the query appended, absolute when the route is not local. */
|
|
13
|
+
entrypointUrl: (req?: Partial<R>, opts?: EntrypointUrlOptions) => Promise<string>;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/utils/handler/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAC9E,OAAO,KAAK,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AAErG,gGAAgG;AAChG,MAAM,WAAW,aAAa,CAAC,CAAC,EAAE,CAAC,SAAS,eAAe,GAAG,eAAe;IAC3E;;;OAGG;IACH,UAAU,EAAE,iBAAiB,CAAA;IAC7B,mHAAmH;IACnH,SAAS,EAAE,CAAC,IAAI,CAAC,EAAE,uBAAuB,KAAK,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IACrE,iHAAiH;IACjH,aAAa,EAAE,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,oBAAoB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;CAClF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/utils/handler/types.ts"],"names":[],"mappings":""}
|
package/build/utils/handler.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { type AbstractRequest
|
|
2
|
-
import type {
|
|
3
|
-
|
|
4
|
-
export declare const
|
|
1
|
+
import { type AbstractRequest } from '@owlmeans/entrypoint';
|
|
2
|
+
import type { EntrypointUrlOptions, EntrypointRef, ClientRequest } from '../types.js';
|
|
3
|
+
import type { ApiCallHelper } from './handler/types.js';
|
|
4
|
+
export declare const makeApiCallHelper: <T, R extends AbstractRequest = AbstractRequest>(ref: EntrypointRef<T, R>) => ApiCallHelper<T, R>;
|
|
5
|
+
export declare const apiCallOf: <T, R extends AbstractRequest = AbstractRequest<{}>>(target: EntrypointRef<T, R>) => ApiCallHelper<T, R>;
|
|
6
|
+
/** @deprecated compat:factory-refactor — use `makeApiCallHelper(ref).entrypointUrl(…)` */
|
|
5
7
|
export declare const entrypointUrl: <T, R extends ClientRequest = ClientRequest>(ref: EntrypointRef<T, R>, req?: Partial<R>, opts?: EntrypointUrlOptions) => Promise<string>;
|
|
6
8
|
//# sourceMappingURL=handler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/utils/handler.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,eAAe,
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/utils/handler.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,eAAe,EAAwG,MAAM,sBAAsB,CAAA;AACjK,OAAO,KAAK,EAAsC,oBAAoB,EAA2B,aAAa,EAAE,aAAa,EAA4B,MAAM,aAAa,CAAA;AAU5K,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAIvD,eAAO,MAAM,iBAAiB,GAAI,CAAC,EAAE,CAAC,SAAS,eAAe,GAAG,eAAe,OACzE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,KACvB,aAAa,CAAC,CAAC,EAAE,CAAC,CA4IpB,CAAA;AAED,eAAO,MAAM,SAAS,GAhJY,CAAC,EAAE,CAAC,SAAS,eAAe,2EAgJA,CAAA;AAE9D,0FAA0F;AAC1F,eAAO,MAAM,aAAa,GAAI,CAAC,EAAE,CAAC,SAAS,aAAa,GAAG,aAAa,OACjE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,OAAO,CAAC,CAAC,CAAC,SAAS,oBAAoB,KACtE,OAAO,CAAC,MAAM,CAAoD,CAAA"}
|
package/build/utils/handler.js
CHANGED
|
@@ -1,131 +1,137 @@
|
|
|
1
1
|
import { DEFAULT_KEY } from '@owlmeans/client-config';
|
|
2
2
|
import { EntrypointOutcome, provideResponse, transportAlias } from '@owlmeans/entrypoint';
|
|
3
3
|
import { validate } from './entrypoint.js';
|
|
4
|
-
import {
|
|
4
|
+
import { clientRouteHelper } from '@owlmeans/client-route';
|
|
5
5
|
import { PARAM, RouteMethod, RouteProtocols } from '@owlmeans/route';
|
|
6
6
|
import { stringify } from 'qs';
|
|
7
|
-
import { assertContext } from '@owlmeans/context';
|
|
7
|
+
import { assertContext, memoHelper } from '@owlmeans/context';
|
|
8
8
|
import { makeSecurityHelper } from '@owlmeans/config';
|
|
9
9
|
import { ENTRYPOINT_FAILURE_SERVICE } from '../consts.js';
|
|
10
10
|
import { logger } from '@owlmeans/log';
|
|
11
11
|
const log = logger('client-entrypoint');
|
|
12
|
-
export const
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
12
|
+
export const makeApiCallHelper = (ref) => {
|
|
13
|
+
const apiHandler = async (req, res) => {
|
|
14
|
+
const location = `client-entrypoint:api-handler:${ref.ref?.alias}`;
|
|
15
|
+
const context = assertContext(ref.ref?.ctx, location);
|
|
16
|
+
if (context.cfg.webService == null) {
|
|
17
|
+
throw new SyntaxError('No webService provided');
|
|
18
|
+
}
|
|
19
|
+
const ep = context.entrypoint(req.alias);
|
|
20
|
+
// A route names the protocol it answers on. Whatever is bound under that protocol takes the
|
|
21
|
+
// call, so a consumer writes `ep.call(...)` without learning which transport ran.
|
|
22
|
+
const transport = transportAlias(ep.route.route.protocol);
|
|
23
|
+
if (context.hasService(transport)) {
|
|
24
|
+
req.path = ep.path();
|
|
25
|
+
return context.service(transport).handle(req, res);
|
|
26
|
+
}
|
|
27
|
+
// Which web client carries this call is decided by the service the route answers on — the one it
|
|
28
|
+
// names, or the one the context picks for its app type when it names none.
|
|
29
|
+
const route = ep.service();
|
|
30
|
+
const alias = typeof context.cfg.webService === 'string'
|
|
31
|
+
? context.cfg.webService
|
|
32
|
+
: context.cfg.webService[route.service] ?? context.cfg.webService[DEFAULT_KEY];
|
|
33
|
+
if (alias == null) {
|
|
34
|
+
throw new SyntaxError(`Can't cast web service alias for ${ep.alias} entrypoint`);
|
|
35
|
+
}
|
|
36
|
+
const service = context.service(alias);
|
|
23
37
|
req.path = ep.path();
|
|
24
|
-
return
|
|
25
|
-
}
|
|
26
|
-
// Which web client carries this call is decided by the service the route answers on — the one it
|
|
27
|
-
// names, or the one the context picks for its app type when it names none.
|
|
28
|
-
const route = ep.service();
|
|
29
|
-
const alias = typeof context.cfg.webService === 'string'
|
|
30
|
-
? context.cfg.webService
|
|
31
|
-
: context.cfg.webService[route.service] ?? context.cfg.webService[DEFAULT_KEY];
|
|
32
|
-
if (alias == null) {
|
|
33
|
-
throw new SyntaxError(`Can't cast web service alias for ${ep.alias} entrypoint`);
|
|
34
|
-
}
|
|
35
|
-
const service = context.service(alias);
|
|
36
|
-
req.path = ep.path();
|
|
37
|
-
return service.handler(req, res);
|
|
38
|
-
};
|
|
39
|
-
export const apiInvoke = (ref, opts) => (async (req) => {
|
|
40
|
-
const ep = ref.ref;
|
|
41
|
-
if (ep == null) {
|
|
42
|
-
throw new SyntaxError('Try to make API call before the entrypoint is created');
|
|
43
|
-
}
|
|
44
|
-
const ctx = ep.ctx;
|
|
45
|
-
if (ctx == null) {
|
|
46
|
-
throw new SyntaxError(`No context provided in apiCall for ${ep.alias} entrypoint`);
|
|
47
|
-
}
|
|
48
|
-
if (req?.canceled) {
|
|
49
|
-
return { value: null, outcome: EntrypointOutcome.Ok };
|
|
50
|
-
}
|
|
51
|
-
const request = {
|
|
52
|
-
alias: ep.alias,
|
|
53
|
-
params: req?.params ?? {},
|
|
54
|
-
// JSON transports must send a body for mutation methods even when the contract has no
|
|
55
|
-
// payload. Keeping that rule here makes every typed caller use `call({ params })`, never
|
|
56
|
-
// an SDK-specific `{ body: {} }` workaround.
|
|
57
|
-
body: req?.body ?? ([RouteMethod.POST, RouteMethod.PUT, RouteMethod.PATCH]
|
|
58
|
-
.includes(ep.route.route.method ?? RouteMethod.GET) ? {} : undefined),
|
|
59
|
-
headers: req?.headers ?? {},
|
|
60
|
-
query: req?.query ?? {},
|
|
61
|
-
host: req?.host,
|
|
62
|
-
base: req?.base,
|
|
63
|
-
path: ep.path(),
|
|
64
|
-
timeout: req?.timeout,
|
|
65
|
-
signal: req?.signal,
|
|
38
|
+
return service.handler(req, res);
|
|
66
39
|
};
|
|
67
|
-
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
40
|
+
const apiInvoke = (opts) => (async (req) => {
|
|
41
|
+
const ep = ref.ref;
|
|
42
|
+
if (ep == null) {
|
|
43
|
+
throw new SyntaxError('Try to make API call before the entrypoint is created');
|
|
44
|
+
}
|
|
45
|
+
const ctx = ep.ctx;
|
|
46
|
+
if (ctx == null) {
|
|
47
|
+
throw new SyntaxError(`No context provided in apiCall for ${ep.alias} entrypoint`);
|
|
48
|
+
}
|
|
49
|
+
if (req?.canceled) {
|
|
50
|
+
return { value: null, outcome: EntrypointOutcome.Ok };
|
|
51
|
+
}
|
|
52
|
+
const request = {
|
|
53
|
+
alias: ep.alias,
|
|
54
|
+
params: req?.params ?? {},
|
|
55
|
+
// JSON transports must send a body for mutation methods even when the contract has no
|
|
56
|
+
// payload. Keeping that rule here makes every typed caller use `call({ params })`, never
|
|
57
|
+
// an SDK-specific `{ body: {} }` workaround.
|
|
58
|
+
body: req?.body ?? ([RouteMethod.POST, RouteMethod.PUT, RouteMethod.PATCH]
|
|
59
|
+
.includes(ep.route.route.method ?? RouteMethod.GET) ? {} : undefined),
|
|
60
|
+
headers: req?.headers ?? {},
|
|
61
|
+
query: req?.query ?? {},
|
|
62
|
+
host: req?.host,
|
|
63
|
+
base: req?.base,
|
|
64
|
+
path: ep.path(),
|
|
65
|
+
timeout: req?.timeout,
|
|
66
|
+
signal: req?.signal,
|
|
72
67
|
};
|
|
73
|
-
|
|
74
|
-
|
|
68
|
+
if (req?.cancel != null) {
|
|
69
|
+
const cancel = req.cancel;
|
|
70
|
+
req.cancel = () => {
|
|
71
|
+
cancel();
|
|
72
|
+
request.canceled = true;
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
if (opts?.validateOnCall) {
|
|
76
|
+
try {
|
|
77
|
+
await validate(ref)(request);
|
|
78
|
+
}
|
|
79
|
+
catch (e) {
|
|
80
|
+
log.error('Request validation failed', { alias: ep.alias, error: e });
|
|
81
|
+
throw e;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const reply = provideResponse();
|
|
85
|
+
if (ctx == null && ep.ctx == null) {
|
|
86
|
+
throw new SyntaxError(`Use entrypoint ${ep.alias} without context`);
|
|
87
|
+
}
|
|
75
88
|
try {
|
|
76
|
-
await
|
|
89
|
+
await apiHandler(request, reply);
|
|
90
|
+
if (reply.error != null)
|
|
91
|
+
throw reply.error;
|
|
77
92
|
}
|
|
78
|
-
catch (
|
|
79
|
-
|
|
80
|
-
|
|
93
|
+
catch (error) {
|
|
94
|
+
if (ctx.hasService(ENTRYPOINT_FAILURE_SERVICE)) {
|
|
95
|
+
await ctx.service(ENTRYPOINT_FAILURE_SERVICE)
|
|
96
|
+
.notify({ alias: ep.alias, request, error });
|
|
97
|
+
}
|
|
98
|
+
throw error;
|
|
81
99
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
await apiHandler(ref)(request, reply);
|
|
89
|
-
if (reply.error != null)
|
|
90
|
-
throw reply.error;
|
|
91
|
-
}
|
|
92
|
-
catch (error) {
|
|
93
|
-
if (ctx.hasService(ENTRYPOINT_FAILURE_SERVICE)) {
|
|
94
|
-
await ctx.service(ENTRYPOINT_FAILURE_SERVICE)
|
|
95
|
-
.notify({ alias: ep.alias, request, error });
|
|
100
|
+
return { value: reply.value ?? null, outcome: reply.outcome ?? EntrypointOutcome.Ok };
|
|
101
|
+
});
|
|
102
|
+
const entrypointUrl = async (req, opts) => {
|
|
103
|
+
const ep = ref.ref;
|
|
104
|
+
if (ep == null) {
|
|
105
|
+
throw new SyntaxError('Try to make URL before the entrypoint is created');
|
|
96
106
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
// name: a route that names no service belongs to the asking context, and addressing it absolutely
|
|
124
|
-
// would turn in-app navigation into a full page load.
|
|
125
|
-
if (socket || !ep.isLocal() || opts?.absolute === true) {
|
|
126
|
-
const helper = makeSecurityHelper(ctx);
|
|
127
|
-
path = helper.makeUrl(ep.address(), path, { host: req?.host, base: req?.base, forceUnsecure: req?.unsecure });
|
|
128
|
-
}
|
|
129
|
-
return path;
|
|
107
|
+
const ctx = ep.ctx;
|
|
108
|
+
if (ctx == null) {
|
|
109
|
+
throw new SyntaxError(`No context provided in entrypointUrl for ${ep.alias} entrypoint`);
|
|
110
|
+
}
|
|
111
|
+
// The base is left off here: an in-service URL is addressed relative to it, and the absolute
|
|
112
|
+
// branch below has `makeUrl` prepend it.
|
|
113
|
+
const epPath = ep.path();
|
|
114
|
+
const pathParams = clientRouteHelper.extractParams(epPath);
|
|
115
|
+
let path = pathParams.reduce((p, param) => {
|
|
116
|
+
return p.replace(`${PARAM}${param}`, `${req?.params?.[param]}`);
|
|
117
|
+
}, epPath) + (req?.query != null ? `?${stringify(req?.query)}` : '');
|
|
118
|
+
// A socket address is always absolute, whoever owns the route. `new WebSocket(path)` resolves a
|
|
119
|
+
// relative value against the PAGE's origin, which in a split deployment is the web host and not
|
|
120
|
+
// the service that answers the upgrade — so the handshake goes somewhere that never speaks it
|
|
121
|
+
// and dies on a gateway timeout. Only a same-origin HTTP route benefits from staying relative.
|
|
122
|
+
const socket = ep.route.route.protocol === RouteProtocols.SOCKET;
|
|
123
|
+
// Locality is a question about the RESOLVED service, not about what the declaration happens to
|
|
124
|
+
// name: a route that names no service belongs to the asking context, and addressing it absolutely
|
|
125
|
+
// would turn in-app navigation into a full page load.
|
|
126
|
+
if (socket || !ep.isLocal() || opts?.absolute === true) {
|
|
127
|
+
const helper = makeSecurityHelper(ctx);
|
|
128
|
+
path = helper.makeUrl(ep.address(), path, { host: req?.host, base: req?.base, forceUnsecure: req?.unsecure });
|
|
129
|
+
}
|
|
130
|
+
return path;
|
|
131
|
+
};
|
|
132
|
+
return { apiHandler, apiInvoke, entrypointUrl };
|
|
130
133
|
};
|
|
134
|
+
export const apiCallOf = memoHelper.oncePer(makeApiCallHelper);
|
|
135
|
+
/** @deprecated compat:factory-refactor — use `makeApiCallHelper(ref).entrypointUrl(…)` */
|
|
136
|
+
export const entrypointUrl = (ref, req, opts) => makeApiCallHelper(ref).entrypointUrl(req, opts);
|
|
131
137
|
//# sourceMappingURL=handler.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../src/utils/handler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AACrD,OAAO,EAA0E,iBAAiB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAEjK,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAC1C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../src/utils/handler.ts"],"names":[],"mappings":"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"}
|
package/build/utils/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AACA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AACA,mBAAmB,oBAAoB,CAAA;AACvC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA"}
|
package/build/utils/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAEA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@owlmeans/client-entrypoint",
|
|
3
|
-
"version": "0.1.18-rc.
|
|
3
|
+
"version": "0.1.18-rc.48",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -28,16 +28,16 @@
|
|
|
28
28
|
}
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@owlmeans/api": "^0.1.18-rc.
|
|
32
|
-
"@owlmeans/client-config": "^0.1.18-rc.
|
|
33
|
-
"@owlmeans/client-context": "^0.1.18-rc.
|
|
34
|
-
"@owlmeans/client-route": "^0.1.18-rc.
|
|
35
|
-
"@owlmeans/config": "^0.1.18-rc.
|
|
36
|
-
"@owlmeans/context": "^0.1.18-rc.
|
|
37
|
-
"@owlmeans/entrypoint": "^0.1.18-rc.
|
|
38
|
-
"@owlmeans/error": "^0.1.18-rc.
|
|
39
|
-
"@owlmeans/log": "^0.1.18-rc.
|
|
40
|
-
"@owlmeans/route": "^0.1.18-rc.
|
|
31
|
+
"@owlmeans/api": "^0.1.18-rc.48",
|
|
32
|
+
"@owlmeans/client-config": "^0.1.18-rc.44",
|
|
33
|
+
"@owlmeans/client-context": "^0.1.18-rc.49",
|
|
34
|
+
"@owlmeans/client-route": "^0.1.18-rc.49",
|
|
35
|
+
"@owlmeans/config": "^0.1.18-rc.44",
|
|
36
|
+
"@owlmeans/context": "^0.1.18-rc.34",
|
|
37
|
+
"@owlmeans/entrypoint": "^0.1.18-rc.41",
|
|
38
|
+
"@owlmeans/error": "^0.1.18-rc.38",
|
|
39
|
+
"@owlmeans/log": "^0.1.18-rc.2",
|
|
40
|
+
"@owlmeans/route": "^0.1.18-rc.35",
|
|
41
41
|
"ajv-formats": "^3.0.1",
|
|
42
42
|
"qs": "^6.16.0"
|
|
43
43
|
},
|
package/src/entrypoint.ts
CHANGED
|
@@ -2,9 +2,9 @@ import type { ClientEntrypoint, ClientEntrypointOptions, EntrypointRef, RefedEnt
|
|
|
2
2
|
import type { AbstractRequest, CommonEntrypoint } from '@owlmeans/entrypoint'
|
|
3
3
|
import { validate } from './utils/entrypoint.js'
|
|
4
4
|
import { route } from '@owlmeans/client-route'
|
|
5
|
-
import {
|
|
5
|
+
import { apiCallOf } from './utils/handler.js'
|
|
6
6
|
import { AppType } from '@owlmeans/context'
|
|
7
|
-
import {
|
|
7
|
+
import { clientRequestHelper } from './helper.js'
|
|
8
8
|
|
|
9
9
|
/** Attach client behaviour to an entrypoint already materialized from a protocol. */
|
|
10
10
|
export const bindMaterializedEntrypoint = <T, R extends AbstractRequest = AbstractRequest>(
|
|
@@ -16,6 +16,7 @@ export const bindMaterializedEntrypoint = <T, R extends AbstractRequest = Abstra
|
|
|
16
16
|
|
|
17
17
|
let _entrypoint: ClientEntrypoint<T, R>
|
|
18
18
|
|
|
19
|
+
const apiHandler: RefedEntrypointHandler<T, R> = ref => apiCallOf(ref).apiHandler
|
|
19
20
|
const _handler = handler ?? (arg.route.route.type === AppType.Backend ? apiHandler : undefined)
|
|
20
21
|
|
|
21
22
|
assertExplicitHandler(arg.route.route.type, handler)
|
|
@@ -29,7 +30,7 @@ export const bindMaterializedEntrypoint = <T, R extends AbstractRequest = Abstra
|
|
|
29
30
|
_entrypoint.gateParams = opts?.gateParams ?? arg.gateParams
|
|
30
31
|
|
|
31
32
|
_entrypoint.url = ((req?: Partial<R>, urlOpts?: { absolute?: boolean }) =>
|
|
32
|
-
entrypointUrl
|
|
33
|
+
apiCallOf(entrypointHandle).entrypointUrl(req as never, urlOpts)) as ClientEntrypoint<T, R>['url']
|
|
33
34
|
|
|
34
35
|
// An entrypoint carrying a renderer IS a screen: it is addressed by URL, never called over the
|
|
35
36
|
// wire. Saying so here turns what used to be a URL-shaped answer from `call()` into a report.
|
|
@@ -39,7 +40,7 @@ export const bindMaterializedEntrypoint = <T, R extends AbstractRequest = Abstra
|
|
|
39
40
|
`Entrypoint ${_entrypoint.alias} renders a screen - address it with url() instead of call()/invoke()`
|
|
40
41
|
)
|
|
41
42
|
})
|
|
42
|
-
: apiInvoke
|
|
43
|
+
: apiCallOf(entrypointHandle).apiInvoke(opts)) as ClientEntrypoint<T, R>['invoke']
|
|
43
44
|
|
|
44
45
|
_entrypoint.call = (async (req?: Partial<R>) =>
|
|
45
46
|
(await _entrypoint.invoke(req)).value) as ClientEntrypoint<T, R>['call']
|
|
@@ -48,7 +49,7 @@ export const bindMaterializedEntrypoint = <T, R extends AbstractRequest = Abstra
|
|
|
48
49
|
if (entrypointHandle.ref == null) {
|
|
49
50
|
throw SyntaxError(`Try to request uninitialized entrypoint ${JSON.stringify(arg)}`)
|
|
50
51
|
}
|
|
51
|
-
const _request = provideRequest(entrypointHandle.ref.alias, entrypointHandle.ref.path()) as R
|
|
52
|
+
const _request = clientRequestHelper.provideRequest(entrypointHandle.ref.alias, entrypointHandle.ref.path()) as R
|
|
52
53
|
|
|
53
54
|
request != null && Object.entries(request).forEach(([key, value]) => {
|
|
54
55
|
_request[key as keyof R] = value
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AbstractRequest } from '@owlmeans/entrypoint'
|
|
2
|
+
import type { JSONSchemaType } from 'ajv'
|
|
3
|
+
|
|
4
|
+
/** Builds and shapes the requests a client sends. */
|
|
5
|
+
export interface ClientRequestHelper {
|
|
6
|
+
/** A minimal cancellable `AbstractRequest` for an entrypoint alias at a path. */
|
|
7
|
+
provideRequest: <T extends {} = {}>(alias: string, path: string) => AbstractRequest<T>
|
|
8
|
+
/** Keeps only the non-null keys of `object` the AJV schema declares. */
|
|
9
|
+
pickPerSchema: <T, R>(object: T, schema: JSONSchemaType<R>) => Partial<R>
|
|
10
|
+
}
|
package/src/helper.ts
CHANGED
|
@@ -1,31 +1,36 @@
|
|
|
1
|
-
import type { RefedEntrypointHandler } from './types.js'
|
|
2
1
|
import type { AbstractRequest } from '@owlmeans/entrypoint'
|
|
3
2
|
import type { JSONSchemaType } from "ajv"
|
|
3
|
+
import type { ClientRequestHelper } from './helper/types.js'
|
|
4
4
|
|
|
5
|
-
export const
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
export const createClientRequestHelper = (): ClientRequestHelper => {
|
|
6
|
+
const provideRequest = <T extends {} = {}>(alias: string, path: string): AbstractRequest<T> => {
|
|
7
|
+
const request = {
|
|
8
|
+
alias,
|
|
9
|
+
params: {},
|
|
10
|
+
headers: {},
|
|
11
|
+
query: {},
|
|
12
|
+
path,
|
|
13
|
+
canceled: false,
|
|
14
|
+
cancel: () => request.canceled = true
|
|
15
|
+
}
|
|
8
16
|
|
|
9
|
-
|
|
10
|
-
const request = {
|
|
11
|
-
alias,
|
|
12
|
-
params: {},
|
|
13
|
-
headers: {},
|
|
14
|
-
query: {},
|
|
15
|
-
path,
|
|
16
|
-
canceled: false,
|
|
17
|
-
cancel: () => request.canceled = true
|
|
17
|
+
return request
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
const pickPerSchema = <T, R>(object: T, schema: JSONSchemaType<R>): Partial<R> =>
|
|
21
|
+
Object.keys(schema.properties).reduce(
|
|
22
|
+
(acc, key) => {
|
|
23
|
+
if (object[key as keyof T] != null) {
|
|
24
|
+
acc[key as keyof R] = object[key as keyof T] as unknown as R[keyof R]
|
|
25
|
+
}
|
|
26
|
+
return acc
|
|
27
|
+
}, {} as Partial<R>
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
return { provideRequest, pickPerSchema }
|
|
21
31
|
}
|
|
22
32
|
|
|
23
|
-
export const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
acc[key as keyof R] = object[key as keyof T] as unknown as R[keyof R]
|
|
28
|
-
}
|
|
29
|
-
return acc
|
|
30
|
-
}, {} as Partial<R>
|
|
31
|
-
)
|
|
33
|
+
export const clientRequestHelper = createClientRequestHelper()
|
|
34
|
+
|
|
35
|
+
/** @deprecated compat:factory-refactor — use `clientRequestHelper.provideRequest(…)` */
|
|
36
|
+
export const provideRequest = <T extends {} = {}>(alias: string, path: string): AbstractRequest<T> => clientRequestHelper.provideRequest<T>(alias, path)
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
|
|
2
2
|
export type * from './types.js'
|
|
3
|
+
export type * from './helper/types.js'
|
|
3
4
|
export * from './errors.js'
|
|
4
5
|
export * from './failure.js'
|
|
5
6
|
export * from './consts.js'
|
|
6
7
|
export * from './protocol.js'
|
|
7
|
-
export {
|
|
8
|
+
export { clientRequestHelper, createClientRequestHelper, provideRequest } from './helper.js'
|
|
9
|
+
export { stab } from './stab.js'
|
package/src/stab.ts
ADDED
package/src/types.ts
CHANGED
|
@@ -31,12 +31,7 @@ export interface ClientEntrypoint<T = {}, R extends ClientRequest = ClientReques
|
|
|
31
31
|
* its request and reply types are read directly from the declaration and cannot be replaced at a
|
|
32
32
|
* call site.
|
|
33
33
|
*/
|
|
34
|
-
export
|
|
35
|
-
Omit<ClientEntrypoint, 'call' | 'invoke' | 'url' | 'validate' | 'request'>
|
|
36
|
-
& RegisteredEntrypoint<RequestOf<Protocol>, import('@owlmeans/entrypoint').ResponseOf<Protocol>>
|
|
37
|
-
& {
|
|
38
|
-
readonly protocol: Protocol
|
|
39
|
-
}
|
|
34
|
+
export interface ClientProtocolEntrypoint<Protocol extends EntrypointProtocolDeclaration> extends Omit<ClientEntrypoint, 'call' | 'invoke' | 'url' | 'validate' | 'request'>, RegisteredEntrypoint<RequestOf<Protocol>, import('@owlmeans/entrypoint').ResponseOf<Protocol>> { readonly protocol: Protocol }
|
|
40
35
|
|
|
41
36
|
export interface EntrypointCall<T, Req extends ClientRequest = ClientRequest> {
|
|
42
37
|
<Type extends T, R extends Req = Req>(req?: Partial<R>): Promise<Type>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { AbstractRequest, EntrypointHandler } from '@owlmeans/entrypoint'
|
|
2
|
+
import type { ClientEntrypointOptions, EntrypointInvoke, EntrypointUrlOptions } from '../../types.js'
|
|
3
|
+
|
|
4
|
+
/** How a client entrypoint reaches its backend: the handler, the round trip and the address. */
|
|
5
|
+
export interface ApiCallHelper<T, R extends AbstractRequest = AbstractRequest> {
|
|
6
|
+
/**
|
|
7
|
+
* The handler that carries the entrypoint's call: the transport service bound to its route's
|
|
8
|
+
* protocol, else the API client of the web service its route answers on.
|
|
9
|
+
*/
|
|
10
|
+
apiHandler: EntrypointHandler
|
|
11
|
+
/** The round trip behind `invoke()`: builds the request, validates it on demand and notifies failure observers. */
|
|
12
|
+
apiInvoke: (opts?: ClientEntrypointOptions) => EntrypointInvoke<T, R>
|
|
13
|
+
/** The address behind `url()`: `:params` filled in, the query appended, absolute when the route is not local. */
|
|
14
|
+
entrypointUrl: (req?: Partial<R>, opts?: EntrypointUrlOptions) => Promise<string>
|
|
15
|
+
}
|
package/src/utils/handler.ts
CHANGED
|
@@ -3,62 +3,60 @@ import { DEFAULT_KEY } from '@owlmeans/client-config'
|
|
|
3
3
|
import { type AbstractRequest, type EntrypointHandler, type EntrypointTransport, EntrypointOutcome, provideResponse, transportAlias } from '@owlmeans/entrypoint'
|
|
4
4
|
import type { ClientEntrypoint, EntrypointInvoke, EntrypointUrlOptions, ClientEntrypointOptions, EntrypointRef, ClientRequest, EntrypointFailureService } from '../types.js'
|
|
5
5
|
import { validate } from './entrypoint.js'
|
|
6
|
-
import {
|
|
6
|
+
import { clientRouteHelper } from '@owlmeans/client-route'
|
|
7
7
|
import { PARAM, RouteMethod, RouteProtocols } from '@owlmeans/route'
|
|
8
8
|
import { stringify } from 'qs'
|
|
9
|
-
import { assertContext } from '@owlmeans/context'
|
|
9
|
+
import { assertContext, memoHelper } from '@owlmeans/context'
|
|
10
10
|
import { makeSecurityHelper } from '@owlmeans/config'
|
|
11
11
|
import { ENTRYPOINT_FAILURE_SERVICE } from '../consts.js'
|
|
12
12
|
import { logger } from '@owlmeans/log'
|
|
13
13
|
import type { Config, Context } from './types.local.js'
|
|
14
|
+
import type { ApiCallHelper } from './handler/types.js'
|
|
14
15
|
|
|
15
16
|
const log = logger('client-entrypoint')
|
|
16
17
|
|
|
18
|
+
export const makeApiCallHelper = <T, R extends AbstractRequest = AbstractRequest>(
|
|
19
|
+
ref: EntrypointRef<T, R>
|
|
20
|
+
): ApiCallHelper<T, R> => {
|
|
21
|
+
const apiHandler: EntrypointHandler = async (req, res) => {
|
|
22
|
+
const location = `client-entrypoint:api-handler:${ref.ref?.alias}`
|
|
23
|
+
const context = assertContext<Config, Context>(ref.ref?.ctx as Context, location)
|
|
17
24
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const location = `client-entrypoint:api-handler:${ref.ref?.alias}`
|
|
22
|
-
const context = assertContext<Config, Context>(ref.ref?.ctx as Context, location)
|
|
23
|
-
|
|
24
|
-
if (context.cfg.webService == null) {
|
|
25
|
-
throw new SyntaxError('No webService provided')
|
|
26
|
-
}
|
|
25
|
+
if (context.cfg.webService == null) {
|
|
26
|
+
throw new SyntaxError('No webService provided')
|
|
27
|
+
}
|
|
27
28
|
|
|
28
|
-
|
|
29
|
+
const ep = context.entrypoint<ClientEntrypoint>(req.alias)
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
// A route names the protocol it answers on. Whatever is bound under that protocol takes the
|
|
32
|
+
// call, so a consumer writes `ep.call(...)` without learning which transport ran.
|
|
33
|
+
const transport = transportAlias(ep.route.route.protocol)
|
|
34
|
+
if (context.hasService(transport)) {
|
|
35
|
+
req.path = ep.path()
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
return context.service<EntrypointTransport>(transport).handle(req, res)
|
|
38
|
+
}
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
// Which web client carries this call is decided by the service the route answers on — the one it
|
|
41
|
+
// names, or the one the context picks for its app type when it names none.
|
|
42
|
+
const route = ep.service()
|
|
42
43
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
const alias: string | undefined = typeof context.cfg.webService === 'string'
|
|
45
|
+
? context.cfg.webService
|
|
46
|
+
: context.cfg.webService[route.service] ?? context.cfg.webService[DEFAULT_KEY]
|
|
46
47
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
if (alias == null) {
|
|
49
|
+
throw new SyntaxError(`Can't cast web service alias for ${ep.alias} entrypoint`)
|
|
50
|
+
}
|
|
50
51
|
|
|
51
|
-
|
|
52
|
+
const service: ApiClient = context.service(alias)
|
|
52
53
|
|
|
53
|
-
|
|
54
|
+
req.path = ep.path()
|
|
54
55
|
|
|
55
|
-
|
|
56
|
-
}
|
|
56
|
+
return service.handler(req, res as any)
|
|
57
|
+
}
|
|
57
58
|
|
|
58
|
-
|
|
59
|
-
T, R extends AbstractRequest = AbstractRequest
|
|
60
|
-
>(ref: EntrypointRef<T, R>, opts?: ClientEntrypointOptions) => EntrypointInvoke<T, R> =
|
|
61
|
-
(ref, opts) => (async (req) => {
|
|
59
|
+
const apiInvoke = (opts?: ClientEntrypointOptions): EntrypointInvoke<T, R> => (async (req: Partial<R> | undefined) => {
|
|
62
60
|
const ep = ref.ref
|
|
63
61
|
if (ep == null) {
|
|
64
62
|
throw new SyntaxError('Try to make API call before the entrypoint is created')
|
|
@@ -108,7 +106,7 @@ export const apiInvoke: <
|
|
|
108
106
|
throw new SyntaxError(`Use entrypoint ${ep.alias} without context`)
|
|
109
107
|
}
|
|
110
108
|
try {
|
|
111
|
-
await apiHandler(
|
|
109
|
+
await apiHandler(request, reply)
|
|
112
110
|
if (reply.error != null) throw reply.error
|
|
113
111
|
} catch (error) {
|
|
114
112
|
if (ctx.hasService(ENTRYPOINT_FAILURE_SERVICE)) {
|
|
@@ -121,41 +119,49 @@ export const apiInvoke: <
|
|
|
121
119
|
return { value: reply.value ?? null, outcome: reply.outcome ?? EntrypointOutcome.Ok }
|
|
122
120
|
}) as EntrypointInvoke<any>
|
|
123
121
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
122
|
+
const entrypointUrl = async (req?: Partial<R>, opts?: EntrypointUrlOptions): Promise<string> => {
|
|
123
|
+
const ep = ref.ref
|
|
124
|
+
if (ep == null) {
|
|
125
|
+
throw new SyntaxError('Try to make URL before the entrypoint is created')
|
|
126
|
+
}
|
|
127
|
+
const ctx = ep.ctx
|
|
128
|
+
if (ctx == null) {
|
|
129
|
+
throw new SyntaxError(`No context provided in entrypointUrl for ${ep.alias} entrypoint`)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// The base is left off here: an in-service URL is addressed relative to it, and the absolute
|
|
133
|
+
// branch below has `makeUrl` prepend it.
|
|
134
|
+
const epPath = ep.path()
|
|
135
|
+
const pathParams = clientRouteHelper.extractParams(epPath)
|
|
136
|
+
let path = pathParams.reduce((p, param) => {
|
|
137
|
+
return p.replace(`${PARAM}${param}`, `${req?.params?.[param as keyof typeof req.params]}`)
|
|
138
|
+
}, epPath) + (req?.query != null ? `?${stringify(req?.query)}` : '')
|
|
139
|
+
|
|
140
|
+
// A socket address is always absolute, whoever owns the route. `new WebSocket(path)` resolves a
|
|
141
|
+
// relative value against the PAGE's origin, which in a split deployment is the web host and not
|
|
142
|
+
// the service that answers the upgrade — so the handshake goes somewhere that never speaks it
|
|
143
|
+
// and dies on a gateway timeout. Only a same-origin HTTP route benefits from staying relative.
|
|
144
|
+
const socket = ep.route.route.protocol === RouteProtocols.SOCKET
|
|
145
|
+
|
|
146
|
+
// Locality is a question about the RESOLVED service, not about what the declaration happens to
|
|
147
|
+
// name: a route that names no service belongs to the asking context, and addressing it absolutely
|
|
148
|
+
// would turn in-app navigation into a full page load.
|
|
149
|
+
if (socket || !ep.isLocal() || opts?.absolute === true) {
|
|
150
|
+
const helper = makeSecurityHelper(ctx)
|
|
151
|
+
path = helper.makeUrl(
|
|
152
|
+
ep.address(), path, { host: req?.host, base: req?.base, forceUnsecure: req?.unsecure }
|
|
153
|
+
)
|
|
154
|
+
}
|
|
135
155
|
|
|
136
|
-
|
|
137
|
-
// branch below has `makeUrl` prepend it.
|
|
138
|
-
const epPath = ep.path()
|
|
139
|
-
const pathParams = extractParams(epPath)
|
|
140
|
-
let path = pathParams.reduce((p, param) => {
|
|
141
|
-
return p.replace(`${PARAM}${param}`, `${req?.params?.[param as keyof typeof req.params]}`)
|
|
142
|
-
}, epPath) + (req?.query != null ? `?${stringify(req?.query)}` : '')
|
|
143
|
-
|
|
144
|
-
// A socket address is always absolute, whoever owns the route. `new WebSocket(path)` resolves a
|
|
145
|
-
// relative value against the PAGE's origin, which in a split deployment is the web host and not
|
|
146
|
-
// the service that answers the upgrade — so the handshake goes somewhere that never speaks it
|
|
147
|
-
// and dies on a gateway timeout. Only a same-origin HTTP route benefits from staying relative.
|
|
148
|
-
const socket = ep.route.route.protocol === RouteProtocols.SOCKET
|
|
149
|
-
|
|
150
|
-
// Locality is a question about the RESOLVED service, not about what the declaration happens to
|
|
151
|
-
// name: a route that names no service belongs to the asking context, and addressing it absolutely
|
|
152
|
-
// would turn in-app navigation into a full page load.
|
|
153
|
-
if (socket || !ep.isLocal() || opts?.absolute === true) {
|
|
154
|
-
const helper = makeSecurityHelper(ctx)
|
|
155
|
-
path = helper.makeUrl(
|
|
156
|
-
ep.address(), path, { host: req?.host, base: req?.base, forceUnsecure: req?.unsecure }
|
|
157
|
-
)
|
|
156
|
+
return path
|
|
158
157
|
}
|
|
159
158
|
|
|
160
|
-
return
|
|
159
|
+
return { apiHandler, apiInvoke, entrypointUrl }
|
|
161
160
|
}
|
|
161
|
+
|
|
162
|
+
export const apiCallOf = memoHelper.oncePer(makeApiCallHelper)
|
|
163
|
+
|
|
164
|
+
/** @deprecated compat:factory-refactor — use `makeApiCallHelper(ref).entrypointUrl(…)` */
|
|
165
|
+
export const entrypointUrl = <T, R extends ClientRequest = ClientRequest>(
|
|
166
|
+
ref: EntrypointRef<T, R>, req?: Partial<R>, opts?: EntrypointUrlOptions
|
|
167
|
+
): Promise<string> => makeApiCallHelper(ref).entrypointUrl(req, opts)
|
package/src/utils/index.ts
CHANGED