@owlmeans/client-entrypoint 0.1.18-rc.12 → 0.1.18-rc.14
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 +2 -2
- package/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/client-entrypoint/SKILL.md +73 -8
- package/build/entrypoint.d.ts.map +1 -1
- package/build/errors.d.ts.map +1 -1
- package/build/errors.js.map +1 -1
- package/build/helper.d.ts.map +1 -1
- package/build/index.d.ts +1 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -0
- package/build/index.js.map +1 -1
- package/build/protocol.d.ts +9 -0
- package/build/protocol.d.ts.map +1 -0
- package/build/protocol.js +15 -0
- package/build/protocol.js.map +1 -0
- package/build/types.d.ts +10 -2
- package/build/types.d.ts.map +1 -1
- package/build/utils/entrypoint.d.ts.map +1 -1
- package/build/utils/handler.d.ts.map +1 -1
- package/build/utils/handler.js +12 -3
- package/build/utils/handler.js.map +1 -1
- package/package.json +10 -10
- package/src/index.ts +1 -0
- package/src/protocol.ts +38 -0
- package/src/types.ts +17 -2
- package/src/utils/handler.ts +13 -3
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ Client-side entrypoint system: elevates route definitions into API-calling `Clie
|
|
|
15
15
|
## Installation
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
|
-
bun add @owlmeans/client-entrypoint
|
|
18
|
+
bun add @owlmeans/client-entrypoint@^0.1.18-rc.12
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
## Usage
|
|
@@ -110,7 +110,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
|
|
|
110
110
|
your project's skill store (`.agents/skills/`):
|
|
111
111
|
|
|
112
112
|
```sh
|
|
113
|
-
npx @owlmeans/agent-skills
|
|
113
|
+
npx @owlmeans/agent-skills@^0.1.18-rc.13
|
|
114
114
|
```
|
|
115
115
|
|
|
116
116
|
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-09-
|
|
4
|
+
"version": "0.1.18-rc.14",
|
|
5
|
+
"generatedAt": "2026-09-10T18:54:42.491Z",
|
|
6
6
|
"canonicalRepo": "https://github.com/owlmeans/common",
|
|
7
7
|
"entries": [
|
|
8
8
|
{
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: client-entrypoint
|
|
3
|
-
description: How to use @owlmeans/client-entrypoint —
|
|
3
|
+
description: How to use @owlmeans/client-entrypoint — binding immutable protocols to client call/invoke/url modules, React screen binding, and legacy elevation. Auto-invoked when importing client entrypoint helpers.
|
|
4
4
|
user-invocable: false
|
|
5
5
|
---
|
|
6
6
|
<!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
|
|
@@ -8,36 +8,70 @@ user-invocable: false
|
|
|
8
8
|
# @owlmeans/client-entrypoint
|
|
9
9
|
|
|
10
10
|
**Layer:** Client
|
|
11
|
-
**Install:** `"@owlmeans/client-entrypoint": "^0.1.18-rc.
|
|
11
|
+
**Install:** `"@owlmeans/client-entrypoint": "^0.1.18-rc.14"` in `dependencies`
|
|
12
12
|
|
|
13
13
|
## Key Exports
|
|
14
14
|
|
|
15
15
|
| Export | Description |
|
|
16
16
|
|--------|-------------|
|
|
17
|
+
| `bind(protocol, opts?)` | Materialize one shared protocol as a typed client entrypoint |
|
|
18
|
+
| `bindAll(tree)` | Flatten and bind a protocol tree |
|
|
19
|
+
| `bindScreen(protocol, handler, opts?)` | Bind a frontend protocol to its renderer |
|
|
20
|
+
| `ClientProtocolEntrypoint<P>` | The client module whose request/reply types come from `P` |
|
|
17
21
|
| `ClientEntrypoint<T, R>` | Client entrypoint interface — `call`, `invoke`, `url`, `validate`, `request` |
|
|
18
22
|
| `entrypoint(arg, handler?, opts?)` | Build a client entrypoint from a route model or an existing declaration |
|
|
19
23
|
| `elevate(entrypoints, alias, handler?, opts?)` | Make a declared entrypoint client-callable, optionally attaching a screen |
|
|
20
24
|
| `EntrypointCall` / `EntrypointInvoke` / `EntrypointUrl` | The typed signatures of the three verbs |
|
|
21
25
|
| `EntrypointReply<T>` | `{ value, outcome }` — what `invoke` resolves to |
|
|
22
26
|
| `EntrypointRef` / `RefedEntrypointHandler` | Handler reference pattern |
|
|
27
|
+
| `ClientEntrypointOptions` | What `entrypoint`/`elevate` accept — `guards`, `filter`, `gate`, `gateParams`, `routeOptions`, `validateOnCall` |
|
|
28
|
+
| `ClientRequest<T>` / `EntrypointFilter` / `EntrypointUrlOptions` | The request shape, the validator signature, and `{ absolute }` |
|
|
23
29
|
| `provideRequest(alias, path)` / `pickPerSchema(obj, schema)` | Request construction helpers |
|
|
30
|
+
| `stab` | A handler that renders nothing — for an entrypoint that exists only to be addressed |
|
|
24
31
|
| `ClientEntrypointError` / `ClientValidationError` | Typed client-side failures |
|
|
25
32
|
|
|
26
33
|
## Subpath Exports
|
|
27
34
|
|
|
28
|
-
- `./utils` — `entrypointUrl(ref, req?, opts?)`, `apiInvoke(ref, opts?)`, `apiHandler(ref)`,
|
|
35
|
+
- `./utils` — `entrypointUrl(ref, req?, opts?)`, `apiInvoke(ref, opts?)`, `apiHandler(ref)`,
|
|
36
|
+
`validate(ref)`, `normalizeHelperParams(handler?, opts?)`, and the re-exported
|
|
37
|
+
`makeBasicEntrypoint` / `isEntrypoint`
|
|
29
38
|
|
|
30
39
|
## Usage
|
|
31
40
|
|
|
32
|
-
|
|
41
|
+
New protocol-based applications bind their shared declarations and let lookup infer the contract:
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
import { bindAll, bindScreen, handler } from '@owlmeans/client-entrypoint'
|
|
45
|
+
import { item, web } from 'project-common'
|
|
46
|
+
|
|
47
|
+
const entrypoints = bindAll(item)
|
|
48
|
+
entrypoints.push(bindScreen(web.items, handler(ItemsScreen)))
|
|
49
|
+
|
|
50
|
+
const result = await context.entrypoint(item.get).call({ params: { id } })
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
`bind`/`bindAll` make backend protocols callable; `bindScreen` is only for frontend protocols.
|
|
54
|
+
The protocol stays immutable and the local module receives its own context and handler state.
|
|
55
|
+
|
|
56
|
+
Most legacy app code uses `elevate()` from `@owlmeans/web-client` (which builds on this). Use the
|
|
57
|
+
legacy generic only while working on a surface that has not migrated:
|
|
33
58
|
|
|
34
59
|
```typescript
|
|
35
60
|
import type { ClientEntrypoint } from '@owlmeans/client-entrypoint'
|
|
36
61
|
```
|
|
37
62
|
|
|
38
63
|
Client-side callability is an **explicit opt-in**: a declaration only becomes callable from a client
|
|
39
|
-
once a bare client `elevate` (or `celevate` on the server side) has been
|
|
40
|
-
|
|
64
|
+
once `bind`/`bindAll`, or a bare legacy client `elevate` (or `celevate` on the server side), has been
|
|
65
|
+
applied to it. Elevating is
|
|
66
|
+
idempotent, and guards passed at elevation are added to the ones the declaration already carries;
|
|
67
|
+
`filter`, `gate` and `gateParams` passed at elevation replace what was declared. An alias no
|
|
68
|
+
entrypoint in the list carries throws `SyntaxError`.
|
|
69
|
+
|
|
70
|
+
Both `entrypoint()` and `elevate()` accept the options in the handler slot when there is no handler,
|
|
71
|
+
and a bare boolean where the options go means `{ validateOnCall }`. With `validateOnCall`, every call is
|
|
72
|
+
checked against the declaration's `filter` (ajv, with formats) before it leaves, and a mismatch
|
|
73
|
+
throws `ClientValidationError` naming the offending path. A **backend** entrypoint given a handler
|
|
74
|
+
throws `SyntaxError` — a backend alias is opted in by elevating it with nothing.
|
|
41
75
|
|
|
42
76
|
## The three verbs
|
|
43
77
|
|
|
@@ -72,9 +106,40 @@ const url = await context.entrypoint<ClientEntrypoint<string>>(HOME).url({}, { a
|
|
|
72
106
|
|
|
73
107
|
This is the preferred pattern for redirect URIs and navigation targets instead of manual
|
|
74
108
|
`window.location` concatenation. The underlying helper is `entrypointUrl(ref, req?, opts?)` from
|
|
75
|
-
`./utils`, which packages building their own addressing
|
|
109
|
+
`./utils`, which packages building their own addressing call directly.
|
|
110
|
+
|
|
111
|
+
Two cases are absolute whatever the caller asks for. A route that resolves to **another service** is
|
|
112
|
+
one — an in-app target addressed absolutely would turn navigation into a full page load, and a
|
|
113
|
+
foreign one addressed relatively would hit this app. A **socket** route is the other: `new
|
|
114
|
+
WebSocket(path)` resolves a relative value against the page's origin, which in a split deployment is
|
|
115
|
+
the web host rather than the service that answers the upgrade.
|
|
116
|
+
|
|
117
|
+
## Which carrier takes the call
|
|
118
|
+
|
|
119
|
+
`apiHandler` checks `cfg.webService` **before** it looks at anything else and throws
|
|
120
|
+
`SyntaxError('No webService provided')` when the field is absent. That check is unconditional, so
|
|
121
|
+
every client entrypoint needs an API client configured — including one that is carried by a queue
|
|
122
|
+
and never touches an API client at all.
|
|
123
|
+
|
|
124
|
+
Past that check the route's protocol decides. When a service is registered under that protocol's
|
|
125
|
+
transport alias, it takes the call, so a queue-carried entrypoint and an HTTP-carried one are the
|
|
126
|
+
same `call(...)` at the call site.
|
|
127
|
+
|
|
128
|
+
Otherwise the carrier is the API client `cfg.webService` names. A string names one for everything; a
|
|
129
|
+
record is looked up by the alias of the service the route resolves to, then by `DEFAULT_KEY`, and a
|
|
130
|
+
record carrying neither throws ``SyntaxError("Can't cast web service alias for <alias> entrypoint")``
|
|
131
|
+
— read that as "this config names API clients, but none of them for this target service". See
|
|
132
|
+
[[client-config]] for the field itself.
|
|
76
133
|
|
|
77
134
|
## Depends On
|
|
78
135
|
|
|
79
|
-
- `@owlmeans/entrypoint`, `@owlmeans/client-route`, `@owlmeans/client-context
|
|
136
|
+
- `@owlmeans/entrypoint`, `@owlmeans/client-route`, `@owlmeans/client-context`,
|
|
137
|
+
`@owlmeans/client-config` (`webService` resolution), `@owlmeans/route`, `@owlmeans/context`,
|
|
138
|
+
`@owlmeans/error`
|
|
80
139
|
- `@owlmeans/api` (the HTTP carrier), `@owlmeans/config` (`makeSecurityHelper` for absolute URLs)
|
|
140
|
+
- `qs` (query serialization), `ajv-formats`; `ajv` is a peer dependency
|
|
141
|
+
|
|
142
|
+
## Related
|
|
143
|
+
|
|
144
|
+
- [[client]] — the React layer that navigates through `url()` and renders elevated screens
|
|
145
|
+
- [[client-config]] — `webService`, which decides the carrier
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entrypoint.d.ts","sourceRoot":"","sources":["../src/entrypoint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AAC9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAiB,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAClH,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAK7E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAGjD,eAAO,MAAM,UAAU,GAAI,CAAC,EAAE,CAAC,SAAS,eAAe,GAAG,eAAe,
|
|
1
|
+
{"version":3,"file":"entrypoint.d.ts","sourceRoot":"","sources":["../src/entrypoint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AAC9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAiB,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAClH,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAK7E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAGjD,eAAO,MAAM,UAAU,GAAI,CAAC,EAAE,CAAC,SAAS,eAAe,GAAG,eAAe,OAClE,gBAAgB,GAAG,gBAAgB,GAAG,UAAU,YAC3C,sBAAsB,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,uBAAuB,GAAG,OAAO,SACnE,uBAAuB,GAAG,OAAO,KACvC,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAoEvB,CAAA"}
|
package/build/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAEhD,qBAAa,qBAAsB,SAAQ,cAAc;IACvD,OAAuB,QAAQ,SAAsB;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAEhD,qBAAa,qBAAsB,SAAQ,cAAc;IACvD,OAAuB,QAAQ,SAAsB;IAErD,YAAY,OAAO,EAAE,MAAM,EAE1B;CACF;AAED,qBAAa,qBAAsB,SAAQ,qBAAqB;IAC9D,OAAuB,QAAQ,SAAgD;IAE/E,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF"}
|
package/build/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAEhD,MAAM,OAAO,qBAAsB,SAAQ,cAAc;IAChD,MAAM,CAAU,QAAQ,GAAG,mBAAmB,CAAA;IAErD,YAAY,OAAe;QACzB,KAAK,CAAC,qBAAqB,CAAC,QAAQ,EAAE,iBAAiB,OAAO,EAAE,CAAC,CAAA;IACnE,CAAC
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAEhD,MAAM,OAAO,qBAAsB,SAAQ,cAAc;IAChD,MAAM,CAAU,QAAQ,GAAG,mBAAmB,CAAA;IAErD,YAAY,OAAe;QACzB,KAAK,CAAC,qBAAqB,CAAC,QAAQ,EAAE,iBAAiB,OAAO,EAAE,CAAC,CAAA;IACnE,CAAC;CACF;AAED,MAAM,OAAO,qBAAsB,SAAQ,qBAAqB;IACvD,MAAM,CAAU,QAAQ,GAAG,GAAG,qBAAqB,CAAC,QAAQ,YAAY,CAAA;IAE/E,YAAY,OAAe;QACzB,KAAK,CAAC,cAAc,OAAO,EAAE,CAAC,CAAA;QAC9B,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC,QAAQ,CAAA;IAC5C,CAAC;CACF;AAGD,cAAc,CAAC,kBAAkB,CAAC,qBAAqB,CAAC,CAAA;AACxD,cAAc,CAAC,kBAAkB,CAAC,qBAAqB,CAAC,CAAA"}
|
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,gBAAgB,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAEnG,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAE7E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,KAAK,CAAA;AAEzC;;;;;;GAMG;AACH,eAAO,MAAM,OAAO,GAAI,CAAC,GAAG,EAAE,EAAE,CAAC,SAAS,eAAe,GAAG,eAAe,
|
|
1
|
+
{"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAEnG,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAE7E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,KAAK,CAAA;AAEzC;;;;;;GAMG;AACH,eAAO,MAAM,OAAO,GAAI,CAAC,GAAG,EAAE,EAAE,CAAC,SAAS,eAAe,GAAG,eAAe,eAC5D,CAAC,gBAAgB,GAAG,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SACnD,MAAM,YACH,sBAAsB,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,uBAAuB,GAAG,OAAO,SACnE,uBAAuB,GAAG,OAAO,KACvC,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAWxB,CAAA;AAED,eAAO,MAAM,IAAI,EAAE,sBAAsB,CAAC,EAAE,CAE3C,CAAA;AAED,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,EAAE,GAAG,EAAE,SAAS,MAAM,QAAQ,MAAM,KAAG,eAAe,CAAC,CAAC,CAYhG,CAAA;AAED,eAAO,MAAM,aAAa,GAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,cAAc,CAAC,CAAC,CAAC,KAAG,OAAO,CAAC,CAAC,CAQjF,CAAA"}
|
package/build/index.d.ts
CHANGED
package/build/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,aAAa,CAAA;AAC3B,mBAAmB,YAAY,CAAA;AAC/B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,aAAa,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,aAAa,CAAA;AAC3B,mBAAmB,YAAY,CAAA;AAC/B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA"}
|
package/build/index.js
CHANGED
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,aAAa,CAAA;AAE3B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,aAAa,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,aAAa,CAAA;AAE3B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { EntrypointProtocolDeclaration, EntrypointTree } from '@owlmeans/entrypoint';
|
|
2
|
+
import type { ClientEntrypointOptions, ClientProtocolEntrypoint, RefedEntrypointHandler } from './types.js';
|
|
3
|
+
/** Bind a shared protocol to the client context without changing the declaration itself. */
|
|
4
|
+
export declare const bind: <Protocol extends EntrypointProtocolDeclaration>(protocol: Protocol, options?: ClientEntrypointOptions) => ClientProtocolEntrypoint<Protocol>;
|
|
5
|
+
/** Materialize every protocol in an exported declaration tree for a browser context. */
|
|
6
|
+
export declare const bindAll: (tree: EntrypointTree) => ClientProtocolEntrypoint<EntrypointProtocolDeclaration>[];
|
|
7
|
+
/** Bind a frontend protocol to the component that renders it. */
|
|
8
|
+
export declare const bindScreen: <Protocol extends EntrypointProtocolDeclaration>(protocol: Protocol, handler: RefedEntrypointHandler, options?: ClientEntrypointOptions) => ClientProtocolEntrypoint<Protocol>;
|
|
9
|
+
//# sourceMappingURL=protocol.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,6BAA6B,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAEzF,OAAO,KAAK,EACV,uBAAuB,EAAE,wBAAwB,EAAE,sBAAsB,EAC1E,MAAM,YAAY,CAAA;AAEnB,4FAA4F;AAC5F,eAAO,MAAM,IAAI,GAAI,QAAQ,SAAS,6BAA6B,YACvD,QAAQ,YACR,uBAAuB,KAChC,wBAAwB,CAAC,QAAQ,CAOnC,CAAA;AAED,wFAAwF;AACxF,eAAO,MAAM,OAAO,SAAU,cAAc,KAAG,wBAAwB,CAAC,6BAA6B,CAAC,EACrD,CAAA;AAEjD,iEAAiE;AACjE,eAAO,MAAM,UAAU,GAAI,QAAQ,SAAS,6BAA6B,YAC7D,QAAQ,WACT,sBAAsB,YACrB,uBAAuB,KAChC,wBAAwB,CAAC,QAAQ,CAQnC,CAAA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { materializeEntrypoint, protocols } from '@owlmeans/entrypoint';
|
|
2
|
+
import { entrypoint } from './entrypoint.js';
|
|
3
|
+
/** Bind a shared protocol to the client context without changing the declaration itself. */
|
|
4
|
+
export const bind = (protocol, options) => {
|
|
5
|
+
const bound = Object.assign(entrypoint(materializeEntrypoint(protocol), options), { protocol });
|
|
6
|
+
return bound;
|
|
7
|
+
};
|
|
8
|
+
/** Materialize every protocol in an exported declaration tree for a browser context. */
|
|
9
|
+
export const bindAll = (tree) => protocols(tree).map(protocol => bind(protocol));
|
|
10
|
+
/** Bind a frontend protocol to the component that renders it. */
|
|
11
|
+
export const bindScreen = (protocol, handler, options) => {
|
|
12
|
+
const bound = Object.assign(entrypoint(materializeEntrypoint(protocol), handler, options), { protocol });
|
|
13
|
+
return bound;
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=protocol.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAEvE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAK5C,4FAA4F;AAC5F,MAAM,CAAC,MAAM,IAAI,GAAG,CAClB,QAAkB,EAClB,OAAiC,EACG,EAAE;IACtC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,CACpC,qBAAqB,CAAC,QAAQ,CAAC,EAC/B,OAAO,CACR,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAA;IAEhB,OAAO,KAA2C,CAAA;AACpD,CAAC,CAAA;AAED,wFAAwF;AACxF,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,IAAoB,EAA6D,EAAE,CACzG,SAAS,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAA;AAEjD,iEAAiE;AACjE,MAAM,CAAC,MAAM,UAAU,GAAG,CACxB,QAAkB,EAClB,OAA+B,EAC/B,OAAiC,EACG,EAAE;IACtC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,CACpC,qBAAqB,CAAC,QAAQ,CAAC,EAC/B,OAAO,EACP,OAAO,CACR,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAA;IAEhB,OAAO,KAA2C,CAAA;AACpD,CAAC,CAAA"}
|
package/build/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ClientRouteModel, ClientRouteOptions } from '@owlmeans/client-route';
|
|
2
|
-
import type { AbstractRequest, CommonEntrypoint, CommonEntrypointOptions, EntrypointHandler, EntrypointOutcome } from '@owlmeans/entrypoint';
|
|
2
|
+
import type { AbstractRequest, CommonEntrypoint, CommonEntrypointOptions, EntrypointHandler, EntrypointOutcome, EntrypointProtocolDeclaration, RegisteredEntrypoint, RequestOf } from '@owlmeans/entrypoint';
|
|
3
3
|
export interface ClientEntrypoint<T = {}, R extends ClientRequest = ClientRequest> extends CommonEntrypoint {
|
|
4
4
|
route: ClientRouteModel;
|
|
5
5
|
/**
|
|
@@ -20,6 +20,14 @@ export interface ClientEntrypoint<T = {}, R extends ClientRequest = ClientReques
|
|
|
20
20
|
validate: EntrypointFilter<R>;
|
|
21
21
|
request: (request?: Partial<R>) => R;
|
|
22
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* The context-bound client view of a protocol. Unlike the legacy `ClientEntrypoint` generic,
|
|
25
|
+
* its request and reply types are read directly from the declaration and cannot be replaced at a
|
|
26
|
+
* call site.
|
|
27
|
+
*/
|
|
28
|
+
export type ClientProtocolEntrypoint<Protocol extends EntrypointProtocolDeclaration> = Omit<ClientEntrypoint, 'call' | 'invoke' | 'url' | 'validate' | 'request'> & RegisteredEntrypoint<RequestOf<Protocol>, import('@owlmeans/entrypoint').ResponseOf<Protocol>> & {
|
|
29
|
+
readonly protocol: Protocol;
|
|
30
|
+
};
|
|
23
31
|
export interface EntrypointCall<T, Req extends ClientRequest = ClientRequest> {
|
|
24
32
|
<Type extends T, R extends Req = Req>(req?: Partial<R>): Promise<Type>;
|
|
25
33
|
}
|
|
@@ -49,7 +57,7 @@ export interface ClientEntrypointOptions extends CommonEntrypointOptions {
|
|
|
49
57
|
export interface EntrypointRef<T, R extends AbstractRequest = AbstractRequest> {
|
|
50
58
|
ref?: ClientEntrypoint<T, R>;
|
|
51
59
|
}
|
|
52
|
-
export interface RefedEntrypointHandler<T, R extends AbstractRequest = AbstractRequest> {
|
|
60
|
+
export interface RefedEntrypointHandler<T = {}, R extends AbstractRequest = AbstractRequest> {
|
|
53
61
|
(ref: EntrypointRef<T, R>): EntrypointHandler;
|
|
54
62
|
}
|
|
55
63
|
//# sourceMappingURL=types.d.ts.map
|
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,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entrypoint.d.ts","sourceRoot":"","sources":["../../src/utils/entrypoint.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAE5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AAGxE,OAAO,EAAE,UAAU,IAAI,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAKzD;;;GAGG;AACH,eAAO,MAAM,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,SAAS,eAAe,GAAG,eAAe,EAAE,GAAG,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,gBAiClG,CAAA;AAEH,eAAO,MAAM,qBAAqB,GAAI,CAAC,EAAE,CAAC,SAAS,eAAe,GAAG,eAAe,
|
|
1
|
+
{"version":3,"file":"entrypoint.d.ts","sourceRoot":"","sources":["../../src/utils/entrypoint.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAE5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AAGxE,OAAO,EAAE,UAAU,IAAI,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAKzD;;;GAGG;AACH,eAAO,MAAM,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,SAAS,eAAe,GAAG,eAAe,EAAE,GAAG,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,gBAiClG,CAAA;AAEH,eAAO,MAAM,qBAAqB,GAAI,CAAC,EAAE,CAAC,SAAS,eAAe,GAAG,eAAe,YACxE,sBAAsB,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,uBAAuB,GAAG,OAAO,SACnE,uBAAuB,GAAG,OAAO,KACvC,CAAC,sBAAsB,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,SAAS,EAAE,uBAAuB,GAAG,SAAS,CAShF,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/utils/handler.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAuB,MAAM,sBAAsB,CAAA;AAEnG,OAAO,KAAK,EAAoB,gBAAgB,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAWlJ,eAAO,MAAM,UAAU,EAAE,CACvB,CAAC,EAAE,CAAC,SAAS,eAAe,GAAG,eAAe,EAC9C,GAAG,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,iBAqC9B,CAAA;AAED,eAAO,MAAM,SAAS,EAAE,CACtB,CAAC,EAAE,CAAC,SAAS,eAAe,GAAG,eAAe,EAC9C,GAAG,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,uBAAuB,KAAK,gBAAgB,CAAC,CAAC,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/utils/handler.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAuB,MAAM,sBAAsB,CAAA;AAEnG,OAAO,KAAK,EAAoB,gBAAgB,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAWlJ,eAAO,MAAM,UAAU,EAAE,CACvB,CAAC,EAAE,CAAC,SAAS,eAAe,GAAG,eAAe,EAC9C,GAAG,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,iBAqC9B,CAAA;AAED,eAAO,MAAM,SAAS,EAAE,CACtB,CAAC,EAAE,CAAC,SAAS,eAAe,GAAG,eAAe,EAC9C,GAAG,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,uBAAuB,KAAK,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAwDvD,CAAA;AAE7B,eAAO,MAAM,aAAa,EAAE,CAC1B,CAAC,EAAE,CAAC,SAAS,aAAa,GAAG,aAAa,EAC1C,GAAG,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,oBAAoB,KAAK,OAAO,CAAC,MAAM,CAmC3F,CAAA"}
|
package/build/utils/handler.js
CHANGED
|
@@ -2,7 +2,7 @@ import { DEFAULT_KEY } from '@owlmeans/client-config';
|
|
|
2
2
|
import { EntrypointOutcome, provideResponse, transportAlias } from '@owlmeans/entrypoint';
|
|
3
3
|
import { validate } from './entrypoint.js';
|
|
4
4
|
import { extractParams } from '@owlmeans/client-route';
|
|
5
|
-
import { PARAM } from '@owlmeans/route';
|
|
5
|
+
import { PARAM, RouteMethod, RouteProtocols } from '@owlmeans/route';
|
|
6
6
|
import { stringify } from 'qs';
|
|
7
7
|
import { assertContext } from '@owlmeans/context';
|
|
8
8
|
import { makeSecurityHelper } from '@owlmeans/config';
|
|
@@ -49,7 +49,11 @@ export const apiInvoke = (ref, opts) => (async (req) => {
|
|
|
49
49
|
const request = {
|
|
50
50
|
alias: ep.alias,
|
|
51
51
|
params: req?.params ?? {},
|
|
52
|
-
body
|
|
52
|
+
// JSON transports must send a body for mutation methods even when the contract has no
|
|
53
|
+
// payload. Keeping that rule here makes every typed caller use `call({ params })`, never
|
|
54
|
+
// an SDK-specific `{ body: {} }` workaround.
|
|
55
|
+
body: req?.body ?? ([RouteMethod.POST, RouteMethod.PUT, RouteMethod.PATCH]
|
|
56
|
+
.includes(ep.route.route.method ?? RouteMethod.GET) ? {} : undefined),
|
|
53
57
|
headers: req?.headers ?? {},
|
|
54
58
|
query: req?.query ?? {},
|
|
55
59
|
host: req?.host,
|
|
@@ -100,10 +104,15 @@ export const entrypointUrl = async (ref, req, opts) => {
|
|
|
100
104
|
let path = pathParams.reduce((p, param) => {
|
|
101
105
|
return p.replace(`${PARAM}${param}`, `${req?.params?.[param]}`);
|
|
102
106
|
}, epPath) + (req?.query != null ? `?${stringify(req?.query)}` : '');
|
|
107
|
+
// A socket address is always absolute, whoever owns the route. `new WebSocket(path)` resolves a
|
|
108
|
+
// relative value against the PAGE's origin, which in a split deployment is the web host and not
|
|
109
|
+
// the service that answers the upgrade — so the handshake goes somewhere that never speaks it
|
|
110
|
+
// and dies on a gateway timeout. Only a same-origin HTTP route benefits from staying relative.
|
|
111
|
+
const socket = ep.route.route.protocol === RouteProtocols.SOCKET;
|
|
103
112
|
// Locality is a question about the RESOLVED service, not about what the declaration happens to
|
|
104
113
|
// name: a route that names no service belongs to the asking context, and addressing it absolutely
|
|
105
114
|
// would turn in-app navigation into a full page load.
|
|
106
|
-
if (!ep.isLocal() || opts?.absolute === true) {
|
|
115
|
+
if (socket || !ep.isLocal() || opts?.absolute === true) {
|
|
107
116
|
const helper = makeSecurityHelper(ctx);
|
|
108
117
|
path = helper.makeUrl(ep.address(), path, { host: req?.host, base: req?.base, forceUnsecure: req?.unsecure });
|
|
109
118
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../src/utils/handler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAGrD,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAEzF,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACtD,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../src/utils/handler.ts"],"names":[],"mappings":"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"}
|
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.14",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -28,15 +28,15 @@
|
|
|
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/route": "^0.1.18-rc.
|
|
31
|
+
"@owlmeans/api": "^0.1.18-rc.14",
|
|
32
|
+
"@owlmeans/client-config": "^0.1.18-rc.13",
|
|
33
|
+
"@owlmeans/client-context": "^0.1.18-rc.14",
|
|
34
|
+
"@owlmeans/client-route": "^0.1.18-rc.14",
|
|
35
|
+
"@owlmeans/config": "^0.1.18-rc.13",
|
|
36
|
+
"@owlmeans/context": "^0.1.18-rc.9",
|
|
37
|
+
"@owlmeans/entrypoint": "^0.1.18-rc.12",
|
|
38
|
+
"@owlmeans/error": "^0.1.18-rc.9",
|
|
39
|
+
"@owlmeans/route": "^0.1.18-rc.10",
|
|
40
40
|
"ajv-formats": "^3.0.1",
|
|
41
41
|
"qs": "^6.13.0"
|
|
42
42
|
},
|
package/src/index.ts
CHANGED
package/src/protocol.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { materializeEntrypoint, protocols } from '@owlmeans/entrypoint'
|
|
2
|
+
import type { EntrypointProtocolDeclaration, EntrypointTree } from '@owlmeans/entrypoint'
|
|
3
|
+
import { entrypoint } from './entrypoint.js'
|
|
4
|
+
import type {
|
|
5
|
+
ClientEntrypointOptions, ClientProtocolEntrypoint, RefedEntrypointHandler,
|
|
6
|
+
} from './types.js'
|
|
7
|
+
|
|
8
|
+
/** Bind a shared protocol to the client context without changing the declaration itself. */
|
|
9
|
+
export const bind = <Protocol extends EntrypointProtocolDeclaration>(
|
|
10
|
+
protocol: Protocol,
|
|
11
|
+
options?: ClientEntrypointOptions,
|
|
12
|
+
): ClientProtocolEntrypoint<Protocol> => {
|
|
13
|
+
const bound = Object.assign(entrypoint(
|
|
14
|
+
materializeEntrypoint(protocol),
|
|
15
|
+
options,
|
|
16
|
+
), { protocol })
|
|
17
|
+
|
|
18
|
+
return bound as ClientProtocolEntrypoint<Protocol>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Materialize every protocol in an exported declaration tree for a browser context. */
|
|
22
|
+
export const bindAll = (tree: EntrypointTree): ClientProtocolEntrypoint<EntrypointProtocolDeclaration>[] =>
|
|
23
|
+
protocols(tree).map(protocol => bind(protocol))
|
|
24
|
+
|
|
25
|
+
/** Bind a frontend protocol to the component that renders it. */
|
|
26
|
+
export const bindScreen = <Protocol extends EntrypointProtocolDeclaration>(
|
|
27
|
+
protocol: Protocol,
|
|
28
|
+
handler: RefedEntrypointHandler,
|
|
29
|
+
options?: ClientEntrypointOptions,
|
|
30
|
+
): ClientProtocolEntrypoint<Protocol> => {
|
|
31
|
+
const bound = Object.assign(entrypoint(
|
|
32
|
+
materializeEntrypoint(protocol),
|
|
33
|
+
handler,
|
|
34
|
+
options,
|
|
35
|
+
), { protocol })
|
|
36
|
+
|
|
37
|
+
return bound as ClientProtocolEntrypoint<Protocol>
|
|
38
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { ClientRouteModel, ClientRouteOptions } from '@owlmeans/client-route'
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
AbstractRequest, CommonEntrypoint, CommonEntrypointOptions, EntrypointHandler,
|
|
4
|
+
EntrypointOutcome, EntrypointProtocolDeclaration, RegisteredEntrypoint, RequestOf,
|
|
5
|
+
} from '@owlmeans/entrypoint'
|
|
3
6
|
|
|
4
7
|
export interface ClientEntrypoint<T = {}, R extends ClientRequest = ClientRequest> extends CommonEntrypoint {
|
|
5
8
|
route: ClientRouteModel
|
|
@@ -22,6 +25,18 @@ export interface ClientEntrypoint<T = {}, R extends ClientRequest = ClientReques
|
|
|
22
25
|
request: (request?: Partial<R>) => R
|
|
23
26
|
}
|
|
24
27
|
|
|
28
|
+
/**
|
|
29
|
+
* The context-bound client view of a protocol. Unlike the legacy `ClientEntrypoint` generic,
|
|
30
|
+
* its request and reply types are read directly from the declaration and cannot be replaced at a
|
|
31
|
+
* call site.
|
|
32
|
+
*/
|
|
33
|
+
export type ClientProtocolEntrypoint<Protocol extends EntrypointProtocolDeclaration> =
|
|
34
|
+
Omit<ClientEntrypoint, 'call' | 'invoke' | 'url' | 'validate' | 'request'>
|
|
35
|
+
& RegisteredEntrypoint<RequestOf<Protocol>, import('@owlmeans/entrypoint').ResponseOf<Protocol>>
|
|
36
|
+
& {
|
|
37
|
+
readonly protocol: Protocol
|
|
38
|
+
}
|
|
39
|
+
|
|
25
40
|
export interface EntrypointCall<T, Req extends ClientRequest = ClientRequest> {
|
|
26
41
|
<Type extends T, R extends Req = Req>(req?: Partial<R>): Promise<Type>
|
|
27
42
|
}
|
|
@@ -60,6 +75,6 @@ export interface EntrypointRef<T, R extends AbstractRequest = AbstractRequest> {
|
|
|
60
75
|
ref?: ClientEntrypoint<T, R>
|
|
61
76
|
}
|
|
62
77
|
|
|
63
|
-
export interface RefedEntrypointHandler<T, R extends AbstractRequest = AbstractRequest> {
|
|
78
|
+
export interface RefedEntrypointHandler<T = {}, R extends AbstractRequest = AbstractRequest> {
|
|
64
79
|
(ref: EntrypointRef<T, R>): EntrypointHandler
|
|
65
80
|
}
|
package/src/utils/handler.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { EntrypointOutcome, provideResponse, transportAlias } from '@owlmeans/en
|
|
|
6
6
|
import type { ClientEntrypoint, EntrypointInvoke, EntrypointUrlOptions, ClientEntrypointOptions, EntrypointRef, ClientRequest } from '../types.js'
|
|
7
7
|
import { validate } from './entrypoint.js'
|
|
8
8
|
import { extractParams } from '@owlmeans/client-route'
|
|
9
|
-
import { PARAM } from '@owlmeans/route'
|
|
9
|
+
import { PARAM, RouteMethod, RouteProtocols } from '@owlmeans/route'
|
|
10
10
|
import { stringify } from 'qs'
|
|
11
11
|
import { assertContext } from '@owlmeans/context'
|
|
12
12
|
import { makeSecurityHelper } from '@owlmeans/config'
|
|
@@ -75,7 +75,11 @@ export const apiInvoke: <
|
|
|
75
75
|
const request: AbstractRequest = {
|
|
76
76
|
alias: ep.alias,
|
|
77
77
|
params: req?.params ?? {},
|
|
78
|
-
body
|
|
78
|
+
// JSON transports must send a body for mutation methods even when the contract has no
|
|
79
|
+
// payload. Keeping that rule here makes every typed caller use `call({ params })`, never
|
|
80
|
+
// an SDK-specific `{ body: {} }` workaround.
|
|
81
|
+
body: req?.body ?? ([RouteMethod.POST, RouteMethod.PUT, RouteMethod.PATCH]
|
|
82
|
+
.includes(ep.route.route.method ?? RouteMethod.GET) ? {} : undefined),
|
|
79
83
|
headers: req?.headers ?? {},
|
|
80
84
|
query: req?.query ?? {},
|
|
81
85
|
host: req?.host,
|
|
@@ -131,10 +135,16 @@ export const entrypointUrl: <
|
|
|
131
135
|
return p.replace(`${PARAM}${param}`, `${req?.params?.[param as keyof typeof req.params]}`)
|
|
132
136
|
}, epPath) + (req?.query != null ? `?${stringify(req?.query)}` : '')
|
|
133
137
|
|
|
138
|
+
// A socket address is always absolute, whoever owns the route. `new WebSocket(path)` resolves a
|
|
139
|
+
// relative value against the PAGE's origin, which in a split deployment is the web host and not
|
|
140
|
+
// the service that answers the upgrade — so the handshake goes somewhere that never speaks it
|
|
141
|
+
// and dies on a gateway timeout. Only a same-origin HTTP route benefits from staying relative.
|
|
142
|
+
const socket = ep.route.route.protocol === RouteProtocols.SOCKET
|
|
143
|
+
|
|
134
144
|
// Locality is a question about the RESOLVED service, not about what the declaration happens to
|
|
135
145
|
// name: a route that names no service belongs to the asking context, and addressing it absolutely
|
|
136
146
|
// would turn in-app navigation into a full page load.
|
|
137
|
-
if (!ep.isLocal() || opts?.absolute === true) {
|
|
147
|
+
if (socket || !ep.isLocal() || opts?.absolute === true) {
|
|
138
148
|
const helper = makeSecurityHelper(ctx)
|
|
139
149
|
path = helper.makeUrl(
|
|
140
150
|
ep.address(), path, { host: req?.host, base: req?.base, forceUnsecure: req?.unsecure }
|