@mohasinac/appkit 2.6.8 → 2.7.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/README.md +207 -0
- package/dist/_internal/server/jobs/core/onScamReportCreate.d.ts +12 -0
- package/dist/_internal/server/jobs/core/onScamReportCreate.js +50 -0
- package/dist/_internal/server/jobs/core/onScamReportRejected.d.ts +11 -0
- package/dist/_internal/server/jobs/core/onScamReportRejected.js +28 -0
- package/dist/_internal/server/jobs/core/onScamReportVerified.d.ts +11 -0
- package/dist/_internal/server/jobs/core/onScamReportVerified.js +28 -0
- package/dist/_internal/server/jobs/handlers/index.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/index.js +3 -0
- package/dist/_internal/server/jobs/handlers/onScamReportCreate.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/onScamReportCreate.js +7 -0
- package/dist/_internal/server/jobs/handlers/onScamReportUpdate.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/onScamReportUpdate.js +25 -0
- package/dist/client.d.ts +2 -0
- package/dist/client.js +1 -0
- package/dist/configs/next.js +2 -0
- package/dist/features/scams/components/ScamAwarenessModal.d.ts +5 -0
- package/dist/features/scams/components/ScamAwarenessModal.js +31 -0
- package/dist/features/scams/components/index.d.ts +2 -0
- package/dist/features/scams/components/index.js +1 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +4 -5
- package/dist/jobs.d.ts +1 -1
- package/dist/jobs.js +2 -0
- package/dist/react/contexts/SessionContext.d.ts +1 -0
- package/dist/react/contexts/SessionContext.js +6 -0
- package/dist/seed/actions/demo-seed-actions.d.ts +1 -1
- package/dist/seed/index.d.ts +1 -0
- package/dist/seed/index.js +1 -0
- package/dist/seed/manifest.js +5 -0
- package/dist/seed/support-tickets-seed-data.d.ts +9 -0
- package/dist/seed/support-tickets-seed-data.js +135 -0
- package/dist/tailwind-utilities.css +1 -1
- package/package.json +210 -210
package/README.md
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# @mohasinac/appkit
|
|
2
|
+
|
|
3
|
+
Internal component library and server toolkit for the LetItRip collectibles marketplace.
|
|
4
|
+
|
|
5
|
+
## Architecture
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
appkit/src/
|
|
9
|
+
├── _internal/
|
|
10
|
+
│ ├── client/features/ # Client-side feature views (RSC-compatible islands)
|
|
11
|
+
│ ├── server/features/ # Server data-fetchers, adapters, server actions
|
|
12
|
+
│ └── shared/ # Types, config, constants shared across both
|
|
13
|
+
├── features/ # Domain feature modules (auth, products, scams, support …)
|
|
14
|
+
├── repositories/ # Firestore Admin SDK repository layer (one per collection)
|
|
15
|
+
├── seed/ # Seed data + manifest for SeedPanel
|
|
16
|
+
├── ui/ # Primitive UI components (Button, Input, Modal, Stack …)
|
|
17
|
+
├── next/ # Next.js helpers (ROUTES, route-map, hooks, SSR utilities)
|
|
18
|
+
├── seo/ # JSON-LD builders, metadata helpers
|
|
19
|
+
└── configs/ # Next.js + Tailwind shared config
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Entry Points
|
|
23
|
+
|
|
24
|
+
| Entry | Purpose |
|
|
25
|
+
|-------|---------|
|
|
26
|
+
| `@mohasinac/appkit` | Main barrel — UI, repositories, constants, seed data |
|
|
27
|
+
| `@mohasinac/appkit/client` | Client bundle — UI components, client hooks (firebase-admin free) |
|
|
28
|
+
| `@mohasinac/appkit/server` | Server bundle — Admin SDK providers, server actions |
|
|
29
|
+
| `@mohasinac/appkit/jobs` | Firebase Functions binders + pure job handlers |
|
|
30
|
+
| `@mohasinac/appkit/styles` | Pre-compiled Tailwind utilities CSS |
|
|
31
|
+
|
|
32
|
+
## Development
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# From the letitrip.in root — watches src/ and recompiles on change
|
|
36
|
+
npm run watch:appkit
|
|
37
|
+
|
|
38
|
+
# Full build + CSS + asset copy
|
|
39
|
+
npm run build # inside appkit/
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The consumer app links via `"file:./appkit"` — no npm publish required during local dev.
|
|
43
|
+
|
|
44
|
+
## Publishing
|
|
45
|
+
|
|
46
|
+
Only publish when explicitly requested. See `CLAUDE.md § Appkit Publish & Deploy Rules`.
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# 1. Commit all source changes
|
|
50
|
+
# 2. npm run build (inside appkit/)
|
|
51
|
+
# 3. npm publish (inside appkit/)
|
|
52
|
+
# 4. Update letitrip package.json + lockfile
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Version History
|
|
58
|
+
|
|
59
|
+
### v2.7.0 — 2026-05-14
|
|
60
|
+
|
|
61
|
+
**Support Tickets seed data + Firestore indices + seed pipeline wiring (BAN9/SCAM9 followup)**
|
|
62
|
+
|
|
63
|
+
- `appkit/src/seed/support-tickets-seed-data.ts` — 6 sample tickets covering all 5 statuses (open, in_progress, waiting_on_user, resolved, closed) and 5 categories
|
|
64
|
+
- `SeedCollectionName` extended with `"supportTickets"`; wired into seed manifest + barrel + consumer seed route
|
|
65
|
+
- `SUPPORT_TICKET_COLLECTION`, `ACTIVE_TICKET_STATUSES`, `TicketCategoryValues`, `TicketStatusValues`, `TicketPriorityValues` exported from main barrel
|
|
66
|
+
- 6 new Firestore composite indices for `supportTickets` (userId+status+createdAt, assignedTo+status, status+priority, category+status, etc.)
|
|
67
|
+
- `firestore.indexes.json` regenerated via `firebase-merge.mjs`
|
|
68
|
+
- SeedPanel: `supportTickets` entry added to Trust & Safety group with full field schema + seededItems + uiPath
|
|
69
|
+
- CSS build fix: stale `tailwind-utilities.css` rebuilt; `verify-css-build.mjs` passes all 8 required breakpoints/classes
|
|
70
|
+
|
|
71
|
+
### v2.6.9 — 2026-05-14
|
|
72
|
+
|
|
73
|
+
**Vercel Lambda transitive dependency tracing fix**
|
|
74
|
+
|
|
75
|
+
- `appkit/src/configs/next.ts`: added `@grpc/**`, `protobufjs/**`, `@protobufjs/**`, `object-hash/**`, `proto3-json-serializer/**`, `long/**`, `node-fetch/**`, `abort-controller/**`, `retry-request/**`, `duplexify/**`, `uuid/**`, `lodash.camelcase/**` to `defaultOutputFileTracingIncludes["/api/**"]`
|
|
76
|
+
- Fixes `MODULE_NOT_FOUND: object-hash` and `@protobufjs/*` sub-package `Cannot find module` errors in Vercel Lambdas (google-gax transitive deps)
|
|
77
|
+
|
|
78
|
+
### v2.6.8 — 2026-05-14
|
|
79
|
+
|
|
80
|
+
**gRPC/protobuf transitive dep tracing**
|
|
81
|
+
|
|
82
|
+
- Added `grpc_node.node` native binding and `@grpc/grpc-js/**` to `defaultOutputFileTracingIncludes`
|
|
83
|
+
|
|
84
|
+
### v2.6.7 — 2026-05-14
|
|
85
|
+
|
|
86
|
+
**TitleBar auth buttons + role badge + employee role + avatar fix**
|
|
87
|
+
|
|
88
|
+
- `TitleBarLayout`: `loginHref`/`registerHref` props; guest "Sign in"/"Register" buttons on desktop (lg+); replaced `next/image` with `<img>` for any-domain avatar support
|
|
89
|
+
- `AppLayoutShell`: `registerHref` prop forwarded to `TitleBar`; `RoleBadge` overlay replaced with 16px colored dot (role initial, no text overflow)
|
|
90
|
+
- `RoleBadge + Badge`: `employee` label/color/variant; `appkit-badge--employee` amber CSS (light + dark)
|
|
91
|
+
- Scam awareness: `ScamAwarenessModal` client component (non-dismissible, 7 category cards, checkbox ack); `scamAwarenessAcknowledgedAt` added to `SessionUser`; `LayoutShellClient` 30-day gate
|
|
92
|
+
- `LoginForm`/`RegisterForm`: `renderCreateAccountLink`, `renderForgotPasswordLink`, `renderLoginLink`, `renderTermsLink` slot props
|
|
93
|
+
- Seed users: `avatarMetadata` on 3 existing users; `user-deepak-verma` (moderator) + `user-simran-kaur` (employee) with avatarMetadata
|
|
94
|
+
|
|
95
|
+
### v2.6.5 — 2026-05-13
|
|
96
|
+
|
|
97
|
+
**Dashboard listing quality pass + CSS var tokens**
|
|
98
|
+
|
|
99
|
+
- `AdminPrizeDrawsView`: CSS var token pass replacing hardcoded zinc/red dark pairs
|
|
100
|
+
- `SellerPreOrdersView`, `SellerPrizeDrawsView`: new seller listing views with URL state
|
|
101
|
+
- `SELLER_PRE_ORDER_STATUS_TABS`, `SELLER_PRIZE_DRAW_STATUS_TABS` added to `filter-tabs.ts`
|
|
102
|
+
- Client barrel exports for 3 new views
|
|
103
|
+
|
|
104
|
+
### v2.6.4 — 2026-05-13
|
|
105
|
+
|
|
106
|
+
**S-SBUNI-RULES refund/payout/shipping constants quality pass**
|
|
107
|
+
|
|
108
|
+
- `REFUND_COPY` constants module — single source for all refund/shipping/sibling-payment strings
|
|
109
|
+
- `PayoutRefundDeduction` interface + `applyRefundDeductionAction`
|
|
110
|
+
- `buildShiprocketTrackingUrl()` + `SHIPROCKET_STATUS_PICKUP_SCHEDULED` constants
|
|
111
|
+
- `TB1/TB2/MNB-1/BN-1` layout system: breakpoint `lg` governs all four; no duplicate wishlist/notificationSlot
|
|
112
|
+
|
|
113
|
+
### v2.6.3 — 2026-05-13
|
|
114
|
+
|
|
115
|
+
**Firebase Functions ADC cold-start fix**
|
|
116
|
+
|
|
117
|
+
- `admin.ts` + `admin-app-lite.ts`: detect `FUNCTION_TARGET || K_SERVICE || FIREBASE_CONFIG || GOOGLE_APPLICATION_CREDENTIALS` → `initializeApp()` with no credential
|
|
118
|
+
- Closes cold-start 500 on every HTTPS Cloud Function
|
|
119
|
+
|
|
120
|
+
### v2.6.2 — 2026-05-13
|
|
121
|
+
|
|
122
|
+
**S9 RBAC complete — employee permission system + team management + store capabilities**
|
|
123
|
+
|
|
124
|
+
- `Permission` union (85+ strings) + `EmployeeGroup` union (18 presets) + `PERMISSION_GROUPS` bundles + `StoreCapability` flags
|
|
125
|
+
- `getServerPermissions()` resolver — admin bypasses, employee gated by `permissions[]`
|
|
126
|
+
- `makeAdminSectionLayout()` factory — generates per-section RSC layout with `admin:X:read` gate
|
|
127
|
+
- `AdminTeamView` + `AdminEmployeeEditorView` — invite/edit/revoke employee accounts with permission group picker
|
|
128
|
+
- `getStoreCapabilities()` + `storeHasCapability()` — `capabilities[]` array enforcement on auction/preorder creation
|
|
129
|
+
- `AdminStoreEditorView` Capabilities section — 3 collapsible tiers with per-capability checkboxes
|
|
130
|
+
- `ADMIN_NAV_GROUPS`: `requiredPermission` annotation on every item; `DashboardLayoutClient.filterAdminGroups` hides items by permissions
|
|
131
|
+
- `ROUTE_PERMISSION_MAP` — maps every `/admin/[section]` path to its required read permission
|
|
132
|
+
|
|
133
|
+
### v2.6.1 — 2026-05-13
|
|
134
|
+
|
|
135
|
+
**S-SBUNI Phase 1 fully closed + SB-UNI-Z1/Z2/Z3 media upload reliability**
|
|
136
|
+
|
|
137
|
+
- Signed-URL upload flow replacing `/api/media/upload` (SB-UNI-Z1)
|
|
138
|
+
- MIME widening: `3gpp`, `3gpp2`, `x-matroska` (SB-UNI-Z2)
|
|
139
|
+
- Media limits centralized in `_internal/shared/media/limits.ts` (SB-UNI-Z3)
|
|
140
|
+
- `bundleStockStatus` propagation via `onProductStockChangeHandler` (SB-UNI-V)
|
|
141
|
+
- Bundle → `categoryType:"bundle"` migration complete; `BUNDLES_COLLECTION` dropped
|
|
142
|
+
|
|
143
|
+
### v2.6.0 — 2026-05-13
|
|
144
|
+
|
|
145
|
+
**S8 Event Raffles + Spin Wheel + SB10 tab constants**
|
|
146
|
+
|
|
147
|
+
- SB9 raffle/spin schema (14 raffle fields on Event, 5 on EventEntry)
|
|
148
|
+
- `triggerEventRaffleAction` + `assignSpinPrizeAction` server actions (`crypto.randomInt`)
|
|
149
|
+
- `SpinWheelView` + public winner page
|
|
150
|
+
- Admin raffle section with manual trigger in event editor
|
|
151
|
+
- `SB10` filter-tab constants: `SELLER_LISTING_TABS`, `STORE_LISTINGS_TABS`, `filter-tabs.ts` with 6 view migrations
|
|
152
|
+
- SB11 homepage section builder types for `FeaturedBundles`, `PrizeDraws`, `EventRaffles`
|
|
153
|
+
|
|
154
|
+
### v2.5.x — 2026-05-11 to 2026-05-13
|
|
155
|
+
|
|
156
|
+
**S7 Prize Draws cohort + SB-UNI Phases 1–5**
|
|
157
|
+
|
|
158
|
+
- SB4 reveal API (crypto.randomInt pool-exhaust auto-refund) + lock-on-reveal + theatrical 3.2s modal
|
|
159
|
+
- 7 Firebase Functions: prizeRevealOpen/Close/Expiry/Reminder, bundleStockSync, triggerEventRaffle, assignSpinPrize
|
|
160
|
+
- SB-UNI address top-level collection (`ownerType` discriminator), categories unification (sublisting/brand/bundle)
|
|
161
|
+
- `listingType` migration complete: `isAuction`/`isPreOrder` booleans removed; all queries via `where("listingType","==",X)`
|
|
162
|
+
- `isAuctionListing()`, `isPreOrderListing()`, `normalizeListingType()` canonical accessors
|
|
163
|
+
|
|
164
|
+
### v2.4.x — 2026-05-10 to 2026-05-11
|
|
165
|
+
|
|
166
|
+
**S5/S6 seed scale + S4 bundle/pre-order foundation**
|
|
167
|
+
|
|
168
|
+
- Auction expansion (11→20) + bid ladder helper `buildBidLadder()`
|
|
169
|
+
- Bundle schema: `SB3` stock-sync hook, admin list/edit pages, Zod hardening
|
|
170
|
+
- OG edge-runtime fix: all 9 OG routes switched from `runtime="edge"` to Node runtime
|
|
171
|
+
- Wishlist (20-cap), History (50-cap FIFO), Cart (50-cap) per-user one-doc pattern
|
|
172
|
+
|
|
173
|
+
### v2.3.x — 2026-05-08 to 2026-05-09
|
|
174
|
+
|
|
175
|
+
**S2/S3 cart, checkout, orders, SSR architecture**
|
|
176
|
+
|
|
177
|
+
- `_internal/server/features/` layers: cart, orders, promotions, reviews, wishlist, history, homepage
|
|
178
|
+
- `listingType` field introduced; `isAuction`/`isPreOrder` deprecated (fully removed in v2.5)
|
|
179
|
+
- Support ticket schema + `SupportRepository` (BAN1)
|
|
180
|
+
- Ban schema: `softBans[]`, `hardBanReason`, `hardBannedAt`; `isSoftBanned()` helper
|
|
181
|
+
|
|
182
|
+
### v2.2.x — 2026-05-06 to 2026-05-07
|
|
183
|
+
|
|
184
|
+
**Scam registry foundation + homepage sections + prize draws schema**
|
|
185
|
+
|
|
186
|
+
- `ScammerDocument` + `scammerRepository` + 27 scam types + SCAM_CATEGORIES
|
|
187
|
+
- Public scam pages: `/scams`, `/scams/[slug]`, `/scams/types`
|
|
188
|
+
- Homepage sections (19 types): `SB11` full section-builder admin UI
|
|
189
|
+
- `DashboardLayoutClient` + `RoleGuard` — collapsed 3 separate layout shells
|
|
190
|
+
|
|
191
|
+
### v2.1.x — 2026-05-04 to 2026-05-05
|
|
192
|
+
|
|
193
|
+
**Auth, addresses, messages foundation**
|
|
194
|
+
|
|
195
|
+
- RTDB signal channel for Google OAuth
|
|
196
|
+
- Addresses top-level collection (`SB-UNI-A`)
|
|
197
|
+
- `conversationsRepository` + RTDB ping-channel for messages (D5+VC7)
|
|
198
|
+
- `ScrollToTop` component; `BaseListingCard.Checkbox` + `useLongPress` card-selection pattern
|
|
199
|
+
|
|
200
|
+
### v2.0.0 — 2026-05-03
|
|
201
|
+
|
|
202
|
+
**Initial appkit extraction from letitrip monorepo**
|
|
203
|
+
|
|
204
|
+
- Extracted from inline letitrip.in code into standalone `@mohasinac/appkit` package
|
|
205
|
+
- Firebase Admin SDK entry point separation (`server.ts` vs `client.ts`)
|
|
206
|
+
- `sideEffects: false` for Turbopack client-bundle safety
|
|
207
|
+
- Repository pattern: `BaseRepository` with PII encryption hooks
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { JobContext } from "../runtime/types";
|
|
2
|
+
export interface HandleScamReportCreateInput {
|
|
3
|
+
scammerId: string;
|
|
4
|
+
report: {
|
|
5
|
+
reportedBy?: string;
|
|
6
|
+
displayNames?: string[];
|
|
7
|
+
scamType?: string;
|
|
8
|
+
scamPlatform?: string;
|
|
9
|
+
amountLost?: number;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export declare function handleScamReportCreate(input: HandleScamReportCreateInput, ctx: JobContext): Promise<void>;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { notificationRepository, userRepository } from "../../../../repositories";
|
|
2
|
+
import { SCAM_TYPE_LABELS } from "../../../../features/scams/constants/scam-types";
|
|
3
|
+
export async function handleScamReportCreate(input, ctx) {
|
|
4
|
+
const { scammerId, report } = input;
|
|
5
|
+
const { reportedBy, displayNames, scamType, scamPlatform, amountLost } = report;
|
|
6
|
+
const name = displayNames?.[0] ?? "Unknown";
|
|
7
|
+
// 1. Notify the reporter
|
|
8
|
+
if (reportedBy) {
|
|
9
|
+
try {
|
|
10
|
+
await notificationRepository.create({
|
|
11
|
+
userId: reportedBy,
|
|
12
|
+
type: "account_action",
|
|
13
|
+
title: "Scam report submitted",
|
|
14
|
+
body: `Your report for "${name}" has been received. Our team will review it within 48 hours.`,
|
|
15
|
+
isRead: false,
|
|
16
|
+
entityId: scammerId,
|
|
17
|
+
entityType: "scammer",
|
|
18
|
+
createdAt: new Date(),
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
ctx.logger.error("Failed to notify reporter (non-fatal)", err, { scammerId, reportedBy });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
// 2. Notify all employees with admin:scammers:read permission
|
|
26
|
+
try {
|
|
27
|
+
const result = await userRepository.list({
|
|
28
|
+
filters: "role==employee",
|
|
29
|
+
page: 1,
|
|
30
|
+
pageSize: 100,
|
|
31
|
+
});
|
|
32
|
+
const scamTypeLabel = scamType ? (SCAM_TYPE_LABELS[scamType] ?? scamType) : "Unknown";
|
|
33
|
+
const amountStr = amountLost ? ` ₹${(amountLost / 100).toLocaleString("en-IN")}` : "";
|
|
34
|
+
const platformStr = scamPlatform ? ` via ${scamPlatform}` : "";
|
|
35
|
+
await Promise.all(result.items.map((employee) => notificationRepository.create({
|
|
36
|
+
userId: employee.id,
|
|
37
|
+
type: "account_action",
|
|
38
|
+
title: "New scam report submitted",
|
|
39
|
+
body: `A report was submitted for "${name}" — ${scamTypeLabel}${platformStr}.${amountStr}`,
|
|
40
|
+
isRead: false,
|
|
41
|
+
entityId: scammerId,
|
|
42
|
+
entityType: "scammer",
|
|
43
|
+
createdAt: new Date(),
|
|
44
|
+
}).catch((err) => ctx.logger.error("Failed to notify employee (non-fatal)", err, { scammerId, employeeId: employee.id }))));
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
ctx.logger.error("Failed to query employees for scam notification (non-fatal)", err, { scammerId });
|
|
48
|
+
}
|
|
49
|
+
ctx.logger.info("onScamReportCreate complete", { scammerId, reportedBy });
|
|
50
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { JobContext } from "../runtime/types";
|
|
2
|
+
export interface HandleScamReportRejectedInput {
|
|
3
|
+
scammerId: string;
|
|
4
|
+
report: {
|
|
5
|
+
reportedBy?: string;
|
|
6
|
+
displayNames?: string[];
|
|
7
|
+
prevStatus?: string;
|
|
8
|
+
nextStatus?: string;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export declare function handleScamReportRejected(input: HandleScamReportRejectedInput, ctx: JobContext): Promise<void>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { notificationRepository } from "../../../../repositories";
|
|
2
|
+
export async function handleScamReportRejected(input, ctx) {
|
|
3
|
+
const { scammerId, report } = input;
|
|
4
|
+
const { reportedBy, displayNames, prevStatus, nextStatus } = report;
|
|
5
|
+
if (prevStatus === nextStatus)
|
|
6
|
+
return;
|
|
7
|
+
if (nextStatus !== "rejected")
|
|
8
|
+
return;
|
|
9
|
+
if (!reportedBy)
|
|
10
|
+
return;
|
|
11
|
+
const name = displayNames?.[0] ?? "Unknown";
|
|
12
|
+
try {
|
|
13
|
+
await notificationRepository.create({
|
|
14
|
+
userId: reportedBy,
|
|
15
|
+
type: "account_action",
|
|
16
|
+
title: "Scam report not verified",
|
|
17
|
+
body: `Your report for "${name}" could not be verified with the evidence provided. You may submit a new report with additional evidence.`,
|
|
18
|
+
isRead: false,
|
|
19
|
+
entityId: scammerId,
|
|
20
|
+
entityType: "scammer",
|
|
21
|
+
createdAt: new Date(),
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
ctx.logger.error("Failed to notify reporter of rejection (non-fatal)", err, { scammerId, reportedBy });
|
|
26
|
+
}
|
|
27
|
+
ctx.logger.info("onScamReportRejected complete", { scammerId, reportedBy });
|
|
28
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { JobContext } from "../runtime/types";
|
|
2
|
+
export interface HandleScamReportVerifiedInput {
|
|
3
|
+
scammerId: string;
|
|
4
|
+
report: {
|
|
5
|
+
reportedBy?: string;
|
|
6
|
+
displayNames?: string[];
|
|
7
|
+
prevStatus?: string;
|
|
8
|
+
nextStatus?: string;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export declare function handleScamReportVerified(input: HandleScamReportVerifiedInput, ctx: JobContext): Promise<void>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { notificationRepository } from "../../../../repositories";
|
|
2
|
+
export async function handleScamReportVerified(input, ctx) {
|
|
3
|
+
const { scammerId, report } = input;
|
|
4
|
+
const { reportedBy, displayNames, prevStatus, nextStatus } = report;
|
|
5
|
+
if (prevStatus === nextStatus)
|
|
6
|
+
return;
|
|
7
|
+
if (nextStatus !== "verified")
|
|
8
|
+
return;
|
|
9
|
+
if (!reportedBy)
|
|
10
|
+
return;
|
|
11
|
+
const name = displayNames?.[0] ?? "Unknown";
|
|
12
|
+
try {
|
|
13
|
+
await notificationRepository.create({
|
|
14
|
+
userId: reportedBy,
|
|
15
|
+
type: "account_action",
|
|
16
|
+
title: "Your scam report was verified",
|
|
17
|
+
body: `The report for "${name}" has been verified and published to the Scam Registry. Thank you for helping protect the community.`,
|
|
18
|
+
isRead: false,
|
|
19
|
+
entityId: scammerId,
|
|
20
|
+
entityType: "scammer",
|
|
21
|
+
createdAt: new Date(),
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
ctx.logger.error("Failed to notify reporter of verification (non-fatal)", err, { scammerId, reportedBy });
|
|
26
|
+
}
|
|
27
|
+
ctx.logger.info("onScamReportVerified complete", { scammerId, reportedBy });
|
|
28
|
+
}
|
|
@@ -44,3 +44,5 @@ export { assignSpinPrizeHandler } from "./assignSpinPrize";
|
|
|
44
44
|
export { onSupportTicketCreateHandler } from "./onSupportTicketCreate";
|
|
45
45
|
export { onSupportTicketUpdateHandler } from "./onSupportTicketUpdate";
|
|
46
46
|
export { onUserBanChangeHandler } from "./onUserBanChange";
|
|
47
|
+
export { onScamReportCreateHandler } from "./onScamReportCreate";
|
|
48
|
+
export { onScamReportUpdateHandler } from "./onScamReportUpdate";
|
|
@@ -50,3 +50,6 @@ export { assignSpinPrizeHandler } from "./assignSpinPrize";
|
|
|
50
50
|
export { onSupportTicketCreateHandler } from "./onSupportTicketCreate";
|
|
51
51
|
export { onSupportTicketUpdateHandler } from "./onSupportTicketUpdate";
|
|
52
52
|
export { onUserBanChangeHandler } from "./onUserBanChange";
|
|
53
|
+
// SCAM8 — scam report notifications
|
|
54
|
+
export { onScamReportCreateHandler } from "./onScamReportCreate";
|
|
55
|
+
export { onScamReportUpdateHandler } from "./onScamReportUpdate";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { handleScamReportCreate } from "../core/onScamReportCreate";
|
|
2
|
+
export const onScamReportCreateHandler = async (event, ctx) => {
|
|
3
|
+
const report = event.after;
|
|
4
|
+
if (!report)
|
|
5
|
+
return;
|
|
6
|
+
await handleScamReportCreate({ scammerId: event.params.scammerId, report }, ctx);
|
|
7
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { handleScamReportVerified } from "../core/onScamReportVerified";
|
|
2
|
+
import { handleScamReportRejected } from "../core/onScamReportRejected";
|
|
3
|
+
export const onScamReportUpdateHandler = async (event, ctx) => {
|
|
4
|
+
const before = event.before;
|
|
5
|
+
const after = event.after;
|
|
6
|
+
if (!after)
|
|
7
|
+
return;
|
|
8
|
+
const prevStatus = before?.status;
|
|
9
|
+
const nextStatus = after.status;
|
|
10
|
+
const baseInput = {
|
|
11
|
+
scammerId: event.params.scammerId,
|
|
12
|
+
report: {
|
|
13
|
+
reportedBy: (after.reportedBy ?? before?.reportedBy),
|
|
14
|
+
displayNames: (after.displayNames ?? before?.displayNames),
|
|
15
|
+
prevStatus,
|
|
16
|
+
nextStatus,
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
if (nextStatus === "verified") {
|
|
20
|
+
await handleScamReportVerified(baseInput, ctx);
|
|
21
|
+
}
|
|
22
|
+
else if (nextStatus === "rejected") {
|
|
23
|
+
await handleScamReportRejected(baseInput, ctx);
|
|
24
|
+
}
|
|
25
|
+
};
|
package/dist/client.d.ts
CHANGED
|
@@ -189,3 +189,5 @@ export { LISTING_TYPE_REGISTRY, pluginFor } from "./_internal/shared/listing-typ
|
|
|
189
189
|
export type { ListingTypePlugin } from "./_internal/shared/listing-types/_registry";
|
|
190
190
|
export { MEGABYTE, MAX_IMAGE_BYTES, MAX_PDF_BYTES, MAX_VIDEO_BYTES, MAX_LABEL, MAX_BYTES, ALLOWED_IMAGE_MIMES, ALLOWED_VIDEO_MIMES, ALLOWED_DOC_MIMES, ALLOWED_MIMES, ALLOWED_TYPES_LABEL, MIME_TO_EXT, PDF_MAGIC, VIDEO_CONVERSION_HINTS, classifyMime, isAllowedMime, maxBytesFor, getConversionHint, } from "./_internal/shared/media/limits";
|
|
191
191
|
export type { MediaKind, AllowedImageMime, AllowedVideoMime, AllowedDocMime, AllowedMime, } from "./_internal/shared/media/limits";
|
|
192
|
+
export { ScamAwarenessModal } from "./features/scams/components/ScamAwarenessModal";
|
|
193
|
+
export type { ScamAwarenessModalProps } from "./features/scams/components/ScamAwarenessModal";
|
package/dist/client.js
CHANGED
|
@@ -218,3 +218,4 @@ export { LISTING_TYPE_CAPABILITIES, capabilityFor, canAddToCart, canBid, support
|
|
|
218
218
|
export { LISTING_TYPE_REGISTRY, pluginFor } from "./_internal/shared/listing-types/_registry";
|
|
219
219
|
// Media upload limits — shared by client uploaders + server sign/finalize routes.
|
|
220
220
|
export { MEGABYTE, MAX_IMAGE_BYTES, MAX_PDF_BYTES, MAX_VIDEO_BYTES, MAX_LABEL, MAX_BYTES, ALLOWED_IMAGE_MIMES, ALLOWED_VIDEO_MIMES, ALLOWED_DOC_MIMES, ALLOWED_MIMES, ALLOWED_TYPES_LABEL, MIME_TO_EXT, PDF_MAGIC, VIDEO_CONVERSION_HINTS, classifyMime, isAllowedMime, maxBytesFor, getConversionHint, } from "./_internal/shared/media/limits";
|
|
221
|
+
export { ScamAwarenessModal } from "./features/scams/components/ScamAwarenessModal";
|
package/dist/configs/next.js
CHANGED
|
@@ -97,6 +97,7 @@ export function defineNextConfig(override = {}) {
|
|
|
97
97
|
"./node_modules/@grpc/**",
|
|
98
98
|
// Transitive deps of google-gax / @grpc hoisted to root node_modules
|
|
99
99
|
"./node_modules/protobufjs/**",
|
|
100
|
+
"./node_modules/@protobufjs/**",
|
|
100
101
|
"./node_modules/object-hash/**",
|
|
101
102
|
"./node_modules/proto3-json-serializer/**",
|
|
102
103
|
"./node_modules/long/**",
|
|
@@ -105,6 +106,7 @@ export function defineNextConfig(override = {}) {
|
|
|
105
106
|
"./node_modules/retry-request/**",
|
|
106
107
|
"./node_modules/duplexify/**",
|
|
107
108
|
"./node_modules/uuid/**",
|
|
109
|
+
"./node_modules/lodash.camelcase/**",
|
|
108
110
|
],
|
|
109
111
|
};
|
|
110
112
|
const mergedOutputFileTracingIncludes = {
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
|
5
|
+
import { Shield, IndianRupee, UserX, CreditCard, Package, UserCheck, ShieldAlert, Truck } from "lucide-react";
|
|
6
|
+
import { Modal, Stack, Row, Text, Checkbox } from "../../../ui";
|
|
7
|
+
import { apiClient } from "../../../http";
|
|
8
|
+
import { ACCOUNT_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
9
|
+
import { SCAM_CATEGORIES } from "../constants/scam-types";
|
|
10
|
+
import { ROUTES } from "../../../next/routing/route-map";
|
|
11
|
+
const CATEGORY_ICONS = {
|
|
12
|
+
price_manipulation: _jsx(IndianRupee, { className: "h-5 w-5" }),
|
|
13
|
+
social_engineering: _jsx(UserX, { className: "h-5 w-5" }),
|
|
14
|
+
payment_fraud: _jsx(CreditCard, { className: "h-5 w-5" }),
|
|
15
|
+
preorder_delivery_fraud: _jsx(Package, { className: "h-5 w-5" }),
|
|
16
|
+
identity_impersonation: _jsx(UserCheck, { className: "h-5 w-5" }),
|
|
17
|
+
item_authenticity_fraud: _jsx(ShieldAlert, { className: "h-5 w-5" }),
|
|
18
|
+
logistics_fraud: _jsx(Truck, { className: "h-5 w-5" }),
|
|
19
|
+
};
|
|
20
|
+
export function ScamAwarenessModal({ isOpen, onAcknowledged }) {
|
|
21
|
+
const [checked, setChecked] = useState(false);
|
|
22
|
+
const queryClient = useQueryClient();
|
|
23
|
+
const mutation = useMutation({
|
|
24
|
+
mutationFn: () => apiClient.patch(ACCOUNT_ENDPOINTS.PROFILE, { acknowledgeScamAwareness: true }),
|
|
25
|
+
onSuccess: () => {
|
|
26
|
+
queryClient.invalidateQueries({ queryKey: ["auth", "me"] });
|
|
27
|
+
onAcknowledged();
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
return (_jsx(Modal, { isOpen: isOpen, onClose: () => { }, showCloseButton: false, size: "lg", title: _jsxs(Row, { gap: "sm", align: "center", children: [_jsx(Shield, { className: "h-5 w-5 text-[color:var(--appkit-color-warning,theme(colors.amber.500))]" }), _jsx("span", { children: "Before you start \u2014 Stay Safe on LetItRip" })] }), actions: _jsx(Row, { gap: "sm", justify: "end", className: "w-full", children: _jsx("button", { className: "appkit-button appkit-button--primary appkit-button--md", disabled: !checked || mutation.isPending, onClick: () => mutation.mutate(), children: mutation.isPending ? "Saving…" : "Continue to LetItRip →" }) }), children: _jsxs(Stack, { gap: "md", children: [_jsx(Text, { variant: "secondary", className: "text-sm", children: "LetItRip connects you with verified sellers, but collectibles markets attract scams. Take 60 seconds to learn the most common patterns \u2014 it could save your money." }), _jsx("div", { className: "grid grid-cols-1 gap-3 sm:grid-cols-2", children: SCAM_CATEGORIES.map((cat) => (_jsxs("div", { className: "flex gap-3 rounded-lg border border-[color:var(--appkit-color-border,theme(colors.zinc.200))] bg-[color:var(--appkit-color-surface,theme(colors.zinc.50))] p-3", children: [_jsx("span", { className: "mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-md bg-[color:var(--appkit-color-warning,theme(colors.amber.500))]/10 text-[color:var(--appkit-color-warning,theme(colors.amber.600))]", children: CATEGORY_ICONS[cat.id] ?? _jsx(Shield, { className: "h-4 w-4" }) }), _jsxs(Stack, { gap: "none", children: [_jsx(Text, { weight: "semibold", className: "text-sm", children: cat.label }), _jsx(Text, { variant: "secondary", className: "text-xs leading-relaxed", children: cat.description })] })] }, cat.id))) }), _jsxs(Row, { gap: "md", className: "flex-wrap text-sm", children: [_jsx("a", { href: String(ROUTES.PUBLIC.SCAM_TYPES), target: "_blank", rel: "noopener noreferrer", className: "text-[color:var(--appkit-color-primary,theme(colors.blue.600))] hover:underline", children: "See all 27 scam types \u2192" }), _jsx("a", { href: String(ROUTES.PUBLIC.SCAM_FAQS), target: "_blank", rel: "noopener noreferrer", className: "text-[color:var(--appkit-color-primary,theme(colors.blue.600))] hover:underline", children: "Common scam FAQs \u2192" })] }), mutation.isError && (_jsx(Text, { variant: "error", className: "text-sm", children: "Something went wrong \u2014 please try again." })), _jsx(Checkbox, { id: "scam-awareness-ack", checked: checked, onChange: (e) => setChecked(e.target.checked), label: "I have read the above and understand the risks of buying and selling collectibles online." })] }) }));
|
|
31
|
+
}
|
|
@@ -2,3 +2,5 @@ export { ScamRegistryView } from "./ScamRegistryView";
|
|
|
2
2
|
export type { ScamRegistryViewProps } from "./ScamRegistryView";
|
|
3
3
|
export { ScamProfileView } from "./ScamProfileView";
|
|
4
4
|
export type { ScamProfileViewProps } from "./ScamProfileView";
|
|
5
|
+
export { ScamAwarenessModal } from "./ScamAwarenessModal";
|
|
6
|
+
export type { ScamAwarenessModalProps } from "./ScamAwarenessModal";
|
package/dist/index.d.ts
CHANGED
|
@@ -528,7 +528,8 @@ export { storeRepository } from "./repositories/index";
|
|
|
528
528
|
export { scammerRepository } from "./repositories/index";
|
|
529
529
|
export { supportRepository, SupportRepository } from "./repositories/index";
|
|
530
530
|
export type { SupportTicketDocument, SupportTicketCreateInput, SupportTicketUpdateInput, TicketMessage, TicketCategory, TicketStatus, TicketPriority, } from "./repositories/index";
|
|
531
|
-
export { ELIGIBLE_ORDER_STATUSES_FOR_TICKET } from "./features/support/schemas/firestore";
|
|
531
|
+
export { ELIGIBLE_ORDER_STATUSES_FOR_TICKET, SUPPORT_TICKET_COLLECTION, ACTIVE_TICKET_STATUSES, TicketCategoryValues, TicketStatusValues, TicketPriorityValues, } from "./features/support/schemas/firestore";
|
|
532
|
+
export { supportTicketsSeedData } from "./seed/index";
|
|
532
533
|
export { productFeaturesRepository } from "./repositories/index";
|
|
533
534
|
export type { ProductFeatureListFilter } from "./repositories/index";
|
|
534
535
|
export { loadProductFeaturesForStore } from "./repositories/index";
|
|
@@ -875,7 +876,6 @@ export type { ShiprocketTrackingResponse } from "./providers/shipping-shiprocket
|
|
|
875
876
|
export type { ShiprocketVerifyPickupOTPRequest } from "./providers/shipping-shiprocket/index";
|
|
876
877
|
export type { ShiprocketVerifyPickupOTPResponse } from "./providers/shipping-shiprocket/index";
|
|
877
878
|
export type { ShiprocketWebhookPayload } from "./providers/shipping-shiprocket/index";
|
|
878
|
-
export { firebaseStorageProvider } from "./providers/storage-firebase/index";
|
|
879
879
|
export { STORAGE_PATHS } from "./providers/storage-firebase/client";
|
|
880
880
|
export { createStorageHelpers } from "./providers/storage-firebase/client";
|
|
881
881
|
export { validateFileSize } from "./providers/storage-firebase/client";
|
|
@@ -3028,6 +3028,8 @@ export { ScamRegistryView } from "./features/scams/components/ScamRegistryView";
|
|
|
3028
3028
|
export type { ScamRegistryViewProps } from "./features/scams/components/ScamRegistryView";
|
|
3029
3029
|
export { ScamProfileView } from "./features/scams/components/ScamProfileView";
|
|
3030
3030
|
export type { ScamProfileViewProps } from "./features/scams/components/ScamProfileView";
|
|
3031
|
+
export { ScamAwarenessModal } from "./features/scams/components/ScamAwarenessModal";
|
|
3032
|
+
export type { ScamAwarenessModalProps } from "./features/scams/components/ScamAwarenessModal";
|
|
3031
3033
|
export { listVerifiedScammers, getPublicScammerById, getScammerProfilePageData, } from "./features/scams/actions/scam-actions";
|
|
3032
3034
|
export type { ScammerProfilePageData } from "./features/scams/actions/scam-actions";
|
|
3033
3035
|
export type { ScammerListResult } from "./features/scams/actions/scam-actions";
|
package/dist/index.js
CHANGED
|
@@ -1084,7 +1084,9 @@ export { storeRepository } from "./repositories/index";
|
|
|
1084
1084
|
export { scammerRepository } from "./repositories/index";
|
|
1085
1085
|
// supportRepository - Server-only repository for support tickets (BAN1).
|
|
1086
1086
|
export { supportRepository, SupportRepository } from "./repositories/index";
|
|
1087
|
-
export { ELIGIBLE_ORDER_STATUSES_FOR_TICKET } from "./features/support/schemas/firestore";
|
|
1087
|
+
export { ELIGIBLE_ORDER_STATUSES_FOR_TICKET, SUPPORT_TICKET_COLLECTION, ACTIVE_TICKET_STATUSES, TicketCategoryValues, TicketStatusValues, TicketPriorityValues, } from "./features/support/schemas/firestore";
|
|
1088
|
+
// Support tickets — seed data
|
|
1089
|
+
export { supportTicketsSeedData } from "./seed/index";
|
|
1088
1090
|
// SB-UNI-B — sublistingCategoriesRepository + SublistingCategoryDocument deleted.
|
|
1089
1091
|
// Use categoriesRepository.findBySlugAndType(slug, "sublisting") and CategoryDocument with categoryType:"sublisting".
|
|
1090
1092
|
// [DB]-Database layer — uses firebase-admin; server-only.
|
|
@@ -1806,10 +1808,6 @@ export { shiprocketTrackByAWB } from "./providers/shipping-shiprocket/index";
|
|
|
1806
1808
|
// [SERVER-ONLY]-Server-only — uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
|
|
1807
1809
|
// shiprocketVerifyPickupOTP - Shared export for shiprocket verify pickup otp.
|
|
1808
1810
|
export { shiprocketVerifyPickupOTP } from "./providers/shipping-shiprocket/index";
|
|
1809
|
-
// ./providers/storage-firebase/index
|
|
1810
|
-
// [CLIENT-SSR]-Runs in both SSR and browser — React component or hook that does not depend on browser-only APIs.
|
|
1811
|
-
// firebaseStorageProvider - Component for firebase storage provider.
|
|
1812
|
-
export { firebaseStorageProvider } from "./providers/storage-firebase/index";
|
|
1813
1811
|
// ./providers/storage-firebase/client
|
|
1814
1812
|
// [CLIENT-SSR]-Runs in both SSR and browser — React component or hook that does not depend on browser-only APIs.
|
|
1815
1813
|
// STORAGE_PATHS - Constant used across modules.
|
|
@@ -5496,6 +5494,7 @@ export { SCAM_TYPES, SCAM_CATEGORIES, SCAM_TYPE_LABELS, SCAM_CATEGORY_LABELS, ge
|
|
|
5496
5494
|
// Scam Registry view components (SCAM3–SCAM4)
|
|
5497
5495
|
export { ScamRegistryView } from "./features/scams/components/ScamRegistryView";
|
|
5498
5496
|
export { ScamProfileView } from "./features/scams/components/ScamProfileView";
|
|
5497
|
+
export { ScamAwarenessModal } from "./features/scams/components/ScamAwarenessModal";
|
|
5499
5498
|
// Scam server actions
|
|
5500
5499
|
export { listVerifiedScammers, getPublicScammerById, getScammerProfilePageData, } from "./features/scams/actions/scam-actions";
|
|
5501
5500
|
// --- Shell primitives (UX1/UX2/UX3/UX6) ----------------------------------------
|
package/dist/jobs.d.ts
CHANGED
|
@@ -20,5 +20,5 @@
|
|
|
20
20
|
* listingProcessorHandler,
|
|
21
21
|
* } from "@mohasinac/appkit/jobs";
|
|
22
22
|
*/
|
|
23
|
-
export { couponExpiryHandler, offerExpiryHandler, cartPruneHandler, notificationPruneHandler, dailyDataCleanupHandler, cleanupRtdbEventsHandler, auctionSettlementHandler, autoPayoutEligibilityHandler, countersReconcileHandler, onOrderCreateHandler, onOrderStatusChangeHandler, onBidPlacedHandler, onReviewWriteHandler, promotionsHandler, mediaTmpCleanupHandler, pendingOrderTimeoutHandler, productStatsSyncHandler, positionsReconcileHandler, payoutBatchHandler, weeklyPayoutEligibilityHandler, onCategoryWriteHandler, onProductWriteHandler, onStoreWriteHandler, adminAnalyticsHandler, storeAnalyticsHandler, listingProcessorHandler, supportedListingCollections, prizeRevealOpenHandler, prizeRevealCloseHandler, prizeRevealExpiryHandler, prizeRevealReminderHandler, bundleStockSyncHandler, onProductStockChangeHandler, triggerEventRaffleHandler, assignSpinPrizeHandler, onSupportTicketCreateHandler, onSupportTicketUpdateHandler, onUserBanChangeHandler, bindSchedule, bindDocumentWritten, bindDocumentCreated, bindDocumentUpdated, bindCallable, bindHttps, bindToFirebase, } from "./_internal/server/jobs/index.js";
|
|
23
|
+
export { couponExpiryHandler, offerExpiryHandler, cartPruneHandler, notificationPruneHandler, dailyDataCleanupHandler, cleanupRtdbEventsHandler, auctionSettlementHandler, autoPayoutEligibilityHandler, countersReconcileHandler, onOrderCreateHandler, onOrderStatusChangeHandler, onBidPlacedHandler, onReviewWriteHandler, promotionsHandler, mediaTmpCleanupHandler, pendingOrderTimeoutHandler, productStatsSyncHandler, positionsReconcileHandler, payoutBatchHandler, weeklyPayoutEligibilityHandler, onCategoryWriteHandler, onProductWriteHandler, onStoreWriteHandler, adminAnalyticsHandler, storeAnalyticsHandler, listingProcessorHandler, supportedListingCollections, prizeRevealOpenHandler, prizeRevealCloseHandler, prizeRevealExpiryHandler, prizeRevealReminderHandler, bundleStockSyncHandler, onProductStockChangeHandler, triggerEventRaffleHandler, assignSpinPrizeHandler, onSupportTicketCreateHandler, onSupportTicketUpdateHandler, onUserBanChangeHandler, onScamReportCreateHandler, onScamReportUpdateHandler, bindSchedule, bindDocumentWritten, bindDocumentCreated, bindDocumentUpdated, bindCallable, bindHttps, bindToFirebase, } from "./_internal/server/jobs/index.js";
|
|
24
24
|
export type { PromotionsCallableResult, AdminAnalyticsResult, StoreAnalyticsInput, StoreAnalyticsResult, ListingRequestBody, ListingResponseBody, JobContext, JobLogger, JobHandlers, ScheduleHandler, FirestoreTriggerHandler, FirestoreTriggerEvent, CallableHandler, BindHttpsOptions, } from "./_internal/server/jobs/index.js";
|
package/dist/jobs.js
CHANGED
|
@@ -29,5 +29,7 @@ prizeRevealOpenHandler, prizeRevealCloseHandler, prizeRevealExpiryHandler, prize
|
|
|
29
29
|
onProductStockChangeHandler, triggerEventRaffleHandler, assignSpinPrizeHandler,
|
|
30
30
|
// BAN9 — support ticket lifecycle + ban audit trail
|
|
31
31
|
onSupportTicketCreateHandler, onSupportTicketUpdateHandler, onUserBanChangeHandler,
|
|
32
|
+
// SCAM8 — scam report notifications
|
|
33
|
+
onScamReportCreateHandler, onScamReportUpdateHandler,
|
|
32
34
|
// Firebase binder adapter
|
|
33
35
|
bindSchedule, bindDocumentWritten, bindDocumentCreated, bindDocumentUpdated, bindCallable, bindHttps, bindToFirebase, } from "./_internal/server/jobs/index.js";
|
|
@@ -29,6 +29,7 @@ export interface SessionUser {
|
|
|
29
29
|
publicProfile?: Record<string, unknown>;
|
|
30
30
|
stats?: Record<string, unknown>;
|
|
31
31
|
metadata?: Record<string, unknown>;
|
|
32
|
+
scamAwarenessAcknowledgedAt?: Date | null;
|
|
32
33
|
}
|
|
33
34
|
export interface SessionContextValue {
|
|
34
35
|
user: SessionUser | null;
|
|
@@ -71,6 +71,9 @@ function buildSessionUser(authUser, serverData) {
|
|
|
71
71
|
publicProfile: serverData.publicProfile,
|
|
72
72
|
stats: serverData.stats,
|
|
73
73
|
metadata: serverData.metadata,
|
|
74
|
+
scamAwarenessAcknowledgedAt: serverData.scamAwarenessAcknowledgedAt
|
|
75
|
+
? new Date(serverData.scamAwarenessAcknowledgedAt)
|
|
76
|
+
: null,
|
|
74
77
|
};
|
|
75
78
|
}
|
|
76
79
|
// ---------------------------------------------------------------------------
|
|
@@ -134,6 +137,9 @@ export function SessionProvider({ children, initialUser, endpoints: endpointOver
|
|
|
134
137
|
publicProfile: data.publicProfile,
|
|
135
138
|
stats: data.stats,
|
|
136
139
|
metadata: data.metadata,
|
|
140
|
+
scamAwarenessAcknowledgedAt: data.scamAwarenessAcknowledgedAt
|
|
141
|
+
? new Date(data.scamAwarenessAcknowledgedAt)
|
|
142
|
+
: null,
|
|
137
143
|
};
|
|
138
144
|
}
|
|
139
145
|
catch {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* the actual collection-specific seeding logic (800+ lines with PII encryption,
|
|
7
7
|
* Auth user creation, subcollection handling, etc.).
|
|
8
8
|
*/
|
|
9
|
-
export type SeedCollectionName = "users" | "addresses" | "categories" | "stores" | "products" | "orders" | "reviews" | "bids" | "coupons" | "carousels" | "carouselSlides" | "homepageSections" | "siteSettings" | "faqs" | "notifications" | "payouts" | "blogPosts" | "events" | "eventEntries" | "sessions" | "carts" | "wishlists" | "history" | "conversations" | "groupedListings" | "scammerProfiles" | "productFeatures";
|
|
9
|
+
export type SeedCollectionName = "users" | "addresses" | "categories" | "stores" | "products" | "orders" | "reviews" | "bids" | "coupons" | "carousels" | "carouselSlides" | "homepageSections" | "siteSettings" | "faqs" | "notifications" | "payouts" | "blogPosts" | "events" | "eventEntries" | "sessions" | "carts" | "wishlists" | "history" | "conversations" | "groupedListings" | "scammerProfiles" | "supportTickets" | "productFeatures";
|
|
10
10
|
export interface SeedOperationResult {
|
|
11
11
|
success?: boolean;
|
|
12
12
|
message: string;
|
package/dist/seed/index.d.ts
CHANGED
|
@@ -70,6 +70,7 @@ export { historySeedData } from "./history-seed-data";
|
|
|
70
70
|
export { conversationsSeedData } from "./conversations-seed-data";
|
|
71
71
|
export { groupedListingsSeedData } from "./grouped-listings-seed-data";
|
|
72
72
|
export { scammersSeedData } from "./scammers-seed-data";
|
|
73
|
+
export { supportTicketsSeedData } from "./support-tickets-seed-data";
|
|
73
74
|
export { productFeaturesSeedData } from "./product-features-seed-data";
|
|
74
75
|
export type { SeedManifest, SeedManifestEntry } from "./manifest";
|
|
75
76
|
export { SEED_MANIFEST } from "./manifest";
|