pgserve 0.1.3 → 0.1.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pgserve",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Multi-instance PostgreSQL embedded server using PGlite - zero config, auto-port allocation, perfect for development and embedded apps",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
package/src/protocol.js CHANGED
@@ -11,7 +11,9 @@
11
11
  */
12
12
 
13
13
  const PROTOCOL_VERSION_3 = 196608;
14
- const SSL_REQUEST_CODE = 80877103; // PostgreSQL SSL negotiation request
14
+ const SSL_REQUEST_CODE = 80877103; // PostgreSQL SSL negotiation request
15
+ const GSSAPI_REQUEST_CODE = 80877104; // PostgreSQL GSSAPI encryption request
16
+ const CANCEL_REQUEST_CODE = 80877102; // PostgreSQL cancel request
15
17
  const DATABASE_KEY = Buffer.from('database\0');
16
18
 
17
19
  /**
@@ -176,14 +178,17 @@ export async function readStartupMessage(socket) {
176
178
  socket.on('data', onData);
177
179
  socket.on('error', onError);
178
180
 
179
- // Timeout after 5 seconds
181
+ // Resume socket AFTER listeners are set up (prevents race condition)
182
+ socket.resume();
183
+
184
+ // Timeout after 2 seconds (reduced from 5s for faster probe connection handling)
180
185
  setTimeout(() => {
181
186
  if (resolved) return;
182
187
  resolved = true;
183
188
  socket.removeListener('data', onData);
184
189
  socket.removeListener('error', onError);
185
190
  reject(new Error('Timeout reading startup message'));
186
- }, 5000);
191
+ }, 2000);
187
192
  });
188
193
  }
189
194
 
@@ -196,7 +201,7 @@ export async function readStartupMessage(socket) {
196
201
  export async function extractDatabaseNameFromSocket(socket) {
197
202
  let { message, allData } = await readStartupMessage(socket);
198
203
 
199
- // Check if this is an SSL request
204
+ // Check if this is a protocol negotiation request (SSL, GSSAPI, Cancel)
200
205
  if (message.length >= 8) {
201
206
  const version = message.readInt32BE(4);
202
207
 
@@ -208,6 +213,18 @@ export async function extractDatabaseNameFromSocket(socket) {
208
213
  const result = await readStartupMessage(socket);
209
214
  message = result.message;
210
215
  allData = result.allData;
216
+ } else if (version === GSSAPI_REQUEST_CODE) {
217
+ // Respond with 'N' (no GSSAPI support)
218
+ socket.write(Buffer.from('N'));
219
+
220
+ // Read the actual startup message
221
+ const result = await readStartupMessage(socket);
222
+ message = result.message;
223
+ allData = result.allData;
224
+ } else if (version === CANCEL_REQUEST_CODE) {
225
+ // Cancel request - PGlite doesn't support query cancellation
226
+ // Just close gracefully (cancel requests don't expect a response)
227
+ throw new Error('Cancel request received (not supported)');
211
228
  }
212
229
  }
213
230
 
package/src/router.js CHANGED
@@ -152,8 +152,8 @@ export class MultiTenantRouter extends EventEmitter {
152
152
  // Track connection
153
153
  this.connections.add(socket);
154
154
 
155
- // Resume socket (was paused on connect)
156
- socket.resume();
155
+ // NOTE: Don't resume here - let readStartupMessage() resume after setting up listeners
156
+ // This prevents race condition where data arrives before listener is attached
157
157
 
158
158
  let dbName = null;
159
159
  let handler = null;