Files
order_site/apps/backend/src/repositories/webhook-event-repo.js
T

181 lines
5.0 KiB
JavaScript

// @ts-check
import { query } from '../db/client.js'
/** @typedef {import('../types/repository-inputs.js').WebhookEventCreateInput} WebhookEventCreateInput */
/** @typedef {import('../types/repository-inputs.js').WebhookEventListQueryInput} WebhookEventListQueryInput */
/** @typedef {import('../types/repository-inputs.js').WebhookEventUpdatePatch} WebhookEventUpdatePatch */
/** @typedef {import('../types/repository-rows.js').WebhookEventListQueryResult} WebhookEventListQueryResult */
/** @typedef {import('../types/repository-rows.js').WebhookEventRow} WebhookEventRow */
/** @returns {Promise<WebhookEventRow | null>} */
/** @param {WebhookEventCreateInput} input */
export async function createWebhookEvent(input) {
const result = await query(
`
INSERT INTO webhook_events (
provider,
platform,
shop_id,
shop_name,
event_type,
event_key,
signature_valid,
headers_json,
query_json,
body_json,
processed,
process_error,
related_order_id,
created_at
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8::jsonb, $9::jsonb, $10::jsonb, $11, $12, $13, $14)
RETURNING *
`,
[
input.provider,
input.platform,
input.shopId || '',
input.shopName || '',
input.eventType,
input.eventKey,
Boolean(input.signatureValid),
input.headersJson || '{}',
input.queryJson || '{}',
input.bodyJson || '{}',
Boolean(input.processed),
input.processError || '',
input.relatedOrderId || null,
input.createdAt,
],
)
return /** @type {WebhookEventRow | null} */ (result.rows[0] || null)
}
/** @returns {Promise<WebhookEventRow | null>} */
/** @param {WebhookEventUpdatePatch} patch */
export async function updateWebhookEvent(eventId, patch) {
const current = await getWebhookEventById(eventId)
if (!current) {
return null
}
const next = { ...current, ...patch }
const result = await query(
`
UPDATE webhook_events
SET
processed = $1,
process_error = $2,
related_order_id = $3
WHERE id = $4
RETURNING *
`,
[Boolean(next.processed), next.process_error || '', next.related_order_id || null, Number(eventId)],
)
return /** @type {WebhookEventRow | null} */ (result.rows[0] || null)
}
/** @returns {Promise<WebhookEventRow | null>} */
export async function getWebhookEventById(eventId) {
const result = await query('SELECT * FROM webhook_events WHERE id = $1 LIMIT 1', [Number(eventId)])
return /** @type {WebhookEventRow | null} */ (result.rows[0] || null)
}
/** @returns {Promise<WebhookEventListQueryResult>} */
/** @param {WebhookEventListQueryInput} [queryInput] */
export async function listWebhookEvents({
page = 1,
pageSize = 20,
provider = '',
platform = '',
platformOrderId = '',
processed = '',
visibility = 'important',
relatedOrderId = '',
dateFrom = '',
dateTo = '',
} = /** @type {WebhookEventListQueryInput} */ ({})) {
const offset = (page - 1) * pageSize
const filters = []
const params = []
if (provider) {
params.push(provider)
filters.push(`provider = $${params.length}`)
}
if (platform) {
params.push(platform)
filters.push(`platform = $${params.length}`)
}
if (platformOrderId) {
params.push(`%${platformOrderId}%`)
filters.push(`(event_key ILIKE $${params.length} OR body_json::text ILIKE $${params.length})`)
}
if (processed === '0' || processed === '1') {
params.push(processed === '1')
filters.push(`processed = $${params.length}`)
}
if (visibility === 'ignored') {
filters.push(`process_error LIKE 'ignored_%'`)
} else if (visibility === 'important') {
filters.push(`(process_error = '' OR process_error NOT LIKE 'ignored_%')`)
}
if (relatedOrderId) {
params.push(Number(relatedOrderId))
filters.push(`related_order_id = $${params.length}`)
}
if (dateFrom) {
params.push(dateFrom)
filters.push(`created_at >= $${params.length}`)
}
if (dateTo) {
params.push(dateTo)
filters.push(`created_at <= $${params.length}`)
}
const whereClause = filters.length > 0 ? `WHERE ${filters.join(' AND ')}` : ''
const totalResult = await query(`SELECT COUNT(*)::int AS total FROM webhook_events ${whereClause}`, params)
params.push(pageSize)
params.push(offset)
const itemsResult = await query(
`
SELECT *
FROM webhook_events
${whereClause}
ORDER BY id DESC
LIMIT $${params.length - 1} OFFSET $${params.length}
`,
params,
)
return {
items: /** @type {WebhookEventRow[]} */ (itemsResult.rows),
total: Number(totalResult.rows[0]?.total || 0),
}
}
/** @returns {Promise<WebhookEventRow[]>} */
export async function listWebhookEventsByOrderId(orderId) {
const result = await query(
`
SELECT *
FROM webhook_events
WHERE related_order_id = $1
ORDER BY id DESC
`,
[Number(orderId)],
)
return /** @type {WebhookEventRow[]} */ (result.rows)
}