@gurulu/cli 0.4.6 → 1.0.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.
Files changed (180) 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 +25410 -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 +25 -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 +24985 -853
  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/package.json +40 -20
  28. package/bin/gurulu.js +0 -2
  29. package/dist/api-client.d.ts +0 -33
  30. package/dist/api-client.js +0 -175
  31. package/dist/commands/add-server.d.ts +0 -9
  32. package/dist/commands/add-server.js +0 -162
  33. package/dist/commands/alerts.d.ts +0 -27
  34. package/dist/commands/alerts.js +0 -309
  35. package/dist/commands/api-keys.d.ts +0 -20
  36. package/dist/commands/api-keys.js +0 -130
  37. package/dist/commands/attribution.d.ts +0 -22
  38. package/dist/commands/attribution.js +0 -111
  39. package/dist/commands/audiences.d.ts +0 -23
  40. package/dist/commands/audiences.js +0 -243
  41. package/dist/commands/audit.d.ts +0 -20
  42. package/dist/commands/audit.js +0 -130
  43. package/dist/commands/auth.js +0 -249
  44. package/dist/commands/chat.d.ts +0 -18
  45. package/dist/commands/chat.js +0 -117
  46. package/dist/commands/config.d.ts +0 -10
  47. package/dist/commands/config.js +0 -92
  48. package/dist/commands/consent.d.ts +0 -27
  49. package/dist/commands/consent.js +0 -233
  50. package/dist/commands/conversion-paths.d.ts +0 -19
  51. package/dist/commands/conversion-paths.js +0 -55
  52. package/dist/commands/db.d.ts +0 -25
  53. package/dist/commands/db.js +0 -330
  54. package/dist/commands/destinations.d.ts +0 -20
  55. package/dist/commands/destinations.js +0 -191
  56. package/dist/commands/doctor.js +0 -360
  57. package/dist/commands/errors.d.ts +0 -27
  58. package/dist/commands/errors.js +0 -121
  59. package/dist/commands/events.d.ts +0 -33
  60. package/dist/commands/events.js +0 -349
  61. package/dist/commands/experiments.d.ts +0 -22
  62. package/dist/commands/experiments.js +0 -264
  63. package/dist/commands/funnels.d.ts +0 -17
  64. package/dist/commands/funnels.js +0 -203
  65. package/dist/commands/goals.d.ts +0 -18
  66. package/dist/commands/goals.js +0 -214
  67. package/dist/commands/heatmap.d.ts +0 -27
  68. package/dist/commands/heatmap.js +0 -112
  69. package/dist/commands/identity.d.ts +0 -29
  70. package/dist/commands/identity.js +0 -328
  71. package/dist/commands/init.js +0 -215
  72. package/dist/commands/insights.d.ts +0 -10
  73. package/dist/commands/insights.js +0 -65
  74. package/dist/commands/install.d.ts +0 -259
  75. package/dist/commands/install.js +0 -1590
  76. package/dist/commands/login.d.ts +0 -20
  77. package/dist/commands/login.js +0 -170
  78. package/dist/commands/logout.d.ts +0 -10
  79. package/dist/commands/logout.js +0 -41
  80. package/dist/commands/playground.d.ts +0 -11
  81. package/dist/commands/playground.js +0 -47
  82. package/dist/commands/releases.d.ts +0 -17
  83. package/dist/commands/releases.js +0 -54
  84. package/dist/commands/replay.d.ts +0 -18
  85. package/dist/commands/replay.js +0 -64
  86. package/dist/commands/secrets.d.ts +0 -19
  87. package/dist/commands/secrets.js +0 -145
  88. package/dist/commands/sites.d.ts +0 -18
  89. package/dist/commands/sites.js +0 -139
  90. package/dist/commands/skad.d.ts +0 -18
  91. package/dist/commands/skad.js +0 -53
  92. package/dist/commands/sourcemap.d.ts +0 -33
  93. package/dist/commands/sourcemap.js +0 -204
  94. package/dist/commands/status.d.ts +0 -7
  95. package/dist/commands/status.js +0 -136
  96. package/dist/commands/upgrade.d.ts +0 -21
  97. package/dist/commands/upgrade.js +0 -183
  98. package/dist/commands/warehouse.d.ts +0 -20
  99. package/dist/commands/warehouse.js +0 -65
  100. package/dist/commands/warehouses.d.ts +0 -17
  101. package/dist/commands/warehouses.js +0 -182
  102. package/dist/commands/watch.d.ts +0 -45
  103. package/dist/commands/watch.js +0 -258
  104. package/dist/commands/whoami.d.ts +0 -9
  105. package/dist/commands/whoami.js +0 -50
  106. package/dist/config.d.ts +0 -75
  107. package/dist/config.js +0 -329
  108. package/dist/frameworks/detect.d.ts +0 -8
  109. package/dist/frameworks/detect.js +0 -444
  110. package/dist/install-intent-proposal.d.ts +0 -99
  111. package/dist/install-intent-proposal.js +0 -202
  112. package/dist/utils/api.d.ts +0 -20
  113. package/dist/utils/api.js +0 -47
  114. package/dist/utils/config.d.ts +0 -13
  115. package/dist/utils/config.js +0 -30
  116. package/dist/utils/confirm.d.ts +0 -17
  117. package/dist/utils/confirm.js +0 -40
  118. package/dist/utils/dry-run.d.ts +0 -20
  119. package/dist/utils/dry-run.js +0 -67
  120. package/dist/utils/from-file.d.ts +0 -9
  121. package/dist/utils/from-file.js +0 -72
  122. package/dist/utils/redact.d.ts +0 -14
  123. package/dist/utils/redact.js +0 -48
  124. package/dist/utils/ui.d.ts +0 -14
  125. package/dist/utils/ui.js +0 -59
  126. package/scripts/.gitkeep +0 -0
  127. package/scripts/README-gurulu-agentic-install.md +0 -114
  128. package/scripts/README-gurulu-scan.md +0 -98
  129. package/scripts/audit-cli-scopes.mjs +0 -204
  130. package/scripts/backfill-tenant-id.mjs +0 -172
  131. package/scripts/backfill-tenant-links.ts +0 -252
  132. package/scripts/backup-clickhouse.sh +0 -27
  133. package/scripts/backup-postgres.sh +0 -19
  134. package/scripts/bootstrap-runtime-schema.mjs +0 -87
  135. package/scripts/bootstrap-stripe.mjs +0 -158
  136. package/scripts/gurulu-agentic-install.lib.cjs +0 -762
  137. package/scripts/gurulu-agentic-install.mjs +0 -623
  138. package/scripts/gurulu-scan.lib.cjs +0 -1509
  139. package/scripts/gurulu-scan.mjs +0 -91
  140. package/scripts/gurulu-verify-install.lib.cjs +0 -334
  141. package/scripts/gurulu-verify-install.mjs +0 -59
  142. package/scripts/init-ssl.sh +0 -26
  143. package/scripts/migrate-flow-graph-enums.sh +0 -86
  144. package/scripts/monitor-disk.sh +0 -24
  145. package/scripts/patches/astro.patch.cjs +0 -74
  146. package/scripts/patches/auto-instrument/ast-helper.cjs +0 -480
  147. package/scripts/patches/auto-instrument/astro.cjs +0 -273
  148. package/scripts/patches/auto-instrument/express.cjs +0 -383
  149. package/scripts/patches/auto-instrument/fastify.cjs +0 -262
  150. package/scripts/patches/auto-instrument/hono.cjs +0 -392
  151. package/scripts/patches/auto-instrument/index.cjs +0 -80
  152. package/scripts/patches/auto-instrument/nestjs.cjs +0 -286
  153. package/scripts/patches/auto-instrument/nextjs-app-router.cjs +0 -345
  154. package/scripts/patches/auto-instrument/nextjs-pages.cjs +0 -361
  155. package/scripts/patches/auto-instrument/remix.cjs +0 -168
  156. package/scripts/patches/auto-instrument/sdk-helper-map.cjs +0 -241
  157. package/scripts/patches/auto-instrument/singleton-helper.cjs +0 -193
  158. package/scripts/patches/auto-instrument/sveltekit.cjs +0 -161
  159. package/scripts/patches/auto-instrument/vite-react.cjs +0 -37
  160. package/scripts/patches/auto-instrument/vue.cjs +0 -196
  161. package/scripts/patches/express.patch.cjs +0 -99
  162. package/scripts/patches/fastify.patch.cjs +0 -108
  163. package/scripts/patches/index.cjs +0 -300
  164. package/scripts/patches/nestjs.patch.cjs +0 -112
  165. package/scripts/patches/nextjs-app-router.patch.cjs +0 -97
  166. package/scripts/patches/nextjs-pages.patch.cjs +0 -97
  167. package/scripts/patches/remix.patch.cjs +0 -75
  168. package/scripts/patches/sveltekit.patch.cjs +0 -72
  169. package/scripts/patches/vite-react.patch.cjs +0 -73
  170. package/scripts/patches/vue.patch.cjs +0 -82
  171. package/scripts/renew-ssl.sh +0 -14
  172. package/scripts/resolve-migration.sh +0 -23
  173. package/scripts/seed-cli-dev-keys.mjs +0 -130
  174. package/scripts/seed-test-data.mjs +0 -391
  175. package/scripts/spike-browserless.ts +0 -65
  176. package/scripts/tenant-pivot-consistency-check.mjs +0 -205
  177. package/scripts/tenant-pivot-phase-3-cleanup.lib.cjs +0 -258
  178. package/scripts/tenant-pivot-phase-3-cleanup.mjs +0 -98
  179. package/scripts/test-identity-resolution.ts +0 -804
  180. 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,65 +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
