后端迁移平台配置底座
This commit is contained in:
+15
-27
@@ -1,6 +1,6 @@
|
||||
// @ts-check
|
||||
type JsonObject = Record<string, any>
|
||||
|
||||
export function pickFirstNonEmpty(values) {
|
||||
export function pickFirstNonEmpty(values: unknown[]) {
|
||||
for (const value of values) {
|
||||
const normalized = String(value || "").trim();
|
||||
if (normalized) {
|
||||
@@ -11,31 +11,23 @@ export function pickFirstNonEmpty(values) {
|
||||
return "";
|
||||
}
|
||||
|
||||
export function isPlainObject(value) {
|
||||
export function isPlainObject(value: unknown): value is JsonObject {
|
||||
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
||||
}
|
||||
|
||||
export function resolveKuaishouEticketAdminContext(payload = {}, options = {}) {
|
||||
const savedSource = /** @type {Record<string, unknown>} */ (
|
||||
options.savedSource || {}
|
||||
);
|
||||
export function resolveKuaishouEticketAdminContext(payload: JsonObject = {}, options: JsonObject = {}) {
|
||||
const savedSource = options.savedSource || {};
|
||||
const findShopConfig =
|
||||
/** @type {(shopId: string, source: Record<string, unknown>) => unknown} */ (
|
||||
options.findShopConfig || (() => null)
|
||||
);
|
||||
(options.findShopConfig || (() => null)) as (shopId: string, source: JsonObject) => unknown;
|
||||
const getFirstAvailableShop =
|
||||
/** @type {(source: Record<string, unknown>) => unknown} */ (
|
||||
options.getFirstAvailableShop || (() => null)
|
||||
);
|
||||
(options.getFirstAvailableShop || (() => null)) as (source: JsonObject) => unknown;
|
||||
const defaultBaseUrl = String(
|
||||
options.defaultBaseUrl || "https://s.kwaixiaodian.com"
|
||||
).trim();
|
||||
const requestedShopId = String(payload.shopId || "").trim();
|
||||
const configuredShop = /** @type {Record<string, unknown> | null} */ (
|
||||
requestedShopId
|
||||
const configuredShop = (requestedShopId
|
||||
? findShopConfig(requestedShopId, savedSource)
|
||||
: getFirstAvailableShop(savedSource)
|
||||
);
|
||||
: getFirstAvailableShop(savedSource)) as JsonObject | null;
|
||||
|
||||
return {
|
||||
baseUrl: pickFirstNonEmpty([
|
||||
@@ -52,18 +44,14 @@ export function resolveKuaishouEticketAdminContext(payload = {}, options = {}) {
|
||||
import { getCloudtentaclesSourceByKey } from "../../platforms/cloudtentacles/source-config-service.js";
|
||||
import { getCloudtentaclesSessionStateByKey } from "../../platforms/cloudtentacles/session-state-service.js";
|
||||
|
||||
export function resolveCloudtentaclesAdminContext(payload = {}, options = {}) {
|
||||
export function resolveCloudtentaclesAdminContext(payload: JsonObject = {}, options: JsonObject = {}) {
|
||||
const sourceKey = String(
|
||||
payload.sourceKey || options.sourceKey || "default"
|
||||
).trim();
|
||||
const savedSource = /** @type {Record<string, unknown>} */ (
|
||||
options.savedSource || getCloudtentaclesSourceByKey(sourceKey) || {}
|
||||
);
|
||||
const persistedSession = /** @type {Record<string, unknown>} */ (
|
||||
options.persistedSession ||
|
||||
const savedSource = options.savedSource || getCloudtentaclesSourceByKey(sourceKey) || {};
|
||||
const persistedSession = options.persistedSession ||
|
||||
getCloudtentaclesSessionStateByKey(sourceKey) ||
|
||||
{}
|
||||
);
|
||||
{};
|
||||
const defaultBaseUrl = String(
|
||||
options.defaultBaseUrl || "https://123.207.217.176"
|
||||
).trim();
|
||||
@@ -89,8 +77,8 @@ export function resolveCloudtentaclesAdminContext(payload = {}, options = {}) {
|
||||
}
|
||||
|
||||
export function hasCloudtentaclesCredentialContextChanged(
|
||||
current = {},
|
||||
next = {}
|
||||
current: JsonObject = {},
|
||||
next: JsonObject = {}
|
||||
) {
|
||||
return (
|
||||
String(current.baseUrl || "").trim() !==
|
||||
+9
-9
@@ -1,9 +1,9 @@
|
||||
// @ts-check
|
||||
|
||||
import { normalizeAgisoMessageTemplate } from '../../platforms/agiso/xianyu/message-service.js'
|
||||
import { maskSecret } from './mappers.js'
|
||||
|
||||
export function mapAdminAgisoMessagingDefaults(defaults = {}) {
|
||||
type JsonObject = Record<string, any>
|
||||
|
||||
export function mapAdminAgisoMessagingDefaults(defaults: JsonObject = {}) {
|
||||
return {
|
||||
messageTemplate: normalizeAgisoMessageTemplate(String(defaults.messageTemplate || '').trim()),
|
||||
autoDeliveryMessageTemplate: normalizeAgisoMessageTemplate(
|
||||
@@ -12,7 +12,7 @@ export function mapAdminAgisoMessagingDefaults(defaults = {}) {
|
||||
}
|
||||
}
|
||||
|
||||
export function mapAdminAgisoShopConfigItem(shopId, config = {}) {
|
||||
export function mapAdminAgisoShopConfigItem(shopId: unknown, config: JsonObject = {}) {
|
||||
return {
|
||||
shopId,
|
||||
shopName: String(config.shopName || '').trim(),
|
||||
@@ -29,7 +29,7 @@ export function mapAdminAgisoShopConfigItem(shopId, config = {}) {
|
||||
}
|
||||
}
|
||||
|
||||
export function applyOptionalStringField(target, key, source) {
|
||||
export function applyOptionalStringField(target: JsonObject, key: string, source: JsonObject) {
|
||||
if (!source || typeof source[key] !== 'string') {
|
||||
return
|
||||
}
|
||||
@@ -43,7 +43,7 @@ export function applyOptionalStringField(target, key, source) {
|
||||
delete target[key]
|
||||
}
|
||||
|
||||
export function mapAdminFulfillmentBindingConfigItem(item) {
|
||||
export function mapAdminFulfillmentBindingConfigItem(item: JsonObject) {
|
||||
const match = item?.match || {}
|
||||
return {
|
||||
provider: String(item?.provider || '').trim(),
|
||||
@@ -65,7 +65,7 @@ export function mapAdminFulfillmentBindingConfigItem(item) {
|
||||
}
|
||||
}
|
||||
|
||||
export function matchesObservedProduct(binding, observed) {
|
||||
export function matchesObservedProduct(binding: JsonObject, observed: JsonObject) {
|
||||
const provider = String(binding?.provider || '').trim()
|
||||
const platform = String(binding?.platform || '').trim()
|
||||
const shopId = String(binding?.shopId || '').trim()
|
||||
@@ -93,11 +93,11 @@ export function matchesObservedProduct(binding, observed) {
|
||||
)
|
||||
}
|
||||
|
||||
export function findMatchingObservedBinding(bindings, observed) {
|
||||
export function findMatchingObservedBinding(bindings: JsonObject[], observed: JsonObject) {
|
||||
return (Array.isArray(bindings) ? bindings : []).find((binding) => matchesObservedProduct(binding, observed)) || null
|
||||
}
|
||||
|
||||
export function mapAdminObservedProductItem(item, bindings = []) {
|
||||
export function mapAdminObservedProductItem(item: JsonObject, bindings: JsonObject[] = []) {
|
||||
const matchedBinding = findMatchingObservedBinding(bindings, item)
|
||||
|
||||
return {
|
||||
+9
-9
@@ -1,6 +1,6 @@
|
||||
// @ts-check
|
||||
type JsonObject = Record<string, any>
|
||||
|
||||
export function maskSecret(value) {
|
||||
export function maskSecret(value: unknown) {
|
||||
const normalized = String(value || "").trim();
|
||||
if (!normalized) {
|
||||
return "";
|
||||
@@ -13,7 +13,7 @@ export function maskSecret(value) {
|
||||
return `${normalized.slice(0, 6)}****${normalized.slice(-6)}`;
|
||||
}
|
||||
|
||||
export function maskPhone(value) {
|
||||
export function maskPhone(value: unknown) {
|
||||
const normalized = String(value || "").trim();
|
||||
if (!normalized) {
|
||||
return "";
|
||||
@@ -26,7 +26,7 @@ export function maskPhone(value) {
|
||||
return `${normalized.slice(0, 3)}****${normalized.slice(-4)}`;
|
||||
}
|
||||
|
||||
export function mapAdminKuaishouEticketShopItem(item = {}) {
|
||||
export function mapAdminKuaishouEticketShopItem(item: JsonObject = {}) {
|
||||
return {
|
||||
shopId: String(item.shopId || "").trim(),
|
||||
kshopName: String(item.kshopName || "").trim(),
|
||||
@@ -38,7 +38,7 @@ export function mapAdminKuaishouEticketShopItem(item = {}) {
|
||||
};
|
||||
}
|
||||
|
||||
export function mapAdminKuaishouEticketSourceConfig(config = {}, shops = []) {
|
||||
export function mapAdminKuaishouEticketSourceConfig(config: JsonObject = {}, shops: JsonObject[] = []) {
|
||||
return {
|
||||
enabled: config.enabled !== false,
|
||||
baseUrl: String(config.baseUrl || "").trim(),
|
||||
@@ -46,7 +46,7 @@ export function mapAdminKuaishouEticketSourceConfig(config = {}, shops = []) {
|
||||
};
|
||||
}
|
||||
|
||||
export function mapAdminCloudtentaclesSourceConfig(config = {}) {
|
||||
export function mapAdminCloudtentaclesSourceConfig(config: JsonObject = {}) {
|
||||
return {
|
||||
key: String(config.key || "").trim(),
|
||||
label: String(config.label || "").trim(),
|
||||
@@ -60,7 +60,7 @@ export function mapAdminCloudtentaclesSourceConfig(config = {}) {
|
||||
};
|
||||
}
|
||||
|
||||
export function mapAdminCloudtentaclesSession(session = {}) {
|
||||
export function mapAdminCloudtentaclesSession(session: JsonObject = {}) {
|
||||
return {
|
||||
token: String(session.token || "").trim(),
|
||||
tokenMasked: maskSecret(session.token),
|
||||
@@ -74,7 +74,7 @@ export function mapAdminCloudtentaclesSession(session = {}) {
|
||||
};
|
||||
}
|
||||
|
||||
export function mapAdminKuaishouCloudFulfillmentItem(item = {}) {
|
||||
export function mapAdminKuaishouCloudFulfillmentItem(item: JsonObject = {}) {
|
||||
return {
|
||||
id: String(item.id || "").trim(),
|
||||
enabled: item.enabled !== false,
|
||||
@@ -103,7 +103,7 @@ export function mapAdminKuaishouCloudFulfillmentItem(item = {}) {
|
||||
};
|
||||
}
|
||||
|
||||
export function mapAdminKuaishouCloudFulfillmentSource(config = {}) {
|
||||
export function mapAdminKuaishouCloudFulfillmentSource(config: JsonObject = {}) {
|
||||
return {
|
||||
enabled: config.enabled !== false,
|
||||
items: (Array.isArray(config.items) ? config.items : []).map((item) =>
|
||||
+10
-10
@@ -1,10 +1,10 @@
|
||||
// @ts-check
|
||||
|
||||
import { createHttpError } from '../../../utils/http.js'
|
||||
import { normalizeProductName } from '../../order/product-match-service.js'
|
||||
import { isPlainObject } from './context.js'
|
||||
|
||||
export function assertAdminFulfillmentBindingsInput(bindings) {
|
||||
type JsonObject = Record<string, any>
|
||||
|
||||
export function assertAdminFulfillmentBindingsInput(bindings: unknown) {
|
||||
if (Array.isArray(bindings)) {
|
||||
return
|
||||
}
|
||||
@@ -16,8 +16,8 @@ export function assertAdminFulfillmentBindingsInput(bindings) {
|
||||
}
|
||||
|
||||
export function normalizeAdminFulfillmentBindingItem(
|
||||
rawBinding,
|
||||
options = {},
|
||||
rawBinding: unknown,
|
||||
options: JsonObject = {},
|
||||
) {
|
||||
const index = Number(options.index || 0)
|
||||
if (!isPlainObject(rawBinding)) {
|
||||
@@ -87,16 +87,16 @@ export function buildAdminFulfillmentBindingUniqueKey(binding) {
|
||||
}
|
||||
|
||||
export async function validateAdminFulfillmentBindingConfigs(
|
||||
bindings,
|
||||
options = {},
|
||||
bindings: JsonObject[],
|
||||
options: JsonObject = {},
|
||||
) {
|
||||
assertAdminFulfillmentBindingsInput(bindings)
|
||||
|
||||
const getFulfillmentProfileByKey = /** @type {(profileKey: string) => Promise<unknown>} */ (
|
||||
const getFulfillmentProfileByKey = (
|
||||
options.getFulfillmentProfileByKey || (async () => null)
|
||||
)
|
||||
) as (profileKey: string) => Promise<unknown>
|
||||
const seenKeys = new Set()
|
||||
const normalizedBindings = []
|
||||
const normalizedBindings: JsonObject[] = []
|
||||
|
||||
for (const [index, rawBinding] of bindings.entries()) {
|
||||
const normalized = normalizeAdminFulfillmentBindingItem(rawBinding, { index })
|
||||
@@ -578,6 +578,17 @@
|
||||
- `npm run typecheck`
|
||||
- `npm run build`
|
||||
- `npm test` 共 139 个用例通过
|
||||
135. 后台平台配置底座模块迁移到 `.ts`:
|
||||
- `src/services/admin/platform-config/context.ts`
|
||||
- `src/services/admin/platform-config/domain.ts`
|
||||
- `src/services/admin/platform-config/mappers.ts`
|
||||
- `src/services/admin/platform-config/validation.ts`
|
||||
136. 后台平台配置上下文解析、展示映射、敏感信息脱敏、履约绑定校验与重复规则检测已进入 TS 编译链路;动态配置对象补齐通用类型,`isPlainObject` 改为类型守卫
|
||||
137. Docker 内验证通过:
|
||||
- `src/services/admin/platform-config/context.test.js`、`domain.test.js`、`mappers.test.js`、`validation.test.js` 共 23 个用例通过
|
||||
- `npm run typecheck`
|
||||
- `npm run build`
|
||||
- `npm test` 共 139 个用例通过
|
||||
|
||||
## 下一步建议
|
||||
|
||||
|
||||
Reference in New Issue
Block a user