@vertz/db 0.2.11 → 0.2.13

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.
@@ -0,0 +1,105 @@
1
+ // src/dialect/postgres.ts
2
+ class PostgresDialect {
3
+ name = "postgres";
4
+ supportsReturning = true;
5
+ supportsArrayOps = true;
6
+ supportsJsonbPath = true;
7
+ param(index) {
8
+ return `$${index}`;
9
+ }
10
+ now() {
11
+ return "NOW()";
12
+ }
13
+ mapColumnType(sqlType, meta) {
14
+ switch (sqlType) {
15
+ case "uuid":
16
+ return "UUID";
17
+ case "text":
18
+ return "TEXT";
19
+ case "integer":
20
+ return "INTEGER";
21
+ case "serial":
22
+ return "SERIAL";
23
+ case "boolean":
24
+ return "BOOLEAN";
25
+ case "timestamp":
26
+ return "TIMESTAMPTZ";
27
+ case "float":
28
+ return "DOUBLE PRECISION";
29
+ case "json":
30
+ return "JSONB";
31
+ case "decimal":
32
+ return meta?.precision ? `NUMERIC(${meta.precision},${meta.scale ?? 0})` : "NUMERIC";
33
+ case "varchar":
34
+ return meta?.length ? `VARCHAR(${meta.length})` : "VARCHAR";
35
+ case "enum":
36
+ return meta?.enumName ?? "TEXT";
37
+ default:
38
+ return "TEXT";
39
+ }
40
+ }
41
+ }
42
+ var defaultPostgresDialect = new PostgresDialect;
43
+
44
+ // src/dialect/sqlite.ts
45
+ class SqliteDialect {
46
+ name = "sqlite";
47
+ supportsReturning = true;
48
+ supportsArrayOps = false;
49
+ supportsJsonbPath = false;
50
+ param(_index) {
51
+ return "?";
52
+ }
53
+ now() {
54
+ return "datetime('now')";
55
+ }
56
+ mapColumnType(sqlType, _meta) {
57
+ switch (sqlType) {
58
+ case "uuid":
59
+ return "TEXT";
60
+ case "boolean":
61
+ return "INTEGER";
62
+ case "timestamp":
63
+ return "TEXT";
64
+ case "json":
65
+ case "jsonb":
66
+ return "TEXT";
67
+ case "decimal":
68
+ return "REAL";
69
+ case "text":
70
+ return "TEXT";
71
+ case "integer":
72
+ return "INTEGER";
73
+ case "bigint":
74
+ return "INTEGER";
75
+ case "serial":
76
+ return "INTEGER";
77
+ default:
78
+ return "TEXT";
79
+ }
80
+ }
81
+ }
82
+ var defaultSqliteDialect = new SqliteDialect;
83
+ // src/sql/casing.ts
84
+ function camelToSnake(str, overrides) {
85
+ if (str.length === 0)
86
+ return str;
87
+ if (overrides && str in overrides) {
88
+ return overrides[str];
89
+ }
90
+ return str.replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2").replace(/([a-z\d])([A-Z])/g, "$1_$2").toLowerCase();
91
+ }
92
+ function snakeToCamel(str, overrides) {
93
+ if (str.length === 0)
94
+ return str;
95
+ if (overrides) {
96
+ for (const [camelKey, snakeVal] of Object.entries(overrides)) {
97
+ if (snakeVal === str) {
98
+ return camelKey;
99
+ }
100
+ }
101
+ }
102
+ return str.replace(/([a-zA-Z\d])_([a-zA-Z])/g, (_, prev, char) => prev + char.toUpperCase());
103
+ }
104
+
105
+ export { PostgresDialect, defaultPostgresDialect, SqliteDialect, defaultSqliteDialect, camelToSnake, snakeToCamel };
@@ -2,7 +2,7 @@ import {
2
2
  BaseSqlAdapter,
3
3
  generateCreateTableSql,
4
4
  generateIndexSql
5
- } from "./chunk-sfmyxz6r.js";
5
+ } from "./chunk-pkv8w501.js";
6
6
 
7
7
  // src/adapters/d1-adapter.ts
