stitchkit 0.55.0 → 0.56.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/socket-io.d.ts +14 -6
- package/dist/browser/socket-io.d.ts.map +1 -1
- package/dist/cli.js +4 -4
- package/dist/contract/errors.d.ts +7 -0
- package/dist/contract/errors.d.ts.map +1 -1
- package/dist/contract/index.js +1 -1
- package/dist/files/boundary.d.ts +8 -5
- package/dist/files/boundary.d.ts.map +1 -1
- package/dist/files.js +1 -1
- package/dist/{index-rgd18hx3.js → index-28cqssm3.js} +7 -0
- package/dist/index-557by2db.js +34 -0
- package/dist/index-5r13htq1.js +283 -0
- package/dist/index-6y759j86.js +1031 -0
- package/dist/{index-npye5kt7.js → index-75njxz7p.js} +69 -7
- package/dist/{index-1k16zv57.js → index-bfcpjw20.js} +125 -31
- package/dist/{index-0gv7k0ra.js → index-escqg10p.js} +73 -666
- package/dist/{index-v4bbq3p4.js → index-j3dem06f.js} +1 -1
- package/dist/{index-qx84bqzk.js → index-jcc611vh.js} +1 -1
- package/dist/{index-pzc32v75.js → index-sm2tjx06.js} +41 -4
- package/dist/{index-js7yexng.js → index-xy8fmh6w.js} +83 -4
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +27 -6
- package/dist/node.js +5 -4
- package/dist/observability/audit.d.ts +4 -0
- package/dist/observability/audit.d.ts.map +1 -1
- package/dist/observability/event.d.ts +5 -0
- package/dist/observability/event.d.ts.map +1 -1
- package/dist/observability/index.js +17 -11
- package/dist/remote.js +1 -1
- package/dist/server/context-contribution.d.ts +8 -0
- package/dist/server/context-contribution.d.ts.map +1 -1
- package/dist/server/create.d.ts.map +1 -1
- package/dist/server/error-hook.d.ts +1 -1
- package/dist/server/error-hook.d.ts.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +10 -6
- package/dist/server/logger.d.ts.map +1 -1
- package/dist/server/middleware/auth.d.ts +29 -2
- package/dist/server/middleware/auth.d.ts.map +1 -1
- package/dist/server/request-body.d.ts.map +1 -1
- package/dist/testing/surface-conformance.d.ts +143 -10
- package/dist/testing/surface-conformance.d.ts.map +1 -1
- package/dist/testing/surface-manifest.d.ts +132 -33
- package/dist/testing/surface-manifest.d.ts.map +1 -1
- package/dist/testing.d.ts +2 -2
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +470 -122
- package/dist/tools/async-operation.d.ts +210 -18
- package/dist/tools/async-operation.d.ts.map +1 -1
- package/dist/tools/define-download-tool.d.ts.map +1 -1
- package/dist/tools/define-upload-tool.d.ts.map +1 -1
- package/dist/tools/internal/surface-projector.d.ts +101 -0
- package/dist/tools/internal/surface-projector.d.ts.map +1 -0
- package/dist/tools/managed-file-error.d.ts +6 -0
- package/dist/tools/managed-file-error.d.ts.map +1 -0
- package/dist/tools/mcp-prepare.d.ts +3 -21
- package/dist/tools/mcp-prepare.d.ts.map +1 -1
- package/dist/tools/mcp-round-policy.d.ts +9 -0
- package/dist/tools/mcp-round-policy.d.ts.map +1 -0
- package/dist/tools/mcp-round.d.ts +0 -4
- package/dist/tools/mcp-round.d.ts.map +1 -1
- package/dist/tools/mount-download.d.ts.map +1 -1
- package/dist/tools/mount-upload.d.ts.map +1 -1
- package/dist/tools/mount.d.ts +5 -9
- package/dist/tools/mount.d.ts.map +1 -1
- package/dist/tools/runtime-tool.d.ts.map +1 -1
- package/dist/tools/surface.d.ts +7 -0
- package/dist/tools/surface.d.ts.map +1 -1
- package/dist/tools/view-file.d.ts.map +1 -1
- package/dist/tools.d.ts +1 -1
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +348 -383
- package/llms-full.txt +425 -66
- package/package.json +1 -1
- package/dist/index-h60df7rj.js +0 -110
- package/dist/index-k4dftwf7.js +0 -66
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
defaultSignalSource,
|
|
8
8
|
guardSignalCallback,
|
|
9
9
|
reportSignalError
|
|
10
|
-
} from "./index-
|
|
10
|
+
} from "./index-sm2tjx06.js";
|
|
11
11
|
import {
|
|
12
12
|
errorCode,
|
|
13
13
|
extractIp,
|
|
@@ -23,13 +23,13 @@ import {
|
|
|
23
23
|
setRequestError,
|
|
24
24
|
validateDeclaredOutput,
|
|
25
25
|
zodIssues
|
|
26
|
-
} from "./index-
|
|
26
|
+
} from "./index-j3dem06f.js";
|
|
27
27
|
import {
|
|
28
28
|
AppError,
|
|
29
29
|
badRequest,
|
|
30
30
|
isUnsafeKey,
|
|
31
31
|
safeJsonParse
|
|
32
|
-
} from "./index-
|
|
32
|
+
} from "./index-5r13htq1.js";
|
|
33
33
|
import {
|
|
34
34
|
isRecord,
|
|
35
35
|
parseTrailingWildcard,
|
|
@@ -466,12 +466,20 @@ async function parseMultipart(req, descriptor, fieldsSchema, receivers) {
|
|
|
466
466
|
}
|
|
467
467
|
|
|
468
468
|
// src/server/request-body.ts
|
|
469
|
+
function requestAbortReason(req) {
|
|
470
|
+
return req.signal.reason ?? new DOMException("The connection was closed", "AbortError");
|
|
471
|
+
}
|
|
472
|
+
function throwIfRequestAborted(req) {
|
|
473
|
+
if (req.signal.aborted)
|
|
474
|
+
throw requestAbortReason(req);
|
|
475
|
+
}
|
|
469
476
|
function assertJsonBodyLimit(maxBytes, owner) {
|
|
470
477
|
if (maxBytes !== undefined && (!Number.isSafeInteger(maxBytes) || maxBytes <= 0)) {
|
|
471
478
|
throw new Error(`${owner} must be a positive safe integer, received ${maxBytes}`);
|
|
472
479
|
}
|
|
473
480
|
}
|
|
474
481
|
async function readRequestText(req, maxBytes) {
|
|
482
|
+
throwIfRequestAborted(req);
|
|
475
483
|
if (maxBytes === undefined)
|
|
476
484
|
return req.text();
|
|
477
485
|
assertJsonBodyLimit(maxBytes, "maxJsonBodyBytes");
|
|
@@ -480,9 +488,25 @@ async function readRequestText(req, maxBytes) {
|
|
|
480
488
|
return "";
|
|
481
489
|
const chunks = [];
|
|
482
490
|
let total = 0;
|
|
491
|
+
let rejectAbortedRead = (_reason) => {
|
|
492
|
+
return;
|
|
493
|
+
};
|
|
494
|
+
const abortedRead = new Promise((_resolve, reject) => {
|
|
495
|
+
rejectAbortedRead = reject;
|
|
496
|
+
});
|
|
497
|
+
const onAbort = () => {
|
|
498
|
+
const reason = requestAbortReason(req);
|
|
499
|
+
rejectAbortedRead(reason);
|
|
500
|
+
reader.cancel(reason).catch(() => {
|
|
501
|
+
return;
|
|
502
|
+
});
|
|
503
|
+
};
|
|
504
|
+
req.signal.addEventListener("abort", onAbort, { once: true });
|
|
505
|
+
if (req.signal.aborted)
|
|
506
|
+
onAbort();
|
|
483
507
|
try {
|
|
484
508
|
while (true) {
|
|
485
|
-
const { done, value } = await reader.read();
|
|
509
|
+
const { done, value } = await Promise.race([reader.read(), abortedRead]);
|
|
486
510
|
if (done)
|
|
487
511
|
break;
|
|
488
512
|
total += value.byteLength;
|
|
@@ -493,7 +517,9 @@ async function readRequestText(req, maxBytes) {
|
|
|
493
517
|
chunks.push(value);
|
|
494
518
|
}
|
|
495
519
|
} finally {
|
|
496
|
-
|
|
520
|
+
req.signal.removeEventListener("abort", onAbort);
|
|
521
|
+
if (!req.signal.aborted)
|
|
522
|
+
reader.releaseLock();
|
|
497
523
|
}
|
|
498
524
|
const bytes = new Uint8Array(total);
|
|
499
525
|
let offset = 0;
|
|
@@ -630,6 +656,8 @@ function safePath(pathname) {
|
|
|
630
656
|
return out;
|
|
631
657
|
}
|
|
632
658
|
function levelForStatus(status) {
|
|
659
|
+
if (status === 499)
|
|
660
|
+
return "info";
|
|
633
661
|
if (status >= 500)
|
|
634
662
|
return "error";
|
|
635
663
|
if (status >= 400)
|
|
@@ -1037,6 +1065,29 @@ function validateRawRoutes(rawRoutes) {
|
|
|
1037
1065
|
|
|
1038
1066
|
// src/server/create.ts
|
|
1039
1067
|
var BODY_METHODS = new Set(["POST", "PUT", "PATCH", "DELETE"]);
|
|
1068
|
+
var MAX_REQUEST_ABORT_CAUSE_DEPTH = 8;
|
|
1069
|
+
function containsRequestAbortReason(error, reason) {
|
|
1070
|
+
let current = error;
|
|
1071
|
+
const visited = new Set;
|
|
1072
|
+
for (let depth = 0;depth <= MAX_REQUEST_ABORT_CAUSE_DEPTH; depth += 1) {
|
|
1073
|
+
if (current === reason)
|
|
1074
|
+
return true;
|
|
1075
|
+
if (depth === MAX_REQUEST_ABORT_CAUSE_DEPTH || !isRecord(current))
|
|
1076
|
+
return false;
|
|
1077
|
+
if (visited.has(current))
|
|
1078
|
+
return false;
|
|
1079
|
+
visited.add(current);
|
|
1080
|
+
current = current.cause;
|
|
1081
|
+
}
|
|
1082
|
+
return false;
|
|
1083
|
+
}
|
|
1084
|
+
function isClientClosedRequest(req, error) {
|
|
1085
|
+
if (!req.signal.aborted)
|
|
1086
|
+
return false;
|
|
1087
|
+
if (isRecord(error) && error.name === "AbortError")
|
|
1088
|
+
return true;
|
|
1089
|
+
return req.signal.reason !== undefined && containsRequestAbortReason(error, req.signal.reason);
|
|
1090
|
+
}
|
|
1040
1091
|
function createHandler(config) {
|
|
1041
1092
|
const { cors, hooks, logging = false, observability, trustProxy = false } = config;
|
|
1042
1093
|
if (cors)
|
|
@@ -1100,7 +1151,7 @@ function createHandler(config) {
|
|
|
1100
1151
|
} catch {}
|
|
1101
1152
|
}
|
|
1102
1153
|
let completed = false;
|
|
1103
|
-
const complete = (status, errorCode2) => {
|
|
1154
|
+
const complete = (status, errorCode2, outcome) => {
|
|
1104
1155
|
if (completed)
|
|
1105
1156
|
return;
|
|
1106
1157
|
completed = true;
|
|
@@ -1148,11 +1199,22 @@ function createHandler(config) {
|
|
|
1148
1199
|
const context = getRequestContext();
|
|
1149
1200
|
if (observability && context) {
|
|
1150
1201
|
try {
|
|
1151
|
-
observability.complete({
|
|
1202
|
+
observability.complete({
|
|
1203
|
+
context,
|
|
1204
|
+
statusCode: status,
|
|
1205
|
+
durationMs,
|
|
1206
|
+
payload,
|
|
1207
|
+
...outcome !== undefined && { outcome }
|
|
1208
|
+
});
|
|
1152
1209
|
} catch {}
|
|
1153
1210
|
}
|
|
1154
1211
|
};
|
|
1155
1212
|
const respondError = async (err, errCtx, endpoint) => {
|
|
1213
|
+
if (isClientClosedRequest(req, err)) {
|
|
1214
|
+
const response = applyCors(new Response(null, { status: 499, statusText: "Client Closed Request" }), cors, req);
|
|
1215
|
+
complete(response.status, undefined, "cancelled");
|
|
1216
|
+
return response;
|
|
1217
|
+
}
|
|
1156
1218
|
const recordFailure = (normalized) => {
|
|
1157
1219
|
if (getRequestContext()?.error !== undefined)
|
|
1158
1220
|
return;
|
|
@@ -9,11 +9,16 @@ import {
|
|
|
9
9
|
// src/files/boundary.ts
|
|
10
10
|
import { randomUUID } from "node:crypto";
|
|
11
11
|
import { constants } from "node:fs";
|
|
12
|
-
import { link, open, realpath, rename, stat, unlink } from "node:fs/promises";
|
|
12
|
+
import { link, mkdir, open, realpath, rename, stat, unlink } from "node:fs/promises";
|
|
13
13
|
import { basename, dirname, resolve } from "node:path";
|
|
14
14
|
var DEFAULT_MAX_BYTES = 100 * 1024 * 1024;
|
|
15
15
|
var DEFAULT_INSPECTION_BYTES = 64 * 1024;
|
|
16
|
+
var DEFAULT_INSPECTION_TIMEOUT_MS = 15000;
|
|
16
17
|
var NOFOLLOW_FLAG = constants.O_NOFOLLOW ?? 0;
|
|
18
|
+
var ManagedFileInspectionSchema = ManagedFileRefSchema.pick({
|
|
19
|
+
mediaType: true,
|
|
20
|
+
name: true
|
|
21
|
+
});
|
|
17
22
|
|
|
18
23
|
class ManagedFileError extends Error {
|
|
19
24
|
code;
|
|
@@ -47,20 +52,118 @@ function ioError(message, error) {
|
|
|
47
52
|
return error;
|
|
48
53
|
return new ManagedFileError("FILE_IO_ERROR", message, { cause: error });
|
|
49
54
|
}
|
|
55
|
+
async function realpathOrNull(path, message) {
|
|
56
|
+
try {
|
|
57
|
+
return await realpath(path);
|
|
58
|
+
} catch (error) {
|
|
59
|
+
if (errorCode(error) === "ENOENT")
|
|
60
|
+
return null;
|
|
61
|
+
throw ioError(message, error);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async function bindRoot(config) {
|
|
65
|
+
const requested = resolve(config.root);
|
|
66
|
+
let canonical = await realpathOrNull(requested, "failed to resolve managed-file root");
|
|
67
|
+
if (canonical === null && config.createRoot) {
|
|
68
|
+
const parent = await realpathOrNull(dirname(requested), "failed to resolve managed-file root parent");
|
|
69
|
+
if (parent === null) {
|
|
70
|
+
throw new ManagedFileError("FILE_NOT_FOUND", "managed-file root parent must exist");
|
|
71
|
+
}
|
|
72
|
+
const parentInfo = await stat(parent).catch((error) => {
|
|
73
|
+
throw ioError("failed to inspect managed-file root parent", error);
|
|
74
|
+
});
|
|
75
|
+
if (!parentInfo.isDirectory()) {
|
|
76
|
+
throw new ManagedFileError("FILE_NOT_REGULAR", "managed-file root parent must be a directory");
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
await mkdir(requested, { mode: 448 });
|
|
80
|
+
} catch (error) {
|
|
81
|
+
if (errorCode(error) !== "EEXIST") {
|
|
82
|
+
if (errorCode(error) === "ENOENT") {
|
|
83
|
+
throw new ManagedFileError("FILE_NOT_FOUND", "managed-file root parent must exist");
|
|
84
|
+
}
|
|
85
|
+
throw ioError("failed to create managed-file root", error);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
canonical = await realpathOrNull(requested, "failed to resolve managed-file root");
|
|
89
|
+
}
|
|
90
|
+
if (canonical === null) {
|
|
91
|
+
throw new ManagedFileError("FILE_NOT_FOUND", "managed-file root must exist");
|
|
92
|
+
}
|
|
93
|
+
const info = await stat(canonical).catch((error) => {
|
|
94
|
+
throw ioError("failed to inspect managed-file root", error);
|
|
95
|
+
});
|
|
96
|
+
if (!info.isDirectory()) {
|
|
97
|
+
throw new ManagedFileError("FILE_NOT_REGULAR", "managed-file root must be a directory");
|
|
98
|
+
}
|
|
99
|
+
return canonical;
|
|
100
|
+
}
|
|
50
101
|
async function existingParent(root, target) {
|
|
51
|
-
const parent = await
|
|
102
|
+
const parent = await realpathOrNull(dirname(target), "failed to resolve managed-file parent directory");
|
|
52
103
|
if (parent === null) {
|
|
53
104
|
throw new ManagedFileError("FILE_NOT_FOUND", "managed-file parent directory not found");
|
|
54
105
|
}
|
|
55
106
|
if (!isWithinDir(root, parent)) {
|
|
56
107
|
throw new ManagedFileError("FILE_OUTSIDE_ROOT", "managed-file path escapes its boundary");
|
|
57
108
|
}
|
|
58
|
-
const info = await stat(parent).catch(() =>
|
|
59
|
-
|
|
60
|
-
|
|
109
|
+
const info = await stat(parent).catch((error) => {
|
|
110
|
+
throw ioError("failed to inspect managed-file parent directory", error);
|
|
111
|
+
});
|
|
112
|
+
if (!info.isDirectory()) {
|
|
113
|
+
throw new ManagedFileError("FILE_NOT_REGULAR", "managed-file parent is not a directory");
|
|
61
114
|
}
|
|
62
115
|
return parent;
|
|
63
116
|
}
|
|
117
|
+
function abortReason(signal) {
|
|
118
|
+
return signal.reason ?? new DOMException("The operation was aborted", "AbortError");
|
|
119
|
+
}
|
|
120
|
+
function raceWithSignal(operation, signal) {
|
|
121
|
+
signal.throwIfAborted();
|
|
122
|
+
return new Promise((resolvePromise, rejectPromise) => {
|
|
123
|
+
let settled = false;
|
|
124
|
+
const settle = (complete) => {
|
|
125
|
+
if (settled)
|
|
126
|
+
return;
|
|
127
|
+
settled = true;
|
|
128
|
+
signal.removeEventListener("abort", onAbort);
|
|
129
|
+
complete();
|
|
130
|
+
};
|
|
131
|
+
const onAbort = () => settle(() => rejectPromise(abortReason(signal)));
|
|
132
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
133
|
+
if (signal.aborted)
|
|
134
|
+
onAbort();
|
|
135
|
+
operation.then((value) => settle(() => resolvePromise(value)), (error) => settle(() => rejectPromise(error)));
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
async function inspectFile(inspector, input, timeoutMs, outerSignal) {
|
|
139
|
+
if (!inspector)
|
|
140
|
+
return {};
|
|
141
|
+
outerSignal?.throwIfAborted();
|
|
142
|
+
const timeoutSignal = AbortSignal.timeout(timeoutMs);
|
|
143
|
+
const signal = outerSignal ? AbortSignal.any([outerSignal, timeoutSignal]) : timeoutSignal;
|
|
144
|
+
try {
|
|
145
|
+
const inspected = await raceWithSignal(Promise.resolve().then(() => inspector({ ...input, signal })), signal);
|
|
146
|
+
return ManagedFileInspectionSchema.parse(inspected);
|
|
147
|
+
} catch (error) {
|
|
148
|
+
if (outerSignal?.aborted)
|
|
149
|
+
throw abortReason(outerSignal);
|
|
150
|
+
throw new ManagedFileError("FILE_INSPECTION_REJECTED", "managed file rejected by inspection", { cause: error });
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
function inspectedRef(path, size, inspection, fallback = {}) {
|
|
154
|
+
const mediaType = inspection.mediaType ?? fallback.mediaType;
|
|
155
|
+
const name = inspection.name ?? fallback.name;
|
|
156
|
+
const parsed = ManagedFileRefSchema.safeParse({
|
|
157
|
+
path,
|
|
158
|
+
size,
|
|
159
|
+
...mediaType ? { mediaType } : {},
|
|
160
|
+
...name ? { name } : {}
|
|
161
|
+
});
|
|
162
|
+
if (!parsed.success) {
|
|
163
|
+
throw new ManagedFileError("FILE_INSPECTION_REJECTED", "managed file rejected by inspection", { cause: parsed.error });
|
|
164
|
+
}
|
|
165
|
+
return parsed.data;
|
|
166
|
+
}
|
|
64
167
|
async function readHandle(handle, maxBytes, signal) {
|
|
65
168
|
const chunks = [];
|
|
66
169
|
let total = 0;
|
|
@@ -143,13 +246,11 @@ async function writeSource(handle, source, maxBytes, inspectionBytes, signal) {
|
|
|
143
246
|
return { size, prefix };
|
|
144
247
|
}
|
|
145
248
|
async function createManagedFileBoundary(config) {
|
|
146
|
-
const root = await
|
|
147
|
-
if (root === null || !(await stat(root).catch(() => null))?.isDirectory()) {
|
|
148
|
-
throw new ManagedFileError("FILE_NOT_FOUND", "managed-file root must exist");
|
|
149
|
-
}
|
|
249
|
+
const root = await bindRoot(config);
|
|
150
250
|
const maxReadBytes = positiveLimit(config.maxReadBytes, DEFAULT_MAX_BYTES, "maxReadBytes");
|
|
151
251
|
const maxWriteBytes = positiveLimit(config.maxWriteBytes, DEFAULT_MAX_BYTES, "maxWriteBytes");
|
|
152
252
|
const inspectionBytes = positiveLimit(config.inspectionBytes, DEFAULT_INSPECTION_BYTES, "inspectionBytes");
|
|
253
|
+
const inspectionTimeoutMs = positiveLimit(config.inspectionTimeoutMs, DEFAULT_INSPECTION_TIMEOUT_MS, "inspectionTimeoutMs");
|
|
153
254
|
const targetFor = (path) => {
|
|
154
255
|
const relative = filePath(path);
|
|
155
256
|
const target = resolve(root, ...relative.split("/"));
|
|
@@ -161,7 +262,8 @@ async function createManagedFileBoundary(config) {
|
|
|
161
262
|
return {
|
|
162
263
|
async read(path, options = {}) {
|
|
163
264
|
const resolved = targetFor(path);
|
|
164
|
-
|
|
265
|
+
options.signal?.throwIfAborted();
|
|
266
|
+
const realTarget = await realpathOrNull(resolved.target, "failed to resolve managed file");
|
|
165
267
|
if (realTarget === null) {
|
|
166
268
|
throw new ManagedFileError("FILE_NOT_FOUND", "managed file not found");
|
|
167
269
|
}
|
|
@@ -177,8 +279,12 @@ async function createManagedFileBoundary(config) {
|
|
|
177
279
|
throw new ManagedFileError("FILE_NOT_REGULAR", "managed path is not a regular file");
|
|
178
280
|
}
|
|
179
281
|
const bytes = await readHandle(handle, maxBytes, options.signal);
|
|
282
|
+
const inspection = await inspectFile(config.inspect, {
|
|
283
|
+
prefix: bytes.slice(0, inspectionBytes),
|
|
284
|
+
name: basename(resolved.path)
|
|
285
|
+
}, inspectionTimeoutMs, options.signal);
|
|
180
286
|
return {
|
|
181
|
-
ref:
|
|
287
|
+
ref: inspectedRef(resolved.path, bytes.byteLength, inspection),
|
|
182
288
|
bytes
|
|
183
289
|
};
|
|
184
290
|
} catch (error) {
|
|
@@ -211,18 +317,11 @@ async function createManagedFileBoundary(config) {
|
|
|
211
317
|
await handle.sync();
|
|
212
318
|
await handle.close();
|
|
213
319
|
handle = undefined;
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
declaredMediaType: options.mediaType,
|
|
220
|
-
name: options.name ?? basename(resolved.path)
|
|
221
|
-
});
|
|
222
|
-
} catch (error) {
|
|
223
|
-
throw new ManagedFileError("FILE_INSPECTION_REJECTED", "managed file rejected by inspection", { cause: error });
|
|
224
|
-
}
|
|
225
|
-
}
|
|
320
|
+
const inspection = await inspectFile(config.inspect, {
|
|
321
|
+
prefix: written.prefix,
|
|
322
|
+
...options.mediaType ? { declaredMediaType: options.mediaType } : {},
|
|
323
|
+
name: options.name ?? basename(resolved.path)
|
|
324
|
+
}, inspectionTimeoutMs, options.signal);
|
|
226
325
|
options.signal?.throwIfAborted();
|
|
227
326
|
if (options.replace) {
|
|
228
327
|
await rename(temporary, resolved.target);
|
|
@@ -238,15 +337,10 @@ async function createManagedFileBoundary(config) {
|
|
|
238
337
|
throw error;
|
|
239
338
|
}
|
|
240
339
|
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
path: resolved.path,
|
|
245
|
-
size,
|
|
246
|
-
...mediaType ? { mediaType } : {},
|
|
247
|
-
...name ? { name } : {}
|
|
340
|
+
return inspectedRef(resolved.path, size, inspection, {
|
|
341
|
+
mediaType: options.mediaType,
|
|
342
|
+
name: options.name
|
|
248
343
|
});
|
|
249
|
-
return ref;
|
|
250
344
|
} catch (error) {
|
|
251
345
|
if (options.signal?.aborted && error === options.signal.reason)
|
|
252
346
|
throw error;
|