stitchkit 0.103.12 → 0.104.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/CHANGELOG.md +112 -0
- package/darwin-native.cjs +12 -0
- package/darwin-native.d.cts +2 -0
- package/dist/agent-runtime/store-conformance-lifecycle.d.ts +10 -10
- package/dist/application/directory-inbox-accept.d.ts +13 -0
- package/dist/application/directory-inbox-accept.d.ts.map +1 -0
- package/dist/application/directory-inbox-contract.d.ts +42 -5
- package/dist/application/directory-inbox-contract.d.ts.map +1 -1
- package/dist/application/directory-inbox-delivery.d.ts +14 -0
- package/dist/application/directory-inbox-delivery.d.ts.map +1 -0
- package/dist/application/directory-inbox-files.d.ts +28 -0
- package/dist/application/directory-inbox-files.d.ts.map +1 -0
- package/dist/application/directory-inbox-state.d.ts +14 -0
- package/dist/application/directory-inbox-state.d.ts.map +1 -0
- package/dist/application/directory-inbox.d.ts +2 -1
- package/dist/application/directory-inbox.d.ts.map +1 -1
- package/dist/application/file-state-store.d.ts +2 -8
- package/dist/application/file-state-store.d.ts.map +1 -1
- package/dist/application/state-store.d.ts +6 -1
- package/dist/application/state-store.d.ts.map +1 -1
- package/dist/browser/client-arguments.d.ts +4 -0
- package/dist/browser/client-arguments.d.ts.map +1 -0
- package/dist/browser/client-executors.d.ts.map +1 -1
- package/dist/browser/client.d.ts.map +1 -1
- package/dist/browser/contract-stream.d.ts.map +1 -1
- package/dist/browser/http.d.ts +2 -1
- package/dist/browser/http.d.ts.map +1 -1
- package/dist/browser/native-fetch.d.ts +8 -0
- package/dist/browser/native-fetch.d.ts.map +1 -0
- package/dist/contract/errors.d.ts +16 -12
- package/dist/contract/errors.d.ts.map +1 -1
- package/dist/contract/normalize.d.ts +5 -1
- package/dist/contract/normalize.d.ts.map +1 -1
- package/dist/contract/stream.d.ts +1 -0
- package/dist/contract/stream.d.ts.map +1 -1
- package/dist/entrypoints/agent-runtime/browser.js +3 -3
- package/dist/entrypoints/agent-runtime/coding-tools.js +8 -6
- package/dist/entrypoints/agent-runtime/harness-tools.js +8 -8
- package/dist/entrypoints/agent-runtime/harness.js +12 -11
- package/dist/entrypoints/agent-runtime/realtime.js +3 -3
- package/dist/entrypoints/agent-runtime/sandbox.js +8 -6
- package/dist/entrypoints/agent-runtime.js +13 -13
- package/dist/entrypoints/application/diagnostic-journal.js +3 -2
- package/dist/entrypoints/application/directory-inbox.js +424 -119
- package/dist/entrypoints/application/grammy.js +1 -1
- package/dist/entrypoints/application.d.ts +2 -2
- package/dist/entrypoints/application.d.ts.map +1 -1
- package/dist/entrypoints/application.js +7 -3
- package/dist/entrypoints/cli.d.ts +2 -0
- package/dist/entrypoints/cli.d.ts.map +1 -1
- package/dist/entrypoints/cli.js +757 -136
- package/dist/entrypoints/contract.js +3 -3
- package/dist/entrypoints/files.js +11 -107
- package/dist/entrypoints/index.js +7 -7
- package/dist/entrypoints/node.js +8 -8
- package/dist/entrypoints/observability.js +2 -2
- package/dist/entrypoints/process.js +2 -1
- package/dist/entrypoints/react.js +1 -1
- package/dist/entrypoints/remote.js +19 -6
- package/dist/entrypoints/server.d.ts +1 -1
- package/dist/entrypoints/server.d.ts.map +1 -1
- package/dist/entrypoints/server.js +20 -14
- package/dist/entrypoints/telegram.d.ts +1 -0
- package/dist/entrypoints/telegram.d.ts.map +1 -1
- package/dist/entrypoints/telegram.js +214 -98
- package/dist/entrypoints/testing.js +7 -7
- package/dist/entrypoints/tools/connections.d.ts +2 -2
- package/dist/entrypoints/tools/connections.d.ts.map +1 -1
- package/dist/entrypoints/tools/connections.js +427 -294
- package/dist/entrypoints/tools/invoker.js +6 -6
- package/dist/entrypoints/tools/mcp.d.ts +12 -0
- package/dist/entrypoints/tools/mcp.d.ts.map +1 -0
- package/dist/entrypoints/tools/mcp.js +45 -0
- package/dist/entrypoints/tools.d.ts +1 -0
- package/dist/entrypoints/tools.d.ts.map +1 -1
- package/dist/entrypoints/tools.js +82 -1147
- package/dist/entrypoints/tracking.js +1 -1
- package/dist/files/boundary.d.ts +2 -8
- package/dist/files/boundary.d.ts.map +1 -1
- package/dist/files/file-io.d.ts +0 -5
- package/dist/files/file-io.d.ts.map +1 -1
- package/dist/files/read.d.ts +2 -2
- package/dist/files/read.d.ts.map +1 -1
- package/dist/index-1a6jtnd9.js +88 -0
- package/dist/{index-fyphpknh.js → index-22rhg58f.js} +1 -1
- package/dist/index-269zqj8m.js +77 -0
- package/dist/{index-r34mvse1.js → index-27a2pj09.js} +1 -1
- package/dist/{index-r956rndn.js → index-2hyavjjj.js} +3 -3
- package/dist/{index-m2xqkv55.js → index-2vnh05w4.js} +83 -14
- package/dist/{index-pw99k9h5.js → index-43p08g7t.js} +1 -1
- package/dist/{index-xwq9j1sf.js → index-4e0ah203.js} +9 -7
- package/dist/{index-nybn2err.js → index-5csmzesf.js} +1 -1
- package/dist/{index-qapzv4p5.js → index-5z6jn897.js} +1 -1
- package/dist/{index-ahvsksw5.js → index-6d9xaxw1.js} +1 -1
- package/dist/{index-ahtnte39.js → index-6drst9sg.js} +46 -35
- package/dist/{index-x87j7csh.js → index-77nxk6ay.js} +2 -2
- package/dist/{index-dnn9z96q.js → index-a0zzh8ak.js} +3 -3
- package/dist/{index-kmpzj1cq.js → index-a3wma1hk.js} +1 -1
- package/dist/{index-j8aw2c0e.js → index-bakgedh8.js} +35 -7
- package/dist/index-bhb950qs.js +1145 -0
- package/dist/{index-tgzhq07n.js → index-cvda079a.js} +1 -1
- package/dist/{index-n2gre124.js → index-fa4wg312.js} +4 -4
- package/dist/{index-zp4jpkp0.js → index-fk18k56k.js} +2 -2
- package/dist/{index-afjvjyck.js → index-g2j7pnak.js} +2 -134
- package/dist/index-g95fk660.js +116 -0
- package/dist/{index-ej331hah.js → index-gxm9rc97.js} +1 -1
- package/dist/{index-r5c4fedv.js → index-h2fhjqy7.js} +2 -1
- package/dist/{index-sybedc8b.js → index-hbd32c6a.js} +23 -94
- package/dist/index-jd470k6q.js +109 -0
- package/dist/{index-b2bz0kdm.js → index-kb8styz3.js} +4 -3
- package/dist/{index-0c419yx7.js → index-kemm0ej5.js} +12 -9
- package/dist/{index-806d5phm.js → index-ptn0g0gj.js} +7 -7
- package/dist/{index-w575evhq.js → index-r4r70zmh.js} +1 -1
- package/dist/{index-12m2v2a9.js → index-s4evrmp5.js} +1 -1
- package/dist/{index-1khy8y7n.js → index-t1sr4aks.js} +3 -3
- package/dist/index-v5ee8ath.js +88 -0
- package/dist/{index-45tdvqa3.js → index-wh0ecvyk.js} +1 -1
- package/dist/{index-n53mswt3.js → index-x928baz2.js} +8 -1
- package/dist/index-yk4g8805.js +133 -0
- package/dist/{index-ygkka6zn.js → index-ywppsaby.js} +28 -5
- package/dist/{index-xvdd2rbb.js → index-za6j7nwy.js} +19 -5
- package/dist/internal/bounded-file-read.d.ts +41 -0
- package/dist/internal/bounded-file-read.d.ts.map +1 -0
- package/dist/internal/darwin-binding-error.d.ts +24 -0
- package/dist/internal/darwin-binding-error.d.ts.map +1 -0
- package/dist/internal/darwin-binding.d.ts.map +1 -1
- package/dist/internal/exclusive-lock.d.ts +2 -0
- package/dist/internal/exclusive-lock.d.ts.map +1 -1
- package/dist/internal/with-exclusive-lock.d.ts +4 -2
- package/dist/internal/with-exclusive-lock.d.ts.map +1 -1
- package/dist/telegram/broadcast-delivery.d.ts +23 -0
- package/dist/telegram/broadcast-delivery.d.ts.map +1 -0
- package/dist/telegram/broadcast-failure.d.ts +22 -0
- package/dist/telegram/broadcast-failure.d.ts.map +1 -0
- package/dist/telegram/broadcast-state.d.ts +6 -3
- package/dist/telegram/broadcast-state.d.ts.map +1 -1
- package/dist/telegram/broadcast.d.ts +10 -5
- package/dist/telegram/broadcast.d.ts.map +1 -1
- package/dist/tools/cli/args-fields.d.ts +2 -0
- package/dist/tools/cli/args-fields.d.ts.map +1 -1
- package/dist/tools/cli/args.d.ts.map +1 -1
- package/dist/tools/cli/format.d.ts.map +1 -1
- package/dist/tools/cli/invoke.d.ts +2 -2
- package/dist/tools/cli/invoke.d.ts.map +1 -1
- package/dist/tools/cli/publication-assets.d.ts +10 -0
- package/dist/tools/cli/publication-assets.d.ts.map +1 -0
- package/dist/tools/cli/publication-contract.d.ts +75 -0
- package/dist/tools/cli/publication-contract.d.ts.map +1 -0
- package/dist/tools/cli/publication-control.d.ts +4 -0
- package/dist/tools/cli/publication-control.d.ts.map +1 -0
- package/dist/tools/cli/publication-storage.d.ts +32 -0
- package/dist/tools/cli/publication-storage.d.ts.map +1 -0
- package/dist/tools/cli/publication.d.ts +35 -0
- package/dist/tools/cli/publication.d.ts.map +1 -0
- package/dist/tools/cli/update.d.ts.map +1 -1
- package/dist/tools/connections/define.d.ts.map +1 -1
- package/dist/tools/connections/error-projection.d.ts +4 -0
- package/dist/tools/connections/error-projection.d.ts.map +1 -0
- package/dist/tools/connections/errors.d.ts +24 -8
- package/dist/tools/connections/errors.d.ts.map +1 -1
- package/dist/tools/connections/limits.d.ts +11 -31
- package/dist/tools/connections/limits.d.ts.map +1 -1
- package/dist/tools/connections/mcp-client.d.ts +6 -4
- package/dist/tools/connections/mcp-client.d.ts.map +1 -1
- package/dist/tools/connections/mcp.d.ts.map +1 -1
- package/dist/tools/connections/openapi.d.ts.map +1 -1
- package/dist/tools/connections/operation-limits.d.ts +25 -0
- package/dist/tools/connections/operation-limits.d.ts.map +1 -0
- package/dist/tools/connections/sse-frames.d.ts +11 -2
- package/dist/tools/connections/sse-frames.d.ts.map +1 -1
- package/dist/tools/connections/sse-session.d.ts +15 -2
- package/dist/tools/connections/sse-session.d.ts.map +1 -1
- package/dist/tools/connections/types.d.ts +19 -1
- package/dist/tools/connections/types.d.ts.map +1 -1
- package/dist/tools/execute-result.d.ts.map +1 -1
- package/dist/tools/execute.d.ts.map +1 -1
- package/dist/tools/internal/observe-hook.d.ts +3 -0
- package/dist/tools/internal/observe-hook.d.ts.map +1 -0
- package/dist/tools/internal/surface-projector.d.ts +2 -1
- package/dist/tools/internal/surface-projector.d.ts.map +1 -1
- package/dist/tools/mcp/mount.d.ts +2 -2
- package/dist/tools/mcp/mount.d.ts.map +1 -1
- package/dist/tools/mcp/prepare.d.ts +4 -5
- package/dist/tools/mcp/prepare.d.ts.map +1 -1
- package/dist/tools/mcp/register.d.ts +4 -1
- package/dist/tools/mcp/register.d.ts.map +1 -1
- package/dist/tools/mcp/runtime-tools.d.ts.map +1 -1
- package/dist/tools/remote.d.ts.map +1 -1
- package/dist/tools/runtime-tool-execution.d.ts +65 -0
- package/dist/tools/runtime-tool-execution.d.ts.map +1 -0
- package/dist/tools/runtime-tool-mcp.d.ts +27 -0
- package/dist/tools/runtime-tool-mcp.d.ts.map +1 -0
- package/dist/tools/runtime-tool.d.ts +9 -60
- package/dist/tools/runtime-tool.d.ts.map +1 -1
- package/dist/tools/surface.d.ts +12 -14
- package/dist/tools/surface.d.ts.map +1 -1
- package/llms/application.2.txt +221 -44
- package/llms/application.3.txt +3 -1
- package/llms/application.txt +1 -1
- package/llms/cli.2.txt +144 -1
- package/llms/cli.txt +133 -104
- package/llms/contract.txt +1 -1
- package/llms/process.txt +34 -5
- package/llms/server.4.txt +4 -1
- package/llms/server.5.txt +1 -0
- package/llms/stitchkit.2.txt +14 -0
- package/llms/stitchkit.txt +5 -4
- package/llms/telegram.txt +64 -2
- package/llms/tools-connections.txt +3 -0
- package/llms/tools-mcp.txt +29 -0
- package/llms/tools.2.txt +59 -0
- package/llms/tools.3.txt +1 -0
- package/llms/tools.txt +11 -52
- package/llms/upgrading-0.37.0-0.44.0.txt +444 -0
- package/llms/{upgrading-0.44.0-0.60.0.txt → upgrading-0.44.0-0.61.0.txt} +140 -271
- package/llms/{upgrading-0.61.0-0.74.0.txt → upgrading-0.62.0-0.79.0.txt} +171 -140
- package/llms/{upgrading-0.75.0-0.103.0.txt → upgrading-0.80.0-0.104.0.txt} +120 -171
- package/llms/upgrading.txt +4 -4
- package/llms-full.txt +677 -64
- package/llms.txt +13 -12
- package/package.json +10 -1
- package/dist/index-d4pa2bgs.js +0 -42
- package/dist/index-wykebpn9.js +0 -221
- package/llms/upgrading-0.37.0.txt +0 -176
- package/dist/{index-69nvze1q.js → index-pptyv13k.js} +3 -3
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AppError2
|
|
3
|
-
} from "./index-
|
|
3
|
+
} from "./index-x928baz2.js";
|
|
4
4
|
import {
|
|
5
5
|
toolErrorFromResult
|
|
6
|
-
} from "./index-
|
|
6
|
+
} from "./index-2vnh05w4.js";
|
|
7
7
|
import {
|
|
8
8
|
assertUniqueToolName
|
|
9
|
-
} from "./index-
|
|
9
|
+
} from "./index-77nxk6ay.js";
|
|
10
10
|
import {
|
|
11
11
|
collectTools2,
|
|
12
12
|
createToolRunner
|
|
13
|
-
} from "./index-
|
|
13
|
+
} from "./index-2hyavjjj.js";
|
|
14
14
|
|
|
15
15
|
// src/tools/invoker.ts
|
|
16
16
|
function createToolInvoker2(services, config) {
|
|
@@ -14,13 +14,13 @@ import {
|
|
|
14
14
|
import {
|
|
15
15
|
ToolExecutionControlError2,
|
|
16
16
|
isToolExecutionControlError2
|
|
17
|
-
} from "./index-
|
|
17
|
+
} from "./index-2vnh05w4.js";
|
|
18
18
|
import {
|
|
19
19
|
agentDurableEventId2
|
|
20
20
|
} from "./index-mnkk1ffz.js";
|
|
21
21
|
import {
|
|
22
22
|
createLocalStepDurability2
|
|
23
|
-
} from "./index-
|
|
23
|
+
} from "./index-pptyv13k.js";
|
|
24
24
|
import {
|
|
25
25
|
isAgentToolError2,
|
|
26
26
|
createToolDurabilityContext
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AppError2
|
|
3
|
-
} from "./index-
|
|
3
|
+
} from "./index-x928baz2.js";
|
|
4
4
|
import {
|
|
5
5
|
contractMethodFields
|
|
6
6
|
} from "./index-1bx1xv1k.js";
|
|
@@ -9,109 +9,6 @@ import {
|
|
|
9
9
|
callRuntimeHandler
|
|
10
10
|
} from "./index-9jfdm5tg.js";
|
|
11
11
|
|
|
12
|
-
// src/server/middleware/cors.ts
|
|
13
|
-
var DEFAULT_CORS_ALLOW_HEADERS2 = "Content-Type, Authorization, X-Trace-Id, traceparent, tracestate";
|
|
14
|
-
var DEFAULT_CORS_EXPOSE_HEADERS2 = "Content-Disposition, Content-Length, Content-Range, Accept-Ranges, ETag, Last-Modified, X-Request-Id, X-Build-Id";
|
|
15
|
-
function assertCorsConfig(config) {
|
|
16
|
-
if (config.credentials && (config.origin === undefined || config.origin === "*")) {
|
|
17
|
-
throw new Error("[stitchkit] cors: `credentials: true` cannot be combined with a wildcard origin. " + "Set `origin` to an explicit string or list.");
|
|
18
|
-
}
|
|
19
|
-
if (config.origin === undefined) {
|
|
20
|
-
throw new Error("[stitchkit] cors: `origin` is required. Pass an explicit origin (or list), or '*' to deliberately allow every origin — omit `cors` entirely to emit no CORS headers.");
|
|
21
|
-
}
|
|
22
|
-
if (Array.isArray(config.origin) && config.origin.length === 0) {
|
|
23
|
-
throw new Error("[stitchkit] cors: `origin` cannot be an empty list. Pass explicit origins, or '*' to deliberately allow every origin.");
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
function resolveOrigin(config, requestOrigin) {
|
|
27
|
-
if (config.origin === undefined)
|
|
28
|
-
return;
|
|
29
|
-
if (config.origin === "*") {
|
|
30
|
-
return "*";
|
|
31
|
-
}
|
|
32
|
-
if (Array.isArray(config.origin)) {
|
|
33
|
-
if (!requestOrigin)
|
|
34
|
-
return;
|
|
35
|
-
const lower = requestOrigin.toLowerCase();
|
|
36
|
-
return config.origin.some((o) => o.toLowerCase() === lower) ? requestOrigin : undefined;
|
|
37
|
-
}
|
|
38
|
-
return config.origin;
|
|
39
|
-
}
|
|
40
|
-
function isOriginAllowed(config, requestOrigin) {
|
|
41
|
-
if (!config || config.origin === undefined || config.origin === "*")
|
|
42
|
-
return false;
|
|
43
|
-
if (!requestOrigin || requestOrigin === "null")
|
|
44
|
-
return false;
|
|
45
|
-
const lower = requestOrigin.toLowerCase();
|
|
46
|
-
const allowed = Array.isArray(config.origin) ? config.origin : [config.origin];
|
|
47
|
-
return allowed.some((origin) => origin.toLowerCase() === lower);
|
|
48
|
-
}
|
|
49
|
-
function corsHeaders2(config, requestOrigin) {
|
|
50
|
-
const allowOrigin = resolveOrigin(config, requestOrigin);
|
|
51
|
-
const headers = {
|
|
52
|
-
"Access-Control-Allow-Methods": config.methods ?? "GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS",
|
|
53
|
-
"Access-Control-Allow-Headers": config.headers ?? DEFAULT_CORS_ALLOW_HEADERS2
|
|
54
|
-
};
|
|
55
|
-
const expose = Array.isArray(config.exposeHeaders) ? config.exposeHeaders.join(", ") : config.exposeHeaders ?? DEFAULT_CORS_EXPOSE_HEADERS2;
|
|
56
|
-
if (expose !== "") {
|
|
57
|
-
headers["Access-Control-Expose-Headers"] = expose;
|
|
58
|
-
}
|
|
59
|
-
if (allowOrigin !== undefined) {
|
|
60
|
-
headers["Access-Control-Allow-Origin"] = allowOrigin;
|
|
61
|
-
if (config.credentials) {
|
|
62
|
-
headers["Access-Control-Allow-Credentials"] = "true";
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
if (Array.isArray(config.origin)) {
|
|
66
|
-
headers.Vary = "Origin";
|
|
67
|
-
}
|
|
68
|
-
return headers;
|
|
69
|
-
}
|
|
70
|
-
function corsPreflightResponse2(config, req) {
|
|
71
|
-
return new Response(null, {
|
|
72
|
-
status: 204,
|
|
73
|
-
headers: corsHeaders2(config, req.headers.get("origin"))
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
function requestCorsHeaders(cors, req) {
|
|
77
|
-
if (!cors)
|
|
78
|
-
return {};
|
|
79
|
-
return corsHeaders2(cors, req.headers.get("origin"));
|
|
80
|
-
}
|
|
81
|
-
function applyCors(res, cors, req) {
|
|
82
|
-
const extra = requestCorsHeaders(cors, req);
|
|
83
|
-
if (Object.keys(extra).length === 0)
|
|
84
|
-
return res;
|
|
85
|
-
try {
|
|
86
|
-
for (const [key, value] of Object.entries(extra))
|
|
87
|
-
setCorsHeader(res.headers, key, value);
|
|
88
|
-
return res;
|
|
89
|
-
} catch {
|
|
90
|
-
const headers = new Headers(res.headers);
|
|
91
|
-
for (const [key, value] of Object.entries(extra))
|
|
92
|
-
setCorsHeader(headers, key, value);
|
|
93
|
-
return new Response(res.body, {
|
|
94
|
-
status: res.status,
|
|
95
|
-
statusText: res.statusText,
|
|
96
|
-
headers
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
function setCorsHeader(headers, key, value) {
|
|
101
|
-
if (key !== "Vary") {
|
|
102
|
-
headers.set(key, value);
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
const existing = headers.get("Vary");
|
|
106
|
-
if (existing === null || existing.trim() === "") {
|
|
107
|
-
headers.set("Vary", value);
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
const present = existing.split(",").some((field) => field.trim().toLowerCase() === "origin");
|
|
111
|
-
if (!present)
|
|
112
|
-
headers.set("Vary", `${existing}, ${value}`);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
12
|
// src/server/implement.ts
|
|
116
13
|
function isStreamingImplementation(value) {
|
|
117
14
|
return typeof value === "object" && value !== null && "kind" in value && value.kind === "stitchkit.multipart.stream";
|
|
@@ -229,38 +126,9 @@ function createScopedImplement2() {
|
|
|
229
126
|
return Object.assign(implementScoped, { stream, declare });
|
|
230
127
|
}
|
|
231
128
|
|
|
232
|
-
// src/server/process-signal-common.ts
|
|
233
|
-
var DEFAULT_PROCESS_SIGNALS = ["SIGINT", "SIGTERM"];
|
|
234
|
-
var defaultSignalSource = {
|
|
235
|
-
on: (signal, handler) => {
|
|
236
|
-
process.on(signal, handler);
|
|
237
|
-
},
|
|
238
|
-
off: (signal, handler) => {
|
|
239
|
-
process.off(signal, handler);
|
|
240
|
-
},
|
|
241
|
-
raiseDefault: (signal) => {
|
|
242
|
-
if (process.listenerCount(signal) > 0)
|
|
243
|
-
return false;
|
|
244
|
-
process.kill(process.pid, signal);
|
|
245
|
-
return true;
|
|
246
|
-
}
|
|
247
|
-
};
|
|
248
|
-
function reportSignalError(phase, error, onError) {
|
|
249
|
-
try {
|
|
250
|
-
onError?.(phase, error);
|
|
251
|
-
} catch {}
|
|
252
|
-
}
|
|
253
|
-
function guardSignalCallback(run, phase, onError) {
|
|
254
|
-
try {
|
|
255
|
-
run();
|
|
256
|
-
} catch (error) {
|
|
257
|
-
reportSignalError(phase, error, onError);
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
129
|
// src/internal/media-type.ts
|
|
262
130
|
function mediaTypeEssence(contentType) {
|
|
263
131
|
return (contentType ?? "").split(";", 1)[0]?.trim().toLowerCase() ?? "";
|
|
264
132
|
}
|
|
265
133
|
|
|
266
|
-
export {
|
|
134
|
+
export { defineMultipartStream2, createMultipartStream2, contractOnlyService, bindContract, implement2, createImplement2, createScopedImplement2, mediaTypeEssence };
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import {
|
|
2
|
+
attemptExclusiveLock
|
|
3
|
+
} from "./index-za6j7nwy.js";
|
|
4
|
+
|
|
5
|
+
// src/internal/with-exclusive-lock.ts
|
|
6
|
+
class ExclusiveLockError2 extends Error {
|
|
7
|
+
code;
|
|
8
|
+
label;
|
|
9
|
+
holder;
|
|
10
|
+
name = "ExclusiveLockError";
|
|
11
|
+
constructor(code, label, holder, message, options) {
|
|
12
|
+
super(message, options);
|
|
13
|
+
this.code = code;
|
|
14
|
+
this.label = label;
|
|
15
|
+
this.holder = holder;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
var DEFAULT_TIMEOUT_MS = 1e4;
|
|
19
|
+
var DEFAULT_OWNERLESS_GRACE_MS = 5000;
|
|
20
|
+
var FIRST_RETRY_MS = 10;
|
|
21
|
+
var MAX_RETRY_MS = 100;
|
|
22
|
+
function nonNegative(name, value, fallback) {
|
|
23
|
+
if (value === undefined)
|
|
24
|
+
return fallback;
|
|
25
|
+
if (!Number.isFinite(value) || value < 0) {
|
|
26
|
+
throw new RangeError(`[stitchkit] withExclusiveLock: ${name} must be a finite number ≥ 0`);
|
|
27
|
+
}
|
|
28
|
+
return value;
|
|
29
|
+
}
|
|
30
|
+
function describeHolder(holder) {
|
|
31
|
+
if (!holder)
|
|
32
|
+
return "a holder that recorded no owner";
|
|
33
|
+
const machine = holder.machine === undefined ? "" : `, machine ${holder.machine}`;
|
|
34
|
+
return `pid ${holder.pid} on ${holder.host}${machine} since ${holder.acquiredAt}`;
|
|
35
|
+
}
|
|
36
|
+
function describeEvidence(diagnosis) {
|
|
37
|
+
if (!diagnosis)
|
|
38
|
+
return "";
|
|
39
|
+
const identity = diagnosis.identity === undefined ? "" : `, identity ${diagnosis.identity}`;
|
|
40
|
+
return ` (${diagnosis.attribution}, liveness ${diagnosis.liveness}${identity})`;
|
|
41
|
+
}
|
|
42
|
+
function pause(ms, signal) {
|
|
43
|
+
return new Promise((resolve) => {
|
|
44
|
+
const done = () => {
|
|
45
|
+
clearTimeout(timer);
|
|
46
|
+
signal?.removeEventListener("abort", done);
|
|
47
|
+
resolve();
|
|
48
|
+
};
|
|
49
|
+
const timer = setTimeout(done, ms);
|
|
50
|
+
signal?.addEventListener("abort", done, { once: true });
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
async function withExclusiveLock2(path, run, options = {}) {
|
|
54
|
+
const label = options.label ?? path;
|
|
55
|
+
const timeoutMs = nonNegative("timeoutMs", options.timeoutMs, DEFAULT_TIMEOUT_MS);
|
|
56
|
+
const ownerlessGraceMs = options.ownerlessGraceMs === null ? null : nonNegative("ownerlessGraceMs", options.ownerlessGraceMs, DEFAULT_OWNERLESS_GRACE_MS);
|
|
57
|
+
const mode = options.mode ?? 384;
|
|
58
|
+
if (!Number.isInteger(mode) || mode < 0 || mode > 511)
|
|
59
|
+
throw new RangeError("[stitchkit] withExclusiveLock: mode must be permission bits from 0000 to 0777");
|
|
60
|
+
const { signal } = options;
|
|
61
|
+
const deadline = performance.now() + timeoutMs;
|
|
62
|
+
let delay = FIRST_RETRY_MS;
|
|
63
|
+
for (;; ) {
|
|
64
|
+
if (signal?.aborted) {
|
|
65
|
+
throw new ExclusiveLockError2("LOCK_ABORTED", label, null, `[stitchkit] waiting for the lock on "${label}" was cancelled`, { cause: signal.reason });
|
|
66
|
+
}
|
|
67
|
+
const attempt = await attemptExclusiveLock(path, {
|
|
68
|
+
mode,
|
|
69
|
+
reclaim: true,
|
|
70
|
+
signal,
|
|
71
|
+
ownerlessGraceMs,
|
|
72
|
+
...options.machineIdentity !== undefined && {
|
|
73
|
+
machineIdentity: options.machineIdentity
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
if ("held" in attempt) {
|
|
77
|
+
const { held } = attempt;
|
|
78
|
+
let result;
|
|
79
|
+
try {
|
|
80
|
+
if (signal?.aborted) {
|
|
81
|
+
throw new ExclusiveLockError2("LOCK_ABORTED", label, null, `[stitchkit] waiting for the lock on "${label}" was cancelled`, { cause: signal.reason });
|
|
82
|
+
}
|
|
83
|
+
result = await run({
|
|
84
|
+
path: held.path,
|
|
85
|
+
owner: held.owner,
|
|
86
|
+
reclaimed: held.reclaimed,
|
|
87
|
+
async assertHeld() {
|
|
88
|
+
try {
|
|
89
|
+
await held.assertHeld();
|
|
90
|
+
} catch (cause) {
|
|
91
|
+
throw new ExclusiveLockError2("LOCK_LOST", label, held.owner, `[stitchkit] the held lock on "${label}" changed or was released`, { cause });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
} catch (error) {
|
|
96
|
+
await held.release().catch(() => {
|
|
97
|
+
return;
|
|
98
|
+
});
|
|
99
|
+
throw error;
|
|
100
|
+
}
|
|
101
|
+
await held.release();
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
if (signal?.aborted)
|
|
105
|
+
continue;
|
|
106
|
+
const remaining = deadline - performance.now();
|
|
107
|
+
if (remaining <= 0) {
|
|
108
|
+
const holder = attempt.diagnosis?.owner ?? null;
|
|
109
|
+
throw new ExclusiveLockError2("LOCK_TIMEOUT", label, holder, `[stitchkit] the lock on "${label}" is held by ${describeHolder(holder)}${describeEvidence(attempt.diagnosis)}; gave up after ${timeoutMs} ms`, { cause: attempt.diagnosis?.cause ?? attempt.error });
|
|
110
|
+
}
|
|
111
|
+
await pause(Math.min(delay * (0.5 + Math.random() / 2), remaining), signal);
|
|
112
|
+
delay = Math.min(delay * 2, MAX_RETRY_MS);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export { ExclusiveLockError2, withExclusiveLock2 };
|
|
@@ -9,7 +9,8 @@ var ContractStreamFrameSchema2 = z.discriminatedUnion("type", [
|
|
|
9
9
|
code: z.string(),
|
|
10
10
|
message: z.string().optional(),
|
|
11
11
|
details: z.unknown().optional(),
|
|
12
|
-
hint: z.string().optional()
|
|
12
|
+
hint: z.string().optional(),
|
|
13
|
+
retryable: z.boolean().optional()
|
|
13
14
|
}).strict()
|
|
14
15
|
}).strict(),
|
|
15
16
|
z.object({ type: z.literal("end") }).strict()
|
|
@@ -3,16 +3,20 @@ import {
|
|
|
3
3
|
ManagedFileRefSchema2
|
|
4
4
|
} from "./index-xqhede6x.js";
|
|
5
5
|
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
} from "./index-
|
|
6
|
+
BoundedFileReadError,
|
|
7
|
+
readBoundedFile
|
|
8
|
+
} from "./index-jd470k6q.js";
|
|
9
9
|
import {
|
|
10
10
|
isWithinDir2
|
|
11
11
|
} from "./index-5cc6r990.js";
|
|
12
|
+
import {
|
|
13
|
+
AtomicFilePublicationError2,
|
|
14
|
+
publishAtomicFile
|
|
15
|
+
} from "./index-8a9ksm91.js";
|
|
12
16
|
|
|
13
17
|
// src/files/boundary.ts
|
|
14
18
|
import { randomUUID } from "node:crypto";
|
|
15
|
-
import { constants
|
|
19
|
+
import { constants } from "node:fs";
|
|
16
20
|
import { mkdir, open as open2, realpath, stat, unlink } from "node:fs/promises";
|
|
17
21
|
import { basename as basename2, dirname, resolve } from "node:path";
|
|
18
22
|
|
|
@@ -71,40 +75,6 @@ function inspectedRef(path, size, inspection, fallback = {}) {
|
|
|
71
75
|
}
|
|
72
76
|
return parsed.data;
|
|
73
77
|
}
|
|
74
|
-
async function readHandle(handle, maxBytes, signal) {
|
|
75
|
-
const chunks = [];
|
|
76
|
-
let total = 0;
|
|
77
|
-
let ended = false;
|
|
78
|
-
while (!ended) {
|
|
79
|
-
const capacity = Math.min(64 * 1024, maxBytes + 1 - total);
|
|
80
|
-
if (capacity <= 0)
|
|
81
|
-
throw new ManagedFileError2("FILE_TOO_LARGE", `file exceeds the ${maxBytes}-byte cap`);
|
|
82
|
-
const chunk = new Uint8Array(capacity);
|
|
83
|
-
let filled = 0;
|
|
84
|
-
while (filled < capacity) {
|
|
85
|
-
signal?.throwIfAborted();
|
|
86
|
-
const { bytesRead } = await handle.read(chunk, filled, capacity - filled);
|
|
87
|
-
if (bytesRead === 0) {
|
|
88
|
-
ended = true;
|
|
89
|
-
break;
|
|
90
|
-
}
|
|
91
|
-
filled += bytesRead;
|
|
92
|
-
total += bytesRead;
|
|
93
|
-
if (total > maxBytes)
|
|
94
|
-
throw new ManagedFileError2("FILE_TOO_LARGE", `file exceeds the ${maxBytes}-byte cap`);
|
|
95
|
-
}
|
|
96
|
-
if (filled > 0)
|
|
97
|
-
chunks.push(chunk.subarray(0, filled));
|
|
98
|
-
}
|
|
99
|
-
signal?.throwIfAborted();
|
|
100
|
-
const bytes = new Uint8Array(total);
|
|
101
|
-
let offset = 0;
|
|
102
|
-
for (const chunk of chunks) {
|
|
103
|
-
bytes.set(chunk, offset);
|
|
104
|
-
offset += chunk.byteLength;
|
|
105
|
-
}
|
|
106
|
-
return bytes;
|
|
107
|
-
}
|
|
108
78
|
async function writeChunk(handle, chunk) {
|
|
109
79
|
let offset = 0;
|
|
110
80
|
while (offset < chunk.byteLength) {
|
|
@@ -161,67 +131,26 @@ async function writeSource(handle, source, maxBytes, inspectionBytes, signal) {
|
|
|
161
131
|
}
|
|
162
132
|
|
|
163
133
|
// src/files/read.ts
|
|
164
|
-
import { constants } from "node:fs";
|
|
165
134
|
import { open } from "node:fs/promises";
|
|
166
135
|
import { basename } from "node:path";
|
|
167
136
|
async function readManagedDescriptor(target, path, maxBytes, options, inspection, openDescriptor = open) {
|
|
168
|
-
if (options.rejectSymlinks && !constants.O_NOFOLLOW)
|
|
169
|
-
throw new ManagedFileError2("FILE_UNSUPPORTED", "strict leaf nofollow is unavailable");
|
|
170
|
-
const flags = constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0);
|
|
171
|
-
const handle = await openDescriptor(target, flags);
|
|
172
|
-
let failed = false;
|
|
173
|
-
let failure;
|
|
174
137
|
let source;
|
|
175
138
|
try {
|
|
176
|
-
options
|
|
177
|
-
const before = await handle.stat();
|
|
178
|
-
if (!before.isFile())
|
|
179
|
-
throw new ManagedFileError2("FILE_NOT_REGULAR", "managed path is not a regular file");
|
|
180
|
-
if (options.singleLink && before.nlink !== 1)
|
|
181
|
-
throw new ManagedFileError2("FILE_UNSAFE_LINK", "managed file has multiple links");
|
|
182
|
-
if (before.size > maxBytes)
|
|
183
|
-
throw new ManagedFileError2("FILE_TOO_LARGE", `file exceeds the ${maxBytes}-byte cap`);
|
|
184
|
-
const bytes = await readHandle(handle, maxBytes, options.signal);
|
|
185
|
-
const after = options.stable || options.observe ? await handle.stat() : before;
|
|
186
|
-
if (options.stable && (before.dev !== after.dev || before.ino !== after.ino || before.size !== after.size || before.mtimeMs !== after.mtimeMs || before.ctimeMs !== after.ctimeMs || before.nlink !== after.nlink || bytes.length !== after.size))
|
|
187
|
-
throw new ManagedFileError2("FILE_CHANGED", "managed file changed during read");
|
|
188
|
-
options.signal?.throwIfAborted();
|
|
189
|
-
const inspected = await inspectFile(inspection.inspect, {
|
|
190
|
-
prefix: bytes.slice(0, inspection.bytes),
|
|
191
|
-
name: basename(path)
|
|
192
|
-
}, inspection.timeoutMs, options.signal);
|
|
193
|
-
source = {
|
|
194
|
-
ref: inspectedRef(path, bytes.byteLength, inspected),
|
|
195
|
-
bytes,
|
|
196
|
-
...options.observe ? {
|
|
197
|
-
observation: {
|
|
198
|
-
dev: after.dev,
|
|
199
|
-
ino: after.ino,
|
|
200
|
-
size: after.size,
|
|
201
|
-
nlink: after.nlink,
|
|
202
|
-
mtimeMs: after.mtimeMs,
|
|
203
|
-
ctimeMs: after.ctimeMs
|
|
204
|
-
}
|
|
205
|
-
} : {}
|
|
206
|
-
};
|
|
139
|
+
source = await readBoundedFile(target, maxBytes, options, openDescriptor);
|
|
207
140
|
} catch (error) {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
try {
|
|
212
|
-
await handle.close();
|
|
213
|
-
} catch (error) {
|
|
214
|
-
if (!failed) {
|
|
215
|
-
failed = true;
|
|
216
|
-
failure = error;
|
|
217
|
-
}
|
|
218
|
-
}
|
|
141
|
+
if (error instanceof BoundedFileReadError)
|
|
142
|
+
throw new ManagedFileError2(error.code, error.message, { cause: error });
|
|
143
|
+
throw error;
|
|
219
144
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
return
|
|
145
|
+
const inspected = await inspectFile(inspection.inspect, {
|
|
146
|
+
prefix: source.bytes.slice(0, inspection.bytes),
|
|
147
|
+
name: basename(path)
|
|
148
|
+
}, inspection.timeoutMs, options.signal);
|
|
149
|
+
return {
|
|
150
|
+
ref: inspectedRef(path, source.bytes.byteLength, inspected),
|
|
151
|
+
bytes: source.bytes,
|
|
152
|
+
...options.observe && { observation: source.observation }
|
|
153
|
+
};
|
|
225
154
|
}
|
|
226
155
|
|
|
227
156
|
// src/files/boundary.ts
|
|
@@ -230,7 +159,7 @@ var DEFAULT_INSPECTION_BYTES = 64 * 1024;
|
|
|
230
159
|
var DEFAULT_INSPECTION_TIMEOUT_MS = 15000;
|
|
231
160
|
var nofollowFlag;
|
|
232
161
|
var noFollow = () => {
|
|
233
|
-
nofollowFlag ??=
|
|
162
|
+
nofollowFlag ??= constants.O_NOFOLLOW ?? 0;
|
|
234
163
|
return nofollowFlag;
|
|
235
164
|
};
|
|
236
165
|
|
|
@@ -387,7 +316,7 @@ async function createManagedFileBoundary2(config) {
|
|
|
387
316
|
let committed = false;
|
|
388
317
|
let size = 0;
|
|
389
318
|
try {
|
|
390
|
-
handle = await open2(temporary,
|
|
319
|
+
handle = await open2(temporary, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY | noFollow(), 384);
|
|
391
320
|
const written = await writeSource(handle, source, maxBytes, inspectionBytes, options.signal);
|
|
392
321
|
size = written.size;
|
|
393
322
|
if (options.durable)
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// src/internal/bounded-file-read.ts
|
|
2
|
+
import { constants } from "node:fs";
|
|
3
|
+
import { open } from "node:fs/promises";
|
|
4
|
+
|
|
5
|
+
class BoundedFileReadError extends Error {
|
|
6
|
+
code;
|
|
7
|
+
observation;
|
|
8
|
+
constructor(code, message, observation) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.code = code;
|
|
11
|
+
this.observation = observation;
|
|
12
|
+
this.name = "BoundedFileReadError";
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
var observationOf = (info) => ({
|
|
16
|
+
dev: info.dev,
|
|
17
|
+
ino: info.ino,
|
|
18
|
+
size: info.size,
|
|
19
|
+
nlink: info.nlink,
|
|
20
|
+
mtimeMs: info.mtimeMs,
|
|
21
|
+
ctimeMs: info.ctimeMs
|
|
22
|
+
});
|
|
23
|
+
async function readBoundedFile(target, maxBytes, options = {}, openDescriptor = open) {
|
|
24
|
+
if (options.rejectSymlinks && !constants.O_NOFOLLOW)
|
|
25
|
+
throw new BoundedFileReadError("FILE_UNSUPPORTED", "strict leaf nofollow is unavailable");
|
|
26
|
+
options.signal?.throwIfAborted();
|
|
27
|
+
const flags = constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0);
|
|
28
|
+
const handle = await openDescriptor(target, flags);
|
|
29
|
+
let failed = false;
|
|
30
|
+
let failure;
|
|
31
|
+
let before;
|
|
32
|
+
let source;
|
|
33
|
+
try {
|
|
34
|
+
options.signal?.throwIfAborted();
|
|
35
|
+
before = await handle.stat();
|
|
36
|
+
if (!before.isFile())
|
|
37
|
+
throw new BoundedFileReadError("FILE_NOT_REGULAR", "managed path is not a regular file");
|
|
38
|
+
if (options.singleLink && before.nlink !== 1)
|
|
39
|
+
throw new BoundedFileReadError("FILE_UNSAFE_LINK", "managed file has multiple links");
|
|
40
|
+
if (before.size > maxBytes)
|
|
41
|
+
throw new BoundedFileReadError("FILE_TOO_LARGE", `file exceeds the ${maxBytes}-byte cap`);
|
|
42
|
+
const bytes = await readHandle(handle, maxBytes, options.signal);
|
|
43
|
+
const after = await handle.stat();
|
|
44
|
+
if (options.stable && (before.dev !== after.dev || before.ino !== after.ino || before.size !== after.size || before.mtimeMs !== after.mtimeMs || before.ctimeMs !== after.ctimeMs || before.nlink !== after.nlink || bytes.length !== after.size))
|
|
45
|
+
throw new BoundedFileReadError("FILE_CHANGED", "managed file changed during read");
|
|
46
|
+
options.signal?.throwIfAborted();
|
|
47
|
+
source = { bytes, observation: observationOf(after) };
|
|
48
|
+
} catch (error) {
|
|
49
|
+
failed = true;
|
|
50
|
+
failure = error;
|
|
51
|
+
if (error instanceof BoundedFileReadError && error.code === "FILE_TOO_LARGE" && before) {
|
|
52
|
+
const after = await handle.stat().catch(() => {
|
|
53
|
+
return;
|
|
54
|
+
});
|
|
55
|
+
if (after?.isFile() && after.dev === before.dev && after.ino === before.ino && after.nlink === 1)
|
|
56
|
+
failure = new BoundedFileReadError(error.code, error.message, observationOf(after));
|
|
57
|
+
}
|
|
58
|
+
} finally {
|
|
59
|
+
try {
|
|
60
|
+
await handle.close();
|
|
61
|
+
} catch (error) {
|
|
62
|
+
if (!failed) {
|
|
63
|
+
failed = true;
|
|
64
|
+
failure = error;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (failed)
|
|
69
|
+
throw failure;
|
|
70
|
+
if (source === undefined)
|
|
71
|
+
throw new Error("Read completed without a result");
|
|
72
|
+
return source;
|
|
73
|
+
}
|
|
74
|
+
async function readHandle(handle, maxBytes, signal) {
|
|
75
|
+
const chunks = [];
|
|
76
|
+
let total = 0;
|
|
77
|
+
let ended = false;
|
|
78
|
+
while (!ended) {
|
|
79
|
+
const capacity = Math.min(64 * 1024, maxBytes + 1 - total);
|
|
80
|
+
if (capacity <= 0)
|
|
81
|
+
throw new BoundedFileReadError("FILE_TOO_LARGE", `file exceeds the ${maxBytes}-byte cap`);
|
|
82
|
+
const chunk = new Uint8Array(capacity);
|
|
83
|
+
let filled = 0;
|
|
84
|
+
while (filled < capacity) {
|
|
85
|
+
signal?.throwIfAborted();
|
|
86
|
+
const { bytesRead } = await handle.read(chunk, filled, capacity - filled);
|
|
87
|
+
if (bytesRead === 0) {
|
|
88
|
+
ended = true;
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
filled += bytesRead;
|
|
92
|
+
total += bytesRead;
|
|
93
|
+
if (total > maxBytes)
|
|
94
|
+
throw new BoundedFileReadError("FILE_TOO_LARGE", `file exceeds the ${maxBytes}-byte cap`);
|
|
95
|
+
}
|
|
96
|
+
if (filled > 0)
|
|
97
|
+
chunks.push(chunk.subarray(0, filled));
|
|
98
|
+
}
|
|
99
|
+
signal?.throwIfAborted();
|
|
100
|
+
const bytes = new Uint8Array(total);
|
|
101
|
+
let offset = 0;
|
|
102
|
+
for (const chunk of chunks) {
|
|
103
|
+
bytes.set(chunk, offset);
|
|
104
|
+
offset += chunk.byteLength;
|
|
105
|
+
}
|
|
106
|
+
return bytes;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export { BoundedFileReadError, readBoundedFile };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AppError2
|
|
3
|
-
} from "./index-
|
|
3
|
+
} from "./index-x928baz2.js";
|
|
4
4
|
import {
|
|
5
5
|
zodIssues2,
|
|
6
6
|
formatZodError2
|
|
@@ -28,7 +28,7 @@ function recordedErrorMessage(code, envelopeMessage, thrown) {
|
|
|
28
28
|
}
|
|
29
29
|
return envelopeMessage;
|
|
30
30
|
}
|
|
31
|
-
function normalizeError2(err) {
|
|
31
|
+
function normalizeError2(err, options = {}) {
|
|
32
32
|
if (AppError2.is(err)) {
|
|
33
33
|
if (err.code === "REALTIME_CONTRACT_VIOLATION") {
|
|
34
34
|
return new AppError2("REALTIME_CONTRACT_VIOLATION", "Realtime contract violation", 500);
|
|
@@ -40,7 +40,8 @@ function normalizeError2(err) {
|
|
|
40
40
|
issues: zodIssues2(err).slice(0, MAX_DETAIL_ISSUES)
|
|
41
41
|
});
|
|
42
42
|
}
|
|
43
|
-
|
|
43
|
+
if (options.logUnexpected !== false)
|
|
44
|
+
console.error("[stitchkit] unhandled error:", err);
|
|
44
45
|
return new AppError2("INTERNAL_SERVER_ERROR", "Internal server error", 500);
|
|
45
46
|
}
|
|
46
47
|
function strippedPaths(before, after, prefix) {
|