@rineex/pg-slonik 0.4.0 → 0.5.0

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
@@ -4,6 +4,9 @@
4
4
  > connection management with dependency injection, automatic retry logic, and
5
5
  > graceful shutdown handling.
6
6
 
7
+ > See also: [API Reference](./docs/API.md) for formal type and decorator
8
+ > documentation.
9
+
7
10
  [![npm version](https://img.shields.io/npm/v/@rineex/pg-slonik)](https://www.npmjs.com/package/@rineex/pg-slonik)
8
11
  [![License: Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)
9
12
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.9+-blue.svg)](https://www.typescriptlang.org/)
package/dist/index.d.mts CHANGED
@@ -65,4 +65,12 @@ declare class SlonikModule extends SlonikCoreModule implements OnApplicationShut
65
65
  onApplicationShutdown(): Promise<void>;
66
66
  }
67
67
 
68
- export { ASYNC_OPTIONS_TYPE, InjectPool, MODULE_OPTIONS_TOKEN, OPTIONS_TYPE, SlonikCoreModule, SlonikModule };
68
+ /**
69
+ * Builds the Nest injection token for a named Slonik pool.
70
+ *
71
+ * @param name - Connection name (default: DEFAULT_POOL_NAME). Normalized to uppercase in token.
72
+ * @returns Token string, e.g. '__SLONIK_DEFAULT_POOL__'.
73
+ */
74
+ declare const createSlonikToken: (name?: string) => string;
75
+
76
+ export { ASYNC_OPTIONS_TYPE, InjectPool, MODULE_OPTIONS_TOKEN, OPTIONS_TYPE, SlonikCoreModule, SlonikModule, createSlonikToken };
package/dist/index.d.ts CHANGED
@@ -65,4 +65,12 @@ declare class SlonikModule extends SlonikCoreModule implements OnApplicationShut
65
65
  onApplicationShutdown(): Promise<void>;
66
66
  }
67
67
 
