@lark-apaas/nestjs-datapaas 1.0.7 → 1.0.8-alpha.2

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/index.cjs CHANGED
@@ -32,6 +32,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
32
32
  var index_exports = {};
33
33
  __export(index_exports, {
34
34
  DATAPAAS_CONFIG: () => DATAPAAS_CONFIG,
35
+ DATAPAAS_LOGGER_SERVICE: () => DATAPAAS_LOGGER_SERVICE,
35
36
  DRIZZLE_DATABASE: () => DRIZZLE_DATABASE,
36
37
  DataPaasDatabaseService: () => DataPaasDatabaseService,
37
38
  DataPaasModule: () => DataPaasModule,
@@ -42,7 +43,7 @@ __export(index_exports, {
42
43
  module.exports = __toCommonJS(index_exports);
43
44
 
44
45
  // src/database/drizzle-manager.ts
45
- var import_common = require("@nestjs/common");
46
+ var import_common2 = require("@nestjs/common");
46
47
  var import_postgres_js = require("drizzle-orm/postgres-js");
47
48
  var import_drizzle_orm = require("drizzle-orm");
48
49
  var import_postgres = __toESM(require("postgres"), 1);
@@ -50,11 +51,16 @@ var import_postgres = __toESM(require("postgres"), 1);
50
51
  // src/database/const.ts
51
52
  var DRIZZLE_DATABASE = "DRIZZLE_DATABASE";
52
53
  var DATAPAAS_CONFIG = "DATAPAAS_CONFIG";
54
+ var DATAPAAS_LOGGER_SERVICE = /* @__PURE__ */ Symbol("DATAPAAS_LOGGER_SERVICE");
55
+
56
+ // src/database/drizzle-manager.ts
57
+ var import_nestjs_observable = require("@lark-apaas/nestjs-observable");
58
+ var import_nestjs_common = require("@lark-apaas/nestjs-common");
53
59
 
54
60
  // src/utils.ts
55
61
  function parseConnectionInfo(connectionString, config) {
56
62
  const { maxConnections, idleTimeout, connectionTimeout, ssl, logger } = config || {};
57
- let parsedConfigFromUrl = null;
63
+ let parsedConfigFromUrl;
58
64
  try {
59
65
  parsedConfigFromUrl = new URL(connectionString);
60
66
  const temp = new URL(connectionString);
@@ -87,6 +93,98 @@ function parseConnectionInfo(connectionString, config) {
87
93
  }
88
94
  __name(parseConnectionInfo, "parseConnectionInfo");
89
95
 
96
+ // src/database/postgres-proxy.ts
97
+ var import_common = require("@nestjs/common");
98
+ var nestLogger = new import_common.Logger("Database");
99
+ function genPostgresProxy(sql3, observable, requestContext) {
100
+ const wrapQuery = /* @__PURE__ */ __name((query) => {
101
+ if (query && typeof query.then === "function") {
102
+ return new Proxy(query, {
103
+ get(target, prop, receiver) {
104
+ if (prop === "then") {
105
+ return async (onfulfilled, onrejected) => {
106
+ const sqlStr = query.strings instanceof Array ? query.strings[0] : "";
107
+ const span = observable.startTrace(sqlStr, requestContext?.getContext()?.requestRootSpan);
108
+ span.setAttribute("module", "data");
109
+ span.setAttribute("source_type", "platform");
110
+ const start = Date.now();
111
+ try {
112
+ const result = await target;
113
+ const isSetRoleSql = result?.command === "SET";
114
+ if (!isSetRoleSql) {
115
+ const duration = Date.now() - start;
116
+ const parsedParams = JSON.stringify({
117
+ operation: result?.command,
118
+ sql: result?.statement?.string,
119
+ duration_ms: duration,
120
+ result_count: result.length ?? 0,
121
+ error_message: ""
122
+ });
123
+ nestLogger.log(parsedParams, {
124
+ source_type: "platform",
125
+ paas_attributes_module: "data"
126
+ });
127
+ } else {
128
+ observable.dropTrace(span);
129
+ }
130
+ span.end();
131
+ return onfulfilled ? onfulfilled(result) : result;
132
+ } catch (error) {
133
+ const duration = Date.now() - start;
134
+ const sqlStr2 = query.strings instanceof Array ? query.strings[0] : "";
135
+ const parsedParams = JSON.stringify({
136
+ operation: "",
137
+ sql: sqlStr2,
138
+ duration_ms: duration,
139
+ result_count: 0,
140
+ error_message: error instanceof Error ? error.message : String(error)
141
+ });
142
+ nestLogger.log(parsedParams, {
143
+ source_type: "platform",
144
+ paas_attributes_module: "data"
145
+ });
146
+ span.end();
147
+ return onrejected ? onrejected(error) : Promise.reject(error);
148
+ }
149
+ };
150
+ }
151
+ const value = Reflect.get(target, prop, receiver);
152
+ return typeof value === "function" ? value.bind(receiver) : value;
153
+ }
154
+ });
155
+ }
156
+ return query;
157
+ }, "wrapQuery");
158
+ return new Proxy(sql3, {
159
+ apply(target, thisArg, argArray) {
160
+ const query = Reflect.apply(target, thisArg, argArray);
161
+ return wrapQuery(query);
162
+ },
163
+ get(target, prop, receiver) {
164
+ const value = Reflect.get(target, prop, receiver);
165
+ if (prop === "begin" && typeof value === "function") {
166
+ return (arg, cb) => {
167
+ if (typeof arg === "function") {
168
+ return value.call(target, (tx) => arg(genPostgresProxy(tx, observable, requestContext)));
169
+ }
170
+ if (typeof cb === "function") {
171
+ return value.call(target, arg, (tx) => cb(genPostgresProxy(tx, observable, requestContext)));
172
+ }
173
+ return value.call(target, arg);
174
+ };
175
+ }
176
+ if (prop === "unsafe" && typeof value === "function") {
177
+ return (queryStr, args, options) => {
178
+ const query = value.call(target, queryStr, args, options);
179
+ return wrapQuery(query);
180
+ };
181
+ }
182
+ return typeof value === "function" ? value.bind(receiver) : value;
183
+ }
184
+ });
185
+ }
186
+ __name(genPostgresProxy, "genPostgresProxy");
187
+
90
188
  // src/database/drizzle-manager.ts
91
189
  function _ts_decorate(decorators, target, key, desc) {
92
190
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -110,12 +208,16 @@ var DrizzleDatabaseManager = class {
110
208
  __name(this, "DrizzleDatabaseManager");
111
209
  }
112
210
  config;
211
+ observable;
212
+ requestContext;
113
213
  db = null;
114
214
  currentConnectionInfo = null;
115
215
  isConnected = false;
116
216
  skipInitDbConnection = false;
117
- constructor(config) {
217
+ constructor(config, observable, requestContext) {
118
218
  this.config = config;
219
+ this.observable = observable;
220
+ this.requestContext = requestContext;
119
221
  this.skipInitDbConnection = !!process.env.DEPRECATED_SKIP_INIT_DB_CONNECTION;
120
222
  }
121
223
  async onModuleInit() {
@@ -138,10 +240,11 @@ var DrizzleDatabaseManager = class {
138
240
  }
139
241
  try {
140
242
  const { connectionString, connectionConfig } = parseConnectionInfo(this.config.connectionString, this.config);
141
- const sql3 = (0, import_postgres.default)(connectionString, connectionConfig);
142
- this.db = (0, import_postgres_js.drizzle)(sql3, {
243
+ const baseSql = (0, import_postgres.default)(connectionString, connectionConfig);
244
+ const sqlProxy = genPostgresProxy(baseSql, this.observable, this.requestContext);
245
+ this.db = (0, import_postgres_js.drizzle)(sqlProxy, {
143
246
  schema: this.config.schema,
144
- logger: this.config.logger
247
+ logger: false
145
248
  });
146
249
  this.currentConnectionInfo = {
147
250
  connectionString,
@@ -244,19 +347,22 @@ var DrizzleDatabaseManager = class {
244
347
  }
245
348
  };
246
349
  DrizzleDatabaseManager = _ts_decorate([
247
- (0, import_common.Injectable)(),
248
- _ts_param(0, (0, import_common.Inject)(DATAPAAS_CONFIG)),
350
+ (0, import_common2.Injectable)(),
351
+ _ts_param(0, (0, import_common2.Inject)(DATAPAAS_CONFIG)),
352
+ _ts_param(1, (0, import_common2.Inject)(DATAPAAS_LOGGER_SERVICE)),
249
353
  _ts_metadata("design:type", Function),
250
354
  _ts_metadata("design:paramtypes", [
251
- typeof DataPaasConfig === "undefined" ? Object : DataPaasConfig
355
+ typeof DataPaasConfig === "undefined" ? Object : DataPaasConfig,
356
+ typeof import_nestjs_observable.Observable === "undefined" ? Object : import_nestjs_observable.Observable,
357
+ typeof import_nestjs_common.RequestContextService === "undefined" ? Object : import_nestjs_common.RequestContextService
252
358
  ])
253
359
  ], DrizzleDatabaseManager);
254
360
 
255
361
  // src/database/database.module.ts
256
- var import_common4 = require("@nestjs/common");
362
+ var import_common5 = require("@nestjs/common");
257
363
 
258
364
  // src/database/database.service.ts
259
- var import_common2 = require("@nestjs/common");
365
+ var import_common3 = require("@nestjs/common");
260
366
  function _ts_decorate2(decorators, target, key, desc) {
261
367
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
262
368
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -342,7 +448,7 @@ var DataPaasDatabaseService = class {
342
448
  }
343
449
  };
344
450
  DataPaasDatabaseService = _ts_decorate2([
345
- (0, import_common2.Injectable)(),
451
+ (0, import_common3.Injectable)(),
346
452
  _ts_metadata2("design:type", Function),
347
453
  _ts_metadata2("design:paramtypes", [
348
454
  typeof DrizzleDatabaseManager === "undefined" ? Object : DrizzleDatabaseManager
@@ -350,7 +456,7 @@ DataPaasDatabaseService = _ts_decorate2([
350
456
  ], DataPaasDatabaseService);
351
457
 
352
458
  // src/database/sql-exection-context.middleware.ts
353
- var import_common3 = require("@nestjs/common");
459
+ var import_common4 = require("@nestjs/common");
354
460
  var session = __toESM(require("drizzle-orm/postgres-js"), 1);
355
461
  function _ts_decorate3(decorators, target, key, desc) {
356
462
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -402,8 +508,8 @@ var SqlExecutionContextMiddleware = class {
402
508
  }
403
509
  };
404
510
  SqlExecutionContextMiddleware = _ts_decorate3([
405
- (0, import_common3.Injectable)(),
406
- _ts_param2(0, (0, import_common3.Inject)(DATAPAAS_CONFIG)),
511
+ (0, import_common4.Injectable)(),
512
+ _ts_param2(0, (0, import_common4.Inject)(DATAPAAS_CONFIG)),
407
513
  _ts_metadata3("design:type", Function),
408
514
  _ts_metadata3("design:paramtypes", [
409
515
  typeof DataPaasConfig === "undefined" ? Object : DataPaasConfig
@@ -411,6 +517,8 @@ SqlExecutionContextMiddleware = _ts_decorate3([
411
517
  ], SqlExecutionContextMiddleware);
412
518
 
413
519
  // src/database/database.module.ts
520
+ var import_nestjs_common2 = require("@lark-apaas/nestjs-common");
521
+ var import_nestjs_observable2 = require("@lark-apaas/nestjs-observable");
414
522
  function _ts_decorate4(decorators, target, key, desc) {
415
523
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
416
524
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -629,7 +737,23 @@ var DataPaasModule = class _DataPaasModule {
629
737
  }
630
738
  };
631
739
  DataPaasModule = _ts_decorate4([
632
- (0, import_common4.Module)({})
740
+ (0, import_common5.Module)({
741
+ providers: [
742
+ {
743
+ provide: DATAPAAS_LOGGER_SERVICE,
744
+ useFactory: /* @__PURE__ */ __name((observable, rtx) => {
745
+ return observable ?? new import_nestjs_observable2.Observable(rtx);
746
+ }, "useFactory"),
747
+ inject: [
748
+ {
749
+ token: import_nestjs_common2.OBSERVABLE_SERVICE,
750
+ optional: true
751
+ },
752
+ import_nestjs_common2.RequestContextService
753
+ ]
754
+ }
755
+ ]
756
+ })
633
757
  ], DataPaasModule);
634
758
 
635
759
  // src/database/database-utils.ts
@@ -813,6 +937,7 @@ var DatabaseUtils = class {
813
937
  // Annotate the CommonJS export names for ESM import in node:
814
938
  0 && (module.exports = {
815
939
  DATAPAAS_CONFIG,
940
+ DATAPAAS_LOGGER_SERVICE,
816
941
  DRIZZLE_DATABASE,
817
942
  DataPaasDatabaseService,
818
943
  DataPaasModule,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/database/drizzle-manager.ts","../src/database/const.ts","../src/utils.ts","../src/database/database.module.ts","../src/database/database.service.ts","../src/database/sql-exection-context.middleware.ts","../src/database/database-utils.ts"],"sourcesContent":["// 导出所有公共API\n\nexport * from './database';\nexport * from './types';\n","import { Injectable, OnModuleInit, OnModuleDestroy, Inject } from '@nestjs/common';\nimport { drizzle, type PostgresJsDatabase } from 'drizzle-orm/postgres-js';\nimport { sql } from 'drizzle-orm';\nimport postgres from 'postgres';\nimport { DATAPAAS_CONFIG } from './const';\n\nimport { type DataPaasConfig, type DatabaseConnectionInfo } from '../types';\nimport { parseConnectionInfo } from '../utils';\n@Injectable()\nexport class DrizzleDatabaseManager implements OnModuleInit, OnModuleDestroy {\n private db: PostgresJsDatabase | null = null;\n private currentConnectionInfo: DatabaseConnectionInfo | null = null;\n private isConnected: boolean = false;\n private skipInitDbConnection: boolean = false;\n constructor(\n @Inject(DATAPAAS_CONFIG)\n private readonly config: DataPaasConfig,\n ) { \n this.skipInitDbConnection = !!process.env.DEPRECATED_SKIP_INIT_DB_CONNECTION;\n\n }\n\n async onModuleInit() {\n await this.initialize();\n }\n\n async onModuleDestroy() {\n await this.disconnect();\n }\n\n /**\n * 初始化数据库连接\n * @returns Drizzle 数据库实例\n */\n async initialize(): Promise<PostgresJsDatabase> {\n if (this.skipInitDbConnection) {\n this.isConnected = true;\n this.db = {name: 'skipInitDbConnection'} as unknown as PostgresJsDatabase;\n return this.db;\n }\n try {\n const { connectionString, connectionConfig } = parseConnectionInfo(this.config.connectionString, this.config);\n const sql = postgres(connectionString, connectionConfig);\n // 创建 Drizzle 实例\n this.db = drizzle(sql, { schema: this.config.schema, logger: this.config.logger });\n this.currentConnectionInfo = {\n connectionString,\n connectionConfig: {\n ssl: connectionConfig.ssl,\n connectionTimeout: connectionConfig.connect_timeout,\n idleTimeout: connectionConfig.idle_timeout,\n maxConnections: connectionConfig.max,\n },\n };\n this.isConnected = true;\n return this.db;\n } catch (error) {\n this.isConnected = false;\n throw new Error(`Failed to initialize database connection: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n }\n\n /**\n * 获取数据库实例\n * @returns Drizzle 数据库实例\n */\n getDatabase(): PostgresJsDatabase {\n if (!this.db || !this.isConnected) {\n throw new Error('Database not initialized. Call initialize() first.');\n }\n return this.db;\n }\n\n /**\n * 测试数据库连接\n * @returns 连接是否正常\n */\n async testConnection(): Promise<boolean> {\n if (!this.db) {\n return false;\n }\n\n try {\n await this.db.execute(sql`SELECT 1`);\n return true;\n } catch (error) {\n console.error('Database connection test failed:', error);\n this.isConnected = false;\n return false;\n }\n }\n\n /**\n * 重新连接数据库\n * @param forceRefresh 是否强制刷新连接信息\n * @returns 新的数据库实例\n */\n async reconnect(_forceRefresh: boolean = false): Promise<PostgresJsDatabase> {\n await this.disconnect();\n return this.initialize();\n }\n\n /**\n * 断开数据库连接\n */\n async disconnect(): Promise<void> {\n if (this.db) {\n try {\n // postgres-js 会自动处理连接关闭\n this.db = null;\n this.isConnected = false;\n this.currentConnectionInfo = null;\n } catch (error) {\n console.error('Error disconnecting from database:', error);\n }\n }\n }\n\n /**\n * 获取当前连接信息\n * @returns 当前连接信息\n */\n getConnectionInfo(): DatabaseConnectionInfo | null {\n return this.currentConnectionInfo;\n }\n\n /**\n * 检查连接状态\n * @returns 是否已连接\n */\n isDatabaseConnected(): boolean {\n return this.isConnected;\n }\n\n\n /**\n * 开始事务\n * @param callback 事务回调函数\n * @returns 事务结果\n */\n async transaction<T>(callback: (tx: PostgresJsDatabase) => Promise<T>): Promise<T> {\n const db = this.getDatabase();\n return db.transaction(callback);\n }\n\n /**\n * 获取连接池状态\n * @returns 连接池状态信息\n */\n getConnectionPoolStatus(): { isConnected: boolean; connectionInfo: DatabaseConnectionInfo | null } {\n return {\n isConnected: this.isConnected,\n connectionInfo: this.currentConnectionInfo,\n };\n }\n}","export const DRIZZLE_DATABASE = 'DRIZZLE_DATABASE';\nexport const DATAPAAS_CONFIG = 'DATAPAAS_CONFIG';","import { type Logger } from 'drizzle-orm';\nimport { PostgresOptions } from './types';\ninterface ConnectionConfig {\n maxConnections?: number;\n idleTimeout?: number;\n connectionTimeout?: number;\n ssl?: PostgresOptions['ssl'];\n logger?: boolean | Logger;\n}\nexport function parseConnectionInfo(connectionString: string, config?: ConnectionConfig) {\n const { maxConnections, idleTimeout, connectionTimeout, ssl, logger } = config || {};\n // 创建 postgres 连接\n let parsedConfigFromUrl = null;\n try {\n parsedConfigFromUrl = new URL(connectionString);\n const temp = new URL(connectionString);\n temp.searchParams.delete('schema'); // 移除schema参数,避免 postgres 解析错误\n connectionString = temp.toString();\n } catch (error) {\n throw new Error('Failed to parse connection info');\n }\n const { username, password, hostname, port, pathname } = parsedConfigFromUrl;\n const connectionConfig = {\n username: decodeURIComponent(username),\n password: decodeURIComponent(password),\n host: [hostname] as unknown as string,\n port: [parseInt(port) || 5432] as unknown as number,\n pathname: decodeURIComponent(pathname),\n max: maxConnections || 1,\n idle_timeout: idleTimeout || 20,\n connect_timeout: connectionTimeout || 10,\n ssl,\n onnotice: logger ? console.log : undefined,\n }\n return { connectionString, connectionConfig };\n}","import {\n Module,\n DynamicModule,\n Provider,\n MiddlewareConsumer,\n InjectionToken,\n ModuleMetadata,\n} from '@nestjs/common';\nimport { DrizzleDatabaseManager } from './drizzle-manager';\nimport { DataPaasDatabaseService } from './database.service';\nimport { SqlExecutionContextMiddleware } from './sql-exection-context.middleware';\nimport { type DataPaasConfig } from '@/types';\nimport { DATAPAAS_CONFIG, DRIZZLE_DATABASE } from './const';\nexport { type PostgresJsDatabase } from 'drizzle-orm/postgres-js';\n\nexport interface DataPaasModuleOptions extends DataPaasConfig {}\n\n/**\n * 异步配置选项\n */\nexport interface DataPaasModuleAsyncOptions {\n /**\n * 需要导入的模块(例如 ConfigModule)\n */\n imports?: ModuleMetadata['imports'];\n /**\n * 使用工厂函数创建配置\n */\n useFactory?: (...args: unknown[]) => Promise<DataPaasConfig> | DataPaasConfig;\n /**\n * 工厂函数需要注入的依赖\n */\n inject?: InjectionToken[];\n}\n\nfunction verifyDrizzlePatched(): void {\n try {\n // 直接加载被 patch 的 CJS 模块并检查导出是否存在\n // 注意:此路径与补丁文件一致:drizzle-orm/postgres-js/session.cjs\n // 若未来包结构变化,请同步更新补丁与此校验\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const postgres = require('drizzle-orm/postgres-js');\n const ok =\n postgres &&\n typeof postgres.getAuthContextStore === 'function' &&\n typeof postgres.runWithAuthContext === 'function';\n if (!ok) {\n throw new Error(\n 'drizzle-orm 未检测到补丁导出:getAuthContextStore/runWithAuthContext',\n );\n }\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err);\n throw new Error(`drizzle-orm 补丁未生效或版本不匹配:${reason}`);\n }\n}\n\n// 在模块初始化阶段进行一次 drizzle-orm 补丁自检\nverifyDrizzlePatched();\n\n@Module({})\nexport class DataPaasModule {\n configure(_consumer: MiddlewareConsumer) {}\n /**\n * 注册数据平台模块(同步方式)\n * @param options 模块配置选项\n * @returns 动态模块\n */\n static forRoot(options: DataPaasConfig): DynamicModule {\n let roleSchema = '';\n let sslModeRequired = false;\n if (options.connectionString) {\n try {\n const url = new URL(options.connectionString);\n\n roleSchema = url.searchParams.get(\n 'schema'\n ) as string;\n sslModeRequired = url.searchParams.get('sslmode') === \"require\";\n } catch (err) {\n roleSchema = '';\n }\n }\n const config: DataPaasConfig = {\n connectionString: options.connectionString,\n schema: options.schema,\n logger: options.logger || false,\n timeout: options.timeout || 10000,\n maxConnections: options.maxConnections || 1,\n idleTimeout: options.idleTimeout || 20,\n connectionTimeout: options.connectionTimeout || 10,\n ssl: options.ssl || (sslModeRequired ? 'require' : false),\n autoContext: options.autoContext == null ? true : !!options.autoContext,\n roleSchema,\n };\n\n const providers: Provider[] = [\n // 配置提供者 - 使用 useValue\n {\n provide: DATAPAAS_CONFIG,\n useValue: config,\n },\n // 数据库管理器 - 使用 useClass,依赖注入连接服务和配置服务\n {\n provide: DrizzleDatabaseManager,\n useClass: DrizzleDatabaseManager,\n },\n // 数据库服务 - 使用 useClass,依赖注入管理器\n {\n provide: DataPaasDatabaseService,\n useClass: DataPaasDatabaseService,\n },\n {\n provide: SqlExecutionContextMiddleware,\n useClass: SqlExecutionContextMiddleware,\n },\n // Drizzle 数据库实例 - 使用 useFactory 获取管理器中的数据库实例\n {\n provide: DRIZZLE_DATABASE,\n useFactory: async (manager: DrizzleDatabaseManager) => {\n await manager.initialize();\n return manager.getDatabase();\n },\n inject: [DrizzleDatabaseManager],\n },\n ];\n\n return {\n module: DataPaasModule,\n providers,\n exports: [\n DrizzleDatabaseManager,\n DataPaasDatabaseService,\n SqlExecutionContextMiddleware,\n DRIZZLE_DATABASE,\n DATAPAAS_CONFIG,\n ],\n global: true,\n };\n }\n\n /**\n * 注册数据平台模块(异步方式)\n * 支持从 ConfigModule 等异步源获取配置\n * @param options 异步配置选项\n * @returns 动态模块\n * @example\n * ```typescript\n * DataPaasModule.forRootAsync({\n * imports: [ConfigModule],\n * useFactory: async (configService: ConfigService) => ({\n * connectionString: configService.get('DATABASE_URL'),\n * }),\n * inject: [ConfigService],\n * })\n * ```\n */\n static forRootAsync(options: DataPaasModuleAsyncOptions): DynamicModule {\n const asyncProviders = this.createAsyncProviders(options);\n\n const providers: Provider[] = [\n ...asyncProviders,\n // 数据库管理器 - 使用 useClass,依赖注入连接服务和配置服务\n {\n provide: DrizzleDatabaseManager,\n useClass: DrizzleDatabaseManager,\n },\n // 数据库服务 - 使用 useClass,依赖注入管理器\n {\n provide: DataPaasDatabaseService,\n useClass: DataPaasDatabaseService,\n },\n {\n provide: SqlExecutionContextMiddleware,\n useClass: SqlExecutionContextMiddleware,\n },\n // Drizzle 数据库实例 - 使用 useFactory 获取管理器中的数据库实例\n {\n provide: DRIZZLE_DATABASE,\n useFactory: async (manager: DrizzleDatabaseManager) => {\n await manager.initialize();\n return manager.getDatabase();\n },\n inject: [DrizzleDatabaseManager],\n },\n ];\n\n return {\n module: DataPaasModule,\n imports: options.imports || [],\n providers,\n exports: [\n DrizzleDatabaseManager,\n DataPaasDatabaseService,\n SqlExecutionContextMiddleware,\n DRIZZLE_DATABASE,\n DATAPAAS_CONFIG,\n ],\n global: true,\n };\n }\n\n /**\n * 创建异步配置 providers\n */\n private static createAsyncProviders(\n options: DataPaasModuleAsyncOptions\n ): Provider[] {\n if (options.useFactory) {\n return [this.createAsyncConfigProvider(options)];\n }\n\n throw new Error('DataPaasModule.forRootAsync 需要指定 useFactory');\n }\n\n /**\n * 创建异步配置 provider\n */\n private static createAsyncConfigProvider(\n options: DataPaasModuleAsyncOptions\n ): Provider {\n if (options.useFactory) {\n return {\n provide: DATAPAAS_CONFIG,\n useFactory: async (...args: unknown[]) => {\n const config = await options.useFactory!(...args);\n return this.normalizeConfig(config);\n },\n inject: options.inject || [],\n };\n }\n\n throw new Error('Invalid async options');\n }\n\n /**\n * 标准化配置,设置默认值\n */\n private static normalizeConfig(config: DataPaasConfig): DataPaasConfig {\n let roleSchema = '';\n let sslModeRequired = false;\n if (config.connectionString) {\n try {\n const url = new URL(config.connectionString);\n roleSchema = url.searchParams.get(\n 'schema'\n ) as string;\n sslModeRequired = url.searchParams.get('sslmode') === \"require\";\n } catch (err) {\n roleSchema = '';\n }\n }\n return {\n connectionString: config.connectionString,\n schema: config.schema,\n logger: config.logger || false,\n timeout: config.timeout || 10000,\n maxConnections: config.maxConnections || 1,\n idleTimeout: config.idleTimeout || 20,\n connectionTimeout: config.connectionTimeout || 10,\n ssl: config.ssl || (sslModeRequired ? 'require' : false),\n autoContext: config.autoContext == null ? true : !!config.autoContext,\n roleSchema,\n };\n }\n}\n","import { Injectable, OnModuleDestroy } from '@nestjs/common';\nimport { type PostgresJsDatabase } from 'drizzle-orm/postgres-js';\nimport { DrizzleDatabaseManager } from './drizzle-manager';\nimport { DatabaseConnectionInfo } from '../types';\n\n@Injectable()\nexport class DataPaasDatabaseService implements OnModuleDestroy {\n constructor(\n private readonly databaseManager: DrizzleDatabaseManager,\n ) {}\n\n /**\n * 获取 Drizzle 数据库实例\n * @returns Drizzle 数据库实例\n */\n getDatabase(): PostgresJsDatabase {\n return this.databaseManager.getDatabase();\n }\n\n /**\n * 获取数据库管理器\n * @returns 数据库管理器实例\n */\n getDatabaseManager(): DrizzleDatabaseManager {\n return this.databaseManager;\n }\n\n\n /**\n * 测试数据库连接\n * @returns 连接是否正常\n */\n async testConnection(): Promise<boolean> {\n return this.databaseManager.testConnection();\n }\n\n /**\n * 重新连接数据库\n * @param forceRefresh 是否强制刷新连接信息\n * @returns 新的数据库实例\n */\n async reconnect(forceRefresh: boolean = false): Promise<PostgresJsDatabase> {\n return this.databaseManager.reconnect(forceRefresh);\n }\n\n /**\n * 获取当前连接信息\n * @returns 当前连接信息\n */\n getConnectionInfo(): DatabaseConnectionInfo | null {\n return this.databaseManager.getConnectionInfo();\n }\n\n /**\n * 检查连接状态\n * @returns 是否已连接\n */\n isConnected(): boolean {\n return this.databaseManager.isDatabaseConnected();\n }\n\n /**\n * 开始事务\n * @param callback 事务回调函数\n * @returns 事务结果\n */\n async transaction<T>(callback: (tx: PostgresJsDatabase) => Promise<T>): Promise<T> {\n return this.databaseManager.transaction(callback);\n }\n\n /**\n * 获取连接池状态\n * @returns 连接池状态信息\n */\n getConnectionPoolStatus(): { isConnected: boolean; connectionInfo: DatabaseConnectionInfo | null } {\n return this.databaseManager.getConnectionPoolStatus();\n }\n\n\n /**\n * 模块销毁时断开数据库连接\n */\n async onModuleDestroy(): Promise<void> {\n await this.databaseManager.disconnect();\n }\n}\n","import { Injectable, NestMiddleware, Inject } from '@nestjs/common';\nimport { Request, Response, NextFunction } from 'express';\nimport * as session from 'drizzle-orm/postgres-js';\nimport { DATAPAAS_CONFIG } from './const';\nimport { type DataPaasConfig } from '../types';\n\ninterface UserContext {\n userId?: string;\n tenantId?: number;\n appId?: string;\n // 用户角色(如果有)\n userRoles?: string[];\n // 是否为系统账号\n isSystemAccount: boolean;\n // 用户类型\n userType?: string;\n}\n\n@Injectable()\nexport class SqlExecutionContextMiddleware implements NestMiddleware {\n constructor(\n @Inject(DATAPAAS_CONFIG)\n private readonly config: DataPaasConfig,\n ) {}\n\n use(req: Request, _res: Response, next: NextFunction) {\n const roleSchema = this.config.roleSchema ?? '';\n const userContext =\n (req as unknown as { userContext: UserContext }).userContext || {};\n const roles = (userContext.userRoles || []).join(',');\n const userId = userContext.userId;\n const isSystemAccount = userContext.isSystemAccount;\n const userType = userContext.userType;\n const sqls = [\n // 设置用户 ID, 匿名用户时设置为空字符串\n userId\n ? `SET LOCAL app.user_id = '${userId}'`\n : `SET LOCAL app.user_id = ''`,\n // 系统用户设置为service_role, 登录用户设置为 authenticated_xxx 角色,匿名用户设置为 anon_xxx 角色\n isSystemAccount ? `SET LOCAL ROLE 'service_role_${roleSchema}'` : (\n userId\n ? `SET LOCAL ROLE 'authenticated_${roleSchema}'`\n : `SET LOCAL ROLE 'anon_${roleSchema}'`),\n // 自定义角色\n roles && `SET LOCAL app.role_ids = '${roles}'`,\n // 用户类型\n userType\n ? `SET LOCAL app.user_type = '${userType}'`\n : `SET LOCAL app.user_type = ''`,\n ]\n .filter(Boolean)\n .join(';');\n\n // 需要确认角色设置是否对后续 SQL 执行有影响,预期是只影响当前会话\n session.runWithAuthContext({ preSql: sqls }, () => {\n next();\n });\n }\n}\n","import { type PostgresJsDatabase } from 'drizzle-orm/postgres-js';\nimport { sql } from 'drizzle-orm';\n\nimport { DataPaasDatabaseService } from './database.service';\n\n/**\n * 数据库工具函数集合\n */\nexport class DatabaseUtils {\n /**\n * 安全执行数据库操作\n * @param databaseService 数据库服务实例\n * @param operation 数据库操作函数\n * @param fallback 失败时的回退值\n * @returns 操作结果或回退值\n */\n static async safeExecute<T>(\n databaseService: DataPaasDatabaseService,\n operation: (db: PostgresJsDatabase) => Promise<T>,\n fallback?: T\n ): Promise<T | undefined> {\n try {\n if (!databaseService.isConnected()) {\n throw new Error('Database not connected');\n }\n \n const db = databaseService.getDatabase();\n return await operation(db);\n } catch (error) {\n console.error('Database operation failed:', error);\n return fallback;\n }\n }\n\n /**\n * 批量执行数据库操作\n * @param databaseService 数据库服务实例\n * @param operations 操作数组\n * @param batchSize 批处理大小\n * @returns 所有操作的结果\n */\n static async batchExecute<T>(\n databaseService: DataPaasDatabaseService,\n operations: Array<(db: PostgresJsDatabase) => Promise<T>>,\n batchSize: number = 10\n ): Promise<T[]> {\n const results: T[] = [];\n const db = databaseService.getDatabase();\n\n for (let i = 0; i < operations.length; i += batchSize) {\n const batch = operations.slice(i, i + batchSize);\n const batchResults = await Promise.all(\n batch.map(operation => operation(db))\n );\n results.push(...batchResults);\n }\n\n return results;\n }\n\n /**\n * 执行带重试的数据库操作\n * @param databaseService 数据库服务实例\n * @param operation 数据库操作函数\n * @param maxRetries 最大重试次数\n * @param retryDelay 重试延迟(毫秒)\n * @returns 操作结果\n */\n static async executeWithRetry<T>(\n databaseService: DataPaasDatabaseService,\n operation: (db: PostgresJsDatabase) => Promise<T>,\n maxRetries: number = 3,\n retryDelay: number = 1000\n ): Promise<T> {\n let lastError: Error;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n const db = databaseService.getDatabase();\n return await operation(db);\n } catch (error) {\n lastError = error as Error;\n \n if (attempt === maxRetries) {\n break;\n }\n\n console.warn(`Database operation failed (attempt ${attempt + 1}/${maxRetries + 1}):`, error);\n \n // 等待后重试\n await new Promise(resolve => setTimeout(resolve, retryDelay * (attempt + 1)));\n }\n }\n\n throw lastError!;\n }\n\n /**\n * 检查表是否存在\n * @param databaseService 数据库服务实例\n * @param tableName 表名\n * @returns 表是否存在\n */\n static async tableExists(\n db: PostgresJsDatabase,\n tableName: string\n ): Promise<boolean> {\n try {\n const result = await db.execute(\n sql`SELECT EXISTS (\n SELECT FROM information_schema.tables \n WHERE table_schema = 'public' \n AND table_name = ${tableName}\n )`\n );\n \n return result[0]?.exists as boolean || false;\n } catch (error) {\n console.error('Failed to check table existence:', error);\n return false;\n }\n }\n\n /**\n * 获取表结构信息\n * @param databaseService 数据库服务实例\n * @param tableName 表名\n * @returns 表结构信息\n */\n static async getTableStructure(\n db: PostgresJsDatabase,\n tableName: string\n ): Promise<any[]> {\n try {\n const result = await db.execute(\n sql`SELECT \n column_name,\n data_type,\n is_nullable,\n column_default,\n character_maximum_length\n FROM information_schema.columns \n WHERE table_schema = 'public' \n AND table_name = ${tableName}\n ORDER BY ordinal_position`,\n );\n \n return result;\n } catch (error) {\n console.error('Failed to get table structure:', error);\n return [];\n }\n }\n\n /**\n * 获取数据库版本信息\n * @param databaseService 数据库服务实例\n * @returns 数据库版本\n */\n static async getDatabaseVersion(\n db: PostgresJsDatabase\n ): Promise<string> {\n try {\n const result = await db.execute(sql`SELECT version()`);\n return result[0]?.version as string || 'Unknown';\n } catch (error) {\n console.error('Failed to get database version:', error);\n return 'Unknown';\n }\n }\n\n /**\n * 获取连接统计信息\n * @param databaseService 数据库服务实例\n * @returns 连接统计信息\n */\n static async getConnectionStats(\n db: PostgresJsDatabase\n ): Promise<any> {\n try {\n const result = await db.execute(sql`\n SELECT \n count(*) as total_connections,\n count(*) FILTER (WHERE state = 'active') as active_connections,\n count(*) FILTER (WHERE state = 'idle') as idle_connections\n FROM pg_stat_activity \n WHERE datname = current_database()\n `);\n \n return result[0] || {};\n } catch (error) {\n console.error('Failed to get connection stats:', error);\n return {};\n }\n }\n\n /**\n * 健康检查\n * @param databaseService 数据库服务实例\n * @returns 健康状态\n */\n static async healthCheck(\n databaseService: DataPaasDatabaseService\n ): Promise<{\n isHealthy: boolean;\n isConnected: boolean;\n version?: string;\n connectionInfo?: any;\n error?: string;\n }> {\n try {\n const isConnected = databaseService.isConnected();\n const connectionInfo = databaseService.getConnectionInfo();\n\n const db = databaseService.getDatabase();\n if (!isConnected) {\n return {\n isHealthy: false,\n isConnected: false,\n error: 'Database not connected'\n };\n }\n\n const version = await this.getDatabaseVersion(db);\n \n return {\n isHealthy: true,\n isConnected: true,\n version,\n connectionInfo\n };\n } catch (error) {\n return {\n isHealthy: false,\n isConnected: false,\n error: error instanceof Error ? error.message : 'Unknown error'\n };\n }\n }\n}\n"],"mappings":"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","names":["DRIZZLE_DATABASE","DATAPAAS_CONFIG","parseConnectionInfo","connectionString","config","maxConnections","idleTimeout","connectionTimeout","ssl","logger","parsedConfigFromUrl","URL","temp","searchParams","delete","toString","error","Error","username","password","hostname","port","pathname","connectionConfig","decodeURIComponent","host","parseInt","max","idle_timeout","connect_timeout","onnotice","console","log","undefined","DrizzleDatabaseManager","db","currentConnectionInfo","isConnected","skipInitDbConnection","config","process","env","DEPRECATED_SKIP_INIT_DB_CONNECTION","onModuleInit","initialize","onModuleDestroy","disconnect","name","connectionString","connectionConfig","parseConnectionInfo","sql","postgres","drizzle","schema","logger","ssl","connectionTimeout","connect_timeout","idleTimeout","idle_timeout","maxConnections","max","error","Error","message","getDatabase","testConnection","execute","console","reconnect","_forceRefresh","getConnectionInfo","isDatabaseConnected","transaction","callback","getConnectionPoolStatus","connectionInfo","import_common","import_common","DataPaasDatabaseService","databaseManager","getDatabase","getDatabaseManager","testConnection","reconnect","forceRefresh","getConnectionInfo","isConnected","isDatabaseConnected","transaction","callback","getConnectionPoolStatus","onModuleDestroy","disconnect","import_common","SqlExecutionContextMiddleware","config","use","req","_res","next","roleSchema","userContext","roles","userRoles","join","userId","isSystemAccount","userType","sqls","filter","Boolean","session","runWithAuthContext","preSql","verifyDrizzlePatched","postgres","require","ok","getAuthContextStore","runWithAuthContext","Error","err","reason","message","String","DataPaasModule","configure","_consumer","forRoot","options","roleSchema","sslModeRequired","connectionString","url","URL","searchParams","get","config","schema","logger","timeout","maxConnections","idleTimeout","connectionTimeout","ssl","autoContext","providers","provide","DATAPAAS_CONFIG","useValue","DrizzleDatabaseManager","useClass","DataPaasDatabaseService","SqlExecutionContextMiddleware","DRIZZLE_DATABASE","useFactory","manager","initialize","getDatabase","inject","module","exports","global","forRootAsync","asyncProviders","createAsyncProviders","imports","createAsyncConfigProvider","args","normalizeConfig","import_drizzle_orm","DatabaseUtils","safeExecute","databaseService","operation","fallback","isConnected","Error","db","getDatabase","error","console","batchExecute","operations","batchSize","results","i","length","batch","slice","batchResults","Promise","all","map","push","executeWithRetry","maxRetries","retryDelay","lastError","attempt","warn","resolve","setTimeout","tableExists","tableName","result","execute","sql","exists","getTableStructure","getDatabaseVersion","version","getConnectionStats","healthCheck","connectionInfo","getConnectionInfo","isHealthy","message"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/database/drizzle-manager.ts","../src/database/const.ts","../src/utils.ts","../src/database/postgres-proxy.ts","../src/database/database.module.ts","../src/database/database.service.ts","../src/database/sql-exection-context.middleware.ts","../src/database/database-utils.ts"],"sourcesContent":["// 导出所有公共API\n\nexport * from './database';\nexport * from './types';\n","import { Injectable, OnModuleInit, OnModuleDestroy, Inject } from '@nestjs/common';\nimport { drizzle, type PostgresJsDatabase } from 'drizzle-orm/postgres-js';\nimport { sql } from 'drizzle-orm';\nimport postgres from 'postgres';\nimport { DATAPAAS_CONFIG, DATAPAAS_LOGGER_SERVICE } from './const';\nimport { Observable } from '@lark-apaas/nestjs-observable';\nimport { RequestContextService } from '@lark-apaas/nestjs-common';\n\nimport { type DataPaasConfig, type DatabaseConnectionInfo } from '../types';\nimport { parseConnectionInfo } from '../utils';\nimport { genPostgresProxy } from \"./postgres-proxy\";\n@Injectable()\nexport class DrizzleDatabaseManager implements OnModuleInit, OnModuleDestroy {\n private db: PostgresJsDatabase | null = null;\n private currentConnectionInfo: DatabaseConnectionInfo | null = null;\n private isConnected: boolean = false;\n private skipInitDbConnection: boolean = false;\n constructor(\n @Inject(DATAPAAS_CONFIG)\n private readonly config: DataPaasConfig,\n @Inject(DATAPAAS_LOGGER_SERVICE)\n private readonly observable: Observable,\n private readonly requestContext: RequestContextService,\n ) { \n this.skipInitDbConnection = !!process.env.DEPRECATED_SKIP_INIT_DB_CONNECTION;\n }\n\n async onModuleInit() {\n await this.initialize();\n }\n\n async onModuleDestroy() {\n await this.disconnect();\n }\n\n /**\n * 初始化数据库连接\n * @returns Drizzle 数据库实例\n */\n async initialize(): Promise<PostgresJsDatabase> {\n if (this.skipInitDbConnection) {\n this.isConnected = true;\n this.db = {name: 'skipInitDbConnection'} as unknown as PostgresJsDatabase;\n return this.db;\n }\n try {\n const { connectionString, connectionConfig } = parseConnectionInfo(this.config.connectionString, this.config);\n const baseSql = postgres(connectionString, connectionConfig);\n const sqlProxy = genPostgresProxy(baseSql, this.observable, this.requestContext);\n // 创建 Drizzle 实例\n this.db = drizzle(sqlProxy, { schema: this.config.schema, logger: false });\n this.currentConnectionInfo = {\n connectionString,\n connectionConfig: {\n ssl: connectionConfig.ssl,\n connectionTimeout: connectionConfig.connect_timeout,\n idleTimeout: connectionConfig.idle_timeout,\n maxConnections: connectionConfig.max,\n },\n };\n this.isConnected = true;\n return this.db;\n } catch (error) {\n this.isConnected = false;\n throw new Error(`Failed to initialize database connection: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n }\n\n /**\n * 获取数据库实例\n * @returns Drizzle 数据库实例\n */\n getDatabase(): PostgresJsDatabase {\n if (!this.db || !this.isConnected) {\n throw new Error('Database not initialized. Call initialize() first.');\n }\n return this.db;\n }\n\n /**\n * 测试数据库连接\n * @returns 连接是否正常\n */\n async testConnection(): Promise<boolean> {\n if (!this.db) {\n return false;\n }\n\n try {\n await this.db.execute(sql`SELECT 1`);\n return true;\n } catch (error) {\n console.error('Database connection test failed:', error);\n this.isConnected = false;\n return false;\n }\n }\n\n /**\n * 重新连接数据库\n * @param forceRefresh 是否强制刷新连接信息\n * @returns 新的数据库实例\n */\n async reconnect(_forceRefresh: boolean = false): Promise<PostgresJsDatabase> {\n await this.disconnect();\n return this.initialize();\n }\n\n /**\n * 断开数据库连接\n */\n async disconnect(): Promise<void> {\n if (this.db) {\n try {\n // postgres-js 会自动处理连接关闭\n this.db = null;\n this.isConnected = false;\n this.currentConnectionInfo = null;\n } catch (error) {\n console.error('Error disconnecting from database:', error);\n }\n }\n }\n\n /**\n * 获取当前连接信息\n * @returns 当前连接信息\n */\n getConnectionInfo(): DatabaseConnectionInfo | null {\n return this.currentConnectionInfo;\n }\n\n /**\n * 检查连接状态\n * @returns 是否已连接\n */\n isDatabaseConnected(): boolean {\n return this.isConnected;\n }\n\n\n /**\n * 开始事务\n * @param callback 事务回调函数\n * @returns 事务结果\n */\n async transaction<T>(callback: (tx: PostgresJsDatabase) => Promise<T>): Promise<T> {\n const db = this.getDatabase();\n return db.transaction(callback);\n }\n\n /**\n * 获取连接池状态\n * @returns 连接池状态信息\n */\n getConnectionPoolStatus(): { isConnected: boolean; connectionInfo: DatabaseConnectionInfo | null } {\n return {\n isConnected: this.isConnected,\n connectionInfo: this.currentConnectionInfo,\n };\n }\n}","export const DRIZZLE_DATABASE = 'DRIZZLE_DATABASE';\nexport const DATAPAAS_CONFIG = 'DATAPAAS_CONFIG';\nexport const DATAPAAS_LOGGER_SERVICE = Symbol('DATAPAAS_LOGGER_SERVICE');","import type postgres from 'postgres';\nimport { type Logger as DrizzleLogger } from 'drizzle-orm';\nimport { PostgresOptions } from './types';\n\ninterface ConnectionConfig {\n maxConnections?: number;\n idleTimeout?: number;\n connectionTimeout?: number;\n ssl?: PostgresOptions['ssl'];\n logger?: boolean | DrizzleLogger;\n}\nexport function parseConnectionInfo(connectionString: string, config?: ConnectionConfig) {\n const { maxConnections, idleTimeout, connectionTimeout, ssl, logger } = config || {};\n // 创建 postgres 连接\n let parsedConfigFromUrl: URL;\n try {\n parsedConfigFromUrl = new URL(connectionString);\n const temp = new URL(connectionString);\n temp.searchParams.delete('schema'); // 移除schema参数,避免 postgres 解析错误\n connectionString = temp.toString();\n } catch (error) {\n throw new Error('Failed to parse connection info');\n }\n const { username, password, hostname, port, pathname } = parsedConfigFromUrl;\n const connectionConfig = {\n username: decodeURIComponent(username),\n password: decodeURIComponent(password),\n host: [hostname] as unknown as string,\n port: [parseInt(port) || 5432] as unknown as number,\n pathname: decodeURIComponent(pathname),\n max: maxConnections || 1,\n idle_timeout: idleTimeout || 20,\n connect_timeout: connectionTimeout || 10,\n ssl,\n onnotice: logger ? console.log : undefined,\n }\n return { connectionString, connectionConfig };\n}","import type postgres from 'postgres';\nimport { Logger } from '@nestjs/common';\nimport { Span, Observable } from '@lark-apaas/nestjs-observable';\nimport { RequestContextService } from '@lark-apaas/nestjs-common';\n\nconst nestLogger = new Logger('Database');\n\n/**\n * 包装 postgres 实例以记录 SQL 和结果\n */\nexport function genPostgresProxy(sql: postgres.Sql, observable: Observable, requestContext: RequestContextService): postgres.Sql {\n const wrapQuery = <T extends readonly (postgres.Row | undefined)[]>(query: postgres.PendingQuery<T>): postgres.PendingQuery<T> => {\n if (query && typeof query.then === 'function') {\n return new Proxy(query, {\n get(target, prop, receiver) {\n if (prop === 'then') {\n return async (onfulfilled?: (value: postgres.RowList<T>) => unknown, onrejected?: (reason: unknown) => unknown) => {\n const sqlStr = (query as unknown as Record<string, unknown>).strings instanceof Array ? (query as unknown as { strings: string[] }).strings[0] : '';\n const span = observable.startTrace(sqlStr, requestContext?.getContext()?.requestRootSpan as Span);\n\n span.setAttribute(\"module\", \"data\");\n span.setAttribute(\"source_type\", \"platform\");\n\n const start = Date.now();\n try {\n const result = await target;\n const isSetRoleSql = result?.command === 'SET';\n\n // rls SET ROLE 不上报日志\n if (!isSetRoleSql) {\n const duration = Date.now() - start;\n\n const parsedParams = JSON.stringify({ \n operation: result?.command,\n sql: result?.statement?.string,\n duration_ms: duration,\n result_count: result.length ?? 0,\n error_message: ''\n });\n\n nestLogger.log(parsedParams, {\n source_type: 'platform',\n paas_attributes_module: 'data'\n });\n } else {\n observable.dropTrace(span);\n }\n\n span.end();\n return onfulfilled ? onfulfilled(result) : result;\n } catch (error) {\n const duration = Date.now() - start;\n const sqlStr = (query as unknown as Record<string, unknown>).strings instanceof Array ? (query as unknown as { strings: string[] }).strings[0] : '';\n const parsedParams = JSON.stringify({ \n operation: '',\n sql: sqlStr,\n duration_ms: duration,\n result_count: 0,\n error_message: error instanceof Error ? error.message : String(error)\n });\n nestLogger.log(parsedParams, {\n source_type: 'platform',\n paas_attributes_module: 'data'\n });\n\n span.end();\n return onrejected ? onrejected(error) : Promise.reject(error);\n }\n };\n }\n const value = Reflect.get(target, prop, receiver);\n return typeof value === 'function' ? value.bind(receiver) : value;\n },\n }) as postgres.PendingQuery<T>;\n }\n return query;\n };\n\n return new Proxy(sql, {\n apply(target, thisArg, argArray) {\n const query = Reflect.apply(target, thisArg, argArray);\n return wrapQuery(query);\n },\n get(target, prop, receiver) {\n const value = Reflect.get(target, prop, receiver);\n if (prop === 'begin' && typeof value === 'function') {\n return <T>(arg: string | ((tx: postgres.TransactionSql) => T | Promise<T>), cb?: (tx: postgres.TransactionSql) => T | Promise<T>) => {\n if (typeof arg === 'function') {\n return value.call(target, (tx: postgres.TransactionSql) => arg(genPostgresProxy(tx as unknown as postgres.Sql, observable, requestContext) as unknown as postgres.TransactionSql));\n }\n if (typeof cb === 'function') {\n return value.call(target, arg, (tx: postgres.TransactionSql) => cb(genPostgresProxy(tx as unknown as postgres.Sql, observable, requestContext) as unknown as postgres.TransactionSql));\n }\n return value.call(target, arg);\n };\n }\n if (prop === 'unsafe' && typeof value === 'function') {\n return <T extends readonly (postgres.Row | undefined)[] = postgres.Row[]>(queryStr: string, args?: unknown[], options?: postgres.UnsafeQueryOptions): postgres.PendingQuery<T> => {\n const query = value.call(target, queryStr, args, options) as postgres.PendingQuery<T>;\n return wrapQuery(query);\n };\n }\n return typeof value === 'function' ? value.bind(receiver) : value;\n },\n }) as postgres.Sql;\n}","import {\n Module,\n DynamicModule,\n Provider,\n MiddlewareConsumer,\n InjectionToken,\n ModuleMetadata,\n} from '@nestjs/common';\nimport { DrizzleDatabaseManager } from './drizzle-manager';\nimport { DataPaasDatabaseService } from './database.service';\nimport { SqlExecutionContextMiddleware } from './sql-exection-context.middleware';\nimport { type DataPaasConfig } from '@/types';\nimport { DATAPAAS_CONFIG, DRIZZLE_DATABASE, DATAPAAS_LOGGER_SERVICE } from './const';\nexport { type PostgresJsDatabase } from 'drizzle-orm/postgres-js';\nimport { RequestContextService, OBSERVABLE_SERVICE, ObservableService } from '@lark-apaas/nestjs-common';\nimport { Observable } from '@lark-apaas/nestjs-observable';\n\nexport interface DataPaasModuleOptions extends DataPaasConfig {}\n\n/**\n * 异步配置选项\n */\nexport interface DataPaasModuleAsyncOptions {\n /**\n * 需要导入的模块(例如 ConfigModule)\n */\n imports?: ModuleMetadata['imports'];\n /**\n * 使用工厂函数创建配置\n */\n useFactory?: (...args: unknown[]) => Promise<DataPaasConfig> | DataPaasConfig;\n /**\n * 工厂函数需要注入的依赖\n */\n inject?: InjectionToken[];\n}\n\nfunction verifyDrizzlePatched(): void {\n try {\n // 直接加载被 patch 的 CJS 模块并检查导出是否存在\n // 注意:此路径与补丁文件一致:drizzle-orm/postgres-js/session.cjs\n // 若未来包结构变化,请同步更新补丁与此校验\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const postgres = require('drizzle-orm/postgres-js');\n const ok =\n postgres &&\n typeof postgres.getAuthContextStore === 'function' &&\n typeof postgres.runWithAuthContext === 'function';\n if (!ok) {\n throw new Error(\n 'drizzle-orm 未检测到补丁导出:getAuthContextStore/runWithAuthContext',\n );\n }\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err);\n throw new Error(`drizzle-orm 补丁未生效或版本不匹配:${reason}`);\n }\n}\n\n// 在模块初始化阶段进行一次 drizzle-orm 补丁自检\nverifyDrizzlePatched();\n\n@Module({\n providers: [{\n provide: DATAPAAS_LOGGER_SERVICE,\n useFactory: (observable: ObservableService | null, rtx: RequestContextService) => {\n return observable ?? new Observable(rtx);\n },\n inject: [{\n token: OBSERVABLE_SERVICE,\n optional: true,\n }, RequestContextService],\n }],\n})\nexport class DataPaasModule {\n configure(_consumer: MiddlewareConsumer) {}\n /**\n * 注册数据平台模块(同步方式)\n * @param options 模块配置选项\n * @returns 动态模块\n */\n static forRoot(options: DataPaasConfig): DynamicModule {\n let roleSchema = '';\n let sslModeRequired = false;\n if (options.connectionString) {\n try {\n const url = new URL(options.connectionString);\n\n roleSchema = url.searchParams.get(\n 'schema'\n ) as string;\n sslModeRequired = url.searchParams.get('sslmode') === \"require\";\n } catch (err) {\n roleSchema = '';\n }\n }\n const config: DataPaasConfig = {\n connectionString: options.connectionString,\n schema: options.schema,\n logger: options.logger || false,\n timeout: options.timeout || 10000,\n maxConnections: options.maxConnections || 1,\n idleTimeout: options.idleTimeout || 20,\n connectionTimeout: options.connectionTimeout || 10,\n ssl: options.ssl || (sslModeRequired ? 'require' : false),\n autoContext: options.autoContext == null ? true : !!options.autoContext,\n roleSchema,\n };\n\n const providers: Provider[] = [\n // 配置提供者 - 使用 useValue\n {\n provide: DATAPAAS_CONFIG,\n useValue: config,\n },\n // 数据库管理器 - 使用 useClass,依赖注入连接服务和配置服务\n {\n provide: DrizzleDatabaseManager,\n useClass: DrizzleDatabaseManager,\n },\n // 数据库服务 - 使用 useClass,依赖注入管理器\n {\n provide: DataPaasDatabaseService,\n useClass: DataPaasDatabaseService,\n },\n {\n provide: SqlExecutionContextMiddleware,\n useClass: SqlExecutionContextMiddleware,\n },\n // Drizzle 数据库实例 - 使用 useFactory 获取管理器中的数据库实例\n {\n provide: DRIZZLE_DATABASE,\n useFactory: async (manager: DrizzleDatabaseManager) => {\n await manager.initialize();\n return manager.getDatabase();\n },\n inject: [DrizzleDatabaseManager],\n },\n ];\n\n return {\n module: DataPaasModule,\n providers,\n exports: [\n DrizzleDatabaseManager,\n DataPaasDatabaseService,\n SqlExecutionContextMiddleware,\n DRIZZLE_DATABASE,\n DATAPAAS_CONFIG,\n ],\n global: true,\n };\n }\n\n /**\n * 注册数据平台模块(异步方式)\n * 支持从 ConfigModule 等异步源获取配置\n * @param options 异步配置选项\n * @returns 动态模块\n * @example\n * ```typescript\n * DataPaasModule.forRootAsync({\n * imports: [ConfigModule],\n * useFactory: async (configService: ConfigService) => ({\n * connectionString: configService.get('DATABASE_URL'),\n * }),\n * inject: [ConfigService],\n * })\n * ```\n */\n static forRootAsync(options: DataPaasModuleAsyncOptions): DynamicModule {\n const asyncProviders = this.createAsyncProviders(options);\n\n const providers: Provider[] = [\n ...asyncProviders,\n // 数据库管理器 - 使用 useClass,依赖注入连接服务和配置服务\n {\n provide: DrizzleDatabaseManager,\n useClass: DrizzleDatabaseManager,\n },\n // 数据库服务 - 使用 useClass,依赖注入管理器\n {\n provide: DataPaasDatabaseService,\n useClass: DataPaasDatabaseService,\n },\n {\n provide: SqlExecutionContextMiddleware,\n useClass: SqlExecutionContextMiddleware,\n },\n // Drizzle 数据库实例 - 使用 useFactory 获取管理器中的数据库实例\n {\n provide: DRIZZLE_DATABASE,\n useFactory: async (manager: DrizzleDatabaseManager) => {\n await manager.initialize();\n return manager.getDatabase();\n },\n inject: [DrizzleDatabaseManager],\n },\n ];\n\n return {\n module: DataPaasModule,\n imports: options.imports || [],\n providers,\n exports: [\n DrizzleDatabaseManager,\n DataPaasDatabaseService,\n SqlExecutionContextMiddleware,\n DRIZZLE_DATABASE,\n DATAPAAS_CONFIG,\n ],\n global: true,\n };\n }\n\n /**\n * 创建异步配置 providers\n */\n private static createAsyncProviders(\n options: DataPaasModuleAsyncOptions\n ): Provider[] {\n if (options.useFactory) {\n return [this.createAsyncConfigProvider(options)];\n }\n\n throw new Error('DataPaasModule.forRootAsync 需要指定 useFactory');\n }\n\n /**\n * 创建异步配置 provider\n */\n private static createAsyncConfigProvider(\n options: DataPaasModuleAsyncOptions\n ): Provider {\n if (options.useFactory) {\n return {\n provide: DATAPAAS_CONFIG,\n useFactory: async (...args: unknown[]) => {\n const config = await options.useFactory!(...args);\n return this.normalizeConfig(config);\n },\n inject: options.inject || [],\n };\n }\n\n throw new Error('Invalid async options');\n }\n\n /**\n * 标准化配置,设置默认值\n */\n private static normalizeConfig(config: DataPaasConfig): DataPaasConfig {\n let roleSchema = '';\n let sslModeRequired = false;\n if (config.connectionString) {\n try {\n const url = new URL(config.connectionString);\n roleSchema = url.searchParams.get(\n 'schema'\n ) as string;\n sslModeRequired = url.searchParams.get('sslmode') === \"require\";\n } catch (err) {\n roleSchema = '';\n }\n }\n return {\n connectionString: config.connectionString,\n schema: config.schema,\n logger: config.logger || false,\n timeout: config.timeout || 10000,\n maxConnections: config.maxConnections || 1,\n idleTimeout: config.idleTimeout || 20,\n connectionTimeout: config.connectionTimeout || 10,\n ssl: config.ssl || (sslModeRequired ? 'require' : false),\n autoContext: config.autoContext == null ? true : !!config.autoContext,\n roleSchema,\n };\n }\n}\n","import { Injectable, OnModuleDestroy } from '@nestjs/common';\nimport { type PostgresJsDatabase } from 'drizzle-orm/postgres-js';\nimport { DrizzleDatabaseManager } from './drizzle-manager';\nimport { DatabaseConnectionInfo } from '../types';\n\n@Injectable()\nexport class DataPaasDatabaseService implements OnModuleDestroy {\n constructor(\n private readonly databaseManager: DrizzleDatabaseManager,\n ) {}\n\n /**\n * 获取 Drizzle 数据库实例\n * @returns Drizzle 数据库实例\n */\n getDatabase(): PostgresJsDatabase {\n return this.databaseManager.getDatabase();\n }\n\n /**\n * 获取数据库管理器\n * @returns 数据库管理器实例\n */\n getDatabaseManager(): DrizzleDatabaseManager {\n return this.databaseManager;\n }\n\n\n /**\n * 测试数据库连接\n * @returns 连接是否正常\n */\n async testConnection(): Promise<boolean> {\n return this.databaseManager.testConnection();\n }\n\n /**\n * 重新连接数据库\n * @param forceRefresh 是否强制刷新连接信息\n * @returns 新的数据库实例\n */\n async reconnect(forceRefresh: boolean = false): Promise<PostgresJsDatabase> {\n return this.databaseManager.reconnect(forceRefresh);\n }\n\n /**\n * 获取当前连接信息\n * @returns 当前连接信息\n */\n getConnectionInfo(): DatabaseConnectionInfo | null {\n return this.databaseManager.getConnectionInfo();\n }\n\n /**\n * 检查连接状态\n * @returns 是否已连接\n */\n isConnected(): boolean {\n return this.databaseManager.isDatabaseConnected();\n }\n\n /**\n * 开始事务\n * @param callback 事务回调函数\n * @returns 事务结果\n */\n async transaction<T>(callback: (tx: PostgresJsDatabase) => Promise<T>): Promise<T> {\n return this.databaseManager.transaction(callback);\n }\n\n /**\n * 获取连接池状态\n * @returns 连接池状态信息\n */\n getConnectionPoolStatus(): { isConnected: boolean; connectionInfo: DatabaseConnectionInfo | null } {\n return this.databaseManager.getConnectionPoolStatus();\n }\n\n\n /**\n * 模块销毁时断开数据库连接\n */\n async onModuleDestroy(): Promise<void> {\n await this.databaseManager.disconnect();\n }\n}\n","import { Injectable, NestMiddleware, Inject } from '@nestjs/common';\nimport { Request, Response, NextFunction } from 'express';\nimport * as session from 'drizzle-orm/postgres-js';\nimport { DATAPAAS_CONFIG } from './const';\nimport { type DataPaasConfig } from '../types';\n\ninterface UserContext {\n userId?: string;\n tenantId?: number;\n appId?: string;\n // 用户角色(如果有)\n userRoles?: string[];\n // 是否为系统账号\n isSystemAccount: boolean;\n // 用户类型\n userType?: string;\n}\n\n@Injectable()\nexport class SqlExecutionContextMiddleware implements NestMiddleware {\n constructor(\n @Inject(DATAPAAS_CONFIG)\n private readonly config: DataPaasConfig,\n ) {}\n\n use(req: Request, _res: Response, next: NextFunction) {\n const roleSchema = this.config.roleSchema ?? '';\n const userContext =\n (req as unknown as { userContext: UserContext }).userContext || {};\n const roles = (userContext.userRoles || []).join(',');\n const userId = userContext.userId;\n const isSystemAccount = userContext.isSystemAccount;\n const userType = userContext.userType;\n const sqls = [\n // 设置用户 ID, 匿名用户时设置为空字符串\n userId\n ? `SET LOCAL app.user_id = '${userId}'`\n : `SET LOCAL app.user_id = ''`,\n // 系统用户设置为service_role, 登录用户设置为 authenticated_xxx 角色,匿名用户设置为 anon_xxx 角色\n isSystemAccount ? `SET LOCAL ROLE 'service_role_${roleSchema}'` : (\n userId\n ? `SET LOCAL ROLE 'authenticated_${roleSchema}'`\n : `SET LOCAL ROLE 'anon_${roleSchema}'`),\n // 自定义角色\n roles && `SET LOCAL app.role_ids = '${roles}'`,\n // 用户类型\n userType\n ? `SET LOCAL app.user_type = '${userType}'`\n : `SET LOCAL app.user_type = ''`,\n ]\n .filter(Boolean)\n .join(';');\n\n // 需要确认角色设置是否对后续 SQL 执行有影响,预期是只影响当前会话\n session.runWithAuthContext({ preSql: sqls }, () => {\n next();\n });\n }\n}\n","import { type PostgresJsDatabase } from 'drizzle-orm/postgres-js';\nimport { sql } from 'drizzle-orm';\n\nimport { DataPaasDatabaseService } from './database.service';\n\n/**\n * 数据库工具函数集合\n */\nexport class DatabaseUtils {\n /**\n * 安全执行数据库操作\n * @param databaseService 数据库服务实例\n * @param operation 数据库操作函数\n * @param fallback 失败时的回退值\n * @returns 操作结果或回退值\n */\n static async safeExecute<T>(\n databaseService: DataPaasDatabaseService,\n operation: (db: PostgresJsDatabase) => Promise<T>,\n fallback?: T\n ): Promise<T | undefined> {\n try {\n if (!databaseService.isConnected()) {\n throw new Error('Database not connected');\n }\n \n const db = databaseService.getDatabase();\n return await operation(db);\n } catch (error) {\n console.error('Database operation failed:', error);\n return fallback;\n }\n }\n\n /**\n * 批量执行数据库操作\n * @param databaseService 数据库服务实例\n * @param operations 操作数组\n * @param batchSize 批处理大小\n * @returns 所有操作的结果\n */\n static async batchExecute<T>(\n databaseService: DataPaasDatabaseService,\n operations: Array<(db: PostgresJsDatabase) => Promise<T>>,\n batchSize: number = 10\n ): Promise<T[]> {\n const results: T[] = [];\n const db = databaseService.getDatabase();\n\n for (let i = 0; i < operations.length; i += batchSize) {\n const batch = operations.slice(i, i + batchSize);\n const batchResults = await Promise.all(\n batch.map(operation => operation(db))\n );\n results.push(...batchResults);\n }\n\n return results;\n }\n\n /**\n * 执行带重试的数据库操作\n * @param databaseService 数据库服务实例\n * @param operation 数据库操作函数\n * @param maxRetries 最大重试次数\n * @param retryDelay 重试延迟(毫秒)\n * @returns 操作结果\n */\n static async executeWithRetry<T>(\n databaseService: DataPaasDatabaseService,\n operation: (db: PostgresJsDatabase) => Promise<T>,\n maxRetries: number = 3,\n retryDelay: number = 1000\n ): Promise<T> {\n let lastError: Error;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n const db = databaseService.getDatabase();\n return await operation(db);\n } catch (error) {\n lastError = error as Error;\n \n if (attempt === maxRetries) {\n break;\n }\n\n console.warn(`Database operation failed (attempt ${attempt + 1}/${maxRetries + 1}):`, error);\n \n // 等待后重试\n await new Promise(resolve => setTimeout(resolve, retryDelay * (attempt + 1)));\n }\n }\n\n throw lastError!;\n }\n\n /**\n * 检查表是否存在\n * @param databaseService 数据库服务实例\n * @param tableName 表名\n * @returns 表是否存在\n */\n static async tableExists(\n db: PostgresJsDatabase,\n tableName: string\n ): Promise<boolean> {\n try {\n const result = await db.execute(\n sql`SELECT EXISTS (\n SELECT FROM information_schema.tables \n WHERE table_schema = 'public' \n AND table_name = ${tableName}\n )`\n );\n \n return result[0]?.exists as boolean || false;\n } catch (error) {\n console.error('Failed to check table existence:', error);\n return false;\n }\n }\n\n /**\n * 获取表结构信息\n * @param databaseService 数据库服务实例\n * @param tableName 表名\n * @returns 表结构信息\n */\n static async getTableStructure(\n db: PostgresJsDatabase,\n tableName: string\n ): Promise<any[]> {\n try {\n const result = await db.execute(\n sql`SELECT \n column_name,\n data_type,\n is_nullable,\n column_default,\n character_maximum_length\n FROM information_schema.columns \n WHERE table_schema = 'public' \n AND table_name = ${tableName}\n ORDER BY ordinal_position`,\n );\n \n return result;\n } catch (error) {\n console.error('Failed to get table structure:', error);\n return [];\n }\n }\n\n /**\n * 获取数据库版本信息\n * @param databaseService 数据库服务实例\n * @returns 数据库版本\n */\n static async getDatabaseVersion(\n db: PostgresJsDatabase\n ): Promise<string> {\n try {\n const result = await db.execute(sql`SELECT version()`);\n return result[0]?.version as string || 'Unknown';\n } catch (error) {\n console.error('Failed to get database version:', error);\n return 'Unknown';\n }\n }\n\n /**\n * 获取连接统计信息\n * @param databaseService 数据库服务实例\n * @returns 连接统计信息\n */\n static async getConnectionStats(\n db: PostgresJsDatabase\n ): Promise<any> {\n try {\n const result = await db.execute(sql`\n SELECT \n count(*) as total_connections,\n count(*) FILTER (WHERE state = 'active') as active_connections,\n count(*) FILTER (WHERE state = 'idle') as idle_connections\n FROM pg_stat_activity \n WHERE datname = current_database()\n `);\n \n return result[0] || {};\n } catch (error) {\n console.error('Failed to get connection stats:', error);\n return {};\n }\n }\n\n /**\n * 健康检查\n * @param databaseService 数据库服务实例\n * @returns 健康状态\n */\n static async healthCheck(\n databaseService: DataPaasDatabaseService\n ): Promise<{\n isHealthy: boolean;\n isConnected: boolean;\n version?: string;\n connectionInfo?: any;\n error?: string;\n }> {\n try {\n const isConnected = databaseService.isConnected();\n const connectionInfo = databaseService.getConnectionInfo();\n\n const db = databaseService.getDatabase();\n if (!isConnected) {\n return {\n isHealthy: false,\n isConnected: false,\n error: 'Database not connected'\n };\n }\n\n const version = await this.getDatabaseVersion(db);\n \n return {\n isHealthy: true,\n isConnected: true,\n version,\n connectionInfo\n };\n } catch (error) {\n return {\n isHealthy: false,\n isConnected: false,\n error: error instanceof Error ? error.message : 'Unknown error'\n };\n }\n }\n}\n"],"mappings":"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","names":["import_common","DRIZZLE_DATABASE","DATAPAAS_CONFIG","DATAPAAS_LOGGER_SERVICE","Symbol","parseConnectionInfo","connectionString","config","maxConnections","idleTimeout","connectionTimeout","ssl","logger","parsedConfigFromUrl","URL","temp","searchParams","delete","toString","error","Error","username","password","hostname","port","pathname","connectionConfig","decodeURIComponent","host","parseInt","max","idle_timeout","connect_timeout","onnotice","console","log","undefined","nestLogger","Logger","genPostgresProxy","sql","observable","requestContext","wrapQuery","query","then","Proxy","get","target","prop","receiver","onfulfilled","onrejected","sqlStr","strings","Array","span","startTrace","getContext","requestRootSpan","setAttribute","start","Date","now","result","isSetRoleSql","command","duration","parsedParams","JSON","stringify","operation","statement","string","duration_ms","result_count","length","error_message","log","source_type","paas_attributes_module","dropTrace","end","error","Error","message","String","Promise","reject","value","Reflect","bind","apply","thisArg","argArray","arg","cb","call","tx","queryStr","args","options","DrizzleDatabaseManager","db","currentConnectionInfo","isConnected","skipInitDbConnection","config","observable","requestContext","process","env","DEPRECATED_SKIP_INIT_DB_CONNECTION","onModuleInit","initialize","onModuleDestroy","disconnect","name","connectionString","connectionConfig","parseConnectionInfo","baseSql","postgres","sqlProxy","genPostgresProxy","drizzle","schema","logger","ssl","connectionTimeout","connect_timeout","idleTimeout","idle_timeout","maxConnections","max","error","Error","message","getDatabase","testConnection","execute","sql","console","reconnect","_forceRefresh","getConnectionInfo","isDatabaseConnected","transaction","callback","getConnectionPoolStatus","connectionInfo","import_common","import_common","DataPaasDatabaseService","databaseManager","getDatabase","getDatabaseManager","testConnection","reconnect","forceRefresh","getConnectionInfo","isConnected","isDatabaseConnected","transaction","callback","getConnectionPoolStatus","onModuleDestroy","disconnect","import_common","SqlExecutionContextMiddleware","config","use","req","_res","next","roleSchema","userContext","roles","userRoles","join","userId","isSystemAccount","userType","sqls","filter","Boolean","session","runWithAuthContext","preSql","import_nestjs_common","import_nestjs_observable","verifyDrizzlePatched","postgres","require","ok","getAuthContextStore","runWithAuthContext","Error","err","reason","message","String","DataPaasModule","configure","_consumer","forRoot","options","roleSchema","sslModeRequired","connectionString","url","URL","searchParams","get","config","schema","logger","timeout","maxConnections","idleTimeout","connectionTimeout","ssl","autoContext","providers","provide","DATAPAAS_CONFIG","useValue","DrizzleDatabaseManager","useClass","DataPaasDatabaseService","SqlExecutionContextMiddleware","DRIZZLE_DATABASE","useFactory","manager","initialize","getDatabase","inject","module","exports","global","forRootAsync","asyncProviders","createAsyncProviders","imports","createAsyncConfigProvider","args","normalizeConfig","DATAPAAS_LOGGER_SERVICE","observable","rtx","Observable","token","OBSERVABLE_SERVICE","optional","RequestContextService","import_drizzle_orm","DatabaseUtils","safeExecute","databaseService","operation","fallback","isConnected","Error","db","getDatabase","error","console","batchExecute","operations","batchSize","results","i","length","batch","slice","batchResults","Promise","all","map","push","executeWithRetry","maxRetries","retryDelay","lastError","attempt","warn","resolve","setTimeout","tableExists","tableName","result","execute","sql","exists","getTableStructure","getDatabaseVersion","version","getConnectionStats","healthCheck","connectionInfo","getConnectionInfo","isHealthy","message"]}
package/dist/index.d.cts CHANGED
@@ -1,6 +1,8 @@
1
1
  import { OnModuleInit, OnModuleDestroy, ModuleMetadata, InjectionToken, MiddlewareConsumer, DynamicModule, NestMiddleware } from '@nestjs/common';
2
2
  import { PostgresJsDatabase } from 'drizzle-orm/postgres-js';
3
3
  export { PostgresJsDatabase } from 'drizzle-orm/postgres-js';
4
+ import { Observable } from '@lark-apaas/nestjs-observable';
5
+ import { RequestContextService } from '@lark-apaas/nestjs-common';
4
6
  import { Options } from 'postgres';
5
7
  import { Logger } from 'drizzle-orm';
6
8
  import { Request, Response, NextFunction } from 'express';
@@ -31,11 +33,13 @@ interface DataPaasConfig {
31
33
 
32
34
  declare class DrizzleDatabaseManager implements OnModuleInit, OnModuleDestroy {
33
35
  private readonly config;
36
+ private readonly observable;
37
+ private readonly requestContext;
34
38
  private db;
35
39
  private currentConnectionInfo;
36
40
  private isConnected;
37
41
  private skipInitDbConnection;
38
- constructor(config: DataPaasConfig);
42
+ constructor(config: DataPaasConfig, observable: Observable, requestContext: RequestContextService);
39
43
  onModuleInit(): Promise<void>;
40
44
  onModuleDestroy(): Promise<void>;
41
45
  /**
@@ -272,6 +276,7 @@ declare class DatabaseUtils {
272
276
 
273
277
  declare const DRIZZLE_DATABASE = "DRIZZLE_DATABASE";
274
278
  declare const DATAPAAS_CONFIG = "DATAPAAS_CONFIG";
279
+ declare const DATAPAAS_LOGGER_SERVICE: unique symbol;
275
280
 
276
281
  declare class SqlExecutionContextMiddleware implements NestMiddleware {
277
282
  private readonly config;
@@ -279,4 +284,4 @@ declare class SqlExecutionContextMiddleware implements NestMiddleware {
279
284
  use(req: Request, _res: Response, next: NextFunction): void;
280
285
  }
281
286
 
282
- export { DATAPAAS_CONFIG, DRIZZLE_DATABASE, type DataPaasConfig, DataPaasDatabaseService, DataPaasModule, type DataPaasModuleAsyncOptions, type DataPaasModuleOptions, type DatabaseConnectionConfig, type DatabaseConnectionInfo, DatabaseUtils, DrizzleDatabaseManager, type PostgresOptions, SqlExecutionContextMiddleware };
287
+ export { DATAPAAS_CONFIG, DATAPAAS_LOGGER_SERVICE, DRIZZLE_DATABASE, type DataPaasConfig, DataPaasDatabaseService, DataPaasModule, type DataPaasModuleAsyncOptions, type DataPaasModuleOptions, type DatabaseConnectionConfig, type DatabaseConnectionInfo, DatabaseUtils, DrizzleDatabaseManager, type PostgresOptions, SqlExecutionContextMiddleware };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import { OnModuleInit, OnModuleDestroy, ModuleMetadata, InjectionToken, MiddlewareConsumer, DynamicModule, NestMiddleware } from '@nestjs/common';
2
2
  import { PostgresJsDatabase } from 'drizzle-orm/postgres-js';
3
3
  export { PostgresJsDatabase } from 'drizzle-orm/postgres-js';
4
+ import { Observable } from '@lark-apaas/nestjs-observable';
5
+ import { RequestContextService } from '@lark-apaas/nestjs-common';
4
6
  import { Options } from 'postgres';
5
7
  import { Logger } from 'drizzle-orm';
6
8
  import { Request, Response, NextFunction } from 'express';
@@ -31,11 +33,13 @@ interface DataPaasConfig {
31
33
 
32
34
  declare class DrizzleDatabaseManager implements OnModuleInit, OnModuleDestroy {
33
35
  private readonly config;
36
+ private readonly observable;
37
+ private readonly requestContext;
34
38
  private db;
35
39
  private currentConnectionInfo;
36
40
  private isConnected;
37
41
  private skipInitDbConnection;
38
- constructor(config: DataPaasConfig);
42
+ constructor(config: DataPaasConfig, observable: Observable, requestContext: RequestContextService);
39
43
  onModuleInit(): Promise<void>;
40
44
  onModuleDestroy(): Promise<void>;
41
45
  /**
@@ -272,6 +276,7 @@ declare class DatabaseUtils {
272
276
 
273
277
  declare const DRIZZLE_DATABASE = "DRIZZLE_DATABASE";
274
278
  declare const DATAPAAS_CONFIG = "DATAPAAS_CONFIG";
279
+ declare const DATAPAAS_LOGGER_SERVICE: unique symbol;
275
280
 
276
281
  declare class SqlExecutionContextMiddleware implements NestMiddleware {
277
282
  private readonly config;
@@ -279,4 +284,4 @@ declare class SqlExecutionContextMiddleware implements NestMiddleware {
279
284
  use(req: Request, _res: Response, next: NextFunction): void;
280
285
  }
281
286
 
282
- export { DATAPAAS_CONFIG, DRIZZLE_DATABASE, type DataPaasConfig, DataPaasDatabaseService, DataPaasModule, type DataPaasModuleAsyncOptions, type DataPaasModuleOptions, type DatabaseConnectionConfig, type DatabaseConnectionInfo, DatabaseUtils, DrizzleDatabaseManager, type PostgresOptions, SqlExecutionContextMiddleware };
287
+ export { DATAPAAS_CONFIG, DATAPAAS_LOGGER_SERVICE, DRIZZLE_DATABASE, type DataPaasConfig, DataPaasDatabaseService, DataPaasModule, type DataPaasModuleAsyncOptions, type DataPaasModuleOptions, type DatabaseConnectionConfig, type DatabaseConnectionInfo, DatabaseUtils, DrizzleDatabaseManager, type PostgresOptions, SqlExecutionContextMiddleware };
package/dist/index.js CHANGED
@@ -16,11 +16,16 @@ import postgres from "postgres";
16
16
  // src/database/const.ts
17
17
  var DRIZZLE_DATABASE = "DRIZZLE_DATABASE";
18
18
  var DATAPAAS_CONFIG = "DATAPAAS_CONFIG";
19
+ var DATAPAAS_LOGGER_SERVICE = /* @__PURE__ */ Symbol("DATAPAAS_LOGGER_SERVICE");
20
+
21
+ // src/database/drizzle-manager.ts
22
+ import { Observable } from "@lark-apaas/nestjs-observable";
23
+ import { RequestContextService } from "@lark-apaas/nestjs-common";
19
24
 
20
25
  // src/utils.ts
21
26
  function parseConnectionInfo(connectionString, config) {
22
27
  const { maxConnections, idleTimeout, connectionTimeout, ssl, logger } = config || {};
23
- let parsedConfigFromUrl = null;
28
+ let parsedConfigFromUrl;
24
29
  try {
25
30
  parsedConfigFromUrl = new URL(connectionString);
26
31
  const temp = new URL(connectionString);
@@ -53,6 +58,98 @@ function parseConnectionInfo(connectionString, config) {
53
58
  }
54
59
  __name(parseConnectionInfo, "parseConnectionInfo");
55
60
 
61
+ // src/database/postgres-proxy.ts
62
+ import { Logger } from "@nestjs/common";
63
+ var nestLogger = new Logger("Database");
64
+ function genPostgresProxy(sql3, observable, requestContext) {
65
+ const wrapQuery = /* @__PURE__ */ __name((query) => {
66
+ if (query && typeof query.then === "function") {
67
+ return new Proxy(query, {
68
+ get(target, prop, receiver) {
69
+ if (prop === "then") {
70
+ return async (onfulfilled, onrejected) => {
71
+ const sqlStr = query.strings instanceof Array ? query.strings[0] : "";
72
+ const span = observable.startTrace(sqlStr, requestContext?.getContext()?.requestRootSpan);
73
+ span.setAttribute("module", "data");
74
+ span.setAttribute("source_type", "platform");
75
+ const start = Date.now();
76
+ try {
77
+ const result = await target;
78
+ const isSetRoleSql = result?.command === "SET";
79
+ if (!isSetRoleSql) {
80
+ const duration = Date.now() - start;
81
+ const parsedParams = JSON.stringify({
82
+ operation: result?.command,
83
+ sql: result?.statement?.string,
84
+ duration_ms: duration,
85
+ result_count: result.length ?? 0,
86
+ error_message: ""
87
+ });
88
+ nestLogger.log(parsedParams, {
89
+ source_type: "platform",
90
+ paas_attributes_module: "data"
91
+ });
92
+ } else {
93
+ observable.dropTrace(span);
94
+ }
95
+ span.end();
96
+ return onfulfilled ? onfulfilled(result) : result;
97
+ } catch (error) {
98
+ const duration = Date.now() - start;
99
+ const sqlStr2 = query.strings instanceof Array ? query.strings[0] : "";
100
+ const parsedParams = JSON.stringify({
101
+ operation: "",
102
+ sql: sqlStr2,
103
+ duration_ms: duration,
104
+ result_count: 0,
105
+ error_message: error instanceof Error ? error.message : String(error)
106
+ });
107
+ nestLogger.log(parsedParams, {
108
+ source_type: "platform",
109
+ paas_attributes_module: "data"
110
+ });
111
+ span.end();
112
+ return onrejected ? onrejected(error) : Promise.reject(error);
113
+ }
114
+ };
115
+ }
116
+ const value = Reflect.get(target, prop, receiver);
117
+ return typeof value === "function" ? value.bind(receiver) : value;
118
+ }
119
+ });
120
+ }
121
+ return query;
122
+ }, "wrapQuery");
123
+ return new Proxy(sql3, {
124
+ apply(target, thisArg, argArray) {
125
+ const query = Reflect.apply(target, thisArg, argArray);
126
+ return wrapQuery(query);
127
+ },
128
+ get(target, prop, receiver) {
129
+ const value = Reflect.get(target, prop, receiver);
130
+ if (prop === "begin" && typeof value === "function") {
131
+ return (arg, cb) => {
132
+ if (typeof arg === "function") {
133
+ return value.call(target, (tx) => arg(genPostgresProxy(tx, observable, requestContext)));
134
+ }
135
+ if (typeof cb === "function") {
136
+ return value.call(target, arg, (tx) => cb(genPostgresProxy(tx, observable, requestContext)));
137
+ }
138
+ return value.call(target, arg);
139
+ };
140
+ }
141
+ if (prop === "unsafe" && typeof value === "function") {
142
+ return (queryStr, args, options) => {
143
+ const query = value.call(target, queryStr, args, options);
144
+ return wrapQuery(query);
145
+ };
146
+ }
147
+ return typeof value === "function" ? value.bind(receiver) : value;
148
+ }
149
+ });
150
+ }
151
+ __name(genPostgresProxy, "genPostgresProxy");
152
+
56
153
  // src/database/drizzle-manager.ts
57
154
  function _ts_decorate(decorators, target, key, desc) {
58
155
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -76,12 +173,16 @@ var DrizzleDatabaseManager = class {
76
173
  __name(this, "DrizzleDatabaseManager");
77
174
  }
78
175
  config;
176
+ observable;
177
+ requestContext;
79
178
  db = null;
80
179
  currentConnectionInfo = null;
81
180
  isConnected = false;
82
181
  skipInitDbConnection = false;
83
- constructor(config) {
182
+ constructor(config, observable, requestContext) {
84
183
  this.config = config;
184
+ this.observable = observable;
185
+ this.requestContext = requestContext;
85
186
  this.skipInitDbConnection = !!process.env.DEPRECATED_SKIP_INIT_DB_CONNECTION;
86
187
  }
87
188
  async onModuleInit() {
@@ -104,10 +205,11 @@ var DrizzleDatabaseManager = class {
104
205
  }
105
206
  try {
106
207
  const { connectionString, connectionConfig } = parseConnectionInfo(this.config.connectionString, this.config);
107
- const sql3 = postgres(connectionString, connectionConfig);
108
- this.db = drizzle(sql3, {
208
+ const baseSql = postgres(connectionString, connectionConfig);
209
+ const sqlProxy = genPostgresProxy(baseSql, this.observable, this.requestContext);
210
+ this.db = drizzle(sqlProxy, {
109
211
  schema: this.config.schema,
110
- logger: this.config.logger
212
+ logger: false
111
213
  });
112
214
  this.currentConnectionInfo = {
113
215
  connectionString,
@@ -212,9 +314,12 @@ var DrizzleDatabaseManager = class {
212
314
  DrizzleDatabaseManager = _ts_decorate([
213
315
  Injectable(),
214
316
  _ts_param(0, Inject(DATAPAAS_CONFIG)),
317
+ _ts_param(1, Inject(DATAPAAS_LOGGER_SERVICE)),
215
318
  _ts_metadata("design:type", Function),
216
319
  _ts_metadata("design:paramtypes", [
217
- typeof DataPaasConfig === "undefined" ? Object : DataPaasConfig
320
+ typeof DataPaasConfig === "undefined" ? Object : DataPaasConfig,
321
+ typeof Observable === "undefined" ? Object : Observable,
322
+ typeof RequestContextService === "undefined" ? Object : RequestContextService
218
323
  ])
219
324
  ], DrizzleDatabaseManager);
220
325
 
@@ -377,6 +482,8 @@ SqlExecutionContextMiddleware = _ts_decorate3([
377
482
  ], SqlExecutionContextMiddleware);
378
483
 
379
484
  // src/database/database.module.ts
485
+ import { RequestContextService as RequestContextService2, OBSERVABLE_SERVICE } from "@lark-apaas/nestjs-common";
486
+ import { Observable as Observable2 } from "@lark-apaas/nestjs-observable";
380
487
  function _ts_decorate4(decorators, target, key, desc) {
381
488
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
382
489
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -595,7 +702,23 @@ var DataPaasModule = class _DataPaasModule {
595
702
  }
596
703
  };
597
704
  DataPaasModule = _ts_decorate4([
598
- Module({})
705
+ Module({
706
+ providers: [
707
+ {
708
+ provide: DATAPAAS_LOGGER_SERVICE,
709
+ useFactory: /* @__PURE__ */ __name((observable, rtx) => {
710
+ return observable ?? new Observable2(rtx);
711
+ }, "useFactory"),
712
+ inject: [
713
+ {
714
+ token: OBSERVABLE_SERVICE,
715
+ optional: true
716
+ },
717
+ RequestContextService2
718
+ ]
719
+ }
720
+ ]
721
+ })
599
722
  ], DataPaasModule);
600
723
 
601
724
  // src/database/database-utils.ts
@@ -778,6 +901,7 @@ var DatabaseUtils = class {
778
901
  };
779
902
  export {
780
903
  DATAPAAS_CONFIG,
904
+ DATAPAAS_LOGGER_SERVICE,
781
905
  DRIZZLE_DATABASE,
782
906
  DataPaasDatabaseService,
783
907
  DataPaasModule,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/database/drizzle-manager.ts","../src/database/const.ts","../src/utils.ts","../src/database/database.module.ts","../src/database/database.service.ts","../src/database/sql-exection-context.middleware.ts","../src/database/database-utils.ts"],"sourcesContent":["import { Injectable, OnModuleInit, OnModuleDestroy, Inject } from '@nestjs/common';\nimport { drizzle, type PostgresJsDatabase } from 'drizzle-orm/postgres-js';\nimport { sql } from 'drizzle-orm';\nimport postgres from 'postgres';\nimport { DATAPAAS_CONFIG } from './const';\n\nimport { type DataPaasConfig, type DatabaseConnectionInfo } from '../types';\nimport { parseConnectionInfo } from '../utils';\n@Injectable()\nexport class DrizzleDatabaseManager implements OnModuleInit, OnModuleDestroy {\n private db: PostgresJsDatabase | null = null;\n private currentConnectionInfo: DatabaseConnectionInfo | null = null;\n private isConnected: boolean = false;\n private skipInitDbConnection: boolean = false;\n constructor(\n @Inject(DATAPAAS_CONFIG)\n private readonly config: DataPaasConfig,\n ) { \n this.skipInitDbConnection = !!process.env.DEPRECATED_SKIP_INIT_DB_CONNECTION;\n\n }\n\n async onModuleInit() {\n await this.initialize();\n }\n\n async onModuleDestroy() {\n await this.disconnect();\n }\n\n /**\n * 初始化数据库连接\n * @returns Drizzle 数据库实例\n */\n async initialize(): Promise<PostgresJsDatabase> {\n if (this.skipInitDbConnection) {\n this.isConnected = true;\n this.db = {name: 'skipInitDbConnection'} as unknown as PostgresJsDatabase;\n return this.db;\n }\n try {\n const { connectionString, connectionConfig } = parseConnectionInfo(this.config.connectionString, this.config);\n const sql = postgres(connectionString, connectionConfig);\n // 创建 Drizzle 实例\n this.db = drizzle(sql, { schema: this.config.schema, logger: this.config.logger });\n this.currentConnectionInfo = {\n connectionString,\n connectionConfig: {\n ssl: connectionConfig.ssl,\n connectionTimeout: connectionConfig.connect_timeout,\n idleTimeout: connectionConfig.idle_timeout,\n maxConnections: connectionConfig.max,\n },\n };\n this.isConnected = true;\n return this.db;\n } catch (error) {\n this.isConnected = false;\n throw new Error(`Failed to initialize database connection: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n }\n\n /**\n * 获取数据库实例\n * @returns Drizzle 数据库实例\n */\n getDatabase(): PostgresJsDatabase {\n if (!this.db || !this.isConnected) {\n throw new Error('Database not initialized. Call initialize() first.');\n }\n return this.db;\n }\n\n /**\n * 测试数据库连接\n * @returns 连接是否正常\n */\n async testConnection(): Promise<boolean> {\n if (!this.db) {\n return false;\n }\n\n try {\n await this.db.execute(sql`SELECT 1`);\n return true;\n } catch (error) {\n console.error('Database connection test failed:', error);\n this.isConnected = false;\n return false;\n }\n }\n\n /**\n * 重新连接数据库\n * @param forceRefresh 是否强制刷新连接信息\n * @returns 新的数据库实例\n */\n async reconnect(_forceRefresh: boolean = false): Promise<PostgresJsDatabase> {\n await this.disconnect();\n return this.initialize();\n }\n\n /**\n * 断开数据库连接\n */\n async disconnect(): Promise<void> {\n if (this.db) {\n try {\n // postgres-js 会自动处理连接关闭\n this.db = null;\n this.isConnected = false;\n this.currentConnectionInfo = null;\n } catch (error) {\n console.error('Error disconnecting from database:', error);\n }\n }\n }\n\n /**\n * 获取当前连接信息\n * @returns 当前连接信息\n */\n getConnectionInfo(): DatabaseConnectionInfo | null {\n return this.currentConnectionInfo;\n }\n\n /**\n * 检查连接状态\n * @returns 是否已连接\n */\n isDatabaseConnected(): boolean {\n return this.isConnected;\n }\n\n\n /**\n * 开始事务\n * @param callback 事务回调函数\n * @returns 事务结果\n */\n async transaction<T>(callback: (tx: PostgresJsDatabase) => Promise<T>): Promise<T> {\n const db = this.getDatabase();\n return db.transaction(callback);\n }\n\n /**\n * 获取连接池状态\n * @returns 连接池状态信息\n */\n getConnectionPoolStatus(): { isConnected: boolean; connectionInfo: DatabaseConnectionInfo | null } {\n return {\n isConnected: this.isConnected,\n connectionInfo: this.currentConnectionInfo,\n };\n }\n}","export const DRIZZLE_DATABASE = 'DRIZZLE_DATABASE';\nexport const DATAPAAS_CONFIG = 'DATAPAAS_CONFIG';","import { type Logger } from 'drizzle-orm';\nimport { PostgresOptions } from './types';\ninterface ConnectionConfig {\n maxConnections?: number;\n idleTimeout?: number;\n connectionTimeout?: number;\n ssl?: PostgresOptions['ssl'];\n logger?: boolean | Logger;\n}\nexport function parseConnectionInfo(connectionString: string, config?: ConnectionConfig) {\n const { maxConnections, idleTimeout, connectionTimeout, ssl, logger } = config || {};\n // 创建 postgres 连接\n let parsedConfigFromUrl = null;\n try {\n parsedConfigFromUrl = new URL(connectionString);\n const temp = new URL(connectionString);\n temp.searchParams.delete('schema'); // 移除schema参数,避免 postgres 解析错误\n connectionString = temp.toString();\n } catch (error) {\n throw new Error('Failed to parse connection info');\n }\n const { username, password, hostname, port, pathname } = parsedConfigFromUrl;\n const connectionConfig = {\n username: decodeURIComponent(username),\n password: decodeURIComponent(password),\n host: [hostname] as unknown as string,\n port: [parseInt(port) || 5432] as unknown as number,\n pathname: decodeURIComponent(pathname),\n max: maxConnections || 1,\n idle_timeout: idleTimeout || 20,\n connect_timeout: connectionTimeout || 10,\n ssl,\n onnotice: logger ? console.log : undefined,\n }\n return { connectionString, connectionConfig };\n}","import {\n Module,\n DynamicModule,\n Provider,\n MiddlewareConsumer,\n InjectionToken,\n ModuleMetadata,\n} from '@nestjs/common';\nimport { DrizzleDatabaseManager } from './drizzle-manager';\nimport { DataPaasDatabaseService } from './database.service';\nimport { SqlExecutionContextMiddleware } from './sql-exection-context.middleware';\nimport { type DataPaasConfig } from '@/types';\nimport { DATAPAAS_CONFIG, DRIZZLE_DATABASE } from './const';\nexport { type PostgresJsDatabase } from 'drizzle-orm/postgres-js';\n\nexport interface DataPaasModuleOptions extends DataPaasConfig {}\n\n/**\n * 异步配置选项\n */\nexport interface DataPaasModuleAsyncOptions {\n /**\n * 需要导入的模块(例如 ConfigModule)\n */\n imports?: ModuleMetadata['imports'];\n /**\n * 使用工厂函数创建配置\n */\n useFactory?: (...args: unknown[]) => Promise<DataPaasConfig> | DataPaasConfig;\n /**\n * 工厂函数需要注入的依赖\n */\n inject?: InjectionToken[];\n}\n\nfunction verifyDrizzlePatched(): void {\n try {\n // 直接加载被 patch 的 CJS 模块并检查导出是否存在\n // 注意:此路径与补丁文件一致:drizzle-orm/postgres-js/session.cjs\n // 若未来包结构变化,请同步更新补丁与此校验\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const postgres = require('drizzle-orm/postgres-js');\n const ok =\n postgres &&\n typeof postgres.getAuthContextStore === 'function' &&\n typeof postgres.runWithAuthContext === 'function';\n if (!ok) {\n throw new Error(\n 'drizzle-orm 未检测到补丁导出:getAuthContextStore/runWithAuthContext',\n );\n }\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err);\n throw new Error(`drizzle-orm 补丁未生效或版本不匹配:${reason}`);\n }\n}\n\n// 在模块初始化阶段进行一次 drizzle-orm 补丁自检\nverifyDrizzlePatched();\n\n@Module({})\nexport class DataPaasModule {\n configure(_consumer: MiddlewareConsumer) {}\n /**\n * 注册数据平台模块(同步方式)\n * @param options 模块配置选项\n * @returns 动态模块\n */\n static forRoot(options: DataPaasConfig): DynamicModule {\n let roleSchema = '';\n let sslModeRequired = false;\n if (options.connectionString) {\n try {\n const url = new URL(options.connectionString);\n\n roleSchema = url.searchParams.get(\n 'schema'\n ) as string;\n sslModeRequired = url.searchParams.get('sslmode') === \"require\";\n } catch (err) {\n roleSchema = '';\n }\n }\n const config: DataPaasConfig = {\n connectionString: options.connectionString,\n schema: options.schema,\n logger: options.logger || false,\n timeout: options.timeout || 10000,\n maxConnections: options.maxConnections || 1,\n idleTimeout: options.idleTimeout || 20,\n connectionTimeout: options.connectionTimeout || 10,\n ssl: options.ssl || (sslModeRequired ? 'require' : false),\n autoContext: options.autoContext == null ? true : !!options.autoContext,\n roleSchema,\n };\n\n const providers: Provider[] = [\n // 配置提供者 - 使用 useValue\n {\n provide: DATAPAAS_CONFIG,\n useValue: config,\n },\n // 数据库管理器 - 使用 useClass,依赖注入连接服务和配置服务\n {\n provide: DrizzleDatabaseManager,\n useClass: DrizzleDatabaseManager,\n },\n // 数据库服务 - 使用 useClass,依赖注入管理器\n {\n provide: DataPaasDatabaseService,\n useClass: DataPaasDatabaseService,\n },\n {\n provide: SqlExecutionContextMiddleware,\n useClass: SqlExecutionContextMiddleware,\n },\n // Drizzle 数据库实例 - 使用 useFactory 获取管理器中的数据库实例\n {\n provide: DRIZZLE_DATABASE,\n useFactory: async (manager: DrizzleDatabaseManager) => {\n await manager.initialize();\n return manager.getDatabase();\n },\n inject: [DrizzleDatabaseManager],\n },\n ];\n\n return {\n module: DataPaasModule,\n providers,\n exports: [\n DrizzleDatabaseManager,\n DataPaasDatabaseService,\n SqlExecutionContextMiddleware,\n DRIZZLE_DATABASE,\n DATAPAAS_CONFIG,\n ],\n global: true,\n };\n }\n\n /**\n * 注册数据平台模块(异步方式)\n * 支持从 ConfigModule 等异步源获取配置\n * @param options 异步配置选项\n * @returns 动态模块\n * @example\n * ```typescript\n * DataPaasModule.forRootAsync({\n * imports: [ConfigModule],\n * useFactory: async (configService: ConfigService) => ({\n * connectionString: configService.get('DATABASE_URL'),\n * }),\n * inject: [ConfigService],\n * })\n * ```\n */\n static forRootAsync(options: DataPaasModuleAsyncOptions): DynamicModule {\n const asyncProviders = this.createAsyncProviders(options);\n\n const providers: Provider[] = [\n ...asyncProviders,\n // 数据库管理器 - 使用 useClass,依赖注入连接服务和配置服务\n {\n provide: DrizzleDatabaseManager,\n useClass: DrizzleDatabaseManager,\n },\n // 数据库服务 - 使用 useClass,依赖注入管理器\n {\n provide: DataPaasDatabaseService,\n useClass: DataPaasDatabaseService,\n },\n {\n provide: SqlExecutionContextMiddleware,\n useClass: SqlExecutionContextMiddleware,\n },\n // Drizzle 数据库实例 - 使用 useFactory 获取管理器中的数据库实例\n {\n provide: DRIZZLE_DATABASE,\n useFactory: async (manager: DrizzleDatabaseManager) => {\n await manager.initialize();\n return manager.getDatabase();\n },\n inject: [DrizzleDatabaseManager],\n },\n ];\n\n return {\n module: DataPaasModule,\n imports: options.imports || [],\n providers,\n exports: [\n DrizzleDatabaseManager,\n DataPaasDatabaseService,\n SqlExecutionContextMiddleware,\n DRIZZLE_DATABASE,\n DATAPAAS_CONFIG,\n ],\n global: true,\n };\n }\n\n /**\n * 创建异步配置 providers\n */\n private static createAsyncProviders(\n options: DataPaasModuleAsyncOptions\n ): Provider[] {\n if (options.useFactory) {\n return [this.createAsyncConfigProvider(options)];\n }\n\n throw new Error('DataPaasModule.forRootAsync 需要指定 useFactory');\n }\n\n /**\n * 创建异步配置 provider\n */\n private static createAsyncConfigProvider(\n options: DataPaasModuleAsyncOptions\n ): Provider {\n if (options.useFactory) {\n return {\n provide: DATAPAAS_CONFIG,\n useFactory: async (...args: unknown[]) => {\n const config = await options.useFactory!(...args);\n return this.normalizeConfig(config);\n },\n inject: options.inject || [],\n };\n }\n\n throw new Error('Invalid async options');\n }\n\n /**\n * 标准化配置,设置默认值\n */\n private static normalizeConfig(config: DataPaasConfig): DataPaasConfig {\n let roleSchema = '';\n let sslModeRequired = false;\n if (config.connectionString) {\n try {\n const url = new URL(config.connectionString);\n roleSchema = url.searchParams.get(\n 'schema'\n ) as string;\n sslModeRequired = url.searchParams.get('sslmode') === \"require\";\n } catch (err) {\n roleSchema = '';\n }\n }\n return {\n connectionString: config.connectionString,\n schema: config.schema,\n logger: config.logger || false,\n timeout: config.timeout || 10000,\n maxConnections: config.maxConnections || 1,\n idleTimeout: config.idleTimeout || 20,\n connectionTimeout: config.connectionTimeout || 10,\n ssl: config.ssl || (sslModeRequired ? 'require' : false),\n autoContext: config.autoContext == null ? true : !!config.autoContext,\n roleSchema,\n };\n }\n}\n","import { Injectable, OnModuleDestroy } from '@nestjs/common';\nimport { type PostgresJsDatabase } from 'drizzle-orm/postgres-js';\nimport { DrizzleDatabaseManager } from './drizzle-manager';\nimport { DatabaseConnectionInfo } from '../types';\n\n@Injectable()\nexport class DataPaasDatabaseService implements OnModuleDestroy {\n constructor(\n private readonly databaseManager: DrizzleDatabaseManager,\n ) {}\n\n /**\n * 获取 Drizzle 数据库实例\n * @returns Drizzle 数据库实例\n */\n getDatabase(): PostgresJsDatabase {\n return this.databaseManager.getDatabase();\n }\n\n /**\n * 获取数据库管理器\n * @returns 数据库管理器实例\n */\n getDatabaseManager(): DrizzleDatabaseManager {\n return this.databaseManager;\n }\n\n\n /**\n * 测试数据库连接\n * @returns 连接是否正常\n */\n async testConnection(): Promise<boolean> {\n return this.databaseManager.testConnection();\n }\n\n /**\n * 重新连接数据库\n * @param forceRefresh 是否强制刷新连接信息\n * @returns 新的数据库实例\n */\n async reconnect(forceRefresh: boolean = false): Promise<PostgresJsDatabase> {\n return this.databaseManager.reconnect(forceRefresh);\n }\n\n /**\n * 获取当前连接信息\n * @returns 当前连接信息\n */\n getConnectionInfo(): DatabaseConnectionInfo | null {\n return this.databaseManager.getConnectionInfo();\n }\n\n /**\n * 检查连接状态\n * @returns 是否已连接\n */\n isConnected(): boolean {\n return this.databaseManager.isDatabaseConnected();\n }\n\n /**\n * 开始事务\n * @param callback 事务回调函数\n * @returns 事务结果\n */\n async transaction<T>(callback: (tx: PostgresJsDatabase) => Promise<T>): Promise<T> {\n return this.databaseManager.transaction(callback);\n }\n\n /**\n * 获取连接池状态\n * @returns 连接池状态信息\n */\n getConnectionPoolStatus(): { isConnected: boolean; connectionInfo: DatabaseConnectionInfo | null } {\n return this.databaseManager.getConnectionPoolStatus();\n }\n\n\n /**\n * 模块销毁时断开数据库连接\n */\n async onModuleDestroy(): Promise<void> {\n await this.databaseManager.disconnect();\n }\n}\n","import { Injectable, NestMiddleware, Inject } from '@nestjs/common';\nimport { Request, Response, NextFunction } from 'express';\nimport * as session from 'drizzle-orm/postgres-js';\nimport { DATAPAAS_CONFIG } from './const';\nimport { type DataPaasConfig } from '../types';\n\ninterface UserContext {\n userId?: string;\n tenantId?: number;\n appId?: string;\n // 用户角色(如果有)\n userRoles?: string[];\n // 是否为系统账号\n isSystemAccount: boolean;\n // 用户类型\n userType?: string;\n}\n\n@Injectable()\nexport class SqlExecutionContextMiddleware implements NestMiddleware {\n constructor(\n @Inject(DATAPAAS_CONFIG)\n private readonly config: DataPaasConfig,\n ) {}\n\n use(req: Request, _res: Response, next: NextFunction) {\n const roleSchema = this.config.roleSchema ?? '';\n const userContext =\n (req as unknown as { userContext: UserContext }).userContext || {};\n const roles = (userContext.userRoles || []).join(',');\n const userId = userContext.userId;\n const isSystemAccount = userContext.isSystemAccount;\n const userType = userContext.userType;\n const sqls = [\n // 设置用户 ID, 匿名用户时设置为空字符串\n userId\n ? `SET LOCAL app.user_id = '${userId}'`\n : `SET LOCAL app.user_id = ''`,\n // 系统用户设置为service_role, 登录用户设置为 authenticated_xxx 角色,匿名用户设置为 anon_xxx 角色\n isSystemAccount ? `SET LOCAL ROLE 'service_role_${roleSchema}'` : (\n userId\n ? `SET LOCAL ROLE 'authenticated_${roleSchema}'`\n : `SET LOCAL ROLE 'anon_${roleSchema}'`),\n // 自定义角色\n roles && `SET LOCAL app.role_ids = '${roles}'`,\n // 用户类型\n userType\n ? `SET LOCAL app.user_type = '${userType}'`\n : `SET LOCAL app.user_type = ''`,\n ]\n .filter(Boolean)\n .join(';');\n\n // 需要确认角色设置是否对后续 SQL 执行有影响,预期是只影响当前会话\n session.runWithAuthContext({ preSql: sqls }, () => {\n next();\n });\n }\n}\n","import { type PostgresJsDatabase } from 'drizzle-orm/postgres-js';\nimport { sql } from 'drizzle-orm';\n\nimport { DataPaasDatabaseService } from './database.service';\n\n/**\n * 数据库工具函数集合\n */\nexport class DatabaseUtils {\n /**\n * 安全执行数据库操作\n * @param databaseService 数据库服务实例\n * @param operation 数据库操作函数\n * @param fallback 失败时的回退值\n * @returns 操作结果或回退值\n */\n static async safeExecute<T>(\n databaseService: DataPaasDatabaseService,\n operation: (db: PostgresJsDatabase) => Promise<T>,\n fallback?: T\n ): Promise<T | undefined> {\n try {\n if (!databaseService.isConnected()) {\n throw new Error('Database not connected');\n }\n \n const db = databaseService.getDatabase();\n return await operation(db);\n } catch (error) {\n console.error('Database operation failed:', error);\n return fallback;\n }\n }\n\n /**\n * 批量执行数据库操作\n * @param databaseService 数据库服务实例\n * @param operations 操作数组\n * @param batchSize 批处理大小\n * @returns 所有操作的结果\n */\n static async batchExecute<T>(\n databaseService: DataPaasDatabaseService,\n operations: Array<(db: PostgresJsDatabase) => Promise<T>>,\n batchSize: number = 10\n ): Promise<T[]> {\n const results: T[] = [];\n const db = databaseService.getDatabase();\n\n for (let i = 0; i < operations.length; i += batchSize) {\n const batch = operations.slice(i, i + batchSize);\n const batchResults = await Promise.all(\n batch.map(operation => operation(db))\n );\n results.push(...batchResults);\n }\n\n return results;\n }\n\n /**\n * 执行带重试的数据库操作\n * @param databaseService 数据库服务实例\n * @param operation 数据库操作函数\n * @param maxRetries 最大重试次数\n * @param retryDelay 重试延迟(毫秒)\n * @returns 操作结果\n */\n static async executeWithRetry<T>(\n databaseService: DataPaasDatabaseService,\n operation: (db: PostgresJsDatabase) => Promise<T>,\n maxRetries: number = 3,\n retryDelay: number = 1000\n ): Promise<T> {\n let lastError: Error;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n const db = databaseService.getDatabase();\n return await operation(db);\n } catch (error) {\n lastError = error as Error;\n \n if (attempt === maxRetries) {\n break;\n }\n\n console.warn(`Database operation failed (attempt ${attempt + 1}/${maxRetries + 1}):`, error);\n \n // 等待后重试\n await new Promise(resolve => setTimeout(resolve, retryDelay * (attempt + 1)));\n }\n }\n\n throw lastError!;\n }\n\n /**\n * 检查表是否存在\n * @param databaseService 数据库服务实例\n * @param tableName 表名\n * @returns 表是否存在\n */\n static async tableExists(\n db: PostgresJsDatabase,\n tableName: string\n ): Promise<boolean> {\n try {\n const result = await db.execute(\n sql`SELECT EXISTS (\n SELECT FROM information_schema.tables \n WHERE table_schema = 'public' \n AND table_name = ${tableName}\n )`\n );\n \n return result[0]?.exists as boolean || false;\n } catch (error) {\n console.error('Failed to check table existence:', error);\n return false;\n }\n }\n\n /**\n * 获取表结构信息\n * @param databaseService 数据库服务实例\n * @param tableName 表名\n * @returns 表结构信息\n */\n static async getTableStructure(\n db: PostgresJsDatabase,\n tableName: string\n ): Promise<any[]> {\n try {\n const result = await db.execute(\n sql`SELECT \n column_name,\n data_type,\n is_nullable,\n column_default,\n character_maximum_length\n FROM information_schema.columns \n WHERE table_schema = 'public' \n AND table_name = ${tableName}\n ORDER BY ordinal_position`,\n );\n \n return result;\n } catch (error) {\n console.error('Failed to get table structure:', error);\n return [];\n }\n }\n\n /**\n * 获取数据库版本信息\n * @param databaseService 数据库服务实例\n * @returns 数据库版本\n */\n static async getDatabaseVersion(\n db: PostgresJsDatabase\n ): Promise<string> {\n try {\n const result = await db.execute(sql`SELECT version()`);\n return result[0]?.version as string || 'Unknown';\n } catch (error) {\n console.error('Failed to get database version:', error);\n return 'Unknown';\n }\n }\n\n /**\n * 获取连接统计信息\n * @param databaseService 数据库服务实例\n * @returns 连接统计信息\n */\n static async getConnectionStats(\n db: PostgresJsDatabase\n ): Promise<any> {\n try {\n const result = await db.execute(sql`\n SELECT \n count(*) as total_connections,\n count(*) FILTER (WHERE state = 'active') as active_connections,\n count(*) FILTER (WHERE state = 'idle') as idle_connections\n FROM pg_stat_activity \n WHERE datname = current_database()\n `);\n \n return result[0] || {};\n } catch (error) {\n console.error('Failed to get connection stats:', error);\n return {};\n }\n }\n\n /**\n * 健康检查\n * @param databaseService 数据库服务实例\n * @returns 健康状态\n */\n static async healthCheck(\n databaseService: DataPaasDatabaseService\n ): Promise<{\n isHealthy: boolean;\n isConnected: boolean;\n version?: string;\n connectionInfo?: any;\n error?: string;\n }> {\n try {\n const isConnected = databaseService.isConnected();\n const connectionInfo = databaseService.getConnectionInfo();\n\n const db = databaseService.getDatabase();\n if (!isConnected) {\n return {\n isHealthy: false,\n isConnected: false,\n error: 'Database not connected'\n };\n }\n\n const version = await this.getDatabaseVersion(db);\n \n return {\n isHealthy: true,\n isConnected: true,\n version,\n connectionInfo\n };\n } catch (error) {\n return {\n isHealthy: false,\n isConnected: false,\n error: error instanceof Error ? error.message : 'Unknown error'\n };\n }\n }\n}\n"],"mappings":";;;;;;;;;;AAAA,SAASA,YAA2CC,cAAc;AAClE,SAASC,eAAwC;AACjD,SAASC,WAAW;AACpB,OAAOC,cAAc;;;ACHd,IAAMC,mBAAmB;AACzB,IAAMC,kBAAkB;;;ACQxB,SAASC,oBAAoBC,kBAA0BC,QAAyB;AACrF,QAAM,EAAEC,gBAAgBC,aAAaC,mBAAmBC,KAAKC,OAAM,IAAKL,UAAU,CAAC;AAEnF,MAAIM,sBAAsB;AAC1B,MAAI;AACFA,0BAAsB,IAAIC,IAAIR,gBAAAA;AAC9B,UAAMS,OAAO,IAAID,IAAIR,gBAAAA;AACrBS,SAAKC,aAAaC,OAAO,QAAA;AACzBX,uBAAmBS,KAAKG,SAAQ;EAClC,SAASC,OAAO;AACd,UAAM,IAAIC,MAAM,iCAAA;EAClB;AACA,QAAM,EAAEC,UAAUC,UAAUC,UAAUC,MAAMC,SAAQ,IAAKZ;AACzD,QAAMa,mBAAmB;IACvBL,UAAUM,mBAAmBN,QAAAA;IAC7BC,UAAUK,mBAAmBL,QAAAA;IAC7BM,MAAM;MAACL;;IACPC,MAAM;MAACK,SAASL,IAAAA,KAAS;;IACzBC,UAAUE,mBAAmBF,QAAAA;IAC7BK,KAAKtB,kBAAkB;IACvBuB,cAActB,eAAe;IAC7BuB,iBAAiBtB,qBAAqB;IACtCC;IACAsB,UAAUrB,SAASsB,QAAQC,MAAMC;EACnC;AACA,SAAO;IAAE9B;IAAkBoB;EAAiB;AAC9C;AA1BgBrB;;;;;;;;;;;;;;;;;;;;AFAT,IAAMgC,yBAAN,MAAMA;SAAAA;;;;EACHC,KAAgC;EAChCC,wBAAuD;EACvDC,cAAuB;EACvBC,uBAAgC;EACxC,YAEmBC,QACjB;SADiBA,SAAAA;AAEjB,SAAKD,uBAAuB,CAAC,CAACE,QAAQC,IAAIC;EAE5C;EAEA,MAAMC,eAAe;AACnB,UAAM,KAAKC,WAAU;EACvB;EAEA,MAAMC,kBAAkB;AACtB,UAAM,KAAKC,WAAU;EACvB;;;;;EAMA,MAAMF,aAA0C;AAC9C,QAAI,KAAKN,sBAAsB;AAC7B,WAAKD,cAAc;AACnB,WAAKF,KAAK;QAACY,MAAM;MAAsB;AACvC,aAAO,KAAKZ;IACd;AACA,QAAI;AACF,YAAM,EAAEa,kBAAkBC,iBAAgB,IAAKC,oBAAoB,KAAKX,OAAOS,kBAAkB,KAAKT,MAAM;AAC5G,YAAMY,OAAMC,SAASJ,kBAAkBC,gBAAAA;AAEvC,WAAKd,KAAKkB,QAAQF,MAAK;QAAEG,QAAQ,KAAKf,OAAOe;QAAQC,QAAQ,KAAKhB,OAAOgB;MAAO,CAAA;AAChF,WAAKnB,wBAAwB;QAC3BY;QACAC,kBAAkB;UAChBO,KAAKP,iBAAiBO;UACtBC,mBAAmBR,iBAAiBS;UACpCC,aAAaV,iBAAiBW;UAC9BC,gBAAgBZ,iBAAiBa;QACnC;MACF;AACA,WAAKzB,cAAc;AACnB,aAAO,KAAKF;IACd,SAAS4B,OAAO;AACd,WAAK1B,cAAc;AACnB,YAAM,IAAI2B,MAAM,6CAA6CD,iBAAiBC,QAAQD,MAAME,UAAU,eAAA,EAAiB;IACzH;EACF;;;;;EAMAC,cAAkC;AAChC,QAAI,CAAC,KAAK/B,MAAM,CAAC,KAAKE,aAAa;AACjC,YAAM,IAAI2B,MAAM,oDAAA;IAClB;AACA,WAAO,KAAK7B;EACd;;;;;EAMA,MAAMgC,iBAAmC;AACvC,QAAI,CAAC,KAAKhC,IAAI;AACZ,aAAO;IACT;AAEA,QAAI;AACF,YAAM,KAAKA,GAAGiC,QAAQjB,aAAa;AACnC,aAAO;IACT,SAASY,OAAO;AACdM,cAAQN,MAAM,oCAAoCA,KAAAA;AAClD,WAAK1B,cAAc;AACnB,aAAO;IACT;EACF;;;;;;EAOA,MAAMiC,UAAUC,gBAAyB,OAAoC;AAC3E,UAAM,KAAKzB,WAAU;AACrB,WAAO,KAAKF,WAAU;EACxB;;;;EAKA,MAAME,aAA4B;AAChC,QAAI,KAAKX,IAAI;AACX,UAAI;AAEF,aAAKA,KAAK;AACV,aAAKE,cAAc;AACnB,aAAKD,wBAAwB;MAC/B,SAAS2B,OAAO;AACdM,gBAAQN,MAAM,sCAAsCA,KAAAA;MACtD;IACF;EACF;;;;;EAMAS,oBAAmD;AACjD,WAAO,KAAKpC;EACd;;;;;EAMAqC,sBAA+B;AAC7B,WAAO,KAAKpC;EACd;;;;;;EAQA,MAAMqC,YAAeC,UAA8D;AACjF,UAAMxC,KAAK,KAAK+B,YAAW;AAC3B,WAAO/B,GAAGuC,YAAYC,QAAAA;EACxB;;;;;EAMAC,0BAAmG;AACjG,WAAO;MACLvC,aAAa,KAAKA;MAClBwC,gBAAgB,KAAKzC;IACvB;EACF;AACF;;;;;;;;;;;AG3JA,SACE0C,cAMK;;;ACPP,SAASC,cAAAA,mBAAmC;;;;;;;;;;;;AAMrC,IAAMC,0BAAN,MAAMA;SAAAA;;;;EACX,YACmBC,iBACjB;SADiBA,kBAAAA;EAChB;;;;;EAMHC,cAAkC;AAChC,WAAO,KAAKD,gBAAgBC,YAAW;EACzC;;;;;EAMAC,qBAA6C;AAC3C,WAAO,KAAKF;EACd;;;;;EAOA,MAAMG,iBAAmC;AACvC,WAAO,KAAKH,gBAAgBG,eAAc;EAC5C;;;;;;EAOA,MAAMC,UAAUC,eAAwB,OAAoC;AAC1E,WAAO,KAAKL,gBAAgBI,UAAUC,YAAAA;EACxC;;;;;EAMAC,oBAAmD;AACjD,WAAO,KAAKN,gBAAgBM,kBAAiB;EAC/C;;;;;EAMAC,cAAuB;AACrB,WAAO,KAAKP,gBAAgBQ,oBAAmB;EACjD;;;;;;EAOA,MAAMC,YAAeC,UAA8D;AACjF,WAAO,KAAKV,gBAAgBS,YAAYC,QAAAA;EAC1C;;;;;EAMAC,0BAAmG;AACjG,WAAO,KAAKX,gBAAgBW,wBAAuB;EACrD;;;;EAMA,MAAMC,kBAAiC;AACrC,UAAM,KAAKZ,gBAAgBa,WAAU;EACvC;AACF;;;;;;;;;;ACrFA,SAASC,cAAAA,aAA4BC,UAAAA,eAAc;AAEnD,YAAYC,aAAa;;;;;;;;;;;;;;;;;;AAiBlB,IAAMC,gCAAN,MAAMA;SAAAA;;;;EACX,YAEmBC,QACjB;SADiBA,SAAAA;EAChB;EAEHC,IAAIC,KAAcC,MAAgBC,MAAoB;AACpD,UAAMC,aAAa,KAAKL,OAAOK,cAAc;AAC7C,UAAMC,cACHJ,IAAgDI,eAAe,CAAC;AACnE,UAAMC,SAASD,YAAYE,aAAa,CAAA,GAAIC,KAAK,GAAA;AACjD,UAAMC,SAASJ,YAAYI;AAC3B,UAAMC,kBAAkBL,YAAYK;AACpC,UAAMC,WAAWN,YAAYM;AAC7B,UAAMC,OAAO;;MAEXH,SACI,4BAA4BA,MAAAA,MAC5B;;MAEJC,kBAAkB,gCAAgCN,UAAAA,MAChDK,SACI,iCAAiCL,UAAAA,MACjC,wBAAwBA,UAAAA;;MAE9BE,SAAS,6BAA6BA,KAAAA;;MAEtCK,WACI,8BAA8BA,QAAAA,MAC9B;MAEHE,OAAOC,OAAAA,EACPN,KAAK,GAAA;AAGRO,IAAQC,2BAAmB;MAAEC,QAAQL;IAAK,GAAG,MAAA;AAC3CT,WAAAA;IACF,CAAA;EACF;AACF;;;;;;;;;;;;;;;;;;AFvBA,SAASe,uBAAAA;AACP,MAAI;AAKF,UAAMC,YAAWC,UAAQ,yBAAA;AACzB,UAAMC,KACJF,aACA,OAAOA,UAASG,wBAAwB,cACxC,OAAOH,UAASI,uBAAuB;AACzC,QAAI,CAACF,IAAI;AACP,YAAM,IAAIG,MACR,0GAAA;IAEJ;EACF,SAASC,KAAK;AACZ,UAAMC,SAASD,eAAeD,QAAQC,IAAIE,UAAUC,OAAOH,GAAAA;AAC3D,UAAM,IAAID,MAAM,uFAA2BE,MAAAA,EAAQ;EACrD;AACF;AApBSR;AAuBTA,qBAAAA;AAGO,IAAMW,iBAAN,MAAMA,gBAAAA;SAAAA;;;EACXC,UAAUC,WAA+B;EAAC;;;;;;EAM1C,OAAOC,QAAQC,SAAwC;AACrD,QAAIC,aAAa;AACjB,QAAIC,kBAAkB;AACtB,QAAIF,QAAQG,kBAAkB;AAC5B,UAAI;AACF,cAAMC,MAAM,IAAIC,IAAIL,QAAQG,gBAAgB;AAE5CF,qBAAaG,IAAIE,aAAaC,IAC5B,QAAA;AAEFL,0BAAkBE,IAAIE,aAAaC,IAAI,SAAA,MAAe;MACxD,SAASf,KAAK;AACZS,qBAAa;MACf;IACF;AACA,UAAMO,SAAyB;MAC7BL,kBAAkBH,QAAQG;MAC1BM,QAAQT,QAAQS;MAChBC,QAAQV,QAAQU,UAAU;MAC1BC,SAASX,QAAQW,WAAW;MAC5BC,gBAAgBZ,QAAQY,kBAAkB;MAC1CC,aAAab,QAAQa,eAAe;MACpCC,mBAAmBd,QAAQc,qBAAqB;MAChDC,KAAKf,QAAQe,QAAQb,kBAAkB,YAAY;MACnDc,aAAahB,QAAQgB,eAAe,OAAO,OAAO,CAAC,CAAChB,QAAQgB;MAC5Df;IACF;AAEA,UAAMgB,YAAwB;;MAE5B;QACEC,SAASC;QACTC,UAAUZ;MACZ;;MAEA;QACEU,SAASG;QACTC,UAAUD;MACZ;;MAEA;QACEH,SAASK;QACTD,UAAUC;MACZ;MACA;QACEL,SAASM;QACTF,UAAUE;MACZ;;MAEA;QACEN,SAASO;QACTC,YAAY,8BAAOC,YAAAA;AACjB,gBAAMA,QAAQC,WAAU;AACxB,iBAAOD,QAAQE,YAAW;QAC5B,GAHY;QAIZC,QAAQ;UAACT;;MACX;;AAGF,WAAO;MACLU,QAAQnC;MACRqB;MACAe,SAAS;QACPX;QACAE;QACAC;QACAC;QACAN;;MAEFc,QAAQ;IACV;EACF;;;;;;;;;;;;;;;;;EAkBA,OAAOC,aAAalC,SAAoD;AACtE,UAAMmC,iBAAiB,KAAKC,qBAAqBpC,OAAAA;AAEjD,UAAMiB,YAAwB;SACzBkB;;MAEH;QACEjB,SAASG;QACTC,UAAUD;MACZ;;MAEA;QACEH,SAASK;QACTD,UAAUC;MACZ;MACA;QACEL,SAASM;QACTF,UAAUE;MACZ;;MAEA;QACEN,SAASO;QACTC,YAAY,8BAAOC,YAAAA;AACjB,gBAAMA,QAAQC,WAAU;AACxB,iBAAOD,QAAQE,YAAW;QAC5B,GAHY;QAIZC,QAAQ;UAACT;;MACX;;AAGF,WAAO;MACLU,QAAQnC;MACRyC,SAASrC,QAAQqC,WAAW,CAAA;MAC5BpB;MACAe,SAAS;QACPX;QACAE;QACAC;QACAC;QACAN;;MAEFc,QAAQ;IACV;EACF;;;;EAKA,OAAeG,qBACbpC,SACY;AACZ,QAAIA,QAAQ0B,YAAY;AACtB,aAAO;QAAC,KAAKY,0BAA0BtC,OAAAA;;IACzC;AAEA,UAAM,IAAIT,MAAM,iEAAA;EAClB;;;;EAKA,OAAe+C,0BACbtC,SACU;AACV,QAAIA,QAAQ0B,YAAY;AACtB,aAAO;QACLR,SAASC;QACTO,YAAY,iCAAUa,SAAAA;AACpB,gBAAM/B,SAAS,MAAMR,QAAQ0B,WAAU,GAAKa,IAAAA;AAC5C,iBAAO,KAAKC,gBAAgBhC,MAAAA;QAC9B,GAHY;QAIZsB,QAAQ9B,QAAQ8B,UAAU,CAAA;MAC5B;IACF;AAEA,UAAM,IAAIvC,MAAM,uBAAA;EAClB;;;;EAKA,OAAeiD,gBAAgBhC,QAAwC;AACrE,QAAIP,aAAa;AACjB,QAAIC,kBAAkB;AACtB,QAAIM,OAAOL,kBAAkB;AAC3B,UAAI;AACF,cAAMC,MAAM,IAAIC,IAAIG,OAAOL,gBAAgB;AAC3CF,qBAAaG,IAAIE,aAAaC,IAC5B,QAAA;AAEFL,0BAAkBE,IAAIE,aAAaC,IAAI,SAAA,MAAe;MACxD,SAASf,KAAK;AACZS,qBAAa;MACf;IACF;AACA,WAAO;MACLE,kBAAkBK,OAAOL;MACzBM,QAAQD,OAAOC;MACfC,QAAQF,OAAOE,UAAU;MACzBC,SAASH,OAAOG,WAAW;MAC3BC,gBAAgBJ,OAAOI,kBAAkB;MACzCC,aAAaL,OAAOK,eAAe;MACnCC,mBAAmBN,OAAOM,qBAAqB;MAC/CC,KAAKP,OAAOO,QAAQb,kBAAkB,YAAY;MAClDc,aAAaR,OAAOQ,eAAe,OAAO,OAAO,CAAC,CAACR,OAAOQ;MAC1Df;IACF;EACF;AACF;;;;;;AGxQA,SAASwC,OAAAA,YAAW;AAOb,IAAMC,gBAAN,MAAMA;EAPb,OAOaA;;;;;;;;;;EAQX,aAAaC,YACXC,iBACAC,WACAC,UACwB;AACxB,QAAI;AACF,UAAI,CAACF,gBAAgBG,YAAW,GAAI;AAClC,cAAM,IAAIC,MAAM,wBAAA;MAClB;AAEA,YAAMC,KAAKL,gBAAgBM,YAAW;AACtC,aAAO,MAAML,UAAUI,EAAAA;IACzB,SAASE,OAAO;AACdC,cAAQD,MAAM,8BAA8BA,KAAAA;AAC5C,aAAOL;IACT;EACF;;;;;;;;EASA,aAAaO,aACXT,iBACAU,YACAC,YAAoB,IACN;AACd,UAAMC,UAAe,CAAA;AACrB,UAAMP,KAAKL,gBAAgBM,YAAW;AAEtC,aAASO,IAAI,GAAGA,IAAIH,WAAWI,QAAQD,KAAKF,WAAW;AACrD,YAAMI,QAAQL,WAAWM,MAAMH,GAAGA,IAAIF,SAAAA;AACtC,YAAMM,eAAe,MAAMC,QAAQC,IACjCJ,MAAMK,IAAInB,CAAAA,cAAaA,UAAUI,EAAAA,CAAAA,CAAAA;AAEnCO,cAAQS,KAAI,GAAIJ,YAAAA;IAClB;AAEA,WAAOL;EACT;;;;;;;;;EAUA,aAAaU,iBACXtB,iBACAC,WACAsB,aAAqB,GACrBC,aAAqB,KACT;AACZ,QAAIC;AAEJ,aAASC,UAAU,GAAGA,WAAWH,YAAYG,WAAW;AACtD,UAAI;AACF,cAAMrB,KAAKL,gBAAgBM,YAAW;AACtC,eAAO,MAAML,UAAUI,EAAAA;MACzB,SAASE,OAAO;AACdkB,oBAAYlB;AAEZ,YAAImB,YAAYH,YAAY;AAC1B;QACF;AAEAf,gBAAQmB,KAAK,sCAAsCD,UAAU,CAAA,IAAKH,aAAa,CAAA,MAAOhB,KAAAA;AAGtF,cAAM,IAAIW,QAAQU,CAAAA,YAAWC,WAAWD,SAASJ,cAAcE,UAAU,EAAA,CAAA;MAC3E;IACF;AAEA,UAAMD;EACR;;;;;;;EAQA,aAAaK,YACXzB,IACA0B,WACkB;AAClB,QAAI;AACF,YAAMC,SAAS,MAAM3B,GAAG4B,QACtBC;;;6BAGqBH,SAAAA;UACnB;AAGJ,aAAOC,OAAO,CAAA,GAAIG,UAAqB;IACzC,SAAS5B,OAAO;AACdC,cAAQD,MAAM,oCAAoCA,KAAAA;AAClD,aAAO;IACT;EACF;;;;;;;EAQA,aAAa6B,kBACX/B,IACA0B,WACgB;AAChB,QAAI;AACF,YAAMC,SAAS,MAAM3B,GAAG4B,QACtBC;;;;;;;;2BAQmBH,SAAAA;kCACO;AAG5B,aAAOC;IACT,SAASzB,OAAO;AACdC,cAAQD,MAAM,kCAAkCA,KAAAA;AAChD,aAAO,CAAA;IACT;EACF;;;;;;EAOA,aAAa8B,mBACXhC,IACiB;AACjB,QAAI;AACF,YAAM2B,SAAS,MAAM3B,GAAG4B,QAAQC,sBAAqB;AACrD,aAAOF,OAAO,CAAA,GAAIM,WAAqB;IACzC,SAAS/B,OAAO;AACdC,cAAQD,MAAM,mCAAmCA,KAAAA;AACjD,aAAO;IACT;EACF;;;;;;EAOA,aAAagC,mBACXlC,IACc;AACd,QAAI;AACF,YAAM2B,SAAS,MAAM3B,GAAG4B,QAAQC;;;;;;;OAO/B;AAED,aAAOF,OAAO,CAAA,KAAM,CAAC;IACvB,SAASzB,OAAO;AACdC,cAAQD,MAAM,mCAAmCA,KAAAA;AACjD,aAAO,CAAC;IACV;EACF;;;;;;EAOA,aAAaiC,YACXxC,iBAOC;AACD,QAAI;AACF,YAAMG,cAAcH,gBAAgBG,YAAW;AAC/C,YAAMsC,iBAAiBzC,gBAAgB0C,kBAAiB;AAExD,YAAMrC,KAAKL,gBAAgBM,YAAW;AACtC,UAAI,CAACH,aAAa;AAChB,eAAO;UACLwC,WAAW;UACXxC,aAAa;UACbI,OAAO;QACT;MACF;AAEA,YAAM+B,UAAU,MAAM,KAAKD,mBAAmBhC,EAAAA;AAE9C,aAAO;QACLsC,WAAW;QACXxC,aAAa;QACbmC;QACAG;MACF;IACF,SAASlC,OAAO;AACd,aAAO;QACLoC,WAAW;QACXxC,aAAa;QACbI,OAAOA,iBAAiBH,QAAQG,MAAMqC,UAAU;MAClD;IACF;EACF;AACF;","names":["Injectable","Inject","drizzle","sql","postgres","DRIZZLE_DATABASE","DATAPAAS_CONFIG","parseConnectionInfo","connectionString","config","maxConnections","idleTimeout","connectionTimeout","ssl","logger","parsedConfigFromUrl","URL","temp","searchParams","delete","toString","error","Error","username","password","hostname","port","pathname","connectionConfig","decodeURIComponent","host","parseInt","max","idle_timeout","connect_timeout","onnotice","console","log","undefined","DrizzleDatabaseManager","db","currentConnectionInfo","isConnected","skipInitDbConnection","config","process","env","DEPRECATED_SKIP_INIT_DB_CONNECTION","onModuleInit","initialize","onModuleDestroy","disconnect","name","connectionString","connectionConfig","parseConnectionInfo","sql","postgres","drizzle","schema","logger","ssl","connectionTimeout","connect_timeout","idleTimeout","idle_timeout","maxConnections","max","error","Error","message","getDatabase","testConnection","execute","console","reconnect","_forceRefresh","getConnectionInfo","isDatabaseConnected","transaction","callback","getConnectionPoolStatus","connectionInfo","Module","Injectable","DataPaasDatabaseService","databaseManager","getDatabase","getDatabaseManager","testConnection","reconnect","forceRefresh","getConnectionInfo","isConnected","isDatabaseConnected","transaction","callback","getConnectionPoolStatus","onModuleDestroy","disconnect","Injectable","Inject","session","SqlExecutionContextMiddleware","config","use","req","_res","next","roleSchema","userContext","roles","userRoles","join","userId","isSystemAccount","userType","sqls","filter","Boolean","session","runWithAuthContext","preSql","verifyDrizzlePatched","postgres","require","ok","getAuthContextStore","runWithAuthContext","Error","err","reason","message","String","DataPaasModule","configure","_consumer","forRoot","options","roleSchema","sslModeRequired","connectionString","url","URL","searchParams","get","config","schema","logger","timeout","maxConnections","idleTimeout","connectionTimeout","ssl","autoContext","providers","provide","DATAPAAS_CONFIG","useValue","DrizzleDatabaseManager","useClass","DataPaasDatabaseService","SqlExecutionContextMiddleware","DRIZZLE_DATABASE","useFactory","manager","initialize","getDatabase","inject","module","exports","global","forRootAsync","asyncProviders","createAsyncProviders","imports","createAsyncConfigProvider","args","normalizeConfig","sql","DatabaseUtils","safeExecute","databaseService","operation","fallback","isConnected","Error","db","getDatabase","error","console","batchExecute","operations","batchSize","results","i","length","batch","slice","batchResults","Promise","all","map","push","executeWithRetry","maxRetries","retryDelay","lastError","attempt","warn","resolve","setTimeout","tableExists","tableName","result","execute","sql","exists","getTableStructure","getDatabaseVersion","version","getConnectionStats","healthCheck","connectionInfo","getConnectionInfo","isHealthy","message"]}
1
+ {"version":3,"sources":["../src/database/drizzle-manager.ts","../src/database/const.ts","../src/utils.ts","../src/database/postgres-proxy.ts","../src/database/database.module.ts","../src/database/database.service.ts","../src/database/sql-exection-context.middleware.ts","../src/database/database-utils.ts"],"sourcesContent":["import { Injectable, OnModuleInit, OnModuleDestroy, Inject } from '@nestjs/common';\nimport { drizzle, type PostgresJsDatabase } from 'drizzle-orm/postgres-js';\nimport { sql } from 'drizzle-orm';\nimport postgres from 'postgres';\nimport { DATAPAAS_CONFIG, DATAPAAS_LOGGER_SERVICE } from './const';\nimport { Observable } from '@lark-apaas/nestjs-observable';\nimport { RequestContextService } from '@lark-apaas/nestjs-common';\n\nimport { type DataPaasConfig, type DatabaseConnectionInfo } from '../types';\nimport { parseConnectionInfo } from '../utils';\nimport { genPostgresProxy } from \"./postgres-proxy\";\n@Injectable()\nexport class DrizzleDatabaseManager implements OnModuleInit, OnModuleDestroy {\n private db: PostgresJsDatabase | null = null;\n private currentConnectionInfo: DatabaseConnectionInfo | null = null;\n private isConnected: boolean = false;\n private skipInitDbConnection: boolean = false;\n constructor(\n @Inject(DATAPAAS_CONFIG)\n private readonly config: DataPaasConfig,\n @Inject(DATAPAAS_LOGGER_SERVICE)\n private readonly observable: Observable,\n private readonly requestContext: RequestContextService,\n ) { \n this.skipInitDbConnection = !!process.env.DEPRECATED_SKIP_INIT_DB_CONNECTION;\n }\n\n async onModuleInit() {\n await this.initialize();\n }\n\n async onModuleDestroy() {\n await this.disconnect();\n }\n\n /**\n * 初始化数据库连接\n * @returns Drizzle 数据库实例\n */\n async initialize(): Promise<PostgresJsDatabase> {\n if (this.skipInitDbConnection) {\n this.isConnected = true;\n this.db = {name: 'skipInitDbConnection'} as unknown as PostgresJsDatabase;\n return this.db;\n }\n try {\n const { connectionString, connectionConfig } = parseConnectionInfo(this.config.connectionString, this.config);\n const baseSql = postgres(connectionString, connectionConfig);\n const sqlProxy = genPostgresProxy(baseSql, this.observable, this.requestContext);\n // 创建 Drizzle 实例\n this.db = drizzle(sqlProxy, { schema: this.config.schema, logger: false });\n this.currentConnectionInfo = {\n connectionString,\n connectionConfig: {\n ssl: connectionConfig.ssl,\n connectionTimeout: connectionConfig.connect_timeout,\n idleTimeout: connectionConfig.idle_timeout,\n maxConnections: connectionConfig.max,\n },\n };\n this.isConnected = true;\n return this.db;\n } catch (error) {\n this.isConnected = false;\n throw new Error(`Failed to initialize database connection: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n }\n\n /**\n * 获取数据库实例\n * @returns Drizzle 数据库实例\n */\n getDatabase(): PostgresJsDatabase {\n if (!this.db || !this.isConnected) {\n throw new Error('Database not initialized. Call initialize() first.');\n }\n return this.db;\n }\n\n /**\n * 测试数据库连接\n * @returns 连接是否正常\n */\n async testConnection(): Promise<boolean> {\n if (!this.db) {\n return false;\n }\n\n try {\n await this.db.execute(sql`SELECT 1`);\n return true;\n } catch (error) {\n console.error('Database connection test failed:', error);\n this.isConnected = false;\n return false;\n }\n }\n\n /**\n * 重新连接数据库\n * @param forceRefresh 是否强制刷新连接信息\n * @returns 新的数据库实例\n */\n async reconnect(_forceRefresh: boolean = false): Promise<PostgresJsDatabase> {\n await this.disconnect();\n return this.initialize();\n }\n\n /**\n * 断开数据库连接\n */\n async disconnect(): Promise<void> {\n if (this.db) {\n try {\n // postgres-js 会自动处理连接关闭\n this.db = null;\n this.isConnected = false;\n this.currentConnectionInfo = null;\n } catch (error) {\n console.error('Error disconnecting from database:', error);\n }\n }\n }\n\n /**\n * 获取当前连接信息\n * @returns 当前连接信息\n */\n getConnectionInfo(): DatabaseConnectionInfo | null {\n return this.currentConnectionInfo;\n }\n\n /**\n * 检查连接状态\n * @returns 是否已连接\n */\n isDatabaseConnected(): boolean {\n return this.isConnected;\n }\n\n\n /**\n * 开始事务\n * @param callback 事务回调函数\n * @returns 事务结果\n */\n async transaction<T>(callback: (tx: PostgresJsDatabase) => Promise<T>): Promise<T> {\n const db = this.getDatabase();\n return db.transaction(callback);\n }\n\n /**\n * 获取连接池状态\n * @returns 连接池状态信息\n */\n getConnectionPoolStatus(): { isConnected: boolean; connectionInfo: DatabaseConnectionInfo | null } {\n return {\n isConnected: this.isConnected,\n connectionInfo: this.currentConnectionInfo,\n };\n }\n}","export const DRIZZLE_DATABASE = 'DRIZZLE_DATABASE';\nexport const DATAPAAS_CONFIG = 'DATAPAAS_CONFIG';\nexport const DATAPAAS_LOGGER_SERVICE = Symbol('DATAPAAS_LOGGER_SERVICE');","import type postgres from 'postgres';\nimport { type Logger as DrizzleLogger } from 'drizzle-orm';\nimport { PostgresOptions } from './types';\n\ninterface ConnectionConfig {\n maxConnections?: number;\n idleTimeout?: number;\n connectionTimeout?: number;\n ssl?: PostgresOptions['ssl'];\n logger?: boolean | DrizzleLogger;\n}\nexport function parseConnectionInfo(connectionString: string, config?: ConnectionConfig) {\n const { maxConnections, idleTimeout, connectionTimeout, ssl, logger } = config || {};\n // 创建 postgres 连接\n let parsedConfigFromUrl: URL;\n try {\n parsedConfigFromUrl = new URL(connectionString);\n const temp = new URL(connectionString);\n temp.searchParams.delete('schema'); // 移除schema参数,避免 postgres 解析错误\n connectionString = temp.toString();\n } catch (error) {\n throw new Error('Failed to parse connection info');\n }\n const { username, password, hostname, port, pathname } = parsedConfigFromUrl;\n const connectionConfig = {\n username: decodeURIComponent(username),\n password: decodeURIComponent(password),\n host: [hostname] as unknown as string,\n port: [parseInt(port) || 5432] as unknown as number,\n pathname: decodeURIComponent(pathname),\n max: maxConnections || 1,\n idle_timeout: idleTimeout || 20,\n connect_timeout: connectionTimeout || 10,\n ssl,\n onnotice: logger ? console.log : undefined,\n }\n return { connectionString, connectionConfig };\n}","import type postgres from 'postgres';\nimport { Logger } from '@nestjs/common';\nimport { Span, Observable } from '@lark-apaas/nestjs-observable';\nimport { RequestContextService } from '@lark-apaas/nestjs-common';\n\nconst nestLogger = new Logger('Database');\n\n/**\n * 包装 postgres 实例以记录 SQL 和结果\n */\nexport function genPostgresProxy(sql: postgres.Sql, observable: Observable, requestContext: RequestContextService): postgres.Sql {\n const wrapQuery = <T extends readonly (postgres.Row | undefined)[]>(query: postgres.PendingQuery<T>): postgres.PendingQuery<T> => {\n if (query && typeof query.then === 'function') {\n return new Proxy(query, {\n get(target, prop, receiver) {\n if (prop === 'then') {\n return async (onfulfilled?: (value: postgres.RowList<T>) => unknown, onrejected?: (reason: unknown) => unknown) => {\n const sqlStr = (query as unknown as Record<string, unknown>).strings instanceof Array ? (query as unknown as { strings: string[] }).strings[0] : '';\n const span = observable.startTrace(sqlStr, requestContext?.getContext()?.requestRootSpan as Span);\n\n span.setAttribute(\"module\", \"data\");\n span.setAttribute(\"source_type\", \"platform\");\n\n const start = Date.now();\n try {\n const result = await target;\n const isSetRoleSql = result?.command === 'SET';\n\n // rls SET ROLE 不上报日志\n if (!isSetRoleSql) {\n const duration = Date.now() - start;\n\n const parsedParams = JSON.stringify({ \n operation: result?.command,\n sql: result?.statement?.string,\n duration_ms: duration,\n result_count: result.length ?? 0,\n error_message: ''\n });\n\n nestLogger.log(parsedParams, {\n source_type: 'platform',\n paas_attributes_module: 'data'\n });\n } else {\n observable.dropTrace(span);\n }\n\n span.end();\n return onfulfilled ? onfulfilled(result) : result;\n } catch (error) {\n const duration = Date.now() - start;\n const sqlStr = (query as unknown as Record<string, unknown>).strings instanceof Array ? (query as unknown as { strings: string[] }).strings[0] : '';\n const parsedParams = JSON.stringify({ \n operation: '',\n sql: sqlStr,\n duration_ms: duration,\n result_count: 0,\n error_message: error instanceof Error ? error.message : String(error)\n });\n nestLogger.log(parsedParams, {\n source_type: 'platform',\n paas_attributes_module: 'data'\n });\n\n span.end();\n return onrejected ? onrejected(error) : Promise.reject(error);\n }\n };\n }\n const value = Reflect.get(target, prop, receiver);\n return typeof value === 'function' ? value.bind(receiver) : value;\n },\n }) as postgres.PendingQuery<T>;\n }\n return query;\n };\n\n return new Proxy(sql, {\n apply(target, thisArg, argArray) {\n const query = Reflect.apply(target, thisArg, argArray);\n return wrapQuery(query);\n },\n get(target, prop, receiver) {\n const value = Reflect.get(target, prop, receiver);\n if (prop === 'begin' && typeof value === 'function') {\n return <T>(arg: string | ((tx: postgres.TransactionSql) => T | Promise<T>), cb?: (tx: postgres.TransactionSql) => T | Promise<T>) => {\n if (typeof arg === 'function') {\n return value.call(target, (tx: postgres.TransactionSql) => arg(genPostgresProxy(tx as unknown as postgres.Sql, observable, requestContext) as unknown as postgres.TransactionSql));\n }\n if (typeof cb === 'function') {\n return value.call(target, arg, (tx: postgres.TransactionSql) => cb(genPostgresProxy(tx as unknown as postgres.Sql, observable, requestContext) as unknown as postgres.TransactionSql));\n }\n return value.call(target, arg);\n };\n }\n if (prop === 'unsafe' && typeof value === 'function') {\n return <T extends readonly (postgres.Row | undefined)[] = postgres.Row[]>(queryStr: string, args?: unknown[], options?: postgres.UnsafeQueryOptions): postgres.PendingQuery<T> => {\n const query = value.call(target, queryStr, args, options) as postgres.PendingQuery<T>;\n return wrapQuery(query);\n };\n }\n return typeof value === 'function' ? value.bind(receiver) : value;\n },\n }) as postgres.Sql;\n}","import {\n Module,\n DynamicModule,\n Provider,\n MiddlewareConsumer,\n InjectionToken,\n ModuleMetadata,\n} from '@nestjs/common';\nimport { DrizzleDatabaseManager } from './drizzle-manager';\nimport { DataPaasDatabaseService } from './database.service';\nimport { SqlExecutionContextMiddleware } from './sql-exection-context.middleware';\nimport { type DataPaasConfig } from '@/types';\nimport { DATAPAAS_CONFIG, DRIZZLE_DATABASE, DATAPAAS_LOGGER_SERVICE } from './const';\nexport { type PostgresJsDatabase } from 'drizzle-orm/postgres-js';\nimport { RequestContextService, OBSERVABLE_SERVICE, ObservableService } from '@lark-apaas/nestjs-common';\nimport { Observable } from '@lark-apaas/nestjs-observable';\n\nexport interface DataPaasModuleOptions extends DataPaasConfig {}\n\n/**\n * 异步配置选项\n */\nexport interface DataPaasModuleAsyncOptions {\n /**\n * 需要导入的模块(例如 ConfigModule)\n */\n imports?: ModuleMetadata['imports'];\n /**\n * 使用工厂函数创建配置\n */\n useFactory?: (...args: unknown[]) => Promise<DataPaasConfig> | DataPaasConfig;\n /**\n * 工厂函数需要注入的依赖\n */\n inject?: InjectionToken[];\n}\n\nfunction verifyDrizzlePatched(): void {\n try {\n // 直接加载被 patch 的 CJS 模块并检查导出是否存在\n // 注意:此路径与补丁文件一致:drizzle-orm/postgres-js/session.cjs\n // 若未来包结构变化,请同步更新补丁与此校验\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const postgres = require('drizzle-orm/postgres-js');\n const ok =\n postgres &&\n typeof postgres.getAuthContextStore === 'function' &&\n typeof postgres.runWithAuthContext === 'function';\n if (!ok) {\n throw new Error(\n 'drizzle-orm 未检测到补丁导出:getAuthContextStore/runWithAuthContext',\n );\n }\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err);\n throw new Error(`drizzle-orm 补丁未生效或版本不匹配:${reason}`);\n }\n}\n\n// 在模块初始化阶段进行一次 drizzle-orm 补丁自检\nverifyDrizzlePatched();\n\n@Module({\n providers: [{\n provide: DATAPAAS_LOGGER_SERVICE,\n useFactory: (observable: ObservableService | null, rtx: RequestContextService) => {\n return observable ?? new Observable(rtx);\n },\n inject: [{\n token: OBSERVABLE_SERVICE,\n optional: true,\n }, RequestContextService],\n }],\n})\nexport class DataPaasModule {\n configure(_consumer: MiddlewareConsumer) {}\n /**\n * 注册数据平台模块(同步方式)\n * @param options 模块配置选项\n * @returns 动态模块\n */\n static forRoot(options: DataPaasConfig): DynamicModule {\n let roleSchema = '';\n let sslModeRequired = false;\n if (options.connectionString) {\n try {\n const url = new URL(options.connectionString);\n\n roleSchema = url.searchParams.get(\n 'schema'\n ) as string;\n sslModeRequired = url.searchParams.get('sslmode') === \"require\";\n } catch (err) {\n roleSchema = '';\n }\n }\n const config: DataPaasConfig = {\n connectionString: options.connectionString,\n schema: options.schema,\n logger: options.logger || false,\n timeout: options.timeout || 10000,\n maxConnections: options.maxConnections || 1,\n idleTimeout: options.idleTimeout || 20,\n connectionTimeout: options.connectionTimeout || 10,\n ssl: options.ssl || (sslModeRequired ? 'require' : false),\n autoContext: options.autoContext == null ? true : !!options.autoContext,\n roleSchema,\n };\n\n const providers: Provider[] = [\n // 配置提供者 - 使用 useValue\n {\n provide: DATAPAAS_CONFIG,\n useValue: config,\n },\n // 数据库管理器 - 使用 useClass,依赖注入连接服务和配置服务\n {\n provide: DrizzleDatabaseManager,\n useClass: DrizzleDatabaseManager,\n },\n // 数据库服务 - 使用 useClass,依赖注入管理器\n {\n provide: DataPaasDatabaseService,\n useClass: DataPaasDatabaseService,\n },\n {\n provide: SqlExecutionContextMiddleware,\n useClass: SqlExecutionContextMiddleware,\n },\n // Drizzle 数据库实例 - 使用 useFactory 获取管理器中的数据库实例\n {\n provide: DRIZZLE_DATABASE,\n useFactory: async (manager: DrizzleDatabaseManager) => {\n await manager.initialize();\n return manager.getDatabase();\n },\n inject: [DrizzleDatabaseManager],\n },\n ];\n\n return {\n module: DataPaasModule,\n providers,\n exports: [\n DrizzleDatabaseManager,\n DataPaasDatabaseService,\n SqlExecutionContextMiddleware,\n DRIZZLE_DATABASE,\n DATAPAAS_CONFIG,\n ],\n global: true,\n };\n }\n\n /**\n * 注册数据平台模块(异步方式)\n * 支持从 ConfigModule 等异步源获取配置\n * @param options 异步配置选项\n * @returns 动态模块\n * @example\n * ```typescript\n * DataPaasModule.forRootAsync({\n * imports: [ConfigModule],\n * useFactory: async (configService: ConfigService) => ({\n * connectionString: configService.get('DATABASE_URL'),\n * }),\n * inject: [ConfigService],\n * })\n * ```\n */\n static forRootAsync(options: DataPaasModuleAsyncOptions): DynamicModule {\n const asyncProviders = this.createAsyncProviders(options);\n\n const providers: Provider[] = [\n ...asyncProviders,\n // 数据库管理器 - 使用 useClass,依赖注入连接服务和配置服务\n {\n provide: DrizzleDatabaseManager,\n useClass: DrizzleDatabaseManager,\n },\n // 数据库服务 - 使用 useClass,依赖注入管理器\n {\n provide: DataPaasDatabaseService,\n useClass: DataPaasDatabaseService,\n },\n {\n provide: SqlExecutionContextMiddleware,\n useClass: SqlExecutionContextMiddleware,\n },\n // Drizzle 数据库实例 - 使用 useFactory 获取管理器中的数据库实例\n {\n provide: DRIZZLE_DATABASE,\n useFactory: async (manager: DrizzleDatabaseManager) => {\n await manager.initialize();\n return manager.getDatabase();\n },\n inject: [DrizzleDatabaseManager],\n },\n ];\n\n return {\n module: DataPaasModule,\n imports: options.imports || [],\n providers,\n exports: [\n DrizzleDatabaseManager,\n DataPaasDatabaseService,\n SqlExecutionContextMiddleware,\n DRIZZLE_DATABASE,\n DATAPAAS_CONFIG,\n ],\n global: true,\n };\n }\n\n /**\n * 创建异步配置 providers\n */\n private static createAsyncProviders(\n options: DataPaasModuleAsyncOptions\n ): Provider[] {\n if (options.useFactory) {\n return [this.createAsyncConfigProvider(options)];\n }\n\n throw new Error('DataPaasModule.forRootAsync 需要指定 useFactory');\n }\n\n /**\n * 创建异步配置 provider\n */\n private static createAsyncConfigProvider(\n options: DataPaasModuleAsyncOptions\n ): Provider {\n if (options.useFactory) {\n return {\n provide: DATAPAAS_CONFIG,\n useFactory: async (...args: unknown[]) => {\n const config = await options.useFactory!(...args);\n return this.normalizeConfig(config);\n },\n inject: options.inject || [],\n };\n }\n\n throw new Error('Invalid async options');\n }\n\n /**\n * 标准化配置,设置默认值\n */\n private static normalizeConfig(config: DataPaasConfig): DataPaasConfig {\n let roleSchema = '';\n let sslModeRequired = false;\n if (config.connectionString) {\n try {\n const url = new URL(config.connectionString);\n roleSchema = url.searchParams.get(\n 'schema'\n ) as string;\n sslModeRequired = url.searchParams.get('sslmode') === \"require\";\n } catch (err) {\n roleSchema = '';\n }\n }\n return {\n connectionString: config.connectionString,\n schema: config.schema,\n logger: config.logger || false,\n timeout: config.timeout || 10000,\n maxConnections: config.maxConnections || 1,\n idleTimeout: config.idleTimeout || 20,\n connectionTimeout: config.connectionTimeout || 10,\n ssl: config.ssl || (sslModeRequired ? 'require' : false),\n autoContext: config.autoContext == null ? true : !!config.autoContext,\n roleSchema,\n };\n }\n}\n","import { Injectable, OnModuleDestroy } from '@nestjs/common';\nimport { type PostgresJsDatabase } from 'drizzle-orm/postgres-js';\nimport { DrizzleDatabaseManager } from './drizzle-manager';\nimport { DatabaseConnectionInfo } from '../types';\n\n@Injectable()\nexport class DataPaasDatabaseService implements OnModuleDestroy {\n constructor(\n private readonly databaseManager: DrizzleDatabaseManager,\n ) {}\n\n /**\n * 获取 Drizzle 数据库实例\n * @returns Drizzle 数据库实例\n */\n getDatabase(): PostgresJsDatabase {\n return this.databaseManager.getDatabase();\n }\n\n /**\n * 获取数据库管理器\n * @returns 数据库管理器实例\n */\n getDatabaseManager(): DrizzleDatabaseManager {\n return this.databaseManager;\n }\n\n\n /**\n * 测试数据库连接\n * @returns 连接是否正常\n */\n async testConnection(): Promise<boolean> {\n return this.databaseManager.testConnection();\n }\n\n /**\n * 重新连接数据库\n * @param forceRefresh 是否强制刷新连接信息\n * @returns 新的数据库实例\n */\n async reconnect(forceRefresh: boolean = false): Promise<PostgresJsDatabase> {\n return this.databaseManager.reconnect(forceRefresh);\n }\n\n /**\n * 获取当前连接信息\n * @returns 当前连接信息\n */\n getConnectionInfo(): DatabaseConnectionInfo | null {\n return this.databaseManager.getConnectionInfo();\n }\n\n /**\n * 检查连接状态\n * @returns 是否已连接\n */\n isConnected(): boolean {\n return this.databaseManager.isDatabaseConnected();\n }\n\n /**\n * 开始事务\n * @param callback 事务回调函数\n * @returns 事务结果\n */\n async transaction<T>(callback: (tx: PostgresJsDatabase) => Promise<T>): Promise<T> {\n return this.databaseManager.transaction(callback);\n }\n\n /**\n * 获取连接池状态\n * @returns 连接池状态信息\n */\n getConnectionPoolStatus(): { isConnected: boolean; connectionInfo: DatabaseConnectionInfo | null } {\n return this.databaseManager.getConnectionPoolStatus();\n }\n\n\n /**\n * 模块销毁时断开数据库连接\n */\n async onModuleDestroy(): Promise<void> {\n await this.databaseManager.disconnect();\n }\n}\n","import { Injectable, NestMiddleware, Inject } from '@nestjs/common';\nimport { Request, Response, NextFunction } from 'express';\nimport * as session from 'drizzle-orm/postgres-js';\nimport { DATAPAAS_CONFIG } from './const';\nimport { type DataPaasConfig } from '../types';\n\ninterface UserContext {\n userId?: string;\n tenantId?: number;\n appId?: string;\n // 用户角色(如果有)\n userRoles?: string[];\n // 是否为系统账号\n isSystemAccount: boolean;\n // 用户类型\n userType?: string;\n}\n\n@Injectable()\nexport class SqlExecutionContextMiddleware implements NestMiddleware {\n constructor(\n @Inject(DATAPAAS_CONFIG)\n private readonly config: DataPaasConfig,\n ) {}\n\n use(req: Request, _res: Response, next: NextFunction) {\n const roleSchema = this.config.roleSchema ?? '';\n const userContext =\n (req as unknown as { userContext: UserContext }).userContext || {};\n const roles = (userContext.userRoles || []).join(',');\n const userId = userContext.userId;\n const isSystemAccount = userContext.isSystemAccount;\n const userType = userContext.userType;\n const sqls = [\n // 设置用户 ID, 匿名用户时设置为空字符串\n userId\n ? `SET LOCAL app.user_id = '${userId}'`\n : `SET LOCAL app.user_id = ''`,\n // 系统用户设置为service_role, 登录用户设置为 authenticated_xxx 角色,匿名用户设置为 anon_xxx 角色\n isSystemAccount ? `SET LOCAL ROLE 'service_role_${roleSchema}'` : (\n userId\n ? `SET LOCAL ROLE 'authenticated_${roleSchema}'`\n : `SET LOCAL ROLE 'anon_${roleSchema}'`),\n // 自定义角色\n roles && `SET LOCAL app.role_ids = '${roles}'`,\n // 用户类型\n userType\n ? `SET LOCAL app.user_type = '${userType}'`\n : `SET LOCAL app.user_type = ''`,\n ]\n .filter(Boolean)\n .join(';');\n\n // 需要确认角色设置是否对后续 SQL 执行有影响,预期是只影响当前会话\n session.runWithAuthContext({ preSql: sqls }, () => {\n next();\n });\n }\n}\n","import { type PostgresJsDatabase } from 'drizzle-orm/postgres-js';\nimport { sql } from 'drizzle-orm';\n\nimport { DataPaasDatabaseService } from './database.service';\n\n/**\n * 数据库工具函数集合\n */\nexport class DatabaseUtils {\n /**\n * 安全执行数据库操作\n * @param databaseService 数据库服务实例\n * @param operation 数据库操作函数\n * @param fallback 失败时的回退值\n * @returns 操作结果或回退值\n */\n static async safeExecute<T>(\n databaseService: DataPaasDatabaseService,\n operation: (db: PostgresJsDatabase) => Promise<T>,\n fallback?: T\n ): Promise<T | undefined> {\n try {\n if (!databaseService.isConnected()) {\n throw new Error('Database not connected');\n }\n \n const db = databaseService.getDatabase();\n return await operation(db);\n } catch (error) {\n console.error('Database operation failed:', error);\n return fallback;\n }\n }\n\n /**\n * 批量执行数据库操作\n * @param databaseService 数据库服务实例\n * @param operations 操作数组\n * @param batchSize 批处理大小\n * @returns 所有操作的结果\n */\n static async batchExecute<T>(\n databaseService: DataPaasDatabaseService,\n operations: Array<(db: PostgresJsDatabase) => Promise<T>>,\n batchSize: number = 10\n ): Promise<T[]> {\n const results: T[] = [];\n const db = databaseService.getDatabase();\n\n for (let i = 0; i < operations.length; i += batchSize) {\n const batch = operations.slice(i, i + batchSize);\n const batchResults = await Promise.all(\n batch.map(operation => operation(db))\n );\n results.push(...batchResults);\n }\n\n return results;\n }\n\n /**\n * 执行带重试的数据库操作\n * @param databaseService 数据库服务实例\n * @param operation 数据库操作函数\n * @param maxRetries 最大重试次数\n * @param retryDelay 重试延迟(毫秒)\n * @returns 操作结果\n */\n static async executeWithRetry<T>(\n databaseService: DataPaasDatabaseService,\n operation: (db: PostgresJsDatabase) => Promise<T>,\n maxRetries: number = 3,\n retryDelay: number = 1000\n ): Promise<T> {\n let lastError: Error;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n const db = databaseService.getDatabase();\n return await operation(db);\n } catch (error) {\n lastError = error as Error;\n \n if (attempt === maxRetries) {\n break;\n }\n\n console.warn(`Database operation failed (attempt ${attempt + 1}/${maxRetries + 1}):`, error);\n \n // 等待后重试\n await new Promise(resolve => setTimeout(resolve, retryDelay * (attempt + 1)));\n }\n }\n\n throw lastError!;\n }\n\n /**\n * 检查表是否存在\n * @param databaseService 数据库服务实例\n * @param tableName 表名\n * @returns 表是否存在\n */\n static async tableExists(\n db: PostgresJsDatabase,\n tableName: string\n ): Promise<boolean> {\n try {\n const result = await db.execute(\n sql`SELECT EXISTS (\n SELECT FROM information_schema.tables \n WHERE table_schema = 'public' \n AND table_name = ${tableName}\n )`\n );\n \n return result[0]?.exists as boolean || false;\n } catch (error) {\n console.error('Failed to check table existence:', error);\n return false;\n }\n }\n\n /**\n * 获取表结构信息\n * @param databaseService 数据库服务实例\n * @param tableName 表名\n * @returns 表结构信息\n */\n static async getTableStructure(\n db: PostgresJsDatabase,\n tableName: string\n ): Promise<any[]> {\n try {\n const result = await db.execute(\n sql`SELECT \n column_name,\n data_type,\n is_nullable,\n column_default,\n character_maximum_length\n FROM information_schema.columns \n WHERE table_schema = 'public' \n AND table_name = ${tableName}\n ORDER BY ordinal_position`,\n );\n \n return result;\n } catch (error) {\n console.error('Failed to get table structure:', error);\n return [];\n }\n }\n\n /**\n * 获取数据库版本信息\n * @param databaseService 数据库服务实例\n * @returns 数据库版本\n */\n static async getDatabaseVersion(\n db: PostgresJsDatabase\n ): Promise<string> {\n try {\n const result = await db.execute(sql`SELECT version()`);\n return result[0]?.version as string || 'Unknown';\n } catch (error) {\n console.error('Failed to get database version:', error);\n return 'Unknown';\n }\n }\n\n /**\n * 获取连接统计信息\n * @param databaseService 数据库服务实例\n * @returns 连接统计信息\n */\n static async getConnectionStats(\n db: PostgresJsDatabase\n ): Promise<any> {\n try {\n const result = await db.execute(sql`\n SELECT \n count(*) as total_connections,\n count(*) FILTER (WHERE state = 'active') as active_connections,\n count(*) FILTER (WHERE state = 'idle') as idle_connections\n FROM pg_stat_activity \n WHERE datname = current_database()\n `);\n \n return result[0] || {};\n } catch (error) {\n console.error('Failed to get connection stats:', error);\n return {};\n }\n }\n\n /**\n * 健康检查\n * @param databaseService 数据库服务实例\n * @returns 健康状态\n */\n static async healthCheck(\n databaseService: DataPaasDatabaseService\n ): Promise<{\n isHealthy: boolean;\n isConnected: boolean;\n version?: string;\n connectionInfo?: any;\n error?: string;\n }> {\n try {\n const isConnected = databaseService.isConnected();\n const connectionInfo = databaseService.getConnectionInfo();\n\n const db = databaseService.getDatabase();\n if (!isConnected) {\n return {\n isHealthy: false,\n isConnected: false,\n error: 'Database not connected'\n };\n }\n\n const version = await this.getDatabaseVersion(db);\n \n return {\n isHealthy: true,\n isConnected: true,\n version,\n connectionInfo\n };\n } catch (error) {\n return {\n isHealthy: false,\n isConnected: false,\n error: error instanceof Error ? error.message : 'Unknown error'\n };\n }\n }\n}\n"],"mappings":"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","names":["Injectable","Inject","drizzle","sql","postgres","DRIZZLE_DATABASE","DATAPAAS_CONFIG","DATAPAAS_LOGGER_SERVICE","Symbol","Observable","RequestContextService","parseConnectionInfo","connectionString","config","maxConnections","idleTimeout","connectionTimeout","ssl","logger","parsedConfigFromUrl","URL","temp","searchParams","delete","toString","error","Error","username","password","hostname","port","pathname","connectionConfig","decodeURIComponent","host","parseInt","max","idle_timeout","connect_timeout","onnotice","console","log","undefined","Logger","nestLogger","Logger","genPostgresProxy","sql","observable","requestContext","wrapQuery","query","then","Proxy","get","target","prop","receiver","onfulfilled","onrejected","sqlStr","strings","Array","span","startTrace","getContext","requestRootSpan","setAttribute","start","Date","now","result","isSetRoleSql","command","duration","parsedParams","JSON","stringify","operation","statement","string","duration_ms","result_count","length","error_message","log","source_type","paas_attributes_module","dropTrace","end","error","Error","message","String","Promise","reject","value","Reflect","bind","apply","thisArg","argArray","arg","cb","call","tx","queryStr","args","options","DrizzleDatabaseManager","db","currentConnectionInfo","isConnected","skipInitDbConnection","config","observable","requestContext","process","env","DEPRECATED_SKIP_INIT_DB_CONNECTION","onModuleInit","initialize","onModuleDestroy","disconnect","name","connectionString","connectionConfig","parseConnectionInfo","baseSql","postgres","sqlProxy","genPostgresProxy","drizzle","schema","logger","ssl","connectionTimeout","connect_timeout","idleTimeout","idle_timeout","maxConnections","max","error","Error","message","getDatabase","testConnection","execute","sql","console","reconnect","_forceRefresh","getConnectionInfo","isDatabaseConnected","transaction","callback","getConnectionPoolStatus","connectionInfo","Module","Injectable","DataPaasDatabaseService","databaseManager","getDatabase","getDatabaseManager","testConnection","reconnect","forceRefresh","getConnectionInfo","isConnected","isDatabaseConnected","transaction","callback","getConnectionPoolStatus","onModuleDestroy","disconnect","Injectable","Inject","session","SqlExecutionContextMiddleware","config","use","req","_res","next","roleSchema","userContext","roles","userRoles","join","userId","isSystemAccount","userType","sqls","filter","Boolean","session","runWithAuthContext","preSql","RequestContextService","OBSERVABLE_SERVICE","Observable","verifyDrizzlePatched","postgres","require","ok","getAuthContextStore","runWithAuthContext","Error","err","reason","message","String","DataPaasModule","configure","_consumer","forRoot","options","roleSchema","sslModeRequired","connectionString","url","URL","searchParams","get","config","schema","logger","timeout","maxConnections","idleTimeout","connectionTimeout","ssl","autoContext","providers","provide","DATAPAAS_CONFIG","useValue","DrizzleDatabaseManager","useClass","DataPaasDatabaseService","SqlExecutionContextMiddleware","DRIZZLE_DATABASE","useFactory","manager","initialize","getDatabase","inject","module","exports","global","forRootAsync","asyncProviders","createAsyncProviders","imports","createAsyncConfigProvider","args","normalizeConfig","DATAPAAS_LOGGER_SERVICE","observable","rtx","Observable","token","OBSERVABLE_SERVICE","optional","RequestContextService","sql","DatabaseUtils","safeExecute","databaseService","operation","fallback","isConnected","Error","db","getDatabase","error","console","batchExecute","operations","batchSize","results","i","length","batch","slice","batchResults","Promise","all","map","push","executeWithRetry","maxRetries","retryDelay","lastError","attempt","warn","resolve","setTimeout","tableExists","tableName","result","execute","sql","exists","getTableStructure","getDatabaseVersion","version","getConnectionStats","healthCheck","connectionInfo","getConnectionInfo","isHealthy","message"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/nestjs-datapaas",
3
- "version": "1.0.7",
3
+ "version": "1.0.8-alpha.2",
4
4
  "description": "FullStack Nestjs DataPaas",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -65,6 +65,8 @@
65
65
  "typescript": "^5.0.0"
66
66
  },
67
67
  "peerDependencies": {
68
+ "@lark-apaas/nestjs-common": "0.1.2-alpha.1",
69
+ "@lark-apaas/nestjs-observable": "0.0.3-alpha.1",
68
70
  "@nestjs/common": "^10.0.0",
69
71
  "@nestjs/core": "^10.0.0",
70
72
  "drizzle-orm": "0.44.6"
@@ -101,7 +101,7 @@ index dac222a..7708081 100644
101
101
  + if (!fields && !customResultMapper) {
102
102
  + result = await import_tracing.tracer.startActiveSpan("drizzle.driver.execute.main", () => {
103
103
  + return this.queryWithCache(this.queryString, params, async () => {
104
- + return await tx.unsafe(this.queryString, params);
104
+ + return await client.unsafe(this.queryString, params);
105
105
  + });
106
106
  + });
107
107
  + } else {