@bedolla/enrivision 0.1.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 +619 -0
- package/README.md +214 -0
- package/dist/client/EnriProxyClient.d.ts +323 -0
- package/dist/client/EnriProxyClient.d.ts.map +1 -0
- package/dist/client/EnriProxyClient.js +348 -0
- package/dist/client/EnriProxyClient.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +90 -0
- package/dist/index.js.map +1 -0
- package/dist/package-info.d.ts +8 -0
- package/dist/package-info.d.ts.map +1 -0
- package/dist/package-info.js +28 -0
- package/dist/package-info.js.map +1 -0
- package/dist/server/EnriVisionServer.d.ts +63 -0
- package/dist/server/EnriVisionServer.d.ts.map +1 -0
- package/dist/server/EnriVisionServer.js +246 -0
- package/dist/server/EnriVisionServer.js.map +1 -0
- package/dist/shared/tar.d.ts +108 -0
- package/dist/shared/tar.d.ts.map +1 -0
- package/dist/shared/tar.js +346 -0
- package/dist/shared/tar.js.map +1 -0
- package/dist/shared/validation.d.ts +61 -0
- package/dist/shared/validation.d.ts.map +1 -0
- package/dist/shared/validation.js +107 -0
- package/dist/shared/validation.js.map +1 -0
- package/dist/tools/AnalyzeMediaTool.d.ts +302 -0
- package/dist/tools/AnalyzeMediaTool.d.ts.map +1 -0
- package/dist/tools/AnalyzeMediaTool.js +509 -0
- package/dist/tools/AnalyzeMediaTool.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TAR UTILITIES
|
|
3
|
+
*
|
|
4
|
+
* Small, dependency-free tar (ustar) helpers used to package multiple local
|
|
5
|
+
* files into a single resumable upload stream.
|
|
6
|
+
*
|
|
7
|
+
* @module shared/tar
|
|
8
|
+
*/
|
|
9
|
+
import { open } from "node:fs/promises";
|
|
10
|
+
/**
|
|
11
|
+
* Computes the total tar size in bytes, including the 1024-byte end marker.
|
|
12
|
+
*
|
|
13
|
+
* @param entries - Tar entries
|
|
14
|
+
* @returns Total tar size in bytes
|
|
15
|
+
*/
|
|
16
|
+
export function computeTarSizeBytes(entries) {
|
|
17
|
+
let total = 0;
|
|
18
|
+
for (const entry of entries) {
|
|
19
|
+
total += 512;
|
|
20
|
+
const contentSize = entry.source.type === "buffer" ? entry.source.buffer.length : entry.source.sizeBytes;
|
|
21
|
+
total += contentSize;
|
|
22
|
+
total += computePaddingSize(contentSize);
|
|
23
|
+
}
|
|
24
|
+
// Two 512-byte zero blocks.
|
|
25
|
+
total += 1024;
|
|
26
|
+
return total;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Streaming tar generator that can start from an arbitrary byte offset.
|
|
30
|
+
*/
|
|
31
|
+
export class TarStream {
|
|
32
|
+
/**
|
|
33
|
+
* Precomputed tar layout.
|
|
34
|
+
*/
|
|
35
|
+
layout;
|
|
36
|
+
/**
|
|
37
|
+
* Total tar size.
|
|
38
|
+
*/
|
|
39
|
+
totalSizeBytes;
|
|
40
|
+
/**
|
|
41
|
+
* Creates a new {@link TarStream}.
|
|
42
|
+
*
|
|
43
|
+
* @param entries - Tar entries in order
|
|
44
|
+
*/
|
|
45
|
+
constructor(entries) {
|
|
46
|
+
const normalized = [];
|
|
47
|
+
let cursor = 0;
|
|
48
|
+
for (const entry of entries) {
|
|
49
|
+
const name = entry.name;
|
|
50
|
+
if (!isSafeTarName(name)) {
|
|
51
|
+
throw new Error(`Invalid tar entry name: ${name}`);
|
|
52
|
+
}
|
|
53
|
+
const contentSize = entry.source.type === "buffer" ? entry.source.buffer.length : entry.source.sizeBytes;
|
|
54
|
+
const header = buildUstarHeader(name, contentSize, entry.mtimeSeconds);
|
|
55
|
+
const paddingSize = computePaddingSize(contentSize);
|
|
56
|
+
const totalSize = 512 + contentSize + paddingSize;
|
|
57
|
+
normalized.push({
|
|
58
|
+
name,
|
|
59
|
+
header,
|
|
60
|
+
source: entry.source,
|
|
61
|
+
headerStart: cursor,
|
|
62
|
+
contentStart: cursor + 512,
|
|
63
|
+
contentSize,
|
|
64
|
+
paddingSize,
|
|
65
|
+
totalSize
|
|
66
|
+
});
|
|
67
|
+
cursor += totalSize;
|
|
68
|
+
}
|
|
69
|
+
this.layout = normalized;
|
|
70
|
+
this.totalSizeBytes = cursor + 1024;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Returns the total tar size in bytes.
|
|
74
|
+
*
|
|
75
|
+
* @returns Total size
|
|
76
|
+
*/
|
|
77
|
+
getSizeBytes() {
|
|
78
|
+
return this.totalSizeBytes;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Iterates tar bytes as chunks, starting from a given offset.
|
|
82
|
+
*
|
|
83
|
+
* @param startOffset - Starting byte offset (for resumable uploads)
|
|
84
|
+
* @param chunkSize - Maximum bytes per yielded chunk
|
|
85
|
+
* @returns Async iterator of buffers
|
|
86
|
+
*/
|
|
87
|
+
async *iterateChunks(startOffset, chunkSize) {
|
|
88
|
+
const normalizedStart = Math.max(0, Math.floor(startOffset));
|
|
89
|
+
const normalizedChunk = Math.max(1, Math.floor(chunkSize));
|
|
90
|
+
if (normalizedStart >= this.totalSizeBytes) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
let position = normalizedStart;
|
|
94
|
+
const state = this.seek(position);
|
|
95
|
+
while (position < this.totalSizeBytes) {
|
|
96
|
+
const remainingTar = this.totalSizeBytes - position;
|
|
97
|
+
const desired = Math.min(normalizedChunk, remainingTar);
|
|
98
|
+
const parts = [];
|
|
99
|
+
let remaining = desired;
|
|
100
|
+
let emptyReadsInARow = 0;
|
|
101
|
+
while (remaining > 0) {
|
|
102
|
+
const read = await this.readNext(state, remaining);
|
|
103
|
+
if (read.length <= 0) {
|
|
104
|
+
emptyReadsInARow += 1;
|
|
105
|
+
if (emptyReadsInARow > 50) {
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
emptyReadsInARow = 0;
|
|
111
|
+
parts.push(read);
|
|
112
|
+
remaining -= read.length;
|
|
113
|
+
position += read.length;
|
|
114
|
+
}
|
|
115
|
+
if (parts.length === 0) {
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
yield parts.length === 1 ? parts[0] : Buffer.concat(parts);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Internal seek state for reading.
|
|
123
|
+
*/
|
|
124
|
+
seek(offset) {
|
|
125
|
+
let cursor = 0;
|
|
126
|
+
for (let i = 0; i < this.layout.length; i++) {
|
|
127
|
+
const entry = this.layout[i];
|
|
128
|
+
const next = cursor + entry.totalSize;
|
|
129
|
+
if (offset < next) {
|
|
130
|
+
const rel = offset - cursor;
|
|
131
|
+
if (rel < 512) {
|
|
132
|
+
return { phase: "entry_header", entryIndex: i, phaseOffset: rel, fileHandle: null };
|
|
133
|
+
}
|
|
134
|
+
const relContent = rel - 512;
|
|
135
|
+
if (relContent < entry.contentSize) {
|
|
136
|
+
return { phase: "entry_content", entryIndex: i, phaseOffset: relContent, fileHandle: null };
|
|
137
|
+
}
|
|
138
|
+
const relPadding = relContent - entry.contentSize;
|
|
139
|
+
return { phase: "entry_padding", entryIndex: i, phaseOffset: relPadding, fileHandle: null };
|
|
140
|
+
}
|
|
141
|
+
cursor = next;
|
|
142
|
+
}
|
|
143
|
+
const eofStart = cursor;
|
|
144
|
+
const eofOffset = offset - eofStart;
|
|
145
|
+
return { phase: "eof", entryIndex: this.layout.length, phaseOffset: eofOffset, fileHandle: null };
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Reads up to maxBytes from the current state and advances the state.
|
|
149
|
+
*/
|
|
150
|
+
async readNext(state, maxBytes) {
|
|
151
|
+
const want = Math.max(1, Math.floor(maxBytes));
|
|
152
|
+
if (state.phase === "eof") {
|
|
153
|
+
const remaining = Math.max(0, 1024 - state.phaseOffset);
|
|
154
|
+
if (remaining <= 0) {
|
|
155
|
+
return Buffer.alloc(0);
|
|
156
|
+
}
|
|
157
|
+
const take = Math.min(want, remaining);
|
|
158
|
+
state.phaseOffset += take;
|
|
159
|
+
return Buffer.alloc(take, 0);
|
|
160
|
+
}
|
|
161
|
+
const entry = this.layout[state.entryIndex];
|
|
162
|
+
if (state.phase === "entry_header") {
|
|
163
|
+
const remaining = Math.max(0, 512 - state.phaseOffset);
|
|
164
|
+
const take = Math.min(want, remaining);
|
|
165
|
+
const out = entry.header.subarray(state.phaseOffset, state.phaseOffset + take);
|
|
166
|
+
state.phaseOffset += take;
|
|
167
|
+
if (state.phaseOffset >= 512) {
|
|
168
|
+
state.phase = "entry_content";
|
|
169
|
+
state.phaseOffset = 0;
|
|
170
|
+
}
|
|
171
|
+
return out;
|
|
172
|
+
}
|
|
173
|
+
if (state.phase === "entry_content") {
|
|
174
|
+
const remaining = Math.max(0, entry.contentSize - state.phaseOffset);
|
|
175
|
+
if (remaining <= 0) {
|
|
176
|
+
state.phase = "entry_padding";
|
|
177
|
+
state.phaseOffset = 0;
|
|
178
|
+
await this.closeFileHandle(state);
|
|
179
|
+
return Buffer.alloc(0);
|
|
180
|
+
}
|
|
181
|
+
const take = Math.min(want, remaining);
|
|
182
|
+
if (entry.source.type === "buffer") {
|
|
183
|
+
const buf = entry.source.buffer.subarray(state.phaseOffset, state.phaseOffset + take);
|
|
184
|
+
state.phaseOffset += take;
|
|
185
|
+
if (state.phaseOffset >= entry.contentSize) {
|
|
186
|
+
state.phase = "entry_padding";
|
|
187
|
+
state.phaseOffset = 0;
|
|
188
|
+
}
|
|
189
|
+
return buf;
|
|
190
|
+
}
|
|
191
|
+
const handle = await this.ensureFileHandle(state, entry.source.path);
|
|
192
|
+
const buffer = Buffer.allocUnsafe(take);
|
|
193
|
+
const read = await handle.read(buffer, 0, take, state.phaseOffset);
|
|
194
|
+
if (read.bytesRead <= 0) {
|
|
195
|
+
await this.closeFileHandle(state);
|
|
196
|
+
state.phase = "entry_padding";
|
|
197
|
+
state.phaseOffset = 0;
|
|
198
|
+
return Buffer.alloc(0);
|
|
199
|
+
}
|
|
200
|
+
state.phaseOffset += read.bytesRead;
|
|
201
|
+
const out = read.bytesRead === buffer.length ? buffer : buffer.subarray(0, read.bytesRead);
|
|
202
|
+
if (state.phaseOffset >= entry.contentSize) {
|
|
203
|
+
await this.closeFileHandle(state);
|
|
204
|
+
state.phase = "entry_padding";
|
|
205
|
+
state.phaseOffset = 0;
|
|
206
|
+
}
|
|
207
|
+
return out;
|
|
208
|
+
}
|
|
209
|
+
// entry_padding
|
|
210
|
+
const remaining = Math.max(0, entry.paddingSize - state.phaseOffset);
|
|
211
|
+
if (remaining <= 0) {
|
|
212
|
+
state.entryIndex += 1;
|
|
213
|
+
state.phaseOffset = 0;
|
|
214
|
+
state.fileHandle = null;
|
|
215
|
+
if (state.entryIndex >= this.layout.length) {
|
|
216
|
+
state.phase = "eof";
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
state.phase = "entry_header";
|
|
220
|
+
}
|
|
221
|
+
return Buffer.alloc(0);
|
|
222
|
+
}
|
|
223
|
+
const take = Math.min(want, remaining);
|
|
224
|
+
state.phaseOffset += take;
|
|
225
|
+
if (state.phaseOffset >= entry.paddingSize) {
|
|
226
|
+
state.entryIndex += 1;
|
|
227
|
+
state.phaseOffset = 0;
|
|
228
|
+
state.fileHandle = null;
|
|
229
|
+
if (state.entryIndex >= this.layout.length) {
|
|
230
|
+
state.phase = "eof";
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
state.phase = "entry_header";
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return Buffer.alloc(take, 0);
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Ensures a file handle is open for the current file-backed entry.
|
|
240
|
+
*/
|
|
241
|
+
async ensureFileHandle(state, filePath) {
|
|
242
|
+
if (state.fileHandle) {
|
|
243
|
+
return state.fileHandle;
|
|
244
|
+
}
|
|
245
|
+
state.fileHandle = await open(filePath, "r");
|
|
246
|
+
return state.fileHandle;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Closes any open file handle for the current state.
|
|
250
|
+
*/
|
|
251
|
+
async closeFileHandle(state) {
|
|
252
|
+
if (!state.fileHandle) {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
try {
|
|
256
|
+
await state.fileHandle.close();
|
|
257
|
+
}
|
|
258
|
+
finally {
|
|
259
|
+
state.fileHandle = null;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Computes tar padding size for a payload length.
|
|
265
|
+
*/
|
|
266
|
+
function computePaddingSize(sizeBytes) {
|
|
267
|
+
const mod = sizeBytes % 512;
|
|
268
|
+
return mod === 0 ? 0 : 512 - mod;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Validates that a name is safe for a simple ustar header.
|
|
272
|
+
*/
|
|
273
|
+
function isSafeTarName(name) {
|
|
274
|
+
const normalized = name.trim();
|
|
275
|
+
if (!normalized) {
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
278
|
+
if (normalized.includes("\u0000")) {
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
// Keep it simple: only basenames, no directories.
|
|
282
|
+
if (normalized.includes("/") || normalized.includes("\\") || normalized.includes(":")) {
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
const bytes = Buffer.byteLength(normalized, "utf8");
|
|
286
|
+
return bytes > 0 && bytes <= 100 && /^[A-Za-z0-9._-]{1,100}$/.test(normalized);
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Builds a ustar header block for a regular file.
|
|
290
|
+
*/
|
|
291
|
+
function buildUstarHeader(name, sizeBytes, mtimeSeconds) {
|
|
292
|
+
const buf = Buffer.alloc(512, 0);
|
|
293
|
+
writeString(buf, 0, 100, name);
|
|
294
|
+
writeOctal(buf, 100, 8, 0o644);
|
|
295
|
+
writeOctal(buf, 108, 8, 0);
|
|
296
|
+
writeOctal(buf, 116, 8, 0);
|
|
297
|
+
writeOctal(buf, 124, 12, sizeBytes);
|
|
298
|
+
writeOctal(buf, 136, 12, Math.max(0, Math.floor(mtimeSeconds)));
|
|
299
|
+
// Checksum field: 8 bytes, initially filled with spaces.
|
|
300
|
+
buf.fill(0x20, 148, 156);
|
|
301
|
+
// Typeflag '0' (regular file).
|
|
302
|
+
buf[156] = 0x30;
|
|
303
|
+
// UStar magic + version.
|
|
304
|
+
writeString(buf, 257, 6, "ustar\0");
|
|
305
|
+
writeString(buf, 263, 2, "00");
|
|
306
|
+
const checksum = computeTarChecksum(buf);
|
|
307
|
+
writeChecksum(buf, checksum);
|
|
308
|
+
return buf;
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Writes a fixed-width string field (null-padded).
|
|
312
|
+
*/
|
|
313
|
+
function writeString(buf, offset, length, value) {
|
|
314
|
+
const bytes = Buffer.from(value, "utf8");
|
|
315
|
+
bytes.copy(buf, offset, 0, Math.min(bytes.length, length));
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Writes a fixed-width octal number field.
|
|
319
|
+
*/
|
|
320
|
+
function writeOctal(buf, offset, length, value) {
|
|
321
|
+
const raw = Math.max(0, Math.floor(value));
|
|
322
|
+
const oct = raw.toString(8);
|
|
323
|
+
const padded = oct.padStart(Math.max(0, length - 1), "0");
|
|
324
|
+
const field = `${padded}\0`;
|
|
325
|
+
writeString(buf, offset, length, field);
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Computes tar header checksum.
|
|
329
|
+
*/
|
|
330
|
+
function computeTarChecksum(buf) {
|
|
331
|
+
let sum = 0;
|
|
332
|
+
for (let i = 0; i < buf.length; i++) {
|
|
333
|
+
sum += buf[i] ?? 0;
|
|
334
|
+
}
|
|
335
|
+
return sum;
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Writes tar checksum field (6 octal digits + null + space).
|
|
339
|
+
*/
|
|
340
|
+
function writeChecksum(buf, checksum) {
|
|
341
|
+
const oct = Math.max(0, Math.floor(checksum)).toString(8).padStart(6, "0");
|
|
342
|
+
writeString(buf, 148, 6, oct);
|
|
343
|
+
buf[154] = 0;
|
|
344
|
+
buf[155] = 0x20;
|
|
345
|
+
}
|
|
346
|
+
//# sourceMappingURL=tar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tar.js","sourceRoot":"","sources":["../../src/shared/tar.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VALIDATION HELPERS
|
|
3
|
+
*
|
|
4
|
+
* Small, dependency-free runtime validation utilities for MCP tool inputs and
|
|
5
|
+
* server responses.
|
|
6
|
+
*
|
|
7
|
+
* @module shared/validation
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Asserts that a value is a non-null object (but not an array).
|
|
11
|
+
*
|
|
12
|
+
* @param value - Value to validate
|
|
13
|
+
* @param name - Human-readable field name for error messages
|
|
14
|
+
* @returns The value as a record
|
|
15
|
+
*/
|
|
16
|
+
export declare function assertObject(value: unknown, name: string): Record<string, unknown>;
|
|
17
|
+
/**
|
|
18
|
+
* Asserts that a value is a non-empty string.
|
|
19
|
+
*
|
|
20
|
+
* @param value - Value to validate
|
|
21
|
+
* @param name - Human-readable field name for error messages
|
|
22
|
+
* @returns Trimmed string
|
|
23
|
+
*/
|
|
24
|
+
export declare function assertNonEmptyString(value: unknown, name: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* Returns a trimmed string when the value is a string, otherwise undefined.
|
|
27
|
+
*
|
|
28
|
+
* @param value - Value to validate
|
|
29
|
+
* @returns Trimmed string or undefined
|
|
30
|
+
*/
|
|
31
|
+
export declare function optionalString(value: unknown): string | undefined;
|
|
32
|
+
/**
|
|
33
|
+
* Returns an integer when the value is a number or numeric string, otherwise undefined.
|
|
34
|
+
*
|
|
35
|
+
* @param value - Value to validate
|
|
36
|
+
* @returns Parsed integer or undefined
|
|
37
|
+
*/
|
|
38
|
+
export declare function optionalInt(value: unknown): number | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* Returns a number when the value is a number or numeric string, otherwise undefined.
|
|
41
|
+
*
|
|
42
|
+
* @param value - Value to validate
|
|
43
|
+
* @returns Parsed number or undefined
|
|
44
|
+
*/
|
|
45
|
+
export declare function optionalNumber(value: unknown): number | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* Returns a boolean when the value is a boolean, otherwise undefined.
|
|
48
|
+
*
|
|
49
|
+
* @param value - Value to validate
|
|
50
|
+
* @returns Boolean or undefined
|
|
51
|
+
*/
|
|
52
|
+
export declare function optionalBoolean(value: unknown): boolean | undefined;
|
|
53
|
+
/**
|
|
54
|
+
* Asserts that a string looks like an HTTP(S) URL.
|
|
55
|
+
*
|
|
56
|
+
* @param value - Value to validate
|
|
57
|
+
* @param name - Field name
|
|
58
|
+
* @returns Normalized URL string
|
|
59
|
+
*/
|
|
60
|
+
export declare function assertHttpUrl(value: unknown, name: string): string;
|
|
61
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/shared/validation.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAKlF;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CASzE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAMjE;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAS9D;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CASjE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,CAEnE;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMlE"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VALIDATION HELPERS
|
|
3
|
+
*
|
|
4
|
+
* Small, dependency-free runtime validation utilities for MCP tool inputs and
|
|
5
|
+
* server responses.
|
|
6
|
+
*
|
|
7
|
+
* @module shared/validation
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Asserts that a value is a non-null object (but not an array).
|
|
11
|
+
*
|
|
12
|
+
* @param value - Value to validate
|
|
13
|
+
* @param name - Human-readable field name for error messages
|
|
14
|
+
* @returns The value as a record
|
|
15
|
+
*/
|
|
16
|
+
export function assertObject(value, name) {
|
|
17
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
18
|
+
throw new Error(`${name} must be an object.`);
|
|
19
|
+
}
|
|
20
|
+
return value;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Asserts that a value is a non-empty string.
|
|
24
|
+
*
|
|
25
|
+
* @param value - Value to validate
|
|
26
|
+
* @param name - Human-readable field name for error messages
|
|
27
|
+
* @returns Trimmed string
|
|
28
|
+
*/
|
|
29
|
+
export function assertNonEmptyString(value, name) {
|
|
30
|
+
if (typeof value !== "string") {
|
|
31
|
+
throw new Error(`${name} must be a string.`);
|
|
32
|
+
}
|
|
33
|
+
const trimmed = value.trim();
|
|
34
|
+
if (!trimmed) {
|
|
35
|
+
throw new Error(`${name} must be a non-empty string.`);
|
|
36
|
+
}
|
|
37
|
+
return trimmed;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Returns a trimmed string when the value is a string, otherwise undefined.
|
|
41
|
+
*
|
|
42
|
+
* @param value - Value to validate
|
|
43
|
+
* @returns Trimmed string or undefined
|
|
44
|
+
*/
|
|
45
|
+
export function optionalString(value) {
|
|
46
|
+
if (typeof value !== "string") {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
const trimmed = value.trim();
|
|
50
|
+
return trimmed ? trimmed : undefined;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Returns an integer when the value is a number or numeric string, otherwise undefined.
|
|
54
|
+
*
|
|
55
|
+
* @param value - Value to validate
|
|
56
|
+
* @returns Parsed integer or undefined
|
|
57
|
+
*/
|
|
58
|
+
export function optionalInt(value) {
|
|
59
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
60
|
+
return Math.floor(value);
|
|
61
|
+
}
|
|
62
|
+
if (typeof value === "string" && value.trim()) {
|
|
63
|
+
const parsed = Number.parseInt(value.trim(), 10);
|
|
64
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
65
|
+
}
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Returns a number when the value is a number or numeric string, otherwise undefined.
|
|
70
|
+
*
|
|
71
|
+
* @param value - Value to validate
|
|
72
|
+
* @returns Parsed number or undefined
|
|
73
|
+
*/
|
|
74
|
+
export function optionalNumber(value) {
|
|
75
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
76
|
+
return value;
|
|
77
|
+
}
|
|
78
|
+
if (typeof value === "string" && value.trim()) {
|
|
79
|
+
const parsed = Number.parseFloat(value.trim());
|
|
80
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
81
|
+
}
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Returns a boolean when the value is a boolean, otherwise undefined.
|
|
86
|
+
*
|
|
87
|
+
* @param value - Value to validate
|
|
88
|
+
* @returns Boolean or undefined
|
|
89
|
+
*/
|
|
90
|
+
export function optionalBoolean(value) {
|
|
91
|
+
return typeof value === "boolean" ? value : undefined;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Asserts that a string looks like an HTTP(S) URL.
|
|
95
|
+
*
|
|
96
|
+
* @param value - Value to validate
|
|
97
|
+
* @param name - Field name
|
|
98
|
+
* @returns Normalized URL string
|
|
99
|
+
*/
|
|
100
|
+
export function assertHttpUrl(value, name) {
|
|
101
|
+
const url = assertNonEmptyString(value, name);
|
|
102
|
+
if (!url.startsWith("http://") && !url.startsWith("https://")) {
|
|
103
|
+
throw new Error(`${name} must start with http:// or https://`);
|
|
104
|
+
}
|
|
105
|
+
return url.replace(/\/+$/, "");
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/shared/validation.ts"],"names":[],"mappings":"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"}
|