kryptheon 0.1.16 → 0.1.17

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/bin/kryptheon.js CHANGED
@@ -2057,6 +2057,57 @@ async function finishWith(code) {
2057
2057
  );
2058
2058
  }
2059
2059
 
2060
+ // The copy that must run `check` is the one the recordings load. Measured: in
2061
+ // a folder `record` set up, `npx kryptheon@latest check` ran npx's copy, whose
2062
+ // Playwright loads the config, while the recordings loaded the folder's copy -
2063
+ // two Playwrights, and "Requiring @playwright/test second time" before a single
2064
+ // recording ran. `npx kryptheon check` worked in the same folder only because
2065
+ // npx happened to pick the local copy.
2066
+ //
2067
+ // So when this is not the folder's copy, the folder's copy does the work.
2068
+ // Returns its exit code, or null to carry on here.
2069
+ function handToFolderCopy() {
2070
+ if (process.env.KRYPTHEON_HANDED_OVER) return null; // once, never in a loop
2071
+ const theirs = project.kryptheonCopyFor(USER_DIR);
2072
+ if (!theirs) return null;
2073
+ let same = false;
2074
+ try {
2075
+ same = fs.realpathSync(theirs) === fs.realpathSync(PACKAGE_DIR);
2076
+ } catch (err) {
2077
+ same = path.resolve(theirs) === path.resolve(PACKAGE_DIR);
2078
+ }
2079
+ if (same) return null;
2080
+
2081
+ let theirVersion = 'unknown';
2082
+ try {
2083
+ theirVersion = JSON.parse(fs.readFileSync(path.join(theirs, 'package.json'), 'utf8')).version;
2084
+ } catch (err) {
2085
+ /* said as unknown */
2086
+ }
2087
+ const mine = packageVersion();
2088
+ if (theirVersion !== mine) {
2089
+ // Not an error: the folder's copy is the one its recordings are written
2090
+ // against. Said, so an older one is never mistaken for this one.
2091
+ console.log('');
2092
+ console.log(' Running the kryptheon installed in this folder (' + theirVersion + '), because your');
2093
+ console.log(' recordings load that one. ' + (mine !== 'unknown' ? 'To move this folder to ' + mine + ':' : 'To update it:'));
2094
+ console.log(' npm i -D kryptheon@latest');
2095
+ }
2096
+ const result = spawnSync(process.execPath, [path.join(theirs, 'bin', 'kryptheon.js')].concat(process.argv.slice(2)), {
2097
+ cwd: USER_DIR,
2098
+ stdio: 'inherit',
2099
+ env: Object.assign({}, process.env, { KRYPTHEON_HANDED_OVER: '1' }),
2100
+ });
2101
+ if (result.error) {
2102
+ console.error('');
2103
+ console.error(' Could not run the kryptheon installed in this folder: ' + result.error.message);
2104
+ console.error(' Reinstalling it usually fixes this: npm i -D kryptheon@latest');
2105
+ console.error('');
2106
+ return 1;
2107
+ }
2108
+ return result.status === null ? 1 : result.status;
2109
+ }
2110
+
2060
2111
  async function main() {
2061
2112
  if (nodeIsTooOld()) {
2062
2113
  console.error('');
@@ -2073,9 +2124,11 @@ async function main() {
2073
2124
  case 'record':
2074
2125
  return finishWith(await record(rest[0]));
2075
2126
  break;
2076
- case 'check':
2127
+ case 'check': {
2128
+ const handedOver = handToFolderCopy();
2129
+ if (handedOver !== null) return finishWith(handedOver);
2077
2130
  return finishWith(check({ quiet: rest.indexOf('--quiet') !== -1 || rest.indexOf('-q') !== -1 }));
2078
- break;
2131
+ }
2079
2132
  case 'remove':
2080
2133
  case 'rm':
2081
2134
  return finishWith(await remove(rest.join(" ").trim()));
@@ -2122,6 +2175,7 @@ module.exports = {
2122
2175
  rulesBlock: rulesBlock,
2123
2176
  record: record,
2124
2177
  prepareFolder: prepareFolder,
2178
+ handToFolderCopy: handToFolderCopy,
2125
2179
  finaliseRecording: finaliseRecording,
2126
2180
  takeOutSecrets: takeOutSecrets,
2127
2181
  reportSecrets: reportSecrets,
@@ -238,6 +238,31 @@ function noRecordingsLines() {
238
238
  // missing before the browser, which is a 200MB download on a new machine, and
239
239
  // offers to add it.
240
240
 
241
+ /**
242
+ * The installed kryptheon a recording saved in this folder will load - the
243
+ * nearest node_modules/kryptheon going up - or null if there is none.
244
+ *
245
+ * `check` must be run by this same copy. Found through the MCP server, then
246
+ * measured by hand in a folder `record` had set up: `npx kryptheon@latest
247
+ * check` runs npx's own copy, whose Playwright loads the config, while the
248
+ * recordings load this one's - and Playwright stops with "Requiring
249
+ * @playwright/test second time" before a single recording runs.
250
+ */
251
+ function kryptheonCopyFor(dir) {
252
+ let current = path.resolve(String(dir || ''));
253
+ for (;;) {
254
+ const candidate = path.join(current, 'node_modules', 'kryptheon');
255
+ // Whole copies only. A half-finished install - the fixture there, the rest
256
+ // not - was handed the run and answered with Node's own stack trace.
257
+ const whole = ['kryptheon-fixture.js', 'package.json', path.join('bin', 'kryptheon.js')]
258
+ .every((f) => fs.existsSync(path.join(candidate, f)));
259
+ if (whole) return candidate;
260
+ const parent = path.dirname(current);
261
+ if (parent === current) return null;
262
+ current = parent;
263
+ }
264
+ }
265
+
241
266
  /**
242
267
  * Whether kryptheon can be loaded by a recording saved in this folder.
243
268
  *
@@ -505,6 +530,7 @@ module.exports = {
505
530
  ESCAPE_HATCH: ESCAPE_HATCH,
506
531
  HOME_RECORDINGS: HOME_RECORDINGS,
507
532
  kryptheonReachableFrom: kryptheonReachableFrom,
533
+ kryptheonCopyFor: kryptheonCopyFor,
508
534
  kryptheonInstalledIn: kryptheonInstalledIn,
509
535
  projectAbove: projectAbove,
510
536
  setupPlan: setupPlan,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kryptheon",
3
- "version": "0.1.16",
3
+ "version": "0.1.17",
4
4
  "description": "Record what you do in your app and get plain-language reports when it breaks.",
5
5
  "license": "MIT",
6
6
  "type": "commonjs",