- async function todayCmd(args) {
24
- try {
25
- const body = await (0, api_client_1.cliApiJson)('/api/cli/insights', {
26
- profile: args.profile,
27
- });
28
- if (args.json) {
29
- process.stdout.write(JSON.stringify(body, null, 2) + '\n');
30
- return;
31
- }
32
- const i = body.insight;
33
- process.stdout.write(`Date: ${String(i.date).slice(0, 10)}\n`);
34
- process.stdout.write(`Summary: ${i.summary || '-'}\n`);
35
- if (Array.isArray(i.highlights)) {
36
- process.stdout.write(`Highlights:\n`);
37
- for (const h of i.highlights)
38
- process.stdout.write(` - ${h}\n`);
39
- }
40
- }
41
- catch (err) {
42
- if (err?.status === 404) {
43
- (0, ui_1.info)('No daily insight available yet.');
44
- return;
45
- }
46
- throw err;
47
- }
48
- }
49
- async function historyCmd(args) {
50
- const days = args.days ?? 7;
51
- const body = await (0, api_client_1.cliApiJson)(`/api/cli/insights/history?days=${days}`, { profile: args.profile });
52
- if (args.json) {
53
- process.stdout.write(JSON.stringify(body, null, 2) + '\n');
54
- return;
55
- }
56
- const rows = body.insights || [];
57
- if (rows.length === 0) {
58
- (0, ui_1.info)('No insights in the selected window.');
59
- return;
60
- }
61
- process.stdout.write(['DATE', 'SUMMARY'].join('\t') + '\n');
62
- for (const r of rows) {
63
- process.stdout.write([String(r.date).slice(0, 10), String(r.summary || '-').slice(0, 80)].join('\t') + '\n');
64
- }
65
- }