重构后台管理服务并推进渐进式类型化

This commit is contained in:
yml2213
2026-04-14 09:21:20 +08:00
parent fa36be6539
commit 335eb44104
35 changed files with 4143 additions and 2738 deletions
@@ -1,5 +1,14 @@
// @ts-check
import { query, withTransaction } from '../db/client.js'
/** @typedef {import('../types/repository-inputs.js').InventoryCreateItemInput} InventoryCreateItemInput */
/** @typedef {import('../types/repository-inputs.js').InventoryListQueryInput} InventoryListQueryInput */
/** @typedef {import('../types/repository-inputs.js').InventorySkuSuggestionQueryInput} InventorySkuSuggestionQueryInput */
/** @typedef {import('../types/repository-rows.js').InventoryItemRow} InventoryItemRow */
/** @typedef {import('../types/repository-rows.js').InventoryListQueryResult} InventoryListQueryResult */
/** @typedef {import('../types/repository-rows.js').InventorySkuSuggestionRow} InventorySkuSuggestionRow */
const INVENTORY_ITEM_SELECT = `
SELECT
ii.id,
@@ -26,6 +35,7 @@ const INVENTORY_ITEM_SELECT = `
LEFT JOIN fulfillment_tasks ft ON ft.id = tib.task_id
`
/** @returns {Promise<InventoryItemRow | null>} */
export async function findFirstAvailableInventoryItemBySkuCode(skuCode, credentialType = 'tencent_code') {
const result = await query(
`${INVENTORY_ITEM_SELECT}
@@ -35,9 +45,10 @@ export async function findFirstAvailableInventoryItemBySkuCode(skuCode, credenti
[skuCode, credentialType],
)
return result.rows[0] || null
return /** @type {InventoryItemRow | null} */ (result.rows[0] || null)
}
/** @returns {Promise<InventoryItemRow | null>} */
export async function assignReservedInventoryItem(inventoryItemId, taskId, updatedAt, roleKey = 'primary_code') {
return withTransaction(async (client) => {
const inventoryResult = await client.query(
@@ -76,6 +87,7 @@ export async function assignReservedInventoryItem(inventoryItemId, taskId, updat
})
}
/** @returns {Promise<InventoryItemRow | null>} */
export async function getInventoryItemById(inventoryItemId) {
const result = await query(
`${INVENTORY_ITEM_SELECT}
@@ -84,9 +96,10 @@ export async function getInventoryItemById(inventoryItemId) {
[Number(inventoryItemId)],
)
return result.rows[0] || null
return /** @type {InventoryItemRow | null} */ (result.rows[0] || null)
}
/** @returns {Promise<InventoryItemRow | null>} */
export async function markInventoryItemDelivered(inventoryItemId, deliveredAt) {
return withTransaction(async (client) => {
await client.query(
@@ -111,6 +124,7 @@ export async function markInventoryItemDelivered(inventoryItemId, deliveredAt) {
})
}
/** @returns {Promise<InventoryItemRow | null>} */
export async function markInventoryItemConsumed(inventoryItemId, reason, consumedAt) {
return withTransaction(async (client) => {
await client.query(
@@ -139,6 +153,8 @@ export async function markInventoryItemConsumed(inventoryItemId, reason, consume
})
}
/** @returns {Promise<InventoryListQueryResult>} */
/** @param {InventoryListQueryInput} [queryInput] */
export async function listInventoryItems({
page = 1,
pageSize = 20,
@@ -146,7 +162,7 @@ export async function listInventoryItems({
credentialType = '',
status = '',
batchNo = '',
} = {}) {
} = /** @type {InventoryListQueryInput} */ ({})) {
const offset = (page - 1) * pageSize
const filters = []
const params = []
@@ -188,16 +204,18 @@ export async function listInventoryItems({
)
return {
items: itemsResult.rows,
items: /** @type {InventoryItemRow[]} */ (itemsResult.rows),
total: Number(totalResult.rows[0]?.total || 0),
}
}
/** @returns {Promise<InventorySkuSuggestionRow[]>} */
/** @param {InventorySkuSuggestionQueryInput} [queryInput] */
export async function listInventorySkuSuggestions({
credentialType = '',
keyword = '',
limit = 50,
} = {}) {
} = /** @type {InventorySkuSuggestionQueryInput} */ ({})) {
const filters = []
const params = []
@@ -238,9 +256,10 @@ export async function listInventorySkuSuggestions({
params,
)
return result.rows
return /** @type {InventorySkuSuggestionRow[]} */ (result.rows)
}
/** @param {InventoryCreateItemInput[]} rows */
export async function createInventoryItems(rows) {
let created = 0
@@ -284,6 +303,7 @@ export async function createInventoryItems(rows) {
return created
}
/** @returns {Promise<InventoryItemRow | null>} */
export async function releaseReservedInventoryItem(inventoryItemId, updatedAt) {
return withTransaction(async (client) => {
await client.query(
@@ -1,5 +1,11 @@
// @ts-check
import { query } from '../db/client.js'
/** @typedef {import('../types/repository-inputs.js').OrderItemReplaceInput} OrderItemReplaceInput */
/** @typedef {import('../types/repository-rows.js').OrderItemRow} OrderItemRow */
/** @returns {Promise<OrderItemRow[]>} */
export async function listOrderItemsByOrderId(orderId) {
const result = await query(
`
@@ -11,9 +17,11 @@ export async function listOrderItemsByOrderId(orderId) {
[Number(orderId)],
)
return result.rows
return /** @type {OrderItemRow[]} */ (result.rows)
}
/** @returns {Promise<OrderItemRow[]>} */
/** @param {OrderItemReplaceInput[]} items */
export async function replaceOrderItems(orderId, items) {
await query('DELETE FROM order_items WHERE order_id = $1', [Number(orderId)])
@@ -47,7 +55,8 @@ export async function replaceOrderItems(orderId, items) {
return listOrderItemsByOrderId(orderId)
}
/** @returns {Promise<OrderItemRow | null>} */
export async function getOrderItemById(orderItemId) {
const result = await query('SELECT * FROM order_items WHERE id = $1 LIMIT 1', [Number(orderItemId)])
return result.rows[0] || null
return /** @type {OrderItemRow | null} */ (result.rows[0] || null)
}
+22 -6
View File
@@ -1,5 +1,14 @@
// @ts-check
import { query } from '../db/client.js'
/** @typedef {import('../types/repository-inputs.js').OrderUpsertInput} OrderUpsertInput */
/** @typedef {import('../types/repository-inputs.js').OrderListQueryInput} OrderListQueryInput */
/** @typedef {import('../types/repository-rows.js').OrderListQueryResult} OrderListQueryResult */
/** @typedef {import('../types/repository-rows.js').OrderListRow} OrderListRow */
/** @typedef {import('../types/repository-rows.js').OrderRow} OrderRow */
/** @returns {Promise<OrderRow | null>} */
export async function findOrderByPlatformOrderId({ provider = 'agiso', platform, shopId = '', platformOrderId }) {
const result = await query(
`
@@ -11,9 +20,11 @@ export async function findOrderByPlatformOrderId({ provider = 'agiso', platform,
[provider, platform, shopId, platformOrderId],
)
return result.rows[0] || null
return /** @type {OrderRow | null} */ (result.rows[0] || null)
}
/** @returns {Promise<OrderRow | null>} */
/** @param {OrderUpsertInput} input */
export async function createOrder(input) {
const result = await query(
`
@@ -57,9 +68,11 @@ export async function createOrder(input) {
],
)
return result.rows[0] || null
return /** @type {OrderRow | null} */ (result.rows[0] || null)
}
/** @returns {Promise<OrderRow | null>} */
/** @param {OrderUpsertInput} input */
export async function updateOrder(orderId, input) {
const result = await query(
`
@@ -101,14 +114,17 @@ export async function updateOrder(orderId, input) {
],
)
return result.rows[0] || null
return /** @type {OrderRow | null} */ (result.rows[0] || null)
}
/** @returns {Promise<OrderRow | null>} */
export async function getOrderById(orderId) {
const result = await query('SELECT * FROM orders WHERE id = $1 LIMIT 1', [Number(orderId)])
return result.rows[0] || null
return /** @type {OrderRow | null} */ (result.rows[0] || null)
}
/** @returns {Promise<OrderListQueryResult>} */
/** @param {OrderListQueryInput} [queryInput] */
export async function listOrders({
page = 1,
pageSize = 20,
@@ -117,7 +133,7 @@ export async function listOrders({
skuCode = '',
dateFrom = '',
dateTo = '',
} = {}) {
} = /** @type {OrderListQueryInput} */ ({})) {
const offset = (page - 1) * pageSize
const filters = []
const params = []
@@ -166,7 +182,7 @@ export async function listOrders({
)
return {
items: itemsResult.rows,
items: /** @type {OrderListRow[]} */ (itemsResult.rows),
total: Number(totalResult.rows[0]?.total || 0),
}
}
@@ -1,5 +1,11 @@
// @ts-check
import { query } from '../db/client.js'
/** @typedef {import('../types/repository-rows.js').TaskInventoryBindingRow} TaskInventoryBindingRow */
/** @typedef {import('../types/repository-rows.js').TaskInventoryBindingSummaryRow} TaskInventoryBindingSummaryRow */
/** @returns {Promise<TaskInventoryBindingRow[]>} */
export async function listTaskInventoryBindingsByTaskId(taskId) {
const result = await query(
`
@@ -29,9 +35,10 @@ export async function listTaskInventoryBindingsByTaskId(taskId) {
[Number(taskId)],
)
return result.rows
return /** @type {TaskInventoryBindingRow[]} */ (result.rows)
}
/** @returns {Promise<TaskInventoryBindingRow | null>} */
export async function getTaskInventoryBindingById(bindingId) {
const result = await query(
`
@@ -61,9 +68,10 @@ export async function getTaskInventoryBindingById(bindingId) {
[Number(bindingId)],
)
return result.rows[0] || null
return /** @type {TaskInventoryBindingRow | null} */ (result.rows[0] || null)
}
/** @returns {Promise<TaskInventoryBindingSummaryRow[]>} */
export async function listTaskInventoryBindingSummariesByTaskIds(taskIds = []) {
const normalizedTaskIds = Array.from(new Set((Array.isArray(taskIds) ? taskIds : [])
.map((value) => Number(value))
@@ -89,5 +97,5 @@ export async function listTaskInventoryBindingSummariesByTaskIds(taskIds = []) {
[normalizedTaskIds],
)
return result.rows
return /** @type {TaskInventoryBindingSummaryRow[]} */ (result.rows)
}
+25 -5
View File
@@ -1,5 +1,14 @@
// @ts-check
import { query, withTransaction } from '../db/client.js'
/** @typedef {import('../types/repository-inputs.js').TaskCreateInput} TaskCreateInput */
/** @typedef {import('../types/repository-inputs.js').TaskListQueryInput} TaskListQueryInput */
/** @typedef {import('../types/repository-inputs.js').TaskTencentContextPatch} TaskTencentContextPatch */
/** @typedef {import('../types/repository-inputs.js').TaskUpdatePatch} TaskUpdatePatch */
/** @typedef {import('../types/repository-rows.js').TaskListQueryResult} TaskListQueryResult */
/** @typedef {import('../types/repository-rows.js').TaskRow} TaskRow */
const TASK_FIELDS = `
ft.*,
ct.id AS primary_claim_token_id,
@@ -52,6 +61,7 @@ function buildTaskSelect(extraFields = '') {
return `SELECT ${fieldSql} ${TASK_JOINS}`
}
/** @returns {Promise<TaskRow[]>} */
export async function listTasksByOrderId(orderId) {
const result = await query(
`${buildTaskSelect()}
@@ -59,9 +69,11 @@ export async function listTasksByOrderId(orderId) {
ORDER BY ft.id ASC`,
[Number(orderId)],
)
return result.rows
return /** @type {TaskRow[]} */ (result.rows)
}
/** @returns {Promise<TaskRow | null>} */
/** @param {TaskCreateInput} input */
export async function createTask(input) {
return withTransaction(async (client) => {
const taskResult = await client.query(
@@ -139,6 +151,8 @@ export async function createTask(input) {
})
}
/** @returns {Promise<TaskRow | null>} */
/** @param {TaskUpdatePatch} patch */
export async function updateTask(taskId, patch) {
const current = await getTaskById(taskId)
if (!current) {
@@ -212,10 +226,12 @@ export async function updateTask(taskId, patch) {
})
}
/** @returns {Promise<TaskRow | null>} */
export async function getTaskById(taskId) {
return getTaskByIdWithExecutor(query, taskId)
}
/** @returns {Promise<TaskRow | null>} */
export async function findTaskByClaimTokenId(claimTokenId) {
const result = await query(
`${buildTaskSelect()}
@@ -224,9 +240,11 @@ export async function findTaskByClaimTokenId(claimTokenId) {
LIMIT 1`,
[Number(claimTokenId)],
)
return result.rows[0] || null
return /** @type {TaskRow | null} */ (result.rows[0] || null)
}
/** @returns {Promise<TaskListQueryResult>} */
/** @param {TaskListQueryInput} [queryInput] */
export async function listTasks({
page = 1,
pageSize = 20,
@@ -237,7 +255,7 @@ export async function listTasks({
roleId = '',
dateFrom = '',
dateTo = '',
} = {}) {
} = /** @type {TaskListQueryInput} */ ({})) {
const offset = (page - 1) * pageSize
const filters = []
const params = []
@@ -301,11 +319,12 @@ export async function listTasks({
)
return {
items: itemsResult.rows,
items: /** @type {TaskRow[]} */ (itemsResult.rows),
total: Number(totalResult.rows[0]?.total || 0),
}
}
/** @param {TaskTencentContextPatch} patch */
async function upsertTencentBrowserContextWithClient(client, taskId, patch = {}, timestamp) {
const currentResult = await client.query(
'SELECT * FROM tencent_browser_contexts WHERE task_id = $1 LIMIT 1',
@@ -399,6 +418,7 @@ async function upsertTencentBrowserContextWithClient(client, taskId, patch = {},
)
}
/** @returns {Promise<TaskRow | null>} */
async function getTaskByIdWithExecutor(executor, taskId) {
const result = await executor(
`${buildTaskSelect()}
@@ -406,7 +426,7 @@ async function getTaskByIdWithExecutor(executor, taskId) {
LIMIT 1`,
[Number(taskId)],
)
return result.rows[0] || null
return /** @type {TaskRow | null} */ (result.rows[0] || null)
}
function containsTencentPatch(patch = {}) {
@@ -1,5 +1,15 @@
// @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(
`
@@ -39,9 +49,11 @@ export async function createWebhookEvent(input) {
],
)
return result.rows[0] || null
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) {
@@ -62,14 +74,17 @@ export async function updateWebhookEvent(eventId, patch) {
[Boolean(next.processed), next.process_error || '', next.related_order_id || null, Number(eventId)],
)
return result.rows[0] || null
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 result.rows[0] || null
return /** @type {WebhookEventRow | null} */ (result.rows[0] || null)
}
/** @returns {Promise<WebhookEventListQueryResult>} */
/** @param {WebhookEventListQueryInput} [queryInput] */
export async function listWebhookEvents({
page = 1,
pageSize = 20,
@@ -80,7 +95,7 @@ export async function listWebhookEvents({
relatedOrderId = '',
dateFrom = '',
dateTo = '',
} = {}) {
} = /** @type {WebhookEventListQueryInput} */ ({})) {
const offset = (page - 1) * pageSize
const filters = []
const params = []
@@ -137,11 +152,12 @@ export async function listWebhookEvents({
)
return {
items: itemsResult.rows,
items: /** @type {WebhookEventRow[]} */ (itemsResult.rows),
total: Number(totalResult.rows[0]?.total || 0),
}
}
/** @returns {Promise<WebhookEventRow[]>} */
export async function listWebhookEventsByOrderId(orderId) {
const result = await query(
`
@@ -153,5 +169,5 @@ export async function listWebhookEventsByOrderId(orderId) {
[Number(orderId)],
)
return result.rows
return /** @type {WebhookEventRow[]} */ (result.rows)
}