@prisma-next/adapter-mongo 0.11.0 → 0.12.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.
@@ -1,4 +1,5 @@
1
1
  import { isExprArray, isRecordArgs } from "@prisma-next/mongo-query-ast/execution";
2
+ import { blindCast } from "@prisma-next/utils/casts";
2
3
  import { checkAborted, raceAgainstAbort, runtimeError } from "@prisma-next/framework-components/runtime";
3
4
  import { MongoParamRef } from "@prisma-next/mongo-value";
4
5
  import { AggregateWireCommand, DeleteManyWireCommand, DeleteOneWireCommand, FindOneAndDeleteWireCommand, FindOneAndUpdateWireCommand, InsertManyWireCommand, InsertOneWireCommand, UpdateManyWireCommand, UpdateOneWireCommand } from "@prisma-next/mongo-wire";
@@ -73,11 +74,46 @@ async function resolveValue(value, codecs, ctx) {
73
74
  }
74
75
  return result;
75
76
  }
77
+ /**
78
+ * Resolves a draft slot value — which may be `MongoParamRef`, a primitive, a
79
+ * nested plain-object, or an array — into the corresponding wire value.
80
+ * Mirrors `resolveValue`'s traversal strategy but accepts `unknown` so it can
81
+ * handle pipeline stage documents whose field types cannot be narrowed to
82
+ * `MongoValue` statically (e.g. `$geoNear.near: unknown`).
83
+ */
84
+ async function resolveDraftSlot(value, codecs, ctx) {
85
+ if (value instanceof MongoParamRef) return resolveValue(value, codecs, ctx);
86
+ if (value === null || typeof value !== "object") return value;
87
+ if (value instanceof Date) return value;
88
+ if (Array.isArray(value)) return raceAgainstAbort(Promise.all(value.map((v) => resolveDraftSlot(v, codecs, ctx))), ctx.signal, "encode");
89
+ return resolveDraftDoc(blindCast(value), codecs, ctx);
90
+ }
91
+ /**
92
+ * Resolves a pipeline stage draft document by walking every entry and
93
+ * forwarding to {@link resolveDraftSlot}. Used by `MongoAdapterImpl.resolveParams`
94
+ * for aggregate pipeline stages, which carry `unknown`-typed fields (e.g.
95
+ * `$geoNear.near`) alongside filter sub-documents that may contain
96
+ * `MongoParamRef` leaves.
97
+ */
98
+ async function resolveDraftDoc(doc, codecs, ctx) {
99
+ checkAborted(ctx, "encode");
100
+ const entries = Object.entries(doc);
101
+ const resolved = await raceAgainstAbort(Promise.all(entries.map(([, val]) => resolveDraftSlot(val, codecs, ctx))), ctx.signal, "encode");
102
+ const result = {};
103
+ for (let i = 0; i < entries.length; i++) {
104
+ const entry = entries[i];
105
+ if (entry) result[entry[0]] = resolved[i];
106
+ }
107
+ return result;
108
+ }
76
109
  function paramRefLabel(ref, codecId) {
77
110
  return ref.name ?? codecId;
78
111
  }
112
+ function isErrorWithCode(error) {
113
+ return error instanceof Error && "code" in error;
114
+ }
79
115
  function isAlreadyEncodeFailure(error) {
80
- return error instanceof Error && "code" in error && error.code === "RUNTIME.ENCODE_FAILED";
116
+ return isErrorWithCode(error) && error.code === "RUNTIME.ENCODE_FAILED";
81
117
  }
