@grekt/cli 6.38.1 → 6.40.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 +364 -22
  2. package/package.json +7 -6
package/dist/index.js CHANGED
@@ -16782,7 +16782,7 @@ var require_braces = __commonJS((exports2, module2) => {
16782
16782
  module2.exports = braces;
16783
16783
  });
16784
16784
 
16785
- // node_modules/picomatch/lib/constants.js
16785
+ // node_modules/micromatch/node_modules/picomatch/lib/constants.js
16786
16786
  var require_constants3 = __commonJS((exports2, module2) => {
16787
16787
  var path8 = __require("path");
16788
16788
  var WIN_SLASH = "\\\\/";
@@ -16922,7 +16922,7 @@ var require_constants3 = __commonJS((exports2, module2) => {
16922
16922
  };
16923
16923
  });
16924
16924
 
16925
- // node_modules/picomatch/lib/utils.js
16925
+ // node_modules/micromatch/node_modules/picomatch/lib/utils.js
16926
16926
  var require_utils4 = __commonJS((exports2) => {
16927
16927
  var path8 = __require("path");
16928
16928
  var win322 = process.platform === "win32";
@@ -16982,7 +16982,7 @@ var require_utils4 = __commonJS((exports2) => {
16982
16982
  };
16983
16983
  });
16984
16984
 
16985
- // node_modules/picomatch/lib/scan.js
16985
+ // node_modules/micromatch/node_modules/picomatch/lib/scan.js
16986
16986
  var require_scan = __commonJS((exports2, module2) => {
16987
16987
  var utils = require_utils4();
16988
16988
  var {
@@ -17297,7 +17297,7 @@ var require_scan = __commonJS((exports2, module2) => {
17297
17297
  module2.exports = scan;
17298
17298
  });
17299
17299
 
17300
- // node_modules/picomatch/lib/parse.js
17300
+ // node_modules/micromatch/node_modules/picomatch/lib/parse.js
17301
17301
  var require_parse6 = __commonJS((exports2, module2) => {
17302
17302
  var constants2 = require_constants3();
17303
17303
  var utils = require_utils4();
@@ -18075,7 +18075,7 @@ var require_parse6 = __commonJS((exports2, module2) => {
18075
18075
  module2.exports = parse6;
18076
18076
  });
18077
18077
 
18078
- // node_modules/picomatch/lib/picomatch.js
18078
+ // node_modules/micromatch/node_modules/picomatch/lib/picomatch.js
18079
18079
  var require_picomatch = __commonJS((exports2, module2) => {
18080
18080
  var path8 = __require("path");
18081
18081
  var scan = require_scan();
@@ -91853,6 +91853,9 @@ var INDEX_FILE = join8(GREKT_DIR, "index");
91853
91853
 
91854
91854
  // src/shared/filesystem/filesystem.ts
91855
91855
  import { dirname as dirname3, join as join9 } from "path";
91856
+ function normalizePath(path8) {
91857
+ return path8.replace(/\\/g, "/");
91858
+ }
91856
91859
  function ensureDir(filepath) {
91857
91860
  const dir = dirname3(filepath);
91858
91861
  if (!fs.exists(dir)) {
@@ -103332,6 +103335,343 @@ function findArtifacts(basePath) {
103332
103335
  return artifacts;
103333
103336
  }
103334
103337
 
103338
+ // src/commands/changelog/git.ts
103339
+ function exec(args) {
103340
+ return shell.execFile("git", args).trim();
103341
+ }
103342
+ function execOrNull(args) {
103343
+ try {
103344
+ const result = exec(args);
103345
+ return result || null;
103346
+ } catch {
103347
+ return null;
103348
+ }
103349
+ }
103350
+ function splitLines(output) {
103351
+ if (!output)
103352
+ return [];
103353
+ return output.split(`
103354
+ `).map((line) => line.trim()).filter(Boolean);
103355
+ }
103356
+ function detectDefaultBranch() {
103357
+ const symbolicRef = execOrNull([
103358
+ "symbolic-ref",
103359
+ "refs/remotes/origin/HEAD"
103360
+ ]);
103361
+ if (symbolicRef) {
103362
+ const parts = symbolicRef.split("/");
103363
+ return parts[parts.length - 1] ?? "main";
103364
+ }
103365
+ return "main";
103366
+ }
103367
+ function getFirstCommit() {
103368
+ return execOrNull(["rev-list", "--max-parents=0", "HEAD"]);
103369
+ }
103370
+ function detectBaseRef(overrideSince) {
103371
+ if (overrideSince) {
103372
+ const resolved = execOrNull(["rev-parse", "--verify", overrideSince]);
103373
+ if (!resolved) {
103374
+ throw new Error(`Invalid ref: ${overrideSince}`);
103375
+ }
103376
+ return overrideSince;
103377
+ }
103378
+ const currentBranch = execOrNull(["rev-parse", "--abbrev-ref", "HEAD"]);
103379
+ const defaultBranch = detectDefaultBranch();
103380
+ const isDefaultBranch = currentBranch === defaultBranch || currentBranch === "HEAD";
103381
+ if (isDefaultBranch) {
103382
+ return null;
103383
+ }
103384
+ const hasRemote = execOrNull(["remote"]);
103385
+ if (hasRemote) {
103386
+ return `origin/${defaultBranch}`;
103387
+ }
103388
+ warning("No remote found, falling back to local refs");
103389
+ return defaultBranch;
103390
+ }
103391
+ function detectArtifactBaseRef(artifactName) {
103392
+ const lastTag = execOrNull([
103393
+ "describe",
103394
+ "--tags",
103395
+ "--abbrev=0",
103396
+ "--match",
103397
+ `${artifactName}@*`
103398
+ ]);
103399
+ if (lastTag)
103400
+ return lastTag;
103401
+ const firstCommit = getFirstCommit();
103402
+ if (firstCommit)
103403
+ return firstCommit;
103404
+ warning(`${artifactName}: no tags found, falling back to HEAD~1`);
103405
+ return "HEAD~1";
103406
+ }
103407
+ function getChangedFiles(baseRef, path8) {
103408
+ const baseArgs = ["diff", "--name-only"];
103409
+ const pathFilter = path8 ? ["--", path8] : [];
103410
+ const output = execOrNull([...baseArgs, `${baseRef}...HEAD`, ...pathFilter]) ?? execOrNull([...baseArgs, baseRef, "HEAD", ...pathFilter]);
103411
+ return splitLines(output);
103412
+ }
103413
+ function getCommitsForPath(baseRef, path8) {
103414
+ const output = execOrNull([
103415
+ "log",
103416
+ "--format=%H %s",
103417
+ `${baseRef}..HEAD`,
103418
+ "--",
103419
+ path8
103420
+ ]);
103421
+ return splitLines(output);
103422
+ }
103423
+
103424
+ // src/commands/changelog/conventional-commits.ts
103425
+ var CONVENTIONAL_COMMIT_REGEX = /^([a-f0-9]+)\s+(\w+)(\(.+?\))?(!)?\s*:\s*(.+)$/;
103426
+ function parseConventionalCommit(line) {
103427
+ if (line.includes("\x00"))
103428
+ return null;
103429
+ const match = line.match(CONVENTIONAL_COMMIT_REGEX);
103430
+ if (!match)
103431
+ return null;
103432
+ const hash = match[1] ?? "";
103433
+ const type = match[2] ?? "";
103434
+ const scopeRaw = match[3];
103435
+ const bang = match[4];
103436
+ const message = match[5] ?? "";
103437
+ const scope = scopeRaw ? scopeRaw.slice(1, -1) : null;
103438
+ const breaking = bang === "!" || message.toUpperCase().includes("BREAKING CHANGE");
103439
+ return {
103440
+ hash,
103441
+ type,
103442
+ scope,
103443
+ breaking,
103444
+ message,
103445
+ raw: line
103446
+ };
103447
+ }
103448
+ function determineBumpType(commits) {
103449
+ if (commits.some((commit) => commit.breaking))
103450
+ return "major";
103451
+ if (commits.some((commit) => commit.type === "feat"))
103452
+ return "minor";
103453
+ return "patch";
103454
+ }
103455
+ function mapFilesToArtifacts(changedFiles, artifacts) {
103456
+ const result = new Map;
103457
+ for (const file of changedFiles) {
103458
+ for (const artifact of artifacts) {
103459
+ const normalized = normalizePath(artifact.relativePath);
103460
+ const prefix = normalized.endsWith("/") ? normalized : `${normalized}/`;
103461
+ if (file.startsWith(prefix)) {
103462
+ const existing = result.get(artifact.relativePath) ?? [];
103463
+ existing.push(file);
103464
+ result.set(artifact.relativePath, existing);
103465
+ break;
103466
+ }
103467
+ }
103468
+ }
103469
+ return result;
103470
+ }
103471
+
103472
+ // src/commands/changelog/changeset-output.ts
103473
+ import { join as join31 } from "path";
103474
+ import { randomBytes as randomBytes3 } from "crypto";
103475
+ var CHANGESET_DIR = ".changeset";
103476
+ function generateChangesetFile(artifacts, workspaceRoot) {
103477
+ const changesetDir = join31(workspaceRoot, CHANGESET_DIR);
103478
+ if (!fs.exists(changesetDir)) {
103479
+ fs.mkdir(changesetDir, { recursive: true });
103480
+ }
103481
+ const filename = `${randomBytes3(4).toString("hex")}.md`;
103482
+ const filepath = join31(changesetDir, filename);
103483
+ const content = buildChangesetContent(artifacts);
103484
+ fs.writeFile(filepath, content);
103485
+ return filepath;
103486
+ }
103487
+ function buildChangesetContent(artifacts) {
103488
+ const frontmatterLines = [];
103489
+ const bodyLines = [];
103490
+ for (const entry of artifacts) {
103491
+ const { name: name2 } = entry.artifact.manifest;
103492
+ frontmatterLines.push(`"${name2}": ${entry.calculatedBump}`);
103493
+ if (entry.commits.length > 0) {
103494
+ for (const commit of entry.commits) {
103495
+ bodyLines.push(`- ${name2}: ${commit.type}: ${commit.message}`);
103496
+ }
103497
+ } else {
103498
+ bodyLines.push(`- ${name2}: changed files detected`);
103499
+ }
103500
+ }
103501
+ return ["---", ...frontmatterLines, "---", "", ...bodyLines, ""].join(`
103502
+ `);
103503
+ }
103504
+ function previewChangesetContent(artifacts) {
103505
+ return buildChangesetContent(artifacts);
103506
+ }
103507
+ function toOutputEntry(entry) {
103508
+ return {
103509
+ name: entry.artifact.manifest.name,
103510
+ version: entry.artifact.manifest.version,
103511
+ bump: entry.calculatedBump,
103512
+ commits: entry.commits.map((commit) => ({
103513
+ hash: commit.hash,
103514
+ type: commit.type,
103515
+ scope: commit.scope,
103516
+ breaking: commit.breaking,
103517
+ message: commit.message
103518
+ })),
103519
+ changedFiles: entry.changedFiles
103520
+ };
103521
+ }
103522
+ function formatJson(artifacts, baseRef) {
103523
+ return JSON.stringify({ baseRef, artifacts: artifacts.map(toOutputEntry) }, null, 2);
103524
+ }
103525
+ function formatYaml(artifacts, baseRef) {
103526
+ return $stringify2({
103527
+ baseRef,
103528
+ artifacts: artifacts.map(toOutputEntry)
103529
+ });
103530
+ }
103531
+
103532
+ // src/commands/changelog/changelog.ts
103533
+ var BUMP_CHOICES = [
103534
+ { name: "patch", value: "patch" },
103535
+ { name: "minor", value: "minor" },
103536
+ { name: "major", value: "major" },
103537
+ { name: "skip", value: "skip" }
103538
+ ];
103539
+ var changelogCommand = new Command("changelog").description("Generate changesets from git history for workspace artifacts").option("--ci", "Unattended mode (no prompts, auto-generate from commits)").option("--format <format>", "Output format: changeset (default), json, yaml", "changeset").option("--since <ref>", "Override base ref (auto-detected otherwise)").option("--dry-run", "Preview without writing").action(async (options2) => {
103540
+ const cwd = process.cwd();
103541
+ if (!isWorkspaceRoot(fs, cwd)) {
103542
+ error("Not a workspace (grekt-workspace.yaml not found)");
103543
+ info("Run this command from your workspace root");
103544
+ process.exit(1);
103545
+ }
103546
+ const workspace = await loadWorkspace(cwd);
103547
+ if (!workspace || workspace.artifacts.length === 0) {
103548
+ error("No artifacts found in workspace");
103549
+ process.exit(1);
103550
+ }
103551
+ const globalBaseRef = detectBaseRef(options2.since);
103552
+ const artifactChangelogs = globalBaseRef ? buildFromGlobalRef(workspace.artifacts, globalBaseRef, options2.ci) : buildPerArtifact(workspace.artifacts, options2.ci);
103553
+ if (artifactChangelogs.length === 0) {
103554
+ info("No artifact changes detected");
103555
+ process.exit(0);
103556
+ }
103557
+ const displayRef = globalBaseRef ?? "per-artifact tags";
103558
+ if (options2.ci) {
103559
+ printSummary(artifactChangelogs, displayRef);
103560
+ outputResult(artifactChangelogs, displayRef, cwd, options2);
103561
+ } else {
103562
+ await withPromptHandler(() => handleInteractiveMode(artifactChangelogs, displayRef, cwd, options2));
103563
+ }
103564
+ });
103565
+ function buildFromGlobalRef(artifacts, baseRef, ciMode) {
103566
+ const changedFiles = getChangedFiles(baseRef);
103567
+ if (changedFiles.length === 0)
103568
+ return [];
103569
+ const filesByArtifact = mapFilesToArtifacts(changedFiles, artifacts);
103570
+ const result = [];
103571
+ for (const artifact of artifacts) {
103572
+ const files = filesByArtifact.get(artifact.relativePath);
103573
+ if (!files)
103574
+ continue;
103575
+ result.push(buildArtifactChangelog(artifact, files, baseRef, ciMode));
103576
+ }
103577
+ return result;
103578
+ }
103579
+ function buildPerArtifact(artifacts, ciMode) {
103580
+ const result = [];
103581
+ for (const artifact of artifacts) {
103582
+ const baseRef = detectArtifactBaseRef(artifact.manifest.name);
103583
+ const changedFiles = getChangedFiles(baseRef, artifact.relativePath);
103584
+ if (changedFiles.length === 0)
103585
+ continue;
103586
+ result.push(buildArtifactChangelog(artifact, changedFiles, baseRef, ciMode));
103587
+ }
103588
+ return result;
103589
+ }
103590
+ function buildArtifactChangelog(artifact, changedFiles, baseRef, ciMode) {
103591
+ const commitLines = getCommitsForPath(baseRef, artifact.relativePath);
103592
+ const commits = commitLines.map(parseConventionalCommit).filter((commit) => commit !== null);
103593
+ const nonConventionalCount = commitLines.length - commits.length;
103594
+ if (nonConventionalCount > 0 && ciMode) {
103595
+ warning(`${artifact.manifest.name}: ${nonConventionalCount} non-conventional commit(s) ignored`);
103596
+ }
103597
+ const calculatedBump = commits.length > 0 ? determineBumpType(commits) : "patch";
103598
+ if (commits.length === 0 && ciMode) {
103599
+ warning(`${artifact.manifest.name}: no conventional commits found, defaulting to patch`);
103600
+ }
103601
+ return {
103602
+ artifact,
103603
+ commits,
103604
+ calculatedBump,
103605
+ changedFiles
103606
+ };
103607
+ }
103608
+ function printSummary(artifactChangelogs, baseRef) {
103609
+ newline();
103610
+ info(`Base ref: ${colors5.highlight(baseRef)}`);
103611
+ info(`${artifactChangelogs.length} artifact(s) with changes:`);
103612
+ newline();
103613
+ for (const entry of artifactChangelogs) {
103614
+ const { name: name2, version: version3 } = entry.artifact.manifest;
103615
+ log(` ${name2} ${colors5.dim(`v${version3}`)} ${symbols.arrow} ${colors5.bold(entry.calculatedBump)} ${colors5.dim(`(${entry.commits.length} commit(s))`)}`);
103616
+ }
103617
+ newline();
103618
+ }
103619
+ async function handleInteractiveMode(artifactChangelogs, baseRef, cwd, options2) {
103620
+ printSummary(artifactChangelogs, baseRef);
103621
+ const finalChangelogs = [];
103622
+ for (const entry of artifactChangelogs) {
103623
+ const { name: name2 } = entry.artifact.manifest;
103624
+ const bump = await esm_default6({
103625
+ message: `${name2}: bump type?`,
103626
+ choices: BUMP_CHOICES,
103627
+ default: entry.calculatedBump
103628
+ });
103629
+ if (bump === "skip") {
103630
+ info(`Skipping ${name2}`);
103631
+ continue;
103632
+ }
103633
+ finalChangelogs.push({
103634
+ ...entry,
103635
+ calculatedBump: bump
103636
+ });
103637
+ }
103638
+ if (finalChangelogs.length === 0) {
103639
+ newline();
103640
+ info("All artifacts skipped");
103641
+ return;
103642
+ }
103643
+ newline();
103644
+ const confirmed = await esm_default3({
103645
+ message: `Generate changeset for ${finalChangelogs.length} artifact(s)?`,
103646
+ default: true
103647
+ });
103648
+ if (!confirmed) {
103649
+ info("Cancelled");
103650
+ return;
103651
+ }
103652
+ outputResult(finalChangelogs, baseRef, cwd, options2);
103653
+ }
103654
+ function outputResult(artifactChangelogs, baseRef, cwd, options2) {
103655
+ const format = options2.format ?? "changeset";
103656
+ if (format === "json") {
103657
+ log(formatJson(artifactChangelogs, baseRef));
103658
+ return;
103659
+ }
103660
+ if (format === "yaml") {
103661
+ log(formatYaml(artifactChangelogs, baseRef));
103662
+ return;
103663
+ }
103664
+ if (options2.dryRun) {
103665
+ newline();
103666
+ info("Dry run — changeset content:");
103667
+ newline();
103668
+ log(previewChangesetContent(artifactChangelogs));
103669
+ return;
103670
+ }
103671
+ const filepath = generateChangesetFile(artifactChangelogs, cwd);
103672
+ newline();
103673
+ success(`Changeset written to ${filepath}`);
103674
+ }
103335
103675
  // src/commands/workspace/workspace.ts
103336
103676
  var listSubcommand = new Command("list").description("List all artifacts in the workspace").action(async () => {
103337
103677
  const cwd = process.cwd();
@@ -103355,7 +103695,7 @@ var listSubcommand = new Command("list").description("List all artifacts in the
103355
103695
  });
103356
103696
  var workspaceCommand = new Command("workspace").description("Manage monorepo workspaces").addCommand(listSubcommand);
103357
103697
  // src/commands/worktree/worktree.ts
103358
- import { join as join31, dirname as dirname11, isAbsolute as isAbsolute4 } from "path";
103698
+ import { join as join32, dirname as dirname11, isAbsolute as isAbsolute4 } from "path";
103359
103699
  var GREKT_DIR2 = ".grekt";
103360
103700
  function getGitCommonDir() {
103361
103701
  try {
@@ -103372,7 +103712,7 @@ function getWorktreeRoot() {
103372
103712
  }
103373
103713
  }
103374
103714
  function resolveOriginalRepoRoot(commonDir, worktreeRoot) {
103375
- const absoluteCommonDir = isAbsolute4(commonDir) ? commonDir : join31(worktreeRoot, commonDir);
103715
+ const absoluteCommonDir = isAbsolute4(commonDir) ? commonDir : join32(worktreeRoot, commonDir);
103376
103716
  return dirname11(absoluteCommonDir);
103377
103717
  }
103378
103718
  function isInsideWorktree(commonDir) {
@@ -103395,8 +103735,8 @@ var syncSubcommand = new Command("sync").description("Copy .grekt/ from the orig
103395
103735
  process.exit(1);
103396
103736
  }
103397
103737
  const originalRepoRoot = resolveOriginalRepoRoot(commonDir, worktreeRoot);
103398
- const sourcePath = join31(originalRepoRoot, GREKT_DIR2);
103399
- const destPath = join31(worktreeRoot, GREKT_DIR2);
103738
+ const sourcePath = join32(originalRepoRoot, GREKT_DIR2);
103739
+ const destPath = join32(worktreeRoot, GREKT_DIR2);
103400
103740
  if (!fs.exists(sourcePath)) {
103401
103741
  info("No .grekt/ directory found in the original repository");
103402
103742
  process.exit(0);
@@ -103419,7 +103759,7 @@ var syncSubcommand = new Command("sync").description("Copy .grekt/ from the orig
103419
103759
  });
103420
103760
  var worktreeCommand = new Command("worktree").description("Manage git worktree integration").addCommand(syncSubcommand);
103421
103761
  // src/commands/scan.ts
103422
- import { join as join32, resolve as resolve8 } from "path";
103762
+ import { join as join33, resolve as resolve8 } from "path";
103423
103763
  var VALID_BADGES = ["certified", "conditional", "suspicious", "rejected"];
103424
103764
  var BADGE_COLORS = {
103425
103765
  certified: colors5.success,
@@ -103515,7 +103855,7 @@ var scanCommand = new Command("scan").description("Scan artifacts for security i
103515
103855
  });
103516
103856
  async function scanRemoteArtifact(source, projectRoot, jsonOutput, failOnThreshold) {
103517
103857
  const displayName = getSourceDisplayName(source);
103518
- const tempDir = join32(projectRoot, ARTIFACTS_DIR, `.tmp-scan-${cryptoProvider.randomUUID()}`);
103858
+ const tempDir = join33(projectRoot, ARTIFACTS_DIR, `.tmp-scan-${cryptoProvider.randomUUID()}`);
103519
103859
  try {
103520
103860
  if (!jsonOutput) {
103521
103861
  const spin = spinner(`Downloading ${colors5.highlight(displayName)}...`);
@@ -103641,14 +103981,14 @@ async function scanAllInstalled(projectRoot, jsonOutput, failOnThreshold) {
103641
103981
  }
103642
103982
  const config = getConfig(projectRoot);
103643
103983
  const trustKey = process.env.GREKT_TRUST_KEY;
103644
- const artifactsDir = join32(projectRoot, ARTIFACTS_DIR);
103984
+ const artifactsDir = join33(projectRoot, ARTIFACTS_DIR);
103645
103985
  const results = [];
103646
103986
  const errors4 = [];
103647
103987
  if (!jsonOutput) {
103648
103988
  log(`Scanning ${colors5.bold(String(artifactIds.length))} artifact${artifactIds.length === 1 ? "" : "s"}...`);
103649
103989
  }
103650
103990
  for (const artifactId of artifactIds) {
103651
- const artifactDir = join32(artifactsDir, artifactId);
103991
+ const artifactDir = join33(artifactsDir, artifactId);
103652
103992
  if (!fs.exists(artifactDir)) {
103653
103993
  errors4.push({ artifactId, message: "Not installed (directory missing)" });
103654
103994
  continue;
@@ -103996,7 +104336,7 @@ var whoamiCommand = new Command("whoami").description("Show current user").actio
103996
104336
  // package.json
103997
104337
  var package_default = {
103998
104338
  name: "@grekt/cli",
103999
- version: "6.38.1",
104339
+ version: "6.40.0",
104000
104340
  description: "AI tools versioned, synced, and shared across tools and teams",
104001
104341
  type: "module",
104002
104342
  bin: {
@@ -104023,11 +104363,10 @@ var package_default = {
104023
104363
  deploy: "bun run scripts/deploy.ts",
104024
104364
  release: "bun run build:all && bun run deploy",
104025
104365
  typecheck: "tsc --noEmit",
104026
- test: "bun test",
104027
- "test:watch": "bun test --watch",
104028
- "test:coverage": "bun test --coverage",
104366
+ test: "vitest run",
104367
+ "test:watch": "vitest watch",
104368
+ "test:coverage": "vitest run --coverage",
104029
104369
  "test:e2e": "bun test spec/",
104030
- "test:e2e:watch": "bun test spec/ --watch",
104031
104370
  prepare: "husky"
104032
104371
  },
104033
104372
  dependencies: {
@@ -104053,7 +104392,9 @@ var package_default = {
104053
104392
  "bun-types": "^1.3.6",
104054
104393
  husky: "^9.1.7",
104055
104394
  "semantic-release": "^25.0.2",
104056
- typescript: "^5.7.2"
104395
+ typescript: "^5.7.2",
104396
+ "vite-tsconfig-paths": "^6.1.1",
104397
+ vitest: "^4.0.18"
104057
104398
  },
104058
104399
  engines: {
104059
104400
  node: ">=18.0.0"
@@ -104064,13 +104405,13 @@ var package_default = {
104064
104405
  // src/update-check/update-check.ts
104065
104406
  import { existsSync as existsSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
104066
104407
  import { homedir as homedir3 } from "os";
104067
- import { join as join33 } from "path";
104408
+ import { join as join34 } from "path";
104068
104409
  var CACHE_FILENAME = ".update-check";
104069
104410
  var STALENESS_MS = 24 * 60 * 60 * 1000;
104070
104411
  var FETCH_TIMEOUT_MS = 1500;
104071
104412
  var GITHUB_RELEASES_URL = "https://api.github.com/repos/grekt-labs/cli/releases/latest";
104072
104413
  function getCachePath() {
104073
- return join33(homedir3(), ".grekt", CACHE_FILENAME);
104414
+ return join34(homedir3(), ".grekt", CACHE_FILENAME);
104074
104415
  }
104075
104416
  function isOptedOut() {
104076
104417
  return process.env.GREKT_NO_UPDATE_CHECK === "1";
@@ -104089,7 +104430,7 @@ function readCache() {
104089
104430
  }
104090
104431
  function writeCache(cache2) {
104091
104432
  try {
104092
- const dir = join33(homedir3(), ".grekt");
104433
+ const dir = join34(homedir3(), ".grekt");
104093
104434
  if (!existsSync2(dir)) {
104094
104435
  mkdirSync3(dir, { recursive: true });
104095
104436
  }
@@ -104197,6 +104538,7 @@ program2.addCommand(versionsCommand);
104197
104538
  program2.addCommand(outdatedCommand);
104198
104539
  program2.addCommand(upgradeCommand);
104199
104540
  program2.addCommand(versionCommand);
104541
+ program2.addCommand(changelogCommand);
104200
104542
  program2.addCommand(workspaceCommand);
104201
104543
  program2.addCommand(worktreeCommand);
104202
104544
  program2.addCommand(scanCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grekt/cli",
3
- "version": "6.38.1",
3
+ "version": "6.40.0",
4
4
  "description": "AI tools versioned, synced, and shared across tools and teams",
5
5
  "type": "module",
6
6
  "bin": {
@@ -27,11 +27,10 @@
27
27
  "deploy": "bun run scripts/deploy.ts",
28
28
  "release": "bun run build:all && bun run deploy",
29
29
  "typecheck": "tsc --noEmit",
30
- "test": "bun test",
31
- "test:watch": "bun test --watch",
32
- "test:coverage": "bun test --coverage",
30
+ "test": "vitest run",
31
+ "test:watch": "vitest watch",
32
+ "test:coverage": "vitest run --coverage",
33
33
  "test:e2e": "bun test spec/",
34
- "test:e2e:watch": "bun test spec/ --watch",
35
34
  "prepare": "husky"
36
35
  },
37
36
  "dependencies": {
@@ -57,7 +56,9 @@
57
56
  "bun-types": "^1.3.6",
58
57
  "husky": "^9.1.7",
59
58
  "semantic-release": "^25.0.2",
60
- "typescript": "^5.7.2"
59
+ "typescript": "^5.7.2",
60
+ "vite-tsconfig-paths": "^6.1.1",
61
+ "vitest": "^4.0.18"
61
62
  },
62
63
  "engines": {
63
64
  "node": ">=18.0.0"