gigadrive 0.0.3 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +707 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.mjs +684 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +9 -10
- package/dist/gigadrive.js +0 -728
- package/dist/gigadrive.js.map +0 -7
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,707 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
18
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
19
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
20
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
21
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
22
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
23
|
+
mod
|
|
24
|
+
));
|
|
25
|
+
|
|
26
|
+
// src/index.ts
|
|
27
|
+
var import_commander = require("commander");
|
|
28
|
+
|
|
29
|
+
// src/commands/build/index.ts
|
|
30
|
+
var import_build_utils = require("@gigadrive/build-utils");
|
|
31
|
+
var import_fs2 = __toESM(require("fs"), 1);
|
|
32
|
+
var import_path2 = __toESM(require("path"), 1);
|
|
33
|
+
|
|
34
|
+
// src/util/pm.ts
|
|
35
|
+
var import_fs = __toESM(require("fs"), 1);
|
|
36
|
+
var import_path = __toESM(require("path"), 1);
|
|
37
|
+
|
|
38
|
+
// ../build-utils/src/exec.ts
|
|
39
|
+
var import_child_process = require("child_process");
|
|
40
|
+
async function exec({
|
|
41
|
+
command,
|
|
42
|
+
cwd = process.cwd(),
|
|
43
|
+
env,
|
|
44
|
+
onOutput = (data) => console.log(data),
|
|
45
|
+
onError = (data) => console.error(data)
|
|
46
|
+
}) {
|
|
47
|
+
return new Promise((resolve, reject) => {
|
|
48
|
+
let spawnCommand;
|
|
49
|
+
let spawnArgs = [];
|
|
50
|
+
if (typeof command === "string") {
|
|
51
|
+
const parts = command.split(" ");
|
|
52
|
+
spawnCommand = parts[0];
|
|
53
|
+
spawnArgs = parts.slice(1);
|
|
54
|
+
} else {
|
|
55
|
+
spawnCommand = command.command;
|
|
56
|
+
spawnArgs = command.args || [];
|
|
57
|
+
}
|
|
58
|
+
const childProcess = (0, import_child_process.spawn)(spawnCommand, spawnArgs, {
|
|
59
|
+
cwd,
|
|
60
|
+
shell: true,
|
|
61
|
+
env
|
|
62
|
+
});
|
|
63
|
+
childProcess.stdout.on("data", (data) => {
|
|
64
|
+
onOutput(data.toString().trim());
|
|
65
|
+
});
|
|
66
|
+
childProcess.stderr.on("data", (data) => {
|
|
67
|
+
onError(data.toString().trim());
|
|
68
|
+
});
|
|
69
|
+
childProcess.on("error", (error2) => {
|
|
70
|
+
reject(new Error(`Failed to start process: ${error2.message}`));
|
|
71
|
+
});
|
|
72
|
+
childProcess.on("close", (code) => {
|
|
73
|
+
if (code === 0) {
|
|
74
|
+
resolve();
|
|
75
|
+
} else {
|
|
76
|
+
reject(new Error(`Process exited with code ${code}`));
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// src/util/pm.ts
|
|
83
|
+
var getPackageManager = async ({ cwd }) => {
|
|
84
|
+
const packageJsonPath = import_path.default.join(cwd, "package.json");
|
|
85
|
+
if (!import_fs.default.existsSync(packageJsonPath)) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
if (import_fs.default.existsSync(import_path.default.join(cwd, "yarn.lock"))) {
|
|
89
|
+
return "yarn";
|
|
90
|
+
}
|
|
91
|
+
if (import_fs.default.existsSync(import_path.default.join(cwd, "pnpm-lock.yaml"))) {
|
|
92
|
+
return "pnpm";
|
|
93
|
+
}
|
|
94
|
+
if (import_fs.default.existsSync(import_path.default.join(cwd, "bun.lockb"))) {
|
|
95
|
+
return "bun";
|
|
96
|
+
}
|
|
97
|
+
if (import_fs.default.existsSync(import_path.default.join(cwd, "package-lock.json"))) {
|
|
98
|
+
return "npm";
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
await exec({ command: "bun --version", cwd });
|
|
102
|
+
return "bun";
|
|
103
|
+
} catch (e) {
|
|
104
|
+
return "npm";
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
var installCommand = (pm) => {
|
|
108
|
+
return {
|
|
109
|
+
bun: "bun install",
|
|
110
|
+
npm: "npm install",
|
|
111
|
+
pnpm: "pnpm install",
|
|
112
|
+
yarn: "yarn install"
|
|
113
|
+
}[pm] || "npm install";
|
|
114
|
+
};
|
|
115
|
+
var buildCommand = (pm) => {
|
|
116
|
+
return {
|
|
117
|
+
bun: "bun run build",
|
|
118
|
+
npm: "npm run build",
|
|
119
|
+
pnpm: "pnpm build",
|
|
120
|
+
yarn: "yarn build"
|
|
121
|
+
}[pm] || "npm run build";
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
// src/commands/build/index.ts
|
|
125
|
+
var build = (parent) => {
|
|
126
|
+
parent.command("build").description("Build the current project").action(async () => {
|
|
127
|
+
const env = {
|
|
128
|
+
...process.env,
|
|
129
|
+
NODE_ENV: "production",
|
|
130
|
+
NEBULA: "1",
|
|
131
|
+
VERCEL: "1",
|
|
132
|
+
// Vercel compatibility
|
|
133
|
+
NOW_BUILDER: "1"
|
|
134
|
+
};
|
|
135
|
+
const cwd = process.cwd();
|
|
136
|
+
const packageJsonPath = import_path2.default.join(cwd, "package.json");
|
|
137
|
+
if (!import_fs2.default.existsSync(packageJsonPath)) {
|
|
138
|
+
console.log("No package.json found");
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
const packageJson = JSON.parse(import_fs2.default.readFileSync(packageJsonPath, "utf-8"));
|
|
142
|
+
const buildScript = packageJson.scripts?.build;
|
|
143
|
+
if (!buildScript) {
|
|
144
|
+
console.log("No build script found in package.json");
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const packageManager = await getPackageManager({ cwd });
|
|
148
|
+
if (!packageManager) {
|
|
149
|
+
console.log("No package manager found");
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
await (0, import_build_utils.exec)({
|
|
153
|
+
command: installCommand(packageManager),
|
|
154
|
+
cwd,
|
|
155
|
+
env,
|
|
156
|
+
onOutput: (chunk) => {
|
|
157
|
+
console.log(chunk);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
await (0, import_build_utils.exec)({
|
|
161
|
+
command: buildCommand(packageManager),
|
|
162
|
+
cwd,
|
|
163
|
+
env,
|
|
164
|
+
onOutput: (chunk) => {
|
|
165
|
+
console.log(chunk);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
// src/commands/platform/deploy/index.ts
|
|
172
|
+
var import_commons = require("@gigadrive/commons");
|
|
173
|
+
var import_network_config = require("@gigadrive/network-config");
|
|
174
|
+
var import_fs4 = __toESM(require("fs"), 1);
|
|
175
|
+
var import_os = __toESM(require("os"), 1);
|
|
176
|
+
var import_path4 = __toESM(require("path"), 1);
|
|
177
|
+
|
|
178
|
+
// src/util/log.ts
|
|
179
|
+
var import_consola = require("consola");
|
|
180
|
+
var verbose = false;
|
|
181
|
+
var consola = (0, import_consola.createConsola)({
|
|
182
|
+
level: verbose ? 4 : 3,
|
|
183
|
+
// 4 includes debug messages, 3 is the default (info and above)
|
|
184
|
+
formatOptions: {
|
|
185
|
+
colors: true
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
var updateConsola = () => {
|
|
189
|
+
consola.level = verbose ? 4 : 3;
|
|
190
|
+
};
|
|
191
|
+
var setVerbose = (value) => {
|
|
192
|
+
verbose = value;
|
|
193
|
+
updateConsola();
|
|
194
|
+
};
|
|
195
|
+
var log = (message) => {
|
|
196
|
+
consola.info(message);
|
|
197
|
+
};
|
|
198
|
+
var error = (message) => {
|
|
199
|
+
consola.error(message);
|
|
200
|
+
};
|
|
201
|
+
var success = (message) => {
|
|
202
|
+
consola.success(message);
|
|
203
|
+
};
|
|
204
|
+
var warn = (message) => {
|
|
205
|
+
consola.warn(message);
|
|
206
|
+
};
|
|
207
|
+
var debug = (message, ...optionalParams) => {
|
|
208
|
+
if (!verbose) {
|
|
209
|
+
console.log("debug", message, ...optionalParams);
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
consola.debug("[DEBUG]", message, ...optionalParams);
|
|
213
|
+
};
|
|
214
|
+
var spinner = (message) => {
|
|
215
|
+
log(message);
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
// src/util/zip.ts
|
|
219
|
+
var import_archiver = __toESM(require("archiver"), 1);
|
|
220
|
+
var import_fs3 = __toESM(require("fs"), 1);
|
|
221
|
+
var import_ignore = __toESM(require("ignore"), 1);
|
|
222
|
+
var import_path3 = __toESM(require("path"), 1);
|
|
223
|
+
var ignoreFileNames = [
|
|
224
|
+
/*'.gitignore', */
|
|
225
|
+
".gigadriveignore",
|
|
226
|
+
".vercelignore",
|
|
227
|
+
".dockerignore",
|
|
228
|
+
".nowignore"
|
|
229
|
+
];
|
|
230
|
+
function readIgnoreFile(ignorePath) {
|
|
231
|
+
if (import_fs3.default.existsSync(ignorePath)) {
|
|
232
|
+
return import_fs3.default.readFileSync(ignorePath, "utf8").split("\n").filter((line) => line.trim() !== "");
|
|
233
|
+
}
|
|
234
|
+
return [];
|
|
235
|
+
}
|
|
236
|
+
function collectIgnorePatterns(dir, baseDir, ignoreRules) {
|
|
237
|
+
const items = import_fs3.default.readdirSync(dir);
|
|
238
|
+
items.forEach((item) => {
|
|
239
|
+
const fullPath = import_path3.default.join(dir, item);
|
|
240
|
+
const relativePath = import_path3.default.relative(baseDir, fullPath);
|
|
241
|
+
const stat = import_fs3.default.lstatSync(fullPath);
|
|
242
|
+
if (stat.isDirectory()) {
|
|
243
|
+
if (ignoreRules.ignores(`${relativePath}/`)) {
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
ignoreFileNames.forEach((ignoreFileName) => {
|
|
247
|
+
const ignoreFilePath = import_path3.default.join(fullPath, ignoreFileName);
|
|
248
|
+
if (import_fs3.default.existsSync(ignoreFilePath)) {
|
|
249
|
+
const patterns = readIgnoreFile(ignoreFilePath).map((pattern) => {
|
|
250
|
+
return pattern.startsWith("!") ? `!${import_path3.default.join(relativePath, pattern.slice(1))}` : import_path3.default.join(relativePath, pattern);
|
|
251
|
+
});
|
|
252
|
+
ignoreRules.add(patterns);
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
collectIgnorePatterns(fullPath, baseDir, ignoreRules);
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
function initializeIgnoreRules(baseDir) {
|
|
260
|
+
const ignoreRules = (0, import_ignore.default)();
|
|
261
|
+
ignoreRules.add([".git/", "**/.DS_Store", "**/Thumbs.db"]);
|
|
262
|
+
ignoreFileNames.forEach((ignoreFileName) => {
|
|
263
|
+
const ignoreFilePath = import_path3.default.join(baseDir, ignoreFileName);
|
|
264
|
+
if (import_fs3.default.existsSync(ignoreFilePath)) {
|
|
265
|
+
const patterns = readIgnoreFile(ignoreFilePath).map((pattern) => {
|
|
266
|
+
return pattern.startsWith("!") ? `!${pattern.slice(1)}` : pattern;
|
|
267
|
+
});
|
|
268
|
+
ignoreRules.add(patterns);
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
collectIgnorePatterns(baseDir, baseDir, ignoreRules);
|
|
272
|
+
return ignoreRules;
|
|
273
|
+
}
|
|
274
|
+
async function getFilesToInclude(dir, ignoreRules) {
|
|
275
|
+
const filesToInclude = [];
|
|
276
|
+
function walkSync(currentDir) {
|
|
277
|
+
const items = import_fs3.default.readdirSync(currentDir);
|
|
278
|
+
items.forEach((item) => {
|
|
279
|
+
const fullPath = import_path3.default.join(currentDir, item);
|
|
280
|
+
const relativePath = import_path3.default.relative(dir, fullPath);
|
|
281
|
+
const stat = import_fs3.default.lstatSync(fullPath);
|
|
282
|
+
if (stat.isDirectory()) {
|
|
283
|
+
if (ignoreRules.ignores(`${relativePath}/`)) {
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
walkSync(fullPath);
|
|
287
|
+
} else {
|
|
288
|
+
if (!ignoreRules.ignores(relativePath)) {
|
|
289
|
+
filesToInclude.push(fullPath);
|
|
290
|
+
} else if (ignoreRules.ignores(relativePath) && ignoreRules.test(relativePath).unignored) {
|
|
291
|
+
filesToInclude.push(fullPath);
|
|
292
|
+
} else {
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
walkSync(dir);
|
|
298
|
+
return filesToInclude;
|
|
299
|
+
}
|
|
300
|
+
async function createZipArchive(inputDir, outputFile, options = {}) {
|
|
301
|
+
const ignoreRules = options.useIgnoreFiles !== false ? initializeIgnoreRules(inputDir) : (0, import_ignore.default)();
|
|
302
|
+
const filesToInclude = await getFilesToInclude(inputDir, ignoreRules);
|
|
303
|
+
const output = import_fs3.default.createWriteStream(outputFile);
|
|
304
|
+
const archive = (0, import_archiver.default)("zip", { zlib: { level: 9 } });
|
|
305
|
+
return new Promise((resolve, reject) => {
|
|
306
|
+
output.on("close", () => resolve());
|
|
307
|
+
archive.on("error", reject);
|
|
308
|
+
archive.pipe(output);
|
|
309
|
+
filesToInclude.forEach((file) => {
|
|
310
|
+
archive.file(file, { name: import_path3.default.relative(inputDir, file) });
|
|
311
|
+
});
|
|
312
|
+
archive.finalize();
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// src/commands/platform/deploy/index.ts
|
|
317
|
+
var deploy = (parent) => {
|
|
318
|
+
parent.command("deploy").description("Deploy the current project").action(async () => {
|
|
319
|
+
debug("Starting deploy command");
|
|
320
|
+
const configPath = (0, import_network_config.findConfig)(process.cwd());
|
|
321
|
+
if (!configPath) {
|
|
322
|
+
debug("No config file found");
|
|
323
|
+
throw new Error("The current project folder does not have a valid config file.");
|
|
324
|
+
}
|
|
325
|
+
debug(`Found config at: ${configPath}`);
|
|
326
|
+
const config = await (0, import_network_config.parseConfig)(configPath, process.cwd());
|
|
327
|
+
debug("Parsed config", config);
|
|
328
|
+
if (config.warnings.length > 0) {
|
|
329
|
+
debug(`Found ${config.warnings.length} warnings in config`);
|
|
330
|
+
config.warnings.forEach((message) => {
|
|
331
|
+
warn(message);
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
if (config.errors.length > 0) {
|
|
335
|
+
debug(`Found ${config.errors.length} errors in config`);
|
|
336
|
+
config.errors.forEach((message) => {
|
|
337
|
+
error(message);
|
|
338
|
+
});
|
|
339
|
+
throw new Error("The current project folder does not have a valid config file.");
|
|
340
|
+
}
|
|
341
|
+
debug("Creating deployment");
|
|
342
|
+
const deploymentId = await createDeployment({
|
|
343
|
+
applicationId: "test"
|
|
344
|
+
// TODO
|
|
345
|
+
});
|
|
346
|
+
debug(`Deployment ID: ${deploymentId}`);
|
|
347
|
+
debug("Starting deployment process");
|
|
348
|
+
await handleDeployment(deploymentId, config);
|
|
349
|
+
});
|
|
350
|
+
};
|
|
351
|
+
var handleDeployment = async (deploymentId, config) => {
|
|
352
|
+
debug("Deployment process initialized");
|
|
353
|
+
let status = "PENDING";
|
|
354
|
+
const logs = [];
|
|
355
|
+
addLog("Deployment ID: " + deploymentId, "INFO", logs);
|
|
356
|
+
try {
|
|
357
|
+
debug("Starting upload process");
|
|
358
|
+
await uploadArchive(deploymentId, logs);
|
|
359
|
+
debug("Upload completed successfully");
|
|
360
|
+
addLog("Upload complete.", "INFO", logs);
|
|
361
|
+
addLog("The deployment pipeline is now being provisioned. This may take a few seconds.", "INFO", logs);
|
|
362
|
+
} catch (err) {
|
|
363
|
+
debug(`Upload failed with error: ${err.message}`);
|
|
364
|
+
addLog(`Upload failed: ${err.message}`, "ERROR", logs);
|
|
365
|
+
status = "FAILED";
|
|
366
|
+
error("The deployment failed. Please check the logs for more information.");
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
const statusInterval = setInterval(async () => {
|
|
370
|
+
try {
|
|
371
|
+
debug(`Fetching deployment status for ${deploymentId}`);
|
|
372
|
+
const newStatus = await getDeploymentStatus(deploymentId);
|
|
373
|
+
debug(`Current status: ${status}, New status: ${newStatus}`);
|
|
374
|
+
if (newStatus === "ACTIVE" || newStatus === "FAILED") {
|
|
375
|
+
debug(`Final status reached: ${newStatus}, clearing interval`);
|
|
376
|
+
clearInterval(statusInterval);
|
|
377
|
+
clearInterval(logsInterval);
|
|
378
|
+
if (newStatus === "ACTIVE") {
|
|
379
|
+
success(`Deployed to https://${deploymentId}.gigadrivedev.com`);
|
|
380
|
+
} else {
|
|
381
|
+
error("The deployment failed. Please check the logs for more information.");
|
|
382
|
+
}
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
if (newStatus !== status) {
|
|
386
|
+
debug(`Updating status from ${status} to ${newStatus}`);
|
|
387
|
+
status = newStatus;
|
|
388
|
+
spinner(`Status: ${status.toLowerCase().replace(/^\w/, (c) => c.toUpperCase())}`);
|
|
389
|
+
}
|
|
390
|
+
} catch (err) {
|
|
391
|
+
debug(`Error fetching status: ${err.message}`);
|
|
392
|
+
}
|
|
393
|
+
}, 1e3);
|
|
394
|
+
const logsInterval = setInterval(async () => {
|
|
395
|
+
try {
|
|
396
|
+
debug(`Fetching logs for ${deploymentId}, current log count: ${logs.length}`);
|
|
397
|
+
const newLogs = await getLogs(deploymentId, {
|
|
398
|
+
offset: logs.length,
|
|
399
|
+
limit: 100,
|
|
400
|
+
"createdAt[gt]": logs[logs.length - 1]?.createdAt
|
|
401
|
+
});
|
|
402
|
+
debug(`Fetched ${newLogs.items.length} new logs`);
|
|
403
|
+
for (const logEntry of newLogs.items) {
|
|
404
|
+
logs.push(logEntry);
|
|
405
|
+
if (logEntry.type === "ERROR") {
|
|
406
|
+
error(logEntry.message);
|
|
407
|
+
} else if (logEntry.type === "WARN") {
|
|
408
|
+
warn(logEntry.message);
|
|
409
|
+
} else {
|
|
410
|
+
log(logEntry.message);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
} catch (err) {
|
|
414
|
+
debug(`Error fetching logs: ${err.message}`);
|
|
415
|
+
}
|
|
416
|
+
}, 1e3);
|
|
417
|
+
spinner(`Status: ${status.toLowerCase().replace(/^\w/, (c) => c.toUpperCase())}`);
|
|
418
|
+
};
|
|
419
|
+
var addLog = (message, type, logs) => {
|
|
420
|
+
debug(`Adding log: [${type}] ${message}`);
|
|
421
|
+
logs.push({
|
|
422
|
+
id: String(logs.length),
|
|
423
|
+
message,
|
|
424
|
+
type,
|
|
425
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
426
|
+
});
|
|
427
|
+
if (type === "ERROR") {
|
|
428
|
+
error(message);
|
|
429
|
+
} else if (type === "WARN") {
|
|
430
|
+
warn(message);
|
|
431
|
+
} else {
|
|
432
|
+
log(message);
|
|
433
|
+
}
|
|
434
|
+
};
|
|
435
|
+
var uploadArchive = async (deploymentId, logs) => {
|
|
436
|
+
debug("Starting uploadArchive");
|
|
437
|
+
addLog("Creating archive...", "INFO", logs);
|
|
438
|
+
const archivePath = import_path4.default.join(process.env.TEMP || import_os.default.tmpdir(), `project-${Date.now()}.zip`);
|
|
439
|
+
debug(`Archive path: ${archivePath}`);
|
|
440
|
+
if (import_fs4.default.existsSync(archivePath)) {
|
|
441
|
+
debug(`Archive already exists, removing: ${archivePath}`);
|
|
442
|
+
import_fs4.default.unlinkSync(archivePath);
|
|
443
|
+
}
|
|
444
|
+
debug("Creating zip archive");
|
|
445
|
+
await createZipArchive(process.cwd(), archivePath, { useIgnoreFiles: false, useManagedIgnore: false });
|
|
446
|
+
const fileStats = import_fs4.default.statSync(archivePath);
|
|
447
|
+
const fileSize = fileStats.size;
|
|
448
|
+
debug(`Archive created, size: ${fileSize} bytes (${(0, import_commons.formatFileSize)(fileSize)})`);
|
|
449
|
+
addLog(`Archive created (${(0, import_commons.formatFileSize)(fileSize)})`, "INFO", logs);
|
|
450
|
+
addLog("Uploading archive...", "INFO", logs);
|
|
451
|
+
debug(`Starting multipart upload for deployment: ${deploymentId}`);
|
|
452
|
+
const uploadId = await startMultipartUpload(deploymentId);
|
|
453
|
+
debug(`Upload ID: ${uploadId}`);
|
|
454
|
+
debug("Uploading archive...");
|
|
455
|
+
const fileChunkSize = 10 * 1024 * 1024;
|
|
456
|
+
const numChunks = Math.ceil(fileSize / fileChunkSize);
|
|
457
|
+
debug(`File size: ${fileSize}, chunk size: ${fileChunkSize}, number of chunks: ${numChunks}`);
|
|
458
|
+
const promises = [];
|
|
459
|
+
let start, end;
|
|
460
|
+
for (let index = 1; index < numChunks + 1; index++) {
|
|
461
|
+
start = (index - 1) * fileChunkSize;
|
|
462
|
+
end = index * fileChunkSize;
|
|
463
|
+
debug(`Processing chunk ${index}/${numChunks}, start: ${start}, end: ${end}`);
|
|
464
|
+
const presignedUrl = await getPresignedUrl(deploymentId, uploadId, index);
|
|
465
|
+
debug("Presigned URL for part", index, presignedUrl);
|
|
466
|
+
const promise = new Promise(async (resolve, reject) => {
|
|
467
|
+
try {
|
|
468
|
+
debug(`Reading chunk ${index} data`);
|
|
469
|
+
const readStream = import_fs4.default.createReadStream(archivePath, {
|
|
470
|
+
start,
|
|
471
|
+
end: index < numChunks ? end - 1 : void 0
|
|
472
|
+
});
|
|
473
|
+
const chunks = [];
|
|
474
|
+
readStream.on("data", (chunk) => {
|
|
475
|
+
chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
|
|
476
|
+
});
|
|
477
|
+
await new Promise((resolveRead) => {
|
|
478
|
+
readStream.on("end", () => resolveRead());
|
|
479
|
+
readStream.on("error", reject);
|
|
480
|
+
});
|
|
481
|
+
const buffer = Buffer.concat(chunks);
|
|
482
|
+
debug(`Uploading chunk ${index} to presigned URL (${buffer.length} bytes)`);
|
|
483
|
+
const response = await fetch(presignedUrl, {
|
|
484
|
+
method: "PUT",
|
|
485
|
+
headers: {
|
|
486
|
+
"Content-Type": "application/zip",
|
|
487
|
+
"Content-Length": String(buffer.length)
|
|
488
|
+
},
|
|
489
|
+
body: buffer
|
|
490
|
+
});
|
|
491
|
+
resolve(response);
|
|
492
|
+
} catch (err) {
|
|
493
|
+
reject(err);
|
|
494
|
+
}
|
|
495
|
+
});
|
|
496
|
+
promises.push(promise);
|
|
497
|
+
}
|
|
498
|
+
const finishedParts = [];
|
|
499
|
+
try {
|
|
500
|
+
debug(`Waiting for all ${promises.length} upload promises to complete`);
|
|
501
|
+
const responses = await Promise.all(promises);
|
|
502
|
+
debug("All upload promises completed");
|
|
503
|
+
for (let index = 0; index < responses.length; index++) {
|
|
504
|
+
const res = responses[index];
|
|
505
|
+
debug(`Checking response for part ${index + 1}, status: ${res.status}`);
|
|
506
|
+
if (!res.ok) {
|
|
507
|
+
debug(`Failed to upload part ${index + 1}: ${res.statusText} ${await res.text()}`);
|
|
508
|
+
throw new Error(`Failed to upload part ${index + 1}: ${res.statusText}`);
|
|
509
|
+
}
|
|
510
|
+
const etag = res.headers.get("ETag");
|
|
511
|
+
if (!etag) {
|
|
512
|
+
debug(`Failed to get ETag for part ${index + 1}`);
|
|
513
|
+
throw new Error(`Failed to get ETag for part ${index + 1}`);
|
|
514
|
+
}
|
|
515
|
+
debug(`Part ${index + 1} uploaded successfully, ETag: ${etag}`);
|
|
516
|
+
finishedParts.push({
|
|
517
|
+
partNumber: index + 1,
|
|
518
|
+
etag
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
debug(`Completing upload with ${finishedParts.length} parts`);
|
|
522
|
+
await completeUpload(deploymentId, uploadId, finishedParts);
|
|
523
|
+
debug("Upload completed successfully");
|
|
524
|
+
} catch (err) {
|
|
525
|
+
const error2 = err;
|
|
526
|
+
debug(`Upload error: ${error2.message}`);
|
|
527
|
+
addLog(`Upload error: ${error2.message}`, "ERROR", logs);
|
|
528
|
+
throw error2;
|
|
529
|
+
}
|
|
530
|
+
};
|
|
531
|
+
var createDeployment = async ({ applicationId }) => {
|
|
532
|
+
debug(`Creating deployment for application: ${applicationId}`);
|
|
533
|
+
const res = await fetch(`http://localhost:3000/${applicationId}/deployments`, {
|
|
534
|
+
method: "POST",
|
|
535
|
+
headers: {
|
|
536
|
+
"Content-Type": "application/json"
|
|
537
|
+
},
|
|
538
|
+
body: JSON.stringify({}),
|
|
539
|
+
duplex: "half"
|
|
540
|
+
});
|
|
541
|
+
if (!res.ok) {
|
|
542
|
+
const errorText = await res.text();
|
|
543
|
+
debug(`Failed to create deployment: ${errorText}`);
|
|
544
|
+
throw new Error("Failed to create deployment: " + errorText);
|
|
545
|
+
}
|
|
546
|
+
const deployment = await res.json();
|
|
547
|
+
debug(`Deployment created with ID: ${deployment.id}`);
|
|
548
|
+
return deployment.id;
|
|
549
|
+
};
|
|
550
|
+
var startMultipartUpload = async (deploymentId) => {
|
|
551
|
+
debug(`Starting multipart upload for deployment: ${deploymentId}`);
|
|
552
|
+
const res = await fetch(`http://localhost:3000/deployments/${deploymentId}/pre-signed-url/start`, {
|
|
553
|
+
method: "GET",
|
|
554
|
+
headers: {
|
|
555
|
+
"Content-Type": "application/json"
|
|
556
|
+
}
|
|
557
|
+
});
|
|
558
|
+
if (!res.ok) {
|
|
559
|
+
const errorText = await res.text();
|
|
560
|
+
debug(`Failed to start multipart upload: ${errorText}`);
|
|
561
|
+
throw new Error("Failed to start multipart upload: " + errorText);
|
|
562
|
+
}
|
|
563
|
+
const upload = await res.json();
|
|
564
|
+
debug(`Multipart upload started with ID: ${upload.uploadId}`);
|
|
565
|
+
return upload.uploadId;
|
|
566
|
+
};
|
|
567
|
+
var getPresignedUrl = async (deploymentId, uploadId, partNumber) => {
|
|
568
|
+
debug(`Getting presigned URL for deployment: ${deploymentId}, upload: ${uploadId}, part: ${partNumber}`);
|
|
569
|
+
const res = await fetch(
|
|
570
|
+
`http://localhost:3000/deployments/${deploymentId}/pre-signed-url/part?uploadId=${uploadId}&partNumber=${partNumber}`,
|
|
571
|
+
{
|
|
572
|
+
method: "GET",
|
|
573
|
+
headers: {
|
|
574
|
+
"Content-Type": "application/json"
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
);
|
|
578
|
+
if (!res.ok) {
|
|
579
|
+
const errorText = await res.text();
|
|
580
|
+
debug(`Failed to get pre-signed URL: ${errorText}`);
|
|
581
|
+
throw new Error("Failed to get pre-signed URL: " + errorText);
|
|
582
|
+
}
|
|
583
|
+
const upload = await res.json();
|
|
584
|
+
debug(`Got presigned URL for part ${partNumber}`);
|
|
585
|
+
return upload.url;
|
|
586
|
+
};
|
|
587
|
+
var completeUpload = async (deploymentId, uploadId, parts) => {
|
|
588
|
+
debug(`Completing upload for deployment: ${deploymentId}, upload: ${uploadId}, parts: ${parts.length}`);
|
|
589
|
+
const res = await fetch(`http://localhost:3000/deployments/${deploymentId}/pre-signed-url/complete`, {
|
|
590
|
+
method: "POST",
|
|
591
|
+
headers: {
|
|
592
|
+
"Content-Type": "application/json"
|
|
593
|
+
},
|
|
594
|
+
body: JSON.stringify({
|
|
595
|
+
uploadId,
|
|
596
|
+
parts
|
|
597
|
+
}),
|
|
598
|
+
duplex: "half"
|
|
599
|
+
});
|
|
600
|
+
if (!res.ok) {
|
|
601
|
+
const errorText = await res.text();
|
|
602
|
+
debug(`Failed to complete upload: ${errorText}`);
|
|
603
|
+
throw new Error("Failed to complete upload: " + errorText);
|
|
604
|
+
}
|
|
605
|
+
debug("Upload completed successfully");
|
|
606
|
+
};
|
|
607
|
+
var getDeploymentStatus = async (deploymentId) => {
|
|
608
|
+
debug(`Getting deployment status for: ${deploymentId}`);
|
|
609
|
+
const res = await fetch(`http://localhost:3000/deployments/${deploymentId}`, {
|
|
610
|
+
method: "GET",
|
|
611
|
+
headers: {
|
|
612
|
+
"Content-Type": "application/json"
|
|
613
|
+
}
|
|
614
|
+
});
|
|
615
|
+
if (!res.ok) {
|
|
616
|
+
const errorText = await res.text();
|
|
617
|
+
debug(`Failed to get deployment status: ${errorText}`);
|
|
618
|
+
throw new Error("Failed to get deployment status: " + errorText);
|
|
619
|
+
}
|
|
620
|
+
const deployment = await res.json();
|
|
621
|
+
debug(`Deployment status: ${deployment.status}`);
|
|
622
|
+
return deployment.status;
|
|
623
|
+
};
|
|
624
|
+
var getLogs = async (deploymentId, options) => {
|
|
625
|
+
debug(`Getting logs for deployment: ${deploymentId}, options:`, options);
|
|
626
|
+
const res = await fetch(`http://localhost:3000/deployments/${deploymentId}/logs${(0, import_commons.objectToQueryString)(options)}`, {
|
|
627
|
+
method: "GET",
|
|
628
|
+
headers: {
|
|
629
|
+
"Content-Type": "application/json"
|
|
630
|
+
}
|
|
631
|
+
});
|
|
632
|
+
if (!res.ok) {
|
|
633
|
+
const errorText = await res.text();
|
|
634
|
+
debug(`Failed to get logs: ${errorText}`);
|
|
635
|
+
throw new Error("Failed to get logs: " + errorText);
|
|
636
|
+
}
|
|
637
|
+
const logs = await res.json();
|
|
638
|
+
debug(`Got ${logs.items.length} logs, total: ${logs.totalItems}`);
|
|
639
|
+
return logs;
|
|
640
|
+
};
|
|
641
|
+
|
|
642
|
+
// src/commands/platform/index.ts
|
|
643
|
+
var platform = (program) => {
|
|
644
|
+
const platform2 = program.command("platform").description("Manage the platform");
|
|
645
|
+
deploy(platform2);
|
|
646
|
+
};
|
|
647
|
+
|
|
648
|
+
// src/index.ts
|
|
649
|
+
var { isTTY } = process.stdout;
|
|
650
|
+
var main = async () => {
|
|
651
|
+
if (process.env.FORCE_TTY === "1") {
|
|
652
|
+
isTTY = true;
|
|
653
|
+
process.stdout.isTTY = true;
|
|
654
|
+
process.stdin.isTTY = true;
|
|
655
|
+
}
|
|
656
|
+
let exitCode = 0;
|
|
657
|
+
const program = new import_commander.Command();
|
|
658
|
+
program.option("-v, --verbose", "Enable verbose logging");
|
|
659
|
+
program.hook("preSubcommand", (thisCommand, actionCommand) => {
|
|
660
|
+
setVerbose(thisCommand.opts().verbose);
|
|
661
|
+
console.log("preSubcommand hook", thisCommand.opts().verbose);
|
|
662
|
+
if (thisCommand.opts().verbose) {
|
|
663
|
+
log("Using verbose mode");
|
|
664
|
+
}
|
|
665
|
+
});
|
|
666
|
+
program.hook("preAction", (thisCommand) => {
|
|
667
|
+
setVerbose(thisCommand.opts().verbose);
|
|
668
|
+
});
|
|
669
|
+
platform(program);
|
|
670
|
+
build(program);
|
|
671
|
+
try {
|
|
672
|
+
await program.parseAsync(process.argv);
|
|
673
|
+
} catch (err) {
|
|
674
|
+
error(err);
|
|
675
|
+
exitCode = 1;
|
|
676
|
+
}
|
|
677
|
+
return exitCode;
|
|
678
|
+
};
|
|
679
|
+
var handleRejection = async (err) => {
|
|
680
|
+
if (err) {
|
|
681
|
+
if (err instanceof Error) {
|
|
682
|
+
await handleUnexpected(err);
|
|
683
|
+
} else {
|
|
684
|
+
console.error(`An unexpected rejection occurred
|
|
685
|
+
${err}`);
|
|
686
|
+
}
|
|
687
|
+
} else {
|
|
688
|
+
console.error("An unexpected empty rejection occurred");
|
|
689
|
+
}
|
|
690
|
+
process.exit(1);
|
|
691
|
+
};
|
|
692
|
+
var handleUnexpected = (error2) => {
|
|
693
|
+
const { message } = error2;
|
|
694
|
+
console.error(`An unexpected error occurred
|
|
695
|
+
${message}`);
|
|
696
|
+
process.exit(1);
|
|
697
|
+
};
|
|
698
|
+
process.on("unhandledRejection", handleRejection);
|
|
699
|
+
process.on("uncaughtException", handleUnexpected);
|
|
700
|
+
process.on("exit", () => {
|
|
701
|
+
const terminal = process.stderr.isTTY ? process.stderr : process.stdout.isTTY ? process.stdout : void 0;
|
|
702
|
+
terminal?.write("\x1B[?25h");
|
|
703
|
+
});
|
|
704
|
+
main().then(async (exitCode) => {
|
|
705
|
+
process.exitCode = exitCode;
|
|
706
|
+
}).catch(handleUnexpected);
|
|
707
|
+
//# sourceMappingURL=index.cjs.map
|