@ponceca/firestore-sdk 0.1.1 → 1.0.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.
Files changed (72) hide show
  1. package/README.md +62 -638
  2. package/dist/app.d.mts +1 -1
  3. package/dist/app.d.ts +1 -1
  4. package/dist/app.js +3 -3
  5. package/dist/app.js.map +1 -1
  6. package/dist/app.mjs +1 -1
  7. package/dist/auth/index.d.mts +17 -10
  8. package/dist/auth/index.d.ts +17 -10
  9. package/dist/auth/index.js +13 -5
  10. package/dist/auth/index.js.map +1 -1
  11. package/dist/auth/index.mjs +12 -4
  12. package/dist/chunk-4CV4JOE5.js.map +1 -1
  13. package/dist/chunk-5ETO65FT.mjs +324 -0
  14. package/dist/chunk-5ETO65FT.mjs.map +1 -0
  15. package/dist/{chunk-R7K4CI3S.mjs → chunk-6XAVSRLT.mjs} +4 -4
  16. package/dist/{chunk-KZWSIKQZ.mjs → chunk-BV43NSDW.mjs} +9 -2
  17. package/dist/chunk-BV43NSDW.mjs.map +1 -0
  18. package/dist/chunk-BXV7KTHB.js.map +1 -1
  19. package/dist/{chunk-YMFAPE5C.js → chunk-DBP3RTRA.js} +6 -6
  20. package/dist/chunk-DBP3RTRA.js.map +1 -0
  21. package/dist/chunk-HCH4ADFN.js +324 -0
  22. package/dist/chunk-HCH4ADFN.js.map +1 -0
  23. package/dist/{chunk-BZZ7QVIL.js → chunk-JXJTWQJ4.js} +9 -2
  24. package/dist/chunk-JXJTWQJ4.js.map +1 -0
  25. package/dist/{chunk-6J3LNKUQ.js → chunk-KNNYFWIP.js} +7 -3
  26. package/dist/chunk-KNNYFWIP.js.map +1 -0
  27. package/dist/{chunk-C6SKWUQV.mjs → chunk-SZNBHCPW.mjs} +5 -1
  28. package/dist/chunk-SZNBHCPW.mjs.map +1 -0
  29. package/dist/{chunk-6UU4YPC7.mjs → chunk-VMO4IG3Q.mjs} +3 -3
  30. package/dist/{chunk-UAJM24MR.js → chunk-ZNDLJ5PH.js} +23 -23
  31. package/dist/chunk-ZNDLJ5PH.js.map +1 -0
  32. package/dist/firestore/index.d.mts +2 -2
  33. package/dist/firestore/index.d.ts +2 -2
  34. package/dist/firestore/index.js +5 -5
  35. package/dist/firestore/index.js.map +1 -1
  36. package/dist/firestore/index.mjs +4 -4
  37. package/dist/http-F3DW64CJ.js +10 -0
  38. package/dist/http-F3DW64CJ.js.map +1 -0
  39. package/dist/{http-SZFONH6Z.mjs → http-IM4ZHBF6.mjs} +2 -2
  40. package/dist/index.d.mts +2 -2
  41. package/dist/index.d.ts +2 -2
  42. package/dist/index.js +15 -7
  43. package/dist/index.js.map +1 -1
  44. package/dist/index.mjs +13 -5
  45. package/dist/index.mjs.map +1 -1
  46. package/dist/indexeddb-mutation-queue-5EB7C2D5.js.map +1 -1
  47. package/dist/indexeddb-store-DNWBZUQE.js.map +1 -1
  48. package/dist/snapshot-MCQVLVHL.js.map +1 -1
  49. package/dist/storage/index.d.mts +138 -0
  50. package/dist/storage/index.d.ts +138 -0
  51. package/dist/storage/index.js +557 -0
  52. package/dist/storage/index.js.map +1 -0
  53. package/dist/storage/index.mjs +557 -0
  54. package/dist/storage/index.mjs.map +1 -0
  55. package/dist/{types-meoR-Ecp.d.ts → types-CxCKB06U.d.mts} +6 -4
  56. package/dist/{types-meoR-Ecp.d.mts → types-CxCKB06U.d.ts} +6 -4
  57. package/package.json +17 -4
  58. package/dist/chunk-6J3LNKUQ.js.map +0 -1
  59. package/dist/chunk-BZZ7QVIL.js.map +0 -1
  60. package/dist/chunk-C6SKWUQV.mjs.map +0 -1
  61. package/dist/chunk-JSUWIG2E.js +0 -128
  62. package/dist/chunk-JSUWIG2E.js.map +0 -1
  63. package/dist/chunk-KZWSIKQZ.mjs.map +0 -1
  64. package/dist/chunk-PZLJFCKL.mjs +0 -128
  65. package/dist/chunk-PZLJFCKL.mjs.map +0 -1
  66. package/dist/chunk-UAJM24MR.js.map +0 -1
  67. package/dist/chunk-YMFAPE5C.js.map +0 -1
  68. package/dist/http-A2S5CWEV.js +0 -10
  69. package/dist/http-A2S5CWEV.js.map +0 -1
  70. /package/dist/{chunk-R7K4CI3S.mjs.map → chunk-6XAVSRLT.mjs.map} +0 -0
  71. /package/dist/{chunk-6UU4YPC7.mjs.map → chunk-VMO4IG3Q.mjs.map} +0 -0
  72. /package/dist/{http-SZFONH6Z.mjs.map → http-IM4ZHBF6.mjs.map} +0 -0
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @ponceca/firestore-sdk
2
2
 
