@owlmeans/route 0.1.18-rc.2 → 0.1.18-rc.21

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
@@ -1,78 +1,271 @@
1
1
  # @owlmeans/route
2
2
 
3
- Route model factory and type definitions for OwlMeans modules.
3
+ The route declaration vocabulary for OwlMeans entrypoints. An app imports it in its shared contract
4
+ package, next to `@owlmeans/entrypoint`, to state for each entrypoint the URL segment, parent,
5
+ HTTP method, app type (backend or frontend) and transport (HTTP, WebSocket or queue). It is not a
6
+ router and serves nothing: server binding is `@owlmeans/server-route` / `@owlmeans/server-app`,
7
+ client binding is `@owlmeans/client-route` / `@owlmeans/client-entrypoint`, UI routing is
8
+ `@owlmeans/router`. Application code usually reads addresses through the entrypoint accessors
9
+ (`path()`, `mount()`, `address()`) rather than through this package's `./utils`.
4
10
 
5
- ## Overview
6
-
7
- - `route()` creates a `CommonRouteModel` used as the first argument to `module()`
8
- - `frontend()` / `backend()` / `socket()` helpers set the route's `AppType` and parent
9
- - `RouteMethod` enum covers HTTP verbs; `RouteProtocols` covers `http`/`ws`
10
- - This package is a dependency of `@owlmeans/module` — you rarely use it directly unless defining module-level routes
11
+ A `RouteDeclaration` is plain, immutable data: its `path` is the segment the route contributes under
12
+ its parent, and it is never rewritten. Where the route actually answers — the full path, the mount
13
+ under a service base, the host and scheme — is computed on demand from the declaration plus the
14
+ context that asks, so the same declaration serves a server and a browser alike.
11
15
 
12
16
  ## Installation
13
17
 
14
18
  ```bash
15
- bun add @owlmeans/route
19
+ bun add @owlmeans/route@^0.1.18-rc.20
16
20
  ```
17
21
 
22
+ ## Concepts
23
+
24
+ - **Declaration** — the `RouteDeclaration` a `route()` call produces: `alias`, `path` (the segment
25
+ under `parent`), `type`, `method`, `protocol`, the service coordinates, and the queue fields.
26
+ - **Model** — `RouteModel` is `{ route: RouteDeclaration }` and nothing more. `protocol()` and
27
+ `openProtocol()` from `@owlmeans/entrypoint` take it as their first argument.
28
+ - **Marker** — `backend()`, `frontend()`, `socket()`, `job()` return `Partial<RouteOptions>` that set
29
+ the app type and protocol; `route()` accepts them as its options.
30
+ - **Parent** — a route nests under another entrypoint. Pass the parent protocol object
31
+ (`parent: storyProtocols.base`); the declaration stores only its alias.
32
+ - **Service** — `service` names the configured service (`cfg.services`) that answers the route.
33
+ Without it the route belongs to the asking context's own service or the default one of its type.
34
+ - **Protocol** — `RouteProtocols` picks the transport that carries a call: HTTP request, socket
35
+ frame or queued job. The call site never chooses.
36
+
18
37
  ## Usage
19
38
 
20
- Define routes for modules (typically via `@owlmeans/server-app` re-exports):
39
+ ### A backend protocol tree
21
40
 
22
- ```typescript
23
- import { route, frontend, backend, socket, RouteMethod } from '@owlmeans/route'
24
- import { module } from '@owlmeans/module'
41
+ Aliases stay private to the declaration module; the exported value is a tree of protocol objects.
25
42
 
26
- // Backend REST route
27
- const createRoute = module(
28
- route('story-create', '/stories', backend('api', RouteMethod.POST))
29
- )
43
+ ```ts
44
+ import { contract, protocol } from '@owlmeans/entrypoint'
45
+ import { backend, route, RouteMethod } from '@owlmeans/route'
46
+ import { DEFAULT_GUARD } from '@owlmeans/auth-common'
47
+ import { InvoiceSchema, CreateInvoiceBodySchema } from './schemas.js'
30
48
 
31
- // Frontend client route nested under parent
32
- const storyRoute = module(
33
- route('story-view', '/stories/:id', frontend('app'))
34
- )
49
+ const aliases = {
50
+ base: 'my-app:api:invoice:base',
51
+ list: 'my-app:api:invoice:list',
52
+ create: 'my-app:api:invoice:create',
53
+ } as const
35
54
 
