durcno 1.0.0-alpha.13 → 1.0.0-alpha.14

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 CHANGED
@@ -26,6 +26,7 @@
26
26
  - **🔌 Multiple Drivers** — Support for `pg`, `postgres`, `bun`, and `pglite` drivers.
27
27
  - **🛡️ Zod Integration** — Built-in Zod validators for schema validation and type inference.
28
28
  - **🌍 PostGIS Support** — First-class geographic column types for spatial queries.
29
+ - **🔍 pgvector Support** — Vector similarity search with type-safe distance functions and indexes.
29
30
 
30
31
  ## Setup
31
32
 
package/dist/bin.cjs CHANGED
@@ -9411,7 +9411,9 @@ function generateMigration(prev, curr, direction, renamedTables = {}, renamedCol
9411
9411
  }
9412
9412
  statements.push(tableBuilder.join("\n"));
9413
9413
  for (const idx of Object.values(currTable.indexes)) {
9414
- const cols = idx.columns.map((c) => `"${c}"`).join(", ");
9414
+ const cols = idx.columns.map(
9415
+ (c) => c.opclass ? `["${c.name}", "${c.opclass}"]` : `"${c.name}"`
9416
+ ).join(", ");
9415
9417
  let indexStmt = `ddl.createIndex("${idx.name}").on("${currTable.schema}", "${currTable.name}", [${cols}]).using("${idx.type}")`;
9416
9418
  if (idx.unique) indexStmt += ".unique()";
9417
9419
  statements.push(indexStmt);
@@ -9531,7 +9533,9 @@ function generateAlterTableStmts(prevTable, currTable, tableName, curr, statemen
9531
9533
  for (const idxName in currTable.indexes) {
9532
9534
  if (!prevTable.indexes[idxName]) {
9533
9535
  const idx = currTable.indexes[idxName];
9534
- const cols = idx.columns.map((c) => `"${c}"`).join(", ");
9536
+ const cols = idx.columns.map(
9537
+ (c) => c.opclass ? `["${c.name}", "${c.opclass}"]` : `"${c.name}"`
9538
+ ).join(", ");
9535
9539
  let indexStmt = `ddl.createIndex("${idx.name}").on("${currTable.schema}", "${currTable.name}", [${cols}]).using("${idx.type}")`;
9536
9540
  if (idx.unique) indexStmt += ".unique()";
9537
9541
  statements.push(indexStmt);
@@ -10451,7 +10455,7 @@ async function status(options) {
10451
10455
  }
10452
10456
 
10453
10457
  // src/cli/index.ts
10454
- program.version("1.0.0-alpha.12");
10458
+ program.version("1.0.0-alpha.13");
10455
10459
  var Options = {
10456
10460
  config: ["--config <path>", "Path to the config file"]
10457
10461
  };
@@ -1,6 +1,6 @@
1
1
  import { CheckExpression } from "../constraints/check.mjs";
2
2
  import { entityType } from "../symbols.mjs";
3
- import { StdTable, StdTableColumn } from "../table.mjs";
3
+ import { AnyColumn, StdTable, StdTableColumn } from "../table.mjs";
4
4
  import { AnyFilter } from "../filters/index.mjs";
5
5
  import { Arg } from "../query-builders/pre.mjs";
6
6
  import { Query, QueryContext } from "../query-builders/query.mjs";
@@ -308,6 +308,19 @@ declare abstract class Column<TConfig extends ColumnConfig, TColVal, TPgType ext
308
308
  * @returns an `Arg` instance with the type of this column
309
309
  */
310
310
  arg(): Arg<this["ValType"]>;
311
+ /**
312
+ * Applies an operator class to this column for index creation.
313
+ *
314
+ * @param opclass - The operator class to use (e.g., 'vector_l2_ops').
315
+ * @returns an IndexOn instance wrapping this column and its opclass.
316
+ */
317
+ opclass(opclass: string): IndexOn<this>;
318
+ }
319
+ declare class IndexOn<TCol extends AnyColumn = AnyColumn> {
320
+ readonly column: StdTableColumn<TCol>;
321
+ readonly opclassStr: string;
322
+ static readonly [entityType] = "IndexOn";
323
+ constructor(column: StdTableColumn<TCol>, opclassStr: string);
311
324
  }
312
325
  //#endregion
313
- export { Column, ColumnConfig, Dimension, GeneratedAlways, GeneratedByDefault, OnDeleteAction, array, notNull, primaryKey, tuple, unique };
326
+ export { Column, ColumnConfig, Dimension, GeneratedAlways, GeneratedByDefault, IndexOn, OnDeleteAction, Tuple, array, notNull, primaryKey, tuple, unique };
@@ -390,6 +390,22 @@ var Column = class {
390
390
  arg() {
391
391
  return new Arg(this.toDriver.bind(this), this.sqlCast);
392
392
  }
393
+ /**
394
+ * Applies an operator class to this column for index creation.
395
+ *
396
+ * @param opclass - The operator class to use (e.g., 'vector_l2_ops').
397
+ * @returns an IndexOn instance wrapping this column and its opclass.
398
+ */
399
+ opclass(opclass) {
400
+ return new IndexOn(this, opclass);
401
+ }
402
+ };
403
+ var IndexOn = class {
404
+ static [entityType] = "IndexOn";
405
+ constructor(column, opclassStr) {
406
+ this.column = column;
407
+ this.opclassStr = opclassStr;
408
+ }
393
409
  };
394
410
  //#endregion
395
- export { Column, Dimension, array, identity, notNull, primaryKey, tuple, unique };
411
+ export { Column, Dimension, IndexOn, array, identity, notNull, primaryKey, tuple, unique };
@@ -0,0 +1,122 @@
1
+ import { Column, ColumnConfig, Tuple } from "../common.mjs";
2
+ import { Sql } from "../../sql.mjs";
3
+ import * as z from "zod";
4
+
5
+ //#region src/columns/pgvector/index.d.ts
6
+ type VectorConfig = ColumnConfig & {
7
+ dimensions?: number;
8
+ };
9
+ /** Derives a fixed-length numeric tuple when `dimensions` is a number literal, otherwise `number[]`. */
10
+ type VectorValue<TConfig extends VectorConfig> = TConfig extends {
11
+ dimensions: infer D extends number;
12
+ } ? number extends D ? number[] : Tuple<number, D> : number[];
13
+ declare class VectorColumn<TConfig extends VectorConfig> extends Column<TConfig, VectorValue<TConfig>, "numeric"> {
14
+ #private;
15
+ static readonly id = "Column.Vector";
16
+ constructor(config: TConfig);
17
+ get sqlTypeScalar(): string;
18
+ get sqlCastScalar(): string;
19
+ get zodTypeScaler(): TConfig["dimensions"] extends number ? z.ZodTuple<Tuple<z.ZodNumber, TConfig["dimensions"]>, null> : z.ZodArray<z.ZodNumber>;
20
+ toDriverScalar(value: VectorValue<TConfig> | Sql | null): string | null;
21
+ toSQLScalar(value: VectorValue<TConfig> | Sql | null): string;
22
+ fromDriverScalar(value: unknown): VectorValue<TConfig> | null;
23
+ }
24
+ /**
25
+ * Creates a `vector` column. PostgreSQL pgvector dense vector type, maps to `number[]`.
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * vector({ dimensions: 1536, notNull }) // vector(1536) NOT NULL
30
+ * ```
31
+ *
32
+ * @param config.dimensions - Fixed vector dimension length
33
+ */
34
+ declare function vector<const TConfig extends VectorConfig>(config?: TConfig): VectorColumn<TConfig>;
35
+ type HalfvecConfig = ColumnConfig & {
36
+ dimensions?: number;
37
+ };
38
+ /** Derives a fixed-length numeric tuple when `dimensions` is a number literal, otherwise `number[]`. */
39
+ type HalfvecValue<TConfig extends HalfvecConfig> = TConfig extends {
40
+ dimensions: infer D extends number;
41
+ } ? number extends D ? number[] : Tuple<number, D> : number[];
42
+ declare class HalfvecColumn<TConfig extends HalfvecConfig> extends Column<TConfig, HalfvecValue<TConfig>, "numeric"> {
43
+ #private;
44
+ static readonly id = "Column.Halfvec";
45
+ constructor(config: TConfig);
46
+ get sqlTypeScalar(): string;
47
+ get sqlCastScalar(): string;
48
+ get zodTypeScaler(): TConfig["dimensions"] extends number ? z.ZodTuple<Tuple<z.ZodNumber, TConfig["dimensions"]>, null> : z.ZodArray<z.ZodNumber>;
49
+ toDriverScalar(value: HalfvecValue<TConfig> | Sql | null): string | null;
50
+ toSQLScalar(value: HalfvecValue<TConfig> | Sql | null): string;
51
+ fromDriverScalar(value: unknown): HalfvecValue<TConfig> | null;
52
+ }
53
+ /**
54
+ * Creates a `halfvec` column. PostgreSQL pgvector half precision vector type, maps to `number[]`.
55
+ *
56
+ * @example
57
+ * ```ts
58
+ * halfvec({ dimensions: 1536, notNull }) // halfvec(1536) NOT NULL
59
+ * ```
60
+ *
61
+ * @param config.dimensions - Fixed vector dimension length
62
+ */
63
+ declare function halfvec<const TConfig extends HalfvecConfig>(config?: TConfig): HalfvecColumn<TConfig>;
64
+ type SparsevecConfig = ColumnConfig & {
65
+ dimensions?: number;
66
+ };
67
+ declare class SparsevecColumn<TConfig extends SparsevecConfig> extends Column<TConfig, string, "string"> {
68
+ #private;
69
+ static readonly id = "Column.Sparsevec";
70
+ constructor(config: TConfig);
71
+ get sqlTypeScalar(): string;
72
+ get sqlCastScalar(): string;
73
+ get zodTypeScaler(): z.ZodString;
74
+ toDriverScalar(value: string | Sql | null): string | null;
75
+ toSQLScalar(value: string | Sql | null): string;
76
+ fromDriverScalar(value: string | null): string | null;
77
+ }
78
+ /**
79
+ * Creates a `sparsevec` column. PostgreSQL pgvector sparse vector type, maps to `string`.
80
+ *
81
+ * @example
82
+ * ```ts
83
+ * sparsevec({ dimensions: 1000, notNull }) // sparsevec(1000) NOT NULL
84
+ * ```
85
+ *
86
+ * @param config.dimensions - Fixed vector dimension length
87
+ */
88
+ declare function sparsevec<const TConfig extends SparsevecConfig>(config?: TConfig): SparsevecColumn<TConfig>;
89
+ type BitConfig = ColumnConfig & {
90
+ length?: number;
91
+ };
92
+ declare class BitColumn<TConfig extends BitConfig> extends Column<TConfig, string, "string"> {
93
+ #private;
94
+ static readonly id = "Column.Bit";
95
+ constructor(config: TConfig);
96
+ get sqlTypeScalar(): string;
97
+ get sqlCastScalar(): string;
98
+ get zodTypeScaler(): z.ZodString;
99
+ toDriverScalar(value: string | Sql | null): string | null;
100
+ toSQLScalar(value: string | Sql | null): string;
101
+ fromDriverScalar(value: string | null): string | null;
102
+ }
103
+ /**
104
+ * Creates a `bit` column. PostgreSQL bit string type, maps to `string`.
105
+ *
106
+ * @example
107
+ * ```ts
108
+ * bit({ length: 16, notNull }) // bit(16) NOT NULL
109
+ * ```
110
+ *
111
+ * @param config.length - Fixed bit string length
112
+ */
113
+ declare function bit<const TConfig extends BitConfig>(config?: TConfig): BitColumn<TConfig>;
114
+ /** All pgvector column constructors grouped as a single object. */
115
+ declare const pgvector: {
116
+ vector: typeof vector;
117
+ halfvec: typeof halfvec;
118
+ sparsevec: typeof sparsevec;
119
+ bit: typeof bit;
120
+ };
121
+ //#endregion
122
+ export { pgvector };
@@ -0,0 +1,195 @@
1
+ import { Column } from "../common.mjs";
2
+ import { Sql } from "../../sql.mjs";
3
+ import * as z from "zod";
4
+ //#region src/columns/pgvector/index.ts
5
+ var VectorColumn = class extends Column {
6
+ static id = "Column.Vector";
7
+ #dimensions;
8
+ constructor(config) {
9
+ super(config);
10
+ this.#dimensions = config.dimensions;
11
+ }
12
+ get sqlTypeScalar() {
13
+ return this.#dimensions ? `vector(${this.#dimensions})` : "vector";
14
+ }
15
+ get sqlCastScalar() {
16
+ return this.sqlTypeScalar;
17
+ }
18
+ get zodTypeScaler() {
19
+ if (this.#dimensions === void 0) return z.array(z.number());
20
+ return z.tuple(Array.from({ length: this.#dimensions }, () => z.number()));
21
+ }
22
+ toDriverScalar(value) {
23
+ if (value === null) return null;
24
+ return value instanceof Sql ? value.string : `[${value.join(",")}]`;
25
+ }
26
+ toSQLScalar(value) {
27
+ if (value === null) return "NULL";
28
+ return value instanceof Sql ? value.string : `'[${value.join(",")}]'`;
29
+ }
30
+ fromDriverScalar(value) {
31
+ if (value === null) return null;
32
+ if (Array.isArray(value)) return value;
33
+ if (typeof value === "string") try {
34
+ return JSON.parse(value);
35
+ } catch {
36
+ return null;
37
+ }
38
+ return null;
39
+ }
40
+ };
41
+ /**
42
+ * Creates a `vector` column. PostgreSQL pgvector dense vector type, maps to `number[]`.
43
+ *
44
+ * @example
45
+ * ```ts
46
+ * vector({ dimensions: 1536, notNull }) // vector(1536) NOT NULL
47
+ * ```
48
+ *
49
+ * @param config.dimensions - Fixed vector dimension length
50
+ */
51
+ function vector(config = {}) {
52
+ return new VectorColumn(config);
53
+ }
54
+ var HalfvecColumn = class extends Column {
55
+ static id = "Column.Halfvec";
56
+ #dimensions;
57
+ constructor(config) {
58
+ super(config);
59
+ this.#dimensions = config.dimensions;
60
+ }
61
+ get sqlTypeScalar() {
62
+ return this.#dimensions ? `halfvec(${this.#dimensions})` : "halfvec";
63
+ }
64
+ get sqlCastScalar() {
65
+ return this.sqlTypeScalar;
66
+ }
67
+ get zodTypeScaler() {
68
+ if (this.#dimensions === void 0) return z.array(z.number());
69
+ return z.tuple(Array.from({ length: this.#dimensions }, () => z.number()));
70
+ }
71
+ toDriverScalar(value) {
72
+ if (value === null) return null;
73
+ return value instanceof Sql ? value.string : `[${value.join(",")}]`;
74
+ }
75
+ toSQLScalar(value) {
76
+ if (value === null) return "NULL";
77
+ return value instanceof Sql ? value.string : `'[${value.join(",")}]'`;
78
+ }
79
+ fromDriverScalar(value) {
80
+ if (value === null) return null;
81
+ if (Array.isArray(value)) return value;
82
+ if (typeof value === "string") try {
83
+ return JSON.parse(value);
84
+ } catch {
85
+ return null;
86
+ }
87
+ return null;
88
+ }
89
+ };
90
+ /**
91
+ * Creates a `halfvec` column. PostgreSQL pgvector half precision vector type, maps to `number[]`.
92
+ *
93
+ * @example
94
+ * ```ts
95
+ * halfvec({ dimensions: 1536, notNull }) // halfvec(1536) NOT NULL
96
+ * ```
97
+ *
98
+ * @param config.dimensions - Fixed vector dimension length
99
+ */
100
+ function halfvec(config = {}) {
101
+ return new HalfvecColumn(config);
102
+ }
103
+ var SparsevecColumn = class extends Column {
104
+ static id = "Column.Sparsevec";
105
+ #dimensions;
106
+ constructor(config) {
107
+ super(config);
108
+ this.#dimensions = config.dimensions;
109
+ }
110
+ get sqlTypeScalar() {
111
+ return this.#dimensions ? `sparsevec(${this.#dimensions})` : "sparsevec";
112
+ }
113
+ get sqlCastScalar() {
114
+ return this.sqlTypeScalar;
115
+ }
116
+ get zodTypeScaler() {
117
+ return z.string();
118
+ }
119
+ toDriverScalar(value) {
120
+ if (value === null) return null;
121
+ return value instanceof Sql ? value.string : value;
122
+ }
123
+ toSQLScalar(value) {
124
+ if (value === null) return "NULL";
125
+ return value instanceof Sql ? value.string : `'${value.replace(/'/g, "''")}'`;
126
+ }
127
+ fromDriverScalar(value) {
128
+ return value;
129
+ }
130
+ };
131
+ /**
132
+ * Creates a `sparsevec` column. PostgreSQL pgvector sparse vector type, maps to `string`.
133
+ *
134
+ * @example
135
+ * ```ts
136
+ * sparsevec({ dimensions: 1000, notNull }) // sparsevec(1000) NOT NULL
137
+ * ```
138
+ *
139
+ * @param config.dimensions - Fixed vector dimension length
140
+ */
141
+ function sparsevec(config = {}) {
142
+ return new SparsevecColumn(config);
143
+ }
144
+ var BitColumn = class extends Column {
145
+ static id = "Column.Bit";
146
+ #length;
147
+ constructor(config) {
148
+ super(config);
149
+ this.#length = config.length;
150
+ }
151
+ get sqlTypeScalar() {
152
+ return this.#length ? `bit(${this.#length})` : "bit";
153
+ }
154
+ get sqlCastScalar() {
155
+ return this.sqlTypeScalar;
156
+ }
157
+ get zodTypeScaler() {
158
+ let base = z.string().regex(/^[01]+$/);
159
+ if (this.#length !== void 0) base = base.length(this.#length);
160
+ return base;
161
+ }
162
+ toDriverScalar(value) {
163
+ if (value === null) return null;
164
+ return value instanceof Sql ? value.string : value;
165
+ }
166
+ toSQLScalar(value) {
167
+ if (value === null) return "NULL";
168
+ return value instanceof Sql ? value.string : `B'${value}'`;
169
+ }
170
+ fromDriverScalar(value) {
171
+ return value;
172
+ }
173
+ };
174
+ /**
175
+ * Creates a `bit` column. PostgreSQL bit string type, maps to `string`.
176
+ *
177
+ * @example
178
+ * ```ts
179
+ * bit({ length: 16, notNull }) // bit(16) NOT NULL
180
+ * ```
181
+ *
182
+ * @param config.length - Fixed bit string length
183
+ */
184
+ function bit(config = {}) {
185
+ return new BitColumn(config);
186
+ }
187
+ /** All pgvector column constructors grouped as a single object. */
188
+ const pgvector = {
189
+ vector,
190
+ halfvec,
191
+ sparsevec,
192
+ bit
193
+ };
194
+ //#endregion
195
+ export { pgvector };
@@ -59,7 +59,7 @@ var BunPool = class extends $Pool {
59
59
  #pool;
60
60
  constructor(options) {
61
61
  super(options);
62
- this.#pool = new Bun.SQL(getUrlFromDbCredentials(options.dbCredentials), { max: options.pool?.max ?? 10 });
62
+ this.#pool = new Bun.SQL(getUrlFromDbCredentials(options.dbCredentials), { max: options.pool?.max ?? 5 });
63
63
  this.query = this.#pool.unsafe.bind(this.#pool);
64
64
  }
65
65
  async connect() {
@@ -66,7 +66,7 @@ var PgPool = class extends $Pool {
66
66
  super(options);
67
67
  this.#pool = new Pool({
68
68
  connectionString: getUrlFromDbCredentials(options.dbCredentials),
69
- max: options.pool?.max ?? 10
69
+ max: options.pool?.max ?? 5
70
70
  });
71
71
  this.query = this.#pool.query.bind(this.#pool);
72
72
  }
@@ -60,7 +60,7 @@ var PostgresPool = class extends $Pool {
60
60
  #sql;
61
61
  constructor(options) {
62
62
  super(options);
63
- this.#sql = postgresLib(getUrlFromDbCredentials(options.dbCredentials), { max: options.pool?.max ?? 10 });
63
+ this.#sql = postgresLib(getUrlFromDbCredentials(options.dbCredentials), { max: options.pool?.max ?? 5 });
64
64
  this.query = this.#sql.unsafe.bind(this.#sql);
65
65
  }
66
66
  async connect() {}
@@ -0,0 +1,33 @@
1
+ import { AnyColumn } from "../table.mjs";
2
+ import { SqlFn } from "./index.mjs";
3
+ import { Arg, IsArg } from "../query-builders/pre.mjs";
4
+ import { Query, QueryContext } from "../query-builders/query.mjs";
5
+
6
+ //#region src/functions/pgvector.d.ts
7
+ declare class DistanceFn<TCol extends AnyColumn, TOp extends string = string, TVal extends TCol["ValType"] | Arg<TCol["ValType"]> = TCol["ValType"] | Arg<TCol["ValType"]>> extends SqlFn<TCol, IsArg<TVal>, "scalar", "numeric", number> {
8
+ private readonly col;
9
+ private readonly val;
10
+ private readonly op;
11
+ constructor(col: TCol, val: TVal, op: TOp);
12
+ toQuery(query: Query, ctx?: QueryContext): void;
13
+ }
14
+ /** Computes the L2 distance using the `<->` operator. */
15
+ declare function l2Distance<TCol extends AnyColumn>(col: TCol, val: TCol["ValType"]): DistanceFn<TCol, "<->", TCol["ValType"]>;
16
+ declare function l2Distance<TCol extends AnyColumn>(col: TCol, val: Arg<TCol["ValType"]>): DistanceFn<TCol, "<->", Arg<TCol["ValType"]>>;
17
+ /** Computes the inner product using the `<#>` operator. */
18
+ declare function innerProduct<TCol extends AnyColumn>(col: TCol, val: TCol["ValType"]): DistanceFn<TCol, "<#>", TCol["ValType"]>;
19
+ declare function innerProduct<TCol extends AnyColumn>(col: TCol, val: Arg<TCol["ValType"]>): DistanceFn<TCol, "<#>", Arg<TCol["ValType"]>>;
20
+ /** Computes the cosine distance using the `<=>` operator. */
21
+ declare function cosineDistance<TCol extends AnyColumn>(col: TCol, val: TCol["ValType"]): DistanceFn<TCol, "<=>", TCol["ValType"]>;
22
+ declare function cosineDistance<TCol extends AnyColumn>(col: TCol, val: Arg<TCol["ValType"]>): DistanceFn<TCol, "<=>", Arg<TCol["ValType"]>>;
23
+ /** Computes the L1 distance using the `<+>` operator. */
24
+ declare function l1Distance<TCol extends AnyColumn>(col: TCol, val: TCol["ValType"]): DistanceFn<TCol, "<+>", TCol["ValType"]>;
25
+ declare function l1Distance<TCol extends AnyColumn>(col: TCol, val: Arg<TCol["ValType"]>): DistanceFn<TCol, "<+>", Arg<TCol["ValType"]>>;
26
+ /** Computes the Hamming distance using the `<~>` operator. */
27
+ declare function hammingDistance<TCol extends AnyColumn>(col: TCol, val: TCol["ValType"]): DistanceFn<TCol, "<~>", TCol["ValType"]>;
28
+ declare function hammingDistance<TCol extends AnyColumn>(col: TCol, val: Arg<TCol["ValType"]>): DistanceFn<TCol, "<~>", Arg<TCol["ValType"]>>;
29
+ /** Computes the Jaccard distance using the `<%>` operator. */
30
+ declare function jaccardDistance<TCol extends AnyColumn>(col: TCol, val: TCol["ValType"]): DistanceFn<TCol, "<%>", TCol["ValType"]>;
31
+ declare function jaccardDistance<TCol extends AnyColumn>(col: TCol, val: Arg<TCol["ValType"]>): DistanceFn<TCol, "<%>", Arg<TCol["ValType"]>>;
32
+ //#endregion
33
+ export { cosineDistance, hammingDistance, innerProduct, jaccardDistance, l1Distance, l2Distance };
@@ -0,0 +1,38 @@
1
+ import { SqlFn } from "./index.mjs";
2
+ import { Arg } from "../query-builders/pre.mjs";
3
+ import { is } from "../entity.mjs";
4
+ //#region src/functions/pgvector.ts
5
+ var DistanceFn = class extends SqlFn {
6
+ constructor(col, val, op) {
7
+ super();
8
+ this.col = col;
9
+ this.val = val;
10
+ this.op = op;
11
+ }
12
+ toQuery(query, ctx) {
13
+ this.col.toQuery(query, ctx);
14
+ query.sql += ` ${this.op} `;
15
+ if (is(this.val, Arg)) query.addArg(this.val);
16
+ else query.sql += this.col.toSQL(this.val, { cast: true });
17
+ }
18
+ };
19
+ function l2Distance(col, val) {
20
+ return new DistanceFn(col, val, "<->");
21
+ }
22
+ function innerProduct(col, val) {
23
+ return new DistanceFn(col, val, "<#>");
24
+ }
25
+ function cosineDistance(col, val) {
26
+ return new DistanceFn(col, val, "<=>");
27
+ }
28
+ function l1Distance(col, val) {
29
+ return new DistanceFn(col, val, "<+>");
30
+ }
31
+ function hammingDistance(col, val) {
32
+ return new DistanceFn(col, val, "<~>");
33
+ }
34
+ function jaccardDistance(col, val) {
35
+ return new DistanceFn(col, val, "<%>");
36
+ }
37
+ //#endregion
38
+ export { cosineDistance, hammingDistance, innerProduct, jaccardDistance, l1Distance, l2Distance };
@@ -24,6 +24,7 @@ import { json } from "./columns/json.mjs";
24
24
  import { jsonb } from "./columns/jsonb.mjs";
25
25
  import { macaddr } from "./columns/macaddr.mjs";
26
26
  import { numeric } from "./columns/numeric.mjs";
27
+ import { pgvector } from "./columns/pgvector/index.mjs";
27
28
  import { geography } from "./columns/postgis/geography/index.mjs";
28
29
  import { serial } from "./columns/serial.mjs";
29
30
  import { smallint } from "./columns/smallint.mjs";
@@ -38,6 +39,7 @@ import { stContains, stDWithin, stIntersects, stWithin } from "./filters/postgis
38
39
  import { contains, endsWith, like, startsWith } from "./filters/string.mjs";
39
40
  import { avg, count, countDistinct, max, min, sum } from "./functions/aggregate.mjs";
40
41
  import { abs, ceil, floor, mod, round } from "./functions/numeric.mjs";
42
+ import { cosineDistance, hammingDistance, innerProduct, jaccardDistance, l1Distance, l2Distance } from "./functions/pgvector.mjs";
41
43
  import { stDistance } from "./functions/postgis.mjs";
42
44
  import { left, length, lower, position, right, trim, upper } from "./functions/string.mjs";
43
45
  import { Migrations, pk } from "./models.mjs";
@@ -98,4 +100,4 @@ type Config<T extends Connector = Connector> = {
98
100
  connector: T;
99
101
  };
100
102
  //#endregion
101
- export { $, type $Client, type AnyColumn, Arg, Column, type ColumnConfig, Config, type ConnectorOptions, Dimension, Filter, type Key, Migrations, type Prettify, PrimaryKeyConstraint, Query, type QueryContext, type QueryLogger, Sql, SqlFn, type TableColumn, UniqueConstraint, type UuidVersion, abs, and, array, arrayAll, arrayContainedBy, arrayContains, arrayHas, arrayOverlaps, asc, avg, bigint, bigserial, boolean, bytea, ceil, char, cidr, contains, count, countDistinct, database, date, defineConfig, desc, endsWith, enumed, enumtype, eq, fk, floor, geography, gt, gte, index, inet, integer, isIn, isNotNull, isNull, json, jsonb, left, length, like, lower, lt, lte, macaddr, many, max, min, mod, ne, notIn, notNull, now, numeric, one, or, pk, position, prequery, primaryKey, primaryKeyConstraint, relations, right, round, sequence, serial, smallint, smallserial, sql, stContains, stDWithin, stDistance, stIntersects, stWithin, startsWith, sum, table, text, time, timestamp, trim, tuple, unique, uniqueConstraint, uniqueIndex, upper, uuid, uuidv4, uuidv7, varchar };
103
+ export { $, type $Client, type AnyColumn, Arg, Column, type ColumnConfig, Config, type ConnectorOptions, Dimension, Filter, type Key, Migrations, type Prettify, PrimaryKeyConstraint, Query, type QueryContext, type QueryLogger, Sql, SqlFn, type TableColumn, UniqueConstraint, type UuidVersion, abs, and, array, arrayAll, arrayContainedBy, arrayContains, arrayHas, arrayOverlaps, asc, avg, bigint, bigserial, boolean, bytea, ceil, char, cidr, contains, cosineDistance, count, countDistinct, database, date, defineConfig, desc, endsWith, enumed, enumtype, eq, fk, floor, geography, gt, gte, hammingDistance, index, inet, innerProduct, integer, isIn, isNotNull, isNull, jaccardDistance, json, jsonb, l1Distance, l2Distance, left, length, like, lower, lt, lte, macaddr, many, max, min, mod, ne, notIn, notNull, now, numeric, one, or, pgvector, pk, position, prequery, primaryKey, primaryKeyConstraint, relations, right, round, sequence, serial, smallint, smallserial, sql, stContains, stDWithin, stDistance, stIntersects, stWithin, startsWith, sum, table, text, time, timestamp, trim, tuple, unique, uniqueConstraint, uniqueIndex, upper, uuid, uuidv4, uuidv7, varchar };
@@ -18,6 +18,7 @@ import { json } from "./columns/json.mjs";
18
18
  import { jsonb } from "./columns/jsonb.mjs";
19
19
  import { macaddr } from "./columns/macaddr.mjs";
20
20
  import { numeric } from "./columns/numeric.mjs";
21
+ import { pgvector } from "./columns/pgvector/index.mjs";
21
22
  import { geography } from "./columns/postgis/geography/index.mjs";
22
23
  import { serial } from "./columns/serial.mjs";
23
24
  import { smallint } from "./columns/smallint.mjs";
@@ -38,6 +39,7 @@ import { stContains, stDWithin, stIntersects, stWithin } from "./filters/postgis
38
39
  import { contains, endsWith, like, startsWith } from "./filters/string.mjs";
39
40
  import { avg, count, countDistinct, max, min, sum } from "./functions/aggregate.mjs";
40
41
  import { abs, ceil, floor, mod, round } from "./functions/numeric.mjs";
42
+ import { cosineDistance, hammingDistance, innerProduct, jaccardDistance, l1Distance, l2Distance } from "./functions/pgvector.mjs";
41
43
  import { stDistance } from "./functions/postgis.mjs";
42
44
  import { left, length, lower, position, right, trim, upper } from "./functions/string.mjs";
43
45
  import { index, uniqueIndex } from "./indexes.mjs";
@@ -80,4 +82,4 @@ function defineConfig(config) {
80
82
  return config;
81
83
  }
82
84
  //#endregion
83
- export { $, Arg, Column, Dimension, Filter, Migrations, PrimaryKeyConstraint, Query, Sql, SqlFn, UniqueConstraint, abs, and, array, arrayAll, arrayContainedBy, arrayContains, arrayHas, arrayOverlaps, asc, avg, bigint, bigserial, boolean, bytea, ceil, char, cidr, contains, count, countDistinct, database, date, defineConfig, desc, endsWith, enumed, enumtype, eq, fk, floor, geography, gt, gte, index, inet, integer, isIn, isNotNull, isNull, json, jsonb, left, length, like, lower, lt, lte, macaddr, many, max, min, mod, ne, notIn, notNull, now, numeric, one, or, pk, position, prequery, primaryKey, primaryKeyConstraint, relations, right, round, sequence, serial, smallint, smallserial, sql, stContains, stDWithin, stDistance, stIntersects, stWithin, startsWith, sum, table, text, time, timestamp, trim, tuple, unique, uniqueConstraint, uniqueIndex, upper, uuid, uuidv4, uuidv7, varchar };
85
+ export { $, Arg, Column, Dimension, Filter, Migrations, PrimaryKeyConstraint, Query, Sql, SqlFn, UniqueConstraint, abs, and, array, arrayAll, arrayContainedBy, arrayContains, arrayHas, arrayOverlaps, asc, avg, bigint, bigserial, boolean, bytea, ceil, char, cidr, contains, cosineDistance, count, countDistinct, database, date, defineConfig, desc, endsWith, enumed, enumtype, eq, fk, floor, geography, gt, gte, hammingDistance, index, inet, innerProduct, integer, isIn, isNotNull, isNull, jaccardDistance, json, jsonb, l1Distance, l2Distance, left, length, like, lower, lt, lte, macaddr, many, max, min, mod, ne, notIn, notNull, now, numeric, one, or, pgvector, pk, position, prequery, primaryKey, primaryKeyConstraint, relations, right, round, sequence, serial, smallint, smallserial, sql, stContains, stDWithin, stDistance, stIntersects, stWithin, startsWith, sum, table, text, time, timestamp, trim, tuple, unique, uniqueConstraint, uniqueIndex, upper, uuid, uuidv4, uuidv7, varchar };
@@ -1,12 +1,13 @@
1
+ import { IndexOn } from "./columns/common.mjs";
1
2
  import { AnyColumn, StdTable, StdTableColumn } from "./table.mjs";
2
3
 
3
4
  //#region src/indexes.d.ts
4
5
  type IndexType = "btree" | "hash" | "gist" | "spgist" | "gin" | "brin" | "hnsw" | "ivfflat" | (string & {});
5
6
  declare class Index<Col extends AnyColumn> {
6
7
  #private;
7
- constructor(columns: StdTableColumn<Col>[], using: IndexType, unique: boolean);
8
+ constructor(columns: (StdTableColumn<Col> | IndexOn<Col>)[], using: IndexType, unique: boolean);
8
9
  _: {
9
- getColumns: () => StdTableColumn<Col>[];
10
+ getColumns: () => (StdTableColumn<Col> | IndexOn<Col>)[];
10
11
  getUsing: () => IndexType;
11
12
  getUnique: () => boolean;
12
13
  getName: (table: StdTable) => string;
@@ -25,7 +26,7 @@ declare class Index<Col extends AnyColumn> {
25
26
  */
26
27
  using(using: IndexType): this;
27
28
  }
28
- declare function index<Col extends AnyColumn>(columns: StdTableColumn<Col>[], using?: IndexType): Index<Col>;
29
- declare function uniqueIndex<Col extends AnyColumn>(columns: StdTableColumn<Col>[], using?: IndexType): Index<Col>;
29
+ declare function index<Col extends AnyColumn>(columns: (StdTableColumn<Col> | IndexOn<Col>)[], using?: IndexType): Index<Col>;
30
+ declare function uniqueIndex<Col extends AnyColumn>(columns: (StdTableColumn<Col> | IndexOn<Col>)[], using?: IndexType): Index<Col>;
30
31
  //#endregion
31
32
  export { Index, IndexType, index, uniqueIndex };
@@ -1,3 +1,4 @@
1
+ import { IndexOn } from "./columns/common.mjs";
1
2
  //#region src/indexes.ts
2
3
  var Index = class {
3
4
  #columns;
@@ -13,7 +14,7 @@ var Index = class {
13
14
  getUsing: () => this.#using,
14
15
  getUnique: () => this.#unique,
15
16
  getName: (table) => {
16
- return `${table._.nameSql}_${this.#columns.map((col) => col.nameSql).join("_")}_index`;
17
+ return `${table._.nameSql}_${this.#columns.map((col) => col instanceof IndexOn ? col.column.nameSql : col.nameSql).join("_")}_index`;
17
18
  }
18
19
  };
19
20
  /**
@@ -51,7 +51,7 @@ declare class CreateIndexBuilder extends DDLStatement {
51
51
  * @param columns - Optional array of column names to index.
52
52
  * @returns `this` for chaining.
53
53
  */
54
- on(schema: string, table: string, columns?: string[]): this;
54
+ on(schema: string, table: string, columns?: (string | [string, string])[]): this;
55
55
  /**
56
56
  * Specify the index method.
57
57
  *
@@ -59,7 +59,7 @@ declare class CreateIndexBuilder extends DDLStatement {
59
59
  * @param columns - Optional array of column names to index.
60
60
  * @returns `this` for chaining.
61
61
  */
62
- using(type: IndexType, columns?: string[]): this;
62
+ using(type: IndexType, columns?: (string | [string, string])[]): this;
63
63
  /**
64
64
  * Make this a unique index.
65
65
  *
@@ -82,7 +82,11 @@ var CreateIndexBuilder = class extends DDLStatement {
82
82
  }
83
83
  toSQL() {
84
84
  const tableRelation = `"${this.tableSchema}"."${this.tableName}"`;
85
- const columns = this.indexColumns.map((c) => `"${c}"`).join(", ");
85
+ const columns = this.indexColumns.map((c) => {
86
+ const colName = typeof c === "string" ? c : c[0];
87
+ const colOpclass = typeof c === "string" ? void 0 : c[1];
88
+ return colOpclass ? `"${colName}" ${colOpclass}` : `"${colName}"`;
89
+ }).join(", ");
86
90
  return `CREATE${this.isUnique ? " UNIQUE" : ""} INDEX${this.isConcurrent ? " CONCURRENTLY" : ""} ${this.indexName} ON ${tableRelation} USING ${this.indexType} (${columns});`;
87
91
  }
88
92
  applyToSnapshot(snapshot) {
@@ -91,7 +95,12 @@ var CreateIndexBuilder = class extends DDLStatement {
91
95
  if (!table) return;
92
96
  table.indexes[this.indexName] = {
93
97
  name: this.indexName,
94
- columns: [...this.indexColumns],
98
+ columns: this.indexColumns.map((c) => {
99
+ return {
100
+ name: typeof c === "string" ? c : c[0],
101
+ opclass: typeof c === "string" ? void 0 : c[1]
102
+ };
103
+ }),
95
104
  type: this.indexType,
96
105
  unique: this.isUnique
97
106
  };
@@ -102,14 +102,23 @@ interface SnapshotSequence {
102
102
  /** Number of sequence values to pre-allocate (`CACHE`). */
103
103
  cache?: number;
104
104
  }
105
+ /**
106
+ * Snapshot of a table index column.
107
+ */
108
+ interface SnapshotTableIndexColumn {
109
+ /** The column name. */
110
+ name: string;
111
+ /** Optional operator class for this specific column. */
112
+ opclass?: string;
113
+ }
105
114
  /**
106
115
  * Snapshot of a table index.
107
116
  */
108
117
  interface SnapshotTableIndex {
109
118
  /** The index name. */
110
119
  name: string;
111
- /** Column names included in the index. */
112
- columns: string[];
120
+ /** Columns included in the index. */
121
+ columns: SnapshotTableIndexColumn[];
113
122
  /** The index method (e.g. `"btree"`, `"hash"`, `"gin"`, `"gist"`). */
114
123
  type: IndexType;
115
124
  /** Whether this is a unique index. */
@@ -1,4 +1,5 @@
1
1
  import { Query } from "../query-builders/query.mjs";
2
+ import { IndexOn } from "../columns/common.mjs";
2
3
  import { is } from "../entity.mjs";
3
4
  import { Sql } from "../sql.mjs";
4
5
  import { primaryKeyConstraint } from "../constraints/primary-key.mjs";
@@ -74,7 +75,13 @@ function snapshot(entities) {
74
75
  (table._.extra.indexes?.(table) ?? []).forEach((index) => {
75
76
  ss.tables[`${table._.schemaSql}.${table._.nameSql}`].indexes[index._.getName(table)] = {
76
77
  name: index._.getName(table),
77
- columns: index._.getColumns().map((col) => col.nameSql),
78
+ columns: index._.getColumns().map((col) => {
79
+ if (col instanceof IndexOn) return {
80
+ name: col.column.nameSql,
81
+ opclass: col.opclassStr
82
+ };
83
+ return { name: col.nameSql };
84
+ }),
78
85
  type: index._.getUsing(),
79
86
  unique: index._.getUnique()
80
87
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "durcno",
3
- "version": "1.0.0-alpha.13",
3
+ "version": "1.0.0-alpha.14",
4
4
  "description": "A PostgreSQL Query Builder and Migration Manager for TypeScript, from the future.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://durcno.dev",