@yinuo-ngm/server 1.0.22 → 1.0.24

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 (97) hide show
  1. package/lib/modules/agent-connections/agent-connections.schema.d.ts +4 -0
  2. package/lib/modules/agent-connections/agent-connections.schema.js +112 -0
  3. package/lib/modules/agent-connections/agent-connections.service.d.ts +18 -0
  4. package/lib/modules/agent-connections/agent-connections.service.js +209 -0
  5. package/lib/modules/agent-connections/agent-connections.types.d.ts +57 -0
  6. package/lib/modules/agent-connections/agent-connections.types.js +2 -0
  7. package/lib/modules/agent-connections/atomic-json-file.d.ts +8 -0
  8. package/lib/modules/agent-connections/atomic-json-file.js +44 -0
  9. package/lib/modules/agent-connections/token-mask.d.ts +1 -0
  10. package/lib/modules/agent-connections/token-mask.js +12 -0
  11. package/lib/routes/agent-connections.routes.d.ts +3 -0
  12. package/lib/routes/agent-connections.routes.js +28 -0
  13. package/lib/routes/index.js +2 -0
  14. package/package.json +7 -6
  15. package/www/3rdpartylicenses.txt +5 -5
  16. package/www/browser/chunk-2EB7UV3S.js +15 -0
  17. package/www/browser/{chunk-3I7BQCXS.js → chunk-2S6Y2RQI.js} +1 -1
  18. package/www/browser/{chunk-U3EUR236.js → chunk-2SYBXRWK.js} +1 -1
  19. package/www/browser/{chunk-OUGN4APK.js → chunk-365ZCRSD.js} +1 -1
  20. package/www/browser/{chunk-6UFDNETG.js → chunk-3MPEGFKP.js} +1 -1
  21. package/www/browser/{chunk-WCHN62X6.js → chunk-4PSSTE76.js} +1 -1
  22. package/www/browser/{chunk-DENFXXOY.js → chunk-5HVK6MON.js} +1 -1
  23. package/www/browser/{chunk-TXAXE73U.js → chunk-5Y7KNVNN.js} +1 -1
  24. package/www/browser/chunk-6L2CHHFV.js +1 -0
  25. package/www/browser/{chunk-NNOWADVM.js → chunk-6ZXQKFRQ.js} +1 -1
  26. package/www/browser/chunk-735SLX4X.js +1 -0
  27. package/www/browser/chunk-7KLACOZT.js +2 -0
  28. package/www/browser/chunk-7VJKEZTT.js +20 -0
  29. package/www/browser/{chunk-CO3CQHKV.js → chunk-7X4X4YHI.js} +1 -1
  30. package/www/browser/chunk-ACYCDF6M.js +1 -0
  31. package/www/browser/{chunk-UJKK4A7Y.js → chunk-AQYHNHJ3.js} +1 -1
  32. package/www/browser/chunk-BHKSOTOM.js +1 -0
  33. package/www/browser/{chunk-3ODVU46S.js → chunk-BXZVX5KD.js} +1 -1
  34. package/www/browser/{chunk-TCBOC5FF.js → chunk-C5DOE7UG.js} +1 -1
  35. package/www/browser/{chunk-7AKVG375.js → chunk-C6GC5OOE.js} +1 -1
  36. package/www/browser/{chunk-SSCUT2GF.js → chunk-D5W7J3FS.js} +1 -1
  37. package/www/browser/chunk-DPGKZHEW.js +1 -0
  38. package/www/browser/chunk-DRV2KPHO.js +1 -0
  39. package/www/browser/chunk-E2WRB7KQ.js +2 -0
  40. package/www/browser/{chunk-MPLGMTLT.js → chunk-EAFAHVBG.js} +1 -1
  41. package/www/browser/{chunk-WWIPELAV.js → chunk-ERH36Q6S.js} +1 -1
  42. package/www/browser/chunk-GSUKZOEV.js +1 -0
  43. package/www/browser/chunk-GYXK6ZZT.js +1 -0
  44. package/www/browser/{chunk-PDI3HSSH.js → chunk-H27FQ6OP.js} +3 -3
  45. package/www/browser/chunk-I7RTVSMK.js +1 -0
  46. package/www/browser/{chunk-SD2HFD54.js → chunk-IVX3LVU4.js} +1 -1
  47. package/www/browser/{chunk-U2YWR3HF.js → chunk-IX6UZA7J.js} +1 -1
  48. package/www/browser/{chunk-CPJTSA6E.js → chunk-JFR7U5DE.js} +1 -1
  49. package/www/browser/chunk-JIVQNGBJ.js +1 -0
  50. package/www/browser/{chunk-PY3AUTHC.js → chunk-KDMWEV46.js} +1 -1
  51. package/www/browser/{chunk-JM6DCZP6.js → chunk-LRHJZDWY.js} +1 -1
  52. package/www/browser/chunk-NVN2P466.js +1 -0
  53. package/www/browser/{chunk-NREWZQVN.js → chunk-O64FT2TA.js} +1 -1
  54. package/www/browser/{chunk-YVRGRFK2.js → chunk-OZONPLGN.js} +1 -1
  55. package/www/browser/chunk-PC7TJLCL.js +2 -0
  56. package/www/browser/{chunk-7GLWEFTM.js → chunk-PNFC3J4Z.js} +1 -1
  57. package/www/browser/chunk-PRKDURHI.js +1 -0
  58. package/www/browser/{chunk-RMIYLAEM.js → chunk-PUHSNEN6.js} +1 -1
  59. package/www/browser/{chunk-442QFABJ.js → chunk-RKKAY5CD.js} +1 -1
  60. package/www/browser/{chunk-M6NZ6C2R.js → chunk-RLH7DAA2.js} +1 -1
  61. package/www/browser/chunk-S6BY2OTR.js +1 -0
  62. package/www/browser/{chunk-KRYMOHYF.js → chunk-SIKDYQOR.js} +1 -1
  63. package/www/browser/{chunk-RKK4I2RT.js → chunk-SVRGVAFE.js} +1 -1
  64. package/www/browser/chunk-TPVKLECM.js +1 -0
  65. package/www/browser/{chunk-UPOORT3S.js → chunk-VBMHQZWH.js} +1 -1
  66. package/www/browser/chunk-WVRMU265.js +1 -0
  67. package/www/browser/chunk-X6PRUZ5G.js +1 -0
  68. package/www/browser/{chunk-PUG3VNTI.js → chunk-XQQ6PT2E.js} +1 -1
  69. package/www/browser/chunk-XUUNCF53.js +1 -0
  70. package/www/browser/{chunk-4BRW6LCZ.js → chunk-YGWA6NUS.js} +1 -1
  71. package/www/browser/{chunk-2VJVGBXG.js → chunk-YNYWN7QI.js} +1 -1
  72. package/www/browser/chunk-Z4T3LTE2.js +1 -0
  73. package/www/browser/chunk-Z7GYTPTP.js +1 -0
  74. package/www/browser/chunk-ZZN3NP7F.js +1 -0
  75. package/www/browser/index.html +1 -1
  76. package/www/browser/main-HMOP3OWL.js +38 -0
  77. package/www/browser/chunk-6J6G7JEP.js +0 -1
  78. package/www/browser/chunk-7QR6RHLA.js +0 -1
  79. package/www/browser/chunk-H2USFIYR.js +0 -1
  80. package/www/browser/chunk-HC5KLPHD.js +0 -1
  81. package/www/browser/chunk-HJAP6WBI.js +0 -1
  82. package/www/browser/chunk-K6C5ZIV2.js +0 -20
  83. package/www/browser/chunk-MBPB43C6.js +0 -1
  84. package/www/browser/chunk-PB2LGZNW.js +0 -1
  85. package/www/browser/chunk-R4HSZU2J.js +0 -1
  86. package/www/browser/chunk-RZA3IFQV.js +0 -2
  87. package/www/browser/chunk-SEJGGBE2.js +0 -1
  88. package/www/browser/chunk-TS5ZQYYY.js +0 -1
  89. package/www/browser/chunk-TVJHI463.js +0 -1
  90. package/www/browser/chunk-UKCMUTYL.js +0 -1
  91. package/www/browser/chunk-VW3S7C2Z.js +0 -1
  92. package/www/browser/chunk-VZYJ3MSW.js +0 -15
  93. package/www/browser/chunk-WUA5JFDD.js +0 -1
  94. package/www/browser/chunk-WYNERG74.js +0 -2
  95. package/www/browser/chunk-XJDJL3TQ.js +0 -1
  96. package/www/browser/chunk-YV6QPLF5.js +0 -1
  97. package/www/browser/main-7GYUOEJY.js +0 -38
