Skip to content

Commit

Permalink
refactor(hub-search): use a new base-64 encoding lib
Browse files Browse the repository at this point in the history
affects: @esri/hub-common, @esri/hub-search
  • Loading branch information
drewdaemon committed Sep 16, 2021
1 parent b6b5a11 commit 99c6712
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 66 deletions.
1 change: 1 addition & 0 deletions packages/common/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ import OperationStack from "./OperationStack";
import OperationError from "./OperationError";
// Re-exports
export { OperationStack, OperationError };
export { btoa, atob } from "abab";
2 changes: 0 additions & 2 deletions packages/search/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
"types": "dist/types/index.d.ts",
"license": "Apache-2.0",
"dependencies": {
"base-64": "^1.0.0",
"tslib": "^1.13.0"
},
"peerDependencies": {
Expand All @@ -31,7 +30,6 @@
"@rollup/plugin-commonjs": "^15.0.0",
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^9.0.0",
"@types/base-64": "^0.1.3",
"@types/faker": "^5.1.5",
"faker": "^5.1.0",
"rollup": "^2.26.5",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import { decode } from "base-64";
import { Logger } from "@esri/hub-common";
import { Logger, atob as decode } from "@esri/hub-common";
import { IPagingParams, ISearchOptions } from "@esri/arcgis-rest-portal";
import { UserSession } from "@esri/arcgis-rest-auth";
import {
IBooleanOperator,
IContentSearchFilter,
IContentSearchOptions,
IContentSearchRequest,
IContentFieldFilter
IContentFieldFilter,
} from "../../types/content";
import { IDateRange } from "../../types/common";
import {
isFilterAnArrayWithData,
isFilterANonEmptyString,
isFilterFieldADateRange
isFilterFieldADateRange,
} from "./common";

const TERM_FIELD = "terms";
Expand All @@ -25,7 +24,7 @@ const STRING_ENCLOSED_FILTER_FIELDS = [
"description",
"tags",
"snippet",
"categories"
"categories",
];

/**
Expand Down Expand Up @@ -72,7 +71,7 @@ export function processPage(request: IContentSearchRequest): IPagingParams {
const options: IContentSearchOptions = request.options || {};
const providedPage: IPagingParams | string = options.page || {
start: 1,
num: 10
num: 10,
};
return typeof providedPage === "string"
? decodePage(providedPage)
Expand All @@ -94,12 +93,12 @@ function createSearchOptions(
countFields: options.aggregations,
countSize: options.aggregations ? 200 : undefined,
start: page.start,
num: page.num
num: page.num,
},
bbox: options.bbox,
portal: options.portal || defaultPortal,
authentication: options.authentication || defaultAuthentication,
httpMethod: "POST"
httpMethod: "POST",
};
}

Expand Down Expand Up @@ -143,8 +142,9 @@ function processDateField(
filterField: string,
filterValue: IDateRange<number>
) {
return `(${filterField}: [${filterValue.from || 0} TO ${filterValue.to ||
new Date().getTime()}])`;
return `(${filterField}: [${filterValue.from || 0} TO ${
filterValue.to || new Date().getTime()
}])`;
}

function processFieldFilter(
Expand Down Expand Up @@ -181,6 +181,9 @@ function stringifyFilterValue(
function decodePage(page: string): IPagingParams {
try {
const decodedPage: any = decode(page);
if (decodedPage === null) {
throw new Error();
}
return JSON.parse(decodedPage);
} catch (err) {
Logger.error(
Expand Down
2 changes: 1 addition & 1 deletion packages/search/src/util/merge-pagination/merge.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { encode } from "base-64";
import { btoa as encode } from "@esri/hub-common";
import { InvalidPaginationInputError } from "./invalid-pagination-input";

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import { SortDirection } from "../../../src/types/common";
import {
IBooleanOperator,
IContentSearchFilter,
IContentSearchOptions
IContentSearchOptions,
} from "../../../src/types/content";
import { btoa } from "@esri/hub-common";

describe("Convert Portal Params Function", () => {
it("can convert content filters to Portal API filters", () => {
Expand All @@ -23,8 +24,8 @@ describe("Convert Portal Params Function", () => {
culture: ["en", "de"],
categories: {
value: ["category one", "category 2", "category three"],
bool: IBooleanOperator.AND
}
bool: IBooleanOperator.AND,
},
};

// Test
Expand Down Expand Up @@ -63,8 +64,8 @@ describe("Convert Portal Params Function", () => {
culture: ["en", "de"],
categories: {
value: ["category one", "category 2", "category three"],
bool: IBooleanOperator.AND
}
bool: IBooleanOperator.AND,
},
};

// Test
Expand Down Expand Up @@ -101,7 +102,7 @@ describe("Convert Portal Params Function", () => {
type: { value: null },
access: "",
culture: [],
categories: null
categories: null,
};

// Test
Expand Down Expand Up @@ -140,16 +141,16 @@ describe("Convert Portal Params Function", () => {
culture: ["en", "de"],
categories: {
value: ["category one", "category 2", "category three"],
bool: IBooleanOperator.AND
}
bool: IBooleanOperator.AND,
},
};

const page: string = "eyJzdGFydCI6NSwibnVtIjoyMH0=";

// Test
const portalParams = convertToPortalParams({
filter: filters,
options: { page }
options: { page },
});

// Assert
Expand All @@ -170,7 +171,7 @@ describe("Convert Portal Params Function", () => {
expect(portalParams.bbox).toBeUndefined();
});

it("can handle an error occuring upon decoding a page", () => {
fit("can handle an error occuring upon decoding a page", () => {
// Setup
const filters: IContentSearchFilter = {
terms: "water",
Expand All @@ -185,34 +186,36 @@ describe("Convert Portal Params Function", () => {
culture: ["en", "de"],
categories: {
value: ["category one", "category 2", "category three"],
bool: IBooleanOperator.AND
}
bool: IBooleanOperator.AND,
},
};
const testInvalidPageOption = (pageOption: string) => {
// Test
const portalParams = convertToPortalParams({
filter: filters,
options: { page: pageOption },
});

// Assert
expect(portalParams).toBeDefined();
expect(portalParams.q).toBeDefined();
expect(portalParams.q).toEqual(
`(water) AND (owner: me OR owner: you) AND (created: [1609459200000 TO 1612137600000]) AND (modified: [1609459200000 TO 1612137600000]) AND (-title: "a title" AND -title: "b title") AND (typekeywords: "a type keyword") AND (tags: "tag 1" OR tags: "tag 2" OR tags: "tag 3") AND (type: "Feature Layer" OR type: "Table" OR type: "CSV") AND (access: private) AND (culture: en OR culture: de) AND (categories: "category one" AND categories: "category 2" AND categories: "category three") AND (-type: "code attachment")`
);
expect(portalParams.sortOrder).toBeUndefined();
expect(portalParams.sortField).toBeUndefined();
expect(portalParams.params).toBeDefined();
expect(portalParams.params.start).toBeDefined();
expect(portalParams.params.start).toEqual(1);
expect(portalParams.params.num).toBeDefined();
expect(portalParams.params.num).toEqual(10);
expect(portalParams.params.countFields).toBeUndefined();
expect(portalParams.params.countSize).toBeUndefined();
expect(portalParams.bbox).toBeUndefined();
};

const page: string = "dummy";

// Test
const portalParams = convertToPortalParams({
filter: filters,
options: { page }
});

// Assert
expect(portalParams).toBeDefined();
expect(portalParams.q).toBeDefined();
expect(portalParams.q).toEqual(
`(water) AND (owner: me OR owner: you) AND (created: [1609459200000 TO 1612137600000]) AND (modified: [1609459200000 TO 1612137600000]) AND (-title: "a title" AND -title: "b title") AND (typekeywords: "a type keyword") AND (tags: "tag 1" OR tags: "tag 2" OR tags: "tag 3") AND (type: "Feature Layer" OR type: "Table" OR type: "CSV") AND (access: private) AND (culture: en OR culture: de) AND (categories: "category one" AND categories: "category 2" AND categories: "category three") AND (-type: "code attachment")`
);
expect(portalParams.sortOrder).toBeUndefined();
expect(portalParams.sortField).toBeUndefined();
expect(portalParams.params).toBeDefined();
expect(portalParams.params.start).toBeDefined();
expect(portalParams.params.start).toEqual(1);
expect(portalParams.params.num).toBeDefined();
expect(portalParams.params.num).toEqual(10);
expect(portalParams.params.countFields).toBeUndefined();
expect(portalParams.params.countSize).toBeUndefined();
expect(portalParams.bbox).toBeUndefined();
testInvalidPageOption("invalid base 64");
testInvalidPageOption(btoa("invalid serialized json"));
});

it("can convert content filters to Portal API filters with proper sorting", () => {
Expand All @@ -230,15 +233,15 @@ describe("Convert Portal Params Function", () => {
culture: "en",
categories: { value: ["category one", "category 2", "category three"] },
orgid: ["org one", "org two"],
id: { value: ["1", "2", "3"], bool: IBooleanOperator.NOT }
id: { value: ["1", "2", "3"], bool: IBooleanOperator.NOT },
};

const portalOptions = { sortField: "title", sortOrder: SortDirection.desc };

// Test
const portalParams = convertToPortalParams({
filter: filters,
options: portalOptions
options: portalOptions,
});

// Assert
Expand Down Expand Up @@ -276,19 +279,19 @@ describe("Convert Portal Params Function", () => {
culture: "en",
categories: { value: ["category one", "category 2", "category three"] },
orgid: ["org one", "org two"],
id: { value: ["1", "2", "3"], bool: IBooleanOperator.NOT }
id: { value: ["1", "2", "3"], bool: IBooleanOperator.NOT },
};

const portalOptions = {
sortField: "title",
sortOrder: SortDirection.desc,
aggregations: "categories,type,access"
aggregations: "categories,type,access",
};

// Test
const portalParams = convertToPortalParams({
filter: filters,
options: portalOptions
options: portalOptions,
});

// Assert
Expand Down Expand Up @@ -328,20 +331,20 @@ describe("Convert Portal Params Function", () => {
culture: "en",
categories: { value: ["category one", "category 2", "category three"] },
orgid: ["org one", "org two"],
id: { value: ["1", "2", "3"], bool: IBooleanOperator.NOT }
id: { value: ["1", "2", "3"], bool: IBooleanOperator.NOT },
};

const portalOptions = {
sortField: "title",
sortOrder: SortDirection.desc,
aggregations: "categories,type,access",
bbox: "bbox"
bbox: "bbox",
};

// Test
const portalParams = convertToPortalParams({
filter: filters,
options: portalOptions
options: portalOptions,
});

// Assert
Expand Down Expand Up @@ -382,7 +385,7 @@ describe("Convert Portal Params Function", () => {
culture: "en",
categories: { value: ["category one", "category 2", "category three"] },
orgid: ["org one", "org two"],
id: { value: ["1", "2", "3"], bool: IBooleanOperator.NOT }
id: { value: ["1", "2", "3"], bool: IBooleanOperator.NOT },
};

const portalOptions: IContentSearchOptions = {
Expand All @@ -391,14 +394,14 @@ describe("Convert Portal Params Function", () => {
aggregations: "categories,type,access",
bbox: "bbox",
portal: "dummy-portal-sharing-one",
authentication: new UserSession({ portal: "dummy-portal-one" })
authentication: new UserSession({ portal: "dummy-portal-one" }),
};

// Test
const portalParams = convertToPortalParams(
{
filter: filters,
options: portalOptions
options: portalOptions,
},
"dummy-portal-sharing-two",
new UserSession({ portal: "dummy-portal-two" })
Expand Down Expand Up @@ -446,21 +449,21 @@ describe("Convert Portal Params Function", () => {
culture: "en",
categories: { value: ["category one", "category 2", "category three"] },
orgid: ["org one", "org two"],
id: { value: ["1", "2", "3"], bool: IBooleanOperator.NOT }
id: { value: ["1", "2", "3"], bool: IBooleanOperator.NOT },
};

const portalOptions: IContentSearchOptions = {
sortField: "title",
sortOrder: SortDirection.desc,
aggregations: "categories,type,access",
bbox: "bbox"
bbox: "bbox",
};

// Test
const portalParams = convertToPortalParams(
{
filter: filters,
options: portalOptions
options: portalOptions,
},
"dummy-portal-sharing-two",
new UserSession({ portal: "dummy-portal-two" })
Expand Down Expand Up @@ -508,20 +511,20 @@ describe("Convert Portal Params Function", () => {
culture: "en",
categories: { value: ["category one", "category 2", "category three"] },
orgid: ["org one", "org two"],
id: { value: ["1", "2", "3"], bool: IBooleanOperator.NOT }
id: { value: ["1", "2", "3"], bool: IBooleanOperator.NOT },
};

const portalOptions: IContentSearchOptions = {
sortField: "title",
sortOrder: SortDirection.desc,
aggregations: "categories,type,access",
bbox: "bbox"
bbox: "bbox",
};

// Test
const portalParams = convertToPortalParams({
filter: filters,
options: portalOptions
options: portalOptions,
});

// Assert
Expand Down

0 comments on commit 99c6712

Please sign in to comment.