0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-01-27 21:39:16 -05:00

refactor(core): custom phrase and log query factories (#2856)

This commit is contained in:
Gao Sun 2023-01-09 16:02:15 +08:00 committed by GitHub
parent c5729e7a2d
commit be57e7e1af
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 132 additions and 87 deletions

View file

@ -1,57 +1,80 @@
import type { CreateCustomPhrase, CustomPhrase } from '@logto/schemas';
import { CustomPhrases } from '@logto/schemas';
import { convertToIdentifiers, manyRows } from '@logto/shared';
import type { CommonQueryMethods } from 'slonik';
import { sql } from 'slonik';
import { buildInsertInto } from '#src/database/insert-into.js';
import { buildInsertIntoWithPool } from '#src/database/insert-into.js';
import envSet from '#src/env-set/index.js';
import { DeletionError } from '#src/errors/SlonikError/index.js';
const { table, fields } = convertToIdentifiers(CustomPhrases);
export const findAllCustomLanguageTags = async () => {
const rows = await manyRows<{ languageTag: string }>(
envSet.pool.query(sql`
select ${fields.languageTag}
export const createCustomPhraseQueries = (pool: CommonQueryMethods) => {
const findAllCustomLanguageTags = async () => {
const rows = await manyRows<{ languageTag: string }>(
pool.query(sql`
select ${fields.languageTag}
from ${table}
order by ${fields.languageTag}
`)
);
return rows.map((row) => row.languageTag);
};
const findAllCustomPhrases = async () =>
manyRows(
pool.query<CustomPhrase>(sql`
select ${sql.join(Object.values(fields), sql`,`)}
from ${table}
order by ${fields.languageTag}
`)
);
const findCustomPhraseByLanguageTag = async (languageTag: string): Promise<CustomPhrase> =>
pool.one<CustomPhrase>(sql`
select ${sql.join(Object.values(fields), sql`, `)}
from ${table}
order by ${fields.languageTag}
`)
where ${fields.languageTag} = ${languageTag}
`);
const upsertCustomPhrase = buildInsertIntoWithPool(pool)<CreateCustomPhrase, CustomPhrase>(
CustomPhrases,
{
returning: true,
onConflict: {
fields: [fields.languageTag],
setExcludedFields: [fields.translation],
},
}
);
return rows.map((row) => row.languageTag);
const deleteCustomPhraseByLanguageTag = async (languageTag: string) => {
const { rowCount } = await pool.query(sql`
delete from ${table}
where ${fields.languageTag}=${languageTag}
`);
if (rowCount < 1) {
throw new DeletionError(CustomPhrases.table, languageTag);
}
};
return {
findAllCustomLanguageTags,
findAllCustomPhrases,
findCustomPhraseByLanguageTag,
upsertCustomPhrase,
deleteCustomPhraseByLanguageTag,
};
};
export const findAllCustomPhrases = async () =>
manyRows(
envSet.pool.query<CustomPhrase>(sql`
select ${sql.join(Object.values(fields), sql`,`)}
from ${table}
order by ${fields.languageTag}
`)
);
export const findCustomPhraseByLanguageTag = async (languageTag: string): Promise<CustomPhrase> =>
envSet.pool.one<CustomPhrase>(sql`
select ${sql.join(Object.values(fields), sql`, `)}
from ${table}
where ${fields.languageTag} = ${languageTag}
`);
export const upsertCustomPhrase = buildInsertInto<CreateCustomPhrase, CustomPhrase>(CustomPhrases, {
returning: true,
onConflict: {
fields: [fields.languageTag],
setExcludedFields: [fields.translation],
},
});
export const deleteCustomPhraseByLanguageTag = async (languageTag: string) => {
const { rowCount } = await envSet.pool.query(sql`
delete from ${table}
where ${fields.languageTag}=${languageTag}
`);
if (rowCount < 1) {
throw new DeletionError(CustomPhrases.table, languageTag);
}
};
/** @deprecated Will be removed soon. Use createCustomPhraseQueries() factory instead. */
export const {
findAllCustomLanguageTags,
findAllCustomPhrases,
findCustomPhraseByLanguageTag,
upsertCustomPhrase,
deleteCustomPhraseByLanguageTag,
} = createCustomPhraseQueries(envSet.pool);

View file

@ -1,16 +1,15 @@
import type { CreateLog, Log } from '@logto/schemas';
import { token, Logs } from '@logto/schemas';
import { conditionalSql, convertToIdentifiers } from '@logto/shared';
import type { CommonQueryMethods } from 'slonik';
import { sql } from 'slonik';
import { buildFindEntityById } from '#src/database/find-entity-by-id.js';
import { buildInsertInto } from '#src/database/insert-into.js';
import { buildFindEntityByIdWithPool } from '#src/database/find-entity-by-id.js';
import { buildInsertIntoWithPool } from '#src/database/insert-into.js';
import envSet from '#src/env-set/index.js';
const { table, fields } = convertToIdentifiers(Logs);
export const insertLog = buildInsertInto<CreateLog>(Logs);
export type LogCondition = {
logKey?: string;
applicationId?: string;
@ -31,48 +30,71 @@ const buildLogConditionSql = (logCondition: LogCondition) =>
return subConditions.length > 0 ? sql`where ${sql.join(subConditions, sql` and `)}` : sql``;
});
export const countLogs = async (condition: LogCondition) =>
envSet.pool.one<{ count: number }>(sql`
select count(*)
from ${table}
${buildLogConditionSql(condition)}
`);
export const createLogQueries = (pool: CommonQueryMethods) => {
const insertLog = buildInsertIntoWithPool(pool)<CreateLog>(Logs);
export const findLogs = async (limit: number, offset: number, logCondition: LogCondition) =>
envSet.pool.any<Log>(sql`
select ${sql.join(Object.values(fields), sql`,`)}
from ${table}
${buildLogConditionSql(logCondition)}
order by ${fields.createdAt} desc
limit ${limit}
offset ${offset}
`);
const countLogs = async (condition: LogCondition) =>
pool.one<{ count: number }>(sql`
select count(*)
from ${table}
${buildLogConditionSql(condition)}
`);
export const findLogById = buildFindEntityById<CreateLog, Log>(Logs);
const findLogs = async (limit: number, offset: number, logCondition: LogCondition) =>
pool.any<Log>(sql`
select ${sql.join(Object.values(fields), sql`,`)}
from ${table}
${buildLogConditionSql(logCondition)}
order by ${fields.createdAt} desc
limit ${limit}
offset ${offset}
`);
export const getDailyActiveUserCountsByTimeInterval = async (
startTimeExclusive: number,
endTimeInclusive: number
) =>
envSet.pool.any<{ date: string; count: number }>(sql`
select date(${fields.createdAt}), count(distinct(${fields.payload}->>'userId'))
from ${table}
where ${fields.createdAt} > to_timestamp(${startTimeExclusive}::double precision / 1000)
and ${fields.createdAt} <= to_timestamp(${endTimeInclusive}::double precision / 1000)
and ${fields.key} like ${`${token.Type.ExchangeTokenBy}.%`}
and ${fields.payload}->>'result' = 'Success'
group by date(${fields.createdAt})
`);
const findLogById = buildFindEntityByIdWithPool(pool)<CreateLog, Log>(Logs);
export const countActiveUsersByTimeInterval = async (
startTimeExclusive: number,
endTimeInclusive: number
) =>
envSet.pool.one<{ count: number }>(sql`
select count(distinct(${fields.payload}->>'userId'))
from ${table}
where ${fields.createdAt} > to_timestamp(${startTimeExclusive}::double precision / 1000)
and ${fields.createdAt} <= to_timestamp(${endTimeInclusive}::double precision / 1000)
and ${fields.key} like ${`${token.Type.ExchangeTokenBy}.%`}
and ${fields.payload}->>'result' = 'Success'
`);
const getDailyActiveUserCountsByTimeInterval = async (
startTimeExclusive: number,
endTimeInclusive: number
) =>
pool.any<{ date: string; count: number }>(sql`
select date(${fields.createdAt}), count(distinct(${fields.payload}->>'userId'))
from ${table}
where ${fields.createdAt} > to_timestamp(${startTimeExclusive}::double precision / 1000)
and ${fields.createdAt} <= to_timestamp(${endTimeInclusive}::double precision / 1000)
and ${fields.key} like ${`${token.Type.ExchangeTokenBy}.%`}
and ${fields.payload}->>'result' = 'Success'
group by date(${fields.createdAt})
`);
const countActiveUsersByTimeInterval = async (
startTimeExclusive: number,
endTimeInclusive: number
) =>
pool.one<{ count: number }>(sql`
select count(distinct(${fields.payload}->>'userId'))
from ${table}
where ${fields.createdAt} > to_timestamp(${startTimeExclusive}::double precision / 1000)
and ${fields.createdAt} <= to_timestamp(${endTimeInclusive}::double precision / 1000)
and ${fields.key} like ${`${token.Type.ExchangeTokenBy}.%`}
and ${fields.payload}->>'result' = 'Success'
`);
return {
insertLog,
countLogs,
findLogs,
findLogById,
getDailyActiveUserCountsByTimeInterval,
countActiveUsersByTimeInterval,
};
};
/** @deprecated Will be removed soon. Use createLogQueries() factory instead. */
export const {
insertLog,
countLogs,
findLogs,
findLogById,
getDailyActiveUserCountsByTimeInterval,
countActiveUsersByTimeInterval,
} = createLogQueries(envSet.pool);