@gurulu/cli 0.4.7 → 1.0.1

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 (190) hide show
  1. package/LICENSE +92 -0
  2. package/README.md +35 -106
  3. package/dist/bin.d.ts +3 -0
  4. package/dist/bin.d.ts.map +1 -0
  5. package/dist/bin.js +25751 -0
  6. package/dist/commands/auth.d.ts +23 -20
  7. package/dist/commands/auth.d.ts.map +1 -0
  8. package/dist/commands/doctor.d.ts +20 -6
  9. package/dist/commands/doctor.d.ts.map +1 -0
  10. package/dist/commands/init.d.ts +33 -11
  11. package/dist/commands/init.d.ts.map +1 -0
  12. package/dist/commands/pull.d.ts +13 -0
  13. package/dist/commands/pull.d.ts.map +1 -0
  14. package/dist/commands/push.d.ts +40 -0
  15. package/dist/commands/push.d.ts.map +1 -0
  16. package/dist/commands/validate.d.ts +36 -0
  17. package/dist/commands/validate.d.ts.map +1 -0
  18. package/dist/index.d.ts +4 -1
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +25326 -876
  21. package/dist/lib/api.d.ts +139 -0
  22. package/dist/lib/api.d.ts.map +1 -0
  23. package/dist/lib/codegen.d.ts +4 -0
  24. package/dist/lib/codegen.d.ts.map +1 -0
  25. package/dist/lib/config.d.ts +43 -0
  26. package/dist/lib/config.d.ts.map +1 -0
  27. package/dist/lib/detect.d.ts +27 -0
  28. package/dist/lib/detect.d.ts.map +1 -0
  29. package/dist/lib/detect.js +106 -0
  30. package/dist/lib/exec-install.d.ts +21 -0
  31. package/dist/lib/exec-install.d.ts.map +1 -0
  32. package/dist/lib/install-plan.d.ts +25 -0
  33. package/dist/lib/install-plan.d.ts.map +1 -0
  34. package/dist/lib/install-plan.js +161 -0
  35. package/package.json +51 -20
  36. package/bin/gurulu.js +0 -2
  37. package/dist/api-client.d.ts +0 -33
  38. package/dist/api-client.js +0 -175
  39. package/dist/commands/add-server.d.ts +0 -9
  40. package/dist/commands/add-server.js +0 -162
  41. package/dist/commands/alerts.d.ts +0 -27
  42. package/dist/commands/alerts.js +0 -309
  43. package/dist/commands/api-keys.d.ts +0 -20
  44. package/dist/commands/api-keys.js +0 -130
  45. package/dist/commands/attribution.d.ts +0 -22
  46. package/dist/commands/attribution.js +0 -111
  47. package/dist/commands/audiences.d.ts +0 -23
  48. package/dist/commands/audiences.js +0 -243
  49. package/dist/commands/audit.d.ts +0 -20
  50. package/dist/commands/audit.js +0 -130
  51. package/dist/commands/auth.js +0 -249
  52. package/dist/commands/chat.d.ts +0 -19
  53. package/dist/commands/chat.js +0 -118
  54. package/dist/commands/config.d.ts +0 -10
  55. package/dist/commands/config.js +0 -92
  56. package/dist/commands/consent.d.ts +0 -27
  57. package/dist/commands/consent.js +0 -233
  58. package/dist/commands/conversion-paths.d.ts +0 -19
  59. package/dist/commands/conversion-paths.js +0 -55
  60. package/dist/commands/db.d.ts +0 -25
  61. package/dist/commands/db.js +0 -330
  62. package/dist/commands/destinations.d.ts +0 -20
  63. package/dist/commands/destinations.js +0 -191
  64. package/dist/commands/doctor.js +0 -360
  65. package/dist/commands/errors.d.ts +0 -27
  66. package/dist/commands/errors.js +0 -121
  67. package/dist/commands/events.d.ts +0 -33
  68. package/dist/commands/events.js +0 -371
  69. package/dist/commands/experiments.d.ts +0 -22
  70. package/dist/commands/experiments.js +0 -264
  71. package/dist/commands/funnels.d.ts +0 -17
  72. package/dist/commands/funnels.js +0 -203
  73. package/dist/commands/goals.d.ts +0 -18
  74. package/dist/commands/goals.js +0 -214
  75. package/dist/commands/heatmap.d.ts +0 -27
  76. package/dist/commands/heatmap.js +0 -112
  77. package/dist/commands/identity.d.ts +0 -29
  78. package/dist/commands/identity.js +0 -328
  79. package/dist/commands/init.js +0 -215
  80. package/dist/commands/insights.d.ts +0 -10
  81. package/dist/commands/insights.js +0 -77
  82. package/dist/commands/install.d.ts +0 -259
  83. package/dist/commands/install.js +0 -1590
  84. package/dist/commands/login.d.ts +0 -20
  85. package/dist/commands/login.js +0 -170
  86. package/dist/commands/logout.d.ts +0 -10
  87. package/dist/commands/logout.js +0 -41
  88. package/dist/commands/playground.d.ts +0 -11
  89. package/dist/commands/playground.js +0 -47
  90. package/dist/commands/releases.d.ts +0 -17
  91. package/dist/commands/releases.js +0 -54
  92. package/dist/commands/replay.d.ts +0 -18
  93. package/dist/commands/replay.js +0 -64
  94. package/dist/commands/secrets.d.ts +0 -19
  95. package/dist/commands/secrets.js +0 -145
  96. package/dist/commands/setup.d.ts +0 -21
  97. package/dist/commands/setup.js +0 -67
  98. package/dist/commands/sites.d.ts +0 -18
  99. package/dist/commands/sites.js +0 -139
  100. package/dist/commands/skad.d.ts +0 -18
  101. package/dist/commands/skad.js +0 -53
  102. package/dist/commands/sourcemap.d.ts +0 -33
  103. package/dist/commands/sourcemap.js +0 -204
  104. package/dist/commands/status.d.ts +0 -7
  105. package/dist/commands/status.js +0 -136
  106. package/dist/commands/upgrade.d.ts +0 -21
  107. package/dist/commands/upgrade.js +0 -183
  108. package/dist/commands/warehouse.d.ts +0 -20
  109. package/dist/commands/warehouse.js +0 -65
  110. package/dist/commands/warehouses.d.ts +0 -17
  111. package/dist/commands/warehouses.js +0 -182
  112. package/dist/commands/watch.d.ts +0 -45
  113. package/dist/commands/watch.js +0 -258
  114. package/dist/commands/whoami.d.ts +0 -9
  115. package/dist/commands/whoami.js +0 -50
  116. package/dist/config.d.ts +0 -75
  117. package/dist/config.js +0 -329
  118. package/dist/frameworks/detect.d.ts +0 -8
  119. package/dist/frameworks/detect.js +0 -458
  120. package/dist/install-intent-proposal.d.ts +0 -99
  121. package/dist/install-intent-proposal.js +0 -202
  122. package/dist/utils/api.d.ts +0 -20
  123. package/dist/utils/api.js +0 -47
  124. package/dist/utils/config.d.ts +0 -13
  125. package/dist/utils/config.js +0 -30
  126. package/dist/utils/confirm.d.ts +0 -17
  127. package/dist/utils/confirm.js +0 -40
  128. package/dist/utils/dry-run.d.ts +0 -20
  129. package/dist/utils/dry-run.js +0 -67
  130. package/dist/utils/from-file.d.ts +0 -9
  131. package/dist/utils/from-file.js +0 -72
  132. package/dist/utils/redact.d.ts +0 -14
  133. package/dist/utils/redact.js +0 -48
  134. package/dist/utils/ui.d.ts +0 -14
  135. package/dist/utils/ui.js +0 -59
  136. package/scripts/.gitkeep +0 -0
  137. package/scripts/README-gurulu-agentic-install.md +0 -114
  138. package/scripts/README-gurulu-scan.md +0 -98
  139. package/scripts/audit-cli-scopes.mjs +0 -204
  140. package/scripts/backfill-tenant-id.mjs +0 -172
  141. package/scripts/backfill-tenant-links.ts +0 -252
  142. package/scripts/backup-clickhouse.sh +0 -27
  143. package/scripts/backup-postgres.sh +0 -19
  144. package/scripts/bootstrap-runtime-schema.mjs +0 -87
  145. package/scripts/bootstrap-stripe.mjs +0 -158
  146. package/scripts/gurulu-agentic-install.lib.cjs +0 -762
  147. package/scripts/gurulu-agentic-install.mjs +0 -623
  148. package/scripts/gurulu-scan.lib.cjs +0 -1509
  149. package/scripts/gurulu-scan.mjs +0 -91
  150. package/scripts/gurulu-verify-install.lib.cjs +0 -334
  151. package/scripts/gurulu-verify-install.mjs +0 -59
  152. package/scripts/init-ssl.sh +0 -26
  153. package/scripts/migrate-flow-graph-enums.sh +0 -86
  154. package/scripts/monitor-disk.sh +0 -24
  155. package/scripts/patches/astro.patch.cjs +0 -74
  156. package/scripts/patches/auto-instrument/ast-helper.cjs +0 -480
  157. package/scripts/patches/auto-instrument/astro.cjs +0 -273
  158. package/scripts/patches/auto-instrument/express.cjs +0 -383
  159. package/scripts/patches/auto-instrument/fastify.cjs +0 -262
  160. package/scripts/patches/auto-instrument/hono.cjs +0 -392
  161. package/scripts/patches/auto-instrument/index.cjs +0 -80
  162. package/scripts/patches/auto-instrument/nestjs.cjs +0 -286
  163. package/scripts/patches/auto-instrument/nextjs-app-router.cjs +0 -345
  164. package/scripts/patches/auto-instrument/nextjs-pages.cjs +0 -361
  165. package/scripts/patches/auto-instrument/remix.cjs +0 -168
  166. package/scripts/patches/auto-instrument/sdk-helper-map.cjs +0 -241
  167. package/scripts/patches/auto-instrument/singleton-helper.cjs +0 -193
  168. package/scripts/patches/auto-instrument/sveltekit.cjs +0 -161
  169. package/scripts/patches/auto-instrument/vite-react.cjs +0 -37
  170. package/scripts/patches/auto-instrument/vue.cjs +0 -196
  171. package/scripts/patches/express.patch.cjs +0 -99
  172. package/scripts/patches/fastify.patch.cjs +0 -108
  173. package/scripts/patches/index.cjs +0 -300
  174. package/scripts/patches/nestjs.patch.cjs +0 -112
  175. package/scripts/patches/nextjs-app-router.patch.cjs +0 -97
  176. package/scripts/patches/nextjs-pages.patch.cjs +0 -97
  177. package/scripts/patches/remix.patch.cjs +0 -75
  178. package/scripts/patches/sveltekit.patch.cjs +0 -72
  179. package/scripts/patches/vite-react.patch.cjs +0 -73
  180. package/scripts/patches/vue.patch.cjs +0 -82
  181. package/scripts/renew-ssl.sh +0 -14
  182. package/scripts/resolve-migration.sh +0 -23
  183. package/scripts/seed-cli-dev-keys.mjs +0 -130
  184. package/scripts/seed-test-data.mjs +0 -391
  185. package/scripts/spike-browserless.ts +0 -65
  186. package/scripts/tenant-pivot-consistency-check.mjs +0 -205
  187. package/scripts/tenant-pivot-phase-3-cleanup.lib.cjs +0 -258
  188. package/scripts/tenant-pivot-phase-3-cleanup.mjs +0 -98
  189. package/scripts/test-identity-resolution.ts +0 -804
  190. package/scripts/validate-gurulu-schemas.mjs +0 -79
