@golemio/core 3.1.1 → 3.2.0-dev.2585439595
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/dist/helpers/data-access/azure/AzureBearerTokenProvider.d.ts +9 -0
- package/dist/helpers/data-access/azure/AzureBearerTokenProvider.js +27 -0
- package/dist/helpers/data-access/azure/AzureBearerTokenProvider.js.map +1 -0
- package/dist/helpers/data-access/azure/buildBearerTokenProvider.d.ts +12 -0
- package/dist/helpers/data-access/azure/buildBearerTokenProvider.js +30 -0
- package/dist/helpers/data-access/azure/buildBearerTokenProvider.js.map +1 -0
- package/dist/helpers/data-access/azure/index.d.ts +5 -0
- package/dist/helpers/data-access/azure/index.js +10 -0
- package/dist/helpers/data-access/azure/index.js.map +1 -0
- package/dist/helpers/data-access/opensearch/IOpenSearchConnector.d.ts +8 -0
- package/dist/helpers/data-access/opensearch/IOpenSearchConnector.js +3 -0
- package/dist/helpers/data-access/opensearch/IOpenSearchConnector.js.map +1 -0
- package/dist/helpers/data-access/opensearch/IOpenSearchInfo.d.ts +6 -0
- package/dist/helpers/data-access/opensearch/IOpenSearchInfo.js +3 -0
- package/dist/helpers/data-access/opensearch/IOpenSearchInfo.js.map +1 -0
- package/dist/helpers/data-access/opensearch/ISyncableIndex.d.ts +9 -0
- package/dist/helpers/data-access/opensearch/ISyncableIndex.js +3 -0
- package/dist/helpers/data-access/opensearch/ISyncableIndex.js.map +1 -0
- package/dist/helpers/data-access/opensearch/OpenSearchConnector.d.ts +21 -0
- package/dist/helpers/data-access/opensearch/OpenSearchConnector.js +113 -0
- package/dist/helpers/data-access/opensearch/OpenSearchConnector.js.map +1 -0
- package/dist/helpers/data-access/opensearch/OpenSearchService.d.ts +24 -0
- package/dist/helpers/data-access/opensearch/OpenSearchService.js +162 -0
- package/dist/helpers/data-access/opensearch/OpenSearchService.js.map +1 -0
- package/dist/helpers/data-access/opensearch/OpenSearchSyncOrchestrator.d.ts +14 -0
- package/dist/helpers/data-access/opensearch/OpenSearchSyncOrchestrator.js +78 -0
- package/dist/helpers/data-access/opensearch/OpenSearchSyncOrchestrator.js.map +1 -0
- package/dist/helpers/data-access/opensearch/czechAnalyzer.d.ts +6 -0
- package/dist/helpers/data-access/opensearch/czechAnalyzer.js +30 -0
- package/dist/helpers/data-access/opensearch/czechAnalyzer.js.map +1 -0
- package/dist/helpers/data-access/opensearch/index.d.ts +8 -0
- package/dist/helpers/data-access/opensearch/index.js +14 -0
- package/dist/helpers/data-access/opensearch/index.js.map +1 -0
- package/dist/helpers/data-access/postgres/DatabaseConnector.js +10 -3
- package/dist/helpers/data-access/postgres/DatabaseConnector.js.map +1 -1
- package/dist/helpers/data-access/postgres/IDatabaseInfo.d.ts +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/input-gateway/connectors/AMQPConnector.d.ts +1 -1
- package/dist/input-gateway/helpers/SaveRawDataMiddleware.d.ts +1 -1
- package/dist/integration-engine/connectors/AMQPConnector.d.ts +1 -1
- package/dist/integration-engine/data-access/RawDataStorage.d.ts +1 -1
- package/dist/integration-engine/datasources/BatchWritable.d.ts +16 -0
- package/dist/integration-engine/datasources/BatchWritable.js +42 -0
- package/dist/integration-engine/datasources/BatchWritable.js.map +1 -0
- package/dist/integration-engine/datasources/DataSourceStreamedPipeline.d.ts +25 -0
- package/dist/integration-engine/datasources/DataSourceStreamedPipeline.js +72 -0
- package/dist/integration-engine/datasources/DataSourceStreamedPipeline.js.map +1 -0
- package/dist/integration-engine/datasources/datatype-strategy/JSONStreamTransformer.d.ts +5 -0
- package/dist/integration-engine/datasources/datatype-strategy/JSONStreamTransformer.js +12 -0
- package/dist/integration-engine/datasources/datatype-strategy/JSONStreamTransformer.js.map +1 -0
- package/dist/integration-engine/datasources/index.d.ts +5 -0
- package/dist/integration-engine/datasources/index.js +5 -0
- package/dist/integration-engine/datasources/index.js.map +1 -1
- package/dist/integration-engine/datasources/protocol-strategy/HTTPRequestProtocolStrategyStreamed.d.ts +5 -1
- package/dist/integration-engine/datasources/protocol-strategy/HTTPRequestProtocolStrategyStreamed.js +30 -1
- package/dist/integration-engine/datasources/protocol-strategy/HTTPRequestProtocolStrategyStreamed.js.map +1 -1
- package/dist/integration-engine/datasources/protocol-strategy/IStreamingProtocolStrategy.d.ts +5 -0
- package/dist/integration-engine/datasources/protocol-strategy/IStreamingProtocolStrategy.js +3 -0
- package/dist/integration-engine/datasources/protocol-strategy/IStreamingProtocolStrategy.js.map +1 -0
- package/dist/integration-engine/datasources/protocol-strategy/ProtocolStrategy.d.ts +3 -0
- package/dist/integration-engine/datasources/protocol-strategy/ProtocolStrategy.js +42 -3
- package/dist/integration-engine/datasources/protocol-strategy/ProtocolStrategy.js.map +1 -1
- package/dist/integration-engine/helpers/GeocodeApi.d.ts +1 -1
- package/dist/integration-engine/ioc/Di.js +1 -0
- package/dist/integration-engine/ioc/Di.js.map +1 -1
- package/dist/output-gateway/ioc/Di.js +1 -0
- package/dist/output-gateway/ioc/Di.js.map +1 -1
- package/dist/output-gateway/models/interfaces/IGeoJsonModel.d.ts +1 -1
- package/dist/shared/opensearch.d.ts +1 -0
- package/dist/shared/opensearch.js +18 -0
- package/dist/shared/opensearch.js.map +1 -0
- package/package.json +16 -6
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AccessToken } from "@azure/core-auth";
|
|
2
|
+
import { AbstractAzureService } from "./AbstractAzureService";
|
|
3
|
+
import { IAzureServiceConfig } from "./IAzureServiceConfig";
|
|
4
|
+
export declare class AzureBearerTokenProvider extends AbstractAzureService {
|
|
5
|
+
protected readonly config: IAzureServiceConfig;
|
|
6
|
+
private readonly scope;
|
|
7
|
+
constructor(config: IAzureServiceConfig, scope: string);
|
|
8
|
+
getToken: () => Promise<AccessToken>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AzureBearerTokenProvider = void 0;
|
|
4
|
+
const errors_1 = require("@golemio/errors");
|
|
5
|
+
const AbstractAzureService_1 = require("./AbstractAzureService");
|
|
6
|
+
class AzureBearerTokenProvider extends AbstractAzureService_1.AbstractAzureService {
|
|
7
|
+
constructor(config, scope) {
|
|
8
|
+
super();
|
|
9
|
+
this.config = config;
|
|
10
|
+
this.scope = scope;
|
|
11
|
+
this.getToken = async () => {
|
|
12
|
+
try {
|
|
13
|
+
const credential = this.getCredential();
|
|
14
|
+
const accessToken = await credential.getToken(this.scope);
|
|
15
|
+
if (!accessToken) {
|
|
16
|
+
throw new errors_1.RecoverableError(`We received an empty access token (null) for ${this.scope}`, this.constructor.name);
|
|
17
|
+
}
|
|
18
|
+
return accessToken;
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
throw new errors_1.RecoverableError(`Failed to acquire Azure AD token for scope ${this.scope}: ${error instanceof Error ? error.message : String(error)}`, this.constructor.name, error instanceof Error ? error : new Error(String(error)));
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.AzureBearerTokenProvider = AzureBearerTokenProvider;
|
|
27
|
+
//# sourceMappingURL=AzureBearerTokenProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AzureBearerTokenProvider.js","sourceRoot":"","sources":["../../../../src/helpers/data-access/azure/AzureBearerTokenProvider.ts"],"names":[],"mappings":";;;AAAA,4CAAmD;AAEnD,iEAA8D;AAG9D,MAAa,wBAAyB,SAAQ,2CAAoB;IAC9D,YAA+B,MAA2B,EAAmB,KAAa;QACtF,KAAK,EAAE,CAAC;QADmB,WAAM,GAAN,MAAM,CAAqB;QAAmB,UAAK,GAAL,KAAK,CAAQ;QAInF,aAAQ,GAAG,KAAK,IAA0B,EAAE;YAC/C,IAAI;gBACA,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;gBACxC,MAAM,WAAW,GAAuB,MAAM,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC9E,IAAI,CAAC,WAAW,EAAE;oBACd,MAAM,IAAI,yBAAgB,CAAC,gDAAgD,IAAI,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;iBACnH;gBACD,OAAO,WAAW,CAAC;aACtB;YAAC,OAAO,KAAK,EAAE;gBACZ,MAAM,IAAI,yBAAgB,CACtB,8CAA8C,IAAI,CAAC,KAAK,KACpD,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CACzD,EAAE,EACF,IAAI,CAAC,WAAW,CAAC,IAAI,EACrB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAC5D,CAAC;aACL;QACL,CAAC,CAAC;IAnBF,CAAC;CAoBJ;AAvBD,4DAuBC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ISimpleConfig } from "../../configuration/ISimpleConfig";
|
|
2
|
+
import { ILogger } from "../../logger";
|
|
3
|
+
import type { AccessToken } from "@azure/core-auth";
|
|
4
|
+
export interface IBearerTokenProviderOptions {
|
|
5
|
+
scopeEnvVar: string;
|
|
6
|
+
logLabel?: string;
|
|
7
|
+
tokenFileEnvVar?: string;
|
|
8
|
+
clientIdEnvVar?: string;
|
|
9
|
+
tenantIdEnvVar?: string;
|
|
10
|
+
clientSecretEnvVar?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare const buildBearerTokenProvider: (config: ISimpleConfig, logger: ILogger, options: IBearerTokenProviderOptions) => (() => Promise<AccessToken>) | undefined;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildBearerTokenProvider = void 0;
|
|
4
|
+
const AzureBearerTokenProvider_1 = require("./AzureBearerTokenProvider");
|
|
5
|
+
const DEFAULT_ENV_VARS = {
|
|
6
|
+
TOKEN_FILE: "AZURE_FEDERATED_TOKEN_FILE",
|
|
7
|
+
CLIENT_ID: "AZURE_CLIENT_ID",
|
|
8
|
+
TENANT_ID: "AZURE_TENANT_ID",
|
|
9
|
+
CLIENT_SECRET: "AZURE_CLIENT_SECRET",
|
|
10
|
+
};
|
|
11
|
+
const buildBearerTokenProvider = (config, logger, options) => {
|
|
12
|
+
const env = (key) => config.getValue(`env.${key}`, null);
|
|
13
|
+
const tokenFile = env(options.tokenFileEnvVar ?? DEFAULT_ENV_VARS.TOKEN_FILE);
|
|
14
|
+
const clientId = env(options.clientIdEnvVar ?? DEFAULT_ENV_VARS.CLIENT_ID);
|
|
15
|
+
const tenantId = env(options.tenantIdEnvVar ?? DEFAULT_ENV_VARS.TENANT_ID);
|
|
16
|
+
const clientSecret = env(options.clientSecretEnvVar ?? DEFAULT_ENV_VARS.CLIENT_SECRET);
|
|
17
|
+
// What app I need access to - opensearch
|
|
18
|
+
const scope = env(options.scopeEnvVar);
|
|
19
|
+
const label = options.logLabel ?? "Bearer";
|
|
20
|
+
const hasIdentity = Boolean(tenantId && clientId && scope);
|
|
21
|
+
const hasCredentialSource = Boolean(tokenFile || clientSecret);
|
|
22
|
+
if (!hasIdentity || !hasCredentialSource) {
|
|
23
|
+
logger.info(`${label} auth: anonymous (no Azure credentials configured)`);
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
const provider = new AzureBearerTokenProvider_1.AzureBearerTokenProvider({ clientId, tenantId, clientSecret, azureFederatedTokenFile: tokenFile }, scope);
|
|
27
|
+
return () => provider.getToken();
|
|
28
|
+
};
|
|
29
|
+
exports.buildBearerTokenProvider = buildBearerTokenProvider;
|
|
30
|
+
//# sourceMappingURL=buildBearerTokenProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildBearerTokenProvider.js","sourceRoot":"","sources":["../../../../src/helpers/data-access/azure/buildBearerTokenProvider.ts"],"names":[],"mappings":";;;AAGA,yEAAsE;AAEtE,MAAM,gBAAgB,GAAG;IACrB,UAAU,EAAE,4BAA4B;IACxC,SAAS,EAAE,iBAAiB;IAC5B,SAAS,EAAE,iBAAiB;IAC5B,aAAa,EAAE,qBAAqB;CAC9B,CAAC;AAWJ,MAAM,wBAAwB,GAAG,CACpC,MAAqB,EACrB,MAAe,EACf,OAAoC,EACI,EAAE;IAC1C,MAAM,GAAG,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAgB,OAAO,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;IAEhF,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,eAAe,IAAI,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAC9E,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,cAAc,IAAI,gBAAgB,CAAC,SAAS,CAAC,CAAC;IAC3E,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,cAAc,IAAI,gBAAgB,CAAC,SAAS,CAAC,CAAC;IAC3E,MAAM,YAAY,GAAG,GAAG,CAAC,OAAO,CAAC,kBAAkB,IAAI,gBAAgB,CAAC,aAAa,CAAC,CAAC;IACvF,yCAAyC;IACzC,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,IAAI,QAAQ,CAAC;IAE3C,MAAM,WAAW,GAAG,OAAO,CAAC,QAAQ,IAAI,QAAQ,IAAI,KAAK,CAAC,CAAC;IAC3D,MAAM,mBAAmB,GAAG,OAAO,CAAC,SAAS,IAAI,YAAY,CAAC,CAAC;IAE/D,IAAI,CAAC,WAAW,IAAI,CAAC,mBAAmB,EAAE;QACtC,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,oDAAoD,CAAC,CAAC;QAC1E,OAAO,SAAS,CAAC;KACpB;IAED,MAAM,QAAQ,GAAG,IAAI,mDAAwB,CACzC,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,uBAAuB,EAAE,SAAS,EAAE,EACxE,KAAe,CAClB,CAAC;IACF,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;AACrC,CAAC,CAAC;AA5BW,QAAA,wBAAwB,4BA4BnC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { buildBearerTokenProvider } from "./buildBearerTokenProvider";
|
|
2
|
+
export type { IBearerTokenProviderOptions } from "./buildBearerTokenProvider";
|
|
3
|
+
export { AzureBearerTokenProvider } from "./AzureBearerTokenProvider";
|
|
4
|
+
export { AbstractAzureService } from "./AbstractAzureService";
|
|
5
|
+
export type { IAzureServiceConfig } from "./IAzureServiceConfig";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AbstractAzureService = exports.AzureBearerTokenProvider = exports.buildBearerTokenProvider = void 0;
|
|
4
|
+
var buildBearerTokenProvider_1 = require("./buildBearerTokenProvider");
|
|
5
|
+
Object.defineProperty(exports, "buildBearerTokenProvider", { enumerable: true, get: function () { return buildBearerTokenProvider_1.buildBearerTokenProvider; } });
|
|
6
|
+
var AzureBearerTokenProvider_1 = require("./AzureBearerTokenProvider");
|
|
7
|
+
Object.defineProperty(exports, "AzureBearerTokenProvider", { enumerable: true, get: function () { return AzureBearerTokenProvider_1.AzureBearerTokenProvider; } });
|
|
8
|
+
var AbstractAzureService_1 = require("./AbstractAzureService");
|
|
9
|
+
Object.defineProperty(exports, "AbstractAzureService", { enumerable: true, get: function () { return AbstractAzureService_1.AbstractAzureService; } });
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/helpers/data-access/azure/index.ts"],"names":[],"mappings":";;;AAAA,uEAAsE;AAA7D,oIAAA,wBAAwB,OAAA;AAEjC,uEAAsE;AAA7D,oIAAA,wBAAwB,OAAA;AACjC,+DAA8D;AAArD,4HAAA,oBAAoB,OAAA"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Client } from "@opensearch-project/opensearch";
|
|
2
|
+
import { Disposable } from "tsyringe";
|
|
3
|
+
export interface IOpenSearchConnector extends Disposable {
|
|
4
|
+
connect(): Promise<Client>;
|
|
5
|
+
getConnection(): Client;
|
|
6
|
+
isConnected(): Promise<boolean>;
|
|
7
|
+
disconnect(): Promise<void>;
|
|
8
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IOpenSearchConnector.js","sourceRoot":"","sources":["../../../../src/helpers/data-access/opensearch/IOpenSearchConnector.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IOpenSearchInfo.js","sourceRoot":"","sources":["../../../../src/helpers/data-access/opensearch/IOpenSearchInfo.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ISyncableIndex.js","sourceRoot":"","sources":["../../../../src/helpers/data-access/opensearch/ISyncableIndex.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ILogger } from "../../logger";
|
|
2
|
+
import { Client, ClientOptions } from "@opensearch-project/opensearch";
|
|
3
|
+
import { IOpenSearchConnector } from "./IOpenSearchConnector";
|
|
4
|
+
import { IOpenSearchInfo } from "./IOpenSearchInfo";
|
|
5
|
+
export declare class OpenSearchConnector implements IOpenSearchConnector {
|
|
6
|
+
private readonly openSearchInfo;
|
|
7
|
+
private readonly log;
|
|
8
|
+
private readonly clientOptions?;
|
|
9
|
+
private static readonly REFRESH_SAFETY_MARGIN_MS;
|
|
10
|
+
private connection?;
|
|
11
|
+
private tokenExpiresAt?;
|
|
12
|
+
constructor(openSearchInfo: IOpenSearchInfo, log: ILogger, clientOptions?: ClientOptions | undefined);
|
|
13
|
+
connect: (additionalOptions?: ClientOptions) => Promise<Client>;
|
|
14
|
+
getConnection: () => Client;
|
|
15
|
+
isConnected: () => Promise<boolean>;
|
|
16
|
+
disconnect: () => Promise<void>;
|
|
17
|
+
dispose: () => Promise<void>;
|
|
18
|
+
private getOptions;
|
|
19
|
+
private clearConnection;
|
|
20
|
+
private isTokenStale;
|
|
21
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OpenSearchConnector = void 0;
|
|
4
|
+
const opensearch_1 = require("@opensearch-project/opensearch");
|
|
5
|
+
const errors_1 = require("@golemio/errors");
|
|
6
|
+
class OpenSearchConnector {
|
|
7
|
+
constructor(openSearchInfo, log, clientOptions) {
|
|
8
|
+
this.openSearchInfo = openSearchInfo;
|
|
9
|
+
this.log = log;
|
|
10
|
+
this.clientOptions = clientOptions;
|
|
11
|
+
this.connect = async (additionalOptions) => {
|
|
12
|
+
if (!this.openSearchInfo.url) {
|
|
13
|
+
throw new errors_1.RecoverableError("The OpenSearch URL cannot be undefined.", this.constructor.name);
|
|
14
|
+
}
|
|
15
|
+
if (this.connection && !this.isTokenStale()) {
|
|
16
|
+
return this.connection;
|
|
17
|
+
}
|
|
18
|
+
if (this.connection && this.isTokenStale()) {
|
|
19
|
+
this.log.info("OpenSearch connection recreated due to stale Bearer token");
|
|
20
|
+
await this.disconnect();
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
const options = await this.getOptions(additionalOptions);
|
|
24
|
+
this.connection = new opensearch_1.Client(options);
|
|
25
|
+
await this.connection.ping();
|
|
26
|
+
this.log.info("Connected to OpenSearch!");
|
|
27
|
+
return this.connection;
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
if (this.connection) {
|
|
31
|
+
try {
|
|
32
|
+
await this.connection.close();
|
|
33
|
+
}
|
|
34
|
+
catch (closeErr) {
|
|
35
|
+
this.log.warn(`Failed to close OpenSearch connection during error cleanup: ${closeErr.message}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
this.clearConnection();
|
|
39
|
+
throw new errors_1.RecoverableError("Error while connecting to OpenSearch.", this.constructor.name, err);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
this.getConnection = () => {
|
|
43
|
+
if (!this.connection) {
|
|
44
|
+
throw new errors_1.RecoverableError("OpenSearch connection does not exist. First call connect() method.", this.constructor.name);
|
|
45
|
+
}
|
|
46
|
+
return this.connection;
|
|
47
|
+
};
|
|
48
|
+
this.isConnected = async () => {
|
|
49
|
+
if (!this.connection) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
await this.connection.ping();
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
this.log.info(`Unable to test connection to OpenSearch due to: "${err.message}".`);
|
|
58
|
+
try {
|
|
59
|
+
await this.connection.close();
|
|
60
|
+
}
|
|
61
|
+
catch (closeErr) {
|
|
62
|
+
this.log.warn(`Failed to close OpenSearch connection during cleanup: ${closeErr.message}`);
|
|
63
|
+
}
|
|
64
|
+
this.clearConnection();
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
this.disconnect = async () => {
|
|
69
|
+
this.log.info("OpenSearch disconnect called");
|
|
70
|
+
if (this.connection) {
|
|
71
|
+
await this.connection.close();
|
|
72
|
+
this.clearConnection();
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
this.dispose = async () => {
|
|
76
|
+
await this.disconnect();
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
async getOptions(additionalOptions) {
|
|
80
|
+
const { url, rejectUnauthorized, getBearerToken } = this.openSearchInfo;
|
|
81
|
+
const merged = {
|
|
82
|
+
node: url,
|
|
83
|
+
maxRetries: 3,
|
|
84
|
+
ssl: { rejectUnauthorized: rejectUnauthorized ?? true },
|
|
85
|
+
...this.clientOptions,
|
|
86
|
+
...additionalOptions,
|
|
87
|
+
};
|
|
88
|
+
if (getBearerToken) {
|
|
89
|
+
const accessToken = await getBearerToken();
|
|
90
|
+
merged.headers = {
|
|
91
|
+
...merged.headers,
|
|
92
|
+
Authorization: `Bearer ${accessToken.token}`,
|
|
93
|
+
};
|
|
94
|
+
this.tokenExpiresAt =
|
|
95
|
+
accessToken.refreshAfterTimestamp ??
|
|
96
|
+
accessToken.expiresOnTimestamp - OpenSearchConnector.REFRESH_SAFETY_MARGIN_MS;
|
|
97
|
+
}
|
|
98
|
+
return merged;
|
|
99
|
+
}
|
|
100
|
+
clearConnection() {
|
|
101
|
+
this.connection = undefined;
|
|
102
|
+
this.tokenExpiresAt = undefined;
|
|
103
|
+
}
|
|
104
|
+
isTokenStale() {
|
|
105
|
+
if (this.tokenExpiresAt === undefined) {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
return Date.now() >= this.tokenExpiresAt;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
exports.OpenSearchConnector = OpenSearchConnector;
|
|
112
|
+
OpenSearchConnector.REFRESH_SAFETY_MARGIN_MS = 5 * 60 * 1000;
|
|
113
|
+
//# sourceMappingURL=OpenSearchConnector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OpenSearchConnector.js","sourceRoot":"","sources":["../../../../src/helpers/data-access/opensearch/OpenSearchConnector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ILogger } from "../../logger";
|
|
2
|
+
import { IOpenSearchConnector } from "./IOpenSearchConnector";
|
|
3
|
+
import { ISyncableDoc } from "./ISyncableIndex";
|
|
4
|
+
export type IndexCount = number | "not_initialized";
|
|
5
|
+
export type HealthStatus = "ok" | "unreachable" | "disabled";
|
|
6
|
+
export interface IOpenSearchServiceConfig {
|
|
7
|
+
namespace: string;
|
|
8
|
+
enabled: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare class OpenSearchService {
|
|
11
|
+
private readonly connector;
|
|
12
|
+
private readonly logger;
|
|
13
|
+
readonly namespace: string;
|
|
14
|
+
readonly enabled: boolean;
|
|
15
|
+
constructor(connector: IOpenSearchConnector, logger: ILogger, config: IOpenSearchServiceConfig);
|
|
16
|
+
healthCheck(): Promise<HealthStatus>;
|
|
17
|
+
createIndex(baseName: string, mapping: Record<string, unknown>): Promise<"created" | "exists">;
|
|
18
|
+
indexDoc(baseName: string, document: ISyncableDoc): Promise<void>;
|
|
19
|
+
deleteDoc(baseName: string, id: string): Promise<void>;
|
|
20
|
+
bulkIndex(baseName: string, documents: ISyncableDoc[]): Promise<void>;
|
|
21
|
+
retainOnly(baseName: string, keepIds: Set<string>): Promise<IndexCount>;
|
|
22
|
+
count(baseName: string): Promise<IndexCount>;
|
|
23
|
+
private indexName;
|
|
24
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OpenSearchService = void 0;
|
|
4
|
+
const errors_1 = require("@golemio/errors");
|
|
5
|
+
const opensearch_1 = require("@opensearch-project/opensearch");
|
|
6
|
+
class OpenSearchService {
|
|
7
|
+
constructor(connector, logger, config) {
|
|
8
|
+
this.connector = connector;
|
|
9
|
+
this.logger = logger;
|
|
10
|
+
this.enabled = config.enabled;
|
|
11
|
+
this.namespace = config.namespace;
|
|
12
|
+
if (this.enabled && !this.namespace) {
|
|
13
|
+
throw new errors_1.GeneralError("OpenSearchService: namespace is required when enabled=true. Set OPENSEARCH_NAMESPACE env var.", this.constructor.name, undefined, 500);
|
|
14
|
+
}
|
|
15
|
+
if (this.enabled) {
|
|
16
|
+
this.logger.info(`OpenSearchService initialized (namespace=${this.namespace})`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
async healthCheck() {
|
|
20
|
+
if (!this.enabled)
|
|
21
|
+
return "disabled";
|
|
22
|
+
try {
|
|
23
|
+
const client = await this.connector.connect();
|
|
24
|
+
await client.ping();
|
|
25
|
+
return "ok";
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
this.logger.warn("OpenSearchService healthCheck failed", error);
|
|
29
|
+
return "unreachable";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async createIndex(baseName, mapping) {
|
|
33
|
+
const index = this.indexName(baseName);
|
|
34
|
+
try {
|
|
35
|
+
const client = await this.connector.connect();
|
|
36
|
+
await client.indices.create({ index, body: mapping });
|
|
37
|
+
this.logger.info(`OpenSearchService index ${index} created`);
|
|
38
|
+
return "created";
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
if (error instanceof opensearch_1.errors.ResponseError &&
|
|
42
|
+
error.body?.error?.type === "resource_already_exists_exception") {
|
|
43
|
+
return "exists";
|
|
44
|
+
}
|
|
45
|
+
throw new errors_1.RecoverableError(`Failed to create index ${index}`, this.constructor.name, error, 500);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async indexDoc(baseName, document) {
|
|
49
|
+
const index = this.indexName(baseName);
|
|
50
|
+
const { id, ...body } = document;
|
|
51
|
+
try {
|
|
52
|
+
const client = await this.connector.connect();
|
|
53
|
+
await client.index({ index, id, body });
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
throw new errors_1.RecoverableError(`Failed to index doc ${id} into ${index}`, this.constructor.name, error, 500);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
async deleteDoc(baseName, id) {
|
|
60
|
+
const index = this.indexName(baseName);
|
|
61
|
+
try {
|
|
62
|
+
const client = await this.connector.connect();
|
|
63
|
+
await client.delete({ index, id }, { ignore: [404] });
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
throw new errors_1.RecoverableError(`Failed to delete doc ${id} from ${index}`, this.constructor.name, error, 500);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async bulkIndex(baseName, documents) {
|
|
70
|
+
if (documents.length === 0)
|
|
71
|
+
return;
|
|
72
|
+
const index = this.indexName(baseName);
|
|
73
|
+
try {
|
|
74
|
+
const client = await this.connector.connect();
|
|
75
|
+
const dropsByReason = new Map();
|
|
76
|
+
const stats = await client.helpers.bulk({
|
|
77
|
+
datasource: documents,
|
|
78
|
+
onDocument: (doc) => {
|
|
79
|
+
const { id, ...body } = doc;
|
|
80
|
+
return [{ index: { _index: index, _id: String(id) } }, body];
|
|
81
|
+
},
|
|
82
|
+
onDrop: (dropped) => {
|
|
83
|
+
const reason = dropped.error?.reason ?? dropped.error?.type ?? "unknown";
|
|
84
|
+
const existing = dropsByReason.get(reason);
|
|
85
|
+
if (existing) {
|
|
86
|
+
existing.count++;
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
dropsByReason.set(reason, {
|
|
90
|
+
count: 1,
|
|
91
|
+
status: dropped.status,
|
|
92
|
+
sampleId: String(dropped.document?.id),
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
if (stats.failed > 0) {
|
|
98
|
+
this.logger.warn({
|
|
99
|
+
index,
|
|
100
|
+
failed: stats.failed,
|
|
101
|
+
retried: stats.retry,
|
|
102
|
+
timeMs: stats.time,
|
|
103
|
+
reasons: Array.from(dropsByReason.entries()).map(([reason, info]) => ({ reason, ...info })),
|
|
104
|
+
}, `OpenSearchService bulk save had ${stats.failed} failed items in ${index} ` +
|
|
105
|
+
`(${stats.retry} retried, ${stats.time}ms)`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
throw new errors_1.RecoverableError(`Failed to bulk index ${index}`, this.constructor.name, error, 500);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
async retainOnly(baseName, keepIds) {
|
|
113
|
+
if (keepIds.size === 0) {
|
|
114
|
+
this.logger.warn(`OpenSearchService retainOnly called with empty keepIds for ${baseName}, ` + "skipping to prevent full index wipe");
|
|
115
|
+
return 0;
|
|
116
|
+
}
|
|
117
|
+
const index = this.indexName(baseName);
|
|
118
|
+
const idsToKeep = Array.from(keepIds);
|
|
119
|
+
try {
|
|
120
|
+
const client = await this.connector.connect();
|
|
121
|
+
const response = await client.deleteByQuery({
|
|
122
|
+
index,
|
|
123
|
+
body: {
|
|
124
|
+
query: {
|
|
125
|
+
bool: {
|
|
126
|
+
must_not: [{ ids: { values: idsToKeep } }],
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
}, { ignore: [404] });
|
|
131
|
+
if (response.statusCode === 404)
|
|
132
|
+
return "not_initialized";
|
|
133
|
+
const responseBody = response.body;
|
|
134
|
+
const deletedCount = responseBody.deleted ?? 0;
|
|
135
|
+
if (deletedCount > 0) {
|
|
136
|
+
this.logger.info(`OpenSearchService deleted ${deletedCount} orphans from ${index}`);
|
|
137
|
+
}
|
|
138
|
+
return deletedCount;
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
throw new errors_1.RecoverableError(`Failed to prune ${index}`, this.constructor.name, error, 500);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
async count(baseName) {
|
|
145
|
+
const index = this.indexName(baseName);
|
|
146
|
+
try {
|
|
147
|
+
const client = await this.connector.connect();
|
|
148
|
+
const response = await client.count({ index }, { ignore: [404] });
|
|
149
|
+
if (response.statusCode === 404)
|
|
150
|
+
return "not_initialized";
|
|
151
|
+
return response.body.count;
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
throw new errors_1.RecoverableError(`Failed to count ${index}`, this.constructor.name, error, 500);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
indexName(baseName) {
|
|
158
|
+
return `${this.namespace}_${baseName}`;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
exports.OpenSearchService = OpenSearchService;
|
|
162
|
+
//# sourceMappingURL=OpenSearchService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OpenSearchService.js","sourceRoot":"","sources":["../../../../src/helpers/data-access/opensearch/OpenSearchService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ILogger } from "../../logger";
|
|
2
|
+
import { OpenSearchService } from "./OpenSearchService";
|
|
3
|
+
import { ISyncableIndex } from "./ISyncableIndex";
|
|
4
|
+
export declare class OpenSearchSyncOrchestrator {
|
|
5
|
+
private readonly openSearchService;
|
|
6
|
+
private readonly syncableIndexes;
|
|
7
|
+
private readonly logger;
|
|
8
|
+
private isRunning;
|
|
9
|
+
constructor(openSearchService: OpenSearchService, syncableIndexes: ISyncableIndex[], logger: ILogger);
|
|
10
|
+
execute: () => Promise<void>;
|
|
11
|
+
initIndexes(): Promise<void>;
|
|
12
|
+
private syncIndex;
|
|
13
|
+
private extractIdsToKeep;
|
|
14
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OpenSearchSyncOrchestrator = void 0;
|
|
4
|
+
const errors_1 = require("@golemio/errors");
|
|
5
|
+
class OpenSearchSyncOrchestrator {
|
|
6
|
+
constructor(openSearchService, syncableIndexes, logger) {
|
|
7
|
+
this.openSearchService = openSearchService;
|
|
8
|
+
this.syncableIndexes = syncableIndexes;
|
|
9
|
+
this.logger = logger;
|
|
10
|
+
this.isRunning = false;
|
|
11
|
+
this.execute = async () => {
|
|
12
|
+
if (!this.openSearchService.enabled) {
|
|
13
|
+
this.logger.warn("OpenSearchSyncOrchestrator skipped, OpenSearch sync is disabled");
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (this.isRunning) {
|
|
17
|
+
this.logger.warn("OpenSearchSyncOrchestrator previous run still in progress, skipping");
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
this.isRunning = true;
|
|
21
|
+
this.logger.debug("OpenSearchSyncOrchestrator executed");
|
|
22
|
+
const startTime = Date.now();
|
|
23
|
+
try {
|
|
24
|
+
for (const syncableIndex of this.syncableIndexes) {
|
|
25
|
+
await this.syncIndex(syncableIndex);
|
|
26
|
+
}
|
|
27
|
+
this.logger.info(`OpenSearchSyncOrchestrator completed in ${Date.now() - startTime}ms`);
|
|
28
|
+
}
|
|
29
|
+
finally {
|
|
30
|
+
this.isRunning = false;
|
|
31
|
+
this.logger.debug("OpenSearchSyncOrchestrator done");
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
async initIndexes() {
|
|
36
|
+
if (!this.openSearchService.enabled)
|
|
37
|
+
return;
|
|
38
|
+
const failed = [];
|
|
39
|
+
for (const syncableIndex of this.syncableIndexes) {
|
|
40
|
+
try {
|
|
41
|
+
await this.openSearchService.createIndex(syncableIndex.baseName, syncableIndex.mapping);
|
|
42
|
+
const count = await this.openSearchService.count(syncableIndex.baseName);
|
|
43
|
+
if (count === 0 || count === "not_initialized") {
|
|
44
|
+
this.logger.info(`OpenSearchSyncOrchestrator ${syncableIndex.baseName} is empty (count=${count}), seeding from source`);
|
|
45
|
+
await this.syncIndex(syncableIndex);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
const wrappedError = new errors_1.RecoverableError(`initIndexes(${syncableIndex.baseName}) failed`, this.constructor.name, error);
|
|
50
|
+
this.logger.error(wrappedError.message, wrappedError);
|
|
51
|
+
failed.push(syncableIndex.baseName);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (failed.length > 0) {
|
|
55
|
+
throw new errors_1.RecoverableError(`Failed to initialize OpenSearch indexes: ${failed.join(", ")}`, this.constructor.name);
|
|
56
|
+
}
|
|
57
|
+
this.logger.info("OpenSearchSyncOrchestrator indexes initialized");
|
|
58
|
+
}
|
|
59
|
+
async syncIndex(syncableIndex) {
|
|
60
|
+
const startTime = Date.now();
|
|
61
|
+
try {
|
|
62
|
+
const documents = await syncableIndex.fetchAll();
|
|
63
|
+
await this.openSearchService.bulkIndex(syncableIndex.baseName, documents);
|
|
64
|
+
await this.openSearchService.retainOnly(syncableIndex.baseName, this.extractIdsToKeep(documents));
|
|
65
|
+
this.logger.info(`OpenSearchSyncOrchestrator synced ${syncableIndex.baseName} = ${documents.length} docs ` +
|
|
66
|
+
`in ${Date.now() - startTime}ms`);
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
this.logger.error(`OpenSearchSyncOrchestrator syncIndex(${syncableIndex.baseName}) was not successful ` +
|
|
70
|
+
(error instanceof Error ? error.message : String(error)), error);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
extractIdsToKeep(documents) {
|
|
74
|
+
return new Set(documents.map((document) => document.id));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.OpenSearchSyncOrchestrator = OpenSearchSyncOrchestrator;
|
|
78
|
+
//# sourceMappingURL=OpenSearchSyncOrchestrator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OpenSearchSyncOrchestrator.js","sourceRoot":"","sources":["../../../../src/helpers/data-access/opensearch/OpenSearchSyncOrchestrator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Types } from "@opensearch-project/opensearch";
|
|
2
|
+
export declare const czechAnalysis: {
|
|
3
|
+
analysis: Types.Indices_Common.IndexSettingsAnalysis;
|
|
4
|
+
};
|
|
5
|
+
export declare const defaultIndexSettings: Types.Indices_Common.IndexSettings;
|
|
6
|
+
export declare const czechText: () => Types.Common_Mapping.TextProperty;
|