n8n-nodes-base 1.90.0 → 1.91.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/credentials/GSuiteAdminOAuth2Api.credentials.js +3 -1
- package/dist/credentials/GSuiteAdminOAuth2Api.credentials.js.map +1 -1
- package/dist/methods/defined.json +2 -1
- package/dist/methods/referenced.json +1 -0
- package/dist/nodes/Calendly/CalendlyTrigger.node.js +11 -0
- package/dist/nodes/Calendly/CalendlyTrigger.node.js.map +1 -1
- package/dist/nodes/EmailReadImap/v1/EmailReadImapV1.node.js +2 -2
- package/dist/nodes/EmailReadImap/v1/EmailReadImapV1.node.js.map +1 -1
- package/dist/nodes/EmailReadImap/v2/EmailReadImapV2.node.js +2 -2
- package/dist/nodes/EmailReadImap/v2/EmailReadImapV2.node.js.map +1 -1
- package/dist/nodes/Files/ReadWriteFile/actions/read.operation.js +0 -1
- package/dist/nodes/Files/ReadWriteFile/actions/read.operation.js.map +1 -1
- package/dist/nodes/Form/utils.js.map +1 -1
- package/dist/nodes/Google/GSuiteAdmin/DeviceDescription.js +381 -0
- package/dist/nodes/Google/GSuiteAdmin/DeviceDescription.js.map +1 -0
- package/dist/nodes/Google/GSuiteAdmin/GSuiteAdmin.node.js +395 -88
- package/dist/nodes/Google/GSuiteAdmin/GSuiteAdmin.node.js.map +1 -1
- package/dist/nodes/Google/GSuiteAdmin/GenericFunctions.js +6 -2
- package/dist/nodes/Google/GSuiteAdmin/GenericFunctions.js.map +1 -1
- package/dist/nodes/Google/GSuiteAdmin/GroupDescripion.js +112 -88
- package/dist/nodes/Google/GSuiteAdmin/GroupDescripion.js.map +1 -1
- package/dist/nodes/Google/GSuiteAdmin/SearchFunctions.js +101 -0
- package/dist/nodes/Google/GSuiteAdmin/SearchFunctions.js.map +1 -0
- package/dist/nodes/Google/GSuiteAdmin/UserDescription.js +538 -195
- package/dist/nodes/Google/GSuiteAdmin/UserDescription.js.map +1 -1
- package/dist/nodes/Google/GSuiteAdmin/gSuiteAdmin.svg +1 -0
- package/dist/nodes/HttpRequest/V2/HttpRequestV2.node.js +11 -0
- package/dist/nodes/HttpRequest/V2/HttpRequestV2.node.js.map +1 -1
- package/dist/nodes/HttpRequest/V3/HttpRequestV3.node.js +8 -0
- package/dist/nodes/HttpRequest/V3/HttpRequestV3.node.js.map +1 -1
- package/dist/nodes/Jira/GenericFunctions.js +25 -12
- package/dist/nodes/Jira/GenericFunctions.js.map +1 -1
- package/dist/nodes/Jira/Jira.node.js +11 -7
- package/dist/nodes/Jira/Jira.node.js.map +1 -1
- package/dist/nodes/LocalFileTrigger/LocalFileTrigger.node.js +2 -2
- package/dist/nodes/LocalFileTrigger/LocalFileTrigger.node.js.map +1 -1
- package/dist/nodes/MQTT/MqttTrigger.node.js +2 -2
- package/dist/nodes/MQTT/MqttTrigger.node.js.map +1 -1
- package/dist/nodes/Postgres/PostgresTrigger.node.js +2 -2
- package/dist/nodes/Postgres/PostgresTrigger.node.js.map +1 -1
- package/dist/nodes/RabbitMQ/RabbitMQTrigger.node.js +2 -2
- package/dist/nodes/RabbitMQ/RabbitMQTrigger.node.js.map +1 -1
- package/dist/nodes/SeaTable/v2/actions/asset/upload.operation.js.map +1 -1
- package/dist/nodes/SeaTable/v2/actions/row/get.operation.js.map +1 -1
- package/dist/nodes/SeaTable/v2/actions/row/list.operation.js.map +1 -1
- package/dist/nodes/SeaTable/v2/actions/row/search.operation.js.map +1 -1
- package/dist/nodes/SseTrigger/SseTrigger.node.js +2 -2
- package/dist/nodes/SseTrigger/SseTrigger.node.js.map +1 -1
- package/dist/nodes/Transform/Summarize/utils.js +7 -7
- package/dist/nodes/Transform/Summarize/utils.js.map +1 -1
- package/dist/test/nodes/Helpers.d.ts +5 -0
- package/dist/test/nodes/Helpers.js +16 -170
- package/dist/test/nodes/Helpers.js.map +1 -1
- package/dist/types/credentials.json +1 -1
- package/dist/types/nodes.json +11 -11
- package/package.json +4 -4
- package/dist/nodes/Google/GSuiteAdmin/google-workspace-admin.png +0 -0
- package/dist/test/nodes/ExecuteWorkflow.js +0 -120
- package/dist/test/nodes/ExecuteWorkflow.js.map +0 -1
- package/dist/test/nodes/credential-types.js +0 -57
- package/dist/test/nodes/credential-types.js.map +0 -1
- package/dist/test/nodes/credentials-helper.js +0 -76
- package/dist/test/nodes/credentials-helper.js.map +0 -1
- package/dist/test/nodes/load-nodes-and-credentials.js +0 -68
- package/dist/test/nodes/load-nodes-and-credentials.js.map +0 -1
- package/dist/test/nodes/node-types.js +0 -56
- package/dist/test/nodes/node-types.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../nodes/Postgres/PostgresTrigger.node.ts"],"sourcesContent":["import {\n\tTriggerCloseError,\n\ttype IDataObject,\n\ttype INodeType,\n\ttype INodeTypeDescription,\n\ttype ITriggerFunctions,\n\ttype ITriggerResponse,\n\tNodeConnectionTypes,\n} from 'n8n-workflow';\n\nimport {\n\tpgTriggerFunction,\n\tinitDB,\n\tsearchSchema,\n\tsearchTables,\n\tprepareNames,\n} from './PostgresTrigger.functions';\n\nexport class PostgresTrigger implements INodeType {\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'Postgres Trigger',\n\t\tname: 'postgresTrigger',\n\t\ticon: 'file:postgres.svg',\n\t\tgroup: ['trigger'],\n\t\tversion: 1,\n\t\tdescription: 'Listens to Postgres messages',\n\t\teventTriggerDescription: '',\n\t\tdefaults: {\n\t\t\tname: 'Postgres Trigger',\n\t\t},\n\t\ttriggerPanel: {\n\t\t\theader: '',\n\t\t\texecutionsHelp: {\n\t\t\t\tinactive:\n\t\t\t\t\t\"<b>While building your workflow</b>, click the 'listen' button, then trigger a Postgres event. This will trigger an execution, which will show up in this editor.<br /> <br /><b>Once you're happy with your workflow</b>, <a data-key='activate'>activate</a> it. Then every time a change is detected, the workflow will execute. These executions will show up in the <a data-key='executions'>executions list</a>, but not in the editor.\",\n\t\t\t\tactive:\n\t\t\t\t\t\"<b>While building your workflow</b>, click the 'listen' button, then trigger a Postgres event. This will trigger an execution, which will show up in this editor.<br /> <br /><b>Your workflow will also execute automatically</b>, since it's activated. Every time a change is detected, this node will trigger an execution. These executions will show up in the <a data-key='executions'>executions list</a>, but not in the editor.\",\n\t\t\t},\n\t\t\tactivationHint:\n\t\t\t\t\"Once you've finished building your workflow, <a data-key='activate'>activate</a> it to have it also listen continuously (you just won't see those executions here).\",\n\t\t},\n\t\tinputs: [],\n\t\toutputs: [NodeConnectionTypes.Main],\n\t\tcredentials: [\n\t\t\t{\n\t\t\t\tname: 'postgres',\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t],\n\t\tproperties: [\n\t\t\t{\n\t\t\t\tdisplayName: 'Listen For',\n\t\t\t\tname: 'triggerMode',\n\t\t\t\ttype: 'options',\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Table Row Change Events',\n\t\t\t\t\t\tvalue: 'createTrigger',\n\t\t\t\t\t\tdescription: 'Insert, update or delete',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Advanced',\n\t\t\t\t\t\tvalue: 'listenTrigger',\n\t\t\t\t\t\tdescription: 'Listen to existing Postgres channel',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdefault: 'createTrigger',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Schema Name',\n\t\t\t\tname: 'schema',\n\t\t\t\ttype: 'resourceLocator',\n\t\t\t\tdefault: { mode: 'list', value: 'public' },\n\t\t\t\trequired: true,\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\ttriggerMode: ['createTrigger'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tmodes: [\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'From List',\n\t\t\t\t\t\tname: 'list',\n\t\t\t\t\t\ttype: 'list',\n\t\t\t\t\t\tplaceholder: 'Select a schema',\n\t\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\t\tsearchListMethod: 'searchSchema',\n\t\t\t\t\t\t\tsearchFilterRequired: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Name',\n\t\t\t\t\t\tname: 'name',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tplaceholder: 'e.g. public',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Table Name',\n\t\t\t\tname: 'tableName',\n\t\t\t\ttype: 'resourceLocator',\n\t\t\t\tdefault: { mode: 'list', value: '' },\n\t\t\t\trequired: true,\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\ttriggerMode: ['createTrigger'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tmodes: [\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'From List',\n\t\t\t\t\t\tname: 'list',\n\t\t\t\t\t\ttype: 'list',\n\t\t\t\t\t\tplaceholder: 'Select a table',\n\t\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\t\tsearchListMethod: 'searchTables',\n\t\t\t\t\t\t\tsearchFilterRequired: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Name',\n\t\t\t\t\t\tname: 'name',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tplaceholder: 'e.g. table_name',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Channel Name',\n\t\t\t\tname: 'channelName',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\trequired: true,\n\t\t\t\tplaceholder: 'e.g. n8n_channel',\n\t\t\t\tdescription: 'Name of the channel to listen to',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\ttriggerMode: ['listenTrigger'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Event to listen for',\n\t\t\t\tname: 'firesOn',\n\t\t\t\ttype: 'options',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\ttriggerMode: ['createTrigger'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Insert',\n\t\t\t\t\t\tvalue: 'INSERT',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Update',\n\t\t\t\t\t\tvalue: 'UPDATE',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Delete',\n\t\t\t\t\t\tvalue: 'DELETE',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdefault: 'INSERT',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Additional Fields',\n\t\t\t\tname: 'additionalFields',\n\t\t\t\ttype: 'collection',\n\t\t\t\tplaceholder: 'Add Field',\n\t\t\t\tdefault: {},\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\ttriggerMode: ['createTrigger'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Channel Name',\n\t\t\t\t\t\tname: 'channelName',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tplaceholder: 'e.g. n8n_channel',\n\t\t\t\t\t\tdescription: 'Name of the channel to listen to',\n\t\t\t\t\t\tdefault: '',\n\t\t\t\t\t},\n\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Function Name',\n\t\t\t\t\t\tname: 'functionName',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdescription: 'Name of the function to create',\n\t\t\t\t\t\tplaceholder: 'e.g. n8n_trigger_function()',\n\t\t\t\t\t\tdefault: '',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Replace if Exists',\n\t\t\t\t\t\tname: 'replaceIfExists',\n\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\tdescription: 'Whether to replace an existing function and trigger with the same name',\n\t\t\t\t\t\tdefault: false,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Trigger Name',\n\t\t\t\t\t\tname: 'triggerName',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdescription: 'Name of the trigger to create',\n\t\t\t\t\t\tplaceholder: 'e.g. n8n_trigger',\n\t\t\t\t\t\tdefault: '',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Options',\n\t\t\t\tname: 'options',\n\t\t\t\ttype: 'collection',\n\t\t\t\tplaceholder: 'Add option',\n\t\t\t\tdefault: {},\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Connection Timeout',\n\t\t\t\t\t\tname: 'connectionTimeout',\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\tdefault: 30,\n\t\t\t\t\t\tdescription: 'Number of seconds reserved for connecting to the database',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Delay Closing Idle Connection',\n\t\t\t\t\t\tname: 'delayClosingIdleConnection',\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\tdefault: 0,\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'Number of seconds to wait before idle connection would be eligible for closing',\n\t\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\t\tminValue: 0,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t],\n\t};\n\n\tmethods = {\n\t\tlistSearch: {\n\t\t\tsearchSchema,\n\t\t\tsearchTables,\n\t\t},\n\t};\n\n\tasync trigger(this: ITriggerFunctions): Promise<ITriggerResponse> {\n\t\tconst triggerMode = this.getNodeParameter('triggerMode', 0) as string;\n\t\tconst additionalFields = this.getNodeParameter('additionalFields', 0) as IDataObject;\n\n\t\t// initialize and connect to database\n\t\tconst { db } = await initDB.call(this);\n\t\tconst connection = await db.connect({ direct: true });\n\n\t\t// prepare and set up listener\n\t\tconst onNotification = async (data: IDataObject) => {\n\t\t\tif (data.payload) {\n\t\t\t\ttry {\n\t\t\t\t\tdata.payload = JSON.parse(data.payload as string) as IDataObject;\n\t\t\t\t} catch (error) {}\n\t\t\t}\n\t\t\tthis.emit([this.helpers.returnJsonArray([data])]);\n\t\t};\n\n\t\t// create trigger, function and channel or use existing channel\n\t\tconst pgNames = prepareNames(this.getNode().id, this.getMode(), additionalFields);\n\t\tif (triggerMode === 'createTrigger') {\n\t\t\tawait pgTriggerFunction.call(\n\t\t\t\tthis,\n\t\t\t\tdb,\n\t\t\t\tadditionalFields,\n\t\t\t\tpgNames.functionName,\n\t\t\t\tpgNames.triggerName,\n\t\t\t\tpgNames.channelName,\n\t\t\t);\n\t\t} else {\n\t\t\tpgNames.channelName = this.getNodeParameter('channelName', '') as string;\n\t\t}\n\n\t\t// listen to channel\n\t\tawait connection.none(`LISTEN ${pgNames.channelName}`);\n\n\t\tconst cleanUpDb = async () => {\n\t\t\ttry {\n\t\t\t\ttry {\n\t\t\t\t\t// check if the connection is healthy\n\t\t\t\t\tawait connection.query('SELECT 1');\n\t\t\t\t} catch {\n\t\t\t\t\t// connection already closed. Can't perform cleanup\n\n\t\t\t\t\tthrow new TriggerCloseError(this.getNode(), { level: 'warning' });\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tawait connection.none('UNLISTEN $1:name', [pgNames.channelName]);\n\t\t\t\t\tif (triggerMode === 'createTrigger') {\n\t\t\t\t\t\tconst functionName = pgNames.functionName.includes('(')\n\t\t\t\t\t\t\t? pgNames.functionName.split('(')[0]\n\t\t\t\t\t\t\t: pgNames.functionName;\n\t\t\t\t\t\tawait connection.any('DROP FUNCTION IF EXISTS $1:name CASCADE', [functionName]);\n\n\t\t\t\t\t\tconst schema = this.getNodeParameter('schema', undefined, {\n\t\t\t\t\t\t\textractValue: true,\n\t\t\t\t\t\t}) as string;\n\t\t\t\t\t\tconst table = this.getNodeParameter('tableName', undefined, {\n\t\t\t\t\t\t\textractValue: true,\n\t\t\t\t\t\t}) as string;\n\n\t\t\t\t\t\tawait connection.any('DROP TRIGGER IF EXISTS $1:name ON $2:name.$3:name CASCADE', [\n\t\t\t\t\t\t\tpgNames.triggerName,\n\t\t\t\t\t\t\tschema,\n\t\t\t\t\t\t\ttable,\n\t\t\t\t\t\t]);\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow new TriggerCloseError(this.getNode(), { cause: error as Error, level: 'error' });\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tconnection.client.removeListener('notification', onNotification);\n\t\t\t}\n\t\t};\n\n\t\tconnection.client.on('notification', onNotification);\n\n\t\t// The \"closeFunction\" function gets called by n8n whenever\n\t\t// the workflow gets deactivated and can so clean up.\n\t\tconst closeFunction = async () => {\n\t\t\tawait cleanUpDb();\n\t\t};\n\n\t\tconst manualTriggerFunction = async () => {\n\t\t\tawait new Promise(async (resolve, reject) => {\n\t\t\t\tconst timeoutHandler = setTimeout(async () => {\n\t\t\t\t\treject(\n\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\tawait (async () => {\n\t\t\t\t\t\t\t\tawait cleanUpDb();\n\t\t\t\t\t\t\t\treturn 'Aborted, no data received within 30secs. This 30sec timeout is only set for \"manually triggered execution\". Active Workflows will listen indefinitely.';\n\t\t\t\t\t\t\t})(),\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}, 60000);\n\t\t\t\tconnection.client.on('notification', async (data: IDataObject) => {\n\t\t\t\t\tif (data.payload) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tdata.payload = JSON.parse(data.payload as string) as IDataObject;\n\t\t\t\t\t\t} catch (error) {}\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.emit([this.helpers.returnJsonArray([data])]);\n\t\t\t\t\tclearTimeout(timeoutHandler);\n\t\t\t\t\tresolve(true);\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\n\t\treturn {\n\t\t\tcloseFunction,\n\t\t\tmanualTriggerFunction: this.getMode() === 'manual' ? manualTriggerFunction : undefined,\n\t\t};\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAQO;AAEP,6BAMO;AAEA,MAAM,gBAAqC;AAAA,EAA3C;AACN,uBAAoC;AAAA,MACnC,aAAa;AAAA,MACb,MAAM;AAAA,MACN,MAAM;AAAA,MACN,OAAO,CAAC,SAAS;AAAA,MACjB,SAAS;AAAA,MACT,aAAa;AAAA,MACb,yBAAyB;AAAA,MACzB,UAAU;AAAA,QACT,MAAM;AAAA,MACP;AAAA,MACA,cAAc;AAAA,QACb,QAAQ;AAAA,QACR,gBAAgB;AAAA,UACf,UACC;AAAA,UACD,QACC;AAAA,QACF;AAAA,QACA,gBACC;AAAA,MACF;AAAA,MACA,QAAQ,CAAC;AAAA,MACT,SAAS,CAAC,wCAAoB,IAAI;AAAA,MAClC,aAAa;AAAA,QACZ;AAAA,UACC,MAAM;AAAA,UACN,UAAU;AAAA,QACX;AAAA,MACD;AAAA,MACA,YAAY;AAAA,QACX;AAAA,UACC,aAAa;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS;AAAA,YACR;AAAA,cACC,MAAM;AAAA,cACN,OAAO;AAAA,cACP,aAAa;AAAA,YACd;AAAA,YACA;AAAA,cACC,MAAM;AAAA,cACN,OAAO;AAAA,cACP,aAAa;AAAA,YACd;AAAA,UACD;AAAA,UACA,SAAS;AAAA,QACV;AAAA,QACA;AAAA,UACC,aAAa;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS,EAAE,MAAM,QAAQ,OAAO,SAAS;AAAA,UACzC,UAAU;AAAA,UACV,gBAAgB;AAAA,YACf,MAAM;AAAA,cACL,aAAa,CAAC,eAAe;AAAA,YAC9B;AAAA,UACD;AAAA,UACA,OAAO;AAAA,YACN;AAAA,cACC,aAAa;AAAA,cACb,MAAM;AAAA,cACN,MAAM;AAAA,cACN,aAAa;AAAA,cACb,aAAa;AAAA,gBACZ,kBAAkB;AAAA,gBAClB,sBAAsB;AAAA,cACvB;AAAA,YACD;AAAA,YACA;AAAA,cACC,aAAa;AAAA,cACb,MAAM;AAAA,cACN,MAAM;AAAA,cACN,aAAa;AAAA,YACd;AAAA,UACD;AAAA,QACD;AAAA,QACA;AAAA,UACC,aAAa;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS,EAAE,MAAM,QAAQ,OAAO,GAAG;AAAA,UACnC,UAAU;AAAA,UACV,gBAAgB;AAAA,YACf,MAAM;AAAA,cACL,aAAa,CAAC,eAAe;AAAA,YAC9B;AAAA,UACD;AAAA,UACA,OAAO;AAAA,YACN;AAAA,cACC,aAAa;AAAA,cACb,MAAM;AAAA,cACN,MAAM;AAAA,cACN,aAAa;AAAA,cACb,aAAa;AAAA,gBACZ,kBAAkB;AAAA,gBAClB,sBAAsB;AAAA,cACvB;AAAA,YACD;AAAA,YACA;AAAA,cACC,aAAa;AAAA,cACb,MAAM;AAAA,cACN,MAAM;AAAA,cACN,aAAa;AAAA,YACd;AAAA,UACD;AAAA,QACD;AAAA,QACA;AAAA,UACC,aAAa;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS;AAAA,UACT,UAAU;AAAA,UACV,aAAa;AAAA,UACb,aAAa;AAAA,UACb,gBAAgB;AAAA,YACf,MAAM;AAAA,cACL,aAAa,CAAC,eAAe;AAAA,YAC9B;AAAA,UACD;AAAA,QACD;AAAA,QACA;AAAA,UACC,aAAa;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA,UACN,gBAAgB;AAAA,YACf,MAAM;AAAA,cACL,aAAa,CAAC,eAAe;AAAA,YAC9B;AAAA,UACD;AAAA,UACA,SAAS;AAAA,YACR;AAAA,cACC,MAAM;AAAA,cACN,OAAO;AAAA,YACR;AAAA,YACA;AAAA,cACC,MAAM;AAAA,cACN,OAAO;AAAA,YACR;AAAA,YACA;AAAA,cACC,MAAM;AAAA,cACN,OAAO;AAAA,YACR;AAAA,UACD;AAAA,UACA,SAAS;AAAA,QACV;AAAA,QACA;AAAA,UACC,aAAa;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA,UACN,aAAa;AAAA,UACb,SAAS,CAAC;AAAA,UACV,gBAAgB;AAAA,YACf,MAAM;AAAA,cACL,aAAa,CAAC,eAAe;AAAA,YAC9B;AAAA,UACD;AAAA,UACA,SAAS;AAAA,YACR;AAAA,cACC,aAAa;AAAA,cACb,MAAM;AAAA,cACN,MAAM;AAAA,cACN,aAAa;AAAA,cACb,aAAa;AAAA,cACb,SAAS;AAAA,YACV;AAAA,YAEA;AAAA,cACC,aAAa;AAAA,cACb,MAAM;AAAA,cACN,MAAM;AAAA,cACN,aAAa;AAAA,cACb,aAAa;AAAA,cACb,SAAS;AAAA,YACV;AAAA,YACA;AAAA,cACC,aAAa;AAAA,cACb,MAAM;AAAA,cACN,MAAM;AAAA,cACN,aAAa;AAAA,cACb,SAAS;AAAA,YACV;AAAA,YACA;AAAA,cACC,aAAa;AAAA,cACb,MAAM;AAAA,cACN,MAAM;AAAA,cACN,aAAa;AAAA,cACb,aAAa;AAAA,cACb,SAAS;AAAA,YACV;AAAA,UACD;AAAA,QACD;AAAA,QACA;AAAA,UACC,aAAa;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA,UACN,aAAa;AAAA,UACb,SAAS,CAAC;AAAA,UACV,SAAS;AAAA,YACR;AAAA,cACC,aAAa;AAAA,cACb,MAAM;AAAA,cACN,MAAM;AAAA,cACN,SAAS;AAAA,cACT,aAAa;AAAA,YACd;AAAA,YACA;AAAA,cACC,aAAa;AAAA,cACb,MAAM;AAAA,cACN,MAAM;AAAA,cACN,SAAS;AAAA,cACT,aACC;AAAA,cACD,aAAa;AAAA,gBACZ,UAAU;AAAA,cACX;AAAA,YACD;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAEA,mBAAU;AAAA,MACT,YAAY;AAAA,QACX;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAAA;AAAA,EAEA,MAAM,UAA4D;AACjE,UAAM,cAAc,KAAK,iBAAiB,eAAe,CAAC;AAC1D,UAAM,mBAAmB,KAAK,iBAAiB,oBAAoB,CAAC;AAGpE,UAAM,EAAE,GAAG,IAAI,MAAM,8BAAO,KAAK,IAAI;AACrC,UAAM,aAAa,MAAM,GAAG,QAAQ,EAAE,QAAQ,KAAK,CAAC;AAGpD,UAAM,iBAAiB,OAAO,SAAsB;AACnD,UAAI,KAAK,SAAS;AACjB,YAAI;AACH,eAAK,UAAU,KAAK,MAAM,KAAK,OAAiB;AAAA,QACjD,SAAS,OAAO;AAAA,QAAC;AAAA,MAClB;AACA,WAAK,KAAK,CAAC,KAAK,QAAQ,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;AAAA,IACjD;AAGA,UAAM,cAAU,qCAAa,KAAK,QAAQ,EAAE,IAAI,KAAK,QAAQ,GAAG,gBAAgB;AAChF,QAAI,gBAAgB,iBAAiB;AACpC,YAAM,yCAAkB;AAAA,QACvB;AAAA,QACA;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,QAAQ;AAAA,MACT;AAAA,IACD,OAAO;AACN,cAAQ,cAAc,KAAK,iBAAiB,eAAe,EAAE;AAAA,IAC9D;AAGA,UAAM,WAAW,KAAK,UAAU,QAAQ,WAAW,EAAE;AAErD,UAAM,YAAY,YAAY;AAC7B,UAAI;AACH,YAAI;AAEH,gBAAM,WAAW,MAAM,UAAU;AAAA,QAClC,QAAQ;AAGP,gBAAM,IAAI,sCAAkB,KAAK,QAAQ,GAAG,EAAE,OAAO,UAAU,CAAC;AAAA,QACjE;AAEA,YAAI;AACH,gBAAM,WAAW,KAAK,oBAAoB,CAAC,QAAQ,WAAW,CAAC;AAC/D,cAAI,gBAAgB,iBAAiB;AACpC,kBAAM,eAAe,QAAQ,aAAa,SAAS,GAAG,IACnD,QAAQ,aAAa,MAAM,GAAG,EAAE,CAAC,IACjC,QAAQ;AACX,kBAAM,WAAW,IAAI,2CAA2C,CAAC,YAAY,CAAC;AAE9E,kBAAM,SAAS,KAAK,iBAAiB,UAAU,QAAW;AAAA,cACzD,cAAc;AAAA,YACf,CAAC;AACD,kBAAM,QAAQ,KAAK,iBAAiB,aAAa,QAAW;AAAA,cAC3D,cAAc;AAAA,YACf,CAAC;AAED,kBAAM,WAAW,IAAI,6DAA6D;AAAA,cACjF,QAAQ;AAAA,cACR;AAAA,cACA;AAAA,YACD,CAAC;AAAA,UACF;AAAA,QACD,SAAS,OAAO;AACf,gBAAM,IAAI,sCAAkB,KAAK,QAAQ,GAAG,EAAE,OAAO,OAAgB,OAAO,QAAQ,CAAC;AAAA,QACtF;AAAA,MACD,UAAE;AACD,mBAAW,OAAO,eAAe,gBAAgB,cAAc;AAAA,MAChE;AAAA,IACD;AAEA,eAAW,OAAO,GAAG,gBAAgB,cAAc;AAInD,UAAM,gBAAgB,YAAY;AACjC,YAAM,UAAU;AAAA,IACjB;AAEA,UAAM,wBAAwB,YAAY;AACzC,YAAM,IAAI,QAAQ,OAAO,SAAS,WAAW;AAC5C,cAAM,iBAAiB,WAAW,YAAY;AAC7C;AAAA,YACC,IAAI;AAAA,cACH,OAAO,YAAY;AAClB,sBAAM,UAAU;AAChB,uBAAO;AAAA,cACR,GAAG;AAAA,YACJ;AAAA,UACD;AAAA,QACD,GAAG,GAAK;AACR,mBAAW,OAAO,GAAG,gBAAgB,OAAO,SAAsB;AACjE,cAAI,KAAK,SAAS;AACjB,gBAAI;AACH,mBAAK,UAAU,KAAK,MAAM,KAAK,OAAiB;AAAA,YACjD,SAAS,OAAO;AAAA,YAAC;AAAA,UAClB;AAEA,eAAK,KAAK,CAAC,KAAK,QAAQ,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;AAChD,uBAAa,cAAc;AAC3B,kBAAQ,IAAI;AAAA,QACb,CAAC;AAAA,MACF,CAAC;AAAA,IACF;AAEA,WAAO;AAAA,MACN;AAAA,MACA,uBAAuB,KAAK,QAAQ,MAAM,WAAW,wBAAwB;AAAA,IAC9E;AAAA,EACD;AACD;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../nodes/Postgres/PostgresTrigger.node.ts"],"sourcesContent":["import {\n\tTriggerCloseError,\n\ttype IDataObject,\n\ttype INodeType,\n\ttype INodeTypeDescription,\n\ttype ITriggerFunctions,\n\ttype ITriggerResponse,\n\tNodeConnectionTypes,\n} from 'n8n-workflow';\n\nimport {\n\tpgTriggerFunction,\n\tinitDB,\n\tsearchSchema,\n\tsearchTables,\n\tprepareNames,\n} from './PostgresTrigger.functions';\n\nexport class PostgresTrigger implements INodeType {\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'Postgres Trigger',\n\t\tname: 'postgresTrigger',\n\t\ticon: 'file:postgres.svg',\n\t\tgroup: ['trigger'],\n\t\tversion: 1,\n\t\tdescription: 'Listens to Postgres messages',\n\t\teventTriggerDescription: '',\n\t\tdefaults: {\n\t\t\tname: 'Postgres Trigger',\n\t\t},\n\t\ttriggerPanel: {\n\t\t\theader: '',\n\t\t\texecutionsHelp: {\n\t\t\t\tinactive:\n\t\t\t\t\t\"<b>While building your workflow</b>, click the 'test step' button, then trigger a Postgres event. This will trigger an execution, which will show up in this editor.<br /> <br /><b>Once you're happy with your workflow</b>, <a data-key='activate'>activate</a> it. Then every time a change is detected, the workflow will execute. These executions will show up in the <a data-key='executions'>executions list</a>, but not in the editor.\",\n\t\t\t\tactive:\n\t\t\t\t\t\"<b>While building your workflow</b>, click the 'test step' button, then trigger a Postgres event. This will trigger an execution, which will show up in this editor.<br /> <br /><b>Your workflow will also execute automatically</b>, since it's activated. Every time a change is detected, this node will trigger an execution. These executions will show up in the <a data-key='executions'>executions list</a>, but not in the editor.\",\n\t\t\t},\n\t\t\tactivationHint:\n\t\t\t\t\"Once you've finished building your workflow, <a data-key='activate'>activate</a> it to have it also listen continuously (you just won't see those executions here).\",\n\t\t},\n\t\tinputs: [],\n\t\toutputs: [NodeConnectionTypes.Main],\n\t\tcredentials: [\n\t\t\t{\n\t\t\t\tname: 'postgres',\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t],\n\t\tproperties: [\n\t\t\t{\n\t\t\t\tdisplayName: 'Listen For',\n\t\t\t\tname: 'triggerMode',\n\t\t\t\ttype: 'options',\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Table Row Change Events',\n\t\t\t\t\t\tvalue: 'createTrigger',\n\t\t\t\t\t\tdescription: 'Insert, update or delete',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Advanced',\n\t\t\t\t\t\tvalue: 'listenTrigger',\n\t\t\t\t\t\tdescription: 'Listen to existing Postgres channel',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdefault: 'createTrigger',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Schema Name',\n\t\t\t\tname: 'schema',\n\t\t\t\ttype: 'resourceLocator',\n\t\t\t\tdefault: { mode: 'list', value: 'public' },\n\t\t\t\trequired: true,\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\ttriggerMode: ['createTrigger'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tmodes: [\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'From List',\n\t\t\t\t\t\tname: 'list',\n\t\t\t\t\t\ttype: 'list',\n\t\t\t\t\t\tplaceholder: 'Select a schema',\n\t\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\t\tsearchListMethod: 'searchSchema',\n\t\t\t\t\t\t\tsearchFilterRequired: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Name',\n\t\t\t\t\t\tname: 'name',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tplaceholder: 'e.g. public',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Table Name',\n\t\t\t\tname: 'tableName',\n\t\t\t\ttype: 'resourceLocator',\n\t\t\t\tdefault: { mode: 'list', value: '' },\n\t\t\t\trequired: true,\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\ttriggerMode: ['createTrigger'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tmodes: [\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'From List',\n\t\t\t\t\t\tname: 'list',\n\t\t\t\t\t\ttype: 'list',\n\t\t\t\t\t\tplaceholder: 'Select a table',\n\t\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\t\tsearchListMethod: 'searchTables',\n\t\t\t\t\t\t\tsearchFilterRequired: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Name',\n\t\t\t\t\t\tname: 'name',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tplaceholder: 'e.g. table_name',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Channel Name',\n\t\t\t\tname: 'channelName',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\trequired: true,\n\t\t\t\tplaceholder: 'e.g. n8n_channel',\n\t\t\t\tdescription: 'Name of the channel to listen to',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\ttriggerMode: ['listenTrigger'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Event to listen for',\n\t\t\t\tname: 'firesOn',\n\t\t\t\ttype: 'options',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\ttriggerMode: ['createTrigger'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Insert',\n\t\t\t\t\t\tvalue: 'INSERT',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Update',\n\t\t\t\t\t\tvalue: 'UPDATE',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Delete',\n\t\t\t\t\t\tvalue: 'DELETE',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdefault: 'INSERT',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Additional Fields',\n\t\t\t\tname: 'additionalFields',\n\t\t\t\ttype: 'collection',\n\t\t\t\tplaceholder: 'Add Field',\n\t\t\t\tdefault: {},\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\ttriggerMode: ['createTrigger'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Channel Name',\n\t\t\t\t\t\tname: 'channelName',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tplaceholder: 'e.g. n8n_channel',\n\t\t\t\t\t\tdescription: 'Name of the channel to listen to',\n\t\t\t\t\t\tdefault: '',\n\t\t\t\t\t},\n\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Function Name',\n\t\t\t\t\t\tname: 'functionName',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdescription: 'Name of the function to create',\n\t\t\t\t\t\tplaceholder: 'e.g. n8n_trigger_function()',\n\t\t\t\t\t\tdefault: '',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Replace if Exists',\n\t\t\t\t\t\tname: 'replaceIfExists',\n\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\tdescription: 'Whether to replace an existing function and trigger with the same name',\n\t\t\t\t\t\tdefault: false,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Trigger Name',\n\t\t\t\t\t\tname: 'triggerName',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdescription: 'Name of the trigger to create',\n\t\t\t\t\t\tplaceholder: 'e.g. n8n_trigger',\n\t\t\t\t\t\tdefault: '',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Options',\n\t\t\t\tname: 'options',\n\t\t\t\ttype: 'collection',\n\t\t\t\tplaceholder: 'Add option',\n\t\t\t\tdefault: {},\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Connection Timeout',\n\t\t\t\t\t\tname: 'connectionTimeout',\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\tdefault: 30,\n\t\t\t\t\t\tdescription: 'Number of seconds reserved for connecting to the database',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Delay Closing Idle Connection',\n\t\t\t\t\t\tname: 'delayClosingIdleConnection',\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\tdefault: 0,\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'Number of seconds to wait before idle connection would be eligible for closing',\n\t\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\t\tminValue: 0,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t],\n\t};\n\n\tmethods = {\n\t\tlistSearch: {\n\t\t\tsearchSchema,\n\t\t\tsearchTables,\n\t\t},\n\t};\n\n\tasync trigger(this: ITriggerFunctions): Promise<ITriggerResponse> {\n\t\tconst triggerMode = this.getNodeParameter('triggerMode', 0) as string;\n\t\tconst additionalFields = this.getNodeParameter('additionalFields', 0) as IDataObject;\n\n\t\t// initialize and connect to database\n\t\tconst { db } = await initDB.call(this);\n\t\tconst connection = await db.connect({ direct: true });\n\n\t\t// prepare and set up listener\n\t\tconst onNotification = async (data: IDataObject) => {\n\t\t\tif (data.payload) {\n\t\t\t\ttry {\n\t\t\t\t\tdata.payload = JSON.parse(data.payload as string) as IDataObject;\n\t\t\t\t} catch (error) {}\n\t\t\t}\n\t\t\tthis.emit([this.helpers.returnJsonArray([data])]);\n\t\t};\n\n\t\t// create trigger, function and channel or use existing channel\n\t\tconst pgNames = prepareNames(this.getNode().id, this.getMode(), additionalFields);\n\t\tif (triggerMode === 'createTrigger') {\n\t\t\tawait pgTriggerFunction.call(\n\t\t\t\tthis,\n\t\t\t\tdb,\n\t\t\t\tadditionalFields,\n\t\t\t\tpgNames.functionName,\n\t\t\t\tpgNames.triggerName,\n\t\t\t\tpgNames.channelName,\n\t\t\t);\n\t\t} else {\n\t\t\tpgNames.channelName = this.getNodeParameter('channelName', '') as string;\n\t\t}\n\n\t\t// listen to channel\n\t\tawait connection.none(`LISTEN ${pgNames.channelName}`);\n\n\t\tconst cleanUpDb = async () => {\n\t\t\ttry {\n\t\t\t\ttry {\n\t\t\t\t\t// check if the connection is healthy\n\t\t\t\t\tawait connection.query('SELECT 1');\n\t\t\t\t} catch {\n\t\t\t\t\t// connection already closed. Can't perform cleanup\n\n\t\t\t\t\tthrow new TriggerCloseError(this.getNode(), { level: 'warning' });\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tawait connection.none('UNLISTEN $1:name', [pgNames.channelName]);\n\t\t\t\t\tif (triggerMode === 'createTrigger') {\n\t\t\t\t\t\tconst functionName = pgNames.functionName.includes('(')\n\t\t\t\t\t\t\t? pgNames.functionName.split('(')[0]\n\t\t\t\t\t\t\t: pgNames.functionName;\n\t\t\t\t\t\tawait connection.any('DROP FUNCTION IF EXISTS $1:name CASCADE', [functionName]);\n\n\t\t\t\t\t\tconst schema = this.getNodeParameter('schema', undefined, {\n\t\t\t\t\t\t\textractValue: true,\n\t\t\t\t\t\t}) as string;\n\t\t\t\t\t\tconst table = this.getNodeParameter('tableName', undefined, {\n\t\t\t\t\t\t\textractValue: true,\n\t\t\t\t\t\t}) as string;\n\n\t\t\t\t\t\tawait connection.any('DROP TRIGGER IF EXISTS $1:name ON $2:name.$3:name CASCADE', [\n\t\t\t\t\t\t\tpgNames.triggerName,\n\t\t\t\t\t\t\tschema,\n\t\t\t\t\t\t\ttable,\n\t\t\t\t\t\t]);\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow new TriggerCloseError(this.getNode(), { cause: error as Error, level: 'error' });\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tconnection.client.removeListener('notification', onNotification);\n\t\t\t}\n\t\t};\n\n\t\tconnection.client.on('notification', onNotification);\n\n\t\t// The \"closeFunction\" function gets called by n8n whenever\n\t\t// the workflow gets deactivated and can so clean up.\n\t\tconst closeFunction = async () => {\n\t\t\tawait cleanUpDb();\n\t\t};\n\n\t\tconst manualTriggerFunction = async () => {\n\t\t\tawait new Promise(async (resolve, reject) => {\n\t\t\t\tconst timeoutHandler = setTimeout(async () => {\n\t\t\t\t\treject(\n\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\tawait (async () => {\n\t\t\t\t\t\t\t\tawait cleanUpDb();\n\t\t\t\t\t\t\t\treturn 'Aborted, no data received within 30secs. This 30sec timeout is only set for \"manually triggered execution\". Active Workflows will listen indefinitely.';\n\t\t\t\t\t\t\t})(),\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}, 60000);\n\t\t\t\tconnection.client.on('notification', async (data: IDataObject) => {\n\t\t\t\t\tif (data.payload) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tdata.payload = JSON.parse(data.payload as string) as IDataObject;\n\t\t\t\t\t\t} catch (error) {}\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.emit([this.helpers.returnJsonArray([data])]);\n\t\t\t\t\tclearTimeout(timeoutHandler);\n\t\t\t\t\tresolve(true);\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\n\t\treturn {\n\t\t\tcloseFunction,\n\t\t\tmanualTriggerFunction: this.getMode() === 'manual' ? manualTriggerFunction : undefined,\n\t\t};\n\t}\n}\n"],"mappings":"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","names":[]}
|
|
@@ -40,8 +40,8 @@ class RabbitMQTrigger {
|
|
|
40
40
|
triggerPanel: {
|
|
41
41
|
header: "",
|
|
42
42
|
executionsHelp: {
|
|
43
|
-
inactive: "<b>While building your workflow</b>, click the '
|
|
44
|
-
active: "<b>While building your workflow</b>, click the '
|
|
43
|
+
inactive: "<b>While building your workflow</b>, click the 'test step' button, then trigger a Rabbit MQ event. This will trigger an execution, which will show up in this editor.<br /> <br /><b>Once you're happy with your workflow</b>, <a data-key='activate'>activate</a> it. Then every time a change is detected, the workflow will execute. These executions will show up in the <a data-key='executions'>executions list</a>, but not in the editor.",
|
|
44
|
+
active: "<b>While building your workflow</b>, click the 'test step' button, then trigger a Rabbit MQ event. This will trigger an execution, which will show up in this editor.<br /> <br /><b>Your workflow will also execute automatically</b>, since it's activated. Every time a change is detected, this node will trigger an execution. These executions will show up in the <a data-key='executions'>executions list</a>, but not in the editor."
|
|
45
45
|
},
|
|
46
46
|
activationHint: "Once you\u2019ve finished building your workflow, <a data-key='activate'>activate</a> it to have it also listen continuously (you just won\u2019t see those executions here)."
|
|
47
47
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../nodes/RabbitMQ/RabbitMQTrigger.node.ts"],"sourcesContent":["/* eslint-disable n8n-nodes-base/node-filename-against-convention */\nimport type { Message } from 'amqplib';\nimport type {\n\tIDeferredPromise,\n\tIExecuteResponsePromiseData,\n\tINodeProperties,\n\tINodeType,\n\tINodeTypeDescription,\n\tIRun,\n\tITriggerFunctions,\n\tITriggerResponse,\n} from 'n8n-workflow';\nimport { NodeConnectionTypes, NodeOperationError } from 'n8n-workflow';\n\nimport { rabbitDefaultOptions } from './DefaultOptions';\nimport { MessageTracker, rabbitmqConnectQueue, parseMessage } from './GenericFunctions';\nimport type { TriggerOptions } from './types';\n\nexport class RabbitMQTrigger implements INodeType {\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'RabbitMQ Trigger',\n\t\tname: 'rabbitmqTrigger',\n\t\ticon: 'file:rabbitmq.svg',\n\t\tgroup: ['trigger'],\n\t\tversion: 1,\n\t\tdescription: 'Listens to RabbitMQ messages',\n\t\teventTriggerDescription: '',\n\t\tdefaults: {\n\t\t\tname: 'RabbitMQ Trigger',\n\t\t},\n\t\ttriggerPanel: {\n\t\t\theader: '',\n\t\t\texecutionsHelp: {\n\t\t\t\tinactive:\n\t\t\t\t\t\"<b>While building your workflow</b>, click the 'listen' button, then trigger a Rabbit MQ event. This will trigger an execution, which will show up in this editor.<br /> <br /><b>Once you're happy with your workflow</b>, <a data-key='activate'>activate</a> it. Then every time a change is detected, the workflow will execute. These executions will show up in the <a data-key='executions'>executions list</a>, but not in the editor.\",\n\t\t\t\tactive:\n\t\t\t\t\t\"<b>While building your workflow</b>, click the 'listen' button, then trigger a Rabbit MQ event. This will trigger an execution, which will show up in this editor.<br /> <br /><b>Your workflow will also execute automatically</b>, since it's activated. Every time a change is detected, this node will trigger an execution. These executions will show up in the <a data-key='executions'>executions list</a>, but not in the editor.\",\n\t\t\t},\n\t\t\tactivationHint:\n\t\t\t\t\"Once you’ve finished building your workflow, <a data-key='activate'>activate</a> it to have it also listen continuously (you just won’t see those executions here).\",\n\t\t},\n\t\tinputs: [],\n\t\toutputs: [NodeConnectionTypes.Main],\n\t\tcredentials: [\n\t\t\t{\n\t\t\t\tname: 'rabbitmq',\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t],\n\t\tproperties: [\n\t\t\t{\n\t\t\t\tdisplayName: 'Queue / Topic',\n\t\t\t\tname: 'queue',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\tplaceholder: 'queue-name',\n\t\t\t\tdescription: 'The name of the queue to read from',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Options',\n\t\t\t\tname: 'options',\n\t\t\t\ttype: 'collection',\n\t\t\t\tdefault: {},\n\t\t\t\tplaceholder: 'Add option',\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Content Is Binary',\n\t\t\t\t\t\tname: 'contentIsBinary',\n\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\tdefault: false,\n\t\t\t\t\t\tdescription: 'Whether to save the content as binary',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Delete From Queue When',\n\t\t\t\t\t\tname: 'acknowledge',\n\t\t\t\t\t\ttype: 'options',\n\t\t\t\t\t\toptions: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'Execution Finishes',\n\t\t\t\t\t\t\t\tvalue: 'executionFinishes',\n\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t'After the workflow execution finished. No matter if the execution was successful or not.',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'Execution Finishes Successfully',\n\t\t\t\t\t\t\t\tvalue: 'executionFinishesSuccessfully',\n\t\t\t\t\t\t\t\tdescription: 'After the workflow execution finished successfully',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'Immediately',\n\t\t\t\t\t\t\t\tvalue: 'immediately',\n\t\t\t\t\t\t\t\tdescription: 'As soon as the message got received',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'Specified Later in Workflow',\n\t\t\t\t\t\t\t\tvalue: 'laterMessageNode',\n\t\t\t\t\t\t\t\tdescription: 'Using a RabbitMQ node to remove the item from the queue',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tdefault: 'immediately',\n\t\t\t\t\t\tdescription: 'When to acknowledge the message',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'JSON Parse Body',\n\t\t\t\t\t\tname: 'jsonParseBody',\n\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\t\tcontentIsBinary: [true],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdefault: false,\n\t\t\t\t\t\tdescription: 'Whether to parse the body to an object',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Only Content',\n\t\t\t\t\t\tname: 'onlyContent',\n\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\t\tcontentIsBinary: [true],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdefault: false,\n\t\t\t\t\t\tdescription: 'Whether to return only the content property',\n\t\t\t\t\t},\n\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Parallel Message Processing Limit',\n\t\t\t\t\t\tname: 'parallelMessages',\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\tdefault: -1,\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\t\tacknowledge: ['immediately'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdescription: 'Max number of executions at a time. Use -1 for no limit.',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Binding',\n\t\t\t\t\t\tname: 'binding',\n\t\t\t\t\t\tplaceholder: 'Add Binding',\n\t\t\t\t\t\tdescription: 'Add binding to queu',\n\t\t\t\t\t\ttype: 'fixedCollection',\n\t\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\t\tmultipleValues: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdefault: {},\n\t\t\t\t\t\toptions: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'bindings',\n\t\t\t\t\t\t\t\tdisplayName: 'Binding',\n\t\t\t\t\t\t\t\tvalues: [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tdisplayName: 'Exchange',\n\t\t\t\t\t\t\t\t\t\tname: 'exchange',\n\t\t\t\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\t\t\t\tdefault: '',\n\t\t\t\t\t\t\t\t\t\tplaceholder: 'exchange',\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tdisplayName: 'RoutingKey',\n\t\t\t\t\t\t\t\t\t\tname: 'routingKey',\n\t\t\t\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\t\t\t\tdefault: '',\n\t\t\t\t\t\t\t\t\t\tplaceholder: 'routing-key',\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t\t...rabbitDefaultOptions,\n\t\t\t\t].sort((a, b) => {\n\t\t\t\t\tif (\n\t\t\t\t\t\t(a as INodeProperties).displayName.toLowerCase() <\n\t\t\t\t\t\t(b as INodeProperties).displayName.toLowerCase()\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn -1;\n\t\t\t\t\t}\n\t\t\t\t\tif (\n\t\t\t\t\t\t(a as INodeProperties).displayName.toLowerCase() >\n\t\t\t\t\t\t(b as INodeProperties).displayName.toLowerCase()\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\t\t\t\t\treturn 0;\n\t\t\t\t}) as INodeProperties[],\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName:\n\t\t\t\t\t\"To delete an item from the queue, insert a RabbitMQ node later in the workflow and use the 'Delete from queue' operation\",\n\t\t\t\tname: 'laterMessageNode',\n\t\t\t\ttype: 'notice',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\t'/options.acknowledge': ['laterMessageNode'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tdefault: '',\n\t\t\t},\n\t\t],\n\t};\n\n\tasync trigger(this: ITriggerFunctions): Promise<ITriggerResponse> {\n\t\tconst queue = this.getNodeParameter('queue') as string;\n\t\tconst options = this.getNodeParameter('options', {}) as TriggerOptions;\n\t\tconst channel = await rabbitmqConnectQueue.call(this, queue, options);\n\n\t\tif (this.getMode() === 'manual') {\n\t\t\tconst manualTriggerFunction = async () => {\n\t\t\t\t// Do only catch a single message when executing manually, else messages will leak\n\t\t\t\tawait channel.prefetch(1);\n\n\t\t\t\tconst processMessage = async (message: Message | null) => {\n\t\t\t\t\tif (message !== null) {\n\t\t\t\t\t\tconst item = await parseMessage(message, options, this.helpers);\n\t\t\t\t\t\tchannel.ack(message);\n\t\t\t\t\t\tthis.emit([[item]]);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.emitError(new Error('Connection got closed unexpectedly'));\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tconst existingMessage = await channel.get(queue);\n\t\t\t\tif (existingMessage) await processMessage(existingMessage);\n\t\t\t\telse await channel.consume(queue, processMessage);\n\t\t\t};\n\n\t\t\tconst closeFunction = async () => {\n\t\t\t\tawait channel.close();\n\t\t\t\tawait channel.connection.close();\n\t\t\t\treturn;\n\t\t\t};\n\n\t\t\treturn {\n\t\t\t\tcloseFunction,\n\t\t\t\tmanualTriggerFunction,\n\t\t\t};\n\t\t}\n\n\t\tconst parallelMessages = options.parallelMessages ?? -1;\n\t\tif (isNaN(parallelMessages) || parallelMessages === 0 || parallelMessages < -1) {\n\t\t\tthrow new NodeOperationError(\n\t\t\t\tthis.getNode(),\n\t\t\t\t'Parallel message processing limit must be a number greater than zero (or -1 for no limit)',\n\t\t\t);\n\t\t}\n\n\t\tlet acknowledgeMode = options.acknowledge ?? 'immediately';\n\n\t\tif (parallelMessages !== -1 && acknowledgeMode === 'immediately') {\n\t\t\t// If parallel message limit is set, then the default mode is \"executionFinishes\"\n\t\t\t// unless acknowledgeMode got set specifically. Be aware that the mode \"immediately\"\n\t\t\t// can not be supported in this case.\n\t\t\tacknowledgeMode = 'executionFinishes';\n\t\t}\n\n\t\tconst messageTracker = new MessageTracker();\n\t\tlet closeGotCalled = false;\n\n\t\tif (parallelMessages !== -1) {\n\t\t\tawait channel.prefetch(parallelMessages);\n\t\t}\n\n\t\tchannel.on('close', () => {\n\t\t\tif (!closeGotCalled) {\n\t\t\t\tthis.emitError(new Error('Connection got closed unexpectedly'));\n\t\t\t}\n\t\t});\n\n\t\tconst consumerInfo = await channel.consume(queue, async (message) => {\n\t\t\tif (message !== null) {\n\t\t\t\ttry {\n\t\t\t\t\tif (acknowledgeMode !== 'immediately') {\n\t\t\t\t\t\tmessageTracker.received(message);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst item = await parseMessage(message, options, this.helpers);\n\n\t\t\t\t\tlet responsePromise: IDeferredPromise<IRun> | undefined = undefined;\n\t\t\t\t\tlet responsePromiseHook: IDeferredPromise<IExecuteResponsePromiseData> | undefined =\n\t\t\t\t\t\tundefined;\n\t\t\t\t\tif (acknowledgeMode !== 'immediately' && acknowledgeMode !== 'laterMessageNode') {\n\t\t\t\t\t\tresponsePromise = this.helpers.createDeferredPromise();\n\t\t\t\t\t} else if (acknowledgeMode === 'laterMessageNode') {\n\t\t\t\t\t\tresponsePromiseHook = this.helpers.createDeferredPromise<IExecuteResponsePromiseData>();\n\t\t\t\t\t}\n\t\t\t\t\tif (responsePromiseHook) {\n\t\t\t\t\t\tthis.emit([[item]], responsePromiseHook, undefined);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.emit([[item]], undefined, responsePromise);\n\t\t\t\t\t}\n\t\t\t\t\tif (responsePromise && acknowledgeMode !== 'laterMessageNode') {\n\t\t\t\t\t\t// Acknowledge message after the execution finished\n\t\t\t\t\t\tawait responsePromise.promise.then(async (data: IRun) => {\n\t\t\t\t\t\t\tif (data.data.resultData.error) {\n\t\t\t\t\t\t\t\t// The execution did fail\n\t\t\t\t\t\t\t\tif (acknowledgeMode === 'executionFinishesSuccessfully') {\n\t\t\t\t\t\t\t\t\tchannel.nack(message);\n\t\t\t\t\t\t\t\t\tmessageTracker.answered(message);\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tchannel.ack(message);\n\t\t\t\t\t\t\tmessageTracker.answered(message);\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if (responsePromiseHook && acknowledgeMode === 'laterMessageNode') {\n\t\t\t\t\t\tawait responsePromiseHook.promise.then(() => {\n\t\t\t\t\t\t\tchannel.ack(message);\n\t\t\t\t\t\t\tmessageTracker.answered(message);\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Acknowledge message directly\n\t\t\t\t\t\tchannel.ack(message);\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst workflow = this.getWorkflow();\n\t\t\t\t\tconst node = this.getNode();\n\t\t\t\t\tif (acknowledgeMode !== 'immediately') {\n\t\t\t\t\t\tmessageTracker.answered(message);\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.logger.error(\n\t\t\t\t\t\t`There was a problem with the RabbitMQ Trigger node \"${node.name}\" in workflow \"${workflow.id}\": \"${error.message}\"`,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tnode: node.name,\n\t\t\t\t\t\t\tworkflowId: workflow.id,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tconst consumerTag = consumerInfo.consumerTag;\n\n\t\t// The \"closeFunction\" function gets called by n8n whenever\n\t\t// the workflow gets deactivated and can so clean up.\n\t\tconst closeFunction = async () => {\n\t\t\tcloseGotCalled = true;\n\t\t\ttry {\n\t\t\t\treturn await messageTracker.closeChannel(channel, consumerTag);\n\t\t\t} catch (error) {\n\t\t\t\tconst workflow = this.getWorkflow();\n\t\t\t\tconst node = this.getNode();\n\t\t\t\tthis.logger.error(\n\t\t\t\t\t`There was a problem closing the RabbitMQ Trigger node connection \"${node.name}\" in workflow \"${workflow.id}\": \"${error.message}\"`,\n\t\t\t\t\t{\n\t\t\t\t\t\tnode: node.name,\n\t\t\t\t\t\tworkflowId: workflow.id,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\n\t\treturn {\n\t\t\tcloseFunction,\n\t\t};\n\t}\n}\n"],"mappings":"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","names":["closeFunction"]}
|
|
1
|
+
{"version":3,"sources":["../../../nodes/RabbitMQ/RabbitMQTrigger.node.ts"],"sourcesContent":["/* eslint-disable n8n-nodes-base/node-filename-against-convention */\nimport type { Message } from 'amqplib';\nimport type {\n\tIDeferredPromise,\n\tIExecuteResponsePromiseData,\n\tINodeProperties,\n\tINodeType,\n\tINodeTypeDescription,\n\tIRun,\n\tITriggerFunctions,\n\tITriggerResponse,\n} from 'n8n-workflow';\nimport { NodeConnectionTypes, NodeOperationError } from 'n8n-workflow';\n\nimport { rabbitDefaultOptions } from './DefaultOptions';\nimport { MessageTracker, rabbitmqConnectQueue, parseMessage } from './GenericFunctions';\nimport type { TriggerOptions } from './types';\n\nexport class RabbitMQTrigger implements INodeType {\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'RabbitMQ Trigger',\n\t\tname: 'rabbitmqTrigger',\n\t\ticon: 'file:rabbitmq.svg',\n\t\tgroup: ['trigger'],\n\t\tversion: 1,\n\t\tdescription: 'Listens to RabbitMQ messages',\n\t\teventTriggerDescription: '',\n\t\tdefaults: {\n\t\t\tname: 'RabbitMQ Trigger',\n\t\t},\n\t\ttriggerPanel: {\n\t\t\theader: '',\n\t\t\texecutionsHelp: {\n\t\t\t\tinactive:\n\t\t\t\t\t\"<b>While building your workflow</b>, click the 'test step' button, then trigger a Rabbit MQ event. This will trigger an execution, which will show up in this editor.<br /> <br /><b>Once you're happy with your workflow</b>, <a data-key='activate'>activate</a> it. Then every time a change is detected, the workflow will execute. These executions will show up in the <a data-key='executions'>executions list</a>, but not in the editor.\",\n\t\t\t\tactive:\n\t\t\t\t\t\"<b>While building your workflow</b>, click the 'test step' button, then trigger a Rabbit MQ event. This will trigger an execution, which will show up in this editor.<br /> <br /><b>Your workflow will also execute automatically</b>, since it's activated. Every time a change is detected, this node will trigger an execution. These executions will show up in the <a data-key='executions'>executions list</a>, but not in the editor.\",\n\t\t\t},\n\t\t\tactivationHint:\n\t\t\t\t\"Once you’ve finished building your workflow, <a data-key='activate'>activate</a> it to have it also listen continuously (you just won’t see those executions here).\",\n\t\t},\n\t\tinputs: [],\n\t\toutputs: [NodeConnectionTypes.Main],\n\t\tcredentials: [\n\t\t\t{\n\t\t\t\tname: 'rabbitmq',\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t],\n\t\tproperties: [\n\t\t\t{\n\t\t\t\tdisplayName: 'Queue / Topic',\n\t\t\t\tname: 'queue',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\tplaceholder: 'queue-name',\n\t\t\t\tdescription: 'The name of the queue to read from',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Options',\n\t\t\t\tname: 'options',\n\t\t\t\ttype: 'collection',\n\t\t\t\tdefault: {},\n\t\t\t\tplaceholder: 'Add option',\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Content Is Binary',\n\t\t\t\t\t\tname: 'contentIsBinary',\n\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\tdefault: false,\n\t\t\t\t\t\tdescription: 'Whether to save the content as binary',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Delete From Queue When',\n\t\t\t\t\t\tname: 'acknowledge',\n\t\t\t\t\t\ttype: 'options',\n\t\t\t\t\t\toptions: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'Execution Finishes',\n\t\t\t\t\t\t\t\tvalue: 'executionFinishes',\n\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t'After the workflow execution finished. No matter if the execution was successful or not.',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'Execution Finishes Successfully',\n\t\t\t\t\t\t\t\tvalue: 'executionFinishesSuccessfully',\n\t\t\t\t\t\t\t\tdescription: 'After the workflow execution finished successfully',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'Immediately',\n\t\t\t\t\t\t\t\tvalue: 'immediately',\n\t\t\t\t\t\t\t\tdescription: 'As soon as the message got received',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'Specified Later in Workflow',\n\t\t\t\t\t\t\t\tvalue: 'laterMessageNode',\n\t\t\t\t\t\t\t\tdescription: 'Using a RabbitMQ node to remove the item from the queue',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tdefault: 'immediately',\n\t\t\t\t\t\tdescription: 'When to acknowledge the message',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'JSON Parse Body',\n\t\t\t\t\t\tname: 'jsonParseBody',\n\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\t\tcontentIsBinary: [true],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdefault: false,\n\t\t\t\t\t\tdescription: 'Whether to parse the body to an object',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Only Content',\n\t\t\t\t\t\tname: 'onlyContent',\n\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\t\tcontentIsBinary: [true],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdefault: false,\n\t\t\t\t\t\tdescription: 'Whether to return only the content property',\n\t\t\t\t\t},\n\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Parallel Message Processing Limit',\n\t\t\t\t\t\tname: 'parallelMessages',\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\tdefault: -1,\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\t\tacknowledge: ['immediately'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdescription: 'Max number of executions at a time. Use -1 for no limit.',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Binding',\n\t\t\t\t\t\tname: 'binding',\n\t\t\t\t\t\tplaceholder: 'Add Binding',\n\t\t\t\t\t\tdescription: 'Add binding to queu',\n\t\t\t\t\t\ttype: 'fixedCollection',\n\t\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\t\tmultipleValues: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdefault: {},\n\t\t\t\t\t\toptions: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'bindings',\n\t\t\t\t\t\t\t\tdisplayName: 'Binding',\n\t\t\t\t\t\t\t\tvalues: [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tdisplayName: 'Exchange',\n\t\t\t\t\t\t\t\t\t\tname: 'exchange',\n\t\t\t\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\t\t\t\tdefault: '',\n\t\t\t\t\t\t\t\t\t\tplaceholder: 'exchange',\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tdisplayName: 'RoutingKey',\n\t\t\t\t\t\t\t\t\t\tname: 'routingKey',\n\t\t\t\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\t\t\t\tdefault: '',\n\t\t\t\t\t\t\t\t\t\tplaceholder: 'routing-key',\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t\t...rabbitDefaultOptions,\n\t\t\t\t].sort((a, b) => {\n\t\t\t\t\tif (\n\t\t\t\t\t\t(a as INodeProperties).displayName.toLowerCase() <\n\t\t\t\t\t\t(b as INodeProperties).displayName.toLowerCase()\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn -1;\n\t\t\t\t\t}\n\t\t\t\t\tif (\n\t\t\t\t\t\t(a as INodeProperties).displayName.toLowerCase() >\n\t\t\t\t\t\t(b as INodeProperties).displayName.toLowerCase()\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\t\t\t\t\treturn 0;\n\t\t\t\t}) as INodeProperties[],\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName:\n\t\t\t\t\t\"To delete an item from the queue, insert a RabbitMQ node later in the workflow and use the 'Delete from queue' operation\",\n\t\t\t\tname: 'laterMessageNode',\n\t\t\t\ttype: 'notice',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\t'/options.acknowledge': ['laterMessageNode'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tdefault: '',\n\t\t\t},\n\t\t],\n\t};\n\n\tasync trigger(this: ITriggerFunctions): Promise<ITriggerResponse> {\n\t\tconst queue = this.getNodeParameter('queue') as string;\n\t\tconst options = this.getNodeParameter('options', {}) as TriggerOptions;\n\t\tconst channel = await rabbitmqConnectQueue.call(this, queue, options);\n\n\t\tif (this.getMode() === 'manual') {\n\t\t\tconst manualTriggerFunction = async () => {\n\t\t\t\t// Do only catch a single message when executing manually, else messages will leak\n\t\t\t\tawait channel.prefetch(1);\n\n\t\t\t\tconst processMessage = async (message: Message | null) => {\n\t\t\t\t\tif (message !== null) {\n\t\t\t\t\t\tconst item = await parseMessage(message, options, this.helpers);\n\t\t\t\t\t\tchannel.ack(message);\n\t\t\t\t\t\tthis.emit([[item]]);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.emitError(new Error('Connection got closed unexpectedly'));\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tconst existingMessage = await channel.get(queue);\n\t\t\t\tif (existingMessage) await processMessage(existingMessage);\n\t\t\t\telse await channel.consume(queue, processMessage);\n\t\t\t};\n\n\t\t\tconst closeFunction = async () => {\n\t\t\t\tawait channel.close();\n\t\t\t\tawait channel.connection.close();\n\t\t\t\treturn;\n\t\t\t};\n\n\t\t\treturn {\n\t\t\t\tcloseFunction,\n\t\t\t\tmanualTriggerFunction,\n\t\t\t};\n\t\t}\n\n\t\tconst parallelMessages = options.parallelMessages ?? -1;\n\t\tif (isNaN(parallelMessages) || parallelMessages === 0 || parallelMessages < -1) {\n\t\t\tthrow new NodeOperationError(\n\t\t\t\tthis.getNode(),\n\t\t\t\t'Parallel message processing limit must be a number greater than zero (or -1 for no limit)',\n\t\t\t);\n\t\t}\n\n\t\tlet acknowledgeMode = options.acknowledge ?? 'immediately';\n\n\t\tif (parallelMessages !== -1 && acknowledgeMode === 'immediately') {\n\t\t\t// If parallel message limit is set, then the default mode is \"executionFinishes\"\n\t\t\t// unless acknowledgeMode got set specifically. Be aware that the mode \"immediately\"\n\t\t\t// can not be supported in this case.\n\t\t\tacknowledgeMode = 'executionFinishes';\n\t\t}\n\n\t\tconst messageTracker = new MessageTracker();\n\t\tlet closeGotCalled = false;\n\n\t\tif (parallelMessages !== -1) {\n\t\t\tawait channel.prefetch(parallelMessages);\n\t\t}\n\n\t\tchannel.on('close', () => {\n\t\t\tif (!closeGotCalled) {\n\t\t\t\tthis.emitError(new Error('Connection got closed unexpectedly'));\n\t\t\t}\n\t\t});\n\n\t\tconst consumerInfo = await channel.consume(queue, async (message) => {\n\t\t\tif (message !== null) {\n\t\t\t\ttry {\n\t\t\t\t\tif (acknowledgeMode !== 'immediately') {\n\t\t\t\t\t\tmessageTracker.received(message);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst item = await parseMessage(message, options, this.helpers);\n\n\t\t\t\t\tlet responsePromise: IDeferredPromise<IRun> | undefined = undefined;\n\t\t\t\t\tlet responsePromiseHook: IDeferredPromise<IExecuteResponsePromiseData> | undefined =\n\t\t\t\t\t\tundefined;\n\t\t\t\t\tif (acknowledgeMode !== 'immediately' && acknowledgeMode !== 'laterMessageNode') {\n\t\t\t\t\t\tresponsePromise = this.helpers.createDeferredPromise();\n\t\t\t\t\t} else if (acknowledgeMode === 'laterMessageNode') {\n\t\t\t\t\t\tresponsePromiseHook = this.helpers.createDeferredPromise<IExecuteResponsePromiseData>();\n\t\t\t\t\t}\n\t\t\t\t\tif (responsePromiseHook) {\n\t\t\t\t\t\tthis.emit([[item]], responsePromiseHook, undefined);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.emit([[item]], undefined, responsePromise);\n\t\t\t\t\t}\n\t\t\t\t\tif (responsePromise && acknowledgeMode !== 'laterMessageNode') {\n\t\t\t\t\t\t// Acknowledge message after the execution finished\n\t\t\t\t\t\tawait responsePromise.promise.then(async (data: IRun) => {\n\t\t\t\t\t\t\tif (data.data.resultData.error) {\n\t\t\t\t\t\t\t\t// The execution did fail\n\t\t\t\t\t\t\t\tif (acknowledgeMode === 'executionFinishesSuccessfully') {\n\t\t\t\t\t\t\t\t\tchannel.nack(message);\n\t\t\t\t\t\t\t\t\tmessageTracker.answered(message);\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tchannel.ack(message);\n\t\t\t\t\t\t\tmessageTracker.answered(message);\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if (responsePromiseHook && acknowledgeMode === 'laterMessageNode') {\n\t\t\t\t\t\tawait responsePromiseHook.promise.then(() => {\n\t\t\t\t\t\t\tchannel.ack(message);\n\t\t\t\t\t\t\tmessageTracker.answered(message);\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Acknowledge message directly\n\t\t\t\t\t\tchannel.ack(message);\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst workflow = this.getWorkflow();\n\t\t\t\t\tconst node = this.getNode();\n\t\t\t\t\tif (acknowledgeMode !== 'immediately') {\n\t\t\t\t\t\tmessageTracker.answered(message);\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.logger.error(\n\t\t\t\t\t\t`There was a problem with the RabbitMQ Trigger node \"${node.name}\" in workflow \"${workflow.id}\": \"${error.message}\"`,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tnode: node.name,\n\t\t\t\t\t\t\tworkflowId: workflow.id,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tconst consumerTag = consumerInfo.consumerTag;\n\n\t\t// The \"closeFunction\" function gets called by n8n whenever\n\t\t// the workflow gets deactivated and can so clean up.\n\t\tconst closeFunction = async () => {\n\t\t\tcloseGotCalled = true;\n\t\t\ttry {\n\t\t\t\treturn await messageTracker.closeChannel(channel, consumerTag);\n\t\t\t} catch (error) {\n\t\t\t\tconst workflow = this.getWorkflow();\n\t\t\t\tconst node = this.getNode();\n\t\t\t\tthis.logger.error(\n\t\t\t\t\t`There was a problem closing the RabbitMQ Trigger node connection \"${node.name}\" in workflow \"${workflow.id}\": \"${error.message}\"`,\n\t\t\t\t\t{\n\t\t\t\t\t\tnode: node.name,\n\t\t\t\t\t\tworkflowId: workflow.id,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\n\t\treturn {\n\t\t\tcloseFunction,\n\t\t};\n\t}\n}\n"],"mappings":"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","names":["closeFunction"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../nodes/SeaTable/v2/actions/asset/upload.operation.ts"],"sourcesContent":["import {\n\ttype IDataObject,\n\ttype INodeExecutionData,\n\ttype INodeProperties,\n\ttype IExecuteFunctions,\n\tupdateDisplayOptions,\n} from 'n8n-workflow';\n\nimport { seaTableApiRequest } from '../../GenericFunctions';\nimport type { IUploadLink, IRowObject } from '../Interfaces';\n\nconst properties: INodeProperties[] = [\n\t{\n\t\t// eslint-disable-next-line n8n-nodes-base/node-param-display-name-wrong-for-dynamic-options\n\t\tdisplayName: 'Table Name',\n\t\tname: 'tableName',\n\t\ttype: 'options',\n\t\tplaceholder: 'Select a table',\n\t\trequired: true,\n\t\ttypeOptions: {\n\t\t\tloadOptionsMethod: 'getTableNames',\n\t\t},\n\t\tdefault: '',\n\t\t// eslint-disable-next-line n8n-nodes-base/node-param-description-wrong-for-dynamic-options\n\t\tdescription:\n\t\t\t'Choose from the list, or specify a name using an <a href=\"https://docs.n8n.io/code-examples/expressions/\">expression</a>',\n\t},\n\t{\n\t\t// eslint-disable-next-line n8n-nodes-base/node-param-display-name-wrong-for-dynamic-options\n\t\tdisplayName: 'Column Name',\n\t\tname: 'uploadColumn',\n\t\ttype: 'options',\n\t\ttypeOptions: {\n\t\t\tloadOptionsDependsOn: ['tableName'],\n\t\t\tloadOptionsMethod: 'getAssetColumns',\n\t\t},\n\t\trequired: true,\n\t\tdefault: '',\n\t\t// eslint-disable-next-line n8n-nodes-base/node-param-description-wrong-for-dynamic-options\n\t\tdescription:\n\t\t\t'Choose from the list, or specify the name using an <a href=\"https://docs.n8n.io/code/expressions/\">expression</a>',\n\t},\n\t{\n\t\t// eslint-disable-next-line n8n-nodes-base/node-param-display-name-wrong-for-dynamic-options\n\t\tdisplayName: 'Row ID',\n\t\tname: 'rowId',\n\t\ttype: 'options',\n\t\tdescription:\n\t\t\t'Choose from the list, or specify an ID using an <a href=\"https://docs.n8n.io/code/expressions/\">expression</a>',\n\t\trequired: true,\n\t\ttypeOptions: {\n\t\t\tloadOptionsDependsOn: ['tableName'],\n\t\t\tloadOptionsMethod: 'getRowIds',\n\t\t},\n\t\tdefault: '',\n\t},\n\t{\n\t\tdisplayName: 'Property Name',\n\t\tname: 'dataPropertyName',\n\t\ttype: 'string',\n\t\tdefault: 'data',\n\t\trequired: true,\n\t\tdescription: 'Name of the binary property which contains the data for the file to be written',\n\t},\n\t{\n\t\tdisplayName: 'Options',\n\t\tname: 'options',\n\t\ttype: 'collection',\n\t\tplaceholder: 'Add Option',\n\t\tdefault: {},\n\t\toptions: [\n\t\t\t{\n\t\t\t\tdisplayName: 'Replace Existing File',\n\t\t\t\tname: 'replace',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: true,\n\t\t\t\tdescription:\n\t\t\t\t\t'Whether to replace the existing asset with the same name (true). Otherwise, a new version with a different name (numeral in parentheses) will be uploaded (false).',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Append to Column',\n\t\t\t\tname: 'append',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: true,\n\t\t\t\tdescription:\n\t\t\t\t\t'Whether to keep existing files/images in the column and append the new asset (true). Otherwise, the existing files/images are removed from the column (false).',\n\t\t\t},\n\t\t],\n\t},\n];\n\nconst displayOptions = {\n\tshow: {\n\t\tresource: ['asset'],\n\t\toperation: ['upload'],\n\t},\n};\n\nexport const description = updateDisplayOptions(displayOptions, properties);\n\nexport async function execute(\n\tthis: IExecuteFunctions,\n\tindex: number,\n): Promise<INodeExecutionData[]> {\n\tconst uploadColumn = this.getNodeParameter('uploadColumn', index) as string;\n\tconst uploadColumnType = uploadColumn.split(':::')[1];\n\tconst uploadColumnName = uploadColumn.split(':::')[0];\n\tconst dataPropertyName = this.getNodeParameter('dataPropertyName', index);\n\tconst tableName = this.getNodeParameter('tableName', index) as string;\n\tconst rowId = this.getNodeParameter('rowId', index) as string;\n\tconst uploadLink = (await seaTableApiRequest.call(\n\t\tthis,\n\t\t{},\n\t\t'GET',\n\t\t'/api/v2.1/dtable/app-upload-link/',\n\t)) as IUploadLink;\n\tconst relativePath =\n\t\tuploadColumnType === 'image' ? uploadLink.img_relative_path : uploadLink.file_relative_path;\n\n\tconst options = this.getNodeParameter('options', index) as IDataObject;\n\n\t// get server url\n\tconst credentials: any = await this.getCredentials('seaTableApi');\n\tconst serverURL: string = credentials.domain\n\t\t? credentials.domain.replace(/\\/$/, '')\n\t\t: 'https://cloud.seatable.io';\n\n\t// get workspaceId\n\tconst workspaceId = (\n\t\tawait this.helpers.httpRequest({\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Token ${credentials.token}`,\n\t\t\t},\n\t\t\turl: `${serverURL}/api/v2.1/dtable/app-access-token/`,\n\t\t\tjson: true,\n\t\t})\n\t).workspace_id;\n\n\t// if there are already assets attached to the column\n\tlet existingAssetArray = [];\n\tconst append = options.append ?? true;\n\tif (append) {\n\t\tconst rowToUpdate = await seaTableApiRequest.call(\n\t\t\tthis,\n\t\t\t{},\n\t\t\t'GET',\n\t\t\t'/api-gateway/api/v2/dtables/{{dtable_uuid}}/rows/' + rowId,\n\t\t\t{},\n\t\t\t{\n\t\t\t\ttable_name: tableName,\n\t\t\t\tconvert_keys: true,\n\t\t\t},\n\t\t);\n\t\texistingAssetArray = rowToUpdate[uploadColumnName] ?? [];\n\t}\n\n\t// Get the binary data and prepare asset for upload\n\tconst fileBufferData = await this.helpers.getBinaryDataBuffer(index, dataPropertyName);\n\tconst binaryData = this.helpers.assertBinaryData(index, dataPropertyName);\n\tconst requestOptions = {\n\t\tformData: {\n\t\t\tfile: {\n\t\t\t\tvalue: fileBufferData,\n\t\t\t\toptions: {\n\t\t\t\t\tfilename: binaryData.fileName,\n\t\t\t\t\tcontentType: binaryData.mimeType,\n\t\t\t\t},\n\t\t\t},\n\t\t\tparent_dir: uploadLink.parent_path,\n\t\t\treplace: options.replace ? '1' : '0',\n\t\t\trelative_path: relativePath,\n\t\t},\n\t};\n\n\t// Send the upload request\n\tconst uploadAsset = await seaTableApiRequest.call(\n\t\tthis,\n\t\t{},\n\t\t'POST',\n\t\t`/seafhttp/upload-api/${uploadLink.upload_link.split('seafhttp/upload-api/')[1]}?ret-json=true`,\n\t\t{},\n\t\t{},\n\t\t'',\n\t\trequestOptions,\n\t);\n\n\t// attach the asset to a column in a base\n\tfor (let c = 0; c < uploadAsset.length; c++) {\n\t\tconst rowInput = {} as IRowObject;\n\n\t\tconst filePath = `${serverURL}/workspace/${workspaceId}${uploadLink.parent_path}/${relativePath}/${uploadAsset[c].name}`;\n\n\t\tif (uploadColumnType === 'image') {\n\t\t\trowInput[uploadColumnName] = [filePath];\n\t\t} else if (uploadColumnType === 'file') {\n\t\t\trowInput[uploadColumnName] = uploadAsset;\n\t\t\tuploadAsset[c].type = 'file';\n\t\t\tuploadAsset[c].url = filePath;\n\t\t}\n\n\t\t// merge with existing assets in this column or with [] and remove duplicates\n\t\tconst mergedArray = existingAssetArray.concat(rowInput[uploadColumnName]);\n\n\t\t// Remove duplicates from input, keeping the last one\n\t\tconst uniqueAssets = Array.from(new Set(mergedArray));\n\n\t\t// Update the rowInput with the unique assets and store into body.row.\n\t\trowInput[uploadColumnName] = uniqueAssets;\n\t\tconst body = {\n\t\t\ttable_name: tableName,\n\t\t\tupdates: [\n\t\t\t\t{\n\t\t\t\t\trow_id: rowId,\n\t\t\t\t\trow: rowInput,\n\t\t\t\t},\n\t\t\t],\n\t\t} as IDataObject;\n\n\t\t// attach assets to table row\n\t\tconst responseData = await seaTableApiRequest.call(\n\t\t\tthis,\n\t\t\t{},\n\t\t\t'PUT',\n\t\t\t'/api-gateway/api/v2/dtables/{{dtable_uuid}}/rows/',\n\t\t\tbody,\n\t\t);\n\n\t\tuploadAsset[c].upload_successful = responseData.success;\n\t}\n\n\treturn this.helpers.returnJsonArray(uploadAsset as IDataObject[]);\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../../../nodes/SeaTable/v2/actions/asset/upload.operation.ts"],"sourcesContent":["import {\n\ttype IDataObject,\n\ttype INodeExecutionData,\n\ttype INodeProperties,\n\ttype IExecuteFunctions,\n\tupdateDisplayOptions,\n} from 'n8n-workflow';\n\nimport { seaTableApiRequest } from '../../GenericFunctions';\nimport type { IUploadLink, IRowObject } from '../Interfaces';\n\nconst properties: INodeProperties[] = [\n\t{\n\t\t// eslint-disable-next-line n8n-nodes-base/node-param-display-name-wrong-for-dynamic-options\n\t\tdisplayName: 'Table Name',\n\t\tname: 'tableName',\n\t\ttype: 'options',\n\t\tplaceholder: 'Select a table',\n\t\trequired: true,\n\t\ttypeOptions: {\n\t\t\tloadOptionsMethod: 'getTableNames',\n\t\t},\n\t\tdefault: '',\n\t\t// eslint-disable-next-line n8n-nodes-base/node-param-description-wrong-for-dynamic-options\n\t\tdescription:\n\t\t\t'Choose from the list, or specify a name using an <a href=\"https://docs.n8n.io/code-examples/expressions/\">expression</a>',\n\t},\n\t{\n\t\t// eslint-disable-next-line n8n-nodes-base/node-param-display-name-wrong-for-dynamic-options\n\t\tdisplayName: 'Column Name',\n\t\tname: 'uploadColumn',\n\t\ttype: 'options',\n\t\ttypeOptions: {\n\t\t\tloadOptionsDependsOn: ['tableName'],\n\t\t\tloadOptionsMethod: 'getAssetColumns',\n\t\t},\n\t\trequired: true,\n\t\tdefault: '',\n\t\t// eslint-disable-next-line n8n-nodes-base/node-param-description-wrong-for-dynamic-options\n\t\tdescription:\n\t\t\t'Choose from the list, or specify the name using an <a href=\"https://docs.n8n.io/code/expressions/\">expression</a>',\n\t},\n\t{\n\t\t// eslint-disable-next-line n8n-nodes-base/node-param-display-name-wrong-for-dynamic-options\n\t\tdisplayName: 'Row ID',\n\t\tname: 'rowId',\n\t\ttype: 'options',\n\t\tdescription:\n\t\t\t'Choose from the list, or specify an ID using an <a href=\"https://docs.n8n.io/code/expressions/\">expression</a>',\n\t\trequired: true,\n\t\ttypeOptions: {\n\t\t\tloadOptionsDependsOn: ['tableName'],\n\t\t\tloadOptionsMethod: 'getRowIds',\n\t\t},\n\t\tdefault: '',\n\t},\n\t{\n\t\tdisplayName: 'Property Name',\n\t\tname: 'dataPropertyName',\n\t\ttype: 'string',\n\t\tdefault: 'data',\n\t\trequired: true,\n\t\tdescription: 'Name of the binary property which contains the data for the file to be written',\n\t},\n\t{\n\t\tdisplayName: 'Options',\n\t\tname: 'options',\n\t\ttype: 'collection',\n\t\tplaceholder: 'Add Option',\n\t\tdefault: {},\n\t\toptions: [\n\t\t\t{\n\t\t\t\tdisplayName: 'Replace Existing File',\n\t\t\t\tname: 'replace',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: true,\n\t\t\t\tdescription:\n\t\t\t\t\t'Whether to replace the existing asset with the same name (true). Otherwise, a new version with a different name (numeral in parentheses) will be uploaded (false).',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Append to Column',\n\t\t\t\tname: 'append',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: true,\n\t\t\t\tdescription:\n\t\t\t\t\t'Whether to keep existing files/images in the column and append the new asset (true). Otherwise, the existing files/images are removed from the column (false).',\n\t\t\t},\n\t\t],\n\t},\n];\n\nconst displayOptions = {\n\tshow: {\n\t\tresource: ['asset'],\n\t\toperation: ['upload'],\n\t},\n};\n\nexport const description = updateDisplayOptions(displayOptions, properties);\n\nexport async function execute(\n\tthis: IExecuteFunctions,\n\tindex: number,\n): Promise<INodeExecutionData[]> {\n\tconst uploadColumn = this.getNodeParameter('uploadColumn', index) as string;\n\tconst uploadColumnType = uploadColumn.split(':::')[1];\n\tconst uploadColumnName = uploadColumn.split(':::')[0];\n\tconst dataPropertyName = this.getNodeParameter('dataPropertyName', index);\n\tconst tableName = this.getNodeParameter('tableName', index) as string;\n\tconst rowId = this.getNodeParameter('rowId', index) as string;\n\tconst uploadLink = (await seaTableApiRequest.call(\n\t\tthis,\n\t\t{},\n\t\t'GET',\n\t\t'/api/v2.1/dtable/app-upload-link/',\n\t)) as IUploadLink;\n\tconst relativePath =\n\t\tuploadColumnType === 'image' ? uploadLink.img_relative_path : uploadLink.file_relative_path;\n\n\tconst options = this.getNodeParameter('options', index);\n\n\t// get server url\n\tconst credentials: any = await this.getCredentials('seaTableApi');\n\tconst serverURL: string = credentials.domain\n\t\t? credentials.domain.replace(/\\/$/, '')\n\t\t: 'https://cloud.seatable.io';\n\n\t// get workspaceId\n\tconst workspaceId = (\n\t\tawait this.helpers.httpRequest({\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Token ${credentials.token}`,\n\t\t\t},\n\t\t\turl: `${serverURL}/api/v2.1/dtable/app-access-token/`,\n\t\t\tjson: true,\n\t\t})\n\t).workspace_id;\n\n\t// if there are already assets attached to the column\n\tlet existingAssetArray = [];\n\tconst append = options.append ?? true;\n\tif (append) {\n\t\tconst rowToUpdate = await seaTableApiRequest.call(\n\t\t\tthis,\n\t\t\t{},\n\t\t\t'GET',\n\t\t\t'/api-gateway/api/v2/dtables/{{dtable_uuid}}/rows/' + rowId,\n\t\t\t{},\n\t\t\t{\n\t\t\t\ttable_name: tableName,\n\t\t\t\tconvert_keys: true,\n\t\t\t},\n\t\t);\n\t\texistingAssetArray = rowToUpdate[uploadColumnName] ?? [];\n\t}\n\n\t// Get the binary data and prepare asset for upload\n\tconst fileBufferData = await this.helpers.getBinaryDataBuffer(index, dataPropertyName);\n\tconst binaryData = this.helpers.assertBinaryData(index, dataPropertyName);\n\tconst requestOptions = {\n\t\tformData: {\n\t\t\tfile: {\n\t\t\t\tvalue: fileBufferData,\n\t\t\t\toptions: {\n\t\t\t\t\tfilename: binaryData.fileName,\n\t\t\t\t\tcontentType: binaryData.mimeType,\n\t\t\t\t},\n\t\t\t},\n\t\t\tparent_dir: uploadLink.parent_path,\n\t\t\treplace: options.replace ? '1' : '0',\n\t\t\trelative_path: relativePath,\n\t\t},\n\t};\n\n\t// Send the upload request\n\tconst uploadAsset = await seaTableApiRequest.call(\n\t\tthis,\n\t\t{},\n\t\t'POST',\n\t\t`/seafhttp/upload-api/${uploadLink.upload_link.split('seafhttp/upload-api/')[1]}?ret-json=true`,\n\t\t{},\n\t\t{},\n\t\t'',\n\t\trequestOptions,\n\t);\n\n\t// attach the asset to a column in a base\n\tfor (let c = 0; c < uploadAsset.length; c++) {\n\t\tconst rowInput = {} as IRowObject;\n\n\t\tconst filePath = `${serverURL}/workspace/${workspaceId}${uploadLink.parent_path}/${relativePath}/${uploadAsset[c].name}`;\n\n\t\tif (uploadColumnType === 'image') {\n\t\t\trowInput[uploadColumnName] = [filePath];\n\t\t} else if (uploadColumnType === 'file') {\n\t\t\trowInput[uploadColumnName] = uploadAsset;\n\t\t\tuploadAsset[c].type = 'file';\n\t\t\tuploadAsset[c].url = filePath;\n\t\t}\n\n\t\t// merge with existing assets in this column or with [] and remove duplicates\n\t\tconst mergedArray = existingAssetArray.concat(rowInput[uploadColumnName]);\n\n\t\t// Remove duplicates from input, keeping the last one\n\t\tconst uniqueAssets = Array.from(new Set(mergedArray));\n\n\t\t// Update the rowInput with the unique assets and store into body.row.\n\t\trowInput[uploadColumnName] = uniqueAssets;\n\t\tconst body = {\n\t\t\ttable_name: tableName,\n\t\t\tupdates: [\n\t\t\t\t{\n\t\t\t\t\trow_id: rowId,\n\t\t\t\t\trow: rowInput,\n\t\t\t\t},\n\t\t\t],\n\t\t} as IDataObject;\n\n\t\t// attach assets to table row\n\t\tconst responseData = await seaTableApiRequest.call(\n\t\t\tthis,\n\t\t\t{},\n\t\t\t'PUT',\n\t\t\t'/api-gateway/api/v2/dtables/{{dtable_uuid}}/rows/',\n\t\t\tbody,\n\t\t);\n\n\t\tuploadAsset[c].upload_successful = responseData.success;\n\t}\n\n\treturn this.helpers.returnJsonArray(uploadAsset as IDataObject[]);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../nodes/SeaTable/v2/actions/row/get.operation.ts"],"sourcesContent":["import {\n\ttype IDataObject,\n\ttype INodeExecutionData,\n\ttype INodeProperties,\n\ttype IExecuteFunctions,\n\tupdateDisplayOptions,\n} from 'n8n-workflow';\n\nimport {\n\tseaTableApiRequest,\n\tenrichColumns,\n\tsimplify_new,\n\tgetBaseCollaborators,\n} from '../../GenericFunctions';\nimport type { IRowResponse, IDtableMetadataColumn } from '../Interfaces';\n\nexport const properties: INodeProperties[] = [\n\t{\n\t\tdisplayName: 'Options',\n\t\tname: 'options',\n\t\ttype: 'collection',\n\t\tplaceholder: 'Add Option',\n\t\tdefault: {},\n\t\toptions: [\n\t\t\t{\n\t\t\t\tdisplayName: 'Simplify',\n\t\t\t\tname: 'simple',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: true,\n\t\t\t\tdescription:\n\t\t\t\t\t'Whether to return a simplified version of the response instead of the raw data',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Return Column Names',\n\t\t\t\tname: 'convert',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: true,\n\t\t\t\tdescription: 'Whether to return the column keys (false) or the column names (true)',\n\t\t\t},\n\t\t],\n\t},\n];\n\nconst displayOptions = {\n\tshow: {\n\t\tresource: ['row'],\n\t\toperation: ['get'],\n\t},\n};\n\nexport const description = updateDisplayOptions(displayOptions, properties);\n\nexport async function execute(\n\tthis: IExecuteFunctions,\n\tindex: number,\n): Promise<INodeExecutionData[]> {\n\t// get parameters\n\tconst tableName = this.getNodeParameter('tableName', index) as string;\n\tconst rowId = this.getNodeParameter('rowId', index) as string;\n\tconst options = this.getNodeParameter('options', index)
|
|
1
|
+
{"version":3,"sources":["../../../../../../nodes/SeaTable/v2/actions/row/get.operation.ts"],"sourcesContent":["import {\n\ttype IDataObject,\n\ttype INodeExecutionData,\n\ttype INodeProperties,\n\ttype IExecuteFunctions,\n\tupdateDisplayOptions,\n} from 'n8n-workflow';\n\nimport {\n\tseaTableApiRequest,\n\tenrichColumns,\n\tsimplify_new,\n\tgetBaseCollaborators,\n} from '../../GenericFunctions';\nimport type { IRowResponse, IDtableMetadataColumn } from '../Interfaces';\n\nexport const properties: INodeProperties[] = [\n\t{\n\t\tdisplayName: 'Options',\n\t\tname: 'options',\n\t\ttype: 'collection',\n\t\tplaceholder: 'Add Option',\n\t\tdefault: {},\n\t\toptions: [\n\t\t\t{\n\t\t\t\tdisplayName: 'Simplify',\n\t\t\t\tname: 'simple',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: true,\n\t\t\t\tdescription:\n\t\t\t\t\t'Whether to return a simplified version of the response instead of the raw data',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Return Column Names',\n\t\t\t\tname: 'convert',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: true,\n\t\t\t\tdescription: 'Whether to return the column keys (false) or the column names (true)',\n\t\t\t},\n\t\t],\n\t},\n];\n\nconst displayOptions = {\n\tshow: {\n\t\tresource: ['row'],\n\t\toperation: ['get'],\n\t},\n};\n\nexport const description = updateDisplayOptions(displayOptions, properties);\n\nexport async function execute(\n\tthis: IExecuteFunctions,\n\tindex: number,\n): Promise<INodeExecutionData[]> {\n\t// get parameters\n\tconst tableName = this.getNodeParameter('tableName', index) as string;\n\tconst rowId = this.getNodeParameter('rowId', index) as string;\n\tconst options = this.getNodeParameter('options', index);\n\n\t// get collaborators\n\tconst collaborators = await getBaseCollaborators.call(this);\n\n\t// get rows\n\tconst sqlResult = (await seaTableApiRequest.call(\n\t\tthis,\n\t\t{},\n\t\t'POST',\n\t\t'/api-gateway/api/v2/dtables/{{dtable_uuid}}/sql/',\n\t\t{\n\t\t\tsql: `SELECT * FROM \\`${tableName}\\` WHERE _id = '${rowId}'`,\n\t\t\tconvert_keys: options.convert ?? true,\n\t\t},\n\t)) as IRowResponse;\n\tconst metadata = sqlResult.metadata as IDtableMetadataColumn[];\n\tconst rows = sqlResult.results;\n\n\t// hide columns like button\n\trows.map((row) => enrichColumns(row, metadata, collaborators));\n\tconst simple = options.simple ?? true;\n\t// remove columns starting with _ if simple;\n\tif (simple) {\n\t\trows.map((row) => simplify_new(row));\n\t}\n\n\treturn this.helpers.returnJsonArray(rows as IDataObject[]);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAMO;AAEP,8BAKO;AAGA,MAAM,aAAgC;AAAA,EAC5C;AAAA,IACC,aAAa;AAAA,IACb,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS,CAAC;AAAA,IACV,SAAS;AAAA,MACR;AAAA,QACC,aAAa;AAAA,QACb,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS;AAAA,QACT,aACC;AAAA,MACF;AAAA,MACA;AAAA,QACC,aAAa;AAAA,QACb,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS;AAAA,QACT,aAAa;AAAA,MACd;AAAA,IACD;AAAA,EACD;AACD;AAEA,MAAM,iBAAiB;AAAA,EACtB,MAAM;AAAA,IACL,UAAU,CAAC,KAAK;AAAA,IAChB,WAAW,CAAC,KAAK;AAAA,EAClB;AACD;AAEO,MAAM,kBAAc,0CAAqB,gBAAgB,UAAU;AAE1E,eAAsB,QAErB,OACgC;AAEhC,QAAM,YAAY,KAAK,iBAAiB,aAAa,KAAK;AAC1D,QAAM,QAAQ,KAAK,iBAAiB,SAAS,KAAK;AAClD,QAAM,UAAU,KAAK,iBAAiB,WAAW,KAAK;AAGtD,QAAM,gBAAgB,MAAM,6CAAqB,KAAK,IAAI;AAG1D,QAAM,YAAa,MAAM,2CAAmB;AAAA,IAC3C;AAAA,IACA,CAAC;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,MACC,KAAK,mBAAmB,SAAS,mBAAmB,KAAK;AAAA,MACzD,cAAc,QAAQ,WAAW;AAAA,IAClC;AAAA,EACD;AACA,QAAM,WAAW,UAAU;AAC3B,QAAM,OAAO,UAAU;AAGvB,OAAK,IAAI,CAAC,YAAQ,uCAAc,KAAK,UAAU,aAAa,CAAC;AAC7D,QAAM,SAAS,QAAQ,UAAU;AAEjC,MAAI,QAAQ;AACX,SAAK,IAAI,CAAC,YAAQ,sCAAa,GAAG,CAAC;AAAA,EACpC;AAEA,SAAO,KAAK,QAAQ,gBAAgB,IAAqB;AAC1D;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../nodes/SeaTable/v2/actions/row/list.operation.ts"],"sourcesContent":["import {\n\ttype IDataObject,\n\ttype INodeExecutionData,\n\ttype INodeProperties,\n\ttype IExecuteFunctions,\n\tupdateDisplayOptions,\n} from 'n8n-workflow';\n\nimport {\n\tseaTableApiRequest,\n\tenrichColumns,\n\tsimplify_new,\n\tgetBaseCollaborators,\n} from '../../GenericFunctions';\nimport type { IRow } from '../Interfaces';\n\nexport const properties: INodeProperties[] = [\n\t{\n\t\t// eslint-disable-next-line n8n-nodes-base/node-param-display-name-wrong-for-dynamic-options\n\t\tdisplayName: 'View Name',\n\t\tname: 'viewName',\n\t\ttype: 'options',\n\t\ttypeOptions: {\n\t\t\tloadOptionsDependsOn: ['tableName'],\n\t\t\tloadOptionsMethod: 'getTableViews',\n\t\t},\n\t\tdefault: '',\n\t\t// eslint-disable-next-line n8n-nodes-base/node-param-description-wrong-for-dynamic-options\n\t\tdescription:\n\t\t\t'The name of SeaTable view to access, or specify by using an expression. Provide it in the way \"col.name:::col.type\".',\n\t},\n\t{\n\t\tdisplayName: 'Options',\n\t\tname: 'options',\n\t\ttype: 'collection',\n\t\tplaceholder: 'Add Option',\n\t\tdefault: {},\n\t\toptions: [\n\t\t\t{\n\t\t\t\tdisplayName: 'Simplify',\n\t\t\t\tname: 'simple',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: true,\n\t\t\t\tdescription:\n\t\t\t\t\t'Whether to return a simplified version of the response instead of the raw data',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Return Column Names',\n\t\t\t\tname: 'convert',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: true,\n\t\t\t\tdescription: 'Whether to return the column keys (false) or the column names (true)',\n\t\t\t},\n\t\t],\n\t},\n];\n\nconst displayOptions = {\n\tshow: {\n\t\tresource: ['row'],\n\t\toperation: ['list'],\n\t},\n};\n\nexport const description = updateDisplayOptions(displayOptions, properties);\n\nexport async function execute(\n\tthis: IExecuteFunctions,\n\tindex: number,\n): Promise<INodeExecutionData[]> {\n\t// get parameters\n\tconst tableName = this.getNodeParameter('tableName', index) as string;\n\tconst viewName = this.getNodeParameter('viewName', index) as string;\n\tconst options = this.getNodeParameter('options', index)
|
|
1
|
+
{"version":3,"sources":["../../../../../../nodes/SeaTable/v2/actions/row/list.operation.ts"],"sourcesContent":["import {\n\ttype IDataObject,\n\ttype INodeExecutionData,\n\ttype INodeProperties,\n\ttype IExecuteFunctions,\n\tupdateDisplayOptions,\n} from 'n8n-workflow';\n\nimport {\n\tseaTableApiRequest,\n\tenrichColumns,\n\tsimplify_new,\n\tgetBaseCollaborators,\n} from '../../GenericFunctions';\nimport type { IRow } from '../Interfaces';\n\nexport const properties: INodeProperties[] = [\n\t{\n\t\t// eslint-disable-next-line n8n-nodes-base/node-param-display-name-wrong-for-dynamic-options\n\t\tdisplayName: 'View Name',\n\t\tname: 'viewName',\n\t\ttype: 'options',\n\t\ttypeOptions: {\n\t\t\tloadOptionsDependsOn: ['tableName'],\n\t\t\tloadOptionsMethod: 'getTableViews',\n\t\t},\n\t\tdefault: '',\n\t\t// eslint-disable-next-line n8n-nodes-base/node-param-description-wrong-for-dynamic-options\n\t\tdescription:\n\t\t\t'The name of SeaTable view to access, or specify by using an expression. Provide it in the way \"col.name:::col.type\".',\n\t},\n\t{\n\t\tdisplayName: 'Options',\n\t\tname: 'options',\n\t\ttype: 'collection',\n\t\tplaceholder: 'Add Option',\n\t\tdefault: {},\n\t\toptions: [\n\t\t\t{\n\t\t\t\tdisplayName: 'Simplify',\n\t\t\t\tname: 'simple',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: true,\n\t\t\t\tdescription:\n\t\t\t\t\t'Whether to return a simplified version of the response instead of the raw data',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Return Column Names',\n\t\t\t\tname: 'convert',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: true,\n\t\t\t\tdescription: 'Whether to return the column keys (false) or the column names (true)',\n\t\t\t},\n\t\t],\n\t},\n];\n\nconst displayOptions = {\n\tshow: {\n\t\tresource: ['row'],\n\t\toperation: ['list'],\n\t},\n};\n\nexport const description = updateDisplayOptions(displayOptions, properties);\n\nexport async function execute(\n\tthis: IExecuteFunctions,\n\tindex: number,\n): Promise<INodeExecutionData[]> {\n\t// get parameters\n\tconst tableName = this.getNodeParameter('tableName', index) as string;\n\tconst viewName = this.getNodeParameter('viewName', index) as string;\n\tconst options = this.getNodeParameter('options', index);\n\n\t// get collaborators\n\tconst collaborators = await getBaseCollaborators.call(this);\n\n\t// get rows\n\tconst requestMeta = await seaTableApiRequest.call(\n\t\tthis,\n\t\t{},\n\t\t'GET',\n\t\t'/api-gateway/api/v2/dtables/{{dtable_uuid}}/metadata/',\n\t);\n\n\tconst requestRows = await seaTableApiRequest.call(\n\t\tthis,\n\t\t{},\n\t\t'GET',\n\t\t'/api-gateway/api/v2/dtables/{{dtable_uuid}}/rows/',\n\t\t{},\n\t\t{\n\t\t\ttable_name: tableName,\n\t\t\tview_name: viewName,\n\t\t\tlimit: 1000,\n\t\t\tconvert_keys: options.convert ?? true,\n\t\t},\n\t);\n\n\tconst metadata =\n\t\trequestMeta.metadata.tables.find((table: { name: string }) => table.name === tableName)\n\t\t\t?.columns ?? [];\n\tconst rows = requestRows.rows as IRow[];\n\n\t// hide columns like button\n\trows.map((row) => enrichColumns(row, metadata, collaborators));\n\n\tconst simple = options.simple ?? true;\n\t// remove columns starting with _ if simple;\n\tif (simple) {\n\t\trows.map((row) => simplify_new(row));\n\t}\n\n\treturn this.helpers.returnJsonArray(rows as IDataObject[]);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAMO;AAEP,8BAKO;AAGA,MAAM,aAAgC;AAAA,EAC5C;AAAA;AAAA,IAEC,aAAa;AAAA,IACb,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,MACZ,sBAAsB,CAAC,WAAW;AAAA,MAClC,mBAAmB;AAAA,IACpB;AAAA,IACA,SAAS;AAAA;AAAA,IAET,aACC;AAAA,EACF;AAAA,EACA;AAAA,IACC,aAAa;AAAA,IACb,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS,CAAC;AAAA,IACV,SAAS;AAAA,MACR;AAAA,QACC,aAAa;AAAA,QACb,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS;AAAA,QACT,aACC;AAAA,MACF;AAAA,MACA;AAAA,QACC,aAAa;AAAA,QACb,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS;AAAA,QACT,aAAa;AAAA,MACd;AAAA,IACD;AAAA,EACD;AACD;AAEA,MAAM,iBAAiB;AAAA,EACtB,MAAM;AAAA,IACL,UAAU,CAAC,KAAK;AAAA,IAChB,WAAW,CAAC,MAAM;AAAA,EACnB;AACD;AAEO,MAAM,kBAAc,0CAAqB,gBAAgB,UAAU;AAE1E,eAAsB,QAErB,OACgC;AAEhC,QAAM,YAAY,KAAK,iBAAiB,aAAa,KAAK;AAC1D,QAAM,WAAW,KAAK,iBAAiB,YAAY,KAAK;AACxD,QAAM,UAAU,KAAK,iBAAiB,WAAW,KAAK;AAGtD,QAAM,gBAAgB,MAAM,6CAAqB,KAAK,IAAI;AAG1D,QAAM,cAAc,MAAM,2CAAmB;AAAA,IAC5C;AAAA,IACA,CAAC;AAAA,IACD;AAAA,IACA;AAAA,EACD;AAEA,QAAM,cAAc,MAAM,2CAAmB;AAAA,IAC5C;AAAA,IACA,CAAC;AAAA,IACD;AAAA,IACA;AAAA,IACA,CAAC;AAAA,IACD;AAAA,MACC,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,OAAO;AAAA,MACP,cAAc,QAAQ,WAAW;AAAA,IAClC;AAAA,EACD;AAEA,QAAM,WACL,YAAY,SAAS,OAAO,KAAK,CAAC,UAA4B,MAAM,SAAS,SAAS,GACnF,WAAW,CAAC;AAChB,QAAM,OAAO,YAAY;AAGzB,OAAK,IAAI,CAAC,YAAQ,uCAAc,KAAK,UAAU,aAAa,CAAC;AAE7D,QAAM,SAAS,QAAQ,UAAU;AAEjC,MAAI,QAAQ;AACX,SAAK,IAAI,CAAC,YAAQ,sCAAa,GAAG,CAAC;AAAA,EACpC;AAEA,SAAO,KAAK,QAAQ,gBAAgB,IAAqB;AAC1D;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../nodes/SeaTable/v2/actions/row/search.operation.ts"],"sourcesContent":["import {\n\ttype IDataObject,\n\ttype INodeExecutionData,\n\ttype INodeProperties,\n\ttype IExecuteFunctions,\n\tupdateDisplayOptions,\n} from 'n8n-workflow';\n\nimport {\n\tseaTableApiRequest,\n\tenrichColumns,\n\tsimplify_new,\n\tgetBaseCollaborators,\n} from '../../GenericFunctions';\nimport type { IDtableMetadataColumn, IRowResponse } from '../Interfaces';\n\nexport const properties: INodeProperties[] = [\n\t{\n\t\tdisplayName: 'Column Name or ID',\n\t\tname: 'searchColumn',\n\t\ttype: 'options',\n\t\ttypeOptions: {\n\t\t\tloadOptionsDependsOn: ['tableName'],\n\t\t\tloadOptionsMethod: 'getSearchableColumns',\n\t\t},\n\t\trequired: true,\n\t\tdefault: '',\n\t\t// eslint-disable-next-line n8n-nodes-base/node-param-description-wrong-for-dynamic-options\n\t\tdescription:\n\t\t\t'Select the column to be searched. Not all column types are supported for search. Choose from the list, or specify a name using an <a href=\"https://docs.n8n.io/code-examples/expressions/\">expression</a>.',\n\t},\n\t{\n\t\tdisplayName: 'Search Term',\n\t\tname: 'searchTerm',\n\t\ttype: 'string',\n\t\trequired: true,\n\t\tdefault: '',\n\t\tdescription: 'What to look for?',\n\t},\n\t{\n\t\tdisplayName: 'Options',\n\t\tname: 'options',\n\t\ttype: 'collection',\n\t\tplaceholder: 'Add Option',\n\t\tdefault: {},\n\t\toptions: [\n\t\t\t{\n\t\t\t\tdisplayName: 'Case Insensitive Search',\n\t\t\t\tname: 'insensitive',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: false,\n\t\t\t\tdescription:\n\t\t\t\t\t'Whether the search ignores case sensitivity (true). Otherwise, it distinguishes between uppercase and lowercase characters.',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Activate Wildcard Search',\n\t\t\t\tname: 'wildcard',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: true,\n\t\t\t\tdescription:\n\t\t\t\t\t'Whether the search only results perfect matches (true). Otherwise, it finds a row even if the search value is part of a string (false).',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Simplify',\n\t\t\t\tname: 'simple',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: true,\n\t\t\t\tdescription:\n\t\t\t\t\t'Whether to return a simplified version of the response instead of the raw data',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Return Column Names',\n\t\t\t\tname: 'convert',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: true,\n\t\t\t\tdescription: 'Whether to return the column keys (false) or the column names (true)',\n\t\t\t},\n\t\t],\n\t},\n];\n\nconst displayOptions = {\n\tshow: {\n\t\tresource: ['row'],\n\t\toperation: ['search'],\n\t},\n};\n\nexport const description = updateDisplayOptions(displayOptions, properties);\n\nexport async function execute(\n\tthis: IExecuteFunctions,\n\tindex: number,\n): Promise<INodeExecutionData[]> {\n\tconst tableName = this.getNodeParameter('tableName', index) as string;\n\tconst searchColumn = this.getNodeParameter('searchColumn', index) as string;\n\tconst searchTerm = this.getNodeParameter('searchTerm', index) as string | number;\n\tlet searchTermString = String(searchTerm);\n\tconst options = this.getNodeParameter('options', index)
|
|
1
|
+
{"version":3,"sources":["../../../../../../nodes/SeaTable/v2/actions/row/search.operation.ts"],"sourcesContent":["import {\n\ttype IDataObject,\n\ttype INodeExecutionData,\n\ttype INodeProperties,\n\ttype IExecuteFunctions,\n\tupdateDisplayOptions,\n} from 'n8n-workflow';\n\nimport {\n\tseaTableApiRequest,\n\tenrichColumns,\n\tsimplify_new,\n\tgetBaseCollaborators,\n} from '../../GenericFunctions';\nimport type { IDtableMetadataColumn, IRowResponse } from '../Interfaces';\n\nexport const properties: INodeProperties[] = [\n\t{\n\t\tdisplayName: 'Column Name or ID',\n\t\tname: 'searchColumn',\n\t\ttype: 'options',\n\t\ttypeOptions: {\n\t\t\tloadOptionsDependsOn: ['tableName'],\n\t\t\tloadOptionsMethod: 'getSearchableColumns',\n\t\t},\n\t\trequired: true,\n\t\tdefault: '',\n\t\t// eslint-disable-next-line n8n-nodes-base/node-param-description-wrong-for-dynamic-options\n\t\tdescription:\n\t\t\t'Select the column to be searched. Not all column types are supported for search. Choose from the list, or specify a name using an <a href=\"https://docs.n8n.io/code-examples/expressions/\">expression</a>.',\n\t},\n\t{\n\t\tdisplayName: 'Search Term',\n\t\tname: 'searchTerm',\n\t\ttype: 'string',\n\t\trequired: true,\n\t\tdefault: '',\n\t\tdescription: 'What to look for?',\n\t},\n\t{\n\t\tdisplayName: 'Options',\n\t\tname: 'options',\n\t\ttype: 'collection',\n\t\tplaceholder: 'Add Option',\n\t\tdefault: {},\n\t\toptions: [\n\t\t\t{\n\t\t\t\tdisplayName: 'Case Insensitive Search',\n\t\t\t\tname: 'insensitive',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: false,\n\t\t\t\tdescription:\n\t\t\t\t\t'Whether the search ignores case sensitivity (true). Otherwise, it distinguishes between uppercase and lowercase characters.',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Activate Wildcard Search',\n\t\t\t\tname: 'wildcard',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: true,\n\t\t\t\tdescription:\n\t\t\t\t\t'Whether the search only results perfect matches (true). Otherwise, it finds a row even if the search value is part of a string (false).',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Simplify',\n\t\t\t\tname: 'simple',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: true,\n\t\t\t\tdescription:\n\t\t\t\t\t'Whether to return a simplified version of the response instead of the raw data',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Return Column Names',\n\t\t\t\tname: 'convert',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: true,\n\t\t\t\tdescription: 'Whether to return the column keys (false) or the column names (true)',\n\t\t\t},\n\t\t],\n\t},\n];\n\nconst displayOptions = {\n\tshow: {\n\t\tresource: ['row'],\n\t\toperation: ['search'],\n\t},\n};\n\nexport const description = updateDisplayOptions(displayOptions, properties);\n\nexport async function execute(\n\tthis: IExecuteFunctions,\n\tindex: number,\n): Promise<INodeExecutionData[]> {\n\tconst tableName = this.getNodeParameter('tableName', index) as string;\n\tconst searchColumn = this.getNodeParameter('searchColumn', index) as string;\n\tconst searchTerm = this.getNodeParameter('searchTerm', index) as string | number;\n\tlet searchTermString = String(searchTerm);\n\tconst options = this.getNodeParameter('options', index);\n\n\t// get collaborators\n\tconst collaborators = await getBaseCollaborators.call(this);\n\n\t// this is the base query. The WHERE has to be finalized...\n\tlet sqlQuery = `SELECT * FROM \\`${tableName}\\` WHERE \\`${searchColumn}\\``;\n\n\tif (options.insensitive) {\n\t\tsearchTermString = searchTermString.toLowerCase();\n\t\tsqlQuery = `SELECT * FROM \\`${tableName}\\` WHERE lower(\\`${searchColumn}\\`)`;\n\t}\n\n\tconst wildcard = options.wildcard ?? true;\n\n\tif (wildcard) sqlQuery = sqlQuery + ' LIKE \"%' + searchTermString + '%\"';\n\telse if (!wildcard) sqlQuery = sqlQuery + ' = \"' + searchTermString + '\"';\n\n\tconst sqlResult = (await seaTableApiRequest.call(\n\t\tthis,\n\t\t{},\n\t\t'POST',\n\t\t'/api-gateway/api/v2/dtables/{{dtable_uuid}}/sql',\n\t\t{\n\t\t\tsql: sqlQuery,\n\t\t\tconvert_keys: options.convert ?? true,\n\t\t},\n\t)) as IRowResponse;\n\tconst metadata = sqlResult.metadata as IDtableMetadataColumn[];\n\tconst rows = sqlResult.results;\n\n\t// hide columns like button\n\trows.map((row) => enrichColumns(row, metadata, collaborators));\n\n\t// remove columns starting with _;\n\tif (options.simple) {\n\t\trows.map((row) => simplify_new(row));\n\t}\n\n\treturn this.helpers.returnJsonArray(rows as IDataObject[]);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAMO;AAEP,8BAKO;AAGA,MAAM,aAAgC;AAAA,EAC5C;AAAA,IACC,aAAa;AAAA,IACb,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,MACZ,sBAAsB,CAAC,WAAW;AAAA,MAClC,mBAAmB;AAAA,IACpB;AAAA,IACA,UAAU;AAAA,IACV,SAAS;AAAA;AAAA,IAET,aACC;AAAA,EACF;AAAA,EACA;AAAA,IACC,aAAa;AAAA,IACb,MAAM;AAAA,IACN,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,IACT,aAAa;AAAA,EACd;AAAA,EACA;AAAA,IACC,aAAa;AAAA,IACb,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS,CAAC;AAAA,IACV,SAAS;AAAA,MACR;AAAA,QACC,aAAa;AAAA,QACb,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS;AAAA,QACT,aACC;AAAA,MACF;AAAA,MACA;AAAA,QACC,aAAa;AAAA,QACb,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS;AAAA,QACT,aACC;AAAA,MACF;AAAA,MACA;AAAA,QACC,aAAa;AAAA,QACb,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS;AAAA,QACT,aACC;AAAA,MACF;AAAA,MACA;AAAA,QACC,aAAa;AAAA,QACb,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS;AAAA,QACT,aAAa;AAAA,MACd;AAAA,IACD;AAAA,EACD;AACD;AAEA,MAAM,iBAAiB;AAAA,EACtB,MAAM;AAAA,IACL,UAAU,CAAC,KAAK;AAAA,IAChB,WAAW,CAAC,QAAQ;AAAA,EACrB;AACD;AAEO,MAAM,kBAAc,0CAAqB,gBAAgB,UAAU;AAE1E,eAAsB,QAErB,OACgC;AAChC,QAAM,YAAY,KAAK,iBAAiB,aAAa,KAAK;AAC1D,QAAM,eAAe,KAAK,iBAAiB,gBAAgB,KAAK;AAChE,QAAM,aAAa,KAAK,iBAAiB,cAAc,KAAK;AAC5D,MAAI,mBAAmB,OAAO,UAAU;AACxC,QAAM,UAAU,KAAK,iBAAiB,WAAW,KAAK;AAGtD,QAAM,gBAAgB,MAAM,6CAAqB,KAAK,IAAI;AAG1D,MAAI,WAAW,mBAAmB,SAAS,cAAc,YAAY;AAErE,MAAI,QAAQ,aAAa;AACxB,uBAAmB,iBAAiB,YAAY;AAChD,eAAW,mBAAmB,SAAS,oBAAoB,YAAY;AAAA,EACxE;AAEA,QAAM,WAAW,QAAQ,YAAY;AAErC,MAAI,SAAU,YAAW,WAAW,aAAa,mBAAmB;AAAA,WAC3D,CAAC,SAAU,YAAW,WAAW,SAAS,mBAAmB;AAEtE,QAAM,YAAa,MAAM,2CAAmB;AAAA,IAC3C;AAAA,IACA,CAAC;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,MACC,KAAK;AAAA,MACL,cAAc,QAAQ,WAAW;AAAA,IAClC;AAAA,EACD;AACA,QAAM,WAAW,UAAU;AAC3B,QAAM,OAAO,UAAU;AAGvB,OAAK,IAAI,CAAC,YAAQ,uCAAc,KAAK,UAAU,aAAa,CAAC;AAG7D,MAAI,QAAQ,QAAQ;AACnB,SAAK,IAAI,CAAC,YAAQ,sCAAa,GAAG,CAAC;AAAA,EACpC;AAEA,SAAO,KAAK,QAAQ,gBAAgB,IAAqB;AAC1D;","names":[]}
|
|
@@ -52,8 +52,8 @@ class SseTrigger {
|
|
|
52
52
|
triggerPanel: {
|
|
53
53
|
header: "",
|
|
54
54
|
executionsHelp: {
|
|
55
|
-
inactive: "<b>While building your workflow</b>, click the '
|
|
56
|
-
active: "<b>While building your workflow</b>, click the '
|
|
55
|
+
inactive: "<b>While building your workflow</b>, click the 'test step' button, then trigger an SSE event. This will trigger an execution, which will show up in this editor.<br /> <br /><b>Once you're happy with your workflow</b>, <a data-key='activate'>activate</a> it. Then every time a change is detected, the workflow will execute. These executions will show up in the <a data-key='executions'>executions list</a>, but not in the editor.",
|
|
56
|
+
active: "<b>While building your workflow</b>, click the 'test step' button, then trigger an SSE event. This will trigger an execution, which will show up in this editor.<br /> <br /><b>Your workflow will also execute automatically</b>, since it's activated. Every time a change is detected, this node will trigger an execution. These executions will show up in the <a data-key='executions'>executions list</a>, but not in the editor."
|
|
57
57
|
},
|
|
58
58
|
activationHint: "Once you\u2019ve finished building your workflow, <a data-key='activate'>activate</a> it to have it also listen continuously (you just won\u2019t see those executions here)."
|
|
59
59
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../nodes/SseTrigger/SseTrigger.node.ts"],"sourcesContent":["import EventSource from 'eventsource';\nimport type {\n\tIDataObject,\n\tITriggerFunctions,\n\tINodeType,\n\tINodeTypeDescription,\n\tITriggerResponse,\n} from 'n8n-workflow';\nimport { NodeConnectionTypes, jsonParse } from 'n8n-workflow';\n\nexport class SseTrigger implements INodeType {\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'SSE Trigger',\n\t\tname: 'sseTrigger',\n\t\ticon: 'fa:cloud-download-alt',\n\t\ticonColor: 'dark-blue',\n\t\tgroup: ['trigger'],\n\t\tversion: 1,\n\t\tdescription: 'Triggers the workflow when Server-Sent Events occur',\n\t\teventTriggerDescription: '',\n\t\tactivationMessage: 'You can now make calls to your SSE URL to trigger executions.',\n\t\tdefaults: {\n\t\t\tname: 'SSE Trigger',\n\t\t\tcolor: '#225577',\n\t\t},\n\t\ttriggerPanel: {\n\t\t\theader: '',\n\t\t\texecutionsHelp: {\n\t\t\t\tinactive:\n\t\t\t\t\t\"<b>While building your workflow</b>, click the '
|
|
1
|
+
{"version":3,"sources":["../../../nodes/SseTrigger/SseTrigger.node.ts"],"sourcesContent":["import EventSource from 'eventsource';\nimport type {\n\tIDataObject,\n\tITriggerFunctions,\n\tINodeType,\n\tINodeTypeDescription,\n\tITriggerResponse,\n} from 'n8n-workflow';\nimport { NodeConnectionTypes, jsonParse } from 'n8n-workflow';\n\nexport class SseTrigger implements INodeType {\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'SSE Trigger',\n\t\tname: 'sseTrigger',\n\t\ticon: 'fa:cloud-download-alt',\n\t\ticonColor: 'dark-blue',\n\t\tgroup: ['trigger'],\n\t\tversion: 1,\n\t\tdescription: 'Triggers the workflow when Server-Sent Events occur',\n\t\teventTriggerDescription: '',\n\t\tactivationMessage: 'You can now make calls to your SSE URL to trigger executions.',\n\t\tdefaults: {\n\t\t\tname: 'SSE Trigger',\n\t\t\tcolor: '#225577',\n\t\t},\n\t\ttriggerPanel: {\n\t\t\theader: '',\n\t\t\texecutionsHelp: {\n\t\t\t\tinactive:\n\t\t\t\t\t\"<b>While building your workflow</b>, click the 'test step' button, then trigger an SSE event. This will trigger an execution, which will show up in this editor.<br /> <br /><b>Once you're happy with your workflow</b>, <a data-key='activate'>activate</a> it. Then every time a change is detected, the workflow will execute. These executions will show up in the <a data-key='executions'>executions list</a>, but not in the editor.\",\n\t\t\t\tactive:\n\t\t\t\t\t\"<b>While building your workflow</b>, click the 'test step' button, then trigger an SSE event. This will trigger an execution, which will show up in this editor.<br /> <br /><b>Your workflow will also execute automatically</b>, since it's activated. Every time a change is detected, this node will trigger an execution. These executions will show up in the <a data-key='executions'>executions list</a>, but not in the editor.\",\n\t\t\t},\n\t\t\tactivationHint:\n\t\t\t\t\"Once you’ve finished building your workflow, <a data-key='activate'>activate</a> it to have it also listen continuously (you just won’t see those executions here).\",\n\t\t},\n\t\tinputs: [],\n\t\toutputs: [NodeConnectionTypes.Main],\n\t\tproperties: [\n\t\t\t{\n\t\t\t\tdisplayName: 'URL',\n\t\t\t\tname: 'url',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\tplaceholder: 'http://example.com',\n\t\t\t\tdescription: 'The URL to receive the SSE from',\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t],\n\t};\n\n\tasync trigger(this: ITriggerFunctions): Promise<ITriggerResponse> {\n\t\tconst url = this.getNodeParameter('url') as string;\n\n\t\tconst eventSource = new EventSource(url);\n\n\t\teventSource.onmessage = (event) => {\n\t\t\tconst eventData = jsonParse<IDataObject>(event.data as string, {\n\t\t\t\terrorMessage: 'Invalid JSON for event data',\n\t\t\t});\n\t\t\tthis.emit([this.helpers.returnJsonArray([eventData])]);\n\t\t};\n\n\t\tasync function closeFunction() {\n\t\t\teventSource.close();\n\t\t}\n\n\t\treturn {\n\t\t\tcloseFunction,\n\t\t};\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAAwB;AAQxB,0BAA+C;AAExC,MAAM,WAAgC;AAAA,EAAtC;AACN,uBAAoC;AAAA,MACnC,aAAa;AAAA,MACb,MAAM;AAAA,MACN,MAAM;AAAA,MACN,WAAW;AAAA,MACX,OAAO,CAAC,SAAS;AAAA,MACjB,SAAS;AAAA,MACT,aAAa;AAAA,MACb,yBAAyB;AAAA,MACzB,mBAAmB;AAAA,MACnB,UAAU;AAAA,QACT,MAAM;AAAA,QACN,OAAO;AAAA,MACR;AAAA,MACA,cAAc;AAAA,QACb,QAAQ;AAAA,QACR,gBAAgB;AAAA,UACf,UACC;AAAA,UACD,QACC;AAAA,QACF;AAAA,QACA,gBACC;AAAA,MACF;AAAA,MACA,QAAQ,CAAC;AAAA,MACT,SAAS,CAAC,wCAAoB,IAAI;AAAA,MAClC,YAAY;AAAA,QACX;AAAA,UACC,aAAa;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS;AAAA,UACT,aAAa;AAAA,UACb,aAAa;AAAA,UACb,UAAU;AAAA,QACX;AAAA,MACD;AAAA,IACD;AAAA;AAAA,EAEA,MAAM,UAA4D;AACjE,UAAM,MAAM,KAAK,iBAAiB,KAAK;AAEvC,UAAM,cAAc,IAAI,mBAAAA,QAAY,GAAG;AAEvC,gBAAY,YAAY,CAAC,UAAU;AAClC,YAAM,gBAAY,+BAAuB,MAAM,MAAgB;AAAA,QAC9D,cAAc;AAAA,MACf,CAAC;AACD,WAAK,KAAK,CAAC,KAAK,QAAQ,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC;AAAA,IACtD;AAEA,mBAAe,gBAAgB;AAC9B,kBAAY,MAAM;AAAA,IACnB;AAEA,WAAO;AAAA,MACN;AAAA,IACD;AAAA,EACD;AACD;","names":["EventSource"]}
|
|
@@ -176,18 +176,18 @@ function aggregateAndSplitData({
|
|
|
176
176
|
const [firstSplitKey, ...restSplitKeys] = splitKeys;
|
|
177
177
|
const groupedItems = /* @__PURE__ */ new Map();
|
|
178
178
|
for (const item of inputItems) {
|
|
179
|
-
let
|
|
180
|
-
if (
|
|
181
|
-
|
|
179
|
+
let splitValue = getValue(item, firstSplitKey);
|
|
180
|
+
if (splitValue && typeof splitValue === "object") {
|
|
181
|
+
splitValue = JSON.stringify(splitValue);
|
|
182
182
|
}
|
|
183
183
|
if (convertKeysToString) {
|
|
184
|
-
|
|
184
|
+
splitValue = String(splitValue);
|
|
185
185
|
}
|
|
186
|
-
if (options.skipEmptySplitFields && typeof
|
|
186
|
+
if (options.skipEmptySplitFields && typeof splitValue !== "number" && !splitValue) {
|
|
187
187
|
continue;
|
|
188
188
|
}
|
|
189
|
-
const group = groupedItems.get(
|
|
190
|
-
groupedItems.set(
|
|
189
|
+
const group = groupedItems.get(splitValue) ?? [];
|
|
190
|
+
groupedItems.set(splitValue, group.concat([item]));
|
|
191
191
|
}
|
|
192
192
|
const splits = new Map(
|
|
193
193
|
Array.from(groupedItems.entries()).map(([groupKey, items]) => [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../nodes/Transform/Summarize/utils.ts"],"sourcesContent":["import get from 'lodash/get';\nimport {\n\ttype GenericValue,\n\ttype IDataObject,\n\ttype IExecuteFunctions,\n\tNodeOperationError,\n} from 'n8n-workflow';\n\ntype AggregationType =\n\t| 'append'\n\t| 'average'\n\t| 'concatenate'\n\t| 'count'\n\t| 'countUnique'\n\t| 'max'\n\t| 'min'\n\t| 'sum';\n\nexport type Aggregation = {\n\taggregation: AggregationType;\n\tfield: string;\n\tincludeEmpty?: boolean;\n\tseparateBy?: string;\n\tcustomSeparator?: string;\n};\n\nexport type Aggregations = Aggregation[];\n\nconst AggregationDisplayNames = {\n\tappend: 'appended_',\n\taverage: 'average_',\n\tconcatenate: 'concatenated_',\n\tcount: 'count_',\n\tcountUnique: 'unique_count_',\n\tmax: 'max_',\n\tmin: 'min_',\n\tsum: 'sum_',\n};\n\nexport const NUMERICAL_AGGREGATIONS = ['average', 'sum'];\n\nexport type SummarizeOptions = {\n\tcontinueIfFieldNotFound: boolean;\n\tdisableDotNotation?: boolean;\n\toutputFormat?: 'separateItems' | 'singleItem';\n\tskipEmptySplitFields?: boolean;\n};\n\nexport type ValueGetterFn = (\n\titem: IDataObject,\n\tfield: string,\n) => IDataObject | IDataObject[] | GenericValue | GenericValue[];\n\nfunction isEmpty<T>(value: T) {\n\treturn value === undefined || value === null || value === '';\n}\n\nfunction normalizeFieldName(fieldName: string) {\n\treturn fieldName.replace(/[\\]\\[\"]/g, '').replace(/[ .]/g, '_');\n}\n\nexport const fieldValueGetter = (disableDotNotation?: boolean) => {\n\treturn (item: IDataObject, field: string) =>\n\t\tdisableDotNotation ? item[field] : get(item, field);\n};\n\nexport function checkIfFieldExists(\n\tthis: IExecuteFunctions,\n\titems: IDataObject[],\n\taggregations: Aggregations,\n\tgetValue: ValueGetterFn,\n) {\n\tfor (const aggregation of aggregations) {\n\t\tif (aggregation.field === '') {\n\t\t\tcontinue;\n\t\t}\n\t\tconst exist = items.some((item) => getValue(item, aggregation.field) !== undefined);\n\t\tif (!exist) {\n\t\t\tthrow new NodeOperationError(\n\t\t\t\tthis.getNode(),\n\t\t\t\t`The field '${aggregation.field}' does not exist in any items`,\n\t\t\t);\n\t\t}\n\t}\n}\n\nfunction aggregate(items: IDataObject[], entry: Aggregation, getValue: ValueGetterFn) {\n\tconst { aggregation, field } = entry;\n\tlet data = [...items];\n\n\tif (NUMERICAL_AGGREGATIONS.includes(aggregation)) {\n\t\tdata = data.filter(\n\t\t\t(item) => typeof getValue(item, field) === 'number' && !isEmpty(getValue(item, field)),\n\t\t);\n\t}\n\n\tswitch (aggregation) {\n\t\t//combine operations\n\t\tcase 'append':\n\t\t\tif (!entry.includeEmpty) {\n\t\t\t\tdata = data.filter((item) => !isEmpty(getValue(item, field)));\n\t\t\t}\n\t\t\treturn data.map((item) => getValue(item, field));\n\t\tcase 'concatenate':\n\t\t\tconst separateBy = entry.separateBy === 'other' ? entry.customSeparator : entry.separateBy;\n\t\t\tif (!entry.includeEmpty) {\n\t\t\t\tdata = data.filter((item) => !isEmpty(getValue(item, field)));\n\t\t\t}\n\t\t\treturn data\n\t\t\t\t.map((item) => {\n\t\t\t\t\tlet value = getValue(item, field);\n\t\t\t\t\tif (typeof value === 'object') {\n\t\t\t\t\t\tvalue = JSON.stringify(value);\n\t\t\t\t\t}\n\t\t\t\t\tif (typeof value === 'undefined') {\n\t\t\t\t\t\tvalue = 'undefined';\n\t\t\t\t\t}\n\n\t\t\t\t\treturn value;\n\t\t\t\t})\n\t\t\t\t.join(separateBy);\n\n\t\t//numerical operations\n\t\tcase 'average':\n\t\t\treturn (\n\t\t\t\tdata.reduce((acc, item) => {\n\t\t\t\t\treturn acc + (getValue(item, field) as number);\n\t\t\t\t}, 0) / data.length\n\t\t\t);\n\t\tcase 'sum':\n\t\t\treturn data.reduce((acc, item) => {\n\t\t\t\treturn acc + (getValue(item, field) as number);\n\t\t\t}, 0);\n\t\t//comparison operations\n\t\tcase 'min':\n\t\t\tlet min;\n\t\t\tfor (const item of data) {\n\t\t\t\tconst value = getValue(item, field);\n\t\t\t\tif (value !== undefined && value !== null && value !== '') {\n\t\t\t\t\tif (min === undefined || value < min) {\n\t\t\t\t\t\tmin = value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn min ?? null;\n\t\tcase 'max':\n\t\t\tlet max;\n\t\t\tfor (const item of data) {\n\t\t\t\tconst value = getValue(item, field);\n\t\t\t\tif (value !== undefined && value !== null && value !== '') {\n\t\t\t\t\tif (max === undefined || value > max) {\n\t\t\t\t\t\tmax = value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn max ?? null;\n\n\t\t//count operations\n\t\tcase 'countUnique':\n\t\t\tif (!entry.includeEmpty) {\n\t\t\t\treturn new Set(data.map((item) => getValue(item, field)).filter((item) => !isEmpty(item)))\n\t\t\t\t\t.size;\n\t\t\t}\n\t\t\treturn new Set(data.map((item) => getValue(item, field))).size;\n\n\t\tdefault:\n\t\t\t//count by default\n\t\t\tif (!entry.includeEmpty) {\n\t\t\t\treturn data.filter((item) => !isEmpty(getValue(item, field))).length;\n\t\t\t}\n\t\t\treturn data.length;\n\t}\n}\n\nfunction aggregateData(\n\tdata: IDataObject[],\n\tfieldsToSummarize: Aggregations,\n\toptions: SummarizeOptions,\n\tgetValue: ValueGetterFn,\n): { returnData: IDataObject; pairedItems?: number[] } {\n\tconst returnData = Object.fromEntries(\n\t\tfieldsToSummarize.map((aggregation) => {\n\t\t\tconst key = normalizeFieldName(\n\t\t\t\t`${AggregationDisplayNames[aggregation.aggregation]}${aggregation.field}`,\n\t\t\t);\n\t\t\tconst result = aggregate(data, aggregation, getValue);\n\t\t\treturn [key, result];\n\t\t}),\n\t);\n\n\tif (options.outputFormat === 'singleItem') {\n\t\treturn { returnData };\n\t}\n\n\treturn { returnData, pairedItems: data.map((item) => item._itemIndex as number) };\n}\n\ntype AggregationResult = { returnData: IDataObject; pairedItems?: number[] };\ntype NestedAggregationResult =\n\t| AggregationResult\n\t| { fieldName: string; splits: Map<unknown, NestedAggregationResult> };\n\n// Using Map to preserve types\n// With a plain JS object, keys are converted to string\nexport function aggregateAndSplitData({\n\tsplitKeys,\n\tinputItems,\n\tfieldsToSummarize,\n\toptions,\n\tgetValue,\n\tconvertKeysToString = false,\n}: {\n\tsplitKeys: string[] | undefined;\n\tinputItems: IDataObject[];\n\tfieldsToSummarize: Aggregations;\n\toptions: SummarizeOptions;\n\tgetValue: ValueGetterFn;\n\tconvertKeysToString?: boolean; // Legacy option for v1\n}): NestedAggregationResult {\n\tif (!splitKeys?.length) {\n\t\treturn aggregateData(inputItems, fieldsToSummarize, options, getValue);\n\t}\n\n\tconst [firstSplitKey, ...restSplitKeys] = splitKeys;\n\n\tconst groupedItems = new Map<unknown, IDataObject[]>();\n\tfor (const item of inputItems) {\n\t\tlet key = getValue(item, firstSplitKey);\n\n\t\tif (key && typeof key === 'object') {\n\t\t\tkey = JSON.stringify(key);\n\t\t}\n\n\t\tif (convertKeysToString) {\n\t\t\tkey = normalizeFieldName(String(key));\n\t\t}\n\n\t\tif (options.skipEmptySplitFields && typeof key !== 'number' && !key) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst group = groupedItems.get(key) ?? [];\n\t\tgroupedItems.set(key, group.concat([item]));\n\t}\n\n\tconst splits = new Map(\n\t\tArray.from(groupedItems.entries()).map(([groupKey, items]) => [\n\t\t\tgroupKey,\n\t\t\taggregateAndSplitData({\n\t\t\t\tsplitKeys: restSplitKeys,\n\t\t\t\tinputItems: items,\n\t\t\t\tfieldsToSummarize,\n\t\t\t\toptions,\n\t\t\t\tgetValue,\n\t\t\t}),\n\t\t]),\n\t);\n\n\treturn { fieldName: firstSplitKey, splits };\n}\n\nexport function flattenAggregationResultToObject(result: NestedAggregationResult): IDataObject {\n\tif ('splits' in result) {\n\t\treturn Object.fromEntries(\n\t\t\tArray.from(result.splits.entries()).map(([key, value]) => [\n\t\t\t\tkey,\n\t\t\t\tflattenAggregationResultToObject(value),\n\t\t\t]),\n\t\t);\n\t}\n\n\treturn result.returnData;\n}\n\nexport function flattenAggregationResultToArray(\n\tresult: NestedAggregationResult,\n): AggregationResult[] {\n\tif ('splits' in result) {\n\t\treturn Array.from(result.splits.entries()).flatMap(([value, innerResult]) =>\n\t\t\tflattenAggregationResultToArray(innerResult).map((v) => {\n\t\t\t\tv.returnData[normalizeFieldName(result.fieldName)] = value as IDataObject;\n\t\t\t\treturn v;\n\t\t\t}),\n\t\t);\n\t}\n\treturn [result];\n}\n"],"mappings":"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","names":["get"]}
|
|
1
|
+
{"version":3,"sources":["../../../../nodes/Transform/Summarize/utils.ts"],"sourcesContent":["import get from 'lodash/get';\nimport {\n\ttype GenericValue,\n\ttype IDataObject,\n\ttype IExecuteFunctions,\n\tNodeOperationError,\n} from 'n8n-workflow';\n\ntype AggregationType =\n\t| 'append'\n\t| 'average'\n\t| 'concatenate'\n\t| 'count'\n\t| 'countUnique'\n\t| 'max'\n\t| 'min'\n\t| 'sum';\n\nexport type Aggregation = {\n\taggregation: AggregationType;\n\tfield: string;\n\tincludeEmpty?: boolean;\n\tseparateBy?: string;\n\tcustomSeparator?: string;\n};\n\nexport type Aggregations = Aggregation[];\n\nconst AggregationDisplayNames = {\n\tappend: 'appended_',\n\taverage: 'average_',\n\tconcatenate: 'concatenated_',\n\tcount: 'count_',\n\tcountUnique: 'unique_count_',\n\tmax: 'max_',\n\tmin: 'min_',\n\tsum: 'sum_',\n};\n\nexport const NUMERICAL_AGGREGATIONS = ['average', 'sum'];\n\nexport type SummarizeOptions = {\n\tcontinueIfFieldNotFound: boolean;\n\tdisableDotNotation?: boolean;\n\toutputFormat?: 'separateItems' | 'singleItem';\n\tskipEmptySplitFields?: boolean;\n};\n\nexport type ValueGetterFn = (\n\titem: IDataObject,\n\tfield: string,\n) => IDataObject | IDataObject[] | GenericValue | GenericValue[];\n\nfunction isEmpty<T>(value: T) {\n\treturn value === undefined || value === null || value === '';\n}\n\nfunction normalizeFieldName(fieldName: string) {\n\treturn fieldName.replace(/[\\]\\[\"]/g, '').replace(/[ .]/g, '_');\n}\n\nexport const fieldValueGetter = (disableDotNotation?: boolean) => {\n\treturn (item: IDataObject, field: string) =>\n\t\tdisableDotNotation ? item[field] : get(item, field);\n};\n\nexport function checkIfFieldExists(\n\tthis: IExecuteFunctions,\n\titems: IDataObject[],\n\taggregations: Aggregations,\n\tgetValue: ValueGetterFn,\n) {\n\tfor (const aggregation of aggregations) {\n\t\tif (aggregation.field === '') {\n\t\t\tcontinue;\n\t\t}\n\t\tconst exist = items.some((item) => getValue(item, aggregation.field) !== undefined);\n\t\tif (!exist) {\n\t\t\tthrow new NodeOperationError(\n\t\t\t\tthis.getNode(),\n\t\t\t\t`The field '${aggregation.field}' does not exist in any items`,\n\t\t\t);\n\t\t}\n\t}\n}\n\nfunction aggregate(items: IDataObject[], entry: Aggregation, getValue: ValueGetterFn) {\n\tconst { aggregation, field } = entry;\n\tlet data = [...items];\n\n\tif (NUMERICAL_AGGREGATIONS.includes(aggregation)) {\n\t\tdata = data.filter(\n\t\t\t(item) => typeof getValue(item, field) === 'number' && !isEmpty(getValue(item, field)),\n\t\t);\n\t}\n\n\tswitch (aggregation) {\n\t\t//combine operations\n\t\tcase 'append':\n\t\t\tif (!entry.includeEmpty) {\n\t\t\t\tdata = data.filter((item) => !isEmpty(getValue(item, field)));\n\t\t\t}\n\t\t\treturn data.map((item) => getValue(item, field));\n\t\tcase 'concatenate':\n\t\t\tconst separateBy = entry.separateBy === 'other' ? entry.customSeparator : entry.separateBy;\n\t\t\tif (!entry.includeEmpty) {\n\t\t\t\tdata = data.filter((item) => !isEmpty(getValue(item, field)));\n\t\t\t}\n\t\t\treturn data\n\t\t\t\t.map((item) => {\n\t\t\t\t\tlet value = getValue(item, field);\n\t\t\t\t\tif (typeof value === 'object') {\n\t\t\t\t\t\tvalue = JSON.stringify(value);\n\t\t\t\t\t}\n\t\t\t\t\tif (typeof value === 'undefined') {\n\t\t\t\t\t\tvalue = 'undefined';\n\t\t\t\t\t}\n\n\t\t\t\t\treturn value;\n\t\t\t\t})\n\t\t\t\t.join(separateBy);\n\n\t\t//numerical operations\n\t\tcase 'average':\n\t\t\treturn (\n\t\t\t\tdata.reduce((acc, item) => {\n\t\t\t\t\treturn acc + (getValue(item, field) as number);\n\t\t\t\t}, 0) / data.length\n\t\t\t);\n\t\tcase 'sum':\n\t\t\treturn data.reduce((acc, item) => {\n\t\t\t\treturn acc + (getValue(item, field) as number);\n\t\t\t}, 0);\n\t\t//comparison operations\n\t\tcase 'min':\n\t\t\tlet min;\n\t\t\tfor (const item of data) {\n\t\t\t\tconst value = getValue(item, field);\n\t\t\t\tif (value !== undefined && value !== null && value !== '') {\n\t\t\t\t\tif (min === undefined || value < min) {\n\t\t\t\t\t\tmin = value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn min ?? null;\n\t\tcase 'max':\n\t\t\tlet max;\n\t\t\tfor (const item of data) {\n\t\t\t\tconst value = getValue(item, field);\n\t\t\t\tif (value !== undefined && value !== null && value !== '') {\n\t\t\t\t\tif (max === undefined || value > max) {\n\t\t\t\t\t\tmax = value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn max ?? null;\n\n\t\t//count operations\n\t\tcase 'countUnique':\n\t\t\tif (!entry.includeEmpty) {\n\t\t\t\treturn new Set(data.map((item) => getValue(item, field)).filter((item) => !isEmpty(item)))\n\t\t\t\t\t.size;\n\t\t\t}\n\t\t\treturn new Set(data.map((item) => getValue(item, field))).size;\n\n\t\tdefault:\n\t\t\t//count by default\n\t\t\tif (!entry.includeEmpty) {\n\t\t\t\treturn data.filter((item) => !isEmpty(getValue(item, field))).length;\n\t\t\t}\n\t\t\treturn data.length;\n\t}\n}\n\nfunction aggregateData(\n\tdata: IDataObject[],\n\tfieldsToSummarize: Aggregations,\n\toptions: SummarizeOptions,\n\tgetValue: ValueGetterFn,\n): { returnData: IDataObject; pairedItems?: number[] } {\n\tconst returnData = Object.fromEntries(\n\t\tfieldsToSummarize.map((aggregation) => {\n\t\t\tconst key = normalizeFieldName(\n\t\t\t\t`${AggregationDisplayNames[aggregation.aggregation]}${aggregation.field}`,\n\t\t\t);\n\t\t\tconst result = aggregate(data, aggregation, getValue);\n\t\t\treturn [key, result];\n\t\t}),\n\t);\n\n\tif (options.outputFormat === 'singleItem') {\n\t\treturn { returnData };\n\t}\n\n\treturn { returnData, pairedItems: data.map((item) => item._itemIndex as number) };\n}\n\ntype AggregationResult = { returnData: IDataObject; pairedItems?: number[] };\ntype NestedAggregationResult =\n\t| AggregationResult\n\t| { fieldName: string; splits: Map<unknown, NestedAggregationResult> };\n\n// Using Map to preserve types\n// With a plain JS object, keys are converted to string\nexport function aggregateAndSplitData({\n\tsplitKeys,\n\tinputItems,\n\tfieldsToSummarize,\n\toptions,\n\tgetValue,\n\tconvertKeysToString = false,\n}: {\n\tsplitKeys: string[] | undefined;\n\tinputItems: IDataObject[];\n\tfieldsToSummarize: Aggregations;\n\toptions: SummarizeOptions;\n\tgetValue: ValueGetterFn;\n\tconvertKeysToString?: boolean; // Legacy option for v1\n}): NestedAggregationResult {\n\tif (!splitKeys?.length) {\n\t\treturn aggregateData(inputItems, fieldsToSummarize, options, getValue);\n\t}\n\n\tconst [firstSplitKey, ...restSplitKeys] = splitKeys;\n\n\tconst groupedItems = new Map<unknown, IDataObject[]>();\n\tfor (const item of inputItems) {\n\t\tlet splitValue = getValue(item, firstSplitKey);\n\n\t\tif (splitValue && typeof splitValue === 'object') {\n\t\t\tsplitValue = JSON.stringify(splitValue);\n\t\t}\n\n\t\tif (convertKeysToString) {\n\t\t\tsplitValue = String(splitValue);\n\t\t}\n\n\t\tif (options.skipEmptySplitFields && typeof splitValue !== 'number' && !splitValue) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst group = groupedItems.get(splitValue) ?? [];\n\t\tgroupedItems.set(splitValue, group.concat([item]));\n\t}\n\n\tconst splits = new Map(\n\t\tArray.from(groupedItems.entries()).map(([groupKey, items]) => [\n\t\t\tgroupKey,\n\t\t\taggregateAndSplitData({\n\t\t\t\tsplitKeys: restSplitKeys,\n\t\t\t\tinputItems: items,\n\t\t\t\tfieldsToSummarize,\n\t\t\t\toptions,\n\t\t\t\tgetValue,\n\t\t\t}),\n\t\t]),\n\t);\n\n\treturn { fieldName: firstSplitKey, splits };\n}\n\nexport function flattenAggregationResultToObject(result: NestedAggregationResult): IDataObject {\n\tif ('splits' in result) {\n\t\treturn Object.fromEntries(\n\t\t\tArray.from(result.splits.entries()).map(([key, value]) => [\n\t\t\t\tkey,\n\t\t\t\tflattenAggregationResultToObject(value),\n\t\t\t]),\n\t\t);\n\t}\n\n\treturn result.returnData;\n}\n\nexport function flattenAggregationResultToArray(\n\tresult: NestedAggregationResult,\n): AggregationResult[] {\n\tif ('splits' in result) {\n\t\treturn Array.from(result.splits.entries()).flatMap(([value, innerResult]) =>\n\t\t\tflattenAggregationResultToArray(innerResult).map((v) => {\n\t\t\t\tv.returnData[normalizeFieldName(result.fieldName)] = value as IDataObject;\n\t\t\t\treturn v;\n\t\t\t}),\n\t\t);\n\t}\n\treturn [result];\n}\n"],"mappings":"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","names":["get"]}
|