@happyvertical/sql 0.102.4 → 0.102.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -0
- package/dist/chunks/{duckdb-LMyfKZGi.js → duckdb-c4vdDzPL.js} +5 -4
- package/dist/chunks/{duckdb-LMyfKZGi.js.map → duckdb-c4vdDzPL.js.map} +1 -1
- package/dist/chunks/duckdb-resources-DBlvosDo.js +44 -0
- package/dist/chunks/duckdb-resources-DBlvosDo.js.map +1 -0
- package/dist/chunks/{postgres-dialect-Bfswr4Vs.js → postgres-dialect-CGv6DxSP.js} +3 -775
- package/dist/chunks/postgres-dialect-CGv6DxSP.js.map +1 -0
- package/dist/chunks/query-RzXJ4B9s.js +353 -0
- package/dist/chunks/query-RzXJ4B9s.js.map +1 -0
- package/dist/chunks/schema-manager-cxsySSDA.js +777 -0
- package/dist/chunks/schema-manager-cxsySSDA.js.map +1 -0
- package/dist/chunks/{sqlite-connection-cache-ChWav9iY.js → sqlite-connection-cache-CYThh9l5.js} +2 -2
- package/dist/chunks/{sqlite-connection-cache-ChWav9iY.js.map → sqlite-connection-cache-CYThh9l5.js.map} +1 -1
- package/dist/chunks/{sqlite-native--z4BnolL.js → sqlite-native-CsJ_BLqN.js} +5 -4
- package/dist/chunks/{sqlite-native--z4BnolL.js.map → sqlite-native-CsJ_BLqN.js.map} +1 -1
- package/dist/chunks/{sqlite-0PMv1va2.js → sqlite-rILMdW7Z.js} +6 -5
- package/dist/chunks/{sqlite-0PMv1va2.js.map → sqlite-rILMdW7Z.js.map} +1 -1
- package/dist/index.d.ts +3 -45
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -238
- package/dist/index.js.map +1 -1
- package/dist/pglite.js +2 -1
- package/dist/pglite.js.map +1 -1
- package/dist/query.d.ts +61 -0
- package/dist/query.d.ts.map +1 -0
- package/dist/query.js +3 -0
- package/package.json +6 -2
- package/dist/chunks/duckdb-resources-Cci6Lo6H.js +0 -156
- package/dist/chunks/duckdb-resources-Cci6Lo6H.js.map +0 -1
- package/dist/chunks/postgres-dialect-Bfswr4Vs.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -49,62 +49,20 @@ export type GetDatabaseOptions = (PostgresOptions & {
|
|
|
49
49
|
* @throws Error if the database type is invalid
|
|
50
50
|
*/
|
|
51
51
|
export declare function getDatabase(options?: GetDatabaseOptions | DatabaseInterface): Promise<DatabaseInterface>;
|
|
52
|
-
|
|
53
|
-
* Synchronizes a SQL schema definition with a database
|
|
54
|
-
* Creates tables if they don't exist and adds missing columns to existing tables
|
|
55
|
-
*
|
|
56
|
-
* @param options - Object containing database and schema
|
|
57
|
-
* @param options.db - Database interface to use
|
|
58
|
-
* @param options.schema - SQL schema definition
|
|
59
|
-
* @throws Error if db or schema are missing or if the database doesn't support syncSchema
|
|
60
|
-
*/
|
|
61
|
-
export declare function syncSchema(options: {
|
|
62
|
-
db: DatabaseInterface;
|
|
63
|
-
schema: string;
|
|
64
|
-
}): Promise<void>;
|
|
65
|
-
/**
|
|
66
|
-
* Checks if a table exists in the database
|
|
67
|
-
*
|
|
68
|
-
* @param db - Database interface to use
|
|
69
|
-
* @param tableName - Name of the table to check
|
|
70
|
-
* @returns Promise resolving to boolean indicating if the table exists
|
|
71
|
-
*/
|
|
72
|
-
export declare function tableExists(db: DatabaseInterface, tableName: string): Promise<boolean>;
|
|
73
|
-
/**
|
|
74
|
-
* Escapes and formats a value for use in SQL queries
|
|
75
|
-
*
|
|
76
|
-
* @param value - Value to escape
|
|
77
|
-
* @returns String representation of the value safe for SQL use
|
|
78
|
-
*/
|
|
79
|
-
export declare function escapeSqlValue(value: any): string;
|
|
80
|
-
/**
|
|
81
|
-
* Validates a column name for use in SQL queries
|
|
82
|
-
*
|
|
83
|
-
* @param column - Column name to validate
|
|
84
|
-
* @returns The validated column name
|
|
85
|
-
* @throws Error if the column name contains invalid characters
|
|
86
|
-
*/
|
|
87
|
-
export declare function validateColumnName(column: string): string;
|
|
88
|
-
import { buildWhere, formatDbError, raw } from "./shared/utils.js";
|
|
89
|
-
export { type AggregateBuildResult, type AggregateFunction, type AggregateSelectExpr, type AggregateSpec, type AggregateTimeBucketUnit, bucketExpr, buildAggregate, } from './aggregate.js';
|
|
90
|
-
export type { RawSqlKey, SqlAdapterType } from "./shared/utils.js";
|
|
91
|
-
export { buildWhere, formatDbError, raw };
|
|
92
|
-
import { convertUniqueIndexesToInlineConstraints } from "./shared/duckdb-schema-utils.js";
|
|
52
|
+
import { raw, syncSchema, tableExists } from './query.js';
|
|
93
53
|
export { checkExpectedTables, checkRelationship, checkUniqueColumn, type DoctorCheck, type DoctorContext, type DoctorIssue, type DoctorLevel, type DoctorResult, type RelationshipSpec, type RunDoctorOptions, runDoctor, type UniqueColumnSpec, } from "./doctor.js";
|
|
94
54
|
export { clearConnectionCache } from './json.js';
|
|
95
55
|
export type { PGliteLike, PGliteOptions } from "./pglite.js";
|
|
96
56
|
export { clearPostgresConnectionCache } from './postgres.js';
|
|
97
57
|
export { assertCanExportDatabase, assertCanImportDatabase, type CreateDropOptions, createPostgresDatabase, type DumpOptions, databaseNameFromUrl, dropPostgresDatabase, dumpPostgresDatabase, isLocalDatabaseUrl, type PostgresImportLocalityOptions, type PostgresLocalityOptions, postgresEnvFromUrl, type RestoreOptions, redactDatabaseUrl, restorePostgresDatabase, } from "./postgres-cli.js";
|
|
98
|
-
export type
|
|
99
|
-
export { DatabaseSchemaManager } from "./schema-manager.js";
|
|
58
|
+
export { type AggregateBuildResult, type AggregateFunction, type AggregateSelectExpr, type AggregateSpec, type AggregateTimeBucketUnit, bucketExpr, buildAggregate, buildWhere, convertUniqueIndexesToInlineConstraints, DatabaseSchemaManager, escapeSqlValue, formatDbError, type RawSqlKey, raw, type SchemaInitializationResult, type SqlAdapterType, syncSchema, tableExists, validateColumnName, } from './query.js';
|
|
100
59
|
export * from "./shared/types.js";
|
|
101
60
|
export type { SecureSqliteFileOptions, SqliteOptions } from './sqlite.js';
|
|
102
|
-
export { convertUniqueIndexesToInlineConstraints };
|
|
103
61
|
declare const _default: {
|
|
104
62
|
getDatabase: typeof getDatabase;
|
|
105
63
|
syncSchema: typeof syncSchema;
|
|
106
64
|
tableExists: typeof tableExists;
|
|
107
|
-
buildWhere: (where: import("./
|
|
65
|
+
buildWhere: (where: import("./query.js").WhereClause, startIndex?: number, adapterType?: import("./query.js").SqlAdapterType) => {
|
|
108
66
|
sql: string;
|
|
109
67
|
values: any[];
|
|
110
68
|
};
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAU,CAAC;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAY,CAAC;AAClD,OAAO,KAAK,EACV,iBAAiB,EACjB,aAAa,EACb,WAAW,EACZ,MAAM,mBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAU,CAAC;AAE9C;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAC1B,CAAC,eAAe,GAAG;IAAE,IAAI,CAAC,EAAE,UAAU,CAAA;CAAE,CAAC,GACzC,CAAC,aAAa,GAAG;IAAE,IAAI,CAAC,EAAE,QAAQ,CAAA;CAAE,CAAC,GACrC,CAAC,aAAa,GAAG;IAAE,IAAI,CAAC,EAAE,QAAQ,CAAA;CAAE,CAAC,GACrC,CAAC,aAAa,GAAG;IAAE,IAAI,CAAC,EAAE,QAAQ,CAAA;CAAE,CAAC,GACrC,WAAW,CAAC;AAmBhB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAsB,WAAW,CAC/B,OAAO,GAAE,kBAAkB,GAAG,iBAAsB,GACnD,OAAO,CAAC,iBAAiB,CAAC,CAqD5B;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAU,CAAC;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAY,CAAC;AAClD,OAAO,KAAK,EACV,iBAAiB,EACjB,aAAa,EACb,WAAW,EACZ,MAAM,mBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAU,CAAC;AAE9C;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAC1B,CAAC,eAAe,GAAG;IAAE,IAAI,CAAC,EAAE,UAAU,CAAA;CAAE,CAAC,GACzC,CAAC,aAAa,GAAG;IAAE,IAAI,CAAC,EAAE,QAAQ,CAAA;CAAE,CAAC,GACrC,CAAC,aAAa,GAAG;IAAE,IAAI,CAAC,EAAE,QAAQ,CAAA;CAAE,CAAC,GACrC,CAAC,aAAa,GAAG;IAAE,IAAI,CAAC,EAAE,QAAQ,CAAA;CAAE,CAAC,GACrC,WAAW,CAAC;AAmBhB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAsB,WAAW,CAC/B,OAAO,GAAE,kBAAkB,GAAG,iBAAsB,GACnD,OAAO,CAAC,iBAAiB,CAAC,CAqD5B;AAcD,OAAO,EAAc,GAAG,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAGtE,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,SAAS,EACT,KAAK,gBAAgB,GACtB,MAAM,aAAU,CAAC;AAElB,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAIjD,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,aAAU,CAAC;AAC1D,OAAO,EAAE,4BAA4B,EAAE,MAAM,eAAe,CAAC;AAE7D,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,KAAK,iBAAiB,EACtB,sBAAsB,EACtB,KAAK,WAAW,EAChB,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,KAAK,6BAA6B,EAClC,KAAK,uBAAuB,EAC5B,kBAAkB,EAClB,KAAK,cAAc,EACnB,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,mBAAgB,CAAC;AACxB,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,aAAa,EAClB,KAAK,uBAAuB,EAC5B,UAAU,EACV,cAAc,EACd,UAAU,EACV,uCAAuC,EACvC,qBAAqB,EACrB,cAAc,EACd,aAAa,EACb,KAAK,SAAS,EACd,GAAG,EACH,KAAK,0BAA0B,EAC/B,KAAK,cAAc,EACnB,UAAU,EACV,WAAW,EACX,kBAAkB,GACnB,MAAM,YAAY,CAAC;AACpB,cAAc,mBAAgB,CAAC;AAC/B,YAAY,EAAE,uBAAuB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;;;;;;;;;;;AAE1E,wBAME;AAEF,gBAAgB;AAChB,eAAO,MAAM,2BAA2B,OAAO,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as
|
|
1
|
+
import { a as raw, c as wrapDatabaseError, n as buildWhere, o as resolveInsertColumns, r as formatDbError, t as DatabaseSchemaManager } from "./chunks/schema-manager-cxsySSDA.js";
|
|
2
|
+
import { a as NestedTransactionError, c as bucketExpr, i as validateColumnName, l as buildAggregate, n as syncSchema, o as resolveSchemas, r as tableExists, s as convertUniqueIndexesToInlineConstraints, t as escapeSqlValue } from "./chunks/query-RzXJ4B9s.js";
|
|
3
3
|
import { a as dropPostgresDatabase, c as postgresEnvFromUrl, i as databaseNameFromUrl, l as redactDatabaseUrl, n as assertCanImportDatabase, o as dumpPostgresDatabase, r as createPostgresDatabase, s as isLocalDatabaseUrl, t as assertCanExportDatabase, u as restorePostgresDatabase } from "./chunks/postgres-cli-DzZcXSIG.js";
|
|
4
|
+
import { _ as validateColumnNames, a as createVectorCapabilities, c as createTransactionLock, d as validateDatabaseCacheOptions, f as escapeQuotedIdentifier, i as createTransactionErrorTracker, l as ConnectionCache, n as createGetTableSchema, o as normalizePostgresRawQuery, p as escapeStringLiteral, r as createPostgresDialect, t as createAlterTable, u as enableCachedValidation } from "./chunks/postgres-dialect-CGv6DxSP.js";
|
|
5
|
+
import { n as throwWithDuckDBCleanup, t as createDuckDBResourceCloser } from "./chunks/duckdb-resources-DBlvosDo.js";
|
|
4
6
|
import { t as redactDatabaseUrl$1 } from "./chunks/redact-database-url-CfMDvSdy.js";
|
|
5
7
|
import { DatabaseError, loadEnvConfig } from "@happyvertical/utils";
|
|
6
8
|
import { mkdir, readdir, stat } from "node:fs/promises";
|
|
@@ -20,149 +22,6 @@ var __exportAll = (all, no_symbols) => {
|
|
|
20
22
|
return target;
|
|
21
23
|
};
|
|
22
24
|
//#endregion
|
|
23
|
-
//#region src/aggregate.ts
|
|
24
|
-
var VALID_DIRECTIONS = /* @__PURE__ */ new Set(["ASC", "DESC"]);
|
|
25
|
-
var VALID_BUCKET_UNITS = /* @__PURE__ */ new Set([
|
|
26
|
-
"minute",
|
|
27
|
-
"hour",
|
|
28
|
-
"day",
|
|
29
|
-
"week",
|
|
30
|
-
"month",
|
|
31
|
-
"quarter",
|
|
32
|
-
"year"
|
|
33
|
-
]);
|
|
34
|
-
function validateSqlIdentifier(identifier) {
|
|
35
|
-
if (typeof identifier !== "string" || !/^[a-zA-Z0-9_.]+$/.test(identifier)) throw new Error(`Invalid SQL identifier: ${identifier}`);
|
|
36
|
-
return identifier;
|
|
37
|
-
}
|
|
38
|
-
function normalizeAdapter(adapterType) {
|
|
39
|
-
return adapterType ?? "sqlite";
|
|
40
|
-
}
|
|
41
|
-
function placeholder(index) {
|
|
42
|
-
return `$${index}`;
|
|
43
|
-
}
|
|
44
|
-
function bucketExpr(adapterType, unit, column) {
|
|
45
|
-
if (!VALID_BUCKET_UNITS.has(unit)) throw new Error(`Invalid aggregate bucket unit: ${unit}`);
|
|
46
|
-
const col = validateSqlIdentifier(column);
|
|
47
|
-
const adapter = normalizeAdapter(adapterType);
|
|
48
|
-
if (adapter === "postgres" || adapter === "duckdb" || adapter === "json") return `date_trunc('${unit}', ${col})`;
|
|
49
|
-
switch (unit) {
|
|
50
|
-
case "minute": return `strftime('%Y-%m-%d %H:%M:00', ${col})`;
|
|
51
|
-
case "hour": return `strftime('%Y-%m-%d %H:00:00', ${col})`;
|
|
52
|
-
case "day": return `strftime('%Y-%m-%d 00:00:00', ${col})`;
|
|
53
|
-
case "week": return `strftime('%Y-%m-%d 00:00:00', date(${col}, printf('-%d days', (CAST(strftime('%w', ${col}) AS INTEGER) + 6) % 7)))`;
|
|
54
|
-
case "month": return `strftime('%Y-%m-01 00:00:00', ${col})`;
|
|
55
|
-
case "quarter": return `strftime('%Y-%m-%d 00:00:00', date(strftime('%Y-', ${col}) || printf('%02d', ((CAST(strftime('%m', ${col}) AS INTEGER) - 1) / 3) * 3 + 1) || '-01'))`;
|
|
56
|
-
case "year": return `strftime('%Y-01-01 00:00:00', ${col})`;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
function aggregateExpression(expr) {
|
|
60
|
-
const normalizedFn = String(expr.fn).toLowerCase();
|
|
61
|
-
const fn = validateSqlIdentifier(String(expr.fn)).toUpperCase();
|
|
62
|
-
if (normalizedFn === "count" && !expr.column) {
|
|
63
|
-
if (expr.distinct) throw new Error(`Aggregate ${expr.fn} with distinct requires a column`);
|
|
64
|
-
return "COUNT(*)";
|
|
65
|
-
}
|
|
66
|
-
if (!expr.column) throw new Error(`Aggregate ${expr.fn} requires a column`);
|
|
67
|
-
const col = validateSqlIdentifier(expr.column);
|
|
68
|
-
return `${fn}(${expr.distinct ? "DISTINCT " : ""}${col})`;
|
|
69
|
-
}
|
|
70
|
-
function selectExpression(expr, adapterType) {
|
|
71
|
-
if ("column" in expr && !("fn" in expr) && !("bucket" in expr)) return {
|
|
72
|
-
expression: validateSqlIdentifier(expr.column),
|
|
73
|
-
alias: validateSqlIdentifier(expr.as ?? expr.column),
|
|
74
|
-
groupingCandidate: true
|
|
75
|
-
};
|
|
76
|
-
if ("bucket" in expr) return {
|
|
77
|
-
expression: bucketExpr(adapterType, expr.bucket, expr.column),
|
|
78
|
-
alias: validateSqlIdentifier(expr.as),
|
|
79
|
-
groupingCandidate: true
|
|
80
|
-
};
|
|
81
|
-
return {
|
|
82
|
-
expression: aggregateExpression(expr),
|
|
83
|
-
alias: validateSqlIdentifier(expr.as),
|
|
84
|
-
groupingCandidate: false
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
function expandHavingKey(key, expressionByAlias) {
|
|
88
|
-
if (unwrapRawKey(key).isRaw) return key;
|
|
89
|
-
const parsed = parseConditionKey(key);
|
|
90
|
-
return raw(`${expressionByAlias.get(parsed.field) ?? validateSqlIdentifier(parsed.field)} ${parsed.operator}`);
|
|
91
|
-
}
|
|
92
|
-
function expandHaving(having, expressionByAlias) {
|
|
93
|
-
const expandCondition = (condition) => Object.fromEntries(Object.entries(condition).map(([key, value]) => [expandHavingKey(key, expressionByAlias), value]));
|
|
94
|
-
if (Array.isArray(having)) return having.map((andGroup) => andGroup.map((condition) => expandCondition(condition)));
|
|
95
|
-
return expandCondition(having);
|
|
96
|
-
}
|
|
97
|
-
function buildHaving(having, expressionByAlias, startIndex, adapterType) {
|
|
98
|
-
if (!having) return {
|
|
99
|
-
sql: "",
|
|
100
|
-
values: []
|
|
101
|
-
};
|
|
102
|
-
const built = buildWhere(expandHaving(having, expressionByAlias), startIndex, adapterType);
|
|
103
|
-
return {
|
|
104
|
-
sql: built.sql ? built.sql.replace(/^WHERE/, "HAVING") : "",
|
|
105
|
-
values: built.values
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
function buildOrderBy(orderBy) {
|
|
109
|
-
if (!orderBy) return "";
|
|
110
|
-
return `ORDER BY ${(Array.isArray(orderBy) ? orderBy : [orderBy]).map((item) => {
|
|
111
|
-
const [field, direction = "ASC"] = item.trim().split(/\s+/);
|
|
112
|
-
const normalizedDirection = direction.toUpperCase();
|
|
113
|
-
if (!VALID_DIRECTIONS.has(normalizedDirection)) throw new Error(`Invalid aggregate order direction: ${direction}`);
|
|
114
|
-
return `${validateSqlIdentifier(field)} ${normalizedDirection}`;
|
|
115
|
-
}).join(", ")}`;
|
|
116
|
-
}
|
|
117
|
-
function buildAggregate(spec, startIndex = 1, adapterType) {
|
|
118
|
-
const from = validateSqlIdentifier(spec.from);
|
|
119
|
-
if (spec.select.length === 0) throw new Error("AggregateSpec.select must contain at least one expression");
|
|
120
|
-
const expressionByAlias = /* @__PURE__ */ new Map();
|
|
121
|
-
const groupingAliases = [];
|
|
122
|
-
const selectSql = spec.select.map((expr) => {
|
|
123
|
-
const selected = selectExpression(expr, adapterType);
|
|
124
|
-
expressionByAlias.set(selected.alias, selected.expression);
|
|
125
|
-
if (selected.groupingCandidate) groupingAliases.push(selected.alias);
|
|
126
|
-
return `${selected.expression} AS ${selected.alias}`;
|
|
127
|
-
});
|
|
128
|
-
const where = spec.where ? buildWhere(spec.where, startIndex, adapterType) : {
|
|
129
|
-
sql: "",
|
|
130
|
-
values: []
|
|
131
|
-
};
|
|
132
|
-
let nextParamIndex = startIndex + where.values.length;
|
|
133
|
-
const groupByItems = spec.groupBy ?? groupingAliases;
|
|
134
|
-
const groupBySql = groupByItems.length > 0 ? `GROUP BY ${groupByItems.map((item) => expressionByAlias.has(item) ? expressionByAlias.get(item) : validateSqlIdentifier(item)).join(", ")}` : "";
|
|
135
|
-
const having = buildHaving(spec.having, expressionByAlias, nextParamIndex, adapterType);
|
|
136
|
-
nextParamIndex += having.values.length;
|
|
137
|
-
const orderBySql = buildOrderBy(spec.orderBy);
|
|
138
|
-
const pagingValues = [];
|
|
139
|
-
const pagingSql = [];
|
|
140
|
-
if (spec.limit !== void 0) {
|
|
141
|
-
pagingSql.push(`LIMIT ${placeholder(nextParamIndex++)}`);
|
|
142
|
-
pagingValues.push(spec.limit);
|
|
143
|
-
} else if (spec.offset !== void 0 && normalizeAdapter(adapterType) === "sqlite") pagingSql.push("LIMIT -1");
|
|
144
|
-
if (spec.offset !== void 0) {
|
|
145
|
-
pagingSql.push(`OFFSET ${placeholder(nextParamIndex++)}`);
|
|
146
|
-
pagingValues.push(spec.offset);
|
|
147
|
-
}
|
|
148
|
-
return {
|
|
149
|
-
sql: [
|
|
150
|
-
`SELECT ${selectSql.join(", ")}`,
|
|
151
|
-
`FROM ${from}`,
|
|
152
|
-
where.sql,
|
|
153
|
-
groupBySql,
|
|
154
|
-
having.sql,
|
|
155
|
-
orderBySql,
|
|
156
|
-
pagingSql.join(" ")
|
|
157
|
-
].filter(Boolean).join(" "),
|
|
158
|
-
values: [
|
|
159
|
-
...where.values,
|
|
160
|
-
...having.values,
|
|
161
|
-
...pagingValues
|
|
162
|
-
]
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
//#endregion
|
|
166
25
|
//#region src/doctor.ts
|
|
167
26
|
/**
|
|
168
27
|
* Database integrity-check framework.
|
|
@@ -298,48 +157,6 @@ function countValueFromRow(value) {
|
|
|
298
157
|
return "0";
|
|
299
158
|
}
|
|
300
159
|
//#endregion
|
|
301
|
-
//#region src/shared/types.ts
|
|
302
|
-
/**
|
|
303
|
-
* Error thrown when `transaction()` is called on a transaction-scoped interface
|
|
304
|
-
* belonging to an adapter whose engine has no savepoints.
|
|
305
|
-
*
|
|
306
|
-
* DuckDB — and therefore the JSON adapter built on it — does not implement
|
|
307
|
-
* `SAVEPOINT`, so there is no way to re-enter the current transaction. Adapters
|
|
308
|
-
* that can re-enter (PostgreSQL, SQLite) do so under a savepoint and never
|
|
309
|
-
* throw this.
|
|
310
|
-
*
|
|
311
|
-
* The alternative would be to open a second, independent transaction, which is
|
|
312
|
-
* what these adapters used to do; on a shared connection that silently
|
|
313
|
-
* destroyed the enclosing transaction's uncommitted work.
|
|
314
|
-
*
|
|
315
|
-
* @example Ensuring a helper works on every adapter
|
|
316
|
-
* ```typescript
|
|
317
|
-
* // Take the transaction as a parameter rather than opening a nested one.
|
|
318
|
-
* async function recordClick(db: DatabaseInterface, id: string) {
|
|
319
|
-
* await db.update('links', { id }, { clicks: 1 });
|
|
320
|
-
* }
|
|
321
|
-
* await db.transaction(async (tx) => recordClick(tx, id));
|
|
322
|
-
* ```
|
|
323
|
-
*/
|
|
324
|
-
var NestedTransactionError = class extends DatabaseError {
|
|
325
|
-
constructor(message, context) {
|
|
326
|
-
super(message, context);
|
|
327
|
-
this.name = "NestedTransactionError";
|
|
328
|
-
}
|
|
329
|
-
};
|
|
330
|
-
/**
|
|
331
|
-
* Resolves a SchemasOption to its concrete value.
|
|
332
|
-
*
|
|
333
|
-
* Adapters that need schemas (JSON, DuckDB) call this to unwrap the
|
|
334
|
-
* lazy function. Adapters that don't (Postgres, SQLite) simply ignore
|
|
335
|
-
* the `schemas` option without calling this.
|
|
336
|
-
*/
|
|
337
|
-
function resolveSchemas(schemas) {
|
|
338
|
-
if (!schemas) return void 0;
|
|
339
|
-
if (typeof schemas === "function") return schemas();
|
|
340
|
-
return schemas;
|
|
341
|
-
}
|
|
342
|
-
//#endregion
|
|
343
160
|
//#region src/json.ts
|
|
344
161
|
var json_exports = /* @__PURE__ */ __exportAll({
|
|
345
162
|
clearConnectionCache: () => clearConnectionCache,
|
|
@@ -2550,60 +2367,11 @@ async function getDatabase(options = {}) {
|
|
|
2550
2367
|
if (!options.type && (options.url?.startsWith("file:") || options.url === ":memory:")) options.type = "sqlite";
|
|
2551
2368
|
if (options.type === "postgres") return (await Promise.resolve().then(() => postgres_exports)).getDatabase(options);
|
|
2552
2369
|
if (options.type === "pglite") return (await import("./pglite.js")).getDatabase(options);
|
|
2553
|
-
if (options.type === "sqlite") return (await import("./chunks/sqlite-
|
|
2554
|
-
if (options.type === "duckdb") return (await import("./chunks/duckdb-
|
|
2370
|
+
if (options.type === "sqlite") return (await import("./chunks/sqlite-rILMdW7Z.js")).getDatabase(options);
|
|
2371
|
+
if (options.type === "duckdb") return (await import("./chunks/duckdb-c4vdDzPL.js")).getDatabase(options);
|
|
2555
2372
|
if (options.type === "json") return (await Promise.resolve().then(() => json_exports)).getDatabase(options);
|
|
2556
2373
|
throw new Error("Invalid database type");
|
|
2557
2374
|
}
|
|
2558
|
-
/**
|
|
2559
|
-
* Synchronizes a SQL schema definition with a database
|
|
2560
|
-
* Creates tables if they don't exist and adds missing columns to existing tables
|
|
2561
|
-
*
|
|
2562
|
-
* @param options - Object containing database and schema
|
|
2563
|
-
* @param options.db - Database interface to use
|
|
2564
|
-
* @param options.schema - SQL schema definition
|
|
2565
|
-
* @throws Error if db or schema are missing or if the database doesn't support syncSchema
|
|
2566
|
-
*/
|
|
2567
|
-
async function syncSchema(options) {
|
|
2568
|
-
const { db, schema } = options;
|
|
2569
|
-
if (!db || !schema) throw new Error("db and schema are required");
|
|
2570
|
-
if (db.syncSchema) await db.syncSchema(schema);
|
|
2571
|
-
else throw new Error("Database adapter does not support schema synchronization");
|
|
2572
|
-
}
|
|
2573
|
-
/**
|
|
2574
|
-
* Checks if a table exists in the database
|
|
2575
|
-
*
|
|
2576
|
-
* @param db - Database interface to use
|
|
2577
|
-
* @param tableName - Name of the table to check
|
|
2578
|
-
* @returns Promise resolving to boolean indicating if the table exists
|
|
2579
|
-
*/
|
|
2580
|
-
async function tableExists(db, tableName) {
|
|
2581
|
-
return db.tableExists(tableName);
|
|
2582
|
-
}
|
|
2583
|
-
/**
|
|
2584
|
-
* Escapes and formats a value for use in SQL queries
|
|
2585
|
-
*
|
|
2586
|
-
* @param value - Value to escape
|
|
2587
|
-
* @returns String representation of the value safe for SQL use
|
|
2588
|
-
*/
|
|
2589
|
-
function escapeSqlValue(value) {
|
|
2590
|
-
if (value === null) return "NULL";
|
|
2591
|
-
if (value instanceof Date) return `'${value.toISOString()}'`;
|
|
2592
|
-
if (typeof value === "number") return value.toString();
|
|
2593
|
-
if (typeof value === "boolean") return value ? "1" : "0";
|
|
2594
|
-
return `'${String(value).replace(/'/g, "''")}'`;
|
|
2595
|
-
}
|
|
2596
|
-
/**
|
|
2597
|
-
* Validates a column name for use in SQL queries
|
|
2598
|
-
*
|
|
2599
|
-
* @param column - Column name to validate
|
|
2600
|
-
* @returns The validated column name
|
|
2601
|
-
* @throws Error if the column name contains invalid characters
|
|
2602
|
-
*/
|
|
2603
|
-
function validateColumnName(column) {
|
|
2604
|
-
if (typeof column !== "string" || !/^[a-zA-Z0-9_.]+$/.test(column)) throw new Error(`Invalid column name: ${column}`);
|
|
2605
|
-
return column;
|
|
2606
|
-
}
|
|
2607
2375
|
var src_default = {
|
|
2608
2376
|
getDatabase,
|
|
2609
2377
|
syncSchema,
|