8
8
  function createD1Driver(d1) {
@@ -1,7 +1,7 @@
1
1
  // src/id/generators.ts
2
2
  import { createId } from "@paralleldrive/cuid2";
3
- import { v7 as uuidv7 } from "uuid";
4
3
  import { nanoid } from "nanoid";
4
+ import { v7 as uuidv7 } from "uuid";
5
5
  function generateId(strategy) {
6
6
  switch (strategy) {
7
7
  case "cuid":
@@ -99,7 +99,8 @@ function generateIndexSql(schema) {
99
99
  for (const index of schema._indexes) {
100
100
  const indexName = index.name || `idx_${tableName}_${index.columns.join("_")}`;
101
101
  const unique = index.unique ? "UNIQUE " : "";
102
- sqls.push(`CREATE ${unique}INDEX IF NOT EXISTS ${indexName} ON ${tableName} (${index.columns.join(", ")})`);
102
+ const where = index.where ? ` WHERE ${index.where}` : "";
103
+ sqls.push(`CREATE ${unique}INDEX IF NOT EXISTS ${indexName} ON ${tableName} (${index.columns.join(", ")})${where}`);
103
104
  }
104
105
  for (const [colName, colBuilder] of Object.entries(schema._columns)) {
105
106
  const meta = colBuilder._meta;
@@ -1,89 +1,8 @@
1
1
  import {
2
- camelToSnake
3
- } from "./chunk-v2qm94qp.js";
2
+ camelToSnake,
3
+ defaultPostgresDialect
4
+ } from "./chunk-8v70x3hq.js";
4
5
 
5
- // src/dialect/postgres.ts
6
- class PostgresDialect {
7
- name = "postgres";
8
- supportsReturning = true;
9
- supportsArrayOps = true;
10
- supportsJsonbPath = true;
11
- param(index) {
12
- return `$${index}`;
13
- }
14
- now() {
15
- return "NOW()";
16
- }
17
- mapColumnType(sqlType, meta) {
18
- switch (sqlType) {
19
- case "uuid":
20
- return "UUID";
21
- case "text":
22
- return "TEXT";
23
- case "integer":
24
- return "INTEGER";
25
- case "serial":
26
- return "SERIAL";
27
- case "boolean":
28
- return "BOOLEAN";
29
- case "timestamp":
30
- return "TIMESTAMPTZ";
31
- case "float":
32
- return "DOUBLE PRECISION";
33
- case "json":
34
- return "JSONB";
35
- case "decimal":
36
- return meta?.precision ? `NUMERIC(${meta.precision},${meta.scale ?? 0})` : "NUMERIC";
37
- case "varchar":
38
- return meta?.length ? `VARCHAR(${meta.length})` : "VARCHAR";
39
- case "enum":
40
- return meta?.enumName ?? "TEXT";
41
- default:
42
- return "TEXT";
43
- }
44
- }
45
- }
46
- var defaultPostgresDialect = new PostgresDialect;
47
-
48
- // src/dialect/sqlite.ts
49
- class SqliteDialect {
50
- name = "sqlite";
51
- supportsReturning = true;
52
- supportsArrayOps = false;
53
- supportsJsonbPath = false;
54
- param(_index) {
55
- return "?";
56
- }
57
- now() {
58
- return "datetime('now')";
59
- }
60
- mapColumnType(sqlType, _meta) {
61
- switch (sqlType) {
62
- case "uuid":
63
- return "TEXT";
64
- case "boolean":
65
- return "INTEGER";
66
- case "timestamp":
67
- return "TEXT";
68
- case "json":
69
- case "jsonb":
70
- return "TEXT";
71
- case "decimal":
72
- return "REAL";
73
- case "text":
74
- return "TEXT";
75
- case "integer":
76
- return "INTEGER";
77
- case "bigint":
78
- return "INTEGER";
79
- case "serial":
80
- return "INTEGER";
81
- default:
82
- return "TEXT";
83
- }
84
- }
85
- }
86
- var defaultSqliteDialect = new SqliteDialect;
87
6
  // src/sql/where.ts
88
7
  var OPERATOR_KEYS = new Set([
89
8
  "eq",
@@ -520,4 +439,4 @@ function buildUpdate(options, dialect = options.dialect ?? defaultPostgresDialec
520
439
  return { sql, params: allParams };
521
440
  }
522
441
 
523
- export { PostgresDialect, defaultPostgresDialect, SqliteDialect, defaultSqliteDialect, buildWhere, buildDelete, buildInsert, buildSelect, buildUpdate };
442
+ export { buildWhere, buildDelete, buildInsert, buildSelect, buildUpdate };
package/dist/sql/index.js CHANGED
@@ -4,11 +4,11 @@ import {
4
4
  buildSelect,
5
5
  buildUpdate,
6
6
  buildWhere
7
- } from "../shared/chunk-0e1vy9qd.js";
7
+ } from "../shared/chunk-pxjcpnpx.js";
8
8
  import {
9
9
  camelToSnake,
10
10
  snakeToCamel
11
- } from "../shared/chunk-v2qm94qp.js";
11
+ } from "../shared/chunk-8v70x3hq.js";
12
12
  // src/sql/tagged.ts
13
13
  function isSqlFragment(value) {
14
14
  return typeof value === "object" && value !== null && "_tag" in value && value._tag === "SqlFragment";
@@ -32,11 +32,6 @@ interface ColumnMetadata {
32
32
  readonly _annotations: Record<string, true>;
33
33
  readonly isReadOnly: boolean;
34
34
  readonly isAutoUpdate: boolean;
35
- readonly isTenant: boolean;
36
- readonly references: {
37
- readonly table: string;
38
- readonly column: string;
39
- } | null;
40
35
  readonly check: string | null;
41
36
  readonly defaultValue?: unknown;
42
37
  readonly format?: string;
@@ -87,18 +82,15 @@ interface ColumnBuilder<
87
82
  check(sql: string): ColumnBuilder<TType, Omit<TMeta, "check"> & {
88
83
  readonly check: string;
89
84
  }>;
90
- references(table: string, column?: string): ColumnBuilder<TType, Omit<TMeta, "references"> & {
91
- readonly references: {
92
- readonly table: string;
93
- readonly column: string;
94
- };
95
- }>;
96
85
  }
97
86
  type InferColumnType<C> = C extends ColumnBuilder<infer T, ColumnMetadata> ? T : never;
87
+ type IndexType = "btree" | "hash" | "gin" | "gist" | "brin";
98
88
  interface IndexDef {
99
89
  readonly columns: readonly string[];
100
90
  readonly name?: string;
101
91
  readonly unique?: boolean;
92
+ readonly type?: IndexType;
93
+ readonly where?: string;
102
94
  }
103
95
  /** A record of column builders -- the shape passed to d.table(). */
104
96
  type ColumnRecord = Record<string, ColumnBuilder<unknown, ColumnMetadata>>;
@@ -2,7 +2,7 @@ import {
2
2
  BaseSqlAdapter,
3
3
  generateCreateTableSql,
4
4
  generateIndexSql
5
- } from "../shared/chunk-sfmyxz6r.js";
5
+ } from "../shared/chunk-pkv8w501.js";
6
6
  import {
7
7
  __commonJS,
8
8
  __require
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vertz/db",
3
- "version": "0.2.11",
3
+ "version": "0.2.13",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Database layer for Vertz — typed queries, migrations, codegen",
@@ -81,8 +81,8 @@
81
81
  "node": ">=22"
82
82
  },
83
83
  "dependencies": {
84
- "@vertz/errors": "^0.2.11",
85
- "@vertz/schema": "^0.2.11",
84
+ "@vertz/errors": "^0.2.12",
85
+ "@vertz/schema": "^0.2.12",
86
86
  "@paralleldrive/cuid2": "^3.3.0",
87
87
  "nanoid": "^5.1.5",
88
88
  "uuid": "^13.0.0"
@@ -1,302 +0,0 @@
1
- import {
2
- snakeToCamel
3
- } from "./chunk-v2qm94qp.js";
4
-
5
- // src/errors/db-error.ts
6
- class DbError extends Error {
7
- pgCode;
8
- table;
9
- query;
10
- constructor(message) {
11
- super(message);
12
- this.name = new.target.name;
13
- }
14
- toJSON() {
15
- const json = {
16
- error: this.name,
17
- code: this.code,
18
- message: this.message
19
- };
20
- if (this.table !== undefined) {
21
- json.table = this.table;
22
- }
23
- return json;
24
- }
25
- }
26
-
27
- class UniqueConstraintError extends DbError {
28
- code = "UNIQUE_VIOLATION";
29
- pgCode = "23505";
30
- table;
31
- query;
32
- column;
33
- value;
34
- constructor(options) {
35
- super(`Unique constraint violated on ${options.table}.${options.column}${options.value !== undefined ? ` (value: ${options.value})` : ""}`);
36
- this.table = options.table;
37
- this.column = options.column;
38
- this.value = options.value;
39
- this.query = options.query;
40
- }
41
- toJSON() {
42
- return {
43
- ...super.toJSON(),
44
- table: this.table,
45
- column: this.column
46
- };
47
- }
48
- }
49
-
50
- class ForeignKeyError extends DbError {
51
- code = "FOREIGN_KEY_VIOLATION";
52
- pgCode = "23503";
53
- table;
54
- query;
55
- constraint;
56
- detail;
57
- constructor(options) {
58
- super(`Foreign key constraint "${options.constraint}" violated on table ${options.table}`);
59
- this.table = options.table;
60
- this.constraint = options.constraint;
61
- this.detail = options.detail;
62
- this.query = options.query;
63
- }
64
- toJSON() {
65
- return {
66
- ...super.toJSON(),
67
- table: this.table
68
- };
69
- }
70
- }
71
-
72
- class NotNullError extends DbError {
73
- code = "NOT_NULL_VIOLATION";
74
- pgCode = "23502";
75
- table;
76
- query;
77
- column;
78
- constructor(options) {
79
- super(`Not-null constraint violated on ${options.table}.${options.column}`);
80
- this.table = options.table;
81
- this.column = options.column;
82
- this.query = options.query;
83
- }
84
- toJSON() {
85
- return {
86
- ...super.toJSON(),
87
- table: this.table,
88
- column: this.column
89
- };
90
- }
91
- }
92
-
93
- class CheckConstraintError extends DbError {
94
- code = "CHECK_VIOLATION";
95
- pgCode = "23514";
96
- table;
97
- query;
98
- constraint;
99
- constructor(options) {
100
- super(`Check constraint "${options.constraint}" violated on table ${options.table}`);
101
- this.table = options.table;
102
- this.constraint = options.constraint;
103
- this.query = options.query;
104
- }
105
- toJSON() {
106
- return {
107
- ...super.toJSON(),
108
- table: this.table
109
- };
110
- }
111
- }
112
-
113
- class NotFoundError extends DbError {
114
- code = "NotFound";
115
- table;
116
- query;
117
- constructor(table, query) {
118
- super(`Record not found in table ${table}`);
119
- this.table = table;
120
- this.query = query;
121
- }
122
- toJSON() {
123
- return {
124
- ...super.toJSON(),
125
- table: this.table
126
- };
127
- }
128
- }
129
-
130
- class ConnectionError extends DbError {
131
- code = "CONNECTION_ERROR";
132
- constructor(message) {
133
- super(`Database connection error: ${message}`);
134
- }
135
- }
136
-
137
- class ConnectionPoolExhaustedError extends ConnectionError {
138
- code = "POOL_EXHAUSTED";
139
- constructor(poolSize) {
140
- super(`Connection pool exhausted (max: ${poolSize})`);
141
- this.name = "ConnectionPoolExhaustedError";
142
- }
143
- }
144
-
145
- // src/errors/pg-parser.ts
146
- function extractKeyDetail(detail) {
147
- if (!detail)
148
- return null;
149
- const match = detail.match(/^Key \(([^)]+)\)=\(([^)]*)\)/);
150
- if (!match)
151
- return null;
152
- return { column: match[1], value: match[2] };
153
- }
154
- function extractNotNullColumn(message) {
155
- const match = message.match(/null value in column "([^"]+)"/);
156
- return match ? match[1] : null;
157
- }
158
- function extractCheckConstraint(message) {
159
- const match = message.match(/violates check constraint "([^"]+)"/);
160
- return match ? match[1] : null;
161
- }
162
- function isConnectionErrorCode(code) {
163
- return code.startsWith("08");
164
- }
165
-
166
- class UnknownDbError extends DbError {
167
- code;
168
- table;
169
- query;
170
- constructor(code, message, table, query) {
171
- super(message);
172
- this.code = code;
173
- this.table = table;
174
- this.query = query;
175
- }
176
- }
177
- function parsePgError(pgError, query) {
178
- const { code, message, table, column, constraint, detail } = pgError;
179
- switch (code) {
180
- case "23505": {
181
- const keyDetail = extractKeyDetail(detail);
182
- return new UniqueConstraintError({
183
- table: table ?? "unknown",
184
- column: column ?? keyDetail?.column ?? "unknown",
185
- value: keyDetail?.value,
186
- query
187
- });
188
- }
189
- case "23503": {
190
- return new ForeignKeyError({
191
- table: table ?? "unknown",
192
- constraint: constraint ?? "unknown",
193
- detail,
194
- query
195
- });
196
- }
197
- case "23502": {
198
- const extractedColumn = extractNotNullColumn(message);
199
- return new NotNullError({
200
- table: table ?? "unknown",
201
- column: column ?? extractedColumn ?? "unknown",
202
- query
203
- });
204
- }
205
- case "23514": {
206
- const extractedConstraint = extractCheckConstraint(message);
207
- return new CheckConstraintError({
208
- table: table ?? "unknown",
209
- constraint: constraint ?? extractedConstraint ?? "unknown",
210
- query
211
- });
212
- }
213
- default: {
214
- if (isConnectionErrorCode(code)) {
215
- return new ConnectionError(message);
216
- }
217
- return new UnknownDbError(code, message, table, query);
218
- }
219
- }
220
- }
221
-
222
- // src/query/executor.ts
223
- function isPgError(error) {
224
- return typeof error === "object" && error !== null && "code" in error && typeof error.code === "string" && "message" in error && typeof error.message === "string";
225
- }
226
- async function executeQuery(queryFn, sql, params) {
227
- try {
228
- return await queryFn(sql, params);
229
- } catch (error) {
230
- if (isPgError(error)) {
231
- throw parsePgError(error, sql);
232
- }
233
- throw error;
234
- }
235
- }
236
-
237
- // src/query/helpers.ts
238
- function getColumnNames(table) {
239
- return Object.keys(table._columns);
240
- }
241
- function getDefaultColumns(table) {
242
- return getColumnsWithoutAnnotations(table, []);
243
- }
244
- function getColumnsWithoutAnnotations(table, annotations) {
245
- const allAnnotations = annotations.includes("hidden") ? annotations : [...annotations, "hidden"];
246
- return Object.keys(table._columns).filter((key) => {
247
- const col = table._columns[key];
248
- if (!col)
249
- return true;
250
- const colAnnotations = col._meta._annotations;
251
- return !allAnnotations.some((f) => colAnnotations[f]);
252
- });
253
- }
254
- function resolveSelectColumns(table, select) {
255
- if (!select) {
256
- return getDefaultColumns(table);
257
- }
258
- if ("not" in select && select.not !== undefined) {
259
- const notValue = select.not;
260
- const flags = Array.isArray(notValue) ? notValue : [notValue];
261
- return getColumnsWithoutAnnotations(table, flags);
262
- }
263
- return Object.keys(select).filter((k) => select[k] === true);
264
- }
265
- function getTimestampColumns(table) {
266
- return Object.keys(table._columns).filter((key) => {
267
- const col = table._columns[key];
268
- return col ? col._meta.sqlType === "timestamp with time zone" : false;
269
- });
270
- }
271
- function getPrimaryKeyColumns(table) {
272
- return Object.keys(table._columns).filter((key) => {
273
- const col = table._columns[key];
274
- return col ? col._meta.primary : false;
275
- });
276
- }
277
- function getReadOnlyColumns(table) {
278
- return Object.keys(table._columns).filter((key) => {
279
- const col = table._columns[key];
280
- return col ? col._meta.isReadOnly : false;
281
- });
282
- }
283
- function getAutoUpdateColumns(table) {
284
- return Object.keys(table._columns).filter((key) => {
285
- const col = table._columns[key];
286
- return col ? col._meta.isAutoUpdate : false;
287
- });
288
- }
289
-
290
- // src/query/row-mapper.ts
291
- function mapRow(row) {
292
- const result = {};
293
- for (const key of Object.keys(row)) {
294
- result[snakeToCamel(key)] = row[key];
295
- }
296
- return result;
297
- }
298
- function mapRows(rows) {
299
- return rows.map((row) => mapRow(row));
300
- }
301
-
302
- export { DbError, UniqueConstraintError, ForeignKeyError, NotNullError, CheckConstraintError, NotFoundError, ConnectionError, ConnectionPoolExhaustedError, parsePgError, executeQuery, getColumnNames, getDefaultColumns, getColumnsWithoutAnnotations, resolveSelectColumns, getTimestampColumns, getPrimaryKeyColumns, getReadOnlyColumns, getAutoUpdateColumns, mapRow, mapRows };
@@ -1,23 +0,0 @@
1
- // src/sql/casing.ts
2
- function camelToSnake(str, overrides) {
3
- if (str.length === 0)
4
- return str;
5
- if (overrides && str in overrides) {
6
- return overrides[str];
7
- }
8
- return str.replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2").replace(/([a-z\d])([A-Z])/g, "$1_$2").toLowerCase();
9
- }
10
- function snakeToCamel(str, overrides) {
11
- if (str.length === 0)
12
- return str;
13
- if (overrides) {
14
- for (const [camelKey, snakeVal] of Object.entries(overrides)) {
15
- if (snakeVal === str) {
16
- return camelKey;
17
- }
18
- }
19
- }
20
- return str.replace(/([a-zA-Z\d])_([a-zA-Z])/g, (_, prev, char) => prev + char.toUpperCase());
21
- }
22
-
23
- export { camelToSnake, snakeToCamel };