@qawolf/cli 1.2.0 → 1.3.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.
package/dist/cli.js CHANGED
@@ -134044,7 +134044,7 @@ var require_snapshot_utils = __commonJS((exports, module) => {
134044
134044
  // node_modules/undici/lib/mock/snapshot-recorder.js
134045
134045
  var require_snapshot_recorder = __commonJS((exports, module) => {
134046
134046
  var { writeFile, readFile, mkdir } = __require("node:fs/promises");
134047
- var { dirname: dirname10, resolve: resolve9 } = __require("node:path");
134047
+ var { dirname: dirname11, resolve: resolve9 } = __require("node:path");
134048
134048
  var { setTimeout: setTimeout3, clearTimeout: clearTimeout2 } = __require("node:timers");
134049
134049
  var { InvalidArgumentError: InvalidArgumentError3, UndiciError } = require_errors6();
134050
134050
  var { hashId, isUrlExcludedFactory, normalizeHeaders, createHeaderFilters } = require_snapshot_utils();
@@ -134239,7 +134239,7 @@ var require_snapshot_recorder = __commonJS((exports, module) => {
134239
134239
  throw new InvalidArgumentError3("Snapshot path is required");
134240
134240
  }
134241
134241
  const resolvedPath = resolve9(path4);
134242
- await mkdir(dirname10(resolvedPath), { recursive: true });
134242
+ await mkdir(dirname11(resolvedPath), { recursive: true });
134243
134243
  const data2 = Array.from(this.#snapshots.entries()).map(([hash2, snapshot]) => ({
134244
134244
  hash: hash2,
134245
134245
  snapshot
@@ -155273,6 +155273,10 @@ var flowsMessages = {
155273
155273
  title: "Flows",
155274
155274
  remoteTitle: "Remote Flows",
155275
155275
  flowCount: (count) => pluralize(count, "flow"),
155276
+ list: {
155277
+ remoteRequiresEnv: "--remote requires --env <env> to pick the environment to list",
155278
+ flagsRequireRemote: "--env and --include-drafts require --remote"
155279
+ },
155276
155280
  pull: {
155277
155281
  downloadingBundle: "Downloading flows bundle",
155278
155282
  fetchingEnvVars: "Fetching environment variables",
@@ -170022,7 +170026,8 @@ async function validateApiKey(deps) {
170022
170026
  }
170023
170027
  // src/shell/logger.ts
170024
170028
  var import_pino = __toESM(require_pino(), 1);
170025
- import { join as join4 } from "node:path";
170029
+ import { mkdirSync as mkdirSync2, openSync } from "node:fs";
170030
+ import { dirname, join as join4 } from "node:path";
170026
170031
  function defaultLogPath() {
170027
170032
  return join4(envPaths("qawolf", { suffix: "" }).log, "cli.log");
170028
170033
  }
@@ -170036,7 +170041,8 @@ function resolveStderrLevel(env2, verbose) {
170036
170041
  }
170037
170042
  function createLoggingSystem(opts) {
170038
170043
  const { stderrLevel, logPath } = opts;
170039
- const dest = import_pino.default.destination({ dest: logPath, mkdir: true, sync: false });
170044
+ mkdirSync2(dirname(logPath), { recursive: true });
170045
+ const dest = import_pino.default.destination({ fd: openSync(logPath, "a"), sync: false });
170040
170046
  const fileLogger = import_pino.default({ level: "debug" }, dest);
170041
170047
  const levelNums = {
170042
170048
  trace: 10,
@@ -171158,45 +171164,6 @@ async function getIdentity(apiKey, deps) {
171158
171164
  return { ok: true, data: parsed.data };
171159
171165
  }
171160
171166
 
171161
- // src/shell/platform/getRemoteFlows.ts
171162
- var remoteFlowSchema = exports_external.object({
171163
- executionTarget: exports_external.union([exports_external.string(), exports_external.record(exports_external.string(), exports_external.unknown())]),
171164
- id: exports_external.string(),
171165
- name: exports_external.string(),
171166
- path: exports_external.string(),
171167
- tags: exports_external.array(exports_external.string())
171168
- });
171169
- var remoteFlowsResponseSchema = exports_external.object({
171170
- flows: exports_external.array(remoteFlowSchema)
171171
- });
171172
- async function getRemoteFlows(apiKey, deps) {
171173
- const url2 = `${deps.baseUrl}/api/v0/flows?includeDrafts=false`;
171174
- let response;
171175
- try {
171176
- response = await deps.fetch(url2, {
171177
- headers: { Authorization: `Bearer ${apiKey}` },
171178
- signal: AbortSignal.timeout(15000)
171179
- });
171180
- } catch (error51) {
171181
- return { ok: false, error: { kind: "network", cause: toError(error51) } };
171182
- }
171183
- if (!response.ok) {
171184
- const body = await response.text().catch(() => "");
171185
- return {
171186
- ok: false,
171187
- error: { kind: "http", status: response.status, body }
171188
- };
171189
- }
171190
- const json2 = await response.json().catch(() => {
171191
- return;
171192
- });
171193
- const parsed = remoteFlowsResponseSchema.safeParse(json2);
171194
- if (!parsed.success) {
171195
- return { ok: false, error: { kind: "parse", cause: parsed.error } };
171196
- }
171197
- return { ok: true, data: parsed.data };
171198
- }
171199
-
171200
171167
  // src/shell/platform/types.ts
171201
171168
  var environmentListItemSchema = exports_external.object({
171202
171169
  envId: exports_external.string(),
@@ -171250,10 +171217,10 @@ async function listTeamStorageFiles(trpc, args, deps) {
171250
171217
  }
171251
171218
 
171252
171219
  // src/shell/platform/teamStorageAssets.ts
171253
- import { dirname as dirname2, join as join8 } from "node:path";
171220
+ import { dirname as dirname3, join as join8 } from "node:path";
171254
171221
 
171255
171222
  // src/shell/platform/teamStorageAssetManifest.ts
171256
- import { dirname } from "node:path";
171223
+ import { dirname as dirname2 } from "node:path";
171257
171224
  var assetManifestSchema = exports_external.object({
171258
171225
  version: exports_external.literal(1),
171259
171226
  files: exports_external.array(exports_external.object({
@@ -171297,7 +171264,7 @@ async function writeAssetManifest(assetsAbs, files, fs2) {
171297
171264
  }))
171298
171265
  };
171299
171266
  const path2 = assetManifestPath(assetsAbs);
171300
- await fs2.mkdir(dirname(path2), { recursive: true });
171267
+ await fs2.mkdir(dirname2(path2), { recursive: true });
171301
171268
  await fs2.writeFile(path2, `${JSON.stringify(manifest, undefined, 2)}
171302
171269
  `);
171303
171270
  }
@@ -171463,7 +171430,7 @@ async function writeAssetSnapshot(args) {
171463
171430
  await args.deps.fs.mkdir(args.tmpAssets, { recursive: true });
171464
171431
  for (const { file: file2, relativePath } of args.safeFiles) {
171465
171432
  const dest = join8(args.tmpAssets, relativePath);
171466
- await args.deps.fs.mkdir(dirname2(dest), { recursive: true });
171433
+ await args.deps.fs.mkdir(dirname3(dest), { recursive: true });
171467
171434
  if (args.reusable.has(relativePath)) {
171468
171435
  await args.deps.fs.copyFile(join8(args.assetsAbs, relativePath), dest);
171469
171436
  continue;
@@ -171502,14 +171469,6 @@ function createPlatformClient(apiKey, deps) {
171502
171469
  sleep: deps.sleep
171503
171470
  });
171504
171471
  },
171505
- async getRemoteFlows() {
171506
- return requestWithRetry({
171507
- call: () => getRemoteFlows(apiKey, deps),
171508
- backoffMs: requestBackoffMs2,
171509
- describe: (err) => describeRequestError(err, deps.baseUrl, "flows"),
171510
- sleep: deps.sleep
171511
- });
171512
- },
171513
171472
  getFlowsBundleUrl: getFlowsBundleUrlImpl,
171514
171473
  callPublicApi: makeCallPublicApiMethod(trpc, deps, requestBackoffMs2),
171515
171474
  async getEnvVars(envId) {
@@ -173630,7 +173589,7 @@ function registerAuthCommand(program2, signals) {
173630
173589
  // package.json
173631
173590
  var package_default = {
173632
173591
  name: "@qawolf/cli",
173633
- version: "1.2.0",
173592
+ version: "1.3.0",
173634
173593
  description: "Run and manage QA Wolf flows from the terminal, CI, or an AI agent",
173635
173594
  keywords: [
173636
173595
  "automation",
@@ -173690,7 +173649,7 @@ var package_default = {
173690
173649
  "@napi-rs/keyring": "1.3.0",
173691
173650
  "@oxc-node/core": "0.1.0",
173692
173651
  "@playwright/test": "1.60.0",
173693
- "@qawolf/api-contracts": "0.1.0",
173652
+ "@qawolf/api-contracts": "0.2.0",
173694
173653
  "@qawolf/emails": "1.1.1",
173695
173654
  "@qawolf/flow-targets": "1.0.0",
173696
173655
  "@qawolf/flows": "0.1.1",
@@ -174217,13 +174176,13 @@ function renderResults(ui, results) {
174217
174176
  }
174218
174177
 
174219
174178
  // src/domains/flows/ensureDeps.ts
174220
- import { dirname as dirname3, join as join10 } from "node:path";
174179
+ import { dirname as dirname4, join as join10 } from "node:path";
174221
174180
  function findEnvDir(flowPath, fs2) {
174222
- let dir = dirname3(flowPath);
174181
+ let dir = dirname4(flowPath);
174223
174182
  while (true) {
174224
174183
  if (fs2.existsSync(join10(dir, "package.json")))
174225
174184
  return dir;
174226
- const parent = dirname3(dir);
174185
+ const parent = dirname4(dir);
174227
174186
  if (parent === dir)
174228
174187
  return;
174229
174188
  dir = parent;
@@ -174256,7 +174215,7 @@ import { fileURLToPath } from "url";
174256
174215
 
174257
174216
  // node_modules/fdir/dist/index.mjs
174258
174217
  import { createRequire as createRequire2 } from "module";
174259
- import { basename, dirname as dirname4, normalize as normalize2, relative as relative2, resolve, sep as sep3 } from "path";
174218
+ import { basename, dirname as dirname5, normalize as normalize2, relative as relative2, resolve, sep as sep3 } from "path";
174260
174219
  import * as nativeFs from "fs";
174261
174220
  var __require2 = /* @__PURE__ */ createRequire2(import.meta.url);
174262
174221
  function cleanPath(path2) {
@@ -174420,7 +174379,7 @@ function build$2(options, isSynchronous) {
174420
174379
  function isRecursive(path2, resolved, state) {
174421
174380
  if (state.options.useRealPaths)
174422
174381
  return isRecursiveUsingRealPaths(resolved, state);
174423
- let parent = dirname4(path2);
174382
+ let parent = dirname5(path2);
174424
174383
  let depth = 1;
174425
174384
  while (parent !== state.root && depth < 2) {
174426
174385
  const resolvedPath = state.symlinks.get(parent);
@@ -174428,7 +174387,7 @@ function isRecursive(path2, resolved, state) {
174428
174387
  if (isSameRoot)
174429
174388
  depth++;
174430
174389
  else
174431
- parent = dirname4(parent);
174390
+ parent = dirname5(parent);
174432
174391
  }
174433
174392
  state.symlinks.set(path2, resolved);
174434
174393
  return depth > 1;
@@ -174624,7 +174583,7 @@ var Walker = class {
174624
174583
  } else {
174625
174584
  resolvedPath = useRealPaths ? resolvedPath : path2;
174626
174585
  const filename = basename(resolvedPath);
174627
- const directoryPath$1 = normalizePath(dirname4(resolvedPath), this.state.options);
174586
+ const directoryPath$1 = normalizePath(dirname5(resolvedPath), this.state.options);
174628
174587
  resolvedPath = this.joinPath(filename, directoryPath$1);
174629
174588
  this.pushFile(resolvedPath, files, this.state.counts, filters);
174630
174589
  }
@@ -175702,14 +175661,80 @@ function handleFlowsList(ctx, pattern) {
175702
175661
 
175703
175662
  // src/domains/flows/listRemote.ts
175704
175663
  var import_picomatch2 = __toESM(require_picomatch2(), 1);
175705
- async function flowsListRemote(ctx, pattern) {
175706
- const result = await ctx.platform.getRemoteFlows();
175664
+
175665
+ // node_modules/@qawolf/api-contracts/dist/v1/ids.js
175666
+ var defaultIdSchemas = {
175667
+ environment: exports_external.string().min(1).describe("The id of the environment."),
175668
+ flow: exports_external.string().min(1).describe("The id of the flow."),
175669
+ run: exports_external.string().min(1).describe("The id of the run.")
175670
+ };
175671
+
175672
+ // node_modules/@qawolf/api-contracts/dist/v1/flow/index.js
175673
+ var makeListFlowsContract = (ids) => {
175674
+ const input = exports_external.object({
175675
+ environmentId: ids.environment,
175676
+ includeDrafts: exports_external.boolean().default(false).describe("Include draft flows in the listing.")
175677
+ });
175678
+ const executionTarget = exports_external.union([exports_external.string().min(1), exports_external.record(exports_external.string(), exports_external.unknown())]).describe("The target the flow executes against, as a preset or object.");
175679
+ const output = exports_external.object({
175680
+ flows: exports_external.array(exports_external.object({
175681
+ executionTarget,
175682
+ flowId: ids.flow,
175683
+ name: exports_external.string(),
175684
+ path: exports_external.string().describe("The flow file path, relative to the repo."),
175685
+ tags: exports_external.array(exports_external.string())
175686
+ }))
175687
+ });
175688
+ return {
175689
+ description: "List the flows of an environment at its latest reconciled commit.",
175690
+ input,
175691
+ kind: "read",
175692
+ name: "flow.list",
175693
+ output
175694
+ };
175695
+ };
175696
+
175697
+ // node_modules/@qawolf/api-contracts/dist/v1/run/index.js
175698
+ var makeCreateRunContract = (ids) => {
175699
+ const input = exports_external.object({
175700
+ environmentId: ids.environment,
175701
+ environmentVariables: exports_external.record(exports_external.string(), exports_external.string()).optional(),
175702
+ flowIds: exports_external.array(ids.flow).min(1),
175703
+ ignoreRules: exports_external.boolean().default(false)
175704
+ });
175705
+ const output = exports_external.object({ runId: ids.run });
175706
+ return {
175707
+ description: "Create a run for selected flows in an environment.",
175708
+ input,
175709
+ kind: "write",
175710
+ name: "run.create",
175711
+ output
175712
+ };
175713
+ };
175714
+
175715
+ // node_modules/@qawolf/api-contracts/dist/v1/index.js
175716
+ var makeContractsV1 = (ids) => ({
175717
+ flow: {
175718
+ list: makeListFlowsContract(ids)
175719
+ },
175720
+ run: {
175721
+ create: makeCreateRunContract(ids)
175722
+ }
175723
+ });
175724
+ var publicContractsV1 = makeContractsV1(defaultIdSchemas);
175725
+
175726
+ // src/domains/flows/listRemote.ts
175727
+ async function flowsListRemote(ctx, pattern, options) {
175728
+ const result = await ctx.platform.callPublicApi(publicContractsV1.flow.list, {
175729
+ environmentId: options.env,
175730
+ includeDrafts: options.includeDrafts
175731
+ });
175707
175732
  if (!result.ok) {
175708
175733
  return { error: result.error };
175709
175734
  }
175710
175735
  const matches = pattern ? import_picomatch2.default(pattern) : undefined;
175711
175736
  const items = result.value.flows.filter((f2) => !matches || matches(f2.path)).map((f2) => ({
175712
- id: f2.id,
175737
+ flowId: f2.flowId,
175713
175738
  file: f2.path,
175714
175739
  name: f2.name,
175715
175740
  tags: f2.tags,
@@ -175739,7 +175764,7 @@ async function flowsListRemote(ctx, pattern) {
175739
175764
  }
175740
175765
 
175741
175766
  // src/domains/flows/pull/handler.ts
175742
- import { dirname as dirname6, join as join23, resolve as resolve7 } from "node:path";
175767
+ import { dirname as dirname7, join as join23, resolve as resolve7 } from "node:path";
175743
175768
 
175744
175769
  // src/shell/manifest/io.ts
175745
175770
  import { createHash as createHash2 } from "node:crypto";
@@ -176130,7 +176155,7 @@ async function writeEnvFile(envDir, vars, fs2 = makeDefaultFs()) {
176130
176155
  }
176131
176156
 
176132
176157
  // src/domains/flows/pull/extract.ts
176133
- import { dirname as dirname5, resolve as resolve6 } from "node:path";
176158
+ import { dirname as dirname6, resolve as resolve6 } from "node:path";
176134
176159
  import { createGunzip } from "node:zlib";
176135
176160
 
176136
176161
  // node_modules/tar/dist/esm/index.min.js
@@ -179394,7 +179419,7 @@ async function handleEntry(args) {
179394
179419
  total: args.getTotal()
179395
179420
  });
179396
179421
  args.addTotal(size);
179397
- args.fs.mkdirSync(dirname5(target), { recursive: true });
179422
+ args.fs.mkdirSync(dirname6(target), { recursive: true });
179398
179423
  const chunks = [];
179399
179424
  await new Promise((res, rej) => {
179400
179425
  entry.on("data", (chunk) => chunks.push(chunk));
@@ -179498,7 +179523,7 @@ async function handleFlowsPull(ctx, opts, deps) {
179498
179523
  return { error: validation.error };
179499
179524
  }
179500
179525
  const destAbs = resolve7(opts.out ?? join23(".qawolf", opts.env));
179501
- const assetsAbs = join23(dirname6(destAbs), "assets");
179526
+ const assetsAbs = join23(dirname7(destAbs), "assets");
179502
179527
  await resolvedDeps.fs.mkdir(assetsAbs, { recursive: true });
179503
179528
  const yes = opts.yes ?? false;
179504
179529
  let archive;
@@ -180034,7 +180059,7 @@ async function defaultRunWebFlowDeps(cwd = process.cwd(), signals) {
180034
180059
 
180035
180060
  // src/domains/runtimeEnv/prepareRunDir.ts
180036
180061
  import { createHash as createHash3 } from "node:crypto";
180037
- import { basename as basename4, dirname as dirname9, join as join28, resolve as resolve8, sep as sep4 } from "node:path";
180062
+ import { basename as basename4, dirname as dirname10, join as join28, resolve as resolve8, sep as sep4 } from "node:path";
180038
180063
 
180039
180064
  // src/shell/copyDir.ts
180040
180065
  import { cp, readdir as readdir2 } from "node:fs/promises";
@@ -180075,7 +180100,7 @@ async function readPackageJson(pkgPath, fs3) {
180075
180100
  }
180076
180101
 
180077
180102
  // src/domains/runtimeEnv/innerHop.ts
180078
- import { dirname as dirname7, join as join26 } from "node:path";
180103
+ import { dirname as dirname8, join as join26 } from "node:path";
180079
180104
 
180080
180105
  // src/domains/runtimeEnv/symlinkDir.ts
180081
180106
  import { symlink } from "node:fs/promises";
@@ -180094,7 +180119,7 @@ async function populateInnerHop(args) {
180094
180119
  const segments = name.split("/");
180095
180120
  const target = join26(innerModules, ...segments);
180096
180121
  if (segments.length > 1) {
180097
- await fs3.mkdir(dirname7(target), { recursive: true });
180122
+ await fs3.mkdir(dirname8(target), { recursive: true });
180098
180123
  }
180099
180124
  await createDirSymlink(join26(managedModules, ...segments), target);
180100
180125
  }
@@ -180102,7 +180127,7 @@ async function populateInnerHop(args) {
180102
180127
 
180103
180128
  // src/domains/runtimeEnv/outerHop.ts
180104
180129
  import { lstat } from "node:fs/promises";
180105
- import { dirname as dirname8, join as join27 } from "node:path";
180130
+ import { dirname as dirname9, join as join27 } from "node:path";
180106
180131
  var executorPackageNames = new Set(pinnedPackages.map((p3) => p3.name));
180107
180132
  async function populateOuterHop(args) {
180108
180133
  const { projectDir, runDir, fs: fs3 } = args;
@@ -180133,7 +180158,7 @@ async function findSatisfyingNodeModulesDir(startDir, depNames, fs3) {
180133
180158
  return { satisfying: candidate, rejected };
180134
180159
  rejected.push({ dir: candidate, missing });
180135
180160
  }
180136
- const parent = dirname8(dir);
180161
+ const parent = dirname9(dir);
180137
180162
  if (parent === dir)
180138
180163
  return { satisfying: undefined, rejected };
180139
180164
  dir = parent;
@@ -180221,7 +180246,7 @@ async function stageFlowFiles(args) {
180221
180246
  }
180222
180247
  if (files.length > 1) {
180223
180248
  return Promise.all(files.map(async (f3) => {
180224
- const dirHash = createHash3("sha256").update(dirname9(f3)).digest("hex").slice(0, 8);
180249
+ const dirHash = createHash3("sha256").update(dirname10(f3)).digest("hex").slice(0, 8);
180225
180250
  const subDir = join28(execDir, dirHash);
180226
180251
  await fs3.mkdir(subDir, { recursive: true });
180227
180252
  const dest = join28(subDir, basename4(f3));
@@ -180834,12 +180859,12 @@ Install Android Studio and open Tools > SDK Manager.`);
180834
180859
  }
180835
180860
 
180836
180861
  // src/shell/manifest/lookup.ts
180837
- import { basename as basename5, dirname as dirname10, relative as relative6 } from "node:path";
180862
+ import { basename as basename5, dirname as dirname11, relative as relative6 } from "node:path";
180838
180863
  async function findFlowStamp(flowAbsPath) {
180839
180864
  let envDir;
180840
- let current = dirname10(flowAbsPath);
180841
- while (current !== dirname10(current)) {
180842
- const parent2 = dirname10(current);
180865
+ let current = dirname11(flowAbsPath);
180866
+ while (current !== dirname11(current)) {
180867
+ const parent2 = dirname11(current);
180843
180868
  if (basename5(parent2) === ".qawolf") {
180844
180869
  envDir = current;
180845
180870
  break;
@@ -181646,7 +181671,7 @@ async function runWebFlow({
181646
181671
  }
181647
181672
 
181648
181673
  // src/shell/embeddedWorkerCli.ts
181649
- import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
181674
+ import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
181650
181675
  import { basename as basename6, join as join32 } from "node:path";
181651
181676
  var embeddedCliPathEnv = "QAWOLF_EMBEDDED_CLI_PATH";
181652
181677
  function extractEmbeddedWorkerCli() {
@@ -181657,7 +181682,7 @@ function extractEmbeddedWorkerCli() {
181657
181682
  const dest = join32(dir, basename6(assetPath));
181658
181683
  if (existsSync3(dest))
181659
181684
  return dest;
181660
- mkdirSync2(dir, { recursive: true });
181685
+ mkdirSync3(dir, { recursive: true });
181661
181686
  writeFileSync2(dest, readFileSync2(assetPath));
181662
181687
  return dest;
181663
181688
  }
@@ -181807,7 +181832,7 @@ function makePooledDispatch(resolvedDir) {
181807
181832
  }
181808
181833
 
181809
181834
  // src/commands/flows/buildRunReporter.ts
181810
- import { dirname as dirname11 } from "node:path";
181835
+ import { dirname as dirname12 } from "node:path";
181811
181836
 
181812
181837
  // src/shell/reporter/createConsoleReporter.ts
181813
181838
  import { styleText as styleText3 } from "node:util";
@@ -182035,7 +182060,7 @@ function buildRunReporter(flags, deps) {
182035
182060
  const junit = createJUnitReporter({
182036
182061
  outputPath: resolveJUnitOutputPath(flags.junit, flags.outputDir),
182037
182062
  writeFile: (path9, content) => {
182038
- deps.fs.mkdirSync(dirname11(path9), { recursive: true });
182063
+ deps.fs.mkdirSync(dirname12(path9), { recursive: true });
182039
182064
  deps.fs.writeFileSync(path9, content);
182040
182065
  },
182041
182066
  stderr
@@ -182321,8 +182346,8 @@ var listExamples = `
182321
182346
  Examples:
182322
182347
  $ qawolf flows list
182323
182348
  $ qawolf flows list "flows/checkout/**"
182324
- $ qawolf flows list --remote
182325
- $ qawolf flows list "**/checkout/**" --remote`;
182349
+ $ qawolf flows list --remote --env staging
182350
+ $ qawolf flows list "**/checkout/**" --remote --env staging --include-drafts`;
182326
182351
  var pullExamples = `
182327
182352
  Examples:
182328
182353
  $ qawolf flows pull --env staging
@@ -182334,9 +182359,23 @@ function registerFlowsCommand(program2, signals) {
182334
182359
  registerRunWorkerCommand(flows, signals);
182335
182360
  declareCommandKind(flows.command("list [pattern]"), "local", {
182336
182361
  kindNote: "read with --remote"
182337
- }).description("List flows matching [pattern] from the local project, or from QA Wolf with --remote").option("--remote", "List flows from the QA Wolf platform instead of the local project", false).addHelpText("after", listExamples).action((pattern, opts, command) => {
182362
+ }).description("List flows matching [pattern] from the local project, or from a QA Wolf environment with --remote").option("--remote", "List flows from the QA Wolf platform instead of the local project", false).option("--env <env>", "Environment to list flows from (required with --remote)").option("--include-drafts", "Include draft flows in the listing (requires --remote)", false).addHelpText("after", listExamples).action((pattern, opts, command) => {
182338
182363
  if (opts.remote) {
182339
- return withAuthContext(signals, (ctx) => flowsListRemote(ctx, pattern))(opts, command);
182364
+ const env3 = opts.env;
182365
+ if (env3 === undefined) {
182366
+ return withContext(signals, async () => ({
182367
+ error: flowsMessages.list.remoteRequiresEnv
182368
+ }))(opts, command);
182369
+ }
182370
+ return withAuthContext(signals, (ctx) => flowsListRemote(ctx, pattern, {
182371
+ env: env3,
182372
+ includeDrafts: opts.includeDrafts
182373
+ }))(opts, command);
182374
+ }
182375
+ if (opts.env !== undefined || opts.includeDrafts) {
182376
+ return withContext(signals, async () => ({
182377
+ error: flowsMessages.list.flagsRequireRemote
182378
+ }))(opts, command);
182340
182379
  }
182341
182380
  return withContext(signals, (ctx) => handleFlowsList(ctx, pattern))(opts, command);
182342
182381
  });
@@ -182346,7 +182385,7 @@ function registerFlowsCommand(program2, signals) {
182346
182385
  }
182347
182386
 
182348
182387
  // src/domains/init/init.ts
182349
- import { dirname as dirname12, join as join36, relative as relative7 } from "node:path";
182388
+ import { dirname as dirname13, join as join36, relative as relative7 } from "node:path";
182350
182389
 
182351
182390
  // src/domains/init/templates.ts
182352
182391
  var qawolfConfigTs = `export default {
@@ -182405,7 +182444,7 @@ async function writeWithPrompt(ctx, filePath, content, yes, deps) {
182405
182444
  return;
182406
182445
  }
182407
182446
  }
182408
- await deps.fs.mkdir(dirname12(filePath), { recursive: true });
182447
+ await deps.fs.mkdir(dirname13(filePath), { recursive: true });
182409
182448
  await deps.fs.writeFile(filePath, content);
182410
182449
  ctx.ui.step(initMessages.createdFile(relPath));
182411
182450
  }
@@ -182779,39 +182818,6 @@ Examples:
182779
182818
  });
182780
182819
  }
182781
182820
 
182782
- // node_modules/@qawolf/api-contracts/dist/v1/ids.js
182783
- var defaultIdSchemas = {
182784
- environment: exports_external.string().min(1).describe("The id of the environment."),
182785
- flow: exports_external.string().min(1).describe("The id of the flow."),
182786
- run: exports_external.string().min(1).describe("The id of the run.")
182787
- };
182788
-
182789
- // node_modules/@qawolf/api-contracts/dist/v1/run/index.js
182790
- var makeCreateRunContract = (ids) => {
182791
- const input = exports_external.object({
182792
- environmentId: ids.environment,
182793
- environmentVariables: exports_external.record(exports_external.string(), exports_external.string()).optional(),
182794
- flowIds: exports_external.array(ids.flow).min(1),
182795
- ignoreRules: exports_external.boolean().default(false)
182796
- });
182797
- const output = exports_external.object({ runId: ids.run });
182798
- return {
182799
- description: "Create a run for selected flows in an environment.",
182800
- input,
182801
- kind: "write",
182802
- name: "run.create",
182803
- output
182804
- };
182805
- };
182806
-
182807
- // node_modules/@qawolf/api-contracts/dist/v1/index.js
182808
- var makeContractsV1 = (ids) => ({
182809
- run: {
182810
- create: makeCreateRunContract(ids)
182811
- }
182812
- });
182813
- var publicContractsV1 = makeContractsV1(defaultIdSchemas);
182814
-
182815
182821
  // src/core/publicApi/flagSpecs.ts
182816
182822
  var kebabCase = (field) => field.replace(/[A-Z]/g, (char) => `-${char.toLowerCase()}`);
182817
182823
  function flagKind(schema) {
@@ -182908,8 +182914,16 @@ function buildSpec(contract, path9) {
182908
182914
  contract
182909
182915
  };
182910
182916
  }
182911
- function buildCommandSpecs(tree) {
182912
- const walk3 = (node2, path9) => Object.entries(node2).flatMap(([key, value]) => isContract(value) ? [buildSpec(value, [...path9, key])] : walk3(value, [...path9, key]));
182917
+ function buildCommandSpecs(tree, options = {}) {
182918
+ const skip = options.skipContractNames;
182919
+ const walk3 = (node2, path9) => Object.entries(node2).flatMap(([key, value]) => {
182920
+ const childPath = [...path9, key];
182921
+ if (!isContract(value))
182922
+ return walk3(value, childPath);
182923
+ if (skip?.has(childPath.join(".")))
182924
+ return [];
182925
+ return [buildSpec(value, childPath)];
182926
+ });
182913
182927
  return walk3(tree, []);
182914
182928
  }
182915
182929
 
@@ -182980,6 +182994,7 @@ async function handlePublicApiCommand(ctx, spec, options) {
182980
182994
  var groupDescriptions = {
182981
182995
  run: "Trigger and manage QA Wolf runs on the platform"
182982
182996
  };
182997
+ var handWrittenContractNames = new Set(["flow.list"]);
182983
182998
  function resolveGroup(parent2, segment) {
182984
182999
  const existing = parent2.commands.find((command) => command.name() === segment);
182985
183000
  return existing ?? parent2.command(segment).description(groupDescriptions[segment] ?? `QA Wolf public API ${segment} commands`);
@@ -183005,7 +183020,9 @@ function registerSpec(program2, signals, spec, authDeps) {
183005
183020
  command.action((options, leaf) => withAuthContext(signals, (ctx) => handlePublicApiCommand(ctx, spec, options), authDeps ?? {})(options, leaf));
183006
183021
  }
183007
183022
  function registerPublicApiCommands(program2, signals, options = {}) {
183008
- const specs = buildCommandSpecs(options.contracts ?? publicContractsV1);
183023
+ const specs = buildCommandSpecs(options.contracts ?? publicContractsV1, {
183024
+ skipContractNames: handWrittenContractNames
183025
+ });
183009
183026
  for (const spec of specs) {
183010
183027
  registerSpec(program2, signals, spec, options.authDeps);
183011
183028
  }
@@ -183046,4 +183063,4 @@ createProgram({ signals }).parseAsync().catch(() => {
183046
183063
  process.exitCode = 1;
183047
183064
  }).finally(() => flushAndExit(typeof process.exitCode === "number" ? process.exitCode : 0));
183048
183065
 
183049
- //# debugId=2C8E0221ECEF946764756E2164756E21
183066
+ //# debugId=64AB4032821CC8E864756E2164756E21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qawolf/cli",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "Run and manage QA Wolf flows from the terminal, CI, or an AI agent",
5
5
  "keywords": [
6
6
  "automation",
@@ -60,7 +60,7 @@
60
60
  "@napi-rs/keyring": "1.3.0",
61
61
  "@oxc-node/core": "0.1.0",
62
62
  "@playwright/test": "1.60.0",
63
- "@qawolf/api-contracts": "0.1.0",
63
+ "@qawolf/api-contracts": "0.2.0",
64
64
  "@qawolf/emails": "1.1.1",
65
65
  "@qawolf/flow-targets": "1.0.0",
66
66
  "@qawolf/flows": "0.1.1",
@@ -41,7 +41,7 @@ write on timeout: it may have reached the server the first time.
41
41
  | `qawolf auth logout` | local | Remove stored credentials |
42
42
  | `qawolf auth whoami` | read | Show authentication status |
43
43
  | `qawolf doctor` | local | Diagnose problems running flows locally |
44
- | `qawolf flows list` | local (read with --remote) | List flows matching [pattern] from the local project, or from QA Wolf with --remote |
44
+ | `qawolf flows list` | local (read with --remote) | List flows matching [pattern] from the local project, or from a QA Wolf environment with --remote |
45
45
  | `qawolf flows pull` | read | Download an environment's flows into the local .qawolf/<env>/ cache |
46
46
  | `qawolf flows run` | local (read with --env) | Run flows matching [pattern], or every flow when omitted; with --env, pull missing flows from that QA Wolf environment |
47
47
  | `qawolf init` | local | Scaffold a QA Wolf project in the current directory |