0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-16 20:26:19 -05:00

feat: buildFindMany (#159)

This commit is contained in:
Wang Sijie 2022-01-07 14:54:32 +08:00 committed by GitHub
parent 5b404e2b2e
commit e8908c3b24
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 96 additions and 0 deletions

View file

@ -0,0 +1,55 @@
import { Users } from '@logto/schemas';
import { createTestPool } from '@/utils/test-utils';
import { buildFindMany } from './find-many';
describe('buildFindMany()', () => {
it('matches expected sql', async () => {
const pool = createTestPool(
'select "id", "username", "primary_email", "primary_phone", "password_encrypted", "password_encryption_method", "password_encryption_salt"\nfrom "users"'
);
const findMany = buildFindMany(pool, Users);
await findMany();
});
it('matches expected sql with where conditions', async () => {
const pool = createTestPool(
'select "id", "username", "primary_email", "primary_phone", "password_encrypted", "password_encryption_method", "password_encryption_salt"\nfrom "users"\nwhere "id"=$1'
);
const findMany = buildFindMany(pool, Users);
await findMany({ where: { id: '123' } });
});
it('matches expected sql with limit', async () => {
const pool = createTestPool(
'select "id", "username", "primary_email", "primary_phone", "password_encrypted", "password_encryption_method", "password_encryption_salt"\nfrom "users"\nlimit $1'
);
const findMany = buildFindMany(pool, Users);
await findMany({ limit: 10 });
});
it('matches expected sql with offset', async () => {
const pool = createTestPool(
'select "id", "username", "primary_email", "primary_phone", "password_encrypted", "password_encryption_method", "password_encryption_salt"\nfrom "users"\noffset $1'
);
const findMany = buildFindMany(pool, Users);
await findMany({ offset: 10 });
});
it('matches expected sql with offset 0', async () => {
const pool = createTestPool(
'select "id", "username", "primary_email", "primary_phone", "password_encrypted", "password_encryption_method", "password_encryption_salt"\nfrom "users"'
);
const findMany = buildFindMany(pool, Users);
await findMany({ offset: 0 });
});
it('matches expected sql with where conditions, limit and offset', async () => {
const pool = createTestPool(
'select "id", "username", "primary_email", "primary_phone", "password_encrypted", "password_encryption_method", "password_encryption_salt"\nfrom "users"\nwhere "id"=$1\nlimit $2\noffset $3'
);
const findMany = buildFindMany(pool, Users);
await findMany({ where: { id: '123' }, limit: 20, offset: 20 });
});
});

View file

@ -0,0 +1,41 @@
import { SchemaLike, GeneratedSchema } from '@logto/schemas';
import { notFalsy, Truthy } from '@silverhand/essentials';
import { DatabasePoolType, sql } from 'slonik';
import { isKeyOf } from '@/utils/schema';
import { conditionalSql, convertToIdentifiers, convertToPrimitiveOrSql } from './utils';
export type FindManyData<Schema extends SchemaLike> = {
where?: Partial<Schema>;
limit?: number;
offset?: number;
};
export const buildFindMany = <Schema extends SchemaLike, ReturnType extends SchemaLike>(
pool: DatabasePoolType,
schema: GeneratedSchema<Schema>
) => {
const { table, fields } = convertToIdentifiers(schema);
const isKeyOfSchema = isKeyOf(schema);
const connectKeyValueWithEqualSign = (data: Partial<Schema>) =>
Object.entries(data)
.map(
([key, value]) =>
isKeyOfSchema(key) && sql`${fields[key]}=${convertToPrimitiveOrSql(key, value)}`
)
.filter((value): value is Truthy<typeof value> => notFalsy(value));
return async ({ where, limit, offset }: FindManyData<Schema> = {}) => {
return pool.any<ReturnType>(sql`
select ${sql.join(Object.values(fields), sql`, `)}
from ${table}
${conditionalSql(
where,
(where) => sql`where ${sql.join(connectKeyValueWithEqualSign(where), sql` and `)}`
)}
${conditionalSql(limit, (limit) => sql`limit ${limit}`)}
${conditionalSql(offset, (offset) => sql`offset ${offset}`)}
`);
};
};