@mohasinac/appkit 4.30.12 → 4.30.15

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 (57) hide show
  1. package/dist/errors/degraded.d.ts +52 -0
  2. package/dist/errors/degraded.js +47 -0
  3. package/dist/errors/index.d.ts +1 -0
  4. package/dist/errors/index.js +1 -0
  5. package/dist/features/admin/components/AdminBlogView.js +8 -1
  6. package/dist/features/admin/components/AdminCouponsView.js +8 -1
  7. package/dist/features/admin/components/AdminOffersView.js +9 -1
  8. package/dist/features/admin/components/AdminPayoutsView.js +9 -1
  9. package/dist/features/admin/components/AdminReviewsView.js +14 -1
  10. package/dist/features/admin/components/AdminScammersView.js +15 -1
  11. package/dist/features/admin/components/DataListingView.d.ts +22 -1
  12. package/dist/features/admin/components/DataListingView.js +7 -0
  13. package/dist/features/admin/hooks/useAdminListing.d.ts +9 -0
  14. package/dist/features/admin/hooks/useAdminListing.js +30 -2
  15. package/dist/features/events/components/AdminEventsView.js +7 -1
  16. package/dist/features/events/server.d.ts +0 -1
  17. package/dist/features/events/server.js +0 -1
  18. package/dist/features/faq/index.d.ts +0 -1
  19. package/dist/features/faq/index.js +0 -1
  20. package/dist/features/faq/server.d.ts +0 -1
  21. package/dist/features/faq/server.js +0 -1
  22. package/dist/features/reviews/server.d.ts +0 -1
  23. package/dist/features/reviews/server.js +0 -1
  24. package/dist/features/scams/repository/scammer.repository.d.ts +10 -1
  25. package/dist/features/scams/repository/scammer.repository.js +20 -2
  26. package/dist/features/scams/schemas/firestore.d.ts +10 -0
  27. package/dist/features/scams/schemas/firestore.js +1 -0
  28. package/dist/features/scams/schemas/index.d.ts +10 -10
  29. package/dist/features/seller/components/SellerCouponsView.js +7 -1
  30. package/dist/features/seller/components/SellerOffersView.js +8 -1
  31. package/dist/features/seller/components/SellerOrdersView.js +8 -1
  32. package/dist/features/seller/hooks/useSellerListingData.d.ts +11 -25
  33. package/dist/features/seller/hooks/useSellerListingData.js +0 -38
  34. package/dist/features/stores/server.d.ts +0 -1
  35. package/dist/features/stores/server.js +0 -1
  36. package/dist/index.d.ts +2 -7
  37. package/dist/index.js +3 -13
  38. package/dist/providers/db-firebase/base.js +7 -11
  39. package/dist/schemas/registry.d.ts +8 -8
  40. package/dist/security/index.d.ts +1 -1
  41. package/dist/security/index.js +1 -1
  42. package/dist/security/pii-encrypt.d.ts +0 -10
  43. package/dist/security/pii-encrypt.js +0 -38
  44. package/dist/seed/_helpers/search-txt-wrappers.d.ts +2 -0
  45. package/dist/seed/_helpers/search-txt-wrappers.js +4 -1
  46. package/dist/seed/scammers-seed-data.js +10 -1
  47. package/dist/server.d.ts +0 -6
  48. package/dist/server.js +0 -10
  49. package/dist/styles.css +1 -1
  50. package/dist/tailwind-utilities.css +1 -1
  51. package/dist/utils/index.d.ts +0 -1
  52. package/dist/utils/index.js +0 -1
  53. package/dist/utils/search-txt-builders.d.ts +13 -0
  54. package/dist/utils/search-txt-builders.js +20 -0
  55. package/dist/utils/sieve-builder.d.ts +0 -5
  56. package/dist/utils/sieve-builder.js +7 -8
  57. package/package.json +2 -9
