akeyless-server-commons 1.0.187 → 1.0.191

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 (97) hide show
  1. package/dist/cjs/helpers/firebase_helpers.d.ts +1 -1
  2. package/dist/cjs/helpers/firebase_helpers.js +4 -5
  3. package/dist/cjs/helpers/firebase_helpers.js.map +1 -1
  4. package/dist/cjs/helpers/global_helpers.d.ts +1 -1
  5. package/dist/esm/helpers/firebase_helpers.d.ts +1 -1
  6. package/dist/esm/helpers/firebase_helpers.js +2 -3
  7. package/dist/esm/helpers/firebase_helpers.js.map +1 -1
  8. package/dist/esm/helpers/global_helpers.d.ts +1 -1
  9. package/dist/helpers/boards_helpers.js +62 -0
  10. package/dist/helpers/email_helpers.js +153 -0
  11. package/dist/helpers/firebase_helpers.js +576 -0
  12. package/dist/helpers/global_helpers.js +147 -0
  13. package/dist/helpers/index.js +12 -0
  14. package/dist/helpers/location_helpers.js +15 -0
  15. package/dist/helpers/login_helpers.js +18 -0
  16. package/dist/helpers/notification_helpers.js +234 -0
  17. package/dist/helpers/phone_number_helpers.js +91 -0
  18. package/dist/helpers/redis/index.js +3 -0
  19. package/dist/helpers/redis/initialize.js +139 -0
  20. package/dist/helpers/redis/keys.js +23 -0
  21. package/dist/helpers/redis/snapshot.js +163 -0
  22. package/dist/helpers/start.js +43 -0
  23. package/dist/helpers/tasks_helpers.js +136 -0
  24. package/dist/helpers/time_helpers.js +167 -0
  25. package/dist/index.js +5 -0
  26. package/dist/managers/cache_manager.js +27 -0
  27. package/dist/managers/index.js +3 -0
  28. package/dist/managers/logger_manager.js +51 -0
  29. package/dist/managers/translation_manager.js +38 -0
  30. package/dist/middlewares/auth_mw.js +50 -0
  31. package/dist/middlewares/error_handling.js +20 -0
  32. package/dist/middlewares/global_mw.js +110 -0
  33. package/dist/middlewares/index.js +4 -0
  34. package/dist/middlewares/trim_mw.js +7 -0
  35. package/dist/test.js +1 -0
  36. package/dist/types/enums/global.js +8 -0
  37. package/dist/types/enums/index.js +1 -0
  38. package/dist/types/helpers/boards_helpers.d.ts +10 -0
  39. package/dist/types/helpers/email_helpers.d.ts +12 -0
  40. package/dist/types/helpers/firebase_helpers.d.ts +55 -0
  41. package/dist/types/helpers/global_helpers.d.ts +16 -0
  42. package/dist/types/helpers/index.d.ts +12 -0
  43. package/dist/types/helpers/location_helpers.d.ts +3 -0
  44. package/dist/types/helpers/login_helpers.d.ts +4 -0
  45. package/dist/types/helpers/notification_helpers.d.ts +11 -0
  46. package/dist/types/helpers/phone_number_helpers.d.ts +14 -0
  47. package/dist/types/helpers/redis/index.d.ts +3 -0
  48. package/dist/types/helpers/redis/initialize.d.ts +6 -0
  49. package/dist/types/helpers/redis/keys.d.ts +5 -0
  50. package/dist/types/helpers/redis/snapshot.d.ts +2 -0
  51. package/dist/types/helpers/start.d.ts +4 -0
  52. package/dist/types/helpers/tasks_helpers.d.ts +22 -0
  53. package/dist/types/helpers/time_helpers.d.ts +40 -0
  54. package/dist/types/index.d.ts +5 -0
  55. package/dist/types/index.js +3 -0
  56. package/dist/types/interfaces/index.js +2 -0
  57. package/dist/types/managers/cache_manager.d.ts +11 -0
  58. package/dist/types/managers/index.d.ts +3 -0
  59. package/dist/types/managers/logger_manager.d.ts +12 -0
  60. package/dist/types/managers/translation_manager.d.ts +14 -0
  61. package/dist/types/middlewares/auth_mw.d.ts +4 -0
  62. package/dist/types/middlewares/error_handling.d.ts +11 -0
  63. package/dist/types/middlewares/global_mw.d.ts +5 -0
  64. package/dist/types/middlewares/index.d.ts +4 -0
  65. package/dist/types/middlewares/trim_mw.d.ts +2 -0
  66. package/dist/types/test.d.ts +0 -0
  67. package/dist/types/types/enums/global.d.ts +9 -0
  68. package/dist/types/types/enums/index.d.ts +1 -0
  69. package/dist/types/types/firebase_types.js +1 -0
  70. package/dist/types/types/global.js +1 -0
  71. package/dist/types/types/index.d.ts +3 -0
  72. package/dist/types/types/index.js +2 -0
  73. package/dist/types/types/interfaces/email.d.ts +33 -0
  74. package/dist/types/types/interfaces/global.d.ts +23 -0
  75. package/dist/types/types/interfaces/index.d.ts +2 -0
  76. package/dist/types/types/types/firebase_types.d.ts +50 -0
  77. package/dist/types/types/types/global.d.ts +17 -0
  78. package/dist/types/types/types/index.d.ts +2 -0
  79. package/package.json +1 -1
  80. package/dist/cjs/helpers/tasks.d.ts +0 -12
  81. package/dist/cjs/helpers/tasks.js +0 -62
  82. package/dist/cjs/helpers/tasks.js.map +0 -1
  83. package/dist/cjs/managers/cacche_manager2.d.ts +0 -18
  84. package/dist/cjs/managers/cacche_manager2.js +0 -41
  85. package/dist/cjs/managers/cacche_manager2.js.map +0 -1
  86. package/dist/cjs/managers/socket_manager.js +0 -245
  87. package/dist/cjs/managers/socket_manager.js.map +0 -1
  88. package/dist/esm/helpers/tasks.d.ts +0 -12
  89. package/dist/esm/helpers/tasks.js +0 -58
  90. package/dist/esm/helpers/tasks.js.map +0 -1
  91. package/dist/esm/managers/cacche_manager2.d.ts +0 -18
  92. package/dist/esm/managers/cacche_manager2.js +0 -37
  93. package/dist/esm/managers/cacche_manager2.js.map +0 -1
  94. package/dist/esm/managers/socket_manager.js +0 -243
  95. package/dist/esm/managers/socket_manager.js.map +0 -1
  96. /package/dist/{cjs/managers/socket_manager.d.ts → types/interfaces/email.js} +0 -0
  97. /package/dist/{esm/managers/socket_manager.d.ts → types/interfaces/global.js} +0 -0
