@roit/roit-data-firestore 1.2.43 → 1.2.45

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 (36) hide show
  1. package/dist/archive/ArchivePluginRegistry.d.ts +78 -0
  2. package/dist/archive/ArchivePluginRegistry.js +135 -0
  3. package/dist/archive/ArchiveService.d.ts +61 -11
  4. package/dist/archive/ArchiveService.js +138 -120
  5. package/dist/archive/IArchivePlugin.d.ts +102 -0
  6. package/dist/archive/IArchivePlugin.js +12 -0
  7. package/dist/archive/index.d.ts +2 -0
  8. package/dist/archive/index.js +11 -0
  9. package/dist/cache/CacheResolver.js +6 -5
  10. package/dist/config/ArchiveConfig.d.ts +17 -12
  11. package/dist/config/ArchiveConfig.js +25 -41
  12. package/dist/config/BaseRepository.js +1 -1
  13. package/dist/config/ReadonlyRepository.js +1 -1
  14. package/dist/exception/RepositoryException.js +1 -1
  15. package/dist/index.d.ts +4 -0
  16. package/dist/index.js +10 -1
  17. package/dist/model/CacheProviders.d.ts +1 -2
  18. package/dist/model/CacheProviders.js +1 -2
  19. package/dist/query/ManualQueryHelper.js +0 -1
  20. package/dist/query/QueryPredicateFunctionTransform.js +4 -1
  21. package/dist/template/FunctionAggregationTemplate.txt +1 -1
  22. package/dist/template/FunctionAverageTemplate.txt +1 -1
  23. package/dist/template/FunctionCountTemplate.txt +20 -25
  24. package/dist/template/FunctionCreateOrUpdateTemplate.txt +69 -20
  25. package/dist/template/FunctionCreateTemplate.txt +15 -13
  26. package/dist/template/FunctionDeleteTemplate.txt +45 -13
  27. package/dist/template/FunctionFindAllTemplate.txt +39 -23
  28. package/dist/template/FunctionFindByIdTemplate.txt +24 -14
  29. package/dist/template/FunctionQueryTemplate.txt +67 -41
  30. package/dist/template/FunctionSumTemplate.txt +48 -32
  31. package/dist/template/FunctionUpdatePartialTemplate.txt +76 -21
  32. package/dist/template/FunctionUpdateTemplate.txt +64 -17
  33. package/dist/tsconfig.build.tsbuildinfo +1 -1
  34. package/package.json +1 -1
  35. package/dist/cache/providers/RedisCacheArchiveProvider.d.ts +0 -19
  36. package/dist/cache/providers/RedisCacheArchiveProvider.js +0 -115
@@ -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,2 @@
1
+ export { IArchivePlugin, ARCHIVE_METADATA_FIELDS } from './IArchivePlugin';
2
+ export { registerArchivePlugin, getArchivePlugin, hasArchivePlugin, resetArchivePlugin, ArchivePluginRegistry, } from './ArchivePluginRegistry';
@@ -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
- (0, ArchiveConfig_1.onDebugLog)(`Archive Cache > Removing key: ${key}`);
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
- (0, ArchiveConfig_1.onDebugLog)(`Archive Cache > Removing archive key: ${key}`);
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
- bucketName: string;
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.onDebugWarn = exports.onDebugError = exports.onDebugLog = exports.DEBUG_PREFIX = exports.ArchiveConfig = void 0;
4
- const FIRESTORE_PROJECT_ID = process.env.FIRESTORE_PROJECTID || '';
5
- const FIRESTORE_ARCHIVE_DEBUG = process.env.FIRESTORE_ARCHIVE_DEBUG || false;
6
- const FIRESTORE_ARCHIVE_ENABLED = process.env.FIRESTORE_ARCHIVE_ENABLED || false;
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
- return {
16
- debug: ['true', true].includes(FIRESTORE_ARCHIVE_DEBUG),
17
- enabled: ['true', true].includes(FIRESTORE_ARCHIVE_ENABLED),
18
- bucketName: FIRESTORE_ARCHIVE_BUCKET_NAME,
19
- projectId: FIRESTORE_PROJECT_ID,
20
- cache: {
21
- enabled: ['true', true].includes(FIRESTORE_ARCHIVE_CACHE_ENABLED),
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
- exports.DEBUG_PREFIX = '[ARCHIVE SERVICE]';
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;
@@ -20,4 +20,4 @@ var ErrorType;
20
20
  (function (ErrorType) {
21
21
  ErrorType["SYSTEM"] = "system";
22
22
  ErrorType["BUSINESS"] = "business";
23
- })(ErrorType || (exports.ErrorType = ErrorType = {}));
23
+ })(ErrorType = exports.ErrorType || (exports.ErrorType = {}));
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);
@@ -1,5 +1,4 @@
1
1
  export declare enum CacheProviders {
2
2
  LOCAL = "LOCAL",
3
- REDIS = "REDIS",
4
- REDIS_ARCHIVE = "REDIS_ARCHIVE"
3
+ REDIS = "REDIS"
5
4
  }
