@vibeorm/extensions 4.0.0 → 4.1.0
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/dist/index.js +35 -25
- package/dist/index.js.map +6 -6
- package/dist/search/index.js +25 -17
- package/dist/search/index.js.map +4 -4
- package/dist/shared.d.ts +6 -0
- package/dist/trgm/index.js +10 -4
- package/dist/trgm/index.js.map +4 -4
- package/dist/vector/index.js +16 -8
- package/dist/vector/index.js.map +4 -4
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// packages/extensions/src/search/index.ts
|
|
3
|
-
import { VibeError as VibeError2, assertIdentifierFits, defineExtension, fitDefaultName, unsupportedCapability } from "@vibeorm/schema";
|
|
3
|
+
import { VibeError as VibeError2, assertExtensionModelPlacement as assertExtensionModelPlacement2, assertIdentifierFits, defineExtension, fitDefaultName, unsupportedCapability } from "@vibeorm/schema";
|
|
4
4
|
|
|
5
5
|
// packages/extensions/src/shared.ts
|
|
6
|
-
import { VibeError } from "@vibeorm/schema";
|
|
6
|
+
import { VibeError, assertExtensionModelPlacement, qualifiedSqlName } from "@vibeorm/schema";
|
|
7
|
+
function extensionSqlName(params) {
|
|
8
|
+
const { dialect, name } = params;
|
|
9
|
+
const physical = qualifiedSqlName({ name });
|
|
10
|
+
return dialect.name === "postgres" ? `${dialect.quoteIdent({ name: physical.namespace })}.${dialect.quoteIdent({ name: physical.name })}` : dialect.quoteIdent({ name });
|
|
11
|
+
}
|
|
7
12
|
function finiteNumber(params) {
|
|
8
13
|
const { value, name, integer, min } = params;
|
|
9
14
|
if (typeof value !== "number" || !Number.isFinite(value) || integer === true && !Number.isSafeInteger(value) || min !== undefined && value < min) {
|
|
@@ -16,6 +21,7 @@ function finiteNumber(params) {
|
|
|
16
21
|
return value;
|
|
17
22
|
}
|
|
18
23
|
function tableNameOf(params) {
|
|
24
|
+
assertExtensionModelPlacement({ namespace: params.model.namespace });
|
|
19
25
|
return params.model.dbName ?? params.model.name;
|
|
20
26
|
}
|
|
21
27
|
function columnNameOf(params) {
|
|
@@ -461,16 +467,16 @@ function searchArtifacts(ctx) {
|
|
|
461
467
|
id: `search:${modelName}:column`,
|
|
462
468
|
owns: { kind: "column", table, column: tsvColumn },
|
|
463
469
|
create: [
|
|
464
|
-
`ALTER TABLE ${
|
|
470
|
+
`ALTER TABLE ${extensionSqlName({ dialect, name: table })} ADD COLUMN IF NOT EXISTS ${quote(tsvColumn)} tsvector GENERATED ALWAYS AS (${expression}) STORED;`
|
|
465
471
|
],
|
|
466
|
-
drop: [`ALTER TABLE ${
|
|
472
|
+
drop: [`ALTER TABLE ${extensionSqlName({ dialect, name: table })} DROP COLUMN IF EXISTS ${quote(tsvColumn)};`]
|
|
467
473
|
}, {
|
|
468
474
|
id: `search:${modelName}:index`,
|
|
469
475
|
owns: { kind: "index", table, name: indexName },
|
|
470
476
|
create: [
|
|
471
|
-
`CREATE INDEX IF NOT EXISTS ${quote(indexName)} ON ${
|
|
477
|
+
`CREATE INDEX IF NOT EXISTS ${quote(indexName)} ON ${extensionSqlName({ dialect, name: table })} USING gin (${quote(tsvColumn)});`
|
|
472
478
|
],
|
|
473
|
-
drop: [`DROP INDEX IF EXISTS ${
|
|
479
|
+
drop: [`DROP INDEX IF EXISTS ${extensionSqlName({ dialect, name: indexName })};`]
|
|
474
480
|
});
|
|
475
481
|
continue;
|
|
476
482
|
}
|
|
@@ -490,9 +496,9 @@ function searchArtifacts(ctx) {
|
|
|
490
496
|
id: `search:${modelName}:index`,
|
|
491
497
|
owns: { kind: "index", table, name: bm25Names.indexName },
|
|
492
498
|
create: [
|
|
493
|
-
`CREATE INDEX IF NOT EXISTS ${quote(bm25Names.indexName)} ON ${
|
|
499
|
+
`CREATE INDEX IF NOT EXISTS ${quote(bm25Names.indexName)} ON ${extensionSqlName({ dialect, name: table })} USING bm25 (${indexed.join(", ")}) WITH (${withOptions.join(", ")});`
|
|
494
500
|
],
|
|
495
|
-
drop: [`DROP INDEX IF EXISTS ${
|
|
501
|
+
drop: [`DROP INDEX IF EXISTS ${extensionSqlName({ dialect, name: bm25Names.indexName })};`]
|
|
496
502
|
});
|
|
497
503
|
continue;
|
|
498
504
|
}
|
|
@@ -528,10 +534,10 @@ function searchArtifacts(ctx) {
|
|
|
528
534
|
id: `search:${modelName}:fts5-triggers`,
|
|
529
535
|
owns: { kind: "trigger", table, name: `${fts}_ai` },
|
|
530
536
|
create: [
|
|
531
|
-
`CREATE TRIGGER IF NOT EXISTS ${quote(`${fts}_ai`)} AFTER INSERT ON ${
|
|
537
|
+
`CREATE TRIGGER IF NOT EXISTS ${quote(`${fts}_ai`)} AFTER INSERT ON ${extensionSqlName({ dialect, name: table })} BEGIN
|
|
532
538
|
INSERT INTO ${quote(fts)}(rowid, ${columnList}) VALUES (new.rowid, ${newList});
|
|
533
539
|
END;`,
|
|
534
|
-
`CREATE TRIGGER IF NOT EXISTS ${quote(`${fts}_ad`)} AFTER DELETE ON ${
|
|
540
|
+
`CREATE TRIGGER IF NOT EXISTS ${quote(`${fts}_ad`)} AFTER DELETE ON ${extensionSqlName({ dialect, name: table })} BEGIN
|
|
535
541
|
INSERT INTO ${quote(fts)}(${quote(fts)}, rowid, ${columnList}) VALUES ('delete', old.rowid, ${oldList});
|
|
536
542
|
END;`,
|
|
537
543
|
updateTrigger.create,
|
|
@@ -561,9 +567,9 @@ END;`,
|
|
|
561
567
|
id: `search:${modelName}:index`,
|
|
562
568
|
owns: { kind: "index", table, name: fulltextNames.indexName },
|
|
563
569
|
create: [
|
|
564
|
-
`CREATE FULLTEXT INDEX ${quote(fulltextNames.indexName)} ON ${
|
|
570
|
+
`CREATE FULLTEXT INDEX ${quote(fulltextNames.indexName)} ON ${extensionSqlName({ dialect, name: table })} (${columns.map((column) => quote(column)).join(", ")});`
|
|
565
571
|
],
|
|
566
|
-
drop: [`DROP INDEX ${quote(fulltextNames.indexName)} ON ${
|
|
572
|
+
drop: [`DROP INDEX ${quote(fulltextNames.indexName)} ON ${extensionSqlName({ dialect, name: table })};`]
|
|
567
573
|
});
|
|
568
574
|
}
|
|
569
575
|
return artifacts;
|
|
@@ -596,6 +602,8 @@ function shapeHits(params) {
|
|
|
596
602
|
}
|
|
597
603
|
function createSearchDelegate(config) {
|
|
598
604
|
return (ctx) => {
|
|
605
|
+
if (ctx.model !== null)
|
|
606
|
+
assertExtensionModelPlacement2({ namespace: ctx.model.namespace, dialect: ctx.dialect.name });
|
|
599
607
|
const dialect = ctx.dialect;
|
|
600
608
|
const quote = (name) => dialect.quoteIdent({ name });
|
|
601
609
|
const t = quote("t");
|
|
@@ -678,7 +686,7 @@ function createSearchDelegate(config) {
|
|
|
678
686
|
if (hlColumn !== null) {
|
|
679
687
|
text += `, ts_headline('${language}', ${t}.${quote(hlColumn)}, ${tsquery()}) AS ${quote(HIGHLIGHT_ALIAS)}`;
|
|
680
688
|
}
|
|
681
|
-
text += ` FROM ${
|
|
689
|
+
text += ` FROM ${extensionSqlName({ dialect, name: config.table })} AS ${t} WHERE ${tsv} @@ ${tsquery()}`;
|
|
682
690
|
const where = userWhere("t");
|
|
683
691
|
if (where !== null)
|
|
684
692
|
text += ` AND (${where})`;
|
|
@@ -692,7 +700,7 @@ function createSearchDelegate(config) {
|
|
|
692
700
|
const index = config.fields.findIndex((field) => field.column === hlColumn);
|
|
693
701
|
text += `, snippet(${fts}, ${index}, '<b>', '</b>', '\u2026', 16) AS ${quote(HIGHLIGHT_ALIAS)}`;
|
|
694
702
|
}
|
|
695
|
-
text += ` FROM ${fts} JOIN ${
|
|
703
|
+
text += ` FROM ${fts} JOIN ${extensionSqlName({ dialect, name: config.table })} AS ${t} ON ${t}.rowid = ${fts}.rowid`;
|
|
696
704
|
text += ` WHERE ${fts} MATCH ${collector.add(matchText)}`;
|
|
697
705
|
const where = userWhere("t");
|
|
698
706
|
if (where !== null)
|
|
@@ -704,7 +712,7 @@ function createSearchDelegate(config) {
|
|
|
704
712
|
engineHasHighlights = false;
|
|
705
713
|
const mode = prefix ? "IN BOOLEAN MODE" : "IN NATURAL LANGUAGE MODE";
|
|
706
714
|
const match = () => `MATCH (${config.fields.map((field) => `${t}.${quote(field.column)}`).join(", ")}) AGAINST (${collector.add(matchText)} ${mode})`;
|
|
707
|
-
text = `SELECT ${projection}, ${match()} AS ${quote(SCORE_ALIAS)} FROM ${
|
|
715
|
+
text = `SELECT ${projection}, ${match()} AS ${quote(SCORE_ALIAS)} FROM ${extensionSqlName({ dialect, name: config.table })} AS ${t}`;
|
|
708
716
|
text += ` WHERE ${match()}`;
|
|
709
717
|
const where = userWhere("t");
|
|
710
718
|
if (where !== null)
|
|
@@ -720,7 +728,7 @@ function createSearchDelegate(config) {
|
|
|
720
728
|
if (hlColumn !== null) {
|
|
721
729
|
text += `, paradedb.snippet(${t}.${quote(hlColumn)}) AS ${quote(HIGHLIGHT_ALIAS)}`;
|
|
722
730
|
}
|
|
723
|
-
text += ` FROM ${
|
|
731
|
+
text += ` FROM ${extensionSqlName({ dialect, name: config.table })} AS ${t} WHERE (${config.fields.map((field, index) => {
|
|
724
732
|
const boost = config.boosts?.[index];
|
|
725
733
|
const boostCast = boost === undefined || boost === 1 ? "" : `::pdb.boost(${boost})`;
|
|
726
734
|
return `${t}.${quote(field.column)} ${operator} ${collector.add(matchText)}${fuzzyCast}${boostCast}`;
|
|
@@ -907,7 +915,7 @@ function search(options = {}) {
|
|
|
907
915
|
});
|
|
908
916
|
}
|
|
909
917
|
// packages/extensions/src/vector/index.ts
|
|
910
|
-
import { VibeError as VibeError3, assertIdentifierFits as assertIdentifierFits2, defineExtension as defineExtension2, fitDefaultName as fitDefaultName2, unsupportedCapability as unsupportedCapability2 } from "@vibeorm/schema";
|
|
918
|
+
import { VibeError as VibeError3, assertExtensionModelPlacement as assertExtensionModelPlacement3, assertIdentifierFits as assertIdentifierFits2, defineExtension as defineExtension2, fitDefaultName as fitDefaultName2, unsupportedCapability as unsupportedCapability2 } from "@vibeorm/schema";
|
|
911
919
|
import { ParamCollector as ParamCollector2, getSqlDialect as getSqlDialect2, renderExpr as renderExpr2 } from "@vibeorm/sql";
|
|
912
920
|
var VERSION2 = "2.0.0-alpha.0";
|
|
913
921
|
var METRIC_OPERATOR = {
|
|
@@ -1020,9 +1028,9 @@ function vectorArtifacts(ctx) {
|
|
|
1020
1028
|
id: `vector:${modelName}:${field}`,
|
|
1021
1029
|
owns: { kind: "index", table, name: indexName },
|
|
1022
1030
|
create: [
|
|
1023
|
-
`CREATE INDEX IF NOT EXISTS ${quote(indexName)} ON ${
|
|
1031
|
+
`CREATE INDEX IF NOT EXISTS ${quote(indexName)} ON ${extensionSqlName({ dialect, name: table })} USING ${kindRaw} (${quote(column)} ${METRIC_OPCLASS[metric]})${withClause};`
|
|
1024
1032
|
],
|
|
1025
|
-
drop: [`DROP INDEX IF EXISTS ${
|
|
1033
|
+
drop: [`DROP INDEX IF EXISTS ${extensionSqlName({ dialect, name: indexName })};`]
|
|
1026
1034
|
});
|
|
1027
1035
|
}
|
|
1028
1036
|
}
|
|
@@ -1056,6 +1064,8 @@ function resolveColumn(params) {
|
|
|
1056
1064
|
}
|
|
1057
1065
|
function createVectorNamespace(config) {
|
|
1058
1066
|
return (ctx) => {
|
|
1067
|
+
if (ctx.model !== null)
|
|
1068
|
+
assertExtensionModelPlacement3({ namespace: ctx.model.namespace, dialect: ctx.dialect.name });
|
|
1059
1069
|
const dialect = ctx.dialect;
|
|
1060
1070
|
const quote = (name) => dialect.quoteIdent({ name });
|
|
1061
1071
|
const t = quote("t");
|
|
@@ -1071,7 +1081,7 @@ function createVectorNamespace(config) {
|
|
|
1071
1081
|
const collector = new ParamCollector2(dialect);
|
|
1072
1082
|
const vector = dialect.name === "postgres" ? collector.add(literal) : undefined;
|
|
1073
1083
|
let text = `SELECT ${ctx.projection({ qualify: "t" })}, (${col} ${op} ${vector ?? collector.add(literal)}) AS ${quote(DISTANCE_ALIAS)}`;
|
|
1074
|
-
text += ` FROM ${
|
|
1084
|
+
text += ` FROM ${extensionSqlName({ dialect, name: config.table })} AS ${t}`;
|
|
1075
1085
|
text += ` WHERE ${col} IS NOT NULL`;
|
|
1076
1086
|
if (args.where !== undefined) {
|
|
1077
1087
|
const expr = ctx.compileWhere({ where: args.where, qualify: "t" });
|
|
@@ -1095,7 +1105,7 @@ function createVectorNamespace(config) {
|
|
|
1095
1105
|
set: async (args) => {
|
|
1096
1106
|
const { column, literal } = resolveColumn({ config, args });
|
|
1097
1107
|
const collector = new ParamCollector2(dialect);
|
|
1098
|
-
let text = `UPDATE ${
|
|
1108
|
+
let text = `UPDATE ${extensionSqlName({ dialect, name: config.table })} SET ${quote(column)} = ${collector.add(literal)}`;
|
|
1099
1109
|
const expr = ctx.compileWhere({ where: args.where });
|
|
1100
1110
|
if (expr !== undefined)
|
|
1101
1111
|
text += ` WHERE ${renderExpr2({ dialect, expr, collector })}`;
|
|
@@ -1158,7 +1168,7 @@ function vector(options = {}) {
|
|
|
1158
1168
|
}
|
|
1159
1169
|
if (fields.length !== 1) {
|
|
1160
1170
|
return {
|
|
1161
|
-
error: `indexName needs exactly one indexed field \u2014
|
|
1171
|
+
error: `indexName needs exactly one indexed field \u2014 one named index declaration per model is supported`
|
|
1162
1172
|
};
|
|
1163
1173
|
}
|
|
1164
1174
|
}
|
|
@@ -1265,9 +1275,9 @@ function trgmArtifacts(ctx) {
|
|
|
1265
1275
|
id: `trgm:${modelName}:${field}`,
|
|
1266
1276
|
owns: { kind: "index", table, name: indexName },
|
|
1267
1277
|
create: [
|
|
1268
|
-
`CREATE INDEX IF NOT EXISTS ${quote(indexName)} ON ${
|
|
1278
|
+
`CREATE INDEX IF NOT EXISTS ${quote(indexName)} ON ${extensionSqlName({ dialect, name: table })} USING gin (${quote(column)} gin_trgm_ops);`
|
|
1269
1279
|
],
|
|
1270
|
-
drop: [`DROP INDEX IF EXISTS ${
|
|
1280
|
+
drop: [`DROP INDEX IF EXISTS ${extensionSqlName({ dialect, name: indexName })};`]
|
|
1271
1281
|
});
|
|
1272
1282
|
}
|
|
1273
1283
|
}
|
|
@@ -1415,4 +1425,4 @@ export {
|
|
|
1415
1425
|
vector
|
|
1416
1426
|
};
|
|
1417
1427
|
|
|
1418
|
-
//# debugId=
|
|
1428
|
+
//# debugId=198B01543660222064756E2164756E21
|