36
- // WebSocket route
37
- const wsRoute = module(
38
- route('story-ws', '/stories/stream', socket('api'))
39
- )
55
+ const base = protocol(route(aliases.base, '/invoice', backend()), contract(), {
56
+ guards: DEFAULT_GUARD,
57
+ })
58
+
59
+ export const invoiceProtocols = {
60
+ base,
61
+ list: protocol(
62
+ route(aliases.list, '/', backend({ parent: base, method: RouteMethod.GET })),
63
+ contract(InvoiceSchema),
64
+ ),
65
+ create: protocol(
66
+ route(aliases.create, '/', backend({ parent: base, method: RouteMethod.POST })),
67
+ contract(CreateInvoiceBodySchema, InvoiceSchema),
68
+ ),
69
+ } as const
40
70
  ```
41
71
 
42
- ## API
72
+ `invoiceProtocols.create` resolves to `/invoice` on the backend service, answering `POST`, and
73
+ inherits the guard declared on `base`.
43
74
 
44
- ### `route(alias, path, opts?): CommonRouteModel`
75
+ ### Path params, screens and default children
45
76
 
46
- Creates a route model. `opts` can be a `RouteOptions` object or the result of `frontend()`, `backend()`, or `socket()`.
77
+ Path params use the `:name` form and are typed through `contract.request`. `frontend()` marks a
78
+ screen; `default: true` marks the child screen shown at the parent's path.
47
79
 
48
- ### `frontend(parent?, sticky?): Partial<RouteOptions>`
80
+ ```ts
81
+ import { contract, openProtocol, protocol, typed } from '@owlmeans/entrypoint'
82
+ import { backend, frontend, route, RouteMethod } from '@owlmeans/route'
83
+ import type { ProjectParams, Project, RenameProject } from './types.js'
84
+ import { ProjectParamsSchema, RenameProjectSchema } from './schemas.js'
49
85
 
50
- Returns options marking the route as frontend (`AppType.Frontend`), optionally with a parent alias.
86
+ const aliases = {
87
+ base: 'my-app:api:project:base',
88
+ rename: 'my-app:api:project:rename',
89
+ web: 'my-app:web:project:base',
90
+ dashboard: 'my-app:web:project:dashboard',
91
+ overview: 'my-app:web:project:overview',
92
+ } as const
51
93
 
52
- ### `backend(parent?, method?): Partial<RouteOptions>`
94
+ const base = openProtocol(route(aliases.base, '/project', backend()))
95
+ const web = openProtocol(route(aliases.web, '/project/:projectId', frontend()))
53
96
 
54
- Returns options marking the route as backend (`AppType.Backend`), optionally with a parent alias and `RouteMethod`.
97
+ export const projectProtocols = {
98
+ base,
99
+ rename: protocol(
100
+ route(aliases.rename, '/:id/rename', backend({ parent: base, method: RouteMethod.PATCH })),
101
+ contract.request(
102
+ { params: typed<ProjectParams>(ProjectParamsSchema), body: typed<RenameProject>(RenameProjectSchema) },
103
+ typed<Project>(),
104
+ ),
105
+ ),
106
+ web: {
107
+ base: web,
108
+ dashboard: openProtocol(route(aliases.dashboard, '/dashboard', frontend({ parent: web }))),
109
+ overview: openProtocol(route(aliases.overview, '/', frontend({ parent: web, default: true }))),
110
+ },
111
+ } as const
112
+ ```
55
113
 
56
- ### `socket(parent?): Partial<RouteOptions>`
114
+ ### Sockets, queued jobs and other services
57
115
 
58
- Returns options for a WebSocket route with `RouteProtocols.SOCKET`.
116
+ `socket()` and `job()` are `backend()` with a different protocol. A route pointed at another
117
+ service carries `service`; a queue route also names its `queue`, `timeout` and, optionally, `reply`.
59
118
 
60
- ### `RouteMethod`
119
+ ```ts
120
+ import { contract, openProtocol, protocol, typed } from '@owlmeans/entrypoint'
121
+ import { job, route, RouteMethod, socket } from '@owlmeans/route'
122
+ import { GUARD_ED25519 } from '@owlmeans/auth-common'
123
+ import type { ProjectParams, StoryUpdate, Story } from './types.js'
124
+ import { ProjectParamsSchema } from './schemas.js'
61
125
 
62
- ```typescript
63
- enum RouteMethod { GET, POST, PATCH, PUT, DELETE }
126
+ const WORKER = 'my-app-worker'
127
+ const aliases = {
128
+ updates: 'my-app:api:update:base',
129
+ story: 'my-app:api:update:story',
130
+ jobs: 'my-app:worker:story:base',
131
+ develop: 'my-app:worker:story:develop',
132
+ cleanup: 'my-app:worker:story:cleanup',
133
+ } as const
134
+
135
+ const updates = openProtocol(route(aliases.updates, '/update'))
136
+ const jobs = openProtocol(route(aliases.jobs, '/story', { service: WORKER }), { guards: GUARD_ED25519 })
137
+
138
+ export const storyProtocols = {
139
+ updates,
140
+ // WebSocket subscription under /update
141
+ story: protocol(
142
+ route(aliases.story, '/story/:id', socket({ parent: updates })),
143
+ contract.request({ params: typed<ProjectParams>(ProjectParamsSchema) }, typed<StoryUpdate>()),
144
+ ),
145
+ jobs,
146
+ // Queued job: the caller waits up to timeout ms for the job's result
147
+ develop: protocol(
148
+ route(aliases.develop, '/:id/develop', job({
149
+ parent: jobs, method: RouteMethod.POST, service: WORKER, queue: 'story-work', timeout: 600_000,
150
+ })),
151
+ contract.request({ params: typed<ProjectParams>(ProjectParamsSchema) }, typed<Story>()),
152
+ ),
153
+ // reply: false resolves once the broker accepts the job; the outcome is Accepted
154
+ cleanup: protocol(
155
+ route(aliases.cleanup, '/:id/cleanup', job({
156
+ parent: jobs, method: RouteMethod.POST, service: WORKER, queue: 'story-ops', reply: false, timeout: 30_000,
157
+ })),
158
+ contract.request({ params: typed<ProjectParams>(ProjectParamsSchema) }, typed<unknown>()),
159
+ ),
160
+ } as const
64
161
  ```
