Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 27 additions & 23 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
{
"extends": [
"plugin:@typescript-eslint/recommended",
"plugin:prettier/recommended",
"plugin:node/recommended",
"plugin:security/recommended-legacy"
],
"rules": {
"node/no-unsupported-features/es-syntax": "off",
// no-missing-import gets confused by typescript `paths`
"node/no-missing-import": "off",
"@typescript-eslint/no-unused-vars": [
"error",
{
"ignoreRestSiblings": true
}
"extends": [
"plugin:@typescript-eslint/recommended",
"plugin:prettier/recommended",
"plugin:node/recommended",
"plugin:security/recommended-legacy"
],
"node/no-unpublished-import": [
"error",
{
"allowModules": ["vitest", "vitest-fetch-mock"]
}
]
}
}
"rules": {
"node/no-unsupported-features/es-syntax": "off",
// no-missing-import gets confused by typescript `paths`
"node/no-missing-import": "off",
"@typescript-eslint/no-unused-vars": [
"error",
{
"ignoreRestSiblings": true
}
],
"node/no-unpublished-import": [
"error",
{
"allowModules": [
"vitest",
"vitest-fetch-mock"
]
}
],
"@typescript-eslint/no-explicit-any": "warn"
}
}
1,318 changes: 1,318 additions & 0 deletions bun.lock

Large diffs are not rendered by default.

