Skip to content

Commit

Permalink
Merge pull request #3 from marioivangf/main
Browse files Browse the repository at this point in the history
esmodules, new vercel api and team support
  • Loading branch information
zehfernandes committed Feb 16, 2022
2 parents df921f5 + 3a15812 commit 8313b34
Show file tree
Hide file tree
Showing 5 changed files with 945 additions and 385 deletions.
3 changes: 2 additions & 1 deletion .env.sample
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
VERCEL_TOKEN =
VERCEL_TOKEN =
VERCEL_TEAM =
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

<img width="1530" alt="Screen Shot 2021-04-08 at 12 33 31" src="https://user-images.githubusercontent.com/1891339/114068653-88949800-9874-11eb-9083-99b9f5be615a.png">


## Instructions

1 - Install the dependecies.
Expand All @@ -15,12 +14,16 @@ npm i

```
VERCEL_TOKEN = ""
# Optionally if using a team account
VERCEL_TEAM = ""
```

3 - Run the script and wait until complete.

```
node index.js <VERCEL URL> <DESTINATION>
node index.js <VERCEL DEPLOYMENT URL or ID> <DESTINATION>
```

For example, `node index.js brazilianswhodesign-5ik51k4n7.vercel.app ../brazilianswhodesign`.
For example, `node index.js example-5ik51k4n7.vercel.app ../example`.

Or using the id directly, `node index.js dpl_6CR1uw9hBdpWgrMvPkncsTGRC18A ../example`.
177 changes: 96 additions & 81 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,96 +1,111 @@
const fs = require('fs');
const got = require('got');
const download = require('download');
const chalk = require('chalk');
const ora = require('ora');
require('dotenv').config()

let VERCEL_TOKEN = ""
let VERCEL_URL = ""
let DESTDIR = ""

const fileTree = [];
import "dotenv/config";
import * as fs from "fs";
import got from "got";
import chalk from "chalk";
import { oraPromise } from "ora";

const error = chalk.bold.red;
const success = chalk.keyword('green');

function main() {
VERCEL_TOKEN = process.env.VERCEL_TOKEN
VERCEL_URL = process.argv[2]
DESTDIR = process.argv[3] || VERCEL_URL

if (VERCEL_TOKEN === undefined || VERCEL_TOKEN === "") {
console.log(error("Please add your Vercel Token in .env file. \n\nLook at Readme for more informations"))
return
}

if (VERCEL_URL === undefined || VERCEL_URL === "") {
console.log(error("Please pass the Vercel URL:"))
console.log("\ne.g: node index.js brazilianswhodesign-5ik51k4n7.vercel.app")
return
}

getSourceCode()
const VERCEL_TOKEN = process.env.VERCEL_TOKEN;
const VERCEL_DEPLOYMENT = process.argv[2];
const DESTDIR = process.argv[3] || VERCEL_DEPLOYMENT;
const VERCEL_TEAM = process.env.VERCEL_TEAM;

try {
if (VERCEL_TOKEN === undefined) {
console.log(
error(
"Missing VERCEL_TOKEN in .env file. \n\nLook at README for more information"
)
);
} else if (VERCEL_DEPLOYMENT === undefined) {
console.log(error("Missing deployment URL or id"));
console.log(
"\ne.g: node index.js example-5ik51k4n7.vercel.app",
"\ne.g: node index.js dpl_6CR1uw9hBdpWgrMvPkncsTGRC18A"
);
} else {
await main();
}
} catch (err) {
console.log(error(err.stack || err));
}

main()

async function getSourceCode() {
const spinner = ora('Loading file tree').start();
await getFileTree("src/")

for (let i = 0; i < fileTree.length; i++) {
const f = fileTree[i];

if (f.type == "directory") {
await getFileTree(`${f.name}`)
}

if (f.type == "file") {
spinner.text = `Downloading ${f.name}`;
await downloadFile(f.link, f.dir)
}
}

spinner.stop()
console.log(success("Source code downloaded. ✨"))
async function main() {
const deploymentId = VERCEL_DEPLOYMENT.startsWith("dpl_")
? VERCEL_DEPLOYMENT
: await oraPromise(
getDeploymentId(VERCEL_DEPLOYMENT),
"Getting deployment id"
);
const srcFiles = await oraPromise(
getDeploymentSource(deploymentId),
"Loading source files tree"
);
// Download files one by one
if (!fs.existsSync(DESTDIR)) fs.mkdirSync(DESTDIR);
for (const file of srcFiles) {
let pathname = file.name.replace("src", DESTDIR);
if (fs.existsSync(pathname)) continue;
if (file.type === "directory") fs.mkdirSync(pathname);
if (file.type === "file") {
await oraPromise(
downloadFile(deploymentId, file.uid, pathname),
`Downloading ${pathname}`
);
}
}
}

async function downloadFile(url, dir) {
let filename = url.split("/").pop()
let path = `${DESTDIR}${dir}`

if (fs.existsSync(`${path}/${filename}}`)) {
return
}

await download(url, path, {
headers: {
'Authorization': `Bearer ${VERCEL_TOKEN}`,
}
})
async function getDeploymentSource(id) {
let path = `/v6/deployments/${id}/files`;
if (VERCEL_TEAM) path += `?teamId=${VERCEL_TEAM}`;
const files = await getJSONFromAPI(path);
// Get only src directory
const source = files.find((x) => x.name === "src");
// Flatten tree structure to list of files/dirs for easier downloading
return flattenTree(source);
}

async function getDeploymentId(domain) {
const deployment = await getJSONFromAPI(`/v13/deployments/${domain}`);
return deployment.id;
}

async function getFileTree(dir) {
const response = await got(`https://vercel.com/api/now/file-tree/${VERCEL_URL}?base=${dir}`, {
headers: {
'Authorization': `Bearer ${VERCEL_TOKEN}`,
}
async function downloadFile(deploymentId, fileId, destination) {
let path = `/v6/deployments/${deploymentId}/files/${fileId}`;
if (VERCEL_TEAM) path += `?teamId=${VERCEL_TEAM}`;
const response = await getFromAPI(path);
return new Promise((resolve, reject) => {
fs.writeFile(destination, response.body, function (err) {
if (err) reject(err);
resolve();
});
});
}

const result = JSON.parse(response.body)
const tree = result.map((f) => {
if (f.type == "directory") {
f.name = `${dir}${f.name}/`
}
function getFromAPI(path) {
return got(`https://api.vercel.com${path}`, {
headers: {
Authorization: `Bearer ${VERCEL_TOKEN}`,
},
retry: {
limit: 0,
},
});
}

if (f.type == "file") {
f.dir = `${dir.replace('src/', '/')}`
}

return f
})
function getJSONFromAPI(path) {
return getFromAPI(path).json();
}

fileTree.push(...tree)
function flattenTree({ name, children = [] }) {
let childrenNamed = children.map((child) => ({
...child,
name: `${name}/${child.name}`,
}));
return Array.prototype.concat.apply(
childrenNamed,
childrenNamed.map(flattenTree)
);
}
Loading

0 comments on commit 8313b34

Please sign in to comment.