68
- export { ASYNC_OPTIONS_TYPE, InjectPool, MODULE_OPTIONS_TOKEN, OPTIONS_TYPE, SlonikCoreModule, SlonikModule };
68
+ /**
69
+ * Builds the Nest injection token for a named Slonik pool.
70
+ *
71
+ * @param name - Connection name (default: DEFAULT_POOL_NAME). Normalized to uppercase in token.
72
+ * @returns Token string, e.g. '__SLONIK_DEFAULT_POOL__'.
73
+ */
74
+ declare const createSlonikToken: (name?: string) => string;
75
+
76
+ export { ASYNC_OPTIONS_TYPE, InjectPool, MODULE_OPTIONS_TOKEN, OPTIONS_TYPE, SlonikCoreModule, SlonikModule, createSlonikToken };
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- var u=Object.defineProperty;var _=Object.getOwnPropertyDescriptor;var D=Object.getOwnPropertyNames,S=Object.getOwnPropertySymbols;var g=Object.prototype.hasOwnProperty,I=Object.prototype.propertyIsEnumerable;var E=(t,o,e)=>o in t?u(t,o,{enumerable:!0,configurable:!0,writable:!0,value:e}):t[o]=e,k=(t,o)=>{for(var e in o||(o={}))g.call(o,e)&&E(t,e,o[e]);if(S)for(var e of S(o))I.call(o,e)&&E(t,e,o[e]);return t};var h=(t,o)=>{for(var e in o)u(t,e,{get:o[e],enumerable:!0})},F=(t,o,e,n)=>{if(o&&typeof o=="object"||typeof o=="function")for(let r of D(o))!g.call(t,r)&&r!==e&&u(t,r,{get:()=>o[r],enumerable:!(n=_(o,r))||n.enumerable});return t};var K=t=>F(u({},"__esModule",{value:!0}),t),y=(t,o,e,n)=>{for(var r=n>1?void 0:n?_(o,e):o,l=t.length-1,s;l>=0;l--)(s=t[l])&&(r=(n?s(o,e,r):s(r))||r);return n&&r&&u(o,e,r),r};var d=(t,o,e)=>new Promise((n,r)=>{var l=a=>{try{i(e.next(a))}catch(c){r(c)}},s=a=>{try{i(e.throw(a))}catch(c){r(c)}},i=a=>a.done?n(a.value):Promise.resolve(a.value).then(l,s);i((e=e.apply(t,o)).next())});var B={};h(B,{ASYNC_OPTIONS_TYPE:()=>G,InjectPool:()=>Y,MODULE_OPTIONS_TOKEN:()=>j,OPTIONS_TYPE:()=>$,SlonikCoreModule:()=>T,SlonikModule:()=>m});module.exports=K(B);var N=require("@nestjs/common");var x="__SLONIK_%s_POOL__",f="DEFAULT";var L=require("@nestjs/common"),P=require("util"),p=require("rxjs"),v=require("slonik");var O=(t=f)=>(0,P.format)(x,t.toUpperCase()),C=new L.Logger("SlonikModule");function M({dsn:t,name:o,options:e}){let n=O(o);return(0,p.lastValueFrom)((0,p.defer)(()=>d(null,null,function*(){let r=yield(0,v.createPool)(t,e);return yield r.connect(()=>Promise.resolve()).then(()=>{C.log(`Connected to database ${n}`)}),r})).pipe(U()))}function U(t=9,o=3e3,e=f,n=!1,r){return l=>l.pipe((0,p.retry)({count:t,delay:(s,i)=>{if(r&&!r(s))return(0,p.throwError)(()=>s);let a=e===f?"":` (${e})`,c=s instanceof Error?s.message:String(s),b=n?` Message: ${c}.`:"";return C.error((0,P.format)("unable to connect to the database#%s.%s Retrying (%s)%s",a,b,i,b?"":` Error: ${c}`)),(0,p.of)(null).pipe((0,p.delay)(o))}}))}function Y(t=f){return(0,N.Inject)(O(t))}var A=require("@nestjs/common");var w=require("@nestjs/common");var{ConfigurableModuleClass:T,MODULE_OPTIONS_TOKEN:j,OPTIONS_TYPE:$,ASYNC_OPTIONS_TYPE:G}=new w.ConfigurableModuleBuilder().setExtras({isGlobal:!0},(t,o)=>k({global:o.isGlobal},t)).build();var m=class extends T{static register(o){var l,s;let{connections:e}=o,n=super.register(o);(l=n.providers)!=null||(n.providers=[]),(s=n.exports)!=null||(n.exports=[]);let r=e.map(i=>({provide:O(i.name),useFactory:()=>d(this,null,function*(){let a=yield M({dsn:i.dsn,options:i.options,name:i.name});return this.pools.set(i.name,a),a})}));return n.providers.push(...r),n.exports.push(...e.map(i=>O(i.name))),n}onApplicationShutdown(){return d(this,null,function*(){yield Promise.allSettled(Array.from(m.pools.values()).map(o=>o.end()))})}};m.pools=new Map,m=y([(0,A.Module)({})],m);0&&(module.exports={ASYNC_OPTIONS_TYPE,InjectPool,MODULE_OPTIONS_TOKEN,OPTIONS_TYPE,SlonikCoreModule,SlonikModule});
1
+ var u=Object.defineProperty;var E=Object.getOwnPropertyDescriptor;var D=Object.getOwnPropertyNames,S=Object.getOwnPropertySymbols;var _=Object.prototype.hasOwnProperty,I=Object.prototype.propertyIsEnumerable;var k=(t,o,e)=>o in t?u(t,o,{enumerable:!0,configurable:!0,writable:!0,value:e}):t[o]=e,g=(t,o)=>{for(var e in o||(o={}))_.call(o,e)&&k(t,e,o[e]);if(S)for(var e of S(o))I.call(o,e)&&k(t,e,o[e]);return t};var h=(t,o)=>{for(var e in o)u(t,e,{get:o[e],enumerable:!0})},F=(t,o,e,n)=>{if(o&&typeof o=="object"||typeof o=="function")for(let r of D(o))!_.call(t,r)&&r!==e&&u(t,r,{get:()=>o[r],enumerable:!(n=E(o,r))||n.enumerable});return t};var K=t=>F(u({},"__esModule",{value:!0}),t),x=(t,o,e,n)=>{for(var r=n>1?void 0:n?E(o,e):o,l=t.length-1,i;l>=0;l--)(i=t[l])&&(r=(n?i(o,e,r):i(r))||r);return n&&r&&u(o,e,r),r};var d=(t,o,e)=>new Promise((n,r)=>{var l=a=>{try{s(e.next(a))}catch(f){r(f)}},i=a=>{try{s(e.throw(a))}catch(f){r(f)}},s=a=>a.done?n(a.value):Promise.resolve(a.value).then(l,i);s((e=e.apply(t,o)).next())});var B={};h(B,{ASYNC_OPTIONS_TYPE:()=>G,InjectPool:()=>Y,MODULE_OPTIONS_TOKEN:()=>j,OPTIONS_TYPE:()=>$,SlonikCoreModule:()=>T,SlonikModule:()=>c,createSlonikToken:()=>m});module.exports=K(B);var N=require("@nestjs/common");var y="__SLONIK_%s_POOL__",O="DEFAULT";var L=require("@nestjs/common"),P=require("util"),p=require("rxjs"),v=require("slonik");var m=(t=O)=>(0,P.format)(y,t.toUpperCase()),C=new L.Logger("SlonikModule");function M({dsn:t,name:o,options:e}){let n=m(o);return(0,p.lastValueFrom)((0,p.defer)(()=>d(null,null,function*(){let r=yield(0,v.createPool)(t,e);return yield r.connect(()=>Promise.resolve()).then(()=>{C.log(`Connected to database ${n}`)}),r})).pipe(U()))}function U(t=9,o=3e3,e=O,n=!1,r){return l=>l.pipe((0,p.retry)({count:t,delay:(i,s)=>{if(r&&!r(i))return(0,p.throwError)(()=>i);let a=e===O?"":` (${e})`,f=i instanceof Error?i.message:String(i),b=n?` Message: ${f}.`:"";return C.error((0,P.format)("unable to connect to the database#%s.%s Retrying (%s)%s",a,b,s,b?"":` Error: ${f}`)),(0,p.of)(null).pipe((0,p.delay)(o))}}))}function Y(t=O){return(0,N.Inject)(m(t))}var A=require("@nestjs/common");var w=require("@nestjs/common");var{ConfigurableModuleClass:T,MODULE_OPTIONS_TOKEN:j,OPTIONS_TYPE:$,ASYNC_OPTIONS_TYPE:G}=new w.ConfigurableModuleBuilder().setExtras({isGlobal:!0},(t,o)=>g({global:o.isGlobal},t)).build();var c=class extends T{static register(o){var l,i;let{connections:e}=o,n=super.register(o);(l=n.providers)!=null||(n.providers=[]),(i=n.exports)!=null||(n.exports=[]);let r=e.map(s=>({provide:m(s.name),useFactory:()=>d(this,null,function*(){let a=yield M({dsn:s.dsn,options:s.options,name:s.name});return this.pools.set(s.name,a),a})}));return n.providers.push(...r),n.exports.push(...e.map(s=>m(s.name))),n}onApplicationShutdown(){return d(this,null,function*(){yield Promise.allSettled(Array.from(c.pools.values()).map(o=>o.end()))})}};c.pools=new Map,c=x([(0,A.Module)({})],c);0&&(module.exports={ASYNC_OPTIONS_TYPE,InjectPool,MODULE_OPTIONS_TOKEN,OPTIONS_TYPE,SlonikCoreModule,SlonikModule,createSlonikToken});
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/slonik.decorator.ts","../src/constants/index.ts","../src/slonik.util.ts","../src/slonik.module.ts","../src/slonik.module-definition.ts"],"sourcesContent":["export * from './slonik.decorator';\nexport * from './slonik.module';\nexport * from './slonik.module-definition';\n","import { Inject } from '@nestjs/common';\n\nimport { DEFAULT_POOL_NAME } from './constants';\nimport { createSlonikToken } from './slonik.util';\n\n/**\n * Parameter decorator that injects the Slonik DatabasePool for the given connection name.\n *\n * @param name - Connection name (default: 'DEFAULT'). Must match a name in SlonikModule.register().\n * @returns Nest parameter decorator that injects DatabasePool.\n *\n * @example\n * constructor(@InjectPool() private readonly pool: DatabasePool) {}\n * constructor(@InjectPool('replica') private readonly replica: DatabasePool) {}\n */\nexport function InjectPool(name = DEFAULT_POOL_NAME) {\n return Inject(createSlonikToken(name));\n}\n","/**\n * The token for the Slonik pool\n * @example `createSlonikToken('DEFAULT')` will return '__SLONIK_DEFAULT_POOL__'\n */\nexport const SLONIK_POOL_TOKEN = '__SLONIK_%s_POOL__';\n\n/**\n * The default name for the Slonik pool\n */\nexport const DEFAULT_POOL_NAME = 'DEFAULT';\n","import type { Observable } from 'rxjs';\nimport type { DatabasePool } from 'slonik';\n\nimport { Logger } from '@nestjs/common';\nimport { format } from 'node:util';\nimport { defer, delay, lastValueFrom, of, retry, throwError } from 'rxjs';\nimport { createPool } from 'slonik';\n\nimport type { SlonikConnectionConfig } from './slonik.interface';\n\nimport { DEFAULT_POOL_NAME, SLONIK_POOL_TOKEN } from './constants';\n\n/**\n * Builds the Nest injection token for a named Slonik pool.\n *\n * @param name - Connection name (default: DEFAULT_POOL_NAME). Normalized to uppercase in token.\n * @returns Token string, e.g. '__SLONIK_DEFAULT_POOL__'.\n */\nexport const createSlonikToken = (name: string = DEFAULT_POOL_NAME) =>\n format(SLONIK_POOL_TOKEN, name.toUpperCase());\n\nconst logger = new Logger('SlonikModule');\n\n/**\n * Creates a Slonik pool, verifies connectivity with pool.connect(), and retries on failure.\n * Options (including interceptors) are passed through to createPool.\n *\n * @param config - Connection config (name, dsn, optional options).\n * @returns Promise resolving to the Slonik DatabasePool.\n * @throws If connection or verification fails after all retries.\n */\nexport function createSlonikConnection({\n dsn,\n name,\n options,\n}: SlonikConnectionConfig): Promise<DatabasePool> {\n const token = createSlonikToken(name);\n\n return lastValueFrom(\n defer(async () => {\n const pool = await createPool(dsn, options);\n\n await pool\n .connect(() => Promise.resolve())\n .then(() => {\n logger.log(`Connected to database ${token}`);\n });\n return pool;\n }).pipe(handleRetry()),\n );\n}\n\n/**\n * RxJS operator that retries the source observable on error (e.g. connection failure).\n * Logs each retry via SlonikModule logger. Optional predicate controls which errors are retried.\n *\n * @param retryAttempts - Max retry count (default 9).\n * @param retryDelay - Delay in ms between retries (default 3000).\n * @param poolName - Name used in log messages (default DEFAULT_POOL_NAME).\n * @param verboseRetryLog - If true, include error message in logs.\n * @param toRetry - Optional (err) => boolean; retry only when true. Omit to retry all errors.\n * @returns RxJS operator function.\n */\nexport function handleRetry(\n retryAttempts = 9,\n retryDelay = 3000,\n poolName = DEFAULT_POOL_NAME,\n verboseRetryLog = false,\n toRetry?: (err: unknown) => boolean,\n): <T>(source: Observable<T>) => Observable<T> {\n return <T>(source: Observable<T>) =>\n source.pipe(\n retry({\n count: retryAttempts,\n delay: (error: unknown, retryCount) => {\n if (toRetry && !toRetry(error)) {\n return throwError(() => error);\n }\n\n const poolInfo =\n poolName === DEFAULT_POOL_NAME ? '' : ` (${poolName})`;\n const errMessage =\n error instanceof Error ? error.message : String(error);\n const verboseMessage = verboseRetryLog\n ? ` Message: ${errMessage}.`\n : '';\n\n logger.error(\n format(\n 'unable to connect to the database#%s.%s Retrying (%s)%s',\n poolInfo,\n verboseMessage,\n retryCount,\n verboseMessage ? '' : ` Error: ${errMessage}`,\n ),\n );\n\n return of(null).pipe(delay(retryDelay));\n },\n }),\n );\n}\n","import type {\n DynamicModule,\n OnApplicationShutdown,\n Provider,\n} from '@nestjs/common';\nimport type { DatabasePool } from 'slonik';\n\nimport { Module } from '@nestjs/common';\n\nimport type { OPTIONS_TYPE } from './slonik.module-definition';\n\nimport { SlonikCoreModule } from './slonik.module-definition';\nimport { createSlonikConnection, createSlonikToken } from './slonik.util';\n\n/**\n * NestJS module that provides one or more Slonik PostgreSQL pools as injectable providers.\n * Each connection is created with retries; pools are closed on application shutdown.\n */\n@Module({})\nexport class SlonikModule\n extends SlonikCoreModule\n implements OnApplicationShutdown\n{\n private static pools = new Map<string, DatabasePool>();\n\n /**\n * Registers the module with the given connections. One provider (pool) per connection;\n * inject via InjectPool(name).\n *\n * @param options - Module options; must include connections array.\n * @returns DynamicModule with providers and exports for each connection token.\n */\n static register(options: typeof OPTIONS_TYPE): DynamicModule {\n const { connections } = options;\n\n const module = super.register(options);\n\n module.providers ??= [];\n module.exports ??= [];\n\n const providers: Provider[] = connections.map(conn => ({\n provide: createSlonikToken(conn.name),\n useFactory: async () => {\n const connection = await createSlonikConnection({\n dsn: conn.dsn,\n options: conn.options,\n name: conn.name,\n });\n this.pools.set(conn.name, connection);\n return connection;\n },\n }));\n\n module.providers.push(...providers);\n module.exports.push(...connections.map(c => createSlonikToken(c.name)));\n\n return module;\n }\n\n /** Ends all pools created by this module. Called by Nest on shutdown. */\n async onApplicationShutdown() {\n await Promise.allSettled(\n Array.from(SlonikModule.pools.values()).map(pool => pool.end()),\n );\n }\n}\n","import { ConfigurableModuleBuilder } from '@nestjs/common';\n\nimport type {\n SlonikModuleExtraOptions,\n SlonikModuleOptions,\n} from './slonik.interface';\n\n/** Configurable module builder: base class, options token, and option types for register/registerAsync. */\nexport const {\n ConfigurableModuleClass: SlonikCoreModule,\n MODULE_OPTIONS_TOKEN,\n OPTIONS_TYPE,\n ASYNC_OPTIONS_TYPE,\n} = new ConfigurableModuleBuilder<SlonikModuleOptions>()\n .setExtras<SlonikModuleExtraOptions>(\n {\n isGlobal: true,\n },\n (definition, extra) => {\n return { global: extra.isGlobal, ...definition };\n },\n )\n .build();\n"],"mappings":"8/BAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,wBAAAE,EAAA,eAAAC,EAAA,yBAAAC,EAAA,iBAAAC,EAAA,qBAAAC,EAAA,iBAAAC,IAAA,eAAAC,EAAAR,GCAA,IAAAS,EAAuB,0BCIhB,IAAMC,EAAoB,qBAKpBC,EAAoB,UCNjC,IAAAC,EAAuB,0BACvBC,EAAuB,gBACvBC,EAAmE,gBACnEC,EAA2B,kBAYpB,IAAMC,EAAoB,CAACC,EAAeC,OAC/C,UAAOC,EAAmBF,EAAK,YAAY,CAAC,EAExCG,EAAS,IAAI,SAAO,cAAc,EAUjC,SAASC,EAAuB,CACrC,IAAAC,EACA,KAAAL,EACA,QAAAM,CACF,EAAkD,CAChD,IAAMC,EAAQR,EAAkBC,CAAI,EAEpC,SAAO,oBACL,SAAM,IAAYQ,EAAA,sBAChB,IAAMC,EAAO,QAAM,cAAWJ,EAAKC,CAAO,EAE1C,aAAMG,EACH,QAAQ,IAAM,QAAQ,QAAQ,CAAC,EAC/B,KAAK,IAAM,CACVN,EAAO,IAAI,yBAAyBI,CAAK,EAAE,CAC7C,CAAC,EACIE,CACT,EAAC,EAAE,KAAKC,EAAY,CAAC,CACvB,CACF,CAaO,SAASA,EACdC,EAAgB,EAChBC,EAAa,IACbC,EAAWZ,EACXa,EAAkB,GAClBC,EAC6C,CAC7C,OAAWC,GACTA,EAAO,QACL,SAAM,CACJ,MAAOL,EACP,MAAO,CAACM,EAAgBC,IAAe,CACrC,GAAIH,GAAW,CAACA,EAAQE,CAAK,EAC3B,SAAO,cAAW,IAAMA,CAAK,EAG/B,IAAME,EACJN,IAAaZ,EAAoB,GAAK,KAAKY,CAAQ,IAC/CO,EACJH,aAAiB,MAAQA,EAAM,QAAU,OAAOA,CAAK,EACjDI,EAAiBP,EACnB,aAAaM,CAAU,IACvB,GAEJ,OAAAjB,EAAO,SACL,UACE,2DACAgB,EACAE,EACAH,EACAG,EAAiB,GAAK,WAAWD,CAAU,EAC7C,CACF,KAEO,MAAG,IAAI,EAAE,QAAK,SAAMR,CAAU,CAAC,CACxC,CACF,CAAC,CACH,CACJ,CFtFO,SAASU,EAAWC,EAAOC,EAAmB,CACnD,SAAO,UAAOC,EAAkBF,CAAI,CAAC,CACvC,CGVA,IAAAG,EAAuB,0BCPvB,IAAAC,EAA0C,0BAQnC,GAAM,CACX,wBAAyBC,EACzB,qBAAAC,EACA,aAAAC,EACA,mBAAAC,CACF,EAAI,IAAI,4BAA+C,EACpD,UACC,CACE,SAAU,EACZ,EACA,CAACC,EAAYC,IACJC,EAAA,CAAE,OAAQD,EAAM,UAAaD,EAExC,EACC,MAAM,EDHF,IAAMG,EAAN,cACGC,CAEV,CAUE,OAAO,SAASC,EAA6C,CAhC/D,IAAAC,EAAAC,EAiCI,GAAM,CAAE,YAAAC,CAAY,EAAIH,EAElBI,EAAS,MAAM,SAASJ,CAAO,GAErCC,EAAAG,EAAO,YAAP,OAAAA,EAAO,UAAc,CAAC,IACtBF,EAAAE,EAAO,UAAP,OAAAA,EAAO,QAAY,CAAC,GAEpB,IAAMC,EAAwBF,EAAY,IAAIG,IAAS,CACrD,QAASC,EAAkBD,EAAK,IAAI,EACpC,WAAY,IAAYE,EAAA,sBACtB,IAAMC,EAAa,MAAMC,EAAuB,CAC9C,IAAKJ,EAAK,IACV,QAASA,EAAK,QACd,KAAMA,EAAK,IACb,CAAC,EACD,YAAK,MAAM,IAAIA,EAAK,KAAMG,CAAU,EAC7BA,CACT,EACF,EAAE,EAEF,OAAAL,EAAO,UAAU,KAAK,GAAGC,CAAS,EAClCD,EAAO,QAAQ,KAAK,GAAGD,EAAY,IAAIQ,GAAKJ,EAAkBI,EAAE,IAAI,CAAC,CAAC,EAE/DP,CACT,CAGM,uBAAwB,QAAAI,EAAA,sBAC5B,MAAM,QAAQ,WACZ,MAAM,KAAKV,EAAa,MAAM,OAAO,CAAC,EAAE,IAAIc,GAAQA,EAAK,IAAI,CAAC,CAChE,CACF,GACF,EA9Cad,EAII,MAAQ,IAAI,IAJhBA,EAANe,EAAA,IADN,UAAO,CAAC,CAAC,GACGf","names":["index_exports","__export","ASYNC_OPTIONS_TYPE","InjectPool","MODULE_OPTIONS_TOKEN","OPTIONS_TYPE","SlonikCoreModule","SlonikModule","__toCommonJS","import_common","SLONIK_POOL_TOKEN","DEFAULT_POOL_NAME","import_common","import_node_util","import_rxjs","import_slonik","createSlonikToken","name","DEFAULT_POOL_NAME","SLONIK_POOL_TOKEN","logger","createSlonikConnection","dsn","options","token","__async","pool","handleRetry","retryAttempts","retryDelay","poolName","verboseRetryLog","toRetry","source","error","retryCount","poolInfo","errMessage","verboseMessage","InjectPool","name","DEFAULT_POOL_NAME","createSlonikToken","import_common","import_common","SlonikCoreModule","MODULE_OPTIONS_TOKEN","OPTIONS_TYPE","ASYNC_OPTIONS_TYPE","definition","extra","__spreadValues","SlonikModule","SlonikCoreModule","options","_a","_b","connections","module","providers","conn","createSlonikToken","__async","connection","createSlonikConnection","c","pool","__decorateClass"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/slonik.decorator.ts","../src/constants/index.ts","../src/slonik.util.ts","../src/slonik.module.ts","../src/slonik.module-definition.ts"],"sourcesContent":["export * from './slonik.decorator';\nexport * from './slonik.module';\nexport * from './slonik.module-definition';\nexport { createSlonikToken } from './slonik.util';\n","import { Inject } from '@nestjs/common';\n\nimport { DEFAULT_POOL_NAME } from './constants';\nimport { createSlonikToken } from './slonik.util';\n\n/**\n * Parameter decorator that injects the Slonik DatabasePool for the given connection name.\n *\n * @param name - Connection name (default: 'DEFAULT'). Must match a name in SlonikModule.register().\n * @returns Nest parameter decorator that injects DatabasePool.\n *\n * @example\n * constructor(@InjectPool() private readonly pool: DatabasePool) {}\n * constructor(@InjectPool('replica') private readonly replica: DatabasePool) {}\n */\nexport function InjectPool(name = DEFAULT_POOL_NAME) {\n return Inject(createSlonikToken(name));\n}\n","/**\n * The token for the Slonik pool\n * @example `createSlonikToken('DEFAULT')` will return '__SLONIK_DEFAULT_POOL__'\n */\nexport const SLONIK_POOL_TOKEN = '__SLONIK_%s_POOL__';\n\n/**\n * The default name for the Slonik pool\n */\nexport const DEFAULT_POOL_NAME = 'DEFAULT';\n","import type { Observable } from 'rxjs';\nimport type { DatabasePool } from 'slonik';\n\nimport { Logger } from '@nestjs/common';\nimport { format } from 'node:util';\nimport { defer, delay, lastValueFrom, of, retry, throwError } from 'rxjs';\nimport { createPool } from 'slonik';\n\nimport type { SlonikConnectionConfig } from './slonik.interface';\n\nimport { DEFAULT_POOL_NAME, SLONIK_POOL_TOKEN } from './constants';\n\n/**\n * Builds the Nest injection token for a named Slonik pool.\n *\n * @param name - Connection name (default: DEFAULT_POOL_NAME). Normalized to uppercase in token.\n * @returns Token string, e.g. '__SLONIK_DEFAULT_POOL__'.\n */\nexport const createSlonikToken = (name: string = DEFAULT_POOL_NAME) =>\n format(SLONIK_POOL_TOKEN, name.toUpperCase());\n\nconst logger = new Logger('SlonikModule');\n\n/**\n * Creates a Slonik pool, verifies connectivity with pool.connect(), and retries on failure.\n * Options (including interceptors) are passed through to createPool.\n *\n * @param config - Connection config (name, dsn, optional options).\n * @returns Promise resolving to the Slonik DatabasePool.\n * @throws If connection or verification fails after all retries.\n */\nexport function createSlonikConnection({\n dsn,\n name,\n options,\n}: SlonikConnectionConfig): Promise<DatabasePool> {\n const token = createSlonikToken(name);\n\n return lastValueFrom(\n defer(async () => {\n const pool = await createPool(dsn, options);\n\n await pool\n .connect(() => Promise.resolve())\n .then(() => {\n logger.log(`Connected to database ${token}`);\n });\n return pool;\n }).pipe(handleRetry()),\n );\n}\n\n/**\n * RxJS operator that retries the source observable on error (e.g. connection failure).\n * Logs each retry via SlonikModule logger. Optional predicate controls which errors are retried.\n *\n * @param retryAttempts - Max retry count (default 9).\n * @param retryDelay - Delay in ms between retries (default 3000).\n * @param poolName - Name used in log messages (default DEFAULT_POOL_NAME).\n * @param verboseRetryLog - If true, include error message in logs.\n * @param toRetry - Optional (err) => boolean; retry only when true. Omit to retry all errors.\n * @returns RxJS operator function.\n */\nexport function handleRetry(\n retryAttempts = 9,\n retryDelay = 3000,\n poolName = DEFAULT_POOL_NAME,\n verboseRetryLog = false,\n toRetry?: (err: unknown) => boolean,\n): <T>(source: Observable<T>) => Observable<T> {\n return <T>(source: Observable<T>) =>\n source.pipe(\n retry({\n count: retryAttempts,\n delay: (error: unknown, retryCount) => {\n if (toRetry && !toRetry(error)) {\n return throwError(() => error);\n }\n\n const poolInfo =\n poolName === DEFAULT_POOL_NAME ? '' : ` (${poolName})`;\n const errMessage =\n error instanceof Error ? error.message : String(error);\n const verboseMessage = verboseRetryLog\n ? ` Message: ${errMessage}.`\n : '';\n\n logger.error(\n format(\n 'unable to connect to the database#%s.%s Retrying (%s)%s',\n poolInfo,\n verboseMessage,\n retryCount,\n verboseMessage ? '' : ` Error: ${errMessage}`,\n ),\n );\n\n return of(null).pipe(delay(retryDelay));\n },\n }),\n );\n}\n","import type {\n DynamicModule,\n OnApplicationShutdown,\n Provider,\n} from '@nestjs/common';\nimport type { DatabasePool } from 'slonik';\n\nimport { Module } from '@nestjs/common';\n\nimport type { OPTIONS_TYPE } from './slonik.module-definition';\n\nimport { SlonikCoreModule } from './slonik.module-definition';\nimport { createSlonikConnection, createSlonikToken } from './slonik.util';\n\n/**\n * NestJS module that provides one or more Slonik PostgreSQL pools as injectable providers.\n * Each connection is created with retries; pools are closed on application shutdown.\n */\n@Module({})\nexport class SlonikModule\n extends SlonikCoreModule\n implements OnApplicationShutdown\n{\n private static pools = new Map<string, DatabasePool>();\n\n /**\n * Registers the module with the given connections. One provider (pool) per connection;\n * inject via InjectPool(name).\n *\n * @param options - Module options; must include connections array.\n * @returns DynamicModule with providers and exports for each connection token.\n */\n static register(options: typeof OPTIONS_TYPE): DynamicModule {\n const { connections } = options;\n\n const module = super.register(options);\n\n module.providers ??= [];\n module.exports ??= [];\n\n const providers: Provider[] = connections.map(conn => ({\n provide: createSlonikToken(conn.name),\n useFactory: async () => {\n const connection = await createSlonikConnection({\n dsn: conn.dsn,\n options: conn.options,\n name: conn.name,\n });\n this.pools.set(conn.name, connection);\n return connection;\n },\n }));\n\n module.providers.push(...providers);\n module.exports.push(...connections.map(c => createSlonikToken(c.name)));\n\n return module;\n }\n\n /** Ends all pools created by this module. Called by Nest on shutdown. */\n async onApplicationShutdown() {\n await Promise.allSettled(\n Array.from(SlonikModule.pools.values()).map(pool => pool.end()),\n );\n }\n}\n","import { ConfigurableModuleBuilder } from '@nestjs/common';\n\nimport type {\n SlonikModuleExtraOptions,\n SlonikModuleOptions,\n} from './slonik.interface';\n\n/** Configurable module builder: base class, options token, and option types for register/registerAsync. */\nexport const {\n ConfigurableModuleClass: SlonikCoreModule,\n MODULE_OPTIONS_TOKEN,\n OPTIONS_TYPE,\n ASYNC_OPTIONS_TYPE,\n} = new ConfigurableModuleBuilder<SlonikModuleOptions>()\n .setExtras<SlonikModuleExtraOptions>(\n {\n isGlobal: true,\n },\n (definition, extra) => {\n return { global: extra.isGlobal, ...definition };\n },\n )\n .build();\n"],"mappings":"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","names":["index_exports","__export","ASYNC_OPTIONS_TYPE","InjectPool","MODULE_OPTIONS_TOKEN","OPTIONS_TYPE","SlonikCoreModule","SlonikModule","createSlonikToken","__toCommonJS","import_common","SLONIK_POOL_TOKEN","DEFAULT_POOL_NAME","import_common","import_node_util","import_rxjs","import_slonik","createSlonikToken","name","DEFAULT_POOL_NAME","SLONIK_POOL_TOKEN","logger","createSlonikConnection","dsn","options","token","__async","pool","handleRetry","retryAttempts","retryDelay","poolName","verboseRetryLog","toRetry","source","error","retryCount","poolInfo","errMessage","verboseMessage","InjectPool","name","DEFAULT_POOL_NAME","createSlonikToken","import_common","import_common","SlonikCoreModule","MODULE_OPTIONS_TOKEN","OPTIONS_TYPE","ASYNC_OPTIONS_TYPE","definition","extra","__spreadValues","SlonikModule","SlonikCoreModule","options","_a","_b","connections","module","providers","conn","createSlonikToken","__async","connection","createSlonikConnection","c","pool","__decorateClass"]}
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- var T=Object.defineProperty;var x=Object.getOwnPropertyDescriptor;var d=Object.getOwnPropertySymbols;var L=Object.prototype.hasOwnProperty,v=Object.prototype.propertyIsEnumerable;var P=(t,o,e)=>o in t?T(t,o,{enumerable:!0,configurable:!0,writable:!0,value:e}):t[o]=e,b=(t,o)=>{for(var e in o||(o={}))L.call(o,e)&&P(t,e,o[e]);if(d)for(var e of d(o))v.call(o,e)&&P(t,e,o[e]);return t};var S=(t,o,e,r)=>{for(var n=r>1?void 0:r?x(o,e):o,p=t.length-1,s;p>=0;p--)(s=t[p])&&(n=(r?s(o,e,n):s(n))||n);return r&&n&&T(o,e,n),n};var O=(t,o,e)=>new Promise((r,n)=>{var p=a=>{try{i(e.next(a))}catch(m){n(m)}},s=a=>{try{i(e.throw(a))}catch(m){n(m)}},i=a=>a.done?r(a.value):Promise.resolve(a.value).then(p,s);i((e=e.apply(t,o)).next())});import{Inject as K}from"@nestjs/common";var E="__SLONIK_%s_POOL__",c="DEFAULT";import{Logger as C}from"@nestjs/common";import{format as _}from"util";import{defer as M,delay as N,lastValueFrom as w,of as A,retry as D,throwError as I}from"rxjs";import{createPool as h}from"slonik";var f=(t=c)=>_(E,t.toUpperCase()),g=new C("SlonikModule");function k({dsn:t,name:o,options:e}){let r=f(o);return w(M(()=>O(null,null,function*(){let n=yield h(t,e);return yield n.connect(()=>Promise.resolve()).then(()=>{g.log(`Connected to database ${r}`)}),n})).pipe(F()))}function F(t=9,o=3e3,e=c,r=!1,n){return p=>p.pipe(D({count:t,delay:(s,i)=>{if(n&&!n(s))return I(()=>s);let a=e===c?"":` (${e})`,m=s instanceof Error?s.message:String(s),u=r?` Message: ${m}.`:"";return g.error(_("unable to connect to the database#%s.%s Retrying (%s)%s",a,u,i,u?"":` Error: ${m}`)),A(null).pipe(N(o))}}))}function X(t=c){return K(f(t))}import{Module as Y}from"@nestjs/common";import{ConfigurableModuleBuilder as U}from"@nestjs/common";var{ConfigurableModuleClass:y,MODULE_OPTIONS_TOKEN:eo,OPTIONS_TYPE:to,ASYNC_OPTIONS_TYPE:ro}=new U().setExtras({isGlobal:!0},(t,o)=>b({global:o.isGlobal},t)).build();var l=class extends y{static register(o){var p,s;let{connections:e}=o,r=super.register(o);(p=r.providers)!=null||(r.providers=[]),(s=r.exports)!=null||(r.exports=[]);let n=e.map(i=>({provide:f(i.name),useFactory:()=>O(this,null,function*(){let a=yield k({dsn:i.dsn,options:i.options,name:i.name});return this.pools.set(i.name,a),a})}));return r.providers.push(...n),r.exports.push(...e.map(i=>f(i.name))),r}onApplicationShutdown(){return O(this,null,function*(){yield Promise.allSettled(Array.from(l.pools.values()).map(o=>o.end()))})}};l.pools=new Map,l=S([Y({})],l);export{ro as ASYNC_OPTIONS_TYPE,X as InjectPool,eo as MODULE_OPTIONS_TOKEN,to as OPTIONS_TYPE,y as SlonikCoreModule,l as SlonikModule};
1
+ var T=Object.defineProperty;var y=Object.getOwnPropertyDescriptor;var d=Object.getOwnPropertySymbols;var L=Object.prototype.hasOwnProperty,v=Object.prototype.propertyIsEnumerable;var P=(t,o,e)=>o in t?T(t,o,{enumerable:!0,configurable:!0,writable:!0,value:e}):t[o]=e,b=(t,o)=>{for(var e in o||(o={}))L.call(o,e)&&P(t,e,o[e]);if(d)for(var e of d(o))v.call(o,e)&&P(t,e,o[e]);return t};var S=(t,o,e,r)=>{for(var n=r>1?void 0:r?y(o,e):o,p=t.length-1,i;p>=0;p--)(i=t[p])&&(n=(r?i(o,e,n):i(n))||n);return r&&n&&T(o,e,n),n};var O=(t,o,e)=>new Promise((r,n)=>{var p=a=>{try{s(e.next(a))}catch(c){n(c)}},i=a=>{try{s(e.throw(a))}catch(c){n(c)}},s=a=>a.done?r(a.value):Promise.resolve(a.value).then(p,i);s((e=e.apply(t,o)).next())});import{Inject as K}from"@nestjs/common";var k="__SLONIK_%s_POOL__",f="DEFAULT";import{Logger as C}from"@nestjs/common";import{format as E}from"util";import{defer as M,delay as N,lastValueFrom as w,of as A,retry as D,throwError as I}from"rxjs";import{createPool as h}from"slonik";var l=(t=f)=>E(k,t.toUpperCase()),_=new C("SlonikModule");function g({dsn:t,name:o,options:e}){let r=l(o);return w(M(()=>O(null,null,function*(){let n=yield h(t,e);return yield n.connect(()=>Promise.resolve()).then(()=>{_.log(`Connected to database ${r}`)}),n})).pipe(F()))}function F(t=9,o=3e3,e=f,r=!1,n){return p=>p.pipe(D({count:t,delay:(i,s)=>{if(n&&!n(i))return I(()=>i);let a=e===f?"":` (${e})`,c=i instanceof Error?i.message:String(i),u=r?` Message: ${c}.`:"";return _.error(E("unable to connect to the database#%s.%s Retrying (%s)%s",a,u,s,u?"":` Error: ${c}`)),A(null).pipe(N(o))}}))}function X(t=f){return K(l(t))}import{Module as Y}from"@nestjs/common";import{ConfigurableModuleBuilder as U}from"@nestjs/common";var{ConfigurableModuleClass:x,MODULE_OPTIONS_TOKEN:eo,OPTIONS_TYPE:to,ASYNC_OPTIONS_TYPE:ro}=new U().setExtras({isGlobal:!0},(t,o)=>b({global:o.isGlobal},t)).build();var m=class extends x{static register(o){var p,i;let{connections:e}=o,r=super.register(o);(p=r.providers)!=null||(r.providers=[]),(i=r.exports)!=null||(r.exports=[]);let n=e.map(s=>({provide:l(s.name),useFactory:()=>O(this,null,function*(){let a=yield g({dsn:s.dsn,options:s.options,name:s.name});return this.pools.set(s.name,a),a})}));return r.providers.push(...n),r.exports.push(...e.map(s=>l(s.name))),r}onApplicationShutdown(){return O(this,null,function*(){yield Promise.allSettled(Array.from(m.pools.values()).map(o=>o.end()))})}};m.pools=new Map,m=S([Y({})],m);export{ro as ASYNC_OPTIONS_TYPE,X as InjectPool,eo as MODULE_OPTIONS_TOKEN,to as OPTIONS_TYPE,x as SlonikCoreModule,m as SlonikModule,l as createSlonikToken};
2
2
  //# sourceMappingURL=index.mjs.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rineex/pg-slonik",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "PostgreSQL adapter using Slonik for Rineex core modules",
5
5
  "author": "Rineex Team",
6
6
  "main": "./dist/index.js",