snowflake-promise
Version:
A Promise-based, TypeScript-friendly helper for the Snowflake SDK
354 lines (341 loc) • 11.7 kB
JavaScript
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var index_exports = {};
__export(index_exports, {
Snowflake: () => Snowflake,
SnowflakeError: () => SnowflakeError,
Statement: () => Statement,
StatementAlreadyExecutedError: () => StatementAlreadyExecutedError,
StatementNotExecutedError: () => StatementNotExecutedError,
promisifyConnection: () => promisifyConnection
});
module.exports = __toCommonJS(index_exports);
// src/lib/promisify-or-not.ts
var import_node_util = require("util");
function promisifyOrNot(original) {
const promisified = (0, import_node_util.promisify)(original);
return function(...args) {
const lastArg = args.at(-1);
if (typeof lastArg === "function") {
return original.apply(this, args);
}
return promisified.apply(this, args);
};
}
// src/lib/promisify-statement.ts
function promisifyStatement(stmt) {
if (stmt && Object.prototype.hasOwnProperty.call(stmt, "__isPromisified")) {
return stmt;
}
return new Proxy(stmt, {
get(target, prop, receiver) {
if (prop === "__isPromisified") {
return true;
}
const originalValue = Reflect.get(target, prop, receiver);
if (typeof originalValue === "function") {
switch (prop) {
// Methods with a traditional callback
case "cancel":
return promisifyOrNot(
originalValue
).bind(target);
default:
return originalValue.bind(target);
}
}
return originalValue;
}
});
}
// src/lib/promisify-options-callback-function.ts
function promisifyOptionsCallbackFunction(target, fn) {
return function(options) {
if (options && typeof options.complete === "function") {
return fn.call(target, options);
}
let rowsResolve;
let rowsReject;
const resultsPromise = new Promise((resolve, reject) => {
rowsResolve = resolve;
rowsReject = reject;
});
const newOptions = { ...options };
newOptions.complete = (err, stmt, rows) => {
if (err) {
rowsReject(err);
} else {
rowsResolve(rows);
}
};
const statement = fn.call(target, newOptions);
return {
statement: promisifyStatement(statement),
resultsPromise
};
};
}
// src/lib/promisify-connection.ts
function promisifyConnection(conn) {
if (conn && Object.prototype.hasOwnProperty.call(conn, "__isPromisified")) {
return conn;
}
const proxy = new Proxy(conn, {
get(target, prop, receiver) {
if (prop === "__isPromisified") {
return true;
}
const originalValue = Reflect.get(target, prop, receiver);
if (typeof originalValue === "function") {
switch (prop) {
// Methods that take an options object containing a `complete` property
// These methods return RowStatement objects that are wrapped with
// promisifyStatement. `getResultsFromQueryId` is not promisified due to
// its use case, which would be hard to handle and isn’t needed when using
// this Promise proxy.
case "execute":
case "fetchResult":
return promisifyOptionsCallbackFunction(target, originalValue);
// Methods with a traditional callback
case "connect":
case "connectAsync":
case "destroy":
return promisifyOrNot(originalValue).bind(target);
default:
return originalValue.bind(target);
}
}
return originalValue;
}
});
return proxy;
}
// src/legacy-compatibility/snowflake.ts
var import_snowflake_sdk = __toESM(require("snowflake-sdk"), 1);
// src/legacy-compatibility/statement.ts
var import_node_assert = require("assert");
// src/legacy-compatibility/types/SnowflakeError.ts
var SnowflakeError = class extends Error {
constructor(message) {
super(message);
}
};
// src/legacy-compatibility/types/StatementNotExecutedError.ts
var StatementNotExecutedError = class extends SnowflakeError {
constructor() {
super("Statement not executed yet - call the execute() method");
}
};
// src/legacy-compatibility/statement.ts
var Statement = class {
connection;
executePromise;
stmt;
rows;
executeOptions;
logSql;
constructor(connection, executeOptions, logSql) {
this.connection = promisifyConnection(connection);
this.executeOptions = executeOptions;
this.logSql = logSql;
}
execute() {
if (this.executePromise) {
throw new StatementAlreadyExecutedError();
}
const startTime = Date.now();
const { statement, resultsPromise } = this.connection.execute(this.executeOptions);
this.stmt = statement;
this.executePromise = resultsPromise.then((rows) => {
if (this.logSql) {
const elapsed = Date.now() - startTime;
this.log(elapsed);
}
this.rows = rows;
});
return this.executePromise;
}
async cancel() {
await this.stmt?.cancel();
}
getRows() {
if (!this.executePromise) {
throw new StatementNotExecutedError();
}
return this.executePromise.then(() => this.rows);
}
streamRows(options = {}) {
if (!this.executePromise) {
throw new StatementNotExecutedError();
}
(0, import_node_assert.strict)(this.stmt, "Statement must be executed before streaming rows");
return this.stmt.streamRows(options);
}
getSqlText() {
if (!this.executePromise) {
throw new StatementNotExecutedError();
}
(0, import_node_assert.strict)(this.stmt, "Statement must be executed before getting SQL text");
return this.stmt.getSqlText();
}
getStatus() {
if (!this.executePromise) {
throw new StatementNotExecutedError();
}
(0, import_node_assert.strict)(this.stmt, "Statement must be executed before getting status");
return this.stmt.getStatus();
}
getColumns() {
if (!this.executePromise) {
throw new StatementNotExecutedError();
}
(0, import_node_assert.strict)(this.stmt, "Statement must be executed before getting columns");
return this.stmt.getColumns();
}
getColumn(columnIdentifier) {
if (!this.executePromise) {
throw new StatementNotExecutedError();
}
(0, import_node_assert.strict)(this.stmt, "Statement must be executed before getting column");
return this.stmt.getColumn(columnIdentifier);
}
getNumRows() {
if (!this.executePromise) {
throw new StatementNotExecutedError();
}
(0, import_node_assert.strict)(this.stmt, "Statement must be executed before getting number of rows");
return this.stmt.getNumRows();
}
getNumUpdatedRows() {
if (!this.executePromise) {
throw new StatementNotExecutedError();
}
(0, import_node_assert.strict)(this.stmt, "Statement must be executed before getting number of updated rows");
return this.stmt.getNumUpdatedRows();
}
getSessionState() {
if (!this.executePromise) {
throw new StatementNotExecutedError();
}
(0, import_node_assert.strict)(this.stmt, "Statement must be executed before getting session state");
return this.stmt.getSessionState();
}
getRequestId() {
if (!this.executePromise) {
throw new StatementNotExecutedError();
}
(0, import_node_assert.strict)(this.stmt, "Statement must be executed before getting request ID");
return this.stmt.getRequestId();
}
getStatementId() {
if (!this.executePromise) {
throw new StatementNotExecutedError();
}
(0, import_node_assert.strict)(this.stmt, "Statement must be executed before getting statement ID");
return this.stmt.getQueryId();
}
log(elapsedTime) {
let logMessage = "Executed";
const state = this.getSessionState();
if (state) {
logMessage += ` (${state.getCurrentDatabase()}.${state.getCurrentSchema()})`;
}
logMessage += `: ${this.getSqlText()}`;
if (logMessage[logMessage.length - 1] !== ";") {
logMessage += ";";
}
if (this.executeOptions.binds) {
logMessage += ` with binds: ${JSON.stringify(this.executeOptions.binds)};`;
}
logMessage += ` Elapsed time: ${elapsedTime}ms`;
this.logSql?.(logMessage);
}
};
// src/legacy-compatibility/types/LoggingOptions.ts
function toSdkLogLevel(logLevel) {
return logLevel.toUpperCase();
}
// src/legacy-compatibility/snowflake.ts
var Snowflake = class {
logSql;
connection;
constructor(connectionOptions, loggingOptions = {}, configureOptions) {
if (loggingOptions && loggingOptions.logLevel) {
import_snowflake_sdk.default.configure({ logLevel: toSdkLogLevel(loggingOptions.logLevel) });
}
this.logSql = (loggingOptions && loggingOptions.logSql) ?? void 0;
if (typeof configureOptions === "boolean") {
console.warn(
"[snowflake-promise] the insecureConnect boolean argument is deprecated; please remove it or use the ocspFailOpen configure option"
);
} else if (typeof configureOptions === "object") {
import_snowflake_sdk.default.configure(configureOptions);
}
this.connection = promisifyConnection(import_snowflake_sdk.default.createConnection(connectionOptions));
}
get id() {
return this.connection.getId();
}
async connect() {
await this.connection.connect();
}
async connectAsync() {
await this.connection.connectAsync();
}
async destroy() {
await this.connection.destroy();
}
createStatement(options) {
return new Statement(this.connection, options, this.logSql);
}
/** A convenience function to execute a SQL statement and return the resulting rows. */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async execute(sqlText, binds) {
const { resultsPromise } = this.connection.execute({ sqlText, binds });
const rows = await resultsPromise;
return rows;
}
};
// src/legacy-compatibility/types/StatementAlreadyExecutedError.ts
var StatementAlreadyExecutedError = class extends SnowflakeError {
constructor() {
super("Statement already executed - it cannot be executed again");
}
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
Snowflake,
SnowflakeError,
Statement,
StatementAlreadyExecutedError,
StatementNotExecutedError,
promisifyConnection
});
//# sourceMappingURL=index.cjs.map