@russ-b/nestjs-common-tools 2.1.0 → 2.1.1

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/README.md CHANGED
@@ -598,6 +598,32 @@ export class AppModule {}
598
598
 
599
599
  PostgreSQL support is also exposed directly as `createPostgresTypeormOptions`. Its `schema` option is applied both as TypeORM's schema and as `search_path`, and pool options are passed through the `pg` driver via TypeORM's `extra` config.
600
600
 
601
+ For managed PostgreSQL providers that require SSL with a CA certificate, you can pass atomic connection fields and `sslCa`. This avoids `pg` overwriting the explicit `ssl` object when `sslmode` or `sslrootcert` exists in the connection string.
602
+
603
+ ```typescript
604
+ TypeOrmModule.forRootAsync({
605
+ imports: [ConfigModule],
606
+ inject: [ConfigService],
607
+ useFactory: (config: ConfigService) =>
608
+ createTypeOrmOptions({
609
+ type: 'postgres',
610
+ database: {
611
+ host: config.getOrThrow<string>('DB_HOST'),
612
+ port: config.get<number>('DB_PORT'),
613
+ username: config.getOrThrow<string>('DB_USER'),
614
+ password: config.getOrThrow<string>('DB_PASSWORD'),
615
+ database: config.getOrThrow<string>('DB_NAME'),
616
+ },
617
+ sslCa: config.get<string>('DB_CA_CERT'),
618
+ sync: config.get<string>('TYPEORM_SYNC'),
619
+ logging: config.get<string>('TYPEORM_LOGGING'),
620
+ isProduction: config.get<string>('NODE_ENV') === 'production',
621
+ }),
622
+ });
623
+ ```
624
+
625
+ When `sslCa` is used together with `databaseUrl`, SSL-related query params such as `sslmode` and `sslrootcert` are removed from the URL before TypeORM passes the config to `pg`.
626
+
601
627
  For MySQL, use `type: 'mysql'` or call `createMysqlTypeormOptions` directly:
602
628
 
