@struktoai/mirage-core
Version:
A Unified Virtual Filesystem For AI Agents
81 lines • 4.16 kB
JavaScript
// ========= 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 { jsonBytes } from "../../../../core/render/json.js";
import { getRecord, listBases, listComments, listRecords, listTables, } from "../../../../core/airtable/client.js";
import { normalizeBase, normalizeBaseSummary, normalizeComment, normalizeTable, recordsJsonl, } from "../../../../core/airtable/normalize.js";
import { IOResult } from "../../../../io/types.js";
import { UsageError } from "../../../errors.js";
import { findTable, noOperands, oneOperand, run, scopedBase } from "./util.js";
async function baseListBody(accessor, texts, _ctx, _fl) {
noOperands(texts);
const bases = await listBases(accessor);
return [jsonBytes(bases.map(normalizeBaseSummary)), new IOResult()];
}
async function baseGetBody(accessor, texts, _ctx, _fl) {
const baseId = scopedBase(accessor.config, oneOperand(texts, 'BASE'));
for (const base of await listBases(accessor)) {
if (base.id === baseId) {
const tables = await listTables(accessor, baseId);
return [jsonBytes(normalizeBase(base, tables)), new IOResult()];
}
}
throw new Error(`${baseId}: no such base`);
}
async function tableGetBody(accessor, texts, _ctx, fl) {
const ref = oneOperand(texts, 'TABLE');
const baseId = scopedBase(accessor.config, fl.asStr('base') ?? '');
const table = findTable(await listTables(accessor, baseId), ref);
if (table === undefined)
throw new Error(`${ref}: no such table in ${baseId}`);
return [jsonBytes(normalizeTable(table, baseId)), new IOResult()];
}
async function recordListBody(accessor, texts, _ctx, fl) {
noOperands(texts);
const asked = fl.asInt('max_records');
if (asked !== undefined && asked < 1)
throw new UsageError('--max-records must be at least 1');
const baseId = scopedBase(accessor.config, fl.asStr('base') ?? '');
const cap = accessor.maxReadRecords;
const view = fl.asStr('view');
const formula = fl.asStr('formula');
const records = await listRecords(accessor, baseId, fl.asStr('table') ?? '', {
...(view !== undefined ? { view } : {}),
...(formula !== undefined ? { formula } : {}),
maxRecords: asked ?? cap + 1,
});
if (asked === undefined && records.length > cap) {
throw new Error(`more than ${String(cap)} records match (max_read_records); narrow them with --formula ` +
'or --view, or take the first N with --max-records N');
}
return [recordsJsonl(records), new IOResult()];
}
async function recordGetBody(accessor, texts, _ctx, fl) {
const recordId = oneOperand(texts, 'RECORD');
const baseId = scopedBase(accessor.config, fl.asStr('base') ?? '');
const record = await getRecord(accessor, baseId, fl.asStr('table') ?? '', recordId);
return [recordsJsonl([record]), new IOResult()];
}
async function commentListBody(accessor, texts, _ctx, fl) {
const recordId = oneOperand(texts, 'RECORD');
const baseId = scopedBase(accessor.config, fl.asStr('base') ?? '');
const comments = await listComments(accessor, baseId, fl.asStr('table') ?? '', recordId);
return [jsonBytes(comments.map(normalizeComment)), new IOResult()];
}
export const baseList = run(baseListBody);
export const baseGet = run(baseGetBody);
export const tableGet = run(tableGetBody);
export const recordList = run(recordListBody);
export const recordGet = run(recordGetBody);
export const commentList = run(commentListBody);
//# sourceMappingURL=reads.js.map