129 changes: 63 additions & 66 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,68 +1,65 @@
{
"name": "wherobots-sql-driver",
"version": "0.4.2",
"description": "TypeScript SDK for Wherobots DB",
"license": "Apache-2.0",
"main": "dist/src/index.js",
"keywords": [
"wherobots",
"sedona",
"geospatial",
"spatial sql"
],
"homepage": "https://github.com/wherobots/wherobots-typescript-sdk",
"bugs": "https://github.com/wherobots/wherobots-typescript-sdk/issues",
"repository": {
"type": "git",
"url": "https://github.com/wherobots/wherobots-typescript-sdk"
},
"engines": {
"node": ">=18.0.0"
},
"scripts": {
"build": "tsc",
"build:check": "tsc --noEmit",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"format": "prettier --check .",
"format:fix": "prettier --write .",
"prepare": "husky",
"prepublish": "npm run build",
"test": "vitest"
},
"devDependencies": {
"@commitlint/cli": "^19.4.0",
"@commitlint/config-conventional": "^19.2.2",
"@swc-node/register": "^1.10.9",
"@tsconfig/node-lts": "^20.1.3",
"@tsconfig/strictest": "^2.0.5",
"@types/uuid": "^10.0.0",
"@types/ws": "^8.5.12",
"@typescript-eslint/eslint-plugin": "^7.18.0",
"@typescript-eslint/parser": "^7.18.0",
"eslint": "^8.57.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^18.0.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-security": "^3.0.1",
"husky": "^9.1.4",
"lint-staged": "^15.2.9",
"prettier": "^3.3.3",
"typescript": "^5.5.4",
"vitest": "^3.0.5",
"vitest-fetch-mock": "^0.3.0"
},
"dependencies": {
"apache-arrow": "^17.0.0",
"bufferutil": "^4.0.8",
"cbor": "^9.0.2",
"pino": "^9.3.2",
"pino-pretty": "^11.2.2",
"read-pkg-up": "^7.0.0",
"uuid": "^10.0.0",
"ws": "^8.18.0",
"zod": "^3.23.8"
}
"name": "wherobots-sql-driver",
"version": "0.4.2",
"description": "TypeScript SDK for Wherobots DB",
"license": "Apache-2.0",
"main": "dist/src/index.js",
"type": "module",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is "type": "module" necessary? it breaks the running of the example scripts (e.g. node -r @swc-node/register examples/connectionWithDefaults.ts)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I needed to use it to be esm compatible for one of the packages. Will see if I can remove it. Also, I recommend we use npx for this so I have now replaced the command with npx tsx examples/connectionWithDefaults.ts (tsx runs ts files)

"keywords": [
"wherobots",
"sedona",
"geospatial",
"spatial sql"
],
"homepage": "https://github.com/wherobots/wherobots-typescript-sdk",
"bugs": "https://github.com/wherobots/wherobots-typescript-sdk/issues",
"repository": {
"type": "git",
"url": "https://github.com/wherobots/wherobots-typescript-sdk"
},
"engines": {
"node": ">=18.0.0"
},
"scripts": {
"build": "tsc",
"build:check": "tsc --noEmit",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"format": "prettier --check .",
"format:fix": "prettier --write .",
"prepare": "husky",
"prepublish": "npm run build",
"test": "vitest"
},
"devDependencies": {
"@commitlint/cli": "^19.4.0",
"@commitlint/config-conventional": "^19.2.2",
"@swc-node/register": "^1.10.9",
"@tsconfig/node-lts": "^20.1.3",
"@tsconfig/strictest": "^2.0.5",
"@types/uuid": "^10.0.0",
"@typescript-eslint/eslint-plugin": "^7.18.0",
"@typescript-eslint/parser": "^7.18.0",
"eslint": "^8.57.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^18.0.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-security": "^3.0.1",
"husky": "^9.1.4",
"lint-staged": "^15.2.9",
"prettier": "^3.3.3",
"typescript": "^5.5.4",
"vitest": "^3.0.5",
"vitest-fetch-mock": "^0.3.0"
},
"dependencies": {
"apache-arrow": "^17.0.0",
"cbor-x": "^1.6.0",
"isomorphic-ws": "^5.0.0",
"loglevel": "^1.9.2",
"uuid": "^10.0.0",
"zod": "^3.23.8"
}
}
26 changes: 18 additions & 8 deletions src/connection.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { decodeFirstSync } from "cbor";
import { decode } from "cbor-x";
import * as uuid from "uuid";
import WebSocket from "ws";
import WebSocket from "isomorphic-ws";
import logger, { sessionContextLogger } from "./logger";
import {
CancelExecutionEvent,
Expand Down Expand Up @@ -30,7 +30,6 @@ import {
} from "./api-utils";
import z from "zod";
import { Table, TypeMap } from "apache-arrow";
import readPackageUp from "read-pkg-up";

// used to mock out the fetch and WebSocket APIs
// in a unit testing environment
Expand All @@ -46,14 +45,13 @@ type ConnectionTestHarness = {
protocolVersion?: string | undefined;
};

const { packageJson } = readPackageUp.sync({ cwd: __dirname }) || {};
const API_URL =
process.env["WHEROBOTS_API_URL"] || "https://api.cloud.wherobots.com";

const PROTOCOL_VERSION = "1.0.0";
const OS_TYPE = `${process.platform};${process.arch}`;
const NODE_VERSION = process.version;
const USER_AGENT = `${packageJson?.name}/${packageJson?.version} os/${OS_TYPE} node/${NODE_VERSION}"`;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'd rather not lose the package version from the user agent string. is there a way we can inject this as a build-time variable?

const USER_AGENT = `os/${OS_TYPE} node/${NODE_VERSION}`;

const API_REQUEST_TIMEOUT = 10e3;

Expand Down Expand Up @@ -348,16 +346,28 @@ export class Connection {
logger.child(errorEvent).error("Error event received");
cleanup();
abortSignal.removeEventListener("abort", handleSignalAborted);
reject(new Error("Error event received"));
reject(new Error(errorEvent.message));
}
}
let toParse: unknown;
if (typeof e.data === "string") {
toParse = JSON.parse(e.data);
} else if (Array.isArray(e.data)) {
toParse = decodeFirstSync(Buffer.concat(e.data));
const uint8ArrayArray = e.data.map(
(buffer) =>
new Uint8Array(
buffer.buffer,
buffer.byteOffset,
buffer.byteLength,
),
);
toParse = decode(Buffer.concat(uint8ArrayArray));
} else {
toParse = decodeFirstSync(e.data);
toParse = decode(
e.data instanceof Buffer
? e.data
: new Uint8Array(e.data as ArrayBuffer),
);
}
const data = schema.parse(toParse);
if (data["execution_id"] === executionId) {
Expand Down
102 changes: 92 additions & 10 deletions src/logger.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,101 @@
import pino from "pino";
import pinoPretty from "pino-pretty";
import log from "loglevel";
import { SessionReponse } from "./schemas";

const shouldUseDebugLogging = (process.env["NODE_DEBUG"] || "")
.split(",")
.includes("wherobots-sql-driver");

const logger = pino(
{
name: "wherobots-sql-driver",
level: shouldUseDebugLogging ? "debug" : "info",
enabled: process.env["NODE_ENV"] !== "test",
},
pinoPretty(),
);
// Configure the default logger
log.setLevel(shouldUseDebugLogging ? log.levels.DEBUG : log.levels.INFO);

// If tests are running, disable the logger
if (process.env["NODE_ENV"] === "test") {
log.setLevel(log.levels.SILENT);
}

// Setup a method factory to format log messages with context
const originalFactory = log.methodFactory;
log.methodFactory = function (methodName, logLevel, loggerName) {
const rawMethod = originalFactory(methodName, logLevel, loggerName);

return function (...args) {
// Check if the last argument is an object (context)
const lastArg = args[args.length - 1];
const hasContext =
lastArg && typeof lastArg === "object" && !Array.isArray(lastArg);

if (hasContext && args.length > 1) {
// Format message with context
const context = args.pop();
const formattedContext = Object.entries(context)
.map(([key, value]) => `${key}=${JSON.stringify(value)}`)
.join(" ");

rawMethod(`${args.join(" ")} [${formattedContext}]`);
} else {
// Regular logging without context
rawMethod(...args);
}
};
};

// Apply the method factory
log.setDefaultLevel(log.getLevel());

abstract class Logger {
abstract debug(...args: any[]): void;
abstract info(...args: any[]): void;
abstract warn(...args: any[]): void;
abstract error(...args: any[]): void;
abstract child(context: Record<string, any>): Logger;
}

class LogLevelLogger extends Logger {
private context: Record<string, any>;

constructor(context?: Record<string, any>) {
super();
this.context = context || {};
}

debug(...args: any[]) {
if (Object.keys(this.context).length > 0) {
log.debug(...args, this.context);
} else {
log.debug(...args);
}
}

info(...args: any[]) {
if (Object.keys(this.context).length > 0) {
log.info(...args, this.context);
} else {
log.info(...args);
}
}

warn(...args: any[]) {
if (Object.keys(this.context).length > 0) {
log.warn(...args, this.context);
} else {
log.warn(...args);
}
}

error(...args: any[]) {
if (Object.keys(this.context).length > 0) {
log.error(...args, this.context);
} else {
log.error(...args);
}
}

child(context: Record<string, any>) {
return new LogLevelLogger({ ...this.context, ...context });
}
}

const logger = new LogLevelLogger();

export default logger;

Expand Down
4 changes: 2 additions & 2 deletions src/testing/mockSocketBehaviors.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { encode } from "cbor";
import { encode } from "cbor-x";
import { readFileSync } from "fs";
import { resolve } from "path";
import WebSocket from "ws";
import WebSocket from "isomorphic-ws";
import { vi, MockedFunction, expect } from "vitest";
import {
ErrorEvent,
Expand Down
Loading