65
162
 
66
- ### `RouteProtocols`
163
+ Which queues a process consumes is configuration of that process (`listenQueues()`), never part of
164
+ the declaration.
165
+
166
+ ### Reading where a route answers
167
+
168
+ Once protocols are registered on a context, the entrypoint accessors answer address questions. The
169
+ `./utils` helpers are the same functions over a bare declaration.
170
+
171
+ ```ts
172
+ import { AppType } from '@owlmeans/context'
173
+ import { service } from '@owlmeans/config'
174
+ import { resolveAddress, resolveMount } from '@owlmeans/route/utils'
175
+ import { invoiceProtocols } from 'my-app-common'
67
176
 
68
- ```typescript
69
- enum RouteProtocols { WEB = 'http', SOCKET = 'ws' }
177
+ // Config side: the service the backend routes resolve against
178
+ const cfg = service({ service: 'my-app-api', type: AppType.Backend, host: 'localhost', port: 8080, base: 'api' }, baseCfg)
179
+
180
+ // Runtime side, through the registered entrypoint
181
+ const entrypoint = context.entrypoint(invoiceProtocols.create)
182
+ entrypoint.path() // '/invoice'
183
+ entrypoint.mount() // '/api/invoice'
184
+ entrypoint.address() // { host: 'localhost', port: 8080, base: 'api', secure: true, protocol: 'http' }
185
+ entrypoint.isLocal() // true inside the my-app-api process
186
+
187
+ // Same answers from a declaration
188
+ const declaration = invoiceProtocols.create.route.route
189
+ resolveMount(context, declaration)
190
+ resolveAddress(context, declaration)
70
191
  ```
71
192
 
72
- ## Related Packages
193
+ ## API
194
+
195
+ ### `@owlmeans/route`
196
+
197
+ | Symbol | Kind | Purpose |
198
+ |--------|------|---------|
199
+ | `route(alias, path, opts?)` | function | Build a `RouteModel`; `opts` is `RouteOptions` or a parent alias string |
200
+ | `createRoute(alias, path, opts?)` | function | Build the bare `RouteDeclaration` (parent reference collapsed to its alias) |
201
+ | `makeRouteModel(declaration)` | function | Wrap a declaration as `{ route }` |
202
+ | `backend(opts?, method?)` | function | Mark `AppType.Backend`; `opts` is options, a parent alias or `null`; `method` is a `RouteMethod` or more options |
203
+ | `frontend(opts?, default?)` | function | Mark `AppType.Frontend`; `default` is a boolean flag or more options |
204
+ | `socket(opts?, secondary?)` | function | `backend()` with `protocol: RouteProtocols.SOCKET` |
205
+ | `job(opts?, secondary?)` | function | `backend()` with `protocol: RouteProtocols.QUEUE` |
206
+ | `service(alias, opts?)` | function | Set `service` on `opts` (mutated and returned) |
207
+ | `rtype(type, opts?)` | function | Set an arbitrary `AppType`; the primitive behind `backend()` / `frontend()` |
208
+ | `normalizePath(path)` | function | Trim whitespace and one leading and trailing `/` |
209
+ | `RouteMethod` | enum | `GET = 'get'`, `POST = 'post'`, `PATCH = 'patch'`, `PUT = 'put'`, `DELETE = 'delete'` |
210
+ | `RouteProtocols` | enum | `WEB = 'http'`, `SOCKET = 'ws'`, `QUEUE = 'queue'` |
211
+ | `SEP` | const | Path separator `'/'` |
212
+ | `PARAM` | const | Path param prefix `':'` |
213
+ | `BasicRoute` | interface | `type`, `service?`, `host?`, `port?`, `base?`, `internalHost?`, `internalPort?` |
214
+ | `RouteDeclaration` | interface | `BasicRoute` + `alias`, `path`, `parent?`, `default?`, `method?`, `protocol?`, `secure?`, `queue?`, `reply?`, `timeout?` |
215
+ | `RouteOptions` | interface | `Partial<RouteDeclaration>` whose `parent` is a `RouteParent` |
216
+ | `RouteParent` | type | `string \| EntrypointReference` |
217
+ | `RouteModel` | interface | `{ route: RouteDeclaration }` |
218
+ | `RouteAddress` | interface | `{ host, port?, base?, secure, protocol }` |
219
+ | `CommonServiceRoute` | interface | A service entry: `BasicRoute` + `service`, `home?`, `default?` |
220
+ | `ResolvedServiceRoute` | interface | A service entry that names its `host` |
221
+
222
+ ### `@owlmeans/route/utils`
223
+
224
+ The first six take `(context, declaration)`; the other four are pure and take no context.
225
+
226
+ | Symbol | Kind | Purpose |
227
+ |--------|------|---------|
228
+ | `resolvePath(context, route)` | function | Every ancestor's segment, then this one |
229
+ | `resolveMount(context, route)` | function | Service `base` + the full path |
230
+ | `resolveService(context, route)` | function | The named service, else the default of the route's type, else the first of that type |
231
+ | `resolveAddress(context, route)` | function | The `RouteAddress`; a hop over the service's internal host is never TLS |
232
+ | `isLocalRoute(context, route)` | function | Does the route belong to the context's own service |
233
+ | `getParentRoute(context, route)` | function | The parent declaration, with parentship-cycle detection |
234
+ | `overrideParams(route, overrides?, filter?)` | function | Fill only blank fields of `route` from `overrides`; mutates, returns nothing |
235
+ | `prependBase(route, path)` | function | `path` prefixed with `route.base` when set |
236
+ | `isServiceRoute(obj?)` | type guard | Is `obj` a `CommonServiceRoute` with a known `AppType` |
237
+ | `isServiceRouteResolved(route)` | type guard | Does the service entry name a host |
238
+ | `CreateRouteSignature<R>` | interface | Call signature shared by `route()` and `createRoute()` |
239
+
240
+ ## Common pitfalls
241
+
242
+ - Pass the parent protocol object in route options, never an exported alias string. Keep aliases
243
+ private to the declaration module and export a `*Protocols` tree.
244
+ - The positional marker forms (`backend(parent, method)`, `frontend(parent, true)`) accept a parent
245
+ only as an alias string: a protocol object in first position is spread into the options and
246
+ overwrites the child's alias. Pass protocols as `{ parent }`.
247
+ - `path` is only this route's segment. Do not repeat the parent's path in it; `resolvePath()` joins
248
+ the chain.
249
+ - `job()` routes must name `service`, `queue` and `timeout`. `reply: false` returns the job identity
250
+ with an `Accepted` outcome, not the job's result.
251
+ - Do not pass a context to the pure `./utils` helpers: `overrideParams(ctx, decl)` writes route
252
+ fields into the context object instead of resolving anything.
253
+ - A mis-wired tree (no `cfg.services`, a service without a host, a parentship cycle) throws
254
+ `SyntaxError` when an address is resolved. Fix the config; do not catch it.
255
+ - `transportAlias` and `EntrypointTransport` live in `@owlmeans/entrypoint`, not here. A route only
256
+ names its protocol.
257
+
258
+ ## Related packages
73
259
 
74
- - [`@owlmeans/module`](../module) — `module()` takes a `CommonRouteModel` as first argument
75
- - [`@owlmeans/server-app`](../server-app) — re-exports `route` as `broute` (backend) alongside `route`
260
+ - [`@owlmeans/entrypoint`](../entrypoint) — `protocol()` / `openProtocol()` consume a `RouteModel` and
261
+ expose `path()`, `mount()`, `address()`, `isLocal()`
262
+ - [`@owlmeans/context`](../context) — `AppType`, `EntrypointReference` and the registry the address helpers walk
263
+ - [`@owlmeans/config`](../config) — `service()` declares the service entries routes resolve against
264
+ - [`@owlmeans/server-route`](../server-route) — server-side route model; re-exported by
265
+ [`@owlmeans/server-app`](../server-app) as `broute`
266
+ - [`@owlmeans/client-route`](../client-route) — marks a route as client-side and extracts its params
267
+ - [`@owlmeans/queue`](../queue) — the QUEUE transport a `job()` route is carried by
268
+ - [`@owlmeans/socket`](../socket) — the SOCKET transport contracts
76
269
 
77
270
  <!-- owlmeans:agent-guidance:start -->
78
271
  ## Agent guidance
@@ -82,7 +275,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
82
275
  your project's skill store (`.agents/skills/`):
83
276
 
84
277
  ```sh
