masterrecord 0.2.36 → 0.3.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/.claude/settings.local.json +19 -1
- package/Entity/entityModel.js +6 -0
- package/Entity/entityTrackerModel.js +20 -3
- package/Entity/fieldTransformer.js +266 -0
- package/Migrations/migrationMySQLQuery.js +145 -1
- package/Migrations/migrationPostgresQuery.js +402 -0
- package/Migrations/migrationSQLiteQuery.js +145 -1
- package/Migrations/schema.js +131 -28
- package/QueryLanguage/queryMethods.js +193 -15
- package/QueryLanguage/queryParameters.js +136 -0
- package/QueryLanguage/queryScript.js +13 -4
- package/SQLLiteEngine.js +309 -19
- package/context.js +47 -10
- package/docs/INCLUDES_CLARIFICATION.md +202 -0
- package/docs/METHODS_REFERENCE.md +184 -0
- package/docs/MIGRATIONS_GUIDE.md +699 -0
- package/docs/POSTGRESQL_SETUP.md +415 -0
- package/examples/jsonArrayTransformer.js +215 -0
- package/mySQLEngine.js +249 -17
- package/package.json +3 -3
- package/postgresEngine.js +434 -491
- package/postgresSyncConnect.js +209 -0
- package/readme.md +1046 -416
- package/test/anyCommaStringTest.js +237 -0
- package/test/anyMethodTest.js +176 -0
- package/test/findByIdTest.js +227 -0
- package/test/includesFeatureTest.js +183 -0
- package/test/includesTransformTest.js +110 -0
- package/test/newMethodTest.js +330 -0
- package/test/newMethodUnitTest.js +320 -0
- package/test/parameterizedPlaceholderTest.js +159 -0
- package/test/postgresEngineTest.js +463 -0
- package/test/postgresIntegrationTest.js +381 -0
- package/test/securityTest.js +268 -0
- package/test/singleDollarPlaceholderTest.js +238 -0
- package/test/transformerTest.js +287 -0
- package/test/verifyFindById.js +169 -0
- package/test/verifyNewMethod.js +191 -0
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
// Version 1.0.0 - PostgreSQL connection helper for pg 8.16.3
|
|
2
|
+
const { Pool } = require('pg');
|
|
3
|
+
const postgresEngine = require('./postgresEngine');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* PostgreSQL connection manager for MasterRecord
|
|
7
|
+
* Uses pg library with connection pooling
|
|
8
|
+
*/
|
|
9
|
+
class PostgresSyncConnect {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.pool = null;
|
|
12
|
+
this.engine = null;
|
|
13
|
+
this.config = null;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Initialize PostgreSQL connection
|
|
18
|
+
* @param {Object} config - Connection configuration
|
|
19
|
+
* @param {string} config.host - Database host (default: 'localhost')
|
|
20
|
+
* @param {number} config.port - Database port (default: 5432)
|
|
21
|
+
* @param {string} config.database - Database name (required)
|
|
22
|
+
* @param {string} config.user - Database user (required)
|
|
23
|
+
* @param {string} config.password - Database password (required)
|
|
24
|
+
* @param {number} config.max - Max pool size (default: 20)
|
|
25
|
+
* @param {number} config.idleTimeoutMillis - Idle timeout (default: 30000)
|
|
26
|
+
* @param {number} config.connectionTimeoutMillis - Connection timeout (default: 2000)
|
|
27
|
+
*/
|
|
28
|
+
async connect(config) {
|
|
29
|
+
if (!config.database) {
|
|
30
|
+
throw new Error('PostgreSQL: database name is required');
|
|
31
|
+
}
|
|
32
|
+
if (!config.user) {
|
|
33
|
+
throw new Error('PostgreSQL: user is required');
|
|
34
|
+
}
|
|
35
|
+
if (!config.password) {
|
|
36
|
+
throw new Error('PostgreSQL: password is required');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
this.config = {
|
|
40
|
+
host: config.host || 'localhost',
|
|
41
|
+
port: config.port || 5432,
|
|
42
|
+
database: config.database,
|
|
43
|
+
user: config.user,
|
|
44
|
+
password: config.password,
|
|
45
|
+
max: config.max || 20,
|
|
46
|
+
idleTimeoutMillis: config.idleTimeoutMillis || 30000,
|
|
47
|
+
connectionTimeoutMillis: config.connectionTimeoutMillis || 2000,
|
|
48
|
+
ssl: config.ssl || false,
|
|
49
|
+
// Enable better error messages
|
|
50
|
+
application_name: 'MasterRecord',
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// Create connection pool
|
|
54
|
+
this.pool = new Pool(this.config);
|
|
55
|
+
|
|
56
|
+
// Test connection
|
|
57
|
+
try {
|
|
58
|
+
const client = await this.pool.connect();
|
|
59
|
+
console.log(`PostgreSQL connected to ${config.database} at ${config.host}:${config.port}`);
|
|
60
|
+
client.release();
|
|
61
|
+
} catch (err) {
|
|
62
|
+
console.error('PostgreSQL connection failed:', err.message);
|
|
63
|
+
throw err;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Initialize engine
|
|
67
|
+
this.engine = new postgresEngine();
|
|
68
|
+
this.engine.setDB(this.pool, 'postgres');
|
|
69
|
+
|
|
70
|
+
// Set up error handlers
|
|
71
|
+
this.pool.on('error', (err, client) => {
|
|
72
|
+
console.error('Unexpected PostgreSQL error:', err);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
this.pool.on('connect', (client) => {
|
|
76
|
+
console.log('New PostgreSQL client connected');
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
return this.pool;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Get the SQL engine instance
|
|
84
|
+
*/
|
|
85
|
+
getEngine() {
|
|
86
|
+
if (!this.engine) {
|
|
87
|
+
throw new Error('PostgreSQL not connected. Call connect() first.');
|
|
88
|
+
}
|
|
89
|
+
return this.engine;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Get the connection pool
|
|
94
|
+
*/
|
|
95
|
+
getPool() {
|
|
96
|
+
if (!this.pool) {
|
|
97
|
+
throw new Error('PostgreSQL not connected. Call connect() first.');
|
|
98
|
+
}
|
|
99
|
+
return this.pool;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Execute raw SQL query
|
|
104
|
+
* @param {string} query - SQL query with $1, $2 placeholders
|
|
105
|
+
* @param {Array} params - Query parameters
|
|
106
|
+
*/
|
|
107
|
+
async query(query, params = []) {
|
|
108
|
+
if (!this.pool) {
|
|
109
|
+
throw new Error('PostgreSQL not connected. Call connect() first.');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
const result = await this.pool.query(query, params);
|
|
114
|
+
return result;
|
|
115
|
+
} catch (err) {
|
|
116
|
+
console.error('PostgreSQL query error:', err);
|
|
117
|
+
throw err;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Execute query in a transaction
|
|
123
|
+
* @param {Function} callback - Async function that receives client
|
|
124
|
+
*/
|
|
125
|
+
async transaction(callback) {
|
|
126
|
+
if (!this.pool) {
|
|
127
|
+
throw new Error('PostgreSQL not connected. Call connect() first.');
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const client = await this.pool.connect();
|
|
131
|
+
|
|
132
|
+
try {
|
|
133
|
+
await client.query('BEGIN');
|
|
134
|
+
const result = await callback(client);
|
|
135
|
+
await client.query('COMMIT');
|
|
136
|
+
return result;
|
|
137
|
+
} catch (err) {
|
|
138
|
+
await client.query('ROLLBACK');
|
|
139
|
+
console.error('Transaction error:', err);
|
|
140
|
+
throw err;
|
|
141
|
+
} finally {
|
|
142
|
+
client.release();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Check if connected
|
|
148
|
+
*/
|
|
149
|
+
isConnected() {
|
|
150
|
+
return this.pool !== null;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Get connection info
|
|
155
|
+
*/
|
|
156
|
+
getConnectionInfo() {
|
|
157
|
+
if (!this.config) {
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return {
|
|
162
|
+
host: this.config.host,
|
|
163
|
+
port: this.config.port,
|
|
164
|
+
database: this.config.database,
|
|
165
|
+
user: this.config.user,
|
|
166
|
+
maxConnections: this.config.max
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Close connection pool
|
|
172
|
+
*/
|
|
173
|
+
async close() {
|
|
174
|
+
if (this.pool) {
|
|
175
|
+
await this.pool.end();
|
|
176
|
+
console.log('PostgreSQL pool closed');
|
|
177
|
+
this.pool = null;
|
|
178
|
+
this.engine = null;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Health check
|
|
184
|
+
*/
|
|
185
|
+
async healthCheck() {
|
|
186
|
+
if (!this.pool) {
|
|
187
|
+
return { healthy: false, error: 'Not connected' };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
try {
|
|
191
|
+
const result = await this.pool.query('SELECT NOW() as time, version() as version');
|
|
192
|
+
return {
|
|
193
|
+
healthy: true,
|
|
194
|
+
serverTime: result.rows[0].time,
|
|
195
|
+
version: result.rows[0].version,
|
|
196
|
+
poolSize: this.pool.totalCount,
|
|
197
|
+
idleCount: this.pool.idleCount,
|
|
198
|
+
waitingCount: this.pool.waitingCount
|
|
199
|
+
};
|
|
200
|
+
} catch (err) {
|
|
201
|
+
return {
|
|
202
|
+
healthy: false,
|
|
203
|
+
error: err.message
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
module.exports = PostgresSyncConnect;
|