securewithtrace 0.17.0 → 0.17.1

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 (2) hide show
  1. package/dist/index.js +120 -57
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -25260,7 +25260,13 @@ async function refreshAfterOrganizationSwitch(workosOrganizationId, refreshForOr
25260
25260
  return refreshForOrganization(workosOrganizationId);
25261
25261
  }
25262
25262
  function createLoginCommand() {
25263
- return new Command("login").description("Authenticate with Trace").action(async () => {
25263
+ return new Command("login").description("Authenticate with Trace").addHelpText(
25264
+ "after",
25265
+ `
25266
+ Examples:
25267
+ tracecli auth login
25268
+ tracecli auth logout && tracecli auth login # re-authenticate`
25269
+ ).action(async () => {
25264
25270
  const existingToken = readToken();
25265
25271
  if (existingToken) {
25266
25272
  console.log("You are already logged in. Run `trace auth logout` first to re-authenticate.");
@@ -25294,7 +25300,12 @@ Authenticated as ${displayName} (${tokenResponse.user.email})`);
25294
25300
  });
25295
25301
  }
25296
25302
  function createLogoutCommand() {
25297
- return new Command("logout").description("Log out of Trace").action(() => {
25303
+ return new Command("logout").description("Log out of Trace").addHelpText(
25304
+ "after",
25305
+ `
25306
+ Examples:
25307
+ tracecli auth logout`
25308
+ ).action(() => {
25298
25309
  const removed = removeToken();
25299
25310
  if (removed) {
25300
25311
  console.log("Logged out successfully. Local session data removed from ~/.trace/");
@@ -25303,66 +25314,96 @@ function createLogoutCommand() {
25303
25314
  }
25304
25315
  });
25305
25316
  }
25317
+ function buildAuthStatusInfo(token, refreshToken, selectedOrganizationId) {
25318
+ if (!token) {
25319
+ return { loggedIn: false, expired: false, hasRefreshToken: refreshToken !== null };
25320
+ }
25321
+ const base = {
25322
+ loggedIn: true,
25323
+ expired: false,
25324
+ hasRefreshToken: refreshToken !== null,
25325
+ ...selectedOrganizationId ? { activeOrg: selectedOrganizationId } : {}
25326
+ };
25327
+ try {
25328
+ const parts = token.split(".");
25329
+ const payload = parts[1];
25330
+ if (!payload) {
25331
+ return base;
25332
+ }
25333
+ const decoded = JSON.parse(Buffer.from(payload, "base64url").toString("utf-8"));
25334
+ const expiry = decoded.exp ? new Date(decoded.exp * 1e3) : null;
25335
+ const isExpired = expiry ? expiry < /* @__PURE__ */ new Date() : false;
25336
+ return {
25337
+ ...base,
25338
+ ...decoded.sub ? { userId: decoded.sub } : {},
25339
+ ...decoded.org_id ? { orgId: decoded.org_id } : {},
25340
+ ...expiry ? { expires: expiry.toISOString() } : {},
25341
+ expired: isExpired
25342
+ };
25343
+ } catch {
25344
+ return base;
25345
+ }
25346
+ }
25306
25347
  function createStatusCommand() {
25307
- return new Command("status").description("Show current authentication status").action(() => {
25348
+ return new Command("status").description("Show current authentication status").option("-o, --output <format>", "Output format: table (default), json, tsv").addHelpText(
25349
+ "after",
25350
+ `
25351
+ Examples:
25352
+ tracecli auth status
25353
+ tracecli auth status --output json
25354
+ tracecli auth status --output tsv`
25355
+ ).action((options) => {
25308
25356
  const token = readToken();
25309
25357
  const refreshToken = readRefreshToken();
25310
25358
  const selectedOrganizationId = readSelectedOrganizationId();
25311
- if (token) {
25312
- try {
25313
- const parts = token.split(".");
25314
- const payload = parts[1];
25315
- if (payload) {
25316
- const decoded = JSON.parse(Buffer.from(payload, "base64url").toString("utf-8"));
25317
- const expiry = decoded.exp ? new Date(decoded.exp * 1e3) : null;
25318
- const isExpired = expiry ? expiry < /* @__PURE__ */ new Date() : false;
25319
- console.log("Logged in to Trace");
25320
- if (decoded.sub) {
25321
- console.log(` User ID: ${decoded.sub}`);
25322
- }
25323
- if (decoded.org_id) {
25324
- console.log(` Org ID: ${decoded.org_id}`);
25325
- }
25326
- if (selectedOrganizationId) {
25327
- console.log(` Active Org (CLI): ${selectedOrganizationId}`);
25328
- }
25329
- if (expiry) {
25330
- console.log(` Expires: ${expiry.toISOString()}${isExpired ? " (EXPIRED)" : ""}`);
25331
- }
25332
- console.log(
25333
- ` Refresh: ${refreshToken ? "Available (auto-refresh enabled)" : "Not available"}`
25334
- );
25335
- if (isExpired) {
25336
- if (refreshToken) {
25337
- console.log(
25338
- "\nYour access token is expired, but a refresh token is available and will be used automatically."
25339
- );
25340
- } else {
25341
- console.log(
25342
- "\nYour token has expired. Run `trace auth login` after logging out to re-authenticate."
25343
- );
25344
- }
25345
- }
25346
- } else {
25347
- console.log("Logged in to Trace (access token stored at ~/.trace/token)");
25348
- if (selectedOrganizationId) {
25349
- console.log(` Active Org (CLI): ${selectedOrganizationId}`);
25350
- }
25351
- console.log(
25352
- ` Refresh: ${refreshToken ? "Available (auto-refresh enabled)" : "Not available"}`
25353
- );
25354
- }
25355
- } catch {
25356
- console.log("Logged in to Trace (access token stored at ~/.trace/token)");
25357
- if (selectedOrganizationId) {
25358
- console.log(` Active Org (CLI): ${selectedOrganizationId}`);
25359
- }
25359
+ const info = buildAuthStatusInfo(token, refreshToken, selectedOrganizationId);
25360
+ if (options.output === "json") {
25361
+ console.log(JSON.stringify(info, null, 2));
25362
+ return;
25363
+ }
25364
+ if (options.output === "tsv") {
25365
+ console.log(
25366
+ [
25367
+ String(info.loggedIn),
25368
+ String(info.expired),
25369
+ String(info.hasRefreshToken),
25370
+ info.userId ?? "",
25371
+ info.orgId ?? "",
25372
+ info.activeOrg ?? ""
25373
+ ].join(" ")
25374
+ );
25375
+ return;
25376
+ }
25377
+ if (!info.loggedIn) {
25378
+ console.log("Not logged in. Run `tracecli auth login` to authenticate.");
25379
+ return;
25380
+ }
25381
+ console.log("Logged in to Trace");
25382
+ if (info.userId) {
25383
+ console.log(` User ID: ${info.userId}`);
25384
+ }
25385
+ if (info.orgId) {
25386
+ console.log(` Org ID: ${info.orgId}`);
25387
+ }
25388
+ if (info.activeOrg) {
25389
+ console.log(` Active Org (CLI): ${info.activeOrg}`);
25390
+ }
25391
+ if (info.expires) {
25392
+ console.log(` Expires: ${info.expires}${info.expired ? " (EXPIRED)" : ""}`);
25393
+ }
25394
+ console.log(
25395
+ ` Refresh: ${info.hasRefreshToken ? "Available (auto-refresh enabled)" : "Not available"}`
25396
+ );
25397
+ if (info.expired) {
25398
+ if (info.hasRefreshToken) {
25399
+ console.log(
25400
+ "\nYour access token is expired, but a refresh token is available and will be used automatically."
25401
+ );
25402
+ } else {
25360
25403
  console.log(
25361
- ` Refresh: ${refreshToken ? "Available (auto-refresh enabled)" : "Not available"}`
25404
+ "\nYour token has expired. Run `tracecli auth login` after logging out to re-authenticate."
25362
25405
  );
25363
25406
  }
25364
- } else {
25365
- console.log("Not logged in. Run `trace auth login` to authenticate.");
25366
25407
  }
25367
25408
  });
25368
25409
  }
@@ -25459,7 +25500,13 @@ Examples:
25459
25500
  });
25460
25501
  }
25461
25502
  function createOrgSwitchCommand() {
25462
- return new Command("switch").description("Switch the active organization for subsequent CLI commands").argument("<organization>", "Organization ID, slug, or name").action(async (organization) => {
25503
+ return new Command("switch").description("Switch the active organization for subsequent CLI commands").argument("<organization>", "Organization ID, slug, or name").addHelpText(
25504
+ "after",
25505
+ `
25506
+ Examples:
25507
+ tracecli org switch engineering
25508
+ tracecli org switch org_01KJTJFFG497Z1C54Z07AP6NA3`
25509
+ ).action(async (organization) => {
25463
25510
  const organizationContext = await fetchOrganizationContext();
25464
25511
  const match = findOrganizationByInput(organizationContext.organizations, organization);
25465
25512
  if ("error" in match) {
@@ -26398,6 +26445,7 @@ function parseListLimit(value) {
26398
26445
  return n;
26399
26446
  }
26400
26447
  function printRepositoriesTsv(repositories) {
26448
+ console.log("repositoryUrl platform status defaultBranch language");
26401
26449
  for (const repo of repositories) {
26402
26450
  console.log(
26403
26451
  [
@@ -26463,6 +26511,10 @@ async function runRepositoryListCommand(options) {
26463
26511
  params: { organizationId }
26464
26512
  })
26465
26513
  );
26514
+ if (result.status === 401) {
26515
+ console.error("Authentication failed. Run `tracecli auth login` to re-authenticate.");
26516
+ process.exit(1);
26517
+ }
26466
26518
  if (result.status !== 200) {
26467
26519
  console.error(`Failed to list repositories (status ${result.status}).`);
26468
26520
  process.exit(1);
@@ -26515,6 +26567,10 @@ async function runDependencyFilter(organizationId, options) {
26515
26567
  }
26516
26568
  })
26517
26569
  );
26570
+ if (result.status === 401) {
26571
+ console.error("Authentication failed. Run `tracecli auth login` to re-authenticate.");
26572
+ process.exit(1);
26573
+ }
26518
26574
  if (result.status !== 200) {
26519
26575
  console.error(`Failed to search dependencies (status ${result.status}).`);
26520
26576
  process.exit(1);
@@ -26643,7 +26699,14 @@ async function fetchCloneToken(repoUrl) {
26643
26699
  }
26644
26700
  }
26645
26701
  function createCloneCommand() {
26646
- return new Command("clone").description("Clone a repository").argument("<repository>", "Repository URL or owner/repo shorthand").argument("[directory]", "Directory to clone into").option("--branch <branch>", "Branch to clone").option("--depth <depth>", "Shallow clone depth", parseCloneDepth).action(
26702
+ return new Command("clone").description("Clone a repository").argument("<repository>", "Repository URL or owner/repo shorthand").argument("[directory]", "Directory to clone into").option("--branch <branch>", "Branch to clone").option("--depth <depth>", "Shallow clone depth", parseCloneDepth).addHelpText(
26703
+ "after",
26704
+ `
26705
+ Examples:
26706
+ tracecli repo clone securewithtrace/trace
26707
+ tracecli repo clone securewithtrace/trace trace-src
26708
+ tracecli repo clone https://github.com/owner/repo --branch main --depth 1`
26709
+ ).action(
26647
26710
  async (repository, directory, options) => {
26648
26711
  const cloneUrl = resolveRepoUrl(repository);
26649
26712
  const targetDir = directory ?? extractRepoName(repository);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securewithtrace",
3
- "version": "0.17.0",
3
+ "version": "0.17.1",
4
4
  "description": "Official Trace CLI for vulnerability intelligence in your terminal",
5
5
  "type": "module",
6
6
  "bin": {