@seasonkoh/webaz 0.1.24 → 0.1.25
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/README.md +2 -0
- package/dist/layer0-foundation/L0-1-database/db-backends/pg-backend.js +51 -0
- package/dist/layer0-foundation/L0-1-database/db-backends/sql-dialect-datetime.js +437 -0
- package/dist/layer0-foundation/L0-1-database/db-backends/sql-placeholders.js +98 -0
- package/dist/layer0-foundation/L0-1-database/db.js +65 -0
- package/dist/layer0-foundation/L0-2-state-machine/order-chain.js +13 -11
- package/dist/layer0-foundation/L0-2-state-machine/transitions.js +1 -1
- package/dist/layer0-foundation/L0-5-manifest/manifest.js +13 -11
- package/dist/layer1-agent/L1-1-mcp-server/server.js +165 -64
- package/dist/layer1-agent/L1-2-external-anchor/anchor-engine.js +14 -12
- package/dist/layer2-business/L2-6-notifications/notification-engine.js +8 -5
- package/dist/layer2-business/L2-7-snf/snf-engine.js +16 -14
- package/dist/layer2-business/L2-8-feedback/build-feedback-engine.js +18 -10
- package/dist/layer2-business/L2-9-contribution/build-reputation-engine.js +37 -23
- package/dist/layer2-business/L2-9-contribution/build-task-agent-metadata-store.js +173 -0
- package/dist/layer2-business/L2-9-contribution/build-task-participation.js +47 -0
- package/dist/layer2-business/L2-9-contribution/build-task-read.js +222 -0
- package/dist/layer2-business/L2-9-contribution/build-tasks-engine.js +10 -2
- package/dist/layer2-business/L2-9-contribution/canonical-contribution-target.js +16 -0
- package/dist/layer2-business/L2-9-contribution/contribution-display-envelope.js +40 -0
- package/dist/layer2-business/L2-9-contribution/contribution-score-contract.js +36 -0
- package/dist/layer2-business/L2-9-contribution/contribution-score-evidence.js +61 -0
- package/dist/layer2-business/L2-9-contribution/github-credential/canonical.js +60 -0
- package/dist/layer2-business/L2-9-contribution/github-credential/github-credential.schema.js +140 -0
- package/dist/layer2-business/L2-9-contribution/github-credential/github-fetch-adapter.js +437 -0
- package/dist/layer2-business/L2-9-contribution/github-credential/self-consistency.js +38 -0
- package/dist/layer2-business/L2-9-contribution/github-credential/verifier.js +231 -0
- package/dist/layer2-business/L2-9-contribution/github-credential-ingestion-engine.js +145 -0
- package/dist/layer2-business/L2-9-contribution/github-credential-store.js +115 -0
- package/dist/layer2-business/L2-9-contribution/identity-binding-engine.js +134 -0
- package/dist/layer2-business/L2-9-contribution/identity-binding-store.js +101 -0
- package/dist/layer2-business/L2-9-contribution/identity-claim-challenge-engine.js +126 -0
- package/dist/layer2-business/L2-9-contribution/identity-claim-challenge-store.js +30 -0
- package/dist/layer2-business/L2-9-contribution/identity-claim-engine.js +109 -0
- package/dist/layer2-business/L2-9-contribution/identity-claim-fact-precondition.js +22 -0
- package/dist/layer2-business/L2-9-contribution/identity-claim-proof-verifier.js +97 -0
- package/dist/layer2-business/L2-9-contribution/identity-claim-read.js +59 -0
- package/dist/layer2-business/L2-9-contribution/task-proposal-store.js +129 -0
- package/dist/layer2-business/L2-notes/note-photo-storage.js +4 -2
- package/dist/layer3-trust/L3-1-dispute-engine/dispute-engine.js +17 -15
- package/dist/layer3-trust/L3-1-dispute-engine/evidence-storage.js +11 -8
- package/dist/layer4-economics/L4-3-reputation/reputation-engine.js +9 -8
- package/dist/layer4-economics/L4-4-skill-market/skill-engine.js +11 -8
- package/dist/layer4-economics/L4-4-skill-market/skill-listing-engine.js +22 -16
- package/dist/pwa/acp-feed.js +13 -1
- package/dist/pwa/contract-fingerprint.js +2 -0
- package/dist/pwa/endpoint-actions.js +5 -1
- package/dist/pwa/goal-index.js +8 -8
- package/dist/pwa/human-presence.js +62 -0
- package/dist/pwa/public/app.js +575 -68
- package/dist/pwa/public/i18n.js +29 -20
- package/dist/pwa/public/index.html +1 -0
- package/dist/pwa/public/openapi.json +2 -2
- package/dist/pwa/rate-limit.js +22 -0
- package/dist/pwa/routes/account-deletion.js +15 -13
- package/dist/pwa/routes/addresses.js +10 -9
- package/dist/pwa/routes/admin-admins.js +13 -14
- package/dist/pwa/routes/admin-analytics.js +109 -69
- package/dist/pwa/routes/admin-catalog.js +13 -11
- package/dist/pwa/routes/admin-editor-picks.js +15 -10
- package/dist/pwa/routes/admin-events.js +5 -3
- package/dist/pwa/routes/admin-health.js +2 -1
- package/dist/pwa/routes/admin-moderation.js +26 -29
- package/dist/pwa/routes/admin-ops.js +22 -21
- package/dist/pwa/routes/admin-protocol-params.js +16 -19
- package/dist/pwa/routes/admin-reports.js +23 -21
- package/dist/pwa/routes/admin-tokenomics.js +26 -25
- package/dist/pwa/routes/admin-users-lifecycle.js +37 -40
- package/dist/pwa/routes/admin-users-query.js +54 -53
- package/dist/pwa/routes/admin-verifier-flow.js +82 -41
- package/dist/pwa/routes/admin-verifier-whitelist.js +55 -27
- package/dist/pwa/routes/admin-wallet-ops.js +7 -5
- package/dist/pwa/routes/agent-buy.js +46 -22
- package/dist/pwa/routes/agent-governance.js +52 -56
- package/dist/pwa/routes/ai.js +7 -5
- package/dist/pwa/routes/analytics.js +43 -41
- package/dist/pwa/routes/anchors.js +19 -20
- package/dist/pwa/routes/announcements.js +13 -13
- package/dist/pwa/routes/arbitrator.js +97 -31
- package/dist/pwa/routes/auction.js +153 -114
- package/dist/pwa/routes/auth-login.js +6 -4
- package/dist/pwa/routes/auth-read.js +11 -9
- package/dist/pwa/routes/auth-register.js +35 -20
- package/dist/pwa/routes/auth-sessions.js +12 -11
- package/dist/pwa/routes/blocklist.js +16 -15
- package/dist/pwa/routes/build-feedback.js +10 -9
- package/dist/pwa/routes/build-reputation.js +6 -2
- package/dist/pwa/routes/build-tasks.js +45 -13
- package/dist/pwa/routes/buyer-feeds.js +27 -25
- package/dist/pwa/routes/cart.js +16 -15
- package/dist/pwa/routes/charity.js +212 -150
- package/dist/pwa/routes/chat.js +42 -43
- package/dist/pwa/routes/checkin-tasks.js +10 -9
- package/dist/pwa/routes/checkout-helpers.js +12 -10
- package/dist/pwa/routes/claim-initiators.js +34 -14
- package/dist/pwa/routes/claim-verify.js +86 -53
- package/dist/pwa/routes/claim-voting.js +43 -18
- package/dist/pwa/routes/contribution-identity.js +147 -0
- package/dist/pwa/routes/contribution-score.js +19 -0
- package/dist/pwa/routes/coupons.js +19 -16
- package/dist/pwa/routes/dashboards.js +18 -16
- package/dist/pwa/routes/dispute-cases.js +25 -24
- package/dist/pwa/routes/disputes-read.js +45 -51
- package/dist/pwa/routes/disputes-write.js +124 -61
- package/dist/pwa/routes/evidence.js +9 -9
- package/dist/pwa/routes/external-anchors.js +13 -12
- package/dist/pwa/routes/feedback.js +29 -33
- package/dist/pwa/routes/flash-sales.js +18 -16
- package/dist/pwa/routes/follows.js +25 -24
- package/dist/pwa/routes/governance-auto-deactivate.js +21 -9
- package/dist/pwa/routes/governance-onboarding.js +70 -59
- package/dist/pwa/routes/group-buys.js +22 -22
- package/dist/pwa/routes/growth.js +33 -30
- package/dist/pwa/routes/import-product.js +12 -10
- package/dist/pwa/routes/kyc.js +9 -8
- package/dist/pwa/routes/leaderboard.js +20 -18
- package/dist/pwa/routes/listings.js +23 -22
- package/dist/pwa/routes/logistics.js +10 -8
- package/dist/pwa/routes/manifests.js +27 -27
- package/dist/pwa/routes/me-data.js +23 -21
- package/dist/pwa/routes/notifications.js +7 -6
- package/dist/pwa/routes/offers.js +30 -12
- package/dist/pwa/routes/orders-action.js +33 -17
- package/dist/pwa/routes/orders-create.js +75 -20
- package/dist/pwa/routes/orders-read.js +21 -20
- package/dist/pwa/routes/p2p-products.js +30 -18
- package/dist/pwa/routes/payments-governance.js +61 -56
- package/dist/pwa/routes/peers.js +9 -8
- package/dist/pwa/routes/pin-receipts.js +13 -13
- package/dist/pwa/routes/products-aliases.js +12 -10
- package/dist/pwa/routes/products-claims.js +36 -17
- package/dist/pwa/routes/products-create.js +53 -38
- package/dist/pwa/routes/products-crud.js +17 -16
- package/dist/pwa/routes/products-links.js +49 -26
- package/dist/pwa/routes/products-list.js +6 -4
- package/dist/pwa/routes/products-meta.js +40 -39
- package/dist/pwa/routes/products-update.js +19 -5
- package/dist/pwa/routes/profile-credentials.js +14 -16
- package/dist/pwa/routes/profile-identity.js +14 -13
- package/dist/pwa/routes/profile-location.js +7 -6
- package/dist/pwa/routes/profile-placement.js +19 -17
- package/dist/pwa/routes/profile-prefs.js +11 -11
- package/dist/pwa/routes/promoter.js +55 -49
- package/dist/pwa/routes/public-build-tasks.js +19 -0
- package/dist/pwa/routes/public-utils.js +108 -46
- package/dist/pwa/routes/push.js +16 -15
- package/dist/pwa/routes/ratings.js +30 -30
- package/dist/pwa/routes/recover-key.js +13 -12
- package/dist/pwa/routes/referral.js +37 -32
- package/dist/pwa/routes/reputation.js +3 -2
- package/dist/pwa/routes/returns.js +76 -73
- package/dist/pwa/routes/reviews.js +41 -18
- package/dist/pwa/routes/rewards-apply.js +16 -15
- package/dist/pwa/routes/rewards-auto-downgrade.js +9 -7
- package/dist/pwa/routes/rewards-escrow-expire.js +7 -5
- package/dist/pwa/routes/rfqs.js +163 -85
- package/dist/pwa/routes/search.js +16 -14
- package/dist/pwa/routes/secondhand.js +25 -22
- package/dist/pwa/routes/seller-quota.js +24 -26
- package/dist/pwa/routes/share-redirects.js +59 -55
- package/dist/pwa/routes/shareables-interactions.js +34 -35
- package/dist/pwa/routes/shareables.js +55 -51
- package/dist/pwa/routes/shop-referral.js +57 -0
- package/dist/pwa/routes/shops.js +20 -18
- package/dist/pwa/routes/signaling.js +10 -9
- package/dist/pwa/routes/skill-market.js +16 -16
- package/dist/pwa/routes/skills.js +15 -14
- package/dist/pwa/routes/snf.js +14 -13
- package/dist/pwa/routes/tags.js +10 -9
- package/dist/pwa/routes/task-proposals.js +45 -0
- package/dist/pwa/routes/trial.js +69 -51
- package/dist/pwa/routes/trusted-kpi.js +20 -18
- package/dist/pwa/routes/url-claim.js +67 -28
- package/dist/pwa/routes/users-public.js +62 -60
- package/dist/pwa/routes/variants.js +12 -13
- package/dist/pwa/routes/verifier-user.js +61 -21
- package/dist/pwa/routes/verify-tasks.js +49 -25
- package/dist/pwa/routes/waitlist.js +16 -15
- package/dist/pwa/routes/wallet-read.js +74 -36
- package/dist/pwa/routes/wallet-write.js +12 -9
- package/dist/pwa/routes/webauthn.js +25 -26
- package/dist/pwa/routes/webhooks.js +26 -26
- package/dist/pwa/routes/welcome.js +45 -50
- package/dist/pwa/routes/wishlist-qa.js +29 -32
- package/dist/pwa/server.js +237 -81
- package/dist/version.js +1 -1
- package/package.json +47 -2
|
@@ -1,35 +1,36 @@
|
|
|
1
|
+
import { dbOne, dbAll, dbRun } from '../../layer0-foundation/L0-1-database/db.js'; // RFC-016 异步 DB seam
|
|
1
2
|
export function registerWishlistQaRoutes(app, deps) {
|
|
2
|
-
|
|
3
|
+
// db 已全量走 RFC-016 异步 seam(dbOne/dbAll/dbRun),不再直接用 deps.db
|
|
4
|
+
const { generateId, auth, isTrustedRole, errorRes } = deps;
|
|
3
5
|
// ─── Wave A-1: 心愿单 ────────────────────────────────────
|
|
4
|
-
app.post('/api/wishlist/:product_id', (req, res) => {
|
|
6
|
+
app.post('/api/wishlist/:product_id', async (req, res) => {
|
|
5
7
|
const user = auth(req, res);
|
|
6
8
|
if (!user)
|
|
7
9
|
return;
|
|
8
10
|
if (isTrustedRole(user))
|
|
9
11
|
return void errorRes(res, 403, 'TRUSTED_ROLE_NO_TRADE', '受信角色无购物功能');
|
|
10
|
-
const p =
|
|
12
|
+
const p = await dbOne('SELECT id, price, status, seller_id FROM products WHERE id = ?', [req.params.product_id]);
|
|
11
13
|
if (!p)
|
|
12
14
|
return void res.status(404).json({ error: '商品不存在' });
|
|
13
15
|
if (p.seller_id === user.id)
|
|
14
16
|
return void res.status(400).json({ error: '不可收藏自己的商品' });
|
|
15
17
|
const note = req.body?.note ? String(req.body.note).slice(0, 200) : null;
|
|
16
|
-
|
|
17
|
-
.run(user.id, req.params.product_id, note, p.price);
|
|
18
|
+
await dbRun(`INSERT OR REPLACE INTO user_wishlist (user_id, product_id, note, price_at_add) VALUES (?,?,?,?)`, [user.id, req.params.product_id, note, p.price]);
|
|
18
19
|
res.json({ success: true });
|
|
19
20
|
});
|
|
20
|
-
app.delete('/api/wishlist/:product_id', (req, res) => {
|
|
21
|
+
app.delete('/api/wishlist/:product_id', async (req, res) => {
|
|
21
22
|
const user = auth(req, res);
|
|
22
23
|
if (!user)
|
|
23
24
|
return;
|
|
24
|
-
|
|
25
|
+
await dbRun('DELETE FROM user_wishlist WHERE user_id = ? AND product_id = ?', [user.id, req.params.product_id]);
|
|
25
26
|
res.json({ success: true });
|
|
26
27
|
});
|
|
27
|
-
app.get('/api/wishlist', (req, res) => {
|
|
28
|
+
app.get('/api/wishlist', async (req, res) => {
|
|
28
29
|
const user = auth(req, res);
|
|
29
30
|
if (!user)
|
|
30
31
|
return;
|
|
31
32
|
// 过滤已删除商品(已下架但 status=warehouse 仍显示让买家可见)
|
|
32
|
-
const rows =
|
|
33
|
+
const rows = await dbAll(`
|
|
33
34
|
SELECT w.product_id, w.note, w.price_at_add, w.notify_price_drop, w.notify_back_in_stock, w.created_at,
|
|
34
35
|
p.title, p.price as current_price, p.stock, p.status as product_status,
|
|
35
36
|
p.category, p.claim_loss_count,
|
|
@@ -39,7 +40,7 @@ export function registerWishlistQaRoutes(app, deps) {
|
|
|
39
40
|
JOIN users u ON u.id = p.seller_id
|
|
40
41
|
WHERE w.user_id = ? AND p.status != 'deleted'
|
|
41
42
|
ORDER BY w.created_at DESC LIMIT 200
|
|
42
|
-
|
|
43
|
+
`, [user.id]);
|
|
43
44
|
for (const r of rows) {
|
|
44
45
|
const cur = Number(r.current_price);
|
|
45
46
|
const old = Number(r.price_at_add || cur);
|
|
@@ -48,21 +49,21 @@ export function registerWishlistQaRoutes(app, deps) {
|
|
|
48
49
|
}
|
|
49
50
|
res.json({ items: rows });
|
|
50
51
|
});
|
|
51
|
-
app.get('/api/wishlist/:product_id/check', (req, res) => {
|
|
52
|
+
app.get('/api/wishlist/:product_id/check', async (req, res) => {
|
|
52
53
|
const user = auth(req, res);
|
|
53
54
|
if (!user)
|
|
54
55
|
return;
|
|
55
|
-
const exists =
|
|
56
|
+
const exists = await dbOne('SELECT 1 FROM user_wishlist WHERE user_id = ? AND product_id = ?', [user.id, req.params.product_id]);
|
|
56
57
|
res.json({ in_wishlist: !!exists });
|
|
57
58
|
});
|
|
58
59
|
// ─── Wave A-2: 商品 Q&A ─────────────────────────────────
|
|
59
|
-
app.post('/api/products/:product_id/qa', (req, res) => {
|
|
60
|
+
app.post('/api/products/:product_id/qa', async (req, res) => {
|
|
60
61
|
const user = auth(req, res);
|
|
61
62
|
if (!user)
|
|
62
63
|
return;
|
|
63
64
|
if (isTrustedRole(user))
|
|
64
65
|
return void errorRes(res, 403, 'TRUSTED_ROLE_NO_QA', '受信角色不参与商品 Q&A');
|
|
65
|
-
const p =
|
|
66
|
+
const p = await dbOne('SELECT id, seller_id, status FROM products WHERE id = ?', [req.params.product_id]);
|
|
66
67
|
if (!p)
|
|
67
68
|
return void res.status(404).json({ error: '商品不存在' });
|
|
68
69
|
if (p.seller_id === user.id)
|
|
@@ -73,20 +74,18 @@ export function registerWishlistQaRoutes(app, deps) {
|
|
|
73
74
|
if (question.length < 6 || question.length > 500)
|
|
74
75
|
return void res.status(400).json({ error: 'question 长度需 6-500 字' });
|
|
75
76
|
const id = generateId('qa');
|
|
76
|
-
|
|
77
|
-
.run(id, req.params.product_id, user.id, p.seller_id, question);
|
|
77
|
+
await dbRun(`INSERT INTO product_qa (id, product_id, asker_id, seller_id, question) VALUES (?,?,?,?,?)`, [id, req.params.product_id, user.id, p.seller_id, question]);
|
|
78
78
|
try {
|
|
79
|
-
|
|
80
|
-
.run(generateId('ntf'), p.seller_id, '收到商品提问', question.slice(0, 80) + (question.length > 80 ? '...' : ''), null);
|
|
79
|
+
await dbRun(`INSERT INTO notifications (id, user_id, title, body, order_id) VALUES (?,?,?,?,?)`, [generateId('ntf'), p.seller_id, '收到商品提问', question.slice(0, 80) + (question.length > 80 ? '...' : ''), null]);
|
|
81
80
|
}
|
|
82
81
|
catch { }
|
|
83
82
|
res.json({ success: true, id });
|
|
84
83
|
});
|
|
85
|
-
app.post('/api/products/:product_id/qa/:qa_id/answer', (req, res) => {
|
|
84
|
+
app.post('/api/products/:product_id/qa/:qa_id/answer', async (req, res) => {
|
|
86
85
|
const user = auth(req, res);
|
|
87
86
|
if (!user)
|
|
88
87
|
return;
|
|
89
|
-
const qa =
|
|
88
|
+
const qa = await dbOne('SELECT id, seller_id, answer FROM product_qa WHERE id = ? AND product_id = ?', [req.params.qa_id, req.params.product_id]);
|
|
90
89
|
if (!qa)
|
|
91
90
|
return void res.status(404).json({ error: '提问不存在' });
|
|
92
91
|
if (qa.seller_id !== user.id)
|
|
@@ -96,40 +95,38 @@ export function registerWishlistQaRoutes(app, deps) {
|
|
|
96
95
|
const answer = String(req.body?.answer || '').trim();
|
|
97
96
|
if (answer.length < 2 || answer.length > 1000)
|
|
98
97
|
return void res.status(400).json({ error: 'answer 长度需 2-1000 字' });
|
|
99
|
-
|
|
98
|
+
await dbRun(`UPDATE product_qa SET answer = ?, answered_at = datetime('now') WHERE id = ?`, [answer, req.params.qa_id]);
|
|
100
99
|
try {
|
|
101
|
-
const asker =
|
|
102
|
-
|
|
103
|
-
.run(generateId('ntf'), asker.asker_id, '卖家回答了你的提问', answer.slice(0, 80) + (answer.length > 80 ? '...' : ''), null);
|
|
100
|
+
const asker = (await dbOne('SELECT asker_id, question FROM product_qa WHERE id = ?', [req.params.qa_id]));
|
|
101
|
+
await dbRun(`INSERT INTO notifications (id, user_id, title, body, order_id) VALUES (?,?,?,?,?)`, [generateId('ntf'), asker.asker_id, '卖家回答了你的提问', answer.slice(0, 80) + (answer.length > 80 ? '...' : ''), null]);
|
|
104
102
|
}
|
|
105
103
|
catch { }
|
|
106
104
|
res.json({ success: true });
|
|
107
105
|
});
|
|
108
|
-
app.get('/api/products/:product_id/qa', (req, res) => {
|
|
106
|
+
app.get('/api/products/:product_id/qa', async (req, res) => {
|
|
109
107
|
// 公开列表(不需要登录,但只返回 is_public=1)
|
|
110
|
-
const rows =
|
|
108
|
+
const rows = await dbAll(`
|
|
111
109
|
SELECT qa.id, qa.question, qa.answer, qa.answered_at, qa.helpful_count, qa.created_at,
|
|
112
110
|
ua.name as asker_name, ua.handle as asker_handle
|
|
113
111
|
FROM product_qa qa JOIN users ua ON ua.id = qa.asker_id
|
|
114
112
|
WHERE qa.product_id = ? AND qa.is_public = 1
|
|
115
113
|
ORDER BY qa.answered_at IS NULL ASC, qa.helpful_count DESC, qa.created_at DESC LIMIT 50
|
|
116
|
-
|
|
114
|
+
`, [req.params.product_id]);
|
|
117
115
|
res.json({ items: rows });
|
|
118
116
|
});
|
|
119
|
-
app.post('/api/products/:product_id/qa/:qa_id/helpful', (req, res) => {
|
|
117
|
+
app.post('/api/products/:product_id/qa/:qa_id/helpful', async (req, res) => {
|
|
120
118
|
const user = auth(req, res);
|
|
121
119
|
if (!user)
|
|
122
120
|
return;
|
|
123
121
|
// 防重复 — 每用户每条 QA 仅可 +1
|
|
124
122
|
try {
|
|
125
|
-
|
|
123
|
+
await dbRun(`INSERT INTO product_qa_helpful_voters (qa_id, user_id) VALUES (?, ?)`, [req.params.qa_id, user.id]);
|
|
126
124
|
}
|
|
127
125
|
catch {
|
|
128
|
-
const qa =
|
|
126
|
+
const qa = await dbOne(`SELECT helpful_count FROM product_qa WHERE id = ?`, [req.params.qa_id]);
|
|
129
127
|
return void res.json({ success: false, already_voted: true, helpful_count: qa?.helpful_count || 0 });
|
|
130
128
|
}
|
|
131
|
-
|
|
132
|
-
.run(req.params.qa_id, req.params.product_id);
|
|
129
|
+
await dbRun(`UPDATE product_qa SET helpful_count = COALESCE(helpful_count, 0) + 1 WHERE id = ? AND product_id = ?`, [req.params.qa_id, req.params.product_id]);
|
|
133
130
|
res.json({ success: true });
|
|
134
131
|
});
|
|
135
132
|
}
|