@owlmeans/client-entrypoint 0.1.18-rc.45 → 0.1.18-rc.47
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 +11 -10
- package/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/client-entrypoint/SKILL.md +1 -1
- package/build/consts.d.ts +2 -0
- package/build/consts.d.ts.map +1 -0
- package/build/consts.js +2 -0
- package/build/consts.js.map +1 -0
- package/build/entrypoint.d.ts.map +1 -1
- package/build/entrypoint.js +6 -5
- package/build/entrypoint.js.map +1 -1
- package/build/failure.d.ts +2 -16
- package/build/failure.d.ts.map +1 -1
- package/build/failure.js +1 -1
- package/build/failure.js.map +1 -1
- package/build/helper/types.d.ts +10 -0
- package/build/helper/types.d.ts.map +1 -0
- package/build/helper/types.js +2 -0
- package/build/helper/types.js.map +1 -0
- package/build/helper.d.ts +4 -4
- package/build/helper.d.ts.map +1 -1
- package/build/helper.js +22 -19
- package/build/helper.js.map +1 -1
- package/build/index.d.ts +4 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +3 -1
- package/build/index.js.map +1 -1
- package/build/stab.d.ts +4 -0
- package/build/stab.d.ts.map +1 -0
- package/build/stab.js +5 -0
- package/build/stab.js.map +1 -0
- package/build/types.d.ts +16 -2
- package/build/types.d.ts.map +1 -1
- package/build/utils/handler/types.d.ts +15 -0
- package/build/utils/handler/types.d.ts.map +1 -0
- package/build/utils/handler/types.js +2 -0
- package/build/utils/handler/types.js.map +1 -0
- package/build/utils/handler.d.ts +6 -4
- package/build/utils/handler.d.ts.map +1 -1
- package/build/utils/handler.js +120 -114
- package/build/utils/handler.js.map +1 -1
- package/build/utils/index.d.ts +1 -0
- package/build/utils/index.d.ts.map +1 -1
- package/build/utils/index.js.map +1 -1
- package/build/utils/types.local.d.ts +5 -0
- package/build/utils/types.local.d.ts.map +1 -0
- package/build/utils/types.local.js +2 -0
- package/build/utils/types.local.js.map +1 -0
- package/package.json +13 -13
- package/src/consts.ts +1 -0
- package/src/entrypoint.ts +6 -5
- package/src/failure.ts +3 -21
- package/src/helper/types.ts +10 -0
- package/src/helper.ts +28 -23
- package/src/index.ts +4 -1
- package/src/stab.ts +6 -0
- package/src/types.ts +18 -6
- package/src/utils/handler/types.ts +15 -0
- package/src/utils/handler.ts +81 -79
- package/src/utils/index.ts +1 -0
- package/src/utils/types.local.ts +5 -0
package/build/utils/handler.js
CHANGED
|
@@ -1,131 +1,137 @@
|
|
|
1
1
|
import { DEFAULT_KEY } from '@owlmeans/client-config';
|
|
2
2
|
import { EntrypointOutcome, provideResponse, transportAlias } from '@owlmeans/entrypoint';
|
|
3
3
|
import { validate } from './entrypoint.js';
|
|
4
|
-
import {
|
|
4
|
+
import { clientRouteHelper } from '@owlmeans/client-route';
|
|
5
5
|
import { PARAM, RouteMethod, RouteProtocols } from '@owlmeans/route';
|
|
6
6
|
import { stringify } from 'qs';
|
|
7
|
-
import { assertContext } from '@owlmeans/context';
|
|
7
|
+
import { assertContext, memoHelper } from '@owlmeans/context';
|
|
8
8
|
import { makeSecurityHelper } from '@owlmeans/config';
|
|
9
|
-
import { ENTRYPOINT_FAILURE_SERVICE } from '../
|
|
9
|
+
import { ENTRYPOINT_FAILURE_SERVICE } from '../consts.js';
|
|
10
10
|
import { logger } from '@owlmeans/log';
|
|
11
11
|
const log = logger('client-entrypoint');
|
|
12
|
-
export const
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
12
|
+
export const makeApiCallHelper = (ref) => {
|
|
13
|
+
const apiHandler = async (req, res) => {
|
|
14
|
+
const location = `client-entrypoint:api-handler:${ref.ref?.alias}`;
|
|
15
|
+
const context = assertContext(ref.ref?.ctx, location);
|
|
16
|
+
if (context.cfg.webService == null) {
|
|
17
|
+
throw new SyntaxError('No webService provided');
|
|
18
|
+
}
|
|
19
|
+
const ep = context.entrypoint(req.alias);
|
|
20
|
+
// A route names the protocol it answers on. Whatever is bound under that protocol takes the
|
|
21
|
+
// call, so a consumer writes `ep.call(...)` without learning which transport ran.
|
|
22
|
+
const transport = transportAlias(ep.route.route.protocol);
|
|
23
|
+
if (context.hasService(transport)) {
|
|
24
|
+
req.path = ep.path();
|
|
25
|
+
return context.service(transport).handle(req, res);
|
|
26
|
+
}
|
|
27
|
+
// Which web client carries this call is decided by the service the route answers on — the one it
|
|
28
|
+
// names, or the one the context picks for its app type when it names none.
|
|
29
|
+
const route = ep.service();
|
|
30
|
+
const alias = typeof context.cfg.webService === 'string'
|
|
31
|
+
? context.cfg.webService
|
|
32
|
+
: context.cfg.webService[route.service] ?? context.cfg.webService[DEFAULT_KEY];
|
|
33
|
+
if (alias == null) {
|
|
34
|
+
throw new SyntaxError(`Can't cast web service alias for ${ep.alias} entrypoint`);
|
|
35
|
+
}
|
|
36
|
+
const service = context.service(alias);
|
|
23
37
|
req.path = ep.path();
|
|
24
|
-
return
|
|
25
|
-
}
|
|
26
|
-
// Which web client carries this call is decided by the service the route answers on — the one it
|
|
27
|
-
// names, or the one the context picks for its app type when it names none.
|
|
28
|
-
const route = ep.service();
|
|
29
|
-
const alias = typeof context.cfg.webService === 'string'
|
|
30
|
-
? context.cfg.webService
|
|
31
|
-
: context.cfg.webService[route.service] ?? context.cfg.webService[DEFAULT_KEY];
|
|
32
|
-
if (alias == null) {
|
|
33
|
-
throw new SyntaxError(`Can't cast web service alias for ${ep.alias} entrypoint`);
|
|
34
|
-
}
|
|
35
|
-
const service = context.service(alias);
|
|
36
|
-
req.path = ep.path();
|
|
37
|
-
return service.handler(req, res);
|
|
38
|
-
};
|
|
39
|
-
export const apiInvoke = (ref, opts) => (async (req) => {
|
|
40
|
-
const ep = ref.ref;
|
|
41
|
-
if (ep == null) {
|
|
42
|
-
throw new SyntaxError('Try to make API call before the entrypoint is created');
|
|
43
|
-
}
|
|
44
|
-
const ctx = ep.ctx;
|
|
45
|
-
if (ctx == null) {
|
|
46
|
-
throw new SyntaxError(`No context provided in apiCall for ${ep.alias} entrypoint`);
|
|
47
|
-
}
|
|
48
|
-
if (req?.canceled) {
|
|
49
|
-
return { value: null, outcome: EntrypointOutcome.Ok };
|
|
50
|
-
}
|
|
51
|
-
const request = {
|
|
52
|
-
alias: ep.alias,
|
|
53
|
-
params: req?.params ?? {},
|
|
54
|
-
// JSON transports must send a body for mutation methods even when the contract has no
|
|
55
|
-
// payload. Keeping that rule here makes every typed caller use `call({ params })`, never
|
|
56
|
-
// an SDK-specific `{ body: {} }` workaround.
|
|
57
|
-
body: req?.body ?? ([RouteMethod.POST, RouteMethod.PUT, RouteMethod.PATCH]
|
|
58
|
-
.includes(ep.route.route.method ?? RouteMethod.GET) ? {} : undefined),
|
|
59
|
-
headers: req?.headers ?? {},
|
|
60
|
-
query: req?.query ?? {},
|
|
61
|
-
host: req?.host,
|
|
62
|
-
base: req?.base,
|
|
63
|
-
path: ep.path(),
|
|
64
|
-
timeout: req?.timeout,
|
|
65
|
-
signal: req?.signal,
|
|
38
|
+
return service.handler(req, res);
|
|
66
39
|
};
|
|
67
|
-
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
40
|
+
const apiInvoke = (opts) => (async (req) => {
|
|
41
|
+
const ep = ref.ref;
|
|
42
|
+
if (ep == null) {
|
|
43
|
+
throw new SyntaxError('Try to make API call before the entrypoint is created');
|
|
44
|
+
}
|
|
45
|
+
const ctx = ep.ctx;
|
|
46
|
+
if (ctx == null) {
|
|
47
|
+
throw new SyntaxError(`No context provided in apiCall for ${ep.alias} entrypoint`);
|
|
48
|
+
}
|
|
49
|
+
if (req?.canceled) {
|
|
50
|
+
return { value: null, outcome: EntrypointOutcome.Ok };
|
|
51
|
+
}
|
|
52
|
+
const request = {
|
|
53
|
+
alias: ep.alias,
|
|
54
|
+
params: req?.params ?? {},
|
|
55
|
+
// JSON transports must send a body for mutation methods even when the contract has no
|
|
56
|
+
// payload. Keeping that rule here makes every typed caller use `call({ params })`, never
|
|
57
|
+
// an SDK-specific `{ body: {} }` workaround.
|
|
58
|
+
body: req?.body ?? ([RouteMethod.POST, RouteMethod.PUT, RouteMethod.PATCH]
|
|
59
|
+
.includes(ep.route.route.method ?? RouteMethod.GET) ? {} : undefined),
|
|
60
|
+
headers: req?.headers ?? {},
|
|
61
|
+
query: req?.query ?? {},
|
|
62
|
+
host: req?.host,
|
|
63
|
+
base: req?.base,
|
|
64
|
+
path: ep.path(),
|
|
65
|
+
timeout: req?.timeout,
|
|
66
|
+
signal: req?.signal,
|
|
72
67
|
};
|
|
73
|
-
|
|
74
|
-
|
|
68
|
+
if (req?.cancel != null) {
|
|
69
|
+
const cancel = req.cancel;
|
|
70
|
+
req.cancel = () => {
|
|
71
|
+
cancel();
|
|
72
|
+
request.canceled = true;
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
if (opts?.validateOnCall) {
|
|
76
|
+
try {
|
|
77
|
+
await validate(ref)(request);
|
|
78
|
+
}
|
|
79
|
+
catch (e) {
|
|
80
|
+
log.error('Request validation failed', { alias: ep.alias, error: e });
|
|
81
|
+
throw e;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const reply = provideResponse();
|
|
85
|
+
if (ctx == null && ep.ctx == null) {
|
|
86
|
+
throw new SyntaxError(`Use entrypoint ${ep.alias} without context`);
|
|
87
|
+
}
|
|
75
88
|
try {
|
|
76
|
-
await
|
|
89
|
+
await apiHandler(request, reply);
|
|
90
|
+
if (reply.error != null)
|
|
91
|
+
throw reply.error;
|
|
77
92
|
}
|
|
78
|
-
catch (
|
|
79
|
-
|
|
80
|
-
|
|
93
|
+
catch (error) {
|
|
94
|
+
if (ctx.hasService(ENTRYPOINT_FAILURE_SERVICE)) {
|
|
95
|
+
await ctx.service(ENTRYPOINT_FAILURE_SERVICE)
|
|
96
|
+
.notify({ alias: ep.alias, request, error });
|
|
97
|
+
}
|
|
98
|
+
throw error;
|
|
81
99
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
await apiHandler(ref)(request, reply);
|
|
89
|
-
if (reply.error != null)
|
|
90
|
-
throw reply.error;
|
|
91
|
-
}
|
|
92
|
-
catch (error) {
|
|
93
|
-
if (ctx.hasService(ENTRYPOINT_FAILURE_SERVICE)) {
|
|
94
|
-
await ctx.service(ENTRYPOINT_FAILURE_SERVICE)
|
|
95
|
-
.notify({ alias: ep.alias, request, error });
|
|
100
|
+
return { value: reply.value ?? null, outcome: reply.outcome ?? EntrypointOutcome.Ok };
|
|
101
|
+
});
|
|
102
|
+
const entrypointUrl = async (req, opts) => {
|
|
103
|
+
const ep = ref.ref;
|
|
104
|
+
if (ep == null) {
|
|
105
|
+
throw new SyntaxError('Try to make URL before the entrypoint is created');
|
|
96
106
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
// name: a route that names no service belongs to the asking context, and addressing it absolutely
|
|
124
|
-
// would turn in-app navigation into a full page load.
|
|
125
|
-
if (socket || !ep.isLocal() || opts?.absolute === true) {
|
|
126
|
-
const helper = makeSecurityHelper(ctx);
|
|
127
|
-
path = helper.makeUrl(ep.address(), path, { host: req?.host, base: req?.base, forceUnsecure: req?.unsecure });
|
|
128
|
-
}
|
|
129
|
-
return path;
|
|
107
|
+
const ctx = ep.ctx;
|
|
108
|
+
if (ctx == null) {
|
|
109
|
+
throw new SyntaxError(`No context provided in entrypointUrl for ${ep.alias} entrypoint`);
|
|
110
|
+
}
|
|
111
|
+
// The base is left off here: an in-service URL is addressed relative to it, and the absolute
|
|
112
|
+
// branch below has `makeUrl` prepend it.
|
|
113
|
+
const epPath = ep.path();
|
|
114
|
+
const pathParams = clientRouteHelper.extractParams(epPath);
|
|
115
|
+
let path = pathParams.reduce((p, param) => {
|
|
116
|
+
return p.replace(`${PARAM}${param}`, `${req?.params?.[param]}`);
|
|
117
|
+
}, epPath) + (req?.query != null ? `?${stringify(req?.query)}` : '');
|
|
118
|
+
// A socket address is always absolute, whoever owns the route. `new WebSocket(path)` resolves a
|
|
119
|
+
// relative value against the PAGE's origin, which in a split deployment is the web host and not
|
|
120
|
+
// the service that answers the upgrade — so the handshake goes somewhere that never speaks it
|
|
121
|
+
// and dies on a gateway timeout. Only a same-origin HTTP route benefits from staying relative.
|
|
122
|
+
const socket = ep.route.route.protocol === RouteProtocols.SOCKET;
|
|
123
|
+
// Locality is a question about the RESOLVED service, not about what the declaration happens to
|
|
124
|
+
// name: a route that names no service belongs to the asking context, and addressing it absolutely
|
|
125
|
+
// would turn in-app navigation into a full page load.
|
|
126
|
+
if (socket || !ep.isLocal() || opts?.absolute === true) {
|
|
127
|
+
const helper = makeSecurityHelper(ctx);
|
|
128
|
+
path = helper.makeUrl(ep.address(), path, { host: req?.host, base: req?.base, forceUnsecure: req?.unsecure });
|
|
129
|
+
}
|
|
130
|
+
return path;
|
|
131
|
+
};
|
|
132
|
+
return { apiHandler, apiInvoke, entrypointUrl };
|
|
130
133
|
};
|
|
134
|
+
export const apiCallOf = memoHelper.oncePer(makeApiCallHelper);
|
|
135
|
+
/** @deprecated compat:factory-refactor — use `makeApiCallHelper(ref).entrypointUrl(…)` */
|
|
136
|
+
export const entrypointUrl = (ref, req, opts) => makeApiCallHelper(ref).entrypointUrl(req, opts);
|
|
131
137
|
//# sourceMappingURL=handler.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../src/utils/handler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;
|
|
1
|
+
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../src/utils/handler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AACrD,OAAO,EAA0E,iBAAiB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAEjK,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC1D,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,CAAA;AAC9B,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAA;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAItC,MAAM,GAAG,GAAG,MAAM,CAAC,mBAAmB,CAAC,CAAA;AAEvC,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,GAAwB,EACH,EAAE;IACvB,MAAM,UAAU,GAAsB,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;QACvD,MAAM,QAAQ,GAAG,iCAAiC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,CAAA;QAClE,MAAM,OAAO,GAAG,aAAa,CAAkB,GAAG,CAAC,GAAG,EAAE,GAAc,EAAE,QAAQ,CAAC,CAAA;QAEjF,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,IAAI,EAAE,CAAC;YACnC,MAAM,IAAI,WAAW,CAAC,wBAAwB,CAAC,CAAA;QACjD,CAAC;QAED,MAAM,EAAE,GAAG,OAAO,CAAC,UAAU,CAAmB,GAAG,CAAC,KAAK,CAAC,CAAA;QAE1D,4FAA4F;QAC5F,kFAAkF;QAClF,MAAM,SAAS,GAAG,cAAc,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;QACzD,IAAI,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAClC,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC,IAAI,EAAE,CAAA;YAEpB,OAAO,OAAO,CAAC,OAAO,CAAsB,SAAS,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;QACzE,CAAC;QAED,iGAAiG;QACjG,2EAA2E;QAC3E,MAAM,KAAK,GAAG,EAAE,CAAC,OAAO,EAAE,CAAA;QAE1B,MAAM,KAAK,GAAuB,OAAO,OAAO,CAAC,GAAG,CAAC,UAAU,KAAK,QAAQ;YAC1E,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU;YACxB,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC,CAAA;QAEhF,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;YAClB,MAAM,IAAI,WAAW,CAAC,oCAAoC,EAAE,CAAC,KAAK,aAAa,CAAC,CAAA;QAClF,CAAC;QAED,MAAM,OAAO,GAAc,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;QAEjD,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC,IAAI,EAAE,CAAA;QAEpB,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,GAAU,CAAC,CAAA;IACzC,CAAC,CAAA;IAED,MAAM,SAAS,GAAG,CAAC,IAA8B,EAA0B,EAAE,CAAC,CAAC,KAAK,EAAE,GAA2B,EAAE,EAAE;QACnH,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAA;QAClB,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC;YACf,MAAM,IAAI,WAAW,CAAC,uDAAuD,CAAC,CAAA;QAChF,CAAC;QACD,MAAM,GAAG,GAAG,EAAE,CAAC,GAAG,CAAA;QAClB,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;YAChB,MAAM,IAAI,WAAW,CAAC,sCAAsC,EAAE,CAAC,KAAK,aAAa,CAAC,CAAA;QACpF,CAAC;QAED,IAAI,GAAG,EAAE,QAAQ,EAAE,CAAC;YAClB,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,iBAAiB,CAAC,EAAE,EAAE,CAAA;QACvD,CAAC;QAED,MAAM,OAAO,GAAoB;YAC/B,KAAK,EAAE,EAAE,CAAC,KAAK;YACf,MAAM,EAAE,GAAG,EAAE,MAAM,IAAI,EAAE;YACzB,sFAAsF;YACtF,0FAA0F;YAC1F,6CAA6C;YAC7C,IAAI,EAAE,GAAG,EAAE,IAAI,IAAI,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,WAAW,CAAC,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC;iBACvE,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,IAAI,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;YACvE,OAAO,EAAE,GAAG,EAAE,OAAO,IAAI,EAAE;YAC3B,KAAK,EAAE,GAAG,EAAE,KAAK,IAAI,EAAE;YACvB,IAAI,EAAE,GAAG,EAAE,IAAI;YACf,IAAI,EAAE,GAAG,EAAE,IAAI;YACf,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE;YACf,OAAO,EAAE,GAAG,EAAE,OAAO;YACrB,MAAM,EAAE,GAAG,EAAE,MAAM;SACpB,CAAA;QACD,IAAI,GAAG,EAAE,MAAM,IAAI,IAAI,EAAE,CAAC;YACxB,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAA;YACzB,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE;gBAChB,MAAM,EAAE,CAAA;gBACR,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAA;YACzB,CAAC,CAAA;QACH,CAAC;QACD,IAAI,IAAI,EAAE,cAAc,EAAE,CAAC;YACzB,IAAI,CAAC;gBACH,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAA;YAC9B,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,GAAG,CAAC,KAAK,CAAC,2BAA2B,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAA;gBACrE,MAAM,CAAC,CAAA;YACT,CAAC;QACH,CAAC;QACD,MAAM,KAAK,GAAG,eAAe,EAAW,CAAA;QACxC,IAAI,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC;YAClC,MAAM,IAAI,WAAW,CAAC,kBAAkB,EAAE,CAAC,KAAK,kBAAkB,CAAC,CAAA;QACrE,CAAC;QACD,IAAI,CAAC;YACH,MAAM,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;YAChC,IAAI,KAAK,CAAC,KAAK,IAAI,IAAI;gBAAE,MAAM,KAAK,CAAC,KAAK,CAAA;QAC5C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,GAAG,CAAC,UAAU,CAAC,0BAA0B,CAAC,EAAE,CAAC;gBAC/C,MAAM,GAAG,CAAC,OAAO,CAA2B,0BAA0B,CAAC;qBACpE,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAA;YAChD,CAAC;YACD,MAAM,KAAK,CAAA;QACb,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,iBAAiB,CAAC,EAAE,EAAE,CAAA;IACvF,CAAC,CAA0B,CAAA;IAE3B,MAAM,aAAa,GAAG,KAAK,EAAE,GAAgB,EAAE,IAA2B,EAAmB,EAAE;QAC7F,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAA;QAClB,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC;YACf,MAAM,IAAI,WAAW,CAAC,kDAAkD,CAAC,CAAA;QAC3E,CAAC;QACD,MAAM,GAAG,GAAG,EAAE,CAAC,GAAG,CAAA;QAClB,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;YAChB,MAAM,IAAI,WAAW,CAAC,4CAA4C,EAAE,CAAC,KAAK,aAAa,CAAC,CAAA;QAC1F,CAAC;QAED,6FAA6F;QAC7F,yCAAyC;QACzC,MAAM,MAAM,GAAG,EAAE,CAAC,IAAI,EAAE,CAAA;QACxB,MAAM,UAAU,GAAG,iBAAiB,CAAC,aAAa,CAAC,MAAM,CAAC,CAAA;QAC1D,IAAI,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE;YACxC,OAAO,CAAC,CAAC,OAAO,CAAC,GAAG,KAAK,GAAG,KAAK,EAAE,EAAE,GAAG,GAAG,EAAE,MAAM,EAAE,CAAC,KAAgC,CAAC,EAAE,CAAC,CAAA;QAC5F,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;QAEpE,gGAAgG;QAChG,gGAAgG;QAChG,8FAA8F;QAC9F,+FAA+F;QAC/F,MAAM,MAAM,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,KAAK,cAAc,CAAC,MAAM,CAAA;QAEhE,+FAA+F;QAC/F,kGAAkG;QAClG,sDAAsD;QACtD,IAAI,MAAM,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,IAAI,EAAE,QAAQ,KAAK,IAAI,EAAE,CAAC;YACvD,MAAM,MAAM,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAA;YACtC,IAAI,GAAG,MAAM,CAAC,OAAO,CACnB,EAAE,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,QAAQ,EAAE,CACvF,CAAA;QACH,CAAC;QAED,OAAO,IAAI,CAAA;IACb,CAAC,CAAA;IAED,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,CAAA;AACjD,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAA;AAE9D,0FAA0F;AAC1F,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,GAAwB,EAAE,GAAgB,EAAE,IAA2B,EACtD,EAAE,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA"}
|
package/build/utils/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AACA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AACA,mBAAmB,oBAAoB,CAAA;AACvC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA"}
|
package/build/utils/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAEA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.local.d.ts","sourceRoot":"","sources":["../../src/utils/types.local.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAE3E,MAAM,MAAM,MAAM,GAAG,YAAY,CAAA;AAEjC,MAAM,WAAW,OAAO,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,CAAE,SAAQ,aAAa,CAAC,CAAC,CAAC;CAAI"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.local.js","sourceRoot":"","sources":["../../src/utils/types.local.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@owlmeans/client-entrypoint",
|
|
3
|
-
"version": "0.1.18-rc.
|
|
3
|
+
"version": "0.1.18-rc.47",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -28,25 +28,25 @@
|
|
|
28
28
|
}
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@owlmeans/api": "^0.1.18-rc.
|
|
32
|
-
"@owlmeans/client-config": "^0.1.18-rc.
|
|
33
|
-
"@owlmeans/client-context": "^0.1.18-rc.
|
|
34
|
-
"@owlmeans/client-route": "^0.1.18-rc.
|
|
35
|
-
"@owlmeans/config": "^0.1.18-rc.
|
|
36
|
-
"@owlmeans/context": "^0.1.18-rc.
|
|
37
|
-
"@owlmeans/entrypoint": "^0.1.18-rc.
|
|
38
|
-
"@owlmeans/error": "^0.1.18-rc.
|
|
39
|
-
"@owlmeans/log": "^0.1.18-rc.
|
|
40
|
-
"@owlmeans/route": "^0.1.18-rc.
|
|
31
|
+
"@owlmeans/api": "^0.1.18-rc.47",
|
|
32
|
+
"@owlmeans/client-config": "^0.1.18-rc.44",
|
|
33
|
+
"@owlmeans/client-context": "^0.1.18-rc.48",
|
|
34
|
+
"@owlmeans/client-route": "^0.1.18-rc.48",
|
|
35
|
+
"@owlmeans/config": "^0.1.18-rc.44",
|
|
36
|
+
"@owlmeans/context": "^0.1.18-rc.34",
|
|
37
|
+
"@owlmeans/entrypoint": "^0.1.18-rc.41",
|
|
38
|
+
"@owlmeans/error": "^0.1.18-rc.38",
|
|
39
|
+
"@owlmeans/log": "^0.1.18-rc.2",
|
|
40
|
+
"@owlmeans/route": "^0.1.18-rc.35",
|
|
41
41
|
"ajv-formats": "^3.0.1",
|
|
42
|
-
"qs": "^6.
|
|
42
|
+
"qs": "^6.16.0"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
45
|
"ajv": "*"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@owlmeans/dep-config": "workspace:*",
|
|
49
|
-
"@types/qs": "^6.
|
|
49
|
+
"@types/qs": "^6.15.1",
|
|
50
50
|
"nodemon": "^3.1.14",
|
|
51
51
|
"typescript": "^7.0.2"
|
|
52
52
|
},
|
package/src/consts.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const ENTRYPOINT_FAILURE_SERVICE = 'client-entrypoint:failure'
|
package/src/entrypoint.ts
CHANGED
|
@@ -2,9 +2,9 @@ import type { ClientEntrypoint, ClientEntrypointOptions, EntrypointRef, RefedEnt
|
|
|
2
2
|
import type { AbstractRequest, CommonEntrypoint } from '@owlmeans/entrypoint'
|
|
3
3
|
import { validate } from './utils/entrypoint.js'
|
|
4
4
|
import { route } from '@owlmeans/client-route'
|
|
5
|
-
import {
|
|
5
|
+
import { apiCallOf } from './utils/handler.js'
|
|
6
6
|
import { AppType } from '@owlmeans/context'
|
|
7
|
-
import {
|
|
7
|
+
import { clientRequestHelper } from './helper.js'
|
|
8
8
|
|
|
9
9
|
/** Attach client behaviour to an entrypoint already materialized from a protocol. */
|
|
10
10
|
export const bindMaterializedEntrypoint = <T, R extends AbstractRequest = AbstractRequest>(
|
|
@@ -16,6 +16,7 @@ export const bindMaterializedEntrypoint = <T, R extends AbstractRequest = Abstra
|
|
|
16
16
|
|
|
17
17
|
let _entrypoint: ClientEntrypoint<T, R>
|
|
18
18
|
|
|
19
|
+
const apiHandler: RefedEntrypointHandler<T, R> = ref => apiCallOf(ref).apiHandler
|
|
19
20
|
const _handler = handler ?? (arg.route.route.type === AppType.Backend ? apiHandler : undefined)
|
|
20
21
|
|
|
21
22
|
assertExplicitHandler(arg.route.route.type, handler)
|
|
@@ -29,7 +30,7 @@ export const bindMaterializedEntrypoint = <T, R extends AbstractRequest = Abstra
|
|
|
29
30
|
_entrypoint.gateParams = opts?.gateParams ?? arg.gateParams
|
|
30
31
|
|
|
31
32
|
_entrypoint.url = ((req?: Partial<R>, urlOpts?: { absolute?: boolean }) =>
|
|
32
|
-
entrypointUrl
|
|
33
|
+
apiCallOf(entrypointHandle).entrypointUrl(req as never, urlOpts)) as ClientEntrypoint<T, R>['url']
|
|
33
34
|
|
|
34
35
|
// An entrypoint carrying a renderer IS a screen: it is addressed by URL, never called over the
|
|
35
36
|
// wire. Saying so here turns what used to be a URL-shaped answer from `call()` into a report.
|
|
@@ -39,7 +40,7 @@ export const bindMaterializedEntrypoint = <T, R extends AbstractRequest = Abstra
|
|
|
39
40
|
`Entrypoint ${_entrypoint.alias} renders a screen - address it with url() instead of call()/invoke()`
|
|
40
41
|
)
|
|
41
42
|
})
|
|
42
|
-
: apiInvoke
|
|
43
|
+
: apiCallOf(entrypointHandle).apiInvoke(opts)) as ClientEntrypoint<T, R>['invoke']
|
|
43
44
|
|
|
44
45
|
_entrypoint.call = (async (req?: Partial<R>) =>
|
|
45
46
|
(await _entrypoint.invoke(req)).value) as ClientEntrypoint<T, R>['call']
|
|
@@ -48,7 +49,7 @@ export const bindMaterializedEntrypoint = <T, R extends AbstractRequest = Abstra
|
|
|
48
49
|
if (entrypointHandle.ref == null) {
|
|
49
50
|
throw SyntaxError(`Try to request uninitialized entrypoint ${JSON.stringify(arg)}`)
|
|
50
51
|
}
|
|
51
|
-
const _request = provideRequest(entrypointHandle.ref.alias, entrypointHandle.ref.path()) as R
|
|
52
|
+
const _request = clientRequestHelper.provideRequest(entrypointHandle.ref.alias, entrypointHandle.ref.path()) as R
|
|
52
53
|
|
|
53
54
|
request != null && Object.entries(request).forEach(([key, value]) => {
|
|
54
55
|
_request[key as keyof R] = value
|
package/src/failure.ts
CHANGED
|
@@ -1,28 +1,10 @@
|
|
|
1
|
-
import { createLazyService } from '@owlmeans/context'
|
|
2
|
-
import type { BasicContext, LazyService } from '@owlmeans/context'
|
|
3
|
-
import type { AbstractRequest } from '@owlmeans/entrypoint'
|
|
1
|
+
import { createLazyService, type BasicContext } from '@owlmeans/context'
|
|
4
2
|
import { logger } from '@owlmeans/log'
|
|
3
|
+
import { ENTRYPOINT_FAILURE_SERVICE } from './consts.js'
|
|
4
|
+
import type { EntrypointFailurePlugin, EntrypointFailureService } from './types.js'
|
|
5
5
|
|
|
6
6
|
const log = logger('client-entrypoint')
|
|
7
7
|
|
|
8
|
-
export const ENTRYPOINT_FAILURE_SERVICE = 'client-entrypoint:failure'
|
|
9
|
-
|
|
10
|
-
export interface EntrypointFailure {
|
|
11
|
-
alias: string
|
|
12
|
-
request: AbstractRequest
|
|
13
|
-
error: unknown
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface EntrypointFailurePlugin {
|
|
17
|
-
alias: string
|
|
18
|
-
onFailure: (failure: EntrypointFailure) => void | Promise<void>
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export interface EntrypointFailureService extends LazyService {
|
|
22
|
-
registerPlugin: (plugin: EntrypointFailurePlugin) => void
|
|
23
|
-
notify: (failure: EntrypointFailure) => Promise<void>
|
|
24
|
-
}
|
|
25
|
-
|
|
26
8
|
/** Context-local observers for rejected client calls; observers never replace the thrown error. */
|
|
27
9
|
export const ensureEntrypointFailureService = (ctx: BasicContext<any>): EntrypointFailureService => {
|
|
28
10
|
if (ctx.hasService(ENTRYPOINT_FAILURE_SERVICE)) {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AbstractRequest } from '@owlmeans/entrypoint'
|
|
2
|
+
import type { JSONSchemaType } from 'ajv'
|
|
3
|
+
|
|
4
|
+
/** Builds and shapes the requests a client sends. */
|
|
5
|
+
export interface ClientRequestHelper {
|
|
6
|
+
/** A minimal cancellable `AbstractRequest` for an entrypoint alias at a path. */
|
|
7
|
+
provideRequest: <T extends {} = {}>(alias: string, path: string) => AbstractRequest<T>
|
|
8
|
+
/** Keeps only the non-null keys of `object` the AJV schema declares. */
|
|
9
|
+
pickPerSchema: <T, R>(object: T, schema: JSONSchemaType<R>) => Partial<R>
|
|
10
|
+
}
|
package/src/helper.ts
CHANGED
|
@@ -1,31 +1,36 @@
|
|
|
1
|
-
import type { RefedEntrypointHandler } from './types.js'
|
|
2
1
|
import type { AbstractRequest } from '@owlmeans/entrypoint'
|
|
3
2
|
import type { JSONSchemaType } from "ajv"
|
|
3
|
+
import type { ClientRequestHelper } from './helper/types.js'
|
|
4
4
|
|
|
5
|
-
export const
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
export const createClientRequestHelper = (): ClientRequestHelper => {
|
|
6
|
+
const provideRequest = <T extends {} = {}>(alias: string, path: string): AbstractRequest<T> => {
|
|
7
|
+
const request = {
|
|
8
|
+
alias,
|
|
9
|
+
params: {},
|
|
10
|
+
headers: {},
|
|
11
|
+
query: {},
|
|
12
|
+
path,
|
|
13
|
+
canceled: false,
|
|
14
|
+
cancel: () => request.canceled = true
|
|
15
|
+
}
|
|
8
16
|
|
|
9
|
-
|
|
10
|
-
const request = {
|
|
11
|
-
alias,
|
|
12
|
-
params: {},
|
|
13
|
-
headers: {},
|
|
14
|
-
query: {},
|
|
15
|
-
path,
|
|
16
|
-
canceled: false,
|
|
17
|
-
cancel: () => request.canceled = true
|
|
17
|
+
return request
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
const pickPerSchema = <T, R>(object: T, schema: JSONSchemaType<R>): Partial<R> =>
|
|
21
|
+
Object.keys(schema.properties).reduce(
|
|
22
|
+
(acc, key) => {
|
|
23
|
+
if (object[key as keyof T] != null) {
|
|
24
|
+
acc[key as keyof R] = object[key as keyof T] as unknown as R[keyof R]
|
|
25
|
+
}
|
|
26
|
+
return acc
|
|
27
|
+
}, {} as Partial<R>
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
return { provideRequest, pickPerSchema }
|
|
21
31
|
}
|
|
22
32
|
|
|
23
|
-
export const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
acc[key as keyof R] = object[key as keyof T] as unknown as R[keyof R]
|
|
28
|
-
}
|
|
29
|
-
return acc
|
|
30
|
-
}, {} as Partial<R>
|
|
31
|
-
)
|
|
33
|
+
export const clientRequestHelper = createClientRequestHelper()
|
|
34
|
+
|
|
35
|
+
/** @deprecated compat:factory-refactor — use `clientRequestHelper.provideRequest(…)` */
|
|
36
|
+
export const provideRequest = <T extends {} = {}>(alias: string, path: string): AbstractRequest<T> => clientRequestHelper.provideRequest<T>(alias, path)
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
|
|
2
2
|
export type * from './types.js'
|
|
3
|
+
export type * from './helper/types.js'
|
|
3
4
|
export * from './errors.js'
|
|
4
5
|
export * from './failure.js'
|
|
6
|
+
export * from './consts.js'
|
|
5
7
|
export * from './protocol.js'
|
|
6
|
-
export {
|
|
8
|
+
export { clientRequestHelper, createClientRequestHelper, provideRequest } from './helper.js'
|
|
9
|
+
export { stab } from './stab.js'
|
package/src/stab.ts
ADDED
package/src/types.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
AbstractRequest, CommonEntrypoint, CommonEntrypointOptions, EntrypointHandler,
|
|
4
4
|
EntrypointOutcome, EntrypointProtocolDeclaration, RegisteredEntrypoint, RequestOf,
|
|
5
5
|
} from '@owlmeans/entrypoint'
|
|
6
|
+
import type { LazyService } from '@owlmeans/context'
|
|
6
7
|
|
|
7
8
|
export interface ClientEntrypoint<T = {}, R extends ClientRequest = ClientRequest> extends CommonEntrypoint {
|
|
8
9
|
route: ClientRouteModel
|
|
@@ -30,12 +31,7 @@ export interface ClientEntrypoint<T = {}, R extends ClientRequest = ClientReques
|
|
|
30
31
|
* its request and reply types are read directly from the declaration and cannot be replaced at a
|
|
31
32
|
* call site.
|
|
32
33
|
*/
|
|
33
|
-
export
|
|
34
|
-
Omit<ClientEntrypoint, 'call' | 'invoke' | 'url' | 'validate' | 'request'>
|
|
35
|
-
& RegisteredEntrypoint<RequestOf<Protocol>, import('@owlmeans/entrypoint').ResponseOf<Protocol>>
|
|
36
|
-
& {
|
|
37
|
-
readonly protocol: Protocol
|
|
38
|
-
}
|
|
34
|
+
export interface ClientProtocolEntrypoint<Protocol extends EntrypointProtocolDeclaration> extends Omit<ClientEntrypoint, 'call' | 'invoke' | 'url' | 'validate' | 'request'>, RegisteredEntrypoint<RequestOf<Protocol>, import('@owlmeans/entrypoint').ResponseOf<Protocol>> { readonly protocol: Protocol }
|
|
39
35
|
|
|
40
36
|
export interface EntrypointCall<T, Req extends ClientRequest = ClientRequest> {
|
|
41
37
|
<Type extends T, R extends Req = Req>(req?: Partial<R>): Promise<Type>
|
|
@@ -78,3 +74,19 @@ export interface EntrypointRef<T, R extends AbstractRequest = AbstractRequest> {
|
|
|
78
74
|
export interface RefedEntrypointHandler<T = {}, R extends AbstractRequest = AbstractRequest> {
|
|
79
75
|
(ref: EntrypointRef<T, R>): EntrypointHandler
|
|
80
76
|
}
|
|
77
|
+
|
|
78
|
+
export interface EntrypointFailure {
|
|
79
|
+
alias: string
|
|
80
|
+
request: AbstractRequest
|
|
81
|
+
error: unknown
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface EntrypointFailurePlugin {
|
|
85
|
+
alias: string
|
|
86
|
+
onFailure: (failure: EntrypointFailure) => void | Promise<void>
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export interface EntrypointFailureService extends LazyService {
|
|
90
|
+
registerPlugin: (plugin: EntrypointFailurePlugin) => void
|
|
91
|
+
notify: (failure: EntrypointFailure) => Promise<void>
|
|
92
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { AbstractRequest, EntrypointHandler } from '@owlmeans/entrypoint'
|
|
2
|
+
import type { ClientEntrypointOptions, EntrypointInvoke, EntrypointUrlOptions } from '../../types.js'
|
|
3
|
+
|
|
4
|
+
/** How a client entrypoint reaches its backend: the handler, the round trip and the address. */
|
|
5
|
+
export interface ApiCallHelper<T, R extends AbstractRequest = AbstractRequest> {
|
|
6
|
+
/**
|
|
7
|
+
* The handler that carries the entrypoint's call: the transport service bound to its route's
|
|
8
|
+
* protocol, else the API client of the web service its route answers on.
|
|
9
|
+
*/
|
|
10
|
+
apiHandler: EntrypointHandler
|
|
11
|
+
/** The round trip behind `invoke()`: builds the request, validates it on demand and notifies failure observers. */
|
|
12
|
+
apiInvoke: (opts?: ClientEntrypointOptions) => EntrypointInvoke<T, R>
|
|
13
|
+
/** The address behind `url()`: `:params` filled in, the query appended, absolute when the route is not local. */
|
|
14
|
+
entrypointUrl: (req?: Partial<R>, opts?: EntrypointUrlOptions) => Promise<string>
|
|
15
|
+
}
|