@vibgrate/cli 1.0.1 → 1.0.2

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/dist/cli.js CHANGED
@@ -4,22 +4,22 @@ import {
4
4
  } from "./chunk-VXZT34Y5.js";
5
5
  import {
6
6
  baselineCommand
7
- } from "./chunk-NTRKEIKP.js";
7
+ } from "./chunk-GG5AUF7X.js";
8
8
  import {
9
9
  VERSION,
10
+ dsnCommand,
10
11
  ensureDir,
11
12
  formatText,
12
13
  pathExists,
14
+ pushCommand,
13
15
  readJsonFile,
14
- readTextFile,
15
16
  scanCommand,
16
- writeDefaultConfig,
17
- writeTextFile
18
- } from "./chunk-VMNBKARQ.js";
17
+ writeDefaultConfig
18
+ } from "./chunk-XZ4NRZMT.js";
19
19
 
20
20
  // src/cli.ts
21
- import { Command as Command6 } from "commander";
22
- import chalk6 from "chalk";
21
+ import { Command as Command4 } from "commander";
22
+ import chalk4 from "chalk";
23
23
 
24
24
  // src/commands/init.ts
25
25
  import * as path from "path";
@@ -38,7 +38,7 @@ var initCommand = new Command("init").description("Initialize vibgrate in a proj
38
38
  console.log(chalk.green("\u2714") + ` Created ${chalk.bold("vibgrate.config.ts")}`);
39
39
  }
40
40
  if (opts.baseline) {
41
- const { runBaseline } = await import("./baseline-35XRSRAD.js");
41
+ const { runBaseline } = await import("./baseline-5SAUNH2V.js");
42
42
  await runBaseline(rootDir);
43
43
  }
44
44
  console.log("");
@@ -74,153 +74,20 @@ var reportCommand = new Command2("report").description("Generate a drift report
74
74
  }
75
75
  });
76
76
 
