@toxplanet/pegasus-sdk 1.1.4 → 1.1.6

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.
@@ -1,11 +1,11 @@
1
1
  module.exports = {
2
2
  environment: 'acc',
3
3
  region: 'us-east-1',
4
- secretName: 'arn:aws:secretsmanager:us-east-1:292931567094:secret:rds!cluster-b851c3ce-58cc-41cd-aeae-05cc7f5e031a-ZYSjiI',
5
- openSearchEndpoint: 'https://war8lk73nzswquk8dcz1.us-east-1.aoss.amazonaws.com',
4
+ secretName: 'arn:aws:secretsmanager:us-east-1:605134466764:secret:rds!cluster-9b502dde-5e2a-49db-b2c5-9801141ee40b-gkHbLm',
5
+ openSearchEndpoint: 'https://1pbu0yqr197lq07hfcjh.us-east-1.aoss.amazonaws.com',
6
6
  openSearchIndex: 'chemicals',
7
7
  database: {
8
- host: 'cr-chemicals.cluster-cz0iqdg8irhb.us-east-1.rds.amazonaws.com',
8
+ host: 'cr-chemicals-acc.cluster-czgc4c20yerz.us-east-1.rds.amazonaws.com',
9
9
  name: 'chemicals'
10
10
  },
11
11
  postgres: {
@@ -20,7 +20,7 @@ module.exports = {
20
20
  }
21
21
  },
22
22
  indexRoutes: {
23
- chemicals: ['chemicals*'],
23
+ chemicals: ['*'],
24
24
  documents: ['documents*'],
25
25
  search: [/^(chemicals|substances|search)/]
26
26
  }
@@ -20,7 +20,7 @@ module.exports = {
20
20
  }
21
21
  },
22
22
  indexRoutes: {
23
- chemicals: ['chemical_index*'],
23
+ chemicals: ['chemical_index*', 'synonym_lookup_index'],
24
24
  documents: ['document_nones_index*'],
25
25
  search: [/^(chemical_index|document_nones_index|search)/]
26
26
  }
