feat: form-submitted trigger multi-form dropdown + skill/docs sync
This commit is contained in:
@@ -122,14 +122,19 @@ inkreach-teable trigger set <wfId> --type recordCreatedOrUpdated --table-id tblX
|
||||
## 5. formSubmitted — When a form is submitted
|
||||
|
||||
```bash
|
||||
inkreach-teable trigger set <wfId> --type formSubmitted --table-id tblXXX --form-id viwXXX
|
||||
inkreach-teable trigger set <wfId> --type formSubmitted --table-id tblXXX --form-ids 'viwXXX1,viwXXX2'
|
||||
```
|
||||
|
||||
**Config:**
|
||||
```json
|
||||
{ "tableId": "tblXXX", "formId": "viwXXX" }
|
||||
{ "tableId": "tblXXX", "formIds": ["viwXXX1", "viwXXX2"] }
|
||||
```
|
||||
- `formId` is the **form view's id** (a view of type `form`).
|
||||
- `formIds` is an array of **form view ids** (views of type `form`). The trigger
|
||||
fires when **any** of the listed forms is submitted.
|
||||
- **Legacy compatibility:** the older single-string `formId` key is still
|
||||
accepted (migrated to `[formId]` automatically), so existing workflows keep
|
||||
working.
|
||||
- An empty `formIds` array means the trigger never fires.
|
||||
|
||||
**Output:** `record.id`, `record.fields.*`, `user`, `tableId`, `formId`.
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ Automations (workflows) are event-driven: a **trigger** fires, then **actions**
|
||||
| React to record changes | `recordUpdated` | `--table-id`, `--field-ids` (empty = all) |
|
||||
| React when a condition matches | `recordCondition` | `--table-id`, `--conditions` (required) |
|
||||
| React to create OR update | `recordCreatedOrUpdated` | `--table-id`, `--conditions` (optional) |
|
||||
| Form submission | `formSubmitted` | `--table-id`, `--form-id` |
|
||||
| Form submission | `formSubmitted` | `--table-id`, `--form-ids <csv>` |
|
||||
| Schedule (only type+interval work) | `scheduledTime` | `--schedule '{"timing":{"type":"minutes","interval":5}}'` |
|
||||
| Button field click | `buttonClick` | `--table-id`, `--field-ids` |
|
||||
| External HTTP POST | `webhook` | (none; auth backend-ignored) |
|
||||
|
||||
@@ -93,7 +93,7 @@ inkreach-teable trigger set <workflowId> --type <T> [options] [--base-id <id>]
|
||||
| `recordUpdated` | `--table-id`, `--field-ids '<json>'` |
|
||||
| `recordCondition` | `--table-id`, `--conditions '<json>'` |
|
||||
| `recordCreatedOrUpdated` | `--table-id` |
|
||||
| `formSubmitted` | `--table-id`, `--form-id <id>` |
|
||||
| `formSubmitted` | `--table-id`, `--form-ids <csv>` |
|
||||
| `scheduledTime` | `--schedule '{"timing":{"type":"minutes","interval":5}}'` |
|
||||
| `buttonClick` | `--table-id`, `--field-ids '<json>'` |
|
||||
| `webhook` | (none) |
|
||||
|
||||
Vendored
+42
-10
@@ -158,7 +158,10 @@ function workflowCommand() {
|
||||
if (ctx.json)
|
||||
(0, output_1.printJson)({ ok: true, ...res });
|
||||
else
|
||||
(0, output_1.printKv)([['snapshotId', res.snapshotId], ['status', 'activated']]);
|
||||
(0, output_1.printKv)([
|
||||
['snapshotId', res.snapshotId],
|
||||
['status', 'activated'],
|
||||
]);
|
||||
}));
|
||||
cmd
|
||||
.command('deactivate <workflowId>')
|
||||
@@ -206,8 +209,14 @@ function workflowCommand() {
|
||||
exports.workflowCommand = workflowCommand;
|
||||
// ===================== trigger =====================
|
||||
const TRIGGER_TYPES = [
|
||||
'recordCreated', 'recordUpdated', 'recordCondition', 'recordCreatedOrUpdated',
|
||||
'formSubmitted', 'scheduledTime', 'buttonClick', 'webhook',
|
||||
'recordCreated',
|
||||
'recordUpdated',
|
||||
'recordCondition',
|
||||
'recordCreatedOrUpdated',
|
||||
'formSubmitted',
|
||||
'scheduledTime',
|
||||
'buttonClick',
|
||||
'webhook',
|
||||
];
|
||||
function triggerCommand() {
|
||||
const cmd = new commander_1.Command('trigger');
|
||||
@@ -218,7 +227,8 @@ function triggerCommand() {
|
||||
.requiredOption('--type <type>', `Trigger type: ${TRIGGER_TYPES.join('|')}`)
|
||||
.option('--table-id <id>', 'Table id (most record/button triggers)')
|
||||
.option('--field-ids <json>', 'Field ids JSON array, e.g. \'["fldXXX"]\' (recordUpdated, buttonClick)')
|
||||
.option('--form-id <id>', 'Form view id (formSubmitted)')
|
||||
.option('--form-id <id>', 'Form view id (formSubmitted, legacy single). Prefer --form-ids.')
|
||||
.option('--form-ids <csv>', 'Comma-separated form view ids (formSubmitted, multi-select)')
|
||||
.option('--conditions <json>', 'Filter conditions JSON (recordCondition/recordCreated)')
|
||||
.option('--schedule <json>', 'Schedule JSON {timing:{type,interval}} (scheduledTime)')
|
||||
.option('--batch <json>', 'Batch config JSON {enabled,batchWindow,batchSize}')
|
||||
@@ -228,12 +238,15 @@ function triggerCommand() {
|
||||
const opts = o;
|
||||
const baseId = (0, ctx_1.requireBaseId)(ctx, opts.baseId);
|
||||
if (!TRIGGER_TYPES.includes(opts.type)) {
|
||||
throw Object.assign(new Error(`Invalid trigger type: ${opts.type}`), { code: 'INVALID_TYPE' });
|
||||
throw Object.assign(new Error(`Invalid trigger type: ${opts.type}`), {
|
||||
code: 'INVALID_TYPE',
|
||||
});
|
||||
}
|
||||
const config = buildTriggerConfig(opts.type, {
|
||||
tableId: opts.tableId,
|
||||
fieldIds: opts.fieldIds,
|
||||
formId: opts.formId,
|
||||
formIds: opts.formIds,
|
||||
conditions: opts.conditions,
|
||||
schedule: opts.schedule,
|
||||
batch: opts.batch,
|
||||
@@ -295,14 +308,25 @@ function buildTriggerConfig(type, opts) {
|
||||
if (opts.tableId)
|
||||
config.tableId = opts.tableId;
|
||||
// conditions is required for recordCondition
|
||||
config.conditions = opts.conditions ? parse(opts.conditions) : { conjunction: 'and', filterSet: [] };
|
||||
config.conditions = opts.conditions
|
||||
? parse(opts.conditions)
|
||||
: { conjunction: 'and', filterSet: [] };
|
||||
break;
|
||||
}
|
||||
case 'formSubmitted': {
|
||||
if (opts.tableId)
|
||||
config.tableId = opts.tableId;
|
||||
if (opts.formId)
|
||||
// Prefer --form-ids (csv) which populates formIds:string[]. Fall back to
|
||||
// legacy --form-id (single string) for backward compatibility.
|
||||
if (opts.formIds) {
|
||||
config.formIds = opts.formIds
|
||||
.split(',')
|
||||
.map((s) => s.trim())
|
||||
.filter((s) => s.length > 0);
|
||||
}
|
||||
else if (opts.formId) {
|
||||
config.formId = opts.formId;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'scheduledTime': {
|
||||
@@ -328,7 +352,8 @@ function buildTriggerConfig(type, opts) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (opts.batch && ['recordCreated', 'recordUpdated', 'recordCondition', 'recordCreatedOrUpdated'].includes(type)) {
|
||||
if (opts.batch &&
|
||||
['recordCreated', 'recordUpdated', 'recordCondition', 'recordCreatedOrUpdated'].includes(type)) {
|
||||
config.batch = parse(opts.batch);
|
||||
}
|
||||
return config;
|
||||
@@ -336,7 +361,12 @@ function buildTriggerConfig(type, opts) {
|
||||
exports.buildTriggerConfig = buildTriggerConfig;
|
||||
// ===================== action =====================
|
||||
const ACTION_TYPES = [
|
||||
'script', 'sendEmail', 'httpRequest', 'createRecord', 'updateRecord', 'getRecords',
|
||||
'script',
|
||||
'sendEmail',
|
||||
'httpRequest',
|
||||
'createRecord',
|
||||
'updateRecord',
|
||||
'getRecords',
|
||||
];
|
||||
function actionCommand() {
|
||||
const cmd = new commander_1.Command('action');
|
||||
@@ -367,7 +397,9 @@ function actionCommand() {
|
||||
const opts = o;
|
||||
const baseId = (0, ctx_1.requireBaseId)(ctx, opts.baseId);
|
||||
if (!ACTION_TYPES.includes(opts.type)) {
|
||||
throw Object.assign(new Error(`Invalid action type: ${opts.type}`), { code: 'INVALID_TYPE' });
|
||||
throw Object.assign(new Error(`Invalid action type: ${opts.type}`), {
|
||||
code: 'INVALID_TYPE',
|
||||
});
|
||||
}
|
||||
const config = opts.config ? JSON.parse(opts.config) : buildActionConfig(opts);
|
||||
const wf = await ctx.client.getWorkflowInBase(baseId, workflowId);
|
||||
|
||||
@@ -261,7 +261,8 @@ export function triggerCommand(): Command {
|
||||
'--field-ids <json>',
|
||||
'Field ids JSON array, e.g. \'["fldXXX"]\' (recordUpdated, buttonClick)'
|
||||
)
|
||||
.option('--form-id <id>', 'Form view id (formSubmitted)')
|
||||
.option('--form-id <id>', 'Form view id (formSubmitted, legacy single). Prefer --form-ids.')
|
||||
.option('--form-ids <csv>', 'Comma-separated form view ids (formSubmitted, multi-select)')
|
||||
.option('--conditions <json>', 'Filter conditions JSON (recordCondition/recordCreated)')
|
||||
.option('--schedule <json>', 'Schedule JSON {timing:{type,interval}} (scheduledTime)')
|
||||
.option('--batch <json>', 'Batch config JSON {enabled,batchWindow,batchSize}')
|
||||
@@ -274,6 +275,7 @@ export function triggerCommand(): Command {
|
||||
tableId?: string;
|
||||
fieldIds?: string;
|
||||
formId?: string;
|
||||
formIds?: string;
|
||||
conditions?: string;
|
||||
schedule?: string;
|
||||
batch?: string;
|
||||
@@ -289,6 +291,7 @@ export function triggerCommand(): Command {
|
||||
tableId: opts.tableId,
|
||||
fieldIds: opts.fieldIds,
|
||||
formId: opts.formId,
|
||||
formIds: opts.formIds,
|
||||
conditions: opts.conditions,
|
||||
schedule: opts.schedule,
|
||||
batch: opts.batch,
|
||||
@@ -332,6 +335,7 @@ export function buildTriggerConfig(
|
||||
tableId?: string;
|
||||
fieldIds?: string;
|
||||
formId?: string;
|
||||
formIds?: string;
|
||||
conditions?: string;
|
||||
schedule?: string;
|
||||
batch?: string;
|
||||
@@ -362,7 +366,16 @@ export function buildTriggerConfig(
|
||||
}
|
||||
case 'formSubmitted': {
|
||||
if (opts.tableId) config.tableId = opts.tableId;
|
||||
if (opts.formId) config.formId = opts.formId;
|
||||
// Prefer --form-ids (csv) which populates formIds:string[]. Fall back to
|
||||
// legacy --form-id (single string) for backward compatibility.
|
||||
if (opts.formIds) {
|
||||
config.formIds = opts.formIds
|
||||
.split(',')
|
||||
.map((s) => s.trim())
|
||||
.filter((s) => s.length > 0);
|
||||
} else if (opts.formId) {
|
||||
config.formId = opts.formId;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'scheduledTime': {
|
||||
|
||||
Reference in New Issue
Block a user