@ponceca/firestore-sdk 0.1.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/LICENSE +21 -0
- package/README.md +692 -0
- package/dist/app.d.mts +51 -0
- package/dist/app.d.ts +51 -0
- package/dist/app.js +16 -0
- package/dist/app.js.map +1 -0
- package/dist/app.mjs +16 -0
- package/dist/app.mjs.map +1 -0
- package/dist/auth/index.d.mts +43 -0
- package/dist/auth/index.d.ts +43 -0
- package/dist/auth/index.js +18 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/index.mjs +18 -0
- package/dist/auth/index.mjs.map +1 -0
- package/dist/chunk-2RQUHE2K.js +719 -0
- package/dist/chunk-2RQUHE2K.js.map +1 -0
- package/dist/chunk-4CV4JOE5.js +27 -0
- package/dist/chunk-4CV4JOE5.js.map +1 -0
- package/dist/chunk-57XXMSJA.js +65 -0
- package/dist/chunk-57XXMSJA.js.map +1 -0
- package/dist/chunk-6J3LNKUQ.js +213 -0
- package/dist/chunk-6J3LNKUQ.js.map +1 -0
- package/dist/chunk-BXV7KTHB.js +645 -0
- package/dist/chunk-BXV7KTHB.js.map +1 -0
- package/dist/chunk-C3PCJJX4.mjs +645 -0
- package/dist/chunk-C3PCJJX4.mjs.map +1 -0
- package/dist/chunk-C6SKWUQV.mjs +213 -0
- package/dist/chunk-C6SKWUQV.mjs.map +1 -0
- package/dist/chunk-DXPQJR5D.mjs +2469 -0
- package/dist/chunk-DXPQJR5D.mjs.map +1 -0
- package/dist/chunk-MRVKMKSO.mjs +65 -0
- package/dist/chunk-MRVKMKSO.mjs.map +1 -0
- package/dist/chunk-NFEGQTCC.mjs +27 -0
- package/dist/chunk-NFEGQTCC.mjs.map +1 -0
- package/dist/chunk-RSBBZLDE.js +128 -0
- package/dist/chunk-RSBBZLDE.js.map +1 -0
- package/dist/chunk-RZWTSZSJ.js +2469 -0
- package/dist/chunk-RZWTSZSJ.js.map +1 -0
- package/dist/chunk-SZKHE2TQ.mjs +719 -0
- package/dist/chunk-SZKHE2TQ.mjs.map +1 -0
- package/dist/chunk-ZJ4A4Y2T.mjs +128 -0
- package/dist/chunk-ZJ4A4Y2T.mjs.map +1 -0
- package/dist/firestore/index.d.mts +1476 -0
- package/dist/firestore/index.d.ts +1476 -0
- package/dist/firestore/index.js +156 -0
- package/dist/firestore/index.js.map +1 -0
- package/dist/firestore/index.mjs +156 -0
- package/dist/firestore/index.mjs.map +1 -0
- package/dist/http-A2S5CWEV.js +10 -0
- package/dist/http-A2S5CWEV.js.map +1 -0
- package/dist/http-SZFONH6Z.mjs +10 -0
- package/dist/http-SZFONH6Z.mjs.map +1 -0
- package/dist/index.d.mts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +171 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +171 -0
- package/dist/index.mjs.map +1 -0
- package/dist/indexeddb-mutation-queue-5EB7C2D5.js +192 -0
- package/dist/indexeddb-mutation-queue-5EB7C2D5.js.map +1 -0
- package/dist/indexeddb-mutation-queue-M2MAH4E4.mjs +192 -0
- package/dist/indexeddb-mutation-queue-M2MAH4E4.mjs.map +1 -0
- package/dist/indexeddb-store-D23ZY3PR.mjs +162 -0
- package/dist/indexeddb-store-D23ZY3PR.mjs.map +1 -0
- package/dist/indexeddb-store-DNWBZUQE.js +162 -0
- package/dist/indexeddb-store-DNWBZUQE.js.map +1 -0
- package/dist/snapshot-MCQVLVHL.js +22 -0
- package/dist/snapshot-MCQVLVHL.js.map +1 -0
- package/dist/snapshot-ZWZFIFZD.mjs +22 -0
- package/dist/snapshot-ZWZFIFZD.mjs.map +1 -0
- package/dist/types-meoR-Ecp.d.mts +269 -0
- package/dist/types-meoR-Ecp.d.ts +269 -0
- package/package.json +78 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import {
|
|
2
|
+
addDoc,
|
|
3
|
+
and,
|
|
4
|
+
average,
|
|
5
|
+
collection,
|
|
6
|
+
collectionGroup,
|
|
7
|
+
count,
|
|
8
|
+
deleteDoc,
|
|
9
|
+
doc,
|
|
10
|
+
endAt,
|
|
11
|
+
endBefore,
|
|
12
|
+
fastSearch,
|
|
13
|
+
getAggregateFromServer,
|
|
14
|
+
getCountFromServer,
|
|
15
|
+
getDoc,
|
|
16
|
+
getDocFromCache,
|
|
17
|
+
getDocFromServer,
|
|
18
|
+
getDocs,
|
|
19
|
+
getDocsFromCache,
|
|
20
|
+
getDocsFromServer,
|
|
21
|
+
limit,
|
|
22
|
+
limitToLast,
|
|
23
|
+
offset,
|
|
24
|
+
onSnapshot,
|
|
25
|
+
onSnapshotsInSync,
|
|
26
|
+
or,
|
|
27
|
+
orderBy,
|
|
28
|
+
orderByRelevance,
|
|
29
|
+
query,
|
|
30
|
+
queryEqual,
|
|
31
|
+
refEqual,
|
|
32
|
+
runTransaction,
|
|
33
|
+
setDoc,
|
|
34
|
+
snapshotEqual,
|
|
35
|
+
startAfter,
|
|
36
|
+
startAt,
|
|
37
|
+
sum,
|
|
38
|
+
updateDoc,
|
|
39
|
+
where,
|
|
40
|
+
whereContains,
|
|
41
|
+
whereFuzzy,
|
|
42
|
+
whereSearch,
|
|
43
|
+
whereSimilar,
|
|
44
|
+
withConverter,
|
|
45
|
+
writeBatch
|
|
46
|
+
} from "./chunk-DXPQJR5D.mjs";
|
|
47
|
+
import {
|
|
48
|
+
getAuth,
|
|
49
|
+
onAuthStateChanged,
|
|
50
|
+
signInWithCustomToken,
|
|
51
|
+
signOut
|
|
52
|
+
} from "./chunk-ZJ4A4Y2T.mjs";
|
|
53
|
+
import {
|
|
54
|
+
clearIndexedDbPersistence,
|
|
55
|
+
connectFirestoreEmulator,
|
|
56
|
+
disableNetwork,
|
|
57
|
+
enableIndexedDbPersistence,
|
|
58
|
+
enableMultiTabIndexedDbPersistence,
|
|
59
|
+
enableNetwork,
|
|
60
|
+
getAuthToken,
|
|
61
|
+
getFirestore,
|
|
62
|
+
initializeFirestore,
|
|
63
|
+
setAuthToken,
|
|
64
|
+
terminate,
|
|
65
|
+
waitForPendingWrites
|
|
66
|
+
} from "./chunk-SZKHE2TQ.mjs";
|
|
67
|
+
import {
|
|
68
|
+
deleteApp,
|
|
69
|
+
getApp,
|
|
70
|
+
getApps,
|
|
71
|
+
init_app,
|
|
72
|
+
initializeApp
|
|
73
|
+
} from "./chunk-MRVKMKSO.mjs";
|
|
74
|
+
import "./chunk-C6SKWUQV.mjs";
|
|
75
|
+
import {
|
|
76
|
+
Bytes,
|
|
77
|
+
FieldPath,
|
|
78
|
+
GeoPoint,
|
|
79
|
+
Timestamp,
|
|
80
|
+
VectorValue,
|
|
81
|
+
arrayRemove,
|
|
82
|
+
arrayUnion,
|
|
83
|
+
deleteField,
|
|
84
|
+
documentId,
|
|
85
|
+
increment,
|
|
86
|
+
serverTimestamp,
|
|
87
|
+
vector
|
|
88
|
+
} from "./chunk-C3PCJJX4.mjs";
|
|
89
|
+
import "./chunk-NFEGQTCC.mjs";
|
|
90
|
+
|
|
91
|
+
// src/index.ts
|
|
92
|
+
init_app();
|
|
93
|
+
export {
|
|
94
|
+
Bytes,
|
|
95
|
+
FieldPath as FieldPathClass,
|
|
96
|
+
GeoPoint,
|
|
97
|
+
Timestamp,
|
|
98
|
+
VectorValue,
|
|
99
|
+
addDoc,
|
|
100
|
+
and,
|
|
101
|
+
arrayRemove,
|
|
102
|
+
arrayUnion,
|
|
103
|
+
average,
|
|
104
|
+
clearIndexedDbPersistence,
|
|
105
|
+
collection,
|
|
106
|
+
collectionGroup,
|
|
107
|
+
connectFirestoreEmulator,
|
|
108
|
+
count,
|
|
109
|
+
deleteApp,
|
|
110
|
+
deleteDoc,
|
|
111
|
+
deleteField,
|
|
112
|
+
disableNetwork,
|
|
113
|
+
doc,
|
|
114
|
+
documentId,
|
|
115
|
+
enableIndexedDbPersistence,
|
|
116
|
+
enableMultiTabIndexedDbPersistence,
|
|
117
|
+
enableNetwork,
|
|
118
|
+
endAt,
|
|
119
|
+
endBefore,
|
|
120
|
+
fastSearch,
|
|
121
|
+
getAggregateFromServer,
|
|
122
|
+
getApp,
|
|
123
|
+
getApps,
|
|
124
|
+
getAuth,
|
|
125
|
+
getAuthToken,
|
|
126
|
+
getCountFromServer,
|
|
127
|
+
getDoc,
|
|
128
|
+
getDocFromCache,
|
|
129
|
+
getDocFromServer,
|
|
130
|
+
getDocs,
|
|
131
|
+
getDocsFromCache,
|
|
132
|
+
getDocsFromServer,
|
|
133
|
+
getFirestore,
|
|
134
|
+
increment,
|
|
135
|
+
initializeApp,
|
|
136
|
+
initializeFirestore,
|
|
137
|
+
limit,
|
|
138
|
+
limitToLast,
|
|
139
|
+
offset,
|
|
140
|
+
onAuthStateChanged,
|
|
141
|
+
onSnapshot,
|
|
142
|
+
onSnapshotsInSync,
|
|
143
|
+
or,
|
|
144
|
+
orderBy,
|
|
145
|
+
orderByRelevance,
|
|
146
|
+
query,
|
|
147
|
+
queryEqual,
|
|
148
|
+
refEqual,
|
|
149
|
+
runTransaction,
|
|
150
|
+
serverTimestamp,
|
|
151
|
+
setAuthToken,
|
|
152
|
+
setDoc,
|
|
153
|
+
signInWithCustomToken,
|
|
154
|
+
signOut,
|
|
155
|
+
snapshotEqual,
|
|
156
|
+
startAfter,
|
|
157
|
+
startAt,
|
|
158
|
+
sum,
|
|
159
|
+
terminate,
|
|
160
|
+
updateDoc,
|
|
161
|
+
vector,
|
|
162
|
+
waitForPendingWrites,
|
|
163
|
+
where,
|
|
164
|
+
whereContains,
|
|
165
|
+
whereFuzzy,
|
|
166
|
+
whereSearch,
|
|
167
|
+
whereSimilar,
|
|
168
|
+
withConverter,
|
|
169
|
+
writeBatch
|
|
170
|
+
};
|
|
171
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\r\n * Firestore SDK - Export Principal\r\n * 100% Compatible con Firebase v9+ modular API\r\n * \r\n * @example\r\n * ```typescript\r\n * import { initializeApp } from '@ponceca/firestore-sdk';\r\n * import { \r\n * getFirestore,\r\n * connectFirestoreEmulator,\r\n * collection, \r\n * doc, \r\n * getDoc, \r\n * setDoc,\r\n * query,\r\n * where,\r\n * getDocs,\r\n * onSnapshot\r\n * } from '@ponceca/firestore-sdk/firestore';\r\n * \r\n * // Inicializar app (idéntico a Firebase)\r\n * const app = initializeApp({\r\n * projectId: 'my-project'\r\n * });\r\n * \r\n * // Obtener Firestore\r\n * const db = getFirestore(app);\r\n * \r\n * // Conectar a tu servidor (igual que Firebase emulator)\r\n * connectFirestoreEmulator(db, 'localhost', 3000);\r\n * \r\n * // Crear referencia a documento\r\n * const userRef = doc(db, 'users', 'user123');\r\n * \r\n * // Escribir documento\r\n * await setDoc(userRef, {\r\n * name: 'Juan',\r\n * age: 25\r\n * });\r\n * \r\n * // Leer documento\r\n * const snapshot = await getDoc(userRef);\r\n * console.log(snapshot.data());\r\n * \r\n * // Query con filtros\r\n * const q = query(\r\n * collection(db, 'users'),\r\n * where('age', '>=', 18),\r\n * orderBy('age')\r\n * );\r\n * const results = await getDocs(q);\r\n * \r\n * // Listener en tiempo real\r\n * const unsubscribe = onSnapshot(userRef, (doc) => {\r\n * console.log('Cambio:', doc.data());\r\n * });\r\n * ```\r\n */\r\n\r\n// ============================================================================\r\n// App\r\n// ============================================================================\r\n\r\nexport {\r\n initializeApp,\r\n getApp,\r\n getApps,\r\n deleteApp,\r\n} from './app';\r\n\r\nexport type {\r\n FirebaseApp,\r\n FirebaseOptions,\r\n} from './app';\r\n\r\n// ============================================================================\r\n// Auth\r\n// ============================================================================\r\n\r\nexport {\r\n getAuth,\r\n signInWithCustomToken,\r\n signOut,\r\n onAuthStateChanged,\r\n} from './auth';\r\n\r\nexport type {\r\n Auth,\r\n User,\r\n} from './auth';\r\n\r\n// ============================================================================\r\n// Firestore (re-export para conveniencia)\r\n// ============================================================================\r\n\r\n// Nota: Se recomienda importar desde '@ponceca/firestore-sdk/firestore'\r\n// para mejor tree-shaking\r\n\r\nexport {\r\n getFirestore,\r\n initializeFirestore,\r\n connectFirestoreEmulator,\r\n setAuthToken,\r\n getAuthToken,\r\n doc,\r\n collection,\r\n getDoc,\r\n getDocFromCache,\r\n getDocFromServer,\r\n setDoc,\r\n updateDoc,\r\n deleteDoc,\r\n addDoc,\r\n query,\r\n where,\r\n orderBy,\r\n limit,\r\n limitToLast,\r\n startAt,\r\n startAfter,\r\n endAt,\r\n endBefore,\r\n getDocs,\r\n getDocsFromCache,\r\n getDocsFromServer,\r\n onSnapshot,\r\n serverTimestamp,\r\n increment,\r\n arrayUnion,\r\n arrayRemove,\r\n deleteField,\r\n writeBatch,\r\n runTransaction,\r\n terminate,\r\n // Compatibilidad Offline/Network (stubs para API compatible)\r\n clearIndexedDbPersistence,\r\n enableIndexedDbPersistence,\r\n enableMultiTabIndexedDbPersistence,\r\n enableNetwork,\r\n disableNetwork,\r\n waitForPendingWrites,\r\n // Tipos especiales\r\n Timestamp,\r\n GeoPoint,\r\n Bytes,\r\n FieldPathClass,\r\n documentId,\r\n VectorValue,\r\n vector,\r\n // Queries avanzadas\r\n and,\r\n or,\r\n collectionGroup,\r\n // Agregaciones\r\n count,\r\n sum,\r\n average,\r\n getCountFromServer,\r\n getAggregateFromServer,\r\n // Búsqueda avanzada (extensiones propias)\r\n whereSearch,\r\n whereContains,\r\n whereFuzzy,\r\n whereSimilar,\r\n orderByRelevance,\r\n offset,\r\n fastSearch,\r\n // Utilidades\r\n withConverter,\r\n refEqual,\r\n queryEqual,\r\n snapshotEqual,\r\n onSnapshotsInSync,\r\n} from './firestore';\r\n\r\n// Tipos\r\nexport type {\r\n Firestore,\r\n FirestoreSettings,\r\n AuthTokenProvider,\r\n FieldPath,\r\n FieldValue,\r\n Unsubscribe,\r\n ListenSource,\r\n WriteBatch,\r\n Transaction,\r\n // Referencias y Snapshots\r\n DocumentReference,\r\n CollectionReference,\r\n Query,\r\n DocumentSnapshot,\r\n QuerySnapshot,\r\n DocumentData,\r\n DocumentChange,\r\n // Errores\r\n FirestoreError,\r\n FirestoreErrorCode,\r\n // Tipos avanzados\r\n AndConstraint,\r\n OrConstraint,\r\n CompositeFilterConstraint,\r\n CollectionGroupReference,\r\n AggregateField,\r\n AggregateSpec,\r\n AggregateQuerySnapshot,\r\n FastSearchOptions,\r\n FastSearchResponse,\r\n FastSearchResult,\r\n FirestoreDataConverter,\r\n QueryDocumentSnapshot,\r\n} from './firestore';\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+DA;","names":[]}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }require('./chunk-4CV4JOE5.js');
|
|
2
|
+
|
|
3
|
+
// src/persistence/indexeddb-mutation-queue.ts
|
|
4
|
+
var DB_VERSION = 1;
|
|
5
|
+
var MUTATIONS_STORE = "mutations";
|
|
6
|
+
var mutationCounter = 0;
|
|
7
|
+
var IndexedDBMutationQueue = class _IndexedDBMutationQueue {
|
|
8
|
+
constructor(projectId) {
|
|
9
|
+
this.db = null;
|
|
10
|
+
this._initPromise = null;
|
|
11
|
+
this.pendingWaiters = [];
|
|
12
|
+
this.dbName = `firestore_mutations_${projectId}`;
|
|
13
|
+
}
|
|
14
|
+
// ===========================================================================
|
|
15
|
+
// INICIALIZACIÓN
|
|
16
|
+
// ===========================================================================
|
|
17
|
+
init() {
|
|
18
|
+
if (this.db) return Promise.resolve();
|
|
19
|
+
if (this._initPromise) return this._initPromise;
|
|
20
|
+
this._initPromise = new Promise((resolve, reject) => {
|
|
21
|
+
const request = indexedDB.open(this.dbName, DB_VERSION);
|
|
22
|
+
request.onupgradeneeded = () => {
|
|
23
|
+
const db = request.result;
|
|
24
|
+
if (!db.objectStoreNames.contains(MUTATIONS_STORE)) {
|
|
25
|
+
const store = db.createObjectStore(MUTATIONS_STORE, { keyPath: "id" });
|
|
26
|
+
store.createIndex("by_timestamp", "timestamp", { unique: false });
|
|
27
|
+
store.createIndex("by_path", "path", { unique: false });
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
request.onsuccess = () => {
|
|
31
|
+
this.db = request.result;
|
|
32
|
+
resolve();
|
|
33
|
+
};
|
|
34
|
+
request.onerror = () => {
|
|
35
|
+
reject(new Error(`IndexedDB mutations open failed: ${_optionalChain([request, 'access', _ => _.error, 'optionalAccess', _2 => _2.message])}`));
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
return this._initPromise;
|
|
39
|
+
}
|
|
40
|
+
/** Helper transaccional */
|
|
41
|
+
async tx(mode, fn) {
|
|
42
|
+
await this.init();
|
|
43
|
+
return new Promise((resolve, reject) => {
|
|
44
|
+
const tx = this.db.transaction(MUTATIONS_STORE, mode);
|
|
45
|
+
const store = tx.objectStore(MUTATIONS_STORE);
|
|
46
|
+
const request = fn(store);
|
|
47
|
+
request.onsuccess = () => resolve(request.result);
|
|
48
|
+
request.onerror = () => reject(request.error);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
/** Helper: obtiene todas las mutaciones ordenadas por timestamp */
|
|
52
|
+
async getAllSorted() {
|
|
53
|
+
await this.init();
|
|
54
|
+
return new Promise((resolve, reject) => {
|
|
55
|
+
const tx = this.db.transaction(MUTATIONS_STORE, "readonly");
|
|
56
|
+
const store = tx.objectStore(MUTATIONS_STORE);
|
|
57
|
+
const index = store.index("by_timestamp");
|
|
58
|
+
const request = index.getAll();
|
|
59
|
+
request.onsuccess = () => resolve(request.result);
|
|
60
|
+
request.onerror = () => reject(request.error);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
// ===========================================================================
|
|
64
|
+
// API PRINCIPAL
|
|
65
|
+
// ===========================================================================
|
|
66
|
+
async add(type, path, data, options) {
|
|
67
|
+
const id = `mutation_${++mutationCounter}_${Date.now()}`;
|
|
68
|
+
const mutation = {
|
|
69
|
+
id,
|
|
70
|
+
type,
|
|
71
|
+
path,
|
|
72
|
+
data: data ? JSON.parse(JSON.stringify(data)) : null,
|
|
73
|
+
options: options ? { ...options } : void 0,
|
|
74
|
+
timestamp: Date.now()
|
|
75
|
+
};
|
|
76
|
+
await this.tx("readwrite", (store) => store.put(mutation));
|
|
77
|
+
return id;
|
|
78
|
+
}
|
|
79
|
+
async peek() {
|
|
80
|
+
const all = await this.getAllSorted();
|
|
81
|
+
return all[0];
|
|
82
|
+
}
|
|
83
|
+
async shift() {
|
|
84
|
+
const all = await this.getAllSorted();
|
|
85
|
+
const first = all[0];
|
|
86
|
+
if (!first) return void 0;
|
|
87
|
+
await this.tx("readwrite", (store) => store.delete(first.id));
|
|
88
|
+
if (all.length <= 1) {
|
|
89
|
+
this.notifyWaiters();
|
|
90
|
+
}
|
|
91
|
+
return first;
|
|
92
|
+
}
|
|
93
|
+
async remove(id) {
|
|
94
|
+
const existing = await this.tx(
|
|
95
|
+
"readonly",
|
|
96
|
+
(store) => store.get(id)
|
|
97
|
+
);
|
|
98
|
+
if (!existing) return false;
|
|
99
|
+
await this.tx("readwrite", (store) => store.delete(id));
|
|
100
|
+
const count = await this.tx("readonly", (store) => store.count());
|
|
101
|
+
if (count === 0) {
|
|
102
|
+
this.notifyWaiters();
|
|
103
|
+
}
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
async hasPendingForPath(path) {
|
|
107
|
+
await this.init();
|
|
108
|
+
return new Promise((resolve, reject) => {
|
|
109
|
+
const tx = this.db.transaction(MUTATIONS_STORE, "readonly");
|
|
110
|
+
const store = tx.objectStore(MUTATIONS_STORE);
|
|
111
|
+
const index = store.index("by_path");
|
|
112
|
+
const request = index.count(IDBKeyRange.only(path));
|
|
113
|
+
request.onsuccess = () => resolve(request.result > 0);
|
|
114
|
+
request.onerror = () => reject(request.error);
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
async getForPath(path) {
|
|
118
|
+
await this.init();
|
|
119
|
+
return new Promise((resolve, reject) => {
|
|
120
|
+
const tx = this.db.transaction(MUTATIONS_STORE, "readonly");
|
|
121
|
+
const store = tx.objectStore(MUTATIONS_STORE);
|
|
122
|
+
const index = store.index("by_path");
|
|
123
|
+
const request = index.getAll(IDBKeyRange.only(path));
|
|
124
|
+
request.onsuccess = () => {
|
|
125
|
+
const results = request.result.sort((a, b) => a.timestamp - b.timestamp);
|
|
126
|
+
resolve(results);
|
|
127
|
+
};
|
|
128
|
+
request.onerror = () => reject(request.error);
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
async getForCollection(collectionPath) {
|
|
132
|
+
const all = await this.getAllSorted();
|
|
133
|
+
const prefix = collectionPath + "/";
|
|
134
|
+
return all.filter((m) => m.path.startsWith(prefix) && !m.path.substring(prefix.length).includes("/"));
|
|
135
|
+
}
|
|
136
|
+
async getAll() {
|
|
137
|
+
return this.getAllSorted();
|
|
138
|
+
}
|
|
139
|
+
get size() {
|
|
140
|
+
return this.tx("readonly", (store) => store.count());
|
|
141
|
+
}
|
|
142
|
+
get isEmpty() {
|
|
143
|
+
return this.size.then((s) => s === 0);
|
|
144
|
+
}
|
|
145
|
+
async clear() {
|
|
146
|
+
await this.tx("readwrite", (store) => store.clear());
|
|
147
|
+
this.notifyWaiters();
|
|
148
|
+
}
|
|
149
|
+
waitForEmpty() {
|
|
150
|
+
return this.isEmpty.then((empty) => {
|
|
151
|
+
if (empty) return;
|
|
152
|
+
return new Promise((resolve) => {
|
|
153
|
+
this.pendingWaiters.push(resolve);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
// ===========================================================================
|
|
158
|
+
// HELPERS
|
|
159
|
+
// ===========================================================================
|
|
160
|
+
notifyWaiters() {
|
|
161
|
+
const waiters = this.pendingWaiters.splice(0);
|
|
162
|
+
for (const resolve of waiters) {
|
|
163
|
+
resolve();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/** Cierra la conexión */
|
|
167
|
+
close() {
|
|
168
|
+
if (this.db) {
|
|
169
|
+
this.db.close();
|
|
170
|
+
this.db = null;
|
|
171
|
+
this._initPromise = null;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/** Borra toda la DB de mutaciones (instancia) */
|
|
175
|
+
async deleteDatabase() {
|
|
176
|
+
this.close();
|
|
177
|
+
return _IndexedDBMutationQueue.deleteDatabase(this.dbName);
|
|
178
|
+
}
|
|
179
|
+
/** Borra una base de datos de mutaciones IndexedDB por projectId (estático) */
|
|
180
|
+
static deleteDatabase(projectId) {
|
|
181
|
+
const dbName = projectId.startsWith("firestore_mutations_") ? projectId : `firestore_mutations_${projectId}`;
|
|
182
|
+
return new Promise((resolve, reject) => {
|
|
183
|
+
const request = indexedDB.deleteDatabase(dbName);
|
|
184
|
+
request.onsuccess = () => resolve();
|
|
185
|
+
request.onerror = () => reject(request.error);
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
exports.IndexedDBMutationQueue = IndexedDBMutationQueue;
|
|
192
|
+
//# sourceMappingURL=indexeddb-mutation-queue-5EB7C2D5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["c:\\Users\\ponce\\Documents\\codigo-2026\\firestore\\sdk\\js\\dist\\indexeddb-mutation-queue-5EB7C2D5.js"],"names":[],"mappings":"AAAA,4mBAA4B;AAC5B;AACA;AACA,IAAI,WAAW,EAAE,CAAC;AAClB,IAAI,gBAAgB,EAAE,WAAW;AACjC,IAAI,gBAAgB,EAAE,CAAC;AACvB,IAAI,uBAAuB,EAAE,MAAM,wBAAwB;AAC3D,EAAE,WAAW,CAAC,SAAS,EAAE;AACzB,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI;AAClB,IAAI,IAAI,CAAC,aAAa,EAAE,IAAI;AAC5B,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC;AAC5B,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC,oBAAoB,EAAE,SAAS,CAAC,CAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA","file":"C:\\Users\\ponce\\Documents\\codigo-2026\\firestore\\sdk\\js\\dist\\indexeddb-mutation-queue-5EB7C2D5.js","sourcesContent":[null]}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import "./chunk-NFEGQTCC.mjs";
|
|
2
|
+
|
|
3
|
+
// src/persistence/indexeddb-mutation-queue.ts
|
|
4
|
+
var DB_VERSION = 1;
|
|
5
|
+
var MUTATIONS_STORE = "mutations";
|
|
6
|
+
var mutationCounter = 0;
|
|
7
|
+
var IndexedDBMutationQueue = class _IndexedDBMutationQueue {
|
|
8
|
+
constructor(projectId) {
|
|
9
|
+
this.db = null;
|
|
10
|
+
this._initPromise = null;
|
|
11
|
+
this.pendingWaiters = [];
|
|
12
|
+
this.dbName = `firestore_mutations_${projectId}`;
|
|
13
|
+
}
|
|
14
|
+
// ===========================================================================
|
|
15
|
+
// INICIALIZACIÓN
|
|
16
|
+
// ===========================================================================
|
|
17
|
+
init() {
|
|
18
|
+
if (this.db) return Promise.resolve();
|
|
19
|
+
if (this._initPromise) return this._initPromise;
|
|
20
|
+
this._initPromise = new Promise((resolve, reject) => {
|
|
21
|
+
const request = indexedDB.open(this.dbName, DB_VERSION);
|
|
22
|
+
request.onupgradeneeded = () => {
|
|
23
|
+
const db = request.result;
|
|
24
|
+
if (!db.objectStoreNames.contains(MUTATIONS_STORE)) {
|
|
25
|
+
const store = db.createObjectStore(MUTATIONS_STORE, { keyPath: "id" });
|
|
26
|
+
store.createIndex("by_timestamp", "timestamp", { unique: false });
|
|
27
|
+
store.createIndex("by_path", "path", { unique: false });
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
request.onsuccess = () => {
|
|
31
|
+
this.db = request.result;
|
|
32
|
+
resolve();
|
|
33
|
+
};
|
|
34
|
+
request.onerror = () => {
|
|
35
|
+
reject(new Error(`IndexedDB mutations open failed: ${request.error?.message}`));
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
return this._initPromise;
|
|
39
|
+
}
|
|
40
|
+
/** Helper transaccional */
|
|
41
|
+
async tx(mode, fn) {
|
|
42
|
+
await this.init();
|
|
43
|
+
return new Promise((resolve, reject) => {
|
|
44
|
+
const tx = this.db.transaction(MUTATIONS_STORE, mode);
|
|
45
|
+
const store = tx.objectStore(MUTATIONS_STORE);
|
|
46
|
+
const request = fn(store);
|
|
47
|
+
request.onsuccess = () => resolve(request.result);
|
|
48
|
+
request.onerror = () => reject(request.error);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
/** Helper: obtiene todas las mutaciones ordenadas por timestamp */
|
|
52
|
+
async getAllSorted() {
|
|
53
|
+
await this.init();
|
|
54
|
+
return new Promise((resolve, reject) => {
|
|
55
|
+
const tx = this.db.transaction(MUTATIONS_STORE, "readonly");
|
|
56
|
+
const store = tx.objectStore(MUTATIONS_STORE);
|
|
57
|
+
const index = store.index("by_timestamp");
|
|
58
|
+
const request = index.getAll();
|
|
59
|
+
request.onsuccess = () => resolve(request.result);
|
|
60
|
+
request.onerror = () => reject(request.error);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
// ===========================================================================
|
|
64
|
+
// API PRINCIPAL
|
|
65
|
+
// ===========================================================================
|
|
66
|
+
async add(type, path, data, options) {
|
|
67
|
+
const id = `mutation_${++mutationCounter}_${Date.now()}`;
|
|
68
|
+
const mutation = {
|
|
69
|
+
id,
|
|
70
|
+
type,
|
|
71
|
+
path,
|
|
72
|
+
data: data ? JSON.parse(JSON.stringify(data)) : null,
|
|
73
|
+
options: options ? { ...options } : void 0,
|
|
74
|
+
timestamp: Date.now()
|
|
75
|
+
};
|
|
76
|
+
await this.tx("readwrite", (store) => store.put(mutation));
|
|
77
|
+
return id;
|
|
78
|
+
}
|
|
79
|
+
async peek() {
|
|
80
|
+
const all = await this.getAllSorted();
|
|
81
|
+
return all[0];
|
|
82
|
+
}
|
|
83
|
+
async shift() {
|
|
84
|
+
const all = await this.getAllSorted();
|
|
85
|
+
const first = all[0];
|
|
86
|
+
if (!first) return void 0;
|
|
87
|
+
await this.tx("readwrite", (store) => store.delete(first.id));
|
|
88
|
+
if (all.length <= 1) {
|
|
89
|
+
this.notifyWaiters();
|
|
90
|
+
}
|
|
91
|
+
return first;
|
|
92
|
+
}
|
|
93
|
+
async remove(id) {
|
|
94
|
+
const existing = await this.tx(
|
|
95
|
+
"readonly",
|
|
96
|
+
(store) => store.get(id)
|
|
97
|
+
);
|
|
98
|
+
if (!existing) return false;
|
|
99
|
+
await this.tx("readwrite", (store) => store.delete(id));
|
|
100
|
+
const count = await this.tx("readonly", (store) => store.count());
|
|
101
|
+
if (count === 0) {
|
|
102
|
+
this.notifyWaiters();
|
|
103
|
+
}
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
async hasPendingForPath(path) {
|
|
107
|
+
await this.init();
|
|
108
|
+
return new Promise((resolve, reject) => {
|
|
109
|
+
const tx = this.db.transaction(MUTATIONS_STORE, "readonly");
|
|
110
|
+
const store = tx.objectStore(MUTATIONS_STORE);
|
|
111
|
+
const index = store.index("by_path");
|
|
112
|
+
const request = index.count(IDBKeyRange.only(path));
|
|
113
|
+
request.onsuccess = () => resolve(request.result > 0);
|
|
114
|
+
request.onerror = () => reject(request.error);
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
async getForPath(path) {
|
|
118
|
+
await this.init();
|
|
119
|
+
return new Promise((resolve, reject) => {
|
|
120
|
+
const tx = this.db.transaction(MUTATIONS_STORE, "readonly");
|
|
121
|
+
const store = tx.objectStore(MUTATIONS_STORE);
|
|
122
|
+
const index = store.index("by_path");
|
|
123
|
+
const request = index.getAll(IDBKeyRange.only(path));
|
|
124
|
+
request.onsuccess = () => {
|
|
125
|
+
const results = request.result.sort((a, b) => a.timestamp - b.timestamp);
|
|
126
|
+
resolve(results);
|
|
127
|
+
};
|
|
128
|
+
request.onerror = () => reject(request.error);
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
async getForCollection(collectionPath) {
|
|
132
|
+
const all = await this.getAllSorted();
|
|
133
|
+
const prefix = collectionPath + "/";
|
|
134
|
+
return all.filter((m) => m.path.startsWith(prefix) && !m.path.substring(prefix.length).includes("/"));
|
|
135
|
+
}
|
|
136
|
+
async getAll() {
|
|
137
|
+
return this.getAllSorted();
|
|
138
|
+
}
|
|
139
|
+
get size() {
|
|
140
|
+
return this.tx("readonly", (store) => store.count());
|
|
141
|
+
}
|
|
142
|
+
get isEmpty() {
|
|
143
|
+
return this.size.then((s) => s === 0);
|
|
144
|
+
}
|
|
145
|
+
async clear() {
|
|
146
|
+
await this.tx("readwrite", (store) => store.clear());
|
|
147
|
+
this.notifyWaiters();
|
|
148
|
+
}
|
|
149
|
+
waitForEmpty() {
|
|
150
|
+
return this.isEmpty.then((empty) => {
|
|
151
|
+
if (empty) return;
|
|
152
|
+
return new Promise((resolve) => {
|
|
153
|
+
this.pendingWaiters.push(resolve);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
// ===========================================================================
|
|
158
|
+
// HELPERS
|
|
159
|
+
// ===========================================================================
|
|
160
|
+
notifyWaiters() {
|
|
161
|
+
const waiters = this.pendingWaiters.splice(0);
|
|
162
|
+
for (const resolve of waiters) {
|
|
163
|
+
resolve();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/** Cierra la conexión */
|
|
167
|
+
close() {
|
|
168
|
+
if (this.db) {
|
|
169
|
+
this.db.close();
|
|
170
|
+
this.db = null;
|
|
171
|
+
this._initPromise = null;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/** Borra toda la DB de mutaciones (instancia) */
|
|
175
|
+
async deleteDatabase() {
|
|
176
|
+
this.close();
|
|
177
|
+
return _IndexedDBMutationQueue.deleteDatabase(this.dbName);
|
|
178
|
+
}
|
|
179
|
+
/** Borra una base de datos de mutaciones IndexedDB por projectId (estático) */
|
|
180
|
+
static deleteDatabase(projectId) {
|
|
181
|
+
const dbName = projectId.startsWith("firestore_mutations_") ? projectId : `firestore_mutations_${projectId}`;
|
|
182
|
+
return new Promise((resolve, reject) => {
|
|
183
|
+
const request = indexedDB.deleteDatabase(dbName);
|
|
184
|
+
request.onsuccess = () => resolve();
|
|
185
|
+
request.onerror = () => reject(request.error);
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
export {
|
|
190
|
+
IndexedDBMutationQueue
|
|
191
|
+
};
|
|
192
|
+
//# sourceMappingURL=indexeddb-mutation-queue-M2MAH4E4.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/persistence/indexeddb-mutation-queue.ts"],"sourcesContent":["/**\r\n * Firestore SDK - IndexedDB Mutation Queue\r\n * Cola de escrituras pendientes persistida en IndexedDB.\r\n * Sobrevive recargas de página — las mutaciones se sincronizan cuando la app reabre.\r\n */\r\n\r\nimport type { DocumentData } from '../firestore/types';\r\nimport type { Mutation, MutationType, MutationStore } from './types';\r\n\r\nconst DB_VERSION = 1;\r\nconst MUTATIONS_STORE = 'mutations';\r\n\r\n/** Contador para IDs únicos */\r\nlet mutationCounter = 0;\r\n\r\n/**\r\n * Cola de mutaciones persistida en IndexedDB.\r\n * Mantiene escrituras pendientes en orden FIFO con persistencia entre sesiones.\r\n */\r\nexport class IndexedDBMutationQueue implements MutationStore {\r\n private db: IDBDatabase | null = null;\r\n private readonly dbName: string;\r\n private _initPromise: Promise<void> | null = null;\r\n private readonly pendingWaiters: Array<() => void> = [];\r\n\r\n constructor(projectId: string) {\r\n this.dbName = `firestore_mutations_${projectId}`;\r\n }\r\n\r\n // ===========================================================================\r\n // INICIALIZACIÓN\r\n // ===========================================================================\r\n\r\n init(): Promise<void> {\r\n if (this.db) return Promise.resolve();\r\n if (this._initPromise) return this._initPromise;\r\n\r\n this._initPromise = new Promise<void>((resolve, reject) => {\r\n const request = indexedDB.open(this.dbName, DB_VERSION);\r\n\r\n request.onupgradeneeded = () => {\r\n const db = request.result;\r\n if (!db.objectStoreNames.contains(MUTATIONS_STORE)) {\r\n const store = db.createObjectStore(MUTATIONS_STORE, { keyPath: 'id' });\r\n // Índice por timestamp para orden FIFO\r\n store.createIndex('by_timestamp', 'timestamp', { unique: false });\r\n // Índice por path para queries rápidas\r\n store.createIndex('by_path', 'path', { unique: false });\r\n }\r\n };\r\n\r\n request.onsuccess = () => {\r\n this.db = request.result;\r\n resolve();\r\n };\r\n\r\n request.onerror = () => {\r\n reject(new Error(`IndexedDB mutations open failed: ${request.error?.message}`));\r\n };\r\n });\r\n\r\n return this._initPromise;\r\n }\r\n\r\n /** Helper transaccional */\r\n private async tx<T>(\r\n mode: IDBTransactionMode,\r\n fn: (store: IDBObjectStore) => IDBRequest<T>,\r\n ): Promise<T> {\r\n await this.init();\r\n return new Promise<T>((resolve, reject) => {\r\n const tx = this.db!.transaction(MUTATIONS_STORE, mode);\r\n const store = tx.objectStore(MUTATIONS_STORE);\r\n const request = fn(store);\r\n request.onsuccess = () => resolve(request.result);\r\n request.onerror = () => reject(request.error);\r\n });\r\n }\r\n\r\n /** Helper: obtiene todas las mutaciones ordenadas por timestamp */\r\n private async getAllSorted(): Promise<Mutation[]> {\r\n await this.init();\r\n return new Promise<Mutation[]>((resolve, reject) => {\r\n const tx = this.db!.transaction(MUTATIONS_STORE, 'readonly');\r\n const store = tx.objectStore(MUTATIONS_STORE);\r\n const index = store.index('by_timestamp');\r\n const request = index.getAll();\r\n request.onsuccess = () => resolve(request.result as Mutation[]);\r\n request.onerror = () => reject(request.error);\r\n });\r\n }\r\n\r\n // ===========================================================================\r\n // API PRINCIPAL\r\n // ===========================================================================\r\n\r\n async add(\r\n type: MutationType,\r\n path: string,\r\n data: DocumentData | null,\r\n options?: { merge?: boolean; mergeFields?: string[] },\r\n ): Promise<string> {\r\n const id = `mutation_${++mutationCounter}_${Date.now()}`;\r\n const mutation: Mutation = {\r\n id,\r\n type,\r\n path,\r\n data: data ? JSON.parse(JSON.stringify(data)) : null,\r\n options: options ? { ...options } : undefined,\r\n timestamp: Date.now(),\r\n };\r\n await this.tx('readwrite', (store) => store.put(mutation));\r\n return id;\r\n }\r\n\r\n async peek(): Promise<Mutation | undefined> {\r\n const all = await this.getAllSorted();\r\n return all[0];\r\n }\r\n\r\n async shift(): Promise<Mutation | undefined> {\r\n const all = await this.getAllSorted();\r\n const first = all[0];\r\n if (!first) return undefined;\r\n\r\n await this.tx('readwrite', (store) => store.delete(first.id));\r\n\r\n // Notificar waiters si la cola quedó vacía\r\n if (all.length <= 1) {\r\n this.notifyWaiters();\r\n }\r\n return first;\r\n }\r\n\r\n async remove(id: string): Promise<boolean> {\r\n const existing = await this.tx<Mutation | undefined>(\r\n 'readonly', (store) => store.get(id),\r\n );\r\n if (!existing) return false;\r\n\r\n await this.tx('readwrite', (store) => store.delete(id));\r\n\r\n const count = await this.tx<number>('readonly', (store) => store.count());\r\n if (count === 0) {\r\n this.notifyWaiters();\r\n }\r\n return true;\r\n }\r\n\r\n async hasPendingForPath(path: string): Promise<boolean> {\r\n await this.init();\r\n return new Promise<boolean>((resolve, reject) => {\r\n const tx = this.db!.transaction(MUTATIONS_STORE, 'readonly');\r\n const store = tx.objectStore(MUTATIONS_STORE);\r\n const index = store.index('by_path');\r\n const request = index.count(IDBKeyRange.only(path));\r\n request.onsuccess = () => resolve(request.result > 0);\r\n request.onerror = () => reject(request.error);\r\n });\r\n }\r\n\r\n async getForPath(path: string): Promise<Mutation[]> {\r\n await this.init();\r\n return new Promise<Mutation[]>((resolve, reject) => {\r\n const tx = this.db!.transaction(MUTATIONS_STORE, 'readonly');\r\n const store = tx.objectStore(MUTATIONS_STORE);\r\n const index = store.index('by_path');\r\n const request = index.getAll(IDBKeyRange.only(path));\r\n request.onsuccess = () => {\r\n const results = (request.result as Mutation[]).sort((a, b) => a.timestamp - b.timestamp);\r\n resolve(results);\r\n };\r\n request.onerror = () => reject(request.error);\r\n });\r\n }\r\n\r\n async getForCollection(collectionPath: string): Promise<Mutation[]> {\r\n const all = await this.getAllSorted();\r\n const prefix = collectionPath + '/';\r\n return all.filter((m) => m.path.startsWith(prefix) && !m.path.substring(prefix.length).includes('/'));\r\n }\r\n\r\n async getAll(): Promise<Mutation[]> {\r\n return this.getAllSorted();\r\n }\r\n\r\n get size(): Promise<number> {\r\n return this.tx<number>('readonly', (store) => store.count());\r\n }\r\n\r\n get isEmpty(): Promise<boolean> {\r\n return this.size.then((s) => s === 0);\r\n }\r\n\r\n async clear(): Promise<void> {\r\n await this.tx('readwrite', (store) => store.clear());\r\n this.notifyWaiters();\r\n }\r\n\r\n waitForEmpty(): Promise<void> {\r\n return this.isEmpty.then((empty) => {\r\n if (empty) return;\r\n return new Promise<void>((resolve) => {\r\n this.pendingWaiters.push(resolve);\r\n });\r\n });\r\n }\r\n\r\n // ===========================================================================\r\n // HELPERS\r\n // ===========================================================================\r\n\r\n private notifyWaiters(): void {\r\n const waiters = this.pendingWaiters.splice(0);\r\n for (const resolve of waiters) {\r\n resolve();\r\n }\r\n }\r\n\r\n /** Cierra la conexión */\r\n close(): void {\r\n if (this.db) {\r\n this.db.close();\r\n this.db = null;\r\n this._initPromise = null;\r\n }\r\n }\r\n\r\n /** Borra toda la DB de mutaciones (instancia) */\r\n async deleteDatabase(): Promise<void> {\r\n this.close();\r\n return IndexedDBMutationQueue.deleteDatabase(this.dbName);\r\n }\r\n\r\n /** Borra una base de datos de mutaciones IndexedDB por projectId (estático) */\r\n static deleteDatabase(projectId: string): Promise<void> {\r\n const dbName = projectId.startsWith('firestore_mutations_') ? projectId : `firestore_mutations_${projectId}`;\r\n return new Promise<void>((resolve, reject) => {\r\n const request = indexedDB.deleteDatabase(dbName);\r\n request.onsuccess = () => resolve();\r\n request.onerror = () => reject(request.error);\r\n });\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
|