@canaryai/cli 0.2.0 → 0.2.2

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 (39) hide show
  1. package/dist/{chunk-2T64Z2NI.js → chunk-7R4YFGP6.js} +53 -2
  2. package/dist/chunk-7R4YFGP6.js.map +1 -0
  3. package/dist/chunk-DXJNFJ3A.js +64 -0
  4. package/dist/chunk-DXJNFJ3A.js.map +1 -0
  5. package/dist/{chunk-V7U52ISX.js → chunk-HOYYXZPV.js} +136 -131
  6. package/dist/chunk-HOYYXZPV.js.map +1 -0
  7. package/dist/{chunk-ROTCL5WO.js → chunk-TO66FC4R.js} +688 -479
  8. package/dist/chunk-TO66FC4R.js.map +1 -0
  9. package/dist/debug-workflow-EHKNO7BJ.js +240 -0
  10. package/dist/debug-workflow-EHKNO7BJ.js.map +1 -0
  11. package/dist/{feature-flag-ESPSOSKG.js → feature-flag-ZDLDYRSF.js} +15 -92
  12. package/dist/feature-flag-ZDLDYRSF.js.map +1 -0
  13. package/dist/index.js +50 -66
  14. package/dist/index.js.map +1 -1
  15. package/dist/issues-FI3RIWGV.js +362 -0
  16. package/dist/issues-FI3RIWGV.js.map +1 -0
  17. package/dist/{knobs-HKONHY55.js → knobs-3MKMOXIV.js} +19 -104
  18. package/dist/knobs-3MKMOXIV.js.map +1 -0
  19. package/dist/{local-browser-MKKPBTYI.js → local-browser-GG5GUXDS.js} +2 -2
  20. package/dist/{mcp-4F4HI7L2.js → mcp-AD67OLQM.js} +3 -3
  21. package/dist/{psql-6IFVXM3A.js → psql-IVAPNYZV.js} +2 -2
  22. package/dist/{redis-HZC32IEO.js → redis-LWY7L6AS.js} +2 -2
  23. package/dist/{release-WOD3DAX4.js → release-KQFCTAXA.js} +5 -35
  24. package/dist/release-KQFCTAXA.js.map +1 -0
  25. package/dist/runner/preload.js +7 -323
  26. package/dist/runner/preload.js.map +1 -1
  27. package/dist/test.js +5 -340
  28. package/dist/test.js.map +1 -1
  29. package/package.json +1 -1
  30. package/dist/chunk-2T64Z2NI.js.map +0 -1
  31. package/dist/chunk-ROTCL5WO.js.map +0 -1
  32. package/dist/chunk-V7U52ISX.js.map +0 -1
  33. package/dist/feature-flag-ESPSOSKG.js.map +0 -1
  34. package/dist/knobs-HKONHY55.js.map +0 -1
  35. package/dist/release-WOD3DAX4.js.map +0 -1
  36. /package/dist/{local-browser-MKKPBTYI.js.map → local-browser-GG5GUXDS.js.map} +0 -0
  37. /package/dist/{mcp-4F4HI7L2.js.map → mcp-AD67OLQM.js.map} +0 -0
  38. /package/dist/{psql-6IFVXM3A.js.map → psql-IVAPNYZV.js.map} +0 -0
  39. /package/dist/{redis-HZC32IEO.js.map → redis-LWY7L6AS.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/feature-flag.ts"],"sourcesContent":["/**\n * CLI Feature Flag Management\n *\n * Allows superadmins to manage feature flags via the CLI.\n */\n\nimport process from \"node:process\";\nimport { resolveConfig, getArgValue, hasFlag } from \"./auth.js\";\nimport {\n type LifecycleStage,\n toLifecycleLabel,\n parseLifecycleStage,\n apiRequest,\n fetchList,\n} from \"./cli-helpers.js\";\n\ntype FeatureFlag = {\n id: string;\n name: string;\n description: string | null;\n lifecycleStage: LifecycleStage;\n finalValue: boolean | null;\n createdAt: string;\n organizations?: Array<{\n gateId: string;\n orgId: string;\n orgName: string;\n createdAt: string;\n }>;\n};\n\ntype FlagApiResponse = {\n ok: boolean;\n error?: string;\n flag?: FeatureFlag;\n};\n\nfunction fetchFlags(apiUrl: string, token: string): Promise<FeatureFlag[]> {\n return fetchList<FeatureFlag>(apiUrl, token, \"/superadmin/feature-flags\", \"flags\");\n}\n\nasync function handleList(argv: string[], apiUrl: string, token: string): Promise<void> {\n const jsonOutput = hasFlag(argv, \"--json\");\n const flags = await fetchFlags(apiUrl, token);\n\n if (jsonOutput) {\n console.log(JSON.stringify(flags, null, 2));\n return;\n }\n\n if (flags.length === 0) {\n console.log(\"No feature flags found.\");\n return;\n }\n\n for (const flag of flags) {\n const orgCount = flag.organizations?.length ?? 0;\n const lifecycle = `lifecycle=${toLifecycleLabel(flag.lifecycleStage)}`;\n const finalValue =\n flag.lifecycleStage === \"active\" ? \"\" : ` final=${flag.finalValue === true ? \"true\" : \"false\"}`;\n console.log(` ${flag.name} ${flag.description ?? \"\"} (${lifecycle}${finalValue}) [orgs=${orgCount}]`);\n }\n}\n\nasync function handleCreate(argv: string[], apiUrl: string, token: string): Promise<void> {\n const name = argv[0];\n if (!name || name.startsWith(\"--\")) {\n console.error(\"Error: Missing flag name.\");\n console.error(\"Usage: canary feature-flag create <name> [--description <text>]\");\n process.exit(1);\n }\n\n const description = getArgValue(argv, \"--description\") ?? null;\n const result = await apiRequest<FlagApiResponse>(apiUrl, token, \"POST\", \"/superadmin/feature-flags\", {\n name,\n description,\n });\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n console.log(`Created feature flag: ${name}`);\n}\n\nasync function handleDelete(argv: string[], apiUrl: string, token: string): Promise<void> {\n const name = argv[0];\n if (!name || name.startsWith(\"--\")) {\n console.error(\"Error: Missing flag name.\");\n console.error(\"Usage: canary feature-flag delete <name>\");\n process.exit(1);\n }\n\n const result = await apiRequest<FlagApiResponse>(\n apiUrl, token, \"DELETE\", `/superadmin/feature-flags/${encodeURIComponent(name)}`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n console.log(`Deleted feature flag: ${name}`);\n}\n\nasync function handleEnable(argv: string[], apiUrl: string, token: string): Promise<void> {\n const name = argv[0];\n const orgId = getArgValue(argv, \"--org\");\n\n if (!name || name.startsWith(\"--\")) {\n console.error(\"Error: Missing flag name.\");\n console.error(\"Usage: canary feature-flag enable <name> --org <orgId>\");\n process.exit(1);\n }\n\n if (!orgId) {\n console.error(\"Error: Missing --org <orgId>.\");\n console.error(\"Usage: canary feature-flag enable <name> --org <orgId>\");\n process.exit(1);\n }\n\n const result = await apiRequest<FlagApiResponse>(\n apiUrl, token, \"POST\",\n `/superadmin/feature-flags/${encodeURIComponent(name)}/organizations/${encodeURIComponent(orgId)}`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n console.log(`Enabled ${name} for org ${orgId}`);\n}\n\nasync function handleDisable(argv: string[], apiUrl: string, token: string): Promise<void> {\n const name = argv[0];\n const orgId = getArgValue(argv, \"--org\");\n\n if (!name || name.startsWith(\"--\")) {\n console.error(\"Error: Missing flag name.\");\n console.error(\"Usage: canary feature-flag disable <name> --org <orgId>\");\n process.exit(1);\n }\n\n if (!orgId) {\n console.error(\"Error: Missing --org <orgId>.\");\n console.error(\"Usage: canary feature-flag disable <name> --org <orgId>\");\n process.exit(1);\n }\n\n const result = await apiRequest<FlagApiResponse>(\n apiUrl, token, \"DELETE\",\n `/superadmin/feature-flags/${encodeURIComponent(name)}/organizations/${encodeURIComponent(orgId)}`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n console.log(`Disabled ${name} for org ${orgId}`);\n}\n\nasync function handleLifecycle(argv: string[], apiUrl: string, token: string): Promise<void> {\n const name = argv[0];\n\n if (!name || name.startsWith(\"--\")) {\n console.error(\"Error: Missing flag name.\");\n console.error(\"Usage: canary feature-flag lifecycle <name> --stage <active|deprecated|ready_for_cleanup> [--final-value true|false]\");\n process.exit(1);\n }\n\n const stage = parseLifecycleStage(argv);\n const rawFinalValue = getArgValue(argv, \"--final-value\");\n const clearFinalValue = hasFlag(argv, \"--clear-final-value\");\n\n if (rawFinalValue !== undefined && clearFinalValue) {\n console.error(\"Error: use either --final-value or --clear-final-value, not both.\");\n process.exit(1);\n }\n\n let finalValue: boolean | undefined = undefined;\n\n if (stage === \"active\") {\n if (rawFinalValue !== undefined) {\n console.error(\"Error: active stage does not accept --final-value.\");\n process.exit(1);\n }\n finalValue = undefined;\n } else {\n if (clearFinalValue) {\n console.error(\"Error: --clear-final-value can only be used with --stage active.\");\n process.exit(1);\n }\n if (!rawFinalValue) {\n console.error(\"Error: --final-value true|false is required for deprecated or ready_for_cleanup.\");\n process.exit(1);\n }\n if (rawFinalValue !== \"true\" && rawFinalValue !== \"false\") {\n console.error(\"Error: --final-value must be true or false.\");\n process.exit(1);\n }\n finalValue = rawFinalValue === \"true\";\n }\n\n const result = await apiRequest<FlagApiResponse>(\n apiUrl, token, \"POST\",\n `/superadmin/feature-flags/${encodeURIComponent(name)}/lifecycle`,\n { stage, finalValue }\n );\n\n if (!result.ok || !result.flag) {\n console.error(`Error: ${result.error ?? \"Failed to update lifecycle\"}`);\n process.exit(1);\n }\n\n const final =\n result.flag.lifecycleStage === \"active\"\n ? \"(none)\"\n : result.flag.finalValue === true\n ? \"true\"\n : \"false\";\n console.log(`Updated lifecycle for ${name}: stage=${toLifecycleLabel(result.flag.lifecycleStage)}, final=${final}`);\n}\n\nfunction printFeatureFlagHelp(): void {\n console.log(\n [\n \"Usage: canary feature-flag <sub-command> [options]\",\n \"\",\n \"Sub-commands:\",\n \" list List all feature flags\",\n \" create <name> [--description <text>] Create a new flag\",\n \" delete <name> Delete a flag and all its gates\",\n \" enable <name> --org <orgId> Enable a flag for an organization\",\n \" disable <name> --org <orgId> Disable a flag for an organization\",\n \" lifecycle <name> --stage <stage> [--final-value true|false]\",\n \" Mark lifecycle + final value\",\n \"\",\n \"Stages: active, deprecated, ready_for_cleanup\",\n \"\",\n \"Options:\",\n \" --final-value <true|false> Final value for deprecated/ready_for_cleanup\",\n \" --clear-final-value Clear final value (only valid with --stage active)\",\n \" --env <env> Target environment (prod, dev, local)\",\n \" --json Output as JSON (list only)\",\n \" --api-url <url> API URL override (takes precedence over --env)\",\n \" --token <key> API token override\",\n ].join(\"\\n\")\n );\n}\n\nexport async function runFeatureFlag(argv: string[]): Promise<void> {\n const [subCommand, ...rest] = argv;\n\n if (!subCommand || subCommand === \"help\" || hasFlag(argv, \"--help\", \"-h\")) {\n printFeatureFlagHelp();\n return;\n }\n\n const { apiUrl, token } = await resolveConfig(argv);\n\n switch (subCommand) {\n case \"list\":\n await handleList(rest, apiUrl, token);\n break;\n case \"create\":\n await handleCreate(rest, apiUrl, token);\n break;\n case \"delete\":\n await handleDelete(rest, apiUrl, token);\n break;\n case \"enable\":\n await handleEnable(rest, apiUrl, token);\n break;\n case \"disable\":\n await handleDisable(rest, apiUrl, token);\n break;\n case \"lifecycle\":\n await handleLifecycle(rest, apiUrl, token);\n break;\n default:\n console.error(`Unknown sub-command: ${subCommand}`);\n printFeatureFlagHelp();\n process.exit(1);\n }\n}\n"],"mappings":"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","names":[]}
