@dainprotocol/cli 1.2.34 → 1.3.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/commands/build.d.ts +9 -0
- package/dist/commands/build.js +108 -260
- package/dist/commands/config.d.ts +1 -0
- package/dist/commands/config.js +37 -96
- package/dist/commands/deploy.d.ts +3 -0
- package/dist/commands/deploy.js +123 -267
- package/dist/commands/dev.d.ts +6 -0
- package/dist/commands/dev.js +202 -314
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.js +28 -31
- package/dist/commands/logs.d.ts +4 -0
- package/dist/commands/logs.js +53 -143
- package/dist/commands/start.d.ts +3 -0
- package/dist/commands/start.js +16 -22
- package/dist/commands/status.d.ts +8 -0
- package/dist/commands/status.js +26 -83
- package/dist/commands/testchat.d.ts +5 -0
- package/dist/commands/testchat.js +82 -197
- package/dist/commands/undeploy.d.ts +3 -0
- package/dist/commands/undeploy.js +18 -74
- package/dist/index.d.ts +2 -0
- package/dist/index.js +35 -38
- package/dist/templates/default/package.json +1 -1
- package/dist/templates/default/tsconfig.json +3 -3
- package/dist/utils.d.ts +62 -0
- package/dist/utils.js +154 -240
- package/package.json +3 -3
- package/dist/__tests__/build.test.js +0 -289
- package/dist/__tests__/deploy.test.js +0 -126
- package/dist/__tests__/dev.test.js +0 -321
- package/dist/__tests__/init.test.js +0 -290
- package/dist/__tests__/integration.test.js +0 -134
- package/dist/__tests__/logs.test.js +0 -135
- package/dist/__tests__/testchat.test.js +0 -214
- package/dist/__tests__/utils.test.js +0 -324
package/dist/commands/deploy.js
CHANGED
|
@@ -1,293 +1,149 @@
|
|
|
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
|
-
|
|
1
|
+
import { DEFAULT_API_BASE_URL, fetchWithTimeout, getDainConfig, joinUrl, logError, parseEnvContent, } from "../utils";
|
|
2
|
+
import ora from "ora";
|
|
3
|
+
import fs from "fs-extra";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import archiver from "archiver";
|
|
6
|
+
import build from "./build";
|
|
7
|
+
const START_DEPLOY_URI = "/api/app/data/deployments/start-deploy";
|
|
8
|
+
const DEPLOY_TIMEOUT_MS = 120000;
|
|
9
|
+
export default async function deploy(options) {
|
|
10
|
+
const config = getDainConfig(options.config);
|
|
11
|
+
const spinner = ora("Deploying project...").start();
|
|
12
|
+
const basePath = config["api-base-url"] || DEFAULT_API_BASE_URL;
|
|
13
|
+
const deployPath = joinUrl(basePath, START_DEPLOY_URI);
|
|
14
|
+
const isProduction = config["environment"] === "production";
|
|
15
|
+
const environmentName = config["environment"] || "production";
|
|
16
|
+
const { repoName, branchName } = checkGitConfig();
|
|
17
|
+
if (repoName && branchName)
|
|
18
|
+
spinner.info("Found git config, checking if project exists...").start();
|
|
19
|
+
const projectId = repoName && branchName ? await getProjectId({ basePath, repoName }) : null;
|
|
20
|
+
if (!projectId && repoName && branchName)
|
|
21
|
+
spinner.fail("No project found on platform linked to this repository.");
|
|
22
|
+
try {
|
|
23
|
+
let result;
|
|
24
|
+
if (projectId && repoName && branchName) {
|
|
25
|
+
spinner.info("Deploying project using github repository...").start();
|
|
26
|
+
const response = await fetchWithTimeout(joinUrl(basePath, `/api/app/codegen/data/projects/${projectId}/start-deploy`), {
|
|
27
|
+
method: "POST",
|
|
28
|
+
headers: { "Content-Type": "application/json" },
|
|
29
|
+
body: JSON.stringify({ environment: environmentName, isProduction, branch: branchName }),
|
|
30
|
+
}, DEPLOY_TIMEOUT_MS);
|
|
31
|
+
if (!response.ok)
|
|
32
|
+
throw new Error(`Deploy failed: ${response.status} ${response.statusText}`);
|
|
33
|
+
result = await response.json();
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
spinner.info("Deploying project using local files...").start();
|
|
37
|
+
const envArray = await loadAndValidateEnvVariables();
|
|
38
|
+
await build({ config: options.config, deploy: true });
|
|
39
|
+
result = await deployAndPushFiles(deployPath, envArray, isProduction, environmentName);
|
|
40
|
+
try {
|
|
41
|
+
await fetchWithTimeout(result.service.url, { method: "GET" }, 10000);
|
|
32
42
|
}
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
43
|
+
catch { }
|
|
44
|
+
}
|
|
45
|
+
await updateDainJson(result);
|
|
46
|
+
printDeploymentResult(result, spinner);
|
|
47
|
+
process.exit(0);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
spinner.fail("Deployment failed.");
|
|
51
|
+
logError("Error during deployment: ", error);
|
|
52
|
+
process.exit(1);
|
|
36
53
|
}
|
|
37
|
-
};
|
|
38
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
39
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
|
-
};
|
|
41
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
exports.default = deploy;
|
|
43
|
-
var utils_1 = require("../utils");
|
|
44
|
-
var ora_1 = __importDefault(require("ora"));
|
|
45
|
-
var fs_extra_1 = __importDefault(require("fs-extra"));
|
|
46
|
-
var path_1 = __importDefault(require("path"));
|
|
47
|
-
var archiver_1 = __importDefault(require("archiver"));
|
|
48
|
-
var build_1 = __importDefault(require("./build"));
|
|
49
|
-
var START_DEPLOY_URI = "/api/app/data/deployments/start-deploy";
|
|
50
|
-
var DEPLOY_TIMEOUT_MS = 120000;
|
|
51
|
-
function deploy(options) {
|
|
52
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
53
|
-
var config, spinner, basePath, deployPath, isProduction, environmentName, _a, repoName, branchName, projectId, _b, result, response, envArray, _c, error_1;
|
|
54
|
-
return __generator(this, function (_d) {
|
|
55
|
-
switch (_d.label) {
|
|
56
|
-
case 0:
|
|
57
|
-
config = (0, utils_1.getDainConfig)(options.config);
|
|
58
|
-
spinner = (0, ora_1.default)("Deploying project...").start();
|
|
59
|
-
basePath = config["api-base-url"] || utils_1.DEFAULT_API_BASE_URL;
|
|
60
|
-
deployPath = (0, utils_1.joinUrl)(basePath, START_DEPLOY_URI);
|
|
61
|
-
isProduction = config["environment"] === "production";
|
|
62
|
-
environmentName = config["environment"] || "production";
|
|
63
|
-
_a = checkGitConfig(), repoName = _a.repoName, branchName = _a.branchName;
|
|
64
|
-
if (repoName && branchName)
|
|
65
|
-
spinner.info("Found git config, checking if project exists...").start();
|
|
66
|
-
if (!(repoName && branchName)) return [3 /*break*/, 2];
|
|
67
|
-
return [4 /*yield*/, getProjectId({ basePath: basePath, repoName: repoName })];
|
|
68
|
-
case 1:
|
|
69
|
-
_b = _d.sent();
|
|
70
|
-
return [3 /*break*/, 3];
|
|
71
|
-
case 2:
|
|
72
|
-
_b = null;
|
|
73
|
-
_d.label = 3;
|
|
74
|
-
case 3:
|
|
75
|
-
projectId = _b;
|
|
76
|
-
if (!projectId && repoName && branchName)
|
|
77
|
-
spinner.fail("No project found on platform linked to this repository.");
|
|
78
|
-
_d.label = 4;
|
|
79
|
-
case 4:
|
|
80
|
-
_d.trys.push([4, 16, , 17]);
|
|
81
|
-
result = void 0;
|
|
82
|
-
if (!(projectId && repoName && branchName)) return [3 /*break*/, 7];
|
|
83
|
-
spinner.info("Deploying project using github repository...").start();
|
|
84
|
-
return [4 /*yield*/, (0, utils_1.fetchWithTimeout)((0, utils_1.joinUrl)(basePath, "/api/app/codegen/data/projects/".concat(projectId, "/start-deploy")), {
|
|
85
|
-
method: "POST",
|
|
86
|
-
headers: { "Content-Type": "application/json" },
|
|
87
|
-
body: JSON.stringify({ environment: environmentName, isProduction: isProduction, branch: branchName }),
|
|
88
|
-
}, DEPLOY_TIMEOUT_MS)];
|
|
89
|
-
case 5:
|
|
90
|
-
response = _d.sent();
|
|
91
|
-
if (!response.ok)
|
|
92
|
-
throw new Error("Deploy failed: ".concat(response.status, " ").concat(response.statusText));
|
|
93
|
-
return [4 /*yield*/, response.json()];
|
|
94
|
-
case 6:
|
|
95
|
-
result = _d.sent();
|
|
96
|
-
return [3 /*break*/, 14];
|
|
97
|
-
case 7:
|
|
98
|
-
spinner.info("Deploying project using local files...").start();
|
|
99
|
-
return [4 /*yield*/, loadAndValidateEnvVariables()];
|
|
100
|
-
case 8:
|
|
101
|
-
envArray = _d.sent();
|
|
102
|
-
return [4 /*yield*/, (0, build_1.default)({ config: options.config, deploy: true })];
|
|
103
|
-
case 9:
|
|
104
|
-
_d.sent();
|
|
105
|
-
return [4 /*yield*/, deployAndPushFiles(deployPath, envArray, isProduction, environmentName)];
|
|
106
|
-
case 10:
|
|
107
|
-
result = _d.sent();
|
|
108
|
-
_d.label = 11;
|
|
109
|
-
case 11:
|
|
110
|
-
_d.trys.push([11, 13, , 14]);
|
|
111
|
-
return [4 /*yield*/, (0, utils_1.fetchWithTimeout)(result.service.url, { method: "GET" }, 10000)];
|
|
112
|
-
case 12:
|
|
113
|
-
_d.sent();
|
|
114
|
-
return [3 /*break*/, 14];
|
|
115
|
-
case 13:
|
|
116
|
-
_c = _d.sent();
|
|
117
|
-
return [3 /*break*/, 14];
|
|
118
|
-
case 14: return [4 /*yield*/, updateDainJson(result)];
|
|
119
|
-
case 15:
|
|
120
|
-
_d.sent();
|
|
121
|
-
printDeploymentResult(result, spinner);
|
|
122
|
-
process.exit(0);
|
|
123
|
-
return [3 /*break*/, 17];
|
|
124
|
-
case 16:
|
|
125
|
-
error_1 = _d.sent();
|
|
126
|
-
spinner.fail("Deployment failed.");
|
|
127
|
-
(0, utils_1.logError)("Error during deployment: ", error_1);
|
|
128
|
-
process.exit(1);
|
|
129
|
-
return [3 /*break*/, 17];
|
|
130
|
-
case 17: return [2 /*return*/];
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
54
|
}
|
|
135
|
-
function loadAndValidateEnvVariables() {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
}
|
|
147
|
-
if (!envArray.some(function (env) { return env.name === "DAIN_API_KEY"; })) {
|
|
148
|
-
(0, utils_1.logError)("DAIN_API_KEY not found in environment variables. Please check your .env file.");
|
|
149
|
-
process.exit(1);
|
|
150
|
-
}
|
|
151
|
-
return [2 /*return*/, envArray];
|
|
152
|
-
}
|
|
153
|
-
});
|
|
154
|
-
});
|
|
55
|
+
async function loadAndValidateEnvVariables() {
|
|
56
|
+
const envArray = await loadEnvVariables();
|
|
57
|
+
if (envArray.length === 0) {
|
|
58
|
+
logError("No environment variables found. Please ensure your .env file is correctly set up.");
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
if (!envArray.some((env) => env.name === "DAIN_API_KEY")) {
|
|
62
|
+
logError("DAIN_API_KEY not found in environment variables. Please check your .env file.");
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
return envArray;
|
|
155
66
|
}
|
|
156
|
-
function deployAndPushFiles(startDeployUrl, envArray, isProduction, environmentName) {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
return [4 /*yield*/, (0, utils_1.fetchWithTimeout)(startDeployUrl, { method: "POST", body: formData }, DEPLOY_TIMEOUT_MS)];
|
|
176
|
-
case 4:
|
|
177
|
-
response = _a.sent();
|
|
178
|
-
if (!!response.ok) return [3 /*break*/, 6];
|
|
179
|
-
return [4 /*yield*/, response.text()];
|
|
180
|
-
case 5:
|
|
181
|
-
errorText = _a.sent();
|
|
182
|
-
throw new Error("Deployment failed: ".concat(response.status, " ").concat(response.statusText, ". Response: ").concat(errorText));
|
|
183
|
-
case 6: return [2 /*return*/, response.json()];
|
|
184
|
-
case 7: return [4 /*yield*/, fs_extra_1.default.remove(projectZip).catch(function () { return undefined; })];
|
|
185
|
-
case 8:
|
|
186
|
-
_a.sent();
|
|
187
|
-
return [7 /*endfinally*/];
|
|
188
|
-
case 9: return [2 /*return*/];
|
|
189
|
-
}
|
|
190
|
-
});
|
|
191
|
-
});
|
|
67
|
+
async function deployAndPushFiles(startDeployUrl, envArray, isProduction, environmentName) {
|
|
68
|
+
const projectZip = await zipDirectory("./", "project.zip");
|
|
69
|
+
try {
|
|
70
|
+
const projectZipBuffer = await fs.readFile(projectZip);
|
|
71
|
+
const formData = new FormData();
|
|
72
|
+
formData.append("array", JSON.stringify(envArray));
|
|
73
|
+
formData.append("file", new Blob([new Uint8Array(projectZipBuffer)]), "project.zip");
|
|
74
|
+
formData.append("isProduction", isProduction.toString());
|
|
75
|
+
formData.append("environment", environmentName);
|
|
76
|
+
const response = await fetchWithTimeout(startDeployUrl, { method: "POST", body: formData }, DEPLOY_TIMEOUT_MS);
|
|
77
|
+
if (!response.ok) {
|
|
78
|
+
const errorText = await response.text();
|
|
79
|
+
throw new Error(`Deployment failed: ${response.status} ${response.statusText}. Response: ${errorText}`);
|
|
80
|
+
}
|
|
81
|
+
return response.json();
|
|
82
|
+
}
|
|
83
|
+
finally {
|
|
84
|
+
await fs.remove(projectZip).catch(() => undefined);
|
|
85
|
+
}
|
|
192
86
|
}
|
|
193
|
-
function loadEnvVariables() {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
envFile = files.find(function (file) { return file === ".env"; });
|
|
202
|
-
if (!envFile) {
|
|
203
|
-
(0, utils_1.logError)("Environment file not found. Please create a .env file in the build directory.");
|
|
204
|
-
process.exit(1);
|
|
205
|
-
}
|
|
206
|
-
_a = utils_1.parseEnvContent;
|
|
207
|
-
return [4 /*yield*/, fs_extra_1.default.readFile(path_1.default.join("./", envFile), "utf-8")];
|
|
208
|
-
case 2: return [2 /*return*/, _a.apply(void 0, [_b.sent()])];
|
|
209
|
-
}
|
|
210
|
-
});
|
|
211
|
-
});
|
|
87
|
+
async function loadEnvVariables() {
|
|
88
|
+
const files = await fs.readdir("./");
|
|
89
|
+
const envFile = files.find((file) => file === ".env");
|
|
90
|
+
if (!envFile) {
|
|
91
|
+
logError("Environment file not found. Please create a .env file in the build directory.");
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
return parseEnvContent(await fs.readFile(path.join("./", envFile), "utf-8"));
|
|
212
95
|
}
|
|
213
96
|
function zipDirectory(sourceDir, outputZip) {
|
|
214
|
-
return new Promise(
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
output.on("close",
|
|
218
|
-
archive.on("error",
|
|
97
|
+
return new Promise((resolve, reject) => {
|
|
98
|
+
const output = fs.createWriteStream(outputZip);
|
|
99
|
+
const archive = archiver("zip", { zlib: { level: 9 } });
|
|
100
|
+
output.on("close", () => resolve(outputZip));
|
|
101
|
+
archive.on("error", (err) => { logError("Error during zipping: ", err); reject(err); });
|
|
219
102
|
archive.pipe(output);
|
|
220
103
|
archive.glob("**/*", { ignore: ["node_modules/**", "project.zip", ".git/**", ".env*", ".dain/**"] });
|
|
221
104
|
archive.finalize();
|
|
222
105
|
});
|
|
223
106
|
}
|
|
224
107
|
function checkGitConfig() {
|
|
225
|
-
var _a, _b, _c;
|
|
226
108
|
try {
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
||
|
|
109
|
+
const gitConfig = fs.readFileSync(".git/config", "utf-8");
|
|
110
|
+
const remote = gitConfig.match(/\[remote "origin"\][\s\S]*?url = ([^\n]+)/);
|
|
111
|
+
const remoteUrl = remote ? remote[1].trim() : null;
|
|
112
|
+
const repoName = remoteUrl?.match(/git@github.com:(.+)\.git/)?.[1]
|
|
113
|
+
|| remoteUrl?.match(/https?:\/\/github.com\/(.+)\.git/)?.[1]
|
|
232
114
|
|| null;
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
return { repoName
|
|
115
|
+
const gitHead = fs.readFileSync(".git/HEAD", "utf-8");
|
|
116
|
+
const branchName = gitHead.match(/ref: refs\/heads\/(.*)/)?.[1] || null;
|
|
117
|
+
return { repoName, branchName };
|
|
236
118
|
}
|
|
237
|
-
catch
|
|
119
|
+
catch {
|
|
238
120
|
return { repoName: null, branchName: null };
|
|
239
121
|
}
|
|
240
122
|
}
|
|
241
|
-
function getProjectId(
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
return [4 /*yield*/, (0, utils_1.fetchWithTimeout)((0, utils_1.joinUrl)(basePath, "/api/app/codegen/data/projects/get-by-repo?repo=".concat(encodeURIComponent(repoName))), { method: "GET" })];
|
|
250
|
-
case 1:
|
|
251
|
-
response = _d.sent();
|
|
252
|
-
return [2 /*return*/, response.ok ? response.json() : null];
|
|
253
|
-
case 2:
|
|
254
|
-
_c = _d.sent();
|
|
255
|
-
return [2 /*return*/, null];
|
|
256
|
-
case 3: return [2 /*return*/];
|
|
257
|
-
}
|
|
258
|
-
});
|
|
259
|
-
});
|
|
123
|
+
async function getProjectId({ basePath, repoName }) {
|
|
124
|
+
try {
|
|
125
|
+
const response = await fetchWithTimeout(joinUrl(basePath, `/api/app/codegen/data/projects/get-by-repo?repo=${encodeURIComponent(repoName)}`), { method: "GET" });
|
|
126
|
+
return response.ok ? response.json() : null;
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
260
131
|
}
|
|
261
|
-
function updateDainJson(result) {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
dainJson = _b.apply(_a, [_c.sent()]);
|
|
272
|
-
dainJson["deployment-id"] = result.deploymentId;
|
|
273
|
-
dainJson["service-id"] = result.serviceId;
|
|
274
|
-
return [4 /*yield*/, fs_extra_1.default.writeFile("./dain.json", JSON.stringify(dainJson, null, 2))];
|
|
275
|
-
case 2:
|
|
276
|
-
_c.sent();
|
|
277
|
-
return [3 /*break*/, 4];
|
|
278
|
-
case 3:
|
|
279
|
-
error_2 = _c.sent();
|
|
280
|
-
(0, utils_1.logError)("Failed to update dain.json", error_2);
|
|
281
|
-
return [3 /*break*/, 4];
|
|
282
|
-
case 4: return [2 /*return*/];
|
|
283
|
-
}
|
|
284
|
-
});
|
|
285
|
-
});
|
|
132
|
+
async function updateDainJson(result) {
|
|
133
|
+
try {
|
|
134
|
+
const dainJson = JSON.parse(await fs.readFile("./dain.json", "utf-8"));
|
|
135
|
+
dainJson["deployment-id"] = result.deploymentId;
|
|
136
|
+
dainJson["service-id"] = result.serviceId;
|
|
137
|
+
await fs.writeFile("./dain.json", JSON.stringify(dainJson, null, 2));
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
logError("Failed to update dain.json", error);
|
|
141
|
+
}
|
|
286
142
|
}
|
|
287
143
|
function printDeploymentResult(result, spinner) {
|
|
288
144
|
console.log("\n-----------------------");
|
|
289
|
-
spinner.succeed(
|
|
290
|
-
spinner.succeed(
|
|
145
|
+
spinner.succeed(`Deployment URL: ${result.service.url}`);
|
|
146
|
+
spinner.succeed(`Deployment ID: ${result.deploymentId}`);
|
|
291
147
|
spinner.succeed("Deployment completed at: " + new Date().toISOString());
|
|
292
148
|
spinner.succeed("Deployment completed successfully.");
|
|
293
149
|
spinner.info("You can access logs using `dain logs -w` command.");
|