@@ -5,5 +5,4 @@ var CacheProviders;
5
5
  (function (CacheProviders) {
6
6
  CacheProviders["LOCAL"] = "LOCAL";
7
7
  CacheProviders["REDIS"] = "REDIS";
8
- CacheProviders["REDIS_ARCHIVE"] = "REDIS_ARCHIVE";
9
- })(CacheProviders || (exports.CacheProviders = CacheProviders = {}));
8
+ })(CacheProviders = exports.CacheProviders || (exports.CacheProviders = {}));
@@ -170,7 +170,6 @@ class ManualQueryHelper {
170
170
  };
171
171
  }
172
172
  catch (error) {
173
- console.error(error);
174
173
  span.setStatus({
175
174
  code: 2,
176
175
  message: error.message
@@ -44,6 +44,7 @@ const fs_1 = __importDefault(require("fs"));
44
44
  const path_1 = __importDefault(require("path"));
45
45
  const Tracer_1 = require("../tracer/Tracer");
46
46
  const ArchiveService_1 = require("../archive/ArchiveService");
47
+ const archive_1 = require("../archive");
47
48
  const functionQueryTemplate = fs_1.default.readFileSync(path_1.default.resolve(__dirname, '../template/FunctionQueryTemplate.txt'), 'utf8');
48
49
  const methodList = {
49
50
  'aggregation': fs_1.default.readFileSync(path_1.default.resolve(__dirname, '../template/FunctionAggregationTemplate.txt'), 'utf8'),
@@ -73,13 +74,15 @@ class QueryPredicateFunctionTransform {
73
74
  environmentUtil: new EnvironmentUtil_1.EnvironmentUtil,
74
75
  firestoreReadAuditResolver: FirestoreReadAuditResolver_1.FirestoreReadAuditResolver.getInstance(),
75
76
  fieldValueIncrement: firestore_1.FieldValue.increment,
77
+ FieldValue: firestore_1.FieldValue,
76
78
  getTtlTimestamp: TtlBuilderUtil_1.TtlBuilderUtil.getTtlTimestamp,
77
79
  convertToMQuery: ManualQueryHelper_1.ManualQueryHelper.convertToMQuery,
78
80
  aggregateAverage: firestore_1.AggregateField.average,
79
81
  aggregateSum: firestore_1.AggregateField.sum,
80
82
  aggregateCount: firestore_1.AggregateField.count,
81
83
  startTracer: Tracer_1.startTracer,
82
- archiveService: ArchiveService_1.ArchiveService.getInstance()
84
+ archiveService: ArchiveService_1.ArchiveService.getInstance(),
85
+ ARCHIVE_FIELDS: archive_1.ARCHIVE_METADATA_FIELDS
83
86
  };
84
87
  if (!options?.collection) {
85
88
  throw new Error(`Collection is required`);
@@ -65,4 +65,4 @@ aggregation(config) {
65
65
  }
66
66
  })
67
67
  });
68
- }
68
+ }
@@ -49,4 +49,4 @@ average(config) {
49
49
  }
50
50
  })
51
51
  });