@@ -0,0 +1,4 @@
1
+ import type { CreateHubV2ConnectionInput, UpdateHubV2ConnectionInput } from "./agent-connections.types";
2
+ export declare function parseHubV2NameParam(value: unknown): string;
3
+ export declare function parseCreateHubV2ConnectionInput(input: unknown): CreateHubV2ConnectionInput;
4
+ export declare function parseUpdateHubV2ConnectionInput(input: unknown): UpdateHubV2ConnectionInput;
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseHubV2NameParam = parseHubV2NameParam;
4
+ exports.parseCreateHubV2ConnectionInput = parseCreateHubV2ConnectionInput;
5
+ exports.parseUpdateHubV2ConnectionInput = parseUpdateHubV2ConnectionInput;
6
+ const errors_1 = require("@yinuo-ngm/errors");
7
+ const NAME_PATTERN = /^[a-zA-Z0-9._-]+$/;
8
+ function ensureObject(value, message) {
9
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
10
+ throw new errors_1.GlobalError(errors_1.GlobalErrorCodes.BAD_REQUEST, message);
11
+ }
12
+ return value;
13
+ }
14
+ function readOptionalString(value, fieldName) {
15
+ if (value === undefined) {
16
+ return undefined;
17
+ }
18
+ if (typeof value !== "string") {
19
+ throw new errors_1.GlobalError(errors_1.GlobalErrorCodes.BAD_REQUEST, `${fieldName} must be string`);
20
+ }
21
+ const text = value.trim();
22
+ return text || undefined;
23
+ }
24
+ function readRequiredString(value, fieldName) {
25
+ const text = readOptionalString(value, fieldName);
26
+ if (!text) {
27
+ throw new errors_1.GlobalError(errors_1.GlobalErrorCodes.BAD_REQUEST, `${fieldName} is required`);
28
+ }
29
+ return text;
30
+ }
31
+ function ensureValidName(name, fieldName) {
32
+ if (!NAME_PATTERN.test(name)) {
33
+ throw new errors_1.GlobalError(errors_1.GlobalErrorCodes.BAD_REQUEST, `${fieldName} only allows [a-zA-Z0-9._-]`);
34
+ }
35
+ return name;
36
+ }
37
+ function ensureHttpUrl(url, fieldName) {
38
+ try {
39
+ const parsed = new URL(url);
40
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
41
+ throw new Error("invalid protocol");
42
+ }
43
+ return parsed.toString().replace(/\/+$/, "");
44
+ }
45
+ catch {
46
+ throw new errors_1.GlobalError(errors_1.GlobalErrorCodes.BAD_REQUEST, `${fieldName} must start with http:// or https://`);
47
+ }
48
+ }
49
+ function readOptionalBoolean(value, fieldName) {
50
+ if (value === undefined) {
51
+ return undefined;
52
+ }
53
+ if (typeof value !== "boolean") {
54
+ throw new errors_1.GlobalError(errors_1.GlobalErrorCodes.BAD_REQUEST, `${fieldName} must be boolean`);
55
+ }
56
+ return value;
57
+ }
58
+ function readOptionalNullableString(value, fieldName) {
59
+ if (value === undefined || value === null) {
60
+ return value;
61
+ }
62
+ if (typeof value !== "string") {
63
+ throw new errors_1.GlobalError(errors_1.GlobalErrorCodes.BAD_REQUEST, `${fieldName} must be string|null`);
64
+ }
65
+ return value;
66
+ }
67
+ function parseHubV2NameParam(value) {
68
+ const name = readRequiredString(value, "name");
69
+ return ensureValidName(name, "name");
70
+ }
71
+ function parseCreateHubV2ConnectionInput(input) {
72
+ const body = ensureObject(input, "invalid request body");
73
+ const name = ensureValidName(readRequiredString(body.name, "name"), "name");
74
+ const baseUrl = ensureHttpUrl(readRequiredString(body.baseUrl, "baseUrl"), "baseUrl");
75
+ const projectKey = readRequiredString(body.projectKey, "projectKey");
76
+ const projectName = readOptionalString(body.projectName, "projectName");
77
+ const projectToken = readOptionalNullableString(body.projectToken, "projectToken");
78
+ const personalToken = readOptionalNullableString(body.personalToken, "personalToken");
79
+ const isDefault = readOptionalBoolean(body.isDefault, "isDefault");
80
+ return {
81
+ name,
82
+ baseUrl,
83
+ projectKey,
84
+ projectName,
85
+ projectToken,
86
+ personalToken,
87
+ isDefault,
88
+ };
89
+ }
90
+ function parseUpdateHubV2ConnectionInput(input) {
91
+ const body = ensureObject(input, "invalid request body");
92
+ const next = {};
93
+ if (Object.prototype.hasOwnProperty.call(body, "baseUrl")) {
94
+ next.baseUrl = ensureHttpUrl(readRequiredString(body.baseUrl, "baseUrl"), "baseUrl");
95
+ }
96
+ if (Object.prototype.hasOwnProperty.call(body, "projectKey")) {
97
+ next.projectKey = readRequiredString(body.projectKey, "projectKey");
98
+ }
99
+ if (Object.prototype.hasOwnProperty.call(body, "projectName")) {
100
+ next.projectName = readOptionalString(body.projectName, "projectName");
101
+ }
102
+ if (Object.prototype.hasOwnProperty.call(body, "projectToken")) {
103
+ next.projectToken = readOptionalNullableString(body.projectToken, "projectToken");
104
+ }
105
+ if (Object.prototype.hasOwnProperty.call(body, "personalToken")) {
106
+ next.personalToken = readOptionalNullableString(body.personalToken, "personalToken");
107
+ }
108
+ if (Object.prototype.hasOwnProperty.call(body, "isDefault")) {
109
+ next.isDefault = readOptionalBoolean(body.isDefault, "isDefault");
110
+ }
111
+ return next;
112
+ }
@@ -0,0 +1,18 @@
1
+ import type { CreateHubV2ConnectionInput, ListHubV2ConnectionsResult, UpdateHubV2ConnectionInput } from "./agent-connections.types";
2
+ type AgentConnectionsServiceOptions = {
3
+ dataDir?: string;
4
+ };
5
+ export declare class AgentConnectionsService {
6
+ readonly dataDir: string;
7
+ readonly configPath: string;
8
+ constructor(options?: AgentConnectionsServiceOptions);
9
+ listHubV2Connections(): Promise<ListHubV2ConnectionsResult>;
10
+ createHubV2Connection(input: CreateHubV2ConnectionInput): Promise<ListHubV2ConnectionsResult>;
11
+ updateHubV2Connection(name: string, patch: UpdateHubV2ConnectionInput): Promise<ListHubV2ConnectionsResult>;
12
+ deleteHubV2Connection(name: string): Promise<ListHubV2ConnectionsResult>;
13
+ setDefaultHubV2Connection(name: string): Promise<ListHubV2ConnectionsResult>;
14
+ private readPreparedState;
15
+ private writePreparedState;
16
+ private toListResult;
17
+ }
18
+ export {};
@@ -0,0 +1,209 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.AgentConnectionsService = void 0;
7
+ const errors_1 = require("@yinuo-ngm/errors");
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const env_1 = require("../../env");
10
+ const atomic_json_file_1 = require("./atomic-json-file");
11
+ const token_mask_1 = require("./token-mask");
12
+ function asRecord(value) {
13
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
14
+ return {};
15
+ }
16
+ return value;
17
+ }
18
+ function readString(source, ...keys) {
19
+ for (const key of keys) {
20
+ const raw = source[key];
21
+ if (typeof raw !== "string") {
22
+ continue;
23
+ }
24
+ const text = raw.trim();
25
+ if (text) {
26
+ return text;
27
+ }
28
+ }
29
+ return undefined;
30
+ }
31
+ function hasOwn(source, key) {
32
+ return Object.prototype.hasOwnProperty.call(source, key);
33
+ }
34
+ function applyTokenPatch(target, key, patchValue, hasField) {
35
+ if (!hasField || patchValue === undefined || patchValue === "") {
36
+ return;
37
+ }
38
+ if (patchValue === null) {
39
+ delete target[key];
40
+ return;
41
+ }
42
+ const token = patchValue.trim();
43
+ if (!token) {
44
+ return;
45
+ }
46
+ target[key] = token;
47
+ }
48
+ function normalizeProject(projectName, rawValue) {
49
+ const raw = asRecord(rawValue);
50
+ const normalized = {
51
+ ...raw,
52
+ };
53
+ normalized.name = readString(raw, "name") ?? projectName;
54
+ normalized.baseUrl = readString(raw, "baseUrl", "base_url");
55
+ normalized.projectKey = readString(raw, "projectKey", "project_key");
56
+ normalized.projectName = readString(raw, "projectName", "project_name");
57
+ normalized.projectToken = readString(raw, "projectToken", "project_token", "token");
58
+ normalized.personalToken = readString(raw, "personalToken", "personal_token");
59
+ normalized.source = readString(raw, "source");
60
+ return normalized;
61
+ }
62
+ class AgentConnectionsService {
63
+ constructor(options = {}) {
64
+ this.dataDir = options.dataDir ?? env_1.env.dataDir;
65
+ this.configPath = node_path_1.default.join(this.dataDir, "agent-connections.json");
66
+ }
67
+ async listHubV2Connections() {
68
+ const state = await this.readPreparedState();
69
+ return this.toListResult(state);
70
+ }
71
+ async createHubV2Connection(input) {
72
+ const state = await this.readPreparedState();
73
+ if (state.projects[input.name]) {
74
+ throw new errors_1.GlobalError(errors_1.GlobalErrorCodes.FS_ALREADY_EXISTS, `hub-v2 connection already exists: ${input.name}`);
75
+ }
76
+ const nextProject = {
77
+ name: input.name,
78
+ baseUrl: input.baseUrl,
79
+ projectKey: input.projectKey,
80
+ source: "ng-manager-ui",
81
+ };
82
+ if (input.projectName) {
83
+ nextProject.projectName = input.projectName;
84
+ }
85
+ if (input.projectToken && input.projectToken.trim()) {
86
+ nextProject.projectToken = input.projectToken.trim();
87
+ }
88
+ if (input.personalToken && input.personalToken.trim()) {
89
+ nextProject.personalToken = input.personalToken.trim();
90
+ }
91
+ state.projects[input.name] = nextProject;
92
+ const projectNames = Object.keys(state.projects);
93
+ if (input.isDefault === true || projectNames.length === 1 || !state.defaultProject) {
94
+ state.defaultProject = input.name;
95
+ }
96
+ await this.writePreparedState(state);
97
+ return this.toListResult(state);
98
+ }
99
+ async updateHubV2Connection(name, patch) {
100
+ const state = await this.readPreparedState();
101
+ const existed = state.projects[name];
102
+ if (!existed) {
103
+ throw new errors_1.GlobalError(errors_1.GlobalErrorCodes.NOT_FOUND, `hub-v2 connection not found: ${name}`);
104
+ }
105
+ const updated = { ...existed };
106
+ if (hasOwn(patch, "baseUrl") && patch.baseUrl) {
107
+ updated.baseUrl = patch.baseUrl;
108
+ }
109
+ if (hasOwn(patch, "projectKey") && patch.projectKey) {
110
+ updated.projectKey = patch.projectKey;
111
+ }
112
+ if (hasOwn(patch, "projectName")) {
113
+ updated.projectName = patch.projectName || undefined;
114
+ }
115
+ applyTokenPatch(updated, "projectToken", patch.projectToken, hasOwn(patch, "projectToken"));
116
+ applyTokenPatch(updated, "personalToken", patch.personalToken, hasOwn(patch, "personalToken"));
117
+ state.projects[name] = updated;
118
+ if (patch.isDefault === true) {
119
+ state.defaultProject = name;
120
+ }
121
+ await this.writePreparedState(state);
122
+ return this.toListResult(state);
123
+ }
124
+ async deleteHubV2Connection(name) {
125
+ const state = await this.readPreparedState();
126
+ if (!state.projects[name]) {
127
+ throw new errors_1.GlobalError(errors_1.GlobalErrorCodes.NOT_FOUND, `hub-v2 connection not found: ${name}`);
128
+ }
129
+ delete state.projects[name];
130
+ if (state.defaultProject === name) {
131
+ const nextDefault = Object.keys(state.projects)[0];
132
+ state.defaultProject = nextDefault;
133
+ }
134
+ await this.writePreparedState(state);
135
+ return this.toListResult(state);
136
+ }
137
+ async setDefaultHubV2Connection(name) {
138
+ const state = await this.readPreparedState();
139
+ if (!state.projects[name]) {
140
+ throw new errors_1.GlobalError(errors_1.GlobalErrorCodes.NOT_FOUND, `hub-v2 connection not found: ${name}`);
141
+ }
142
+ state.defaultProject = name;
143
+ await this.writePreparedState(state);
144
+ return this.toListResult(state);
145
+ }
146
+ async readPreparedState() {
147
+ const loaded = await (0, atomic_json_file_1.readJsonObjectIfExists)(this.configPath);
148
+ const root = loaded.exists
149
+ ? { ...loaded.value }
150
+ : { version: 1 };
151
+ const hubRaw = asRecord(root.hubV2);
152
+ const hubV2 = { ...hubRaw };
153
+ const projectsRaw = asRecord(hubRaw.projects);
154
+ const projects = {};
155
+ for (const [projectName, projectValue] of Object.entries(projectsRaw)) {
156
+ const normalized = normalizeProject(projectName, projectValue);
157
+ projects[projectName] = normalized;
158
+ }
159
+ const defaultProject = readString(hubRaw, "defaultProject", "default_project");
160
+ return {
161
+ root,
162
+ hubV2,
163
+ projects,
164
+ defaultProject,
165
+ };
166
+ }
167
+ async writePreparedState(state) {
168
+ const nextRoot = {
169
+ ...state.root,
170
+ version: 1,
171
+ };
172
+ const nextHub = {
173
+ ...state.hubV2,
174
+ projects: state.projects,
175
+ };
176
+ if (state.defaultProject) {
177
+ nextHub.defaultProject = state.defaultProject;
178
+ }
179
+ else {
180
+ delete nextHub.defaultProject;
181
+ }
182
+ nextRoot.hubV2 = nextHub;
183
+ await (0, atomic_json_file_1.writeJsonAtomic)(this.configPath, nextRoot);
184
+ }
185
+ toListResult(state) {
186
+ const items = Object.entries(state.projects).map(([name, project]) => {
187
+ const projectToken = project.projectToken;
188
+ const personalToken = project.personalToken;
189
+ return {
190
+ name,
191
+ baseUrl: project.baseUrl || "",
192
+ projectKey: project.projectKey || "",
193
+ projectName: project.projectName,
194
+ hasProjectToken: !!projectToken,
195
+ hasPersonalToken: !!personalToken,
196
+ projectTokenPreview: (0, token_mask_1.maskToken)(projectToken),
197
+ personalTokenPreview: (0, token_mask_1.maskToken)(personalToken),
198
+ isDefault: state.defaultProject === name,
199
+ source: project.source,
200
+ };
201
+ });
202
+ return {
203
+ items,
204
+ defaultProject: state.defaultProject,
205
+ configPath: this.configPath,
206
+ };
207
+ }
208
+ }
209
+ exports.AgentConnectionsService = AgentConnectionsService;
@@ -0,0 +1,57 @@
1
+ export type HubV2ProjectRecord = {
2
+ name?: string;
3
+ baseUrl?: string;
4
+ projectKey?: string;
5
+ projectName?: string;
6
+ projectToken?: string;
7
+ personalToken?: string;
8
+ source?: string;
9
+ [key: string]: unknown;
10
+ };
11
+ export type HubV2Record = {
12
+ defaultProject?: string;
13
+ projects?: Record<string, HubV2ProjectRecord>;
14
+ [key: string]: unknown;
15
+ };
16
+ export type AgentConnectionsRootRecord = {
17
+ version?: number;
18
+ hubV2?: HubV2Record;
19
+ [key: string]: unknown;
20
+ };
21
+ export type HubV2ConnectionListItem = {
22
+ name: string;
23
+ baseUrl: string;
24
+ projectKey: string;
25
+ projectName?: string;
26
+ hasProjectToken: boolean;
27
+ hasPersonalToken: boolean;
28
+ projectTokenPreview?: string;
29
+ personalTokenPreview?: string;
30
+ isDefault: boolean;
31
+ source?: string;
32
+ };
33
+ export type ListHubV2ConnectionsResult = {
34
+ items: HubV2ConnectionListItem[];
35
+ defaultProject?: string;
36
+ configPath: string;
37
+ };
38
+ export type CreateHubV2ConnectionInput = {
39
+ name: string;
40
+ baseUrl: string;
41
+ projectKey: string;
42
+ projectName?: string;
43
+ projectToken?: string | null;
44
+ personalToken?: string | null;
45
+ isDefault?: boolean;
46
+ };
47
+ export type UpdateHubV2ConnectionInput = {
48
+ baseUrl?: string;
49
+ projectKey?: string;
50
+ projectName?: string;
51
+ projectToken?: string | null;
52
+ personalToken?: string | null;
53
+ isDefault?: boolean;
54
+ };
55
+ export type AgentConnectionsRoutesOptions = {
56
+ dataDir?: string;
57
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,8 @@
1
+ import type { AgentConnectionsRootRecord } from "./agent-connections.types";
2
+ type ReadJsonResult = {
3
+ exists: boolean;
4
+ value?: AgentConnectionsRootRecord;
5
+ };
6
+ export declare function readJsonObjectIfExists(filePath: string): Promise<ReadJsonResult>;
7
+ export declare function writeJsonAtomic(filePath: string, value: AgentConnectionsRootRecord): Promise<void>;
8
+ export {};
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.readJsonObjectIfExists = readJsonObjectIfExists;
7
+ exports.writeJsonAtomic = writeJsonAtomic;
8
+ const errors_1 = require("@yinuo-ngm/errors");
9
+ const promises_1 = require("node:fs/promises");
10
+ const node_path_1 = __importDefault(require("node:path"));
11
+ async function readJsonObjectIfExists(filePath) {
12
+ try {
13
+ await (0, promises_1.access)(filePath);
14
+ }
15
+ catch (error) {
16
+ if (error.code === "ENOENT") {
17
+ return { exists: false };
18
+ }
19
+ throw new errors_1.GlobalError(errors_1.GlobalErrorCodes.STORAGE_IO_ERROR, "failed to access agent connections config", { filePath, cause: error instanceof Error ? error.message : String(error) });
20
+ }
21
+ const text = await (0, promises_1.readFile)(filePath, "utf8");
22
+ let parsed;
23
+ try {
24
+ parsed = JSON.parse(text);
25
+ }
26
+ catch (error) {
27
+ throw new errors_1.GlobalError(errors_1.GlobalErrorCodes.BAD_JSON, "agent connections config JSON parse failed", { filePath, cause: error instanceof Error ? error.message : String(error) });
28
+ }
29
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
30
+ throw new errors_1.GlobalError(errors_1.GlobalErrorCodes.BAD_JSON, "agent connections config must be a JSON object", { filePath });
31
+ }
32
+ return {
33
+ exists: true,
34
+ value: parsed,
35
+ };
36
+ }
37
+ async function writeJsonAtomic(filePath, value) {
38
+ const dir = node_path_1.default.dirname(filePath);
39
+ await (0, promises_1.mkdir)(dir, { recursive: true });
40
+ const tmpPath = `${filePath}.tmp`;
41
+ const content = `${JSON.stringify(value, null, 2)}\n`;
42
+ await (0, promises_1.writeFile)(tmpPath, content, { encoding: "utf8", mode: 0o600 });
43
+ await (0, promises_1.rename)(tmpPath, filePath);
44
+ }
@@ -0,0 +1 @@
1
+ export declare function maskToken(token?: string | null): string | undefined;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.maskToken = maskToken;
4
+ function maskToken(token) {
5
+ if (!token) {
6
+ return undefined;
7
+ }
8
+ if (token.length <= 8) {
9
+ return "****";
10
+ }
11
+ return `${token.slice(0, 4)}****${token.slice(-4)}`;
12
+ }
@@ -0,0 +1,3 @@
1
+ import type { FastifyInstance } from "fastify";
2
+ import type { AgentConnectionsRoutesOptions } from "../modules/agent-connections/agent-connections.types";
3
+ export default function agentConnectionsRoutes(fastify: FastifyInstance, opts: AgentConnectionsRoutesOptions): Promise<void>;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = agentConnectionsRoutes;
4
+ const agent_connections_schema_1 = require("../modules/agent-connections/agent-connections.schema");
5
+ const agent_connections_service_1 = require("../modules/agent-connections/agent-connections.service");
6
+ async function agentConnectionsRoutes(fastify, opts) {
7
+ const service = new agent_connections_service_1.AgentConnectionsService({ dataDir: opts?.dataDir });
8
+ fastify.get("/hub-v2", async () => {
9
+ return service.listHubV2Connections();
10
+ });
11
+ fastify.post("/hub-v2", async (req) => {
12
+ const input = (0, agent_connections_schema_1.parseCreateHubV2ConnectionInput)(req.body);
13
+ return service.createHubV2Connection(input);
14
+ });
15
+ fastify.put("/hub-v2/:name", async (req) => {
16
+ const name = (0, agent_connections_schema_1.parseHubV2NameParam)(req.params?.name);
17
+ const patch = (0, agent_connections_schema_1.parseUpdateHubV2ConnectionInput)(req.body);
18
+ return service.updateHubV2Connection(name, patch);
19
+ });
20
+ fastify.delete("/hub-v2/:name", async (req) => {
21
+ const name = (0, agent_connections_schema_1.parseHubV2NameParam)(req.params?.name);
22
+ return service.deleteHubV2Connection(name);
23
+ });
24
+ fastify.post("/hub-v2/:name/set-default", async (req) => {
25
+ const name = (0, agent_connections_schema_1.parseHubV2NameParam)(req.params?.name);
26
+ return service.setDefaultHubV2Connection(name);
27
+ });
28
+ }
@@ -21,6 +21,7 @@ const static_files_routes_1 = __importDefault(require("./static-files.routes"));
21
21
  const hub_routes_1 = __importDefault(require("./hub.routes"));
