@celerity-sdk/sql-database 0.3.1 → 0.4.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["// TODO: Implement SQL database abstraction.\n// Key modules: interfaces (SqlDatabaseClient), factory (createSqlDatabaseClient), providers\nexport {};\n"],"mappings":";;;;;;;;;;;;;;;;AAAA;;","names":[]}
1
+ {"version":3,"sources":["../src/rds-token-provider.ts","../src/index.ts","../src/errors.ts","../src/config.ts","../src/credentials.ts","../src/factory.ts","../src/sql-database.ts","../src/decorators.ts","../src/helpers.ts","../src/layer.ts"],"sourcesContent":["import type { TokenProvider, TokenProviderFactory } from \"./types\";\n\n// 14 minutes — refresh ~1 min before the 15-minute RDS token expiry\nconst TOKEN_CACHE_MS = 14 * 60 * 1_000;\n\nexport class RdsTokenProvider implements TokenProvider {\n private cached: { token: string; expiresAt: number } | null = null;\n\n constructor(\n private readonly hostname: string,\n private readonly port: number,\n private readonly username: string,\n private readonly region?: string,\n ) {}\n\n async getToken(): Promise<string> {\n const now = Date.now();\n if (this.cached && now < this.cached.expiresAt) return this.cached.token;\n\n const pkg = \"@aws-sdk/rds-signer\";\n const { Signer } = (await import(pkg)) as typeof import(\"@aws-sdk/rds-signer\");\n const signer = new Signer({\n hostname: this.hostname,\n port: this.port,\n username: this.username,\n region: this.region,\n });\n\n const token = await signer.getAuthToken();\n this.cached = { token, expiresAt: now + TOKEN_CACHE_MS };\n return token;\n }\n}\n\nexport function createRdsTokenProviderFactory(region?: string): TokenProviderFactory {\n return (hostname, port, username) => new RdsTokenProvider(hostname, port, username, region);\n}\n","// Types\nexport type {\n SqlEngine,\n SqlAuthMode,\n DeployTarget,\n PoolConfig,\n SqlConnectionInfo,\n SqlPasswordAuth,\n SqlIamAuth,\n SqlDatabaseCredentials,\n TokenProvider,\n TokenProviderFactory,\n} from \"./types\";\n\n// Errors\nexport { SqlDatabaseError } from \"./errors\";\n\n// Config\nexport {\n captureSqlDatabaseLayerConfig,\n POOL_PRESETS,\n resolvePoolOverrides,\n resolvePoolConfig,\n} from \"./config\";\nexport type { SqlDatabaseLayerConfig } from \"./config\";\n\n// Credentials\nexport { resolveDatabaseCredentials, buildConnectionUrl } from \"./credentials\";\nexport type { ConnectionUrlParams } from \"./credentials\";\n\n// Token providers\nexport { RdsTokenProvider, createRdsTokenProviderFactory } from \"./rds-token-provider\";\n\n// Factory\nexport { createKnexInstance } from \"./factory\";\nexport type { CreateKnexOptions } from \"./factory\";\n\n// SqlDatabaseInstance\nexport { SqlDatabaseInstance } from \"./sql-database\";\n\n// Decorators & tokens\nexport {\n SqlDatabase,\n SqlWriter,\n SqlReader,\n SqlCredentials,\n sqlWriterToken,\n sqlReaderToken,\n sqlDatabaseCredentialsToken,\n sqlDatabaseInstanceToken,\n DEFAULT_SQL_WRITER_TOKEN,\n DEFAULT_SQL_READER_TOKEN,\n DEFAULT_SQL_CREDENTIALS_TOKEN,\n DEFAULT_SQL_DATABASE_INSTANCE_TOKEN,\n} from \"./decorators\";\n\n// Helpers\nexport { getSqlWriter, getSqlReader, getSqlCredentials } from \"./helpers\";\n\n// Layer\nexport { SqlDatabaseLayer } from \"./layer\";\n","export class SqlDatabaseError extends Error {\n constructor(\n message: string,\n public readonly database: string,\n options?: { cause?: unknown },\n ) {\n super(message, options);\n this.name = \"SqlDatabaseError\";\n }\n}\n","import { type Platform, CelerityConfig, type ConfigNamespace } from \"@celerity-sdk/config\";\nimport type { DeployTarget, PoolConfig, TokenProviderFactory } from \"./types\";\n\nexport type SqlDatabaseLayerConfig = {\n deployTarget: DeployTarget;\n platform: Platform;\n};\n\nexport function captureSqlDatabaseLayerConfig(): SqlDatabaseLayerConfig {\n return {\n deployTarget: process.env.CELERITY_RUNTIME ? \"runtime\" : \"functions\",\n platform: CelerityConfig.getPlatform(),\n };\n}\n\nexport async function resolveTokenProviderFactory(\n platform: Platform,\n): Promise<TokenProviderFactory | undefined> {\n if (platform !== \"aws\") return undefined;\n\n const mod = await import(\"./rds-token-provider\");\n return mod.createRdsTokenProviderFactory();\n}\n\nconst FUNCTIONS_POOL: PoolConfig = {\n min: 0,\n max: 2,\n idleTimeoutMillis: 1_000,\n acquireTimeoutMillis: 10_000,\n createTimeoutMillis: 10_000,\n reapIntervalMillis: 500,\n};\n\nconst RUNTIME_POOL: PoolConfig = {\n min: 2,\n max: 10,\n idleTimeoutMillis: 30_000,\n acquireTimeoutMillis: 10_000,\n createTimeoutMillis: 10_000,\n reapIntervalMillis: 1_000,\n};\n\nexport const POOL_PRESETS: Record<DeployTarget, PoolConfig> = {\n functions: FUNCTIONS_POOL,\n runtime: RUNTIME_POOL,\n};\n\nconst POOL_CONFIG_KEYS: ReadonlyArray<[suffix: string, field: keyof PoolConfig]> = [\n [\"poolMin\", \"min\"],\n [\"poolMax\", \"max\"],\n [\"poolIdleTimeoutMs\", \"idleTimeoutMillis\"],\n [\"poolAcquireTimeoutMs\", \"acquireTimeoutMillis\"],\n [\"poolCreateTimeoutMs\", \"createTimeoutMillis\"],\n [\"poolReapIntervalMs\", \"reapIntervalMillis\"],\n];\n\nexport async function resolvePoolOverrides(\n configKey: string,\n resourceConfig: ConfigNamespace,\n): Promise<Partial<PoolConfig>> {\n const overrides: Partial<PoolConfig> = {};\n\n for (const [suffix, field] of POOL_CONFIG_KEYS) {\n const value = await resourceConfig.get(`${configKey}_${suffix}`);\n if (value !== undefined) {\n overrides[field] = Number.parseInt(value, 10);\n }\n }\n\n return overrides;\n}\n\nexport function resolvePoolConfig(\n deployTarget: DeployTarget,\n configOverrides?: Partial<PoolConfig>,\n programmaticOverrides?: Partial<PoolConfig>,\n): PoolConfig {\n return {\n ...POOL_PRESETS[deployTarget],\n ...configOverrides,\n ...programmaticOverrides,\n };\n}\n","import type { ConfigNamespace } from \"@celerity-sdk/config\";\nimport type {\n SqlAuthMode,\n SqlConnectionInfo,\n SqlDatabaseCredentials,\n SqlEngine,\n SqlIamAuth,\n SqlPasswordAuth,\n TokenProvider,\n TokenProviderFactory,\n} from \"./types\";\nimport { SqlDatabaseError } from \"./errors\";\n\nconst DEFAULT_PORTS: Record<SqlEngine, number> = {\n postgres: 5432,\n mysql: 3306,\n};\n\nexport type ConnectionUrlParams = {\n engine: SqlEngine;\n user: string;\n password: string;\n host: string;\n port: number;\n database: string;\n ssl: boolean;\n};\n\nexport function buildConnectionUrl(params: ConnectionUrlParams): string {\n const { engine, user, password, host, port, database, ssl } = params;\n const encodedPassword = encodeURIComponent(password);\n const protocol = engine === \"postgres\" ? \"postgresql\" : \"mysql\";\n const sslParam = ssl ? (engine === \"postgres\" ? \"?sslmode=require\" : \"?ssl=true\") : \"\";\n return `${protocol}://${user}:${encodedPassword}@${host}:${port}/${database}${sslParam}`;\n}\n\nexport async function resolveDatabaseCredentials(\n configKey: string,\n resourceConfig: ConfigNamespace,\n tokenProviderFactory?: TokenProviderFactory,\n): Promise<SqlDatabaseCredentials> {\n const host = await resourceConfig.get(`${configKey}_host`);\n if (!host) {\n throw new SqlDatabaseError(`Missing required config key \"${configKey}_host\"`, configKey);\n }\n\n const user = await resourceConfig.get(`${configKey}_user`);\n if (!user) {\n throw new SqlDatabaseError(`Missing required config key \"${configKey}_user\"`, configKey);\n }\n\n const engineRaw = await resourceConfig.get(`${configKey}_engine`);\n const engine: SqlEngine = engineRaw === \"mysql\" ? \"mysql\" : \"postgres\";\n\n const portRaw = await resourceConfig.get(`${configKey}_port`);\n const port = portRaw ? Number.parseInt(portRaw, 10) : DEFAULT_PORTS[engine];\n\n const databaseName = (await resourceConfig.get(`${configKey}_database`)) ?? configKey;\n\n const authModeRaw = await resourceConfig.get(`${configKey}_authMode`);\n const authMode: SqlAuthMode = authModeRaw === \"iam\" ? \"iam\" : \"password\";\n\n const sslRaw = await resourceConfig.get(`${configKey}_ssl`);\n // IAM auth forces SSL; otherwise default to true\n const ssl = authMode === \"iam\" ? true : sslRaw !== \"false\";\n\n const readHost = await resourceConfig.get(`${configKey}_readHost`);\n\n const connectionInfo: SqlConnectionInfo = {\n host,\n port,\n database: databaseName,\n user,\n engine,\n ssl,\n authMode,\n ...(readHost ? { readHost } : {}),\n };\n\n if (authMode === \"password\") {\n const password = await resourceConfig.get(`${configKey}_password`);\n if (!password) {\n throw new SqlDatabaseError(\n `Missing required config key \"${configKey}_password\" for password auth`,\n configKey,\n );\n }\n return new PasswordCredentials(connectionInfo, password);\n }\n\n if (!tokenProviderFactory) {\n throw new SqlDatabaseError(\n `IAM auth requires a tokenProviderFactory for config key \"${configKey}\"`,\n configKey,\n );\n }\n\n return new IamCredentials(connectionInfo, tokenProviderFactory);\n}\n\nclass PasswordCredentials implements SqlDatabaseCredentials {\n constructor(\n private readonly info: SqlConnectionInfo,\n private readonly password: string,\n ) {}\n\n async getConnectionInfo(): Promise<SqlConnectionInfo> {\n return this.info;\n }\n\n async getPasswordAuth(): Promise<SqlPasswordAuth> {\n const { engine, user, host, port, database, ssl } = this.info;\n const url = buildConnectionUrl({\n engine,\n user,\n password: this.password,\n host,\n port,\n database,\n ssl,\n });\n\n const readUrl = this.info.readHost\n ? buildConnectionUrl({\n engine,\n user,\n password: this.password,\n host: this.info.readHost,\n port,\n database,\n ssl,\n })\n : undefined;\n\n return { password: this.password, url, ...(readUrl ? { readUrl } : {}) };\n }\n\n async getIamAuth(): Promise<SqlIamAuth> {\n throw new SqlDatabaseError(\n 'Cannot call getIamAuth() when authMode is \"password\"',\n this.info.database,\n );\n }\n}\n\nclass IamCredentials implements SqlDatabaseCredentials {\n private tokenProvider: TokenProvider | null = null;\n private readTokenProvider: TokenProvider | null = null;\n\n constructor(\n private readonly info: SqlConnectionInfo,\n private readonly factory: TokenProviderFactory,\n ) {}\n\n async getConnectionInfo(): Promise<SqlConnectionInfo> {\n return this.info;\n }\n\n async getPasswordAuth(): Promise<SqlPasswordAuth> {\n throw new SqlDatabaseError(\n 'Cannot call getPasswordAuth() when authMode is \"iam\"',\n this.info.database,\n );\n }\n\n async getIamAuth(): Promise<SqlIamAuth> {\n const provider = this.getOrCreateTokenProvider();\n const token = await provider.getToken();\n const { engine, user, host, port, database, ssl } = this.info;\n\n const url = buildConnectionUrl({ engine, user, password: token, host, port, database, ssl });\n\n let readUrl: string | undefined;\n if (this.info.readHost) {\n const readProvider = this.getOrCreateReadTokenProvider();\n const readToken = await readProvider.getToken();\n readUrl = buildConnectionUrl({\n engine,\n user,\n password: readToken,\n host: this.info.readHost,\n port,\n database,\n ssl,\n });\n }\n\n return { token, url, ...(readUrl ? { readUrl } : {}) };\n }\n\n private getOrCreateTokenProvider(): TokenProvider {\n if (!this.tokenProvider) {\n this.tokenProvider = this.factory(this.info.host, this.info.port, this.info.user);\n }\n return this.tokenProvider;\n }\n\n private getOrCreateReadTokenProvider(): TokenProvider {\n if (!this.readTokenProvider) {\n this.readTokenProvider = this.factory(this.info.readHost!, this.info.port, this.info.user);\n }\n return this.readTokenProvider;\n }\n}\n","import type { Knex } from \"knex\";\nimport type { DeployTarget, PoolConfig, SqlDatabaseCredentials } from \"./types\";\nimport { resolvePoolConfig } from \"./config\";\n\nexport type CreateKnexOptions = {\n credentials: SqlDatabaseCredentials;\n deployTarget: DeployTarget;\n pool?: Partial<PoolConfig>;\n useReadHost?: boolean;\n};\n\nconst ENGINE_CLIENT: Record<string, string> = {\n postgres: \"pg\",\n mysql: \"mysql2\",\n};\n\nexport async function createKnexInstance(options: CreateKnexOptions): Promise<Knex> {\n const { credentials, deployTarget, pool: poolOverrides, useReadHost } = options;\n\n const pkg = \"knex\";\n const { default: createKnex } = (await import(pkg)) as { default: typeof import(\"knex\").knex };\n\n const info = await credentials.getConnectionInfo();\n const client = ENGINE_CLIENT[info.engine];\n if (!client) {\n throw new Error(`Unsupported SQL engine: \"${info.engine}\"`);\n }\n\n const poolConfig = resolvePoolConfig(deployTarget, poolOverrides);\n const host = useReadHost && info.readHost ? info.readHost : info.host;\n\n const sslConfig = info.ssl ? { rejectUnauthorized: true } : false;\n\n const knexPool = {\n min: poolConfig.min,\n max: poolConfig.max,\n idleTimeoutMillis: poolConfig.idleTimeoutMillis,\n acquireTimeoutMillis: poolConfig.acquireTimeoutMillis,\n createTimeoutMillis: poolConfig.createTimeoutMillis,\n reapIntervalMillis: poolConfig.reapIntervalMillis,\n };\n\n if (info.authMode === \"iam\") {\n // Dynamic connection function — each new pool connection gets a fresh token\n return createKnex({\n client,\n connection: async () => {\n const auth = await credentials.getIamAuth();\n return {\n host,\n port: info.port,\n user: info.user,\n database: info.database,\n password: auth.token,\n ssl: sslConfig,\n };\n },\n pool: knexPool,\n });\n }\n\n // Password auth — static connection config\n const auth = await credentials.getPasswordAuth();\n return createKnex({\n client,\n connection: {\n host,\n port: info.port,\n user: info.user,\n database: info.database,\n password: auth.password,\n ssl: sslConfig,\n },\n pool: knexPool,\n });\n}\n","import type { Knex } from \"knex\";\nimport type { Closeable } from \"@celerity-sdk/types\";\n\nexport class SqlDatabaseInstance implements Closeable {\n private readonly _writer: Knex;\n private readonly _reader: Knex;\n\n constructor(writer: Knex, reader?: Knex) {\n this._writer = writer;\n this._reader = reader ?? writer;\n }\n\n writer(): Knex {\n return this._writer;\n }\n\n reader(): Knex {\n return this._reader;\n }\n\n async close(): Promise<void> {\n await this._writer.destroy();\n // Only destroy reader if it's a separate instance\n if (this._reader !== this._writer) {\n await this._reader.destroy();\n }\n }\n}\n","import \"reflect-metadata\";\nimport { INJECT_METADATA, USE_RESOURCE_METADATA } from \"@celerity-sdk/common\";\n\nexport function sqlWriterToken(resourceName: string): symbol {\n return Symbol.for(`celerity:sqlDatabase:writer:${resourceName}`);\n}\n\nexport function sqlReaderToken(resourceName: string): symbol {\n return Symbol.for(`celerity:sqlDatabase:reader:${resourceName}`);\n}\n\nexport function sqlDatabaseCredentialsToken(resourceName: string): symbol {\n return Symbol.for(`celerity:sqlDatabase:credentials:${resourceName}`);\n}\n\nexport function sqlDatabaseInstanceToken(resourceName: string): symbol {\n return Symbol.for(`celerity:sqlDatabase:instance:${resourceName}`);\n}\n\nexport const DEFAULT_SQL_WRITER_TOKEN = Symbol.for(\"celerity:sqlDatabase:writer:default\");\nexport const DEFAULT_SQL_READER_TOKEN = Symbol.for(\"celerity:sqlDatabase:reader:default\");\nexport const DEFAULT_SQL_CREDENTIALS_TOKEN = Symbol.for(\"celerity:sqlDatabase:credentials:default\");\nexport const DEFAULT_SQL_DATABASE_INSTANCE_TOKEN = Symbol.for(\n \"celerity:sqlDatabase:instance:default\",\n);\n\nfunction createResourceDecorator(\n tokenFn: (name: string) => symbol,\n defaultToken: symbol,\n): (resourceName?: string) => ParameterDecorator {\n return (resourceName?: string): ParameterDecorator => {\n return (target, _propertyKey, parameterIndex) => {\n const token = resourceName ? tokenFn(resourceName) : defaultToken;\n const existing: Map<number, unknown> =\n Reflect.getOwnMetadata(INJECT_METADATA, target) ?? new Map();\n existing.set(parameterIndex, token);\n Reflect.defineMetadata(INJECT_METADATA, existing, target);\n\n if (resourceName) {\n const resources: string[] = Reflect.getOwnMetadata(USE_RESOURCE_METADATA, target) ?? [];\n if (!resources.includes(resourceName)) {\n Reflect.defineMetadata(USE_RESOURCE_METADATA, [...resources, resourceName], target);\n }\n }\n };\n };\n}\n\n/**\n * Parameter decorator that injects the writer {@link Knex} instance for the\n * given SQL database resource. Alias for {@link SqlWriter}.\n *\n * @example\n * ```ts\n * constructor(@SqlDatabase(\"ordersDb\") private db: Knex) {}\n * ```\n */\nexport const SqlDatabase = createResourceDecorator(sqlWriterToken, DEFAULT_SQL_WRITER_TOKEN);\n\n/**\n * Parameter decorator that injects the writer {@link Knex} instance.\n * Explicit alternative to {@link SqlDatabase} when paired with {@link SqlReader}.\n */\nexport const SqlWriter = createResourceDecorator(sqlWriterToken, DEFAULT_SQL_WRITER_TOKEN);\n\n/**\n * Parameter decorator that injects the reader {@link Knex} instance for the\n * given SQL database resource. Falls back to the writer when no read replica\n * is configured.\n */\nexport const SqlReader = createResourceDecorator(sqlReaderToken, DEFAULT_SQL_READER_TOKEN);\n\n/**\n * Parameter decorator that injects {@link SqlDatabaseCredentials} for BYO ORM or SQL library.\n */\nexport const SqlCredentials = createResourceDecorator(\n sqlDatabaseCredentialsToken,\n DEFAULT_SQL_CREDENTIALS_TOKEN,\n);\n","import type { Knex } from \"knex\";\nimport type { ServiceContainer } from \"@celerity-sdk/types\";\nimport type { SqlDatabaseCredentials } from \"./types\";\nimport {\n sqlWriterToken,\n sqlReaderToken,\n sqlDatabaseCredentialsToken,\n DEFAULT_SQL_WRITER_TOKEN,\n DEFAULT_SQL_READER_TOKEN,\n DEFAULT_SQL_CREDENTIALS_TOKEN,\n} from \"./decorators\";\n\n/**\n * Resolves the writer {@link Knex} instance from the DI container.\n * For function-based handlers where parameter decorators aren't available.\n *\n * @param container - The service container (typically `context.container`).\n * @param resourceName - The blueprint resource name. Omit for default.\n */\nexport function getSqlWriter(container: ServiceContainer, resourceName?: string): Promise<Knex> {\n const token = resourceName ? sqlWriterToken(resourceName) : DEFAULT_SQL_WRITER_TOKEN;\n return container.resolve<Knex>(token);\n}\n\n/**\n * Resolves the reader {@link Knex} instance from the DI container.\n * Falls back to the writer when no read replica is configured.\n *\n * @param container - The service container (typically `context.container`).\n * @param resourceName - The blueprint resource name. Omit for default.\n */\nexport function getSqlReader(container: ServiceContainer, resourceName?: string): Promise<Knex> {\n const token = resourceName ? sqlReaderToken(resourceName) : DEFAULT_SQL_READER_TOKEN;\n return container.resolve<Knex>(token);\n}\n\n/**\n * Resolves {@link SqlDatabaseCredentials} from the DI container for BYO ORM.\n *\n * @param container - The service container (typically `context.container`).\n * @param resourceName - The blueprint resource name. Omit for default.\n */\nexport function getSqlCredentials(\n container: ServiceContainer,\n resourceName?: string,\n): Promise<SqlDatabaseCredentials> {\n const token = resourceName\n ? sqlDatabaseCredentialsToken(resourceName)\n : DEFAULT_SQL_CREDENTIALS_TOKEN;\n return container.resolve<SqlDatabaseCredentials>(token);\n}\n","import createDebug from \"debug\";\nimport type { CelerityLayer, BaseHandlerContext, ServiceContainer } from \"@celerity-sdk/types\";\nimport { CONFIG_SERVICE_TOKEN } from \"@celerity-sdk/common\";\nimport {\n type ConfigService,\n type ConfigNamespace,\n captureResourceLinks,\n getLinksOfType,\n RESOURCE_CONFIG_NAMESPACE,\n} from \"@celerity-sdk/config\";\nimport type { SqlDatabaseLayerConfig } from \"./config\";\nimport type { TokenProviderFactory } from \"./types\";\nimport {\n captureSqlDatabaseLayerConfig,\n resolvePoolOverrides,\n resolveTokenProviderFactory,\n} from \"./config\";\nimport { resolveDatabaseCredentials } from \"./credentials\";\nimport { createKnexInstance } from \"./factory\";\nimport { SqlDatabaseInstance } from \"./sql-database\";\nimport {\n sqlWriterToken,\n sqlReaderToken,\n sqlDatabaseCredentialsToken,\n sqlDatabaseInstanceToken,\n DEFAULT_SQL_WRITER_TOKEN,\n DEFAULT_SQL_READER_TOKEN,\n DEFAULT_SQL_CREDENTIALS_TOKEN,\n DEFAULT_SQL_DATABASE_INSTANCE_TOKEN,\n} from \"./decorators\";\n\nconst debug = createDebug(\"celerity:sql-database\");\n\n/**\n * System layer that auto-registers per-resource SQL database instances\n * in the DI container.\n *\n * Reads resource link topology from `CELERITY_RESOURCE_LINKS` and resolves\n * connection credentials + pool config from the ConfigService \"resources\"\n * namespace. Must run after ConfigLayer in the layer pipeline.\n */\nexport class SqlDatabaseLayer implements CelerityLayer<BaseHandlerContext> {\n private initialized = false;\n private config: SqlDatabaseLayerConfig | null = null;\n\n async handle(context: BaseHandlerContext, next: () => Promise<unknown>): Promise<unknown> {\n if (!this.initialized) {\n this.config = captureSqlDatabaseLayerConfig();\n\n const links = captureResourceLinks();\n const sqlLinks = getLinksOfType(links, \"sqlDatabase\");\n\n if (sqlLinks.size > 0) {\n const configService = await context.container.resolve<ConfigService>(CONFIG_SERVICE_TOKEN);\n const resourceConfig = configService.namespace(RESOURCE_CONFIG_NAMESPACE);\n const tokenProviderFactory = await resolveTokenProviderFactory(this.config.platform);\n\n for (const [resourceName, configKey] of sqlLinks) {\n await this.initializeResource(\n context.container,\n resourceName,\n configKey,\n resourceConfig,\n tokenProviderFactory,\n );\n }\n\n if (sqlLinks.size === 1) {\n const [resourceName] = [...sqlLinks.keys()];\n await this.registerDefaultTokens(context.container, resourceName);\n }\n }\n\n this.initialized = true;\n }\n\n return next();\n }\n\n private async initializeResource(\n container: ServiceContainer,\n resourceName: string,\n configKey: string,\n resourceConfig: ConfigNamespace,\n tokenProviderFactory: TokenProviderFactory | undefined,\n ): Promise<void> {\n debug(\"resolving sql database resource %s (configKey=%s)\", resourceName, configKey);\n\n const credentials = await resolveDatabaseCredentials(\n configKey,\n resourceConfig,\n tokenProviderFactory,\n );\n const poolOverrides = await resolvePoolOverrides(configKey, resourceConfig);\n const info = await credentials.getConnectionInfo();\n\n const writerKnex = await createKnexInstance({\n credentials,\n deployTarget: this.config!.deployTarget,\n pool: poolOverrides,\n });\n\n let readerKnex = writerKnex;\n if (info.readHost) {\n readerKnex = await createKnexInstance({\n credentials,\n deployTarget: this.config!.deployTarget,\n pool: poolOverrides,\n useReadHost: true,\n });\n }\n\n const instance = new SqlDatabaseInstance(writerKnex, readerKnex);\n\n container.register(sqlDatabaseInstanceToken(resourceName), {\n useValue: instance,\n onClose: () => instance.close(),\n });\n container.register(sqlWriterToken(resourceName), { useValue: writerKnex });\n container.register(sqlReaderToken(resourceName), { useValue: readerKnex });\n container.register(sqlDatabaseCredentialsToken(resourceName), { useValue: credentials });\n\n debug(\"registered sql database resource %s\", resourceName);\n }\n\n private async registerDefaultTokens(\n container: ServiceContainer,\n resourceName: string,\n ): Promise<void> {\n const instance = await container.resolve(sqlDatabaseInstanceToken(resourceName));\n const writer = await container.resolve(sqlWriterToken(resourceName));\n const reader = await container.resolve(sqlReaderToken(resourceName));\n const creds = await container.resolve(sqlDatabaseCredentialsToken(resourceName));\n\n container.register(DEFAULT_SQL_DATABASE_INSTANCE_TOKEN, { useValue: instance });\n container.register(DEFAULT_SQL_WRITER_TOKEN, { useValue: writer });\n container.register(DEFAULT_SQL_READER_TOKEN, { useValue: reader });\n container.register(DEFAULT_SQL_CREDENTIALS_TOKEN, { useValue: creds });\n\n debug(\"registered default sql database tokens → %s\", resourceName);\n }\n}\n"],"mappings":"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","names":["createRdsTokenProviderFactory","region","hostname","port","username","RdsTokenProvider","TOKEN_CACHE_MS","cached","getToken","now","Date","expiresAt","token","pkg","Signer","signer","getAuthToken","SqlDatabaseError","Error","message","database","options","name","captureSqlDatabaseLayerConfig","deployTarget","process","env","CELERITY_RUNTIME","platform","CelerityConfig","getPlatform","resolveTokenProviderFactory","undefined","mod","createRdsTokenProviderFactory","FUNCTIONS_POOL","min","max","idleTimeoutMillis","acquireTimeoutMillis","createTimeoutMillis","reapIntervalMillis","RUNTIME_POOL","POOL_PRESETS","functions","runtime","POOL_CONFIG_KEYS","resolvePoolOverrides","configKey","resourceConfig","overrides","suffix","field","value","get","Number","parseInt","resolvePoolConfig","configOverrides","programmaticOverrides","DEFAULT_PORTS","postgres","mysql","buildConnectionUrl","params","engine","user","password","host","port","database","ssl","encodedPassword","encodeURIComponent","protocol","sslParam","resolveDatabaseCredentials","configKey","resourceConfig","tokenProviderFactory","get","SqlDatabaseError","engineRaw","portRaw","Number","parseInt","databaseName","authModeRaw","authMode","sslRaw","readHost","connectionInfo","PasswordCredentials","IamCredentials","info","getConnectionInfo","getPasswordAuth","url","readUrl","undefined","getIamAuth","tokenProvider","readTokenProvider","factory","provider","getOrCreateTokenProvider","token","getToken","readProvider","getOrCreateReadTokenProvider","readToken","ENGINE_CLIENT","postgres","mysql","createKnexInstance","options","credentials","deployTarget","pool","poolOverrides","useReadHost","pkg","default","createKnex","info","getConnectionInfo","client","engine","Error","poolConfig","resolvePoolConfig","host","readHost","sslConfig","ssl","rejectUnauthorized","knexPool","min","max","idleTimeoutMillis","acquireTimeoutMillis","createTimeoutMillis","reapIntervalMillis","authMode","connection","auth","getIamAuth","port","user","database","password","token","getPasswordAuth","SqlDatabaseInstance","_writer","_reader","writer","reader","close","destroy","sqlWriterToken","resourceName","Symbol","for","sqlReaderToken","sqlDatabaseCredentialsToken","sqlDatabaseInstanceToken","DEFAULT_SQL_WRITER_TOKEN","DEFAULT_SQL_READER_TOKEN","DEFAULT_SQL_CREDENTIALS_TOKEN","DEFAULT_SQL_DATABASE_INSTANCE_TOKEN","createResourceDecorator","tokenFn","defaultToken","target","_propertyKey","parameterIndex","token","existing","Reflect","getOwnMetadata","INJECT_METADATA","Map","set","defineMetadata","resources","USE_RESOURCE_METADATA","includes","SqlDatabase","SqlWriter","SqlReader","SqlCredentials","getSqlWriter","container","resourceName","token","sqlWriterToken","DEFAULT_SQL_WRITER_TOKEN","resolve","getSqlReader","sqlReaderToken","DEFAULT_SQL_READER_TOKEN","getSqlCredentials","sqlDatabaseCredentialsToken","DEFAULT_SQL_CREDENTIALS_TOKEN","import_common","import_config","debug","createDebug","SqlDatabaseLayer","initialized","config","handle","context","next","captureSqlDatabaseLayerConfig","links","captureResourceLinks","sqlLinks","getLinksOfType","size","configService","container","resolve","CONFIG_SERVICE_TOKEN","resourceConfig","namespace","RESOURCE_CONFIG_NAMESPACE","tokenProviderFactory","resolveTokenProviderFactory","platform","resourceName","configKey","initializeResource","keys","registerDefaultTokens","credentials","resolveDatabaseCredentials","poolOverrides","resolvePoolOverrides","info","getConnectionInfo","writerKnex","createKnexInstance","deployTarget","pool","readerKnex","readHost","useReadHost","instance","SqlDatabaseInstance","register","sqlDatabaseInstanceToken","useValue","onClose","close","sqlWriterToken","sqlReaderToken","sqlDatabaseCredentialsToken","writer","reader","creds","DEFAULT_SQL_DATABASE_INSTANCE_TOKEN","DEFAULT_SQL_WRITER_TOKEN","DEFAULT_SQL_READER_TOKEN","DEFAULT_SQL_CREDENTIALS_TOKEN"]}
package/dist/index.d.cts CHANGED
@@ -1,2 +1,176 @@
1
+ import { Platform, ConfigNamespace } from '@celerity-sdk/config';
2
+ import { Knex } from 'knex';
3
+ import { Closeable, ServiceContainer, CelerityLayer, BaseHandlerContext } from '@celerity-sdk/types';
1
4
 
