@roit/roit-data-firestore 1.2.42 → 1.2.44

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 (37) hide show
  1. package/README.md +107 -0
  2. package/dist/archive/ArchivePluginRegistry.d.ts +78 -0
  3. package/dist/archive/ArchivePluginRegistry.js +135 -0
  4. package/dist/archive/ArchiveService.d.ts +61 -11
  5. package/dist/archive/ArchiveService.js +138 -120
  6. package/dist/archive/IArchivePlugin.d.ts +102 -0
  7. package/dist/archive/IArchivePlugin.js +12 -0
  8. package/dist/archive/index.d.ts +2 -0
  9. package/dist/archive/index.js +11 -0
  10. package/dist/cache/CacheResolver.js +6 -5
  11. package/dist/config/ArchiveConfig.d.ts +17 -12
  12. package/dist/config/ArchiveConfig.js +25 -41
  13. package/dist/config/BaseRepository.js +1 -1
  14. package/dist/config/ReadonlyRepository.js +1 -1
  15. package/dist/exception/RepositoryException.js +1 -1
  16. package/dist/index.d.ts +4 -0
  17. package/dist/index.js +10 -1
  18. package/dist/model/CacheProviders.d.ts +1 -2
  19. package/dist/model/CacheProviders.js +1 -2
  20. package/dist/query/ManualQueryHelper.js +0 -1
  21. package/dist/query/QueryPredicateFunctionTransform.js +4 -1
  22. package/dist/template/FunctionAggregationTemplate.txt +1 -1
  23. package/dist/template/FunctionAverageTemplate.txt +1 -1
  24. package/dist/template/FunctionCountTemplate.txt +20 -25
  25. package/dist/template/FunctionCreateOrUpdateTemplate.txt +69 -20
  26. package/dist/template/FunctionCreateTemplate.txt +15 -13
  27. package/dist/template/FunctionDeleteTemplate.txt +45 -13
  28. package/dist/template/FunctionFindAllTemplate.txt +39 -23
  29. package/dist/template/FunctionFindByIdTemplate.txt +24 -14
  30. package/dist/template/FunctionQueryTemplate.txt +67 -41
  31. package/dist/template/FunctionSumTemplate.txt +48 -32
  32. package/dist/template/FunctionUpdatePartialTemplate.txt +76 -21
  33. package/dist/template/FunctionUpdateTemplate.txt +64 -17
  34. package/dist/tsconfig.build.tsbuildinfo +1 -1
  35. package/package.json +1 -1
  36. package/dist/cache/providers/RedisCacheArchiveProvider.d.ts +0 -19
  37. package/dist/cache/providers/RedisCacheArchiveProvider.js +0 -115
