@owlmeans/route 0.1.18-rc.5 → 0.1.18-rc.7

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,13 +1,18 @@
1
1
  # @owlmeans/route
2
2
 
3
- Route model factory and type definitions for OwlMeans modules.
3
+ Route model factory and type definitions for OwlMeans entrypoints.
4
4
 
5
5
  ## Overview
6
6
 
7
- - `route()` creates a `CommonRouteModel` used as the first argument to `module()`
7
+ - `route()` creates a `RouteModel` used as the first argument to `entrypoint()`
8
8
  - `frontend()` / `backend()` / `socket()` helpers set the route's `AppType` and parent
9
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
10
+ - This package is a dependency of `@owlmeans/entrypoint` — you rarely use it directly unless defining entrypoint-level routes
11
+
12
+ A `RouteDeclaration` is plain, immutable data: its `path` is the segment the route contributes under
13
+ its parent, and it is never rewritten. Where the route actually answers — the full path, the mount
14
+ under a service base, the host and scheme — is computed on demand from the declaration plus the
15
+ context that asks, so the same declaration serves a server and a browser alike.
11
16
 
12
17
  ## Installation
13
18
 
@@ -17,33 +22,33 @@ bun add @owlmeans/route
17
22
 
18
23
  ## Usage
19
24
 
20
- Define routes for modules (typically via `@owlmeans/server-app` re-exports):
25
+ Define routes for entrypoints (typically via `@owlmeans/server-app` re-exports):
21
26
 
22
27
  ```typescript
23
28
  import { route, frontend, backend, socket, RouteMethod } from '@owlmeans/route'
24
- import { module } from '@owlmeans/module'
29
+ import { entrypoint } from '@owlmeans/entrypoint'
25
30
 
26
31
  // Backend REST route
27
- const createRoute = module(
32
+ const createEntrypoint = entrypoint(
28
33
  route('story-create', '/stories', backend('api', RouteMethod.POST))
29
34
  )
30
35
 
31
36
  // Frontend client route nested under parent
32
- const storyRoute = module(
37
+ const storyEntrypoint = entrypoint(
33
38
  route('story-view', '/stories/:id', frontend('app'))
34
39
  )
35
40
 
36
41
  // WebSocket route
37
- const wsRoute = module(
42
+ const wsEntrypoint = entrypoint(
38
43
  route('story-ws', '/stories/stream', socket('api'))
39
44
  )
40
45
  ```
41
46
 
42
47
  ## API
43
48
 
44
- ### `route(alias, path, opts?): CommonRouteModel`
49
+ ### `route(alias, path, opts?): RouteModel`
45
50
 
46
- Creates a route model. `opts` can be a `RouteOptions` object or the result of `frontend()`, `backend()`, or `socket()`.
51
+ Creates a route model. `path` is the segment this route contributes under its parent. `opts` can be a `RouteOptions` object or the result of `frontend()`, `backend()`, or `socket()`.
47
52
 
48
53
  ### `frontend(parent?, sticky?): Partial<RouteOptions>`
49
54
 
@@ -69,9 +74,28 @@ enum RouteMethod { GET, POST, PATCH, PUT, DELETE }
69
74
  enum RouteProtocols { WEB = 'http', SOCKET = 'ws' }
70
75
  ```
71
76
 
77
+ The protocol also selects the transport that carries a call to an entrypoint on this route.
78
+
79
+ ### Types
80
+
81
+ - `RouteDeclaration` — the plain, immutable data a `route()` call produces: `alias`, `path`,
82
+ `parent`, `method`, `protocol`, `secure`, plus the service coordinates
83
+ - `RouteModel` — `{ route: RouteDeclaration }`, the model an entrypoint carries
84
+ - `RouteAddress` — `{ host, port?, base?, secure, protocol }`, where a route answers once its
85
+ service has been picked
86
+
87
+ ### `@owlmeans/route/utils`
88
+
89
+ The pure functions the entrypoint accessors are built on. Each takes a context and a declaration:
90
+
91
+ - `resolveService(ctx, route)` / `isLocalRoute(ctx, route)`
92
+ - `resolvePath(ctx, route)` — the route's segment under every ancestor's
93
+ - `resolveMount(ctx, route)` — that path under the service base
94
+ - `resolveAddress(ctx, route)` — host, port, scheme and protocol
95
+
72
96
  ## Related Packages
73
97
 
74
- - [`@owlmeans/module`](../module) — `module()` takes a `CommonRouteModel` as first argument
98
+ - [`@owlmeans/entrypoint`](../entrypoint) — `entrypoint()` takes a `RouteModel` as first argument
75
99
  - [`@owlmeans/server-app`](../server-app) — re-exports `route` as `broute` (backend) alongside `route`
76
100
 
77
101
  <!-- owlmeans:agent-guidance:start -->
@@ -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.7",
5
+ "generatedAt": "2026-09-01T16:28:56.994Z",
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() 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,21 +8,50 @@ 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.7"` 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
+ | `service(alias, options?)` | Point a route at a named service |
22
+ | `RouteMethod` | enum of GET, POST, PUT, PATCH, DELETE |
23
+ | `RouteProtocols` | enum of WEB (`http`), SOCKET (`ws`) |
24
+ | `RouteDeclaration` | The immutable declaration `route()` produces |
25
+ | `RouteModel` | `{ route }` — the model wrapping a declaration |
26
+ | `RouteAddress` | `{ host, port, base, secure, protocol }` — where a route answers |
27
+ | `CommonServiceRoute` / `ResolvedServiceRoute` | A service entry, and one that knows its host |
28
+ | `normalizePath(path)`, `SEP`, `PARAM` | Path primitives |
29
+
30
+ ## Declaration and model
31
+
32
+ `route()` returns a `RouteModel` that does nothing but **wrap an immutable `RouteDeclaration`**. The
33
+ declaration is plain data an application ships in its contract package: `path` stays the segment this
34
+ route contributes under its parent and is never rewritten, and the model carries no state of its own.
35
+ Where the route answers is worked out on demand, against the context that asks — which is what lets
36
+ the same declaration serve a client and a server at once.
22
37
 
23
38
  ## Subpath Exports
24
39
 
