mason-context 0.17.3 → 0.18.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.
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/hook/hook.ts
4
- import fs5 from "fs/promises";
4
+ import fs6 from "fs/promises";
5
5
  import path10 from "path";
6
- import os from "os";
6
+ import os2 from "os";
7
7
 
8
8
  // src/decisions/decisions.ts
9
- import fs3 from "fs/promises";
9
+ import fs4 from "fs/promises";
10
10
  import path7 from "path";
11
11
  import { createHash } from "crypto";
12
12
  import { z as z3 } from "zod";
@@ -34,14 +34,48 @@ function matchingPaths(anchors, files) {
34
34
  return [...new Set(files)].filter((file) => anchors.some((anchor) => anchorMatches(anchor, file)));
35
35
  }
36
36
 
37
+ // src/utils/git-read.ts
38
+ import { execFile } from "child_process";
39
+ import { promisify } from "util";
40
+
41
+ // src/utils/profile.ts
42
+ import { AsyncLocalStorage } from "async_hooks";
43
+ var profiles = new AsyncLocalStorage();
44
+ async function profilePhase(label, run) {
45
+ const phases = profiles.getStore();
46
+ if (!phases) return run();
47
+ const start = performance.now();
48
+ try {
49
+ return await run();
50
+ } finally {
51
+ const timing = phases[label] ??= { calls: 0, totalMs: 0 };
52
+ timing.calls++;
53
+ timing.totalMs += performance.now() - start;
54
+ }
55
+ }
56
+
57
+ // src/utils/git-read.ts
58
+ var execute = promisify(execFile);
59
+ var commands = /* @__PURE__ */ new Set(["rev-parse", "symbolic-ref", "for-each-ref", "ls-files", "check-ignore", "status", "log", "diff", "ls-tree", "show", "merge-base"]);
60
+ function execGit(args, options) {
61
+ const command = args.find((arg) => !arg.startsWith("-")) ?? "other";
62
+ return profilePhase("git." + (commands.has(command) ? command : "other"), async () => {
63
+ const { input, ...processOptions } = options;
64
+ const operation = execute("git", args, processOptions);
65
+ if (input !== void 0) {
66
+ operation.child.stdin.on("error", () => {
67
+ });
68
+ operation.child.stdin.end(input);
69
+ }
70
+ return operation;
71
+ });
72
+ }
73
+
37
74
  // src/utils/files.ts
38
75
  import fs from "fs/promises";
39
76
  import { constants } from "fs";
40
77
  import path2 from "path";
41
- import { execFile } from "child_process";
42
- import { promisify } from "util";
43
78
  import fg from "fast-glob";
44
- var exec = promisify(execFile);
45
79
  var SOURCE_EXTENSIONS = ["ts", "tsx", "js", "jsx", "mts", "cts", "mjs", "cjs", "vue", "svelte", "kt", "kts", "java", "py", "go", "rs", "swift", "rb", "cs", "cpp", "c", "h", "hpp", "dart", "php"];
46
80
  var SOURCE_GLOB = `**/*.{${SOURCE_EXTENSIONS.join(",")}}`;
47
81
  var MAX_SOURCE_BYTES = 1024 * 1024;
