@lofder/dsers-mcp-product 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +210 -0
- package/dist/dsers/account.d.ts +17 -0
- package/dist/dsers/account.d.ts.map +1 -0
- package/dist/dsers/account.js +37 -0
- package/dist/dsers/account.js.map +1 -0
- package/dist/dsers/auth.d.ts +14 -0
- package/dist/dsers/auth.d.ts.map +1 -0
- package/dist/dsers/auth.js +87 -0
- package/dist/dsers/auth.js.map +1 -0
- package/dist/dsers/client.d.ts +21 -0
- package/dist/dsers/client.d.ts.map +1 -0
- package/dist/dsers/client.js +78 -0
- package/dist/dsers/client.js.map +1 -0
- package/dist/dsers/config.d.ts +9 -0
- package/dist/dsers/config.d.ts.map +1 -0
- package/dist/dsers/config.js +28 -0
- package/dist/dsers/config.js.map +1 -0
- package/dist/dsers/product.d.ts +42 -0
- package/dist/dsers/product.d.ts.map +1 -0
- package/dist/dsers/product.js +289 -0
- package/dist/dsers/product.js.map +1 -0
- package/dist/dsers/settings.d.ts +30 -0
- package/dist/dsers/settings.d.ts.map +1 -0
- package/dist/dsers/settings.js +63 -0
- package/dist/dsers/settings.js.map +1 -0
- package/dist/error-map.d.ts +7 -0
- package/dist/error-map.d.ts.map +1 -0
- package/dist/error-map.js +231 -0
- package/dist/error-map.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -0
- package/dist/job-store-memory.d.ts +8 -0
- package/dist/job-store-memory.d.ts.map +1 -0
- package/dist/job-store-memory.js +60 -0
- package/dist/job-store-memory.js.map +1 -0
- package/dist/job-store.d.ts +14 -0
- package/dist/job-store.d.ts.map +1 -0
- package/dist/job-store.js +31 -0
- package/dist/job-store.js.map +1 -0
- package/dist/provider.d.ts +53 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +1298 -0
- package/dist/provider.js.map +1 -0
- package/dist/push-options.d.ts +7 -0
- package/dist/push-options.d.ts.map +1 -0
- package/dist/push-options.js +158 -0
- package/dist/push-options.js.map +1 -0
- package/dist/resolver.d.ts +8 -0
- package/dist/resolver.d.ts.map +1 -0
- package/dist/resolver.js +81 -0
- package/dist/resolver.js.map +1 -0
- package/dist/rules.d.ts +14 -0
- package/dist/rules.d.ts.map +1 -0
- package/dist/rules.js +332 -0
- package/dist/rules.js.map +1 -0
- package/dist/service.d.ts +22 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +461 -0
- package/dist/service.js.map +1 -0
- package/dist/tools.d.ts +4 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +402 -0
- package/dist/tools.js.map +1 -0
- package/package.json +54 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 lofder
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# DSers MCP Product — Automate Dropshipping AI tools/AliExpress to Shopify & Wix Import
|
|
2
|
+
|
|
3
|
+
[](https://smithery.ai/server/@dsersx/product-mcp)
|
|
4
|
+
|
|
5
|
+
> An open-source MCP server to automate DSers product import, bulk edit variants, and push to Shopify or Wix using AI.
|
|
6
|
+
|
|
7
|
+
> [English](#english) | [中文](#中文)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
<a id="english"></a>
|
|
12
|
+
|
|
13
|
+
## English
|
|
14
|
+
|
|
15
|
+
**DSers MCP Product** is an open-source [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) server that lets AI Agents automate the entire DSers import workflow — from AliExpress / Alibaba / 1688 product URL to Shopify or Wix store listing. Bulk import, batch edit variants, clean AliExpress titles, apply pricing rules, and push to multiple stores — all with a single sentence to your AI agent.
|
|
16
|
+
|
|
17
|
+
The server is hosted on [Vercel](https://dsers-mcp-product.vercel.app/api/mcp) and published on [Smithery](https://smithery.ai/server/@dsersx/product-mcp) for instant connection.
|
|
18
|
+
|
|
19
|
+
### Documentation
|
|
20
|
+
|
|
21
|
+
| Document | Description |
|
|
22
|
+
|----------|-------------|
|
|
23
|
+
| [ARCHITECTURE.md](ARCHITECTURE.md) | Three-layer architecture, directory structure, data flow |
|
|
24
|
+
| [USAGE.md](USAGE.md) | Installation, client config (Cursor, Claude Desktop), scenario examples |
|
|
25
|
+
| [SKILL.md](SKILL.md) | AI agent instruction file — workflow, rules, push options, error handling |
|
|
26
|
+
| [SKILL-CN.md](SKILL-CN.md) | Chinese human-readable guide for SKILL.md |
|
|
27
|
+
|
|
28
|
+
### Install via Smithery
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npx @smithery/cli mcp add @dsersx/product-mcp --client cursor
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Or browse at [smithery.ai/server/@dsersx/product-mcp](https://smithery.ai/server/@dsersx/product-mcp).
|
|
35
|
+
|
|
36
|
+
### Install from Source
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Clone
|
|
40
|
+
git clone https://github.com/lofder/dsers-mcp-product.git
|
|
41
|
+
cd dsers-mcp-product
|
|
42
|
+
|
|
43
|
+
# Install
|
|
44
|
+
npm install
|
|
45
|
+
|
|
46
|
+
# Configure (copy and fill in your DSers credentials)
|
|
47
|
+
cp .env.example .env
|
|
48
|
+
|
|
49
|
+
# Type check
|
|
50
|
+
npx tsc --noEmit
|
|
51
|
+
|
|
52
|
+
# Run with Smithery dev
|
|
53
|
+
npx @smithery/cli dev ./src/index.ts
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Project Structure
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
dsers-mcp-product/
|
|
60
|
+
├── src/
|
|
61
|
+
│ ├── index.ts # MCP server entry — tool registration
|
|
62
|
+
│ ├── service.ts # Import flow orchestration (7 operations)
|
|
63
|
+
│ ├── provider.ts # DSers API adapter
|
|
64
|
+
│ ├── rules.ts # Rule validation & application engine
|
|
65
|
+
│ ├── push-options.ts # Push option normalization
|
|
66
|
+
│ ├── resolver.ts # URL normalization (AliExpress/Alibaba/1688)
|
|
67
|
+
│ ├── job-store.ts # File-based job persistence
|
|
68
|
+
│ └── dsers/ # Low-level DSers API wrappers
|
|
69
|
+
│ ├── config.ts # Configuration & environment
|
|
70
|
+
│ ├── auth.ts # Login, session cache, auto-refresh
|
|
71
|
+
│ ├── client.ts # Authenticated HTTP client
|
|
72
|
+
│ ├── account.ts # Store & user management APIs
|
|
73
|
+
│ ├── product.ts # Import list & push APIs
|
|
74
|
+
│ └── settings.ts # Shipping, pricing, billing APIs
|
|
75
|
+
├── test/ # Smoke tests
|
|
76
|
+
├── smithery.yaml # Smithery runtime config
|
|
77
|
+
├── package.json
|
|
78
|
+
├── tsconfig.json
|
|
79
|
+
└── .env.example
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Seven Tools
|
|
83
|
+
|
|
84
|
+
| # | Tool | Title | Description |
|
|
85
|
+
|---|------|-------|-------------|
|
|
86
|
+
| 1 | `dsers.store.discover` | DSers Store & Rule Discovery | Discover stores, shipping profiles, supported rules |
|
|
87
|
+
| 2 | `dsers.rules.validate` | Pricing & Content Rule Validator | Dry-run rule validation |
|
|
88
|
+
| 3 | `dsers.product.import` | AliExpress / Alibaba / 1688 Import | Import from URL(s), apply rules, get preview |
|
|
89
|
+
| 4 | `dsers.product.preview` | Import Draft Preview | Reload a saved preview |
|
|
90
|
+
| 5 | `dsers.product.visibility` | Shopify / Wix Visibility Toggle | Toggle draft / published |
|
|
91
|
+
| 6 | `dsers.store.push` | Push to Shopify / Wix Store | Push single/batch/multi-store |
|
|
92
|
+
| 7 | `dsers.job.status` | Job Status Tracker | Check push result |
|
|
93
|
+
|
|
94
|
+
All tools include MCP annotations (`readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`) and return structured error messages with `{Error, Cause, Action}` for AI agent consumption.
|
|
95
|
+
|
|
96
|
+
### Three Prompts
|
|
97
|
+
|
|
98
|
+
Pre-built workflow templates that MCP clients can present to users:
|
|
99
|
+
|
|
100
|
+
| Prompt | Description |
|
|
101
|
+
|--------|-------------|
|
|
102
|
+
| `dsers.workflow.quick-import` | Import a single product and push to store as draft |
|
|
103
|
+
| `dsers.workflow.bulk-import` | Batch import with pricing multiplier |
|
|
104
|
+
| `dsers.workflow.multi-push` | Push one product to all connected stores |
|
|
105
|
+
|
|
106
|
+
### Credentials
|
|
107
|
+
|
|
108
|
+
The server supports two credential sources (checked in order):
|
|
109
|
+
|
|
110
|
+
1. **HTTP headers** `x-dsers-email` / `x-dsers-password` — used by Smithery and direct HTTP connections
|
|
111
|
+
2. **Environment variables** `DSERS_EMAIL` / `DSERS_PASSWORD` — used by local stdio (Cursor, Claude Desktop)
|
|
112
|
+
|
|
113
|
+
See [USAGE.md](USAGE.md) for setup details per connection method.
|
|
114
|
+
|
|
115
|
+
### Environment Variables
|
|
116
|
+
|
|
117
|
+
| Variable | Required | Description |
|
|
118
|
+
|----------|----------|-------------|
|
|
119
|
+
| `DSERS_EMAIL` | Yes* | DSers account email (*or provide via HTTP header) |
|
|
120
|
+
| `DSERS_PASSWORD` | Yes* | DSers account password (*or provide via HTTP header) |
|
|
121
|
+
| `DSERS_ENV` | No | `production` (default) or `test` |
|
|
122
|
+
| `DSERS_BASE_URL` | No | Override API base URL |
|
|
123
|
+
| `IMPORT_MCP_STATE_DIR` | No | Job state directory (default: `.state`) |
|
|
124
|
+
|
|
125
|
+
### Also Available
|
|
126
|
+
|
|
127
|
+
A [Python version](https://github.com/lofder/dsers-mcp-product-py) is available for local stdio deployments.
|
|
128
|
+
|
|
129
|
+
### License
|
|
130
|
+
|
|
131
|
+
MIT
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
<a id="中文"></a>
|
|
136
|
+
|
|
137
|
+
## 中文
|
|
138
|
+
|
|
139
|
+
**DSers MCP Product** 是一个开源的 [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) 服务器,让 AI Agent 自动完成 DSers 的整个商品导入流程 —— 从速卖通 / Alibaba / 1688 商品链接到 Shopify 或 Wix 店铺上架。批量导入、批量编辑变体、清理速卖通标题、应用定价规则、推送到多个店铺 —— 只需一句话给你的 AI agent。
|
|
140
|
+
|
|
141
|
+
服务已托管在 [Vercel](https://dsers-mcp-product.vercel.app/api/mcp) 并发布到 [Smithery](https://smithery.ai/server/@dsersx/product-mcp),可即时连接使用。
|
|
142
|
+
|
|
143
|
+
### 文档
|
|
144
|
+
|
|
145
|
+
| 文档 | 说明 |
|
|
146
|
+
|------|------|
|
|
147
|
+
| [ARCHITECTURE.md](ARCHITECTURE.md) | 三层架构、目录结构、数据流 |
|
|
148
|
+
| [USAGE.md](USAGE.md) | 安装、客户端配置(Cursor、Claude Desktop)、使用场景 |
|
|
149
|
+
| [SKILL.md](SKILL.md) | AI agent 指令文件 — 工作流、规则、推送选项、错误处理 |
|
|
150
|
+
| [SKILL-CN.md](SKILL-CN.md) | SKILL.md 的中文说明 |
|
|
151
|
+
|
|
152
|
+
### 通过 Smithery 安装
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
npx @smithery/cli mcp add @dsersx/product-mcp --client cursor
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
或在 [smithery.ai/server/@dsersx/product-mcp](https://smithery.ai/server/@dsersx/product-mcp) 浏览和安装。
|
|
159
|
+
|
|
160
|
+
### 从源码安装
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
# 克隆
|
|
164
|
+
git clone https://github.com/lofder/dsers-mcp-product.git
|
|
165
|
+
cd dsers-mcp-product
|
|
166
|
+
|
|
167
|
+
# 安装
|
|
168
|
+
npm install
|
|
169
|
+
|
|
170
|
+
# 配置(复制并填写你的 DSers 账户信息)
|
|
171
|
+
cp .env.example .env
|
|
172
|
+
|
|
173
|
+
# 类型检查
|
|
174
|
+
npx tsc --noEmit
|
|
175
|
+
|
|
176
|
+
# 开发运行
|
|
177
|
+
npx @smithery/cli dev ./src/index.ts
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### 七个工具
|
|
181
|
+
|
|
182
|
+
| # | 工具 | 标题 | 说明 |
|
|
183
|
+
|---|------|------|------|
|
|
184
|
+
| 1 | `dsers.store.discover` | 店铺与规则发现 | 查询店铺、配送方案、支持的规则 |
|
|
185
|
+
| 2 | `dsers.rules.validate` | 定价与内容规则校验 | 规则校验试运行 |
|
|
186
|
+
| 3 | `dsers.product.import` | 速卖通/Alibaba/1688 导入 | 从 URL 导入、应用规则、获取预览 |
|
|
187
|
+
| 4 | `dsers.product.preview` | 导入草稿预览 | 重新加载已保存的预览 |
|
|
188
|
+
| 5 | `dsers.product.visibility` | Shopify/Wix 可见性切换 | 切换草稿 / 上架 |
|
|
189
|
+
| 6 | `dsers.store.push` | 推送到 Shopify/Wix | 单条/批量/多店铺推送 |
|
|
190
|
+
| 7 | `dsers.job.status` | 任务状态跟踪 | 查看推送结果 |
|
|
191
|
+
|
|
192
|
+
所有工具均包含 MCP 注解(`readOnlyHint`、`destructiveHint`、`idempotentHint`、`openWorldHint`),错误返回结构化格式 `{Error, Cause, Action}`,方便 AI agent 理解和处理。
|
|
193
|
+
|
|
194
|
+
### 三个预设提示
|
|
195
|
+
|
|
196
|
+
MCP 客户端可直接展示给用户的工作流模板:
|
|
197
|
+
|
|
198
|
+
| 提示 | 说明 |
|
|
199
|
+
|------|------|
|
|
200
|
+
| `dsers.workflow.quick-import` | 一键导入单个商品并推送为草稿 |
|
|
201
|
+
| `dsers.workflow.bulk-import` | 批量导入 + 统一定价倍率 |
|
|
202
|
+
| `dsers.workflow.multi-push` | 一个商品推送到所有店铺 |
|
|
203
|
+
|
|
204
|
+
### 其他版本
|
|
205
|
+
|
|
206
|
+
也提供 [Python 版本](https://github.com/lofder/dsers-mcp-product-py),适用于本地 stdio 部署。
|
|
207
|
+
|
|
208
|
+
### 许可证
|
|
209
|
+
|
|
210
|
+
MIT
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DSers Account API – BFF wrappers for stores, users, staffs, suppliers, and apps.
|
|
3
|
+
*/
|
|
4
|
+
import type { DSersClient } from "./client.js";
|
|
5
|
+
export declare function listStores(client: DSersClient): Promise<Record<string, unknown>>;
|
|
6
|
+
export declare function getStoreDetail(client: DSersClient, storeId: string): Promise<Record<string, unknown>>;
|
|
7
|
+
export declare function getUserInfo(client: DSersClient): Promise<Record<string, unknown>>;
|
|
8
|
+
export declare function updateUserInfo(client: DSersClient, body: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
9
|
+
export declare function bindStore(client: DSersClient, platform: string, authCode: string): Promise<Record<string, unknown>>;
|
|
10
|
+
export declare function unbindStore(client: DSersClient, storeId: string): Promise<Record<string, unknown>>;
|
|
11
|
+
export declare function listStaff(client: DSersClient): Promise<Record<string, unknown>>;
|
|
12
|
+
export declare function inviteStaff(client: DSersClient, email: string, permissions: string[]): Promise<Record<string, unknown>>;
|
|
13
|
+
export declare function removeStaff(client: DSersClient, staffId: string): Promise<Record<string, unknown>>;
|
|
14
|
+
export declare function updateStaffPermission(client: DSersClient, staffId: string, permissions: string[]): Promise<Record<string, unknown>>;
|
|
15
|
+
export declare function listSuppliers(client: DSersClient): Promise<Record<string, unknown>>;
|
|
16
|
+
export declare function listApps(client: DSersClient): Promise<Record<string, unknown>>;
|
|
17
|
+
//# sourceMappingURL=account.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account.d.ts","sourceRoot":"","sources":["../../src/dsers/account.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,wBAAsB,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAEtF;AAED,wBAAsB,cAAc,CAClC,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAElC;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAEvF;AAED,wBAAsB,cAAc,CAClC,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAElC;AAED,wBAAsB,SAAS,CAC7B,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAElC;AAED,wBAAsB,WAAW,CAC/B,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAElC;AAED,wBAAsB,SAAS,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAErF;AAED,wBAAsB,WAAW,CAC/B,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EAAE,GACpB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAElC;AAED,wBAAsB,WAAW,CAC/B,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAElC;AAED,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EAAE,GACpB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAElC;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAEzF;AAED,wBAAsB,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAEpF"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export async function listStores(client) {
|
|
2
|
+
return client.post("/account-user-bff/v1/stores/user/list");
|
|
3
|
+
}
|
|
4
|
+
export async function getStoreDetail(client, storeId) {
|
|
5
|
+
return client.get("/account-user-bff/v1/stores/detail", { storeId });
|
|
6
|
+
}
|
|
7
|
+
export async function getUserInfo(client) {
|
|
8
|
+
return client.get("/account-user-bff/v1/users/info");
|
|
9
|
+
}
|
|
10
|
+
export async function updateUserInfo(client, body) {
|
|
11
|
+
return client.post("/account-user-bff/v1/users/info", body);
|
|
12
|
+
}
|
|
13
|
+
export async function bindStore(client, platform, authCode) {
|
|
14
|
+
return client.post("/account-user-bff/v1/stores/bindStore", { platform, authCode });
|
|
15
|
+
}
|
|
16
|
+
export async function unbindStore(client, storeId) {
|
|
17
|
+
return client.post("/account-user-bff/v1/stores/unbind", { storeId });
|
|
18
|
+
}
|
|
19
|
+
export async function listStaff(client) {
|
|
20
|
+
return client.post("/account-user-bff/v1/staffs/list");
|
|
21
|
+
}
|
|
22
|
+
export async function inviteStaff(client, email, permissions) {
|
|
23
|
+
return client.post("/account-user-bff/v1/staffs/invite", { email, permissions });
|
|
24
|
+
}
|
|
25
|
+
export async function removeStaff(client, staffId) {
|
|
26
|
+
return client.post("/account-user-bff/v1/staffs/remove", { staffId });
|
|
27
|
+
}
|
|
28
|
+
export async function updateStaffPermission(client, staffId, permissions) {
|
|
29
|
+
return client.post("/account-user-bff/v1/staffs/permission", { staffId, permissions });
|
|
30
|
+
}
|
|
31
|
+
export async function listSuppliers(client) {
|
|
32
|
+
return client.get("/account-user-bff/v1/suppliers/list");
|
|
33
|
+
}
|
|
34
|
+
export async function listApps(client) {
|
|
35
|
+
return client.get("/account-user-bff/v1/apps/list");
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=account.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account.js","sourceRoot":"","sources":["../../src/dsers/account.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAmB;IAClD,OAAO,MAAM,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAmB,EACnB,OAAe;IAEf,OAAO,MAAM,CAAC,GAAG,CAAC,oCAAoC,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAmB;IACnD,OAAO,MAAM,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAmB,EACnB,IAA6B;IAE7B,OAAO,MAAM,CAAC,IAAI,CAAC,iCAAiC,EAAE,IAAI,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,MAAmB,EACnB,QAAgB,EAChB,QAAgB;IAEhB,OAAO,MAAM,CAAC,IAAI,CAAC,uCAAuC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;AACtF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAmB,EACnB,OAAe;IAEf,OAAO,MAAM,CAAC,IAAI,CAAC,oCAAoC,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;AACxE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,MAAmB;IACjD,OAAO,MAAM,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAmB,EACnB,KAAa,EACb,WAAqB;IAErB,OAAO,MAAM,CAAC,IAAI,CAAC,oCAAoC,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;AACnF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAmB,EACnB,OAAe;IAEf,OAAO,MAAM,CAAC,IAAI,CAAC,oCAAoC,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;AACxE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,MAAmB,EACnB,OAAe,EACf,WAAqB;IAErB,OAAO,MAAM,CAAC,IAAI,CAAC,wCAAwC,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;AACzF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAmB;IACrD,OAAO,MAAM,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,MAAmB;IAChD,OAAO,MAAM,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;AACtD,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { DSersConfig } from "./config.js";
|
|
2
|
+
export declare class DSersAuth {
|
|
3
|
+
private config;
|
|
4
|
+
private sessionId;
|
|
5
|
+
private state;
|
|
6
|
+
private fetchedAt;
|
|
7
|
+
constructor(config: DSersConfig);
|
|
8
|
+
getSession(): Promise<[string, string]>;
|
|
9
|
+
login(): Promise<[string, string]>;
|
|
10
|
+
invalidate(): void;
|
|
11
|
+
private readCache;
|
|
12
|
+
private writeCache;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/dsers/auth.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAU/C,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,SAAS,CAAK;gBAEV,MAAM,EAAE,WAAW;IAIzB,UAAU,IAAI,OAAO,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAcvC,KAAK,IAAI,OAAO,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAwCxC,UAAU,IAAI,IAAI;IAMlB,OAAO,CAAC,SAAS;IAYjB,OAAO,CAAC,UAAU;CAYnB"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { dirname } from "node:path";
|
|
4
|
+
const SESSION_TTL = 3600 * 6 * 1000; // 6 hours in ms
|
|
5
|
+
export class DSersAuth {
|
|
6
|
+
config;
|
|
7
|
+
sessionId = null;
|
|
8
|
+
state = null;
|
|
9
|
+
fetchedAt = 0;
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.config = config;
|
|
12
|
+
}
|
|
13
|
+
async getSession() {
|
|
14
|
+
if (this.sessionId && Date.now() - this.fetchedAt < SESSION_TTL) {
|
|
15
|
+
return [this.sessionId, this.state ?? ""];
|
|
16
|
+
}
|
|
17
|
+
const cached = this.readCache();
|
|
18
|
+
if (cached) {
|
|
19
|
+
[this.sessionId, this.state, this.fetchedAt] = cached;
|
|
20
|
+
return [this.sessionId, this.state];
|
|
21
|
+
}
|
|
22
|
+
return this.login();
|
|
23
|
+
}
|
|
24
|
+
async login() {
|
|
25
|
+
if (!this.config.email || !this.config.password) {
|
|
26
|
+
throw new Error("DSers credentials not found. Provide them through one of:\n" +
|
|
27
|
+
"1. Smithery config form (dsers_email / dsers_password fields)\n" +
|
|
28
|
+
"2. HTTP headers: x-dsers-email, x-dsers-password\n" +
|
|
29
|
+
"3. Environment variables: DSERS_EMAIL, DSERS_PASSWORD\n" +
|
|
30
|
+
"4. MCP client config env block (Cursor .cursor/mcp.json, Claude Desktop config)");
|
|
31
|
+
}
|
|
32
|
+
const resp = await fetch(`${this.config.baseUrl}/account-user-bff/v1/users/login`, {
|
|
33
|
+
method: "POST",
|
|
34
|
+
headers: { "Content-Type": "application/json" },
|
|
35
|
+
body: JSON.stringify({
|
|
36
|
+
email: this.config.email,
|
|
37
|
+
password: this.config.password,
|
|
38
|
+
}),
|
|
39
|
+
});
|
|
40
|
+
if (!resp.ok) {
|
|
41
|
+
throw new Error(`Login HTTP ${resp.status}: ${await resp.text()}`);
|
|
42
|
+
}
|
|
43
|
+
const data = (await resp.json());
|
|
44
|
+
const inner = data.data;
|
|
45
|
+
if (!inner?.sessionId) {
|
|
46
|
+
throw new Error(`Login failed: ${JSON.stringify(data)}`);
|
|
47
|
+
}
|
|
48
|
+
this.sessionId = inner.sessionId;
|
|
49
|
+
this.state = inner.state ?? "";
|
|
50
|
+
this.fetchedAt = Date.now();
|
|
51
|
+
this.writeCache();
|
|
52
|
+
return [this.sessionId, this.state];
|
|
53
|
+
}
|
|
54
|
+
invalidate() {
|
|
55
|
+
this.sessionId = null;
|
|
56
|
+
this.state = null;
|
|
57
|
+
this.fetchedAt = 0;
|
|
58
|
+
}
|
|
59
|
+
readCache() {
|
|
60
|
+
try {
|
|
61
|
+
const p = this.config.sessionFile;
|
|
62
|
+
if (!existsSync(p))
|
|
63
|
+
return null;
|
|
64
|
+
const obj = JSON.parse(readFileSync(p, "utf-8"));
|
|
65
|
+
if (Date.now() - obj.ts > SESSION_TTL)
|
|
66
|
+
return null;
|
|
67
|
+
return [obj.session_id, obj.state ?? "", obj.ts];
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
writeCache() {
|
|
74
|
+
try {
|
|
75
|
+
const p = this.config.sessionFile;
|
|
76
|
+
mkdirSync(dirname(p), { recursive: true });
|
|
77
|
+
const payload = {
|
|
78
|
+
session_id: this.sessionId,
|
|
79
|
+
state: this.state ?? "",
|
|
80
|
+
ts: this.fetchedAt,
|
|
81
|
+
};
|
|
82
|
+
writeFileSync(p, JSON.stringify(payload), "utf-8");
|
|
83
|
+
}
|
|
84
|
+
catch { /* graceful fallback to in-memory only */ }
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/dsers/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { DSersConfig } from "./config.js";
|
|
2
|
+
export declare class DSersAPIError extends Error {
|
|
3
|
+
status: number;
|
|
4
|
+
body: string;
|
|
5
|
+
constructor(status: number, body: string);
|
|
6
|
+
}
|
|
7
|
+
export declare class DSersClient {
|
|
8
|
+
private config;
|
|
9
|
+
private auth;
|
|
10
|
+
constructor(config: DSersConfig);
|
|
11
|
+
request(method: string, path: string, opts?: {
|
|
12
|
+
params?: Record<string, any>;
|
|
13
|
+
json?: Record<string, any>;
|
|
14
|
+
}, retried?: boolean): Promise<Record<string, any>>;
|
|
15
|
+
get(path: string, params?: Record<string, any>): Promise<Record<string, any>>;
|
|
16
|
+
post(path: string, json?: Record<string, any>, params?: Record<string, any>): Promise<Record<string, any>>;
|
|
17
|
+
put(path: string, json?: Record<string, any>, params?: Record<string, any>): Promise<Record<string, any>>;
|
|
18
|
+
delete(path: string, params?: Record<string, any>): Promise<Record<string, any>>;
|
|
19
|
+
login(): Promise<Record<string, any>>;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/dsers/client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAS/C,qBAAa,aAAc,SAAQ,KAAK;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;gBACD,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;CAKzC;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,IAAI,CAAY;gBAEZ,MAAM,EAAE,WAAW;IAKzB,OAAO,CACX,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE;QACL,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC7B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;KAC5B,EACD,OAAO,UAAQ,GACd,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IA2CzB,GAAG,CACP,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC3B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAIzB,IAAI,CACR,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC1B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC3B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAIzB,GAAG,CACP,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC1B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC3B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAIzB,MAAM,CACV,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC3B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAIzB,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAI5C"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { DSersAuth } from "./auth.js";
|
|
2
|
+
const RETRYABLE_REASONS = new Set([
|
|
3
|
+
"TOKEN_NOT_FOUND",
|
|
4
|
+
"TOKEN_EXPIRED",
|
|
5
|
+
"UNAUTHORIZED",
|
|
6
|
+
"INVALID_TOKEN",
|
|
7
|
+
]);
|
|
8
|
+
export class DSersAPIError extends Error {
|
|
9
|
+
status;
|
|
10
|
+
body;
|
|
11
|
+
constructor(status, body) {
|
|
12
|
+
super(`DSers API ${status}: ${body.slice(0, 500)}`);
|
|
13
|
+
this.status = status;
|
|
14
|
+
this.body = body;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export class DSersClient {
|
|
18
|
+
config;
|
|
19
|
+
auth;
|
|
20
|
+
constructor(config) {
|
|
21
|
+
this.config = config;
|
|
22
|
+
this.auth = new DSersAuth(config);
|
|
23
|
+
}
|
|
24
|
+
async request(method, path, opts, retried = false) {
|
|
25
|
+
const [sessionId, state] = await this.auth.getSession();
|
|
26
|
+
const url = new URL(`${this.config.baseUrl}${path}`);
|
|
27
|
+
if (opts?.params) {
|
|
28
|
+
for (const [k, v] of Object.entries(opts.params)) {
|
|
29
|
+
if (v != null)
|
|
30
|
+
url.searchParams.set(k, String(v));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const headers = {
|
|
34
|
+
"Content-Type": "application/json",
|
|
35
|
+
Authorization: `Bearer ${sessionId}`,
|
|
36
|
+
Cookie: `session_id=${sessionId}; state=${state}`,
|
|
37
|
+
};
|
|
38
|
+
const resp = await fetch(url.toString(), {
|
|
39
|
+
method,
|
|
40
|
+
headers,
|
|
41
|
+
body: opts?.json ? JSON.stringify(opts.json) : undefined,
|
|
42
|
+
});
|
|
43
|
+
const bodyText = await resp.text();
|
|
44
|
+
if (resp.status === 400 && !retried) {
|
|
45
|
+
try {
|
|
46
|
+
const body = JSON.parse(bodyText);
|
|
47
|
+
if (RETRYABLE_REASONS.has(body.reason)) {
|
|
48
|
+
this.auth.invalidate();
|
|
49
|
+
return this.request(method, path, opts, true);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// not JSON, fall through to error
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (resp.status >= 400) {
|
|
57
|
+
throw new DSersAPIError(resp.status, bodyText);
|
|
58
|
+
}
|
|
59
|
+
return JSON.parse(bodyText);
|
|
60
|
+
}
|
|
61
|
+
async get(path, params) {
|
|
62
|
+
return this.request("GET", path, { params });
|
|
63
|
+
}
|
|
64
|
+
async post(path, json, params) {
|
|
65
|
+
return this.request("POST", path, { json, params });
|
|
66
|
+
}
|
|
67
|
+
async put(path, json, params) {
|
|
68
|
+
return this.request("PUT", path, { json, params });
|
|
69
|
+
}
|
|
70
|
+
async delete(path, params) {
|
|
71
|
+
return this.request("DELETE", path, { params });
|
|
72
|
+
}
|
|
73
|
+
async login() {
|
|
74
|
+
const [sid, state] = await this.auth.login();
|
|
75
|
+
return { session_id: sid, state };
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/dsers/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface DSersConfig {
|
|
2
|
+
baseUrl: string;
|
|
3
|
+
email: string;
|
|
4
|
+
password: string;
|
|
5
|
+
sessionFile: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function configFromEnv(): DSersConfig;
|
|
8
|
+
export declare function configFromParams(email: string, password: string, env?: string): DSersConfig;
|
|
9
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/dsers/config.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,aAAa,IAAI,WAAW,CAY3C;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,GAAG,GAAE,MAAqB,GACzB,WAAW,CAIb"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { resolve, dirname } from "node:path";
|
|
2
|
+
const PROD_URL = "https://bff-api-gw.dsers.com";
|
|
3
|
+
const TEST_URL = "https://bff-api-gw-test.dsers.com";
|
|
4
|
+
function getSafeDir() {
|
|
5
|
+
try {
|
|
6
|
+
if (typeof import.meta?.url === "string" && import.meta.url.startsWith("file:")) {
|
|
7
|
+
const { fileURLToPath } = require("node:url");
|
|
8
|
+
return dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
catch { /* Workers runtime */ }
|
|
12
|
+
return process.cwd?.() ?? "/tmp";
|
|
13
|
+
}
|
|
14
|
+
export function configFromEnv() {
|
|
15
|
+
const env = (process.env.DSERS_ENV ?? "production").toLowerCase();
|
|
16
|
+
const baseUrl = process.env.DSERS_BASE_URL || (env === "test" ? TEST_URL : PROD_URL);
|
|
17
|
+
const email = process.env.DSERS_EMAIL ?? "";
|
|
18
|
+
const password = process.env.DSERS_PASSWORD ?? "";
|
|
19
|
+
const sessionFile = process.env.DSERS_SESSION_FILE ||
|
|
20
|
+
resolve(getSafeDir(), "..", "..", ".session.json");
|
|
21
|
+
return { baseUrl, email, password, sessionFile };
|
|
22
|
+
}
|
|
23
|
+
export function configFromParams(email, password, env = "production") {
|
|
24
|
+
const baseUrl = env === "test" ? TEST_URL : PROD_URL;
|
|
25
|
+
const sessionFile = resolve(getSafeDir(), "..", "..", ".session.json");
|
|
26
|
+
return { baseUrl, email, password, sessionFile };
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/dsers/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE7C,MAAM,QAAQ,GAAG,8BAA8B,CAAC;AAChD,MAAM,QAAQ,GAAG,mCAAmC,CAAC;AAErD,SAAS,UAAU;IACjB,IAAI,CAAC;QACH,IAAI,OAAO,MAAM,CAAC,IAAI,EAAE,GAAG,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAChF,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;YAC9C,OAAO,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAC,qBAAqB,CAAC,CAAC;IACjC,OAAO,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,MAAM,CAAC;AACnC,CAAC;AASD,MAAM,UAAU,aAAa;IAC3B,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,YAAY,CAAC,CAAC,WAAW,EAAE,CAAC;IAClE,MAAM,OAAO,GACX,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IACvE,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC;IAC5C,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,EAAE,CAAC;IAElD,MAAM,WAAW,GACf,OAAO,CAAC,GAAG,CAAC,kBAAkB;QAC9B,OAAO,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,eAAe,CAAC,CAAC;IAErD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,KAAa,EACb,QAAgB,EAChB,MAAc,YAAY;IAE1B,MAAM,OAAO,GAAG,GAAG,KAAK,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;IACrD,MAAM,WAAW,GAAG,OAAO,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,eAAe,CAAC,CAAC;IACvE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DSers Product API — BFF wrappers and push-flow utilities for dsers-product-bff.
|
|
3
|
+
*/
|
|
4
|
+
import type { DSersClient } from "./client.js";
|
|
5
|
+
export declare function cleanNone(value: unknown): unknown;
|
|
6
|
+
export declare function coerceIntId(value: unknown): unknown;
|
|
7
|
+
export declare function mergeLegacyPushSettings(target: Record<string, unknown>, source: unknown): void;
|
|
8
|
+
export declare function normalizePushProductPayload(args: Record<string, unknown>): Record<string, unknown>;
|
|
9
|
+
export declare function getImportList(client: DSersClient, params?: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
10
|
+
export declare function getImportListItem(client: DSersClient, id: string): Promise<Record<string, unknown>>;
|
|
11
|
+
export declare function importByProductId(client: DSersClient, body: {
|
|
12
|
+
supplyProductId: string;
|
|
13
|
+
supplyAppId: string | number;
|
|
14
|
+
country: string;
|
|
15
|
+
language?: string[];
|
|
16
|
+
}): Promise<Record<string, unknown>>;
|
|
17
|
+
export declare function importByProductIdBatch(client: DSersClient, body: {
|
|
18
|
+
supplyProductIds: string[];
|
|
19
|
+
supplyAppId: string | number;
|
|
20
|
+
country: string;
|
|
21
|
+
isBackError?: number;
|
|
22
|
+
}): Promise<Record<string, unknown>>;
|
|
23
|
+
export declare function updateImportListItem(client: DSersClient, id: string, updates: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
24
|
+
export declare function deleteImportList(client: DSersClient, ids: string): Promise<Record<string, unknown>>;
|
|
25
|
+
export declare function pushToStore(client: DSersClient, payload: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
26
|
+
export declare function pushBeforeCheck(client: DSersClient, body: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
27
|
+
export declare function getPushPrice(client: DSersClient, body: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
28
|
+
export declare function getPushLogistics(client: DSersClient, body: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
29
|
+
export declare function getPushStatus(client: DSersClient, eventId: string): Promise<Record<string, unknown>>;
|
|
30
|
+
export declare function getStoreShippingProfile(client: DSersClient, storeId?: string): Promise<Record<string, unknown>>;
|
|
31
|
+
export declare function getShopifyShippingProfiles(client: DSersClient): Promise<Record<string, unknown>>;
|
|
32
|
+
export declare function listImportTags(client: DSersClient): Promise<Record<string, unknown>>;
|
|
33
|
+
export declare function getMyProducts(client: DSersClient, params: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
34
|
+
export declare function getMapping(client: DSersClient, dsersProductId: string): Promise<Record<string, unknown>>;
|
|
35
|
+
export declare function findSuppliers(client: DSersClient, params: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
36
|
+
export declare function parseProductUrl(client: DSersClient, url: string, appId: string | number): Promise<Record<string, unknown>>;
|
|
37
|
+
export declare function getPoolProductDetail(client: DSersClient, params: {
|
|
38
|
+
productId: string;
|
|
39
|
+
appId: number;
|
|
40
|
+
shipTo: string;
|
|
41
|
+
}): Promise<Record<string, unknown>>;
|
|
42
|
+
//# sourceMappingURL=product.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"product.d.ts","sourceRoot":"","sources":["../../src/dsers/product.ts"],"names":[],"mappings":"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"}
|