@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.
- package/README.md +107 -0
- package/dist/archive/ArchivePluginRegistry.d.ts +78 -0
- package/dist/archive/ArchivePluginRegistry.js +135 -0
- package/dist/archive/ArchiveService.d.ts +61 -11
- package/dist/archive/ArchiveService.js +138 -120
- package/dist/archive/IArchivePlugin.d.ts +102 -0
- package/dist/archive/IArchivePlugin.js +12 -0
- package/dist/archive/index.d.ts +2 -0
- package/dist/archive/index.js +11 -0
- package/dist/cache/CacheResolver.js +6 -5
- package/dist/config/ArchiveConfig.d.ts +17 -12
- package/dist/config/ArchiveConfig.js +25 -41
- package/dist/config/BaseRepository.js +1 -1
- package/dist/config/ReadonlyRepository.js +1 -1
- package/dist/exception/RepositoryException.js +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +10 -1
- package/dist/model/CacheProviders.d.ts +1 -2
- package/dist/model/CacheProviders.js +1 -2
- package/dist/query/ManualQueryHelper.js +0 -1
- package/dist/query/QueryPredicateFunctionTransform.js +4 -1
- package/dist/template/FunctionAggregationTemplate.txt +1 -1
- package/dist/template/FunctionAverageTemplate.txt +1 -1
- package/dist/template/FunctionCountTemplate.txt +20 -25
- package/dist/template/FunctionCreateOrUpdateTemplate.txt +69 -20
- package/dist/template/FunctionCreateTemplate.txt +15 -13
- package/dist/template/FunctionDeleteTemplate.txt +45 -13
- package/dist/template/FunctionFindAllTemplate.txt +39 -23
- package/dist/template/FunctionFindByIdTemplate.txt +24 -14
- package/dist/template/FunctionQueryTemplate.txt +67 -41
- package/dist/template/FunctionSumTemplate.txt +48 -32
- package/dist/template/FunctionUpdatePartialTemplate.txt +76 -21
- package/dist/template/FunctionUpdateTemplate.txt +64 -17
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/dist/cache/providers/RedisCacheArchiveProvider.d.ts +0 -19
- package/dist/cache/providers/RedisCacheArchiveProvider.js +0 -115
|
@@ -1,40 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
3
|
exports.ArchiveService = void 0;
|
|
27
|
-
const storage_1 = require("@google-cloud/storage");
|
|
28
|
-
const zlib = __importStar(require("zlib"));
|
|
29
|
-
const stream_1 = require("stream");
|
|
30
4
|
const ArchiveConfig_1 = require("../config/ArchiveConfig");
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
5
|
+
const index_1 = require("./index");
|
|
6
|
+
/**
|
|
7
|
+
* Logger interno para padronizar logs do ArchiveService
|
|
8
|
+
*/
|
|
9
|
+
class ArchiveLogger {
|
|
10
|
+
constructor(debug) {
|
|
11
|
+
this.prefix = '[ArchiveServices]';
|
|
12
|
+
this.isDebug = debug;
|
|
13
|
+
}
|
|
14
|
+
debug(message, ...args) {
|
|
15
|
+
if (this.isDebug) {
|
|
16
|
+
console.debug(`${this.prefix} ${message}`, ...args);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
info(message, ...args) {
|
|
20
|
+
if (this.isDebug) {
|
|
21
|
+
console.info(`${this.prefix} ${message}`, ...args);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
warn(message, ...args) {
|
|
25
|
+
console.warn(`${this.prefix} ${message}`, ...args);
|
|
26
|
+
}
|
|
27
|
+
error(message, ...args) {
|
|
28
|
+
console.error(`${this.prefix} ${message}`, ...args);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
34
31
|
class ArchiveService {
|
|
35
32
|
/**
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
* Construtor privado para prevenir instanciação direta
|
|
34
|
+
*/
|
|
38
35
|
constructor() {
|
|
39
36
|
this.isInitialized = false;
|
|
40
37
|
// Construtor vazio - inicialização será feita em initialize()
|
|
@@ -67,33 +64,23 @@ class ArchiveService {
|
|
|
67
64
|
return;
|
|
68
65
|
}
|
|
69
66
|
this.config = ArchiveConfig_1.ArchiveConfig.getConfig();
|
|
70
|
-
this.
|
|
67
|
+
this.logger = new ArchiveLogger(this.config.debug);
|
|
68
|
+
// ProjectId do Firestore que está sendo arquivado (usado para paths no Storage)
|
|
71
69
|
this.projectId = this.config.projectId;
|
|
72
|
-
(
|
|
73
|
-
|
|
74
|
-
this.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
// REGISTRAR O ARCHIVESERVICE COMO REPOSITORY
|
|
79
|
-
this.cacheResolver.addRepository('ArchiveService', {
|
|
80
|
-
cacheExpiresInSeconds: 3600,
|
|
81
|
-
cacheProvider: CacheProviders_1.CacheProviders.REDIS_ARCHIVE
|
|
82
|
-
});
|
|
70
|
+
if (!this.projectId) {
|
|
71
|
+
this.logger.warn('projectId não configurado - usando variável de ambiente');
|
|
72
|
+
this.projectId = process.env.FIRESTORE_PROJECTID || process.env.GCP_PROJECT || '';
|
|
73
|
+
}
|
|
74
|
+
this.logger.debug(`Configuração: projectId=${this.projectId}, enabled=${this.config.enabled}`);
|
|
83
75
|
if (!this.config.enabled) {
|
|
84
|
-
|
|
76
|
+
this.logger.info('Arquivamento desabilitado via configuração');
|
|
77
|
+
this.isInitialized = true;
|
|
85
78
|
return;
|
|
86
79
|
}
|
|
87
|
-
|
|
88
|
-
this.
|
|
89
|
-
this.bucketName = this.config.bucketName;
|
|
90
|
-
if (!this.bucketName) {
|
|
91
|
-
(0, ArchiveConfig_1.onDebugWarn)('ArchiveService: bucket_name não configurado');
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
(0, ArchiveConfig_1.onDebugLog)(`Bucket configurado: ${this.bucketName}`);
|
|
95
|
-
}
|
|
80
|
+
if (!(0, index_1.hasArchivePlugin)()) {
|
|
81
|
+
this.logger.warn('Plugin firestore-archive não registrado - arquivamento desabilitado');
|
|
96
82
|
}
|
|
83
|
+
this.isInitialized = true;
|
|
97
84
|
}
|
|
98
85
|
static resetInstance() {
|
|
99
86
|
ArchiveService.instance = null;
|
|
@@ -101,9 +88,11 @@ class ArchiveService {
|
|
|
101
88
|
}
|
|
102
89
|
/**
|
|
103
90
|
* Verifica se o arquivamento está habilitado
|
|
91
|
+
* Requer que o plugin firestore-archive esteja registrado
|
|
104
92
|
*/
|
|
105
93
|
isEnabled() {
|
|
106
|
-
|
|
94
|
+
// Arquivamento só funciona com plugin registrado
|
|
95
|
+
return this.config.enabled && (0, index_1.hasArchivePlugin)();
|
|
107
96
|
}
|
|
108
97
|
/**
|
|
109
98
|
* Verifica se um documento está arquivado
|
|
@@ -112,43 +101,7 @@ class ArchiveService {
|
|
|
112
101
|
if (!this.isEnabled()) {
|
|
113
102
|
return false;
|
|
114
103
|
}
|
|
115
|
-
return
|
|
116
|
-
}
|
|
117
|
-
async pipeline(readStream, gunzip, writable) {
|
|
118
|
-
return new Promise((resolve, reject) => {
|
|
119
|
-
readStream.pipe(gunzip).pipe(writable);
|
|
120
|
-
writable.on('finish', resolve);
|
|
121
|
-
writable.on('error', reject);
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* Recupera documento arquivado em formato JSON
|
|
126
|
-
*/
|
|
127
|
-
async retrieveJsonDocument(collectionName, docId) {
|
|
128
|
-
try {
|
|
129
|
-
const filePath = `${this.projectId}/${collectionName}/${docId}.json.gz`;
|
|
130
|
-
const bucket = this.storage.bucket(this.bucketName);
|
|
131
|
-
const file = bucket.file(filePath);
|
|
132
|
-
const [exists] = await file.exists();
|
|
133
|
-
if (!exists) {
|
|
134
|
-
return null;
|
|
135
|
-
}
|
|
136
|
-
const readStream = file.createReadStream();
|
|
137
|
-
const gunzip = zlib.createGunzip();
|
|
138
|
-
const chunks = [];
|
|
139
|
-
await this.pipeline(readStream, gunzip, new stream_1.Writable({
|
|
140
|
-
write(chunk, _enc, cb) {
|
|
141
|
-
chunks.push(chunk);
|
|
142
|
-
cb();
|
|
143
|
-
}
|
|
144
|
-
}));
|
|
145
|
-
const result = Buffer.concat(chunks).toString('utf-8');
|
|
146
|
-
return JSON.parse(result);
|
|
147
|
-
}
|
|
148
|
-
catch (error) {
|
|
149
|
-
console.log(`${ArchiveConfig_1.DEBUG_PREFIX} Erro ao recuperar documento JSON arquivado ${collectionName}/${docId}:`, error);
|
|
150
|
-
return null;
|
|
151
|
-
}
|
|
104
|
+
return (0, index_1.getArchivePlugin)().isDocumentArchived(documentData);
|
|
152
105
|
}
|
|
153
106
|
/**
|
|
154
107
|
* Verifica se um documento está arquivado e recupera seus dados completos
|
|
@@ -157,45 +110,110 @@ class ArchiveService {
|
|
|
157
110
|
if (!this.isEnabled()) {
|
|
158
111
|
return null;
|
|
159
112
|
}
|
|
160
|
-
if (!this.bucketName) {
|
|
161
|
-
console.warn(`${ArchiveConfig_1.DEBUG_PREFIX} ArchiveService: bucket_name não configurado, não é possível recuperar documentos arquivados`);
|
|
162
|
-
return null;
|
|
163
|
-
}
|
|
164
113
|
const docId = doc.id;
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
114
|
+
const archivePath = typeof doc?.[index_1.ARCHIVE_METADATA_FIELDS.ARCHIVE_PATH] === 'string'
|
|
115
|
+
? doc[index_1.ARCHIVE_METADATA_FIELDS.ARCHIVE_PATH]
|
|
116
|
+
: '';
|
|
117
|
+
if (!archivePath || archivePath.trim().length === 0) {
|
|
118
|
+
throw new Error(`ArchiveService.getArchivedDocument: fbArchivePath is required. collection=${collectionName} docId=${docId}`);
|
|
119
|
+
}
|
|
120
|
+
// Delega para plugin (isEnabled já garante que existe)
|
|
121
|
+
return (0, index_1.getArchivePlugin)().getArchivedDocument({
|
|
122
|
+
collection: collectionName,
|
|
123
|
+
docId,
|
|
124
|
+
archivePath,
|
|
125
|
+
projectId: this.projectId,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Atualiza um documento arquivado no Cloud Storage
|
|
130
|
+
* Usado quando um documento arquivado é atualizado no Firestore
|
|
131
|
+
*
|
|
132
|
+
* @param collectionName - Nome da collection
|
|
133
|
+
* @param docId - ID do documento
|
|
134
|
+
* @param newData - Novos dados a serem mesclados com o documento arquivado
|
|
135
|
+
* @param archivePath - Path completo do objeto no Storage, normalmente o `fbArchivePath` do stub.
|
|
136
|
+
* @param options - Opções de atualização
|
|
137
|
+
* @returns Resultado da operação e dados mesclados
|
|
138
|
+
*/
|
|
139
|
+
async updateArchivedDocument(collectionName, docId, newData, archivePath, options) {
|
|
140
|
+
if (!this.isEnabled()) {
|
|
141
|
+
return { result: { success: false, message: 'Arquivamento desabilitado ou plugin não registrado' } };
|
|
142
|
+
}
|
|
143
|
+
if (!archivePath || typeof archivePath !== 'string' || archivePath.trim().length === 0) {
|
|
144
|
+
throw new Error(`ArchiveService.updateArchivedDocument: fbArchivePath is required. collection=${collectionName} docId=${docId}`);
|
|
145
|
+
}
|
|
146
|
+
// Delega para plugin (isEnabled já garante que existe)
|
|
147
|
+
return (0, index_1.getArchivePlugin)().updateArchivedDocument({
|
|
148
|
+
collection: collectionName,
|
|
149
|
+
docId,
|
|
150
|
+
newData,
|
|
151
|
+
options,
|
|
152
|
+
projectId: this.projectId,
|
|
153
|
+
archivePath,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Deleta um documento arquivado do Cloud Storage
|
|
158
|
+
* Usado quando um documento é permanentemente deletado ou restaurado
|
|
159
|
+
*
|
|
160
|
+
* @param collectionName - Nome da collection
|
|
161
|
+
* @param docId - ID do documento
|
|
162
|
+
* @param archivePath - Path completo do objeto no Storage, normalmente o `fbArchivePath` do stub.
|
|
163
|
+
* @returns Resultado da operação
|
|
164
|
+
*/
|
|
165
|
+
async deleteArchivedDocument(collectionName, docId, archivePath) {
|
|
166
|
+
if (!this.isEnabled()) {
|
|
167
|
+
return { success: false, message: 'Arquivamento desabilitado ou plugin não registrado' };
|
|
185
168
|
}
|
|
186
|
-
|
|
187
|
-
|
|
169
|
+
if (!archivePath || typeof archivePath !== 'string' || archivePath.trim().length === 0) {
|
|
170
|
+
throw new Error(`ArchiveService.deleteArchivedDocument: fbArchivePath is required. collection=${collectionName} docId=${docId}`);
|
|
188
171
|
}
|
|
189
|
-
|
|
172
|
+
// Delega para plugin (isEnabled já garante que existe)
|
|
173
|
+
return (0, index_1.getArchivePlugin)().deleteArchivedDocument({
|
|
174
|
+
collection: collectionName,
|
|
175
|
+
docId,
|
|
176
|
+
projectId: this.projectId,
|
|
177
|
+
archivePath,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Recupera dados completos de um documento arquivado e o prepara para restauração
|
|
182
|
+
* Combina os dados do stub (Firestore) com os dados arquivados (Storage)
|
|
183
|
+
*
|
|
184
|
+
* @param collectionName - Nome da collection
|
|
185
|
+
* @param stubData - Dados do stub no Firestore (inclui fbArchivedAt)
|
|
186
|
+
* @returns Dados completos mesclados ou null se não encontrado
|
|
187
|
+
*/
|
|
188
|
+
async getCompleteArchivedDocument(collectionName, stubData) {
|
|
189
|
+
if (!this.isDocumentArchived(stubData)) {
|
|
190
|
+
return stubData;
|
|
191
|
+
}
|
|
192
|
+
const archivedData = await this.getArchivedDocument(collectionName, stubData);
|
|
193
|
+
if (!archivedData) {
|
|
194
|
+
this.logger.warn(`Dados arquivados não encontrados para documento: ${collectionName}/${stubData.id}`);
|
|
195
|
+
return stubData; // Retorna stub se não encontrar dados arquivados
|
|
196
|
+
}
|
|
197
|
+
// Mesclar: dados do storage sobrescrevem o stub, exceto fbArchivedAt
|
|
198
|
+
const { fbArchivedAt } = stubData;
|
|
199
|
+
return { ...stubData, ...archivedData, fbArchivedAt };
|
|
190
200
|
}
|
|
191
201
|
/**
|
|
192
202
|
* Limpa o cache de documentos arquivados
|
|
203
|
+
* Delega para o plugin firestore-archive
|
|
193
204
|
*/
|
|
194
205
|
async clearArchivedCache(collectionName, docId) {
|
|
195
|
-
if (!this.
|
|
206
|
+
if (!this.isEnabled()) {
|
|
196
207
|
return;
|
|
197
208
|
}
|
|
198
|
-
await
|
|
209
|
+
await (0, index_1.getArchivePlugin)().invalidateCache(collectionName, docId);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Retorna o projectId do Firestore sendo arquivado
|
|
213
|
+
* (usado para organização de paths no Storage)
|
|
214
|
+
*/
|
|
215
|
+
getProjectId() {
|
|
216
|
+
return this.projectId;
|
|
199
217
|
}
|
|
200
218
|
}
|
|
201
219
|
exports.ArchiveService = ArchiveService;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interface para plugins de arquivamento
|
|
3
|
+
*
|
|
4
|
+
* Esta interface define o contrato que plugins de archive devem implementar.
|
|
5
|
+
* O plugin `firestore-archive` implementa esta interface.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { registerArchivePlugin } from '@roit/roit-data-firestore';
|
|
10
|
+
* import { createArchivePlugin } from 'firestore-archive';
|
|
11
|
+
*
|
|
12
|
+
* // Registrar o plugin no início da aplicação
|
|
13
|
+
* registerArchivePlugin(createArchivePlugin());
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export interface IArchivePlugin {
|
|
17
|
+
/**
|
|
18
|
+
* Verifica se o arquivamento está habilitado
|
|
19
|
+
*/
|
|
20
|
+
isEnabled(): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Verifica se um documento está arquivado (tem fbArchivedAt)
|
|
23
|
+
*/
|
|
24
|
+
isDocumentArchived(doc: Record<string, unknown>): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Recupera documento arquivado do Storage.
|
|
27
|
+
*
|
|
28
|
+
* @param collection - Nome da collection
|
|
29
|
+
* @param docId - ID do documento
|
|
30
|
+
* @param archivePath - Path completo do objeto no Storage, normalmente o `fbArchivePath` do stub.
|
|
31
|
+
* @param projectId - ID do projeto (opcional)
|
|
32
|
+
* @returns Resultado da operação
|
|
33
|
+
*/
|
|
34
|
+
getArchivedDocument(params: {
|
|
35
|
+
collection: string;
|
|
36
|
+
docId: string;
|
|
37
|
+
archivePath: string;
|
|
38
|
+
projectId?: string;
|
|
39
|
+
}): Promise<Record<string, unknown> | null>;
|
|
40
|
+
/**
|
|
41
|
+
* Atualiza documento arquivado (merge dados do Storage com novos dados)
|
|
42
|
+
*
|
|
43
|
+
* @param collection - Nome da collection
|
|
44
|
+
* @param docId - ID do documento
|
|
45
|
+
* @param newData - Novos dados para mesclar
|
|
46
|
+
* @param options - Opções (unarchive: true para remover do Storage)
|
|
47
|
+
* @param projectId - ID do projeto (opcional)
|
|
48
|
+
* @param archivePath - Path completo do objeto no Storage, normalmente o `fbArchivePath` do stub. É obrigatório quando unarchive=true
|
|
49
|
+
* @returns Resultado com dados mesclados
|
|
50
|
+
*/
|
|
51
|
+
updateArchivedDocument(params: {
|
|
52
|
+
collection: string;
|
|
53
|
+
docId: string;
|
|
54
|
+
newData: Record<string, unknown>;
|
|
55
|
+
options?: {
|
|
56
|
+
unarchive?: boolean;
|
|
57
|
+
};
|
|
58
|
+
projectId?: string;
|
|
59
|
+
archivePath: string;
|
|
60
|
+
}): Promise<{
|
|
61
|
+
result: {
|
|
62
|
+
success: boolean;
|
|
63
|
+
message?: string;
|
|
64
|
+
error?: Error;
|
|
65
|
+
};
|
|
66
|
+
mergedData?: Record<string, unknown>;
|
|
67
|
+
}>;
|
|
68
|
+
/**
|
|
69
|
+
* Deleta documento arquivado do Storage
|
|
70
|
+
*
|
|
71
|
+
* @param collection - Nome da collection
|
|
72
|
+
* @param docId - ID do documento
|
|
73
|
+
* @param projectId - ID do projeto (opcional)
|
|
74
|
+
* @returns Resultado da operação
|
|
75
|
+
*/
|
|
76
|
+
deleteArchivedDocument(params: {
|
|
77
|
+
collection: string;
|
|
78
|
+
docId: string;
|
|
79
|
+
archivePath: string;
|
|
80
|
+
projectId?: string;
|
|
81
|
+
}): Promise<{
|
|
82
|
+
success: boolean;
|
|
83
|
+
message?: string;
|
|
84
|
+
error?: Error;
|
|
85
|
+
}>;
|
|
86
|
+
/**
|
|
87
|
+
* Invalida cache de documentos arquivados
|
|
88
|
+
*
|
|
89
|
+
* @param collection - Nome da collection (opcional)
|
|
90
|
+
* @param docId - ID do documento (opcional)
|
|
91
|
+
*/
|
|
92
|
+
invalidateCache(collection?: string, docId?: string): Promise<void>;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Campos de metadados de arquivamento no Firestore
|
|
96
|
+
*/
|
|
97
|
+
export declare const ARCHIVE_METADATA_FIELDS: {
|
|
98
|
+
readonly ARCHIVED_AT: "fbArchivedAt";
|
|
99
|
+
readonly ARCHIVE_HASH: "fbArchiveHash";
|
|
100
|
+
readonly ARCHIVE_PATH: "fbArchivePath";
|
|
101
|
+
readonly RESTORED_AT: "fbRestoredAt";
|
|
102
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ARCHIVE_METADATA_FIELDS = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Campos de metadados de arquivamento no Firestore
|
|
6
|
+
*/
|
|
7
|
+
exports.ARCHIVE_METADATA_FIELDS = {
|
|
8
|
+
ARCHIVED_AT: 'fbArchivedAt',
|
|
9
|
+
ARCHIVE_HASH: 'fbArchiveHash',
|
|
10
|
+
ARCHIVE_PATH: 'fbArchivePath',
|
|
11
|
+
RESTORED_AT: 'fbRestoredAt',
|
|
12
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ArchivePluginRegistry = exports.resetArchivePlugin = exports.hasArchivePlugin = exports.getArchivePlugin = exports.registerArchivePlugin = exports.ARCHIVE_METADATA_FIELDS = void 0;
|
|
4
|
+
var IArchivePlugin_1 = require("./IArchivePlugin");
|
|
5
|
+
Object.defineProperty(exports, "ARCHIVE_METADATA_FIELDS", { enumerable: true, get: function () { return IArchivePlugin_1.ARCHIVE_METADATA_FIELDS; } });
|
|
6
|
+
var ArchivePluginRegistry_1 = require("./ArchivePluginRegistry");
|
|
7
|
+
Object.defineProperty(exports, "registerArchivePlugin", { enumerable: true, get: function () { return ArchivePluginRegistry_1.registerArchivePlugin; } });
|
|
8
|
+
Object.defineProperty(exports, "getArchivePlugin", { enumerable: true, get: function () { return ArchivePluginRegistry_1.getArchivePlugin; } });
|
|
9
|
+
Object.defineProperty(exports, "hasArchivePlugin", { enumerable: true, get: function () { return ArchivePluginRegistry_1.hasArchivePlugin; } });
|
|
10
|
+
Object.defineProperty(exports, "resetArchivePlugin", { enumerable: true, get: function () { return ArchivePluginRegistry_1.resetArchivePlugin; } });
|
|
11
|
+
Object.defineProperty(exports, "ArchivePluginRegistry", { enumerable: true, get: function () { return ArchivePluginRegistry_1.ArchivePluginRegistry; } });
|
|
@@ -7,8 +7,6 @@ const RedisCacheProvider_1 = require("./providers/RedisCacheProvider");
|
|
|
7
7
|
const CacheProviders_1 = require("../model/CacheProviders");
|
|
8
8
|
const CurrentEnv_1 = require("../util/CurrentEnv");
|
|
9
9
|
const QueryPredicateFunctionTransform_1 = require("../query/QueryPredicateFunctionTransform");
|
|
10
|
-
const RedisCacheArchiveProvider_1 = require("./providers/RedisCacheArchiveProvider");
|
|
11
|
-
const ArchiveConfig_1 = require("../config/ArchiveConfig");
|
|
12
10
|
const IsDebug_1 = require("../util/IsDebug");
|
|
13
11
|
class CacheResolver {
|
|
14
12
|
constructor() {
|
|
@@ -16,7 +14,6 @@ class CacheResolver {
|
|
|
16
14
|
this.providersImplMap = new Map;
|
|
17
15
|
this.providersImplMap.set(CacheProviders_1.CacheProviders.LOCAL, providers_1.InMemoryCacheProvider);
|
|
18
16
|
this.providersImplMap.set(CacheProviders_1.CacheProviders.REDIS, RedisCacheProvider_1.RedisCacheProvider);
|
|
19
|
-
this.providersImplMap.set(CacheProviders_1.CacheProviders.REDIS_ARCHIVE, RedisCacheArchiveProvider_1.RedisCacheArchiveProvider);
|
|
20
17
|
}
|
|
21
18
|
static getInstance() {
|
|
22
19
|
return this.instance;
|
|
@@ -99,7 +96,9 @@ class CacheResolver {
|
|
|
99
96
|
shouldDelete = key.includes('getArchivedDocument');
|
|
100
97
|
}
|
|
101
98
|
if (shouldDelete) {
|
|
102
|
-
(
|
|
99
|
+
if (IsDebug_1.isDebug) {
|
|
100
|
+
console.debug('[DEBUG] Archive Cache >', `Removing key: ${key}`);
|
|
101
|
+
}
|
|
103
102
|
await this.cacheProvider.delete(key);
|
|
104
103
|
}
|
|
105
104
|
}
|
|
@@ -120,7 +119,9 @@ class CacheResolver {
|
|
|
120
119
|
if (archiveKeys && Array.isArray(archiveKeys)) {
|
|
121
120
|
for (const key of archiveKeys) {
|
|
122
121
|
if (key.includes(`getArchivedDocument:archived_${collectionName}`)) {
|
|
123
|
-
(
|
|
122
|
+
if (IsDebug_1.isDebug) {
|
|
123
|
+
console.debug('[DEBUG] Archive Cache >', `Removing archive key: ${key}`);
|
|
124
|
+
}
|
|
124
125
|
await this.cacheProvider.delete(key);
|
|
125
126
|
}
|
|
126
127
|
}
|
|
@@ -1,20 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configurações mínimas para o ArchiveService no roit-data-firestore.
|
|
3
|
+
*
|
|
4
|
+
* Nota: As configurações detalhadas de Storage e Cache agora são
|
|
5
|
+
* responsabilidade do plugin firestore-archive.
|
|
6
|
+
*/
|
|
1
7
|
export interface ArchiveConfig {
|
|
8
|
+
/** Se o arquivamento está habilitado */
|
|
2
9
|
enabled: boolean;
|
|
3
|
-
|
|
10
|
+
/** Habilita logs de debug */
|
|
4
11
|
debug: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* ProjectId do Firestore que está sendo arquivado.
|
|
14
|
+
* Usado para organizar os arquivos no Storage: {projectId}/{collection}/{docId}.json.gz
|
|
15
|
+
*/
|
|
5
16
|
projectId: string;
|
|
6
|
-
cache: {
|
|
7
|
-
enabled: boolean;
|
|
8
|
-
redisUrl: string;
|
|
9
|
-
timeout: number;
|
|
10
|
-
reconnectInSecondsAfterTimeout: number;
|
|
11
|
-
expiresInSeconds: number;
|
|
12
|
-
};
|
|
13
17
|
}
|
|
14
18
|
export declare class ArchiveConfig {
|
|
19
|
+
private static instance;
|
|
15
20
|
static getConfig(): ArchiveConfig;
|
|
21
|
+
/**
|
|
22
|
+
* Reseta a configuração (útil para testes)
|
|
23
|
+
*/
|
|
24
|
+
static reset(): void;
|
|
16
25
|
}
|
|
17
|
-
export declare const DEBUG_PREFIX = "[ARCHIVE SERVICE]";
|
|
18
|
-
export declare const onDebugLog: (message: string) => void;
|
|
19
|
-
export declare const onDebugError: (message: string, error: any) => void;
|
|
20
|
-
export declare const onDebugWarn: (message: string) => void;
|
|
@@ -1,49 +1,33 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Configurações mínimas para o ArchiveService no roit-data-firestore.
|
|
4
|
+
*
|
|
5
|
+
* Nota: As configurações detalhadas de Storage e Cache agora são
|
|
6
|
+
* responsabilidade do plugin firestore-archive.
|
|
7
|
+
*/
|
|
2
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const FIRESTORE_ARCHIVE_BUCKET_NAME = process.env.FIRESTORE_ARCHIVE_BUCKET_NAME || "firestore-archive-roit";
|
|
8
|
-
const FIRESTORE_ARCHIVE_CACHE_ENABLED = process.env.FIRESTORE_ARCHIVE_CACHE_ENABLED || false;
|
|
9
|
-
const FIRESTORE_ARCHIVE_CACHE_REDIS_URL = process.env.FIRESTORE_ARCHIVE_CACHE_REDISURL || '';
|
|
10
|
-
const FIRESTORE_ARCHIVE_CACHE_REDIS_TIMEOUT = process.env.FIRESTORE_ARCHIVE_CACHE_REDIS_TIMEOUT || 2000;
|
|
11
|
-
const FIRESTORE_ARCHIVE_CACHE_REDIS_RECONNECT_IN_SECONDS_AFTER_TIMEOUT = process.env.FIRESTORE_ARCHIVE_CACHE_REDIS_RECONNECT_IN_SECONDS_AFTER_TIMEOUT || 30;
|
|
12
|
-
const FIRESTORE_ARCHIVE_CACHE_EXPIRES_IN_SECONDS = process.env.FIRESTORE_ARCHIVE_CACHE_EXPIRESINSECONDS || 3600;
|
|
9
|
+
exports.ArchiveConfig = void 0;
|
|
10
|
+
const parseBoolean = (value) => {
|
|
11
|
+
return value === true || value === 'true';
|
|
12
|
+
};
|
|
13
13
|
class ArchiveConfig {
|
|
14
14
|
static getConfig() {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
redisUrl: FIRESTORE_ARCHIVE_CACHE_REDIS_URL,
|
|
23
|
-
timeout: FIRESTORE_ARCHIVE_CACHE_REDIS_TIMEOUT,
|
|
24
|
-
reconnectInSecondsAfterTimeout: FIRESTORE_ARCHIVE_CACHE_REDIS_RECONNECT_IN_SECONDS_AFTER_TIMEOUT,
|
|
25
|
-
expiresInSeconds: FIRESTORE_ARCHIVE_CACHE_EXPIRES_IN_SECONDS
|
|
26
|
-
}
|
|
15
|
+
if (this.instance) {
|
|
16
|
+
return this.instance;
|
|
17
|
+
}
|
|
18
|
+
this.instance = {
|
|
19
|
+
enabled: parseBoolean(process.env.FIRESTORE_ARCHIVE_ENABLED),
|
|
20
|
+
debug: parseBoolean(process.env.FIRESTORE_ARCHIVE_DEBUG),
|
|
21
|
+
projectId: process.env.FIRESTORE_PROJECTID || process.env.GCP_PROJECT || '',
|
|
27
22
|
};
|
|
23
|
+
return this.instance;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Reseta a configuração (útil para testes)
|
|
27
|
+
*/
|
|
28
|
+
static reset() {
|
|
29
|
+
this.instance = null;
|
|
28
30
|
}
|
|
29
31
|
}
|
|
30
32
|
exports.ArchiveConfig = ArchiveConfig;
|
|
31
|
-
|
|
32
|
-
const onDebugLog = (message) => {
|
|
33
|
-
if (ArchiveConfig.getConfig().debug) {
|
|
34
|
-
console.log(`${exports.DEBUG_PREFIX} ${message}`);
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
exports.onDebugLog = onDebugLog;
|
|
38
|
-
const onDebugError = (message, error) => {
|
|
39
|
-
if (ArchiveConfig.getConfig().debug) {
|
|
40
|
-
console.error(`${exports.DEBUG_PREFIX} ${message}`, error);
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
exports.onDebugError = onDebugError;
|
|
44
|
-
const onDebugWarn = (message) => {
|
|
45
|
-
if (ArchiveConfig.getConfig().debug) {
|
|
46
|
-
console.warn(`${exports.DEBUG_PREFIX} ${message}`);
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
exports.onDebugWarn = onDebugWarn;
|
|
33
|
+
ArchiveConfig.instance = null;
|
|
@@ -36,7 +36,6 @@ class BaseRepository {
|
|
|
36
36
|
await archiveService.clearArchivedCache(collectionName, docId);
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
|
-
exports.BaseRepository = BaseRepository;
|
|
40
39
|
__decorate([
|
|
41
40
|
(0, Query_1.Query)(),
|
|
42
41
|
__metadata("design:type", Function)
|
|
@@ -85,3 +84,4 @@ __decorate([
|
|
|
85
84
|
(0, Query_1.Query)(),
|
|
86
85
|
__metadata("design:type", Function)
|
|
87
86
|
], BaseRepository.prototype, "aggregation", void 0);
|
|
87
|
+
exports.BaseRepository = BaseRepository;
|
|
@@ -22,7 +22,6 @@ class ReadonlyRepository {
|
|
|
22
22
|
return ManualQueryHelper_1.ManualQueryHelper.executeQueryManualPaginated(className, config);
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
-
exports.ReadonlyRepository = ReadonlyRepository;
|
|
26
25
|
__decorate([
|
|
27
26
|
(0, Query_1.Query)(),
|
|
28
27
|
__metadata("design:type", Function)
|
|
@@ -31,3 +30,4 @@ __decorate([
|
|
|
31
30
|
(0, Query_1.Query)(),
|
|
32
31
|
__metadata("design:type", Function)
|
|
33
32
|
], ReadonlyRepository.prototype, "findById", void 0);
|
|
33
|
+
exports.ReadonlyRepository = ReadonlyRepository;
|
package/dist/index.d.ts
CHANGED
|
@@ -14,4 +14,8 @@ export { GenericRepository } from "./config/GenericRepository";
|
|
|
14
14
|
export { ArchiveConfig } from "./config/ArchiveConfig";
|
|
15
15
|
export { CacheProviders } from "./model/CacheProviders";
|
|
16
16
|
export { FirestoreInstance } from "./config/FirestoreInstance";
|
|
17
|
+
/**
|
|
18
|
+
* archive plugin system
|
|
19
|
+
*/
|
|
20
|
+
export { IArchivePlugin, ARCHIVE_METADATA_FIELDS, registerArchivePlugin, getArchivePlugin, hasArchivePlugin, resetArchivePlugin, } from "./archive";
|
|
17
21
|
export * from "./model";
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.FirestoreInstance = exports.CacheProviders = exports.ArchiveConfig = exports.GenericRepository = exports.ReadonlyRepository = exports.BaseRepository = exports.Cacheable = exports.Query = exports.Repository = void 0;
|
|
17
|
+
exports.resetArchivePlugin = exports.hasArchivePlugin = exports.getArchivePlugin = exports.registerArchivePlugin = exports.ARCHIVE_METADATA_FIELDS = exports.FirestoreInstance = exports.CacheProviders = exports.ArchiveConfig = exports.GenericRepository = exports.ReadonlyRepository = exports.BaseRepository = exports.Cacheable = exports.Query = exports.Repository = void 0;
|
|
18
18
|
require("reflect-metadata");
|
|
19
19
|
/**
|
|
20
20
|
* decorators
|
|
@@ -40,4 +40,13 @@ var CacheProviders_1 = require("./model/CacheProviders");
|
|
|
40
40
|
Object.defineProperty(exports, "CacheProviders", { enumerable: true, get: function () { return CacheProviders_1.CacheProviders; } });
|
|
41
41
|
var FirestoreInstance_1 = require("./config/FirestoreInstance");
|
|
42
42
|
Object.defineProperty(exports, "FirestoreInstance", { enumerable: true, get: function () { return FirestoreInstance_1.FirestoreInstance; } });
|
|
43
|
+
/**
|
|
44
|
+
* archive plugin system
|
|
45
|
+
*/
|
|
46
|
+
var archive_1 = require("./archive");
|
|
47
|
+
Object.defineProperty(exports, "ARCHIVE_METADATA_FIELDS", { enumerable: true, get: function () { return archive_1.ARCHIVE_METADATA_FIELDS; } });
|
|
48
|
+
Object.defineProperty(exports, "registerArchivePlugin", { enumerable: true, get: function () { return archive_1.registerArchivePlugin; } });
|
|
49
|
+
Object.defineProperty(exports, "getArchivePlugin", { enumerable: true, get: function () { return archive_1.getArchivePlugin; } });
|
|
50
|
+
Object.defineProperty(exports, "hasArchivePlugin", { enumerable: true, get: function () { return archive_1.hasArchivePlugin; } });
|
|
51
|
+
Object.defineProperty(exports, "resetArchivePlugin", { enumerable: true, get: function () { return archive_1.resetArchivePlugin; } });
|
|
43
52
|
__exportStar(require("./model"), exports);
|