node-server-engine 1.8.0 → 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.
- package/README.md +712 -67
- package/dist/entities/AWSS3/AWSS3.d.ts +157 -0
- package/dist/entities/AWSS3/AWSS3.js +426 -0
- package/dist/entities/AWSS3/AWSS3.js.map +1 -0
- package/dist/entities/AWSS3/AWSS3.types.d.ts +78 -0
- package/dist/entities/AWSS3/AWSS3.types.js +2 -0
- package/dist/entities/AWSS3/AWSS3.types.js.map +1 -0
- package/dist/entities/AWSS3/index.d.ts +2 -0
- package/dist/entities/{Storage → AWSS3}/index.js +8 -8
- package/dist/entities/AWSS3/index.js.map +1 -0
- package/dist/entities/ElasticSearch/ElasticSearch.d.ts +5 -0
- package/dist/entities/ElasticSearch/ElasticSearch.js +137 -38
- package/dist/entities/ElasticSearch/ElasticSearch.js.map +1 -1
- package/dist/entities/GoogleCloudStorage/GoogleCloudStorage.d.ts +141 -0
- package/dist/entities/GoogleCloudStorage/GoogleCloudStorage.js +351 -0
- package/dist/entities/GoogleCloudStorage/GoogleCloudStorage.js.map +1 -0
- package/dist/entities/{Storage/Storage.types.d.ts → GoogleCloudStorage/GoogleCloudStorage.types.d.ts} +14 -0
- package/dist/entities/GoogleCloudStorage/GoogleCloudStorage.types.js +2 -0
- package/dist/entities/GoogleCloudStorage/GoogleCloudStorage.types.js.map +1 -0
- package/dist/entities/GoogleCloudStorage/index.d.ts +2 -0
- package/dist/entities/GoogleCloudStorage/index.js +28 -0
- package/dist/entities/GoogleCloudStorage/index.js.map +1 -0
- package/dist/entities/Localizator/Localizator.js +2 -2
- package/dist/entities/Localizator/Localizator.js.map +1 -1
- package/dist/entities/index.d.ts +2 -1
- package/dist/entities/index.js +15 -4
- package/dist/entities/index.js.map +1 -1
- package/package.json +11 -10
- package/dist/entities/Storage/Storage.d.ts +0 -38
- package/dist/entities/Storage/Storage.js +0 -214
- package/dist/entities/Storage/Storage.js.map +0 -1
- package/dist/entities/Storage/Storage.types.js +0 -2
- package/dist/entities/Storage/Storage.types.js.map +0 -1
- package/dist/entities/Storage/index.d.ts +0 -2
- 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 @@
|
|
|
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":[]}
|
|
@@ -3,25 +3,25 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
var
|
|
7
|
-
Object.keys(
|
|
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] ===
|
|
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
|
|
13
|
+
return _AWSS[key];
|
|
14
14
|
}
|
|
15
15
|
});
|
|
16
16
|
});
|
|
17
|
-
var
|
|
18
|
-
Object.keys(
|
|
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] ===
|
|
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
|
|
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
|
|
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
|
-
|
|
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')
|
|
41
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
file
|
|
70
|
-
}
|
|
136
|
+
query: {
|
|
137
|
+
match: {
|
|
138
|
+
file
|
|
71
139
|
}
|
|
72
140
|
}
|
|
73
141
|
});
|
|
74
|
-
|
|
75
|
-
if (
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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)(
|
|
88
|
-
|
|
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}
|
|
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)
|
|
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
|
+
};
|