85
- npx @owlmeans/agent-skills
278
+ npx @owlmeans/agent-skills@^0.1.18-rc.24
86
279
  ```
87
280
 
88
281
  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/route",
4
- "version": "0.1.18-rc.0",
5
- "generatedAt": "2026-08-16T22:20:50.511Z",
4
+ "version": "0.1.18-rc.21",
5
+ "generatedAt": "2026-09-15T12:59:01.062Z",
6
6
  "canonicalRepo": "https://github.com/owlmeans/common",
7
7
  "entries": [
8
8
  {
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: route
3
- description: How to use @owlmeans/route — route() helper for declaring URL paths, frontend() marker for React routes, RouteMethod enum, and route model types. Auto-invoked when importing route helpers or defining a module's URL path.
3
+ description: How to use @owlmeans/route — route() for declaring URL segments, frontend()/backend()/socket()/job() markers, RouteMethod and RouteProtocols enums, and the address helpers under ./utils. Auto-invoked when importing route helpers or defining an entrypoint's URL path.
4
4
  user-invocable: false
5
5
  ---
6
6
  <!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
@@ -8,43 +8,101 @@ user-invocable: false
8
8
  # @owlmeans/route
9
9
 
10
10
  **Layer:** Core
11
- **Install:** `"@owlmeans/route": "^0.1.18-rc.0"` in `dependencies`
11
+ **Install:** `"@owlmeans/route": "^0.1.18-rc.21"` in `dependencies`
12
12
 
13
13
  ## Key Exports
14
14
 
15
15
  | Export | Description |
16
16
  |--------|-------------|
17
- | `route(alias, path, options?)` | Define a route — path is relative to `parent` |
18
- | `frontend(options?)` | Mark a route as a React page (web only) |
19
- | `RouteMethod` | enum of GET, POST, PUT, DELETE, PATCH |
20
- | `Route` types | Resolved route shape |
21
- | Constants | Default route aliases |
17
+ | `route(alias, path, options?)` | Build a route model — `path` is the segment contributed under `parent` |
18
+ | `frontend(options?, default?)` | Mark a route as a React page (web only) |
19
+ | `backend(options?, method?)` | Mark a route as a backend endpoint |
20
+ | `socket(options?, secondary?)` | A backend route answering over `RouteProtocols.SOCKET` |
21
+ | `job(options?, secondary?)` | A backend route carried by the queue (`RouteProtocols.QUEUE`); its declaration names `service`, `queue`, `reply` and `timeout` |
22
+ | `service(alias, options?)` | Point a route at a named service |
23
+ | `RouteMethod` | enum of GET, POST, PUT, PATCH, DELETE |
24
+ | `RouteProtocols` | enum of WEB (`http`), SOCKET (`ws`), QUEUE (`queue`) |
25
+ | `rtype(type, options?)` | The primitive `frontend()` / `backend()` are built from |
26
+ | `createRoute(alias, path, opts?)` / `makeRouteModel(decl)` | The declaration and its wrapper, when you need them apart |
27
+ | `BasicRoute` | `{ type, service?, host?, port?, base?, internalHost?, internalPort? }` |
28
+ | `RouteDeclaration` | The immutable declaration `route()` produces |
29
+ | `RouteOptions` | `Partial<RouteDeclaration>` — what the marker helpers return |
30
+ | `RouteModel` | `{ route }` — the model wrapping a declaration |
31
+ | `RouteAddress` | `{ host, port, base, secure, protocol }` — where a route answers |
32
+ | `CommonServiceRoute` / `ResolvedServiceRoute` | A service entry, and one that knows its host |
33
+ | `normalizePath(path)`, `SEP`, `PARAM` | Path primitives |
34
+
35
+ ## Declaration and model
36
+
37
+ `route()` returns a `RouteModel` that does nothing but **wrap an immutable `RouteDeclaration`**. The
38
+ declaration is plain data an application ships in its contract package: `path` stays the segment this
39
+ route contributes under its parent and is never rewritten, and the model carries no state of its own.
40
+ Where the route answers is worked out on demand, against the context that asks — which is what lets
41
+ the same declaration serve a client and a server at once.
42
+
43
+ ## Protocol picks the transport
44
+
45
+ A route names the protocol it answers on, and an application binds one by registering a transport
46
+ service under `transportAlias(protocol)`. So the protocol is what decides whether a call travels as
47
+ an HTTP request, a socket frame or a queued job — the call site never says. Both `transportAlias`
48
+ and the `EntrypointTransport` contract a transport implements are exported by `@owlmeans/entrypoint`,
49
+ not by this package; a route only names the protocol.
50
+
51
+ `job()` is `backend()` with `RouteProtocols.QUEUE`. Three declaration fields matter only for that
52
+ protocol: `queue` (which queue carries it), `reply` and `timeout`. `reply: false` resolves once the
53
+ broker has taken the job — the value is the job's identity and the outcome is `Accepted`, not the
54
+ job's result; the default is to wait for the result. Use the parent protocol object in a route
55
+ option (`job({ parent: storyProtocols.base, service, queue, timeout })`), never an exported alias string.
22
56
 
23
57
  ## Subpath Exports
24
58
 
25
- - `./utils` — path manipulation helpers
59
+ `./utils` holds two kinds of helper, and their signatures differ. The six that answer *where* a
60
+ route lives take `(context, declaration)`, because that is a question about the asking context. The
61
+ other four are pure functions over a declaration or a service entry and take **no context**.
62
+ Passing one to them resolves nothing: `overrideParams(ctx, decl)` writes route fields straight into
63
+ the context object instead.
64
+
65
+ | Helper | Signature | Answers |
66
+ |--------|-----------|---------|
67
+ | `resolvePath` | `(context, route)` | Every ancestor's segment, then this one |
68
+ | `resolveMount` | `(context, route)` | `base` + the full path — what a server mounts and a client requests |
69
+ | `resolveService` | `(context, route)` | The service the declaration answers on: the one it names, else the default of its app type, else the first of that type |
70
+ | `resolveAddress` | `(context, route)` | The `RouteAddress`; a hop over a service's INTERNAL host is never TLS |
71
+ | `isLocalRoute` | `(context, route)` | Does the route belong to the service the asking context IS? |
72
+ | `getParentRoute` | `(context, route)` | The parent declaration, with parentship-cycle detection |
73
+ | `overrideParams` | `(route, overrides?, filter?)` | Fill in **only the blank** fields of `route` from `overrides`; `filter` narrows it to the listed keys. Mutates `route` and returns nothing |
74
+ | `prependBase` | `(route, path)` | `path` prefixed with `route.base`, or `path` when there is no base |
75
+ | `isServiceRoute` | `(obj?)` | Type guard: is this a service entry (`type` + `service`, `type` a known `AppType`)? |
76
+ | `isServiceRouteResolved` | `(route)` | Type guard: does that service entry name a host? |
77
+
78
+ Application code rarely calls these directly — `@owlmeans/entrypoint` exposes them as `path()`,
79
+ `mount()`, `service()`, `address()` and `isLocal()` on the entrypoint itself.
26
80
 
27
81
  ## Usage
28
82
 
29
83
  ```typescript
