@tiangong-lca/cli 0.0.22 → 0.0.24
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/README.md +23 -7
- package/dist/src/cli.js +25 -12
- package/dist/src/cli.js.map +1 -1
- package/dist/src/lib/dataset-maintenance-apply.js +274 -6
- package/dist/src/lib/dataset-maintenance-apply.js.map +1 -1
- package/dist/src/lib/dataset-maintenance-clear-account.js +121 -58
- package/dist/src/lib/dataset-maintenance-clear-account.js.map +1 -1
- package/dist/src/lib/dataset-maintenance-contract.js +126 -16
- package/dist/src/lib/dataset-maintenance-contract.js.map +1 -1
- package/dist/src/lib/dataset-maintenance-derivatives.js +265 -0
- package/dist/src/lib/dataset-maintenance-derivatives.js.map +1 -0
- package/dist/src/lib/dataset-maintenance-pagination.js +270 -0
- package/dist/src/lib/dataset-maintenance-pagination.js.map +1 -0
- package/dist/src/lib/dataset-maintenance-plan.js +41 -6
- package/dist/src/lib/dataset-maintenance-plan.js.map +1 -1
- package/dist/src/lib/dataset-maintenance-remote.js +76 -28
- package/dist/src/lib/dataset-maintenance-remote.js.map +1 -1
- package/dist/src/lib/dataset-maintenance-verify.js +314 -5
- package/dist/src/lib/dataset-maintenance-verify.js.map +1 -1
- package/package.json +1 -1
|
@@ -2,6 +2,7 @@ import path from 'node:path';
|
|
|
2
2
|
import { writeJsonArtifact } from './artifacts.js';
|
|
3
3
|
import { deleteDatasetRecord, deriveSupabaseFunctionsBaseUrl, } from './dataset-command.js';
|
|
4
4
|
import { CliError } from './errors.js';
|
|
5
|
+
import { buildSnapshotCompleteness, fetchCompletePostgrestPages, } from './dataset-maintenance-pagination.js';
|
|
5
6
|
import { buildSupabaseAuthHeaders, deriveSupabaseProjectBaseUrl, requireSupabaseRestRuntime, } from './supabase-client.js';
|
|
6
7
|
import { resolveSupabaseUserSession } from './supabase-session.js';
|
|
7
8
|
const CLEAR_ACCOUNT_TABLES = [
|
|
@@ -151,43 +152,66 @@ async function fetchCurrentUser(options) {
|
|
|
151
152
|
};
|
|
152
153
|
}
|
|
153
154
|
async function fetchTableRows(options) {
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
exitCode: 1,
|
|
177
|
-
details: response.body,
|
|
155
|
+
const result = await fetchCompletePostgrestPages({
|
|
156
|
+
table: options.table,
|
|
157
|
+
requestedPageSize: options.pageSize,
|
|
158
|
+
rowIdentity: (row) => `${row.id}\u0000${row.version}`,
|
|
159
|
+
fetchPage: async (offset) => {
|
|
160
|
+
const url = buildTableFilterUrl(options);
|
|
161
|
+
url.searchParams.set('order', 'id.asc,version.asc');
|
|
162
|
+
url.searchParams.set('limit', String(options.pageSize));
|
|
163
|
+
url.searchParams.set('offset', String(offset));
|
|
164
|
+
const sourceUrl = url.toString();
|
|
165
|
+
const response = await fetchJson({
|
|
166
|
+
url: sourceUrl,
|
|
167
|
+
init: {
|
|
168
|
+
method: 'GET',
|
|
169
|
+
headers: {
|
|
170
|
+
...buildSupabaseAuthHeaders(options.publishableKey, options.accessToken),
|
|
171
|
+
Prefer: 'count=exact',
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
fetchImpl: options.fetchImpl,
|
|
175
|
+
timeoutMs: options.timeoutMs,
|
|
176
|
+
label: `${options.table} RLS visible snapshot`,
|
|
178
177
|
});
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
178
|
+
if (!Array.isArray(response.body)) {
|
|
179
|
+
throw new CliError(`Remote ${options.table} snapshot response was not an array.`, {
|
|
180
|
+
code: 'DATASET_MAINTENANCE_SNAPSHOT_INVALID',
|
|
181
|
+
exitCode: 1,
|
|
182
|
+
details: response.body,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
const pageRows = response.body.map((row) => normalizeRow(options.table, row));
|
|
186
|
+
if (pageRows.some((row) => row === null || !row.id || !row.version || row.user_id !== options.userId)) {
|
|
187
|
+
throw new CliError(`Remote ${options.table} snapshot contained an invalid account row.`, {
|
|
188
|
+
code: 'DATASET_MAINTENANCE_SNAPSHOT_INVALID',
|
|
189
|
+
exitCode: 1,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
return {
|
|
193
|
+
rows: pageRows,
|
|
194
|
+
source_url: sourceUrl,
|
|
195
|
+
content_range: response.headers.get('content-range'),
|
|
196
|
+
};
|
|
197
|
+
},
|
|
198
|
+
});
|
|
199
|
+
return { rows: result.rows, sourceUrls: result.source_urls, completeness: result.completeness };
|
|
200
|
+
}
|
|
201
|
+
async function fetchAccountSnapshot(options) {
|
|
202
|
+
const tables = await Promise.all(CLEAR_ACCOUNT_TABLES.map(async (table) => ({
|
|
203
|
+
table,
|
|
204
|
+
...(await fetchTableRows({ ...options, table })),
|
|
205
|
+
})));
|
|
206
|
+
return {
|
|
207
|
+
tables,
|
|
208
|
+
rows: tables.flatMap((table) => table.rows),
|
|
209
|
+
completeness: buildSnapshotCompleteness({
|
|
210
|
+
tables: CLEAR_ACCOUNT_TABLES,
|
|
211
|
+
requestedPageSize: options.pageSize,
|
|
212
|
+
results: tables,
|
|
213
|
+
}),
|
|
214
|
+
};
|
|
191
215
|
}
|
|
192
216
|
async function deleteTableRows(options) {
|
|
193
217
|
const deleteUrl = `${options.transport.functionsBaseUrl}/app_dataset_delete`;
|
|
@@ -226,7 +250,7 @@ async function deleteTableRows(options) {
|
|
|
226
250
|
}
|
|
227
251
|
return { deletedRows, deleteUrl, failures };
|
|
228
252
|
}
|
|
229
|
-
function buildSummary(tables) {
|
|
253
|
+
function buildSummary(tables, additionalFailures = 0) {
|
|
230
254
|
const byTable = Object.fromEntries(CLEAR_ACCOUNT_TABLES.map((table) => {
|
|
231
255
|
const report = tables.find((entry) => entry.table === table);
|
|
232
256
|
return [
|
|
@@ -243,7 +267,7 @@ function buildSummary(tables) {
|
|
|
243
267
|
total_candidates: tables.reduce((sum, table) => sum + table.candidates, 0),
|
|
244
268
|
total_deleted: tables.reduce((sum, table) => sum + table.deleted, 0),
|
|
245
269
|
total_remaining: tables.reduce((sum, table) => sum + (table.remaining ?? 0), 0),
|
|
246
|
-
total_failures: tables.filter((table) => table.status === 'failed').length,
|
|
270
|
+
total_failures: tables.filter((table) => table.status === 'failed').length + additionalFailures,
|
|
247
271
|
by_table: byTable,
|
|
248
272
|
};
|
|
249
273
|
}
|
|
@@ -290,21 +314,19 @@ export async function runDatasetMaintenanceClearAccount(options) {
|
|
|
290
314
|
},
|
|
291
315
|
});
|
|
292
316
|
}
|
|
293
|
-
const
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
}));
|
|
307
|
-
const snapshotRows = snapshotTables.flatMap((table) => table.rows);
|
|
317
|
+
const initialSnapshot = await fetchAccountSnapshot({
|
|
318
|
+
restBaseUrl,
|
|
319
|
+
userId: currentUser.id,
|
|
320
|
+
stateCodes,
|
|
321
|
+
pageSize,
|
|
322
|
+
publishableKey: runtime.publishableKey,
|
|
323
|
+
accessToken: session.accessToken,
|
|
324
|
+
fetchImpl: options.fetchImpl,
|
|
325
|
+
timeoutMs,
|
|
326
|
+
});
|
|
327
|
+
const snapshotTables = initialSnapshot.tables;
|
|
328
|
+
const snapshotRows = initialSnapshot.rows;
|
|
329
|
+
const snapshotCompleteness = initialSnapshot.completeness;
|
|
308
330
|
const artifacts = {
|
|
309
331
|
rls_visible_snapshot: path.join(outDir, 'rls-visible-snapshot.json'),
|
|
310
332
|
dry_run_report: path.join(outDir, 'dry-run-report.json'),
|
|
@@ -325,6 +347,7 @@ export async function runDatasetMaintenanceClearAccount(options) {
|
|
|
325
347
|
state_codes: stateCodes,
|
|
326
348
|
page_size: pageSize,
|
|
327
349
|
},
|
|
350
|
+
completeness: snapshotCompleteness,
|
|
328
351
|
row_count: snapshotRows.length,
|
|
329
352
|
rows: snapshotRows,
|
|
330
353
|
});
|
|
@@ -393,7 +416,7 @@ export async function runDatasetMaintenanceClearAccount(options) {
|
|
|
393
416
|
blockedByFailure = failed;
|
|
394
417
|
const failureDetails = deleteResult.failures
|
|
395
418
|
.slice(0, 5)
|
|
396
|
-
.map((failure) => `${failure.row.table}:${failure.row.id
|
|
419
|
+
.map((failure) => `${failure.row.table}:${failure.row.id}@${failure.row.version} ${failure.error}`);
|
|
397
420
|
tableReports.push({
|
|
398
421
|
table,
|
|
399
422
|
status: failed ? 'failed' : 'deleted',
|
|
@@ -429,14 +452,46 @@ export async function runDatasetMaintenanceClearAccount(options) {
|
|
|
429
452
|
});
|
|
430
453
|
}
|
|
431
454
|
}
|
|
432
|
-
|
|
455
|
+
let readbackCompleteness = null;
|
|
456
|
+
let readbackError = null;
|
|
457
|
+
if (commit) {
|
|
458
|
+
try {
|
|
459
|
+
const finalReadback = await fetchAccountSnapshot({
|
|
460
|
+
restBaseUrl,
|
|
461
|
+
userId: currentUser.id,
|
|
462
|
+
stateCodes,
|
|
463
|
+
pageSize,
|
|
464
|
+
publishableKey: runtime.publishableKey,
|
|
465
|
+
accessToken: session.accessToken,
|
|
466
|
+
fetchImpl: options.fetchImpl,
|
|
467
|
+
timeoutMs,
|
|
468
|
+
});
|
|
469
|
+
readbackCompleteness = finalReadback.completeness;
|
|
470
|
+
for (const table of CLEAR_ACCOUNT_TABLES) {
|
|
471
|
+
const tableReadback = finalReadback.tables.find((entry) => entry.table === table);
|
|
472
|
+
const tableReport = tableReports.find((entry) => entry.table === table);
|
|
473
|
+
tableReport.remaining = tableReadback.rows.length;
|
|
474
|
+
tableReport.source_urls.push(...tableReadback.sourceUrls);
|
|
475
|
+
if (tableReadback.rows.length > 0) {
|
|
476
|
+
const message = `${tableReadback.rows.length} row(s) remained in the final all-table readback.`;
|
|
477
|
+
tableReport.status = 'failed';
|
|
478
|
+
tableReport.error = [tableReport.error, message].filter(Boolean).join(' ');
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
catch (error) {
|
|
483
|
+
readbackError = `Final all-table readback could not prove account state: ${caughtErrorMessage(error)}`;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
const summary = buildSummary(tableReports, readbackError ? 1 : 0);
|
|
487
|
+
const finalReadbackPassed = readbackCompleteness !== null && readbackCompleteness.row_count === 0;
|
|
433
488
|
const report = {
|
|
434
489
|
schema_version: 1,
|
|
435
490
|
generated_at_utc: generatedAtUtc,
|
|
436
491
|
status: commit
|
|
437
|
-
? summary.total_failures
|
|
438
|
-
? '
|
|
439
|
-
: '
|
|
492
|
+
? summary.total_failures === 0 && summary.total_remaining === 0 && finalReadbackPassed
|
|
493
|
+
? 'cleared_account'
|
|
494
|
+
: 'completed_with_failures'
|
|
440
495
|
: 'planned_account_clear',
|
|
441
496
|
mode: commit ? 'commit' : 'dry-run',
|
|
442
497
|
account: {
|
|
@@ -449,6 +504,9 @@ export async function runDatasetMaintenanceClearAccount(options) {
|
|
|
449
504
|
state_codes: stateCodes,
|
|
450
505
|
page_size: pageSize,
|
|
451
506
|
},
|
|
507
|
+
snapshot_completeness: snapshotCompleteness,
|
|
508
|
+
readback_completeness: readbackCompleteness,
|
|
509
|
+
readback_error: readbackError,
|
|
452
510
|
summary,
|
|
453
511
|
tables: tableReports,
|
|
454
512
|
artifacts,
|
|
@@ -470,12 +528,16 @@ export async function runDatasetMaintenanceClearAccount(options) {
|
|
|
470
528
|
confirmed_email: options.confirm,
|
|
471
529
|
filters: report.filters,
|
|
472
530
|
candidate_count: summary.total_candidates,
|
|
531
|
+
snapshot_completeness: snapshotCompleteness,
|
|
473
532
|
});
|
|
474
533
|
writeJsonArtifact(artifacts.commit_report, report);
|
|
475
534
|
writeJsonArtifact(artifacts.readback_verify_report, {
|
|
476
535
|
schema_version: 1,
|
|
477
536
|
generated_at_utc: generatedAtUtc,
|
|
478
537
|
status: report.status,
|
|
538
|
+
initial_snapshot_completeness: snapshotCompleteness,
|
|
539
|
+
readback_completeness: readbackCompleteness,
|
|
540
|
+
readback_error: readbackError,
|
|
479
541
|
tables: tableReports.map((table) => ({
|
|
480
542
|
table: table.table,
|
|
481
543
|
candidates: table.candidates,
|
|
@@ -493,6 +555,7 @@ export const __testInternals = {
|
|
|
493
555
|
buildTableFilterUrl,
|
|
494
556
|
caughtErrorMessage,
|
|
495
557
|
deleteTableRows,
|
|
558
|
+
fetchAccountSnapshot,
|
|
496
559
|
fetchCurrentUser,
|
|
497
560
|
fetchJson,
|
|
498
561
|
fetchTableRows,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataset-maintenance-clear-account.js","sourceRoot":"","sources":["../../../src/lib/dataset-maintenance-clear-account.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'node:path';\nimport { writeJsonArtifact } from './artifacts.js';\nimport {\n deleteDatasetRecord,\n deriveSupabaseFunctionsBaseUrl,\n type DatasetCommandTransport,\n} from './dataset-command.js';\nimport { CliError } from './errors.js';\nimport type { FetchLike, ResponseLike } from './http.js';\nimport {\n buildSupabaseAuthHeaders,\n deriveSupabaseProjectBaseUrl,\n requireSupabaseRestRuntime,\n} from './supabase-client.js';\nimport { resolveSupabaseUserSession } from './supabase-session.js';\n\ntype JsonObject = Record<string, unknown>;\n\nexport type DatasetMaintenanceClearAccountTable =\n | 'lifecyclemodels'\n | 'processes'\n | 'flows'\n | 'sources'\n | 'contacts';\n\nexport type DatasetMaintenanceClearAccountRow = {\n table: DatasetMaintenanceClearAccountTable;\n id: string | null;\n version: string | null;\n user_id: string | null;\n state_code: number | null;\n modified_at: string | null;\n};\n\nexport type DatasetMaintenanceClearAccountTableReport = {\n table: DatasetMaintenanceClearAccountTable;\n status: 'dry_run' | 'skipped_empty' | 'deleted' | 'failed' | 'skipped_after_failure';\n candidates: number;\n deleted: number;\n remaining: number | null;\n source_urls: string[];\n delete_url: string | null;\n error: string | null;\n};\n\nexport type DatasetMaintenanceClearAccountReport = {\n schema_version: 1;\n generated_at_utc: string;\n status: 'planned_account_clear' | 'cleared_account' | 'completed_with_failures';\n mode: 'dry-run' | 'commit';\n account: {\n email: string;\n user_id: string;\n session_source: string;\n };\n filters: {\n tables: DatasetMaintenanceClearAccountTable[];\n state_codes: number[] | null;\n page_size: number;\n };\n summary: {\n total_candidates: number;\n total_deleted: number;\n total_remaining: number;\n total_failures: number;\n by_table: Record<\n DatasetMaintenanceClearAccountTable,\n {\n candidates: number;\n deleted: number;\n remaining: number | null;\n status: DatasetMaintenanceClearAccountTableReport['status'];\n }\n >;\n };\n tables: DatasetMaintenanceClearAccountTableReport[];\n artifacts: {\n rls_visible_snapshot: string;\n dry_run_report: string;\n approval_record: string | null;\n commit_report: string | null;\n readback_verify_report: string | null;\n };\n};\n\nexport type RunDatasetMaintenanceClearAccountOptions = {\n outDir?: string | null;\n stateCodes?: number[] | null;\n pageSize?: number;\n timeoutMs?: number;\n commit?: boolean;\n confirm?: string | null;\n env: NodeJS.ProcessEnv;\n fetchImpl: FetchLike;\n now?: Date;\n};\n\nconst CLEAR_ACCOUNT_TABLES: DatasetMaintenanceClearAccountTable[] = [\n 'lifecyclemodels',\n 'processes',\n 'flows',\n 'sources',\n 'contacts',\n];\n\nconst DEFAULT_PAGE_SIZE = 1_000;\nconst DEFAULT_TIMEOUT_MS = 10_000;\n\nfunction isRecord(value: unknown): value is JsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction trimToken(value: unknown): string | null {\n if (typeof value !== 'string') {\n return null;\n }\n\n const trimmed = value.trim();\n return trimmed ? trimmed : null;\n}\n\nfunction normalizeEmail(value: unknown): string {\n return typeof value === 'string' ? value.trim().toLowerCase() : '';\n}\n\nfunction caughtErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction normalizeStateCode(value: unknown): number | null {\n if (typeof value === 'number' && Number.isInteger(value)) {\n return value;\n }\n\n if (typeof value === 'string' && /^-?\\d+$/u.test(value.trim())) {\n return Number.parseInt(value.trim(), 10);\n }\n\n return null;\n}\n\nfunction normalizeStateCodes(values: number[] | null | undefined): number[] | null {\n const normalized = [...new Set((values ?? []).filter((value) => Number.isInteger(value)))].sort(\n (left, right) => left - right,\n );\n return normalized.length > 0 ? normalized : null;\n}\n\nfunction normalizePageSize(value: number | undefined): number {\n if (value === undefined) {\n return DEFAULT_PAGE_SIZE;\n }\n\n if (!Number.isInteger(value) || value < 1 || value > 5_000) {\n throw new CliError('--page-size must be an integer between 1 and 5000.', {\n code: 'DATASET_MAINTENANCE_PAGE_SIZE_INVALID',\n exitCode: 2,\n details: value,\n });\n }\n\n return value;\n}\n\nfunction normalizeTimeoutMs(value: number | undefined): number {\n if (value === undefined) {\n return DEFAULT_TIMEOUT_MS;\n }\n\n if (!Number.isInteger(value) || value < 1) {\n throw new CliError('--timeout-ms must be a positive integer.', {\n code: 'DATASET_MAINTENANCE_TIMEOUT_INVALID',\n exitCode: 2,\n details: value,\n });\n }\n\n return value;\n}\n\nfunction normalizeRow(\n table: DatasetMaintenanceClearAccountTable,\n value: unknown,\n): DatasetMaintenanceClearAccountRow | null {\n if (!isRecord(value)) {\n return null;\n }\n\n const modifiedAt = trimToken(value.modified_at);\n return {\n table,\n id: trimToken(value.id),\n version: trimToken(value.version),\n user_id: trimToken(value.user_id),\n state_code: normalizeStateCode(value.state_code),\n modified_at: modifiedAt,\n };\n}\n\nfunction buildTableFilterUrl(options: {\n restBaseUrl: string;\n table: DatasetMaintenanceClearAccountTable;\n userId: string;\n stateCodes: number[] | null;\n}): URL {\n const url = new URL(`${options.restBaseUrl}/${options.table}`);\n url.searchParams.set('select', 'id,version,user_id,state_code,modified_at');\n url.searchParams.set('user_id', `eq.${options.userId}`);\n if (options.stateCodes) {\n url.searchParams.set('state_code', `in.(${options.stateCodes.join(',')})`);\n }\n return url;\n}\n\nasync function fetchJson(options: {\n url: string;\n init: RequestInit;\n fetchImpl: FetchLike;\n timeoutMs: number;\n label: string;\n}): Promise<{ body: unknown; headers: ResponseLike['headers'] }> {\n const response = await options.fetchImpl(options.url, {\n ...options.init,\n signal: AbortSignal.timeout(options.timeoutMs),\n });\n const rawText = await response.text();\n\n if (!response.ok) {\n throw new CliError(`HTTP ${response.status} returned from ${options.label}`, {\n code: 'DATASET_MAINTENANCE_REMOTE_REQUEST_FAILED',\n exitCode: 1,\n details: {\n url: options.url,\n body: rawText,\n },\n });\n }\n\n const trimmed = rawText.trim();\n if (!trimmed) {\n return { body: null, headers: response.headers };\n }\n\n try {\n return { body: JSON.parse(trimmed), headers: response.headers };\n } catch (error) {\n throw new CliError(`Remote response was not valid JSON for ${options.label}`, {\n code: 'DATASET_MAINTENANCE_REMOTE_INVALID_JSON',\n exitCode: 1,\n details: {\n url: options.url,\n error: String(error),\n },\n });\n }\n}\n\nasync function fetchCurrentUser(options: {\n projectBaseUrl: string;\n publishableKey: string;\n accessToken: string;\n fetchImpl: FetchLike;\n timeoutMs: number;\n}): Promise<{ id: string; email: string | null }> {\n const url = `${options.projectBaseUrl}/auth/v1/user`;\n const response = await fetchJson({\n url,\n init: {\n method: 'GET',\n headers: buildSupabaseAuthHeaders(options.publishableKey, options.accessToken),\n },\n fetchImpl: options.fetchImpl,\n timeoutMs: options.timeoutMs,\n label: 'supabase current-user lookup',\n });\n\n const body = isRecord(response.body) ? response.body : {};\n const id = trimToken(body.id);\n if (!id) {\n throw new CliError('Supabase current-user lookup succeeded without a user id.', {\n code: 'DATASET_MAINTENANCE_CURRENT_USER_ID_MISSING',\n exitCode: 1,\n });\n }\n\n return {\n id,\n email: trimToken(body.email),\n };\n}\n\nasync function fetchTableRows(options: {\n restBaseUrl: string;\n table: DatasetMaintenanceClearAccountTable;\n userId: string;\n stateCodes: number[] | null;\n pageSize: number;\n publishableKey: string;\n accessToken: string;\n fetchImpl: FetchLike;\n timeoutMs: number;\n}): Promise<{ rows: DatasetMaintenanceClearAccountRow[]; sourceUrls: string[] }> {\n const rows: DatasetMaintenanceClearAccountRow[] = [];\n const sourceUrls: string[] = [];\n let offset = 0;\n\n while (true) {\n const url = buildTableFilterUrl(options);\n url.searchParams.set('order', 'id.asc,version.asc');\n url.searchParams.set('limit', String(options.pageSize));\n url.searchParams.set('offset', String(offset));\n\n const sourceUrl = url.toString();\n const response = await fetchJson({\n url: sourceUrl,\n init: {\n method: 'GET',\n headers: buildSupabaseAuthHeaders(options.publishableKey, options.accessToken),\n },\n fetchImpl: options.fetchImpl,\n timeoutMs: options.timeoutMs,\n label: `${options.table} RLS visible snapshot`,\n });\n\n if (!Array.isArray(response.body)) {\n throw new CliError(`Remote ${options.table} snapshot response was not an array.`, {\n code: 'DATASET_MAINTENANCE_SNAPSHOT_INVALID',\n exitCode: 1,\n details: response.body,\n });\n }\n\n const pageRows = response.body\n .map((row) => normalizeRow(options.table, row))\n .filter((row): row is DatasetMaintenanceClearAccountRow => row !== null);\n rows.push(...pageRows);\n sourceUrls.push(sourceUrl);\n\n if (response.body.length < options.pageSize) {\n break;\n }\n\n offset += options.pageSize;\n }\n\n return { rows, sourceUrls };\n}\n\nasync function deleteTableRows(options: {\n transport: DatasetCommandTransport;\n table: DatasetMaintenanceClearAccountTable;\n rows: DatasetMaintenanceClearAccountRow[];\n}): Promise<{\n deletedRows: DatasetMaintenanceClearAccountRow[];\n deleteUrl: string;\n failures: Array<{ row: DatasetMaintenanceClearAccountRow; error: string }>;\n}> {\n const deleteUrl = `${options.transport.functionsBaseUrl}/app_dataset_delete`;\n const deletedRows: DatasetMaintenanceClearAccountRow[] = [];\n const failures: Array<{ row: DatasetMaintenanceClearAccountRow; error: string }> = [];\n\n for (const row of options.rows) {\n if (!row.id || !row.version) {\n failures.push({\n row,\n error: 'Row is missing id or version and cannot be deleted through app_dataset_delete.',\n });\n continue;\n }\n\n if (row.state_code !== 0) {\n failures.push({\n row,\n error: `Protected non-draft row state_code=${String(\n row.state_code,\n )}; cmd_dataset_delete only deletes draft rows.`,\n });\n continue;\n }\n\n try {\n await deleteDatasetRecord({\n transport: options.transport,\n table: options.table,\n id: row.id,\n version: row.version,\n });\n deletedRows.push(row);\n } catch (error) {\n failures.push({\n row,\n error: caughtErrorMessage(error),\n });\n }\n }\n\n return { deletedRows, deleteUrl, failures };\n}\n\nfunction buildSummary(\n tables: DatasetMaintenanceClearAccountTableReport[],\n): DatasetMaintenanceClearAccountReport['summary'] {\n const byTable = Object.fromEntries(\n CLEAR_ACCOUNT_TABLES.map((table) => {\n const report = tables.find((entry) => entry.table === table);\n return [\n table,\n {\n candidates: report?.candidates ?? 0,\n deleted: report?.deleted ?? 0,\n remaining: report?.remaining ?? null,\n status: report?.status ?? 'skipped_after_failure',\n },\n ];\n }),\n ) as DatasetMaintenanceClearAccountReport['summary']['by_table'];\n\n return {\n total_candidates: tables.reduce((sum, table) => sum + table.candidates, 0),\n total_deleted: tables.reduce((sum, table) => sum + table.deleted, 0),\n total_remaining: tables.reduce((sum, table) => sum + (table.remaining ?? 0), 0),\n total_failures: tables.filter((table) => table.status === 'failed').length,\n by_table: byTable,\n };\n}\n\nexport async function runDatasetMaintenanceClearAccount(\n options: RunDatasetMaintenanceClearAccountOptions,\n): Promise<DatasetMaintenanceClearAccountReport> {\n const now = options.now ?? new Date();\n const generatedAtUtc = now.toISOString();\n const pageSize = normalizePageSize(options.pageSize);\n const timeoutMs = normalizeTimeoutMs(options.timeoutMs);\n const stateCodes = normalizeStateCodes(options.stateCodes);\n const commit = Boolean(options.commit);\n const outDir = path.resolve(options.outDir ?? 'dataset-maintenance/clear-account');\n const runtime = requireSupabaseRestRuntime(options.env);\n const projectBaseUrl = deriveSupabaseProjectBaseUrl(runtime.apiBaseUrl);\n const restBaseUrl = `${projectBaseUrl}/rest/v1`;\n const functionsBaseUrl = deriveSupabaseFunctionsBaseUrl(runtime.apiBaseUrl);\n const session = await resolveSupabaseUserSession({\n runtime,\n fetchImpl: options.fetchImpl,\n timeoutMs,\n now,\n });\n const currentUser = await fetchCurrentUser({\n projectBaseUrl,\n publishableKey: runtime.publishableKey,\n accessToken: session.accessToken,\n fetchImpl: options.fetchImpl,\n timeoutMs,\n });\n const accountEmail = currentUser.email ?? session.userEmail;\n const commandTransport: DatasetCommandTransport = {\n functionsBaseUrl,\n publishableKey: runtime.publishableKey,\n accessToken: session.accessToken,\n fetchImpl: options.fetchImpl,\n timeoutMs,\n };\n\n if (commit && normalizeEmail(options.confirm) !== normalizeEmail(accountEmail)) {\n throw new CliError(\n '--commit requires --confirm to exactly match the current authenticated account email.',\n {\n code: 'DATASET_MAINTENANCE_CONFIRMATION_REQUIRED',\n exitCode: 2,\n details: {\n expected_email: accountEmail,\n received_email: options.confirm ?? null,\n },\n },\n );\n }\n\n const snapshotTables = await Promise.all(\n CLEAR_ACCOUNT_TABLES.map(async (table) => {\n const snapshot = await fetchTableRows({\n restBaseUrl,\n table,\n userId: currentUser.id,\n stateCodes,\n pageSize,\n publishableKey: runtime.publishableKey,\n accessToken: session.accessToken,\n fetchImpl: options.fetchImpl,\n timeoutMs,\n });\n return { table, ...snapshot };\n }),\n );\n\n const snapshotRows = snapshotTables.flatMap((table) => table.rows);\n const artifacts: DatasetMaintenanceClearAccountReport['artifacts'] = {\n rls_visible_snapshot: path.join(outDir, 'rls-visible-snapshot.json'),\n dry_run_report: path.join(outDir, 'dry-run-report.json'),\n approval_record: commit ? path.join(outDir, 'approval-record.json') : null,\n commit_report: commit ? path.join(outDir, 'commit-report.json') : null,\n readback_verify_report: commit ? path.join(outDir, 'readback-verify-report.json') : null,\n };\n\n writeJsonArtifact(artifacts.rls_visible_snapshot, {\n schema_version: 1,\n generated_at_utc: generatedAtUtc,\n account: {\n email: accountEmail,\n user_id: currentUser.id,\n session_source: session.source,\n },\n filters: {\n tables: CLEAR_ACCOUNT_TABLES,\n state_codes: stateCodes,\n page_size: pageSize,\n },\n row_count: snapshotRows.length,\n rows: snapshotRows,\n });\n\n const tableReports: DatasetMaintenanceClearAccountTableReport[] = [];\n let blockedByFailure = false;\n\n for (const table of CLEAR_ACCOUNT_TABLES) {\n const snapshot = snapshotTables.find((entry) => entry.table === table)!;\n\n if (!commit) {\n tableReports.push({\n table,\n status: 'dry_run',\n candidates: snapshot.rows.length,\n deleted: 0,\n remaining: null,\n source_urls: snapshot.sourceUrls,\n delete_url: null,\n error: null,\n });\n continue;\n }\n\n if (blockedByFailure) {\n tableReports.push({\n table,\n status: 'skipped_after_failure',\n candidates: snapshot.rows.length,\n deleted: 0,\n remaining: snapshot.rows.length,\n source_urls: snapshot.sourceUrls,\n delete_url: null,\n error: 'Skipped because an earlier table delete or readback verification failed.',\n });\n continue;\n }\n\n if (snapshot.rows.length === 0) {\n tableReports.push({\n table,\n status: 'skipped_empty',\n candidates: 0,\n deleted: 0,\n remaining: 0,\n source_urls: snapshot.sourceUrls,\n delete_url: null,\n error: null,\n });\n continue;\n }\n\n try {\n const deleteResult = await deleteTableRows({\n transport: commandTransport,\n table,\n rows: snapshot.rows,\n });\n const readback = await fetchTableRows({\n restBaseUrl,\n table,\n userId: currentUser.id,\n stateCodes,\n pageSize,\n publishableKey: runtime.publishableKey,\n accessToken: session.accessToken,\n fetchImpl: options.fetchImpl,\n timeoutMs,\n });\n const remaining = readback.rows.length;\n const failed = remaining > 0 || deleteResult.failures.length > 0;\n blockedByFailure = failed;\n const failureDetails = deleteResult.failures\n .slice(0, 5)\n .map(\n (failure) =>\n `${failure.row.table}:${failure.row.id ?? '?'}@${failure.row.version ?? '?'} ${\n failure.error\n }`,\n );\n\n tableReports.push({\n table,\n status: failed ? 'failed' : 'deleted',\n candidates: snapshot.rows.length,\n deleted: Math.max(snapshot.rows.length - remaining, deleteResult.deletedRows.length),\n remaining,\n source_urls: [...snapshot.sourceUrls, ...readback.sourceUrls],\n delete_url: deleteResult.deleteUrl,\n error: failed\n ? [\n deleteResult.failures.length > 0\n ? `${deleteResult.failures.length} row delete request(s) failed.`\n : null,\n remaining > 0 ? `${remaining} row(s) remained after delete readback.` : null,\n ...failureDetails,\n ]\n .filter((message): message is string => typeof message === 'string')\n .join(' ')\n : null,\n });\n } catch (error) {\n blockedByFailure = true;\n tableReports.push({\n table,\n status: 'failed',\n candidates: snapshot.rows.length,\n deleted: 0,\n remaining: snapshot.rows.length,\n source_urls: snapshot.sourceUrls,\n delete_url: null,\n error: caughtErrorMessage(error),\n });\n }\n }\n\n const summary = buildSummary(tableReports);\n const report: DatasetMaintenanceClearAccountReport = {\n schema_version: 1,\n generated_at_utc: generatedAtUtc,\n status: commit\n ? summary.total_failures > 0 || summary.total_remaining > 0\n ? 'completed_with_failures'\n : 'cleared_account'\n : 'planned_account_clear',\n mode: commit ? 'commit' : 'dry-run',\n account: {\n email: accountEmail,\n user_id: currentUser.id,\n session_source: session.source,\n },\n filters: {\n tables: CLEAR_ACCOUNT_TABLES,\n state_codes: stateCodes,\n page_size: pageSize,\n },\n summary,\n tables: tableReports,\n artifacts,\n };\n\n writeJsonArtifact(artifacts.dry_run_report, {\n ...report,\n mode: 'dry-run',\n status: 'planned_account_clear',\n });\n\n if (\n commit &&\n artifacts.approval_record &&\n artifacts.commit_report &&\n artifacts.readback_verify_report\n ) {\n writeJsonArtifact(artifacts.approval_record, {\n schema_version: 1,\n approved_at_utc: generatedAtUtc,\n operation: 'clear-account',\n account: report.account,\n confirmed_email: options.confirm,\n filters: report.filters,\n candidate_count: summary.total_candidates,\n });\n writeJsonArtifact(artifacts.commit_report, report);\n writeJsonArtifact(artifacts.readback_verify_report, {\n schema_version: 1,\n generated_at_utc: generatedAtUtc,\n status: report.status,\n tables: tableReports.map((table) => ({\n table: table.table,\n candidates: table.candidates,\n deleted: table.deleted,\n remaining: table.remaining,\n status: table.status,\n error: table.error,\n })),\n });\n }\n\n return report;\n}\n\nexport const __testInternals = {\n buildSummary,\n buildTableFilterUrl,\n caughtErrorMessage,\n deleteTableRows,\n fetchCurrentUser,\n fetchJson,\n fetchTableRows,\n normalizeEmail,\n normalizePageSize,\n normalizeRow,\n normalizeStateCode,\n normalizeStateCodes,\n normalizeTimeoutMs,\n};\n"]}
|
|
1
|
+
{"version":3,"file":"dataset-maintenance-clear-account.js","sourceRoot":"","sources":["../../../src/lib/dataset-maintenance-clear-account.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'node:path';\nimport { writeJsonArtifact } from './artifacts.js';\nimport {\n deleteDatasetRecord,\n deriveSupabaseFunctionsBaseUrl,\n type DatasetCommandTransport,\n} from './dataset-command.js';\nimport { CliError } from './errors.js';\nimport type { FetchLike, ResponseLike } from './http.js';\nimport {\n buildSnapshotCompleteness,\n fetchCompletePostgrestPages,\n type DatasetMaintenanceSnapshotCompleteness,\n type DatasetMaintenanceTableCompleteness,\n} from './dataset-maintenance-pagination.js';\nimport {\n buildSupabaseAuthHeaders,\n deriveSupabaseProjectBaseUrl,\n requireSupabaseRestRuntime,\n} from './supabase-client.js';\nimport { resolveSupabaseUserSession } from './supabase-session.js';\n\ntype JsonObject = Record<string, unknown>;\n\nexport type DatasetMaintenanceClearAccountTable =\n | 'lifecyclemodels'\n | 'processes'\n | 'flows'\n | 'sources'\n | 'contacts';\n\nexport type DatasetMaintenanceClearAccountRow = {\n table: DatasetMaintenanceClearAccountTable;\n id: string | null;\n version: string | null;\n user_id: string | null;\n state_code: number | null;\n modified_at: string | null;\n};\n\nexport type DatasetMaintenanceClearAccountTableReport = {\n table: DatasetMaintenanceClearAccountTable;\n status: 'dry_run' | 'skipped_empty' | 'deleted' | 'failed' | 'skipped_after_failure';\n candidates: number;\n deleted: number;\n remaining: number | null;\n source_urls: string[];\n delete_url: string | null;\n error: string | null;\n};\n\nexport type DatasetMaintenanceClearAccountReport = {\n schema_version: 1;\n generated_at_utc: string;\n status: 'planned_account_clear' | 'cleared_account' | 'completed_with_failures';\n mode: 'dry-run' | 'commit';\n account: {\n email: string;\n user_id: string;\n session_source: string;\n };\n filters: {\n tables: DatasetMaintenanceClearAccountTable[];\n state_codes: number[] | null;\n page_size: number;\n };\n snapshot_completeness: DatasetMaintenanceSnapshotCompleteness<DatasetMaintenanceClearAccountTable>;\n readback_completeness: DatasetMaintenanceSnapshotCompleteness<DatasetMaintenanceClearAccountTable> | null;\n readback_error: string | null;\n summary: {\n total_candidates: number;\n total_deleted: number;\n total_remaining: number;\n total_failures: number;\n by_table: Record<\n DatasetMaintenanceClearAccountTable,\n {\n candidates: number;\n deleted: number;\n remaining: number | null;\n status: DatasetMaintenanceClearAccountTableReport['status'];\n }\n >;\n };\n tables: DatasetMaintenanceClearAccountTableReport[];\n artifacts: {\n rls_visible_snapshot: string;\n dry_run_report: string;\n approval_record: string | null;\n commit_report: string | null;\n readback_verify_report: string | null;\n };\n};\n\nexport type RunDatasetMaintenanceClearAccountOptions = {\n outDir?: string | null;\n stateCodes?: number[] | null;\n pageSize?: number;\n timeoutMs?: number;\n commit?: boolean;\n confirm?: string | null;\n env: NodeJS.ProcessEnv;\n fetchImpl: FetchLike;\n now?: Date;\n};\n\nconst CLEAR_ACCOUNT_TABLES: DatasetMaintenanceClearAccountTable[] = [\n 'lifecyclemodels',\n 'processes',\n 'flows',\n 'sources',\n 'contacts',\n];\n\nconst DEFAULT_PAGE_SIZE = 1_000;\nconst DEFAULT_TIMEOUT_MS = 10_000;\n\nfunction isRecord(value: unknown): value is JsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction trimToken(value: unknown): string | null {\n if (typeof value !== 'string') {\n return null;\n }\n\n const trimmed = value.trim();\n return trimmed ? trimmed : null;\n}\n\nfunction normalizeEmail(value: unknown): string {\n return typeof value === 'string' ? value.trim().toLowerCase() : '';\n}\n\nfunction caughtErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction normalizeStateCode(value: unknown): number | null {\n if (typeof value === 'number' && Number.isInteger(value)) {\n return value;\n }\n\n if (typeof value === 'string' && /^-?\\d+$/u.test(value.trim())) {\n return Number.parseInt(value.trim(), 10);\n }\n\n return null;\n}\n\nfunction normalizeStateCodes(values: number[] | null | undefined): number[] | null {\n const normalized = [...new Set((values ?? []).filter((value) => Number.isInteger(value)))].sort(\n (left, right) => left - right,\n );\n return normalized.length > 0 ? normalized : null;\n}\n\nfunction normalizePageSize(value: number | undefined): number {\n if (value === undefined) {\n return DEFAULT_PAGE_SIZE;\n }\n\n if (!Number.isInteger(value) || value < 1 || value > 5_000) {\n throw new CliError('--page-size must be an integer between 1 and 5000.', {\n code: 'DATASET_MAINTENANCE_PAGE_SIZE_INVALID',\n exitCode: 2,\n details: value,\n });\n }\n\n return value;\n}\n\nfunction normalizeTimeoutMs(value: number | undefined): number {\n if (value === undefined) {\n return DEFAULT_TIMEOUT_MS;\n }\n\n if (!Number.isInteger(value) || value < 1) {\n throw new CliError('--timeout-ms must be a positive integer.', {\n code: 'DATASET_MAINTENANCE_TIMEOUT_INVALID',\n exitCode: 2,\n details: value,\n });\n }\n\n return value;\n}\n\nfunction normalizeRow(\n table: DatasetMaintenanceClearAccountTable,\n value: unknown,\n): DatasetMaintenanceClearAccountRow | null {\n if (!isRecord(value)) {\n return null;\n }\n\n const modifiedAt = trimToken(value.modified_at);\n return {\n table,\n id: trimToken(value.id),\n version: trimToken(value.version),\n user_id: trimToken(value.user_id),\n state_code: normalizeStateCode(value.state_code),\n modified_at: modifiedAt,\n };\n}\n\nfunction buildTableFilterUrl(options: {\n restBaseUrl: string;\n table: DatasetMaintenanceClearAccountTable;\n userId: string;\n stateCodes: number[] | null;\n}): URL {\n const url = new URL(`${options.restBaseUrl}/${options.table}`);\n url.searchParams.set('select', 'id,version,user_id,state_code,modified_at');\n url.searchParams.set('user_id', `eq.${options.userId}`);\n if (options.stateCodes) {\n url.searchParams.set('state_code', `in.(${options.stateCodes.join(',')})`);\n }\n return url;\n}\n\nasync function fetchJson(options: {\n url: string;\n init: RequestInit;\n fetchImpl: FetchLike;\n timeoutMs: number;\n label: string;\n}): Promise<{ body: unknown; headers: ResponseLike['headers'] }> {\n const response = await options.fetchImpl(options.url, {\n ...options.init,\n signal: AbortSignal.timeout(options.timeoutMs),\n });\n const rawText = await response.text();\n\n if (!response.ok) {\n throw new CliError(`HTTP ${response.status} returned from ${options.label}`, {\n code: 'DATASET_MAINTENANCE_REMOTE_REQUEST_FAILED',\n exitCode: 1,\n details: {\n url: options.url,\n body: rawText,\n },\n });\n }\n\n const trimmed = rawText.trim();\n if (!trimmed) {\n return { body: null, headers: response.headers };\n }\n\n try {\n return { body: JSON.parse(trimmed), headers: response.headers };\n } catch (error) {\n throw new CliError(`Remote response was not valid JSON for ${options.label}`, {\n code: 'DATASET_MAINTENANCE_REMOTE_INVALID_JSON',\n exitCode: 1,\n details: {\n url: options.url,\n error: String(error),\n },\n });\n }\n}\n\nasync function fetchCurrentUser(options: {\n projectBaseUrl: string;\n publishableKey: string;\n accessToken: string;\n fetchImpl: FetchLike;\n timeoutMs: number;\n}): Promise<{ id: string; email: string | null }> {\n const url = `${options.projectBaseUrl}/auth/v1/user`;\n const response = await fetchJson({\n url,\n init: {\n method: 'GET',\n headers: buildSupabaseAuthHeaders(options.publishableKey, options.accessToken),\n },\n fetchImpl: options.fetchImpl,\n timeoutMs: options.timeoutMs,\n label: 'supabase current-user lookup',\n });\n\n const body = isRecord(response.body) ? response.body : {};\n const id = trimToken(body.id);\n if (!id) {\n throw new CliError('Supabase current-user lookup succeeded without a user id.', {\n code: 'DATASET_MAINTENANCE_CURRENT_USER_ID_MISSING',\n exitCode: 1,\n });\n }\n\n return {\n id,\n email: trimToken(body.email),\n };\n}\n\nasync function fetchTableRows(options: {\n restBaseUrl: string;\n table: DatasetMaintenanceClearAccountTable;\n userId: string;\n stateCodes: number[] | null;\n pageSize: number;\n publishableKey: string;\n accessToken: string;\n fetchImpl: FetchLike;\n timeoutMs: number;\n}): Promise<{\n rows: DatasetMaintenanceClearAccountRow[];\n sourceUrls: string[];\n completeness: DatasetMaintenanceTableCompleteness;\n}> {\n const result = await fetchCompletePostgrestPages({\n table: options.table,\n requestedPageSize: options.pageSize,\n rowIdentity: (row: DatasetMaintenanceClearAccountRow) => `${row.id!}\\u0000${row.version!}`,\n fetchPage: async (offset) => {\n const url = buildTableFilterUrl(options);\n url.searchParams.set('order', 'id.asc,version.asc');\n url.searchParams.set('limit', String(options.pageSize));\n url.searchParams.set('offset', String(offset));\n\n const sourceUrl = url.toString();\n const response = await fetchJson({\n url: sourceUrl,\n init: {\n method: 'GET',\n headers: {\n ...buildSupabaseAuthHeaders(options.publishableKey, options.accessToken),\n Prefer: 'count=exact',\n },\n },\n fetchImpl: options.fetchImpl,\n timeoutMs: options.timeoutMs,\n label: `${options.table} RLS visible snapshot`,\n });\n\n if (!Array.isArray(response.body)) {\n throw new CliError(`Remote ${options.table} snapshot response was not an array.`, {\n code: 'DATASET_MAINTENANCE_SNAPSHOT_INVALID',\n exitCode: 1,\n details: response.body,\n });\n }\n\n const pageRows = response.body.map((row) => normalizeRow(options.table, row));\n if (\n pageRows.some(\n (row) => row === null || !row.id || !row.version || row.user_id !== options.userId,\n )\n ) {\n throw new CliError(`Remote ${options.table} snapshot contained an invalid account row.`, {\n code: 'DATASET_MAINTENANCE_SNAPSHOT_INVALID',\n exitCode: 1,\n });\n }\n return {\n rows: pageRows as DatasetMaintenanceClearAccountRow[],\n source_url: sourceUrl,\n content_range: response.headers.get('content-range'),\n };\n },\n });\n return { rows: result.rows, sourceUrls: result.source_urls, completeness: result.completeness };\n}\n\nasync function fetchAccountSnapshot(\n options: Omit<Parameters<typeof fetchTableRows>[0], 'table'>,\n): Promise<{\n tables: Array<{\n table: DatasetMaintenanceClearAccountTable;\n rows: DatasetMaintenanceClearAccountRow[];\n sourceUrls: string[];\n completeness: DatasetMaintenanceTableCompleteness;\n }>;\n rows: DatasetMaintenanceClearAccountRow[];\n completeness: DatasetMaintenanceSnapshotCompleteness<DatasetMaintenanceClearAccountTable>;\n}> {\n const tables = await Promise.all(\n CLEAR_ACCOUNT_TABLES.map(async (table) => ({\n table,\n ...(await fetchTableRows({ ...options, table })),\n })),\n );\n return {\n tables,\n rows: tables.flatMap((table) => table.rows),\n completeness: buildSnapshotCompleteness({\n tables: CLEAR_ACCOUNT_TABLES,\n requestedPageSize: options.pageSize,\n results: tables,\n }),\n };\n}\n\nasync function deleteTableRows(options: {\n transport: DatasetCommandTransport;\n table: DatasetMaintenanceClearAccountTable;\n rows: DatasetMaintenanceClearAccountRow[];\n}): Promise<{\n deletedRows: DatasetMaintenanceClearAccountRow[];\n deleteUrl: string;\n failures: Array<{ row: DatasetMaintenanceClearAccountRow; error: string }>;\n}> {\n const deleteUrl = `${options.transport.functionsBaseUrl}/app_dataset_delete`;\n const deletedRows: DatasetMaintenanceClearAccountRow[] = [];\n const failures: Array<{ row: DatasetMaintenanceClearAccountRow; error: string }> = [];\n\n for (const row of options.rows) {\n if (!row.id || !row.version) {\n failures.push({\n row,\n error: 'Row is missing id or version and cannot be deleted through app_dataset_delete.',\n });\n continue;\n }\n\n if (row.state_code !== 0) {\n failures.push({\n row,\n error: `Protected non-draft row state_code=${String(\n row.state_code,\n )}; cmd_dataset_delete only deletes draft rows.`,\n });\n continue;\n }\n\n try {\n await deleteDatasetRecord({\n transport: options.transport,\n table: options.table,\n id: row.id,\n version: row.version,\n });\n deletedRows.push(row);\n } catch (error) {\n failures.push({\n row,\n error: caughtErrorMessage(error),\n });\n }\n }\n\n return { deletedRows, deleteUrl, failures };\n}\n\nfunction buildSummary(\n tables: DatasetMaintenanceClearAccountTableReport[],\n additionalFailures = 0,\n): DatasetMaintenanceClearAccountReport['summary'] {\n const byTable = Object.fromEntries(\n CLEAR_ACCOUNT_TABLES.map((table) => {\n const report = tables.find((entry) => entry.table === table);\n return [\n table,\n {\n candidates: report?.candidates ?? 0,\n deleted: report?.deleted ?? 0,\n remaining: report?.remaining ?? null,\n status: report?.status ?? 'skipped_after_failure',\n },\n ];\n }),\n ) as DatasetMaintenanceClearAccountReport['summary']['by_table'];\n\n return {\n total_candidates: tables.reduce((sum, table) => sum + table.candidates, 0),\n total_deleted: tables.reduce((sum, table) => sum + table.deleted, 0),\n total_remaining: tables.reduce((sum, table) => sum + (table.remaining ?? 0), 0),\n total_failures: tables.filter((table) => table.status === 'failed').length + additionalFailures,\n by_table: byTable,\n };\n}\n\nexport async function runDatasetMaintenanceClearAccount(\n options: RunDatasetMaintenanceClearAccountOptions,\n): Promise<DatasetMaintenanceClearAccountReport> {\n const now = options.now ?? new Date();\n const generatedAtUtc = now.toISOString();\n const pageSize = normalizePageSize(options.pageSize);\n const timeoutMs = normalizeTimeoutMs(options.timeoutMs);\n const stateCodes = normalizeStateCodes(options.stateCodes);\n const commit = Boolean(options.commit);\n const outDir = path.resolve(options.outDir ?? 'dataset-maintenance/clear-account');\n const runtime = requireSupabaseRestRuntime(options.env);\n const projectBaseUrl = deriveSupabaseProjectBaseUrl(runtime.apiBaseUrl);\n const restBaseUrl = `${projectBaseUrl}/rest/v1`;\n const functionsBaseUrl = deriveSupabaseFunctionsBaseUrl(runtime.apiBaseUrl);\n const session = await resolveSupabaseUserSession({\n runtime,\n fetchImpl: options.fetchImpl,\n timeoutMs,\n now,\n });\n const currentUser = await fetchCurrentUser({\n projectBaseUrl,\n publishableKey: runtime.publishableKey,\n accessToken: session.accessToken,\n fetchImpl: options.fetchImpl,\n timeoutMs,\n });\n const accountEmail = currentUser.email ?? session.userEmail;\n const commandTransport: DatasetCommandTransport = {\n functionsBaseUrl,\n publishableKey: runtime.publishableKey,\n accessToken: session.accessToken,\n fetchImpl: options.fetchImpl,\n timeoutMs,\n };\n\n if (commit && normalizeEmail(options.confirm) !== normalizeEmail(accountEmail)) {\n throw new CliError(\n '--commit requires --confirm to exactly match the current authenticated account email.',\n {\n code: 'DATASET_MAINTENANCE_CONFIRMATION_REQUIRED',\n exitCode: 2,\n details: {\n expected_email: accountEmail,\n received_email: options.confirm ?? null,\n },\n },\n );\n }\n\n const initialSnapshot = await fetchAccountSnapshot({\n restBaseUrl,\n userId: currentUser.id,\n stateCodes,\n pageSize,\n publishableKey: runtime.publishableKey,\n accessToken: session.accessToken,\n fetchImpl: options.fetchImpl,\n timeoutMs,\n });\n const snapshotTables = initialSnapshot.tables;\n const snapshotRows = initialSnapshot.rows;\n const snapshotCompleteness = initialSnapshot.completeness;\n const artifacts: DatasetMaintenanceClearAccountReport['artifacts'] = {\n rls_visible_snapshot: path.join(outDir, 'rls-visible-snapshot.json'),\n dry_run_report: path.join(outDir, 'dry-run-report.json'),\n approval_record: commit ? path.join(outDir, 'approval-record.json') : null,\n commit_report: commit ? path.join(outDir, 'commit-report.json') : null,\n readback_verify_report: commit ? path.join(outDir, 'readback-verify-report.json') : null,\n };\n\n writeJsonArtifact(artifacts.rls_visible_snapshot, {\n schema_version: 1,\n generated_at_utc: generatedAtUtc,\n account: {\n email: accountEmail,\n user_id: currentUser.id,\n session_source: session.source,\n },\n filters: {\n tables: CLEAR_ACCOUNT_TABLES,\n state_codes: stateCodes,\n page_size: pageSize,\n },\n completeness: snapshotCompleteness,\n row_count: snapshotRows.length,\n rows: snapshotRows,\n });\n\n const tableReports: DatasetMaintenanceClearAccountTableReport[] = [];\n let blockedByFailure = false;\n\n for (const table of CLEAR_ACCOUNT_TABLES) {\n const snapshot = snapshotTables.find((entry) => entry.table === table)!;\n\n if (!commit) {\n tableReports.push({\n table,\n status: 'dry_run',\n candidates: snapshot.rows.length,\n deleted: 0,\n remaining: null,\n source_urls: snapshot.sourceUrls,\n delete_url: null,\n error: null,\n });\n continue;\n }\n\n if (blockedByFailure) {\n tableReports.push({\n table,\n status: 'skipped_after_failure',\n candidates: snapshot.rows.length,\n deleted: 0,\n remaining: snapshot.rows.length,\n source_urls: snapshot.sourceUrls,\n delete_url: null,\n error: 'Skipped because an earlier table delete or readback verification failed.',\n });\n continue;\n }\n\n if (snapshot.rows.length === 0) {\n tableReports.push({\n table,\n status: 'skipped_empty',\n candidates: 0,\n deleted: 0,\n remaining: 0,\n source_urls: snapshot.sourceUrls,\n delete_url: null,\n error: null,\n });\n continue;\n }\n\n try {\n const deleteResult = await deleteTableRows({\n transport: commandTransport,\n table,\n rows: snapshot.rows,\n });\n const readback = await fetchTableRows({\n restBaseUrl,\n table,\n userId: currentUser.id,\n stateCodes,\n pageSize,\n publishableKey: runtime.publishableKey,\n accessToken: session.accessToken,\n fetchImpl: options.fetchImpl,\n timeoutMs,\n });\n const remaining = readback.rows.length;\n const failed = remaining > 0 || deleteResult.failures.length > 0;\n blockedByFailure = failed;\n const failureDetails = deleteResult.failures\n .slice(0, 5)\n .map(\n (failure) =>\n `${failure.row.table}:${failure.row.id!}@${failure.row.version!} ${failure.error}`,\n );\n\n tableReports.push({\n table,\n status: failed ? 'failed' : 'deleted',\n candidates: snapshot.rows.length,\n deleted: Math.max(snapshot.rows.length - remaining, deleteResult.deletedRows.length),\n remaining,\n source_urls: [...snapshot.sourceUrls, ...readback.sourceUrls],\n delete_url: deleteResult.deleteUrl,\n error: failed\n ? [\n deleteResult.failures.length > 0\n ? `${deleteResult.failures.length} row delete request(s) failed.`\n : null,\n remaining > 0 ? `${remaining} row(s) remained after delete readback.` : null,\n ...failureDetails,\n ]\n .filter((message): message is string => typeof message === 'string')\n .join(' ')\n : null,\n });\n } catch (error) {\n blockedByFailure = true;\n tableReports.push({\n table,\n status: 'failed',\n candidates: snapshot.rows.length,\n deleted: 0,\n remaining: snapshot.rows.length,\n source_urls: snapshot.sourceUrls,\n delete_url: null,\n error: caughtErrorMessage(error),\n });\n }\n }\n\n let readbackCompleteness: DatasetMaintenanceClearAccountReport['readback_completeness'] = null;\n let readbackError: string | null = null;\n if (commit) {\n try {\n const finalReadback = await fetchAccountSnapshot({\n restBaseUrl,\n userId: currentUser.id,\n stateCodes,\n pageSize,\n publishableKey: runtime.publishableKey,\n accessToken: session.accessToken,\n fetchImpl: options.fetchImpl,\n timeoutMs,\n });\n readbackCompleteness = finalReadback.completeness;\n for (const table of CLEAR_ACCOUNT_TABLES) {\n const tableReadback = finalReadback.tables.find((entry) => entry.table === table)!;\n const tableReport = tableReports.find((entry) => entry.table === table)!;\n tableReport.remaining = tableReadback.rows.length;\n tableReport.source_urls.push(...tableReadback.sourceUrls);\n if (tableReadback.rows.length > 0) {\n const message = `${tableReadback.rows.length} row(s) remained in the final all-table readback.`;\n tableReport.status = 'failed';\n tableReport.error = [tableReport.error, message].filter(Boolean).join(' ');\n }\n }\n } catch (error) {\n readbackError = `Final all-table readback could not prove account state: ${caughtErrorMessage(\n error,\n )}`;\n }\n }\n\n const summary = buildSummary(tableReports, readbackError ? 1 : 0);\n const finalReadbackPassed = readbackCompleteness !== null && readbackCompleteness.row_count === 0;\n const report: DatasetMaintenanceClearAccountReport = {\n schema_version: 1,\n generated_at_utc: generatedAtUtc,\n status: commit\n ? summary.total_failures === 0 && summary.total_remaining === 0 && finalReadbackPassed\n ? 'cleared_account'\n : 'completed_with_failures'\n : 'planned_account_clear',\n mode: commit ? 'commit' : 'dry-run',\n account: {\n email: accountEmail,\n user_id: currentUser.id,\n session_source: session.source,\n },\n filters: {\n tables: CLEAR_ACCOUNT_TABLES,\n state_codes: stateCodes,\n page_size: pageSize,\n },\n snapshot_completeness: snapshotCompleteness,\n readback_completeness: readbackCompleteness,\n readback_error: readbackError,\n summary,\n tables: tableReports,\n artifacts,\n };\n\n writeJsonArtifact(artifacts.dry_run_report, {\n ...report,\n mode: 'dry-run',\n status: 'planned_account_clear',\n });\n\n if (\n commit &&\n artifacts.approval_record &&\n artifacts.commit_report &&\n artifacts.readback_verify_report\n ) {\n writeJsonArtifact(artifacts.approval_record, {\n schema_version: 1,\n approved_at_utc: generatedAtUtc,\n operation: 'clear-account',\n account: report.account,\n confirmed_email: options.confirm,\n filters: report.filters,\n candidate_count: summary.total_candidates,\n snapshot_completeness: snapshotCompleteness,\n });\n writeJsonArtifact(artifacts.commit_report, report);\n writeJsonArtifact(artifacts.readback_verify_report, {\n schema_version: 1,\n generated_at_utc: generatedAtUtc,\n status: report.status,\n initial_snapshot_completeness: snapshotCompleteness,\n readback_completeness: readbackCompleteness,\n readback_error: readbackError,\n tables: tableReports.map((table) => ({\n table: table.table,\n candidates: table.candidates,\n deleted: table.deleted,\n remaining: table.remaining,\n status: table.status,\n error: table.error,\n })),\n });\n }\n\n return report;\n}\n\nexport const __testInternals = {\n buildSummary,\n buildTableFilterUrl,\n caughtErrorMessage,\n deleteTableRows,\n fetchAccountSnapshot,\n fetchCurrentUser,\n fetchJson,\n fetchTableRows,\n normalizeEmail,\n normalizePageSize,\n normalizeRow,\n normalizeStateCode,\n normalizeStateCodes,\n normalizeTimeoutMs,\n};\n"]}
|