@seasonkoh/webaz 0.1.24 → 0.1.26

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.
Files changed (195) hide show
  1. package/README.md +5 -1
  2. package/dist/layer0-foundation/L0-1-database/db-backends/pg-backend.js +51 -0
  3. package/dist/layer0-foundation/L0-1-database/db-backends/sql-dialect-datetime.js +437 -0
  4. package/dist/layer0-foundation/L0-1-database/db-backends/sql-placeholders.js +98 -0
  5. package/dist/layer0-foundation/L0-1-database/db.js +65 -0
  6. package/dist/layer0-foundation/L0-2-state-machine/order-chain.js +13 -11
  7. package/dist/layer0-foundation/L0-2-state-machine/transitions.js +1 -1
  8. package/dist/layer0-foundation/L0-5-manifest/manifest.js +13 -11
  9. package/dist/layer1-agent/L1-1-mcp-server/server.js +288 -208
  10. package/dist/layer1-agent/L1-2-external-anchor/anchor-engine.js +14 -12
  11. package/dist/layer2-business/L2-6-notifications/notification-engine.js +8 -5
  12. package/dist/layer2-business/L2-7-snf/snf-engine.js +16 -14
  13. package/dist/layer2-business/L2-8-feedback/build-feedback-engine.js +18 -10
  14. package/dist/layer2-business/L2-9-contribution/build-reputation-engine.js +37 -23
  15. package/dist/layer2-business/L2-9-contribution/build-task-agent-metadata-store.js +182 -0
  16. package/dist/layer2-business/L2-9-contribution/build-task-participation.js +47 -0
  17. package/dist/layer2-business/L2-9-contribution/build-task-read.js +222 -0
  18. package/dist/layer2-business/L2-9-contribution/build-tasks-engine.js +11 -3
  19. package/dist/layer2-business/L2-9-contribution/canonical-contribution-target.js +16 -0
  20. package/dist/layer2-business/L2-9-contribution/contribution-display-envelope.js +40 -0
  21. package/dist/layer2-business/L2-9-contribution/contribution-score-contract.js +36 -0
  22. package/dist/layer2-business/L2-9-contribution/contribution-score-evidence.js +61 -0
  23. package/dist/layer2-business/L2-9-contribution/github-credential/canonical.js +60 -0
  24. package/dist/layer2-business/L2-9-contribution/github-credential/github-credential.schema.js +140 -0
  25. package/dist/layer2-business/L2-9-contribution/github-credential/github-fetch-adapter.js +437 -0
  26. package/dist/layer2-business/L2-9-contribution/github-credential/self-consistency.js +38 -0
  27. package/dist/layer2-business/L2-9-contribution/github-credential/verifier.js +231 -0
  28. package/dist/layer2-business/L2-9-contribution/github-credential-ingestion-engine.js +145 -0
  29. package/dist/layer2-business/L2-9-contribution/github-credential-store.js +115 -0
  30. package/dist/layer2-business/L2-9-contribution/identity-binding-engine.js +134 -0
  31. package/dist/layer2-business/L2-9-contribution/identity-binding-store.js +101 -0
  32. package/dist/layer2-business/L2-9-contribution/identity-claim-challenge-engine.js +126 -0
  33. package/dist/layer2-business/L2-9-contribution/identity-claim-challenge-store.js +30 -0
  34. package/dist/layer2-business/L2-9-contribution/identity-claim-discovery.js +55 -0
  35. package/dist/layer2-business/L2-9-contribution/identity-claim-engine.js +109 -0
  36. package/dist/layer2-business/L2-9-contribution/identity-claim-fact-precondition.js +22 -0
  37. package/dist/layer2-business/L2-9-contribution/identity-claim-proof-verifier.js +97 -0
  38. package/dist/layer2-business/L2-9-contribution/identity-claim-read.js +59 -0
  39. package/dist/layer2-business/L2-9-contribution/task-proposal-ai-store.js +99 -0
  40. package/dist/layer2-business/L2-9-contribution/task-proposal-draft.js +191 -0
  41. package/dist/layer2-business/L2-9-contribution/task-proposal-store.js +129 -0
  42. package/dist/layer2-business/L2-notes/note-photo-storage.js +4 -2
  43. package/dist/layer3-trust/L3-1-dispute-engine/dispute-engine.js +17 -15
  44. package/dist/layer3-trust/L3-1-dispute-engine/evidence-storage.js +11 -8
  45. package/dist/layer4-economics/L4-3-reputation/reputation-engine.js +9 -8
  46. package/dist/layer4-economics/L4-4-skill-market/skill-engine.js +11 -8
  47. package/dist/layer4-economics/L4-4-skill-market/skill-listing-engine.js +22 -16
  48. package/dist/pwa/acp-feed.js +13 -1
  49. package/dist/pwa/admin-bearer-auth.js +21 -0
  50. package/dist/pwa/contract-fingerprint.js +2 -0
  51. package/dist/pwa/email-delivery.js +127 -0
  52. package/dist/pwa/endpoint-actions.js +5 -1
  53. package/dist/pwa/goal-index.js +8 -8
  54. package/dist/pwa/human-presence.js +62 -0
  55. package/dist/pwa/public/app.js +1485 -283
  56. package/dist/pwa/public/i18n.js +297 -59
  57. package/dist/pwa/public/index.html +1 -0
  58. package/dist/pwa/public/openapi.json +5 -5
  59. package/dist/pwa/public/whitepaper/en/index.html +153 -0
  60. package/dist/pwa/public/whitepaper/zh-CN/index.html +153 -0
  61. package/dist/pwa/rate-limit.js +22 -0
  62. package/dist/pwa/routes/account-deletion.js +15 -13
  63. package/dist/pwa/routes/addresses.js +10 -9
  64. package/dist/pwa/routes/admin-admins.js +13 -14
  65. package/dist/pwa/routes/admin-analytics.js +109 -69
  66. package/dist/pwa/routes/admin-atomic.js +10 -4
  67. package/dist/pwa/routes/admin-catalog.js +13 -11
  68. package/dist/pwa/routes/admin-editor-picks.js +15 -10
  69. package/dist/pwa/routes/admin-events.js +5 -3
  70. package/dist/pwa/routes/admin-health.js +2 -1
  71. package/dist/pwa/routes/admin-moderation.js +50 -29
  72. package/dist/pwa/routes/admin-ops.js +35 -23
  73. package/dist/pwa/routes/admin-protocol-params.js +16 -19
  74. package/dist/pwa/routes/admin-reports.js +23 -21
  75. package/dist/pwa/routes/admin-tokenomics.js +26 -25
  76. package/dist/pwa/routes/admin-users-lifecycle.js +37 -40
  77. package/dist/pwa/routes/admin-users-query.js +65 -53
  78. package/dist/pwa/routes/admin-verifier-flow.js +82 -41
  79. package/dist/pwa/routes/admin-verifier-whitelist.js +55 -27
  80. package/dist/pwa/routes/admin-wallet-ops.js +32 -7
  81. package/dist/pwa/routes/agent-buy.js +46 -22
  82. package/dist/pwa/routes/agent-governance.js +52 -56
  83. package/dist/pwa/routes/ai.js +7 -5
  84. package/dist/pwa/routes/analytics.js +43 -41
  85. package/dist/pwa/routes/anchors.js +19 -20
  86. package/dist/pwa/routes/announcements.js +13 -13
  87. package/dist/pwa/routes/arbitrator.js +97 -31
  88. package/dist/pwa/routes/auction.js +157 -116
  89. package/dist/pwa/routes/auth-login.js +6 -4
  90. package/dist/pwa/routes/auth-read.js +21 -10
  91. package/dist/pwa/routes/auth-register.js +111 -26
  92. package/dist/pwa/routes/auth-sessions.js +12 -11
  93. package/dist/pwa/routes/blocklist.js +16 -15
  94. package/dist/pwa/routes/build-feedback.js +10 -9
  95. package/dist/pwa/routes/build-reputation.js +6 -2
  96. package/dist/pwa/routes/build-tasks.js +45 -13
  97. package/dist/pwa/routes/buyer-feeds.js +27 -25
  98. package/dist/pwa/routes/cart.js +16 -15
  99. package/dist/pwa/routes/charity.js +212 -150
  100. package/dist/pwa/routes/chat.js +42 -43
  101. package/dist/pwa/routes/checkin-tasks.js +10 -9
  102. package/dist/pwa/routes/checkout-helpers.js +12 -10
  103. package/dist/pwa/routes/claim-initiators.js +34 -14
  104. package/dist/pwa/routes/claim-verify.js +86 -53
  105. package/dist/pwa/routes/claim-voting.js +43 -18
  106. package/dist/pwa/routes/contribution-identity.js +164 -0
  107. package/dist/pwa/routes/contribution-score.js +19 -0
  108. package/dist/pwa/routes/coupons.js +19 -16
  109. package/dist/pwa/routes/dashboards.js +18 -16
  110. package/dist/pwa/routes/dispute-cases.js +25 -24
  111. package/dist/pwa/routes/disputes-read.js +45 -51
  112. package/dist/pwa/routes/disputes-write.js +124 -61
  113. package/dist/pwa/routes/evidence.js +9 -9
  114. package/dist/pwa/routes/external-anchors.js +13 -12
  115. package/dist/pwa/routes/feedback.js +29 -33
  116. package/dist/pwa/routes/flash-sales.js +18 -16
  117. package/dist/pwa/routes/follows.js +25 -24
  118. package/dist/pwa/routes/governance-auto-deactivate.js +21 -9
  119. package/dist/pwa/routes/governance-onboarding.js +70 -59
  120. package/dist/pwa/routes/group-buys.js +22 -22
  121. package/dist/pwa/routes/growth.js +34 -31
  122. package/dist/pwa/routes/import-product.js +12 -10
  123. package/dist/pwa/routes/kyc.js +9 -8
  124. package/dist/pwa/routes/leaderboard.js +20 -18
  125. package/dist/pwa/routes/listings.js +23 -22
  126. package/dist/pwa/routes/logistics.js +10 -8
  127. package/dist/pwa/routes/manifests.js +27 -27
  128. package/dist/pwa/routes/me-data.js +23 -21
  129. package/dist/pwa/routes/notifications.js +7 -6
  130. package/dist/pwa/routes/offers.js +30 -12
  131. package/dist/pwa/routes/orders-action.js +51 -29
  132. package/dist/pwa/routes/orders-create.js +75 -20
  133. package/dist/pwa/routes/orders-read.js +21 -20
  134. package/dist/pwa/routes/p2p-products.js +30 -18
  135. package/dist/pwa/routes/payments-governance.js +61 -56
  136. package/dist/pwa/routes/peers.js +9 -8
  137. package/dist/pwa/routes/pin-receipts.js +13 -13
  138. package/dist/pwa/routes/products-aliases.js +12 -10
  139. package/dist/pwa/routes/products-claims.js +36 -17
  140. package/dist/pwa/routes/products-create.js +53 -38
  141. package/dist/pwa/routes/products-crud.js +17 -16
  142. package/dist/pwa/routes/products-links.js +49 -26
  143. package/dist/pwa/routes/products-list.js +6 -4
  144. package/dist/pwa/routes/products-meta.js +40 -39
  145. package/dist/pwa/routes/products-update.js +19 -5
  146. package/dist/pwa/routes/profile-credentials.js +20 -19
  147. package/dist/pwa/routes/profile-identity.js +14 -13
  148. package/dist/pwa/routes/profile-location.js +7 -6
  149. package/dist/pwa/routes/profile-placement.js +20 -19
  150. package/dist/pwa/routes/profile-prefs.js +11 -11
  151. package/dist/pwa/routes/promoter.js +58 -66
  152. package/dist/pwa/routes/public-build-tasks.js +19 -0
  153. package/dist/pwa/routes/public-utils.js +108 -46
  154. package/dist/pwa/routes/push.js +16 -15
  155. package/dist/pwa/routes/ratings.js +92 -32
  156. package/dist/pwa/routes/recover-key.js +66 -26
  157. package/dist/pwa/routes/referral.js +37 -52
  158. package/dist/pwa/routes/reputation.js +3 -2
  159. package/dist/pwa/routes/returns.js +76 -73
  160. package/dist/pwa/routes/reviews.js +41 -18
  161. package/dist/pwa/routes/rewards-apply.js +16 -15
  162. package/dist/pwa/routes/rewards-auto-downgrade.js +9 -7
  163. package/dist/pwa/routes/rewards-escrow-expire.js +7 -5
  164. package/dist/pwa/routes/rfqs.js +163 -85
  165. package/dist/pwa/routes/search.js +16 -14
  166. package/dist/pwa/routes/secondhand.js +25 -22
  167. package/dist/pwa/routes/seller-quota.js +24 -26
  168. package/dist/pwa/routes/share-redirects.js +60 -55
  169. package/dist/pwa/routes/shareables-interactions.js +34 -35
  170. package/dist/pwa/routes/shareables.js +55 -51
  171. package/dist/pwa/routes/shop-referral.js +58 -0
  172. package/dist/pwa/routes/shops.js +25 -20
  173. package/dist/pwa/routes/signaling.js +10 -9
  174. package/dist/pwa/routes/skill-market.js +16 -16
  175. package/dist/pwa/routes/skills.js +15 -14
  176. package/dist/pwa/routes/snf.js +14 -13
  177. package/dist/pwa/routes/tags.js +10 -9
  178. package/dist/pwa/routes/task-proposals.js +121 -0
  179. package/dist/pwa/routes/trial.js +72 -52
  180. package/dist/pwa/routes/trusted-kpi.js +20 -18
  181. package/dist/pwa/routes/url-claim.js +67 -28
  182. package/dist/pwa/routes/users-public.js +62 -70
  183. package/dist/pwa/routes/variants.js +12 -13
  184. package/dist/pwa/routes/verifier-user.js +61 -21
  185. package/dist/pwa/routes/verify-tasks.js +49 -25
  186. package/dist/pwa/routes/waitlist.js +16 -15
  187. package/dist/pwa/routes/wallet-read.js +75 -37
  188. package/dist/pwa/routes/wallet-write.js +12 -9
  189. package/dist/pwa/routes/webauthn.js +25 -26
  190. package/dist/pwa/routes/webhooks.js +26 -26
  191. package/dist/pwa/routes/welcome.js +45 -50
  192. package/dist/pwa/routes/wishlist-qa.js +29 -32
  193. package/dist/pwa/server.js +304 -90
  194. package/dist/version.js +1 -1
  195. package/package.json +76 -3
