@simplysm/orm-node 13.0.0-beta.46 → 13.0.0-beta.48

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.
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/connections/mssql-db-conn.ts"],
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
4
  "mappings": "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",
6
5
  "names": []
7
6
  }
@@ -1,7 +1,6 @@
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 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
4
  "mappings": "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",
6
5
  "names": []
7
6
  }
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/connections/postgresql-db-conn.ts"],
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
4
  "mappings": "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",
6
5
  "names": []
7
6
  }
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/db-conn-factory.ts"],
4
- "sourcesContent": ["import type { Pool } from \"generic-pool\";\nimport { createPool } from \"generic-pool\";\nimport type { DbConn, DbConnConfig } from \"./types/db-conn\";\nimport { PooledDbConn } from \"./pooled-db-conn\";\nimport { MysqlDbConn } from \"./connections/mysql-db-conn\";\nimport { MssqlDbConn } from \"./connections/mssql-db-conn\";\nimport { PostgresqlDbConn } from \"./connections/postgresql-db-conn\";\n\n/**\n * DB \uC5F0\uACB0 \uD329\uD1A0\uB9AC\n *\n * \uB370\uC774\uD130\uBCA0\uC774\uC2A4 \uC5F0\uACB0 \uC778\uC2A4\uD134\uC2A4\uB97C \uC0DD\uC131\uD558\uACE0 \uD480\uB9C1\uC744 \uAD00\uB9AC\uD55C\uB2E4.\n * MSSQL, MySQL, PostgreSQL\uC744 \uC9C0\uC6D0\uD55C\uB2E4.\n */\nexport class DbConnFactory {\n // \uC124\uC815\uBCC4 \uCEE4\uB125\uC158 \uD480 \uCE90\uC2F1\n private static readonly _poolMap = new Map<string, Pool<DbConn>>();\n\n /**\n * DB \uC5F0\uACB0 \uC0DD\uC131\n *\n * \uCEE4\uB125\uC158 \uD480\uC5D0\uC11C \uC5F0\uACB0\uC744 \uD68D\uB4DD\uD558\uC5EC \uBC18\uD658\uD55C\uB2E4.\n * \uD480\uC774 \uC5C6\uB294 \uACBD\uC6B0 \uC0C8\uB85C \uC0DD\uC131\uD55C\uB2E4.\n *\n * @param config - \uB370\uC774\uD130\uBCA0\uC774\uC2A4 \uC5F0\uACB0 \uC124\uC815\n * @returns \uD480\uB9C1\uB41C DB \uC5F0\uACB0 \uAC1D\uCCB4\n */\n static create(config: DbConnConfig): Promise<DbConn> {\n // 1. \uD480 \uAC00\uC838\uC624\uAE30 (\uC5C6\uC73C\uBA74 \uC0DD\uC131)\n const pool = this._getOrCreatePool(config);\n\n // 2. \uB798\uD37C \uAC1D\uCCB4 \uBC18\uD658\n return Promise.resolve(new PooledDbConn(pool, config));\n }\n\n private static _getOrCreatePool(config: DbConnConfig): Pool<DbConn> {\n // \uAC1D\uCCB4\uB97C \uD0A4\uB85C \uC4F0\uAE30 \uC704\uD574 \uBB38\uC790\uC5F4 \uBCC0\uD658 (\uC911\uCCA9 \uAC1D\uCCB4\uB3C4 \uC815\uB82C\uD558\uC5EC \uB3D9\uC77C \uC124\uC815\uC758 \uC77C\uAD00\uB41C \uD0A4 \uBCF4\uC7A5)\n const configKey = JSON.stringify(config, (_, value: unknown) =>\n value != null && typeof value === \"object\" && !Array.isArray(value)\n ? Object.fromEntries(Object.entries(value).sort(([a], [b]) => a.localeCompare(b)))\n : value,\n );\n\n if (!this._poolMap.has(configKey)) {\n const pool = createPool<DbConn>(\n {\n create: async () => {\n const conn = await this._createRawConnection(config);\n await conn.connect();\n return conn;\n },\n destroy: async (conn) => {\n await conn.close(); // \uD480\uC5D0\uC11C \uC81C\uAC70\uB420 \uB54C \uC2E4\uC81C \uC5F0\uACB0 \uC885\uB8CC\n },\n validate: (conn) => {\n // \uD68D\uB4DD \uC2DC \uC5F0\uACB0 \uC0C1\uD0DC \uD655\uC778 (\uB04A\uACA8\uC788\uC73C\uBA74 Pool\uC774 \uD3D0\uAE30\uD558\uACE0 \uC0C8\uB85C \uB9CC\uB4E6)\n return Promise.resolve(conn.isConnected);\n },\n },\n {\n min: config.pool?.min ?? 1,\n max: config.pool?.max ?? 10,\n acquireTimeoutMillis: config.pool?.acquireTimeoutMillis ?? 30000,\n idleTimeoutMillis: config.pool?.idleTimeoutMillis ?? 30000,\n testOnBorrow: true, // [\uC911\uC694] \uBE4C\uB824\uC904 \uB54C validate \uC2E4\uD589 \uC5EC\uBD80\n },\n );\n\n this._poolMap.set(configKey, pool);\n }\n\n return this._poolMap.get(configKey)!;\n }\n\n private static async _createRawConnection(config: DbConnConfig): Promise<DbConn> {\n if (config.dialect === \"mysql\") {\n const mysql = await this._ensureModule(\"mysql\");\n return new MysqlDbConn(mysql, config);\n } else if (config.dialect === \"postgresql\") {\n const pg = await this._ensureModule(\"pg\");\n const pgCopyStreams = await this._ensureModule(\"pgCopyStreams\");\n return new PostgresqlDbConn(pg, pgCopyStreams.from, config);\n } else {\n // mssql, mssql-azure\n const tedious = await this._ensureModule(\"tedious\");\n return new MssqlDbConn(tedious, config);\n }\n }\n\n // \uC9C0\uC5F0 \uB85C\uB529 \uBAA8\uB4C8 \uCE90\uC2DC\n private static readonly _modules: {\n tedious?: typeof import(\"tedious\");\n mysql?: typeof import(\"mysql2/promise\");\n pg?: typeof import(\"pg\");\n pgCopyStreams?: typeof import(\"pg-copy-streams\");\n } = {};\n\n private static async _ensureModule<K extends keyof typeof this._modules>(\n name: K,\n ): Promise<NonNullable<(typeof this._modules)[K]>> {\n if (this._modules[name] == null) {\n if (name === \"mysql\") {\n this._modules.mysql = await import(\"mysql2/promise\");\n } else if (name === \"pg\") {\n this._modules.pg = await import(\"pg\");\n } else if (name === \"pgCopyStreams\") {\n this._modules.pgCopyStreams = await import(\"pg-copy-streams\");\n } else {\n this._modules.tedious = await import(\"tedious\");\n }\n }\n return this._modules[name]!;\n }\n}\n"],
5
4
  "mappings": "AACA,SAAS,kBAAkB;AAE3B,SAAS,oBAAoB;AAC7B,SAAS,mBAAmB;AAC5B,SAAS,mBAAmB;AAC5B,SAAS,wBAAwB;AAQ1B,MAAM,cAAc;AAAA;AAAA,EAEzB,OAAwB,WAAW,oBAAI,IAA0B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWjE,OAAO,OAAO,QAAuC;AAEnD,UAAM,OAAO,KAAK,iBAAiB,MAAM;AAGzC,WAAO,QAAQ,QAAQ,IAAI,aAAa,MAAM,MAAM,CAAC;AAAA,EACvD;AAAA,EAEA,OAAe,iBAAiB,QAAoC;AAElE,UAAM,YAAY,KAAK;AAAA,MAAU;AAAA,MAAQ,CAAC,GAAG,UAC3C,SAAS,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,IAC9D,OAAO,YAAY,OAAO,QAAQ,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,IAC/E;AAAA,IACN;AAEA,QAAI,CAAC,KAAK,SAAS,IAAI,SAAS,GAAG;AACjC,YAAM,OAAO;AAAA,QACX;AAAA,UACE,QAAQ,YAAY;AAClB,kBAAM,OAAO,MAAM,KAAK,qBAAqB,MAAM;AACnD,kBAAM,KAAK,QAAQ;AACnB,mBAAO;AAAA,UACT;AAAA,UACA,SAAS,OAAO,SAAS;AACvB,kBAAM,KAAK,MAAM;AAAA,UACnB;AAAA,UACA,UAAU,CAAC,SAAS;AAElB,mBAAO,QAAQ,QAAQ,KAAK,WAAW;AAAA,UACzC;AAAA,QACF;AAAA,QACA;AAAA,UACE,KAAK,OAAO,MAAM,OAAO;AAAA,UACzB,KAAK,OAAO,MAAM,OAAO;AAAA,UACzB,sBAAsB,OAAO,MAAM,wBAAwB;AAAA,UAC3D,mBAAmB,OAAO,MAAM,qBAAqB;AAAA,UACrD,cAAc;AAAA;AAAA,QAChB;AAAA,MACF;AAEA,WAAK,SAAS,IAAI,WAAW,IAAI;AAAA,IACnC;AAEA,WAAO,KAAK,SAAS,IAAI,SAAS;AAAA,EACpC;AAAA,EAEA,aAAqB,qBAAqB,QAAuC;AAC/E,QAAI,OAAO,YAAY,SAAS;AAC9B,YAAM,QAAQ,MAAM,KAAK,cAAc,OAAO;AAC9C,aAAO,IAAI,YAAY,OAAO,MAAM;AAAA,IACtC,WAAW,OAAO,YAAY,cAAc;AAC1C,YAAM,KAAK,MAAM,KAAK,cAAc,IAAI;AACxC,YAAM,gBAAgB,MAAM,KAAK,cAAc,eAAe;AAC9D,aAAO,IAAI,iBAAiB,IAAI,cAAc,MAAM,MAAM;AAAA,IAC5D,OAAO;AAEL,YAAM,UAAU,MAAM,KAAK,cAAc,SAAS;AAClD,aAAO,IAAI,YAAY,SAAS,MAAM;AAAA,IACxC;AAAA,EACF;AAAA;AAAA,EAGA,OAAwB,WAKpB,CAAC;AAAA,EAEL,aAAqB,cACnB,MACiD;AACjD,QAAI,KAAK,SAAS,IAAI,KAAK,MAAM;AAC/B,UAAI,SAAS,SAAS;AACpB,aAAK,SAAS,QAAQ,MAAM,OAAO,gBAAgB;AAAA,MACrD,WAAW,SAAS,MAAM;AACxB,aAAK,SAAS,KAAK,MAAM,OAAO,IAAI;AAAA,MACtC,WAAW,SAAS,iBAAiB;AACnC,aAAK,SAAS,gBAAgB,MAAM,OAAO,iBAAiB;AAAA,MAC9D,OAAO;AACL,aAAK,SAAS,UAAU,MAAM,OAAO,SAAS;AAAA,MAChD;AAAA,IACF;AACA,WAAO,KAAK,SAAS,IAAI;AAAA,EAC3B;AACF;",
