systemview 1.20.1 → 1.22.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.
@@ -1,80 +1,172 @@
1
- const fs = require("fs");
2
- const path = require("path");
3
- const { HttpClient } = require("systemlynx");
4
- const { createCookieClient } = require("./cookieClient");
5
- const Client = createCookieClient();
1
+ const { HttpClient, createClient } = require("systemlynx");
2
+ const { createCookieHttpClient } = require("./cookieClient");
3
+ const cookieHttpClient = createCookieHttpClient();
4
+ const Client = createClient(cookieHttpClient);
6
5
  const log = require("./logger");
7
6
 
8
- async function probeService(url) {
9
- const connectionData = await HttpClient.request({ url });
10
- if (!connectionData.SystemLynxService) {
11
- throw new Error(`No SystemLynx service found at ${url}`);
12
- }
13
- const client = Client.createService(connectionData);
14
- const connection = await client.Plugin.getConnection();
15
- return connection; // { projectCode, serviceId, system, specList }
16
- }
17
-
18
- function readManifest(manifestFile) {
19
- if (!fs.existsSync(manifestFile)) return null;
7
+ async function getUiSvc(uiUrl) {
20
8
  try {
21
- return JSON.parse(fs.readFileSync(manifestFile, "utf8"));
9
+ const { SystemView } = await Client.loadService(`${uiUrl}/systemview/api`);
10
+ return SystemView;
22
11
  } catch {
23
12
  return null;
24
13
  }
25
14
  }
26
15
 
27
- function writeManifest(manifestFile, connection) {
28
- const manifest = readManifest(manifestFile) || { projectCode: connection.projectCode, services: [] };
29
- if (!manifest.services) manifest.services = [];
30
- const entry = { serviceId: connection.serviceId, system: connection.system, specList: connection.specList };
31
- const idx = manifest.services.findIndex((s) => s.serviceId === connection.serviceId);
32
- if (idx > -1) manifest.services[idx] = entry;
33
- else manifest.services.push(entry);
34
- manifest.projectCode = connection.projectCode;
35
- fs.writeFileSync(manifestFile, JSON.stringify(manifest, null, 2));
16
+ async function notifyUi(uiSvc, project) {
17
+ if (!uiSvc) return;
18
+ try {
19
+ await uiSvc.connect(project);
20
+ } catch {}
21
+ }
22
+
23
+ function serviceIdFromRoute(route) {
24
+ const segments = (route || "").split("/").filter(Boolean);
25
+ return [...segments].reverse().find((s) => s.toLowerCase() !== "api") || "Service";
36
26
  }
37
27
 
38
- module.exports = async function connectService(serviceId, url, { manifest: manifestPath } = {}) {
39
- const manifestFile = manifestPath || path.join(process.cwd(), "systemview.manifest.json");
28
+ function printSummary(entries) {
29
+ console.log("");
30
+ entries.forEach(({ projectCode, serviceId, url }) => {
31
+ log.plain(` ${projectCode} › ${serviceId}${url ? " " + url : ""}`);
32
+ });
33
+ console.log("");
34
+ }
40
35
 
41
- if (!url) {
42
- // Re-probe all services already in the manifest
43
- const manifest = readManifest(manifestFile);
44
- if (!manifest || !manifest.services || !manifest.services.length) {
45
- log.warn("No manifest found. Use: systemview connect <serviceId> <url>");
36
+ module.exports = async function connectService(target, { useManifest, force, connectedUrls, uiUrl } = {}) {
37
+ const uiSvc = await getUiSvc(uiUrl);
38
+
39
+ // connect (no args) connect to every service stored in UI
40
+ if (!target) {
41
+ if (!uiSvc) {
42
+ log.warn("SystemView UI not running. Start it first or provide a URL.");
43
+ return;
44
+ }
45
+ const projects = await uiSvc.getProjects();
46
+ const all = Object.entries(projects).flatMap(([pc, svcs]) =>
47
+ svcs.map((s) => ({ projectCode: pc, ...s }))
48
+ );
49
+ if (!all.length) {
50
+ log.warn("No services in UI store. Use: systemview connect <url>");
46
51
  return;
47
52
  }
48
- log.info(`Re-probing ${manifest.services.length} service(s)...`);
49
- for (const { serviceId: id, system } of manifest.services) {
53
+ log.info(`Connecting to ${all.length} stored service(s)...`);
54
+ const summary = [];
55
+ for (const { projectCode, serviceId, connectionData, serviceUrl } of all) {
56
+ const url = serviceUrl || (connectionData && connectionData.serviceUrl);
57
+ if (!url) continue;
50
58
  try {
51
- const connection = await probeService(system.connectionData.serviceUrl);
52
- writeManifest(manifestFile, connection);
53
- log.success(`${id} updated`);
59
+ if (force) {
60
+ await Client.loadService(url);
61
+ } else {
62
+ Client.createService(connectionData);
63
+ }
64
+ connectedUrls.add(url);
65
+ log.success(`${projectCode} › ${serviceId}`);
66
+ summary.push({ projectCode, serviceId, url });
54
67
  } catch (err) {
55
- log.error(`${id} failed: ${err.message}`);
68
+ log.error(`${serviceId} failed: ${err.message}`);
56
69
  }
57
70
  }
58
- printManifestSummary(readManifest(manifestFile));
71
+ printSummary(summary);
59
72
  return;
60
73
  }
61
74
 
62
- log.info(`Connecting to ${serviceId || "service"} @ ${url}...`);
75
+ const isUrl = /^https?:\/\//i.test(target);
76
+
77
+ // connect <projectCode> — look up from UI store
78
+ if (!isUrl) {
79
+ if (!uiSvc) {
80
+ log.warn("SystemView UI not running. Cannot look up project by code.");
81
+ return;
82
+ }
83
+ const services = await uiSvc.getServices(target);
84
+ if (!services || !services.length) {
85
+ log.warn(`No services found for project: ${target}`);
86
+ return;
87
+ }
88
+ log.info(`Connecting to ${services.length} service(s) for ${target}...`);
89
+ const summary = [];
90
+ for (const { serviceId, system } of services) {
91
+ const { serviceUrl } = system.connectionData;
92
+ try {
93
+ if (force) {
94
+ await Client.loadService(serviceUrl);
95
+ } else {
96
+ Client.createService(system.connectionData);
97
+ }
98
+ connectedUrls.add(serviceUrl);
99
+ log.success(`${target} › ${serviceId}`);
100
+ summary.push({ projectCode: target, serviceId, url: serviceUrl });
101
+ } catch (err) {
102
+ log.error(`${serviceId} failed: ${err.message}`);
103
+ }
104
+ }
105
+ printSummary(summary);
106
+ return;
107
+ }
108
+
109
+ // connect <url> [--manifest]
110
+ log.info(`Connecting to ${target}...`);
63
111
  try {
64
- const connection = await probeService(url);
65
- writeManifest(manifestFile, connection);
66
- printManifestSummary(readManifest(manifestFile));
112
+ if (useManifest) {
113
+ const svc = await Client.loadService(target);
114
+ let manifest = null;
115
+ try { manifest = await svc.Plugin.getManifest(); } catch {}
116
+ if (manifest && manifest.services && manifest.services.length) {
117
+ log.info(`Plugin manifest found: ${manifest.projectCode} (${manifest.services.length} service(s))`);
118
+ const summary = [];
119
+ for (const service of manifest.services) {
120
+ try {
121
+ Client.createService(service.system.connectionData);
122
+ connectedUrls.add(service.system.connectionData.serviceUrl);
123
+ await notifyUi(uiSvc, {
124
+ system: service.system,
125
+ projectCode: manifest.projectCode,
126
+ serviceId: service.serviceId,
127
+ specList: service.specList || { tests: [], docs: [] },
128
+ });
129
+ log.success(`${manifest.projectCode} › ${service.serviceId}`);
130
+ summary.push({ projectCode: manifest.projectCode, serviceId: service.serviceId, url: service.system.connectionData.serviceUrl });
131
+ } catch (err) {
132
+ log.error(`${service.serviceId} failed: ${err.message}`);
133
+ }
134
+ }
135
+ printSummary(summary);
136
+ } else {
137
+ log.warn("No plugin manifest found. Storing as connected-services.");
138
+ const connectionData = await HttpClient.request({ url: target });
139
+ const serviceId = serviceIdFromRoute(connectionData.route);
140
+ const project = {
141
+ system: { connectionData },
142
+ projectCode: "connected-services",
143
+ serviceId,
144
+ specList: { tests: [], docs: [] },
145
+ };
146
+ Client.createService(connectionData);
147
+ connectedUrls.add(target);
148
+ await notifyUi(uiSvc, project);
149
+ printSummary([{ projectCode: "connected-services", serviceId, url: target }]);
150
+ }
151
+ } else {
152
+ const connectionData = await HttpClient.request({ url: target });
153
+ if (!connectionData || !connectionData.SystemLynxService) {
154
+ throw new Error("No SystemLynx service found at " + target);
155
+ }
156
+ const serviceId = serviceIdFromRoute(connectionData.route);
157
+ const project = {
158
+ system: { connectionData },
159
+ projectCode: "connected-services",
160
+ serviceId,
161
+ specList: { tests: [], docs: [] },
162
+ };
163
+ Client.createService(connectionData);
164
+ connectedUrls.add(target);
165
+ await notifyUi(uiSvc, project);
166
+ log.success(`connected-services › ${serviceId}`);
167
+ printSummary([{ projectCode: "connected-services", serviceId, url: target }]);
168
+ }
67
169
  } catch (err) {
68
170
  log.error(`Connection failed: ${err.message}`);
69
171
  }
70
172
  };
71
-
72
- function printManifestSummary(manifest) {
73
- if (!manifest) return;
74
- log.plain(`\n Project: ${manifest.projectCode}`);
75
- log.plain(` Services:`);
76
- (manifest.services || []).forEach(({ serviceId, system }) => {
77
- log.plain(` - ${serviceId} @ ${system.connectionData.serviceUrl}`);
78
- });
79
- log.plain("");
80
- }
@@ -87,7 +87,4 @@ function createCookieHttpClient(extraHeaders = {}) {
87
87
  };
88
88
  }
89
89
 
90
- module.exports = {
91
- createCookieHttpClient,
92
- createCookieClient: (extraHeaders = {}) => createClient(createCookieHttpClient(extraHeaders)),
93
- };
90
+ module.exports = { createCookieHttpClient };
package/cli/index.js CHANGED
@@ -13,17 +13,39 @@ const listTests = require("./listTests");
13
13
  const appIsRunning = require("./appIsRunning");
14
14
  const openBrowser = require("./openBrowser");
15
15
  const connectService = require("./connectService");
16
+ const manifestCommands = require("./manifest");
16
17
  const probe = require("./probe");
17
- const { HttpClient } = require("systemlynx");
18
- const { createCookieClient } = require("./cookieClient");
18
+ const logsCommand = require("./logs");
19
+ const { createClient } = require("systemlynx");
20
+ const { createCookieHttpClient } = require("./cookieClient");
21
+ const cookieHttpClient = createCookieHttpClient();
22
+ const Client = createClient(cookieHttpClient);
19
23
 
20
24
  const DEFAULT_PORT = 3000;
21
25
  const VERSION = require("../package.json").version;
26
+ const UI_URL = `http://localhost:${DEFAULT_PORT}`;
27
+
28
+ const MANIFEST_FILE = flags.manifest || path.join(process.cwd(), "systemview.manifest.json");
29
+ const connectedUrls = new Set();
30
+
31
+ function loadManifest() {
32
+ if (!fs.existsSync(MANIFEST_FILE)) return;
33
+ try {
34
+ const manifest = JSON.parse(fs.readFileSync(MANIFEST_FILE, "utf8"));
35
+ const services = manifest.services || [manifest];
36
+ for (const { system } of services) {
37
+ if (system && system.connectionData) {
38
+ Client.createService(system.connectionData);
39
+ connectedUrls.add(system.connectionData.serviceUrl);
40
+ }
41
+ }
42
+ } catch {}
43
+ }
22
44
 
23
45
  async function startApp() {
24
46
  const port = isNaN(input[1]) ? DEFAULT_PORT : Number(input[1]);
25
47
  try {
26
- await launchApp(port, { interactive: true });
48
+ await launchApp(port, { interactive: true, connectedUrls, client: Client });
27
49
  } catch (error) {
28
50
  log.error("Launch failed: " + error.message);
29
51
  }
@@ -32,13 +54,11 @@ async function startApp() {
32
54
  async function startTest() {
33
55
  const project_code = input[1];
34
56
  const namespace = input[2];
35
- const url = `http://localhost:${DEFAULT_PORT}`;
36
57
  try {
37
58
  await launchApp(DEFAULT_PORT);
38
- const exitCode = await runTests(url, project_code, namespace, {
59
+ const exitCode = await runTests(UI_URL, project_code, namespace, {
39
60
  json: flags.json,
40
61
  verbose: flags.verbose,
41
- manifest: flags.manifest,
42
62
  headers: flags.headers,
43
63
  bail: flags.bail,
44
64
  dryRun: flags.dryRun,
@@ -56,41 +76,35 @@ async function startTest() {
56
76
  async function list() {
57
77
  const project_code = input[1];
58
78
  const namespace = input[2];
59
- const url = `http://localhost:${DEFAULT_PORT}`;
60
- const api = `${url}/systemview/api`;
79
+ const api = `${UI_URL}/systemview/api`;
61
80
  if (!(await appIsRunning(api))) {
62
81
  await launchApp(DEFAULT_PORT);
63
82
  }
64
- await listTests(url, project_code, namespace, { manifest: flags.manifest, verbose: flags.verbose });
83
+ await listTests(UI_URL, project_code, namespace, {
84
+ connectedUrls,
85
+ verbose: flags.verbose,
86
+ json: flags.json,
87
+ });
65
88
  process.exit(0);
66
89
  }
67
90
 
68
91
  async function open() {
69
92
  const project_code = input[1];
70
93
  const namespace = input[2];
71
- const ui = `http://localhost:${DEFAULT_PORT}`;
72
- const api = `${ui}/systemview/api`;
94
+ const api = `${UI_URL}/systemview/api`;
73
95
  if (!(await appIsRunning(api))) {
74
96
  await launchApp(DEFAULT_PORT);
75
97
  }
76
98
 
77
99
  let connectedServices = [];
78
100
  if (namespace && project_code) {
79
- const manifestFile = flags.manifest || path.join(process.cwd(), "systemview.manifest.json");
80
- if (fs.existsSync(manifestFile)) {
81
- try {
82
- const raw = JSON.parse(fs.readFileSync(manifestFile, "utf8"));
83
- connectedServices = raw.services ? raw.services : [raw];
84
- } catch {}
85
- } else {
86
- try {
87
- const { SystemView } = await createCookieClient().loadService(api);
88
- connectedServices = (await SystemView.getServices(project_code)) || [];
89
- } catch {}
90
- }
101
+ try {
102
+ const { SystemView } = await Client.loadService(api);
103
+ connectedServices = (await SystemView.getServices(project_code)) || [];
104
+ } catch {}
91
105
  }
92
106
 
93
- openBrowser(ui, project_code, namespace, connectedServices);
107
+ openBrowser(UI_URL, project_code, namespace, connectedServices);
94
108
  process.exit(0);
95
109
  }
96
110
 
@@ -100,24 +114,20 @@ async function quitApp() {
100
114
 
101
115
  if (await appIsRunning(api)) {
102
116
  log.info("Attempting remote shutdown...");
103
- const url = `${api}/SystemView/shutdown`;
104
117
  try {
105
- await HttpClient.request({ url, method: "put" });
118
+ const { SystemView } = await Client.loadService(api);
119
+ await SystemView.shutdown();
120
+ } catch {}
121
+ if (!(await appIsRunning(api))) {
106
122
  log.success("SystemView shutdown successful!");
107
- process.exit(0);
108
- } catch (error) {
109
- if (!(await appIsRunning(api))) {
110
- log.success("SystemView shutdown successful!");
111
- process.exit(0);
112
- } else {
113
- log.error("Remote shutdown failed!");
114
- process.exit(1);
115
- }
123
+ } else {
124
+ log.error("Remote shutdown failed!");
125
+ process.exit(1);
116
126
  }
117
127
  } else {
118
128
  log.warn(`No SystemView instance found @ ${api}`);
119
- process.exit(0);
120
129
  }
130
+ process.exit(0);
121
131
  }
122
132
 
123
133
  (async () => {
@@ -127,6 +137,8 @@ async function quitApp() {
127
137
  }
128
138
 
129
139
  init();
140
+ loadManifest();
141
+
130
142
  const command = input[0];
131
143
 
132
144
  if (command === "open") {
@@ -140,15 +152,58 @@ async function quitApp() {
140
152
  } else if (["exit", "q", "shutdown", "stop"].includes(command)) {
141
153
  await quitApp();
142
154
  } else if (command === "connect") {
143
- await connectService(input[1], input[2], { manifest: flags.manifest });
155
+ const useManifest = process.argv.includes("--manifest");
156
+ await connectService(input[1], {
157
+ useManifest,
158
+ force: flags.force,
159
+ connectedUrls,
160
+ uiUrl: UI_URL,
161
+ });
162
+ process.exit(0);
163
+ } else if (command === "disconnect") {
164
+ await manifestCommands.disconnect(input[1], input[2], {
165
+ connectedUrls,
166
+ uiUrl: UI_URL,
167
+ });
168
+ process.exit(0);
169
+ } else if (command === "manifest") {
170
+ const sub = input[1];
171
+ if (sub === "save") {
172
+ log.warn("manifest save requires an interactive session. Run: systemview start");
173
+ } else if (sub === "clean") {
174
+ await manifestCommands.clean(MANIFEST_FILE);
175
+ } else {
176
+ log.warn("Usage: systemview manifest <save|clean>");
177
+ }
144
178
  process.exit(0);
145
179
  } else if (command === "probe") {
180
+ await launchApp(DEFAULT_PORT);
146
181
  const exitCode = await probe(input[1], input[2], {
147
182
  json: flags.json,
148
183
  manifest: flags.manifest,
149
184
  headers: flags.headers,
185
+ uiUrl: UI_URL,
150
186
  });
151
187
  process.exit(exitCode || 0);
188
+ } else if (command === "logs" || command === "log") {
189
+ await launchApp(DEFAULT_PORT);
190
+ await logsCommand(input[1], input[2], {
191
+ uiUrl: UI_URL,
192
+ level: flags.level,
193
+ limit: flags.limit,
194
+ clear: flags.clear,
195
+ json: flags.json,
196
+ current: flags.current,
197
+ follow: flags.follow,
198
+ verbose: flags.verbose,
199
+ filter: flags.filter,
200
+ or: flags.or,
201
+ include: flags.include,
202
+ save: flags.save,
203
+ saved: flags.saved,
204
+ saveLimit: flags.saveLimit,
205
+ });
206
+ if (!flags.follow) process.exit(0);
152
207
  } else {
153
208
  await startApp();
154
209
  }
package/cli/launchApp.js CHANGED
@@ -2,8 +2,9 @@ const log = require("./logger");
2
2
  const appIsRunning = require("./appIsRunning");
3
3
  const launchSystemView = require("../api");
4
4
  const startLineReader = require("./startLineReader");
5
+ const listTests = require("./listTests");
5
6
 
6
- module.exports = async function launchApp(port, { interactive = false } = {}) {
7
+ module.exports = async function launchApp(port, { interactive = false, connectedUrls = new Set() } = {}) {
7
8
  const ui = `http://localhost:${port}`;
8
9
  const api = `${ui}/systemview/api`;
9
10
 
@@ -15,17 +16,20 @@ module.exports = async function launchApp(port, { interactive = false } = {}) {
15
16
 
16
17
  if (await appIsRunning(api)) {
17
18
  if (interactive) {
18
- log.info("SystemView is running from another terminal");
19
+ log.warn(`SystemView already running on port ${port} — attaching.`);
19
20
  logConnection();
21
+ await listTests(ui, null, null, { connectedUrls });
22
+ return startLineReader(ui, { connectedUrls });
20
23
  }
21
24
  return;
22
25
  }
23
26
 
24
- if (interactive) log.info("Launching...");
27
+ if (interactive) log.info(`Launching on port ${port}...`);
25
28
  await launchSystemView(port);
26
29
  logConnection();
27
30
 
28
31
  if (interactive) {
29
- return startLineReader(ui);
32
+ await listTests(ui, null, null, { connectedUrls });
33
+ return startLineReader(ui, { connectedUrls });
30
34
  }
31
35
  };
package/cli/listTests.js CHANGED
@@ -1,24 +1,44 @@
1
- const fs = require("fs");
2
- const path = require("path");
3
- const { createCookieClient } = require("./cookieClient");
1
+ const { createClient } = require("systemlynx");
2
+ const { createCookieHttpClient } = require("./cookieClient");
4
3
  const log = require("./logger");
5
4
  const chalk = require("chalk");
6
5
 
7
- module.exports = async function listTests(url, project_code, namespace, { manifest: manifestPath, verbose = false } = {}) {
6
+ const cookieHttpClient = createCookieHttpClient();
7
+ const Client = createClient(cookieHttpClient);
8
+
9
+ module.exports = async function listTests(url, project_code, namespace, { connectedUrls = new Set(), verbose = false, json = false } = {}) {
8
10
  const api = `${url}/systemview/api`;
9
- const Client = createCookieClient();
10
11
 
11
12
  if (!project_code) {
12
- await listAllProjects(api, Client, verbose);
13
+ await listAllProjects(api, Client, verbose, connectedUrls, json);
13
14
  return;
14
15
  }
15
16
 
16
- const connectedServices = await loadServices(api, project_code, manifestPath, Client);
17
+ const connectedServices = await loadServices(api, project_code, Client);
17
18
  if (!connectedServices.length) {
18
19
  log.warn("No connected services found for project: " + project_code);
19
20
  return;
20
21
  }
21
22
 
23
+ if (json) {
24
+ const output = [];
25
+ for (const { serviceId, system } of connectedServices) {
26
+ let testList = [];
27
+ try {
28
+ const svc = Client.createService(system.connectionData);
29
+ testList = await svc.Plugin.getTests();
30
+ } catch { continue; }
31
+ const filtered = namespace
32
+ ? testList.filter(({ namespace: n }) =>
33
+ `${n.serviceId}.${n.moduleName}.${n.methodName}`.includes(namespace)
34
+ )
35
+ : testList;
36
+ output.push({ serviceId, tests: filtered });
37
+ }
38
+ console.log(JSON.stringify(output, null, 2));
39
+ return;
40
+ }
41
+
22
42
  console.log("");
23
43
  console.log(` ${chalk.bold(project_code)}`);
24
44
 
@@ -30,7 +50,7 @@ module.exports = async function listTests(url, project_code, namespace, { manife
30
50
 
31
51
  let testList = [];
32
52
  try {
33
- const svc = createCookieClient().createService(system.connectionData);
53
+ const svc = Client.createService(system.connectionData);
34
54
  testList = await svc.Plugin.getTests();
35
55
  } catch {
36
56
  console.log(`${servicePrefix}${chalk.dim(serviceId)} ${chalk.dim("(could not load tests)")}`);
@@ -93,7 +113,7 @@ module.exports = async function listTests(url, project_code, namespace, { manife
93
113
  console.log("");
94
114
  };
95
115
 
96
- async function listAllProjects(api, Client, verbose = false) {
116
+ async function listAllProjects(api, Client, verbose = false, connectedUrls = new Set(), json = false) {
97
117
  let projects;
98
118
  try {
99
119
  const { SystemView } = await Client.loadService(api);
@@ -105,10 +125,13 @@ async function listAllProjects(api, Client, verbose = false) {
105
125
 
106
126
  const codes = Object.keys(projects);
107
127
  if (!codes.length) {
128
+ if (json) { console.log(JSON.stringify({})); return; }
108
129
  log.warn("No connected projects found.");
109
130
  return;
110
131
  }
111
132
 
133
+ if (json) { console.log(JSON.stringify(projects, null, 2)); return; }
134
+
112
135
  const total = codes.reduce((n, c) => n + projects[c].length, 0);
113
136
  console.log("");
114
137
  console.log(chalk.dim(` ${codes.length} ${codes.length === 1 ? "project" : "projects"}, ${total} ${total === 1 ? "service" : "services"}`));
@@ -120,9 +143,11 @@ async function listAllProjects(api, Client, verbose = false) {
120
143
  const isLastService = si === services.length - 1;
121
144
  const servicePrefix = isLastService ? " └── " : " ├── ";
122
145
  const childPad = isLastService ? " " : " │ ";
146
+ const connected = connectedUrls.has(serviceUrl);
147
+ const connectedMark = connected ? chalk.green(" ●") : chalk.dim(" ○");
123
148
 
124
149
  if (verbose && connectionData && connectionData.modules) {
125
- console.log(`${servicePrefix}${chalk.bold(serviceId)} ${chalk.dim(serviceUrl)}`);
150
+ console.log(`${servicePrefix}${chalk.bold(serviceId)}${connectedMark} ${chalk.dim(serviceUrl)}`);
126
151
  const mods = connectionData.modules.filter((m) => m.name !== "Plugin");
127
152
  mods.forEach((mod, mi) => {
128
153
  const isLastMod = mi === mods.length - 1;
@@ -137,7 +162,7 @@ async function listAllProjects(api, Client, verbose = false) {
137
162
  });
138
163
  });
139
164
  } else {
140
- console.log(`${servicePrefix}${serviceId} ${chalk.dim(serviceUrl)}`);
165
+ console.log(`${servicePrefix}${serviceId}${connectedMark} ${chalk.dim(serviceUrl)}`);
141
166
  }
142
167
  });
143
168
  if (pi < codes.length - 1) console.log("");
@@ -145,14 +170,7 @@ async function listAllProjects(api, Client, verbose = false) {
145
170
  console.log("");
146
171
  }
147
172
 
148
- async function loadServices(api, project_code, manifestPath, Client) {
149
- const manifestFile = manifestPath || path.join(process.cwd(), "systemview.manifest.json");
150
- if (fs.existsSync(manifestFile)) {
151
- try {
152
- const raw = JSON.parse(fs.readFileSync(manifestFile, "utf8"));
153
- return raw.services ? raw.services : [raw];
154
- } catch {}
155
- }
173
+ async function loadServices(api, project_code, Client) {
156
174
  try {
157
175
  const { SystemView } = await Client.loadService(api);
158
176
  return (await SystemView.getServices(project_code)) || [];