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:
parent
c5729e7a2d
commit
be57e7e1af
2 changed files with 132 additions and 87 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue