@blzsky/variant 0.2.0 → 0.3.0-canary.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 (49) hide show
  1. package/README.md +241 -136
  2. package/dist/{build-2LO7GD2S.js → build-GKWNLU4Q.js} +11 -10
  3. package/dist/{check-ZTKGGF4M.js → check-KO5VY67Z.js} +9 -9
  4. package/dist/{chunk-4LLK2S4R.js → chunk-7NC7AO75.js} +19 -32
  5. package/dist/{chunk-RVXUCJYA.js → chunk-ACTY42RE.js} +27 -0
  6. package/dist/{chunk-SWPVR2DF.js → chunk-CN25SRKD.js} +9 -9
  7. package/dist/{chunk-LXKLCLL6.js → chunk-CWF6QXEW.js} +1 -1
  8. package/dist/{chunk-MZZOE7L4.js → chunk-DMDAJPFJ.js} +1 -1
  9. package/dist/{chunk-O4LZKXNZ.js → chunk-DSQDMFQ6.js} +59 -2
  10. package/dist/{chunk-V22IPJ7A.js → chunk-EISTWXDW.js} +5 -1
  11. package/dist/chunk-H5C4SE73.js +184 -0
  12. package/dist/chunk-IFFZ46YS.js +575 -0
  13. package/dist/chunk-IHXJ72XA.js +31 -0
  14. package/dist/chunk-KCEGA56S.js +670 -0
  15. package/dist/{chunk-LJDDS4RR.js → chunk-MAK3HG46.js} +54 -8
  16. package/dist/chunk-MT4BOAAV.js +167 -0
  17. package/dist/{chunk-VTJ67TT5.js → chunk-NFFXYYM6.js} +122 -27
  18. package/dist/{chunk-ISRF5F3Q.js → chunk-QRPI6TJE.js} +1 -1
  19. package/dist/{chunk-RGD422OM.js → chunk-RJBFCURK.js} +1 -1
  20. package/dist/{chunk-XUBWCTJZ.js → chunk-RSIOYQOQ.js} +85 -8
  21. package/dist/chunk-SGP5JX6I.js +377 -0
  22. package/dist/chunk-X3VVGTEV.js +268 -0
  23. package/dist/{chunk-NSNZOH5P.js → chunk-YII4TAKS.js} +10 -3
  24. package/dist/cli.js +76 -37
  25. package/dist/{diff-GFI6RAEA.js → diff-A3TQWWUJ.js} +9 -5
  26. package/dist/{doctor-GH4RZVEH.js → doctor-6ONS6LKY.js} +5 -5
  27. package/dist/{env-QORDD6FQ.js → env-XF2US3CB.js} +8 -8
  28. package/dist/git-W6N3WMYQ.js +24 -0
  29. package/dist/impact-DPZIAJR4.js +263 -0
  30. package/dist/index.js +2 -2
  31. package/dist/init-VNK5E4H3.js +777 -0
  32. package/dist/{insight-DZ5NQY6D.js → insight-LNYVMCAE.js} +9 -9
  33. package/dist/pr-6CYMM2XU.js +707 -0
  34. package/dist/{run-6PNH4QRA.js → run-44PKMOV5.js} +11 -10
  35. package/dist/{symbol-graph-YYUEMZGR.js → symbol-graph-OB4AJCLW.js} +3 -3
  36. package/dist/{tsconfig-paths-E3UEDGXZ.js → tsconfig-paths-SV3PULCW.js} +3 -1
  37. package/dist/vitest.cjs +629 -0
  38. package/dist/vitest.d.cts +181 -0
  39. package/dist/vitest.d.ts +181 -0
  40. package/dist/vitest.js +356 -0
  41. package/dist/workspace-PIQXG4ZD.js +65 -0
  42. package/package.json +15 -4
  43. package/dist/chunk-DRMASVYN.js +0 -25
  44. package/dist/chunk-KSHWC2XN.js +0 -78
  45. package/dist/chunk-XTYVVUWW.js +0 -279
  46. package/dist/impact-AF453PLK.js +0 -702
  47. package/dist/init-KJIUNGAN.js +0 -158
  48. package/dist/pr-UFZRZX6S.js +0 -152
  49. package/dist/workspace-X5FUBTY3.js +0 -186
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  CacheError
3
- } from "./chunk-RVXUCJYA.js";
3
+ } from "./chunk-ACTY42RE.js";
4
4
 
5
5
  // src/core/cache/store.ts
6
6
  import { mkdirSync, renameSync, unlinkSync, writeFileSync } from "fs";
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-3E5LBU3O.js";
4
4
  import {
5
5
  listChangedFiles
6
- } from "./chunk-XUBWCTJZ.js";
6
+ } from "./chunk-RSIOYQOQ.js";
7
7
 
8
8
  // src/core/cache/git-diff.ts
9
9
  import path from "path";
@@ -1,4 +1,11 @@
1
1
  // src/core/semantic/surface.ts
2
+ var STAR_REEXPORT_PREFIX = "* from ";
3
+ function starReexportKey(moduleSpec) {
4
+ return `${STAR_REEXPORT_PREFIX}${moduleSpec}`;
5
+ }
6
+ function isStarReexportKey(name) {
7
+ return name.startsWith(STAR_REEXPORT_PREFIX);
8
+ }
2
9
  function collectExportedSurface(file, tsm) {
3
10
  const symbols = /* @__PURE__ */ new Map();
4
11
  const notes = [];
@@ -42,7 +49,7 @@ function collectExportedSurface(file, tsm) {
42
49
  });
43
50
  continue;
44
51
  }
45
- symbols.set(`* from ${moduleSpec}`, {
52
+ symbols.set(starReexportKey(moduleSpec), {
46
53
  signature: reexportSignature("*", moduleSpec, declTypeOnly),
47
54
  body: "",
48
55
  typeSpace: declTypeOnly,
@@ -276,6 +283,7 @@ function inferTypeText(get) {
276
283
  }
277
284
  function significantText(src, tsm) {
278
285
  if (src.trim() === "") return "";
286
+ const { SyntaxKind } = tsm.ts;
279
287
  const scanner = tsm.ts.createScanner(
280
288
  tsm.ts.ScriptTarget.Latest,
281
289
  /* skipTrivia */
@@ -284,18 +292,67 @@ function significantText(src, tsm) {
284
292
  src
285
293
  );
286
294
  const parts = [];
295
+ const substitutionBraces = [];
296
+ let previous = SyntaxKind.Unknown;
287
297
  let kind = scanner.scan();
288
- while (kind !== tsm.ts.SyntaxKind.EndOfFileToken) {
298
+ while (kind !== SyntaxKind.EndOfFileToken) {
299
+ if (kind === SyntaxKind.CloseBraceToken && substitutionBraces.at(-1) === 0) {
300
+ substitutionBraces.pop();
301
+ kind = scanner.reScanTemplateToken(
302
+ /* isTaggedTemplate */
303
+ false
304
+ );
305
+ } else if (kind === SyntaxKind.OpenBraceToken || kind === SyntaxKind.CloseBraceToken) {
306
+ const depth = substitutionBraces.pop();
307
+ if (depth !== void 0) {
308
+ substitutionBraces.push(
309
+ kind === SyntaxKind.OpenBraceToken ? depth + 1 : depth - 1
310
+ );
311
+ }
312
+ } else if ((kind === SyntaxKind.SlashToken || kind === SyntaxKind.SlashEqualsToken) && !endsOperand(previous, tsm)) {
313
+ kind = scanner.reScanSlashToken();
314
+ }
315
+ if (kind === SyntaxKind.TemplateHead || kind === SyntaxKind.TemplateMiddle) {
316
+ substitutionBraces.push(0);
317
+ }
289
318
  parts.push(scanner.getTokenText());
319
+ previous = kind;
290
320
  kind = scanner.scan();
291
321
  }
292
322
  return parts.join(" ");
293
323
  }
324
+ function endsOperand(kind, tsm) {
325
+ const { SyntaxKind } = tsm.ts;
326
+ switch (kind) {
327
+ case SyntaxKind.Identifier:
328
+ case SyntaxKind.PrivateIdentifier:
329
+ case SyntaxKind.NumericLiteral:
330
+ case SyntaxKind.BigIntLiteral:
331
+ case SyntaxKind.StringLiteral:
332
+ case SyntaxKind.NoSubstitutionTemplateLiteral:
333
+ case SyntaxKind.TemplateTail:
334
+ case SyntaxKind.RegularExpressionLiteral:
335
+ case SyntaxKind.CloseParenToken:
336
+ case SyntaxKind.CloseBracketToken:
337
+ case SyntaxKind.CloseBraceToken:
338
+ case SyntaxKind.PlusPlusToken:
339
+ case SyntaxKind.MinusMinusToken:
340
+ case SyntaxKind.ThisKeyword:
341
+ case SyntaxKind.SuperKeyword:
342
+ case SyntaxKind.TrueKeyword:
343
+ case SyntaxKind.FalseKeyword:
344
+ case SyntaxKind.NullKeyword:
345
+ return true;
346
+ default:
347
+ return false;
348
+ }
349
+ }
294
350
  function normalize(text) {
295
351
  return text.replace(/\s+/g, " ").trim();
296
352
  }
297
353
 
298
354
  export {
355
+ isStarReexportKey,
299
356
  collectExportedSurface,
300
357
  significantText
301
358
  };
@@ -17,8 +17,12 @@ var Printer = class _Printer {
17
17
  if (flags.noProgress) return new _Printer("no-progress", streams);
18
18
  return new _Printer("default", streams);
19
19
  }
20
+ /**
21
+ * As in uv, `-q` quiets the commentary, not the answer: a script that asks
22
+ * for `--json` with `-q` still gets its JSON. Only `-qq` silences stdout.
23
+ */
20
24
  get stdoutEnabled() {
21
- return this.mode !== "silent" && this.mode !== "quiet";
25
+ return this.mode !== "silent";
22
26
  }
23
27
  get stderrEnabled() {
24
28
  return this.mode !== "silent" && this.mode !== "quiet";
@@ -0,0 +1,184 @@
1
+ import {
2
+ defaultBranchRef,
3
+ mergeBase,
4
+ resolveCommit
5
+ } from "./chunk-RSIOYQOQ.js";
6
+ import {
7
+ GitRefError,
8
+ NoBaseCommitError
9
+ } from "./chunk-ACTY42RE.js";
10
+
11
+ // src/core/vcs/change-base.ts
12
+ import { readFile } from "fs/promises";
13
+ function changeBaseDeps(cwd) {
14
+ return {
15
+ env: process.env,
16
+ readEvent: async (path2) => {
17
+ try {
18
+ return JSON.parse(await readFile(path2, "utf8"));
19
+ } catch {
20
+ return void 0;
21
+ }
22
+ },
23
+ resolveCommit: (ref) => resolveCommit(cwd, ref),
24
+ mergeBase: (a, b) => mergeBase(cwd, a, b),
25
+ defaultBranch: () => defaultBranchRef(cwd)
26
+ };
27
+ }
28
+ var ZERO_SHA = /^0+$/;
29
+ function field(value, ...keys) {
30
+ let current = value;
31
+ for (const key of keys) {
32
+ if (typeof current !== "object" || current === null) return void 0;
33
+ current = current[key];
34
+ }
35
+ return current;
36
+ }
37
+ function isPullRequest(env) {
38
+ const event = env["GITHUB_EVENT_NAME"];
39
+ return env["GITHUB_ACTIONS"] === "true" && (event === "pull_request" || event === "pull_request_target") && (env["GITHUB_BASE_REF"] ?? "") !== "";
40
+ }
41
+ async function readEvent(deps) {
42
+ const path2 = deps.env["GITHUB_EVENT_PATH"];
43
+ return path2 === void 0 || path2 === "" ? void 0 : deps.readEvent(path2);
44
+ }
45
+ async function resolveChangeBase(explicit, deps) {
46
+ if (explicit !== void 0) {
47
+ return { ref: explicit, source: "flag", label: explicit };
48
+ }
49
+ const fromEnvironment = deps.env["VARIANT_BASE"];
50
+ if (fromEnvironment !== void 0 && fromEnvironment !== "") {
51
+ return {
52
+ ref: fromEnvironment,
53
+ source: "environment",
54
+ label: `${fromEnvironment} (VARIANT_BASE)`
55
+ };
56
+ }
57
+ if (isPullRequest(deps.env)) {
58
+ const target = `origin/${deps.env["GITHUB_BASE_REF"]}`;
59
+ if (await deps.resolveCommit(target) === null) {
60
+ throw new GitRefError(
61
+ `The pull request's target branch, "${target}", is not in this clone`
62
+ );
63
+ }
64
+ const fork = await deps.mergeBase("HEAD", target);
65
+ if (fork === null) {
66
+ throw new GitRefError(
67
+ `"${target}" shares no history with HEAD in this clone`
68
+ );
69
+ }
70
+ const pushed = field(await readEvent(deps), "pull_request", "head", "sha");
71
+ return {
72
+ ref: fork,
73
+ source: "pull-request",
74
+ label: `merge base with ${target}`,
75
+ ...typeof pushed === "string" && pushed !== "" && { headSha: pushed }
76
+ };
77
+ }
78
+ if (deps.env["GITHUB_ACTIONS"] === "true" && deps.env["GITHUB_EVENT_NAME"] === "push") {
79
+ const before = field(await readEvent(deps), "before");
80
+ if (typeof before !== "string" || before === "" || ZERO_SHA.test(before) || await deps.resolveCommit(before) === null) {
81
+ throw new NoBaseCommitError();
82
+ }
83
+ const pushed = deps.env["GITHUB_SHA"];
84
+ return {
85
+ ref: before,
86
+ source: "push",
87
+ label: "the commit this push replaced",
88
+ ...pushed !== void 0 && pushed !== "" && { headSha: pushed }
89
+ };
90
+ }
91
+ const branch = await deps.defaultBranch();
92
+ if (branch !== null) {
93
+ const [fork, head] = await Promise.all([
94
+ deps.mergeBase("HEAD", branch),
95
+ deps.resolveCommit("HEAD")
96
+ ]);
97
+ if (fork !== null && fork !== head) {
98
+ return {
99
+ ref: fork,
100
+ source: "default-branch",
101
+ label: `merge base with ${branch}`
102
+ };
103
+ }
104
+ }
105
+ return { ref: "HEAD~1", source: "previous-commit", label: "previous commit" };
106
+ }
107
+ async function resolvePullRequestBase(explicit, deps) {
108
+ if (explicit !== void 0) return explicit;
109
+ if (isPullRequest(deps.env)) return `origin/${deps.env["GITHUB_BASE_REF"]}`;
110
+ return await deps.defaultBranch() ?? "main";
111
+ }
112
+ async function detectHeadSha(deps) {
113
+ if (deps.env["GITHUB_ACTIONS"] !== "true") return void 0;
114
+ if (isPullRequest(deps.env)) {
115
+ const pushed = field(await readEvent(deps), "pull_request", "head", "sha");
116
+ return typeof pushed === "string" && pushed !== "" ? pushed : void 0;
117
+ }
118
+ const sha = deps.env["GITHUB_SHA"];
119
+ return deps.env["GITHUB_EVENT_NAME"] === "push" && sha !== void 0 && sha !== "" ? sha : void 0;
120
+ }
121
+
122
+ // src/core/history/impact-log.ts
123
+ import { appendFile, mkdir, readFile as readFile2, writeFile } from "fs/promises";
124
+ import path from "path";
125
+ var MAX_IMPACT_RECORDS = 1e3;
126
+ var LOG_FILENAME = "impact.jsonl";
127
+ var RECONCILIATION_FILENAME = "reconciliation.jsonl";
128
+ function defaultHistoryDir(cwd) {
129
+ return path.join(cwd, ".variant", "history");
130
+ }
131
+ async function appendImpactPrediction(historyDir, prediction) {
132
+ return appendRecord(historyDir, LOG_FILENAME, prediction);
133
+ }
134
+ async function appendReconciliation(historyDir, reconciliation) {
135
+ return appendRecord(historyDir, RECONCILIATION_FILENAME, reconciliation);
136
+ }
137
+ async function appendRecord(historyDir, filename, record) {
138
+ try {
139
+ await mkdir(historyDir, { recursive: true });
140
+ const file = path.join(historyDir, filename);
141
+ await appendFile(file, `${JSON.stringify(record)}
142
+ `);
143
+ const lines = (await readFile2(file, "utf8")).split("\n").filter((l) => l.trim() !== "");
144
+ if (lines.length > MAX_IMPACT_RECORDS) {
145
+ await writeFile(file, `${lines.slice(-MAX_IMPACT_RECORDS).join("\n")}
146
+ `);
147
+ }
148
+ return true;
149
+ } catch {
150
+ return false;
151
+ }
152
+ }
153
+ async function readImpactPredictions(historyDir) {
154
+ return readRecords(historyDir, LOG_FILENAME);
155
+ }
156
+ async function readRecords(historyDir, filename) {
157
+ let raw;
158
+ try {
159
+ raw = await readFile2(path.join(historyDir, filename), "utf8");
160
+ } catch {
161
+ return [];
162
+ }
163
+ const out = [];
164
+ for (const line of raw.split("\n")) {
165
+ const trimmed = line.trim();
166
+ if (trimmed === "") continue;
167
+ try {
168
+ out.push(JSON.parse(trimmed));
169
+ } catch {
170
+ }
171
+ }
172
+ return out;
173
+ }
174
+
175
+ export {
176
+ defaultHistoryDir,
177
+ appendImpactPrediction,
178
+ appendReconciliation,
179
+ readImpactPredictions,
180
+ changeBaseDeps,
181
+ resolveChangeBase,
182
+ resolvePullRequestBase,
183
+ detectHeadSha
184
+ };