@astrale-os/kernel-server 0.5.0-beta.1 → 0.5.0-beta.11
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/dist/capture.d.ts +0 -1
- package/dist/capture.js +0 -1
- package/dist/cors/cors.d.ts +0 -1
- package/dist/cors/cors.js +0 -1
- package/dist/cors/index.d.ts +0 -1
- package/dist/cors/index.js +0 -1
- package/dist/cors/types.d.ts +0 -1
- package/dist/cors/types.js +0 -1
- package/dist/errors/availability.d.ts +3 -4
- package/dist/errors/availability.js +4 -5
- package/dist/errors/classify.d.ts +2 -3
- package/dist/errors/classify.js +4 -217
- package/dist/errors/index.d.ts +1 -2
- package/dist/errors/index.js +1 -2
- package/dist/errors/request-body.d.ts +0 -1
- package/dist/errors/request-body.js +0 -1
- package/dist/errors/response-body.d.ts +0 -1
- package/dist/errors/response-body.js +0 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/invocation/context.d.ts +2 -3
- package/dist/invocation/context.js +2 -4
- package/dist/invocation/identity.d.ts +9 -0
- package/dist/invocation/identity.js +11 -0
- package/dist/invocation/index.d.ts +3 -2
- package/dist/invocation/index.js +2 -1
- package/dist/invocation/publication-route.d.ts +13 -0
- package/dist/invocation/publication-route.js +44 -0
- package/dist/invocation/types.d.ts +38 -10
- package/dist/invocation/types.js +0 -1
- package/dist/issuer/exchange.d.ts +12 -0
- package/dist/issuer/exchange.js +136 -0
- package/dist/issuer/index.d.ts +1 -1
- package/dist/issuer/index.js +0 -1
- package/dist/issuer/routes.d.ts +3 -3
- package/dist/issuer/routes.js +25 -14
- package/dist/issuer/types.d.ts +2 -2
- package/dist/issuer/types.js +0 -1
- package/dist/lifecycle/active.d.ts +0 -1
- package/dist/lifecycle/active.js +0 -1
- package/dist/lifecycle/index.d.ts +0 -1
- package/dist/lifecycle/index.js +0 -1
- package/dist/publication/delivery/handler.d.ts +9 -0
- package/dist/{installation → publication/delivery}/handler.js +29 -28
- package/dist/publication/delivery/index.d.ts +2 -0
- package/dist/publication/delivery/index.js +1 -0
- package/dist/publication/delivery/types.d.ts +11 -0
- package/dist/publication/delivery/types.js +1 -0
- package/dist/publication/index.d.ts +1 -1
- package/dist/publication/index.js +1 -1
- package/dist/publication/snapshot.d.ts +5 -3
- package/dist/publication/snapshot.js +14 -7
- package/dist/publication/table.d.ts +4 -0
- package/dist/publication/table.js +16 -0
- package/dist/publication/types.d.ts +5 -2
- package/dist/publication/types.js +0 -1
- package/dist/routes/index.d.ts +0 -1
- package/dist/routes/index.js +0 -1
- package/dist/routes/routes.d.ts +6 -5
- package/dist/routes/routes.js +51 -41
- package/dist/server.d.ts +0 -1
- package/dist/server.js +56 -16
- package/dist/transport/body.d.ts +0 -1
- package/dist/transport/body.js +0 -1
- package/dist/transport/codecs.d.ts +1 -2
- package/dist/transport/codecs.js +1 -2
- package/dist/transport/credential.d.ts +1 -2
- package/dist/transport/credential.js +1 -2
- package/dist/transport/http/handler.d.ts +2 -1
- package/dist/transport/http/handler.js +47 -37
- package/dist/transport/http/index.d.ts +0 -1
- package/dist/transport/http/index.js +0 -1
- package/dist/transport/http/render.d.ts +13 -11
- package/dist/transport/http/render.js +50 -39
- package/dist/transport/index.d.ts +0 -1
- package/dist/transport/index.js +0 -1
- package/dist/transport/router.d.ts +0 -1
- package/dist/transport/router.js +0 -1
- package/dist/transport/stream-error.d.ts +2 -3
- package/dist/transport/stream-error.js +3 -4
- package/dist/transport/types.d.ts +1 -2
- package/dist/transport/types.js +0 -1
- package/dist/transport/websocket/index.d.ts +0 -1
- package/dist/transport/websocket/index.js +0 -1
- package/dist/transport/websocket/session.d.ts +4 -3
- package/dist/transport/websocket/session.js +46 -39
- package/dist/transport/websocket/upgrade.d.ts +2 -1
- package/dist/transport/websocket/upgrade.js +2 -2
- package/dist/types.d.ts +13 -10
- package/dist/types.js +0 -1
- package/package.json +23 -11
- package/dist/capture.d.ts.map +0 -1
- package/dist/capture.js.map +0 -1
- package/dist/cors/cors.d.ts.map +0 -1
- package/dist/cors/cors.js.map +0 -1
- package/dist/cors/index.d.ts.map +0 -1
- package/dist/cors/index.js.map +0 -1
- package/dist/cors/types.d.ts.map +0 -1
- package/dist/cors/types.js.map +0 -1
- package/dist/errors/availability.d.ts.map +0 -1
- package/dist/errors/availability.js.map +0 -1
- package/dist/errors/classify.d.ts.map +0 -1
- package/dist/errors/classify.js.map +0 -1
- package/dist/errors/index.d.ts.map +0 -1
- package/dist/errors/index.js.map +0 -1
- package/dist/errors/request-body.d.ts.map +0 -1
- package/dist/errors/request-body.js.map +0 -1
- package/dist/errors/response-body.d.ts.map +0 -1
- package/dist/errors/response-body.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/installation/handler.d.ts +0 -10
- package/dist/installation/handler.d.ts.map +0 -1
- package/dist/installation/handler.js.map +0 -1
- package/dist/installation/index.d.ts +0 -3
- package/dist/installation/index.d.ts.map +0 -1
- package/dist/installation/index.js +0 -2
- package/dist/installation/index.js.map +0 -1
- package/dist/installation/types.d.ts +0 -12
- package/dist/installation/types.d.ts.map +0 -1
- package/dist/installation/types.js +0 -2
- package/dist/installation/types.js.map +0 -1
- package/dist/invocation/context.d.ts.map +0 -1
- package/dist/invocation/context.js.map +0 -1
- package/dist/invocation/index.d.ts.map +0 -1
- package/dist/invocation/index.js.map +0 -1
- package/dist/invocation/types.d.ts.map +0 -1
- package/dist/invocation/types.js.map +0 -1
- package/dist/issuer/index.d.ts.map +0 -1
- package/dist/issuer/index.js.map +0 -1
- package/dist/issuer/routes.d.ts.map +0 -1
- package/dist/issuer/routes.js.map +0 -1
- package/dist/issuer/types.d.ts.map +0 -1
- package/dist/issuer/types.js.map +0 -1
- package/dist/lifecycle/active.d.ts.map +0 -1
- package/dist/lifecycle/active.js.map +0 -1
- package/dist/lifecycle/index.d.ts.map +0 -1
- package/dist/lifecycle/index.js.map +0 -1
- package/dist/publication/index.d.ts.map +0 -1
- package/dist/publication/index.js.map +0 -1
- package/dist/publication/snapshot.d.ts.map +0 -1
- package/dist/publication/snapshot.js.map +0 -1
- package/dist/publication/types.d.ts.map +0 -1
- package/dist/publication/types.js.map +0 -1
- package/dist/routes/index.d.ts.map +0 -1
- package/dist/routes/index.js.map +0 -1
- package/dist/routes/routes.d.ts.map +0 -1
- package/dist/routes/routes.js.map +0 -1
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js.map +0 -1
- package/dist/transport/body.d.ts.map +0 -1
- package/dist/transport/body.js.map +0 -1
- package/dist/transport/codecs.d.ts.map +0 -1
- package/dist/transport/codecs.js.map +0 -1
- package/dist/transport/credential.d.ts.map +0 -1
- package/dist/transport/credential.js.map +0 -1
- package/dist/transport/http/handler.d.ts.map +0 -1
- package/dist/transport/http/handler.js.map +0 -1
- package/dist/transport/http/index.d.ts.map +0 -1
- package/dist/transport/http/index.js.map +0 -1
- package/dist/transport/http/render.d.ts.map +0 -1
- package/dist/transport/http/render.js.map +0 -1
- package/dist/transport/index.d.ts.map +0 -1
- package/dist/transport/index.js.map +0 -1
- package/dist/transport/router.d.ts.map +0 -1
- package/dist/transport/router.js.map +0 -1
- package/dist/transport/stream-error.d.ts.map +0 -1
- package/dist/transport/stream-error.js.map +0 -1
- package/dist/transport/types.d.ts.map +0 -1
- package/dist/transport/types.js.map +0 -1
- package/dist/transport/websocket/index.d.ts.map +0 -1
- package/dist/transport/websocket/index.js.map +0 -1
- package/dist/transport/websocket/session.d.ts.map +0 -1
- package/dist/transport/websocket/session.js.map +0 -1
- package/dist/transport/websocket/upgrade.d.ts.map +0 -1
- package/dist/transport/websocket/upgrade.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
package/dist/routes/routes.js
CHANGED
|
@@ -1,28 +1,43 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as codecs from '@astrale-os/kernel-protocol/codecs';
|
|
2
|
+
import * as errors from '@astrale-os/kernel-protocol/errors';
|
|
3
|
+
import * as protocol from '@astrale-os/kernel-protocol/invocation';
|
|
4
|
+
import { PATH as PUBLICATION_PATH, url as publicationUrl, } from '@astrale-os/kernel-protocol/publication/publication';
|
|
5
|
+
import { reference as publicationReference } from '@astrale-os/kernel-protocol/publication/reference';
|
|
6
|
+
import * as routes from '@astrale-os/kernel-protocol/routes';
|
|
2
7
|
import { classifyError, RequestBodyInvalidError, RequestBodyTooLargeError, } from '../errors/index.js';
|
|
3
|
-
import { handleInstallation } from '../installation/index.js';
|
|
4
8
|
import { invocationContext } from '../invocation/index.js';
|
|
9
|
+
import { handleDelivery } from '../publication/delivery/index.js';
|
|
5
10
|
import { readPreparedPublicationSnapshot, } from '../publication/index.js';
|
|
6
|
-
import {
|
|
7
|
-
|
|
11
|
+
import { readBoundedBody } from '../transport/body.js';
|
|
12
|
+
import {} from '../transport/router.js';
|
|
13
|
+
import { interruptedStreamError } from '../transport/stream-error.js';
|
|
14
|
+
export function mountRoutes(app, source, deliveryProvider, handler, active, nextInvocation, limits, cors, hostFor, reservations, externalIssuer) {
|
|
15
|
+
const publicationPath = externalIssuer === undefined
|
|
16
|
+
? PUBLICATION_PATH
|
|
17
|
+
: new URL(publicationUrl(externalIssuer)).pathname;
|
|
18
|
+
const externalOrigin = externalIssuer === undefined ? undefined : new URL(externalIssuer).origin;
|
|
8
19
|
if (cors.enabled) {
|
|
9
|
-
app.options(
|
|
20
|
+
app.options(publicationPath, (context) => cors.preflight(context.req.raw, {
|
|
10
21
|
methods: ['GET'],
|
|
11
22
|
headers: ['if-none-match'],
|
|
12
23
|
}));
|
|
13
24
|
}
|
|
14
|
-
app.get(
|
|
25
|
+
app.get(publicationPath, (context) => {
|
|
15
26
|
const responseCors = cors.response(context.req.raw, ['etag']);
|
|
16
27
|
if (!active.isAccepting)
|
|
17
28
|
return response({ error: 'Publication is unavailable while draining.' }, 503, responseCors);
|
|
18
|
-
const snapshot = servingSnapshot(source, limits, context.req.raw, reservations,
|
|
29
|
+
const snapshot = servingSnapshot(source, limits, context.req.raw, reservations, externalIssuer);
|
|
19
30
|
if (snapshot === undefined)
|
|
20
31
|
return response({ error: 'Publication is not ready.' }, 503, responseCors);
|
|
21
32
|
const body = snapshot.publicationBytes;
|
|
22
33
|
if (context.req.raw.headers.get('if-none-match') === quoteEtag(snapshot.publication.etag)) {
|
|
23
34
|
return new Response(null, {
|
|
24
35
|
status: 304,
|
|
25
|
-
headers: {
|
|
36
|
+
headers: {
|
|
37
|
+
...responseCors,
|
|
38
|
+
etag: quoteEtag(snapshot.publication.etag),
|
|
39
|
+
'cache-control': 'public, max-age=0, must-revalidate, no-transform',
|
|
40
|
+
},
|
|
26
41
|
});
|
|
27
42
|
}
|
|
28
43
|
return new Response(toBody(body), {
|
|
@@ -31,12 +46,12 @@ export function mountRoutes(app, source, installationProvider, handler, active,
|
|
|
31
46
|
...responseCors,
|
|
32
47
|
'content-type': 'application/json',
|
|
33
48
|
etag: quoteEtag(snapshot.publication.etag),
|
|
34
|
-
'cache-control': 'public, max-age=0, must-revalidate',
|
|
49
|
+
'cache-control': 'public, max-age=0, must-revalidate, no-transform',
|
|
35
50
|
},
|
|
36
51
|
});
|
|
37
52
|
});
|
|
38
53
|
app.all('*', async (context) => {
|
|
39
|
-
const snapshot = servingSnapshot(source, limits, context.req.raw, reservations,
|
|
54
|
+
const snapshot = servingSnapshot(source, limits, context.req.raw, reservations, externalIssuer);
|
|
40
55
|
if (snapshot === undefined)
|
|
41
56
|
return context.notFound();
|
|
42
57
|
const request = context.req.raw;
|
|
@@ -50,22 +65,22 @@ export function mountRoutes(app, source, installationProvider, handler, active,
|
|
|
50
65
|
if (request.method !== 'GET')
|
|
51
66
|
return response({ error: 'Bundle retrieval requires GET.' }, 405, responseCors);
|
|
52
67
|
const body = snapshot.bundle;
|
|
53
|
-
if (body.byteLength !== snapshot.publication.schema.bundle.size) {
|
|
68
|
+
if (body.byteLength !== snapshot.publication.schema.bundle.ref.size) {
|
|
54
69
|
return response({ error: 'Bundle differs from its Publication.' }, 500, responseCors);
|
|
55
70
|
}
|
|
56
71
|
return new Response(toBody(body), {
|
|
57
72
|
status: 200,
|
|
58
73
|
headers: {
|
|
59
74
|
...responseCors,
|
|
60
|
-
'content-type': snapshot.publication.schema.bundle.mediaType,
|
|
61
|
-
etag: quoteEtag(snapshot.publication.schema.bundle.digest),
|
|
62
|
-
'cache-control': 'public, max-age=31536000, immutable',
|
|
75
|
+
'content-type': snapshot.publication.schema.bundle.ref.mediaType,
|
|
76
|
+
etag: quoteEtag(snapshot.publication.schema.bundle.ref.digest),
|
|
77
|
+
'cache-control': 'public, max-age=31536000, immutable, no-transform',
|
|
63
78
|
},
|
|
64
79
|
});
|
|
65
80
|
}
|
|
66
|
-
const
|
|
67
|
-
if (
|
|
68
|
-
return
|
|
81
|
+
const deliveryUrl = snapshot.publication.delivery?.href;
|
|
82
|
+
if (deliveryUrl !== undefined && sameRoute(request.url, deliveryUrl, externalOrigin)) {
|
|
83
|
+
return handleDelivery(request, snapshot, deliveryProvider, active, limits, cors.response(request));
|
|
69
84
|
}
|
|
70
85
|
let routing;
|
|
71
86
|
try {
|
|
@@ -81,7 +96,7 @@ export function mountRoutes(app, source, installationProvider, handler, active,
|
|
|
81
96
|
},
|
|
82
97
|
});
|
|
83
98
|
}
|
|
84
|
-
routing = routes.decodeRouting(request,
|
|
99
|
+
routing = routes.decodeRouting(request, publicationReference(snapshot.publication));
|
|
85
100
|
}
|
|
86
101
|
catch (cause) {
|
|
87
102
|
if (cause instanceof routes.RouteError) {
|
|
@@ -89,9 +104,10 @@ export function mountRoutes(app, source, installationProvider, handler, active,
|
|
|
89
104
|
}
|
|
90
105
|
throw cause;
|
|
91
106
|
}
|
|
92
|
-
const route = routes.match(snapshot.
|
|
107
|
+
const route = routes.match(snapshot.table, request);
|
|
93
108
|
if (route === undefined)
|
|
94
109
|
return context.notFound();
|
|
110
|
+
const assigned = nextInvocation();
|
|
95
111
|
const operation = active.begin(limits.invocationTimeoutMs, request.signal);
|
|
96
112
|
if (operation === undefined)
|
|
97
113
|
return nativeError({
|
|
@@ -101,12 +117,7 @@ export function mountRoutes(app, source, installationProvider, handler, active,
|
|
|
101
117
|
let handedOff = false;
|
|
102
118
|
try {
|
|
103
119
|
const body = await readBoundedBody(request, limits.maximumRequestBytes, operation.signal);
|
|
104
|
-
const invocation = routes.decode(route, {
|
|
105
|
-
url: request.url,
|
|
106
|
-
method: request.method,
|
|
107
|
-
headers: request.headers,
|
|
108
|
-
body,
|
|
109
|
-
});
|
|
120
|
+
const invocation = routes.decode(route, { url: request.url, method: request.method, headers: request.headers, body }, snapshot.domain, snapshot.table.publication);
|
|
110
121
|
const idempotencyHeader = request.headers.get(protocol.HTTP_IDEMPOTENCY_KEY);
|
|
111
122
|
const idempotencyKey = idempotencyHeader === null
|
|
112
123
|
? undefined
|
|
@@ -116,7 +127,7 @@ export function mountRoutes(app, source, installationProvider, handler, active,
|
|
|
116
127
|
...(invocation.credential === undefined ? {} : { credential: invocation.credential }),
|
|
117
128
|
...(routing === undefined ? {} : { via: routing }),
|
|
118
129
|
publication: snapshot.snapshot,
|
|
119
|
-
context: invocationContext(operation, active, hostFor(request), body, idempotencyKey),
|
|
130
|
+
context: invocationContext(assigned, operation, active, hostFor(request), body, idempotencyKey),
|
|
120
131
|
}));
|
|
121
132
|
if (result.kind === 'value') {
|
|
122
133
|
return new Response(encodedBody(codecs.json.encode(result.value)), {
|
|
@@ -190,8 +201,8 @@ function publicationPreflight(cors, request, snapshot, externalOrigin) {
|
|
|
190
201
|
if (sameRoute(request.url, snapshot.publication.schema.bundle.href, externalOrigin)) {
|
|
191
202
|
return cors.preflight(request, { methods: ['GET'], headers: ['if-none-match'] });
|
|
192
203
|
}
|
|
193
|
-
const
|
|
194
|
-
if (
|
|
204
|
+
const deliveryUrl = snapshot.publication.delivery?.href;
|
|
205
|
+
if (deliveryUrl !== undefined && sameRoute(request.url, deliveryUrl, externalOrigin)) {
|
|
195
206
|
return cors.preflight(request, {
|
|
196
207
|
methods: ['POST'],
|
|
197
208
|
headers: ['authorization', 'content-type'],
|
|
@@ -200,7 +211,7 @@ function publicationPreflight(cors, request, snapshot, externalOrigin) {
|
|
|
200
211
|
const requestedMethod = request.headers.get('access-control-request-method');
|
|
201
212
|
const route = requestedMethod === null
|
|
202
213
|
? undefined
|
|
203
|
-
: routes.match(snapshot.
|
|
214
|
+
: routes.match(snapshot.table, { url: request.url, method: requestedMethod });
|
|
204
215
|
return cors.preflight(request, route === undefined ? undefined : nativeCorsRoute(route, requestedMethod));
|
|
205
216
|
}
|
|
206
217
|
function nativeCorsRoute(entry, requestedMethod) {
|
|
@@ -210,16 +221,16 @@ function nativeCorsRoute(entry, requestedMethod) {
|
|
|
210
221
|
routes.HTTP_ROUTE_ISSUER,
|
|
211
222
|
protocol.HTTP_IDEMPOTENCY_KEY,
|
|
212
223
|
]);
|
|
213
|
-
if (entry.
|
|
224
|
+
if (entry.body !== undefined)
|
|
214
225
|
headers.add('content-type');
|
|
215
226
|
let allowAnyHeaders = false;
|
|
216
|
-
for (const pick of Object.values(entry.
|
|
227
|
+
for (const pick of Object.values(entry.headers ?? {})) {
|
|
217
228
|
if (pick === '*')
|
|
218
229
|
allowAnyHeaders = true;
|
|
219
230
|
else
|
|
220
231
|
headers.add(pick.toLowerCase());
|
|
221
232
|
}
|
|
222
|
-
const credential = entry.
|
|
233
|
+
const credential = entry.credential;
|
|
223
234
|
const sources = credential === undefined
|
|
224
235
|
? [{ in: 'header' }]
|
|
225
236
|
: Array.isArray(credential)
|
|
@@ -230,9 +241,7 @@ function nativeCorsRoute(entry, requestedMethod) {
|
|
|
230
241
|
headers.add((source.name ?? 'authorization').toLowerCase());
|
|
231
242
|
}
|
|
232
243
|
return Object.freeze({
|
|
233
|
-
methods: Object.freeze([
|
|
234
|
-
entry.route.method === '*' ? requestedMethod.toUpperCase() : entry.route.method,
|
|
235
|
-
]),
|
|
244
|
+
methods: Object.freeze([entry.method === '*' ? requestedMethod.toUpperCase() : entry.method]),
|
|
236
245
|
headers: Object.freeze([...headers]),
|
|
237
246
|
...(allowAnyHeaders ? { allowAnyHeaders: true } : {}),
|
|
238
247
|
});
|
|
@@ -245,23 +254,25 @@ export function currentPublicationSnapshot(source, limits, serving) {
|
|
|
245
254
|
if (prepared === undefined ||
|
|
246
255
|
prepared.publicationBytes.byteLength > limits.maximumPublicationBytes ||
|
|
247
256
|
prepared.bundle.byteLength > limits.maximumBundleBytes ||
|
|
257
|
+
(serving?.issuer !== undefined && prepared.publication.identity.issuer !== serving.issuer) ||
|
|
248
258
|
(serving !== undefined && conflictsWithServingRoutes(prepared, serving))) {
|
|
249
259
|
return undefined;
|
|
250
260
|
}
|
|
251
261
|
return prepared;
|
|
252
262
|
}
|
|
253
|
-
function servingSnapshot(source, limits, request, reservations,
|
|
263
|
+
function servingSnapshot(source, limits, request, reservations, externalIssuer) {
|
|
254
264
|
return currentPublicationSnapshot(source, limits, {
|
|
255
|
-
origin:
|
|
265
|
+
origin: externalIssuer === undefined ? new URL(request.url).origin : new URL(externalIssuer).origin,
|
|
266
|
+
...(externalIssuer === undefined ? {} : { issuer: externalIssuer }),
|
|
256
267
|
reservations,
|
|
257
268
|
});
|
|
258
269
|
}
|
|
259
270
|
function conflictsWithServingRoutes(snapshot, serving) {
|
|
260
271
|
for (const reservation of serving.reservations) {
|
|
261
272
|
const href = `${serving.origin}${reservation.path}`;
|
|
262
|
-
for (const entry of snapshot.
|
|
263
|
-
if (reservation.methods.some((method) => entry.
|
|
264
|
-
routes.templatesOverlap(entry.
|
|
273
|
+
for (const entry of snapshot.table.entries) {
|
|
274
|
+
if (reservation.methods.some((method) => entry.method === '*' || entry.method === method) &&
|
|
275
|
+
routes.templatesOverlap(entry.href, href)) {
|
|
265
276
|
return true;
|
|
266
277
|
}
|
|
267
278
|
}
|
|
@@ -435,4 +446,3 @@ function encodedBody(input) {
|
|
|
435
446
|
function toBody(input) {
|
|
436
447
|
return input.buffer.slice(input.byteOffset, input.byteOffset + input.byteLength);
|
|
437
448
|
}
|
|
438
|
-
//# sourceMappingURL=routes.js.map
|
package/dist/server.d.ts
CHANGED
|
@@ -2,4 +2,3 @@ import type { Server, ServerConfig, ServerOptions, PreparedServer } from './type
|
|
|
2
2
|
export declare function createServer(config: ServerConfig): Server;
|
|
3
3
|
/** Validate all static transport configuration before a Host starts Runtime recovery/bootstrap. */
|
|
4
4
|
export declare function prepareServer(options: ServerOptions): PreparedServer;
|
|
5
|
-
//# sourceMappingURL=server.d.ts.map
|
package/dist/server.js
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
import { PATH as PUBLICATION_PATH, url as publicationUrl, } from '@astrale-os/kernel-protocol/publication/publication';
|
|
1
2
|
import { captureMethod } from './capture.js';
|
|
2
3
|
import { prepareCors } from './cors/index.js';
|
|
4
|
+
import { captureInvocationSource } from './invocation/index.js';
|
|
5
|
+
import { capture as captureExchangeProvider } from './issuer/exchange.js';
|
|
3
6
|
import { admitIssuer, issuerRouteReservations, mountIssuer } from './issuer/index.js';
|
|
4
7
|
import { ActiveOperations } from './lifecycle/index.js';
|
|
5
8
|
import { currentPublicationSnapshot, mountRoutes } from './routes/index.js';
|
|
6
|
-
import { createHttpHandler
|
|
9
|
+
import { createHttpHandler } from './transport/http/handler.js';
|
|
10
|
+
import { createServerRouter } from './transport/router.js';
|
|
11
|
+
import { handleWebSocketUpgrade } from './transport/websocket/upgrade.js';
|
|
7
12
|
export function createServer(config) {
|
|
8
13
|
const { handler, ...options } = config;
|
|
9
14
|
return prepareServer(options).create(handler);
|
|
@@ -20,10 +25,12 @@ function createPreparedServer(input, config) {
|
|
|
20
25
|
const active = new ActiveOperations(config.limits.maximumConcurrentOperations);
|
|
21
26
|
const app = createServerRouter();
|
|
22
27
|
const hosts = new WeakMap();
|
|
23
|
-
const
|
|
28
|
+
const externalIssuer = config.issuer?.issuer;
|
|
29
|
+
const externalOrigin = externalIssuer === undefined ? undefined : new URL(externalIssuer).origin;
|
|
24
30
|
const handleHttp = createHttpHandler({
|
|
25
31
|
handler,
|
|
26
32
|
active,
|
|
33
|
+
invocation: config.invocation,
|
|
27
34
|
...config.limits,
|
|
28
35
|
cors: config.cors,
|
|
29
36
|
websocket: config.websocket !== undefined,
|
|
@@ -32,6 +39,7 @@ function createPreparedServer(input, config) {
|
|
|
32
39
|
: {
|
|
33
40
|
currentPublication: (request) => currentPublicationSnapshot(config.publication, config.limits, {
|
|
34
41
|
origin: externalOrigin ?? new URL(request.url).origin,
|
|
42
|
+
...(externalIssuer === undefined ? {} : { issuer: externalIssuer }),
|
|
35
43
|
reservations: config.routeReservations,
|
|
36
44
|
})?.snapshot,
|
|
37
45
|
}),
|
|
@@ -42,6 +50,7 @@ function createPreparedServer(input, config) {
|
|
|
42
50
|
adapter: config.websocket,
|
|
43
51
|
handler,
|
|
44
52
|
active,
|
|
53
|
+
invocation: config.invocation,
|
|
45
54
|
...config.limits,
|
|
46
55
|
cors: config.cors,
|
|
47
56
|
...(config.publication === undefined
|
|
@@ -49,6 +58,7 @@ function createPreparedServer(input, config) {
|
|
|
49
58
|
: {
|
|
50
59
|
currentPublication: () => currentPublicationSnapshot(config.publication, config.limits, {
|
|
51
60
|
origin: externalOrigin ?? new URL(context.req.raw.url).origin,
|
|
61
|
+
...(externalIssuer === undefined ? {} : { issuer: externalIssuer }),
|
|
52
62
|
reservations: config.routeReservations,
|
|
53
63
|
})?.snapshot,
|
|
54
64
|
}),
|
|
@@ -69,10 +79,10 @@ function createPreparedServer(input, config) {
|
|
|
69
79
|
}
|
|
70
80
|
}
|
|
71
81
|
if (config.issuer !== undefined) {
|
|
72
|
-
mountIssuer(app, config.issuer, config.cors, active, config.limits.invocationTimeoutMs);
|
|
82
|
+
mountIssuer(app, config.issuer, config.cors, active, config.limits.invocationTimeoutMs, config.tokenExchange);
|
|
73
83
|
}
|
|
74
84
|
if (config.publication !== undefined) {
|
|
75
|
-
mountRoutes(app, config.publication, config.
|
|
85
|
+
mountRoutes(app, config.publication, config.delivery, handler, active, config.invocation, config.limits, config.cors, (request) => hosts.get(request), config.routeReservations, externalIssuer);
|
|
76
86
|
}
|
|
77
87
|
app.onError((_error, context) => new Response('{"error":"Internal server error."}', {
|
|
78
88
|
status: 500,
|
|
@@ -121,9 +131,14 @@ function captureHandler(input) {
|
|
|
121
131
|
return Object.freeze({ dispatch });
|
|
122
132
|
}
|
|
123
133
|
function admitOptions(config) {
|
|
134
|
+
const invocation = captureInvocationSource(config.invocation);
|
|
124
135
|
const limits = admitLimits(config.limits);
|
|
125
136
|
const path = admitRoute(config.path ?? '/', 'invocation path');
|
|
126
137
|
const issuer = config.issuer === undefined ? undefined : admitIssuer(config.issuer);
|
|
138
|
+
const tokenExchange = config.tokenExchange === undefined ? undefined : captureExchangeProvider(config.tokenExchange);
|
|
139
|
+
if (tokenExchange !== undefined && issuer === undefined) {
|
|
140
|
+
throw new TypeError('Token exchange requires issuer configuration.');
|
|
141
|
+
}
|
|
127
142
|
const health = config.health === undefined || config.health === false
|
|
128
143
|
? undefined
|
|
129
144
|
: Object.freeze({
|
|
@@ -132,34 +147,52 @@ function admitOptions(config) {
|
|
|
132
147
|
});
|
|
133
148
|
const websocket = config.websocket === undefined ? undefined : captureWebSocket(config.websocket);
|
|
134
149
|
const publication = config.publication === undefined ? undefined : capturePublicationSource(config.publication);
|
|
135
|
-
const
|
|
136
|
-
if (
|
|
137
|
-
throw new TypeError('
|
|
150
|
+
const delivery = config.delivery === undefined ? undefined : captureDeliveryProvider(config.delivery);
|
|
151
|
+
if (delivery !== undefined && publication === undefined) {
|
|
152
|
+
throw new TypeError('Publication Delivery requires a Publication source.');
|
|
138
153
|
}
|
|
154
|
+
const publicationPath = publication === undefined
|
|
155
|
+
? undefined
|
|
156
|
+
: issuer === undefined
|
|
157
|
+
? protocolPublicationPath()
|
|
158
|
+
: protocolPublicationPath(issuer.issuer);
|
|
139
159
|
if (health?.path === path)
|
|
140
160
|
throw new TypeError('Health and invocation paths must be distinct.');
|
|
161
|
+
if (publicationPath === path) {
|
|
162
|
+
throw new TypeError('Publication and invocation paths must be distinct.');
|
|
163
|
+
}
|
|
164
|
+
if (health !== undefined && publicationPath === health.path) {
|
|
165
|
+
throw new TypeError('Health and Publication paths must be distinct.');
|
|
166
|
+
}
|
|
141
167
|
if (issuer !== undefined) {
|
|
142
|
-
const
|
|
168
|
+
const issuerReservations = issuerRouteReservations(issuer, tokenExchange !== undefined);
|
|
169
|
+
const issuerPaths = issuerReservations.map(({ path }) => path);
|
|
143
170
|
if (health !== undefined && issuerPaths.includes(health.path)) {
|
|
144
171
|
throw new TypeError('Health and issuer paths must be distinct.');
|
|
145
172
|
}
|
|
146
173
|
if (websocket !== undefined && issuerPaths.includes(path)) {
|
|
147
174
|
throw new TypeError('WebSocket invocation and issuer paths must be distinct.');
|
|
148
175
|
}
|
|
176
|
+
if (websocket === undefined &&
|
|
177
|
+
issuerReservations.some((reservation) => reservation.path === path && reservation.methods.includes('POST'))) {
|
|
178
|
+
throw new TypeError('Invocation and token-exchange paths must be distinct.');
|
|
179
|
+
}
|
|
149
180
|
}
|
|
150
181
|
return Object.freeze({
|
|
182
|
+
invocation,
|
|
151
183
|
limits,
|
|
152
184
|
path,
|
|
153
185
|
cors: prepareCors(config.cors),
|
|
154
186
|
...(health === undefined ? {} : { health }),
|
|
155
187
|
...(issuer === undefined ? {} : { issuer }),
|
|
188
|
+
...(tokenExchange === undefined ? {} : { tokenExchange }),
|
|
156
189
|
...(publication === undefined ? {} : { publication }),
|
|
157
|
-
...(
|
|
158
|
-
routeReservations: routeReservations(path, health?.path, issuer, websocket !== undefined),
|
|
190
|
+
...(delivery === undefined ? {} : { delivery }),
|
|
191
|
+
routeReservations: routeReservations(path, health?.path, issuer, websocket !== undefined, tokenExchange !== undefined, publicationPath),
|
|
159
192
|
...(websocket === undefined ? {} : { websocket }),
|
|
160
193
|
});
|
|
161
194
|
}
|
|
162
|
-
function routeReservations(invocationPath, healthPath, issuer, websocket) {
|
|
195
|
+
function routeReservations(invocationPath, healthPath, issuer, websocket, tokenExchange, publicationPath) {
|
|
163
196
|
const reservations = [
|
|
164
197
|
Object.freeze({
|
|
165
198
|
path: invocationPath,
|
|
@@ -170,10 +203,18 @@ function routeReservations(invocationPath, healthPath, issuer, websocket) {
|
|
|
170
203
|
reservations.push(Object.freeze({ path: healthPath, methods: Object.freeze(['GET']) }));
|
|
171
204
|
}
|
|
172
205
|
if (issuer !== undefined) {
|
|
173
|
-
reservations.push(...issuerRouteReservations(issuer));
|
|
206
|
+
reservations.push(...issuerRouteReservations(issuer, tokenExchange));
|
|
207
|
+
}
|
|
208
|
+
if (publicationPath !== undefined) {
|
|
209
|
+
reservations.push(Object.freeze({ path: publicationPath, methods: Object.freeze(['GET']) }));
|
|
174
210
|
}
|
|
175
211
|
return Object.freeze(reservations);
|
|
176
212
|
}
|
|
213
|
+
function protocolPublicationPath(issuer) {
|
|
214
|
+
if (issuer === undefined)
|
|
215
|
+
return PUBLICATION_PATH;
|
|
216
|
+
return new URL(publicationUrl(issuer)).pathname;
|
|
217
|
+
}
|
|
177
218
|
function captureHealthProbe(probe) {
|
|
178
219
|
const check = captureMethod(probe, 'check', 'Health probe is invalid.');
|
|
179
220
|
return Object.freeze({ check });
|
|
@@ -186,8 +227,8 @@ function capturePublicationSource(input) {
|
|
|
186
227
|
const current = captureMethod(input, 'current', 'Publication source is invalid.');
|
|
187
228
|
return Object.freeze({ current });
|
|
188
229
|
}
|
|
189
|
-
function
|
|
190
|
-
const create = captureMethod(input, 'create', '
|
|
230
|
+
function captureDeliveryProvider(input) {
|
|
231
|
+
const create = captureMethod(input, 'create', 'Publication Delivery provider is invalid.');
|
|
191
232
|
return Object.freeze({ create });
|
|
192
233
|
}
|
|
193
234
|
function admitLimits(limits) {
|
|
@@ -206,7 +247,7 @@ function admitLimits(limits) {
|
|
|
206
247
|
maximumConcurrentOperations: admitOptionalLimit(limits.maximumConcurrentOperations, 1_024, 'maximumConcurrentOperations'),
|
|
207
248
|
maximumPublicationBytes: admitOptionalLimit(limits.maximumPublicationBytes, limits.maximumRequestBytes, 'maximumPublicationBytes'),
|
|
208
249
|
maximumBundleBytes: admitOptionalLimit(limits.maximumBundleBytes, 16 * 1024 * 1024, 'maximumBundleBytes'),
|
|
209
|
-
|
|
250
|
+
maximumDeliveryBytes: admitOptionalLimit(limits.maximumDeliveryBytes, limits.maximumRequestBytes, 'maximumDeliveryBytes'),
|
|
210
251
|
invocationTimeoutMs: limits.invocationTimeoutMs,
|
|
211
252
|
});
|
|
212
253
|
}
|
|
@@ -223,4 +264,3 @@ function admitRoute(path, label) {
|
|
|
223
264
|
}
|
|
224
265
|
return path;
|
|
225
266
|
}
|
|
226
|
-
//# sourceMappingURL=server.js.map
|
package/dist/transport/body.d.ts
CHANGED
|
@@ -2,4 +2,3 @@ export { RequestBodyInvalidError, RequestBodyTooLargeError } from '../errors/ind
|
|
|
2
2
|
/** Read a request body while enforcing the limit before retaining excess bytes. */
|
|
3
3
|
export declare function readBoundedBody(request: Request, maximumBytes: number, signal: AbortSignal): Promise<Uint8Array>;
|
|
4
4
|
export declare function byteLength(input: string | Uint8Array): number;
|
|
5
|
-
//# sourceMappingURL=body.d.ts.map
|
package/dist/transport/body.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as codecs from '@astrale-os/kernel-protocol/codecs';
|
|
2
2
|
export type LoadedCodec = codecs.Codec;
|
|
3
3
|
/** Load the built-in Server representation set before pure Protocol binding selection. */
|
|
4
4
|
export declare function loadCodecs(): Promise<readonly [codecs.Codec, codecs.Codec]>;
|
|
5
|
-
//# sourceMappingURL=codecs.d.ts.map
|
package/dist/transport/codecs.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as codecs from '@astrale-os/kernel-protocol/codecs';
|
|
2
2
|
/** Load the built-in Server representation set before pure Protocol binding selection. */
|
|
3
3
|
export async function loadCodecs() {
|
|
4
4
|
return Object.freeze([codecs.json, await codecs.loadMsgpack()]);
|
|
5
5
|
}
|
|
6
|
-
//# sourceMappingURL=codecs.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as errors from '@astrale-os/kernel-protocol/errors';
|
|
2
2
|
export type CredentialResult = {
|
|
3
3
|
readonly ok: true;
|
|
4
4
|
readonly credential: string | undefined;
|
|
@@ -8,4 +8,3 @@ export type CredentialResult = {
|
|
|
8
8
|
};
|
|
9
9
|
/** Resolve exactly zero or one untrusted credential channel without authenticating it. */
|
|
10
10
|
export declare function resolveCredential(envelope: string | undefined, authorization: string | null): CredentialResult;
|
|
11
|
-
//# sourceMappingURL=credential.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as errors from '@astrale-os/kernel-protocol/errors';
|
|
2
2
|
/** Resolve exactly zero or one untrusted credential channel without authenticating it. */
|
|
3
3
|
export function resolveCredential(envelope, authorization) {
|
|
4
4
|
if (envelope !== undefined && authorization !== null) {
|
|
@@ -26,4 +26,3 @@ function failure(message) {
|
|
|
26
26
|
error: { code: errors.CODES.INVALID_REQUEST, message },
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
|
-
//# sourceMappingURL=credential.js.map
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { CorsPolicy } from '../../cors/index.js';
|
|
2
|
+
import type { NextInvocationId } from '../../invocation/index.js';
|
|
2
3
|
import type { ActiveOperations } from '../../lifecycle/index.js';
|
|
3
4
|
import type { PublicationSnapshot } from '../../publication/index.js';
|
|
4
5
|
import { type ApplicationHost, type Handler } from '../../invocation/index.js';
|
|
5
6
|
export interface HttpHandlerConfig {
|
|
6
7
|
readonly handler: Handler;
|
|
7
8
|
readonly active: ActiveOperations;
|
|
9
|
+
readonly invocation: NextInvocationId;
|
|
8
10
|
readonly maximumRequestBytes: number;
|
|
9
11
|
readonly maximumResponseBytes: number;
|
|
10
12
|
readonly invocationTimeoutMs: number;
|
|
@@ -13,4 +15,3 @@ export interface HttpHandlerConfig {
|
|
|
13
15
|
readonly currentPublication?: (request: Request) => PublicationSnapshot | undefined;
|
|
14
16
|
}
|
|
15
17
|
export declare function createHttpHandler(config: HttpHandlerConfig): (request: Request, host?: ApplicationHost) => Promise<Response>;
|
|
16
|
-
//# sourceMappingURL=handler.d.ts.map
|