@andrew_l/binlog 0.3.22 → 0.4.1

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": "@andrew_l/binlog",
3
- "version": "0.3.22",
3
+ "version": "0.4.1",
4
4
  "description": "A high-performance binary logging system for Node.js applications.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -15,27 +15,28 @@
15
15
  "exports": {
16
16
  ".": {
17
17
  "import": "./dist/index.mjs",
18
- "require": "./dist/index.cjs"
18
+ "require": "./dist/index.mjs",
19
+ "types": "./dist/index.d.mts"
19
20
  }
20
21
  },
21
- "main": "./dist/index.cjs",
22
- "types": "./dist/index.d.ts",
22
+ "main": "./dist/index.mjs",
23
+ "types": "./dist/index.d.mts",
23
24
  "files": [
24
25
  "dist"
25
26
  ],
26
27
  "devDependencies": {
27
28
  "@types/node": "22.10.5",
28
- "typescript": "~5.8.3",
29
- "unbuild": "3.5.0",
29
+ "obuild": "^0.4.37",
30
+ "typescript": "6.0.3",
30
31
  "vitest": "^3.2.4"
31
32
  },
32
33
  "dependencies": {
33
- "@andrew_l/toolkit": "0.3.22",
34
- "@andrew_l/tl-pack": "0.3.22"
34
+ "@andrew_l/toolkit": "0.4.1",
35
+ "@andrew_l/tl-pack": "0.4.1"
35
36
  },
36
37
  "scripts": {
37
38
  "check-types": "tsc --noEmit",
38
- "build": "unbuild",
39
+ "build": "obuild",
39
40
  "test": "vitest run --typecheck",
40
41
  "test:watch": "vitest watch --typecheck"
41
42
  }
