🚀 Socket Launch Week Day 4:Socket MCP Adds Org Alerts, Threat Feed Review, and Package Inspection.Learn more
Sign In

@pglite/core

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@pglite/core - npm Package Compare versions

Comparing version
0.0.3
to
0.0.4
+76
-5
dist/ast/index.d.ts

@@ -1,5 +0,6 @@

export type TokenType = 'KEYWORD' | 'IDENTIFIER' | 'STRING' | 'NUMBER' | 'SYMBOL' | 'EOF' | 'PARAMETER';
export type TokenType = 'KEYWORD' | 'IDENTIFIER' | 'STRING' | 'NUMBER' | 'SYMBOL' | 'EOF' | 'PARAMETER' | 'NAMED_PARAMETER';
export interface Token {
type: TokenType;
value: string;
isDoubleQuoted?: boolean;
}

@@ -12,2 +13,3 @@ export type Expr = {

name: string;
isDoubleQuoted?: boolean;
} | {

@@ -17,2 +19,5 @@ type: 'Parameter';

} | {
type: 'NamedParameter';
name: string;
} | {
type: 'Binary';

@@ -34,2 +39,3 @@ left: Expr;

args: Expr[];
distinct?: boolean;
argsOrderBy?: OrderBy[];

@@ -82,2 +88,6 @@ over?: {

} | {
type: 'Extract';
field: string;
source: Expr;
} | {
type: 'Exists';

@@ -106,5 +116,8 @@ stmt: Statement;

comment?: string;
_isNumeric?: boolean;
_isBool?: boolean;
_isJson?: boolean;
}
export interface JoinClause {
type: 'INNER' | 'LEFT';
type: 'INNER' | 'LEFT' | 'RIGHT' | 'FULL' | 'CROSS';
tableName?: string;

@@ -122,2 +135,4 @@ stmt?: Statement;

desc: boolean;
nullsFirst?: boolean;
nullsLast?: boolean;
}

@@ -132,2 +147,3 @@ export type AlterTableAction = {

ifExists?: boolean;
cascade?: boolean;
} | {

@@ -157,2 +173,16 @@ type: 'RenameColumn';

columnName: string;
} | {
type: 'AddForeignKey';
columnName: string;
references: {
table: string;
column: string;
onDelete?: 'CASCADE' | 'RESTRICT' | 'SET NULL' | 'SET DEFAULT' | 'NO ACTION';
onUpdate?: 'CASCADE' | 'RESTRICT' | 'SET NULL' | 'SET DEFAULT' | 'NO ACTION';
};
} | {
type: 'DropConstraint';
constraintName: string;
ifExists?: boolean;
cascade?: boolean;
};

@@ -164,4 +194,12 @@ export type Statement = {

} | {
type: 'CreateIndex';
indexName: string;
tableName: string;
columns: string[];
unique?: boolean;
ifNotExists?: boolean;
where?: Expr;
} | {
type: 'DropSchema';
schemaName: string;
schemaNames: string[];
ifExists?: boolean;

@@ -171,5 +209,15 @@ cascade?: boolean;

type: 'DropTable';
tableName: string;
tableNames: string[];
ifExists?: boolean;
cascade?: boolean;
} | {
type: 'DropIndex';
indexNames: string[];
ifExists?: boolean;
cascade?: boolean;
} | {
type: 'DropOther';
objectType: string;
names: string[];
} | {
type: 'CreateTable';

@@ -183,3 +231,4 @@ tableName: string;

columns: string[];
values: Expr[][] | Expr[];
values?: Expr[][] | Expr[];
select?: Statement;
returning?: Expr[];

@@ -190,2 +239,4 @@ onConflict?: OnConflict;

columns: Expr[];
distinct?: boolean;
distinctOn?: Expr[];
from?: {

@@ -208,6 +259,12 @@ tableName?: string;

name: string;
columnAliases?: string[];
stmt: Statement;
recursive?: boolean;
}[];
union?: Statement;
unionAll?: Statement;
intersect?: Statement;
intersectAll?: Statement;
except?: Statement;
exceptAll?: Statement;
} | {

@@ -225,2 +282,16 @@ type: 'Update';

} | {
type: 'Truncate';
tableNames: string[];
cascade?: boolean;
restartIdentity?: boolean;
} | {
type: 'Values';
values: Expr[][];
ctes?: {
name: string;
columnAliases?: string[];
stmt: Statement;
recursive?: boolean;
}[];
} | {
type: 'AlterTable';

@@ -227,0 +298,0 @@ tableName: string;

import { type VFS } from './storage/engine';
export declare class FileMutex {
private static locks;
static acquire(filepath: string): Promise<() => void>;
}
export declare class LitePostgres {

@@ -8,5 +12,9 @@ private static readonly executor;

private currentDb?;
private destroyOnClose;
private txRelease?;
private queue;
constructor(filepath: string, options: {
database?: string;
adapter: VFS;
destroyOnClose?: boolean;
});

@@ -16,12 +24,22 @@ /**

*/
exec<T = any>(sql: string, params?: any[], dbName?: string): Promise<T>;
exec<T = any>(sql: string, params?: any[] | Record<string, any> | string, dbName?: string): Promise<T>;
/**
* Used for statements that return rows (SELECT)
*/
query<T = any>(sql: string, params?: any[], dbName?: string): Promise<T[]>;
query<T = any>(sql: string, params?: any[] | Record<string, any> | string, dbName?: string): Promise<T[]>;
/**
* Execute a callback function within a database transaction.
* If the callback resolves, the transaction is committed.
* If the callback throws an error, the transaction is rolled back.
*/
transaction<T>(callback: (tx: LitePostgres) => Promise<T>, dbName?: string): Promise<T>;
/**
* Explicitly release resources. Crucial for handling 1M+ database instances.
*/
close(): Promise<void>;
/**
* Explicitly destroy the database files.
*/
destroy(): Promise<void>;
private run;
}

@@ -5,2 +5,19 @@ import { Lexer } from './parser/lexer';

import { StorageEngine } from './storage/engine';
export class FileMutex {
static locks = new Map();
static async acquire(filepath) {
while (this.locks.has(filepath)) {
await this.locks.get(filepath);
}
let release;
const p = new Promise((resolve) => {
release = () => {
this.locks.delete(filepath);
resolve();
};
});
this.locks.set(filepath, p);
return release;
}
}
export class LitePostgres {

@@ -12,4 +29,8 @@ static executor = new Executor();

currentDb;
destroyOnClose;
txRelease;
queue = Promise.resolve();
constructor(filepath, options) {
this.defaultDb = options.database || 'postgres';
this.destroyOnClose = !!options.destroyOnClose;
if (!options.adapter) {

@@ -23,4 +44,21 @@ throw new Error("A VFS adapter must be provided. For Node.js, use NodeFSAdapter from '@pglite/core/node-fs'.");

*/
async exec(sql, params = [], dbName) {
return this.run(sql, params, dbName || this.defaultDb);
async exec(sql, params, dbName) {
let actualParams = [];
let actualDbName = dbName;
if (typeof params === 'string') {
actualDbName = params;
}
else if (params !== undefined && params !== null) {
actualParams = params;
}
return new Promise((resolve, reject) => {
this.queue = this.queue.then(async () => {
try {
resolve(await this.run(sql, actualParams, actualDbName || this.defaultDb));
}
catch (e) {
reject(e);
}
});
});
}

@@ -30,16 +68,153 @@ /**

*/
async query(sql, params = [], dbName) {
const result = await this.run(sql, params, dbName || this.defaultDb);
return Array.isArray(result) ? result : [];
async query(sql, params, dbName) {
let actualParams = [];
let actualDbName = dbName;
if (typeof params === 'string') {
actualDbName = params;
}
else if (params !== undefined && params !== null) {
actualParams = params;
}
return new Promise((resolve, reject) => {
this.queue = this.queue.then(async () => {
try {
const result = await this.run(sql, actualParams, actualDbName || this.defaultDb);
resolve(Array.isArray(result) ? result : []);
}
catch (e) {
reject(e);
}
});
});
}
/**
* Execute a callback function within a database transaction.
* If the callback resolves, the transaction is committed.
* If the callback throws an error, the transaction is rolled back.
*/
async transaction(callback, dbName) {
const txDb = dbName || this.defaultDb;
return new Promise((resolve, reject) => {
this.queue = this.queue.then(async () => {
let txQueue = Promise.resolve();
try {
await this.run('BEGIN', [], txDb);
const txObj = new Proxy(this, {
get: (target, prop) => {
if (prop === 'exec')
return (sql, p, db) => {
let actualP = [];
let actualDb = db;
if (typeof p === 'string') {
actualDb = p;
}
else if (p !== undefined && p !== null) {
actualP = p;
}
return new Promise((resolve, reject) => {
txQueue = txQueue.then(async () => {
try {
resolve(await target.run(sql, actualP, actualDb || txDb));
}
catch (e) {
reject(e);
}
});
});
};
if (prop === 'query')
return (sql, p, db) => {
let actualP = [];
let actualDb = db;
if (typeof p === 'string') {
actualDb = p;
}
else if (p !== undefined && p !== null) {
actualP = p;
}
return new Promise((resolve, reject) => {
txQueue = txQueue.then(async () => {
try {
const res = await target.run(sql, actualP, actualDb || txDb);
resolve(Array.isArray(res) ? res : []);
}
catch (e) {
reject(e);
}
});
});
};
if (prop === 'transaction')
return async () => { throw new Error("Nested transactions not supported"); };
return target[prop];
}
});
const result = await callback(txObj);
await txQueue;
if (this.storage.isInTransaction()) {
await this.run('COMMIT', [], txDb);
}
resolve(result);
}
catch (error) {
await txQueue;
if (this.storage.isInTransaction()) {
try {
await this.run('ROLLBACK', [], txDb);
}
catch (rollbackError) { }
}
reject(error);
}
});
});
}
/**
* Explicitly release resources. Crucial for handling 1M+ database instances.
*/
async close() {
await this.storage.close();
return new Promise((resolve, reject) => {
this.queue = this.queue.then(async () => {
try {
if (this.destroyOnClose) {
await this.storage.destroy();
}
else {
await this.storage.close();
}
resolve();
}
catch (e) {
reject(e);
}
});
});
}
/**
* Explicitly destroy the database files.
*/
async destroy() {
return new Promise((resolve, reject) => {
this.queue = this.queue.then(async () => {
try {
await this.storage.destroy();
resolve();
}
catch (e) {
reject(e);
}
});
});
}
async run(sql, params = [], dbName) {
let release;
if (!this.storage.isInTransaction()) {
release = await FileMutex.acquire(this.storage.filepath);
}
try {
sql = sql.trim();
if (this.currentDb !== dbName) {
if (this.storage.isInTransaction()) {
throw new Error("Cannot switch database within a transaction");
}
await this.storage.init(dbName);

@@ -70,6 +245,29 @@ this.currentDb = dbName;

await this.storage.flush();
if (release)
release();
if (this.txRelease) {
this.txRelease();
this.txRelease = undefined;
}
}
else {
if (release) {
this.txRelease = release;
}
}
return results.length === 1 ? results[0] : results;
}
catch (error) {
if (this.storage.isInTransaction()) {
await this.storage.rollback();
}
else {
await this.storage.rollbackStatement();
}
if (this.txRelease) {
this.txRelease();
this.txRelease = undefined;
}
if (release)
release();
console.log(`[LitePostgres Error]`, error);

@@ -76,0 +274,0 @@ throw new Error(`[LitePostgres Error] ${error.message}`);

@@ -11,4 +11,6 @@ import { Statement } from "../ast";

private getExprKey;
private getTableCopy;
constructor();
execute(storage: StorageEngine, stmt: Statement, params?: any[]): Promise<any>;
private rewriteTableData;
execute(storage: StorageEngine, stmt: Statement, params?: any): Promise<any>;
private executeSelect;

@@ -19,3 +21,8 @@ private mapStream;

private hashJoinStream;
private distinctStream;
private concatStreams;
private intersectStream;
private intersectAllStream;
private exceptStream;
private exceptAllStream;
private applyOffset;

@@ -27,3 +34,10 @@ private applyLimit;

private streamingAggregate;
private castValue;
private getDatePart;
private calculateAge;
private deepSet;
private deepInsert;
private stripNulls;
private jsonTypeof;
private evaluateExpr;
}
+61
-21

@@ -6,9 +6,13 @@ export class Lexer {

"CREATE", "TABLE", "INSERT", "INTO", "VALUES", "SELECT", "FROM", "WHERE", "UPDATE", "SET", "DELETE",
"PRIMARY", "KEY", "SERIAL", "TEXT", "NUMBER", "AND", "OR", "NOT", "IN", "LIKE", "ORDER", "BY",
"DESC", "ASC", "LIMIT", "OFFSET", "INNER", "LEFT", "JOIN", "ON", "GROUP", "HAVING", "AS", "RETURNING",
"PRIMARY", "KEY", "SERIAL", "TEXT", "NUMBER", "AND", "OR", "NOT", "IN", "LIKE", "ORDER", "BY", "FIRST_VALUE", "LAST_VALUE",
"DESC", "ASC", "LIMIT", "OFFSET", "INNER", "LEFT", "RIGHT", "FULL", "CROSS", "OUTER", "JOIN", "ON", "GROUP", "HAVING", "AS", "RETURNING", "BETWEEN",
"UNIQUE", "NULL", "IS", "REFERENCES", "ALTER", "ADD", "COLUMN", "DEFAULT", "BEGIN", "COMMIT", "ROLLBACK",
"CONFLICT", "NOTHING", "OVER", "PARTITION", "CASE", "WHEN", "THEN", "ELSE", "ARRAY", "UNNEST", "ORDINALITY",
"WITH", "UNION", "INTERSECT", "DO", "LANGUAGE", "$DO", "SCHEMA", "IF", "EXISTS", "CASCADE", "RESTRICT", "DROP", "FILTER", "INTERVAL", "ESCAPE", "ILIKE", "ESCAPE", "ILIKE",
"CONFLICT", "NOTHING", "OVER", "PARTITION", "CASE", "WHEN", "THEN", "ELSE", "ARRAY", "UNNEST", "JSON_EACH", "JSONB_EACH", "JSON_ARRAY_ELEMENTS", "JSONB_ARRAY_ELEMENTS", "ORDINALITY",
"LEAD", "LAG", "FIRST_VALUE", "LAST_VALUE", "DENSE_RANK",
"WITH", "RECURSIVE", "UNION", "ALL", "INTERSECT", "EXCEPT", "DO", "LANGUAGE", "$DO", "SCHEMA", "IF", "EXISTS", "CASCADE", "RESTRICT", "DROP", "FILTER", "INTERVAL", "ESCAPE", "ILIKE", "DISTINCT",
"EXTRACT", "AGE", "TO_CHAR", "DATE_PART", "CURRENT_TIMESTAMP", "CURRENT_DATE", "CURRENT_TIME", "LOCALTIMESTAMP", "LOCALTIME",
"RENAME", "TO", "TYPE", "COMMENT", "ON", "IS", "CONSTRAINT", "FOREIGN", "TRUE", "FALSE", "CAST", "LATERAL",
"START", "TRANSACTION", "ABORT", "END", "CHECK", "GENERATED", "ALWAYS", "IDENTITY",
"START", "TRANSACTION", "ABORT", "END", "CHECK", "GENERATED", "ALWAYS", "IDENTITY", "INDEX",
"MATERIALIZED", "VIEW", "SEQUENCE", "DOMAIN", "ROLE", "USER", "EXTENSION",
"TRUNCATE", "RESTART", "CONTINUE",
"INT", "INTEGER", "SMALLINT", "BIGINT", "DECIMAL", "NUMERIC", "REAL", "DOUBLE", "PRECISION", "MONEY",

@@ -98,3 +102,3 @@ "VARCHAR", "CHAR", "CHARACTER", "VARYING", "TEXT", "BYTEA", "TIMESTAMP", "TIMESTAMPTZ", "DATE", "TIME", "TIMETZ", "INTERVAL",

const twoChar = this.input.slice(this.pos, this.pos + 2);
if (['>=', '<=', '!=', '::', '||', '->', '~*', '!~', '#>', '@>', '&&'].includes(twoChar)) {
if (['>=', '<=', '!=', '::', '||', '->', '~*', '!~', '#>', '#-', '@>', '&&'].includes(twoChar)) {
tokens.push({ type: "SYMBOL", value: twoChar });

@@ -104,2 +108,10 @@ this.pos += 2;

}
if (char === ":") {
const paramMatch = this.input.slice(this.pos).match(/^:([a-zA-Z0-9_]+)/);
if (paramMatch) {
tokens.push({ type: "NAMED_PARAMETER", value: paramMatch[1] });
this.pos += paramMatch[0].length;
continue;
}
}
if (/[=><*+,();\/.:;[\]|!~?\-]/.test(char)) {

@@ -131,2 +143,3 @@ tokens.push({ type: "SYMBOL", value: char });

let hasE = false;
let isIdentifier = false;
while (this.pos < this.input.length) {

@@ -142,9 +155,19 @@ const char = this.input[this.pos] || "";

else if ((char === 'e' || char === 'E') && !hasE) {
hasE = true;
this.pos++;
const nextChar = this.input[this.pos] || "";
if (nextChar === '+' || nextChar === '-') {
const nextChar = this.input[this.pos + 1] || "";
if (/[0-9+\-]/.test(nextChar)) {
hasE = true;
this.pos++;
if (nextChar === '+' || nextChar === '-') {
this.pos++;
}
}
else {
isIdentifier = true;
this.pos++;
}
}
else if (/[a-zA-Z_$]/.test(char)) {
isIdentifier = true;
this.pos++;
}
else {

@@ -154,3 +177,4 @@ break;

}
return { type: "NUMBER", value: this.input.slice(start, this.pos) };
const value = this.input.slice(start, this.pos);
return { type: isIdentifier ? "IDENTIFIER" : "NUMBER", value };
}

@@ -180,3 +204,5 @@ readString() {

}
throw new Error("Lexer Error: Unterminated string");
// Implicitly close at EOF for truncated queries
res += this.input.slice(start, this.pos);
return { type: "STRING", value: res };
}

@@ -186,10 +212,23 @@ readQuotedIdentifier() {

let start = this.pos;
while (this.pos < this.input.length && this.input[this.pos] !== '"') {
this.pos++;
let res = "";
while (this.pos < this.input.length) {
if (this.input[this.pos] === '"') {
if (this.input[this.pos + 1] === '"') {
res += this.input.slice(start, this.pos) + '"';
this.pos += 2;
start = this.pos;
}
else {
res += this.input.slice(start, this.pos);
this.pos++; // skip closing "
return { type: "IDENTIFIER", value: res, isDoubleQuoted: true };
}
}
else {
this.pos++;
}
}
if (this.pos >= this.input.length)
throw new Error("Lexer Error: Unterminated quoted identifier");
const id = this.input.slice(start, this.pos);
this.pos++; // skip "
return { type: "IDENTIFIER", value: id };
// Implicitly close at EOF
res += this.input.slice(start, this.pos);
return { type: "IDENTIFIER", value: res, isDoubleQuoted: true };
}

@@ -205,4 +244,5 @@ readDollarString(tag) {

}
if (this.pos >= this.input.length)
throw new Error("Lexer Error: Unterminated dollar-quoted string");
if (this.pos >= this.input.length) {
return { type: "STRING", value: this.input.slice(start, this.pos) };
}
const str = this.input.slice(start, this.pos);

@@ -209,0 +249,0 @@ this.pos += tag.length; // skip closing tag

@@ -14,2 +14,4 @@ import { Token, TokenType, Statement } from '../ast';

private parseExpr;
private parseQuery;
private parseValues;
private parseReturning;

@@ -27,3 +29,3 @@ private parseOr;

private parseDataType;
private parseCreateTable;
private parseCreate;
private parseAlter;

@@ -34,2 +36,3 @@ private parseSelect;

private parseDelete;
private parseTruncate;
private parseDrop;

@@ -36,0 +39,0 @@ private parseComment;

@@ -32,12 +32,13 @@ import { ColumnDef } from "../ast";

export declare class StorageEngine {
private filepath;
filepath: string;
private pager;
vfs: VFS;
private static dbMetaCache;
private tableCache;
private schemaCache;
private pkIndexes;
private static tableCache;
private static schemaCache;
private static pkIndexes;
private tempTables;
private inTransaction;
private txBackup;
private txDbMetaBackup;
private txClusterMetaBackup;
private currentDbName?;

@@ -66,2 +67,3 @@ private clusterInitialized;

getFullTableName(name: string): string;
createIndex(indexName: string, tableName: string, columns: string[], unique: boolean, ifNotExists: boolean): Promise<void>;
createSchema(name: string, ifNotExists?: boolean): Promise<void>;

@@ -73,3 +75,4 @@ private getSchemas;

renameTable(oldName: string, newName: string): Promise<void>;
dropTable(name: string, ifExists?: boolean): Promise<void>;
dropIndex(indexName: string, ifExists?: boolean, cascade?: boolean): Promise<void>;
dropTable(name: string, ifExists?: boolean, cascade?: boolean): Promise<void>;
getTable(name: string): TableData;

@@ -88,7 +91,9 @@ getTableAsync(name: string): Promise<TableData | null>;

private isNumericType;
private static readonly SERIALIZATION_SCRATCH;
private handleOverflow;
private isOverflow;
private freeOverflowPages;
private resolveOverflow;
private serializeRow;
private deserializeRow;
truncateTable(name: string, cascade?: boolean, restartIdentity?: boolean, visited?: Set<string>, tablesInStmt?: Set<string>, ignoreFkChecks?: boolean): Promise<void>;
getPKColumn(name: string): Promise<string | null>;

@@ -108,2 +113,4 @@ /**

updateRows(name: string, filterFn: (row: any) => Promise<boolean>, updateFn: (row: any) => Promise<void>): Promise<number>;
updateRowByPK(name: string, pkValue: any, filterFn: (row: any) => Promise<boolean>, updateFn: (row: any) => Promise<void>): Promise<number>;
deleteRowByPK(name: string, pkValue: any, filterFn: (row: any) => Promise<boolean>): Promise<number>;
deleteRows(name: string, filterFn: (row: any) => Promise<boolean>): Promise<number>;

@@ -114,4 +121,6 @@ begin(): void;

rollback(): Promise<void>;
rollbackStatement(): Promise<void>;
flush(): Promise<void>;
close(): Promise<void>;
destroy(): Promise<void>;
}
{
"name": "@pglite/core",
"version": "0.0.3",
"version": "0.0.4",
"description": "High-performance, in-process, zero-dependency embedded PostgreSQL database engine for Bun & Node.js. A lightweight, serverless SQLite alternative with full Postgres syntax support.",

@@ -5,0 +5,0 @@ "keywords": [

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display