postgresdk 0.18.26 → 0.18.28
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/dist/cli-utils.d.ts +14 -0
- package/dist/cli.js +102 -22
- package/dist/index.d.ts +3 -1
- package/dist/index.js +69 -11
- package/dist/utils.d.ts +10 -0
- package/package.json +1 -1
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Parse --force / -y / --yes from CLI args */
|
|
2
|
+
export declare function parseForceFlag(args: string[]): boolean;
|
|
3
|
+
/**
|
|
4
|
+
* For each stale file, prompt the user to confirm deletion (shadcn-style per-file).
|
|
5
|
+
* If `force` is true, all files are deleted without prompting.
|
|
6
|
+
* If stdout is not a TTY (e.g. CI), files are skipped with a warning unless `force` is true.
|
|
7
|
+
*
|
|
8
|
+
* Returns counts of deleted and skipped files.
|
|
9
|
+
*/
|
|
10
|
+
export declare function confirmAndDeleteStaleFiles(staleFiles: string[], force: boolean): Promise<{
|
|
11
|
+
deleted: number;
|
|
12
|
+
skipped: number;
|
|
13
|
+
filesDeleted: string[];
|
|
14
|
+
}>;
|
package/dist/cli.js
CHANGED
|
@@ -515,9 +515,21 @@ async function ensureDirs(dirs) {
|
|
|
515
515
|
for (const d of dirs)
|
|
516
516
|
await mkdir(d, { recursive: true });
|
|
517
517
|
}
|
|
518
|
-
async function
|
|
519
|
-
|
|
520
|
-
|
|
518
|
+
async function collectDirsRecursively(root) {
|
|
519
|
+
if (!existsSync(root))
|
|
520
|
+
return [];
|
|
521
|
+
const dirs = [root];
|
|
522
|
+
const entries = await readdir(root, { withFileTypes: true });
|
|
523
|
+
for (const entry of entries) {
|
|
524
|
+
if (!entry.isDirectory())
|
|
525
|
+
continue;
|
|
526
|
+
const sub = join(root, entry.name);
|
|
527
|
+
dirs.push(...await collectDirsRecursively(sub));
|
|
528
|
+
}
|
|
529
|
+
return dirs;
|
|
530
|
+
}
|
|
531
|
+
async function findStaleFiles(generatedPaths, dirsToScan) {
|
|
532
|
+
const stale = [];
|
|
521
533
|
for (const dir of dirsToScan) {
|
|
522
534
|
if (!existsSync(dir))
|
|
523
535
|
continue;
|
|
@@ -529,13 +541,11 @@ async function deleteStaleFiles(generatedPaths, dirsToScan) {
|
|
|
529
541
|
continue;
|
|
530
542
|
const fullPath = join(dir, entry.name);
|
|
531
543
|
if (!generatedPaths.has(fullPath)) {
|
|
532
|
-
|
|
533
|
-
deleted++;
|
|
534
|
-
filesDeleted.push(fullPath);
|
|
544
|
+
stale.push(fullPath);
|
|
535
545
|
}
|
|
536
546
|
}
|
|
537
547
|
}
|
|
538
|
-
return
|
|
548
|
+
return stale;
|
|
539
549
|
}
|
|
540
550
|
var pascal = (s) => s.split(/[_\s-]+/).map((w) => w?.[0] ? w[0].toUpperCase() + w.slice(1) : "").join("");
|
|
541
551
|
var init_utils = () => {};
|
|
@@ -1414,6 +1424,50 @@ var init_emit_sdk_contract = __esm(() => {
|
|
|
1414
1424
|
init_emit_include_methods();
|
|
1415
1425
|
});
|
|
1416
1426
|
|
|
1427
|
+
// src/cli-utils.ts
|
|
1428
|
+
import { unlink as unlink2 } from "fs/promises";
|
|
1429
|
+
import prompts from "prompts";
|
|
1430
|
+
function parseForceFlag(args) {
|
|
1431
|
+
return args.includes("--force") || args.includes("-y") || args.includes("--yes");
|
|
1432
|
+
}
|
|
1433
|
+
async function confirmAndDeleteStaleFiles(staleFiles, force) {
|
|
1434
|
+
if (staleFiles.length === 0)
|
|
1435
|
+
return { deleted: 0, skipped: 0, filesDeleted: [] };
|
|
1436
|
+
if (!force && !process.stdout.isTTY) {
|
|
1437
|
+
console.log(`⚠️ ${staleFiles.length} stale file(s) not deleted (non-interactive shell). Re-run with --force to delete.`);
|
|
1438
|
+
return { deleted: 0, skipped: staleFiles.length, filesDeleted: [] };
|
|
1439
|
+
}
|
|
1440
|
+
let deleted = 0;
|
|
1441
|
+
let skipped = 0;
|
|
1442
|
+
const filesDeleted = [];
|
|
1443
|
+
for (const filePath of staleFiles) {
|
|
1444
|
+
let shouldDelete = force;
|
|
1445
|
+
if (!force) {
|
|
1446
|
+
const { confirmed } = await prompts({
|
|
1447
|
+
type: "confirm",
|
|
1448
|
+
name: "confirmed",
|
|
1449
|
+
message: `Delete stale file: ${filePath}?`,
|
|
1450
|
+
initial: false
|
|
1451
|
+
});
|
|
1452
|
+
if (confirmed === undefined) {
|
|
1453
|
+
console.log("Stale file deletion aborted.");
|
|
1454
|
+
break;
|
|
1455
|
+
}
|
|
1456
|
+
shouldDelete = confirmed;
|
|
1457
|
+
}
|
|
1458
|
+
if (shouldDelete) {
|
|
1459
|
+
await unlink2(filePath);
|
|
1460
|
+
console.log(` ✗ ${filePath}`);
|
|
1461
|
+
filesDeleted.push(filePath);
|
|
1462
|
+
deleted++;
|
|
1463
|
+
} else {
|
|
1464
|
+
skipped++;
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
return { deleted, skipped, filesDeleted };
|
|
1468
|
+
}
|
|
1469
|
+
var init_cli_utils = () => {};
|
|
1470
|
+
|
|
1417
1471
|
// src/cli-config-utils.ts
|
|
1418
1472
|
function extractConfigFields(configContent) {
|
|
1419
1473
|
const fields = [];
|
|
@@ -1835,7 +1889,7 @@ __export(exports_cli_init, {
|
|
|
1835
1889
|
});
|
|
1836
1890
|
import { existsSync as existsSync3, writeFileSync, readFileSync as readFileSync2, copyFileSync } from "fs";
|
|
1837
1891
|
import { resolve } from "path";
|
|
1838
|
-
import
|
|
1892
|
+
import prompts2 from "prompts";
|
|
1839
1893
|
async function initCommand(args) {
|
|
1840
1894
|
console.log(`\uD83D\uDE80 Initializing postgresdk configuration...
|
|
1841
1895
|
`);
|
|
@@ -1860,7 +1914,7 @@ async function initCommand(args) {
|
|
|
1860
1914
|
}
|
|
1861
1915
|
});
|
|
1862
1916
|
console.log();
|
|
1863
|
-
const { mergeStrategy } = await
|
|
1917
|
+
const { mergeStrategy } = await prompts2({
|
|
1864
1918
|
type: "select",
|
|
1865
1919
|
name: "mergeStrategy",
|
|
1866
1920
|
message: "How would you like to proceed?",
|
|
@@ -1900,7 +1954,7 @@ async function initCommand(args) {
|
|
|
1900
1954
|
\uD83D\uDD04 Let's review your configuration:
|
|
1901
1955
|
`);
|
|
1902
1956
|
for (const field of existingFields.filter((f) => !f.isCommented)) {
|
|
1903
|
-
const { choice } = await
|
|
1957
|
+
const { choice } = await prompts2({
|
|
1904
1958
|
type: "select",
|
|
1905
1959
|
name: "choice",
|
|
1906
1960
|
message: `${field.description}:
|
|
@@ -1932,7 +1986,7 @@ async function initCommand(args) {
|
|
|
1932
1986
|
\uD83D\uDCE6 New configuration options available:
|
|
1933
1987
|
`);
|
|
1934
1988
|
for (const option of missingOptions) {
|
|
1935
|
-
const { addOption } = await
|
|
1989
|
+
const { addOption } = await prompts2({
|
|
1936
1990
|
type: "confirm",
|
|
1937
1991
|
name: "addOption",
|
|
1938
1992
|
message: `Add ${option.description} configuration? (commented out by default)`,
|
|
@@ -1971,7 +2025,7 @@ async function initCommand(args) {
|
|
|
1971
2025
|
} else if (isSdkSide) {
|
|
1972
2026
|
projectType = "sdk";
|
|
1973
2027
|
} else {
|
|
1974
|
-
const response = await
|
|
2028
|
+
const response = await prompts2({
|
|
1975
2029
|
type: "select",
|
|
1976
2030
|
name: "projectType",
|
|
1977
2031
|
message: "What type of project is this?",
|
|
@@ -2267,6 +2321,7 @@ async function pullCommand(args) {
|
|
|
2267
2321
|
console.error("⚠️ Failed to load config file:", err);
|
|
2268
2322
|
}
|
|
2269
2323
|
}
|
|
2324
|
+
const force = parseForceFlag(args);
|
|
2270
2325
|
const cliConfig = {
|
|
2271
2326
|
from: args.find((a) => a.startsWith("--from="))?.split("=")[1],
|
|
2272
2327
|
output: args.find((a) => a.startsWith("--output="))?.split("=")[1],
|
|
@@ -2328,8 +2383,9 @@ Options:`);
|
|
|
2328
2383
|
let filesWritten = 0;
|
|
2329
2384
|
let filesUnchanged = 0;
|
|
2330
2385
|
const changedFiles = [];
|
|
2386
|
+
const resolvedOutput = resolve2(config.output);
|
|
2331
2387
|
for (const [path, content] of Object.entries(sdk.files)) {
|
|
2332
|
-
const fullPath = join3(
|
|
2388
|
+
const fullPath = join3(resolvedOutput, path);
|
|
2333
2389
|
await mkdir2(dirname3(fullPath), { recursive: true });
|
|
2334
2390
|
let shouldWrite = true;
|
|
2335
2391
|
if (existsSync4(fullPath)) {
|
|
@@ -2346,7 +2402,11 @@ Options:`);
|
|
|
2346
2402
|
console.log(` ✓ ${path}`);
|
|
2347
2403
|
}
|
|
2348
2404
|
}
|
|
2349
|
-
const
|
|
2405
|
+
const generatedPaths = new Set(Object.keys(sdk.files).map((p) => join3(resolvedOutput, p)));
|
|
2406
|
+
const dirsToScan = await collectDirsRecursively(resolvedOutput);
|
|
2407
|
+
const staleFiles = await findStaleFiles(generatedPaths, dirsToScan);
|
|
2408
|
+
const deleteResult = await confirmAndDeleteStaleFiles(staleFiles, force);
|
|
2409
|
+
const metadataPath = join3(resolvedOutput, ".postgresdk.json");
|
|
2350
2410
|
const metadata = {
|
|
2351
2411
|
version: sdk.version,
|
|
2352
2412
|
pulledFrom: config.from
|
|
@@ -2361,18 +2421,30 @@ Options:`);
|
|
|
2361
2421
|
if (metadataChanged) {
|
|
2362
2422
|
await writeFile2(metadataPath, JSON.stringify(metadata, null, 2));
|
|
2363
2423
|
}
|
|
2364
|
-
if (filesWritten === 0 && !metadataChanged) {
|
|
2424
|
+
if (filesWritten === 0 && !metadataChanged && deleteResult.deleted === 0 && deleteResult.skipped === 0) {
|
|
2365
2425
|
console.log(`✅ SDK up-to-date (${filesUnchanged} files unchanged)`);
|
|
2366
2426
|
} else {
|
|
2427
|
+
const parts = [];
|
|
2428
|
+
if (filesWritten > 0)
|
|
2429
|
+
parts.push(`updated ${filesWritten} files`);
|
|
2430
|
+
if (deleteResult.deleted > 0)
|
|
2431
|
+
parts.push(`deleted ${deleteResult.deleted} stale files`);
|
|
2432
|
+
if (deleteResult.skipped > 0)
|
|
2433
|
+
parts.push(`skipped ${deleteResult.skipped} stale files`);
|
|
2434
|
+
if (filesUnchanged > 0)
|
|
2435
|
+
parts.push(`${filesUnchanged} unchanged`);
|
|
2367
2436
|
console.log(`✅ SDK pulled successfully to ${config.output}`);
|
|
2368
|
-
console.log(`
|
|
2437
|
+
console.log(` ${parts.join(", ")}`);
|
|
2369
2438
|
}
|
|
2370
2439
|
} catch (err) {
|
|
2371
2440
|
console.error(`❌ Pull failed:`, err);
|
|
2372
2441
|
process.exit(1);
|
|
2373
2442
|
}
|
|
2374
2443
|
}
|
|
2375
|
-
var init_cli_pull = () => {
|
|
2444
|
+
var init_cli_pull = __esm(() => {
|
|
2445
|
+
init_utils();
|
|
2446
|
+
init_cli_utils();
|
|
2447
|
+
});
|
|
2376
2448
|
|
|
2377
2449
|
// src/index.ts
|
|
2378
2450
|
var import_config = __toESM(require_config(), 1);
|
|
@@ -7082,6 +7154,7 @@ function generateTestCases(table, sampleData, updateData, hasForeignKeys = false
|
|
|
7082
7154
|
// src/index.ts
|
|
7083
7155
|
init_emit_sdk_contract();
|
|
7084
7156
|
init_utils();
|
|
7157
|
+
init_cli_utils();
|
|
7085
7158
|
var __filename2 = fileURLToPath(import.meta.url);
|
|
7086
7159
|
var __dirname2 = dirname2(__filename2);
|
|
7087
7160
|
var { version: CLI_VERSION } = JSON.parse(readFileSync(join2(__dirname2, "../package.json"), "utf-8"));
|
|
@@ -7091,7 +7164,7 @@ function resolveSoftDeleteColumn(cfg, tableName) {
|
|
|
7091
7164
|
return overrides[tableName] ?? null;
|
|
7092
7165
|
return cfg.softDeleteColumn ?? null;
|
|
7093
7166
|
}
|
|
7094
|
-
async function generate(configPath) {
|
|
7167
|
+
async function generate(configPath, options) {
|
|
7095
7168
|
if (!existsSync2(configPath)) {
|
|
7096
7169
|
throw new Error(`Config file not found: ${configPath}
|
|
7097
7170
|
|
|
@@ -7286,7 +7359,7 @@ async function generate(configPath) {
|
|
|
7286
7359
|
}
|
|
7287
7360
|
console.log("✍️ Writing files...");
|
|
7288
7361
|
const writeResult = await writeFilesIfChanged(files);
|
|
7289
|
-
let deleteResult = { deleted: 0, filesDeleted: [] };
|
|
7362
|
+
let deleteResult = { deleted: 0, skipped: 0, filesDeleted: [] };
|
|
7290
7363
|
if (cfg.clean !== false) {
|
|
7291
7364
|
const dirsToScan = [
|
|
7292
7365
|
serverDir,
|
|
@@ -7302,9 +7375,10 @@ async function generate(configPath) {
|
|
|
7302
7375
|
if (generateTests)
|
|
7303
7376
|
dirsToScan.push(testDir);
|
|
7304
7377
|
const generatedPaths = new Set(files.map((f) => f.path));
|
|
7305
|
-
|
|
7378
|
+
const staleFiles = await findStaleFiles(generatedPaths, dirsToScan);
|
|
7379
|
+
deleteResult = await confirmAndDeleteStaleFiles(staleFiles, options?.force ?? false);
|
|
7306
7380
|
}
|
|
7307
|
-
if (writeResult.written === 0 && deleteResult.deleted === 0) {
|
|
7381
|
+
if (writeResult.written === 0 && deleteResult.deleted === 0 && deleteResult.skipped === 0) {
|
|
7308
7382
|
console.log(`✅ All ${writeResult.unchanged} files up-to-date (no changes)`);
|
|
7309
7383
|
} else {
|
|
7310
7384
|
const parts = [];
|
|
@@ -7312,6 +7386,8 @@ async function generate(configPath) {
|
|
|
7312
7386
|
parts.push(`updated ${writeResult.written} files`);
|
|
7313
7387
|
if (deleteResult.deleted > 0)
|
|
7314
7388
|
parts.push(`deleted ${deleteResult.deleted} stale files`);
|
|
7389
|
+
if (deleteResult.skipped > 0)
|
|
7390
|
+
parts.push(`skipped ${deleteResult.skipped} stale files`);
|
|
7315
7391
|
if (writeResult.unchanged > 0)
|
|
7316
7392
|
parts.push(`${writeResult.unchanged} unchanged`);
|
|
7317
7393
|
console.log(`✅ ${parts.join(", ")}`);
|
|
@@ -7354,6 +7430,7 @@ import { resolve as resolve3 } from "node:path";
|
|
|
7354
7430
|
import { readFileSync as readFileSync3 } from "node:fs";
|
|
7355
7431
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
7356
7432
|
import { dirname as dirname4, join as join4 } from "node:path";
|
|
7433
|
+
init_cli_utils();
|
|
7357
7434
|
var __filename3 = fileURLToPath2(import.meta.url);
|
|
7358
7435
|
var __dirname3 = dirname4(__filename3);
|
|
7359
7436
|
var packageJson = JSON.parse(readFileSync3(join4(__dirname3, "../package.json"), "utf-8"));
|
|
@@ -7383,11 +7460,13 @@ Init Options:
|
|
|
7383
7460
|
|
|
7384
7461
|
Generate Options:
|
|
7385
7462
|
-c, --config <path> Path to config file (default: postgresdk.config.ts)
|
|
7463
|
+
--force, -y Delete stale files without prompting
|
|
7386
7464
|
|
|
7387
7465
|
Pull Options:
|
|
7388
7466
|
--from <url> API URL to pull SDK from
|
|
7389
7467
|
--output <path> Output directory (default: ./src/sdk)
|
|
7390
7468
|
--token <token> Authentication token
|
|
7469
|
+
--force, -y Delete stale files without prompting
|
|
7391
7470
|
-c, --config <path> Path to config file with pull settings
|
|
7392
7471
|
|
|
7393
7472
|
Examples:
|
|
@@ -7409,8 +7488,9 @@ if (command === "init") {
|
|
|
7409
7488
|
if (configIndex !== -1 && args[configIndex + 1]) {
|
|
7410
7489
|
configPath = args[configIndex + 1];
|
|
7411
7490
|
}
|
|
7491
|
+
const force = parseForceFlag(args);
|
|
7412
7492
|
try {
|
|
7413
|
-
await generate(resolve3(process.cwd(), configPath));
|
|
7493
|
+
await generate(resolve3(process.cwd(), configPath), { force });
|
|
7414
7494
|
} catch (err) {
|
|
7415
7495
|
console.error("❌ Generation failed:", err);
|
|
7416
7496
|
process.exit(1);
|
package/dist/index.d.ts
CHANGED
|
@@ -2,4 +2,6 @@ import "dotenv/config";
|
|
|
2
2
|
import type { Config } from "./types";
|
|
3
3
|
/** Resolves the effective soft delete column for a given table, respecting per-table overrides. */
|
|
4
4
|
export declare function resolveSoftDeleteColumn(cfg: Pick<Config, "softDeleteColumn" | "softDeleteColumnOverrides">, tableName: string): string | null;
|
|
5
|
-
export declare function generate(configPath: string
|
|
5
|
+
export declare function generate(configPath: string, options?: {
|
|
6
|
+
force?: boolean;
|
|
7
|
+
}): Promise<void>;
|
package/dist/index.js
CHANGED
|
@@ -514,9 +514,21 @@ async function ensureDirs(dirs) {
|
|
|
514
514
|
for (const d of dirs)
|
|
515
515
|
await mkdir(d, { recursive: true });
|
|
516
516
|
}
|
|
517
|
-
async function
|
|
518
|
-
|
|
519
|
-
|
|
517
|
+
async function collectDirsRecursively(root) {
|
|
518
|
+
if (!existsSync(root))
|
|
519
|
+
return [];
|
|
520
|
+
const dirs = [root];
|
|
521
|
+
const entries = await readdir(root, { withFileTypes: true });
|
|
522
|
+
for (const entry of entries) {
|
|
523
|
+
if (!entry.isDirectory())
|
|
524
|
+
continue;
|
|
525
|
+
const sub = join(root, entry.name);
|
|
526
|
+
dirs.push(...await collectDirsRecursively(sub));
|
|
527
|
+
}
|
|
528
|
+
return dirs;
|
|
529
|
+
}
|
|
530
|
+
async function findStaleFiles(generatedPaths, dirsToScan) {
|
|
531
|
+
const stale = [];
|
|
520
532
|
for (const dir of dirsToScan) {
|
|
521
533
|
if (!existsSync(dir))
|
|
522
534
|
continue;
|
|
@@ -528,13 +540,11 @@ async function deleteStaleFiles(generatedPaths, dirsToScan) {
|
|
|
528
540
|
continue;
|
|
529
541
|
const fullPath = join(dir, entry.name);
|
|
530
542
|
if (!generatedPaths.has(fullPath)) {
|
|
531
|
-
|
|
532
|
-
deleted++;
|
|
533
|
-
filesDeleted.push(fullPath);
|
|
543
|
+
stale.push(fullPath);
|
|
534
544
|
}
|
|
535
545
|
}
|
|
536
546
|
}
|
|
537
|
-
return
|
|
547
|
+
return stale;
|
|
538
548
|
}
|
|
539
549
|
var pascal = (s) => s.split(/[_\s-]+/).map((w) => w?.[0] ? w[0].toUpperCase() + w.slice(1) : "").join("");
|
|
540
550
|
var init_utils = () => {};
|
|
@@ -1413,6 +1423,50 @@ var init_emit_sdk_contract = __esm(() => {
|
|
|
1413
1423
|
init_emit_include_methods();
|
|
1414
1424
|
});
|
|
1415
1425
|
|
|
1426
|
+
// src/cli-utils.ts
|
|
1427
|
+
import { unlink as unlink2 } from "fs/promises";
|
|
1428
|
+
import prompts from "prompts";
|
|
1429
|
+
function parseForceFlag(args) {
|
|
1430
|
+
return args.includes("--force") || args.includes("-y") || args.includes("--yes");
|
|
1431
|
+
}
|
|
1432
|
+
async function confirmAndDeleteStaleFiles(staleFiles, force) {
|
|
1433
|
+
if (staleFiles.length === 0)
|
|
1434
|
+
return { deleted: 0, skipped: 0, filesDeleted: [] };
|
|
1435
|
+
if (!force && !process.stdout.isTTY) {
|
|
1436
|
+
console.log(`⚠️ ${staleFiles.length} stale file(s) not deleted (non-interactive shell). Re-run with --force to delete.`);
|
|
1437
|
+
return { deleted: 0, skipped: staleFiles.length, filesDeleted: [] };
|
|
1438
|
+
}
|
|
1439
|
+
let deleted = 0;
|
|
1440
|
+
let skipped = 0;
|
|
1441
|
+
const filesDeleted = [];
|
|
1442
|
+
for (const filePath of staleFiles) {
|
|
1443
|
+
let shouldDelete = force;
|
|
1444
|
+
if (!force) {
|
|
1445
|
+
const { confirmed } = await prompts({
|
|
1446
|
+
type: "confirm",
|
|
1447
|
+
name: "confirmed",
|
|
1448
|
+
message: `Delete stale file: ${filePath}?`,
|
|
1449
|
+
initial: false
|
|
1450
|
+
});
|
|
1451
|
+
if (confirmed === undefined) {
|
|
1452
|
+
console.log("Stale file deletion aborted.");
|
|
1453
|
+
break;
|
|
1454
|
+
}
|
|
1455
|
+
shouldDelete = confirmed;
|
|
1456
|
+
}
|
|
1457
|
+
if (shouldDelete) {
|
|
1458
|
+
await unlink2(filePath);
|
|
1459
|
+
console.log(` ✗ ${filePath}`);
|
|
1460
|
+
filesDeleted.push(filePath);
|
|
1461
|
+
deleted++;
|
|
1462
|
+
} else {
|
|
1463
|
+
skipped++;
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
return { deleted, skipped, filesDeleted };
|
|
1467
|
+
}
|
|
1468
|
+
var init_cli_utils = () => {};
|
|
1469
|
+
|
|
1416
1470
|
// src/index.ts
|
|
1417
1471
|
var import_config = __toESM(require_config(), 1);
|
|
1418
1472
|
import { join as join2, relative, dirname as dirname2 } from "node:path";
|
|
@@ -6121,6 +6175,7 @@ function generateTestCases(table, sampleData, updateData, hasForeignKeys = false
|
|
|
6121
6175
|
// src/index.ts
|
|
6122
6176
|
init_emit_sdk_contract();
|
|
6123
6177
|
init_utils();
|
|
6178
|
+
init_cli_utils();
|
|
6124
6179
|
var __filename2 = fileURLToPath(import.meta.url);
|
|
6125
6180
|
var __dirname2 = dirname2(__filename2);
|
|
6126
6181
|
var { version: CLI_VERSION } = JSON.parse(readFileSync(join2(__dirname2, "../package.json"), "utf-8"));
|
|
@@ -6130,7 +6185,7 @@ function resolveSoftDeleteColumn(cfg, tableName) {
|
|
|
6130
6185
|
return overrides[tableName] ?? null;
|
|
6131
6186
|
return cfg.softDeleteColumn ?? null;
|
|
6132
6187
|
}
|
|
6133
|
-
async function generate(configPath) {
|
|
6188
|
+
async function generate(configPath, options) {
|
|
6134
6189
|
if (!existsSync2(configPath)) {
|
|
6135
6190
|
throw new Error(`Config file not found: ${configPath}
|
|
6136
6191
|
|
|
@@ -6325,7 +6380,7 @@ async function generate(configPath) {
|
|
|
6325
6380
|
}
|
|
6326
6381
|
console.log("✍️ Writing files...");
|
|
6327
6382
|
const writeResult = await writeFilesIfChanged(files);
|
|
6328
|
-
let deleteResult = { deleted: 0, filesDeleted: [] };
|
|
6383
|
+
let deleteResult = { deleted: 0, skipped: 0, filesDeleted: [] };
|
|
6329
6384
|
if (cfg.clean !== false) {
|
|
6330
6385
|
const dirsToScan = [
|
|
6331
6386
|
serverDir,
|
|
@@ -6341,9 +6396,10 @@ async function generate(configPath) {
|
|
|
6341
6396
|
if (generateTests)
|
|
6342
6397
|
dirsToScan.push(testDir);
|
|
6343
6398
|
const generatedPaths = new Set(files.map((f) => f.path));
|
|
6344
|
-
|
|
6399
|
+
const staleFiles = await findStaleFiles(generatedPaths, dirsToScan);
|
|
6400
|
+
deleteResult = await confirmAndDeleteStaleFiles(staleFiles, options?.force ?? false);
|
|
6345
6401
|
}
|
|
6346
|
-
if (writeResult.written === 0 && deleteResult.deleted === 0) {
|
|
6402
|
+
if (writeResult.written === 0 && deleteResult.deleted === 0 && deleteResult.skipped === 0) {
|
|
6347
6403
|
console.log(`✅ All ${writeResult.unchanged} files up-to-date (no changes)`);
|
|
6348
6404
|
} else {
|
|
6349
6405
|
const parts = [];
|
|
@@ -6351,6 +6407,8 @@ async function generate(configPath) {
|
|
|
6351
6407
|
parts.push(`updated ${writeResult.written} files`);
|
|
6352
6408
|
if (deleteResult.deleted > 0)
|
|
6353
6409
|
parts.push(`deleted ${deleteResult.deleted} stale files`);
|
|
6410
|
+
if (deleteResult.skipped > 0)
|
|
6411
|
+
parts.push(`skipped ${deleteResult.skipped} stale files`);
|
|
6354
6412
|
if (writeResult.unchanged > 0)
|
|
6355
6413
|
parts.push(`${writeResult.unchanged} unchanged`);
|
|
6356
6414
|
console.log(`✅ ${parts.join(", ")}`);
|
package/dist/utils.d.ts
CHANGED
|
@@ -20,6 +20,16 @@ export declare function writeFilesIfChanged(files: Array<{
|
|
|
20
20
|
*/
|
|
21
21
|
export declare function hashContent(content: string): string;
|
|
22
22
|
export declare function ensureDirs(dirs: string[]): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Recursively collect all subdirectory paths under `root`, including root itself.
|
|
25
|
+
* Returns an empty array if `root` does not exist.
|
|
26
|
+
*/
|
|
27
|
+
export declare function collectDirsRecursively(root: string): Promise<string[]>;
|
|
28
|
+
/**
|
|
29
|
+
* Find files in the given directories that are not in the set of generated paths,
|
|
30
|
+
* without deleting them. Used to identify stale files before prompting for confirmation.
|
|
31
|
+
*/
|
|
32
|
+
export declare function findStaleFiles(generatedPaths: Set<string>, dirsToScan: string[]): Promise<string[]>;
|
|
23
33
|
/**
|
|
24
34
|
* Delete files in the given directories that are not in the set of generated paths.
|
|
25
35
|
* Used to remove stale files for tables that no longer exist in the schema.
|