@prisma-next/adapter-mongo 0.3.0-dev.135 → 0.3.0-dev.146

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,11 @@
1
+ //#region src/core/codec-ids.ts
2
+ const MONGO_OBJECTID_CODEC_ID = "mongo/objectId@1";
3
+ const MONGO_STRING_CODEC_ID = "mongo/string@1";
4
+ const MONGO_INT32_CODEC_ID = "mongo/int32@1";
5
+ const MONGO_BOOLEAN_CODEC_ID = "mongo/bool@1";
6
+ const MONGO_DATE_CODEC_ID = "mongo/date@1";
7
+ const MONGO_VECTOR_CODEC_ID = "mongo/vector@1";
8
+
9
+ //#endregion
10
+ export { MONGO_STRING_CODEC_ID as a, MONGO_OBJECTID_CODEC_ID as i, MONGO_DATE_CODEC_ID as n, MONGO_VECTOR_CODEC_ID as o, MONGO_INT32_CODEC_ID as r, MONGO_BOOLEAN_CODEC_ID as t };
11
+ //# sourceMappingURL=codec-ids-B-QSSwbW.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codec-ids-B-QSSwbW.mjs","names":[],"sources":["../src/core/codec-ids.ts"],"sourcesContent":["export const MONGO_OBJECTID_CODEC_ID = 'mongo/objectId@1' as const;\nexport const MONGO_STRING_CODEC_ID = 'mongo/string@1' as const;\nexport const MONGO_INT32_CODEC_ID = 'mongo/int32@1' as const;\nexport const MONGO_BOOLEAN_CODEC_ID = 'mongo/bool@1' as const;\nexport const MONGO_DATE_CODEC_ID = 'mongo/date@1' as const;\nexport const MONGO_VECTOR_CODEC_ID = 'mongo/vector@1' as const;\n"],"mappings":";AAAA,MAAa,0BAA0B;AACvC,MAAa,wBAAwB;AACrC,MAAa,uBAAuB;AACpC,MAAa,yBAAyB;AACtC,MAAa,sBAAsB;AACnC,MAAa,wBAAwB"}
@@ -1,4 +1,7 @@
1
1
  //#region src/exports/codec-types.d.ts
