fix(storage): neutral queryConstraints honored by both adapters
Bug: server adapter accepted queryConstraints (orderBy/limit) but ignored them.
Combat log [orderBy('timestamp','desc'), limit(500)] returned ALL logs unordered
in server mode — unbounded growth. No test caught it: shared contract tested
subscribeCollection with 0 constraints; the firebase-only queryConstraint test
never touched the server adapter. Parity gap.
Fix (Plan A — neutral shape):
- index.js: orderBy()/limit() now NEUTRAL builders returning {__type}. Removed
SDK orderBy/limit re-export.
- firebase.js: subscribeCollection translates neutral -> SDK query constraints.
- server.js: applyConstraints() helper sorts/limits client-side (backend returns
all). Constraints stored per collection, applied on initial fetch + WS change.
- contract.js: added 3 queryConstraint tests (orderBy desc, limit, no-constraints)
to SHARED contract — both adapters now run identical assertions.
- firebase.contract.test.js: removed now-redundant firebase-only constraint
block (covered by shared contract).
Data impact: ZERO. Constraints are query-time only, never stored. Combat log
docs keep timestamp field. No Firebase data migration needed.
208 tests green.
This commit is contained in:
+10
-2
@@ -1,5 +1,6 @@
|
||||
// src/storage/index.js — storage factory + SDK re-exports.
|
||||
// STORAGE=firebase (default): adapter wraps SDK. STORAGE=server: backend.
|
||||
// orderBy/limit below = NEUTRAL builders (not SDK passthrough).
|
||||
// App.js imports getStorage() for subscribe; still imports SDK pieces for writes (per-group refactor pending).
|
||||
|
||||
import { initializeApp } from 'firebase/app';
|
||||
@@ -8,7 +9,7 @@ import {
|
||||
} from 'firebase/auth';
|
||||
import {
|
||||
getFirestore, doc, setDoc, getDoc, getDocs, addDoc, collection,
|
||||
onSnapshot, updateDoc, deleteDoc, query, orderBy, limit, writeBatch,
|
||||
onSnapshot, updateDoc, deleteDoc, query, writeBatch,
|
||||
} from 'firebase/firestore';
|
||||
import { initFirebase, createFirebaseStorage } from './firebase';
|
||||
import { createServerStorage } from './server';
|
||||
@@ -38,9 +39,16 @@ export function getStorageMode() {
|
||||
return process.env.REACT_APP_STORAGE || 'firebase';
|
||||
}
|
||||
|
||||
// Neutral query-constraint builders. App builds constraints with these (not
|
||||
// raw SDK), so both adapters read the same shape. firebase adapter translates
|
||||
// neutral -> SDK; server adapter applies client-side. Combat log uses these:
|
||||
// [orderBy('timestamp','desc'), limit(500)]
|
||||
export function orderBy(field, dir) { return { __type: 'orderBy', field, dir }; }
|
||||
export function limit(n) { return { __type: 'limit', n }; }
|
||||
|
||||
export {
|
||||
initializeApp,
|
||||
getAuth, signInAnonymously, onAuthStateChanged, signInWithCustomToken,
|
||||
getFirestore, doc, setDoc, getDoc, getDocs, addDoc, collection,
|
||||
onSnapshot, updateDoc, deleteDoc, query, orderBy, limit, writeBatch,
|
||||
onSnapshot, updateDoc, deleteDoc, query, writeBatch,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user