{"_id":"@bluealba/nestjs-slonik","_rev":"3-bb4b21123b415df9507df9836758f7ff","name":"@bluealba/nestjs-slonik","dist-tags":{"latest":"1.1.0"},"versions":{"1.0.0":{"name":"@bluealba/nestjs-slonik","version":"1.0.0","author":{"name":"Blue Alba"},"license":"PolyForm-Noncommercial-1.0.0","_id":"@bluealba/nestjs-slonik@1.0.0","maintainers":[{"name":"bluealba","email":"npm@bluealba.com"}],"dist":{"shasum":"426bb9f964291bc2e71f92b79ed1c06860560782","tarball":"https://registry.npmjs.org/@bluealba/nestjs-slonik/-/nestjs-slonik-1.0.0.tgz","fileCount":35,"integrity":"sha512-XQ6NMAZGpIqgKjtYKTSdiQkJXfWBnZNKUlbZsWF7d0dpASSjJuQzsYtvhfu30hOlG5byhx0gzha7nusV44a9iA==","signatures":[{"sig":"MEUCIQDqcy5MZ+SnGn6hXTRs/xm/kKPoq2JzyDXmdGqqCxRSuwIgbIBiJBdWBccbeHOz7jelOQpPVAKJZkzX03SGbTTbYZM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":56275},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"eb2d8a36859c78c31ae552e01f61edba7d7a3baf","private":false,"scripts":{"dev":"npm run start:dev","lint":"biome check","test":"jest","build":"nest build","start":"nest start | pino-pretty -c","coverage":"jest --coverage","lint:fix":"biome check --write","test:e2e":"jest --config ./test/jest-e2e.json","changeset":"npm run changeset","start:dev":"nest start --watch | pino-pretty -c","start:prod":"node dist/main","test:debug":"node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand","test:watch":"jest --watch","start:debug":"nest start --debug --watch | pino-pretty -c"},"_npmUser":{"name":"bluealba","email":"npm@bluealba.com"},"_npmVersion":"10.9.4","description":"NestJS module providing PostgreSQL integration with Slonik query builder, automatic migrations, and type parsing","directories":{},"displayName":"Slonik NestJS Module","_nodeVersion":"22.22.0","dependencies":{"zod":"^3.23.8","rxjs":"^7.8.2","umzug":"^3.8.2","slonik":"^45.2.0","@nestjs/core":"^11.1.9","@nestjs/common":"^11.1.9","@changesets/cli":"^2.29.8","class-validator":"^0.14.2","reflect-metadata":"^0.2.2","class-transformer":"^0.5.1","@nestjs/platform-express":"^11.1.9"},"publishConfig":{"access":"public","@bluealba:registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"packageManager":"npm@11.6.2","devDependencies":{"jest":"^29.7.0","biome":"^0.3.3","nestjs":"^0.0.1","ts-jest":"^29.4.6","ts-node":"^10.9.2","@nestjs/cli":"^11.0.16","@types/jest":"^29.5.0","@types/node":"^24.10.1","pino-pretty":"^13.1.2","@biomejs/biome":"^2.3.5","@nestjs/testing":"^11.1.9","@testcontainers/postgresql":"^11.0.3"},"_npmOperationalInternal":{"tmp":"tmp/nestjs-slonik_1.0.0_1769178549058_0.16040869048458606","host":"s3://npm-registry-packages-npm-production"}},"1.1.0-develop-15":{"name":"@bluealba/nestjs-slonik","version":"1.1.0-develop-15","author":{"name":"Blue Alba"},"license":"PolyForm-Noncommercial-1.0.0","_id":"@bluealba/nestjs-slonik@1.1.0-develop-15","maintainers":[{"name":"bluealba","email":"npm@bluealba.com"}],"dist":{"shasum":"d777622191fdd9111cd9e6a319dfe885f31ece61","tarball":"https://registry.npmjs.org/@bluealba/nestjs-slonik/-/nestjs-slonik-1.1.0-develop-15.tgz","fileCount":35,"integrity":"sha512-C8Jl5pmbtBDzIhfXfTpc54u5nKi4BCf3S9lgp8ZSGFeKUvEMCmW9LhI3BGDRfPopkaTvaPlz+13JVOJ4DemTXA==","signatures":[{"sig":"MEYCIQCXLH8i5sbOGYkZmukijfBURJou+B9Aw61LUCpu/+E3FgIhAJ0IxroLzJdbAUM1kjPM7oo5fsznSkYFp2qpUv7vndAP","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDenFdEkyFY8ff3muVTFhTXHaZ2RR96AqHOEMpA7mGEywIgbSoK9gRzqKJBE+DleHP0bhx34Mc+ppB8rSZl29nAk6c=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":56473},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"d11d8939c0eecfbec962f2bdae6cb47d3ace8411","private":false,"scripts":{"dev":"npm run start:dev","lint":"biome check","test":"jest","build":"nest build","start":"nest start | pino-pretty -c","coverage":"jest --coverage","lint:fix":"biome check --write","test:e2e":"jest --config ./test/jest-e2e.json","changeset":"changeset","start:dev":"nest start --watch | pino-pretty -c","start:prod":"node dist/main","test:debug":"node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand","test:watch":"jest --watch","start:debug":"nest start --debug --watch | pino-pretty -c"},"_npmUser":{"name":"bluealba","email":"npm@bluealba.com"},"_npmVersion":"10.9.8","description":"NestJS module providing PostgreSQL integration with Slonik query builder, automatic migrations, and type parsing","directories":{},"displayName":"Slonik NestJS Module","_nodeVersion":"22.23.2","dependencies":{"zod":"^3.23.8","rxjs":"^7.8.2","umzug":"^3.8.2","slonik":"^47.3.2","@nestjs/core":"^11.1.9","@nestjs/common":"^11.1.9","@changesets/cli":"^2.29.8","class-validator":"^0.14.2","reflect-metadata":"^0.2.2","class-transformer":"^0.5.1","@nestjs/platform-express":"^11.1.9"},"publishConfig":{"access":"public","@bluealba:registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"packageManager":"npm@11.6.2","devDependencies":{"jest":"^29.7.0","biome":"^0.3.3","nestjs":"^0.0.1","ts-jest":"^29.4.6","ts-node":"^10.9.2","@nestjs/cli":"^11.0.16","@types/jest":"^29.5.0","@types/node":"^24.10.1","pino-pretty":"^13.1.2","@biomejs/biome":"^2.3.5","@nestjs/testing":"^11.1.9","@babel/preset-env":"^7.29.7","@testcontainers/postgresql":"^11.0.3"},"_npmOperationalInternal":{"tmp":"tmp/nestjs-slonik_1.1.0-develop-15_1789485282947_0.5288604284654659","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"_id":"@bluealba/nestjs-slonik@1.1.0","dist":{"shasum":"d3ec42a3f383ccd3f54b22a476c71ef71c24c2c5","tarball":"https://registry.npmjs.org/@bluealba/nestjs-slonik/-/nestjs-slonik-1.1.0.tgz","fileCount":35,"integrity":"sha512-RmK/6qtA66CsrYYZw3PthcCkY38oy5XGw3/AAhtmRRbDzGh+fEOEQ1bY+lb72GZCqUjFkPic4OgYkP7KNSU0lQ==","signatures":[{"sig":"MEQCIDI59qk67Z6ahT/hmLlWiVXCVSTLDGw7uOh9lDRwVCRdAiB4Qerw5Y9/KCY6aRq4sbyTMzVRk/z30TEhoKLoc7OQIg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQD4ClA0L/JM95kYhhw72ZGkz3QmOxYMn/v+9QrCZrB5DgIhAKV5e7r9JG9UKY+U8gMPyUv9gWFSh+3X1a9BhPpH9DWy"}],"unpackedSize":56462},"main":"dist/index.js","name":"@bluealba/nestjs-slonik","types":"dist/index.d.ts","author":{"name":"Blue Alba"},"gitHead":"6e9a19ca619a193b1a24889f524e550ea7f3dec5","license":"PolyForm-Noncommercial-1.0.0","private":false,"scripts":{"dev":"npm run start:dev","lint":"biome check","test":"jest","build":"nest build","start":"nest start | pino-pretty -c","coverage":"jest --coverage","lint:fix":"biome check --write","test:e2e":"jest --config ./test/jest-e2e.json","changeset":"changeset","start:dev":"nest start --watch | pino-pretty -c","start:prod":"node dist/main","test:debug":"node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand","test:watch":"jest --watch","start:debug":"nest start --debug --watch | pino-pretty -c"},"version":"1.1.0","_npmUser":{"name":"bluealba","email":"npm@bluealba.com"},"_npmVersion":"10.9.8","description":"NestJS module providing PostgreSQL integration with Slonik query builder, automatic migrations, and type parsing","directories":{},"displayName":"Slonik NestJS Module","maintainers":[{"name":"bluealba","email":"npm@bluealba.com"}],"_nodeVersion":"22.23.2","dependencies":{"zod":"^3.23.8","rxjs":"^7.8.2","umzug":"^3.8.2","slonik":"^47.3.2","@nestjs/core":"^11.1.9","@nestjs/common":"^11.1.9","@changesets/cli":"^2.29.8","class-validator":"^0.14.2","reflect-metadata":"^0.2.2","class-transformer":"^0.5.1","@nestjs/platform-express":"^11.1.9"},"publishConfig":{"access":"public","@bluealba:registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"packageManager":"npm@11.6.2","devDependencies":{"jest":"^29.7.0","biome":"^0.3.3","nestjs":"^0.0.1","ts-jest":"^29.4.6","ts-node":"^10.9.2","@nestjs/cli":"^11.0.16","@types/jest":"^29.5.0","@types/node":"^24.10.1","pino-pretty":"^13.1.2","@biomejs/biome":"^2.3.5","@nestjs/testing":"^11.1.9","@babel/preset-env":"^7.29.7","@testcontainers/postgresql":"^11.0.3"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/nestjs-slonik_1.1.0_1789485580511_0.9855331503917903"}}},"time":{"created":"2026-01-23T14:29:09.005Z","modified":"2026-09-15T15:19:40.750Z","1.0.0":"2026-01-23T14:29:09.210Z","1.1.0-develop-15":"2026-09-15T15:14:43.021Z","1.1.0":"2026-09-15T15:19:40.595Z"},"author":{"name":"Blue Alba"},"license":"PolyForm-Noncommercial-1.0.0","description":"NestJS module providing PostgreSQL integration with Slonik query builder, automatic migrations, and type parsing","maintainers":[{"name":"bluealba","email":"npm@bluealba.com"}],"readme":"# SlonikModule\n\nA NestJS module that provides PostgreSQL database integration using Slonik query builder with built-in migrations and type parsing.\n\n## Features\n\n- **Slonik Integration**: Wraps the powerful Slonik PostgreSQL client for NestJS\n- **Automatic Migrations**: Built-in database migration support with environment-specific migrations\n- **Type Parsing**: Automatic parsing of PostgreSQL timestamp types to JavaScript Date objects\n- **Async Configuration**: Flexible configuration with dependency injection support\n\n## Installation\n\n```bash\nnpm install @bluealba/nestjs-slonik\n```\n\n## Usage\n\n### Basic Configuration\n\n```typescript\nimport { Module } from '@nestjs/common';\nimport { SlonikModule } from '@bluealba/nestjs-slonik';\n\n// Define your environment type for type safety\ntype AppEnv = 'local' | 'dev' | 'staging' | 'prod';\n\n@Module({\n  imports: [\n    SlonikModule.forRootAsync<AppEnv>({\n      useFactory: async () => ({\n        connectionUri: 'postgresql://user:password@localhost:5432/database',\n        migrations: {\n          migrationsPath: 'src/postgres-migrations',\n          environment: 'local', // TypeScript validates this against AppEnv\n        },\n      }),\n    }),\n  ],\n})\nexport class AppModule {}\n```\n\n### Configuration with ConfigService and mapColumnNamesToCamelCase enabled\n\n```typescript\nimport { Module } from '@nestjs/common';\nimport { ConfigModule, ConfigService } from '@nestjs/config';\nimport { SlonikModule } from '@bluealba/nestjs-slonik';\n\n// Define your environment type for type safety\ntype AppEnv = 'local' | 'dev' | 'staging' | 'prod';\n\n@Module({\n  imports: [\n    ConfigModule.forRoot(),\n    SlonikModule.forRootAsync<AppEnv>({\n      imports: [ConfigModule],\n      useFactory: async (configService: ConfigService) => ({\n        connectionUri: configService.get('DATABASE_URL'),\n        mapColumnNamesToCamelCase: true,\n        migrations: {\n          migrationsPath: 'src/postgres-migrations',\n          environment: (configService.get('NODE_ENV') || 'local') as AppEnv,\n        },\n      }),\n      inject: [ConfigService],\n    }),\n  ],\n})\nexport class AppModule {}\n```\n\n### Global Module Configuration\n\nWhen `global: true` is set, the module becomes globally available across your application, eliminating the need to import it in other modules:\n\n```typescript\nimport { Module } from '@nestjs/common';\nimport { ConfigModule, ConfigService } from '@nestjs/config';\nimport { SlonikModule } from '@bluealba/nestjs-slonik';\n\n// Define your environment type for type safety\ntype AppEnv = 'local' | 'dev' | 'staging' | 'prod';\n\n@Module({\n  imports: [\n    ConfigModule.forRoot(),\n    SlonikModule.forRootAsync<AppEnv>({\n      imports: [ConfigModule],\n      useFactory: async (configService: ConfigService) => ({\n        connectionUri: configService.get('DATABASE_URL'),\n        mapColumnNamesToCamelCase: true,\n        migrations: {\n          migrationsPath: 'src/postgres-migrations',\n          environment: (configService.get('NODE_ENV') || 'local') as AppEnv,\n        },\n      }),\n      inject: [ConfigService],\n      global: true, // Makes the module globally available\n    }),\n  ],\n})\nexport class AppModule {}\n```\n\nWith `global: true`, you can inject the database pool in any service without importing `SlonikModule` in feature modules.\n\n### Using the Database in Services\n\n```typescript\nimport { Injectable } from '@nestjs/common';\nimport { DatabasePool } from 'slonik';\nimport { InjectPool } from '@bluealba/nestjs-slonik';\n\n@Injectable()\nexport class UserService {\n  constructor(@InjectPool() private readonly db: DatabasePool) {}\n\n  async findUser(id: number) {\n    return await this.db.one`\n      SELECT id, name, email, created_at\n      FROM users\n      WHERE id = ${id}\n    `;\n  }\n\n  async createUser(name: string, email: string) {\n    return await this.db.one`\n      INSERT INTO users (name, email, created_at)\n      VALUES (${name}, ${email}, NOW())\n      RETURNING *\n    `;\n  }\n}\n```\n\n## Configuration Options\n\n### SlonikModuleOptions\n\n| Option       | Type                                    | Description                                                            |\n| ------------ | --------------------------------------- | ---------------------------------------------------------------------- |\n| `useFactory` | `(...args: any[]) => Promise<Config> \\| Config` | Factory function to create module configuration (required) |\n| `inject`     | `any[]`                                 | Optional dependencies to inject into useFactory                        |\n| `imports`    | `Array<Type \\| DynamicModule>`          | Optional modules to import                                             |\n| `global`     | `boolean` (default: `false`)            | Makes the module globally available without needing to import it       |\n\n### SlonikModuleConfig\n\n| Option                      | Type                       | Description                                                      |\n| --------------------------- | -------------------------- | ---------------------------------------------------------------- |\n| `connectionUri`             | `string`                   | PostgreSQL connection string                                     |\n| `mapColumnNamesToCamelCase` | `boolean` (default: `false`)| Transforms snake_case column names to camelCase in query results |\n| `migrations`                | `DeploymentModuleOptions`  | Migration configuration                                          |\n| `clientConfigurationInput`  | `ClientConfigurationInput` | Additional Slonik client configuration                           |\n\n### DeploymentModuleOptions\n\n| Option           | Type     | Description                       |\n| ---------------- | -------- | --------------------------------- |\n| `migrationsPath` | `string` | Path to migration files directory |\n| `environment`    | `TEnv extends string` | Target environment for migrations (type-safe with generics) |\n\n## Migration Files\n\nCreate migration files in your specified `migrationsPath`:\n\n```\nsrc/postgres-migrations/\n|--- 2025.01.01T00.00.00.000Z.create_users_table.js\n|--- 2025.01.02T00.00.00.000Z.add_user_indexes.js\n|--- byEnv/\n      |--- prd/\n            |--- 2025.01.01T00.00.00.000Z.production_specific_migration.js\n```\n\n### Migration File Example\n\n```javascript\n// 2025.01.01T00.00.00.000Z.create_users_table.js\nconst { sql } = require('slonik');\n\n/** @type {import('umzug').MigrationFn<import('slonik').DatabaseConnection>} */\nconst up = async ({ context: connection }) => {\n  await connection.query(sql`\n    CREATE TABLE users (\n      id SERIAL PRIMARY KEY,\n      name VARCHAR(255) NOT NULL,\n      email VARCHAR(255) UNIQUE NOT NULL,\n      created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()\n    )\n  `);\n};\n\n/** @type {import('umzug').MigrationFn<import('slonik').DatabaseConnection>} */\nconst down = async ({ context: connection }) => {\n  await connection.query(sql`DROP TABLE users`);\n};\n\nmodule.exports = { up, down };\n```\n\n## Type Parsing\n\nThe module automatically configures type parsers for PostgreSQL timestamp types:\n\n- `timestamp` � `Date`\n- `timestamptz` � `Date`\n\nThese parsers are automatically applied to all database queries.\n\n## Environment-Specific Migrations\n\nMigrations can be organized by environment using the `byEnv` directory structure:\n\n```\nsrc/postgres-migrations/\n|--- common_migration.js          # Runs in all environments\n|--- byEnv/\n    |--- local/\n         |--- local_only.js       # Runs only in local environment\n    |--- dev/\n        |--- dev_only.js         # Runs only in dev environment\n    |--- prd/\n        |--- production_only.js  # Runs only in production\n        |--- common_migration.js # Overrides base common_migration in production\n```\n\n**Migration Override Behavior**: If a migration file exists in both the base directory and the environment-specific `byEnv/` directory with the same filename, the environment-specific version will override the base migration. This allows for customizing migrations per environment while maintaining a common base.\n\n## Environment Type Safety\n\nThe module supports TypeScript generic types to enforce compile-time type safety for environment names. Define your own environment type and pass it to the module:\n\n```typescript\nimport { Module } from '@nestjs/common';\nimport { ConfigModule, ConfigService } from '@nestjs/config';\nimport { SlonikModule } from '@bluealba/nestjs-slonik';\n\n// Define your environment type\ntype MyEnv = 'local' | 'dev' | 'staging' | 'prod';\n\n@Module({\n  imports: [\n    ConfigModule.forRoot(),\n    SlonikModule.forRootAsync<MyEnv>({\n      imports: [ConfigModule],\n      useFactory: async (configService: ConfigService) => ({\n        connectionUri: configService.get('DATABASE_URL'),\n        migrations: {\n          migrationsPath: 'src/postgres-migrations',\n          environment: configService.get('NODE_ENV') as MyEnv, // TypeScript validates this!\n        },\n      }),\n      inject: [ConfigService],\n    }),\n  ],\n})\nexport class AppModule {}\n```\n\n### Runtime Validation\n\nIf you need runtime validation for environment values, use `@IsIn()` from `class-validator`:\n\n```typescript\nimport { IsDefined, IsIn } from 'class-validator';\n\n// Define allowed environments\nconst VALID_ENVS = ['local', 'dev', 'staging', 'prod'] as const;\ntype MyEnv = typeof VALID_ENVS[number];\n\nexport class Environment {\n  @IsDefined()\n  @IsIn(VALID_ENVS)\n  NODE_ENV: MyEnv;\n\n  @IsDefined()\n  DB_HOST: string;\n\n  @IsDefined()\n  DB_USER: string;\n\n  @IsDefined()\n  DB_PASS: string;\n\n  @IsDefined()\n  DB_NAME: string;\n}\n```\n\n## Dependencies\n\nThis module depends on:\n\n- `slonik` - PostgreSQL client\n- `umzug` - Migration framework","readmeFilename":"README.md"}