25
- - `./utils` — path manipulation helpers
40
+ - `./utils` — the computed address helpers, all taking `(context, declaration)`
41
+
42
+ | Helper | Answers |
43
+ |--------|---------|
44
+ | `resolvePath` | Every ancestor's segment, then this one |
45
+ | `resolveMount` | `base` + the full path — what a server mounts and a client requests |
46
+ | `resolveService` | The service the declaration answers on: the one it names, else the default of its app type, else the first of that type |
47
+ | `resolveAddress` | The `RouteAddress`; a hop over a service's INTERNAL host is never TLS |
48
+ | `isLocalRoute` | Does the route belong to the service the asking context IS? |
49
+ | `getParentRoute` | The parent declaration, with parentship-cycle detection |
50
+ | `overrideParams` / `prependBase` | Fill blanks in a declaration; prefix a path with its base |
51
+ | `isServiceRoute` / `isServiceRouteResolved` | Guards for service entries |
52
+
53
+ Application code rarely calls these directly — `@owlmeans/entrypoint` exposes them as `path()`,
54
+ `mount()`, `service()`, `address()` and `isLocal()` on the entrypoint itself.
26
55
 
27
56
  ## Usage
28
57
 
@@ -46,5 +75,6 @@ entrypoint(
46
75
 
47
76
  ## Depends On
48
77
 
78
+ - `@owlmeans/context` — `AppType`, and the entrypoint registry the address helpers walk
49
79
  - `@owlmeans/error` — route errors
50
80
  - `@owlmeans/i18n` — translatable errors
package/build/helper.d.ts CHANGED
@@ -1,8 +1,8 @@
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>;
@@ -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,GAAI,MAAM,MAAM,KAAG,MAM5C,CAAA;AAED,eAAO,MAAM,KAAK,GAAI,MAAM,OAAO,EAAE,OAAO,YAAY,GAAG,MAAM,KAAG,OAAO,CAAC,YAAY,CAEvF,CAAA;AAED,eAAO,MAAM,OAAO,GAAI,OAAO,YAAY,GAAG,MAAM,GAAG,IAAI,EAAE,SAAS,YAAY,GAAG,WAAW,KAAG,OAAO,CAAC,YAAY,CAQtH,CAAA;AAED,eAAO,MAAM,OAAO,GAAI,SAAS,MAAM,EAAE,OAAO,OAAO,CAAC,YAAY,CAAC,KAAG,OAAO,CAAC,YAAY,CAI3F,CAAA;AAED,eAAO,MAAM,MAAM,GAAI,OAAO,YAAY,GAAG,MAAM,GAAG,IAAI,EAAE,YAAY,YAAY,KAAG,OAAO,CAAC,YAAY,CAM1G,CAAA;AAED,eAAO,MAAM,QAAQ,GAAI,OAAO,YAAY,GAAG,MAAM,GAAG,IAAI,EAAE,MAAM,YAAY,GAAG,OAAO,KAAG,OAAO,CAAC,YAAY,CAQhH,CAAA"}
@@ -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,GAAI,OAAO,gBAAgB,KAAG,UAAyB,CAAA;AAElF,eAAO,MAAM,WAAW,EAAE,oBAAoB,CAAC,gBAAgB,CAS9D,CAAA"}
package/build/model.js CHANGED
@@ -1,18 +1,10 @@
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) => {
11
4
  const route = {
12
5
  alias,
13
6
  type: AppType.Backend,
14
7
  path,
15
- resolved: false,
16
8
  ...(typeof opts === 'string' ? { parent: opts } : opts)
17
9
  };
18
10
  return route;
@@ -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,KAAK,GAAqB;QAC9B,KAAK;QACL,IAAI,EAAE,OAAO,CAAC,OAAO;QACrB,IAAI;QACJ,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"}
package/build/types.d.ts CHANGED
@@ -1,6 +1,20 @@
1
- import type { AppType, BasicContext, BasicConfig } from '@owlmeans/context';
1
+ import type { AppType } from '@owlmeans/context';
2
2
  import type { RouteProtocols, RouteMethod } from './consts';
3
- export interface CommonRoute extends BasicRoute {
3
+ export interface BasicRoute {
4
+ type: AppType;
5
+ service?: string;
6
+ host?: string;
7
+ port?: number;
8
+ base?: string;
9
+ internalHost?: string;
10
+ internalPort?: number;
11
+ }
12
+ /**
13
+ * The plain, declarative half of a route — what a `route()` call produces and what an application
14
+ * ships in its contract package. It is never rewritten: `path` stays the segment this route
15
+ * contributes under its parent, and the address is worked out on demand against a context.
16
+ */
17
+ export interface RouteDeclaration extends BasicRoute {
4
18
  alias: string;
5
19
  path: string;
6
20
  parent?: string;
@@ -14,22 +28,24 @@ export interface CommonServiceRoute extends BasicRoute {
14
28
  service: string;
15
29
  default?: boolean;
16
30
  }
17
- export interface BasicRoute {
18
- type: AppType;
19
- service?: string;
20
- host?: string;
21
- port?: number;
22
- base?: string;
23
- resolved: boolean;
24
- }
25
31
  export interface ResolvedServiceRoute extends CommonServiceRoute {
26
32
  host: string;
27
- resolved: true;
28
33
  }
29
- export interface CommonRouteModel {
30
- route: CommonRoute;
31
- resolve: <C extends BasicConfig, T extends BasicContext<C>>(context: T) => Promise<CommonRoute>;
34
+ /** Where a route actually answers, once its service has been picked. */
35
+ export interface RouteAddress {
36
+ host: string;
37
+ port?: number;
38
+ base?: string;
39
+ secure: boolean;
40
+ protocol: RouteProtocols;
41
+ }
42
+ /**
43
+ * The model wrapping a declaration. It carries no resolution state of its own — every address
44
+ * question is answered from the declaration plus the context that asks.
45
+ */
46
+ export interface RouteModel {
47
+ route: RouteDeclaration;
32
48
  }
33
- export interface RouteOptions extends Partial<CommonRoute> {
49
+ export interface RouteOptions extends Partial<RouteDeclaration> {
34
50
  }
35
51
  //# 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,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC3E,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAE3D,MAAM,WAAW,WAAY,SAAQ,UAAU;IAC7C,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,QAAQ,CAAC,EAAE,cAAc,CAAA;IACzB,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,MAAM,WAAW,kBAAmB,SAAQ,UAAU;IACpD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,oBAAqB,SAAQ,kBAAkB;IAC9D,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,IAAI,CAAA;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,WAAW,CAAA;IAClB,OAAO,EAAE,CAAC,CAAC,SAAS,WAAW,EAAE,CAAC,SAAS,YAAY,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,OAAO,CAAC,WAAW,CAAC,CAAA;CAChG;AAED,MAAM,WAAW,YAAa,SAAQ,OAAO,CAAC,WAAW,CAAC;CACzD"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAE3D,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAiB,SAAQ,UAAU;IAClD,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,QAAQ,CAAC,EAAE,cAAc,CAAA;IACzB,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,MAAM,WAAW,kBAAmB,SAAQ,UAAU;IACpD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,oBAAqB,SAAQ,kBAAkB;IAC9D,IAAI,EAAE,MAAM,CAAA;CACb;AAED,wEAAwE;AACxE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,OAAO,CAAA;IACf,QAAQ,EAAE,cAAc,CAAA;CACzB;AAED;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,gBAAgB,CAAA;CACxB;AAED,MAAM,WAAW,YAAa,SAAQ,OAAO,CAAC,gBAAgB,CAAC;CAC9D"}
@@ -1,9 +1,29 @@
1
1
  import type { BasicConfig, BasicContext } from '@owlmeans/context';
2
- import type { CommonRoute } from '../types.js';
2
+ import type { RouteAddress, RouteDeclaration, ResolvedServiceRoute } from '../types.js';
3
3
  type Config = BasicConfig;
4
- export declare const getParentRoute: <C extends Config, T extends BasicContext<C>>(context: T, route: CommonRoute) => Promise<CommonRoute | null>;
5
- export declare const overrideParams: (route: CommonRoute, overrides?: Partial<CommonRoute>, filter?: string[]) => void;
6
- export declare const resolve: <C extends Config, T extends BasicContext<C>>(route: CommonRoute) => (context: T) => Promise<CommonRoute>;
7
- export declare const prependBase: (route: CommonRoute) => string;
4
+ export declare const getParentRoute: <C extends Config, T extends BasicContext<C>>(context: T, route: RouteDeclaration) => RouteDeclaration | null;
5
+ export declare const overrideParams: (route: RouteDeclaration, overrides?: Partial<RouteDeclaration>, filter?: string[]) => void;
6
+ /**
7
+ * Pick the service route this declaration answers on: the one it names, else the default of its
8
+ * app type, else the first of its app type.
9
+ *
10
+ * @throws {SyntaxError}
11
+ */
12
+ export declare const resolveService: <C extends Config, T extends BasicContext<C>>(context: T, route: RouteDeclaration) => ResolvedServiceRoute;
13
+ /**
14
+ * The full path: every ancestor's declared segment, then this one. Walks the parent chain through
15
+ * the context, so a declaration always states only what it contributes.
16
+ */
17
+ export declare const resolvePath: <C extends Config, T extends BasicContext<C>>(context: T, route: RouteDeclaration) => string;
18
+ /** `base` + the full path — what a server mounts and a client requests. */
19
+ export declare const resolveMount: <C extends Config, T extends BasicContext<C>>(context: T, route: RouteDeclaration) => string;
20
+ /**
21
+ * Where the route answers. A backend caller reaching a service over its INTERNAL host is inside the
22
+ * cluster, so that hop is never TLS.
23
+ */
24
+ export declare const resolveAddress: <C extends Config, T extends BasicContext<C>>(context: T, route: RouteDeclaration) => RouteAddress;
25
+ /** Does this route belong to the service the asking context IS? */
26
+ export declare const isLocalRoute: <C extends Config, T extends BasicContext<C>>(context: T, route: RouteDeclaration) => boolean;
27
+ export declare const prependBase: (route: RouteDeclaration, path: string) => string;
8
28
  export {};
9
29
  //# sourceMappingURL=route.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../src/utils/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAc,MAAM,mBAAmB,CAAA;AAC9E,OAAO,KAAK,EAAE,WAAW,EAAwC,MAAM,aAAa,CAAA;AAKpF,KAAK,MAAM,GAAG,WAAW,CAAA;AAEzB,eAAO,MAAM,cAAc,GAAU,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC,SAAS,WAAW,KAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAkB5I,CAAA;AAED,eAAO,MAAM,cAAc,UAAW,WAAW,cAAc,OAAO,CAAC,WAAW,CAAC,WAAW,MAAM,EAAE,SAOrG,CAAA;AAED,eAAO,MAAM,OAAO,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,YAAY,CAAC,CAAC,CAAC,SAAS,WAAW,eAAqB,CAAC,yBA8D5G,CAAA;AAcD,eAAO,MAAM,WAAW,UAAW,WAAW,WAO7C,CAAA"}
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../src/utils/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAc,MAAM,mBAAmB,CAAA;AAC9E,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAkC,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAKvH,KAAK,MAAM,GAAG,WAAW,CAAA;AAWzB,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,YAAY,CAAC,CAAC,CAAC,EACxE,SAAS,CAAC,EAAE,OAAO,gBAAgB,KAClC,gBAAgB,GAAG,IAWrB,CAAA;AAED,eAAO,MAAM,cAAc,GAAI,OAAO,gBAAgB,EAAE,YAAY,OAAO,CAAC,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,SAO/G,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,YAAY,CAAC,CAAC,CAAC,EACxE,SAAS,CAAC,EAAE,OAAO,gBAAgB,KAClC,oBA4BF,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,YAAY,CAAC,CAAC,CAAC,EACrE,SAAS,CAAC,EAAE,OAAO,gBAAgB,KAClC,MASF,CAAA;AAED,2EAA2E;AAC3E,eAAO,MAAM,YAAY,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,YAAY,CAAC,CAAC,CAAC,EACtE,SAAS,CAAC,EAAE,OAAO,gBAAgB,KAClC,MAOF,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,YAAY,CAAC,CAAC,CAAC,EACxE,SAAS,CAAC,EAAE,OAAO,gBAAgB,KAClC,YAYF,CAAA;AAED,mEAAmE;AACnE,eAAO,MAAM,YAAY,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,YAAY,CAAC,CAAC,CAAC,EACtE,SAAS,CAAC,EAAE,OAAO,gBAAgB,KAClC,OAAyE,CAAA;AAgB5E,eAAO,MAAM,WAAW,GAAI,OAAO,gBAAgB,EAAE,MAAM,MAAM,WAGvD,CAAA"}
@@ -1,24 +1,17 @@
1
1
  import { isServiceRoute, isServiceRouteResolved } from './service.js';
2
2
  import { normalizePath } from '../helper.js';
3
- import { SEP } from '../consts.js';
4
- export const getParentRoute = async (context, route) => {
5
- if (route.parent != null) {
6
- const parent = context.module(route.parent);
7
- assertCycle(context, route, parent.route.route);
8
- if (parent.route == null) {
9
- throw new SyntaxError('Parent module doesn\'t provide a route');
10
- }
11
- if (!parent.route.route.resolved) {
12
- if (parent.resolve != null) {
13
- await parent.resolve();
14
- }
15
- else {
16
- return await parent.route.resolve(context);
17
- }
18
- }
19
- return parent.route.route;
3
+ import { RouteProtocols, SEP } from '../consts.js';
4
+ const carrier = (context, alias) => context.entrypoint(alias);
5
+ export const getParentRoute = (context, route) => {
6
+ if (route.parent == null) {
7
+ return null;
8
+ }
9
+ const parent = carrier(context, route.parent);
10
+ if (parent.route == null) {
11
+ throw new SyntaxError('Parent entrypoint doesn\'t provide a route');
20
12
  }
21
- return null;
13
+ assertCycle(context, route, parent.route.route);
14
+ return parent.route.route;
22
15
  };
23
16
  export const overrideParams = (route, overrides, filter) => {
24
17
  Object.entries(overrides ?? {}).forEach(([key, value]) => {
@@ -28,59 +21,72 @@ export const overrideParams = (route, overrides, filter) => {
28
21
  }
29
22
  });
30
23
  };
31
- export const resolve = (route) => async (context) => {
32
- if (route.resolved)
33
- return route;
34
- route.resolved = true;
24
+ /**
25
+ * Pick the service route this declaration answers on: the one it names, else the default of its
26
+ * app type, else the first of its app type.
27
+ *
28
+ * @throws {SyntaxError}
29
+ */
30
+ export const resolveService = (context, route) => {
35
31
  if (context.cfg.services == null) {
36
32
  throw new SyntaxError('Services aren\'t configured to resolve routes');
37
33
  }
38
- const firstGuessService = context.cfg.services[route.service ?? context.cfg.service];
39
- if (firstGuessService != null && !isServiceRoute(firstGuessService)) {
34
+ const named = context.cfg.services[route.service ?? context.cfg.service];
35
+ if (named != null && !isServiceRoute(named)) {
40
36
  throw new SyntaxError('Service is not a valid service route');
41
37
  }
42
- const service = firstGuessService?.type === route.type ? firstGuessService
43
- : Object.values(context.cfg.services).find((service) => {
44
- const _service = service;
45
- return _service.default === true && _service.type === route.type;
46
- }) ?? Object.values(context.cfg.services).find((service) => {
47
- const _service = service;
48
- return _service.type === route.type;
49
- });
38
+ const service = named?.type === route.type ? named
39
+ : Object.values(context.cfg.services).find((candidate) => {
40
+ const _candidate = candidate;
41
+ return _candidate.default === true && _candidate.type === route.type;
42
+ }) ?? Object.values(context.cfg.services).find((candidate) => candidate.type === route.type);
50
43
  if (!isServiceRoute(service)) {
51
44
  throw new SyntaxError('Service is not a valid service route');
52
45
  }
53
- if (!service.resolved && service.host != null) {
54
- service.resolved = true;
55
- }
56
46
  if (!isServiceRouteResolved(service)) {
57
47
  throw new SyntaxError('Service route is not resolved');
58
48
  }
59
- overrideParams(route, service, ['host', 'port', 'service', 'base']);
60
- // Internal host access is non secure only
61
- // it's required for server side client routes
62
- if ("internalHost" in route) {
63
- if (route.internalHost === route.host) {
64
- route.secure = false;
65
- }
66
- }
67
- else if ("internalHost" in service) {
68
- if (service.internalHost === route.host) {
69
- route.secure = false;
70
- }
71
- }
72
- const parent = await getParentRoute(context, route);
73
- if (parent != null) {
74
- route.path = (parent.path.startsWith(SEP) ? SEP : '')
75
- + normalizePath(normalizePath(parent.path) + SEP + normalizePath(route.path));
49
+ return service;
50
+ };
51
+ /**
52
+ * The full path: every ancestor's declared segment, then this one. Walks the parent chain through
53
+ * the context, so a declaration always states only what it contributes.
54
+ */
55
+ export const resolvePath = (context, route) => {
56
+ const parent = getParentRoute(context, route);
57
+ if (parent == null) {
58
+ return route.path;
76
59
  }
77
- // Moved base resolution to the final service
78
- // if (parent == null && route.base != null && route.base.trim() !== '') {
79
- // route.path = SEP + normalizePath(route.base) + SEP + normalizePath(route.path)
80
- // // route.path = route.base.startsWith(SEP) ? SEP + route.path : route.path
81
- // }
82
- return route;
60
+ const parentPath = resolvePath(context, parent);
61
+ return (parentPath.startsWith(SEP) ? SEP : '')
62
+ + normalizePath(normalizePath(parentPath) + SEP + normalizePath(route.path));
63
+ };
64
+ /** `base` + the full path — what a server mounts and a client requests. */
65
+ export const resolveMount = (context, route) => {
66
+ const path = resolvePath(context, route);
67
+ const base = route.base ?? resolveService(context, route).base;
68
+ return base != null && base.trim() !== ''
69
+ ? SEP + normalizePath(base) + SEP + normalizePath(path)
70
+ : path;
83
71
  };
72
+ /**
73
+ * Where the route answers. A backend caller reaching a service over its INTERNAL host is inside the
74
+ * cluster, so that hop is never TLS.
75
+ */
76
+ export const resolveAddress = (context, route) => {
77
+ const service = resolveService(context, route);
78
+ const host = route.host ?? service.host;
79
+ const internalHost = route.internalHost ?? service.internalHost;
80
+ return {
81
+ host,
82
+ port: route.port ?? service.port,
83
+ base: route.base ?? service.base,
84
+ secure: internalHost != null && internalHost === host ? false : route.secure ?? true,
85
+ protocol: route.protocol ?? RouteProtocols.WEB,
86
+ };
87
+ };
88
+ /** Does this route belong to the service the asking context IS? */
89
+ export const isLocalRoute = (context, route) => (route.service ?? context.cfg.service) === context.cfg.service;
84
90
  /**
85
91
  * @throws {SyntaxError}
86
92
  */
@@ -89,15 +95,10 @@ const assertCycle = (context, route, parent) => {
89
95
  if (parent.parent === route.alias) {
90
96
  throw new SyntaxError(`Route parentship cycle detected. Parent: ${parent.alias} has his child as ancestor ${route.alias}`);
91
97
  }
92
- parent = context.module(parent.parent).route.route;
93
- }
94
- };
95
- export const prependBase = (route) => {
96
- let path = route.path;
97
- if (route.base != null && route.base.trim() !== '') {
98
- path = SEP + normalizePath(route.base) + SEP + normalizePath(route.path);
99
- // route.path = route.base.startsWith(SEP) ? SEP + route.path : route.path
98
+ parent = carrier(context, parent.parent).route.route;
100
99
  }
101
- return path;
102
100
  };
101
+ export const prependBase = (route, path) => route.base != null && route.base.trim() !== ''
102
+ ? SEP + normalizePath(route.base) + SEP + normalizePath(path)
103
+ : path;
103
104
  //# sourceMappingURL=route.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"route.js","sourceRoot":"","sources":["../../src/utils/route.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAA;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAA;AAIlC,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EAA+C,OAAU,EAAE,KAAkB,EAA+B,EAAE;IAC/I,IAAI,KAAK,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAyF,KAAK,CAAC,MAAM,CAAC,CAAA;QACnI,WAAW,CAAO,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;QACrD,IAAI,MAAM,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC;YACzB,MAAM,IAAI,WAAW,CAAC,wCAAwC,CAAC,CAAA;QACjE,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;YACjC,IAAI,MAAM,CAAC,OAAO,IAAI,IAAI,EAAE,CAAC;gBAC3B,MAAM,MAAM,CAAC,OAAO,EAAE,CAAA;YACxB,CAAC;iBAAM,CAAC;gBACN,OAAO,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,CAAO,OAAO,CAAC,CAAA;YAClD,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC,KAAK,CAAC,KAAK,CAAA;IAC3B,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAkB,EAAE,SAAgC,EAAE,MAAiB,EAAE,EAAE;IACxG,MAAM,CAAC,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;QACvD,IAAI,KAAK,CAAC,GAAwB,CAAC,IAAI,IAAI;eACtC,CAAC,MAAM,IAAI,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YAC7C,KAAK,CAAC,GAAwB,CAAoC,GAAG,KAAK,CAAA;QAC7E,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,OAAO,GAAG,CAA8C,KAAkB,EAAE,EAAE,CAAC,KAAK,EAAE,OAAU,EAAE,EAAE;IAC/G,IAAI,KAAK,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAA;IAChC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAA;IAErB,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,IAAI,EAAE,CAAC;QACjC,MAAM,IAAI,WAAW,CAAC,+CAA+C,CAAC,CAAA;IACxE,CAAC;IAED,MAAM,iBAAiB,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IACpF,IAAI,iBAAiB,IAAI,IAAI,IAAI,CAAC,cAAc,CAAC,iBAAiB,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,WAAW,CAAC,sCAAsC,CAAC,CAAA;IAC/D,CAAC;IACD,MAAM,OAAO,GAAG,iBAAiB,EAAE,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,iBAAiB;QACxE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CACxC,CAAC,OAAO,EAAiC,EAAE;YACzC,MAAM,QAAQ,GAAG,OAA6B,CAAA;YAC9C,OAAO,QAAQ,CAAC,OAAO,KAAK,IAAI,IAAI,QAAQ,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,CAAA;QAClE,CAAC,CACF,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CAC3C,CAAC,OAAO,EAAiC,EAAE;YACzC,MAAM,QAAQ,GAAG,OAA6B,CAAA;YAC9C,OAAO,QAAQ,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,CAAA;QACrC,CAAC,CACF,CAAA;IACH,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,WAAW,CAAC,sCAAsC,CAAC,CAAA;IAC/D,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC;QAC9C,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAA;IACzB,CAAC;IACD,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,WAAW,CAAC,+BAA+B,CAAC,CAAA;IACxD,CAAC;IAED,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAA;IAEnE,0CAA0C;IAC1C,8CAA8C;IAC9C,IAAI,cAAc,IAAI,KAAK,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,YAAY,KAAK,KAAK,CAAC,IAAI,EAAE,CAAC;YACtC,KAAK,CAAC,MAAM,GAAG,KAAK,CAAA;QACtB,CAAC;IACH,CAAC;SAAM,IAAI,cAAc,IAAI,OAAO,EAAE,CAAC;QACrC,IAAI,OAAO,CAAC,YAAY,KAAK,KAAK,CAAC,IAAI,EAAE,CAAC;YACxC,KAAK,CAAC,MAAM,GAAG,KAAK,CAAA;QACtB,CAAC;IACH,CAAC;IAGD,MAAM,MAAM,GAAG,MAAM,cAAc,CAAO,OAAO,EAAE,KAAK,CAAC,CAAA;IACzD,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;QACnB,KAAK,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;cACjD,aAAa,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,GAAG,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAA;IACjF,CAAC;IAED,6CAA6C;IAC7C,0EAA0E;IAC1E,mFAAmF;IACnF,+EAA+E;IAC/E,IAAI;IAEJ,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,WAAW,GAAG,CAAmD,OAAU,EAAE,KAAkB,EAAE,MAAmB,EAAE,EAAE;IAC5H,OAAO,MAAM,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC;QAC7B,IAAI,MAAM,CAAC,MAAM,KAAK,KAAK,CAAC,KAAK,EAAE,CAAC;YAClC,MAAM,IAAI,WAAW,CAAC,4CAA4C,MAAM,CAAC,KAAK,8BAA8B,KAAK,CAAC,KAAK,EAAE,CAAC,CAAA;QAC5H,CAAC;QACD,MAAM,GAAG,OAAO,CAAC,MAAM,CAA0D,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,KAAK,CAAA;IAC7G,CAAC;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,KAAkB,EAAE,EAAE;IAChD,IAAI,IAAI,GAAG,KAAK,CAAC,IAAI,CAAA;IACrB,IAAI,KAAK,CAAC,IAAI,IAAI,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACnD,IAAI,GAAG,GAAG,GAAG,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,GAAG,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QACxE,0EAA0E;IAC5E,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC,CAAA"}
1
+ {"version":3,"file":"route.js","sourceRoot":"","sources":["../../src/utils/route.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import type { ResolvedServiceRoute, CommonServiceRoute } from '../types.js';
2
2
  export declare const isServiceRoute: (obj?: Object) => obj is CommonServiceRoute;
3
+ /** A service route is usable exactly when it knows the host it answers on. */
3
4
  export declare const isServiceRouteResolved: (route: CommonServiceRoute) => route is ResolvedServiceRoute;
4
5
  //# sourceMappingURL=service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/utils/service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAE3E,eAAO,MAAM,cAAc,SAAU,MAAM,KAAG,GAAG,IAAI,kBAEM,CAAA;AAE3D,eAAO,MAAM,sBAAsB,UAAW,kBAAkB,KAAG,KAAK,IAAI,oBACnD,CAAA"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/utils/service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAE3E,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,KAAG,GAAG,IAAI,kBAEM,CAAA;AAE3D,8EAA8E;AAC9E,eAAO,MAAM,sBAAsB,GAAI,OAAO,kBAAkB,KAAG,KAAK,IAAI,oBAC5B,CAAA"}
@@ -1,5 +1,6 @@
1
1
  import { AppType } from '@owlmeans/context';
2
2
  export const isServiceRoute = (obj) => obj != null && ('type' in obj) && ('service' in obj)
3
3
  && (Object.values(AppType).includes(obj.type));
4
- export const isServiceRouteResolved = (route) => route.resolved === true;
4
+ /** A service route is usable exactly when it knows the host it answers on. */
5
+ export const isServiceRouteResolved = (route) => route.host != null && route.host.trim() !== '';
5
6
  //# sourceMappingURL=service.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/utils/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAG3C,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,GAAY,EAA6B,EAAE,CACxE,GAAG,IAAI,IAAI,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,SAAS,IAAI,GAAG,CAAC;OACjD,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAe,CAAC,CAAC,CAAA;AAE3D,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,KAAyB,EAAiC,EAAE,CACjG,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAA"}
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/utils/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAG3C,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,GAAY,EAA6B,EAAE,CACxE,GAAG,IAAI,IAAI,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,SAAS,IAAI,GAAG,CAAC;OACjD,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAe,CAAC,CAAC,CAAA;AAE3D,8EAA8E;AAC9E,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,KAAyB,EAAiC,EAAE,CACjG,KAAK,CAAC,IAAI,IAAI,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owlmeans/route",
3
- "version": "0.1.18-rc.5",
3
+ "version": "0.1.18-rc.7",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -28,7 +28,7 @@
28
28
  }
29
29
  },
30
30
  "dependencies": {
31
- "@owlmeans/context": "^0.1.18-rc.5"
31
+ "@owlmeans/context": "^0.1.18-rc.7"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@owlmeans/dep-config": "workspace:*",
package/src/helper.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import { AppType } from '@owlmeans/context'
2
2
  import { RouteMethod, RouteProtocols, SEP } from './consts.js'
3
3
  import { createRoute, makeRouteModel } from './model.js'
4
- import type { CommonRouteModel, RouteOptions } from './types.js'
4
+ import type { RouteModel, RouteOptions } from './types.js'
5
5
  import type { CreateRouteSignature } from './utils/types.js'
6
6
 
7
- export const route: CreateRouteSignature<CommonRouteModel> = (alias, path, opts?) =>
7
+ export const route: CreateRouteSignature<RouteModel> = (alias, path, opts?) =>
8
8
  makeRouteModel(createRoute(alias, path, opts))
9
9
 
10
10
  export const normalizePath = (path: string): string => {
package/src/model.ts CHANGED
@@ -1,23 +1,14 @@
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
- import { resolve } from './utils/route.js'
4
- import { AppType, BasicConfig, BasicContext } from '@owlmeans/context'
3
+ import { AppType } from '@owlmeans/context'
5
4
 
6
- export const makeRouteModel = (route: CommonRoute): CommonRouteModel => {
7
- const model: CommonRouteModel = {
8
- route,
9
- resolve: ctx => resolve(route)(ctx as unknown as BasicContext<BasicConfig>)
10
- }
11
-
12
- return model
13
- }
5
+ export const makeRouteModel = (route: RouteDeclaration): RouteModel => ({ route })
14
6
 
15
- export const createRoute: CreateRouteSignature<CommonRoute> = (alias, path, opts?) => {
16
- const route: CommonRoute = {
7
+ export const createRoute: CreateRouteSignature<RouteDeclaration> = (alias, path, opts?) => {
8
+ const route: RouteDeclaration = {
17
9
  alias,
18
10
  type: AppType.Backend,
19
11
  path,
20
- resolved: false,
21
12
  ...(typeof opts === 'string' ? { parent: opts } : opts)
22
13
  }
23
14
 
package/src/types.ts CHANGED
@@ -1,7 +1,22 @@
1
- import type { AppType, BasicContext, BasicConfig } from '@owlmeans/context'
1
+ import type { AppType } from '@owlmeans/context'
2
2
  import type { RouteProtocols, RouteMethod } from './consts'
3
3
 
4
- export interface CommonRoute extends BasicRoute {
4
+ export interface BasicRoute {
5
+ type: AppType
6
+ service?: string
7
+ host?: string
8
+ port?: number
9
+ base?: string
10
+ internalHost?: string
11
+ internalPort?: number
12
+ }
13
+
14
+ /**
15
+ * The plain, declarative half of a route — what a `route()` call produces and what an application
16
+ * ships in its contract package. It is never rewritten: `path` stays the segment this route
17
+ * contributes under its parent, and the address is worked out on demand against a context.
18
+ */
19
+ export interface RouteDeclaration extends BasicRoute {
5
20
  alias: string
6
21
  path: string
7
22
  parent?: string
@@ -17,24 +32,26 @@ export interface CommonServiceRoute extends BasicRoute {
17
32
  default?: boolean
18
33
  }
19
34
 
20
- export interface BasicRoute {
21
- type: AppType
22
- service?: string
23
- host?: string
24
- port?: number
25
- base?: string
26
- resolved: boolean
35
+ export interface ResolvedServiceRoute extends CommonServiceRoute {
36
+ host: string
27
37
  }
28
38
 
29
- export interface ResolvedServiceRoute extends CommonServiceRoute {
39
+ /** Where a route actually answers, once its service has been picked. */
40
+ export interface RouteAddress {
30
41
  host: string
31
- resolved: true
42
+ port?: number
43
+ base?: string
44
+ secure: boolean
45
+ protocol: RouteProtocols
32
46
  }
33
47
 
34
- export interface CommonRouteModel {
35
- route: CommonRoute
36
- resolve: <C extends BasicConfig, T extends BasicContext<C>>(context: T) => Promise<CommonRoute>
48
+ /**
49
+ * The model wrapping a declaration. It carries no resolution state of its own — every address
50
+ * question is answered from the declaration plus the context that asks.
51
+ */
52
+ export interface RouteModel {
53
+ route: RouteDeclaration
37
54
  }
38
55
 
39
- export interface RouteOptions extends Partial<CommonRoute> {
56
+ export interface RouteOptions extends Partial<RouteDeclaration> {
40
57
  }
@@ -1,121 +1,151 @@
1
1
  import type { BasicConfig, BasicContext, Contextual } from '@owlmeans/context'
2
- import type { CommonRoute, CommonRouteModel, CommonServiceRoute } from '../types.js'
2
+ import type { RouteAddress, RouteDeclaration, RouteModel, CommonServiceRoute, ResolvedServiceRoute } from '../types.js'
3
3
  import { isServiceRoute, isServiceRouteResolved } from './service.js'
4
4
  import { normalizePath } from '../helper.js'
5
- import { SEP } from '../consts.js'
5
+ import { RouteProtocols, SEP } from '../consts.js'
6
6
 
7
7
  type Config = BasicConfig
8
8
 
9
- export const getParentRoute = async <C extends Config, T extends BasicContext<C>>(context: T, route: CommonRoute): Promise<CommonRoute | null> => {
10
- if (route.parent != null) {
11
- const parent = context.module<Contextual & { _module: true, route: CommonRouteModel, resolve?: () => Promise<void> }>(route.parent)
12
- assertCycle<C, T>(context, route, parent.route.route)
13
- if (parent.route == null) {
14
- throw new SyntaxError('Parent module doesn\'t provide a route')
15
- }
16
- if (!parent.route.route.resolved) {
17
- if (parent.resolve != null) {
18
- await parent.resolve()
19
- } else {
20
- return await parent.route.resolve<C, T>(context)
21
- }
22
- }
23
- return parent.route.route
9
+ /** What an entrypoint looks like from the route layer: something that carries a route model. */
10
+ interface RouteCarrier extends Contextual {
11
+ _entrypoint: true
12
+ route: RouteModel
13
+ }
14
+
15
+ const carrier = <C extends Config, T extends BasicContext<C>>(context: T, alias: string): RouteCarrier =>
16
+ context.entrypoint<RouteCarrier>(alias)
17
+
18
+ export const getParentRoute = <C extends Config, T extends BasicContext<C>>(
19
+ context: T, route: RouteDeclaration
20
+ ): RouteDeclaration | null => {
21
+ if (route.parent == null) {
22
+ return null
24
23
  }
24
+ const parent = carrier<C, T>(context, route.parent)
25
+ if (parent.route == null) {
26
+ throw new SyntaxError('Parent entrypoint doesn\'t provide a route')
27
+ }
28
+ assertCycle<C, T>(context, route, parent.route.route)
25
29
 
26
- return null
30
+ return parent.route.route
27
31
  }
28
32
 
29
- export const overrideParams = (route: CommonRoute, overrides?: Partial<CommonRoute>, filter?: string[]) => {
33
+ export const overrideParams = (route: RouteDeclaration, overrides?: Partial<RouteDeclaration>, filter?: string[]) => {
30
34
  Object.entries(overrides ?? {}).forEach(([key, value]) => {
31
- if (route[key as keyof CommonRoute] == null
35
+ if (route[key as keyof RouteDeclaration] == null
32
36
  && (filter == null || filter.includes(key))) {
33
- (route[key as keyof CommonRoute] as CommonRoute[keyof CommonRoute]) = value
37
+ (route[key as keyof RouteDeclaration] as RouteDeclaration[keyof RouteDeclaration]) = value
34
38
  }
35
39
  })
36
40
  }
37
41
 
38
- export const resolve = <C extends Config, T extends BasicContext<C>>(route: CommonRoute) => async (context: T) => {
39
- if (route.resolved) return route
40
- route.resolved = true
41
-
42
+ /**
43
+ * Pick the service route this declaration answers on: the one it names, else the default of its
44
+ * app type, else the first of its app type.
45
+ *
46
+ * @throws {SyntaxError}
47
+ */
48
+ export const resolveService = <C extends Config, T extends BasicContext<C>>(
49
+ context: T, route: RouteDeclaration
50
+ ): ResolvedServiceRoute => {
42
51
  if (context.cfg.services == null) {
43
52
  throw new SyntaxError('Services aren\'t configured to resolve routes')
44
53
  }
45
54
 
46
- const firstGuessService = context.cfg.services[route.service ?? context.cfg.service]
47
- if (firstGuessService != null && !isServiceRoute(firstGuessService)) {
55
+ const named = context.cfg.services[route.service ?? context.cfg.service]
56
+ if (named != null && !isServiceRoute(named)) {
48
57
  throw new SyntaxError('Service is not a valid service route')
49
58
  }
50
- const service = firstGuessService?.type === route.type ? firstGuessService
59
+
60
+ const service = named?.type === route.type ? named
51
61
  : Object.values(context.cfg.services).find<CommonServiceRoute>(
52
- (service): service is CommonServiceRoute => {
53
- const _service = service as CommonServiceRoute
54
- return _service.default === true && _service.type === route.type
62
+ (candidate): candidate is CommonServiceRoute => {
63
+ const _candidate = candidate as CommonServiceRoute
64
+ return _candidate.default === true && _candidate.type === route.type
55
65
  }
56
66
  ) ?? Object.values(context.cfg.services).find<CommonServiceRoute>(
57
- (service): service is CommonServiceRoute => {
58
- const _service = service as CommonServiceRoute
59
- return _service.type === route.type
60
- }
67
+ (candidate): candidate is CommonServiceRoute => (candidate as CommonServiceRoute).type === route.type
61
68
  )
69
+
62
70
  if (!isServiceRoute(service)) {
63
71
  throw new SyntaxError('Service is not a valid service route')
64
72
  }
65
- if (!service.resolved && service.host != null) {
66
- service.resolved = true
67
- }
68
73
  if (!isServiceRouteResolved(service)) {
69
74
  throw new SyntaxError('Service route is not resolved')
70
75
  }
71
76
 
72
- overrideParams(route, service, ['host', 'port', 'service', 'base'])
77
+ return service
78
+ }
73
79
 
74
- // Internal host access is non secure only
75
- // it's required for server side client routes
76
- if ("internalHost" in route) {
77
- if (route.internalHost === route.host) {
78
- route.secure = false
79
- }
80
- } else if ("internalHost" in service) {
81
- if (service.internalHost === route.host) {
82
- route.secure = false
83
- }
80
+ /**
81
+ * The full path: every ancestor's declared segment, then this one. Walks the parent chain through
82
+ * the context, so a declaration always states only what it contributes.
83
+ */
84
+ export const resolvePath = <C extends Config, T extends BasicContext<C>>(
85
+ context: T, route: RouteDeclaration
86
+ ): string => {
87
+ const parent = getParentRoute<C, T>(context, route)
88
+ if (parent == null) {
89
+ return route.path
84
90
  }
85
-
91
+ const parentPath = resolvePath<C, T>(context, parent)
86
92
 
87
- const parent = await getParentRoute<C, T>(context, route)
88
- if (parent != null) {
89
- route.path = (parent.path.startsWith(SEP) ? SEP : '')
90
- + normalizePath(normalizePath(parent.path) + SEP + normalizePath(route.path))
91
- }
93
+ return (parentPath.startsWith(SEP) ? SEP : '')
94
+ + normalizePath(normalizePath(parentPath) + SEP + normalizePath(route.path))
95
+ }
92
96
 
93
- // Moved base resolution to the final service
94
- // if (parent == null && route.base != null && route.base.trim() !== '') {
95
- // route.path = SEP + normalizePath(route.base) + SEP + normalizePath(route.path)
96
- // // route.path = route.base.startsWith(SEP) ? SEP + route.path : route.path
97
- // }
97
+ /** `base` + the full path — what a server mounts and a client requests. */
98
+ export const resolveMount = <C extends Config, T extends BasicContext<C>>(
99
+ context: T, route: RouteDeclaration
100
+ ): string => {
101
+ const path = resolvePath<C, T>(context, route)
102
+ const base = route.base ?? resolveService<C, T>(context, route).base
98
103
 
99
- return route
104
+ return base != null && base.trim() !== ''
105
+ ? SEP + normalizePath(base) + SEP + normalizePath(path)
106
+ : path
100
107
  }
101
108
 
109
+ /**
110
+ * Where the route answers. A backend caller reaching a service over its INTERNAL host is inside the
111
+ * cluster, so that hop is never TLS.
112
+ */
113
+ export const resolveAddress = <C extends Config, T extends BasicContext<C>>(
114
+ context: T, route: RouteDeclaration
115
+ ): RouteAddress => {
116
+ const service = resolveService<C, T>(context, route)
117
+ const host = route.host ?? service.host
118
+ const internalHost = route.internalHost ?? service.internalHost
119
+
120
+ return {
121
+ host,
122
+ port: route.port ?? service.port,
123
+ base: route.base ?? service.base,
124
+ secure: internalHost != null && internalHost === host ? false : route.secure ?? true,
125
+ protocol: route.protocol ?? RouteProtocols.WEB,
126
+ }
127
+ }
128
+
129
+ /** Does this route belong to the service the asking context IS? */
130
+ export const isLocalRoute = <C extends Config, T extends BasicContext<C>>(
131
+ context: T, route: RouteDeclaration
132
+ ): boolean => (route.service ?? context.cfg.service) === context.cfg.service
133
+
102
134
  /**
103
135
  * @throws {SyntaxError}
104
136
  */
105
- const assertCycle = <C extends BasicConfig, T extends BasicContext<C>>(context: T, route: CommonRoute, parent: CommonRoute) => {
137
+ const assertCycle = <C extends BasicConfig, T extends BasicContext<C>>(
138
+ context: T, route: RouteDeclaration, parent: RouteDeclaration
139
+ ) => {
106
140
  while (parent.parent != null) {
107
141
  if (parent.parent === route.alias) {
108
142
  throw new SyntaxError(`Route parentship cycle detected. Parent: ${parent.alias} has his child as ancestor ${route.alias}`)
109
143
  }
110
- parent = context.module<Contextual & { _module: true, route: CommonRouteModel }>(parent.parent).route.route
144
+ parent = carrier<C, T>(context, parent.parent).route.route
111
145
  }
112
146
  }
113
147
 
114
- export const prependBase = (route: CommonRoute) => {
115
- let path = route.path
116
- if (route.base != null && route.base.trim() !== '') {
117
- path = SEP + normalizePath(route.base) + SEP + normalizePath(route.path)
118
- // route.path = route.base.startsWith(SEP) ? SEP + route.path : route.path
119
- }
120
- return path
121
- }
148
+ export const prependBase = (route: RouteDeclaration, path: string) =>
149
+ route.base != null && route.base.trim() !== ''
150
+ ? SEP + normalizePath(route.base) + SEP + normalizePath(path)
151
+ : path
@@ -5,5 +5,6 @@ export const isServiceRoute = (obj?: Object): obj is CommonServiceRoute =>
5
5
  obj != null && ('type' in obj) && ('service' in obj)
6
6
  && (Object.values(AppType).includes(obj.type as AppType))
7
7
 
8
+ /** A service route is usable exactly when it knows the host it answers on. */
8
9
  export const isServiceRouteResolved = (route: CommonServiceRoute): route is ResolvedServiceRoute =>
9
- route.resolved === true
10
+ route.host != null && route.host.trim() !== ''
package/build/.gitkeep DELETED
File without changes