@effectuate/cubejs-mongosql-driver 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 +23 -0
- package/README.md +579 -0
- package/dist/MongoSqlDriver.d.ts +238 -0
- package/dist/MongoSqlDriver.d.ts.map +1 -0
- package/dist/MongoSqlDriver.js +745 -0
- package/dist/MongoSqlDriver.js.map +1 -0
- package/dist/MongoSqlQuery.d.ts +353 -0
- package/dist/MongoSqlQuery.d.ts.map +1 -0
- package/dist/MongoSqlQuery.js +551 -0
- package/dist/MongoSqlQuery.js.map +1 -0
- package/dist/config.d.ts +29 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +298 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/native.d.ts +104 -0
- package/dist/native.d.ts.map +1 -0
- package/dist/native.js +192 -0
- package/dist/native.js.map +1 -0
- package/dist/types.d.ts +49 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +24 -0
- package/dist/types.js.map +1 -0
- package/index.d.ts +160 -0
- package/index.js +316 -0
- package/package.json +108 -0
package/dist/config.js
ADDED
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveUriConfig = resolveUriConfig;
|
|
4
|
+
exports.parseDurationToMillis = parseDurationToMillis;
|
|
5
|
+
const TLS_ENV = {
|
|
6
|
+
envVar: 'CUBEJS_DB_SSL',
|
|
7
|
+
uriParam: 'tls',
|
|
8
|
+
parse: parseBoolToString,
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Mongo-specific tunables. The mongodb Rust crate matches URI keys
|
|
12
|
+
* case-insensitively (`options.rs:2262` `key.to_lowercase()`), but we
|
|
13
|
+
* emit standard MongoDB camelCase per
|
|
14
|
+
* https://www.mongodb.com/docs/manual/reference/connection-string-options/
|
|
15
|
+
* for readability and to match what users find in MongoDB docs.
|
|
16
|
+
*/
|
|
17
|
+
const URI_PARAM_SPECS = [
|
|
18
|
+
TLS_ENV,
|
|
19
|
+
{ envVar: 'CUBEJS_DB_MAX_POOL', uriParam: 'maxPoolSize', parse: parsePositiveInteger },
|
|
20
|
+
{ envVar: 'CUBEJS_DB_MIN_POOL', uriParam: 'minPoolSize', parse: parseNonNegativeInteger },
|
|
21
|
+
{ envVar: 'CUBEJS_DB_IDLE_TIMEOUT', uriParam: 'maxIdleTimeMS', parse: parseDurationToMillisString },
|
|
22
|
+
{ envVar: 'CUBEJS_MONGOSQL_MAX_CONNECTING', uriParam: 'maxConnecting', parse: parsePositiveInteger },
|
|
23
|
+
{ envVar: 'CUBEJS_MONGOSQL_WAIT_QUEUE_TIMEOUT_MS', uriParam: 'waitQueueTimeoutMS', parse: parseNonNegativeInteger },
|
|
24
|
+
{ envVar: 'CUBEJS_MONGOSQL_CONNECT_TIMEOUT_MS', uriParam: 'connectTimeoutMS', parse: parseNonNegativeInteger },
|
|
25
|
+
{ envVar: 'CUBEJS_MONGOSQL_SOCKET_TIMEOUT_MS', uriParam: 'socketTimeoutMS', parse: parseNonNegativeInteger },
|
|
26
|
+
{
|
|
27
|
+
envVar: 'CUBEJS_MONGOSQL_SERVER_SELECTION_TIMEOUT_MS',
|
|
28
|
+
uriParam: 'serverSelectionTimeoutMS',
|
|
29
|
+
parse: parseNonNegativeInteger,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
envVar: 'CUBEJS_MONGOSQL_HEARTBEAT_FREQUENCY_MS',
|
|
33
|
+
uriParam: 'heartbeatFrequencyMS',
|
|
34
|
+
parse: parseNonNegativeInteger,
|
|
35
|
+
},
|
|
36
|
+
{ envVar: 'CUBEJS_MONGOSQL_APP_NAME', uriParam: 'appName', parse: parseNonEmpty },
|
|
37
|
+
{ envVar: 'CUBEJS_MONGOSQL_RETRY_WRITES', uriParam: 'retryWrites', parse: parseBoolToString },
|
|
38
|
+
{ envVar: 'CUBEJS_MONGOSQL_RETRY_READS', uriParam: 'retryReads', parse: parseBoolToString },
|
|
39
|
+
{ envVar: 'CUBEJS_MONGOSQL_COMPRESSORS', uriParam: 'compressors', parse: parseNonEmpty },
|
|
40
|
+
];
|
|
41
|
+
/**
|
|
42
|
+
* Resolve `(uri, queryTimeoutMs)` from constructor overrides + env.
|
|
43
|
+
*
|
|
44
|
+
* Throws `MONGOSQL_CONFIG_INVALID` when:
|
|
45
|
+
* - neither explicit uri / `CUBEJS_DB_URL` / `CUBEJS_DB_URI` is set
|
|
46
|
+
* AND `CUBEJS_DB_HOST` is also unset;
|
|
47
|
+
* - a duration env var is malformed (e.g. `"forever"`);
|
|
48
|
+
* - a numeric env var fails to parse.
|
|
49
|
+
*/
|
|
50
|
+
function resolveUriConfig(overrideUri, env) {
|
|
51
|
+
// Step 1: pick the base URI.
|
|
52
|
+
const baseUri = overrideUri ?? env.CUBEJS_DB_URL ?? env.CUBEJS_DB_URI ?? composeUriFromParts(env);
|
|
53
|
+
// Step 2: enrich with env-driven URI params (only if not already in URI).
|
|
54
|
+
const finalUri = applyUriParams(baseUri, env);
|
|
55
|
+
// Step 3: resolve effective query-timeout-ms. CUBEJS_DB_QUERY_TIMEOUT
|
|
56
|
+
// (duration-aware) wins over the legacy CUBEJS_MONGOSQL_QUERY_TIMEOUT_MS
|
|
57
|
+
// (bare number). Both still recognised for back-compat.
|
|
58
|
+
const cubeStandardTimeout = env.CUBEJS_DB_QUERY_TIMEOUT;
|
|
59
|
+
const queryTimeoutMs = cubeStandardTimeout !== undefined && cubeStandardTimeout !== ''
|
|
60
|
+
? parseDurationToMillis(cubeStandardTimeout, 'CUBEJS_DB_QUERY_TIMEOUT')
|
|
61
|
+
: parseLegacyTimeoutMs(env.CUBEJS_MONGOSQL_QUERY_TIMEOUT_MS);
|
|
62
|
+
return { uri: finalUri, queryTimeoutMs };
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Build `mongodb://[user:pass@]host[:port]/[db]` from discrete env
|
|
66
|
+
* pieces. Used when neither `CUBEJS_DB_URL` nor `CUBEJS_DB_URI` is set.
|
|
67
|
+
*
|
|
68
|
+
* - `CUBEJS_DB_HOST` is required (clear error if missing).
|
|
69
|
+
* - `CUBEJS_DB_PORT` appended if set.
|
|
70
|
+
* - `CUBEJS_DB_USER` / `CUBEJS_DB_PASS` URL-encoded so `@` `:` `/`
|
|
71
|
+
* `?` `#` in passwords don't break the userinfo parser.
|
|
72
|
+
* - `CUBEJS_DB_NAME` appended as the path segment. Not load-bearing
|
|
73
|
+
* (the driver also reads it separately into `MongoSqlConfig.database`),
|
|
74
|
+
* but the mongodb crate parses it so we include it for consistency
|
|
75
|
+
* with the URL/URI shape — and any auth-database fallback the crate
|
|
76
|
+
* does.
|
|
77
|
+
*
|
|
78
|
+
* Host strings with commas (replica-set seed lists like `a:27017,b:27017`)
|
|
79
|
+
* pass through verbatim.
|
|
80
|
+
*/
|
|
81
|
+
function composeUriFromParts(env) {
|
|
82
|
+
const host = env.CUBEJS_DB_HOST;
|
|
83
|
+
if (!host) {
|
|
84
|
+
throw configInvalid('missing required config: uri (set CUBEJS_DB_URL / CUBEJS_DB_URI or pass `uri` to the constructor; or set CUBEJS_DB_HOST to compose one)');
|
|
85
|
+
}
|
|
86
|
+
const port = env.CUBEJS_DB_PORT;
|
|
87
|
+
const user = env.CUBEJS_DB_USER;
|
|
88
|
+
const pass = env.CUBEJS_DB_PASS;
|
|
89
|
+
const db = env.CUBEJS_DB_NAME;
|
|
90
|
+
let userinfo = '';
|
|
91
|
+
if (user !== undefined && user !== '') {
|
|
92
|
+
userinfo = encodeURIComponent(user);
|
|
93
|
+
if (pass !== undefined && pass !== '') {
|
|
94
|
+
userinfo += `:${encodeURIComponent(pass)}`;
|
|
95
|
+
}
|
|
96
|
+
userinfo += '@';
|
|
97
|
+
}
|
|
98
|
+
else if (pass !== undefined && pass !== '') {
|
|
99
|
+
throw configInvalid('CUBEJS_DB_PASS is set but CUBEJS_DB_USER is not — credentials require both');
|
|
100
|
+
}
|
|
101
|
+
// host may itself be a seed list ("h1,h2:27017") or a hostname.
|
|
102
|
+
// Port is only meaningful when host is a single hostname; we append
|
|
103
|
+
// it conservatively if the host string has no ':' AND no ','.
|
|
104
|
+
let hostPart = host;
|
|
105
|
+
if (port !== undefined && port !== '' && !host.includes(':') && !host.includes(',')) {
|
|
106
|
+
hostPart = `${host}:${port}`;
|
|
107
|
+
}
|
|
108
|
+
const dbPart = db !== undefined && db !== '' ? `/${encodeURIComponent(db)}` : '/';
|
|
109
|
+
return `mongodb://${userinfo}${hostPart}${dbPart}`;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Append env-driven URI params to the base URI, skipping any key that
|
|
113
|
+
* already appears in the URI's query string.
|
|
114
|
+
*
|
|
115
|
+
* Implemented via `new URL` — Node's parser handles both `mongodb://`
|
|
116
|
+
* and `mongodb+srv://` schemes correctly (verified: see commit message).
|
|
117
|
+
* We reconstruct the URI by string concatenation rather than reading
|
|
118
|
+
* `URL.href` back because Node's URL normalisation otherwise drops
|
|
119
|
+
* authentication-related characters (e.g. `+` in passwords) and we
|
|
120
|
+
* want byte-identical pass-through of any URI the user provides.
|
|
121
|
+
*/
|
|
122
|
+
function applyUriParams(baseUri, env) {
|
|
123
|
+
const existingKeys = extractExistingParamKeys(baseUri);
|
|
124
|
+
const additions = [];
|
|
125
|
+
for (const spec of URI_PARAM_SPECS) {
|
|
126
|
+
const raw = env[spec.envVar];
|
|
127
|
+
if (raw === undefined || raw === '')
|
|
128
|
+
continue;
|
|
129
|
+
if (existingKeys.has(spec.uriParam.toLowerCase()))
|
|
130
|
+
continue;
|
|
131
|
+
const value = spec.parse ? spec.parse(raw) : raw;
|
|
132
|
+
if (value === undefined) {
|
|
133
|
+
throw configInvalid(`${spec.envVar} has invalid value: '${raw}'`);
|
|
134
|
+
}
|
|
135
|
+
additions.push([spec.uriParam, value]);
|
|
136
|
+
}
|
|
137
|
+
if (additions.length === 0)
|
|
138
|
+
return baseUri;
|
|
139
|
+
// Determine separator: `?` if URI has no query, else `&`.
|
|
140
|
+
// `existingKeys.size > 0` is equivalent to "URI has a `?`" except for
|
|
141
|
+
// the empty-query-string edge case (`mongodb://h/db?`) which is not
|
|
142
|
+
// produced by us and would be parsed as a query by `new URL` anyway.
|
|
143
|
+
const queryStart = findQueryStart(baseUri);
|
|
144
|
+
const separator = queryStart === -1 ? '?' : '&';
|
|
145
|
+
const tail = additions.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`).join('&');
|
|
146
|
+
// Insert before any URL fragment (`#...`), although MongoDB URIs do
|
|
147
|
+
// not normally have one — defensive only.
|
|
148
|
+
const hashAt = baseUri.indexOf('#');
|
|
149
|
+
if (hashAt === -1)
|
|
150
|
+
return `${baseUri}${separator}${tail}`;
|
|
151
|
+
return `${baseUri.slice(0, hashAt)}${separator}${tail}${baseUri.slice(hashAt)}`;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Pull the set of param keys (lowercased) already present in the URI's
|
|
155
|
+
* query string. Returns an empty set for URIs with no query.
|
|
156
|
+
*/
|
|
157
|
+
function extractExistingParamKeys(uri) {
|
|
158
|
+
const start = findQueryStart(uri);
|
|
159
|
+
if (start === -1)
|
|
160
|
+
return new Set();
|
|
161
|
+
const end = uri.indexOf('#', start + 1);
|
|
162
|
+
const query = uri.slice(start + 1, end === -1 ? undefined : end);
|
|
163
|
+
if (!query)
|
|
164
|
+
return new Set();
|
|
165
|
+
const keys = new Set();
|
|
166
|
+
for (const part of query.split('&')) {
|
|
167
|
+
if (!part)
|
|
168
|
+
continue;
|
|
169
|
+
const eq = part.indexOf('=');
|
|
170
|
+
const rawKey = eq === -1 ? part : part.slice(0, eq);
|
|
171
|
+
// URI keys aren't expected to be percent-encoded, but be tolerant.
|
|
172
|
+
try {
|
|
173
|
+
keys.add(decodeURIComponent(rawKey).toLowerCase());
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
keys.add(rawKey.toLowerCase());
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return keys;
|
|
180
|
+
}
|
|
181
|
+
function findQueryStart(uri) {
|
|
182
|
+
// Skip the protocol-relative `//` — those are not the query.
|
|
183
|
+
return uri.indexOf('?');
|
|
184
|
+
}
|
|
185
|
+
// ---------- value parsers ----------
|
|
186
|
+
/**
|
|
187
|
+
* Accepts `"true"` / `"false"` (case-insensitive) or `"1"` / `"0"`.
|
|
188
|
+
* Returns the canonical `"true"` / `"false"` MongoDB URI form.
|
|
189
|
+
*/
|
|
190
|
+
function parseBoolToString(raw) {
|
|
191
|
+
const v = raw.trim().toLowerCase();
|
|
192
|
+
if (v === 'true' || v === '1')
|
|
193
|
+
return 'true';
|
|
194
|
+
if (v === 'false' || v === '0')
|
|
195
|
+
return 'false';
|
|
196
|
+
return undefined;
|
|
197
|
+
}
|
|
198
|
+
function parseNonEmpty(raw) {
|
|
199
|
+
const v = raw.trim();
|
|
200
|
+
return v === '' ? undefined : v;
|
|
201
|
+
}
|
|
202
|
+
function parsePositiveInteger(raw) {
|
|
203
|
+
const n = parseStrictInteger(raw);
|
|
204
|
+
if (n === undefined || n <= 0)
|
|
205
|
+
return undefined;
|
|
206
|
+
return String(n);
|
|
207
|
+
}
|
|
208
|
+
function parseNonNegativeInteger(raw) {
|
|
209
|
+
const n = parseStrictInteger(raw);
|
|
210
|
+
if (n === undefined || n < 0)
|
|
211
|
+
return undefined;
|
|
212
|
+
return String(n);
|
|
213
|
+
}
|
|
214
|
+
function parseStrictInteger(raw) {
|
|
215
|
+
const v = raw.trim();
|
|
216
|
+
if (!/^-?\d+$/.test(v))
|
|
217
|
+
return undefined;
|
|
218
|
+
const n = Number(v);
|
|
219
|
+
if (!Number.isFinite(n) || !Number.isInteger(n))
|
|
220
|
+
return undefined;
|
|
221
|
+
return n;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Convert a duration-or-number string to a millisecond integer string.
|
|
225
|
+
*
|
|
226
|
+
* Accepts a bare number (treated as **milliseconds**) or a unit
|
|
227
|
+
* suffix: `ms`, `s`, `m`, `h`. Whitespace inside is trimmed.
|
|
228
|
+
*
|
|
229
|
+
* Returns the canonical `"<N>"` ms representation as a string (URI
|
|
230
|
+
* param values are strings). Returns `undefined` for unparseable
|
|
231
|
+
* input so the caller can produce a `MONGOSQL_CONFIG_INVALID` error
|
|
232
|
+
* naming the offending env var.
|
|
233
|
+
*/
|
|
234
|
+
function parseDurationToMillisString(raw) {
|
|
235
|
+
const ms = parseDurationToMillisOrUndefined(raw);
|
|
236
|
+
return ms === undefined ? undefined : String(ms);
|
|
237
|
+
}
|
|
238
|
+
/** Same as `parseDurationToMillisString` but returns the integer directly. Throws on malformed input. */
|
|
239
|
+
function parseDurationToMillis(raw, envVarName) {
|
|
240
|
+
const ms = parseDurationToMillisOrUndefined(raw);
|
|
241
|
+
if (ms === undefined) {
|
|
242
|
+
throw configInvalid(`${envVarName} has invalid duration: '${raw}'. Accepted: bare ms (e.g. '60000'), or with unit suffix '<N>ms' / '<N>s' / '<N>m' / '<N>h'`);
|
|
243
|
+
}
|
|
244
|
+
return ms;
|
|
245
|
+
}
|
|
246
|
+
function parseDurationToMillisOrUndefined(raw) {
|
|
247
|
+
const v = raw.trim();
|
|
248
|
+
if (v === '')
|
|
249
|
+
return undefined;
|
|
250
|
+
// Most specific suffix first so `"500ms"` doesn't match the `s`
|
|
251
|
+
// branch — `ms` must be tested before bare `s`.
|
|
252
|
+
const match = v.match(/^(\d+(?:\.\d+)?)\s*(ms|s|m|h)?$/i);
|
|
253
|
+
if (!match)
|
|
254
|
+
return undefined;
|
|
255
|
+
const n = Number(match[1]);
|
|
256
|
+
if (!Number.isFinite(n) || n < 0)
|
|
257
|
+
return undefined;
|
|
258
|
+
const unit = (match[2] ?? 'ms').toLowerCase();
|
|
259
|
+
let multiplier;
|
|
260
|
+
switch (unit) {
|
|
261
|
+
case 'ms':
|
|
262
|
+
multiplier = 1;
|
|
263
|
+
break;
|
|
264
|
+
case 's':
|
|
265
|
+
multiplier = 1_000;
|
|
266
|
+
break;
|
|
267
|
+
case 'm':
|
|
268
|
+
multiplier = 60_000;
|
|
269
|
+
break;
|
|
270
|
+
case 'h':
|
|
271
|
+
multiplier = 3_600_000;
|
|
272
|
+
break;
|
|
273
|
+
default:
|
|
274
|
+
return undefined;
|
|
275
|
+
}
|
|
276
|
+
// Round to nearest ms to keep fractional inputs (`0.5s`) usable.
|
|
277
|
+
return Math.round(n * multiplier);
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Legacy `CUBEJS_MONGOSQL_QUERY_TIMEOUT_MS` is documented as a bare
|
|
281
|
+
* number-of-milliseconds. Preserve the old behaviour: empty/invalid
|
|
282
|
+
* returns `undefined` (so the native default takes over) — we do NOT
|
|
283
|
+
* throw on invalid here, matching the pre-this-change behaviour where
|
|
284
|
+
* `numEnv` silently returned `undefined`.
|
|
285
|
+
*/
|
|
286
|
+
function parseLegacyTimeoutMs(raw) {
|
|
287
|
+
if (raw === undefined || raw === '')
|
|
288
|
+
return undefined;
|
|
289
|
+
const n = Number(raw);
|
|
290
|
+
return Number.isFinite(n) ? n : undefined;
|
|
291
|
+
}
|
|
292
|
+
function configInvalid(detail) {
|
|
293
|
+
const err = new Error(`MONGOSQL_CONFIG_INVALID: ${detail}`);
|
|
294
|
+
err.code = 'MONGOSQL_CONFIG_INVALID';
|
|
295
|
+
err.name = 'MongoSqlError';
|
|
296
|
+
return err;
|
|
297
|
+
}
|
|
298
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public exports for mongosql-cubejs-driver.
|
|
3
|
+
* See SPEC.md §5.1.
|
|
4
|
+
*/
|
|
5
|
+
export { MongoSqlDriver } from './MongoSqlDriver.js';
|
|
6
|
+
export { MongoSqlQuery } from './MongoSqlQuery.js';
|
|
7
|
+
export type { MongoSqlConfig, SchemaSource, ErrorCode, MongoSqlError } from './types.js';
|
|
8
|
+
export { ERROR_CODES } from './types.js';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACzF,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ERROR_CODES = exports.MongoSqlQuery = exports.MongoSqlDriver = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Public exports for mongosql-cubejs-driver.
|
|
6
|
+
* See SPEC.md §5.1.
|
|
7
|
+
*/
|
|
8
|
+
var MongoSqlDriver_js_1 = require("./MongoSqlDriver.js");
|
|
9
|
+
Object.defineProperty(exports, "MongoSqlDriver", { enumerable: true, get: function () { return MongoSqlDriver_js_1.MongoSqlDriver; } });
|
|
10
|
+
var MongoSqlQuery_js_1 = require("./MongoSqlQuery.js");
|
|
11
|
+
Object.defineProperty(exports, "MongoSqlQuery", { enumerable: true, get: function () { return MongoSqlQuery_js_1.MongoSqlQuery; } });
|
|
12
|
+
var types_js_1 = require("./types.js");
|
|
13
|
+
Object.defineProperty(exports, "ERROR_CODES", { enumerable: true, get: function () { return types_js_1.ERROR_CODES; } });
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA;;;GAGG;AACH,yDAAqD;AAA5C,mHAAA,cAAc,OAAA;AACvB,uDAAmD;AAA1C,iHAAA,aAAa,OAAA;AAEtB,uCAAyC;AAAhC,uGAAA,WAAW,OAAA"}
|
package/dist/native.d.ts
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type-safe wrapper around the napi-rs `.node` module.
|
|
3
|
+
*
|
|
4
|
+
* Native errors carry the SPEC §6 code prefixed in the message, e.g.
|
|
5
|
+
* `"MONGOSQL_CONFIG_INVALID: ..."`. This wrapper parses that prefix and
|
|
6
|
+
* rethrows as `MongoSqlError` with `code`/`name` set. Errors without a
|
|
7
|
+
* recognised prefix are passed through unchanged.
|
|
8
|
+
*/
|
|
9
|
+
import type { MongoSqlConfig } from './types.js';
|
|
10
|
+
interface NativeAbortHandle {
|
|
11
|
+
abort(): void;
|
|
12
|
+
aborted(): boolean;
|
|
13
|
+
}
|
|
14
|
+
interface NativeMongoSqlClient {
|
|
15
|
+
testConnection(signal?: NativeAbortHandle | null): Promise<void>;
|
|
16
|
+
query(sql: string, signal?: NativeAbortHandle | null): Promise<unknown>;
|
|
17
|
+
tablesSchema(signal?: NativeAbortHandle | null): Promise<unknown>;
|
|
18
|
+
close(): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Authoritative `(name, type)` column descriptor produced by the native
|
|
22
|
+
* layer from `mongosql::Translation::{select_order, result_set_schema}`.
|
|
23
|
+
* Used by `downloadQueryResults` to drive Cube Store's LOAD ROWS column
|
|
24
|
+
* list, replacing the old value-sniffing heuristic.
|
|
25
|
+
*/
|
|
26
|
+
export interface ColumnType {
|
|
27
|
+
name: string;
|
|
28
|
+
/** Cube generic-type string: `timestamp` | `int` | `bigint` | `decimal` | `boolean` | `string` | `text`. */
|
|
29
|
+
type: string;
|
|
30
|
+
}
|
|
31
|
+
/** Shape returned by the native `query()` napi binding. */
|
|
32
|
+
export interface NativeQueryResult {
|
|
33
|
+
rows: unknown[];
|
|
34
|
+
types: ColumnType[];
|
|
35
|
+
}
|
|
36
|
+
interface NativeModule {
|
|
37
|
+
MongoSqlClient: new (config: MongoSqlConfig) => NativeMongoSqlClient;
|
|
38
|
+
AbortHandle?: new () => NativeAbortHandle;
|
|
39
|
+
}
|
|
40
|
+
/** Column descriptor returned by `tablesSchema()`. Mirrors the Rust shape. */
|
|
41
|
+
export interface ColumnInfo {
|
|
42
|
+
name: string;
|
|
43
|
+
type: string;
|
|
44
|
+
attributes: string[];
|
|
45
|
+
}
|
|
46
|
+
/** `tablesSchema()` shape: `{ <db>: { <coll>: ColumnInfo[] } }`. */
|
|
47
|
+
export type TablesSchema = Record<string, Record<string, ColumnInfo[]>>;
|
|
48
|
+
/** Test hook: reset the cached native-module reference. */
|
|
49
|
+
export declare function _resetNativeModuleForTests(): void;
|
|
50
|
+
/** Test hook: inject a mock native module. */
|
|
51
|
+
export declare function _setNativeModuleForTests(mod: NativeModule): void;
|
|
52
|
+
/**
|
|
53
|
+
* Type-safe TypeScript wrapper around the napi-rs `MongoSqlClient`.
|
|
54
|
+
* One-to-one method mapping; errors are normalised into `MongoSqlError`.
|
|
55
|
+
*
|
|
56
|
+
* **Cancellation contract.** Each cancellable method takes an optional
|
|
57
|
+
* `AbortSignal`. Internally we lazily allocate a native `AbortHandle` and
|
|
58
|
+
* wire `signal.addEventListener('abort', () => handle.abort())`. The
|
|
59
|
+
* native side races the work future against the handle's
|
|
60
|
+
* `CancelToken::cancelled()` future and rejects with
|
|
61
|
+
* `MONGOSQL_CANCELLED` if it fires first. Pre-aborted signals are
|
|
62
|
+
* special-cased so they reject immediately without crossing the napi
|
|
63
|
+
* boundary at all.
|
|
64
|
+
*
|
|
65
|
+
* napi-rs 2.16's first-class `AbortSignal` only integrates with
|
|
66
|
+
* `AsyncTask` (libuv async-work pattern), not `#[napi] async fn`. The
|
|
67
|
+
* Rust side therefore exposes its own opaque `AbortHandle` class
|
|
68
|
+
* (`crates/native/src/cancel.rs`) and we bridge here.
|
|
69
|
+
*/
|
|
70
|
+
export declare class MongoSqlClient {
|
|
71
|
+
private readonly inner;
|
|
72
|
+
private readonly nativeAbortHandleCtor;
|
|
73
|
+
constructor(config: MongoSqlConfig);
|
|
74
|
+
testConnection(signal?: AbortSignal): Promise<void>;
|
|
75
|
+
query<R = Record<string, unknown>>(sql: string, signal?: AbortSignal): Promise<R[]>;
|
|
76
|
+
/**
|
|
77
|
+
* Like `query()` but returns the authoritative `(name, type)` list
|
|
78
|
+
* alongside the rows. Used by `downloadQueryResults` to drive Cube
|
|
79
|
+
* Store's column-list payload; replaces the value-sniffed inference
|
|
80
|
+
* the driver used pre-fix.
|
|
81
|
+
*
|
|
82
|
+
* The shape mirrors the native binding exactly:
|
|
83
|
+
* `{ rows: R[], types: Array<{name, type}> }`.
|
|
84
|
+
* `types` is empty when (and only when) `mongosql::select_order` is
|
|
85
|
+
* empty — a degenerate case in practice but possible if upstream
|
|
86
|
+
* doesn't parse a projection list.
|
|
87
|
+
*/
|
|
88
|
+
queryWithTypes<R = Record<string, unknown>>(sql: string, signal?: AbortSignal): Promise<{
|
|
89
|
+
rows: R[];
|
|
90
|
+
types: ColumnType[];
|
|
91
|
+
}>;
|
|
92
|
+
tablesSchema(signal?: AbortSignal): Promise<TablesSchema>;
|
|
93
|
+
close(): Promise<void>;
|
|
94
|
+
/**
|
|
95
|
+
* Bridge a JS `AbortSignal` to a native `AbortHandle` for the duration
|
|
96
|
+
* of one call. If `signal` is undefined, the call runs un-cancelled
|
|
97
|
+
* (the native side still wires the parent close-token, so `close()`
|
|
98
|
+
* can still cancel it). If `signal` is already aborted, we throw
|
|
99
|
+
* `MONGOSQL_CANCELLED` synchronously without invoking the native side.
|
|
100
|
+
*/
|
|
101
|
+
private runCancellable;
|
|
102
|
+
}
|
|
103
|
+
export {};
|
|
104
|
+
//# sourceMappingURL=native.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../src/native.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAA4B,MAAM,YAAY,CAAC;AAG3E,UAAU,iBAAiB;IACzB,KAAK,IAAI,IAAI,CAAC;IACd,OAAO,IAAI,OAAO,CAAC;CACpB;AAED,UAAU,oBAAoB;IAC5B,cAAc,CAAC,MAAM,CAAC,EAAE,iBAAiB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,iBAAiB,GAAG,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACxE,YAAY,CAAC,MAAM,CAAC,EAAE,iBAAiB,GAAG,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAClE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,4GAA4G;IAC5G,IAAI,EAAE,MAAM,CAAC;CACd;AAED,2DAA2D;AAC3D,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB;AAED,UAAU,YAAY;IACpB,cAAc,EAAE,KAAK,MAAM,EAAE,cAAc,KAAK,oBAAoB,CAAC;IAIrE,WAAW,CAAC,EAAE,UAAU,iBAAiB,CAAC;CAC3C;AAED,8EAA8E;AAC9E,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,oEAAoE;AACpE,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC;AAiBxE,2DAA2D;AAC3D,wBAAgB,0BAA0B,IAAI,IAAI,CAEjD;AAED,8CAA8C;AAC9C,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,CAEhE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuB;IAC7C,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAA4C;gBAEtE,MAAM,EAAE,cAAc;IAc5B,cAAc,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAInD,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAQzF;;;;;;;;;;;OAWG;IACG,cAAc,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9C,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC;QAAE,IAAI,EAAE,CAAC,EAAE,CAAC;QAAC,KAAK,EAAE,UAAU,EAAE,CAAA;KAAE,CAAC;IAWxC,YAAY,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAKzD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B;;;;;;OAMG;YACW,cAAc;CA6B7B"}
|
package/dist/native.js
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Type-safe wrapper around the napi-rs `.node` module.
|
|
4
|
+
*
|
|
5
|
+
* Native errors carry the SPEC §6 code prefixed in the message, e.g.
|
|
6
|
+
* `"MONGOSQL_CONFIG_INVALID: ..."`. This wrapper parses that prefix and
|
|
7
|
+
* rethrows as `MongoSqlError` with `code`/`name` set. Errors without a
|
|
8
|
+
* recognised prefix are passed through unchanged.
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.MongoSqlClient = void 0;
|
|
12
|
+
exports._resetNativeModuleForTests = _resetNativeModuleForTests;
|
|
13
|
+
exports._setNativeModuleForTests = _setNativeModuleForTests;
|
|
14
|
+
const types_js_1 = require("./types.js");
|
|
15
|
+
let nativeModule;
|
|
16
|
+
function loadNative() {
|
|
17
|
+
if (nativeModule)
|
|
18
|
+
return nativeModule;
|
|
19
|
+
// napi-rs's `index.js` lives at project root. From `src/native.ts` (vitest)
|
|
20
|
+
// it's `../index.js`; from `dist/src/native.js` (built consumer) it's
|
|
21
|
+
// `../../index.js`. Try both.
|
|
22
|
+
try {
|
|
23
|
+
nativeModule = require('../index.js');
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
nativeModule = require('../../index.js');
|
|
27
|
+
}
|
|
28
|
+
return nativeModule;
|
|
29
|
+
}
|
|
30
|
+
/** Test hook: reset the cached native-module reference. */
|
|
31
|
+
function _resetNativeModuleForTests() {
|
|
32
|
+
nativeModule = undefined;
|
|
33
|
+
}
|
|
34
|
+
/** Test hook: inject a mock native module. */
|
|
35
|
+
function _setNativeModuleForTests(mod) {
|
|
36
|
+
nativeModule = mod;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Type-safe TypeScript wrapper around the napi-rs `MongoSqlClient`.
|
|
40
|
+
* One-to-one method mapping; errors are normalised into `MongoSqlError`.
|
|
41
|
+
*
|
|
42
|
+
* **Cancellation contract.** Each cancellable method takes an optional
|
|
43
|
+
* `AbortSignal`. Internally we lazily allocate a native `AbortHandle` and
|
|
44
|
+
* wire `signal.addEventListener('abort', () => handle.abort())`. The
|
|
45
|
+
* native side races the work future against the handle's
|
|
46
|
+
* `CancelToken::cancelled()` future and rejects with
|
|
47
|
+
* `MONGOSQL_CANCELLED` if it fires first. Pre-aborted signals are
|
|
48
|
+
* special-cased so they reject immediately without crossing the napi
|
|
49
|
+
* boundary at all.
|
|
50
|
+
*
|
|
51
|
+
* napi-rs 2.16's first-class `AbortSignal` only integrates with
|
|
52
|
+
* `AsyncTask` (libuv async-work pattern), not `#[napi] async fn`. The
|
|
53
|
+
* Rust side therefore exposes its own opaque `AbortHandle` class
|
|
54
|
+
* (`crates/native/src/cancel.rs`) and we bridge here.
|
|
55
|
+
*/
|
|
56
|
+
class MongoSqlClient {
|
|
57
|
+
inner;
|
|
58
|
+
nativeAbortHandleCtor;
|
|
59
|
+
constructor(config) {
|
|
60
|
+
const native = loadNative();
|
|
61
|
+
this.nativeAbortHandleCtor = native.AbortHandle;
|
|
62
|
+
this.inner = new native.MongoSqlClient({
|
|
63
|
+
uri: config.uri,
|
|
64
|
+
database: config.database,
|
|
65
|
+
schemaSource: config.schemaSource,
|
|
66
|
+
schemaRefreshSec: config.schemaRefreshSec,
|
|
67
|
+
schemaFailOpen: config.schemaFailOpen,
|
|
68
|
+
queryTimeoutMs: config.queryTimeoutMs,
|
|
69
|
+
maxRows: config.maxRows,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
async testConnection(signal) {
|
|
73
|
+
return this.runCancellable(signal, (handle) => this.inner.testConnection(handle));
|
|
74
|
+
}
|
|
75
|
+
async query(sql, signal) {
|
|
76
|
+
// `query()` keeps its historical `R[]` signature for ergonomic
|
|
77
|
+
// consumption — pre-aggregation paths that need the type list call
|
|
78
|
+
// `queryWithTypes` instead and pay the extra unwrap.
|
|
79
|
+
const { rows } = await this.queryWithTypes(sql, signal);
|
|
80
|
+
return rows;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Like `query()` but returns the authoritative `(name, type)` list
|
|
84
|
+
* alongside the rows. Used by `downloadQueryResults` to drive Cube
|
|
85
|
+
* Store's column-list payload; replaces the value-sniffed inference
|
|
86
|
+
* the driver used pre-fix.
|
|
87
|
+
*
|
|
88
|
+
* The shape mirrors the native binding exactly:
|
|
89
|
+
* `{ rows: R[], types: Array<{name, type}> }`.
|
|
90
|
+
* `types` is empty when (and only when) `mongosql::select_order` is
|
|
91
|
+
* empty — a degenerate case in practice but possible if upstream
|
|
92
|
+
* doesn't parse a projection list.
|
|
93
|
+
*/
|
|
94
|
+
async queryWithTypes(sql, signal) {
|
|
95
|
+
const result = await this.runCancellable(signal, (handle) => this.inner.query(sql, handle));
|
|
96
|
+
if (!isQueryResult(result)) {
|
|
97
|
+
throw createError('MONGOSQL_EXECUTE_FAILED', `expected query result to be an object with rows + types arrays, got ${describe(result)}`);
|
|
98
|
+
}
|
|
99
|
+
return { rows: result.rows, types: result.types };
|
|
100
|
+
}
|
|
101
|
+
async tablesSchema(signal) {
|
|
102
|
+
const result = await this.runCancellable(signal, (handle) => this.inner.tablesSchema(handle));
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
async close() {
|
|
106
|
+
return wrapErrors(() => this.inner.close());
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Bridge a JS `AbortSignal` to a native `AbortHandle` for the duration
|
|
110
|
+
* of one call. If `signal` is undefined, the call runs un-cancelled
|
|
111
|
+
* (the native side still wires the parent close-token, so `close()`
|
|
112
|
+
* can still cancel it). If `signal` is already aborted, we throw
|
|
113
|
+
* `MONGOSQL_CANCELLED` synchronously without invoking the native side.
|
|
114
|
+
*/
|
|
115
|
+
async runCancellable(signal, op) {
|
|
116
|
+
if (signal === undefined) {
|
|
117
|
+
return wrapErrors(() => op(null));
|
|
118
|
+
}
|
|
119
|
+
if (signal.aborted) {
|
|
120
|
+
// Pre-aborted: skip the napi round-trip entirely. Mirror the
|
|
121
|
+
// wire-format of MONGOSQL_CANCELLED that the Rust side produces
|
|
122
|
+
// so callers see one consistent error shape.
|
|
123
|
+
throw createError('MONGOSQL_CANCELLED', 'signal was aborted before call');
|
|
124
|
+
}
|
|
125
|
+
if (!this.nativeAbortHandleCtor) {
|
|
126
|
+
// Defensive: production builds always export AbortHandle; this
|
|
127
|
+
// branch only fires under test mocks that didn't stub it. Run
|
|
128
|
+
// un-cancellable rather than crashing — the caller still gets
|
|
129
|
+
// their result.
|
|
130
|
+
return wrapErrors(() => op(null));
|
|
131
|
+
}
|
|
132
|
+
const handle = new this.nativeAbortHandleCtor();
|
|
133
|
+
const onAbort = () => handle.abort();
|
|
134
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
135
|
+
try {
|
|
136
|
+
return await wrapErrors(() => op(handle));
|
|
137
|
+
}
|
|
138
|
+
finally {
|
|
139
|
+
signal.removeEventListener('abort', onAbort);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
exports.MongoSqlClient = MongoSqlClient;
|
|
144
|
+
const ERROR_CODE_RE = /^(MONGOSQL_[A-Z_]+):\s*(.*)$/s;
|
|
145
|
+
async function wrapErrors(op) {
|
|
146
|
+
try {
|
|
147
|
+
return await op();
|
|
148
|
+
}
|
|
149
|
+
catch (err) {
|
|
150
|
+
if (err instanceof Error) {
|
|
151
|
+
const match = ERROR_CODE_RE.exec(err.message);
|
|
152
|
+
if (match) {
|
|
153
|
+
const [, code, message] = match;
|
|
154
|
+
if (types_js_1.ERROR_CODES.includes(code)) {
|
|
155
|
+
throw createError(code, message);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
throw err;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
function createError(code, message) {
|
|
163
|
+
const err = new Error(message);
|
|
164
|
+
err.code = code;
|
|
165
|
+
err.name = 'MongoSqlError';
|
|
166
|
+
return err;
|
|
167
|
+
}
|
|
168
|
+
function isQueryResult(value) {
|
|
169
|
+
if (typeof value !== 'object' || value === null)
|
|
170
|
+
return false;
|
|
171
|
+
const v = value;
|
|
172
|
+
if (!Array.isArray(v.rows))
|
|
173
|
+
return false;
|
|
174
|
+
if (!Array.isArray(v.types))
|
|
175
|
+
return false;
|
|
176
|
+
for (const t of v.types) {
|
|
177
|
+
if (typeof t !== 'object' || t === null)
|
|
178
|
+
return false;
|
|
179
|
+
const ct = t;
|
|
180
|
+
if (typeof ct.name !== 'string' || typeof ct.type !== 'string')
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
function describe(value) {
|
|
186
|
+
if (value === null)
|
|
187
|
+
return 'null';
|
|
188
|
+
if (Array.isArray(value))
|
|
189
|
+
return 'array';
|
|
190
|
+
return typeof value;
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=native.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native.js","sourceRoot":"","sources":["../src/native.ts"],"names":[],"mappings":"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"}
|