@mastra/pg 0.11.1-alpha.0 → 0.11.1-alpha.2
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/.turbo/turbo-build.log +7 -7
- package/CHANGELOG.md +28 -0
- package/dist/_tsup-dts-rollup.d.cts +40 -6
- package/dist/_tsup-dts-rollup.d.ts +40 -6
- package/dist/index.cjs +808 -255
- package/dist/index.js +785 -232
- package/package.json +4 -4
- package/src/storage/index.test.ts +428 -35
- package/src/storage/index.ts +596 -197
- package/src/vector/filter.test.ts +12 -12
- package/src/vector/filter.ts +36 -7
- package/src/vector/index.test.ts +2 -2
- package/src/vector/index.ts +283 -90
- package/src/vector/sql-builder.ts +2 -1
|
@@ -54,7 +54,7 @@ describe('PGFilterTranslator', () => {
|
|
|
54
54
|
translator.translate({
|
|
55
55
|
nested: {
|
|
56
56
|
field: 'value',
|
|
57
|
-
},
|
|
57
|
+
} as any,
|
|
58
58
|
}),
|
|
59
59
|
).toEqual({
|
|
60
60
|
'nested.field': { $eq: 'value' },
|
|
@@ -634,7 +634,7 @@ describe('PGFilterTranslator', () => {
|
|
|
634
634
|
|
|
635
635
|
it('throws error for $not if not an object', () => {
|
|
636
636
|
expect(() => translator.translate({ $not: 'value' })).toThrow();
|
|
637
|
-
expect(() => translator.translate({ $not: [{ field: 'value' }] })).toThrow();
|
|
637
|
+
expect(() => translator.translate({ $not: [{ field: 'value' }] } as any)).toThrow();
|
|
638
638
|
});
|
|
639
639
|
it('throws error for $not if empty', () => {
|
|
640
640
|
expect(() => translator.translate({ $not: {} })).toThrow();
|
|
@@ -645,21 +645,21 @@ describe('PGFilterTranslator', () => {
|
|
|
645
645
|
// $and cannot be used in field conditions
|
|
646
646
|
expect(() =>
|
|
647
647
|
translator.translate({
|
|
648
|
-
field: { $and: [{ $eq: 'value1' }, { $eq: 'value2' }] },
|
|
648
|
+
field: { $and: [{ $eq: 'value1' }, { $eq: 'value2' }] } as any,
|
|
649
649
|
}),
|
|
650
650
|
).toThrow();
|
|
651
651
|
|
|
652
652
|
// $or cannot be used in field conditions
|
|
653
653
|
expect(() =>
|
|
654
654
|
translator.translate({
|
|
655
|
-
field: { $or: [{ $eq: 'value1' }, { $eq: 'value2' }] },
|
|
655
|
+
field: { $or: [{ $eq: 'value1' }, { $eq: 'value2' }] } as any,
|
|
656
656
|
}),
|
|
657
657
|
).toThrow();
|
|
658
658
|
|
|
659
659
|
// $nor cannot be used in field conditions
|
|
660
660
|
expect(() =>
|
|
661
661
|
translator.translate({
|
|
662
|
-
field: { $nor: [{ $eq: 'value1' }, { $eq: 'value2' }] },
|
|
662
|
+
field: { $nor: [{ $eq: 'value1' }, { $eq: 'value2' }] } as any,
|
|
663
663
|
}),
|
|
664
664
|
).toThrow();
|
|
665
665
|
});
|
|
@@ -710,7 +710,7 @@ describe('PGFilterTranslator', () => {
|
|
|
710
710
|
$gt: {
|
|
711
711
|
$or: [{ subfield: 'value1' }, { subfield: 'value2' }],
|
|
712
712
|
},
|
|
713
|
-
},
|
|
713
|
+
} as any,
|
|
714
714
|
}),
|
|
715
715
|
).toThrow();
|
|
716
716
|
|
|
@@ -721,7 +721,7 @@ describe('PGFilterTranslator', () => {
|
|
|
721
721
|
$in: [
|
|
722
722
|
{
|
|
723
723
|
$and: [{ subfield: 'value1' }, { subfield: 'value2' }],
|
|
724
|
-
},
|
|
724
|
+
} as any,
|
|
725
725
|
],
|
|
726
726
|
},
|
|
727
727
|
}),
|
|
@@ -730,7 +730,7 @@ describe('PGFilterTranslator', () => {
|
|
|
730
730
|
|
|
731
731
|
it('validates $not operator structure', () => {
|
|
732
732
|
// $not must be an object
|
|
733
|
-
expect(() => translator.translate({ field: { $not: 'value' } })).toThrow();
|
|
733
|
+
expect(() => translator.translate({ field: { $not: 'value' } } as any)).toThrow();
|
|
734
734
|
expect(() => translator.translate({ field: { $not: ['value'] } })).toThrow();
|
|
735
735
|
expect(() => translator.translate({ $not: 'value' })).toThrow();
|
|
736
736
|
expect(() => translator.translate({ $not: ['value'] })).toThrow();
|
|
@@ -790,7 +790,7 @@ describe('PGFilterTranslator', () => {
|
|
|
790
790
|
});
|
|
791
791
|
|
|
792
792
|
it('throws error for non-logical operators at top level', () => {
|
|
793
|
-
const invalidFilters = [{ $gt: 100 }, { $in: ['value1', 'value2'] }, { $eq: true }];
|
|
793
|
+
const invalidFilters: any = [{ $gt: 100 }, { $in: ['value1', 'value2'] }, { $eq: true }];
|
|
794
794
|
|
|
795
795
|
invalidFilters.forEach(filter => {
|
|
796
796
|
expect(() => translator.translate(filter)).toThrow(/Invalid top-level operator/);
|
|
@@ -808,13 +808,13 @@ describe('PGFilterTranslator', () => {
|
|
|
808
808
|
// Should throw for non-object values
|
|
809
809
|
expect(() =>
|
|
810
810
|
translator.translate({
|
|
811
|
-
field: { $elemMatch: 'value' },
|
|
811
|
+
field: { $elemMatch: 'value' } as any,
|
|
812
812
|
}),
|
|
813
813
|
).toThrow('$elemMatch requires an object with conditions');
|
|
814
814
|
|
|
815
815
|
expect(() =>
|
|
816
816
|
translator.translate({
|
|
817
|
-
field: { $elemMatch: ['value'] },
|
|
817
|
+
field: { $elemMatch: ['value'] } as any,
|
|
818
818
|
}),
|
|
819
819
|
).toThrow('$elemMatch requires an object with conditions');
|
|
820
820
|
});
|
|
@@ -917,7 +917,7 @@ describe('PGFilterTranslator', () => {
|
|
|
917
917
|
translator.translate({
|
|
918
918
|
nested: {
|
|
919
919
|
field: { $regex: 'pattern', $options: 'i' },
|
|
920
|
-
},
|
|
920
|
+
} as any,
|
|
921
921
|
}),
|
|
922
922
|
).toEqual({
|
|
923
923
|
'nested.field': { $regex: '(?i)pattern' },
|
package/src/vector/filter.ts
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
import { BaseFilterTranslator } from '@mastra/core/vector/filter';
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
VectorFilter,
|
|
4
|
+
OperatorSupport,
|
|
5
|
+
OperatorValueMap,
|
|
6
|
+
LogicalOperatorValueMap,
|
|
7
|
+
BlacklistedRootOperators,
|
|
8
|
+
VectorFieldValue,
|
|
9
|
+
} from '@mastra/core/vector/filter';
|
|
10
|
+
|
|
11
|
+
type PGOperatorValueMap = Omit<OperatorValueMap, '$in' | '$all' | '$nin' | '$eq' | '$ne'> & {
|
|
12
|
+
$size: number;
|
|
13
|
+
$contains: VectorFieldValue | Record<string, unknown>;
|
|
14
|
+
$all: VectorFieldValue;
|
|
15
|
+
$in: VectorFieldValue;
|
|
16
|
+
$nin: VectorFieldValue;
|
|
17
|
+
$eq: VectorFieldValue;
|
|
18
|
+
$ne: VectorFieldValue;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
type PGBlacklisted = BlacklistedRootOperators | '$contains' | '$size';
|
|
22
|
+
|
|
23
|
+
type PGFilterValue = VectorFieldValue | RegExp;
|
|
24
|
+
|
|
25
|
+
export type PGVectorFilter = VectorFilter<
|
|
26
|
+
keyof PGOperatorValueMap,
|
|
27
|
+
PGOperatorValueMap,
|
|
28
|
+
LogicalOperatorValueMap,
|
|
29
|
+
PGBlacklisted,
|
|
30
|
+
PGFilterValue
|
|
31
|
+
>;
|
|
3
32
|
|
|
4
33
|
/**
|
|
5
34
|
* Translates MongoDB-style filters to PG compatible filters.
|
|
@@ -11,7 +40,7 @@ import type { FieldCondition, VectorFilter, OperatorSupport } from '@mastra/core
|
|
|
11
40
|
* - Can take either a single condition or an array of conditions
|
|
12
41
|
*
|
|
13
42
|
*/
|
|
14
|
-
export class PGFilterTranslator extends BaseFilterTranslator {
|
|
43
|
+
export class PGFilterTranslator extends BaseFilterTranslator<PGVectorFilter> {
|
|
15
44
|
protected override getSupportedOperators(): OperatorSupport {
|
|
16
45
|
return {
|
|
17
46
|
...BaseFilterTranslator.DEFAULT_OPERATORS,
|
|
@@ -19,7 +48,7 @@ export class PGFilterTranslator extends BaseFilterTranslator {
|
|
|
19
48
|
};
|
|
20
49
|
}
|
|
21
50
|
|
|
22
|
-
translate(filter?:
|
|
51
|
+
translate(filter?: PGVectorFilter): PGVectorFilter {
|
|
23
52
|
if (this.isEmpty(filter)) {
|
|
24
53
|
return filter;
|
|
25
54
|
}
|
|
@@ -27,7 +56,7 @@ export class PGFilterTranslator extends BaseFilterTranslator {
|
|
|
27
56
|
return this.translateNode(filter);
|
|
28
57
|
}
|
|
29
58
|
|
|
30
|
-
private translateNode(node:
|
|
59
|
+
private translateNode(node: PGVectorFilter, currentPath: string = ''): any {
|
|
31
60
|
// Helper to wrap result with path if needed
|
|
32
61
|
const withPath = (result: any) => (currentPath ? { [currentPath]: result } : result);
|
|
33
62
|
|
|
@@ -49,14 +78,14 @@ export class PGFilterTranslator extends BaseFilterTranslator {
|
|
|
49
78
|
const entries = Object.entries(node as Record<string, any>);
|
|
50
79
|
const result: Record<string, any> = {};
|
|
51
80
|
|
|
52
|
-
if ('$options' in node && !('$regex' in node)) {
|
|
81
|
+
if (node && '$options' in node && !('$regex' in node)) {
|
|
53
82
|
throw new Error('$options is not valid without $regex');
|
|
54
83
|
}
|
|
55
84
|
|
|
56
85
|
// Handle special regex object format
|
|
57
|
-
if ('$regex' in node) {
|
|
86
|
+
if (node && '$regex' in node) {
|
|
58
87
|
const options = (node as any).$options || '';
|
|
59
|
-
return withPath(this.translateRegexPattern(node.$regex, options));
|
|
88
|
+
return withPath(this.translateRegexPattern((node as any).$regex, options));
|
|
60
89
|
}
|
|
61
90
|
|
|
62
91
|
// Process remaining entries
|
package/src/vector/index.test.ts
CHANGED
|
@@ -1288,7 +1288,7 @@ describe('PgVector', () => {
|
|
|
1288
1288
|
vectorDB.query({
|
|
1289
1289
|
indexName,
|
|
1290
1290
|
queryVector: [1, 0, 0],
|
|
1291
|
-
filter: { price: { $invalid: 100 } },
|
|
1291
|
+
filter: { price: { $invalid: 100 } } as any,
|
|
1292
1292
|
}),
|
|
1293
1293
|
).rejects.toThrow('Unsupported operator: $invalid');
|
|
1294
1294
|
});
|
|
@@ -1567,7 +1567,7 @@ describe('PgVector', () => {
|
|
|
1567
1567
|
vectorDB.query({
|
|
1568
1568
|
indexName,
|
|
1569
1569
|
queryVector: [1, 0, 0],
|
|
1570
|
-
filter: { price: { $invalid: 100 } },
|
|
1570
|
+
filter: { price: { $invalid: 100 } } as any,
|
|
1571
1571
|
}),
|
|
1572
1572
|
).rejects.toThrow('Unsupported operator: $invalid');
|
|
1573
1573
|
});
|