22
22
  const node_runtime_routes_1 = __importDefault(require("./node-runtime.routes"));
23
23
  const node_version_routes_1 = __importDefault(require("./node-version.routes"));
24
+ const agent_connections_routes_1 = __importDefault(require("./agent-connections.routes"));
24
25
  async function routes(fastify) {
25
26
  await fastify.register(system_routes_1.default);
26
27
  await fastify.register(task_routes_1.default, { prefix: '/api/tasks' });
@@ -44,4 +45,5 @@ async function routes(fastify) {
44
45
  await fastify.register(nginx_routes_1.nginxRoutes, { prefix: '/api/nginx' });
45
46
  await fastify.register(node_version_routes_1.default, { prefix: '/api/node-version' });
46
47
  await fastify.register(node_runtime_routes_1.default, { prefix: '/api/node-runtimes' });
48
+ await fastify.register(agent_connections_routes_1.default, { prefix: '/api/agent-connections' });
47
49
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yinuo-ngm/server",
3
- "version": "1.0.22",
3
+ "version": "1.0.24",
4
4
  "description": "a server package for Yinuo NG Manager",
5
5
  "author": "ZhangJing <892295834@qq.com>",
6
6
  "license": "ISC",
@@ -23,16 +23,17 @@
23
23
  "scripts": {
24
24
  "dev": "tsx watch src/index.ts",
25
25
  "build": "tsc -p tsconfig.json",
26
- "start": "node lib/index.js"
26
+ "start": "node lib/index.js",
27
+ "test": "node --import tsx --test test"
27
28
  },
28
29
  "dependencies": {
29
30
  "@fastify/static": "^9.0.0",
30
31
  "@fastify/websocket": "^11.2.0",
31
- "@yinuo-ngm/api": "^0.1.8",
32
- "@yinuo-ngm/core": "^0.1.14",
32
+ "@yinuo-ngm/api": "^0.1.9",
33
+ "@yinuo-ngm/core": "^0.1.15",
33
34
  "@yinuo-ngm/errors": "^1.0.2",
34
35
  "@yinuo-ngm/nginx": "^0.1.4",
35
- "@yinuo-ngm/protocol": "^0.1.3",
36
+ "@yinuo-ngm/protocol": "^0.1.4",
36
37
  "fastify": "^5.6.2",
37
38
  "fastify-plugin": "^5.1.0",
38
39
  "launch-editor": "^2.12.0",
@@ -43,5 +44,5 @@
43
44
  "@types/mime-types": "^3.0.1",
44
45
  "tsx": "^4.21.0"
45
46
  },
46
- "gitHead": "f64135f6db80de6928bc0b83c29c26e408e9fcfb"
47
+ "gitHead": "425cb641977ad61c5f535a068f736b8970f79086"
47
48
  }
@@ -1,4 +1,9 @@
1
1
 
2
+ --------------------------------------------------------------------------------
3
+ Package: ng-zorro-antd
4
+ License: "MIT"
5
+
6
+
2
7
  --------------------------------------------------------------------------------
3
8
  Package: dayjs
4
9
  License: "MIT"
@@ -25,11 +30,6 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
30
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
31
  SOFTWARE.
27
32
 
28
- --------------------------------------------------------------------------------
29
- Package: ng-zorro-antd
30
- License: "MIT"
31
-
32
-
33
33
  --------------------------------------------------------------------------------
34
34
  Package: @angular/common
35
35
  License: "MIT"