@cefense-npm/cefense-cli 0.1.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 (118) hide show
  1. package/LICENSE.md +21 -0
  2. package/dist/commands/auth.d.ts +9 -0
  3. package/dist/commands/auth.d.ts.map +1 -0
  4. package/dist/commands/auth.js +190 -0
  5. package/dist/commands/auth.js.map +1 -0
  6. package/dist/commands/fix.d.ts +3 -0
  7. package/dist/commands/fix.d.ts.map +1 -0
  8. package/dist/commands/fix.js +146 -0
  9. package/dist/commands/fix.js.map +1 -0
  10. package/dist/commands/fixactions.d.ts +12 -0
  11. package/dist/commands/fixactions.d.ts.map +1 -0
  12. package/dist/commands/fixactions.js +176 -0
  13. package/dist/commands/fixactions.js.map +1 -0
  14. package/dist/commands/link.d.ts +8 -0
  15. package/dist/commands/link.d.ts.map +1 -0
  16. package/dist/commands/link.js +0 -0
  17. package/dist/commands/link.js.map +1 -0
  18. package/dist/commands/observed.d.ts +18 -0
  19. package/dist/commands/observed.d.ts.map +1 -0
  20. package/dist/commands/observed.js +254 -0
  21. package/dist/commands/observed.js.map +1 -0
  22. package/dist/commands/pick.d.ts +3 -0
  23. package/dist/commands/pick.d.ts.map +1 -0
  24. package/dist/commands/pick.js +18 -0
  25. package/dist/commands/pick.js.map +1 -0
  26. package/dist/commands/repo.d.ts +12 -0
  27. package/dist/commands/repo.d.ts.map +1 -0
  28. package/dist/commands/repo.js +330 -0
  29. package/dist/commands/repo.js.map +1 -0
  30. package/dist/commands/scan.d.ts +9 -0
  31. package/dist/commands/scan.d.ts.map +1 -0
  32. package/dist/commands/scan.js +98 -0
  33. package/dist/commands/scan.js.map +1 -0
  34. package/dist/commands/status.d.ts +5 -0
  35. package/dist/commands/status.d.ts.map +1 -0
  36. package/dist/commands/status.js +250 -0
  37. package/dist/commands/status.js.map +1 -0
  38. package/dist/core/client.d.ts +87 -0
  39. package/dist/core/client.d.ts.map +1 -0
  40. package/dist/core/client.js +235 -0
  41. package/dist/core/client.js.map +1 -0
  42. package/dist/core/config.d.ts +24 -0
  43. package/dist/core/config.d.ts.map +1 -0
  44. package/dist/core/config.js +85 -0
  45. package/dist/core/config.js.map +1 -0
  46. package/dist/core/credentials.d.ts +17 -0
  47. package/dist/core/credentials.d.ts.map +1 -0
  48. package/dist/core/credentials.js +139 -0
  49. package/dist/core/credentials.js.map +1 -0
  50. package/dist/core/discovery.d.ts +8 -0
  51. package/dist/core/discovery.d.ts.map +1 -0
  52. package/dist/core/discovery.js +62 -0
  53. package/dist/core/discovery.js.map +1 -0
  54. package/dist/core/errors.d.ts +32 -0
  55. package/dist/core/errors.d.ts.map +1 -0
  56. package/dist/core/errors.js +56 -0
  57. package/dist/core/errors.js.map +1 -0
  58. package/dist/core/index.d.ts +10 -0
  59. package/dist/core/index.d.ts.map +1 -0
  60. package/dist/core/index.js +9 -0
  61. package/dist/core/index.js.map +1 -0
  62. package/dist/core/oauth.d.ts +20 -0
  63. package/dist/core/oauth.d.ts.map +1 -0
  64. package/dist/core/oauth.js +218 -0
  65. package/dist/core/oauth.js.map +1 -0
  66. package/dist/core/repo.d.ts +24 -0
  67. package/dist/core/repo.d.ts.map +1 -0
  68. package/dist/core/repo.js +101 -0
  69. package/dist/core/repo.js.map +1 -0
  70. package/dist/core/session.d.ts +24 -0
  71. package/dist/core/session.d.ts.map +1 -0
  72. package/dist/core/session.js +32 -0
  73. package/dist/core/session.js.map +1 -0
  74. package/dist/core/types.d.ts +309 -0
  75. package/dist/core/types.d.ts.map +1 -0
  76. package/dist/core/types.js +2 -0
  77. package/dist/core/types.js.map +1 -0
  78. package/dist/index.d.ts +3 -0
  79. package/dist/index.d.ts.map +1 -0
  80. package/dist/index.js +148 -0
  81. package/dist/index.js.map +1 -0
  82. package/dist/ui/browser.d.ts +30 -0
  83. package/dist/ui/browser.d.ts.map +1 -0
  84. package/dist/ui/browser.js +350 -0
  85. package/dist/ui/browser.js.map +1 -0
  86. package/dist/ui/format.d.ts +15 -0
  87. package/dist/ui/format.d.ts.map +1 -0
  88. package/dist/ui/format.js +131 -0
  89. package/dist/ui/format.js.map +1 -0
  90. package/dist/ui/output.d.ts +16 -0
  91. package/dist/ui/output.d.ts.map +1 -0
  92. package/dist/ui/output.js +63 -0
  93. package/dist/ui/output.js.map +1 -0
  94. package/dist/ui/prompts.d.ts +39 -0
  95. package/dist/ui/prompts.d.ts.map +1 -0
  96. package/dist/ui/prompts.js +76 -0
  97. package/dist/ui/prompts.js.map +1 -0
  98. package/dist/ui/screen.d.ts +27 -0
  99. package/dist/ui/screen.d.ts.map +1 -0
  100. package/dist/ui/screen.js +120 -0
  101. package/dist/ui/screen.js.map +1 -0
  102. package/dist/ui/spinner.d.ts +8 -0
  103. package/dist/ui/spinner.d.ts.map +1 -0
  104. package/dist/ui/spinner.js +98 -0
  105. package/dist/ui/spinner.js.map +1 -0
  106. package/dist/ui/table.d.ts +14 -0
  107. package/dist/ui/table.d.ts.map +1 -0
  108. package/dist/ui/table.js +47 -0
  109. package/dist/ui/table.js.map +1 -0
  110. package/dist/ui/theme.d.ts +44 -0
  111. package/dist/ui/theme.d.ts.map +1 -0
  112. package/dist/ui/theme.js +85 -0
  113. package/dist/ui/theme.js.map +1 -0
  114. package/dist/version.d.ts +3 -0
  115. package/dist/version.d.ts.map +1 -0
  116. package/dist/version.js +17 -0
  117. package/dist/version.js.map +1 -0
  118. package/package.json +54 -0
