Fast MariaDB and MySQL connector for Node.js with Promise and callback APIs
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Comprehensive type definitions for MariaDB/MySQL data types, field attributes, and type casting functionality. These types provide full type safety and precise control over data handling in the MariaDB connector.
Numeric constants representing MySQL/MariaDB column types as they appear in the protocol.
enum TypeNumbers {
DECIMAL = 0,
TINY = 1,
SHORT = 2,
LONG = 3,
FLOAT = 4,
DOUBLE = 5,
NULL = 6,
TIMESTAMP = 7,
BIGINT = 8,
INT24 = 9,
DATE = 10,
TIME = 11,
DATETIME = 12,
YEAR = 13,
NEWDATE = 14,
VARCHAR = 15,
BIT = 16,
TIMESTAMP2 = 17,
DATETIME2 = 18,
TIME2 = 19,
JSON = 245, // MySQL only
NEWDECIMAL = 246,
ENUM = 247,
SET = 248,
TINY_BLOB = 249,
MEDIUM_BLOB = 250,
LONG_BLOB = 251,
BLOB = 252,
VAR_STRING = 253,
STRING = 254,
GEOMETRY = 255
}String constants representing MySQL/MariaDB column types for readable type identification.
enum Types {
DECIMAL = 'DECIMAL',
TINY = 'TINY',
SHORT = 'SHORT',
LONG = 'LONG',
FLOAT = 'FLOAT',
DOUBLE = 'DOUBLE',
NULL = 'NULL',
TIMESTAMP = 'TIMESTAMP',
BIGINT = 'BIGINT',
INT24 = 'INT24',
DATE = 'DATE',
TIME = 'TIME',
DATETIME = 'DATETIME',
YEAR = 'YEAR',
NEWDATE = 'NEWDATE',
VARCHAR = 'VARCHAR',
BIT = 'BIT',
TIMESTAMP2 = 'TIMESTAMP2',
DATETIME2 = 'DATETIME2',
TIME2 = 'TIME2',
JSON = 'JSON',
NEWDECIMAL = 'NEWDECIMAL',
ENUM = 'ENUM',
SET = 'SET',
TINY_BLOB = 'TINY_BLOB',
MEDIUM_BLOB = 'MEDIUM_BLOB',
LONG_BLOB = 'LONG_BLOB',
BLOB = 'BLOB',
VAR_STRING = 'VAR_STRING',
STRING = 'STRING',
GEOMETRY = 'GEOMETRY'
}Bit flags representing various attributes and constraints of database columns.
enum Flags {
/** Field cannot be null */
NOT_NULL = 1,
/** Field is a primary key */
PRIMARY_KEY = 2,
/** Field has a unique constraint */
UNIQUE_KEY = 4,
/** Field is part of a multiple-column key */
MULTIPLE_KEY = 8,
/** Field is a BLOB type */
BLOB = 16,
/** Field is unsigned (numeric types) */
UNSIGNED = 32,
/** Field has ZEROFILL attribute */
ZEROFILL_FLAG = 64,
/** Field has binary collation */
BINARY_COLLATION = 128,
/** Field is an ENUM */
ENUM = 256,
/** Field auto-increments */
AUTO_INCREMENT = 512,
/** Field is a TIMESTAMP */
TIMESTAMP = 1024,
/** Field is a SET */
SET = 2048,
/** Field has no default value */
NO_DEFAULT_VALUE_FLAG = 4096,
/** Field updates to NOW() on UPDATE */
ON_UPDATE_NOW_FLAG = 8192,
/** Field is numeric */
NUM_FLAG = 16384
}Type casting functionality for customizing how database values are converted to JavaScript types.
/**
* Custom type casting function for controlling data type conversion
* @param field - Field metadata information
* @param next - Function to get default type conversion
* @returns Converted value or result of next() for default conversion
*/
type TypeCastFunction = (field: FieldInfo, next: TypeCastNextFunction) => TypeCastResult;
/**
* Function to get the default type conversion for a field
* @returns Default converted value
*/
type TypeCastNextFunction = () => TypeCastResult;
/**
* Possible return types from type casting functions
*/
type TypeCastResult = boolean | number | string | symbol | null | Date | Geometry | Buffer;Type Casting Examples:
import { TypeCastFunction } from "mariadb";
// Convert TINYINT(1) to boolean, others to default
const booleanTypeCast: TypeCastFunction = (field, next) => {
if (field.type === 'TINY' && field.columnLength === 1) {
return field.string() === '1';
}
return next(); // Use default conversion
};
// Custom date formatting
const dateTypeCast: TypeCastFunction = (field, next) => {
if (field.type === 'DATE') {
const date = field.date();
return date ? date.toISOString().split('T')[0] : null;
}
return next();
};
// Handle large numbers safely
const safeNumberTypeCast: TypeCastFunction = (field, next) => {
if (field.type === 'BIGINT') {
const str = field.string();
const num = str ? BigInt(str) : null;
// Keep as BigInt if outside safe integer range
return num && num <= Number.MAX_SAFE_INTEGER && num >= Number.MIN_SAFE_INTEGER
? Number(num) : num;
}
return next();
};
// Use in connection config
const connection = await mariadb.createConnection({
host: "localhost",
user: "root",
password: "password",
database: "test",
typeCast: booleanTypeCast
});Interface for handling character set collations and encoding information.
interface Collation {
/** Collation index number */
index: number;
/** Collation name (e.g., 'utf8mb4_unicode_ci') */
name: string;
/** Character encoding (e.g., 'utf8mb4') */
encoding: string;
/** Maximum bytes per character */
maxLength: number;
/** Get collation by encoding name */
fromEncoding(encoding: string): Collation;
/** Get collation by index number */
fromIndex(index: number): Collation;
/** Get collation by collation name */
fromName(name: string): Collation;
}Comprehensive metadata interface for database columns providing type information and value access methods.
interface FieldInfo {
/** Collation information for the field */
collation: Collation;
/** Maximum length of the column */
columnLength: number;
/** Numeric type identifier */
columnType: TypeNumbers;
/** Decimal scale for numeric types */
scale: number;
/** String type identifier */
type: Types;
/** Bit flags for field attributes */
flags: Flags;
/** Get database name */
db(): string;
/** Get schema name (alias for db) */
schema(): string;
/** Get table name */
table(): string;
/** Get original table name */
orgTable(): string;
/** Get column name */
name(): string;
/** Get original column name */
orgName(): string;
/** Get field value as string */
string(): string | null;
/** Get field value as Buffer */
buffer(): Buffer | null;
/** Get field value as float */
float(): number | null;
/** Get field value as integer */
int(): number | null;
/** Get field value as long integer */
long(): number | null;
/** Get field value as decimal */
decimal(): number | null;
/** Get field value as Date object */
date(): Date | null;
/** Get field value as GeoJSON Geometry */
geometry(): Geometry | null;
}FieldInfo Usage Examples:
// Custom result processing with field metadata
const results = await connection.query("SELECT id, name, created_at, location FROM users");
// Access metadata through meta property
const meta = results.meta as FieldInfo[];
meta.forEach((field, index) => {
console.log(`Column ${index}:`);
console.log(` Name: ${field.name()}`);
console.log(` Type: ${field.type}`);
console.log(` Table: ${field.table()}`);
console.log(` Nullable: ${!(field.flags & Flags.NOT_NULL)}`);
console.log(` Primary Key: ${!!(field.flags & Flags.PRIMARY_KEY)}`);
console.log(` Auto Increment: ${!!(field.flags & Flags.AUTO_INCREMENT)}`);
});
// Type-based processing
const processRow = (row: any, meta: FieldInfo[]) => {
const processed: any = {};
meta.forEach((field, index) => {
const value = row[index];
const name = field.name();
switch (field.type) {
case 'TINY':
// Convert TINYINT(1) to boolean
processed[name] = field.columnLength === 1 ? !!value : value;
break;
case 'DATETIME':
case 'TIMESTAMP':
// Ensure dates are Date objects
processed[name] = value instanceof Date ? value : new Date(value);
break;
case 'JSON':
// Parse JSON strings
processed[name] = typeof value === 'string' ? JSON.parse(value) : value;
break;
default:
processed[name] = value;
}
});
return processed;
};Support for spatial/geometry data types using GeoJSON format.
import { Geometry } from 'geojson';
// Geometry types are represented using the standard GeoJSON format
interface Point extends Geometry {
type: 'Point';
coordinates: [number, number] | [number, number, number];
}
interface LineString extends Geometry {
type: 'LineString';
coordinates: Array<[number, number] | [number, number, number]>;
}
interface Polygon extends Geometry {
type: 'Polygon';
coordinates: Array<Array<[number, number] | [number, number, number]>>;
}Geometry Usage Example:
// Insert geometry data
await connection.execute(
"INSERT INTO locations (name, point) VALUES (?, ?)",
['Central Park', { type: 'Point', coordinates: [-73.965355, 40.782865] }]
);
// Query geometry data
const locations = await connection.query("SELECT name, ST_AsGeoJSON(point) as point FROM locations");
locations.forEach(row => {
const point = JSON.parse(row.point) as Point;
console.log(`${row.name}: ${point.coordinates[1]}, ${point.coordinates[0]}`);
});Type definitions for stream-related callback functions.
/**
* Callback function for stream operations
* @param err - Error if stream creation failed
* @param stream - Duplex stream for database communication
*/
function StreamCallback(err?: Error, stream?: Duplex): void;Additional utility types for working with MariaDB data.
/**
* User connection configuration for changeUser operations
*/
interface UserConnectionConfig {
/** Database name to switch to */
database?: string;
/** Connection attributes to send to server */
connectAttributes?: any;
/** Character set for the connection */
charset?: string;
/** Collation for the connection */
collation?: string;
/** Username to authenticate as */
user?: string;
/** Password for authentication */
password?: string;
}
/**
* Logger configuration for debugging and monitoring
*/
interface LoggerConfig {
/** Network-level logging */
network?: (msg: string) => void;
/** Query-level logging */
query?: (msg: string) => void;
/** Error logging */
error?: (err: Error) => void;
/** Warning logging */
warning?: (msg: string) => void;
}
/**
* Collation information for character encoding
*/
interface Collation {
/** Collation index number */
index: number;
/** Collation name */
name: string;
/** Character encoding */
encoding: string;
/** Maximum character length in bytes */
maxLength: number;
/** Get collation by encoding name */
fromEncoding(encoding: string): Collation;
/** Get collation by index */
fromIndex(index: number): Collation;
/** Get collation by name */
fromName(name: string): Collation;
}
/**
* Result structure for INSERT/UPDATE/DELETE operations
*/
interface UpsertResult {
/** Number of rows affected by the operation */
affectedRows: number;
/** Auto-generated ID from INSERT operations */
insertId: number | bigint;
/** Warning status from the server */
warningStatus: number;
}
/**
* Server version information
*/
interface ServerVersion {
/** Raw version string from server */
raw: string;
/** Whether server is MariaDB (true) or MySQL (false) */
mariaDb: boolean;
/** Major version number */
major: number;
/** Minor version number */
minor: number;
/** Patch version number */
patch: number;
}
/**
* Connection information and server details
*/
interface ConnectionInfo {
/** Server connection thread ID */
threadId: number | null;
/** Connection status flags */
status: number;
/** Server version information */
serverVersion: ServerVersion;
/** Connection collation */
collation: any;
/** Server capability flags */
serverCapabilities: number;
/** Check if server is MariaDB */
isMariaDB(): boolean;
/** Check if server version meets minimum requirement */
hasMinVersion(major: number, minor: number, patch: number): boolean;
}Working with Large Numbers:
// Configure safe number handling
const connection = await mariadb.createConnection({
host: "localhost",
user: "root",
password: "password",
database: "test",
// Keep BigInt as BigInt, don't convert to number
bigIntAsNumber: false,
// Keep decimals as strings for precision
decimalAsNumber: false,
// Throw error if number conversion would be unsafe
checkNumberRange: true,
// Convert insert IDs to numbers for convenience
insertIdAsNumber: true
});Custom Type Validation:
const validateTypeCast: TypeCastFunction = (field, next) => {
const value = next();
// Validate email format for email columns
if (field.name() === 'email' && typeof value === 'string') {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(value)) {
throw new Error(`Invalid email format: ${value}`);
}
}
// Validate date ranges
if (field.type === 'DATE' && value instanceof Date) {
const minDate = new Date('1900-01-01');
const maxDate = new Date('2100-01-01');
if (value < minDate || value > maxDate) {
throw new Error(`Date out of valid range: ${value}`);
}
}
return value;
};