30
84
  import { route, frontend, RouteMethod } from '@owlmeans/route'
31
- import { entrypoint } from '@owlmeans/entrypoint'
85
+ import { contract, openProtocol, protocol, typed } from '@owlmeans/entrypoint'
32
86
 
33
87
  // Server route
34
- entrypoint(
88
+ protocol(
35
89
  route(manager.back.project.create, '/create', {
36
90
  parent: manager.back.project.base,
37
91
  method: RouteMethod.POST,
38
- })
92
+ }),
93
+ contract(typed<Project>()),
39
94
  )
40
95
 
41
96
  // Web route — frontend() marks it as a React page
42
- entrypoint(
97
+ openProtocol(
43
98
  route(HOME, '/', frontend({ default: true, parent: BASE }))
44
99
  )
45
100
  ```
46
101
 
47
102
  ## Depends On
48
103
 
49
- - `@owlmeans/error` — route errors
50
- - `@owlmeans/i18n` — translatable errors
104
+ - `@owlmeans/context` — `AppType`, and the entrypoint registry the address helpers walk
105
+
106
+ That is the only dependency. The address helpers signal a mis-wired route tree by throwing
107
+ `SyntaxError` — an unconfigured service, an unresolved host, a parentship cycle — so the process
108
+ crashes on a wiring mistake instead of serving a wrong URL.
package/build/consts.d.ts CHANGED
@@ -7,8 +7,14 @@ export declare enum RouteMethod {
7
7
  }
8
8
  export declare const SEP = "/";
9
9
  export declare const PARAM = ":";
10
+ /**
11
+ * How a route is carried. The protocol picks the transport that answers it — an application binds
12
+ * one by registering a service under `transportAlias(protocol)` — so a caller writes `call()` and
13
+ * never learns whether an HTTP request, a socket frame or a queued job did the work.
14
+ */
10
15
  export declare enum RouteProtocols {
11
16
  WEB = "http",
12
- SOCKET = "ws"
17
+ SOCKET = "ws",
18
+ QUEUE = "queue"
13
19
  }
14
20
  //# sourceMappingURL=consts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AACA,oBAAY,WAAW;IACrB,GAAG,QAAQ;IACX,IAAI,SAAS;IACb,KAAK,UAAU;IACf,GAAG,QAAQ;IACX,MAAM,WAAW;CAClB;AAED,eAAO,MAAM,GAAG,MAAM,CAAA;AAEtB,eAAO,MAAM,KAAK,MAAM,CAAA;AAExB,oBAAY,cAAc;IACxB,GAAG,SAAS;IACZ,MAAM,OAAO;CACd"}
1
+ {"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AACA,oBAAY,WAAW;IACrB,GAAG,QAAQ;IACX,IAAI,SAAS;IACb,KAAK,UAAU;IACf,GAAG,QAAQ;IACX,MAAM,WAAW;CAClB;AAED,eAAO,MAAM,GAAG,MAAM,CAAA;AAEtB,eAAO,MAAM,KAAK,MAAM,CAAA;AAExB;;;;GAIG;AACH,oBAAY,cAAc;IACxB,GAAG,SAAS;IACZ,MAAM,OAAO;IACb,KAAK,UAAU;CAChB"}
package/build/consts.js CHANGED
@@ -8,9 +8,15 @@ export var RouteMethod;
8
8
  })(RouteMethod || (RouteMethod = {}));
9
9
  export const SEP = '/';
10
10
  export const PARAM = ':';
11
+ /**
12
+ * How a route is carried. The protocol picks the transport that answers it — an application binds
13
+ * one by registering a service under `transportAlias(protocol)` — so a caller writes `call()` and
14
+ * never learns whether an HTTP request, a socket frame or a queued job did the work.
15
+ */
11
16
  export var RouteProtocols;
12
17
  (function (RouteProtocols) {
13
18
  RouteProtocols["WEB"] = "http";
14
19
  RouteProtocols["SOCKET"] = "ws";
20
+ RouteProtocols["QUEUE"] = "queue";
15
21
  })(RouteProtocols || (RouteProtocols = {}));
16
22
  //# sourceMappingURL=consts.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"consts.js","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AACA,MAAM,CAAN,IAAY,WAMX;AAND,WAAY,WAAW;IACrB,0BAAW,CAAA;IACX,4BAAa,CAAA;IACb,8BAAe,CAAA;IACf,0BAAW,CAAA;IACX,gCAAiB,CAAA;AACnB,CAAC,EANW,WAAW,KAAX,WAAW,QAMtB;AAED,MAAM,CAAC,MAAM,GAAG,GAAG,GAAG,CAAA;AAEtB,MAAM,CAAC,MAAM,KAAK,GAAG,GAAG,CAAA;AAExB,MAAM,CAAN,IAAY,cAGX;AAHD,WAAY,cAAc;IACxB,8BAAY,CAAA;IACZ,+BAAa,CAAA;AACf,CAAC,EAHW,cAAc,KAAd,cAAc,QAGzB"}
1
+ {"version":3,"file":"consts.js","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AACA,MAAM,CAAN,IAAY,WAMX;AAND,WAAY,WAAW;IACrB,0BAAW,CAAA;IACX,4BAAa,CAAA;IACb,8BAAe,CAAA;IACf,0BAAW,CAAA;IACX,gCAAiB,CAAA;AACnB,CAAC,EANW,WAAW,KAAX,WAAW,QAMtB;AAED,MAAM,CAAC,MAAM,GAAG,GAAG,GAAG,CAAA;AAEtB,MAAM,CAAC,MAAM,KAAK,GAAG,GAAG,CAAA;AAExB;;;;GAIG;AACH,MAAM,CAAN,IAAY,cAIX;AAJD,WAAY,cAAc;IACxB,8BAAY,CAAA;IACZ,+BAAa,CAAA;IACb,iCAAe,CAAA;AACjB,CAAC,EAJW,cAAc,KAAd,cAAc,QAIzB"}
package/build/helper.d.ts CHANGED
@@ -1,12 +1,18 @@
1
1
  import { AppType } from '@owlmeans/context';
2
2
  import { RouteMethod } from './consts.js';
3
- import type { CommonRouteModel, RouteOptions } from './types.js';
3
+ import type { RouteModel, RouteOptions } from './types.js';
4
4
  import type { CreateRouteSignature } from './utils/types.js';
5
- export declare const route: CreateRouteSignature<CommonRouteModel>;
5
+ export declare const route: CreateRouteSignature<RouteModel>;
6
6
  export declare const normalizePath: (path: string) => string;
7
7
  export declare const rtype: (type: AppType, opts?: RouteOptions | string) => Partial<RouteOptions>;
8
8
  export declare const backend: (opts?: RouteOptions | string | null, method?: RouteOptions | RouteMethod) => Partial<RouteOptions>;
9
9
  export declare const service: (service: string, opts?: Partial<RouteOptions>) => Partial<RouteOptions>;
10
10
  export declare const socket: (opts?: RouteOptions | string | null, secondary?: RouteOptions) => Partial<RouteOptions>;
11
+ /**
12
+ * A backend route carried by the queue rather than by HTTP. Everything else about it is a normal
13
+ * backend route — it has a path, a parent, guards and a filter — so the same declaration is served
14
+ * with `bind(...)` and called with `call()`; only the transport underneath differs.
15
+ */
16
+ export declare const job: (opts?: RouteOptions | string | null, secondary?: RouteOptions) => Partial<RouteOptions>;
11
17
  export declare const frontend: (opts?: RouteOptions | string | null, def?: RouteOptions | boolean) => Partial<RouteOptions>;
12
18
  //# sourceMappingURL=helper.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAC3C,OAAO,EAAE,WAAW,EAAuB,MAAM,aAAa,CAAA;AAE9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAChE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAE5D,eAAO,MAAM,KAAK,EAAE,oBAAoB,CAAC,gBAAgB,CACT,CAAA;AAEhD,eAAO,MAAM,aAAa,SAAU,MAAM,KAAG,MAM5C,CAAA;AAED,eAAO,MAAM,KAAK,SAAU,OAAO,SAAS,YAAY,GAAG,MAAM,KAAG,OAAO,CAAC,YAAY,CAEvF,CAAA;AAED,eAAO,MAAM,OAAO,UAAW,YAAY,GAAG,MAAM,GAAG,IAAI,WAAW,YAAY,GAAG,WAAW,KAAG,OAAO,CAAC,YAAY,CAQtH,CAAA;AAED,eAAO,MAAM,OAAO,YAAa,MAAM,SAAS,OAAO,CAAC,YAAY,CAAC,KAAG,OAAO,CAAC,YAAY,CAI3F,CAAA;AAED,eAAO,MAAM,MAAM,UAAW,YAAY,GAAG,MAAM,GAAG,IAAI,cAAc,YAAY,KAAG,OAAO,CAAC,YAAY,CAM1G,CAAA;AAED,eAAO,MAAM,QAAQ,UAAW,YAAY,GAAG,MAAM,GAAG,IAAI,QAAQ,YAAY,GAAG,OAAO,KAAG,OAAO,CAAC,YAAY,CAQhH,CAAA"}
1
+ {"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAC3C,OAAO,EAAE,WAAW,EAAuB,MAAM,aAAa,CAAA;AAE9D,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC1D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAE5D,eAAO,MAAM,KAAK,EAAE,oBAAoB,CAAC,UAAU,CACH,CAAA;AAEhD,eAAO,MAAM,aAAa,SAAU,MAAM,KAAG,MAM5C,CAAA;AAED,eAAO,MAAM,KAAK,SAAU,OAAO,SAAS,YAAY,GAAG,MAAM,KAAG,OAAO,CAAC,YAAY,CAEvF,CAAA;AAED,eAAO,MAAM,OAAO,UAAW,YAAY,GAAG,MAAM,GAAG,IAAI,WAAW,YAAY,GAAG,WAAW,KAAG,OAAO,CAAC,YAAY,CAQtH,CAAA;AAED,eAAO,MAAM,OAAO,YAAa,MAAM,SAAS,OAAO,CAAC,YAAY,CAAC,KAAG,OAAO,CAAC,YAAY,CAI3F,CAAA;AAED,eAAO,MAAM,MAAM,UAAW,YAAY,GAAG,MAAM,GAAG,IAAI,cAAc,YAAY,KAAG,OAAO,CAAC,YAAY,CAM1G,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,GAAG,UAAW,YAAY,GAAG,MAAM,GAAG,IAAI,cAAc,YAAY,KAAG,OAAO,CAAC,YAAY,CAMvG,CAAA;AAED,eAAO,MAAM,QAAQ,UAAW,YAAY,GAAG,MAAM,GAAG,IAAI,QAAQ,YAAY,GAAG,OAAO,KAAG,OAAO,CAAC,YAAY,CAQhH,CAAA"}
package/build/helper.js CHANGED
@@ -28,6 +28,16 @@ export const socket = (opts, secondary) => {
28
28
  route.protocol = RouteProtocols.SOCKET;
29
29
  return route;
30
30
  };
31
+ /**
32
+ * A backend route carried by the queue rather than by HTTP. Everything else about it is a normal
33
+ * backend route — it has a path, a parent, guards and a filter — so the same declaration is served
34
+ * with `bind(...)` and called with `call()`; only the transport underneath differs.
35
+ */
36
+ export const job = (opts, secondary) => {
37
+ const route = backend(opts, secondary);
38
+ route.protocol = RouteProtocols.QUEUE;
39
+ return route;
40
+ };
31
41
  export const frontend = (opts, def) => {
32
42
  if (typeof def === 'boolean') {
33
43
  opts = typeof opts === 'string' ? { parent: opts, default: def } : { default: def, ...(opts ?? {}) };
@@ -1 +1 @@
1
- {"version":3,"file":"helper.js","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"helper.js","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"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"}
package/build/model.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import type { CommonRoute, CommonRouteModel } from './types.js';
1
+ import type { RouteDeclaration, RouteModel } from './types.js';
2
2
  import type { CreateRouteSignature } from './utils/types.js';
3
- export declare const makeRouteModel: (route: CommonRoute) => CommonRouteModel;
4
- export declare const createRoute: CreateRouteSignature<CommonRoute>;
3
+ export declare const makeRouteModel: (route: RouteDeclaration) => RouteModel;
4
+ export declare const createRoute: CreateRouteSignature<RouteDeclaration>;
5
5
  //# sourceMappingURL=model.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAC/D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAI5D,eAAO,MAAM,cAAc,UAAW,WAAW,KAAG,gBAOnD,CAAA;AAED,eAAO,MAAM,WAAW,EAAE,oBAAoB,CAAC,WAAW,CAUzD,CAAA"}
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAC9D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAG5D,eAAO,MAAM,cAAc,UAAW,gBAAgB,KAAG,UAAyB,CAAA;AAElF,eAAO,MAAM,WAAW,EAAE,oBAAoB,CAAC,gBAAgB,CAY9D,CAAA"}
package/build/model.js CHANGED
@@ -1,19 +1,14 @@
1
- import { resolve } from './utils/route.js';
2
1
  import { AppType } from '@owlmeans/context';
3
- export const makeRouteModel = (route) => {
4
- const model = {
5
- route,
6
- resolve: ctx => resolve(route)(ctx)
7
- };
8
- return model;
9
- };
2
+ export const makeRouteModel = (route) => ({ route });
10
3
  export const createRoute = (alias, path, opts) => {
4
+ const options = typeof opts === 'string' ? { parent: opts } : opts;
5
+ const { parent, ...rest } = options ?? {};
11
6
  const route = {
12
7
  alias,
13
8
  type: AppType.Backend,
14
9
  path,
15
- resolved: false,
16
- ...(typeof opts === 'string' ? { parent: opts } : opts)
10
+ ...rest,
11
+ ...(parent == null ? {} : { parent: typeof parent === 'string' ? parent : parent.alias }),
17
12
  };
18
13
  return route;
19
14
  };
@@ -1 +1 @@
1
- {"version":3,"file":"model.js","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAC1C,OAAO,EAAE,OAAO,EAA6B,MAAM,mBAAmB,CAAA;AAEtE,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAkB,EAAoB,EAAE;IACrE,MAAM,KAAK,GAAqB;QAC9B,KAAK;QACL,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAA2C,CAAC;KAC5E,CAAA;IAED,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,WAAW,GAAsC,CAAC,KAAK,EAAE,IAAI,EAAE,IAAK,EAAE,EAAE;IACnF,MAAM,KAAK,GAAgB;QACzB,KAAK;QACL,IAAI,EAAE,OAAO,CAAC,OAAO;QACrB,IAAI;QACJ,QAAQ,EAAE,KAAK;QACf,GAAG,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;KACxD,CAAA;IAED,OAAO,KAAK,CAAA;AACd,CAAC,CAAA"}
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAE3C,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAuB,EAAc,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;AAElF,MAAM,CAAC,MAAM,WAAW,GAA2C,CAAC,KAAK,EAAE,IAAI,EAAE,IAAK,EAAE,EAAE;IACxF,MAAM,OAAO,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;IAClE,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,IAAI,EAAE,CAAA;IACzC,MAAM,KAAK,GAAqB;QAC9B,KAAK;QACL,IAAI,EAAE,OAAO,CAAC,OAAO;QACrB,IAAI;QACJ,GAAG,IAAI;QACP,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;KAC1F,CAAA;IAED,OAAO,KAAK,CAAA;AACd,CAAC,CAAA"}