"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.baseResourceCommands = void 0; /** * `inkreach base|table|field|record|view` — resource CRUD commands. * * These endpoints are compatible with official teable open-api. */ const commander_1 = require("commander"); const ctx_1 = require("../lib/ctx"); const output_1 = require("../lib/output"); function baseResourceCommands() { return [baseCmd(), tableCmd(), fieldCmd(), recordCmd(), viewCmd()]; } exports.baseResourceCommands = baseResourceCommands; // ===================== base ===================== function baseCmd() { const cmd = new commander_1.Command('base'); cmd.description('Manage bases (database containers)'); cmd .command('list') .description('List all accessible bases') .action((0, ctx_1.run)(async (ctx) => { const list = (await ctx.client.listBases()); if (ctx.json) (0, output_1.printJson)(list); else { if (!list.length) { process.stdout.write('No bases found.\n'); return; } (0, output_1.printTable)([ { key: 'id', header: 'ID' }, { key: 'name', header: 'NAME' }, ], list.map((b) => ({ id: (0, output_1.truncate)(b.id), name: (0, output_1.truncate)(b.name, 30) }))); } })); cmd .command('get ') .description('Get base details') .action((0, ctx_1.run)(async (ctx, args) => { const baseId = args[0]; const base = await ctx.client.getBase(baseId); if (ctx.json) (0, output_1.printJson)(base); else { const b = base; (0, output_1.printKv)(Object.entries(b).map(([k, v]) => [k, v])); } })); return cmd; } // ===================== table ===================== function tableCmd() { const cmd = new commander_1.Command('table'); cmd.description('Manage tables within a base'); cmd .command('list') .description('List tables in a base') .option('--base-id ', 'Base id (overrides default)') .action((0, ctx_1.run)(async (ctx, _args, o) => { const opts = o; const baseId = (0, ctx_1.requireBaseId)(ctx, opts.baseId); const list = (await ctx.client.listTables(baseId)); if (ctx.json) (0, output_1.printJson)(list); else { if (!list.length) { process.stdout.write('No tables found.\n'); return; } (0, output_1.printTable)([ { key: 'id', header: 'ID' }, { key: 'name', header: 'NAME' }, { key: 'dbTableName', header: 'DB TABLE' }, ], list.map((t) => ({ id: (0, output_1.truncate)(t.id), name: (0, output_1.truncate)(t.name, 30), dbTableName: (0, output_1.truncate)(t.dbTableName ?? ''), }))); } })); cmd .command('get ') .description('Get table details') .action((0, ctx_1.run)(async (ctx, args) => { const tableId = args[0]; const table = await ctx.client.getTable(tableId); if (ctx.json) (0, output_1.printJson)(table); else { const t = table; (0, output_1.printKv)(Object.entries(t).map(([k, v]) => [k, v])); } })); cmd .command('create') .description('Create a new table') .requiredOption('--name ', 'Table name') .option('--base-id ', 'Base id (overrides default)') .option('--fields ', 'Field definitions JSON array, e.g. \'[{"name":"Title","type":"singleLineText"}]\'') .action((0, ctx_1.run)(async (ctx, _args, o) => { const opts = o; const baseId = (0, ctx_1.requireBaseId)(ctx, opts.baseId); const body = { name: opts.name }; if (opts.fields) body.fields = JSON.parse(opts.fields); const table = await ctx.client.createTable(baseId, body); if (ctx.json) (0, output_1.printJson)(table); else { const t = table; (0, output_1.printKv)([['id', t.id], ['name', t.name]]); } })); cmd .command('update ') .description('Update table (rename)') .requiredOption('--name ', 'New table name') .action((0, ctx_1.run)(async (ctx, args, o) => { const tableId = args[0]; const opts = o; const table = await ctx.client.updateTable(tableId, { name: opts.name }); if (ctx.json) (0, output_1.printJson)(table); else process.stdout.write(`✓ Table ${tableId} updated\n`); })); cmd .command('delete ') .description('Delete a table') .action((0, ctx_1.run)(async (ctx, args) => { const tableId = args[0]; await ctx.client.deleteTable(tableId); if (ctx.json) (0, output_1.printJson)({ ok: true, id: tableId }); else process.stdout.write(`✓ Table ${tableId} deleted\n`); })); return cmd; } // ===================== field ===================== function fieldCmd() { const cmd = new commander_1.Command('field'); cmd.description('Manage fields (columns) in a table'); cmd .command('list ') .description('List fields in a table') .action((0, ctx_1.run)(async (ctx, args) => { const tableId = args[0]; const list = (await ctx.client.listFields(tableId)); if (ctx.json) (0, output_1.printJson)(list); else { if (!list.length) { process.stdout.write('No fields found.\n'); return; } (0, output_1.printTable)([ { key: 'id', header: 'ID' }, { key: 'name', header: 'NAME' }, { key: 'type', header: 'TYPE' }, ], list.map((f) => ({ id: (0, output_1.truncate)(f.id), name: (0, output_1.truncate)(f.name, 30), type: f.type, }))); } })); cmd .command('get ') .description('Get field details') .action((0, ctx_1.run)(async (ctx, args) => { const fieldId = args[0]; const field = await ctx.client.getField(fieldId); if (ctx.json) (0, output_1.printJson)(field); else { const f = field; (0, output_1.printKv)(Object.entries(f).map(([k, v]) => [k, v])); } })); cmd .command('create') .description('Create a new field') .requiredOption('--table-id ', 'Table id') .requiredOption('--name ', 'Field name') .requiredOption('--type ', 'Field type (singleLineText, number, singleSelect, link, formula, etc.)') .option('--options ', 'Field options JSON (type-specific)') .action((0, ctx_1.run)(async (ctx, _args, o) => { const opts = o; const body = { name: opts.name, type: opts.type }; if (opts.options) body.options = JSON.parse(opts.options); const field = await ctx.client.createField(opts.tableId, body); if (ctx.json) (0, output_1.printJson)(field); else { const f = field; (0, output_1.printKv)([['id', f.id], ['name', f.name], ['type', f.type]]); } })); cmd .command('update ') .description('Update a field') .option('--name ', 'New field name') .option('--options ', 'New field options JSON') .action((0, ctx_1.run)(async (ctx, args, o) => { const fieldId = args[0]; const opts = o; const body = {}; if (opts.name) body.name = opts.name; if (opts.options) body.options = JSON.parse(opts.options); const field = await ctx.client.updateField(fieldId, body); if (ctx.json) (0, output_1.printJson)(field); else process.stdout.write(`✓ Field ${fieldId} updated\n`); })); cmd .command('delete ') .description('Delete a field') .action((0, ctx_1.run)(async (ctx, args) => { const fieldId = args[0]; await ctx.client.deleteField(fieldId); if (ctx.json) (0, output_1.printJson)({ ok: true, id: fieldId }); else process.stdout.write(`✓ Field ${fieldId} deleted\n`); })); return cmd; } // ===================== record ===================== function recordCmd() { const cmd = new commander_1.Command('record'); cmd.description('Manage records (rows) in a table'); cmd .command('get') .description('Query records with filters, pagination, and search') .requiredOption('--table-id ', 'Table id') .option('--filter ', 'Filter conditions JSON') .option('--projection ', 'Field projection JSON array') .option('--page-size ', 'Records per page') .option('--page ', 'Page number (1-based)') .option('--search ', 'Search keyword') .option('--base-id ', 'Base id (overrides default)') .action((0, ctx_1.run)(async (ctx, _args, o) => { const opts = o; // validate baseId is present (even though getRecords only needs tableId, // we follow the convention that base-scoped commands require baseId config) (0, ctx_1.requireBaseId)(ctx, opts.baseId); const query = {}; if (opts.filter) query.filter = JSON.parse(opts.filter); if (opts.projection) query.projection = JSON.parse(opts.projection); if (opts.search) query.search = opts.search; const page = opts.page ? parseInt(opts.page, 10) : undefined; const pageSize = opts.pageSize ? parseInt(opts.pageSize, 10) : undefined; if (pageSize) query.take = pageSize; if (page) { const take = pageSize || 100; query.skip = (page - 1) * take; if (!pageSize) query.take = take; } const result = (await ctx.client.getRecords(opts.tableId, query)); if (ctx.json) { (0, output_1.printJson)(result); } else { if (!result.records?.length) { process.stdout.write('No records found.\n'); return; } const firstFields = result.records[0].fields || {}; const fieldKeys = Object.keys(firstFields); const columns = fieldKeys.map((k) => ({ key: k, header: k })); (0, output_1.printTable)(columns, result.records.map((rec) => { const f = rec.fields || {}; const row = { id: (0, output_1.truncate)(rec.id) }; for (const k of fieldKeys) { row[k] = (0, output_1.truncate)(f[k], 30); } return row; })); if (result.total !== undefined) { process.stdout.write(`\n${result.records.length} of ${result.total} record(s).\n`); } else { process.stdout.write(`\n${result.records.length} record(s).\n`); } } })); cmd .command('get-one ') .description('Get a single record by id') .action((0, ctx_1.run)(async (ctx, args) => { const recordId = args[0]; const record = await ctx.client.getRecord(recordId); if (ctx.json) (0, output_1.printJson)(record); else { const rec = record; const fields = rec.fields || {}; (0, output_1.printKv)([ ['id', rec.id], ...Object.entries(fields).map(([k, v]) => [k, v]), ]); } })); cmd .command('create') .description('Create record(s). Use --fields for a single record, --records for bulk.') .requiredOption('--table-id ', 'Table id') .option('--fields ', 'Fields object JSON, e.g. \'{"Title":"hello"}\'') .option('--records ', 'Records array JSON for bulk, e.g. \'[{"fields":{"Title":"a"}}]\'') .action((0, ctx_1.run)(async (ctx, _args, o) => { const opts = o; let body; if (opts.records) { body = { records: JSON.parse(opts.records) }; } else if (opts.fields) { body = { fields: JSON.parse(opts.fields) }; } else { throw Object.assign(new Error('Provide --fields or --records'), { code: 'MISSING_FIELDS', }); } const result = await ctx.client.createRecord(opts.tableId, body); if (ctx.json) (0, output_1.printJson)(result); else process.stdout.write(`✓ Record(s) created\n`); })); cmd .command('update') .description('Batch update records') .requiredOption('--table-id ', 'Table id') .requiredOption('--records ', 'Records JSON, e.g. \'[{"id":"recX","fields":{"Title":"b"}}]\'') .action((0, ctx_1.run)(async (ctx, _args, o) => { const opts = o; const body = { records: JSON.parse(opts.records) }; const result = await ctx.client.updateRecord(opts.tableId, body); if (ctx.json) (0, output_1.printJson)(result); else process.stdout.write(`✓ Records updated\n`); })); cmd .command('delete') .description('Batch delete records by ids') .requiredOption('--table-id ', 'Table id') .requiredOption('--record-ids ', 'Record ids (comma-separated)') .action((0, ctx_1.run)(async (ctx, _args, o) => { const opts = o; const ids = opts.recordIds .split(',') .map((s) => s.trim()) .filter(Boolean); const body = { records: ids }; const result = await ctx.client.deleteRecord(opts.tableId, body); if (ctx.json) (0, output_1.printJson)(result); else process.stdout.write(`✓ ${ids.length} record(s) deleted\n`); })); return cmd; } // ===================== view ===================== function viewCmd() { const cmd = new commander_1.Command('view'); cmd.description('Manage views in a table'); cmd .command('list ') .description('List views in a table') .action((0, ctx_1.run)(async (ctx, args) => { const tableId = args[0]; const list = (await ctx.client.listViews(tableId)); if (ctx.json) (0, output_1.printJson)(list); else { if (!list.length) { process.stdout.write('No views found.\n'); return; } (0, output_1.printTable)([ { key: 'id', header: 'ID' }, { key: 'name', header: 'NAME' }, { key: 'type', header: 'TYPE' }, ], list.map((v) => ({ id: (0, output_1.truncate)(v.id), name: (0, output_1.truncate)(v.name, 30), type: v.type, }))); } })); cmd .command('get ') .description('Get view details') .action((0, ctx_1.run)(async (ctx, args) => { const viewId = args[0]; const view = await ctx.client.getView(viewId); if (ctx.json) (0, output_1.printJson)(view); else { const v = view; (0, output_1.printKv)(Object.entries(v).map(([k, val]) => [k, val])); } })); cmd .command('create') .description('Create a new view') .requiredOption('--table-id ', 'Table id') .requiredOption('--name ', 'View name') .option('--type ', 'View type (grid, calendar, kanban, gallery, form)', 'grid') .action((0, ctx_1.run)(async (ctx, _args, o) => { const opts = o; const body = { name: opts.name, type: opts.type }; const view = await ctx.client.createView(opts.tableId, body); if (ctx.json) (0, output_1.printJson)(view); else { const v = view; (0, output_1.printKv)([['id', v.id], ['name', v.name], ['type', v.type]]); } })); cmd .command('update ') .description('Update a view (rename)') .option('--name ', 'New view name') .action((0, ctx_1.run)(async (ctx, args, o) => { const viewId = args[0]; const opts = o; const body = {}; if (opts.name) body.name = opts.name; const view = await ctx.client.updateView(viewId, body); if (ctx.json) (0, output_1.printJson)(view); else process.stdout.write(`✓ View ${viewId} updated\n`); })); cmd .command('delete ') .description('Delete a view') .action((0, ctx_1.run)(async (ctx, args) => { const viewId = args[0]; await ctx.client.deleteView(viewId); if (ctx.json) (0, output_1.printJson)({ ok: true, id: viewId }); else process.stdout.write(`✓ View ${viewId} deleted\n`); })); return cmd; }