-
-
Notifications
You must be signed in to change notification settings - Fork 22
/
index.js
118 lines (107 loc) · 3.23 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
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 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));
}
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"
);
if (!fs.existsSync(DESTDIR)) fs.mkdirSync(DESTDIR);
Promise.allSettled(
srcFiles
.map((file) => {
let pathname = file.name.replace("src", DESTDIR);
if (fs.existsSync(pathname)) return null;
if (file.type === "directory") fs.mkdirSync(pathname);
if (file.type === "file") {
return oraPromise(
downloadFile(deploymentId, file.uid, pathname),
`Downloading ${pathname}`
);
}
})
.filter(Boolean)
);
}
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 downloadFile(deploymentId, fileId, destination) {
let path = `/v7/deployments/${deploymentId}/files/${fileId}`;
if (VERCEL_TEAM) path += `?teamId=${VERCEL_TEAM}`;
const response = await getFromAPI(path);
return new Promise((resolve, reject) => {
const encodedValue = JSON.parse(response.body).data;
const decodedValue = Buffer.from(encodedValue, 'base64'); // Decode base64 to binary buffer
fs.writeFile(destination, decodedValue, function (err) {
if (err) reject(err);
resolve();
});
});
}
function getFromAPI(path) {
return got(`https://api.vercel.com${path}`, {
headers: {
Authorization: `Bearer ${VERCEL_TOKEN}`,
},
responseType: 'buffer',
retry: {
limit: 0,
},
});
}
function getJSONFromAPI(path) {
return getFromAPI(path).json();
}
function flattenTree({ name, children = [] }) {
let childrenNamed = children.map((child) => ({
...child,
name: `${name}/${child.name}`,
}));
return Array.prototype.concat.apply(
childrenNamed,
childrenNamed.map(flattenTree)
);
}