@simplysm/orm-node 13.0.0-beta.36 → 13.0.0-beta.41
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/connections/mssql-db-conn.js +2 -2
- package/dist/connections/mssql-db-conn.js.map +2 -2
- package/dist/connections/mysql-db-conn.js +2 -2
- package/dist/connections/mysql-db-conn.js.map +2 -2
- package/dist/connections/postgresql-db-conn.js +2 -2
- package/dist/connections/postgresql-db-conn.js.map +2 -2
- package/dist/pooled-db-conn.js +2 -2
- package/dist/pooled-db-conn.js.map +2 -2
- package/package.json +3 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import consola from "consola";
|
|
2
2
|
import {
|
|
3
3
|
DateOnly,
|
|
4
4
|
DateTime,
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
waitUntil
|
|
12
12
|
} from "@simplysm/core-common";
|
|
13
13
|
import { DB_CONN_DEFAULT_TIMEOUT, DB_CONN_ERRORS } from "../types/db-conn.js";
|
|
14
|
-
const logger =
|
|
14
|
+
const logger = consola.withTag("mssql-db-conn");
|
|
15
15
|
class MssqlDbConn extends EventEmitter {
|
|
16
16
|
constructor(_tedious, config) {
|
|
17
17
|
super();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/connections/mssql-db-conn.ts"],
|
|
4
|
-
"sourcesContent": ["import { createConsola } from \"consola\";\nimport {\n DateOnly,\n DateTime,\n jsonStringify,\n SdError,\n EventEmitter,\n strIsNullOrEmpty,\n Time,\n Uuid,\n waitUntil,\n} from \"@simplysm/core-common\";\nimport type { ColumnMeta, DataType, IsolationLevel } from \"@simplysm/orm-common\";\nimport { DB_CONN_DEFAULT_TIMEOUT, DB_CONN_ERRORS, type DbConn, type MssqlDbConnConfig } from \"../types/db-conn\";\nimport type tediousType from \"tedious\";\nimport type { DataType as TediousDataType } from \"tedious/lib/data-type\";\n\nconst logger = createConsola().withTag(\"mssql-db-conn\");\n\n/**\n * MSSQL \uB370\uC774\uD130\uBCA0\uC774\uC2A4 \uC5F0\uACB0 \uD074\uB798\uC2A4\n *\n * tedious \uB77C\uC774\uBE0C\uB7EC\uB9AC\uB97C \uC0AC\uC6A9\uD558\uC5EC MSSQL/Azure SQL \uC5F0\uACB0\uC744 \uAD00\uB9AC\uD569\uB2C8\uB2E4.\n */\nexport class MssqlDbConn extends EventEmitter<{ close: void }> implements DbConn {\n private readonly _timeout = DB_CONN_DEFAULT_TIMEOUT;\n\n private _conn?: tediousType.Connection;\n private _connTimeout?: ReturnType<typeof setTimeout>;\n private _requests: tediousType.Request[] = [];\n\n isConnected = false;\n isOnTransaction = false;\n\n constructor(\n private readonly _tedious: typeof import(\"tedious\"),\n readonly config: MssqlDbConnConfig,\n ) {\n super();\n }\n\n async connect(): Promise<void> {\n if (this.isConnected) {\n throw new SdError(DB_CONN_ERRORS.ALREADY_CONNECTED);\n }\n\n const conn = new this._tedious.Connection({\n server: this.config.host,\n authentication: {\n type: \"default\",\n options: {\n userName: this.config.username,\n password: this.config.password,\n },\n },\n options: {\n database: this.config.database,\n port: this.config.port,\n rowCollectionOnDone: true,\n useUTC: false,\n encrypt: this.config.dialect === \"mssql-azure\",\n requestTimeout: this._timeout,\n trustServerCertificate: true,\n connectTimeout: this._timeout * 5,\n } as tediousType.ConnectionOptions,\n });\n\n conn.on(\"infoMessage\", (info) => {\n logger.debug(\"info\", info.message);\n });\n\n conn.on(\"errorMessage\", (error) => {\n logger.error(\"errorMessage\", error.message);\n });\n\n conn.on(\"error\", (error) => {\n logger.error(\"error\", error.message);\n });\n\n conn.on(\"end\", () => {\n this.emit(\"close\");\n this._resetState();\n });\n\n await new Promise<void>((resolve, reject) => {\n conn.connect((err: Error | undefined) => {\n if (err != null) {\n reject(new SdError(err));\n return;\n }\n\n this._startTimeout();\n this.isConnected = true;\n this.isOnTransaction = false;\n resolve();\n });\n });\n\n this._conn = conn;\n }\n\n async close(): Promise<void> {\n this._stopTimeout();\n\n if (this._conn == null || !this.isConnected) {\n return;\n }\n\n const conn = this._conn;\n\n // \uC9C4\uD589 \uC911\uC778 \uC694\uCCAD \uCDE8\uC18C\n conn.cancel();\n await waitUntil(() => this._requests.length < 1, 30000, 100);\n\n // \uC5F0\uACB0 \uC885\uB8CC \uB300\uAE30\n await new Promise<void>((resolve) => {\n conn.on(\"end\", () => {\n waitUntil(() => this._conn == null, 30000, 100)\n .then(() => resolve())\n .catch(() => resolve());\n });\n conn.close();\n });\n }\n\n async beginTransaction(isolationLevel?: IsolationLevel): Promise<void> {\n this._assertConnected();\n this._startTimeout();\n\n const conn = this._conn!;\n\n await new Promise<void>((resolve, reject) => {\n conn.beginTransaction(\n (err) => {\n if (err != null) {\n reject(new SdError(err));\n return;\n }\n\n this.isOnTransaction = true;\n resolve();\n },\n \"\",\n this._tedious.ISOLATION_LEVEL[isolationLevel ?? this.config.defaultIsolationLevel ?? \"READ_UNCOMMITTED\"],\n );\n });\n }\n\n async commitTransaction(): Promise<void> {\n this._assertConnected();\n this._startTimeout();\n\n const conn = this._conn!;\n\n await new Promise<void>((resolve, reject) => {\n conn.commitTransaction((err) => {\n if (err != null) {\n reject(new SdError(err));\n return;\n }\n\n this.isOnTransaction = false;\n resolve();\n });\n });\n }\n\n async rollbackTransaction(): Promise<void> {\n this._assertConnected();\n this._startTimeout();\n\n const conn = this._conn!;\n\n await new Promise<void>((resolve, reject) => {\n conn.rollbackTransaction((err) => {\n if (err != null) {\n reject(new SdError(err));\n return;\n }\n\n this.isOnTransaction = false;\n resolve();\n });\n });\n }\n\n async execute(queries: string[]): Promise<unknown[][]> {\n const results: unknown[][] = [];\n for (const query of queries.filter((item) => !strIsNullOrEmpty(item))) {\n const resultItems = await this.executeParametrized(query);\n results.push(...resultItems);\n }\n\n return results;\n }\n\n async executeParametrized(query: string, params?: unknown[]): Promise<unknown[][]> {\n this._assertConnected();\n this._startTimeout();\n\n const conn = this._conn!;\n\n const results: unknown[][] = [];\n\n logger.debug(\"\uCFFC\uB9AC \uC2E4\uD589\", { queryLength: query.length, params });\n await new Promise<void>((resolve, reject) => {\n let rejected = false;\n const queryRequest = new this._tedious.Request(query, (err) => {\n if (err != null) {\n rejected = true;\n this._requests = this._requests.filter((r) => r !== queryRequest);\n\n const errRec = err as unknown as Record<string, unknown>;\n if (errRec[\"code\"] === \"ECANCEL\") {\n reject(new SdError(err, \"\uCFFC\uB9AC\uAC00 \uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4.\"));\n } else {\n const lineNumber = errRec[\"lineNumber\"] as number | undefined;\n if (lineNumber != null && lineNumber > 0) {\n const splitQuery = query.split(\"\\n\");\n splitQuery[lineNumber - 1] = \"==> \" + splitQuery[lineNumber - 1];\n reject(new SdError(err, `\uCFFC\uB9AC \uC218\uD589\uC911 \uC624\uB958\uBC1C\uC0DD\\n-- query\\n${splitQuery.join(\"\\n\")}\\n--`));\n } else {\n reject(new SdError(err, `\uCFFC\uB9AC \uC218\uD589\uC911 \uC624\uB958\uBC1C\uC0DD\\n-- query\\n${query}\\n--`));\n }\n }\n }\n });\n\n queryRequest\n .on(\"done\", (_rowCount, _more, rst) => {\n this._startTimeout();\n\n if (rejected) {\n return;\n }\n\n results.push(this._parseRowsToRecords(rst));\n })\n .on(\"doneInProc\", (_rowCount, _more, rst) => {\n this._startTimeout();\n\n if (rejected) {\n return;\n }\n\n results.push(this._parseRowsToRecords(rst));\n })\n .on(\"error\", (err) => {\n this._startTimeout();\n\n if (rejected) {\n return;\n }\n\n rejected = true;\n this._requests = this._requests.filter((r) => r !== queryRequest);\n reject(new SdError(err, `\uCFFC\uB9AC \uC218\uD589\uC911 \uC624\uB958\uBC1C\uC0DD\\n-- query\\n${query}\\n--`));\n })\n .on(\"requestCompleted\", () => {\n this._startTimeout();\n\n if (rejected) {\n return;\n }\n\n this._requests = this._requests.filter((r) => r !== queryRequest);\n resolve();\n });\n\n this._requests.push(queryRequest);\n\n if (params != null) {\n for (let i = 0; i < params.length; i++) {\n const paramValue = params[i];\n const paramName = `p${i}`;\n const type = this._guessTediousType(paramValue);\n\n queryRequest.addParameter(paramName, type, paramValue);\n }\n\n conn.execSql(queryRequest);\n } else {\n conn.execSqlBatch(queryRequest);\n }\n });\n\n return results;\n }\n\n async bulkInsert(\n tableName: string,\n columnMetas: Record<string, ColumnMeta>,\n records: Record<string, unknown>[],\n ): Promise<void> {\n if (records.length === 0) return;\n\n this._assertConnected();\n this._startTimeout();\n\n const tediousColumnDefs = Object.entries(columnMetas).map(([name, meta]) =>\n this._convertColumnMetaToTediousBulkColumnDef(name, meta),\n );\n\n await new Promise<void>((resolve, reject) => {\n const bulkLoad = this._conn!.newBulkLoad(tableName, (err) => {\n if (err != null) {\n reject(\n new SdError(\n err,\n `Bulk Insert \uC624\uB958\uBC1C\uC0DD\\n${jsonStringify(tediousColumnDefs)}\\n-- data\\n${jsonStringify(records).substring(0, 10000)}...\\n--`,\n ),\n );\n return;\n }\n resolve();\n });\n\n const colNames = Object.keys(columnMetas);\n\n for (const tediousColumnDef of tediousColumnDefs) {\n bulkLoad.addColumn(tediousColumnDef.name, tediousColumnDef.type, tediousColumnDef.options);\n }\n\n // \uB808\uCF54\uB4DC\uB97C row \uBC30\uC5F4\uB85C \uBCC0\uD658 (\uCEEC\uB7FC \uC21C\uC11C \uC720\uC9C0, \uAC12 \uBCC0\uD658 \uD3EC\uD568)\n const rows = records.map((record) =>\n colNames.map((colName) => {\n const val = record[colName];\n if (val instanceof Uuid) return val.toString();\n // eslint-disable-next-line no-restricted-globals -- tedious \uB77C\uC774\uBE0C\uB7EC\uB9AC\uAC00 Buffer\uB97C \uC694\uAD6C\uD568\n if (val instanceof Uint8Array) return Buffer.from(val);\n if (val instanceof DateTime) return val.date;\n if (val instanceof DateOnly) return val.date;\n if (val instanceof Time) return val.toFormatString(\"HH:mm:ss\");\n return val;\n }),\n );\n\n this._conn!.execBulkLoad(bulkLoad, rows);\n });\n }\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Private helpers\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private _assertConnected(): void {\n if (this._conn == null || !this.isConnected) {\n throw new SdError(DB_CONN_ERRORS.NOT_CONNECTED);\n }\n }\n\n private _parseRowsToRecords(\n rows: Array<Array<{ metadata: { colName: string }; value: unknown }>> | undefined,\n ): Record<string, unknown>[] {\n return (rows ?? []).map((item) => {\n const resultItem: Record<string, unknown> = {};\n for (const col of item) {\n resultItem[col.metadata.colName] = col.value;\n }\n return resultItem;\n });\n }\n\n private _resetState(): void {\n this.isConnected = false;\n this.isOnTransaction = false;\n this._conn = undefined;\n this._requests = [];\n }\n\n private _stopTimeout(): void {\n if (this._connTimeout != null) {\n clearTimeout(this._connTimeout);\n }\n }\n\n private _startTimeout(): void {\n this._stopTimeout();\n this._connTimeout = setTimeout(() => {\n this.close().catch((err) => {\n logger.error(\"close error\", err instanceof Error ? err.message : String(err));\n });\n }, this._timeout * 2);\n }\n\n private _convertColumnMetaToTediousBulkColumnDef(\n name: string,\n meta: ColumnMeta,\n ): {\n name: string;\n type: TediousDataType;\n options: TediousColumnOptions;\n } {\n const tediousDataType = this._convertDataTypeToTediousBulkColumnType(meta.dataType);\n return {\n name,\n type: tediousDataType.type,\n options: {\n length: tediousDataType.length,\n nullable: meta.nullable ?? false,\n precision: tediousDataType.precision,\n scale: tediousDataType.scale,\n },\n };\n }\n\n private _convertDataTypeToTediousBulkColumnType(dataType: DataType): {\n type: TediousDataType;\n length?: number;\n precision?: number;\n scale?: number;\n } {\n switch (dataType.type) {\n case \"int\":\n return { type: this._tedious.TYPES.Int };\n case \"bigint\":\n return { type: this._tedious.TYPES.BigInt };\n case \"float\":\n return { type: this._tedious.TYPES.Real };\n case \"double\":\n return { type: this._tedious.TYPES.Float };\n case \"decimal\":\n return {\n type: this._tedious.TYPES.Decimal,\n precision: dataType.precision,\n scale: dataType.scale,\n };\n case \"varchar\":\n return { type: this._tedious.TYPES.NVarChar, length: dataType.length };\n case \"char\":\n return { type: this._tedious.TYPES.NChar, length: dataType.length };\n case \"text\":\n return { type: this._tedious.TYPES.NText };\n case \"binary\":\n return { type: this._tedious.TYPES.VarBinary, length: Infinity };\n case \"boolean\":\n return { type: this._tedious.TYPES.Bit };\n case \"datetime\":\n return { type: this._tedious.TYPES.DateTime2 };\n case \"date\":\n return { type: this._tedious.TYPES.Date };\n case \"time\":\n return { type: this._tedious.TYPES.Time };\n case \"uuid\":\n return { type: this._tedious.TYPES.UniqueIdentifier };\n default:\n throw new SdError(`\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 DataType: ${JSON.stringify(dataType)}`);\n }\n }\n\n /**\n * \uAC12\uC758 \uD0C0\uC785\uC744 \uCD94\uB860\uD558\uC5EC Tedious \uB370\uC774\uD130 \uD0C0\uC785 \uBC18\uD658\n *\n * @param value - \uD0C0\uC785\uC744 \uCD94\uB860\uD560 \uAC12 (null/undefined \uC804\uB2EC \uC2DC \uC624\uB958 \uBC1C\uC0DD)\n * @throws null/undefined\uAC00 \uC804\uB2EC\uB418\uBA74 \uC624\uB958 \uBC1C\uC0DD\n */\n private _guessTediousType(value: unknown): TediousDataType {\n if (value == null) {\n throw new SdError(\"_guessTediousType: null/undefined \uAC12\uC740 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.\");\n }\n if (typeof value === \"string\") {\n return this._tedious.TYPES.NVarChar;\n }\n if (typeof value === \"number\") {\n return Number.isInteger(value) ? this._tedious.TYPES.BigInt : this._tedious.TYPES.Decimal;\n }\n if (typeof value === \"boolean\") return this._tedious.TYPES.Bit;\n if (value instanceof DateTime) return this._tedious.TYPES.DateTime2;\n if (value instanceof DateOnly) return this._tedious.TYPES.Date;\n if (value instanceof Time) return this._tedious.TYPES.Time;\n if (value instanceof Uuid) return this._tedious.TYPES.UniqueIdentifier;\n if (value instanceof Uint8Array) return this._tedious.TYPES.VarBinary;\n\n throw new SdError(`\uC54C \uC218 \uC5C6\uB294 \uAC12 \uD0C0\uC785: ${typeof value}`);\n }\n}\n\ninterface TediousColumnOptions {\n length?: number;\n precision?: number;\n scale?: number;\n nullable?: boolean;\n}\n"],
|
|
5
|
-
"mappings": "AAAA,
|
|
4
|
+
"sourcesContent": ["import consola from \"consola\";\nimport {\n DateOnly,\n DateTime,\n jsonStringify,\n SdError,\n EventEmitter,\n strIsNullOrEmpty,\n Time,\n Uuid,\n waitUntil,\n} from \"@simplysm/core-common\";\nimport type { ColumnMeta, DataType, IsolationLevel } from \"@simplysm/orm-common\";\nimport { DB_CONN_DEFAULT_TIMEOUT, DB_CONN_ERRORS, type DbConn, type MssqlDbConnConfig } from \"../types/db-conn\";\nimport type tediousType from \"tedious\";\nimport type { DataType as TediousDataType } from \"tedious/lib/data-type\";\n\nconst logger = consola.withTag(\"mssql-db-conn\");\n\n/**\n * MSSQL \uB370\uC774\uD130\uBCA0\uC774\uC2A4 \uC5F0\uACB0 \uD074\uB798\uC2A4\n *\n * tedious \uB77C\uC774\uBE0C\uB7EC\uB9AC\uB97C \uC0AC\uC6A9\uD558\uC5EC MSSQL/Azure SQL \uC5F0\uACB0\uC744 \uAD00\uB9AC\uD569\uB2C8\uB2E4.\n */\nexport class MssqlDbConn extends EventEmitter<{ close: void }> implements DbConn {\n private readonly _timeout = DB_CONN_DEFAULT_TIMEOUT;\n\n private _conn?: tediousType.Connection;\n private _connTimeout?: ReturnType<typeof setTimeout>;\n private _requests: tediousType.Request[] = [];\n\n isConnected = false;\n isOnTransaction = false;\n\n constructor(\n private readonly _tedious: typeof import(\"tedious\"),\n readonly config: MssqlDbConnConfig,\n ) {\n super();\n }\n\n async connect(): Promise<void> {\n if (this.isConnected) {\n throw new SdError(DB_CONN_ERRORS.ALREADY_CONNECTED);\n }\n\n const conn = new this._tedious.Connection({\n server: this.config.host,\n authentication: {\n type: \"default\",\n options: {\n userName: this.config.username,\n password: this.config.password,\n },\n },\n options: {\n database: this.config.database,\n port: this.config.port,\n rowCollectionOnDone: true,\n useUTC: false,\n encrypt: this.config.dialect === \"mssql-azure\",\n requestTimeout: this._timeout,\n trustServerCertificate: true,\n connectTimeout: this._timeout * 5,\n } as tediousType.ConnectionOptions,\n });\n\n conn.on(\"infoMessage\", (info) => {\n logger.debug(\"info\", info.message);\n });\n\n conn.on(\"errorMessage\", (error) => {\n logger.error(\"errorMessage\", error.message);\n });\n\n conn.on(\"error\", (error) => {\n logger.error(\"error\", error.message);\n });\n\n conn.on(\"end\", () => {\n this.emit(\"close\");\n this._resetState();\n });\n\n await new Promise<void>((resolve, reject) => {\n conn.connect((err: Error | undefined) => {\n if (err != null) {\n reject(new SdError(err));\n return;\n }\n\n this._startTimeout();\n this.isConnected = true;\n this.isOnTransaction = false;\n resolve();\n });\n });\n\n this._conn = conn;\n }\n\n async close(): Promise<void> {\n this._stopTimeout();\n\n if (this._conn == null || !this.isConnected) {\n return;\n }\n\n const conn = this._conn;\n\n // \uC9C4\uD589 \uC911\uC778 \uC694\uCCAD \uCDE8\uC18C\n conn.cancel();\n await waitUntil(() => this._requests.length < 1, 30000, 100);\n\n // \uC5F0\uACB0 \uC885\uB8CC \uB300\uAE30\n await new Promise<void>((resolve) => {\n conn.on(\"end\", () => {\n waitUntil(() => this._conn == null, 30000, 100)\n .then(() => resolve())\n .catch(() => resolve());\n });\n conn.close();\n });\n }\n\n async beginTransaction(isolationLevel?: IsolationLevel): Promise<void> {\n this._assertConnected();\n this._startTimeout();\n\n const conn = this._conn!;\n\n await new Promise<void>((resolve, reject) => {\n conn.beginTransaction(\n (err) => {\n if (err != null) {\n reject(new SdError(err));\n return;\n }\n\n this.isOnTransaction = true;\n resolve();\n },\n \"\",\n this._tedious.ISOLATION_LEVEL[isolationLevel ?? this.config.defaultIsolationLevel ?? \"READ_UNCOMMITTED\"],\n );\n });\n }\n\n async commitTransaction(): Promise<void> {\n this._assertConnected();\n this._startTimeout();\n\n const conn = this._conn!;\n\n await new Promise<void>((resolve, reject) => {\n conn.commitTransaction((err) => {\n if (err != null) {\n reject(new SdError(err));\n return;\n }\n\n this.isOnTransaction = false;\n resolve();\n });\n });\n }\n\n async rollbackTransaction(): Promise<void> {\n this._assertConnected();\n this._startTimeout();\n\n const conn = this._conn!;\n\n await new Promise<void>((resolve, reject) => {\n conn.rollbackTransaction((err) => {\n if (err != null) {\n reject(new SdError(err));\n return;\n }\n\n this.isOnTransaction = false;\n resolve();\n });\n });\n }\n\n async execute(queries: string[]): Promise<unknown[][]> {\n const results: unknown[][] = [];\n for (const query of queries.filter((item) => !strIsNullOrEmpty(item))) {\n const resultItems = await this.executeParametrized(query);\n results.push(...resultItems);\n }\n\n return results;\n }\n\n async executeParametrized(query: string, params?: unknown[]): Promise<unknown[][]> {\n this._assertConnected();\n this._startTimeout();\n\n const conn = this._conn!;\n\n const results: unknown[][] = [];\n\n logger.debug(\"\uCFFC\uB9AC \uC2E4\uD589\", { queryLength: query.length, params });\n await new Promise<void>((resolve, reject) => {\n let rejected = false;\n const queryRequest = new this._tedious.Request(query, (err) => {\n if (err != null) {\n rejected = true;\n this._requests = this._requests.filter((r) => r !== queryRequest);\n\n const errRec = err as unknown as Record<string, unknown>;\n if (errRec[\"code\"] === \"ECANCEL\") {\n reject(new SdError(err, \"\uCFFC\uB9AC\uAC00 \uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4.\"));\n } else {\n const lineNumber = errRec[\"lineNumber\"] as number | undefined;\n if (lineNumber != null && lineNumber > 0) {\n const splitQuery = query.split(\"\\n\");\n splitQuery[lineNumber - 1] = \"==> \" + splitQuery[lineNumber - 1];\n reject(new SdError(err, `\uCFFC\uB9AC \uC218\uD589\uC911 \uC624\uB958\uBC1C\uC0DD\\n-- query\\n${splitQuery.join(\"\\n\")}\\n--`));\n } else {\n reject(new SdError(err, `\uCFFC\uB9AC \uC218\uD589\uC911 \uC624\uB958\uBC1C\uC0DD\\n-- query\\n${query}\\n--`));\n }\n }\n }\n });\n\n queryRequest\n .on(\"done\", (_rowCount, _more, rst) => {\n this._startTimeout();\n\n if (rejected) {\n return;\n }\n\n results.push(this._parseRowsToRecords(rst));\n })\n .on(\"doneInProc\", (_rowCount, _more, rst) => {\n this._startTimeout();\n\n if (rejected) {\n return;\n }\n\n results.push(this._parseRowsToRecords(rst));\n })\n .on(\"error\", (err) => {\n this._startTimeout();\n\n if (rejected) {\n return;\n }\n\n rejected = true;\n this._requests = this._requests.filter((r) => r !== queryRequest);\n reject(new SdError(err, `\uCFFC\uB9AC \uC218\uD589\uC911 \uC624\uB958\uBC1C\uC0DD\\n-- query\\n${query}\\n--`));\n })\n .on(\"requestCompleted\", () => {\n this._startTimeout();\n\n if (rejected) {\n return;\n }\n\n this._requests = this._requests.filter((r) => r !== queryRequest);\n resolve();\n });\n\n this._requests.push(queryRequest);\n\n if (params != null) {\n for (let i = 0; i < params.length; i++) {\n const paramValue = params[i];\n const paramName = `p${i}`;\n const type = this._guessTediousType(paramValue);\n\n queryRequest.addParameter(paramName, type, paramValue);\n }\n\n conn.execSql(queryRequest);\n } else {\n conn.execSqlBatch(queryRequest);\n }\n });\n\n return results;\n }\n\n async bulkInsert(\n tableName: string,\n columnMetas: Record<string, ColumnMeta>,\n records: Record<string, unknown>[],\n ): Promise<void> {\n if (records.length === 0) return;\n\n this._assertConnected();\n this._startTimeout();\n\n const tediousColumnDefs = Object.entries(columnMetas).map(([name, meta]) =>\n this._convertColumnMetaToTediousBulkColumnDef(name, meta),\n );\n\n await new Promise<void>((resolve, reject) => {\n const bulkLoad = this._conn!.newBulkLoad(tableName, (err) => {\n if (err != null) {\n reject(\n new SdError(\n err,\n `Bulk Insert \uC624\uB958\uBC1C\uC0DD\\n${jsonStringify(tediousColumnDefs)}\\n-- data\\n${jsonStringify(records).substring(0, 10000)}...\\n--`,\n ),\n );\n return;\n }\n resolve();\n });\n\n const colNames = Object.keys(columnMetas);\n\n for (const tediousColumnDef of tediousColumnDefs) {\n bulkLoad.addColumn(tediousColumnDef.name, tediousColumnDef.type, tediousColumnDef.options);\n }\n\n // \uB808\uCF54\uB4DC\uB97C row \uBC30\uC5F4\uB85C \uBCC0\uD658 (\uCEEC\uB7FC \uC21C\uC11C \uC720\uC9C0, \uAC12 \uBCC0\uD658 \uD3EC\uD568)\n const rows = records.map((record) =>\n colNames.map((colName) => {\n const val = record[colName];\n if (val instanceof Uuid) return val.toString();\n // eslint-disable-next-line no-restricted-globals -- tedious \uB77C\uC774\uBE0C\uB7EC\uB9AC\uAC00 Buffer\uB97C \uC694\uAD6C\uD568\n if (val instanceof Uint8Array) return Buffer.from(val);\n if (val instanceof DateTime) return val.date;\n if (val instanceof DateOnly) return val.date;\n if (val instanceof Time) return val.toFormatString(\"HH:mm:ss\");\n return val;\n }),\n );\n\n this._conn!.execBulkLoad(bulkLoad, rows);\n });\n }\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Private helpers\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private _assertConnected(): void {\n if (this._conn == null || !this.isConnected) {\n throw new SdError(DB_CONN_ERRORS.NOT_CONNECTED);\n }\n }\n\n private _parseRowsToRecords(\n rows: Array<Array<{ metadata: { colName: string }; value: unknown }>> | undefined,\n ): Record<string, unknown>[] {\n return (rows ?? []).map((item) => {\n const resultItem: Record<string, unknown> = {};\n for (const col of item) {\n resultItem[col.metadata.colName] = col.value;\n }\n return resultItem;\n });\n }\n\n private _resetState(): void {\n this.isConnected = false;\n this.isOnTransaction = false;\n this._conn = undefined;\n this._requests = [];\n }\n\n private _stopTimeout(): void {\n if (this._connTimeout != null) {\n clearTimeout(this._connTimeout);\n }\n }\n\n private _startTimeout(): void {\n this._stopTimeout();\n this._connTimeout = setTimeout(() => {\n this.close().catch((err) => {\n logger.error(\"close error\", err instanceof Error ? err.message : String(err));\n });\n }, this._timeout * 2);\n }\n\n private _convertColumnMetaToTediousBulkColumnDef(\n name: string,\n meta: ColumnMeta,\n ): {\n name: string;\n type: TediousDataType;\n options: TediousColumnOptions;\n } {\n const tediousDataType = this._convertDataTypeToTediousBulkColumnType(meta.dataType);\n return {\n name,\n type: tediousDataType.type,\n options: {\n length: tediousDataType.length,\n nullable: meta.nullable ?? false,\n precision: tediousDataType.precision,\n scale: tediousDataType.scale,\n },\n };\n }\n\n private _convertDataTypeToTediousBulkColumnType(dataType: DataType): {\n type: TediousDataType;\n length?: number;\n precision?: number;\n scale?: number;\n } {\n switch (dataType.type) {\n case \"int\":\n return { type: this._tedious.TYPES.Int };\n case \"bigint\":\n return { type: this._tedious.TYPES.BigInt };\n case \"float\":\n return { type: this._tedious.TYPES.Real };\n case \"double\":\n return { type: this._tedious.TYPES.Float };\n case \"decimal\":\n return {\n type: this._tedious.TYPES.Decimal,\n precision: dataType.precision,\n scale: dataType.scale,\n };\n case \"varchar\":\n return { type: this._tedious.TYPES.NVarChar, length: dataType.length };\n case \"char\":\n return { type: this._tedious.TYPES.NChar, length: dataType.length };\n case \"text\":\n return { type: this._tedious.TYPES.NText };\n case \"binary\":\n return { type: this._tedious.TYPES.VarBinary, length: Infinity };\n case \"boolean\":\n return { type: this._tedious.TYPES.Bit };\n case \"datetime\":\n return { type: this._tedious.TYPES.DateTime2 };\n case \"date\":\n return { type: this._tedious.TYPES.Date };\n case \"time\":\n return { type: this._tedious.TYPES.Time };\n case \"uuid\":\n return { type: this._tedious.TYPES.UniqueIdentifier };\n default:\n throw new SdError(`\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 DataType: ${JSON.stringify(dataType)}`);\n }\n }\n\n /**\n * \uAC12\uC758 \uD0C0\uC785\uC744 \uCD94\uB860\uD558\uC5EC Tedious \uB370\uC774\uD130 \uD0C0\uC785 \uBC18\uD658\n *\n * @param value - \uD0C0\uC785\uC744 \uCD94\uB860\uD560 \uAC12 (null/undefined \uC804\uB2EC \uC2DC \uC624\uB958 \uBC1C\uC0DD)\n * @throws null/undefined\uAC00 \uC804\uB2EC\uB418\uBA74 \uC624\uB958 \uBC1C\uC0DD\n */\n private _guessTediousType(value: unknown): TediousDataType {\n if (value == null) {\n throw new SdError(\"_guessTediousType: null/undefined \uAC12\uC740 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.\");\n }\n if (typeof value === \"string\") {\n return this._tedious.TYPES.NVarChar;\n }\n if (typeof value === \"number\") {\n return Number.isInteger(value) ? this._tedious.TYPES.BigInt : this._tedious.TYPES.Decimal;\n }\n if (typeof value === \"boolean\") return this._tedious.TYPES.Bit;\n if (value instanceof DateTime) return this._tedious.TYPES.DateTime2;\n if (value instanceof DateOnly) return this._tedious.TYPES.Date;\n if (value instanceof Time) return this._tedious.TYPES.Time;\n if (value instanceof Uuid) return this._tedious.TYPES.UniqueIdentifier;\n if (value instanceof Uint8Array) return this._tedious.TYPES.VarBinary;\n\n throw new SdError(`\uC54C \uC218 \uC5C6\uB294 \uAC12 \uD0C0\uC785: ${typeof value}`);\n }\n}\n\ninterface TediousColumnOptions {\n length?: number;\n precision?: number;\n scale?: number;\n nullable?: boolean;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -2,7 +2,7 @@ import { randomUUID } from "crypto";
|
|
|
2
2
|
import fs from "fs";
|
|
3
3
|
import os from "os";
|
|
4
4
|
import path from "path";
|
|
5
|
-
import
|
|
5
|
+
import consola from "consola";
|
|
6
6
|
import {
|
|
7
7
|
bytesToHex,
|
|
8
8
|
DateOnly,
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
Uuid
|
|
15
15
|
} from "@simplysm/core-common";
|
|
16
16
|
import { DB_CONN_DEFAULT_TIMEOUT, DB_CONN_ERRORS } from "../types/db-conn.js";
|
|
17
|
-
const logger =
|
|
17
|
+
const logger = consola.withTag("mysql-db-conn");
|
|
18
18
|
class MysqlDbConn extends EventEmitter {
|
|
19
19
|
constructor(_mysql2, config) {
|
|
20
20
|
super();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/connections/mysql-db-conn.ts"],
|
|
4
|
-
"sourcesContent": ["import { randomUUID } from \"crypto\";\nimport fs from \"fs\";\nimport os from \"os\";\nimport path from \"path\";\nimport type { Connection } from \"mysql2/promise\";\nimport { createConsola } from \"consola\";\nimport {\n bytesToHex,\n DateOnly,\n DateTime,\n SdError,\n EventEmitter,\n strIsNullOrEmpty,\n Time,\n Uuid,\n} from \"@simplysm/core-common\";\nimport type { ColumnMeta, DataType, IsolationLevel } from \"@simplysm/orm-common\";\nimport { DB_CONN_DEFAULT_TIMEOUT, DB_CONN_ERRORS, type DbConn, type MysqlDbConnConfig } from \"../types/db-conn\";\n\nconst logger = createConsola().withTag(\"mysql-db-conn\");\n\n/**\n * MySQL \uB370\uC774\uD130\uBCA0\uC774\uC2A4 \uC5F0\uACB0 \uD074\uB798\uC2A4\n *\n * mysql2/promise \uB77C\uC774\uBE0C\uB7EC\uB9AC\uB97C \uC0AC\uC6A9\uD558\uC5EC MySQL \uC5F0\uACB0\uC744 \uAD00\uB9AC\uD569\uB2C8\uB2E4.\n */\nexport class MysqlDbConn extends EventEmitter<{ close: void }> implements DbConn {\n private static readonly _ROOT_USER = \"root\";\n private readonly _timeout = DB_CONN_DEFAULT_TIMEOUT;\n\n private _conn?: Connection;\n private _connTimeout?: ReturnType<typeof setTimeout>;\n\n isConnected = false;\n isOnTransaction = false;\n\n constructor(\n private readonly _mysql2: typeof import(\"mysql2/promise\"),\n readonly config: MysqlDbConnConfig,\n ) {\n super();\n }\n\n async connect(): Promise<void> {\n if (this.isConnected) {\n throw new SdError(DB_CONN_ERRORS.ALREADY_CONNECTED);\n }\n\n const conn = await this._mysql2.createConnection({\n host: this.config.host,\n port: this.config.port,\n user: this.config.username,\n password: this.config.password,\n // root \uC0AC\uC6A9\uC790\uB294 \uD2B9\uC815 database\uC5D0 \uBC14\uC778\uB529\uB418\uC9C0 \uC54A\uACE0 \uC5F0\uACB0\uD558\uC5EC\n // \uBAA8\uB4E0 \uB370\uC774\uD130\uBCA0\uC774\uC2A4\uC5D0 \uC811\uADFC\uD560 \uC218 \uC788\uB3C4\uB85D \uD568 (\uAD00\uB9AC \uC791\uC5C5\uC6A9)\n database: this.config.username === MysqlDbConn._ROOT_USER ? undefined : this.config.database,\n multipleStatements: true,\n charset: \"utf8mb4\",\n infileStreamFactory: (filePath: string) => fs.createReadStream(filePath), // LOAD DATA LOCAL INFILE \uC9C0\uC6D0\n } as Parameters<typeof this._mysql2.createConnection>[0]);\n\n conn.on(\"end\", () => {\n this.emit(\"close\");\n this._resetState();\n });\n\n conn.on(\"error\", (error) => {\n logger.error(\"DB \uC5F0\uACB0 \uC624\uB958\", error.message);\n });\n\n this._conn = conn;\n this._startTimeout();\n this.isConnected = true;\n }\n\n async close(): Promise<void> {\n this._stopTimeout();\n\n if (this._conn == null || !this.isConnected) {\n return;\n }\n\n await this._conn.end();\n\n this.emit(\"close\");\n this._resetState();\n }\n\n async beginTransaction(isolationLevel?: IsolationLevel): Promise<void> {\n const conn = this._assertConnected();\n\n const level = (isolationLevel ?? this.config.defaultIsolationLevel ?? \"READ_UNCOMMITTED\").replace(/_/g, \" \");\n\n // \uACA9\uB9AC \uC218\uC900\uC744 \uBA3C\uC800 \uC124\uC815 (\uB2E4\uC74C \uD2B8\uB79C\uC7AD\uC158\uC5D0 \uC801\uC6A9\uB428)\n await conn.query({\n sql: `SET SESSION TRANSACTION ISOLATION LEVEL ${level}`,\n timeout: this._timeout,\n });\n\n // \uADF8 \uB2E4\uC74C \uD2B8\uB79C\uC7AD\uC158 \uC2DC\uC791\n await conn.beginTransaction();\n\n this.isOnTransaction = true;\n }\n\n async commitTransaction(): Promise<void> {\n const conn = this._assertConnected();\n await conn.commit();\n this.isOnTransaction = false;\n }\n\n async rollbackTransaction(): Promise<void> {\n const conn = this._assertConnected();\n await conn.rollback();\n this.isOnTransaction = false;\n }\n\n async execute(queries: string[]): Promise<unknown[][]> {\n const results: unknown[][] = [];\n for (const query of queries.filter((item) => !strIsNullOrEmpty(item))) {\n const resultItems = await this.executeParametrized(query);\n results.push(...resultItems);\n }\n return results;\n }\n\n async executeParametrized(query: string, params?: unknown[]): Promise<unknown[][]> {\n const conn = this._assertConnected();\n\n logger.debug(\"\uCFFC\uB9AC \uC2E4\uD589\", { queryLength: query.length, params });\n\n try {\n const [queryResults] = await conn.query({\n sql: query,\n timeout: this._timeout,\n values: params,\n });\n\n this._startTimeout();\n\n // MySQL\uC740 INSERT/UPDATE/DELETE \uBB38\uC5D0 \uB300\uD574 ResultSetHeader\uB97C \uBC18\uD658\uD568\n // SELECT \uACB0\uACFC\uB9CC \uCD94\uCD9C\uD558\uAE30 \uC704\uD574 ResultSetHeader \uAC1D\uCCB4\uB97C \uD544\uD130\uB9C1\uD568\n // ResultSetHeader\uB294 affectedRows, fieldCount \uB4F1\uC758 \uD544\uB4DC\uB97C \uAC00\uC9C0\uACE0 \uC788\uC74C\n const result: unknown[] = [];\n if (queryResults instanceof Array) {\n for (const queryResult of queryResults.filter(\n (item: unknown) =>\n !(typeof item === \"object\" && item !== null && \"affectedRows\" in item && \"fieldCount\" in item),\n )) {\n result.push(queryResult);\n }\n }\n\n return [result];\n } catch (err) {\n this._startTimeout();\n const error = err as Error & { sql?: string };\n throw new SdError(\n error,\n \"\uCFFC\uB9AC \uC218\uD589\uC911 \uC624\uB958\uBC1C\uC0DD\" + (error.sql != null ? \"\\n-- query\\n\" + error.sql.trim() + \"\\n--\" : \"\"),\n );\n }\n }\n\n async bulkInsert(\n tableName: string,\n columnMetas: Record<string, ColumnMeta>,\n records: Record<string, unknown>[],\n ): Promise<void> {\n const conn = this._assertConnected();\n\n if (records.length === 0) return;\n\n const colNames = Object.keys(columnMetas);\n\n // \uC784\uC2DC CSV \uD30C\uC77C \uC0DD\uC131\n const tmpDir = os.tmpdir();\n const tmpFile = path.join(tmpDir, `mysql_bulk_${randomUUID()}.csv`);\n\n try {\n // CSV \uB370\uC774\uD130 \uC0DD\uC131\n const csvLines: string[] = [];\n for (const record of records) {\n const row = colNames.map((colName) => this._escapeForCsv(record[colName], columnMetas[colName].dataType));\n csvLines.push(row.join(\"\\t\"));\n }\n const csvContent = csvLines.join(\"\\n\");\n\n // \uD30C\uC77C \uC4F0\uAE30\n await fs.promises.writeFile(tmpFile, csvContent, \"utf8\");\n\n // UUID/binary \uCEEC\uB7FC\uC740 \uC784\uC2DC \uBCC0\uC218\uB85C \uC77D\uACE0 SET \uC808\uC5D0\uC11C UNHEX() \uBCC0\uD658\n const binaryColNames = colNames.filter((c) => {\n const dt = columnMetas[c].dataType.type;\n return dt === \"uuid\" || dt === \"binary\";\n });\n const normalCols = colNames.map((c) => {\n if (binaryColNames.includes(c)) return `@_${c}`;\n return `\\`${c}\\``;\n });\n const setClauses = binaryColNames.map((c) => `\\`${c}\\` = UNHEX(@_${c})`);\n\n // LOAD DATA LOCAL INFILE \uC2E4\uD589\n let query = `LOAD DATA LOCAL INFILE ? INTO TABLE ${tableName} FIELDS TERMINATED BY '\\\\t' LINES TERMINATED BY '\\\\n' (${normalCols.join(\", \")})`;\n if (setClauses.length > 0) {\n query += ` SET ${setClauses.join(\", \")}`;\n }\n\n await conn.query({ sql: query, timeout: this._timeout, values: [tmpFile] });\n } finally {\n // \uC784\uC2DC \uD30C\uC77C \uC0AD\uC81C\n try {\n await fs.promises.unlink(tmpFile);\n } catch {\n // \uC0AD\uC81C \uC2E4\uD328 \uBB34\uC2DC\n }\n }\n }\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Private helpers\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * MySQL LOAD DATA INFILE\uC6A9 \uAC12 \uC774\uC2A4\uCF00\uC774\uD504\n */\n private _escapeForCsv(value: unknown, dataType: DataType): string {\n if (value == null) {\n return \"\\\\N\"; // MySQL NULL \uD45C\uD604\n }\n\n switch (dataType.type) {\n case \"int\":\n case \"bigint\":\n case \"float\":\n case \"double\":\n case \"decimal\":\n return String(value);\n\n case \"boolean\":\n return (value as boolean) ? \"1\" : \"0\";\n\n case \"varchar\":\n case \"char\":\n case \"text\": {\n const str = value as string;\n // \uD0ED, \uC904\uBC14\uAFC8, \uBC31\uC2AC\uB798\uC2DC \uC774\uC2A4\uCF00\uC774\uD504\n return str.replace(/\\\\/g, \"\\\\\\\\\").replace(/\\t/g, \"\\\\t\").replace(/\\n/g, \"\\\\n\").replace(/\\r/g, \"\\\\r\");\n }\n\n case \"datetime\":\n return (value as DateTime).toFormatString(\"yyyy-MM-dd HH:mm:ss.fff\");\n\n case \"date\":\n return (value as DateOnly).toFormatString(\"yyyy-MM-dd\");\n\n case \"time\":\n return (value as Time).toFormatString(\"HH:mm:ss\");\n\n case \"uuid\":\n return (value as Uuid).toString().replace(/-/g, \"\"); // BINARY(16) \uC800\uC7A5\uC6A9 hex\n\n case \"binary\":\n return bytesToHex(value as Uint8Array);\n\n default:\n throw new SdError(`\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 DataType: ${JSON.stringify(dataType)}`);\n }\n }\n\n private _assertConnected(): Connection {\n if (this._conn == null || !this.isConnected) {\n throw new SdError(DB_CONN_ERRORS.NOT_CONNECTED);\n }\n this._startTimeout();\n return this._conn;\n }\n\n private _resetState(): void {\n this.isConnected = false;\n this.isOnTransaction = false;\n this._conn = undefined;\n }\n\n private _stopTimeout(): void {\n if (this._connTimeout != null) {\n clearTimeout(this._connTimeout);\n }\n }\n\n private _startTimeout(): void {\n this._stopTimeout();\n this._connTimeout = setTimeout(() => {\n this.close().catch((err) => {\n logger.error(\"close error\", err instanceof Error ? err.message : String(err));\n });\n }, this._timeout * 2);\n }\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,kBAAkB;AAC3B,OAAO,QAAQ;AACf,OAAO,QAAQ;AACf,OAAO,UAAU;AAEjB,
|
|
4
|
+
"sourcesContent": ["import { randomUUID } from \"crypto\";\nimport fs from \"fs\";\nimport os from \"os\";\nimport path from \"path\";\nimport type { Connection } from \"mysql2/promise\";\nimport consola from \"consola\";\nimport {\n bytesToHex,\n DateOnly,\n DateTime,\n SdError,\n EventEmitter,\n strIsNullOrEmpty,\n Time,\n Uuid,\n} from \"@simplysm/core-common\";\nimport type { ColumnMeta, DataType, IsolationLevel } from \"@simplysm/orm-common\";\nimport { DB_CONN_DEFAULT_TIMEOUT, DB_CONN_ERRORS, type DbConn, type MysqlDbConnConfig } from \"../types/db-conn\";\n\nconst logger = consola.withTag(\"mysql-db-conn\");\n\n/**\n * MySQL \uB370\uC774\uD130\uBCA0\uC774\uC2A4 \uC5F0\uACB0 \uD074\uB798\uC2A4\n *\n * mysql2/promise \uB77C\uC774\uBE0C\uB7EC\uB9AC\uB97C \uC0AC\uC6A9\uD558\uC5EC MySQL \uC5F0\uACB0\uC744 \uAD00\uB9AC\uD569\uB2C8\uB2E4.\n */\nexport class MysqlDbConn extends EventEmitter<{ close: void }> implements DbConn {\n private static readonly _ROOT_USER = \"root\";\n private readonly _timeout = DB_CONN_DEFAULT_TIMEOUT;\n\n private _conn?: Connection;\n private _connTimeout?: ReturnType<typeof setTimeout>;\n\n isConnected = false;\n isOnTransaction = false;\n\n constructor(\n private readonly _mysql2: typeof import(\"mysql2/promise\"),\n readonly config: MysqlDbConnConfig,\n ) {\n super();\n }\n\n async connect(): Promise<void> {\n if (this.isConnected) {\n throw new SdError(DB_CONN_ERRORS.ALREADY_CONNECTED);\n }\n\n const conn = await this._mysql2.createConnection({\n host: this.config.host,\n port: this.config.port,\n user: this.config.username,\n password: this.config.password,\n // root \uC0AC\uC6A9\uC790\uB294 \uD2B9\uC815 database\uC5D0 \uBC14\uC778\uB529\uB418\uC9C0 \uC54A\uACE0 \uC5F0\uACB0\uD558\uC5EC\n // \uBAA8\uB4E0 \uB370\uC774\uD130\uBCA0\uC774\uC2A4\uC5D0 \uC811\uADFC\uD560 \uC218 \uC788\uB3C4\uB85D \uD568 (\uAD00\uB9AC \uC791\uC5C5\uC6A9)\n database: this.config.username === MysqlDbConn._ROOT_USER ? undefined : this.config.database,\n multipleStatements: true,\n charset: \"utf8mb4\",\n infileStreamFactory: (filePath: string) => fs.createReadStream(filePath), // LOAD DATA LOCAL INFILE \uC9C0\uC6D0\n } as Parameters<typeof this._mysql2.createConnection>[0]);\n\n conn.on(\"end\", () => {\n this.emit(\"close\");\n this._resetState();\n });\n\n conn.on(\"error\", (error) => {\n logger.error(\"DB \uC5F0\uACB0 \uC624\uB958\", error.message);\n });\n\n this._conn = conn;\n this._startTimeout();\n this.isConnected = true;\n }\n\n async close(): Promise<void> {\n this._stopTimeout();\n\n if (this._conn == null || !this.isConnected) {\n return;\n }\n\n await this._conn.end();\n\n this.emit(\"close\");\n this._resetState();\n }\n\n async beginTransaction(isolationLevel?: IsolationLevel): Promise<void> {\n const conn = this._assertConnected();\n\n const level = (isolationLevel ?? this.config.defaultIsolationLevel ?? \"READ_UNCOMMITTED\").replace(/_/g, \" \");\n\n // \uACA9\uB9AC \uC218\uC900\uC744 \uBA3C\uC800 \uC124\uC815 (\uB2E4\uC74C \uD2B8\uB79C\uC7AD\uC158\uC5D0 \uC801\uC6A9\uB428)\n await conn.query({\n sql: `SET SESSION TRANSACTION ISOLATION LEVEL ${level}`,\n timeout: this._timeout,\n });\n\n // \uADF8 \uB2E4\uC74C \uD2B8\uB79C\uC7AD\uC158 \uC2DC\uC791\n await conn.beginTransaction();\n\n this.isOnTransaction = true;\n }\n\n async commitTransaction(): Promise<void> {\n const conn = this._assertConnected();\n await conn.commit();\n this.isOnTransaction = false;\n }\n\n async rollbackTransaction(): Promise<void> {\n const conn = this._assertConnected();\n await conn.rollback();\n this.isOnTransaction = false;\n }\n\n async execute(queries: string[]): Promise<unknown[][]> {\n const results: unknown[][] = [];\n for (const query of queries.filter((item) => !strIsNullOrEmpty(item))) {\n const resultItems = await this.executeParametrized(query);\n results.push(...resultItems);\n }\n return results;\n }\n\n async executeParametrized(query: string, params?: unknown[]): Promise<unknown[][]> {\n const conn = this._assertConnected();\n\n logger.debug(\"\uCFFC\uB9AC \uC2E4\uD589\", { queryLength: query.length, params });\n\n try {\n const [queryResults] = await conn.query({\n sql: query,\n timeout: this._timeout,\n values: params,\n });\n\n this._startTimeout();\n\n // MySQL\uC740 INSERT/UPDATE/DELETE \uBB38\uC5D0 \uB300\uD574 ResultSetHeader\uB97C \uBC18\uD658\uD568\n // SELECT \uACB0\uACFC\uB9CC \uCD94\uCD9C\uD558\uAE30 \uC704\uD574 ResultSetHeader \uAC1D\uCCB4\uB97C \uD544\uD130\uB9C1\uD568\n // ResultSetHeader\uB294 affectedRows, fieldCount \uB4F1\uC758 \uD544\uB4DC\uB97C \uAC00\uC9C0\uACE0 \uC788\uC74C\n const result: unknown[] = [];\n if (queryResults instanceof Array) {\n for (const queryResult of queryResults.filter(\n (item: unknown) =>\n !(typeof item === \"object\" && item !== null && \"affectedRows\" in item && \"fieldCount\" in item),\n )) {\n result.push(queryResult);\n }\n }\n\n return [result];\n } catch (err) {\n this._startTimeout();\n const error = err as Error & { sql?: string };\n throw new SdError(\n error,\n \"\uCFFC\uB9AC \uC218\uD589\uC911 \uC624\uB958\uBC1C\uC0DD\" + (error.sql != null ? \"\\n-- query\\n\" + error.sql.trim() + \"\\n--\" : \"\"),\n );\n }\n }\n\n async bulkInsert(\n tableName: string,\n columnMetas: Record<string, ColumnMeta>,\n records: Record<string, unknown>[],\n ): Promise<void> {\n const conn = this._assertConnected();\n\n if (records.length === 0) return;\n\n const colNames = Object.keys(columnMetas);\n\n // \uC784\uC2DC CSV \uD30C\uC77C \uC0DD\uC131\n const tmpDir = os.tmpdir();\n const tmpFile = path.join(tmpDir, `mysql_bulk_${randomUUID()}.csv`);\n\n try {\n // CSV \uB370\uC774\uD130 \uC0DD\uC131\n const csvLines: string[] = [];\n for (const record of records) {\n const row = colNames.map((colName) => this._escapeForCsv(record[colName], columnMetas[colName].dataType));\n csvLines.push(row.join(\"\\t\"));\n }\n const csvContent = csvLines.join(\"\\n\");\n\n // \uD30C\uC77C \uC4F0\uAE30\n await fs.promises.writeFile(tmpFile, csvContent, \"utf8\");\n\n // UUID/binary \uCEEC\uB7FC\uC740 \uC784\uC2DC \uBCC0\uC218\uB85C \uC77D\uACE0 SET \uC808\uC5D0\uC11C UNHEX() \uBCC0\uD658\n const binaryColNames = colNames.filter((c) => {\n const dt = columnMetas[c].dataType.type;\n return dt === \"uuid\" || dt === \"binary\";\n });\n const normalCols = colNames.map((c) => {\n if (binaryColNames.includes(c)) return `@_${c}`;\n return `\\`${c}\\``;\n });\n const setClauses = binaryColNames.map((c) => `\\`${c}\\` = UNHEX(@_${c})`);\n\n // LOAD DATA LOCAL INFILE \uC2E4\uD589\n let query = `LOAD DATA LOCAL INFILE ? INTO TABLE ${tableName} FIELDS TERMINATED BY '\\\\t' LINES TERMINATED BY '\\\\n' (${normalCols.join(\", \")})`;\n if (setClauses.length > 0) {\n query += ` SET ${setClauses.join(\", \")}`;\n }\n\n await conn.query({ sql: query, timeout: this._timeout, values: [tmpFile] });\n } finally {\n // \uC784\uC2DC \uD30C\uC77C \uC0AD\uC81C\n try {\n await fs.promises.unlink(tmpFile);\n } catch {\n // \uC0AD\uC81C \uC2E4\uD328 \uBB34\uC2DC\n }\n }\n }\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Private helpers\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * MySQL LOAD DATA INFILE\uC6A9 \uAC12 \uC774\uC2A4\uCF00\uC774\uD504\n */\n private _escapeForCsv(value: unknown, dataType: DataType): string {\n if (value == null) {\n return \"\\\\N\"; // MySQL NULL \uD45C\uD604\n }\n\n switch (dataType.type) {\n case \"int\":\n case \"bigint\":\n case \"float\":\n case \"double\":\n case \"decimal\":\n return String(value);\n\n case \"boolean\":\n return (value as boolean) ? \"1\" : \"0\";\n\n case \"varchar\":\n case \"char\":\n case \"text\": {\n const str = value as string;\n // \uD0ED, \uC904\uBC14\uAFC8, \uBC31\uC2AC\uB798\uC2DC \uC774\uC2A4\uCF00\uC774\uD504\n return str.replace(/\\\\/g, \"\\\\\\\\\").replace(/\\t/g, \"\\\\t\").replace(/\\n/g, \"\\\\n\").replace(/\\r/g, \"\\\\r\");\n }\n\n case \"datetime\":\n return (value as DateTime).toFormatString(\"yyyy-MM-dd HH:mm:ss.fff\");\n\n case \"date\":\n return (value as DateOnly).toFormatString(\"yyyy-MM-dd\");\n\n case \"time\":\n return (value as Time).toFormatString(\"HH:mm:ss\");\n\n case \"uuid\":\n return (value as Uuid).toString().replace(/-/g, \"\"); // BINARY(16) \uC800\uC7A5\uC6A9 hex\n\n case \"binary\":\n return bytesToHex(value as Uint8Array);\n\n default:\n throw new SdError(`\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 DataType: ${JSON.stringify(dataType)}`);\n }\n }\n\n private _assertConnected(): Connection {\n if (this._conn == null || !this.isConnected) {\n throw new SdError(DB_CONN_ERRORS.NOT_CONNECTED);\n }\n this._startTimeout();\n return this._conn;\n }\n\n private _resetState(): void {\n this.isConnected = false;\n this.isOnTransaction = false;\n this._conn = undefined;\n }\n\n private _stopTimeout(): void {\n if (this._connTimeout != null) {\n clearTimeout(this._connTimeout);\n }\n }\n\n private _startTimeout(): void {\n this._stopTimeout();\n this._connTimeout = setTimeout(() => {\n this.close().catch((err) => {\n logger.error(\"close error\", err instanceof Error ? err.message : String(err));\n });\n }, this._timeout * 2);\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Readable } from "stream";
|
|
2
|
-
import
|
|
2
|
+
import consola from "consola";
|
|
3
3
|
import {
|
|
4
4
|
bytesToHex,
|
|
5
5
|
DateOnly,
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
Uuid
|
|
12
12
|
} from "@simplysm/core-common";
|
|
13
13
|
import { DB_CONN_DEFAULT_TIMEOUT, DB_CONN_ERRORS } from "../types/db-conn.js";
|
|
14
|
-
const logger =
|
|
14
|
+
const logger = consola.withTag("postgresql-db-conn");
|
|
15
15
|
class PostgresqlDbConn extends EventEmitter {
|
|
16
16
|
constructor(_pg, _pgCopyFrom, config) {
|
|
17
17
|
super();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/connections/postgresql-db-conn.ts"],
|
|
4
|
-
"sourcesContent": ["import { Readable } from \"stream\";\nimport
|
|
5
|
-
"mappings": "AAAA,SAAS,gBAAgB;AACzB,
|
|
4
|
+
"sourcesContent": ["import { Readable } from \"stream\";\nimport consola from \"consola\";\nimport {\n bytesToHex,\n DateOnly,\n DateTime,\n SdError,\n EventEmitter,\n strIsNullOrEmpty,\n Time,\n Uuid,\n} from \"@simplysm/core-common\";\nimport type { ColumnMeta, DataType, IsolationLevel } from \"@simplysm/orm-common\";\nimport { DB_CONN_DEFAULT_TIMEOUT, DB_CONN_ERRORS, type DbConn, type PostgresqlDbConnConfig } from \"../types/db-conn\";\nimport type { Client } from \"pg\";\nimport type { CopyStreamQuery } from \"pg-copy-streams\";\n\nconst logger = consola.withTag(\"postgresql-db-conn\");\n\n/**\n * PostgreSQL \uB370\uC774\uD130\uBCA0\uC774\uC2A4 \uC5F0\uACB0 \uD074\uB798\uC2A4\n *\n * pg \uB77C\uC774\uBE0C\uB7EC\uB9AC\uB97C \uC0AC\uC6A9\uD558\uC5EC PostgreSQL \uC5F0\uACB0\uC744 \uAD00\uB9AC\uD569\uB2C8\uB2E4.\n */\nexport class PostgresqlDbConn extends EventEmitter<{ close: void }> implements DbConn {\n private readonly _timeout = DB_CONN_DEFAULT_TIMEOUT;\n\n private _client?: Client;\n private _connTimeout?: ReturnType<typeof setTimeout>;\n\n isConnected = false;\n isOnTransaction = false;\n\n constructor(\n private readonly _pg: typeof import(\"pg\"),\n private readonly _pgCopyFrom: (queryText: string) => CopyStreamQuery,\n readonly config: PostgresqlDbConnConfig,\n ) {\n super();\n }\n\n async connect(): Promise<void> {\n if (this.isConnected) {\n throw new SdError(DB_CONN_ERRORS.ALREADY_CONNECTED);\n }\n\n const client = new this._pg.Client({\n host: this.config.host,\n port: this.config.port ?? 5432,\n user: this.config.username,\n password: this.config.password,\n database: this.config.database,\n connectionTimeoutMillis: this._timeout,\n query_timeout: this._timeout,\n });\n\n client.on(\"end\", () => {\n this.emit(\"close\");\n this._resetState();\n });\n\n client.on(\"error\", (error) => {\n logger.error(\"DB \uC5F0\uACB0 \uC624\uB958\", error.message);\n });\n\n await client.connect();\n\n this._client = client;\n this._startTimeout();\n this.isConnected = true;\n }\n\n async close(): Promise<void> {\n this._stopTimeout();\n\n if (this._client == null || !this.isConnected) {\n return;\n }\n\n await this._client.end();\n\n this.emit(\"close\");\n this._resetState();\n }\n\n async beginTransaction(isolationLevel?: IsolationLevel): Promise<void> {\n this._assertConnected();\n\n const level = (isolationLevel ?? this.config.defaultIsolationLevel ?? \"READ_UNCOMMITTED\").replace(/_/g, \" \");\n\n await this._client!.query(\"BEGIN\");\n await this._client!.query(`SET TRANSACTION ISOLATION LEVEL ${level}`);\n\n this.isOnTransaction = true;\n }\n\n async commitTransaction(): Promise<void> {\n this._assertConnected();\n await this._client!.query(\"COMMIT\");\n this.isOnTransaction = false;\n }\n\n async rollbackTransaction(): Promise<void> {\n this._assertConnected();\n await this._client!.query(\"ROLLBACK\");\n this.isOnTransaction = false;\n }\n\n async execute(queries: string[]): Promise<unknown[][]> {\n const results: unknown[][] = [];\n for (const query of queries.filter((item) => !strIsNullOrEmpty(item))) {\n const resultItems = await this.executeParametrized(query);\n results.push(...resultItems);\n }\n return results;\n }\n\n async executeParametrized(query: string, params?: unknown[]): Promise<unknown[][]> {\n this._assertConnected();\n\n logger.debug(\"\uCFFC\uB9AC \uC2E4\uD589\", { queryLength: query.length, params });\n\n try {\n const result = await this._client!.query(query, params);\n\n this._startTimeout();\n\n // PostgreSQL\uC740 \uB2E8\uC77C \uACB0\uACFC\uC14B \uBC18\uD658\n return [result.rows];\n } catch (err) {\n this._startTimeout();\n const error = err instanceof Error ? err : new Error(String(err));\n throw new SdError(error, \"\uCFFC\uB9AC \uC218\uD589\uC911 \uC624\uB958\uBC1C\uC0DD\\n-- query\\n\" + query.trim() + \"\\n--\");\n }\n }\n\n async bulkInsert(\n tableName: string,\n columnMetas: Record<string, ColumnMeta>,\n records: Record<string, unknown>[],\n ): Promise<void> {\n this._assertConnected();\n\n if (records.length === 0) return;\n\n const colNames = Object.keys(columnMetas);\n const wrappedCols = colNames.map((c) => `\"${c}\"`).join(\", \");\n\n // COPY FROM STDIN \uC2A4\uD2B8\uB9BC \uC0DD\uC131\n const copyQuery = `COPY ${tableName} (${wrappedCols}) FROM STDIN WITH (FORMAT csv, NULL '\\\\N')`;\n const stream = this._client!.query(this._pgCopyFrom(copyQuery));\n\n // CSV \uB370\uC774\uD130 \uC0DD\uC131\n const csvLines: string[] = [];\n for (const record of records) {\n const row = colNames.map((colName) => this._escapeForCsv(record[colName], columnMetas[colName].dataType));\n csvLines.push(row.join(\",\"));\n }\n const csvContent = csvLines.join(\"\\n\") + \"\\n\";\n\n // \uC2A4\uD2B8\uB9BC\uC73C\uB85C \uB370\uC774\uD130 \uC804\uC1A1\n await new Promise<void>((resolve, reject) => {\n const readable = Readable.from([csvContent]);\n\n readable.on(\"error\", reject);\n stream.on(\"error\", reject);\n stream.on(\"finish\", resolve);\n\n readable.pipe(stream);\n });\n }\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Private helpers\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * PostgreSQL COPY CSV\uC6A9 \uAC12 \uC774\uC2A4\uCF00\uC774\uD504\n */\n private _escapeForCsv(value: unknown, dataType: DataType): string {\n if (value == null) {\n return \"\\\\N\"; // NULL \uD45C\uD604\n }\n\n switch (dataType.type) {\n case \"int\":\n case \"bigint\":\n case \"float\":\n case \"double\":\n case \"decimal\":\n return String(value);\n\n case \"boolean\":\n return (value as boolean) ? \"true\" : \"false\";\n\n case \"varchar\":\n case \"char\":\n case \"text\": {\n const str = value as string;\n // CSV \uD615\uC2DD: \uC30D\uB530\uC634\uD45C\uB85C \uAC10\uC2F8\uACE0, \uB0B4\uBD80 \uC30D\uB530\uC634\uD45C\uB294 \uB450 \uBC88\n if (str.includes('\"') || str.includes(\",\") || str.includes(\"\\n\") || str.includes(\"\\r\")) {\n return '\"' + str.replace(/\"/g, '\"\"') + '\"';\n }\n return str;\n }\n\n case \"datetime\":\n return (value as DateTime).toFormatString(\"yyyy-MM-dd HH:mm:ss.fff\");\n\n case \"date\":\n return (value as DateOnly).toFormatString(\"yyyy-MM-dd\");\n\n case \"time\":\n return (value as Time).toFormatString(\"HH:mm:ss\");\n\n case \"uuid\":\n return (value as Uuid).toString();\n\n case \"binary\":\n return '\"\\\\x' + bytesToHex(value as Uint8Array) + '\"'; // PostgreSQL bytea hex \uD615\uC2DD (CSV \uC30D\uB530\uC634\uD45C\uB85C \uAC10\uC308)\n\n default:\n throw new SdError(`\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 DataType: ${JSON.stringify(dataType)}`);\n }\n }\n\n private _assertConnected(): void {\n if (this._client == null || !this.isConnected) {\n throw new SdError(DB_CONN_ERRORS.NOT_CONNECTED);\n }\n this._startTimeout();\n }\n\n private _resetState(): void {\n this.isConnected = false;\n this.isOnTransaction = false;\n this._client = undefined;\n }\n\n private _stopTimeout(): void {\n if (this._connTimeout != null) {\n clearTimeout(this._connTimeout);\n }\n }\n\n private _startTimeout(): void {\n this._stopTimeout();\n this._connTimeout = setTimeout(() => {\n this.close().catch((err) => {\n logger.error(\"close error\", err instanceof Error ? err.message : String(err));\n });\n }, this._timeout * 2);\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/pooled-db-conn.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import consola from "consola";
|
|
2
2
|
import { SdError, EventEmitter } from "@simplysm/core-common";
|
|
3
3
|
import { DB_CONN_ERRORS } from "./types/db-conn.js";
|
|
4
|
-
const logger =
|
|
4
|
+
const logger = consola.withTag("pooled-db-conn");
|
|
5
5
|
class PooledDbConn extends EventEmitter {
|
|
6
6
|
constructor(_pool, _initialConfig) {
|
|
7
7
|
super();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/pooled-db-conn.ts"],
|
|
4
|
-
"sourcesContent": ["import
|
|
5
|
-
"mappings": "AAAA,
|
|
4
|
+
"sourcesContent": ["import consola from \"consola\";\nimport { SdError, EventEmitter } from \"@simplysm/core-common\";\nimport type { Pool } from \"generic-pool\";\nimport type { ColumnMeta, IsolationLevel } from \"@simplysm/orm-common\";\nimport { DB_CONN_ERRORS, type DbConn, type DbConnConfig } from \"./types/db-conn\";\n\nconst logger = consola.withTag(\"pooled-db-conn\");\n\n/**\n * \uCEE4\uB125\uC158 \uD480\uC5D0\uC11C \uAD00\uB9AC\uB418\uB294 DB \uC5F0\uACB0 \uB798\uD37C\n *\n * generic-pool \uB77C\uC774\uBE0C\uB7EC\uB9AC\uB97C \uC0AC\uC6A9\uD558\uC5EC \uCEE4\uB125\uC158 \uD480\uB9C1\uC744 \uC9C0\uC6D0\uD55C\uB2E4.\n * \uC2E4\uC81C \uBB3C\uB9AC \uC5F0\uACB0\uC740 \uD480\uC5D0\uC11C \uD68D\uB4DD\uD558\uACE0 \uBC18\uD658\uD55C\uB2E4.\n */\nexport class PooledDbConn extends EventEmitter<{ close: void }> implements DbConn {\n // \uD480\uC5D0\uC11C \uBE4C\uB824\uC628 \uC2E4\uC81C \uBB3C\uB9AC \uCEE4\uB125\uC158\n private _rawConn?: DbConn;\n\n constructor(\n private readonly _pool: Pool<DbConn>,\n private readonly _initialConfig: DbConnConfig,\n ) {\n super();\n }\n\n // [Property] config\n get config(): DbConnConfig {\n return this._rawConn?.config ?? this._initialConfig;\n }\n\n // [Property] isConnected\n get isConnected(): boolean {\n return this._rawConn?.isConnected ?? false;\n }\n\n // [Property] isOnTransaction\n get isOnTransaction(): boolean {\n return this._rawConn?.isOnTransaction ?? false;\n }\n\n /**\n * \uD480\uC5D0\uC11C DB \uC5F0\uACB0\uC744 \uD68D\uB4DD\uD55C\uB2E4.\n *\n * @throws {SdError} \uC774\uBBF8 \uC5F0\uACB0\uB41C \uC0C1\uD0DC\uC77C \uB54C\n */\n async connect(): Promise<void> {\n if (this._rawConn != null) {\n throw new SdError(DB_CONN_ERRORS.ALREADY_CONNECTED);\n }\n\n // 1. \uD480\uC5D0\uC11C \uCEE4\uB125\uC158 \uD68D\uB4DD\n this._rawConn = await this._pool.acquire();\n\n // 2. \uBB3C\uB9AC \uC5F0\uACB0\uC774 (\uD0C0\uC784\uC544\uC6C3 \uB4F1\uC73C\uB85C) \uB04A\uC5B4\uC9C8 \uACBD\uC6B0\uB97C \uB300\uBE44\uD574 \uB9AC\uC2A4\uB108 \uB4F1\uB85D\n // \uB9CC\uC57D \uC0AC\uC6A9 \uC911\uC5D0 \uB04A\uAE30\uBA74 PooledDbConn\uB3C4 close \uC774\uBCA4\uD2B8\uB97C \uBC1C\uC0DD\uC2DC\uCF1C\uC57C \uD568\n this._rawConn.on(\"close\", this._onRawConnClose);\n }\n\n /**\n * \uD480\uC5D0 DB \uC5F0\uACB0\uC744 \uBC18\uD658\uD55C\uB2E4. (\uC2E4\uC81C \uC5F0\uACB0\uC744 \uC885\uB8CC\uD558\uC9C0 \uC54A\uC74C)\n */\n async close(): Promise<void> {\n if (this._rawConn != null) {\n // 1. \uD2B8\uB79C\uC7AD\uC158 \uC9C4\uD589 \uC911\uC774\uBA74 \uB864\uBC31\uD558\uC5EC \uAE68\uB057\uD55C \uC0C1\uD0DC\uB85C \uD480\uC5D0 \uBC18\uD658\n if (this._rawConn.isOnTransaction) {\n try {\n await this._rawConn.rollbackTransaction();\n } catch (err) {\n // \uB864\uBC31 \uC2E4\uD328 \uC2DC \uB85C\uADF8\uB9CC \uB0A8\uAE30\uACE0 \uACC4\uC18D \uC9C4\uD589 (\uC5F0\uACB0\uC774 \uC774\uBBF8 \uB04A\uAE34 \uACBD\uC6B0 \uB4F1)\n logger.warn(\"\uD480 \uBC18\uD658 \uC2DC \uB864\uBC31 \uC2E4\uD328\", err instanceof Error ? err.message : String(err));\n }\n }\n\n // 2. \uB9AC\uC2A4\uB108 \uD574\uC81C (Pool\uC5D0 \uB3CC\uC544\uAC00\uC11C \uB2E4\uB978 \uB798\uD37C\uC5D0 \uC758\uD574 \uC7AC\uC0AC\uC6A9\uB420 \uB54C \uC601\uD5A5 \uC8FC\uC9C0 \uC54A\uB3C4\uB85D)\n this._rawConn.off(\"close\", this._onRawConnClose);\n\n // 3. \uD480\uC5D0 \uCEE4\uB125\uC158 \uBC18\uD658 (\uC2E4\uC81C\uB85C \uB04A\uC9C0 \uC54A\uC74C)\n await this._pool.release(this._rawConn);\n this._rawConn = undefined;\n\n // 4. \uC18C\uBE44\uC790\uC5D0\uAC8C \uB17C\uB9AC\uC801\uC73C\uB85C \uC5F0\uACB0\uC774 \uB2EB\uD614\uC74C\uC744 \uC54C\uB9BC\n this.emit(\"close\");\n }\n }\n\n // \uBB3C\uB9AC \uC5F0\uACB0\uC774 \uB04A\uACBC\uC744 \uB54C \uCC98\uB9AC \uD578\uB4E4\uB7EC\n private readonly _onRawConnClose = () => {\n // \uBB3C\uB9AC \uC5F0\uACB0\uC774 \uB04A\uACBC\uC73C\uBBC0\uB85C \uCC38\uC870 \uC81C\uAC70 (Pool\uC5D0\uC11C\uB294 validate \uC2DC\uC810\uC5D0 \uAC78\uB7EC\uB0BC \uAC83\uC784)\n this._rawConn = undefined;\n // \uC18C\uBE44\uC790\uC5D0\uAC8C \uC54C\uB9BC\n this.emit(\"close\");\n };\n\n // --- \uC544\uB798\uB294 \uC704\uC784(Delegation) \uBA54\uC18C\uB4DC ---\n\n /**\n * \uD2B8\uB79C\uC7AD\uC158 \uC2DC\uC791\n *\n * @param isolationLevel - \uD2B8\uB79C\uC7AD\uC158 \uACA9\uB9AC \uC218\uC900\n * @throws {SdError} \uC5F0\uACB0\uC774 \uD68D\uB4DD\uB418\uC9C0 \uC54A\uC740 \uC0C1\uD0DC\uC77C \uB54C\n */\n async beginTransaction(isolationLevel?: IsolationLevel): Promise<void> {\n const conn = this._requireRawConn();\n await conn.beginTransaction(isolationLevel);\n }\n\n /**\n * \uD2B8\uB79C\uC7AD\uC158 \uCEE4\uBC0B\n *\n * @throws {SdError} \uC5F0\uACB0\uC774 \uD68D\uB4DD\uB418\uC9C0 \uC54A\uC740 \uC0C1\uD0DC\uC77C \uB54C\n */\n async commitTransaction(): Promise<void> {\n const conn = this._requireRawConn();\n await conn.commitTransaction();\n }\n\n /**\n * \uD2B8\uB79C\uC7AD\uC158 \uB864\uBC31\n *\n * @throws {SdError} \uC5F0\uACB0\uC774 \uD68D\uB4DD\uB418\uC9C0 \uC54A\uC740 \uC0C1\uD0DC\uC77C \uB54C\n */\n async rollbackTransaction(): Promise<void> {\n const conn = this._requireRawConn();\n await conn.rollbackTransaction();\n }\n\n /**\n * SQL \uCFFC\uB9AC \uC2E4\uD589\n *\n * @param queries - \uC2E4\uD589\uD560 SQL \uCFFC\uB9AC \uBC30\uC5F4\n * @returns \uAC01 \uCFFC\uB9AC\uC758 \uACB0\uACFC \uBC30\uC5F4\n * @throws {SdError} \uC5F0\uACB0\uC774 \uD68D\uB4DD\uB418\uC9C0 \uC54A\uC740 \uC0C1\uD0DC\uC77C \uB54C\n */\n async execute(queries: string[]): Promise<unknown[][]> {\n const conn = this._requireRawConn();\n return conn.execute(queries);\n }\n\n /**\n * \uD30C\uB77C\uBBF8\uD130\uD654\uB41C SQL \uCFFC\uB9AC \uC2E4\uD589\n *\n * @param query - SQL \uCFFC\uB9AC \uBB38\uC790\uC5F4\n * @param params - \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uBC30\uC5F4\n * @returns \uCFFC\uB9AC \uACB0\uACFC \uBC30\uC5F4\n * @throws {SdError} \uC5F0\uACB0\uC774 \uD68D\uB4DD\uB418\uC9C0 \uC54A\uC740 \uC0C1\uD0DC\uC77C \uB54C\n */\n async executeParametrized(query: string, params?: unknown[]): Promise<unknown[][]> {\n const conn = this._requireRawConn();\n return conn.executeParametrized(query, params);\n }\n\n /**\n * \uB300\uB7C9 \uB370\uC774\uD130 \uC0BD\uC785 (\uB124\uC774\uD2F0\uBE0C \uBC8C\uD06C API \uC0AC\uC6A9)\n *\n * @param tableName - \uB300\uC0C1 \uD14C\uC774\uBE14\uBA85\n * @param columnMetas - \uCEEC\uB7FC \uBA54\uD0C0\uB370\uC774\uD130\n * @param records - \uC0BD\uC785\uD560 \uB808\uCF54\uB4DC \uBC30\uC5F4\n * @throws {SdError} \uC5F0\uACB0\uC774 \uD68D\uB4DD\uB418\uC9C0 \uC54A\uC740 \uC0C1\uD0DC\uC77C \uB54C\n */\n async bulkInsert(\n tableName: string,\n columnMetas: Record<string, ColumnMeta>,\n records: Record<string, unknown>[],\n ): Promise<void> {\n const conn = this._requireRawConn();\n await conn.bulkInsert(tableName, columnMetas, records);\n }\n\n private _requireRawConn(): DbConn {\n if (this._rawConn == null) {\n throw new SdError(`${DB_CONN_ERRORS.NOT_CONNECTED} (Pool Connection is not acquired)`);\n }\n return this._rawConn;\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,OAAO,aAAa;AACpB,SAAS,SAAS,oBAAoB;AAGtC,SAAS,sBAAsD;AAE/D,MAAM,SAAS,QAAQ,QAAQ,gBAAgB;AAQxC,MAAM,qBAAqB,aAAgD;AAAA,EAIhF,YACmB,OACA,gBACjB;AACA,UAAM;AAHW;AACA;AAAA,EAGnB;AAAA;AAAA,EAPQ;AAAA;AAAA,EAUR,IAAI,SAAuB;AACzB,WAAO,KAAK,UAAU,UAAU,KAAK;AAAA,EACvC;AAAA;AAAA,EAGA,IAAI,cAAuB;AACzB,WAAO,KAAK,UAAU,eAAe;AAAA,EACvC;AAAA;AAAA,EAGA,IAAI,kBAA2B;AAC7B,WAAO,KAAK,UAAU,mBAAmB;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,UAAyB;AAC7B,QAAI,KAAK,YAAY,MAAM;AACzB,YAAM,IAAI,QAAQ,eAAe,iBAAiB;AAAA,IACpD;AAGA,SAAK,WAAW,MAAM,KAAK,MAAM,QAAQ;AAIzC,SAAK,SAAS,GAAG,SAAS,KAAK,eAAe;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAuB;AAC3B,QAAI,KAAK,YAAY,MAAM;AAEzB,UAAI,KAAK,SAAS,iBAAiB;AACjC,YAAI;AACF,gBAAM,KAAK,SAAS,oBAAoB;AAAA,QAC1C,SAAS,KAAK;AAEZ,iBAAO,KAAK,wDAAgB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,QAC9E;AAAA,MACF;AAGA,WAAK,SAAS,IAAI,SAAS,KAAK,eAAe;AAG/C,YAAM,KAAK,MAAM,QAAQ,KAAK,QAAQ;AACtC,WAAK,WAAW;AAGhB,WAAK,KAAK,OAAO;AAAA,IACnB;AAAA,EACF;AAAA;AAAA,EAGiB,kBAAkB,MAAM;AAEvC,SAAK,WAAW;AAEhB,SAAK,KAAK,OAAO;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,iBAAiB,gBAAgD;AACrE,UAAM,OAAO,KAAK,gBAAgB;AAClC,UAAM,KAAK,iBAAiB,cAAc;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,oBAAmC;AACvC,UAAM,OAAO,KAAK,gBAAgB;AAClC,UAAM,KAAK,kBAAkB;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,sBAAqC;AACzC,UAAM,OAAO,KAAK,gBAAgB;AAClC,UAAM,KAAK,oBAAoB;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,QAAQ,SAAyC;AACrD,UAAM,OAAO,KAAK,gBAAgB;AAClC,WAAO,KAAK,QAAQ,OAAO;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,oBAAoB,OAAe,QAA0C;AACjF,UAAM,OAAO,KAAK,gBAAgB;AAClC,WAAO,KAAK,oBAAoB,OAAO,MAAM;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,WACJ,WACA,aACA,SACe;AACf,UAAM,OAAO,KAAK,gBAAgB;AAClC,UAAM,KAAK,WAAW,WAAW,aAAa,OAAO;AAAA,EACvD;AAAA,EAEQ,kBAA0B;AAChC,QAAI,KAAK,YAAY,MAAM;AACzB,YAAM,IAAI,QAAQ,GAAG,eAAe,aAAa,oCAAoC;AAAA,IACvF;AACA,WAAO,KAAK;AAAA,EACd;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simplysm/orm-node",
|
|
3
3
|
"sideEffects": false,
|
|
4
|
-
"version": "13.0.0-beta.
|
|
4
|
+
"version": "13.0.0-beta.41",
|
|
5
5
|
"description": "심플리즘 패키지 - ORM 모듈 (node)",
|
|
6
6
|
"author": "김석래",
|
|
7
7
|
"repository": {
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"consola": "^3.4.2",
|
|
21
21
|
"generic-pool": "^3.9.0",
|
|
22
|
-
"@simplysm/core-common": "13.0.0-beta.
|
|
23
|
-
"@simplysm/orm-common": "13.0.0-beta.
|
|
22
|
+
"@simplysm/core-common": "13.0.0-beta.41",
|
|
23
|
+
"@simplysm/orm-common": "13.0.0-beta.41"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"@types/pg": "^8.16.0",
|