@decohere/http 0.0.1-dev.130 → 0.0.1-dev.20261105.103
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/es6/src/routing/services/route-registry.js +5 -0
- package/package.json +9 -14
- package/commonjs/src/app/app.js +0 -166
- package/commonjs/src/app/index.js +0 -19
- package/commonjs/src/app/module.js +0 -17
- package/commonjs/src/auth/ability.js +0 -54
- package/commonjs/src/auth/auth.config.js +0 -23
- package/commonjs/src/auth/auth.extensions.js +0 -106
- package/commonjs/src/auth/auth.types.js +0 -65
- package/commonjs/src/auth/casl-authorization.service.js +0 -36
- package/commonjs/src/auth/index.js +0 -23
- package/commonjs/src/auth/principal-provider.js +0 -19
- package/commonjs/src/auth/safe-outbound-url.js +0 -102
- package/commonjs/src/auth/token-service.js +0 -151
- package/commonjs/src/builder/builder.js +0 -95
- package/commonjs/src/builder/index.js +0 -18
- package/commonjs/src/const.js +0 -86
- package/commonjs/src/health/health.controller.js +0 -75
- package/commonjs/src/health/health.extensions.js +0 -50
- package/commonjs/src/health/index.js +0 -21
- package/commonjs/src/health/readiness.service.js +0 -67
- package/commonjs/src/health/readiness.types.js +0 -7
- package/commonjs/src/hosting/hosted-service-host.js +0 -88
- package/commonjs/src/hosting/hosted-service.js +0 -11
- package/commonjs/src/hosting/index.js +0 -19
- package/commonjs/src/http/http.compression.js +0 -27
- package/commonjs/src/http/http.extensions.js +0 -269
- package/commonjs/src/http/http.options.js +0 -26
- package/commonjs/src/http/http.options.store.js +0 -20
- package/commonjs/src/http/http.security.js +0 -27
- package/commonjs/src/http/http.static.js +0 -248
- package/commonjs/src/http/index.js +0 -22
- package/commonjs/src/index.js +0 -27
- package/commonjs/src/openapi/index.js +0 -45
- package/commonjs/src/openapi/openapi.generator.js +0 -103
- package/commonjs/src/openapi/openapi.types.js +0 -4
- package/commonjs/src/openapi/request-schema.js +0 -187
- package/commonjs/src/openapi/request-validator.js +0 -85
- package/commonjs/src/providers/fastify.provider.js +0 -391
- package/commonjs/src/providers/index.js +0 -18
- package/commonjs/src/routing/decorators/argument.decorator.js +0 -49
- package/commonjs/src/routing/decorators/auth.decorator.js +0 -70
- package/commonjs/src/routing/decorators/controller.decorator.js +0 -16
- package/commonjs/src/routing/decorators/field.decorator.js +0 -25
- package/commonjs/src/routing/decorators/index.js +0 -24
- package/commonjs/src/routing/decorators/request.decorator.js +0 -30
- package/commonjs/src/routing/decorators/response.decorator.js +0 -34
- package/commonjs/src/routing/decorators/route.decorator.js +0 -67
- package/commonjs/src/routing/filters/exception-filter-host.js +0 -145
- package/commonjs/src/routing/filters/exception-filter.js +0 -28
- package/commonjs/src/routing/http.types.js +0 -99
- package/commonjs/src/routing/index.js +0 -25
- package/commonjs/src/routing/middleware/http-access-log.middleware.js +0 -47
- package/commonjs/src/routing/middleware/middleware.js +0 -20
- package/commonjs/src/routing/middleware/request-id.js +0 -30
- package/commonjs/src/routing/path.util.js +0 -51
- package/commonjs/src/routing/pipes/index.js +0 -18
- package/commonjs/src/routing/pipes/pipes.js +0 -145
- package/commonjs/src/routing/services/index.js +0 -18
- package/commonjs/src/routing/services/route-argument-resolver.js +0 -77
- package/commonjs/src/routing/services/route-registry.js +0 -194
- package/commonjs/src/routing/services/router.js +0 -158
- package/commonjs/src/sse/index.js +0 -26
- package/commonjs/src/sse/sse.decorator.js +0 -42
- package/commonjs/src/sse/sse.encoder.js +0 -73
- package/commonjs/src/sse/sse.types.js +0 -36
- package/commonjs/src/sse/sse.wire.js +0 -40
- package/commonjs/src/testing/boot-module.js +0 -38
- package/commonjs/src/testing/index.js +0 -20
- package/commonjs/src/testing/sse-reader.js +0 -98
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
Object.defineProperty(exports, "encodeSse", {
|
|
6
|
-
enumerable: true,
|
|
7
|
-
get: function() {
|
|
8
|
-
return encodeSse;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
const _scribe = require("@decohere/scribe");
|
|
12
|
-
const _ssewire = require("./sse.wire.js");
|
|
13
|
-
const logger = _scribe.scribe.logger("SseEncoder");
|
|
14
|
-
async function* encodeSse(source, options) {
|
|
15
|
-
const { signal, heartbeatMs } = options;
|
|
16
|
-
const iterator = source[Symbol.asyncIterator]();
|
|
17
|
-
let onAbort;
|
|
18
|
-
const abortStep = new Promise((resolve)=>{
|
|
19
|
-
onAbort = ()=>resolve({
|
|
20
|
-
kind: "abort"
|
|
21
|
-
});
|
|
22
|
-
if (signal.aborted) onAbort();
|
|
23
|
-
else signal.addEventListener("abort", onAbort, {
|
|
24
|
-
once: true
|
|
25
|
-
});
|
|
26
|
-
});
|
|
27
|
-
let pending;
|
|
28
|
-
try {
|
|
29
|
-
yield _ssewire.sseWire.formatComment("open");
|
|
30
|
-
while(!signal.aborted){
|
|
31
|
-
pending ??= iterator.next().then((result)=>({
|
|
32
|
-
kind: "item",
|
|
33
|
-
result
|
|
34
|
-
}));
|
|
35
|
-
let timer;
|
|
36
|
-
const steps = [
|
|
37
|
-
pending,
|
|
38
|
-
abortStep
|
|
39
|
-
];
|
|
40
|
-
if (heartbeatMs > 0) {
|
|
41
|
-
steps.push(new Promise((resolve)=>{
|
|
42
|
-
timer = setTimeout(()=>resolve({
|
|
43
|
-
kind: "heartbeat"
|
|
44
|
-
}), heartbeatMs);
|
|
45
|
-
}));
|
|
46
|
-
}
|
|
47
|
-
let step;
|
|
48
|
-
try {
|
|
49
|
-
step = await Promise.race(steps);
|
|
50
|
-
} finally{
|
|
51
|
-
clearTimeout(timer);
|
|
52
|
-
}
|
|
53
|
-
if (step.kind === "abort") return;
|
|
54
|
-
if (step.kind === "heartbeat") {
|
|
55
|
-
yield _ssewire.sseWire.formatComment("heartbeat");
|
|
56
|
-
continue;
|
|
57
|
-
}
|
|
58
|
-
pending = undefined;
|
|
59
|
-
if (step.result.done) return;
|
|
60
|
-
yield _ssewire.sseWire.formatMessage(step.result.value);
|
|
61
|
-
}
|
|
62
|
-
} catch (error) {
|
|
63
|
-
// Headers are already sent, so the only honest thing left is to log and end the stream.
|
|
64
|
-
if (!signal.aborted) logger.error("SSE producer failed", error);
|
|
65
|
-
} finally{
|
|
66
|
-
if (onAbort) signal.removeEventListener("abort", onAbort);
|
|
67
|
-
// If the producer has not answered its last `next()`, `return()` waits behind it. That is
|
|
68
|
-
// why handlers must pass the signal to whatever they wait on.
|
|
69
|
-
options.onProducerStopped(Promise.resolve().then(()=>iterator.return?.()).then(()=>undefined, (error)=>{
|
|
70
|
-
if (!signal.aborted) logger.error("SSE producer failed while stopping", error);
|
|
71
|
-
}));
|
|
72
|
-
}
|
|
73
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* One server-sent event. A bare `string` yielded by a handler is shorthand for `{ data }`.
|
|
3
|
-
*
|
|
4
|
-
* `data` is written as-is when it is a string and as JSON otherwise.
|
|
5
|
-
*/ "use strict";
|
|
6
|
-
Object.defineProperty(exports, "__esModule", {
|
|
7
|
-
value: true
|
|
8
|
-
});
|
|
9
|
-
function _export(target, all) {
|
|
10
|
-
for(var name in all)Object.defineProperty(target, name, {
|
|
11
|
-
enumerable: true,
|
|
12
|
-
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
13
|
-
});
|
|
14
|
-
}
|
|
15
|
-
_export(exports, {
|
|
16
|
-
get DEFAULT_SSE_HEARTBEAT_MS () {
|
|
17
|
-
return DEFAULT_SSE_HEARTBEAT_MS;
|
|
18
|
-
},
|
|
19
|
-
get SseResponse () {
|
|
20
|
-
return SseResponse;
|
|
21
|
-
}
|
|
22
|
-
});
|
|
23
|
-
const DEFAULT_SSE_HEARTBEAT_MS = 15_000;
|
|
24
|
-
class SseResponse {
|
|
25
|
-
events;
|
|
26
|
-
onRelease;
|
|
27
|
-
released;
|
|
28
|
-
constructor(events, onRelease){
|
|
29
|
-
this.events = events;
|
|
30
|
-
this.onRelease = onRelease;
|
|
31
|
-
}
|
|
32
|
-
/** Safe to call more than once. */ release() {
|
|
33
|
-
this.released ??= this.onRelease();
|
|
34
|
-
return this.released;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
Object.defineProperty(exports, "sseWire", {
|
|
6
|
-
enumerable: true,
|
|
7
|
-
get: function() {
|
|
8
|
-
return sseWire;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
/** Line breaks would end a field early, so a client-controlled `id` could inject extra fields. */ function singleLine(value) {
|
|
12
|
-
return value.replace(/[\r\n]+/g, " ");
|
|
13
|
-
}
|
|
14
|
-
function toMessage(item) {
|
|
15
|
-
if (typeof item === "object" && item !== null && "data" in item) {
|
|
16
|
-
return item;
|
|
17
|
-
}
|
|
18
|
-
return {
|
|
19
|
-
data: item
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
/** Encode one event as the text a browser's `EventSource` parses. */ function formatMessage(item) {
|
|
23
|
-
const { data, event, id, retry } = toMessage(item);
|
|
24
|
-
let frame = "";
|
|
25
|
-
if (id != null) frame += `id: ${singleLine(String(id))}\n`;
|
|
26
|
-
if (event != null) frame += `event: ${singleLine(event)}\n`;
|
|
27
|
-
if (retry != null && Number.isFinite(retry)) frame += `retry: ${Math.trunc(retry)}\n`;
|
|
28
|
-
const text = typeof data === "string" ? data : JSON.stringify(data) ?? "";
|
|
29
|
-
for (const line of text.split(/\r\n|\r|\n/)){
|
|
30
|
-
frame += `data: ${line}\n`;
|
|
31
|
-
}
|
|
32
|
-
return `${frame}\n`;
|
|
33
|
-
}
|
|
34
|
-
/** A comment line: ignored by `EventSource`, but it is traffic on the wire. */ function formatComment(text) {
|
|
35
|
-
return `: ${singleLine(text)}\n\n`;
|
|
36
|
-
}
|
|
37
|
-
const sseWire = {
|
|
38
|
-
formatMessage,
|
|
39
|
-
formatComment
|
|
40
|
-
};
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
Object.defineProperty(exports, "bootModule", {
|
|
6
|
-
enumerable: true,
|
|
7
|
-
get: function() {
|
|
8
|
-
return bootModule;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
const _builder = require("../builder/builder.js");
|
|
12
|
-
require("../http/http.extensions.js");
|
|
13
|
-
const _fastifyprovider = require("../providers/fastify.provider.js");
|
|
14
|
-
const _ssereader = require("./sse-reader.js");
|
|
15
|
-
async function bootModule(options) {
|
|
16
|
-
let builder = _builder.Builder.create().withHttp(options.provider ?? _fastifyprovider.FastifyProvider).withControllers(...options.controllers);
|
|
17
|
-
if (options.services) builder = builder.withServices(options.services);
|
|
18
|
-
options.configure?.(builder);
|
|
19
|
-
const app = await builder.build();
|
|
20
|
-
await app.start({
|
|
21
|
-
port: 0,
|
|
22
|
-
host: "127.0.0.1",
|
|
23
|
-
shutdownSignals: false
|
|
24
|
-
});
|
|
25
|
-
const baseUrl = app.addresses[0];
|
|
26
|
-
if (baseUrl == null) {
|
|
27
|
-
await app.dispose();
|
|
28
|
-
throw new Error("app.start({ port: 0 }) advertised no IPv4 address");
|
|
29
|
-
}
|
|
30
|
-
const stop = ()=>app.dispose();
|
|
31
|
-
return {
|
|
32
|
-
app,
|
|
33
|
-
baseUrl,
|
|
34
|
-
readEvents: (path, readOptions)=>(0, _ssereader.readEventStream)(`${baseUrl}${path}`, readOptions),
|
|
35
|
-
stop,
|
|
36
|
-
[Symbol.asyncDispose]: stop
|
|
37
|
-
};
|
|
38
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
function _export(target, all) {
|
|
6
|
-
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
-
enumerable: true,
|
|
8
|
-
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
_export(exports, {
|
|
12
|
-
get bootModule () {
|
|
13
|
-
return _bootmodule.bootModule;
|
|
14
|
-
},
|
|
15
|
-
get readEventStream () {
|
|
16
|
-
return _ssereader.readEventStream;
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
const _bootmodule = require("./boot-module.js");
|
|
20
|
-
const _ssereader = require("./sse-reader.js");
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
Object.defineProperty(exports, "readEventStream", {
|
|
6
|
-
enumerable: true,
|
|
7
|
-
get: function() {
|
|
8
|
-
return readEventStream;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
/** Incremental parser for the `text/event-stream` format. */ class SseParser {
|
|
12
|
-
buffer = "";
|
|
13
|
-
data = [];
|
|
14
|
-
current = {
|
|
15
|
-
data: ""
|
|
16
|
-
};
|
|
17
|
-
hasFields = false;
|
|
18
|
-
events = [];
|
|
19
|
-
comments = [];
|
|
20
|
-
push(chunk) {
|
|
21
|
-
this.buffer += chunk;
|
|
22
|
-
let newline;
|
|
23
|
-
while((newline = this.buffer.search(/\r\n|\r|\n/)) !== -1){
|
|
24
|
-
const line = this.buffer.slice(0, newline);
|
|
25
|
-
const eol = this.buffer.slice(newline).startsWith("\r\n") ? 2 : 1;
|
|
26
|
-
this.buffer = this.buffer.slice(newline + eol);
|
|
27
|
-
this.line(line);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
line(line) {
|
|
31
|
-
if (line === "") {
|
|
32
|
-
if (this.hasFields) {
|
|
33
|
-
this.events.push({
|
|
34
|
-
...this.current,
|
|
35
|
-
data: this.data.join("\n")
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
this.data = [];
|
|
39
|
-
this.current = {
|
|
40
|
-
data: ""
|
|
41
|
-
};
|
|
42
|
-
this.hasFields = false;
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
if (line.startsWith(":")) {
|
|
46
|
-
this.comments.push(line.slice(1).trim());
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
const colon = line.indexOf(":");
|
|
50
|
-
const field = colon === -1 ? line : line.slice(0, colon);
|
|
51
|
-
let value = colon === -1 ? "" : line.slice(colon + 1);
|
|
52
|
-
if (value.startsWith(" ")) value = value.slice(1);
|
|
53
|
-
this.hasFields = true;
|
|
54
|
-
if (field === "data") this.data.push(value);
|
|
55
|
-
else if (field === "event") this.current.event = value;
|
|
56
|
-
else if (field === "id") this.current.id = value;
|
|
57
|
-
else if (field === "retry") this.current.retry = Number(value);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
async function readEventStream(url, options = {}) {
|
|
61
|
-
const count = options.count ?? 1;
|
|
62
|
-
const abort = new AbortController();
|
|
63
|
-
const timer = setTimeout(()=>abort.abort(new Error(`No ${count} events from ${url} in time`)), options.timeoutMs ?? 5000);
|
|
64
|
-
try {
|
|
65
|
-
const response = await fetch(url, {
|
|
66
|
-
headers: {
|
|
67
|
-
accept: "text/event-stream",
|
|
68
|
-
...options.headers
|
|
69
|
-
},
|
|
70
|
-
signal: abort.signal
|
|
71
|
-
});
|
|
72
|
-
const parser = new SseParser();
|
|
73
|
-
let ended = false;
|
|
74
|
-
if (response.status === 200 && response.body != null) {
|
|
75
|
-
const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
|
|
76
|
-
while(parser.events.length < count){
|
|
77
|
-
const { done, value } = await reader.read();
|
|
78
|
-
if (done) {
|
|
79
|
-
ended = true;
|
|
80
|
-
break;
|
|
81
|
-
}
|
|
82
|
-
parser.push(value);
|
|
83
|
-
}
|
|
84
|
-
await reader.cancel();
|
|
85
|
-
} else {
|
|
86
|
-
await response.body?.cancel();
|
|
87
|
-
}
|
|
88
|
-
return {
|
|
89
|
-
status: response.status,
|
|
90
|
-
headers: response.headers,
|
|
91
|
-
events: parser.events.slice(0, count),
|
|
92
|
-
comments: parser.comments,
|
|
93
|
-
ended
|
|
94
|
-
};
|
|
95
|
-
} finally{
|
|
96
|
-
clearTimeout(timer);
|
|
97
|
-
}
|
|
98
|
-
}
|