qhttpx 2.1.0 → 2.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/LICENSE +201 -21
- package/README.md +117 -221
- package/dist/chunk-QW72SEAS.mjs +98 -0
- package/dist/{src/cli/index.d.ts → cli.d.mts} +0 -1
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +287 -0
- package/dist/cli.mjs +209 -0
- package/dist/index.d.mts +433 -0
- package/dist/index.d.ts +433 -0
- package/dist/index.js +1955 -0
- package/dist/index.mjs +1863 -0
- package/dist/qhttpx-core-new.linux-x64-gnu.node +0 -0
- package/dist/qhttpx-core-new.node +0 -0
- package/dist/qhttpx-core-new.win32-x64-msvc.node +0 -0
- package/examples/benchmark.ts +67 -0
- package/examples/body_demo.ts +32 -0
- package/examples/chat_client.ts +36 -0
- package/examples/chat_demo.ts +41 -0
- package/examples/cluster_demo.ts +26 -0
- package/examples/cors_demo.ts +25 -0
- package/examples/db_auth_demo.ts +66 -0
- package/examples/demo.ts +52 -0
- package/examples/headers_demo.ts +24 -0
- package/examples/hello.ts +7 -0
- package/examples/http2_demo.ts +52 -0
- package/examples/magic-dev.ts +15 -0
- package/examples/middleware_demo.ts +34 -0
- package/examples/mongo_demo.ts +40 -0
- package/examples/native_policy_demo.ts +33 -0
- package/examples/observability_demo.ts +24 -0
- package/examples/public/1mb.dat +1 -0
- package/examples/query_demo.ts +29 -0
- package/examples/response_demo.ts +21 -0
- package/examples/routing_demo.ts +24 -0
- package/examples/server.ts +51 -0
- package/examples/static_demo.ts +29 -0
- package/examples/test_middleware_client.ts +33 -0
- package/examples/test_query_client.ts +34 -0
- package/examples/test_response_client.ts +30 -0
- package/examples/tls_demo.ts +32 -0
- package/examples/upload_demo.ts +43 -0
- package/examples/uploads/test.txt +1 -0
- package/examples/verify_upload.ts +69 -0
- package/examples/ws_client.ts +26 -0
- package/examples/ws_demo.ts +21 -0
- package/package.json +65 -81
- package/CHANGELOG.md +0 -285
- package/dist/examples/api-server.d.ts +0 -1
- package/dist/examples/api-server.js +0 -80
- package/dist/examples/basic.d.ts +0 -1
- package/dist/examples/basic.js +0 -9
- package/dist/examples/compression.d.ts +0 -1
- package/dist/examples/compression.js +0 -15
- package/dist/examples/cors.d.ts +0 -1
- package/dist/examples/cors.js +0 -18
- package/dist/examples/errors.d.ts +0 -1
- package/dist/examples/errors.js +0 -26
- package/dist/examples/file-upload.d.ts +0 -1
- package/dist/examples/file-upload.js +0 -22
- package/dist/examples/fusion.d.ts +0 -1
- package/dist/examples/fusion.js +0 -21
- package/dist/examples/rate-limiting.d.ts +0 -1
- package/dist/examples/rate-limiting.js +0 -17
- package/dist/examples/validation.d.ts +0 -1
- package/dist/examples/validation.js +0 -22
- package/dist/examples/websockets.d.ts +0 -1
- package/dist/examples/websockets.js +0 -19
- package/dist/package.json +0 -107
- package/dist/src/benchmarks/quantam-users.d.ts +0 -1
- package/dist/src/benchmarks/quantam-users.js +0 -56
- package/dist/src/benchmarks/quick-bench.d.ts +0 -1
- package/dist/src/benchmarks/quick-bench.js +0 -57
- package/dist/src/benchmarks/simple-json.d.ts +0 -1
- package/dist/src/benchmarks/simple-json.js +0 -171
- package/dist/src/benchmarks/ultra-mode.d.ts +0 -1
- package/dist/src/benchmarks/ultra-mode.js +0 -64
- package/dist/src/cli/index.js +0 -222
- package/dist/src/client/index.d.ts +0 -17
- package/dist/src/client/index.js +0 -72
- package/dist/src/core/batch.d.ts +0 -24
- package/dist/src/core/batch.js +0 -97
- package/dist/src/core/body-parser.d.ts +0 -15
- package/dist/src/core/body-parser.js +0 -121
- package/dist/src/core/buffer-pool.d.ts +0 -41
- package/dist/src/core/buffer-pool.js +0 -70
- package/dist/src/core/config.d.ts +0 -7
- package/dist/src/core/config.js +0 -50
- package/dist/src/core/context-pool.d.ts +0 -12
- package/dist/src/core/context-pool.js +0 -34
- package/dist/src/core/errors.d.ts +0 -34
- package/dist/src/core/errors.js +0 -70
- package/dist/src/core/fusion.d.ts +0 -20
- package/dist/src/core/fusion.js +0 -191
- package/dist/src/core/logger.d.ts +0 -22
- package/dist/src/core/logger.js +0 -49
- package/dist/src/core/metrics.d.ts +0 -50
- package/dist/src/core/metrics.js +0 -123
- package/dist/src/core/resources.d.ts +0 -9
- package/dist/src/core/resources.js +0 -25
- package/dist/src/core/scheduler.d.ts +0 -38
- package/dist/src/core/scheduler.js +0 -126
- package/dist/src/core/scope.d.ts +0 -41
- package/dist/src/core/scope.js +0 -107
- package/dist/src/core/serializer.d.ts +0 -10
- package/dist/src/core/serializer.js +0 -82
- package/dist/src/core/server.d.ts +0 -179
- package/dist/src/core/server.js +0 -1511
- package/dist/src/core/stream.d.ts +0 -15
- package/dist/src/core/stream.js +0 -71
- package/dist/src/core/tasks.d.ts +0 -29
- package/dist/src/core/tasks.js +0 -87
- package/dist/src/core/timer.d.ts +0 -11
- package/dist/src/core/timer.js +0 -29
- package/dist/src/core/types.d.ts +0 -225
- package/dist/src/core/types.js +0 -19
- package/dist/src/core/websocket.d.ts +0 -25
- package/dist/src/core/websocket.js +0 -86
- package/dist/src/core/worker-queue.d.ts +0 -41
- package/dist/src/core/worker-queue.js +0 -73
- package/dist/src/database/adapters/memory.d.ts +0 -21
- package/dist/src/database/adapters/memory.js +0 -90
- package/dist/src/database/adapters/mongo.d.ts +0 -11
- package/dist/src/database/adapters/mongo.js +0 -141
- package/dist/src/database/adapters/postgres.d.ts +0 -10
- package/dist/src/database/adapters/postgres.js +0 -111
- package/dist/src/database/adapters/sqlite.d.ts +0 -10
- package/dist/src/database/adapters/sqlite.js +0 -42
- package/dist/src/database/coalescer.d.ts +0 -14
- package/dist/src/database/coalescer.js +0 -134
- package/dist/src/database/manager.d.ts +0 -35
- package/dist/src/database/manager.js +0 -87
- package/dist/src/database/types.d.ts +0 -20
- package/dist/src/database/types.js +0 -2
- package/dist/src/index.d.ts +0 -52
- package/dist/src/index.js +0 -92
- package/dist/src/middleware/compression.d.ts +0 -2
- package/dist/src/middleware/compression.js +0 -133
- package/dist/src/middleware/cors.d.ts +0 -2
- package/dist/src/middleware/cors.js +0 -66
- package/dist/src/middleware/presets.d.ts +0 -15
- package/dist/src/middleware/presets.js +0 -52
- package/dist/src/middleware/rate-limit.d.ts +0 -14
- package/dist/src/middleware/rate-limit.js +0 -83
- package/dist/src/middleware/security.d.ts +0 -10
- package/dist/src/middleware/security.js +0 -74
- package/dist/src/middleware/static.d.ts +0 -11
- package/dist/src/middleware/static.js +0 -191
- package/dist/src/openapi/generator.d.ts +0 -19
- package/dist/src/openapi/generator.js +0 -149
- package/dist/src/router/radix-router.d.ts +0 -18
- package/dist/src/router/radix-router.js +0 -89
- package/dist/src/router/radix-tree.d.ts +0 -21
- package/dist/src/router/radix-tree.js +0 -175
- package/dist/src/router/router.d.ts +0 -37
- package/dist/src/router/router.js +0 -203
- package/dist/src/testing/index.d.ts +0 -25
- package/dist/src/testing/index.js +0 -84
- package/dist/src/utils/cookies.d.ts +0 -3
- package/dist/src/utils/cookies.js +0 -59
- package/dist/src/utils/logger.d.ts +0 -2
- package/dist/src/utils/logger.js +0 -45
- package/dist/src/utils/signals.d.ts +0 -6
- package/dist/src/utils/signals.js +0 -31
- package/dist/src/utils/sse.d.ts +0 -6
- package/dist/src/utils/sse.js +0 -32
- package/dist/src/validation/index.d.ts +0 -3
- package/dist/src/validation/index.js +0 -19
- package/dist/src/validation/simple.d.ts +0 -5
- package/dist/src/validation/simple.js +0 -102
- package/dist/src/validation/types.d.ts +0 -32
- package/dist/src/validation/types.js +0 -12
- package/dist/src/validation/zod.d.ts +0 -4
- package/dist/src/validation/zod.js +0 -18
- package/dist/src/views/index.d.ts +0 -1
- package/dist/src/views/index.js +0 -17
- package/dist/src/views/types.d.ts +0 -3
- package/dist/src/views/types.js +0 -2
- package/dist/tests/adapters.test.d.ts +0 -1
- package/dist/tests/adapters.test.js +0 -106
- package/dist/tests/batch.test.d.ts +0 -1
- package/dist/tests/batch.test.js +0 -117
- package/dist/tests/body-parser.test.d.ts +0 -1
- package/dist/tests/body-parser.test.js +0 -52
- package/dist/tests/compression-sse.test.d.ts +0 -1
- package/dist/tests/compression-sse.test.js +0 -87
- package/dist/tests/cookies.test.d.ts +0 -1
- package/dist/tests/cookies.test.js +0 -63
- package/dist/tests/cors.test.d.ts +0 -1
- package/dist/tests/cors.test.js +0 -55
- package/dist/tests/database.test.d.ts +0 -1
- package/dist/tests/database.test.js +0 -80
- package/dist/tests/dx.test.d.ts +0 -1
- package/dist/tests/dx.test.js +0 -114
- package/dist/tests/ecosystem.test.d.ts +0 -1
- package/dist/tests/ecosystem.test.js +0 -133
- package/dist/tests/features.test.d.ts +0 -1
- package/dist/tests/features.test.js +0 -47
- package/dist/tests/fusion.test.d.ts +0 -1
- package/dist/tests/fusion.test.js +0 -92
- package/dist/tests/http-basic.test.d.ts +0 -1
- package/dist/tests/http-basic.test.js +0 -124
- package/dist/tests/logger.test.d.ts +0 -1
- package/dist/tests/logger.test.js +0 -33
- package/dist/tests/middleware.test.d.ts +0 -1
- package/dist/tests/middleware.test.js +0 -109
- package/dist/tests/observability.test.d.ts +0 -1
- package/dist/tests/observability.test.js +0 -59
- package/dist/tests/openapi.test.d.ts +0 -1
- package/dist/tests/openapi.test.js +0 -64
- package/dist/tests/plugin.test.d.ts +0 -1
- package/dist/tests/plugin.test.js +0 -65
- package/dist/tests/plugins.test.d.ts +0 -1
- package/dist/tests/plugins.test.js +0 -71
- package/dist/tests/rate-limit.test.d.ts +0 -1
- package/dist/tests/rate-limit.test.js +0 -77
- package/dist/tests/resources.test.d.ts +0 -1
- package/dist/tests/resources.test.js +0 -47
- package/dist/tests/scheduler.test.d.ts +0 -1
- package/dist/tests/scheduler.test.js +0 -46
- package/dist/tests/schema-routes.test.d.ts +0 -1
- package/dist/tests/schema-routes.test.js +0 -79
- package/dist/tests/security.test.d.ts +0 -1
- package/dist/tests/security.test.js +0 -83
- package/dist/tests/server-db.test.d.ts +0 -1
- package/dist/tests/server-db.test.js +0 -72
- package/dist/tests/smoke.test.d.ts +0 -1
- package/dist/tests/smoke.test.js +0 -10
- package/dist/tests/sqlite-fusion.test.d.ts +0 -1
- package/dist/tests/sqlite-fusion.test.js +0 -92
- package/dist/tests/static.test.d.ts +0 -1
- package/dist/tests/static.test.js +0 -102
- package/dist/tests/stream.test.d.ts +0 -1
- package/dist/tests/stream.test.js +0 -44
- package/dist/tests/task-metrics.test.d.ts +0 -1
- package/dist/tests/task-metrics.test.js +0 -53
- package/dist/tests/tasks.test.d.ts +0 -1
- package/dist/tests/tasks.test.js +0 -62
- package/dist/tests/testing.test.d.ts +0 -1
- package/dist/tests/testing.test.js +0 -47
- package/dist/tests/validation.test.d.ts +0 -1
- package/dist/tests/validation.test.js +0 -107
- package/dist/tests/websocket.test.d.ts +0 -1
- package/dist/tests/websocket.test.js +0 -146
- package/dist/vitest.config.d.ts +0 -2
- package/dist/vitest.config.js +0 -9
- package/docs/AEGIS.md +0 -91
- package/docs/API_REFERENCE.md +0 -749
- package/docs/BENCHMARKS.md +0 -39
- package/docs/CAPABILITIES.md +0 -70
- package/docs/CLI.md +0 -43
- package/docs/DATABASE.md +0 -142
- package/docs/ECOSYSTEM.md +0 -146
- package/docs/ERRORS.md +0 -112
- package/docs/FUSION.md +0 -87
- package/docs/MIDDLEWARE.md +0 -65
- package/docs/MIGRATION_1.9_TO_2.0.md +0 -495
- package/docs/NEXT_STEPS.md +0 -99
- package/docs/OPENAPI.md +0 -99
- package/docs/PLUGINS.md +0 -59
- package/docs/PRODUCTION_DEPLOYMENT.md +0 -798
- package/docs/REAL_WORLD_EXAMPLES.md +0 -109
- package/docs/ROADMAP.md +0 -366
- package/docs/ROUTING.md +0 -78
- package/docs/SECURITY.md +0 -876
- package/docs/STATIC.md +0 -61
- package/docs/VALIDATION.md +0 -114
- package/docs/WEBSOCKETS.md +0 -76
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Lock-free (or lock-minimal) work queue for per-worker task distribution.
|
|
4
|
-
* Uses a simple ring buffer for high throughput.
|
|
5
|
-
*/
|
|
6
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.WorkerQueue = void 0;
|
|
8
|
-
class WorkerQueue {
|
|
9
|
-
constructor(capacity = 1024) {
|
|
10
|
-
this.writeIndex = 0;
|
|
11
|
-
this.readIndex = 0;
|
|
12
|
-
this.size = 0;
|
|
13
|
-
if (capacity <= 0 || !Number.isInteger(capacity)) {
|
|
14
|
-
throw new Error('Capacity must be a positive integer');
|
|
15
|
-
}
|
|
16
|
-
// Ensure capacity is a power of 2 for efficient modulo with bitmask
|
|
17
|
-
this.capacity = Math.pow(2, Math.ceil(Math.log2(capacity)));
|
|
18
|
-
this.buffer = new Array(this.capacity);
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Enqueue a work item. Returns true if successful, false if queue is full.
|
|
22
|
-
*/
|
|
23
|
-
enqueue(item) {
|
|
24
|
-
if (this.size >= this.capacity) {
|
|
25
|
-
return false;
|
|
26
|
-
}
|
|
27
|
-
this.buffer[this.writeIndex] = item;
|
|
28
|
-
this.writeIndex = (this.writeIndex + 1) & (this.capacity - 1);
|
|
29
|
-
this.size += 1;
|
|
30
|
-
return true;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Dequeue a work item. Returns undefined if queue is empty.
|
|
34
|
-
*/
|
|
35
|
-
dequeue() {
|
|
36
|
-
if (this.size <= 0) {
|
|
37
|
-
return undefined;
|
|
38
|
-
}
|
|
39
|
-
const item = this.buffer[this.readIndex];
|
|
40
|
-
this.buffer[this.readIndex] = undefined;
|
|
41
|
-
this.readIndex = (this.readIndex + 1) & (this.capacity - 1);
|
|
42
|
-
this.size -= 1;
|
|
43
|
-
return item;
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Peek at the next item without removing it.
|
|
47
|
-
*/
|
|
48
|
-
peek() {
|
|
49
|
-
if (this.size <= 0) {
|
|
50
|
-
return undefined;
|
|
51
|
-
}
|
|
52
|
-
return this.buffer[this.readIndex];
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Check if the queue is empty.
|
|
56
|
-
*/
|
|
57
|
-
isEmpty() {
|
|
58
|
-
return this.size === 0;
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Get the current size of the queue.
|
|
62
|
-
*/
|
|
63
|
-
getSize() {
|
|
64
|
-
return this.size;
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Get the capacity of the queue.
|
|
68
|
-
*/
|
|
69
|
-
getCapacity() {
|
|
70
|
-
return this.capacity;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
exports.WorkerQueue = WorkerQueue;
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { DatabaseAdapter, DatabaseConfig } from '../types';
|
|
2
|
-
export declare class MemoryAdapter implements DatabaseAdapter {
|
|
3
|
-
private config;
|
|
4
|
-
private connected;
|
|
5
|
-
private collections;
|
|
6
|
-
constructor(config: DatabaseConfig);
|
|
7
|
-
connect(): Promise<void>;
|
|
8
|
-
disconnect(): Promise<void>;
|
|
9
|
-
isConnected(): boolean;
|
|
10
|
-
/**
|
|
11
|
-
* Execute a query against the in-memory database
|
|
12
|
-
* @param query Object specifying collection, action, and parameters
|
|
13
|
-
* @example
|
|
14
|
-
* // Find
|
|
15
|
-
* query({ collection: 'users', action: 'find', filter: { id: 1 } })
|
|
16
|
-
* // Insert
|
|
17
|
-
* query({ collection: 'users', action: 'insert', data: { name: 'Alice' } })
|
|
18
|
-
*/
|
|
19
|
-
query<T = any>(query: any): Promise<T>;
|
|
20
|
-
private matches;
|
|
21
|
-
}
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MemoryAdapter = void 0;
|
|
4
|
-
class MemoryAdapter {
|
|
5
|
-
constructor(config) {
|
|
6
|
-
this.config = config;
|
|
7
|
-
this.connected = false;
|
|
8
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
9
|
-
this.collections = new Map();
|
|
10
|
-
}
|
|
11
|
-
async connect() {
|
|
12
|
-
// Simulate connection delay
|
|
13
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
14
|
-
this.connected = true;
|
|
15
|
-
}
|
|
16
|
-
async disconnect() {
|
|
17
|
-
this.connected = false;
|
|
18
|
-
this.collections.clear();
|
|
19
|
-
}
|
|
20
|
-
isConnected() {
|
|
21
|
-
return this.connected;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Execute a query against the in-memory database
|
|
25
|
-
* @param query Object specifying collection, action, and parameters
|
|
26
|
-
* @example
|
|
27
|
-
* // Find
|
|
28
|
-
* query({ collection: 'users', action: 'find', filter: { id: 1 } })
|
|
29
|
-
* // Insert
|
|
30
|
-
* query({ collection: 'users', action: 'insert', data: { name: 'Alice' } })
|
|
31
|
-
*/
|
|
32
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
33
|
-
async query(query) {
|
|
34
|
-
if (!this.connected) {
|
|
35
|
-
throw new Error('Database not connected');
|
|
36
|
-
}
|
|
37
|
-
const { collection, action, data, filter } = query;
|
|
38
|
-
if (!collection || !action) {
|
|
39
|
-
throw new Error('Query must specify collection and action');
|
|
40
|
-
}
|
|
41
|
-
if (!this.collections.has(collection)) {
|
|
42
|
-
this.collections.set(collection, []);
|
|
43
|
-
}
|
|
44
|
-
const store = this.collections.get(collection);
|
|
45
|
-
switch (action) {
|
|
46
|
-
case 'find':
|
|
47
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
48
|
-
if (!filter)
|
|
49
|
-
return store;
|
|
50
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
51
|
-
return store.filter(item => this.matches(item, filter));
|
|
52
|
-
case 'findOne':
|
|
53
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
54
|
-
if (!filter)
|
|
55
|
-
return store[0];
|
|
56
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
57
|
-
return store.find(item => this.matches(item, filter));
|
|
58
|
-
case 'insert':
|
|
59
|
-
const newItem = { id: Date.now(), ...data };
|
|
60
|
-
store.push(newItem);
|
|
61
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
62
|
-
return newItem;
|
|
63
|
-
case 'update':
|
|
64
|
-
let updatedCount = 0;
|
|
65
|
-
store.forEach((item, index) => {
|
|
66
|
-
if (this.matches(item, filter)) {
|
|
67
|
-
store[index] = { ...item, ...data };
|
|
68
|
-
updatedCount++;
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
72
|
-
return updatedCount;
|
|
73
|
-
case 'delete':
|
|
74
|
-
const initialLength = store.length;
|
|
75
|
-
const newStore = store.filter(item => !this.matches(item, filter));
|
|
76
|
-
this.collections.set(collection, newStore);
|
|
77
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
78
|
-
return (initialLength - newStore.length);
|
|
79
|
-
default:
|
|
80
|
-
throw new Error(`Unknown action: ${action}`);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
84
|
-
matches(item, filter) {
|
|
85
|
-
if (!filter)
|
|
86
|
-
return true;
|
|
87
|
-
return Object.entries(filter).every(([key, value]) => item[key] === value);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
exports.MemoryAdapter = MemoryAdapter;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { DatabaseAdapter, DatabaseConfig } from '../types';
|
|
2
|
-
export declare class MongoAdapter implements DatabaseAdapter {
|
|
3
|
-
private client;
|
|
4
|
-
private db;
|
|
5
|
-
private config;
|
|
6
|
-
constructor(config: DatabaseConfig);
|
|
7
|
-
connect(): Promise<void>;
|
|
8
|
-
disconnect(): Promise<void>;
|
|
9
|
-
query<T = any>(query: string | object, params?: any[]): Promise<T>;
|
|
10
|
-
isConnected(): boolean;
|
|
11
|
-
}
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.MongoAdapter = void 0;
|
|
37
|
-
class MongoAdapter {
|
|
38
|
-
constructor(config) {
|
|
39
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
40
|
-
this.client = null;
|
|
41
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
42
|
-
this.db = null;
|
|
43
|
-
this.config = config;
|
|
44
|
-
}
|
|
45
|
-
async connect() {
|
|
46
|
-
if (this.client)
|
|
47
|
-
return;
|
|
48
|
-
try {
|
|
49
|
-
const mongodb = await Promise.resolve().then(() => __importStar(require('mongodb')));
|
|
50
|
-
const { MongoClient } = mongodb.default || mongodb;
|
|
51
|
-
const url = this.config.url || `mongodb://${this.config.host || 'localhost'}:${this.config.port || 27017}`;
|
|
52
|
-
this.client = new MongoClient(url, {
|
|
53
|
-
auth: this.config.username ? {
|
|
54
|
-
username: this.config.username,
|
|
55
|
-
password: this.config.password
|
|
56
|
-
} : undefined,
|
|
57
|
-
...this.config.options
|
|
58
|
-
});
|
|
59
|
-
await this.client.connect();
|
|
60
|
-
this.db = this.client.db(this.config.database);
|
|
61
|
-
}
|
|
62
|
-
catch (err) {
|
|
63
|
-
if (err.message.includes('Cannot find module')) {
|
|
64
|
-
throw new Error('MongoDB driver not found. Please run: npm install mongodb');
|
|
65
|
-
}
|
|
66
|
-
throw err;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
async disconnect() {
|
|
70
|
-
if (this.client) {
|
|
71
|
-
await this.client.close();
|
|
72
|
-
this.client = null;
|
|
73
|
-
this.db = null;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
77
|
-
async query(query, params) {
|
|
78
|
-
if (!this.db) {
|
|
79
|
-
throw new Error('Database not connected');
|
|
80
|
-
}
|
|
81
|
-
// MongoDB "query" is usually a collection.find() or similar.
|
|
82
|
-
// We need a convention here.
|
|
83
|
-
// Convention: query is a JSON object with { collection: 'name', action: 'find', filter: {}, ... }
|
|
84
|
-
// OR: query is just the collection name, and params[0] is the operation?
|
|
85
|
-
// Let's go with a structured object for maximum flexibility if passed as object.
|
|
86
|
-
// If query is string, maybe it's just collection name?
|
|
87
|
-
// Let's support a simple object-based API:
|
|
88
|
-
// db.query({ collection: 'users', action: 'find', filter: { id: 1 } })
|
|
89
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
90
|
-
let op = query;
|
|
91
|
-
if (typeof query === 'string') {
|
|
92
|
-
// Fallback or simple format?
|
|
93
|
-
// Maybe "users.find" ?
|
|
94
|
-
const parts = query.split('.');
|
|
95
|
-
if (parts.length >= 2) {
|
|
96
|
-
op = {
|
|
97
|
-
collection: parts[0],
|
|
98
|
-
action: parts[1],
|
|
99
|
-
filter: params?.[0]
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
else {
|
|
103
|
-
throw new Error('Invalid MongoDB query format. Use object or "collection.action" string.');
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
const collection = this.db.collection(op.collection);
|
|
107
|
-
switch (op.action) {
|
|
108
|
-
case 'find':
|
|
109
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
110
|
-
const cursor = collection.find(op.filter || {});
|
|
111
|
-
if (op.limit)
|
|
112
|
-
cursor.limit(op.limit);
|
|
113
|
-
if (op.skip)
|
|
114
|
-
cursor.skip(op.skip);
|
|
115
|
-
return (await cursor.toArray());
|
|
116
|
-
case 'findOne':
|
|
117
|
-
return (await collection.findOne(op.filter || {}));
|
|
118
|
-
case 'insertOne':
|
|
119
|
-
return (await collection.insertOne(op.doc || params?.[0]));
|
|
120
|
-
case 'insertMany':
|
|
121
|
-
return (await collection.insertMany(op.docs || params?.[0]));
|
|
122
|
-
case 'updateOne':
|
|
123
|
-
return (await collection.updateOne(op.filter, op.update || params?.[1]));
|
|
124
|
-
case 'updateMany':
|
|
125
|
-
return (await collection.updateMany(op.filter, op.update || params?.[1]));
|
|
126
|
-
case 'deleteOne':
|
|
127
|
-
return (await collection.deleteOne(op.filter));
|
|
128
|
-
case 'deleteMany':
|
|
129
|
-
return (await collection.deleteMany(op.filter));
|
|
130
|
-
case 'aggregate':
|
|
131
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
132
|
-
return (await collection.aggregate((op.pipeline || params)).toArray());
|
|
133
|
-
default:
|
|
134
|
-
throw new Error(`Unsupported MongoDB action: ${op.action}`);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
isConnected() {
|
|
138
|
-
return this.client !== null;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
exports.MongoAdapter = MongoAdapter;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { DatabaseAdapter, DatabaseConfig } from '../types';
|
|
2
|
-
export declare class PostgresAdapter implements DatabaseAdapter {
|
|
3
|
-
private pool;
|
|
4
|
-
private config;
|
|
5
|
-
constructor(config: DatabaseConfig);
|
|
6
|
-
connect(): Promise<void>;
|
|
7
|
-
disconnect(): Promise<void>;
|
|
8
|
-
query<T = any>(sql: string, params?: any[]): Promise<T>;
|
|
9
|
-
isConnected(): boolean;
|
|
10
|
-
}
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.PostgresAdapter = void 0;
|
|
37
|
-
class PostgresAdapter {
|
|
38
|
-
constructor(config) {
|
|
39
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
40
|
-
this.pool = null;
|
|
41
|
-
this.config = config;
|
|
42
|
-
}
|
|
43
|
-
async connect() {
|
|
44
|
-
if (this.pool)
|
|
45
|
-
return;
|
|
46
|
-
try {
|
|
47
|
-
// Dynamic import
|
|
48
|
-
const pg = await Promise.resolve().then(() => __importStar(require('pg')));
|
|
49
|
-
const { Pool } = pg.default || pg;
|
|
50
|
-
this.pool = new Pool({
|
|
51
|
-
host: this.config.host,
|
|
52
|
-
port: this.config.port || 5432,
|
|
53
|
-
user: this.config.username,
|
|
54
|
-
password: this.config.password,
|
|
55
|
-
database: this.config.database,
|
|
56
|
-
// Postgres-specific options can be passed via config.options
|
|
57
|
-
...this.config.options
|
|
58
|
-
});
|
|
59
|
-
// Verify connection
|
|
60
|
-
const client = await this.pool.connect();
|
|
61
|
-
client.release();
|
|
62
|
-
}
|
|
63
|
-
catch (err) {
|
|
64
|
-
if (err.message.includes('Cannot find module')) {
|
|
65
|
-
throw new Error('PostgreSQL driver not found. Please run: npm install pg');
|
|
66
|
-
}
|
|
67
|
-
throw err;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
async disconnect() {
|
|
71
|
-
if (this.pool) {
|
|
72
|
-
await this.pool.end();
|
|
73
|
-
this.pool = null;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
77
|
-
async query(sql, params) {
|
|
78
|
-
if (!this.pool) {
|
|
79
|
-
throw new Error('Database not connected');
|
|
80
|
-
}
|
|
81
|
-
try {
|
|
82
|
-
// pg supports parameterized queries using $1, $2, etc.
|
|
83
|
-
// But our Coalescer might be sending '?' if it's generic.
|
|
84
|
-
// If the user writes 'SELECT * FROM users WHERE id = $1', that's fine.
|
|
85
|
-
// If they write '?', we might need to convert it?
|
|
86
|
-
// For now, we assume the user provides SQL compatible with the underlying driver.
|
|
87
|
-
// Or we could implement a simple '?' -> '$n' converter if we want to standardize.
|
|
88
|
-
// Standardizing is better for the generic "engine" feel.
|
|
89
|
-
if (sql.includes('?')) {
|
|
90
|
-
let i = 1;
|
|
91
|
-
sql = sql.replace(/\?/g, () => `$${i++}`);
|
|
92
|
-
}
|
|
93
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
94
|
-
const result = await this.pool.query(sql, params);
|
|
95
|
-
// Return rows for SELECT, or result meta for others?
|
|
96
|
-
// Our interface implies T.
|
|
97
|
-
// Usually users expect rows array for SELECT.
|
|
98
|
-
if (result.command === 'SELECT' || result.command === 'INSERT' && result.rows.length > 0) {
|
|
99
|
-
return result.rows;
|
|
100
|
-
}
|
|
101
|
-
return result;
|
|
102
|
-
}
|
|
103
|
-
catch (err) {
|
|
104
|
-
throw err;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
isConnected() {
|
|
108
|
-
return this.pool !== null && !this.pool.ended;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
exports.PostgresAdapter = PostgresAdapter;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { DatabaseAdapter, DatabaseConfig } from '../types';
|
|
2
|
-
export declare class SQLiteAdapter implements DatabaseAdapter {
|
|
3
|
-
private db;
|
|
4
|
-
private config;
|
|
5
|
-
constructor(config: DatabaseConfig);
|
|
6
|
-
connect(): Promise<void>;
|
|
7
|
-
disconnect(): Promise<void>;
|
|
8
|
-
query<T = any>(sql: string, params?: any[]): Promise<T>;
|
|
9
|
-
isConnected(): boolean;
|
|
10
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.SQLiteAdapter = void 0;
|
|
7
|
-
const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
|
|
8
|
-
class SQLiteAdapter {
|
|
9
|
-
constructor(config) {
|
|
10
|
-
this.db = null;
|
|
11
|
-
this.config = config;
|
|
12
|
-
}
|
|
13
|
-
async connect() {
|
|
14
|
-
const filename = this.config.database || ':memory:';
|
|
15
|
-
this.db = new better_sqlite3_1.default(filename, this.config.options);
|
|
16
|
-
}
|
|
17
|
-
async disconnect() {
|
|
18
|
-
if (this.db) {
|
|
19
|
-
this.db.close();
|
|
20
|
-
this.db = null;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
24
|
-
async query(sql, params) {
|
|
25
|
-
if (!this.db) {
|
|
26
|
-
throw new Error('Database not connected');
|
|
27
|
-
}
|
|
28
|
-
const stmt = this.db.prepare(sql);
|
|
29
|
-
// better-sqlite3 handles '?' params automatically
|
|
30
|
-
// Determine if it's a read or write operation
|
|
31
|
-
if (sql.trim().toLowerCase().startsWith('select')) {
|
|
32
|
-
return stmt.all(params || []);
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
35
|
-
return stmt.run(params || []);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
isConnected() {
|
|
39
|
-
return this.db !== null && this.db.open;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
exports.SQLiteAdapter = SQLiteAdapter;
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { DatabaseAdapter } from './types';
|
|
2
|
-
export declare class QueryCoalescer<T = unknown> {
|
|
3
|
-
private pending;
|
|
4
|
-
private timeout;
|
|
5
|
-
private readonly adapter;
|
|
6
|
-
constructor(adapter: DatabaseAdapter);
|
|
7
|
-
/**
|
|
8
|
-
* Intercepts a query and attempts to coalesce it with others.
|
|
9
|
-
* Only supports simple queries of the form "SELECT ... WHERE col = ?" for now.
|
|
10
|
-
*/
|
|
11
|
-
query(query: string, params?: unknown[]): Promise<T>;
|
|
12
|
-
private scheduleFlush;
|
|
13
|
-
private flush;
|
|
14
|
-
}
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.QueryCoalescer = void 0;
|
|
4
|
-
// eslint-enable @typescript-eslint/no-explicit-any
|
|
5
|
-
class QueryCoalescer {
|
|
6
|
-
constructor(adapter) {
|
|
7
|
-
this.pending = new Map();
|
|
8
|
-
this.timeout = null;
|
|
9
|
-
this.adapter = adapter;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Intercepts a query and attempts to coalesce it with others.
|
|
13
|
-
* Only supports simple queries of the form "SELECT ... WHERE col = ?" for now.
|
|
14
|
-
*/
|
|
15
|
-
async query(query, params) {
|
|
16
|
-
// Basic check for coalescing eligibility:
|
|
17
|
-
// 1. Must have exactly one parameter (for simplicity in this v1)
|
|
18
|
-
// 2. Must contain " = ?" pattern
|
|
19
|
-
if (!params || params.length !== 1 || !query.includes(' = ?')) {
|
|
20
|
-
return this.adapter.query(query, params);
|
|
21
|
-
}
|
|
22
|
-
return new Promise((resolve, reject) => {
|
|
23
|
-
if (!this.pending.has(query)) {
|
|
24
|
-
this.pending.set(query, []);
|
|
25
|
-
}
|
|
26
|
-
this.pending.get(query).push({
|
|
27
|
-
query,
|
|
28
|
-
paramValue: params[0],
|
|
29
|
-
resolve: resolve,
|
|
30
|
-
reject
|
|
31
|
-
});
|
|
32
|
-
this.scheduleFlush();
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
scheduleFlush() {
|
|
36
|
-
if (this.timeout)
|
|
37
|
-
return;
|
|
38
|
-
// Use microtask or short timeout to gather queries from the current event loop tick
|
|
39
|
-
this.timeout = setTimeout(() => this.flush(), 0);
|
|
40
|
-
}
|
|
41
|
-
async flush() {
|
|
42
|
-
this.timeout = null;
|
|
43
|
-
const currentBatch = this.pending;
|
|
44
|
-
this.pending = new Map(); // Clear for next batch
|
|
45
|
-
for (const [originalQuery, items] of currentBatch.entries()) {
|
|
46
|
-
if (items.length === 1) {
|
|
47
|
-
// No fusion needed
|
|
48
|
-
const item = items[0];
|
|
49
|
-
try {
|
|
50
|
-
const result = await this.adapter.query(item.query, [item.paramValue]);
|
|
51
|
-
item.resolve(result);
|
|
52
|
-
}
|
|
53
|
-
catch (err) {
|
|
54
|
-
item.reject(err);
|
|
55
|
-
}
|
|
56
|
-
continue;
|
|
57
|
-
}
|
|
58
|
-
// Fuse queries
|
|
59
|
-
// Transform "SELECT * FROM table WHERE id = ?"
|
|
60
|
-
// into "SELECT * FROM table WHERE id IN (?, ?, ...)"
|
|
61
|
-
// Basic string manipulation (safe enough for this controlled feature)
|
|
62
|
-
// We assume the query ends with " = ?" or contains it clearly.
|
|
63
|
-
const fusedQuery = originalQuery.replace(' = ?', ` IN (${items.map(() => '?').join(', ')})`);
|
|
64
|
-
const allParams = items.map(i => i.paramValue);
|
|
65
|
-
try {
|
|
66
|
-
const results = await this.adapter.query(fusedQuery, allParams);
|
|
67
|
-
// Distribute results back to callers
|
|
68
|
-
// We need to map results back to params.
|
|
69
|
-
// This is the tricky part: standard SQL doesn't guarantee order matching input IN clause.
|
|
70
|
-
// We must assume the result objects contain the key used in WHERE.
|
|
71
|
-
// Extract the column name from the query
|
|
72
|
-
// "WHERE id = ?" -> "id"
|
|
73
|
-
const match = originalQuery.match(/WHERE\s+(\w+)\s*=\s*\?/i);
|
|
74
|
-
if (!match) {
|
|
75
|
-
// Fallback if we can't parse: execute individually (should not happen given check above)
|
|
76
|
-
await Promise.all(items.map(async (item) => {
|
|
77
|
-
try {
|
|
78
|
-
const r = await this.adapter.query(item.query, [item.paramValue]);
|
|
79
|
-
item.resolve(r);
|
|
80
|
-
}
|
|
81
|
-
catch (e) {
|
|
82
|
-
item.reject(e);
|
|
83
|
-
}
|
|
84
|
-
}));
|
|
85
|
-
continue;
|
|
86
|
-
}
|
|
87
|
-
const keyColumn = match[1];
|
|
88
|
-
// Map results by key
|
|
89
|
-
// Note: This assumes the result is an array of objects
|
|
90
|
-
// If the adapter returns something else, this might fail.
|
|
91
|
-
if (!Array.isArray(results)) {
|
|
92
|
-
// Fallback for non-array results
|
|
93
|
-
// Just give everyone the full result? No, that's wrong.
|
|
94
|
-
// If it's not an array, we probably can't split it.
|
|
95
|
-
// Reject? Or execute individually?
|
|
96
|
-
// Let's execute individually as fallback.
|
|
97
|
-
await Promise.all(items.map(async (item) => {
|
|
98
|
-
try {
|
|
99
|
-
const r = await this.adapter.query(item.query, [item.paramValue]);
|
|
100
|
-
item.resolve(r);
|
|
101
|
-
}
|
|
102
|
-
catch (e) {
|
|
103
|
-
item.reject(e);
|
|
104
|
-
}
|
|
105
|
-
}));
|
|
106
|
-
continue;
|
|
107
|
-
}
|
|
108
|
-
const resultMap = new Map();
|
|
109
|
-
results.forEach(row => {
|
|
110
|
-
if (typeof row === 'object' && row !== null && keyColumn in row) {
|
|
111
|
-
const typedRow = row;
|
|
112
|
-
const key = typedRow[keyColumn];
|
|
113
|
-
if (typeof key === 'string' || typeof key === 'number') {
|
|
114
|
-
if (!resultMap.has(key)) {
|
|
115
|
-
resultMap.set(key, []);
|
|
116
|
-
}
|
|
117
|
-
resultMap.get(key).push(row);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
items.forEach(item => {
|
|
122
|
-
const key = typeof item.paramValue === 'string' || typeof item.paramValue === 'number' ? item.paramValue : undefined;
|
|
123
|
-
const res = key !== undefined ? resultMap.get(key) || [] : [];
|
|
124
|
-
item.resolve(res);
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
catch (err) {
|
|
128
|
-
// Fail all
|
|
129
|
-
items.forEach(item => item.reject(err));
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
exports.QueryCoalescer = QueryCoalescer;
|