longcelot-sheet-db
Version:
Google Sheets-backed staging database adapter for Node.js with schema-first design
74 lines • 3.24 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveTableRef = resolveTableRef;
exports.promptOrResolveTable = promptOrResolveTable;
const chalk_1 = __importDefault(require("chalk"));
const inquirer_1 = __importDefault(require("inquirer"));
const suggest_1 = require("../../utils/suggest");
/**
* Resolves a user-typed table reference against every loaded schema. Table names are only
* unique per actor (see skills/schema/SKILL.md), so a bare name that matches more than one
* actor is treated as ambiguous rather than guessing — the caller can disambiguate with
* 'actor/tableName'.
*/
function resolveTableRef(all, rawName) {
if (rawName.includes('/')) {
const [actor, name] = rawName.split('/');
const match = all.find((s) => s.actor === actor && s.schema.name === name);
if (match)
return { ok: true, table: match };
const candidates = all.filter((s) => s.actor === actor).map((s) => s.schema.name);
const suggestion = (0, suggest_1.closestMatch)(name, candidates);
return {
ok: false,
error: `Table '${rawName}' not found.${suggestion ? ` Did you mean '${actor}/${suggestion}'?` : ''}`,
};
}
const matches = all.filter((s) => s.schema.name === rawName);
if (matches.length === 1)
return { ok: true, table: matches[0] };
if (matches.length > 1) {
const actors = matches.map((m) => m.actor).join(', ');
return {
ok: false,
error: `Table '${rawName}' exists under multiple actors (${actors}). Use 'actor/${rawName}' to disambiguate.`,
};
}
const suggestion = (0, suggest_1.closestMatch)(rawName, all.map((s) => s.schema.name));
const available = all.map((s) => `${s.actor}/${s.schema.name}`).join(', ') || '(none)';
return {
ok: false,
error: `Table '${rawName}' not found.${suggestion ? ` Did you mean '${suggestion}'?` : ''} Available: ${available}`,
};
}
/**
* Resolves a table from a CLI argument, exiting with a clear error on an invalid name — or,
* if no argument was given, prompts an interactive single-select list. Shared by drop-column
* and rename-column, which both operate on exactly one table.
*/
async function promptOrResolveTable(all, tableName) {
if (tableName) {
const result = resolveTableRef(all, tableName);
if (!result.ok) {
console.error(chalk_1.default.red(`❌ ${result.error}`));
process.exit(1);
}
return result.table;
}
const { chosen } = await inquirer_1.default.prompt([
{
type: 'list',
name: 'chosen',
message: 'Which table?',
choices: all.map((s) => ({ name: `${s.actor}/${s.schema.name}`, value: `${s.actor}/${s.schema.name}` })),
},
]);
const result = resolveTableRef(all, chosen);
if (!result.ok)
throw new Error(result.error); // unreachable — chosen came from the choices list itself
return result.table;
}
//# sourceMappingURL=resolveTable.js.map