@@ -1,21 +1,23 @@
1
+ import { dbOne, dbAll } from '../../layer0-foundation/L0-1-database/db.js'; // RFC-016 异步 DB seam
1
2
  export function registerBuyerFeedsRoutes(app, deps) {
2
- const { db, auth, isTrustedRole, errorRes, getNearbyCellPrecision, getProtocolParam } = deps;
3
- app.get('/api/recommendations/me', (req, res) => {
3
+ // db 已走 RFC-016 异步 seam(dbOne/dbAll),不再直接用 deps.db
4
+ const { auth, isTrustedRole, errorRes, getNearbyCellPrecision, getProtocolParam } = deps;
5
+ app.get('/api/recommendations/me', async (req, res) => {
4
6
  const user = auth(req, res);
5
7
  if (!user)
6
8
  return;
7
9
  if (isTrustedRole(user))
8
10
  return void errorRes(res, 403, 'TRUSTED_ROLE_NO_TRADE', '受信角色无购物功能');
9
11
  const limit = Math.min(30, Math.max(5, Number(req.query.limit) || 20));
10
- const wishlistRows = db.prepare(`
12
+ const wishlistRows = await dbAll(`
11
13
  SELECT w.product_id, p.category, p.seller_id FROM user_wishlist w
12
14
  JOIN products p ON p.id = w.product_id
13
15
  WHERE w.user_id = ? AND p.status = 'active' LIMIT 50
14
- `).all(user.id);
15
- const purchasedRows = db.prepare(`
16
+ `, [user.id]);
17
+ const purchasedRows = await dbAll(`
16
18
  SELECT DISTINCT product_id, seller_id FROM orders WHERE buyer_id = ? AND status = 'completed' LIMIT 200
17
- `).all(user.id);
18
- const followedRows = db.prepare(`SELECT followee_id FROM follows WHERE follower_id = ?`).all(user.id);
19
+ `, [user.id]);
20
+ const followedRows = await dbAll(`SELECT followee_id FROM follows WHERE follower_id = ?`, [user.id]);
19
21
  const wishCats = new Set(wishlistRows.map(r => r.category).filter(Boolean));
20
22
  const knownProductIds = new Set([...wishlistRows.map(r => r.product_id), ...purchasedRows.map(r => r.product_id)]);
21
23
  const knownSellerIds = new Set([...wishlistRows.map(r => r.seller_id), ...purchasedRows.map(r => r.seller_id)]);
@@ -31,40 +33,40 @@ export function registerBuyerFeedsRoutes(app, deps) {
31
33
  let followedProducts = [];
32
34
  if (followedSellerIds.length > 0) {
33
35
  const ph = followedSellerIds.map(() => '?').join(',');
34
- followedProducts = db.prepare(`
36
+ followedProducts = await dbAll(`
35
37
  SELECT ${baseCols}
36
38
  FROM products p JOIN users u ON u.id = p.seller_id
37
39
  WHERE p.seller_id IN (${ph}) AND p.status = 'active' AND p.stock > 0 ${exclSql}
38
40
  ORDER BY p.created_at DESC LIMIT 10
39
- `).all(...followedSellerIds, ...exclArgs);
41
+ `, [...followedSellerIds, ...exclArgs]);
40
42
  }
41
43
  let categoryProducts = [];
42
44
  if (wishCats.size > 0) {
43
45
  const ph = [...wishCats].map(() => '?').join(',');
44
- categoryProducts = db.prepare(`
46
+ categoryProducts = await dbAll(`
45
47
  SELECT ${baseCols}
46
48
  FROM products p JOIN users u ON u.id = p.seller_id
47
49
  WHERE p.category IN (${ph}) AND p.status = 'active' AND p.stock > 0 ${exclSql}
48
50
  ORDER BY sales_count DESC LIMIT 10
49
- `).all(...wishCats, ...exclArgs);
51
+ `, [...wishCats, ...exclArgs]);
50
52
  }
51
53
  let pastSellerProducts = [];
52
54
  const pastSellers = [...knownSellerIds].filter(s => !followedSellerIds.includes(s));
53
55
  if (pastSellers.length > 0) {
54
56
  const ph = pastSellers.map(() => '?').join(',');
55
- pastSellerProducts = db.prepare(`
57
+ pastSellerProducts = await dbAll(`
56
58
  SELECT ${baseCols}
57
59
  FROM products p JOIN users u ON u.id = p.seller_id
58
60
  WHERE p.seller_id IN (${ph}) AND p.status = 'active' AND p.stock > 0 ${exclSql}
59
61
  ORDER BY p.created_at DESC LIMIT 10
60
- `).all(...pastSellers, ...exclArgs);
62
+ `, [...pastSellers, ...exclArgs]);
61
63
  }
62
- const fallback = db.prepare(`
64
+ const fallback = await dbAll(`
63
65
  SELECT ${baseCols}
64
66
  FROM products p JOIN users u ON u.id = p.seller_id
65
67
  WHERE p.status = 'active' AND p.stock > 0 ${exclSql}
66
68
  ORDER BY sales_count DESC, p.created_at DESC LIMIT 10
67
- `).all(...exclArgs);
69
+ `, exclArgs);
68
70
  const seen = new Set();
69
71
  const labeled = (bucket, arr) => arr.filter(it => {
70
72
  const id = String(it.id);
@@ -88,7 +90,7 @@ export function registerBuyerFeedsRoutes(app, deps) {
88
90
  },
89
91
  });
90
92
  });
91
- app.get('/api/feed', (req, res) => {
93
+ app.get('/api/feed', async (req, res) => {
92
94
  const user = auth(req, res);
93
95
  if (!user)
94
96
  return;
@@ -137,13 +139,13 @@ export function registerBuyerFeedsRoutes(app, deps) {
137
139
  WHERE ts IS NOT NULL
138
140
  ORDER BY ts DESC LIMIT 50
139
141
  `;
140
- const events = db.prepare(sql).all(...params);
142
+ const events = await dbAll(sql, params);
141
143
  res.json({ events, scope });
142
144
  });
143
145
  // 雷达扫描 MVP (2026-05-29):scope 范围档 + window 时间窗,k≥3 守护贯穿
144
146
  // scope: cell(本格) / neighbors(周边 3×3) / region(同城) / global(全网)
145
147
  // window: 24h / 7d / 30d
146
- app.get('/api/nearby', (req, res) => {
148
+ app.get('/api/nearby', async (req, res) => {
147
149
  const user = auth(req, res);
148
150
  if (!user)
149
151
  return;
@@ -153,7 +155,7 @@ export function registerBuyerFeedsRoutes(app, deps) {
153
155
  const days = windowKey === '24h' ? 1 : windowKey === '30d' ? 30 : 7;
154
156
  const { precision_deg, approx_km } = getNearbyCellPrecision();
155
157
  const K = getProtocolParam('nearby_k_anonymity', 3);
156
- const u = db.prepare("SELECT geo_lat, geo_lng, geo_updated_at, region FROM users WHERE id = ?").get(user.id);
158
+ const u = (await dbOne("SELECT geo_lat, geo_lng, geo_updated_at, region FROM users WHERE id = ?", [user.id]));
157
159
  const needsGeo = scope === 'cell' || scope === 'neighbors';
158
160
  if (needsGeo && (u?.geo_lat == null || u?.geo_lng == null)) {
159
161
  // 本格/周边需定位;同城/全网不需 → 前端可引导切到更大范围
@@ -186,24 +188,24 @@ export function registerBuyerFeedsRoutes(app, deps) {
186
188
  scopeLabel = '全网';
187
189
  }
188
190
  const dayClause = `o.updated_at > datetime('now', '-${days} day')`;
189
- const totals = db.prepare(`
191
+ const totals = (await dbOne(`
190
192
  SELECT COUNT(DISTINCT o.buyer_id) as au, COUNT(*) as orders
191
193
  FROM orders o JOIN users u ON u.id = o.buyer_id
192
194
  WHERE ${where} AND o.status = 'completed' AND ${dayClause}
193
- `).get(...args);
195
+ `, args));
194
196
  const sufficient = Number(totals.au) >= K;
195
- const topProducts = sufficient ? db.prepare(`
197
+ const topProducts = sufficient ? await dbAll(`
196
198
  SELECT p.id, p.title, p.price, p.category, p.images, COUNT(DISTINCT o.buyer_id) as buyers
197
199
  FROM orders o JOIN users u ON u.id = o.buyer_id JOIN products p ON p.id = o.product_id
198
200
  WHERE ${where} AND o.status = 'completed' AND ${dayClause}
199
201
  GROUP BY p.id HAVING buyers >= ? ORDER BY buyers DESC LIMIT 10
200
- `).all(...args, K) : [];
201
- const topCategories = sufficient ? db.prepare(`
202
+ `, [...args, K]) : [];
203
+ const topCategories = sufficient ? await dbAll(`
202
204
  SELECT p.category, COUNT(*) as orders, COUNT(DISTINCT o.buyer_id) as buyers
203
205
  FROM orders o JOIN users u ON u.id = o.buyer_id JOIN products p ON p.id = o.product_id
204
206
  WHERE ${where} AND o.status = 'completed' AND ${dayClause} AND p.category IS NOT NULL
205
207
  GROUP BY p.category HAVING buyers >= ? ORDER BY orders DESC LIMIT 6
206
- `).all(...args, K) : [];
208
+ `, [...args, K]) : [];
207
209
  const staleDays = u?.geo_updated_at
208
210
  ? Math.floor((Date.now() - new Date(u.geo_updated_at.replace(' ', 'T') + 'Z').getTime()) / 86400_000)
209
211
  : null;
@@ -1,12 +1,13 @@
1
1
  import { transition } from '../../layer0-foundation/L0-2-state-machine/engine.js';
2
2
  import { notifyTransition } from '../../layer2-business/L2-6-notifications/notification-engine.js';
3
+ import { dbOne, dbAll, dbRun } from '../../layer0-foundation/L0-1-database/db.js'; // RFC-016 异步 DB seam
3
4
  export function registerCartRoutes(app, deps) {
4
5
  const { db, generateId, auth, isTrustedRole, errorRes, broadcastSystemEvent, checkStockAndMaybeDelist, addHours } = deps;
5
- app.get('/api/cart', (req, res) => {
6
+ app.get('/api/cart', async (req, res) => {
6
7
  const user = auth(req, res);
7
8
  if (!user)
8
9
  return;
9
- const items = db.prepare(`
10
+ const items = await dbAll(`
10
11
  SELECT c.product_id, c.qty, c.added_at,
11
12
  p.title, p.price, p.category, p.commission_rate, p.stock, p.status as product_status,
12
13
  u.name as seller_name
@@ -15,10 +16,10 @@ export function registerCartRoutes(app, deps) {
15
16
  JOIN users u ON u.id = p.seller_id
16
17
  WHERE c.user_id = ?
17
18
  ORDER BY c.added_at DESC
18
- `).all(user.id);
19
+ `, [user.id]);
19
20
  res.json({ items });
20
21
  });
21
- app.post('/api/cart', (req, res) => {
22
+ app.post('/api/cart', async (req, res) => {
22
23
  const user = auth(req, res);
23
24
  if (!user)
24
25
  return;
@@ -26,29 +27,29 @@ export function registerCartRoutes(app, deps) {
26
27
  const q = Math.max(1, Math.min(99, Number(qty) || 1));
27
28
  if (!product_id)
28
29
  return void res.json({ error: 'product_id 必填' });
29
- const product = db.prepare("SELECT id, status FROM products WHERE id = ?").get(product_id);
30
+ const product = await dbOne("SELECT id, status FROM products WHERE id = ?", [product_id]);
30
31
  if (!product)
31
32
  return void res.json({ error: '商品不存在' });
32
33
  if (product.status !== 'active')
33
34
  return void res.json({ error: '商品已下架' });
34
- db.prepare(`
35
+ await dbRun(`
35
36
  INSERT INTO cart_items (user_id, product_id, qty) VALUES (?, ?, ?)
36
37
  ON CONFLICT(user_id, product_id) DO UPDATE SET qty = MIN(99, cart_items.qty + ?)
37
- `).run(user.id, product_id, q, q);
38
+ `, [user.id, product_id, q, q]);
38
39
  res.json({ ok: true });
39
40
  });
40
- app.patch('/api/cart/:product_id', (req, res) => {
41
+ app.patch('/api/cart/:product_id', async (req, res) => {
41
42
  const user = auth(req, res);
42
43
  if (!user)
43
44
  return;
44
45
  const q = Math.max(1, Math.min(99, Number(req.body.qty) || 1));
45
- const r = db.prepare("UPDATE cart_items SET qty = ? WHERE user_id = ? AND product_id = ?").run(q, user.id, req.params.product_id);
46
+ const r = await dbRun("UPDATE cart_items SET qty = ? WHERE user_id = ? AND product_id = ?", [q, user.id, req.params.product_id]);
46
47
  if (r.changes === 0)
47
48
  return void res.json({ error: '购物车中没有此商品' });
48
49
  res.json({ ok: true, qty: q });
49
50
  });
50
51
  // C-1: 购物车批量下单(按 seller 自动分订单)
51
- app.post('/api/cart/checkout', (req, res) => {
52
+ app.post('/api/cart/checkout', async (req, res) => {
52
53
  const user = auth(req, res);
53
54
  if (!user)
54
55
  return;
@@ -59,11 +60,11 @@ export function registerCartRoutes(app, deps) {
59
60
  const { shipping_address, notes } = req.body || {};
60
61
  if (!shipping_address)
61
62
  return void res.status(400).json({ error: '请填写收货地址' });
62
- const items = db.prepare(`
63
+ const items = await dbAll(`
63
64
  SELECT c.product_id, c.qty, p.title, p.price, p.stock, p.seller_id, p.has_variants, p.status
64
65
  FROM cart_items c JOIN products p ON p.id = c.product_id
65
66
  WHERE c.user_id = ?
66
- `).all(user.id);
67
+ `, [user.id]);
67
68
  if (items.length === 0)
68
69
  return void res.status(400).json({ error: '购物车为空' });
69
70
  const skipped = [];
@@ -93,7 +94,7 @@ export function registerCartRoutes(app, deps) {
93
94
  if (ok.length === 0) {
94
95
  return void res.status(400).json({ error: '购物车中无可下单商品', skipped });
95
96
  }
96
- const wallet = db.prepare('SELECT balance FROM wallets WHERE user_id = ?').get(user.id);
97
+ const wallet = await dbOne('SELECT balance FROM wallets WHERE user_id = ?', [user.id]);
97
98
  if (!wallet)
98
99
  return void res.status(500).json({ error: '钱包记录缺失' });
99
100
  if (wallet.balance < totalNeed)
@@ -145,11 +146,11 @@ export function registerCartRoutes(app, deps) {
145
146
  total_paid: created.reduce((s, c) => s + c.total, 0),
146
147
  });
147
148
  });
148
- app.delete('/api/cart/:product_id', (req, res) => {
149
+ app.delete('/api/cart/:product_id', async (req, res) => {
149
150
  const user = auth(req, res);
150
151
  if (!user)
151
152
  return;
152
- db.prepare("DELETE FROM cart_items WHERE user_id = ? AND product_id = ?").run(user.id, req.params.product_id);
153
+ await dbRun("DELETE FROM cart_items WHERE user_id = ? AND product_id = ?", [user.id, req.params.product_id]);
153
154
  res.json({ ok: true });
154
155
  });
155
156
  }