@@ -0,0 +1,576 @@
1
+ import { performance } from "perf_hooks";
2
+ import firebase_admin from "firebase-admin";
3
+ import { cache_manager, logger, translation_manager } from "../managers";
4
+ import dotenv from "dotenv";
5
+ import { init_env_variables } from "./global_helpers";
6
+ import { Timestamp } from "firebase-admin/firestore";
7
+ import { redis_snapshots_bulk } from "./redis";
8
+ dotenv.config();
9
+ // initial firebase
10
+ const required_env_vars = [
11
+ "type",
12
+ "project_id",
13
+ "private_key_id",
14
+ "private_key",
15
+ "client_email",
16
+ "client_id",
17
+ "auth_uri",
18
+ "token_uri",
19
+ "auth_provider_x509_cert_url",
20
+ "client_x509_cert_url",
21
+ "universe_domain",
22
+ ];
23
+ const env_data = init_env_variables(required_env_vars);
24
+ export const service_account_firebase = {
25
+ type: env_data.type,
26
+ project_id: env_data.project_id,
27
+ private_key_id: env_data.private_key_id,
28
+ private_key: env_data.private_key.replace(/\\n/g, "\n"),
29
+ client_email: env_data.client_email,
30
+ client_id: env_data.client_id,
31
+ auth_uri: env_data.auth_uri,
32
+ token_uri: env_data.token_uri,
33
+ auth_provider_x509_cert_url: env_data.auth_provider_x509_cert_url,
34
+ client_x509_cert_url: env_data.client_x509_cert_url,
35
+ universe_domain: env_data.universe_domain,
36
+ };
37
+ firebase_admin.initializeApp({
38
+ credential: firebase_admin.credential.cert(service_account_firebase),
39
+ storageBucket: `${service_account_firebase.project_id}.appspot.com`,
40
+ });
41
+ export const db = firebase_admin.firestore();
42
+ export const messaging = firebase_admin.messaging();
43
+ export const auth = firebase_admin.auth();
44
+ export const storage = firebase_admin.storage();
45
+ /// extract
46
+ export const simple_extract_data = (doc) => {
47
+ const doc_data = doc.data();
48
+ return {
49
+ ...doc_data,
50
+ id: doc.id,
51
+ };
52
+ };
53
+ /// documents
54
+ export const get_all_documents = async (collection_path) => {
55
+ try {
56
+ const snapshot = await db.collection(collection_path).get();
57
+ const documents = snapshot.docs.flatMap((doc) => {
58
+ return simple_extract_data(doc);
59
+ });
60
+ return documents;
61
+ }
62
+ catch (error) {
63
+ logger.error("Error fetching documents:", error);
64
+ throw error;
65
+ }
66
+ };
67
+ export const query_documents = async (collection_path, field_name, operator, value) => {
68
+ try {
69
+ const querySnapshot = await db.collection(collection_path).where(field_name, operator, value).get();
70
+ const documentsData = querySnapshot.docs;
71
+ const documents = documentsData.flatMap((doc) => simple_extract_data(doc));
72
+ return documents;
73
+ }
74
+ catch (error) {
75
+ logger.error(`Error querying documents: ${collection_path} - ${field_name} - ${operator} - ${value} `, error);
76
+ throw error;
77
+ }
78
+ };
79
+ export const query_documents_by_conditions = async (collection_path, where_conditions) => {
80
+ try {
81
+ let query = db.collection(collection_path);
82
+ where_conditions.forEach((condition) => {
83
+ query = query.where(condition.field_name, condition.operator, condition.value);
84
+ });
85
+ const querySnapshot = await query.get();
86
+ const documentsData = querySnapshot.docs;
87
+ const documents = documentsData.flatMap((doc) => simple_extract_data(doc));
88
+ return documents;
89
+ }
90
+ catch (error) {
91
+ logger.error(`Error querying documents: ${collection_path} - ${JSON.stringify(where_conditions)} `, error);
92
+ throw error;
93
+ }
94
+ };
95
+ export const query_document_by_conditions = async (collection_path, where_conditions, log = true) => {
96
+ try {
97
+ let query = db.collection(collection_path);
98
+ where_conditions.forEach((condition) => {
99
+ query = query.where(condition.field_name, condition.operator, condition.value);
100
+ });
101
+ const querySnapshot = await query.get();
102
+ const documentsData = querySnapshot.docs;
103
+ const documents = documentsData.flatMap((doc) => simple_extract_data(doc));
104
+ if (!documents[0]) {
105
+ throw "no data returned from DB";
106
+ }
107
+ return documents[0];
108
+ }
109
+ catch (error) {
110
+ if (log) {
111
+ logger.error(`Error querying documents: ${collection_path} - ${JSON.stringify(where_conditions)} `, error);
112
+ }
113
+ throw error;
114
+ }
115
+ };
116
+ /// document
117
+ export const query_document = async (collection_path, field_name, operator, value, ignore_log = false) => {
118
+ try {
119
+ const querySnapshot = await db.collection(collection_path).where(field_name, operator, value).get();
120
+ const documentsData = querySnapshot.docs;
121
+ const documents = documentsData.flatMap((doc) => simple_extract_data(doc));
122
+ if (documents.length < 1) {
123
+ throw `No data to return from: collection: ${collection_path}, field_name: ${field_name}, operator: ${operator}, value:${value}`;
124
+ }
125
+ return documents[0];
126
+ }
127
+ catch (error) {
128
+ if (!ignore_log) {
129
+ logger.error("Error querying document: " + JSON.stringify({ collection_path, field_name, operator, value }), error);
130
+ }
131
+ throw error;
132
+ }
133
+ };
134
+ export const query_document_optional = async (collection_path, field_name, operator, value, ignore_log = true) => {
135
+ try {
136
+ const querySnapshot = await db.collection(collection_path).where(field_name, operator, value).get();
137
+ const documentsData = querySnapshot.docs;
138
+ const documents = documentsData.flatMap((doc) => simple_extract_data(doc));
139
+ return documents[0] || null;
140
+ }
141
+ catch (error) {
142
+ if (!ignore_log) {
143
+ logger.error("Error querying optional document: " + JSON.stringify({ collection_path, field_name, operator, value }), error);
144
+ }
145
+ return null;
146
+ }
147
+ };
148
+ export const get_document_by_id = async (collection_path, doc_id) => {
149
+ try {
150
+ const docRef = db.collection(collection_path).doc(doc_id);
151
+ const doc = await docRef.get();
152
+ if (!doc.exists) {
153
+ throw "Document not found, document id: " + doc_id;
154
+ }
155
+ return simple_extract_data(doc);
156
+ }
157
+ catch (error) {
158
+ logger.error("error from get_document_by_id", error);
159
+ throw error;
160
+ }
161
+ };
162
+ export const get_document_by_id_optional = async (collection_path, doc_id) => {
163
+ try {
164
+ const docRef = db.collection(collection_path).doc(doc_id);
165
+ const doc = await docRef.get();
166
+ if (!doc.exists) {
167
+ throw "Document not found, document id: " + doc_id;
168
+ }
169
+ return simple_extract_data(doc);
170
+ }
171
+ catch (error) {
172
+ logger.error("error from get_document_by_id_optional", error);
173
+ return null;
174
+ }
175
+ };
176
+ export const set_document = async (collection_path, doc_id, data, merge = true) => {
177
+ try {
178
+ await db
179
+ .collection(collection_path)
180
+ .doc(doc_id)
181
+ .set({ ...data }, { merge });
182
+ }
183
+ catch (error) {
184
+ logger.error(`failed to create document by id: ${doc_id} in collection: ${collection_path}`, error);
185
+ throw `failed to create document by id ${doc_id} in collection ${collection_path}`;
186
+ }
187
+ };
188
+ export const add_document = async (collection_path, data, include_id = false, custom_id) => {
189
+ try {
190
+ const new_document = custom_id ? db.collection(collection_path).doc(custom_id) : db.collection(collection_path).doc();
191
+ const update = include_id ? { ...data, id: new_document.id } : data;
192
+ await new_document.set(update);
193
+ return new_document.id;
194
+ }
195
+ catch (error) {
196
+ logger.error(`failed to create document in collection: ${collection_path}`, error);
197
+ throw `failed to create document in collection ${collection_path}`;
198
+ }
199
+ };
200
+ export const delete_document = async (collection_path, doc_id) => {
201
+ try {
202
+ await db.collection(collection_path).doc(doc_id).delete();
203
+ }
204
+ catch (error) {
205
+ throw `Failed to delete document with id ${doc_id} from collection ${collection_path}`;
206
+ }
207
+ };
208
+ /// token
209
+ export const verify_token = async (authorization) => {
210
+ try {
211
+ if (!authorization) {
212
+ throw "Authorization token is required";
213
+ }
214
+ if (!authorization.toLowerCase().startsWith("bearer")) {
215
+ throw "Invalid authorization token";
216
+ }
217
+ const token = authorization.split(/bearer\s+(.+)/i)[1];
218
+ if (!token) {
219
+ throw "validation error: Token not found";
220
+ }
221
+ const res = await firebase_admin.auth().verifyIdToken(token);
222
+ if (!res) {
223
+ throw "User not found";
224
+ }
225
+ return res;
226
+ }
227
+ catch (error) {
228
+ logger.error("error from verify_token", error);
229
+ throw error;
230
+ }
231
+ };
232
+ /// parsers
233
+ const parse_add_update_translations = (documents) => {
234
+ const data = translation_manager.getTranslationData();
235
+ documents.forEach((doc) => {
236
+ data[doc.id] = doc;
237
+ delete data[doc.id].id;
238
+ });
239
+ translation_manager.setTranslationData(data);
240
+ };
241
+ const parse_delete_translations = (documents) => {
242
+ const data = translation_manager.getTranslationData();
243
+ documents.forEach((doc) => {
244
+ if (data[doc.id]) {
245
+ delete data[doc.id];
246
+ }
247
+ });
248
+ translation_manager.setTranslationData(data);
249
+ };
250
+ const parse_add_update_settings = (documents, name_for_cache) => {
251
+ const data = cache_manager.getObjectData(name_for_cache, {});
252
+ documents.forEach((doc) => {
253
+ data[doc.id] = doc;
254
+ });
255
+ cache_manager.setObjectData(name_for_cache, data);
256
+ };
257
+ const parse_delete_settings = (documents, name_for_cache) => {
258
+ const data = cache_manager.getObjectData(name_for_cache, {});
259
+ documents.forEach((doc) => {
260
+ if (data[doc.id]) {
261
+ delete data[doc.id];
262
+ }
263
+ });
264
+ cache_manager.setObjectData(name_for_cache, data);
265
+ };
266
+ export const parse_add_update_as_object = (documents, config) => {
267
+ const { collection_name, cache_name = collection_name, doc_key_property = "id" } = config;
268
+ const data = cache_manager.getObjectData(cache_name, {});
269
+ documents.forEach((doc) => {
270
+ data[doc[doc_key_property]] = doc;
271
+ });
272
+ cache_manager.setObjectData(cache_name, data);
273
+ };
274
+ export const parse_delete_as_object = (documents, config) => {
275
+ const { collection_name, cache_name = collection_name, doc_key_property = "id" } = config;
276
+ const data = cache_manager.getObjectData(cache_name, {});
277
+ documents.forEach((doc) => {
278
+ if (data[doc[doc_key_property]]) {
279
+ delete data[doc[doc_key_property]];
280
+ }
281
+ });
282
+ cache_manager.setObjectData(cache_name, data);
283
+ };
284
+ export const parse_add_update_as_array = (documents, config) => {
285
+ const { on_remove, collection_name, cache_name = collection_name } = config;
286
+ on_remove?.(documents, config);
287
+ const existing_array = cache_manager.getArrayData(cache_name);
288
+ const updated_array = [...existing_array, ...documents];
289
+ cache_manager.setArrayData(cache_name, updated_array);
290
+ };
291
+ export const parse_delete_as_array = (documents, config) => {
292
+ const { collection_name, cache_name = collection_name } = config;
293
+ const existing_array = cache_manager.getArrayData(cache_name);
294
+ const keys_to_delete = documents.map((doc) => doc.id);
295
+ const updated_array = existing_array.filter((doc) => !keys_to_delete.includes(doc.id));
296
+ cache_manager.setArrayData(cache_name, updated_array);
297
+ };
298
+ /// snapshots
299
+ let snapshots_first_time = [];
300
+ export const snapshot = (config) => {
301
+ const { collection_name, cache_name = collection_name, conditions, debug } = config;
302
+ return new Promise((resolve) => {
303
+ let q = db.collection(collection_name);
304
+ if (conditions) {
305
+ conditions.forEach((condition) => {
306
+ const { field_name, operator, value } = condition;
307
+ q = q.where(field_name, operator, value);
308
+ });
309
+ }
310
+ let attempt = 0;
311
+ let unsubscribe = null;
312
+ // 🔒 CRITICAL: prevent startup deadlock
313
+ let resolved = false;
314
+ const safe_resolve = () => {
315
+ if (resolved)
316
+ return;
317
+ resolved = true;
318
+ resolve();
319
+ };
320
+ const start = () => {
321
+ unsubscribe = q.onSnapshot((snapshot) => {
322
+ if (!snapshots_first_time.includes(cache_name)) {
323
+ snapshots_first_time.push(cache_name);
324
+ const documents = snapshot.docs.flatMap((doc) => simple_extract_data(doc));
325
+ if (debug?.on_first_time) {
326
+ logger.log(`${cache_name} => Firebase snapshot on first time: `, debug.on_first_time === "documents" ? documents : { length: documents.length });
327
+ }
328
+ config.on_first_time?.(documents, config);
329
+ config.extra_parsers?.forEach((extra_parser) => {
330
+ if (debug?.extra_parsers?.on_first_time) {
331
+ logger.log(`${cache_name} => Firebase snapshot extra parsers on first time: `, debug.extra_parsers.on_first_time === "documents" ? documents : { length: documents.length });
332
+ }
333
+ extra_parser.on_first_time?.(documents, config);
334
+ });
335
+ safe_resolve(); // ✅ boot can continue
336
+ return;
337
+ }
338
+ const get_docs_from_snapshot = (action) => {
339
+ return snapshot
340
+ .docChanges()
341
+ .filter((change) => change.type === action)
342
+ .map((change) => simple_extract_data(change.doc));
343
+ };
344
+ const [added, modified, removed] = [
345
+ get_docs_from_snapshot("added"),
346
+ get_docs_from_snapshot("modified"),
347
+ get_docs_from_snapshot("removed"),
348
+ ];
349
+ if (added.length) {
350
+ if (debug?.on_add) {
351
+ logger.log(`${cache_name} => Firebase snapshot on add: `, added);
352
+ }
353
+ config.on_add?.(added, config);
354
+ }
355
+ if (modified.length) {
356
+ if (debug?.on_modify) {
357
+ logger.log(`${cache_name} => Firebase snapshot on modify: `, modified);
358
+ }
359
+ config.on_modify?.(modified, config);
360
+ }
361
+ if (removed.length) {
362
+ if (debug?.on_remove) {
363
+ logger.log(`${cache_name} => Firebase snapshot on remove: `, removed);
364
+ }
365
+ config.on_remove?.(removed, config);
366
+ }
367
+ config.extra_parsers?.forEach((extra_parser) => {
368
+ if (added.length) {
369
+ if (debug?.extra_parsers?.on_add) {
370
+ logger.log(`${cache_name} => Firebase snapshot extra parsers on add: `, added);
371
+ }
372
+ extra_parser.on_add?.(added, config);
373
+ }
374
+ if (modified.length) {
375
+ if (debug?.extra_parsers?.on_modify) {
376
+ logger.log(`${cache_name} => Firebase snapshot extra parsers on modify: `, modified);
377
+ }
378
+ extra_parser.on_modify?.(modified, config);
379
+ }
380
+ if (removed.length) {
381
+ if (debug?.extra_parsers?.on_remove) {
382
+ logger.log(`${cache_name} => Firebase snapshot extra parsers on remove: `, removed);
383
+ }
384
+ extra_parser.on_remove?.(removed, config);
385
+ }
386
+ });
387
+ }, (error) => {
388
+ logger.error(`Error listening to collection: ${config.collection_name}`, error);
389
+ // 🚑 DO NOT BLOCK BOOT
390
+ safe_resolve();
391
+ try {
392
+ unsubscribe?.();
393
+ }
394
+ catch { }
395
+ unsubscribe = null;
396
+ const delay_ms = Math.min(30000, 500 * 2 ** attempt++);
397
+ setTimeout(() => {
398
+ start();
399
+ }, delay_ms);
400
+ });
401
+ };
402
+ start();
403
+ });
404
+ };
405
+ export const init_snapshots = async (options) => {
406
+ const { subscription_type = "firebase", debug } = options || {};
407
+ await snapshot_bulk_by_names([
408
+ "nx-settings",
409
+ "settings",
410
+ {
411
+ collection_name: "nx-translations",
412
+ extra_parsers: [
413
+ {
414
+ on_first_time: parse_add_update_translations,
415
+ on_add: parse_add_update_translations,
416
+ on_modify: parse_add_update_translations,
417
+ on_remove: parse_delete_translations,
418
+ },
419
+ ],
420
+ },
421
+ ], {
422
+ subscription_type,
423
+ debug,
424
+ parse_as: "object",
425
+ label: "Common snapshots",
426
+ });
427
+ };
428
+ export const snapshot_bulk = async (snapshots, label) => {
429
+ const start = performance.now();
430
+ logger.log(`==> ${label || "custom snapshots"} started... `);
431
+ await Promise.all(snapshots);
432
+ logger.log(`==> ${label || "custom snapshots"} ended. It took ${(performance.now() - start).toFixed(2)} ms`);
433
+ };
434
+ const get_default_parsers_as_array = () => {
435
+ return {
436
+ on_first_time: parse_add_update_as_array,
437
+ on_add: parse_add_update_as_array,
438
+ on_modify: parse_add_update_as_array,
439
+ on_remove: parse_delete_as_array,
440
+ };
441
+ };
442
+ const get_default_parsers_as_object = () => {
443
+ return {
444
+ on_first_time: parse_add_update_as_object,
445
+ on_add: parse_add_update_as_object,
446
+ on_modify: parse_add_update_as_object,
447
+ on_remove: parse_delete_as_object,
448
+ };
449
+ };
450
+ export const get_default_parsers = (parse_as) => {
451
+ if (parse_as === "array") {
452
+ return get_default_parsers_as_array();
453
+ }
454
+ else {
455
+ return get_default_parsers_as_object();
456
+ }
457
+ };
458
+ export const snapshot_bulk_by_names = async (params, options) => {
459
+ const { label = "snapshot_bulk_by_names", subscription_type = "firebase", debug, parse_as = "array", doc_key_property = "id" } = options || {};
460
+ const start = performance.now();
461
+ logger.log(`==> Snapshots ${label} => [${subscription_type}] started... `);
462
+ const uniq_collections = new Set();
463
+ const redis_configs = [];
464
+ const firebase_promises = [];
465
+ for (const param of params) {
466
+ const name = typeof param === "string" ? param : param.cache_name || param.collection_name;
467
+ if (uniq_collections.has(name)) {
468
+ continue;
469
+ }
470
+ uniq_collections.add(name);
471
+ const config = typeof param === "string"
472
+ ? {
473
+ collection_name: param,
474
+ subscription_type,
475
+ doc_key_property,
476
+ debug,
477
+ ...get_default_parsers(parse_as),
478
+ }
479
+ : {
480
+ collection_name: param.collection_name,
481
+ extra_parsers: param.extra_parsers,
482
+ conditions: param.conditions,
483
+ cache_name: param.cache_name,
484
+ doc_key_property: param.doc_key_property || doc_key_property,
485
+ subscription_type: param.subscription_type || subscription_type,
486
+ debug: param.debug || debug,
487
+ // parse_as: param.parse_as,
488
+ ...get_default_parsers(param.parse_as || parse_as),
489
+ };
490
+ if (config.subscription_type === "redis") {
491
+ redis_configs.push(config);
492
+ }
493
+ else {
494
+ firebase_promises.push(snapshot(config));
495
+ }
496
+ }
497
+ await redis_snapshots_bulk(redis_configs);
498
+ await Promise.all(firebase_promises);
499
+ logger.log(`==> Snapshots ${label} => [${subscription_type}] ended. It took ${(performance.now() - start).toFixed(2)} ms`);
500
+ };
501
+ export const add_audit_record = async (action, entity, details, user) => {
502
+ const data = {
503
+ action,
504
+ entity,
505
+ details,
506
+ datetime: Timestamp.now(),
507
+ user: user || null,
508
+ };
509
+ try {
510
+ await db.collection("nx-audit").add(data);
511
+ }
512
+ catch (error) {
513
+ throw { msg: "unable to add audit record", data };
514
+ }
515
+ };
516
+ export const save_file_in_storage = async (file_path, buffer, options = {}) => {
517
+ try {
518
+ const bucket = storage.bucket();
519
+ const normalized_path = file_path.replace(/^\/+/, "");
520
+ const file = bucket.file(normalized_path);
521
+ const metadata = {
522
+ contentType: options.content_type,
523
+ cacheControl: options.cache_control,
524
+ contentDisposition: options.content_disposition,
525
+ };
526
+ await file.save(buffer, {
527
+ metadata,
528
+ resumable: options.resumable ?? false,
529
+ });
530
+ if (options.make_public ?? true) {
531
+ await file.makePublic();
532
+ }
533
+ const [url] = await file.getSignedUrl({
534
+ action: "read",
535
+ expires: Date.now() + (options.signed_url_ttl_ms ?? 1000 * 60 * 60 * 24 * 7),
536
+ });
537
+ return url;
538
+ }
539
+ catch (error) {
540
+ logger.error("error from save_file_in_storage", { error: error?.message || error });
541
+ throw error;
542
+ }
543
+ };
544
+ export const get_file_url_from_storage = async (file_path) => {
545
+ try {
546
+ const bucket = storage.bucket();
547
+ const normalized_path = file_path.replace(/^\/+/, "");
548
+ const file = bucket.file(normalized_path);
549
+ const [exists] = await file.exists();
550
+ if (!exists) {
551
+ throw new Error("file not exist");
552
+ }
553
+ const [url] = await file.getSignedUrl({
554
+ action: "read",
555
+ expires: Date.now() + 1000 * 60 * 60 * 24 * 7,
556
+ });
557
+ return url;
558
+ }
559
+ catch (error) {
560
+ logger.error(`error from get_file_url_from_storage, file_path: ${file_path}`, error);
561
+ throw error;
562
+ }
563
+ };
564
+ export const get_nx_settings = async () => {
565
+ const cache = cache_manager.getObjectData("nx-settings");
566
+ if (cache) {
567
+ return cache;
568
+ }
569
+ const docs = await get_all_documents("nx-settings");
570
+ const nx_settings = {};
571
+ docs.forEach((doc) => {
572
+ nx_settings[doc.id] = doc;
573
+ });
574
+ cache_manager.setObjectData("nx-settings", nx_settings);
575
+ return nx_settings;
576
+ };