@streamsy/serve 0.0.0-stage → 0.4.0
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/LICENSE +21 -0
- package/README.md +107 -2
- package/dist/action/contract.d.ts +100 -0
- package/dist/action/contract.js +28 -0
- package/dist/action/errors.d.ts +35 -0
- package/dist/action/errors.js +51 -0
- package/dist/action/outbox.d.ts +67 -0
- package/dist/action/outbox.js +109 -0
- package/dist/action/runtime.d.ts +80 -0
- package/dist/action/runtime.js +182 -0
- package/dist/action/sql.d.ts +8 -0
- package/dist/action/sql.js +229 -0
- package/dist/alchemy.d.ts +25 -0
- package/dist/alchemy.js +39 -0
- package/dist/bun.d.ts +13 -0
- package/dist/bun.js +14 -0
- package/dist/cloudflare.d.ts +35 -0
- package/dist/cloudflare.js +40 -0
- package/dist/contract-BUWJ-Sy2.d.ts +67 -0
- package/dist/contract.d.ts +2 -0
- package/dist/contract.js +124 -0
- package/dist/deno.d.ts +27 -0
- package/dist/deno.js +32 -0
- package/dist/index.d.ts +171 -0
- package/dist/index.js +337 -0
- package/dist/node.d.ts +20 -0
- package/dist/node.js +58 -0
- package/dist/placement-BOM3E08P.d.ts +60 -0
- package/dist/rolldown-runtime-D7D4PA-g.js +13 -0
- package/dist/router-DviIc1O7.js +130 -0
- package/dist/wakeup-BtnMEjLv.d.ts +56 -0
- package/dist/wakeup-CWKg8pts.js +125 -0
- package/package.json +132 -4
package/dist/contract.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
//#region src/contract.ts
|
|
2
|
+
/** Encode a value with object keys sorted, recursively. Array order is preserved. */
|
|
3
|
+
function canonicalJson(value) {
|
|
4
|
+
if (isCanonicalArray(value)) return `[${value.map((item) => canonicalJson(item)).join(",")}]`;
|
|
5
|
+
if (value === null) return "null";
|
|
6
|
+
if (value instanceof Object) return canonicalObject(value);
|
|
7
|
+
if (typeof value === "number" && !Number.isFinite(value)) throw new TypeError("Expected finite JSON number");
|
|
8
|
+
return JSON.stringify(value);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A written predicate rather than a bare `Array.isArray` call, because only a
|
|
12
|
+
* predicate narrows the non-array branch of this union to the record type.
|
|
13
|
+
*/
|
|
14
|
+
function isCanonicalArray(value) {
|
|
15
|
+
return Array.isArray(value);
|
|
16
|
+
}
|
|
17
|
+
function canonicalObject(value) {
|
|
18
|
+
const entries = [];
|
|
19
|
+
for (const key of Object.keys(value).toSorted(compareKeys)) {
|
|
20
|
+
const member = value[key];
|
|
21
|
+
if (member === void 0) continue;
|
|
22
|
+
entries.push(`${JSON.stringify(key)}:${canonicalJson(member)}`);
|
|
23
|
+
}
|
|
24
|
+
return `{${entries.join(",")}}`;
|
|
25
|
+
}
|
|
26
|
+
function compareKeys(left, right) {
|
|
27
|
+
if (left === right) return 0;
|
|
28
|
+
return left < right ? -1 : 1;
|
|
29
|
+
}
|
|
30
|
+
/** Eight lowercase hex characters of FNV-1a over the canonical encoding's UTF-16 code units. */
|
|
31
|
+
function contractFingerprint(value) {
|
|
32
|
+
return hex(fnv1a(canonicalJson(value), 2166136261));
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Sixteen lowercase hex characters, as a strong entity tag body.
|
|
36
|
+
*
|
|
37
|
+
* Two FNV-1a passes with different offset bases are concatenated, because a
|
|
38
|
+
* cache validator that collides serves a stale value: eight hex characters
|
|
39
|
+
* are enough to notice that a contract changed, but not enough to key a
|
|
40
|
+
* consumer's cache on.
|
|
41
|
+
*/
|
|
42
|
+
function valueEtag(canonical) {
|
|
43
|
+
return `"${hex(fnv1a(canonical, 2166136261))}${hex(fnv1a(canonical, 16777619))}"`;
|
|
44
|
+
}
|
|
45
|
+
function fnv1a(input, seed) {
|
|
46
|
+
let hash = seed;
|
|
47
|
+
for (let index = 0; index < input.length; index += 1) {
|
|
48
|
+
hash ^= input.charCodeAt(index);
|
|
49
|
+
hash = Math.imul(hash, 16777619);
|
|
50
|
+
}
|
|
51
|
+
return hash >>> 0;
|
|
52
|
+
}
|
|
53
|
+
function hex(value) {
|
|
54
|
+
return value.toString(16).padStart(8, "0");
|
|
55
|
+
}
|
|
56
|
+
const STATE_VERSION_HEADER = "x-streamsy-state-version";
|
|
57
|
+
const STATE_CONTRACT_HEADER = "x-streamsy-state-contract";
|
|
58
|
+
const STREAM_VERSION_HEADER = "x-streamsy-stream-version";
|
|
59
|
+
const STREAM_CONTRACT_HEADER = "x-streamsy-stream-contract";
|
|
60
|
+
const VALUE_CONTRACT_HEADER = "x-streamsy-value-contract";
|
|
61
|
+
const DURABLE_STATE_PROTOCOL = "https://durable-streams.dev/state-protocol/v1";
|
|
62
|
+
const PUBLIC_ERROR_TAGS = [
|
|
63
|
+
"InvalidParams",
|
|
64
|
+
"ProtocolVersionUnsupported",
|
|
65
|
+
"ResumeRejected",
|
|
66
|
+
"ContractChanged",
|
|
67
|
+
"TransportUnavailable",
|
|
68
|
+
"WireEncodeFailed"
|
|
69
|
+
];
|
|
70
|
+
/** The browser's JSON error boundary; unknown fields are discarded. */
|
|
71
|
+
function decodePublicError(value) {
|
|
72
|
+
if (value === null || !(value instanceof Object) || Array.isArray(value)) throw new TypeError("Expected error object");
|
|
73
|
+
const field = (key) => Object.getOwnPropertyDescriptor(value, key)?.value;
|
|
74
|
+
const string = (key) => {
|
|
75
|
+
const result = field(key);
|
|
76
|
+
if (typeof result !== "string") throw new TypeError(`Expected string ${key}`);
|
|
77
|
+
return result;
|
|
78
|
+
};
|
|
79
|
+
const _tag = string("_tag");
|
|
80
|
+
const route = string("route");
|
|
81
|
+
switch (_tag) {
|
|
82
|
+
case "InvalidParams": return {
|
|
83
|
+
_tag,
|
|
84
|
+
route,
|
|
85
|
+
parameter: string("parameter"),
|
|
86
|
+
detail: string("detail")
|
|
87
|
+
};
|
|
88
|
+
case "ProtocolVersionUnsupported":
|
|
89
|
+
if (field("supported") !== 1 || field("recovery") !== "replay-from-start") throw new TypeError("Invalid protocol recovery");
|
|
90
|
+
return {
|
|
91
|
+
_tag,
|
|
92
|
+
route,
|
|
93
|
+
supported: 1,
|
|
94
|
+
received: string("received"),
|
|
95
|
+
recovery: "replay-from-start"
|
|
96
|
+
};
|
|
97
|
+
case "ResumeRejected": {
|
|
98
|
+
const reason = field("reason");
|
|
99
|
+
if (reason !== "invalid-offset" && reason !== "history-unavailable" && reason !== "contract-changed" || field("recovery") !== "replay-from-start") throw new TypeError("Invalid resume recovery");
|
|
100
|
+
return {
|
|
101
|
+
_tag,
|
|
102
|
+
route,
|
|
103
|
+
reason,
|
|
104
|
+
recovery: "replay-from-start"
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
case "ContractChanged":
|
|
108
|
+
if (field("recovery") !== "refetch") throw new TypeError("Invalid refetch recovery");
|
|
109
|
+
return {
|
|
110
|
+
_tag,
|
|
111
|
+
route,
|
|
112
|
+
recovery: "refetch"
|
|
113
|
+
};
|
|
114
|
+
case "TransportUnavailable":
|
|
115
|
+
case "WireEncodeFailed": return {
|
|
116
|
+
_tag,
|
|
117
|
+
route,
|
|
118
|
+
detail: string("detail")
|
|
119
|
+
};
|
|
120
|
+
default: throw new TypeError("Unknown public error tag");
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
//#endregion
|
|
124
|
+
export { DURABLE_STATE_PROTOCOL, PUBLIC_ERROR_TAGS, STATE_CONTRACT_HEADER, STATE_VERSION_HEADER, STREAM_CONTRACT_HEADER, STREAM_VERSION_HEADER, VALUE_CONTRACT_HEADER, canonicalJson, contractFingerprint, decodePublicError, valueEtag };
|
package/dist/deno.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Duration, Effect } from "effect";
|
|
2
|
+
//#region src/deno.d.ts
|
|
3
|
+
export declare const DEFAULT_PORT = 3000;
|
|
4
|
+
export declare const DEFAULT_HOSTNAME = "127.0.0.1";
|
|
5
|
+
export interface ListenerOptions {
|
|
6
|
+
readonly port?: number;
|
|
7
|
+
readonly hostname?: string;
|
|
8
|
+
readonly gracefulShutdownTimeout?: Duration.Input;
|
|
9
|
+
}
|
|
10
|
+
/** The Deno listener for a Streamsy host. */
|
|
11
|
+
export declare const listener: (options?: ListenerOptions) => import("effect/Layer").Layer<import("effect/http/Etag").Generator | import("effect/http/HttpPlatform").HttpPlatform | import("effect/http/HttpServer").HttpServer | import("@effect/platform-deno/DenoServices").DenoServices, import("effect/http/HttpServerError").ServeError, never>;
|
|
12
|
+
/**
|
|
13
|
+
* Lets `@effect/sql-sqlite-node` open a database on Deno.
|
|
14
|
+
*
|
|
15
|
+
* The driver calls `enableLoadExtension(false)` on every open. Deno's
|
|
16
|
+
* `node:sqlite` `DatabaseSync` has no such method, so the open throws. This
|
|
17
|
+
* adds a no-op method when it is missing and leaves a runtime that has it
|
|
18
|
+
* alone. Run it before the first `SqliteClient.make`:
|
|
19
|
+
*
|
|
20
|
+
* ```ts
|
|
21
|
+
* const client = Deno.nodeSqliteCompat.pipe(
|
|
22
|
+
* Effect.andThen(SqliteClient.make({ filename })),
|
|
23
|
+
* );
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare const nodeSqliteCompat: Effect.Effect<void>;
|
|
27
|
+
//#endregion
|
package/dist/deno.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { DenoHttpServer } from "@effect/platform-deno";
|
|
3
|
+
//#region src/deno.ts
|
|
4
|
+
const DEFAULT_PORT = 3e3;
|
|
5
|
+
const DEFAULT_HOSTNAME = "127.0.0.1";
|
|
6
|
+
const listenerOptions = (options) => ({
|
|
7
|
+
port: options.port ?? 3e3,
|
|
8
|
+
hostname: options.hostname ?? "127.0.0.1",
|
|
9
|
+
...options.gracefulShutdownTimeout === void 0 ? { disablePreemptiveShutdown: true } : { gracefulShutdownTimeout: options.gracefulShutdownTimeout }
|
|
10
|
+
});
|
|
11
|
+
/** The Deno listener for a Streamsy host. */
|
|
12
|
+
const listener = (options = {}) => DenoHttpServer.layer(listenerOptions(options));
|
|
13
|
+
/**
|
|
14
|
+
* Lets `@effect/sql-sqlite-node` open a database on Deno.
|
|
15
|
+
*
|
|
16
|
+
* The driver calls `enableLoadExtension(false)` on every open. Deno's
|
|
17
|
+
* `node:sqlite` `DatabaseSync` has no such method, so the open throws. This
|
|
18
|
+
* adds a no-op method when it is missing and leaves a runtime that has it
|
|
19
|
+
* alone. Run it before the first `SqliteClient.make`:
|
|
20
|
+
*
|
|
21
|
+
* ```ts
|
|
22
|
+
* const client = Deno.nodeSqliteCompat.pipe(
|
|
23
|
+
* Effect.andThen(SqliteClient.make({ filename })),
|
|
24
|
+
* );
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
const nodeSqliteCompat = Effect.promise(() => import("node:sqlite")).pipe(Effect.flatMap(({ DatabaseSync }) => Effect.sync(() => {
|
|
28
|
+
const prototype = DatabaseSync.prototype;
|
|
29
|
+
if (prototype.enableLoadExtension === void 0) prototype.enableLoadExtension = () => {};
|
|
30
|
+
})));
|
|
31
|
+
//#endregion
|
|
32
|
+
export { DEFAULT_HOSTNAME, DEFAULT_PORT, listener, nodeSqliteCompat };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { t as CanonicalValue } from "./contract-BUWJ-Sy2.js";
|
|
2
|
+
import { Duration, Effect, Layer, Runtime, Schema } from "effect";
|
|
3
|
+
import { HttpRouter, HttpServerRequest, HttpServerRespondable, HttpServerResponse } from "effect/http";
|
|
4
|
+
import { Http, StreamAddress, Streamsy } from "@streamsy/core";
|
|
5
|
+
import { StreamRoute } from "@streamsy/core/protocol";
|
|
6
|
+
import { ShutdownSignal } from "@streamsy/core/http";
|
|
7
|
+
//#region src/errors.d.ts
|
|
8
|
+
/** The public error body. `cases` gives one validating constructor per tag. */
|
|
9
|
+
export declare const PublicErrorSchema: Schema.TaggedUnion<{
|
|
10
|
+
readonly ContractChanged: Schema.TaggedStruct<"ContractChanged", {
|
|
11
|
+
readonly route: Schema.String;
|
|
12
|
+
readonly recovery: Schema.Literal<"refetch">;
|
|
13
|
+
}>;
|
|
14
|
+
readonly InvalidParams: Schema.TaggedStruct<"InvalidParams", {
|
|
15
|
+
readonly route: Schema.String;
|
|
16
|
+
readonly parameter: Schema.String;
|
|
17
|
+
readonly detail: Schema.String;
|
|
18
|
+
}>;
|
|
19
|
+
readonly ProtocolVersionUnsupported: Schema.TaggedStruct<"ProtocolVersionUnsupported", {
|
|
20
|
+
readonly route: Schema.String;
|
|
21
|
+
readonly supported: Schema.Literal<1>;
|
|
22
|
+
readonly received: Schema.String;
|
|
23
|
+
readonly recovery: Schema.Literal<"replay-from-start">;
|
|
24
|
+
}>;
|
|
25
|
+
readonly ResumeRejected: Schema.TaggedStruct<"ResumeRejected", {
|
|
26
|
+
readonly route: Schema.String;
|
|
27
|
+
readonly reason: Schema.Literals<readonly ["invalid-offset", "history-unavailable", "contract-changed"]>;
|
|
28
|
+
readonly recovery: Schema.Literal<"replay-from-start">;
|
|
29
|
+
}>;
|
|
30
|
+
readonly TransportUnavailable: Schema.TaggedStruct<"TransportUnavailable", {
|
|
31
|
+
readonly route: Schema.String;
|
|
32
|
+
readonly detail: Schema.String;
|
|
33
|
+
}>;
|
|
34
|
+
readonly WireEncodeFailed: Schema.TaggedStruct<"WireEncodeFailed", {
|
|
35
|
+
readonly route: Schema.String;
|
|
36
|
+
readonly detail: Schema.String;
|
|
37
|
+
}>;
|
|
38
|
+
}>;
|
|
39
|
+
declare const InvalidParams_base: Schema.Class<InvalidParams, Schema.TaggedStruct<"InvalidParams", {
|
|
40
|
+
readonly _tag: Schema.tag<"InvalidParams">;
|
|
41
|
+
readonly route: Schema.String;
|
|
42
|
+
readonly parameter: Schema.String;
|
|
43
|
+
readonly detail: Schema.String;
|
|
44
|
+
}>, import("effect/Cause").YieldableError>;
|
|
45
|
+
declare class InvalidParams extends InvalidParams_base {
|
|
46
|
+
responseHeaders: Readonly<Record<string, string>>;
|
|
47
|
+
[HttpServerRespondable.symbol](): Effect.Effect<HttpServerResponse.HttpServerResponse, never, never>;
|
|
48
|
+
}
|
|
49
|
+
declare const ProtocolVersionUnsupported_base: Schema.Class<ProtocolVersionUnsupported, Schema.TaggedStruct<"ProtocolVersionUnsupported", {
|
|
50
|
+
readonly _tag: Schema.tag<"ProtocolVersionUnsupported">;
|
|
51
|
+
readonly route: Schema.String;
|
|
52
|
+
readonly supported: Schema.Literal<1>;
|
|
53
|
+
readonly received: Schema.String;
|
|
54
|
+
readonly recovery: Schema.Literal<"replay-from-start">;
|
|
55
|
+
}>, import("effect/Cause").YieldableError>;
|
|
56
|
+
declare class ProtocolVersionUnsupported extends ProtocolVersionUnsupported_base {
|
|
57
|
+
responseHeaders: Readonly<Record<string, string>>;
|
|
58
|
+
[HttpServerRespondable.symbol](): Effect.Effect<HttpServerResponse.HttpServerResponse, never, never>;
|
|
59
|
+
}
|
|
60
|
+
declare const ResumeRejected_base: Schema.Class<ResumeRejected, Schema.TaggedStruct<"ResumeRejected", {
|
|
61
|
+
readonly _tag: Schema.tag<"ResumeRejected">;
|
|
62
|
+
readonly route: Schema.String;
|
|
63
|
+
readonly reason: Schema.Literals<readonly ["invalid-offset", "history-unavailable", "contract-changed"]>;
|
|
64
|
+
readonly recovery: Schema.Literal<"replay-from-start">;
|
|
65
|
+
}>, import("effect/Cause").YieldableError>;
|
|
66
|
+
declare class ResumeRejected extends ResumeRejected_base {
|
|
67
|
+
responseHeaders: Readonly<Record<string, string>>;
|
|
68
|
+
[HttpServerRespondable.symbol](): Effect.Effect<HttpServerResponse.HttpServerResponse, never, never>;
|
|
69
|
+
}
|
|
70
|
+
declare const ContractChanged_base: Schema.Class<ContractChanged, Schema.TaggedStruct<"ContractChanged", {
|
|
71
|
+
readonly _tag: Schema.tag<"ContractChanged">;
|
|
72
|
+
readonly route: Schema.String;
|
|
73
|
+
readonly recovery: Schema.Literal<"refetch">;
|
|
74
|
+
}>, import("effect/Cause").YieldableError>;
|
|
75
|
+
declare class ContractChanged extends ContractChanged_base {
|
|
76
|
+
responseHeaders: Readonly<Record<string, string>>;
|
|
77
|
+
[HttpServerRespondable.symbol](): Effect.Effect<HttpServerResponse.HttpServerResponse, never, never>;
|
|
78
|
+
}
|
|
79
|
+
declare const TransportUnavailable_base: Schema.Class<TransportUnavailable, Schema.TaggedStruct<"TransportUnavailable", {
|
|
80
|
+
readonly _tag: Schema.tag<"TransportUnavailable">;
|
|
81
|
+
readonly route: Schema.String;
|
|
82
|
+
readonly detail: Schema.String;
|
|
83
|
+
}>, import("effect/Cause").YieldableError>;
|
|
84
|
+
declare class TransportUnavailable extends TransportUnavailable_base {
|
|
85
|
+
responseHeaders: Readonly<Record<string, string>>;
|
|
86
|
+
[HttpServerRespondable.symbol](): Effect.Effect<HttpServerResponse.HttpServerResponse, never, never>;
|
|
87
|
+
}
|
|
88
|
+
declare const WireEncodeFailed_base: Schema.Class<WireEncodeFailed, Schema.TaggedStruct<"WireEncodeFailed", {
|
|
89
|
+
readonly _tag: Schema.tag<"WireEncodeFailed">;
|
|
90
|
+
readonly route: Schema.String;
|
|
91
|
+
readonly detail: Schema.String;
|
|
92
|
+
}>, import("effect/Cause").YieldableError>;
|
|
93
|
+
declare class WireEncodeFailed extends WireEncodeFailed_base {
|
|
94
|
+
responseHeaders: Readonly<Record<string, string>>;
|
|
95
|
+
[HttpServerRespondable.symbol](): Effect.Effect<HttpServerResponse.HttpServerResponse, never, never>;
|
|
96
|
+
}
|
|
97
|
+
type ServeError = InvalidParams | ProtocolVersionUnsupported | ResumeRejected | ContractChanged | TransportUnavailable | WireEncodeFailed;
|
|
98
|
+
//#endregion
|
|
99
|
+
//#region src/host.d.ts
|
|
100
|
+
type DefaultServeRequires<R> = HttpRouter.Request.Only<"Requires", R> | HttpRouter.Request.Only<"GlobalRequires", R>;
|
|
101
|
+
/** The options of `HttpRouter.serve`, plus the drain bound. */
|
|
102
|
+
type LayerOptions<R = never, HE = never, HR = DefaultServeRequires<R>> = NonNullable<Parameters<typeof HttpRouter.serve<unknown, unknown, R, HE, HR>>[1]> & {
|
|
103
|
+
/** Upper bound on the wait for live reads to finish; default 2 seconds. */
|
|
104
|
+
readonly drainTimeout?: Duration.Input | undefined;
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* `HttpRouter.serve` with the Streamsy drain applied in the only correct place.
|
|
108
|
+
*
|
|
109
|
+
* Before the serve layer closes, the drain signals every live read: a parked
|
|
110
|
+
* long poll answers `204` with its offset and cursor, and an open SSE body ends
|
|
111
|
+
* after its last whole batch. It then waits until no live read is running, or
|
|
112
|
+
* `drainTimeout` passes. After that the serve layer interrupts any handler that
|
|
113
|
+
* is still running.
|
|
114
|
+
*
|
|
115
|
+
* The host provides storage, the listener and the Effect main:
|
|
116
|
+
*
|
|
117
|
+
* ```ts
|
|
118
|
+
* const Server = Serve.layer(routes).pipe(
|
|
119
|
+
* Layer.provide(MemoryStorage.layer(streams)),
|
|
120
|
+
* Layer.provide(listener()),
|
|
121
|
+
* );
|
|
122
|
+
* BunRuntime.runMain(Layer.launch(Server), { teardown: Serve.teardown });
|
|
123
|
+
* ```
|
|
124
|
+
*/
|
|
125
|
+
declare const layer: <A, E, R, HE = never, HR = DefaultServeRequires<R>>(routes: Layer.Layer<A, E, R>, options?: LayerOptions<R, HE, HR>) => Layer.Layer<A, HttpRouter.Request.Without<E>, import("effect/http/HttpServer").HttpServer | Exclude<Exclude<Exclude<HR, HttpRouter.GlobalProvided>, HttpRouter.HttpRouter>, ShutdownSignal> | Exclude<Exclude<HttpRouter.Request.Without<R>, HttpRouter.HttpRouter>, ShutdownSignal>>;
|
|
126
|
+
/**
|
|
127
|
+
* Exit policy for a long-running Streamsy host after `Serve.layer` drains.
|
|
128
|
+
* Pass it to the runtime's `runMain` as `{ teardown: Serve.teardown }`.
|
|
129
|
+
*
|
|
130
|
+
* An exit that holds only interrupts maps to 0: after the drain, an interrupt
|
|
131
|
+
* from `SIGINT` or `SIGTERM` is the normal way for the server to stop. Every
|
|
132
|
+
* other exit uses `Runtime.defaultTeardown`, so a startup failure stays
|
|
133
|
+
* non-zero. Any interrupt-only exit maps to 0, including one that no signal
|
|
134
|
+
* caused. In a `Layer.launch` main the fiber ends only on failure or a signal.
|
|
135
|
+
*/
|
|
136
|
+
declare const teardown: Runtime.Teardown;
|
|
137
|
+
declare namespace serve_d_exports {
|
|
138
|
+
export { ContractChanged, InvalidParams, LayerOptions, ProtocolVersionUnsupported, ReadOptions, ResumeRejected, ServeError, TransportUnavailable, ValueOptions, WireEncodeFailed, layer, mount, params, route, state, stream, teardown, value };
|
|
139
|
+
}
|
|
140
|
+
type Names<S extends string> = S extends `${string}:${infer N}/${infer Tail}` ? N | Names<Tail> : S extends `${string}:${infer N}` ? N : never;
|
|
141
|
+
type ExactPath<Path extends string, P> = `/${string}` extends Path ? unknown : [Exclude<Names<Path>, keyof P>, Exclude<keyof P, Names<Path>>] extends [never, never] ? unknown : never;
|
|
142
|
+
interface ReadOptions extends Http.ReadOptions {
|
|
143
|
+
readonly contract?: CanonicalValue;
|
|
144
|
+
}
|
|
145
|
+
/** Decode the matched route's parameters with the stream's codecs. */
|
|
146
|
+
declare const params: <P>(declaration: {
|
|
147
|
+
readonly paramSchema: StreamRoute.PathSchema<P>;
|
|
148
|
+
}) => Effect.Effect<P, InvalidParams, HttpRouter.RouteContext>;
|
|
149
|
+
/** Own every method at this path, including beneath protocol wildcard routes. */
|
|
150
|
+
declare function route<E, R>(path: HttpRouter.PathInput, handler: Effect.Effect<HttpServerResponse.HttpServerResponse, E, R>): import("effect/Layer").Layer<never, never, HttpRouter.HttpRouter | HttpRouter.Request.From<"Error", E> | HttpRouter.Request.From<"Requires", Exclude<R, HttpRouter.Provided>>>;
|
|
151
|
+
/** Mount one declared stream; state addresses select the Durable State contract. */
|
|
152
|
+
declare function mount<P, A, K, RD, RE, const Path extends `/${string}`>(declaration: {
|
|
153
|
+
readonly paramSchema: StreamRoute.PathSchema<P>;
|
|
154
|
+
readonly at: (params: P) => Streamsy.Address<A, K, RD, RE>;
|
|
155
|
+
}, path: Path & ExactPath<Path, NoInfer<P>>, options?: ReadOptions): import("effect/Layer").Layer<never, never, HttpRouter.HttpRouter | HttpRouter.Request<"Error", InvalidParams> | HttpRouter.Request<"Error", ProtocolVersionUnsupported> | HttpRouter.Request<"Error", ResumeRejected> | HttpRouter.Request<"Error", TransportUnavailable> | HttpRouter.Request<"Error", WireEncodeFailed> | HttpRouter.Request.From<"Requires", Exclude<K, HttpRouter.Provided>>>;
|
|
156
|
+
/** Durable Streams response for one resolved address. */
|
|
157
|
+
declare function stream<A, K, RD, RE>(address: Streamsy.Address<A, K, RD, RE>, options?: ReadOptions): Effect.Effect<HttpServerResponse.HttpServerResponse, ProtocolVersionUnsupported | ResumeRejected | TransportUnavailable | WireEncodeFailed, K | HttpServerRequest.HttpServerRequest | HttpRouter.RouteContext>;
|
|
158
|
+
/** Durable State change response with replay-from-start recovery. */
|
|
159
|
+
declare function state<C extends StreamAddress.Collections, K, RD, RE>(address: StreamAddress.StateAddress<C, RD, RE> & Streamsy.Address<StreamAddress.CollectionsChange<C>, K, RD, RE>, options?: ReadOptions): Effect.Effect<HttpServerResponse.HttpServerResponse, ProtocolVersionUnsupported | ResumeRejected | TransportUnavailable | WireEncodeFailed, K | HttpServerRequest.HttpServerRequest | HttpRouter.RouteContext>;
|
|
160
|
+
interface ValueOptions {
|
|
161
|
+
readonly cache?: {
|
|
162
|
+
readonly visibility: "private" | "public";
|
|
163
|
+
readonly maxAgeSeconds: number;
|
|
164
|
+
readonly mustRevalidate: boolean;
|
|
165
|
+
};
|
|
166
|
+
readonly contract?: CanonicalValue;
|
|
167
|
+
}
|
|
168
|
+
/** Canonical JSON response for any computation, including mapped projection state. */
|
|
169
|
+
declare const value: <A, I extends CanonicalValue, E, R, RE>(schema: Schema.Codec<A, I, never, RE>, compute: Effect.Effect<A, E, R>, options?: ValueOptions | undefined) => Effect.Effect<HttpServerResponse.HttpServerResponse, E | ContractChanged | WireEncodeFailed, R | RE | HttpServerRequest.HttpServerRequest | HttpRouter.RouteContext>;
|
|
170
|
+
//#endregion
|
|
171
|
+
export { serve_d_exports as Serve };
|