@rcrsr/rill 0.8.0 → 0.8.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/README.md +28 -0
- package/dist/error-registry.d.ts.map +1 -1
- package/dist/error-registry.js +164 -0
- package/dist/error-registry.js.map +1 -1
- package/dist/ext/crypto/index.d.ts +32 -0
- package/dist/ext/crypto/index.d.ts.map +1 -0
- package/dist/ext/crypto/index.js +143 -0
- package/dist/ext/crypto/index.js.map +1 -0
- package/dist/ext/exec/index.d.ts +45 -0
- package/dist/ext/exec/index.d.ts.map +1 -0
- package/dist/ext/exec/index.js +168 -0
- package/dist/ext/exec/index.js.map +1 -0
- package/dist/ext/exec/runner.d.ts +62 -0
- package/dist/ext/exec/runner.d.ts.map +1 -0
- package/dist/ext/exec/runner.js +168 -0
- package/dist/ext/exec/runner.js.map +1 -0
- package/dist/ext/fetch/index.d.ts +68 -0
- package/dist/ext/fetch/index.d.ts.map +1 -0
- package/dist/ext/fetch/index.js +259 -0
- package/dist/ext/fetch/index.js.map +1 -0
- package/dist/ext/fetch/request.d.ts +90 -0
- package/dist/ext/fetch/request.d.ts.map +1 -0
- package/dist/ext/fetch/request.js +413 -0
- package/dist/ext/fetch/request.js.map +1 -0
- package/dist/ext/fs/index.d.ts +39 -0
- package/dist/ext/fs/index.d.ts.map +1 -0
- package/dist/ext/fs/index.js +560 -0
- package/dist/ext/fs/index.js.map +1 -0
- package/dist/ext/fs/sandbox.d.ts +78 -0
- package/dist/ext/fs/sandbox.d.ts.map +1 -0
- package/dist/ext/fs/sandbox.js +208 -0
- package/dist/ext/fs/sandbox.js.map +1 -0
- package/dist/ext/kv/index.d.ts +46 -0
- package/dist/ext/kv/index.d.ts.map +1 -0
- package/dist/ext/kv/index.js +215 -0
- package/dist/ext/kv/index.js.map +1 -0
- package/dist/ext/kv/store.d.ts +46 -0
- package/dist/ext/kv/store.d.ts.map +1 -0
- package/dist/ext/kv/store.js +256 -0
- package/dist/ext/kv/store.js.map +1 -0
- package/dist/generated/version-data.d.ts +1 -1
- package/dist/generated/version-data.js +2 -2
- package/package.json +37 -11
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetch Request Module
|
|
3
|
+
* Handles URL building, retry logic, response parsing, and error handling
|
|
4
|
+
*/
|
|
5
|
+
import { RuntimeError } from '../../error-classes.js';
|
|
6
|
+
// ============================================================
|
|
7
|
+
// CONCURRENCY SEMAPHORE
|
|
8
|
+
// ============================================================
|
|
9
|
+
/**
|
|
10
|
+
* Simple semaphore for limiting concurrent requests.
|
|
11
|
+
* Queues requests when limit is reached.
|
|
12
|
+
*/
|
|
13
|
+
class Semaphore {
|
|
14
|
+
permits;
|
|
15
|
+
queue = [];
|
|
16
|
+
constructor(permits) {
|
|
17
|
+
this.permits = permits;
|
|
18
|
+
}
|
|
19
|
+
async acquire() {
|
|
20
|
+
if (this.permits > 0) {
|
|
21
|
+
this.permits--;
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
return new Promise((resolve) => {
|
|
25
|
+
this.queue.push(resolve);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
release() {
|
|
29
|
+
const next = this.queue.shift();
|
|
30
|
+
if (next) {
|
|
31
|
+
next();
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
this.permits++;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// ============================================================
|
|
39
|
+
// URL BUILDING
|
|
40
|
+
// ============================================================
|
|
41
|
+
/**
|
|
42
|
+
* Interpolate path parameters in URL pattern.
|
|
43
|
+
* Replaces `:param` placeholders with values from pathArgs.
|
|
44
|
+
*
|
|
45
|
+
* @param pattern - URL pattern with :param placeholders
|
|
46
|
+
* @param pathArgs - Map of parameter names to values
|
|
47
|
+
* @returns Interpolated URL path
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* interpolatePathParams('/users/:id/posts/:postId', { id: '123', postId: '456' })
|
|
51
|
+
* // Returns: '/users/123/posts/456'
|
|
52
|
+
*/
|
|
53
|
+
function interpolatePathParams(pattern, pathArgs) {
|
|
54
|
+
return pattern.replace(/:([a-zA-Z_][a-zA-Z0-9_]*)/g, (_match, paramName) => {
|
|
55
|
+
const value = pathArgs.get(paramName);
|
|
56
|
+
if (value === undefined) {
|
|
57
|
+
throw new TypeError(`Missing path parameter: ${paramName}`);
|
|
58
|
+
}
|
|
59
|
+
return encodeURIComponent(value);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Build query string from query arguments.
|
|
64
|
+
*
|
|
65
|
+
* @param queryArgs - Map of query parameter names to values
|
|
66
|
+
* @returns Query string (without leading ?)
|
|
67
|
+
*/
|
|
68
|
+
function buildQueryString(queryArgs) {
|
|
69
|
+
const params = new URLSearchParams();
|
|
70
|
+
for (const [key, value] of queryArgs) {
|
|
71
|
+
params.append(key, value);
|
|
72
|
+
}
|
|
73
|
+
return params.toString();
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Build full URL from base, path pattern, and arguments.
|
|
77
|
+
*
|
|
78
|
+
* @param baseUrl - Base URL
|
|
79
|
+
* @param pathPattern - URL path pattern with :param placeholders
|
|
80
|
+
* @param pathArgs - Path parameter values
|
|
81
|
+
* @param queryArgs - Query parameter values
|
|
82
|
+
* @returns Complete URL
|
|
83
|
+
*/
|
|
84
|
+
function buildUrl(baseUrl, pathPattern, pathArgs, queryArgs) {
|
|
85
|
+
const path = interpolatePathParams(pathPattern, pathArgs);
|
|
86
|
+
const url = new URL(path, baseUrl);
|
|
87
|
+
const queryString = buildQueryString(queryArgs);
|
|
88
|
+
if (queryString) {
|
|
89
|
+
url.search = queryString;
|
|
90
|
+
}
|
|
91
|
+
return url.toString();
|
|
92
|
+
}
|
|
93
|
+
// ============================================================
|
|
94
|
+
// HEADER HANDLING
|
|
95
|
+
// ============================================================
|
|
96
|
+
/**
|
|
97
|
+
* Flatten multi-value headers to string-to-string dict.
|
|
98
|
+
* Multiple values joined with `, `.
|
|
99
|
+
*
|
|
100
|
+
* @param headers - Headers object from fetch Response
|
|
101
|
+
* @returns Flattened headers dict
|
|
102
|
+
*/
|
|
103
|
+
function flattenHeaders(headers) {
|
|
104
|
+
const result = {};
|
|
105
|
+
headers.forEach((value, key) => {
|
|
106
|
+
result[key] = value;
|
|
107
|
+
});
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Resolve dynamic headers (call function if provided).
|
|
112
|
+
*
|
|
113
|
+
* @param headers - Static headers or function returning headers
|
|
114
|
+
* @returns Resolved headers dict
|
|
115
|
+
*/
|
|
116
|
+
function resolveHeaders(headers) {
|
|
117
|
+
if (!headers)
|
|
118
|
+
return {};
|
|
119
|
+
if (typeof headers === 'function')
|
|
120
|
+
return headers();
|
|
121
|
+
return headers;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Merge headers with endpoint headers taking precedence.
|
|
125
|
+
*
|
|
126
|
+
* @param globalHeaders - Global extension headers
|
|
127
|
+
* @param endpointHeaders - Endpoint-specific headers
|
|
128
|
+
* @returns Merged headers dict
|
|
129
|
+
*/
|
|
130
|
+
function mergeHeaders(globalHeaders, endpointHeaders) {
|
|
131
|
+
return { ...globalHeaders, ...(endpointHeaders || {}) };
|
|
132
|
+
}
|
|
133
|
+
// ============================================================
|
|
134
|
+
// RESPONSE PARSING
|
|
135
|
+
// ============================================================
|
|
136
|
+
/**
|
|
137
|
+
* Parse response body as JSON.
|
|
138
|
+
* Throws RuntimeError on invalid JSON.
|
|
139
|
+
*
|
|
140
|
+
* @param response - Fetch Response object
|
|
141
|
+
* @param namespace - Extension namespace for error messages
|
|
142
|
+
* @returns Parsed JSON body
|
|
143
|
+
*/
|
|
144
|
+
async function parseJsonResponse(response, namespace) {
|
|
145
|
+
const text = await response.text();
|
|
146
|
+
try {
|
|
147
|
+
return JSON.parse(text);
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
throw new RuntimeError('RILL-R026', `${namespace}: invalid JSON response`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Build full response object with status, headers, and body.
|
|
155
|
+
*
|
|
156
|
+
* @param response - Fetch Response object
|
|
157
|
+
* @param namespace - Extension namespace for error messages
|
|
158
|
+
* @returns Full response object
|
|
159
|
+
*/
|
|
160
|
+
async function buildFullResponse(response, namespace) {
|
|
161
|
+
const body = await parseJsonResponse(response, namespace);
|
|
162
|
+
return {
|
|
163
|
+
status: response.status,
|
|
164
|
+
headers: flattenHeaders(response.headers),
|
|
165
|
+
body,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
// ============================================================
|
|
169
|
+
// RETRY LOGIC
|
|
170
|
+
// ============================================================
|
|
171
|
+
/**
|
|
172
|
+
* Check if status code should be retried.
|
|
173
|
+
* Retry on: 429, 502, 503, 504
|
|
174
|
+
*
|
|
175
|
+
* @param status - HTTP status code
|
|
176
|
+
* @returns true if status should be retried
|
|
177
|
+
*/
|
|
178
|
+
function shouldRetryStatus(status) {
|
|
179
|
+
return status === 429 || status === 502 || status === 503 || status === 504;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Extract Retry-After header value in seconds.
|
|
183
|
+
* Supports both delay-seconds and HTTP-date formats.
|
|
184
|
+
*
|
|
185
|
+
* @param response - Fetch Response object
|
|
186
|
+
* @returns Retry delay in milliseconds, or null if not present
|
|
187
|
+
*/
|
|
188
|
+
function getRetryAfterMs(response) {
|
|
189
|
+
const retryAfter = response.headers.get('Retry-After');
|
|
190
|
+
if (!retryAfter)
|
|
191
|
+
return null;
|
|
192
|
+
// Try parsing as seconds
|
|
193
|
+
const seconds = parseInt(retryAfter, 10);
|
|
194
|
+
if (!isNaN(seconds)) {
|
|
195
|
+
return seconds * 1000;
|
|
196
|
+
}
|
|
197
|
+
// Try parsing as HTTP date
|
|
198
|
+
const date = new Date(retryAfter);
|
|
199
|
+
if (!isNaN(date.getTime())) {
|
|
200
|
+
return Math.max(0, date.getTime() - Date.now());
|
|
201
|
+
}
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Calculate exponential backoff delay.
|
|
206
|
+
*
|
|
207
|
+
* @param baseDelay - Base delay in milliseconds
|
|
208
|
+
* @param attempt - Attempt number (0-indexed)
|
|
209
|
+
* @returns Delay in milliseconds
|
|
210
|
+
*/
|
|
211
|
+
function calculateBackoff(baseDelay, attempt) {
|
|
212
|
+
return baseDelay * Math.pow(2, attempt);
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Sleep for specified duration.
|
|
216
|
+
*
|
|
217
|
+
* @param ms - Milliseconds to sleep
|
|
218
|
+
*/
|
|
219
|
+
function sleep(ms) {
|
|
220
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
221
|
+
}
|
|
222
|
+
// ============================================================
|
|
223
|
+
// REQUEST EXECUTION
|
|
224
|
+
// ============================================================
|
|
225
|
+
/**
|
|
226
|
+
* Execute HTTP request with retry logic.
|
|
227
|
+
* Handles timeouts, network errors, and retries.
|
|
228
|
+
*
|
|
229
|
+
* @param url - Request URL
|
|
230
|
+
* @param options - Fetch options
|
|
231
|
+
* @param config - Extension configuration
|
|
232
|
+
* @param namespace - Extension namespace for error messages
|
|
233
|
+
* @param semaphore - Concurrency semaphore (optional)
|
|
234
|
+
* @returns Response body or full response
|
|
235
|
+
*/
|
|
236
|
+
export async function executeRequest(url, options, config, namespace, responseShape, semaphore) {
|
|
237
|
+
const retryLimit = config.retryLimit ?? 3;
|
|
238
|
+
const retryDelay = config.retryDelay ?? 100;
|
|
239
|
+
const timeoutMs = config.timeout ?? 30000;
|
|
240
|
+
let lastError = null;
|
|
241
|
+
let attempt = 0;
|
|
242
|
+
while (attempt <= retryLimit) {
|
|
243
|
+
try {
|
|
244
|
+
// Acquire semaphore permit if concurrency control enabled
|
|
245
|
+
if (semaphore) {
|
|
246
|
+
await semaphore.acquire();
|
|
247
|
+
}
|
|
248
|
+
try {
|
|
249
|
+
// Create abort controller for timeout
|
|
250
|
+
const controller = new AbortController();
|
|
251
|
+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
252
|
+
try {
|
|
253
|
+
// Execute fetch request
|
|
254
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
255
|
+
const response = await fetch(url, {
|
|
256
|
+
...options,
|
|
257
|
+
signal: controller.signal,
|
|
258
|
+
});
|
|
259
|
+
clearTimeout(timeoutId);
|
|
260
|
+
// Handle HTTP errors
|
|
261
|
+
if (!response.ok) {
|
|
262
|
+
const status = response.status;
|
|
263
|
+
// 4xx errors (except 429) - no retry
|
|
264
|
+
if (status >= 400 && status < 500 && status !== 429) {
|
|
265
|
+
const body = await response.text();
|
|
266
|
+
throw new RuntimeError('RILL-R022', `${namespace}: HTTP ${status} — ${body}`);
|
|
267
|
+
}
|
|
268
|
+
// 5xx errors or 429 - retry
|
|
269
|
+
if (shouldRetryStatus(status)) {
|
|
270
|
+
if (attempt < retryLimit) {
|
|
271
|
+
// Calculate retry delay
|
|
272
|
+
let delay = calculateBackoff(retryDelay, attempt);
|
|
273
|
+
// Respect Retry-After header for 429
|
|
274
|
+
if (status === 429) {
|
|
275
|
+
const retryAfterMs = getRetryAfterMs(response);
|
|
276
|
+
if (retryAfterMs !== null) {
|
|
277
|
+
delay = retryAfterMs;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
await sleep(delay);
|
|
281
|
+
attempt++;
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
// Max retries reached
|
|
286
|
+
throw new RuntimeError('RILL-R023', `${namespace}: HTTP ${status} after ${retryLimit} retries`);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
// Success - parse response
|
|
291
|
+
if (responseShape === 'full') {
|
|
292
|
+
return await buildFullResponse(response, namespace);
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
return await parseJsonResponse(response, namespace);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
finally {
|
|
299
|
+
clearTimeout(timeoutId);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
finally {
|
|
303
|
+
// Release semaphore permit
|
|
304
|
+
if (semaphore) {
|
|
305
|
+
semaphore.release();
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
catch (error) {
|
|
310
|
+
// Timeout - no retry
|
|
311
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
312
|
+
throw new RuntimeError('RILL-R024', `${namespace}: request timeout (${timeoutMs}ms)`);
|
|
313
|
+
}
|
|
314
|
+
// Already formatted error - rethrow immediately
|
|
315
|
+
if (error instanceof RuntimeError) {
|
|
316
|
+
throw error;
|
|
317
|
+
}
|
|
318
|
+
// Network error - retry logic
|
|
319
|
+
if (error instanceof TypeError) {
|
|
320
|
+
if (attempt < retryLimit) {
|
|
321
|
+
const delay = calculateBackoff(retryDelay, attempt);
|
|
322
|
+
await sleep(delay);
|
|
323
|
+
attempt++;
|
|
324
|
+
lastError = error;
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
else {
|
|
328
|
+
throw new RuntimeError('RILL-R025', `${namespace}: network error — ${error.message}`);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
// Unknown error
|
|
332
|
+
lastError = error;
|
|
333
|
+
break;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
// Max retries reached for network errors
|
|
337
|
+
throw new RuntimeError('RILL-R025', `${namespace}: network error — ${lastError?.message ?? 'unknown error'}`);
|
|
338
|
+
}
|
|
339
|
+
// ============================================================
|
|
340
|
+
// PUBLIC API
|
|
341
|
+
// ============================================================
|
|
342
|
+
/**
|
|
343
|
+
* Create semaphore for concurrency control.
|
|
344
|
+
*
|
|
345
|
+
* @param maxConcurrent - Maximum concurrent requests
|
|
346
|
+
* @returns Semaphore instance or undefined if no limit
|
|
347
|
+
*/
|
|
348
|
+
export function createSemaphore(maxConcurrent) {
|
|
349
|
+
if (maxConcurrent && maxConcurrent > 0) {
|
|
350
|
+
return new Semaphore(maxConcurrent);
|
|
351
|
+
}
|
|
352
|
+
return undefined;
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Build request from endpoint config and arguments.
|
|
356
|
+
*
|
|
357
|
+
* @param config - Extension configuration
|
|
358
|
+
* @param endpointName - Endpoint name
|
|
359
|
+
* @param args - Request arguments
|
|
360
|
+
* @returns Request URL and options
|
|
361
|
+
*/
|
|
362
|
+
export function buildRequest(config, endpointName, args) {
|
|
363
|
+
const endpoint = config.endpoints[endpointName];
|
|
364
|
+
if (!endpoint) {
|
|
365
|
+
throw new TypeError(`Unknown endpoint: ${endpointName}`);
|
|
366
|
+
}
|
|
367
|
+
// Categorize arguments by location
|
|
368
|
+
const pathArgs = new Map();
|
|
369
|
+
const queryArgs = new Map();
|
|
370
|
+
const headerArgs = {};
|
|
371
|
+
let bodyValue = null;
|
|
372
|
+
for (const [argName, argValue] of Object.entries(args)) {
|
|
373
|
+
const argDef = endpoint.args?.find((a) => a.name === argName);
|
|
374
|
+
if (!argDef)
|
|
375
|
+
continue;
|
|
376
|
+
const stringValue = typeof argValue === 'string' ? argValue : String(argValue);
|
|
377
|
+
switch (argDef.location) {
|
|
378
|
+
case 'path':
|
|
379
|
+
pathArgs.set(argName, stringValue);
|
|
380
|
+
break;
|
|
381
|
+
case 'query':
|
|
382
|
+
queryArgs.set(argName, stringValue);
|
|
383
|
+
break;
|
|
384
|
+
case 'header':
|
|
385
|
+
headerArgs[argName] = stringValue;
|
|
386
|
+
break;
|
|
387
|
+
case 'body':
|
|
388
|
+
bodyValue = argValue;
|
|
389
|
+
break;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
// Build URL
|
|
393
|
+
const url = buildUrl(config.baseUrl, endpoint.path, pathArgs, queryArgs);
|
|
394
|
+
// Resolve and merge headers
|
|
395
|
+
const globalHeaders = resolveHeaders(config.headers);
|
|
396
|
+
const allHeaders = mergeHeaders(globalHeaders, endpoint.headers);
|
|
397
|
+
const finalHeaders = { ...allHeaders, ...headerArgs };
|
|
398
|
+
// Build fetch options
|
|
399
|
+
const options = {
|
|
400
|
+
method: endpoint.method,
|
|
401
|
+
headers: finalHeaders,
|
|
402
|
+
};
|
|
403
|
+
if (bodyValue !== null) {
|
|
404
|
+
options.body = JSON.stringify(bodyValue);
|
|
405
|
+
finalHeaders['Content-Type'] = 'application/json';
|
|
406
|
+
}
|
|
407
|
+
return {
|
|
408
|
+
url,
|
|
409
|
+
options,
|
|
410
|
+
responseShape: endpoint.responseShape ?? 'body',
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
//# sourceMappingURL=request.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request.js","sourceRoot":"","sources":["../../../src/ext/fetch/request.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fs Extension Factory
|
|
3
|
+
*
|
|
4
|
+
* Provides sandboxed filesystem operations via mount-based access control.
|
|
5
|
+
* All 12 functions implement path validation, permission checks, and glob filtering.
|
|
6
|
+
*/
|
|
7
|
+
import type { ExtensionResult } from '../../runtime/ext/extensions.js';
|
|
8
|
+
import { type MountConfig } from './sandbox.js';
|
|
9
|
+
/** Filesystem extension configuration */
|
|
10
|
+
export interface FsConfig {
|
|
11
|
+
/** Mount definitions keyed by mount name */
|
|
12
|
+
mounts: Record<string, MountConfig>;
|
|
13
|
+
/** Global file size limit in bytes (default: 10485760 = 10MB) */
|
|
14
|
+
maxFileSize?: number | undefined;
|
|
15
|
+
/** Text encoding for file operations (default: 'utf-8') */
|
|
16
|
+
encoding?: 'utf-8' | 'utf8' | 'ascii' | undefined;
|
|
17
|
+
}
|
|
18
|
+
export type { MountConfig };
|
|
19
|
+
/**
|
|
20
|
+
* Create filesystem extension with sandboxed operations.
|
|
21
|
+
*
|
|
22
|
+
* Initializes all mounts by resolving paths at creation time.
|
|
23
|
+
* Returns 12 functions: read, write, append, list, find, exists, remove, stat, mkdir, copy, move, mounts.
|
|
24
|
+
*
|
|
25
|
+
* @param config - Mount configuration and defaults
|
|
26
|
+
* @returns ExtensionResult with 12 filesystem functions
|
|
27
|
+
* @throws RuntimeError if mount initialization fails
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* const fsExt = createFsExtension({
|
|
32
|
+
* mounts: {
|
|
33
|
+
* workspace: { path: '/home/user/project', mode: 'read-write' }
|
|
34
|
+
* }
|
|
35
|
+
* });
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare function createFsExtension(config: FsConfig): ExtensionResult;
|
|
39
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ext/fs/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAEvE,OAAO,EACL,KAAK,WAAW,EAIjB,MAAM,cAAc,CAAC;AAMtB,yCAAyC;AACzC,MAAM,WAAW,QAAQ;IACvB,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACpC,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;CACnD;AAGD,YAAY,EAAE,WAAW,EAAE,CAAC;AAM5B;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,QAAQ,GAAG,eAAe,CA8oBnE"}
|