@usejourney/cli 0.1.5 → 0.2.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 (2) hide show
  1. package/dist/index.js +70 -57
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -24,8 +24,8 @@ async function runEnvList(projectDir) {
24
24
 
25
25
  // src/commands/exportK6.ts
26
26
  import { stat } from "fs/promises";
27
- import { isAbsolute, resolve } from "path";
28
- import { exportToK6 } from "@usejourney/k6-adapter";
27
+ import { dirname as dirname2, isAbsolute, resolve } from "path";
28
+ import { exportToK6, findProjectDir } from "@usejourney/k6-adapter";
29
29
 
30
30
  // src/util/discover.ts
31
31
  import { readdir } from "fs/promises";
@@ -58,6 +58,35 @@ async function importJourneyFiles(files) {
58
58
  }
59
59
  }
60
60
 
61
+ // src/util/projectCoreLink.ts
62
+ import { existsSync, readFileSync } from "fs";
63
+ import { mkdir, symlink } from "fs/promises";
64
+ import { dirname, join as join2 } from "path";
65
+ import { fileURLToPath } from "url";
66
+ function locateJourneyCoreDir() {
67
+ let dir = dirname(fileURLToPath(import.meta.url));
68
+ for (let depth = 0; depth < 50; depth++) {
69
+ const pkgJson = join2(dir, "node_modules", "@usejourney", "core", "package.json");
70
+ if (existsSync(pkgJson)) {
71
+ JSON.parse(readFileSync(pkgJson, "utf8"));
72
+ return dirname(pkgJson);
73
+ }
74
+ const parent = dirname(dir);
75
+ if (parent === dir) break;
76
+ dir = parent;
77
+ }
78
+ throw new Error("ensureProjectCoreLink: could not locate the CLI-bundled @usejourney/core");
79
+ }
80
+ var cachedCoreDir;
81
+ async function ensureProjectCoreLink(projectDir) {
82
+ const link = join2(projectDir, "node_modules", "@usejourney", "core");
83
+ if (existsSync(link)) return;
84
+ if (!cachedCoreDir) cachedCoreDir = locateJourneyCoreDir();
85
+ await mkdir(dirname(link), { recursive: true });
86
+ const type = process.platform === "win32" ? "junction" : "dir";
87
+ await symlink(cachedCoreDir, link, type);
88
+ }
89
+
61
90
  // src/commands/exportK6.ts
