stitchkit 0.53.2 → 0.55.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/README.md +4 -1
- package/dist/browser/socket-io.d.ts +11 -1
- package/dist/browser/socket-io.d.ts.map +1 -1
- package/dist/cli.d.ts +2 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +15 -8
- package/dist/contract/define.d.ts +27 -0
- package/dist/contract/define.d.ts.map +1 -1
- package/dist/contract/file-ref.d.ts +13 -0
- package/dist/contract/file-ref.d.ts.map +1 -0
- package/dist/contract/index.d.ts +2 -1
- package/dist/contract/index.d.ts.map +1 -1
- package/dist/contract/index.js +21 -17
- package/dist/files/boundary.d.ts +52 -0
- package/dist/files/boundary.d.ts.map +1 -0
- package/dist/files.d.ts +3 -0
- package/dist/files.d.ts.map +1 -0
- package/dist/files.js +16 -0
- package/dist/{index-c78w2y09.js → index-0gv7k0ra.js} +515 -156
- package/dist/index-1bx83sw4.js +4 -0
- package/dist/index-1k16zv57.js +269 -0
- package/dist/index-6k1937bx.js +20 -0
- package/dist/{index-bmnhqtya.js → index-7eq9va6e.js} +1 -4
- package/dist/{index-yxpe3phd.js → index-cby4ar3v.js} +1 -18
- package/dist/index-h60df7rj.js +110 -0
- package/dist/{index-yez419px.js → index-js7yexng.js} +19 -6
- package/dist/index-k4dftwf7.js +66 -0
- package/dist/{index-pdv1mjjr.js → index-npye5kt7.js} +30 -59
- package/dist/{index-yydqk4fh.js → index-pzc32v75.js} +90 -3
- package/dist/{index-e1es808r.js → index-qh4xevf5.js} +1 -1
- package/dist/{index-gvha32jh.js → index-qx84bqzk.js} +2 -2
- package/dist/{index-pfqjb5xy.js → index-rgd18hx3.js} +23 -5
- package/dist/index-sbdmyz75.js +18 -0
- package/dist/{index-173tvqcp.js → index-v4bbq3p4.js} +9 -114
- package/dist/index.js +162 -35
- package/dist/node.js +30 -27
- package/dist/observability/event.d.ts +2 -16
- package/dist/observability/event.d.ts.map +1 -1
- package/dist/observability/index.js +28 -25
- package/dist/react.js +2 -2
- package/dist/realtime/contract.d.ts +9 -0
- package/dist/realtime/contract.d.ts.map +1 -1
- package/dist/realtime/index.d.ts +2 -1
- package/dist/realtime/index.d.ts.map +1 -1
- package/dist/realtime/request.d.ts +21 -0
- package/dist/realtime/request.d.ts.map +1 -0
- package/dist/realtime/socket.d.ts +3 -0
- package/dist/realtime/socket.d.ts.map +1 -1
- package/dist/remote.d.ts +9 -0
- package/dist/remote.d.ts.map +1 -0
- package/dist/remote.js +79 -0
- package/dist/server/context-contribution.d.ts +10 -0
- package/dist/server/context-contribution.d.ts.map +1 -0
- package/dist/server/context.d.ts.map +1 -1
- package/dist/server/index.d.ts +2 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +133 -88
- package/dist/server/lifecycle.d.ts +4 -0
- package/dist/server/lifecycle.d.ts.map +1 -0
- package/dist/server/middleware/auth.d.ts +35 -7
- package/dist/server/middleware/auth.d.ts.map +1 -1
- package/dist/server/process-signal-common.d.ts +6 -0
- package/dist/server/process-signal-common.d.ts.map +1 -0
- package/dist/server/process-signals.d.ts.map +1 -1
- package/dist/server/types.d.ts +1 -1
- package/dist/server/types.d.ts.map +1 -1
- package/dist/testing/surface-conformance.d.ts +47 -0
- package/dist/testing/surface-conformance.d.ts.map +1 -0
- package/dist/testing/surface-manifest.d.ts +156 -0
- package/dist/testing/surface-manifest.d.ts.map +1 -0
- package/dist/testing.d.ts +2 -0
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +366 -3
- package/dist/tools/agent.d.ts.map +1 -1
- package/dist/tools/async-operation.d.ts +168 -0
- package/dist/tools/async-operation.d.ts.map +1 -0
- package/dist/tools/cli-args.d.ts +1 -1
- package/dist/tools/cli-args.d.ts.map +1 -1
- package/dist/tools/cli-command.d.ts +29 -0
- package/dist/tools/cli-command.d.ts.map +1 -0
- package/dist/tools/cli-format.d.ts +2 -2
- package/dist/tools/cli-format.d.ts.map +1 -1
- package/dist/tools/cli-wait.d.ts +11 -2
- package/dist/tools/cli-wait.d.ts.map +1 -1
- package/dist/tools/cli.d.ts +13 -6
- package/dist/tools/cli.d.ts.map +1 -1
- package/dist/tools/define-download-tool.d.ts +18 -0
- package/dist/tools/define-download-tool.d.ts.map +1 -0
- package/dist/tools/define-upload-tool.d.ts +16 -0
- package/dist/tools/define-upload-tool.d.ts.map +1 -0
- package/dist/tools/define-view-file-tool.d.ts +10 -0
- package/dist/tools/define-view-file-tool.d.ts.map +1 -0
- package/dist/tools/define-wait-tool.d.ts +22 -0
- package/dist/tools/define-wait-tool.d.ts.map +1 -0
- package/dist/tools/download-core.d.ts +20 -0
- package/dist/tools/download-core.d.ts.map +1 -0
- package/dist/tools/execute.d.ts +3 -1
- package/dist/tools/execute.d.ts.map +1 -1
- package/dist/tools/lifecycle.d.ts +4 -0
- package/dist/tools/lifecycle.d.ts.map +1 -0
- package/dist/tools/mcp-round.d.ts +0 -1
- package/dist/tools/mcp-round.d.ts.map +1 -1
- package/dist/tools/mcp-stdio-signals.d.ts +33 -0
- package/dist/tools/mcp-stdio-signals.d.ts.map +1 -0
- package/dist/tools/mount-download.d.ts +10 -4
- package/dist/tools/mount-download.d.ts.map +1 -1
- package/dist/tools/mount-upload.d.ts +4 -2
- package/dist/tools/mount-upload.d.ts.map +1 -1
- package/dist/tools/mount-wait.d.ts.map +1 -1
- package/dist/tools/native-definition.d.ts +15 -0
- package/dist/tools/native-definition.d.ts.map +1 -0
- package/dist/tools/runtime-tool.d.ts +5 -4
- package/dist/tools/runtime-tool.d.ts.map +1 -1
- package/dist/tools/surface.d.ts.map +1 -1
- package/dist/tools/upload-core.d.ts +4 -0
- package/dist/tools/upload-core.d.ts.map +1 -0
- package/dist/tools/view-file.d.ts +84 -23
- package/dist/tools/view-file.d.ts.map +1 -1
- package/dist/tools/wait-core.d.ts +16 -2
- package/dist/tools/wait-core.d.ts.map +1 -1
- package/dist/tools.d.ts +12 -3
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +827 -495
- package/llms-full.txt +720 -53
- package/package.json +10 -2
|
@@ -1,35 +1,44 @@
|
|
|
1
1
|
import {
|
|
2
|
+
DEFAULT_PROCESS_SIGNALS,
|
|
3
|
+
RUNTIME_CONTEXT_RESERVED_KEYS,
|
|
2
4
|
assertCorsConfig,
|
|
3
5
|
corsHeaders,
|
|
4
|
-
corsPreflightResponse
|
|
5
|
-
|
|
6
|
+
corsPreflightResponse,
|
|
7
|
+
defaultSignalSource,
|
|
8
|
+
guardSignalCallback,
|
|
9
|
+
reportSignalError
|
|
10
|
+
} from "./index-pzc32v75.js";
|
|
6
11
|
import {
|
|
7
|
-
AppError,
|
|
8
|
-
badRequest,
|
|
9
12
|
errorCode,
|
|
10
13
|
extractIp,
|
|
11
14
|
getClientInfo,
|
|
12
15
|
getRequestContext,
|
|
13
|
-
isUnsafeKey,
|
|
14
16
|
normalizeError,
|
|
15
17
|
parseQueryParams,
|
|
16
18
|
recordedErrorMessage,
|
|
17
19
|
resolveSocketIp,
|
|
18
20
|
resolveTraceId,
|
|
19
21
|
runWithRequestContext,
|
|
20
|
-
safeJsonParse,
|
|
21
22
|
setRequestEndpoint,
|
|
22
23
|
setRequestError,
|
|
23
24
|
validateDeclaredOutput,
|
|
24
25
|
zodIssues
|
|
25
|
-
} from "./index-
|
|
26
|
+
} from "./index-v4bbq3p4.js";
|
|
27
|
+
import {
|
|
28
|
+
AppError,
|
|
29
|
+
badRequest,
|
|
30
|
+
isUnsafeKey,
|
|
31
|
+
safeJsonParse
|
|
32
|
+
} from "./index-h60df7rj.js";
|
|
26
33
|
import {
|
|
27
|
-
__require,
|
|
28
34
|
isRecord,
|
|
29
35
|
parseTrailingWildcard,
|
|
30
36
|
resolveTraceContext,
|
|
31
37
|
transportResult
|
|
32
|
-
} from "./index-
|
|
38
|
+
} from "./index-7eq9va6e.js";
|
|
39
|
+
import {
|
|
40
|
+
__require
|
|
41
|
+
} from "./index-1bx83sw4.js";
|
|
33
42
|
|
|
34
43
|
// src/server/multipart.ts
|
|
35
44
|
var DEFAULT_MAX_REQUEST_BYTES = 25 * 1024 * 1024;
|
|
@@ -496,19 +505,6 @@ async function readRequestText(req, maxBytes) {
|
|
|
496
505
|
}
|
|
497
506
|
|
|
498
507
|
// src/server/context.ts
|
|
499
|
-
var RESERVED_KEYS = new Set([
|
|
500
|
-
"params",
|
|
501
|
-
"input",
|
|
502
|
-
"source",
|
|
503
|
-
"req",
|
|
504
|
-
"url",
|
|
505
|
-
"headers",
|
|
506
|
-
"rawBody",
|
|
507
|
-
"traceId",
|
|
508
|
-
"spanId",
|
|
509
|
-
"ipAddress",
|
|
510
|
-
"userAgent"
|
|
511
|
-
]);
|
|
512
508
|
function parseJsonBody(req, text) {
|
|
513
509
|
if (text.trim() === "")
|
|
514
510
|
return {};
|
|
@@ -524,7 +520,7 @@ function parseJsonBody(req, text) {
|
|
|
524
520
|
function buildBaseContext(req, url, pathParams, traceId, clientIp) {
|
|
525
521
|
const safePathParams = {};
|
|
526
522
|
for (const [k, v] of Object.entries(pathParams)) {
|
|
527
|
-
if (!
|
|
523
|
+
if (!RUNTIME_CONTEXT_RESERVED_KEYS.has(k) && !isUnsafeKey(k))
|
|
528
524
|
safePathParams[k] = v;
|
|
529
525
|
}
|
|
530
526
|
return {
|
|
@@ -534,6 +530,7 @@ function buildBaseContext(req, url, pathParams, traceId, clientIp) {
|
|
|
534
530
|
req,
|
|
535
531
|
url,
|
|
536
532
|
headers: req.headers,
|
|
533
|
+
signal: req.signal,
|
|
537
534
|
...safePathParams,
|
|
538
535
|
traceId,
|
|
539
536
|
...getClientInfo(req, clientIp)
|
|
@@ -581,6 +578,7 @@ function buildErrorContext(req, url, traceId, clientIp) {
|
|
|
581
578
|
req,
|
|
582
579
|
url,
|
|
583
580
|
headers: req.headers,
|
|
581
|
+
signal: req.signal,
|
|
584
582
|
traceId,
|
|
585
583
|
...getClientInfo(req, clientIp)
|
|
586
584
|
};
|
|
@@ -1606,40 +1604,13 @@ function createServerLifecycle(getAdapter) {
|
|
|
1606
1604
|
}
|
|
1607
1605
|
|
|
1608
1606
|
// src/server/process-signals.ts
|
|
1609
|
-
var DEFAULT_SIGNALS = ["SIGINT", "SIGTERM"];
|
|
1610
|
-
var defaultSignalSource = {
|
|
1611
|
-
on: (signal, handler) => {
|
|
1612
|
-
process.on(signal, handler);
|
|
1613
|
-
},
|
|
1614
|
-
off: (signal, handler) => {
|
|
1615
|
-
process.off(signal, handler);
|
|
1616
|
-
},
|
|
1617
|
-
raiseDefault: (signal) => {
|
|
1618
|
-
if (process.listenerCount(signal) > 0)
|
|
1619
|
-
return false;
|
|
1620
|
-
process.kill(process.pid, signal);
|
|
1621
|
-
return true;
|
|
1622
|
-
}
|
|
1623
|
-
};
|
|
1624
1607
|
var bound = new WeakSet;
|
|
1625
|
-
function reportError(phase, error, onError) {
|
|
1626
|
-
try {
|
|
1627
|
-
onError?.(phase, error);
|
|
1628
|
-
} catch {}
|
|
1629
|
-
}
|
|
1630
|
-
function guard(run, phase, onError) {
|
|
1631
|
-
try {
|
|
1632
|
-
run();
|
|
1633
|
-
} catch (error) {
|
|
1634
|
-
reportError(phase, error, onError);
|
|
1635
|
-
}
|
|
1636
|
-
}
|
|
1637
1608
|
function bindProcessSignals(handle, options = {}) {
|
|
1638
1609
|
if (bound.has(handle)) {
|
|
1639
1610
|
throw new Error("[stitchkit] bindProcessSignals: this server is already bound; close the first binding before creating another");
|
|
1640
1611
|
}
|
|
1641
1612
|
bound.add(handle);
|
|
1642
|
-
const signals = [...new Set(options.signals ??
|
|
1613
|
+
const signals = [...new Set(options.signals ?? DEFAULT_PROCESS_SIGNALS)];
|
|
1643
1614
|
const source = options.signalSource ?? defaultSignalSource;
|
|
1644
1615
|
const budgets = ShutdownOptionsSchema.omit({ signal: true }).parse(options.shutdown ?? {});
|
|
1645
1616
|
const controller = new AbortController;
|
|
@@ -1680,7 +1651,7 @@ function bindProcessSignals(handle, options = {}) {
|
|
|
1680
1651
|
try {
|
|
1681
1652
|
await options.onShutdown?.(signal);
|
|
1682
1653
|
} catch (error) {
|
|
1683
|
-
|
|
1654
|
+
reportSignalError("prepare", error, options.onError);
|
|
1684
1655
|
}
|
|
1685
1656
|
let result;
|
|
1686
1657
|
try {
|
|
@@ -1688,7 +1659,7 @@ function bindProcessSignals(handle, options = {}) {
|
|
|
1688
1659
|
} catch (error) {
|
|
1689
1660
|
settled = true;
|
|
1690
1661
|
rejectChain(error);
|
|
1691
|
-
|
|
1662
|
+
reportSignalError("shutdown", error, options.onError);
|
|
1692
1663
|
removeListeners();
|
|
1693
1664
|
return;
|
|
1694
1665
|
}
|
|
@@ -1697,7 +1668,7 @@ function bindProcessSignals(handle, options = {}) {
|
|
|
1697
1668
|
try {
|
|
1698
1669
|
await options.onComplete?.(result);
|
|
1699
1670
|
} catch (error) {
|
|
1700
|
-
|
|
1671
|
+
reportSignalError("complete", error, options.onError);
|
|
1701
1672
|
} finally {
|
|
1702
1673
|
removeListeners();
|
|
1703
1674
|
}
|
|
@@ -1709,26 +1680,26 @@ function bindProcessSignals(handle, options = {}) {
|
|
|
1709
1680
|
queueMicrotask(() => {
|
|
1710
1681
|
sameTurnAsStart = false;
|
|
1711
1682
|
});
|
|
1712
|
-
run(signal).catch((error) =>
|
|
1683
|
+
run(signal).catch((error) => reportSignalError("shutdown", error, options.onError));
|
|
1713
1684
|
return;
|
|
1714
1685
|
}
|
|
1715
1686
|
if (sameTurnAsStart)
|
|
1716
1687
|
return;
|
|
1717
1688
|
if (!settled && !controller.signal.aborted) {
|
|
1718
1689
|
controller.abort();
|
|
1719
|
-
|
|
1690
|
+
guardSignalCallback(() => options.onRepeatedSignal?.(signal, "force"), "shutdown", options.onError);
|
|
1720
1691
|
return;
|
|
1721
1692
|
}
|
|
1722
1693
|
removeListeners();
|
|
1723
|
-
|
|
1694
|
+
guardSignalCallback(() => options.onRepeatedSignal?.(signal, "escalate"), "shutdown", options.onError);
|
|
1724
1695
|
let restored = false;
|
|
1725
1696
|
try {
|
|
1726
1697
|
restored = source.raiseDefault(signal);
|
|
1727
1698
|
} catch (error) {
|
|
1728
|
-
|
|
1699
|
+
reportSignalError("shutdown", error, options.onError);
|
|
1729
1700
|
}
|
|
1730
1701
|
if (!restored) {
|
|
1731
|
-
|
|
1702
|
+
guardSignalCallback(() => options.onEscalationBlocked?.(signal), "shutdown", options.onError);
|
|
1732
1703
|
}
|
|
1733
1704
|
};
|
|
1734
1705
|
for (const signal of signals) {
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
|
+
isUnsafeKey,
|
|
2
3
|
mergeMeta
|
|
3
|
-
} from "./index-
|
|
4
|
+
} from "./index-h60df7rj.js";
|
|
4
5
|
import {
|
|
5
6
|
callRuntimeHandler,
|
|
6
7
|
isRecord,
|
|
7
8
|
transportResult,
|
|
8
9
|
typedEntries
|
|
9
|
-
} from "./index-
|
|
10
|
+
} from "./index-7eq9va6e.js";
|
|
10
11
|
|
|
11
12
|
// src/server/middleware/cors.ts
|
|
12
13
|
var DEFAULT_CORS_ALLOW_HEADERS = "Content-Type, Authorization, X-Trace-Id, traceparent, tracestate";
|
|
@@ -246,4 +247,90 @@ function createImplementRegistry() {
|
|
|
246
247
|
return (contracts, handlers) => transportResult(bindRegistry(contracts, handlers));
|
|
247
248
|
}
|
|
248
249
|
|
|
249
|
-
|
|
250
|
+
// src/server/context-contribution.ts
|
|
251
|
+
var RUNTIME_CONTEXT_RESERVED_KEYS = new Set([
|
|
252
|
+
"params",
|
|
253
|
+
"input",
|
|
254
|
+
"files",
|
|
255
|
+
"rawBody",
|
|
256
|
+
"source",
|
|
257
|
+
"req",
|
|
258
|
+
"url",
|
|
259
|
+
"headers",
|
|
260
|
+
"traceId",
|
|
261
|
+
"spanId",
|
|
262
|
+
"ipAddress",
|
|
263
|
+
"userAgent",
|
|
264
|
+
"signal",
|
|
265
|
+
"mcp"
|
|
266
|
+
]);
|
|
267
|
+
function contributionError(scope, reason) {
|
|
268
|
+
return new TypeError(`[stitchkit] auth: invalid context contribution for scope ${JSON.stringify(scope)}: ${reason}`);
|
|
269
|
+
}
|
|
270
|
+
function mergeContextContribution(ctx, value, scope) {
|
|
271
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
272
|
+
throw contributionError(scope, "expected a plain record");
|
|
273
|
+
}
|
|
274
|
+
let prototype;
|
|
275
|
+
let descriptors;
|
|
276
|
+
let keys;
|
|
277
|
+
try {
|
|
278
|
+
prototype = Object.getPrototypeOf(value);
|
|
279
|
+
descriptors = Object.getOwnPropertyDescriptors(value);
|
|
280
|
+
keys = Reflect.ownKeys(value);
|
|
281
|
+
} catch {
|
|
282
|
+
throw contributionError(scope, "record inspection failed");
|
|
283
|
+
}
|
|
284
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
285
|
+
throw contributionError(scope, "expected Object.prototype or null prototype");
|
|
286
|
+
}
|
|
287
|
+
const prepared = Object.create(null);
|
|
288
|
+
for (const key of keys) {
|
|
289
|
+
if (typeof key !== "string") {
|
|
290
|
+
throw contributionError(scope, "symbol keys are not supported");
|
|
291
|
+
}
|
|
292
|
+
if (isUnsafeKey(key)) {
|
|
293
|
+
throw contributionError(scope, `unsafe key ${JSON.stringify(key)}`);
|
|
294
|
+
}
|
|
295
|
+
if (RUNTIME_CONTEXT_RESERVED_KEYS.has(key)) {
|
|
296
|
+
throw contributionError(scope, `reserved key ${JSON.stringify(key)}`);
|
|
297
|
+
}
|
|
298
|
+
const descriptor = descriptors[key];
|
|
299
|
+
if (!descriptor?.enumerable || !("value" in descriptor)) {
|
|
300
|
+
throw contributionError(scope, `key ${JSON.stringify(key)} must be enumerable data`);
|
|
301
|
+
}
|
|
302
|
+
prepared[key] = descriptor.value;
|
|
303
|
+
}
|
|
304
|
+
Object.assign(ctx, prepared);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// src/server/process-signal-common.ts
|
|
308
|
+
var DEFAULT_PROCESS_SIGNALS = ["SIGINT", "SIGTERM"];
|
|
309
|
+
var defaultSignalSource = {
|
|
310
|
+
on: (signal, handler) => {
|
|
311
|
+
process.on(signal, handler);
|
|
312
|
+
},
|
|
313
|
+
off: (signal, handler) => {
|
|
314
|
+
process.off(signal, handler);
|
|
315
|
+
},
|
|
316
|
+
raiseDefault: (signal) => {
|
|
317
|
+
if (process.listenerCount(signal) > 0)
|
|
318
|
+
return false;
|
|
319
|
+
process.kill(process.pid, signal);
|
|
320
|
+
return true;
|
|
321
|
+
}
|
|
322
|
+
};
|
|
323
|
+
function reportSignalError(phase, error, onError) {
|
|
324
|
+
try {
|
|
325
|
+
onError?.(phase, error);
|
|
326
|
+
} catch {}
|
|
327
|
+
}
|
|
328
|
+
function guardSignalCallback(run, phase, onError) {
|
|
329
|
+
try {
|
|
330
|
+
run();
|
|
331
|
+
} catch (error) {
|
|
332
|
+
reportSignalError(phase, error, onError);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
export { RUNTIME_CONTEXT_RESERVED_KEYS, mergeContextContribution, DEFAULT_CORS_ALLOW_HEADERS, DEFAULT_CORS_EXPOSE_HEADERS, assertCorsConfig, corsHeaders, corsPreflightResponse, defineMultipartStream, createMultipartStream, contractOnlyService, implement, createImplement, createScopedImplement, createScopedImplementRegistry, implementRegistry, createImplementRegistry, DEFAULT_PROCESS_SIGNALS, defaultSignalSource, reportSignalError, guardSignalCallback };
|
|
@@ -350,8 +350,26 @@ function createContractFactory(config) {
|
|
|
350
350
|
};
|
|
351
351
|
return { defineContract: explicit };
|
|
352
352
|
}
|
|
353
|
-
// src/contract/
|
|
353
|
+
// src/contract/file-ref.ts
|
|
354
354
|
import { z as z3 } from "zod";
|
|
355
|
+
function isManagedFilePath(value) {
|
|
356
|
+
if (value.length === 0 || value.includes("\x00") || value.includes("\\"))
|
|
357
|
+
return false;
|
|
358
|
+
if (value.startsWith("/") || value.startsWith("//") || /^[A-Za-z]:/.test(value)) {
|
|
359
|
+
return false;
|
|
360
|
+
}
|
|
361
|
+
const parts = value.split("/");
|
|
362
|
+
return parts.every((part) => part.length > 0 && part !== "." && part !== "..");
|
|
363
|
+
}
|
|
364
|
+
var ManagedFilePathSchema = z3.string().refine(isManagedFilePath, "expected a canonical relative managed-file path");
|
|
365
|
+
var ManagedFileRefSchema = z3.object({
|
|
366
|
+
path: ManagedFilePathSchema,
|
|
367
|
+
size: z3.number().int().nonnegative(),
|
|
368
|
+
mediaType: z3.string().min(1).optional(),
|
|
369
|
+
name: z3.string().min(1).optional()
|
|
370
|
+
});
|
|
371
|
+
// src/contract/pagination.ts
|
|
372
|
+
import { z as z4 } from "zod";
|
|
355
373
|
|
|
356
374
|
// src/internal/base64url.ts
|
|
357
375
|
function bytesToBase64Url(bytes) {
|
|
@@ -371,9 +389,9 @@ function base64UrlToBytes(segment) {
|
|
|
371
389
|
|
|
372
390
|
// src/contract/pagination.ts
|
|
373
391
|
function paginatedSchema(itemSchema) {
|
|
374
|
-
return
|
|
375
|
-
items:
|
|
376
|
-
nextCursor:
|
|
392
|
+
return z4.object({
|
|
393
|
+
items: z4.array(itemSchema),
|
|
394
|
+
nextCursor: z4.string().nullable()
|
|
377
395
|
});
|
|
378
396
|
}
|
|
379
397
|
function toBase64Url(str) {
|
|
@@ -395,4 +413,4 @@ function decodeCursor(cursor, schema) {
|
|
|
395
413
|
return null;
|
|
396
414
|
}
|
|
397
415
|
}
|
|
398
|
-
export { parseTrailingWildcard, AppError, notFound, badRequest, unauthorized, forbidden, conflict, rateLimited, STITCH_ERROR_STATUS, isStitchErrorCode, appError, ALL_TRANSPORTS, defineContract, defineErrors, createContractFactory, paginatedSchema, encodeCursor, decodeCursor };
|
|
416
|
+
export { parseTrailingWildcard, AppError, notFound, badRequest, unauthorized, forbidden, conflict, rateLimited, STITCH_ERROR_STATUS, isStitchErrorCode, appError, ALL_TRANSPORTS, defineContract, defineErrors, createContractFactory, ManagedFilePathSchema, ManagedFileRefSchema, paginatedSchema, encodeCursor, decodeCursor };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// src/internal/within-dir.ts
|
|
2
|
+
import { realpath } from "node:fs/promises";
|
|
3
|
+
import { sep } from "node:path";
|
|
4
|
+
function isWithinDir(root, target) {
|
|
5
|
+
const base = root.endsWith(sep) ? root.slice(0, -sep.length) : root;
|
|
6
|
+
return target === root || target === base || target.startsWith(base + sep);
|
|
7
|
+
}
|
|
8
|
+
async function realPathWithinDir(root, target) {
|
|
9
|
+
const [realRoot, realTarget] = await Promise.all([
|
|
10
|
+
realpath(root).catch(() => null),
|
|
11
|
+
realpath(target).catch(() => null)
|
|
12
|
+
]);
|
|
13
|
+
if (realRoot === null || realTarget === null)
|
|
14
|
+
return null;
|
|
15
|
+
return isWithinDir(realRoot, realTarget) ? realTarget : null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { isWithinDir, realPathWithinDir };
|
|
@@ -1,119 +1,14 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AppError,
|
|
3
|
+
isUnsafeKey
|
|
4
|
+
} from "./index-h60df7rj.js";
|
|
1
5
|
import {
|
|
2
6
|
isRecord,
|
|
3
7
|
resolveTraceContext
|
|
4
|
-
} from "./index-
|
|
5
|
-
|
|
6
|
-
// src/contract/errors.ts
|
|
7
|
-
var APP_ERROR_BRAND = Symbol.for("stitchkit.AppError");
|
|
8
|
-
|
|
9
|
-
class AppError extends Error {
|
|
10
|
-
code;
|
|
11
|
-
status;
|
|
12
|
-
details;
|
|
13
|
-
hint;
|
|
14
|
-
traceId;
|
|
15
|
-
constructor(code, message, status = 500, details, hint, traceId) {
|
|
16
|
-
super(message ?? code);
|
|
17
|
-
this.code = code;
|
|
18
|
-
this.status = status;
|
|
19
|
-
this.details = details;
|
|
20
|
-
this.hint = hint;
|
|
21
|
-
this.traceId = traceId;
|
|
22
|
-
this.name = "AppError";
|
|
23
|
-
Object.defineProperty(this, APP_ERROR_BRAND, { value: true });
|
|
24
|
-
}
|
|
25
|
-
static is(err) {
|
|
26
|
-
return typeof err === "object" && err !== null && APP_ERROR_BRAND in err;
|
|
27
|
-
}
|
|
28
|
-
toJSON() {
|
|
29
|
-
return {
|
|
30
|
-
error: {
|
|
31
|
-
code: this.code,
|
|
32
|
-
message: this.message,
|
|
33
|
-
...this.details && { details: this.details },
|
|
34
|
-
...this.hint && { hint: this.hint }
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
function notFound(message = "Not found") {
|
|
40
|
-
throw new AppError("NOT_FOUND", message, 404);
|
|
41
|
-
}
|
|
42
|
-
function badRequest(message, details) {
|
|
43
|
-
throw new AppError("BAD_REQUEST", message, 400, details);
|
|
44
|
-
}
|
|
45
|
-
function unauthorized(message = "Unauthorized") {
|
|
46
|
-
throw new AppError("UNAUTHORIZED", message, 401);
|
|
47
|
-
}
|
|
48
|
-
function forbidden(message = "Forbidden") {
|
|
49
|
-
throw new AppError("FORBIDDEN", message, 403);
|
|
50
|
-
}
|
|
51
|
-
function conflict(message = "Conflict", details) {
|
|
52
|
-
throw new AppError("CONFLICT", message, 409, details);
|
|
53
|
-
}
|
|
54
|
-
function rateLimited(message = "Too many requests") {
|
|
55
|
-
throw new AppError("RATE_LIMITED", message, 429);
|
|
56
|
-
}
|
|
57
|
-
var STITCH_ERROR_STATUS = {
|
|
58
|
-
BAD_REQUEST: 400,
|
|
59
|
-
UNAUTHORIZED: 401,
|
|
60
|
-
FORBIDDEN: 403,
|
|
61
|
-
NOT_FOUND: 404,
|
|
62
|
-
METHOD_NOT_ALLOWED: 405,
|
|
63
|
-
CONFLICT: 409,
|
|
64
|
-
RATE_LIMITED: 429,
|
|
65
|
-
VALIDATION_ERROR: 400,
|
|
66
|
-
REALTIME_CONTRACT_VIOLATION: 500,
|
|
67
|
-
INTERNAL_SERVER_ERROR: 500
|
|
68
|
-
};
|
|
69
|
-
function isStitchErrorCode(code) {
|
|
70
|
-
return Object.hasOwn(STITCH_ERROR_STATUS, code);
|
|
71
|
-
}
|
|
72
|
-
function appError(code, message, details) {
|
|
73
|
-
throw new AppError(code, message, isStitchErrorCode(code) ? STITCH_ERROR_STATUS[code] : 500, details);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// src/contract/define.ts
|
|
77
|
-
import { z } from "zod";
|
|
78
|
-
|
|
79
|
-
// src/internal/safe-json.ts
|
|
80
|
-
function isUnsafeKey(key) {
|
|
81
|
-
return key === "__proto__";
|
|
82
|
-
}
|
|
83
|
-
function safeJsonParse(text) {
|
|
84
|
-
return JSON.parse(text, (key, value) => isUnsafeKey(key) ? undefined : value);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// src/contract/define.ts
|
|
88
|
-
function mergeMeta(contractMeta, endpointMeta) {
|
|
89
|
-
if (!contractMeta)
|
|
90
|
-
return endpointMeta;
|
|
91
|
-
if (!endpointMeta)
|
|
92
|
-
return { ...contractMeta };
|
|
93
|
-
return { ...contractMeta, ...endpointMeta };
|
|
94
|
-
}
|
|
95
|
-
// src/contract/errors-factory.ts
|
|
96
|
-
import { z as z2 } from "zod";
|
|
97
|
-
// src/contract/pagination.ts
|
|
98
|
-
import { z as z3 } from "zod";
|
|
8
|
+
} from "./index-7eq9va6e.js";
|
|
99
9
|
|
|
100
|
-
// src/internal/base64url.ts
|
|
101
|
-
function bytesToBase64Url(bytes) {
|
|
102
|
-
let binary = "";
|
|
103
|
-
for (const byte of bytes)
|
|
104
|
-
binary += String.fromCharCode(byte);
|
|
105
|
-
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
106
|
-
}
|
|
107
|
-
function base64UrlToBytes(segment) {
|
|
108
|
-
if (!/^[A-Za-z0-9_-]*$/.test(segment) || segment.length % 4 === 1) {
|
|
109
|
-
throw new Error("invalid base64url segment");
|
|
110
|
-
}
|
|
111
|
-
const b64 = segment.replace(/-/g, "+").replace(/_/g, "/");
|
|
112
|
-
const padded = b64.padEnd(Math.ceil(b64.length / 4) * 4, "=");
|
|
113
|
-
return Uint8Array.from(atob(padded), (c) => c.charCodeAt(0));
|
|
114
|
-
}
|
|
115
10
|
// src/internal/errors.ts
|
|
116
|
-
import { z
|
|
11
|
+
import { z } from "zod";
|
|
117
12
|
function issuePath(path) {
|
|
118
13
|
return path.length > 0 ? path.map(String).join(".") : "(root)";
|
|
119
14
|
}
|
|
@@ -136,7 +31,7 @@ var MAX_DETAIL_ISSUES = 20;
|
|
|
136
31
|
function errorCode(err) {
|
|
137
32
|
if (AppError.is(err))
|
|
138
33
|
return err.code;
|
|
139
|
-
if (err instanceof
|
|
34
|
+
if (err instanceof z.ZodError)
|
|
140
35
|
return "VALIDATION_ERROR";
|
|
141
36
|
return;
|
|
142
37
|
}
|
|
@@ -156,7 +51,7 @@ function normalizeError(err) {
|
|
|
156
51
|
}
|
|
157
52
|
return err;
|
|
158
53
|
}
|
|
159
|
-
if (err instanceof
|
|
54
|
+
if (err instanceof z.ZodError) {
|
|
160
55
|
return new AppError("VALIDATION_ERROR", formatZodError(err), 400, {
|
|
161
56
|
issues: zodIssues(err).slice(0, MAX_DETAIL_ISSUES)
|
|
162
57
|
});
|
|
@@ -322,4 +217,4 @@ function wrapInRequestContext(handler, options = {}) {
|
|
|
322
217
|
};
|
|
323
218
|
}
|
|
324
219
|
|
|
325
|
-
export {
|
|
220
|
+
export { formatZodError, zodIssues, errorCode, recordedErrorMessage, normalizeError, validateDeclaredOutput, generateTraceId, resolveTraceId, resolveSocketIp, extractIp, getClientInfo, parseQueryParams, runWithRequestContext, getRequestContext, getTraceId, getUserId, setRequestUser, setRequestEndpoint, setRequestDimensions, setRequestError, wrapInRequestContext };
|