@gurulu/cli 0.4.7 → 1.0.0

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