@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.
Files changed (92) hide show
  1. package/README.md +92 -0
  2. package/assets/deploy/deploy.sh +172 -0
  3. package/assets/deploy/domains.yaml +18 -0
  4. package/assets/deploy/lib/common.sh +62 -0
  5. package/assets/deploy/nginx/n2.conf +162 -0
  6. package/assets/deploy/server-setup.sh +285 -0
  7. package/assets/deploy/ssl/README.md +320 -0
  8. package/assets/deploy/ssl/check-and-setup-ssl.sh +222 -0
  9. package/assets/deploy/ssl/domains.txt +3 -0
  10. package/assets/deploy/ssl/renew-ssl.sh +236 -0
  11. package/assets/deploy/ssl/setup-ssl.sh +474 -0
  12. package/dist/cli.d.ts +7 -0
  13. package/dist/cli.d.ts.map +1 -0
  14. package/dist/cli.js +186 -0
  15. package/dist/cli.js.map +1 -0
  16. package/dist/commands/config.d.ts +29 -0
  17. package/dist/commands/config.d.ts.map +1 -0
  18. package/dist/commands/config.js +134 -0
  19. package/dist/commands/config.js.map +1 -0
  20. package/dist/commands/config.test.d.ts +2 -0
  21. package/dist/commands/config.test.d.ts.map +1 -0
  22. package/dist/commands/config.test.js +215 -0
  23. package/dist/commands/config.test.js.map +1 -0
  24. package/dist/commands/init.d.ts +10 -0
  25. package/dist/commands/init.d.ts.map +1 -0
  26. package/dist/commands/init.js +106 -0
  27. package/dist/commands/init.js.map +1 -0
  28. package/dist/commands/init.test.d.ts +2 -0
  29. package/dist/commands/init.test.d.ts.map +1 -0
  30. package/dist/commands/init.test.js +70 -0
  31. package/dist/commands/init.test.js.map +1 -0
  32. package/dist/commands/nginx.d.ts +10 -0
  33. package/dist/commands/nginx.d.ts.map +1 -0
  34. package/dist/commands/nginx.js +72 -0
  35. package/dist/commands/nginx.js.map +1 -0
  36. package/dist/commands/nginx.test.d.ts +2 -0
  37. package/dist/commands/nginx.test.d.ts.map +1 -0
  38. package/dist/commands/nginx.test.js +75 -0
  39. package/dist/commands/nginx.test.js.map +1 -0
  40. package/dist/commands/ssl-logs.d.ts +17 -0
  41. package/dist/commands/ssl-logs.d.ts.map +1 -0
  42. package/dist/commands/ssl-logs.js +55 -0
  43. package/dist/commands/ssl-logs.js.map +1 -0
  44. package/dist/commands/ssl-logs.test.d.ts +2 -0
  45. package/dist/commands/ssl-logs.test.d.ts.map +1 -0
  46. package/dist/commands/ssl-logs.test.js +54 -0
  47. package/dist/commands/ssl-logs.test.js.map +1 -0
  48. package/dist/commands/ssl.d.ts +16 -0
  49. package/dist/commands/ssl.d.ts.map +1 -0
  50. package/dist/commands/ssl.js +105 -0
  51. package/dist/commands/ssl.js.map +1 -0
  52. package/dist/commands/ssl.test.d.ts +2 -0
  53. package/dist/commands/ssl.test.d.ts.map +1 -0
  54. package/dist/commands/ssl.test.js +95 -0
  55. package/dist/commands/ssl.test.js.map +1 -0
  56. package/dist/lib/config-store.d.ts +14 -0
  57. package/dist/lib/config-store.d.ts.map +1 -0
  58. package/dist/lib/config-store.js +111 -0
  59. package/dist/lib/config-store.js.map +1 -0
  60. package/dist/lib/config-store.test.d.ts +2 -0
  61. package/dist/lib/config-store.test.d.ts.map +1 -0
  62. package/dist/lib/config-store.test.js +173 -0
  63. package/dist/lib/config-store.test.js.map +1 -0
  64. package/dist/lib/domains.d.ts +37 -0
  65. package/dist/lib/domains.d.ts.map +1 -0
  66. package/dist/lib/domains.js +134 -0
  67. package/dist/lib/domains.js.map +1 -0
  68. package/dist/lib/domains.test.d.ts +2 -0
  69. package/dist/lib/domains.test.d.ts.map +1 -0
  70. package/dist/lib/domains.test.js +141 -0
  71. package/dist/lib/domains.test.js.map +1 -0
  72. package/dist/lib/logger.d.ts +19 -0
  73. package/dist/lib/logger.d.ts.map +1 -0
  74. package/dist/lib/logger.js +58 -0
  75. package/dist/lib/logger.js.map +1 -0
  76. package/dist/lib/nginx.d.ts +7 -0
  77. package/dist/lib/nginx.d.ts.map +1 -0
  78. package/dist/lib/nginx.js +86 -0
  79. package/dist/lib/nginx.js.map +1 -0
  80. package/dist/lib/nginx.test.d.ts +2 -0
  81. package/dist/lib/nginx.test.d.ts.map +1 -0
  82. package/dist/lib/nginx.test.js +46 -0
  83. package/dist/lib/nginx.test.js.map +1 -0
  84. package/dist/lib/paths.d.ts +13 -0
  85. package/dist/lib/paths.d.ts.map +1 -0
  86. package/dist/lib/paths.js +36 -0
  87. package/dist/lib/paths.js.map +1 -0
  88. package/dist/lib/paths.test.d.ts +2 -0
  89. package/dist/lib/paths.test.d.ts.map +1 -0
  90. package/dist/lib/paths.test.js +52 -0
  91. package/dist/lib/paths.test.js.map +1 -0
  92. 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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=nginx.test.d.ts.map
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ssl-logs.test.d.ts.map
@@ -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":"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"}
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ssl.test.d.ts.map
@@ -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"}