gpxe 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.
package/src/demo.js ADDED
@@ -0,0 +1,211 @@
1
+ const DEMO_MODE = ['1', 'true', 'yes', 'on'].includes((process.env.GRIDPOINT_DEMO || '').toLowerCase());
2
+
3
+ const isDemo = (opts) => Boolean(opts?.demo) || DEMO_MODE;
4
+
5
+ const demoIncidentExplain = (incidentId) => ({
6
+ id: incidentId,
7
+ severity: 'high',
8
+ status: 'ongoing',
9
+ summary: 'Elevated 5xx on api-gateway after deploy v2.14.3; queue latency increased 3.2x.',
10
+ confidence: 0.82,
11
+ primary_cause: { type: 'deploy', id: 'v2.14.3', score: 0.91 },
12
+ signals: [
13
+ { name: 'p95_latency_ms', delta: '+420ms', service: 'api-gateway' },
14
+ { name: 'queue_backlog', delta: '+18k', service: 'ingest' },
15
+ { name: 'db_pool_saturation', delta: '92%', service: 'core-db' }
16
+ ],
17
+ evidence: [
18
+ { detail: 'deploy v2.14.3 at 09:12 UTC -> error spike at 09:15 UTC' },
19
+ { detail: 'trace sample 7a3f... shows retry storm from queue worker' },
20
+ { detail: 'regression in handler /v1/events (diff hunk #42)' }
21
+ ],
22
+ suggested_actions: [
23
+ {
24
+ reason: 'Validate recent changes',
25
+ cmd: 'gridpoint changes correlate --window 2h --service api-gateway'
26
+ },
27
+ { reason: 'Check SLO burn', cmd: 'gridpoint slos status --service api-gateway' },
28
+ {
29
+ reason: 'Rollback last deploy',
30
+ cmd: 'gridpoint deploy rollback v2.14.3 --service api-gateway'
31
+ }
32
+ ]
33
+ });
34
+
35
+ const demoChangesCorrelate = (window) => ({
36
+ window: window || '24h',
37
+ results: [
38
+ { type: 'deploy', id: 'v2.14.3', score: 0.91, impact: { error_rate_pct: 3.8 } },
39
+ { type: 'config', id: 'queue.concurrency', score: 0.62, impact: { p95_latency_ms: -120 } },
40
+ { type: 'infra', id: 'db.resize', score: 0.41, impact: { cpu_pct: -18 } }
41
+ ]
42
+ });
43
+
44
+ const demoSloStatus = (project) => ({
45
+ project: project || 'core',
46
+ slos: [
47
+ {
48
+ service: 'api-gateway',
49
+ availability: 99.93,
50
+ budget_left_pct: 38,
51
+ burn_rate: 1.3,
52
+ time_to_breach: '6d'
53
+ },
54
+ {
55
+ service: 'ingest',
56
+ availability: 99.88,
57
+ budget_left_pct: 22,
58
+ burn_rate: 2.1,
59
+ time_to_breach: '2d'
60
+ }
61
+ ]
62
+ });
63
+
64
+ const demoAlertsTune = (window, service) => ({
65
+ window: window || '24h',
66
+ service: service || null,
67
+ summary: {
68
+ noisy_alerts: 12,
69
+ total_alerts: 38,
70
+ noise_pct: 32
71
+ },
72
+ recommendations: [
73
+ {
74
+ alert: 'latency_p95',
75
+ action: 'raise_threshold',
76
+ current: '900ms',
77
+ suggested: '1.2s',
78
+ expected_noise_reduction_pct: 28
79
+ },
80
+ {
81
+ alert: 'queue_backlog',
82
+ action: 'add_sustained_window',
83
+ current: '5m',
84
+ suggested: '10m',
85
+ expected_noise_reduction_pct: 18
86
+ },
87
+ {
88
+ alert: 'error_rate',
89
+ action: 'lower_sensitivity',
90
+ current: '1.8%',
91
+ suggested: '2.2%',
92
+ expected_noise_reduction_pct: 12
93
+ }
94
+ ]
95
+ });
96
+
97
+ const demoRunbookSuggest = (incidentId, service) => ({
98
+ incident_id: incidentId,
99
+ title: 'Elevated 5xx on api-gateway',
100
+ service: service || 'api-gateway',
101
+ steps: [
102
+ {
103
+ title: 'Confirm change correlation',
104
+ command: 'gridpoint changes correlate --window 2h --service api-gateway',
105
+ rationale: 'Recent deploys or config changes are the most common cause.'
106
+ },
107
+ {
108
+ title: 'Review SLO burn',
109
+ command: 'gridpoint slos status --service api-gateway',
110
+ rationale: 'Determine if this will breach the error budget.'
111
+ },
112
+ {
113
+ title: 'Tune alerts temporarily',
114
+ command: 'gridpoint alerts tune --service api-gateway --window 6h',
115
+ rationale: 'Reduce alert noise while triaging.'
116
+ },
117
+ {
118
+ title: 'Rollback last deploy',
119
+ command: 'gridpoint deploy rollback v2.14.3 --service api-gateway',
120
+ rationale: 'Rollback typically stabilizes error rate within minutes.'
121
+ }
122
+ ]
123
+ });
124
+
125
+ const demoCapacityForecast = (window, service) => ({
126
+ window: window || '30d',
127
+ service: service || 'ingest',
128
+ saturation: { days: 18, utilization_pct: 86 },
129
+ cost: { projected_monthly_usd: 1240, delta_pct: 18 },
130
+ recommendations: [
131
+ { action: 'increase_worker_pool', detail: 'Scale ingest workers to 12 by week 3.' },
132
+ { action: 'optimize_batching', detail: 'Raise batch size to 1200 to reduce CPU cost.' }
133
+ ]
134
+ });
135
+
136
+ const demoBillingStatus = () => ({
137
+ account: {
138
+ id: 'acct_4c1d',
139
+ workspace_id: 'core',
140
+ plan: 'Pro',
141
+ usage_tier: 'Growth',
142
+ usage_limit: 5000000,
143
+ status: 'active',
144
+ period_start: '2025-12-01',
145
+ period_end: '2025-12-31',
146
+ payment_method: { brand: 'Visa', last4: '4242' },
147
+ next_invoice: { amount: 8900, currency: 'USD', due_at: '2026-01-01' },
148
+ portal_url: 'https://app.gridpointanalytics.com/billing'
149
+ },
150
+ usage: {
151
+ month: '2025-12',
152
+ unit: 'events',
153
+ total: 1842000,
154
+ by_service: [
155
+ { service: 'api-gateway', total: 920000, unit: 'events' },
156
+ { service: 'ingest', total: 642000, unit: 'events' },
157
+ { service: 'workers', total: 280000, unit: 'events' }
158
+ ]
159
+ },
160
+ invoices: [
161
+ {
162
+ id: 'inv_1032',
163
+ number: 'INV-1032',
164
+ status: 'paid',
165
+ amount_due: 8900,
166
+ currency: 'USD',
167
+ issued_at: '2025-12-01',
168
+ due_at: '2025-12-01',
169
+ hosted_url: 'https://app.gridpointanalytics.com/invoices/INV-1032'
170
+ }
171
+ ]
172
+ });
173
+
174
+ const demoBillingUsageReport = (payload) => ({
175
+ status: 'recorded',
176
+ usage: {
177
+ id: 'use_demo',
178
+ account_id: payload.account_id || null,
179
+ workspace_id: payload.workspace_id || null,
180
+ service: payload.service || null,
181
+ quantity: payload.quantity,
182
+ unit: payload.unit || 'events',
183
+ source: payload.source || 'cli',
184
+ created_at: new Date().toISOString()
185
+ }
186
+ });
187
+
188
+ const demoSupportRequest = (topic, subject, message, email) => ({
189
+ status: 'open',
190
+ request: {
191
+ id: 'sup_demo',
192
+ topic: topic || 'general',
193
+ subject: subject || 'Billing question',
194
+ message: message || 'Need help with invoice history.',
195
+ email: email || 'operator@example.com',
196
+ created_at: new Date().toISOString()
197
+ }
198
+ });
199
+
200
+ module.exports = {
201
+ isDemo,
202
+ demoIncidentExplain,
203
+ demoChangesCorrelate,
204
+ demoSloStatus,
205
+ demoAlertsTune,
206
+ demoRunbookSuggest,
207
+ demoCapacityForecast,
208
+ demoBillingStatus,
209
+ demoBillingUsageReport,
210
+ demoSupportRequest,
211
+ };
package/src/main.js ADDED
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env node
2
+ const { program } = require('commander');
3
+ const chalk = require('chalk');
4
+ const {
5
+ initFlags,
6
+ shouldShowBanner,
7
+ shouldShowHints,
8
+ } = require('./util');
9
+ const { recordUsage } = require('./billing');
10
+
11
+
12
+
13
+ program
14
+ .name('gpxe')
15
+ .version('2.0.0')
16
+ .description('CLI-first telemetry for Cloudflare stacks.')
17
+ .usage('<command> [options]')
18
+ .addHelpText(
19
+ 'after',
20
+ '\nQuick start:\n gpxe login\n gpxe init\n gpxe status\n\nExamples:\n gpxe metrics --watch 10\n gpxe incidents explain inc_123 --demo\n gpxe alerts tune --service api-gateway\n gpxe capacity forecast --window 30d\n gpxe status --json\n'
21
+ );
22
+
23
+ program.hook('postAction', async (thisCommand, actionCommand) => {
24
+ await recordUsage(actionCommand);
25
+ });
26
+
27
+ program.hook('preAction', (thisCommand, actionCommand) => {
28
+ if (actionCommand && typeof actionCommand.opts === 'function') {
29
+ actionCommand.opts()._startTime = Date.now();
30
+ }
31
+ });
32
+
33
+ require('./commands/basic');
34
+ require('./commands/reserve');
35
+ require('./commands/config');
36
+ require('./commands/status');
37
+ require('./commands/incidents');
38
+ require('./commands/changes');
39
+ require('./commands/slos');
40
+ require('./commands/alerts');
41
+ require('./commands/runbooks');
42
+ require('./commands/capacity');
43
+ require('./commands/deploy');
44
+ require('./commands/billing');
45
+ require('./commands/support');
46
+
47
+
48
+
49
+ const run = async (argv) => {
50
+ initFlags(argv);
51
+
52
+ if (shouldShowBanner()) {
53
+
54
+ console.log(chalk.green.bold("\nGridpoint Analytics CLI (gpxe)\n"));
55
+
56
+ }
57
+
58
+ await program.parseAsync(argv);
59
+
60
+ if (!argv.slice(2).length) {
61
+ program.outputHelp();
62
+ }
63
+ };
64
+
65
+
66
+
67
+ if (require.main === module) {
68
+
69
+ run(process.argv).catch((err) => {
70
+
71
+ console.error(chalk.red('Unexpected CLI error.'));
72
+
73
+ if (shouldShowHints()) {
74
+
75
+ console.error(err);
76
+
77
+ }
78
+
79
+ process.exitCode = 1;
80
+
81
+ });
82
+
83
+ }
84
+
85
+
86
+
87
+ module.exports = { run };
88
+
89
+
package/src/util.js ADDED
@@ -0,0 +1,110 @@
1
+ const chalk = require('chalk');
2
+ const { program } = require('commander');
3
+
4
+ let wantsJson = false;
5
+ let showBanner = false;
6
+ let showHints = false;
7
+
8
+ const toInt = (value, fallback) => {
9
+ const parsed = Number.parseInt(value, 10);
10
+ return Number.isFinite(parsed) ? parsed : fallback;
11
+ };
12
+
13
+ const parseQuantity = (value) => {
14
+ const parsed = Number(value);
15
+ return Number.isFinite(parsed) ? parsed : null;
16
+ };
17
+
18
+ const maskToken = (token) => {
19
+ if (!token) return null;
20
+ if (token.length <= 8) return "********";
21
+ return `${token.slice(0, 4)}...${token.slice(-4)}`;
22
+ };
23
+
24
+ const printRequestError = (error, fallback, endpoint) => {
25
+ const status = error?.response?.status;
26
+ const detail = error?.response?.data?.error || error?.response?.data?.message;
27
+ const message = status ? `${fallback} (HTTP ${status})` : fallback;
28
+ console.log(chalk.red(message));
29
+ if (detail) {
30
+ console.log(detail);
31
+ }
32
+ if (!showHints) return;
33
+ if (status === 401 || status === 403) {
34
+ console.log(chalk.gray('Tip: run "gpxe login" to set a token.'));
35
+ return;
36
+ }
37
+ if (error?.code === 'ECONNABORTED') {
38
+ console.log(chalk.gray('Tip: the endpoint is slow or unreachable. Check "gpxe config".'));
39
+ return;
40
+ }
41
+ if (error?.code === 'ENOTFOUND' || error?.code === 'ECONNREFUSED') {
42
+ console.log(chalk.gray(`Tip: verify the endpoint: ${endpoint || 'set with gpxe init'}`));
43
+ return;
44
+ }
45
+ console.log(chalk.gray('Tip: verify your endpoint with "gpxe config".'));
46
+ };
47
+
48
+ const getCommandPath = (actionCommand) => {
49
+ const parts = [];
50
+ let current = actionCommand;
51
+ while (current && typeof current.name === 'function') {
52
+ const name = current.name();
53
+ if (!name || name === 'gridpoint') break;
54
+ parts.unshift(name);
55
+ current = current.parent;
56
+ }
57
+ return parts.join(' ');
58
+ };
59
+
60
+ const formatImpact = (impact) => {
61
+ if (!impact || typeof impact !== 'object') return 'impact: n/a';
62
+ const parts = Object.entries(impact)
63
+ .filter(([, value]) => value !== null && value !== undefined)
64
+ .map(([key, value]) => {
65
+ if (typeof value === 'number') {
66
+ const sign = value > 0 ? '+' : '';
67
+ return `${key} ${sign}${value}`;
68
+ }
69
+ return `${key} ${value}`;
70
+ });
71
+ return parts.length ? `impact: ${parts.join(', ')}` : 'impact: n/a';
72
+ };
73
+
74
+ const formatPercent = (value) => (Number.isFinite(value) ? `${value}%` : 'n/a');
75
+ const formatCurrency = (value) =>
76
+ Number.isFinite(value)
77
+ ? `$${value.toLocaleString('en-US', { maximumFractionDigits: 0 })}`
78
+ : 'n/a';
79
+ const formatCents = (value, currency = 'USD') => {
80
+ if (!Number.isFinite(value)) return 'n/a';
81
+ const amount = (value / 100).toFixed(2);
82
+ return currency === 'USD' ? `$${amount}` : `${amount} ${currency}`;
83
+ };
84
+
85
+ const initFlags = (argv) => {
86
+ wantsJson = argv.includes('--json');
87
+ showBanner = process.stdout.isTTY && !wantsJson;
88
+ showHints = process.stdout.isTTY && !wantsJson;
89
+ };
90
+
91
+
92
+ const shouldShowHints = () => showHints;
93
+ const shouldShowBanner = () => showBanner;
94
+ const wantsJSON = () => wantsJson;
95
+
96
+ module.exports = {
97
+ toInt,
98
+ parseQuantity,
99
+ maskToken,
100
+ printRequestError,
101
+ getCommandPath,
102
+ formatImpact,
103
+ formatPercent,
104
+ formatCurrency,
105
+ formatCents,
106
+ initFlags,
107
+ shouldShowHints,
108
+ shouldShowBanner,
109
+ wantsJSON,
110
+ };