@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,258 +0,0 @@
|
|
|
1
|
-
// tenant-pivot-phase-3-cleanup.lib.cjs — destructive-cleanup logic for the
|
|
2
|
-
// Phase 18 A4 tenant pivot phase 3 migration (drop `site_id` column).
|
|
3
|
-
//
|
|
4
|
-
// CommonJS so it can be `require()`-d by both the ESM CLI wrapper
|
|
5
|
-
// (`scripts/tenant-pivot-phase-3-cleanup.mjs`) and the ts-jest test
|
|
6
|
-
// (`tests/scripts-tenant-pivot-phase-3-cleanup.test.ts`). See the README
|
|
7
|
-
// header in the .mjs wrapper for the operator-facing contract.
|
|
8
|
-
//
|
|
9
|
-
// IMPORTANT: This module exposes pure helpers and a CLI orchestrator. None of
|
|
10
|
-
// it self-executes. The `.mjs` wrapper is the only thing with a top-level
|
|
11
|
-
// `runCli()` call, gated on `import.meta.url === process.argv[1]`.
|
|
12
|
-
|
|
13
|
-
'use strict';
|
|
14
|
-
|
|
15
|
-
const fs = require('node:fs').promises;
|
|
16
|
-
const path = require('node:path');
|
|
17
|
-
const readline = require('node:readline');
|
|
18
|
-
|
|
19
|
-
// ---------------------------------------------------------------------------
|
|
20
|
-
// Constants
|
|
21
|
-
// ---------------------------------------------------------------------------
|
|
22
|
-
|
|
23
|
-
// Every analytics table that still carries `site_id` after Phase 18 A4. See
|
|
24
|
-
// docker/clickhouse/init/01_schema.sql for the canonical column definitions.
|
|
25
|
-
// ORDER MATTERS for the dry-run output but not for execution.
|
|
26
|
-
const AFFECTED_TABLES = [
|
|
27
|
-
'events_raw',
|
|
28
|
-
'flow_session_events',
|
|
29
|
-
'journey_events',
|
|
30
|
-
'cross_property_journeys',
|
|
31
|
-
'inferred_events',
|
|
32
|
-
];
|
|
33
|
-
|
|
34
|
-
const LOG_PATH_DEFAULT = path.resolve(process.cwd(), 'logs', 'tenant-pivot-phase-3.log');
|
|
35
|
-
|
|
36
|
-
// ---------------------------------------------------------------------------
|
|
37
|
-
// Pure helpers
|
|
38
|
-
// ---------------------------------------------------------------------------
|
|
39
|
-
|
|
40
|
-
function buildDropColumnSql(table) {
|
|
41
|
-
if (!table || typeof table !== 'string') {
|
|
42
|
-
throw new Error('buildDropColumnSql: table is required');
|
|
43
|
-
}
|
|
44
|
-
// ClickHouse ALTER TABLE DROP COLUMN is implemented as a mutation on the
|
|
45
|
-
// affected parts. Destructive and irreversible without a backup.
|
|
46
|
-
return `ALTER TABLE ${table} DROP COLUMN IF EXISTS site_id`;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function buildRowCountSql(table) {
|
|
50
|
-
return `SELECT count() AS c FROM ${table}`;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function parseArgs(argv) {
|
|
54
|
-
const args = { apply: false, help: false, noConfirm: false };
|
|
55
|
-
for (let i = 2; i < argv.length; i++) {
|
|
56
|
-
const a = argv[i];
|
|
57
|
-
if (a === '--apply') args.apply = true;
|
|
58
|
-
else if (a === '--no-confirm') args.noConfirm = true;
|
|
59
|
-
else if (a === '--help' || a === '-h') args.help = true;
|
|
60
|
-
}
|
|
61
|
-
return args;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function printHelp(out) {
|
|
65
|
-
const log = out || console.log;
|
|
66
|
-
log(
|
|
67
|
-
[
|
|
68
|
-
'',
|
|
69
|
-
'Usage: node scripts/tenant-pivot-phase-3-cleanup.mjs [--apply] [--no-confirm]',
|
|
70
|
-
'',
|
|
71
|
-
' (default) DRY-RUN. Prints SQL + row counts. Touches nothing.',
|
|
72
|
-
' --apply Actually execute ALTER TABLE DROP COLUMN. Requires',
|
|
73
|
-
' an interactive `yes` confirmation from a human operator.',
|
|
74
|
-
' --no-confirm Skip the readline prompt (still requires --apply). For',
|
|
75
|
-
' automated test harnesses only — do NOT use in prod.',
|
|
76
|
-
'',
|
|
77
|
-
'⚠ This is a DESTRUCTIVE migration. Take a ClickHouse backup first.',
|
|
78
|
-
'',
|
|
79
|
-
].join('\n'),
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Real ClickHouse HTTP client — unit tests inject a stub via the runCli
|
|
84
|
-
// `queryFn` parameter so this is never actually invoked under jest.
|
|
85
|
-
async function clickhouseQuery(query, params = {}) {
|
|
86
|
-
const CLICKHOUSE_URL = process.env.CLICKHOUSE_URL || 'http://localhost:8123';
|
|
87
|
-
const CLICKHOUSE_DB = process.env.CLICKHOUSE_DATABASE || 'gurulu';
|
|
88
|
-
const url = new URL(CLICKHOUSE_URL);
|
|
89
|
-
url.searchParams.set('database', CLICKHOUSE_DB);
|
|
90
|
-
url.searchParams.set('default_format', 'JSON');
|
|
91
|
-
for (const [k, v] of Object.entries(params)) {
|
|
92
|
-
url.searchParams.set(`param_${k}`, String(v));
|
|
93
|
-
}
|
|
94
|
-
const res = await fetch(url.toString(), {
|
|
95
|
-
method: 'POST',
|
|
96
|
-
body: query,
|
|
97
|
-
headers: { 'Content-Type': 'text/plain' },
|
|
98
|
-
});
|
|
99
|
-
if (!res.ok) {
|
|
100
|
-
throw new Error(`ClickHouse error ${res.status}: ${await res.text()}`);
|
|
101
|
-
}
|
|
102
|
-
return res.json();
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
async function safeRowCount(table, queryFn) {
|
|
106
|
-
const fn = queryFn || clickhouseQuery;
|
|
107
|
-
try {
|
|
108
|
-
const res = await fn(buildRowCountSql(table));
|
|
109
|
-
const row = (res && res.data && res.data[0]) || {};
|
|
110
|
-
return Number(row.c != null ? row.c : (row.count != null ? row.count : 0));
|
|
111
|
-
} catch (_err) {
|
|
112
|
-
return null;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
async function buildPlan(queryFn) {
|
|
117
|
-
const plan = [];
|
|
118
|
-
for (const table of AFFECTED_TABLES) {
|
|
119
|
-
const rowCount = await safeRowCount(table, queryFn);
|
|
120
|
-
plan.push({ table, rowCount, sql: buildDropColumnSql(table) });
|
|
121
|
-
}
|
|
122
|
-
return plan;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
function renderPlan(plan, mode) {
|
|
126
|
-
const lines = [];
|
|
127
|
-
lines.push(`# tenant-pivot-phase-3-cleanup mode=${mode} ts=${new Date().toISOString()}`);
|
|
128
|
-
lines.push('');
|
|
129
|
-
lines.push('Affected tables:');
|
|
130
|
-
for (const step of plan) {
|
|
131
|
-
const rc =
|
|
132
|
-
step.rowCount === null || step.rowCount === undefined
|
|
133
|
-
? '(unknown)'
|
|
134
|
-
: Number(step.rowCount).toLocaleString();
|
|
135
|
-
lines.push(` • ${step.table} rows=${rc}`);
|
|
136
|
-
lines.push(` ${step.sql}`);
|
|
137
|
-
}
|
|
138
|
-
lines.push('');
|
|
139
|
-
return lines.join('\n');
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
async function appendLog(block, logPath) {
|
|
143
|
-
const target = logPath || LOG_PATH_DEFAULT;
|
|
144
|
-
await fs.mkdir(path.dirname(target), { recursive: true });
|
|
145
|
-
await fs.appendFile(target, block + '\n', 'utf8');
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// Interactive confirmation prompt. Defaults to a real readline interface;
|
|
149
|
-
// tests inject `promptFn` to avoid touching stdin.
|
|
150
|
-
async function confirmDestructive(promptFn) {
|
|
151
|
-
const ask =
|
|
152
|
-
promptFn ||
|
|
153
|
-
function defaultAsk(q) {
|
|
154
|
-
return new Promise((resolve) => {
|
|
155
|
-
const rl = readline.createInterface({
|
|
156
|
-
input: process.stdin,
|
|
157
|
-
output: process.stdout,
|
|
158
|
-
});
|
|
159
|
-
rl.question(q, (ans) => {
|
|
160
|
-
rl.close();
|
|
161
|
-
resolve(ans);
|
|
162
|
-
});
|
|
163
|
-
});
|
|
164
|
-
};
|
|
165
|
-
const answer = await ask(
|
|
166
|
-
'\n⚠ About to DROP COLUMN site_id from production analytics tables. Type "yes" to proceed: ',
|
|
167
|
-
);
|
|
168
|
-
return String(answer || '').trim().toLowerCase() === 'yes';
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// ---------------------------------------------------------------------------
|
|
172
|
-
// CLI orchestrator
|
|
173
|
-
// ---------------------------------------------------------------------------
|
|
174
|
-
|
|
175
|
-
async function runCli(opts) {
|
|
176
|
-
const o = opts || {};
|
|
177
|
-
const argv = o.argv || process.argv;
|
|
178
|
-
const queryFn = o.queryFn || clickhouseQuery;
|
|
179
|
-
const promptFn = o.promptFn;
|
|
180
|
-
const log = o.log || console.log;
|
|
181
|
-
const errorLog = o.errorLog || console.error;
|
|
182
|
-
const logPath = o.logPath || LOG_PATH_DEFAULT;
|
|
183
|
-
|
|
184
|
-
const args = parseArgs(argv);
|
|
185
|
-
if (args.help) {
|
|
186
|
-
printHelp(log);
|
|
187
|
-
return { ok: true, mode: 'help' };
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
const mode = args.apply ? 'APPLY' : 'DRY-RUN';
|
|
191
|
-
log(`[phase-3-cleanup] mode=${mode}`);
|
|
192
|
-
log('[phase-3-cleanup] ⚠ This script is destructive. See the README header.');
|
|
193
|
-
|
|
194
|
-
const plan = await buildPlan(queryFn);
|
|
195
|
-
const rendered = renderPlan(plan, mode);
|
|
196
|
-
log(rendered);
|
|
197
|
-
try {
|
|
198
|
-
await appendLog(rendered, logPath);
|
|
199
|
-
} catch (err) {
|
|
200
|
-
errorLog('[phase-3-cleanup] WARNING: failed to write migration log:', err);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
if (!args.apply) {
|
|
204
|
-
log('[phase-3-cleanup] dry-run complete. Re-run with --apply to actually drop columns.');
|
|
205
|
-
return { ok: true, mode: 'dry-run', plan };
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// --apply path: require either an interactive `yes` or the explicit
|
|
209
|
-
// --no-confirm test-only flag.
|
|
210
|
-
if (!args.noConfirm) {
|
|
211
|
-
const confirmed = await confirmDestructive(promptFn);
|
|
212
|
-
if (!confirmed) {
|
|
213
|
-
errorLog('[phase-3-cleanup] confirmation declined; nothing was changed.');
|
|
214
|
-
return { ok: false, mode: 'apply', reason: 'declined' };
|
|
215
|
-
}
|
|
216
|
-
} else {
|
|
217
|
-
log('[phase-3-cleanup] --no-confirm set: skipping interactive prompt (test mode).');
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
const executed = [];
|
|
221
|
-
for (const step of plan) {
|
|
222
|
-
log(`[phase-3-cleanup] APPLY ${step.table}`);
|
|
223
|
-
log(` ${step.sql}`);
|
|
224
|
-
try {
|
|
225
|
-
await queryFn(step.sql);
|
|
226
|
-
executed.push(Object.assign({}, step, { status: 'ok' }));
|
|
227
|
-
} catch (err) {
|
|
228
|
-
errorLog(`[phase-3-cleanup] FAILED on ${step.table}:`, err);
|
|
229
|
-
executed.push(Object.assign({}, step, { status: 'error', error: String(err) }));
|
|
230
|
-
break;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
await appendLog(
|
|
235
|
-
`# applied ts=${new Date().toISOString()}\n` +
|
|
236
|
-
executed.map((s) => ` ${s.status} ${s.table} :: ${s.sql}`).join('\n') +
|
|
237
|
-
'\n',
|
|
238
|
-
logPath,
|
|
239
|
-
);
|
|
240
|
-
|
|
241
|
-
return { ok: executed.every((s) => s.status === 'ok'), mode: 'apply', executed };
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
module.exports = {
|
|
245
|
-
AFFECTED_TABLES,
|
|
246
|
-
LOG_PATH_DEFAULT,
|
|
247
|
-
buildDropColumnSql,
|
|
248
|
-
buildRowCountSql,
|
|
249
|
-
parseArgs,
|
|
250
|
-
printHelp,
|
|
251
|
-
clickhouseQuery,
|
|
252
|
-
safeRowCount,
|
|
253
|
-
buildPlan,
|
|
254
|
-
renderPlan,
|
|
255
|
-
appendLog,
|
|
256
|
-
confirmDestructive,
|
|
257
|
-
runCli,
|
|
258
|
-
};
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* ============================================================================
|
|
4
|
-
* README — DO NOT RUN AUTOMATICALLY. EVER.
|
|
5
|
-
* ============================================================================
|
|
6
|
-
*
|
|
7
|
-
* Phase 18 A4 — Tenant pivot phase 3 cleanup script.
|
|
8
|
-
*
|
|
9
|
-
* This is a DESTRUCTIVE migration tool. It exists so an operator can, when
|
|
10
|
-
* they are ready, drop the obsolete `site_id` column from the ClickHouse
|
|
11
|
-
* analytics tables now that the tenant-first read path (Phase 18 A4) and
|
|
12
|
-
* the tenant-first write path (Phase 17 B1) are both in production.
|
|
13
|
-
*
|
|
14
|
-
* ⚠ This script must NEVER be invoked by CI, pre-commit, deploy hooks,
|
|
15
|
-
* ⚠ cron, AI agents, or anything other than a human operator who has
|
|
16
|
-
* ⚠ taken a verified ClickHouse backup and read PHASE-18-ROADMAP.md §A4.
|
|
17
|
-
*
|
|
18
|
-
* Default behaviour (no flags) is a SAFE DRY-RUN: it prints exactly the
|
|
19
|
-
* ALTER TABLE statements it would execute, fetches a current row count for
|
|
20
|
-
* every affected table, and writes a markdown-friendly migration log to
|
|
21
|
-
* `logs/tenant-pivot-phase-3.log`. It does NOT touch ClickHouse beyond the
|
|
22
|
-
* read-only `SELECT count()` queries.
|
|
23
|
-
*
|
|
24
|
-
* Passing `--apply` is the only way to actually run the destructive ALTER
|
|
25
|
-
* TABLE DROP COLUMN statements. The `--apply` path additionally requires an
|
|
26
|
-
* interactive `yes` typed at a confirmation prompt so an operator cannot
|
|
27
|
-
* fat-finger it from shell history.
|
|
28
|
-
*
|
|
29
|
-
* Affected tables (every analytics table that still carries `site_id` after
|
|
30
|
-
* Phase 18 A4 — see docker/clickhouse/init/01_schema.sql for the canonical
|
|
31
|
-
* list):
|
|
32
|
-
*
|
|
33
|
-
* • events_raw — primary fact table
|
|
34
|
-
* • flow_session_events — per-session ordered event tape
|
|
35
|
-
* • journey_events — cross-property event timeline (Phase 13)
|
|
36
|
-
* • cross_property_journeys — aggregated journey rollup (Phase 13)
|
|
37
|
-
* • inferred_events — server-derived event sink
|
|
38
|
-
*
|
|
39
|
-
* Usage:
|
|
40
|
-
*
|
|
41
|
-
* node scripts/tenant-pivot-phase-3-cleanup.mjs # dry-run (default)
|
|
42
|
-
* node scripts/tenant-pivot-phase-3-cleanup.mjs --apply # interactive destructive run
|
|
43
|
-
* node scripts/tenant-pivot-phase-3-cleanup.mjs --apply --no-confirm # test harness only
|
|
44
|
-
*
|
|
45
|
-
* Env:
|
|
46
|
-
* CLICKHOUSE_URL (default http://localhost:8123)
|
|
47
|
-
* CLICKHOUSE_DATABASE (default gurulu)
|
|
48
|
-
*
|
|
49
|
-
* The detection / orchestration logic lives in
|
|
50
|
-
* `scripts/tenant-pivot-phase-3-cleanup.lib.cjs` so it can be reused by the
|
|
51
|
-
* ts-jest test suite via `require()`. This wrapper exposes the same API as
|
|
52
|
-
* an ESM module and, when invoked directly, runs the CLI.
|
|
53
|
-
*
|
|
54
|
-
* IMPORTANT: Do not modify this script to auto-run. Do not add it to any
|
|
55
|
-
* workflow. The whole point of the human-in-the-loop confirmation is to
|
|
56
|
-
* guarantee an operator chose to drop the column.
|
|
57
|
-
* ============================================================================
|
|
58
|
-
*/
|
|
59
|
-
|
|
60
|
-
import { createRequire } from 'node:module';
|
|
61
|
-
import { fileURLToPath } from 'node:url';
|
|
62
|
-
|
|
63
|
-
const require = createRequire(import.meta.url);
|
|
64
|
-
const lib = require('./tenant-pivot-phase-3-cleanup.lib.cjs');
|
|
65
|
-
|
|
66
|
-
export const AFFECTED_TABLES = lib.AFFECTED_TABLES;
|
|
67
|
-
export const buildDropColumnSql = lib.buildDropColumnSql;
|
|
68
|
-
export const buildRowCountSql = lib.buildRowCountSql;
|
|
69
|
-
export const parseArgs = lib.parseArgs;
|
|
70
|
-
export const printHelp = lib.printHelp;
|
|
71
|
-
export const safeRowCount = lib.safeRowCount;
|
|
72
|
-
export const buildPlan = lib.buildPlan;
|
|
73
|
-
export const renderPlan = lib.renderPlan;
|
|
74
|
-
export const appendLog = lib.appendLog;
|
|
75
|
-
export const confirmDestructive = lib.confirmDestructive;
|
|
76
|
-
export const runCli = lib.runCli;
|
|
77
|
-
|
|
78
|
-
// CLI entry — only auto-runs when invoked directly via `node ...mjs`, not
|
|
79
|
-
// when imported by another module.
|
|
80
|
-
const isMain = (() => {
|
|
81
|
-
try {
|
|
82
|
-
return fileURLToPath(import.meta.url) === process.argv[1];
|
|
83
|
-
} catch {
|
|
84
|
-
return false;
|
|
85
|
-
}
|
|
86
|
-
})();
|
|
87
|
-
|
|
88
|
-
if (isMain) {
|
|
89
|
-
lib.runCli().then(
|
|
90
|
-
(r) => {
|
|
91
|
-
if (!r.ok) process.exitCode = 1;
|
|
92
|
-
},
|
|
93
|
-
(err) => {
|
|
94
|
-
console.error('[phase-3-cleanup] fatal:', err);
|
|
95
|
-
process.exitCode = 1;
|
|
96
|
-
},
|
|
97
|
-
);
|
|
98
|
-
}
|