Skip to content

Commit

Permalink
add assertion about key not having brackets
Browse files Browse the repository at this point in the history
  • Loading branch information
tintinthong committed Nov 4, 2024
1 parent 7888d80 commit 060aaa6
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 41 deletions.
54 changes: 17 additions & 37 deletions packages/runtime-common/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -307,9 +307,9 @@ function assertEveryFilter(
`${pointer.join('/') || '/'}: every must be an array of Filters`,
);
} else {
filter.every.every((value: any, index: number) =>
assertFilter(value, pointer.concat(`[${index}]`)),
);
filter.every.forEach((value: any, index: number) => {
assertFilter(value, pointer.concat(`[${index}]`));
});
}
}

Expand Down Expand Up @@ -348,9 +348,10 @@ function assertEqFilter(
if (typeof filter.eq !== 'object' || filter.eq == null) {
throw new Error(`${pointer.join('/') || '/'}: eq must be an object`);
}
Object.entries(filter.eq).every(([key, value]) =>
assertJSONValue(value, pointer.concat(key)),
);
Object.entries(filter.eq).forEach(([key, value]) => {
assertKey(key, pointer);
assertJSONValue(value, pointer.concat(key));
});
}

function assertContainsFilter(
Expand All @@ -371,9 +372,10 @@ function assertContainsFilter(
if (typeof filter.contains !== 'object' || filter.contains == null) {
throw new Error(`${pointer.join('/') || '/'}: contains must be an object`);
}
Object.entries(filter.contains).every(([key, value]) =>
assertJSONValue(value, pointer.concat(key)),
);
Object.entries(filter.contains).forEach(([key, value]) => {
assertKey(key, pointer);
assertJSONValue(value, pointer.concat(key));
});
}

function assertRangeFilter(
Expand Down Expand Up @@ -420,32 +422,10 @@ function assertRangeFilter(
});
}

// This is a helper function to remove brackets from keys in a query object returned by qs.parse.
// For example, qs.parse consumes stringified search query and returns a query object with key '[author.firstName]; we should get 'author.firstName' instead
// Our search index doesn't account for path segments which are wrapped in brackets so we need to remove them.
const removeBrackets = (obj: any): any => {
if (!obj || typeof obj !== 'object') return obj;

if (Array.isArray(obj)) {
return obj.map((item) => removeBrackets(item));
export function assertKey(key: string, pointer: string[]) {
if (key.startsWith('[') && key.endsWith(']')) {
throw new Error(
`${pointer.join('/')}: field names cannot be wrapped in brackets: ${key}`,
);
}

return Object.entries(obj).reduce((acc, [key, value]) => {
// Remove surrounding brackets if they exist
const newKey = key.replace(/^\[(.*)\]$/, '$1');

if (Array.isArray(value)) {
acc[newKey] = value.map((item) => removeBrackets(item));
} else if (typeof value === 'object' && value !== null) {
acc[newKey] = removeBrackets(value);
} else {
acc[newKey] = value;
}

return acc;
}, {} as any);
};

export const parseQuery = (queryString: string) => {
return removeBrackets(qs.parse(queryString));
};
}
8 changes: 4 additions & 4 deletions packages/runtime-common/realm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ import {
SupportedMimeType,
lookupRouteTable,
} from './router';
import { assertQuery, parseQuery } from './query';
import { assertQuery } from './query';
import type { Readable } from 'stream';
import { type CardDef } from 'https://cardstack.com/base/card-api';
import type * as CardAPI from 'https://cardstack.com/base/card-api';
Expand All @@ -75,6 +75,7 @@ import { fetcher } from './fetcher';
import { RealmIndexQueryEngine } from './realm-index-query-engine';
import { RealmIndexUpdater } from './realm-index-updater';

import qs from 'qs';
import {
MatrixBackendAuthentication,
Utils,
Expand Down Expand Up @@ -1530,7 +1531,7 @@ export class Realm {
request.headers.get('X-Boxel-Building-Index'),
);

let cardsQuery = parseQuery(new URL(request.url).search.slice(1));
let cardsQuery = qs.parse(new URL(request.url).search.slice(1));
assertQuery(cardsQuery);

let doc = await this.#realmIndexQueryEngine.search(cardsQuery, {
Expand All @@ -1554,8 +1555,7 @@ export class Realm {
request.headers.get('X-Boxel-Building-Index'),
);

let href = new URL(request.url).search.slice(1);
let parsedQueryString = parseQuery(href);
let parsedQueryString = qs.parse(new URL(request.url).search.slice(1));
let htmlFormat = parsedQueryString.prerenderedHtmlFormat as string;
let cardUrls = parsedQueryString.cardUrls as string[];

Expand Down

0 comments on commit 060aaa6

Please sign in to comment.