Conversation
- Add handleCommand hook for server-side command dispatch in handlePacket - Thread serverOptions (handleCommand, encoding) through createServer → Server → ConnectionConfig → Connection - Add Query.fromPacket() for server-side COM_QUERY deserialization - Make Handshake packet support configurable getSalt and authPluginName - Simplify HandshakeResponse to accept pre-calculated authToken - Use _serverEncoding getter for server write helpers (writeColumns, writeOk, etc.) - Bump sequenceId by 1 on server-side command start - Emit auth errors to connection instead of throwing
9173fea to
fb4d774
Compare
…ump, update tests - Restore this.database = connection.config.database in sendCredentials (dropped during rebase) - Only bump server sequenceId when responding to a client packet (not for initial handshake) - Default HandshakeResponse.authToken to empty buffer when not provided - Update HandshakeResponse tests to match simplified constructor API
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1405 +/- ##
==========================================
- Coverage 90.86% 90.55% -0.32%
==========================================
Files 89 95 +6
Lines 14490 14848 +358
Branches 1864 1941 +77
==========================================
+ Hits 13167 13445 +278
- Misses 1323 1403 +80
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
- Add ServerOptions interface with onConnection, handleCommand, encoding - Update createServer() type signature to accept ServerOptions | handler function - Add serverOptions to ConnectionOptions type - Export ServerOptions from package typings - Improve error message when server receives packets without handleCommand configured
Two new API forms for creating MySQL servers:
Static handlers (pure data-in/data-out, no protocol concerns):
createServer({
async query(sql) { return db.query(sql); },
auth({ user }) { if (user !== 'admin') throw new Error('denied'); },
});
Factory function (per-connection state via closure):
createServer((connection) => ({
async query(sql) { return upstream.query(sql); },
}));
Handler return values are automatically serialized:
- Array of objects -> writeTextResult with inferred columns
- { rows, columns } -> writeTextResult with explicit columns
- { affectedRows, insertId } -> writeOk
- void -> writeOk
- Thrown error -> writeError
Implementation:
- lib/commands/server/ - ServerQuery, ServerPing, ServerQuit, ServerInitDb command classes
- buildHandleCommand() bridges high-level handlers to low-level handleCommand hook
- ServerHandshake yields to handleCommand after handshake when configured
- Comprehensive TypeScript types (ServerHandlers, ServerFactory, ServerResult)
- Integration tests for both API forms, auth, and backward compatibility
- Rewritten documentation with examples for all API styles
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refactor: Command-Based Server API with High-Level Handlers
Motivation
The current server API requires manual protocol handling: call
serverHandshake(), listen for'query'events, and manually serialize responses withwriteColumns()/writeTextRow()/writeEof(). This is low-level, verbose, and error-prone.This PR introduces a layered server API where the simplest use case is also the most concise:
API Design
Three API styles from simplest to most powerful:
1. Static handlers — pure
sql → datafunctionsHandlers have zero protocol surface. Return values are automatically serialized:
[{ id: 1 }]→ ResultSetHeader + ColumnDefinition + TextRow packets (columns inferred){ rows, columns }→ ResultSetHeader + explicit ColumnDefinition + TextRow packets{ affectedRows: 3, insertId: 10 }→ OK packetvoid→ OK packet2. Factory function — per-connection state via closure
Connection is available via closure — handler signatures stay clean.
3. Low-level
handleCommand— full protocol controlEach command is a
Commandsubclass (packet-driven state machine) — compose, test in isolation, handle multi-step protocols.The legacy
createServer(handler)+conn.serverHandshake()+conn.on('query')pattern is fully preserved.Architecture
What Changed
New:
lib/commands/server/— Server-side command classesServerQuery,ServerPing,ServerQuit,ServerInitDb— bridge user handlers to protocolsendResult— interprets handler return values, infers column definitions, callswriteXxxbuildHandleCommand— maps a handlers object to thehandleCommand(code) => CommandhookChanged:
index.js—createServer()detects four API shapes (legacy function, static handlers, factory, low-level options) and wires up handshake + handleCommand automaticallyChanged:
lib/commands/server_handshake.js—readClientReplyyields tohandleCommandafter handshake when configured (returnsnullinstead ofdispatchCommands)Changed:
lib/base/connection.js—handlePacket()dispatches tohandleCommandwhen server has no active command;_serverEncodinggetter for server write helpersChanged:
lib/commands/command.js— Server-side sequenceId bump only when responding to client packetChanged:
lib/packets/—Handshakesupports configurablegetSaltandauthPluginName;HandshakeResponseaccepts pre-calculatedauthToken;Query.fromPacket()for server-side deserializationNew: TypeScript types —
ServerHandlers,ServerFactory,ServerResult,AuthParams;createServer()overloadsNew:
test/integration/test-server-api.test.mts— 8 integration tests covering static handlers, factory function, auth accept/reject, error handling, backward compatibilityRewritten: Documentation —
website/docs/documentation/mysql-server.mdxandwebsite/docs/examples/tests/server.mdxwith comprehensive coverage of all API stylesRemaining Work