{ "kind": "open-flow-workflow", "version": 1, "name": "Import CSV Users to Snowflake", "content": { "modelVersion": 14, "document": { "bindings": {}, "graph": { "nodes": { "n_5af4f6841e886209": { "name": "Import the CSV", "kind": "start", "inputDefs": [] }, "n_50dbbcc7384492e9": { "inputs": { "url": { "kind": "value", "value": "https://n8niostorageaccount.blob.core.windows.net/n8nio-strapi-blobs-prod/assets/example_c0b48ce677.csv?updated_at=2023-05-30T10:36:21.820Z" } }, "name": "Download the CSV", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "url" } ], "outputs": [ { "jsonSchema": { "type": "string" }, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "statusCode" }, { "jsonSchema": { "type": "object", "additionalProperties": { "type": "string" } }, "nullable": false, "handle": "headers" } ], "name": "Download the CSV", "executor": { "method": "GET", "query": { "mode": "fields", "names": [] }, "headers": { "mode": "fields", "names": [] }, "bodyFormat": "none", "authentication": { "type": "none" }, "responseFormat": "text", "statusPolicy": "success", "kind": "http-request" } } }, "n_71f26aa29f0b6049": { "inputs": { "text": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_50dbbcc7384492e9", "output": "body" } ] } }, "name": "Read user records", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": true, "handle": "text" } ], "outputs": [ { "jsonSchema": { "type": "array", "items": { "type": "object", "additionalProperties": true } }, "nullable": false, "handle": "rows" } ], "name": "Read user records", "moduleId": "n_9351da9939fedb94", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_ba7c2746d3610f7c": { "inputs": { "rows": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_71f26aa29f0b6049", "output": "rows" } ] }, "previous": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_ba7c2746d3610f7c", "output": "state" } ] }, "account": { "kind": "value", "value": "YOUR_ACCOUNT" }, "warehouse": { "kind": "value", "value": "YOUR_WAREHOUSE" }, "database": { "kind": "value", "value": "YOUR_DATABASE" }, "schema": { "kind": "value", "value": "YOUR_SCHEMA" }, "confirmed": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_0ece22b4183ccc21", "output": "confirmed" } ] } }, "name": "Prepare the next insert", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "array", "items": { "type": "object", "additionalProperties": true } }, "nullable": false, "handle": "rows" }, { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": true, "handle": "previous" }, { "jsonSchema": { "type": "boolean" }, "nullable": true, "handle": "confirmed" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "account" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "warehouse" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "database" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "schema" } ], "outputs": [ { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": false, "handle": "state" }, { "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "more" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "url" }, { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": false, "handle": "body" }, { "jsonSchema": { "type": "integer", "minimum": 0 }, "nullable": false, "handle": "count" } ], "name": "Prepare the next insert", "moduleId": "n_082947b6b7aab94d", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_f1b7cc078b25b32c": { "inputs": {}, "name": "Another user?", "kind": "condition", "matchMode": "first", "cases": [ { "output": "yes", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_ba7c2746d3610f7c", "output": "more" } }, "operator": "isTrue" } ] } ] } ] }, "n_817e2b781a24409a": { "inputs": { "url": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_ba7c2746d3610f7c", "output": "url" } ] }, "body": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_ba7c2746d3610f7c", "output": "body" } ] }, "auth.token": { "kind": "unset" } }, "name": "Insert the user", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "url" }, { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "auth.token" } ], "outputs": [ { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "statusCode" }, { "jsonSchema": { "type": "object", "additionalProperties": { "type": "string" } }, "nullable": false, "handle": "headers" } ], "name": "Insert the user", "executor": { "method": "POST", "query": { "mode": "fields", "names": [] }, "headers": { "mode": "fields", "names": [] }, "bodyFormat": "json", "authentication": { "type": "bearer" }, "responseFormat": "json", "statusPolicy": "success", "kind": "http-request" } } }, "n_cca062776dd83704": { "inputs": { "body": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_817e2b781a24409a", "output": "body" } ] }, "statusCode": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_817e2b781a24409a", "output": "statusCode" } ] }, "url": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_ba7c2746d3610f7c", "output": "url" } ] }, "previous": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_cca062776dd83704", "output": "state" } ] } }, "name": "Check the statement", "kind": "task", "task": { "inputs": [ { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "statusCode" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "url" }, { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": true, "handle": "previous" } ], "outputs": [ { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": false, "handle": "state" }, { "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "pending" }, { "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "confirmed" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "pollUrl" } ], "name": "Check the statement", "moduleId": "n_c12a0c306e2b05b6", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_39ff5ec2648f778c": { "inputs": {}, "name": "Statement running?", "kind": "condition", "matchMode": "first", "cases": [ { "output": "yes", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_cca062776dd83704", "output": "pending" } }, "operator": "isTrue" } ] } ] } ] }, "n_8b01ea6720f423e6": { "inputs": {}, "name": "Wait before checking", "kind": "wait", "inputDefinitions": [], "prompt": "Wait before checking", "autoContinue": { "kind": "after", "durationMs": 5000 } }, "n_bc216edf8b4d0fa9": { "inputs": { "url": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_cca062776dd83704", "output": "pollUrl" } ] }, "auth.token": { "kind": "unset" } }, "name": "Check statement status", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "url" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "auth.token" } ], "outputs": [ { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "statusCode" }, { "jsonSchema": { "type": "object", "additionalProperties": { "type": "string" } }, "nullable": false, "handle": "headers" } ], "name": "Check statement status", "executor": { "method": "GET", "query": { "mode": "fields", "names": [] }, "headers": { "mode": "fields", "names": [] }, "bodyFormat": "none", "authentication": { "type": "bearer" }, "responseFormat": "json", "statusPolicy": "success", "kind": "http-request" } } }, "n_c73a562788547d88": { "inputs": { "body": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_bc216edf8b4d0fa9", "output": "body" } ] }, "statusCode": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_bc216edf8b4d0fa9", "output": "statusCode" } ] }, "url": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_ba7c2746d3610f7c", "output": "url" } ] }, "previous": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_c73a562788547d88", "output": "state" } ] } }, "name": "Check polling result", "kind": "task", "task": { "inputs": [ { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "statusCode" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "url" }, { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": true, "handle": "previous" } ], "outputs": [ { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": false, "handle": "state" }, { "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "pending" }, { "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "confirmed" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "pollUrl" } ], "name": "Check polling result", "moduleId": "n_dae738bd1871ceb3", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_8f2aa304af32c9cf": { "inputs": {}, "name": "Still running?", "kind": "condition", "matchMode": "first", "cases": [ { "output": "yes", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_c73a562788547d88", "output": "pending" } }, "operator": "isTrue" } ] } ] } ] }, "n_0ece22b4183ccc21": { "inputs": {}, "name": "Confirm the insert", "kind": "task", "task": { "inputs": [], "outputs": [ { "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "confirmed" } ], "name": "Confirm the insert", "moduleId": "n_2fee37d5ff8b7362", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_e6a5267a67ac8187": { "name": "Return imported count", "kind": "outputs", "outputDefs": [ { "jsonSchema": { "type": "integer", "minimum": 0 }, "nullable": false, "handle": "count" } ], "outputMappings": { "count": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_ba7c2746d3610f7c", "output": "count" } ] } } } }, "edges": [ { "source": "n_5af4f6841e886209", "target": "n_50dbbcc7384492e9" }, { "source": "n_50dbbcc7384492e9", "target": "n_71f26aa29f0b6049" }, { "source": "n_71f26aa29f0b6049", "target": "n_ba7c2746d3610f7c" }, { "source": "n_ba7c2746d3610f7c", "target": "n_f1b7cc078b25b32c" }, { "source": "n_f1b7cc078b25b32c", "target": "n_817e2b781a24409a", "sourceHandle": "yes" }, { "source": "n_f1b7cc078b25b32c", "target": "n_e6a5267a67ac8187", "sourceHandle": "otherwise" }, { "source": "n_817e2b781a24409a", "target": "n_cca062776dd83704" }, { "source": "n_cca062776dd83704", "target": "n_39ff5ec2648f778c" }, { "source": "n_39ff5ec2648f778c", "target": "n_8b01ea6720f423e6", "sourceHandle": "yes" }, { "source": "n_8b01ea6720f423e6", "target": "n_bc216edf8b4d0fa9", "sourceHandle": "continue" }, { "source": "n_bc216edf8b4d0fa9", "target": "n_c73a562788547d88" }, { "source": "n_c73a562788547d88", "target": "n_8f2aa304af32c9cf" }, { "source": "n_8f2aa304af32c9cf", "target": "n_8b01ea6720f423e6", "sourceHandle": "yes" }, { "source": "n_8f2aa304af32c9cf", "target": "n_0ece22b4183ccc21", "sourceHandle": "otherwise" }, { "source": "n_39ff5ec2648f778c", "target": "n_0ece22b4183ccc21", "sourceHandle": "otherwise" }, { "source": "n_0ece22b4183ccc21", "target": "n_ba7c2746d3610f7c" } ] } }, "modules": { "n_9351da9939fedb94": { "name": "Read user records", "imports": [], "source": "export default function parse({text}){if(typeof text!=='string')throw Error('Invalid CSV');text=text.replace(/^\\uFEFF/,'');let rows=[],row=[],field='',quoted=false;for(let i=0;ix!==''))rows.push(row);row=[];field=''}else field+=c}if(quoted)throw Error('Unclosed CSV quote');if(field||row.length){row.push(field);rows.push(row)}const header=rows.shift();if(!header)throw Error('Missing CSV header');const cols=['id','first_name','last_name'].map(k=>{const i=header.indexOf(k);if(i<0||header.lastIndexOf(k)!==i)throw Error('Missing or duplicate '+k);return i});return{rows:rows.map(r=>{const [id,first,last]=cols.map(i=>r[i]);if(!/^\\d+$/.test(id??'')||typeof first!=='string'||typeof last!=='string'||!first||!last)throw Error('Invalid CSV row');return{id,first_name:first,last_name:last}})};}\n" }, "n_082947b6b7aab94d": { "name": "Prepare the next insert", "imports": [], "source": "export default function next({rows,previous,confirmed,account,warehouse,database,schema}){const i=previous?.index??0,index=i+(confirmed===true?1:0);if(!/^[A-Za-z0-9_-]+(?:\\.[A-Za-z0-9_-]+)*$/.test(account)||[warehouse,database,schema].some(x=>typeof x!=='string'||!x||x.startsWith('YOUR_')))throw Error('Configure Snowflake account and context');if(!Array.isArray(rows)||index>rows.length)throw Error('Invalid import state');const url='https://'+account+'.snowflakecomputing.com/api/v2/statements';if(index===rows.length)return{state:{index},more:false,url,body:{},count:index};const r=rows[index];return{state:{index},more:true,url,count:index,body:{statement:'INSERT INTO \"users\" (\"id\", \"first_name\", \"last_name\") VALUES (?, ?, ?)',warehouse,database,schema,bindings:{'1':{type:'FIXED',value:r.id},'2':{type:'TEXT',value:r.first_name},'3':{type:'TEXT',value:r.last_name}}}};}\n" }, "n_c12a0c306e2b05b6": { "name": "Check the statement", "imports": [], "source": "export default function status({body,statusCode,url,previous}){const attempts=(previous?.attempts??0)+1;if(!body||typeof body!=='object')throw Error('Invalid Snowflake response');if(statusCode===200){if(body.code!=='090001')throw Error('Snowflake statement did not succeed');return{state:{attempts:0},pending:false,confirmed:true,pollUrl:url};}if(statusCode!==202||typeof body.statementHandle!=='string'||!/^[A-Za-z0-9-]+$/.test(body.statementHandle)||attempts>60)throw Error('Snowflake statement not confirmed');return{state:{attempts},pending:true,confirmed:false,pollUrl:url+'/'+body.statementHandle};}\n" }, "n_dae738bd1871ceb3": { "name": "Check polling result", "imports": [], "source": "export default function status({body,statusCode,url,previous}){const attempts=(previous?.attempts??0)+1;if(!body||typeof body!=='object')throw Error('Invalid Snowflake response');if(statusCode===200){if(body.code!=='090001')throw Error('Snowflake statement did not succeed');return{state:{attempts:0},pending:false,confirmed:true,pollUrl:url};}if(statusCode!==202||typeof body.statementHandle!=='string'||!/^[A-Za-z0-9-]+$/.test(body.statementHandle)||attempts>60)throw Error('Snowflake statement not confirmed');return{state:{attempts},pending:true,confirmed:false,pollUrl:url+'/'+body.statementHandle};}\n" }, "n_2fee37d5ff8b7362": { "name": "Confirm the insert", "imports": [], "source": "export default function(){return {confirmed:true}}" } } }, "presentation": { "designer": { "version": 1, "flow": { "direction": "vertical" } } } }