From dff23b57db0507c403379464d55b510e63c6ba49 Mon Sep 17 00:00:00 2001 From: Gao Sun Date: Tue, 19 Apr 2022 21:49:20 +0800 Subject: [PATCH] refactor(core): move database pool into env set --- packages/core/jest.config.js | 4 +- ...t.global-setup.js => jest.global-setup.ts} | 14 ++-- packages/core/jest.setup.js | 12 ---- packages/core/jest.setup.ts | 15 +++++ .../core/src/database/insert-into.test.ts | 17 +++-- packages/core/src/database/insert-into.ts | 8 +-- packages/core/src/database/pool.ts | 10 --- .../core/src/database/update-where.test.ts | 24 +++++-- packages/core/src/database/update-where.ts | 15 ++--- packages/core/src/database/utils.ts | 5 +- packages/core/src/env-set/index.ts | 45 ++++++++++--- packages/core/src/index.ts | 1 + packages/core/src/middleware/koa-auth.test.ts | 18 ++--- .../core/src/middleware/koa-spa-proxy.test.ts | 28 +++++--- packages/core/src/queries/application.test.ts | 3 +- packages/core/src/queries/application.ts | 24 +++---- packages/core/src/queries/connector.test.ts | 3 +- packages/core/src/queries/connector.ts | 10 +-- .../src/queries/oidc-model-instance.test.ts | 3 +- .../core/src/queries/oidc-model-instance.ts | 14 ++-- packages/core/src/queries/passcode.test.ts | 3 +- packages/core/src/queries/passcode.ts | 14 ++-- packages/core/src/queries/resource.test.ts | 3 +- packages/core/src/queries/resource.ts | 14 ++-- packages/core/src/queries/roles.test.ts | 3 +- packages/core/src/queries/roles.ts | 6 +- packages/core/src/queries/setting.test.ts | 3 +- packages/core/src/queries/setting.ts | 5 +- .../src/queries/sign-in-experience.test.ts | 3 +- .../core/src/queries/sign-in-experience.ts | 5 +- packages/core/src/queries/user-log.test.ts | 67 +++++++++++++++++++ packages/core/src/queries/user-log.ts | 18 +++++ packages/core/src/queries/user.test.ts | 3 +- packages/core/src/queries/user.ts | 38 ++++++----- packages/core/tsconfig.json | 3 +- 35 files changed, 293 insertions(+), 168 deletions(-) rename packages/core/{jest.global-setup.js => jest.global-setup.ts} (50%) delete mode 100644 packages/core/jest.setup.js create mode 100644 packages/core/jest.setup.ts delete mode 100644 packages/core/src/database/pool.ts create mode 100644 packages/core/src/queries/user-log.test.ts create mode 100644 packages/core/src/queries/user-log.ts diff --git a/packages/core/jest.config.js b/packages/core/jest.config.js index b156e8163..a91ec2d46 100644 --- a/packages/core/jest.config.js +++ b/packages/core/jest.config.js @@ -2,8 +2,8 @@ module.exports = { preset: 'ts-jest', testEnvironment: 'node', - setupFilesAfterEnv: ['./jest.setup.js', 'jest-matcher-specific-error'], - globalSetup: './jest.global-setup.js', + setupFilesAfterEnv: ['./jest.setup.ts', 'jest-matcher-specific-error'], + globalSetup: './jest.global-setup.ts', globals: { 'ts-jest': { tsconfig: 'tsconfig.test.json', diff --git a/packages/core/jest.global-setup.js b/packages/core/jest.global-setup.ts similarity index 50% rename from packages/core/jest.global-setup.js rename to packages/core/jest.global-setup.ts index c61d467f0..ded7947fe 100644 --- a/packages/core/jest.global-setup.js +++ b/packages/core/jest.global-setup.ts @@ -1,13 +1,12 @@ -/* eslint-disable unicorn/prefer-module */ /** * Generate private key for tests */ -const { generateKeyPairSync } = require('crypto'); -const { writeFileSync } = require('fs'); +import { generateKeyPairSync } from 'crypto'; +import { writeFileSync } from 'fs'; -const privateKeyPath = 'oidc-private-key.test.pem'; +export const privateKeyPath = 'oidc-private-key.test.pem'; -module.exports = () => { +const globalSetup = () => { const { privateKey } = generateKeyPairSync('rsa', { modulusLength: 4096, publicKeyEncoding: { @@ -23,7 +22,4 @@ module.exports = () => { writeFileSync(privateKeyPath, privateKey); }; -exports = module.exports; -exports.privateKeyPath = privateKeyPath; - -/* eslint-enable unicorn/prefer-module */ +export default globalSetup; diff --git a/packages/core/jest.setup.js b/packages/core/jest.setup.js deleted file mode 100644 index d9734d8ad..000000000 --- a/packages/core/jest.setup.js +++ /dev/null @@ -1,12 +0,0 @@ -/* eslint-disable unicorn/prefer-module */ -/** - * Setup environment variables for unit test - */ - -const { privateKeyPath } = require('./jest.global-setup.js'); - -process.env = { - ...process.env, - OIDC_PRIVATE_KEY_PATH: privateKeyPath, -}; -/* eslint-enable unicorn/prefer-module */ diff --git a/packages/core/jest.setup.ts b/packages/core/jest.setup.ts new file mode 100644 index 000000000..bc69e6935 --- /dev/null +++ b/packages/core/jest.setup.ts @@ -0,0 +1,15 @@ +/** + * Setup environment variables for unit test + */ + +import envSet from '@/env-set'; + +import { privateKeyPath } from './jest.global-setup'; + +(async () => { + process.env = { + ...process.env, + OIDC_PRIVATE_KEY_PATH: privateKeyPath, + }; + await envSet.load(); +})(); diff --git a/packages/core/src/database/insert-into.test.ts b/packages/core/src/database/insert-into.test.ts index ec16b7d99..2fc6295f6 100644 --- a/packages/core/src/database/insert-into.test.ts +++ b/packages/core/src/database/insert-into.test.ts @@ -1,6 +1,7 @@ import { CreateUser, Users } from '@logto/schemas'; import decamelize from 'decamelize'; +import envSet from '@/env-set'; import { InsertionError } from '@/errors/SlonikError'; import { createTestPool } from '@/utils/test-utils'; @@ -18,7 +19,9 @@ describe('buildInsertInto()', () => { const user: CreateUser = { id: 'foo', username: '456' }; const expectInsertIntoSql = buildExpectedInsertIntoSql(Object.keys(user)); const pool = createTestPool(expectInsertIntoSql.join('\n')); - const insertInto = buildInsertInto(pool, Users); + jest.spyOn(envSet, 'pool', 'get').mockReturnValue(pool); + + const insertInto = buildInsertInto(Users); await expect(insertInto(user)).resolves.toBe(undefined); }); @@ -32,8 +35,10 @@ describe('buildInsertInto()', () => { 'set "primary_email"=excluded."primary_email"', ].join('\n') ); + jest.spyOn(envSet, 'pool', 'get').mockReturnValue(pool); + const { fields } = convertToIdentifiers(Users); - const insertInto = buildInsertInto(pool, Users, { + const insertInto = buildInsertInto(Users, { onConflict: { fields: [fields.id, fields.username], setExcludedFields: [fields.primaryEmail], @@ -53,7 +58,9 @@ describe('buildInsertInto()', () => { primaryEmail: String(primaryEmail), }) ); - const insertInto = buildInsertInto(pool, Users, { returning: true }); + jest.spyOn(envSet, 'pool', 'get').mockReturnValue(pool); + + const insertInto = buildInsertInto(Users, { returning: true }); await expect( insertInto({ id: 'foo', username: '123', primaryEmail: 'foo@bar.com' }) ).resolves.toStrictEqual(user); @@ -63,7 +70,9 @@ describe('buildInsertInto()', () => { const user: CreateUser = { id: 'foo', username: '123', primaryEmail: 'foo@bar.com' }; const expectInsertIntoSql = buildExpectedInsertIntoSql(Object.keys(user)); const pool = createTestPool([...expectInsertIntoSql, 'returning *'].join('\n')); - const insertInto = buildInsertInto(pool, Users, { returning: true }); + jest.spyOn(envSet, 'pool', 'get').mockReturnValue(pool); + + const insertInto = buildInsertInto(Users, { returning: true }); const dataToInsert = { id: 'foo', username: '123', primaryEmail: 'foo@bar.com' }; await expect(insertInto(dataToInsert)).rejects.toMatchError( diff --git a/packages/core/src/database/insert-into.ts b/packages/core/src/database/insert-into.ts index 873acb566..57f6025f5 100644 --- a/packages/core/src/database/insert-into.ts +++ b/packages/core/src/database/insert-into.ts @@ -1,7 +1,8 @@ import { SchemaLike, GeneratedSchema } from '@logto/schemas'; import { has } from '@silverhand/essentials'; -import { DatabasePoolType, IdentifierSqlTokenType, sql } from 'slonik'; +import { IdentifierSqlTokenType, sql } from 'slonik'; +import envSet from '@/env-set'; import { InsertionError } from '@/errors/SlonikError'; import assertThat from '@/utils/assert-that'; @@ -36,12 +37,10 @@ type InsertIntoConfig = { interface BuildInsertInto { ( - pool: DatabasePoolType, { fieldKeys, ...rest }: GeneratedSchema, config: InsertIntoConfigReturning ): (data: OmitAutoSetFields) => Promise; ( - pool: DatabasePoolType, { fieldKeys, ...rest }: GeneratedSchema, config?: InsertIntoConfig ): (data: OmitAutoSetFields) => Promise; @@ -51,7 +50,6 @@ export const buildInsertInto: BuildInsertInto = < Schema extends SchemaLike, ReturnType extends SchemaLike >( - pool: DatabasePoolType, schema: GeneratedSchema, config?: InsertIntoConfig | InsertIntoConfigReturning ) => { @@ -65,7 +63,7 @@ export const buildInsertInto: BuildInsertInto = < const insertingKeys = keys.filter((key) => has(data, key)); const { rows: [entry], - } = await pool.query(sql` + } = await envSet.pool.query(sql` insert into ${table} (${sql.join( insertingKeys.map((key) => fields[key]), sql`, ` diff --git a/packages/core/src/database/pool.ts b/packages/core/src/database/pool.ts deleted file mode 100644 index ff6103542..000000000 --- a/packages/core/src/database/pool.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { createPool } from 'slonik'; -import { createInterceptors } from 'slonik-interceptor-preset'; - -import envSet from '@/env-set'; - -const interceptors = [...createInterceptors()]; - -const pool = createPool(envSet.values.dbUrl, { interceptors }); - -export default pool; diff --git a/packages/core/src/database/update-where.test.ts b/packages/core/src/database/update-where.test.ts index d16e04e72..2a610374e 100644 --- a/packages/core/src/database/update-where.test.ts +++ b/packages/core/src/database/update-where.test.ts @@ -1,5 +1,6 @@ import { CreateUser, Users, Applications } from '@logto/schemas'; +import envSet from '@/env-set'; import { UpdateError } from '@/errors/SlonikError'; import { createTestPool } from '@/utils/test-utils'; @@ -10,7 +11,9 @@ describe('buildUpdateWhere()', () => { const pool = createTestPool( 'update "users"\nset "username"=$1\nwhere "id"=$2 and "username"=$3' ); - const updateWhere = buildUpdateWhere(pool, Users); + jest.spyOn(envSet, 'pool', 'get').mockReturnValue(pool); + + const updateWhere = buildUpdateWhere(Users); await expect( updateWhere({ set: { username: '123' }, @@ -29,7 +32,9 @@ describe('buildUpdateWhere()', () => { primaryEmail: String(primaryEmail), }) ); - const updateWhere = buildUpdateWhere(pool, Users, true); + jest.spyOn(envSet, 'pool', 'get').mockReturnValue(pool); + + const updateWhere = buildUpdateWhere(Users, true); await expect( updateWhere({ set: { username: '123', primaryEmail: 'foo@bar.com' }, where: { id: 'foo' } }) ).resolves.toStrictEqual(user); @@ -43,8 +48,9 @@ describe('buildUpdateWhere()', () => { customClientMetadata: String(customClientMetadata), }) ); - const updateWhere = buildUpdateWhere(pool, Applications, true); + jest.spyOn(envSet, 'pool', 'get').mockReturnValue(pool); + const updateWhere = buildUpdateWhere(Applications, true); await expect( updateWhere({ set: { customClientMetadata: { idTokenTtl: 3600 } }, @@ -57,7 +63,9 @@ describe('buildUpdateWhere()', () => { const pool = createTestPool( 'update "users"\nset "username"=$1\nwhere "id"=$2 and "username"=$3' ); - const updateWhere = buildUpdateWhere(pool, Users); + jest.spyOn(envSet, 'pool', 'get').mockReturnValue(pool); + + const updateWhere = buildUpdateWhere(Users); await expect( updateWhere({ @@ -69,7 +77,9 @@ describe('buildUpdateWhere()', () => { it('throws `entity.not_exists_with_id` error with `undefined` when `returning` is true', async () => { const pool = createTestPool('update "users"\nset "username"=$1\nwhere "id"=$2\nreturning *'); - const updateWhere = buildUpdateWhere(pool, Users, true); + jest.spyOn(envSet, 'pool', 'get').mockReturnValue(pool); + + const updateWhere = buildUpdateWhere(Users, true); const updateWhereData = { set: { username: '123' }, where: { id: 'foo' } }; await expect(updateWhere(updateWhereData)).rejects.toMatchError( @@ -81,7 +91,9 @@ describe('buildUpdateWhere()', () => { const pool = createTestPool( 'update "users"\nset "username"=$1\nwhere "username"=$2\nreturning *' ); - const updateWhere = buildUpdateWhere(pool, Users, true); + jest.spyOn(envSet, 'pool', 'get').mockReturnValue(pool); + + const updateWhere = buildUpdateWhere(Users, true); const updateData = { set: { username: '123' }, where: { username: 'foo' } }; await expect(updateWhere(updateData)).rejects.toMatchError(new UpdateError(Users, updateData)); diff --git a/packages/core/src/database/update-where.ts b/packages/core/src/database/update-where.ts index 3fa90da52..aff68d071 100644 --- a/packages/core/src/database/update-where.ts +++ b/packages/core/src/database/update-where.ts @@ -1,7 +1,8 @@ import { SchemaLike, GeneratedSchema } from '@logto/schemas'; import { notFalsy, Truthy } from '@silverhand/essentials'; -import { DatabasePoolType, sql } from 'slonik'; +import { sql } from 'slonik'; +import envSet from '@/env-set'; import { UpdateError } from '@/errors/SlonikError'; import assertThat from '@/utils/assert-that'; import { isKeyOf } from '@/utils/schema'; @@ -11,22 +12,18 @@ import { conditionalSql, convertToIdentifiers, convertToPrimitiveOrSql } from '. interface BuildUpdateWhere { ( - pool: DatabasePoolType, schema: GeneratedSchema, returning: true ): (data: UpdateWhereData) => Promise; - ( - pool: DatabasePoolType, - schema: GeneratedSchema, - returning?: false - ): (data: UpdateWhereData) => Promise; + (schema: GeneratedSchema, returning?: false): ( + data: UpdateWhereData + ) => Promise; } export const buildUpdateWhere: BuildUpdateWhere = < Schema extends SchemaLike, ReturnType extends SchemaLike >( - pool: DatabasePoolType, schema: GeneratedSchema, returning = false ) => { @@ -58,7 +55,7 @@ export const buildUpdateWhere: BuildUpdateWhere = < return async ({ set, where }: UpdateWhereData) => { const { rows: [data], - } = await pool.query(sql` + } = await envSet.pool.query(sql` update ${table} set ${sql.join(connectKeyValueWithEqualSign(set), sql`, `)} where ${sql.join(connectKeyValueWithEqualSign(where), sql` and `)} diff --git a/packages/core/src/database/utils.ts b/packages/core/src/database/utils.ts index c92fb452f..af836cf32 100644 --- a/packages/core/src/database/utils.ts +++ b/packages/core/src/database/utils.ts @@ -3,7 +3,8 @@ import { Falsy, notFalsy } from '@silverhand/essentials'; import dayjs from 'dayjs'; import { sql, SqlSqlTokenType, SqlTokenType, IdentifierSqlTokenType } from 'slonik'; -import pool from './pool'; +import envSet from '@/env-set'; + import { FieldIdentifiers, Table } from './types'; export const conditionalSql = ( @@ -73,7 +74,7 @@ export const convertToIdentifiers = ( export const convertToTimestamp = (time = dayjs()) => sql`to_timestamp(${time.valueOf() / 1000})`; export const getTotalRowCount = async (table: IdentifierSqlTokenType) => - pool.one<{ count: number }>(sql` + envSet.pool.one<{ count: number }>(sql` select count(*) from ${table} `); diff --git a/packages/core/src/env-set/index.ts b/packages/core/src/env-set/index.ts index 34557b67c..a36a91281 100644 --- a/packages/core/src/env-set/index.ts +++ b/packages/core/src/env-set/index.ts @@ -3,6 +3,8 @@ import { readFileSync } from 'fs'; import { assertEnv, getEnv, Optional } from '@silverhand/essentials'; import { nanoid } from 'nanoid'; +import { createPool, DatabasePoolType } from 'slonik'; +import { createInterceptors } from 'slonik-interceptor-preset'; import { string, number } from 'zod'; export enum MountedApps { @@ -33,15 +35,16 @@ const loadOidcValues = (port: number) => { }; }; -const loadEnvValues = () => { +const loadEnvValues = async () => { const isProduction = getEnv('NODE_ENV') === 'production'; const isTest = getEnv('NODE_ENV') === 'test'; const port = Number(getEnv('PORT', '3001')); + const databaseUrl = isTest ? getEnv('DB_URL') : assertEnv('DB_URL'); return Object.freeze({ isTest, isProduction, - dbUrl: isTest ? getEnv('DB_URL') : assertEnv('DB_URL'), + databaseUrl, httpsCert: process.env.HTTPS_CERT, httpsKey: process.env.HTTPS_KEY, port, @@ -57,18 +60,44 @@ const loadEnvValues = () => { }); }; +const throwNotLoadedError = () => { + throw new Error( + 'Env set is not loaded. Make sure to call `await envSet.load()` before using it.' + ); +}; + +/* eslint-disable @silverhand/fp/no-let, @silverhand/fp/no-mutation */ function createEnvSet() { - // eslint-disable-next-line @silverhand/fp/no-let - let values = loadEnvValues(); + let values: Optional>>; + let pool: Optional; return { - values, - reload: () => { - // eslint-disable-next-line @silverhand/fp/no-mutation - values = loadEnvValues(); + get values() { + if (!values) { + return throwNotLoadedError(); + } + + return values; + }, + get pool() { + if (!pool) { + return throwNotLoadedError(); + } + + return pool; + }, + + load: async () => { + values = await loadEnvValues(); + + if (!values.isTest) { + const interceptors = [...createInterceptors()]; + pool = createPool(values.databaseUrl, { interceptors }); + } }, }; } +/* eslint-enable @silverhand/fp/no-let, @silverhand/fp/no-mutation */ const envSet = createEnvSet(); diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index d7cac4049..7bcc230bb 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -14,6 +14,7 @@ import initI18n from './i18n/init'; (async () => { try { + await envSet.load(); const app = new Koa({ proxy: envSet.values.trustingTlsOffloadingProxies, }); diff --git a/packages/core/src/middleware/koa-auth.test.ts b/packages/core/src/middleware/koa-auth.test.ts index d5c43f2d4..c667225fa 100644 --- a/packages/core/src/middleware/koa-auth.test.ts +++ b/packages/core/src/middleware/koa-auth.test.ts @@ -2,6 +2,7 @@ import { jwtVerify } from 'jose/jwt/verify'; import { Context } from 'koa'; import { IRouterParamContext } from 'koa-router'; +import envSet from '@/env-set'; import RequestError from '@/errors/RequestError'; import { createContextWithRouteParameters } from '@/utils/test-utils'; @@ -30,19 +31,14 @@ describe('koaAuth middleware', () => { }); it('should read DEVELOPMENT_USER_ID from env variable first if not production', async () => { - // Mock the @/env/consts - process.env.DEVELOPMENT_USER_ID = 'foo'; + const spy = jest + .spyOn(envSet, 'values', 'get') + .mockReturnValue({ ...envSet.values, developmentUserId: 'foo' }); - /* eslint-disable @typescript-eslint/no-require-imports */ - /* eslint-disable @typescript-eslint/no-var-requires */ - /* eslint-disable unicorn/prefer-module */ - const koaAuthModule = require('./koa-auth') as { default: typeof koaAuth }; - /* eslint-enable @typescript-eslint/no-require-imports */ - /* eslint-enable @typescript-eslint/no-var-requires */ - /* eslint-enable unicorn/prefer-module */ - - await koaAuthModule.default()(ctx, next); + await koaAuth()(ctx, next); expect(ctx.auth).toEqual('foo'); + + spy.mockRestore(); }); it('should set user auth with given sub returned from accessToken', async () => { diff --git a/packages/core/src/middleware/koa-spa-proxy.test.ts b/packages/core/src/middleware/koa-spa-proxy.test.ts index 8e35fb4cb..5ab3ddafb 100644 --- a/packages/core/src/middleware/koa-spa-proxy.test.ts +++ b/packages/core/src/middleware/koa-spa-proxy.test.ts @@ -1,4 +1,4 @@ -import { MountedApps } from '@/env-set'; +import envSet, { MountedApps } from '@/env-set'; import { createContextWithRouteParameters } from '@/utils/test-utils'; import koaSpaProxy from './koa-spa-proxy'; @@ -48,32 +48,38 @@ describe('koaSpaProxy middleware', () => { }); it('production env should overwrite the request path to root if no target ui file are detected', async () => { - process.env.NODE_ENV = 'production'; - process.env.PASSWORD_PEPPERS = JSON.stringify(['foo']); - process.env.DB_URL = 'some_db_url'; + const spy = jest.spyOn(envSet, 'values', 'get').mockReturnValue({ + ...envSet.values, + isProduction: true, + passwordPeppers: ['foo'], + databaseUrl: 'some_db_url', + }); const ctx = createContextWithRouteParameters({ url: '/foo', }); - const { default: proxy } = await import('./koa-spa-proxy'); - await proxy()(ctx, next); + await koaSpaProxy()(ctx, next); expect(mockStaticMiddleware).toBeCalled(); expect(ctx.request.path).toEqual('/'); + spy.mockRestore(); }); it('production env should call the static middleware if path hit the ui file directory', async () => { - process.env.NODE_ENV = 'production'; - process.env.PASSWORD_PEPPERS = JSON.stringify(['foo']); - process.env.DB_URL = 'some_db_url'; + const spy = jest.spyOn(envSet, 'values', 'get').mockReturnValue({ + ...envSet.values, + isProduction: true, + passwordPeppers: ['foo'], + databaseUrl: 'some_db_url', + }); - const { default: proxy } = await import('./koa-spa-proxy'); const ctx = createContextWithRouteParameters({ url: '/sign-in', }); - await proxy()(ctx, next); + await koaSpaProxy()(ctx, next); expect(mockStaticMiddleware).toBeCalled(); + spy.mockRestore(); }); }); diff --git a/packages/core/src/queries/application.test.ts b/packages/core/src/queries/application.test.ts index a141ba3ef..2c1e954ae 100644 --- a/packages/core/src/queries/application.test.ts +++ b/packages/core/src/queries/application.test.ts @@ -8,6 +8,7 @@ import { convertToPrimitiveOrSql, excludeAutoSetFields, } from '@/database/utils'; +import envSet from '@/env-set'; import { DeletionError } from '@/errors/SlonikError'; import { expectSqlAssert, QueryType } from '@/utils/test-utils'; @@ -22,7 +23,7 @@ import { const mockQuery: jest.MockedFunction = jest.fn(); -jest.mock('@/database/pool', () => +jest.spyOn(envSet, 'pool', 'get').mockReturnValue( createMockPool({ query: async (sql, values) => { return mockQuery(sql, values); diff --git a/packages/core/src/queries/application.ts b/packages/core/src/queries/application.ts index c9379ddee..4e1e8f349 100644 --- a/packages/core/src/queries/application.ts +++ b/packages/core/src/queries/application.ts @@ -2,7 +2,6 @@ import { Application, CreateApplication, Applications } from '@logto/schemas'; import { sql } from 'slonik'; import { buildInsertInto } from '@/database/insert-into'; -import pool from '@/database/pool'; import { buildUpdateWhere } from '@/database/update-where'; import { convertToIdentifiers, @@ -10,6 +9,7 @@ import { getTotalRowCount, conditionalSql, } from '@/database/utils'; +import envSet from '@/env-set'; import { DeletionError } from '@/errors/SlonikError'; const { table, fields } = convertToIdentifiers(Applications); @@ -17,7 +17,7 @@ const { table, fields } = convertToIdentifiers(Applications); export const findTotalNumberOfApplications = async () => getTotalRowCount(table); export const findAllApplications = async (limit: number, offset: number) => - pool.many(sql` + envSet.pool.many(sql` select ${sql.join(Object.values(fields), sql`, `)} from ${table} order by ${fields.createdAt} desc @@ -26,25 +26,17 @@ export const findAllApplications = async (limit: number, offset: number) => `); export const findApplicationById = async (id: string) => - pool.one(sql` + envSet.pool.one(sql` select ${sql.join(Object.values(fields), sql`, `)} from ${table} where ${fields.id}=${id} `); -export const insertApplication = buildInsertInto( - pool, - Applications, - { - returning: true, - } -); +export const insertApplication = buildInsertInto(Applications, { + returning: true, +}); -const updateApplication = buildUpdateWhere( - pool, - Applications, - true -); +const updateApplication = buildUpdateWhere(Applications, true); export const updateApplicationById = async ( id: string, @@ -52,7 +44,7 @@ export const updateApplicationById = async ( ) => updateApplication({ set, where: { id } }); export const deleteApplicationById = async (id: string) => { - const { rowCount } = await pool.query(sql` + const { rowCount } = await envSet.pool.query(sql` delete from ${table} where ${fields.id}=${id} `); diff --git a/packages/core/src/queries/connector.test.ts b/packages/core/src/queries/connector.test.ts index ef354af51..8d2e729f7 100644 --- a/packages/core/src/queries/connector.test.ts +++ b/packages/core/src/queries/connector.test.ts @@ -2,6 +2,7 @@ import { Connectors, ConnectorType, CreateConnector } from '@logto/schemas'; import { createMockPool, createMockQueryResult, sql, QueryResultRowType } from 'slonik'; import { convertToIdentifiers } from '@/database/utils'; +import envSet from '@/env-set'; import { expectSqlAssert, QueryType } from '@/utils/test-utils'; import { @@ -13,7 +14,7 @@ import { const mockQuery: jest.MockedFunction = jest.fn(); -jest.mock('@/database/pool', () => +jest.spyOn(envSet, 'pool', 'get').mockReturnValue( createMockPool({ query: async (sql, values) => { return mockQuery(sql, values); diff --git a/packages/core/src/queries/connector.ts b/packages/core/src/queries/connector.ts index e0e3e6cc6..9265fa63b 100644 --- a/packages/core/src/queries/connector.ts +++ b/packages/core/src/queries/connector.ts @@ -2,28 +2,28 @@ import { Connector, CreateConnector, Connectors } from '@logto/schemas'; import { sql } from 'slonik'; import { buildInsertInto } from '@/database/insert-into'; -import pool from '@/database/pool'; import { buildUpdateWhere } from '@/database/update-where'; import { convertToIdentifiers } from '@/database/utils'; +import envSet from '@/env-set'; const { table, fields } = convertToIdentifiers(Connectors); export const findAllConnectors = async () => - pool.many(sql` + envSet.pool.many(sql` select ${sql.join(Object.values(fields), sql`, `)} from ${table} order by ${fields.enabled} desc, ${fields.id} asc `); export const findConnectorById = async (id: string) => - pool.one(sql` + envSet.pool.one(sql` select ${sql.join(Object.values(fields), sql`, `)} from ${table} where ${fields.id}=${id} `); -export const insertConnector = buildInsertInto(pool, Connectors, { +export const insertConnector = buildInsertInto(Connectors, { returning: true, }); -export const updateConnector = buildUpdateWhere(pool, Connectors, true); +export const updateConnector = buildUpdateWhere(Connectors, true); diff --git a/packages/core/src/queries/oidc-model-instance.test.ts b/packages/core/src/queries/oidc-model-instance.test.ts index a876ec3ba..016dc3f50 100644 --- a/packages/core/src/queries/oidc-model-instance.test.ts +++ b/packages/core/src/queries/oidc-model-instance.test.ts @@ -2,6 +2,7 @@ import { OidcModelInstances, CreateOidcModelInstance } from '@logto/schemas'; import { createMockPool, createMockQueryResult, sql } from 'slonik'; import { convertToIdentifiers } from '@/database/utils'; +import envSet from '@/env-set'; import { expectSqlAssert, QueryType } from '@/utils/test-utils'; import { @@ -15,7 +16,7 @@ import { const mockQuery: jest.MockedFunction = jest.fn(); -jest.mock('@/database/pool', () => +jest.spyOn(envSet, 'pool', 'get').mockReturnValue( createMockPool({ query: async (sql, values) => { return mockQuery(sql, values); diff --git a/packages/core/src/queries/oidc-model-instance.ts b/packages/core/src/queries/oidc-model-instance.ts index 95120eaa9..60544a648 100644 --- a/packages/core/src/queries/oidc-model-instance.ts +++ b/packages/core/src/queries/oidc-model-instance.ts @@ -8,8 +8,8 @@ import { conditional } from '@silverhand/essentials'; import { sql, ValueExpressionType } from 'slonik'; import { buildInsertInto } from '@/database/insert-into'; -import pool from '@/database/pool'; import { convertToIdentifiers, convertToTimestamp } from '@/database/utils'; +import envSet from '@/env-set'; export type WithConsumed = T & { consumed?: boolean }; export type QueryResult = Pick; @@ -26,7 +26,7 @@ const withConsumed = (data: T, consumedAt?: number | null): WithConsumed = const convertResult = (result: QueryResult | null) => conditional(result && withConsumed(result.payload, result.consumedAt)); -export const upsertInstance = buildInsertInto(pool, OidcModelInstances, { +export const upsertInstance = buildInsertInto(OidcModelInstances, { onConflict: { fields: [fields.modelName, fields.id], setExcludedFields: [fields.payload, fields.expiresAt], @@ -40,7 +40,7 @@ const findByModel = (modelName: string) => sql` `; export const findPayloadById = async (modelName: string, id: string) => { - const result = await pool.maybeOne(sql` + const result = await envSet.pool.maybeOne(sql` ${findByModel(modelName)} and ${fields.id}=${id} `); @@ -56,7 +56,7 @@ export const findPayloadByPayloadField = async < field: Field, value: T ) => { - const result = await pool.maybeOne(sql` + const result = await envSet.pool.maybeOne(sql` ${findByModel(modelName)} and ${fields.payload}->>${field}=${value} `); @@ -65,7 +65,7 @@ export const findPayloadByPayloadField = async < }; export const consumeInstanceById = async (modelName: string, id: string) => { - await pool.query(sql` + await envSet.pool.query(sql` update ${table} set ${fields.consumedAt}=${convertToTimestamp()} where ${fields.modelName}=${modelName} @@ -74,7 +74,7 @@ export const consumeInstanceById = async (modelName: string, id: string) => { }; export const destroyInstanceById = async (modelName: string, id: string) => { - await pool.query(sql` + await envSet.pool.query(sql` delete from ${table} where ${fields.modelName}=${modelName} and ${fields.id}=${id} @@ -82,7 +82,7 @@ export const destroyInstanceById = async (modelName: string, id: string) => { }; export const revokeInstanceByGrantId = async (modelName: string, grantId: string) => { - await pool.query(sql` + await envSet.pool.query(sql` delete from ${table} where ${fields.modelName}=${modelName} and ${fields.payload}->>'grantId'=${grantId} diff --git a/packages/core/src/queries/passcode.test.ts b/packages/core/src/queries/passcode.test.ts index 065192a26..9a232f74d 100644 --- a/packages/core/src/queries/passcode.test.ts +++ b/packages/core/src/queries/passcode.test.ts @@ -8,6 +8,7 @@ import { convertToPrimitiveOrSql, excludeAutoSetFields, } from '@/database/utils'; +import envSet from '@/env-set'; import { DeletionError } from '@/errors/SlonikError'; import { expectSqlAssert, QueryType } from '@/utils/test-utils'; @@ -22,7 +23,7 @@ import { const mockQuery: jest.MockedFunction = jest.fn(); -jest.mock('@/database/pool', () => +jest.spyOn(envSet, 'pool', 'get').mockReturnValue( createMockPool({ query: async (sql, values) => { return mockQuery(sql, values); diff --git a/packages/core/src/queries/passcode.ts b/packages/core/src/queries/passcode.ts index 5244e003d..e4c7479c1 100644 --- a/packages/core/src/queries/passcode.ts +++ b/packages/core/src/queries/passcode.ts @@ -2,35 +2,35 @@ import { PasscodeType, Passcode, Passcodes, CreatePasscode } from '@logto/schema import { sql } from 'slonik'; import { buildInsertInto } from '@/database/insert-into'; -import pool from '@/database/pool'; import { buildUpdateWhere } from '@/database/update-where'; import { convertToIdentifiers } from '@/database/utils'; +import envSet from '@/env-set'; import { DeletionError } from '@/errors/SlonikError'; const { table, fields } = convertToIdentifiers(Passcodes); export const findUnconsumedPasscodeByJtiAndType = async (jti: string, type: PasscodeType) => - pool.maybeOne(sql` + envSet.pool.maybeOne(sql` select ${sql.join(Object.values(fields), sql`, `)} from ${table} where ${fields.interactionJti}=${jti} and ${fields.type}=${type} and ${fields.consumed} = false `); export const findUnconsumedPasscodesByJtiAndType = async (jti: string, type: PasscodeType) => - pool.any(sql` + envSet.pool.any(sql` select ${sql.join(Object.values(fields), sql`, `)} from ${table} where ${fields.interactionJti}=${jti} and ${fields.type}=${type} and ${fields.consumed} = false `); -export const insertPasscode = buildInsertInto(pool, Passcodes, { +export const insertPasscode = buildInsertInto(Passcodes, { returning: true, }); -export const updatePasscode = buildUpdateWhere(pool, Passcodes, true); +export const updatePasscode = buildUpdateWhere(Passcodes, true); export const deletePasscodeById = async (id: string) => { - const { rowCount } = await pool.query(sql` + const { rowCount } = await envSet.pool.query(sql` delete from ${table} where ${fields.id}=${id} `); @@ -41,7 +41,7 @@ export const deletePasscodeById = async (id: string) => { }; export const deletePasscodesByIds = async (ids: string[]) => { - const { rowCount } = await pool.query(sql` + const { rowCount } = await envSet.pool.query(sql` delete from ${table} where ${fields.id} in (${ids.join(',')}) `); diff --git a/packages/core/src/queries/resource.test.ts b/packages/core/src/queries/resource.test.ts index a2a0a6d2b..8853bdc70 100644 --- a/packages/core/src/queries/resource.test.ts +++ b/packages/core/src/queries/resource.test.ts @@ -3,6 +3,7 @@ import { createMockPool, createMockQueryResult, sql } from 'slonik'; import { mockResource } from '@/__mocks__'; import { convertToIdentifiers, convertToPrimitiveOrSql } from '@/database/utils'; +import envSet from '@/env-set'; import { DeletionError } from '@/errors/SlonikError'; import { expectSqlAssert, QueryType } from '@/utils/test-utils'; @@ -18,7 +19,7 @@ import { const mockQuery: jest.MockedFunction = jest.fn(); -jest.mock('@/database/pool', () => +jest.spyOn(envSet, 'pool', 'get').mockReturnValue( createMockPool({ query: async (sql, values) => { return mockQuery(sql, values); diff --git a/packages/core/src/queries/resource.ts b/packages/core/src/queries/resource.ts index 97713f611..fa6298271 100644 --- a/packages/core/src/queries/resource.ts +++ b/packages/core/src/queries/resource.ts @@ -2,7 +2,6 @@ import { Resource, CreateResource, Resources } from '@logto/schemas'; import { sql } from 'slonik'; import { buildInsertInto } from '@/database/insert-into'; -import pool from '@/database/pool'; import { buildUpdateWhere } from '@/database/update-where'; import { convertToIdentifiers, @@ -10,6 +9,7 @@ import { getTotalRowCount, conditionalSql, } from '@/database/utils'; +import envSet from '@/env-set'; import { DeletionError } from '@/errors/SlonikError'; const { table, fields } = convertToIdentifiers(Resources); @@ -17,7 +17,7 @@ const { table, fields } = convertToIdentifiers(Resources); export const findTotalNumberOfResources = async () => getTotalRowCount(table); export const findAllResources = async (limit: number, offset: number) => - pool.many(sql` + envSet.pool.many(sql` select ${sql.join(Object.values(fields), sql`, `)} from ${table} ${conditionalSql(limit, (limit) => sql`limit ${limit}`)} @@ -25,24 +25,24 @@ export const findAllResources = async (limit: number, offset: number) => `); export const findResourceByIndicator = async (indicator: string) => - pool.maybeOne(sql` + envSet.pool.maybeOne(sql` select ${sql.join(Object.values(fields), sql`, `)} from ${table} where ${fields.indicator}=${indicator} `); export const findResourceById = async (id: string) => - pool.one(sql` + envSet.pool.one(sql` select ${sql.join(Object.values(fields), sql`, `)} from ${table} where ${fields.id}=${id} `); -export const insertResource = buildInsertInto(pool, Resources, { +export const insertResource = buildInsertInto(Resources, { returning: true, }); -const updateResource = buildUpdateWhere(pool, Resources, true); +const updateResource = buildUpdateWhere(Resources, true); export const updateResourceById = async ( id: string, @@ -50,7 +50,7 @@ export const updateResourceById = async ( ) => updateResource({ set, where: { id } }); export const deleteResourceById = async (id: string) => { - const { rowCount } = await pool.query(sql` + const { rowCount } = await envSet.pool.query(sql` delete from ${table} where ${fields.id}=${id} `); diff --git a/packages/core/src/queries/roles.test.ts b/packages/core/src/queries/roles.test.ts index a30c1ae63..58d688aff 100644 --- a/packages/core/src/queries/roles.test.ts +++ b/packages/core/src/queries/roles.test.ts @@ -3,13 +3,14 @@ import { createMockPool, createMockQueryResult, sql } from 'slonik'; import { mockRole } from '@/__mocks__'; import { convertToIdentifiers } from '@/database/utils'; +import envSet from '@/env-set'; import { expectSqlAssert, QueryType } from '@/utils/test-utils'; import { findAllRoles, findRolesByRoleNames } from './roles'; const mockQuery: jest.MockedFunction = jest.fn(); -jest.mock('@/database/pool', () => +jest.spyOn(envSet, 'pool', 'get').mockReturnValue( createMockPool({ query: async (sql, values) => { return mockQuery(sql, values); diff --git a/packages/core/src/queries/roles.ts b/packages/core/src/queries/roles.ts index da31d5d00..81d844ae4 100644 --- a/packages/core/src/queries/roles.ts +++ b/packages/core/src/queries/roles.ts @@ -1,19 +1,19 @@ import { Roles, Role } from '@logto/schemas'; import { sql } from 'slonik'; -import pool from '@/database/pool'; import { convertToIdentifiers } from '@/database/utils'; +import envSet from '@/env-set'; const { table, fields } = convertToIdentifiers(Roles); export const findAllRoles = async () => - pool.any(sql` + envSet.pool.any(sql` select ${sql.join(Object.values(fields), sql`, `)} from ${table} `); export const findRolesByRoleNames = async (roleNames: string[]) => - pool.any(sql` + envSet.pool.any(sql` select ${sql.join(Object.values(fields), sql`, `)} from ${table} where ${fields.name} in (${sql.join(roleNames, sql`, `)}) diff --git a/packages/core/src/queries/setting.test.ts b/packages/core/src/queries/setting.test.ts index 082bd9fbb..9f8996c5b 100644 --- a/packages/core/src/queries/setting.test.ts +++ b/packages/core/src/queries/setting.test.ts @@ -3,13 +3,14 @@ import { createMockPool, createMockQueryResult, sql } from 'slonik'; import { mockSetting } from '@/__mocks__'; import { convertToIdentifiers } from '@/database/utils'; +import envSet from '@/env-set'; import { expectSqlAssert, QueryType } from '@/utils/test-utils'; import { defaultSettingId, getSetting, updateSetting } from './setting'; const mockQuery: jest.MockedFunction = jest.fn(); -jest.mock('@/database/pool', () => +jest.spyOn(envSet, 'pool', 'get').mockReturnValue( createMockPool({ query: async (sql, values) => { return mockQuery(sql, values); diff --git a/packages/core/src/queries/setting.ts b/packages/core/src/queries/setting.ts index 512dfc1f6..e410e8323 100644 --- a/packages/core/src/queries/setting.ts +++ b/packages/core/src/queries/setting.ts @@ -1,16 +1,16 @@ import { Setting, CreateSetting, Settings } from '@logto/schemas'; import { sql } from 'slonik'; -import pool from '@/database/pool'; import { buildUpdateWhere } from '@/database/update-where'; import { convertToIdentifiers, OmitAutoSetFields } from '@/database/utils'; +import envSet from '@/env-set'; export const defaultSettingId = 'default'; const { table, fields } = convertToIdentifiers(Settings); export const getSetting = async () => - pool.one(sql` + envSet.pool.one(sql` select ${sql.join(Object.values(fields), sql`, `)} from ${table} where ${fields.id}=${defaultSettingId} @@ -18,7 +18,6 @@ export const getSetting = async () => export const updateSetting = async (setting: Partial>) => { return buildUpdateWhere( - pool, Settings, true )({ set: setting, where: { id: defaultSettingId } }); diff --git a/packages/core/src/queries/sign-in-experience.test.ts b/packages/core/src/queries/sign-in-experience.test.ts index 9f338bd2c..66c782547 100644 --- a/packages/core/src/queries/sign-in-experience.test.ts +++ b/packages/core/src/queries/sign-in-experience.test.ts @@ -1,13 +1,14 @@ import { createMockPool, createMockQueryResult } from 'slonik'; import { mockSignInExperience } from '@/__mocks__'; +import envSet from '@/env-set'; import { expectSqlAssert, QueryType } from '@/utils/test-utils'; import { findDefaultSignInExperience, updateDefaultSignInExperience } from './sign-in-experience'; const mockQuery: jest.MockedFunction = jest.fn(); -jest.mock('@/database/pool', () => +jest.spyOn(envSet, 'pool', 'get').mockReturnValue( createMockPool({ query: async (sql, values) => { return mockQuery(sql, values); diff --git a/packages/core/src/queries/sign-in-experience.ts b/packages/core/src/queries/sign-in-experience.ts index 2b6a3a5b6..41f16147d 100644 --- a/packages/core/src/queries/sign-in-experience.ts +++ b/packages/core/src/queries/sign-in-experience.ts @@ -1,14 +1,13 @@ import { SignInExperience, CreateSignInExperience, SignInExperiences } from '@logto/schemas'; import { sql } from 'slonik'; -import pool from '@/database/pool'; import { buildUpdateWhere } from '@/database/update-where'; import { convertToIdentifiers } from '@/database/utils'; +import envSet from '@/env-set'; const { table, fields } = convertToIdentifiers(SignInExperiences); const updateSignInExperience = buildUpdateWhere( - pool, SignInExperiences, true ); @@ -19,7 +18,7 @@ export const updateDefaultSignInExperience = async (set: Partial - pool.one(sql` + envSet.pool.one(sql` select ${sql.join(Object.values(fields), sql`, `)} from ${table} where ${fields.id} = ${id} diff --git a/packages/core/src/queries/user-log.test.ts b/packages/core/src/queries/user-log.test.ts new file mode 100644 index 000000000..cf8ef6835 --- /dev/null +++ b/packages/core/src/queries/user-log.test.ts @@ -0,0 +1,67 @@ +import { UserLogs } from '@logto/schemas'; +import { createMockPool, createMockQueryResult, sql } from 'slonik'; +import { snakeCase } from 'snake-case'; + +import { mockUserLog } from '@/__mocks__'; +import { + convertToIdentifiers, + excludeAutoSetFields, + convertToPrimitiveOrSql, +} from '@/database/utils'; +import envSet from '@/env-set'; +import { expectSqlAssert, QueryType } from '@/utils/test-utils'; + +import { insertUserLog, findLogsByUserId } from './user-log'; + +const mockQuery: jest.MockedFunction = jest.fn(); + +jest.spyOn(envSet, 'pool', 'get').mockReturnValue( + createMockPool({ + query: async (sql, values) => { + return mockQuery(sql, values); + }, + }) +); + +describe('user-log query', () => { + const { table, fields } = convertToIdentifiers(UserLogs); + const dbvalue = { ...mockUserLog, payload: JSON.stringify(mockUserLog.payload) }; + + it('findLogsByUserId', async () => { + const userId = 'foo'; + const expectSql = sql` + select ${sql.join(Object.values(fields), sql`,`)} + from ${table} + where ${fields.userId}=${userId} + order by created_at desc + `; + + mockQuery.mockImplementationOnce(async (sql, values) => { + expectSqlAssert(sql, expectSql.sql); + expect(values).toEqual([userId]); + + return createMockQueryResult([dbvalue]); + }); + + await expect(findLogsByUserId(userId)).resolves.toEqual([dbvalue]); + }); + + it('insertUserLog', async () => { + const keys = excludeAutoSetFields(UserLogs.fieldKeys); + + // eslint-disable-next-line sql/no-unsafe-query + const expectSql = ` + insert into "user_logs" (${keys.map((k) => `"${snakeCase(k)}"`).join(', ')}) + values (${keys.map((_, index) => `$${index + 1}`).join(', ')}) + `; + + mockQuery.mockImplementationOnce(async (sql, values) => { + expectSqlAssert(sql, expectSql); + expect(values).toEqual(keys.map((k) => convertToPrimitiveOrSql(k, mockUserLog[k]))); + + return createMockQueryResult([]); + }); + + await insertUserLog(mockUserLog); + }); +}); diff --git a/packages/core/src/queries/user-log.ts b/packages/core/src/queries/user-log.ts new file mode 100644 index 000000000..bc29de2e0 --- /dev/null +++ b/packages/core/src/queries/user-log.ts @@ -0,0 +1,18 @@ +import { CreateUserLog, UserLogs } from '@logto/schemas'; +import { sql } from 'slonik'; + +import { buildInsertInto } from '@/database/insert-into'; +import { convertToIdentifiers } from '@/database/utils'; +import envSet from '@/env-set'; + +const { table, fields } = convertToIdentifiers(UserLogs); + +export const insertUserLog = buildInsertInto(UserLogs); + +export const findLogsByUserId = async (userId: string) => + envSet.pool.many(sql` + select ${sql.join(Object.values(fields), sql`,`)} + from ${table} + where ${fields.userId}=${userId} + order by created_at desc + `); diff --git a/packages/core/src/queries/user.test.ts b/packages/core/src/queries/user.test.ts index 79ecbd4ff..a0e988955 100644 --- a/packages/core/src/queries/user.test.ts +++ b/packages/core/src/queries/user.test.ts @@ -3,6 +3,7 @@ import { createMockPool, createMockQueryResult, sql } from 'slonik'; import { mockUser } from '@/__mocks__'; import { convertToIdentifiers, convertToPrimitiveOrSql } from '@/database/utils'; +import envSet from '@/env-set'; import { DeletionError } from '@/errors/SlonikError'; import { expectSqlAssert, QueryType } from '@/utils/test-utils'; @@ -28,7 +29,7 @@ import { const mockQuery: jest.MockedFunction = jest.fn(); -jest.mock('@/database/pool', () => +jest.spyOn(envSet, 'pool', 'get').mockReturnValue( createMockPool({ query: async (sql, values) => { return mockQuery(sql, values); diff --git a/packages/core/src/queries/user.ts b/packages/core/src/queries/user.ts index ad94a4637..83ad9bdc7 100644 --- a/packages/core/src/queries/user.ts +++ b/packages/core/src/queries/user.ts @@ -2,43 +2,43 @@ import { User, CreateUser, Users } from '@logto/schemas'; import { sql } from 'slonik'; import { buildInsertInto } from '@/database/insert-into'; -import pool from '@/database/pool'; import { buildUpdateWhere } from '@/database/update-where'; import { conditionalSql, convertToIdentifiers, OmitAutoSetFields } from '@/database/utils'; +import envSet from '@/env-set'; import { DeletionError, UpdateError } from '@/errors/SlonikError'; const { table, fields } = convertToIdentifiers(Users); export const findUserByUsername = async (username: string) => - pool.one(sql` + envSet.pool.one(sql` select ${sql.join(Object.values(fields), sql`,`)} from ${table} where ${fields.username}=${username} `); export const findUserByEmail = async (email: string) => - pool.one(sql` + envSet.pool.one(sql` select ${sql.join(Object.values(fields), sql`,`)} from ${table} where ${fields.primaryEmail}=${email} `); export const findUserByPhone = async (phone: string) => - pool.one(sql` + envSet.pool.one(sql` select ${sql.join(Object.values(fields), sql`,`)} from ${table} where ${fields.primaryPhone}=${phone} `); export const findUserById = async (id: string) => - pool.one(sql` + envSet.pool.one(sql` select ${sql.join(Object.values(fields), sql`,`)} from ${table} where ${fields.id}=${id} `); export const findUserByIdentity = async (connectorId: string, userId: string) => - pool.one( + envSet.pool.one( sql` select ${sql.join(Object.values(fields), sql`,`)} from ${table} @@ -47,35 +47,35 @@ export const findUserByIdentity = async (connectorId: string, userId: string) => ); export const hasUser = async (username: string) => - pool.exists(sql` + envSet.pool.exists(sql` select ${fields.id} from ${table} where ${fields.username}=${username} `); export const hasUserWithId = async (id: string) => - pool.exists(sql` + envSet.pool.exists(sql` select ${fields.id} from ${table} where ${fields.id}=${id} `); export const hasUserWithEmail = async (email: string) => - pool.exists(sql` + envSet.pool.exists(sql` select ${fields.primaryEmail} from ${table} where ${fields.primaryEmail}=${email} `); export const hasUserWithPhone = async (phone: string) => - pool.exists(sql` + envSet.pool.exists(sql` select ${fields.primaryPhone} from ${table} where ${fields.primaryPhone}=${phone} `); export const hasUserWithIdentity = async (connectorId: string, userId: string) => - pool.exists( + envSet.pool.exists( sql` select ${fields.id} from ${table} @@ -83,7 +83,9 @@ export const hasUserWithIdentity = async (connectorId: string, userId: string) = ` ); -export const insertUser = buildInsertInto(pool, Users, { returning: true }); +export const insertUser = buildInsertInto(Users, { + returning: true, +}); const buildUserSearchConditionSql = (search: string) => { const searchFields = [fields.primaryEmail, fields.primaryPhone, fields.username, fields.name]; @@ -93,14 +95,14 @@ const buildUserSearchConditionSql = (search: string) => { }; export const countUsers = async (search?: string) => - pool.one<{ count: number }>(sql` + envSet.pool.one<{ count: number }>(sql` select count(*) from ${table} ${conditionalSql(search, (search) => sql`where ${buildUserSearchConditionSql(search)}`)} `); export const findUsers = async (limit: number, offset: number, search?: string) => - pool.any( + envSet.pool.any( sql` select ${sql.join(Object.values(fields), sql`,`)} from ${table} @@ -110,13 +112,13 @@ export const findUsers = async (limit: number, offset: number, search?: string) ` ); -const updateUser = buildUpdateWhere(pool, Users, true); +const updateUser = buildUpdateWhere(Users, true); export const updateUserById = async (id: string, set: Partial>) => updateUser({ set, where: { id } }); export const deleteUserById = async (id: string) => { - const { rowCount } = await pool.query(sql` + const { rowCount } = await envSet.pool.query(sql` delete from ${table} where ${fields.id}=${id} `); @@ -127,7 +129,7 @@ export const deleteUserById = async (id: string) => { }; export const clearUserCustomDataById = async (id: string) => { - const { rowCount } = await pool.query(sql` + const { rowCount } = await envSet.pool.query(sql` update ${table} set ${fields.customData}='{}'::jsonb where ${fields.id}=${id} @@ -139,7 +141,7 @@ export const clearUserCustomDataById = async (id: string) => { }; export const deleteUserIdentity = async (userId: string, connectorId: string) => - pool.one(sql` + envSet.pool.one(sql` update ${table} set ${fields.identities}=${fields.identities}::jsonb-${connectorId} where ${fields.id}=${userId} diff --git a/packages/core/tsconfig.json b/packages/core/tsconfig.json index 2796b3926..64517c9bb 100644 --- a/packages/core/tsconfig.json +++ b/packages/core/tsconfig.json @@ -8,6 +8,7 @@ ] }, "include": [ - "src" + "src", + "jest.*.ts" ] }