77
- // src/commands/dsn.ts
78
- import * as crypto from "crypto";
79
- import * as path3 from "path";
80
- import { Command as Command3 } from "commander";
81
- import chalk3 from "chalk";
82
- var REGION_HOSTS = {
83
- us: "us.ingest.vibgrate.com",
84
- eu: "eu.ingest.vibgrate.com"
85
- };
86
- function resolveIngestHost(region, ingest) {
87
- if (ingest) {
88
- try {
89
- return new URL(ingest).host;
90
- } catch {
91
- throw new Error(`Invalid ingest URL: ${ingest}`);
92
- }
93
- }
94
- const r = (region ?? "us").toLowerCase();
95
- const host = REGION_HOSTS[r];
96
- if (!host) {
97
- throw new Error(`Unknown region "${r}". Supported: ${Object.keys(REGION_HOSTS).join(", ")}`);
98
- }
99
- return host;
100
- }
101
- var dsnCommand = new Command3("dsn").description("Manage DSN tokens");
102
- dsnCommand.command("create").description("Create a new DSN token").option("--ingest <url>", "Ingest API URL (overrides --region)").option("--region <region>", "Data residency region (us, eu)", "us").requiredOption("--workspace <id>", "Workspace ID").option("--write <path>", "Write DSN to file").action(async (opts) => {
103
- const keyId = crypto.randomBytes(8).toString("hex");
104
- const secret = crypto.randomBytes(32).toString("hex");
105
- let ingestHost;
106
- try {
107
- ingestHost = resolveIngestHost(opts.region, opts.ingest);
108
- } catch (e) {
109
- console.error(chalk3.red(e instanceof Error ? e.message : String(e)));
110
- process.exit(1);
111
- }
112
- const dsn = `vibgrate+https://${keyId}:${secret}@${ingestHost}/${opts.workspace}`;
113
- console.log(chalk3.green("\u2714") + " DSN created");
114
- console.log("");
115
- console.log(chalk3.bold("DSN:"));
116
- console.log(` ${dsn}`);
117
- console.log("");
118
- console.log(chalk3.bold("Key ID:"));
119
- console.log(` ${keyId}`);
120
- console.log("");
121
- console.log(chalk3.dim("Set this as VIBGRATE_DSN in your CI environment."));
122
- console.log(chalk3.dim("The secret must be registered on your Vibgrate ingest API."));
123
- if (opts.write) {
124
- const writePath = path3.resolve(opts.write);
125
- await writeTextFile(writePath, dsn + "\n");
126
- console.log("");
127
- console.log(chalk3.green("\u2714") + ` DSN written to ${opts.write}`);
128
- console.log(chalk3.yellow("\u26A0") + " Add this file to .gitignore!");
129
- }
130
- });
131
-
132
- // src/commands/push.ts
133
- import * as crypto2 from "crypto";
134
- import * as path4 from "path";
135
- import { Command as Command4 } from "commander";
136
- import chalk4 from "chalk";
137
- function parseDsn(dsn) {
138
- const match = dsn.match(/^vibgrate\+https:\/\/([^:]+):([^@]+)@([^/]+)\/(.+)$/);
139
- if (!match) return null;
140
- return {
141
- keyId: match[1],
142
- secret: match[2],
143
- host: match[3],
144
- workspaceId: match[4]
145
- };
146
- }
147
- function computeHmac(body, secret) {
148
- return crypto2.createHmac("sha256", secret).update(body).digest("base64");
149
- }
150
- var pushCommand = new Command4("push").description("Push scan results to Vibgrate API").option("--dsn <dsn>", "DSN token (or use VIBGRATE_DSN env)").option("--region <region>", "Override data residency region (us, eu)").option("--file <file>", "Scan artifact file", ".vibgrate/scan_result.json").option("--strict", "Fail on upload errors").action(async (opts) => {
151
- const dsn = opts.dsn || process.env.VIBGRATE_DSN;
152
- if (!dsn) {
153
- console.error(chalk4.red("No DSN provided."));
154
- console.error(chalk4.dim("Set VIBGRATE_DSN environment variable or use --dsn flag."));
155
- if (opts.strict) process.exit(1);
156
- return;
157
- }
158
- const parsed = parseDsn(dsn);
159
- if (!parsed) {
160
- console.error(chalk4.red("Invalid DSN format."));
161
- console.error(chalk4.dim("Expected: vibgrate+https://<key_id>:<secret>@<host>/<workspace_id>"));
162
- if (opts.strict) process.exit(1);
163
- return;
164
- }
165
- const filePath = path4.resolve(opts.file);
166
- if (!await pathExists(filePath)) {
167
- console.error(chalk4.red(`Scan artifact not found: ${filePath}`));
168
- console.error(chalk4.dim('Run "vibgrate scan" first.'));
169
- if (opts.strict) process.exit(1);
170
- return;
171
- }
172
- const body = await readTextFile(filePath);
173
- const timestamp = String(Date.now());
174
- const hmac = computeHmac(body, parsed.secret);
175
- let host = parsed.host;
176
- if (opts.region) {
177
- try {
178
- host = resolveIngestHost(opts.region);
179
- } catch (e) {
180
- console.error(chalk4.red(e instanceof Error ? e.message : String(e)));
181
- if (opts.strict) process.exit(1);
182
- return;
183
- }
184
- }
185
- const url = `https://${host}/v1/ingest/scan`;
186
- console.log(chalk4.dim(`Uploading to ${host}...`));
187
- try {
188
- const response = await fetch(url, {
189
- method: "POST",
190
- headers: {
191
- "Content-Type": "application/json",
192
- "X-Vibgrate-Timestamp": timestamp,
193
- "Authorization": `VibgrateDSN ${parsed.keyId}:${hmac}`
194
- },
195
- body
196
- });
197
- if (!response.ok) {
198
- const text = await response.text();
199
- throw new Error(`HTTP ${response.status}: ${text}`);
200
- }
201
- const result = await response.json();
202
- console.log(chalk4.green("\u2714") + ` Uploaded successfully (${result.ingestId ?? "ok"})`);
203
- } catch (e) {
204
- const msg = e instanceof Error ? e.message : String(e);
205
- console.error(chalk4.red(`Upload failed: ${msg}`));
206
- if (opts.strict) process.exit(1);
207
- }
208
- });
209
-
210
77
  // src/commands/update.ts
211
78
  import { execSync } from "child_process";
