{
  "name": "Yoink - one public file to URL",
  "nodes": [
    {
      "id": "1289b190-9379-492c-8d95-03aaf2e10393",
      "name": "Run manually",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        0,
        300
      ],
      "parameters": {}
    },
    {
      "id": "d88fc53c-bdaa-4d89-b6e5-0f6d24ac79f5",
      "name": "Create demo file",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        220,
        300
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const bytes = Buffer.from('Yoink public n8n sample\\n', 'utf8');\nconst filename = 'n8n-demo.txt';\nconst contentType = 'text/plain';\nconst data = await this.helpers.prepareBinaryData(bytes, filename, contentType);\n\nreturn [{\n    json: { filename, contentType, size: bytes.byteLength },\n    binary: { data },\n}];"
      }
    },
    {
      "id": "ebb9ff8d-1922-43e9-b154-e39933073709",
      "name": "Presign upload",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        440,
        300
      ],
      "parameters": {
        "method": "POST",
        "url": "https://yoink.zip/api/v1/presign",
        "authentication": "none",
        "sendBody": true,
        "contentType": "json",
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ filename: $json.filename, contentType: $json.contentType, size: $json.size }) }}",
        "options": {
          "timeout": 60000,
          "redirect": {
            "redirect": {
              "followRedirects": false
            }
          },
          "response": {
            "response": {
              "responseFormat": "json",
              "neverError": false
            }
          }
        }
      }
    },
    {
      "id": "a7c421d3-3874-4cf2-9673-f5f68405efd9",
      "name": "Restore file",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        660,
        300
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const signed = $input.first().json;\nconst source = $('Create demo file').first();\n\nif (typeof signed.uploadUrl !== 'string' || !signed.uploadUrl.startsWith('https://') ||\n    typeof signed.publicUrl !== 'string' || !signed.publicUrl.startsWith('https://files.yoink.zip/') ||\n    typeof signed.contentType !== 'string' || !signed.contentType || !source.binary?.data) {\n    throw new Error('Presign response or source binary is missing required fields');\n}\n\nreturn [{ json: signed, binary: source.binary }];"
      }
    },
    {
      "id": "e24eb818-cfcd-49a4-b3ae-cab7014e3190",
      "name": "Upload file",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        880,
        300
      ],
      "parameters": {
        "method": "PUT",
        "url": "={{ $json.uploadUrl }}",
        "authentication": "none",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "={{ $json.contentType }}"
            }
          ]
        },
        "sendBody": true,
        "contentType": "binaryData",
        "inputDataFieldName": "data",
        "options": {
          "timeout": 60000,
          "redirect": {
            "redirect": {
              "followRedirects": false
            }
          },
          "response": {
            "response": {
              "responseFormat": "text",
              "fullResponse": true,
              "neverError": false
            }
          }
        }
      }
    },
    {
      "id": "92e1df82-bbbd-46a8-a5c0-4ef527f1ca63",
      "name": "Return public URL",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1100,
        300
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const status = $input.first().json.statusCode;\n\nif (typeof status !== 'number' || status < 200 || status >= 300) {\n    throw new Error(`Upload did not succeed (HTTP ${status})`);\n}\n\nreturn [{ json: { publicUrl: $('Presign upload').first().json.publicUrl } }];"
      }
    }
  ],
  "connections": {
    "Run manually": {
      "main": [
        [
          {
            "node": "Create demo file",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create demo file": {
      "main": [
        [
          {
            "node": "Presign upload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Presign upload": {
      "main": [
        [
          {
            "node": "Restore file",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Restore file": {
      "main": [
        [
          {
            "node": "Upload file",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload file": {
      "main": [
        [
          {
            "node": "Return public URL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {}
}