@@ -0,0 +1,330 @@
1
+ import open from "open";
2
+ import { openSession } from "../core/session.js";
3
+ import { clearRepoDefault, readRepoDefault, writeRepoDefault } from "../core/config.js";
4
+ import { CefenseError, UsageError } from "../core/errors.js";
5
+ import { defaultScope, gitRemote, gitToplevel, matchProject, parseRepoArgument, resolveProject } from "../core/repo.js";
6
+ import * as out from "../ui/output.js";
7
+ import { confirm, confirmByTyping, multiselect, spinner } from "../ui/prompts.js";
8
+ import { renderTable } from "../ui/table.js";
9
+ import { relativeTime, terminalWidth } from "../ui/format.js";
10
+ import { c, glyph, scanStatusLabel } from "../ui/theme.js";
11
+ import { pickProject } from "./pick.js";
12
+ import { watchScan } from "./scan.js";
13
+ async function ensureGithubConnected(session, assumeYes) {
14
+ const status = await session.client.githubStatus();
15
+ if (status.connected)
16
+ return;
17
+ if (!status.configured) {
18
+ throw new CefenseError("GitHub is not configured on this Cefense instance.", {
19
+ remedy: "Run cf doctor for the full picture.",
20
+ });
21
+ }
22
+ const webUrl = session.config?.webUrl ?? session.apiUrl;
23
+ const target = `${webUrl}/app/repositories`;
24
+ out.line();
25
+ out.warn("Your GitHub account is not connected to Cefense.");
26
+ out.line();
27
+ out.line(` ${c.cyan(target)}`);
28
+ out.line();
29
+ if (!assumeYes) {
30
+ const proceed = await confirm({
31
+ message: "Open that page in your browser now?",
32
+ initialValue: true,
33
+ assumeYes,
34
+ });
35
+ if (!proceed) {
36
+ throw new UsageError("GitHub must be connected before a repository can be added.");
37
+ }
38
+ }
39
+ void open(target).catch(() => undefined);
40
+ const progress = spinner();
41
+ progress.start("Waiting for the GitHub connection");
42
+ const deadline = Date.now() + 5 * 60_000;
43
+ for (;;) {
44
+ await new Promise((resolve) => setTimeout(resolve, 2000));
45
+ const next = await session.client.githubStatus().catch(() => null);
46
+ if (next?.connected) {
47
+ progress.stop(`GitHub connected as ${next.login}`);
48
+ return;
49
+ }
50
+ if (Date.now() > deadline) {
51
+ progress.stop("Gave up waiting for the GitHub connection.", "fail");
52
+ throw new CefenseError("GitHub was not connected in time.", {
53
+ remedy: `Finish the connection at ${target}, then run cf repo connect again.`,
54
+ });
55
+ }
56
+ }
57
+ }
58
+ export async function repoConnect(globals, target, options = {}) {
59
+ const session = await openSession(globals, { auth: true });
60
+ await ensureGithubConnected(session, Boolean(globals.yes));
61
+ const listing = await session.client.githubRepos();
62
+ if (listing.needsReconnect) {
63
+ throw new CefenseError("Your GitHub connection has expired.", {
64
+ remedy: `Reconnect at ${session.config?.webUrl ?? session.apiUrl}/app/repositories.`,
65
+ });
66
+ }
67
+ let chosen = [];
68
+ if (target) {
69
+ const wanted = parseRepoArgument(target)?.fullName.toLowerCase() ?? target.toLowerCase();
70
+ const repo = listing.repos.find((entry) => entry.fullName.toLowerCase() === wanted);
71
+ if (!repo) {
72
+ throw new UsageError(`${target} is not available to Cefense on GitHub.`, listing.manageUrl
73
+ ? `Check the spelling, or grant access at ${listing.manageUrl}.`
74
+ : "Check the spelling, or grant Cefense access to it on GitHub.");
75
+ }
76
+ if (repo.connected) {
77
+ out.line();
78
+ out.info(`${c.bold(repo.fullName)} is already connected.`);
79
+ out.line();
80
+ return 0;
81
+ }
82
+ chosen = [repo];
83
+ }
84
+ else {
85
+ const available = listing.repos.filter((repo) => !repo.connected);
86
+ if (available.length === 0) {
87
+ out.line();
88
+ out.info("Every repository Cefense can see is already connected.");
89
+ if (listing.manageUrl)
90
+ out.hint(`Grant access to more at ${listing.manageUrl}`);
91
+ out.line();
92
+ return 0;
93
+ }
94
+ const remote = gitRemote();
95
+ const suggested = remote
96
+ ? available.find((repo) => repo.fullName.toLowerCase() === remote.fullName.toLowerCase())
97
+ : undefined;
98
+ const picked = await multiselect({
99
+ message: `Connect a repository${listing.login ? ` ${listing.login}` : ""}`,
100
+ choices: available.map((repo) => ({
101
+ value: repo.githubRepoId,
102
+ label: repo.fullName,
103
+ hint: [repo.private ? "private" : "public", repo.defaultBranch ?? undefined]
104
+ .filter(Boolean)
105
+ .join(" "),
106
+ })),
107
+ initialValues: suggested ? [suggested.githubRepoId] : [],
108
+ required: true,
109
+ });
110
+ chosen = available.filter((repo) => picked.includes(repo.githubRepoId));
111
+ }
112
+ if (chosen.length === 0) {
113
+ out.line();
114
+ out.info("Nothing selected.");
115
+ out.line();
116
+ return 0;
117
+ }
118
+ out.line();
119
+ const connected = [];
120
+ for (const repo of chosen) {
121
+ try {
122
+ const result = await session.client.connectRepo(repo);
123
+ out.success(`Connected ${c.bold(repo.fullName)}`);
124
+ connected.push({ project: result.project, scanId: result.scanId });
125
+ }
126
+ catch (error) {
127
+ if (error instanceof CefenseError && /token is unavailable|GitHub connection/i.test(error.message)) {
128
+ out.success(`Connected ${c.bold(repo.fullName)}`);
129
+ out.warn("The scan did not start: your GitHub connection has expired.");
130
+ out.hint(`Reconnect at ${session.config?.webUrl ?? session.apiUrl}/app/repositories`);
131
+ continue;
132
+ }
133
+ throw error;
134
+ }
135
+ }
136
+ if (out.isJsonMode()) {
137
+ out.json(connected.map((entry) => ({ repository: entry.project.fullName, scanId: entry.scanId })));
138
+ return 0;
139
+ }
140
+ const scope = defaultScope();
141
+ if (connected.length === 1 && gitToplevel() && !readRepoDefault(scope)) {
142
+ const only = connected[0].project;
143
+ writeRepoDefault(scope, { githubRepoId: only.githubRepoId, fullName: only.fullName });
144
+ out.hint(`Set as the default repository for ${scope}`);
145
+ }
146
+ if (options.watch !== false) {
147
+ for (const entry of connected) {
148
+ if (!entry.scanId)
149
+ continue;
150
+ out.line();
151
+ await watchScan(session.client, entry.project.githubRepoId, entry.project.fullName);
152
+ }
153
+ }
154
+ out.line();
155
+ out.info("Next: review the findings");
156
+ out.line(` ${c.dim("cf observed")}`);
157
+ out.line();
158
+ return 0;
159
+ }
160
+ export async function repoList(globals) {
161
+ const session = await openSession(globals, { auth: true });
162
+ const { projects } = await session.client.projects();
163
+ if (out.isJsonMode()) {
164
+ out.json(projects);
165
+ return 0;
166
+ }
167
+ if (projects.length === 0) {
168
+ out.line();
169
+ out.info("No repositories are connected.");
170
+ out.hint("Run cf repo connect.");
171
+ out.line();
172
+ return 0;
173
+ }
174
+ const scope = defaultScope();
175
+ const fallback = readRepoDefault(scope);
176
+ out.line();
177
+ out.lines(renderTable(projects, [
178
+ {
179
+ header: "",
180
+ value: (project) => fallback?.githubRepoId === project.githubRepoId ? c.cyan(glyph.arrow) : " ",
181
+ min: 1,
182
+ max: 1,
183
+ },
184
+ { header: "repository", value: (project) => project.fullName, min: 16 },
185
+ { header: "visibility", value: (project) => (project.private ? "private" : "public"), min: 7 },
186
+ { header: "status", value: (project) => scanStatusLabel(project.scan?.status), min: 8 },
187
+ {
188
+ header: "findings",
189
+ value: (project) => (project.scan ? String(project.scan.findingCount) : "-"),
190
+ align: "right",
191
+ min: 5,
192
+ },
193
+ {
194
+ header: "last scan",
195
+ value: (project) => project.scan ? relativeTime(project.scan.finishedAt ?? project.scan.createdAt) : "never",
196
+ min: 9,
197
+ },
198
+ ], { width: terminalWidth() - 4 }).map((row) => ` ${row}`));
199
+ out.line();
200
+ return 0;
201
+ }
202
+ export async function repoSetDefault(globals, target, options = {}) {
203
+ const scope = defaultScope();
204
+ if (options.unset) {
205
+ const cleared = clearRepoDefault(scope);
206
+ out.line();
207
+ if (cleared)
208
+ out.success(`Cleared the default repository for ${scope}`);
209
+ else
210
+ out.info(`No default repository was set for ${scope}`);
211
+ out.line();
212
+ return 0;
213
+ }
214
+ const session = await openSession(globals, { auth: true });
215
+ const { projects } = await session.client.projects();
216
+ if (projects.length === 0) {
217
+ throw new UsageError("No repositories are connected yet.", "Run cf repo connect.");
218
+ }
219
+ let project = null;
220
+ if (target) {
221
+ project = matchProject(projects, target);
222
+ if (!project) {
223
+ throw new UsageError(`${target} is not connected to Cefense.`, `Run cf repo connect ${target}.`);
224
+ }
225
+ }
226
+ else {
227
+ const toplevel = gitToplevel();
228
+ const remote = gitRemote();
229
+ const suggested = remote ? matchProject(projects, remote.fullName) : null;
230
+ out.line();
231
+ if (toplevel && remote) {
232
+ out.info(`${c.bold(toplevel)} is a git repository`);
233
+ out.hint(`origin ${remote.fullName}`);
234
+ out.line();
235
+ }
236
+ if (suggested) {
237
+ const accept = await confirm({
238
+ message: `Use ${suggested.fullName} as the default here?`,
239
+ initialValue: true,
240
+ assumeYes: globals.yes,
241
+ });
242
+ project = accept ? suggested : await pickProject(projects, "Which repository should be the default here?");
243
+ }
244
+ else {
245
+ project = await pickProject(projects, "Which repository should be the default here?");
246
+ }
247
+ }
248
+ if (!project) {
249
+ out.info("Nothing selected.");
250
+ return 0;
251
+ }
252
+ writeRepoDefault(scope, { githubRepoId: project.githubRepoId, fullName: project.fullName });
253
+ out.line();
254
+ out.success(`Default set: ${c.bold(project.fullName)}`);
255
+ out.hint(`Stored for ${scope}`);
256
+ out.line();
257
+ return 0;
258
+ }
259
+ export async function repoDisconnect(globals, target, options = {}) {
260
+ const session = await openSession(globals, { auth: true });
261
+ if (options.account) {
262
+ const status = await session.client.githubStatus();
263
+ if (!status.connected) {
264
+ out.line();
265
+ out.info("No GitHub account is connected.");
266
+ out.line();
267
+ return 0;
268
+ }
269
+ out.line();
270
+ out.warn(`This disconnects the GitHub account ${c.bold(status.login ?? "")} from Cefense entirely.`);
271
+ out.hint("Connected repositories stop scanning until you reconnect.");
272
+ out.line();
273
+ const ok = await confirmByTyping({
274
+ message: `Type ${status.login} to confirm`,
275
+ expected: status.login ?? "",
276
+ assumeYes: globals.yes,
277
+ });
278
+ if (!ok) {
279
+ out.info("Left connected.");
280
+ out.line();
281
+ return 0;
282
+ }
283
+ await session.client.disconnectGithubAccount();
284
+ out.success("GitHub account disconnected");
285
+ out.line();
286
+ return 0;
287
+ }
288
+ const { projects } = await session.client.projects();
289
+ if (projects.length === 0) {
290
+ out.line();
291
+ out.info("No repositories are connected.");
292
+ out.line();
293
+ return 0;
294
+ }
295
+ const resolution = target
296
+ ? { project: matchProject(projects, target) }
297
+ : await resolveProject(session.client, projects, {
298
+ repo: globals.repo,
299
+ pick: (candidates) => pickProject(candidates, "Disconnect which repository?"),
300
+ }).catch(async () => ({
301
+ project: await pickProject(projects, "Disconnect which repository?"),
302
+ }));
303
+ const project = resolution.project;
304
+ if (!project) {
305
+ throw new UsageError(`${target} is not connected to Cefense.`);
306
+ }
307
+ out.line();
308
+ out.warn(`Disconnecting ${c.bold(project.fullName)}`);
309
+ out.hint("This removes the repository and its scan history from Cefense.");
310
+ out.hint("Your code and your GitHub account are not affected.");
311
+ out.line();
312
+ const ok = await confirmByTyping({
313
+ message: `Type ${project.fullName} to confirm`,
314
+ expected: project.fullName,
315
+ assumeYes: globals.yes,
316
+ });
317
+ if (!ok) {
318
+ out.info("Left connected.");
319
+ out.line();
320
+ return 0;
321
+ }
322
+ await session.client.disconnectRepo(project.githubRepoId);
323
+ const scope = defaultScope();
324
+ if (readRepoDefault(scope)?.githubRepoId === project.githubRepoId)
325
+ clearRepoDefault(scope);
326
+ out.success(`Disconnected ${project.fullName}`);
327
+ out.line();
328
+ return 0;
329
+ }
330
+ //# sourceMappingURL=repo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo.js","sourceRoot":"","sources":["../../src/commands/repo.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { CefenseClient } from "../core/client.js";
2
+ import type { Project, ScanSummary } from "../core/types.js";
3
+ import { type GlobalOptions } from "../core/session.js";
4
+ export declare function watchScan(client: CefenseClient, githubRepoId: string, label: string): Promise<ScanSummary | null>;
5
+ export declare function scanCommand(globals: GlobalOptions, options?: {
6
+ watch?: boolean;
7
+ }): Promise<number>;
8
+ export declare function projectScanSummary(project: Project): string;
9
+ //# sourceMappingURL=scan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAe,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAuBrE,wBAAsB,SAAS,CAC7B,MAAM,EAAE,aAAa,EACrB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAuC7B;AAED,wBAAsB,WAAW,CAC/B,OAAO,EAAE,aAAa,EACtB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAChC,OAAO,CAAC,MAAM,CAAC,CAgCjB;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAU3D"}
@@ -0,0 +1,98 @@
1
+ import { openSession } from "../core/session.js";
2
+ import { resolveLinkedProject } from "./link.js";
3
+ import * as out from "../ui/output.js";
4
+ import { spinner } from "../ui/prompts.js";
5
+ import { elapsed, progressBar } from "../ui/format.js";
6
+ import { c } from "../ui/theme.js";
7
+ const POLL_MS = 2000;
8
+ function terminal(scan) {
9
+ return !scan || scan.status === "completed" || scan.status === "failed";
10
+ }
11
+ function describe(scan) {
12
+ const stage = (scan.stage ?? scan.status).padEnd(10);
13
+ const done = scan.filesScanned ?? 0;
14
+ const total = scan.fileCount ?? 0;
15
+ const bar = total > 0 ? `${progressBar(done, total)} ${done} / ${total} files` : "starting";
16
+ const clock = elapsed(scan.createdAt);
17
+ const findings = scan.findingCount > 0 ? ` ${scan.findingCount} so far` : "";
18
+ return `${stage} ${bar} ${clock}${findings}`;
19
+ }
20
+ export async function watchScan(client, githubRepoId, label) {
21
+ const progress = spinner();
22
+ progress.start(`Scanning ${label}`);
23
+ let interrupted = false;
24
+ const onInterrupt = () => {
25
+ interrupted = true;
26
+ };
27
+ process.once("SIGINT", onInterrupt);
28
+ let latest = null;
29
+ try {
30
+ for (;;) {
31
+ if (interrupted) {
32
+ progress.stop(`Still scanning ${label} in the background.`, "none");
33
+ return latest;
34
+ }
35
+ const { projects } = await client.projects();
36
+ latest = projects.find((project) => project.githubRepoId === githubRepoId)?.scan ?? null;
37
+ if (terminal(latest))
38
+ break;
39
+ progress.message(describe(latest));
40
+ await new Promise((resolve) => setTimeout(resolve, POLL_MS));
41
+ }
42
+ }
43
+ finally {
44
+ process.removeListener("SIGINT", onInterrupt);
45
+ }
46
+ if (!latest) {
47
+ progress.stop(`No scan is recorded for ${label}.`, "warn");
48
+ return null;
49
+ }
50
+ if (latest.status === "failed") {
51
+ progress.stop(`Scan failed: ${latest.error ?? "no reason reported"}`, "fail");
52
+ return latest;
53
+ }
54
+ progress.stop(`Scanned ${label} in ${elapsed(latest.createdAt, latest.finishedAt)} · ${latest.findingCount} ${latest.findingCount === 1 ? "finding" : "findings"}`);
55
+ return latest;
56
+ }
57
+ export async function scanCommand(globals, options = {}) {
58
+ const session = await openSession(globals, { auth: true });
59
+ const { project } = await resolveLinkedProject(session, globals);
60
+ const running = project.scan && !terminal(project.scan);
61
+ const { scanId } = await session.client.startScan(project.githubRepoId);
62
+ if (out.isJsonMode()) {
63
+ out.json({ repository: project.fullName, scanId });
64
+ return 0;
65
+ }
66
+ out.line();
67
+ if (running) {
68
+ out.warn("Abandoned the scan already in progress and started a new one.");
69
+ }
70
+ if (options.watch === false) {
71
+ out.success(`Scan queued for ${c.bold(project.fullName)}`);
72
+ out.hint(`scan ${scanId}`);
73
+ out.line();
74
+ return 0;
75
+ }
76
+ const scan = await watchScan(session.client, project.githubRepoId, project.fullName);
77
+ out.line();
78
+ if (scan?.status === "completed" && scan.findingCount > 0) {
79
+ out.info("Next: review the findings");
80
+ out.line(` ${c.dim(`cf observed --repo ${project.fullName}`)}`);
81
+ out.line();
82
+ }
83
+ return scan?.status === "failed" ? 4 : 0;
84
+ }
85
+ export function projectScanSummary(project) {
86
+ const scan = project.scan;
87
+ if (!scan)
88
+ return c.dim("never scanned");
89
+ if (scan.status === "running" || scan.status === "queued") {
90
+ const done = scan.filesScanned ?? 0;
91
+ const total = scan.fileCount ?? 0;
92
+ return total > 0 ? `${scan.stage ?? "running"} ${done}/${total}` : (scan.stage ?? "queued");
93
+ }
94
+ if (scan.status === "failed")
95
+ return c.red(scan.error ?? "failed");
96
+ return "";
97
+ }
98
+ //# sourceMappingURL=scan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.js","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { type GlobalOptions } from "../core/session.js";
2
+ export declare function statusCommand(globals: GlobalOptions, options?: {
3
+ watch?: boolean;
4
+ }): Promise<number>;
5
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAsGrE,wBAAsB,aAAa,CACjC,OAAO,EAAE,aAAa,EACtB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAChC,OAAO,CAAC,MAAM,CAAC,CAwKjB"}