212
- import * as path6 from "path";
213
- import { Command as Command5 } from "commander";
214
- import chalk5 from "chalk";
79
+ import * as path4 from "path";
80
+ import { Command as Command3 } from "commander";
81
+ import chalk3 from "chalk";
215
82
 
216
83
  // src/utils/update-check.ts
217
84
  import * as fs from "fs/promises";
218
- import * as path5 from "path";
85
+ import * as path3 from "path";
219
86
  import * as os from "os";
220
87
  import semver from "semver";
221
88
  var REGISTRY_URL = "https://registry.npmjs.org/@vibgrate%2fcli/latest";
222
- var CACHE_DIR = path5.join(os.homedir(), ".vibgrate");
223
- var CACHE_FILE = path5.join(CACHE_DIR, "update-check.json");
89
+ var CACHE_DIR = path3.join(os.homedir(), ".vibgrate");
90
+ var CACHE_FILE = path3.join(CACHE_DIR, "update-check.json");
224
91
  var CHECK_INTERVAL_MS = 12 * 60 * 60 * 1e3;
225
92
  async function checkForUpdate() {
226
93
  try {
@@ -292,9 +159,9 @@ async function writeCache(data) {
292
159
 
293
160
  // src/commands/update.ts
294
161
  async function detectPackageManager(cwd) {
295
- if (await pathExists(path6.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
296
- if (await pathExists(path6.join(cwd, "bun.lockb"))) return "bun";
297
- if (await pathExists(path6.join(cwd, "yarn.lock"))) return "yarn";
162
+ if (await pathExists(path4.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
163
+ if (await pathExists(path4.join(cwd, "bun.lockb"))) return "bun";
164
+ if (await pathExists(path4.join(cwd, "yarn.lock"))) return "yarn";
298
165
  return "npm";
299
166
  }
300
167
  function getInstallCommand(pm, pkg, version, isDev) {
@@ -313,7 +180,7 @@ function getInstallCommand(pm, pkg, version, isDev) {
313
180
  }
314
181
  async function isDevDependency(cwd) {
315
182
  try {
316
- const pkgPath = path6.join(cwd, "package.json");
183
+ const pkgPath = path4.join(cwd, "package.json");
317
184
  const raw = await (await import("fs/promises")).readFile(pkgPath, "utf-8");
318
185
  const pkg = JSON.parse(raw);
319
186
  return Boolean(pkg.devDependencies?.["@vibgrate/cli"]);
@@ -321,40 +188,40 @@ async function isDevDependency(cwd) {
321
188
  return true;
322
189
  }
323
190
  }
324
- var updateCommand = new Command5("update").description("Update vibgrate to the latest version").option("--check", "Only check for updates, do not install").option("--pm <manager>", "Package manager to use (npm, pnpm, yarn, bun)").action(async (opts) => {
325
- console.log(chalk5.dim(`Current version: ${VERSION}`));
326
- console.log(chalk5.dim("Checking npm registry..."));
191
+ var updateCommand = new Command3("update").description("Update vibgrate to the latest version").option("--check", "Only check for updates, do not install").option("--pm <manager>", "Package manager to use (npm, pnpm, yarn, bun)").action(async (opts) => {
192
+ console.log(chalk3.dim(`Current version: ${VERSION}`));
193
+ console.log(chalk3.dim("Checking npm registry..."));
327
194
  const latest = await fetchLatestVersion();
328
195
  if (!latest) {
329
- console.error(chalk5.red("Could not reach the npm registry. Check your network connection."));
196
+ console.error(chalk3.red("Could not reach the npm registry. Check your network connection."));
330
197
  process.exit(1);
331
198
  }
332
199
  const semver2 = await import("semver");
333
200
  if (!semver2.gt(latest, VERSION)) {
334
- console.log(chalk5.green("\u2714") + ` You are on the latest version (${VERSION}).`);
201
+ console.log(chalk3.green("\u2714") + ` You are on the latest version (${VERSION}).`);
335
202
  return;
336
203
  }
337
- console.log(chalk5.yellow(`Update available: ${VERSION} \u2192 ${latest}`));
204
+ console.log(chalk3.yellow(`Update available: ${VERSION} \u2192 ${latest}`));
338
205
  if (opts.check) {
339
- console.log(chalk5.dim('Run "vibgrate update" to install.'));
206
+ console.log(chalk3.dim('Run "vibgrate update" to install.'));
340
207
  return;
341
208
  }
342
209
  const cwd = process.cwd();
343
210
  const pm = opts.pm || await detectPackageManager(cwd);
344
211
  const isDev = await isDevDependency(cwd);
345
212
  const cmd = getInstallCommand(pm, "@vibgrate/cli", latest, isDev);
346
- console.log(chalk5.dim(`Using ${pm}: ${cmd}`));
213
+ console.log(chalk3.dim(`Using ${pm}: ${cmd}`));
347
214
  try {
348
215
  execSync(cmd, { cwd, stdio: "inherit" });
349
- console.log(chalk5.green("\u2714") + ` Updated to @vibgrate/cli@${latest}`);
216
+ console.log(chalk3.green("\u2714") + ` Updated to @vibgrate/cli@${latest}`);
350
217
  } catch {
351
- console.error(chalk5.red(`Update failed. Run manually: ${cmd}`));
218
+ console.error(chalk3.red(`Update failed. Run manually: ${cmd}`));
352
219
  process.exit(1);
353
220
  }
354
221
  });
355
222
 
356
223
  // src/cli.ts
357
- var program = new Command6();
224
+ var program = new Command4();
358
225
  program.name("vibgrate").description("Continuous Upgrade Drift Intelligence for Node & .NET").version(VERSION);
359
226
  program.addCommand(initCommand);
360
227
  program.addCommand(scanCommand);
@@ -367,8 +234,8 @@ program.parseAsync().then(async () => {
367
234
  const update = await checkForUpdate();
368
235
  if (update?.updateAvailable) {
369
236
  console.error("");
370
- console.error(chalk6.yellow(` Update available: ${update.current} \u2192 ${update.latest}`));
371
- console.error(chalk6.dim(' Run "vibgrate update" to install the latest version.'));
237
+ console.error(chalk4.yellow(` Update available: ${update.current} \u2192 ${update.latest}`));
238
+ console.error(chalk4.dim(' Run "vibgrate update" to install the latest version.'));
372
239
  console.error("");
373
240
  }
374
241
  }).catch((err) => {
package/dist/index.d.ts CHANGED
@@ -21,6 +21,8 @@ interface ProjectScan {
21
21
  type: ProjectType;
22
22
  path: string;
23
23
  name: string;
24
+ /** Deterministic project ID: SHA-256 hash of `${path}:${name}:${workspaceId}` */
25
+ projectId?: string;
24
26
  runtime?: string;
25
27
  runtimeLatest?: string;
26
28
  runtimeMajorsBehind?: number;
@@ -33,6 +35,8 @@ interface ProjectScan {
33
35
  twoPlusBehind: number;
34
36
  unknown: number;
35
37
  };
38
+ /** Individual project drift score (computed per-project, then aggregated into artifact.drift) */
39
+ drift?: DriftScore;
36
40
  }
37
41
  interface DriftScore {
38
42
  score: number;
@@ -84,6 +88,13 @@ interface ScanOptions {
84
88
  baseline?: string;
85
89
  changedOnly?: boolean;
86
90
  concurrency: number;
91
+ /** Auto-push after scan. If set, artifact is uploaded using this DSN (or VIBGRATE_DSN env). */
92
+ push?: boolean;
93
+ dsn?: string;
94
+ /** Override data residency region for push */
95
+ region?: string;
96
+ /** Fail on push errors (like --strict on push command) */
97
+ strict?: boolean;
87
98
  }
88
99
  interface ScannerToggle {
89
100
  enabled: boolean;
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  formatText,
8
8
  generateFindings,
9
9
  runScan
10
- } from "./chunk-VMNBKARQ.js";
10
+ } from "./chunk-XZ4NRZMT.js";
11
11
  export {
12
12
  computeDriftScore,
13
13
  formatMarkdown,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibgrate/cli",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "CLI for measuring upgrade drift across Node & .NET projects",
5
5
  "type": "module",
6
6
  "bin": {