@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.
@@ -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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"}