62
91
  function matches(def, tags) {
63
92
  if (tags.length === 0) return true;
@@ -97,6 +126,8 @@ async function runExportK6(opts) {
97
126
  console.log(`No .journey.ts files found in ${opts.path}`);
98
127
  return 0;
99
128
  }
129
+ const projectDir = findProjectDir(isDir ? target : dirname2(target)) ?? process.cwd();
130
+ await ensureProjectCoreLink(projectDir);
100
131
  const work = [];
101
132
  for (const file of files) {
102
133
  const defs = await loadJourneyDefs(file);
@@ -114,7 +145,10 @@ async function runExportK6(opts) {
114
145
  journeyFile: file,
115
146
  ...opts.out !== void 0 ? { outFile: opts.out } : {},
116
147
  ...opts.outDir !== void 0 ? { outDir: opts.outDir } : {},
117
- ...k6Options !== void 0 ? { k6Options } : {}
148
+ ...k6Options !== void 0 ? { k6Options } : {},
149
+ ...opts.metricsPrefix !== void 0 ? { metricsPrefix: opts.metricsPrefix } : {},
150
+ ...opts.haltOnFailure ? { haltOnFailure: true } : {},
151
+ projectDir
118
152
  });
119
153
  console.log(`Wrote k6 script \u2192 ${result.outFile}`);
120
154
  exported++;
@@ -126,8 +160,8 @@ async function runExportK6(opts) {
126
160
  }
127
161
 
128
162
  // src/commands/exportPostman.ts
129
- import { mkdir, stat as stat2, writeFile } from "fs/promises";
130
- import { basename, dirname, isAbsolute as isAbsolute2, join as join2, resolve as resolve2 } from "path";
163
+ import { mkdir as mkdir2, stat as stat2, writeFile } from "fs/promises";
164
+ import { basename, dirname as dirname3, isAbsolute as isAbsolute2, join as join3, resolve as resolve2 } from "path";
131
165
  import {
132
166
  clearActiveEnvironment,
133
167
  collectPipeline,
@@ -232,8 +266,8 @@ function uniqueFolderName(name, seen) {
232
266
  async function exportEnvironment(environmentsDir, envName, outDir) {
233
267
  const values = await loadEnvironment(environmentsDir, envName);
234
268
  const env = buildEnvironment(envName, values);
235
- const outFile = join2(outDir, `${envName}.postman_environment.json`);
236
- await mkdir(dirname(outFile), { recursive: true });
269
+ const outFile = join3(outDir, `${envName}.postman_environment.json`);
270
+ await mkdir2(dirname3(outFile), { recursive: true });
237
271
  await writeFile(outFile, JSON.stringify(env, null, 2), "utf8");
238
272
  return outFile;
239
273
  }
@@ -319,8 +353,8 @@ async function runExportPostman(opts) {
319
353
  const collection = buildCollection(opts.name ?? "journeys", mergedFolders, {
320
354
  reset: opts.threadState ?? false
321
355
  });
322
- const collectionOutDir = dirname(outFile);
323
- await mkdir(collectionOutDir, { recursive: true });
356
+ const collectionOutDir = dirname3(outFile);
357
+ await mkdir2(collectionOutDir, { recursive: true });
324
358
  await writeFile(outFile, JSON.stringify(collection, null, 2), "utf8");
325
359
  console.log(`Wrote Postman collection \u2192 ${outFile}`);
326
360
  exported++;
@@ -351,9 +385,9 @@ async function runExportPostman(opts) {
351
385
  reset: opts.threadState ?? false
352
386
  });
353
387
  const json = JSON.stringify(collection, null, 2);
354
- const outFile = opts.out ? resolve2(process.cwd(), opts.out) : opts.outDir ? resolve2(process.cwd(), opts.outDir, `${fileBase}.postman_collection.json`) : join2(dirname(file), `${fileBase}.postman_collection.json`);
355
- const collectionOutDir = dirname(outFile);
356
- await mkdir(collectionOutDir, { recursive: true });
388
+ const outFile = opts.out ? resolve2(process.cwd(), opts.out) : opts.outDir ? resolve2(process.cwd(), opts.outDir, `${fileBase}.postman_collection.json`) : join3(dirname3(file), `${fileBase}.postman_collection.json`);
389
+ const collectionOutDir = dirname3(outFile);
390
+ await mkdir2(collectionOutDir, { recursive: true });
357
391
  await writeFile(outFile, json, "utf8");
358
392
  console.log(`Wrote Postman collection \u2192 ${outFile}`);
359
393
  exported++;
@@ -388,8 +422,8 @@ async function runGenerate(projectDir) {
388
422
  }
389
423
 
390
424
  // src/commands/init.ts
391
- import { access, copyFile, mkdir as mkdir2, readdir as readdir2, writeFile as writeFile2 } from "fs/promises";
392
- import { basename as basename2, isAbsolute as isAbsolute3, join as join3, resolve as resolve3 } from "path";
425
+ import { access, copyFile, mkdir as mkdir3, readdir as readdir2, writeFile as writeFile2 } from "fs/promises";
426
+ import { basename as basename2, isAbsolute as isAbsolute3, join as join4, resolve as resolve3 } from "path";
393
427
  import { generate as generate2, loadSpec } from "@usejourney/codegen";
394
428
  async function isEmpty(dir) {
395
429
  try {
@@ -416,12 +450,12 @@ async function runInit(opts) {
416
450
  }
417
451
  await loadSpec(specSource);
418
452
  const specDestName = basename2(specSource);
419
- const specDest = join3(projectDir, specDestName);
420
- await mkdir2(projectDir, { recursive: true });
421
- await mkdir2(join3(projectDir, "generated"), { recursive: true });
422
- await mkdir2(join3(projectDir, "journeys"), { recursive: true });
423
- await mkdir2(join3(projectDir, "environments"), { recursive: true });
424
- await mkdir2(join3(projectDir, ".journey", "cache"), { recursive: true });
453
+ const specDest = join4(projectDir, specDestName);
454
+ await mkdir3(projectDir, { recursive: true });
455
+ await mkdir3(join4(projectDir, "generated"), { recursive: true });
456
+ await mkdir3(join4(projectDir, "journeys"), { recursive: true });
457
+ await mkdir3(join4(projectDir, "environments"), { recursive: true });
458
+ await mkdir3(join4(projectDir, ".journey", "cache"), { recursive: true });
425
459
  await copyFile(specSource, specDest);
426
460
  const config = {
427
461
  name: basename2(projectDir),
@@ -431,23 +465,23 @@ async function runInit(opts) {
431
465
  environmentsDir: "environments"
432
466
  };
433
467
  await writeFile2(
434
- join3(projectDir, "journey.config.json"),
468
+ join4(projectDir, "journey.config.json"),
435
469
  `${JSON.stringify(config, null, 2)}
436
470
  `,
437
471
  "utf8"
438
472
  );
439
- await writeFile2(join3(projectDir, ".gitignore"), `.journey/cache/
473
+ await writeFile2(join4(projectDir, ".gitignore"), `.journey/cache/
440
474
  node_modules/
441
475
  `, "utf8");
442
476
  await writeFile2(
443
- join3(projectDir, "package.json"),
477
+ join4(projectDir, "package.json"),
444
478
  `${JSON.stringify({ name: basename2(projectDir), private: true, type: "module" }, null, 2)}
445
479
  `,
446
480
  "utf8"
447
481
  );
448
482
  const generated = await generate2({
449
483
  specPath: specDest,
450
- outDir: join3(projectDir, "generated")
484
+ outDir: join4(projectDir, "generated")
451
485
  });
452
486
  console.log(
453
487
  `Initialized Journey project at ${projectDir} (${generated.operationCount} operations).`
@@ -461,7 +495,7 @@ node_modules/
461
495
 
462
496
  // src/commands/run.ts
463
497
  import { watch } from "fs/promises";
464
- import { dirname as dirname3, isAbsolute as isAbsolute4, join as join5, resolve as resolve4 } from "path";
498
+ import { dirname as dirname4, isAbsolute as isAbsolute4, join as join5, resolve as resolve4 } from "path";
465
499
  import {
466
500
  clearActiveEnvironment as clearActiveEnvironment2,
467
501
  createConsoleLogger,
@@ -533,35 +567,6 @@ async function configureDispatcher(opts) {
533
567
  return agent;
534
568
  }
535
569
 
536
- // src/util/projectCoreLink.ts
537
- import { existsSync, readFileSync } from "fs";
538
- import { mkdir as mkdir3, symlink } from "fs/promises";
539
- import { dirname as dirname2, join as join4 } from "path";
540
- import { fileURLToPath } from "url";
541
- function locateJourneyCoreDir() {
542
- let dir = dirname2(fileURLToPath(import.meta.url));
543
- for (let depth = 0; depth < 50; depth++) {
544
- const pkgJson = join4(dir, "node_modules", "@usejourney", "core", "package.json");
545
- if (existsSync(pkgJson)) {
546
- JSON.parse(readFileSync(pkgJson, "utf8"));
547
- return dirname2(pkgJson);
548
- }
549
- const parent = dirname2(dir);
550
- if (parent === dir) break;
551
- dir = parent;
552
- }
553
- throw new Error("ensureProjectCoreLink: could not locate the CLI-bundled @usejourney/core");
554
- }
555
- var cachedCoreDir;
556
- async function ensureProjectCoreLink(projectDir) {
557
- const link = join4(projectDir, "node_modules", "@usejourney", "core");
558
- if (existsSync(link)) return;
559
- if (!cachedCoreDir) cachedCoreDir = locateJourneyCoreDir();
560
- await mkdir3(dirname2(link), { recursive: true });
561
- const type = process.platform === "win32" ? "junction" : "dir";
562
- await symlink(cachedCoreDir, link, type);
563
- }
564
-
565
570
  // src/commands/run.ts
566
571
  async function runCommand(opts) {
567
572
  const loaded = await loadConfig4(opts.projectDir);
@@ -578,7 +583,7 @@ async function runCommand(opts) {
578
583
  }
579
584
  await ensureProjectCoreLink(opts.projectDir);
580
585
  await importJourneyFiles(files);
581
- const ctx = {};
586
+ const ctx = { baseDir: opts.projectDir };
582
587
  const baseUrl = resolveBaseUrl(loaded.config);
583
588
  if (baseUrl) ctx.baseUrl = baseUrl;
584
589
  const logger = opts.debug ? createConsoleLogger() : loggerFromEnv();
@@ -624,7 +629,7 @@ async function runCommand(opts) {
624
629
  timer = setTimeout(() => void rerun(), DEBOUNCE_MS);
625
630
  };
626
631
  const dirs = /* @__PURE__ */ new Set([paths.journeysDir]);
627
- for (const f of files) dirs.add(dirname3(f));
632
+ for (const f of files) dirs.add(dirname4(f));
628
633
  const watchers = [];
629
634
  for (const dir of dirs) {
630
635
  try {
@@ -741,7 +746,7 @@ async function runJourneyFile(opts) {
741
746
  }
742
747
  await ensureProjectCoreLink(opts.loaded.projectDir);
743
748
  await importJourneyFiles([abs]);
744
- const ctx = {};
749
+ const ctx = { baseDir: opts.loaded.projectDir };
745
750
  const baseUrl = resolveBaseUrl2(opts.loaded.config);
746
751
  if (baseUrl) ctx.baseUrl = baseUrl;
747
752
  const logger = opts.logger ?? (opts.debug ? createConsoleLogger2() : loggerFromEnv2());
@@ -1815,12 +1820,20 @@ function buildProgram() {
1815
1820
  "Only export journeys with this tag (repeatable, AND across repeats)",
1816
1821
  (v, prev = []) => [...prev, v],
1817
1822
  []
1823
+ ).option(
1824
+ "--metrics-prefix <prefix>",
1825
+ "Emit custom metrics per step (<prefix>_<step>_duration Trend, <prefix>_<step>_tps Counter) and per iteration (<prefix>_flow_duration / <prefix>_flow_tps)"
1826
+ ).option(
1827
+ "--halt-on-failure",
1828
+ "Stop an iteration's remaining steps when an assert fails (mirrors journey run)"
1818
1829
  ).description("Export one or more journeys as k6 scripts (path may be a file or directory)").action(
1819
1830
  (path, options) => handle(
1820
1831
  () => runExportK6({
1821
1832
  path,
1822
1833
  ...options.out !== void 0 ? { out: options.out } : {},
1823
1834
  ...options.outDir !== void 0 ? { outDir: options.outDir } : {},
1835
+ ...options.metricsPrefix !== void 0 ? { metricsPrefix: options.metricsPrefix } : {},
1836
+ ...options.haltOnFailure ? { haltOnFailure: true } : {},
1824
1837
  tags: options.tag
1825
1838
  })
1826
1839
  )
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usejourney/cli",
3
- "version": "0.1.5",
3
+ "version": "0.2.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -23,10 +23,10 @@
23
23
  "commander": "^12.1.0",
24
24
  "tsx": "^4.21.0",
25
25
  "undici": "^8.3.0",
26
- "@usejourney/codegen": "^0.1.5",
27
- "@usejourney/core": "0.1.5",
28
- "@usejourney/k6-adapter": "^0.1.5",
29
- "@usejourney/postman-adapter": "^0.1.5"
26
+ "@usejourney/codegen": "^0.2.0",
27
+ "@usejourney/core": "0.2.0",
28
+ "@usejourney/k6-adapter": "^0.2.0",
29
+ "@usejourney/postman-adapter": "^0.2.0"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@types/newman": "^5.3.6",