@mohasinac/appkit 4.71.2 → 4.72.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/dist/.build-stamp.json +3 -3
- package/dist/constants/api-endpoints.d.ts +3 -0
- package/dist/constants/api-endpoints.js +6 -0
- package/dist/features/classified/components/ClassifiedDetailPageView.js +2 -2
- package/dist/features/digital-codes/components/DigitalCodeDetailPageView.js +2 -2
- package/dist/features/events/components/EntryVoteButtons.d.ts +19 -0
- package/dist/features/events/components/EntryVoteButtons.js +65 -0
- package/dist/features/events/repository/entry-votes.repository.d.ts +45 -0
- package/dist/features/events/repository/entry-votes.repository.js +154 -0
- package/dist/features/events/schemas/entry-votes.d.ts +134 -0
- package/dist/features/events/schemas/entry-votes.js +114 -0
- package/dist/features/events/schemas/index.d.ts +29 -7
- package/dist/features/events/schemas/index.js +29 -2
- package/dist/features/inventory/components/AdminMoveLedgerView.d.ts +1 -1
- package/dist/features/live/components/LiveItemDetailPageView.js +2 -2
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +3 -3
- package/dist/features/products/components/ClearanceDetailPageView.js +2 -2
- package/dist/features/products/components/index.d.ts +0 -2
- package/dist/features/products/components/index.js +0 -1
- package/dist/features/products/schemas/index.d.ts +6 -7
- package/dist/features/products/schemas/index.js +20 -2
- package/dist/features/promotions/schemas/firestore.d.ts +17 -1
- package/dist/features/promotions/schemas/firestore.js +22 -0
- package/dist/features/promotions/schemas/index.d.ts +45 -21
- package/dist/features/promotions/schemas/index.js +37 -8
- package/dist/features/promotions/types/index.d.ts +1 -1
- package/dist/features/reviews/schemas/index.d.ts +3 -0
- package/dist/features/reviews/schemas/index.js +25 -0
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -3
- package/dist/next/routing/portals.d.ts +22 -0
- package/dist/next/routing/portals.js +43 -0
- package/dist/providers/db-firebase/admin.d.ts +2 -0
- package/dist/providers/db-firebase/admin.js +25 -2
- package/dist/schemas/registry.d.ts +11 -8
- package/dist/styles.css +1 -1
- package/dist/tailwind-utilities.css +1 -1
- package/dist/ui/components/ListingDetailShell.d.ts +68 -0
- package/dist/ui/components/ListingDetailShell.js +32 -0
- package/package.json +533 -525
- package/scripts/seed-cli.mjs +32 -2
- package/dist/features/products/components/PreOrderDetailView.d.ts +0 -18
- package/dist/features/products/components/PreOrderDetailView.js +0 -12
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
export * from "./firestore";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* 🛑 OPEN, not a closed enum — the same change made to events and listings on
|
|
5
|
+
* 2026-11-08. The four below are the shipped DEFAULT TEMPLATES, kept as a named
|
|
6
|
+
* list so they stay discoverable in pickers and seeds.
|
|
7
|
+
*
|
|
8
|
+
* A site wanting a discount kind we do not ship — tiered, bundle, first-order —
|
|
9
|
+
* adds a coupon-type config row and a handler, rather than editing this file to
|
|
10
|
+
* ask permission.
|
|
11
|
+
*/
|
|
12
|
+
export declare const DEFAULT_COUPON_TYPE_TEMPLATES: readonly ["percentage", "fixed", "free_shipping", "buy_x_get_y"];
|
|
13
|
+
export declare const couponTypeEnumSchema: z.ZodString;
|
|
4
14
|
export declare const discountConfigSchema: z.ZodObject<{
|
|
5
15
|
value: z.ZodNumber;
|
|
6
16
|
maxDiscount: z.ZodOptional<z.ZodEffects<z.ZodNumber, number, number>>;
|
|
@@ -143,7 +153,7 @@ export declare const couponFirestoreSchema: z.ZodObject<{
|
|
|
143
153
|
code: z.ZodString;
|
|
144
154
|
name: z.ZodString;
|
|
145
155
|
description: z.ZodString;
|
|
146
|
-
type: z.
|
|
156
|
+
type: z.ZodString;
|
|
147
157
|
scope: z.ZodEnum<["admin", "seller"]>;
|
|
148
158
|
storeId: z.ZodOptional<z.ZodString>;
|
|
149
159
|
applicableToCollectorDrops: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -274,7 +284,7 @@ export declare const couponFirestoreSchema: z.ZodObject<{
|
|
|
274
284
|
}, "strip", z.ZodTypeAny, {
|
|
275
285
|
code: string;
|
|
276
286
|
id: string;
|
|
277
|
-
type:
|
|
287
|
+
type: string;
|
|
278
288
|
description: string;
|
|
279
289
|
createdAt: string | Date | z.objectOutputType<{
|
|
280
290
|
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
@@ -333,7 +343,7 @@ export declare const couponFirestoreSchema: z.ZodObject<{
|
|
|
333
343
|
}, {
|
|
334
344
|
code: string;
|
|
335
345
|
id: string;
|
|
336
|
-
type:
|
|
346
|
+
type: string;
|
|
337
347
|
description: string;
|
|
338
348
|
createdAt: string | Date | z.objectInputType<{
|
|
339
349
|
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
@@ -414,7 +424,7 @@ export declare const couponCreateBodySchema: z.ZodEffects<z.ZodObject<{
|
|
|
414
424
|
code: z.ZodString;
|
|
415
425
|
name: z.ZodString;
|
|
416
426
|
description: z.ZodDefault<z.ZodString>;
|
|
417
|
-
type: z.
|
|
427
|
+
type: z.ZodString;
|
|
418
428
|
tiers: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
419
429
|
minAmount: z.ZodEffects<z.ZodNumber, number, number>;
|
|
420
430
|
discountValue: z.ZodNumber;
|
|
@@ -508,7 +518,7 @@ export declare const couponCreateBodySchema: z.ZodEffects<z.ZodObject<{
|
|
|
508
518
|
createdBy: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
509
519
|
}, "strip", z.ZodTypeAny, {
|
|
510
520
|
code: string;
|
|
511
|
-
type:
|
|
521
|
+
type: string;
|
|
512
522
|
description: string;
|
|
513
523
|
createdBy: string;
|
|
514
524
|
name: string;
|
|
@@ -548,7 +558,7 @@ export declare const couponCreateBodySchema: z.ZodEffects<z.ZodObject<{
|
|
|
548
558
|
}[] | undefined;
|
|
549
559
|
}, {
|
|
550
560
|
code: string;
|
|
551
|
-
type:
|
|
561
|
+
type: string;
|
|
552
562
|
name: string;
|
|
553
563
|
discount: {
|
|
554
564
|
value: number;
|
|
@@ -588,7 +598,7 @@ export declare const couponCreateBodySchema: z.ZodEffects<z.ZodObject<{
|
|
|
588
598
|
} | undefined;
|
|
589
599
|
}>, {
|
|
590
600
|
code: string;
|
|
591
|
-
type:
|
|
601
|
+
type: string;
|
|
592
602
|
description: string;
|
|
593
603
|
createdBy: string;
|
|
594
604
|
name: string;
|
|
@@ -628,7 +638,7 @@ export declare const couponCreateBodySchema: z.ZodEffects<z.ZodObject<{
|
|
|
628
638
|
}[] | undefined;
|
|
629
639
|
}, {
|
|
630
640
|
code: string;
|
|
631
|
-
type:
|
|
641
|
+
type: string;
|
|
632
642
|
name: string;
|
|
633
643
|
discount: {
|
|
634
644
|
value: number;
|
|
@@ -892,7 +902,7 @@ export declare const claimedCouponSourceSchema: z.ZodEnum<["manual", "promo", "s
|
|
|
892
902
|
export declare const claimedCouponSnapshotSchema: z.ZodObject<{
|
|
893
903
|
name: z.ZodString;
|
|
894
904
|
description: z.ZodOptional<z.ZodString>;
|
|
895
|
-
type: z.
|
|
905
|
+
type: z.ZodString;
|
|
896
906
|
scope: z.ZodEnum<["admin", "seller"]>;
|
|
897
907
|
storeId: z.ZodOptional<z.ZodString>;
|
|
898
908
|
discount: z.ZodObject<{
|
|
@@ -931,7 +941,7 @@ export declare const claimedCouponSnapshotSchema: z.ZodObject<{
|
|
|
931
941
|
excludeCategories?: string[] | undefined;
|
|
932
942
|
}>;
|
|
933
943
|
}, "strip", z.ZodTypeAny, {
|
|
934
|
-
type:
|
|
944
|
+
type: string;
|
|
935
945
|
name: string;
|
|
936
946
|
scope: "seller" | "admin";
|
|
937
947
|
discount: {
|
|
@@ -950,7 +960,7 @@ export declare const claimedCouponSnapshotSchema: z.ZodObject<{
|
|
|
950
960
|
description?: string | undefined;
|
|
951
961
|
storeId?: string | undefined;
|
|
952
962
|
}, {
|
|
953
|
-
type:
|
|
963
|
+
type: string;
|
|
954
964
|
name: string;
|
|
955
965
|
scope: "seller" | "admin";
|
|
956
966
|
discount: {
|
|
@@ -978,7 +988,7 @@ export declare const claimedCouponFirestoreSchema: z.ZodObject<{
|
|
|
978
988
|
couponSnapshot: z.ZodObject<{
|
|
979
989
|
name: z.ZodString;
|
|
980
990
|
description: z.ZodOptional<z.ZodString>;
|
|
981
|
-
type: z.
|
|
991
|
+
type: z.ZodString;
|
|
982
992
|
scope: z.ZodEnum<["admin", "seller"]>;
|
|
983
993
|
storeId: z.ZodOptional<z.ZodString>;
|
|
984
994
|
discount: z.ZodObject<{
|
|
@@ -1017,7 +1027,7 @@ export declare const claimedCouponFirestoreSchema: z.ZodObject<{
|
|
|
1017
1027
|
excludeCategories?: string[] | undefined;
|
|
1018
1028
|
}>;
|
|
1019
1029
|
}, "strip", z.ZodTypeAny, {
|
|
1020
|
-
type:
|
|
1030
|
+
type: string;
|
|
1021
1031
|
name: string;
|
|
1022
1032
|
scope: "seller" | "admin";
|
|
1023
1033
|
discount: {
|
|
@@ -1036,7 +1046,7 @@ export declare const claimedCouponFirestoreSchema: z.ZodObject<{
|
|
|
1036
1046
|
description?: string | undefined;
|
|
1037
1047
|
storeId?: string | undefined;
|
|
1038
1048
|
}, {
|
|
1039
|
-
type:
|
|
1049
|
+
type: string;
|
|
1040
1050
|
name: string;
|
|
1041
1051
|
scope: "seller" | "admin";
|
|
1042
1052
|
discount: {
|
|
@@ -1099,7 +1109,7 @@ export declare const claimedCouponFirestoreSchema: z.ZodObject<{
|
|
|
1099
1109
|
}, z.ZodTypeAny, "passthrough">;
|
|
1100
1110
|
couponId: string;
|
|
1101
1111
|
couponSnapshot: {
|
|
1102
|
-
type:
|
|
1112
|
+
type: string;
|
|
1103
1113
|
name: string;
|
|
1104
1114
|
scope: "seller" | "admin";
|
|
1105
1115
|
discount: {
|
|
@@ -1139,7 +1149,7 @@ export declare const claimedCouponFirestoreSchema: z.ZodObject<{
|
|
|
1139
1149
|
}, z.ZodTypeAny, "passthrough">;
|
|
1140
1150
|
couponId: string;
|
|
1141
1151
|
couponSnapshot: {
|
|
1142
|
-
type:
|
|
1152
|
+
type: string;
|
|
1143
1153
|
name: string;
|
|
1144
1154
|
scope: "seller" | "admin";
|
|
1145
1155
|
discount: {
|
|
@@ -1169,7 +1179,21 @@ export declare const claimedCouponFirestoreSchema: z.ZodObject<{
|
|
|
1169
1179
|
export type CouponFromSchema = z.infer<typeof couponFirestoreSchema>;
|
|
1170
1180
|
export type CouponUsageFromSchema = z.infer<typeof couponUsageFirestoreSchema>;
|
|
1171
1181
|
export type ClaimedCouponFromSchema = z.infer<typeof claimedCouponFirestoreSchema>;
|
|
1172
|
-
|
|
1182
|
+
/**
|
|
1183
|
+
* 🛑 The SECOND coupon-type schema, and the 2026-11-08 pass MISSED it.
|
|
1184
|
+
*
|
|
1185
|
+
* `couponTypeEnumSchema` near the top of this file was opened that day;
|
|
1186
|
+
* this one — same four values, different name, 290 lines further down — stayed
|
|
1187
|
+
* closed, so coupons were still half-fixed. A re-measure on 11-09 found it.
|
|
1188
|
+
*
|
|
1189
|
+
* The lesson is the reason the acceptance test is a GREP and not a memory:
|
|
1190
|
+
* opening "the enum" is not the same as opening every enum, and two schemas
|
|
1191
|
+
* for one concept is exactly how a half-finished change hides.
|
|
1192
|
+
*
|
|
1193
|
+
* Both now accept a validated slug; the four values remain
|
|
1194
|
+
* `DEFAULT_COUPON_TYPE_TEMPLATES` above.
|
|
1195
|
+
*/
|
|
1196
|
+
export declare const couponTypeSchema: z.ZodString;
|
|
1173
1197
|
export declare const couponScopeSchema: z.ZodEnum<["admin", "seller"]>;
|
|
1174
1198
|
/**
|
|
1175
1199
|
* Base Zod schema for a coupon/promotion.
|
|
@@ -1188,7 +1212,7 @@ export declare const couponItemSchema: z.ZodObject<{
|
|
|
1188
1212
|
code: z.ZodString;
|
|
1189
1213
|
name: z.ZodString;
|
|
1190
1214
|
description: z.ZodString;
|
|
1191
|
-
type: z.
|
|
1215
|
+
type: z.ZodString;
|
|
1192
1216
|
scope: z.ZodEnum<["admin", "seller"]>;
|
|
1193
1217
|
discountValue: z.ZodNumber;
|
|
1194
1218
|
minOrderAmount: z.ZodOptional<z.ZodNumber>;
|
|
@@ -1210,7 +1234,7 @@ export declare const couponItemSchema: z.ZodObject<{
|
|
|
1210
1234
|
}, "strip", z.ZodTypeAny, {
|
|
1211
1235
|
code: string;
|
|
1212
1236
|
id: string;
|
|
1213
|
-
type:
|
|
1237
|
+
type: string;
|
|
1214
1238
|
description: string;
|
|
1215
1239
|
createdAt: string;
|
|
1216
1240
|
updatedAt: string;
|
|
@@ -1234,7 +1258,7 @@ export declare const couponItemSchema: z.ZodObject<{
|
|
|
1234
1258
|
}, {
|
|
1235
1259
|
code: string;
|
|
1236
1260
|
id: string;
|
|
1237
|
-
type:
|
|
1261
|
+
type: string;
|
|
1238
1262
|
description: string;
|
|
1239
1263
|
createdAt: string;
|
|
1240
1264
|
updatedAt: string;
|
|
@@ -7,12 +7,27 @@ import { auditTimestampsShape, firestoreDateSchema, rupeesSchema } from "../../.
|
|
|
7
7
|
// SCHEMAS.firestore.coupons
|
|
8
8
|
// SCHEMAS.firestore.couponUsage
|
|
9
9
|
// SCHEMAS.firestore.claimedCoupons
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* 🛑 OPEN, not a closed enum — the same change made to events and listings on
|
|
12
|
+
* 2026-11-08. The four below are the shipped DEFAULT TEMPLATES, kept as a named
|
|
13
|
+
* list so they stay discoverable in pickers and seeds.
|
|
14
|
+
*
|
|
15
|
+
* A site wanting a discount kind we do not ship — tiered, bundle, first-order —
|
|
16
|
+
* adds a coupon-type config row and a handler, rather than editing this file to
|
|
17
|
+
* ask permission.
|
|
18
|
+
*/
|
|
19
|
+
export const DEFAULT_COUPON_TYPE_TEMPLATES = [
|
|
11
20
|
"percentage",
|
|
12
21
|
"fixed",
|
|
13
22
|
"free_shipping",
|
|
14
23
|
"buy_x_get_y",
|
|
15
|
-
]
|
|
24
|
+
];
|
|
25
|
+
export const couponTypeEnumSchema = z
|
|
26
|
+
.string()
|
|
27
|
+
.trim()
|
|
28
|
+
.min(2)
|
|
29
|
+
.max(40)
|
|
30
|
+
.regex(/^[a-z0-9]+(?:[-_][a-z0-9]+)*$/, "Use a lowercase slug, e.g. first_order");
|
|
16
31
|
export const discountConfigSchema = z.object({
|
|
17
32
|
value: z.number(),
|
|
18
33
|
maxDiscount: rupeesSchema.optional(),
|
|
@@ -263,12 +278,26 @@ export const claimedCouponFirestoreSchema = z.object({
|
|
|
263
278
|
updatedAt: firestoreDateSchema,
|
|
264
279
|
});
|
|
265
280
|
// --- Sub-schemas --------------------------------------------------------------
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
281
|
+
/**
|
|
282
|
+
* 🛑 The SECOND coupon-type schema, and the 2026-11-08 pass MISSED it.
|
|
283
|
+
*
|
|
284
|
+
* `couponTypeEnumSchema` near the top of this file was opened that day;
|
|
285
|
+
* this one — same four values, different name, 290 lines further down — stayed
|
|
286
|
+
* closed, so coupons were still half-fixed. A re-measure on 11-09 found it.
|
|
287
|
+
*
|
|
288
|
+
* The lesson is the reason the acceptance test is a GREP and not a memory:
|
|
289
|
+
* opening "the enum" is not the same as opening every enum, and two schemas
|
|
290
|
+
* for one concept is exactly how a half-finished change hides.
|
|
291
|
+
*
|
|
292
|
+
* Both now accept a validated slug; the four values remain
|
|
293
|
+
* `DEFAULT_COUPON_TYPE_TEMPLATES` above.
|
|
294
|
+
*/
|
|
295
|
+
export const couponTypeSchema = z
|
|
296
|
+
.string()
|
|
297
|
+
.trim()
|
|
298
|
+
.min(2)
|
|
299
|
+
.max(40)
|
|
300
|
+
.regex(/^[a-z0-9]+(?:[-_][a-z0-9]+)*$/, "Use a lowercase slug, e.g. first_order");
|
|
272
301
|
export const couponScopeSchema = z.enum(["admin", "seller"]);
|
|
273
302
|
// --- Base item schema ---------------------------------------------------------
|
|
274
303
|
/**
|
|
@@ -16,7 +16,7 @@ export type CouponType = "percentage" | "fixed" | "free_shipping" | "buy_x_get_y
|
|
|
16
16
|
* `Record<CouponType, string>` — that is the point of declaring the union
|
|
17
17
|
* first.
|
|
18
18
|
*/
|
|
19
|
-
| "points_earn";
|
|
19
|
+
| "points_earn" | (string & {});
|
|
20
20
|
export type CouponScope = "admin" | "seller";
|
|
21
21
|
export interface CouponItem {
|
|
22
22
|
id: string;
|
|
@@ -38,6 +38,7 @@ export declare const reviewFirestoreSchema: z.ZodObject<{
|
|
|
38
38
|
productId: z.ZodString;
|
|
39
39
|
productTitle: z.ZodString;
|
|
40
40
|
listingType: z.ZodOptional<z.ZodString>;
|
|
41
|
+
reviewType: z.ZodOptional<z.ZodString>;
|
|
41
42
|
storeId: z.ZodOptional<z.ZodString>;
|
|
42
43
|
storeName: z.ZodOptional<z.ZodString>;
|
|
43
44
|
userId: z.ZodString;
|
|
@@ -147,6 +148,7 @@ export declare const reviewFirestoreSchema: z.ZodObject<{
|
|
|
147
148
|
sellerRepliedAt?: string | Date | z.objectOutputType<{
|
|
148
149
|
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
149
150
|
}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
151
|
+
reviewType?: string | undefined;
|
|
150
152
|
}, {
|
|
151
153
|
title: string;
|
|
152
154
|
id: string;
|
|
@@ -195,6 +197,7 @@ export declare const reviewFirestoreSchema: z.ZodObject<{
|
|
|
195
197
|
sellerRepliedAt?: string | Date | z.objectInputType<{
|
|
196
198
|
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
197
199
|
}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
200
|
+
reviewType?: string | undefined;
|
|
198
201
|
}>;
|
|
199
202
|
export type ReviewFromSchema = z.infer<typeof reviewFirestoreSchema>;
|
|
200
203
|
export declare const reviewStatusSchema: z.ZodEnum<["pending", "approved", "rejected"]>;
|
|
@@ -15,6 +15,31 @@ export const reviewFirestoreSchema = z.object({
|
|
|
15
15
|
productId: z.string(),
|
|
16
16
|
productTitle: z.string(),
|
|
17
17
|
listingType: z.string().optional(),
|
|
18
|
+
/*
|
|
19
|
+
* The KIND of review — the config dimension reviews did not have.
|
|
20
|
+
*
|
|
21
|
+
* Owner, 2026-11-08, naming reviews alongside events, listings and coupons:
|
|
22
|
+
* *"nothing in the code should be fixed … the types we have now are the
|
|
23
|
+
* default templates"*. Reviews had no type at all, so every review was
|
|
24
|
+
* implicitly a product review and a site wanting seller reviews, unboxing
|
|
25
|
+
* reviews or a verified-buyer-only kind had nowhere to put it.
|
|
26
|
+
*
|
|
27
|
+
* An open validated slug, resolved against the review-type config: which
|
|
28
|
+
* rules apply (media allowed, moderation required, who may write one) is a
|
|
29
|
+
* rule set on that row, not a branch in this file.
|
|
30
|
+
*
|
|
31
|
+
* 🛑 `status` below is deliberately NOT opened. It is the moderation STATE
|
|
32
|
+
* MACHINE — pending/approved/rejected is machinery, not a user choice, and an
|
|
33
|
+
* unknown state would mean a review that no queue can ever clear. Types are
|
|
34
|
+
* config; lifecycle states are code.
|
|
35
|
+
*/
|
|
36
|
+
reviewType: z
|
|
37
|
+
.string()
|
|
38
|
+
.trim()
|
|
39
|
+
.min(2)
|
|
40
|
+
.max(40)
|
|
41
|
+
.regex(/^[a-z0-9]+(?:[-_][a-z0-9]+)*$/, "Use a lowercase slug, e.g. seller-review")
|
|
42
|
+
.optional(),
|
|
18
43
|
storeId: z.string().optional(),
|
|
19
44
|
storeName: z.string().optional(),
|
|
20
45
|
userId: z.string(),
|
package/dist/index.d.ts
CHANGED
|
@@ -2137,7 +2137,6 @@ export { PRODUCT_SORT_VALUES } from "./features/products/columns/index";
|
|
|
2137
2137
|
export { PRODUCT_STATUS_OPTIONS } from "./features/products/components/ProductForm";
|
|
2138
2138
|
export { PRODUCT_UPDATABLE_FIELDS } from "./features/products/schemas/firestore";
|
|
2139
2139
|
export { PlaceBidForm } from "./features/products/components/PlaceBidForm";
|
|
2140
|
-
export { PreOrderDetailView } from "./features/products/components/PreOrderDetailView";
|
|
2141
2140
|
export type { ClearanceListingViewProps } from "./features/products/components/ClearanceListingView";
|
|
2142
2141
|
export { ClearanceIndexListing } from "./features/products/components/ClearanceIndexListing";
|
|
2143
2142
|
export type { ClearanceIndexListingProps } from "./features/products/components/ClearanceIndexListing";
|
|
@@ -2234,7 +2233,6 @@ export type { BidHistoryProps } from "./features/products/components/BidHistory"
|
|
|
2234
2233
|
export type { InteractiveProductCardProps } from "./features/products/components/InteractiveProductCard";
|
|
2235
2234
|
export type { ListingType } from "./features/products/types/index";
|
|
2236
2235
|
export type { PlaceBidFormProps } from "./features/products/components/PlaceBidForm";
|
|
2237
|
-
export type { PreOrderDetailViewProps } from "./features/products/components/PreOrderDetailView";
|
|
2238
2236
|
export type { ProductAdminUpdateInput } from "./features/products/schemas/firestore";
|
|
2239
2237
|
export type { ProductCondition } from "./features/products/types/index";
|
|
2240
2238
|
export type { ProductCreateInput } from "./features/products/schemas/firestore";
|
package/dist/index.js
CHANGED
|
@@ -3971,9 +3971,6 @@ export { PRODUCT_UPDATABLE_FIELDS } from "./features/products/schemas/firestore.
|
|
|
3971
3971
|
// [CLIENT-SSR]-Runs in both SSR and browser â€" React component or hook that does not depend on browser-only APIs.
|
|
3972
3972
|
// PlaceBidForm - Component for place bid form.
|
|
3973
3973
|
export { PlaceBidForm } from "./features/products/components/PlaceBidForm.js";
|
|
3974
|
-
// [CLIENT-SSR]-Runs in both SSR and browser â€" React component or hook that does not depend on browser-only APIs.
|
|
3975
|
-
// PreOrderDetailView - Component for pre order detail view.
|
|
3976
|
-
export { PreOrderDetailView } from "./features/products/components/PreOrderDetailView.js";
|
|
3977
3974
|
// [CLIENT]-Client toolbar+grid for clearance (SB4-F).
|
|
3978
3975
|
export { ClearanceIndexListing } from "./features/products/components/ClearanceIndexListing.js";
|
|
3979
3976
|
// [CLIENT]-Marketplace card for clearance (SB4-F).
|
|
@@ -91,6 +91,28 @@ export interface PortalDefinition {
|
|
|
91
91
|
* point — it is data, editable without touching a mechanism.
|
|
92
92
|
*/
|
|
93
93
|
export declare const PORTAL_DEFINITIONS: readonly PortalDefinition[];
|
|
94
|
+
/**
|
|
95
|
+
* Hosts that are their OWN DEPLOYMENT, not a portal of this app.
|
|
96
|
+
*
|
|
97
|
+
* 🛑 A PORTAL and a DEPLOYMENT are not the same thing, and conflating them is
|
|
98
|
+
* how a subdomain ends up serving the wrong site:
|
|
99
|
+
*
|
|
100
|
+
* portal `admin.<domain>` → THIS app, rewritten to `/admin`
|
|
101
|
+
* deployment `events.<domain>` → a DIFFERENT app, with its own build
|
|
102
|
+
*
|
|
103
|
+
* A deployment host must never be rewritten to a section here, and must never
|
|
104
|
+
* be 301'd to the canonical host either. If one of these hostnames reaches
|
|
105
|
+
* this app at all, the DNS or the platform mapping is wrong — redirecting it
|
|
106
|
+
* to www would hide that by silently serving the shop instead, which is
|
|
107
|
+
* exactly the failure CLAUDE.md records for `audit.` and `tools.` serving the
|
|
108
|
+
* main homepage as duplicate content.
|
|
109
|
+
*
|
|
110
|
+
* Listed as DATA for the same reason the portals are: adding `live.` or
|
|
111
|
+
* `media.` later is a row, not a code change.
|
|
112
|
+
*/
|
|
113
|
+
export declare const DEPLOYMENT_LABELS: readonly string[];
|
|
114
|
+
/** Is this hostname a separate deployment rather than a portal of this app? */
|
|
115
|
+
export declare function isDeploymentHost(hostname: string): boolean;
|
|
94
116
|
/** Every route section a portal serves. Derived; never hand-maintained. */
|
|
95
117
|
export declare const PORTAL_SECTIONS: readonly string[];
|
|
96
118
|
/** True for a dev/preview origin that no public-host rule should police. */
|
|
@@ -65,6 +65,42 @@ export const PORTAL_DEFINITIONS = [
|
|
|
65
65
|
*/
|
|
66
66
|
{ label: "auth", section: "/auth", roles: [], home: "/auth/login" },
|
|
67
67
|
];
|
|
68
|
+
/**
|
|
69
|
+
* Hosts that are their OWN DEPLOYMENT, not a portal of this app.
|
|
70
|
+
*
|
|
71
|
+
* 🛑 A PORTAL and a DEPLOYMENT are not the same thing, and conflating them is
|
|
72
|
+
* how a subdomain ends up serving the wrong site:
|
|
73
|
+
*
|
|
74
|
+
* portal `admin.<domain>` → THIS app, rewritten to `/admin`
|
|
75
|
+
* deployment `events.<domain>` → a DIFFERENT app, with its own build
|
|
76
|
+
*
|
|
77
|
+
* A deployment host must never be rewritten to a section here, and must never
|
|
78
|
+
* be 301'd to the canonical host either. If one of these hostnames reaches
|
|
79
|
+
* this app at all, the DNS or the platform mapping is wrong — redirecting it
|
|
80
|
+
* to www would hide that by silently serving the shop instead, which is
|
|
81
|
+
* exactly the failure CLAUDE.md records for `audit.` and `tools.` serving the
|
|
82
|
+
* main homepage as duplicate content.
|
|
83
|
+
*
|
|
84
|
+
* Listed as DATA for the same reason the portals are: adding `live.` or
|
|
85
|
+
* `media.` later is a row, not a code change.
|
|
86
|
+
*/
|
|
87
|
+
export const DEPLOYMENT_LABELS = [
|
|
88
|
+
"auth",
|
|
89
|
+
"wiki",
|
|
90
|
+
"tools",
|
|
91
|
+
"audit",
|
|
92
|
+
"events",
|
|
93
|
+
"blogs",
|
|
94
|
+
"live",
|
|
95
|
+
"media",
|
|
96
|
+
"help",
|
|
97
|
+
"chat",
|
|
98
|
+
];
|
|
99
|
+
/** Is this hostname a separate deployment rather than a portal of this app? */
|
|
100
|
+
export function isDeploymentHost(hostname) {
|
|
101
|
+
const firstLabel = normalizeHostname(hostname).split(".")[0] ?? "";
|
|
102
|
+
return DEPLOYMENT_LABELS.includes(firstLabel);
|
|
103
|
+
}
|
|
68
104
|
/** Every route section a portal serves. Derived; never hand-maintained. */
|
|
69
105
|
export const PORTAL_SECTIONS = PORTAL_DEFINITIONS.map((p) => p.section);
|
|
70
106
|
/**
|
|
@@ -313,6 +349,13 @@ export function isOffCanonicalHost(hostname, canonicalHost) {
|
|
|
313
349
|
return false;
|
|
314
350
|
if (portalForHost(host))
|
|
315
351
|
return false;
|
|
352
|
+
/*
|
|
353
|
+
* A deployment host is someone else's app. Redirecting it to the canonical
|
|
354
|
+
* shop would serve duplicate content under the wrong brand and mask a
|
|
355
|
+
* misrouted DNS record — see `DEPLOYMENT_LABELS`.
|
|
356
|
+
*/
|
|
357
|
+
if (isDeploymentHost(host))
|
|
358
|
+
return false;
|
|
316
359
|
if (isNonPublicHost(host))
|
|
317
360
|
return false;
|
|
318
361
|
return true;
|
|
@@ -47,6 +47,8 @@ export declare function getAdminAuth(): Auth;
|
|
|
47
47
|
* second database — a second database is a split, not a copy.
|
|
48
48
|
*/
|
|
49
49
|
export type DatabaseTarget = "shop" | "wiki";
|
|
50
|
+
/** Which database this process is actually talking to, for logs and guards. */
|
|
51
|
+
export declare function resolvedDatabaseId(target?: DatabaseTarget): string;
|
|
50
52
|
export declare function getAdminDb(target?: DatabaseTarget): Firestore;
|
|
51
53
|
/** The read-only wiki/tools database. Never used by the money path. */
|
|
52
54
|
export declare function getWikiDb(): Firestore;
|
|
@@ -157,11 +157,34 @@ export function getAdminAuth() {
|
|
|
157
157
|
set("__mohasinac_firebase_admin_auth__", auth);
|
|
158
158
|
return auth;
|
|
159
159
|
}
|
|
160
|
-
/**
|
|
160
|
+
/**
|
|
161
|
+
* `undefined` means the `(default)` database.
|
|
162
|
+
*
|
|
163
|
+
* 🛑 THE SHOP TARGET IS ENV-DRIVEN, and that is the whole point of this table.
|
|
164
|
+
*
|
|
165
|
+
* Owner, 2026-11-08: seeding and local work must not touch the live data —
|
|
166
|
+
* *"make the seeds be in the new db … and use that for local and testing while
|
|
167
|
+
* the live site still works on the original db"*.
|
|
168
|
+
*
|
|
169
|
+
* So production sets nothing and gets `(default)`; a developer or the seed CLI
|
|
170
|
+
* sets `FIREBASE_SHOP_DATABASE_ID=dev-db` in `.env.local` and every read and
|
|
171
|
+
* write in the process follows, because this is the ONE place a Firestore
|
|
172
|
+
* handle is constructed. There is no per-call database argument to forget.
|
|
173
|
+
*
|
|
174
|
+
* 🛑 `.env.local` is gitignored, so an unset variable means PRODUCTION. That is
|
|
175
|
+
* deliberate — the safe default for a deploy is the real database, and the
|
|
176
|
+
* dangerous direction (a developer silently writing to live) is the one that
|
|
177
|
+
* requires no action. Check this value before any destructive seed command;
|
|
178
|
+
* `seed-cli` prints the resolved database for exactly that reason.
|
|
179
|
+
*/
|
|
161
180
|
const DATABASE_IDS = {
|
|
162
|
-
shop: undefined,
|
|
181
|
+
shop: process.env.FIREBASE_SHOP_DATABASE_ID || undefined,
|
|
163
182
|
wiki: process.env.FIREBASE_WIKI_DATABASE_ID || "wiki-db",
|
|
164
183
|
};
|
|
184
|
+
/** Which database this process is actually talking to, for logs and guards. */
|
|
185
|
+
export function resolvedDatabaseId(target = "shop") {
|
|
186
|
+
return DATABASE_IDS[target] ?? "(default)";
|
|
187
|
+
}
|
|
165
188
|
/*
|
|
166
189
|
* The global cache keys are a typed literal union, so these are spelled out
|
|
167
190
|
* rather than built with a template — a computed key would not type-check and,
|
|
@@ -1245,7 +1245,7 @@ export declare const SCHEMAS: {
|
|
|
1245
1245
|
couponSnapshot: import("zod").ZodObject<{
|
|
1246
1246
|
name: import("zod").ZodString;
|
|
1247
1247
|
description: import("zod").ZodOptional<import("zod").ZodString>;
|
|
1248
|
-
type: import("zod").
|
|
1248
|
+
type: import("zod").ZodString;
|
|
1249
1249
|
scope: import("zod").ZodEnum<["admin", "seller"]>;
|
|
1250
1250
|
storeId: import("zod").ZodOptional<import("zod").ZodString>;
|
|
1251
1251
|
discount: import("zod").ZodObject<{
|
|
@@ -1284,7 +1284,7 @@ export declare const SCHEMAS: {
|
|
|
1284
1284
|
excludeCategories?: string[] | undefined;
|
|
1285
1285
|
}>;
|
|
1286
1286
|
}, "strip", import("zod").ZodTypeAny, {
|
|
1287
|
-
type:
|
|
1287
|
+
type: string;
|
|
1288
1288
|
name: string;
|
|
1289
1289
|
scope: "seller" | "admin";
|
|
1290
1290
|
discount: {
|
|
@@ -1303,7 +1303,7 @@ export declare const SCHEMAS: {
|
|
|
1303
1303
|
description?: string | undefined;
|
|
1304
1304
|
storeId?: string | undefined;
|
|
1305
1305
|
}, {
|
|
1306
|
-
type:
|
|
1306
|
+
type: string;
|
|
1307
1307
|
name: string;
|
|
1308
1308
|
scope: "seller" | "admin";
|
|
1309
1309
|
discount: {
|
|
@@ -1366,7 +1366,7 @@ export declare const SCHEMAS: {
|
|
|
1366
1366
|
}, import("zod").ZodTypeAny, "passthrough">;
|
|
1367
1367
|
couponId: string;
|
|
1368
1368
|
couponSnapshot: {
|
|
1369
|
-
type:
|
|
1369
|
+
type: string;
|
|
1370
1370
|
name: string;
|
|
1371
1371
|
scope: "seller" | "admin";
|
|
1372
1372
|
discount: {
|
|
@@ -1406,7 +1406,7 @@ export declare const SCHEMAS: {
|
|
|
1406
1406
|
}, import("zod").ZodTypeAny, "passthrough">;
|
|
1407
1407
|
couponId: string;
|
|
1408
1408
|
couponSnapshot: {
|
|
1409
|
-
type:
|
|
1409
|
+
type: string;
|
|
1410
1410
|
name: string;
|
|
1411
1411
|
scope: "seller" | "admin";
|
|
1412
1412
|
discount: {
|
|
@@ -1452,7 +1452,7 @@ export declare const SCHEMAS: {
|
|
|
1452
1452
|
code: import("zod").ZodString;
|
|
1453
1453
|
name: import("zod").ZodString;
|
|
1454
1454
|
description: import("zod").ZodString;
|
|
1455
|
-
type: import("zod").
|
|
1455
|
+
type: import("zod").ZodString;
|
|
1456
1456
|
scope: import("zod").ZodEnum<["admin", "seller"]>;
|
|
1457
1457
|
storeId: import("zod").ZodOptional<import("zod").ZodString>;
|
|
1458
1458
|
applicableToCollectorDrops: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
@@ -1583,7 +1583,7 @@ export declare const SCHEMAS: {
|
|
|
1583
1583
|
}, "strip", import("zod").ZodTypeAny, {
|
|
1584
1584
|
code: string;
|
|
1585
1585
|
id: string;
|
|
1586
|
-
type:
|
|
1586
|
+
type: string;
|
|
1587
1587
|
description: string;
|
|
1588
1588
|
createdAt: string | Date | import("zod").objectOutputType<{
|
|
1589
1589
|
toDate: import("zod").ZodFunction<import("zod").ZodTuple<[], import("zod").ZodUnknown>, import("zod").ZodDate>;
|
|
@@ -1642,7 +1642,7 @@ export declare const SCHEMAS: {
|
|
|
1642
1642
|
}, {
|
|
1643
1643
|
code: string;
|
|
1644
1644
|
id: string;
|
|
1645
|
-
type:
|
|
1645
|
+
type: string;
|
|
1646
1646
|
description: string;
|
|
1647
1647
|
createdAt: string | Date | import("zod").objectInputType<{
|
|
1648
1648
|
toDate: import("zod").ZodFunction<import("zod").ZodTuple<[], import("zod").ZodUnknown>, import("zod").ZodDate>;
|
|
@@ -2929,6 +2929,7 @@ export declare const SCHEMAS: {
|
|
|
2929
2929
|
productId: import("zod").ZodString;
|
|
2930
2930
|
productTitle: import("zod").ZodString;
|
|
2931
2931
|
listingType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
2932
|
+
reviewType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
2932
2933
|
storeId: import("zod").ZodOptional<import("zod").ZodString>;
|
|
2933
2934
|
storeName: import("zod").ZodOptional<import("zod").ZodString>;
|
|
2934
2935
|
userId: import("zod").ZodString;
|
|
@@ -3038,6 +3039,7 @@ export declare const SCHEMAS: {
|
|
|
3038
3039
|
sellerRepliedAt?: string | Date | import("zod").objectOutputType<{
|
|
3039
3040
|
toDate: import("zod").ZodFunction<import("zod").ZodTuple<[], import("zod").ZodUnknown>, import("zod").ZodDate>;
|
|
3040
3041
|
}, import("zod").ZodTypeAny, "passthrough"> | undefined;
|
|
3042
|
+
reviewType?: string | undefined;
|
|
3041
3043
|
}, {
|
|
3042
3044
|
title: string;
|
|
3043
3045
|
id: string;
|
|
@@ -3086,6 +3088,7 @@ export declare const SCHEMAS: {
|
|
|
3086
3088
|
sellerRepliedAt?: string | Date | import("zod").objectInputType<{
|
|
3087
3089
|
toDate: import("zod").ZodFunction<import("zod").ZodTuple<[], import("zod").ZodUnknown>, import("zod").ZodDate>;
|
|
3088
3090
|
}, import("zod").ZodTypeAny, "passthrough"> | undefined;
|
|
3091
|
+
reviewType?: string | undefined;
|
|
3089
3092
|
}>;
|
|
3090
3093
|
readonly scammerProfiles: import("zod").ZodObject<{
|
|
3091
3094
|
createdAt: import("zod").ZodUnion<[import("zod").ZodDate, import("zod").ZodString, import("zod").ZodObject<{
|