@owlmeans/server-entrypoint 0.1.18-rc.10 → 0.1.18-rc.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -12,7 +12,7 @@ Elevates route definitions into runnable server entrypoints with attached reques
12
12
  ## Installation
13
13
 
14
14
  ```bash
15
- bun add @owlmeans/server-entrypoint
15
+ bun add @owlmeans/server-entrypoint@^0.1.18-rc.10
16
16
  ```
17
17
 
18
18
  ## Usage
@@ -76,7 +76,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
76
76
  your project's skill store (`.agents/skills/`):
77
77
 
78
78
  ```sh
79
- npx @owlmeans/agent-skills
79
+ npx @owlmeans/agent-skills@^0.1.18-rc.13
80
80
  ```
81
81
 
82
82
  The embedded files are version-matched to this package release. Do not edit them
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
3
  "package": "@owlmeans/server-entrypoint",
4
- "version": "0.1.18-rc.10",
5
- "generatedAt": "2026-09-01T17:39:40.763Z",
4
+ "version": "0.1.18-rc.12",
5
+ "generatedAt": "2026-09-10T18:54:42.497Z",
6
6
  "canonicalRepo": "https://github.com/owlmeans/common",
7
7
  "entries": [
8
8
  {
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: server-entrypoint
3
- description: How to use @owlmeans/server-entrypoint — server-side entrypoints extending @owlmeans/entrypoint with handler attachment, intermediates and mount(). Auto-invoked when importing server-entrypoint types.
3
+ description: How to use @owlmeans/server-entrypoint — binding immutable protocols to server handlers, plus legacy elevate() forms, intermediates, guards and mount(). Auto-invoked when importing server-entrypoint types or writing a custom entrypoint helper.
4
4
  user-invocable: false
5
5
  ---
6
6
  <!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
@@ -8,32 +8,90 @@ user-invocable: false
8
8
  # @owlmeans/server-entrypoint
9
9
 
10
10
  **Layer:** Server
11
- **Install:** `"@owlmeans/server-entrypoint": "^0.1.18-rc.10"` in `dependencies`
11
+ **Install:** `"@owlmeans/server-entrypoint": "^0.1.18-rc.12"` in `dependencies`
12
12
 
13
13
  ## Key Exports
14
14
 
15
15
  | Export | Description |
16
16
  |--------|-------------|
17
- | `ServerEntrypoint<R>` | Server entrypoint interface a `ServerRouteModel` plus a `handle` |
18
- | `entrypoint(arg, handler?, opts?)` | Build a server entrypoint from a route model or an existing declaration |
19
- | `elevate(entrypoints, alias, handler?, opts?)` | Attach a handler (or just guards) to a declared entrypoint |
20
- | `guard(alias, opts?)` | Require a guard, returning server entrypoint options |
21
- | `EntrypointOptions<R>` | Options for elevating: `handler`, `fixer`, `intermediate`, `routeOptions`, guards/gates/filter |
22
- | `EntrypointRef` / `RefedEntrypointHandler` | Handler reference pattern |
23
- | `FixerService` | Per-entrypoint error rendering (`handle(reply, error)`) |
17
+ | `bind(protocol, implementation?, opts?)` | Materialize a protocol and its protocol-bound handler |
18
+ | `ServerProtocolEntrypoint<P>` | The server module whose request/reply types come from `P` |
19
+ | `BoundEntrypointHandler<P>` | A handler implementation tied to exactly one protocol |
20
+ | `ServerEntrypoint<R>` | Server entrypoint interface a common entrypoint whose `route` is a `ServerRouteModel` plus `handle` and an optional `fixer` |
21
+ | `entrypoint(arg, handler?, opts?)` | Build one from an existing declaration, a server route model, or a plain route model |
22
+ | `elevate(entrypoints, alias, handler?, opts?)` | Replace the declaration under `alias` in-place with its elevated counterpart |
23
+ | `guard(alias, opts?)` | Options that require a guard, ready to pass as `opts` |
24
+ | `EntrypointOptions<R>` | `fixer`, `intermediate`, `routeOptions`, plus everything a common entrypoint declares. `elevate()` reads only `route`-shaping and access keys from it — `intermediate`, `routeOptions`, `filter`, `guards`, `gate`, `gateParams`, `fixer`; `handle` and `sticky` are silently ignored there |
25
+ | `EntrypointRef<R>` / `RefedEntrypointHandler<R>` | `(ref) => handler` — the wrapper is handed a ref that resolves to the entrypoint being built, which is how a handler reaches its own `ctx` |
26
+ | `FixerService` | Per-entrypoint error rendering (`handle(reply, error)`), named by `opts.fixer` and resolved as a service |
24
27
 
25
28
  ## Usage
26
29
 
27
- Most app code uses `elevate()` from `@owlmeans/server-app` (which builds on this package). Import directly only when implementing custom entrypoint helpers.
30
+ New code pairs `bind` with `handlers<Context>()` from `@owlmeans/server-api` (both are re-exported
31
+ by `@owlmeans/server-app`). The callback request and reply are inferred from the protocol, so no
32
+ call-site generic or alias lookup can drift from the shared declaration:
28
33
 
29
34
  ```typescript
35
+ import { bind, handlers } from '@owlmeans/server-app'
36
+ import { item } from 'project-common'
37
+
38
+ const handle = handlers<Context>()
39
+ export const getItem = handle.params(item.get, async ({ id }, context) =>
40
+ await context.resource<ItemResource>('item').load(id))
41
+
42
+ export const appEntrypoints = [bind(item.get, getItem)]
43
+ ```
44
+
45
+ Use `handle.body`, `handle.params`, or `handle.request` according to the protocol contract. A
46
+ body/params helper refuses a protocol that did not declare that section, and the callback return
47
+ must match the protocol response.
48
+
49
+ Most legacy app code uses `elevate()` from `@owlmeans/server-app`. Import directly only when
50
+ implementing custom entrypoint helpers.
51
+
52
+ ```typescript
53
+ import { elevate, guard } from '@owlmeans/server-entrypoint'
30
54
  import type { ServerEntrypoint } from '@owlmeans/server-entrypoint'
31
55
  ```
32
56
 
33
- Elevating is **idempotent** — elevating the same alias again simply replaces the element once more,
34
- and an intermediate stays intermediate unless the new call says otherwise. Guards passed at
35
- elevation are **unioned** with the ones the declaration already carries, so what the entrypoint
36
- declared still applies.
57
+ ### elevate forms
58
+
59
+ The third argument is overloaded, and all four forms are legal:
60
+
61
+ ```typescript
62
+ elevate(entrypoints, alias) // bare — make it a server entrypoint, nothing more
63
+ elevate(entrypoints, alias, handler) // attach a handler
64
+ elevate(entrypoints, alias, guard(DAUTH_GUARD)) // options only
65
+ elevate(entrypoints, alias, handler, true) // trailing boolean === { intermediate: true }
66
+ ```
67
+
68
+ `DAUTH_GUARD` above is `@owlmeans/server-auth`'s `DEFAULT_ALIAS` (`auth`), re-exported under that
69
+ name by `@owlmeans/server-app`.
70
+
71
+ It throws `SyntaxError` when no entrypoint in the list carries that alias, and it mutates the array
72
+ it is given — the elevated entrypoint replaces the element, and the same array is returned.
73
+
74
+ **A handler only ever arrives as the third argument.** `elevate` passes the options through
75
+ `entrypoint()`, which on an already-declared entrypoint applies `route`, `filter`, `guards`, `gate`,
76
+ `gateParams`, `intermediate` and `fixer` and nothing else — so `elevate(list, ALIAS, { handle: fn })`
77
+ type-checks, drops the function, and leaves an entrypoint the server never binds.
78
+
79
+ Elevating is **idempotent**: elevating the same alias again simply replaces the element once more.
80
+ An entrypoint stays intermediate unless the new call says otherwise, guards passed at elevation are
81
+ **unioned** with the ones the declaration already carries (so what the entrypoint declared still
82
+ applies), and a `fixer` already set survives a call that does not name one.
83
+
84
+ The **bare** form only converts the declaration into a server entrypoint — a `ServerRouteModel`
85
+ that `canServeModule` recognises. It creates no route group: an entrypoint with no `handle` is never
86
+ bound as a route, guarded or not, and `intermediate` defaults to what the declaration already was
87
+ (`false` for a common declaration), so a bare elevate does not put it in the intermediate chain
88
+ either. A live intermediate is `elevate(list, ALIAS, handleIntermediate(fn), true)` — a handler plus
89
+ `true`, with `handleIntermediate` from `@owlmeans/server-api`.
90
+
91
+ A parent alias that carries only a `guard()` for its children needs no elevation at all:
92
+ `getGuards()` walks `parent()`, which resolves the alias against the context, and a registered
93
+ declaration answers there whether or not it was elevated. `gate()` is not in this package — it comes
94
+ from `@owlmeans/entrypoint`, and only `guard()` is defined here.
37
95
 
38
96
  ## What a server registers
39
97
 
@@ -47,9 +105,14 @@ server.route({ url: entrypoint.mount(), method, handler })
47
105
  entrypoint.route.match(request, entrypoint.mount()) // intermediates test the same mount
48
106
  ```
49
107
 
108
+ Guards and gates are read with `getGuards()` / `getGates()`, which include everything the ancestors
109
+ declared, and they run before the handler — a handler that re-checks them duplicates an enforced
110
+ rule.
111
+
50
112
  ## Cross-Service URL Generation
51
113
 
52
- Use `makeSecurityHelper` from `@owlmeans/config` to build URLs pointing at other services (OAuth redirect URIs, webhook callbacks, etc.):
114
+ Use `makeSecurityHelper` from `@owlmeans/config` to build URLs pointing at other services (OAuth
115
+ redirect URIs, webhook callbacks, etc.):
53
116
 
54
117
  ```typescript
55
118
  import { makeSecurityHelper } from '@owlmeans/config'
@@ -59,4 +122,4 @@ const url = helper.makeUrl(entrypoint.address(), '/callback')
59
122
 
60
123
  ## Depends On
61
124
 
62
- - `@owlmeans/entrypoint`, `@owlmeans/server-route`, `@owlmeans/server-context`
125
+ - `@owlmeans/entrypoint`, `@owlmeans/server-route`, `@owlmeans/route`, `@owlmeans/context`
@@ -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,iBAAiB,EAAiB,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAG5G,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAEjD,eAAO,MAAM,UAAU,GAAI,CAAC,EAC1B,KAAK,gBAAgB,GAAG,gBAAgB,CAAC,CAAC,CAAC,GAAG,UAAU,EAAE,UAAU,sBAAsB,CAAC,CAAC,CAAC,EAAE,OAAO,iBAAiB,CAAC,CAAC,CAAC,KACzH,gBAAgB,CAAC,CAAC,CAmCpB,CAAA"}
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,iBAAiB,EAAiB,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAG5G,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAEjD,eAAO,MAAM,UAAU,GAAI,CAAC,OACrB,gBAAgB,GAAG,gBAAgB,CAAC,CAAC,CAAC,GAAG,UAAU,YAAY,sBAAsB,CAAC,CAAC,CAAC,SAAS,iBAAiB,CAAC,CAAC,CAAC,KACzH,gBAAgB,CAAC,CAAC,CAmCpB,CAAA"}
package/build/helper.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import type { ServerEntrypoint, EntrypointOptions, RefedEntrypointHandler } from './types.js';
2
- import type { CommonEntrypoint } from '@owlmeans/entrypoint';
1
+ import type { BoundEntrypointHandler, ServerEntrypoint, EntrypointOptions, RefedEntrypointHandler, ServerProtocolEntrypoint } from './types.js';
2
+ import type { CommonEntrypoint, EntrypointProtocolDeclaration } from '@owlmeans/entrypoint';
3
3
  /**
4
4
  * Replace the entrypoint declared under `alias` with its elevated counterpart. Elevating is
5
5
  * idempotent — calling it again simply replaces the element once more, and the guards it brings
@@ -7,6 +7,7 @@ import type { CommonEntrypoint } from '@owlmeans/entrypoint';
7
7
  *
8
8
  * @throws {SyntaxError} when no entrypoint carries the alias
9
9
  */
10
- export declare const elevate: <R>(entrypoints: (CommonEntrypoint | ServerEntrypoint<R>)[], alias: string, handler?: RefedEntrypointHandler<R> | boolean | EntrypointOptions<R>, opts?: boolean | EntrypointOptions<R>) => ServerEntrypoint<R>[];
10
+ export declare function elevate(declarations: EntrypointProtocolDeclaration[], implementations: readonly BoundEntrypointHandler<EntrypointProtocolDeclaration>[]): ServerProtocolEntrypoint<EntrypointProtocolDeclaration>[];
11
+ export declare function elevate<R>(entrypoints: (CommonEntrypoint | ServerEntrypoint<R>)[], alias: string, handler?: RefedEntrypointHandler<R> | boolean | EntrypointOptions<R>, opts?: boolean | EntrypointOptions<R>): ServerEntrypoint<R>[];
11
12
  export declare const guard: <R>(guard: string, opts?: EntrypointOptions<R>) => EntrypointOptions<R>;
12
13
  //# sourceMappingURL=helper.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAG7F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAE5D;;;;;;GAMG;AACH,eAAO,MAAM,OAAO,GAAI,CAAC,EACvB,aAAa,CAAC,gBAAgB,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAAE,EACvD,OAAO,MAAM,EACb,UAAU,sBAAsB,CAAC,CAAC,CAAC,GAAG,OAAO,GAAG,iBAAiB,CAAC,CAAC,CAAC,EACpE,OAAO,OAAO,GAAG,iBAAiB,CAAC,CAAC,CAAC,KACpC,gBAAgB,CAAC,CAAC,CAAC,EAmBrB,CAAA;AAED,eAAO,MAAM,KAAK,GAAI,CAAC,EAAE,OAAO,MAAM,EAAE,OAAO,iBAAiB,CAAC,CAAC,CAAC,KAAG,iBAAiB,CAAC,CAAC,CACjD,CAAA"}
1
+ {"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,sBAAsB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,sBAAsB,EACnF,wBAAwB,EACzB,MAAM,YAAY,CAAA;AAKnB,OAAO,KAAK,EAAE,gBAAgB,EAAE,6BAA6B,EAAE,MAAM,sBAAsB,CAAA;AAE3F;;;;;;GAMG;AACH,wBAAgB,OAAO,CACrB,YAAY,EAAE,6BAA6B,EAAE,EAC7C,eAAe,EAAE,SAAS,sBAAsB,CAAC,6BAA6B,CAAC,EAAE,GAChF,wBAAwB,CAAC,6BAA6B,CAAC,EAAE,CAAA;AAC5D,wBAAgB,OAAO,CAAC,CAAC,EACvB,WAAW,EAAE,CAAC,gBAAgB,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAAE,EACvD,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAAG,OAAO,GAAG,iBAAiB,CAAC,CAAC,CAAC,EACpE,IAAI,CAAC,EAAE,OAAO,GAAG,iBAAiB,CAAC,CAAC,CAAC,GACpC,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAA;AA4CxB,eAAO,MAAM,KAAK,GAAI,CAAC,SAAS,MAAM,SAAS,iBAAiB,CAAC,CAAC,CAAC,KAAG,iBAAiB,CAAC,CAAC,CACjD,CAAA"}
package/build/helper.js CHANGED
@@ -1,16 +1,20 @@
1
1
  import { entrypoint } from './entrypoint.js';
2
+ import { bind } from './protocol.js';
2
3
  import { createBasicGuard } from './utils/helper.js';
3
- /**
4
- * Replace the entrypoint declared under `alias` with its elevated counterpart. Elevating is
5
- * idempotent calling it again simply replaces the element once more, and the guards it brings
6
- * are added to the ones already declared.
7
- *
8
- * @throws {SyntaxError} when no entrypoint carries the alias
9
- */
10
- export const elevate = (entrypoints, alias, handler, opts) => {
11
- const idx = entrypoints.findIndex(({ route }) => route.route.alias === alias);
4
+ import { isEntrypointProtocol } from '@owlmeans/entrypoint';
5
+ export function elevate(entrypoints, target, handler, opts) {
6
+ if (typeof target !== 'string') {
7
+ return entrypoints.map((declaration) => {
8
+ if (!isEntrypointProtocol(declaration)) {
9
+ throw new SyntaxError('Protocol elevation accepts protocol declarations only');
10
+ }
11
+ const implementation = target.find(bound => bound.protocol === declaration);
12
+ return bind(declaration, implementation);
13
+ });
14
+ }
15
+ const idx = entrypoints.findIndex((candidate) => !isEntrypointProtocol(candidate) && candidate.route.route.alias === target);
12
16
  if (idx === -1) {
13
- throw new SyntaxError(`Entrypoint with alias ${alias} not present`);
17
+ throw new SyntaxError(`Entrypoint with alias ${target} not present`);
14
18
  }
15
19
  if (typeof handler === 'boolean') {
16
20
  opts = handler;
@@ -20,8 +24,12 @@ export const elevate = (entrypoints, alias, handler, opts) => {
20
24
  opts = handler;
21
25
  handler = undefined;
22
26
  }
23
- entrypoints[idx] = entrypoint(entrypoints[idx], handler, typeof opts === 'boolean' ? { intermediate: opts } : opts);
27
+ const declaration = entrypoints[idx];
28
+ if (isEntrypointProtocol(declaration)) {
29
+ throw new SyntaxError('String elevation accepts materialized entrypoints only');
30
+ }
31
+ entrypoints[idx] = entrypoint(declaration, handler, typeof opts === 'boolean' ? { intermediate: opts } : opts);
24
32
  return entrypoints;
25
- };
33
+ }
26
34
  export const guard = (guard, opts) => ({ ...createBasicGuard(guard, opts) });
27
35
  //# sourceMappingURL=helper.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"helper.js","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAGpD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CACrB,WAAuD,EACvD,KAAa,EACb,OAAoE,EACpE,IAAqC,EACd,EAAE;IACzB,MAAM,GAAG,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,KAAK,KAAK,CAAC,CAAA;IAC7E,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;QACf,MAAM,IAAI,WAAW,CAAC,yBAAyB,KAAK,cAAc,CAAC,CAAA;IACrE,CAAC;IACD,IAAI,OAAO,OAAO,KAAK,SAAS,EAAE,CAAC;QACjC,IAAI,GAAG,OAAO,CAAA;QACd,OAAO,GAAG,SAAS,CAAA;IACrB,CAAC;IACD,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;QACjE,IAAI,GAAG,OAAO,CAAA;QACd,OAAO,GAAG,SAAS,CAAA;IACrB,CAAC;IAED,WAAW,CAAC,GAAG,CAAC,GAAG,UAAU,CAC3B,WAAW,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CACrF,CAAA;IAED,OAAO,WAAoC,CAAA;AAC7C,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,KAAK,GAAG,CAAI,KAAa,EAAE,IAA2B,EAAwB,EAAE,CAC3F,CAAC,EAAE,GAAG,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,CAAA"}
1
+ {"version":3,"file":"helper.js","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAoB3D,MAAM,UAAU,OAAO,CACrB,WAAiE,EACjE,MAAiF,EACjF,OAAsE,EACtE,IAA0C;IAE1C,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE;YACrC,IAAI,CAAC,oBAAoB,CAAC,WAAW,CAAC,EAAE,CAAC;gBACvC,MAAM,IAAI,WAAW,CAAC,uDAAuD,CAAC,CAAA;YAChF,CAAC;YAED,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,KAAK,WAAW,CAAC,CAAA;YAC3E,OAAO,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAA;QAC1C,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,SAAS,EAAE,EAAE,CAC9C,CAAC,oBAAoB,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,KAAK,MAAM,CAAC,CAAA;IAC7E,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;QACf,MAAM,IAAI,WAAW,CAAC,yBAAyB,MAAM,cAAc,CAAC,CAAA;IACtE,CAAC;IACD,IAAI,OAAO,OAAO,KAAK,SAAS,EAAE,CAAC;QACjC,IAAI,GAAG,OAAO,CAAA;QACd,OAAO,GAAG,SAAS,CAAA;IACrB,CAAC;IACD,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;QACjE,IAAI,GAAG,OAAO,CAAA;QACd,OAAO,GAAG,SAAS,CAAA;IACrB,CAAC;IAED,MAAM,WAAW,GAAG,WAAW,CAAC,GAAG,CAAC,CAAA;IACpC,IAAI,oBAAoB,CAAC,WAAW,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,WAAW,CAAC,wDAAwD,CAAC,CAAA;IACjF,CAAC;IAED,WAAW,CAAC,GAAG,CAAC,GAAG,UAAU,CAC3B,WAAW,EAAE,OAAO,EAAE,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAChF,CAAA;IAED,OAAO,WAAyC,CAAA;AAClD,CAAC;AAED,MAAM,CAAC,MAAM,KAAK,GAAG,CAAI,KAAa,EAAE,IAA2B,EAAwB,EAAE,CAC3F,CAAC,EAAE,GAAG,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,CAAA"}
package/build/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from './helper.js';
2
2
  export type * from './types.js';
3
3
  export * from './entrypoint.js';
4
+ export * from './protocol.js';
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -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"}
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,eAAe,CAAA"}
package/build/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './helper.js';
2
2
  export * from './entrypoint.js';
3
+ export * from './protocol.js';
3
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,aAAa,CAAA;AAE3B,cAAc,iBAAiB,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,eAAe,CAAA"}
@@ -0,0 +1,5 @@
1
+ import type { EntrypointProtocolDeclaration } from '@owlmeans/entrypoint';
2
+ import type { BoundEntrypointHandler, EntrypointOptions, ServerProtocolEntrypoint } from './types.js';
3
+ /** Bind one immutable protocol and, when present, its protocol-bound implementation. */
4
+ export declare const bind: <Protocol extends EntrypointProtocolDeclaration>(protocol: Protocol, implementation?: BoundEntrypointHandler<Protocol>, options?: EntrypointOptions<object>) => ServerProtocolEntrypoint<Protocol>;
5
+ //# 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,MAAM,sBAAsB,CAAA;AAEzE,OAAO,KAAK,EACV,sBAAsB,EAAE,iBAAiB,EAAE,wBAAwB,EACpE,MAAM,YAAY,CAAA;AAEnB,wFAAwF;AACxF,eAAO,MAAM,IAAI,GAAI,QAAQ,SAAS,6BAA6B,YACvD,QAAQ,mBACD,sBAAsB,CAAC,QAAQ,CAAC,YACvC,iBAAiB,CAAC,MAAM,CAAC,KAClC,wBAAwB,CAAC,QAAQ,CAQnC,CAAA"}
@@ -0,0 +1,8 @@
1
+ import { materializeEntrypoint } from '@owlmeans/entrypoint';
2
+ import { entrypoint } from './entrypoint.js';
3
+ /** Bind one immutable protocol and, when present, its protocol-bound implementation. */
4
+ export const bind = (protocol, implementation, options) => {
5
+ const bound = Object.assign(entrypoint(materializeEntrypoint(protocol), implementation?.bind, options), { protocol });
6
+ return bound;
7
+ };
8
+ //# 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,MAAM,sBAAsB,CAAA;AAE5D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAK5C,wFAAwF;AACxF,MAAM,CAAC,MAAM,IAAI,GAAG,CAClB,QAAkB,EAClB,cAAiD,EACjD,OAAmC,EACC,EAAE;IACtC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,CACpC,qBAAqB,CAAC,QAAQ,CAAC,EAC/B,cAAc,EAAE,IAAI,EACpB,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 { ServerRouteModel, ServerRouteOptions } from '@owlmeans/server-route';
2
- import type { CommonEntrypoint, EntrypointHandler, CommonEntrypointOptions } from '@owlmeans/entrypoint';
2
+ import type { CommonEntrypoint, EntrypointHandler, CommonEntrypointOptions, EntrypointProtocolDeclaration } from '@owlmeans/entrypoint';
3
3
  import type { Service } from '@owlmeans/context';
4
4
  export interface ServerEntrypoint<R> extends CommonEntrypoint {
5
5
  route: ServerRouteModel<R>;
@@ -20,4 +20,13 @@ export interface EntrypointRef<R> {
20
20
  export interface RefedEntrypointHandler<R = {}> {
21
21
  (ref: EntrypointRef<R>): EntrypointHandler;
22
22
  }
23
+ /** The server-local representation of a shared protocol declaration. */
24
+ export type ServerProtocolEntrypoint<Protocol extends EntrypointProtocolDeclaration> = ServerEntrypoint<object> & {
25
+ readonly protocol: Protocol;
26
+ };
27
+ /** A handler that is inseparable from the protocol whose request it accepts. */
28
+ export interface BoundEntrypointHandler<Protocol extends EntrypointProtocolDeclaration> {
29
+ readonly protocol: Protocol;
30
+ bind: RefedEntrypointHandler;
31
+ }
23
32
  //# sourceMappingURL=types.d.ts.map
@@ -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,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAA;AACxG,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAEhD,MAAM,WAAW,gBAAgB,CAAC,CAAC,CAAE,SAAQ,gBAAgB;IAC3D,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAA;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,iBAAiB,CAAA;CAC1B;AAED,MAAM,WAAW,iBAAiB,CAAC,CAAC,CAAE,SAAQ,uBAAuB;IACnE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,YAAY,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAA;CACrC;AAED,MAAM,WAAW,YAAa,SAAQ,OAAO;IAC3C,MAAM,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CAC5C;AAED,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,GAAG,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAA;CAC1B;AAED,MAAM,WAAW,sBAAsB,CAAC,CAAC,GAAG,EAAE;IAC5C,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,iBAAiB,CAAA;CAC3C"}
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,gBAAgB,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,6BAA6B,EAC5F,MAAM,sBAAsB,CAAA;AAC7B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAEhD,MAAM,WAAW,gBAAgB,CAAC,CAAC,CAAE,SAAQ,gBAAgB;IAC3D,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAA;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,iBAAiB,CAAA;CAC1B;AAED,MAAM,WAAW,iBAAiB,CAAC,CAAC,CAAE,SAAQ,uBAAuB;IACnE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,YAAY,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAA;CACrC;AAED,MAAM,WAAW,YAAa,SAAQ,OAAO;IAC3C,MAAM,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CAC5C;AAED,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,GAAG,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAA;CAC1B;AAED,MAAM,WAAW,sBAAsB,CAAC,CAAC,GAAG,EAAE;IAC5C,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,iBAAiB,CAAA;CAC3C;AAED,wEAAwE;AACxE,MAAM,MAAM,wBAAwB,CAAC,QAAQ,SAAS,6BAA6B,IAAI,gBAAgB,CAAC,MAAM,CAAC,GAAG;IAChH,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;CAC5B,CAAA;AAED,gFAAgF;AAChF,MAAM,WAAW,sBAAsB,CAAC,QAAQ,SAAS,6BAA6B;IACpF,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;IAC3B,IAAI,EAAE,sBAAsB,CAAA;CAC7B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owlmeans/server-entrypoint",
3
- "version": "0.1.18-rc.10",
3
+ "version": "0.1.18-rc.12",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -21,10 +21,10 @@
21
21
  }
22
22
  },
23
23
  "dependencies": {
24
- "@owlmeans/context": "^0.1.18-rc.7",
25
- "@owlmeans/entrypoint": "^0.1.18-rc.10",
26
- "@owlmeans/route": "^0.1.18-rc.8",
27
- "@owlmeans/server-route": "^0.1.18-rc.8"
24
+ "@owlmeans/context": "^0.1.18-rc.9",
25
+ "@owlmeans/entrypoint": "^0.1.18-rc.12",
26
+ "@owlmeans/route": "^0.1.18-rc.10",
27
+ "@owlmeans/server-route": "^0.1.18-rc.10"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@owlmeans/dep-config": "workspace:*",
package/src/helper.ts CHANGED
@@ -1,7 +1,12 @@
1
- import type { ServerEntrypoint, EntrypointOptions, RefedEntrypointHandler } from './types.js'
1
+ import type {
2
+ BoundEntrypointHandler, ServerEntrypoint, EntrypointOptions, RefedEntrypointHandler,
3
+ ServerProtocolEntrypoint,
4
+ } from './types.js'
2
5
  import { entrypoint } from './entrypoint.js'
6
+ import { bind } from './protocol.js'
3
7
  import { createBasicGuard } from './utils/helper.js'
4
- import type { CommonEntrypoint } from '@owlmeans/entrypoint'
8
+ import { isEntrypointProtocol } from '@owlmeans/entrypoint'
9
+ import type { CommonEntrypoint, EntrypointProtocolDeclaration } from '@owlmeans/entrypoint'
5
10
 
6
11
  /**
7
12
  * Replace the entrypoint declared under `alias` with its elevated counterpart. Elevating is
@@ -10,15 +15,37 @@ import type { CommonEntrypoint } from '@owlmeans/entrypoint'
10
15
  *
11
16
  * @throws {SyntaxError} when no entrypoint carries the alias
12
17
  */
13
- export const elevate = <R>(
18
+ export function elevate(
19
+ declarations: EntrypointProtocolDeclaration[],
20
+ implementations: readonly BoundEntrypointHandler<EntrypointProtocolDeclaration>[],
21
+ ): ServerProtocolEntrypoint<EntrypointProtocolDeclaration>[]
22
+ export function elevate<R>(
14
23
  entrypoints: (CommonEntrypoint | ServerEntrypoint<R>)[],
15
24
  alias: string,
16
25
  handler?: RefedEntrypointHandler<R> | boolean | EntrypointOptions<R>,
17
26
  opts?: boolean | EntrypointOptions<R>
18
- ): ServerEntrypoint<R>[] => {
19
- const idx = entrypoints.findIndex(({ route }) => route.route.alias === alias)
27
+ ): ServerEntrypoint<R>[]
28
+ export function elevate(
29
+ entrypoints: (CommonEntrypoint | EntrypointProtocolDeclaration)[],
30
+ target: string | readonly BoundEntrypointHandler<EntrypointProtocolDeclaration>[],
31
+ handler?: RefedEntrypointHandler | boolean | EntrypointOptions<object>,
32
+ opts?: boolean | EntrypointOptions<object>,
33
+ ): (ServerEntrypoint<object> | ServerProtocolEntrypoint<EntrypointProtocolDeclaration>)[] {
34
+ if (typeof target !== 'string') {
35
+ return entrypoints.map((declaration) => {
36
+ if (!isEntrypointProtocol(declaration)) {
37
+ throw new SyntaxError('Protocol elevation accepts protocol declarations only')
38
+ }
39
+
40
+ const implementation = target.find(bound => bound.protocol === declaration)
41
+ return bind(declaration, implementation)
42
+ })
43
+ }
44
+
45
+ const idx = entrypoints.findIndex((candidate) =>
46
+ !isEntrypointProtocol(candidate) && candidate.route.route.alias === target)
20
47
  if (idx === -1) {
21
- throw new SyntaxError(`Entrypoint with alias ${alias} not present`)
48
+ throw new SyntaxError(`Entrypoint with alias ${target} not present`)
22
49
  }
23
50
  if (typeof handler === 'boolean') {
24
51
  opts = handler
@@ -29,11 +56,16 @@ export const elevate = <R>(
29
56
  handler = undefined
30
57
  }
31
58
 
59
+ const declaration = entrypoints[idx]
60
+ if (isEntrypointProtocol(declaration)) {
61
+ throw new SyntaxError('String elevation accepts materialized entrypoints only')
62
+ }
63
+
32
64
  entrypoints[idx] = entrypoint(
33
- entrypoints[idx], handler, typeof opts === 'boolean' ? { intermediate: opts } : opts
65
+ declaration, handler, typeof opts === 'boolean' ? { intermediate: opts } : opts
34
66
  )
35
67
 
36
- return entrypoints as ServerEntrypoint<R>[]
68
+ return entrypoints as ServerEntrypoint<object>[]
37
69
  }
38
70
 
39
71
  export const guard = <R>(guard: string, opts?: EntrypointOptions<R>): EntrypointOptions<R> =>
package/src/index.ts CHANGED
@@ -2,3 +2,4 @@
2
2
  export * from './helper.js'
3
3
  export type * from './types.js'
4
4
  export * from './entrypoint.js'
5
+ export * from './protocol.js'
@@ -0,0 +1,21 @@
1
+ import { materializeEntrypoint } from '@owlmeans/entrypoint'
2
+ import type { EntrypointProtocolDeclaration } from '@owlmeans/entrypoint'
3
+ import { entrypoint } from './entrypoint.js'
4
+ import type {
5
+ BoundEntrypointHandler, EntrypointOptions, ServerProtocolEntrypoint,
6
+ } from './types.js'
7
+
8
+ /** Bind one immutable protocol and, when present, its protocol-bound implementation. */
9
+ export const bind = <Protocol extends EntrypointProtocolDeclaration>(
10
+ protocol: Protocol,
11
+ implementation?: BoundEntrypointHandler<Protocol>,
12
+ options?: EntrypointOptions<object>,
13
+ ): ServerProtocolEntrypoint<Protocol> => {
14
+ const bound = Object.assign(entrypoint(
15
+ materializeEntrypoint(protocol),
16
+ implementation?.bind,
17
+ options,
18
+ ), { protocol })
19
+
20
+ return bound as ServerProtocolEntrypoint<Protocol>
21
+ }
package/src/types.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  import type { ServerRouteModel, ServerRouteOptions } from '@owlmeans/server-route'
2
- import type { CommonEntrypoint, EntrypointHandler, CommonEntrypointOptions } from '@owlmeans/entrypoint'
2
+ import type {
3
+ CommonEntrypoint, EntrypointHandler, CommonEntrypointOptions, EntrypointProtocolDeclaration,
4
+ } from '@owlmeans/entrypoint'
3
5
  import type { Service } from '@owlmeans/context'
4
6
 
5
7
  export interface ServerEntrypoint<R> extends CommonEntrypoint {
@@ -25,3 +27,14 @@ export interface EntrypointRef<R> {
25
27
  export interface RefedEntrypointHandler<R = {}> {
26
28
  (ref: EntrypointRef<R>): EntrypointHandler
27
29
  }
30
+
31
+ /** The server-local representation of a shared protocol declaration. */
32
+ export type ServerProtocolEntrypoint<Protocol extends EntrypointProtocolDeclaration> = ServerEntrypoint<object> & {
33
+ readonly protocol: Protocol
34
+ }
35
+
36
+ /** A handler that is inseparable from the protocol whose request it accepts. */
37
+ export interface BoundEntrypointHandler<Protocol extends EntrypointProtocolDeclaration> {
38
+ readonly protocol: Protocol
39
+ bind: RefedEntrypointHandler
40
+ }