@gurulu/cli 0.3.3 → 0.4.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @gurulu/cli
2
2
 
3
- CLI wizard for setting up Gurulu.io analytics in any project.
3
+ CLI for Gurulu.io — setup, diagnostics, data exploration, and AI-powered analytics from your terminal.
4
4
 
5
5
  ## Quick Start
6
6
 
@@ -10,31 +10,76 @@ npx @gurulu/cli init
10
10
 
11
11
  ## Commands
12
12
 
13
+ ### Authentication
14
+
15
+ | Command | Description |
16
+ |---------|-------------|
17
+ | `gurulu auth` | Authenticate via device-link flow (or `--key` for manual) |
18
+ | `gurulu login` | Authenticate with API key |
19
+ | `gurulu logout` | Remove a stored profile |
20
+ | `gurulu whoami` | Show current authentication state |
21
+
22
+ ### Setup & Diagnostics
23
+
13
24
  | Command | Description |
14
25
  |---------|-------------|
15
26
  | `gurulu init` | Set up Gurulu analytics (auto-detects framework) |
16
- | `gurulu login` | Authenticate with your Personal API Key |
17
- | `gurulu events` | List detected events from your site |
18
- | `gurulu status` | Quick health check |
19
- | `gurulu doctor` | Comprehensive diagnostics |
27
+ | `gurulu install [path]` | Install Gurulu tracker in a repository |
20
28
  | `gurulu add-server` | Add server-side SDK (@gurulu/node) |
29
+ | `gurulu status` | Check SDK health and connection |
30
+ | `gurulu doctor` | Diagnose setup issues |
31
+ | `gurulu config <action>` | Manage CLI profiles (list, use, show, delete) |
32
+
33
+ ### Sites & Keys
34
+
35
+ | Command | Description |
36
+ |---------|-------------|
37
+ | `gurulu sites <action>` | Manage sites (list, create, show, delete, rotate-token) |
38
+ | `gurulu api-keys <action>` | Manage API keys (list, create, revoke, rotate) |
39
+
40
+ ### Data & Events
41
+
42
+ | Command | Description |
43
+ |---------|-------------|
44
+ | `gurulu events <action>` | View ingested events (list, tail) |
45
+ | `gurulu insights <action>` | View daily insights (today, history, weekly) |
46
+ | `gurulu chat [question]` | Ask analytics questions in natural language (NL -> SQL) |
47
+
48
+ ### Identity & Audiences
49
+
50
+ | Command | Description |
51
+ |---------|-------------|
52
+ | `gurulu identity <action>` | View identity state (decay, transfers, cdc-sources) |
53
+ | `gurulu audiences <action>` | View audiences (list, show) |
54
+ | `gurulu experiments <action>` | View experiments (list, show, results) |
55
+
56
+ ### Integrations & Export
57
+
58
+ | Command | Description |
59
+ |---------|-------------|
60
+ | `gurulu warehouse <action>` | Warehouse exports (BigQuery) |
61
+ | `gurulu warehouses <action>` | View warehouse exports (list, runs) |
62
+ | `gurulu destinations <action>` | View activation destinations (list, show) |
63
+ | `gurulu db <action>` | Connect, list, sync, or remove database sources |
64
+
65
+ ### Monitoring & Debugging
66
+
67
+ | Command | Description |
68
+ |---------|-------------|
69
+ | `gurulu alerts <action>` | View anomaly alerts (list, show, channels) |
70
+ | `gurulu sourcemap <action>` | Upload source maps for error deobfuscation |
71
+ | `gurulu audit <action>` | Stream or export the CLI audit log (tail, export) |
72
+ | `gurulu playground <action>` | View playground sessions (list) |
21
73
 
22
74
  ## Supported Frameworks
23
75
 
24
- - Next.js (App Router & Pages Router)
25
- - React (Vite & CRA)
26
- - Vue 3
27
- - Nuxt 3
28
- - Svelte & SvelteKit
29
- - Astro
30
- - Express
31
- - NestJS
32
- - Plain HTML
76
+ Next.js (App & Pages Router), React (Vite & CRA), Vue 3, Nuxt 3, Svelte & SvelteKit, Astro, Express, NestJS, Plain HTML.
33
77
 
34
78
  ## Authentication
35
79
 
36
80
  ```bash
37
- gurulu login --api-key pak_live_xxxxx
81
+ gurulu auth # Device-link flow (recommended)
82
+ gurulu login --api-key pak_live_x # Manual API key
38
83
  ```
39
84
 
40
85
  Or set the `GURULU_API_KEY` environment variable.
@@ -52,15 +97,7 @@ gurulu init --site-id abc123 --token tok_xxx --no-interactive
52
97
  Use `--json` flag for machine-readable output:
53
98
 
54
99
  ```bash
55
- gurulu events --json
100
+ gurulu events list --json
56
101
  gurulu status --json
57
102
  gurulu doctor --json
58
103
  ```
