feat(cloudtentacles): 后端 Admin 层多账号支持 - admin-service/context/routes/types 改造

This commit is contained in:
yml
2026-05-20 00:35:19 +08:00
parent e812ea2cc4
commit f6acc0b9de
9 changed files with 1386 additions and 839 deletions
File diff suppressed because it is too large Load Diff
@@ -1,29 +1,33 @@
// @ts-check // @ts-check
import { import {
getCloudtentaclesSourceConfig, getCloudtentaclesSourceByKey,
getCloudtentaclesSourcesFilePath, getCloudtentaclesSourcesFilePath,
saveCloudtentaclesSourceConfig, listCloudtentaclesSources,
} from '../../platforms/cloudtentacles/source-config-service.js' saveCloudtentaclesSourceByKey,
saveCloudtentaclesSourcesList,
deleteCloudtentaclesSourceByKey,
} from "../../platforms/cloudtentacles/source-config-service.js";
import { import {
clearCloudtentaclesSessionState, clearCloudtentaclesSessionStateByKey,
getCloudtentaclesSessionFilePath, getCloudtentaclesSessionFilePath,
getCloudtentaclesSessionState, getCloudtentaclesSessionStateByKey,
saveCloudtentaclesSessionState, saveCloudtentaclesSessionStateByKey,
} from '../../platforms/cloudtentacles/session-state-service.js' getAllCloudtentaclesSessionStates,
} from "../../platforms/cloudtentacles/session-state-service.js";
import { import {
loginCloudtentaclesSession, loginCloudtentaclesSession,
sendCloudtentaclesSmsCode, sendCloudtentaclesSmsCode,
validateCloudtentaclesSession, validateCloudtentaclesSession,
} from '../../platforms/cloudtentacles/session-service.js' } from "../../platforms/cloudtentacles/session-service.js";
import { import {
buyCloudtentaclesSku, buyCloudtentaclesSku,
getCloudtentaclesAsset, getCloudtentaclesAsset,
getCloudtentaclesCategories, getCloudtentaclesCategories,
listCloudtentaclesSku, listCloudtentaclesSku,
useCloudtentaclesSku, useCloudtentaclesSku,
} from '../../platforms/cloudtentacles/catalog-service.js' } from "../../platforms/cloudtentacles/catalog-service.js";
import { getCloudtentaclesKnapsack } from '../../platforms/cloudtentacles/knapsack-service.js' import { getCloudtentaclesKnapsack } from "../../platforms/cloudtentacles/knapsack-service.js";
import { import {
appointCloudtentaclesVirtualNumber, appointCloudtentaclesVirtualNumber,
backCloudtentaclesVirtualNumber, backCloudtentaclesVirtualNumber,
@@ -32,22 +36,25 @@ import {
getCloudtentaclesBindUrl, getCloudtentaclesBindUrl,
listCloudtentaclesVirtualNumbers, listCloudtentaclesVirtualNumbers,
verifyCloudtentaclesLoginCode, verifyCloudtentaclesLoginCode,
} from '../../platforms/cloudtentacles/virtual-number-service.js' } from "../../platforms/cloudtentacles/virtual-number-service.js";
import { runCloudtentaclesFullDebugFlow } from '../../platforms/cloudtentacles/debug-flow-service.js' import { runCloudtentaclesFullDebugFlow } from "../../platforms/cloudtentacles/debug-flow-service.js";
import { hasCloudtentaclesCredentialContextChanged, pickFirstNonEmpty } from './context.js' import {
hasCloudtentaclesCredentialContextChanged,
pickFirstNonEmpty,
} from "./context.js";
import { import {
buildAdminCloudtentaclesLoginResult, buildAdminCloudtentaclesLoginResult,
buildAdminCloudtentaclesPersistedSessionPayload, buildAdminCloudtentaclesPersistedSessionPayload,
buildAdminCloudtentaclesValidateResult, buildAdminCloudtentaclesValidateResult,
resolveAdminCloudtentaclesCredentialPayload, resolveAdminCloudtentaclesCredentialPayload,
resolveAdminCloudtentaclesSessionPayload, resolveAdminCloudtentaclesSessionPayload,
} from './cloudtentacles.js' } from "./cloudtentacles.js";
import { normalizeAdminCloudtentaclesSourceConfigPayload } from './writes.js' import { normalizeAdminCloudtentaclesSourceConfigPayload } from "./writes.js";
import { import {
mapAdminCloudtentaclesSession, mapAdminCloudtentaclesSession,
mapAdminCloudtentaclesSourceConfig, mapAdminCloudtentaclesSourceConfig,
maskPhone, maskPhone,
} from './mappers.js' } from "./mappers.js";
/** @typedef {import('../../../types/admin-write-inputs.js').AdminCloudtentaclesSourceConfigInput} AdminCloudtentaclesSourceConfigInput */ /** @typedef {import('../../../types/admin-write-inputs.js').AdminCloudtentaclesSourceConfigInput} AdminCloudtentaclesSourceConfigInput */
/** @typedef {import('../../../types/admin-write-inputs.js').AdminCloudtentaclesSendSmsCodeInput} AdminCloudtentaclesSendSmsCodeInput */ /** @typedef {import('../../../types/admin-write-inputs.js').AdminCloudtentaclesSendSmsCodeInput} AdminCloudtentaclesSendSmsCodeInput */
@@ -59,192 +66,319 @@ import {
/** @typedef {import('../../../types/admin-write-inputs.js').AdminCloudtentaclesVirtualNumberInput} AdminCloudtentaclesVirtualNumberInput */ /** @typedef {import('../../../types/admin-write-inputs.js').AdminCloudtentaclesVirtualNumberInput} AdminCloudtentaclesVirtualNumberInput */
/** @typedef {import('../../../types/admin-write-inputs.js').AdminCloudtentaclesFullFlowInput} AdminCloudtentaclesFullFlowInput */ /** @typedef {import('../../../types/admin-write-inputs.js').AdminCloudtentaclesFullFlowInput} AdminCloudtentaclesFullFlowInput */
export function getAdminCloudtentaclesSourceConfig() { export function listAdminCloudtentaclesSources() {
const config = getCloudtentaclesSourceConfig() const list = listCloudtentaclesSources();
const session = getCloudtentaclesSessionState() const sessions = getAllCloudtentaclesSessionStates();
const sources = Array.isArray(list.sources)
? list.sources.map((s) => mapAdminCloudtentaclesSourceConfig(s))
: [];
const mappedSessions = {};
for (const [key, session] of Object.entries(sessions.sessions || {})) {
mappedSessions[key] = mapAdminCloudtentaclesSession(session);
}
return { return {
filePath: getCloudtentaclesSourcesFilePath(), filePath: getCloudtentaclesSourcesFilePath(),
sessionFilePath: getCloudtentaclesSessionFilePath(), sessionFilePath: getCloudtentaclesSessionFilePath(),
source: mapAdminCloudtentaclesSourceConfig(config), enabled: list.enabled,
session: mapAdminCloudtentaclesSession(session), sources,
} sessions: mappedSessions,
};
} }
/** @param {AdminCloudtentaclesSourceConfigInput} [payload] */ /** @param {AdminCloudtentaclesSourceConfigInput} [payload] */
export function updateAdminCloudtentaclesSourceConfig(payload = /** @type {AdminCloudtentaclesSourceConfigInput} */ ({})) { export function updateAdminCloudtentaclesSourceConfig(
const current = getCloudtentaclesSourceConfig() payload = /** @type {AdminCloudtentaclesSourceConfigInput} */ ({})
const saved = saveCloudtentaclesSourceConfig(normalizeAdminCloudtentaclesSourceConfigPayload(payload)) ) {
const shouldClearSession = hasCloudtentaclesCredentialContextChanged(current, saved) // Batch save: if payload.sources is an array, save the whole list
const session = shouldClearSession ? clearCloudtentaclesSessionState() : getCloudtentaclesSessionState() if (Array.isArray(payload.sources)) {
const normalizedList = payload.sources.map((item) =>
normalizeAdminCloudtentaclesSourceConfigPayload(item)
);
const savedList = saveCloudtentaclesSourcesList({
enabled: payload.enabled !== false,
sources: normalizedList,
});
const sessions = getAllCloudtentaclesSessionStates();
const sources = Array.isArray(savedList.sources)
? savedList.sources.map((s) => mapAdminCloudtentaclesSourceConfig(s))
: [];
const mappedSessions = {};
for (const [key, session] of Object.entries(sessions.sessions || {})) {
mappedSessions[key] = mapAdminCloudtentaclesSession(session);
}
return {
filePath: getCloudtentaclesSourcesFilePath(),
sessionFilePath: getCloudtentaclesSessionFilePath(),
enabled: savedList.enabled,
sources,
sessions: mappedSessions,
};
}
// Single source save
const sourceKey = String(payload.sourceKey || "").trim() || "default";
const current = getCloudtentaclesSourceByKey(sourceKey);
const normalized = normalizeAdminCloudtentaclesSourceConfigPayload({
...payload,
sourceKey,
});
const saved = saveCloudtentaclesSourceByKey(sourceKey, normalized);
const shouldClearSession = hasCloudtentaclesCredentialContextChanged(
current,
saved
);
const session = shouldClearSession
? (clearCloudtentaclesSessionStateByKey(sourceKey),
getCloudtentaclesSessionStateByKey(sourceKey))
: getCloudtentaclesSessionStateByKey(sourceKey);
return { return {
filePath: getCloudtentaclesSourcesFilePath(), filePath: getCloudtentaclesSourcesFilePath(),
sessionFilePath: getCloudtentaclesSessionFilePath(), sessionFilePath: getCloudtentaclesSessionFilePath(),
source: mapAdminCloudtentaclesSourceConfig(saved), source: mapAdminCloudtentaclesSourceConfig(saved),
session: mapAdminCloudtentaclesSession(session), session: mapAdminCloudtentaclesSession(session),
};
}
/** @param {string} sourceKey */
export function deleteAdminCloudtentaclesSource(sourceKey) {
const key = String(sourceKey || "").trim();
if (!key) {
throw new Error("sourceKey is required for deletion");
} }
clearCloudtentaclesSessionStateByKey(key);
deleteCloudtentaclesSourceByKey(key);
} }
/** @param {AdminCloudtentaclesSendSmsCodeInput} [payload] */ /** @param {AdminCloudtentaclesSendSmsCodeInput} [payload] */
export async function sendAdminCloudtentaclesSmsCode(payload = /** @type {AdminCloudtentaclesSendSmsCodeInput} */ ({})) { export async function sendAdminCloudtentaclesSmsCode(
const result = await sendCloudtentaclesSmsCode(resolveAdminCloudtentaclesCredentialPayload(payload)) payload = /** @type {AdminCloudtentaclesSendSmsCodeInput} */ ({})
) {
const result = await sendCloudtentaclesSmsCode(
resolveAdminCloudtentaclesCredentialPayload(payload)
);
return { return {
...result, ...result,
phoneMasked: maskPhone(result.phone), phoneMasked: maskPhone(result.phone),
} };
} }
/** @param {AdminCloudtentaclesTestLoginInput} [payload] */ /** @param {AdminCloudtentaclesTestLoginInput} [payload] */
export async function testAdminCloudtentaclesLogin(payload = /** @type {AdminCloudtentaclesTestLoginInput} */ ({})) { export async function testAdminCloudtentaclesLogin(
const savedSource = getCloudtentaclesSourceConfig() payload = /** @type {AdminCloudtentaclesTestLoginInput} */ ({})
const credentialContext = resolveAdminCloudtentaclesCredentialPayload(payload, { savedSource }) ) {
const sourceKey = String(payload.sourceKey || "").trim() || "default";
const savedSource = getCloudtentaclesSourceByKey(sourceKey) || {};
const credentialContext = resolveAdminCloudtentaclesCredentialPayload(
payload,
{ savedSource }
);
const session = await loginCloudtentaclesSession({ const session = await loginCloudtentaclesSession({
...credentialContext, ...credentialContext,
code: String(payload.code || '').trim(), code: String(payload.code || "").trim(),
}) });
const savedSession = saveCloudtentaclesSessionState(buildAdminCloudtentaclesPersistedSessionPayload(session, { const savedSession = saveCloudtentaclesSessionStateByKey(
deviceId: credentialContext.deviceId, sourceKey,
deviceType: credentialContext.deviceType, buildAdminCloudtentaclesPersistedSessionPayload(session, {
})) deviceId: credentialContext.deviceId,
deviceType: credentialContext.deviceType,
})
);
return buildAdminCloudtentaclesLoginResult(session, savedSession) return buildAdminCloudtentaclesLoginResult(session, savedSession, sourceKey);
} }
/** @param {AdminCloudtentaclesValidateSessionInput} [payload] */ /** @param {AdminCloudtentaclesValidateSessionInput} [payload] */
export async function validateAdminCloudtentaclesSession(payload = /** @type {AdminCloudtentaclesValidateSessionInput} */ ({})) { export async function validateAdminCloudtentaclesSession(
const savedSource = getCloudtentaclesSourceConfig() payload = /** @type {AdminCloudtentaclesValidateSessionInput} */ ({})
const persistedSession = getCloudtentaclesSessionState() ) {
const sessionContext = resolveAdminCloudtentaclesSessionPayload(payload, { savedSource, persistedSession }) const sourceKey = String(payload.sourceKey || "").trim() || "default";
const session = await validateCloudtentaclesSession(sessionContext) const savedSource = getCloudtentaclesSourceByKey(sourceKey) || {};
const savedSession = saveCloudtentaclesSessionState(buildAdminCloudtentaclesPersistedSessionPayload(session, { const persistedSession = getCloudtentaclesSessionStateByKey(sourceKey) || {};
username: pickFirstNonEmpty([persistedSession.username, savedSource.username]), const sessionContext = resolveAdminCloudtentaclesSessionPayload(payload, {
phone: pickFirstNonEmpty([persistedSession.phone, savedSource.phone]), savedSource,
deviceId: sessionContext.deviceId, persistedSession,
deviceType: sessionContext.deviceType, });
})) const session = await validateCloudtentaclesSession(sessionContext);
const savedSession = saveCloudtentaclesSessionStateByKey(
sourceKey,
buildAdminCloudtentaclesPersistedSessionPayload(session, {
username: pickFirstNonEmpty([
persistedSession.username,
savedSource.username,
]),
phone: pickFirstNonEmpty([persistedSession.phone, savedSource.phone]),
deviceId: sessionContext.deviceId,
deviceType: sessionContext.deviceType,
})
);
return buildAdminCloudtentaclesValidateResult(session, savedSession) return buildAdminCloudtentaclesValidateResult(
session,
savedSession,
sourceKey
);
} }
/** @param {AdminCloudtentaclesCatalogQueryInput} [payload] */ /** @param {AdminCloudtentaclesCatalogQueryInput} [payload] */
export async function getAdminCloudtentaclesAsset(payload = /** @type {AdminCloudtentaclesCatalogQueryInput} */ ({})) { export async function getAdminCloudtentaclesAsset(
return getCloudtentaclesAsset(resolveAdminCloudtentaclesSessionPayload(payload)) payload = /** @type {AdminCloudtentaclesCatalogQueryInput} */ ({})
) {
return getCloudtentaclesAsset(
resolveAdminCloudtentaclesSessionPayload(payload)
);
} }
/** @param {AdminCloudtentaclesCatalogQueryInput} [payload] */ /** @param {AdminCloudtentaclesCatalogQueryInput} [payload] */
export async function getAdminCloudtentaclesCategories(payload = /** @type {AdminCloudtentaclesCatalogQueryInput} */ ({})) { export async function getAdminCloudtentaclesCategories(
return getCloudtentaclesCategories(resolveAdminCloudtentaclesSessionPayload(payload)) payload = /** @type {AdminCloudtentaclesCatalogQueryInput} */ ({})
) {
return getCloudtentaclesCategories(
resolveAdminCloudtentaclesSessionPayload(payload)
);
} }
/** @param {AdminCloudtentaclesCatalogQueryInput} [payload] */ /** @param {AdminCloudtentaclesCatalogQueryInput} [payload] */
export async function getAdminCloudtentaclesSkuList(payload = /** @type {AdminCloudtentaclesCatalogQueryInput} */ ({})) { export async function getAdminCloudtentaclesSkuList(
return listCloudtentaclesSku(resolveAdminCloudtentaclesSessionPayload(payload)) payload = /** @type {AdminCloudtentaclesCatalogQueryInput} */ ({})
) {
return listCloudtentaclesSku(
resolveAdminCloudtentaclesSessionPayload(payload)
);
} }
/** @param {AdminCloudtentaclesSkuBuyInput} [payload] */ /** @param {AdminCloudtentaclesSkuBuyInput} [payload] */
export async function buyAdminCloudtentaclesSku(payload = /** @type {AdminCloudtentaclesSkuBuyInput} */ ({})) { export async function buyAdminCloudtentaclesSku(
const context = resolveAdminCloudtentaclesSessionPayload(payload) payload = /** @type {AdminCloudtentaclesSkuBuyInput} */ ({})
) {
const context = resolveAdminCloudtentaclesSessionPayload(payload);
return buyCloudtentaclesSku({ return buyCloudtentaclesSku({
...context, ...context,
id: payload.id, id: payload.id,
count: payload.count, count: payload.count,
}) });
} }
/** @param {AdminCloudtentaclesSkuUseInput} [payload] */ /** @param {AdminCloudtentaclesSkuUseInput} [payload] */
export async function useAdminCloudtentaclesSku(payload = /** @type {AdminCloudtentaclesSkuUseInput} */ ({})) { export async function useAdminCloudtentaclesSku(
const context = resolveAdminCloudtentaclesSessionPayload(payload) payload = /** @type {AdminCloudtentaclesSkuUseInput} */ ({})
) {
const context = resolveAdminCloudtentaclesSessionPayload(payload);
return useCloudtentaclesSku({ return useCloudtentaclesSku({
...context, ...context,
id: payload.id, id: payload.id,
virtualNumberId: payload.virtualNumberId, virtualNumberId: payload.virtualNumberId,
phone: payload.phone, phone: payload.phone,
}) });
} }
/** @param {AdminCloudtentaclesCatalogQueryInput} [payload] */ /** @param {AdminCloudtentaclesCatalogQueryInput} [payload] */
export async function getAdminCloudtentaclesKnapsack(payload = /** @type {AdminCloudtentaclesCatalogQueryInput} */ ({})) { export async function getAdminCloudtentaclesKnapsack(
return getCloudtentaclesKnapsack(resolveAdminCloudtentaclesSessionPayload(payload)) payload = /** @type {AdminCloudtentaclesCatalogQueryInput} */ ({})
) {
return getCloudtentaclesKnapsack(
resolveAdminCloudtentaclesSessionPayload(payload)
);
} }
/** @param {AdminCloudtentaclesVirtualNumberInput} [payload] */ /** @param {AdminCloudtentaclesVirtualNumberInput} [payload] */
export async function listAdminCloudtentaclesVirtualNumbers(payload = /** @type {AdminCloudtentaclesVirtualNumberInput} */ ({})) { export async function listAdminCloudtentaclesVirtualNumbers(
const context = resolveAdminCloudtentaclesSessionPayload(payload) payload = /** @type {AdminCloudtentaclesVirtualNumberInput} */ ({})
) {
const context = resolveAdminCloudtentaclesSessionPayload(payload);
return listCloudtentaclesVirtualNumbers({ return listCloudtentaclesVirtualNumbers({
...context, ...context,
key: payload.key, key: payload.key,
}) });
} }
/** @param {AdminCloudtentaclesVirtualNumberInput} [payload] */ /** @param {AdminCloudtentaclesVirtualNumberInput} [payload] */
export async function appointAdminCloudtentaclesVirtualNumber(payload = /** @type {AdminCloudtentaclesVirtualNumberInput} */ ({})) { export async function appointAdminCloudtentaclesVirtualNumber(
const context = resolveAdminCloudtentaclesSessionPayload(payload) payload = /** @type {AdminCloudtentaclesVirtualNumberInput} */ ({})
) {
const context = resolveAdminCloudtentaclesSessionPayload(payload);
return appointCloudtentaclesVirtualNumber({ return appointCloudtentaclesVirtualNumber({
...context, ...context,
key: payload.key, key: payload.key,
}) });
} }
/** @param {AdminCloudtentaclesVirtualNumberInput} [payload] */ /** @param {AdminCloudtentaclesVirtualNumberInput} [payload] */
export async function generateAdminCloudtentaclesLoginCode(payload = /** @type {AdminCloudtentaclesVirtualNumberInput} */ ({})) { export async function generateAdminCloudtentaclesLoginCode(
const context = resolveAdminCloudtentaclesSessionPayload(payload) payload = /** @type {AdminCloudtentaclesVirtualNumberInput} */ ({})
) {
const context = resolveAdminCloudtentaclesSessionPayload(payload);
return generateCloudtentaclesLoginCode({ return generateCloudtentaclesLoginCode({
...context, ...context,
key: payload.key, key: payload.key,
id: payload.id, id: payload.id,
}) });
} }
/** @param {AdminCloudtentaclesVirtualNumberInput} [payload] */ /** @param {AdminCloudtentaclesVirtualNumberInput} [payload] */
export async function fetchAdminCloudtentaclesVirtualNumberCode(payload = /** @type {AdminCloudtentaclesVirtualNumberInput} */ ({})) { export async function fetchAdminCloudtentaclesVirtualNumberCode(
const context = resolveAdminCloudtentaclesSessionPayload(payload) payload = /** @type {AdminCloudtentaclesVirtualNumberInput} */ ({})
) {
const context = resolveAdminCloudtentaclesSessionPayload(payload);
return fetchCloudtentaclesVirtualNumberCode({ return fetchCloudtentaclesVirtualNumberCode({
...context, ...context,
key: payload.key, key: payload.key,
phone: payload.phone, phone: payload.phone,
}) });
} }
/** @param {AdminCloudtentaclesVirtualNumberInput} [payload] */ /** @param {AdminCloudtentaclesVirtualNumberInput} [payload] */
export async function verifyAdminCloudtentaclesLoginCode(payload = /** @type {AdminCloudtentaclesVirtualNumberInput} */ ({})) { export async function verifyAdminCloudtentaclesLoginCode(
const context = resolveAdminCloudtentaclesSessionPayload(payload) payload = /** @type {AdminCloudtentaclesVirtualNumberInput} */ ({})
) {
const context = resolveAdminCloudtentaclesSessionPayload(payload);
return verifyCloudtentaclesLoginCode({ return verifyCloudtentaclesLoginCode({
...context, ...context,
key: payload.key, key: payload.key,
id: payload.id, id: payload.id,
code: payload.code, code: payload.code,
}) });
} }
/** @param {AdminCloudtentaclesVirtualNumberInput} [payload] */ /** @param {AdminCloudtentaclesVirtualNumberInput} [payload] */
export async function getAdminCloudtentaclesBindUrl(payload = /** @type {AdminCloudtentaclesVirtualNumberInput} */ ({})) { export async function getAdminCloudtentaclesBindUrl(
const context = resolveAdminCloudtentaclesSessionPayload(payload) payload = /** @type {AdminCloudtentaclesVirtualNumberInput} */ ({})
) {
const context = resolveAdminCloudtentaclesSessionPayload(payload);
return getCloudtentaclesBindUrl({ return getCloudtentaclesBindUrl({
...context, ...context,
key: payload.key, key: payload.key,
id: payload.id, id: payload.id,
}) });
} }
/** @param {AdminCloudtentaclesVirtualNumberInput} [payload] */ /** @param {AdminCloudtentaclesVirtualNumberInput} [payload] */
export async function backAdminCloudtentaclesVirtualNumber(payload = /** @type {AdminCloudtentaclesVirtualNumberInput} */ ({})) { export async function backAdminCloudtentaclesVirtualNumber(
const context = resolveAdminCloudtentaclesSessionPayload(payload) payload = /** @type {AdminCloudtentaclesVirtualNumberInput} */ ({})
) {
const context = resolveAdminCloudtentaclesSessionPayload(payload);
return backCloudtentaclesVirtualNumber({ return backCloudtentaclesVirtualNumber({
...context, ...context,
key: payload.key, key: payload.key,
id: payload.id, id: payload.id,
}) });
} }
/** @param {AdminCloudtentaclesFullFlowInput} [payload] */ /** @param {AdminCloudtentaclesFullFlowInput} [payload] */
export async function runAdminCloudtentaclesFullFlow(payload = /** @type {AdminCloudtentaclesFullFlowInput} */ ({})) { export async function runAdminCloudtentaclesFullFlow(
const context = resolveAdminCloudtentaclesSessionPayload(payload) payload = /** @type {AdminCloudtentaclesFullFlowInput} */ ({})
) {
const context = resolveAdminCloudtentaclesSessionPayload(payload);
return runCloudtentaclesFullDebugFlow({ return runCloudtentaclesFullDebugFlow({
...context, ...context,
skuId: payload.skuId, skuId: payload.skuId,
skuCount: payload.skuCount, skuCount: payload.skuCount,
vnKey: payload.vnKey, vnKey: payload.vnKey,
}) });
} }
@@ -1,104 +1,139 @@
// @ts-check // @ts-check
import { getCloudtentaclesSourceConfig } from '../../platforms/cloudtentacles/source-config-service.js' import { getCloudtentaclesSourceByKey } from "../../platforms/cloudtentacles/source-config-service.js";
import { getCloudtentaclesSessionState } from '../../platforms/cloudtentacles/session-state-service.js' import { getCloudtentaclesSessionStateByKey } from "../../platforms/cloudtentacles/session-state-service.js";
import { pickFirstNonEmpty, resolveCloudtentaclesAdminContext } from './context.js' import {
import { maskPhone, maskSecret } from './mappers.js' pickFirstNonEmpty,
resolveCloudtentaclesAdminContext,
} from "./context.js";
import { maskPhone, maskSecret } from "./mappers.js";
const DEFAULT_CLOUDTENTACLES_BASE_URL = 'https://123.207.217.176' const DEFAULT_CLOUDTENTACLES_BASE_URL = "https://123.207.217.176";
function _resolveSourceKey(payload = {}) {
return String(payload.sourceKey || "").trim() || "default";
}
export function resolveAdminCloudtentaclesCredentialPayload( export function resolveAdminCloudtentaclesCredentialPayload(
payload = {}, payload = {},
options = {}, options = {}
) { ) {
const sourceKey = _resolveSourceKey(payload);
const savedSource = /** @type {Record<string, unknown>} */ ( const savedSource = /** @type {Record<string, unknown>} */ (
options.savedSource || getCloudtentaclesSourceConfig() options.savedSource || getCloudtentaclesSourceByKey(sourceKey) || {}
) );
const defaultBaseUrl = String(options.defaultBaseUrl || DEFAULT_CLOUDTENTACLES_BASE_URL).trim() const defaultBaseUrl = String(
options.defaultBaseUrl || DEFAULT_CLOUDTENTACLES_BASE_URL
).trim();
return { return {
baseUrl: pickFirstNonEmpty([payload.baseUrl, savedSource.baseUrl, defaultBaseUrl]), sourceKey,
baseUrl: pickFirstNonEmpty([
payload.baseUrl,
savedSource.baseUrl,
defaultBaseUrl,
]),
username: pickFirstNonEmpty([payload.username, savedSource.username]), username: pickFirstNonEmpty([payload.username, savedSource.username]),
password: pickFirstNonEmpty([payload.password, savedSource.password]), password: pickFirstNonEmpty([payload.password, savedSource.password]),
phone: pickFirstNonEmpty([payload.phone, savedSource.phone]), phone: pickFirstNonEmpty([payload.phone, savedSource.phone]),
deviceId: pickFirstNonEmpty([payload.deviceId, savedSource.deviceId, '-']), deviceId: pickFirstNonEmpty([payload.deviceId, savedSource.deviceId, "-"]),
deviceType: payload.deviceType ?? savedSource.deviceType, deviceType: payload.deviceType ?? savedSource.deviceType,
} };
} }
export function resolveAdminCloudtentaclesSessionPayload( export function resolveAdminCloudtentaclesSessionPayload(
payload = {}, payload = {},
options = {}, options = {}
) { ) {
const sourceKey = _resolveSourceKey(payload);
const savedSource = /** @type {Record<string, unknown>} */ ( const savedSource = /** @type {Record<string, unknown>} */ (
options.savedSource || getCloudtentaclesSourceConfig() options.savedSource || getCloudtentaclesSourceByKey(sourceKey) || {}
) );
const persistedSession = /** @type {Record<string, unknown>} */ ( const persistedSession = /** @type {Record<string, unknown>} */ (
options.persistedSession || getCloudtentaclesSessionState() options.persistedSession ||
) getCloudtentaclesSessionStateByKey(sourceKey) ||
{}
);
return resolveCloudtentaclesAdminContext(payload, { return resolveCloudtentaclesAdminContext(payload, {
savedSource, savedSource,
persistedSession, persistedSession,
sourceKey,
defaultBaseUrl: options.defaultBaseUrl || DEFAULT_CLOUDTENTACLES_BASE_URL, defaultBaseUrl: options.defaultBaseUrl || DEFAULT_CLOUDTENTACLES_BASE_URL,
}) });
} }
export function buildAdminCloudtentaclesPersistedSessionPayload( export function buildAdminCloudtentaclesPersistedSessionPayload(
session = {}, session = {},
options = {}, options = {}
) { ) {
return { return {
token: String(session.token || '').trim(), token: String(session.token || "").trim(),
baseUrl: String(session.baseUrl || '').trim(), baseUrl: String(session.baseUrl || "").trim(),
username: pickFirstNonEmpty([options.username, session.username]), username: pickFirstNonEmpty([options.username, session.username]),
phone: pickFirstNonEmpty([options.phone, session.phone]), phone: pickFirstNonEmpty([options.phone, session.phone]),
loggedInAt: String(session.loggedInAt || '').trim(), loggedInAt: String(session.loggedInAt || "").trim(),
deviceId: pickFirstNonEmpty([options.deviceId, session.deviceId, '-']), deviceId: pickFirstNonEmpty([options.deviceId, session.deviceId, "-"]),
deviceType: options.deviceType ?? session.deviceType, deviceType: options.deviceType ?? session.deviceType,
} };
} }
export function buildAdminCloudtentaclesSessionSummary( export function buildAdminCloudtentaclesSessionSummary(
session = {}, session = {},
savedSession = {}, savedSession = {},
sourceKey = "default"
) { ) {
const permissions = Array.isArray(session.permissions) ? session.permissions : [] const permissions = Array.isArray(session.permissions)
? session.permissions
: [];
return { return {
sourceKey,
tokenMasked: maskSecret(session.token), tokenMasked: maskSecret(session.token),
permissionCount: permissions.length, permissionCount: permissions.length,
permissions, permissions,
persisted: Boolean(savedSession.token), persisted: Boolean(savedSession.token),
} };
} }
export function buildAdminCloudtentaclesLoginResult( export function buildAdminCloudtentaclesLoginResult(
session = {}, session = {},
savedSession = {}, savedSession = {},
sourceKey = "default"
) { ) {
return { return {
baseUrl: String(session.baseUrl || '').trim(), sourceKey,
username: String(session.username || '').trim(), baseUrl: String(session.baseUrl || "").trim(),
username: String(session.username || "").trim(),
phoneMasked: maskPhone(session.phone), phoneMasked: maskPhone(session.phone),
loggedInAt: String(session.loggedInAt || '').trim(), loggedInAt: String(session.loggedInAt || "").trim(),
responseMessage: String(session.responseMessage || '').trim(), responseMessage: String(session.responseMessage || "").trim(),
token: String(session.token || '').trim(), token: String(session.token || "").trim(),
session: buildAdminCloudtentaclesSessionSummary(session, savedSession), session: buildAdminCloudtentaclesSessionSummary(
session,
savedSession,
sourceKey
),
userInfo: session.userInfo, userInfo: session.userInfo,
asset: session.asset, asset: session.asset,
} };
} }
export function buildAdminCloudtentaclesValidateResult( export function buildAdminCloudtentaclesValidateResult(
session = {}, session = {},
savedSession = {}, savedSession = {},
sourceKey = "default"
) { ) {
return { return {
baseUrl: String(session.baseUrl || '').trim(), sourceKey,
loggedInAt: String(session.loggedInAt || '').trim(), baseUrl: String(session.baseUrl || "").trim(),
session: buildAdminCloudtentaclesSessionSummary(session, savedSession), loggedInAt: String(session.loggedInAt || "").trim(),
session: buildAdminCloudtentaclesSessionSummary(
session,
savedSession,
sourceKey
),
userInfo: session.userInfo, userInfo: session.userInfo,
asset: session.asset, asset: session.asset,
} };
} }
@@ -2,67 +2,104 @@
export function pickFirstNonEmpty(values) { export function pickFirstNonEmpty(values) {
for (const value of values) { for (const value of values) {
const normalized = String(value || '').trim() const normalized = String(value || "").trim();
if (normalized) { if (normalized) {
return normalized return normalized;
} }
} }
return '' return "";
} }
export function isPlainObject(value) { export function isPlainObject(value) {
return Boolean(value) && typeof value === 'object' && !Array.isArray(value) return Boolean(value) && typeof value === "object" && !Array.isArray(value);
} }
export function resolveKuaishouEticketAdminContext( export function resolveKuaishouEticketAdminContext(payload = {}, options = {}) {
payload = {}, const savedSource = /** @type {Record<string, unknown>} */ (
options = {}, options.savedSource || {}
) { );
const savedSource = /** @type {Record<string, unknown>} */ (options.savedSource || {}) const findShopConfig =
const findShopConfig = /** @type {(shopId: string, source: Record<string, unknown>) => unknown} */ ( /** @type {(shopId: string, source: Record<string, unknown>) => unknown} */ (
options.findShopConfig || (() => null) options.findShopConfig || (() => null)
) );
const getFirstAvailableShop = /** @type {(source: Record<string, unknown>) => unknown} */ ( const getFirstAvailableShop =
options.getFirstAvailableShop || (() => null) /** @type {(source: Record<string, unknown>) => unknown} */ (
) options.getFirstAvailableShop || (() => null)
const defaultBaseUrl = String(options.defaultBaseUrl || 'https://s.kwaixiaodian.com').trim() );
const requestedShopId = String(payload.shopId || '').trim() const defaultBaseUrl = String(
options.defaultBaseUrl || "https://s.kwaixiaodian.com"
).trim();
const requestedShopId = String(payload.shopId || "").trim();
const configuredShop = /** @type {Record<string, unknown> | null} */ ( const configuredShop = /** @type {Record<string, unknown> | null} */ (
requestedShopId requestedShopId
? findShopConfig(requestedShopId, savedSource) ? findShopConfig(requestedShopId, savedSource)
: getFirstAvailableShop(savedSource) : getFirstAvailableShop(savedSource)
) );
return { return {
baseUrl: pickFirstNonEmpty([payload.baseUrl, savedSource.baseUrl, defaultBaseUrl]), baseUrl: pickFirstNonEmpty([
payload.baseUrl,
savedSource.baseUrl,
defaultBaseUrl,
]),
cookie: pickFirstNonEmpty([payload.cookie, configuredShop?.cookie]), cookie: pickFirstNonEmpty([payload.cookie, configuredShop?.cookie]),
shopId: pickFirstNonEmpty([requestedShopId, configuredShop?.shopId]), shopId: pickFirstNonEmpty([requestedShopId, configuredShop?.shopId]),
shop: configuredShop, shop: configuredShop,
} };
} }
export function resolveCloudtentaclesAdminContext( import { getCloudtentaclesSourceByKey } from "../../platforms/cloudtentacles/source-config-service.js";
payload = {}, import { getCloudtentaclesSessionStateByKey } from "../../platforms/cloudtentacles/session-state-service.js";
options = {},
) { export function resolveCloudtentaclesAdminContext(payload = {}, options = {}) {
const savedSource = /** @type {Record<string, unknown>} */ (options.savedSource || {}) const sourceKey = String(
const persistedSession = /** @type {Record<string, unknown>} */ (options.persistedSession || {}) payload.sourceKey || options.sourceKey || "default"
const defaultBaseUrl = String(options.defaultBaseUrl || 'https://123.207.217.176').trim() ).trim();
const savedSource = /** @type {Record<string, unknown>} */ (
options.savedSource || getCloudtentaclesSourceByKey(sourceKey) || {}
);
const persistedSession = /** @type {Record<string, unknown>} */ (
options.persistedSession ||
getCloudtentaclesSessionStateByKey(sourceKey) ||
{}
);
const defaultBaseUrl = String(
options.defaultBaseUrl || "https://123.207.217.176"
).trim();
return { return {
baseUrl: pickFirstNonEmpty([payload.baseUrl, savedSource.baseUrl, defaultBaseUrl]), sourceKey,
baseUrl: pickFirstNonEmpty([
payload.baseUrl,
savedSource.baseUrl,
defaultBaseUrl,
]),
token: pickFirstNonEmpty([payload.token, persistedSession.token]), token: pickFirstNonEmpty([payload.token, persistedSession.token]),
deviceId: pickFirstNonEmpty([payload.deviceId, savedSource.deviceId, persistedSession.deviceId, '-']), deviceId: pickFirstNonEmpty([
deviceType: payload.deviceType ?? savedSource.deviceType ?? persistedSession.deviceType, payload.deviceId,
} savedSource.deviceId,
persistedSession.deviceId,
"-",
]),
deviceType:
payload.deviceType ??
savedSource.deviceType ??
persistedSession.deviceType,
};
} }
export function hasCloudtentaclesCredentialContextChanged(current = {}, next = {}) { export function hasCloudtentaclesCredentialContextChanged(
current = {},
next = {}
) {
return ( return (
String(current.baseUrl || '').trim() !== String(next.baseUrl || '').trim() String(current.baseUrl || "").trim() !==
|| String(current.username || '').trim() !== String(next.username || '').trim() String(next.baseUrl || "").trim() ||
|| String(current.phone || '').trim() !== String(next.phone || '').trim() String(current.username || "").trim() !==
|| String(current.deviceId || '').trim() !== String(next.deviceId || '').trim() String(next.username || "").trim() ||
|| Number(current.deviceType || 0) !== Number(next.deviceType || 0) String(current.phone || "").trim() !== String(next.phone || "").trim() ||
) String(current.deviceId || "").trim() !==
String(next.deviceId || "").trim() ||
Number(current.deviceType || 0) !== Number(next.deviceType || 0)
);
} }
@@ -1,110 +1,113 @@
// @ts-check // @ts-check
export function maskSecret(value) { export function maskSecret(value) {
const normalized = String(value || '').trim() const normalized = String(value || "").trim();
if (!normalized) { if (!normalized) {
return '' return "";
} }
if (normalized.length <= 10) { if (normalized.length <= 10) {
return `${normalized.slice(0, 2)}****${normalized.slice(-2)}` return `${normalized.slice(0, 2)}****${normalized.slice(-2)}`;
} }
return `${normalized.slice(0, 6)}****${normalized.slice(-6)}` return `${normalized.slice(0, 6)}****${normalized.slice(-6)}`;
} }
export function maskPhone(value) { export function maskPhone(value) {
const normalized = String(value || '').trim() const normalized = String(value || "").trim();
if (!normalized) { if (!normalized) {
return '' return "";
} }
if (normalized.length < 7) { if (normalized.length < 7) {
return normalized return normalized;
} }
return `${normalized.slice(0, 3)}****${normalized.slice(-4)}` return `${normalized.slice(0, 3)}****${normalized.slice(-4)}`;
} }
export function mapAdminKuaishouEticketShopItem(item = {}) { export function mapAdminKuaishouEticketShopItem(item = {}) {
return { return {
shopId: String(item.shopId || '').trim(), shopId: String(item.shopId || "").trim(),
kshopName: String(item.kshopName || '').trim(), kshopName: String(item.kshopName || "").trim(),
cookie: String(item.cookie || '').trim(), cookie: String(item.cookie || "").trim(),
cookieMasked: maskSecret(item.cookie), cookieMasked: maskSecret(item.cookie),
hasCookie: Boolean(String(item.cookie || '').trim()), hasCookie: Boolean(String(item.cookie || "").trim()),
userAvatar: String(item.userAvatar || '').trim(), userAvatar: String(item.userAvatar || "").trim(),
enabled: item.enabled !== false, enabled: item.enabled !== false,
} };
} }
export function mapAdminKuaishouEticketSourceConfig(config = {}, shops = []) { export function mapAdminKuaishouEticketSourceConfig(config = {}, shops = []) {
return { return {
enabled: config.enabled !== false, enabled: config.enabled !== false,
baseUrl: String(config.baseUrl || '').trim(), baseUrl: String(config.baseUrl || "").trim(),
shops: shops.map((item) => mapAdminKuaishouEticketShopItem(item)), shops: shops.map((item) => mapAdminKuaishouEticketShopItem(item)),
} };
} }
export function mapAdminCloudtentaclesSourceConfig(config = {}) { export function mapAdminCloudtentaclesSourceConfig(config = {}) {
return { return {
key: String(config.key || "").trim(),
label: String(config.label || "").trim(),
enabled: config.enabled !== false, enabled: config.enabled !== false,
baseUrl: String(config.baseUrl || '').trim(), baseUrl: String(config.baseUrl || "").trim(),
username: String(config.username || '').trim(), username: String(config.username || "").trim(),
password: String(config.password || '').trim(), password: String(config.password || "").trim(),
phone: String(config.phone || '').trim(), phone: String(config.phone || "").trim(),
deviceId: String(config.deviceId || '-').trim() || '-', deviceId: String(config.deviceId || "-").trim() || "-",
deviceType: Number(config.deviceType || 0), deviceType: Number(config.deviceType || 0),
} };
} }
export function mapAdminCloudtentaclesSession(session = {}) { export function mapAdminCloudtentaclesSession(session = {}) {
return { return {
token: String(session.token || '').trim(), token: String(session.token || "").trim(),
tokenMasked: maskSecret(session.token), tokenMasked: maskSecret(session.token),
baseUrl: String(session.baseUrl || '').trim(), baseUrl: String(session.baseUrl || "").trim(),
username: String(session.username || '').trim(), username: String(session.username || "").trim(),
phoneMasked: maskPhone(session.phone), phoneMasked: maskPhone(session.phone),
loggedInAt: String(session.loggedInAt || '').trim(), loggedInAt: String(session.loggedInAt || "").trim(),
deviceId: String(session.deviceId || '-').trim() || '-', deviceId: String(session.deviceId || "-").trim() || "-",
deviceType: Number(session.deviceType || 0), deviceType: Number(session.deviceType || 0),
hasToken: Boolean(String(session.token || '').trim()), hasToken: Boolean(String(session.token || "").trim()),
} };
} }
export function mapAdminKuaishouCloudFulfillmentItem(item = {}) { export function mapAdminKuaishouCloudFulfillmentItem(item = {}) {
return { return {
id: String(item.id || '').trim(), id: String(item.id || "").trim(),
enabled: item.enabled !== false, enabled: item.enabled !== false,
priority: Number(item.priority || 100) || 100, priority: Number(item.priority || 100) || 100,
provider: String(item.provider || '91kaquan').trim() || '91kaquan', provider: String(item.provider || "91kaquan").trim() || "91kaquan",
platform: String(item.platform || 'kuaishou').trim() || 'kuaishou', platform: String(item.platform || "kuaishou").trim() || "kuaishou",
shopId: String(item.shopId || '').trim(), shopId: String(item.shopId || "").trim(),
internalSkuCode: String(item.internalSkuCode || '').trim(), internalSkuCode: String(item.internalSkuCode || "").trim(),
internalSkuName: String(item.internalSkuName || '').trim(), internalSkuName: String(item.internalSkuName || "").trim(),
externalSkuCode: String(item.externalSkuCode || '').trim(), externalSkuCode: String(item.externalSkuCode || "").trim(),
externalItemId: String(item.externalItemId || '').trim(), externalItemId: String(item.externalItemId || "").trim(),
externalSkuName: String(item.externalSkuName || '').trim(), externalSkuName: String(item.externalSkuName || "").trim(),
resolvedSkuName: String(item.resolvedSkuName || '').trim(), resolvedSkuName: String(item.resolvedSkuName || "").trim(),
cloudSourceKey: String(item.cloudSourceKey || 'default').trim() || 'default', cloudSourceKey:
String(item.cloudSourceKey || "default").trim() || "default",
cloudSkuId: Number(item.cloudSkuId || 0) || 0, cloudSkuId: Number(item.cloudSkuId || 0) || 0,
cloudSkuName: String(item.cloudSkuName || '').trim(), cloudSkuName: String(item.cloudSkuName || "").trim(),
vnKey: String(item.vnKey || '').trim(), vnKey: String(item.vnKey || "").trim(),
autoBuyEnabled: item.autoBuyEnabled !== false, autoBuyEnabled: item.autoBuyEnabled !== false,
minAssetReserve: Number(item.minAssetReserve || 0) || 0, minAssetReserve: Number(item.minAssetReserve || 0) || 0,
autoReturnNumberAfterDispatch: item.autoReturnNumberAfterDispatch === true, autoReturnNumberAfterDispatch: item.autoReturnNumberAfterDispatch === true,
autoConsumeAfterDispatch: item.autoConsumeAfterDispatch === true, autoConsumeAfterDispatch: item.autoConsumeAfterDispatch === true,
kuaishouConsumeShopId: String(item.kuaishouConsumeShopId || '').trim(), kuaishouConsumeShopId: String(item.kuaishouConsumeShopId || "").trim(),
kuaishouConsumeShopName: String(item.kuaishouConsumeShopName || '').trim(), kuaishouConsumeShopName: String(item.kuaishouConsumeShopName || "").trim(),
notes: String(item.notes || '').trim(), notes: String(item.notes || "").trim(),
} };
} }
export function mapAdminKuaishouCloudFulfillmentSource(config = {}) { export function mapAdminKuaishouCloudFulfillmentSource(config = {}) {
return { return {
enabled: config.enabled !== false, enabled: config.enabled !== false,
items: (Array.isArray(config.items) ? config.items : []).map((item) => items: (Array.isArray(config.items) ? config.items : []).map((item) =>
mapAdminKuaishouCloudFulfillmentItem(item), mapAdminKuaishouCloudFulfillmentItem(item)
), ),
} };
} }
@@ -1,13 +1,13 @@
export { export {
getAdminAgisoShopConfigs, getAdminAgisoShopConfigs,
updateAdminAgisoShopConfigs, updateAdminAgisoShopConfigs,
} from './agiso-service.js' } from "./agiso-service.js";
export { export {
getAdminNinetyoneOrders, getAdminNinetyoneOrders,
retryAdminNinetyoneOrder, retryAdminNinetyoneOrder,
failAdminNinetyoneOrder, failAdminNinetyoneOrder,
} from './ninetyone-service.js' } from "./ninetyone-service.js";
export { export {
getAdminKuaishouEticketSourceConfig, getAdminKuaishouEticketSourceConfig,
@@ -15,10 +15,11 @@ export {
queryAdminKuaishouEticketDetail, queryAdminKuaishouEticketDetail,
queryAdminKuaishouEticketShopInfo, queryAdminKuaishouEticketShopInfo,
consumeAdminKuaishouEticket, consumeAdminKuaishouEticket,
} from './kuaishou-eticket-service.js' } from "./kuaishou-eticket-service.js";
export { export {
getAdminCloudtentaclesSourceConfig, listAdminCloudtentaclesSources,
deleteAdminCloudtentaclesSource,
updateAdminCloudtentaclesSourceConfig, updateAdminCloudtentaclesSourceConfig,
sendAdminCloudtentaclesSmsCode, sendAdminCloudtentaclesSmsCode,
testAdminCloudtentaclesLogin, testAdminCloudtentaclesLogin,
@@ -37,18 +38,18 @@ export {
getAdminCloudtentaclesBindUrl, getAdminCloudtentaclesBindUrl,
backAdminCloudtentaclesVirtualNumber, backAdminCloudtentaclesVirtualNumber,
runAdminCloudtentaclesFullFlow, runAdminCloudtentaclesFullFlow,
} from './cloudtentacles-service.js' } from "./cloudtentacles-service.js";
export { export {
getAdminFulfillmentBindingConfigs, getAdminFulfillmentBindingConfigs,
lookupAdminFulfillmentBindingOrder, lookupAdminFulfillmentBindingOrder,
updateAdminFulfillmentBindingConfigs, updateAdminFulfillmentBindingConfigs,
} from './fulfillment-bindings-service.js' } from "./fulfillment-bindings-service.js";
export { export {
getAdminKuaishouCloudFulfillmentConfig, getAdminKuaishouCloudFulfillmentConfig,
updateAdminKuaishouCloudFulfillmentConfig, updateAdminKuaishouCloudFulfillmentConfig,
} from './kuaishou-cloud-fulfillment-service.js' } from "./kuaishou-cloud-fulfillment-service.js";
export { export {
getAdminNotificationConfig, getAdminNotificationConfig,
@@ -57,4 +58,4 @@ export {
getAdminScheduledJobsConfig, getAdminScheduledJobsConfig,
updateAdminScheduledJobsConfig, updateAdminScheduledJobsConfig,
runAdminScheduledJobNow, runAdminScheduledJobNow,
} from './notification-service.js' } from "./notification-service.js";
@@ -1,101 +1,120 @@
// @ts-check // @ts-check
import { applyOptionalStringField } from './domain.js' import { applyOptionalStringField } from "./domain.js";
export function buildAdminAgisoShopConfigUpdate(item, current = {}) { export function buildAdminAgisoShopConfigUpdate(item, current = {}) {
const shopId = String(item?.shopId || '').trim() const shopId = String(item?.shopId || "").trim();
if (!shopId) { if (!shopId) {
return null return null;
} }
const next = /** @type {Record<string, unknown>} */ ({ ...current }) const next = /** @type {Record<string, unknown>} */ ({ ...current });
const shopName = String(item?.shopName || '').trim() const shopName = String(item?.shopName || "").trim();
const accessToken = String(item?.accessToken || '').trim() const accessToken = String(item?.accessToken || "").trim();
const messageTemplate = String(item?.messageTemplate || '').trim() const messageTemplate = String(item?.messageTemplate || "").trim();
const autoDeliveryMessageTemplate = String(item?.autoDeliveryMessageTemplate || '').trim() const autoDeliveryMessageTemplate = String(
const appSecret = String(item?.appSecret || '').trim() item?.autoDeliveryMessageTemplate || ""
const apiVersion = String(item?.apiVersion || '').trim() ).trim();
const sendMessageEndpoint = String(item?.sendMessageEndpoint || '').trim() const appSecret = String(item?.appSecret || "").trim();
const apiVersion = String(item?.apiVersion || "").trim();
const sendMessageEndpoint = String(item?.sendMessageEndpoint || "").trim();
if (shopName) { if (shopName) {
next.shopName = shopName next.shopName = shopName;
} else { } else {
delete next.shopName delete next.shopName;
} }
if (accessToken) { if (accessToken) {
next.accessToken = accessToken next.accessToken = accessToken;
} }
if (messageTemplate) { if (messageTemplate) {
next.messageTemplate = messageTemplate next.messageTemplate = messageTemplate;
} else if (typeof item?.messageTemplate === 'string') { } else if (typeof item?.messageTemplate === "string") {
delete next.messageTemplate delete next.messageTemplate;
} }
if (autoDeliveryMessageTemplate) { if (autoDeliveryMessageTemplate) {
next.autoDeliveryMessageTemplate = autoDeliveryMessageTemplate next.autoDeliveryMessageTemplate = autoDeliveryMessageTemplate;
} else if (typeof item?.autoDeliveryMessageTemplate === 'string') { } else if (typeof item?.autoDeliveryMessageTemplate === "string") {
delete next.autoDeliveryMessageTemplate delete next.autoDeliveryMessageTemplate;
} }
if (appSecret) { if (appSecret) {
next.appSecret = appSecret next.appSecret = appSecret;
} }
if (apiVersion) { if (apiVersion) {
next.apiVersion = apiVersion next.apiVersion = apiVersion;
} }
if (sendMessageEndpoint) { if (sendMessageEndpoint) {
next.sendMessageEndpoint = sendMessageEndpoint next.sendMessageEndpoint = sendMessageEndpoint;
} }
if (typeof item?.enabled === 'boolean') { if (typeof item?.enabled === "boolean") {
next.enabled = item.enabled next.enabled = item.enabled;
} }
if (!next.accessToken) { if (!next.accessToken) {
return null return null;
} }
return { shopId, config: next } return { shopId, config: next };
} }
export function buildAdminAgisoMessagingSavePayload( export function buildAdminAgisoMessagingSavePayload(
payload = {}, payload = {},
options = {}, options = {}
) { ) {
const rawItems = Array.isArray(payload.shops) ? payload.shops : [] const rawItems = Array.isArray(payload.shops) ? payload.shops : [];
const currentDefaults = /** @type {Record<string, unknown>} */ (options.currentDefaults || {}) const currentDefaults = /** @type {Record<string, unknown>} */ (
const currentMap = /** @type {Record<string, Record<string, unknown>>} */ (options.currentMap || {}) options.currentDefaults || {}
const nextDefaults = /** @type {Record<string, unknown>} */ ({ ...currentDefaults }) );
const nextMap = /** @type {Record<string, Record<string, unknown>>} */ ({}) const currentMap = /** @type {Record<string, Record<string, unknown>>} */ (
options.currentMap || {}
);
const nextDefaults = /** @type {Record<string, unknown>} */ ({
...currentDefaults,
});
const nextMap = /** @type {Record<string, Record<string, unknown>>} */ ({});
applyOptionalStringField(nextDefaults, 'messageTemplate', payload.defaults) applyOptionalStringField(nextDefaults, "messageTemplate", payload.defaults);
applyOptionalStringField(nextDefaults, 'autoDeliveryMessageTemplate', payload.defaults) applyOptionalStringField(
nextDefaults,
"autoDeliveryMessageTemplate",
payload.defaults
);
for (const item of rawItems) { for (const item of rawItems) {
const shopId = String(item?.shopId || '').trim() const shopId = String(item?.shopId || "").trim();
if (!shopId) { if (!shopId) {
continue continue;
} }
const updated = buildAdminAgisoShopConfigUpdate(item, currentMap[shopId] || {}) const updated = buildAdminAgisoShopConfigUpdate(
item,
currentMap[shopId] || {}
);
if (!updated) { if (!updated) {
continue continue;
} }
nextMap[updated.shopId] = updated.config nextMap[updated.shopId] = updated.config;
} }
return { return {
defaults: nextDefaults, defaults: nextDefaults,
shops: nextMap, shops: nextMap,
} };
} }
export function normalizeAdminCloudtentaclesSourceConfigPayload(payload = {}) { export function normalizeAdminCloudtentaclesSourceConfigPayload(payload = {}) {
const sourceKey =
String(payload.sourceKey || payload.key || "").trim() || "default";
return { return {
key: sourceKey,
label: String(payload.label || "").trim(),
enabled: payload.enabled !== false, enabled: payload.enabled !== false,
baseUrl: String(payload.baseUrl || '').trim() || 'https://123.207.217.176', baseUrl: String(payload.baseUrl || "").trim() || "https://123.207.217.176",
username: String(payload.username || '').trim(), username: String(payload.username || "").trim(),
password: String(payload.password || '').trim(), password: String(payload.password || "").trim(),
phone: String(payload.phone || '').trim(), phone: String(payload.phone || "").trim(),
deviceId: String(payload.deviceId || '-').trim() || '-', deviceId: String(payload.deviceId || "-").trim() || "-",
deviceType: Number(payload.deviceType || 0), deviceType: Number(payload.deviceType || 0),
} };
} }
+5 -1
View File
@@ -1,6 +1,6 @@
// @ts-check // @ts-check
export {} export {};
/** /**
* @typedef {import('./admin-read-inputs.js').AdminInventoryListQueryInput} AdminInventoryRouteQuery * @typedef {import('./admin-read-inputs.js').AdminInventoryListQueryInput} AdminInventoryRouteQuery
@@ -161,3 +161,7 @@ export {}
/** /**
* @typedef {{ id?: string }} AdminEntityRouteParams * @typedef {{ id?: string }} AdminEntityRouteParams
*/ */
/**
* @typedef {{ sourceKey?: string }} AdminCloudtentaclesSourceRouteParams
*/
+13 -3
View File
@@ -1,6 +1,6 @@
// @ts-check // @ts-check
export {} export {};
/** /**
* @typedef {{ * @typedef {{
@@ -172,7 +172,7 @@ export {}
/** /**
* @typedef {{ * @typedef {{
* baseUrl?: string * baseUrl?: string
* shopId?: string * shopId?: string
* cookie?: string * cookie?: string
* }} AdminKuaishouEticketShopInfoInput * }} AdminKuaishouEticketShopInfoInput
@@ -189,7 +189,7 @@ export {}
/** /**
* @typedef {{ * @typedef {{
* baseUrl?: string * baseUrl?: string
* shopId?: string * shopId?: string
* cookie?: string * cookie?: string
* eTicketId?: string * eTicketId?: string
@@ -202,6 +202,7 @@ export {}
/** /**
* @typedef {{ * @typedef {{
* sourceKey?: string
* enabled?: boolean * enabled?: boolean
* baseUrl?: string * baseUrl?: string
* username?: string * username?: string
@@ -209,11 +210,13 @@ export {}
* phone?: string * phone?: string
* deviceId?: string * deviceId?: string
* deviceType?: number | string * deviceType?: number | string
* sources?: AdminCloudtentaclesSourceConfigInput[]
* }} AdminCloudtentaclesSourceConfigInput * }} AdminCloudtentaclesSourceConfigInput
*/ */
/** /**
* @typedef {{ * @typedef {{
* sourceKey?: string
* baseUrl?: string * baseUrl?: string
* username?: string * username?: string
* phone?: string * phone?: string
@@ -224,6 +227,7 @@ export {}
/** /**
* @typedef {{ * @typedef {{
* sourceKey?: string
* baseUrl?: string * baseUrl?: string
* username?: string * username?: string
* password?: string * password?: string
@@ -236,6 +240,7 @@ export {}
/** /**
* @typedef {{ * @typedef {{
* sourceKey?: string
* baseUrl?: string * baseUrl?: string
* token?: string * token?: string
* deviceId?: string * deviceId?: string
@@ -245,6 +250,7 @@ export {}
/** /**
* @typedef {{ * @typedef {{
* sourceKey?: string
* baseUrl?: string * baseUrl?: string
* token?: string * token?: string
* deviceId?: string * deviceId?: string
@@ -254,6 +260,7 @@ export {}
/** /**
* @typedef {{ * @typedef {{
* sourceKey?: string
* baseUrl?: string * baseUrl?: string
* token?: string * token?: string
* deviceId?: string * deviceId?: string
@@ -265,6 +272,7 @@ export {}
/** /**
* @typedef {{ * @typedef {{
* sourceKey?: string
* baseUrl?: string * baseUrl?: string
* token?: string * token?: string
* deviceId?: string * deviceId?: string
@@ -277,6 +285,7 @@ export {}
/** /**
* @typedef {{ * @typedef {{
* sourceKey?: string
* baseUrl?: string * baseUrl?: string
* token?: string * token?: string
* deviceId?: string * deviceId?: string
@@ -290,6 +299,7 @@ export {}
/** /**
* @typedef {{ * @typedef {{
* sourceKey?: string
* baseUrl?: string * baseUrl?: string
* token?: string * token?: string
* deviceId?: string * deviceId?: string