@velaro/cli 0.1.2 → 0.3.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.
package/lib/oauth.js CHANGED
@@ -22,7 +22,8 @@
22
22
  */
23
23
 
24
24
  const TENANT_ID = '61de45b3-458d-49a5-913c-501247a6fe4f';
25
- const AUTHORITY = `https://login.microsoftonline.com/${TENANT_ID}`;
25
+ // CIAM tenant uses login.velaro.com, not login.microsoftonline.com
26
+ const AUTHORITY = `https://login.velaro.com/${TENANT_ID}`;
26
27
  const CLIENT_ID = process.env.VELARO_CLI_CLIENT_ID || 'c0fdce54-e9b4-4427-a021-b2605855ff8b';
27
28
 
28
29
  const SCOPE = [
package/lib/run.js CHANGED
@@ -1,8 +1,13 @@
1
- /** Wraps a yargs command handler with consistent error reporting. */
1
+ import { track } from './track.js';
2
+
3
+ /** Wraps a yargs command handler with consistent error reporting and usage tracking. */
2
4
  export function runCommand(fn) {
3
5
  return async (argv) => {
4
6
  try {
5
7
  await fn(argv);
8
+ // Fire-and-forget tracking after successful command — never awaited, never blocks
9
+ const action = argv._.join('.') || 'unknown';
10
+ track(action);
6
11
  } catch (err) {
7
12
  console.error(`Error: ${err.message}`);
8
13
  process.exit(1);
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Subscription helpers for CLI commands.
3
+ * Provides a clean gate that prints a plan upgrade message instead of
4
+ * throwing a confusing 403/400 from the API.
5
+ */
6
+
7
+ import { get } from './api.js';
8
+
9
+ let _cachedSub = null;
10
+
11
+ export async function getSubscription() {
12
+ if (!_cachedSub) {
13
+ _cachedSub = await get('/Subscription');
14
+ }
15
+ return _cachedSub;
16
+ }
17
+
18
+ /**
19
+ * Throws an Error with a friendly upgrade message if the feature flag is off.
20
+ * Usage: await requireFeature('enableAI', 'AI Bots');
21
+ */
22
+ export async function requireFeature(flag, featureName) {
23
+ const sub = await getSubscription();
24
+ if (!sub[flag]) {
25
+ throw new Error(
26
+ `${featureName} is not enabled on your plan.\n` +
27
+ ` Upgrade at https://velaro.com/pricing or contact sales@velaro.com.`
28
+ );
29
+ }
30
+ return sub;
31
+ }
32
+
33
+ /**
34
+ * Returns true/false without throwing — for check/status commands.
35
+ */
36
+ export async function hasFeature(flag) {
37
+ const sub = await getSubscription();
38
+ return sub[flag] === true;
39
+ }
package/lib/track.js ADDED
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Fire-and-forget CLI usage tracker.
3
+ * Posts a single event to /ToolUsage/cli after each command.
4
+ * Never throws, never blocks — silently dropped on any failure.
5
+ */
6
+ import { readConfig } from './config.js';
7
+ import { createRequire } from 'module';
8
+
9
+ const require = createRequire(import.meta.url);
10
+ const { version: CLI_VERSION } = require('../package.json');
11
+
12
+ /**
13
+ * Track a CLI action. Call after a command succeeds.
14
+ * @param {string} action e.g. "login", "bot.push", "workflow.pull"
15
+ */
16
+ export function track(action) {
17
+ setImmediate(async () => {
18
+ try {
19
+ const creds = readConfig();
20
+ if (!creds?.velaroToken || !creds?.apiBase) return;
21
+
22
+ await fetch(`${creds.apiBase}/ToolUsage/cli`, {
23
+ method: 'POST',
24
+ headers: {
25
+ Authorization: `Bearer ${creds.velaroToken}`,
26
+ 'Content-Type': 'application/json',
27
+ },
28
+ body: JSON.stringify({ action, cliVersion: CLI_VERSION }),
29
+ signal: AbortSignal.timeout(3000),
30
+ });
31
+ } catch {
32
+ // Silently drop — tracking must never surface errors to the user
33
+ }
34
+ });
35
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Non-blocking update checker.
3
+ * Fetches the latest version from npm once per day (cached in ~/.velaro/config.json).
4
+ * Prints a one-line notice AFTER the command completes if a newer version is available.
5
+ */
6
+
7
+ import { readConfig, writeConfig } from './config.js';
8
+ import { createRequire } from 'module';
9
+
10
+ const require = createRequire(import.meta.url);
11
+ const { version: currentVersion } = require('../package.json');
12
+
13
+ const NPM_REGISTRY = 'https://registry.npmjs.org/@velaro/cli/latest';
14
+ const CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000; // once per day
15
+
16
+ /**
17
+ * Starts the update check in the background.
18
+ * Returns a function you await AFTER your command finishes to print any notice.
19
+ */
20
+ export function startUpdateCheck() {
21
+ const cfg = readConfig();
22
+ const lastCheck = cfg._lastUpdateCheck ?? 0;
23
+ const now = Date.now();
24
+
25
+ if (now - lastCheck < CHECK_INTERVAL_MS) {
26
+ // Use cached result — no network call
27
+ return async () => printNoticeIfStale(cfg._latestVersion);
28
+ }
29
+
30
+ // Fire off the network request without awaiting it here
31
+ const fetchPromise = fetch(NPM_REGISTRY, { signal: AbortSignal.timeout(4000) })
32
+ .then((r) => r.json())
33
+ .then((data) => {
34
+ const latest = data?.version ?? null;
35
+ writeConfig({ ...readConfig(), _lastUpdateCheck: now, _latestVersion: latest });
36
+ return latest;
37
+ })
38
+ .catch(() => null); // never block the CLI on a network failure
39
+
40
+ return async () => {
41
+ const latest = await fetchPromise;
42
+ printNoticeIfStale(latest);
43
+ };
44
+ }
45
+
46
+ function printNoticeIfStale(latest) {
47
+ if (!latest || latest === currentVersion) return;
48
+ if (!isNewer(latest, currentVersion)) return;
49
+
50
+ process.stderr.write(
51
+ `\n Update available: ${currentVersion} → ${latest}\n` +
52
+ ` Run: npm install -g @velaro/cli@latest\n\n`
53
+ );
54
+ }
55
+
56
+ function isNewer(a, b) {
57
+ const pa = a.split('.').map(Number);
58
+ const pb = b.split('.').map(Number);
59
+ for (let i = 0; i < 3; i++) {
60
+ if ((pa[i] ?? 0) > (pb[i] ?? 0)) return true;
61
+ if ((pa[i] ?? 0) < (pb[i] ?? 0)) return false;
62
+ }
63
+ return false;
64
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@velaro/cli",
3
- "version": "0.1.2",
3
+ "version": "0.3.0",
4
4
  "description": "Velaro Workspace v20 — command-line interface for managing bots, knowledge base ingestion, and MCP API keys.",
5
5
  "type": "module",
6
6
  "bin": {