6
5
  "names": []
7
6
  }
package/dist/index.js.map CHANGED
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts"],
4
- "sourcesContent": ["// Types\nexport * from \"./types/db-conn\";\n\n// Connections\nexport * from \"./connections/mssql-db-conn\";\nexport * from \"./connections/mysql-db-conn\";\nexport * from \"./connections/postgresql-db-conn\";\n\n// Core\nexport * from \"./db-conn-factory\";\nexport * from \"./node-db-context-executor\";\nexport * from \"./pooled-db-conn\";\nexport * from \"./sd-orm\";\n"],
5
4
  "mappings": "AACA,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
6
5
  "names": []
7
6
  }
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/node-db-context-executor.ts"],
4
- "sourcesContent": ["import { SdError } from \"@simplysm/core-common\";\nimport type {\n DbContextExecutor,\n IsolationLevel,\n QueryDef,\n ResultMeta,\n Dialect,\n ColumnMeta,\n DataRecord,\n} from \"@simplysm/orm-common\";\nimport { createQueryBuilder, parseQueryResult } from \"@simplysm/orm-common\";\nimport type { DbConn, DbConnConfig } from \"./types/db-conn\";\nimport { DB_CONN_ERRORS, getDialectFromConfig } from \"./types/db-conn\";\nimport { DbConnFactory } from \"./db-conn-factory\";\n\n/**\n * Node.js \uD658\uACBD\uC6A9 DbContextExecutor\n *\n * DbContext\uC5D0\uC11C \uC0AC\uC6A9\uD558\uB294 \uC2E4\uD589\uAE30\uB85C, \uC2E4\uC81C DB \uC5F0\uACB0\uC744 \uB2F4\uB2F9\uD55C\uB2E4.\n */\nexport class NodeDbContextExecutor implements DbContextExecutor {\n private _conn?: DbConn;\n private readonly _dialect: Dialect;\n\n constructor(private readonly _config: DbConnConfig) {\n this._dialect = getDialectFromConfig(_config);\n }\n\n /**\n * DB \uC5F0\uACB0 \uC218\uB9BD\n *\n * \uCEE4\uB125\uC158 \uD480\uC5D0\uC11C \uC5F0\uACB0\uC744 \uD68D\uB4DD\uD558\uACE0 \uC5F0\uACB0 \uC0C1\uD0DC\uB97C \uD65C\uC131\uD654\uD55C\uB2E4.\n */\n async connect(): Promise<void> {\n this._conn = await DbConnFactory.create(this._config);\n await this._conn.connect();\n }\n\n /**\n * DB \uC5F0\uACB0 \uC885\uB8CC\n *\n * \uCEE4\uB125\uC158 \uD480\uC5D0 \uC5F0\uACB0\uC744 \uBC18\uD658\uD55C\uB2E4.\n *\n * @throws {Error} \uC5F0\uACB0\uB418\uC9C0 \uC54A\uC740 \uC0C1\uD0DC\uC77C \uB54C\n */\n async close(): Promise<void> {\n const conn = this._requireConn();\n await conn.close();\n this._conn = undefined;\n }\n\n /**\n * \uD2B8\uB79C\uC7AD\uC158 \uC2DC\uC791\n *\n * @param isolationLevel - \uD2B8\uB79C\uC7AD\uC158 \uACA9\uB9AC \uC218\uC900\n * @throws {Error} \uC5F0\uACB0\uB418\uC9C0 \uC54A\uC740 \uC0C1\uD0DC\uC77C \uB54C\n */\n async beginTransaction(isolationLevel?: IsolationLevel): Promise<void> {\n const conn = this._requireConn();\n await conn.beginTransaction(isolationLevel);\n }\n\n /**\n * \uD2B8\uB79C\uC7AD\uC158 \uCEE4\uBC0B\n *\n * @throws {Error} \uC5F0\uACB0\uB418\uC9C0 \uC54A\uC740 \uC0C1\uD0DC\uC77C \uB54C\n */\n async commitTransaction(): Promise<void> {\n const conn = this._requireConn();\n await conn.commitTransaction();\n }\n\n /**\n * \uD2B8\uB79C\uC7AD\uC158 \uB864\uBC31\n *\n * @throws {Error} \uC5F0\uACB0\uB418\uC9C0 \uC54A\uC740 \uC0C1\uD0DC\uC77C \uB54C\n */\n async rollbackTransaction(): Promise<void> {\n const conn = this._requireConn();\n await conn.rollbackTransaction();\n }\n\n /**\n * \uD30C\uB77C\uBBF8\uD130\uD654\uB41C \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 {Error} \uC5F0\uACB0\uB418\uC9C0 \uC54A\uC740 \uC0C1\uD0DC\uC77C \uB54C\n */\n async executeParametrized(query: string, params?: unknown[]): Promise<unknown[][]> {\n const conn = this._requireConn();\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 {Error} \uC5F0\uACB0\uB418\uC9C0 \uC54A\uC740 \uC0C1\uD0DC\uC77C \uB54C\n */\n async bulkInsert(tableName: string, columnMetas: Record<string, ColumnMeta>, records: DataRecord[]): Promise<void> {\n const conn = this._requireConn();\n await conn.bulkInsert(tableName, columnMetas, records);\n }\n\n /**\n * QueryDef \uBC30\uC5F4 \uC2E4\uD589\n *\n * QueryDef\uB97C SQL\uB85C \uBCC0\uD658\uD558\uC5EC \uC2E4\uD589\uD558\uACE0, ResultMeta\uB97C \uC0AC\uC6A9\uD558\uC5EC \uACB0\uACFC\uB97C \uD30C\uC2F1\uD55C\uB2E4.\n *\n * @param defs - \uC2E4\uD589\uD560 QueryDef \uBC30\uC5F4\n * @param resultMetas - \uACB0\uACFC \uD30C\uC2F1\uC6A9 \uBA54\uD0C0\uB370\uC774\uD130 \uBC30\uC5F4 (\uD0C0\uC785 \uBCC0\uD658\uC5D0 \uC0AC\uC6A9)\n * @returns \uAC01 QueryDef\uC758 \uC2E4\uD589 \uACB0\uACFC \uBC30\uC5F4\n * @throws {Error} \uC5F0\uACB0\uB418\uC9C0 \uC54A\uC740 \uC0C1\uD0DC\uC77C \uB54C\n */\n async executeDefs<T = DataRecord>(defs: QueryDef[], resultMetas?: (ResultMeta | undefined)[]): Promise<T[][]> {\n const conn = this._requireConn();\n\n const builder = createQueryBuilder(this._dialect);\n\n // \uAC00\uC838\uC62C \uB370\uC774\uD130\uAC00 \uC5C6\uB294 \uAC83\uC73C\uB85C \uC635\uC158 \uC124\uC815\uC744 \uD588\uC744 \uB54C, \uD558\uB098\uC758 \uCFFC\uB9AC\uB85C \uD55C\uBC88\uC758 \uC694\uCCAD \uBCF4\uB0C4\n // \uACB0\uACFC\uAC00 \uD544\uC694 \uC5C6\uC73C\uBBC0\uB85C defs.length\uAC1C\uC758 \uBE48 \uBC30\uC5F4\uC744 \uBC18\uD658\uD558\uC5EC \uC778\uD130\uD398\uC774\uC2A4 \uACC4\uC57D \uC720\uC9C0\n if (resultMetas != null && resultMetas.every((item) => item == null)) {\n const combinedSql = defs.map((def) => builder.build(def).sql).join(\"\\n\");\n await conn.execute([combinedSql]);\n return defs.map(() => []) as T[][];\n }\n\n // \uAC01 def\uB97C \uAC1C\uBCC4 \uC2E4\uD589\n const results: T[][] = [];\n for (let i = 0; i < defs.length; i++) {\n const def = defs[i];\n const meta = resultMetas?.[i];\n const buildResult = builder.build(def);\n\n const rawResults = await conn.execute([buildResult.sql]);\n\n // resultSetIndex\uAC00 \uC9C0\uC815\uB41C \uACBD\uC6B0 \uD574\uB2F9 \uC778\uB371\uC2A4\uC758 \uACB0\uACFC\uC14B \uC0AC\uC6A9\n const targetResultSet =\n buildResult.resultSetIndex != null ? rawResults[buildResult.resultSetIndex] : rawResults[0];\n\n if (meta != null) {\n const parsed = await parseQueryResult<T>(targetResultSet as Record<string, unknown>[], meta);\n results.push(parsed ?? []);\n } else {\n results.push(targetResultSet as T[]);\n }\n }\n\n return results;\n }\n\n private _requireConn(): DbConn {\n if (this._conn == null) {\n throw new SdError(DB_CONN_ERRORS.NOT_CONNECTED);\n }\n return this._conn;\n }\n}\n"],
5
4
  "mappings": "AAAA,SAAS,eAAe;AAUxB,SAAS,oBAAoB,wBAAwB;AAErD,SAAS,gBAAgB,4BAA4B;AACrD,SAAS,qBAAqB;AAOvB,MAAM,sBAAmD;AAAA,EAI9D,YAA6B,SAAuB;AAAvB;AAC3B,SAAK,WAAW,qBAAqB,OAAO;AAAA,EAC9C;AAAA,EALQ;AAAA,EACS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWjB,MAAM,UAAyB;AAC7B,SAAK,QAAQ,MAAM,cAAc,OAAO,KAAK,OAAO;AACpD,UAAM,KAAK,MAAM,QAAQ;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,QAAuB;AAC3B,UAAM,OAAO,KAAK,aAAa;AAC/B,UAAM,KAAK,MAAM;AACjB,SAAK,QAAQ;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,iBAAiB,gBAAgD;AACrE,UAAM,OAAO,KAAK,aAAa;AAC/B,UAAM,KAAK,iBAAiB,cAAc;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,oBAAmC;AACvC,UAAM,OAAO,KAAK,aAAa;AAC/B,UAAM,KAAK,kBAAkB;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,sBAAqC;AACzC,UAAM,OAAO,KAAK,aAAa;AAC/B,UAAM,KAAK,oBAAoB;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,oBAAoB,OAAe,QAA0C;AACjF,UAAM,OAAO,KAAK,aAAa;AAC/B,WAAO,KAAK,oBAAoB,OAAO,MAAM;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,WAAW,WAAmB,aAAyC,SAAsC;AACjH,UAAM,OAAO,KAAK,aAAa;AAC/B,UAAM,KAAK,WAAW,WAAW,aAAa,OAAO;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,YAA4B,MAAkB,aAA0D;AAC5G,UAAM,OAAO,KAAK,aAAa;AAE/B,UAAM,UAAU,mBAAmB,KAAK,QAAQ;AAIhD,QAAI,eAAe,QAAQ,YAAY,MAAM,CAAC,SAAS,QAAQ,IAAI,GAAG;AACpE,YAAM,cAAc,KAAK,IAAI,CAAC,QAAQ,QAAQ,MAAM,GAAG,EAAE,GAAG,EAAE,KAAK,IAAI;AACvE,YAAM,KAAK,QAAQ,CAAC,WAAW,CAAC;AAChC,aAAO,KAAK,IAAI,MAAM,CAAC,CAAC;AAAA,IAC1B;AAGA,UAAM,UAAiB,CAAC;AACxB,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,YAAM,MAAM,KAAK,CAAC;AAClB,YAAM,OAAO,cAAc,CAAC;AAC5B,YAAM,cAAc,QAAQ,MAAM,GAAG;AAErC,YAAM,aAAa,MAAM,KAAK,QAAQ,CAAC,YAAY,GAAG,CAAC;AAGvD,YAAM,kBACJ,YAAY,kBAAkB,OAAO,WAAW,YAAY,cAAc,IAAI,WAAW,CAAC;AAE5F,UAAI,QAAQ,MAAM;AAChB,cAAM,SAAS,MAAM,iBAAoB,iBAA8C,IAAI;AAC3F,gBAAQ,KAAK,UAAU,CAAC,CAAC;AAAA,MAC3B,OAAO;AACL,gBAAQ,KAAK,eAAsB;AAAA,MACrC;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,eAAuB;AAC7B,QAAI,KAAK,SAAS,MAAM;AACtB,YAAM,IAAI,QAAQ,eAAe,aAAa;AAAA,IAChD;AACA,WAAO,KAAK;AAAA,EACd;AACF;",