@@ -1,328 +0,0 @@
1
- "use strict";
2
- /**
3
- * Phase 19.5 W2 B8 — `gurulu identity decay|transfers|cdc-sources`.
4
- *
5
- * Sprint E SE-D — `gurulu identity identify|alias|merge` write surface
6
- * (mirrors MCP `gurulu.identity.identify` / `.alias` / `.merge`).
7
- */
8
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
- if (k2 === undefined) k2 = k;
10
- var desc = Object.getOwnPropertyDescriptor(m, k);
11
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
- desc = { enumerable: true, get: function() { return m[k]; } };
13
- }
14
- Object.defineProperty(o, k2, desc);
15
- }) : (function(o, m, k, k2) {
16
- if (k2 === undefined) k2 = k;
17
- o[k2] = m[k];
18
- }));
19
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
- Object.defineProperty(o, "default", { enumerable: true, value: v });
21
- }) : function(o, v) {
22
- o["default"] = v;
23
- });
24
- var __importStar = (this && this.__importStar) || (function () {
25
- var ownKeys = function(o) {
26
- ownKeys = Object.getOwnPropertyNames || function (o) {
27
- var ar = [];
28
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
- return ar;
30
- };
31
- return ownKeys(o);
32
- };
33
- return function (mod) {
34
- if (mod && mod.__esModule) return mod;
35
- var result = {};
36
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
- __setModuleDefault(result, mod);
38
- return result;
39
- };
40
- })();
41
- Object.defineProperty(exports, "__esModule", { value: true });
42
- exports.identityCommand = identityCommand;
43
- const api_client_1 = require("../api-client");
44
- const ui_1 = require("../utils/ui");
45
- const fs = __importStar(require("fs"));
46
- const path = __importStar(require("path"));
47
- async function identityCommand(args) {
48
- const action = args.action || '';
49
- switch (action) {
50
- case 'decay':
51
- return decayCmd(args);
52
- case 'transfers':
53
- return transfersCmd(args);
54
- case 'cdc-sources':
55
- return cdcSourcesCmd(args);
56
- case 'identify':
57
- return identifyCmd(args);
58
- case 'alias':
59
- return aliasCmd(args);
60
- case 'merge':
61
- return mergeCmd(args);
62
- case 'bulk':
63
- return bulkCmd(args);
64
- default:
65
- (0, ui_1.error)(`Unknown identity action: ${action}`);
66
- (0, ui_1.info)('Usage: gurulu identity [decay stats|transfers list|cdc-sources list|identify|alias|merge|bulk]');
67
- process.exit(1);
68
- }
69
- }
70
- async function decayCmd(args) {
71
- // `gurulu identity decay stats` is the only supported form for Phase 19.5.
72
- if (args.sub && args.sub !== 'stats') {
73
- (0, ui_1.error)(`Unknown identity decay sub: ${args.sub}`);
74
- process.exit(1);
75
- }
76
- const body = await (0, api_client_1.cliApiJson)('/api/cli/identity/decay/stats', {
77
- profile: args.profile,
78
- });
79
- if (args.json) {
80
- process.stdout.write(JSON.stringify(body, null, 2) + '\n');
81
- return;
82
- }
83
- process.stdout.write(`Retired claims: ${body.totalRetiredClaims}\n`);
84
- process.stdout.write(`Retired tags: ${body.totalRetiredTags}\n`);
85
- process.stdout.write(`Recent jobs: ${(body.recentRuns || []).length}\n`);
86
- process.stdout.write(`Histogram:\n`);
87
- for (const [k, v] of Object.entries(body.decayHistogram || {})) {
88
- process.stdout.write(` ${k}: ${v}\n`);
89
- }
90
- }
91
- async function transfersCmd(args) {
92
- if (args.sub && args.sub !== 'list') {
93
- (0, ui_1.error)(`Unknown identity transfers sub: ${args.sub}`);
94
- process.exit(1);
95
- }
96
- const qs = new URLSearchParams();
97
- if (args.direction)
98
- qs.set('direction', args.direction);
99
- if (args.status)
100
- qs.set('status', args.status);
101
- if (args.limit)
102
- qs.set('limit', String(args.limit));
103
- const path = `/api/cli/identity/transfers${qs.toString() ? `?${qs.toString()}` : ''}`;
104
- const body = await (0, api_client_1.cliApiJson)(path, { profile: args.profile });
105
- if (args.json) {
106
- process.stdout.write(JSON.stringify(body, null, 2) + '\n');
107
- return;
108
- }
109
- const rows = body.transfers || [];
110
- if (rows.length === 0) {
111
- (0, ui_1.info)('No transfers.');
112
- return;
113
- }
114
- process.stdout.write(['ID', 'SOURCE', 'TARGET', 'STATUS', 'INITIATED'].join('\t') + '\n');
115
- for (const t of rows) {
116
- process.stdout.write([
117
- t.id,
118
- t.sourceTenantId,
119
- t.targetTenantId,
120
- t.status,
121
- String(t.initiatedAt || '-'),
122
- ].join('\t') + '\n');
123
- }
124
- }
125
- async function identifyCmd(args) {
126
- if (!args.site || !args.userId) {
127
- (0, ui_1.error)('Usage: gurulu identity identify --site=<id> --user-id=<id> [--email=...] [--phone=...] [--traits=<json>]');
128
- process.exit(1);
129
- }
130
- let traits;
131
- if (args.traits) {
132
- try {
133
- traits = JSON.parse(args.traits);
134
- }
135
- catch {
136
- (0, ui_1.error)('--traits must be valid JSON');
137
- process.exit(1);
138
- }
139
- }
140
- const body = await (0, api_client_1.cliApiJson)('/api/cli/identity/identify', {
141
- profile: args.profile,
142
- method: 'POST',
143
- json: {
144
- siteId: args.site,
145
- userId: args.userId,
146
- email: args.email,
147
- phone: args.phone,
148
- traits,
149
- },
150
- });
151
- if (args.json) {
152
- process.stdout.write(JSON.stringify(body, null, 2) + '\n');
153
- return;
154
- }
155
- (0, ui_1.success)(`Identified ${args.userId}.`);
156
- if (body.canonicalPersonId) {
157
- process.stdout.write(` canonicalPersonId: ${body.canonicalPersonId}\n`);
158
- }
159
- }
160
- async function aliasCmd(args) {
161
- if (!args.site || !args.previousUserId || !args.newUserId) {
162
- (0, ui_1.error)('Usage: gurulu identity alias --site=<id> --previous-user-id=<anon> --new-user-id=<u123>');
163
- process.exit(1);
164
- }
165
- const body = await (0, api_client_1.cliApiJson)('/api/cli/identity/alias', {
166
- profile: args.profile,
167
- method: 'POST',
168
- json: {
169
- siteId: args.site,
170
- previousUserId: args.previousUserId,
171
- newUserId: args.newUserId,
172
- },
173
- });
174
- if (args.json) {
175
- process.stdout.write(JSON.stringify(body, null, 2) + '\n');
176
- return;
177
- }
178
- (0, ui_1.success)(`Aliased ${args.previousUserId} → ${args.newUserId}.`);
179
- }
180
- /**
181
- * `gurulu identity bulk --site=<id> --file=<path> [--format=csv|json]
182
- * [--resume-from=<offset>]`.
183
- *
184
- * Streams a CSV or JSON file to `/api/ingest/v1/identify/bulk` for
185
- * server-side fan-out. The endpoint chunks records server-side (500 per
186
- * tx); we only enforce a 10 000-record max here as a friendly preflight.
187
- *
188
- * `--resume-from` is forwarded as the `x-resume-from` header so a partial
189
- * import can pick up where it left off without reuploading the whole
190
- * file.
191
- */
192
- async function bulkCmd(args) {
193
- if (!args.site || !args.file) {
194
- (0, ui_1.error)('Usage: gurulu identity bulk --site=<id> --file=<path> [--format=csv|json] [--resume-from=<offset>]');
195
- process.exit(1);
196
- }
197
- const filePath = path.resolve(args.file);
198
- if (!fs.existsSync(filePath)) {
199
- (0, ui_1.error)(`File not found: ${filePath}`);
200
- process.exit(1);
201
- }
202
- // Auto-detect format from extension when --format is not supplied.
203
- let format = (args.format || '').toLowerCase();
204
- if (!format) {
205
- const ext = path.extname(filePath).slice(1).toLowerCase();
206
- format = ext === 'csv' ? 'csv' : 'json';
207
- }
208
- if (format !== 'csv' && format !== 'json') {
209
- (0, ui_1.error)('--format must be csv or json');
210
- process.exit(1);
211
- }
212
- const raw = fs.readFileSync(filePath, 'utf8');
213
- let body;
214
- let contentType;
215
- if (format === 'csv') {
216
- contentType = 'text/csv';
217
- body = raw;
218
- }
219
- else {
220
- contentType = 'application/json';
221
- // Allow files that are either { records: [...] } or a bare array.
222
- let parsed;
223
- try {
224
- parsed = JSON.parse(raw);
225
- }
226
- catch (err) {
227
- (0, ui_1.error)(`JSON file is invalid: ${err.message}`);
228
- process.exit(1);
229
- }
230
- const records = Array.isArray(parsed)
231
- ? parsed
232
- : Array.isArray(parsed?.records)
233
- ? parsed.records
234
- : null;
235
- if (!records) {
236
- (0, ui_1.error)('JSON file must be an array or { records: [...] }');
237
- process.exit(1);
238
- }
239
- body = JSON.stringify({ siteId: args.site, records });
240
- }
241
- const headers = { 'content-type': contentType };
242
- if (args.resumeFrom && args.resumeFrom > 0) {
243
- headers['x-resume-from'] = String(args.resumeFrom);
244
- }
245
- const url = `/api/ingest/v1/identify/bulk?site=${encodeURIComponent(args.site)}`;
246
- let parsedBody;
247
- try {
248
- const res = await (0, api_client_1.cliApi)(url, {
249
- profile: args.profile,
250
- method: 'POST',
251
- headers,
252
- body,
253
- });
254
- const text = await res.text();
255
- parsedBody = text ? JSON.parse(text) : {};
256
- if (!res.ok) {
257
- throw new api_client_1.CliApiError(res.status, parsedBody?.error || 'http_error', parsedBody?.message || `HTTP ${res.status}`, parsedBody);
258
- }
259
- }
260
- catch (err) {
261
- if (err instanceof api_client_1.CliApiError) {
262
- (0, ui_1.error)(`Bulk import failed: ${err.code} (${err.message})`);
263
- process.exit(1);
264
- }
265
- throw err;
266
- }
267
- if (args.json) {
268
- process.stdout.write(JSON.stringify(parsedBody, null, 2) + '\n');
269
- return;
270
- }
271
- (0, ui_1.success)(`Bulk identify done. processed=${parsedBody.processed ?? 0} succeeded=${parsedBody.succeeded ?? 0} failed=${parsedBody.failed ?? 0}`);
272
- if (parsedBody.errors && parsedBody.errors.length > 0) {
273
- const sample = parsedBody.errors.slice(0, 5);
274
- (0, ui_1.info)(`First ${sample.length} error(s):`);
275
- for (const e of sample) {
276
- process.stdout.write(` [${e.index}] ${e.message}\n`);
277
- }
278
- }
279
- }
280
- async function mergeCmd(args) {
281
- if (!args.site || !args.canonicalId || !args.duplicateId) {
282
- (0, ui_1.error)('Usage: gurulu identity merge --site=<id> --canonical-id=<winner> --duplicate-id=<loser>');
283
- process.exit(1);
284
- }
285
- const body = await (0, api_client_1.cliApiJson)('/api/cli/identity/merge', {
286
- profile: args.profile,
287
- method: 'POST',
288
- json: {
289
- siteId: args.site,
290
- canonicalId: args.canonicalId,
291
- duplicateId: args.duplicateId,
292
- },
293
- });
294
- if (args.json) {
295
- process.stdout.write(JSON.stringify(body, null, 2) + '\n');
296
- return;
297
- }
298
- (0, ui_1.success)(`Merged ${args.duplicateId} → ${args.canonicalId}.`);
299
- }
300
- async function cdcSourcesCmd(args) {
301
- if (args.sub && args.sub !== 'list') {
302
- (0, ui_1.error)(`Unknown identity cdc-sources sub: ${args.sub}`);
303
- process.exit(1);
304
- }
305
- const body = await (0, api_client_1.cliApiJson)('/api/cli/identity/cdc-sources', {
306
- profile: args.profile,
307
- });
308
- if (args.json) {
309
- process.stdout.write(JSON.stringify(body, null, 2) + '\n');
310
- return;
311
- }
312
- const rows = body.sources || [];
313
- if (rows.length === 0) {
314
- (0, ui_1.info)('No CDC sources configured.');
315
- return;
316
- }
317
- process.stdout.write(['ID', 'NAME', 'TYPE', 'TABLE', 'ACTIVE', 'LAST_POLL'].join('\t') + '\n');
318
- for (const s of rows) {
319
- process.stdout.write([
320
- s.id,
321
- s.name,
322
- s.sourceType,
323
- s.tableName,
324
- s.isActive ? 'yes' : 'no',
325
- String(s.lastPollAt || '-'),
326
- ].join('\t') + '\n');
327
- }
328
- }
@@ -1,215 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.initCommand = initCommand;
7
- const fs_1 = __importDefault(require("fs"));
8
- const path_1 = __importDefault(require("path"));
9
- const config_1 = require("../config");
10
- const api_client_1 = require("../api-client");
11
- const detect_1 = require("../frameworks/detect");
12
- const ui_1 = require("../utils/ui");
13
- async function initCommand(args) {
14
- const projectDir = process.cwd();
15
- if (args.json) {
16
- return initJSON(args, projectDir);
17
- }
18
- (0, ui_1.banner)();
19
- // Step 1: Detect framework
20
- let framework = args.framework || (0, detect_1.detectFramework)(projectDir);
21
- (0, ui_1.info)(`Detected framework: ${(0, ui_1.bold)((0, detect_1.getFrameworkDisplayName)(framework))}`);
22
- if (!args.framework && !args.noInteractive && framework === 'unknown') {
23
- console.log('');
24
- (0, ui_1.warn)('Could not auto-detect framework.');
25
- const frameworks = ['nextjs-app', 'nextjs-pages', 'react-vite', 'react-cra', 'vue3', 'nuxt3', 'svelte', 'sveltekit', 'astro', 'express', 'fastify', 'hono', 'nestjs', 'react-native', 'ios-swift', 'android-kotlin', 'flutter', 'html'];
26
- const idx = await (0, ui_1.promptSelect)(' Select your framework: ', frameworks.map(f => (0, detect_1.getFrameworkDisplayName)(f)));
27
- framework = frameworks[idx];
28
- (0, ui_1.info)(`Using: ${(0, ui_1.bold)((0, detect_1.getFrameworkDisplayName)(framework))}`);
29
- }
30
- // Step 2: Get site credentials
31
- let siteId = args.siteId || process.env.GURULU_SITE_ID;
32
- let token = args.token || process.env.GURULU_TOKEN;
33
- if (!siteId || !token) {
34
- let profile;
35
- try {
36
- profile = await (0, config_1.loadActiveProfile)({ profile: args.profile });
37
- }
38
- catch {
39
- profile = null;
40
- }
41
- if (profile && !siteId) {
42
- try {
43
- const data = await (0, api_client_1.cliApiJson)('/api/cli/sites', { preloadedProfile: profile });
44
- const sites = data.sites || [];
45
- if (sites.length === 0) {
46
- (0, ui_1.error)('No sites found. Create a site at https://gurulu.io first.');
47
- process.exit(1);
48
- }
49
- if (sites.length === 1 || args.noInteractive) {
50
- siteId = sites[0].id;
51
- (0, ui_1.info)(`Using site: ${(0, ui_1.bold)(sites[0].domain)}`);
52
- }
53
- else {
54
- console.log('');
55
- const idx = await (0, ui_1.promptSelect)(' Select a site: ', sites.map(s => `${s.domain} (${s.id})`));
56
- siteId = sites[idx].id;
57
- }
58
- // Fetch site details to get publishable key as token
59
- if (!token) {
60
- (0, ui_1.step)('Fetching site credentials...');
61
- const siteData = await (0, api_client_1.cliApiJson)(`/api/cli/sites/${encodeURIComponent(siteId)}`, { preloadedProfile: profile });
62
- token = siteData.site?.publishableKey || '';
63
- }
64
- }
65
- catch (err) {
66
- if (!args.noInteractive) {
67
- (0, ui_1.warn)('Could not fetch sites. Enter credentials manually.');
68
- if (!siteId)
69
- siteId = await (0, ui_1.prompt)(' Site ID: ');
70
- if (!token)
71
- token = await (0, ui_1.prompt)(' Site Token: ');
72
- }
73
- else {
74
- (0, ui_1.error)(`Failed to fetch credentials: ${err.message}`);
75
- process.exit(1);
76
- }
77
- }
78
- }
79
- else if (!args.noInteractive) {
80
- if (!profile) {
81
- (0, ui_1.warn)('Not authenticated. Run "gurulu login" first, or provide --site-id and --token.');
82
- console.log('');
83
- }
84
- if (!siteId)
85
- siteId = await (0, ui_1.prompt)(' Site ID: ');
86
- if (!token)
87
- token = await (0, ui_1.prompt)(' Site Token: ');
88
- }
89
- else {
90
- (0, ui_1.error)('Site ID and token required in non-interactive mode. Use --site-id and --token, or run "gurulu login" first.');
91
- process.exit(1);
92
- }
93
- }
94
- if (!siteId || !token) {
95
- (0, ui_1.error)('Site ID and token are required.');
96
- process.exit(1);
97
- }
98
- // Step 3: Generate setup code
99
- const snippet = (0, detect_1.getSetupSnippet)(framework, siteId, token);
100
- console.log('');
101
- if (args.dryRun) {
102
- (0, ui_1.info)('Dry run - showing what would be done:');
103
- console.log('');
104
- if (snippet.file) {
105
- console.log(` ${(0, ui_1.dim)('File:')} ${(0, ui_1.cyan)(snippet.file)}`);
106
- }
107
- console.log(` ${(0, ui_1.dim)('Instruction:')} ${snippet.instruction}`);
108
- console.log('');
109
- console.log((0, ui_1.dim)(' --- Code ---'));
110
- snippet.code.split('\n').forEach(line => {
111
- console.log(` ${(0, ui_1.dim)(line)}`);
112
- });
113
- console.log((0, ui_1.dim)(' --- End ---'));
114
- console.log('');
115
- if (framework !== 'html') {
116
- console.log(` ${(0, ui_1.dim)('.env.local would include:')}`);
117
- console.log(` NEXT_PUBLIC_GURULU_SITE_ID=${siteId}`);
118
- console.log(` NEXT_PUBLIC_GURULU_TOKEN=${token}`);
119
- }
120
- return;
121
- }
122
- // Step 4: Write setup code
123
- if (snippet.file) {
124
- const filePath = path_1.default.join(projectDir, snippet.file);
125
- const fileDir = path_1.default.dirname(filePath);
126
- if (fs_1.default.existsSync(filePath)) {
127
- (0, ui_1.warn)(`File already exists: ${snippet.file}`);
128
- if (!args.noInteractive) {
129
- const answer = await (0, ui_1.prompt)(' Overwrite? (y/N): ');
130
- if (answer.toLowerCase() !== 'y') {
131
- (0, ui_1.info)('Skipping file creation.');
132
- printNextSteps(snippet, siteId, token, framework);
133
- return;
134
- }
135
- }
136
- else {
137
- (0, ui_1.info)('Skipping existing file in non-interactive mode.');
138
- printNextSteps(snippet, siteId, token, framework);
139
- return;
140
- }
141
- }
142
- fs_1.default.mkdirSync(fileDir, { recursive: true });
143
- fs_1.default.writeFileSync(filePath, snippet.code);
144
- (0, ui_1.success)(`Created ${snippet.file}`);
145
- }
146
- // Step 5: Update .env.local (for frontend frameworks)
147
- const frontendFrameworks = ['nextjs-app', 'nextjs-pages', 'react-vite', 'react-cra', 'vue3', 'nuxt3', 'svelte', 'sveltekit', 'astro'];
148
- if (frontendFrameworks.includes(framework)) {
149
- const envFile = path_1.default.join(projectDir, '.env.local');
150
- const envPrefix = framework.startsWith('nuxt') ? 'NUXT_PUBLIC' : framework.startsWith('next') ? 'NEXT_PUBLIC' : 'VITE';
151
- const envLines = [
152
- `${envPrefix}_GURULU_SITE_ID=${siteId}`,
153
- `${envPrefix}_GURULU_TOKEN=${token}`,
154
- ];
155
- let existingEnv = '';
156
- if (fs_1.default.existsSync(envFile)) {
157
- existingEnv = fs_1.default.readFileSync(envFile, 'utf-8');
158
- }
159
- const newLines = envLines.filter(line => {
160
- const key = line.split('=')[0];
161
- return !existingEnv.includes(key);
162
- });
163
- if (newLines.length > 0) {
164
- const separator = existingEnv && !existingEnv.endsWith('\n') ? '\n' : '';
165
- const header = existingEnv ? '' : '# Gurulu.io Analytics\n';
166
- fs_1.default.appendFileSync(envFile, `${separator}${header}${newLines.join('\n')}\n`);
167
- (0, ui_1.success)('Updated .env.local with site credentials');
168
- }
169
- else {
170
- (0, ui_1.info)('.env.local already has Gurulu credentials');
171
- }
172
- }
173
- // Step 6: Print next steps
174
- printNextSteps(snippet, siteId, token, framework);
175
- }
176
- function printNextSteps(snippet, siteId, token, framework) {
177
- console.log('');
178
- console.log((0, ui_1.bold)(' Next steps:'));
179
- console.log('');
180
- (0, ui_1.step)(snippet.instruction);
181
- const mobileFrameworks = ['react-native', 'ios-swift', 'android-kotlin', 'flutter'];
182
- if (framework === 'html' || mobileFrameworks.includes(framework)) {
183
- console.log('');
184
- console.log((0, ui_1.dim)(' Copy this snippet:'));
185
- console.log('');
186
- snippet.code.split('\n').forEach(line => {
187
- console.log(` ${line}`);
188
- });
189
- }
190
- console.log('');
191
- (0, ui_1.step)(`Run ${(0, ui_1.cyan)('gurulu status')} to verify the connection`);
192
- (0, ui_1.step)(`Run ${(0, ui_1.cyan)('gurulu events')} to see detected events`);
193
- (0, ui_1.step)(`Visit ${(0, ui_1.cyan)('https://gurulu.io')} to view your dashboard`);
194
- console.log('');
195
- (0, ui_1.success)('Setup complete!');
196
- console.log('');
197
- }
198
- async function initJSON(args, projectDir) {
199
- const framework = args.framework || (0, detect_1.detectFramework)(projectDir);
200
- const siteId = args.siteId || process.env.GURULU_SITE_ID || '';
201
- const token = args.token || process.env.GURULU_TOKEN || '';
202
- const snippet = (0, detect_1.getSetupSnippet)(framework, siteId, token);
203
- const output = {
204
- framework,
205
- frameworkName: (0, detect_1.getFrameworkDisplayName)(framework),
206
- siteId,
207
- snippet: {
208
- file: snippet.file,
209
- code: snippet.code,
210
- instruction: snippet.instruction,
211
- },
212
- dryRun: !!args.dryRun,
213
- };
214
- console.log(JSON.stringify(output, null, 2));
215
- }
@@ -1,10 +0,0 @@
1
- /**
2
- * Phase 19.5 W2 B5 — `gurulu insights today|history|weekly`.
3
- */
4
- export interface InsightsArgs {
5
- action?: string;
6
- days?: number;
7
- json?: boolean;
8
- profile?: string;
9
- }
10
- export declare function insightsCommand(args: InsightsArgs): Promise<void>;
@@ -1,77 +0,0 @@
1
- "use strict";
2
- /**
3
- * Phase 19.5 W2 B5 — `gurulu insights today|history|weekly`.
4
- */
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.insightsCommand = insightsCommand;
7
- const api_client_1 = require("../api-client");
8
- const ui_1 = require("../utils/ui");
9
- async function insightsCommand(args) {
10
- const action = args.action || 'today';
11
- switch (action) {
12
- case 'today':
13
- return todayCmd(args);
14
- case 'history':
15
- case 'weekly':
16
- return historyCmd(args);
17
- default:
18
- (0, ui_1.error)(`Unknown insights action: ${action}`);
19
- (0, ui_1.info)('Usage: gurulu insights [today|history|weekly]');
20
- process.exit(1);
21
- }
22
- }
23
- function formatHighlight(h) {
24
- if (typeof h === 'string')
25
- return h;
26
- if (h && typeof h === 'object') {
27
- const o = h;
28
- const arrow = o.trend === 'up' ? '↑' : o.trend === 'down' ? '↓' : '→';
29
- const value = typeof o.value === 'number' ? o.value.toLocaleString() : String(o.value ?? '');
30
- const delta = typeof o.delta === 'number' ? ` (${o.delta >= 0 ? '+' : ''}${o.delta.toFixed(1)}% ${arrow})` : '';
31
- return `${o.label ?? 'metric'}: ${value}${delta}`;
32
- }
33
- return String(h);
34
- }
35
- async function todayCmd(args) {
36
- try {
37
- const body = await (0, api_client_1.cliApiJson)('/api/cli/insights', {
38
- profile: args.profile,
39
- });
40
- if (args.json) {
41
- process.stdout.write(JSON.stringify(body, null, 2) + '\n');
42
- return;
43
- }
44
- const i = body.insight;
45
- process.stdout.write(`Date: ${String(i.date).slice(0, 10)}\n`);
46
- process.stdout.write(`Summary: ${i.summary || '-'}\n`);
47
- if (Array.isArray(i.highlights)) {
48
- process.stdout.write(`Highlights:\n`);
49
- for (const h of i.highlights)
50
- process.stdout.write(` - ${formatHighlight(h)}\n`);
51
- }
52
- }
53
- catch (err) {
54
- if (err?.status === 404) {
55
- (0, ui_1.info)('No daily insight available yet.');
56
- return;
57
- }
58
- throw err;
59
- }
60
- }
61
- async function historyCmd(args) {
62
- const days = args.days ?? 7;
63
- const body = await (0, api_client_1.cliApiJson)(`/api/cli/insights/history?days=${days}`, { profile: args.profile });
64
- if (args.json) {
65
- process.stdout.write(JSON.stringify(body, null, 2) + '\n');
66
- return;
67
- }
68
- const rows = body.insights || [];
69
- if (rows.length === 0) {
70
- (0, ui_1.info)('No insights in the selected window.');
71
- return;
72
- }
73
- process.stdout.write(['DATE', 'SUMMARY'].join('\t') + '\n');
74
- for (const r of rows) {
75
- process.stdout.write([String(r.date).slice(0, 10), String(r.summary || '-').slice(0, 80)].join('\t') + '\n');
76
- }
77
- }