@ydbjs/query
Version:
High-level, type-safe YQL query and transaction client for YDB. Supports tagged template syntax, parameter binding, transactions, and statistics.
69 lines • 2.65 kB
JavaScript
import { fromJs } from "@ydbjs/value";
const SymbolUnsafe = Symbol("unsafe");
function isObject(value) {
return typeof value === 'object' && value !== null && !Array.isArray(value);
}
// Enhanced validation with detailed error messages for better debugging
function validateValue(value, index) {
if (value === undefined) {
throw new Error(`❌ Undefined value at position ${index} in yql template. ` +
`This usually means:\n` +
` • A variable wasn't initialized\n` +
` • A function returned undefined\n` +
` • An object property doesn't exist\n` +
`For intentional null database values, use YDB Optional type.`);
}
if (value === null) {
throw new Error(`❌ Null value at position ${index} in yql template. ` +
`JavaScript null is not directly supported in YDB queries.\n` +
`For null database values, use YDB Optional type instead.`);
}
}
export class UnsafeString extends String {
[SymbolUnsafe] = true;
}
export function yql(strings, ...values) {
let text = '';
let params = Object.assign({}, null);
// Handle simple string case
if (typeof strings === 'string') {
return { text: strings, params };
}
// Handle template literal case
if (Array.isArray(strings)) {
let skipCount = 0;
// Process parameters first to build params object and count skipped values
values.forEach((value, i) => {
// Enhanced validation with position info
validateValue(value, i);
if (value[SymbolUnsafe]) {
skipCount++;
return;
}
let ydbValue = isObject(value) && 'type' in value && 'kind' in value['type'] ? value : fromJs(value);
params[`$p${i - skipCount}`] = ydbValue;
});
// Build text with proper parameter references
skipCount = 0;
text = strings.reduce((prev, curr, i) => {
let value = values[i];
// This should never happen due to validation above, but keep for safety
if (value === undefined || value === null) {
return prev + curr;
}
if (value[SymbolUnsafe]) {
skipCount++;
return prev + curr + value.toString();
}
return prev + curr + `$p${i - skipCount}`;
}, '');
}
return { text, params };
}
export function unsafe(value) {
return new UnsafeString(value.toString());
}
export function identifier(path) {
return unsafe("`" + path + "`");
}
//# sourceMappingURL=yql.js.map