6
5
  "names": []
7
6
  }
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/pooled-db-conn.ts"],
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
4
  "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
5
  "names": []
7
6
  }
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/sd-orm.ts"],
4
- "sourcesContent": ["import type { DbContext, IsolationLevel } from \"@simplysm/orm-common\";\nimport type { Type } from \"@simplysm/core-common\";\nimport type { DbConnConfig } from \"./types/db-conn\";\nimport { NodeDbContextExecutor } from \"./node-db-context-executor\";\n\n/**\n * SdOrm \uC635\uC158\n *\n * DbConnConfig\uBCF4\uB2E4 \uC6B0\uC120 \uC801\uC6A9\uB418\uB294 DbContext \uC635\uC158\n */\nexport interface SdOrmOptions {\n /**\n * \uB370\uC774\uD130\uBCA0\uC774\uC2A4 \uC774\uB984 (DbConnConfig\uC758 database \uB300\uC2E0 \uC0AC\uC6A9)\n */\n database?: string;\n\n /**\n * \uC2A4\uD0A4\uB9C8 \uC774\uB984 (MSSQL: dbo, PostgreSQL: public)\n */\n schema?: string;\n}\n\n/**\n * Node.js ORM \uD074\uB798\uC2A4\n *\n * DbContext\uC640 DB \uC5F0\uACB0\uC744 \uAD00\uB9AC\uD558\uB294 \uCD5C\uC0C1\uC704 \uD074\uB798\uC2A4\uC785\uB2C8\uB2E4.\n * DbContext \uD0C0\uC785\uACFC \uC5F0\uACB0 \uC124\uC815\uC744 \uBC1B\uC544 \uD2B8\uB79C\uC7AD\uC158\uC744 \uAD00\uB9AC\uD569\uB2C8\uB2E4.\n *\n * @example\n * ```typescript\n * class MyDb extends DbContext {\n * readonly user = queryable(this, User);\n * }\n *\n * const orm = new SdOrm(MyDb, {\n * dialect: \"mysql\",\n * host: \"localhost\",\n * port: 3306,\n * username: \"root\",\n * password: \"password\",\n * database: \"mydb\",\n * });\n *\n * // \uD2B8\uB79C\uC7AD\uC158 \uB0B4\uC5D0\uC11C \uC2E4\uD589\n * await orm.connect(async (db) => {\n * const users = await db.user().result();\n * return users;\n * });\n *\n * // \uD2B8\uB79C\uC7AD\uC158 \uC5C6\uC774 \uC2E4\uD589\n * await orm.connectWithoutTransaction(async (db) => {\n * const users = await db.user().result();\n * return users;\n * });\n * ```\n */\nexport class SdOrm<T extends DbContext> {\n constructor(\n readonly dbContextType: Type<T>,\n readonly config: DbConnConfig,\n readonly options?: SdOrmOptions,\n ) {}\n\n /**\n * \uD2B8\uB79C\uC7AD\uC158 \uB0B4\uC5D0\uC11C \uCF5C\uBC31 \uC2E4\uD589\n *\n * @param callback - DB \uC5F0\uACB0 \uD6C4 \uC2E4\uD589\uD560 \uCF5C\uBC31\n * @param isolationLevel - \uD2B8\uB79C\uC7AD\uC158 \uACA9\uB9AC \uC218\uC900\n * @returns \uCF5C\uBC31 \uACB0\uACFC\n */\n async connect<R>(callback: (conn: T) => Promise<R>, isolationLevel?: IsolationLevel): Promise<R> {\n const db = this._createDbContext();\n return db.connect(async () => callback(db), isolationLevel);\n }\n\n /**\n * \uD2B8\uB79C\uC7AD\uC158 \uC5C6\uC774 \uCF5C\uBC31 \uC2E4\uD589\n *\n * @param callback - DB \uC5F0\uACB0 \uD6C4 \uC2E4\uD589\uD560 \uCF5C\uBC31\n * @returns \uCF5C\uBC31 \uACB0\uACFC\n */\n async connectWithoutTransaction<R>(callback: (conn: T) => Promise<R>): Promise<R> {\n const db = this._createDbContext();\n return db.connectWithoutTransaction(async () => callback(db));\n }\n\n /**\n * DbContext \uC778\uC2A4\uD134\uC2A4 \uC0DD\uC131\n */\n private _createDbContext(): T {\n // database\uB294 options\uC5D0\uC11C \uC6B0\uC120, \uC5C6\uC73C\uBA74 config\uC5D0\uC11C\n const database = this.options?.database ?? (\"database\" in this.config ? this.config.database : undefined);\n\n // schema\uB294 options\uC5D0\uC11C \uC6B0\uC120, \uC5C6\uC73C\uBA74 config\uC5D0\uC11C\n const schema = this.options?.schema ?? (\"schema\" in this.config ? this.config.schema : undefined);\n\n return new this.dbContextType(new NodeDbContextExecutor(this.config), {\n database,\n schema,\n });\n }\n}\n"],
5
4
  "mappings": "AAGA,SAAS,6BAA6B;AAqD/B,MAAM,MAA2B;AAAA,EACtC,YACW,eACA,QACA,SACT;AAHS;AACA;AACA;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASH,MAAM,QAAW,UAAmC,gBAA6C;AAC/F,UAAM,KAAK,KAAK,iBAAiB;AACjC,WAAO,GAAG,QAAQ,YAAY,SAAS,EAAE,GAAG,cAAc;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,0BAA6B,UAA+C;AAChF,UAAM,KAAK,KAAK,iBAAiB;AACjC,WAAO,GAAG,0BAA0B,YAAY,SAAS,EAAE,CAAC;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAsB;AAE5B,UAAM,WAAW,KAAK,SAAS,aAAa,cAAc,KAAK,SAAS,KAAK,OAAO,WAAW;AAG/F,UAAM,SAAS,KAAK,SAAS,WAAW,YAAY,KAAK,SAAS,KAAK,OAAO,SAAS;AAEvF,WAAO,IAAI,KAAK,cAAc,IAAI,sBAAsB,KAAK,MAAM,GAAG;AAAA,MACpE;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AACF;",
