fix(cli): batch record delete sends recordIds as query params
The API controller reads recordIds from @Query(), not @Body.
CLI was sending { records: ids } as JSON body, causing:
'expected array, received undefined at "recordIds"'
Fixed: rename deleteRecord→deleteRecords, send recordIds as
repeated query params (?recordIds=rec1&recordIds=rec2).
This commit is contained in:
@@ -115,7 +115,10 @@ function tableCmd(): Command {
|
||||
.description('Create a new table')
|
||||
.requiredOption('--name <name>', 'Table name')
|
||||
.option('--base-id <id>', 'Base id (overrides default)')
|
||||
.option('--fields <json>', 'Field definitions JSON array, e.g. \'[{"name":"Title","type":"singleLineText"}]\'')
|
||||
.option(
|
||||
'--fields <json>',
|
||||
'Field definitions JSON array, e.g. \'[{"name":"Title","type":"singleLineText"}]\''
|
||||
)
|
||||
.action(
|
||||
run(async (ctx, _args, o) => {
|
||||
const opts = o as { name: string; baseId?: string; fields?: string };
|
||||
@@ -126,7 +129,10 @@ function tableCmd(): Command {
|
||||
if (ctx.json) printJson(table);
|
||||
else {
|
||||
const t = table as Record<string, unknown>;
|
||||
printKv([['id', t.id], ['name', t.name]]);
|
||||
printKv([
|
||||
['id', t.id],
|
||||
['name', t.name],
|
||||
]);
|
||||
}
|
||||
})
|
||||
);
|
||||
@@ -215,7 +221,10 @@ function fieldCmd(): Command {
|
||||
.description('Create a new field')
|
||||
.requiredOption('--table-id <id>', 'Table id')
|
||||
.requiredOption('--name <name>', 'Field name')
|
||||
.requiredOption('--type <type>', 'Field type (singleLineText, number, singleSelect, link, formula, etc.)')
|
||||
.requiredOption(
|
||||
'--type <type>',
|
||||
'Field type (singleLineText, number, singleSelect, link, formula, etc.)'
|
||||
)
|
||||
.option('--options <json>', 'Field options JSON (type-specific)')
|
||||
.action(
|
||||
run(async (ctx, _args, o) => {
|
||||
@@ -226,7 +235,11 @@ function fieldCmd(): Command {
|
||||
if (ctx.json) printJson(field);
|
||||
else {
|
||||
const f = field as Record<string, unknown>;
|
||||
printKv([['id', f.id], ['name', f.name], ['type', f.type]]);
|
||||
printKv([
|
||||
['id', f.id],
|
||||
['name', f.name],
|
||||
['type', f.type],
|
||||
]);
|
||||
}
|
||||
})
|
||||
);
|
||||
@@ -391,7 +404,10 @@ function recordCmd(): Command {
|
||||
.command('update')
|
||||
.description('Batch update records')
|
||||
.requiredOption('--table-id <id>', 'Table id')
|
||||
.requiredOption('--records <json>', 'Records JSON, e.g. \'[{"id":"recX","fields":{"Title":"b"}}]\'')
|
||||
.requiredOption(
|
||||
'--records <json>',
|
||||
'Records JSON, e.g. \'[{"id":"recX","fields":{"Title":"b"}}]\''
|
||||
)
|
||||
.action(
|
||||
run(async (ctx, _args, o) => {
|
||||
const opts = o as { tableId: string; records: string };
|
||||
@@ -414,8 +430,7 @@ function recordCmd(): Command {
|
||||
.split(',')
|
||||
.map((s) => s.trim())
|
||||
.filter(Boolean);
|
||||
const body = { records: ids };
|
||||
const result = await ctx.client.deleteRecord(opts.tableId, body);
|
||||
const result = await ctx.client.deleteRecords(opts.tableId, ids);
|
||||
if (ctx.json) printJson(result);
|
||||
else process.stdout.write(`✓ ${ids.length} record(s) deleted\n`);
|
||||
})
|
||||
@@ -488,7 +503,11 @@ function viewCmd(): Command {
|
||||
if (ctx.json) printJson(view);
|
||||
else {
|
||||
const v = view as Record<string, unknown>;
|
||||
printKv([['id', v.id], ['name', v.name], ['type', v.type]]);
|
||||
printKv([
|
||||
['id', v.id],
|
||||
['name', v.name],
|
||||
['type', v.type],
|
||||
]);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
+63
-16
@@ -124,8 +124,9 @@ export class Client {
|
||||
updateRecordOne(recordId: string, body: unknown) {
|
||||
return this.call<unknown>('PATCH', `/api/record/${recordId}`, body);
|
||||
}
|
||||
deleteRecord(tableId: string, body: unknown) {
|
||||
return this.call<unknown>('DELETE', `/api/table/${tableId}/record`, body);
|
||||
deleteRecords(tableId: string, recordIds: string[]) {
|
||||
const qs = recordIds.map((id) => `recordIds=${encodeURIComponent(id)}`).join('&');
|
||||
return this.call<unknown>('DELETE', `/api/table/${tableId}/record?${qs}`);
|
||||
}
|
||||
|
||||
// ---- view ----
|
||||
@@ -163,23 +164,37 @@ export class Client {
|
||||
createWorkflow(baseId: string, body: { name: string; description?: string }) {
|
||||
return this.call<IWorkflowVo>('POST', `/api/base/${baseId}/workflow`, body);
|
||||
}
|
||||
updateWorkflow(baseId: string, workflowId: string, body: { name?: string; description?: string }) {
|
||||
updateWorkflow(
|
||||
baseId: string,
|
||||
workflowId: string,
|
||||
body: { name?: string; description?: string }
|
||||
) {
|
||||
return this.call<IWorkflowVo>('PATCH', `/api/base/${baseId}/workflow/${workflowId}`, body);
|
||||
}
|
||||
deleteWorkflow(baseId: string, workflowId: string) {
|
||||
return this.call<unknown>('DELETE', `/api/base/${baseId}/workflow/${workflowId}`);
|
||||
}
|
||||
activateWorkflow(baseId: string, workflowId: string) {
|
||||
return this.call<{ snapshotId: string }>('POST', `/api/base/${baseId}/workflow/${workflowId}/activate`);
|
||||
return this.call<{ snapshotId: string }>(
|
||||
'POST',
|
||||
`/api/base/${baseId}/workflow/${workflowId}/activate`
|
||||
);
|
||||
}
|
||||
deactivateWorkflow(baseId: string, workflowId: string) {
|
||||
return this.call<unknown>('POST', `/api/base/${baseId}/workflow/${workflowId}/deactivate`);
|
||||
}
|
||||
testWorkflow(baseId: string, workflowId: string) {
|
||||
return this.call<{ nodeResults: unknown[] }>('POST', `/api/base/${baseId}/workflow/${workflowId}/test`);
|
||||
return this.call<{ nodeResults: unknown[] }>(
|
||||
'POST',
|
||||
`/api/base/${baseId}/workflow/${workflowId}/test`
|
||||
);
|
||||
}
|
||||
/** PUT /node — whole-graph replacement (delete-all + create-all in a txn). */
|
||||
replaceNodes(baseId: string, workflowId: string, body: { nodes: IWorkflowNodeVo[]; edges: IWorkflowEdgeVo[] }) {
|
||||
replaceNodes(
|
||||
baseId: string,
|
||||
workflowId: string,
|
||||
body: { nodes: IWorkflowNodeVo[]; edges: IWorkflowEdgeVo[] }
|
||||
) {
|
||||
return this.call<IWorkflowVo>('PUT', `/api/base/${baseId}/workflow/${workflowId}/node`, body);
|
||||
}
|
||||
|
||||
@@ -187,14 +202,30 @@ export class Client {
|
||||
listSecrets(baseId: string, workflowId: string) {
|
||||
return this.call<unknown[]>('GET', `/api/base/${baseId}/workflow/${workflowId}/secret`);
|
||||
}
|
||||
createSecret(baseId: string, workflowId: string, body: { name: string; description?: string; value: string }) {
|
||||
createSecret(
|
||||
baseId: string,
|
||||
workflowId: string,
|
||||
body: { name: string; description?: string; value: string }
|
||||
) {
|
||||
return this.call<unknown>('POST', `/api/base/${baseId}/workflow/${workflowId}/secret`, body);
|
||||
}
|
||||
updateSecret(baseId: string, workflowId: string, secretId: string, body: { name?: string; description?: string; value?: string }) {
|
||||
return this.call<unknown>('PATCH', `/api/base/${baseId}/workflow/${workflowId}/secret/${secretId}`, body);
|
||||
updateSecret(
|
||||
baseId: string,
|
||||
workflowId: string,
|
||||
secretId: string,
|
||||
body: { name?: string; description?: string; value?: string }
|
||||
) {
|
||||
return this.call<unknown>(
|
||||
'PATCH',
|
||||
`/api/base/${baseId}/workflow/${workflowId}/secret/${secretId}`,
|
||||
body
|
||||
);
|
||||
}
|
||||
deleteSecret(baseId: string, workflowId: string, secretId: string) {
|
||||
return this.call<unknown>('DELETE', `/api/base/${baseId}/workflow/${workflowId}/secret/${secretId}`);
|
||||
return this.call<unknown>(
|
||||
'DELETE',
|
||||
`/api/base/${baseId}/workflow/${workflowId}/secret/${secretId}`
|
||||
);
|
||||
}
|
||||
|
||||
// ---- execution history ----
|
||||
@@ -202,10 +233,16 @@ export class Client {
|
||||
return this.call<unknown[]>('GET', `/api/base/${baseId}/workflow/${workflowId}/execution`);
|
||||
}
|
||||
getExecution(baseId: string, workflowId: string, executionId: string) {
|
||||
return this.call<unknown>('GET', `/api/base/${baseId}/workflow/${workflowId}/execution/${executionId}`);
|
||||
return this.call<unknown>(
|
||||
'GET',
|
||||
`/api/base/${baseId}/workflow/${workflowId}/execution/${executionId}`
|
||||
);
|
||||
}
|
||||
rerunExecution(baseId: string, workflowId: string, executionId: string) {
|
||||
return this.call<unknown>('POST', `/api/base/${baseId}/workflow/${workflowId}/execution/${executionId}/rerun`);
|
||||
return this.call<unknown>(
|
||||
'POST',
|
||||
`/api/base/${baseId}/workflow/${workflowId}/execution/${executionId}/rerun`
|
||||
);
|
||||
}
|
||||
|
||||
// ---- trigger (manual fire for testing) ----
|
||||
@@ -243,10 +280,20 @@ export class Client {
|
||||
// ---- shared types (mirror backend workflow_node / workflow_edge shapes) ----
|
||||
export type WorkflowNodeType = 'trigger' | 'action' | 'control';
|
||||
export type WorkflowNodeCategory =
|
||||
| 'recordCreated' | 'recordUpdated' | 'recordCondition' | 'recordCreatedOrUpdated'
|
||||
| 'formSubmitted' | 'scheduledTime' | 'buttonClick' | 'webhook'
|
||||
| 'script' | 'sendEmail' | 'httpRequest'
|
||||
| 'createRecord' | 'updateRecord' | 'getRecords'
|
||||
| 'recordCreated'
|
||||
| 'recordUpdated'
|
||||
| 'recordCondition'
|
||||
| 'recordCreatedOrUpdated'
|
||||
| 'formSubmitted'
|
||||
| 'scheduledTime'
|
||||
| 'buttonClick'
|
||||
| 'webhook'
|
||||
| 'script'
|
||||
| 'sendEmail'
|
||||
| 'httpRequest'
|
||||
| 'createRecord'
|
||||
| 'updateRecord'
|
||||
| 'getRecords'
|
||||
| 'triggerEnd';
|
||||
|
||||
export interface IWorkflowNodeVo {
|
||||
|
||||
Reference in New Issue
Block a user