package/dist/index.cjs DELETED
@@ -1,326 +0,0 @@
1
- 'use strict';
2
-
3
- const toolkit = require('@andrew_l/toolkit');
4
- const tlPack = require('@andrew_l/tl-pack');
5
- const fs = require('node:fs');
6
- const path = require('node:path');
7
-
8
- function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
9
-
10
- const fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
11
- const path__default = /*#__PURE__*/_interopDefaultCompat(path);
12
-
13
- class Binlog {
14
- _options;
15
- _filePattern;
16
- _directory;
17
- _currentFile;
18
- _currentFileDescriptor;
19
- _currentFileSize;
20
- _currentFileIndex;
21
- _isOpen;
22
- _log;
23
- BINLOG_MAGIC = 1145197643;
24
- BINLOG_VERSION = 1;
25
- BINLOG_HEADER_SIZE = 16;
26
- BINLOG_ENTRY_HEADER_SIZE = 20;
27
- BINLOG_FLAG = Object.freeze({
28
- NONE: 0,
29
- TL: 1 << 0
30
- });
31
- constructor(options) {
32
- this._log = toolkit.logger("Binlog");
33
- this._options = {
34
- ...options,
35
- structures: options.structures ? [...options.structures] : []
36
- };
37
- this._filePattern = path__default.basename(options.path);
38
- this._directory = path__default.dirname(options.path);
39
- this._currentFile = null;
40
- this._currentFileDescriptor = null;
41
- this._currentFileSize = 0;
42
- this._currentFileIndex = 0;
43
- this._isOpen = false;
44
- }
45
- /**
46
- * Initialize the binlog system, ensuring directory exists and pick most recent binlog file
47
- * @returns Promise resolving to true if successful, false otherwise
48
- */
49
- init() {
50
- return Promise.resolve().then(() => fs__default.promises.mkdir(this._directory, { recursive: true })).then(() => this.#findLatestBinlogFile());
51
- }
52
- /**
53
- * Find the latest binlog file to continue writing
54
- */
55
- #findLatestBinlogFile() {
56
- return Promise.resolve().then(() => fs__default.promises.readdir(this._directory)).then((files) => {
57
- const fileRegEx = filePatternToRegex(this._filePattern);
58
- this._currentFileIndex = 0;
59
- for (const fileName of files) {
60
- const match = fileName.match(fileRegEx);
61
- if (match) {
62
- this._currentFileIndex = Math.max(
63
- this._currentFileIndex,
64
- parseInt(match[1], 10)
65
- );
66
- }
67
- }
68
- });
69
- }
70
- /**
71
- * Open the binlog for writing
72
- */
73
- open() {
74
- const filePath = path__default.join(this._directory, this.currentFileName);
75
- return Promise.resolve().then(() => fs__default.promises.open(filePath, "a+")).then((fileDescription) => {
76
- this._currentFileDescriptor = fileDescription;
77
- this._currentFile = filePath;
78
- return this._currentFileDescriptor.stat();
79
- }).then((fileStat) => {
80
- this._currentFileSize = fileStat.size;
81
- this._isOpen = true;
82
- if (this._currentFileSize === 0) {
83
- return this.#writeBinlogHeader();
84
- } else {
85
- return this.#checkBinlogHeaders(this._currentFileDescriptor).then(
86
- toolkit.noop
87
- );
88
- }
89
- });
90
- }
91
- /**
92
- * Close the current binlog file
93
- */
94
- close() {
95
- return Promise.resolve().then(() => {
96
- if (!this._isOpen || !this._currentFileDescriptor) {
97
- return;
98
- }
99
- return this._currentFileDescriptor.close();
100
- }).then(() => {
101
- this._currentFileDescriptor = null;
102
- this._currentFile = null;
103
- this._isOpen = false;
104
- });
105
- }
106
- /**
107
- * Write a binlog entry
108
- * @param opcode - Operation code
109
- * @param data - Data to write
110
- * @returns Promise resolving to true if successful, false otherwise
111
- */
112
- write(opcode, data) {
113
- let promise = Promise.resolve();
114
- if (!this._isOpen) {
115
- promise = promise.then(() => this.open());
116
- }
117
- return promise.then(() => {
118
- if (this._options.rotation && this._currentFileSize >= this._options.maxFileSize) {
119
- return this.rotate();
120
- }
121
- }).then(() => {
122
- toolkit.assert.ok(this._currentFileDescriptor, "File descriptor is null");
123
- let flags = this.BINLOG_FLAG.NONE;
124
- if (!Buffer.isBuffer(data)) {
125
- if (data instanceof tlPack.Structure) {
126
- data = tlPack.tlEncode(data);
127
- flags |= this.BINLOG_FLAG.TL;
128
- } else {
129
- data = tlPack.tlEncode(data);
130
- flags |= this.BINLOG_FLAG.TL;
131
- }
132
- }
133
- const dataLength = data.length;
134
- const totalLength = this.BINLOG_ENTRY_HEADER_SIZE + dataLength;
135
- const headerBuffer = Buffer.allocUnsafe(this.BINLOG_ENTRY_HEADER_SIZE);
136
- headerBuffer.writeUInt32LE(opcode, 0);
137
- headerBuffer.writeUInt32LE(flags, 4);
138
- headerBuffer.writeUInt32LE(toolkit.timestamp(), 8);
139
- headerBuffer.writeUInt32LE(dataLength, 12);
140
- headerBuffer.writeUInt32LE(
141
- toolkit.crc32(
142
- Buffer.concat([headerBuffer.subarray(0, 16), data])
143
- ) >>> 0,
144
- 16
145
- );
146
- return Promise.resolve().then(() => this._currentFileDescriptor.write(headerBuffer)).then(() => this._currentFileDescriptor.write(data)).then(() => {
147
- if (this._options.syncWrites) {
148
- return this._currentFileDescriptor.sync();
149
- }
150
- }).then(() => {
151
- this._currentFileSize += totalLength;
152
- });
153
- });
154
- }
155
- /**
156
- * Rotate the binlog file
157
- */
158
- rotate() {
159
- return Promise.resolve().then(() => this.close()).then(() => {
160
- this._currentFileIndex++;
161
- return this.open();
162
- });
163
- }
164
- /**
165
- * Write the binlog header
166
- */
167
- #writeBinlogHeader() {
168
- toolkit.assert.ok(this._currentFileDescriptor, "File descriptor is null");
169
- const headerBuffer = Buffer.allocUnsafe(this.BINLOG_HEADER_SIZE);
170
- headerBuffer.writeUInt32LE(this.BINLOG_MAGIC, 0);
171
- headerBuffer.writeUInt32LE(this.BINLOG_VERSION, 4);
172
- headerBuffer.writeUInt32LE(toolkit.timestamp(), 8);
173
- headerBuffer.writeUInt32LE(0, 12);
174
- return Promise.resolve().then(() => this._currentFileDescriptor.write(headerBuffer)).then(() => {
175
- this._currentFileSize += headerBuffer.length;
176
- if (this._options.syncWrites) {
177
- return this._currentFileDescriptor.sync();
178
- }
179
- });
180
- }
181
- /**
182
- * Read and parse all entries from a binlog file
183
- * @param filename - Binlog file to read
184
- * @param unsafe - Ignore broken binlog records otherwise throws error
185
- * @returns Array of parsed entries
186
- */
187
- readEntries(filename, unsafe) {
188
- var filepath = path__default.join(this._directory, filename);
189
- var fileHandle;
190
- var entries = [];
191
- return fs__default.promises.open(filepath, "r").then((_fileHandle) => {
192
- fileHandle = _fileHandle;
193
- return this.#checkBinlogHeaders(fileHandle);
194
- }).then((isValidHeader) => {
195
- if (!isValidHeader) {
196
- if (unsafe) {
197
- this._log.warn("Invalid binlog file format: " + filename);
198
- return;
199
- }
200
- return Promise.reject(
201
- new Error("Invalid binlog file format:\n" + filepath)
202
- );
203
- }
204
- return fileHandle.stat();
205
- }).then((stats) => {
206
- if (!stats) return;
207
- var contentSize = stats.size - this.BINLOG_HEADER_SIZE;
208
- var position = this.BINLOG_HEADER_SIZE;
209
- var headerBuffer = Buffer.allocUnsafe(this.BINLOG_ENTRY_HEADER_SIZE);
210
- return new Promise((resolve, reject) => {
211
- var processNextBatch = () => {
212
- if (position >= contentSize) {
213
- return resolve();
214
- }
215
- fileHandle.read(headerBuffer, 0, this.BINLOG_ENTRY_HEADER_SIZE, position).then(() => {
216
- var header = this.#readEntryHeader(headerBuffer, position);
217
- var dataBuffer = Buffer.allocUnsafe(header.dataLength);
218
- position += this.BINLOG_ENTRY_HEADER_SIZE;
219
- return fileHandle.read(dataBuffer, 0, header.dataLength, position).then(() => {
220
- var entry = this.#readEntry(
221
- headerBuffer,
222
- header,
223
- dataBuffer.subarray(0, header.dataLength)
224
- );
225
- if (!entry) {
226
- if (!unsafe) {
227
- return Promise.reject(
228
- new Error(
229
- `CRC mismatch at position ${position - this.BINLOG_ENTRY_HEADER_SIZE}`
230
- )
231
- );
232
- } else {
233
- this._log.warn(
234
- `CRC mismatch at position ${position - this.BINLOG_ENTRY_HEADER_SIZE}`
235
- );
236
- }
237
- } else {
238
- entries.push(entry);
239
- }
240
- position += header.dataLength;
241
- }).then(() => processNextBatch()).catch(reject);
242
- });
243
- };
244
- processNextBatch();
245
- });
246
- }).then(() => fileHandle?.close()).then(() => entries).catch((error) => {
247
- return fileHandle.close().then(() => Promise.reject(error));
248
- });
249
- }
250
- #readEntryHeader(buffer, position) {
251
- return {
252
- opcode: buffer.readUInt32LE(0),
253
- flags: buffer.readUInt32LE(4),
254
- timestamp: buffer.readUInt32LE(8),
255
- dataLength: buffer.readUInt32LE(12),
256
- crc: buffer.readUInt32LE(16),
257
- position
258
- };
259
- }
260
- #readEntry(headerBuffer, header, dataBuffer) {
261
- var crc = toolkit.crc32([headerBuffer.subarray(0, 16), dataBuffer]) >>> 0;
262
- if (crc !== header.crc) {
263
- return null;
264
- }
265
- var data;
266
- if (toolkit.checkBitmask(header.flags, this.BINLOG_FLAG.TL)) {
267
- data = tlPack.tlDecode(dataBuffer, {
268
- structures: this._options.structures
269
- });
270
- } else {
271
- data = Buffer.from(dataBuffer);
272
- }
273
- return {
274
- opcode: header.opcode,
275
- timestamp: header.timestamp,
276
- data,
277
- position: header.position
278
- };
279
- }
280
- #checkBinlogHeaders(fileHandle) {
281
- var headerBuffer = Buffer.allocUnsafe(this.BINLOG_HEADER_SIZE);
282
- return Promise.resolve().then(() => fileHandle.read(headerBuffer, 0, this.BINLOG_HEADER_SIZE, 0)).then(() => {
283
- var magic = headerBuffer.readUInt32LE(0);
284
- var version = headerBuffer.readUInt32LE(4);
285
- return magic === this.BINLOG_MAGIC && version === this.BINLOG_VERSION;
286
- });
287
- }
288
- /**
289
- * Get the current binlog file index
290
- */
291
- get currentFileIndex() {
292
- return this._currentFileIndex;
293
- }
294
- /**
295
- * Get current binlog file name
296
- */
297
- get currentFileName() {
298
- return this._filePattern.replaceAll(
299
- "{index}",
300
- String(this._currentFileIndex)
301
- );
302
- }
303
- /**
304
- * Get current binlog directory
305
- */
306
- get directory() {
307
- return this._directory;
308
- }
309
- }
310
- function filePatternToRegex(value) {
311
- return new RegExp(value.replaceAll("{index}", "(\\d+)"));
312
- }
313
-
314
- const DEF_OPTIONS = {
315
- path: "./binlogs/log-{index}.bin",
316
- maxFileSize: 104857600,
317
- rotation: true,
318
- syncWrites: true
319
- };
320
- function createBinlog(options) {
321
- return new Binlog(toolkit.deepDefaults(options, DEF_OPTIONS));
322
- }
323
-
324
- exports.Binlog = Binlog;
325
- exports.createBinlog = createBinlog;
326
- //# sourceMappingURL=index.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/Binlog.ts","../src/index.ts"],"sourcesContent":["import { Structure, tlDecode, tlEncode } from '@andrew_l/tl-pack';\nimport {\n type Logger,\n assert,\n checkBitmask,\n crc32,\n logger,\n noop,\n timestamp,\n} from '@andrew_l/toolkit';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\n/**\n * Options for configuring the KdbBinlog\n */\nexport interface BinlogOptions {\n /**\n * File location to store binlog files\n * @default './binlogs/log-{index}.bin'\n */\n path: string;\n\n /**\n * Maximum size of each binlog file before rotation (in bytes)\n * @default 104857600\n */\n maxFileSize: number;\n\n /**\n * Whether to enable log rotation\n * @default true\n */\n rotation: boolean;\n\n /**\n * Whether to sync writes to disk immediately\n * @default true\n */\n syncWrites: boolean;\n\n structures?: Structure.Constructor[];\n}\n\n/**\n * Represents a single binlog entry\n */\nexport interface BinlogEntry<TData = Buffer> {\n /**\n * Operation code defining the type of operation\n */\n opcode: number;\n\n /**\n * Unix timestamp when the entry was created\n */\n timestamp: number;\n\n /**\n * Binary data of the entry\n */\n data: TData | Buffer;\n\n /**\n * Position in the file where this entry starts\n */\n position: number;\n}\n\ninterface EntryHeader {\n opcode: number;\n flags: number;\n timestamp: number;\n dataLength: number;\n crc: number;\n position: number;\n}\n\n/**\n * TypeScript implementation of binlog system\n * Adapted from https://github.com/vk-com/kphp-kdb/blob/master/binlog/kdb-binlog-common.c\n * @group Main\n */\nexport class Binlog {\n private _options: Required<BinlogOptions>;\n private _filePattern: string;\n private _directory: string;\n private _currentFile: string | null;\n private _currentFileDescriptor: fs.promises.FileHandle | null;\n private _currentFileSize: number;\n private _currentFileIndex: number;\n private _isOpen: boolean;\n private _log: Logger;\n\n private readonly BINLOG_MAGIC: number = 0x4442544b;\n private readonly BINLOG_VERSION: number = 1;\n private readonly BINLOG_HEADER_SIZE: number = 16;\n private readonly BINLOG_ENTRY_HEADER_SIZE: number = 20;\n private readonly BINLOG_FLAG = Object.freeze({\n NONE: 0,\n TL: 1 << 0,\n } as const);\n\n constructor(options: BinlogOptions) {\n this._log = logger('Binlog');\n this._options = {\n ...options,\n structures: options.structures ? [...options.structures] : [],\n };\n this._filePattern = path.basename(options.path);\n this._directory = path.dirname(options.path);\n this._currentFile = null;\n this._currentFileDescriptor = null;\n this._currentFileSize = 0;\n this._currentFileIndex = 0;\n this._isOpen = false;\n }\n\n /**\n * Initialize the binlog system, ensuring directory exists and pick most recent binlog file\n * @returns Promise resolving to true if successful, false otherwise\n */\n public init(): Promise<void> {\n return Promise.resolve()\n .then(() => fs.promises.mkdir(this._directory, { recursive: true }))\n .then(() => this.#findLatestBinlogFile());\n }\n\n /**\n * Find the latest binlog file to continue writing\n */\n #findLatestBinlogFile(): Promise<void> {\n return Promise.resolve()\n .then(() => fs.promises.readdir(this._directory))\n .then(files => {\n const fileRegEx = filePatternToRegex(this._filePattern);\n\n this._currentFileIndex = 0;\n\n for (const fileName of files) {\n const match = fileName.match(fileRegEx);\n\n if (match) {\n this._currentFileIndex = Math.max(\n this._currentFileIndex,\n parseInt(match[1], 10),\n );\n }\n }\n });\n }\n\n /**\n * Open the binlog for writing\n */\n public open(): Promise<void> {\n const filePath = path.join(this._directory, this.currentFileName);\n\n return Promise.resolve()\n .then(() => fs.promises.open(filePath, 'a+'))\n .then(fileDescription => {\n this._currentFileDescriptor = fileDescription;\n this._currentFile = filePath;\n\n return this._currentFileDescriptor.stat();\n })\n .then(fileStat => {\n this._currentFileSize = fileStat.size;\n this._isOpen = true;\n\n // Write the binlog header\n if (this._currentFileSize === 0) {\n return this.#writeBinlogHeader();\n } else {\n return this.#checkBinlogHeaders(this._currentFileDescriptor!).then(\n noop,\n );\n }\n });\n }\n\n /**\n * Close the current binlog file\n */\n public close(): Promise<void> {\n return Promise.resolve()\n .then(() => {\n if (!this._isOpen || !this._currentFileDescriptor) {\n return;\n }\n\n return this._currentFileDescriptor.close();\n })\n .then(() => {\n this._currentFileDescriptor = null;\n this._currentFile = null;\n this._isOpen = false;\n });\n }\n\n /**\n * Write a binlog entry\n * @param opcode - Operation code\n * @param data - Data to write\n * @returns Promise resolving to true if successful, false otherwise\n */\n public write(opcode: number, data: unknown): Promise<void> {\n let promise = Promise.resolve();\n\n if (!this._isOpen) {\n promise = promise.then(() => this.open());\n }\n\n // Check if we need to rotate the file\n return promise\n .then(() => {\n if (\n this._options.rotation &&\n this._currentFileSize >= this._options.maxFileSize\n ) {\n return this.rotate();\n }\n })\n .then(() => {\n assert.ok(this._currentFileDescriptor, 'File descriptor is null');\n\n let flags = this.BINLOG_FLAG.NONE;\n\n if (!Buffer.isBuffer(data)) {\n if (data instanceof Structure) {\n data = tlEncode(data);\n flags |= this.BINLOG_FLAG.TL;\n } else {\n data = tlEncode(data) as Buffer;\n flags |= this.BINLOG_FLAG.TL;\n }\n }\n\n // Create entry header\n const dataLength = (data as Buffer).length;\n const totalLength = this.BINLOG_ENTRY_HEADER_SIZE + dataLength;\n\n const headerBuffer = Buffer.allocUnsafe(this.BINLOG_ENTRY_HEADER_SIZE);\n headerBuffer.writeUInt32LE(opcode, 0);\n headerBuffer.writeUInt32LE(flags, 4);\n headerBuffer.writeUInt32LE(timestamp(), 8);\n headerBuffer.writeUInt32LE(dataLength, 12);\n\n headerBuffer.writeUInt32LE(\n crc32(\n Buffer.concat([headerBuffer.subarray(0, 16), data as Buffer]),\n ) >>> 0,\n 16,\n );\n\n // Write the entry\n return Promise.resolve()\n .then(() => this._currentFileDescriptor!.write(headerBuffer))\n .then(() => this._currentFileDescriptor!.write(data as Buffer))\n .then(() => {\n if (this._options.syncWrites) {\n return this._currentFileDescriptor!.sync();\n }\n })\n .then(() => {\n this._currentFileSize += totalLength;\n });\n });\n }\n\n /**\n * Rotate the binlog file\n */\n public rotate(): Promise<void> {\n return Promise.resolve()\n .then(() => this.close())\n .then(() => {\n this._currentFileIndex++;\n return this.open();\n });\n }\n\n /**\n * Write the binlog header\n */\n #writeBinlogHeader(): Promise<void> {\n assert.ok(this._currentFileDescriptor, 'File descriptor is null');\n\n const headerBuffer = Buffer.allocUnsafe(this.BINLOG_HEADER_SIZE);\n\n headerBuffer.writeUInt32LE(this.BINLOG_MAGIC, 0);\n headerBuffer.writeUInt32LE(this.BINLOG_VERSION, 4);\n headerBuffer.writeUInt32LE(timestamp(), 8);\n headerBuffer.writeUInt32LE(0, 12); // Reserved field\n\n return Promise.resolve()\n .then(() => this._currentFileDescriptor!.write(headerBuffer))\n .then(() => {\n this._currentFileSize += headerBuffer.length;\n\n if (this._options.syncWrites) {\n return this._currentFileDescriptor!.sync();\n }\n });\n }\n\n /**\n * Read and parse all entries from a binlog file\n * @param filename - Binlog file to read\n * @param unsafe - Ignore broken binlog records otherwise throws error\n * @returns Array of parsed entries\n */\n public readEntries<TData = Buffer>(\n filename: string,\n unsafe?: boolean,\n ): Promise<BinlogEntry<TData>[]> {\n var filepath = path.join(this._directory, filename);\n var fileHandle: fs.promises.FileHandle;\n var entries: BinlogEntry<TData>[] = [];\n\n return fs.promises\n .open(filepath, 'r')\n .then(_fileHandle => {\n fileHandle = _fileHandle;\n return this.#checkBinlogHeaders(fileHandle);\n })\n .then(isValidHeader => {\n if (!isValidHeader) {\n if (unsafe) {\n this._log.warn('Invalid binlog file format: ' + filename);\n return;\n }\n return Promise.reject(\n new Error('Invalid binlog file format:\\n' + filepath),\n );\n }\n\n return fileHandle.stat();\n })\n .then(stats => {\n if (!stats) return;\n\n var contentSize = stats.size - this.BINLOG_HEADER_SIZE;\n var position = this.BINLOG_HEADER_SIZE;\n var headerBuffer = Buffer.allocUnsafe(this.BINLOG_ENTRY_HEADER_SIZE);\n\n return new Promise<void>((resolve, reject) => {\n var processNextBatch = () => {\n if (position >= contentSize) {\n return resolve();\n }\n\n fileHandle\n .read(headerBuffer, 0, this.BINLOG_ENTRY_HEADER_SIZE, position)\n .then(() => {\n var header = this.#readEntryHeader(headerBuffer, position);\n var dataBuffer = Buffer.allocUnsafe(header.dataLength);\n\n position += this.BINLOG_ENTRY_HEADER_SIZE;\n\n return fileHandle\n .read(dataBuffer, 0, header.dataLength, position)\n .then(() => {\n var entry = this.#readEntry(\n headerBuffer,\n header,\n dataBuffer.subarray(0, header.dataLength),\n );\n\n if (!entry) {\n if (!unsafe) {\n return Promise.reject(\n new Error(\n `CRC mismatch at position ${position - this.BINLOG_ENTRY_HEADER_SIZE}`,\n ),\n );\n } else {\n this._log.warn(\n `CRC mismatch at position ${position - this.BINLOG_ENTRY_HEADER_SIZE}`,\n );\n }\n } else {\n entries.push(entry);\n }\n\n position += header.dataLength;\n })\n .then(() => processNextBatch())\n .catch(reject);\n });\n };\n\n processNextBatch();\n });\n })\n .then(() => fileHandle?.close())\n .then(() => entries)\n .catch(error => {\n return fileHandle.close().then(() => Promise.reject(error));\n });\n }\n\n #readEntryHeader(buffer: Buffer, position: number): EntryHeader {\n return {\n opcode: buffer.readUInt32LE(0),\n flags: buffer.readUInt32LE(4),\n timestamp: buffer.readUInt32LE(8),\n dataLength: buffer.readUInt32LE(12),\n crc: buffer.readUInt32LE(16),\n position,\n };\n }\n\n #readEntry(\n headerBuffer: Buffer,\n header: EntryHeader,\n dataBuffer: Buffer,\n ): BinlogEntry<any> | null {\n // Verify CRC\n var crc = crc32([headerBuffer.subarray(0, 16), dataBuffer]) >>> 0;\n\n if (crc !== header.crc) {\n return null;\n }\n\n var data: any;\n\n if (checkBitmask(header.flags, this.BINLOG_FLAG.TL)) {\n data = tlDecode(dataBuffer, {\n structures: this._options.structures,\n });\n } else {\n // Make copy\n data = Buffer.from(dataBuffer);\n }\n\n return {\n opcode: header.opcode,\n timestamp: header.timestamp,\n data: data,\n position: header.position,\n };\n }\n\n #checkBinlogHeaders(fileHandle: fs.promises.FileHandle): Promise<boolean> {\n var headerBuffer = Buffer.allocUnsafe(this.BINLOG_HEADER_SIZE);\n\n return Promise.resolve()\n .then(() => fileHandle.read(headerBuffer, 0, this.BINLOG_HEADER_SIZE, 0))\n .then(() => {\n var magic = headerBuffer.readUInt32LE(0);\n var version = headerBuffer.readUInt32LE(4);\n\n return magic === this.BINLOG_MAGIC && version === this.BINLOG_VERSION;\n });\n }\n\n /**\n * Get the current binlog file index\n */\n get currentFileIndex(): number {\n return this._currentFileIndex;\n }\n\n /**\n * Get current binlog file name\n */\n get currentFileName(): string {\n return this._filePattern.replaceAll(\n '{index}',\n String(this._currentFileIndex),\n );\n }\n\n /**\n * Get current binlog directory\n */\n get directory(): string {\n return this._directory;\n }\n}\n\nfunction filePatternToRegex(value: string): RegExp {\n return new RegExp(value.replaceAll('{index}', '(\\\\d+)'));\n}\n","import { deepDefaults } from '@andrew_l/toolkit';\nimport { Binlog, type BinlogOptions } from './Binlog.js';\n\nexport * from './Binlog.js';\n\nconst DEF_OPTIONS: BinlogOptions = {\n path: './binlogs/log-{index}.bin',\n maxFileSize: 104857600,\n rotation: true,\n syncWrites: true,\n};\n\n/**\n * Create binlog instance\n * @group Main\n */\nexport function createBinlog(options: Partial<BinlogOptions>): Binlog {\n return new Binlog(deepDefaults(options, DEF_OPTIONS));\n}\n"],"names":["logger","path","fs","noop","assert","Structure","tlEncode","timestamp","crc32","checkBitmask","tlDecode","deepDefaults"],"mappings":"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"}
package/dist/index.d.cts DELETED
@@ -1,123 +0,0 @@
1
- import { Structure } from '@andrew_l/tl-pack';
2
-
3
- /**
4
- * Options for configuring the KdbBinlog
5
- */
6
- interface BinlogOptions {
7
- /**
8
- * File location to store binlog files
9
- * @default './binlogs/log-{index}.bin'
10
- */
11
- path: string;
12
- /**
13
- * Maximum size of each binlog file before rotation (in bytes)
14
- * @default 104857600
15
- */
16
- maxFileSize: number;
17
- /**
18
- * Whether to enable log rotation
19
- * @default true
20
- */
21
- rotation: boolean;
22
- /**
23
- * Whether to sync writes to disk immediately
24
- * @default true
25
- */
26
- syncWrites: boolean;
27
- structures?: Structure.Constructor[];
28
- }
29
- /**
30
- * Represents a single binlog entry
31
- */
32
- interface BinlogEntry<TData = Buffer> {
33
- /**
34
- * Operation code defining the type of operation
35
- */
36
- opcode: number;
37
- /**
38
- * Unix timestamp when the entry was created
39
- */
40
- timestamp: number;
41
- /**
42
- * Binary data of the entry
43
- */
44
- data: TData | Buffer;
45
- /**
46
- * Position in the file where this entry starts
47
- */
48
- position: number;
49
- }
50
- /**
51
- * TypeScript implementation of binlog system
52
- * Adapted from https://github.com/vk-com/kphp-kdb/blob/master/binlog/kdb-binlog-common.c
53
- * @group Main
54
- */
55
- declare class Binlog {
56
- #private;
57
- private _options;
58
- private _filePattern;
59
- private _directory;
60
- private _currentFile;
61
- private _currentFileDescriptor;
62
- private _currentFileSize;
63
- private _currentFileIndex;
64
- private _isOpen;
65
- private _log;
66
- private readonly BINLOG_MAGIC;
67
- private readonly BINLOG_VERSION;
68
- private readonly BINLOG_HEADER_SIZE;
69
- private readonly BINLOG_ENTRY_HEADER_SIZE;
70
- private readonly BINLOG_FLAG;
71
- constructor(options: BinlogOptions);
72
- /**
73
- * Initialize the binlog system, ensuring directory exists and pick most recent binlog file
74
- * @returns Promise resolving to true if successful, false otherwise
75
- */
76
- init(): Promise<void>;
77
- /**
78
- * Open the binlog for writing
79
- */
80
- open(): Promise<void>;
81
- /**
82
- * Close the current binlog file
83
- */
84
- close(): Promise<void>;
85
- /**
86
- * Write a binlog entry
87
- * @param opcode - Operation code
88
- * @param data - Data to write
89
- * @returns Promise resolving to true if successful, false otherwise
90
- */
91
- write(opcode: number, data: unknown): Promise<void>;
92
- /**
93
- * Rotate the binlog file
94
- */
95
- rotate(): Promise<void>;
96
- /**
97
- * Read and parse all entries from a binlog file
98
- * @param filename - Binlog file to read
99
- * @param unsafe - Ignore broken binlog records otherwise throws error
100
- * @returns Array of parsed entries
101
- */
102
- readEntries<TData = Buffer>(filename: string, unsafe?: boolean): Promise<BinlogEntry<TData>[]>;
103
- /**
104
- * Get the current binlog file index
105
- */
106
- get currentFileIndex(): number;
107
- /**
108
- * Get current binlog file name
109
- */
110
- get currentFileName(): string;
111
- /**
112
- * Get current binlog directory
113
- */
114
- get directory(): string;
115
- }
116
-
117
- /**
118
- * Create binlog instance
119
- * @group Main
120
- */
121
- declare function createBinlog(options: Partial<BinlogOptions>): Binlog;
122
-
123
- export { Binlog, type BinlogEntry, type BinlogOptions, createBinlog };
package/dist/index.d.ts DELETED
@@ -1,123 +0,0 @@
1
- import { Structure } from '@andrew_l/tl-pack';
2
-
3
- /**
4
- * Options for configuring the KdbBinlog
5
- */
6
- interface BinlogOptions {
7
- /**
8
- * File location to store binlog files
9
- * @default './binlogs/log-{index}.bin'
10
- */
11
- path: string;
12
- /**
13
- * Maximum size of each binlog file before rotation (in bytes)
14
- * @default 104857600
15
- */
16
- maxFileSize: number;
17
- /**
18
- * Whether to enable log rotation
19
- * @default true
20
- */
21
- rotation: boolean;
22
- /**
23
- * Whether to sync writes to disk immediately
24
- * @default true
25
- */
26
- syncWrites: boolean;
27
- structures?: Structure.Constructor[];
28
- }
29
- /**
30
- * Represents a single binlog entry
31
- */
32
- interface BinlogEntry<TData = Buffer> {
33
- /**
34
- * Operation code defining the type of operation
35
- */
36
- opcode: number;
37
- /**
38
- * Unix timestamp when the entry was created
39
- */
40
- timestamp: number;
41
- /**
42
- * Binary data of the entry
43
- */
44
- data: TData | Buffer;
45
- /**
46
- * Position in the file where this entry starts
47
- */
48
- position: number;
49
- }
50
- /**
51
- * TypeScript implementation of binlog system
52
- * Adapted from https://github.com/vk-com/kphp-kdb/blob/master/binlog/kdb-binlog-common.c
53
- * @group Main
54
- */
55
- declare class Binlog {
56
- #private;
57
- private _options;
58
- private _filePattern;
59
- private _directory;
60
- private _currentFile;
61
- private _currentFileDescriptor;
62
- private _currentFileSize;
63
- private _currentFileIndex;
64
- private _isOpen;
65
- private _log;
66
- private readonly BINLOG_MAGIC;
67
- private readonly BINLOG_VERSION;
68
- private readonly BINLOG_HEADER_SIZE;
69
- private readonly BINLOG_ENTRY_HEADER_SIZE;
70
- private readonly BINLOG_FLAG;
71
- constructor(options: BinlogOptions);
72
- /**
73
- * Initialize the binlog system, ensuring directory exists and pick most recent binlog file
74
- * @returns Promise resolving to true if successful, false otherwise
75
- */
76
- init(): Promise<void>;
77
- /**
78
- * Open the binlog for writing
79
- */
80
- open(): Promise<void>;
81
- /**
82
- * Close the current binlog file
83
- */
84
- close(): Promise<void>;
85
- /**
86
- * Write a binlog entry
87
- * @param opcode - Operation code
88
- * @param data - Data to write
89
- * @returns Promise resolving to true if successful, false otherwise
90
- */
91
- write(opcode: number, data: unknown): Promise<void>;
92
- /**
93
- * Rotate the binlog file
94
- */
95
- rotate(): Promise<void>;
96
- /**
97
- * Read and parse all entries from a binlog file
98
- * @param filename - Binlog file to read
99
- * @param unsafe - Ignore broken binlog records otherwise throws error
100
- * @returns Array of parsed entries
101
- */
102
- readEntries<TData = Buffer>(filename: string, unsafe?: boolean): Promise<BinlogEntry<TData>[]>;
103
- /**
104
- * Get the current binlog file index
105
- */
106
- get currentFileIndex(): number;
107
- /**
108
- * Get current binlog file name
109
- */
110
- get currentFileName(): string;
111
- /**
112
- * Get current binlog directory
113
- */
114
- get directory(): string;
115
- }
116
-
117
- /**
118
- * Create binlog instance
119
- * @group Main
120
- */
121
- declare function createBinlog(options: Partial<BinlogOptions>): Binlog;
122
-
123
- export { Binlog, type BinlogEntry, type BinlogOptions, createBinlog };