@owlmeans/entrypoint 0.1.18-rc.1 → 0.1.18-rc.10
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 +23 -5
- package/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/entrypoint/SKILL.md +107 -13
- package/build/consts.d.ts +5 -0
- package/build/consts.d.ts.map +1 -1
- package/build/consts.js +5 -0
- package/build/consts.js.map +1 -1
- package/build/entrypoint.d.ts +0 -1
- package/build/entrypoint.d.ts.map +1 -1
- package/build/entrypoint.js +19 -57
- package/build/entrypoint.js.map +1 -1
- package/build/filter.d.ts.map +1 -1
- package/build/helper.d.ts +1 -2
- package/build/helper.d.ts.map +1 -1
- package/build/helper.js +0 -9
- package/build/helper.js.map +1 -1
- package/build/types.d.ts +60 -10
- package/build/types.d.ts.map +1 -1
- package/build/utils/entrypoint.d.ts.map +1 -1
- package/build/utils/entrypoint.js +1 -1
- package/build/utils/entrypoint.js.map +1 -1
- package/build/utils/types.d.ts +2 -2
- package/build/utils/types.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/consts.ts +6 -0
- package/src/entrypoint.ts +21 -65
- package/src/helper.ts +1 -12
- package/src/types.ts +63 -10
- package/src/utils/entrypoint.ts +1 -1
- package/src/utils/types.ts +2 -2
package/README.md
CHANGED
|
@@ -4,12 +4,17 @@ Entrypoint system — the URL unit abstraction shared between server and client
|
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
- An **entrypoint** is a URL unit: an alias +
|
|
7
|
+
- An **entrypoint** is a URL unit: an alias + a route declaration + optional guards/gates/filters
|
|
8
8
|
- On the server, entrypoints become API routes with attached handlers
|
|
9
9
|
- On the client, entrypoints provide URL generation and navigation
|
|
10
10
|
- All AJV validation schemas are defined at entrypoint level, keeping data contracts consistent fullstack
|
|
11
11
|
- Most commonly used via re-exports in `@owlmeans/server-app` or `@owlmeans/client-entrypoint`
|
|
12
12
|
|
|
13
|
+
The route declaration an entrypoint carries is immutable: its `path` always stays the segment this
|
|
14
|
+
entrypoint contributes under its parent. Addresses are computed on demand against the context the
|
|
15
|
+
entrypoint is registered in — `path()` walks the parent chain, `mount()` adds the service base,
|
|
16
|
+
`address()` picks host, port and scheme — so one declaration answers correctly on both sides.
|
|
17
|
+
|
|
13
18
|
## Installation
|
|
14
19
|
|
|
15
20
|
```bash
|
|
@@ -24,7 +29,7 @@ Define an entrypoint with body validation and a guard:
|
|
|
24
29
|
import { entrypoint, guard, filter, body, params } from '@owlmeans/server-app'
|
|
25
30
|
import { route } from '@owlmeans/route'
|
|
26
31
|
|
|
27
|
-
const
|
|
32
|
+
const createStoryEntrypoint = entrypoint(
|
|
28
33
|
route('story-create', '/stories', { method: 'POST', parent: 'api' }),
|
|
29
34
|
filter(body({
|
|
30
35
|
type: 'object',
|
|
@@ -67,14 +72,24 @@ Attaches validation schemas (AJV format) to the entrypoint.
|
|
|
67
72
|
|
|
68
73
|
Build a `Filter` object with the given AJV schema applied to the corresponding request part.
|
|
69
74
|
|
|
70
|
-
###
|
|
75
|
+
### Parentship
|
|
71
76
|
|
|
72
|
-
|
|
77
|
+
A child names its parent in the route declaration (`route('story-create', '/stories', { parent: 'api' })`).
|
|
78
|
+
`path()` prefixes the parent's segments, and `getGuards()` / `getGates()` collect the parent's on
|
|
79
|
+
every call — so a guard added to a parent later still applies.
|
|
73
80
|
|
|
74
81
|
### `provideResponse<T>(): AbstractResponse<T>`
|
|
75
82
|
|
|
76
83
|
Creates a response object for use in non-elevated handlers.
|
|
77
84
|
|
|
85
|
+
### Transport
|
|
86
|
+
|
|
87
|
+
A route's protocol picks the carrier. Register a service under `transportAlias(protocol)` —
|
|
88
|
+
`transport:<protocol>` — implementing `EntrypointTransport { protocol, handle }`, and every call to
|
|
89
|
+
an entrypoint on that protocol goes through it. A consumer writes `ep.call(...)` and never learns
|
|
90
|
+
whether that became an HTTP request, a socket message or a queued job. Without a registered
|
|
91
|
+
transport the call goes over HTTP.
|
|
92
|
+
|
|
78
93
|
### `EntrypointOutcome`
|
|
79
94
|
|
|
80
95
|
```typescript
|
|
@@ -85,7 +100,10 @@ enum EntrypointOutcome { Ok, Accepted, Created, Finished }
|
|
|
85
100
|
|
|
86
101
|
- `AbstractRequest<T>` — request with `params`, `body`, `query`, `headers`, `auth`
|
|
87
102
|
- `AbstractResponse<T>` — response with `resolve(value, outcome?)` and `reject(error)`
|
|
88
|
-
- `CommonEntrypoint` — entrypoint with `
|
|
103
|
+
- `CommonEntrypoint` — entrypoint with `alias`, `route`, `handle`, and the context-computed
|
|
104
|
+
`segment()`, `path()`, `mount()`, `service()`, `address()`, `isLocal()`, `parent()`,
|
|
105
|
+
`getGuards()`, `getGates()`
|
|
106
|
+
- `EntrypointTransport` — `{ protocol, handle }`, the service that carries a call for one protocol
|
|
89
107
|
|
|
90
108
|
## Related Packages
|
|
91
109
|
|
package/agent-meta/manifest.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
3
|
"package": "@owlmeans/entrypoint",
|
|
4
|
-
"version": "0.1.18-rc.
|
|
5
|
-
"generatedAt": "2026-
|
|
4
|
+
"version": "0.1.18-rc.10",
|
|
5
|
+
"generatedAt": "2026-09-01T17:39:40.768Z",
|
|
6
6
|
"canonicalRepo": "https://github.com/owlmeans/common",
|
|
7
7
|
"entries": [
|
|
8
8
|
{
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: entrypoint
|
|
3
|
-
description: How to use @owlmeans/entrypoint — declarative entrypoint
|
|
3
|
+
description: How to use @owlmeans/entrypoint — declarative entrypoint definitions over immutable route declarations, with entrypoint(), guard(), gate(), filter(), body(), params(), query() builders, the address accessors, and the transport seam. Auto-invoked when importing from this package or defining a service entrypoint declaration.
|
|
4
4
|
user-invocable: false
|
|
5
5
|
---
|
|
6
6
|
<!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
|
|
@@ -8,27 +8,121 @@ user-invocable: false
|
|
|
8
8
|
# @owlmeans/entrypoint
|
|
9
9
|
|
|
10
10
|
**Layer:** Core
|
|
11
|
-
**Install:** `"@owlmeans/entrypoint": "^0.1.18-rc.
|
|
11
|
+
**Install:** `"@owlmeans/entrypoint": "^0.1.18-rc.10"` in `dependencies`
|
|
12
|
+
|
|
13
|
+
An entrypoint is a **URL unit**: an immutable route declaration plus the guards, gates and schemas
|
|
14
|
+
it answers under. It is the single concept an application declares once in a shared package and
|
|
15
|
+
elevates on either side.
|
|
12
16
|
|
|
13
17
|
## Key Exports
|
|
14
18
|
|
|
15
19
|
| Export | Description |
|
|
16
20
|
|--------|-------------|
|
|
17
|
-
| `entrypoint(
|
|
18
|
-
| `guard(alias,
|
|
19
|
-
| `gate(alias,
|
|
20
|
-
| `filter(
|
|
21
|
-
| `body(Schema)` | AJV
|
|
22
|
-
| `
|
|
23
|
-
| `
|
|
24
|
-
| `
|
|
21
|
+
| `entrypoint(route, opts?)` | Declare an entrypoint on a route model |
|
|
22
|
+
| `guard(alias, opts?)` | Require a guard; returns options, so it wraps rather than takes them |
|
|
23
|
+
| `gate(alias, params, opts?)` | Require a gate; passed as the `opts` of `guard(...)` |
|
|
24
|
+
| `filter(filter, opts?)` | Attach request validators |
|
|
25
|
+
| `body(Schema)` / `params(Schema)` / `query(Schema)` / `headers(Schema)` / `response(Schema, code?)` | AJV validators composed into a `Filter` |
|
|
26
|
+
| `CommonEntrypoint` | The entrypoint interface — declaration, guards/gates, address accessors |
|
|
27
|
+
| `AbstractRequest` / `AbstractResponse` | The request and reply shapes every handler sees |
|
|
28
|
+
| `provideResponse(original?)` | Build a reply object a handler resolves or rejects |
|
|
29
|
+
| `GuardService` / `GateService` | What a guard and a gate implement |
|
|
25
30
|
| `EntrypointOutcome` | Enum: Ok, Accepted, Created, Finished |
|
|
26
|
-
|
|
|
31
|
+
| `EntrypointTransport` | `{ protocol, handle }` — a carrier bound to a route protocol |
|
|
32
|
+
| `transportAlias(protocol?)` | The service alias a transport registers under (`transport:<protocol>`) |
|
|
33
|
+
|
|
34
|
+
`guard`, `gate` and `filter` are **options-object combinators, not variadic composers**. Each
|
|
35
|
+
returns a `CommonEntrypointOptions` and takes the next one as its final argument, so they nest:
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
entrypoint(
|
|
39
|
+
route(app.api.item.remove, '/:id', { parent: app.api.item, method: RouteMethod.DELETE }),
|
|
40
|
+
guard(DEFAULT_GUARD, gate(OIDC_GATE, ['item--delete@id']))
|
|
41
|
+
)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Guards and gates are **inherited by child entrypoints** and enforced by the framework before a
|
|
45
|
+
handler runs — a handler that re-checks them is duplicating an enforced rule, and is wrong even
|
|
46
|
+
when it agrees.
|
|
27
47
|
|
|
28
48
|
## Subpath Exports
|
|
29
49
|
|
|
30
50
|
- `./utils` — entrypoint construction helpers (`isEntrypoint`, `CreateEntrypointSignature`)
|
|
31
51
|
|
|
52
|
+
## Declaration and model
|
|
53
|
+
|
|
54
|
+
The `RouteDeclaration` an entrypoint carries is plain, immutable data: its `path` is the **segment**
|
|
55
|
+
this entrypoint contributes under its parent, and nothing rewrites it. `RouteModel` only wraps that
|
|
56
|
+
declaration. Every address question is therefore a question about the declaration asked **against
|
|
57
|
+
the context that asks it** — computed on demand, never stored — so the same declaration answers one
|
|
58
|
+
way in a server and another in a client without being touched.
|
|
59
|
+
|
|
60
|
+
| Accessor | Answers |
|
|
61
|
+
|----------|---------|
|
|
62
|
+
| `segment()` | The segment declared under the parent |
|
|
63
|
+
| `path()` | Every ancestor's segment, then this one |
|
|
64
|
+
| `mount()` | `base` + `path()` — what a server registers and a client requests |
|
|
65
|
+
| `service()` | The resolved service route this entrypoint answers on |
|
|
66
|
+
| `address()` | `{ host, port, base, secure, protocol }` — where it actually answers |
|
|
67
|
+
| `isLocal()` | Does it belong to the service the asking context IS? |
|
|
68
|
+
| `parent()` | The parent entrypoint, or `null` |
|
|
69
|
+
| `getGuards()` | Own guards plus every ancestor's, deduped |
|
|
70
|
+
| `getGates()` | Own gate plus every ancestor's, as `[gate, params]` |
|
|
71
|
+
|
|
72
|
+
`getGuards()` and `getGates()` walk the chain afresh on every call and are never memoised: a guard
|
|
73
|
+
attached to an ancestor after this entrypoint was first asked still has to count.
|
|
74
|
+
|
|
75
|
+
## Calling an entrypoint
|
|
76
|
+
|
|
77
|
+
Three explicit verbs, so the caller says which answer it wants:
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
const project = await ep.call({ params: { id } }) // the VALUE; the reply error is thrown
|
|
81
|
+
const { value, outcome } = await ep.invoke({ body }) // value AND outcome
|
|
82
|
+
const href = await ep.url({ params: { id } }, { absolute: true }) // the URL string
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Use `invoke` only where the outcome decides what happens next; `call` covers everything else. An
|
|
86
|
+
entrypoint that **renders a screen** is addressed by URL and never over the wire — it throws from
|
|
87
|
+
`call()`/`invoke()` telling the caller to use `url()`.
|
|
88
|
+
|
|
89
|
+
The three verbs sit on the callable entrypoint that `@owlmeans/client-entrypoint` produces; the
|
|
90
|
+
declaration built here is what they address.
|
|
91
|
+
|
|
92
|
+
## Elevation
|
|
93
|
+
|
|
94
|
+
`elevate` replaces the declaration in the entrypoint list with its elevated counterpart, so it is
|
|
95
|
+
**idempotent**: elevating the same alias again simply replaces the element once more. Guards passed
|
|
96
|
+
at elevation are **unioned** with the ones the entrypoint declared — elevating adds guards, it never
|
|
97
|
+
swaps them. Server-side elevation lives in `@owlmeans/server-entrypoint`, client-side callability is
|
|
98
|
+
an explicit opt-in through `@owlmeans/client-entrypoint`.
|
|
99
|
+
|
|
100
|
+
## Transport seam
|
|
101
|
+
|
|
102
|
+
A route names the protocol it answers on, and a protocol may be carried by something other than
|
|
103
|
+
HTTP. A service registered under `transportAlias(protocol)` implementing `EntrypointTransport` takes
|
|
104
|
+
the call, so a consumer writes `ep.call(...)` and never learns whether that became an HTTP request,
|
|
105
|
+
a socket message or a queued job. Bind nothing and the call goes over HTTP.
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
import { transportAlias } from '@owlmeans/entrypoint'
|
|
109
|
+
import type { EntrypointTransport } from '@owlmeans/entrypoint'
|
|
110
|
+
import { RouteProtocols } from '@owlmeans/route'
|
|
111
|
+
import { createService } from '@owlmeans/context'
|
|
112
|
+
|
|
113
|
+
const transport = createService<EntrypointTransport>(transportAlias(RouteProtocols.SOCKET), {
|
|
114
|
+
protocol: RouteProtocols.SOCKET,
|
|
115
|
+
handle: async (req, res) => { /* carry the call, resolve or reject res */ }
|
|
116
|
+
}, service => async () => { service.initialized = true })
|
|
117
|
+
|
|
118
|
+
context.registerService(transport)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
`@owlmeans/queue` is the worked example: `appendQueueTransport(context)` binds
|
|
122
|
+
`RouteProtocols.QUEUE`, and a declaration built with `job()` instead of `backend()` is then carried
|
|
123
|
+
as a broker job. Nothing at the call site changes — which is the point of putting the protocol on
|
|
124
|
+
the route rather than at the call.
|
|
125
|
+
|
|
32
126
|
## Usage
|
|
33
127
|
|
|
34
128
|
Define entrypoints in a shared `common` package, then `elevate()` them with handlers in server/web packages:
|
|
@@ -40,7 +134,7 @@ import { DEFAULT_GUARD } from '@owlmeans/auth-common'
|
|
|
40
134
|
import { OIDC_GATE } from '@owlmeans/oidc'
|
|
41
135
|
import { CreateProjectSchema } from './schemas.js'
|
|
42
136
|
|
|
43
|
-
export const
|
|
137
|
+
export const managerEntrypoints = [
|
|
44
138
|
entrypoint(
|
|
45
139
|
route(manager.back.account.base, '/account'),
|
|
46
140
|
guard(DEFAULT_GUARD, gate(OIDC_GATE, [`my-service-account-{entity}`]))
|
|
@@ -57,6 +151,6 @@ export const managerModules = [
|
|
|
57
151
|
|
|
58
152
|
## Depends On
|
|
59
153
|
|
|
60
|
-
- `@owlmeans/route` — `route()`, `RouteMethod`
|
|
154
|
+
- `@owlmeans/route` — `route()`, `RouteMethod`, `RouteProtocols`, and the address helpers under `/utils`
|
|
61
155
|
- `@owlmeans/auth-common` — guard aliases (`DEFAULT_GUARD`)
|
|
62
156
|
- `@owlmeans/error`, `@owlmeans/i18n`
|
package/build/consts.d.ts
CHANGED
|
@@ -4,4 +4,9 @@ export declare enum EntrypointOutcome {
|
|
|
4
4
|
Created = "created",
|
|
5
5
|
Finished = "finished"
|
|
6
6
|
}
|
|
7
|
+
/**
|
|
8
|
+
* Service alias a transport registers under. The default protocol is the web one, so an application
|
|
9
|
+
* that binds nothing keeps talking HTTP.
|
|
10
|
+
*/
|
|
11
|
+
export declare const transportAlias: (protocol?: string) => string;
|
|
7
12
|
//# sourceMappingURL=consts.d.ts.map
|
package/build/consts.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AACA,oBAAY,iBAAiB;IAC3B,EAAE,OAAO;IACT,QAAQ,aAAa;IACrB,OAAO,YAAY;IACnB,QAAQ,aAAa;CACtB"}
|
|
1
|
+
{"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AACA,oBAAY,iBAAiB;IAC3B,EAAE,OAAO;IACT,QAAQ,aAAa;IACrB,OAAO,YAAY;IACnB,QAAQ,aAAa;CACtB;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,GAAI,WAAU,MAAe,WAA4B,CAAA"}
|
package/build/consts.js
CHANGED
|
@@ -5,4 +5,9 @@ export var EntrypointOutcome;
|
|
|
5
5
|
EntrypointOutcome["Created"] = "created";
|
|
6
6
|
EntrypointOutcome["Finished"] = "finished";
|
|
7
7
|
})(EntrypointOutcome || (EntrypointOutcome = {}));
|
|
8
|
+
/**
|
|
9
|
+
* Service alias a transport registers under. The default protocol is the web one, so an application
|
|
10
|
+
* that binds nothing keeps talking HTTP.
|
|
11
|
+
*/
|
|
12
|
+
export const transportAlias = (protocol = 'http') => `transport:${protocol}`;
|
|
8
13
|
//# sourceMappingURL=consts.js.map
|
package/build/consts.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consts.js","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AACA,MAAM,CAAN,IAAY,iBAKX;AALD,WAAY,iBAAiB;IAC3B,8BAAS,CAAA;IACT,0CAAqB,CAAA;IACrB,wCAAmB,CAAA;IACnB,0CAAqB,CAAA;AACvB,CAAC,EALW,iBAAiB,KAAjB,iBAAiB,QAK5B"}
|
|
1
|
+
{"version":3,"file":"consts.js","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AACA,MAAM,CAAN,IAAY,iBAKX;AALD,WAAY,iBAAiB;IAC3B,8BAAS,CAAA;IACT,0CAAqB,CAAA;IACrB,wCAAmB,CAAA;IACnB,0CAAqB,CAAA;AACvB,CAAC,EALW,iBAAiB,KAAjB,iBAAiB,QAK5B;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,WAAmB,MAAM,EAAE,EAAE,CAAC,aAAa,QAAQ,EAAE,CAAA"}
|
package/build/entrypoint.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { CommonEntrypoint } from './types.js';
|
|
2
2
|
import type { CreateEntrypointSignature } from './utils/types.js';
|
|
3
3
|
export declare const entrypoint: CreateEntrypointSignature<CommonEntrypoint>;
|
|
4
|
-
export declare const parent: <T extends CommonEntrypoint | CommonEntrypoint[]>(ep: T, aliasOrParent: string, _parent?: string) => T;
|
|
5
4
|
//# sourceMappingURL=entrypoint.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entrypoint.d.ts","sourceRoot":"","sources":["../src/entrypoint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"entrypoint.d.ts","sourceRoot":"","sources":["../src/entrypoint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAKlD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAA;AAEjE,eAAO,MAAM,UAAU,EAAE,yBAAyB,CAAC,gBAAgB,CAsDlE,CAAA"}
|
package/build/entrypoint.js
CHANGED
|
@@ -1,61 +1,37 @@
|
|
|
1
1
|
import { appendContextual } from '@owlmeans/context';
|
|
2
|
+
import { isLocalRoute, resolveAddress, resolveMount, resolvePath, resolveService } from '@owlmeans/route/utils';
|
|
2
3
|
export const entrypoint = (route, opts) => {
|
|
3
|
-
let guards = null;
|
|
4
|
-
let gates = null;
|
|
5
4
|
const ep = appendContextual(route.route.alias, {
|
|
6
5
|
_entrypoint: true,
|
|
7
|
-
_module: true,
|
|
8
6
|
sticky: false,
|
|
9
7
|
route,
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
},
|
|
21
|
-
getParent: () => {
|
|
22
|
-
const parentAlias = ep.getParentAlias();
|
|
23
|
-
if (parentAlias == null) {
|
|
24
|
-
throw new SyntaxError(`Entrypoint has no parent - ${ep.getAlias()}`);
|
|
25
|
-
}
|
|
26
|
-
if (ep.ctx == null) {
|
|
27
|
-
throw new SyntaxError(`Entrypoint has no context yet - ${ep.getAlias()}`);
|
|
28
|
-
}
|
|
29
|
-
return ep.ctx.entrypoint(parentAlias);
|
|
30
|
-
},
|
|
31
|
-
setService: service => {
|
|
32
|
-
if (ep.route.route.resolved) {
|
|
33
|
-
throw new SyntaxError(`Cannot update a resolved entrypoint - ${ep.getAlias()}`);
|
|
34
|
-
}
|
|
35
|
-
ep.route.route.service = service;
|
|
36
|
-
},
|
|
8
|
+
segment: () => ep.route.route.path,
|
|
9
|
+
path: () => resolvePath(ep.assertCtx(), ep.route.route),
|
|
10
|
+
mount: () => resolveMount(ep.assertCtx(), ep.route.route),
|
|
11
|
+
service: () => resolveService(ep.assertCtx(), ep.route.route),
|
|
12
|
+
address: () => resolveAddress(ep.assertCtx(), ep.route.route),
|
|
13
|
+
isLocal: () => isLocalRoute(ep.assertCtx(), ep.route.route),
|
|
14
|
+
parent: () => ep.route.route.parent == null ? null
|
|
15
|
+
: ep.assertCtx().entrypoint(ep.route.route.parent),
|
|
16
|
+
// Walked afresh on every call: a guard attached to an ancestor after this entrypoint was first
|
|
17
|
+
// asked still has to count.
|
|
37
18
|
getGuards: () => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (ep.hasParent()) {
|
|
43
|
-
guards.push(...ep.getParent().getGuards().filter(guard => !guards?.includes(guard)));
|
|
19
|
+
const guards = [...ep.guards ?? []];
|
|
20
|
+
const parent = ep.parent();
|
|
21
|
+
if (parent != null) {
|
|
22
|
+
guards.push(...parent.getGuards().filter(guard => !guards.includes(guard)));
|
|
44
23
|
}
|
|
45
24
|
return guards;
|
|
46
25
|
},
|
|
47
26
|
getGates: () => {
|
|
48
|
-
|
|
49
|
-
return gates;
|
|
50
|
-
}
|
|
51
|
-
gates = ep.gate != null ? [[
|
|
27
|
+
const gates = ep.gate != null ? [[
|
|
52
28
|
ep.gate, ep.gateParams == null
|
|
53
29
|
? [] : Array.isArray(ep.gateParams)
|
|
54
30
|
? ep.gateParams : [ep.gateParams]
|
|
55
31
|
]] : [];
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
32
|
+
const parent = ep.parent();
|
|
33
|
+
if (parent != null) {
|
|
34
|
+
gates.push(...parent.getGates().filter(([gate]) => !gates.some(([g]) => g === gate)));
|
|
59
35
|
}
|
|
60
36
|
return gates;
|
|
61
37
|
},
|
|
@@ -63,18 +39,4 @@ export const entrypoint = (route, opts) => {
|
|
|
63
39
|
});
|
|
64
40
|
return ep;
|
|
65
41
|
};
|
|
66
|
-
export const parent = (ep, aliasOrParent, _parent) => {
|
|
67
|
-
if (Array.isArray(ep)) {
|
|
68
|
-
if (_parent == null) {
|
|
69
|
-
throw SyntaxError('Elevating parent requires parent name to be specified');
|
|
70
|
-
}
|
|
71
|
-
ep = ep.find(e => e.route.route.alias === aliasOrParent);
|
|
72
|
-
if (ep == null) {
|
|
73
|
-
throw SyntaxError(`Entrypoint not found ${aliasOrParent}`);
|
|
74
|
-
}
|
|
75
|
-
return parent(ep, _parent);
|
|
76
|
-
}
|
|
77
|
-
ep.route.route.parent = aliasOrParent;
|
|
78
|
-
return ep;
|
|
79
|
-
};
|
|
80
42
|
//# sourceMappingURL=entrypoint.js.map
|
package/build/entrypoint.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entrypoint.js","sourceRoot":"","sources":["../src/entrypoint.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"entrypoint.js","sourceRoot":"","sources":["../src/entrypoint.ts"],"names":[],"mappings":"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"}
|
package/build/filter.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../src/filter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,KAAK,CAAA;AACzC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAExC,eAAO,MAAM,IAAI,GAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../src/filter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,KAAK,CAAA;AACzC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAExC,eAAO,MAAM,IAAI,GAAI,CAAC,EAAE,QAAQ,cAAc,CAAC,CAAC,CAAC,EAAE,SAAS,MAAM,KAAG,MAEpE,CAAA;AAED,eAAO,MAAM,KAAK,GAAI,CAAC,EAAE,QAAQ,cAAc,CAAC,CAAC,CAAC,EAAE,SAAS,MAAM,KAAG,MAErE,CAAA;AAED,eAAO,MAAM,MAAM,GAAI,CAAC,EAAE,QAAQ,cAAc,CAAC,CAAC,CAAC,EAAE,SAAS,MAAM,KAAG,MAEtE,CAAA;AAED,eAAO,MAAM,QAAQ,GAAI,CAAC,EAAE,QAAQ,cAAc,CAAC,CAAC,CAAC,EAAE,OAAO,MAAM,EAAE,SAAS,MAAM,KAAG,MAMvF,CAAA;AAED,eAAO,MAAM,OAAO,GAAI,CAAC,EAAE,QAAQ,cAAc,CAAC,CAAC,CAAC,EAAE,SAAS,MAAM,KAAG,MAEvE,CAAA"}
|
package/build/helper.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { Filter, CommonEntrypointOptions, AbstractResponse
|
|
1
|
+
import { Filter, CommonEntrypointOptions, AbstractResponse } from './types.js';
|
|
2
2
|
export declare const filter: (filter: Filter, opts?: CommonEntrypointOptions) => CommonEntrypointOptions;
|
|
3
3
|
export declare const guard: (guard: string, opts?: CommonEntrypointOptions) => CommonEntrypointOptions;
|
|
4
4
|
export declare const gate: (gate: string, params: string | string[], opts?: CommonEntrypointOptions) => CommonEntrypointOptions;
|
|
5
5
|
export declare const provideResponse: <T>(originalResponse?: unknown) => AbstractResponse<T>;
|
|
6
|
-
export declare const clone: <M extends CommonEntrypoint>(entrypoints: M[], from: string, to: string, service: string) => void;
|
|
7
6
|
//# 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":"
|
|
1
|
+
{"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAE9E,eAAO,MAAM,MAAM,GAAI,QAAQ,MAAM,EAAE,OAAO,uBAAuB,KAAG,uBAAgD,CAAA;AAExH,eAAO,MAAM,KAAK,GAAI,OAAO,MAAM,EAAE,OAAO,uBAAuB,KAAG,uBACC,CAAA;AAEvE,eAAO,MAAM,IAAI,GAAI,MAAM,MAAM,EAAE,QAAQ,MAAM,GAAG,MAAM,EAAE,EAAE,OAAO,uBAAuB,KAAG,uBACtD,CAAA;AAEzC,eAAO,MAAM,eAAe,GAAI,CAAC,EAAE,mBAAmB,OAAO,KAAG,gBAAgB,CAAC,CAAC,CAejF,CAAA"}
|
package/build/helper.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { route } from '@owlmeans/route';
|
|
2
|
-
import { entrypoint } from './entrypoint.js';
|
|
3
1
|
export const filter = (filter, opts) => ({ filter, ...opts });
|
|
4
2
|
export const guard = (guard, opts) => ({ ...opts, guards: [...new Set([guard, ...(opts?.guards ?? [])])] });
|
|
5
3
|
export const gate = (gate, params, opts) => ({ ...opts, gate, gateParams: params });
|
|
@@ -16,11 +14,4 @@ export const provideResponse = (originalResponse) => {
|
|
|
16
14
|
};
|
|
17
15
|
return handler;
|
|
18
16
|
};
|
|
19
|
-
export const clone = (entrypoints, from, to, service) => {
|
|
20
|
-
const source = entrypoints.find(e => e.alias === from);
|
|
21
|
-
if (source?.route.route != null) {
|
|
22
|
-
const _route = { ...source.route.route, service, resolved: false, alias: to };
|
|
23
|
-
entrypoints.push(entrypoint(route(to, _route.path, _route)));
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
17
|
//# 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":"
|
|
1
|
+
{"version":3,"file":"helper.js","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,MAAc,EAAE,IAA8B,EAA2B,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,CAAC,CAAA;AAExH,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,KAAa,EAAE,IAA8B,EAA2B,EAAE,CAC9F,CAAC,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;AAEvE,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,MAAyB,EAAE,IAA8B,EAA2B,EAAE,CACvH,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CAAA;AAEzC,MAAM,CAAC,MAAM,eAAe,GAAG,CAAI,gBAA0B,EAAuB,EAAE;IACpF,MAAM,OAAO,GAAwB;QACnC,gBAAgB,EAAE,gBAAgB;QAElC,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YAC1B,OAAO,CAAC,KAAK,GAAG,KAAK,CAAA;YACrB,OAAO,CAAC,OAAO,GAAG,OAAO,CAAA;QAC3B,CAAC;QAED,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YAChB,OAAO,CAAC,KAAK,GAAG,KAAK,CAAA;QACvB,CAAC;KACF,CAAA;IAED,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA"}
|
package/build/types.d.ts
CHANGED
|
@@ -1,28 +1,42 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ResolvedServiceRoute, RouteAddress, RouteModel, RouteProtocols } from '@owlmeans/route';
|
|
2
2
|
import type { InitializedService, LazyService, BasicEntrypoint } from '@owlmeans/context';
|
|
3
3
|
import type { AnySchemaObject } from 'ajv';
|
|
4
4
|
import type { EntrypointOutcome } from './consts.js';
|
|
5
5
|
import type { Auth } from '@owlmeans/auth';
|
|
6
|
+
/**
|
|
7
|
+
* A URL unit: an immutable route declaration plus what guards, gates and schemas it answers under.
|
|
8
|
+
*
|
|
9
|
+
* Nothing here is rewritten once declared. Every address question — segment, path, mount, service,
|
|
10
|
+
* host — is a question about the declaration asked against the context the entrypoint is registered
|
|
11
|
+
* in, so the same declaration answers differently in a client and in a server without being touched.
|
|
12
|
+
*/
|
|
6
13
|
export interface CommonEntrypoint extends BasicEntrypoint {
|
|
7
|
-
route:
|
|
14
|
+
route: RouteModel;
|
|
8
15
|
/**
|
|
9
16
|
* @property {boolean} - if true — router attaches this entrypoint unconditionally
|
|
10
17
|
* @default false
|
|
11
18
|
*/
|
|
12
19
|
sticky: boolean;
|
|
13
|
-
|
|
20
|
+
/** The guards declared on this entrypoint alone — see `getGuards()` for the inherited set. */
|
|
14
21
|
guards?: string[];
|
|
15
22
|
gate?: string;
|
|
16
23
|
gateParams?: string | string[];
|
|
24
|
+
filter?: Filter;
|
|
17
25
|
handle?: EntrypointHandler;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
/** The segment this entrypoint contributes under its parent. */
|
|
27
|
+
segment: () => string;
|
|
28
|
+
/** Every ancestor's segment, then this one. */
|
|
29
|
+
path: () => string;
|
|
30
|
+
/** `base` + `path()` — what a server mounts and a client requests. */
|
|
31
|
+
mount: () => string;
|
|
32
|
+
service: () => ResolvedServiceRoute;
|
|
33
|
+
address: () => RouteAddress;
|
|
34
|
+
/** Does this entrypoint belong to the service its context IS? */
|
|
35
|
+
isLocal: () => boolean;
|
|
36
|
+
parent: () => CommonEntrypoint | null;
|
|
37
|
+
/** Own guards and every ancestor's, deduped. Recomputed on each call. */
|
|
25
38
|
getGuards: () => string[];
|
|
39
|
+
/** Own gate and every ancestor's, as `[gate, params]`. Recomputed on each call. */
|
|
26
40
|
getGates: () => [string, string[]][];
|
|
27
41
|
}
|
|
28
42
|
export interface CommonEntrypointOptions extends Partial<CommonEntrypoint> {
|
|
@@ -39,6 +53,17 @@ export interface EntrypointAssert {
|
|
|
39
53
|
export interface AbstractRequest<T extends {} = {}> {
|
|
40
54
|
alias: string;
|
|
41
55
|
auth?: Auth;
|
|
56
|
+
/**
|
|
57
|
+
* The organization entity this request acts for, resolved from `auth.entitySlug` once, at the
|
|
58
|
+
* server boundary.
|
|
59
|
+
*
|
|
60
|
+
* The slug on the token is renameable and therefore unusable as a key; `entity.id` is the stable
|
|
61
|
+
* value that records, grants and minted infrastructure names are keyed by. Resolving it here —
|
|
62
|
+
* rather than in each handler — is what keeps a rename from meaning a sweep of every call site,
|
|
63
|
+
* and it is absent whenever no resolver is registered (an implementation that has no notion of
|
|
64
|
+
* an organization store), so consumers must handle that rather than assume it.
|
|
65
|
+
*/
|
|
66
|
+
entity?: ResolvedEntity;
|
|
42
67
|
params: Record<string, string | number | undefined | null> | Partial<T>;
|
|
43
68
|
body?: Record<string, any> | Partial<T>;
|
|
44
69
|
headers: Record<string, string[] | string | undefined>;
|
|
@@ -53,6 +78,20 @@ export interface AbstractRequest<T extends {} = {}> {
|
|
|
53
78
|
timeout?: number;
|
|
54
79
|
signal?: AbortSignal;
|
|
55
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* An organization entity as request handlers see it: the stable id to key by, the current slug to
|
|
83
|
+
* compose user-facing names from, and the frozen key that external systems already know it under.
|
|
84
|
+
*/
|
|
85
|
+
export interface ResolvedEntity {
|
|
86
|
+
id: string;
|
|
87
|
+
slug: string;
|
|
88
|
+
/**
|
|
89
|
+
* The identifier this organization is known by in systems whose names cannot be rewritten —
|
|
90
|
+
* an IAM realm, an object-storage prefix, a cluster object. Minted once and never recomputed,
|
|
91
|
+
* so it stays valid across every later rename.
|
|
92
|
+
*/
|
|
93
|
+
iamKey: string;
|
|
94
|
+
}
|
|
56
95
|
export interface AbstractResponse<T> {
|
|
57
96
|
responseProvider?: any;
|
|
58
97
|
value?: T;
|
|
@@ -80,4 +119,15 @@ export interface Filter {
|
|
|
80
119
|
response?: AnySchemaObject;
|
|
81
120
|
headers?: AnySchemaObject;
|
|
82
121
|
}
|
|
122
|
+
/**
|
|
123
|
+
* How a call to an entrypoint is actually carried.
|
|
124
|
+
*
|
|
125
|
+
* The transport is chosen by the route's protocol, so a consumer always writes `ep.call(...)` and
|
|
126
|
+
* never learns whether that became an HTTP request, a socket message or a queued job. An
|
|
127
|
+
* application binds a protocol by registering a transport service under `transportAlias(protocol)`.
|
|
128
|
+
*/
|
|
129
|
+
export interface EntrypointTransport extends InitializedService {
|
|
130
|
+
readonly protocol: RouteProtocols;
|
|
131
|
+
handle: EntrypointHandler;
|
|
132
|
+
}
|
|
83
133
|
//# 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,
|
|
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":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAE9C,eAAO,MAAM,YAAY,
|
|
1
|
+
{"version":3,"file":"entrypoint.d.ts","sourceRoot":"","sources":["../../src/utils/entrypoint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAE9C,eAAO,MAAM,YAAY,GAAI,KAAK,MAAM,KAAG,GAAG,IAAI,gBAC5B,CAAA"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const isEntrypoint = (obj) => '_entrypoint' in obj
|
|
1
|
+
export const isEntrypoint = (obj) => '_entrypoint' in obj;
|
|
2
2
|
//# sourceMappingURL=entrypoint.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entrypoint.js","sourceRoot":"","sources":["../../src/utils/entrypoint.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAW,EAA2B,EAAE,CACnE,aAAa,IAAI,GAAG,
|
|
1
|
+
{"version":3,"file":"entrypoint.js","sourceRoot":"","sources":["../../src/utils/entrypoint.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAW,EAA2B,EAAE,CACnE,aAAa,IAAI,GAAG,CAAA"}
|
package/build/utils/types.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RouteModel } from '@owlmeans/route';
|
|
2
2
|
import { CommonEntrypointOptions } from '../types.js';
|
|
3
3
|
export interface CreateEntrypointSignature<M> {
|
|
4
|
-
(route:
|
|
4
|
+
(route: RouteModel, opts?: CommonEntrypointOptions): M;
|
|
5
5
|
}
|
|
6
6
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/utils/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/utils/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAErD,MAAM,WAAW,yBAAyB,CAAC,CAAC;IAC1C,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,uBAAuB,GAAG,CAAC,CAAC;CACxD"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@owlmeans/entrypoint",
|
|
3
|
-
"version": "0.1.18-rc.
|
|
3
|
+
"version": "0.1.18-rc.10",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
}
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@owlmeans/auth": "^0.1.18-rc.
|
|
32
|
-
"@owlmeans/context": "^0.1.18-rc.
|
|
33
|
-
"@owlmeans/route": "^0.1.18-rc.
|
|
31
|
+
"@owlmeans/auth": "^0.1.18-rc.8",
|
|
32
|
+
"@owlmeans/context": "^0.1.18-rc.7",
|
|
33
|
+
"@owlmeans/route": "^0.1.18-rc.8",
|
|
34
34
|
"ajv": "^8.17.1"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
package/src/consts.ts
CHANGED
|
@@ -5,3 +5,9 @@ export enum EntrypointOutcome {
|
|
|
5
5
|
Created = 'created',
|
|
6
6
|
Finished = 'finished'
|
|
7
7
|
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Service alias a transport registers under. The default protocol is the web one, so an application
|
|
11
|
+
* that binds nothing keeps talking HTTP.
|
|
12
|
+
*/
|
|
13
|
+
export const transportAlias = (protocol: string = 'http') => `transport:${protocol}`
|
package/src/entrypoint.ts
CHANGED
|
@@ -1,83 +1,55 @@
|
|
|
1
1
|
import type { CommonEntrypoint } from './types.js'
|
|
2
2
|
import { appendContextual } from '@owlmeans/context'
|
|
3
|
+
import {
|
|
4
|
+
isLocalRoute, resolveAddress, resolveMount, resolvePath, resolveService
|
|
5
|
+
} from '@owlmeans/route/utils'
|
|
3
6
|
import type { CreateEntrypointSignature } from './utils/types.js'
|
|
4
7
|
|
|
5
8
|
export const entrypoint: CreateEntrypointSignature<CommonEntrypoint> = (route, opts) => {
|
|
6
|
-
let guards: string[] | null = null
|
|
7
|
-
let gates: [string, string[]][] | null = null
|
|
8
9
|
const ep: CommonEntrypoint = appendContextual<CommonEntrypoint>(route.route.alias, {
|
|
9
10
|
_entrypoint: true,
|
|
10
|
-
_module: true,
|
|
11
11
|
|
|
12
12
|
sticky: false,
|
|
13
13
|
|
|
14
14
|
route,
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
getPath: () => ep.route.route.path,
|
|
18
|
-
getParentAlias: () => ep.route.route.parent ?? null,
|
|
19
|
-
hasParent: () => ep.getParentAlias() != null,
|
|
16
|
+
segment: () => ep.route.route.path,
|
|
20
17
|
|
|
21
|
-
|
|
22
|
-
if (ep.ctx == null) {
|
|
23
|
-
throw new SyntaxError(`Entrypoint has no context yet - ${ep.getAlias()}`)
|
|
24
|
-
}
|
|
18
|
+
path: () => resolvePath(ep.assertCtx(), ep.route.route),
|
|
25
19
|
|
|
26
|
-
|
|
20
|
+
mount: () => resolveMount(ep.assertCtx(), ep.route.route),
|
|
27
21
|
|
|
28
|
-
|
|
29
|
-
},
|
|
22
|
+
service: () => resolveService(ep.assertCtx(), ep.route.route),
|
|
30
23
|
|
|
31
|
-
|
|
32
|
-
const parentAlias = ep.getParentAlias()
|
|
33
|
-
if (parentAlias == null) {
|
|
34
|
-
throw new SyntaxError(`Entrypoint has no parent - ${ep.getAlias()}`)
|
|
35
|
-
}
|
|
36
|
-
if (ep.ctx == null) {
|
|
37
|
-
throw new SyntaxError(`Entrypoint has no context yet - ${ep.getAlias()}`)
|
|
38
|
-
}
|
|
24
|
+
address: () => resolveAddress(ep.assertCtx(), ep.route.route),
|
|
39
25
|
|
|
40
|
-
|
|
41
|
-
},
|
|
26
|
+
isLocal: () => isLocalRoute(ep.assertCtx(), ep.route.route),
|
|
42
27
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
throw new SyntaxError(`Cannot update a resolved entrypoint - ${ep.getAlias()}`)
|
|
46
|
-
}
|
|
47
|
-
ep.route.route.service = service
|
|
48
|
-
},
|
|
28
|
+
parent: () => ep.route.route.parent == null ? null
|
|
29
|
+
: ep.assertCtx().entrypoint<CommonEntrypoint>(ep.route.route.parent),
|
|
49
30
|
|
|
31
|
+
// Walked afresh on every call: a guard attached to an ancestor after this entrypoint was first
|
|
32
|
+
// asked still has to count.
|
|
50
33
|
getGuards: () => {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (ep.hasParent()) {
|
|
57
|
-
guards.push(
|
|
58
|
-
...ep.getParent().getGuards().filter(guard => !guards?.includes(guard))
|
|
59
|
-
)
|
|
34
|
+
const guards = [...ep.guards ?? []]
|
|
35
|
+
const parent = ep.parent()
|
|
36
|
+
if (parent != null) {
|
|
37
|
+
guards.push(...parent.getGuards().filter(guard => !guards.includes(guard)))
|
|
60
38
|
}
|
|
61
39
|
|
|
62
40
|
return guards
|
|
63
41
|
},
|
|
64
42
|
|
|
65
43
|
getGates: () => {
|
|
66
|
-
|
|
67
|
-
return gates
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
gates = ep.gate != null ? [[
|
|
44
|
+
const gates: [string, string[]][] = ep.gate != null ? [[
|
|
71
45
|
ep.gate, ep.gateParams == null
|
|
72
46
|
? [] : Array.isArray(ep.gateParams)
|
|
73
47
|
? ep.gateParams : [ep.gateParams]
|
|
74
48
|
]] : []
|
|
75
49
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
.filter(([gate]) => !gates?.some(([g]) => g === gate))
|
|
80
|
-
)
|
|
50
|
+
const parent = ep.parent()
|
|
51
|
+
if (parent != null) {
|
|
52
|
+
gates.push(...parent.getGates().filter(([gate]) => !gates.some(([g]) => g === gate)))
|
|
81
53
|
}
|
|
82
54
|
|
|
83
55
|
return gates
|
|
@@ -88,19 +60,3 @@ export const entrypoint: CreateEntrypointSignature<CommonEntrypoint> = (route, o
|
|
|
88
60
|
|
|
89
61
|
return ep
|
|
90
62
|
}
|
|
91
|
-
|
|
92
|
-
export const parent = <T extends CommonEntrypoint | CommonEntrypoint[]>(ep: T, aliasOrParent: string, _parent?: string): T => {
|
|
93
|
-
if (Array.isArray(ep)) {
|
|
94
|
-
if (_parent == null) {
|
|
95
|
-
throw SyntaxError('Elevating parent requires parent name to be specified')
|
|
96
|
-
}
|
|
97
|
-
ep = ep.find(e => e.route.route.alias === aliasOrParent) as T
|
|
98
|
-
if (ep == null) {
|
|
99
|
-
throw SyntaxError(`Entrypoint not found ${aliasOrParent}`)
|
|
100
|
-
}
|
|
101
|
-
return parent(ep, _parent)
|
|
102
|
-
}
|
|
103
|
-
ep.route.route.parent = aliasOrParent
|
|
104
|
-
|
|
105
|
-
return ep
|
|
106
|
-
}
|
package/src/helper.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Filter, CommonEntrypointOptions, AbstractResponse, CommonEntrypoint } from './types.js'
|
|
3
|
-
import { entrypoint } from './entrypoint.js'
|
|
1
|
+
import { Filter, CommonEntrypointOptions, AbstractResponse } from './types.js'
|
|
4
2
|
|
|
5
3
|
export const filter = (filter: Filter, opts?: CommonEntrypointOptions): CommonEntrypointOptions => ({ filter, ...opts })
|
|
6
4
|
|
|
@@ -26,12 +24,3 @@ export const provideResponse = <T>(originalResponse?: unknown): AbstractResponse
|
|
|
26
24
|
|
|
27
25
|
return handler
|
|
28
26
|
}
|
|
29
|
-
|
|
30
|
-
export const clone = <M extends CommonEntrypoint>(entrypoints: M[], from: string, to: string, service: string) => {
|
|
31
|
-
const source = entrypoints.find(e => e.alias === from)
|
|
32
|
-
|
|
33
|
-
if (source?.route.route != null) {
|
|
34
|
-
const _route = { ...source.route.route, service, resolved: false, alias: to }
|
|
35
|
-
entrypoints.push(entrypoint(route(to, _route.path, _route)) as M)
|
|
36
|
-
}
|
|
37
|
-
}
|
package/src/types.ts
CHANGED
|
@@ -1,29 +1,44 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ResolvedServiceRoute, RouteAddress, RouteModel, RouteProtocols } from '@owlmeans/route'
|
|
2
2
|
import type { InitializedService, LazyService, BasicEntrypoint } from '@owlmeans/context'
|
|
3
3
|
import type { AnySchemaObject } from 'ajv'
|
|
4
4
|
import type { EntrypointOutcome } from './consts.js'
|
|
5
5
|
import type { Auth } from '@owlmeans/auth'
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* A URL unit: an immutable route declaration plus what guards, gates and schemas it answers under.
|
|
9
|
+
*
|
|
10
|
+
* Nothing here is rewritten once declared. Every address question — segment, path, mount, service,
|
|
11
|
+
* host — is a question about the declaration asked against the context the entrypoint is registered
|
|
12
|
+
* in, so the same declaration answers differently in a client and in a server without being touched.
|
|
13
|
+
*/
|
|
7
14
|
export interface CommonEntrypoint extends BasicEntrypoint {
|
|
8
|
-
route:
|
|
15
|
+
route: RouteModel
|
|
9
16
|
/**
|
|
10
17
|
* @property {boolean} - if true — router attaches this entrypoint unconditionally
|
|
11
18
|
* @default false
|
|
12
19
|
*/
|
|
13
20
|
sticky: boolean
|
|
14
|
-
|
|
21
|
+
/** The guards declared on this entrypoint alone — see `getGuards()` for the inherited set. */
|
|
15
22
|
guards?: string[]
|
|
16
23
|
gate?: string
|
|
17
24
|
gateParams?: string | string[]
|
|
25
|
+
filter?: Filter
|
|
18
26
|
handle?: EntrypointHandler
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
27
|
+
|
|
28
|
+
/** The segment this entrypoint contributes under its parent. */
|
|
29
|
+
segment: () => string
|
|
30
|
+
/** Every ancestor's segment, then this one. */
|
|
31
|
+
path: () => string
|
|
32
|
+
/** `base` + `path()` — what a server mounts and a client requests. */
|
|
33
|
+
mount: () => string
|
|
34
|
+
service: () => ResolvedServiceRoute
|
|
35
|
+
address: () => RouteAddress
|
|
36
|
+
/** Does this entrypoint belong to the service its context IS? */
|
|
37
|
+
isLocal: () => boolean
|
|
38
|
+
parent: () => CommonEntrypoint | null
|
|
39
|
+
/** Own guards and every ancestor's, deduped. Recomputed on each call. */
|
|
26
40
|
getGuards: () => string[]
|
|
41
|
+
/** Own gate and every ancestor's, as `[gate, params]`. Recomputed on each call. */
|
|
27
42
|
getGates: () => [string, string[]][]
|
|
28
43
|
}
|
|
29
44
|
|
|
@@ -47,6 +62,17 @@ export interface EntrypointAssert {
|
|
|
47
62
|
export interface AbstractRequest<T extends {} = {}> {
|
|
48
63
|
alias: string
|
|
49
64
|
auth?: Auth
|
|
65
|
+
/**
|
|
66
|
+
* The organization entity this request acts for, resolved from `auth.entitySlug` once, at the
|
|
67
|
+
* server boundary.
|
|
68
|
+
*
|
|
69
|
+
* The slug on the token is renameable and therefore unusable as a key; `entity.id` is the stable
|
|
70
|
+
* value that records, grants and minted infrastructure names are keyed by. Resolving it here —
|
|
71
|
+
* rather than in each handler — is what keeps a rename from meaning a sweep of every call site,
|
|
72
|
+
* and it is absent whenever no resolver is registered (an implementation that has no notion of
|
|
73
|
+
* an organization store), so consumers must handle that rather than assume it.
|
|
74
|
+
*/
|
|
75
|
+
entity?: ResolvedEntity
|
|
50
76
|
params: Record<string, string | number | undefined | null> | Partial<T>
|
|
51
77
|
body?: Record<string, any> | Partial<T>
|
|
52
78
|
headers: Record<string, string[] | string | undefined>
|
|
@@ -66,6 +92,21 @@ export interface AbstractRequest<T extends {} = {}> {
|
|
|
66
92
|
signal?: AbortSignal
|
|
67
93
|
}
|
|
68
94
|
|
|
95
|
+
/**
|
|
96
|
+
* An organization entity as request handlers see it: the stable id to key by, the current slug to
|
|
97
|
+
* compose user-facing names from, and the frozen key that external systems already know it under.
|
|
98
|
+
*/
|
|
99
|
+
export interface ResolvedEntity {
|
|
100
|
+
id: string
|
|
101
|
+
slug: string
|
|
102
|
+
/**
|
|
103
|
+
* The identifier this organization is known by in systems whose names cannot be rewritten —
|
|
104
|
+
* an IAM realm, an object-storage prefix, a cluster object. Minted once and never recomputed,
|
|
105
|
+
* so it stays valid across every later rename.
|
|
106
|
+
*/
|
|
107
|
+
iamKey: string
|
|
108
|
+
}
|
|
109
|
+
|
|
69
110
|
export interface AbstractResponse<T> {
|
|
70
111
|
responseProvider?: any
|
|
71
112
|
value?: T,
|
|
@@ -98,3 +139,15 @@ export interface Filter {
|
|
|
98
139
|
response?: AnySchemaObject
|
|
99
140
|
headers?: AnySchemaObject
|
|
100
141
|
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* How a call to an entrypoint is actually carried.
|
|
145
|
+
*
|
|
146
|
+
* The transport is chosen by the route's protocol, so a consumer always writes `ep.call(...)` and
|
|
147
|
+
* never learns whether that became an HTTP request, a socket message or a queued job. An
|
|
148
|
+
* application binds a protocol by registering a transport service under `transportAlias(protocol)`.
|
|
149
|
+
*/
|
|
150
|
+
export interface EntrypointTransport extends InitializedService {
|
|
151
|
+
readonly protocol: RouteProtocols
|
|
152
|
+
handle: EntrypointHandler
|
|
153
|
+
}
|
package/src/utils/entrypoint.ts
CHANGED
package/src/utils/types.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RouteModel } from '@owlmeans/route'
|
|
2
2
|
import { CommonEntrypointOptions } from '../types.js'
|
|
3
3
|
|
|
4
4
|
export interface CreateEntrypointSignature<M> {
|
|
5
|
-
(route:
|
|
5
|
+
(route: RouteModel, opts?: CommonEntrypointOptions): M,
|
|
6
6
|
}
|