@mohasinac/appkit 4.30.11 → 4.30.13
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/dist/errors/degraded.d.ts +52 -0
- package/dist/errors/degraded.js +47 -0
- package/dist/errors/index.d.ts +1 -0
- package/dist/errors/index.js +1 -0
- package/dist/features/admin/components/AdminBlogView.js +3 -1
- package/dist/features/admin/components/AdminCouponsView.js +2 -1
- package/dist/features/admin/components/AdminOffersView.js +4 -1
- package/dist/features/events/components/AdminEventsView.js +2 -1
- package/dist/features/events/server.d.ts +0 -1
- package/dist/features/events/server.js +0 -1
- package/dist/features/faq/index.d.ts +0 -1
- package/dist/features/faq/index.js +0 -1
- package/dist/features/faq/server.d.ts +0 -1
- package/dist/features/faq/server.js +0 -1
- package/dist/features/orders/repository/orders.repository.d.ts +3 -1
- package/dist/features/orders/repository/orders.repository.js +18 -3
- package/dist/features/reviews/server.d.ts +0 -1
- package/dist/features/reviews/server.js +0 -1
- package/dist/features/seller/components/SellerCouponsView.js +2 -1
- package/dist/features/seller/components/SellerOffersView.js +3 -1
- package/dist/features/seller/components/SellerOrdersView.js +4 -1
- package/dist/features/seller/hooks/useSellerListingData.d.ts +11 -25
- package/dist/features/seller/hooks/useSellerListingData.js +0 -38
- package/dist/features/stores/server.d.ts +0 -1
- package/dist/features/stores/server.js +0 -1
- package/dist/index.d.ts +2 -7
- package/dist/index.js +3 -13
- package/dist/providers/db-firebase/base.js +7 -11
- package/dist/security/index.d.ts +1 -1
- package/dist/security/index.js +1 -1
- package/dist/security/pii-encrypt.d.ts +0 -10
- package/dist/security/pii-encrypt.js +0 -38
- package/dist/server.d.ts +0 -6
- package/dist/server.js +0 -10
- package/dist/utils/index.d.ts +0 -1
- package/dist/utils/index.js +0 -1
- package/dist/utils/sieve-builder.d.ts +0 -5
- package/dist/utils/sieve-builder.js +7 -8
- package/package.json +1 -1
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Degradation that the caller can SEE.
|
|
3
|
+
*
|
|
4
|
+
* Every bug this search/PII migration surfaced returned HTTP 200 with
|
|
5
|
+
* plausible-looking rows. A dropped Sieve clause, a swallowed
|
|
6
|
+
* FAILED_PRECONDITION, a retry with `q` deleted — none of them errored, and a
|
|
7
|
+
* reader had no way to tell a narrowed list from an unnarrowed one. A
|
|
8
|
+
* `serverLogger.warn` does not help: it goes to the operator, and the person
|
|
9
|
+
* being misled is the user.
|
|
10
|
+
*
|
|
11
|
+
* So when a handler cannot serve exactly what was asked for but chooses to
|
|
12
|
+
* serve something anyway, it must say so ON THE RESPONSE.
|
|
13
|
+
*
|
|
14
|
+
* This is not an error channel. A degraded response is a successful response
|
|
15
|
+
* whose shape is honest about a compromise the handler made deliberately —
|
|
16
|
+
* "I applied your filter but ignored your sort", not "something went wrong".
|
|
17
|
+
* A failure that has no defensible partial answer should still throw.
|
|
18
|
+
*/
|
|
19
|
+
/** One thing the handler could not honour, and why. */
|
|
20
|
+
export interface DegradedNotice {
|
|
21
|
+
/** What was dropped, in the caller's vocabulary: "sorts", "filters.status". */
|
|
22
|
+
dropped: string;
|
|
23
|
+
/**
|
|
24
|
+
* Why, in one sentence a UI can show verbatim. Written for the user, not the
|
|
25
|
+
* operator — "Results are not sorted while searching" beats
|
|
26
|
+
* "FAILED_PRECONDITION: composite index required".
|
|
27
|
+
*/
|
|
28
|
+
reason: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Attach notices to a response payload.
|
|
32
|
+
*
|
|
33
|
+
* Returns the payload UNCHANGED when nothing degraded, so the common path
|
|
34
|
+
* carries no `degraded: false` noise and a client can treat the field's mere
|
|
35
|
+
* presence as the signal.
|
|
36
|
+
*/
|
|
37
|
+
export declare function withDegraded<T extends object>(payload: T, notices: readonly DegradedNotice[]): T | (T & {
|
|
38
|
+
degraded: readonly DegradedNotice[];
|
|
39
|
+
});
|
|
40
|
+
/**
|
|
41
|
+
* The specific compromise three admin search endpoints make.
|
|
42
|
+
*
|
|
43
|
+
* `/api/admin/{users,reviews,payouts}` resolve `q` through an HMAC blind index
|
|
44
|
+
* (`emailIndex==<hash>`) or an exact name match. Firestore needs a composite
|
|
45
|
+
* index for each equality x sort x direction combination, and preserving the
|
|
46
|
+
* caller's sort across all three endpoints was measured at **14** additional
|
|
47
|
+
* indexes — to order a result set that an exact email match bounds at one row.
|
|
48
|
+
*
|
|
49
|
+
* Dropping the sort is therefore the right trade. Dropping it SILENTLY was not:
|
|
50
|
+
* the sort dropdown went on displaying "Oldest" over unsorted rows.
|
|
51
|
+
*/
|
|
52
|
+
export declare const SORT_DROPPED_FOR_EXACT_SEARCH: DegradedNotice;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Degradation that the caller can SEE.
|
|
3
|
+
*
|
|
4
|
+
* Every bug this search/PII migration surfaced returned HTTP 200 with
|
|
5
|
+
* plausible-looking rows. A dropped Sieve clause, a swallowed
|
|
6
|
+
* FAILED_PRECONDITION, a retry with `q` deleted — none of them errored, and a
|
|
7
|
+
* reader had no way to tell a narrowed list from an unnarrowed one. A
|
|
8
|
+
* `serverLogger.warn` does not help: it goes to the operator, and the person
|
|
9
|
+
* being misled is the user.
|
|
10
|
+
*
|
|
11
|
+
* So when a handler cannot serve exactly what was asked for but chooses to
|
|
12
|
+
* serve something anyway, it must say so ON THE RESPONSE.
|
|
13
|
+
*
|
|
14
|
+
* This is not an error channel. A degraded response is a successful response
|
|
15
|
+
* whose shape is honest about a compromise the handler made deliberately —
|
|
16
|
+
* "I applied your filter but ignored your sort", not "something went wrong".
|
|
17
|
+
* A failure that has no defensible partial answer should still throw.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Attach notices to a response payload.
|
|
21
|
+
*
|
|
22
|
+
* Returns the payload UNCHANGED when nothing degraded, so the common path
|
|
23
|
+
* carries no `degraded: false` noise and a client can treat the field's mere
|
|
24
|
+
* presence as the signal.
|
|
25
|
+
*/
|
|
26
|
+
export function withDegraded(payload, notices) {
|
|
27
|
+
if (notices.length === 0)
|
|
28
|
+
return payload;
|
|
29
|
+
return { ...payload, degraded: notices };
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The specific compromise three admin search endpoints make.
|
|
33
|
+
*
|
|
34
|
+
* `/api/admin/{users,reviews,payouts}` resolve `q` through an HMAC blind index
|
|
35
|
+
* (`emailIndex==<hash>`) or an exact name match. Firestore needs a composite
|
|
36
|
+
* index for each equality x sort x direction combination, and preserving the
|
|
37
|
+
* caller's sort across all three endpoints was measured at **14** additional
|
|
38
|
+
* indexes — to order a result set that an exact email match bounds at one row.
|
|
39
|
+
*
|
|
40
|
+
* Dropping the sort is therefore the right trade. Dropping it SILENTLY was not:
|
|
41
|
+
* the sort dropdown went on displaying "Oldest" over unsorted rows.
|
|
42
|
+
*/
|
|
43
|
+
export const SORT_DROPPED_FOR_EXACT_SEARCH = {
|
|
44
|
+
dropped: "sorts",
|
|
45
|
+
reason: "Results are not sorted while searching — search matches an exact value, " +
|
|
46
|
+
"so ordering is unavailable for this query.",
|
|
47
|
+
};
|
package/dist/errors/index.d.ts
CHANGED
|
@@ -16,3 +16,4 @@ export { ERROR_DISPLAY_MAP, getErrorDisplay, type ErrorDisplayEntry, } from "./e
|
|
|
16
16
|
export { safeRead, installDegradedReadReporter, type DegradedReadReport, } from "./safe-read";
|
|
17
17
|
export { normalizeError, getErrorMessage, isAuthError, isApiNormalized, isAppNormalized, isFirebaseAuthNormalized, isFirebaseFirestoreNormalized, isFirebaseStorageNormalized, isNativeNormalized, isNetworkNormalized, isUnknownNormalized, isZodNormalized, } from "./normalize";
|
|
18
18
|
export type { NormalizedError, NormalizedApiError, NormalizedAppError, NormalizedFirebaseAuthError, NormalizedFirebaseFirestoreError, NormalizedFirebaseStorageError, NormalizedNativeError, NormalizedNetworkError, NormalizedUnknownThrownValue, NormalizedZodError, } from "./normalize";
|
|
19
|
+
export * from "./degraded";
|
package/dist/errors/index.js
CHANGED
|
@@ -25,3 +25,4 @@ export { safeRead, installDegradedReadReporter, } from "./safe-read";
|
|
|
25
25
|
// `isAuthError` here replaces the legacy keyword matcher at
|
|
26
26
|
// `appkit/src/utils/auth-error.ts` (now a thin re-export shim).
|
|
27
27
|
export { normalizeError, getErrorMessage, isAuthError, isApiNormalized, isAppNormalized, isFirebaseAuthNormalized, isFirebaseFirestoreNormalized, isFirebaseStorageNormalized, isNativeNormalized, isNetworkNormalized, isUnknownNormalized, isZodNormalized, } from "./normalize";
|
|
28
|
+
export * from "./degraded";
|
|
@@ -21,7 +21,9 @@ export function AdminBlogView({ children, ...props }) {
|
|
|
21
21
|
const config = {
|
|
22
22
|
portal: "admin",
|
|
23
23
|
title: "Blog Posts",
|
|
24
|
-
//
|
|
24
|
+
// buildBlogSearchTxt indexes title + excerpt + category + tags — NOT the post
|
|
25
|
+
// body, which is not tokenised.
|
|
26
|
+
searchPlaceholder: "Search by title, excerpt, category or tag…",
|
|
25
27
|
emptyLabel: "No blog posts found",
|
|
26
28
|
filterKeys: ["status", "isFeatured"],
|
|
27
29
|
defaultSort: sortBy("publishedAt", "DESC"),
|
|
@@ -52,7 +52,8 @@ export function AdminCouponsView({ children, onBulkArchive, onBulkDelete, ...pro
|
|
|
52
52
|
const config = {
|
|
53
53
|
portal: "admin",
|
|
54
54
|
title: "Coupons",
|
|
55
|
-
//
|
|
55
|
+
// buildCouponSearchTxt indexes code + name + description — nothing else.
|
|
56
|
+
searchPlaceholder: "Search by code, name or description…",
|
|
56
57
|
emptyLabel: "No coupons found",
|
|
57
58
|
filterKeys: ["type", "showExpired"],
|
|
58
59
|
defaultSort: sortBy("createdAt", "DESC"),
|
|
@@ -103,7 +103,10 @@ export function AdminOffersView({ children, ...props }) {
|
|
|
103
103
|
const config = {
|
|
104
104
|
portal: "admin",
|
|
105
105
|
title: "Offers",
|
|
106
|
-
//
|
|
106
|
+
// buildOfferSearchTxt indexes productTitle + productSlug + storeName. It does
|
|
107
|
+
// NOT index buyerName or buyerEmail — those are PII, and the placeholder
|
|
108
|
+
// must not promise a match it will never make.
|
|
109
|
+
searchPlaceholder: "Search by product or store…",
|
|
107
110
|
emptyLabel: "No offers found",
|
|
108
111
|
filterKeys: ["status"],
|
|
109
112
|
defaultSort: sortBy("createdAt", "DESC"),
|
|
@@ -33,7 +33,8 @@ export function AdminEventsView({ children, ...props }) {
|
|
|
33
33
|
const config = {
|
|
34
34
|
portal: "admin",
|
|
35
35
|
title: "Events",
|
|
36
|
-
//
|
|
36
|
+
// buildEventSearchTxt indexes title + description + type + tags.
|
|
37
|
+
searchPlaceholder: "Search by title, description, type or tag…",
|
|
37
38
|
emptyLabel: "No events found",
|
|
38
39
|
filterKeys: ["status", "type"],
|
|
39
40
|
defaultSort: sortBy("startsAt", "DESC"),
|
|
@@ -6,5 +6,4 @@
|
|
|
6
6
|
export * from "./actions";
|
|
7
7
|
export { EventRepository, EventsRepository, eventRepository, } from "./repository/events.repository";
|
|
8
8
|
export { EventEntryRepository, EventEntriesRepository, eventEntryRepository, } from "./repository/event-entry.repository";
|
|
9
|
-
export { GET as eventsGET, GET } from "./api/route";
|
|
10
9
|
export { GET as eventIdGET } from "./api/[id]/route";
|
|
@@ -6,5 +6,4 @@
|
|
|
6
6
|
export * from "./actions";
|
|
7
7
|
export { EventRepository, EventsRepository, eventRepository, } from "./repository/events.repository";
|
|
8
8
|
export { EventEntryRepository, EventEntriesRepository, eventEntryRepository, } from "./repository/event-entry.repository";
|
|
9
|
-
export { GET as eventsGET, GET } from "./api/route";
|
|
10
9
|
export { GET as eventIdGET } from "./api/[id]/route";
|
|
@@ -151,7 +151,9 @@ declare class OrderRepository extends BaseRepository<OrderDocument> {
|
|
|
151
151
|
canSort: boolean;
|
|
152
152
|
};
|
|
153
153
|
};
|
|
154
|
-
listForSeller(productIds: string[], model: SieveModel
|
|
154
|
+
listForSeller(productIds: string[], model: SieveModel, opts?: {
|
|
155
|
+
search?: string;
|
|
156
|
+
}): Promise<FirebaseSieveResult<OrderDocument>>;
|
|
155
157
|
listForUser(userId: string, model: SieveModel): Promise<FirebaseSieveResult<OrderDocument>>;
|
|
156
158
|
static readonly ADMIN_SIEVE_FIELDS: {
|
|
157
159
|
searchTxt: {
|
|
@@ -260,7 +260,12 @@ class OrderRepository extends BaseRepository {
|
|
|
260
260
|
throw new DatabaseError(`Failed to delete orders for user: ${userId}`, error);
|
|
261
261
|
}
|
|
262
262
|
}
|
|
263
|
-
async listForSeller(productIds, model) {
|
|
263
|
+
async listForSeller(productIds, model, opts) {
|
|
264
|
+
const plan = planSearchTxt(opts?.search);
|
|
265
|
+
// A search that yielded no usable term must return NOTHING, not the
|
|
266
|
+
// seller's whole order list.
|
|
267
|
+
if (plan.empty)
|
|
268
|
+
return emptySearchResult();
|
|
264
269
|
if (productIds.length === 0) {
|
|
265
270
|
const page = Math.max(1, Number(model.page ?? 1));
|
|
266
271
|
const pageSize = Math.max(1, Number(model.pageSize ?? 20));
|
|
@@ -273,12 +278,22 @@ class OrderRepository extends BaseRepository {
|
|
|
273
278
|
hasMore: false,
|
|
274
279
|
};
|
|
275
280
|
}
|
|
276
|
-
|
|
277
|
-
|
|
281
|
+
let baseQuery = this.getCollection().where(ORDER_FIELDS.PRODUCT_ID, "in", productIds);
|
|
282
|
+
if (plan.head) {
|
|
283
|
+
// `array-contains` alongside `in` is legal — Firestore's one-per-query
|
|
284
|
+
// limits are on `array-contains` and on the `in`/`not-in`/
|
|
285
|
+
// `array-contains-any` family separately, so one of each is fine.
|
|
286
|
+
// Verified against production data before this shipped, and the
|
|
287
|
+
// matching composite index is declared in firestore.indexes.json;
|
|
288
|
+
// the query happened to plan without one, which is not a guarantee.
|
|
289
|
+
baseQuery = baseQuery.where(ORDER_FIELDS.SEARCH_TXT, "array-contains", plan.head);
|
|
290
|
+
}
|
|
291
|
+
const result = await this.sieveQuery(model, OrderRepository.SELLER_SIEVE_FIELDS, {
|
|
278
292
|
baseQuery,
|
|
279
293
|
defaultPageSize: 20,
|
|
280
294
|
maxPageSize: 100,
|
|
281
295
|
});
|
|
296
|
+
return refineSearchTxt(result, plan.rest);
|
|
282
297
|
}
|
|
283
298
|
async listForUser(userId, model) {
|
|
284
299
|
const baseQuery = this.getCollection().where(ORDER_FIELDS.USER_ID, "==", userId);
|
|
@@ -49,7 +49,8 @@ export function SellerCouponsView({ onCreateClick, onEditClick, onToggle, onDele
|
|
|
49
49
|
const config = {
|
|
50
50
|
portal: "seller",
|
|
51
51
|
title: "Coupons",
|
|
52
|
-
//
|
|
52
|
+
// buildCouponSearchTxt indexes code + name + description — nothing else.
|
|
53
|
+
searchPlaceholder: "Search by code, name or description…",
|
|
53
54
|
emptyLabel: "No coupons found — create your first coupon",
|
|
54
55
|
filterKeys: ["isActive"],
|
|
55
56
|
defaultSort: sortBy("createdAt", "DESC"),
|
|
@@ -22,7 +22,9 @@ export function SellerOffersView({ children, onAcceptOffer, onRejectOffer, onCou
|
|
|
22
22
|
const config = {
|
|
23
23
|
portal: "seller",
|
|
24
24
|
title: "Offers",
|
|
25
|
-
//
|
|
25
|
+
// buildOfferSearchTxt indexes productTitle + productSlug + storeName — never
|
|
26
|
+
// the buyer's name or email.
|
|
27
|
+
searchPlaceholder: "Search by product or store…",
|
|
26
28
|
emptyLabel: "No offers received",
|
|
27
29
|
filterKeys: ["status"],
|
|
28
30
|
defaultSort: sortBy("createdAt", "DESC"),
|
|
@@ -294,7 +294,10 @@ export function SellerOrdersView({ orderDetailApiBase = SELLER_ENDPOINTS.ORDERS,
|
|
|
294
294
|
const config = {
|
|
295
295
|
portal: "seller",
|
|
296
296
|
title: "Orders",
|
|
297
|
-
//
|
|
297
|
+
// buildOrderSearchTxt indexes productTitle, storeName and trackingNumber.
|
|
298
|
+
// It does NOT index the buyer's name, email or address — those are PII,
|
|
299
|
+
// and the placeholder must not promise a match it will never make.
|
|
300
|
+
searchPlaceholder: "Search by product, store or tracking number…",
|
|
298
301
|
emptyLabel: "No orders yet",
|
|
299
302
|
filterKeys: ["status"],
|
|
300
303
|
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)
|
|
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;
|
package/dist/security/index.d.ts
CHANGED
|
@@ -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,
|
|
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";
|
package/dist/security/index.js
CHANGED
|
@@ -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,
|
|
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
|
*/
|
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";
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -10,7 +10,6 @@ export * from "./array.helper";
|
|
|
10
10
|
export * from "./object.helper";
|
|
11
11
|
export * from "./pagination.helper";
|
|
12
12
|
export * from "./sorting.helper";
|
|
13
|
-
export * from "./filter.helper";
|
|
14
13
|
export * from "./animation.helper";
|
|
15
14
|
export * from "./color.helper";
|
|
16
15
|
export * from "./business-day";
|
package/dist/utils/index.js
CHANGED
|
@@ -10,7 +10,6 @@ export * from "./array.helper";
|
|
|
10
10
|
export * from "./object.helper";
|
|
11
11
|
export * from "./pagination.helper";
|
|
12
12
|
export * from "./sorting.helper";
|
|
13
|
-
export * from "./filter.helper";
|
|
14
13
|
export * from "./animation.helper";
|
|
15
14
|
export * from "./color.helper";
|
|
16
15
|
export * from "./business-day";
|
|
@@ -11,11 +11,6 @@ export declare const SIEVE_OP: {
|
|
|
11
11
|
readonly NOT_CONTAINS: "!@=";
|
|
12
12
|
readonly NOT_STARTS: "!_=";
|
|
13
13
|
readonly NOT_ENDS: "!_-=";
|
|
14
|
-
readonly CONTAINS_CI: "@=*";
|
|
15
|
-
readonly STARTS_CI: "_=*";
|
|
16
|
-
readonly ENDS_CI: "_-=*";
|
|
17
|
-
readonly EQ_CI: "==*";
|
|
18
|
-
readonly NEQ_CI: "!=*";
|
|
19
14
|
};
|
|
20
15
|
export type SieveOp = (typeof SIEVE_OP)[keyof typeof SIEVE_OP];
|
|
21
16
|
/** Operators for which the pipe `|` is valid for OR-matching within a single clause */
|
|
@@ -11,20 +11,19 @@ export const SIEVE_OP = {
|
|
|
11
11
|
NOT_CONTAINS: "!@=",
|
|
12
12
|
NOT_STARTS: "!_=",
|
|
13
13
|
NOT_ENDS: "!_-=",
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
// The five case-insensitive operators (@=* _=* _-=* ==* !=*) were
|
|
15
|
+
// DELETED. Firestore has no case-insensitive comparison, so the adapter
|
|
16
|
+
// threw on every one — and with `throwExceptions: false` that throw
|
|
17
|
+
// returned a PARTIALLY-BUILT query rather than an error, so the clause,
|
|
18
|
+
// and every clause after it, was silently dropped. They read as working
|
|
19
|
+
// search operators and did the opposite. `searchTxt` + `array-contains`
|
|
20
|
+
// is the replacement.
|
|
19
21
|
};
|
|
20
22
|
/** Operators for which the pipe `|` is valid for OR-matching within a single clause */
|
|
21
23
|
export const SIEVE_PIPE_OPS = new Set([
|
|
22
24
|
SIEVE_OP.CONTAINS,
|
|
23
25
|
SIEVE_OP.STARTS,
|
|
24
26
|
SIEVE_OP.ENDS,
|
|
25
|
-
SIEVE_OP.CONTAINS_CI,
|
|
26
|
-
SIEVE_OP.STARTS_CI,
|
|
27
|
-
SIEVE_OP.ENDS_CI,
|
|
28
27
|
]);
|
|
29
28
|
/** Single Sieve clause: sieveFilter("status", "==", "published") → "status==published" */
|
|
30
29
|
export function sieveFilter(field, op, value) {
|