From 5b583162ff6d78576b94dcb99cfeb3cc6d1d2d9d Mon Sep 17 00:00:00 2001 From: Max Wofford Date: Wed, 29 Jul 2020 21:34:45 -0400 Subject: [PATCH] Initial deno implementation of api/new route --- .gitignore | 3 +- api/new.js | 26 ---------------- api/new.ts | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++ vercel.json | 6 ++++ 4 files changed, 96 insertions(+), 27 deletions(-) delete mode 100644 api/new.js create mode 100644 api/new.ts create mode 100644 vercel.json diff --git a/.gitignore b/.gitignore index 2eea525..d558dbc 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -.env \ No newline at end of file +.env +.vercel \ No newline at end of file diff --git a/api/new.js b/api/new.js deleted file mode 100644 index 67e2823..0000000 --- a/api/new.js +++ /dev/null @@ -1,26 +0,0 @@ -// https://api.vercel.com/v2/now/files - -// https://api.vercel/v12/now/files - -// Vercel protects against env tokens starting with `VERCEL_`, so we're calling -// it the ZEIT_TOKEN -const zeitToken = process.env.ZEIT_TOKEN - -export default (req, res) => { - if (req.method == 'OPTIONS') { - return res.status(204).json({ status: "YIPPE YAY. YOU HAVE CLEARANCE TO PROCEED." }) - } - if (req.method == 'GET') { - return res.status(405).json({ error: '*GET outta here!* (Method not allowed, use POST)' }) - } - if (req.method == 'PUT') { - return res.status(405).json({ error: '*PUT that request away!* (Method not allowed, use POST)' }) - } - if (req.method !== 'POST') { - return res.status(405).json({ error: 'Method not allowed, use POST' }) - } - - res.send(req.body) - - // res.json({ ping: 'pong' }) -} \ No newline at end of file diff --git a/api/new.ts b/api/new.ts new file mode 100644 index 0000000..10d8846 --- /dev/null +++ b/api/new.ts @@ -0,0 +1,88 @@ +import { ServerRequest } from 'https://deno.land/std@0.61.0/http/server.ts' +import { Hash } from "https://deno.land/x/checksum@1.4.0/mod.ts" +import { urlParse } from 'https://deno.land/x/url_parse/mod.ts'; + +// Vercel protects against env tokens starting with `VERCEL_`, so we're calling +// it the ZEIT_TOKEN + +const uploadFile = async (url: string) => { + const req = await fetch(url) + const data = new Uint8Array(await req.arrayBuffer()) + const sha = new Hash('sha1').digest(data).hex() + const size = data.byteLength + const { pathname } = urlParse(url) + const filename = pathname.substr(pathname.lastIndexOf('/') + 1) + + const uploadedFile = await fetch('https://api.vercel.com/v2/now/files', { + method: 'POST', + headers: { + 'Content-Length': size.toString(), + 'x-now-digest': sha, + 'Authorization': `Bearer ${Deno.env.get('ZEIT_TOKEN')}` + }, + body: data.buffer, + }) + + return { + sha, + size, + file: 'public/' + filename, + path: filename + } +} + +const deploy = async (files: {sha: string, file: string, path: string, size: number}[]) => { + const req = await fetch('https://api.vercel.com/v12/now/deployments', { + method: 'POST', + headers: { + 'Authorization': `Bearer ${Deno.env.get('ZEIT_TOKEN')}`, + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + name: 'cloud', + files: files.map(f => ({ + sha: f.sha, + file: f.file, + size: f.size + })), + projectSettings: { + framework: null + } + }) + }) + const json = await req.json() + const baseURL = json.url + const fileURLs = files.map(f => baseURL + '/' + f.path) + + return { status: req.status, fileURLs } +} + +export default async (req: ServerRequest) => { + // req.respond({ body: `Hello, from Deno!` }) + if (req.method == 'OPTIONS') { + return req.respond({status: 204, body: JSON.stringify({ status: "YIPPE YAY. YOU HAVE CLEARANCE TO PROCEED." })}) + } + if (req.method == 'GET') { + return req.respond({status: 405, body: JSON.stringify({ error: '*GET outta here!* (Method not allowed, use POST)' })}) + } + if (req.method == 'PUT') { + return req.respond({status: 405, body: JSON.stringify({ error: '*PUT that request away!* (Method not allowed, use POST)' })}) + } + if (req.method != 'POST') { + return req.respond({status: 405, body: JSON.stringify({ error: 'Method not allowed, use POST' })}) + } + + const decoder = new TextDecoder() + const buf = await Deno.readAll(req.body) + const fileURLs = JSON.parse(decoder.decode(buf)) + if (!Array.isArray(fileURLs) || fileURLs.length < 1) { + return req.respond({status: 422, body: JSON.stringify({ error: 'Empty file array' })}) + } + const uploadedFiles = await Promise.all(fileURLs.map(uploadFile)) + const result = await deploy(uploadedFiles) + + req.respond({ + status: result.status, + body: JSON.stringify(result.fileURLs) + }) +} \ No newline at end of file diff --git a/vercel.json b/vercel.json new file mode 100644 index 0000000..6cfe11e --- /dev/null +++ b/vercel.json @@ -0,0 +1,6 @@ +{ + "version": 2, + "functions": { + "api/**/*.{j,t}s": { "runtime": "vercel-deno@0.4.4" } + } +} \ No newline at end of file