3
- SDK JavaScript/TypeScript 100% compatible con Firebase Firestore v9+ (API modular).
3
+ SDK JavaScript/TypeScript 100% compatible con Firebase v9+ (API modular).
4
4
 
5
5
  **Migrar desde Firebase es tan simple como cambiar el import.**
6
6
 
@@ -10,683 +10,107 @@ SDK JavaScript/TypeScript 100% compatible con Firebase Firestore v9+ (API modula
10
10
  npm install @ponceca/firestore-sdk
11
11
  ```
12
12
 
13
- ## Importación “igual” al SDK oficial (estilo Firebase)
14
-
15
- Ahora puedes importar igual que Firebase:
16
-
17
- - `@ponceca/firestore-sdk/app` (equivalente a `firebase/app`)
18
- - `@ponceca/firestore-sdk/firestore` (equivalente a `firebase/firestore`)
19
-
20
- ## Configuración - Idéntica a Firebase
21
-
22
- ### Opción 1: Conectar al Emulador (Recomendado para desarrollo)
13
+ ## Quick Start
23
14
 
24
15
  ```typescript
25
- import { initializeApp } from '@ponceca/firestore-sdk/app';
26
- import {
27
- getFirestore,
28
- connectFirestoreEmulator
29
- } from '@ponceca/firestore-sdk/firestore';
16
+ import { initializeApp } from '@ponceca/firestore-sdk';
17
+ import { getFirestore, doc, setDoc, getDoc } from '@ponceca/firestore-sdk/firestore';
18
+ import { getAuth, signInWithCustomToken } from '@ponceca/firestore-sdk';
19
+ import { getStorage, ref, uploadBytesResumable } from '@ponceca/firestore-sdk/storage';
30
20
 
31
- // Inicializar app (igual que Firebase)
21
+ // 1. Inicializar
32
22
  const app = initializeApp({
33
- projectId: 'my-project',
23
+ projectId: 'mi-proyecto',
24
+ baseUrl: 'http://localhost:3000', // Firestore backend
25
+ storageUrl: 'http://localhost:3002/api', // Storage backend
26
+ storageBucket: 'default',
34
27
  });
35
28
 
36
- // Obtener Firestore
29
+ // 2. Firestore
37
30
  const db = getFirestore(app);
31
+ await setDoc(doc(db, 'users', 'u1'), { name: 'Juan', age: 28 });
32
+ const snap = await getDoc(doc(db, 'users', 'u1'));
33
+ console.log(snap.data()); // { name: 'Juan', age: 28 }
38
34
 
39
- // Conectar al servidor local (igual que Firebase emulator)
40
- connectFirestoreEmulator(db, 'localhost', 3000);
41
- ```
42
-
43
- ### Opción 2: Configuración en initializeFirestore
44
-
45
- ```typescript
46
- import { initializeApp } from '@ponceca/firestore-sdk/app';
47
- import { initializeFirestore } from '@ponceca/firestore-sdk/firestore';
48
-
49
- const app = initializeApp({
50
- projectId: 'my-project',
51
- });
35
+ // 3. Auth
36
+ const auth = getAuth(app);
37
+ const user = await signInWithCustomToken(auth, 'eyJhbGci...');
38
+ console.log(user.uid);
52
39
 
53
- // Configuración avanzada
54
- const db = initializeFirestore(app, {
55
- host: 'localhost:3000',
56
- ssl: false,
57
- });
58
- ```
59
-
60
- ### Perfil recomendado para producción (balanceado)
61
-
62
- ```typescript
63
- import { initializeApp } from '@ponceca/firestore-sdk/app';
64
- import { initializeFirestore } from '@ponceca/firestore-sdk/firestore';
65
-
66
- const app = initializeApp({
67
- projectId: 'my-project',
68
- });
69
-
70
- const db = initializeFirestore(app, {
71
- host: 'api.my-firestore-clone.com',
72
- ssl: true,
73
- timeout: 12000,
74
- maxRetries: 2,
75
- retryInitialDelayMs: 150,
76
- retryMaxDelayMs: 2000,
77
- });
40
+ // 4. Storage
41
+ const storage = getStorage(app);
42
+ const task = uploadBytesResumable(ref(storage, 'uploads/file.pdf'), fileBlob);
78
43
  ```
79
44
 
80
- ### Opción 3: Configuración con baseUrl (Conveniente)
81
-
82
- ```typescript
83
- import { initializeApp } from '@ponceca/firestore-sdk/app';
45
+ ## Sub-entry points
84
46
 
85
- const app = initializeApp({
86
- projectId: 'my-project',
87
- baseUrl: 'http://localhost:3000', // Auto-configura host y ssl
88
- });
89
-
90
- const db = getFirestore(app);
91
- ```
47
+ | Import | Equivale a Firebase |
48
+ |--------|-------------------|
49
+ | `@ponceca/firestore-sdk` | `firebase/app` + Auth |
50
+ | `@ponceca/firestore-sdk/app` | `firebase/app` |
51
+ | `@ponceca/firestore-sdk/firestore` | `firebase/firestore` |
52
+ | `@ponceca/firestore-sdk/auth` | `firebase/auth` |
53
+ | `@ponceca/firestore-sdk/storage` | `firebase/storage` |
92
54
 
93
55
  ## Migrar desde Firebase
94
56
 
95
57
  ```diff
96
58
  - import { initializeApp } from 'firebase/app';
97
59
  - import { getFirestore, doc, setDoc } from 'firebase/firestore';
98
- + import { initializeApp } from '@ponceca/firestore-sdk/app';
60
+ + import { initializeApp } from '@ponceca/firestore-sdk';
99
61
  + import { getFirestore, doc, setDoc } from '@ponceca/firestore-sdk/firestore';
100
62
 
101
- const app = initializeApp({ projectId: 'my-project' });
102
- const db = getFirestore(app);
103
-
104
- + // Conectar a tu servidor (en desarrollo)
105
- + connectFirestoreEmulator(db, 'localhost', 3000);
106
-
107
- // ¡El resto del código es IDÉNTICO!
108
- await setDoc(doc(db, 'users', 'user1'), { name: 'Juan' });
109
- ```
110
-
111
- ## Uso Básico
112
-
113
- ```typescript
114
- import { initializeApp } from '@ponceca/firestore-sdk/app';
115
- import {
116
- getFirestore,
117
- connectFirestoreEmulator,
118
- collection,
119
- doc,
120
- getDoc,
121
- setDoc,
122
- updateDoc,
123
- deleteDoc,
124
- addDoc,
125
- query,
126
- where,
127
- orderBy,
128
- limit,
129
- getDocs,
130
- onSnapshot,
131
- serverTimestamp,
132
- } from '@ponceca/firestore-sdk/firestore';
133
-
134
- // 1. Inicializar app
135
63
  const app = initializeApp({
136
64
  projectId: 'my-project',
65
+ + baseUrl: 'http://localhost:3000',
137
66
  });
138
67
 
139
- // 2. Obtener instancia de Firestore
140
- const db = getFirestore(app);
141
-
142
- // 3. Conectar al servidor (desarrollo local)
143
- connectFirestoreEmulator(db, 'localhost', 3000);
144
-
145
- // 4. Crear referencia a documento
146
- const userRef = doc(db, 'users', 'user123');
147
-
148
- // 5. Escribir documento
149
- await setDoc(userRef, {
150
- name: 'Juan García',
151
- email: 'juan@example.com',
152
- age: 25,
153
- createdAt: serverTimestamp(),
154
- });
155
-
156
- // 6. Leer documento
157
- const snapshot = await getDoc(userRef);
158
- if (snapshot.exists()) {
159
- console.log('Usuario:', snapshot.data());
160
- }
161
-
162
- // 7. Actualizar documento
163
- await updateDoc(userRef, {
164
- age: 26,
165
- 'address.city': 'Madrid', // Actualización anidada
166
- });
167
-
168
- // 8. Eliminar documento
169
- await deleteDoc(userRef);
170
-
171
- // 9. Añadir documento con ID automático
172
- const newDocRef = await addDoc(collection(db, 'posts'), {
173
- title: 'Mi primer post',
174
- content: 'Hola mundo!',
175
- createdAt: serverTimestamp(),
176
- });
177
- console.log('Nuevo ID:', newDocRef.id);
178
- ```
179
-
180
- ## Autenticación
181
-
182
- El SDK soporta múltiples formas de autenticación, idéntico a Firebase:
183
-
184
- ### Opción 1: Token Manual (Simple)
185
-
186
- ```typescript
187
- import {
188
- getFirestore,
189
- setAuthToken,
190
- getAuthToken
191
- } from '@ponceca/firestore-sdk/firestore';
192
-
68
+ // ¡El resto del código es IDÉNTICO!
193
69
  const db = getFirestore(app);
194
-
195
- // Establecer token JWT
196
- const token = await myAuthService.getToken();
197
- setAuthToken(db, token);
198
-
199
- // Verificar token actual
200
- console.log('Token:', getAuthToken(db));
201
-
202
- // Logout - eliminar token
203
- setAuthToken(db, null);
204
- ```
205
-
206
- ### Opción 2: AuthTokenProvider (Automático - Recomendado)
207
-
208
- Igual que Firebase Auth se integra automáticamente con Firestore:
209
-
210
- ```typescript
211
- import {
212
- initializeFirestore,
213
- type AuthTokenProvider
214
- } from '@ponceca/firestore-sdk/firestore';
215
-
216
- // Crear un provider que obtiene tokens automáticamente
217
- const authProvider: AuthTokenProvider = {
218
- // Obtiene el token actual (llamado en cada request)
219
- async getToken() {
220
- const user = myAuthService.currentUser;
221
- return user ? await user.getIdToken() : null;
222
- },
223
-
224
- // Opcional: escucha cambios de auth
225
- onAuthStateChanged(callback) {
226
- return myAuthService.onAuthStateChanged((user) => {
227
- callback(user ? user.token : null);
228
- });
229
- }
230
- };
231
-
232
- // Configurar Firestore con el provider
233
- const db = initializeFirestore(app, {
234
- host: 'localhost:3000',
235
- ssl: false,
236
- authTokenProvider: authProvider
237
- });
238
-
239
- // Ahora cada request obtiene el token automáticamente
240
- await setDoc(doc(db, 'users', 'user1'), { name: 'Juan' }); // Token incluido!
241
- ```
242
-
243
- ### Opción 3: Integración con Firebase Auth
244
-
245
- ```typescript
246
- import { getAuth, onAuthStateChanged } from 'firebase/auth';
247
- import { initializeFirestore, type AuthTokenProvider } from '@ponceca/firestore-sdk/firestore';
248
-
249
- const firebaseAuth = getAuth();
250
-
251
- // Provider que usa Firebase Auth
252
- const firebaseAuthProvider: AuthTokenProvider = {
253
- async getToken() {
254
- const user = firebaseAuth.currentUser;
255
- return user ? await user.getIdToken() : null;
256
- },
257
- onAuthStateChanged(callback) {
258
- return onAuthStateChanged(firebaseAuth, async (user) => {
259
- callback(user ? await user.getIdToken() : null);
260
- });
261
- }
262
- };
263
-
264
- const db = initializeFirestore(app, {
265
- host: 'localhost:3000',
266
- authTokenProvider: firebaseAuthProvider
267
- });
268
- ```
269
-
270
- ### Opción 4: Mock Token para Testing
271
-
272
- ```typescript
273
- connectFirestoreEmulator(db, 'localhost', 3000, {
274
- mockUserToken: {
275
- sub: 'user123',
276
- email: 'test@example.com',
277
- // Simular claims personalizados
278
- admin: true
279
- }
280
- });
281
- ```
282
-
283
- ## Queries
284
-
285
- ```typescript
286
- // Query con filtros
287
- const q = query(
288
- collection(db, 'users'),
289
- where('age', '>=', 18),
290
- where('status', '==', 'active'),
291
- orderBy('age', 'desc'),
292
- limit(10)
293
- );
294
-
295
- const querySnapshot = await getDocs(q);
296
- querySnapshot.forEach((doc) => {
297
- console.log(doc.id, '=>', doc.data());
298
- });
299
-
300
- // Operadores disponibles
301
- where('field', '==', value); // Igual
302
- where('field', '!=', value); // No igual
303
- where('field', '<', value); // Menor que
304
- where('field', '<=', value); // Menor o igual
305
- where('field', '>', value); // Mayor que
306
- where('field', '>=', value); // Mayor o igual
307
- where('field', 'in', [values]); // En array
308
- where('field', 'not-in', [values]); // No en array
309
- where('field', 'array-contains', value); // Array contiene
310
- where('field', 'array-contains-any', [values]); // Array contiene cualquiera
311
- ```
312
-
313
- ### Modo flexible (opt-in)
314
-
315
- En Firestore original, si usas un filtro de rango (ej: `where('price', '>=', 600)`),
316
- el primer `orderBy` debe ser sobre ese mismo campo. En PostgreSQL no es necesario.
317
-
318
- Si quieres permitir queries más flexibles, activa el flag `allowFlexibleQueries`:
319
-
320
- ```typescript
321
- const db = initializeFirestore(app, {
322
- host: 'localhost:3000',
323
- ssl: false,
324
- allowFlexibleQueries: true,
325
- });
326
-
327
- // Ahora es válido:
328
- const q = query(
329
- collection(db, 'products'),
330
- where('price', '>=', 600),
331
- orderBy('rating', 'desc') // Ordenar por campo diferente al del filtro de rango
332
- );
333
- ```
334
-
335
- 📖 Ver [documentación completa del modo flexible](docs/FLEXIBLE_QUERIES.md) con más ejemplos y casos de uso.
336
-
337
- ## Real-time Listeners
338
-
339
- ```typescript
340
- // Escuchar cambios en documento
341
- const unsubscribe = onSnapshot(userRef, (snapshot) => {
342
- if (snapshot.exists()) {
343
- console.log('Datos actualizados:', snapshot.data());
344
- }
345
- });
346
-
347
- // Escuchar cambios en query
348
- const q = query(collection(db, 'messages'), orderBy('timestamp', 'desc'), limit(50));
349
- const unsubscribeQuery = onSnapshot(q, (snapshot) => {
350
- snapshot.docChanges().forEach((change) => {
351
- if (change.type === 'added') {
352
- console.log('Nuevo mensaje:', change.doc.data());
353
- }
354
- if (change.type === 'modified') {
355
- console.log('Mensaje modificado:', change.doc.data());
356
- }
357
- if (change.type === 'removed') {
358
- console.log('Mensaje eliminado:', change.doc.id);
359
- }
360
- });
361
- });
362
-
363
- // Cancelar suscripción
364
- unsubscribe();
365
- unsubscribeQuery();
366
- ```
367
-
368
- ## Field Values Especiales
369
-
370
- ```typescript
371
- import {
372
- serverTimestamp,
373
- increment,
374
- arrayUnion,
375
- arrayRemove,
376
- deleteField,
377
- } from '@ponceca/firestore-sdk/firestore';
378
-
379
- // Timestamp del servidor
380
- await setDoc(ref, { createdAt: serverTimestamp() });
381
-
382
- // Incrementar valor numérico
383
- await updateDoc(ref, { views: increment(1) });
384
-
385
- // Añadir elementos a array (sin duplicados)
386
- await updateDoc(ref, { tags: arrayUnion('new-tag') });
387
-
388
- // Eliminar elementos de array
389
- await updateDoc(ref, { tags: arrayRemove('old-tag') });
390
-
391
- // Eliminar campo
392
- await updateDoc(ref, { oldField: deleteField() });
393
- ```
394
-
395
- ## Batch Writes
396
-
397
- ```typescript
398
- import { writeBatch } from '@ponceca/firestore-sdk/firestore';
399
-
400
- const batch = writeBatch(db);
401
-
402
- batch.set(doc(db, 'cities', 'NYC'), { name: 'New York' });
403
- batch.update(doc(db, 'cities', 'LA'), { population: 4000000 });
404
- batch.delete(doc(db, 'cities', 'OLD'));
405
-
406
- await batch.commit();
70
+ await setDoc(doc(db, 'users', 'u1'), { name: 'Juan' });
407
71
  ```
408
72
 
409
- ## Transacciones
73
+ ## Configuración por Entorno
410
74
 
411
75
  ```typescript
412
- import { runTransaction } from '@ponceca/firestore-sdk/firestore';
413
-
414
- const newBalance = await runTransaction(db, async (transaction) => {
415
- const accountRef = doc(db, 'accounts', 'account1');
416
- const accountDoc = await transaction.get(accountRef);
417
-
418
- if (!accountDoc.exists()) {
419
- throw new Error('Account does not exist');
420
- }
421
-
422
- const currentBalance = accountDoc.data()!.balance;
423
- const newBalance = currentBalance - 100;
76
+ // Desarrollo (usa defaults: localhost:3000)
77
+ initializeApp({ projectId: 'dev-project' });
424
78
 
425
- if (newBalance < 0) {
426
- throw new Error('Insufficient funds');
427
- }
428
-
429
- transaction.update(accountRef, { balance: newBalance });
430
- return newBalance;
79
+ // Producción
80
+ initializeApp({
81
+ projectId: 'prod-project',
82
+ apiKey: 'mi-api-key',
83
+ baseUrl: 'https://firestore.midominio.com',
84
+ storageUrl: 'https://storage.midominio.com/api',
85
+ storageBucket: 'prod-bucket',
431
86
  });
432
87
  ```
433
88
 
434
- ## Subcolecciones
89
+ ## Features
435
90
 
436
- ```typescript
437
- // Crear referencia a subcolección
438
- const postsRef = collection(db, 'users', 'user123', 'posts');
91
+ - ✅ **CRUD completo**: `getDoc`, `setDoc`, `updateDoc`, `deleteDoc`, `addDoc`
92
+ - **Queries**: `where`, `orderBy`, `limit`, `startAt/After`, `endAt/Before`, `and`, `or`
93
+ - **Real-time**: `onSnapshot` con `docChanges()`
94
+ - ✅ **Auth**: `signInWithCustomToken`, `signOut`, `onAuthStateChanged`, persistencia
95
+ - ✅ **Storage**: Upload resumable, `getDownloadURL`, `listAll`, metadata
96
+ - ✅ **Batch & Transactions**: Operaciones atómicas
97
+ - ✅ **Agregaciones**: `count()`, `sum()`, `average()`
98
+ - ✅ **Tipos especiales**: `Timestamp`, `GeoPoint`, `Bytes`, `VectorValue`
99
+ - ✅ **Búsqueda avanzada**: `fastSearch`, `whereFuzzy`, `whereSearch`
100
+ - ✅ **Field Values**: `serverTimestamp()`, `increment()`, `arrayUnion/Remove`
439
101
 
440
- // O desde documento
441
- const userRef = doc(db, 'users', 'user123');
442
- const postsRef2 = collection(userRef, 'posts');
102
+ ## Documentación Completa
443
103
 
444
- // Añadir documento a subcolección
445
- await addDoc(postsRef, {
446
- title: 'Mi post',
447
- content: 'Contenido...',
448
- });
449
-
450
- // Query en subcolección
451
- const recentPosts = await getDocs(
452
- query(postsRef, orderBy('createdAt', 'desc'), limit(5))
453
- );
454
- ```
455
-
456
- ## Tipos TypeScript
457
-
458
- El SDK incluye tipos completos para TypeScript:
459
-
460
- ```typescript
461
- import type {
462
- DocumentData,
463
- DocumentReference,
464
- CollectionReference,
465
- Query,
466
- DocumentSnapshot,
467
- QuerySnapshot,
468
- Firestore,
469
- FieldValue,
470
- } from '@ponceca/firestore-sdk/firestore';
104
+ 📘 Ver [`sdk/DOCUMENTACION.md`](https://github.com/ponceca/firestore/blob/main/sdk/DOCUMENTACION.md) para la guía completa incluyendo: configuración del backend, variables de entorno, Angular SDK, seguridad JWT, y despliegue en producción.
471
105
 
472
- // Tipos personalizados
473
- interface User {
474
- name: string;
475
- email: string;
476
- age: number;
477
- }
478
-
479
- const userRef = doc(db, 'users', 'user123') as DocumentReference<User>;
480
- const snapshot = await getDoc(userRef);
481
-
482
- if (snapshot.exists()) {
483
- const user: User = snapshot.data()!;
484
- console.log(user.name); // TypeScript conoce el tipo
485
- }
486
- ```
487
-
488
- ## Compatibilidad con Firebase
489
-
490
- Este SDK es un drop-in replacement para Firebase Firestore v9. Para migrar:
491
-
492
- ```typescript
493
- // Antes (Firebase)
494
- import { initializeApp } from 'firebase/app';
495
- import { getFirestore, doc, getDoc } from 'firebase/firestore';
496
-
497
- // Después (Este SDK)
498
- import { initializeApp } from '@ponceca/firestore-sdk/app';
499
- import { getFirestore, doc, getDoc } from '@ponceca/firestore-sdk/firestore';
500
- ```
501
-
502
- ## Queries Avanzadas
503
-
504
- ```typescript
505
- import { and, or, collectionGroup } from '@ponceca/firestore-sdk/firestore';
106
+ ## Para Angular
506
107
 
507
- // Filtros compuestos con AND/OR
508
- const q = query(
509
- collection(db, 'products'),
510
- and(
511
- where('category', '==', 'electronics'),
512
- or(
513
- where('price', '<', 100),
514
- where('onSale', '==', true)
515
- )
516
- )
517
- );
518
-
519
- // Collection Group Query (buscar en todas las subcolecciones con mismo ID)
520
- const allComments = query(
521
- collectionGroup(db, 'comments'),
522
- where('author', '==', 'john'),
523
- orderBy('createdAt', 'desc'),
524
- limit(10)
525
- );
526
- ```
527
-
528
- ## Agregaciones
529
-
530
- ```typescript
531
- import { getCountFromServer, getAggregateFromServer, count, sum, average } from '@ponceca/firestore-sdk/firestore';
532
-
533
- // Contar documentos
534
- const countSnapshot = await getCountFromServer(query(collection(db, 'users')));
535
- console.log('Total users:', countSnapshot.data().count);
536
-
537
- // Múltiples agregaciones
538
- const snapshot = await getAggregateFromServer(
539
- query(collection(db, 'orders'), where('status', '==', 'completed')),
540
- {
541
- totalOrders: count(),
542
- totalRevenue: sum('amount'),
543
- avgOrderValue: average('amount')
544
- }
545
- );
546
-
547
- console.log('Total orders:', snapshot.data().totalOrders);
548
- console.log('Total revenue:', snapshot.data().totalRevenue);
549
- console.log('Average order:', snapshot.data().avgOrderValue);
550
- ```
551
-
552
- ## Tipos Especiales
553
-
554
- ```typescript
555
- import { Timestamp, GeoPoint, Bytes, FieldPath, documentId, vector } from '@ponceca/firestore-sdk/firestore';
556
-
557
- // Timestamp
558
- const ts = Timestamp.now();
559
- const tsFromDate = Timestamp.fromDate(new Date());
560
- console.log(ts.toDate());
561
-
562
- // GeoPoint
563
- const location = new GeoPoint(37.7749, -122.4194);
564
- console.log(location.latitude, location.longitude);
565
-
566
- // Bytes
567
- const bytes = Bytes.fromBase64String('SGVsbG8gV29ybGQ=');
568
- console.log(bytes.toUint8Array());
569
-
570
- // FieldPath para campos anidados
571
- const path = new FieldPath('user', 'address', 'city');
572
-
573
- // documentId() para filtrar por ID de documento
574
- const q = query(
575
- collection(db, 'users'),
576
- where(documentId(), 'in', ['user1', 'user2', 'user3'])
577
- );
578
-
579
- // Vector para embeddings/ML
580
- const embedding = vector([0.1, 0.2, 0.3, 0.4]);
581
- await setDoc(docRef, { embedding });
582
- ```
583
-
584
- ## Utilidades
585
-
586
- ```typescript
587
- import { refEqual, queryEqual, snapshotEqual, onSnapshotsInSync } from '@ponceca/firestore-sdk/firestore';
588
-
589
- // Comparar referencias
590
- const ref1 = doc(db, 'users', '123');
591
- const ref2 = doc(db, 'users', '123');
592
- console.log(refEqual(ref1, ref2)); // true
593
-
594
- // Comparar queries
595
- const q1 = query(collection(db, 'users'), where('age', '>=', 18));
596
- const q2 = query(collection(db, 'users'), where('age', '>=', 18));
597
- console.log(queryEqual(q1, q2)); // true
598
-
599
- // Notificación cuando todos los listeners están sincronizados
600
- const unsubSync = onSnapshotsInSync(db, () => {
601
- console.log('All snapshots are in sync');
602
- });
108
+ ```bash
109
+ npm install @ponceca/firestore-sdk @ponceca/firestore-angular
603
110
  ```
604
111
 
605
- ## API Reference
606
-
607
- ### App
608
-
609
- - `initializeApp(options, name?)` - Inicializa la app
610
- - `getApp(name?)` - Obtiene app existente
611
- - `getApps()` - Lista todas las apps
612
- - `deleteApp(app)` - Elimina una app
613
-
614
- ### Firestore
615
-
616
- - `getFirestore(app?)` - Obtiene instancia de Firestore
617
- - `initializeFirestore(app, settings)` - Inicializa con configuración
618
- - `terminate(firestore)` - Termina instancia
619
-
620
- ### Referencias
621
-
622
- - `doc(firestore, path, ...segments)` - Referencia a documento
623
- - `collection(firestore, path, ...segments)` - Referencia a colección
624
- - `collectionGroup(firestore, collectionId)` - Query sobre grupo de colecciones
625
-
626
- ### CRUD
627
-
628
- - `getDoc(ref)` - Lee documento
629
- - `setDoc(ref, data, options?)` - Escribe documento
630
- - `updateDoc(ref, data)` - Actualiza campos
631
- - `deleteDoc(ref)` - Elimina documento
632
- - `addDoc(collectionRef, data)` - Añade con ID auto
633
-
634
- ### Queries
635
-
636
- - `query(ref, ...constraints)` - Crea query
637
- - `where(field, op, value)` - Filtro
638
- - `orderBy(field, direction?)` - Ordenar
639
- - `limit(n)` - Limitar resultados
640
- - `limitToLast(n)` - Últimos N
641
- - `startAt(...values)` - Cursor inicio inclusivo
642
- - `startAfter(...values)` - Cursor inicio exclusivo
643
- - `endAt(...values)` - Cursor fin inclusivo
644
- - `endBefore(...values)` - Cursor fin exclusivo
645
- - `and(...constraints)` - Filtro AND compuesto
646
- - `or(...constraints)` - Filtro OR compuesto
647
- - `getDocs(query)` - Ejecuta query
648
-
649
- ### Real-time
650
-
651
- - `onSnapshot(ref, onNext, onError?)` - Suscribe a cambios
652
- - `onSnapshotsInSync(firestore, callback)` - Sincronización de listeners
653
-
654
- ### Agregaciones
655
-
656
- - `getCountFromServer(query)` - Cuenta documentos
657
- - `getAggregateFromServer(query, spec)` - Múltiples agregaciones
658
- - `count()` - Campo de conteo
659
- - `sum(field)` - Campo de suma
660
- - `average(field)` - Campo de promedio
661
-
662
- ### Field Values
663
-
664
- - `serverTimestamp()` - Timestamp del servidor
665
- - `increment(n)` - Incrementar número
666
- - `arrayUnion(...values)` - Añadir a array
667
- - `arrayRemove(...values)` - Eliminar de array
668
- - `deleteField()` - Eliminar campo
669
-
670
- ### Tipos Especiales
671
-
672
- - `Timestamp` - Clase para timestamps
673
- - `GeoPoint` - Clase para coordenadas
674
- - `Bytes` - Clase para datos binarios
675
- - `FieldPath` - Clase para paths de campos
676
- - `VectorValue` / `vector()` - Para embeddings/ML
677
- - `documentId()` - Referencia al ID de documento
678
-
679
- ### Batch & Transactions
680
-
681
- - `writeBatch(firestore)` - Crea batch
682
- - `runTransaction(firestore, fn, options?)` - Ejecuta transacción
683
-
684
- ### Utilidades
685
-
686
- - `refEqual(ref1, ref2)` - Compara referencias
687
- - `queryEqual(q1, q2)` - Compara queries
688
- - `snapshotEqual(s1, s2)` - Compara snapshots
112
+ Ver [@ponceca/firestore-angular](https://www.npmjs.com/package/@ponceca/firestore-angular) para la documentación del adapter Angular con Signals, Observables, Guards y SSR.
689
113
 
690
114
  ## Licencia
691
115
 
692
- MIT
116
+ MIT — © 2026 ponceca