@@ -24,7 +24,14 @@ export function SellerOffersView({ children, onAcceptOffer, onRejectOffer, onCou
24
24
  title: "Offers",
25
25
  // buildOfferSearchTxt indexes productTitle + productSlug + storeName — never
26
26
  // the buyer's name or email.
27
- searchPlaceholder: "Search by product or store…",
27
+ // buildOfferSearchTxt indexes productTitle + productSlug + storeName —
28
+ // never the buyer's name or email.
29
+ search: {
30
+ placeholder: "Search by product or store…",
31
+ mode: "partial",
32
+ fields: ["productTitle", "productSlug", "storeName"],
33
+ commit: "debounce",
34
+ },
28
35
  emptyLabel: "No offers received",
29
36
  filterKeys: ["status"],
30
37
  defaultSort: sortBy("createdAt", "DESC"),
@@ -297,7 +297,14 @@ export function SellerOrdersView({ orderDetailApiBase = SELLER_ENDPOINTS.ORDERS,
297
297
  // buildOrderSearchTxt indexes productTitle, storeName and trackingNumber.
298
298
  // It does NOT index the buyer's name, email or address — those are PII,
299
299
  // and the placeholder must not promise a match it will never make.
300
- searchPlaceholder: "Search by product, store or tracking number…",
300
+ // buildOrderSearchTxt indexes productTitle, storeName and trackingNumber.
301
+ // NOT the buyer's name, email or address — those are PII (D1).
302
+ search: {
303
+ placeholder: "Search by product, store or tracking number…",
304
+ mode: "partial",
305
+ fields: ["productTitle", "storeName", "trackingNumber"],
306
+ commit: "debounce",
307
+ },
301
308
  emptyLabel: "No orders yet",
302
309
  filterKeys: ["status"],
303
310
  defaultSort: DEFAULT_SORT,
@@ -1,30 +1,16 @@
1
+ /**
2
+ * Row-shaping helpers for the seller listing views.
3
+ *
4
+ * The `useSellerListingData` hook that used to live here was deleted: it was
5
+ * a second listing-fetch engine beside `DataListingView`/`useAdminListing`,
6
+ * with its own q/sorts/filters handling, and it had ZERO call sites. Two
7
+ * engines for one job is what this whole investigation was about — the dead
8
+ * one is what the next session copies from.
9
+ *
10
+ * The four helpers below are NOT dead: six seller views import them.
11
+ */
1
12
  import type { JsonValue } from "@mohasinac/appkit/client";
2
13
  type UnknownRecord = Record<string, JsonValue>;
3
- interface UseSellerListingDataOptions<TResponse, TRow extends {
4
- id: string;
5
- }> {
6
- queryKey: readonly unknown[];
7
- endpoint: string;
8
- page?: number;
9
- pageSize?: number;
10
- sorts?: string;
11
- filters?: string;
12
- q?: string;
13
- mapRows: (response: TResponse) => TRow[];
14
- getTotal?: (response: TResponse, rows: TRow[]) => number;
15
- }
16
- export interface UseSellerListingDataResult<TRow extends {
17
- id: string;
18
- }> {
19
- rows: TRow[];
20
- total: number;
21
- isLoading: boolean;
22
- errorMessage?: string;
23
- refetch: () => void;
24
- }
25
- export declare function useSellerListingData<TResponse, TRow extends {
26
- id: string;
27
- }>({ queryKey, endpoint, page, pageSize, sorts, filters, q, mapRows, getTotal, }: UseSellerListingDataOptions<TResponse, TRow>): UseSellerListingDataResult<TRow>;
28
14
  export declare function toRecordArray(value: unknown): UnknownRecord[];
29
15
  export declare function toStringValue(value: unknown, fallback?: string): string;
30
16
  export declare function toCurrency(value: unknown): string;
@@ -1,43 +1,5 @@
1
1
  "use client";
2
- import { useQuery } from "@tanstack/react-query";
3
- import { apiClient, ApiClientError } from "../../../http";
4
2
  import { formatCurrency } from "../../../utils/number.formatter";
5
- function withQueryParams(endpoint, params) {
6
- const hasQuery = endpoint.includes("?");
7
- const query = new URLSearchParams(params).toString();
8
- return `${endpoint}${hasQuery ? "&" : "?"}${query}`;
9
- }
10
- export function useSellerListingData({ queryKey, endpoint, page = 1, pageSize = 25, sorts = "-createdAt", filters = "", q, mapRows, getTotal, }) {
11
- const params = {
12
- page: String(page),
13
- pageSize: String(pageSize),
14
- sorts,
15
- };
16
- if (filters)
17
- params.filters = filters;
18
- if (q)
19
- params.q = q;
20
- const query = useQuery({
21
- queryKey: [...queryKey, page, pageSize, sorts, filters, q ?? ""],
22
- queryFn: () => apiClient.get(withQueryParams(endpoint, params)),
23
- staleTime: 60000,
24
- });
25
- const rows = query.data ? mapRows(query.data) : [];
26
- const total = query.data
27
- ? (getTotal?.(query.data, rows) ?? rows.length)
28
- : rows.length;
29
- return {
30
- rows,
31
- total,
32
- isLoading: query.isLoading,
33
- errorMessage: query.error instanceof ApiClientError
34
- ? query.error.message
35
- : query.error
36
- ? "Unable to load records"
37
- : undefined,
38
- refetch: query.refetch,
39
- };
40
- }
41
3
  export function toRecordArray(value) {
42
4
  return Array.isArray(value) ? value.filter(Boolean) : [];
43
5
  }
@@ -5,7 +5,6 @@
5
5
  */
6
6
  export * from "./actions";
7
7
  export { StoreRepository, storeRepository, } from "./repository/store.repository";
8
- export { GET as storesGET, GET } from "./api/route";
9
8
  export { GET as storeSlugGET } from "./api/[storeSlug]/route";
10
9
  export { GET as storeProductsGET } from "./api/[storeSlug]/products/route";
11
10
  export { GET as storeAuctionsGET } from "./api/[storeSlug]/auctions/route";
@@ -7,7 +7,6 @@ export * from "./actions";
7
7
  export { StoreRepository, storeRepository, } from "./repository/store.repository";
8
8
  // SB-UNI-A 2026-05-13 — storeAddressRepository deleted. Use addressesRepository
9
9
  // (top-level addresses collection with ownerType:"store").
10
- export { GET as storesGET, GET } from "./api/route";
11
10
  export { GET as storeSlugGET } from "./api/[storeSlug]/route";
12
11
  export { GET as storeProductsGET } from "./api/[storeSlug]/products/route";
13
12
  export { GET as storeAuctionsGET } from "./api/[storeSlug]/auctions/route";
package/dist/index.d.ts CHANGED
@@ -316,6 +316,8 @@ export type { PasswordStrength } from "./validation/index";
316
316
  export type { ZodSetupProps } from "./validation/index";
317
317
  export { ApiError } from "./errors/index";
318
318
  export { AppError } from "./errors/index";
319
+ export { withDegraded, SORT_DROPPED_FOR_EXACT_SEARCH } from "./errors/index";
320
+ export type { DegradedNotice } from "./errors/index";
319
321
  export { AuthenticationError } from "./errors/index";
320
322
  export { AuthorizationError } from "./errors/index";
321
323
  export { DatabaseError } from "./errors/index";
@@ -1866,7 +1868,6 @@ export { createEvent } from "./features/events/server";
1866
1868
  export { deleteEvent } from "./features/events/server";
1867
1869
  export { enterEvent } from "./features/events/server";
1868
1870
  export { eventIdGET } from "./features/events/server";
1869
- export { eventsGET } from "./features/events/server";
1870
1871
  export { getEventLeaderboard } from "./features/events/server";
1871
1872
  export { getEventPollResults } from "./features/events/server";
1872
1873
  export { getEventSpinResults } from "./features/events/server";
@@ -1914,8 +1915,6 @@ export { faqStatsSchema } from "./features/faq/index";
1914
1915
  export { getHelpfulnessPercentage } from "./features/faq/index";
1915
1916
  export { isPopularFAQ } from "./features/faq/index";
1916
1917
  export { slugifyQuestion } from "./features/faq/index";
1917
- export { useFAQ } from "./features/faq/index";
1918
- export { useFAQs } from "./features/faq/index";
1919
1918
  export { useFaqList } from "./features/faq/index";
1920
1919
  export { useFaqVote } from "./features/faq/index";
1921
1920
  export { usesVariableInterpolation } from "./features/faq/index";
@@ -1940,7 +1939,6 @@ export type { VoteFaqResult } from "./features/faq/index";
1940
1939
  export { createFaq } from "./features/faq/server";
1941
1940
  export { deleteFaq } from "./features/faq/server";
1942
1941
  export { faqCreateSchema } from "./features/faq/server";
1943
- export { faqGET } from "./features/faq/server";
1944
1942
  export { faqUpdateSchema } from "./features/faq/server";
1945
1943
  export { getFaqById } from "./features/faq/server";
1946
1944
  export { listFaqs } from "./features/faq/server";
@@ -2676,7 +2674,6 @@ export { listReviewsBySeller } from "./features/reviews/server";
2676
2674
  export { reviewItemDELETE } from "./features/reviews/server";
2677
2675
  export { reviewItemGET } from "./features/reviews/server";
2678
2676
  export { reviewItemPATCH } from "./features/reviews/server";
2679
- export { reviewsGET } from "./features/reviews/server";
2680
2677
  export { updateReview } from "./features/reviews/server";
2681
2678
  export { voteReviewHelpful } from "./features/reviews/server";
2682
2679
  export type { CreateReviewActionInput } from "./features/reviews/server";
@@ -2995,7 +2992,6 @@ export { storeAuctionsGET } from "./features/stores/server";
2995
2992
  export { storeProductsGET } from "./features/stores/server";
2996
2993
  export { storeReviewsGET } from "./features/stores/server";
2997
2994
  export { storeSlugGET } from "./features/stores/server";
2998
- export { storesGET } from "./features/stores/server";
2999
2995
  export { updateStoreAddressForSeller } from "./features/stores/server";
3000
2996
  export type { StoreContentParams } from "./features/stores/server";
3001
2997
  export type { StoreQueryListParams } from "./features/stores/server";
@@ -3131,7 +3127,6 @@ export type { UseUrlTableOptions } from "./react/index";
3131
3127
  export { SUCCESS_MESSAGES } from "./values/index";
3132
3128
  export { splitCartIntoOrderGroups } from "./features/orders/index";
3133
3129
  export { groupOrderItemsByLine, type LineOrderGroup, type OrderItemForLineGrouping, } from "./features/orders/index";
3134
- export { buildSieveFilters } from "./utils/filter.helper";
3135
3130
  export { formatCurrency, formatFileSize } from "./utils/number.formatter";
3136
3131
  export { formatMonthYear } from "./utils/date.formatter";
3137
3132
  export { generateMediaFilename } from "./utils/id-generators";
package/dist/index.js CHANGED
@@ -526,6 +526,9 @@ export { ApiError } from "./errors/index";
526
526
  // [UTIL]-Pure utility â€" no framework or runtime dependency; safe to import from any environment.
527
527
  // AppError - Model for app error.
528
528
  export { AppError } from "./errors/index";
529
+ // withDegraded / DegradedNotice / SORT_DROPPED_FOR_EXACT_SEARCH — a response
530
+ // that is honest about a compromise the handler made deliberately.
531
+ export { withDegraded, SORT_DROPPED_FOR_EXACT_SEARCH } from "./errors/index";
529
532
  // [UTIL]-Pure utility â€" no framework or runtime dependency; safe to import from any environment.
530
533
  // AuthenticationError - Model for authentication error.
531
534
  export { AuthenticationError } from "./errors/index";
@@ -3481,8 +3484,6 @@ export { enterEvent } from "./features/events/server";
3481
3484
  // eventIdGET - Shared export for event id get.
3482
3485
  export { eventIdGET } from "./features/events/server";
3483
3486
  // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
3484
- // eventsGET - Shared export for events get.
3485
- export { eventsGET } from "./features/events/server";
3486
3487
  // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
3487
3488
  // getEventLeaderboard - Helper for get event leaderboard.
3488
3489
  export { getEventLeaderboard } from "./features/events/server";
@@ -3602,11 +3603,7 @@ export { isPopularFAQ } from "./features/faq/index";
3602
3603
  // slugifyQuestion - Shared export for slugify question.
3603
3604
  export { slugifyQuestion } from "./features/faq/index";
3604
3605
  // [CLIENT-SSR]-Runs in both SSR and browser â€" React component or hook that does not depend on browser-only APIs.
3605
- // useFAQ - React hook for use faq.
3606
- export { useFAQ } from "./features/faq/index";
3607
3606
  // [CLIENT-SSR]-Runs in both SSR and browser â€" React component or hook that does not depend on browser-only APIs.
3608
- // useFAQs - React hook for use faqs.
3609
- export { useFAQs } from "./features/faq/index";
3610
3607
  // [CLIENT-SSR]-Runs in both SSR and browser â€" React component or hook that does not depend on browser-only APIs.
3611
3608
  // useFaqList - React hook for use faq list.
3612
3609
  export { useFaqList } from "./features/faq/index";
@@ -3630,8 +3627,6 @@ export { deleteFaq } from "./features/faq/server";
3630
3627
  // faqCreateSchema - Model for faq create schema.
3631
3628
  export { faqCreateSchema } from "./features/faq/server";
3632
3629
  // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
3633
- // faqGET - Shared export for faq get.
3634
- export { faqGET } from "./features/faq/server";
3635
3630
  // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
3636
3631
  // faqUpdateSchema - Model for faq update schema.
3637
3632
  export { faqUpdateSchema } from "./features/faq/server";
@@ -4828,8 +4823,6 @@ export { reviewItemGET } from "./features/reviews/server";
4828
4823
  // reviewItemPATCH - Shared export for review item patch.
4829
4824
  export { reviewItemPATCH } from "./features/reviews/server";
4830
4825
  // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
4831
- // reviewsGET - Shared export for reviews get.
4832
- export { reviewsGET } from "./features/reviews/server";
4833
4826
  // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
4834
4827
  // updateReview - Helper for update review.
4835
4828
  export { updateReview } from "./features/reviews/server";
@@ -5349,8 +5342,6 @@ export { storeReviewsGET } from "./features/stores/server";
5349
5342
  // storeSlugGET - Shared export for store slug get.
5350
5343
  export { storeSlugGET } from "./features/stores/server";
5351
5344
  // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
5352
- // storesGET - Shared export for stores get.
5353
- export { storesGET } from "./features/stores/server";
5354
5345
  // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
5355
5346
  // updateStoreAddressForSeller - Helper for update store address for seller.
5356
5347
  export { updateStoreAddressForSeller } from "./features/stores/server";
@@ -5540,7 +5531,6 @@ export { splitCartIntoOrderGroups } from "./features/orders/index";
5540
5531
  // S-SBUNI-5 2026-05-13 â€" bundle-aware order item grouping for receipts.
5541
5532
  export { groupOrderItemsByLine, } from "./features/orders/index";
5542
5533
  // -- Missing utils
5543
- export { buildSieveFilters } from "./utils/filter.helper";
5544
5534
  export { formatCurrency, formatFileSize } from "./utils/number.formatter";
5545
5535
  export { formatMonthYear } from "./utils/date.formatter";
5546
5536
  export { generateMediaFilename } from "./utils/id-generators"; // generateProductImageFilename already exported from "./utils/id-generators";
@@ -63,23 +63,19 @@ export class FirebaseRepository {
63
63
  q = q.orderBy(sortField, sortDir);
64
64
  }
65
65
  // -- Basic Sieve filter parsing --------------------------------------------
66
- // Supports: ==, !=, <, <=, >, >=, @= (array-contains), @=* (prefix/starts-with)
66
+ // Supports: ==, !=, <, <=, >, >=, @= (array-contains).
67
+ //
68
+ // The `@=*` prefix arm was DELETED. It built a >= / <= range against a
69
+ //  sentinel, which is a real prefix match — but only over a field
70
+ // stored verbatim and case-sensitively, so it never matched what callers
71
+ // used it for, and pairing an inequality with an unrelated orderBy demanded
72
+ // an index nobody declared. `searchTxt` + `array-contains` replaces it.
67
73
  if (query?.filters) {
68
74
  const clauses = query.filters
69
75
  .split(",")
70
76
  .map((s) => s.trim())
71
77
  .filter(Boolean);
72
78
  for (const clause of clauses) {
73
- // Try @=* (string prefix) before the generic @= match
74
- const prefixMatch = clause.match(/^([^<>=!@]+)\s*@=\*\s*(.+)$/);
75
- if (prefixMatch) {
76
- const field = prefixMatch[1].trim();
77
- const prefix = prefixMatch[2].trim();
78
- q = q
79
- .where(field, ">=", prefix)
80
- .where(field, "<=", prefix + "");
81
- continue;
82
- }
83
79
  const match = clause.match(/^([^<>=!@]+)\s*(==|!=|<=|>=|<|>|@=)\s*(.+)$/);
84
80
  if (!match)
85
81
  continue;
@@ -3281,11 +3281,11 @@ export declare const SCHEMAS: {
3281
3281
  handle: import("zod").ZodString;
3282
3282
  url: import("zod").ZodOptional<import("zod").ZodString>;
3283
3283
  }, "strip", import("zod").ZodTypeAny, {
3284
- platform: "other" | "whatsapp" | "youtube" | "instagram" | "facebook" | "twitter" | "linkedin" | "telegram" | "olx";
3284
+ platform: "other" | "whatsapp" | "youtube" | "instagram" | "facebook" | "telegram" | "twitter" | "olx" | "linkedin";
3285
3285
  handle: string;
3286
3286
  url?: string | undefined;
3287
3287
  }, {
3288
- platform: "other" | "whatsapp" | "youtube" | "instagram" | "facebook" | "twitter" | "linkedin" | "telegram" | "olx";
3288
+ platform: "other" | "whatsapp" | "youtube" | "instagram" | "facebook" | "telegram" | "twitter" | "olx" | "linkedin";
3289
3289
  handle: string;
3290
3290
  url?: string | undefined;
3291
3291
  }>, "many">;
@@ -3330,7 +3330,7 @@ export declare const SCHEMAS: {
3330
3330
  scamType: string;
3331
3331
  reportedBy: string;
3332
3332
  reportedByAnon: boolean;
3333
- scamPlatform: "other" | "whatsapp" | "letitrip" | "instagram" | "facebook" | "twitter" | "telegram" | "olx" | "facebook_marketplace" | "in_person" | "phone_call";
3333
+ scamPlatform: "other" | "whatsapp" | "letitrip" | "instagram" | "facebook" | "telegram" | "twitter" | "olx" | "facebook_marketplace" | "in_person" | "phone_call";
3334
3334
  evidence: string[];
3335
3335
  phones: string[];
3336
3336
  upiIds: string[];
@@ -3339,7 +3339,7 @@ export declare const SCHEMAS: {
3339
3339
  incidentCount: number;
3340
3340
  seoSlug: string;
3341
3341
  socialMedia: {
3342
- platform: "other" | "whatsapp" | "youtube" | "instagram" | "facebook" | "twitter" | "linkedin" | "telegram" | "olx";
3342
+ platform: "other" | "whatsapp" | "youtube" | "instagram" | "facebook" | "telegram" | "twitter" | "olx" | "linkedin";
3343
3343
  handle: string;
3344
3344
  url?: string | undefined;
3345
3345
  }[];
@@ -3370,7 +3370,7 @@ export declare const SCHEMAS: {
3370
3370
  scamType: string;
3371
3371
  reportedBy: string;
3372
3372
  reportedByAnon: boolean;
3373
- scamPlatform: "other" | "whatsapp" | "letitrip" | "instagram" | "facebook" | "twitter" | "telegram" | "olx" | "facebook_marketplace" | "in_person" | "phone_call";
3373
+ scamPlatform: "other" | "whatsapp" | "letitrip" | "instagram" | "facebook" | "telegram" | "twitter" | "olx" | "facebook_marketplace" | "in_person" | "phone_call";
3374
3374
  evidence: string[];
3375
3375
  phones: string[];
3376
3376
  upiIds: string[];
@@ -3379,7 +3379,7 @@ export declare const SCHEMAS: {
3379
3379
  incidentCount: number;
3380
3380
  seoSlug: string;
3381
3381
  socialMedia: {
3382
- platform: "other" | "whatsapp" | "youtube" | "instagram" | "facebook" | "twitter" | "linkedin" | "telegram" | "olx";
3382
+ platform: "other" | "whatsapp" | "youtube" | "instagram" | "facebook" | "telegram" | "twitter" | "olx" | "linkedin";
3383
3383
  handle: string;
3384
3384
  url?: string | undefined;
3385
3385
  }[];
@@ -3438,7 +3438,7 @@ export declare const SCHEMAS: {
3438
3438
  reportedBy: string;
3439
3439
  scammerId: string;
3440
3440
  reportedByAnon: boolean;
3441
- scamPlatform: "other" | "whatsapp" | "letitrip" | "instagram" | "facebook" | "twitter" | "telegram" | "olx" | "facebook_marketplace" | "in_person" | "phone_call";
3441
+ scamPlatform: "other" | "whatsapp" | "letitrip" | "instagram" | "facebook" | "telegram" | "twitter" | "olx" | "facebook_marketplace" | "in_person" | "phone_call";
3442
3442
  evidence: string[];
3443
3443
  verifiedBy?: string | undefined;
3444
3444
  amountLost?: number | undefined;
@@ -3461,7 +3461,7 @@ export declare const SCHEMAS: {
3461
3461
  reportedBy: string;
3462
3462
  scammerId: string;
3463
3463
  reportedByAnon: boolean;
3464
- scamPlatform: "other" | "whatsapp" | "letitrip" | "instagram" | "facebook" | "twitter" | "telegram" | "olx" | "facebook_marketplace" | "in_person" | "phone_call";
3464
+ scamPlatform: "other" | "whatsapp" | "letitrip" | "instagram" | "facebook" | "telegram" | "twitter" | "olx" | "facebook_marketplace" | "in_person" | "phone_call";
3465
3465
  evidence: string[];
3466
3466
  verifiedBy?: string | undefined;
3467
3467
  amountLost?: number | undefined;
@@ -4,7 +4,7 @@ export type { RateLimitConfig, RateLimitResult } from "./rate-limit";
4
4
  export { requireAuth, requireRole, requireOwnership, requireEmailVerified, requireActiveAccount, canChangeRole, getRoleLevel, } from "./authorization";
5
5
  export type { UserRole } from "./authorization";
6
6
  export { redactPii, safeDisplayName, safeDisplayEmail, maskIp } from "./pii-redact";
7
- export { encryptValue, decryptValue, hmacBlindIndex, encryptPiiFields, decryptPiiFields, encryptPii, decryptPii, piiBlindIndex, piiIndicesFor, getPiiConfigError, encryptShippingAddress, decryptShippingAddress, encryptPayoutDetails, decryptPayoutDetails, encryptShippingConfig, decryptShippingConfig, encryptPayoutBankAccount, decryptPayoutBankAccount, } from "./pii-encrypt";
7
+ export { encryptValue, decryptValue, hmacBlindIndex, encryptPiiFields, decryptPiiFields, encryptPii, decryptPii, piiBlindIndex, piiIndicesFor, getPiiConfigError, encryptPayoutDetails, decryptPayoutDetails, encryptShippingConfig, decryptShippingConfig, encryptPayoutBankAccount, decryptPayoutBankAccount, } from "./pii-encrypt";
8
8
  export { isPiiEncrypted, maskName, maskEmail, maskPublicReview, maskPublicBid, maskPublicEventEntry, maskOfferForSeller, ENC_PREFIX, HMAC_PREFIX, } from "./pii-mask";
9
9
  export { USER_PII_FIELDS, USER_PII_INDEX_MAP, ADDRESS_PII_FIELDS, ORDER_PII_FIELDS, PAYOUT_PII_FIELDS, PAYOUT_PII_INDEX_MAP, BID_PII_FIELDS, TOKEN_PII_FIELDS, TOKEN_PII_INDEX_MAP, REVIEW_PII_FIELDS, REVIEW_PII_INDEX_MAP, OFFER_PII_FIELDS, CHAT_PII_FIELDS, EVENT_ENTRY_PII_FIELDS, LOTTERY_ENTRY_PII_FIELDS, PAYMENT_METHOD_PII_FIELDS, } from "./pii-schemas";
10
10
  export { encryptSecret, decryptSecret, isSecretEncrypted, maskSecret, } from "./settings-encryption";
@@ -2,7 +2,7 @@ export { generateNonce, buildCSP } from "./csp";
2
2
  export { rateLimit, applyRateLimit, rateLimitByIdentifier, RateLimitPresets, clearRateLimitStore, getClientIP, hashGuestIdentity, } from "./rate-limit";
3
3
  export { requireAuth, requireRole, requireOwnership, requireEmailVerified, requireActiveAccount, canChangeRole, getRoleLevel, } from "./authorization";
4
4
  export { redactPii, safeDisplayName, safeDisplayEmail, maskIp } from "./pii-redact";
5
- export { encryptValue, decryptValue, hmacBlindIndex, encryptPiiFields, decryptPiiFields, encryptPii, decryptPii, piiBlindIndex, piiIndicesFor, getPiiConfigError, encryptShippingAddress, decryptShippingAddress, encryptPayoutDetails, decryptPayoutDetails, encryptShippingConfig, decryptShippingConfig, encryptPayoutBankAccount, decryptPayoutBankAccount, } from "./pii-encrypt";
5
+ export { encryptValue, decryptValue, hmacBlindIndex, encryptPiiFields, decryptPiiFields, encryptPii, decryptPii, piiBlindIndex, piiIndicesFor, getPiiConfigError, encryptPayoutDetails, decryptPayoutDetails, encryptShippingConfig, decryptShippingConfig, encryptPayoutBankAccount, decryptPayoutBankAccount, } from "./pii-encrypt";
6
6
  // Crypto-free display-masking helpers -- sourced from pii-mask.ts (not
7
7
  // pii-encrypt.ts) so this barrel stays safe to re-export from the
8
8
  // universal client+server index.ts. See pii-mask.ts's header comment.
@@ -54,16 +54,6 @@ export declare function piiBlindIndex(plaintext: string): string;
54
54
  * @param source plaintext document — hashing ciphertext produces a useless index
55
55
  */
56
56
  export declare function piiIndicesFor(source: object, mapping: Record<string, string>): Record<string, string>;
57
- /**
58
- * Encrypt PII inside a shipping address stored in an order.
59
- * Supports string and object address shapes.
60
- */
61
- export declare function encryptShippingAddress<T>(addr: T | undefined | null): T | undefined | null;
62
- /**
63
- * Decrypt PII inside a shipping address read from an order.
64
- * Supports string and object address shapes.
65
- */
66
- export declare function decryptShippingAddress<T>(addr: T | undefined | null): T | undefined | null;
67
57
  /**
68
58
  * Encrypt PII inside seller payoutDetails before writing to Firestore.
69
59
  */
@@ -352,44 +352,6 @@ export function piiIndicesFor(source, mapping) {
352
352
  return indices;
353
353
  }
354
354
  // --- Nested-object PII helpers ----------------------------------------------
355
- /**
356
- * Encrypt PII inside a shipping address stored in an order.
357
- * Supports string and object address shapes.
358
- */
359
- export function encryptShippingAddress(addr) {
360
- if (!addr)
361
- return addr;
362
- if (typeof addr === "string") {
363
- return encryptPii(addr);
364
- }
365
- if (typeof addr !== "object")
366
- return addr;
367
- return encryptPiiFields(addr, [
368
- "fullName",
369
- "phone",
370
- "addressLine1",
371
- "addressLine2",
372
- ]);
373
- }
374
- /**
375
- * Decrypt PII inside a shipping address read from an order.
376
- * Supports string and object address shapes.
377
- */
378
- export function decryptShippingAddress(addr) {
379
- if (!addr)
380
- return addr;
381
- if (typeof addr === "string") {
382
- return decryptPii(addr);
383
- }
384
- if (typeof addr !== "object")
385
- return addr;
386
- return decryptPiiFields(addr, [
387
- "fullName",
388
- "phone",
389
- "addressLine1",
390
- "addressLine2",
391
- ]);
392
- }
393
355
  /**
394
356
  * Encrypt PII inside seller payoutDetails before writing to Firestore.
395
357
  */
@@ -1,4 +1,5 @@
1
1
  import type { StoreDocument } from "../../features/stores/schemas/firestore";
2
+ import type { ScammerDocument } from "../../features/scams/schemas/firestore";
2
3
  import type { EventDocument } from "../../features/events/schemas/firestore";
3
4
  import type { BlogPostDocument } from "../../features/blog/schemas/firestore";
4
5
  import type { ReviewDocument } from "../../features/reviews/schemas/firestore";
@@ -12,3 +13,4 @@ export declare function withReviewSearchTxt<T extends Partial<ReviewDocument>>(p
12
13
  export declare function withOrderSearchTxt<T extends Partial<OrderDocument>>(p: T): T;
13
14
  export declare function withCouponSearchTxt<T extends Partial<CouponDocument>>(p: T): T;
14
15
  export declare function withOfferSearchTxt<T extends Partial<OfferDocument>>(p: T): T;
16
+ export declare function withScammerSearchTxt<T extends Partial<ScammerDocument>>(p: T): T;
@@ -1,4 +1,4 @@
1
- import { buildStoreSearchTxt, buildEventSearchTxt, buildBlogSearchTxt, buildReviewSearchTxt, buildOrderSearchTxt, buildCouponSearchTxt, buildOfferSearchTxt, } from "../../utils/search-txt-builders";
1
+ import { buildStoreSearchTxt, buildEventSearchTxt, buildBlogSearchTxt, buildReviewSearchTxt, buildOrderSearchTxt, buildCouponSearchTxt, buildOfferSearchTxt, buildScammerSearchTxt, } from "../../utils/search-txt-builders";
2
2
  export function withStoreSearchTxt(p) {
3
3
  return { ...p, searchTxt: buildStoreSearchTxt(p) };
4
4
  }
@@ -20,3 +20,6 @@ export function withCouponSearchTxt(p) {
20
20
  export function withOfferSearchTxt(p) {
21
21
  return { ...p, searchTxt: buildOfferSearchTxt(p) };
22
22
  }
23
+ export function withScammerSearchTxt(p) {
24
+ return { ...p, searchTxt: buildScammerSearchTxt(p) };
25
+ }
@@ -17,6 +17,7 @@
17
17
  * @tag consumers:seed/index.ts,seed/runner.ts
18
18
  * @tag sideEffects:none
19
19
  */
20
+ import { withScammerSearchTxt } from "./_helpers/search-txt-wrappers";
20
21
  import { SCAMMER_FIELDS } from "../constants/field-names";
21
22
  import { seedExtMedia } from "./_helpers/media";
22
23
  const NOW = new Date("2026-05-10T00:00:00.000Z");
@@ -32,7 +33,12 @@ const daysAgo = (n) => new Date(NOW.getTime() - n * 86400000);
32
33
  function entry(at, actorRole, trigger, changes, extra) {
33
34
  return { at, actorRole, trigger, changes, ...extra };
34
35
  }
35
- export const scammersSeedData = [
36
+ // Annotated HERE, not on the export, so the literal is contextually typed as
37
+ // Partial<ScammerDocument> before `.map` sees it. Without this TS infers a
38
+ // union of the individual object shapes and rejects the wrapper's generic —
39
+ // and the error points at the map call rather than at the field that actually
40
+ // diverged.
41
+ const scammerRows = [
36
42
  // ── 1. Verified — advance payment ghost ──────────────────────────────────────
37
43
  {
38
44
  id: "scammer-fake-lob-seller",
@@ -224,3 +230,6 @@ export const scammersSeedData = [
224
230
  updatedAt: daysAgo(9),
225
231
  },
226
232
  ];
233
+ // Derived through the wrapper, never per record — an inline literal is how
234
+ // five product seed files shipped their last fixture with no tokens.
235
+ export const scammersSeedData = scammerRows.map(withScammerSearchTxt);
package/dist/server.d.ts CHANGED
@@ -274,7 +274,6 @@ export { createEvent } from "./features/events/server";
274
274
  export { deleteEvent } from "./features/events/server";
275
275
  export { enterEvent } from "./features/events/server";
276
276
  export { eventIdGET } from "./features/events/server";
277
- export { eventsGET } from "./features/events/server";
278
277
  export { getEventLeaderboard } from "./features/events/server";
279
278
  export { getEventPollResults } from "./features/events/server";
280
279
  export type { PollResultEntry, SpinResultEntry } from "./features/events/index";
@@ -292,7 +291,6 @@ export { applyRefundDeductionAction, type ApplyRefundDeductionInput, type ApplyR
292
291
  export { createFaq } from "./features/faq/server";
293
292
  export { deleteFaq } from "./features/faq/server";
294
293
  export { faqCreateSchema } from "./features/faq/server";
295
- export { faqGET } from "./features/faq/server";
296
294
  export { faqUpdateSchema } from "./features/faq/server";
297
295
  export { getFaqById } from "./features/faq/server";
298
296
  export { listFaqs } from "./features/faq/server";
@@ -380,7 +378,6 @@ export { listReviewsBySeller } from "./features/reviews/server";
380
378
  export { reviewItemDELETE } from "./features/reviews/server";
381
379
  export { reviewItemGET } from "./features/reviews/server";
382
380
  export { reviewItemPATCH } from "./features/reviews/server";
383
- export { reviewsGET } from "./features/reviews/server";
384
381
  export { updateReview } from "./features/reviews/server";
385
382
  export { voteReviewHelpful } from "./features/reviews/server";
386
383
  export { searchGET } from "./features/search/server";
@@ -426,7 +423,6 @@ export { storeAuctionsGET } from "./features/stores/server";
426
423
  export { storeProductsGET } from "./features/stores/server";
427
424
  export { storeReviewsGET } from "./features/stores/server";
428
425
  export { storeSlugGET } from "./features/stores/server";
429
- export { storesGET } from "./features/stores/server";
430
426
  export { updateStoreAddressForSeller } from "./features/stores/server";
431
427
  export { buildCheckoutMessageURL } from "./features/whatsapp-bot/server";
432
428
  export { buildStatusMessage } from "./features/whatsapp-bot/server";
@@ -466,8 +462,6 @@ export { piiIndicesFor } from "./security/index";
466
462
  export { reserveUserSlug, userSlugBase, USER_SLUGS_COLLECTION } from "./features/auth/actions/user-slug";
467
463
  export { resolveProfileUser } from "./features/auth/actions/profile-actions";
468
464
  export { getPiiConfigError } from "./security/index";
469
- export { encryptShippingAddress } from "./security/index";
470
- export { decryptShippingAddress } from "./security/index";
471
465
  export { encryptPayoutDetails } from "./security/index";
472
466
  export { decryptPayoutDetails } from "./security/index";
473
467
  export { encryptShippingConfig } from "./security/index";
package/dist/server.js CHANGED
@@ -776,8 +776,6 @@ export { enterEvent } from "./features/events/server";
776
776
  // eventIdGET - Shared export for event id get.
777
777
  export { eventIdGET } from "./features/events/server";
778
778
  // [SERVER-ONLY]-Server-only — uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
779
- // eventsGET - Shared export for events get.
780
- export { eventsGET } from "./features/events/server";
781
779
  // [SERVER-ONLY]-Server-only — uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
782
780
  // getEventLeaderboard - Helper for get event leaderboard.
783
781
  export { getEventLeaderboard } from "./features/events/server";
@@ -820,8 +818,6 @@ export { deleteFaq } from "./features/faq/server";
820
818
  // faqCreateSchema - Model for faq create schema.
821
819
  export { faqCreateSchema } from "./features/faq/server";
822
820
  // [SERVER-ONLY]-Server-only — uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
823
- // faqGET - Shared export for faq get.
824
- export { faqGET } from "./features/faq/server";
825
821
  // [SERVER-ONLY]-Server-only — uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
826
822
  // faqUpdateSchema - Model for faq update schema.
827
823
  export { faqUpdateSchema } from "./features/faq/server";
@@ -1082,8 +1078,6 @@ export { reviewItemGET } from "./features/reviews/server";
1082
1078
  // reviewItemPATCH - Shared export for review item patch.
1083
1079
  export { reviewItemPATCH } from "./features/reviews/server";
1084
1080
  // [SERVER-ONLY]-Server-only — uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
1085
- // reviewsGET - Shared export for reviews get.
1086
- export { reviewsGET } from "./features/reviews/server";
1087
1081
  // [SERVER-ONLY]-Server-only — uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
1088
1082
  // updateReview - Helper for update review.
1089
1083
  export { updateReview } from "./features/reviews/server";
@@ -1221,8 +1215,6 @@ export { storeReviewsGET } from "./features/stores/server";
1221
1215
  // storeSlugGET - Shared export for store slug get.
1222
1216
  export { storeSlugGET } from "./features/stores/server";
1223
1217
  // [SERVER-ONLY]-Server-only — uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
1224
- // storesGET - Shared export for stores get.
1225
- export { storesGET } from "./features/stores/server";
1226
1218
  // [SERVER-ONLY]-Server-only — uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
1227
1219
  // updateStoreAddressForSeller - Helper for update store address for seller.
1228
1220
  export { updateStoreAddressForSeller } from "./features/stores/server";
@@ -1298,8 +1290,6 @@ export { piiIndicesFor } from "./security/index";
1298
1290
  export { reserveUserSlug, userSlugBase, USER_SLUGS_COLLECTION } from "./features/auth/actions/user-slug";
1299
1291
  export { resolveProfileUser } from "./features/auth/actions/profile-actions";
1300
1292
  export { getPiiConfigError } from "./security/index";
1301
- export { encryptShippingAddress } from "./security/index";
1302
- export { decryptShippingAddress } from "./security/index";
1303
1293
  export { encryptPayoutDetails } from "./security/index";
1304
1294
  export { decryptPayoutDetails } from "./security/index";
1305
1295
  export { encryptShippingConfig } from "./security/index";