@spfn/core 0.1.0-alpha.21 → 0.1.0-alpha.23
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/index.js +237 -50
- package/dist/db/index.js.map +1 -1
- package/dist/index.js +280 -68
- package/dist/index.js.map +1 -1
- package/dist/scripts/index.js +992 -820
- package/dist/scripts/index.js.map +1 -1
- package/dist/server/index.js +280 -68
- package/dist/server/index.js.map +1 -1
- package/package.json +1 -1
package/dist/db/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { config } from 'dotenv';
|
|
2
1
|
import { drizzle } from 'drizzle-orm/postgres-js';
|
|
3
2
|
import postgres from 'postgres';
|
|
4
3
|
import pino from 'pino';
|
|
5
4
|
import { existsSync, mkdirSync, createWriteStream } from 'fs';
|
|
6
5
|
import { join } from 'path';
|
|
6
|
+
import { config } from 'dotenv';
|
|
7
7
|
import { AsyncLocalStorage } from 'async_hooks';
|
|
8
8
|
import { createMiddleware } from 'hono/factory';
|
|
9
9
|
import { and, desc, asc, sql, isNull, isNotNull, notInArray, inArray, like, lte, lt, gte, gt, ne, eq } from 'drizzle-orm';
|
|
@@ -12,7 +12,7 @@ import { bigserial, timestamp } from 'drizzle-orm/pg-core';
|
|
|
12
12
|
// src/db/manager/factory.ts
|
|
13
13
|
var PinoAdapter = class _PinoAdapter {
|
|
14
14
|
logger;
|
|
15
|
-
constructor(
|
|
15
|
+
constructor(config) {
|
|
16
16
|
const isProduction = process.env.NODE_ENV === "production";
|
|
17
17
|
const isDevelopment = process.env.NODE_ENV === "development";
|
|
18
18
|
const fileLoggingEnabled = process.env.LOGGER_FILE_ENABLED === "true";
|
|
@@ -45,11 +45,11 @@ var PinoAdapter = class _PinoAdapter {
|
|
|
45
45
|
});
|
|
46
46
|
}
|
|
47
47
|
this.logger = pino({
|
|
48
|
-
level:
|
|
48
|
+
level: config.level,
|
|
49
49
|
// Transport 설정 (targets가 있으면 사용, 없으면 기본 stdout)
|
|
50
50
|
transport: targets.length > 0 ? { targets } : void 0,
|
|
51
51
|
// 기본 필드
|
|
52
|
-
base:
|
|
52
|
+
base: config.module ? { module: config.module } : void 0
|
|
53
53
|
});
|
|
54
54
|
}
|
|
55
55
|
child(module) {
|
|
@@ -92,9 +92,9 @@ var PinoAdapter = class _PinoAdapter {
|
|
|
92
92
|
var Logger = class _Logger {
|
|
93
93
|
config;
|
|
94
94
|
module;
|
|
95
|
-
constructor(
|
|
96
|
-
this.config =
|
|
97
|
-
this.module =
|
|
95
|
+
constructor(config) {
|
|
96
|
+
this.config = config;
|
|
97
|
+
this.module = config.module;
|
|
98
98
|
}
|
|
99
99
|
/**
|
|
100
100
|
* Get current log level
|
|
@@ -310,10 +310,10 @@ var ConsoleTransport = class {
|
|
|
310
310
|
level;
|
|
311
311
|
enabled;
|
|
312
312
|
colorize;
|
|
313
|
-
constructor(
|
|
314
|
-
this.level =
|
|
315
|
-
this.enabled =
|
|
316
|
-
this.colorize =
|
|
313
|
+
constructor(config) {
|
|
314
|
+
this.level = config.level;
|
|
315
|
+
this.enabled = config.enabled;
|
|
316
|
+
this.colorize = config.colorize ?? true;
|
|
317
317
|
}
|
|
318
318
|
async log(metadata) {
|
|
319
319
|
if (!this.enabled) {
|
|
@@ -337,10 +337,10 @@ var FileTransport = class {
|
|
|
337
337
|
logDir;
|
|
338
338
|
currentStream = null;
|
|
339
339
|
currentFilename = null;
|
|
340
|
-
constructor(
|
|
341
|
-
this.level =
|
|
342
|
-
this.enabled =
|
|
343
|
-
this.logDir =
|
|
340
|
+
constructor(config) {
|
|
341
|
+
this.level = config.level;
|
|
342
|
+
this.enabled = config.enabled;
|
|
343
|
+
this.logDir = config.logDir;
|
|
344
344
|
if (!existsSync(this.logDir)) {
|
|
345
345
|
mkdirSync(this.logDir, { recursive: true });
|
|
346
346
|
}
|
|
@@ -472,10 +472,10 @@ function initializeTransports() {
|
|
|
472
472
|
}
|
|
473
473
|
var CustomAdapter = class _CustomAdapter {
|
|
474
474
|
logger;
|
|
475
|
-
constructor(
|
|
475
|
+
constructor(config) {
|
|
476
476
|
this.logger = new Logger({
|
|
477
|
-
level:
|
|
478
|
-
module:
|
|
477
|
+
level: config.level,
|
|
478
|
+
module: config.module,
|
|
479
479
|
transports: initializeTransports()
|
|
480
480
|
});
|
|
481
481
|
}
|
|
@@ -790,6 +790,178 @@ function getRetryConfig() {
|
|
|
790
790
|
};
|
|
791
791
|
}
|
|
792
792
|
|
|
793
|
+
// src/env/config.ts
|
|
794
|
+
var ENV_FILE_PRIORITY = [
|
|
795
|
+
".env",
|
|
796
|
+
// Base configuration (lowest priority)
|
|
797
|
+
".env.{NODE_ENV}",
|
|
798
|
+
// Environment-specific
|
|
799
|
+
".env.local",
|
|
800
|
+
// Local overrides
|
|
801
|
+
".env.{NODE_ENV}.local"
|
|
802
|
+
// Local environment-specific (highest priority)
|
|
803
|
+
];
|
|
804
|
+
var TEST_ONLY_FILES = [
|
|
805
|
+
".env.test",
|
|
806
|
+
".env.test.local"
|
|
807
|
+
];
|
|
808
|
+
|
|
809
|
+
// src/env/loader.ts
|
|
810
|
+
var envLogger = logger.child("environment");
|
|
811
|
+
var environmentLoaded = false;
|
|
812
|
+
var cachedLoadResult;
|
|
813
|
+
function buildFileList(basePath, nodeEnv) {
|
|
814
|
+
const files = [];
|
|
815
|
+
for (const pattern of ENV_FILE_PRIORITY) {
|
|
816
|
+
const fileName = pattern.replace("{NODE_ENV}", nodeEnv);
|
|
817
|
+
if (nodeEnv !== "test" && TEST_ONLY_FILES.includes(fileName)) {
|
|
818
|
+
continue;
|
|
819
|
+
}
|
|
820
|
+
files.push(join(basePath, fileName));
|
|
821
|
+
}
|
|
822
|
+
return files;
|
|
823
|
+
}
|
|
824
|
+
function loadSingleFile(filePath, debug) {
|
|
825
|
+
if (!existsSync(filePath)) {
|
|
826
|
+
if (debug) {
|
|
827
|
+
envLogger.debug("Environment file not found (optional)", {
|
|
828
|
+
path: filePath
|
|
829
|
+
});
|
|
830
|
+
}
|
|
831
|
+
return { success: false, parsed: {}, error: "File not found" };
|
|
832
|
+
}
|
|
833
|
+
try {
|
|
834
|
+
const result = config({ path: filePath });
|
|
835
|
+
if (result.error) {
|
|
836
|
+
envLogger.warn("Failed to parse environment file", {
|
|
837
|
+
path: filePath,
|
|
838
|
+
error: result.error.message
|
|
839
|
+
});
|
|
840
|
+
return {
|
|
841
|
+
success: false,
|
|
842
|
+
parsed: {},
|
|
843
|
+
error: result.error.message
|
|
844
|
+
};
|
|
845
|
+
}
|
|
846
|
+
const parsed = result.parsed || {};
|
|
847
|
+
if (debug) {
|
|
848
|
+
envLogger.debug("Environment file loaded successfully", {
|
|
849
|
+
path: filePath,
|
|
850
|
+
variables: Object.keys(parsed),
|
|
851
|
+
count: Object.keys(parsed).length
|
|
852
|
+
});
|
|
853
|
+
}
|
|
854
|
+
return { success: true, parsed };
|
|
855
|
+
} catch (error) {
|
|
856
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
857
|
+
envLogger.error("Error loading environment file", {
|
|
858
|
+
path: filePath,
|
|
859
|
+
error: message
|
|
860
|
+
});
|
|
861
|
+
return { success: false, parsed: {}, error: message };
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
function validateRequiredVars(required, debug) {
|
|
865
|
+
const missing = [];
|
|
866
|
+
for (const varName of required) {
|
|
867
|
+
if (!process.env[varName]) {
|
|
868
|
+
missing.push(varName);
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
if (missing.length > 0) {
|
|
872
|
+
const error = `Required environment variables missing: ${missing.join(", ")}`;
|
|
873
|
+
envLogger.error("Environment validation failed", {
|
|
874
|
+
missing,
|
|
875
|
+
required
|
|
876
|
+
});
|
|
877
|
+
throw new Error(error);
|
|
878
|
+
}
|
|
879
|
+
if (debug) {
|
|
880
|
+
envLogger.debug("Required environment variables validated", {
|
|
881
|
+
required,
|
|
882
|
+
allPresent: true
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
function loadEnvironment(options = {}) {
|
|
887
|
+
const {
|
|
888
|
+
basePath = process.cwd(),
|
|
889
|
+
customPaths = [],
|
|
890
|
+
debug = false,
|
|
891
|
+
nodeEnv = process.env.NODE_ENV || "development",
|
|
892
|
+
required = [],
|
|
893
|
+
useCache = true
|
|
894
|
+
} = options;
|
|
895
|
+
if (useCache && environmentLoaded && cachedLoadResult) {
|
|
896
|
+
if (debug) {
|
|
897
|
+
envLogger.debug("Returning cached environment", {
|
|
898
|
+
loaded: cachedLoadResult.loaded.length,
|
|
899
|
+
variables: Object.keys(cachedLoadResult.parsed).length
|
|
900
|
+
});
|
|
901
|
+
}
|
|
902
|
+
return cachedLoadResult;
|
|
903
|
+
}
|
|
904
|
+
if (debug) {
|
|
905
|
+
envLogger.debug("Loading environment variables", {
|
|
906
|
+
basePath,
|
|
907
|
+
nodeEnv,
|
|
908
|
+
customPaths,
|
|
909
|
+
required
|
|
910
|
+
});
|
|
911
|
+
}
|
|
912
|
+
const result = {
|
|
913
|
+
success: true,
|
|
914
|
+
loaded: [],
|
|
915
|
+
failed: [],
|
|
916
|
+
parsed: {},
|
|
917
|
+
warnings: []
|
|
918
|
+
};
|
|
919
|
+
const standardFiles = buildFileList(basePath, nodeEnv);
|
|
920
|
+
const allFiles = [...standardFiles, ...customPaths];
|
|
921
|
+
if (debug) {
|
|
922
|
+
envLogger.debug("Environment files to load", {
|
|
923
|
+
standardFiles,
|
|
924
|
+
customPaths,
|
|
925
|
+
total: allFiles.length
|
|
926
|
+
});
|
|
927
|
+
}
|
|
928
|
+
const reversedFiles = [...allFiles].reverse();
|
|
929
|
+
for (const filePath of reversedFiles) {
|
|
930
|
+
const fileResult = loadSingleFile(filePath, debug);
|
|
931
|
+
if (fileResult.success) {
|
|
932
|
+
result.loaded.push(filePath);
|
|
933
|
+
Object.assign(result.parsed, fileResult.parsed);
|
|
934
|
+
} else if (fileResult.error) {
|
|
935
|
+
result.failed.push({
|
|
936
|
+
path: filePath,
|
|
937
|
+
reason: fileResult.error
|
|
938
|
+
});
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
if (debug || result.loaded.length > 0) {
|
|
942
|
+
envLogger.info("Environment loading complete", {
|
|
943
|
+
loaded: result.loaded.length,
|
|
944
|
+
failed: result.failed.length,
|
|
945
|
+
variables: Object.keys(result.parsed).length,
|
|
946
|
+
files: result.loaded
|
|
947
|
+
});
|
|
948
|
+
}
|
|
949
|
+
if (required.length > 0) {
|
|
950
|
+
try {
|
|
951
|
+
validateRequiredVars(required, debug);
|
|
952
|
+
} catch (error) {
|
|
953
|
+
result.success = false;
|
|
954
|
+
result.errors = [
|
|
955
|
+
error instanceof Error ? error.message : "Validation failed"
|
|
956
|
+
];
|
|
957
|
+
throw error;
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
environmentLoaded = true;
|
|
961
|
+
cachedLoadResult = result;
|
|
962
|
+
return result;
|
|
963
|
+
}
|
|
964
|
+
|
|
793
965
|
// src/db/manager/factory.ts
|
|
794
966
|
var dbLogger2 = logger.child("database");
|
|
795
967
|
function hasDatabaseConfig() {
|
|
@@ -797,9 +969,24 @@ function hasDatabaseConfig() {
|
|
|
797
969
|
}
|
|
798
970
|
async function createDatabaseFromEnv(options) {
|
|
799
971
|
if (!hasDatabaseConfig()) {
|
|
800
|
-
|
|
972
|
+
dbLogger2.debug("No DATABASE_URL found, loading environment variables");
|
|
973
|
+
const result = loadEnvironment({
|
|
974
|
+
debug: true
|
|
975
|
+
});
|
|
976
|
+
dbLogger2.debug("Environment variables loaded", {
|
|
977
|
+
success: result.success,
|
|
978
|
+
loaded: result.loaded.length,
|
|
979
|
+
hasDatabaseUrl: !!process.env.DATABASE_URL,
|
|
980
|
+
hasWriteUrl: !!process.env.DATABASE_WRITE_URL,
|
|
981
|
+
hasReadUrl: !!process.env.DATABASE_READ_URL
|
|
982
|
+
});
|
|
801
983
|
}
|
|
802
984
|
if (!hasDatabaseConfig()) {
|
|
985
|
+
dbLogger2.warn("No database configuration found", {
|
|
986
|
+
cwd: process.cwd(),
|
|
987
|
+
nodeEnv: process.env.NODE_ENV,
|
|
988
|
+
checkedVars: ["DATABASE_URL", "DATABASE_WRITE_URL", "DATABASE_READ_URL"]
|
|
989
|
+
});
|
|
803
990
|
return { write: void 0, read: void 0 };
|
|
804
991
|
}
|
|
805
992
|
try {
|
|
@@ -880,7 +1067,7 @@ async function createDatabaseFromEnv(options) {
|
|
|
880
1067
|
hasUrl: !!process.env.DATABASE_URL,
|
|
881
1068
|
hasReplicaUrl: !!process.env.DATABASE_REPLICA_URL
|
|
882
1069
|
});
|
|
883
|
-
|
|
1070
|
+
throw new Error(`Database connection failed: ${message}`, { cause: error });
|
|
884
1071
|
}
|
|
885
1072
|
}
|
|
886
1073
|
|
|
@@ -903,28 +1090,28 @@ function setDatabase(write, read) {
|
|
|
903
1090
|
readInstance = read ?? write;
|
|
904
1091
|
}
|
|
905
1092
|
function getHealthCheckConfig(options) {
|
|
906
|
-
const
|
|
1093
|
+
const parseBoolean2 = (value, defaultValue) => {
|
|
907
1094
|
if (value === void 0) return defaultValue;
|
|
908
1095
|
return value.toLowerCase() === "true";
|
|
909
1096
|
};
|
|
910
1097
|
return {
|
|
911
|
-
enabled: options?.enabled ??
|
|
1098
|
+
enabled: options?.enabled ?? parseBoolean2(process.env.DB_HEALTH_CHECK_ENABLED, true),
|
|
912
1099
|
interval: options?.interval ?? (parseInt(process.env.DB_HEALTH_CHECK_INTERVAL || "", 10) || 6e4),
|
|
913
|
-
reconnect: options?.reconnect ??
|
|
1100
|
+
reconnect: options?.reconnect ?? parseBoolean2(process.env.DB_HEALTH_CHECK_RECONNECT, true),
|
|
914
1101
|
maxRetries: options?.maxRetries ?? (parseInt(process.env.DB_HEALTH_CHECK_MAX_RETRIES || "", 10) || 3),
|
|
915
1102
|
retryInterval: options?.retryInterval ?? (parseInt(process.env.DB_HEALTH_CHECK_RETRY_INTERVAL || "", 10) || 5e3)
|
|
916
1103
|
};
|
|
917
1104
|
}
|
|
918
1105
|
function getMonitoringConfig(options) {
|
|
919
1106
|
const isDevelopment = process.env.NODE_ENV !== "production";
|
|
920
|
-
const
|
|
1107
|
+
const parseBoolean2 = (value, defaultValue) => {
|
|
921
1108
|
if (value === void 0) return defaultValue;
|
|
922
1109
|
return value.toLowerCase() === "true";
|
|
923
1110
|
};
|
|
924
1111
|
return {
|
|
925
|
-
enabled: options?.enabled ??
|
|
1112
|
+
enabled: options?.enabled ?? parseBoolean2(process.env.DB_MONITORING_ENABLED, isDevelopment),
|
|
926
1113
|
slowThreshold: options?.slowThreshold ?? (parseInt(process.env.DB_MONITORING_SLOW_THRESHOLD || "", 10) || 1e3),
|
|
927
|
-
logQueries: options?.logQueries ??
|
|
1114
|
+
logQueries: options?.logQueries ?? parseBoolean2(process.env.DB_MONITORING_LOG_QUERIES, false)
|
|
928
1115
|
};
|
|
929
1116
|
}
|
|
930
1117
|
async function initDatabase(options) {
|
|
@@ -962,7 +1149,7 @@ async function initDatabase(options) {
|
|
|
962
1149
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
963
1150
|
dbLogger3.error("Database connection failed", { error: message });
|
|
964
1151
|
await closeDatabase();
|
|
965
|
-
|
|
1152
|
+
throw new Error(`Database connection test failed: ${message}`, { cause: error });
|
|
966
1153
|
}
|
|
967
1154
|
} else {
|
|
968
1155
|
dbLogger3.warn("No database configuration found");
|
|
@@ -1010,14 +1197,14 @@ function getDatabaseInfo() {
|
|
|
1010
1197
|
isReplica: !!(readInstance && readInstance !== writeInstance)
|
|
1011
1198
|
};
|
|
1012
1199
|
}
|
|
1013
|
-
function startHealthCheck(
|
|
1200
|
+
function startHealthCheck(config) {
|
|
1014
1201
|
if (healthCheckInterval) {
|
|
1015
1202
|
dbLogger3.debug("Health check already running");
|
|
1016
1203
|
return;
|
|
1017
1204
|
}
|
|
1018
1205
|
dbLogger3.info("Starting database health check", {
|
|
1019
|
-
interval: `${
|
|
1020
|
-
reconnect:
|
|
1206
|
+
interval: `${config.interval}ms`,
|
|
1207
|
+
reconnect: config.reconnect
|
|
1021
1208
|
});
|
|
1022
1209
|
healthCheckInterval = setInterval(async () => {
|
|
1023
1210
|
try {
|
|
@@ -1033,22 +1220,22 @@ function startHealthCheck(config2) {
|
|
|
1033
1220
|
} catch (error) {
|
|
1034
1221
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
1035
1222
|
dbLogger3.error("Database health check failed", { error: message });
|
|
1036
|
-
if (
|
|
1037
|
-
await attemptReconnection(
|
|
1223
|
+
if (config.reconnect) {
|
|
1224
|
+
await attemptReconnection(config);
|
|
1038
1225
|
}
|
|
1039
1226
|
}
|
|
1040
|
-
},
|
|
1227
|
+
}, config.interval);
|
|
1041
1228
|
}
|
|
1042
|
-
async function attemptReconnection(
|
|
1229
|
+
async function attemptReconnection(config) {
|
|
1043
1230
|
dbLogger3.warn("Attempting database reconnection", {
|
|
1044
|
-
maxRetries:
|
|
1045
|
-
retryInterval: `${
|
|
1231
|
+
maxRetries: config.maxRetries,
|
|
1232
|
+
retryInterval: `${config.retryInterval}ms`
|
|
1046
1233
|
});
|
|
1047
|
-
for (let attempt = 1; attempt <=
|
|
1234
|
+
for (let attempt = 1; attempt <= config.maxRetries; attempt++) {
|
|
1048
1235
|
try {
|
|
1049
|
-
dbLogger3.debug(`Reconnection attempt ${attempt}/${
|
|
1236
|
+
dbLogger3.debug(`Reconnection attempt ${attempt}/${config.maxRetries}`);
|
|
1050
1237
|
await closeDatabase();
|
|
1051
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
1238
|
+
await new Promise((resolve) => setTimeout(resolve, config.retryInterval));
|
|
1052
1239
|
const result = await createDatabaseFromEnv();
|
|
1053
1240
|
if (result.write) {
|
|
1054
1241
|
await result.write.execute("SELECT 1");
|
|
@@ -1064,9 +1251,9 @@ async function attemptReconnection(config2) {
|
|
|
1064
1251
|
dbLogger3.error(`Reconnection attempt ${attempt} failed`, {
|
|
1065
1252
|
error: message,
|
|
1066
1253
|
attempt,
|
|
1067
|
-
maxRetries:
|
|
1254
|
+
maxRetries: config.maxRetries
|
|
1068
1255
|
});
|
|
1069
|
-
if (attempt ===
|
|
1256
|
+
if (attempt === config.maxRetries) {
|
|
1070
1257
|
dbLogger3.error("Max reconnection attempts reached, giving up");
|
|
1071
1258
|
}
|
|
1072
1259
|
}
|
|
@@ -1569,21 +1756,21 @@ var Repository = class {
|
|
|
1569
1756
|
* @returns Result of the operation
|
|
1570
1757
|
*/
|
|
1571
1758
|
async executeWithMonitoring(operation, fn) {
|
|
1572
|
-
const
|
|
1573
|
-
if (!
|
|
1759
|
+
const config = getDatabaseMonitoringConfig();
|
|
1760
|
+
if (!config?.enabled) {
|
|
1574
1761
|
return fn();
|
|
1575
1762
|
}
|
|
1576
1763
|
const startTime = performance.now();
|
|
1577
1764
|
try {
|
|
1578
1765
|
const result = await fn();
|
|
1579
1766
|
const duration = performance.now() - startTime;
|
|
1580
|
-
if (duration >=
|
|
1767
|
+
if (duration >= config.slowThreshold) {
|
|
1581
1768
|
const dbLogger4 = logger.child("database");
|
|
1582
1769
|
const logData = {
|
|
1583
1770
|
operation,
|
|
1584
1771
|
table: this.table._.name,
|
|
1585
1772
|
duration: `${duration.toFixed(2)}ms`,
|
|
1586
|
-
threshold: `${
|
|
1773
|
+
threshold: `${config.slowThreshold}ms`
|
|
1587
1774
|
};
|
|
1588
1775
|
dbLogger4.warn("Slow query detected", logData);
|
|
1589
1776
|
}
|
|
@@ -2063,14 +2250,14 @@ function getDbCredentials(dialect, url) {
|
|
|
2063
2250
|
}
|
|
2064
2251
|
}
|
|
2065
2252
|
function generateDrizzleConfigFile(options = {}) {
|
|
2066
|
-
const
|
|
2253
|
+
const config = getDrizzleConfig(options);
|
|
2067
2254
|
return `import { defineConfig } from 'drizzle-kit';
|
|
2068
2255
|
|
|
2069
2256
|
export default defineConfig({
|
|
2070
|
-
schema: '${
|
|
2071
|
-
out: '${
|
|
2072
|
-
dialect: '${
|
|
2073
|
-
dbCredentials: ${JSON.stringify(
|
|
2257
|
+
schema: '${config.schema}',
|
|
2258
|
+
out: '${config.out}',
|
|
2259
|
+
dialect: '${config.dialect}',
|
|
2260
|
+
dbCredentials: ${JSON.stringify(config.dbCredentials, null, 4)},
|
|
2074
2261
|
});
|
|
2075
2262
|
`;
|
|
2076
2263
|
}
|