2
+ type Vector<N extends number = number> = readonly number[] & {
3
+ readonly __vectorLength?: N;
4
+ };
2
5
  type CodecTypes = {
3
6
  readonly 'mongo/objectId@1': {
4
7
  readonly input: string;
@@ -20,7 +23,11 @@ type CodecTypes = {
20
23
  readonly input: Date;
21
24
  readonly output: Date;
22
25
  };
26
+ readonly 'mongo/vector@1': {
27
+ readonly input: readonly number[];
28
+ readonly output: readonly number[];
29
+ };
23
30
  };
24
31
  //#endregion
25
- export { CodecTypes };
32
+ export { CodecTypes, Vector };
26
33
  //# sourceMappingURL=codec-types.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"codec-types.d.mts","names":[],"sources":["../src/exports/codec-types.ts"],"sourcesContent":[],"mappings":";KAAY,UAAA;EAAA,SAAA,kBAKiC,EAAA;;;;;;;;;;;;;;;;;oBAAA;qBAAuB"}
1
+ {"version":3,"file":"codec-types.d.mts","names":[],"sources":["../src/exports/codec-types.ts"],"sourcesContent":[],"mappings":";KAAY;EAAA,SAAM,cACW,CAAA,EAAD,CAAC;AAG7B,CAAA;KAAY,UAAA;;;;;;;;;;;;;;;;;;oBAKiC;qBAAuB"}
@@ -0,0 +1,7 @@
1
+ import { ControlAdapterDescriptor } from "@prisma-next/framework-components/control";
2
+
3
+ //#region src/exports/control.d.ts
4
+ declare const mongoAdapterDescriptor: ControlAdapterDescriptor<'mongo', 'mongo'>;
5
+ //#endregion
6
+ export { mongoAdapterDescriptor as default };
7
+ //# sourceMappingURL=control.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control.d.mts","names":[],"sources":["../src/exports/control.ts"],"sourcesContent":[],"mappings":";;;cAUM,wBAAwB"}
@@ -0,0 +1,102 @@
1
+ import { a as MONGO_STRING_CODEC_ID, i as MONGO_OBJECTID_CODEC_ID, n as MONGO_DATE_CODEC_ID, o as MONGO_VECTOR_CODEC_ID, r as MONGO_INT32_CODEC_ID, t as MONGO_BOOLEAN_CODEC_ID } from "./codec-ids-B-QSSwbW.mjs";
2
+ import { mongoCodec } from "@prisma-next/mongo-codec";
3
+ import { ObjectId } from "mongodb";
4
+
5
+ //#region src/core/codecs.ts
6
+ const mongoObjectIdCodec = mongoCodec({
7
+ typeId: MONGO_OBJECTID_CODEC_ID,
8
+ targetTypes: ["objectId"],
9
+ traits: ["equality"],
10
+ decode: (wire) => wire.toHexString(),
11
+ encode: (value) => new ObjectId(value)
12
+ });
13
+ const mongoStringCodec = mongoCodec({
14
+ typeId: MONGO_STRING_CODEC_ID,
15
+ targetTypes: ["string"],
16
+ traits: [
17
+ "equality",
18
+ "order",
19
+ "textual"
20
+ ],
21
+ decode: (wire) => wire,
22
+ encode: (value) => value
23
+ });
24
+ const mongoInt32Codec = mongoCodec({
25
+ typeId: MONGO_INT32_CODEC_ID,
26
+ targetTypes: ["int"],
27
+ traits: [
28
+ "equality",
29
+ "order",
30
+ "numeric"
31
+ ],
32
+ decode: (wire) => wire,
33
+ encode: (value) => value
34
+ });
35
+ const mongoBooleanCodec = mongoCodec({
36
+ typeId: MONGO_BOOLEAN_CODEC_ID,
37
+ targetTypes: ["bool"],
38
+ traits: ["equality", "boolean"],
39
+ decode: (wire) => wire,
40
+ encode: (value) => value
41
+ });
42
+ const mongoDateCodec = mongoCodec({
43
+ typeId: MONGO_DATE_CODEC_ID,
44
+ targetTypes: ["date"],
45
+ traits: ["equality", "order"],
46
+ decode: (wire) => wire,
47
+ encode: (value) => value
48
+ });
49
+ const mongoVectorCodec = mongoCodec({
50
+ typeId: MONGO_VECTOR_CODEC_ID,
51
+ targetTypes: ["vector"],
52
+ traits: ["equality"],
53
+ decode: (wire) => wire,
54
+ encode: (value) => value,
55
+ renderOutputType: (typeParams) => {
56
+ const length = typeParams["length"];
57
+ if (length === void 0) return void 0;
58
+ if (typeof length !== "number" || !Number.isFinite(length) || !Number.isInteger(length)) throw new Error("renderOutputType: expected positive integer \"length\" for Vector");
59
+ return `Vector<${length}>`;
60
+ }
61
+ });
62
+
63
+ //#endregion
64
+ //#region src/exports/control.ts
65
+ const mongoAdapterDescriptor = {
66
+ kind: "adapter",
67
+ id: "mongo",
68
+ familyId: "mongo",
69
+ targetId: "mongo",
70
+ version: "0.0.1",
71
+ types: { codecTypes: {
72
+ codecInstances: [
73
+ mongoObjectIdCodec,
74
+ mongoStringCodec,
75
+ mongoInt32Codec,
76
+ mongoBooleanCodec,
77
+ mongoDateCodec,
78
+ mongoVectorCodec
79
+ ],
80
+ import: {
81
+ package: "@prisma-next/adapter-mongo/codec-types",
82
+ named: "CodecTypes",
83
+ alias: "MongoCodecTypes"
84
+ },
85
+ typeImports: [{
86
+ package: "@prisma-next/adapter-mongo/codec-types",
87
+ named: "Vector",
88
+ alias: "Vector"
89
+ }]
90
+ } },
91
+ create() {
92
+ return {
93
+ familyId: "mongo",
94
+ targetId: "mongo"
95
+ };
96
+ }
97
+ };
98
+ var control_default = mongoAdapterDescriptor;
99
+
100
+ //#endregion
101
+ export { control_default as default };
102
+ //# sourceMappingURL=control.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control.mjs","names":["mongoAdapterDescriptor: ControlAdapterDescriptor<'mongo', 'mongo'>"],"sources":["../src/core/codecs.ts","../src/exports/control.ts"],"sourcesContent":["import { mongoCodec } from '@prisma-next/mongo-codec';\nimport { ObjectId } from 'mongodb';\nimport {\n MONGO_BOOLEAN_CODEC_ID,\n MONGO_DATE_CODEC_ID,\n MONGO_INT32_CODEC_ID,\n MONGO_OBJECTID_CODEC_ID,\n MONGO_STRING_CODEC_ID,\n MONGO_VECTOR_CODEC_ID,\n} from './codec-ids';\n\nexport const mongoObjectIdCodec = mongoCodec({\n typeId: MONGO_OBJECTID_CODEC_ID,\n targetTypes: ['objectId'],\n traits: ['equality'],\n decode: (wire: ObjectId) => wire.toHexString(),\n encode: (value: string) => new ObjectId(value),\n});\n\nexport const mongoStringCodec = mongoCodec({\n typeId: MONGO_STRING_CODEC_ID,\n targetTypes: ['string'],\n traits: ['equality', 'order', 'textual'],\n decode: (wire: string) => wire,\n encode: (value: string) => value,\n});\n\nexport const mongoInt32Codec = mongoCodec({\n typeId: MONGO_INT32_CODEC_ID,\n targetTypes: ['int'],\n traits: ['equality', 'order', 'numeric'],\n decode: (wire: number) => wire,\n encode: (value: number) => value,\n});\n\nexport const mongoBooleanCodec = mongoCodec({\n typeId: MONGO_BOOLEAN_CODEC_ID,\n targetTypes: ['bool'],\n traits: ['equality', 'boolean'],\n decode: (wire: boolean) => wire,\n encode: (value: boolean) => value,\n});\n\nexport const mongoDateCodec = mongoCodec({\n typeId: MONGO_DATE_CODEC_ID,\n targetTypes: ['date'],\n traits: ['equality', 'order'],\n decode: (wire: Date) => wire,\n encode: (value: Date) => value,\n});\n\nexport const mongoVectorCodec = mongoCodec({\n typeId: MONGO_VECTOR_CODEC_ID,\n targetTypes: ['vector'],\n traits: ['equality'],\n decode: (wire: readonly number[]) => wire,\n encode: (value: readonly number[]) => value,\n renderOutputType: (typeParams) => {\n const length = typeParams['length'];\n if (length === undefined) return undefined;\n if (typeof length !== 'number' || !Number.isFinite(length) || !Number.isInteger(length)) {\n throw new Error('renderOutputType: expected positive integer \"length\" for Vector');\n }\n return `Vector<${length}>`;\n },\n});\n","import type { ControlAdapterDescriptor } from '@prisma-next/framework-components/control';\nimport {\n mongoBooleanCodec,\n mongoDateCodec,\n mongoInt32Codec,\n mongoObjectIdCodec,\n mongoStringCodec,\n mongoVectorCodec,\n} from '../core/codecs';\n\nconst mongoAdapterDescriptor: ControlAdapterDescriptor<'mongo', 'mongo'> = {\n kind: 'adapter',\n id: 'mongo',\n familyId: 'mongo',\n targetId: 'mongo',\n version: '0.0.1',\n types: {\n codecTypes: {\n codecInstances: [\n mongoObjectIdCodec,\n mongoStringCodec,\n mongoInt32Codec,\n mongoBooleanCodec,\n mongoDateCodec,\n mongoVectorCodec,\n ],\n import: {\n package: '@prisma-next/adapter-mongo/codec-types',\n named: 'CodecTypes',\n alias: 'MongoCodecTypes',\n },\n typeImports: [\n {\n package: '@prisma-next/adapter-mongo/codec-types',\n named: 'Vector',\n alias: 'Vector',\n },\n ],\n },\n },\n create() {\n return { familyId: 'mongo' as const, targetId: 'mongo' as const };\n },\n};\n\nexport default mongoAdapterDescriptor;\n"],"mappings":";;;;;AAWA,MAAa,qBAAqB,WAAW;CAC3C,QAAQ;CACR,aAAa,CAAC,WAAW;CACzB,QAAQ,CAAC,WAAW;CACpB,SAAS,SAAmB,KAAK,aAAa;CAC9C,SAAS,UAAkB,IAAI,SAAS,MAAM;CAC/C,CAAC;AAEF,MAAa,mBAAmB,WAAW;CACzC,QAAQ;CACR,aAAa,CAAC,SAAS;CACvB,QAAQ;EAAC;EAAY;EAAS;EAAU;CACxC,SAAS,SAAiB;CAC1B,SAAS,UAAkB;CAC5B,CAAC;AAEF,MAAa,kBAAkB,WAAW;CACxC,QAAQ;CACR,aAAa,CAAC,MAAM;CACpB,QAAQ;EAAC;EAAY;EAAS;EAAU;CACxC,SAAS,SAAiB;CAC1B,SAAS,UAAkB;CAC5B,CAAC;AAEF,MAAa,oBAAoB,WAAW;CAC1C,QAAQ;CACR,aAAa,CAAC,OAAO;CACrB,QAAQ,CAAC,YAAY,UAAU;CAC/B,SAAS,SAAkB;CAC3B,SAAS,UAAmB;CAC7B,CAAC;AAEF,MAAa,iBAAiB,WAAW;CACvC,QAAQ;CACR,aAAa,CAAC,OAAO;CACrB,QAAQ,CAAC,YAAY,QAAQ;CAC7B,SAAS,SAAe;CACxB,SAAS,UAAgB;CAC1B,CAAC;AAEF,MAAa,mBAAmB,WAAW;CACzC,QAAQ;CACR,aAAa,CAAC,SAAS;CACvB,QAAQ,CAAC,WAAW;CACpB,SAAS,SAA4B;CACrC,SAAS,UAA6B;CACtC,mBAAmB,eAAe;EAChC,MAAM,SAAS,WAAW;AAC1B,MAAI,WAAW,OAAW,QAAO;AACjC,MAAI,OAAO,WAAW,YAAY,CAAC,OAAO,SAAS,OAAO,IAAI,CAAC,OAAO,UAAU,OAAO,CACrF,OAAM,IAAI,MAAM,oEAAkE;AAEpF,SAAO,UAAU,OAAO;;CAE3B,CAAC;;;;ACvDF,MAAMA,yBAAqE;CACzE,MAAM;CACN,IAAI;CACJ,UAAU;CACV,UAAU;CACV,SAAS;CACT,OAAO,EACL,YAAY;EACV,gBAAgB;GACd;GACA;GACA;GACA;GACA;GACA;GACD;EACD,QAAQ;GACN,SAAS;GACT,OAAO;GACP,OAAO;GACR;EACD,aAAa,CACX;GACE,SAAS;GACT,OAAO;GACP,OAAO;GACR,CACF;EACF,EACF;CACD,SAAS;AACP,SAAO;GAAE,UAAU;GAAkB,UAAU;GAAkB;;CAEpE;AAED,sBAAe"}
package/dist/index.d.mts CHANGED
@@ -1,7 +1,30 @@
1
- import { MongoAdapter } from "@prisma-next/mongo-core";
1
+ import { MongoAggExpr, MongoFilterExpr, MongoPipelineStage } from "@prisma-next/mongo-query-ast";
2
+ import { Document } from "@prisma-next/mongo-value";
3
+ import { OperationDescriptor } from "@prisma-next/operations";
4
+ import { MongoAdapter } from "@prisma-next/mongo-lowering";
2
5
 
6
+ //#region src/core/operations.d.ts
7
+ declare const mongoVectorNearOperation: Readonly<{
8
+ method: "near";
9
+ args: {
10
+ codecId: "mongo/vector@1";
11
+ nullable: boolean;
12
+ }[];
13
+ returns: {
14
+ codecId: "mongo/int32@1";
15
+ nullable: boolean;
16
+ };
17
+ }>;
18
+ declare const mongoVectorOperationDescriptors: readonly OperationDescriptor[];
19
+ //#endregion
20
+ //#region src/lowering.d.ts
21
+ declare function lowerAggExpr(expr: MongoAggExpr): unknown;
22
+ declare function lowerFilter(filter: MongoFilterExpr): Document;
23
+ declare function lowerStage(stage: MongoPipelineStage): Record<string, unknown>;
24
+ declare function lowerPipeline(stages: ReadonlyArray<MongoPipelineStage>): Array<Record<string, unknown>>;
25
+ //#endregion
3
26
  //#region src/mongo-adapter.d.ts
4
27
  declare function createMongoAdapter(): MongoAdapter;
5
28
  //#endregion
6
- export { createMongoAdapter };
29
+ export { createMongoAdapter, lowerAggExpr, lowerFilter, lowerPipeline, lowerStage, mongoVectorNearOperation, mongoVectorOperationDescriptors };
7
30
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/mongo-adapter.ts"],"sourcesContent":[],"mappings":";;;iBAsGgB,kBAAA,CAAA,GAAsB"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/core/operations.ts","../src/lowering.ts","../src/mongo-adapter.ts"],"sourcesContent":[],"mappings":";;;;;;cAGa,0BAAwB;;;;;EAAxB,CAAA,EAAA;EAMA,OAAA,EAAA;;;;AC6Hb,CAAA,CAAA;AAIgB,cDjIH,+BCiIyC,EAAA,SDjIC,mBCiIO,EAAA;;;iBAJ9C,YAAA,OAAmB;iBAInB,WAAA,SAAoB,kBAAkB;iBA8DtC,UAAA,QAAkB,qBAAqB;iBAqMvC,aAAA,SACN,cAAc,sBACrB,MAAM;;;iBC9RO,kBAAA,CAAA,GAAsB"}
package/dist/index.mjs CHANGED
@@ -1,52 +1,369 @@
1
- import { AggregateWireCommand, DeleteOneWireCommand, FindWireCommand, InsertOneWireCommand, MongoParamRef, UpdateOneWireCommand } from "@prisma-next/mongo-core";
1
+ import { o as MONGO_VECTOR_CODEC_ID, r as MONGO_INT32_CODEC_ID } from "./codec-ids-B-QSSwbW.mjs";
2
+ import { isExprArray, isRecordArgs } from "@prisma-next/mongo-query-ast";
3
+ import { MongoParamRef } from "@prisma-next/mongo-value";
4
+ import { AggregateWireCommand, DeleteManyWireCommand, DeleteOneWireCommand, FindOneAndDeleteWireCommand, FindOneAndUpdateWireCommand, InsertManyWireCommand, InsertOneWireCommand, UpdateManyWireCommand, UpdateOneWireCommand } from "@prisma-next/mongo-wire";
2
5
 
