0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-03-10 22:22:45 -05:00

Merge pull request #5512 from logto-io/gao-shared-default-universal

refactor: remove slonik from shared
This commit is contained in:
Gao Sun 2024-03-18 09:58:49 +08:00 committed by GitHub
commit 82408b60c8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
65 changed files with 224 additions and 105 deletions

View file

@ -65,7 +65,7 @@
"pg-protocol": "^1.6.0",
"roarr": "^7.11.0",
"semver": "^7.3.8",
"slonik": "^30.0.0",
"slonik": "30.4.0",
"slonik-interceptor-preset": "^1.2.10",
"slonik-sql-tag-raw": "^1.1.4",
"tar": "^6.1.11",

View file

@ -28,7 +28,7 @@ import {
} from '@logto/schemas';
import { getTenantRole } from '@logto/schemas';
import { Tenants } from '@logto/schemas/models';
import { convertToIdentifiers, generateStandardId } from '@logto/shared';
import { generateStandardId } from '@logto/shared';
import type { DatabaseTransactionConnection } from 'slonik';
import { sql } from 'slonik';
import { raw } from 'slonik-sql-tag-raw';
@ -36,6 +36,7 @@ import { raw } from 'slonik-sql-tag-raw';
import { insertInto } from '../../../database.js';
import { getDatabaseName } from '../../../queries/database.js';
import { updateDatabaseTimestamp } from '../../../queries/system.js';
import { convertToIdentifiers } from '../../../sql.js';
import { consoleLog, getPathInModule } from '../../../utils.js';
import { appendAdminConsoleRedirectUris, seedTenantCloudServiceApplication } from './cloud.js';

View file

@ -1,11 +1,11 @@
import type { SchemaLike } from '@logto/schemas';
import { convertToPrimitiveOrSql } from '@logto/shared';
import { assert } from '@silverhand/essentials';
import decamelize from 'decamelize';
import { DatabaseError } from 'pg-protocol';
import { createPool, parseDsn, sql, stringifyDsn } from 'slonik';
import { createInterceptors } from 'slonik-interceptor-preset';
import { convertToPrimitiveOrSql } from './sql.js';
import { ConfigKey, consoleLog, getCliConfigWithPrompt } from './utils.js';
export const defaultDatabaseUrl = 'postgresql://localhost:5432/logto';

View file

