fix(mongodb): support legacy count helpers
This commit is contained in:
1 parent
c702149931
commit
cabe89a19b
5 files changed
+146
-31
No files matched your search
@@ -88,6 +88,7 @@ export function parseMongoFindCommand(input: string): MongoFindCommand | null {
|
||||
|
||||
const chain = source.slice(findCloseIndex + 1).trim();
|
||||
if (chain && !chain.startsWith(".")) return null;
|
||||
if (findChainedMethodCallIndex(chain, "count") >= 0) return null;
|
||||
|
||||
const sortArg = readChainedCallArgument(chain, "sort");
|
||||
let sort: string | undefined;
|
||||
@@ -113,7 +114,13 @@ export function parseMongoFindCommand(input: string): MongoFindCommand | null {
|
||||
|
||||
export function parseMongoCountDocumentsCommand(input: string): MongoCountDocumentsCommand | null {
|
||||
const source = input.trim().replace(/;$/, "").trim();
|
||||
const target = parseCollectionMethodTarget(source, "countDocuments");
|
||||
// Accept deprecated Mongo shell count helpers for old server workflows, but
|
||||
// keep DBX's internal execution mapped to the countDocuments result shape.
|
||||
return parseCollectionCountCommand(source, "countDocuments") ?? parseCollectionCountCommand(source, "count") ?? parseFindCountCommand(source);
|
||||
}
|
||||
|
||||
function parseCollectionCountCommand(source: string, method: "countDocuments" | "count"): MongoCountDocumentsCommand | null {
|
||||
const target = parseCollectionMethodTarget(source, method);
|
||||
if (!target) return null;
|
||||
|
||||
const openIndex = source.indexOf("(", target.methodCallIndex);
|
||||
@@ -131,6 +138,28 @@ export function parseMongoCountDocumentsCommand(input: string): MongoCountDocume
|
||||
};
|
||||
}
|
||||
|
||||
function parseFindCountCommand(source: string): MongoCountDocumentsCommand | null {
|
||||
const target = parseFindTarget(source);
|
||||
if (!target) return null;
|
||||
|
||||
const findOpenIndex = source.indexOf("(", target.findCallIndex);
|
||||
const findCloseIndex = findMatchingParen(source, findOpenIndex);
|
||||
if (findCloseIndex < 0) return null;
|
||||
|
||||
const chain = source.slice(findCloseIndex + 1).trim();
|
||||
if (!hasSingleEmptyChainedCall(chain, "count")) return null;
|
||||
|
||||
const findArgs = splitTopLevel(source.slice(findOpenIndex + 1, findCloseIndex));
|
||||
if (findArgs.length > 2 && findArgs.slice(2).some((arg) => arg.trim())) return null;
|
||||
const filter = normalizeJsonArgument(findArgs[0] || "{}");
|
||||
if (!filter) return null;
|
||||
|
||||
return {
|
||||
collection: target.collection,
|
||||
filter,
|
||||
};
|
||||
}
|
||||
|
||||
export function parseMongoAggregateCommand(input: string): MongoAggregateCommand | null {
|
||||
const source = input.trim().replace(/;$/, "").trim();
|
||||
const target = parseCollectionMethodTarget(source, "aggregate");
|
||||
@@ -268,18 +297,20 @@ export function parseMongoCommand(input: string): ParsedMongoCommand | null {
|
||||
// Keep the more specific readers ahead of generic write parsing so the
|
||||
// returned kind matches the result renderer we want to use downstream.
|
||||
const parsers: Array<(source: string) => MongoCommand | null> = [
|
||||
(source) => {
|
||||
const find = parseMongoFindCommand(source);
|
||||
return find ? { kind: "find", ...find } : null;
|
||||
},
|
||||
(source) => {
|
||||
const version = parseMongoVersionCommand(source);
|
||||
return version ?? null;
|
||||
},
|
||||
(source) => {
|
||||
// Legacy Mongo shell uses count()/find().count(); keep accepting it
|
||||
// while mapping to DBX's countDocuments-compatible result path.
|
||||
const count = parseMongoCountDocumentsCommand(source);
|
||||
return count ? { kind: "countDocuments", ...count } : null;
|
||||
},
|
||||
(source) => {
|
||||
const find = parseMongoFindCommand(source);
|
||||
return find ? { kind: "find", ...find } : null;
|
||||
},
|
||||
(source) => {
|
||||
const aggregate = parseMongoAggregateCommand(source);
|
||||
return aggregate ? { kind: "aggregate", ...aggregate } : null;
|
||||
@@ -915,6 +946,15 @@ function readChainedCallArgument(source: string, name: string): string | undefin
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function hasSingleEmptyChainedCall(source: string, name: string): boolean {
|
||||
const trimmed = source.trim();
|
||||
const match = chainedMethodCallPattern(name).exec(trimmed);
|
||||
if (!match || match.index !== 0) return false;
|
||||
const openIndex = trimmed.indexOf("(", match.index);
|
||||
const closeIndex = findMatchingParen(trimmed, openIndex);
|
||||
return closeIndex >= 0 && !trimmed.slice(openIndex + 1, closeIndex).trim() && !trimmed.slice(closeIndex + 1).trim();
|
||||
}
|
||||
|
||||
function findChainedMethodCallIndex(source: string, name: string): number {
|
||||
return chainedMethodCallPattern(name).exec(source)?.index ?? -1;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user