52
- }
52
+ }
@@ -5,53 +5,48 @@ count(config) {
5
5
  const db = global.instances.globalDbFile.FirestoreInstance.getInstance();
6
6
  const environmentUtil = global.instances.environmentUtil;
7
7
  const convertToMQuery = global.instances.convertToMQuery;
8
+
8
9
  if (environmentUtil.areWeTesting()) {
9
10
  console.log('It was decreed that it is being executed try, no operation or effective transaction will be performed');
10
11
  return 0;
11
12
  }
13
+
12
14
  const collection = db.collection('<COLLECTION_REPLACE>');
13
- let queryList;
14
- let queryExecute;
15
- const traceQuery = []
16
- const pushTraceQuery = (query) => {
17
- traceQuery.push({ field: query.field, operator: query.operator, value: '?' })
18
- }
19
- if ((config === null || config === void 0 ? void 0 : config.query) && config.query.length > 0) {
20
- queryList = config.query.map(query => {
15
+ let queryExecute = collection;
16
+ const traceQuery = [];
17
+
18
+ if (config?.query && config.query.length > 0) {
19
+ const queryList = config.query.map(query => {
21
20
  if (Object.keys(query).length === 1) {
22
21
  return convertToMQuery(query);
23
22
  }
24
23
  return query;
25
24
  });
26
- const queryInit = queryList[0];
27
- queryExecute = collection.where(queryInit.field, queryInit.operator, queryInit.value);
28
- pushTraceQuery(queryInit)
29
- queryList.shift();
30
- queryList.forEach(que => {
31
- queryExecute = queryExecute.where(que.field, que.operator, que.value);
32
- pushTraceQuery(que)
33
- });
34
- }
35
- else {
36
- queryExecute = collection;
25
+
26
+ for (const query of queryList) {
27
+ queryExecute = queryExecute.where(query.field, query.operator, query.value);
28
+ traceQuery.push({ field: query.field, operator: query.operator, value: '?' });
29
+ }
37
30
  }
31
+
38
32
  const snapshot = yield queryExecute.count().get();
39
33
  const count = snapshot.data().count;
34
+
40
35
  span.setAttributes({
41
36
  'firestore.operation.name': 'count',
42
37
  'firestore.operation.query': JSON.stringify(traceQuery),
43
38
  'firestore.collection.name': '<COLLECTION_REPLACE>',
44
39
  'firestore.operation.result.size': count,
45
- })
40
+ });
46
41
  return count;
47
42
  } catch (error) {
48
43
  span.setStatus({
49
44
  code: 2,
50
45
  message: error.message
51
- })
52
- span.recordException(error)
53
- throw error
46
+ });
47
+ span.recordException(error);
48
+ throw error;
54
49
  }
55
- })
50
+ });
56
51
  });