6
5
  "names": []
7
6
  }
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/types/db-conn.ts"],
4
- "sourcesContent": ["import type { EventEmitter } from \"@simplysm/core-common\";\nimport type { ColumnMeta, Dialect, IsolationLevel } from \"@simplysm/orm-common\";\n\n// ============================================\n// \uACF5\uD1B5 \uC0C1\uC218\n// ============================================\n\n/**\n * DB \uC5F0\uACB0 \uAE30\uBCF8 \uD0C0\uC784\uC544\uC6C3 (10\uBD84)\n */\nexport const DB_CONN_DEFAULT_TIMEOUT = 10 * 60 * 1000;\n\n/**\n * DB \uC5F0\uACB0 \uC5D0\uB7EC \uBA54\uC2DC\uC9C0\n */\nexport const DB_CONN_ERRORS = {\n NOT_CONNECTED: \"'Connection'\uC774 \uC5F0\uACB0\uB418\uC5B4\uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.\",\n ALREADY_CONNECTED: \"\uC774\uBBF8 'Connection'\uC774 \uC5F0\uACB0\uB418\uC5B4\uC788\uC2B5\uB2C8\uB2E4.\",\n} as const;\n\n// ============================================\n// IDbConn Interface\n// ============================================\n\n/**\n * \uC800\uC218\uC900 DB \uC5F0\uACB0 \uC778\uD130\uD398\uC774\uC2A4\n *\n * \uAC01 DBMS\uBCC4 \uAD6C\uD604\uCCB4\uAC00 \uC774 \uC778\uD130\uD398\uC774\uC2A4\uB97C \uAD6C\uD604\uD569\uB2C8\uB2E4.\n * - {@link MysqlDbConn} - MySQL \uC5F0\uACB0\n * - {@link MssqlDbConn} - MSSQL \uC5F0\uACB0\n * - {@link PostgresqlDbConn} - PostgreSQL \uC5F0\uACB0\n *\n * @remarks\n * SdEventEmitter\uB97C \uC0C1\uC18D\uD558\uC5EC 'close' \uC774\uBCA4\uD2B8\uB97C \uBC1C\uC0DD\uC2DC\uD0B5\uB2C8\uB2E4.\n */\nexport interface DbConn extends EventEmitter<{ close: void }> {\n /**\n * \uC5F0\uACB0 \uC124\uC815\n */\n config: DbConnConfig;\n\n /**\n * \uC5F0\uACB0 \uC5EC\uBD80\n */\n isConnected: boolean;\n\n /**\n * \uD2B8\uB79C\uC7AD\uC158 \uC9C4\uD589 \uC5EC\uBD80\n */\n isOnTransaction: boolean;\n\n /**\n * DB \uC5F0\uACB0 \uC218\uB9BD\n */\n connect(): Promise<void>;\n\n /**\n * DB \uC5F0\uACB0 \uC885\uB8CC\n */\n close(): Promise<void>;\n\n /**\n * \uD2B8\uB79C\uC7AD\uC158 \uC2DC\uC791\n *\n * @param isolationLevel - \uACA9\uB9AC \uC218\uC900 (\uC120\uD0DD)\n */\n beginTransaction(isolationLevel?: IsolationLevel): Promise<void>;\n\n /**\n * \uD2B8\uB79C\uC7AD\uC158 \uCEE4\uBC0B\n */\n commitTransaction(): Promise<void>;\n\n /**\n * \uD2B8\uB79C\uC7AD\uC158 \uB864\uBC31\n */\n rollbackTransaction(): Promise<void>;\n\n /**\n * SQL \uCFFC\uB9AC \uBC30\uC5F4 \uC2E4\uD589\n *\n * @param queries - \uC2E4\uD589\uD560 SQL \uBB38\uC790\uC5F4 \uBC30\uC5F4\n * @returns \uAC01 \uCFFC\uB9AC\uBCC4 \uACB0\uACFC \uBC30\uC5F4\uC758 \uBC30\uC5F4\n */\n execute(queries: string[]): Promise<unknown[][]>;\n\n /**\n * \uD30C\uB77C\uBBF8\uD130\uD654\uB41C \uCFFC\uB9AC \uC2E4\uD589\n *\n * @param query - SQL \uCFFC\uB9AC \uBB38\uC790\uC5F4\n * @param params - \uBC14\uC778\uB529 \uD30C\uB77C\uBBF8\uD130 (\uC120\uD0DD)\n * @returns \uACB0\uACFC \uBC30\uC5F4\uC758 \uBC30\uC5F4\n */\n executeParametrized(query: string, params?: unknown[]): Promise<unknown[][]>;\n\n /**\n * \uB300\uB7C9 INSERT (\uB124\uC774\uD2F0\uBE0C \uBC8C\uD06C API \uC0AC\uC6A9)\n *\n * - MSSQL: tedious BulkLoad\n * - MySQL: LOAD DATA LOCAL INFILE (\uC784\uC2DC \uD30C\uC77C)\n * - PostgreSQL: COPY FROM STDIN\n *\n * @param tableName - \uD14C\uC774\uBE14\uBA85 (database.table \uB610\uB294 database.schema.table)\n * @param columnMetas - \uCEEC\uB7FC\uBA85 \u2192 ColumnMeta \uB9E4\uD551\n * @param records - \uC0BD\uC785\uD560 \uB808\uCF54\uB4DC \uBC30\uC5F4\n */\n bulkInsert(\n tableName: string,\n columnMetas: Record<string, ColumnMeta>,\n records: Record<string, unknown>[],\n ): Promise<void>;\n}\n\n// ============================================\n// DbConnConfig Types\n// ============================================\n\n/**\n * \uCEE4\uB125\uC158 \uD480 \uC124\uC815\n *\n * @remarks\n * \uAC01 \uAC12\uC758 \uAE30\uBCF8\uAC12:\n * - min: 1 (\uCD5C\uC18C \uC5F0\uACB0 \uC218)\n * - max: 10 (\uCD5C\uB300 \uC5F0\uACB0 \uC218)\n * - acquireTimeoutMillis: 30000 (\uC5F0\uACB0 \uD68D\uB4DD \uD0C0\uC784\uC544\uC6C3)\n * - idleTimeoutMillis: 30000 (\uC720\uD734 \uC5F0\uACB0 \uD0C0\uC784\uC544\uC6C3)\n */\nexport interface DbPoolConfig {\n /** \uCD5C\uC18C \uC5F0\uACB0 \uC218 (\uAE30\uBCF8: 1) */\n min?: number;\n /** \uCD5C\uB300 \uC5F0\uACB0 \uC218 (\uAE30\uBCF8: 10) */\n max?: number;\n /** \uC5F0\uACB0 \uD68D\uB4DD \uD0C0\uC784\uC544\uC6C3 (\uBC00\uB9AC\uCD08, \uAE30\uBCF8: 30000) */\n acquireTimeoutMillis?: number;\n /** \uC720\uD734 \uC5F0\uACB0 \uD0C0\uC784\uC544\uC6C3 (\uBC00\uB9AC\uCD08, \uAE30\uBCF8: 30000) */\n idleTimeoutMillis?: number;\n}\n\n/**\n * DB \uC5F0\uACB0 \uC124\uC815 \uD0C0\uC785 (dialect\uBCC4 \uBD84\uAE30)\n */\nexport type DbConnConfig = MysqlDbConnConfig | MssqlDbConnConfig | PostgresqlDbConnConfig;\n\n/**\n * MySQL \uC5F0\uACB0 \uC124\uC815\n */\nexport interface MysqlDbConnConfig {\n dialect: \"mysql\";\n host: string;\n port?: number;\n username: string;\n password: string;\n database?: string;\n defaultIsolationLevel?: IsolationLevel;\n pool?: DbPoolConfig;\n}\n\n/**\n * MSSQL \uC5F0\uACB0 \uC124\uC815\n */\nexport interface MssqlDbConnConfig {\n dialect: \"mssql\" | \"mssql-azure\";\n host: string;\n port?: number;\n username: string;\n password: string;\n database?: string;\n schema?: string;\n defaultIsolationLevel?: IsolationLevel;\n pool?: DbPoolConfig;\n}\n\n/**\n * PostgreSQL \uC5F0\uACB0 \uC124\uC815\n */\nexport interface PostgresqlDbConnConfig {\n dialect: \"postgresql\";\n host: string;\n port?: number;\n username: string;\n password: string;\n database?: string;\n schema?: string;\n defaultIsolationLevel?: IsolationLevel;\n pool?: DbPoolConfig;\n}\n\n/**\n * DbConnConfig\uC5D0\uC11C Dialect \uCD94\uCD9C\n */\nexport function getDialectFromConfig(config: DbConnConfig): Dialect {\n if (config.dialect === \"mssql-azure\") {\n return \"mssql\";\n }\n return config.dialect;\n}\n"],
5
4
  "mappings": "AAUO,MAAM,0BAA0B,KAAK,KAAK;AAK1C,MAAM,iBAAiB;AAAA,EAC5B,eAAe;AAAA,EACf,mBAAmB;AACrB;AA4KO,SAAS,qBAAqB,QAA+B;AAClE,MAAI,OAAO,YAAY,eAAe;AACpC,WAAO;AAAA,EACT;AACA,SAAO,OAAO;AAChB;",
6
5
  "names": []
7
6
  }
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.46",
4
+ "version": "13.0.0-beta.48",
5
5
  "description": "심플리즘 패키지 - ORM 모듈 (node)",
6
6
  "author": "김석래",
7
7
  "repository": {
@@ -14,13 +14,14 @@
14
14
  "main": "./dist/index.js",
15
15
  "types": "./dist/index.d.ts",
16
16
  "files": [
17
- "dist"
17
+ "dist",
18
+ "src"
18
19
  ],
19
20
  "dependencies": {
20
21
  "consola": "^3.4.2",
21
22
  "generic-pool": "^3.9.0",
22
- "@simplysm/core-common": "13.0.0-beta.46",
23
- "@simplysm/orm-common": "13.0.0-beta.46"
23
+ "@simplysm/core-common": "13.0.0-beta.48",
24
+ "@simplysm/orm-common": "13.0.0-beta.48"
24
25
  },
25
26
  "devDependencies": {
26
27
  "@types/pg": "^8.16.0",