82
118
  function wrapEncodeFailure(error, ref, codecId) {
83
119
  if (isAlreadyEncodeFailure(error)) throw error;
@@ -168,6 +204,24 @@ function needsLiteralWrap(value) {
168
204
  function lowerAggExpr(expr) {
169
205
  return expr.accept(aggExprLoweringVisitor);
170
206
  }
207
+ /**
208
+ * Structural phase of filter lowering: transforms the filter AST into a
209
+ * plain object without resolving any `MongoParamRef` leaves. Field filter
210
+ * values remain as `MongoValue` (which includes `MongoParamRef`), so the
211
+ * returned document can be passed to `resolveDraftDoc` in the resolve phase.
212
+ * Synchronous — no codec calls.
213
+ */
214
+ function structuralLowerFilter(filter) {
215
+ switch (filter.kind) {
216
+ case "field": return { [filter.field]: { [filter.op]: filter.value } };
217
+ case "and": return { $and: filter.exprs.map((e) => structuralLowerFilter(e)) };
218
+ case "or": return { $or: filter.exprs.map((e) => structuralLowerFilter(e)) };
219
+ case "not": return { $nor: [structuralLowerFilter(filter.expr)] };
220
+ case "exists": return { [filter.field]: { $exists: filter.exists } };
221
+ case "expr": return { $expr: lowerAggExpr(filter.aggExpr) };
222
+ default: throw new Error(`Unhandled filter kind: ${blindCast(filter).kind}`);
223
+ }
224
+ }
171
225
  async function lowerFilter(filter, codecs, ctx) {
172
226
  switch (filter.kind) {
173
227
  case "field": return { [filter.field]: { [filter.op]: await resolveValue(filter.value, codecs, ctx) } };
@@ -176,12 +230,15 @@ async function lowerFilter(filter, codecs, ctx) {
176
230
  case "not": return { $nor: [await lowerFilter(filter.expr, codecs, ctx)] };
177
231
  case "exists": return { [filter.field]: { $exists: filter.exists } };
178
232
  case "expr": return { $expr: lowerAggExpr(filter.aggExpr) };
179
- default: throw new Error(`Unhandled filter kind: ${filter.kind}`);
233
+ default: throw new Error(`Unhandled filter kind: ${blindCast(filter).kind}`);
180
234
  }
181
235
  }
182
236
  function isAggExprNode(value) {
183
237
  return "accept" in value && typeof value.accept === "function";
184
238
  }
239
+ function isAggExprArray(val) {
240
+ return Array.isArray(val);
241
+ }
185
242
  function lowerGroupId(groupId) {
186
243
  if (groupId === null) return null;
187
244
  if (isAggExprNode(groupId)) return lowerAggExpr(groupId);
@@ -189,7 +246,7 @@ function lowerGroupId(groupId) {
189
246
  }
190
247
  function lowerExprRecord(fields) {
191
248
  const result = {};
192
- for (const [key, val] of Object.entries(fields)) if (Array.isArray(val)) result[key] = val.map((v) => lowerAggExpr(v));
249
+ for (const [key, val] of Object.entries(fields)) if (isAggExprArray(val)) result[key] = val.map((v) => lowerAggExpr(v));
193
250
  else result[key] = lowerAggExpr(val);
194
251
  return result;
195
252
  }
@@ -369,12 +426,186 @@ async function lowerStage(stage, codecs, ctx) {
369
426
  if (stage.filter) vs["filter"] = { ...stage.filter };
370
427
  return { $vectorSearch: vs };
371
428
  }
372
- default: throw new Error(`Unhandled stage kind: ${stage.kind}`);
429
+ default: throw new Error(`Unhandled stage kind: ${blindCast(stage).kind}`);
373
430
  }
374
431
  }
375
432
  async function lowerPipeline(stages, codecs, ctx) {
376
433
  return Promise.all(stages.map((s) => lowerStage(s, codecs, ctx)));
377
434
  }
435
+ /**
436
+ * Structural phase of stage lowering: mirrors `lowerStage` but defers all
437
+ * `MongoParamRef` resolution. Filter sub-documents within stages (e.g.
438
+ * `$match`, `$geoNear.query`, `$graphLookup.restrictSearchWithMatch`) are
439
+ * produced by `structuralLowerFilter` and therefore retain `MongoParamRef`
440
+ * leaves. Sub-pipelines (e.g. `$lookup.pipeline`, `$facet.*`) recurse via
441
+ * `structuralLowerPipeline`. Synchronous — no codec calls.
442
+ */
443
+ function structuralLowerStage(stage) {
444
+ switch (stage.kind) {
445
+ case "match": return { $match: structuralLowerFilter(stage.filter) };
446
+ case "project": {
447
+ const projection = {};
448
+ for (const [key, val] of Object.entries(stage.projection)) projection[key] = lowerProjectionValue(val);
449
+ return { $project: projection };
450
+ }
451
+ case "sort": return { $sort: { ...stage.sort } };
452
+ case "limit": return { $limit: stage.limit };
453
+ case "skip": return { $skip: stage.skip };
454
+ case "lookup": {
455
+ const lookup = {
456
+ from: stage.from,
457
+ as: stage.as
458
+ };
459
+ if (stage.localField !== void 0) lookup["localField"] = stage.localField;
460
+ if (stage.foreignField !== void 0) lookup["foreignField"] = stage.foreignField;
461
+ if (stage.pipeline) lookup["pipeline"] = structuralLowerPipeline(stage.pipeline);
462
+ if (stage.let_) lookup["let"] = lowerExprRecord(stage.let_);
463
+ return { $lookup: lookup };
464
+ }
465
+ case "unwind": {
466
+ const unwind = {
467
+ path: stage.path,
468
+ preserveNullAndEmptyArrays: stage.preserveNullAndEmptyArrays
469
+ };
470
+ if (stage.includeArrayIndex !== void 0) unwind["includeArrayIndex"] = stage.includeArrayIndex;
471
+ return { $unwind: unwind };
472
+ }
473
+ case "group": {
474
+ const group = { _id: lowerGroupId(stage.groupId) };
475
+ for (const [key, acc] of Object.entries(stage.accumulators)) group[key] = lowerAggExpr(acc);
476
+ return { $group: group };
477
+ }
478
+ case "addFields": return { $addFields: lowerExprRecord(stage.fields) };
479
+ case "replaceRoot": return { $replaceRoot: { newRoot: lowerAggExpr(stage.newRoot) } };
480
+ case "count": return { $count: stage.field };
481
+ case "sortByCount": return { $sortByCount: lowerAggExpr(stage.expr) };
482
+ case "sample": return { $sample: { size: stage.size } };
483
+ case "redact": return { $redact: lowerAggExpr(stage.expr) };
484
+ case "out": return { $out: stage.db ? {
485
+ db: stage.db,
486
+ coll: stage.collection
487
+ } : stage.collection };
488
+ case "unionWith": {
489
+ const unionWith = { coll: stage.collection };
490
+ if (stage.pipeline) unionWith["pipeline"] = structuralLowerPipeline(stage.pipeline);
491
+ return { $unionWith: unionWith };
492
+ }
493
+ case "bucket": {
494
+ const bucket = {
495
+ groupBy: lowerAggExpr(stage.groupBy),
496
+ boundaries: [...stage.boundaries]
497
+ };
498
+ if (stage.default_ !== void 0) bucket["default"] = stage.default_;
499
+ if (stage.output) bucket["output"] = lowerExprRecord(stage.output);
500
+ return { $bucket: bucket };
501
+ }
502
+ case "bucketAuto": {
503
+ const bucketAuto = {
504
+ groupBy: lowerAggExpr(stage.groupBy),
505
+ buckets: stage.buckets
506
+ };
507
+ if (stage.output) bucketAuto["output"] = lowerExprRecord(stage.output);
508
+ if (stage.granularity !== void 0) bucketAuto["granularity"] = stage.granularity;
509
+ return { $bucketAuto: bucketAuto };
510
+ }
511
+ case "geoNear": {
512
+ const geoNear = {
513
+ near: stage.near,
514
+ distanceField: stage.distanceField
515
+ };
516
+ if (stage.spherical !== void 0) geoNear["spherical"] = stage.spherical;
517
+ if (stage.maxDistance !== void 0) geoNear["maxDistance"] = stage.maxDistance;
518
+ if (stage.minDistance !== void 0) geoNear["minDistance"] = stage.minDistance;
519
+ if (stage.query) geoNear["query"] = structuralLowerFilter(stage.query);
520
+ if (stage.key !== void 0) geoNear["key"] = stage.key;
521
+ if (stage.distanceMultiplier !== void 0) geoNear["distanceMultiplier"] = stage.distanceMultiplier;
522
+ if (stage.includeLocs !== void 0) geoNear["includeLocs"] = stage.includeLocs;
523
+ return { $geoNear: geoNear };
524
+ }
525
+ case "facet": {
526
+ const facet = {};
527
+ for (const [key, pipeline] of Object.entries(stage.facets)) facet[key] = structuralLowerPipeline(pipeline);
528
+ return { $facet: facet };
529
+ }
530
+ case "graphLookup": {
531
+ const graphLookup = {
532
+ from: stage.from,
533
+ startWith: lowerAggExpr(stage.startWith),
534
+ connectFromField: stage.connectFromField,
535
+ connectToField: stage.connectToField,
536
+ as: stage.as
537
+ };
538
+ if (stage.maxDepth !== void 0) graphLookup["maxDepth"] = stage.maxDepth;
539
+ if (stage.depthField !== void 0) graphLookup["depthField"] = stage.depthField;
540
+ if (stage.restrictSearchWithMatch) graphLookup["restrictSearchWithMatch"] = structuralLowerFilter(stage.restrictSearchWithMatch);
541
+ return { $graphLookup: graphLookup };
542
+ }
543
+ case "merge": {
544
+ const merge = { into: stage.into };
545
+ if (stage.on !== void 0) merge["on"] = stage.on;
546
+ if (stage.whenMatched !== void 0) merge["whenMatched"] = Array.isArray(stage.whenMatched) ? structuralLowerPipeline(stage.whenMatched) : stage.whenMatched;
547
+ if (stage.whenNotMatched !== void 0) merge["whenNotMatched"] = stage.whenNotMatched;
548
+ return { $merge: merge };
549
+ }
550
+ case "setWindowFields": {
551
+ const swf = {};
552
+ if (stage.partitionBy) swf["partitionBy"] = lowerAggExpr(stage.partitionBy);
553
+ if (stage.sortBy) swf["sortBy"] = { ...stage.sortBy };
554
+ const output = {};
555
+ for (const [key, wf] of Object.entries(stage.output)) output[key] = lowerWindowField(wf);
556
+ swf["output"] = output;
557
+ return { $setWindowFields: swf };
558
+ }
559
+ case "densify": {
560
+ const densify = {
561
+ field: stage.field,
562
+ range: { ...stage.range }
563
+ };
564
+ if (stage.partitionByFields) densify["partitionByFields"] = [...stage.partitionByFields];
565
+ return { $densify: densify };
566
+ }
567
+ case "fill": {
568
+ const fill = {};
569
+ if (stage.partitionBy) fill["partitionBy"] = lowerAggExpr(stage.partitionBy);
570
+ if (stage.partitionByFields) fill["partitionByFields"] = [...stage.partitionByFields];
571
+ if (stage.sortBy) fill["sortBy"] = { ...stage.sortBy };
572
+ const output = {};
573
+ for (const [key, fo] of Object.entries(stage.output)) {
574
+ const entry = {};
575
+ if (fo.method !== void 0) entry["method"] = fo.method;
576
+ if (fo.value !== void 0) entry["value"] = lowerAggExpr(fo.value);
577
+ output[key] = entry;
578
+ }
579
+ fill["output"] = output;
580
+ return { $fill: fill };
581
+ }
582
+ case "search": {
583
+ const search = { ...stage.config };
584
+ if (stage.index !== void 0) search["index"] = stage.index;
585
+ return { $search: search };
586
+ }
587
+ case "searchMeta": {
588
+ const searchMeta = { ...stage.config };
589
+ if (stage.index !== void 0) searchMeta["index"] = stage.index;
590
+ return { $searchMeta: searchMeta };
591
+ }
592
+ case "vectorSearch": {
593
+ const vs = {
594
+ index: stage.index,
595
+ path: stage.path,
596
+ queryVector: [...stage.queryVector],
597
+ numCandidates: stage.numCandidates,
598
+ limit: stage.limit
599
+ };
600
+ if (stage.filter) vs["filter"] = { ...stage.filter };
601
+ return { $vectorSearch: vs };
602
+ }
603
+ default: throw new Error(`Unhandled stage kind: ${blindCast(stage).kind}`);
604
+ }
605
+ }
606
+ function structuralLowerPipeline(stages) {
607
+ return stages.map((s) => structuralLowerStage(s));
608
+ }
378
609
  //#endregion
379
610
  //#region src/core/codecs.ts
380
611
  const mongoObjectIdCodec = mongoCodec({
@@ -515,59 +746,167 @@ function buildStandardCodecRegistry() {
515
746
  function isUpdatePipeline(update) {
516
747
  return Array.isArray(update);
517
748
  }
749
+ function isDraftUpdatePipeline(update) {
750
+ return Array.isArray(update);
751
+ }
752
+ async function resolveUpdate(update, codecs, ctx) {
753
+ if (isDraftUpdatePipeline(update)) return Promise.all(update.map((stage) => resolveDraftDoc(stage, codecs, ctx)));
754
+ return resolveDraftDoc(update, codecs, ctx);
755
+ }
518
756
  var MongoAdapterImpl = class {
519
757
  #codecs;
520
758
  constructor(codecs) {
521
759
  this.#codecs = codecs;
522
760
  }
523
- async #resolveDocument(expr, ctx) {
524
- const entries = Object.entries(expr);
525
- const resolved = await Promise.all(entries.map(([, val]) => resolveValue(val, this.#codecs, ctx)));
526
- const result = {};
527
- for (let i = 0; i < entries.length; i++) {
528
- const entry = entries[i];
529
- if (entry) result[entry[0]] = resolved[i];
530
- }
531
- return result;
532
- }
533
- async #lowerUpdate(update, ctx) {
534
- if (isUpdatePipeline(update)) return Promise.all(update.map((stage) => lowerStage(stage, this.#codecs, ctx)));
535
- return this.#resolveDocument(update, ctx);
536
- }
537
- async lower(plan, ctx) {
761
+ structuralLower(plan) {
538
762
  const { command } = plan;
539
763
  switch (command.kind) {
540
- case "insertOne": return new InsertOneWireCommand(command.collection, await this.#resolveDocument(command.document, ctx));
764
+ case "insertOne": return {
765
+ kind: "insertOne",
766
+ collection: command.collection,
767
+ document: command.document
768
+ };
769
+ case "insertMany": return {
770
+ kind: "insertMany",
771
+ collection: command.collection,
772
+ documents: command.documents
773
+ };
774
+ case "updateOne": return {
775
+ kind: "updateOne",
776
+ collection: command.collection,
777
+ filter: structuralLowerFilter(command.filter),
778
+ update: isUpdatePipeline(command.update) ? structuralLowerPipeline(command.update) : command.update,
779
+ upsert: command.upsert
780
+ };
781
+ case "updateMany": return {
782
+ kind: "updateMany",
783
+ collection: command.collection,
784
+ filter: structuralLowerFilter(command.filter),
785
+ update: isUpdatePipeline(command.update) ? structuralLowerPipeline(command.update) : command.update,
786
+ upsert: command.upsert
787
+ };
788
+ case "deleteOne": return {
789
+ kind: "deleteOne",
790
+ collection: command.collection,
791
+ filter: structuralLowerFilter(command.filter)
792
+ };
793
+ case "deleteMany": return {
794
+ kind: "deleteMany",
795
+ collection: command.collection,
796
+ filter: structuralLowerFilter(command.filter)
797
+ };
798
+ case "findOneAndUpdate": return {
799
+ kind: "findOneAndUpdate",
800
+ collection: command.collection,
801
+ filter: structuralLowerFilter(command.filter),
802
+ update: isUpdatePipeline(command.update) ? structuralLowerPipeline(command.update) : command.update,
803
+ upsert: command.upsert,
804
+ sort: command.sort,
805
+ returnDocument: command.returnDocument
806
+ };
807
+ case "findOneAndDelete": return {
808
+ kind: "findOneAndDelete",
809
+ collection: command.collection,
810
+ filter: structuralLowerFilter(command.filter),
811
+ sort: command.sort
812
+ };
813
+ case "aggregate": return {
814
+ kind: "aggregate",
815
+ collection: command.collection,
816
+ pipeline: structuralLowerPipeline(command.pipeline)
817
+ };
818
+ case "rawAggregate": return {
819
+ kind: "rawAggregate",
820
+ collection: command.collection,
821
+ pipeline: command.pipeline
822
+ };
823
+ case "rawInsertOne": return {
824
+ kind: "rawInsertOne",
825
+ collection: command.collection,
826
+ document: command.document
827
+ };
828
+ case "rawInsertMany": return {
829
+ kind: "rawInsertMany",
830
+ collection: command.collection,
831
+ documents: command.documents
832
+ };
833
+ case "rawUpdateOne": return {
834
+ kind: "rawUpdateOne",
835
+ collection: command.collection,
836
+ filter: command.filter,
837
+ update: command.update
838
+ };
839
+ case "rawUpdateMany": return {
840
+ kind: "rawUpdateMany",
841
+ collection: command.collection,
842
+ filter: command.filter,
843
+ update: command.update
844
+ };
845
+ case "rawDeleteOne": return {
846
+ kind: "rawDeleteOne",
847
+ collection: command.collection,
848
+ filter: command.filter
849
+ };
850
+ case "rawDeleteMany": return {
851
+ kind: "rawDeleteMany",
852
+ collection: command.collection,
853
+ filter: command.filter
854
+ };
855
+ case "rawFindOneAndUpdate": return {
856
+ kind: "rawFindOneAndUpdate",
857
+ collection: command.collection,
858
+ filter: command.filter,
859
+ update: command.update,
860
+ upsert: command.upsert,
861
+ sort: command.sort,
862
+ returnDocument: command.returnDocument
863
+ };
864
+ case "rawFindOneAndDelete": return {
865
+ kind: "rawFindOneAndDelete",
866
+ collection: command.collection,
867
+ filter: command.filter,
868
+ sort: command.sort
869
+ };
870
+ // v8 ignore next 4
871
+ default: throw new Error(`Unknown command kind: ${blindCast(command).kind}`);
872
+ }
873
+ }
874
+ async resolveParams(draft, ctx) {
875
+ switch (draft.kind) {
876
+ case "insertOne": return new InsertOneWireCommand(draft.collection, await resolveDraftDoc(draft.document, this.#codecs, ctx));
877
+ case "insertMany": return new InsertManyWireCommand(draft.collection, await Promise.all(draft.documents.map((doc) => resolveDraftDoc(doc, this.#codecs, ctx))));
541
878
  case "updateOne": {
542
- const [filter, update] = await Promise.all([lowerFilter(command.filter, this.#codecs, ctx), this.#lowerUpdate(command.update, ctx)]);
543
- return new UpdateOneWireCommand(command.collection, filter, update, command.upsert);
879
+ const [filter, update] = await Promise.all([resolveDraftDoc(draft.filter, this.#codecs, ctx), resolveUpdate(draft.update, this.#codecs, ctx)]);
880
+ return new UpdateOneWireCommand(draft.collection, filter, update, draft.upsert);
544
881
  }
545
- case "insertMany": return new InsertManyWireCommand(command.collection, await Promise.all(command.documents.map((doc) => this.#resolveDocument(doc, ctx))));
546
882
  case "updateMany": {
547
- const [filter, update] = await Promise.all([lowerFilter(command.filter, this.#codecs, ctx), this.#lowerUpdate(command.update, ctx)]);
548
- return new UpdateManyWireCommand(command.collection, filter, update, command.upsert);
883
+ const [filter, update] = await Promise.all([resolveDraftDoc(draft.filter, this.#codecs, ctx), resolveUpdate(draft.update, this.#codecs, ctx)]);
884
+ return new UpdateManyWireCommand(draft.collection, filter, update, draft.upsert);
549
885
  }
550
- case "deleteOne": return new DeleteOneWireCommand(command.collection, await lowerFilter(command.filter, this.#codecs, ctx));
551
- case "deleteMany": return new DeleteManyWireCommand(command.collection, await lowerFilter(command.filter, this.#codecs, ctx));
886
+ case "deleteOne": return new DeleteOneWireCommand(draft.collection, await resolveDraftDoc(draft.filter, this.#codecs, ctx));
887
+ case "deleteMany": return new DeleteManyWireCommand(draft.collection, await resolveDraftDoc(draft.filter, this.#codecs, ctx));
552
888
  case "findOneAndUpdate": {
553
- const [filter, update] = await Promise.all([lowerFilter(command.filter, this.#codecs, ctx), this.#lowerUpdate(command.update, ctx)]);
554
- return new FindOneAndUpdateWireCommand(command.collection, filter, update, command.upsert, command.sort, command.returnDocument);
889
+ const [filter, update] = await Promise.all([resolveDraftDoc(draft.filter, this.#codecs, ctx), resolveUpdate(draft.update, this.#codecs, ctx)]);
890
+ return new FindOneAndUpdateWireCommand(draft.collection, filter, update, draft.upsert, draft.sort, draft.returnDocument);
555
891
  }
556
- case "findOneAndDelete": return new FindOneAndDeleteWireCommand(command.collection, await lowerFilter(command.filter, this.#codecs, ctx), command.sort);
557
- case "aggregate": return new AggregateWireCommand(command.collection, await lowerPipeline(command.pipeline, this.#codecs, ctx));
558
- case "rawAggregate": return new AggregateWireCommand(command.collection, command.pipeline);
559
- case "rawInsertOne": return new InsertOneWireCommand(command.collection, command.document);
560
- case "rawInsertMany": return new InsertManyWireCommand(command.collection, command.documents);
561
- case "rawUpdateOne": return new UpdateOneWireCommand(command.collection, command.filter, command.update);
562
- case "rawUpdateMany": return new UpdateManyWireCommand(command.collection, command.filter, command.update);
563
- case "rawDeleteOne": return new DeleteOneWireCommand(command.collection, command.filter);
564
- case "rawDeleteMany": return new DeleteManyWireCommand(command.collection, command.filter);
565
- case "rawFindOneAndUpdate": return new FindOneAndUpdateWireCommand(command.collection, command.filter, command.update, command.upsert, command.sort, command.returnDocument);
566
- case "rawFindOneAndDelete": return new FindOneAndDeleteWireCommand(command.collection, command.filter, command.sort);
892
+ case "findOneAndDelete": return new FindOneAndDeleteWireCommand(draft.collection, await resolveDraftDoc(draft.filter, this.#codecs, ctx), draft.sort);
893
+ case "aggregate": return new AggregateWireCommand(draft.collection, await Promise.all(draft.pipeline.map((stage) => resolveDraftDoc(stage, this.#codecs, ctx))));
894
+ case "rawAggregate": return new AggregateWireCommand(draft.collection, draft.pipeline);
895
+ case "rawInsertOne": return new InsertOneWireCommand(draft.collection, draft.document);
896
+ case "rawInsertMany": return new InsertManyWireCommand(draft.collection, draft.documents);
897
+ case "rawUpdateOne": return new UpdateOneWireCommand(draft.collection, draft.filter, draft.update);
898
+ case "rawUpdateMany": return new UpdateManyWireCommand(draft.collection, draft.filter, draft.update);
899
+ case "rawDeleteOne": return new DeleteOneWireCommand(draft.collection, draft.filter);
900
+ case "rawDeleteMany": return new DeleteManyWireCommand(draft.collection, draft.filter);
901
+ case "rawFindOneAndUpdate": return new FindOneAndUpdateWireCommand(draft.collection, draft.filter, draft.update, draft.upsert, draft.sort, draft.returnDocument);
902
+ case "rawFindOneAndDelete": return new FindOneAndDeleteWireCommand(draft.collection, draft.filter, draft.sort);
567
903
  // v8 ignore next 4
568
- default: throw new Error(`Unknown command kind: ${command.kind}`);
904
+ default: throw new Error(`Unknown draft kind: ${blindCast(draft).kind}`);
569
905
  }
570
906
  }
907
+ lower(plan, ctx) {
908
+ return this.resolveParams(this.structuralLower(plan), ctx);
909
+ }
571
910
  };
572
911
  /**
573
912
  * Construct a Mongo adapter with the standard wire-type codecs registered
@@ -584,4 +923,4 @@ function createMongoAdapter() {
584
923
  //#endregion
585
924
  export { lowerFilter as a, MONGO_VECTOR_CODEC_ID as c, lowerAggExpr as i, buildStandardCodecRegistry as n, lowerPipeline as o, mongoCodecDescriptors as r, lowerStage as s, createMongoAdapter as t };
586
925
 
587
- //# sourceMappingURL=mongo-adapter-DfCmEYHR.mjs.map
926
+ //# sourceMappingURL=mongo-adapter-DAC5qq3o.mjs.map