node-server-engine 1.7.4 → 1.9.0

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 (43) hide show
  1. package/README.md +712 -67
  2. package/dist/entities/AWSS3/AWSS3.d.ts +157 -0
  3. package/dist/entities/AWSS3/AWSS3.js +426 -0
  4. package/dist/entities/AWSS3/AWSS3.js.map +1 -0
  5. package/dist/entities/AWSS3/AWSS3.types.d.ts +78 -0
  6. package/dist/entities/AWSS3/AWSS3.types.js +2 -0
  7. package/dist/entities/AWSS3/AWSS3.types.js.map +1 -0
  8. package/dist/entities/AWSS3/index.d.ts +2 -0
  9. package/dist/entities/{Storage → AWSS3}/index.js +8 -8
  10. package/dist/entities/AWSS3/index.js.map +1 -0
  11. package/dist/entities/ElasticSearch/ElasticSearch.d.ts +5 -0
  12. package/dist/entities/ElasticSearch/ElasticSearch.js +137 -38
  13. package/dist/entities/ElasticSearch/ElasticSearch.js.map +1 -1
  14. package/dist/entities/GoogleCloudStorage/GoogleCloudStorage.d.ts +141 -0
  15. package/dist/entities/GoogleCloudStorage/GoogleCloudStorage.js +351 -0
  16. package/dist/entities/GoogleCloudStorage/GoogleCloudStorage.js.map +1 -0
  17. package/dist/entities/{Storage/Storage.types.d.ts → GoogleCloudStorage/GoogleCloudStorage.types.d.ts} +14 -0
  18. package/dist/entities/GoogleCloudStorage/GoogleCloudStorage.types.js +2 -0
  19. package/dist/entities/GoogleCloudStorage/GoogleCloudStorage.types.js.map +1 -0
  20. package/dist/entities/GoogleCloudStorage/index.d.ts +2 -0
  21. package/dist/entities/GoogleCloudStorage/index.js +28 -0
  22. package/dist/entities/GoogleCloudStorage/index.js.map +1 -0
  23. package/dist/entities/Localizator/Localizator.js +2 -2
  24. package/dist/entities/Localizator/Localizator.js.map +1 -1
  25. package/dist/entities/Redis/Redis.d.ts +10 -2
  26. package/dist/entities/Redis/Redis.js +104 -9
  27. package/dist/entities/Redis/Redis.js.map +1 -1
  28. package/dist/entities/Redis/Redis.types.d.ts +6 -0
  29. package/dist/entities/Redis/Redis.types.js.map +1 -1
  30. package/dist/entities/Redis/index.d.ts +1 -1
  31. package/dist/entities/Redis/index.js +22 -1
  32. package/dist/entities/Redis/index.js.map +1 -1
  33. package/dist/entities/index.d.ts +2 -1
  34. package/dist/entities/index.js +15 -4
  35. package/dist/entities/index.js.map +1 -1
  36. package/package.json +12 -11
  37. package/dist/entities/Storage/Storage.d.ts +0 -38
  38. package/dist/entities/Storage/Storage.js +0 -214
  39. package/dist/entities/Storage/Storage.js.map +0 -1
  40. package/dist/entities/Storage/Storage.types.js +0 -2
  41. package/dist/entities/Storage/Storage.types.js.map +0 -1
  42. package/dist/entities/Storage/index.d.ts +0 -2
  43. package/dist/entities/Storage/index.js.map +0 -1
