dbgate-mssql-dumper
v0.1.14
Published
Standalone, client-agnostic Microsoft SQL Server SQL dump and restore library for Node.js
Maintainers
Readme
dbgate-mssql-dumper
Standalone, client-agnostic Microsoft SQL Server SQL dump and restore library for Node.js.
Produces a deterministic, restorable plain .sql file and restores it back —
using only a TDS connection. No sqlcmd, no SMO, no bcp, no external
process is ever invoked. Framework-independent: it does not depend on DbGate
internals and works outside DbGate.
- Node.js >= 20, ESM and CJS builds, full TypeScript types
tediousis an optional peer dependency, reachable only through the separatedbgate-mssql-dumper/tediousentry point — the core package never imports a driver- Round-trip verified against a real SQL Server: dump → restore → introspect → compare schema and data semantics (see docs/round-trip-testing.md)
Install
npm install dbgate-mssql-dumper
# optional, for the bundled Tedious adapter:
npm install tediousQuick start
Dump
import { createWriteStream } from 'node:fs';
import { dumpMssql } from 'dbgate-mssql-dumper';
import { fromTediousConnection } from 'dbgate-mssql-dumper/tedious';
import { Connection } from 'tedious';
const tedious = new Connection({
server: 'localhost',
authentication: { type: 'default', options: { userName: 'sa', password: '…' } },
options: { database: 'MyDatabase', trustServerCertificate: true },
});
await new Promise<void>((resolve, reject) =>
tedious.connect(error => (error ? reject(error) : resolve())),
);
const connection = fromTediousConnection(tedious);
const result = await dumpMssql(connection, { mode: 'full' }, createWriteStream('dump.sql'), event =>
console.log(event.phase, event.objectsProcessed ?? '', event.bytesWritten ?? ''),
);
console.log(`${result.rowsExported} rows, ${result.bytesWritten} bytes`);
for (const warning of result.warnings) {
console.warn(`[${warning.severity}] ${warning.code}: ${warning.message}`);
}Restore
import { createReadStream } from 'node:fs';
import { restoreSqlDump } from 'dbgate-mssql-dumper';
const result = await restoreSqlDump({
connection,
source: createReadStream('dump.sql'),
progress: event => console.log(event.phase, event.batchIndex, event.rowsRestored),
});
console.log(`${result.batchesExecuted} batches, ${result.rowsRestored} rows`);
for (const error of result.errors) {
console.error(`batch ${error.batchIndex} (line ${error.location.startLine}): ${error.message}`);
console.error(` ${error.sqlPreview}`); // truncated and credential-redacted
}source accepts a string, a Readable, or any AsyncIterable of text or
Buffer chunks. Input is parsed incrementally, so restoring a multi-gigabyte
dump does not read it into memory.
Public API
| Function | Purpose |
| ---------------------------------------------------------------------- | ------------------------------------------------------------------- |
| dumpMssql(connection, options, output, onProgress?, signal?) | Full pipeline: introspect → plan → render schema → stream data |
| restoreSqlDump({ connection, source, options?, signal?, progress? }) | Parse GO batches; bulk-load generated INSERTs when available |
| introspectMssql(connection, options?, signal?) | Normalized MssqlDatabase model + version/capabilities/diagnostics |
| inspectDumpArchive(database, options?) | Pure dependency planning → ordered ArchiveEntry[] |
| renderPlainSql(request) | Pure model → plain T-SQL text (never touches the network) |
| exportTableDataAsInserts(request) | Stream one table's rows as batched INSERT statements |
| preflightRestore(request) | Detect the restore target's version/capabilities |
| isDumperSqlDump(sample) | Cheap check that input looks like this package's own dump |
| parseSqlBatches(sql) / streamSqlBatches(source) | The GO batch lexer, usable on its own |
| fromTediousConnection(connection) | Adapter (from dbgate-mssql-dumper/tedious) |
| connectTedious(config) | Convenience creator (from dbgate-mssql-dumper/tedious) |
Each stage is independently usable: inspectDumpArchive and renderPlainSql
are pure functions of the model and need no connection at all.
Documentation
| Document | Contents |
| ------------------------------------------------------------ | ----------------------------------------------------------------------- |
| docs/dump-api.md | dumpMssql options, modes, progress, diagnostics, batching |
| docs/restore-api.md | restoreSqlDump, the GO lexer, typed errors, supported script subset |
| docs/tedious-adapter.md | Connection ownership, backpressure, batch execution, pools |
| docs/supported-objects.md | Object kinds: dumped / restored / tested |
| docs/supported-data-types.md | Per-type serialization and round-trip fidelity |
| docs/known-limitations.md | What this package does not do, and why |
| docs/round-trip-testing.md | Running the Docker-backed integration suite |
| docs/architecture.md | Layer-by-layer design and the reasoning behind it |
| docs/coverage.md | Implementation coverage table |
Why GO, not semicolons
SQL Server client scripts use GO as a batch separator, and GO itself is
never sent to the server. Splitting a T-SQL script on semicolons is wrong:
CREATE PROCEDURE/VIEW/FUNCTION/TRIGGER must each be alone in their
batch, and a semicolon inside a module body does not end it.
This package ships a real incremental lexer, so GO is recognized only when it
is genuinely a standalone separator — never inside a string, a bracketed or
double-quoted identifier, a -- comment, or a (possibly nested) /* */ block
comment, including when those span lines or arrive split across stream chunks:
PRINT 'GO'; -- not a separator
/*
GO
*/ -- not a separator
GO -- a separatorDevelopment
npm install
npm run typecheck
npm run lint
npm test # unit tests, no Docker or network needed
npm run docker:up # start SQL Server 2022 on port 14330
npm run test:integration # round-trip tests against it
npm run docker:down
npm run test:package # builds, then smoke-tests dist/ as ESM and CJSIntegration tests skip themselves with a clear message when no server is
reachable; set MSSQL_TEST_REQUIRED=1 (as CI should) to make that a hard
failure instead.
License
GPL-3.0-only