package/README.md CHANGED
@@ -159,6 +159,7 @@ Ref: [Firstore Operators](https://firebase.google.com/docs/firestore/query-data/
159
159
  | OrderBy Desc | findByNameAndOrderByNameDesc | .where('name', '==', value).orderBy("name", "desc")|
160
160
  | OrderBy Asc | findByNameAndOrderByNameAsc | .where('name', '==', value).orderBy("name", "asc")|
161
161
  | Limit | findByNameAndLimit10 | .where('name', '==', value).limit(10) |
162
+ | OR Queries | Manual query with `or` property | Filter.or(...) - See OR Queries section |
162
163
 
163
164
  #### Example
164
165
 
@@ -270,6 +271,112 @@ export class Repository1 extends BaseRepository<User> {
270
271
  }
271
272
  ```
272
273
 
274
+ #### OR Queries
275
+
276
+ The library supports OR queries using the `or` property within the query array. This allows you to create complex queries with multiple conditions using logical OR operations.
277
+
278
+ ##### Basic OR Query
279
+
280
+ ```
281
+ findByStatusOrCategory(): Promise<Array<User>> {
282
+ return this.query({
283
+ query: [
284
+ {
285
+ or: [
286
+ { field: 'status', operator: '==', value: 'active' },
287
+ { field: 'status', operator: '==', value: 'pending' }
288
+ ]
289
+ }
290
+ ]
291
+ })
292
+ }
293
+ ```
294
+
295
+ ##### OR with Simple Syntax
296
+
297
+ ```
298
+ findByStatusOrCategory(): Promise<Array<User>> {
299
+ return this.query({
300
+ query: [
301
+ {
302
+ or: [
303
+ { status: 'active' },
304
+ { status: 'pending' }
305
+ ]
306
+ }
307
+ ]
308
+ })
309
+ }
310
+ ```
311
+
312
+ ##### Combining AND and OR
313
+
314
+ ```
315
+ findByCategoryAndStatusOrRating(): Promise<Array<User>> {
316
+ return this.query({
317
+ query: [
318
+ { field: 'category', operator: '==', value: 'electronics' }, // AND condition
319
+ {
320
+ or: [
321
+ { field: 'price', operator: '>', value: 1000 },
322
+ { field: 'rating', operator: '>', value: 4.5 }
323
+ ]
324
+ }
325
+ ]
326
+ })
327
+ }
328
+ ```
329
+
330
+ ##### Multiple OR Groups
331
+
332
+ ```
333
+ findByMultipleConditions(): Promise<Array<User>> {
334
+ return this.query({
335
+ query: [
336
+ { field: 'active', operator: '==', value: true }, // AND
337
+ {
338
+ or: [
339
+ { field: 'price', operator: '>', value: 1000 },
340
+ { field: 'popular', operator: '==', value: true }
341
+ ]
342
+ },
343
+ {
344
+ or: [
345
+ { field: 'category', operator: 'in', value: ['electronics', 'books'] },
346
+ { field: 'featured', operator: '==', value: true }
347
+ ]
348
+ }
349
+ ]
350
+ })
351
+ }
352
+ ```
353
+
354
+ ##### OR with Different Operators
355
+
356
+ ```
357
+ findByComplexConditions(): Promise<Array<User>> {
358
+ return this.query({
359
+ query: [
360
+ {
361
+ or: [
362
+ { field: 'status', operator: '==', value: 'active' },
363
+ { field: 'price', operator: '>', value: 100 },
364
+ { field: 'tags', operator: 'array-contains', value: 'premium' },
365
+ { field: 'category', operator: 'in', value: ['electronics', 'books'] }
366
+ ]
367
+ }
368
+ ]
369
+ })
370
+ }
371
+ ```
372
+
373
+ ##### Limitations
374
+
375
+ - Firestore limits OR queries to a maximum of 30 disjunctions
376
+ - OR queries cannot be combined with `not-in` operators in the same query
377
+ - Only one `not-in` or `!=` operator is allowed per query
378
+ - Complex OR queries may require composite indexes in Firestore
379
+
273
380
  #### Paginated Query
274
381
 
275
382
 
@@ -0,0 +1,78 @@
1
+ import { IArchivePlugin } from './IArchivePlugin';
2
+ /**
3
+ * Registry para o plugin de arquivamento
4
+ *
5
+ * Permite que aplicações registrem um plugin de archive (como firestore-archive)
6
+ * para habilitar funcionalidades de arquivamento de documentos.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { registerArchivePlugin, getArchivePlugin } from '@roit/roit-data-firestore';
11
+ * import { createArchivePlugin } from 'firestore-archive';
12
+ *
13
+ * // No início da aplicação
14
+ * registerArchivePlugin(createArchivePlugin());
15
+ *
16
+ * // Em qualquer lugar da aplicação
17
+ * const plugin = getArchivePlugin();
18
+ * if (plugin.isEnabled()) {
19
+ * const data = await plugin.getArchivedDocument({
20
+ * collection: 'orders',
21
+ * docId: 'abc123',
22
+ * archivePath: 'gs://bucket/project/orders/YYYY/MM/DD/{ts}_abc123.json.gz',
23
+ * });
24
+ * }
25
+ * ```
26
+ */
27
+ declare class ArchivePluginRegistry {
28
+ private static instance;
29
+ private plugin;
30
+ private constructor();
31
+ static getInstance(): ArchivePluginRegistry;
32
+ /**
33
+ * Registra um plugin de archive
34
+ */
35
+ register(plugin: IArchivePlugin): void;
36
+ /**
37
+ * Retorna o plugin registrado (ou NoOp se nenhum foi registrado)
38
+ */
39
+ getPlugin(): IArchivePlugin;
40
+ /**
41
+ * Verifica se um plugin real foi registrado
42
+ */
43
+ hasPlugin(): boolean;
44
+ /**
45
+ * Reseta o registry (útil para testes)
46
+ */
47
+ reset(): void;
48
+ }
49
+ /**
50
+ * Registra um plugin de archive
51
+ * Deve ser chamado no início da aplicação, antes de usar repositórios
52
+ *
53
+ * @param plugin - Instância do plugin de archive
54
+ *
55
+ * @example
56
+ * ```typescript
57
+ * import { registerArchivePlugin } from '@roit/roit-data-firestore';
58
+ * import { createArchivePlugin } from 'firestore-archive';
59
+ *
60
+ * // No bootstrap da aplicação
61
+ * registerArchivePlugin(createArchivePlugin());
62
+ * ```
63
+ */
64
+ export declare function registerArchivePlugin(plugin: IArchivePlugin): void;
65
+ /**
66
+ * Retorna o plugin de archive registrado
67
+ * Se nenhum plugin foi registrado, retorna um plugin NoOp que desabilita todas as operações
68
+ */
69
+ export declare function getArchivePlugin(): IArchivePlugin;
70
+ /**
71
+ * Verifica se um plugin de archive foi registrado
72
+ */
73
+ export declare function hasArchivePlugin(): boolean;
74
+ /**
75
+ * Reseta o registry de plugins (útil para testes)
76
+ */
77
+ export declare function resetArchivePlugin(): void;
78
+ export { ArchivePluginRegistry };
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ArchivePluginRegistry = exports.resetArchivePlugin = exports.hasArchivePlugin = exports.getArchivePlugin = exports.registerArchivePlugin = void 0;
4
+ /**
5
+ * Plugin NoOp - usado quando nenhum plugin de archive foi registrado
6
+ * Todas as operações retornam valores padrão indicando que archive está desabilitado
7
+ */
8
+ class NoOpArchivePlugin {
9
+ isEnabled() {
10
+ return false;
11
+ }
12
+ isDocumentArchived(_doc) {
13
+ return false;
14
+ }
15
+ async getArchivedDocument(_params) {
16
+ return null;
17
+ }
18
+ async updateArchivedDocument(_params) {
19
+ return {
20
+ result: { success: false, message: 'Archive plugin not registered' },
21
+ };
22
+ }
23
+ async deleteArchivedDocument(_params) {
24
+ return { success: false, message: 'Archive plugin not registered' };
25
+ }
26
+ async invalidateCache(_collection, _docId) {
27
+ // No-op
28
+ }
29
+ }
30
+ /**
31
+ * Registry para o plugin de arquivamento
32
+ *
33
+ * Permite que aplicações registrem um plugin de archive (como firestore-archive)
34
+ * para habilitar funcionalidades de arquivamento de documentos.
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * import { registerArchivePlugin, getArchivePlugin } from '@roit/roit-data-firestore';
39
+ * import { createArchivePlugin } from 'firestore-archive';
40
+ *
41
+ * // No início da aplicação
42
+ * registerArchivePlugin(createArchivePlugin());
43
+ *
44
+ * // Em qualquer lugar da aplicação
45
+ * const plugin = getArchivePlugin();
46
+ * if (plugin.isEnabled()) {
47
+ * const data = await plugin.getArchivedDocument({
48
+ * collection: 'orders',
49
+ * docId: 'abc123',
50
+ * archivePath: 'gs://bucket/project/orders/YYYY/MM/DD/{ts}_abc123.json.gz',
51
+ * });
52
+ * }
53
+ * ```
54
+ */
55
+ class ArchivePluginRegistry {
56
+ constructor() {
57
+ // Inicializa com NoOp por padrão
58
+ this.plugin = new NoOpArchivePlugin();
59
+ }
60
+ static getInstance() {
61
+ if (!ArchivePluginRegistry.instance) {
62
+ ArchivePluginRegistry.instance = new ArchivePluginRegistry();
63
+ }
64
+ return ArchivePluginRegistry.instance;
65
+ }
66
+ /**
67
+ * Registra um plugin de archive
68
+ */
69
+ register(plugin) {
70
+ this.plugin = plugin;
71
+ console.log('[ArchivePluginRegistry] Archive plugin registered successfully');
72
+ }
73
+ /**
74
+ * Retorna o plugin registrado (ou NoOp se nenhum foi registrado)
75
+ */
76
+ getPlugin() {
77
+ return this.plugin;
78
+ }
79
+ /**
80
+ * Verifica se um plugin real foi registrado
81
+ */
82
+ hasPlugin() {
83
+ return !(this.plugin instanceof NoOpArchivePlugin);
84
+ }
85
+ /**
86
+ * Reseta o registry (útil para testes)
87
+ */
88
+ reset() {
89
+ this.plugin = new NoOpArchivePlugin();
90
+ }
91
+ }
92
+ exports.ArchivePluginRegistry = ArchivePluginRegistry;
93
+ ArchivePluginRegistry.instance = null;
94
+ // ========== Funções de conveniência ==========
95
+ /**
96
+ * Registra um plugin de archive
97
+ * Deve ser chamado no início da aplicação, antes de usar repositórios
98
+ *
99
+ * @param plugin - Instância do plugin de archive
100
+ *
101
+ * @example
102
+ * ```typescript
103
+ * import { registerArchivePlugin } from '@roit/roit-data-firestore';
104
+ * import { createArchivePlugin } from 'firestore-archive';
105
+ *
106
+ * // No bootstrap da aplicação
107
+ * registerArchivePlugin(createArchivePlugin());
108
+ * ```
109
+ */
110
+ function registerArchivePlugin(plugin) {
111
+ ArchivePluginRegistry.getInstance().register(plugin);
112
+ }
113
+ exports.registerArchivePlugin = registerArchivePlugin;
114
+ /**
115
+ * Retorna o plugin de archive registrado
116
+ * Se nenhum plugin foi registrado, retorna um plugin NoOp que desabilita todas as operações
117
+ */
118
+ function getArchivePlugin() {
119
+ return ArchivePluginRegistry.getInstance().getPlugin();
120
+ }
121
+ exports.getArchivePlugin = getArchivePlugin;
122
+ /**
123
+ * Verifica se um plugin de archive foi registrado
124
+ */
125
+ function hasArchivePlugin() {
126
+ return ArchivePluginRegistry.getInstance().hasPlugin();
127
+ }
128
+ exports.hasArchivePlugin = hasArchivePlugin;
129
+ /**
130
+ * Reseta o registry de plugins (útil para testes)
131
+ */
132
+ function resetArchivePlugin() {
133
+ ArchivePluginRegistry.getInstance().reset();
134
+ }
135
+ exports.resetArchivePlugin = resetArchivePlugin;
@@ -1,40 +1,90 @@
1
+ /**
2
+ * Interface para opções de atualização de documento arquivado
3
+ */
4
+ interface UpdateArchivedDocumentOptions {
5
+ /** Se true, remove o documento arquivado após a atualização (desarquivamento) */
6
+ unarchive?: boolean;
7
+ }
8
+ /**
9
+ * Resultado de operações de arquivamento
10
+ */
11
+ interface ArchiveOperationResult {
12
+ success: boolean;
13
+ message?: string;
14
+ error?: Error;
15
+ }
1
16
  export declare class ArchiveService {
2
17
  private static instance;
3
18
  private static readonly lock;
4
19
  private static isInitializing;
5
- private storage;
6
- private bucketName;
7
20
  private config;
8
- private cacheResolver;
21
+ /** ProjectId do Firestore sendo arquivado (para organização de paths) */
9
22
  private projectId;
10
- private firestore;
11
23
  private isInitialized;
24
+ private logger;
12
25
  /**
13
- * Construtor privado para prevenir instanciação direta
14
- */
26
+ * Construtor privado para prevenir instanciação direta
27
+ */
15
28
  private constructor();
16
29
  static getInstance(): Promise<ArchiveService>;
17
30
  private initialize;
18
31
  static resetInstance(): void;
19
32
  /**
20
33
  * Verifica se o arquivamento está habilitado
34
+ * Requer que o plugin firestore-archive esteja registrado
21
35
  */
22
36
  isEnabled(): boolean;
23
37
  /**
24
38
  * Verifica se um documento está arquivado
25
39
  */
26
40
  isDocumentArchived(documentData: any): boolean;
27
- private pipeline;
28
- /**
29
- * Recupera documento arquivado em formato JSON
30
- */
31
- private retrieveJsonDocument;
32
41
  /**
33
42
  * Verifica se um documento está arquivado e recupera seus dados completos
34
43
  */
35
44
  getArchivedDocument(collectionName: string, doc: any): Promise<Record<string, any> | null>;
45
+ /**
46
+ * Atualiza um documento arquivado no Cloud Storage
47
+ * Usado quando um documento arquivado é atualizado no Firestore
48
+ *
49
+ * @param collectionName - Nome da collection
50
+ * @param docId - ID do documento
51
+ * @param newData - Novos dados a serem mesclados com o documento arquivado
52
+ * @param archivePath - Path completo do objeto no Storage, normalmente o `fbArchivePath` do stub.
53
+ * @param options - Opções de atualização
54
+ * @returns Resultado da operação e dados mesclados
55
+ */
56
+ updateArchivedDocument(collectionName: string, docId: string, newData: Record<string, any>, archivePath: string, options?: UpdateArchivedDocumentOptions): Promise<{
57
+ result: ArchiveOperationResult;
58
+ mergedData?: Record<string, any>;
59
+ }>;
60
+ /**
61
+ * Deleta um documento arquivado do Cloud Storage
62
+ * Usado quando um documento é permanentemente deletado ou restaurado
63
+ *
64
+ * @param collectionName - Nome da collection
65
+ * @param docId - ID do documento
66
+ * @param archivePath - Path completo do objeto no Storage, normalmente o `fbArchivePath` do stub.
67
+ * @returns Resultado da operação
68
+ */
69
+ deleteArchivedDocument(collectionName: string, docId: string, archivePath: string): Promise<ArchiveOperationResult>;
70
+ /**
71
+ * Recupera dados completos de um documento arquivado e o prepara para restauração
72
+ * Combina os dados do stub (Firestore) com os dados arquivados (Storage)
73
+ *
74
+ * @param collectionName - Nome da collection
75
+ * @param stubData - Dados do stub no Firestore (inclui fbArchivedAt)
76
+ * @returns Dados completos mesclados ou null se não encontrado
77
+ */
78
+ getCompleteArchivedDocument(collectionName: string, stubData: Record<string, any>): Promise<Record<string, any> | null>;
36
79
  /**
37
80
  * Limpa o cache de documentos arquivados
81
+ * Delega para o plugin firestore-archive
38
82
  */
39
83
  clearArchivedCache(collectionName?: string, docId?: string): Promise<void>;
84
+ /**
85
+ * Retorna o projectId do Firestore sendo arquivado
86
+ * (usado para organização de paths no Storage)
87
+ */
88
+ getProjectId(): string;
40
89
  }
90
+ export {};