后端迁移平台配置读写辅助

This commit is contained in:
yml
2026-05-21 16:06:45 +08:00
parent 38b0bf8ba5
commit 381ac44472
4 changed files with 42 additions and 29 deletions
@@ -1,11 +1,11 @@
// @ts-check
import { createHttpError } from '../../../utils/http.js'
import { formatFenToAmount } from '../../../utils/money.js'
import { isPlainObject, pickFirstNonEmpty } from './context.js'
import { mapAdminObservedProductItem } from './domain.js'
export function normalizeFulfillmentLookupPayload(payload = {}) {
type JsonObject = Record<string, any>
export function normalizeFulfillmentLookupPayload(payload: JsonObject = {}) {
const provider = String(payload.provider || 'agiso').trim() || 'agiso'
const platform = String(payload.platform || 'xianyu').trim() || 'xianyu'
const shopId = String(payload.shopId || '').trim()
@@ -35,7 +35,7 @@ export function normalizeFulfillmentLookupPayload(payload = {}) {
return { provider, platform, shopId, platformOrderId }
}
export function resolveFulfillmentLookupDetail(detailResult, platformOrderId) {
export function resolveFulfillmentLookupDetail(detailResult: JsonObject, platformOrderId: unknown) {
const detail = isPlainObject(detailResult?.parsed) ? detailResult.parsed : {}
const items = Array.isArray(detail.items) ? detail.items : []
@@ -66,10 +66,19 @@ export function buildFulfillmentLookupResult({
platform = '',
shopId = '',
platformOrderId = '',
detail = /** @type {Record<string, unknown>} */ ({}),
detailResult = /** @type {Record<string, unknown>} */ ({}),
detail = {},
detailResult = {},
bindings = [],
fallbackShopName = '',
}: {
provider?: string
platform?: string
shopId?: string
platformOrderId?: string
detail?: JsonObject
detailResult?: JsonObject
bindings?: JsonObject[]
fallbackShopName?: string
} = {}) {
const resolvedShopName = pickFirstNonEmpty([detail.shopName, fallbackShopName])
const items = Array.isArray(detail.items) ? detail.items : []
@@ -1,8 +1,8 @@
// @ts-check
import { query } from '../../../db/client.js'
import { mapAdminObservedProductItem } from './domain.js'
type JsonObject = Record<string, any>
export const ADMIN_OBSERVED_PRODUCTS_QUERY = `
SELECT
o.provider,
@@ -31,7 +31,7 @@ export const ADMIN_OBSERVED_PRODUCTS_QUERY = `
LIMIT 200
`
export function mapAdminObservedProductRow(row = {}) {
export function mapAdminObservedProductRow(row: JsonObject = {}) {
return {
provider: String(row.provider || '').trim(),
platform: String(row.platform || '').trim(),
@@ -45,10 +45,8 @@ export function mapAdminObservedProductRow(row = {}) {
}
}
export async function listAdminObservedProducts(bindings = [], options = {}) {
const queryImpl = /** @type {(sql: string) => Promise<{ rows: Array<Record<string, unknown>> }>} */ (
options.query || query
)
export async function listAdminObservedProducts(bindings: JsonObject[] = [], options: JsonObject = {}) {
const queryImpl = (options.query || query) as (sql: string) => Promise<{ rows: JsonObject[] }>
const rowsResult = await queryImpl(ADMIN_OBSERVED_PRODUCTS_QUERY)
return rowsResult.rows.map((row) => mapAdminObservedProductItem(mapAdminObservedProductRow(row), bindings))
}
@@ -1,14 +1,14 @@
// @ts-check
import { applyOptionalStringField } from "./domain.js";
export function buildAdminAgisoShopConfigUpdate(item, current = {}) {
type JsonObject = Record<string, any>
export function buildAdminAgisoShopConfigUpdate(item: JsonObject, current: JsonObject = {}) {
const shopId = String(item?.shopId || "").trim();
if (!shopId) {
return null;
}
const next = /** @type {Record<string, unknown>} */ ({ ...current });
const next: JsonObject = { ...current };
const shopName = String(item?.shopName || "").trim();
const accessToken = String(item?.accessToken || "").trim();
const messageTemplate = String(item?.messageTemplate || "").trim();
@@ -58,20 +58,16 @@ export function buildAdminAgisoShopConfigUpdate(item, current = {}) {
}
export function buildAdminAgisoMessagingSavePayload(
payload = {},
options = {}
payload: JsonObject = {},
options: JsonObject = {}
) {
const rawItems = Array.isArray(payload.shops) ? payload.shops : [];
const currentDefaults = /** @type {Record<string, unknown>} */ (
options.currentDefaults || {}
);
const currentMap = /** @type {Record<string, Record<string, unknown>>} */ (
options.currentMap || {}
);
const nextDefaults = /** @type {Record<string, unknown>} */ ({
const currentDefaults: JsonObject = options.currentDefaults || {};
const currentMap: Record<string, JsonObject> = options.currentMap || {};
const nextDefaults: JsonObject = {
...currentDefaults,
});
const nextMap = /** @type {Record<string, Record<string, unknown>>} */ ({});
};
const nextMap: Record<string, JsonObject> = {};
applyOptionalStringField(nextDefaults, "messageTemplate", payload.defaults);
applyOptionalStringField(
@@ -103,7 +99,7 @@ export function buildAdminAgisoMessagingSavePayload(
};
}
export function normalizeAdminCloudtentaclesSourceConfigPayload(payload = {}) {
export function normalizeAdminCloudtentaclesSourceConfigPayload(payload: JsonObject = {}) {
const sourceKey =
String(payload.sourceKey || payload.key || "").trim() || "default";
return {
+10
View File
@@ -589,6 +589,16 @@
- `npm run typecheck`
- `npm run build`
- `npm test` 共 139 个用例通过
138. 后台平台配置观察 / 查询 / 写入辅助模块迁移到 `.ts`
- `src/services/admin/platform-config/observed-products.ts`
- `src/services/admin/platform-config/fulfillment.ts`
- `src/services/admin/platform-config/writes.ts`
139. 后台观察商品列表、履约手动查询结果组装、Agiso 店铺消息配置写入与 Cloudtentacles 来源配置归一化已进入 TS 编译链路;查询依赖、payload 与配置 map 补齐动态对象类型
140. Docker 内验证通过:
- `src/services/admin/platform-config/observed-products.test.js``fulfillment.test.js``writes.test.js` 共 8 个用例通过
- `npm run typecheck`
- `npm run build`
- `npm test` 共 139 个用例通过
## 下一步建议