@lofder/dsers-mcp-product 1.5.0 → 1.5.3
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/CHANGELOG.md +201 -8
- package/README.md +1 -0
- package/dist/auth/oauth.d.ts.map +1 -1
- package/dist/auth/oauth.js +96 -56
- package/dist/auth/oauth.js.map +1 -1
- package/dist/auth/token-store.d.ts.map +1 -1
- package/dist/auth/token-store.js +80 -27
- package/dist/auth/token-store.js.map +1 -1
- package/dist/cli.js +39 -25
- package/dist/cli.js.map +1 -1
- package/dist/dsers/auth.d.ts +1 -0
- package/dist/dsers/auth.d.ts.map +1 -1
- package/dist/dsers/auth.js +55 -32
- package/dist/dsers/auth.js.map +1 -1
- package/dist/dsers/client.d.ts +0 -2
- package/dist/dsers/client.d.ts.map +1 -1
- package/dist/dsers/client.js +29 -18
- package/dist/dsers/client.js.map +1 -1
- package/dist/dsers/product.d.ts +4 -1
- package/dist/dsers/product.d.ts.map +1 -1
- package/dist/dsers/product.js +26 -18
- package/dist/dsers/product.js.map +1 -1
- package/dist/error-map.d.ts.map +1 -1
- package/dist/error-map.js +12 -5
- package/dist/error-map.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/dist/instructions.d.ts.map +1 -1
- package/dist/instructions.js +12 -0
- package/dist/instructions.js.map +1 -1
- package/dist/job-store-memory.d.ts.map +1 -1
- package/dist/job-store-memory.js +2 -43
- package/dist/job-store-memory.js.map +1 -1
- package/dist/job-store.d.ts.map +1 -1
- package/dist/job-store.js +5 -1
- package/dist/job-store.js.map +1 -1
- package/dist/logger.d.ts +3 -7
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +13 -10
- package/dist/logger.js.map +1 -1
- package/dist/oauth/crypto.d.ts +4 -1
- package/dist/oauth/crypto.d.ts.map +1 -1
- package/dist/oauth/crypto.js +10 -1
- package/dist/oauth/crypto.js.map +1 -1
- package/dist/provider/helpers.d.ts +2 -2
- package/dist/provider/helpers.d.ts.map +1 -1
- package/dist/provider/helpers.js +28 -10
- package/dist/provider/helpers.js.map +1 -1
- package/dist/provider/import-ops.d.ts.map +1 -1
- package/dist/provider/import-ops.js +7 -4
- package/dist/provider/import-ops.js.map +1 -1
- package/dist/provider/index.d.ts +1 -0
- package/dist/provider/index.d.ts.map +1 -1
- package/dist/provider/index.js +3 -1
- package/dist/provider/index.js.map +1 -1
- package/dist/provider/normalize.d.ts.map +1 -1
- package/dist/provider/normalize.js +13 -9
- package/dist/provider/normalize.js.map +1 -1
- package/dist/provider/push.d.ts.map +1 -1
- package/dist/provider/push.js +4 -3
- package/dist/provider/push.js.map +1 -1
- package/dist/provider/sku-matcher.d.ts +26 -23
- package/dist/provider/sku-matcher.d.ts.map +1 -1
- package/dist/provider/sku-matcher.js +82 -51
- package/dist/provider/sku-matcher.js.map +1 -1
- package/dist/provider/store.d.ts +1 -1
- package/dist/provider/store.d.ts.map +1 -1
- package/dist/provider/store.js +7 -5
- package/dist/provider/store.js.map +1 -1
- package/dist/rules.d.ts.map +1 -1
- package/dist/rules.js +60 -4
- package/dist/rules.js.map +1 -1
- package/dist/service/browse-shared.d.ts +1 -0
- package/dist/service/browse-shared.d.ts.map +1 -1
- package/dist/service/browse-shared.js +3 -1
- package/dist/service/browse-shared.js.map +1 -1
- package/dist/service/find-product.d.ts.map +1 -1
- package/dist/service/find-product.js +33 -6
- package/dist/service/find-product.js.map +1 -1
- package/dist/service/import-list.d.ts.map +1 -1
- package/dist/service/import-list.js +5 -2
- package/dist/service/import-list.js.map +1 -1
- package/dist/service/index.d.ts.map +1 -1
- package/dist/service/index.js +8 -5
- package/dist/service/index.js.map +1 -1
- package/dist/service/preview.d.ts.map +1 -1
- package/dist/service/preview.js +7 -3
- package/dist/service/preview.js.map +1 -1
- package/dist/service/push-flow.d.ts.map +1 -1
- package/dist/service/push-flow.js +23 -15
- package/dist/service/push-flow.js.map +1 -1
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +7 -3
- package/dist/tools.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/util.d.ts +6 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +25 -0
- package/dist/util.js.map +1 -0
- package/package.json +6 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,203 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> [English](#english) | [中文](#中文)
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<a id="english"></a>
|
|
8
|
+
|
|
9
|
+
## English
|
|
10
|
+
|
|
11
|
+
### 1.5.1 — 2026-04-10
|
|
12
|
+
|
|
13
|
+
Security hardening + 7 bugfixes from npm testing. No new tools, no algorithm changes — purely defensive.
|
|
14
|
+
|
|
15
|
+
#### Bugfixes
|
|
16
|
+
|
|
17
|
+
- **`dsers_find_product` — empty keyword rejected.** Passing `keyword: ""` or omitting both `keyword` and `image_url` used to return random products. Now throws a clear error.
|
|
18
|
+
- **`dsers_find_product` — image search respects `limit`.** DSers backend ignores `limit` on image search; we now truncate client-side and return `truncated_from` showing the original count.
|
|
19
|
+
- **`dsers_find_product` — pagination overlap note.** Response includes `pagination_note` when `search_after` is present, warning that pages may overlap by one item.
|
|
20
|
+
- **`dsers_find_product` — insufficient results note.** When fewer items than `limit` are returned and there are no more pages, a `note` field explains the shortfall.
|
|
21
|
+
- **`dsers_product_update_rules` — persist failure blocks push.** If `saveDraft()` fails, job status is set to `persist_failed` and `dsers_store_push` refuses to proceed. Previously the failure was a buried warning and push would silently use old rules.
|
|
22
|
+
- **`dsers_store_push` — pricing rule transparency.** When `apply_store_pricing_rule` is chosen, the response now shows the store's actual pricing rule configuration instead of silently overriding.
|
|
23
|
+
- **`dsers_rules_validate` — extreme pricing warnings.** `multiplier > 100`, `fixed_markup > $500`, and `fixed_price > $10,000` now produce warnings with concrete dollar examples.
|
|
24
|
+
|
|
25
|
+
#### Security
|
|
26
|
+
|
|
27
|
+
- **OAuth callback** — `redirect_uri` restricted to `localhost` / `127.0.0.1` / `[::1]`. Authorization code now includes a `nonce` for replay prevention and `client_id` binding.
|
|
28
|
+
- **Token endpoint** — nonce-based code replay prevention (in-memory Map with 10-min TTL). IP-based rate limit: 10 registrations/min.
|
|
29
|
+
- **Vercel route** — replaced unsigned `decodeJwtPayload` with `decryptAccessToken`. Legacy fallback gated by `LEGACY_JWT_FALLBACK=1` (default off, scheduled for removal). Added `assertEncryptionKey()` early check. `jobStores` Map capped at 100 entries with LRU eviction.
|
|
30
|
+
- **FileJobStore** — UUID format validation prevents path traversal.
|
|
31
|
+
- **MemoryJobStore** — `jobId` is now a plain UUID; no longer encodes payload state into the ID.
|
|
32
|
+
- **sku-matcher image fetch** — 10s timeout via `AbortController`, 10 MB size limit, LRU cache eviction (batch 50 at 500 cap), `pLimit(10)` concurrency cap.
|
|
33
|
+
- **Rules engine** — `description_override_html` and `description_append_html` validated against `<script>`, `<iframe>`, `<object>`, `<embed>`, `<form>`, `on*` event handlers, and `javascript:` URLs. Blocked at validation time; sanitized at runtime as defense-in-depth.
|
|
34
|
+
- **CLI OAuth** — callback server binds `127.0.0.1` only. `state` parameter verified on callback. Port fallback (3001 → 3002 → 3003). 5-minute timeout. `openBrowser` deduplicated via import from `browser-finder.ts`.
|
|
35
|
+
- **Token storage** — PBKDF2 (100k iterations) + random salt replaces bare SHA-256. Salt stored in `~/.dsers-mcp/key-salt`. Auto-migrates existing credentials on first load. File written with `mode: 0o600` directly (no post-hoc `chmod`).
|
|
36
|
+
- **Vercel headers** — `X-Content-Type-Options: nosniff`, `X-Frame-Options: DENY`, `X-XSS-Protection: 1; mode=block`, `Referrer-Policy: strict-origin-when-cross-origin`.
|
|
37
|
+
- **Error sanitization** — `err.body` in DSers API errors now strips tokens/keys/session IDs before truncation.
|
|
38
|
+
|
|
39
|
+
#### Improvements
|
|
40
|
+
|
|
41
|
+
- **DSers client** — 30s global request timeout via `AbortController`. Rate limiter promoted to module-level (shared across instances).
|
|
42
|
+
- **Auth** — `getSession()` refresh deduplicates concurrent callers via a shared promise. `invalidate()` clears all fields including `refreshToken`, `clientId`, `oauthBase`.
|
|
43
|
+
- **Push polling** — exponential backoff (1/2/4/8/15s) replaces fixed 10s intervals.
|
|
44
|
+
- **Multi-store push** — `Promise.all` with `pLimit(5)` replaces sequential loop.
|
|
45
|
+
- **Import list** — detail fetches capped at `pLimit(5)` concurrency.
|
|
46
|
+
- **Pricing rule cache** — 5-minute TTL prevents stale reads.
|
|
47
|
+
- **Helpers** — `findFirstValueByKeys` / `findAllValuesByKeys` add `maxDepth=20` + `WeakSet` cycle guard. `variantImages` uses `Set` instead of `Array.includes`.
|
|
48
|
+
- **Normalize** — pre-built `Map<optionId:valueName, valueId>` replaces nested variant loop.
|
|
49
|
+
- **`cleanNone`** — top-level only, no longer recursive (preserves deep null semantics).
|
|
50
|
+
- **`coerceIntId`** — always returns string (removed unsafe `parseInt` branch).
|
|
51
|
+
- **`deleteImportList`** — regex guard + `encodeURIComponent` prevents URL injection.
|
|
52
|
+
- **`checkAliExpressAuth`** — catch block now returns `valid: false` (was `true`).
|
|
53
|
+
- **`recoverImportItemId`** — structured field matching replaces `JSON.stringify + includes`.
|
|
54
|
+
- **Logger** — cached `LOG_LEVEL` read, `__testHooks.setWriter` gated by `NODE_ENV=test`, added `resetLevel()` hook.
|
|
55
|
+
- **eslint** — `no-console: "error"` (cli.ts exempted).
|
|
56
|
+
- **`mcp-handler`** moved from devDependencies to dependencies.
|
|
57
|
+
- **`prepublishOnly: "npm run build"`** added.
|
|
58
|
+
- **`version:sync`** script syncs package.json version to server.json and manifest.json.
|
|
59
|
+
- **`pLimit`** consolidated into `src/util.ts` (was duplicated in 3 files).
|
|
60
|
+
- **Preview warnings** — truncate-then-deduplicate (was deduplicate-then-truncate, which could produce dupes after truncation).
|
|
61
|
+
- **CLI** — graceful SIGTERM/SIGINT shutdown. Token hot-reload uses `fs.watchFile` instead of `statSync` polling.
|
|
62
|
+
- **`centsToDollars`** — `browse-shared.ts` now imports from `helpers.ts` (was duplicated).
|
|
63
|
+
- **Node** — minimum version lowered from >=22 to >=20.
|
|
64
|
+
|
|
65
|
+
#### Regression validation
|
|
66
|
+
|
|
67
|
+
Two independent test accounts (different stores, different product counts). 57 e2e scenarios total, 0 failures. Unit tests: 25 files, 618 tests, all green.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
### 1.5.0 — 2026-04-10
|
|
72
|
+
|
|
73
|
+
Big release. Finally nailed down the "swap supplier" problem.
|
|
74
|
+
|
|
75
|
+
#### New tool: `dsers_sku_remap`
|
|
76
|
+
|
|
77
|
+
There was one scenario that kept nagging at me — the old supplier jacks up the price, runs out of stock, or gets delisted, and you want to swap to a new one. You can do this in the DSers dashboard, but clicking through variant by variant is painful, and you still have to figure out which seller variant corresponds to which new supplier SKU. I'd already built a separate sku-matcher engine (option alignment + unit normalization + synonym tables + dHash image similarity scoring) — originally as an internal tool. This release lifts the whole thing into the MCP interface so your AI agent can do the replacement in one sentence.
|
|
78
|
+
|
|
79
|
+
Two modes:
|
|
80
|
+
|
|
81
|
+
- **STRICT** — You already have the new supplier URL. Pass `new_supplier_url`, the tool uses sku-matcher to align variants on both sides, and honors `auto_confidence` to decide what auto-swaps, what keeps the old supplier, and what gets flagged as unmatched for manual review.
|
|
82
|
+
- **DISCOVER** — You only know "this supplier is dead, find me a replacement". Omit the URL. The tool reverse-image-searches the DSers pool from the current product's images, then ranks candidates via a multi-factor score (sku score + image frequency + product rating + store rating + price proximity + stock + order count) and auto-picks the best match.
|
|
83
|
+
|
|
84
|
+
Both modes are two-step: always call `mode='preview'` first (read-only) to inspect `diffs` and `pool_additions`, then call `mode='apply'` to actually write.
|
|
85
|
+
|
|
86
|
+
Key design decisions:
|
|
87
|
+
|
|
88
|
+
- Old suppliers get **archived into `mapping.pool[]` as history**, not thrown away. If the new supplier turns out to be a lemon, the next `dsers_sku_remap` run can reconsider the old supplier as a candidate.
|
|
89
|
+
- `pool` is monotonic (grow-only). There's a validator rule specifically enforcing this invariant.
|
|
90
|
+
- **6 structural checks run before any write**, covering `supplyProductId` numeric format, `supplyVariantId` format, `optionId` / `valueId` correspondence, and more — so DSers never gets written garbage.
|
|
91
|
+
- Auto-detects `MapBas` vs `MapSta` mapping type based on option alignment consistency. When alignment is incomplete, it force-downgrades to Standard and surfaces the reason in `warnings`.
|
|
92
|
+
|
|
93
|
+
#### Other tool cleanup
|
|
94
|
+
|
|
95
|
+
`manifest.json`'s tools array was missing 4 entries — the code had already shipped them but the metadata never caught up. Fixed in this release:
|
|
96
|
+
|
|
97
|
+
- `dsers_import_list` — browse the import staging list with cost / sell price / stock / markup status
|
|
98
|
+
- `dsers_my_products` — view products already pushed to a store (with supplier links for re-import)
|
|
99
|
+
- `dsers_find_product` — search the DSers product pool (keyword or image)
|
|
100
|
+
- `dsers_sku_remap` — the new one described above
|
|
101
|
+
|
|
102
|
+
Tool count goes from 9 listed to **13** (matches what `tools/list` has actually been returning since 1.4.x).
|
|
103
|
+
|
|
104
|
+
#### Stability fixes
|
|
105
|
+
|
|
106
|
+
`dsers_sku_remap` went through 15 fix rounds from round-1 to round-5.7.5. Headline items:
|
|
107
|
+
|
|
108
|
+
- **F1 — Path A candidate fetch now has a `product-pool/product/detail` fallback.** When the user-provided supplier URL is already mapped to another product in the account, DSers import-list reports "already exists" but doesn't return an `importListId`, which caused the old Path A to time out after 5–26 s. The fallback hits the pool endpoint directly and returns in a few hundred ms.
|
|
109
|
+
- **F2 — `skuRemap` entry point now runs a store-ownership check first.** A shape-valid but wrong `store_id` no longer travels all the way into Path B `rank_candidates` before bottoming out with a misleading "no viable match" error.
|
|
110
|
+
- **F3 — MCP-boundary input shape guard.** Empty strings / letters / 200-char strings / special symbols for `dsers_product_id` are now rejected in 0–1 ms without reaching the handler.
|
|
111
|
+
- **F4 — CODEC copy containment.** DSers' raw Go-map error text no longer leaks into user-visible errors; everything routes through a clean `store_id_mismatch` envelope with explicit `dsers_store_discover` / `dsers_my_products` remediation hints.
|
|
112
|
+
- **M1 — Production-grade int64 range convergence.** The 19-digit numeric validation for `store_id` / `dsers_product_id` now adds a BigInt `.refine()` at the MCP layer that checks against the signed int64 ceiling (`9223372036854775807`). Overflow values are rejected at the MCP boundary, avoiding the DSers int64 parser bug entirely.
|
|
113
|
+
- **O1 — URL scheme case canonicalization.** `HTTPS://` / `HttP://` etc. are now lowercased at the scheme prefix inside `SUPPLIER_URL_SCHEMA.transform()`. Host / path / query are left exactly as provided (RFC 3986: scheme is case-insensitive, path is case-sensitive; Alibaba URLs like `Widget_ABC_1600123456789.html` must survive intact).
|
|
114
|
+
- **O3 — Hard error text hygiene.** `sanitizePrimaryErrorForWarning` strips DSers JSON blobs / Go `<nil>` / `map[]` noise from Path A fetch errors and leaves clean prose with a compact `(DSers API HTTP NNN)` marker for the upstream status code.
|
|
115
|
+
- **O-R4-3 — `checkStoreOwnership` direct-lookup fast path.** Wrong `dsers_product_id` failure latency drops from ~1.3 s (list-scan) to under 500 ms (`getMyProductDetail` direct query), in line with wrong `store_id` latency.
|
|
116
|
+
- **O-R5-3 — Validator now accepts DSers' single-SKU `<none>` sentinel.** DSers natively stores `supplyVariantId: "<none>"` as a literal string for `Default Title` single-variant products. Before this fix the validator's `\d+:\d+[#...]` pattern was wrongly rejecting this real production data, which meant **every single-SKU product in the account would fail on apply**.
|
|
117
|
+
- **O-R55-2 / B-R57-1 — sku-matcher single-SKU seller shortcut.** Fixes a matcher blind spot where a seller is `Default Title` (1v) and the candidate is 1v with a real dimension name like `Color`. The new shortcut fires only when the seller is trivially single-SKU (`isTrivialSellerSingleSku`) and produces confidence 75 with reason `single_sku_seller_trivial`. **The existing algorithm core is untouched** — the shortcut is strictly an early-return at the top of `matchVariants`, preserving all multi-SKU paths and the fat-fat 1v↔1v exact-match path (which still scores 80).
|
|
118
|
+
|
|
119
|
+
#### File hygiene
|
|
120
|
+
|
|
121
|
+
- Fixed a hardcoded `version: "1.3.8"` in `app/dropshipping/[transport]/route.ts` — a legacy drop that had survived three releases without being noticed.
|
|
122
|
+
- `package.json` / `server.json` / `manifest.json` / README all synced to 1.5.0.
|
|
123
|
+
- Added `CHANGELOG.md`.
|
|
124
|
+
- npm package only ships `dist/` + `README` + `LICENSE` + `CHANGELOG` — 239 KB tarball. `src/` / `app/` / `test/` / `docs/` / `scripts/` are not in the published package.
|
|
125
|
+
|
|
126
|
+
#### Known limitations (deferred to later versions)
|
|
127
|
+
|
|
128
|
+
- `dsers_my_products` `page` pagination doesn't actually advance (DSers backend behavior, not a tool bug). Workaround: use `page_size:100` to pull everything at once. Accounts with >100 products will hit this; tracking separately.
|
|
129
|
+
- DSers GET mapping response returns a non-deterministic `mappings[]` array order for multi-supplier (`MapAgc`) products. Values are identical, only the index shifts. Affects byte-level diff workflows; the validator doesn't depend on byte-level comparison so it's not impacted.
|
|
130
|
+
- `dsers_sku_remap` discover mode (Path B) doesn't work on `vp*` virtual products — DSers-side limitation, no seed images available to reverse-search.
|
|
131
|
+
|
|
132
|
+
#### Regression validation
|
|
133
|
+
|
|
134
|
+
Every round from round-1 to round-5.7.5 was run by an **independent QA session** with no access to prior reports, HANDOFF docs, commit bodies, or test files. Full e2e regression + real DSers writes + byte-level rollback verification. The last round: **0 Blocker / 0 Major / 0 Minor / 0 Observation**. 585/585 vitest tests green.
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
### 1.4.x and earlier
|
|
139
|
+
|
|
140
|
+
Previous releases live in the git history. Mostly OAuth 2.1 + remote MCP + Vercel deployment work. No consolidated changelog; check `git log --oneline v1.4.0..v1.5.0` or individual commit messages.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
<a id="中文"></a>
|
|
145
|
+
|
|
146
|
+
## 中文
|
|
147
|
+
|
|
148
|
+
### 1.5.1 — 2026-04-10
|
|
149
|
+
|
|
150
|
+
安全加固 + npm 测试发现的 7 个 bugfix。没有新工具,没有算法改动,纯防御性更新。
|
|
151
|
+
|
|
152
|
+
#### Bugfix
|
|
153
|
+
|
|
154
|
+
- **`dsers_find_product` — 空关键词拒绝**: `keyword: ""` 或不传 keyword 和 image_url 之前会返回随机产品,现在直接报错
|
|
155
|
+
- **`dsers_find_product` — 图片搜索尊重 limit**: DSers 后端对图搜忽略 limit,现在客户端强制截断,返回 `truncated_from` 字段
|
|
156
|
+
- **`dsers_find_product` — 分页重叠提示**: search_after 非空时返回 `pagination_note`,提示去重
|
|
157
|
+
- **`dsers_find_product` — 结果不足说明**: 返回少于 limit 且无更多页时加 `note` 字段
|
|
158
|
+
- **`dsers_product_update_rules` — 持久化失败阻断推送**: saveDraft 失败时 status 设为 `persist_failed`,push 直接拒绝
|
|
159
|
+
- **`dsers_store_push` — 定价规则透明化**: 选 `apply_store_pricing_rule` 时显示店铺实际定价规则配置
|
|
160
|
+
- **`dsers_rules_validate` — 极端定价 warning**: multiplier>100 / markup>$500 / price>$10000 带具体金额警告
|
|
161
|
+
|
|
162
|
+
#### 安全
|
|
163
|
+
|
|
164
|
+
- OAuth 回调限制 localhost、code 加 nonce 防重放、client_id 绑定
|
|
165
|
+
- Token 端点 nonce 防重放 + IP 限流 10 次/分
|
|
166
|
+
- Vercel 路由用 `decryptAccessToken` 替代无验签的 JWT 解码,legacy fallback 默认关闭
|
|
167
|
+
- FileJobStore UUID 校验防路径穿越
|
|
168
|
+
- MemoryJobStore jobId 不再编码 payload
|
|
169
|
+
- sku-matcher 图片拉取加 10s 超时 + 10MB 限制 + LRU 缓存驱逐 + 并发限制
|
|
170
|
+
- rules 引擎拦截 `<script>`/`<iframe>`/`on*` 事件/`javascript:` URL
|
|
171
|
+
- CLI OAuth 绑定 127.0.0.1、state 验证、端口回退、5 分钟超时
|
|
172
|
+
- Token 存储 PBKDF2 + salt 替代裸 SHA-256
|
|
173
|
+
- Vercel 安全响应头
|
|
174
|
+
- 错误信息自动脱敏(token/key/session)
|
|
175
|
+
|
|
176
|
+
#### 改进
|
|
177
|
+
|
|
178
|
+
- DSers 客户端 30s 全局超时,限流器改模块级共享
|
|
179
|
+
- Auth refresh 竞态去重,invalidate 完整清理
|
|
180
|
+
- Push 轮询指数退避(1/2/4/8/15s)
|
|
181
|
+
- 多店铺推送 pLimit(5) 并行
|
|
182
|
+
- Import list 详情请求 pLimit(5) 并发
|
|
183
|
+
- Pricing rule 缓存 5 分钟 TTL
|
|
184
|
+
- 递归查找加深度上限 + 循环引用检测
|
|
185
|
+
- `pLimit` 统一到 `src/util.ts`
|
|
186
|
+
- CLI 优雅退出 + watchFile 替代 statSync
|
|
187
|
+
- eslint `no-console: "error"`
|
|
188
|
+
- Node 最低版本降为 >=20
|
|
189
|
+
|
|
190
|
+
#### 回归验证
|
|
191
|
+
|
|
192
|
+
两个独立测试账号(不同店铺、不同产品量),57 个 e2e 场景全过。单元测试 25 文件 618 用例全绿。
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
### 1.5.0 — 2026-04-10
|
|
4
197
|
|
|
5
198
|
大版本。这版终于把换供应商这件事搞定了。
|
|
6
199
|
|
|
7
|
-
|
|
200
|
+
#### 新工具:`dsers_sku_remap`
|
|
8
201
|
|
|
9
202
|
背景是之前一直有一个绕不过去的场景 —— 老供应商涨价 / 断货 / 被封了,你想换一个新的。DSers 后台手动点也能换,但是每个变体每个变体点下去非常反人类,更不用说你要把 seller 的 variant 精确对应到新 supplier 的哪个 SKU。我之前做了一个单独的 sku-matcher 引擎(用 option 对齐 + 单位规范化 + 同义词表 + dHash 图像相似度做打分),原本是内部工具,这一版整个搬进 MCP 接口,让 AI agent 可以一句话完成整个替换。
|
|
10
203
|
|
|
@@ -22,7 +215,7 @@
|
|
|
22
215
|
- **写入前做 6 条结构校验**,包括 supplyProductId 数字格式、supplyVariantId 格式、optionId/valueId 对应关系,防止把 DSers 写脏
|
|
23
216
|
- **自动识别 Basic vs Standard mapping type**,根据 variant 选项对齐情况决定用哪种 mapping schema。对齐不全时强制 degrade 到 Standard 并在 warnings 里说明原因
|
|
24
217
|
|
|
25
|
-
|
|
218
|
+
#### 其它工具完善
|
|
26
219
|
|
|
27
220
|
顺手把之前零散的 3 个工具也正式加进 inputSchema / 描述里(之前 1.4.x 已经写过代码但 manifest / server.json 这些元数据文件没同步,这次补上):
|
|
28
221
|
|
|
@@ -32,7 +225,7 @@
|
|
|
32
225
|
|
|
33
226
|
加上 `dsers_sku_remap`,这版从 9 个工具扩到 13 个。manifest.json 的 tools 数组之前漏了这 4 个,这版一起补齐。
|
|
34
227
|
|
|
35
|
-
|
|
228
|
+
#### 稳定性修复
|
|
36
229
|
|
|
37
230
|
`dsers_sku_remap` 在 round-1 到 round-5.7.5 中一共发现并修了 15 个问题。按照发现轮次排列的关键几条:
|
|
38
231
|
|
|
@@ -47,25 +240,25 @@
|
|
|
47
240
|
- **O-R5-3 validator 接受 DSers 单 SKU `<none>` 哨兵** — DSers 对"Default Title"单 SKU 产品的真实存储是 `supplyVariantId:"<none>"` 字面字符串,这不是 bug 是生产数据。validator 的 check 4 的 pattern `\d+:\d+[#...]` 之前会误拒这种数据,导致账号里**所有单 SKU 产品**(测试账号里有 9 个)的 apply 都会失败。现在 validator 接受 `<none>` 哨兵,前提是 candidate 也是单 SKU(防御性 guard:防止 matcher 把多 SKU candidate 硬塞到哨兵槽)
|
|
48
241
|
- **O-R55-2 / B-R57-1 sku-matcher 单 SKU seller 快路径** — matcher 的维度对齐路径对"seller 是单 SKU Default Title + candidate 是 1v 真实维度名(比如 `{Color, black}`)"这种退化场景会判 0 分 unmatched。新增一个 early-return 快路径: 当 seller 是 trivial 单 SKU(lean 或 Default Title 哨兵),candidate 不管什么形态,都按 `single_sku_seller_trivial` 策略配对,confidence 75。图像路径保留,candidate 多 SKU 时按 dHash 挑最接近的 variant,其它作为 alternatives 返回。**既有算法主体一行未动**(这点经过一周独立验证,不想动),shortcut 只是 early-return。fat-fat 场景(两边都是 Default Title 哨兵)还是走原算法的 exact 80 分,不被 shortcut 抢占
|
|
49
242
|
|
|
50
|
-
|
|
243
|
+
#### 文件更新
|
|
51
244
|
|
|
52
245
|
- 修了 `app/dropshipping/[transport]/route.ts` 里硬编码的 `version: "1.3.8"`(遗留 bug,历次发版没同步到)
|
|
53
246
|
- `manifest.json` 补齐 4 个漏掉的 tool 描述
|
|
54
247
|
- README 里 `test count (343)` 同步到实际的 585
|
|
55
248
|
- 新增 `CHANGELOG.md`
|
|
56
249
|
|
|
57
|
-
|
|
250
|
+
#### 没做的事(留给后续版本)
|
|
58
251
|
|
|
59
252
|
- `dsers_my_products` 的 `page` 分页参数现在实际不生效(DSers 后端行为,不是本工具的 bug),workaround 是用 `page_size:100` 一次拉完。账号产品超过 100 的用户会撞到这个,另开 issue 跟进
|
|
60
253
|
- DSers GET mapping 对多 supplier(MapAgc)产品返回的 `mappings[]` 数组顺序非确定(服务器行为,10 次里 9 次是顺序 A,1 次是顺序 B,值完全一样)。对做 byte-level diff 的工具链有影响,我们的 validator 不依赖 byte-level 所以不受影响,但使用者要注意
|
|
61
254
|
- `dsers_sku_remap` 的 discover 模式 Path B 对 vp* 虚拟产品(DSers 内部合成的)无效,因为 virtual product 没有 seed 图可以反搜。这是 DSers 侧的限制,不是我们能修的
|
|
62
255
|
|
|
63
|
-
|
|
256
|
+
#### 回归验证
|
|
64
257
|
|
|
65
258
|
这一版从 round-1 做到 round-5.7.5,每轮都是独立 QA 会话(不读前面任何报告、HANDOFF、commit body、测试代码),跑完整 e2e 回归 + 真实 DSers 写入 + 字节级 rollback。585 个单元测试全过,最后一轮 0 Blocker / 0 Major / 0 Minor / 0 Observation。
|
|
66
259
|
|
|
67
260
|
---
|
|
68
261
|
|
|
69
|
-
|
|
262
|
+
### 1.4.x 之前
|
|
70
263
|
|
|
71
264
|
之前的版本在 git history 里,主要是 OAuth 2.1 + 远程 MCP + Vercel 部署相关。没有集中的 changelog,看 `git log --oneline v1.4.0..v1.5.0` 或者各 commit message。
|
package/README.md
CHANGED
|
@@ -76,6 +76,7 @@ This works for both AliExpress and Alibaba products found on Accio.
|
|
|
76
76
|
|
|
77
77
|
### What You Need
|
|
78
78
|
|
|
79
|
+
- **Node.js** >= 20.0.0
|
|
79
80
|
- A [DSers](https://www.dsers.com/) account (free plan works)
|
|
80
81
|
- A Shopify or Wix store already connected in DSers
|
|
81
82
|
- An MCP-compatible AI client — [Cursor](https://cursor.sh/), [Claude Desktop](https://claude.ai/desktop), [Claude Managed Agents](https://platform.claude.com/docs/en/managed-agents/overview), [Windsurf](https://codeium.com/windsurf), or any client that supports MCP
|
package/dist/auth/oauth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../src/auth/oauth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAeH,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;CACZ;
|
|
1
|
+
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../src/auth/oauth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAeH,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;CACZ;AAiKD;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,EAC1B,aAAa,CAAC,EAAE,MAAM,EACtB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,WAAW,CAAC,CA+CtB;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAsB9E"}
|
package/dist/auth/oauth.js
CHANGED
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import * as http from "node:http";
|
|
14
14
|
import * as crypto from "node:crypto";
|
|
15
|
-
import {
|
|
15
|
+
import { openBrowser } from "./browser-finder.js";
|
|
16
16
|
const DEFAULT_OAUTH_BASE = "https://mcp-oauth-api-gw.dsers.com";
|
|
17
17
|
const DEFAULT_BFF_BASE = "https://bff-api-gw.dsers.com";
|
|
18
|
-
const
|
|
19
|
-
const
|
|
18
|
+
const CB_PORTS = [3001, 3002, 3003];
|
|
19
|
+
const CB_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes
|
|
20
20
|
const OAUTH_SCOPES = "user:read store:read store:write staff:read supplier:read " +
|
|
21
21
|
"product:read product:import product:push product:mapping " +
|
|
22
22
|
"settings:read billing:read plan:read order:read";
|
|
@@ -36,66 +36,99 @@ async function fetchJSON(url, init) {
|
|
|
36
36
|
}
|
|
37
37
|
return res.json();
|
|
38
38
|
}
|
|
39
|
-
function openBrowser(url, log) {
|
|
40
|
-
const cmd = process.platform === "darwin" ? "open"
|
|
41
|
-
: process.platform === "win32" ? "cmd"
|
|
42
|
-
: "xdg-open";
|
|
43
|
-
try {
|
|
44
|
-
if (process.platform === "win32") {
|
|
45
|
-
spawnSync(cmd, ["/c", "start", "", url], { stdio: "ignore" });
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
spawnSync(cmd, [url], { stdio: "ignore" });
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
catch {
|
|
52
|
-
log(`Please open this URL in your browser:\n${url}`);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
39
|
// ── OAuth flow ──
|
|
56
40
|
async function getASMetadata(oauthBase) {
|
|
57
41
|
return fetchJSON(`${oauthBase}/.well-known/oauth-authorization-server`);
|
|
58
42
|
}
|
|
59
|
-
async function registerClient(registrationEndpoint, log) {
|
|
43
|
+
async function registerClient(registrationEndpoint, redirectUri, log) {
|
|
60
44
|
log("Registering OAuth client...");
|
|
61
45
|
const data = await fetchJSON(registrationEndpoint, {
|
|
62
46
|
method: "POST",
|
|
63
47
|
headers: { "Content-Type": "application/json" },
|
|
64
48
|
body: JSON.stringify({
|
|
65
49
|
client_name: "DSers MCP Product",
|
|
66
|
-
redirect_uris: [
|
|
50
|
+
redirect_uris: [redirectUri],
|
|
67
51
|
}),
|
|
68
52
|
});
|
|
69
53
|
return data.client_id;
|
|
70
54
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
});
|
|
55
|
+
/**
|
|
56
|
+
* Create a callback server and wait for it to bind.
|
|
57
|
+
* Returns the server and a promise that resolves with the auth code.
|
|
58
|
+
*/
|
|
59
|
+
function createCallbackServer(port, expectedState, log) {
|
|
60
|
+
let settled = false;
|
|
61
|
+
let resolveCode;
|
|
62
|
+
let rejectCode;
|
|
63
|
+
const callbackPromise = new Promise((resolve, reject) => {
|
|
64
|
+
resolveCode = resolve;
|
|
65
|
+
rejectCode = reject;
|
|
66
|
+
});
|
|
67
|
+
const settle = (fn, v) => {
|
|
68
|
+
if (settled)
|
|
69
|
+
return;
|
|
70
|
+
settled = true;
|
|
71
|
+
clearTimeout(timer);
|
|
72
|
+
fn(v);
|
|
73
|
+
};
|
|
74
|
+
const server = http.createServer((req, res) => {
|
|
75
|
+
const url = new URL(req.url, `http://localhost:${port}`);
|
|
76
|
+
const code = url.searchParams.get("code");
|
|
77
|
+
const error = url.searchParams.get("error");
|
|
78
|
+
const callbackState = url.searchParams.get("state");
|
|
79
|
+
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
80
|
+
res.end("<html><body><h2>Authorization successful. You can close this tab.</h2></body></html>");
|
|
81
|
+
server.close();
|
|
82
|
+
if (error) {
|
|
83
|
+
settle(rejectCode, new Error(`OAuth error: ${error}`));
|
|
84
|
+
}
|
|
85
|
+
else if (callbackState !== expectedState) {
|
|
86
|
+
settle(rejectCode, new Error("OAuth state mismatch — possible CSRF attack. Please retry."));
|
|
87
|
+
}
|
|
88
|
+
else if (code) {
|
|
89
|
+
settle(resolveCode, code);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
settle(rejectCode, new Error("Callback missing authorization code"));
|
|
93
|
+
}
|
|
96
94
|
});
|
|
95
|
+
// Bind to localhost only (P0-09)
|
|
96
|
+
server.listen(port, "127.0.0.1", () => log(`Waiting for OAuth callback on port ${port}...`));
|
|
97
|
+
// Timeout after 5 minutes (P3-02)
|
|
98
|
+
const timer = setTimeout(() => {
|
|
99
|
+
server.close();
|
|
100
|
+
settle(rejectCode, new Error("OAuth callback timed out after 5 minutes. Please retry."));
|
|
101
|
+
}, CB_TIMEOUT_MS);
|
|
102
|
+
timer.unref();
|
|
103
|
+
return { server, callbackPromise };
|
|
97
104
|
}
|
|
98
|
-
|
|
105
|
+
/**
|
|
106
|
+
* Try to listen on a series of ports, returning the first that works.
|
|
107
|
+
* Waits for the `listening` event to confirm the port is bound before returning.
|
|
108
|
+
*/
|
|
109
|
+
async function tryListenWithFallback(expectedState, log) {
|
|
110
|
+
for (const port of CB_PORTS) {
|
|
111
|
+
try {
|
|
112
|
+
const { server, callbackPromise } = createCallbackServer(port, expectedState, log);
|
|
113
|
+
// Wait for listening event to confirm port is actually available
|
|
114
|
+
await new Promise((resolve, reject) => {
|
|
115
|
+
server.once("listening", resolve);
|
|
116
|
+
server.once("error", reject);
|
|
117
|
+
});
|
|
118
|
+
const redirectUri = `http://localhost:${port}/callback`;
|
|
119
|
+
return { port, redirectUri, callbackPromise };
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
if (err?.code === "EADDRINUSE") {
|
|
123
|
+
log(`Port ${port} is in use, trying next...`);
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
throw err;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
throw new Error(`All callback ports (${CB_PORTS.join(", ")}) are in use. Free one and retry.`);
|
|
130
|
+
}
|
|
131
|
+
async function exchangeCode(tokenEndpoint, clientId, code, verifier, redirectUri, oauthBase) {
|
|
99
132
|
return fetchJSON(tokenEndpoint, {
|
|
100
133
|
method: "POST",
|
|
101
134
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
@@ -104,7 +137,7 @@ async function exchangeCode(tokenEndpoint, clientId, code, verifier, oauthBase)
|
|
|
104
137
|
code,
|
|
105
138
|
code_verifier: verifier,
|
|
106
139
|
client_id: clientId,
|
|
107
|
-
redirect_uri:
|
|
140
|
+
redirect_uri: redirectUri,
|
|
108
141
|
resource: oauthBase,
|
|
109
142
|
}).toString(),
|
|
110
143
|
});
|
|
@@ -116,28 +149,35 @@ async function exchangeCode(tokenEndpoint, clientId, code, verifier, oauthBase)
|
|
|
116
149
|
export async function authorizeWithPKCE(log, savedClientId, oauthBase) {
|
|
117
150
|
const base = oauthBase || process.env.DSERS_OAUTH_BASE || DEFAULT_OAUTH_BASE;
|
|
118
151
|
const meta = await getASMetadata(base);
|
|
152
|
+
const verifier = generateVerifier();
|
|
153
|
+
const challenge = generateChallenge(verifier);
|
|
154
|
+
const state = crypto.randomBytes(16).toString("hex");
|
|
155
|
+
// Start callback listener first to determine actual port
|
|
156
|
+
const { redirectUri, callbackPromise } = await tryListenWithFallback(state, log);
|
|
119
157
|
// Reuse saved client_id or register new one
|
|
120
158
|
let clientId = savedClientId;
|
|
121
159
|
if (!clientId) {
|
|
122
|
-
clientId = await registerClient(meta.registration_endpoint, log);
|
|
160
|
+
clientId = await registerClient(meta.registration_endpoint, redirectUri, log);
|
|
123
161
|
log(`Client registered: ${clientId}`);
|
|
124
162
|
}
|
|
125
|
-
const verifier = generateVerifier();
|
|
126
|
-
const challenge = generateChallenge(verifier);
|
|
127
|
-
const state = crypto.randomBytes(16).toString("hex");
|
|
128
163
|
const authURL = new URL(meta.authorization_endpoint);
|
|
129
164
|
authURL.searchParams.set("response_type", "code");
|
|
130
165
|
authURL.searchParams.set("client_id", clientId);
|
|
131
|
-
authURL.searchParams.set("redirect_uri",
|
|
166
|
+
authURL.searchParams.set("redirect_uri", redirectUri);
|
|
132
167
|
authURL.searchParams.set("scope", OAUTH_SCOPES);
|
|
133
168
|
authURL.searchParams.set("code_challenge", challenge);
|
|
134
169
|
authURL.searchParams.set("code_challenge_method", "S256");
|
|
135
170
|
authURL.searchParams.set("state", state);
|
|
136
171
|
authURL.searchParams.set("resource", base);
|
|
137
172
|
log("Opening browser for DSers authorization...");
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
173
|
+
try {
|
|
174
|
+
openBrowser(authURL.toString());
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
log(`Please open this URL in your browser:\n${authURL.toString()}`);
|
|
178
|
+
}
|
|
179
|
+
const code = await callbackPromise;
|
|
180
|
+
const tokenData = await exchangeCode(meta.token_endpoint, clientId, code, verifier, redirectUri, base);
|
|
141
181
|
return {
|
|
142
182
|
access_token: tokenData.access_token,
|
|
143
183
|
refresh_token: tokenData.refresh_token,
|
package/dist/auth/oauth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../src/auth/oauth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../src/auth/oauth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAElD,MAAM,kBAAkB,GAAG,oCAAoC,CAAC;AAChE,MAAM,gBAAgB,GAAG,8BAA8B,CAAC;AACxD,MAAM,QAAQ,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AACpC,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,YAAY;AACjD,MAAM,YAAY,GAChB,4DAA4D;IAC5D,2DAA2D;IAC3D,iDAAiD,CAAC;AAkBpD,qBAAqB;AAErB,SAAS,gBAAgB;IACvB,OAAO,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AACtD,CAAC;AAED,SAAS,iBAAiB,CAAC,QAAgB;IACzC,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;AAC1E,CAAC;AAED,qBAAqB;AAErB,KAAK,UAAU,SAAS,CAAI,GAAW,EAAE,IAAkB;IACzD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACnC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,EAAE,MAAM,IAAI,KAAK,IAAI,GAAG,MAAM,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IAC5F,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,EAAgB,CAAC;AAClC,CAAC;AAED,mBAAmB;AAEnB,KAAK,UAAU,aAAa,CAAC,SAAiB;IAC5C,OAAO,SAAS,CAAa,GAAG,SAAS,yCAAyC,CAAC,CAAC;AACtF,CAAC;AAED,KAAK,UAAU,cAAc,CAC3B,oBAA4B,EAC5B,WAAmB,EACnB,GAA0B;IAE1B,GAAG,CAAC,6BAA6B,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,MAAM,SAAS,CAAwB,oBAAoB,EAAE;QACxE,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,WAAW,EAAE,mBAAmB;YAChC,aAAa,EAAE,CAAC,WAAW,CAAC;SAC7B,CAAC;KACH,CAAC,CAAC;IACH,OAAO,IAAI,CAAC,SAAS,CAAC;AACxB,CAAC;AAED;;;GAGG;AACH,SAAS,oBAAoB,CAC3B,IAAY,EACZ,aAAqB,EACrB,GAA0B;IAE1B,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,WAAmC,CAAC;IACxC,IAAI,UAAgC,CAAC;IACrC,MAAM,eAAe,GAAG,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC9D,WAAW,GAAG,OAAO,CAAC;QACtB,UAAU,GAAG,MAAM,CAAC;IACtB,CAAC,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,CAAC,EAAoB,EAAE,CAAM,EAAE,EAAE;QAC9C,IAAI,OAAO;YAAE,OAAO;QACpB,OAAO,GAAG,IAAI,CAAC;QACf,YAAY,CAAC,KAAK,CAAC,CAAC;QACpB,EAAE,CAAC,CAAC,CAAC,CAAC;IACR,CAAC,CAAC;IAEF,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAC5C,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAI,EAAE,oBAAoB,IAAI,EAAE,CAAC,CAAC;QAC1D,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC1C,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC5C,MAAM,aAAa,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAEpD,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,0BAA0B,EAAE,CAAC,CAAC;QACnE,GAAG,CAAC,GAAG,CAAC,sFAAsF,CAAC,CAAC;QAChG,MAAM,CAAC,KAAK,EAAE,CAAC;QAEf,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,CAAC,UAAU,EAAE,IAAI,KAAK,CAAC,gBAAgB,KAAK,EAAE,CAAC,CAAC,CAAC;QACzD,CAAC;aAAM,IAAI,aAAa,KAAK,aAAa,EAAE,CAAC;YAC3C,MAAM,CAAC,UAAU,EAAE,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC,CAAC;QAC9F,CAAC;aAAM,IAAI,IAAI,EAAE,CAAC;YAChB,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QAC5B,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,UAAU,EAAE,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC,CAAC;QACvE,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,iCAAiC;IACjC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,sCAAsC,IAAI,KAAK,CAAC,CAAC,CAAC;IAE7F,kCAAkC;IAClC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;QAC5B,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,UAAU,EAAE,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC,CAAC;IAC3F,CAAC,EAAE,aAAa,CAAC,CAAC;IAClB,KAAK,CAAC,KAAK,EAAE,CAAC;IAEd,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;AACrC,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,qBAAqB,CAClC,aAAqB,EACrB,GAA0B;IAE1B,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,GAAG,oBAAoB,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,CAAC,CAAC;YACnF,iEAAiE;YACjE,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAC1C,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;gBAClC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC/B,CAAC,CAAC,CAAC;YACH,MAAM,WAAW,GAAG,oBAAoB,IAAI,WAAW,CAAC;YACxD,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,eAAe,EAAE,CAAC;QAChD,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,IAAI,GAAG,EAAE,IAAI,KAAK,YAAY,EAAE,CAAC;gBAC/B,GAAG,CAAC,QAAQ,IAAI,4BAA4B,CAAC,CAAC;gBAC9C,SAAS;YACX,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,uBAAuB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;AACjG,CAAC;AAED,KAAK,UAAU,YAAY,CACzB,aAAqB,EACrB,QAAgB,EAChB,IAAY,EACZ,QAAgB,EAChB,WAAmB,EACnB,SAAiB;IAEjB,OAAO,SAAS,CAAC,aAAa,EAAE;QAC9B,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,mCAAmC,EAAE;QAChE,IAAI,EAAE,IAAI,eAAe,CAAC;YACxB,UAAU,EAAE,oBAAoB;YAChC,IAAI;YACJ,aAAa,EAAE,QAAQ;YACvB,SAAS,EAAE,QAAQ;YACnB,YAAY,EAAE,WAAW;YACzB,QAAQ,EAAE,SAAS;SACpB,CAAC,CAAC,QAAQ,EAAE;KACd,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,GAA0B,EAC1B,aAAsB,EACtB,SAAkB;IAElB,MAAM,IAAI,GAAG,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,kBAAkB,CAAC;IAC7E,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;IAEvC,MAAM,QAAQ,GAAG,gBAAgB,EAAE,CAAC;IACpC,MAAM,SAAS,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAErD,yDAAyD;IACzD,MAAM,EAAE,WAAW,EAAE,eAAe,EAAE,GAAG,MAAM,qBAAqB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAEjF,4CAA4C;IAC5C,IAAI,QAAQ,GAAG,aAAa,CAAC;IAC7B,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,QAAQ,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,qBAAqB,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC;QAC9E,GAAG,CAAC,sBAAsB,QAAQ,EAAE,CAAC,CAAC;IACxC,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;IACrD,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;IAClD,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAChD,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;IACtD,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IAChD,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAC;IACtD,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,uBAAuB,EAAE,MAAM,CAAC,CAAC;IAC1D,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACzC,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IAE3C,GAAG,CAAC,4CAA4C,CAAC,CAAC;IAClD,IAAI,CAAC;QACH,WAAW,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,GAAG,CAAC,0CAA0C,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,eAAe,CAAC;IACnC,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,cAAc,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC;IAEvG,OAAO;QACL,YAAY,EAAE,SAAS,CAAC,YAAY;QACpC,aAAa,EAAE,SAAS,CAAC,aAAa;QACtC,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,UAAU,GAAG,IAAI,GAAG,MAAM;QAC7D,SAAS,EAAE,QAAQ;QACnB,UAAU,EAAE,IAAI;QAChB,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,gBAAgB;QACxD,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;KACf,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,YAAoB,EACpB,QAAgB,EAChB,SAAkB;IAElB,MAAM,IAAI,GAAG,SAAS,IAAI,kBAAkB,CAAC;IAC7C,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;IAEvC,MAAM,IAAI,GAAG,MAAM,SAAS,CAC1B,IAAI,CAAC,cAAc,EACnB;QACE,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,mCAAmC,EAAE;QAChE,IAAI,EAAE,IAAI,eAAe,CAAC;YACxB,UAAU,EAAE,eAAe;YAC3B,aAAa,EAAE,YAAY;YAC3B,SAAS,EAAE,QAAQ;SACpB,CAAC,CAAC,QAAQ,EAAE;KACd,CACF,CAAC;IAEF,OAAO;QACL,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,UAAU,GAAG,IAAI,GAAG,MAAM;KACzD,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token-store.d.ts","sourceRoot":"","sources":["../../src/auth/token-store.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"token-store.d.ts","sourceRoot":"","sources":["../../src/auth/token-store.ts"],"names":[],"mappings":"AAaA,sDAAsD;AACtD,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;CACZ;AAoFD,yDAAyD;AACzD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAErE;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAStD;AAED,wBAAgB,SAAS,IAAI,aAAa,GAAG,IAAI,CAsChD;AAED,wBAAgB,UAAU,IAAI,OAAO,CASpC;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,6EAA6E;AAC7E,wBAAgB,oBAAoB,IAAI,OAAO,CAmB9C"}
|