UNPKG

@struktoai/mirage-core

Version:

A Unified Virtual Filesystem For AI Agents

79 lines • 3.22 kB
// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. ========= // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ========= Copyright 2026 @ Strukto.AI All Rights Reserved. ========= import { publishRead } from "../../cache/context.js"; import { eacces, enoent } from "../../errors/fs.js"; import { record, revisionFor, startOp } from "../../observe/context.js"; import { VFSName } from "../../types.js"; import { rawPathOf } from "../../utils/key_prefix.js"; import { rangeHeader } from "../../utils/ranges.js"; import { createS3Client, isDenied, isNotFound, loadS3Module, s3Key, streamToBuffer, } from "./client.js"; /** * Extract `(fingerprint, revision)` from a GetObject / HeadObject response. * * VersionId is null on non-versioned buckets; the SDK can also return the * literal string "null" there, which we normalize. */ export function fpRevFromS3Response(resp) { const rawEtag = resp.ETag ?? ''; const fingerprint = rawEtag.replace(/^"|"$/g, '') || null; let vid = resp.VersionId ?? null; if (vid === 'null') vid = null; return { fingerprint, revision: vid }; } export async function read(accessor, path, options = {}) { const virtual = path.virtual; const rawPath = rawPathOf(path); // `virtual` retains the mount prefix (e.g. /s3/foo) for snapshot records; // `rawPath` is the backend-relative key used for the actual S3 call. const { config } = accessor; const key = s3Key(rawPath, config); const { GetObjectCommand } = await loadS3Module(config); const client = await createS3Client(config); const input = { Bucket: config.bucket, Key: key }; const pinnedRevision = revisionFor(virtual); if (pinnedRevision !== null) { input.VersionId = pinnedRevision; } const range = rangeHeader(options.offset ?? 0, options.size ?? null); if (range !== null) input.Range = range; const timer = startOp(); try { const resp = (await client.send(new GetObjectCommand(input))); const bytes = await streamToBuffer(resp.Body); const { fingerprint, revision } = fpRevFromS3Response(resp); record('read', virtual, VFSName.S3, bytes.byteLength, timer, { fingerprint, revision, }); // Only a whole read's token names the object; a window's does not. if (range === null) publishRead(virtual, bytes, fingerprint); return bytes; } catch (err) { if (isNotFound(err)) { throw enoent(path); } if (isDenied(err)) throw eacces(path); throw err; } finally { ; client.destroy?.(); } } //# sourceMappingURL=read.js.map