crous 1.0.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/LICENSE +21 -0
- package/README.md +413 -0
- package/binding.gyp +50 -0
- package/index.d.ts +358 -0
- package/index.js +290 -0
- package/package.json +57 -0
- package/src/crous_node.c +819 -0
package/index.d.ts
ADDED
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Crous - High-performance binary serialization for Node.js
|
|
3
|
+
*
|
|
4
|
+
* TypeScript type definitions for the Crous serialization library.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Custom error class for Crous-related errors
|
|
11
|
+
*/
|
|
12
|
+
export class CrousError extends Error {
|
|
13
|
+
constructor(message: string);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Error thrown during encoding/serialization
|
|
18
|
+
*/
|
|
19
|
+
export class CrousEncodeError extends CrousError {
|
|
20
|
+
constructor(message: string);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Error thrown during decoding/deserialization
|
|
25
|
+
*/
|
|
26
|
+
export class CrousDecodeError extends CrousError {
|
|
27
|
+
constructor(message: string);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Function type for custom serializers
|
|
32
|
+
* @template T - The type being serialized
|
|
33
|
+
*/
|
|
34
|
+
export type SerializerFunction<T = any> = (obj: T) => any;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Function type for custom decoders
|
|
38
|
+
* @template T - The type being deserialized
|
|
39
|
+
*/
|
|
40
|
+
export type DecoderFunction<T = any> = (value: any) => T;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Function type for object hooks (post-processing dictionaries)
|
|
44
|
+
*/
|
|
45
|
+
export type ObjectHook = (obj: Record<string, any>) => any;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Function type for default serializer fallback
|
|
49
|
+
*/
|
|
50
|
+
export type DefaultFunction = (obj: any) => any;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Options for dumps() function
|
|
54
|
+
*/
|
|
55
|
+
export interface DumpsOptions {
|
|
56
|
+
/**
|
|
57
|
+
* Optional function to handle custom types that aren't natively supported
|
|
58
|
+
*/
|
|
59
|
+
default?: DefaultFunction;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Whether to allow custom serializers (default: true)
|
|
63
|
+
*/
|
|
64
|
+
allowCustom?: boolean;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Options for loads() function
|
|
69
|
+
*/
|
|
70
|
+
export interface LoadsOptions {
|
|
71
|
+
/**
|
|
72
|
+
* Optional function to post-process dictionary objects during deserialization
|
|
73
|
+
*/
|
|
74
|
+
objectHook?: ObjectHook;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Options for dump() function
|
|
79
|
+
*/
|
|
80
|
+
export interface DumpOptions extends DumpsOptions {
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Options for load() function
|
|
85
|
+
*/
|
|
86
|
+
export interface LoadOptions extends LoadsOptions {
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Encoder class for custom serialization control
|
|
91
|
+
*/
|
|
92
|
+
export class CrousEncoder {
|
|
93
|
+
/**
|
|
94
|
+
* Create a new encoder instance
|
|
95
|
+
* @param options - Encoder options
|
|
96
|
+
*/
|
|
97
|
+
constructor(options?: {
|
|
98
|
+
default?: DefaultFunction;
|
|
99
|
+
allowCustom?: boolean;
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Encode an object to binary format
|
|
104
|
+
* @param obj - The object to encode
|
|
105
|
+
* @returns Binary encoded data
|
|
106
|
+
*/
|
|
107
|
+
encode(obj: any): Buffer;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Decoder class for custom deserialization control
|
|
112
|
+
*/
|
|
113
|
+
export class CrousDecoder {
|
|
114
|
+
/**
|
|
115
|
+
* Create a new decoder instance
|
|
116
|
+
* @param options - Decoder options
|
|
117
|
+
*/
|
|
118
|
+
constructor(options?: {
|
|
119
|
+
objectHook?: ObjectHook;
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Decode binary data to an object
|
|
124
|
+
* @param data - The binary data to decode
|
|
125
|
+
* @returns Deserialized object
|
|
126
|
+
*/
|
|
127
|
+
decode(data: Buffer): any;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Version information structure
|
|
132
|
+
*/
|
|
133
|
+
export interface VersionInfo {
|
|
134
|
+
major: number;
|
|
135
|
+
minor: number;
|
|
136
|
+
patch: number;
|
|
137
|
+
string: string;
|
|
138
|
+
tuple: [number, number, number];
|
|
139
|
+
hex: number;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Serialize a JavaScript value to binary format
|
|
144
|
+
*
|
|
145
|
+
* @param obj - The object to serialize
|
|
146
|
+
* @param options - Serialization options
|
|
147
|
+
* @returns Binary encoded data as a Buffer
|
|
148
|
+
* @throws {CrousEncodeError} If encoding fails
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* ```typescript
|
|
152
|
+
* import { dumps } from 'crous';
|
|
153
|
+
*
|
|
154
|
+
* const data = { name: 'Alice', age: 30 };
|
|
155
|
+
* const binary = dumps(data);
|
|
156
|
+
* console.log(binary); // <Buffer ...>
|
|
157
|
+
* ```
|
|
158
|
+
*/
|
|
159
|
+
export function dumps(obj: any, options?: DumpsOptions): Buffer;
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Deserialize binary data to a JavaScript value
|
|
163
|
+
*
|
|
164
|
+
* @param data - Binary data to deserialize
|
|
165
|
+
* @param options - Deserialization options
|
|
166
|
+
* @returns Deserialized JavaScript value
|
|
167
|
+
* @throws {CrousDecodeError} If decoding fails
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* ```typescript
|
|
171
|
+
* import { loads, dumps } from 'crous';
|
|
172
|
+
*
|
|
173
|
+
* const binary = dumps({ name: 'Alice' });
|
|
174
|
+
* const data = loads(binary);
|
|
175
|
+
* console.log(data); // { name: 'Alice' }
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
export function loads(data: Buffer, options?: LoadsOptions): any;
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Serialize a JavaScript value and write to a file
|
|
182
|
+
*
|
|
183
|
+
* @param obj - The object to serialize
|
|
184
|
+
* @param filepath - Path to the output file or writable stream
|
|
185
|
+
* @param options - Serialization options
|
|
186
|
+
* @throws {CrousEncodeError} If encoding fails
|
|
187
|
+
*
|
|
188
|
+
* @example
|
|
189
|
+
* ```typescript
|
|
190
|
+
* import { dump } from 'crous';
|
|
191
|
+
* import * as fs from 'fs';
|
|
192
|
+
*
|
|
193
|
+
* const data = { name: 'Alice', age: 30 };
|
|
194
|
+
*
|
|
195
|
+
* // Write to file path
|
|
196
|
+
* dump(data, 'output.crous');
|
|
197
|
+
*
|
|
198
|
+
* // Write to stream
|
|
199
|
+
* const stream = fs.createWriteStream('output.crous');
|
|
200
|
+
* dump(data, stream);
|
|
201
|
+
* ```
|
|
202
|
+
*/
|
|
203
|
+
export function dump(obj: any, filepath: string | NodeJS.WritableStream, options?: DumpOptions): void;
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Deserialize a JavaScript value from a file
|
|
207
|
+
*
|
|
208
|
+
* @param filepath - Path to the input file or readable stream
|
|
209
|
+
* @param options - Deserialization options
|
|
210
|
+
* @returns Deserialized JavaScript value
|
|
211
|
+
* @throws {CrousDecodeError} If decoding fails
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* ```typescript
|
|
215
|
+
* import { load } from 'crous';
|
|
216
|
+
* import * as fs from 'fs';
|
|
217
|
+
*
|
|
218
|
+
* // Read from file path
|
|
219
|
+
* const data = load('input.crous');
|
|
220
|
+
*
|
|
221
|
+
* // Read from stream
|
|
222
|
+
* const stream = fs.createReadStream('input.crous');
|
|
223
|
+
* const data2 = load(stream);
|
|
224
|
+
* ```
|
|
225
|
+
*/
|
|
226
|
+
export function load(filepath: string | NodeJS.ReadableStream, options?: LoadOptions): any;
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Register a custom serializer for a specific type
|
|
230
|
+
*
|
|
231
|
+
* @param type - The constructor/class to register a serializer for
|
|
232
|
+
* @param serializer - Function to convert instances to serializable values
|
|
233
|
+
* @throws {TypeError} If serializer is not a function
|
|
234
|
+
*
|
|
235
|
+
* @example
|
|
236
|
+
* ```typescript
|
|
237
|
+
* import { registerSerializer, dumps } from 'crous';
|
|
238
|
+
*
|
|
239
|
+
* class Point {
|
|
240
|
+
* constructor(public x: number, public y: number) {}
|
|
241
|
+
* }
|
|
242
|
+
*
|
|
243
|
+
* registerSerializer(Point, (point) => {
|
|
244
|
+
* return { x: point.x, y: point.y };
|
|
245
|
+
* });
|
|
246
|
+
*
|
|
247
|
+
* const binary = dumps(new Point(10, 20));
|
|
248
|
+
* ```
|
|
249
|
+
*/
|
|
250
|
+
export function registerSerializer<T = any>(
|
|
251
|
+
type: new (...args: any[]) => T,
|
|
252
|
+
serializer: SerializerFunction<T>
|
|
253
|
+
): void;
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Unregister a custom serializer for a specific type
|
|
257
|
+
*
|
|
258
|
+
* @param type - The constructor/class to unregister
|
|
259
|
+
*
|
|
260
|
+
* @example
|
|
261
|
+
* ```typescript
|
|
262
|
+
* import { unregisterSerializer } from 'crous';
|
|
263
|
+
*
|
|
264
|
+
* class Point {}
|
|
265
|
+
* unregisterSerializer(Point);
|
|
266
|
+
* ```
|
|
267
|
+
*/
|
|
268
|
+
export function unregisterSerializer<T = any>(
|
|
269
|
+
type: new (...args: any[]) => T
|
|
270
|
+
): void;
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Register a custom decoder for a specific tag
|
|
274
|
+
*
|
|
275
|
+
* @param tag - The tag identifier (integer)
|
|
276
|
+
* @param decoder - Function to convert tagged values to objects
|
|
277
|
+
* @throws {TypeError} If decoder is not a function
|
|
278
|
+
*
|
|
279
|
+
* @example
|
|
280
|
+
* ```typescript
|
|
281
|
+
* import { registerDecoder, loads } from 'crous';
|
|
282
|
+
*
|
|
283
|
+
* class Point {
|
|
284
|
+
* constructor(public x: number, public y: number) {}
|
|
285
|
+
* }
|
|
286
|
+
*
|
|
287
|
+
* registerDecoder(100, (value) => {
|
|
288
|
+
* return new Point(value.x, value.y);
|
|
289
|
+
* });
|
|
290
|
+
*
|
|
291
|
+
* const data = loads(binary);
|
|
292
|
+
* ```
|
|
293
|
+
*/
|
|
294
|
+
export function registerDecoder<T = any>(
|
|
295
|
+
tag: number,
|
|
296
|
+
decoder: DecoderFunction<T>
|
|
297
|
+
): void;
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Unregister a custom decoder for a specific tag
|
|
301
|
+
*
|
|
302
|
+
* @param tag - The tag identifier to unregister
|
|
303
|
+
*
|
|
304
|
+
* @example
|
|
305
|
+
* ```typescript
|
|
306
|
+
* import { unregisterDecoder } from 'crous';
|
|
307
|
+
*
|
|
308
|
+
* unregisterDecoder(100);
|
|
309
|
+
* ```
|
|
310
|
+
*/
|
|
311
|
+
export function unregisterDecoder(tag: number): void;
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Get version information about the Crous library
|
|
315
|
+
*
|
|
316
|
+
* @returns Version information object
|
|
317
|
+
*
|
|
318
|
+
* @example
|
|
319
|
+
* ```typescript
|
|
320
|
+
* import { versionInfo } from 'crous';
|
|
321
|
+
*
|
|
322
|
+
* const info = versionInfo();
|
|
323
|
+
* console.log(`Crous v${info.string}`);
|
|
324
|
+
* ```
|
|
325
|
+
*/
|
|
326
|
+
export function versionInfo(): VersionInfo;
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Module version string
|
|
330
|
+
*/
|
|
331
|
+
export const version: string;
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Module version tuple [major, minor, patch]
|
|
335
|
+
*/
|
|
336
|
+
export const versionTuple: [number, number, number];
|
|
337
|
+
|
|
338
|
+
// Re-export as default for CommonJS compatibility
|
|
339
|
+
declare const crous: {
|
|
340
|
+
dumps: typeof dumps;
|
|
341
|
+
loads: typeof loads;
|
|
342
|
+
dump: typeof dump;
|
|
343
|
+
load: typeof load;
|
|
344
|
+
registerSerializer: typeof registerSerializer;
|
|
345
|
+
unregisterSerializer: typeof unregisterSerializer;
|
|
346
|
+
registerDecoder: typeof registerDecoder;
|
|
347
|
+
unregisterDecoder: typeof unregisterDecoder;
|
|
348
|
+
versionInfo: typeof versionInfo;
|
|
349
|
+
CrousEncoder: typeof CrousEncoder;
|
|
350
|
+
CrousDecoder: typeof CrousDecoder;
|
|
351
|
+
CrousError: typeof CrousError;
|
|
352
|
+
CrousEncodeError: typeof CrousEncodeError;
|
|
353
|
+
CrousDecodeError: typeof CrousDecodeError;
|
|
354
|
+
version: string;
|
|
355
|
+
versionTuple: [number, number, number];
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
export default crous;
|
package/index.js
ADDED
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Crous - High-performance binary serialization for Node.js
|
|
3
|
+
*
|
|
4
|
+
* This module provides complete Crous serialization with full support
|
|
5
|
+
* for Node.js native types and custom serializers.
|
|
6
|
+
*
|
|
7
|
+
* @module crous
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
const path = require('path');
|
|
14
|
+
|
|
15
|
+
// Load native addon
|
|
16
|
+
let native;
|
|
17
|
+
try {
|
|
18
|
+
native = require('./build/Release/crous.node');
|
|
19
|
+
} catch (e) {
|
|
20
|
+
try {
|
|
21
|
+
native = require('./build/Debug/crous.node');
|
|
22
|
+
} catch (e2) {
|
|
23
|
+
throw new Error('Could not load Crous native addon. Please run: npm install');
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Version information
|
|
28
|
+
const VERSION = {
|
|
29
|
+
major: 1,
|
|
30
|
+
minor: 0,
|
|
31
|
+
patch: 0,
|
|
32
|
+
get string() {
|
|
33
|
+
return `${this.major}.${this.minor}.${this.patch}`;
|
|
34
|
+
},
|
|
35
|
+
get tuple() {
|
|
36
|
+
return [this.major, this.minor, this.patch];
|
|
37
|
+
},
|
|
38
|
+
get hex() {
|
|
39
|
+
return (this.major << 16) | (this.minor << 8) | this.patch;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Custom error classes
|
|
45
|
+
*/
|
|
46
|
+
class CrousError extends Error {
|
|
47
|
+
constructor(message) {
|
|
48
|
+
super(message);
|
|
49
|
+
this.name = 'CrousError';
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
class CrousEncodeError extends CrousError {
|
|
54
|
+
constructor(message) {
|
|
55
|
+
super(message);
|
|
56
|
+
this.name = 'CrousEncodeError';
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
class CrousDecodeError extends CrousError {
|
|
61
|
+
constructor(message) {
|
|
62
|
+
super(message);
|
|
63
|
+
this.name = 'CrousDecodeError';
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Encoder class for custom serialization control
|
|
69
|
+
*/
|
|
70
|
+
class CrousEncoder {
|
|
71
|
+
constructor(options = {}) {
|
|
72
|
+
this.default = options.default || null;
|
|
73
|
+
this.allowCustom = options.allowCustom !== false;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
encode(obj) {
|
|
77
|
+
return native.dumps(obj, this.default);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Decoder class for custom deserialization control
|
|
83
|
+
*/
|
|
84
|
+
class CrousDecoder {
|
|
85
|
+
constructor(options = {}) {
|
|
86
|
+
this.objectHook = options.objectHook || null;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
decode(data) {
|
|
90
|
+
return native.loads(data, this.objectHook);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Serialize a JavaScript value to binary format
|
|
96
|
+
*
|
|
97
|
+
* @param {*} obj - The object to serialize
|
|
98
|
+
* @param {Object} options - Serialization options
|
|
99
|
+
* @param {Function} options.default - Optional function for custom types
|
|
100
|
+
* @param {boolean} options.allowCustom - Whether to allow custom serializers
|
|
101
|
+
* @returns {Buffer} Binary encoded data
|
|
102
|
+
* @throws {CrousEncodeError} If encoding fails
|
|
103
|
+
*/
|
|
104
|
+
function dumps(obj, options = {}) {
|
|
105
|
+
try {
|
|
106
|
+
return native.dumps(obj, options.default || null);
|
|
107
|
+
} catch (error) {
|
|
108
|
+
throw new CrousEncodeError(error.message);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Deserialize binary data to a JavaScript value
|
|
114
|
+
*
|
|
115
|
+
* @param {Buffer} data - Binary data to deserialize
|
|
116
|
+
* @param {Object} options - Deserialization options
|
|
117
|
+
* @param {Function} options.objectHook - Optional function for post-processing objects
|
|
118
|
+
* @returns {*} Deserialized JavaScript value
|
|
119
|
+
* @throws {CrousDecodeError} If decoding fails
|
|
120
|
+
*/
|
|
121
|
+
function loads(data, options = {}) {
|
|
122
|
+
try {
|
|
123
|
+
if (!Buffer.isBuffer(data)) {
|
|
124
|
+
data = Buffer.from(data);
|
|
125
|
+
}
|
|
126
|
+
return native.loads(data, options.objectHook || null);
|
|
127
|
+
} catch (error) {
|
|
128
|
+
throw new CrousDecodeError(error.message);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Serialize a JavaScript value and write to a file
|
|
134
|
+
*
|
|
135
|
+
* @param {*} obj - The object to serialize
|
|
136
|
+
* @param {string|stream.Writable} filepath - Path to output file or writable stream
|
|
137
|
+
* @param {Object} options - Serialization options
|
|
138
|
+
* @throws {CrousEncodeError} If encoding fails
|
|
139
|
+
*/
|
|
140
|
+
function dump(obj, filepath, options = {}) {
|
|
141
|
+
try {
|
|
142
|
+
const binary = native.dumps(obj, options.default || null);
|
|
143
|
+
|
|
144
|
+
if (typeof filepath === 'string') {
|
|
145
|
+
// Write to file path
|
|
146
|
+
fs.writeFileSync(filepath, binary);
|
|
147
|
+
} else if (filepath && typeof filepath.write === 'function') {
|
|
148
|
+
// Write to stream
|
|
149
|
+
filepath.write(binary);
|
|
150
|
+
} else {
|
|
151
|
+
throw new Error('filepath must be a string or writable stream');
|
|
152
|
+
}
|
|
153
|
+
} catch (error) {
|
|
154
|
+
if (error instanceof CrousEncodeError) {
|
|
155
|
+
throw error;
|
|
156
|
+
}
|
|
157
|
+
throw new CrousEncodeError(error.message);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Deserialize a JavaScript value from a file
|
|
163
|
+
*
|
|
164
|
+
* @param {string|stream.Readable} filepath - Path to input file or readable stream
|
|
165
|
+
* @param {Object} options - Deserialization options
|
|
166
|
+
* @returns {*} Deserialized JavaScript value
|
|
167
|
+
* @throws {CrousDecodeError} If decoding fails
|
|
168
|
+
*/
|
|
169
|
+
function load(filepath, options = {}) {
|
|
170
|
+
try {
|
|
171
|
+
let binary;
|
|
172
|
+
|
|
173
|
+
if (typeof filepath === 'string') {
|
|
174
|
+
// Read from file path
|
|
175
|
+
binary = fs.readFileSync(filepath);
|
|
176
|
+
} else if (filepath && typeof filepath.read === 'function') {
|
|
177
|
+
// Read from stream
|
|
178
|
+
const chunks = [];
|
|
179
|
+
let chunk;
|
|
180
|
+
while ((chunk = filepath.read()) !== null) {
|
|
181
|
+
chunks.push(chunk);
|
|
182
|
+
}
|
|
183
|
+
binary = Buffer.concat(chunks);
|
|
184
|
+
} else {
|
|
185
|
+
throw new Error('filepath must be a string or readable stream');
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return native.loads(binary, options.objectHook || null);
|
|
189
|
+
} catch (error) {
|
|
190
|
+
if (error instanceof CrousDecodeError) {
|
|
191
|
+
throw error;
|
|
192
|
+
}
|
|
193
|
+
throw new CrousDecodeError(error.message);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Register a custom serializer for a specific type
|
|
199
|
+
*
|
|
200
|
+
* @param {Function} type - The constructor/class to register a serializer for
|
|
201
|
+
* @param {Function} serializer - Function to convert instances to serializable values
|
|
202
|
+
* @throws {TypeError} If serializer is not a function
|
|
203
|
+
*/
|
|
204
|
+
function registerSerializer(type, serializer) {
|
|
205
|
+
if (typeof serializer !== 'function') {
|
|
206
|
+
throw new TypeError('Serializer must be a function');
|
|
207
|
+
}
|
|
208
|
+
native.registerSerializer(type, serializer);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Unregister a custom serializer for a specific type
|
|
213
|
+
*
|
|
214
|
+
* @param {Function} type - The constructor/class to unregister
|
|
215
|
+
*/
|
|
216
|
+
function unregisterSerializer(type) {
|
|
217
|
+
native.unregisterSerializer(type);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Register a custom decoder for a specific tag
|
|
222
|
+
*
|
|
223
|
+
* @param {number} tag - The tag identifier (integer)
|
|
224
|
+
* @param {Function} decoder - Function to convert tagged values to objects
|
|
225
|
+
* @throws {TypeError} If decoder is not a function
|
|
226
|
+
*/
|
|
227
|
+
function registerDecoder(tag, decoder) {
|
|
228
|
+
if (typeof decoder !== 'function') {
|
|
229
|
+
throw new TypeError('Decoder must be a function');
|
|
230
|
+
}
|
|
231
|
+
native.registerDecoder(tag, decoder);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Unregister a custom decoder for a specific tag
|
|
236
|
+
*
|
|
237
|
+
* @param {number} tag - The tag identifier to unregister
|
|
238
|
+
*/
|
|
239
|
+
function unregisterDecoder(tag) {
|
|
240
|
+
native.unregisterDecoder(tag);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Get version information about the Crous library
|
|
245
|
+
*
|
|
246
|
+
* @returns {Object} Version information object
|
|
247
|
+
*/
|
|
248
|
+
function versionInfo() {
|
|
249
|
+
return {
|
|
250
|
+
major: VERSION.major,
|
|
251
|
+
minor: VERSION.minor,
|
|
252
|
+
patch: VERSION.patch,
|
|
253
|
+
string: VERSION.string,
|
|
254
|
+
tuple: VERSION.tuple,
|
|
255
|
+
hex: VERSION.hex
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Export all functions and classes
|
|
260
|
+
module.exports = {
|
|
261
|
+
// Core functions
|
|
262
|
+
dumps,
|
|
263
|
+
loads,
|
|
264
|
+
dump,
|
|
265
|
+
load,
|
|
266
|
+
|
|
267
|
+
// Custom serializers/decoders
|
|
268
|
+
registerSerializer,
|
|
269
|
+
unregisterSerializer,
|
|
270
|
+
registerDecoder,
|
|
271
|
+
unregisterDecoder,
|
|
272
|
+
|
|
273
|
+
// Classes
|
|
274
|
+
CrousEncoder,
|
|
275
|
+
CrousDecoder,
|
|
276
|
+
CrousError,
|
|
277
|
+
CrousEncodeError,
|
|
278
|
+
CrousDecodeError,
|
|
279
|
+
|
|
280
|
+
// Version info
|
|
281
|
+
versionInfo,
|
|
282
|
+
version: VERSION.string,
|
|
283
|
+
versionTuple: VERSION.tuple,
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
// ES6 named exports for modern Node.js
|
|
287
|
+
if (typeof exports !== 'undefined') {
|
|
288
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
289
|
+
exports.default = module.exports;
|
|
290
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "crous",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Crous: High-performance binary serialization format for Node.js",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"types": "index.d.ts",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"serialization",
|
|
9
|
+
"binary",
|
|
10
|
+
"encoding",
|
|
11
|
+
"decoding",
|
|
12
|
+
"msgpack",
|
|
13
|
+
"protobuf",
|
|
14
|
+
"fast",
|
|
15
|
+
"native",
|
|
16
|
+
"performance"
|
|
17
|
+
],
|
|
18
|
+
"author": "Pawan Kumar <aegis.invincible@gmail.com>",
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "https://github.com/axiomchronicles/crous.git"
|
|
23
|
+
},
|
|
24
|
+
"bugs": {
|
|
25
|
+
"url": "https://github.com/axiomchronicles/crous/issues"
|
|
26
|
+
},
|
|
27
|
+
"homepage": "https://github.com/axiomchronicles/crous#readme",
|
|
28
|
+
"scripts": {
|
|
29
|
+
"install": "node-gyp rebuild",
|
|
30
|
+
"build": "node-gyp rebuild",
|
|
31
|
+
"test": "node test/test_basic.js && node test/test_advanced.js",
|
|
32
|
+
"test:basic": "node test/test_basic.js",
|
|
33
|
+
"test:advanced": "node test/test_advanced.js",
|
|
34
|
+
"test:performance": "node test/test_performance.js",
|
|
35
|
+
"test:compat": "node test/test_python_compat.js",
|
|
36
|
+
"test:all": "npm run test:basic && npm run test:advanced && npm run test:performance && npm run test:compat",
|
|
37
|
+
"clean": "node-gyp clean"
|
|
38
|
+
},
|
|
39
|
+
"gypfile": true,
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=14.0.0"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"node-addon-api": "^8.0.0"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"node-gyp": "^10.0.0"
|
|
48
|
+
},
|
|
49
|
+
"files": [
|
|
50
|
+
"binding.gyp",
|
|
51
|
+
"index.js",
|
|
52
|
+
"index.d.ts",
|
|
53
|
+
"src/",
|
|
54
|
+
"README.md",
|
|
55
|
+
"LICENSE"
|
|
56
|
+
]
|
|
57
|
+
}
|