@@ -1,11 +1,11 @@
1
1
  module.exports = {
2
2
  environment: 'prod',
3
3
  region: 'us-east-1',
4
- secretName: 'pegasus/production/database',
5
- openSearchEndpoint: null,
4
+ secretName: 'rds!cluster-25483b3f-3758-43ed-9548-26c91de16c2d',
5
+ openSearchEndpoint: 'https://odusb11s00j5hyy5r6.us-east-1.aoss.amazonaws.com',
6
6
  openSearchIndex: 'chemicals',
7
7
  database: {
8
- host: null,
8
+ host: 'cr-chemicals-qa.cluster-c7gakqksq9m4.us-east-1.rds.amazonaws.com',
9
9
  name: 'chemicals'
10
10
  },
11
11
  postgres: {
@@ -1,11 +1,11 @@
1
1
  module.exports = {
2
2
  environment: 'qa',
3
3
  region: 'us-east-1',
4
- secretName: 'pegasus/qa/database',
5
- openSearchEndpoint: null,
4
+ secretName: 'arn:aws:secretsmanager:us-east-1:147997144422:secret:rds!cluster-25483b3f-3758-43ed-9548-26c91de16c2d-oYjysU',
5
+ openSearchEndpoint: 'https://odusb11s00j5hyy5r6.us-east-1.aoss.amazonaws.com',
6
6
  openSearchIndex: 'chemicals',
7
7
  database: {
8
- host: null,
8
+ host: 'cr-chemicals-qa.cluster-c7gakqksq9m4.us-east-1.rds.amazonaws.com',
9
9
  name: 'chemicals'
10
10
  },
11
11
  postgres: {
@@ -20,7 +20,7 @@ module.exports = {
20
20
  }
21
21
  },
22
22
  indexRoutes: {
23
- chemicals: ['chemicals*'],
23
+ chemicals: ['*'],
24
24
  documents: ['documents*'],
25
25
  search: [/^(chemicals|substances|search)/]
26
26
  }
package/index.js CHANGED
@@ -1,44 +1,44 @@
1
- const PegasusConnection = require('./lib/connection');
2
- const ChemicalsService = require('./lib/chemicals');
3
- const DocumentsService = require('./lib/documents');
4
- const SearchService = require('./lib/search');
5
- const SyncService = require('./lib/sync');
6
- const UtilsService = require('./lib/utils');
7
- const ElasticsearchService = require('./lib/elasticsearch');
8
-
9
- class PegasusSDK {
10
- constructor(config) {
11
- this.connection = new PegasusConnection(config);
12
- this.elasticsearch = new ElasticsearchService(this.connection);
13
- this.chemicals = new ChemicalsService(this.connection);
14
- this.documents = new DocumentsService(this.connection);
15
- this.search = new SearchService(this.connection);
16
- this.sync = new SyncService(this.connection);
17
- this.utils = new UtilsService(this.connection);
18
-
19
- this.chemicals.registerElasticsearchHandlers(this.elasticsearch);
20
- this.documents.registerElasticsearchHandlers(this.elasticsearch);
21
- this.search.registerElasticsearchHandlers(this.elasticsearch);
22
- }
23
-
24
- async connect() {
25
- return this.connection.connect();
26
- }
27
-
28
- async disconnect() {
29
- return this.connection.disconnect();
30
- }
31
-
32
- async healthCheck() {
33
- return this.connection.testConnection();
34
- }
35
- }
36
-
37
- module.exports = PegasusSDK;
38
- module.exports.PegasusConnection = PegasusConnection;
39
- module.exports.ChemicalsService = ChemicalsService;
40
- module.exports.DocumentsService = DocumentsService;
41
- module.exports.SearchService = SearchService;
42
- module.exports.SyncService = SyncService;
43
- module.exports.UtilsService = UtilsService;
1
+ const PegasusConnection = require('./lib/connection');
2
+ const ChemicalsService = require('./lib/chemicals');
3
+ const DocumentsService = require('./lib/documents');
4
+ const SearchService = require('./lib/search');
5
+ const SyncService = require('./lib/sync');
6
+ const UtilsService = require('./lib/utils');
7
+ const ElasticsearchService = require('./lib/elasticsearch');
8
+
9
+ class PegasusSDK {
10
+ constructor(config) {
11
+ this.connection = new PegasusConnection(config);
12
+ this.elasticsearch = new ElasticsearchService(this.connection);
13
+ this.chemicals = new ChemicalsService(this.connection);
14
+ this.documents = new DocumentsService(this.connection);
15
+ this.search = new SearchService(this.connection);
16
+ this.sync = new SyncService(this.connection);
17
+ this.utils = new UtilsService(this.connection);
18
+
19
+ this.chemicals.registerElasticsearchHandlers(this.elasticsearch);
20
+ this.documents.registerElasticsearchHandlers(this.elasticsearch);
21
+ this.search.registerElasticsearchHandlers(this.elasticsearch);
22
+ }
23
+
24
+ async connect() {
25
+ return this.connection.connect();
26
+ }
27
+
28
+ async disconnect() {
29
+ return this.connection.disconnect();
30
+ }
31
+
32
+ async healthCheck() {
33
+ return this.connection.testConnection();
34
+ }
35
+ }
36
+
37
+ module.exports = PegasusSDK;
38
+ module.exports.PegasusConnection = PegasusConnection;
39
+ module.exports.ChemicalsService = ChemicalsService;
40
+ module.exports.DocumentsService = DocumentsService;
41
+ module.exports.SearchService = SearchService;
42
+ module.exports.SyncService = SyncService;
43
+ module.exports.UtilsService = UtilsService;
44
44
  module.exports.ElasticsearchService = ElasticsearchService;
package/lib/chemicals.js CHANGED
@@ -692,7 +692,7 @@ class ChemicalsService {
692
692
  items
693
693
  };
694
694
  },
695
-
695
+
696
696
  get: async (params) => {
697
697
  const result = await this.getChemicalById(params.id);
698
698
 
package/lib/connection.js CHANGED
@@ -1,223 +1,223 @@
1
- const { Pool } = require('pg');
2
- const { Client } = require('@opensearch-project/opensearch');
3
- const { SecretsManagerClient, GetSecretValueCommand } = require('@aws-sdk/client-secrets-manager');
4
- const { AwsSigv4Signer } = require('@opensearch-project/opensearch/aws');
5
- const { fromNodeProviderChain } = require('@aws-sdk/credential-providers');
6
- const { loadConfig } = require('../config');
7
- const { logInfo, logError } = require('@toxplanet/tphelper/logging');
8
-
9
- class PegasusConnection {
10
- constructor(config = {}) {
11
- const envConfig = loadConfig(config.environment);
12
-
13
- this.config = { ...envConfig, ...config };
14
- this.environment = this.config.environment;
15
- this.region = this.config.region;
16
- this.secretName = this.config.secretName;
17
- this.openSearchEndpoint = this.config.openSearchEndpoint;
18
- this.openSearchIndex = this.config.openSearchIndex;
19
- this.databaseHost = this.config.database?.host;
20
- this.databaseName = this.config.database?.name;
21
-
22
- this.pgPool = null;
23
- this.osClient = null;
24
- this.secretsClient = null;
25
- this.cachedSecret = null;
26
- this.isConnected = false;
27
- }
28
-
29
- async getSecret() {
30
- if (this.cachedSecret) {
31
- return this.cachedSecret;
32
- }
33
-
34
- if (!this.secretsClient) {
35
- this.secretsClient = new SecretsManagerClient({ region: this.region });
36
- }
37
-
38
- const command = new GetSecretValueCommand({ SecretId: this.secretName });
39
- const response = await this.secretsClient.send(command);
40
-
41
- if (response.SecretString) {
42
- this.cachedSecret = JSON.parse(response.SecretString);
43
- return this.cachedSecret;
44
- }
45
-
46
- throw new Error(`Secret ${this.secretName} does not contain SecretString`);
47
- }
48
-
49
- async connect() {
50
- if (this.isConnected) {
51
- return;
52
- }
53
-
54
- const secret = await this.getSecret();
55
-
56
- const poolConfig = {
57
- host: this.databaseHost,
58
- port: 5432,
59
- database: this.databaseName,
60
- user: secret.username,
61
- password: secret.password,
62
- max: this.config.postgres.maxConnections,
63
- min: this.config.postgres.minConnections,
64
- idleTimeoutMillis: this.config.postgres.idleTimeoutMillis,
65
- connectionTimeoutMillis: this.config.postgres.connectionTimeoutMillis,
66
- allowExitOnIdle: true,
67
- ssl: this.config.postgres.ssl,
68
- statement_timeout: this.config.postgres.statementTimeout,
69
- query_timeout: this.config.postgres.queryTimeout
70
- };
71
-
72
- this.pgPool = new Pool(poolConfig);
73
-
74
- this.pgPool.on('error', (err) => {
75
- logError('pegasus-sdk', 'PegasusConnection', 'pgPool.error', err);
76
- });
77
-
78
- this.pgPool.on('connect', () => {
79
- logInfo('pegasus-sdk', 'PostgreSQL client connected');
80
- });
81
-
82
- this.pgPool.on('remove', () => {
83
- logInfo('pegasus-sdk', 'PostgreSQL client removed from pool');
84
- });
85
-
86
- if (this.openSearchEndpoint) {
87
- this.osClient = new Client({
88
- ...AwsSigv4Signer({
89
- region: this.region,
90
- service: 'aoss',
91
- getCredentials: () => {
92
- const credentialsProvider = fromNodeProviderChain();
93
- return credentialsProvider();
94
- }
95
- }),
96
- node: this.openSearchEndpoint
97
- });
98
- }
99
-
100
- this.isConnected = true;
101
- }
102
-
103
- async disconnect() {
104
- if (!this.isConnected) {
105
- return;
106
- }
107
-
108
- if (this.pgPool) {
109
- await this.pgPool.end();
110
- this.pgPool = null;
111
- }
112
-
113
- this.osClient = null;
114
- this.isConnected = false;
115
- this.cachedSecret = null;
116
- }
117
-
118
- getPostgresClient() {
119
- if (!this.pgPool) {
120
- throw new Error('PostgreSQL connection not established. Call connect() first.');
121
- }
122
- return this.pgPool;
123
- }
124
-
125
- getOpenSearchClient() {
126
- if (!this.osClient) {
127
- throw new Error('OpenSearch connection not established. Call connect() first or provide openSearchEndpoint.');
128
- }
129
- return this.osClient;
130
- }
131
-
132
- getOpenSearchIndex() {
133
- return this.openSearchIndex || 'chemicals';
134
- }
135
-
136
- async testConnection() {
137
- try {
138
- if (this.pgPool) {
139
- const client = await this.pgPool.connect();
140
- const result = await client.query('SELECT NOW() as current_time, version() as pg_version');
141
- client.release();
142
-
143
- const pgStatus = {
144
- connected: true,
145
- timestamp: result.rows[0].current_time,
146
- version: result.rows[0].pg_version,
147
- poolSize: this.pgPool.totalCount,
148
- idleConnections: this.pgPool.idleCount,
149
- waitingRequests: this.pgPool.waitingCount
150
- };
151
-
152
- let osStatus = null;
153
- if (this.osClient) {
154
- try {
155
- const indexName = this.getOpenSearchIndex();
156
- const testSearch = await this.osClient.search({
157
- index: indexName,
158
- body: {
159
- size: 1,
160
- query: {
161
- match: { chemical_name: 'benzene' }
162
- }
163
- }
164
- });
165
- osStatus = {
166
- connected: true,
167
- resultsFound: testSearch.body.hits.total.value || 0
168
- };
169
- } catch (osError) {
170
- osStatus = {
171
- connected: false,
172
- error: osError.message
173
- };
174
- }
175
- }
176
-
177
- return {
178
- postgres: pgStatus,
179
- opensearch: osStatus,
180
- environment: this.environment,
181
- region: this.region
182
- };
183
- }
184
-
185
- throw new Error('No active connections');
186
- } catch (error) {
187
- return {
188
- postgres: { connected: false, error: error.message },
189
- opensearch: null,
190
- environment: this.environment,
191
- region: this.region
192
- };
193
- }
194
- }
195
-
196
- async query(sql, params) {
197
- const pool = this.getPostgresClient();
198
- return pool.query(sql, params);
199
- }
200
-
201
- async getClient() {
202
- const pool = this.getPostgresClient();
203
- return pool.connect();
204
- }
205
-
206
- async transaction(callback) {
207
- const client = await this.getClient();
208
-
209
- try {
210
- await client.query('BEGIN');
211
- const result = await callback(client);
212
- await client.query('COMMIT');
213
- return result;
214
- } catch (error) {
215
- await client.query('ROLLBACK');
216
- throw error;
217
- } finally {
218
- client.release();
219
- }
220
- }
221
- }
222
-
223
- module.exports = PegasusConnection;
1
+ const { Pool } = require('pg');
2
+ const { Client } = require('@opensearch-project/opensearch');
3
+ const { SecretsManagerClient, GetSecretValueCommand } = require('@aws-sdk/client-secrets-manager');
4
+ const { AwsSigv4Signer } = require('@opensearch-project/opensearch/aws');
5
+ const { fromNodeProviderChain } = require('@aws-sdk/credential-providers');
6
+ const { loadConfig } = require('../config');
7
+ const { logInfo, logError } = require('@toxplanet/tphelper/logging');
8
+
9
+ class PegasusConnection {
10
+ constructor(config = {}) {
11
+ const envConfig = loadConfig(config.environment);
12
+
13
+ this.config = { ...envConfig, ...config };
14
+ this.environment = this.config.environment;
15
+ this.region = this.config.region;
16
+ this.secretName = this.config.secretName;
17
+ this.openSearchEndpoint = this.config.openSearchEndpoint;
18
+ this.openSearchIndex = this.config.openSearchIndex;
19
+ this.databaseHost = this.config.database?.host;
20
+ this.databaseName = this.config.database?.name;
21
+
22
+ this.pgPool = null;
23
+ this.osClient = null;
24
+ this.secretsClient = null;
25
+ this.cachedSecret = null;
26
+ this.isConnected = false;
27
+ }
28
+
29
+ async getSecret() {
30
+ if (this.cachedSecret) {
31
+ return this.cachedSecret;
32
+ }
33
+
34
+ if (!this.secretsClient) {
35
+ this.secretsClient = new SecretsManagerClient({ region: this.region });
36
+ }
37
+
38
+ const command = new GetSecretValueCommand({ SecretId: this.secretName });
39
+ const response = await this.secretsClient.send(command);
40
+
41
+ if (response.SecretString) {
42
+ this.cachedSecret = JSON.parse(response.SecretString);
43
+ return this.cachedSecret;
44
+ }
45
+
46
+ throw new Error(`Secret ${this.secretName} does not contain SecretString`);
47
+ }
48
+
49
+ async connect() {
50
+ if (this.isConnected) {
51
+ return;
52
+ }
53
+
54
+ const secret = await this.getSecret();
55
+
56
+ const poolConfig = {
57
+ host: this.databaseHost,
58
+ port: 5432,
59
+ database: this.databaseName,
60
+ user: secret.username,
61
+ password: secret.password,
62
+ max: this.config.postgres.maxConnections,
63
+ min: this.config.postgres.minConnections,
64
+ idleTimeoutMillis: this.config.postgres.idleTimeoutMillis,
65
+ connectionTimeoutMillis: this.config.postgres.connectionTimeoutMillis,
66
+ allowExitOnIdle: true,
67
+ ssl: this.config.postgres.ssl,
68
+ statement_timeout: this.config.postgres.statementTimeout,
69
+ query_timeout: this.config.postgres.queryTimeout
70
+ };
71
+
72
+ this.pgPool = new Pool(poolConfig);
73
+
74
+ this.pgPool.on('error', (err) => {
75
+ logError('pegasus-sdk', 'PegasusConnection', 'pgPool.error', err);
76
+ });
77
+
78
+ this.pgPool.on('connect', () => {
79
+ logInfo('pegasus-sdk', 'PostgreSQL client connected');
80
+ });
81
+
82
+ this.pgPool.on('remove', () => {
83
+ logInfo('pegasus-sdk', 'PostgreSQL client removed from pool');
84
+ });
85
+
86
+ if (this.openSearchEndpoint) {
87
+ this.osClient = new Client({
88
+ ...AwsSigv4Signer({
89
+ region: this.region,
90
+ service: 'aoss',
91
+ getCredentials: () => {
92
+ const credentialsProvider = fromNodeProviderChain();
93
+ return credentialsProvider();
94
+ }
95
+ }),
96
+ node: this.openSearchEndpoint
97
+ });
98
+ }
99
+
100
+ this.isConnected = true;
101
+ }
102
+
103
+ async disconnect() {
104
+ if (!this.isConnected) {
105
+ return;
106
+ }
107
+
108
+ if (this.pgPool) {
109
+ await this.pgPool.end();
110
+ this.pgPool = null;
111
+ }
112
+
113
+ this.osClient = null;
114
+ this.isConnected = false;
115
+ this.cachedSecret = null;
116
+ }
117
+
118
+ getPostgresClient() {
119
+ if (!this.pgPool) {
120
+ throw new Error('PostgreSQL connection not established. Call connect() first.');
121
+ }
122
+ return this.pgPool;
123
+ }
124
+
125
+ getOpenSearchClient() {
126
+ if (!this.osClient) {
127
+ throw new Error('OpenSearch connection not established. Call connect() first or provide openSearchEndpoint.');
128
+ }
129
+ return this.osClient;
130
+ }
131
+
132
+ getOpenSearchIndex() {
133
+ return this.openSearchIndex || 'chemicals';
134
+ }
135
+
136
+ async testConnection() {
137
+ try {
138
+ if (this.pgPool) {
139
+ const client = await this.pgPool.connect();
140
+ const result = await client.query('SELECT NOW() as current_time, version() as pg_version');
141
+ client.release();
142
+
143
+ const pgStatus = {
144
+ connected: true,
145
+ timestamp: result.rows[0].current_time,
146
+ version: result.rows[0].pg_version,
147
+ poolSize: this.pgPool.totalCount,
148
+ idleConnections: this.pgPool.idleCount,
149
+ waitingRequests: this.pgPool.waitingCount
150
+ };
151
+
152
+ let osStatus = null;
153
+ if (this.osClient) {
154
+ try {
155
+ const indexName = this.getOpenSearchIndex();
156
+ const testSearch = await this.osClient.search({
157
+ index: indexName,
158
+ body: {
159
+ size: 1,
160
+ query: {
161
+ match: { chemical_name: 'benzene' }
162
+ }
163
+ }
164
+ });
165
+ osStatus = {
166
+ connected: true,
167
+ resultsFound: testSearch.body.hits.total.value || 0
168
+ };
169
+ } catch (osError) {
170
+ osStatus = {
171
+ connected: false,
172
+ error: osError.message
173
+ };
174
+ }
175
+ }
176
+
177
+ return {
178
+ postgres: pgStatus,
179
+ opensearch: osStatus,
180
+ environment: this.environment,
181
+ region: this.region
182
+ };
183
+ }
184
+
185
+ throw new Error('No active connections');
186
+ } catch (error) {
187
+ return {
188
+ postgres: { connected: false, error: error.message },
189
+ opensearch: null,
190
+ environment: this.environment,
191
+ region: this.region
192
+ };
193
+ }
194
+ }
195
+
196
+ async query(sql, params) {
197
+ const pool = this.getPostgresClient();
198
+ return pool.query(sql, params);
199
+ }
200
+
201
+ async getClient() {
202
+ const pool = this.getPostgresClient();
203
+ return pool.connect();
204
+ }
205
+
206
+ async transaction(callback) {
207
+ const client = await this.getClient();
208
+
209
+ try {
210
+ await client.query('BEGIN');
211
+ const result = await callback(client);
212
+ await client.query('COMMIT');
213
+ return result;
214
+ } catch (error) {
215
+ await client.query('ROLLBACK');
216
+ throw error;
217
+ } finally {
218
+ client.release();
219
+ }
220
+ }
221
+ }
222
+
223
+ module.exports = PegasusConnection;
package/lib/documents.js CHANGED
@@ -1,94 +1,94 @@
1
- class DocumentsService {
2
- constructor(connection) {
3
- this.connection = connection;
4
- }
5
-
6
- async createDocument(documentPath, casNumbers) {}
7
-
8
- async bulkCreateDocuments(documents) {}
9
-
10
- async updateDocument(documentId, updates) {}
11
-
12
- async deleteDocument(documentId) {}
13
-
14
- async deleteDocumentByPath(documentPath) {}
15
-
16
- async getDocumentById(documentId) {}
17
-
18
- async getDocumentByPath(documentPath) {}
19
-
20
- async getDocumentsByCAS(casNumber) {}
21
-
22
- async getCASByDocument(documentId) {}
23
-
24
- async getCASByDocumentPath(documentPath) {}
25
-
26
- async addCASToDocument(documentId, casNumber) {}
27
-
28
- async addCASToDocumentBatch(documentId, casNumbers) {}
29
-
30
- async removeCASFromDocument(documentId, casNumber) {}
31
-
32
- async findDocumentsWithMultipleCAS(casNumbers, requireAll) {}
33
-
34
- async countDocuments() {}
35
-
36
- async countDocumentsByCAS(casNumber) {}
37
-
38
- async countUniqueCAS() {}
39
-
40
- async getTopCASByDocumentCount(limit) {}
41
-
42
- async extractTextFromPDF(pdfBuffer) {}
43
-
44
- async extractCASFromText(text) {}
45
-
46
- async processDocument(documentPath, documentData) {}
47
-
48
- registerElasticsearchHandlers(elasticsearchService) {
49
- const indexPatterns = this.connection.config.indexRoutes?.documents || ['documents*'];
50
-
51
- indexPatterns.forEach(pattern => {
52
- elasticsearchService.registerIndexRoute(pattern, {
53
- index: async (params) => {
54
- const document = params.body;
55
- return await this.createDocument(document.document_path, document.cas_numbers || []);
56
- },
57
-
58
- bulk: async (params) => {
59
- const operations = params.body || params.operations;
60
- const documents = [];
61
-
62
- for (let i = 0; i < operations.length; i += 2) {
63
- const action = operations[i];
64
- const document = operations[i + 1];
65
-
66
- if (action.index || action.create) {
67
- documents.push(document);
68
- }
69
- }
70
-
71
- return await this.bulkCreateDocuments(documents);
72
- },
73
-
74
- get: async (params) => {
75
- return await this.getDocumentById(params.id);
76
- },
77
-
78
- update: async (params) => {
79
- return await this.updateDocument(params.id, params.body);
80
- },
81
-
82
- delete: async (params) => {
83
- return await this.deleteDocument(params.id);
84
- },
85
-
86
- count: async (params) => {
87
- return await this.countDocuments();
88
- }
89
- });
90
- });
91
- }
92
- }
93
-
94
- module.exports = DocumentsService;
1
+ class DocumentsService {
2
+ constructor(connection) {
3
+ this.connection = connection;
4
+ }
5
+
6
+ async createDocument(documentPath, casNumbers) {}
7
+
8
+ async bulkCreateDocuments(documents) {}
9
+
10
+ async updateDocument(documentId, updates) {}
11
+
12
+ async deleteDocument(documentId) {}
13
+
14
+ async deleteDocumentByPath(documentPath) {}
15
+
16
+ async getDocumentById(documentId) {}
17
+
18
+ async getDocumentByPath(documentPath) {}
19
+
20
+ async getDocumentsByCAS(casNumber) {}
21
+
22
+ async getCASByDocument(documentId) {}
23
+
24
+ async getCASByDocumentPath(documentPath) {}
25
+
26
+ async addCASToDocument(documentId, casNumber) {}
27
+
28
+ async addCASToDocumentBatch(documentId, casNumbers) {}
29
+
30
+ async removeCASFromDocument(documentId, casNumber) {}
31
+
32
+ async findDocumentsWithMultipleCAS(casNumbers, requireAll) {}
33
+
34
+ async countDocuments() {}
35
+
36
+ async countDocumentsByCAS(casNumber) {}
37
+
38
+ async countUniqueCAS() {}
39
+
40
+ async getTopCASByDocumentCount(limit) {}
41
+
42
+ async extractTextFromPDF(pdfBuffer) {}
43
+
44
+ async extractCASFromText(text) {}
45
+
46
+ async processDocument(documentPath, documentData) {}
47
+
48
+ registerElasticsearchHandlers(elasticsearchService) {
49
+ const indexPatterns = this.connection.config.indexRoutes?.documents || ['documents*'];
50
+
51
+ indexPatterns.forEach(pattern => {
52
+ elasticsearchService.registerIndexRoute(pattern, {
53
+ index: async (params) => {
54
+ const document = params.body;
55
+ return await this.createDocument(document.document_path, document.cas_numbers || []);
56
+ },
57
+
58
+ bulk: async (params) => {
59
+ const operations = params.body || params.operations;
60
+ const documents = [];
61
+
62
+ for (let i = 0; i < operations.length; i += 2) {
63
+ const action = operations[i];
64
+ const document = operations[i + 1];
65
+
66
+ if (action.index || action.create) {
67
+ documents.push(document);
68
+ }
69
+ }
70
+
71
+ return await this.bulkCreateDocuments(documents);
72
+ },
73
+
74
+ get: async (params) => {
75
+ return await this.getDocumentById(params.id);
76
+ },
77
+
78
+ update: async (params) => {
79
+ return await this.updateDocument(params.id, params.body);
80
+ },
81
+
82
+ delete: async (params) => {
83
+ return await this.deleteDocument(params.id);
84
+ },
85
+
86
+ count: async (params) => {
87
+ return await this.countDocuments();
88
+ }
89
+ });
90
+ });
91
+ }
92
+ }
93
+
94
+ module.exports = DocumentsService;
package/lib/sync.js CHANGED
@@ -1,43 +1,43 @@
1
- class SyncService {
2
- constructor(connection) {
3
- this.connection = connection;
4
- }
5
-
6
- async syncBatch(batchSize) {}
7
-
8
- async syncAll() {}
9
-
10
- async syncContinuous(intervalMs) {}
11
-
12
- async stopContinuousSync() {}
13
-
14
- async getPendingCount() {}
15
-
16
- async getOldestPending() {}
17
-
18
- async getSyncLag() {}
19
-
20
- async getFailedEntries(minRetryCount) {}
21
-
22
- async retryFailed(outboxId) {}
23
-
24
- async retryAllFailed() {}
25
-
26
- async markAsProcessed(outboxId) {}
27
-
28
- async deleteProcessedOlderThan(days) {}
29
-
30
- async cleanupOutbox(daysToKeep) {}
31
-
32
- async getSyncStats(timeWindowMinutes) {}
33
-
34
- async getSyncThroughput() {}
35
-
36
- async verifySync(chemicalId) {}
37
-
38
- async forceResync(chemicalId) {}
39
-
40
- async getOutboxHealth() {}
41
- }
42
-
43
- module.exports = SyncService;
1
+ class SyncService {
2
+ constructor(connection) {
3
+ this.connection = connection;
4
+ }
5
+
6
+ async syncBatch(batchSize) {}
7
+
8
+ async syncAll() {}
9
+
10
+ async syncContinuous(intervalMs) {}
11
+
12
+ async stopContinuousSync() {}
13
+
14
+ async getPendingCount() {}
15
+
16
+ async getOldestPending() {}
17
+
18
+ async getSyncLag() {}
19
+
20
+ async getFailedEntries(minRetryCount) {}
21
+
22
+ async retryFailed(outboxId) {}
23
+
24
+ async retryAllFailed() {}
25
+
26
+ async markAsProcessed(outboxId) {}
27
+
28
+ async deleteProcessedOlderThan(days) {}
29
+
30
+ async cleanupOutbox(daysToKeep) {}
31
+
32
+ async getSyncStats(timeWindowMinutes) {}
33
+
34
+ async getSyncThroughput() {}
35
+
36
+ async verifySync(chemicalId) {}
37
+
38
+ async forceResync(chemicalId) {}
39
+
40
+ async getOutboxHealth() {}
41
+ }
42
+
43
+ module.exports = SyncService;
package/lib/utils.js CHANGED
@@ -1,49 +1,49 @@
1
- class UtilsService {
2
- constructor(connection) {
3
- this.connection = connection;
4
- }
5
-
6
- async executeBatch(operations, batchSize, concurrency) {}
7
-
8
- async withTransaction(callback) {}
9
-
10
- async withRetry(operation, maxRetries, backoffMs) {}
11
-
12
- validateChemical(chemical) {}
13
-
14
- validateDocument(document) {}
15
-
16
- validateIdentifier(identifier) {}
17
-
18
- validateCAS(casNumber) {}
19
-
20
- transformForOpenSearch(chemical) {}
21
-
22
- transformFromElasticsearch(esDocument) {}
23
-
24
- transformFromDynamoDB(dynamoItem) {}
25
-
26
- buildOpenSearchQuery(searchTerm, searchType) {}
27
-
28
- buildPostgresFilter(filters) {}
29
-
30
- parseChemicalIdentifiers(identifiers) {}
31
-
32
- parseSynonyms(synonyms) {}
33
-
34
- extractCASFromText(text) {}
35
-
36
- sanitizeSearchTerm(term) {}
37
-
38
- generateSourceId(chemical) {}
39
-
40
- calculateChecksum(data) {}
41
-
42
- formatError(error) {}
43
-
44
- logOperation(operation, duration, metadata) {}
45
-
46
- getTimestamp() {}
47
- }
48
-
49
- module.exports = UtilsService;
1
+ class UtilsService {
2
+ constructor(connection) {
3
+ this.connection = connection;
4
+ }
5
+
6
+ async executeBatch(operations, batchSize, concurrency) {}
7
+
8
+ async withTransaction(callback) {}
9
+
10
+ async withRetry(operation, maxRetries, backoffMs) {}
11
+
12
+ validateChemical(chemical) {}
13
+
14
+ validateDocument(document) {}
15
+
16
+ validateIdentifier(identifier) {}
17
+
18
+ validateCAS(casNumber) {}
19
+
20
+ transformForOpenSearch(chemical) {}
21
+
22
+ transformFromElasticsearch(esDocument) {}
23
+
24
+ transformFromDynamoDB(dynamoItem) {}
25
+
26
+ buildOpenSearchQuery(searchTerm, searchType) {}
27
+
28
+ buildPostgresFilter(filters) {}
29
+
30
+ parseChemicalIdentifiers(identifiers) {}
31
+
32
+ parseSynonyms(synonyms) {}
33
+
34
+ extractCASFromText(text) {}
35
+
36
+ sanitizeSearchTerm(term) {}
37
+
38
+ generateSourceId(chemical) {}
39
+
40
+ calculateChecksum(data) {}
41
+
42
+ formatError(error) {}
43
+
44
+ logOperation(operation, duration, metadata) {}
45
+
46
+ getTimestamp() {}
47
+ }
48
+
49
+ module.exports = UtilsService;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toxplanet/pegasus-sdk",
3
- "version": "1.1.4",
3
+ "version": "1.1.6",
4
4
  "description": "SDK for migrating chemical data to Pegasus PostgreSQL + OpenSearch architecture with Elasticsearch client compatibility",
5
5
  "main": "index.js",
6
6
  "type": "commonjs",