59
-
60
- ## Development
61
-
62
- ```bash
63
- npm install
64
- npm run build
65
- node bin/gurulu.js --help
66
- ```
@@ -97,7 +97,7 @@ async function cliApi(path, init = {}) {
97
97
  if (!init.skipAuth && profile) {
98
98
  headers.set('authorization', `Bearer ${profile.secret_key}`);
99
99
  }
100
- if (init.body && !headers.has('content-type')) {
100
+ if (init.body && !headers.has('content-type') && !(init.body instanceof FormData)) {
101
101
  headers.set('content-type', 'application/json');
102
102
  }
103
103
  let res;
@@ -237,6 +237,19 @@ function log(deps, level, msg) {
237
237
  return;
238
238
  l[level](msg);
239
239
  }
240
+ function getEnvPrefix(framework) {
241
+ if (framework.startsWith('nextjs'))
242
+ return 'NEXT_PUBLIC_';
243
+ if (framework === 'vite-react' || framework === 'vite')
244
+ return 'VITE_';
245
+ if (framework === 'nuxt' || framework === 'vue')
246
+ return 'NUXT_PUBLIC_';
247
+ if (framework === 'sveltekit' || framework === 'svelte')
248
+ return 'PUBLIC_';
249
+ if (framework === 'astro')
250
+ return 'PUBLIC_';
251
+ return ''; // Express, Fastify, NestJS don't need prefix
252
+ }
240
253
  async function runInstallFlow(args, deps, scriptsDir) {
241
254
  const repoRoot = path.resolve(args.path || process.cwd());
242
255
  const summary = {
@@ -429,10 +442,11 @@ async function runInstallFlow(args, deps, scriptsDir) {
429
442
  }
430
443
  // ---- 6. .env merge ---------------------------------------------------
431
444
  const ingestUrl = args.ingestUrl || process.env.GURULU_INGEST_URL || 'https://gurulu.io';
445
+ const envPrefix = getEnvPrefix(detectedFw);
432
446
  const envVars = {
433
- NEXT_PUBLIC_GURULU_SITE_ID: args.siteId,
434
- NEXT_PUBLIC_GURULU_TENANT_ID: args.tenantId,
435
- NEXT_PUBLIC_GURULU_INGEST_URL: ingestUrl,
447
+ [`${envPrefix}GURULU_SITE_ID`]: args.siteId,
448
+ [`${envPrefix}GURULU_TENANT_ID`]: args.tenantId,
449
+ [`${envPrefix}GURULU_INGEST_URL`]: ingestUrl,
436
450
  };
437
451
  if (args.skipEnv || args.dryRun) {
438
452
  log(deps, 'info', 'Skipping .env merge.');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gurulu/cli",
3
- "version": "0.3.3",
3
+ "version": "0.4.0",
4
4
  "description": "Gurulu.io CLI — setup analytics in seconds",
5
5
  "bin": {
6
6
  "gurulu": "bin/gurulu.js"
@@ -138,7 +138,7 @@ async function runPatchMode(repoRoot, args) {
138
138
  siteId: args['site-id'],
139
139
  tenantId: args['tenant-id'],
140
140
  publishableKey: args['publishable-key'] || '',
141
- scriptSrc: args['script-src'] || '/gurulu-tracker.js',
141
+ scriptSrc: args['script-src'] || 'https://gurulu.io/t.js',
142
142
  });
143
143
  const plan = patcher.plan({ repoRoot, injection });
144
144
  log(`Framework: ${patcher.name}`);
@@ -37,6 +37,7 @@ function buildScriptTag(injection) {
37
37
  ` src="${injection.scriptSrc}"\n` +
38
38
  ` data-gurulu-site-id="${injection.siteId}"\n` +
39
39
  ` data-gurulu-tenant-id="${injection.tenantId}"${pkAttr}\n` +
40
+ ` data-features="errors,replay,advanced"\n` +
40
41
  ` ${MARKER}\n` +
41
42
  ` async\n` +
42
43
  ` ></script>\n`
@@ -2,7 +2,7 @@
2
2
  //
3
3
  // Detects an Express server (`app.js`, `server.js`, `src/index.js` with the
4
4
  // idiomatic `const app = express()` signature) and appends:
5
- // - A proxy route that serves /gurulu-tracker.js from the Gurulu CDN
5
+ // - A proxy route that serves /gurulu-tracker from the Gurulu CDN
6
6
  // - A `res.locals.guruluConfig` middleware exposing siteId / tenantId
7
7
 
8
8
  const fs = require('fs');
@@ -59,7 +59,7 @@ function buildMiddleware(appVar, injection) {
59
59
  ` };\n` +
60
60
  ` next();\n` +
61
61
  `});\n` +
62
- `${appVar}.use('/gurulu-tracker.js', (req, res) => {\n` +
62
+ `${appVar}.use('/gurulu-tracker', (req, res) => {\n` +
63
63
  ` res.set('Content-Type', 'application/javascript');\n` +
64
64
  ` res.send(\`// Gurulu tracker proxy — site=\${${JSON.stringify(injection.siteId)}} data-gurulu-publishable-key=\${${JSON.stringify(injection.publishableKey || '')}}\\n` +
65
65
  `window.gurulu = window.gurulu || { queue: [] };\`);\n` +
@@ -68,6 +68,7 @@ function buildScriptTag(injection) {
68
68
  ` src="${injection.scriptSrc}"\n` +
69
69
  ` data-gurulu-site-id="${injection.siteId}"\n` +
70
70
  ` data-gurulu-tenant-id="${injection.tenantId}"${pkAttr}\n` +
71
+ ` data-features="errors,replay,advanced"\n` +
71
72
  ` ${MARKER}\n` +
72
73
  ` async\n` +
73
74
  ` ></script>\n`
@@ -70,6 +70,7 @@ function buildScriptTag(injection) {
70
70
  ` src="${injection.scriptSrc}"\n` +
71
71
  ` data-gurulu-site-id="${injection.siteId}"\n` +
72
72
  ` data-gurulu-tenant-id="${injection.tenantId}"${pkAttr}\n` +
73
+ ` data-features="errors,replay,advanced"\n` +
73
74
  ` ${MARKER}\n` +
74
75
  ` async\n` +
75
76
  ` ></script>\n`
@@ -2,7 +2,7 @@
2
2
  //
3
3
  // Detects a Next.js App Router layout (`src/app/layout.tsx` or `app/layout.tsx`)
4
4
  // and injects a <Script> tag loaded via next/script that points to the Gurulu
5
- // Web SDK tracker (`/gurulu-tracker.js` by default).
5
+ // Web SDK tracker (`https://gurulu.io/t.js` by default).
6
6
  //
7
7
  // Regex-based: fast alpha, good enough for most idiomatic RootLayouts.
8
8
 
@@ -40,7 +40,7 @@ function buildScriptTag(injection) {
40
40
  ` data-gurulu-site-id=${JSON.stringify(injection.siteId)}\n` +
41
41
  ` data-gurulu-tenant-id=${JSON.stringify(injection.tenantId)}\n` +
42
42
  pkAttr +
43
- ` data-features="errors"\n` +
43
+ ` data-features="errors,replay,advanced"\n` +
44
44
  ` ${MARKER}\n` +
45
45
  ` />\n`
46
46
  );
@@ -54,6 +54,7 @@ function buildHook(injection) {
54
54
  ` s.setAttribute('data-gurulu-site-id', ${JSON.stringify(injection.siteId)});\n` +
55
55
  ` s.setAttribute('data-gurulu-tenant-id', ${JSON.stringify(injection.tenantId)});\n` +
56
56
  pkLine +
57
+ ` s.setAttribute('data-features', 'errors,replay,advanced');\n` +
57
58
  ` document.head.appendChild(s);\n` +
58
59
  ` }, []);\n`
59
60
  );
@@ -36,6 +36,7 @@ function buildScriptTag(injection) {
36
36
  ` data-gurulu-site-id=${JSON.stringify(injection.siteId)}\n` +
37
37
  ` data-gurulu-tenant-id=${JSON.stringify(injection.tenantId)}\n` +
38
38
  pkAttr +
39
+ ` data-features="errors,replay,advanced"\n` +
39
40
  ` ${MARKER}\n` +
40
41
  ` async\n` +
41
42
  ` />\n`
@@ -33,6 +33,7 @@ function buildScriptTag(injection) {
33
33
  ` src="${injection.scriptSrc}"\n` +
34
34
  ` data-gurulu-site-id="${injection.siteId}"\n` +
35
35
  ` data-gurulu-tenant-id="${injection.tenantId}"${pkAttr}\n` +
36
+ ` data-features="errors,replay,advanced"\n` +
36
37
  ` ${MARKER}\n` +
37
38
  ` async\n` +
38
39
  ` ></script>\n`
@@ -35,6 +35,7 @@ function buildBootstrap(injection) {
35
35
  ` s.setAttribute('data-gurulu-install', '1');\n` +
36
36
  ` s.setAttribute('data-gurulu-site-id', ${JSON.stringify(injection.siteId)});\n` +
37
37
  pkLine +
38
+ ` s.setAttribute('data-features', 'errors,replay,advanced');\n` +
38
39
  ` document.head.appendChild(s);\n` +
39
40
  `}\n`
40
41
  );
@@ -48,6 +48,7 @@ function buildScriptTag(injection) {
48
48
  ` src="${injection.scriptSrc}"\n` +
49
49
  ` data-gurulu-site-id="${injection.siteId}"\n` +
50
50
  ` data-gurulu-tenant-id="${injection.tenantId}"${pkAttr}\n` +
51
+ ` data-features="errors,replay,advanced"\n` +
51
52
  ` ${MARKER}\n` +
52
53
  ` async\n` +
53
54
  ` ></script>\n`