2
- export { }
5
+ type SqlEngine = "postgres" | "mysql";
6
+ type SqlAuthMode = "password" | "iam";
7
+ type DeployTarget = "functions" | "runtime";
8
+ type PoolConfig = {
9
+ min: number;
10
+ max: number;
11
+ idleTimeoutMillis: number;
12
+ acquireTimeoutMillis: number;
13
+ createTimeoutMillis: number;
14
+ reapIntervalMillis: number;
15
+ };
16
+ type SqlConnectionInfo = {
17
+ host: string;
18
+ readHost?: string;
19
+ port: number;
20
+ database: string;
21
+ user: string;
22
+ engine: SqlEngine;
23
+ ssl: boolean;
24
+ authMode: SqlAuthMode;
25
+ };
26
+ type SqlPasswordAuth = {
27
+ password: string;
28
+ url: string;
29
+ readUrl?: string;
30
+ };
31
+ type SqlIamAuth = {
32
+ token: string;
33
+ url: string;
34
+ readUrl?: string;
35
+ };
36
+ interface SqlDatabaseCredentials {
37
+ getConnectionInfo(): Promise<SqlConnectionInfo>;
38
+ getPasswordAuth(): Promise<SqlPasswordAuth>;
39
+ getIamAuth(): Promise<SqlIamAuth>;
40
+ }
41
+ interface TokenProvider {
42
+ getToken(): Promise<string>;
43
+ }
44
+ type TokenProviderFactory = (hostname: string, port: number, username: string) => TokenProvider;
45
+
46
+ declare class SqlDatabaseError extends Error {
47
+ readonly database: string;
48
+ constructor(message: string, database: string, options?: {
49
+ cause?: unknown;
50
+ });
51
+ }
52
+
53
+ type SqlDatabaseLayerConfig = {
54
+ deployTarget: DeployTarget;
55
+ platform: Platform;
56
+ };
57
+ declare function captureSqlDatabaseLayerConfig(): SqlDatabaseLayerConfig;
58
+ declare const POOL_PRESETS: Record<DeployTarget, PoolConfig>;
59
+ declare function resolvePoolOverrides(configKey: string, resourceConfig: ConfigNamespace): Promise<Partial<PoolConfig>>;
60
+ declare function resolvePoolConfig(deployTarget: DeployTarget, configOverrides?: Partial<PoolConfig>, programmaticOverrides?: Partial<PoolConfig>): PoolConfig;
61
+
62
+ type ConnectionUrlParams = {
63
+ engine: SqlEngine;
64
+ user: string;
65
+ password: string;
66
+ host: string;
67
+ port: number;
68
+ database: string;
69
+ ssl: boolean;
70
+ };
71
+ declare function buildConnectionUrl(params: ConnectionUrlParams): string;
72
+ declare function resolveDatabaseCredentials(configKey: string, resourceConfig: ConfigNamespace, tokenProviderFactory?: TokenProviderFactory): Promise<SqlDatabaseCredentials>;
73
+
74
+ declare class RdsTokenProvider implements TokenProvider {
75
+ private readonly hostname;
76
+ private readonly port;
77
+ private readonly username;
78
+ private readonly region?;
79
+ private cached;
80
+ constructor(hostname: string, port: number, username: string, region?: string | undefined);
81
+ getToken(): Promise<string>;
82
+ }
83
+ declare function createRdsTokenProviderFactory(region?: string): TokenProviderFactory;
84
+
85
+ type CreateKnexOptions = {
86
+ credentials: SqlDatabaseCredentials;
87
+ deployTarget: DeployTarget;
88
+ pool?: Partial<PoolConfig>;
89
+ useReadHost?: boolean;
90
+ };
91
+ declare function createKnexInstance(options: CreateKnexOptions): Promise<Knex>;
92
+
93
+ declare class SqlDatabaseInstance implements Closeable {
94
+ private readonly _writer;
95
+ private readonly _reader;
96
+ constructor(writer: Knex, reader?: Knex);
97
+ writer(): Knex;
98
+ reader(): Knex;
99
+ close(): Promise<void>;
100
+ }
101
+
102
+ declare function sqlWriterToken(resourceName: string): symbol;
103
+ declare function sqlReaderToken(resourceName: string): symbol;
104
+ declare function sqlDatabaseCredentialsToken(resourceName: string): symbol;
105
+ declare function sqlDatabaseInstanceToken(resourceName: string): symbol;
106
+ declare const DEFAULT_SQL_WRITER_TOKEN: unique symbol;
107
+ declare const DEFAULT_SQL_READER_TOKEN: unique symbol;
108
+ declare const DEFAULT_SQL_CREDENTIALS_TOKEN: unique symbol;
109
+ declare const DEFAULT_SQL_DATABASE_INSTANCE_TOKEN: unique symbol;
110
+ /**
111
+ * Parameter decorator that injects the writer {@link Knex} instance for the
112
+ * given SQL database resource. Alias for {@link SqlWriter}.
113
+ *
114
+ * @example
115
+ * ```ts
116
+ * constructor(@SqlDatabase("ordersDb") private db: Knex) {}
117
+ * ```
118
+ */
119
+ declare const SqlDatabase: (resourceName?: string) => ParameterDecorator;
120
+ /**
121
+ * Parameter decorator that injects the writer {@link Knex} instance.
122
+ * Explicit alternative to {@link SqlDatabase} when paired with {@link SqlReader}.
123
+ */
124
+ declare const SqlWriter: (resourceName?: string) => ParameterDecorator;
125
+ /**
126
+ * Parameter decorator that injects the reader {@link Knex} instance for the
127
+ * given SQL database resource. Falls back to the writer when no read replica
128
+ * is configured.
129
+ */
130
+ declare const SqlReader: (resourceName?: string) => ParameterDecorator;
131
+ /**
132
+ * Parameter decorator that injects {@link SqlDatabaseCredentials} for BYO ORM or SQL library.
133
+ */
134
+ declare const SqlCredentials: (resourceName?: string) => ParameterDecorator;
135
+
136
+ /**
137
+ * Resolves the writer {@link Knex} instance from the DI container.
138
+ * For function-based handlers where parameter decorators aren't available.
139
+ *
140
+ * @param container - The service container (typically `context.container`).
141
+ * @param resourceName - The blueprint resource name. Omit for default.
142
+ */
143
+ declare function getSqlWriter(container: ServiceContainer, resourceName?: string): Promise<Knex>;
144
+ /**
145
+ * Resolves the reader {@link Knex} instance from the DI container.
146
+ * Falls back to the writer when no read replica is configured.
147
+ *
148
+ * @param container - The service container (typically `context.container`).
149
+ * @param resourceName - The blueprint resource name. Omit for default.
150
+ */
151
+ declare function getSqlReader(container: ServiceContainer, resourceName?: string): Promise<Knex>;
152
+ /**
153
+ * Resolves {@link SqlDatabaseCredentials} from the DI container for BYO ORM.
154
+ *
155
+ * @param container - The service container (typically `context.container`).
156
+ * @param resourceName - The blueprint resource name. Omit for default.
157
+ */
158
+ declare function getSqlCredentials(container: ServiceContainer, resourceName?: string): Promise<SqlDatabaseCredentials>;
159
+
160
+ /**
161
+ * System layer that auto-registers per-resource SQL database instances
162
+ * in the DI container.
163
+ *
164
+ * Reads resource link topology from `CELERITY_RESOURCE_LINKS` and resolves
165
+ * connection credentials + pool config from the ConfigService "resources"
166
+ * namespace. Must run after ConfigLayer in the layer pipeline.
167
+ */
168
+ declare class SqlDatabaseLayer implements CelerityLayer<BaseHandlerContext> {
169
+ private initialized;
170
+ private config;
171
+ handle(context: BaseHandlerContext, next: () => Promise<unknown>): Promise<unknown>;
172
+ private initializeResource;
173
+ private registerDefaultTokens;
174
+ }
175
+
176
+ export { type ConnectionUrlParams, type CreateKnexOptions, DEFAULT_SQL_CREDENTIALS_TOKEN, DEFAULT_SQL_DATABASE_INSTANCE_TOKEN, DEFAULT_SQL_READER_TOKEN, DEFAULT_SQL_WRITER_TOKEN, type DeployTarget, POOL_PRESETS, type PoolConfig, RdsTokenProvider, type SqlAuthMode, type SqlConnectionInfo, SqlCredentials, SqlDatabase, type SqlDatabaseCredentials, SqlDatabaseError, SqlDatabaseInstance, SqlDatabaseLayer, type SqlDatabaseLayerConfig, type SqlEngine, type SqlIamAuth, type SqlPasswordAuth, SqlReader, SqlWriter, type TokenProvider, type TokenProviderFactory, buildConnectionUrl, captureSqlDatabaseLayerConfig, createKnexInstance, createRdsTokenProviderFactory, getSqlCredentials, getSqlReader, getSqlWriter, resolveDatabaseCredentials, resolvePoolConfig, resolvePoolOverrides, sqlDatabaseCredentialsToken, sqlDatabaseInstanceToken, sqlReaderToken, sqlWriterToken };
package/dist/index.d.ts CHANGED
@@ -1,2 +1,176 @@
1
+ import { Platform, ConfigNamespace } from '@celerity-sdk/config';
2
+ import { Knex } from 'knex';
3
+ import { Closeable, ServiceContainer, CelerityLayer, BaseHandlerContext } from '@celerity-sdk/types';
1
4
 
