@aaricchen1991/n2-cli 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/README.md +92 -0
- package/assets/deploy/deploy.sh +172 -0
- package/assets/deploy/domains.yaml +18 -0
- package/assets/deploy/lib/common.sh +62 -0
- package/assets/deploy/nginx/n2.conf +162 -0
- package/assets/deploy/server-setup.sh +285 -0
- package/assets/deploy/ssl/README.md +320 -0
- package/assets/deploy/ssl/check-and-setup-ssl.sh +222 -0
- package/assets/deploy/ssl/domains.txt +3 -0
- package/assets/deploy/ssl/renew-ssl.sh +236 -0
- package/assets/deploy/ssl/setup-ssl.sh +474 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +186 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/config.d.ts +29 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +134 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/config.test.d.ts +2 -0
- package/dist/commands/config.test.d.ts.map +1 -0
- package/dist/commands/config.test.js +215 -0
- package/dist/commands/config.test.js.map +1 -0
- package/dist/commands/init.d.ts +10 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +106 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/init.test.d.ts +2 -0
- package/dist/commands/init.test.d.ts.map +1 -0
- package/dist/commands/init.test.js +70 -0
- package/dist/commands/init.test.js.map +1 -0
- package/dist/commands/nginx.d.ts +10 -0
- package/dist/commands/nginx.d.ts.map +1 -0
- package/dist/commands/nginx.js +72 -0
- package/dist/commands/nginx.js.map +1 -0
- package/dist/commands/nginx.test.d.ts +2 -0
- package/dist/commands/nginx.test.d.ts.map +1 -0
- package/dist/commands/nginx.test.js +75 -0
- package/dist/commands/nginx.test.js.map +1 -0
- package/dist/commands/ssl-logs.d.ts +17 -0
- package/dist/commands/ssl-logs.d.ts.map +1 -0
- package/dist/commands/ssl-logs.js +55 -0
- package/dist/commands/ssl-logs.js.map +1 -0
- package/dist/commands/ssl-logs.test.d.ts +2 -0
- package/dist/commands/ssl-logs.test.d.ts.map +1 -0
- package/dist/commands/ssl-logs.test.js +54 -0
- package/dist/commands/ssl-logs.test.js.map +1 -0
- package/dist/commands/ssl.d.ts +16 -0
- package/dist/commands/ssl.d.ts.map +1 -0
- package/dist/commands/ssl.js +105 -0
- package/dist/commands/ssl.js.map +1 -0
- package/dist/commands/ssl.test.d.ts +2 -0
- package/dist/commands/ssl.test.d.ts.map +1 -0
- package/dist/commands/ssl.test.js +95 -0
- package/dist/commands/ssl.test.js.map +1 -0
- package/dist/lib/config-store.d.ts +14 -0
- package/dist/lib/config-store.d.ts.map +1 -0
- package/dist/lib/config-store.js +111 -0
- package/dist/lib/config-store.js.map +1 -0
- package/dist/lib/config-store.test.d.ts +2 -0
- package/dist/lib/config-store.test.d.ts.map +1 -0
- package/dist/lib/config-store.test.js +173 -0
- package/dist/lib/config-store.test.js.map +1 -0
- package/dist/lib/domains.d.ts +37 -0
- package/dist/lib/domains.d.ts.map +1 -0
- package/dist/lib/domains.js +134 -0
- package/dist/lib/domains.js.map +1 -0
- package/dist/lib/domains.test.d.ts +2 -0
- package/dist/lib/domains.test.d.ts.map +1 -0
- package/dist/lib/domains.test.js +141 -0
- package/dist/lib/domains.test.js.map +1 -0
- package/dist/lib/logger.d.ts +19 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js +58 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/nginx.d.ts +7 -0
- package/dist/lib/nginx.d.ts.map +1 -0
- package/dist/lib/nginx.js +86 -0
- package/dist/lib/nginx.js.map +1 -0
- package/dist/lib/nginx.test.d.ts +2 -0
- package/dist/lib/nginx.test.d.ts.map +1 -0
- package/dist/lib/nginx.test.js +46 -0
- package/dist/lib/nginx.test.js.map +1 -0
- package/dist/lib/paths.d.ts +13 -0
- package/dist/lib/paths.d.ts.map +1 -0
- package/dist/lib/paths.js +36 -0
- package/dist/lib/paths.js.map +1 -0
- package/dist/lib/paths.test.d.ts +2 -0
- package/dist/lib/paths.test.d.ts.map +1 -0
- package/dist/lib/paths.test.js +52 -0
- package/dist/lib/paths.test.js.map +1 -0
- package/package.json +34 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate nginx config from domains config; optionally install and reload.
|
|
3
|
+
*/
|
|
4
|
+
import { spawn } from "node:child_process";
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { parseDeployConfig } from "../lib/domains.js";
|
|
8
|
+
import { error, info, success, warn } from "../lib/logger.js";
|
|
9
|
+
import { generateNginxConf } from "../lib/nginx.js";
|
|
10
|
+
import { resolveConfigPath } from "../lib/paths.js";
|
|
11
|
+
const NGINX_CONF_NAME = "n2.conf";
|
|
12
|
+
export async function runNginx(opts) {
|
|
13
|
+
const configPath = resolveConfigPath(opts.config);
|
|
14
|
+
if (!fs.existsSync(configPath)) {
|
|
15
|
+
error(`配置文件不存在: ${configPath}`);
|
|
16
|
+
info("请先执行: n2-deploy config init");
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
const yaml = fs.readFileSync(configPath, "utf8");
|
|
20
|
+
const { domainsConfig } = parseDeployConfig(yaml);
|
|
21
|
+
const nginxConf = generateNginxConf(domainsConfig);
|
|
22
|
+
const outPath = path.resolve(process.cwd(), opts.output);
|
|
23
|
+
const outDir = path.dirname(outPath);
|
|
24
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
25
|
+
fs.writeFileSync(outPath, nginxConf);
|
|
26
|
+
info(`已写入: ${outPath}`);
|
|
27
|
+
if (opts.install) {
|
|
28
|
+
const destDir = detectNginxConfDir();
|
|
29
|
+
const destPath = path.join(destDir, NGINX_CONF_NAME);
|
|
30
|
+
try {
|
|
31
|
+
fs.copyFileSync(outPath, destPath);
|
|
32
|
+
info(`已安装到: ${destPath}`);
|
|
33
|
+
}
|
|
34
|
+
catch (e) {
|
|
35
|
+
error(`安装失败(可尝试 sudo): ${e}`);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
await nginxTestAndReload();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function detectNginxConfDir() {
|
|
42
|
+
if (fs.existsSync("/etc/nginx/conf.d"))
|
|
43
|
+
return "/etc/nginx/conf.d";
|
|
44
|
+
if (fs.existsSync("/etc/nginx/sites-available"))
|
|
45
|
+
return "/etc/nginx/sites-available";
|
|
46
|
+
return "/etc/nginx/conf.d";
|
|
47
|
+
}
|
|
48
|
+
function nginxTestAndReload() {
|
|
49
|
+
return new Promise((resolve, reject) => {
|
|
50
|
+
const t = spawn("nginx", ["-t"], { stdio: "inherit" });
|
|
51
|
+
t.on("close", code => {
|
|
52
|
+
if (code !== 0) {
|
|
53
|
+
reject(new Error("nginx -t failed"));
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const r = spawn("systemctl", ["reload", "nginx"], { stdio: "inherit" });
|
|
57
|
+
r.on("close", c => {
|
|
58
|
+
if (c === 0) {
|
|
59
|
+
success("Nginx 已重载");
|
|
60
|
+
resolve();
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
warn("systemctl reload nginx 失败,请尝试: sudo systemctl reload nginx");
|
|
64
|
+
resolve();
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
r.on("error", () => resolve());
|
|
68
|
+
});
|
|
69
|
+
t.on("error", () => reject(new Error("nginx not found")));
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=nginx.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nginx.js","sourceRoot":"","sources":["../../src/commands/nginx.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nginx.test.d.ts","sourceRoot":"","sources":["../../src/commands/nginx.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import { runNginx } from "./nginx.js";
|
|
6
|
+
describe("nginx command", () => {
|
|
7
|
+
let tmpDir;
|
|
8
|
+
let configPath;
|
|
9
|
+
let exitMock;
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
tmpDir = path.join(os.tmpdir(), `n2-nginx-${Date.now()}`);
|
|
12
|
+
fs.mkdirSync(tmpDir, { recursive: true });
|
|
13
|
+
configPath = path.join(tmpDir, "config.yaml");
|
|
14
|
+
exitMock = vi.spyOn(process, "exit").mockImplementation((code) => {
|
|
15
|
+
throw new Error(`exit:${code}`);
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
afterEach(() => {
|
|
19
|
+
exitMock.mockRestore();
|
|
20
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
21
|
+
});
|
|
22
|
+
it("exits when config file does not exist", async () => {
|
|
23
|
+
await expect(runNginx({
|
|
24
|
+
config: path.join(tmpDir, "missing.yaml"),
|
|
25
|
+
output: path.join(tmpDir, "out", "n2.conf"),
|
|
26
|
+
})).rejects.toThrow("exit:1");
|
|
27
|
+
expect(exitMock).toHaveBeenCalledWith(1);
|
|
28
|
+
});
|
|
29
|
+
it("writes nginx config to output path", async () => {
|
|
30
|
+
const yaml = `api:
|
|
31
|
+
backend_port: 3000
|
|
32
|
+
domains: []
|
|
33
|
+
|
|
34
|
+
admin:
|
|
35
|
+
domains:
|
|
36
|
+
- admin.example.com
|
|
37
|
+
|
|
38
|
+
tenant:
|
|
39
|
+
domains: []
|
|
40
|
+
|
|
41
|
+
client:
|
|
42
|
+
domains: []
|
|
43
|
+
`;
|
|
44
|
+
fs.writeFileSync(configPath, yaml, "utf8");
|
|
45
|
+
const outPath = path.join(tmpDir, "out", "n2.conf");
|
|
46
|
+
await runNginx({ config: configPath, output: outPath });
|
|
47
|
+
expect(exitMock).not.toHaveBeenCalled();
|
|
48
|
+
expect(fs.existsSync(outPath)).toBe(true);
|
|
49
|
+
const content = fs.readFileSync(outPath, "utf8");
|
|
50
|
+
expect(content).toContain("server_name admin.example.com");
|
|
51
|
+
expect(content).toContain("proxy_pass http://127.0.0.1:3000");
|
|
52
|
+
expect(content).toContain("listen 443 ssl http2");
|
|
53
|
+
expect(content).toContain("return 301 https://");
|
|
54
|
+
});
|
|
55
|
+
it("creates output directory", async () => {
|
|
56
|
+
const yaml = `api:
|
|
57
|
+
backend_port: 3000
|
|
58
|
+
domains: []
|
|
59
|
+
|
|
60
|
+
admin:
|
|
61
|
+
domains: []
|
|
62
|
+
|
|
63
|
+
tenant:
|
|
64
|
+
domains: []
|
|
65
|
+
|
|
66
|
+
client:
|
|
67
|
+
domains: []
|
|
68
|
+
`;
|
|
69
|
+
fs.writeFileSync(configPath, yaml, "utf8");
|
|
70
|
+
const outPath = path.join(tmpDir, "sub", "dir", "n2.conf");
|
|
71
|
+
await runNginx({ config: configPath, output: outPath });
|
|
72
|
+
expect(fs.existsSync(outPath)).toBe(true);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
//# sourceMappingURL=nginx.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nginx.test.js","sourceRoot":"","sources":["../../src/commands/nginx.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* View SSL log file: tail, lines, follow, optional filter by action/result.
|
|
3
|
+
*/
|
|
4
|
+
export interface SslLogsOptions {
|
|
5
|
+
/** Log file path (default: /opt/deploy/logs/ssl.log) */
|
|
6
|
+
logFile?: string;
|
|
7
|
+
/** Show last N lines (default: 50) */
|
|
8
|
+
lines?: number;
|
|
9
|
+
/** Follow (tail -f) */
|
|
10
|
+
follow?: boolean;
|
|
11
|
+
/** Filter: create | renew | success | failure | run */
|
|
12
|
+
action?: string;
|
|
13
|
+
/** Filter: ok | fail */
|
|
14
|
+
result?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function runSslLogs(opts: SslLogsOptions): Promise<void>;
|
|
17
|
+
//# sourceMappingURL=ssl-logs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssl-logs.d.ts","sourceRoot":"","sources":["../../src/commands/ssl-logs.ts"],"names":[],"mappings":"AAAA;;GAEG;AASH,MAAM,WAAW,cAAc;IAC7B,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uBAAuB;IACvB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wBAAwB;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAwDpE"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* View SSL log file: tail, lines, follow, optional filter by action/result.
|
|
3
|
+
*/
|
|
4
|
+
import consola from "consola";
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { getLogFilePath } from "../lib/logger.js";
|
|
8
|
+
const DEFAULT_SSL_LOG = "/opt/deploy/logs/ssl.log";
|
|
9
|
+
export async function runSslLogs(opts) {
|
|
10
|
+
const logPath = opts.logFile ?? getLogFilePath() ?? DEFAULT_SSL_LOG;
|
|
11
|
+
const resolved = path.resolve(process.cwd(), logPath);
|
|
12
|
+
if (!fs.existsSync(resolved)) {
|
|
13
|
+
consola.error("日志文件不存在:", resolved);
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
const lines = opts.lines ?? 50;
|
|
17
|
+
let content;
|
|
18
|
+
const stat = fs.statSync(resolved);
|
|
19
|
+
const fd = fs.openSync(resolved, "r");
|
|
20
|
+
try {
|
|
21
|
+
const buffer = Buffer.alloc(Math.min(stat.size, 256 * 1024));
|
|
22
|
+
const read = fs.readSync(fd, buffer, 0, buffer.length, Math.max(0, stat.size - buffer.length));
|
|
23
|
+
content = buffer.subarray(0, read).toString("utf8");
|
|
24
|
+
}
|
|
25
|
+
finally {
|
|
26
|
+
fs.closeSync(fd);
|
|
27
|
+
}
|
|
28
|
+
const allLines = content.split(/\n/).filter(l => l.length > 0);
|
|
29
|
+
const lastLines = allLines.slice(-lines);
|
|
30
|
+
const filter = (line) => {
|
|
31
|
+
if (opts.action || opts.result) {
|
|
32
|
+
const parts = line.split("\t");
|
|
33
|
+
if (parts.length >= 5) {
|
|
34
|
+
const [, , action, , result] = parts;
|
|
35
|
+
if (opts.action && action !== opts.action)
|
|
36
|
+
return false;
|
|
37
|
+
if (opts.result && result !== opts.result)
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return true;
|
|
42
|
+
};
|
|
43
|
+
const filtered = opts.action || opts.result ? lastLines.filter(filter) : lastLines;
|
|
44
|
+
for (const line of filtered) {
|
|
45
|
+
consola.log(line);
|
|
46
|
+
}
|
|
47
|
+
if (opts.follow) {
|
|
48
|
+
const { spawn } = await import("node:child_process");
|
|
49
|
+
const tail = spawn("tail", ["-n", String(lines), "-f", resolved], {
|
|
50
|
+
stdio: "inherit",
|
|
51
|
+
});
|
|
52
|
+
tail.on("close", code => process.exit(code ?? 0));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=ssl-logs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssl-logs.js","sourceRoot":"","sources":["../../src/commands/ssl-logs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssl-logs.test.d.ts","sourceRoot":"","sources":["../../src/commands/ssl-logs.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import { runSslLogs } from "./ssl-logs.js";
|
|
6
|
+
describe("ssl-logs command", () => {
|
|
7
|
+
let tmpDir;
|
|
8
|
+
let logPath;
|
|
9
|
+
let exitMock;
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
tmpDir = path.join(os.tmpdir(), `n2-ssl-logs-${Date.now()}`);
|
|
12
|
+
fs.mkdirSync(tmpDir, { recursive: true });
|
|
13
|
+
logPath = path.join(tmpDir, "ssl.log");
|
|
14
|
+
exitMock = vi.spyOn(process, "exit").mockImplementation((code) => {
|
|
15
|
+
throw new Error(`exit:${code}`);
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
afterEach(() => {
|
|
19
|
+
exitMock.mockRestore();
|
|
20
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
21
|
+
});
|
|
22
|
+
it("exits when log file does not exist", async () => {
|
|
23
|
+
await expect(runSslLogs({ logFile: path.join(tmpDir, "nonexistent.log") })).rejects.toThrow("exit:1");
|
|
24
|
+
expect(exitMock).toHaveBeenCalledWith(1);
|
|
25
|
+
});
|
|
26
|
+
it("reads and outputs last N lines", async () => {
|
|
27
|
+
const lines = Array.from({ length: 100 }, (_, i) => `line-${i + 1}`);
|
|
28
|
+
fs.writeFileSync(logPath, lines.join("\n"), "utf8");
|
|
29
|
+
const consola = await import("consola");
|
|
30
|
+
const logSpy = vi.spyOn(consola.default, "log").mockImplementation(() => { });
|
|
31
|
+
await runSslLogs({ logFile: logPath, lines: 10 });
|
|
32
|
+
expect(exitMock).not.toHaveBeenCalled();
|
|
33
|
+
expect(logSpy).toHaveBeenCalled();
|
|
34
|
+
const lastCalls = logSpy.mock.calls.slice(-10);
|
|
35
|
+
expect(lastCalls.length).toBeLessThanOrEqual(10);
|
|
36
|
+
logSpy.mockRestore();
|
|
37
|
+
});
|
|
38
|
+
it("filters by action and result when provided", async () => {
|
|
39
|
+
// SSL log format: time \t ssl \t action \t domain \t result \t message
|
|
40
|
+
const logContent = [
|
|
41
|
+
"2025-01-01 00:00:00\tssl\tcreate\tdomain.com\tok\t",
|
|
42
|
+
"2025-01-01 00:00:01\tssl\trenew\tdomain.com\tfail\t",
|
|
43
|
+
"2025-01-01 00:00:02\tssl\tsuccess\tdomain.com\tok\t",
|
|
44
|
+
].join("\n");
|
|
45
|
+
fs.writeFileSync(logPath, logContent, "utf8");
|
|
46
|
+
const consola = await import("consola");
|
|
47
|
+
const logSpy = vi.spyOn(consola.default, "log").mockImplementation(() => { });
|
|
48
|
+
await runSslLogs({ logFile: logPath, lines: 50, action: "create", result: "ok" });
|
|
49
|
+
expect(exitMock).not.toHaveBeenCalled();
|
|
50
|
+
expect(logSpy).toHaveBeenCalledWith("2025-01-01 00:00:00\tssl\tcreate\tdomain.com\tok\t");
|
|
51
|
+
logSpy.mockRestore();
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
//# sourceMappingURL=ssl-logs.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssl-logs.test.js","sourceRoot":"","sources":["../../src/commands/ssl-logs.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,IAAI,MAAc,CAAC;IACnB,IAAI,OAAe,CAAC;IACpB,IAAI,QAAqC,CAAC;IAE1C,UAAU,CAAC,GAAG,EAAE;QACd,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,eAAe,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAC7D,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1C,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QACvC,QAAQ,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC,IAA6B,EAAE,EAAE;YACxF,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;QAClC,CAAC,CAA6B,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,QAAQ,CAAC,WAAW,EAAE,CAAC;QACvB,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;QAClD,MAAM,MAAM,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACtG,MAAM,CAAC,QAAQ,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;QAC9C,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACrE,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;QACpD,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;QACxC,MAAM,MAAM,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC7E,MAAM,UAAU,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;QAClD,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,CAAC,gBAAgB,EAAE,CAAC;QAClC,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/C,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC;QACjD,MAAM,CAAC,WAAW,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC1D,uEAAuE;QACvE,MAAM,UAAU,GAAG;YACjB,oDAAoD;YACpD,qDAAqD;YACrD,qDAAqD;SACtD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;QAC9C,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;QACxC,MAAM,MAAM,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC7E,MAAM,UAAU,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAClF,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,CAAC,oBAAoB,CAAC,oDAAoD,CAAC,CAAC;QAC1F,MAAM,CAAC,WAAW,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSL certificate setup/renew for all domains from config.
|
|
3
|
+
* Runs check-and-setup-ssl.sh; all output and structured events go to SSL log file.
|
|
4
|
+
*/
|
|
5
|
+
export interface SslOptions {
|
|
6
|
+
config: string;
|
|
7
|
+
/** Ali key (or ALIYUN_ACCESS_KEY_ID / Ali_Key env) */
|
|
8
|
+
aliKey?: string;
|
|
9
|
+
/** Ali secret (or ALIYUN_ACCESS_KEY_SECRET / Ali_Secret env) */
|
|
10
|
+
aliSecret?: string;
|
|
11
|
+
logFile?: string;
|
|
12
|
+
/** Path to deploy scripts (default: N2_DEPLOY_SCRIPTS_DIR or package assets/deploy) */
|
|
13
|
+
scriptsDir?: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function runSsl(opts: SslOptions): Promise<void>;
|
|
16
|
+
//# sourceMappingURL=ssl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssl.d.ts","sourceRoot":"","sources":["../../src/commands/ssl.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAkBH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uFAAuF;IACvF,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAsH5D"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSL certificate setup/renew for all domains from config.
|
|
3
|
+
* Runs check-and-setup-ssl.sh; all output and structured events go to SSL log file.
|
|
4
|
+
*/
|
|
5
|
+
import { spawn } from "node:child_process";
|
|
6
|
+
import fs from "node:fs";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import { getAllDomains, parseDeployConfig } from "../lib/domains.js";
|
|
9
|
+
import { appendRaw, appendSslLog, error, info, setLogFile, success, } from "../lib/logger.js";
|
|
10
|
+
import { getScriptsDir, resolveConfigPath } from "../lib/paths.js";
|
|
11
|
+
const DEFAULT_SSL_LOG = "/opt/deploy/logs/ssl.log";
|
|
12
|
+
export async function runSsl(opts) {
|
|
13
|
+
const configPath = resolveConfigPath(opts.config);
|
|
14
|
+
if (!fs.existsSync(configPath)) {
|
|
15
|
+
error(`配置文件不存在: ${configPath}`);
|
|
16
|
+
info("请先执行: n2-deploy config init");
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
const yaml = fs.readFileSync(configPath, "utf8");
|
|
20
|
+
const { domainsConfig, aliyunAccessKeyId: configAliId, aliyunAccessKeySecret: configAliSecret, } = parseDeployConfig(yaml);
|
|
21
|
+
const aliKey = opts.aliKey ??
|
|
22
|
+
configAliId ??
|
|
23
|
+
process.env.ALIYUN_ACCESS_KEY_ID ??
|
|
24
|
+
process.env.Ali_Key;
|
|
25
|
+
const aliSecret = opts.aliSecret ??
|
|
26
|
+
configAliSecret ??
|
|
27
|
+
process.env.ALIYUN_ACCESS_KEY_SECRET ??
|
|
28
|
+
process.env.Ali_Secret;
|
|
29
|
+
if (!aliKey || !aliSecret) {
|
|
30
|
+
error("缺少阿里云 API 凭证");
|
|
31
|
+
info("请在配置 (~/.deploy/config.yaml)、--ali-key/--ali-secret 或环境变量 ALIYUN_ACCESS_KEY_ID/ALIYUN_ACCESS_KEY_SECRET 中设置");
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
const domains = getAllDomains(domainsConfig);
|
|
35
|
+
const domainsTxt = domains.join("\n") + "\n";
|
|
36
|
+
const logPath = opts.logFile ?? DEFAULT_SSL_LOG;
|
|
37
|
+
setLogFile(logPath);
|
|
38
|
+
const logDir = path.dirname(logPath);
|
|
39
|
+
fs.mkdirSync(logDir, { recursive: true });
|
|
40
|
+
info(`SSL 日志: ${logPath}`);
|
|
41
|
+
info(`域名: ${domains.join(", ") || "(无)"}`);
|
|
42
|
+
const scriptsDir = opts.scriptsDir ||
|
|
43
|
+
process.env.N2_DEPLOY_SCRIPTS_DIR ||
|
|
44
|
+
getScriptsDir(process.cwd());
|
|
45
|
+
let scriptPath;
|
|
46
|
+
let domainsFilePath;
|
|
47
|
+
if (fs.existsSync("/opt/ssl/check-and-setup-ssl.sh")) {
|
|
48
|
+
scriptPath = "/opt/ssl/check-and-setup-ssl.sh";
|
|
49
|
+
domainsFilePath = "/opt/ssl/domains.txt";
|
|
50
|
+
fs.writeFileSync(domainsFilePath, domainsTxt);
|
|
51
|
+
info("已更新 /opt/ssl/domains.txt");
|
|
52
|
+
}
|
|
53
|
+
else if (scriptsDir &&
|
|
54
|
+
fs.existsSync(path.join(scriptsDir, "ssl", "check-and-setup-ssl.sh"))) {
|
|
55
|
+
scriptPath = path.join(scriptsDir, "ssl", "check-and-setup-ssl.sh");
|
|
56
|
+
const tmpDomains = path.join(logDir, "domains.txt");
|
|
57
|
+
fs.writeFileSync(tmpDomains, domainsTxt);
|
|
58
|
+
domainsFilePath = tmpDomains;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
error("未找到 SSL 脚本");
|
|
62
|
+
info("请先执行 n2-deploy init 或设置 N2_DEPLOY_SCRIPTS_DIR");
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
appendSslLog("run", "", "ok", "start");
|
|
66
|
+
await new Promise((resolve, reject) => {
|
|
67
|
+
const child = spawn("bash", [scriptPath, "--ali-key", aliKey, "--ali-secret", aliSecret], {
|
|
68
|
+
env: {
|
|
69
|
+
...process.env,
|
|
70
|
+
Ali_Key: aliKey,
|
|
71
|
+
Ali_Secret: aliSecret,
|
|
72
|
+
DOMAINS_FILE: domainsFilePath,
|
|
73
|
+
},
|
|
74
|
+
stdio: ["inherit", "pipe", "pipe"],
|
|
75
|
+
});
|
|
76
|
+
const appendOut = (data) => {
|
|
77
|
+
const s = data.toString();
|
|
78
|
+
process.stdout.write(s);
|
|
79
|
+
appendRaw(s.trimEnd());
|
|
80
|
+
};
|
|
81
|
+
child.stdout?.on("data", appendOut);
|
|
82
|
+
child.stderr?.on("data", data => {
|
|
83
|
+
const s = data.toString();
|
|
84
|
+
process.stderr.write(s);
|
|
85
|
+
appendRaw(s.trimEnd());
|
|
86
|
+
});
|
|
87
|
+
child.on("close", (code, signal) => {
|
|
88
|
+
if (code === 0) {
|
|
89
|
+
appendSslLog("run", "", "ok", "done");
|
|
90
|
+
success("SSL 证书配置完成");
|
|
91
|
+
resolve();
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
appendSslLog("run", "", "fail", `exit ${code} ${signal ?? ""}`);
|
|
95
|
+
error(`SSL script exited with code ${code}`);
|
|
96
|
+
reject(new Error(`SSL script exited with ${code}`));
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
child.on("error", err => {
|
|
100
|
+
appendSslLog("run", "", "fail", err.message);
|
|
101
|
+
reject(err);
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=ssl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssl.js","sourceRoot":"","sources":["../../src/commands/ssl.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssl.test.d.ts","sourceRoot":"","sources":["../../src/commands/ssl.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import { runSsl } from "./ssl.js";
|
|
6
|
+
const mockSpawn = vi.fn();
|
|
7
|
+
vi.mock("node:child_process", () => ({
|
|
8
|
+
spawn: (...args) => mockSpawn(...args),
|
|
9
|
+
}));
|
|
10
|
+
describe("ssl command", () => {
|
|
11
|
+
let tmpDir;
|
|
12
|
+
let configPath;
|
|
13
|
+
let scriptsDir;
|
|
14
|
+
let exitMock;
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
tmpDir = path.join(os.tmpdir(), `n2-ssl-${Date.now()}`);
|
|
17
|
+
fs.mkdirSync(tmpDir, { recursive: true });
|
|
18
|
+
configPath = path.join(tmpDir, "config.yaml");
|
|
19
|
+
scriptsDir = path.join(tmpDir, "scripts");
|
|
20
|
+
const sslDir = path.join(scriptsDir, "ssl");
|
|
21
|
+
fs.mkdirSync(sslDir, { recursive: true });
|
|
22
|
+
fs.writeFileSync(path.join(sslDir, "check-and-setup-ssl.sh"), "#!/bin/bash\nexit 0", "utf8");
|
|
23
|
+
exitMock = vi.spyOn(process, "exit").mockImplementation((code) => {
|
|
24
|
+
throw new Error(`exit:${code}`);
|
|
25
|
+
});
|
|
26
|
+
mockSpawn.mockReturnValue({
|
|
27
|
+
on: (ev, cb) => {
|
|
28
|
+
if (ev === "close")
|
|
29
|
+
setImmediate(() => cb(0));
|
|
30
|
+
if (ev === "error")
|
|
31
|
+
return;
|
|
32
|
+
return {};
|
|
33
|
+
},
|
|
34
|
+
stdout: { on: () => { } },
|
|
35
|
+
stderr: { on: () => { } },
|
|
36
|
+
stdio: "inherit",
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
afterEach(() => {
|
|
40
|
+
exitMock.mockRestore();
|
|
41
|
+
mockSpawn.mockClear();
|
|
42
|
+
vi.unstubAllEnvs();
|
|
43
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
44
|
+
});
|
|
45
|
+
it("exits when config file does not exist", async () => {
|
|
46
|
+
await expect(runSsl({ config: path.join(tmpDir, "missing.yaml") })).rejects.toThrow("exit:1");
|
|
47
|
+
expect(exitMock).toHaveBeenCalledWith(1);
|
|
48
|
+
});
|
|
49
|
+
it("exits when aliyun credentials are missing", async () => {
|
|
50
|
+
const yaml = `api:
|
|
51
|
+
backend_port: 3000
|
|
52
|
+
domains: []
|
|
53
|
+
|
|
54
|
+
admin:
|
|
55
|
+
domains: []
|
|
56
|
+
|
|
57
|
+
tenant:
|
|
58
|
+
domains: []
|
|
59
|
+
|
|
60
|
+
client:
|
|
61
|
+
domains: []
|
|
62
|
+
`;
|
|
63
|
+
fs.writeFileSync(configPath, yaml, "utf8");
|
|
64
|
+
await expect(runSsl({ config: configPath, scriptsDir })).rejects.toThrow("exit:1");
|
|
65
|
+
expect(exitMock).toHaveBeenCalledWith(1);
|
|
66
|
+
});
|
|
67
|
+
it("runs ssl script when credentials provided", async () => {
|
|
68
|
+
const yaml = `api:
|
|
69
|
+
backend_port: 3000
|
|
70
|
+
domains: []
|
|
71
|
+
|
|
72
|
+
admin:
|
|
73
|
+
domains: []
|
|
74
|
+
|
|
75
|
+
tenant:
|
|
76
|
+
domains: []
|
|
77
|
+
|
|
78
|
+
client:
|
|
79
|
+
domains: []
|
|
80
|
+
`;
|
|
81
|
+
fs.writeFileSync(configPath, yaml, "utf8");
|
|
82
|
+
const logDir = path.join(tmpDir, "logs");
|
|
83
|
+
fs.mkdirSync(logDir, { recursive: true });
|
|
84
|
+
await runSsl({
|
|
85
|
+
config: configPath,
|
|
86
|
+
scriptsDir,
|
|
87
|
+
aliKey: "key",
|
|
88
|
+
aliSecret: "secret",
|
|
89
|
+
logFile: path.join(logDir, "ssl.log"),
|
|
90
|
+
});
|
|
91
|
+
expect(exitMock).not.toHaveBeenCalled();
|
|
92
|
+
expect(mockSpawn).toHaveBeenCalledWith("bash", expect.arrayContaining([expect.stringContaining("check-and-setup-ssl.sh"), "--ali-key", "key", "--ali-secret", "secret"]), expect.any(Object));
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
//# sourceMappingURL=ssl.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssl.test.js","sourceRoot":"","sources":["../../src/commands/ssl.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config file CRUD: load, get, set, delete, save for ~/.deploy/config.yaml.
|
|
3
|
+
* Keys: aliyun_access_key_id, aliyun_access_key_secret, api.backend_port,
|
|
4
|
+
* api.domains, admin.domains, tenant.domains, client.domains
|
|
5
|
+
*/
|
|
6
|
+
import type { DeployConfigResult } from "./domains.js";
|
|
7
|
+
export type ConfigKey = "aliyun_access_key_id" | "aliyun_access_key_secret" | "api.backend_port" | "api.domains" | "admin.domains" | "tenant.domains" | "client.domains";
|
|
8
|
+
export declare function isValidConfigKey(key: string): key is ConfigKey;
|
|
9
|
+
export declare function loadConfig(configPath: string): DeployConfigResult;
|
|
10
|
+
export declare function saveConfig(configPath: string, data: DeployConfigResult): void;
|
|
11
|
+
export declare function getConfigValue(data: DeployConfigResult, key: ConfigKey): string | number | string[] | undefined;
|
|
12
|
+
export declare function setConfigValue(data: DeployConfigResult, key: ConfigKey, value: string | number | string[]): void;
|
|
13
|
+
export declare function deleteConfigValue(data: DeployConfigResult, key: ConfigKey): void;
|
|
14
|
+
//# sourceMappingURL=config-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-store.d.ts","sourceRoot":"","sources":["../../src/lib/config-store.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAGvD,MAAM,MAAM,SAAS,GACjB,sBAAsB,GACtB,0BAA0B,GAC1B,kBAAkB,GAClB,aAAa,GACb,eAAe,GACf,gBAAgB,GAChB,gBAAgB,CAAC;AAUrB,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,IAAI,SAAS,CAM9D;AAED,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,kBAAkB,CAGjE;AAED,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,GAAG,IAAI,CAM7E;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,kBAAkB,EACxB,GAAG,EAAE,SAAS,GACb,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAmBxC;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,kBAAkB,EACxB,GAAG,EAAE,SAAS,EACd,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,GAChC,IAAI,CAiCN;AAED,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,kBAAkB,EACxB,GAAG,EAAE,SAAS,GACb,IAAI,CAwBN"}
|