@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.
- package/LICENSE +92 -0
- package/README.md +35 -106
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +25751 -0
- package/dist/commands/auth.d.ts +23 -20
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/doctor.d.ts +20 -6
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/init.d.ts +33 -11
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/pull.d.ts +13 -0
- package/dist/commands/pull.d.ts.map +1 -0
- package/dist/commands/push.d.ts +40 -0
- package/dist/commands/push.d.ts.map +1 -0
- package/dist/commands/validate.d.ts +36 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25326 -876
- package/dist/lib/api.d.ts +139 -0
- package/dist/lib/api.d.ts.map +1 -0
- package/dist/lib/codegen.d.ts +4 -0
- package/dist/lib/codegen.d.ts.map +1 -0
- package/dist/lib/config.d.ts +43 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/detect.d.ts +27 -0
- package/dist/lib/detect.d.ts.map +1 -0
- package/dist/lib/detect.js +106 -0
- package/dist/lib/exec-install.d.ts +21 -0
- package/dist/lib/exec-install.d.ts.map +1 -0
- package/dist/lib/install-plan.d.ts +25 -0
- package/dist/lib/install-plan.d.ts.map +1 -0
- package/dist/lib/install-plan.js +161 -0
- package/package.json +51 -20
- package/bin/gurulu.js +0 -2
- package/dist/api-client.d.ts +0 -33
- package/dist/api-client.js +0 -175
- package/dist/commands/add-server.d.ts +0 -9
- package/dist/commands/add-server.js +0 -162
- package/dist/commands/alerts.d.ts +0 -27
- package/dist/commands/alerts.js +0 -309
- package/dist/commands/api-keys.d.ts +0 -20
- package/dist/commands/api-keys.js +0 -130
- package/dist/commands/attribution.d.ts +0 -22
- package/dist/commands/attribution.js +0 -111
- package/dist/commands/audiences.d.ts +0 -23
- package/dist/commands/audiences.js +0 -243
- package/dist/commands/audit.d.ts +0 -20
- package/dist/commands/audit.js +0 -130
- package/dist/commands/auth.js +0 -249
- package/dist/commands/chat.d.ts +0 -19
- package/dist/commands/chat.js +0 -118
- package/dist/commands/config.d.ts +0 -10
- package/dist/commands/config.js +0 -92
- package/dist/commands/consent.d.ts +0 -27
- package/dist/commands/consent.js +0 -233
- package/dist/commands/conversion-paths.d.ts +0 -19
- package/dist/commands/conversion-paths.js +0 -55
- package/dist/commands/db.d.ts +0 -25
- package/dist/commands/db.js +0 -330
- package/dist/commands/destinations.d.ts +0 -20
- package/dist/commands/destinations.js +0 -191
- package/dist/commands/doctor.js +0 -360
- package/dist/commands/errors.d.ts +0 -27
- package/dist/commands/errors.js +0 -121
- package/dist/commands/events.d.ts +0 -33
- package/dist/commands/events.js +0 -371
- package/dist/commands/experiments.d.ts +0 -22
- package/dist/commands/experiments.js +0 -264
- package/dist/commands/funnels.d.ts +0 -17
- package/dist/commands/funnels.js +0 -203
- package/dist/commands/goals.d.ts +0 -18
- package/dist/commands/goals.js +0 -214
- package/dist/commands/heatmap.d.ts +0 -27
- package/dist/commands/heatmap.js +0 -112
- package/dist/commands/identity.d.ts +0 -29
- package/dist/commands/identity.js +0 -328
- package/dist/commands/init.js +0 -215
- package/dist/commands/insights.d.ts +0 -10
- package/dist/commands/insights.js +0 -77
- package/dist/commands/install.d.ts +0 -259
- package/dist/commands/install.js +0 -1590
- package/dist/commands/login.d.ts +0 -20
- package/dist/commands/login.js +0 -170
- package/dist/commands/logout.d.ts +0 -10
- package/dist/commands/logout.js +0 -41
- package/dist/commands/playground.d.ts +0 -11
- package/dist/commands/playground.js +0 -47
- package/dist/commands/releases.d.ts +0 -17
- package/dist/commands/releases.js +0 -54
- package/dist/commands/replay.d.ts +0 -18
- package/dist/commands/replay.js +0 -64
- package/dist/commands/secrets.d.ts +0 -19
- package/dist/commands/secrets.js +0 -145
- package/dist/commands/setup.d.ts +0 -21
- package/dist/commands/setup.js +0 -67
- package/dist/commands/sites.d.ts +0 -18
- package/dist/commands/sites.js +0 -139
- package/dist/commands/skad.d.ts +0 -18
- package/dist/commands/skad.js +0 -53
- package/dist/commands/sourcemap.d.ts +0 -33
- package/dist/commands/sourcemap.js +0 -204
- package/dist/commands/status.d.ts +0 -7
- package/dist/commands/status.js +0 -136
- package/dist/commands/upgrade.d.ts +0 -21
- package/dist/commands/upgrade.js +0 -183
- package/dist/commands/warehouse.d.ts +0 -20
- package/dist/commands/warehouse.js +0 -65
- package/dist/commands/warehouses.d.ts +0 -17
- package/dist/commands/warehouses.js +0 -182
- package/dist/commands/watch.d.ts +0 -45
- package/dist/commands/watch.js +0 -258
- package/dist/commands/whoami.d.ts +0 -9
- package/dist/commands/whoami.js +0 -50
- package/dist/config.d.ts +0 -75
- package/dist/config.js +0 -329
- package/dist/frameworks/detect.d.ts +0 -8
- package/dist/frameworks/detect.js +0 -458
- package/dist/install-intent-proposal.d.ts +0 -99
- package/dist/install-intent-proposal.js +0 -202
- package/dist/utils/api.d.ts +0 -20
- package/dist/utils/api.js +0 -47
- package/dist/utils/config.d.ts +0 -13
- package/dist/utils/config.js +0 -30
- package/dist/utils/confirm.d.ts +0 -17
- package/dist/utils/confirm.js +0 -40
- package/dist/utils/dry-run.d.ts +0 -20
- package/dist/utils/dry-run.js +0 -67
- package/dist/utils/from-file.d.ts +0 -9
- package/dist/utils/from-file.js +0 -72
- package/dist/utils/redact.d.ts +0 -14
- package/dist/utils/redact.js +0 -48
- package/dist/utils/ui.d.ts +0 -14
- package/dist/utils/ui.js +0 -59
- package/scripts/.gitkeep +0 -0
- package/scripts/README-gurulu-agentic-install.md +0 -114
- package/scripts/README-gurulu-scan.md +0 -98
- package/scripts/audit-cli-scopes.mjs +0 -204
- package/scripts/backfill-tenant-id.mjs +0 -172
- package/scripts/backfill-tenant-links.ts +0 -252
- package/scripts/backup-clickhouse.sh +0 -27
- package/scripts/backup-postgres.sh +0 -19
- package/scripts/bootstrap-runtime-schema.mjs +0 -87
- package/scripts/bootstrap-stripe.mjs +0 -158
- package/scripts/gurulu-agentic-install.lib.cjs +0 -762
- package/scripts/gurulu-agentic-install.mjs +0 -623
- package/scripts/gurulu-scan.lib.cjs +0 -1509
- package/scripts/gurulu-scan.mjs +0 -91
- package/scripts/gurulu-verify-install.lib.cjs +0 -334
- package/scripts/gurulu-verify-install.mjs +0 -59
- package/scripts/init-ssl.sh +0 -26
- package/scripts/migrate-flow-graph-enums.sh +0 -86
- package/scripts/monitor-disk.sh +0 -24
- package/scripts/patches/astro.patch.cjs +0 -74
- package/scripts/patches/auto-instrument/ast-helper.cjs +0 -480
- package/scripts/patches/auto-instrument/astro.cjs +0 -273
- package/scripts/patches/auto-instrument/express.cjs +0 -383
- package/scripts/patches/auto-instrument/fastify.cjs +0 -262
- package/scripts/patches/auto-instrument/hono.cjs +0 -392
- package/scripts/patches/auto-instrument/index.cjs +0 -80
- package/scripts/patches/auto-instrument/nestjs.cjs +0 -286
- package/scripts/patches/auto-instrument/nextjs-app-router.cjs +0 -345
- package/scripts/patches/auto-instrument/nextjs-pages.cjs +0 -361
- package/scripts/patches/auto-instrument/remix.cjs +0 -168
- package/scripts/patches/auto-instrument/sdk-helper-map.cjs +0 -241
- package/scripts/patches/auto-instrument/singleton-helper.cjs +0 -193
- package/scripts/patches/auto-instrument/sveltekit.cjs +0 -161
- package/scripts/patches/auto-instrument/vite-react.cjs +0 -37
- package/scripts/patches/auto-instrument/vue.cjs +0 -196
- package/scripts/patches/express.patch.cjs +0 -99
- package/scripts/patches/fastify.patch.cjs +0 -108
- package/scripts/patches/index.cjs +0 -300
- package/scripts/patches/nestjs.patch.cjs +0 -112
- package/scripts/patches/nextjs-app-router.patch.cjs +0 -97
- package/scripts/patches/nextjs-pages.patch.cjs +0 -97
- package/scripts/patches/remix.patch.cjs +0 -75
- package/scripts/patches/sveltekit.patch.cjs +0 -72
- package/scripts/patches/vite-react.patch.cjs +0 -73
- package/scripts/patches/vue.patch.cjs +0 -82
- package/scripts/renew-ssl.sh +0 -14
- package/scripts/resolve-migration.sh +0 -23
- package/scripts/seed-cli-dev-keys.mjs +0 -130
- package/scripts/seed-test-data.mjs +0 -391
- package/scripts/spike-browserless.ts +0 -65
- package/scripts/tenant-pivot-consistency-check.mjs +0 -205
- package/scripts/tenant-pivot-phase-3-cleanup.lib.cjs +0 -258
- package/scripts/tenant-pivot-phase-3-cleanup.mjs +0 -98
- package/scripts/test-identity-resolution.ts +0 -804
- package/scripts/validate-gurulu-schemas.mjs +0 -79
package/dist/commands/doctor.js
DELETED
|
@@ -1,360 +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.doctorCommand = doctorCommand;
|
|
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 doctorCommand(args) {
|
|
14
|
-
let profile;
|
|
15
|
-
try {
|
|
16
|
-
profile = await (0, config_1.loadActiveProfile)({ profile: args.profile });
|
|
17
|
-
}
|
|
18
|
-
catch {
|
|
19
|
-
profile = null;
|
|
20
|
-
}
|
|
21
|
-
const siteId = args.site;
|
|
22
|
-
const projectDir = process.cwd();
|
|
23
|
-
const checks = [];
|
|
24
|
-
// 1. Framework detection
|
|
25
|
-
const framework = (0, detect_1.detectFramework)(projectDir);
|
|
26
|
-
// If the user explicitly passed --site, the cwd-derived checks should not
|
|
27
|
-
// imply that the *production site* is broken — they're informational only.
|
|
28
|
-
const isLocalProjectDetected = framework !== 'unknown';
|
|
29
|
-
checks.push({
|
|
30
|
-
name: 'Framework Detection',
|
|
31
|
-
status: framework !== 'unknown' ? 'pass' : 'warn',
|
|
32
|
-
message: framework !== 'unknown'
|
|
33
|
-
? `Detected ${(0, detect_1.getFrameworkDisplayName)(framework)}`
|
|
34
|
-
: 'Could not detect framework',
|
|
35
|
-
fix: framework === 'unknown' ? 'Run "gurulu init --framework <name>" to specify manually' : undefined,
|
|
36
|
-
section: 'local',
|
|
37
|
-
});
|
|
38
|
-
// 2. SDK installed
|
|
39
|
-
const pkgPath = path_1.default.join(projectDir, 'package.json');
|
|
40
|
-
let hasWebSDK = false;
|
|
41
|
-
let hasNodeSDK = false;
|
|
42
|
-
let hasReactNativeSDK = false;
|
|
43
|
-
if (fs_1.default.existsSync(pkgPath)) {
|
|
44
|
-
const pkg = JSON.parse(fs_1.default.readFileSync(pkgPath, 'utf-8'));
|
|
45
|
-
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
46
|
-
hasWebSDK = !!allDeps['@gurulu/web-sdk'];
|
|
47
|
-
hasNodeSDK = !!allDeps['@gurulu/node'];
|
|
48
|
-
hasReactNativeSDK = !!allDeps['@gurulu/react-native'];
|
|
49
|
-
}
|
|
50
|
-
// Mobile SDK detection
|
|
51
|
-
let hasFlutterSDK = false;
|
|
52
|
-
const pubspecPath = path_1.default.join(projectDir, 'pubspec.yaml');
|
|
53
|
-
if (fs_1.default.existsSync(pubspecPath)) {
|
|
54
|
-
const pubspec = fs_1.default.readFileSync(pubspecPath, 'utf-8');
|
|
55
|
-
hasFlutterSDK = pubspec.includes('gurulu_flutter');
|
|
56
|
-
}
|
|
57
|
-
let hasIOSSDK = false;
|
|
58
|
-
const swiftPkgPath = path_1.default.join(projectDir, 'Package.swift');
|
|
59
|
-
if (fs_1.default.existsSync(swiftPkgPath)) {
|
|
60
|
-
const swiftPkg = fs_1.default.readFileSync(swiftPkgPath, 'utf-8');
|
|
61
|
-
hasIOSSDK = swiftPkg.includes('gurulu-ios-sdk');
|
|
62
|
-
}
|
|
63
|
-
let hasAndroidSDK = false;
|
|
64
|
-
const gradleKtsPath = path_1.default.join(projectDir, 'build.gradle.kts');
|
|
65
|
-
const gradlePath = path_1.default.join(projectDir, 'build.gradle');
|
|
66
|
-
for (const gPath of [gradleKtsPath, gradlePath]) {
|
|
67
|
-
if (fs_1.default.existsSync(gPath)) {
|
|
68
|
-
const gradle = fs_1.default.readFileSync(gPath, 'utf-8');
|
|
69
|
-
if (gradle.includes('gurulu') || gradle.includes('jitpack')) {
|
|
70
|
-
hasAndroidSDK = true;
|
|
71
|
-
break;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
const hasMobileSDK = hasReactNativeSDK || hasFlutterSDK || hasIOSSDK || hasAndroidSDK;
|
|
76
|
-
const setupFiles = findSetupFiles(projectDir);
|
|
77
|
-
const hasSetup = setupFiles.length > 0 || hasWebSDK || hasMobileSDK;
|
|
78
|
-
const sdkLabel = hasWebSDK ? 'Web SDK installed via npm'
|
|
79
|
-
: hasReactNativeSDK ? 'React Native SDK installed via npm'
|
|
80
|
-
: hasFlutterSDK ? 'Flutter SDK found in pubspec.yaml'
|
|
81
|
-
: hasIOSSDK ? 'iOS SDK found in Package.swift'
|
|
82
|
-
: hasAndroidSDK ? 'Android SDK found in build.gradle'
|
|
83
|
-
: setupFiles.length > 0 ? `Setup file found: ${setupFiles[0]}`
|
|
84
|
-
: 'No client SDK detected';
|
|
85
|
-
// When --site was passed but cwd is not a Gurulu project, downgrade local
|
|
86
|
-
// SDK failures to "skip" so they don't masquerade as production-site issues.
|
|
87
|
-
const localChecksAreInformational = !!siteId && !isLocalProjectDetected;
|
|
88
|
-
checks.push({
|
|
89
|
-
name: 'Client SDK',
|
|
90
|
-
status: hasSetup ? 'pass' : localChecksAreInformational ? 'skip' : 'fail',
|
|
91
|
-
message: hasSetup
|
|
92
|
-
? sdkLabel
|
|
93
|
-
: localChecksAreInformational
|
|
94
|
-
? 'No client SDK detected in this directory (informational — site checks below)'
|
|
95
|
-
: sdkLabel,
|
|
96
|
-
fix: !hasSetup && !localChecksAreInformational
|
|
97
|
-
? 'Run "gurulu init" to set up analytics'
|
|
98
|
-
: undefined,
|
|
99
|
-
section: 'local',
|
|
100
|
-
});
|
|
101
|
-
// 3. Server SDK
|
|
102
|
-
checks.push({
|
|
103
|
-
name: 'Server SDK',
|
|
104
|
-
status: hasNodeSDK ? 'pass' : localChecksAreInformational ? 'skip' : 'warn',
|
|
105
|
-
message: hasNodeSDK
|
|
106
|
-
? '@gurulu/node installed'
|
|
107
|
-
: localChecksAreInformational
|
|
108
|
-
? 'Server SDK check skipped (no local project detected)'
|
|
109
|
-
: 'Server SDK not installed (optional)',
|
|
110
|
-
fix: !hasNodeSDK && !localChecksAreInformational
|
|
111
|
-
? 'Run "gurulu add-server" for server-side tracking'
|
|
112
|
-
: undefined,
|
|
113
|
-
section: 'local',
|
|
114
|
-
});
|
|
115
|
-
// 4. Site ID configured
|
|
116
|
-
checks.push({
|
|
117
|
-
name: 'Site ID',
|
|
118
|
-
status: siteId ? 'pass' : 'fail',
|
|
119
|
-
message: siteId ? `Site ID: ${siteId}` : 'No site ID configured',
|
|
120
|
-
fix: !siteId ? 'Run "gurulu login" to authenticate and select a site' : undefined,
|
|
121
|
-
});
|
|
122
|
-
// 5. Authentication
|
|
123
|
-
checks.push({
|
|
124
|
-
name: 'Authentication',
|
|
125
|
-
status: profile ? 'pass' : 'fail',
|
|
126
|
-
message: profile ? 'Authenticated' : 'Not authenticated',
|
|
127
|
-
fix: !profile ? 'Run "gurulu login" with your Personal API Key' : undefined,
|
|
128
|
-
});
|
|
129
|
-
// 6. Token validation (if we have a profile and siteId)
|
|
130
|
-
if (profile && siteId) {
|
|
131
|
-
try {
|
|
132
|
-
const data = await (0, api_client_1.cliApiJson)(`/api/cli/sites/${encodeURIComponent(siteId)}`, { preloadedProfile: profile });
|
|
133
|
-
const hasToken = !!data.site?.publishableKey;
|
|
134
|
-
checks.push({
|
|
135
|
-
name: 'Token Valid',
|
|
136
|
-
status: hasToken ? 'pass' : 'fail',
|
|
137
|
-
message: hasToken ? 'Site token is valid' : 'Token could not be verified',
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
catch (err) {
|
|
141
|
-
checks.push({
|
|
142
|
-
name: 'Token Valid',
|
|
143
|
-
status: 'fail',
|
|
144
|
-
message: `Token validation failed: ${err.message}`,
|
|
145
|
-
fix: 'Check your API key and site ID, or run "gurulu login" again',
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
else {
|
|
150
|
-
checks.push({
|
|
151
|
-
name: 'Token Valid',
|
|
152
|
-
status: 'skip',
|
|
153
|
-
message: 'Skipped (authentication required)',
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
// 7. Ingest connection + 8. Events flowing — via /api/cli/sites/:id/health
|
|
157
|
-
if (profile && siteId) {
|
|
158
|
-
try {
|
|
159
|
-
const health = await (0, api_client_1.cliApiJson)(`/api/cli/sites/${encodeURIComponent(siteId)}/health`, {
|
|
160
|
-
preloadedProfile: profile,
|
|
161
|
-
});
|
|
162
|
-
checks.push({
|
|
163
|
-
name: 'Ingest Connection',
|
|
164
|
-
status: health.checks.ingest === 'ok' ? 'pass' : 'fail',
|
|
165
|
-
message: health.checks.ingest === 'ok'
|
|
166
|
-
? 'Ingest endpoint is healthy'
|
|
167
|
-
: 'Ingest check failed — site may be archived or missing a valid token',
|
|
168
|
-
fix: health.checks.ingest !== 'ok'
|
|
169
|
-
? 'Verify site exists and has a valid publishable key'
|
|
170
|
-
: undefined,
|
|
171
|
-
});
|
|
172
|
-
const chOk = health.checks.clickhouse === 'ok';
|
|
173
|
-
const pgOk = health.checks.postgres === 'ok';
|
|
174
|
-
const allOk = chOk && pgOk;
|
|
175
|
-
checks.push({
|
|
176
|
-
name: 'Events Flowing',
|
|
177
|
-
status: allOk ? 'pass' : chOk || pgOk ? 'warn' : 'fail',
|
|
178
|
-
message: allOk
|
|
179
|
-
? 'ClickHouse and Postgres are reachable'
|
|
180
|
-
: `Backend health: postgres=${health.checks.postgres}, clickhouse=${health.checks.clickhouse}`,
|
|
181
|
-
fix: !allOk ? 'Check server logs or contact support' : undefined,
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
catch (err) {
|
|
185
|
-
checks.push({
|
|
186
|
-
name: 'Ingest Connection',
|
|
187
|
-
status: 'fail',
|
|
188
|
-
message: `Health check failed: ${err.message}`,
|
|
189
|
-
fix: 'Check your API key and site ID, or run "gurulu login" again',
|
|
190
|
-
});
|
|
191
|
-
checks.push({
|
|
192
|
-
name: 'Events Flowing',
|
|
193
|
-
status: 'skip',
|
|
194
|
-
message: 'Skipped (health check unavailable)',
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
else if (profile && !siteId) {
|
|
199
|
-
// Try to resolve a site automatically
|
|
200
|
-
try {
|
|
201
|
-
const sitesData = await (0, api_client_1.cliApiJson)('/api/cli/sites', { preloadedProfile: profile });
|
|
202
|
-
if (sitesData.sites?.length) {
|
|
203
|
-
const resolvedId = sitesData.sites[0].id;
|
|
204
|
-
const health = await (0, api_client_1.cliApiJson)(`/api/cli/sites/${encodeURIComponent(resolvedId)}/health`, {
|
|
205
|
-
preloadedProfile: profile,
|
|
206
|
-
});
|
|
207
|
-
checks.push({
|
|
208
|
-
name: 'Ingest Connection',
|
|
209
|
-
status: health.checks.ingest === 'ok' ? 'pass' : 'fail',
|
|
210
|
-
message: health.checks.ingest === 'ok'
|
|
211
|
-
? `Ingest healthy (auto-resolved site ${resolvedId})`
|
|
212
|
-
: 'Ingest check failed',
|
|
213
|
-
fix: health.checks.ingest !== 'ok'
|
|
214
|
-
? 'Verify site exists and has a valid publishable key'
|
|
215
|
-
: undefined,
|
|
216
|
-
});
|
|
217
|
-
const chOk = health.checks.clickhouse === 'ok';
|
|
218
|
-
const pgOk = health.checks.postgres === 'ok';
|
|
219
|
-
const allOk = chOk && pgOk;
|
|
220
|
-
checks.push({
|
|
221
|
-
name: 'Events Flowing',
|
|
222
|
-
status: allOk ? 'pass' : chOk || pgOk ? 'warn' : 'fail',
|
|
223
|
-
message: allOk
|
|
224
|
-
? 'ClickHouse and Postgres are reachable'
|
|
225
|
-
: `Backend health: postgres=${health.checks.postgres}, clickhouse=${health.checks.clickhouse}`,
|
|
226
|
-
fix: !allOk ? 'Check server logs or contact support' : undefined,
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
else {
|
|
230
|
-
checks.push({
|
|
231
|
-
name: 'Ingest Connection',
|
|
232
|
-
status: 'skip',
|
|
233
|
-
message: 'No sites found — create one with "gurulu init"',
|
|
234
|
-
});
|
|
235
|
-
checks.push({
|
|
236
|
-
name: 'Events Flowing',
|
|
237
|
-
status: 'skip',
|
|
238
|
-
message: 'Skipped (no sites)',
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
catch {
|
|
243
|
-
checks.push({
|
|
244
|
-
name: 'Ingest Connection',
|
|
245
|
-
status: 'skip',
|
|
246
|
-
message: 'Could not resolve site automatically',
|
|
247
|
-
fix: 'Pass --site <id> or run "gurulu init"',
|
|
248
|
-
});
|
|
249
|
-
checks.push({
|
|
250
|
-
name: 'Events Flowing',
|
|
251
|
-
status: 'skip',
|
|
252
|
-
message: 'Skipped (no site resolved)',
|
|
253
|
-
});
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
else {
|
|
257
|
-
checks.push({
|
|
258
|
-
name: 'Ingest Connection',
|
|
259
|
-
status: 'skip',
|
|
260
|
-
message: 'Skipped (authentication required)',
|
|
261
|
-
});
|
|
262
|
-
checks.push({
|
|
263
|
-
name: 'Events Flowing',
|
|
264
|
-
status: 'skip',
|
|
265
|
-
message: 'Skipped (authentication required)',
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
|
-
// 9. Env file check
|
|
269
|
-
const envFiles = ['.env.local', '.env', '.env.development'];
|
|
270
|
-
let envHasSiteId = false;
|
|
271
|
-
for (const envFile of envFiles) {
|
|
272
|
-
const envPath = path_1.default.join(projectDir, envFile);
|
|
273
|
-
if (fs_1.default.existsSync(envPath)) {
|
|
274
|
-
const content = fs_1.default.readFileSync(envPath, 'utf-8');
|
|
275
|
-
if (content.includes('GURULU_SITE_ID')) {
|
|
276
|
-
envHasSiteId = true;
|
|
277
|
-
break;
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
if (framework !== 'html' && framework !== 'unknown') {
|
|
282
|
-
checks.push({
|
|
283
|
-
name: 'Env Config',
|
|
284
|
-
status: envHasSiteId ? 'pass' : 'warn',
|
|
285
|
-
message: envHasSiteId ? 'Site ID found in env file' : 'No GURULU_SITE_ID in env files',
|
|
286
|
-
fix: !envHasSiteId ? 'Run "gurulu init" to auto-configure .env.local' : undefined,
|
|
287
|
-
section: 'local',
|
|
288
|
-
});
|
|
289
|
-
}
|
|
290
|
-
// Output
|
|
291
|
-
if (args.json) {
|
|
292
|
-
console.log(JSON.stringify({ framework, checks }, null, 2));
|
|
293
|
-
return;
|
|
294
|
-
}
|
|
295
|
-
(0, ui_1.banner)();
|
|
296
|
-
console.log((0, ui_1.bold)(' Diagnostics'));
|
|
297
|
-
console.log('');
|
|
298
|
-
const icons = {
|
|
299
|
-
pass: (0, ui_1.green)('\u2713'),
|
|
300
|
-
fail: (0, ui_1.red)('\u2717'),
|
|
301
|
-
warn: (0, ui_1.yellow)('\u26A0'),
|
|
302
|
-
skip: (0, ui_1.dim)('-'),
|
|
303
|
-
};
|
|
304
|
-
let failCount = 0;
|
|
305
|
-
let warnCount = 0;
|
|
306
|
-
const localChecks = checks.filter((c) => c.section === 'local');
|
|
307
|
-
const siteChecks = checks.filter((c) => c.section !== 'local');
|
|
308
|
-
const printGroup = (title, items, note) => {
|
|
309
|
-
if (items.length === 0)
|
|
310
|
-
return;
|
|
311
|
-
console.log(` ${(0, ui_1.bold)(title)}`);
|
|
312
|
-
if (note)
|
|
313
|
-
console.log(` ${(0, ui_1.dim)(note)}`);
|
|
314
|
-
for (const check of items) {
|
|
315
|
-
const icon = icons[check.status];
|
|
316
|
-
console.log(` ${icon} ${(0, ui_1.bold)(check.name)}: ${check.message}`);
|
|
317
|
-
if (check.fix) {
|
|
318
|
-
console.log(` ${(0, ui_1.dim)('\u2192')} ${(0, ui_1.dim)(check.fix)}`);
|
|
319
|
-
}
|
|
320
|
-
if (check.status === 'fail')
|
|
321
|
-
failCount++;
|
|
322
|
-
if (check.status === 'warn')
|
|
323
|
-
warnCount++;
|
|
324
|
-
}
|
|
325
|
-
console.log('');
|
|
326
|
-
};
|
|
327
|
-
if (localChecks.length > 0) {
|
|
328
|
-
const localNote = siteId && !isLocalProjectDetected
|
|
329
|
-
? `(Local project not detected \u2014 running site-only checks for ${siteId}.)`
|
|
330
|
-
: undefined;
|
|
331
|
-
printGroup('Local Project', localChecks, localNote);
|
|
332
|
-
}
|
|
333
|
-
if (siteChecks.length > 0) {
|
|
334
|
-
const siteTitle = siteId ? `Site (${siteId})` : 'Site';
|
|
335
|
-
printGroup(siteTitle, siteChecks);
|
|
336
|
-
}
|
|
337
|
-
console.log('');
|
|
338
|
-
if (failCount === 0 && warnCount === 0) {
|
|
339
|
-
(0, ui_1.success)('All checks passed! Your setup looks good.');
|
|
340
|
-
}
|
|
341
|
-
else if (failCount === 0) {
|
|
342
|
-
(0, ui_1.info)(`${warnCount} warning(s), but no critical issues.`);
|
|
343
|
-
}
|
|
344
|
-
else {
|
|
345
|
-
(0, ui_1.error)(`${failCount} issue(s) found. Fix them to get analytics working.`);
|
|
346
|
-
}
|
|
347
|
-
console.log('');
|
|
348
|
-
}
|
|
349
|
-
function findSetupFiles(projectDir) {
|
|
350
|
-
const candidates = [
|
|
351
|
-
'src/lib/gurulu.tsx',
|
|
352
|
-
'src/lib/gurulu.ts',
|
|
353
|
-
'src/gurulu.ts',
|
|
354
|
-
'src/plugins/gurulu.ts',
|
|
355
|
-
'plugins/gurulu.client.ts',
|
|
356
|
-
'src/components/Gurulu.astro',
|
|
357
|
-
'src/gurulu.middleware.ts',
|
|
358
|
-
];
|
|
359
|
-
return candidates.filter(f => fs_1.default.existsSync(path_1.default.join(projectDir, f)));
|
|
360
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sprint E SE-B — `gurulu errors list|detail|resolve|mute`.
|
|
3
|
-
*
|
|
4
|
-
* Mirror of MCP `gurulu.errors.list` / `.detail` plus two new write tools
|
|
5
|
-
* (`.resolve`, `.mute`). Hits new `/api/cli/errors/*` proxy endpoints which
|
|
6
|
-
* use CLI-auth instead of the session-auth used by `/api/analytics/error-groups`.
|
|
7
|
-
*
|
|
8
|
-
* Note: `gurulu errors upload-sourcemap` and `upload-native-symbols` are
|
|
9
|
-
* documented aliases of `gurulu sourcemap upload [--platform=...]` — see
|
|
10
|
-
* `commands/sourcemap.ts`.
|
|
11
|
-
*/
|
|
12
|
-
export interface ErrorsArgs {
|
|
13
|
-
action?: string;
|
|
14
|
-
site?: string;
|
|
15
|
-
fingerprint?: string;
|
|
16
|
-
level?: string;
|
|
17
|
-
resolved?: string;
|
|
18
|
-
environment?: string;
|
|
19
|
-
releaseId?: string;
|
|
20
|
-
limit?: number;
|
|
21
|
-
duration?: string;
|
|
22
|
-
format?: string;
|
|
23
|
-
json?: boolean;
|
|
24
|
-
yes?: boolean;
|
|
25
|
-
profile?: string;
|
|
26
|
-
}
|
|
27
|
-
export declare function errorsCommand(args: ErrorsArgs): Promise<void>;
|
package/dist/commands/errors.js
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Sprint E SE-B — `gurulu errors list|detail|resolve|mute`.
|
|
4
|
-
*
|
|
5
|
-
* Mirror of MCP `gurulu.errors.list` / `.detail` plus two new write tools
|
|
6
|
-
* (`.resolve`, `.mute`). Hits new `/api/cli/errors/*` proxy endpoints which
|
|
7
|
-
* use CLI-auth instead of the session-auth used by `/api/analytics/error-groups`.
|
|
8
|
-
*
|
|
9
|
-
* Note: `gurulu errors upload-sourcemap` and `upload-native-symbols` are
|
|
10
|
-
* documented aliases of `gurulu sourcemap upload [--platform=...]` — see
|
|
11
|
-
* `commands/sourcemap.ts`.
|
|
12
|
-
*/
|
|
13
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
-
exports.errorsCommand = errorsCommand;
|
|
15
|
-
const api_client_1 = require("../api-client");
|
|
16
|
-
const ui_1 = require("../utils/ui");
|
|
17
|
-
const confirm_1 = require("../utils/confirm");
|
|
18
|
-
async function errorsCommand(args) {
|
|
19
|
-
const action = args.action || '';
|
|
20
|
-
switch (action) {
|
|
21
|
-
case 'list':
|
|
22
|
-
return listCmd(args);
|
|
23
|
-
case 'detail':
|
|
24
|
-
return detailCmd(args);
|
|
25
|
-
case 'resolve':
|
|
26
|
-
return resolveCmd(args);
|
|
27
|
-
case 'mute':
|
|
28
|
-
return muteCmd(args);
|
|
29
|
-
case 'upload-sourcemap':
|
|
30
|
-
case 'upload-native-symbols':
|
|
31
|
-
(0, ui_1.info)('Use `gurulu sourcemap upload [--platform=ios|android|web|server] ...` — these names are aliases.');
|
|
32
|
-
return;
|
|
33
|
-
default:
|
|
34
|
-
(0, ui_1.error)(`Unknown errors action: ${action}`);
|
|
35
|
-
(0, ui_1.info)('Usage: gurulu errors [list|detail|resolve|mute] --site=<id> [--fingerprint=<hash>] ...');
|
|
36
|
-
process.exit(1);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
async function listCmd(args) {
|
|
40
|
-
if (!args.site) {
|
|
41
|
-
(0, ui_1.error)('Usage: gurulu errors list --site=<id> [--level=error|warning] [--resolved=false] [--limit=20]');
|
|
42
|
-
process.exit(1);
|
|
43
|
-
}
|
|
44
|
-
const usp = new URLSearchParams();
|
|
45
|
-
usp.set('site', args.site);
|
|
46
|
-
if (args.level)
|
|
47
|
-
usp.set('level', args.level);
|
|
48
|
-
if (args.resolved !== undefined)
|
|
49
|
-
usp.set('resolved', args.resolved);
|
|
50
|
-
if (args.environment)
|
|
51
|
-
usp.set('environment', args.environment);
|
|
52
|
-
if (args.releaseId)
|
|
53
|
-
usp.set('releaseId', args.releaseId);
|
|
54
|
-
if (args.limit)
|
|
55
|
-
usp.set('limit', String(args.limit));
|
|
56
|
-
const body = await (0, api_client_1.cliApiJson)(`/api/cli/errors?${usp.toString()}`, {
|
|
57
|
-
profile: args.profile,
|
|
58
|
-
});
|
|
59
|
-
if (args.format === 'table') {
|
|
60
|
-
const rows = body.groups || [];
|
|
61
|
-
process.stdout.write(['FINGERPRINT', 'COUNT', 'LEVEL', 'STATUS', 'TITLE'].join('\t') + '\n');
|
|
62
|
-
for (const g of rows) {
|
|
63
|
-
process.stdout.write([
|
|
64
|
-
(g.fingerprint || '').slice(0, 16),
|
|
65
|
-
g.count ?? 0,
|
|
66
|
-
g.level ?? '-',
|
|
67
|
-
g.status ?? 'unresolved',
|
|
68
|
-
String(g.title || '-').slice(0, 80),
|
|
69
|
-
].join('\t') + '\n');
|
|
70
|
-
}
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
process.stdout.write(JSON.stringify(body, null, 2) + '\n');
|
|
74
|
-
}
|
|
75
|
-
async function detailCmd(args) {
|
|
76
|
-
if (!args.site || !args.fingerprint) {
|
|
77
|
-
(0, ui_1.error)('Usage: gurulu errors detail --site=<id> --fingerprint=<hash>');
|
|
78
|
-
process.exit(1);
|
|
79
|
-
}
|
|
80
|
-
const path = `/api/cli/errors/${encodeURIComponent(args.fingerprint)}?site=${encodeURIComponent(args.site)}`;
|
|
81
|
-
const body = await (0, api_client_1.cliApiJson)(path, { profile: args.profile });
|
|
82
|
-
process.stdout.write(JSON.stringify(body, null, 2) + '\n');
|
|
83
|
-
}
|
|
84
|
-
async function resolveCmd(args) {
|
|
85
|
-
if (!args.site || !args.fingerprint) {
|
|
86
|
-
(0, ui_1.error)('Usage: gurulu errors resolve --site=<id> --fingerprint=<hash>');
|
|
87
|
-
process.exit(1);
|
|
88
|
-
}
|
|
89
|
-
const ok = await (0, confirm_1.promptConfirm)(`Mark error ${args.fingerprint.slice(0, 12)} as resolved?`, { yes: args.yes, defaultYes: true });
|
|
90
|
-
if (!ok) {
|
|
91
|
-
(0, ui_1.info)('Aborted.');
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
const body = await (0, api_client_1.cliApiJson)(`/api/cli/errors/${encodeURIComponent(args.fingerprint)}/resolve`, {
|
|
95
|
-
profile: args.profile,
|
|
96
|
-
method: 'POST',
|
|
97
|
-
json: { siteId: args.site },
|
|
98
|
-
});
|
|
99
|
-
if (args.json) {
|
|
100
|
-
process.stdout.write(JSON.stringify(body, null, 2) + '\n');
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
(0, ui_1.success)(`Resolved ${args.fingerprint.slice(0, 12)}.`);
|
|
104
|
-
}
|
|
105
|
-
async function muteCmd(args) {
|
|
106
|
-
if (!args.site || !args.fingerprint) {
|
|
107
|
-
(0, ui_1.error)('Usage: gurulu errors mute --site=<id> --fingerprint=<hash> [--duration=24h]');
|
|
108
|
-
process.exit(1);
|
|
109
|
-
}
|
|
110
|
-
const duration = args.duration || '24h';
|
|
111
|
-
const body = await (0, api_client_1.cliApiJson)(`/api/cli/errors/${encodeURIComponent(args.fingerprint)}/mute`, {
|
|
112
|
-
profile: args.profile,
|
|
113
|
-
method: 'POST',
|
|
114
|
-
json: { siteId: args.site, duration },
|
|
115
|
-
});
|
|
116
|
-
if (args.json) {
|
|
117
|
-
process.stdout.write(JSON.stringify(body, null, 2) + '\n');
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
(0, ui_1.success)(`Muted ${args.fingerprint.slice(0, 12)} for ${duration}.`);
|
|
121
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Phase 19.5 W2 B1 — `gurulu events list` / `gurulu events tail`.
|
|
3
|
-
*
|
|
4
|
-
* Replaces the legacy Phase 10 `events` command (which talked to a
|
|
5
|
-
* now-defunct credential store) with CLI-bearer-auth subcommands that hit
|
|
6
|
-
* `/api/cli/events` (list) and `/api/cli/events/tail` (SSE stream).
|
|
7
|
-
*
|
|
8
|
-
* All subcommands support `--json` for scripting + agent parsing.
|
|
9
|
-
*/
|
|
10
|
-
import { loadActiveProfile } from '../config';
|
|
11
|
-
export interface EventsArgs {
|
|
12
|
-
action?: string;
|
|
13
|
-
site?: string;
|
|
14
|
-
eventName?: string;
|
|
15
|
-
since?: string;
|
|
16
|
-
filter?: string;
|
|
17
|
-
limit?: number;
|
|
18
|
-
json?: boolean;
|
|
19
|
-
profile?: string;
|
|
20
|
-
displayName?: string;
|
|
21
|
-
description?: string;
|
|
22
|
-
category?: string;
|
|
23
|
-
properties?: string;
|
|
24
|
-
event?: string;
|
|
25
|
-
vertical?: string;
|
|
26
|
-
}
|
|
27
|
-
export declare function eventsCommand(args: EventsArgs): Promise<void>;
|
|
28
|
-
export declare function legacyEventsCommand(args: {
|
|
29
|
-
site?: string;
|
|
30
|
-
json?: boolean;
|
|
31
|
-
profile?: string;
|
|
32
|
-
}): Promise<void>;
|
|
33
|
-
export declare const _loadActiveProfile: typeof loadActiveProfile;
|