@@ -105,20 +139,22 @@ async function readStoreJson(root, relative) {
105
139
 
106
140
  // src/snapshot/snapshot.ts
107
141
  import path5 from "path";
108
- import { execFile as execFile2 } from "child_process";
109
- import { promisify as promisify2 } from "util";
110
142
  import { z } from "zod";
111
143
 
144
+ // src/utils/store-lock.ts
145
+ import fs3 from "fs/promises";
146
+ import os from "os";
147
+
112
148
  // src/test-map.ts
113
149
  import path4 from "path";
114
150
 
115
151
  // src/snapshot/snapshot.ts
116
- var exec2 = promisify2(execFile2);
117
152
  var repoPath = z.string().refine((value) => normalizeRepoPath(value) !== null, "Expected a relative repository path");
118
153
  var verificationFields = {
119
154
  refreshedHash: z.string().optional(),
120
155
  verifiedAt: z.string().optional(),
121
156
  verifiedHash: z.string().optional(),
157
+ verificationToken: z.string().optional(),
122
158
  verificationFailed: z.boolean().optional(),
123
159
  verificationNote: z.string().optional()
124
160
  };
@@ -140,7 +176,7 @@ var snapshotSchema = z.object({
140
176
  }).passthrough();
141
177
  async function getCurrentGitHash(rootDir) {
142
178
  try {
143
- const { stdout } = await exec2("git", ["rev-parse", "HEAD"], {
179
+ const { stdout } = await execGit(["rev-parse", "HEAD"], {
144
180
  cwd: rootDir
145
181
  });
146
182
  return stdout.trim();
@@ -338,7 +374,7 @@ async function loadDecisionStore(rootDir) {
338
374
  const diagnostics = [];
339
375
  let entries;
340
376
  try {
341
- entries = await fs3.readdir(await storePath(rootDir, ".mason/decisions"));
377
+ entries = await fs4.readdir(await storePath(rootDir, ".mason/decisions"));
342
378
  } catch (error) {
343
379
  if (error.code !== "ENOENT") diagnostics.push({ path: ".mason/decisions", message: String(error) });
344
380
  return { records, diagnostics };
@@ -364,11 +400,8 @@ import { createHash as createHash2 } from "crypto";
364
400
  import path9 from "path";
365
401
 
366
402
  // src/drift/drift.ts
367
- import fs4 from "fs/promises";
403
+ import fs5 from "fs/promises";
368
404
  import path8 from "path";
369
- import { execFile as execFile3 } from "child_process";
370
- import { promisify as promisify3 } from "util";
371
- var exec3 = promisify3(execFile3);
372
405
  function parseChanges(output) {
373
406
  const fields = output.split("\0");
374
407
  const changes = [];
@@ -389,7 +422,7 @@ function touchedPaths(changes) {
389
422
  async function getChangesWithStatus(resolvedRoot, fromHash, toHash = "HEAD") {
390
423
  if (!fromHash || fromHash === "unknown" || fromHash.startsWith("-") || !toHash || toHash === "unknown" || toHash.startsWith("-")) return null;
391
424
  try {
392
- const { stdout } = await exec3("git", ["diff", "--name-status", "-z", "-M", fromHash, toHash, "--"], { cwd: resolvedRoot, maxBuffer: 10 * 1024 * 1024 });
425
+ const { stdout } = await execGit(["diff", "--name-status", "-z", "-M", fromHash, toHash, "--"], { cwd: resolvedRoot, maxBuffer: 10 * 1024 * 1024 });
393
426
  return parseChanges(stdout);
394
427
  } catch {
395
428
  return null;
@@ -398,8 +431,8 @@ async function getChangesWithStatus(resolvedRoot, fromHash, toHash = "HEAD") {
398
431
  async function getWorkingTree(resolvedRoot) {
399
432
  try {
400
433
  const [diff, untracked] = await Promise.all([
401
- exec3("git", ["diff", "--name-status", "-z", "-M", "HEAD", "--"], { cwd: resolvedRoot, maxBuffer: 10 * 1024 * 1024 }),
402
- exec3("git", ["ls-files", "-z", "--others", "--exclude-standard"], { cwd: resolvedRoot, maxBuffer: 10 * 1024 * 1024 })
434
+ execGit(["diff", "--name-status", "-z", "-M", "HEAD", "--"], { cwd: resolvedRoot, maxBuffer: 10 * 1024 * 1024 }),
435
+ execGit(["ls-files", "-z", "--others", "--exclude-standard"], { cwd: resolvedRoot, maxBuffer: 10 * 1024 * 1024 })
403
436
  ]);
404
437
  const untrackedFiles = untracked.stdout.split("\0").filter((f) => f && !f.startsWith(".mason/"));
405
438
  return { available: true, changedFiles: [.../* @__PURE__ */ new Set([...touchedPaths(parseChanges(diff.stdout)), ...untrackedFiles])].sort(), untrackedFiles };
@@ -445,7 +478,7 @@ var MAX_WALK_UP = 30;
445
478
  var SUPPORTED_TOOLS = /* @__PURE__ */ new Set(["Read", "Edit", "Write"]);
446
479
  async function exists(p) {
447
480
  try {
448
- await fs5.access(p);
481
+ await fs6.access(p);
449
482
  return true;
450
483
  } catch {
451
484
  return false;
@@ -474,7 +507,7 @@ function stateKey(input) {
474
507
  }
475
508
  async function loadInjected(stateFile) {
476
509
  try {
477
- const parsed = JSON.parse(await fs5.readFile(stateFile, "utf-8"));
510
+ const parsed = JSON.parse(await fs6.readFile(stateFile, "utf-8"));
478
511
  return new Set(Array.isArray(parsed) ? parsed.filter((x) => typeof x === "string") : []);
479
512
  } catch {
480
513
  return /* @__PURE__ */ new Set();
@@ -515,7 +548,7 @@ async function runHook(stdinText, env = {}) {
515
548
  const relPath = path10.relative(root, absPath).split(path10.sep).join("/");
516
549
  if (relPath.startsWith("..")) return null;
517
550
  const { records } = await loadDecisionStore(root);
518
- const stateDir = env.stateDir ?? os.tmpdir();
551
+ const stateDir = env.stateDir ?? os2.tmpdir();
519
552
  const stateFile = path10.join(stateDir, `mason-hook-${createHash2("sha256").update(root).digest("hex").slice(0, 12)}-${stateKey(input)}.json`);
520
553
  const injected = await loadInjected(stateFile);
521
554
  const recordKey = (record) => `${record.id}:${createHash2("sha256").update(JSON.stringify(record)).digest("hex")}`;
@@ -533,7 +566,7 @@ async function runHook(stdinText, env = {}) {
533
566
  const drift = await computeDecisionDrift(root, selected);
534
567
  for (const record of selected) injected.add(recordKey(record));
535
568
  try {
536
- await fs5.writeFile(stateFile, JSON.stringify([...injected]), "utf-8");
569
+ await fs6.writeFile(stateFile, JSON.stringify([...injected]), "utf-8");
537
570
  } catch {
538
571
  }
539
572
  return JSON.stringify({