feat: slonik major upgrade (#7897)

This commit is contained in:
Laurin 2026-04-02 12:43:37 +02:00 committed by GitHub
parent 615fb095d8
commit 84043d9b3a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 809 additions and 475 deletions

View file

@ -353,7 +353,7 @@ export function initSeed() {
const result = await pool.any(psql`
UPDATE "organization_access_tokens"
SET "expires_at" = NOW()
WHERE id IN (${psql.join(tokenIds, psql`, `)}) AND organization_id = ${organization.id}
WHERE id IN (${psql.join(tokenIds, psql.fragment`, `)}) AND organization_id = ${organization.id}
RETURNING
"id"
`);

View file

@ -1,3 +1,4 @@
import { pollFor } from 'testkit/flow';
import { graphql } from 'testkit/gql';
import { ResourceAssignmentModeType } from 'testkit/gql/graphql';
import { execute } from 'testkit/graphql';
@ -115,15 +116,19 @@ test.concurrent('cannot delete a role with members', async ({ expect }) => {
test.concurrent('email invitation', async ({ expect }) => {
const seed = initSeed();
const { createOrg } = await seed.createOwner();
const { inviteMember } = await createOrg();
const { inviteMember, organization } = await createOrg();
const inviteEmail = seed.generateEmail();
const invitationResult = await inviteMember(inviteEmail);
const inviteCode = invitationResult.ok?.createdOrganizationInvitation.code;
expect(inviteCode).toBeDefined();
const sentEmails = await history();
expect(sentEmails).toContainEqual(expect.objectContaining({ to: inviteEmail }));
await pollFor(async () => {
const sentEmails = await history(inviteEmail);
return sentEmails.length > 0;
});
const sentEmails = await history(inviteEmail);
expect(sentEmails[0].subject).toEqual('You have been invited to join ' + organization.slug);
});
test.concurrent('can not invite with role not existing in organization', async ({ expect }) => {

View file

@ -175,7 +175,6 @@
"eslint@8.57.1": "patches/eslint@8.57.1.patch",
"@graphql-eslint/eslint-plugin@3.20.1": "patches/@graphql-eslint__eslint-plugin@3.20.1.patch",
"got@14.4.7": "patches/got@14.4.7.patch",
"slonik@30.4.4": "patches/slonik@30.4.4.patch",
"@oclif/core@3.26.6": "patches/@oclif__core@3.26.6.patch",
"oclif": "patches/oclif.patch",
"graphiql": "patches/graphiql.patch",
@ -184,7 +183,9 @@
"p-cancelable@4.0.1": "patches/p-cancelable@4.0.1.patch",
"bentocache": "patches/bentocache.patch",
"@graphql-codegen/schema-ast": "patches/@graphql-codegen__schema-ast.patch",
"@fastify/vite": "patches/@fastify__vite.patch"
"@fastify/vite": "patches/@fastify__vite.patch",
"@slonik/pg-driver": "patches/@slonik__pg-driver.patch",
"slonik": "patches/slonik.patch"
},
"onlyBuiltDependencies": [
"msw"

View file

@ -7,8 +7,11 @@
".": "./src/index.ts"
},
"dependencies": {
"slonik": "30.4.4",
"slonik-interceptor-query-logging": "46.4.0"
"@standard-schema/spec": "1.0.0",
"slonik": "48.13.2",
"slonik-interceptor-query-logging": "48.13.2",
"slonik-sql-tag-raw": "48.13.2",
"zod": "3.25.76"
},
"devDependencies": {
"@hive/service-common": "workspace:*"

View file

@ -4,11 +4,10 @@ export {
type CommonQueryMethods,
} from './postgres-database-pool';
export { type PostgresConnectionParamaters, createConnectionString } from './connection-string';
export { psql } from './psql';
export { psql, type TaggedTemplateLiteralInvocation } from './psql';
export {
UniqueIntegrityConstraintViolationError,
ForeignKeyIntegrityConstraintViolationError,
type TaggedTemplateLiteralInvocation,
type PrimitiveValueExpression,
type SerializableValue,
type Interceptor,

View file

@ -0,0 +1,91 @@
import type { PoolClient } from 'pg';
import { sql, type DatabasePool, type DatabasePoolConnection } from 'slonik';
import { raw } from 'slonik-sql-tag-raw';
/**
* Bridge {slonik.DatabasePool} to an {pg.Pool} for usage with Postgraphile Workers.
*
* This is a very very pragmatic approach, since slonik moved away from using {pg.Pool} internally.
* https://github.com/gajus/slonik/issues/768
**/
export class PgPoolBridge {
constructor(private pool: DatabasePool) {}
end(): never {
throw new Error('Not implemented.');
}
async connect(): Promise<PoolClient> {
const pgClientAvailableP = Promise.withResolvers<any>();
const pgClientReleasedP = Promise.withResolvers<void>();
// slonik connect works in a way where the client is acquired for the callback handler closure only.
// It is released once the Promise returned from the handler resolves.
// We need to be a bit creative to support the "pg.Pool" API and obviously
// trust graphile-workers to call the `release` method on our fake {pg.Client} :)
// so the client is released back to the pool
void this.pool.connect(async client => {
pgClientAvailableP.resolve(new PgClientBridge(client, pgClientReleasedP.resolve));
await pgClientReleasedP.promise;
});
return pgClientAvailableP.promise;
}
/** Some of graphile-workers logic just calls the `query` method on {pg.Pool} - without first acquiring a connection. */
query(query: unknown, values?: unknown, callback?: unknown): any {
// not used, but just in case so we can catch it in the future...
if (typeof callback !== 'undefined') {
throw new Error('PgClientBridge.query: callback not supported');
}
if ((typeof query !== 'string' && typeof query !== 'object') || !query) {
throw new Error('PgClientBridge.query: unsupported query input');
}
if (typeof query === 'string') {
return this.pool.query(sql.unsafe`${raw(query, values as any)}`);
}
return this.pool.query(sql.unsafe`${raw((query as any).text as any, (query as any).values)}`);
}
on(): this {
// Note: we can skip setting up event handlers, as graphile workers is only setting up error handlers to avoid uncaught exceptions
// For us, the error handlers are already set up by slonik
// https://github.com/graphile/worker/blob/5650fbc4406fa3ce197b2ab582e08fd20974e50c/src/lib.ts#L351-L359
return this;
}
removeListener(): this {
// Note: we can skip tearing down event handlers, since we ship setting them up in the first place
// https://github.com/graphile/worker/blob/5650fbc4406fa3ce197b2ab582e08fd20974e50c/src/lib.ts#L351-L359
return this;
}
}
class PgClientBridge {
constructor(
private connection: DatabasePoolConnection,
/** This is invoked for again releasing the connection. */
public release: () => void,
) {}
query(query: unknown, values?: unknown, callback?: unknown): any {
if (typeof callback !== 'undefined') {
throw new Error('PgClientBridge.query: callback not supported');
}
if ((typeof query !== 'string' && typeof query !== 'object') || !query) {
throw new Error('PgClientBridge.query: unsupported query input');
}
if (typeof query === 'string') {
return this.connection.query(sql.unsafe`${raw(query, values as any)}`);
}
return this.connection.query(
sql.unsafe`${raw((query as any).text as any, (query as any).values)}`,
);
}
}

View file

@ -1,54 +1,58 @@
import type { Pool } from 'pg';
import {
createPool,
createTypeParserPreset,
type DatabasePool,
type Interceptor,
type PrimitiveValueExpression,
type QueryResultRow,
type QueryResultRowColumn,
type QuerySqlToken,
type CommonQueryMethods as SlonikCommonQueryMethods,
type TaggedTemplateLiteralInvocation,
} from 'slonik';
import { createQueryLoggingInterceptor } from 'slonik-interceptor-query-logging';
import { context, SpanKind, SpanStatusCode, trace } from '@hive/service-common';
import type { StandardSchemaV1 } from '@standard-schema/spec';
import { createConnectionString, type PostgresConnectionParamaters } from './connection-string';
import { PgPoolBridge } from './pg-pool-bridge';
const tracer = trace.getTracer('storage');
export interface CommonQueryMethods {
exists(
sql: TaggedTemplateLiteralInvocation,
exists<T extends StandardSchemaV1>(
sql: QuerySqlToken<T>,
values?: PrimitiveValueExpression[],
): Promise<boolean>;
any(
sql: TaggedTemplateLiteralInvocation,
any<T extends StandardSchemaV1>(
sql: QuerySqlToken<T>,
values?: PrimitiveValueExpression[],
): Promise<ReadonlyArray<unknown>>;
maybeOne(
sql: TaggedTemplateLiteralInvocation,
): Promise<ReadonlyArray<StandardSchemaV1.InferOutput<T>>>;
maybeOne<T extends StandardSchemaV1>(
sql: QuerySqlToken<T>,
values?: PrimitiveValueExpression[],
): Promise<unknown>;
query(sql: TaggedTemplateLiteralInvocation, values?: PrimitiveValueExpression[]): Promise<void>;
oneFirst(
sql: TaggedTemplateLiteralInvocation,
): Promise<null | StandardSchemaV1.InferOutput<T>>;
query(sql: QuerySqlToken<any>, values?: PrimitiveValueExpression[]): Promise<void>;
oneFirst<T extends StandardSchemaV1>(
sql: QuerySqlToken<T>,
values?: PrimitiveValueExpression[],
): Promise<unknown>;
one(sql: TaggedTemplateLiteralInvocation, values?: PrimitiveValueExpression[]): Promise<unknown>;
anyFirst(
sql: TaggedTemplateLiteralInvocation,
): Promise<StandardSchemaV1.InferOutput<T>[keyof StandardSchemaV1.InferOutput<T>]>;
one<T extends StandardSchemaV1>(
sql: QuerySqlToken<T>,
values?: PrimitiveValueExpression[],
): Promise<ReadonlyArray<unknown>>;
maybeOneFirst(
sql: TaggedTemplateLiteralInvocation,
): Promise<StandardSchemaV1.InferOutput<T>>;
anyFirst<T extends StandardSchemaV1>(
sql: QuerySqlToken<T>,
values?: PrimitiveValueExpression[],
): Promise<unknown>;
): Promise<ReadonlyArray<StandardSchemaV1.InferOutput<T>[keyof StandardSchemaV1.InferOutput<T>]>>;
maybeOneFirst<T extends StandardSchemaV1>(
sql: QuerySqlToken<T>,
values?: PrimitiveValueExpression[],
): Promise<null | StandardSchemaV1.InferOutput<T>[keyof StandardSchemaV1.InferOutput<T>]>;
}
export class PostgresDatabasePool implements CommonQueryMethods {
constructor(private pool: DatabasePool) {}
/** Retrieve the raw PgPool instance. Refrain from using this API. It only exists for postgraphile workers */
getRawPgPool() {
return this.pool.pool;
getPgPoolCompat(): Pool {
return new PgPoolBridge(this.pool) as any;
}
/** Retrieve the raw Slonik instance. Refrain from using this API. */
@ -56,59 +60,58 @@ export class PostgresDatabasePool implements CommonQueryMethods {
return this.pool;
}
async exists(
sql: TaggedTemplateLiteralInvocation,
async exists<T extends StandardSchemaV1>(
sql: QuerySqlToken<T>,
values?: PrimitiveValueExpression[],
): Promise<boolean> {
return this.pool.exists(sql, values);
}
async any(
sql: TaggedTemplateLiteralInvocation,
async any<T extends StandardSchemaV1>(
sql: QuerySqlToken<T>,
values?: PrimitiveValueExpression[],
): Promise<ReadonlyArray<unknown>> {
return this.pool.any<unknown>(sql, values);
): Promise<ReadonlyArray<StandardSchemaV1.InferOutput<T>>> {
return this.pool.any(sql, values);
}
async maybeOne(
sql: TaggedTemplateLiteralInvocation,
async maybeOne<T extends StandardSchemaV1>(
sql: QuerySqlToken<T>,
values?: PrimitiveValueExpression[],
): Promise<unknown> {
): Promise<null | StandardSchemaV1.InferOutput<T>> {
return this.pool.maybeOne(sql, values);
}
async query(
sql: TaggedTemplateLiteralInvocation,
values?: PrimitiveValueExpression[],
): Promise<void> {
await this.pool.query<unknown>(sql, values);
async query(sql: QuerySqlToken<any>, values?: PrimitiveValueExpression[]): Promise<void> {
await this.pool.query(sql, values);
}
async oneFirst(
sql: TaggedTemplateLiteralInvocation,
async oneFirst<T extends StandardSchemaV1>(
sql: QuerySqlToken<T>,
values?: PrimitiveValueExpression[],
): Promise<unknown> {
): Promise<StandardSchemaV1.InferOutput<T>[keyof StandardSchemaV1.InferOutput<T>]> {
return await this.pool.oneFirst(sql, values);
}
async maybeOneFirst(
sql: TaggedTemplateLiteralInvocation,
async maybeOneFirst<T extends StandardSchemaV1>(
sql: QuerySqlToken<T>,
values?: PrimitiveValueExpression[],
): Promise<unknown> {
): Promise<null | StandardSchemaV1.InferOutput<T>[keyof StandardSchemaV1.InferOutput<T>]> {
return await this.pool.maybeOneFirst(sql, values);
}
async one(
sql: TaggedTemplateLiteralInvocation,
async one<T extends StandardSchemaV1>(
sql: QuerySqlToken<T>,
values?: PrimitiveValueExpression[],
): Promise<unknown> {
): Promise<StandardSchemaV1.InferOutput<T>> {
return await this.pool.one(sql, values);
}
async anyFirst(
sql: TaggedTemplateLiteralInvocation,
async anyFirst<T extends StandardSchemaV1>(
sql: QuerySqlToken<T>,
values?: PrimitiveValueExpression[],
): Promise<ReadonlyArray<unknown>> {
): Promise<
ReadonlyArray<StandardSchemaV1.InferOutput<T>[keyof StandardSchemaV1.InferOutput<T>]>
> {
return await this.pool.anyFirst(sql, values);
}
@ -124,54 +127,19 @@ export class PostgresDatabasePool implements CommonQueryMethods {
return await this.pool.transaction(async methods => {
try {
return await handler({
async exists(
sql: TaggedTemplateLiteralInvocation,
values?: PrimitiveValueExpression[],
): Promise<boolean> {
return methods.exists(sql, values);
},
async any(
sql: TaggedTemplateLiteralInvocation,
values?: PrimitiveValueExpression[],
): Promise<ReadonlyArray<unknown>> {
return methods.any<unknown>(sql, values);
},
async maybeOne(
sql: TaggedTemplateLiteralInvocation,
values?: PrimitiveValueExpression[],
): Promise<unknown> {
return methods.maybeOne(sql, values);
},
exists: methods.exists,
any: methods.any,
maybeOne: methods.maybeOne,
async query(
sql: TaggedTemplateLiteralInvocation,
sql: QuerySqlToken<any>,
values?: PrimitiveValueExpression[],
): Promise<void> {
await methods.query<unknown>(sql, values);
},
async oneFirst(
sql: TaggedTemplateLiteralInvocation,
values?: PrimitiveValueExpression[],
): Promise<unknown> {
return await methods.oneFirst(sql, values);
},
async maybeOneFirst(
sql: TaggedTemplateLiteralInvocation,
values?: PrimitiveValueExpression[],
): Promise<unknown> {
return await methods.maybeOneFirst(sql, values);
},
async anyFirst(
sql: TaggedTemplateLiteralInvocation,
values?: PrimitiveValueExpression[],
): Promise<ReadonlyArray<unknown>> {
return await methods.anyFirst(sql, values);
},
async one(
sql: TaggedTemplateLiteralInvocation,
values?: PrimitiveValueExpression[],
): Promise<unknown> {
return await methods.one(sql, values);
await methods.query(sql, values);
},
oneFirst: methods.oneFirst,
maybeOneFirst: methods.maybeOneFirst,
anyFirst: methods.anyFirst,
one: methods.one,
});
} catch (err) {
span.setAttribute('error', 'true');
@ -200,6 +168,14 @@ export class PostgresDatabasePool implements CommonQueryMethods {
const dbInterceptors: Interceptor[] = [createQueryLoggingInterceptor()];
const typeParsers = [
...createTypeParserPreset().filter(parser => parser.name !== 'int8'),
{
name: 'int8',
parse: (value: string) => parseInt(value, 10),
},
];
export async function createPostgresDatabasePool(args: {
connectionParameters: PostgresConnectionParamaters | string;
maximumPoolSize?: number;
@ -212,6 +188,7 @@ export async function createPostgresDatabasePool(args: {
: createConnectionString(args.connectionParameters);
const pool = await createPool(connectionString, {
interceptors: dbInterceptors.concat(args.additionalInterceptors ?? []),
typeParsers,
captureStackTrace: false,
maximumPoolSize: args.maximumPoolSize,
idleTimeout: 30000,
@ -223,10 +200,10 @@ export async function createPostgresDatabasePool(args: {
) {
const original: SlonikCommonQueryMethods[K] = pool[methodName];
function interceptor<T extends QueryResultRow>(
function interceptor(
this: any,
sql: TaggedTemplateLiteralInvocation<T>,
values?: QueryResultRowColumn[],
sql: QuerySqlToken<any>,
values?: PrimitiveValueExpression[],
): any {
return (original as any).call(this, sql, values).catch((error: any) => {
error.sql = sql.sql;
@ -236,7 +213,7 @@ export async function createPostgresDatabasePool(args: {
});
}
pool[methodName] = interceptor;
pool[methodName] = interceptor as any;
}
interceptError('one');

View file

@ -1,3 +1,23 @@
import { createSqlTag } from 'slonik';
import { createSqlTag, QuerySqlToken, type SqlTag, type ValueExpression } from 'slonik';
import { z } from 'zod';
import { StandardSchemaV1 } from '@standard-schema/spec';
export const psql = createSqlTag();
const tag = createSqlTag();
interface TemplateStringsArray extends ReadonlyArray<string> {
readonly raw: readonly string[];
}
type CallableTag<
T extends StandardSchemaV1<unknown, unknown> = StandardSchemaV1<unknown, unknown>,
> = (template: TemplateStringsArray, ...values: ValueExpression[]) => QuerySqlToken<T>;
export type TaggedTemplateLiteralInvocation = QuerySqlToken<any>;
function psqlFn(template: TemplateStringsArray, ...values: ValueExpression[]) {
return tag.type(z.unknown())(template, ...values);
}
Object.assign(psqlFn, createSqlTag());
export const psql = psqlFn as any as SqlTag<any> & CallableTag;

View file

@ -59,7 +59,7 @@ async function main() {
tracing ? [tracing.instrumentSlonik()] : undefined,
);
const taskScheduler = new TaskScheduler(storage.pool.getRawPgPool());
const taskScheduler = new TaskScheduler(storage.pool);
const usageEstimator = createEstimator({
logger: server.log,

View file

@ -169,7 +169,7 @@ export async function main() {
10,
tracing ? [tracing.instrumentSlonik()] : [],
);
const taskScheduler = new TaskScheduler(storage.pool.getRawPgPool());
const taskScheduler = new TaskScheduler(storage.pool);
const redis = createRedisClient('Redis', env.redis, server.log.child({ source: 'Redis' }));

View file

@ -24,6 +24,7 @@ import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { Instrumentation, registerInstrumentations } from '@opentelemetry/instrumentation';
import {
BatchSpanProcessor,
ReadableSpan,
Sampler,
SamplingDecision,
SpanProcessor,
@ -63,7 +64,7 @@ export class TracingInstance {
if (this.options.collectorEndpoint) {
// Grafana endpoint
const httpExporter = new OTLPTraceExporter({ url: this.options.collectorEndpoint });
processors.push(new BatchSpanProcessor(httpExporter));
processors.push(new ServiceBatchSpanProcessor(httpExporter));
}
if (this.options.hiveTracing) {
// Hive Tracing endpoint
@ -245,11 +246,12 @@ function extractParts(sqlStatement: string): {
}
export const createSlonikInterceptor = (options: SlonikTracingInterceptorOptions): Interceptor => {
const tracer = trace.getTracer('slonik');
const tracer = trace.getTracer('slonik-service-common');
const connections: Record<string, Record<string, Span>> = {};
const shouldExcludeFn = options.shouldExcludeStatement || (() => false);
return {
name: 'slonik-tracing-interceptor',
afterPoolConnection(context) {
connections[context.connectionId] = {};
@ -515,3 +517,9 @@ export function traceFn<This extends object, TArgs extends any[], TResult>(
} as any;
};
}
class ServiceBatchSpanProcessor extends BatchSpanProcessor {
onEnd(span: ReadableSpan): void {
return super.onEnd(span);
}
}

View file

@ -28,7 +28,6 @@
"got": "14.4.7",
"graphql": "^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0",
"pg-promise": "11.10.2",
"slonik-utilities": "1.9.4",
"tslib": "2.8.1",
"typescript": "5.7.3",
"zod": "3.25.76"

View file

@ -1,4 +1,3 @@
import { update } from 'slonik-utilities';
import { z } from 'zod';
import type {
Member,
@ -235,6 +234,21 @@ export async function createStorage(
return roleId;
},
getOIDCIntegrationById(args: { oidcIntegrationId: string }, connection: CommonQueryMethods) {
return connection
.maybeOne(
psql`/* getOIDCIntegrationById */
SELECT
${oidcIntegrationFields()}
FROM
"oidc_integrations"
WHERE
"id" = ${args.oidcIntegrationId}
LIMIT 1
`,
)
.then(OIDCIntegrationModel.nullable().parse);
},
};
function buildUserData(input: {
@ -335,9 +349,12 @@ export async function createStorage(
let invitation: OrganizationInvitation | null = null;
if (oidcIntegration?.id) {
const oidcConfig = await this.getOIDCIntegrationById({
oidcIntegrationId: oidcIntegration.id,
});
const oidcConfig = await shared.getOIDCIntegrationById(
{
oidcIntegrationId: oidcIntegration.id,
},
t,
);
if (oidcConfig) {
invitation = await t
@ -363,10 +380,31 @@ export async function createStorage(
if (oidcConfig?.requireInvitation && !invitation) {
const member = internalUser
? await this.getOrganizationMember({
organizationId: oidcConfig.linkedOrganizationId,
userId: internalUser.id,
})
? await t
.maybeOne(
psql`/* getOrganizationMember */
SELECT
${userFields(psql`"u".`)},
omr.scopes as scopes,
om.organization_id AS "organizationId",
om.connected_to_zendesk AS "connectedToZendesk",
CASE WHEN o.user_id = om.user_id THEN true ELSE false END AS "isOwner",
omr.id as "roleId",
omr.name as "roleName",
omr.locked as "roleLocked",
omr.scopes as "roleScopes",
omr.description as "roleDescription"
FROM organization_member as om
LEFT JOIN organizations as o ON (o.id = om.organization_id)
LEFT JOIN users as u ON (u.id = om.user_id)
LEFT JOIN organization_member_roles as omr ON (omr.organization_id = o.id AND omr.id = om.role_id)
WHERE
om.organization_id = ${oidcConfig.linkedOrganizationId}
AND om.user_id = ${internalUser.id}
ORDER BY u.created_at DESC
`,
)
.then(MemberModel.nullable().parse)
: null;
if (!member) {
@ -617,7 +655,7 @@ export async function createStorage(
psql`/* getOrganizationOwnerId */
SELECT id, user_id
FROM organizations
WHERE id IN (${psql.join(organizations, psql`, `)})`,
WHERE id IN (${psql.join(organizations, psql.fragment`, `)})`,
)
.then(z.array(OrganizationUserIdAndIdModel).parse);
@ -694,7 +732,7 @@ export async function createStorage(
LEFT JOIN organization_member_roles as omr ON (omr.organization_id = o.id AND omr.id = om.role_id)
WHERE (om.organization_id, om.user_id) IN ((${psql.join(
selectors.map(s => psql`${s.organizationId}, ${s.userId}`),
psql`), (`,
psql.fragment`), (`,
)}))
ORDER BY u.created_at DESC
`,
@ -836,7 +874,7 @@ export async function createStorage(
LEFT JOIN organization_member_roles as omr ON (omr.organization_id = om.organization_id AND omr.id = om.role_id)
WHERE (om.organization_id, om.user_id) IN ((${psql.join(
pairs.map(p => psql`${p.organizationId}, ${p.userId}`),
psql`), (`,
psql.fragment`), (`,
)}))
`,
)
@ -1499,7 +1537,7 @@ export async function createStorage(
(id, project_id) IN (
(${psql.join(
uniqueSelectors.map(s => psql`${s.targetId}, ${s.projectId}`),
psql`), (`,
psql.fragment`), (`,
)})
)
`,
@ -1706,7 +1744,7 @@ export async function createStorage(
await trx.query(psql`/* deleteTargetValidation */
DELETE
FROM target_validation
WHERE destination_target_id NOT IN (${psql.join(targets, psql`, `)})
WHERE destination_target_id NOT IN (${psql.join(targets, psql.fragment`, `)})
AND target_id = ${target}
`);
@ -1716,8 +1754,8 @@ export async function createStorage(
VALUES
(
${psql.join(
targets.map(dest => psql.join([target, dest], psql`, `)),
psql`), (`,
targets.map(dest => psql.join([target, dest], psql.fragment`, `)),
psql.fragment`), (`,
)}
)
ON CONFLICT (target_id, destination_target_id) DO NOTHING
@ -2277,7 +2315,7 @@ export async function createStorage(
const service = input.service ?? null;
const output = await pool.transaction('createVersion', async trx => {
const log = await pool
const log = await trx
.maybeOne(
psql`/* createVersion */
INSERT INTO schema_log
@ -2416,7 +2454,7 @@ export async function createStorage(
LEFT JOIN projects as p ON (p.id = sl.project_id)
WHERE (sl.id, sl.target_id) IN ((${psql.join(
selectors.map(s => psql`${s.commit}, ${s.targetId}`),
psql`), (`,
psql.fragment`), (`,
)}))
`,
);
@ -2526,7 +2564,7 @@ export async function createStorage(
DELETE FROM alert_channels
WHERE
project_id = ${projectId} AND
id IN (${psql.join(channelIds, psql`, `)})
id IN (${psql.join(channelIds, psql.fragment`, `)})
RETURNING
${alertChannelFields()}
`,
@ -2570,7 +2608,7 @@ export async function createStorage(
DELETE FROM alerts
WHERE
project_id = ${project} AND
id IN (${psql.join(alerts, psql`, `)})
id IN (${psql.join(alerts, psql.fragment`, `)})
RETURNING
${alertFields()}
`,
@ -2846,33 +2884,19 @@ export async function createStorage(
),
);
},
async completeGetStartedStep({ organizationId: organization, step }) {
await update(
pool.getSlonikPool(),
'organizations',
{
[organizationGetStartedMapping[step]]: true,
},
{
id: organization,
},
);
async completeGetStartedStep({ organizationId, step }) {
await pool.query(psql`
UPDATE
"organizations"
SET
${psql.identifier([organizationGetStartedMapping[step]])} = True
WHERE
"organizations"."id" = ${organizationId}
`);
},
async getOIDCIntegrationById({ oidcIntegrationId: integrationId }) {
return await pool
.maybeOne(
psql`/* getOIDCIntegrationById */
SELECT
${oidcIntegrationFields()}
FROM
"oidc_integrations"
WHERE
"id" = ${integrationId}
LIMIT 1
`,
)
.then(OIDCIntegrationModel.nullable().parse);
async getOIDCIntegrationById(args) {
return shared.getOIDCIntegrationById(args, pool);
},
getOIDCIntegrationForOrganization: batch(async selectors => {
@ -3060,7 +3084,7 @@ export async function createStorage(
throw new Error('Role does not exist');
}
return await pool
return await trx
.maybeOne(
psql`/* updateOIDCDefaultMemberRole */
UPDATE "oidc_integrations"

View file

@ -141,7 +141,7 @@ export async function createTokenStorage(
VALUES
(${psql.join(
tokens.map(t => psql`${t.token}, ${toDate(t.date)}`),
psql`), (`,
psql.fragment`), (`,
)})
) as c(token, last_used_at)
WHERE c.token = t.token;

View file

@ -57,7 +57,7 @@ const pg = await createPostgresDatabasePool({
});
const logger = new Logger({ level: env.log.level });
logger.info({ pid: process.pid }, 'starting workflow service');
logger.info({ pid: process.pid }, 'starting workflow service ' + process.pid);
const stopHttpHeartbeat = env.httpHeartbeat
? startHeartbeats({
@ -144,7 +144,7 @@ const shutdownMetrics = env.prometheus
const runner = await run({
logger: bridgeGraphileLogger(logger),
crontab,
pgPool: pg.getRawPgPool(),
pgPool: pg.getPgPoolCompat(),
taskList: Object.fromEntries(modules.map(module => module.task(context))),
noHandleSignals: true,
events: createTaskEventEmitter(),

View file

@ -1,9 +1,9 @@
import { BentoCache, bentostore } from 'bentocache';
import { memoryDriver } from 'bentocache/build/src/drivers/memory';
import { makeWorkerUtils, WorkerUtils, type JobHelpers, type Task } from 'graphile-worker';
import type { Pool } from 'pg';
import { z } from 'zod';
import { Logger } from '@graphql-hive/logger';
import { PostgresDatabasePool, psql } from '@hive/postgres';
import { bridgeGraphileLogger } from '@hive/pubsub';
import type { Context } from './context';
@ -76,11 +76,11 @@ export class TaskScheduler {
cache: BentoCache<{ store: ReturnType<typeof bentostore> }>;
constructor(
pgPool: Pool,
private pgPool: PostgresDatabasePool,
private logger: Logger = new Logger(),
) {
this.tools = makeWorkerUtils({
pgPool,
pgPool: pgPool.getPgPoolCompat(),
logger: bridgeGraphileLogger(logger),
});
this.cache = new BentoCache({
@ -118,7 +118,6 @@ export class TaskScheduler {
);
const input = taskDefinition.schema.parse(payload);
const tools = await this.tools;
if (opts?.dedupe) {
@ -128,27 +127,26 @@ export class TaskScheduler {
let shouldSkip = true;
const { pgPool } = this;
await this.cache.getOrSet({
key: `${taskDefinition.name}:${dedupeKey}`,
ttl: opts.dedupe.ttl,
async factory() {
return await tools.withPgClient(async client => {
const result = await client.query(
`
const result = await pgPool.anyFirst(
psql`
INSERT INTO "graphile_worker_deduplication" ("task_name", "dedupe_key", "expires_at")
VALUES($1, $2, $3)
VALUES(${taskDefinition.name}, ${dedupeKey}, ${expiresAt})
ON CONFLICT ("task_name", "dedupe_key")
DO
UPDATE SET "expires_at" = EXCLUDED.expires_at
WHERE "graphile_worker_deduplication"."expires_at" < NOW()
RETURNING xmax = 0 AS "inserted"
`,
[taskDefinition.name, dedupeKey, expiresAt],
);
);
shouldSkip = result.rows.length === 0;
return true;
});
shouldSkip = result.length === 0;
return true;
},
});
@ -176,8 +174,4 @@ export class TaskScheduler {
'task enqueued.',
);
}
async dispose() {
await (await this.tools).release();
}
}

View file

@ -0,0 +1,28 @@
diff --git a/dist/factories/createPgDriverFactory.js b/dist/factories/createPgDriverFactory.js
index ed4601ac233435cc8ea5e546c722ede4bd8873d7..b57306c66a3e2176a6fda9d749f870a1b1158007 100644
--- a/dist/factories/createPgDriverFactory.js
+++ b/dist/factories/createPgDriverFactory.js
@@ -230,7 +230,8 @@ export const createPgDriverFactory = () => {
});
}
if (Array.isArray(result)) {
- throw new InvalidInputError("Must not use multiple statements in a single query.");
+ result = result[result.length - 1]
+ // throw new InvalidInputError("Must not use multiple statements in a single query.");
}
return {
command: result.command,
diff --git a/src/factories/createPgDriverFactory.ts b/src/factories/createPgDriverFactory.ts
index 608ed21b07e90fb67dc1d778a836e3554ff50671..c606167619280e58df26601ff1bc7a903dead48d 100644
--- a/src/factories/createPgDriverFactory.ts
+++ b/src/factories/createPgDriverFactory.ts
@@ -314,7 +314,8 @@ export const createPgDriverFactory = (): DriverFactory => {
}
if (Array.isArray(result)) {
- throw new InvalidInputError("Must not use multiple statements in a single query.");
+ result = result[result.length - 1]
+ // throw new InvalidInputError("Must not use multiple statements in a single query.");
}
return {

242
patches/slonik.patch Normal file
View file

@ -0,0 +1,242 @@
diff --git a/dist/factories/createConnection.js b/dist/factories/createConnection.js
index 35b11d4d843c273aa4e0a5003cd1b8e082c41286..82bbb30c22b9f4bb7666f65afa483d71b33e51cd 100644
--- a/dist/factories/createConnection.js
+++ b/dist/factories/createConnection.js
@@ -56,23 +56,8 @@ export const createConnection = async (parentLog, pool, clientConfiguration, con
for (const interceptor of clientConfiguration.interceptors) {
const beforePoolConnection = interceptor.beforePoolConnection;
if (beforePoolConnection) {
- const maybeNewPool = await tracer.startActiveSpan("slonik.interceptor.beforePoolConnection", async (interceptorSpan) => {
- interceptorSpan.setAttribute("interceptor.name", interceptor.name);
- try {
- return await beforePoolConnection(connectionContext);
- }
- catch (error) {
- interceptorSpan.recordException(error);
- interceptorSpan.setStatus({
- code: SpanStatusCode.ERROR,
- message: String(error),
- });
- throw error;
- }
- finally {
- interceptorSpan.end();
- }
- });
+ const maybeNewPool = await beforePoolConnection(connectionContext);
+
if (maybeNewPool) {
return await poolHandler(maybeNewPool);
}
diff --git a/dist/factories/createConnectionPool.js b/dist/factories/createConnectionPool.js
index 5d7d7de147c6c3d9f835ba987c61d34f179bba9d..1df983bf044a9fa5081b19cd181663f897344e35 100644
--- a/dist/factories/createConnectionPool.js
+++ b/dist/factories/createConnectionPool.js
@@ -291,13 +291,7 @@ export const createConnectionPool = ({ driver, events, idleTimeout, maximumConne
isEnded = true;
};
const acquire = async () => {
- return tracer.startActiveSpan("slonik.connection.acquire", async (span) => {
try {
- span.setAttribute("slonik.pool.id", id);
- span.setAttribute("slonik.pool.connections.total", connections.size);
- span.setAttribute("slonik.pool.connections.pending", pendingConnections.size);
- span.setAttribute("slonik.pool.waitingClients", waitingClients.length);
- span.setAttribute("slonik.pool.maximumSize", maximumPoolSize);
if (isEnded) {
span.setStatus({
code: SpanStatusCode.ERROR,
@@ -368,17 +362,11 @@ export const createConnectionPool = ({ driver, events, idleTimeout, maximumConne
}
}
if (idleConnection) {
- span.setAttribute("slonik.connection.id", idleConnection.id());
- span.setAttribute("method", "acquire:reuse-idle");
- span.setStatus({ code: SpanStatusCode.OK });
return idleConnection;
}
if (pendingConnections.size + activeConnectionCount() - destroyedInLoop < maximumPoolSize) {
- const newConnection = await addConnection(span);
+ const newConnection = await addConnection(/*span*/);
newConnection.acquire();
- span.setAttribute("slonik.connection.id", newConnection.id());
- span.setAttribute("method", "acquire:add-connection");
- span.setStatus({ code: SpanStatusCode.OK });
return newConnection;
}
if (isEnding || isEnded) {
@@ -406,25 +394,12 @@ export const createConnectionPool = ({ driver, events, idleTimeout, maximumConne
connectionId: connection.id(),
duration: Number(process.hrtime.bigint() - queuedAt) / 1e6,
}, "connection has been acquired from the queue");
- span.setAttribute("queuedMs", Number(process.hrtime.bigint() - queuedAt) / 1e6);
- span.setAttribute("slonik.connection.id", connection.id());
- span.setAttribute("method", "acquire:queued");
- span.setStatus({ code: SpanStatusCode.OK });
return connection;
});
}
catch (error) {
- span.recordException(error);
- span.setStatus({
- code: SpanStatusCode.ERROR,
- message: error instanceof Error ? error.message : String(error),
- });
throw error;
}
- finally {
- span.end();
- }
- });
};
const warmup = async () => {
if (minimumPoolSize <= 0 || isEnding || isEnded) {
diff --git a/dist/routines/establishConnection.js b/dist/routines/establishConnection.js
index cec0de8d60542a48c47656b0d706de641d4e184e..6ca217362c42878449d1933de4953e3bb0612730 100644
--- a/dist/routines/establishConnection.js
+++ b/dist/routines/establishConnection.js
@@ -5,7 +5,6 @@ import { generateUid } from "@slonik/utilities";
import { serializeError } from "serialize-error";
const tracer = trace.getTracer("slonik");
export const establishConnection = async (parentLog, pool, connectionRetryLimit) => {
- return await tracer.startActiveSpan("slonik.acquireConnection", async (span) => {
let connection;
let remainingConnectionRetryLimit = connectionRetryLimit + 1;
while (true) {
@@ -31,11 +30,6 @@ export const establishConnection = async (parentLog, pool, connectionRetryLimit)
continue;
}
else {
- span.recordException(error);
- span.setStatus({
- code: SpanStatusCode.ERROR,
- message: String(error),
- });
throw new ConnectionError(error.message, {
cause: error,
});
@@ -45,8 +39,6 @@ export const establishConnection = async (parentLog, pool, connectionRetryLimit)
if (!connection) {
throw new UnexpectedStateError("Connection handle is not present.");
}
- span.end();
return connection;
- });
};
//# sourceMappingURL=establishConnection.js.map
\ No newline at end of file
diff --git a/dist/routines/executeQuery.js b/dist/routines/executeQuery.js
index 7446ec489a4fa4728be4e4abaa2495592bf9da9f..9256a675171fea8b42ce5a3895620472d7ff6eb7 100644
--- a/dist/routines/executeQuery.js
+++ b/dist/routines/executeQuery.js
@@ -145,26 +145,8 @@ const executeQueryInternal = async (connectionLogger, connection, clientConfigur
for (const interceptor of clientConfiguration.interceptors) {
const beforeQueryExecution = interceptor.beforeQueryExecution;
if (beforeQueryExecution) {
- result = await tracer.startActiveSpan("slonik.interceptor.beforeQueryExecution", {
- attributes: {
- "interceptor.name": interceptor.name,
- },
- }, async (span) => {
- try {
- return await beforeQueryExecution(executionContext, actualQuery);
- }
- catch (error) {
- span.recordException(error);
- span.setStatus({
- code: SpanStatusCode.ERROR,
- message: String(error),
- });
- throw error;
- }
- finally {
- span.end();
- }
- });
+ result = await beforeQueryExecution(executionContext, actualQuery);
+
if (result) {
log.info("beforeQueryExecution interceptor produced a result; short-circuiting query execution using beforeQueryExecution result");
return result;
@@ -315,26 +297,7 @@ const executeQueryInternal = async (connectionLogger, connection, clientConfigur
for (const interceptor of interceptors) {
const afterQueryExecution = interceptor.afterQueryExecution;
if (afterQueryExecution) {
- await tracer.startActiveSpan("slonik.interceptor.afterQueryExecution", {
- attributes: {
- "interceptor.name": interceptor.name,
- },
- }, async (span) => {
- try {
- await afterQueryExecution(executionContext, actualQuery, result);
- }
- catch (error) {
- span.recordException(error);
- span.setStatus({
- code: SpanStatusCode.ERROR,
- message: String(error),
- });
- throw error;
- }
- finally {
- span.end();
- }
- });
+ await afterQueryExecution(executionContext, actualQuery, result);
}
}
for (const interceptor of interceptors) {
@@ -405,50 +368,12 @@ const executeQueryInternal = async (connectionLogger, connection, clientConfigur
for (const interceptor of interceptors) {
const beforeQueryResult = interceptor.beforeQueryResult;
if (beforeQueryResult) {
- await tracer.startActiveSpan("slonik.interceptor.beforeQueryResult", {
- attributes: {
- "interceptor.name": interceptor.name,
- },
- }, async (span) => {
- try {
- await beforeQueryResult(executionContext, actualQuery, result);
- }
- catch (error) {
- span.recordException(error);
- span.setStatus({
- code: SpanStatusCode.ERROR,
- message: String(error),
- });
- throw error;
- }
- finally {
- span.end();
- }
- });
+ await beforeQueryResult(executionContext, actualQuery, result);
}
}
return result;
};
export const executeQuery = async (connectionLogger, connection, clientConfiguration, query, inheritedQueryId, executionRoutine, stream, integrityValidation) => {
- return await tracer.startActiveSpan("slonik.executeQuery", {
- attributes: {
- sql: query.sql,
- },
- }, async (span) => {
- try {
- return await executeQueryInternal(connectionLogger, connection, clientConfiguration, query, inheritedQueryId, executionRoutine, integrityValidation, stream);
- }
- catch (error) {
- span.recordException(error);
- span.setStatus({
- code: SpanStatusCode.ERROR,
- message: String(error),
- });
- throw error;
- }
- finally {
- span.end();
- }
- });
+ return await executeQueryInternal(connectionLogger, connection, clientConfiguration, query, inheritedQueryId, executionRoutine, integrityValidation, stream);
};
//# sourceMappingURL=executeQuery.js.map
\ No newline at end of file

View file

@ -1,69 +0,0 @@
diff --git a/dist/src/binders/bindPool.js b/dist/src/binders/bindPool.js
index ad509058bf5d26c82d4b2aea35e945df2f83f38e..1ca27403f70362f9a60abef7df6c2fdaaba1805b 100644
--- a/dist/src/binders/bindPool.js
+++ b/dist/src/binders/bindPool.js
@@ -7,6 +7,7 @@ const factories_1 = require("../factories");
const state_1 = require("../state");
const bindPool = (parentLog, pool, clientConfiguration) => {
return {
+ pool,
any: (query) => {
return (0, factories_1.createConnection)(parentLog, pool, clientConfiguration, 'IMPLICIT_QUERY', (connectionLog, connection, boundConnection) => {
return boundConnection.any(query);
diff --git a/dist/src/factories/createPool.js b/dist/src/factories/createPool.js
index b91a9fe433dc340f5cdf096ca4c568297c343ab3..401df1272d1c7f344bb956b38cc7dbde29231742 100644
--- a/dist/src/factories/createPool.js
+++ b/dist/src/factories/createPool.js
@@ -44,6 +44,16 @@ const createPool = async (connectionUri, clientConfigurationInput) => {
getTypeParser,
},
});
+
+ // https://github.com/gajus/slonik/issues/471
+ // https://github.com/brianc/node-postgres/issues/2764#issuecomment-1163475426
+ // Slonik did not have a way to handle errors emitted by the pool, which resulted in an uncaught exception, which would crash the process.
+ pool.on('error', (error) => {
+ poolLog.error({
+ error: (0, serialize_error_1.serializeError)(error),
+ }, 'client error');
+ });
+
state_1.poolStateMap.set(pool, {
ended: false,
mock: false,
diff --git a/dist/src/types.d.ts b/dist/src/types.d.ts
index d091b301b1df0f8d9ad9298d587081fe6d33c0be..57ea5a46fbf0878546e34debed2401efcb66d7fb 100644
--- a/dist/src/types.d.ts
+++ b/dist/src/types.d.ts
@@ -138,6 +138,7 @@ export declare type DatabasePool = CommonQueryMethods & {
readonly end: () => Promise<void>;
readonly getPoolState: () => PoolState;
readonly stream: StreamFunction;
+ readonly pool: PgPool;
};
export declare type DatabaseConnection = DatabasePool | DatabasePoolConnection;
export declare type QueryResultRowColumn = PrimitiveValueExpression;
diff --git a/src/binders/bindPool.ts b/src/binders/bindPool.ts
index d10bb50117b613f262ee715fc40745e8270a60b3..fde977dd042ec2561163f252c7f76f92cb043eb0 100644
--- a/src/binders/bindPool.ts
+++ b/src/binders/bindPool.ts
@@ -26,6 +26,7 @@ export const bindPool = (
clientConfiguration: ClientConfiguration,
): DatabasePool => {
return {
+ pool,
any: (query: TaggedTemplateLiteralInvocation) => {
return createConnection(
parentLog,
diff --git a/src/types.ts b/src/types.ts
index da293a0a4ce2583c43711cbe90d4829ec9c46fa8..962acdd5c2652e6e61147adc03204bca065cd28c 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -191,6 +191,7 @@ export type DatabasePool = CommonQueryMethods & {
readonly end: () => Promise<void>,
readonly getPoolState: () => PoolState,
readonly stream: StreamFunction,
+ readonly pool: PgPool,
};
export type DatabaseConnection = DatabasePool | DatabasePoolConnection;

View file

@ -64,6 +64,9 @@ patchedDependencies:
'@oclif/core@4.0.6':
hash: d1dc04fa0009203663f00e051630035b556b6bd06913c6ab45aeee47ccdedd46
path: patches/@oclif__core@4.0.6.patch
'@slonik/pg-driver':
hash: d281baceb3dc04c2d6348d8b2bb1f5598bef4e24a6a173fc0048c2b3ab6e27ea
path: patches/@slonik__pg-driver.patch
'@theguild/editor@1.2.5':
hash: a401455daa519af0fe686b4f970a02582f9e406c520aad19273a8eeef8f4adf7
path: patches/@theguild__editor@1.2.5.patch
@ -88,9 +91,9 @@ patchedDependencies:
p-cancelable@4.0.1:
hash: 195ae63d47810ca4c987421948f15869356e598dccde9e8c9a4ff4efd3e88322
path: patches/p-cancelable@4.0.1.patch
slonik@30.4.4:
hash: 195b140c0181c27a85a6026c0058087a419e38f6c5d89f5f2c608e39f5bf23e9
path: patches/slonik@30.4.4.patch
slonik:
hash: e16e74ebc8c5f42be257d540b5ac7d175ff3264481046b5c33fc647c9997acdc
path: patches/slonik.patch
importers:
@ -433,12 +436,21 @@ importers:
packages/internal/postgres:
dependencies:
'@standard-schema/spec':
specifier: 1.0.0
version: 1.0.0
slonik:
specifier: 30.4.4
version: 30.4.4(patch_hash=195b140c0181c27a85a6026c0058087a419e38f6c5d89f5f2c608e39f5bf23e9)
specifier: 48.13.2
version: 48.13.2(patch_hash=e16e74ebc8c5f42be257d540b5ac7d175ff3264481046b5c33fc647c9997acdc)
slonik-interceptor-query-logging:
specifier: 46.4.0
version: 46.4.0(slonik@30.4.4(patch_hash=195b140c0181c27a85a6026c0058087a419e38f6c5d89f5f2c608e39f5bf23e9))
specifier: 48.13.2
version: 48.13.2(slonik@48.13.2(patch_hash=e16e74ebc8c5f42be257d540b5ac7d175ff3264481046b5c33fc647c9997acdc))
slonik-sql-tag-raw:
specifier: 48.13.2
version: 48.13.2(slonik@48.13.2(patch_hash=e16e74ebc8c5f42be257d540b5ac7d175ff3264481046b5c33fc647c9997acdc))
zod:
specifier: 3.25.76
version: 3.25.76
devDependencies:
'@hive/service-common':
specifier: workspace:*
@ -1051,7 +1063,7 @@ importers:
version: 6.2.0
pg-promise:
specifier: 11.10.2
version: 11.10.2(pg-query-stream@4.7.0(pg@8.13.1))
version: 11.10.2(pg-query-stream@4.14.0(pg@8.20.0))
tslib:
specifier: 2.8.1
version: 2.8.1
@ -1795,10 +1807,7 @@ importers:
version: 16.9.0
pg-promise:
specifier: 11.10.2
version: 11.10.2(pg-query-stream@4.7.0(pg@8.13.1))
slonik-utilities:
specifier: 1.9.4
version: 1.9.4
version: 11.10.2(pg-query-stream@4.14.0(pg@8.20.0))
tslib:
specifier: 2.8.1
version: 2.8.1
@ -8805,6 +8814,38 @@ packages:
resolution: {integrity: sha512-kT+07JvOqpYH3b/ttVo3iqKIFiHV2NKmD6QUc/F7HrjCgSdSA10zxqi0euXEF2prB49OU7SfjadzQ0WhNc7tiw==}
engines: {node: '>= 18', npm: '>= 8.6.0'}
'@slonik/driver@48.13.2':
resolution: {integrity: sha512-vNywhgnCvaHejW/bGsZglUXGf7LXxin6aZ+iIefuf6p1NWcT/nuyb38QrpB+cveLoho1iVaPdECnk5ksnFbKCw==}
engines: {node: '>=24'}
peerDependencies:
zod: ^3.25 || ^4
'@slonik/errors@48.13.2':
resolution: {integrity: sha512-rUeL6pMVRCK6TzYku0QxFvSmzk4bkbpg3348A7qaTzFEUtX9pmaD0aGXBpc1si9+cVscckRl/ezy9TTRDODPCw==}
engines: {node: '>=24'}
'@slonik/pg-driver@48.13.2':
resolution: {integrity: sha512-ULEWssW52X4sxxqBWtKYw0T1sSPgPm58wDmYo8xocZC5JuXFHvMzHpUk3X0lMUUXdOXKGcIL/G5sWG74PWi1Hg==}
engines: {node: '>=24'}
peerDependencies:
zod: ^3.25 || ^4
'@slonik/sql-tag@48.13.2':
resolution: {integrity: sha512-PWHIOTV5r7QZB8E7LNPCPOH+gTocAKne6P/JpPbSa16xynsABTcWLaa3yF4Z6oAbwCgzAkQdJ1TIubd4hawQ1A==}
engines: {node: '>=24'}
'@slonik/types@48.13.2':
resolution: {integrity: sha512-04iyM4iz68WoYN/9IcQdlwam2vF7QG1QuKfXYJLWTY6sIFMMQgTdlfPpOE7Q5N2UNy7twQXvjoyYJMGYNu/sCA==}
engines: {node: '>=24'}
peerDependencies:
zod: ^3.25 || ^4
'@slonik/utilities@48.13.2':
resolution: {integrity: sha512-KfAKm5P6dsQoTaq3GbJD6ybFS9H18zrwZ3FpNbs4u63NrpIMNas6ZWqdeEz+Pqy+OKpQWxiy1x06S/PBVNJSFA==}
engines: {node: '>=24'}
peerDependencies:
zod: ^3.25 || ^4
'@smithy/abort-controller@4.0.0':
resolution: {integrity: sha512-xFNL1ZfluscKiVI0qlPEnu7pL1UgNNIzQdjTPkaO7JCJtIkbArPYNtqbxohuNaQdksJ01Tn1wLbDA5oIp62P8w==}
engines: {node: '>=18.0.0'}
@ -11173,10 +11214,6 @@ packages:
buffer@6.0.3:
resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==}
bufferput@0.1.3:
resolution: {integrity: sha512-nmPV88vDNzf0VMU1bdQ4A1oBlRR9y+CXfwWKfyKUgI2ZIkvreNzLMM3tkz0Lapb6f+Cz1V001UWRBsoGVCjqdw==}
engines: {node: '>=0.3.0'}
bufrw@1.4.0:
resolution: {integrity: sha512-sWm8iPbqvL9+5SiYxXH73UOkyEbGQg7kyHQmReF89WJHQJw2eV4P/yZ0E+b71cczJ4pPobVhXxgQcmfSTgGHxQ==}
engines: {node: '>= 0.10.x'}
@ -11697,9 +11734,6 @@ packages:
core-js-compat@3.49.0:
resolution: {integrity: sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==}
core-js@3.25.5:
resolution: {integrity: sha512-nbm6eZSjm+ZuBQxCUPQKQCoUEfFOXjUZ8dTTyikyKaWrTYmAVbykQfwsKE5dBK88u3QCkCrzsx/PPlKfhsvgpw==}
core-util-is@1.0.2:
resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==}
@ -12053,10 +12087,6 @@ packages:
resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==}
engines: {node: '>= 14'}
delay@4.4.1:
resolution: {integrity: sha512-aL3AhqtfhOlT/3ai6sWXeqwnw63ATNpnUiN4HL7x9q+My5QtHlO3OIkasmug9LKzpheLdmUKGRKnYXYAS7FQkQ==}
engines: {node: '>=6'}
delayed-stream@1.0.0:
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
engines: {node: '>=0.4.0'}
@ -12362,9 +12392,6 @@ packages:
resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==}
engines: {node: '>= 0.4'}
es6-error@4.1.1:
resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==}
esast-util-from-estree@2.0.0:
resolution: {integrity: sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==}
@ -12790,10 +12817,6 @@ packages:
fast-json-stable-stringify@2.1.0:
resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
fast-json-stringify@2.7.13:
resolution: {integrity: sha512-ar+hQ4+OIurUGjSJD1anvYSDcUflywhKjfxnsW4TBTD7+u0tJufv6DKRWoQk3vI6YBOWMoz0TQtfbe7dxbQmvA==}
engines: {node: '>= 10.0.0'}
fast-json-stringify@5.16.1:
resolution: {integrity: sha512-KAdnLvy1yu/XrRtP+LJnxbBGrhN+xXu+gt3EUvZhYGKCr3lFHq/7UFJHHFgmJKoqlh6B40bZLEv7w46B0mqn1g==}
@ -13160,10 +13183,6 @@ packages:
get-source@2.0.12:
resolution: {integrity: sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==}
get-stack-trace@2.1.1:
resolution: {integrity: sha512-dhqSDD9lHU/6FvIZ9KbXGmVK6IKr9ZskZtNOUvhlCiONlnqatu4FmAeRbxCfJJVuQ0NWfz6dAbibKQg19B7AmQ==}
engines: {node: '>=8.0'}
get-stdin@8.0.0:
resolution: {integrity: sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==}
engines: {node: '>=10'}
@ -13712,9 +13731,6 @@ packages:
humps@2.0.1:
resolution: {integrity: sha512-E0eIbrFWUhwfXJmsbdjRQFQPrl5pTEoKlz163j1mTqqUnU9PgR4AgB8AIITzuB3vLBdxZXyZ9TDIrwB2OASz4g==}
hyperid@2.3.1:
resolution: {integrity: sha512-mIbI7Ymn6MCdODaW1/6wdf5lvvXzmPsARN4zTLakMmcziBOuP4PxCBJvHF6kbAIHX6H4vAELx/pDmt0j6Th5RQ==}
hyperid@3.3.0:
resolution: {integrity: sha512-7qhCVT4MJIoEsNcbhglhdmBKb09QtcmJNiIQGq7js/Khf5FtQQ9bzcAuloeqBeee7XD7JqDeve9KNlQya5tSGQ==}
@ -13855,10 +13871,6 @@ packages:
inline-style-parser@0.2.4:
resolution: {integrity: sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==}
int64-buffer@0.99.1007:
resolution: {integrity: sha512-XDBEu44oSTqlvCSiOZ/0FoUkpWu/vwjJLGSKDabNISPQNZ5wub1FodGHBljRsrR0IXRPq7SslshZYMuA55CgTQ==}
engines: {node: '>= 4.5.0'}
internal-slot@1.1.0:
resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
engines: {node: '>= 0.4'}
@ -14108,10 +14120,6 @@ packages:
resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==}
engines: {node: '>=0.10.0'}
is-plain-object@5.0.0:
resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==}
engines: {node: '>=0.10.0'}
is-primitive@3.0.1:
resolution: {integrity: sha512-GljRxhWvlCNRfZyORiH77FwdFwGcMO620o37EOYC0ORWdq+WYNVqW0w2Juzew4M+L81l6/QS3t5gkkihyRqv9w==}
engines: {node: '>=0.10.0'}
@ -14260,8 +14268,8 @@ packages:
resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==}
engines: {node: '>=16'}
iso8601-duration@1.3.0:
resolution: {integrity: sha512-K4CiUBzo3YeWk76FuET/dQPH03WE04R94feo5TSKQCXpoXQt9E4yx2CnY737QZnSAI3PI4WlKo/zfqizGx52QQ==}
iso8601-duration@2.1.3:
resolution: {integrity: sha512-OwkROKDXYhqKTl9uyB+/+lQ/Tx+L9LVb9tNRcsO4LtCSBDrmYbzyJLg9rGjYKAPDabD6IVdjMyUnnULHpejrCg==}
isobject@3.0.1:
resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==}
@ -15509,9 +15517,6 @@ packages:
muggle-string@0.4.1:
resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==}
multi-fork@0.0.2:
resolution: {integrity: sha512-SHWGuze0cZNiH+JGJQFlB1k7kZLGFCvW1Xo5Fcpe86KICkC3aVTJWpjUcmyYcLCB0I6gdzKLCia/bTIw2ggl8A==}
mustache@4.2.0:
resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==}
hasBin: true
@ -15874,10 +15879,6 @@ packages:
resolution: {integrity: sha512-wBowNApzd45EIKdO1LaU+LrMBwAcjfPaYtVzV3lmfM3gf8Z4CHZsiIqlM8TZZ8okYvh5A1cP6gTfCRQtwUpaUg==}
engines: {node: '>=14.16'}
p-defer@3.0.0:
resolution: {integrity: sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw==}
engines: {node: '>=8'}
p-filter@2.1.0:
resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==}
engines: {node: '>=8'}
@ -16007,9 +16008,9 @@ packages:
resolution: {integrity: sha512-SgOTCX/EZXtZxBE5eJ97P4yGM5n37BwRU+YMsH4vNzFqJV/oWFXXCmwFlgWUM4PrakybVOueJJ6pwHqSVhTFDw==}
engines: {node: '>=16'}
parse-ms@2.1.0:
resolution: {integrity: sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==}
engines: {node: '>=6'}
parse-ms@4.0.0:
resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==}
engines: {node: '>=18'}
parse-node-version@1.0.1:
resolution: {integrity: sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==}
@ -16118,17 +16119,17 @@ packages:
pg-cloudflare@1.1.1:
resolution: {integrity: sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==}
pg-cloudflare@1.3.0:
resolution: {integrity: sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==}
pg-connection-string@2.12.0:
resolution: {integrity: sha512-U7qg+bpswf3Cs5xLzRqbXbQl85ng0mfSV/J0nnA31MCLgvEaAo7CIhmeyrmJpOr7o+zm0rXK+hNnT5l9RHkCkQ==}
pg-connection-string@2.9.1:
resolution: {integrity: sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w==}
pg-copy-streams-binary@2.2.0:
resolution: {integrity: sha512-jPCWgTR8004wz5XOI2sc09+IMwE7YMeINYCabwPMCPtlgj2ay81VLCClMkj/u+xOeisRcN8vCrIZ4FrqlaTyBQ==}
pg-copy-streams@6.0.4:
resolution: {integrity: sha512-FH6q2nFo0n2cFacLyIKorjDz8AOYtxrAANx1XMvYbKWNM2geY731gZstuP4mXMlqO6urRl9oIscFxf3GMIg3Ng==}
pg-cursor@2.18.0:
resolution: {integrity: sha512-WkMubzXP+FWDIC6XfA9pZwJHO0rmUwbNXUNFfBshp9amnCraQslVLYqEuWA+7qemtyz+v3zybcvcX//Dq5WpxQ==}
pg-cursor@2.19.0:
resolution: {integrity: sha512-J5cF1MUz7LRJ9emOqF/06QjabMHMZy587rSPF0UuA8rCwKeeYl2co8Pp+6k5UU9YrAYHMzWkLxilfZB0hqsWWw==}
peerDependencies:
pg: ^8
@ -16144,6 +16145,11 @@ packages:
resolution: {integrity: sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==}
engines: {node: '>=4'}
pg-pool@3.13.0:
resolution: {integrity: sha512-gB+R+Xud1gLFuRD/QgOIgGOBE2KCQPaPwkzBBGC9oG69pHTkhQeIuejVIk3/cnDyX39av2AxomQiyPT13WKHQA==}
peerDependencies:
pg: '>=8.0'
pg-pool@3.7.0:
resolution: {integrity: sha512-ZOBQForurqh4zZWjrgSwwAtzJ7QiRX0ovFkZr2klsen3Nm0aoh33Ls0fzfv3imeH/nw/O27cjdz5kzYJfeGp/g==}
peerDependencies:
@ -16155,11 +16161,14 @@ packages:
peerDependencies:
pg-query-stream: 4.7.1
pg-protocol@1.13.0:
resolution: {integrity: sha512-zzdvXfS6v89r6v7OcFCHfHlyG/wvry1ALxZo4LqgUoy7W9xhBDMaqOuMiF3qEV45VqsN6rdlcehHrfDtlCPc8w==}
pg-protocol@1.7.0:
resolution: {integrity: sha512-hTK/mE36i8fDDhgDFjy6xNOG+LCorxLG3WO17tku+ij6sVHXh1jQUJ8hYAnRhNla4QVD2H8er/FOjc/+EgC6yQ==}
pg-query-stream@4.7.0:
resolution: {integrity: sha512-aQpK8yfFTvOzvPmhXEzWfkwM24lv2Y3TfFY0HJYwx0YM/2fL4DhqpBhLni2Kd+l9p/XoDEi+HFvEvOCm7oqaLg==}
pg-query-stream@4.14.0:
resolution: {integrity: sha512-B1LLxgqngAATPciOPYYKyaQfsw5wyP6BZq6nHqQOC5QaaEBsfW/0OBwWUga+knCAqENMeoow9I8Zgi2m3P9rWw==}
peerDependencies:
pg: ^8
@ -16167,8 +16176,8 @@ packages:
resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==}
engines: {node: '>=4'}
pg-types@4.0.1:
resolution: {integrity: sha512-hRCSDuLII9/LE3smys1hRHcu5QGcLs9ggT7I/TCs0IE+2Eesxi9+9RWAAwZ0yaGjxoWICF/YHLOEjydGujoJ+g==}
pg-types@4.1.0:
resolution: {integrity: sha512-o2XFanIMy/3+mThw69O8d4n1E5zsLhdO+OPqswezu7Z5ekP4hYDqlDjlmOpYMbzY2Br0ufCwJLdDIXeNVwcWFg==}
engines: {node: '>=10'}
pg@8.13.1:
@ -16180,6 +16189,15 @@ packages:
pg-native:
optional: true
pg@8.20.0:
resolution: {integrity: sha512-ldhMxz2r8fl/6QkXnBD3CR9/xg694oT6DZQ2s6c/RI28OjtSOpxnPrUCGOBJ46RCUxcWdx3p6kw/xnDHjKvaRA==}
engines: {node: '>= 16.0.0'}
peerDependencies:
pg-native: '>=3.0.1'
peerDependenciesMeta:
pg-native:
optional: true
pgpass@1.0.5:
resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==}
@ -16317,8 +16335,8 @@ packages:
resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==}
engines: {node: '>=4'}
postgres-array@3.0.1:
resolution: {integrity: sha512-h7i53Dw2Yq3a1uuZ6lbVFAkvMMwssJ8jkzeAg0XaZm1XIFF/t/s+tockdqbWTymyEm07dVenOQbFisEi+kj8uA==}
postgres-array@3.0.4:
resolution: {integrity: sha512-nAUSGfSDGOaOAEGwqsRY27GPOea7CNipJPOA7lPbdEpx5Kg3qzdP0AaWC5MlhTWV9s4hFX39nomVZ+C4tnGOJQ==}
engines: {node: '>=12'}
postgres-bytea@1.0.0:
@ -16333,8 +16351,8 @@ packages:
resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==}
engines: {node: '>=0.10.0'}
postgres-date@2.0.1:
resolution: {integrity: sha512-YtMKdsDt5Ojv1wQRvUhnyDJNSr2dGIC96mQVKz7xufp07nfuFONzdaowrMHjlAzY6GDLd4f+LUHHAAM1h4MdUw==}
postgres-date@2.1.0:
resolution: {integrity: sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==}
engines: {node: '>=12'}
postgres-interval@1.2.0:
@ -16345,8 +16363,8 @@ packages:
resolution: {integrity: sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==}
engines: {node: '>=12'}
postgres-interval@4.0.0:
resolution: {integrity: sha512-OWeL7kyEKJiY7mCmVY+c7/6uhAlt/colA/Nl/Mgls/M3jssrQzFra04iNWnD/qAmG7TsCSgWAASCyiaoBOP/sg==}
postgres-interval@4.0.2:
resolution: {integrity: sha512-EMsphSQ1YkQqKZL2cuG0zHkmjCCzQqQ71l2GXITqRwjhRleCdv00bDk/ktaSi0LnlaPzAc3535KTrjXsTdtx7A==}
engines: {node: '>=12'}
postgres-range@1.1.3:
@ -16452,9 +16470,9 @@ packages:
resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
pretty-ms@7.0.1:
resolution: {integrity: sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==}
engines: {node: '>=10'}
pretty-ms@9.3.0:
resolution: {integrity: sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==}
engines: {node: '>=18'}
pretty-quick@4.0.0:
resolution: {integrity: sha512-M+2MmeufXb/M7Xw3Afh1gxcYpj+sK0AxEfnfF958ktFeAyi5MsKY5brymVURQLgPLV1QaF5P4pb2oFJ54H3yzQ==}
@ -17099,9 +17117,9 @@ packages:
engines: {node: 20 || >=22}
hasBin: true
roarr@7.14.3:
resolution: {integrity: sha512-AvUQY27C6/biXEAyYUXc8ONBtP1cA3MQM88e24Fmsl3LAqtNR309nMaWFALYk7ORTqgGrgrjBJ1vE20DZAc5qA==}
engines: {node: '>=12.0'}
roarr@7.21.4:
resolution: {integrity: sha512-qvfUKCrpPzhWmQ4NxRYnuwhkI5lwmObhBU06BCK/lpj6PID9nL4Hk6XDwek2foKI+TMaV+Yw//XZshGF2Lox/Q==}
engines: {node: '>=18.0'}
rolldown-vite@7.1.14:
resolution: {integrity: sha512-eSiiRJmovt8qDJkGyZuLnbxAOAdie6NCmmd0NkTC0RJI9duiSBTfr8X2mBYJOUFzxQa2USaHmL99J9uMxkjCyw==}
@ -17278,13 +17296,9 @@ packages:
sentence-case@3.0.4:
resolution: {integrity: sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==}
serialize-error@5.0.0:
resolution: {integrity: sha512-/VtpuyzYf82mHYTtI4QKtwHa79vAdU5OQpNPAmE/0UDdlGT0ZxHwC+J6gXkw29wwoVI8fMPsfcVHOwXtUQYYQA==}
engines: {node: '>=8'}
serialize-error@8.1.0:
resolution: {integrity: sha512-3NnuWfM6vBYoy5gZFvHiYsVbafvI9vZv/+jlIigFn4oP4zjNPK3LhcY0xSCgeb1a5L8jO71Mit9LlNoi2UfDDQ==}
engines: {node: '>=10'}
serialize-error@12.0.0:
resolution: {integrity: sha512-ZYkZLAvKTKQXWuh5XpBw7CdbSzagarX39WyZ2H07CDLC5/KfsRGlIXV8d4+tfqX1M7916mRqR1QfNHSij+c9Pw==}
engines: {node: '>=18'}
seroval-plugins@1.3.3:
resolution: {integrity: sha512-16OL3NnUBw8JG1jBLUoZJsLnQq0n5Ua6aHalhJK4fMQkz1lqR7Osz1sA30trBtd9VUDc2NgkuRCn8+/pBwqZ+w==}
@ -17438,21 +17452,21 @@ packages:
slick@1.12.2:
resolution: {integrity: sha512-4qdtOGcBjral6YIBCWJ0ljFSKNLz9KkhbWtuGvUyRowl1kxfuE1x/Z/aJcaiilpb3do9bl5K7/1h9XC5wWpY/A==}
slonik-interceptor-query-logging@46.4.0:
resolution: {integrity: sha512-OVJgY4B4JTynvwc+CrdvYKRZgkqNQ6OyFgh/yf880Chzi2cFcINaXYOq/1fIccAFDXVhxbMsq7M+FjEdlz/ITQ==}
engines: {node: '>=18'}
slonik-interceptor-query-logging@48.13.2:
resolution: {integrity: sha512-/Ib0eIj7pIki+czELuMFvP6z5FWH4m5pCkhWR1QbiCxDB7Zmf705bSkWcux2iChTu2WcWVcAnBdcdk/iZS9fpw==}
engines: {node: '>=24'}
peerDependencies:
slonik: '>=45.0.0'
slonik-utilities@1.9.4:
resolution: {integrity: sha512-kKu6y7cobAyoWfwaS6zZF7oqosxQ+iEBpQYD3YFv+B/jd/YM+4XxFidintA3CGnmq3R4EmXnPMsyy8IpKeE/Hg==}
engines: {node: '>=8.0'}
slonik-sql-tag-raw@48.13.2:
resolution: {integrity: sha512-1bMik7cU7usGIiOtn3Yjzw8p+enS/mAAjzwDyYoeoIUiEivUJytMBBZMP0V7JaeI5BeE89jRCx5LLDUFk3Tqhg==}
engines: {node: '>=24'}
peerDependencies:
slonik: ^28 | ^29
slonik: '>=45.0.0'
slonik@30.4.4:
resolution: {integrity: sha512-5Z1QJhRCDyq0J+0yiUN6COETKtvrYdmukeQn5RZUSt7EvzYo4oTm7D4j2ZV4DN0DMHsaQBSnW/tIgX+UHRJYmQ==}
engines: {node: '>=10.0'}
slonik@48.13.2:
resolution: {integrity: sha512-NU+pTfVJAIPTMcWlMYhFobuAQHM0orXlEWcDxrUVvCLEf+NvzB4nrlih7w6XHIf5RLRDq2zghzWuGSGagBe7HQ==}
engines: {node: '>=24'}
slugify@1.6.6:
resolution: {integrity: sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==}
@ -17635,6 +17649,9 @@ packages:
resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
engines: {node: '>=10.0.0'}
strict-event-emitter-types@2.0.0:
resolution: {integrity: sha512-Nk/brWYpD85WlOgzw5h173aci0Teyv8YdIAEtV+N88nDB0dLlazZyJMIsN6eo1/AR61l+p6CJTG1JIyFaoNEEA==}
strict-event-emitter@0.5.1:
resolution: {integrity: sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==}
@ -17645,10 +17662,6 @@ packages:
string-env-interpolation@1.0.1:
resolution: {integrity: sha512-78lwMoCcn0nNu8LszbP1UA7g55OeE4v7rCeWnM5B453rnNr4aq+5it3FEYtZrSEiMvHZOZ9Jlqb0OD0M2VInqg==}
string-similarity@4.0.4:
resolution: {integrity: sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ==}
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
string-template@0.2.1:
resolution: {integrity: sha512-Yptehjogou2xm4UJbxJ4CxgZx12HBfeystp0y3x7s4Dj32ltVVG1Gg8YhKjHZkHicuKpZX/ffilA8505VbUbpw==}
@ -17916,12 +17929,6 @@ packages:
through2@2.0.5:
resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==}
through2@3.0.2:
resolution: {integrity: sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==}
through2@4.0.2:
resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==}
through@2.3.8:
resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==}
@ -18253,6 +18260,10 @@ packages:
resolution: {integrity: sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==}
engines: {node: '>=16'}
type-fest@4.41.0:
resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==}
engines: {node: '>=16'}
type-fest@5.4.2:
resolution: {integrity: sha512-FLEenlVYf7Zcd34ISMLo3ZzRE1gRjY1nMDTp+bQRBiPsaKyIW8K3Zr99ioHDUgA9OGuGGJPyYpNcffGmBhJfGg==}
engines: {node: '>=20'}
@ -29332,6 +29343,55 @@ snapshots:
transitivePeerDependencies:
- debug
'@slonik/driver@48.13.2(zod@4.3.6)':
dependencies:
'@slonik/types': 48.13.2(zod@4.3.6)
'@slonik/utilities': 48.13.2(zod@4.3.6)
roarr: 7.21.4
serialize-error: 12.0.0
strict-event-emitter-types: 2.0.0
zod: 4.3.6
'@slonik/errors@48.13.2(zod@4.3.6)':
dependencies:
'@slonik/types': 48.13.2(zod@4.3.6)
transitivePeerDependencies:
- zod
'@slonik/pg-driver@48.13.2(patch_hash=d281baceb3dc04c2d6348d8b2bb1f5598bef4e24a6a173fc0048c2b3ab6e27ea)(zod@4.3.6)':
dependencies:
'@slonik/driver': 48.13.2(zod@4.3.6)
'@slonik/errors': 48.13.2(zod@4.3.6)
'@slonik/sql-tag': 48.13.2
'@slonik/types': 48.13.2(zod@4.3.6)
'@slonik/utilities': 48.13.2(zod@4.3.6)
pg: 8.20.0
pg-query-stream: 4.14.0(pg@8.20.0)
pg-types: 4.1.0
postgres-array: 3.0.4
zod: 4.3.6
transitivePeerDependencies:
- pg-native
'@slonik/sql-tag@48.13.2':
dependencies:
'@slonik/errors': 48.13.2(zod@4.3.6)
'@slonik/types': 48.13.2(zod@4.3.6)
roarr: 7.21.4
safe-stable-stringify: 2.5.0
serialize-error: 12.0.0
zod: 4.3.6
'@slonik/types@48.13.2(zod@4.3.6)':
dependencies:
zod: 4.3.6
'@slonik/utilities@48.13.2(zod@4.3.6)':
dependencies:
'@slonik/errors': 48.13.2(zod@4.3.6)
'@slonik/types': 48.13.2(zod@4.3.6)
zod: 4.3.6
'@smithy/abort-controller@4.0.0':
dependencies:
'@smithy/types': 4.11.0
@ -31076,7 +31136,7 @@ snapshots:
dependencies:
'@types/node': 24.10.9
pg-protocol: 1.7.0
pg-types: 4.0.1
pg-types: 4.1.0
'@types/pg@8.15.6':
dependencies:
@ -32298,8 +32358,6 @@ snapshots:
base64-js: 1.5.1
ieee754: 1.2.1
bufferput@0.1.3: {}
bufrw@1.4.0:
dependencies:
ansi-color: 0.2.1
@ -32864,8 +32922,6 @@ snapshots:
dependencies:
browserslist: 4.28.1
core-js@3.25.5: {}
core-util-is@1.0.2: {}
core-util-is@1.0.3: {}
@ -33237,8 +33293,6 @@ snapshots:
escodegen: 2.1.0
esprima: 4.0.1
delay@4.4.1: {}
delayed-stream@1.0.0: {}
delegates@1.0.0: {}
@ -33609,8 +33663,6 @@ snapshots:
is-date-object: 1.1.0
is-symbol: 1.1.1
es6-error@4.1.1: {}
esast-util-from-estree@2.0.0:
dependencies:
'@types/estree-jsx': 1.0.0
@ -34253,13 +34305,6 @@ snapshots:
fast-json-stable-stringify@2.1.0: {}
fast-json-stringify@2.7.13:
dependencies:
ajv: 6.14.0
deepmerge: 4.3.1
rfdc: 1.4.1
string-similarity: 4.0.4
fast-json-stringify@5.16.1:
dependencies:
'@fastify/merge-json-schemas': 0.1.1
@ -34690,11 +34735,6 @@ snapshots:
data-uri-to-buffer: 2.0.2
source-map: 0.6.1
get-stack-trace@2.1.1:
dependencies:
bluebird: 3.7.2
source-map: 0.8.0-beta.0
get-stdin@8.0.0: {}
get-stdin@9.0.0: {}
@ -35589,11 +35629,6 @@ snapshots:
humps@2.0.1: {}
hyperid@2.3.1:
dependencies:
uuid: 8.3.2
uuid-parse: 1.1.0
hyperid@3.3.0:
dependencies:
buffer: 5.7.1
@ -35734,8 +35769,6 @@ snapshots:
inline-style-parser@0.2.4: {}
int64-buffer@0.99.1007: {}
internal-slot@1.1.0:
dependencies:
es-errors: 1.3.0
@ -35962,8 +35995,6 @@ snapshots:
dependencies:
isobject: 3.0.1
is-plain-object@5.0.0: {}
is-primitive@3.0.1: {}
is-property@1.0.2: {}
@ -36092,7 +36123,7 @@ snapshots:
isexe@3.1.1: {}
iso8601-duration@1.3.0: {}
iso8601-duration@2.1.3: {}
isobject@3.0.1: {}
@ -37839,8 +37870,6 @@ snapshots:
muggle-string@0.4.1: {}
multi-fork@0.0.2: {}
mustache@4.2.0: {}
mute-stream@1.0.0: {}
@ -38237,8 +38266,6 @@ snapshots:
p-cancelable@4.0.1(patch_hash=195ae63d47810ca4c987421948f15869356e598dccde9e8c9a4ff4efd3e88322): {}
p-defer@3.0.0: {}
p-filter@2.1.0:
dependencies:
p-map: 2.1.0
@ -38410,7 +38437,7 @@ snapshots:
lines-and-columns: 2.0.3
type-fest: 3.13.1
parse-ms@2.1.0: {}
parse-ms@4.0.0: {}
parse-node-version@1.0.1:
optional: true
@ -38500,24 +38527,16 @@ snapshots:
pg-cloudflare@1.1.1:
optional: true
pg-cloudflare@1.3.0:
optional: true
pg-connection-string@2.12.0: {}
pg-connection-string@2.9.1: {}
pg-copy-streams-binary@2.2.0:
pg-cursor@2.19.0(pg@8.20.0):
dependencies:
bl: 4.1.0
bufferput: 0.1.3
ieee754: 1.2.1
int64-buffer: 0.99.1007
multi-fork: 0.0.2
through2: 3.0.2
pg-copy-streams@6.0.4:
dependencies:
obuf: 1.1.2
pg-cursor@2.18.0(pg@8.13.1):
dependencies:
pg: 8.13.1
pg: 8.20.0
pg-int8@1.0.1: {}
@ -38525,26 +38544,32 @@ snapshots:
pg-numeric@1.0.2: {}
pg-pool@3.13.0(pg@8.20.0):
dependencies:
pg: 8.20.0
pg-pool@3.7.0(pg@8.13.1):
dependencies:
pg: 8.13.1
pg-promise@11.10.2(pg-query-stream@4.7.0(pg@8.13.1)):
pg-promise@11.10.2(pg-query-stream@4.14.0(pg@8.20.0)):
dependencies:
assert-options: 0.8.2
pg: 8.13.1
pg-minify: 1.6.5
pg-query-stream: 4.7.0(pg@8.13.1)
pg-query-stream: 4.14.0(pg@8.20.0)
spex: 3.4.0
transitivePeerDependencies:
- pg-native
pg-protocol@1.13.0: {}
pg-protocol@1.7.0: {}
pg-query-stream@4.7.0(pg@8.13.1):
pg-query-stream@4.14.0(pg@8.20.0):
dependencies:
pg: 8.13.1
pg-cursor: 2.18.0(pg@8.13.1)
pg: 8.20.0
pg-cursor: 2.19.0(pg@8.20.0)
pg-types@2.2.0:
dependencies:
@ -38554,13 +38579,13 @@ snapshots:
postgres-date: 1.0.7
postgres-interval: 1.2.0
pg-types@4.0.1:
pg-types@4.1.0:
dependencies:
pg-int8: 1.0.1
pg-numeric: 1.0.2
postgres-array: 3.0.1
postgres-array: 3.0.4
postgres-bytea: 3.0.0
postgres-date: 2.0.1
postgres-date: 2.1.0
postgres-interval: 3.0.0
postgres-range: 1.1.3
@ -38574,6 +38599,16 @@ snapshots:
optionalDependencies:
pg-cloudflare: 1.1.1
pg@8.20.0:
dependencies:
pg-connection-string: 2.12.0
pg-pool: 3.13.0(pg@8.20.0)
pg-protocol: 1.13.0
pg-types: 2.2.0
pgpass: 1.0.5
optionalDependencies:
pg-cloudflare: 1.3.0
pgpass@1.0.5:
dependencies:
split2: 4.1.0
@ -38708,7 +38743,7 @@ snapshots:
postgres-array@2.0.0: {}
postgres-array@3.0.1: {}
postgres-array@3.0.4: {}
postgres-bytea@1.0.0: {}
@ -38718,7 +38753,7 @@ snapshots:
postgres-date@1.0.7: {}
postgres-date@2.0.1: {}
postgres-date@2.1.0: {}
postgres-interval@1.2.0:
dependencies:
@ -38726,7 +38761,7 @@ snapshots:
postgres-interval@3.0.0: {}
postgres-interval@4.0.0: {}
postgres-interval@4.0.2: {}
postgres-range@1.1.3: {}
@ -38770,9 +38805,9 @@ snapshots:
ansi-styles: 5.2.0
react-is: 18.3.1
pretty-ms@7.0.1:
pretty-ms@9.3.0:
dependencies:
parse-ms: 2.1.0
parse-ms: 4.0.0
pretty-quick@4.0.0(prettier@3.4.2):
dependencies:
@ -39552,12 +39587,9 @@ snapshots:
glob: 13.0.6
package-json-from-dist: 1.0.1
roarr@7.14.3:
roarr@7.21.4:
dependencies:
boolean: 3.2.0
fast-json-stringify: 2.7.13
fast-printf: 1.6.9
globalthis: 1.0.4
safe-stable-stringify: 2.5.0
semver-compare: 1.0.0
@ -39766,13 +39798,9 @@ snapshots:
tslib: 2.8.1
upper-case-first: 2.0.2
serialize-error@5.0.0:
serialize-error@12.0.0:
dependencies:
type-fest: 0.8.1
serialize-error@8.1.0:
dependencies:
type-fest: 0.20.2
type-fest: 4.41.0
seroval-plugins@1.3.3(seroval@1.5.0):
dependencies:
@ -39965,44 +39993,35 @@ snapshots:
slick@1.12.2: {}
slonik-interceptor-query-logging@46.4.0(slonik@30.4.4(patch_hash=195b140c0181c27a85a6026c0058087a419e38f6c5d89f5f2c608e39f5bf23e9)):
slonik-interceptor-query-logging@48.13.2(slonik@48.13.2(patch_hash=e16e74ebc8c5f42be257d540b5ac7d175ff3264481046b5c33fc647c9997acdc)):
dependencies:
crack-json: 1.3.0
pretty-ms: 7.0.1
serialize-error: 8.1.0
slonik: 30.4.4(patch_hash=195b140c0181c27a85a6026c0058087a419e38f6c5d89f5f2c608e39f5bf23e9)
pretty-ms: 9.3.0
serialize-error: 12.0.0
slonik: 48.13.2(patch_hash=e16e74ebc8c5f42be257d540b5ac7d175ff3264481046b5c33fc647c9997acdc)
slonik-utilities@1.9.4:
slonik-sql-tag-raw@48.13.2(slonik@48.13.2(patch_hash=e16e74ebc8c5f42be257d540b5ac7d175ff3264481046b5c33fc647c9997acdc)):
dependencies:
core-js: 3.25.5
delay: 4.4.1
es6-error: 4.1.1
lodash: 4.18.1
roarr: 7.14.3
serialize-error: 5.0.0
'@slonik/sql-tag': 48.13.2
roarr: 7.21.4
slonik: 48.13.2(patch_hash=e16e74ebc8c5f42be257d540b5ac7d175ff3264481046b5c33fc647c9997acdc)
slonik@30.4.4(patch_hash=195b140c0181c27a85a6026c0058087a419e38f6c5d89f5f2c608e39f5bf23e9):
slonik@48.13.2(patch_hash=e16e74ebc8c5f42be257d540b5ac7d175ff3264481046b5c33fc647c9997acdc):
dependencies:
concat-stream: 2.0.0
es6-error: 4.1.1
fast-safe-stringify: 2.1.1
get-stack-trace: 2.1.1
hyperid: 2.3.1
is-plain-object: 5.0.0
iso8601-duration: 1.3.0
p-defer: 3.0.0
pg: 8.13.1
pg-copy-streams: 6.0.4
pg-copy-streams-binary: 2.2.0
pg-cursor: 2.18.0(pg@8.13.1)
pg-protocol: 1.7.0
pg-types: 4.0.1
postgres-array: 3.0.1
postgres-interval: 4.0.0
roarr: 7.14.3
serialize-error: 8.1.0
through2: 4.0.2
zod: 3.25.76
'@opentelemetry/api': 1.9.0
'@slonik/driver': 48.13.2(zod@4.3.6)
'@slonik/errors': 48.13.2(zod@4.3.6)
'@slonik/pg-driver': 48.13.2(patch_hash=d281baceb3dc04c2d6348d8b2bb1f5598bef4e24a6a173fc0048c2b3ab6e27ea)(zod@4.3.6)
'@slonik/sql-tag': 48.13.2
'@slonik/utilities': 48.13.2(zod@4.3.6)
'@standard-schema/spec': 1.0.0
iso8601-duration: 2.1.3
p-limit: 6.2.0
postgres-interval: 4.0.2
roarr: 7.21.4
serialize-error: 12.0.0
strict-event-emitter-types: 2.0.0
zod: 4.3.6
transitivePeerDependencies:
- pg-native
@ -40184,14 +40203,14 @@ snapshots:
streamsearch@1.1.0: {}
strict-event-emitter-types@2.0.0: {}
strict-event-emitter@0.5.1: {}
string-argv@0.3.2: {}
string-env-interpolation@1.0.1: {}
string-similarity@4.0.4: {}
string-template@0.2.1: {}
string-width@4.2.3:
@ -40522,15 +40541,6 @@ snapshots:
readable-stream: 2.3.8
xtend: 4.0.2
through2@3.0.2:
dependencies:
inherits: 2.0.4
readable-stream: 3.6.0
through2@4.0.2:
dependencies:
readable-stream: 3.6.0
through@2.3.8: {}
timeout-signal@2.0.0: {}
@ -40837,6 +40847,8 @@ snapshots:
type-fest@4.26.1: {}
type-fest@4.41.0: {}
type-fest@5.4.2:
dependencies:
tagged-tag: 1.0.0