@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,111 @@
|
|
|
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 fs from "node:fs";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import { parseDeployConfig, serializeDeployConfig } from "./domains.js";
|
|
9
|
+
const SECTION_KEYS = [
|
|
10
|
+
"api.backend_port",
|
|
11
|
+
"api.domains",
|
|
12
|
+
"admin.domains",
|
|
13
|
+
"tenant.domains",
|
|
14
|
+
"client.domains",
|
|
15
|
+
];
|
|
16
|
+
export function isValidConfigKey(key) {
|
|
17
|
+
return (key === "aliyun_access_key_id" ||
|
|
18
|
+
key === "aliyun_access_key_secret" ||
|
|
19
|
+
SECTION_KEYS.includes(key));
|
|
20
|
+
}
|
|
21
|
+
export function loadConfig(configPath) {
|
|
22
|
+
const content = fs.readFileSync(configPath, "utf8");
|
|
23
|
+
return parseDeployConfig(content);
|
|
24
|
+
}
|
|
25
|
+
export function saveConfig(configPath, data) {
|
|
26
|
+
const dir = path.dirname(configPath);
|
|
27
|
+
if (dir && dir !== ".") {
|
|
28
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
29
|
+
}
|
|
30
|
+
fs.writeFileSync(configPath, serializeDeployConfig(data), "utf8");
|
|
31
|
+
}
|
|
32
|
+
export function getConfigValue(data, key) {
|
|
33
|
+
switch (key) {
|
|
34
|
+
case "aliyun_access_key_id":
|
|
35
|
+
return data.aliyunAccessKeyId;
|
|
36
|
+
case "aliyun_access_key_secret":
|
|
37
|
+
return data.aliyunAccessKeySecret;
|
|
38
|
+
case "api.backend_port":
|
|
39
|
+
return data.domainsConfig.api.backend_port;
|
|
40
|
+
case "api.domains":
|
|
41
|
+
return data.domainsConfig.api.domains;
|
|
42
|
+
case "admin.domains":
|
|
43
|
+
return data.domainsConfig.admin.domains;
|
|
44
|
+
case "tenant.domains":
|
|
45
|
+
return data.domainsConfig.tenant.domains;
|
|
46
|
+
case "client.domains":
|
|
47
|
+
return data.domainsConfig.client.domains;
|
|
48
|
+
default:
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
export function setConfigValue(data, key, value) {
|
|
53
|
+
switch (key) {
|
|
54
|
+
case "aliyun_access_key_id":
|
|
55
|
+
data.aliyunAccessKeyId = String(value);
|
|
56
|
+
break;
|
|
57
|
+
case "aliyun_access_key_secret":
|
|
58
|
+
data.aliyunAccessKeySecret = String(value);
|
|
59
|
+
break;
|
|
60
|
+
case "api.backend_port":
|
|
61
|
+
data.domainsConfig.api.backend_port =
|
|
62
|
+
typeof value === "number" ? value : parseInt(String(value), 10);
|
|
63
|
+
break;
|
|
64
|
+
case "api.domains":
|
|
65
|
+
data.domainsConfig.api.domains = Array.isArray(value)
|
|
66
|
+
? value
|
|
67
|
+
: [String(value)];
|
|
68
|
+
break;
|
|
69
|
+
case "admin.domains":
|
|
70
|
+
data.domainsConfig.admin.domains = Array.isArray(value)
|
|
71
|
+
? value
|
|
72
|
+
: [String(value)];
|
|
73
|
+
break;
|
|
74
|
+
case "tenant.domains":
|
|
75
|
+
data.domainsConfig.tenant.domains = Array.isArray(value)
|
|
76
|
+
? value
|
|
77
|
+
: [String(value)];
|
|
78
|
+
break;
|
|
79
|
+
case "client.domains":
|
|
80
|
+
data.domainsConfig.client.domains = Array.isArray(value)
|
|
81
|
+
? value
|
|
82
|
+
: [String(value)];
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
export function deleteConfigValue(data, key) {
|
|
87
|
+
switch (key) {
|
|
88
|
+
case "aliyun_access_key_id":
|
|
89
|
+
data.aliyunAccessKeyId = undefined;
|
|
90
|
+
break;
|
|
91
|
+
case "aliyun_access_key_secret":
|
|
92
|
+
data.aliyunAccessKeySecret = undefined;
|
|
93
|
+
break;
|
|
94
|
+
case "api.backend_port":
|
|
95
|
+
data.domainsConfig.api.backend_port = 3000;
|
|
96
|
+
break;
|
|
97
|
+
case "api.domains":
|
|
98
|
+
data.domainsConfig.api.domains = [];
|
|
99
|
+
break;
|
|
100
|
+
case "admin.domains":
|
|
101
|
+
data.domainsConfig.admin.domains = [];
|
|
102
|
+
break;
|
|
103
|
+
case "tenant.domains":
|
|
104
|
+
data.domainsConfig.tenant.domains = [];
|
|
105
|
+
break;
|
|
106
|
+
case "client.domains":
|
|
107
|
+
data.domainsConfig.client.domains = [];
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=config-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-store.js","sourceRoot":"","sources":["../../src/lib/config-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-store.test.d.ts","sourceRoot":"","sources":["../../src/lib/config-store.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import { isValidConfigKey, loadConfig, saveConfig, getConfigValue, setConfigValue, deleteConfigValue, } from "./config-store.js";
|
|
6
|
+
describe("config-store", () => {
|
|
7
|
+
let tmpDir;
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
tmpDir = path.join(os.tmpdir(), `n2-config-store-${Date.now()}`);
|
|
10
|
+
fs.mkdirSync(tmpDir, { recursive: true });
|
|
11
|
+
});
|
|
12
|
+
afterEach(() => {
|
|
13
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
14
|
+
});
|
|
15
|
+
describe("isValidConfigKey", () => {
|
|
16
|
+
it("returns true for valid keys", () => {
|
|
17
|
+
expect(isValidConfigKey("aliyun_access_key_id")).toBe(true);
|
|
18
|
+
expect(isValidConfigKey("aliyun_access_key_secret")).toBe(true);
|
|
19
|
+
expect(isValidConfigKey("api.backend_port")).toBe(true);
|
|
20
|
+
expect(isValidConfigKey("api.domains")).toBe(true);
|
|
21
|
+
expect(isValidConfigKey("admin.domains")).toBe(true);
|
|
22
|
+
expect(isValidConfigKey("tenant.domains")).toBe(true);
|
|
23
|
+
expect(isValidConfigKey("client.domains")).toBe(true);
|
|
24
|
+
});
|
|
25
|
+
it("returns false for invalid keys", () => {
|
|
26
|
+
expect(isValidConfigKey("foo")).toBe(false);
|
|
27
|
+
expect(isValidConfigKey("api.port")).toBe(false);
|
|
28
|
+
expect(isValidConfigKey("")).toBe(false);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
describe("loadConfig / saveConfig", () => {
|
|
32
|
+
it("loads and parses deploy config", () => {
|
|
33
|
+
const configPath = path.join(tmpDir, "config.yaml");
|
|
34
|
+
const yaml = `aliyun_access_key_id: "my-key"
|
|
35
|
+
aliyun_access_key_secret: "my-secret"
|
|
36
|
+
|
|
37
|
+
api:
|
|
38
|
+
backend_port: 4000
|
|
39
|
+
domains:
|
|
40
|
+
- api.example.com
|
|
41
|
+
|
|
42
|
+
admin:
|
|
43
|
+
domains:
|
|
44
|
+
- admin.example.com
|
|
45
|
+
|
|
46
|
+
tenant:
|
|
47
|
+
domains: []
|
|
48
|
+
|
|
49
|
+
client:
|
|
50
|
+
domains: []
|
|
51
|
+
`;
|
|
52
|
+
fs.writeFileSync(configPath, yaml, "utf8");
|
|
53
|
+
const data = loadConfig(configPath);
|
|
54
|
+
expect(data.aliyunAccessKeyId).toBe("my-key");
|
|
55
|
+
expect(data.aliyunAccessKeySecret).toBe("my-secret");
|
|
56
|
+
expect(data.domainsConfig.api.backend_port).toBe(4000);
|
|
57
|
+
expect(data.domainsConfig.api.domains).toEqual(["api.example.com"]);
|
|
58
|
+
expect(data.domainsConfig.admin.domains).toEqual(["admin.example.com"]);
|
|
59
|
+
expect(data.domainsConfig.tenant.domains).toEqual([]);
|
|
60
|
+
expect(data.domainsConfig.client.domains).toEqual([]);
|
|
61
|
+
});
|
|
62
|
+
it("saveConfig writes back and loadConfig round-trips", () => {
|
|
63
|
+
const configPath = path.join(tmpDir, "config.yaml");
|
|
64
|
+
const yaml = `api:
|
|
65
|
+
backend_port: 3000
|
|
66
|
+
domains: []
|
|
67
|
+
|
|
68
|
+
admin:
|
|
69
|
+
domains: []
|
|
70
|
+
|
|
71
|
+
tenant:
|
|
72
|
+
domains: []
|
|
73
|
+
|
|
74
|
+
client:
|
|
75
|
+
domains: []
|
|
76
|
+
`;
|
|
77
|
+
fs.writeFileSync(configPath, yaml, "utf8");
|
|
78
|
+
const data = loadConfig(configPath);
|
|
79
|
+
data.aliyunAccessKeyId = "new-key";
|
|
80
|
+
data.domainsConfig.admin.domains = ["a.com", "b.com"];
|
|
81
|
+
saveConfig(configPath, data);
|
|
82
|
+
const loaded = loadConfig(configPath);
|
|
83
|
+
expect(loaded.aliyunAccessKeyId).toBe("new-key");
|
|
84
|
+
expect(loaded.domainsConfig.admin.domains).toEqual(["a.com", "b.com"]);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
describe("getConfigValue", () => {
|
|
88
|
+
it("returns value for each key", () => {
|
|
89
|
+
const configPath = path.join(tmpDir, "config.yaml");
|
|
90
|
+
const yaml = `aliyun_access_key_id: "key"
|
|
91
|
+
aliyun_access_key_secret: "secret"
|
|
92
|
+
|
|
93
|
+
api:
|
|
94
|
+
backend_port: 5000
|
|
95
|
+
domains:
|
|
96
|
+
- x.com
|
|
97
|
+
|
|
98
|
+
admin:
|
|
99
|
+
domains: []
|
|
100
|
+
|
|
101
|
+
tenant:
|
|
102
|
+
domains: []
|
|
103
|
+
|
|
104
|
+
client:
|
|
105
|
+
domains: []
|
|
106
|
+
`;
|
|
107
|
+
fs.writeFileSync(configPath, yaml, "utf8");
|
|
108
|
+
const data = loadConfig(configPath);
|
|
109
|
+
expect(getConfigValue(data, "aliyun_access_key_id")).toBe("key");
|
|
110
|
+
expect(getConfigValue(data, "aliyun_access_key_secret")).toBe("secret");
|
|
111
|
+
expect(getConfigValue(data, "api.backend_port")).toBe(5000);
|
|
112
|
+
expect(getConfigValue(data, "api.domains")).toEqual(["x.com"]);
|
|
113
|
+
expect(getConfigValue(data, "admin.domains")).toEqual([]);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
describe("setConfigValue", () => {
|
|
117
|
+
it("sets string keys", () => {
|
|
118
|
+
const configPath = path.join(tmpDir, "config.yaml");
|
|
119
|
+
fs.writeFileSync(configPath, "api:\n backend_port: 3000\n domains: []\n\nadmin:\n domains: []\n\ntenant:\n domains: []\n\nclient:\n domains: []\n", "utf8");
|
|
120
|
+
const data = loadConfig(configPath);
|
|
121
|
+
setConfigValue(data, "aliyun_access_key_id", "id");
|
|
122
|
+
setConfigValue(data, "aliyun_access_key_secret", "sec");
|
|
123
|
+
expect(data.aliyunAccessKeyId).toBe("id");
|
|
124
|
+
expect(data.aliyunAccessKeySecret).toBe("sec");
|
|
125
|
+
});
|
|
126
|
+
it("sets api.backend_port as number", () => {
|
|
127
|
+
const configPath = path.join(tmpDir, "config.yaml");
|
|
128
|
+
fs.writeFileSync(configPath, "api:\n backend_port: 3000\n domains: []\n\nadmin:\n domains: []\n\ntenant:\n domains: []\n\nclient:\n domains: []\n", "utf8");
|
|
129
|
+
const data = loadConfig(configPath);
|
|
130
|
+
setConfigValue(data, "api.backend_port", 8080);
|
|
131
|
+
expect(data.domainsConfig.api.backend_port).toBe(8080);
|
|
132
|
+
});
|
|
133
|
+
it("sets domains arrays", () => {
|
|
134
|
+
const configPath = path.join(tmpDir, "config.yaml");
|
|
135
|
+
fs.writeFileSync(configPath, "api:\n backend_port: 3000\n domains: []\n\nadmin:\n domains: []\n\ntenant:\n domains: []\n\nclient:\n domains: []\n", "utf8");
|
|
136
|
+
const data = loadConfig(configPath);
|
|
137
|
+
setConfigValue(data, "admin.domains", ["a.com", "b.com"]);
|
|
138
|
+
expect(data.domainsConfig.admin.domains).toEqual(["a.com", "b.com"]);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
describe("deleteConfigValue", () => {
|
|
142
|
+
it("clears aliyun keys and resets domains/port", () => {
|
|
143
|
+
const configPath = path.join(tmpDir, "config.yaml");
|
|
144
|
+
const yaml = `aliyun_access_key_id: "k"
|
|
145
|
+
aliyun_access_key_secret: "s"
|
|
146
|
+
|
|
147
|
+
api:
|
|
148
|
+
backend_port: 9999
|
|
149
|
+
domains:
|
|
150
|
+
- x.com
|
|
151
|
+
|
|
152
|
+
admin:
|
|
153
|
+
domains:
|
|
154
|
+
- a.com
|
|
155
|
+
|
|
156
|
+
tenant:
|
|
157
|
+
domains: []
|
|
158
|
+
|
|
159
|
+
client:
|
|
160
|
+
domains: []
|
|
161
|
+
`;
|
|
162
|
+
fs.writeFileSync(configPath, yaml, "utf8");
|
|
163
|
+
const data = loadConfig(configPath);
|
|
164
|
+
deleteConfigValue(data, "aliyun_access_key_id");
|
|
165
|
+
expect(data.aliyunAccessKeyId).toBeUndefined();
|
|
166
|
+
deleteConfigValue(data, "api.backend_port");
|
|
167
|
+
expect(data.domainsConfig.api.backend_port).toBe(3000);
|
|
168
|
+
deleteConfigValue(data, "admin.domains");
|
|
169
|
+
expect(data.domainsConfig.admin.domains).toEqual([]);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
//# sourceMappingURL=config-store.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-store.test.js","sourceRoot":"","sources":["../../src/lib/config-store.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EACL,gBAAgB,EAChB,UAAU,EACV,UAAU,EACV,cAAc,EACd,cAAc,EACd,iBAAiB,GAElB,MAAM,mBAAmB,CAAC;AAE3B,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,IAAI,MAAc,CAAC;IAEnB,UAAU,CAAC,GAAG,EAAE;QACd,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,mBAAmB,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACjE,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAChC,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;YACrC,MAAM,CAAC,gBAAgB,CAAC,sBAAsB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC5D,MAAM,CAAC,gBAAgB,CAAC,0BAA0B,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChE,MAAM,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACxD,MAAM,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnD,MAAM,CAAC,gBAAgB,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrD,MAAM,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtD,MAAM,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;YACxC,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC5C,MAAM,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACjD,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACvC,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;YACxC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;YACpD,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;CAiBlB,CAAC;YACI,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;YAC3C,MAAM,IAAI,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;YACpC,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC9C,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACrD,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACvD,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC;YACpE,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC;YACxE,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YACtD,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACxD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;YAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;YACpD,MAAM,IAAI,GAAG;;;;;;;;;;;;CAYlB,CAAC;YACI,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;YAC3C,MAAM,IAAI,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;YACpC,IAAI,CAAC,iBAAiB,GAAG,SAAS,CAAC;YACnC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACtD,UAAU,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;YAC7B,MAAM,MAAM,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;YACtC,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACjD,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QACzE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;QAC9B,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;YACpC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;YACpD,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;CAgBlB,CAAC;YACI,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;YAC3C,MAAM,IAAI,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;YACpC,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACjE,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,0BAA0B,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACxE,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC5D,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;YAC/D,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC5D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;QAC9B,EAAE,CAAC,kBAAkB,EAAE,GAAG,EAAE;YAC1B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;YACpD,EAAE,CAAC,aAAa,CACd,UAAU,EACV,0HAA0H,EAC1H,MAAM,CACP,CAAC;YACF,MAAM,IAAI,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;YACpC,cAAc,CAAC,IAAI,EAAE,sBAAsB,EAAE,IAAI,CAAC,CAAC;YACnD,cAAc,CAAC,IAAI,EAAE,0BAA0B,EAAE,KAAK,CAAC,CAAC;YACxD,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1C,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;YACzC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;YACpD,EAAE,CAAC,aAAa,CACd,UAAU,EACV,0HAA0H,EAC1H,MAAM,CACP,CAAC;YACF,MAAM,IAAI,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;YACpC,cAAc,CAAC,IAAI,EAAE,kBAAkB,EAAE,IAAI,CAAC,CAAC;YAC/C,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;YAC7B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;YACpD,EAAE,CAAC,aAAa,CACd,UAAU,EACV,0HAA0H,EAC1H,MAAM,CACP,CAAC;YACF,MAAM,IAAI,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;YACpC,cAAc,CAAC,IAAI,EAAE,eAAe,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;YAC1D,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QACvE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;QACjC,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;YACpD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;YACpD,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;CAiBlB,CAAC;YACI,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;YAC3C,MAAM,IAAI,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;YACpC,iBAAiB,CAAC,IAAI,EAAE,sBAAmC,CAAC,CAAC;YAC7D,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,aAAa,EAAE,CAAC;YAC/C,iBAAiB,CAAC,IAAI,EAAE,kBAA+B,CAAC,CAAC;YACzD,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACvD,iBAAiB,CAAC,IAAI,EAAE,eAA4B,CAAC,CAAC;YACtD,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse domains.yaml / deploy config format.
|
|
3
|
+
* Deploy config (~/.deploy/config.yaml) may include ALIYUN_ACCESS_KEY_ID, ALIYUN_ACCESS_KEY_SECRET and domain sections.
|
|
4
|
+
*/
|
|
5
|
+
export interface DomainsConfig {
|
|
6
|
+
api: {
|
|
7
|
+
backend_port: number;
|
|
8
|
+
domains: string[];
|
|
9
|
+
};
|
|
10
|
+
admin: {
|
|
11
|
+
domains: string[];
|
|
12
|
+
};
|
|
13
|
+
tenant: {
|
|
14
|
+
domains: string[];
|
|
15
|
+
};
|
|
16
|
+
client: {
|
|
17
|
+
domains: string[];
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/** Result of parsing a deploy config file (aliyun credentials + domains). */
|
|
21
|
+
export interface DeployConfigResult {
|
|
22
|
+
domainsConfig: DomainsConfig;
|
|
23
|
+
aliyunAccessKeyId?: string;
|
|
24
|
+
aliyunAccessKeySecret?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Parse deploy config YAML: optional aliyun_access_key_id / aliyun_access_key_secret at top level,
|
|
28
|
+
* plus api/admin/tenant/client sections (same as domains.yaml).
|
|
29
|
+
*/
|
|
30
|
+
export declare function parseDeployConfig(content: string): DeployConfigResult;
|
|
31
|
+
/** Parse domains-only YAML (backward compatible). */
|
|
32
|
+
export declare function parseDomainsYaml(content: string): DomainsConfig;
|
|
33
|
+
/** Return all domains that need SSL (admin + tenant + client). API 与前端同域,不再单独申请证书。 */
|
|
34
|
+
export declare function getAllDomains(config: DomainsConfig): string[];
|
|
35
|
+
/** Serialize DeployConfigResult to YAML-like deploy config string. */
|
|
36
|
+
export declare function serializeDeployConfig(data: DeployConfigResult): string;
|
|
37
|
+
//# sourceMappingURL=domains.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domains.d.ts","sourceRoot":"","sources":["../../src/lib/domains.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACjD,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC7B,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC9B,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CAC/B;AAED,6EAA6E;AAC7E,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,aAAa,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAoBD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,kBAAkB,CAiErE;AAED,qDAAqD;AACrD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CAE/D;AAED,sFAAsF;AACtF,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,EAAE,CAM7D;AAED,sEAAsE;AACtE,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CA2BtE"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse domains.yaml / deploy config format.
|
|
3
|
+
* Deploy config (~/.deploy/config.yaml) may include ALIYUN_ACCESS_KEY_ID, ALIYUN_ACCESS_KEY_SECRET and domain sections.
|
|
4
|
+
*/
|
|
5
|
+
const DEFAULT_CONFIG = {
|
|
6
|
+
api: { backend_port: 3000, domains: [] },
|
|
7
|
+
admin: { domains: [] },
|
|
8
|
+
tenant: { domains: [] },
|
|
9
|
+
client: { domains: [] },
|
|
10
|
+
};
|
|
11
|
+
function unquote(s) {
|
|
12
|
+
const t = s.trim();
|
|
13
|
+
if ((t.startsWith('"') && t.endsWith('"')) ||
|
|
14
|
+
(t.startsWith("'") && t.endsWith("'"))) {
|
|
15
|
+
return t.slice(1, -1);
|
|
16
|
+
}
|
|
17
|
+
return t;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Parse deploy config YAML: optional aliyun_access_key_id / aliyun_access_key_secret at top level,
|
|
21
|
+
* plus api/admin/tenant/client sections (same as domains.yaml).
|
|
22
|
+
*/
|
|
23
|
+
export function parseDeployConfig(content) {
|
|
24
|
+
const result = JSON.parse(JSON.stringify(DEFAULT_CONFIG));
|
|
25
|
+
let aliyunAccessKeyId;
|
|
26
|
+
let aliyunAccessKeySecret;
|
|
27
|
+
const lines = content.split(/\r?\n/);
|
|
28
|
+
let current = null;
|
|
29
|
+
let inDomains = false;
|
|
30
|
+
for (const line of lines) {
|
|
31
|
+
const trimmed = line.trim();
|
|
32
|
+
if (trimmed.startsWith("#") || !trimmed)
|
|
33
|
+
continue;
|
|
34
|
+
const aliIdMatch = trimmed.match(/^aliyun_access_key_id:\s*(.*)$/i);
|
|
35
|
+
if (aliIdMatch) {
|
|
36
|
+
aliyunAccessKeyId = unquote(aliIdMatch[1]).trim() || undefined;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
const aliSecretMatch = trimmed.match(/^aliyun_access_key_secret:\s*(.*)$/i);
|
|
40
|
+
if (aliSecretMatch) {
|
|
41
|
+
aliyunAccessKeySecret = unquote(aliSecretMatch[1]).trim() || undefined;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (/^api:\s*$/.test(trimmed)) {
|
|
45
|
+
current = "api";
|
|
46
|
+
inDomains = false;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (/^admin:\s*$/.test(trimmed)) {
|
|
50
|
+
current = "admin";
|
|
51
|
+
inDomains = false;
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (/^tenant:\s*$/.test(trimmed)) {
|
|
55
|
+
current = "tenant";
|
|
56
|
+
inDomains = false;
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (/^client:\s*$/.test(trimmed)) {
|
|
60
|
+
current = "client";
|
|
61
|
+
inDomains = false;
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
const backendPortMatch = trimmed.match(/^backend_port:\s*(\d+)\s*$/);
|
|
65
|
+
if (current === "api" && backendPortMatch) {
|
|
66
|
+
result.api.backend_port = parseInt(backendPortMatch[1], 10);
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (current && /^domains:\s*$/.test(trimmed)) {
|
|
70
|
+
inDomains = true;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const domainMatch = trimmed.match(/^-\s*(.+)$/);
|
|
74
|
+
if (current && inDomains && domainMatch) {
|
|
75
|
+
const domain = domainMatch[1].trim();
|
|
76
|
+
if (domain)
|
|
77
|
+
result[current].domains.push(domain);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
domainsConfig: result,
|
|
82
|
+
aliyunAccessKeyId,
|
|
83
|
+
aliyunAccessKeySecret,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/** Parse domains-only YAML (backward compatible). */
|
|
87
|
+
export function parseDomainsYaml(content) {
|
|
88
|
+
return parseDeployConfig(content).domainsConfig;
|
|
89
|
+
}
|
|
90
|
+
/** Return all domains that need SSL (admin + tenant + client). API 与前端同域,不再单独申请证书。 */
|
|
91
|
+
export function getAllDomains(config) {
|
|
92
|
+
const list = [];
|
|
93
|
+
for (const d of config.admin.domains)
|
|
94
|
+
list.push(d);
|
|
95
|
+
for (const d of config.tenant.domains)
|
|
96
|
+
list.push(d);
|
|
97
|
+
for (const d of config.client.domains)
|
|
98
|
+
list.push(d);
|
|
99
|
+
return list;
|
|
100
|
+
}
|
|
101
|
+
/** Serialize DeployConfigResult to YAML-like deploy config string. */
|
|
102
|
+
export function serializeDeployConfig(data) {
|
|
103
|
+
const lines = [];
|
|
104
|
+
if (data.aliyunAccessKeyId != null && data.aliyunAccessKeyId !== "") {
|
|
105
|
+
lines.push(`aliyun_access_key_id: "${data.aliyunAccessKeyId}"`);
|
|
106
|
+
}
|
|
107
|
+
if (data.aliyunAccessKeySecret != null && data.aliyunAccessKeySecret !== "") {
|
|
108
|
+
lines.push(`aliyun_access_key_secret: "${data.aliyunAccessKeySecret}"`);
|
|
109
|
+
}
|
|
110
|
+
const c = data.domainsConfig;
|
|
111
|
+
lines.push("");
|
|
112
|
+
lines.push("api:");
|
|
113
|
+
lines.push(` backend_port: ${c.api.backend_port}`);
|
|
114
|
+
lines.push(" domains:");
|
|
115
|
+
for (const d of c.api.domains)
|
|
116
|
+
lines.push(` - ${d}`);
|
|
117
|
+
lines.push("");
|
|
118
|
+
lines.push("admin:");
|
|
119
|
+
lines.push(" domains:");
|
|
120
|
+
for (const d of c.admin.domains)
|
|
121
|
+
lines.push(` - ${d}`);
|
|
122
|
+
lines.push("");
|
|
123
|
+
lines.push("tenant:");
|
|
124
|
+
lines.push(" domains:");
|
|
125
|
+
for (const d of c.tenant.domains)
|
|
126
|
+
lines.push(` - ${d}`);
|
|
127
|
+
lines.push("");
|
|
128
|
+
lines.push("client:");
|
|
129
|
+
lines.push(" domains:");
|
|
130
|
+
for (const d of c.client.domains)
|
|
131
|
+
lines.push(` - ${d}`);
|
|
132
|
+
return lines.join("\n") + "\n";
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=domains.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domains.js","sourceRoot":"","sources":["../../src/lib/domains.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domains.test.d.ts","sourceRoot":"","sources":["../../src/lib/domains.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { parseDeployConfig, parseDomainsYaml, getAllDomains, serializeDeployConfig, } from "./domains.js";
|
|
3
|
+
describe("domains", () => {
|
|
4
|
+
describe("parseDeployConfig", () => {
|
|
5
|
+
it("parses minimal config with defaults", () => {
|
|
6
|
+
const yaml = `
|
|
7
|
+
api:
|
|
8
|
+
backend_port: 3000
|
|
9
|
+
domains: []
|
|
10
|
+
|
|
11
|
+
admin:
|
|
12
|
+
domains: []
|
|
13
|
+
|
|
14
|
+
tenant:
|
|
15
|
+
domains: []
|
|
16
|
+
|
|
17
|
+
client:
|
|
18
|
+
domains: []
|
|
19
|
+
`;
|
|
20
|
+
const result = parseDeployConfig(yaml);
|
|
21
|
+
expect(result.domainsConfig.api.backend_port).toBe(3000);
|
|
22
|
+
expect(result.domainsConfig.api.domains).toEqual([]);
|
|
23
|
+
expect(result.aliyunAccessKeyId).toBeUndefined();
|
|
24
|
+
expect(result.aliyunAccessKeySecret).toBeUndefined();
|
|
25
|
+
});
|
|
26
|
+
it("parses aliyun keys and domains", () => {
|
|
27
|
+
const yaml = `aliyun_access_key_id: "my-key"
|
|
28
|
+
aliyun_access_key_secret: "my-secret"
|
|
29
|
+
|
|
30
|
+
api:
|
|
31
|
+
backend_port: 4000
|
|
32
|
+
domains:
|
|
33
|
+
- api.example.com
|
|
34
|
+
|
|
35
|
+
admin:
|
|
36
|
+
domains:
|
|
37
|
+
- admin.example.com
|
|
38
|
+
|
|
39
|
+
tenant:
|
|
40
|
+
domains:
|
|
41
|
+
- t1.com
|
|
42
|
+
- t2.com
|
|
43
|
+
|
|
44
|
+
client:
|
|
45
|
+
domains: []
|
|
46
|
+
`;
|
|
47
|
+
const result = parseDeployConfig(yaml);
|
|
48
|
+
expect(result.aliyunAccessKeyId).toBe("my-key");
|
|
49
|
+
expect(result.aliyunAccessKeySecret).toBe("my-secret");
|
|
50
|
+
expect(result.domainsConfig.api.backend_port).toBe(4000);
|
|
51
|
+
expect(result.domainsConfig.api.domains).toEqual(["api.example.com"]);
|
|
52
|
+
expect(result.domainsConfig.admin.domains).toEqual(["admin.example.com"]);
|
|
53
|
+
expect(result.domainsConfig.tenant.domains).toEqual(["t1.com", "t2.com"]);
|
|
54
|
+
});
|
|
55
|
+
it("ignores comments and empty lines", () => {
|
|
56
|
+
const yaml = `# comment
|
|
57
|
+
api:
|
|
58
|
+
backend_port: 3000
|
|
59
|
+
domains: []
|
|
60
|
+
# another
|
|
61
|
+
admin:
|
|
62
|
+
domains: []
|
|
63
|
+
|
|
64
|
+
tenant:
|
|
65
|
+
domains: []
|
|
66
|
+
|
|
67
|
+
client:
|
|
68
|
+
domains: []
|
|
69
|
+
`;
|
|
70
|
+
const result = parseDeployConfig(yaml);
|
|
71
|
+
expect(result.domainsConfig.api.backend_port).toBe(3000);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
describe("parseDomainsYaml", () => {
|
|
75
|
+
it("returns domainsConfig only", () => {
|
|
76
|
+
const yaml = `api:
|
|
77
|
+
backend_port: 3000
|
|
78
|
+
domains: []
|
|
79
|
+
|
|
80
|
+
admin:
|
|
81
|
+
domains: []
|
|
82
|
+
|
|
83
|
+
tenant:
|
|
84
|
+
domains: []
|
|
85
|
+
|
|
86
|
+
client:
|
|
87
|
+
domains: []
|
|
88
|
+
`;
|
|
89
|
+
const config = parseDomainsYaml(yaml);
|
|
90
|
+
expect(config.api.backend_port).toBe(3000);
|
|
91
|
+
expect(config.admin.domains).toEqual([]);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
describe("getAllDomains", () => {
|
|
95
|
+
it("returns admin + tenant + client domains (no api)", () => {
|
|
96
|
+
const config = {
|
|
97
|
+
api: { backend_port: 3000, domains: ["api.com"] },
|
|
98
|
+
admin: { domains: ["admin.com"] },
|
|
99
|
+
tenant: { domains: ["t1.com", "t2.com"] },
|
|
100
|
+
client: { domains: ["c.com"] },
|
|
101
|
+
};
|
|
102
|
+
expect(getAllDomains(config)).toEqual([
|
|
103
|
+
"admin.com",
|
|
104
|
+
"t1.com",
|
|
105
|
+
"t2.com",
|
|
106
|
+
"c.com",
|
|
107
|
+
]);
|
|
108
|
+
});
|
|
109
|
+
it("returns empty when no domains", () => {
|
|
110
|
+
const config = {
|
|
111
|
+
api: { backend_port: 3000, domains: [] },
|
|
112
|
+
admin: { domains: [] },
|
|
113
|
+
tenant: { domains: [] },
|
|
114
|
+
client: { domains: [] },
|
|
115
|
+
};
|
|
116
|
+
expect(getAllDomains(config)).toEqual([]);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
describe("serializeDeployConfig", () => {
|
|
120
|
+
it("round-trips with parseDeployConfig", () => {
|
|
121
|
+
const data = {
|
|
122
|
+
domainsConfig: {
|
|
123
|
+
api: { backend_port: 3000, domains: ["api.example.com"] },
|
|
124
|
+
admin: { domains: ["admin.example.com"] },
|
|
125
|
+
tenant: { domains: [] },
|
|
126
|
+
client: { domains: ["c.com"] },
|
|
127
|
+
},
|
|
128
|
+
aliyunAccessKeyId: "key",
|
|
129
|
+
aliyunAccessKeySecret: "secret",
|
|
130
|
+
};
|
|
131
|
+
const serialized = serializeDeployConfig(data);
|
|
132
|
+
const parsed = parseDeployConfig(serialized);
|
|
133
|
+
expect(parsed.aliyunAccessKeyId).toBe("key");
|
|
134
|
+
expect(parsed.aliyunAccessKeySecret).toBe("secret");
|
|
135
|
+
expect(parsed.domainsConfig.api.backend_port).toBe(3000);
|
|
136
|
+
expect(parsed.domainsConfig.api.domains).toEqual(["api.example.com"]);
|
|
137
|
+
expect(parsed.domainsConfig.client.domains).toEqual(["c.com"]);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
//# sourceMappingURL=domains.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domains.test.js","sourceRoot":"","sources":["../../src/lib/domains.test.ts"],"names":[],"mappings":"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"}
|