114 lines
3.6 KiB
TypeScript
114 lines
3.6 KiB
TypeScript
import { z } from 'zod';
|
||
|
||
const uuidSchema = z.uuid();
|
||
const currencyCodeSchema = z
|
||
.string()
|
||
.regex(/^[A-Z]{3}$/, '必须是 ISO 4217 大写币种代码');
|
||
|
||
/** 创建门店时唯一允许提交明文 API Key 的请求契约。 */
|
||
export const createStoreRequestSchema = z
|
||
.object({
|
||
platform_id: uuidSchema,
|
||
name: z.string().trim().min(1).max(120),
|
||
client_id: z.string().trim().min(1).max(120),
|
||
api_key: z.string().min(1).max(8_192),
|
||
currency_code: currencyCodeSchema,
|
||
is_default: z.boolean().default(false),
|
||
note: z.string().trim().max(2_000).nullable().optional(),
|
||
})
|
||
.strict();
|
||
|
||
/** 修改门店不允许变更平台或平台账户,避免授权连接身份被悄然替换。 */
|
||
export const updateStoreRequestSchema = z
|
||
.object({
|
||
name: z.string().trim().min(1).max(120).optional(),
|
||
currency_code: currencyCodeSchema.optional(),
|
||
note: z.string().trim().max(2_000).nullable().optional(),
|
||
api_key: z.string().min(1).max(8_192).optional(),
|
||
})
|
||
.strict()
|
||
.refine((value) => Object.keys(value).length > 0, {
|
||
message: '至少需要提交一个可修改字段',
|
||
});
|
||
|
||
export const listStoresQuerySchema = z
|
||
.object({
|
||
platform_id: uuidSchema,
|
||
cursor: z.string().min(1).optional(),
|
||
limit: z.coerce.number().int().min(1).max(100).default(20),
|
||
})
|
||
.strict();
|
||
|
||
export type CreateStoreRequest = z.infer<typeof createStoreRequestSchema>;
|
||
export type UpdateStoreRequest = z.infer<typeof updateStoreRequestSchema>;
|
||
export type ListStoresQuery = z.infer<typeof listStoresQuerySchema>;
|
||
|
||
export type Store = {
|
||
id: string;
|
||
platform_id: string;
|
||
name: string;
|
||
platform_client_id: string;
|
||
currency_code: string;
|
||
is_default: boolean;
|
||
note: string | null;
|
||
status: string;
|
||
credential_status: string;
|
||
credential_checked_at: string | null;
|
||
last_error: { code: string; message: string; at: string } | null;
|
||
api_key_expires_at: string | null;
|
||
product_limit: number | null;
|
||
product_limit_checked_at: string | null;
|
||
warehouse_count: number;
|
||
warehouses_synced_at: string | null;
|
||
cookie_status: null;
|
||
watermark_template: { id: string; name: string } | null;
|
||
created_at: string;
|
||
updated_at: string;
|
||
revision: number;
|
||
};
|
||
|
||
export type Operation = {
|
||
id: string;
|
||
kind: string;
|
||
status: string;
|
||
created_at: string;
|
||
completed_at: string | null;
|
||
error: { code: string; message: string } | null;
|
||
};
|
||
|
||
/** GET /api/platforms 返回的平台目录项,能力字段无配置时为 null(docs/api/stores-and-platforms.md §1)。 */
|
||
export type Platform = {
|
||
id: string;
|
||
code: string;
|
||
name: string;
|
||
supported_currencies: string[];
|
||
default_market_code: string | null;
|
||
default_locale: string | null;
|
||
/** 平台新建店铺时预选的计价币种;未配置时前端回退到第一项可用币种。 */
|
||
default_currency_code: string | null;
|
||
};
|
||
|
||
/** GET /api/platform-context 返回的页头上下文;没有默认店铺不是错误。 */
|
||
export type PlatformContext = {
|
||
platform: { id: string; code: string; name: string };
|
||
default_store: {
|
||
id: string;
|
||
name: string;
|
||
status: string;
|
||
credential_status: string;
|
||
} | null;
|
||
store_count: number;
|
||
};
|
||
|
||
/** 游标分页 meta(docs/api/conventions.md),next_cursor 为 null 表示没有更多数据。 */
|
||
export type CursorPaginationMeta = {
|
||
next_cursor: string | null;
|
||
has_more: boolean;
|
||
};
|
||
|
||
/** 创建门店与重新验证凭据等异步动作的 202 响应。 */
|
||
export type StoreOperationResponse = {
|
||
store: Store;
|
||
operation: Operation;
|
||
};
|