603
629
  ```typescript
@@ -1,9 +1,19 @@
1
1
  import type { TypeOrmModuleOptions } from '@nestjs/typeorm';
2
2
  import { CommonTypeormConfigOptions } from './typeorm-options.util';
3
- export interface PostgresTypeormConfigOptions extends CommonTypeormConfigOptions {
3
+ export interface PostgresTypeormDatabaseConnectionOptions {
4
+ host: string;
5
+ port?: number;
6
+ username: string;
7
+ password: string;
8
+ database: string;
9
+ }
10
+ export interface PostgresTypeormConfigOptions extends Omit<CommonTypeormConfigOptions, 'databaseUrl'> {
4
11
  type?: 'postgres';
5
- appName: string;
12
+ databaseUrl?: string;
13
+ database?: PostgresTypeormDatabaseConnectionOptions;
14
+ appName?: string;
6
15
  schema?: string;
16
+ sslCa?: string;
7
17
  queryTimeout?: number;
8
18
  }
9
19
  export declare function createPostgresTypeormOptions(options: PostgresTypeormConfigOptions): TypeOrmModuleOptions;
@@ -10,9 +10,12 @@ function createPostgresTypeormOptions(options) {
10
10
  queryTimeout: 30_000,
11
11
  ...options,
12
12
  };
13
+ const connectionOptions = createConnectionOptions(resolvedOptions);
14
+ const ssl = createSslOptions(resolvedOptions.sslCa);
13
15
  return {
14
16
  type: 'postgres',
15
- url: encodeURI(resolvedOptions.databaseUrl),
17
+ ...connectionOptions,
18
+ ...(ssl ? { ssl } : {}),
16
19
  autoLoadEntities: true,
17
20
  schema: resolvedOptions.schema,
18
21
  maxQueryExecutionTime: resolvedOptions.maxQueryExecutionTime,
@@ -28,9 +31,41 @@ function createPostgresTypeormOptions(options) {
28
31
  connectionTimeoutMillis: 5000,
29
32
  maxUses: 10000,
30
33
  keepAlive: true,
31
- application_name: resolvedOptions.appName,
34
+ ...(resolvedOptions.appName
35
+ ? { application_name: resolvedOptions.appName }
36
+ : {}),
32
37
  query_timeout: resolvedOptions.queryTimeout,
33
38
  },
34
39
  };
35
40
  }
41
+ function createConnectionOptions(options) {
42
+ if (options.database) {
43
+ return options.database;
44
+ }
45
+ if (!options.databaseUrl) {
46
+ throw new Error('databaseUrl or database connection options must be configured.');
47
+ }
48
+ const databaseUrl = encodeURI(options.databaseUrl);
49
+ return {
50
+ url: options.sslCa
51
+ ? removeConnectionStringSslParams(databaseUrl)
52
+ : databaseUrl,
53
+ };
54
+ }
55
+ function createSslOptions(sslCa) {
56
+ if (!sslCa) {
57
+ return undefined;
58
+ }
59
+ return {
60
+ ca: sslCa.replace(/\\n/g, '\n'),
61
+ rejectUnauthorized: true,
62
+ };
63
+ }
64
+ function removeConnectionStringSslParams(databaseUrl) {
65
+ const parsedUrl = new URL(databaseUrl);
66
+ for (const param of ['ssl', 'sslcert', 'sslkey', 'sslmode', 'sslrootcert']) {
67
+ parsedUrl.searchParams.delete(param);
68
+ }
69
+ return parsedUrl.toString();
70
+ }
36
71
  //# sourceMappingURL=postgres-typeorm-options.factory.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"postgres-typeorm-options.factory.js","sourceRoot":"","sources":["../../../src/typeorm/config/postgres-typeorm-options.factory.ts"],"names":[],"mappings":";;AA2BA,oEA+BC;AA1DD,2CAAwC;AAExC,iEAMgC;AAiBhC,MAAM,MAAM,GAAG,IAAI,eAAM,CAAC,uBAAuB,CAAC,CAAC;AAEnD,SAAgB,4BAA4B,CAC1C,OAAqC;IAErC,MAAM,eAAe,GAAyC;QAC5D,GAAG,8CAAuB;QAC1B,YAAY,EAAE,MAAM;QACpB,GAAG,OAAO;KACX,CAAC;IAEF,OAAO;QACL,IAAI,EAAE,UAAU;QAChB,GAAG,EAAE,SAAS,CAAC,eAAe,CAAC,WAAW,CAAC;QAC3C,gBAAgB,EAAE,IAAI;QACtB,MAAM,EAAE,eAAe,CAAC,MAAM;QAC9B,qBAAqB,EAAE,eAAe,CAAC,qBAAqB;QAC5D,WAAW,EAAE,IAAA,qCAAc,EAAC,eAAe,EAAE,MAAM,CAAC;QACpD,OAAO,EAAE,IAAA,iCAAU,EAAC,eAAe,CAAC,OAAO,CAAC;QAC5C,aAAa,EAAE,CAAC;QAChB,KAAK,EAAE;YACL,OAAO,EAAE,eAAe,CAAC,MAAM;gBAC7B,CAAC,CAAC,kBAAkB,eAAe,CAAC,MAAM,SAAS;gBACnD,CAAC,CAAC,SAAS;YACb,GAAG,EAAE,eAAe,CAAC,cAAc;YACnC,iBAAiB,EAAE,KAAK;YACxB,uBAAuB,EAAE,IAAI;YAC7B,OAAO,EAAE,KAAK;YACd,SAAS,EAAE,IAAI;YACf,gBAAgB,EAAE,eAAe,CAAC,OAAO;YACzC,aAAa,EAAE,eAAe,CAAC,YAAY;SAC5C;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"postgres-typeorm-options.factory.js","sourceRoot":"","sources":["../../../src/typeorm/config/postgres-typeorm-options.factory.ts"],"names":[],"mappings":";;AAuDA,oEAoCC;AA3FD,2CAAwC;AAGxC,iEAKgC;AA6ChC,MAAM,MAAM,GAAG,IAAI,eAAM,CAAC,uBAAuB,CAAC,CAAC;AAEnD,SAAgB,4BAA4B,CAC1C,OAAqC;IAErC,MAAM,eAAe,GAAyC;QAC5D,GAAG,8CAAuB;QAC1B,YAAY,EAAE,MAAM;QACpB,GAAG,OAAO;KACX,CAAC;IACF,MAAM,iBAAiB,GAAG,uBAAuB,CAAC,eAAe,CAAC,CAAC;IACnE,MAAM,GAAG,GAAG,gBAAgB,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IAEpD,OAAO;QACL,IAAI,EAAE,UAAU;QAChB,GAAG,iBAAiB;QACpB,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvB,gBAAgB,EAAE,IAAI;QACtB,MAAM,EAAE,eAAe,CAAC,MAAM;QAC9B,qBAAqB,EAAE,eAAe,CAAC,qBAAqB;QAC5D,WAAW,EAAE,IAAA,qCAAc,EAAC,eAAe,EAAE,MAAM,CAAC;QACpD,OAAO,EAAE,IAAA,iCAAU,EAAC,eAAe,CAAC,OAAO,CAAC;QAC5C,aAAa,EAAE,CAAC;QAChB,KAAK,EAAE;YACL,OAAO,EAAE,eAAe,CAAC,MAAM;gBAC7B,CAAC,CAAC,kBAAkB,eAAe,CAAC,MAAM,SAAS;gBACnD,CAAC,CAAC,SAAS;YACb,GAAG,EAAE,eAAe,CAAC,cAAc;YACnC,iBAAiB,EAAE,KAAK;YACxB,uBAAuB,EAAE,IAAI;YAC7B,OAAO,EAAE,KAAK;YACd,SAAS,EAAE,IAAI;YACf,GAAG,CAAC,eAAe,CAAC,OAAO;gBACzB,CAAC,CAAC,EAAE,gBAAgB,EAAE,eAAe,CAAC,OAAO,EAAE;gBAC/C,CAAC,CAAC,EAAE,CAAC;YACP,aAAa,EAAE,eAAe,CAAC,YAAY;SAC5C;KACF,CAAC;AACJ,CAAC;AAED,SAAS,uBAAuB,CAC9B,OAGC;IAED,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACrB,OAAO,OAAO,CAAC,QAAQ,CAAC;IAC1B,CAAC;IAED,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CACb,gEAAgE,CACjE,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAAG,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAEnD,OAAO;QACL,GAAG,EAAE,OAAO,CAAC,KAAK;YAChB,CAAC,CAAC,+BAA+B,CAAC,WAAW,CAAC;YAC9C,CAAC,CAAC,WAAW;KAChB,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAc;IACtC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO;QACL,EAAE,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC;QAC/B,kBAAkB,EAAE,IAAI;KACzB,CAAC;AACJ,CAAC;AAED,SAAS,+BAA+B,CAAC,WAAmB;IAC1D,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC;IAEvC,KAAK,MAAM,KAAK,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,aAAa,CAAC,EAAE,CAAC;QAC3E,SAAS,CAAC,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvC,CAAC;IAED,OAAO,SAAS,CAAC,QAAQ,EAAE,CAAC;AAC9B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@russ-b/nestjs-common-tools",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "description": "NestJS utility tools",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",