6
+ //#region src/core/operations.ts
7
+ const mongoVectorNearOperation = Object.freeze({
8
+ method: "near",
9
+ args: [{
10
+ codecId: MONGO_VECTOR_CODEC_ID,
11
+ nullable: false
12
+ }],
13
+ returns: {
14
+ codecId: MONGO_INT32_CODEC_ID,
15
+ nullable: false
16
+ }
17
+ });
18
+ const mongoVectorOperationDescriptors = [mongoVectorNearOperation];
19
+
20
+ //#endregion
21
+ //#region src/resolve-value.ts
22
+ function resolveValue(value) {
23
+ if (value instanceof MongoParamRef) return value.value;
24
+ if (value === null || typeof value !== "object") return value;
25
+ if (value instanceof Date) return value;
26
+ if (Array.isArray(value)) return value.map((v) => resolveValue(v));
27
+ const result = {};
28
+ for (const [key, val] of Object.entries(value)) result[key] = resolveValue(val);
29
+ return result;
30
+ }
31
+
32
+ //#endregion
33
+ //#region src/lowering.ts
34
+ const THEN_KEY = "then";
35
+ function condBranch(caseOrIf, thenExpr, elseExpr) {
36
+ const entries = [[elseExpr ? "if" : "case", lowerAggExpr(caseOrIf)], [THEN_KEY, lowerAggExpr(thenExpr)]];
37
+ if (elseExpr) entries.push(["else", lowerAggExpr(elseExpr)]);
38
+ return Object.fromEntries(entries);
39
+ }
40
+ const aggExprLoweringVisitor = {
41
+ fieldRef(expr) {
42
+ return `$${expr.path}`;
43
+ },
44
+ literal(expr) {
45
+ return needsLiteralWrap(expr.value) ? { $literal: expr.value } : expr.value;
46
+ },
47
+ operator(expr) {
48
+ const { args } = expr;
49
+ let loweredArgs;
50
+ if (isExprArray(args)) loweredArgs = args.map((a) => lowerAggExpr(a));
51
+ else if (isRecordArgs(args)) loweredArgs = lowerExprRecord(args);
52
+ else loweredArgs = lowerAggExpr(args);
53
+ return { [expr.op]: loweredArgs };
54
+ },
55
+ accumulator(expr) {
56
+ if (expr.arg === null) return { [expr.op]: {} };
57
+ if (isRecordArgs(expr.arg)) return { [expr.op]: lowerExprRecord(expr.arg) };
58
+ return { [expr.op]: lowerAggExpr(expr.arg) };
59
+ },
60
+ cond(expr) {
61
+ return { $cond: condBranch(expr.condition, expr.then_, expr.else_) };
62
+ },
63
+ switch_(expr) {
64
+ return { $switch: {
65
+ branches: expr.branches.map((b) => condBranch(b.case_, b.then_)),
66
+ default: lowerAggExpr(expr.default_)
67
+ } };
68
+ },
69
+ filter(expr) {
70
+ return { $filter: {
71
+ input: lowerAggExpr(expr.input),
72
+ cond: lowerAggExpr(expr.cond),
73
+ as: expr.as
74
+ } };
75
+ },
76
+ map(expr) {
77
+ return { $map: {
78
+ input: lowerAggExpr(expr.input),
79
+ in: lowerAggExpr(expr.in_),
80
+ as: expr.as
81
+ } };
82
+ },
83
+ reduce(expr) {
84
+ return { $reduce: {
85
+ input: lowerAggExpr(expr.input),
86
+ initialValue: lowerAggExpr(expr.initialValue),
87
+ in: lowerAggExpr(expr.in_)
88
+ } };
89
+ },
90
+ let_(expr) {
91
+ const vars = {};
92
+ for (const [key, val] of Object.entries(expr.vars)) vars[key] = lowerAggExpr(val);
93
+ return { $let: {
94
+ vars,
95
+ in: lowerAggExpr(expr.in_)
96
+ } };
97
+ },
98
+ mergeObjects(expr) {
99
+ return { $mergeObjects: expr.exprs.map((e) => lowerAggExpr(e)) };
100
+ }
101
+ };
102
+ function needsLiteralWrap(value) {
103
+ if (typeof value === "string" && value.startsWith("$")) return true;
104
+ if (Array.isArray(value)) return value.some((v) => needsLiteralWrap(v));
105
+ if (value !== null && typeof value === "object") return Object.entries(value).some(([k, v]) => k.startsWith("$") || needsLiteralWrap(v));
106
+ return false;
107
+ }
108
+ function lowerAggExpr(expr) {
109
+ return expr.accept(aggExprLoweringVisitor);
110
+ }
111
+ function lowerFilter(filter) {
112
+ switch (filter.kind) {
113
+ case "field": return { [filter.field]: { [filter.op]: resolveValue(filter.value) } };
114
+ case "and": return { $and: filter.exprs.map((e) => lowerFilter(e)) };
115
+ case "or": return { $or: filter.exprs.map((e) => lowerFilter(e)) };
116
+ case "not": return { $nor: [lowerFilter(filter.expr)] };
117
+ case "exists": return { [filter.field]: { $exists: filter.exists } };
118
+ case "expr": return { $expr: lowerAggExpr(filter.aggExpr) };
119
+ default: {
120
+ const _exhaustive = filter;
121
+ throw new Error(`Unhandled filter kind: ${_exhaustive.kind}`);
122
+ }
123
+ }
124
+ }
125
+ function isAggExprNode(value) {
126
+ return "accept" in value && typeof value.accept === "function";
127
+ }
128
+ function lowerGroupId(groupId) {
129
+ if (groupId === null) return null;
130
+ if (isAggExprNode(groupId)) return lowerAggExpr(groupId);
131
+ return lowerExprRecord(groupId);
132
+ }
133
+ function lowerExprRecord(fields) {
134
+ const result = {};
135
+ for (const [key, val] of Object.entries(fields)) if (Array.isArray(val)) result[key] = val.map((v) => lowerAggExpr(v));
136
+ else result[key] = lowerAggExpr(val);
137
+ return result;
138
+ }
139
+ function lowerProjectionValue(value) {
140
+ if (typeof value === "number") return value;
141
+ return lowerAggExpr(value);
142
+ }
143
+ function lowerWindowField(wf) {
144
+ const lowered = lowerAggExpr(wf.operator);
145
+ if (typeof lowered !== "object" || lowered === null) throw new Error("Window field operator must lower to an object");
146
+ const result = { ...lowered };
147
+ if (wf.window) result["window"] = { ...wf.window };
148
+ return result;
149
+ }
150
+ function lowerStage(stage) {
151
+ switch (stage.kind) {
152
+ case "match": return { $match: lowerFilter(stage.filter) };
153
+ case "project": {
154
+ const projection = {};
155
+ for (const [key, val] of Object.entries(stage.projection)) projection[key] = lowerProjectionValue(val);
156
+ return { $project: projection };
157
+ }
158
+ case "sort": return { $sort: { ...stage.sort } };
159
+ case "limit": return { $limit: stage.limit };
160
+ case "skip": return { $skip: stage.skip };
161
+ case "lookup": {
162
+ const lookup = {
163
+ from: stage.from,
164
+ as: stage.as
165
+ };
166
+ if (stage.localField !== void 0) lookup["localField"] = stage.localField;
167
+ if (stage.foreignField !== void 0) lookup["foreignField"] = stage.foreignField;
168
+ if (stage.pipeline) lookup["pipeline"] = stage.pipeline.map((s) => lowerStage(s));
169
+ if (stage.let_) lookup["let"] = lowerExprRecord(stage.let_);
170
+ return { $lookup: lookup };
171
+ }
172
+ case "unwind": {
173
+ const unwind = {
174
+ path: stage.path,
175
+ preserveNullAndEmptyArrays: stage.preserveNullAndEmptyArrays
176
+ };
177
+ if (stage.includeArrayIndex !== void 0) unwind["includeArrayIndex"] = stage.includeArrayIndex;
178
+ return { $unwind: unwind };
179
+ }
180
+ case "group": {
181
+ const group = { _id: lowerGroupId(stage.groupId) };
182
+ for (const [key, acc] of Object.entries(stage.accumulators)) group[key] = lowerAggExpr(acc);
183
+ return { $group: group };
184
+ }
185
+ case "addFields": return { $addFields: lowerExprRecord(stage.fields) };
186
+ case "replaceRoot": return { $replaceRoot: { newRoot: lowerAggExpr(stage.newRoot) } };
187
+ case "count": return { $count: stage.field };
188
+ case "sortByCount": return { $sortByCount: lowerAggExpr(stage.expr) };
189
+ case "sample": return { $sample: { size: stage.size } };
190
+ case "redact": return { $redact: lowerAggExpr(stage.expr) };
191
+ case "out": return { $out: stage.db ? {
192
+ db: stage.db,
193
+ coll: stage.collection
194
+ } : stage.collection };
195
+ case "unionWith": {
196
+ const unionWith = { coll: stage.collection };
197
+ if (stage.pipeline) unionWith["pipeline"] = stage.pipeline.map((s) => lowerStage(s));
198
+ return { $unionWith: unionWith };
199
+ }
200
+ case "bucket": {
201
+ const bucket = {
202
+ groupBy: lowerAggExpr(stage.groupBy),
203
+ boundaries: [...stage.boundaries]
204
+ };
205
+ if (stage.default_ !== void 0) bucket["default"] = stage.default_;
206
+ if (stage.output) bucket["output"] = lowerExprRecord(stage.output);
207
+ return { $bucket: bucket };
208
+ }
209
+ case "bucketAuto": {
210
+ const bucketAuto = {
211
+ groupBy: lowerAggExpr(stage.groupBy),
212
+ buckets: stage.buckets
213
+ };
214
+ if (stage.output) bucketAuto["output"] = lowerExprRecord(stage.output);
215
+ if (stage.granularity !== void 0) bucketAuto["granularity"] = stage.granularity;
216
+ return { $bucketAuto: bucketAuto };
217
+ }
218
+ case "geoNear": {
219
+ const geoNear = {
220
+ near: stage.near,
221
+ distanceField: stage.distanceField
222
+ };
223
+ if (stage.spherical !== void 0) geoNear["spherical"] = stage.spherical;
224
+ if (stage.maxDistance !== void 0) geoNear["maxDistance"] = stage.maxDistance;
225
+ if (stage.minDistance !== void 0) geoNear["minDistance"] = stage.minDistance;
226
+ if (stage.query) geoNear["query"] = lowerFilter(stage.query);
227
+ if (stage.key !== void 0) geoNear["key"] = stage.key;
228
+ if (stage.distanceMultiplier !== void 0) geoNear["distanceMultiplier"] = stage.distanceMultiplier;
229
+ if (stage.includeLocs !== void 0) geoNear["includeLocs"] = stage.includeLocs;
230
+ return { $geoNear: geoNear };
231
+ }
232
+ case "facet": {
233
+ const facet = {};
234
+ for (const [key, pipeline] of Object.entries(stage.facets)) facet[key] = pipeline.map((s) => lowerStage(s));
235
+ return { $facet: facet };
236
+ }
237
+ case "graphLookup": {
238
+ const graphLookup = {
239
+ from: stage.from,
240
+ startWith: lowerAggExpr(stage.startWith),
241
+ connectFromField: stage.connectFromField,
242
+ connectToField: stage.connectToField,
243
+ as: stage.as
244
+ };
245
+ if (stage.maxDepth !== void 0) graphLookup["maxDepth"] = stage.maxDepth;
246
+ if (stage.depthField !== void 0) graphLookup["depthField"] = stage.depthField;
247
+ if (stage.restrictSearchWithMatch) graphLookup["restrictSearchWithMatch"] = lowerFilter(stage.restrictSearchWithMatch);
248
+ return { $graphLookup: graphLookup };
249
+ }
250
+ case "merge": {
251
+ const merge = { into: stage.into };
252
+ if (stage.on !== void 0) merge["on"] = stage.on;
253
+ if (stage.whenMatched !== void 0) merge["whenMatched"] = Array.isArray(stage.whenMatched) ? stage.whenMatched.map((s) => lowerStage(s)) : stage.whenMatched;
254
+ if (stage.whenNotMatched !== void 0) merge["whenNotMatched"] = stage.whenNotMatched;
255
+ return { $merge: merge };
256
+ }
257
+ case "setWindowFields": {
258
+ const swf = {};
259
+ if (stage.partitionBy) swf["partitionBy"] = lowerAggExpr(stage.partitionBy);
260
+ if (stage.sortBy) swf["sortBy"] = { ...stage.sortBy };
261
+ const output = {};
262
+ for (const [key, wf] of Object.entries(stage.output)) output[key] = lowerWindowField(wf);
263
+ swf["output"] = output;
264
+ return { $setWindowFields: swf };
265
+ }
266
+ case "densify": {
267
+ const densify = {
268
+ field: stage.field,
269
+ range: { ...stage.range }
270
+ };
271
+ if (stage.partitionByFields) densify["partitionByFields"] = [...stage.partitionByFields];
272
+ return { $densify: densify };
273
+ }
274
+ case "fill": {
275
+ const fill = {};
276
+ if (stage.partitionBy) fill["partitionBy"] = lowerAggExpr(stage.partitionBy);
277
+ if (stage.partitionByFields) fill["partitionByFields"] = [...stage.partitionByFields];
278
+ if (stage.sortBy) fill["sortBy"] = { ...stage.sortBy };
279
+ const output = {};
280
+ for (const [key, fo] of Object.entries(stage.output)) {
281
+ const entry = {};
282
+ if (fo.method !== void 0) entry["method"] = fo.method;
283
+ if (fo.value !== void 0) entry["value"] = lowerAggExpr(fo.value);
284
+ output[key] = entry;
285
+ }
286
+ fill["output"] = output;
287
+ return { $fill: fill };
288
+ }
289
+ case "search": {
290
+ const search = { ...stage.config };
291
+ if (stage.index !== void 0) search["index"] = stage.index;
292
+ return { $search: search };
293
+ }
294
+ case "searchMeta": {
295
+ const searchMeta = { ...stage.config };
296
+ if (stage.index !== void 0) searchMeta["index"] = stage.index;
297
+ return { $searchMeta: searchMeta };
298
+ }
299
+ case "vectorSearch": {
300
+ const vs = {
301
+ index: stage.index,
302
+ path: stage.path,
303
+ queryVector: [...stage.queryVector],
304
+ numCandidates: stage.numCandidates,
305
+ limit: stage.limit
306
+ };
307
+ if (stage.filter) vs["filter"] = { ...stage.filter };
308
+ return { $vectorSearch: vs };
309
+ }
310
+ default: {
311
+ const _exhaustive = stage;
312
+ throw new Error(`Unhandled stage kind: ${_exhaustive.kind}`);
313
+ }
314
+ }
315
+ }
316
+ function lowerPipeline(stages) {
317
+ return stages.map(lowerStage);
318
+ }
319
+
320
+ //#endregion
3
321
  //#region src/mongo-adapter.ts
