@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.
- 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 +25410 -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 +25 -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 +24985 -853
- 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/package.json +40 -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 -18
- package/dist/commands/chat.js +0 -117
- 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 -349
- 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 -65
- 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/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 -444
- 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
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Phase 18.6 — CLI install-time intent proposal rendering + interaction.
|
|
4
|
-
*
|
|
5
|
-
* Pure UI logic (plus a small interactive loop) that turns an `InstallIntent`
|
|
6
|
-
* payload into a human-readable proposal and lets the user toggle individual
|
|
7
|
-
* events/funnels before sending the accepted subset to the backend. This file
|
|
8
|
-
* has NO hard limit on event/funnel count — a full iGaming intent with 20
|
|
9
|
-
* events is rendered in full.
|
|
10
|
-
*
|
|
11
|
-
* Testability: the render function returns a plain string so snapshot-style
|
|
12
|
-
* tests can assert structure. The interactive runner accepts injected I/O so
|
|
13
|
-
* tests can drive it without real stdin/stdout.
|
|
14
|
-
*/
|
|
15
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
-
exports.initProposalState = initProposalState;
|
|
17
|
-
exports.renderProposal = renderProposal;
|
|
18
|
-
exports.applyCommand = applyCommand;
|
|
19
|
-
exports.splitDecision = splitDecision;
|
|
20
|
-
exports.runProposal = runProposal;
|
|
21
|
-
function initProposalState(intent) {
|
|
22
|
-
return {
|
|
23
|
-
intent,
|
|
24
|
-
eventSelected: intent.events.map(() => true),
|
|
25
|
-
funnelSelected: intent.funnels.map(() => true),
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
function formatSource(src) {
|
|
29
|
-
if (src.route)
|
|
30
|
-
return src.route;
|
|
31
|
-
if (src.mutation)
|
|
32
|
-
return `mutation: ${src.mutation}`;
|
|
33
|
-
if (src.inferred)
|
|
34
|
-
return `inferred: ${src.inferredFrom || 'pattern'}`;
|
|
35
|
-
return 'unspecified';
|
|
36
|
-
}
|
|
37
|
-
function pad(str, width) {
|
|
38
|
-
if (str.length >= width)
|
|
39
|
-
return str;
|
|
40
|
-
return str + ' '.repeat(width - str.length);
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Render the proposal to a plain string (TTY colour escapes applied by the
|
|
44
|
-
* caller if `colorize` is true). No truncation — every event/funnel is shown.
|
|
45
|
-
*/
|
|
46
|
-
function renderProposal(state, opts = {}) {
|
|
47
|
-
const { intent } = state;
|
|
48
|
-
const lines = [];
|
|
49
|
-
const analyzerBanner = intent.analyzerMode === 'llm'
|
|
50
|
-
? ''
|
|
51
|
-
: ' [basic analysis — LLM unavailable or disabled]';
|
|
52
|
-
lines.push('');
|
|
53
|
-
lines.push(` Detected: ${intent.vertical} (${intent.confidence} confidence)`);
|
|
54
|
-
if (analyzerBanner)
|
|
55
|
-
lines.push(analyzerBanner);
|
|
56
|
-
if (intent.reasoning) {
|
|
57
|
-
lines.push('');
|
|
58
|
-
lines.push(' Reasoning:');
|
|
59
|
-
for (const w of wrap(intent.reasoning, 72))
|
|
60
|
-
lines.push(` ${w}`);
|
|
61
|
-
}
|
|
62
|
-
if (intent.alternativeVerticals.length > 0) {
|
|
63
|
-
lines.push('');
|
|
64
|
-
lines.push(' Alternative interpretations:');
|
|
65
|
-
for (const a of intent.alternativeVerticals) {
|
|
66
|
-
lines.push(` - ${a.name} (${a.confidence})${a.note ? ` - ${a.note}` : ''}`);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
lines.push('');
|
|
70
|
-
lines.push(` Proposed events (${intent.events.length}):`);
|
|
71
|
-
const nameWidth = Math.max(12, ...intent.events.map((e) => e.name.length));
|
|
72
|
-
const catWidth = Math.max(8, ...intent.events.map((e) => e.category.length));
|
|
73
|
-
intent.events.forEach((ev, i) => {
|
|
74
|
-
const mark = state.eventSelected[i] ? '[x]' : '[ ]';
|
|
75
|
-
lines.push(` ${pad(String(i + 1), 3)}${mark} ${pad(ev.name, nameWidth + 2)}${pad(ev.category, catWidth + 2)}${formatSource(ev.source)}`);
|
|
76
|
-
if (ev.reasoning) {
|
|
77
|
-
for (const w of wrap(ev.reasoning, 68))
|
|
78
|
-
lines.push(` ${w}`);
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
lines.push('');
|
|
82
|
-
lines.push(` Proposed funnels (${intent.funnels.length}):`);
|
|
83
|
-
intent.funnels.forEach((fn, i) => {
|
|
84
|
-
const mark = state.funnelSelected[i] ? '[x]' : '[ ]';
|
|
85
|
-
lines.push(` F${pad(String(i + 1), 2)}${mark} ${fn.name} (${fn.category})`);
|
|
86
|
-
lines.push(` ${fn.steps.join(' -> ')}`);
|
|
87
|
-
if (fn.reasoning) {
|
|
88
|
-
for (const w of wrap(fn.reasoning, 68))
|
|
89
|
-
lines.push(` ${w}`);
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
lines.push('');
|
|
93
|
-
lines.push(' [x] = include, [ ] = skip.');
|
|
94
|
-
lines.push(' Type number to toggle event, F<n> to toggle funnel, A to toggle all, Enter to continue, Q to quit.');
|
|
95
|
-
lines.push('');
|
|
96
|
-
if (opts.colorize) {
|
|
97
|
-
// cheap colorization: highlight the "Detected:" line
|
|
98
|
-
return lines
|
|
99
|
-
.map((l) => l.includes('Detected:')
|
|
100
|
-
? `\x1b[1m${l}\x1b[0m`
|
|
101
|
-
: l.includes('[x]')
|
|
102
|
-
? l
|
|
103
|
-
: l)
|
|
104
|
-
.join('\n');
|
|
105
|
-
}
|
|
106
|
-
return lines.join('\n');
|
|
107
|
-
}
|
|
108
|
-
function wrap(str, width) {
|
|
109
|
-
const words = str.split(/\s+/).filter(Boolean);
|
|
110
|
-
const out = [];
|
|
111
|
-
let line = '';
|
|
112
|
-
for (const w of words) {
|
|
113
|
-
if ((line + ' ' + w).trim().length > width) {
|
|
114
|
-
if (line)
|
|
115
|
-
out.push(line);
|
|
116
|
-
line = w;
|
|
117
|
-
}
|
|
118
|
-
else {
|
|
119
|
-
line = line ? `${line} ${w}` : w;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
if (line)
|
|
123
|
-
out.push(line);
|
|
124
|
-
return out;
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Apply a single user command to the proposal state. Exported so tests can
|
|
128
|
-
* exercise the state machine directly without any I/O.
|
|
129
|
-
*/
|
|
130
|
-
function applyCommand(state, raw) {
|
|
131
|
-
const cmd = (raw || '').trim();
|
|
132
|
-
if (cmd === '')
|
|
133
|
-
return { state, done: true, quit: false };
|
|
134
|
-
const upper = cmd.toUpperCase();
|
|
135
|
-
if (upper === 'Q')
|
|
136
|
-
return { state, done: true, quit: true };
|
|
137
|
-
if (upper === 'A') {
|
|
138
|
-
// If any event is unchecked, select all; else uncheck all.
|
|
139
|
-
const anyOff = state.eventSelected.some((v) => !v);
|
|
140
|
-
const next = state.eventSelected.map(() => anyOff);
|
|
141
|
-
return {
|
|
142
|
-
state: { ...state, eventSelected: next },
|
|
143
|
-
done: false,
|
|
144
|
-
quit: false,
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
const funnelMatch = upper.match(/^F(\d+)$/);
|
|
148
|
-
if (funnelMatch) {
|
|
149
|
-
const idx = parseInt(funnelMatch[1], 10) - 1;
|
|
150
|
-
if (idx >= 0 && idx < state.funnelSelected.length) {
|
|
151
|
-
const next = [...state.funnelSelected];
|
|
152
|
-
next[idx] = !next[idx];
|
|
153
|
-
return { state: { ...state, funnelSelected: next }, done: false, quit: false };
|
|
154
|
-
}
|
|
155
|
-
return { state, done: false, quit: false };
|
|
156
|
-
}
|
|
157
|
-
const eventMatch = cmd.match(/^(\d+)$/);
|
|
158
|
-
if (eventMatch) {
|
|
159
|
-
const idx = parseInt(eventMatch[1], 10) - 1;
|
|
160
|
-
if (idx >= 0 && idx < state.eventSelected.length) {
|
|
161
|
-
const next = [...state.eventSelected];
|
|
162
|
-
next[idx] = !next[idx];
|
|
163
|
-
return { state: { ...state, eventSelected: next }, done: false, quit: false };
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
return { state, done: false, quit: false };
|
|
167
|
-
}
|
|
168
|
-
function splitDecision(state) {
|
|
169
|
-
const accepted = {
|
|
170
|
-
events: state.intent.events.filter((_, i) => state.eventSelected[i]),
|
|
171
|
-
funnels: state.intent.funnels.filter((_, i) => state.funnelSelected[i]),
|
|
172
|
-
};
|
|
173
|
-
const rejected = {
|
|
174
|
-
events: state.intent.events.filter((_, i) => !state.eventSelected[i]),
|
|
175
|
-
funnels: state.intent.funnels.filter((_, i) => !state.funnelSelected[i]),
|
|
176
|
-
};
|
|
177
|
-
return { accepted, rejected, quit: false };
|
|
178
|
-
}
|
|
179
|
-
/**
|
|
180
|
-
* Drive the interactive proposal loop. Returns the accepted + rejected split
|
|
181
|
-
* plus a `quit` flag the caller uses to decide whether to continue the install.
|
|
182
|
-
*/
|
|
183
|
-
async function runProposal(opts) {
|
|
184
|
-
let state = initProposalState(opts.intent);
|
|
185
|
-
if (opts.nonInteractive) {
|
|
186
|
-
opts.io.print(renderProposal(state));
|
|
187
|
-
opts.io.print(' Non-interactive mode: accepting all proposed events and funnels.');
|
|
188
|
-
return splitDecision(state);
|
|
189
|
-
}
|
|
190
|
-
while (true) {
|
|
191
|
-
opts.io.print(renderProposal(state));
|
|
192
|
-
const answer = await opts.io.prompt(' > ');
|
|
193
|
-
const res = applyCommand(state, answer);
|
|
194
|
-
state = res.state;
|
|
195
|
-
if (res.done) {
|
|
196
|
-
if (res.quit) {
|
|
197
|
-
return { ...splitDecision(state), quit: true };
|
|
198
|
-
}
|
|
199
|
-
return splitDecision(state);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
package/dist/utils/api.d.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export declare class GuruluAPI {
|
|
2
|
-
private apiKey;
|
|
3
|
-
private baseUrl;
|
|
4
|
-
constructor(apiKey?: string, baseUrl?: string);
|
|
5
|
-
listSites(): Promise<Array<{
|
|
6
|
-
id: string;
|
|
7
|
-
domain: string;
|
|
8
|
-
name: string;
|
|
9
|
-
}>>;
|
|
10
|
-
getSiteCredentials(siteId: string): Promise<{
|
|
11
|
-
siteId: string;
|
|
12
|
-
token: string;
|
|
13
|
-
}>;
|
|
14
|
-
listEvents(siteId: string): Promise<unknown[]>;
|
|
15
|
-
checkHealth(siteId: string): Promise<{
|
|
16
|
-
connected: boolean;
|
|
17
|
-
lastEvent?: string;
|
|
18
|
-
eventsToday?: number;
|
|
19
|
-
}>;
|
|
20
|
-
}
|
package/dist/utils/api.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.GuruluAPI = void 0;
|
|
4
|
-
const config_1 = require("./config");
|
|
5
|
-
class GuruluAPI {
|
|
6
|
-
apiKey;
|
|
7
|
-
baseUrl;
|
|
8
|
-
constructor(apiKey, baseUrl) {
|
|
9
|
-
this.apiKey = apiKey || (0, config_1.loadConfig)().apiKey || '';
|
|
10
|
-
this.baseUrl = baseUrl || 'https://app.gurulu.io';
|
|
11
|
-
}
|
|
12
|
-
async listSites() {
|
|
13
|
-
const res = await fetch(`${this.baseUrl}/api/v1/sites`, {
|
|
14
|
-
headers: { 'Authorization': `Bearer ${this.apiKey}` },
|
|
15
|
-
});
|
|
16
|
-
if (!res.ok)
|
|
17
|
-
throw new Error(`API error: ${res.status}`);
|
|
18
|
-
const data = await res.json();
|
|
19
|
-
return data.sites;
|
|
20
|
-
}
|
|
21
|
-
async getSiteCredentials(siteId) {
|
|
22
|
-
const res = await fetch(`${this.baseUrl}/api/v1/sites/${siteId}/credentials`, {
|
|
23
|
-
headers: { 'Authorization': `Bearer ${this.apiKey}` },
|
|
24
|
-
});
|
|
25
|
-
if (!res.ok)
|
|
26
|
-
throw new Error(`API error: ${res.status}`);
|
|
27
|
-
return await res.json();
|
|
28
|
-
}
|
|
29
|
-
async listEvents(siteId) {
|
|
30
|
-
const res = await fetch(`${this.baseUrl}/api/events/catalog?siteId=${siteId}`, {
|
|
31
|
-
headers: { 'Authorization': `Bearer ${this.apiKey}` },
|
|
32
|
-
});
|
|
33
|
-
if (!res.ok)
|
|
34
|
-
throw new Error(`API error: ${res.status}`);
|
|
35
|
-
const data = await res.json();
|
|
36
|
-
return data.events;
|
|
37
|
-
}
|
|
38
|
-
async checkHealth(siteId) {
|
|
39
|
-
const res = await fetch(`${this.baseUrl}/api/v1/sites/${siteId}/health`, {
|
|
40
|
-
headers: { 'Authorization': `Bearer ${this.apiKey}` },
|
|
41
|
-
});
|
|
42
|
-
if (!res.ok)
|
|
43
|
-
throw new Error(`API error: ${res.status}`);
|
|
44
|
-
return await res.json();
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
exports.GuruluAPI = GuruluAPI;
|
package/dist/utils/config.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export interface GuruluConfig {
|
|
2
|
-
email?: string;
|
|
3
|
-
apiKey?: string;
|
|
4
|
-
defaultSiteId?: string;
|
|
5
|
-
sites?: Array<{
|
|
6
|
-
id: string;
|
|
7
|
-
domain: string;
|
|
8
|
-
name: string;
|
|
9
|
-
}>;
|
|
10
|
-
}
|
|
11
|
-
export declare function loadConfig(): GuruluConfig;
|
|
12
|
-
export declare function saveConfig(config: GuruluConfig): void;
|
|
13
|
-
export declare function clearConfig(): void;
|
package/dist/utils/config.js
DELETED
|
@@ -1,30 +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.loadConfig = loadConfig;
|
|
7
|
-
exports.saveConfig = saveConfig;
|
|
8
|
-
exports.clearConfig = clearConfig;
|
|
9
|
-
const fs_1 = __importDefault(require("fs"));
|
|
10
|
-
const path_1 = __importDefault(require("path"));
|
|
11
|
-
const os_1 = __importDefault(require("os"));
|
|
12
|
-
const CONFIG_DIR = path_1.default.join(os_1.default.homedir(), '.gurulu');
|
|
13
|
-
const CONFIG_FILE = path_1.default.join(CONFIG_DIR, 'config.json');
|
|
14
|
-
function loadConfig() {
|
|
15
|
-
try {
|
|
16
|
-
if (fs_1.default.existsSync(CONFIG_FILE)) {
|
|
17
|
-
return JSON.parse(fs_1.default.readFileSync(CONFIG_FILE, 'utf-8'));
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
catch { }
|
|
21
|
-
return {};
|
|
22
|
-
}
|
|
23
|
-
function saveConfig(config) {
|
|
24
|
-
fs_1.default.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
25
|
-
fs_1.default.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
26
|
-
}
|
|
27
|
-
function clearConfig() {
|
|
28
|
-
if (fs_1.default.existsSync(CONFIG_FILE))
|
|
29
|
-
fs_1.default.unlinkSync(CONFIG_FILE);
|
|
30
|
-
}
|
package/dist/utils/confirm.d.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Phase 20 W2 B6 — interactive confirm prompt shared by every write command.
|
|
3
|
-
*
|
|
4
|
-
* Bypass rules, in order:
|
|
5
|
-
* 1. `opts.yes === true` (set by `--yes` flag)
|
|
6
|
-
* 2. `GURULU_NO_CONFIRM=1` environment variable
|
|
7
|
-
* 3. stdin is not a TTY (scripted / CI usage)
|
|
8
|
-
*
|
|
9
|
-
* Returns `true` if the user confirmed (or any bypass fired), `false`
|
|
10
|
-
* otherwise. The default is `false` on empty input — mirroring every
|
|
11
|
-
* well-behaved `[y/N]` prompt.
|
|
12
|
-
*/
|
|
13
|
-
export interface ConfirmOptions {
|
|
14
|
-
yes?: boolean;
|
|
15
|
-
defaultYes?: boolean;
|
|
16
|
-
}
|
|
17
|
-
export declare function promptConfirm(message: string, opts?: ConfirmOptions): Promise<boolean>;
|
package/dist/utils/confirm.js
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Phase 20 W2 B6 — interactive confirm prompt shared by every write command.
|
|
4
|
-
*
|
|
5
|
-
* Bypass rules, in order:
|
|
6
|
-
* 1. `opts.yes === true` (set by `--yes` flag)
|
|
7
|
-
* 2. `GURULU_NO_CONFIRM=1` environment variable
|
|
8
|
-
* 3. stdin is not a TTY (scripted / CI usage)
|
|
9
|
-
*
|
|
10
|
-
* Returns `true` if the user confirmed (or any bypass fired), `false`
|
|
11
|
-
* otherwise. The default is `false` on empty input — mirroring every
|
|
12
|
-
* well-behaved `[y/N]` prompt.
|
|
13
|
-
*/
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.promptConfirm = promptConfirm;
|
|
16
|
-
const ui_1 = require("./ui");
|
|
17
|
-
async function promptConfirm(message, opts = {}) {
|
|
18
|
-
if (opts.yes === true)
|
|
19
|
-
return true;
|
|
20
|
-
if (process.env.GURULU_NO_CONFIRM === '1')
|
|
21
|
-
return true;
|
|
22
|
-
if (!process.stdin.isTTY)
|
|
23
|
-
return true;
|
|
24
|
-
const suffix = opts.defaultYes ? '[Y/n]' : '[y/N]';
|
|
25
|
-
process.stdout.write(`${(0, ui_1.yellow)('?')} ${message} ${suffix} `);
|
|
26
|
-
return new Promise((resolve) => {
|
|
27
|
-
const readline = require('readline');
|
|
28
|
-
const rl = readline.createInterface({
|
|
29
|
-
input: process.stdin,
|
|
30
|
-
output: process.stdout,
|
|
31
|
-
});
|
|
32
|
-
rl.question('', (answer) => {
|
|
33
|
-
rl.close();
|
|
34
|
-
const a = (answer || '').trim().toLowerCase();
|
|
35
|
-
if (a === '')
|
|
36
|
-
return resolve(!!opts.defaultYes);
|
|
37
|
-
resolve(a === 'y' || a === 'yes');
|
|
38
|
-
});
|
|
39
|
-
});
|
|
40
|
-
}
|
package/dist/utils/dry-run.d.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Phase 20 W2 B6 — dry-run output helper.
|
|
3
|
-
*
|
|
4
|
-
* The server-side of each write route returns a uniform shape when
|
|
5
|
-
* `?dryRun=1` is set:
|
|
6
|
-
*
|
|
7
|
-
* { dryRun: true, action, resource, before?, after }
|
|
8
|
-
*
|
|
9
|
-
* `printDryRun` renders that as a coloured, line-oriented diff so the
|
|
10
|
-
* CLI user can sanity-check before re-running without `--dry-run`. JSON
|
|
11
|
-
* mode is a straight passthrough for scripts.
|
|
12
|
-
*/
|
|
13
|
-
export interface DryRunPayload {
|
|
14
|
-
dryRun?: boolean;
|
|
15
|
-
action?: string;
|
|
16
|
-
resource?: string;
|
|
17
|
-
before?: unknown;
|
|
18
|
-
after?: unknown;
|
|
19
|
-
}
|
|
20
|
-
export declare function printDryRun(payload: DryRunPayload, json?: boolean): void;
|
package/dist/utils/dry-run.js
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Phase 20 W2 B6 — dry-run output helper.
|
|
4
|
-
*
|
|
5
|
-
* The server-side of each write route returns a uniform shape when
|
|
6
|
-
* `?dryRun=1` is set:
|
|
7
|
-
*
|
|
8
|
-
* { dryRun: true, action, resource, before?, after }
|
|
9
|
-
*
|
|
10
|
-
* `printDryRun` renders that as a coloured, line-oriented diff so the
|
|
11
|
-
* CLI user can sanity-check before re-running without `--dry-run`. JSON
|
|
12
|
-
* mode is a straight passthrough for scripts.
|
|
13
|
-
*/
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.printDryRun = printDryRun;
|
|
16
|
-
const ui_1 = require("./ui");
|
|
17
|
-
function printDryRun(payload, json) {
|
|
18
|
-
if (json) {
|
|
19
|
-
process.stdout.write(JSON.stringify(payload, null, 2) + '\n');
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
const { action = '?', resource = '?', before, after } = payload;
|
|
23
|
-
process.stdout.write(`${(0, ui_1.cyan)('dry-run')} ${(0, ui_1.yellow)(action)} ${resource}\n` + (0, ui_1.dim)('─'.repeat(40)) + '\n');
|
|
24
|
-
const beforeKeys = isObj(before) ? Object.keys(before) : [];
|
|
25
|
-
const afterKeys = isObj(after) ? Object.keys(after) : [];
|
|
26
|
-
const all = Array.from(new Set([...beforeKeys, ...afterKeys])).sort();
|
|
27
|
-
if (all.length === 0) {
|
|
28
|
-
if (after !== undefined && after !== null) {
|
|
29
|
-
process.stdout.write((0, ui_1.green)(`+ ${stringify(after)}\n`));
|
|
30
|
-
}
|
|
31
|
-
if (before !== undefined && before !== null && after === null) {
|
|
32
|
-
process.stdout.write((0, ui_1.red)(`- ${stringify(before)}\n`));
|
|
33
|
-
}
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
for (const k of all) {
|
|
37
|
-
const b = isObj(before) ? before[k] : undefined;
|
|
38
|
-
const a = isObj(after) ? after[k] : undefined;
|
|
39
|
-
if (stringify(a) === stringify(b)) {
|
|
40
|
-
process.stdout.write((0, ui_1.dim)(` ${k}: ${stringify(a)}\n`));
|
|
41
|
-
continue;
|
|
42
|
-
}
|
|
43
|
-
if (b !== undefined) {
|
|
44
|
-
process.stdout.write((0, ui_1.red)(`- ${k}: ${stringify(b)}\n`));
|
|
45
|
-
}
|
|
46
|
-
if (a !== undefined) {
|
|
47
|
-
process.stdout.write((0, ui_1.green)(`+ ${k}: ${stringify(a)}\n`));
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
function isObj(v) {
|
|
52
|
-
return v !== null && typeof v === 'object' && !Array.isArray(v);
|
|
53
|
-
}
|
|
54
|
-
function stringify(v) {
|
|
55
|
-
if (v === undefined)
|
|
56
|
-
return 'undefined';
|
|
57
|
-
if (v === null)
|
|
58
|
-
return 'null';
|
|
59
|
-
if (typeof v === 'string')
|
|
60
|
-
return v;
|
|
61
|
-
try {
|
|
62
|
-
return JSON.stringify(v);
|
|
63
|
-
}
|
|
64
|
-
catch {
|
|
65
|
-
return String(v);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Phase 20 W2 B6 — `--from-file <path>` loader.
|
|
3
|
-
*
|
|
4
|
-
* JSON is handled natively. YAML support is optional: if `js-yaml` is
|
|
5
|
-
* installed in the user's environment we delegate to it, otherwise we
|
|
6
|
-
* throw a clear error asking them to either convert to JSON or install
|
|
7
|
-
* the optional peer.
|
|
8
|
-
*/
|
|
9
|
-
export declare function loadFromFile<T = unknown>(filePath: string): T;
|
package/dist/utils/from-file.js
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Phase 20 W2 B6 — `--from-file <path>` loader.
|
|
4
|
-
*
|
|
5
|
-
* JSON is handled natively. YAML support is optional: if `js-yaml` is
|
|
6
|
-
* installed in the user's environment we delegate to it, otherwise we
|
|
7
|
-
* throw a clear error asking them to either convert to JSON or install
|
|
8
|
-
* the optional peer.
|
|
9
|
-
*/
|
|
10
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
-
if (k2 === undefined) k2 = k;
|
|
12
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
-
}
|
|
16
|
-
Object.defineProperty(o, k2, desc);
|
|
17
|
-
}) : (function(o, m, k, k2) {
|
|
18
|
-
if (k2 === undefined) k2 = k;
|
|
19
|
-
o[k2] = m[k];
|
|
20
|
-
}));
|
|
21
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
22
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
23
|
-
}) : function(o, v) {
|
|
24
|
-
o["default"] = v;
|
|
25
|
-
});
|
|
26
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
27
|
-
var ownKeys = function(o) {
|
|
28
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
29
|
-
var ar = [];
|
|
30
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
31
|
-
return ar;
|
|
32
|
-
};
|
|
33
|
-
return ownKeys(o);
|
|
34
|
-
};
|
|
35
|
-
return function (mod) {
|
|
36
|
-
if (mod && mod.__esModule) return mod;
|
|
37
|
-
var result = {};
|
|
38
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
39
|
-
__setModuleDefault(result, mod);
|
|
40
|
-
return result;
|
|
41
|
-
};
|
|
42
|
-
})();
|
|
43
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
-
exports.loadFromFile = loadFromFile;
|
|
45
|
-
const fs = __importStar(require("fs"));
|
|
46
|
-
const path = __importStar(require("path"));
|
|
47
|
-
function loadFromFile(filePath) {
|
|
48
|
-
const resolved = path.resolve(filePath);
|
|
49
|
-
if (!fs.existsSync(resolved)) {
|
|
50
|
-
throw new Error(`File not found: ${resolved}`);
|
|
51
|
-
}
|
|
52
|
-
const raw = fs.readFileSync(resolved, 'utf8');
|
|
53
|
-
const ext = path.extname(resolved).toLowerCase();
|
|
54
|
-
if (ext === '.json') {
|
|
55
|
-
return JSON.parse(raw);
|
|
56
|
-
}
|
|
57
|
-
if (ext === '.yaml' || ext === '.yml') {
|
|
58
|
-
try {
|
|
59
|
-
// Optional peer dep — loaded lazily so JSON users don't need it.
|
|
60
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
61
|
-
const yaml = require('js-yaml');
|
|
62
|
-
return yaml.load(raw);
|
|
63
|
-
}
|
|
64
|
-
catch (err) {
|
|
65
|
-
throw new Error(`YAML support requires the optional \`js-yaml\` package. ` +
|
|
66
|
-
`Install it with \`npm i -g js-yaml\` or convert the file to JSON. ` +
|
|
67
|
-
`(${err.message})`);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
// Default to JSON if extension is unknown.
|
|
71
|
-
return JSON.parse(raw);
|
|
72
|
-
}
|
package/dist/utils/redact.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CLI@0.4.4 — sensitive-arg redaction helper.
|
|
3
|
-
*
|
|
4
|
-
* Used before any debug/log/telemetry path that might serialize CLI args.
|
|
5
|
-
* Mask any key whose name contains password / token / secret / api-key / authorization
|
|
6
|
-
* (case-insensitive). Returns a shallow clone with offending values replaced
|
|
7
|
-
* by `***REDACTED***` (or `undefined` when the original was falsy, so the log
|
|
8
|
-
* does not imply a value was present).
|
|
9
|
-
*/
|
|
10
|
-
export declare function redactSensitiveArgs<T extends Record<string, unknown>>(args: T): T;
|
|
11
|
-
/**
|
|
12
|
-
* Convenience: produce a JSON string with sensitive fields redacted.
|
|
13
|
-
*/
|
|
14
|
-
export declare function safeStringifyArgs(args: Record<string, unknown>): string;
|
package/dist/utils/redact.js
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* CLI@0.4.4 — sensitive-arg redaction helper.
|
|
4
|
-
*
|
|
5
|
-
* Used before any debug/log/telemetry path that might serialize CLI args.
|
|
6
|
-
* Mask any key whose name contains password / token / secret / api-key / authorization
|
|
7
|
-
* (case-insensitive). Returns a shallow clone with offending values replaced
|
|
8
|
-
* by `***REDACTED***` (or `undefined` when the original was falsy, so the log
|
|
9
|
-
* does not imply a value was present).
|
|
10
|
-
*/
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.redactSensitiveArgs = redactSensitiveArgs;
|
|
13
|
-
exports.safeStringifyArgs = safeStringifyArgs;
|
|
14
|
-
const SENSITIVE_KEY_RX = /(password|passwd|pwd|token|secret|api[_-]?key|authorization|auth[_-]?token|access[_-]?key|private[_-]?key|client[_-]?secret|session[_-]?token)/i;
|
|
15
|
-
function redactSensitiveArgs(args) {
|
|
16
|
-
if (!args || typeof args !== 'object')
|
|
17
|
-
return args;
|
|
18
|
-
const out = Array.isArray(args)
|
|
19
|
-
? [...args]
|
|
20
|
-
: { ...args };
|
|
21
|
-
for (const k of Object.keys(out)) {
|
|
22
|
-
const v = out[k];
|
|
23
|
-
if (SENSITIVE_KEY_RX.test(k)) {
|
|
24
|
-
out[k] = v ? '***REDACTED***' : undefined;
|
|
25
|
-
continue;
|
|
26
|
-
}
|
|
27
|
-
// Recurse into nested objects (but not class instances / Buffers / Dates).
|
|
28
|
-
if (v &&
|
|
29
|
-
typeof v === 'object' &&
|
|
30
|
-
!Buffer.isBuffer(v) &&
|
|
31
|
-
!(v instanceof Date) &&
|
|
32
|
-
(Object.getPrototypeOf(v) === Object.prototype || Array.isArray(v))) {
|
|
33
|
-
out[k] = redactSensitiveArgs(v);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return out;
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Convenience: produce a JSON string with sensitive fields redacted.
|
|
40
|
-
*/
|
|
41
|
-
function safeStringifyArgs(args) {
|
|
42
|
-
try {
|
|
43
|
-
return JSON.stringify(redactSensitiveArgs(args));
|
|
44
|
-
}
|
|
45
|
-
catch {
|
|
46
|
-
return '[unserializable]';
|
|
47
|
-
}
|
|
48
|
-
}
|
package/dist/utils/ui.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export declare const green: (s: string) => string;
|
|
2
|
-
export declare const red: (s: string) => string;
|
|
3
|
-
export declare const yellow: (s: string) => string;
|
|
4
|
-
export declare const cyan: (s: string) => string;
|
|
5
|
-
export declare const bold: (s: string) => string;
|
|
6
|
-
export declare const dim: (s: string) => string;
|
|
7
|
-
export declare function success(msg: string): void;
|
|
8
|
-
export declare function error(msg: string): void;
|
|
9
|
-
export declare function warn(msg: string): void;
|
|
10
|
-
export declare function info(msg: string): void;
|
|
11
|
-
export declare function step(msg: string): void;
|
|
12
|
-
export declare function banner(): void;
|
|
13
|
-
export declare function prompt(question: string): Promise<string>;
|
|
14
|
-
export declare function promptSelect(question: string, options: string[]): Promise<number>;
|