@gurulu/cli 0.4.7 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/LICENSE +92 -0
  2. package/README.md +35 -106
  3. package/dist/bin.d.ts +3 -0
  4. package/dist/bin.d.ts.map +1 -0
  5. package/dist/bin.js +25751 -0
  6. package/dist/commands/auth.d.ts +23 -20
  7. package/dist/commands/auth.d.ts.map +1 -0
  8. package/dist/commands/doctor.d.ts +20 -6
  9. package/dist/commands/doctor.d.ts.map +1 -0
  10. package/dist/commands/init.d.ts +33 -11
  11. package/dist/commands/init.d.ts.map +1 -0
  12. package/dist/commands/pull.d.ts +13 -0
  13. package/dist/commands/pull.d.ts.map +1 -0
  14. package/dist/commands/push.d.ts +40 -0
  15. package/dist/commands/push.d.ts.map +1 -0
  16. package/dist/commands/validate.d.ts +36 -0
  17. package/dist/commands/validate.d.ts.map +1 -0
  18. package/dist/index.d.ts +4 -1
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +25326 -876
  21. package/dist/lib/api.d.ts +139 -0
  22. package/dist/lib/api.d.ts.map +1 -0
  23. package/dist/lib/codegen.d.ts +4 -0
  24. package/dist/lib/codegen.d.ts.map +1 -0
  25. package/dist/lib/config.d.ts +43 -0
  26. package/dist/lib/config.d.ts.map +1 -0
  27. package/dist/lib/detect.d.ts +27 -0
  28. package/dist/lib/detect.d.ts.map +1 -0
  29. package/dist/lib/detect.js +106 -0
  30. package/dist/lib/exec-install.d.ts +21 -0
  31. package/dist/lib/exec-install.d.ts.map +1 -0
  32. package/dist/lib/install-plan.d.ts +25 -0
  33. package/dist/lib/install-plan.d.ts.map +1 -0
  34. package/dist/lib/install-plan.js +161 -0
  35. package/package.json +51 -20
  36. package/bin/gurulu.js +0 -2
  37. package/dist/api-client.d.ts +0 -33
  38. package/dist/api-client.js +0 -175
  39. package/dist/commands/add-server.d.ts +0 -9
  40. package/dist/commands/add-server.js +0 -162
  41. package/dist/commands/alerts.d.ts +0 -27
  42. package/dist/commands/alerts.js +0 -309
  43. package/dist/commands/api-keys.d.ts +0 -20
  44. package/dist/commands/api-keys.js +0 -130
  45. package/dist/commands/attribution.d.ts +0 -22
  46. package/dist/commands/attribution.js +0 -111
  47. package/dist/commands/audiences.d.ts +0 -23
  48. package/dist/commands/audiences.js +0 -243
  49. package/dist/commands/audit.d.ts +0 -20
  50. package/dist/commands/audit.js +0 -130
  51. package/dist/commands/auth.js +0 -249
  52. package/dist/commands/chat.d.ts +0 -19
  53. package/dist/commands/chat.js +0 -118
  54. package/dist/commands/config.d.ts +0 -10
  55. package/dist/commands/config.js +0 -92
  56. package/dist/commands/consent.d.ts +0 -27
  57. package/dist/commands/consent.js +0 -233
  58. package/dist/commands/conversion-paths.d.ts +0 -19
  59. package/dist/commands/conversion-paths.js +0 -55
  60. package/dist/commands/db.d.ts +0 -25
  61. package/dist/commands/db.js +0 -330
  62. package/dist/commands/destinations.d.ts +0 -20
  63. package/dist/commands/destinations.js +0 -191
  64. package/dist/commands/doctor.js +0 -360
  65. package/dist/commands/errors.d.ts +0 -27
  66. package/dist/commands/errors.js +0 -121
  67. package/dist/commands/events.d.ts +0 -33
  68. package/dist/commands/events.js +0 -371
  69. package/dist/commands/experiments.d.ts +0 -22
  70. package/dist/commands/experiments.js +0 -264
  71. package/dist/commands/funnels.d.ts +0 -17
  72. package/dist/commands/funnels.js +0 -203
  73. package/dist/commands/goals.d.ts +0 -18
  74. package/dist/commands/goals.js +0 -214
  75. package/dist/commands/heatmap.d.ts +0 -27
  76. package/dist/commands/heatmap.js +0 -112
  77. package/dist/commands/identity.d.ts +0 -29
  78. package/dist/commands/identity.js +0 -328
  79. package/dist/commands/init.js +0 -215
  80. package/dist/commands/insights.d.ts +0 -10
  81. package/dist/commands/insights.js +0 -77
  82. package/dist/commands/install.d.ts +0 -259
  83. package/dist/commands/install.js +0 -1590
  84. package/dist/commands/login.d.ts +0 -20
  85. package/dist/commands/login.js +0 -170
  86. package/dist/commands/logout.d.ts +0 -10
  87. package/dist/commands/logout.js +0 -41
  88. package/dist/commands/playground.d.ts +0 -11
  89. package/dist/commands/playground.js +0 -47
  90. package/dist/commands/releases.d.ts +0 -17
  91. package/dist/commands/releases.js +0 -54
  92. package/dist/commands/replay.d.ts +0 -18
  93. package/dist/commands/replay.js +0 -64
  94. package/dist/commands/secrets.d.ts +0 -19
  95. package/dist/commands/secrets.js +0 -145
  96. package/dist/commands/setup.d.ts +0 -21
  97. package/dist/commands/setup.js +0 -67
  98. package/dist/commands/sites.d.ts +0 -18
  99. package/dist/commands/sites.js +0 -139
  100. package/dist/commands/skad.d.ts +0 -18
  101. package/dist/commands/skad.js +0 -53
  102. package/dist/commands/sourcemap.d.ts +0 -33
  103. package/dist/commands/sourcemap.js +0 -204
  104. package/dist/commands/status.d.ts +0 -7
  105. package/dist/commands/status.js +0 -136
  106. package/dist/commands/upgrade.d.ts +0 -21
  107. package/dist/commands/upgrade.js +0 -183
  108. package/dist/commands/warehouse.d.ts +0 -20
  109. package/dist/commands/warehouse.js +0 -65
  110. package/dist/commands/warehouses.d.ts +0 -17
  111. package/dist/commands/warehouses.js +0 -182
  112. package/dist/commands/watch.d.ts +0 -45
  113. package/dist/commands/watch.js +0 -258
  114. package/dist/commands/whoami.d.ts +0 -9
  115. package/dist/commands/whoami.js +0 -50
  116. package/dist/config.d.ts +0 -75
  117. package/dist/config.js +0 -329
  118. package/dist/frameworks/detect.d.ts +0 -8
  119. package/dist/frameworks/detect.js +0 -458
  120. package/dist/install-intent-proposal.d.ts +0 -99
  121. package/dist/install-intent-proposal.js +0 -202
  122. package/dist/utils/api.d.ts +0 -20
  123. package/dist/utils/api.js +0 -47
  124. package/dist/utils/config.d.ts +0 -13
  125. package/dist/utils/config.js +0 -30
  126. package/dist/utils/confirm.d.ts +0 -17
  127. package/dist/utils/confirm.js +0 -40
  128. package/dist/utils/dry-run.d.ts +0 -20
  129. package/dist/utils/dry-run.js +0 -67
  130. package/dist/utils/from-file.d.ts +0 -9
  131. package/dist/utils/from-file.js +0 -72
  132. package/dist/utils/redact.d.ts +0 -14
  133. package/dist/utils/redact.js +0 -48
  134. package/dist/utils/ui.d.ts +0 -14
  135. package/dist/utils/ui.js +0 -59
  136. package/scripts/.gitkeep +0 -0
  137. package/scripts/README-gurulu-agentic-install.md +0 -114
  138. package/scripts/README-gurulu-scan.md +0 -98
  139. package/scripts/audit-cli-scopes.mjs +0 -204
  140. package/scripts/backfill-tenant-id.mjs +0 -172
  141. package/scripts/backfill-tenant-links.ts +0 -252
  142. package/scripts/backup-clickhouse.sh +0 -27
  143. package/scripts/backup-postgres.sh +0 -19
  144. package/scripts/bootstrap-runtime-schema.mjs +0 -87
  145. package/scripts/bootstrap-stripe.mjs +0 -158
  146. package/scripts/gurulu-agentic-install.lib.cjs +0 -762
  147. package/scripts/gurulu-agentic-install.mjs +0 -623
  148. package/scripts/gurulu-scan.lib.cjs +0 -1509
  149. package/scripts/gurulu-scan.mjs +0 -91
  150. package/scripts/gurulu-verify-install.lib.cjs +0 -334
  151. package/scripts/gurulu-verify-install.mjs +0 -59
  152. package/scripts/init-ssl.sh +0 -26
  153. package/scripts/migrate-flow-graph-enums.sh +0 -86
  154. package/scripts/monitor-disk.sh +0 -24
  155. package/scripts/patches/astro.patch.cjs +0 -74
  156. package/scripts/patches/auto-instrument/ast-helper.cjs +0 -480
  157. package/scripts/patches/auto-instrument/astro.cjs +0 -273
  158. package/scripts/patches/auto-instrument/express.cjs +0 -383
  159. package/scripts/patches/auto-instrument/fastify.cjs +0 -262
  160. package/scripts/patches/auto-instrument/hono.cjs +0 -392
  161. package/scripts/patches/auto-instrument/index.cjs +0 -80
  162. package/scripts/patches/auto-instrument/nestjs.cjs +0 -286
  163. package/scripts/patches/auto-instrument/nextjs-app-router.cjs +0 -345
  164. package/scripts/patches/auto-instrument/nextjs-pages.cjs +0 -361
  165. package/scripts/patches/auto-instrument/remix.cjs +0 -168
  166. package/scripts/patches/auto-instrument/sdk-helper-map.cjs +0 -241
  167. package/scripts/patches/auto-instrument/singleton-helper.cjs +0 -193
  168. package/scripts/patches/auto-instrument/sveltekit.cjs +0 -161
  169. package/scripts/patches/auto-instrument/vite-react.cjs +0 -37
  170. package/scripts/patches/auto-instrument/vue.cjs +0 -196
  171. package/scripts/patches/express.patch.cjs +0 -99
  172. package/scripts/patches/fastify.patch.cjs +0 -108
  173. package/scripts/patches/index.cjs +0 -300
  174. package/scripts/patches/nestjs.patch.cjs +0 -112
  175. package/scripts/patches/nextjs-app-router.patch.cjs +0 -97
  176. package/scripts/patches/nextjs-pages.patch.cjs +0 -97
  177. package/scripts/patches/remix.patch.cjs +0 -75
  178. package/scripts/patches/sveltekit.patch.cjs +0 -72
  179. package/scripts/patches/vite-react.patch.cjs +0 -73
  180. package/scripts/patches/vue.patch.cjs +0 -82
  181. package/scripts/renew-ssl.sh +0 -14
  182. package/scripts/resolve-migration.sh +0 -23
  183. package/scripts/seed-cli-dev-keys.mjs +0 -130
  184. package/scripts/seed-test-data.mjs +0 -391
  185. package/scripts/spike-browserless.ts +0 -65
  186. package/scripts/tenant-pivot-consistency-check.mjs +0 -205
  187. package/scripts/tenant-pivot-phase-3-cleanup.lib.cjs +0 -258
  188. package/scripts/tenant-pivot-phase-3-cleanup.mjs +0 -98
  189. package/scripts/test-identity-resolution.ts +0 -804
  190. package/scripts/validate-gurulu-schemas.mjs +0 -79
@@ -1,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
- }
@@ -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;
@@ -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;
@@ -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
- }
@@ -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>;
@@ -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
- }
@@ -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;
@@ -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;
@@ -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
- }
@@ -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;
@@ -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
- }
@@ -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>;