@ -1,11 +1,12 @@
import type { LogtoConfig, LogtoConfigKey, logtoConfigGuards } from '@logto/schemas';
import { LogtoConfigs } from '@logto/schemas';
import { convertToIdentifiers } from '@logto/shared';
import type { Nullable } from '@silverhand/essentials';
import type { CommonQueryMethods } from 'slonik';
import { sql } from 'slonik';
import type { z } from 'zod';
import { convertToIdentifiers } from '../sql.js';
const { table, fields } = convertToIdentifiers(LogtoConfigs);
export const doesConfigsTableExist = async (pool: CommonQueryMethods) => {

View file

@ -1,8 +1,8 @@
import { AlterationStateKey, Systems } from '@logto/schemas';
import { convertToIdentifiers } from '@logto/shared';
import { DatabaseError } from 'pg-protocol';
import { createMockPool, createMockQueryResult, sql } from 'slonik';
import { convertToIdentifiers } from '../sql.js';
import type { QueryType } from '../test-utils.js';
import { expectSqlAssert } from '../test-utils.js';

View file

@ -1,12 +1,13 @@
import type { AlterationState, System, SystemKey } from '@logto/schemas';
import { systemGuards, Systems, AlterationStateKey } from '@logto/schemas';
import { convertToIdentifiers } from '@logto/shared';
import type { Nullable } from '@silverhand/essentials';
import { DatabaseError } from 'pg-protocol';
import type { CommonQueryMethods, DatabaseTransactionConnection } from 'slonik';
import { sql } from 'slonik';
import type { z } from 'zod';
import { convertToIdentifiers } from '../sql.js';
const { fields, table } = convertToIdentifiers(Systems);
const doesTableExist = async (pool: CommonQueryMethods, table: string) => {

75
packages/cli/src/sql.ts Normal file
View file

@ -0,0 +1,75 @@
/**
* @fileoverview Copied from `@logto/core`. Originally we put them in `@logto/shared` but it
* requires `slonik` which makes the package too heavy.
*
* Since `@logto/cli` only use these functions in a stable manner, we copy them here for now. If
* the number of functions grows, we should consider moving them to a separate package. (Actually,
* we should remove the dependency on `slonik` at all, and this may not be an issue then.)
*/
import { type SchemaValue, type SchemaValuePrimitive, type Table } from '@logto/shared';
import { type IdentifierSqlToken, type SqlToken, sql } from 'slonik';
/**
* Note `undefined` is removed from the acceptable list,
* since you should NOT call this function if ignoring the field is the desired behavior.
* Calling this function with `null` means an explicit `null` setting in database is expected.
* @param key The key of value. Will treat as `timestamp` if it ends with `_at` or 'At' AND value is a number;
* @param value The value to convert.
* @returns A primitive that can be saved into database.
*/
export const convertToPrimitiveOrSql = (
key: string,
value: SchemaValue
// eslint-disable-next-line @typescript-eslint/ban-types
): NonNullable<SchemaValuePrimitive> | SqlToken | null => {
if (value === null) {
return null;
}
if (typeof value === 'object') {
return JSON.stringify(value);
}
if (
(['_at', 'At'].some((value) => key.endsWith(value)) || key === 'date') &&
typeof value === 'number'
) {
return sql`to_timestamp(${value}::double precision / 1000)`;
}
if (typeof value === 'number' || typeof value === 'boolean') {
return value;
}
if (typeof value === 'string') {
if (value === '') {
return null;
}
return value;
}
throw new Error(`Cannot convert ${key} to primitive`);
};
type FieldIdentifiers<Key extends string> = {
[key in Key]: IdentifierSqlToken;
};
export const convertToIdentifiers = <Key extends string>(
{ table, fields }: Table<Key>,
withPrefix = false
) => {
const fieldsIdentifiers = Object.entries<string>(fields).map<[Key, IdentifierSqlToken]>(
// eslint-disable-next-line no-restricted-syntax -- Object.entries can only return string keys
([key, value]) => [key as Key, sql.identifier(withPrefix ? [table, value] : [value])]
);
return {
table: sql.identifier([table]),
// Key value inferred from the original fields directly
// eslint-disable-next-line no-restricted-syntax
fields: Object.fromEntries(fieldsIdentifiers) as FieldIdentifiers<Key>,
};
};

View file

@ -85,7 +85,7 @@
"roarr": "^7.11.0",
"samlify": "2.8.10",
"semver": "^7.3.8",
"slonik": "^30.0.0",
"slonik": "30.4.0",
"slonik-interceptor-preset": "^1.2.10",
"slonik-sql-tag-raw": "^1.1.4",
"snake-case": "^3.0.4",

View file

@ -1,7 +1,8 @@
import { type GeneratedSchema, type SchemaLike } from '@logto/schemas';
import { conditionalSql, convertToIdentifiers, manyRows } from '@logto/shared';
import { sql, type CommonQueryMethods } from 'slonik';
import { conditionalSql, convertToIdentifiers, manyRows } from '#src/utils/sql.js';
import { buildSearchSql, expandFields, type SearchOptions } from './utils.js';
export const buildFindAllEntitiesWithPool =

View file

@ -1,11 +1,11 @@
import type { SchemaLike, GeneratedSchema } from '@logto/schemas';
import { convertToIdentifiers } from '@logto/shared';
import type { CommonQueryMethods } from 'slonik';
import { sql, NotFoundError } from 'slonik';
import RequestError from '#src/errors/RequestError/index.js';
import assertThat from '#src/utils/assert-that.js';
import { isKeyOf } from '#src/utils/schema.js';
import { convertToIdentifiers } from '#src/utils/sql.js';
type WithId<Key> = Key | 'id';

View file

@ -1,9 +1,9 @@
import type { CreateUser } from '@logto/schemas';
import { Users } from '@logto/schemas';
import { convertToIdentifiers } from '@logto/shared';
import decamelize from 'decamelize';
import { InsertionError } from '#src/errors/SlonikError/index.js';
import { convertToIdentifiers } from '#src/utils/sql.js';
import { createTestPool } from '#src/utils/test-utils.js';
const { buildInsertIntoWithPool } = await import('./insert-into.js');

View file

@ -1,17 +1,17 @@
import type { GeneratedSchema, SchemaLike } from '@logto/schemas';
import type { OmitAutoSetFields } from '@logto/shared';
import {
convertToIdentifiers,
excludeAutoSetFields,
convertToPrimitiveOrSql,
conditionalSql,
} from '@logto/shared';
import { has } from '@silverhand/essentials';
import type { CommonQueryMethods, IdentifierSqlToken } from 'slonik';
import { sql } from 'slonik';
import { InsertionError } from '#src/errors/SlonikError/index.js';
import assertThat from '#src/utils/assert-that.js';
import {
type OmitAutoSetFields,
convertToIdentifiers,
excludeAutoSetFields,
convertToPrimitiveOrSql,
conditionalSql,
} from '#src/utils/sql.js';
const setExcluded = (...fields: IdentifierSqlToken[]) =>
sql.join(

View file

@ -1,5 +1,4 @@
import type { SchemaLike, GeneratedSchema, SchemaValue } from '@logto/schemas';
import { convertToIdentifiers, convertToPrimitiveOrSql, conditionalSql } from '@logto/shared';
import type { UpdateWhereData } from '@logto/shared';
import type { Truthy } from '@silverhand/essentials';
import { notFalsy } from '@silverhand/essentials';
@ -9,6 +8,7 @@ import { sql } from 'slonik';
import { UpdateError } from '#src/errors/SlonikError/index.js';
import assertThat from '#src/utils/assert-that.js';
import { isKeyOf } from '#src/utils/schema.js';
import { convertToIdentifiers, convertToPrimitiveOrSql, conditionalSql } from '#src/utils/sql.js';
type BuildUpdateWhere = {
<

View file

@ -1,7 +1,9 @@
import { type GeneratedSchema } from '@logto/schemas';
import { type SchemaLike, conditionalSql, convertToIdentifiers, type Table } from '@logto/shared';
import { type SchemaLike, type Table } from '@logto/shared';
import { type SqlSqlToken, sql } from 'slonik';
import { conditionalSql, convertToIdentifiers } from '#src/utils/sql.js';
/**
* Options for searching for a string within a set of fields (case-insensitive).
*/

View file

@ -1,7 +1,9 @@
import type { SchemaLike, GeneratedSchema } from '@logto/schemas';
import type { OmitAutoSetFields, UpdateWhereData } from '@logto/shared';
import type { UpdateWhereData } from '@logto/shared';
import { SlonikError } from 'slonik';
import { type OmitAutoSetFields } from '#src/utils/sql.js';
export class DeletionError extends SlonikError {
public constructor(
public readonly table?: string,

View file

@ -7,13 +7,13 @@ import {
jwtCustomizerConfigGuard,
} from '@logto/schemas';
import type { LogtoOidcConfigType, LogtoJwtTokenKey } from '@logto/schemas';
import { convertToIdentifiers } from '@logto/shared';
import chalk from 'chalk';
import { z, ZodError } from 'zod';
import RequestError from '#src/errors/RequestError/index.js';
import type Queries from '#src/tenants/Queries.js';
import { consoleLog } from '#src/utils/console.js';
import { convertToIdentifiers } from '#src/utils/sql.js';
export type LogtoConfigLibrary = ReturnType<typeof createLogtoConfigLibrary>;
const { table } = convertToIdentifiers(LogtoConfigs);

View file

@ -1,7 +1,6 @@
import type { User, CreateUser, Scope, BindMfa, MfaVerification } from '@logto/schemas';
import { MfaFactor, Users, UsersPasswordEncryptionMethod } from '@logto/schemas';
import { generateStandardShortId, generateStandardId } from '@logto/shared';
import type { OmitAutoSetFields } from '@logto/shared';
import type { Nullable } from '@silverhand/essentials';
import { deduplicate } from '@silverhand/essentials';
import { argon2Verify, bcryptVerify, md5, sha1, sha256 } from 'hash-wasm';
@ -14,6 +13,7 @@ import { createUsersRolesQueries } from '#src/queries/users-roles.js';
import type Queries from '#src/tenants/Queries.js';
import assertThat from '#src/utils/assert-that.js';
import { encryptPassword } from '#src/utils/password.js';
import type { OmitAutoSetFields } from '#src/utils/sql.js';
export const encryptUserPassword = async (
password: string

View file

@ -7,13 +7,13 @@ import {
LogtoOidcConfigKey,
LogtoConfigs,
} from '@logto/schemas';
import { convertToIdentifiers } from '@logto/shared';
import { appendPath } from '@silverhand/essentials';
import type { JWK } from 'jose';
import { sql } from 'slonik';
import { EnvSet, getTenantEndpoint } from '#src/env-set/index.js';
import { exportJWK } from '#src/utils/jwks.js';
import { convertToIdentifiers } from '#src/utils/sql.js';
const { table, fields } = convertToIdentifiers(LogtoConfigs);

View file

@ -1,9 +1,9 @@
import { ApplicationSignInExperiences, type ApplicationSignInExperience } from '@logto/schemas';
import { convertToIdentifiers } from '@logto/shared';
import { sql, type CommonQueryMethods } from 'slonik';
import { buildInsertIntoWithPool } from '#src/database/insert-into.js';
import { buildUpdateWhereWithPool } from '#src/database/update-where.js';
import { convertToIdentifiers } from '#src/utils/sql.js';
const createApplicationSignInExperienceQueries = (pool: CommonQueryMethods) => {
const insert = buildInsertIntoWithPool(pool)(ApplicationSignInExperiences, {

View file

@ -4,10 +4,10 @@ import {
Organizations,
Users,
} from '@logto/schemas';
import { convertToIdentifiers } from '@logto/shared';
import { sql, type CommonQueryMethods } from 'slonik';
import RelationQueries from '#src/utils/RelationQueries.js';
import { convertToIdentifiers } from '#src/utils/sql.js';
class ApplicationUserConsentOrganizationsQuery extends RelationQueries<
[typeof Applications, typeof Users, typeof Organizations]

View file

@ -7,12 +7,12 @@ import {
OrganizationScopes,
Scopes,
} from '@logto/schemas';
import { convertToIdentifiers } from '@logto/shared';
import { sql, type CommonQueryMethods } from 'slonik';
import { buildInsertIntoWithPool } from '#src/database/insert-into.js';
import { DeletionError } from '#src/errors/SlonikError/index.js';
import { TwoRelationsQueries } from '#src/utils/RelationQueries.js';
import { convertToIdentifiers } from '#src/utils/sql.js';
export class ApplicationUserConsentOrganizationScopeQueries extends TwoRelationsQueries<
typeof Applications,

View file

@ -1,10 +1,14 @@
import { Applications } from '@logto/schemas';
import { convertToIdentifiers, convertToPrimitiveOrSql, excludeAutoSetFields } from '@logto/shared';
import { createMockPool, createMockQueryResult, sql } from 'slonik';
import { snakeCase } from 'snake-case';
import { mockApplication } from '#src/__mocks__/index.js';
import { DeletionError } from '#src/errors/SlonikError/index.js';
import {
convertToIdentifiers,
convertToPrimitiveOrSql,
excludeAutoSetFields,
} from '#src/utils/sql.js';
import type { QueryType } from '#src/utils/test-utils.js';
import { expectSqlAssert } from '#src/utils/test-utils.js';

View file

@ -1,7 +1,5 @@
import type { Application, CreateApplication } from '@logto/schemas';
import { ApplicationType, Applications, SearchJointMode } from '@logto/schemas';
import type { OmitAutoSetFields } from '@logto/shared';
import { convertToIdentifiers, conditionalSql, conditionalArraySql } from '@logto/shared';
import type { CommonQueryMethods, SqlSqlToken } from 'slonik';
import { sql } from 'slonik';
@ -12,6 +10,8 @@ import { buildUpdateWhereWithPool } from '#src/database/update-where.js';
import { DeletionError } from '#src/errors/SlonikError/index.js';
import { buildConditionsFromSearch } from '#src/utils/search.js';
import type { Search } from '#src/utils/search.js';
import { convertToIdentifiers, conditionalSql, conditionalArraySql } from '#src/utils/sql.js';
import type { OmitAutoSetFields } from '#src/utils/sql.js';
import ApplicationUserConsentOrganizationsQuery from './application-user-consent-organizations.js';
import {

View file

@ -1,11 +1,11 @@
import type { ApplicationsRole, CreateApplicationsRole, Role } from '@logto/schemas';
import { Roles, ApplicationsRoles, RolesScopes } from '@logto/schemas';
import { convertToIdentifiers, conditionalSql } from '@logto/shared';
import { type Nullable } from '@silverhand/essentials';
import type { CommonQueryMethods } from 'slonik';
import { sql } from 'slonik';
import { DeletionError } from '#src/errors/SlonikError/index.js';
import { convertToIdentifiers, conditionalSql } from '#src/utils/sql.js';
const { table, fields } = convertToIdentifiers(ApplicationsRoles, true);
const { fields: insertFields } = convertToIdentifiers(ApplicationsRoles);

View file

@ -1,10 +1,10 @@
import { Connectors } from '@logto/schemas';
import { convertToIdentifiers } from '@logto/shared';
import { createMockPool, createMockQueryResult, sql } from 'slonik';
import { mockConnector } from '#src/__mocks__/index.js';
import { DeletionError } from '#src/errors/SlonikError/index.js';
import { MockWellKnownCache } from '#src/test-utils/tenant.js';
import { convertToIdentifiers } from '#src/utils/sql.js';
import type { QueryType } from '#src/utils/test-utils.js';
import { expectSqlAssert } from '#src/utils/test-utils.js';

View file

@ -1,6 +1,5 @@
import type { Connector } from '@logto/schemas';
import { Connectors } from '@logto/schemas';
import { manyRows, convertToIdentifiers } from '@logto/shared';
import type { CommonQueryMethods } from 'slonik';
import { sql } from 'slonik';
@ -9,6 +8,7 @@ import { buildInsertIntoWithPool } from '#src/database/insert-into.js';
import { buildUpdateWhereWithPool } from '#src/database/update-where.js';
import { DeletionError } from '#src/errors/SlonikError/index.js';
import { type ConnectorWellKnown } from '#src/utils/connectors/types.js';
import { convertToIdentifiers, manyRows } from '#src/utils/sql.js';
const { table, fields } = convertToIdentifiers(Connectors);

View file

@ -1,12 +1,13 @@
import type { CustomPhrase, Translation } from '@logto/schemas';
import { CustomPhrases } from '@logto/schemas';
import { convertToIdentifiers, generateStandardId, manyRows } from '@logto/shared';
import { generateStandardId } from '@logto/shared';
import type { CommonQueryMethods } from 'slonik';
import { sql } from 'slonik';
import { type WellKnownCache } from '#src/caches/well-known.js';
import { buildInsertIntoWithPool } from '#src/database/insert-into.js';
import { DeletionError } from '#src/errors/SlonikError/index.js';
import { convertToIdentifiers, manyRows } from '#src/utils/sql.js';
const { table, fields } = convertToIdentifiers(CustomPhrases);

View file

@ -1,8 +1,8 @@
import { DailyActiveUsers } from '@logto/schemas';
import { convertToIdentifiers } from '@logto/shared';
import { sql, type CommonQueryMethods } from 'slonik';
import { buildInsertIntoWithPool } from '#src/database/insert-into.js';
import { convertToIdentifiers } from '#src/utils/sql.js';
const { table, fields } = convertToIdentifiers(DailyActiveUsers);

View file

@ -1,9 +1,10 @@
import { DailyTokenUsage } from '@logto/schemas';
import { convertToIdentifiers, generateStandardId } from '@logto/shared';
import { generateStandardId } from '@logto/shared';
import type { CommonQueryMethods } from 'slonik';
import { sql } from 'slonik';
import { getUtcStartOfTheDay } from '#src/oidc/utils.js';
import { convertToIdentifiers } from '#src/utils/sql.js';
const { table, fields } = convertToIdentifiers(DailyTokenUsage);
const { fields: fieldsWithPrefix } = convertToIdentifiers(DailyTokenUsage, true);

View file

@ -1,6 +1,4 @@
import { type CreateDomain, type Domain, DomainStatus, Domains } from '@logto/schemas';
import type { OmitAutoSetFields } from '@logto/shared';
import { convertToIdentifiers, manyRows } from '@logto/shared';
import type { CommonQueryMethods } from 'slonik';
import { sql } from 'slonik';
@ -8,6 +6,7 @@ import { buildFindEntityByIdWithPool } from '#src/database/find-entity-by-id.js'
import { buildInsertIntoWithPool } from '#src/database/insert-into.js';
import { buildUpdateWhereWithPool } from '#src/database/update-where.js';
import { DeletionError } from '#src/errors/SlonikError/index.js';
import { convertToIdentifiers, manyRows, type OmitAutoSetFields } from '#src/utils/sql.js';
const { table, fields } = convertToIdentifiers(Domains);

View file

@ -1,6 +1,5 @@
import type { CreateHook } from '@logto/schemas';
import { Hooks } from '@logto/schemas';
import { type OmitAutoSetFields, convertToIdentifiers } from '@logto/shared';
import type { CommonQueryMethods } from 'slonik';
import { sql } from 'slonik';
@ -10,6 +9,7 @@ import { buildInsertIntoWithPool } from '#src/database/insert-into.js';
import { getTotalRowCountWithPool } from '#src/database/row-count.js';
import { buildUpdateWhereWithPool } from '#src/database/update-where.js';
import { DeletionError } from '#src/errors/SlonikError/index.js';
import { convertToIdentifiers, type OmitAutoSetFields } from '#src/utils/sql.js';
const { table, fields } = convertToIdentifiers(Hooks);

View file

@ -7,7 +7,6 @@ import {
type interaction,
type LogKeyUnknown,
} from '@logto/schemas';
import { conditionalSql, convertToIdentifiers } from '@logto/shared';
import { conditional, conditionalArray } from '@silverhand/essentials';
import { subDays } from 'date-fns';
import { sql } from 'slonik';
@ -15,6 +14,7 @@ import type { CommonQueryMethods } from 'slonik';
import { buildFindEntityByIdWithPool } from '#src/database/find-entity-by-id.js';
import { buildInsertIntoWithPool } from '#src/database/insert-into.js';
import { conditionalSql, convertToIdentifiers } from '#src/utils/sql.js';
const { table, fields } = convertToIdentifiers(Logs);

View file

@ -4,9 +4,9 @@ import {
LogtoOidcConfigKey,
LogtoTenantConfigKey,
} from '@logto/schemas';
import { convertToIdentifiers } from '@logto/shared';
import { createMockPool, createMockQueryResult, sql } from 'slonik';
import { convertToIdentifiers } from '#src/utils/sql.js';
import { expectSqlAssert, type QueryType } from '#src/utils/test-utils.js';
const { jest } = import.meta;

View file

@ -9,12 +9,12 @@ import {
type OidcConfigKey,
type LogtoJwtTokenKey,
} from '@logto/schemas';
import { convertToIdentifiers } from '@logto/shared';
import type { CommonQueryMethods } from 'slonik';
import { sql } from 'slonik';
import { type z } from 'zod';
import { DeletionError } from '#src/errors/SlonikError/index.js';
import { convertToIdentifiers } from '#src/utils/sql.js';
const { table, fields } = convertToIdentifiers(LogtoConfigs);

View file

@ -1,8 +1,8 @@
import type { CreateOidcModelInstance } from '@logto/schemas';
import { OidcModelInstances } from '@logto/schemas';
import { convertToIdentifiers } from '@logto/shared';
import { createMockPool, createMockQueryResult, sql } from 'slonik';
import { convertToIdentifiers } from '#src/utils/sql.js';
import type { QueryType } from '#src/utils/test-utils.js';
import { expectSqlAssert } from '#src/utils/test-utils.js';

View file

@ -1,6 +1,5 @@
import type { OidcModelInstance, OidcModelInstancePayload } from '@logto/schemas';
import { OidcModelInstances } from '@logto/schemas';
import { convertToIdentifiers, convertToTimestamp } from '@logto/shared';
import type { Nullable } from '@silverhand/essentials';
import { conditional } from '@silverhand/essentials';
import { addSeconds, isBefore } from 'date-fns';
@ -8,6 +7,7 @@ import type { CommonQueryMethods, ValueExpression } from 'slonik';
import { sql } from 'slonik';
import { buildInsertIntoWithPool } from '#src/database/insert-into.js';
import { convertToIdentifiers, convertToTimestamp } from '#src/utils/sql.js';
export type WithConsumed<T> = T & { consumed?: boolean };
export type QueryResult = Pick<OidcModelInstance, 'payload' | 'consumedAt'>;

View file

@ -18,12 +18,12 @@ import {
OrganizationInvitationRoleRelations,
OrganizationInvitationStatus,
} from '@logto/schemas';
import { conditionalSql, convertToIdentifiers } from '@logto/shared';
import { sql, type CommonQueryMethods } from 'slonik';
import { type SearchOptions, buildSearchSql } from '#src/database/utils.js';
import { TwoRelationsQueries } from '#src/utils/RelationQueries.js';
import SchemaQueries from '#src/utils/SchemaQueries.js';
import { conditionalSql, convertToIdentifiers } from '#src/utils/sql.js';
import { RoleUserRelationQueries, UserRelationQueries } from './relations.js';

View file

@ -11,7 +11,6 @@ import {
type FeaturedUser,
type OrganizationScopeEntity,
} from '@logto/schemas';
import { convertToIdentifiers } from '@logto/shared';
import { sql, type CommonQueryMethods } from 'slonik';
import { type SearchOptions, buildSearchSql, expandFields } from '#src/database/utils.js';
@ -19,6 +18,7 @@ import RelationQueries, {
type GetEntitiesOptions,
TwoRelationsQueries,
} from '#src/utils/RelationQueries.js';
import { convertToIdentifiers } from '#src/utils/sql.js';
import { type userSearchKeys } from '../user.js';

View file

@ -1,11 +1,15 @@
import { TemplateType } from '@logto/connector-kit';
import { Passcodes } from '@logto/schemas';
import { convertToIdentifiers, convertToPrimitiveOrSql, excludeAutoSetFields } from '@logto/shared';
import { createMockPool, createMockQueryResult, sql } from 'slonik';
import { snakeCase } from 'snake-case';
import { mockPasscode } from '#src/__mocks__/index.js';
import { DeletionError } from '#src/errors/SlonikError/index.js';
import {
convertToIdentifiers,
convertToPrimitiveOrSql,
excludeAutoSetFields,
} from '#src/utils/sql.js';
import type { QueryType } from '#src/utils/test-utils.js';
import { expectSqlAssert } from '#src/utils/test-utils.js';

View file

@ -1,12 +1,12 @@
import type { TemplateType } from '@logto/connector-kit';
import type { Passcode, RequestVerificationCodePayload } from '@logto/schemas';
import { Passcodes } from '@logto/schemas';
import { conditionalSql, convertToIdentifiers } from '@logto/shared';
import type { CommonQueryMethods } from 'slonik';
import { sql } from 'slonik';
import { buildInsertIntoWithPool } from '#src/database/insert-into.js';
import { DeletionError } from '#src/errors/SlonikError/index.js';
import { conditionalSql, convertToIdentifiers } from '#src/utils/sql.js';
const { table, fields } = convertToIdentifiers(Passcodes);

View file

@ -1,9 +1,9 @@
import { Resources } from '@logto/schemas';
import { convertToIdentifiers, convertToPrimitiveOrSql } from '@logto/shared';
import { createMockPool, createMockQueryResult, sql } from 'slonik';
import { mockResource } from '#src/__mocks__/index.js';
import { DeletionError } from '#src/errors/SlonikError/index.js';
import { convertToIdentifiers, convertToPrimitiveOrSql } from '#src/utils/sql.js';
import type { QueryType } from '#src/utils/test-utils.js';
import { expectSqlAssert } from '#src/utils/test-utils.js';

View file

@ -1,7 +1,5 @@
import type { Resource, CreateResource } from '@logto/schemas';
import { Resources } from '@logto/schemas';
import type { OmitAutoSetFields } from '@logto/shared';
import { convertToIdentifiers } from '@logto/shared';
import type { CommonQueryMethods } from 'slonik';
import { sql } from 'slonik';
@ -11,6 +9,8 @@ import { buildInsertIntoWithPool } from '#src/database/insert-into.js';
import { getTotalRowCountWithPool } from '#src/database/row-count.js';
import { buildUpdateWhereWithPool } from '#src/database/update-where.js';
import { DeletionError, UpdateError } from '#src/errors/SlonikError/index.js';
import type { OmitAutoSetFields } from '#src/utils/sql.js';
import { convertToIdentifiers } from '#src/utils/sql.js';
const { table, fields } = convertToIdentifiers(Resources);

View file

@ -1,10 +1,10 @@
import type { CreateRolesScope, RolesScope } from '@logto/schemas';
import { RolesScopes } from '@logto/schemas';
import { convertToIdentifiers } from '@logto/shared';
import type { CommonQueryMethods } from 'slonik';
import { sql } from 'slonik';
import { DeletionError } from '#src/errors/SlonikError/index.js';
import { convertToIdentifiers } from '#src/utils/sql.js';
const { table, fields } = convertToIdentifiers(RolesScopes);

View file

@ -1,9 +1,13 @@
import { Roles } from '@logto/schemas';
import { convertToIdentifiers, convertToPrimitiveOrSql, excludeAutoSetFields } from '@logto/shared';
import { createMockPool, createMockQueryResult, sql } from 'slonik';
import { mockAdminUserRole } from '#src/__mocks__/index.js';
import { DeletionError } from '#src/errors/SlonikError/index.js';
import {
convertToIdentifiers,
convertToPrimitiveOrSql,
excludeAutoSetFields,
} from '#src/utils/sql.js';
import type { QueryType } from '#src/utils/test-utils.js';
import { expectSqlAssert } from '#src/utils/test-utils.js';

View file

@ -1,7 +1,5 @@
import type { CreateRole, Role, RoleType } from '@logto/schemas';
import { internalRolePrefix, SearchJointMode, Roles } from '@logto/schemas';
import type { OmitAutoSetFields } from '@logto/shared';
import { conditionalArraySql, conditionalSql, convertToIdentifiers } from '@logto/shared';
import type { CommonQueryMethods } from 'slonik';
import { sql } from 'slonik';
@ -11,6 +9,8 @@ import { buildUpdateWhereWithPool } from '#src/database/update-where.js';
import { DeletionError } from '#src/errors/SlonikError/index.js';
import type { Search } from '#src/utils/search.js';
import { buildConditionsFromSearch } from '#src/utils/search.js';
import { conditionalArraySql, conditionalSql, convertToIdentifiers } from '#src/utils/sql.js';
import type { OmitAutoSetFields } from '#src/utils/sql.js';
const { table, fields } = convertToIdentifiers(Roles);

View file

@ -1,7 +1,5 @@
import type { CreateScope, Scope } from '@logto/schemas';
import { Resources, Scopes } from '@logto/schemas';
import type { OmitAutoSetFields } from '@logto/shared';
import { conditionalSql, convertToIdentifiers } from '@logto/shared';
import type { CommonQueryMethods } from 'slonik';
import { sql } from 'slonik';
@ -11,6 +9,8 @@ import { buildUpdateWhereWithPool } from '#src/database/update-where.js';
import { DeletionError } from '#src/errors/SlonikError/index.js';
import type { Search } from '#src/utils/search.js';
import { buildConditionsFromSearch } from '#src/utils/search.js';
import type { OmitAutoSetFields } from '#src/utils/sql.js';
import { conditionalSql, convertToIdentifiers } from '#src/utils/sql.js';
const { table, fields } = convertToIdentifiers(Scopes, true);
const resources = convertToIdentifiers(Resources, true);

View file

@ -4,10 +4,10 @@ import {
type SsoConnectorKeys,
SsoConnectors,
} from '@logto/schemas';
import { convertToIdentifiers } from '@logto/shared';
import { sql, type CommonQueryMethods } from 'slonik';
import SchemaQueries from '#src/utils/SchemaQueries.js';
import { convertToIdentifiers } from '#src/utils/sql.js';
export default class SsoConnectorQueries extends SchemaQueries<
SsoConnectorKeys,

View file

@ -1,8 +1,9 @@
import { type SystemKey, Systems } from '@logto/schemas';
import { convertToIdentifiers } from '@logto/shared';
import type { CommonQueryMethods } from 'slonik';
import { sql } from 'slonik';
import { convertToIdentifiers } from '#src/utils/sql.js';
const { table, fields } = convertToIdentifiers(Systems);
export const createSystemsQuery = (pool: CommonQueryMethods) => {

View file

@ -1,7 +1,8 @@
import { Tenants, type TenantModel } from '@logto/schemas/models';
import { convertToIdentifiers } from '@logto/shared';
import { sql, type CommonQueryMethods } from 'slonik';
import { convertToIdentifiers } from '#src/utils/sql.js';
const createTenantQueries = (pool: CommonQueryMethods) => {
const { table, fields } = convertToIdentifiers({
table: Tenants.tableName,

View file

@ -4,11 +4,11 @@ import {
type UserSsoIdentity,
UserSsoIdentities,
} from '@logto/schemas';
import { manyRows } from '@logto/shared';
import { type Nullable } from '@silverhand/essentials';
import { sql, type CommonQueryMethods } from 'slonik';
import SchemaQueries from '#src/utils/SchemaQueries.js';
import { manyRows } from '#src/utils/sql.js';
export default class UserSsoIdentityQueries extends SchemaQueries<
UserSsoIdentityKeys,

View file

@ -1,11 +1,11 @@
import { Users } from '@logto/schemas';
import { convertToIdentifiers } from '@logto/shared';
import Sinon from 'sinon';
import { createMockPool, createMockQueryResult, sql } from 'slonik';
import { mockUser } from '#src/__mocks__/index.js';
import { EnvSet } from '#src/env-set/index.js';
import { DeletionError } from '#src/errors/SlonikError/index.js';
import { convertToIdentifiers } from '#src/utils/sql.js';
import type { QueryType } from '#src/utils/test-utils.js';
import { expectSqlAssert } from '#src/utils/test-utils.js';

View file

@ -1,7 +1,5 @@
import type { User, CreateUser } from '@logto/schemas';
import { Users } from '@logto/schemas';
import type { OmitAutoSetFields } from '@logto/shared';
import { conditionalSql, convertToIdentifiers } from '@logto/shared';
import { conditionalArray, pick } from '@silverhand/essentials';
import type { CommonQueryMethods } from 'slonik';
import { sql } from 'slonik';
@ -11,6 +9,8 @@ import { EnvSet } from '#src/env-set/index.js';
import { DeletionError } from '#src/errors/SlonikError/index.js';
import type { Search } from '#src/utils/search.js';
import { buildConditionsFromSearch } from '#src/utils/search.js';
import type { OmitAutoSetFields } from '#src/utils/sql.js';
import { conditionalSql, convertToIdentifiers } from '#src/utils/sql.js';
const { table, fields } = convertToIdentifiers(Users);

View file

@ -1,10 +1,10 @@
import type { CreateUsersRole, UsersRole } from '@logto/schemas';
import { UsersRoles } from '@logto/schemas';
import { conditionalSql, convertToIdentifiers } from '@logto/shared';
import type { CommonQueryMethods } from 'slonik';
import { sql } from 'slonik';
import { DeletionError } from '#src/errors/SlonikError/index.js';
import { conditionalSql, convertToIdentifiers } from '#src/utils/sql.js';
const { table, fields } = convertToIdentifiers(UsersRoles);

View file

@ -1,10 +1,10 @@
import type { VerificationStatus } from '@logto/schemas';
import { VerificationStatuses } from '@logto/schemas';
import { convertToIdentifiers } from '@logto/shared';
import type { CommonQueryMethods } from 'slonik';
import { sql } from 'slonik';
import { buildInsertIntoWithPool } from '#src/database/insert-into.js';
import { convertToIdentifiers } from '#src/utils/sql.js';
const { table, fields } = convertToIdentifiers(VerificationStatuses);

View file

@ -1,7 +1,6 @@
import { defaults, parseAffiliateData } from '@logto/affiliate';
import { consoleLog } from '@logto/cli/lib/utils.js';
import { type CreateUser, type User, adminTenantId } from '@logto/schemas';
import { type OmitAutoSetFields } from '@logto/shared';
import { conditional, trySafe } from '@silverhand/essentials';
import { type IRouterContext } from 'koa-router';
@ -11,6 +10,7 @@ import { type ConnectorLibrary } from '#src/libraries/connector.js';
import { encryptUserPassword } from '#src/libraries/user.js';
import type Queries from '#src/tenants/Queries.js';
import type TenantContext from '#src/tenants/TenantContext.js';
import { type OmitAutoSetFields } from '#src/utils/sql.js';
import {
type Identifier,

View file

@ -8,12 +8,13 @@ import {
SentinelActionResult,
SentinelActivityAction,
} from '@logto/schemas';
import { convertToIdentifiers, generateStandardId } from '@logto/shared';
import { generateStandardId } from '@logto/shared';
import { type Nullable } from '@silverhand/essentials';
import { addMinutes } from 'date-fns';
import { sql, type CommonQueryMethods } from 'slonik';
import { buildInsertIntoWithPool } from '#src/database/insert-into.js';
import { convertToIdentifiers } from '#src/utils/sql.js';
const { fields, table } = convertToIdentifiers(SentinelActivities);

View file

@ -1,4 +1,4 @@
import { type Table, conditionalSql } from '@logto/shared';
import { type Table } from '@logto/shared';
import { type KeysToCamelCase } from '@silverhand/essentials';
import { sql, type CommonQueryMethods } from 'slonik';
import snakecaseKeys from 'snakecase-keys';
@ -7,6 +7,8 @@ import { type z } from 'zod';
import { expandFields } from '#src/database/utils.js';
import { DeletionError } from '#src/errors/SlonikError/index.js';
import { conditionalSql } from './sql.js';
type AtLeast2<T extends unknown[]> = `${T['length']}` extends '0' | '1' ? never : T;
type TableInfo<

View file

@ -1,5 +1,5 @@
import { type GeneratedSchema } from '@logto/schemas';
import { type UpdateWhereData, type OmitAutoSetFields, type SchemaLike } from '@logto/shared';
import { type UpdateWhereData, type SchemaLike } from '@logto/shared';
import { type CommonQueryMethods } from 'slonik';
import { buildDeleteByIdWithPool } from '#src/database/delete-by-id.js';
@ -13,6 +13,8 @@ import { buildGetTotalRowCountWithPool } from '#src/database/row-count.js';
import { buildUpdateWhereWithPool } from '#src/database/update-where.js';
import { type SearchOptions } from '#src/database/utils.js';
import { type OmitAutoSetFields } from './sql.js';
/**
* Query class that contains all the necessary CRUD queries for a schema. It is
* designed to be used with a SchemaRouter. You can also extend this class to add

View file

@ -1,3 +1,4 @@
import type { Table } from '@logto/shared';
import { sql } from 'slonik';
import { SqlToken } from 'slonik/dist/src/tokens.js';
@ -9,7 +10,6 @@ import {
convertToTimestamp,
conditionalSql,
} from './sql.js';
import type { Table } from './types.js';
const { jest } = import.meta;

View file

@ -1,12 +1,12 @@
import type { SchemaValue, SchemaValuePrimitive, Table } from '@logto/shared';
import type { Falsy } from '@silverhand/essentials';
import { notFalsy } from '@silverhand/essentials';
import type { SqlSqlToken, SqlToken, QueryResult, IdentifierSqlToken } from 'slonik';
import type { SqlSqlToken, SqlToken, IdentifierSqlToken, QueryResult } from 'slonik';
import { sql } from 'slonik';
import type { FieldIdentifiers, SchemaValue, SchemaValuePrimitive, Table } from './types.js';
export const conditionalSql = <T>(value: T, buildSql: (value: Exclude<T, Falsy>) => SqlSqlToken) =>
notFalsy(value) ? buildSql(value) : sql``;
export const conditionalArraySql = <T>(
value: T[],
buildSql: (value: Exclude<T[], Falsy>) => SqlSqlToken
@ -14,7 +14,8 @@ export const conditionalArraySql = <T>(
export const autoSetFields = Object.freeze(['tenantId', 'createdAt', 'updatedAt'] as const);
export type OmitAutoSetFields<T> = Omit<T, (typeof autoSetFields)[number]>;
export type ExcludeAutoSetFields<T> = Exclude<T, (typeof autoSetFields)[number]>;
type ExcludeAutoSetFields<T> = Exclude<T, (typeof autoSetFields)[number]>;
export const excludeAutoSetFields = <T extends string>(fields: readonly T[]) =>
Object.freeze(
fields.filter(
@ -33,10 +34,10 @@ export const excludeAutoSetFields = <T extends string>(fields: readonly T[]) =>
* @param value The value to convert.
* @returns A primitive that can be saved into database.
*/
export const convertToPrimitiveOrSql = (
key: string,
value: SchemaValue
// eslint-disable-next-line @typescript-eslint/ban-types
): NonNullable<SchemaValuePrimitive> | SqlToken | null => {
if (value === null) {
return null;
@ -68,6 +69,10 @@ export const convertToPrimitiveOrSql = (
throw new Error(`Cannot convert ${key} to primitive`);
};
type FieldIdentifiers<Key extends string> = {
[key in Key]: IdentifierSqlToken;
};
export const convertToIdentifiers = <Key extends string>(
{ table, fields }: Table<Key>,
withPrefix = false

View file

@ -55,7 +55,7 @@
"pluralize": "^8.0.0",
"prettier": "^3.0.0",
"roarr": "^7.11.0",
"slonik": "^30.0.0",
"slonik": "30.4.0",
"slonik-sql-tag-raw": "^1.1.4",
"typescript": "^5.3.3"
},

View file

@ -64,7 +64,6 @@
"chalk": "^5.0.0",
"find-up": "^7.0.0",
"libphonenumber-js": "^1.9.49",
"nanoid": "^5.0.1",
"slonik": "^30.0.0"
"nanoid": "^5.0.1"
}
}

View file

@ -1,5 +1,3 @@
import type { IdentifierSqlToken } from 'slonik';
export type SchemaValuePrimitive = string | number | boolean | undefined;
export type SchemaValue = SchemaValuePrimitive | Record<string, unknown> | unknown[] | null;
export type SchemaLike<Key extends string> = {
@ -10,9 +8,6 @@ export type Table<Keys extends string, TableName extends string = string> = {
table: TableName;
fields: Record<Keys, string>;
};
export type FieldIdentifiers<Key extends string> = {
[key in Key]: IdentifierSqlToken;
};
export type OrderDirection = 'asc' | 'desc';

View file

@ -1,3 +1,2 @@
export * from './universal.js';
export * from './node/index.js';
export * from './database/sql.js';

60
pnpm-lock.yaml generated
View file

@ -170,14 +170,14 @@ importers:
specifier: ^7.3.8
version: 7.5.2
slonik:
specifier: ^30.0.0
version: 30.1.2
specifier: 30.4.0
version: 30.4.0
slonik-interceptor-preset:
specifier: ^1.2.10
version: 1.2.10
slonik-sql-tag-raw:
specifier: ^1.1.4
version: 1.1.4(roarr@7.11.0)(slonik@30.1.2)
version: 1.1.4(roarr@7.11.0)(slonik@30.4.0)
tar:
specifier: ^6.1.11
version: 6.1.11
@ -3390,14 +3390,14 @@ importers:
specifier: ^7.3.8
version: 7.5.2
slonik:
specifier: ^30.0.0
version: 30.1.2
specifier: 30.4.0
version: 30.4.0
slonik-interceptor-preset:
specifier: ^1.2.10
version: 1.2.10
slonik-sql-tag-raw:
specifier: ^1.1.4
version: 1.1.4(roarr@7.11.0)(slonik@30.1.2)
version: 1.1.4(roarr@7.11.0)(slonik@30.4.0)
snake-case:
specifier: ^3.0.4
version: 3.0.4
@ -4052,11 +4052,11 @@ importers:
specifier: ^7.11.0
version: 7.11.0
slonik:
specifier: ^30.0.0
version: 30.1.2
specifier: 30.4.0
version: 30.4.0
slonik-sql-tag-raw:
specifier: ^1.1.4
version: 1.1.4(roarr@7.11.0)(slonik@30.1.2)
version: 1.1.4(roarr@7.11.0)(slonik@30.4.0)
typescript:
specifier: ^5.3.3
version: 5.3.3
@ -4078,9 +4078,6 @@ importers:
nanoid:
specifier: ^5.0.1
version: 5.0.1
slonik:
specifier: ^30.0.0
version: 30.1.2
devDependencies:
'@logto/connector-kit':
specifier: workspace:^2.1.0
@ -18061,17 +18058,25 @@ packages:
obuf: 1.1.2
dev: false
/pg-copy-streams@6.0.2:
resolution: {integrity: sha512-74doDsDUI3ti1IzeieA7c/VsTpZkBdgjMeag3BtJFV+3J0m7Z3UMJB8iQW+zUWHZGVF9d/WIRfledEaPfKcPEA==}
/pg-copy-streams@6.0.6:
resolution: {integrity: sha512-Z+Dd2C2NIDTsjyFKmc6a9QLlpM8tjpERx+43RSx0WmL7j3uNChERi3xSvZUL0hWJ1oRUn4S3fhyt3apdSrTyKQ==}
dependencies:
obuf: 1.1.2
/pg-cursor@2.10.3(pg@8.8.0):
resolution: {integrity: sha512-rDyBVoqPVnx/PTmnwQAYgusSeAKlTL++gmpf5klVK+mYMFEqsOc6VHHZnPKc/4lOvr4r6fiMuoxSFuBF1dx4FQ==}
peerDependencies:
pg: ^8
dependencies:
pg: 8.8.0
/pg-cursor@2.7.3(pg@8.8.0):
resolution: {integrity: sha512-vmjXRMD4jZK/oHaaYk6clTypgHNlzCCAqyLCO5d/UeI42egJVE5H4ZfZWACub3jzkHUXXyvibH207zAJg9iBOw==}
peerDependencies:
pg: ^8
dependencies:
pg: 8.8.0
dev: false
/pg-formatter@1.3.0:
resolution: {integrity: sha512-y1kNdgD+QWzhmYCm91z/k7VGyx6BekQg6ww/krFEEhw1IIB4zEk2xaB0pmueTcc59YFetpiHIKECgHEuw6gyvg==}
@ -19524,6 +19529,14 @@ packages:
globalthis: 1.0.2
semver-compare: 1.0.0
/roarr@7.21.1:
resolution: {integrity: sha512-3niqt5bXFY1InKU8HKWqqYTYjtrBaxBMnXELXCXUYgtNYGUtZM5rB46HIC430AyacL95iEniGf7RgqsesykLmQ==}
engines: {node: '>=18.0'}
dependencies:
fast-printf: 1.6.9
safe-stable-stringify: 2.4.3
semver-compare: 1.0.0
/rollup-plugin-summary@2.0.0(rollup@4.12.0):
resolution: {integrity: sha512-7Av6DQeCmVNpFmCdkkbMya1CneeGWhjSXXQ3B4yDO+BvN/Kbohqi3IEYXAvgHP3iIafSfMyOw+PBLFUlvf1ViA==}
engines: {node: '>=14.0.0'}
@ -19600,6 +19613,10 @@ packages:
regexp-tree: 0.1.24
dev: true
/safe-stable-stringify@2.4.3:
resolution: {integrity: sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==}
engines: {node: '>=10'}
/safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
@ -19863,7 +19880,7 @@ packages:
- pg-native
dev: false
/slonik-sql-tag-raw@1.1.4(roarr@7.11.0)(slonik@30.1.2):
/slonik-sql-tag-raw@1.1.4(roarr@7.11.0)(slonik@30.4.0):
resolution: {integrity: sha512-os6iRAkQgKNoVzudRtLBlxjqmyQHJdPHw/eMIBJDnUfD5dle5uIyEKtblayW7eBr5x7blkzUg4BgvRkeDZeZPA==}
engines: {node: '>=10.0'}
peerDependencies:
@ -19873,7 +19890,7 @@ packages:
lodash: 4.17.21
roarr: 7.11.0
serialize-error: 8.1.0
slonik: 30.1.2
slonik: 30.4.0
/slonik@22.7.1:
resolution: {integrity: sha512-88GidNOWv4Bg0CqYLXajqcD0bbLip2soY6B4JzHP7EGDrWUb1WSlu7mIppTJVfcK99mx+jnX3xQq3FJ0DoOXag==}
@ -19902,8 +19919,8 @@ packages:
- pg-native
dev: false
/slonik@30.1.2:
resolution: {integrity: sha512-vNCZT4eEr3cKnm83LF8QOCTfm3TH/XSQdMnG4X3A+V1PVJFG3JKjRMB8jwin/3eYeM6nVCSXeZqlPGlHHXrgBQ==}
/slonik@30.4.0:
resolution: {integrity: sha512-1C88SJFBlhQ1bm1H2O2nAktvW1t2tVdpLLZBr86gPxre9LvLIh8Xvkoq0s3aJ0p7zV466TIbRuhI/fq02NP36A==}
engines: {node: '>=10.0'}
dependencies:
concat-stream: 2.0.0
@ -19915,16 +19932,17 @@ packages:
iso8601-duration: 1.3.0
p-defer: 3.0.0
pg: 8.8.0
pg-copy-streams: 6.0.2
pg-copy-streams: 6.0.6
pg-copy-streams-binary: 2.2.0
pg-cursor: 2.7.3(pg@8.8.0)
pg-cursor: 2.10.3(pg@8.8.0)
pg-protocol: 1.6.0
pg-types: 4.0.0
postgres-array: 3.0.1
postgres-interval: 4.0.0
roarr: 7.11.0
roarr: 7.21.1
serialize-error: 8.1.0
through2: 4.0.2
zod: 3.22.4
transitivePeerDependencies:
- pg-native