@machinemetrics/mm-erp-sdk 0.1.7-beta.1 → 0.1.7-beta.3
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/mm-erp-sdk.js +68 -45
- package/dist/mm-erp-sdk.js.map +1 -1
- package/dist/services/data-sync-service/data-sync-service.d.ts.map +1 -1
- package/dist/services/psql-erp-service/psql-service.d.ts +14 -1
- package/dist/services/psql-erp-service/psql-service.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/services/data-sync-service/data-sync-service.ts +0 -5
- package/src/services/psql-erp-service/psql-service.ts +90 -53
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-sync-service.d.ts","sourceRoot":"","sources":["../../../src/services/data-sync-service/data-sync-service.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,kBAAkB,GAAU,eAAe,MAAM,
|
|
1
|
+
{"version":3,"file":"data-sync-service.d.ts","sourceRoot":"","sources":["../../../src/services/data-sync-service/data-sync-service.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,kBAAkB,GAAU,eAAe,MAAM,kBA0I7D,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import odbc from "odbc";
|
|
1
2
|
import { PsqlConfiguration } from "./configuration";
|
|
2
3
|
import { ERPResponse } from "../../types/erp-types";
|
|
3
4
|
type PagingParams = {
|
|
@@ -5,8 +6,10 @@ type PagingParams = {
|
|
|
5
6
|
offset?: number;
|
|
6
7
|
};
|
|
7
8
|
export declare class PsqlService {
|
|
9
|
+
private connection;
|
|
8
10
|
private config;
|
|
9
11
|
constructor(config: PsqlConfiguration);
|
|
12
|
+
dispose(): Promise<void>;
|
|
10
13
|
/**
|
|
11
14
|
* Build PSQL ODBC connection string
|
|
12
15
|
* CRITICAL: ServerName must use IP.PORT format (e.g., 10.4.0.11.1583)
|
|
@@ -14,7 +17,7 @@ export declare class PsqlService {
|
|
|
14
17
|
private buildConnectionString;
|
|
15
18
|
/**
|
|
16
19
|
* Execute a query and return the results
|
|
17
|
-
*
|
|
20
|
+
* Interface matches SqlServerService for consistency
|
|
18
21
|
*
|
|
19
22
|
* @param query The SQL query to execute
|
|
20
23
|
* @param params Query parameters (currently unused for PSQL read operations)
|
|
@@ -22,15 +25,25 @@ export declare class PsqlService {
|
|
|
22
25
|
* @returns The entities fetched from the database, along with paging information
|
|
23
26
|
*/
|
|
24
27
|
executePreparedStatement(query: string, params?: Record<string, string>, paging?: PagingParams): Promise<ERPResponse | undefined>;
|
|
28
|
+
/**
|
|
29
|
+
* Opens a connection to PSQL database
|
|
30
|
+
* Caches the connection so that it can be reused.
|
|
31
|
+
* On failure to connect, throws
|
|
32
|
+
*/
|
|
33
|
+
openConnection(): Promise<odbc.Connection>;
|
|
25
34
|
/**
|
|
26
35
|
* Transform ODBC result set to array of Record<string, string> instances.
|
|
27
36
|
* IMPORTANT: PSQL CHAR fields are often padded with spaces - we trim them
|
|
37
|
+
*
|
|
38
|
+
* @param recordset Result set from ODBC query
|
|
39
|
+
* @returns array of Record<string, string> instances
|
|
28
40
|
*/
|
|
29
41
|
static recordsetToRecords(recordset: any[]): Record<string, string>[];
|
|
30
42
|
/**
|
|
31
43
|
* Handle ODBC errors and provide meaningful messages
|
|
32
44
|
*/
|
|
33
45
|
private handleOdbcError;
|
|
46
|
+
private closeConnection;
|
|
34
47
|
}
|
|
35
48
|
export {};
|
|
36
49
|
//# sourceMappingURL=psql-service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"psql-service.d.ts","sourceRoot":"","sources":["../../../src/services/psql-erp-service/psql-service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"psql-service.d.ts","sourceRoot":"","sources":["../../../src/services/psql-erp-service/psql-service.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAIpD,KAAK,YAAY,GAAG;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,qBAAa,WAAW;IACtB,OAAO,CAAC,UAAU,CAAgC;IAClD,OAAO,CAAC,MAAM,CAAoB;gBAEtB,MAAM,EAAE,iBAAiB;IAI/B,OAAO;IAIb;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAgB7B;;;;;;;;OAQG;IACU,wBAAwB,CACnC,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,EACnC,MAAM,CAAC,EAAE,YAAY,GACpB,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;IAsDnC;;;;OAIG;IACG,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC;IA4BhD;;;;;;OAMG;WACW,kBAAkB,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE;IAmB5E;;OAEG;IACH,OAAO,CAAC,eAAe;YA6BT,eAAe;CAa9B"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@machinemetrics/mm-erp-sdk",
|
|
3
3
|
"description": "A library for syncing data between MachineMetrics and ERP systems",
|
|
4
|
-
"version": "0.1.7-beta.
|
|
4
|
+
"version": "0.1.7-beta.3",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "machinemetrics",
|
|
7
7
|
"main": "dist/mm-erp-sdk.js",
|
|
@@ -45,11 +45,6 @@ export const runDataSyncService = async (connectorPath: string) => {
|
|
|
45
45
|
// Pass through all other environment variables that might be needed
|
|
46
46
|
...process.env,
|
|
47
47
|
},
|
|
48
|
-
|
|
49
|
-
// Add worker options for better isolation and cleanup
|
|
50
|
-
execArgv: [
|
|
51
|
-
"--expose-gc", // Allow manual garbage collection
|
|
52
|
-
],
|
|
53
48
|
},
|
|
54
49
|
|
|
55
50
|
jobs: [
|
|
@@ -10,22 +10,23 @@ type PagingParams = {
|
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
export class PsqlService {
|
|
13
|
+
private connection: odbc.Connection | null = null;
|
|
13
14
|
private config: PsqlConfiguration;
|
|
14
15
|
|
|
15
16
|
constructor(config: PsqlConfiguration) {
|
|
16
17
|
this.config = config;
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
// REMOVED: closeConnection() method - not needed anymore
|
|
20
|
+
async dispose() {
|
|
21
|
+
await this.closeConnection();
|
|
22
|
+
}
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* Build PSQL ODBC connection string
|
|
26
26
|
* CRITICAL: ServerName must use IP.PORT format (e.g., 10.4.0.11.1583)
|
|
27
27
|
*/
|
|
28
28
|
private buildConnectionString(): string {
|
|
29
|
+
// PSQL requires ServerName in format IP.PORT (not IP:PORT)
|
|
29
30
|
const serverName = `${this.config.host}.${this.config.port}`;
|
|
30
31
|
|
|
31
32
|
return (
|
|
@@ -42,7 +43,7 @@ export class PsqlService {
|
|
|
42
43
|
|
|
43
44
|
/**
|
|
44
45
|
* Execute a query and return the results
|
|
45
|
-
*
|
|
46
|
+
* Interface matches SqlServerService for consistency
|
|
46
47
|
*
|
|
47
48
|
* @param query The SQL query to execute
|
|
48
49
|
* @param params Query parameters (currently unused for PSQL read operations)
|
|
@@ -54,14 +55,12 @@ export class PsqlService {
|
|
|
54
55
|
params: Record<string, string> = {},
|
|
55
56
|
paging?: PagingParams
|
|
56
57
|
): Promise<ERPResponse | undefined> {
|
|
57
|
-
|
|
58
|
+
const connection = await this.openConnection();
|
|
58
59
|
|
|
60
|
+
let records;
|
|
59
61
|
try {
|
|
60
|
-
//
|
|
61
|
-
|
|
62
|
-
logger.debug("Creating fresh PSQL connection for query");
|
|
63
|
-
connection = await odbc.connect(connStr);
|
|
64
|
-
|
|
62
|
+
// For Phase 1 (read-only), we execute queries directly
|
|
63
|
+
// Phase 2 will add proper parameter binding for INSERT/UPDATE/DELETE
|
|
65
64
|
if (Object.keys(params).length > 0) {
|
|
66
65
|
logger.warn(
|
|
67
66
|
"PsqlService: Query parameters provided but parameter binding not yet implemented. " +
|
|
@@ -69,62 +68,85 @@ export class PsqlService {
|
|
|
69
68
|
);
|
|
70
69
|
}
|
|
71
70
|
|
|
72
|
-
|
|
73
|
-
const allRecords = PsqlService.recordsetToRecords(records);
|
|
74
|
-
const rowsFetched = allRecords.length;
|
|
75
|
-
|
|
76
|
-
// Apply paging if requested
|
|
77
|
-
const pagedData =
|
|
78
|
-
paging?.offset !== undefined || paging?.limit !== undefined
|
|
79
|
-
? allRecords.slice(
|
|
80
|
-
paging.offset || 0,
|
|
81
|
-
(paging.offset || 0) + (paging.limit || allRecords.length)
|
|
82
|
-
)
|
|
83
|
-
: allRecords;
|
|
84
|
-
|
|
85
|
-
return {
|
|
86
|
-
data: pagedData,
|
|
87
|
-
paging: {
|
|
88
|
-
count: rowsFetched,
|
|
89
|
-
limit: paging?.limit || 0,
|
|
90
|
-
offset: paging?.offset || 0,
|
|
91
|
-
nextPage:
|
|
92
|
-
paging?.limit && (paging.offset || 0) + paging.limit < rowsFetched
|
|
93
|
-
? String((paging.offset || 0) + paging.limit)
|
|
94
|
-
: undefined,
|
|
95
|
-
previousPage: paging?.offset
|
|
96
|
-
? String(Math.max(0, (paging.offset || 0) - (paging.limit || 10)))
|
|
97
|
-
: undefined,
|
|
98
|
-
},
|
|
99
|
-
};
|
|
71
|
+
records = await connection.query(query);
|
|
100
72
|
} catch (error) {
|
|
101
73
|
const errorInfo = error as OdbcErrorResponse;
|
|
102
74
|
logger.error("Error fetching data from PSQL", {
|
|
103
75
|
error: errorInfo.message,
|
|
104
76
|
odbcErrors: errorInfo.odbcErrors,
|
|
105
|
-
query: query.substring(0, 200), // Log first 200 chars of query
|
|
106
77
|
});
|
|
107
78
|
|
|
108
79
|
throw this.handleOdbcError(errorInfo);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const allRecords = PsqlService.recordsetToRecords(records);
|
|
83
|
+
const rowsFetched = allRecords.length;
|
|
84
|
+
|
|
85
|
+
// Apply paging if requested
|
|
86
|
+
const pagedData =
|
|
87
|
+
paging?.offset !== undefined || paging?.limit !== undefined
|
|
88
|
+
? allRecords.slice(
|
|
89
|
+
paging.offset || 0,
|
|
90
|
+
(paging.offset || 0) + (paging.limit || allRecords.length)
|
|
91
|
+
)
|
|
92
|
+
: allRecords;
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
data: pagedData,
|
|
96
|
+
paging: {
|
|
97
|
+
count: rowsFetched,
|
|
98
|
+
limit: paging?.limit || 0,
|
|
99
|
+
offset: paging?.offset || 0,
|
|
100
|
+
nextPage:
|
|
101
|
+
paging?.limit && (paging.offset || 0) + paging.limit < rowsFetched
|
|
102
|
+
? String((paging.offset || 0) + paging.limit)
|
|
103
|
+
: undefined,
|
|
104
|
+
previousPage: paging?.offset
|
|
105
|
+
? String(Math.max(0, (paging.offset || 0) - (paging.limit || 10)))
|
|
106
|
+
: undefined,
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Opens a connection to PSQL database
|
|
113
|
+
* Caches the connection so that it can be reused.
|
|
114
|
+
* On failure to connect, throws
|
|
115
|
+
*/
|
|
116
|
+
async openConnection(): Promise<odbc.Connection> {
|
|
117
|
+
// If we have a connection, reuse it
|
|
118
|
+
// Note: ODBC connections don't have a .connected property like SQL Server
|
|
119
|
+
// We'll keep it simple and reuse if not null
|
|
120
|
+
if (this.connection) {
|
|
121
|
+
logger.debug("Reusing existing PSQL connection");
|
|
122
|
+
return this.connection;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
const connStr = this.buildConnectionString();
|
|
127
|
+
logger.info("Opening new PSQL connection");
|
|
128
|
+
logger.debug(
|
|
129
|
+
"Connection string (password hidden):",
|
|
130
|
+
connStr.replace(/PWD=[^;]+/, "PWD=***")
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
this.connection = await odbc.connect(connStr);
|
|
134
|
+
logger.info("Successfully connected to PSQL database");
|
|
135
|
+
return this.connection;
|
|
136
|
+
} catch (error) {
|
|
137
|
+
logger.error("PsqlService>>openConnection>> Connection failed", {
|
|
138
|
+
error,
|
|
139
|
+
});
|
|
140
|
+
throw this.handleOdbcError(error as OdbcErrorResponse);
|
|
122
141
|
}
|
|
123
142
|
}
|
|
124
143
|
|
|
125
144
|
/**
|
|
126
145
|
* Transform ODBC result set to array of Record<string, string> instances.
|
|
127
146
|
* IMPORTANT: PSQL CHAR fields are often padded with spaces - we trim them
|
|
147
|
+
*
|
|
148
|
+
* @param recordset Result set from ODBC query
|
|
149
|
+
* @returns array of Record<string, string> instances
|
|
128
150
|
*/
|
|
129
151
|
public static recordsetToRecords(recordset: any[]): Record<string, string>[] {
|
|
130
152
|
if (!Array.isArray(recordset)) {
|
|
@@ -135,6 +157,7 @@ export class PsqlService {
|
|
|
135
157
|
const transformedRow: Record<string, string> = {};
|
|
136
158
|
Object.keys(row).forEach((key) => {
|
|
137
159
|
const value = row[key];
|
|
160
|
+
// Convert to string and trim (PSQL CHAR fields have trailing spaces)
|
|
138
161
|
transformedRow[key] =
|
|
139
162
|
value !== null && value !== undefined ? String(value).trim() : "";
|
|
140
163
|
});
|
|
@@ -175,4 +198,18 @@ export class PsqlService {
|
|
|
175
198
|
return new Error(`PSQL error (${errorCode || "unknown"}): ${message}`);
|
|
176
199
|
}
|
|
177
200
|
}
|
|
201
|
+
|
|
202
|
+
private async closeConnection(): Promise<void> {
|
|
203
|
+
if (this.connection) {
|
|
204
|
+
logger.info("Closing PSQL connection");
|
|
205
|
+
try {
|
|
206
|
+
await this.connection.close();
|
|
207
|
+
} catch (error) {
|
|
208
|
+
logger.error("PsqlService::closeConnection: Error closing connection", {
|
|
209
|
+
error,
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
this.connection = null;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
178
215
|
}
|