tersejson 0.2.1 → 0.3.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/README.md +192 -357
- package/dist/mongodb.d.mts +107 -0
- package/dist/mongodb.d.ts +107 -0
- package/dist/mongodb.js +472 -0
- package/dist/mongodb.js.map +1 -0
- package/dist/mongodb.mjs +465 -0
- package/dist/mongodb.mjs.map +1 -0
- package/dist/server-memory.d.mts +167 -0
- package/dist/server-memory.d.ts +167 -0
- package/dist/server-memory.js +455 -0
- package/dist/server-memory.js.map +1 -0
- package/dist/server-memory.mjs +451 -0
- package/dist/server-memory.mjs.map +1 -0
- package/package.json +27 -10
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { C as CompressOptions } from './types-BTonKlz8.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* TerseJSON MongoDB Integration
|
|
5
|
+
*
|
|
6
|
+
* Zero-config integration with MongoDB native driver.
|
|
7
|
+
* Call terseMongo() once at startup and all queries automatically
|
|
8
|
+
* return memory-efficient Proxy-wrapped results.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import { terseMongo } from 'tersejson/mongodb';
|
|
13
|
+
* import { MongoClient } from 'mongodb';
|
|
14
|
+
*
|
|
15
|
+
* terseMongo(); // Patch once at startup
|
|
16
|
+
*
|
|
17
|
+
* const client = new MongoClient(uri);
|
|
18
|
+
* const users = await client.db('mydb').collection('users').find().toArray();
|
|
19
|
+
* // users is automatically Proxy-wrapped - 70% less memory
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @packageDocumentation
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Options for terseMongo initialization
|
|
27
|
+
*/
|
|
28
|
+
interface TerseMongoOptions extends Partial<CompressOptions> {
|
|
29
|
+
/**
|
|
30
|
+
* Enable/disable compression (default: true)
|
|
31
|
+
*/
|
|
32
|
+
enabled?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Minimum array length to compress (default: 1)
|
|
35
|
+
* Single documents are always wrapped for consistency
|
|
36
|
+
*/
|
|
37
|
+
minArrayLength?: number;
|
|
38
|
+
/**
|
|
39
|
+
* Skip compression for single document queries like findOne (default: false)
|
|
40
|
+
* Set to true if you don't want overhead on single doc fetches
|
|
41
|
+
*/
|
|
42
|
+
skipSingleDocs?: boolean;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Initialize TerseJSON integration with MongoDB native driver.
|
|
46
|
+
*
|
|
47
|
+
* Call this once at application startup, before any MongoDB queries.
|
|
48
|
+
* All subsequent queries will automatically return Proxy-wrapped results.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* import { terseMongo } from 'tersejson/mongodb';
|
|
53
|
+
*
|
|
54
|
+
* // Basic usage
|
|
55
|
+
* await terseMongo();
|
|
56
|
+
*
|
|
57
|
+
* // With options
|
|
58
|
+
* await terseMongo({
|
|
59
|
+
* minKeyLength: 4, // Only compress keys with 4+ characters
|
|
60
|
+
* minArrayLength: 5, // Only compress arrays with 5+ items
|
|
61
|
+
* skipSingleDocs: true, // Don't wrap findOne results
|
|
62
|
+
* });
|
|
63
|
+
* ```
|
|
64
|
+
*
|
|
65
|
+
* @param options - Configuration options
|
|
66
|
+
*/
|
|
67
|
+
declare function terseMongo(options?: TerseMongoOptions): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Synchronous version of terseMongo for CommonJS compatibility.
|
|
70
|
+
*
|
|
71
|
+
* Note: This requires mongodb to already be loaded in the module cache.
|
|
72
|
+
* For best results, use the async terseMongo() instead.
|
|
73
|
+
*
|
|
74
|
+
* @param options - Configuration options
|
|
75
|
+
*/
|
|
76
|
+
declare function terseMongoSync(options?: TerseMongoOptions): void;
|
|
77
|
+
/**
|
|
78
|
+
* Remove TerseJSON patches from MongoDB driver.
|
|
79
|
+
*
|
|
80
|
+
* Useful for testing or when you need to temporarily disable compression.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```typescript
|
|
84
|
+
* import { terseMongo, unterse } from 'tersejson/mongodb';
|
|
85
|
+
*
|
|
86
|
+
* await terseMongo();
|
|
87
|
+
* // ... queries are Proxy-wrapped
|
|
88
|
+
*
|
|
89
|
+
* await unterse();
|
|
90
|
+
* // ... queries return normal documents
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
declare function unterse(): Promise<void>;
|
|
94
|
+
/**
|
|
95
|
+
* Check if TerseJSON MongoDB patching is active
|
|
96
|
+
*/
|
|
97
|
+
declare function isTerseMongoActive(): boolean;
|
|
98
|
+
/**
|
|
99
|
+
* Get current TerseJSON MongoDB options
|
|
100
|
+
*/
|
|
101
|
+
declare function getTerseMongoOptions(): TerseMongoOptions;
|
|
102
|
+
/**
|
|
103
|
+
* Update TerseJSON MongoDB options without re-patching
|
|
104
|
+
*/
|
|
105
|
+
declare function setTerseMongoOptions(options: Partial<TerseMongoOptions>): void;
|
|
106
|
+
|
|
107
|
+
export { type TerseMongoOptions, getTerseMongoOptions, isTerseMongoActive, setTerseMongoOptions, terseMongo, terseMongoSync, unterse };
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { C as CompressOptions } from './types-BTonKlz8.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* TerseJSON MongoDB Integration
|
|
5
|
+
*
|
|
6
|
+
* Zero-config integration with MongoDB native driver.
|
|
7
|
+
* Call terseMongo() once at startup and all queries automatically
|
|
8
|
+
* return memory-efficient Proxy-wrapped results.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import { terseMongo } from 'tersejson/mongodb';
|
|
13
|
+
* import { MongoClient } from 'mongodb';
|
|
14
|
+
*
|
|
15
|
+
* terseMongo(); // Patch once at startup
|
|
16
|
+
*
|
|
17
|
+
* const client = new MongoClient(uri);
|
|
18
|
+
* const users = await client.db('mydb').collection('users').find().toArray();
|
|
19
|
+
* // users is automatically Proxy-wrapped - 70% less memory
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @packageDocumentation
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Options for terseMongo initialization
|
|
27
|
+
*/
|
|
28
|
+
interface TerseMongoOptions extends Partial<CompressOptions> {
|
|
29
|
+
/**
|
|
30
|
+
* Enable/disable compression (default: true)
|
|
31
|
+
*/
|
|
32
|
+
enabled?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Minimum array length to compress (default: 1)
|
|
35
|
+
* Single documents are always wrapped for consistency
|
|
36
|
+
*/
|
|
37
|
+
minArrayLength?: number;
|
|
38
|
+
/**
|
|
39
|
+
* Skip compression for single document queries like findOne (default: false)
|
|
40
|
+
* Set to true if you don't want overhead on single doc fetches
|
|
41
|
+
*/
|
|
42
|
+
skipSingleDocs?: boolean;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Initialize TerseJSON integration with MongoDB native driver.
|
|
46
|
+
*
|
|
47
|
+
* Call this once at application startup, before any MongoDB queries.
|
|
48
|
+
* All subsequent queries will automatically return Proxy-wrapped results.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* import { terseMongo } from 'tersejson/mongodb';
|
|
53
|
+
*
|
|
54
|
+
* // Basic usage
|
|
55
|
+
* await terseMongo();
|
|
56
|
+
*
|
|
57
|
+
* // With options
|
|
58
|
+
* await terseMongo({
|
|
59
|
+
* minKeyLength: 4, // Only compress keys with 4+ characters
|
|
60
|
+
* minArrayLength: 5, // Only compress arrays with 5+ items
|
|
61
|
+
* skipSingleDocs: true, // Don't wrap findOne results
|
|
62
|
+
* });
|
|
63
|
+
* ```
|
|
64
|
+
*
|
|
65
|
+
* @param options - Configuration options
|
|
66
|
+
*/
|
|
67
|
+
declare function terseMongo(options?: TerseMongoOptions): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Synchronous version of terseMongo for CommonJS compatibility.
|
|
70
|
+
*
|
|
71
|
+
* Note: This requires mongodb to already be loaded in the module cache.
|
|
72
|
+
* For best results, use the async terseMongo() instead.
|
|
73
|
+
*
|
|
74
|
+
* @param options - Configuration options
|
|
75
|
+
*/
|
|
76
|
+
declare function terseMongoSync(options?: TerseMongoOptions): void;
|
|
77
|
+
/**
|
|
78
|
+
* Remove TerseJSON patches from MongoDB driver.
|
|
79
|
+
*
|
|
80
|
+
* Useful for testing or when you need to temporarily disable compression.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```typescript
|
|
84
|
+
* import { terseMongo, unterse } from 'tersejson/mongodb';
|
|
85
|
+
*
|
|
86
|
+
* await terseMongo();
|
|
87
|
+
* // ... queries are Proxy-wrapped
|
|
88
|
+
*
|
|
89
|
+
* await unterse();
|
|
90
|
+
* // ... queries return normal documents
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
declare function unterse(): Promise<void>;
|
|
94
|
+
/**
|
|
95
|
+
* Check if TerseJSON MongoDB patching is active
|
|
96
|
+
*/
|
|
97
|
+
declare function isTerseMongoActive(): boolean;
|
|
98
|
+
/**
|
|
99
|
+
* Get current TerseJSON MongoDB options
|
|
100
|
+
*/
|
|
101
|
+
declare function getTerseMongoOptions(): TerseMongoOptions;
|
|
102
|
+
/**
|
|
103
|
+
* Update TerseJSON MongoDB options without re-patching
|
|
104
|
+
*/
|
|
105
|
+
declare function setTerseMongoOptions(options: Partial<TerseMongoOptions>): void;
|
|
106
|
+
|
|
107
|
+
export { type TerseMongoOptions, getTerseMongoOptions, isTerseMongoActive, setTerseMongoOptions, terseMongo, terseMongoSync, unterse };
|
package/dist/mongodb.js
ADDED
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
4
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
5
|
+
}) : x)(function(x) {
|
|
6
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
7
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
// src/core.ts
|
|
11
|
+
function alphaGenerator(index) {
|
|
12
|
+
let key = "";
|
|
13
|
+
let remaining = index;
|
|
14
|
+
do {
|
|
15
|
+
key = String.fromCharCode(97 + remaining % 26) + key;
|
|
16
|
+
remaining = Math.floor(remaining / 26) - 1;
|
|
17
|
+
} while (remaining >= 0);
|
|
18
|
+
return key;
|
|
19
|
+
}
|
|
20
|
+
function numericGenerator(index) {
|
|
21
|
+
return String(index);
|
|
22
|
+
}
|
|
23
|
+
function alphanumericGenerator(index) {
|
|
24
|
+
const letterIndex = Math.floor(index / 9);
|
|
25
|
+
const numIndex = index % 9 + 1;
|
|
26
|
+
return alphaGenerator(letterIndex) + numIndex;
|
|
27
|
+
}
|
|
28
|
+
function shortGenerator(index) {
|
|
29
|
+
if (index === 0) return "_";
|
|
30
|
+
return alphaGenerator(index - 1);
|
|
31
|
+
}
|
|
32
|
+
function prefixedGenerator(prefix, style = "numeric") {
|
|
33
|
+
return (index) => {
|
|
34
|
+
if (style === "alpha") {
|
|
35
|
+
return prefix + alphaGenerator(index);
|
|
36
|
+
}
|
|
37
|
+
return prefix + index;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function createKeyGenerator(pattern) {
|
|
41
|
+
if (typeof pattern === "function") {
|
|
42
|
+
return { generator: pattern, name: "custom" };
|
|
43
|
+
}
|
|
44
|
+
if (typeof pattern === "string") {
|
|
45
|
+
switch (pattern) {
|
|
46
|
+
case "alpha":
|
|
47
|
+
return { generator: alphaGenerator, name: "alpha" };
|
|
48
|
+
case "numeric":
|
|
49
|
+
return { generator: numericGenerator, name: "numeric" };
|
|
50
|
+
case "alphanumeric":
|
|
51
|
+
return { generator: alphanumericGenerator, name: "alphanumeric" };
|
|
52
|
+
case "short":
|
|
53
|
+
return { generator: shortGenerator, name: "short" };
|
|
54
|
+
case "prefixed":
|
|
55
|
+
return { generator: prefixedGenerator("k"), name: "prefixed:k" };
|
|
56
|
+
default:
|
|
57
|
+
return { generator: alphaGenerator, name: "alpha" };
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (typeof pattern === "object" && "prefix" in pattern) {
|
|
61
|
+
return {
|
|
62
|
+
generator: prefixedGenerator(pattern.prefix, pattern.style || "numeric"),
|
|
63
|
+
name: `prefixed:${pattern.prefix}`
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return { generator: alphaGenerator, name: "alpha" };
|
|
67
|
+
}
|
|
68
|
+
function resolveNestedDepth(handling, maxDepth) {
|
|
69
|
+
if (handling === void 0 || handling === "deep") {
|
|
70
|
+
return maxDepth;
|
|
71
|
+
}
|
|
72
|
+
if (handling === "shallow") {
|
|
73
|
+
return 1;
|
|
74
|
+
}
|
|
75
|
+
if (handling === "arrays") {
|
|
76
|
+
return maxDepth;
|
|
77
|
+
}
|
|
78
|
+
if (typeof handling === "number") {
|
|
79
|
+
return handling;
|
|
80
|
+
}
|
|
81
|
+
return maxDepth;
|
|
82
|
+
}
|
|
83
|
+
function collectKeys(data, options, currentDepth = 0) {
|
|
84
|
+
const keys = /* @__PURE__ */ new Set();
|
|
85
|
+
const { minKeyLength, maxDepth, nestedHandling, excludeKeys, includeKeys } = options;
|
|
86
|
+
if (currentDepth >= maxDepth) return keys;
|
|
87
|
+
const keyCounts = /* @__PURE__ */ new Map();
|
|
88
|
+
for (const item of data) {
|
|
89
|
+
if (typeof item !== "object" || item === null) continue;
|
|
90
|
+
for (const key of Object.keys(item)) {
|
|
91
|
+
if (excludeKeys?.includes(key)) continue;
|
|
92
|
+
const shouldInclude = includeKeys?.includes(key) || key.length >= minKeyLength;
|
|
93
|
+
if (shouldInclude) {
|
|
94
|
+
keys.add(key);
|
|
95
|
+
keyCounts.set(key, (keyCounts.get(key) || 0) + 1);
|
|
96
|
+
}
|
|
97
|
+
const value = item[key];
|
|
98
|
+
if (nestedHandling === "shallow") {
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
if (Array.isArray(value) && value.length > 0 && isCompressibleArray(value)) {
|
|
102
|
+
const nestedKeys = collectKeys(
|
|
103
|
+
value,
|
|
104
|
+
options,
|
|
105
|
+
currentDepth + 1
|
|
106
|
+
);
|
|
107
|
+
nestedKeys.forEach((k) => keys.add(k));
|
|
108
|
+
} else if (nestedHandling !== "arrays" && typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
109
|
+
const nestedKeys = collectKeys(
|
|
110
|
+
[value],
|
|
111
|
+
options,
|
|
112
|
+
currentDepth + 1
|
|
113
|
+
);
|
|
114
|
+
nestedKeys.forEach((k) => keys.add(k));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (options.homogeneousOnly && data.length > 0) {
|
|
119
|
+
for (const [key, count] of keyCounts) {
|
|
120
|
+
if (count < data.length) {
|
|
121
|
+
keys.delete(key);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return keys;
|
|
126
|
+
}
|
|
127
|
+
function isCompressibleArray(data) {
|
|
128
|
+
if (!Array.isArray(data) || data.length === 0) return false;
|
|
129
|
+
return data.every(
|
|
130
|
+
(item) => typeof item === "object" && item !== null && !Array.isArray(item)
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
function compressObject(obj, keyToShort, maxDepth, currentDepth = 0) {
|
|
134
|
+
if (currentDepth >= maxDepth) return obj;
|
|
135
|
+
const compressed = {};
|
|
136
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
137
|
+
const shortKey = keyToShort.get(key) ?? key;
|
|
138
|
+
if (Array.isArray(value) && isCompressibleArray(value)) {
|
|
139
|
+
compressed[shortKey] = value.map(
|
|
140
|
+
(item) => compressObject(
|
|
141
|
+
item,
|
|
142
|
+
keyToShort,
|
|
143
|
+
maxDepth,
|
|
144
|
+
currentDepth + 1
|
|
145
|
+
)
|
|
146
|
+
);
|
|
147
|
+
} else if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
148
|
+
compressed[shortKey] = compressObject(
|
|
149
|
+
value,
|
|
150
|
+
keyToShort,
|
|
151
|
+
maxDepth,
|
|
152
|
+
currentDepth + 1
|
|
153
|
+
);
|
|
154
|
+
} else {
|
|
155
|
+
compressed[shortKey] = value;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return compressed;
|
|
159
|
+
}
|
|
160
|
+
function compress(data, options = {}) {
|
|
161
|
+
const {
|
|
162
|
+
minKeyLength = 3,
|
|
163
|
+
maxDepth = 10,
|
|
164
|
+
keyPattern = "alpha",
|
|
165
|
+
nestedHandling = "deep",
|
|
166
|
+
homogeneousOnly = false,
|
|
167
|
+
excludeKeys,
|
|
168
|
+
includeKeys
|
|
169
|
+
} = options;
|
|
170
|
+
const { generator, name: patternName } = createKeyGenerator(keyPattern);
|
|
171
|
+
const effectiveDepth = resolveNestedDepth(nestedHandling, maxDepth);
|
|
172
|
+
const allKeys = collectKeys(data, {
|
|
173
|
+
minKeyLength,
|
|
174
|
+
maxDepth: effectiveDepth,
|
|
175
|
+
nestedHandling,
|
|
176
|
+
excludeKeys,
|
|
177
|
+
includeKeys,
|
|
178
|
+
homogeneousOnly
|
|
179
|
+
});
|
|
180
|
+
const sortedKeys = Array.from(allKeys).sort();
|
|
181
|
+
const keyToShort = /* @__PURE__ */ new Map();
|
|
182
|
+
const keyMap = {};
|
|
183
|
+
sortedKeys.forEach((key, index) => {
|
|
184
|
+
const shortKey = generator(index);
|
|
185
|
+
if (shortKey.length < key.length) {
|
|
186
|
+
keyToShort.set(key, shortKey);
|
|
187
|
+
keyMap[shortKey] = key;
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
const compressed = data.map(
|
|
191
|
+
(item) => compressObject(item, keyToShort, effectiveDepth)
|
|
192
|
+
);
|
|
193
|
+
return {
|
|
194
|
+
__terse__: true,
|
|
195
|
+
v: 1,
|
|
196
|
+
k: keyMap,
|
|
197
|
+
d: compressed,
|
|
198
|
+
p: patternName
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
function createTerseProxy(compressed, keyMap) {
|
|
202
|
+
const originalToShort = new Map(
|
|
203
|
+
Object.entries(keyMap).map(([short, original]) => [original, short])
|
|
204
|
+
);
|
|
205
|
+
const handler = {
|
|
206
|
+
get(target, prop) {
|
|
207
|
+
if (typeof prop === "symbol") {
|
|
208
|
+
return Reflect.get(target, prop);
|
|
209
|
+
}
|
|
210
|
+
const shortKey = originalToShort.get(prop);
|
|
211
|
+
const actualKey = shortKey ?? prop;
|
|
212
|
+
const value = target[actualKey];
|
|
213
|
+
if (Array.isArray(value)) {
|
|
214
|
+
return value.map((item) => {
|
|
215
|
+
if (typeof item === "object" && item !== null && !Array.isArray(item)) {
|
|
216
|
+
return createTerseProxy(item, keyMap);
|
|
217
|
+
}
|
|
218
|
+
return item;
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
if (typeof value === "object" && value !== null) {
|
|
222
|
+
return createTerseProxy(value, keyMap);
|
|
223
|
+
}
|
|
224
|
+
return value;
|
|
225
|
+
},
|
|
226
|
+
has(target, prop) {
|
|
227
|
+
if (typeof prop === "symbol") {
|
|
228
|
+
return Reflect.has(target, prop);
|
|
229
|
+
}
|
|
230
|
+
const shortKey = originalToShort.get(prop);
|
|
231
|
+
return (shortKey ?? prop) in target;
|
|
232
|
+
},
|
|
233
|
+
ownKeys(target) {
|
|
234
|
+
return Object.keys(target).map((shortKey) => keyMap[shortKey] ?? shortKey);
|
|
235
|
+
},
|
|
236
|
+
getOwnPropertyDescriptor(target, prop) {
|
|
237
|
+
if (typeof prop === "symbol") {
|
|
238
|
+
return Reflect.getOwnPropertyDescriptor(target, prop);
|
|
239
|
+
}
|
|
240
|
+
const shortKey = originalToShort.get(prop);
|
|
241
|
+
const actualKey = shortKey ?? prop;
|
|
242
|
+
const descriptor = Object.getOwnPropertyDescriptor(target, actualKey);
|
|
243
|
+
if (descriptor) {
|
|
244
|
+
return { ...descriptor, enumerable: true, configurable: true };
|
|
245
|
+
}
|
|
246
|
+
return void 0;
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
return new Proxy(compressed, handler);
|
|
250
|
+
}
|
|
251
|
+
function wrapWithProxy(payload) {
|
|
252
|
+
if (Array.isArray(payload.d)) {
|
|
253
|
+
return payload.d.map((item) => {
|
|
254
|
+
if (typeof item === "object" && item !== null && !Array.isArray(item)) {
|
|
255
|
+
return createTerseProxy(item, payload.k);
|
|
256
|
+
}
|
|
257
|
+
return item;
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
if (typeof payload.d === "object" && payload.d !== null) {
|
|
261
|
+
return createTerseProxy(payload.d, payload.k);
|
|
262
|
+
}
|
|
263
|
+
return payload.d;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// src/mongodb.ts
|
|
267
|
+
var isPatched = false;
|
|
268
|
+
var globalOptions = {};
|
|
269
|
+
var originalMethods = {};
|
|
270
|
+
function wrapResults(results) {
|
|
271
|
+
if (globalOptions.enabled === false) {
|
|
272
|
+
return results;
|
|
273
|
+
}
|
|
274
|
+
if (results.length < (globalOptions.minArrayLength ?? 1)) {
|
|
275
|
+
return results;
|
|
276
|
+
}
|
|
277
|
+
if (!isCompressibleArray(results)) {
|
|
278
|
+
return results;
|
|
279
|
+
}
|
|
280
|
+
const payload = compress(results, globalOptions);
|
|
281
|
+
return wrapWithProxy(payload);
|
|
282
|
+
}
|
|
283
|
+
function wrapSingleDoc(doc) {
|
|
284
|
+
if (globalOptions.enabled === false || globalOptions.skipSingleDocs) {
|
|
285
|
+
return doc;
|
|
286
|
+
}
|
|
287
|
+
if (doc === null || doc === void 0) {
|
|
288
|
+
return doc;
|
|
289
|
+
}
|
|
290
|
+
if (typeof doc !== "object") {
|
|
291
|
+
return doc;
|
|
292
|
+
}
|
|
293
|
+
const payload = compress([doc], globalOptions);
|
|
294
|
+
const wrapped = wrapWithProxy(payload);
|
|
295
|
+
return wrapped[0];
|
|
296
|
+
}
|
|
297
|
+
async function patchMongoDB() {
|
|
298
|
+
let mongodb;
|
|
299
|
+
try {
|
|
300
|
+
mongodb = await import('mongodb');
|
|
301
|
+
} catch {
|
|
302
|
+
throw new Error(
|
|
303
|
+
"terseMongo requires mongodb to be installed. Run: npm install mongodb"
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
const { FindCursor, AggregationCursor, Collection } = mongodb;
|
|
307
|
+
if (FindCursor?.prototype) {
|
|
308
|
+
originalMethods.findCursorToArray = FindCursor.prototype.toArray;
|
|
309
|
+
FindCursor.prototype.toArray = async function() {
|
|
310
|
+
const results = await originalMethods.findCursorToArray.call(this);
|
|
311
|
+
return wrapResults(results);
|
|
312
|
+
};
|
|
313
|
+
originalMethods.findCursorNext = FindCursor.prototype.next;
|
|
314
|
+
FindCursor.prototype.next = async function() {
|
|
315
|
+
const doc = await originalMethods.findCursorNext.call(this);
|
|
316
|
+
return doc ? wrapSingleDoc(doc) : null;
|
|
317
|
+
};
|
|
318
|
+
originalMethods.findCursorIterator = FindCursor.prototype[Symbol.asyncIterator];
|
|
319
|
+
FindCursor.prototype[Symbol.asyncIterator] = async function* () {
|
|
320
|
+
const iterator = originalMethods.findCursorIterator.call(this);
|
|
321
|
+
for await (const doc of iterator) {
|
|
322
|
+
yield wrapSingleDoc(doc);
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
if (AggregationCursor?.prototype) {
|
|
327
|
+
originalMethods.aggregationCursorToArray = AggregationCursor.prototype.toArray;
|
|
328
|
+
AggregationCursor.prototype.toArray = async function() {
|
|
329
|
+
const results = await originalMethods.aggregationCursorToArray.call(this);
|
|
330
|
+
return wrapResults(results);
|
|
331
|
+
};
|
|
332
|
+
originalMethods.aggregationCursorNext = AggregationCursor.prototype.next;
|
|
333
|
+
AggregationCursor.prototype.next = async function() {
|
|
334
|
+
const doc = await originalMethods.aggregationCursorNext.call(this);
|
|
335
|
+
return doc ? wrapSingleDoc(doc) : null;
|
|
336
|
+
};
|
|
337
|
+
originalMethods.aggregationCursorIterator = AggregationCursor.prototype[Symbol.asyncIterator];
|
|
338
|
+
AggregationCursor.prototype[Symbol.asyncIterator] = async function* () {
|
|
339
|
+
const iterator = originalMethods.aggregationCursorIterator.call(this);
|
|
340
|
+
for await (const doc of iterator) {
|
|
341
|
+
yield wrapSingleDoc(doc);
|
|
342
|
+
}
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
if (Collection?.prototype) {
|
|
346
|
+
originalMethods.collectionFindOne = Collection.prototype.findOne;
|
|
347
|
+
Collection.prototype.findOne = async function(...args) {
|
|
348
|
+
const doc = await originalMethods.collectionFindOne.apply(this, args);
|
|
349
|
+
return doc ? wrapSingleDoc(doc) : null;
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
async function unpatchMongoDB() {
|
|
354
|
+
let mongodb;
|
|
355
|
+
try {
|
|
356
|
+
mongodb = await import('mongodb');
|
|
357
|
+
} catch {
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
const { FindCursor, AggregationCursor, Collection } = mongodb;
|
|
361
|
+
if (FindCursor?.prototype && originalMethods.findCursorToArray) {
|
|
362
|
+
FindCursor.prototype.toArray = originalMethods.findCursorToArray;
|
|
363
|
+
FindCursor.prototype.next = originalMethods.findCursorNext;
|
|
364
|
+
FindCursor.prototype[Symbol.asyncIterator] = originalMethods.findCursorIterator;
|
|
365
|
+
}
|
|
366
|
+
if (AggregationCursor?.prototype && originalMethods.aggregationCursorToArray) {
|
|
367
|
+
AggregationCursor.prototype.toArray = originalMethods.aggregationCursorToArray;
|
|
368
|
+
AggregationCursor.prototype.next = originalMethods.aggregationCursorNext;
|
|
369
|
+
AggregationCursor.prototype[Symbol.asyncIterator] = originalMethods.aggregationCursorIterator;
|
|
370
|
+
}
|
|
371
|
+
if (Collection?.prototype && originalMethods.collectionFindOne) {
|
|
372
|
+
Collection.prototype.findOne = originalMethods.collectionFindOne;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
async function terseMongo(options = {}) {
|
|
376
|
+
if (isPatched) {
|
|
377
|
+
globalOptions = { minArrayLength: 1, ...options };
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
globalOptions = { minArrayLength: 1, ...options };
|
|
381
|
+
await patchMongoDB();
|
|
382
|
+
isPatched = true;
|
|
383
|
+
}
|
|
384
|
+
function terseMongoSync(options = {}) {
|
|
385
|
+
if (isPatched) {
|
|
386
|
+
globalOptions = { minArrayLength: 1, ...options };
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
globalOptions = { minArrayLength: 1, ...options };
|
|
390
|
+
let mongodb;
|
|
391
|
+
try {
|
|
392
|
+
mongodb = __require("mongodb");
|
|
393
|
+
} catch {
|
|
394
|
+
throw new Error(
|
|
395
|
+
"terseMongo requires mongodb to be installed. Run: npm install mongodb"
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
const { FindCursor, AggregationCursor, Collection } = mongodb;
|
|
399
|
+
if (FindCursor?.prototype) {
|
|
400
|
+
originalMethods.findCursorToArray = FindCursor.prototype.toArray;
|
|
401
|
+
FindCursor.prototype.toArray = async function() {
|
|
402
|
+
const results = await originalMethods.findCursorToArray.call(this);
|
|
403
|
+
return wrapResults(results);
|
|
404
|
+
};
|
|
405
|
+
originalMethods.findCursorNext = FindCursor.prototype.next;
|
|
406
|
+
FindCursor.prototype.next = async function() {
|
|
407
|
+
const doc = await originalMethods.findCursorNext.call(this);
|
|
408
|
+
return doc ? wrapSingleDoc(doc) : null;
|
|
409
|
+
};
|
|
410
|
+
originalMethods.findCursorIterator = FindCursor.prototype[Symbol.asyncIterator];
|
|
411
|
+
FindCursor.prototype[Symbol.asyncIterator] = async function* () {
|
|
412
|
+
const iterator = originalMethods.findCursorIterator.call(this);
|
|
413
|
+
for await (const doc of iterator) {
|
|
414
|
+
yield wrapSingleDoc(doc);
|
|
415
|
+
}
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
if (AggregationCursor?.prototype) {
|
|
419
|
+
originalMethods.aggregationCursorToArray = AggregationCursor.prototype.toArray;
|
|
420
|
+
AggregationCursor.prototype.toArray = async function() {
|
|
421
|
+
const results = await originalMethods.aggregationCursorToArray.call(this);
|
|
422
|
+
return wrapResults(results);
|
|
423
|
+
};
|
|
424
|
+
originalMethods.aggregationCursorNext = AggregationCursor.prototype.next;
|
|
425
|
+
AggregationCursor.prototype.next = async function() {
|
|
426
|
+
const doc = await originalMethods.aggregationCursorNext.call(this);
|
|
427
|
+
return doc ? wrapSingleDoc(doc) : null;
|
|
428
|
+
};
|
|
429
|
+
originalMethods.aggregationCursorIterator = AggregationCursor.prototype[Symbol.asyncIterator];
|
|
430
|
+
AggregationCursor.prototype[Symbol.asyncIterator] = async function* () {
|
|
431
|
+
const iterator = originalMethods.aggregationCursorIterator.call(this);
|
|
432
|
+
for await (const doc of iterator) {
|
|
433
|
+
yield wrapSingleDoc(doc);
|
|
434
|
+
}
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
if (Collection?.prototype) {
|
|
438
|
+
originalMethods.collectionFindOne = Collection.prototype.findOne;
|
|
439
|
+
Collection.prototype.findOne = async function(...args) {
|
|
440
|
+
const doc = await originalMethods.collectionFindOne.apply(this, args);
|
|
441
|
+
return doc ? wrapSingleDoc(doc) : null;
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
isPatched = true;
|
|
445
|
+
}
|
|
446
|
+
async function unterse() {
|
|
447
|
+
if (!isPatched) return;
|
|
448
|
+
await unpatchMongoDB();
|
|
449
|
+
Object.keys(originalMethods).forEach((key) => {
|
|
450
|
+
delete originalMethods[key];
|
|
451
|
+
});
|
|
452
|
+
isPatched = false;
|
|
453
|
+
globalOptions = {};
|
|
454
|
+
}
|
|
455
|
+
function isTerseMongoActive() {
|
|
456
|
+
return isPatched;
|
|
457
|
+
}
|
|
458
|
+
function getTerseMongoOptions() {
|
|
459
|
+
return { ...globalOptions };
|
|
460
|
+
}
|
|
461
|
+
function setTerseMongoOptions(options) {
|
|
462
|
+
globalOptions = { ...globalOptions, ...options };
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
exports.getTerseMongoOptions = getTerseMongoOptions;
|
|
466
|
+
exports.isTerseMongoActive = isTerseMongoActive;
|
|
467
|
+
exports.setTerseMongoOptions = setTerseMongoOptions;
|
|
468
|
+
exports.terseMongo = terseMongo;
|
|
469
|
+
exports.terseMongoSync = terseMongoSync;
|
|
470
|
+
exports.unterse = unterse;
|
|
471
|
+
//# sourceMappingURL=mongodb.js.map
|
|
472
|
+
//# sourceMappingURL=mongodb.js.map
|