@@ -0,0 +1,78 @@
1
+ import { Readable } from 'stream';
2
+ /** AWS S3 initialization configuration */
3
+ export interface AWSS3Config {
4
+ /** AWS Region (e.g., 'us-east-1') */
5
+ region?: string;
6
+ /** AWS Access Key ID */
7
+ accessKeyId?: string;
8
+ /** AWS Secret Access Key */
9
+ secretAccessKey?: string;
10
+ /** AWS Session Token (for temporary credentials) */
11
+ sessionToken?: string;
12
+ /** Custom endpoint (useful for S3-compatible services like MinIO, LocalStack) */
13
+ endpoint?: string;
14
+ /** Force path style (required for some S3-compatible services) */
15
+ forcePathStyle?: boolean;
16
+ }
17
+ /** Options to set where an uploaded file is stored in the S3 bucket */
18
+ export interface S3UploadDestinationOptions {
19
+ /** Directory of the bucket in which the file is stored. Defaults to the root directory */
20
+ directory?: string;
21
+ /** Name under which the file is stored. If specified, the file is stored with that name. Otherwise random name generation is done */
22
+ fileName?: string;
23
+ /** When using random file name generation (ie: fileName is undefined). We use the MIME type to determine which is the best extension to apply to the file */
24
+ mime?: string;
25
+ /** When using random file name generation (ie: fileName is undefined), use this parameter to skip adding an extension to the file */
26
+ noExtension?: boolean;
27
+ }
28
+ /** Options of the S3 file uploader */
29
+ export interface S3UploaderOptions {
30
+ /** Maximum size of the file (ex: 2MB) */
31
+ maxSize?: string;
32
+ }
33
+ /** Object representing a file that has been uploaded to S3 */
34
+ export interface S3UploadedFile {
35
+ /** Bucket in which the file has been uploaded */
36
+ Bucket: string;
37
+ /** Key (path) of the stored object */
38
+ Key: string;
39
+ /** ETag of the uploaded file */
40
+ ETag?: string;
41
+ /** Location URL of the uploaded file */
42
+ Location?: string;
43
+ /** Server-side encryption method */
44
+ ServerSideEncryption?: string;
45
+ /** Version ID (if versioning is enabled) */
46
+ VersionId?: string;
47
+ }
48
+ /** Return type for a file download */
49
+ export interface S3GetResponse {
50
+ /** The file raw binary content */
51
+ data: Buffer;
52
+ /** The file's metadata */
53
+ metadata: S3FileMetadata;
54
+ }
55
+ /** Return type for a file streaming fetching */
56
+ export interface S3DownloadResponse {
57
+ /** A readable stream with the file's content */
58
+ stream: Readable;
59
+ /** The file's metadata */
60
+ metadata: S3FileMetadata;
61
+ }
62
+ /** S3 file metadata */
63
+ export interface S3FileMetadata {
64
+ /** Content type of the file */
65
+ ContentType?: string;
66
+ /** Content length in bytes */
67
+ ContentLength?: number;
68
+ /** Last modified date */
69
+ LastModified?: Date;
70
+ /** ETag */
71
+ ETag?: string;
72
+ /** Metadata key-value pairs */
73
+ Metadata?: Record<string, string>;
74
+ /** Server-side encryption */
75
+ ServerSideEncryption?: string;
76
+ /** Version ID */
77
+ VersionId?: string;
78
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ //# sourceMappingURL=AWSS3.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AWSS3.types.js","names":[],"sources":["../../../src/entities/AWSS3/AWSS3.types.ts"],"sourcesContent":["import { Readable } from 'stream';\n\n/** AWS S3 initialization configuration */\nexport interface AWSS3Config {\n /** AWS Region (e.g., 'us-east-1') */\n region?: string;\n /** AWS Access Key ID */\n accessKeyId?: string;\n /** AWS Secret Access Key */\n secretAccessKey?: string;\n /** AWS Session Token (for temporary credentials) */\n sessionToken?: string;\n /** Custom endpoint (useful for S3-compatible services like MinIO, LocalStack) */\n endpoint?: string;\n /** Force path style (required for some S3-compatible services) */\n forcePathStyle?: boolean;\n}\n\n/** Options to set where an uploaded file is stored in the S3 bucket */\nexport interface S3UploadDestinationOptions {\n /** Directory of the bucket in which the file is stored. Defaults to the root directory */\n directory?: string;\n /** Name under which the file is stored. If specified, the file is stored with that name. Otherwise random name generation is done */\n fileName?: string;\n /** When using random file name generation (ie: fileName is undefined). We use the MIME type to determine which is the best extension to apply to the file */\n mime?: string;\n /** When using random file name generation (ie: fileName is undefined), use this parameter to skip adding an extension to the file */\n noExtension?: boolean;\n}\n\n/** Options of the S3 file uploader */\nexport interface S3UploaderOptions {\n /** Maximum size of the file (ex: 2MB) */\n maxSize?: string;\n}\n\n/** Object representing a file that has been uploaded to S3 */\nexport interface S3UploadedFile {\n /** Bucket in which the file has been uploaded */\n Bucket: string;\n /** Key (path) of the stored object */\n Key: string;\n /** ETag of the uploaded file */\n ETag?: string;\n /** Location URL of the uploaded file */\n Location?: string;\n /** Server-side encryption method */\n ServerSideEncryption?: string;\n /** Version ID (if versioning is enabled) */\n VersionId?: string;\n}\n\n/** Return type for a file download */\nexport interface S3GetResponse {\n /** The file raw binary content */\n data: Buffer;\n /** The file's metadata */\n metadata: S3FileMetadata;\n}\n\n/** Return type for a file streaming fetching */\nexport interface S3DownloadResponse {\n /** A readable stream with the file's content */\n stream: Readable;\n /** The file's metadata */\n metadata: S3FileMetadata;\n}\n\n/** S3 file metadata */\nexport interface S3FileMetadata {\n /** Content type of the file */\n ContentType?: string;\n /** Content length in bytes */\n ContentLength?: number;\n /** Last modified date */\n LastModified?: Date;\n /** ETag */\n ETag?: string;\n /** Metadata key-value pairs */\n Metadata?: Record<string, string>;\n /** Server-side encryption */\n ServerSideEncryption?: string;\n /** Version ID */\n VersionId?: string;\n}\n"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,2 @@
1
+ export * from './AWSS3';
2
+ export * from './AWSS3.types';
@@ -3,25 +3,25 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- var _Storage = require("./Storage");
7
- Object.keys(_Storage).forEach(function (key) {
6
+ var _AWSS = require("./AWSS3");
7
+ Object.keys(_AWSS).forEach(function (key) {
8
8
  if (key === "default" || key === "__esModule") return;
9
- if (key in exports && exports[key] === _Storage[key]) return;
9
+ if (key in exports && exports[key] === _AWSS[key]) return;
10
10
  Object.defineProperty(exports, key, {
11
11
  enumerable: true,
12
12
  get: function () {
13
- return _Storage[key];
13
+ return _AWSS[key];
14
14
  }
15
15
  });
16
16
  });
17
- var _Storage2 = require("./Storage.types");
18
- Object.keys(_Storage2).forEach(function (key) {
17
+ var _AWSS2 = require("./AWSS3.types");
18
+ Object.keys(_AWSS2).forEach(function (key) {
19
19
  if (key === "default" || key === "__esModule") return;
20
- if (key in exports && exports[key] === _Storage2[key]) return;
20
+ if (key in exports && exports[key] === _AWSS2[key]) return;
21
21
  Object.defineProperty(exports, key, {
22
22
  enumerable: true,
23
23
  get: function () {
24
- return _Storage2[key];
24
+ return _AWSS2[key];
25
25
  }
26
26
  });
27
27
  });
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["_AWSS","require","Object","keys","forEach","key","exports","defineProperty","enumerable","get","_AWSS2"],"sources":["../../../src/entities/AWSS3/index.ts"],"sourcesContent":["export * from './AWSS3';\nexport * from './AWSS3.types';\n"],"mappings":";;;;;AAAA,IAAAA,KAAA,GAAAC,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAH,KAAA,EAAAI,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAL,KAAA,CAAAK,GAAA;EAAAH,MAAA,CAAAK,cAAA,CAAAD,OAAA,EAAAD,GAAA;IAAAG,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAT,KAAA,CAAAK,GAAA;IAAA;EAAA;AAAA;AACA,IAAAK,MAAA,GAAAT,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAO,MAAA,EAAAN,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAK,MAAA,CAAAL,GAAA;EAAAH,MAAA,CAAAK,cAAA,CAAAD,OAAA,EAAAD,GAAA;IAAAG,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAC,MAAA,CAAAL,GAAA;IAAA;EAAA;AAAA","ignoreList":[]}
@@ -1,8 +1,13 @@
1
+ import { Client } from '@elastic/elasticsearch';
1
2
  export declare const ElasticSearch: {
2
3
  /**
3
4
  * Init function that should be called on server startup to establish the connection
4
5
  */
5
6
  init(): Promise<void>;
7
+ /**
8
+ * Get the ElasticSearch client (for advanced use cases)
9
+ */
10
+ getClient(): Client | undefined;
6
11
  /**
7
12
  * Migration function called during the init process
8
13
  * Manages the database structure
@@ -13,6 +13,8 @@ var _LifecycleController = require("../LifecycleController");
13
13
  var _utils = require("../../utils");
14
14
  var _checkEnvironment = require("../../utils/checkEnvironment");
15
15
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
16
+ const namespace = 'engine:elasticsearch';
17
+
16
18
  /** Elastic search client */
17
19
  let client;
18
20
  const ElasticSearch = exports.ElasticSearch = {
@@ -27,77 +29,158 @@ const ElasticSearch = exports.ElasticSearch = {
27
29
  ELASTIC_SEARCH_MIGRATION_PATH: _utils.envAssert.isString()
28
30
  });
29
31
  if (!process.env.ELASTIC_SEARCH_HOST) throw new _EngineError.EngineError({
30
- message: 'ElasticSearch Hosts not set in environment'
32
+ message: 'ElasticSearch Host not set in environment'
33
+ });
34
+ (0, _utils.reportDebug)({
35
+ namespace,
36
+ message: 'Initializing ElasticSearch client',
37
+ data: {
38
+ host: process.env.ELASTIC_SEARCH_HOST
39
+ }
31
40
  });
32
- client = new _elasticsearch.Client({
41
+ const config = {
33
42
  node: process.env.ELASTIC_SEARCH_HOST,
34
43
  auth: {
35
44
  username: process.env.ELASTIC_SEARCH_USERNAME,
36
45
  password: process.env.ELASTIC_SEARCH_PASSWORD
37
- }
38
- });
46
+ },
47
+ maxRetries: 3,
48
+ requestTimeout: 30000,
49
+ sniffOnStart: false
50
+ };
51
+
52
+ // Add TLS configuration if TLS_CA is provided
53
+ if (process.env.TLS_CA) {
54
+ config.tls = {
55
+ ca: process.env.TLS_CA,
56
+ rejectUnauthorized: process.env.NODE_ENV === 'production'
57
+ };
58
+ (0, _utils.reportDebug)({
59
+ namespace,
60
+ message: 'TLS enabled for ElasticSearch connection'
61
+ });
62
+ }
63
+ client = new _elasticsearch.Client(config);
64
+
65
+ // Verify connection
66
+ try {
67
+ await client.ping();
68
+ (0, _utils.reportDebug)({
69
+ namespace,
70
+ message: 'ElasticSearch connection established'
71
+ });
72
+ } catch (error) {
73
+ throw new _EngineError.EngineError({
74
+ message: 'Failed to connect to ElasticSearch',
75
+ data: {
76
+ error: error.message
77
+ }
78
+ });
79
+ }
80
+
39
81
  // In test environment flush the database before running migrations
40
- if (process.env.NODE_ENV === 'test') await client.indices.delete({
41
- index: '*'
42
- });
82
+ if (process.env.NODE_ENV === 'test') {
83
+ (0, _utils.reportDebug)({
84
+ namespace,
85
+ message: 'Test environment detected, flushing all indices'
86
+ });
87
+ await client.indices.delete({
88
+ index: '*'
89
+ });
90
+ }
43
91
  await this.migrate();
44
92
  _LifecycleController.LifecycleController.register(this);
93
+ (0, _utils.reportInfo)({
94
+ message: 'ElasticSearch initialized successfully'
95
+ });
96
+ },
97
+ /**
98
+ * Get the ElasticSearch client (for advanced use cases)
99
+ */
100
+ getClient() {
101
+ return client;
45
102
  },
46
103
  /**
47
104
  * Migration function called during the init process
48
105
  * Manages the database structure
49
106
  */
50
107
  async migrate() {
51
- if (!client) throw new _EngineError.EngineError('ElasticSearch was not initialized');
108
+ if (!client) throw new _EngineError.EngineError({
109
+ message: 'ElasticSearch was not initialized'
110
+ });
111
+ (0, _utils.reportDebug)({
112
+ namespace,
113
+ message: 'Starting ElasticSearch migrations'
114
+ });
52
115
  const migrationPath = _path.default.resolve(process.env.ELASTIC_SEARCH_MIGRATION_PATH);
53
- const files = (0, _fs.readdirSync)(`${migrationPath}`);
116
+ let files;
117
+ try {
118
+ files = (0, _fs.readdirSync)(migrationPath).filter(f => f.endsWith('.ts') || f.endsWith('.js'));
119
+ } catch (error) {
120
+ throw new _EngineError.EngineError({
121
+ message: 'Failed to read migration directory',
122
+ data: {
123
+ path: migrationPath,
124
+ error: error.message
125
+ }
126
+ });
127
+ }
54
128
  const indexExists = await client.indices.exists({
55
129
  index: 'migrations'
56
130
  });
57
131
  const ran = [];
58
132
  for (const file of files) {
59
133
  if (indexExists) {
60
- const {
61
- hits: {
62
- total
63
- }
64
- } = await client.search({
134
+ const result = await client.search({
65
135
  index: 'migrations',
66
- body: {
67
- query: {
68
- match: {
69
- file
70
- }
136
+ query: {
137
+ match: {
138
+ file
71
139
  }
72
140
  }
73
141
  });
74
- let tot = 0;
75
- if (typeof total === 'number') {
76
- tot = total;
77
- } else {
78
- tot = total?.value ?? 0;
142
+ const total = typeof result.hits.total === 'number' ? result.hits.total : result.hits.total?.value ?? 0;
143
+ if (total > 0) {
144
+ (0, _utils.reportDebug)({
145
+ namespace,
146
+ message: `Skipping migration ${file} (already ran)`
147
+ });
148
+ continue;
79
149
  }
80
- if (tot > 0) continue;
81
150
  }
151
+ (0, _utils.reportDebug)({
152
+ namespace,
153
+ message: `Running migration: ${file}`
154
+ });
82
155
  ran.push(file);
83
- const migration = await (specifier => new Promise(r => r(specifier)).then(s => _interopRequireWildcard(require(s))))(`${migrationPath}/${file}`);
84
156
  try {
157
+ const migration = await (specifier => new Promise(r => r(specifier)).then(s => _interopRequireWildcard(require(s))))(`${migrationPath}/${file}`);
85
158
  await migration.migrate(client);
159
+ await client.index({
160
+ index: 'migrations',
161
+ id: file,
162
+ document: {
163
+ file,
164
+ ranAt: new Date().toISOString()
165
+ }
166
+ });
167
+ (0, _utils.reportDebug)({
168
+ namespace,
169
+ message: `Successfully ran migration: ${file}`
170
+ });
86
171
  } catch (error) {
87
- (0, _utils.reportError)(error);
88
- process.exit(1);
172
+ (0, _utils.reportError)(new _EngineError.EngineError({
173
+ message: `Migration failed: ${file}`,
174
+ data: {
175
+ error: error.message,
176
+ stack: error.stack
177
+ }
178
+ }));
179
+ throw error;
89
180
  }
90
- await client.create({
91
- index: 'migrations',
92
- id: file,
93
- body: {
94
- file,
95
- ranAt: new Date()
96
- }
97
- });
98
181
  }
99
182
  (0, _utils.reportInfo)({
100
- message: `ElasticSearch: ran ${ran.length} migrations`,
183
+ message: `ElasticSearch: ran ${ran.length} migration(s)`,
101
184
  data: {
102
185
  files: ran
103
186
  }
@@ -107,7 +190,23 @@ const ElasticSearch = exports.ElasticSearch = {
107
190
  * Shutdown function that should be called on server stop to close the connection
108
191
  */
109
192
  async shutdown() {
110
- if (client) await client.close();
193
+ if (client) {
194
+ try {
195
+ await client.close();
196
+ (0, _utils.reportDebug)({
197
+ namespace,
198
+ message: 'ElasticSearch client disconnected'
199
+ });
200
+ } catch (error) {
201
+ (0, _utils.reportError)(new _EngineError.EngineError({
202
+ message: 'Error during ElasticSearch shutdown',
203
+ data: {
204
+ error: error.message
205
+ }
206
+ }));
207
+ }
208
+ client = undefined;
209
+ }
111
210
  }
112
211
  };
113
212
  //# sourceMappingURL=ElasticSearch.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ElasticSearch.js","names":["_fs","require","_path","_interopRequireDefault","_elasticsearch","_EngineError","_LifecycleController","_utils","_checkEnvironment","_interopRequireWildcard","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","client","ElasticSearch","exports","init","checkEnvironment","ELASTIC_SEARCH_HOST","envAssert","isString","ELASTIC_SEARCH_USERNAME","ELASTIC_SEARCH_PASSWORD","ELASTIC_SEARCH_MIGRATION_PATH","process","env","EngineError","message","Client","node","auth","username","password","NODE_ENV","indices","delete","index","migrate","LifecycleController","register","migrationPath","path","resolve","files","readdirSync","indexExists","exists","ran","file","hits","total","search","body","query","match","tot","value","push","migration","specifier","Promise","then","s","error","reportError","exit","create","id","ranAt","Date","reportInfo","length","data","shutdown","close"],"sources":["../../../src/entities/ElasticSearch/ElasticSearch.ts"],"sourcesContent":["import { readdirSync } from 'fs';\nimport path from 'path';\nimport { Client } from '@elastic/elasticsearch';\nimport { ElasticSearchMigration } from './ElasticSearch.types';\nimport { EngineError } from 'entities/EngineError';\nimport { LifecycleController } from 'entities/LifecycleController';\nimport { envAssert, reportError, reportInfo } from 'utils';\nimport { checkEnvironment } from 'utils/checkEnvironment';\n\n/** Elastic search client */\nlet client: undefined | Client;\n\nexport const ElasticSearch = {\n /**\n * Init function that should be called on server startup to establish the connection\n */\n async init(): Promise<void> {\n checkEnvironment({\n ELASTIC_SEARCH_HOST: envAssert.isString(),\n ELASTIC_SEARCH_USERNAME: envAssert.isString(),\n ELASTIC_SEARCH_PASSWORD: envAssert.isString(),\n ELASTIC_SEARCH_MIGRATION_PATH: envAssert.isString()\n });\n\n if (!process.env.ELASTIC_SEARCH_HOST)\n throw new EngineError({\n message: 'ElasticSearch Hosts not set in environment'\n });\n\n client = new Client({\n node: process.env.ELASTIC_SEARCH_HOST,\n auth: {\n username: process.env.ELASTIC_SEARCH_USERNAME as string,\n password: process.env.ELASTIC_SEARCH_PASSWORD as string\n }\n });\n // In test environment flush the database before running migrations\n if (process.env.NODE_ENV === 'test')\n await client.indices.delete({ index: '*' });\n await this.migrate();\n LifecycleController.register(this);\n },\n\n /**\n * Migration function called during the init process\n * Manages the database structure\n */\n async migrate(): Promise<void> {\n if (!client) throw new EngineError('ElasticSearch was not initialized');\n const migrationPath = path.resolve(\n process.env.ELASTIC_SEARCH_MIGRATION_PATH as string\n );\n const files = readdirSync(`${migrationPath}`);\n const indexExists = await client.indices.exists({\n index: 'migrations'\n });\n const ran = [];\n for (const file of files) {\n if (indexExists) {\n const {\n hits: { total }\n } = await client.search({\n index: 'migrations',\n body: { query: { match: { file } } }\n });\n let tot = 0;\n if (typeof total === 'number') {\n tot = total;\n } else {\n tot = total?.value ?? 0;\n }\n if (tot > 0) continue;\n }\n ran.push(file);\n const migration = (await import(\n `${migrationPath}/${file}`\n )) as ElasticSearchMigration;\n try {\n await migration.migrate(client);\n } catch (error) {\n reportError(error);\n process.exit(1);\n }\n\n await client.create({\n index: 'migrations',\n id: file,\n body: { file, ranAt: new Date() }\n });\n }\n reportInfo({\n message: `ElasticSearch: ran ${ran.length} migrations`,\n data: { files: ran }\n });\n },\n\n /**\n * Shutdown function that should be called on server stop to close the connection\n */\n async shutdown(): Promise<void> {\n if (client) await client.close();\n }\n};\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"ElasticSearch.js","names":["_fs","require","_path","_interopRequireDefault","_elasticsearch","_EngineError","_LifecycleController","_utils","_checkEnvironment","_interopRequireWildcard","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","namespace","client","ElasticSearch","exports","init","checkEnvironment","ELASTIC_SEARCH_HOST","envAssert","isString","ELASTIC_SEARCH_USERNAME","ELASTIC_SEARCH_PASSWORD","ELASTIC_SEARCH_MIGRATION_PATH","process","env","EngineError","message","reportDebug","data","host","config","node","auth","username","password","maxRetries","requestTimeout","sniffOnStart","TLS_CA","tls","ca","rejectUnauthorized","NODE_ENV","Client","ping","error","indices","delete","index","migrate","LifecycleController","register","reportInfo","getClient","migrationPath","path","resolve","files","readdirSync","filter","endsWith","indexExists","exists","ran","file","result","search","query","match","total","hits","value","push","migration","specifier","Promise","then","s","id","document","ranAt","Date","toISOString","reportError","stack","length","shutdown","close","undefined"],"sources":["../../../src/entities/ElasticSearch/ElasticSearch.ts"],"sourcesContent":["import { readdirSync } from 'fs';\nimport path from 'path';\nimport { Client } from '@elastic/elasticsearch';\nimport { ElasticSearchMigration } from './ElasticSearch.types';\nimport { EngineError } from 'entities/EngineError';\nimport { LifecycleController } from 'entities/LifecycleController';\nimport { envAssert, reportError, reportInfo, reportDebug } from 'utils';\nimport { checkEnvironment } from 'utils/checkEnvironment';\n\nconst namespace = 'engine:elasticsearch';\n\n/** Elastic search client */\nlet client: undefined | Client;\n\nexport const ElasticSearch = {\n /**\n * Init function that should be called on server startup to establish the connection\n */\n async init(): Promise<void> {\n checkEnvironment({\n ELASTIC_SEARCH_HOST: envAssert.isString(),\n ELASTIC_SEARCH_USERNAME: envAssert.isString(),\n ELASTIC_SEARCH_PASSWORD: envAssert.isString(),\n ELASTIC_SEARCH_MIGRATION_PATH: envAssert.isString()\n });\n\n if (!process.env.ELASTIC_SEARCH_HOST)\n throw new EngineError({\n message: 'ElasticSearch Host not set in environment'\n });\n\n reportDebug({\n namespace,\n message: 'Initializing ElasticSearch client',\n data: { host: process.env.ELASTIC_SEARCH_HOST }\n });\n\n const config: any = {\n node: process.env.ELASTIC_SEARCH_HOST,\n auth: {\n username: process.env.ELASTIC_SEARCH_USERNAME as string,\n password: process.env.ELASTIC_SEARCH_PASSWORD as string\n },\n maxRetries: 3,\n requestTimeout: 30000,\n sniffOnStart: false\n };\n\n // Add TLS configuration if TLS_CA is provided\n if (process.env.TLS_CA) {\n config.tls = {\n ca: process.env.TLS_CA,\n rejectUnauthorized: process.env.NODE_ENV === 'production'\n };\n reportDebug({\n namespace,\n message: 'TLS enabled for ElasticSearch connection'\n });\n }\n\n client = new Client(config);\n\n // Verify connection\n try {\n await client.ping();\n reportDebug({\n namespace,\n message: 'ElasticSearch connection established'\n });\n } catch (error) {\n throw new EngineError({\n message: 'Failed to connect to ElasticSearch',\n data: { error: (error as Error).message }\n });\n }\n\n // In test environment flush the database before running migrations\n if (process.env.NODE_ENV === 'test') {\n reportDebug({\n namespace,\n message: 'Test environment detected, flushing all indices'\n });\n await client.indices.delete({ index: '*' });\n }\n\n await this.migrate();\n LifecycleController.register(this);\n\n reportInfo({ message: 'ElasticSearch initialized successfully' });\n },\n\n /**\n * Get the ElasticSearch client (for advanced use cases)\n */\n getClient(): Client | undefined {\n return client;\n },\n\n /**\n * Migration function called during the init process\n * Manages the database structure\n */\n async migrate(): Promise<void> {\n if (!client) throw new EngineError({ message: 'ElasticSearch was not initialized' });\n\n reportDebug({\n namespace,\n message: 'Starting ElasticSearch migrations'\n });\n\n const migrationPath = path.resolve(\n process.env.ELASTIC_SEARCH_MIGRATION_PATH as string\n );\n\n let files: string[];\n try {\n files = readdirSync(migrationPath).filter(\n f => f.endsWith('.ts') || f.endsWith('.js')\n );\n } catch (error) {\n throw new EngineError({\n message: 'Failed to read migration directory',\n data: { path: migrationPath, error: (error as Error).message }\n });\n }\n\n const indexExists = await client.indices.exists({\n index: 'migrations'\n });\n\n const ran: string[] = [];\n\n for (const file of files) {\n if (indexExists) {\n const result = await client.search({\n index: 'migrations',\n query: { match: { file } }\n });\n\n const total = typeof result.hits.total === 'number'\n ? result.hits.total\n : result.hits.total?.value ?? 0;\n\n if (total > 0) {\n reportDebug({\n namespace,\n message: `Skipping migration ${file} (already ran)`\n });\n continue;\n }\n }\n\n reportDebug({\n namespace,\n message: `Running migration: ${file}`\n });\n\n ran.push(file);\n\n try {\n const migration = (await import(\n `${migrationPath}/${file}`\n )) as ElasticSearchMigration;\n\n await migration.migrate(client);\n\n await client.index({\n index: 'migrations',\n id: file,\n document: { file, ranAt: new Date().toISOString() }\n });\n\n reportDebug({\n namespace,\n message: `Successfully ran migration: ${file}`\n });\n } catch (error) {\n reportError(\n new EngineError({\n message: `Migration failed: ${file}`,\n data: { error: (error as Error).message, stack: (error as Error).stack }\n })\n );\n throw error;\n }\n }\n\n reportInfo({\n message: `ElasticSearch: ran ${ran.length} migration(s)`,\n data: { files: ran }\n });\n },\n\n /**\n * Shutdown function that should be called on server stop to close the connection\n */\n async shutdown(): Promise<void> {\n if (client) {\n try {\n await client.close();\n reportDebug({\n namespace,\n message: 'ElasticSearch client disconnected'\n });\n } catch (error) {\n reportError(\n new EngineError({\n message: 'Error during ElasticSearch shutdown',\n data: { error: (error as Error).message }\n })\n );\n }\n client = undefined;\n }\n }\n};\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,141 @@
1
+ import { Readable } from 'stream';
2
+ import { Storage as CloudStorage, CreateWriteStreamOptions } from '@google-cloud/storage';
3
+ import { UploadDestinationOptions, StorageUploadedFile, UploaderOptions, StorageGetResponse, StorageDownloadResponse, GoogleCloudStorageConfig } from './GoogleCloudStorage.types';
4
+ /**
5
+ * Generic Google Cloud Storage wrapper for easy file operations
6
+ * Provides methods for uploading, downloading, streaming, and deleting files
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * // Initialize with custom configuration
11
+ * GoogleCloudStorage.init({
12
+ * projectId: 'my-project',
13
+ * keyFilename: '/path/to/keyfile.json'
14
+ * });
15
+ *
16
+ * // Upload a file
17
+ * const result = await GoogleCloudStorage.upload(
18
+ * fileStream,
19
+ * 'my-bucket',
20
+ * { directory: 'uploads', mime: 'image/png' }
21
+ * );
22
+ *
23
+ * // Download a file
24
+ * const { data, metadata } = await GoogleCloudStorage.get('my-bucket', 'uploads/file.png');
25
+ *
26
+ * // Delete a file
27
+ * await GoogleCloudStorage.delete('my-bucket', 'uploads/file.png');
28
+ * ```
29
+ */
30
+ export declare const GoogleCloudStorage: {
31
+ cloudStorage: CloudStorage | null;
32
+ /**
33
+ * Initialize Google Cloud Storage with configuration
34
+ * Call this method before using any other methods
35
+ * @param config - Google Cloud Storage configuration options
36
+ */
37
+ init(config?: GoogleCloudStorageConfig): void;
38
+ /**
39
+ * Get the Cloud Storage instance (auto-initializes if needed)
40
+ * @private
41
+ */
42
+ getStorageInstance(): CloudStorage;
43
+ /**
44
+ * Upload a file to Google Cloud Storage
45
+ * @param readStream - Readable stream of the file content
46
+ * @param bucket - Bucket name where the file should be stored
47
+ * @param destinationOptions - Options for file destination (directory, fileName, etc.)
48
+ * @param storageOptions - Google Cloud Storage write stream options
49
+ * @param uploaderOptions - Additional options like maxSize
50
+ * @returns Promise with file metadata
51
+ *
52
+ * @example
53
+ * ```typescript
54
+ * const fileStream = fs.createReadStream('photo.jpg');
55
+ * const result = await GoogleCloudStorage.upload(
56
+ * fileStream,
57
+ * 'my-bucket',
58
+ * { directory: 'photos', mime: 'image/jpeg' },
59
+ * { metadata: { contentType: 'image/jpeg' } },
60
+ * { maxSize: '5MB' }
61
+ * );
62
+ * console.log(result.name); // photos/uuid.jpeg
63
+ * ```
64
+ */
65
+ upload(readStream: Readable, bucket: string, destinationOptions?: UploadDestinationOptions, storageOptions?: CreateWriteStreamOptions, uploaderOptions?: UploaderOptions): Promise<StorageUploadedFile>;
66
+ /**
67
+ * Download a file from Google Cloud Storage and return its content as Buffer
68
+ * @param bucket - Bucket name
69
+ * @param path - File path in the bucket
70
+ * @returns Promise with file data and metadata
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * const { data, metadata } = await GoogleCloudStorage.get('my-bucket', 'photos/image.jpg');
75
+ * console.log(metadata.size); // File size in bytes
76
+ * console.log(data); // Buffer with file content
77
+ * ```
78
+ */
79
+ get(bucket: string, path: string): Promise<StorageGetResponse>;
80
+ /**
81
+ * Get a readable stream for a file from Google Cloud Storage
82
+ * Use this for large files or when you need to stream the content
83
+ * @param bucket - Bucket name
84
+ * @param path - File path in the bucket
85
+ * @returns Promise with readable stream and metadata
86
+ *
87
+ * @example
88
+ * ```typescript
89
+ * const { stream, metadata } = await GoogleCloudStorage.download('my-bucket', 'videos/video.mp4');
90
+ * stream.pipe(res); // Stream to HTTP response
91
+ * ```
92
+ */
93
+ download(bucket: string, path: string): Promise<StorageDownloadResponse>;
94
+ /**
95
+ * Get a readable stream for a file (without fetching metadata)
96
+ * Use this when you don't need metadata and want faster streaming
97
+ * @param bucket - Bucket name
98
+ * @param path - File path in the bucket
99
+ * @returns Readable stream
100
+ *
101
+ * @example
102
+ * ```typescript
103
+ * const stream = GoogleCloudStorage.getFileStream('my-bucket', 'audio/song.mp3');
104
+ * stream.pipe(res); // Direct streaming without metadata fetch
105
+ * ```
106
+ */
107
+ getFileStream(bucket: string, path: string): Readable;
108
+ /**
109
+ * Delete a file from Google Cloud Storage
110
+ * @param bucket - Bucket name
111
+ * @param path - File path in the bucket
112
+ * @returns Promise that resolves when deletion is complete
113
+ *
114
+ * @example
115
+ * ```typescript
116
+ * await GoogleCloudStorage.delete('my-bucket', 'temp/old-file.txt');
117
+ * ```
118
+ */
119
+ delete(bucket: string, path: string): Promise<void>;
120
+ /**
121
+ * Generate a random file path with optional directory and extension
122
+ * Useful for creating unique file names
123
+ * @param options - Options for file destination generation
124
+ * @returns Generated file path
125
+ *
126
+ * @example
127
+ * ```typescript
128
+ * // Generate UUID only
129
+ * const path1 = GoogleCloudStorage.generateFileDestination();
130
+ * // 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'
131
+ *
132
+ * // With directory and MIME type
133
+ * const path2 = GoogleCloudStorage.generateFileDestination({
134
+ * directory: 'uploads/images',
135
+ * mime: 'image/jpeg'
136
+ * });
137
+ * // 'uploads/images/a1b2c3d4-e5f6-7890-abcd-ef1234567890.jpeg'
138
+ * ```
139
+ */
140
+ generateFileDestination(options?: UploadDestinationOptions): string;
141
+ };