@nmakarov/cli-toolkit 0.11.3 → 0.14.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/dist/db.cjs +97 -2
- package/dist/db.cjs.map +1 -1
- package/dist/db.js +93 -1
- package/dist/db.js.map +1 -1
- package/dist/filedatabase.cjs +195 -15
- package/dist/filedatabase.cjs.map +1 -1
- package/dist/filedatabase.js +192 -14
- package/dist/filedatabase.js.map +1 -1
- package/dist/index.cjs +288 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +283 -13
- package/dist/index.js.map +1 -1
- package/dist/mock-server.cjs +168 -13
- package/dist/mock-server.cjs.map +1 -1
- package/dist/mock-server.js +168 -13
- package/dist/mock-server.js.map +1 -1
- package/dist/utils.cjs +251 -0
- package/dist/utils.cjs.map +1 -0
- package/dist/utils.js +199 -0
- package/dist/utils.js.map +1 -0
- package/package.json +6 -1
package/dist/index.js
CHANGED
|
@@ -2502,20 +2502,48 @@ var FileDatabase = class {
|
|
|
2502
2502
|
}
|
|
2503
2503
|
/**
|
|
2504
2504
|
* Figure out what data to write and which file to use (for pagination)
|
|
2505
|
+
* @param data - Data to write
|
|
2506
|
+
* @param targetFileIndex - Optional index of existing file to overwrite (when customMetadata matches)
|
|
2507
|
+
* @param forceNewFile - If true, always create a new file (when customMetadata provided but no match)
|
|
2505
2508
|
*/
|
|
2506
|
-
figureOutDataAndFileToWrite(data) {
|
|
2509
|
+
figureOutDataAndFileToWrite(data, targetFileIndex = null, forceNewFile = false) {
|
|
2507
2510
|
let dataToWrite;
|
|
2508
2511
|
let dataLeftOver;
|
|
2509
2512
|
const incomingDataType = detectDataType(data);
|
|
2510
2513
|
if (this.metadata.dataType !== incomingDataType) {
|
|
2511
2514
|
this.metadata.dataType = incomingDataType;
|
|
2512
2515
|
}
|
|
2513
|
-
if (this.metadata.files.length
|
|
2516
|
+
if (targetFileIndex !== null && targetFileIndex < this.metadata.files.length) {
|
|
2517
|
+
const targetFile = this.metadata.files[targetFileIndex];
|
|
2518
|
+
if (!Array.isArray(data)) {
|
|
2519
|
+
dataToWrite = data;
|
|
2520
|
+
dataLeftOver = null;
|
|
2521
|
+
return { dataToWrite, dataLeftOver, fileName: targetFile.fileName };
|
|
2522
|
+
} else {
|
|
2523
|
+
dataToWrite = data.slice(0, this.pageSize);
|
|
2524
|
+
dataLeftOver = data.slice(this.pageSize);
|
|
2525
|
+
this.lastFileData = dataToWrite;
|
|
2526
|
+
return { dataToWrite, dataLeftOver, fileName: targetFile.fileName };
|
|
2527
|
+
}
|
|
2528
|
+
}
|
|
2529
|
+
let newlyCreatedFileIndex = null;
|
|
2530
|
+
if (forceNewFile) {
|
|
2531
|
+
const filesBeforeCreate = this.metadata.files.length;
|
|
2532
|
+
this.makeNewFile();
|
|
2533
|
+
newlyCreatedFileIndex = filesBeforeCreate;
|
|
2534
|
+
this.logger.debug?.(`[FileDatabase] Creating new file for unique custom metadata combination, fileNumber: ${this.currentFileNumber}`);
|
|
2535
|
+
} else if (this.metadata.files.length === 0) {
|
|
2514
2536
|
this.makeNewFile();
|
|
2515
2537
|
}
|
|
2516
2538
|
const lastFile = this.metadata.files[this.metadata.files.length - 1];
|
|
2517
2539
|
const lastFileRecordsCount = lastFile.recordsCount;
|
|
2518
|
-
if (
|
|
2540
|
+
if (forceNewFile && newlyCreatedFileIndex !== null) {
|
|
2541
|
+
const newlyCreatedFile = this.metadata.files[newlyCreatedFileIndex];
|
|
2542
|
+
if (newlyCreatedFile && newlyCreatedFile.fileName !== lastFile.fileName) {
|
|
2543
|
+
this.logger.warn?.(`[FileDatabase] Warning: Newly created file ${newlyCreatedFile.fileName} doesn't match last file ${lastFile.fileName}`);
|
|
2544
|
+
}
|
|
2545
|
+
}
|
|
2546
|
+
if (!Array.isArray(data) && !forceNewFile) {
|
|
2519
2547
|
const lastFileExtension = path3.extname(lastFile.fileName);
|
|
2520
2548
|
const expectedExtension = `.${getFileExtension(incomingDataType)}`;
|
|
2521
2549
|
if (lastFileExtension !== expectedExtension) {
|
|
@@ -2525,24 +2553,35 @@ var FileDatabase = class {
|
|
|
2525
2553
|
lastFile.fileName = `${this.currentFileNumber.toString().padStart(6, "0")}.${getFileExtension(incomingDataType)}`;
|
|
2526
2554
|
}
|
|
2527
2555
|
}
|
|
2556
|
+
} else if (!Array.isArray(data) && forceNewFile) {
|
|
2557
|
+
const lastFileExtension = path3.extname(lastFile.fileName);
|
|
2558
|
+
const expectedExtension = `.${getFileExtension(incomingDataType)}`;
|
|
2559
|
+
if (lastFileExtension !== expectedExtension) {
|
|
2560
|
+
lastFile.fileName = `${this.currentFileNumber.toString().padStart(6, "0")}.${getFileExtension(incomingDataType)}`;
|
|
2561
|
+
}
|
|
2528
2562
|
}
|
|
2529
2563
|
if (Array.isArray(data)) {
|
|
2530
|
-
if (
|
|
2564
|
+
if (forceNewFile) {
|
|
2565
|
+
dataToWrite = data.slice(0, this.pageSize);
|
|
2566
|
+
dataLeftOver = data.slice(this.pageSize);
|
|
2567
|
+
this.lastFileData = dataToWrite;
|
|
2568
|
+
} else if (lastFileRecordsCount < this.pageSize) {
|
|
2531
2569
|
dataToWrite = [...this.lastFileData || [], ...data.slice(0, this.pageSize - lastFileRecordsCount)];
|
|
2532
2570
|
dataLeftOver = data.slice(this.pageSize - lastFileRecordsCount);
|
|
2571
|
+
this.lastFileData = dataToWrite;
|
|
2533
2572
|
} else {
|
|
2534
2573
|
this.makeNewFile();
|
|
2535
2574
|
dataToWrite = data.slice(0, this.pageSize);
|
|
2536
2575
|
dataLeftOver = data.slice(this.pageSize);
|
|
2576
|
+
this.lastFileData = dataToWrite;
|
|
2537
2577
|
}
|
|
2538
|
-
this.lastFileData = dataToWrite;
|
|
2539
2578
|
} else {
|
|
2540
2579
|
dataToWrite = data;
|
|
2541
2580
|
dataLeftOver = null;
|
|
2542
2581
|
}
|
|
2543
2582
|
const fileName = this.metadata.files[this.metadata.files.length - 1].fileName;
|
|
2544
2583
|
this.logger.debug?.(
|
|
2545
|
-
`[FileDatabase] figureOutDataAndFileToWrite: filename=${fileName}, dataToWrite.length=${Array.isArray(dataToWrite) ? dataToWrite.length : "N/A"}, lastFileRecordsCount=${lastFileRecordsCount}`
|
|
2584
|
+
`[FileDatabase] figureOutDataAndFileToWrite: filename=${fileName}, forceNewFile=${forceNewFile}, targetFileIndex=${targetFileIndex}, dataToWrite.length=${Array.isArray(dataToWrite) ? dataToWrite.length : "N/A"}, lastFileRecordsCount=${lastFileRecordsCount}`
|
|
2546
2585
|
);
|
|
2547
2586
|
return { dataToWrite, dataLeftOver, fileName };
|
|
2548
2587
|
}
|
|
@@ -2570,7 +2609,7 @@ var FileDatabase = class {
|
|
|
2570
2609
|
/**
|
|
2571
2610
|
* Update metadata after writing data
|
|
2572
2611
|
*/
|
|
2573
|
-
updateMetadata(dataToWrite, fileName) {
|
|
2612
|
+
updateMetadata(dataToWrite, fileName, customMetadata) {
|
|
2574
2613
|
let currentFile;
|
|
2575
2614
|
if (fileName) {
|
|
2576
2615
|
const foundFile = this.metadata.files.find((file) => file.fileName === fileName);
|
|
@@ -2585,6 +2624,9 @@ var FileDatabase = class {
|
|
|
2585
2624
|
}
|
|
2586
2625
|
const recordsCount = Array.isArray(dataToWrite) ? dataToWrite.length : 1;
|
|
2587
2626
|
currentFile.recordsCount = recordsCount;
|
|
2627
|
+
if (customMetadata) {
|
|
2628
|
+
Object.assign(currentFile, customMetadata);
|
|
2629
|
+
}
|
|
2588
2630
|
const fileIndex = this.metadata.files.indexOf(currentFile);
|
|
2589
2631
|
if (fileIndex !== -1) {
|
|
2590
2632
|
this.calculateFileSynopsis(dataToWrite, fileIndex);
|
|
@@ -2637,6 +2679,11 @@ var FileDatabase = class {
|
|
|
2637
2679
|
} else {
|
|
2638
2680
|
if (!this.metadata.files.length) {
|
|
2639
2681
|
this.metadata = await this.figureMetadata(this.currentVersion);
|
|
2682
|
+
if (this.metadata.files && this.metadata.files.length > 0) {
|
|
2683
|
+
this.currentFileNumber = Math.max(...this.metadata.files.map((f) => f.number || 0));
|
|
2684
|
+
} else {
|
|
2685
|
+
this.currentFileNumber = 0;
|
|
2686
|
+
}
|
|
2640
2687
|
}
|
|
2641
2688
|
}
|
|
2642
2689
|
} else {
|
|
@@ -2647,16 +2694,22 @@ var FileDatabase = class {
|
|
|
2647
2694
|
try {
|
|
2648
2695
|
const rawData = await fs3.promises.readFile(metadataPath, "utf8");
|
|
2649
2696
|
this.metadata = JSON.parse(rawData);
|
|
2697
|
+
if (this.metadata.files && this.metadata.files.length > 0) {
|
|
2698
|
+
this.currentFileNumber = Math.max(...this.metadata.files.map((f) => f.number || 0));
|
|
2699
|
+
} else {
|
|
2700
|
+
this.currentFileNumber = 0;
|
|
2701
|
+
}
|
|
2650
2702
|
} catch (e) {
|
|
2651
2703
|
this.metadata = this.getDefaultMetadata();
|
|
2704
|
+
this.currentFileNumber = 0;
|
|
2652
2705
|
}
|
|
2653
2706
|
} else {
|
|
2654
2707
|
this.metadata = this.getDefaultMetadata();
|
|
2655
|
-
this.
|
|
2708
|
+
this.currentFileNumber = 0;
|
|
2656
2709
|
}
|
|
2657
2710
|
} else {
|
|
2658
2711
|
this.metadata = this.getDefaultMetadata();
|
|
2659
|
-
this.
|
|
2712
|
+
this.currentFileNumber = 0;
|
|
2660
2713
|
}
|
|
2661
2714
|
}
|
|
2662
2715
|
} else if (read) {
|
|
@@ -2675,6 +2728,11 @@ var FileDatabase = class {
|
|
|
2675
2728
|
}
|
|
2676
2729
|
if (!this.metadata.files.length) {
|
|
2677
2730
|
this.metadata = await this.figureMetadata(this.currentVersion);
|
|
2731
|
+
if (this.metadata.files && this.metadata.files.length > 0) {
|
|
2732
|
+
this.currentFileNumber = Math.max(...this.metadata.files.map((f) => f.number || 0));
|
|
2733
|
+
} else {
|
|
2734
|
+
this.currentFileNumber = 0;
|
|
2735
|
+
}
|
|
2678
2736
|
}
|
|
2679
2737
|
} else {
|
|
2680
2738
|
this.currentVersion = null;
|
|
@@ -2688,6 +2746,11 @@ var FileDatabase = class {
|
|
|
2688
2746
|
try {
|
|
2689
2747
|
const rawData = await fs3.promises.readFile(metadataPath, "utf8");
|
|
2690
2748
|
this.metadata = JSON.parse(rawData);
|
|
2749
|
+
if (this.metadata.files && this.metadata.files.length > 0) {
|
|
2750
|
+
this.currentFileNumber = Math.max(...this.metadata.files.map((f) => f.number || 0));
|
|
2751
|
+
} else {
|
|
2752
|
+
this.currentFileNumber = 0;
|
|
2753
|
+
}
|
|
2691
2754
|
} catch (e) {
|
|
2692
2755
|
throw new FileDatabaseError(`Failed to read metadata: ${e.message}`);
|
|
2693
2756
|
}
|
|
@@ -2696,6 +2759,11 @@ var FileDatabase = class {
|
|
|
2696
2759
|
}
|
|
2697
2760
|
} else {
|
|
2698
2761
|
this.metadata = await this.figureMetadataFromVersionFiles("");
|
|
2762
|
+
if (this.metadata.files && this.metadata.files.length > 0) {
|
|
2763
|
+
this.currentFileNumber = Math.max(...this.metadata.files.map((f) => f.number || 0));
|
|
2764
|
+
} else {
|
|
2765
|
+
this.currentFileNumber = 0;
|
|
2766
|
+
}
|
|
2699
2767
|
}
|
|
2700
2768
|
}
|
|
2701
2769
|
}
|
|
@@ -2717,14 +2785,44 @@ var FileDatabase = class {
|
|
|
2717
2785
|
this.metadata.dataType = incomingDataType;
|
|
2718
2786
|
this.makeNewFile();
|
|
2719
2787
|
}
|
|
2720
|
-
let
|
|
2788
|
+
let targetFileIndex = null;
|
|
2789
|
+
const hasCustomMetadata = options.customMetadata && Object.keys(options.customMetadata).length > 0;
|
|
2790
|
+
if (hasCustomMetadata) {
|
|
2791
|
+
for (let i = 0; i < this.metadata.files.length; i++) {
|
|
2792
|
+
const fileEntry = this.metadata.files[i];
|
|
2793
|
+
const matches = Object.keys(options.customMetadata).every((key) => {
|
|
2794
|
+
return key in fileEntry && fileEntry[key] === options.customMetadata[key];
|
|
2795
|
+
});
|
|
2796
|
+
if (matches) {
|
|
2797
|
+
targetFileIndex = i;
|
|
2798
|
+
this.logger.debug?.(`[FileDatabase] Found existing file with matching custom metadata: ${fileEntry.fileName}, metadata: ${JSON.stringify(options.customMetadata)}`);
|
|
2799
|
+
break;
|
|
2800
|
+
} else {
|
|
2801
|
+
this.logger.debug?.(`[FileDatabase] File ${fileEntry.fileName} does not match custom metadata: ${JSON.stringify(options.customMetadata)}`);
|
|
2802
|
+
}
|
|
2803
|
+
}
|
|
2804
|
+
if (targetFileIndex === null) {
|
|
2805
|
+
this.logger.debug?.(`[FileDatabase] No existing file found with custom metadata: ${JSON.stringify(options.customMetadata)}, will create new file`);
|
|
2806
|
+
}
|
|
2807
|
+
} else {
|
|
2808
|
+
this.logger.debug?.(`[FileDatabase] No custom metadata provided, will create new file`);
|
|
2809
|
+
}
|
|
2810
|
+
if (targetFileIndex !== null) {
|
|
2811
|
+
const targetFile = this.metadata.files[targetFileIndex];
|
|
2812
|
+
this.currentFileNumber = targetFile.number;
|
|
2813
|
+
this.lastFileData = null;
|
|
2814
|
+
this.currentRecord = 0;
|
|
2815
|
+
this.hasReadFirstPage = false;
|
|
2816
|
+
}
|
|
2817
|
+
const forceNewFile = hasCustomMetadata && targetFileIndex === null;
|
|
2818
|
+
let { dataToWrite, dataLeftOver, fileName } = this.figureOutDataAndFileToWrite(data, targetFileIndex, forceNewFile);
|
|
2721
2819
|
const destPath = this.getDestinationPath(this.currentVersion || void 0);
|
|
2722
2820
|
await this.safeWrite(path3.join(destPath, fileName), dataToWrite);
|
|
2723
|
-
this.updateMetadata(dataToWrite, fileName);
|
|
2724
|
-
while (dataLeftOver && dataLeftOver.length > 0) {
|
|
2821
|
+
this.updateMetadata(dataToWrite, fileName, options.customMetadata);
|
|
2822
|
+
while (dataLeftOver && dataLeftOver.length > 0 && targetFileIndex === null) {
|
|
2725
2823
|
const writeContext = this.figureOutDataAndFileToWrite(dataLeftOver);
|
|
2726
2824
|
await this.safeWrite(path3.join(destPath, writeContext.fileName), writeContext.dataToWrite);
|
|
2727
|
-
this.updateMetadata(writeContext.dataToWrite, writeContext.fileName);
|
|
2825
|
+
this.updateMetadata(writeContext.dataToWrite, writeContext.fileName, options.customMetadata);
|
|
2728
2826
|
dataLeftOver = writeContext.dataLeftOver;
|
|
2729
2827
|
}
|
|
2730
2828
|
this.calculateVersionSynopsis();
|
|
@@ -2841,7 +2939,85 @@ var FileDatabase = class {
|
|
|
2841
2939
|
getMetadata() {
|
|
2842
2940
|
return { ...this.metadata };
|
|
2843
2941
|
}
|
|
2942
|
+
/**
|
|
2943
|
+
* Find data by custom metadata fields
|
|
2944
|
+
* Searches through all versions and files to find entries matching the search criteria
|
|
2945
|
+
*
|
|
2946
|
+
* @param searchCriteria - Object with field names and values to search for (e.g., { ListingKey: "123", id: "456" })
|
|
2947
|
+
* @returns Array of found entries with their file paths and metadata
|
|
2948
|
+
*/
|
|
2949
|
+
async findData(searchCriteria) {
|
|
2950
|
+
const results = [];
|
|
2951
|
+
if (!this.versioned) {
|
|
2952
|
+
await this.prepare({ read: true });
|
|
2953
|
+
const metadata = this.getMetadata();
|
|
2954
|
+
for (const fileEntry of metadata.files) {
|
|
2955
|
+
const matches = Object.keys(searchCriteria).every((key) => {
|
|
2956
|
+
return fileEntry[key] === searchCriteria[key];
|
|
2957
|
+
});
|
|
2958
|
+
if (matches) {
|
|
2959
|
+
const destPath = this.getDestinationPath();
|
|
2960
|
+
const filePath = path3.join(destPath, fileEntry.fileName);
|
|
2961
|
+
const fileData = await fs3.promises.readFile(filePath, "utf8");
|
|
2962
|
+
const data = deserializeData(fileData, metadata.dataType || "json-object");
|
|
2963
|
+
results.push({
|
|
2964
|
+
filePath,
|
|
2965
|
+
fileName: fileEntry.fileName,
|
|
2966
|
+
version: null,
|
|
2967
|
+
metadata: fileEntry,
|
|
2968
|
+
data
|
|
2969
|
+
});
|
|
2970
|
+
}
|
|
2971
|
+
}
|
|
2972
|
+
} else {
|
|
2973
|
+
const versions = await this.getVersions();
|
|
2974
|
+
for (const version of versions) {
|
|
2975
|
+
await this.prepare({ read: true, version });
|
|
2976
|
+
const metadata = this.getMetadata();
|
|
2977
|
+
for (const fileEntry of metadata.files) {
|
|
2978
|
+
const matches = Object.keys(searchCriteria).every((key) => {
|
|
2979
|
+
return fileEntry[key] === searchCriteria[key];
|
|
2980
|
+
});
|
|
2981
|
+
if (matches) {
|
|
2982
|
+
const destPath = this.getDestinationPath(version);
|
|
2983
|
+
const filePath = path3.join(destPath, fileEntry.fileName);
|
|
2984
|
+
const fileData = await fs3.promises.readFile(filePath, "utf8");
|
|
2985
|
+
const data = deserializeData(fileData, metadata.dataType || "json-object");
|
|
2986
|
+
results.push({
|
|
2987
|
+
filePath,
|
|
2988
|
+
fileName: fileEntry.fileName,
|
|
2989
|
+
version,
|
|
2990
|
+
metadata: fileEntry,
|
|
2991
|
+
data
|
|
2992
|
+
});
|
|
2993
|
+
}
|
|
2994
|
+
}
|
|
2995
|
+
}
|
|
2996
|
+
}
|
|
2997
|
+
return results;
|
|
2998
|
+
}
|
|
2844
2999
|
};
|
|
3000
|
+
function listTables(basePath, namespace) {
|
|
3001
|
+
const namespacePath = path3.join(basePath, namespace);
|
|
3002
|
+
if (!fs3.existsSync(namespacePath)) {
|
|
3003
|
+
return [];
|
|
3004
|
+
}
|
|
3005
|
+
try {
|
|
3006
|
+
return fs3.readdirSync(namespacePath, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
|
|
3007
|
+
} catch (error) {
|
|
3008
|
+
return [];
|
|
3009
|
+
}
|
|
3010
|
+
}
|
|
3011
|
+
function listSources(basePath) {
|
|
3012
|
+
if (!fs3.existsSync(basePath)) {
|
|
3013
|
+
return [];
|
|
3014
|
+
}
|
|
3015
|
+
try {
|
|
3016
|
+
return fs3.readdirSync(basePath, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
|
|
3017
|
+
} catch (error) {
|
|
3018
|
+
return [];
|
|
3019
|
+
}
|
|
3020
|
+
}
|
|
2845
3021
|
function fileDatabaseInit(context, options = {}) {
|
|
2846
3022
|
return new FileDatabase(context, options);
|
|
2847
3023
|
}
|
|
@@ -2854,6 +3030,10 @@ var Db = class {
|
|
|
2854
3030
|
logger;
|
|
2855
3031
|
queriesLog = [];
|
|
2856
3032
|
isConnected = false;
|
|
3033
|
+
/**
|
|
3034
|
+
* Constructor - accepts config object
|
|
3035
|
+
* Use dbInit() function to initialize with Context
|
|
3036
|
+
*/
|
|
2857
3037
|
constructor(config2) {
|
|
2858
3038
|
if (!config2.connectionString) {
|
|
2859
3039
|
throw new ParamError("Db: connectionString is required");
|
|
@@ -3140,6 +3320,91 @@ var Db = class {
|
|
|
3140
3320
|
return this.isConnected && this.knexInstance !== null;
|
|
3141
3321
|
}
|
|
3142
3322
|
};
|
|
3323
|
+
function capitalizeFirstLetter(str) {
|
|
3324
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
3325
|
+
}
|
|
3326
|
+
async function dbConnect(context, connectionString, name, dbProfile) {
|
|
3327
|
+
const defs = {
|
|
3328
|
+
testDbConnection: "boolean default true",
|
|
3329
|
+
name: "string",
|
|
3330
|
+
poolMin: "number default 2",
|
|
3331
|
+
poolMax: "number default 10",
|
|
3332
|
+
acquireConnectionTimeout: "number default 10000",
|
|
3333
|
+
sslRejectUnauthorized: "boolean default false"
|
|
3334
|
+
};
|
|
3335
|
+
const paramsConfig = context.params.getAll(defs);
|
|
3336
|
+
const config2 = {
|
|
3337
|
+
connectionString,
|
|
3338
|
+
name: paramsConfig.name || name || "default",
|
|
3339
|
+
testConnection: paramsConfig.testDbConnection,
|
|
3340
|
+
profile: dbProfile ?? false,
|
|
3341
|
+
pool: {
|
|
3342
|
+
min: paramsConfig.poolMin,
|
|
3343
|
+
max: paramsConfig.poolMax
|
|
3344
|
+
},
|
|
3345
|
+
acquireConnectionTimeout: paramsConfig.acquireConnectionTimeout,
|
|
3346
|
+
ssl: {
|
|
3347
|
+
rejectUnauthorized: paramsConfig.sslRejectUnauthorized
|
|
3348
|
+
},
|
|
3349
|
+
logger: context.logger
|
|
3350
|
+
};
|
|
3351
|
+
try {
|
|
3352
|
+
const db = new Db(config2);
|
|
3353
|
+
context.registerCleanup(async () => {
|
|
3354
|
+
await db.disconnect();
|
|
3355
|
+
context.logger.debug(`[Db] instance "${name || connectionString}" destroyed`);
|
|
3356
|
+
});
|
|
3357
|
+
await db.connect();
|
|
3358
|
+
context.logger.debug(`[Db] instance "${name || connectionString}" initialized`);
|
|
3359
|
+
return db;
|
|
3360
|
+
} catch (error) {
|
|
3361
|
+
if (error instanceof ParamError) {
|
|
3362
|
+
throw error;
|
|
3363
|
+
}
|
|
3364
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
3365
|
+
throw new ParamError(`[Db] connect error: ${errorMsg}`);
|
|
3366
|
+
}
|
|
3367
|
+
}
|
|
3368
|
+
async function dbFindAndConnect(context, dbNameOrConnectionString) {
|
|
3369
|
+
let dbName;
|
|
3370
|
+
let dbConnectionString;
|
|
3371
|
+
let dbProfile;
|
|
3372
|
+
if (dbNameOrConnectionString) {
|
|
3373
|
+
if (dbNameOrConnectionString.match(/^(postgresql|mysql):\/\/[^\s]+:[^\s]+@[^\s]+:\d+\/[^\s]+$/)) {
|
|
3374
|
+
dbName = void 0;
|
|
3375
|
+
dbConnectionString = dbNameOrConnectionString;
|
|
3376
|
+
} else {
|
|
3377
|
+
dbName = dbNameOrConnectionString;
|
|
3378
|
+
}
|
|
3379
|
+
} else {
|
|
3380
|
+
const defs = {
|
|
3381
|
+
dbName: "string",
|
|
3382
|
+
dbConnectionString: "string",
|
|
3383
|
+
dbProfile: "boolean default false"
|
|
3384
|
+
};
|
|
3385
|
+
const paramsConfig = context.params.getAll(defs);
|
|
3386
|
+
dbName = paramsConfig.dbName;
|
|
3387
|
+
dbConnectionString = paramsConfig.dbConnectionString;
|
|
3388
|
+
dbProfile = paramsConfig.dbProfile;
|
|
3389
|
+
}
|
|
3390
|
+
if (!dbName && !dbConnectionString) {
|
|
3391
|
+
throw new ParamError("Db: either dbName or dbConnectionString must be specified");
|
|
3392
|
+
}
|
|
3393
|
+
if (dbName) {
|
|
3394
|
+
const paramName = `dbConnectionString${capitalizeFirstLetter(dbName)}`;
|
|
3395
|
+
dbConnectionString = await context.params.get(paramName, "string");
|
|
3396
|
+
if (!dbConnectionString) {
|
|
3397
|
+
throw new ParamError(
|
|
3398
|
+
`Db: cannot find dbConnectionString for dbName="${dbName}" (looked for param "${paramName}")`
|
|
3399
|
+
);
|
|
3400
|
+
}
|
|
3401
|
+
}
|
|
3402
|
+
const db = await dbConnect(context, dbConnectionString, dbName, dbProfile);
|
|
3403
|
+
return db;
|
|
3404
|
+
}
|
|
3405
|
+
async function dbInit(context, dbNameOrConnectionString) {
|
|
3406
|
+
return await dbFindAndConnect(context, dbNameOrConnectionString);
|
|
3407
|
+
}
|
|
3143
3408
|
|
|
3144
3409
|
// src/logger/index.ts
|
|
3145
3410
|
import chalk from "chalk";
|
|
@@ -3534,6 +3799,9 @@ export {
|
|
|
3534
3799
|
buildBreadcrumb,
|
|
3535
3800
|
buildDetailBreadcrumb,
|
|
3536
3801
|
buildFooter,
|
|
3802
|
+
dbConnect,
|
|
3803
|
+
dbFindAndConnect,
|
|
3804
|
+
dbInit,
|
|
3537
3805
|
defaultFileSynopsisFunction,
|
|
3538
3806
|
defaultVersionSynopsisFunction,
|
|
3539
3807
|
fileDatabaseInit,
|
|
@@ -3541,6 +3809,8 @@ export {
|
|
|
3541
3809
|
createElement2 as h,
|
|
3542
3810
|
joiEdateType,
|
|
3543
3811
|
joiStringArrayType,
|
|
3812
|
+
listSources,
|
|
3813
|
+
listTables,
|
|
3544
3814
|
load,
|
|
3545
3815
|
organizeFooterMessages,
|
|
3546
3816
|
setupContext,
|