322
+ function resolveDocument(expr) {
323
+ const result = {};
324
+ for (const [key, val] of Object.entries(expr)) result[key] = resolveValue(val);
325
+ return result;
326
+ }
327
+ function isUpdatePipeline(update) {
328
+ return Array.isArray(update);
329
+ }
330
+ function lowerUpdate(update) {
331
+ if (isUpdatePipeline(update)) return update.map((stage) => lowerStage(stage));
332
+ return resolveDocument(update);
333
+ }
4
334
  var MongoAdapterImpl = class {
5
- lower(queryPlan, _context) {
6
- const wireCommand = this.#lowerCommand(queryPlan.command);
7
- return Object.freeze({
8
- wireCommand,
9
- command: queryPlan.command,
10
- meta: queryPlan.meta
11
- });
12
- }
13
- #lowerCommand(command) {
335
+ lower(plan) {
336
+ const { command } = plan;
14
337
  switch (command.kind) {
15
- case "find": {
16
- const options = {};
17
- if (command.projection) options.projection = { ...command.projection };
18
- if (command.sort) options.sort = { ...command.sort };
19
- if (command.limit !== void 0) options.limit = command.limit;
20
- if (command.skip !== void 0) options.skip = command.skip;
21
- return new FindWireCommand(command.collection, command.filter ? this.#resolveDocument(command.filter) : void 0, options);
22
- }
23
- case "insertOne": return new InsertOneWireCommand(command.collection, this.#resolveDocument(command.document));
24
- case "updateOne": return new UpdateOneWireCommand(command.collection, this.#resolveDocument(command.filter), this.#resolveDocument(command.update));
25
- case "deleteOne": return new DeleteOneWireCommand(command.collection, this.#resolveDocument(command.filter));
26
- case "aggregate": return new AggregateWireCommand(command.collection, command.pipeline.map((stage) => ({ ...stage })));
338
+ case "insertOne": return new InsertOneWireCommand(command.collection, resolveDocument(command.document));
339
+ case "updateOne": return new UpdateOneWireCommand(command.collection, lowerFilter(command.filter), lowerUpdate(command.update));
340
+ case "insertMany": return new InsertManyWireCommand(command.collection, command.documents.map((doc) => resolveDocument(doc)));
341
+ case "updateMany": return new UpdateManyWireCommand(command.collection, lowerFilter(command.filter), lowerUpdate(command.update));
342
+ case "deleteOne": return new DeleteOneWireCommand(command.collection, lowerFilter(command.filter));
343
+ case "deleteMany": return new DeleteManyWireCommand(command.collection, lowerFilter(command.filter));
344
+ case "findOneAndUpdate": return new FindOneAndUpdateWireCommand(command.collection, lowerFilter(command.filter), lowerUpdate(command.update), command.upsert);
345
+ case "findOneAndDelete": return new FindOneAndDeleteWireCommand(command.collection, lowerFilter(command.filter));
346
+ case "aggregate": return new AggregateWireCommand(command.collection, lowerPipeline(command.pipeline));
347
+ case "rawAggregate": return new AggregateWireCommand(command.collection, command.pipeline);
348
+ case "rawInsertOne": return new InsertOneWireCommand(command.collection, command.document);
349
+ case "rawInsertMany": return new InsertManyWireCommand(command.collection, command.documents);
350
+ case "rawUpdateOne": return new UpdateOneWireCommand(command.collection, command.filter, command.update);
351
+ case "rawUpdateMany": return new UpdateManyWireCommand(command.collection, command.filter, command.update);
352
+ case "rawDeleteOne": return new DeleteOneWireCommand(command.collection, command.filter);
353
+ case "rawDeleteMany": return new DeleteManyWireCommand(command.collection, command.filter);
354
+ case "rawFindOneAndUpdate": return new FindOneAndUpdateWireCommand(command.collection, command.filter, command.update, command.upsert);
355
+ case "rawFindOneAndDelete": return new FindOneAndDeleteWireCommand(command.collection, command.filter);
27
356
  default: {
28
357
  const _exhaustive = command;
29
358
  throw new Error(`Unknown command kind: ${_exhaustive.kind}`);
30
359
  }
31
360
  }
32
361
  }
33
- #resolveValue(value) {
34
- if (value instanceof MongoParamRef) return value.value;
35
- if (value === null || typeof value !== "object") return value;
36
- if (value instanceof Date) return value;
37
- if (Array.isArray(value)) return value.map((v) => this.#resolveValue(v));
38
- return this.#resolveDocument(value);
39
- }
40
- #resolveDocument(expr) {
41
- const result = {};
42
- for (const [key, val] of Object.entries(expr)) result[key] = this.#resolveValue(val);
43
- return result;
44
- }
45
362
  };
46
363
  function createMongoAdapter() {
47
364
  return new MongoAdapterImpl();
48
365
  }
49
366
 
50
367
  //#endregion
51
- export { createMongoAdapter };
368
+ export { createMongoAdapter, lowerAggExpr, lowerFilter, lowerPipeline, lowerStage, mongoVectorNearOperation, mongoVectorOperationDescriptors };
52
369
  //# sourceMappingURL=index.mjs.map