@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 +236 -43
- package/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/route/SKILL.md +72 -14
- package/build/consts.d.ts +7 -1
- package/build/consts.d.ts.map +1 -1
- package/build/consts.js +6 -0
- package/build/consts.js.map +1 -1
- package/build/helper.d.ts +8 -2
- package/build/helper.d.ts.map +1 -1
- package/build/helper.js +10 -0
- package/build/helper.js.map +1 -1
- package/build/model.d.ts +3 -3
- package/build/model.d.ts.map +1 -1
- package/build/model.js +5 -10
- package/build/model.js.map +1 -1
- package/build/types.d.ts +46 -15
- package/build/types.d.ts.map +1 -1
- package/build/utils/route.d.ts +25 -5
- package/build/utils/route.d.ts.map +1 -1
- package/build/utils/route.js +68 -67
- package/build/utils/route.js.map +1 -1
- package/build/utils/service.d.ts +1 -0
- package/build/utils/service.d.ts.map +1 -1
- package/build/utils/service.js +2 -1
- package/build/utils/service.js.map +1 -1
- package/package.json +2 -2
- package/src/consts.ts +7 -1
- package/src/helper.ts +15 -2
- package/src/model.ts +9 -15
- package/src/types.ts +48 -15
- package/src/utils/route.ts +101 -71
- package/src/utils/service.ts +2 -1
- package/build/.gitkeep +0 -0
package/build/types.d.ts
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
|
-
import type { AppType,
|
|
1
|
+
import type { AppType, EntrypointReference } from '@owlmeans/context';
|
|
2
2
|
import type { RouteProtocols, RouteMethod } from './consts';
|
|
3
|
-
export interface
|
|
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;
|
|
@@ -8,28 +22,45 @@ export interface CommonRoute extends BasicRoute {
|
|
|
8
22
|
method?: RouteMethod;
|
|
9
23
|
protocol?: RouteProtocols;
|
|
10
24
|
secure?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* QUEUE routes only: the queue that carries this entrypoint's jobs. It names an address, not a
|
|
27
|
+
* process — which queues a given process consumes is configuration, never a declaration.
|
|
28
|
+
*/
|
|
29
|
+
queue?: string;
|
|
30
|
+
/**
|
|
31
|
+
* QUEUE routes only: whether the caller waits for the job's return value. `false` resolves as
|
|
32
|
+
* soon as the job is accepted, which is what a long pipeline wants; the default is to wait.
|
|
33
|
+
*/
|
|
34
|
+
reply?: boolean;
|
|
35
|
+
/** How long a caller waits for an answer, in milliseconds, when the transport supports it. */
|
|
36
|
+
timeout?: number;
|
|
11
37
|
}
|
|
12
38
|
export interface CommonServiceRoute extends BasicRoute {
|
|
13
39
|
home?: string;
|
|
14
40
|
service: string;
|
|
15
41
|
default?: boolean;
|
|
16
42
|
}
|
|
17
|
-
export interface BasicRoute {
|
|
18
|
-
type: AppType;
|
|
19
|
-
service?: string;
|
|
20
|
-
host?: string;
|
|
21
|
-
port?: number;
|
|
22
|
-
base?: string;
|
|
23
|
-
resolved: boolean;
|
|
24
|
-
}
|
|
25
43
|
export interface ResolvedServiceRoute extends CommonServiceRoute {
|
|
26
44
|
host: string;
|
|
27
|
-
resolved: true;
|
|
28
45
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
46
|
+
/** Where a route actually answers, once its service has been picked. */
|
|
47
|
+
export interface RouteAddress {
|
|
48
|
+
host: string;
|
|
49
|
+
port?: number;
|
|
50
|
+
base?: string;
|
|
51
|
+
secure: boolean;
|
|
52
|
+
protocol: RouteProtocols;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* The model wrapping a declaration. It carries no resolution state of its own — every address
|
|
56
|
+
* question is answered from the declaration plus the context that asks.
|
|
57
|
+
*/
|
|
58
|
+
export interface RouteModel {
|
|
59
|
+
route: RouteDeclaration;
|
|
32
60
|
}
|
|
33
|
-
export
|
|
61
|
+
export type RouteParent = string | EntrypointReference;
|
|
62
|
+
export interface RouteOptions extends Omit<Partial<RouteDeclaration>, 'parent'> {
|
|
63
|
+
/** A parent protocol is preferred in application declarations; strings remain adapter input. */
|
|
64
|
+
parent?: RouteParent;
|
|
34
65
|
}
|
|
35
66
|
//# 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,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACrE,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;IAChB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,8FAA8F;IAC9F,OAAO,CAAC,EAAE,MAAM,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,MAAM,WAAW,GAAG,MAAM,GAAG,mBAAmB,CAAA;AAEtD,MAAM,WAAW,YAAa,SAAQ,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,QAAQ,CAAC;IAC7E,gGAAgG;IAChG,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB"}
|
package/build/utils/route.d.ts
CHANGED
|
@@ -1,9 +1,29 @@
|
|
|
1
1
|
import type { BasicConfig, BasicContext } from '@owlmeans/context';
|
|
2
|
-
import type {
|
|
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:
|
|
5
|
-
export declare const overrideParams: (route:
|
|
6
|
-
|
|
7
|
-
|
|
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,
|
|
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,WAC/D,CAAC,SAAS,gBAAgB,KAClC,gBAAgB,GAAG,IAWrB,CAAA;AAED,eAAO,MAAM,cAAc,UAAW,gBAAgB,cAAc,OAAO,CAAC,gBAAgB,CAAC,WAAW,MAAM,EAAE,SAO/G,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,YAAY,CAAC,CAAC,CAAC,WAC/D,CAAC,SAAS,gBAAgB,KAClC,oBA4BF,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,YAAY,CAAC,CAAC,CAAC,WAC5D,CAAC,SAAS,gBAAgB,KAClC,MASF,CAAA;AAED,2EAA2E;AAC3E,eAAO,MAAM,YAAY,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,YAAY,CAAC,CAAC,CAAC,WAC7D,CAAC,SAAS,gBAAgB,KAClC,MAOF,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,YAAY,CAAC,CAAC,CAAC,WAC/D,CAAC,SAAS,gBAAgB,KAClC,YAYF,CAAA;AAED,mEAAmE;AACnE,eAAO,MAAM,YAAY,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,YAAY,CAAC,CAAC,CAAC,WAC7D,CAAC,SAAS,gBAAgB,KAClC,OAAyE,CAAA;AAgB5E,eAAO,MAAM,WAAW,UAAW,gBAAgB,QAAQ,MAAM,WAGvD,CAAA"}
|
package/build/utils/route.js
CHANGED
|
@@ -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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
|
39
|
-
if (
|
|
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 =
|
|
43
|
-
: Object.values(context.cfg.services).find((
|
|
44
|
-
const
|
|
45
|
-
return
|
|
46
|
-
}) ?? Object.values(context.cfg.services).find((
|
|
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
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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
|
|
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
|
package/build/utils/route.js.map
CHANGED
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"route.js","sourceRoot":"","sources":["../../src/utils/route.ts"],"names":[],"mappings":"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"}
|
package/build/utils/service.d.ts
CHANGED
|
@@ -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,
|
|
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,8EAA8E;AAC9E,eAAO,MAAM,sBAAsB,UAAW,kBAAkB,KAAG,KAAK,IAAI,oBAC5B,CAAA"}
|
package/build/utils/service.js
CHANGED
|
@@ -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
|
-
|
|
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,
|
|
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.
|
|
3
|
+
"version": "0.1.18-rc.21",
|
|
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.
|
|
31
|
+
"@owlmeans/context": "^0.1.18-rc.20"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@owlmeans/dep-config": "workspace:*",
|
package/src/consts.ts
CHANGED
|
@@ -11,7 +11,13 @@ export const SEP = '/'
|
|
|
11
11
|
|
|
12
12
|
export const PARAM = ':'
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* How a route is carried. The protocol picks the transport that answers it — an application binds
|
|
16
|
+
* one by registering a service under `transportAlias(protocol)` — so a caller writes `call()` and
|
|
17
|
+
* never learns whether an HTTP request, a socket frame or a queued job did the work.
|
|
18
|
+
*/
|
|
14
19
|
export enum RouteProtocols {
|
|
15
20
|
WEB = 'http',
|
|
16
|
-
SOCKET = 'ws'
|
|
21
|
+
SOCKET = 'ws',
|
|
22
|
+
QUEUE = 'queue'
|
|
17
23
|
}
|
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 {
|
|
4
|
+
import type { RouteModel, RouteOptions } from './types.js'
|
|
5
5
|
import type { CreateRouteSignature } from './utils/types.js'
|
|
6
6
|
|
|
7
|
-
export const route: CreateRouteSignature<
|
|
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 => {
|
|
@@ -43,6 +43,19 @@ export const socket = (opts?: RouteOptions | string | null, secondary?: RouteOpt
|
|
|
43
43
|
return route
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
/**
|
|
47
|
+
* A backend route carried by the queue rather than by HTTP. Everything else about it is a normal
|
|
48
|
+
* backend route — it has a path, a parent, guards and a filter — so the same declaration is served
|
|
49
|
+
* with `bind(...)` and called with `call()`; only the transport underneath differs.
|
|
50
|
+
*/
|
|
51
|
+
export const job = (opts?: RouteOptions | string | null, secondary?: RouteOptions): Partial<RouteOptions> => {
|
|
52
|
+
const route = backend(opts, secondary)
|
|
53
|
+
|
|
54
|
+
route.protocol = RouteProtocols.QUEUE
|
|
55
|
+
|
|
56
|
+
return route
|
|
57
|
+
}
|
|
58
|
+
|
|
46
59
|
export const frontend = (opts?: RouteOptions | string | null, def?: RouteOptions | boolean): Partial<RouteOptions> => {
|
|
47
60
|
if (typeof def === 'boolean') {
|
|
48
61
|
opts = typeof opts === 'string' ? { parent: opts, default: def } : { default: def, ...(opts ?? {}) }
|
package/src/model.ts
CHANGED
|
@@ -1,24 +1,18 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { RouteDeclaration, RouteModel } from './types.js'
|
|
2
2
|
import type { CreateRouteSignature } from './utils/types.js'
|
|
3
|
-
import {
|
|
4
|
-
import { AppType, BasicConfig, BasicContext } from '@owlmeans/context'
|
|
3
|
+
import { AppType } from '@owlmeans/context'
|
|
5
4
|
|
|
6
|
-
export const makeRouteModel = (route:
|
|
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<
|
|
16
|
-
const
|
|
7
|
+
export const createRoute: CreateRouteSignature<RouteDeclaration> = (alias, path, opts?) => {
|
|
8
|
+
const options = typeof opts === 'string' ? { parent: opts } : opts
|
|
9
|
+
const { parent, ...rest } = options ?? {}
|
|
10
|
+
const route: RouteDeclaration = {
|
|
17
11
|
alias,
|
|
18
12
|
type: AppType.Backend,
|
|
19
13
|
path,
|
|
20
|
-
|
|
21
|
-
...(typeof
|
|
14
|
+
...rest,
|
|
15
|
+
...(parent == null ? {} : { parent: typeof parent === 'string' ? parent : parent.alias }),
|
|
22
16
|
}
|
|
23
17
|
|
|
24
18
|
return route
|
package/src/types.ts
CHANGED
|
@@ -1,7 +1,22 @@
|
|
|
1
|
-
import type { AppType,
|
|
1
|
+
import type { AppType, EntrypointReference } from '@owlmeans/context'
|
|
2
2
|
import type { RouteProtocols, RouteMethod } from './consts'
|
|
3
3
|
|
|
4
|
-
export interface
|
|
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
|
|
@@ -9,6 +24,18 @@ export interface CommonRoute extends BasicRoute {
|
|
|
9
24
|
method?: RouteMethod
|
|
10
25
|
protocol?: RouteProtocols
|
|
11
26
|
secure?: boolean
|
|
27
|
+
/**
|
|
28
|
+
* QUEUE routes only: the queue that carries this entrypoint's jobs. It names an address, not a
|
|
29
|
+
* process — which queues a given process consumes is configuration, never a declaration.
|
|
30
|
+
*/
|
|
31
|
+
queue?: string
|
|
32
|
+
/**
|
|
33
|
+
* QUEUE routes only: whether the caller waits for the job's return value. `false` resolves as
|
|
34
|
+
* soon as the job is accepted, which is what a long pipeline wants; the default is to wait.
|
|
35
|
+
*/
|
|
36
|
+
reply?: boolean
|
|
37
|
+
/** How long a caller waits for an answer, in milliseconds, when the transport supports it. */
|
|
38
|
+
timeout?: number
|
|
12
39
|
}
|
|
13
40
|
|
|
14
41
|
export interface CommonServiceRoute extends BasicRoute {
|
|
@@ -17,24 +44,30 @@ export interface CommonServiceRoute extends BasicRoute {
|
|
|
17
44
|
default?: boolean
|
|
18
45
|
}
|
|
19
46
|
|
|
20
|
-
export interface
|
|
21
|
-
|
|
22
|
-
service?: string
|
|
23
|
-
host?: string
|
|
24
|
-
port?: number
|
|
25
|
-
base?: string
|
|
26
|
-
resolved: boolean
|
|
47
|
+
export interface ResolvedServiceRoute extends CommonServiceRoute {
|
|
48
|
+
host: string
|
|
27
49
|
}
|
|
28
50
|
|
|
29
|
-
|
|
51
|
+
/** Where a route actually answers, once its service has been picked. */
|
|
52
|
+
export interface RouteAddress {
|
|
30
53
|
host: string
|
|
31
|
-
|
|
54
|
+
port?: number
|
|
55
|
+
base?: string
|
|
56
|
+
secure: boolean
|
|
57
|
+
protocol: RouteProtocols
|
|
32
58
|
}
|
|
33
59
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
60
|
+
/**
|
|
61
|
+
* The model wrapping a declaration. It carries no resolution state of its own — every address
|
|
62
|
+
* question is answered from the declaration plus the context that asks.
|
|
63
|
+
*/
|
|
64
|
+
export interface RouteModel {
|
|
65
|
+
route: RouteDeclaration
|
|
37
66
|
}
|
|
38
67
|
|
|
39
|
-
export
|
|
68
|
+
export type RouteParent = string | EntrypointReference
|
|
69
|
+
|
|
70
|
+
export interface RouteOptions extends Omit<Partial<RouteDeclaration>, 'parent'> {
|
|
71
|
+
/** A parent protocol is preferred in application declarations; strings remain adapter input. */
|
|
72
|
+
parent?: RouteParent
|
|
40
73
|
}
|