57
- }
52
+ }
@@ -19,12 +19,55 @@ createOrUpdate(items) {
19
19
  const getTtlTimestamp = global.instances.getTtlTimestamp;
20
20
  const collection = db.collection('<COLLECTION_REPLACE>');
21
21
  const validatorDataHandle = global.instances.validatorDataHandle;
22
+ const archiveService = yield global.instances.archiveService;
22
23
  const batch = db.batch();
23
- for (const item of items) {
24
+
25
+ // Preparar IDs e buscar documentos existentes em lote (otimização)
26
+ const itemsWithIds = items.map(item => {
27
+ if (!item.id) item.id = uuid();
28
+ return item;
29
+ });
30
+
31
+ const docRefs = itemsWithIds.map(item => collection.doc(item.id));
32
+ const existingDocs = (archiveService.isEnabled() && docRefs.length > 0)
33
+ ? yield db.getAll(...docRefs)
34
+ : [];
35
+
36
+ for (let i = 0; i < itemsWithIds.length; i++) {
37
+ const item = itemsWithIds[i];
24
38
  yield validatorDataHandle.validateModel(modelName, item, validatorOptions);
25
- if (!item.id) {
26
- item.id = uuid();
39
+
40
+ const docRef = docRefs[i];
41
+ let shouldUnarchive = false;
42
+
43
+ // VERIFICAÇÃO DE DOCUMENTO ARQUIVADO
44
+ if (archiveService.isEnabled() && existingDocs[i]?.exists) {
45
+ const currentData = existingDocs[i].data();
46
+
47
+ if (currentData && archiveService.isDocumentArchived(currentData)) {
48
+ const archivePath = currentData.fbArchivePath;
49
+ const updateResult = yield archiveService.updateArchivedDocument(
50
+ '<COLLECTION_REPLACE>',
51
+ item.id,
52
+ item,
53
+ archivePath,
54
+ { unarchive: true }
55
+ );
56
+
57
+ if (updateResult.result.success && updateResult.mergedData) {
58
+ if (updateResult.mergedData.createAt) {
59
+ item.createAt = updateResult.mergedData.createAt;
60
+ item.createTimestampAt = updateResult.mergedData.createTimestampAt;
61
+ }
62
+ const originalItem = Object.assign({}, item);
63
+ Object.assign(item, updateResult.mergedData, originalItem);
64
+ shouldUnarchive = true;
65
+ } else {
66
+ throw new Error('Failed to update archived document; aborting createOrUpdate to prevent inconsistent state and stale archive overwriting user changes.');
67
+ }
68
+ }
27
69
  }
70
+
28
71
  if (!item.createAt) {
29
72
  item.createAt = newDate();
30
73
  item.createTimestampAt = new Date(item.createAt).getTime();
@@ -32,40 +75,46 @@ createOrUpdate(items) {
32
75
  item.updateAt = newDate();
33
76
  item.updateTimestampAt = new Date(item.updateAt).getTime();
34
77
  item.lastServiceModify = process.env.SERVICE || 'PROJECT_UNDEFINED';
35
- const docRef = collection.doc(item.id);
36
- if (ttlExpirationIn && item?.ttlExpirationAt) {
37
- delete item.ttlExpirationAt;
38
- }
39
- batch.set(docRef, JSON.parse(JSON.stringify(item)), { merge: true });
78
+
79
+ // Preparar dados para persistir (consolidado)
80
+ const itemData = JSON.parse(JSON.stringify(item));
40
81
  if (ttlExpirationIn && ttlUnit) {
41
- const ttl = getTtlTimestamp(ttlExpirationIn, ttlUnit);
42
- batch.set(docRef, {
43
- ttlExpirationAt: ttl,
44
- }, { merge: true });
82
+ itemData.ttlExpirationAt = getTtlTimestamp(ttlExpirationIn, ttlUnit);
83
+ }
84
+
85
+ if (shouldUnarchive) {
86
+ const FieldValue = global.instances.FieldValue;
87
+ const ARCHIVE_FIELDS = global.instances.ARCHIVE_FIELDS;
88
+ itemData[ARCHIVE_FIELDS.ARCHIVED_AT] = FieldValue.delete();
89
+ itemData[ARCHIVE_FIELDS.ARCHIVE_PATH] = FieldValue.delete();
90
+ itemData[ARCHIVE_FIELDS.ARCHIVE_HASH] = FieldValue.delete();
45
91
  }
92
+
93
+ batch.set(docRef, itemData, { merge: true });
46
94
  }
95
+
47
96
  if (!environmentUtil.areWeTesting()) {
48
97
  yield batch.commit();
49
98
  yield this.revokeCache();
50
- }
51
- else {
99
+ } else {
52
100
  console.log('It was decreed that it is being executed try, no operation or effective transaction will be performed');
53
101
  }
102
+
54
103
  span.setAttributes({
55
104
  'firestore.operation.name': 'createOrUpdate',
56
105
  'firestore.operation.size': items.length,
57
106
  'firestore.collection.name': '<COLLECTION_REPLACE>',
58
- })
107
+ });
59
108
  return items;
60
109
 
61
110
  } catch (error) {
62
111
  span.setStatus({
63
112
  code: 2,
64
113
  message: error.message
65
- })
66
- span.recordException(error)
67
- throw error
114
+ });
115
+ span.recordException(error);
116
+ throw error;
68
117
  }
69
- })
118
+ });
70
119
  });
71
- }
120
+ }