carto-md 2.0.4 → 2.0.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "carto-md",
3
- "version": "2.0.4",
3
+ "version": "2.0.5",
4
4
  "description": "Structural intelligence layer for AI coding tools. Indexes your codebase into SQLite — routes, models, import graph, blast radius, domains — and exposes 16 MCP tools for Kiro, Cursor, and Claude.",
5
5
  "bin": {
6
6
  "carto": "src/cli/index.js"
package/src/cli/check.js CHANGED
@@ -4,8 +4,10 @@ const { execSync } = require('child_process');
4
4
  const path = require('path');
5
5
  const fs = require('fs');
6
6
  const { SQLiteStore } = require('../store/sqlite-store');
7
+ const { checkForUpdate } = require('./update-check');
7
8
 
8
9
  async function run(projectRoot) {
10
+ checkForUpdate(); // fire and forget
9
11
  const dbPath = path.join(projectRoot, '.carto', 'carto.db');
10
12
 
11
13
  if (!fs.existsSync(dbPath)) {
package/src/cli/impact.js CHANGED
@@ -2,8 +2,10 @@
2
2
 
3
3
  const path = require('path');
4
4
  const { Carto } = require('../../index.js');
5
+ const { checkForUpdate } = require('./update-check');
5
6
 
6
7
  async function run(projectRoot, fileArg) {
8
+ checkForUpdate(); // fire and forget
7
9
  if (!fileArg) {
8
10
  console.error('[CARTO] Usage: carto impact <file>');
9
11
  process.exit(1);
package/src/cli/init.js CHANGED
@@ -3,8 +3,10 @@ const path = require('path');
3
3
  const { detectFramework } = require('../detector/framework');
4
4
  const { parseCartoIgnore } = require('../security/ignore');
5
5
  const { runSyncV2, discoverFiles: discoverFilesV2 } = require('../store/sync-v2');
6
+ const { checkForUpdate } = require('./update-check');
6
7
 
7
8
  async function run(projectRoot) {
9
+ checkForUpdate(); // fire and forget
8
10
  console.log('[CARTO] Detecting project...');
9
11
 
10
12
  const detection = detectFramework(projectRoot);
package/src/cli/serve.js CHANGED
@@ -1,7 +1,9 @@
1
1
  const path = require('path');
2
2
  const fs = require('fs');
3
+ const { checkForUpdate } = require('./update-check');
3
4
 
4
5
  function run(projectRoot) {
6
+ checkForUpdate(); // fire and forget
5
7
  // Prefer V2 SQLite-backed server
6
8
  const dbPath = path.join(projectRoot, '.carto', 'carto.db');
7
9
  if (fs.existsSync(dbPath)) {
@@ -1,12 +1,21 @@
1
+ 'use strict';
2
+
1
3
  const https = require('https');
2
4
  const pkg = require('../../package.json');
3
5
 
4
6
  /**
5
7
  * Fire-and-forget version check against the npm registry.
6
- * Prints a one-liner to stderr if a newer version exists.
7
- * Never throws, never blocks safe to call without await.
8
+ *
9
+ * Prints a visually distinct notice to stderr if a newer version is on npm.
10
+ * Never throws, never blocks (3s socket timeout, ignores all errors) —
11
+ * safe to call without await from any CLI command's entry point.
12
+ *
13
+ * Set `CARTO_NO_UPDATE_CHECK=1` to disable entirely (used in test runs and
14
+ * by users who don't want the egress).
8
15
  */
9
16
  function checkForUpdate() {
17
+ if (process.env.CARTO_NO_UPDATE_CHECK) return;
18
+
10
19
  const req = https.get('https://registry.npmjs.org/carto-md/latest', {
11
20
  timeout: 3000,
12
21
  }, (res) => {
@@ -16,10 +25,8 @@ function checkForUpdate() {
16
25
  try {
17
26
  const data = JSON.parse(body);
18
27
  const latest = data.version;
19
- if (latest && latest !== pkg.version && isNewer(latest, pkg.version)) {
20
- process.stderr.write(
21
- `[CARTO] Update available: ${pkg.version} → ${latest} | npm install -g carto-md\n`
22
- );
28
+ if (latest && isNewer(latest, pkg.version)) {
29
+ process.stderr.write(formatNotice(pkg.version, latest));
23
30
  }
24
31
  } catch (_) {
25
32
  // malformed JSON — ignore
@@ -27,6 +34,10 @@ function checkForUpdate() {
27
34
  });
28
35
  });
29
36
 
37
+ // unref so the pending request never delays process exit on its own —
38
+ // if the main command finishes first, the check is silently dropped.
39
+ if (typeof req.unref === 'function') req.unref();
40
+
30
41
  req.on('timeout', () => { req.destroy(); });
31
42
  req.on('error', () => { /* offline / DNS failure — ignore */ });
32
43
  }
@@ -45,4 +56,36 @@ function isNewer(a, b) {
45
56
  return false;
46
57
  }
47
58
 
48
- module.exports = { checkForUpdate };
59
+ /**
60
+ * formatNotice(current, latest) → multi-line stderr string.
61
+ *
62
+ * TTY-aware: emits ANSI yellow + bold when stderr is a TTY, plain text
63
+ * otherwise (so piped output and CI logs stay clean).
64
+ *
65
+ * Format (TTY example, ★ in yellow, version + command in bold):
66
+ *
67
+ * <blank line>
68
+ * [CARTO] ★ Update available: 2.0.1 → 2.0.5
69
+ * [CARTO] Run: npm install -g carto-md
70
+ * <blank line>
71
+ *
72
+ * Two blank lines (one before, one after) separate the notice from
73
+ * regular [CARTO] log output so the upgrade prompt stands out even when
74
+ * it lands mid-progress (the check is fire-and-forget, so the response
75
+ * arrives whenever the network resolves).
76
+ */
77
+ function formatNotice(current, latest) {
78
+ const useColor = !!process.stderr.isTTY && !process.env.NO_COLOR;
79
+ const yellow = (s) => useColor ? `\x1b[33m${s}\x1b[0m` : s;
80
+ const bold = (s) => useColor ? `\x1b[1m${s}\x1b[0m` : s;
81
+
82
+ return [
83
+ '',
84
+ `${yellow('[CARTO] ★ Update available:')} ${bold(`${current} → ${latest}`)}`,
85
+ `${yellow('[CARTO] Run:')} ${bold('npm install -g carto-md')}`,
86
+ '',
87
+ ''
88
+ ].join('\n');
89
+ }
90
+
91
+ module.exports = { checkForUpdate, isNewer, formatNotice };