{ "kind": "open-flow-workflow", "version": 1, "name": "Log ISS Position to BigQuery", "content": { "modelVersion": 14, "document": { "bindings": {}, "graph": { "nodes": { "n_e0079f781f81d7ef": { "name": "Every minute", "kind": "cron", "cronTimes": [ { "type": "cron", "expression": "* * * * *", "timezone": "UTC" } ] }, "n_e705d8a34ef5021f": { "inputs": {}, "name": "Prepare the current timestamp", "kind": "task", "task": { "inputs": [], "outputs": [ { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "url" }, { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "timestamp" } ], "name": "Prepare the current timestamp", "moduleId": "n_e914ccaf7d217a41", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_d356e72999ba7c96": { "inputs": { "url": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_e705d8a34ef5021f", "output": "url" } ] } }, "name": "Read the ISS position", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "url" } ], "outputs": [ { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "statusCode" }, { "jsonSchema": { "type": "object", "additionalProperties": { "type": "string" } }, "nullable": false, "handle": "headers" } ], "name": "Read the ISS position", "executor": { "method": "GET", "query": { "mode": "fields", "names": [] }, "headers": { "mode": "fields", "names": [] }, "bodyFormat": "none", "authentication": { "type": "none" }, "responseFormat": "json", "statusPolicy": "success", "kind": "http-request" } } }, "n_2f53d25bc2af6028": { "inputs": { "body": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_d356e72999ba7c96", "output": "body" } ] }, "timestamp": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_e705d8a34ef5021f", "output": "timestamp" } ] } }, "name": "Validate the position", "kind": "task", "task": { "inputs": [ { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "timestamp" } ], "outputs": [ { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": false, "handle": "position" }, { "jsonSchema": { "type": "array", "items": { "type": "object", "properties": { "insertId": { "type": "string", "minLength": 1, "description": "A unique insert ID used for best-effort deduplication." }, "json": { "type": "object", "properties": {}, "additionalProperties": true, "description": "The row JSON object to insert." } }, "required": [ "json" ], "additionalProperties": false, "description": "A BigQuery insertAll row." }, "minItems": 1, "description": "The rows to insert." }, "nullable": false, "handle": "rows" } ], "name": "Validate the position", "moduleId": "n_7c6e1715141248e3", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_909308b5fd0c81ee": { "inputs": { "projectId": { "kind": "value", "value": "YOUR_PROJECT_ID" }, "datasetId": { "kind": "value", "value": "YOUR_DATASET_ID" }, "tableId": { "kind": "value", "value": "YOUR_TABLE_ID" }, "rows": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_2f53d25bc2af6028", "output": "rows" } ] } }, "name": "Insert the position", "kind": "task", "task": { "inputs": [ { "description": "The Google Cloud project ID that owns the BigQuery resource.", "jsonSchema": { "type": "string", "minLength": 1, "description": "The Google Cloud project ID that owns the BigQuery resource." }, "nullable": false, "handle": "projectId" }, { "description": "The BigQuery dataset ID.", "jsonSchema": { "type": "string", "minLength": 1, "description": "The BigQuery dataset ID." }, "nullable": false, "handle": "datasetId" }, { "description": "The BigQuery table ID.", "jsonSchema": { "type": "string", "minLength": 1, "description": "The BigQuery table ID." }, "nullable": false, "handle": "tableId" }, { "description": "The rows to insert.", "jsonSchema": { "type": "array", "items": { "type": "object", "properties": { "insertId": { "type": "string", "minLength": 1, "description": "A unique insert ID used for best-effort deduplication." }, "json": { "type": "object", "properties": {}, "additionalProperties": true, "description": "The row JSON object to insert." } }, "required": [ "json" ], "additionalProperties": false, "description": "A BigQuery insertAll row." }, "minItems": 1, "description": "The rows to insert." }, "nullable": false, "handle": "rows" }, { "description": "Whether to insert valid rows while skipping invalid rows.", "jsonSchema": { "type": "boolean", "description": "Whether to insert valid rows while skipping invalid rows." }, "nullable": true, "handle": "skipInvalidRows", "value": null }, { "description": "Whether to ignore values that do not match the table schema.", "jsonSchema": { "type": "boolean", "description": "Whether to ignore values that do not match the table schema." }, "nullable": true, "handle": "ignoreUnknownValues", "value": null }, { "description": "The template table suffix for creating a generated table.", "jsonSchema": { "type": "string", "minLength": 1, "description": "The template table suffix for creating a generated table." }, "nullable": true, "handle": "templateSuffix", "value": null } ], "outputs": [ { "description": "The row insert errors returned by BigQuery.", "jsonSchema": { "type": "array", "items": { "type": "object", "properties": { "index": { "type": [ "integer", "null" ], "description": "The zero-based row index that failed." }, "errors": { "type": "array", "items": { "type": "object", "properties": {}, "additionalProperties": true, "description": "The raw BigQuery object returned by the API." }, "minItems": 0, "description": "The BigQuery error objects for the row." }, "raw": { "type": "object", "properties": {}, "additionalProperties": true, "description": "The raw BigQuery object returned by the API." } }, "required": [ "index", "errors", "raw" ], "additionalProperties": false, "description": "A normalized BigQuery insertAll row error." }, "minItems": 0, "description": "The row insert errors returned by BigQuery." }, "nullable": false, "handle": "insertErrors" }, { "description": "The raw BigQuery object returned by the API.", "jsonSchema": { "type": "object", "properties": {}, "additionalProperties": true, "description": "The raw BigQuery object returned by the API." }, "nullable": false, "handle": "raw" } ], "name": "Insert the position", "executor": { "kind": "connector", "action": "google_bigquery.insert_all" } } }, "n_45eb03f7c17ccbc8": { "inputs": { "insertErrors": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_909308b5fd0c81ee", "output": "insertErrors" } ] } }, "name": "Confirm the insert", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "array", "items": { "type": "object", "properties": { "index": { "type": [ "integer", "null" ], "description": "The zero-based row index that failed." }, "errors": { "type": "array", "items": { "type": "object", "properties": {}, "additionalProperties": true, "description": "The raw BigQuery object returned by the API." }, "minItems": 0, "description": "The BigQuery error objects for the row." }, "raw": { "type": "object", "properties": {}, "additionalProperties": true, "description": "The raw BigQuery object returned by the API." } }, "required": [ "index", "errors", "raw" ], "additionalProperties": false, "description": "A normalized BigQuery insertAll row error." }, "minItems": 0, "description": "The row insert errors returned by BigQuery." }, "nullable": false, "handle": "insertErrors" } ], "outputs": [ { "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "inserted" } ], "name": "Confirm the insert", "moduleId": "n_b11723b970fe44d2", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_3c44eb304a9542fe": { "name": "Inserted position", "kind": "outputs", "outputDefs": [ { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": false, "handle": "position" }, { "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "inserted" } ], "outputMappings": { "position": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_2f53d25bc2af6028", "output": "position" } ] }, "inserted": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_45eb03f7c17ccbc8", "output": "inserted" } ] } } } }, "edges": [ { "source": "n_e0079f781f81d7ef", "target": "n_e705d8a34ef5021f" }, { "source": "n_e705d8a34ef5021f", "target": "n_d356e72999ba7c96" }, { "source": "n_d356e72999ba7c96", "target": "n_2f53d25bc2af6028" }, { "source": "n_2f53d25bc2af6028", "target": "n_909308b5fd0c81ee" }, { "source": "n_909308b5fd0c81ee", "target": "n_45eb03f7c17ccbc8" }, { "source": "n_45eb03f7c17ccbc8", "target": "n_3c44eb304a9542fe" } ] } }, "modules": { "n_e914ccaf7d217a41": { "name": "Prepare the current timestamp", "imports": [], "source": "export default function query() {const timestamp=Math.floor(Date.now()/1000);return {timestamp,url:'https://api.wheretheiss.at/v1/satellites/25544/positions?timestamps='+timestamp};}\n" }, "n_7c6e1715141248e3": { "name": "Validate the position", "imports": [], "source": "export default function row({body,timestamp}) {\n if(!Array.isArray(body)||body.length!==1)throw Error('Expected one ISS position');const p=body[0];\n if(!p||p.id!==25544||typeof p.name!=='string'||!p.name||!Number.isFinite(p.latitude)||p.latitude < -90||p.latitude>90||!Number.isFinite(p.longitude)||p.longitude < -180||p.longitude>180||p.timestamp!==timestamp)throw Error('ISS position does not match the request');\n const position={name:p.name,latitude:p.latitude,longitude:p.longitude,timestamp:p.timestamp};return {position,rows:[{json:position}]};\n}\n" }, "n_b11723b970fe44d2": { "name": "Confirm the insert", "imports": [], "source": "export default function confirm({insertErrors}) {if(!Array.isArray(insertErrors)||insertErrors.length)throw Error('BigQuery did not accept the position');return {inserted:true};}\n" } } }, "presentation": { "designer": { "version": 1, "flow": { "direction": "vertical" } } } }