2
- export { }
5
+ type SqlEngine = "postgres" | "mysql";
6
+ type SqlAuthMode = "password" | "iam";
7
+ type DeployTarget = "functions" | "runtime";
8
+ type PoolConfig = {
9
+ min: number;
10
+ max: number;
11
+ idleTimeoutMillis: number;
12
+ acquireTimeoutMillis: number;
13
+ createTimeoutMillis: number;
14
+ reapIntervalMillis: number;
15
+ };
16
+ type SqlConnectionInfo = {
17
+ host: string;
18
+ readHost?: string;
19
+ port: number;
20
+ database: string;
21
+ user: string;
22
+ engine: SqlEngine;
23
+ ssl: boolean;
24
+ authMode: SqlAuthMode;
25
+ };
26
+ type SqlPasswordAuth = {
27
+ password: string;
28
+ url: string;
29
+ readUrl?: string;
30
+ };
31
+ type SqlIamAuth = {
32
+ token: string;
33
+ url: string;
34
+ readUrl?: string;
35
+ };
36
+ interface SqlDatabaseCredentials {
37
+ getConnectionInfo(): Promise<SqlConnectionInfo>;
38
+ getPasswordAuth(): Promise<SqlPasswordAuth>;
39
+ getIamAuth(): Promise<SqlIamAuth>;
40
+ }
41
+ interface TokenProvider {
42
+ getToken(): Promise<string>;
43
+ }
44
+ type TokenProviderFactory = (hostname: string, port: number, username: string) => TokenProvider;
45
+
46
+ declare class SqlDatabaseError extends Error {
47
+ readonly database: string;
48
+ constructor(message: string, database: string, options?: {
49
+ cause?: unknown;
50
+ });
51
+ }
52
+
53
+ type SqlDatabaseLayerConfig = {
54
+ deployTarget: DeployTarget;
55
+ platform: Platform;
56
+ };
57
+ declare function captureSqlDatabaseLayerConfig(): SqlDatabaseLayerConfig;
58
+ declare const POOL_PRESETS: Record<DeployTarget, PoolConfig>;
59
+ declare function resolvePoolOverrides(configKey: string, resourceConfig: ConfigNamespace): Promise<Partial<PoolConfig>>;
60
+ declare function resolvePoolConfig(deployTarget: DeployTarget, configOverrides?: Partial<PoolConfig>, programmaticOverrides?: Partial<PoolConfig>): PoolConfig;
61
+
62
+ type ConnectionUrlParams = {
63
+ engine: SqlEngine;
64
+ user: string;
65
+ password: string;
66
+ host: string;
67
+ port: number;
68
+ database: string;
69
+ ssl: boolean;
70
+ };
71
+ declare function buildConnectionUrl(params: ConnectionUrlParams): string;
72
+ declare function resolveDatabaseCredentials(configKey: string, resourceConfig: ConfigNamespace, tokenProviderFactory?: TokenProviderFactory): Promise<SqlDatabaseCredentials>;
73
+
74
+ declare class RdsTokenProvider implements TokenProvider {
75
+ private readonly hostname;
76
+ private readonly port;
77
+ private readonly username;
78
+ private readonly region?;
79
+ private cached;
80
+ constructor(hostname: string, port: number, username: string, region?: string | undefined);
81
+ getToken(): Promise<string>;
82
+ }
83
+ declare function createRdsTokenProviderFactory(region?: string): TokenProviderFactory;
84
+
85
+ type CreateKnexOptions = {
86
+ credentials: SqlDatabaseCredentials;
87
+ deployTarget: DeployTarget;
88
+ pool?: Partial<PoolConfig>;
89
+ useReadHost?: boolean;
90
+ };
91
+ declare function createKnexInstance(options: CreateKnexOptions): Promise<Knex>;
92
+
93
+ declare class SqlDatabaseInstance implements Closeable {
94
+ private readonly _writer;
95
+ private readonly _reader;
96
+ constructor(writer: Knex, reader?: Knex);
97
+ writer(): Knex;
98
+ reader(): Knex;
99
+ close(): Promise<void>;
100
+ }
101
+
102
+ declare function sqlWriterToken(resourceName: string): symbol;
103
+ declare function sqlReaderToken(resourceName: string): symbol;
104
+ declare function sqlDatabaseCredentialsToken(resourceName: string): symbol;
105
+ declare function sqlDatabaseInstanceToken(resourceName: string): symbol;
106
+ declare const DEFAULT_SQL_WRITER_TOKEN: unique symbol;
107
+ declare const DEFAULT_SQL_READER_TOKEN: unique symbol;
108
+ declare const DEFAULT_SQL_CREDENTIALS_TOKEN: unique symbol;
109
+ declare const DEFAULT_SQL_DATABASE_INSTANCE_TOKEN: unique symbol;
110
+ /**
111
+ * Parameter decorator that injects the writer {@link Knex} instance for the
112
+ * given SQL database resource. Alias for {@link SqlWriter}.
113
+ *
114
+ * @example
115
+ * ```ts
116
+ * constructor(@SqlDatabase("ordersDb") private db: Knex) {}
117
+ * ```
118
+ */
119
+ declare const SqlDatabase: (resourceName?: string) => ParameterDecorator;
120
+ /**
121
+ * Parameter decorator that injects the writer {@link Knex} instance.
122
+ * Explicit alternative to {@link SqlDatabase} when paired with {@link SqlReader}.
123
+ */
124
+ declare const SqlWriter: (resourceName?: string) => ParameterDecorator;
125
+ /**
126
+ * Parameter decorator that injects the reader {@link Knex} instance for the
127
+ * given SQL database resource. Falls back to the writer when no read replica
128
+ * is configured.
129
+ */
130
+ declare const SqlReader: (resourceName?: string) => ParameterDecorator;
131
+ /**
132
+ * Parameter decorator that injects {@link SqlDatabaseCredentials} for BYO ORM or SQL library.
133
+ */
134
+ declare const SqlCredentials: (resourceName?: string) => ParameterDecorator;
135
+
136
+ /**
137
+ * Resolves the writer {@link Knex} instance from the DI container.
138
+ * For function-based handlers where parameter decorators aren't available.
139
+ *
140
+ * @param container - The service container (typically `context.container`).
141
+ * @param resourceName - The blueprint resource name. Omit for default.
142
+ */
143
+ declare function getSqlWriter(container: ServiceContainer, resourceName?: string): Promise<Knex>;
144
+ /**
145
+ * Resolves the reader {@link Knex} instance from the DI container.
146
+ * Falls back to the writer when no read replica is configured.
147
+ *
148
+ * @param container - The service container (typically `context.container`).
149
+ * @param resourceName - The blueprint resource name. Omit for default.
150
+ */
151
+ declare function getSqlReader(container: ServiceContainer, resourceName?: string): Promise<Knex>;
152
+ /**
153
+ * Resolves {@link SqlDatabaseCredentials} from the DI container for BYO ORM.
154
+ *
155
+ * @param container - The service container (typically `context.container`).
156
+ * @param resourceName - The blueprint resource name. Omit for default.
157
+ */
158
+ declare function getSqlCredentials(container: ServiceContainer, resourceName?: string): Promise<SqlDatabaseCredentials>;
159
+
160
+ /**
161
+ * System layer that auto-registers per-resource SQL database instances
162
+ * in the DI container.
163
+ *
164
+ * Reads resource link topology from `CELERITY_RESOURCE_LINKS` and resolves
165
+ * connection credentials + pool config from the ConfigService "resources"
166
+ * namespace. Must run after ConfigLayer in the layer pipeline.
167
+ */
168
+ declare class SqlDatabaseLayer implements CelerityLayer<BaseHandlerContext> {
169
+ private initialized;
170
+ private config;
171
+ handle(context: BaseHandlerContext, next: () => Promise<unknown>): Promise<unknown>;
172
+ private initializeResource;
173
+ private registerDefaultTokens;
174
+ }
175
+
176
+ export { type ConnectionUrlParams, type CreateKnexOptions, DEFAULT_SQL_CREDENTIALS_TOKEN, DEFAULT_SQL_DATABASE_INSTANCE_TOKEN, DEFAULT_SQL_READER_TOKEN, DEFAULT_SQL_WRITER_TOKEN, type DeployTarget, POOL_PRESETS, type PoolConfig, RdsTokenProvider, type SqlAuthMode, type SqlConnectionInfo, SqlCredentials, SqlDatabase, type SqlDatabaseCredentials, SqlDatabaseError, SqlDatabaseInstance, SqlDatabaseLayer, type SqlDatabaseLayerConfig, type SqlEngine, type SqlIamAuth, type SqlPasswordAuth, SqlReader, SqlWriter, type TokenProvider, type TokenProviderFactory, buildConnectionUrl, captureSqlDatabaseLayerConfig, createKnexInstance, createRdsTokenProviderFactory, getSqlCredentials, getSqlReader, getSqlWriter, resolveDatabaseCredentials, resolvePoolConfig, resolvePoolOverrides, sqlDatabaseCredentialsToken, sqlDatabaseInstanceToken, sqlReaderToken, sqlWriterToken };