package/dist/index.js CHANGED
@@ -4,15 +4,18 @@ import {
4
4
  createTunnel,
5
5
  runLocalTest,
6
6
  runTunnel
7
- } from "./chunk-V7U52ISX.js";
7
+ } from "./chunk-HOYYXZPV.js";
8
8
  import {
9
9
  ENV_URLS,
10
+ envToProfile,
11
+ getArgValue,
12
+ hasFlag,
10
13
  readAllStoredTokens,
11
- readStoredApiUrl,
12
14
  readStoredAuth,
13
15
  readStoredToken,
16
+ resolveConfig,
14
17
  saveAuth
15
- } from "./chunk-2T64Z2NI.js";
18
+ } from "./chunk-7R4YFGP6.js";
16
19
  import {
17
20
  __require
18
21
  } from "./chunk-DGUM43GV.js";
@@ -333,17 +336,6 @@ function countHealed(eventLogPath) {
333
336
  import process2 from "process";
334
337
  import readline from "readline";
335
338
  import { spawn as spawn2 } from "child_process";
336
- function envToProfile(env) {
337
- if (env === "prod" || env === "production") return "production";
338
- if (env === "dev") return "dev";
339
- if (env === "local") return "local";
340
- return env;
341
- }
342
- function getArgValue(argv, key) {
343
- const index = argv.indexOf(key);
344
- if (index === -1) return void 0;
345
- return argv[index + 1];
346
- }
347
339
  function shouldOpenBrowser(argv) {
348
340
  return !argv.includes("--no-open");
349
341
  }
@@ -629,7 +621,7 @@ function getArgValue3(argv, key) {
629
621
  if (index === -1 || index >= argv.length - 1) return void 0;
630
622
  return argv[index + 1];
631
623
  }
632
- function hasFlag(argv, ...flags) {
624
+ function hasFlag2(argv, ...flags) {
633
625
  return flags.some((flag) => argv.includes(flag));
634
626
  }
635
627
  function formatFailedTests(failedTests, appUrl) {
@@ -646,7 +638,7 @@ async function runRemoteTest(argv) {
646
638
  const token = getArgValue3(argv, "--token") ?? process5.env.CANARY_API_TOKEN ?? await readStoredToken();
647
639
  const tag = getArgValue3(argv, "--tag");
648
640
  const namePattern = getArgValue3(argv, "--name-pattern");
649
- const verbose = hasFlag(argv, "--verbose", "-v");
641
+ const verbose = hasFlag2(argv, "--verbose", "-v");
650
642
  if (!token) {
651
643
  console.error("Error: No API token found.");
652
644
  console.error("");
@@ -811,32 +803,6 @@ import fs3 from "fs/promises";
811
803
  import os2 from "os";
812
804
  import path3 from "path";
813
805
  import process6 from "process";
814
- var ENV_URLS2 = {
815
- prod: {
816
- api: "https://api.trycanary.ai",
817
- app: "https://app.trycanary.ai"
818
- },
819
- production: {
820
- api: "https://api.trycanary.ai",
821
- app: "https://app.trycanary.ai"
822
- },
823
- dev: {
824
- api: "https://api.dev.trycanary.ai",
825
- app: "https://app.dev.trycanary.ai"
826
- },
827
- local: {
828
- api: "http://localhost:3000",
829
- app: "http://localhost:5173"
830
- }
831
- };
832
- function getArgValue4(argv, key) {
833
- const index = argv.indexOf(key);
834
- if (index === -1 || index >= argv.length - 1) return void 0;
835
- return argv[index + 1];
836
- }
837
- function hasFlag2(argv, ...flags) {
838
- return flags.some((flag) => argv.includes(flag));
839
- }
840
806
  async function writeDebugSession(loginUrl, expiresAt, apiUrl) {
841
807
  const dir = path3.join(os2.homedir(), ".config", "canary-cli");
842
808
  const filePath = path3.join(dir, "debug-session.json");
@@ -849,22 +815,8 @@ async function writeDebugSession(loginUrl, expiresAt, apiUrl) {
849
815
  return filePath;
850
816
  }
851
817
  async function runDebugSession(argv) {
852
- const env = getArgValue4(argv, "--env");
853
- const envUrls = env ? ENV_URLS2[env] : void 0;
854
- if (env && !envUrls) {
855
- console.error(`Unknown environment: ${env}`);
856
- console.error("Valid environments: prod, dev, local");
857
- process6.exit(1);
858
- }
859
- const storedApiUrl = await readStoredApiUrl();
860
- const apiUrl = getArgValue4(argv, "--api-url") ?? envUrls?.api ?? process6.env.CANARY_API_URL ?? storedApiUrl ?? "https://api.trycanary.ai";
861
- const token = getArgValue4(argv, "--token") ?? process6.env.CANARY_API_TOKEN ?? await readStoredToken();
862
- const jsonOutput = hasFlag2(argv, "--json");
863
- if (!token) {
864
- console.error("Error: No API token found.");
865
- console.error("Run: canary login [--env <env>]");
866
- process6.exit(1);
867
- }
818
+ const { apiUrl, token } = await resolveConfig(argv);
819
+ const jsonOutput = hasFlag(argv, "--json");
868
820
  try {
869
821
  const res = await fetch(`${apiUrl}/auth/debug-session/create`, {
870
822
  method: "POST",
@@ -957,8 +909,9 @@ function isSuperadminToken(token) {
957
909
  // src/index.ts
958
910
  var require2 = createRequire2(import.meta.url);
959
911
  var pkg = require2("../package.json");
960
- var loadMcp = () => import("./mcp-4F4HI7L2.js").then((m) => m.runMcp);
961
- var loadLocalBrowser = () => import("./local-browser-MKKPBTYI.js").then((m) => m.runLocalBrowser);
912
+ var loadMcp = () => import("./mcp-AD67OLQM.js").then((m) => m.runMcp);
913
+ var loadLocalBrowser = () => import("./local-browser-GG5GUXDS.js").then((m) => m.runLocalBrowser);
914
+ var loadDebugWorkflow = () => import("./debug-workflow-EHKNO7BJ.js").then((m) => m.runDebugWorkflow);
962
915
  var canary = { run };
963
916
  var baseDir = typeof __dirname !== "undefined" ? __dirname : path4.dirname(fileURLToPath2(import.meta.url));
964
917
  var preloadPath = path4.join(baseDir, "runner", "preload.js");
@@ -1000,7 +953,9 @@ function printHelp({ isSuperadmin }) {
1000
953
  " canary mcp",
1001
954
  " canary browser [--mode playwright|cdp] [--cdp-url <url>] [--no-headless]",
1002
955
  " canary login [--org <name>] [--app-url https://app.trycanary.ai] [--no-open]",
1003
- " canary orgs List organizations"
956
+ " canary orgs List organizations",
957
+ " canary debug <workflowId> [options] Debug workflow in local headed browser",
958
+ " canary issues <sub-command> Search and view issues"
1004
959
  ];
1005
960
  lines.push(
1006
961
  " canary release <sub-command> Release QA gate (CI/CD)"
@@ -1044,6 +999,25 @@ function printHelp({ isSuperadmin }) {
1044
999
  " export CANARY_API_URL=http://localhost:3000"
1045
1000
  );
1046
1001
  lines.push(
1002
+ "",
1003
+ "Debug options:",
1004
+ " --to-step <N> Stop after step N (1-based, default: all)",
1005
+ " --env <env> Environment (local, dev, prod)",
1006
+ " --verbose, -v Show all SSE events",
1007
+ "",
1008
+ "Issues sub-commands:",
1009
+ " list [options] List and search issues",
1010
+ " get <issueId> [options] Get issue detail with diagnostics",
1011
+ "",
1012
+ "Issues options:",
1013
+ " --search <query> Full-text search",
1014
+ " --severity <level> Filter: low, medium, high, unknown",
1015
+ " --status <statuses> Filter: open, closed, not_a_bug (comma-separated)",
1016
+ " --property-id <uuid> Filter by property",
1017
+ " --page <n> Page number (default: 1)",
1018
+ " --page-size <n> Page size (default: 25)",
1019
+ " --json Output raw JSON",
1020
+ " --format markdown Output as markdown",
1047
1021
  "",
1048
1022
  "Release sub-commands:",
1049
1023
  " trigger --property-id <uuid> Trigger a Release QA run",
@@ -1190,35 +1164,45 @@ async function main(argv) {
1190
1164
  await runLocalBrowser(rest);
1191
1165
  return;
1192
1166
  }
1167
+ if (command === "debug") {
1168
+ const runDebugWorkflow = await loadDebugWorkflow();
1169
+ await runDebugWorkflow(rest);
1170
+ return;
1171
+ }
1193
1172
  if (command === "debug-session") {
1194
1173
  await runDebugSession(rest);
1195
1174
  return;
1196
1175
  }
1197
1176
  if (command === "psql") {
1198
- const { runPsql } = await import("./psql-6IFVXM3A.js");
1177
+ const { runPsql } = await import("./psql-IVAPNYZV.js");
1199
1178
  await runPsql(rest);
1200
1179
  return;
1201
1180
  }
1202
1181
  if (command === "redis") {
1203
- const { runRedis } = await import("./redis-HZC32IEO.js");
1182
+ const { runRedis } = await import("./redis-LWY7L6AS.js");
1204
1183
  await runRedis(rest);
1205
1184
  return;
1206
1185
  }
1207
1186
  if (command === "release") {
1208
- const { runRelease } = await import("./release-WOD3DAX4.js");
1187
+ const { runRelease } = await import("./release-KQFCTAXA.js");
1209
1188
  await runRelease(rest);
1210
1189
  return;
1211
1190
  }
1212
1191
  if (command === "feature-flag") {
1213
- const { runFeatureFlag } = await import("./feature-flag-ESPSOSKG.js");
1192
+ const { runFeatureFlag } = await import("./feature-flag-ZDLDYRSF.js");
1214
1193
  await runFeatureFlag(rest);
1215
1194
  return;
1216
1195
  }
1217
1196
  if (command === "knobs") {
1218
- const { runKnobs } = await import("./knobs-HKONHY55.js");
1197
+ const { runKnobs } = await import("./knobs-3MKMOXIV.js");
1219
1198
  await runKnobs(rest);
1220
1199
  return;
1221
1200
  }
1201
+ if (command === "issues") {
1202
+ const { runIssues } = await import("./issues-FI3RIWGV.js");
1203
+ await runIssues(rest);
1204
+ return;
1205
+ }
1222
1206
  console.log(`Unknown command "${command}".`);
1223
1207
  printHelp({ isSuperadmin: await resolveIsSuperadmin() });
1224
1208
  process7.exit(1);