@mohasinac/appkit 4.29.0 โ†’ 4.29.1

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.
@@ -10,5 +10,27 @@ export { getAdminRealtimeDb };
10
10
  * Query docs tagged isTestData:true in a collection. `cutoff: null` returns every
11
11
  * tester-sandbox doc regardless of expiry (manual force-purge); a real Date returns
12
12
  * only the ones past testDataExpiresAt (the scheduled 7-day sweep).
13
+ *
14
+ * ## ๐Ÿ›‘ `isTestData` without `testDataExpiresAt` means PERMANENT, never purge
15
+ *
16
+ * The flag has two uses, and only one of them is a sandbox fixture:
17
+ *
18
+ * ยท a fixture โ€” `isTestData: true` PLUS `testDataExpiresAt`. Disposable,
19
+ * swept on the 7-day cycle. Every doc in `features/tester/seed-data/` is
20
+ * this shape; the invariant was checked across all six files.
21
+ * ยท permanently hidden โ€” `isTestData: true` and NO expiry. Real, permanent
22
+ * content that simply must not reach the public or the sitemap.
23
+ * `store-tester-qa-seller` is the case that forced this distinction.
24
+ *
25
+ * The scheduled path already separates them: `testDataExpiresAt <= cutoff`
26
+ * excludes docs lacking the field. The FORCE path did not โ€” `cutoff: null`
27
+ * drops that clause and returned everything, so `tester:purge-sandbox --force`
28
+ * would have deleted a permanent seed store. Hence the filter below.
29
+ *
30
+ * Filtered in memory rather than as a query clause: a Firestore inequality on
31
+ * `testDataExpiresAt` would exclude every doc missing it, which is the trap
32
+ * documented in CLAUDE.md's anti-pattern table โ€” correct here by luck, wrong
33
+ * the moment someone reuses the shape. In-memory keeps the intent legible, and
34
+ * the read is already bounded at 200.
13
35
  */
14
36
  export declare function getTestDataRefs(db: FirebaseFirestore.Firestore, collection: string, cutoff: Date | null): Promise<FirebaseFirestore.DocumentReference[]>;
@@ -22,6 +22,28 @@ export { getAdminRealtimeDb };
22
22
  * Query docs tagged isTestData:true in a collection. `cutoff: null` returns every
23
23
  * tester-sandbox doc regardless of expiry (manual force-purge); a real Date returns
24
24
  * only the ones past testDataExpiresAt (the scheduled 7-day sweep).
25
+ *
26
+ * ## ๐Ÿ›‘ `isTestData` without `testDataExpiresAt` means PERMANENT, never purge
27
+ *
28
+ * The flag has two uses, and only one of them is a sandbox fixture:
29
+ *
30
+ * ยท a fixture โ€” `isTestData: true` PLUS `testDataExpiresAt`. Disposable,
31
+ * swept on the 7-day cycle. Every doc in `features/tester/seed-data/` is
32
+ * this shape; the invariant was checked across all six files.
33
+ * ยท permanently hidden โ€” `isTestData: true` and NO expiry. Real, permanent
34
+ * content that simply must not reach the public or the sitemap.
35
+ * `store-tester-qa-seller` is the case that forced this distinction.
36
+ *
37
+ * The scheduled path already separates them: `testDataExpiresAt <= cutoff`
38
+ * excludes docs lacking the field. The FORCE path did not โ€” `cutoff: null`
39
+ * drops that clause and returned everything, so `tester:purge-sandbox --force`
40
+ * would have deleted a permanent seed store. Hence the filter below.
41
+ *
42
+ * Filtered in memory rather than as a query clause: a Firestore inequality on
43
+ * `testDataExpiresAt` would exclude every doc missing it, which is the trap
44
+ * documented in CLAUDE.md's anti-pattern table โ€” correct here by luck, wrong
45
+ * the moment someone reuses the shape. In-memory keeps the intent legible, and
46
+ * the read is already bounded at 200.
25
47
  */
26
48
  export async function getTestDataRefs(db, collection, cutoff) {
27
49
  let q = db
@@ -30,5 +52,7 @@ export async function getTestDataRefs(db, collection, cutoff) {
30
52
  if (cutoff)
31
53
  q = q.where("testDataExpiresAt", "<=", cutoff);
32
54
  const snap = await q.limit(200).get();
33
- return snap.docs.map((d) => d.ref);
55
+ return snap.docs
56
+ .filter((d) => cutoff !== null || d.get("testDataExpiresAt") != null)
57
+ .map((d) => d.ref);
34
58
  }
@@ -178,6 +178,24 @@ const _rawstoresSeedData = [
178
178
  },
179
179
  isPublic: true,
180
180
  isVacationMode: false,
181
+ /*
182
+ * Reachable, but never advertised to search engines.
183
+ *
184
+ * This is a QA store โ€” real enough for a tester to exercise seller flows
185
+ * against, and not something that belongs in Google's index. `isTestData`
186
+ * is what the codebase already uses to express that: the sitemap's store
187
+ * fetcher filters it out (it has no viewer), public store listings hide
188
+ * it, and `canViewTestData()` keeps it visible to testers and admins โ€” so
189
+ * the checklist case linking to `/stores/store-tester-qa-seller` still
190
+ * resolves.
191
+ *
192
+ * ๐Ÿ›‘ NOTE the deliberate absence of `testDataExpiresAt`. Every sandbox
193
+ * FIXTURE carries one; this store is permanent. `getTestDataRefs` skips
194
+ * docs without an expiry on the force-purge path precisely so
195
+ * `tester:purge-sandbox --force` cannot delete it. Do not add an expiry
196
+ * here โ€” that would put a permanent seed store in range of the sweep.
197
+ */
198
+ isTestData: true,
181
199
  stats: { totalProducts: 0, itemsSold: 0, totalReviews: 0, averageRating: 0 },
182
200
  capabilities: ["host_preorders", "verified_seller", "create_coupons"],
183
201
  createdAt: daysAgo(1),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mohasinac/appkit",
3
- "version": "4.29.0",
3
+ "version": "4.29.1",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public"