后端迁移云触手请求与目录服务

This commit is contained in:
yml
2026-05-21 16:23:04 +08:00
parent ce6a6af820
commit 98781f484c
5 changed files with 68 additions and 39 deletions
@@ -1,10 +1,10 @@
// @ts-check
import { createHttpError } from '../../../utils/http.js'
import { cloudtentaclesRequest } from './http-client.js'
import { resolveCloudtentaclesConfig } from './shared.js'
export async function getCloudtentaclesAsset(payload = {}) {
type JsonObject = Record<string, any>
export async function getCloudtentaclesAsset(payload: JsonObject = {}) {
const token = requireToken(payload.token, 'cloudtentacles 余额查询缺少 token', 'cloudtentacles_asset_missing_token')
const config = resolveCloudtentaclesConfig(payload)
@@ -24,7 +24,7 @@ export async function getCloudtentaclesAsset(payload = {}) {
}
}
export async function getCloudtentaclesCategories(payload = {}) {
export async function getCloudtentaclesCategories(payload: JsonObject = {}) {
const token = requireToken(payload.token, 'cloudtentacles 分类查询缺少 token', 'cloudtentacles_categories_missing_token')
const config = resolveCloudtentaclesConfig(payload)
@@ -47,7 +47,7 @@ export async function getCloudtentaclesCategories(payload = {}) {
}
}
export async function listCloudtentaclesSku(payload = {}) {
export async function listCloudtentaclesSku(payload: JsonObject = {}) {
const token = requireToken(payload.token, 'cloudtentacles SKU 列表查询缺少 token', 'cloudtentacles_sku_list_missing_token')
const config = resolveCloudtentaclesConfig(payload)
@@ -70,7 +70,7 @@ export async function listCloudtentaclesSku(payload = {}) {
}
}
export async function buyCloudtentaclesSku(payload = {}) {
export async function buyCloudtentaclesSku(payload: JsonObject = {}) {
const token = requireToken(payload.token, 'cloudtentacles 购买 SKU 缺少 token', 'cloudtentacles_sku_buy_missing_token')
const skuId = requireId(payload.id, 'cloudtentacles 购买 SKU 缺少商品 id', 'cloudtentacles_sku_buy_missing_id')
const count = requireCount(payload.count)
@@ -96,7 +96,7 @@ export async function buyCloudtentaclesSku(payload = {}) {
}
}
export async function useCloudtentaclesSku(payload = {}) {
export async function useCloudtentaclesSku(payload: JsonObject = {}) {
const token = requireToken(payload.token, 'cloudtentacles 发货缺少 token', 'cloudtentacles_sku_use_missing_token')
const skuId = requireId(payload.id, 'cloudtentacles 发货缺少商品 id', 'cloudtentacles_sku_use_missing_id')
const virtualNumberId = requireId(
@@ -140,7 +140,7 @@ export async function useCloudtentaclesSku(payload = {}) {
}
}
function mapCategoryItem(item) {
function mapCategoryItem(item: unknown) {
const source = isPlainObject(item) ? item : {}
return {
@@ -158,7 +158,7 @@ function mapCategoryItem(item) {
}
}
function mapSkuItem(item) {
function mapSkuItem(item: unknown) {
const source = isPlainObject(item) ? item : {}
return {
@@ -177,7 +177,7 @@ function mapSkuItem(item) {
}
}
function requireToken(value, message, errorCode) {
function requireToken(value: unknown, message: string, errorCode: string) {
const token = String(value || '').trim()
if (!token) {
throw createHttpError(message, {
@@ -189,7 +189,7 @@ function requireToken(value, message, errorCode) {
return token
}
function requireId(value, message, errorCode) {
function requireId(value: unknown, message: string, errorCode: string) {
const id = Number(value)
if (!Number.isInteger(id) || id <= 0) {
throw createHttpError(message, {
@@ -201,7 +201,7 @@ function requireId(value, message, errorCode) {
return id
}
function requireCount(value) {
function requireCount(value: unknown) {
const count = Number(value)
if (!Number.isInteger(count) || count <= 0) {
throw createHttpError('cloudtentacles 购买数量无效', {
@@ -213,6 +213,6 @@ function requireCount(value) {
return count
}
function isPlainObject(value) {
function isPlainObject(value: unknown): value is JsonObject {
return Boolean(value) && typeof value === 'object' && !Array.isArray(value)
}
@@ -1,5 +1,3 @@
// @ts-check
import http from 'node:http'
import https from 'node:https'
@@ -8,9 +6,21 @@ import { logInfo } from '../../../utils/logger.js'
import { notifyCloudtentaclesAuthExpired } from '../../notification/domain-notifications.js'
import { buildCloudtentaclesHeaders, buildCloudtentaclesUrl, resolveCloudtentaclesConfig } from './shared.js'
export async function cloudtentaclesRequest(pathname, options = {}) {
type JsonObject = Record<string, any>
type HeaderAdapter = {
get(name: unknown): string | null
}
type NodeHttpResponse = {
ok: boolean
status: number
headers: HeaderAdapter
bodyText: string
}
export async function cloudtentaclesRequest(pathname: unknown, options: JsonObject = {}) {
const normalizedPathname = String(pathname || '').trim()
const config = resolveCloudtentaclesConfig(options)
const url = buildCloudtentaclesUrl(config.baseUrl, pathname, options.searchParams)
const url = buildCloudtentaclesUrl(config.baseUrl, normalizedPathname, options.searchParams)
const timeoutMs = Number(options.timeoutMs || config.timeoutMs || 5000)
const controller = new AbortController()
const timer = setTimeout(() => controller.abort(), timeoutMs)
@@ -48,7 +58,7 @@ export async function cloudtentaclesRequest(pathname, options = {}) {
if (statusCode === 401 || isCloudtentaclesExpiredMessage(message)) {
await notifyCloudtentaclesAuthExpired({
pathname,
pathname: normalizedPathname,
errorCode,
message,
})
@@ -62,7 +72,7 @@ export async function cloudtentaclesRequest(pathname, options = {}) {
logInfo('[cloudtentacles/http]', '请求完成', {
method,
pathname,
pathname: normalizedPathname,
status: response.status,
})
@@ -86,12 +96,12 @@ export async function cloudtentaclesRequest(pathname, options = {}) {
}
}
function isCloudtentaclesExpiredMessage(message) {
function isCloudtentaclesExpiredMessage(message: unknown) {
const normalized = String(message || '').trim().toLowerCase()
return normalized.includes('expired') || normalized.includes('过期') || normalized.includes('失效')
}
function inferContentType(body) {
function inferContentType(body: unknown) {
if (body == null) {
return ''
}
@@ -103,7 +113,7 @@ function inferContentType(body) {
return 'application/json'
}
function normalizeRequestBody(body, contentType) {
function normalizeRequestBody(body: unknown, contentType: unknown) {
if (body == null) {
return undefined
}
@@ -119,7 +129,7 @@ function normalizeRequestBody(body, contentType) {
return String(body)
}
function tryParseJson(text) {
function tryParseJson(text: string) {
try {
return JSON.parse(text)
} catch {
@@ -127,7 +137,15 @@ function tryParseJson(text) {
}
}
async function requestViaNodeHttp(url, { method, headers, body, signal }) {
async function requestViaNodeHttp(
url: URL,
{ method, headers, body, signal }: {
method: string
headers: JsonObject
body?: string | URLSearchParams
signal?: AbortSignal
},
): Promise<NodeHttpResponse> {
const isHttps = url.protocol === 'https:'
const transport = isHttps ? https : http
@@ -137,7 +155,7 @@ async function requestViaNodeHttp(url, { method, headers, body, signal }) {
headers,
rejectUnauthorized: false,
}, (response) => {
const chunks = []
const chunks: Buffer[] = []
response.on('data', (chunk) => {
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk))
@@ -178,7 +196,7 @@ async function requestViaNodeHttp(url, { method, headers, body, signal }) {
})
}
function createHeaderAdapter(headers) {
function createHeaderAdapter(headers: http.IncomingHttpHeaders): HeaderAdapter {
const normalized = new Map()
for (const [key, value] of Object.entries(headers || {})) {
@@ -193,7 +211,7 @@ function createHeaderAdapter(headers) {
}
return {
get(name) {
get(name: unknown) {
return normalized.get(String(name || '').toLowerCase()) || null
},
}
@@ -1,10 +1,10 @@
// @ts-check
import { createHttpError } from '../../../utils/http.js'
import { cloudtentaclesRequest } from './http-client.js'
import { resolveCloudtentaclesConfig } from './shared.js'
export async function getCloudtentaclesKnapsack(payload = {}) {
type JsonObject = Record<string, any>
export async function getCloudtentaclesKnapsack(payload: JsonObject = {}) {
const token = String(payload.token || '').trim()
if (!token) {
throw createHttpError('cloudtentacles 背包查询缺少 token', {
@@ -33,7 +33,7 @@ export async function getCloudtentaclesKnapsack(payload = {}) {
}
}
function mapKnapsackItem(item) {
function mapKnapsackItem(item: unknown) {
const source = isPlainObject(item) ? item : {}
return {
@@ -48,6 +48,6 @@ function mapKnapsackItem(item) {
}
}
function isPlainObject(value) {
function isPlainObject(value: unknown): value is JsonObject {
return Boolean(value) && typeof value === 'object' && !Array.isArray(value)
}
@@ -1,12 +1,12 @@
// @ts-check
import { createHttpError } from '../../../utils/http.js'
import { logInfo } from '../../../utils/logger.js'
import { encryptCloudtentaclesPayload, md5CloudtentaclesPassword } from './crypto-service.js'
import { cloudtentaclesRequest } from './http-client.js'
import { resolveCloudtentaclesConfig } from './shared.js'
export async function sendCloudtentaclesSmsCode(payload = {}) {
type JsonObject = Record<string, any>
export async function sendCloudtentaclesSmsCode(payload: JsonObject = {}) {
const username = String(payload.username || '').trim()
const phone = String(payload.phone || '').trim()
@@ -56,7 +56,7 @@ export async function sendCloudtentaclesSmsCode(payload = {}) {
}
}
export async function loginCloudtentaclesSession(payload = {}) {
export async function loginCloudtentaclesSession(payload: JsonObject = {}) {
const username = String(payload.username || '').trim()
const password = String(payload.password || '').trim()
const phone = String(payload.phone || '').trim()
@@ -131,7 +131,7 @@ export async function loginCloudtentaclesSession(payload = {}) {
}
}
export async function validateCloudtentaclesSession(payload = {}) {
export async function validateCloudtentaclesSession(payload: JsonObject = {}) {
const token = String(payload.token || '').trim()
if (!token) {
@@ -181,7 +181,7 @@ export async function validateCloudtentaclesSession(payload = {}) {
}
}
function maskPhone(phone) {
function maskPhone(phone: unknown) {
const normalized = String(phone || '').trim()
if (normalized.length < 7) {
return normalized
@@ -190,6 +190,6 @@ function maskPhone(phone) {
return `${normalized.slice(0, 3)}****${normalized.slice(-4)}`
}
function isPlainObject(value) {
function isPlainObject(value: unknown): value is JsonObject {
return Boolean(value) && typeof value === 'object' && !Array.isArray(value)
}