From c595cf8d969fcdafdb809d4ce22417723d5201cf Mon Sep 17 00:00:00 2001 From: Tiffany Forkner Date: Wed, 8 Jan 2025 13:50:46 -0500 Subject: [PATCH 1/4] created helpers for getting domain and index for opensearch --- lib/lambda/deleteIndex.ts | 19 ++--- lib/lambda/getAttachmentUrl.test.ts | 2 +- lib/lambda/getAttachmentUrl.ts | 21 ++---- lib/lambda/getCpocs.ts | 13 ++-- lib/lambda/getSubTypes.ts | 11 ++- lib/lambda/getTypes.ts | 11 +-- lib/lambda/itemExists.test.ts | 6 +- lib/lambda/search.test.ts | 2 +- lib/lambda/search.ts | 13 ++-- lib/libs/api/package/appk.test.ts | 108 +++++++++++++--------------- lib/libs/api/package/appk.ts | 30 +++----- lib/libs/api/package/changelog.ts | 30 +++----- lib/libs/api/package/getPackage.ts | 12 ++-- lib/libs/api/package/itemExists.ts | 20 ++++-- lib/libs/sink-lib.ts | 27 +------ lib/libs/utils.ts | 52 ++++++++++++++ mocks/data/items.ts | 35 ++++++++- mocks/handlers/opensearch/main.ts | 20 +++--- 18 files changed, 227 insertions(+), 205 deletions(-) create mode 100644 lib/libs/utils.ts diff --git a/lib/lambda/deleteIndex.ts b/lib/lambda/deleteIndex.ts index 67492361a4..0a7238d951 100644 --- a/lib/lambda/deleteIndex.ts +++ b/lib/lambda/deleteIndex.ts @@ -8,19 +8,20 @@ export const handler: Handler = async (event, __, callback) => { }; let errorResponse = null; try { - if (!event.osDomain) throw "process.env.osDomain cannot be undefined"; + const { osDomain, indexNamespace = "" } = event; + if (!osDomain) throw "osDomain cannot be undefined"; const indices: Index[] = [ - `${event.indexNamespace}main`, - `${event.indexNamespace}changelog`, - `${event.indexNamespace}insights`, - `${event.indexNamespace}types`, - `${event.indexNamespace}subtypes`, - `${event.indexNamespace}legacyinsights`, - `${event.indexNamespace}cpocs`, + `${indexNamespace}main`, + `${indexNamespace}changelog`, + `${indexNamespace}insights`, + `${indexNamespace}types`, + `${indexNamespace}subtypes`, + `${indexNamespace}legacyinsights`, + `${indexNamespace}cpocs`, ]; for (const index of indices) { - await os.deleteIndex(event.osDomain, index); + await os.deleteIndex(osDomain, index); } } catch (error: any) { response.statusCode = 500; diff --git a/lib/lambda/getAttachmentUrl.test.ts b/lib/lambda/getAttachmentUrl.test.ts index 0ee3102e18..3fd589f891 100644 --- a/lib/lambda/getAttachmentUrl.test.ts +++ b/lib/lambda/getAttachmentUrl.test.ts @@ -70,7 +70,7 @@ describe("Lambda Handler", () => { expect(response).toHaveBeenCalledWith({ statusCode: 500, - body: { message: "ERROR: osDomain env variable is required" }, + body: { message: "ERROR: process.env.osDomain must be defined" }, }); }); diff --git a/lib/lambda/getAttachmentUrl.ts b/lib/lambda/getAttachmentUrl.ts index 7f94231bd9..394b9f62c8 100644 --- a/lib/lambda/getAttachmentUrl.ts +++ b/lib/lambda/getAttachmentUrl.ts @@ -7,27 +7,25 @@ import { getSignedUrl } from "@aws-sdk/s3-request-presigner"; import { getStateFilter } from "../libs/api/auth/user"; import { getPackage, getPackageChangelog } from "../libs/api/package"; +import { getDomain } from "libs/utils"; // Handler function to get Seatool data export const handler = async (event: APIGatewayEvent) => { - if (!process.env.osDomain) { + try { + getDomain(); + } catch (error) { return response({ statusCode: 500, - body: { message: "ERROR: osDomain env variable is required" }, + body: { message: `ERROR: ${error?.message || error}` }, }); } + if (!event.body) { return response({ statusCode: 400, body: { message: "Event body required" }, }); } - if (!process.env.osDomain) { - return response({ - statusCode: 500, - body: { message: "Handler is missing process.env.osDomain env var" }, - }); - } try { const body = JSON.parse(event.body); @@ -72,12 +70,7 @@ export const handler = async (event: APIGatewayEvent) => { } // Now we can generate the presigned url - const url = await generatePresignedUrl( - body.bucket, - body.key, - body.filename, - 60, - ); + const url = await generatePresignedUrl(body.bucket, body.key, body.filename, 60); return response({ statusCode: 200, diff --git a/lib/lambda/getCpocs.ts b/lib/lambda/getCpocs.ts index 5efc373159..c98d5a5867 100644 --- a/lib/lambda/getCpocs.ts +++ b/lib/lambda/getCpocs.ts @@ -2,13 +2,12 @@ import { handleOpensearchError } from "./utils"; import { APIGatewayEvent } from "aws-lambda"; import * as os from "libs/opensearch-lib"; import { response } from "libs/handler-lib"; +import { getDomainAndNamespace } from "libs/utils"; // type GetCpocsBody = object; export const queryCpocs = async () => { - if (!process.env.osDomain) { - throw new Error("process.env.osDomain must be defined"); - } + const { index, domain } = getDomainAndNamespace("cpocs"); const query = { size: 1000, @@ -20,11 +19,7 @@ export const queryCpocs = async () => { }, ], }; - return await os.search( - process.env.osDomain, - `${process.env.indexNamespace}cpocs`, - query, - ); + return await os.search(domain, index, query); }; export const getCpocs = async (event: APIGatewayEvent) => { @@ -47,7 +42,7 @@ export const getCpocs = async (event: APIGatewayEvent) => { body: result, }); } catch (err) { - return response(handleOpensearchError(err)) + return response(handleOpensearchError(err)); } }; diff --git a/lib/lambda/getSubTypes.ts b/lib/lambda/getSubTypes.ts index 3f1d44f56e..95ae6ff9f3 100644 --- a/lib/lambda/getSubTypes.ts +++ b/lib/lambda/getSubTypes.ts @@ -1,7 +1,8 @@ -import { handleOpensearchError } from "./utils"; +import { handleOpensearchError } from "./utils"; import { APIGatewayEvent } from "aws-lambda"; import { response } from "libs/handler-lib"; import * as os from "libs/opensearch-lib"; +import { getDomainAndNamespace } from "libs/utils"; type GetSubTypesBody = { authorityId: string; @@ -9,9 +10,7 @@ type GetSubTypesBody = { }; export const querySubTypes = async (authorityId: string, typeIds: string[]) => { - if (!process.env.osDomain) { - throw new Error("process.env.osDomain must be defined"); - } + const { index, domain } = getDomainAndNamespace("subtypes"); const query = { size: 200, @@ -49,7 +48,7 @@ export const querySubTypes = async (authorityId: string, typeIds: string[]) => { ], }; - return await os.search(process.env.osDomain, `${process.env.indexNamespace}subtypes`, query); + return await os.search(domain, index, query); }; export const getSubTypes = async (event: APIGatewayEvent) => { @@ -74,7 +73,7 @@ export const getSubTypes = async (event: APIGatewayEvent) => { body: result, }); } catch (err) { - return response(handleOpensearchError(err)) + return response(handleOpensearchError(err)); } }; diff --git a/lib/lambda/getTypes.ts b/lib/lambda/getTypes.ts index 21eb17d7ab..ff3f5c0e2f 100644 --- a/lib/lambda/getTypes.ts +++ b/lib/lambda/getTypes.ts @@ -2,15 +2,14 @@ import { handleOpensearchError } from "./utils"; import { APIGatewayEvent } from "aws-lambda"; import * as os from "libs/opensearch-lib"; import { response } from "libs/handler-lib"; +import { getDomainAndNamespace } from "libs/utils"; type GetTypesBody = { authorityId: string; }; export const queryTypes = async (authorityId: string) => { - if (!process.env.osDomain) { - throw new Error("process.env.osDomain must be defined"); - } + const { index, domain } = getDomainAndNamespace("types"); const query = { size: 200, @@ -42,11 +41,7 @@ export const queryTypes = async (authorityId: string) => { }, ], }; - return await os.search( - process.env.osDomain, - `${process.env.indexNamespace}types`, - query, - ); + return await os.search(domain, index, query); }; export const getTypes = async (event: APIGatewayEvent) => { diff --git a/lib/lambda/itemExists.test.ts b/lib/lambda/itemExists.test.ts index fba774d836..e1613b2980 100644 --- a/lib/lambda/itemExists.test.ts +++ b/lib/lambda/itemExists.test.ts @@ -55,7 +55,7 @@ describe("Handler for checking if record exists", () => { ); }); - it("should return 500 error occurs during processing", async () => { + it("should return 200 and exists: false if an error occurs during processing", async () => { const event = { body: JSON.stringify({ id: GET_ERROR_ITEM_ID }), } as APIGatewayEvent; @@ -63,9 +63,9 @@ describe("Handler for checking if record exists", () => { const res = await handler(event); expect(res).toBeTruthy(); - expect(res.statusCode).toEqual(500); + expect(res.statusCode).toEqual(200); expect(res.body).toEqual( - JSON.stringify({ error: "Internal server error", message: "Response Error" }), + JSON.stringify({ message: "No record found for the given id", exists: false }), ); }); }); diff --git a/lib/lambda/search.test.ts b/lib/lambda/search.test.ts index 07f10acfad..2d51b35d21 100644 --- a/lib/lambda/search.test.ts +++ b/lib/lambda/search.test.ts @@ -29,7 +29,7 @@ describe("getSearchData Handler", () => { const body = JSON.parse(res.body); expect(body).toBeTruthy(); expect(body?.hits?.hits).toBeTruthy(); - expect(body?.hits?.hits?.length).toEqual(11); + expect(body?.hits?.hits?.length).toEqual(12); }); it("should handle errors during processing", async () => { diff --git a/lib/lambda/search.ts b/lib/lambda/search.ts index f823579122..6e4a4aa8d1 100644 --- a/lib/lambda/search.ts +++ b/lib/lambda/search.ts @@ -1,21 +1,26 @@ import { handleOpensearchError } from "./utils"; import { APIGatewayEvent } from "aws-lambda"; import { response } from "libs/handler-lib"; -import { Index } from "shared-types/opensearch"; +import { BaseIndex } from "shared-types/opensearch"; import { validateEnvVariable } from "shared-utils"; import { getStateFilter } from "../libs/api/auth/user"; import { getAppkChildren } from "../libs/api/package"; import * as os from "../libs/opensearch-lib"; +import { getDomainAndNamespace } from "libs/utils"; // Handler function to search index export const getSearchData = async (event: APIGatewayEvent) => { validateEnvVariable("osDomain"); + if (!event.pathParameters || !event.pathParameters.index) { return response({ statusCode: 400, body: { message: "Index path parameter required" }, }); } + + const { domain, index } = getDomainAndNamespace(event.pathParameters.index as BaseIndex); + try { let query: any = {}; if (event.body) { @@ -42,11 +47,7 @@ export const getSearchData = async (event: APIGatewayEvent) => { query.from = query.from || 0; query.size = query.size || 100; - const results = await os.search( - process.env.osDomain as string, - `${process.env.indexNamespace}${event.pathParameters.index}` as Index, - query, - ); + const results = await os.search(domain, index, query); for (let i = 0; i < results?.hits?.hits?.length; i++) { if (results.hits.hits[i]._source?.appkParent) { diff --git a/lib/libs/api/package/appk.test.ts b/lib/libs/api/package/appk.test.ts index 8beb6c179a..64717451b0 100644 --- a/lib/libs/api/package/appk.test.ts +++ b/lib/libs/api/package/appk.test.ts @@ -1,87 +1,75 @@ -import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; -import * as os from "../../opensearch-lib"; +import { describe, it, expect, vi, afterEach } from "vitest"; import { getAppkChildren } from "./appk"; -import { opensearch } from "shared-types"; - -vi.mock("../../opensearch-lib"); +import { + OPENSEARCH_DOMAIN, + INITIAL_RELEASE_APPK_ITEM_ID, + EXISTING_ITEM_APPROVED_APPK_ITEM_ID, +} from "mocks"; describe("getAppkChildren", () => { - const mockOsDomain = "mock-os-domain"; - const mockIndexNamespace = "mock-index-namespace"; - const mockPackageId = "mock-package-id"; - const mockFilter = [{ term: { status: "active" } }]; - const mockResponse = { - hits: { - hits: [ - { - _source: { - timestamp: "2024-01-01T00:00:00Z", - change: "Initial release", - }, - }, - ], - }, - } as unknown as opensearch.main.Response; - - beforeEach(() => { - vi.resetModules(); - process.env.osDomain = mockOsDomain; - process.env.indexNamespace = mockIndexNamespace; - }); - afterEach(() => { vi.clearAllMocks(); }); it("should throw an error if osDomain is not defined", async () => { delete process.env.osDomain; - await expect(getAppkChildren(mockPackageId)).rejects.toThrow( + await expect(getAppkChildren(INITIAL_RELEASE_APPK_ITEM_ID)).rejects.toThrow( "process.env.osDomain must be defined", ); + process.env.osDomain = OPENSEARCH_DOMAIN; }); it("should return the children with the specified packageId and no additional filters", async () => { - vi.mocked(os.search).mockResolvedValue(mockResponse); + const result = await getAppkChildren(INITIAL_RELEASE_APPK_ITEM_ID); - const result = await getAppkChildren(mockPackageId); - - expect(os.search).toHaveBeenCalledWith( - mockOsDomain, - `${mockIndexNamespace}main`, - { - from: 0, - size: 200, - query: { - bool: { - must: [{ term: { "appkParentId.keyword": mockPackageId } }], + expect(result).toEqual( + expect.objectContaining({ + hits: { + total: { + value: 1, + relation: "eq", }, + max_score: null, + hits: [ + { + _source: { + changedDate: "2024-01-01T00:00:00Z", + title: "Initial release", + cmsStatus: "Pending", + stateStatus: "Under Review", + }, + }, + ], }, - }, + }), ); - expect(result).toEqual(mockResponse); }); it("should return the children with the specified packageId and additional filters", async () => { - vi.mocked(os.search).mockResolvedValue(mockResponse); - - const result = await getAppkChildren(mockPackageId, mockFilter); + const result = await getAppkChildren(EXISTING_ITEM_APPROVED_APPK_ITEM_ID, [ + { term: { cmsStatus: "Approved" } }, + ]); - expect(os.search).toHaveBeenCalledWith( - mockOsDomain, - `${mockIndexNamespace}main`, - { - from: 0, - size: 200, - query: { - bool: { - must: [ - { term: { "appkParentId.keyword": mockPackageId } }, - ...mockFilter, - ], + expect(result).toEqual( + expect.objectContaining({ + hits: { + total: { + value: 1, + relation: "eq", }, + max_score: null, + hits: [ + { + _source: { + changedDate: "2025-01-08T00:00:00Z", + title: "Approved release", + cmsStatus: "Approved", + stateStatus: "Approved", + }, + }, + ], }, - }, + }), ); - expect(result).toEqual(mockResponse); }); }); diff --git a/lib/libs/api/package/appk.ts b/lib/libs/api/package/appk.ts index 72b417935c..cb49354e39 100644 --- a/lib/libs/api/package/appk.ts +++ b/lib/libs/api/package/appk.ts @@ -1,29 +1,19 @@ import * as os from "../../opensearch-lib"; import { opensearch } from "shared-types"; +import { getDomainAndNamespace } from "../../utils"; -export const getAppkChildren = async ( - packageId: string, - filter: any[] = [], -) => { - if (!process.env.osDomain) { - throw new Error("process.env.osDomain must be defined"); - } +export const getAppkChildren = async (packageId: string, filter: any[] = []) => { + const { domain, index } = getDomainAndNamespace("main"); - const response = (await os.search( - process.env.osDomain, - `${process.env.indexNamespace}main`, - { - from: 0, - size: 200, - query: { - bool: { - must: [{ term: { "appkParentId.keyword": packageId } }].concat( - filter, - ), - }, + const response = (await os.search(domain, index, { + from: 0, + size: 200, + query: { + bool: { + must: [{ term: { "appkParentId.keyword": packageId } }].concat(filter), }, }, - )) as opensearch.main.Response; + })) as opensearch.main.Response; return response; }; diff --git a/lib/libs/api/package/changelog.ts b/lib/libs/api/package/changelog.ts index 83682b5856..8f1f81c2c4 100644 --- a/lib/libs/api/package/changelog.ts +++ b/lib/libs/api/package/changelog.ts @@ -1,26 +1,18 @@ import * as os from "libs/opensearch-lib"; import { opensearch } from "shared-types"; +import { getDomainAndNamespace } from "../../utils"; -export const getPackageChangelog = async ( - packageId: string, - filter: any[] = [], -) => { - if (!process.env.osDomain) { - throw new Error("process.env.osDomain must be defined"); - } +export const getPackageChangelog = async (packageId: string, filter: any[] = []) => { + const { domain, index } = getDomainAndNamespace("changelog"); - return (await os.search( - process.env.osDomain, - `${process.env.indexNamespace}changelog`, - { - from: 0, - size: 200, - sort: [{ timestamp: "desc" }], - query: { - bool: { - must: [{ term: { "packageId.keyword": packageId } }].concat(filter), - }, + return (await os.search(domain, index, { + from: 0, + size: 200, + sort: [{ timestamp: "desc" }], + query: { + bool: { + must: [{ term: { "packageId.keyword": packageId } }].concat(filter), }, }, - )) as opensearch.changelog.Response; + })) as opensearch.changelog.Response; }; diff --git a/lib/libs/api/package/getPackage.ts b/lib/libs/api/package/getPackage.ts index cf66117315..b1033356d7 100644 --- a/lib/libs/api/package/getPackage.ts +++ b/lib/libs/api/package/getPackage.ts @@ -1,18 +1,14 @@ import { ItemResult } from "lib/packages/shared-types/opensearch/main"; import * as os from "libs/opensearch-lib"; +import { getDomainAndNamespace } from "../../utils"; export interface ExtendedItemResult extends ItemResult { appkChildren?: any[]; } export const getPackage = async (id: string): Promise => { - if (!process.env.osDomain) { - throw new Error("process.env.osDomain must be defined"); - } - const packageResult = await os.getItem( - process.env.osDomain, - `${process.env.indexNamespace}main`, - id, - ); + const { domain, index } = getDomainAndNamespace("main"); + + const packageResult = await os.getItem(domain, index, id); return packageResult; }; diff --git a/lib/libs/api/package/itemExists.ts b/lib/libs/api/package/itemExists.ts index 694315baa0..c5172f161b 100644 --- a/lib/libs/api/package/itemExists.ts +++ b/lib/libs/api/package/itemExists.ts @@ -1,14 +1,22 @@ import * as os from "../../../libs/opensearch-lib"; +import { getDomain, getNamespace } from "libs/utils"; +import { BaseIndex } from "lib/packages/shared-types/opensearch"; export async function itemExists(params: { id: string; osDomain?: string; indexNamespace?: string; }): Promise { - const packageResult = await os.getItem( - params.osDomain || process.env.osDomain!, - `${params.indexNamespace || process.env.indexNamespace!}main`, - params.id, - ); - return !!packageResult?._source; + try { + const domain = params.osDomain || getDomain(); + const index: `${string}${BaseIndex}` = params.indexNamespace + ? `${params.indexNamespace}main` + : getNamespace("main"); + + const packageResult = await os.getItem(domain, index, params.id); + return !!packageResult?._source; + } catch (error) { + console.error(error); + return false; + } } diff --git a/lib/libs/sink-lib.ts b/lib/libs/sink-lib.ts index 491387ff01..2eb6cceb8b 100644 --- a/lib/libs/sink-lib.ts +++ b/lib/libs/sink-lib.ts @@ -3,6 +3,7 @@ const logger = pino(); import * as os from "./opensearch-lib"; import { BaseIndex } from "lib/packages/shared-types/opensearch"; +import { getDomainAndNamespace } from "./utils"; export function getTopic(topicPartition: string) { return topicPartition.split("--").pop()?.split("-").slice(0, -1)[0]; @@ -82,32 +83,6 @@ const prettyPrintJsonInObject = (obj: any): any => { return obj; }; -/** - * Returns the `osDomain` and `indexNamespace` env variables. Passing `baseIndex` appends the arg to the `index` variable - * @throws if env variables are not defined, `getDomainAndNamespace` throws error indicating which variable is missing - * @returns - */ -export function getDomainAndNamespace( - baseIndex: T, -): { domain: string; index: `${string}${T}` }; - -export function getDomainAndNamespace(baseIndex?: BaseIndex) { - const domain = process.env.osDomain; - const indexNamespace = process.env.indexNamespace ?? ""; - - if (domain === undefined) { - throw new Error("osDomain is undefined in environment variables"); - } - - if (indexNamespace == "" && process.env.isDev == "true") { - throw new Error("indexName is undefined in environment variables"); - } - - const index = `${indexNamespace}${baseIndex}`; - - return { index, domain }; -} - export async function bulkUpdateDataWrapper( docs: { id: string; [key: string]: unknown }[], baseIndex: BaseIndex, diff --git a/lib/libs/utils.ts b/lib/libs/utils.ts new file mode 100644 index 0000000000..fb7809d806 --- /dev/null +++ b/lib/libs/utils.ts @@ -0,0 +1,52 @@ +import { BaseIndex, Index } from "lib/packages/shared-types/opensearch"; + +/** + * Returns the `osDomain` + * @throws if env variables are not defined, `getDomain` throws error indicating if variable is missing + * @returns the value of `osDomain` + */ +export function getDomain(): string; +export function getDomain(): string { + const domain = process.env.osDomain; + + if (domain === undefined) { + throw new Error("process.env.osDomain must be defined"); + } + + return domain; +} + +/** + * Returns the `indexNamespace` env variables. Passing `baseIndex` appends the arg to the `index` variable + * @throws if env variables are not defined, `getNamespace` throws error indicating if variable is missing and + * the environment the application is running on `isDev` + * @returns the value of `indexNamespace` or empty string if not in development + */ +export function getNamespace(baseIndex?: T): Index; +export function getNamespace(baseIndex?: BaseIndex) { + const indexNamespace = process.env.indexNamespace ?? ""; + + if (indexNamespace == "" && process.env.isDev == "true") { + throw new Error("process.env.indexNamespace must be defined"); + } + + const index = `${indexNamespace}${baseIndex}`; + + return index; +} + +/** + * Returns the `osDomain` and `indexNamespace` env variables. Passing `baseIndex` appends the arg to the `index` variable + * @throws if env variables are not defined, `getDomainAndNamespace` throws error indicating which variable is missing + * @returns + */ +export function getDomainAndNamespace( + baseIndex: T, +): { domain: string; index: Index }; + +export function getDomainAndNamespace(baseIndex: BaseIndex) { + const domain = getDomain(); + const index = getNamespace(baseIndex); + + return { index, domain }; +} diff --git a/mocks/data/items.ts b/mocks/data/items.ts index d302cfdac3..668d39184c 100644 --- a/mocks/data/items.ts +++ b/mocks/data/items.ts @@ -8,7 +8,7 @@ export const EXISTING_ITEM_APPROVED_AMEND_ID = "MD-0000.R00.01"; export const EXISTING_ITEM_APPROVED_RENEW_ID = "MD-0000.R01.00"; export const EXISTING_ITEM_ID = "MD-00-0000"; export const NOT_FOUND_ITEM_ID = "MD-0004.R00.00"; -export const NOT_EXISTING_ITEM_ID = "MD-11-0000" +export const NOT_EXISTING_ITEM_ID = "MD-11-0000"; export const TEST_ITEM_ID = "MD-0005.R01.00"; export const EXISTING_ITEM_TEMPORARY_EXTENSION_ID = "MD-0005.R01.TE00"; export const HI_TEST_ITEM_ID = "HI-0000.R00.00"; @@ -19,6 +19,7 @@ export const CONTRACTING_AMEND_ITEM_ID = "MD-007.R00.01"; export const MISSING_CHANGELOG_ITEM_ID = "MD-008.R00.00"; export const WITHDRAWN_CHANGELOG_ITEM_ID = "MD-009.R00.01"; export const INITIAL_RELEASE_APPK_ITEM_ID = "MD-010.R00.01"; +export const EXISTING_ITEM_APPROVED_APPK_ITEM_ID = "MD-012.R00.01"; export const SUBMISSION_ERROR_ITEM_ID = "Throw Submission Error"; export const GET_ERROR_ITEM_ID = "Throw Get Item Error"; @@ -334,6 +335,38 @@ const items: Record = { _source: { changedDate: "2024-01-01T00:00:00Z", title: "Initial release", + cmsStatus: "Pending", + stateStatus: "Under Review", + }, + }, + ], + }, + }, + [EXISTING_ITEM_APPROVED_APPK_ITEM_ID]: { + _id: EXISTING_ITEM_APPROVED_APPK_ITEM_ID, + found: true, + _source: { + id: EXISTING_ITEM_APPROVED_APPK_ITEM_ID, + seatoolStatus: SEATOOL_STATUS.APPROVED, + actionType: "New", + authority: "1915(c)", + state: "MD", + origin: "OneMAC", + appkChildren: [ + { + _source: { + changedDate: "2024-01-01T00:00:00Z", + title: "Initial release", + cmsStatus: "Pending", + stateStatus: "Under Review", + }, + }, + { + _source: { + changedDate: "2025-01-08T00:00:00Z", + title: "Approved release", + cmsStatus: "Approved", + stateStatus: "Approved", }, }, ], diff --git a/mocks/handlers/opensearch/main.ts b/mocks/handlers/opensearch/main.ts index 9617c9b4ba..3985c34c54 100644 --- a/mocks/handlers/opensearch/main.ts +++ b/mocks/handlers/opensearch/main.ts @@ -28,18 +28,16 @@ const defaultMainSearchHandler = http.post( "https://vpc-opensearchdomain-mock-domain.us-east-1.es.amazonaws.com/test-namespace-main/_search", async ({ request }) => { const { query } = await request.json(); - console.log({ query }) if (query?.match_all?.id == "throw-error") { return new HttpResponse("Internal server error", { status: 500 }); } const must = query?.bool?.must; - console.log("must: ", JSON.stringify(must)) const mustTerms = getTermKeys(must); - console.log({ mustTerms }) - const appkParentIdValue = getTermValues(must, "appkParentId.keyword") || getTermValues(must, "appkParentId"); + const appkParentIdValue = + getTermValues(must, "appkParentId.keyword") || getTermValues(must, "appkParentId"); if (appkParentIdValue) { const appkParentId = @@ -57,14 +55,22 @@ const defaultMainSearchHandler = http.post( let appkChildren: TestAppkItemResult[] = (item._source?.appkChildren as TestAppkItemResult[]) || []; if (appkChildren.length > 0) { - mustTerms.forEach((term) => { + // TODO We don't have this field in the TypeScript, not sure what the parent field actually is + const filteredTerms = mustTerms.filter( + (term) => term !== "appkParentId.keyword" && term !== "appkParentId", + ); + filteredTerms.forEach((term) => { const filterValue = getTermValues(must, term); const filterTerm: keyof TestAppkDocument = term.replace( ".keyword", "", ) as keyof TestAppkDocument; if (filterValue) { - appkChildren = filterItemsByTerm(appkChildren, filterTerm, filterValue); + appkChildren = filterItemsByTerm( + appkChildren, + filterTerm, + filterValue, + ); } }); } @@ -95,12 +101,10 @@ const defaultMainSearchHandler = http.post( if (itemHits.length > 0) { mustTerms.forEach((term) => { const filterValue = getTermValues(must, term); - console.log({ filterValue }) const filterTerm: keyof TestMainDocument = term.replace( ".keyword", "", ) as keyof TestMainDocument; - console.log({ filterTerm }) if (filterValue) { itemHits = filterItemsByTerm(itemHits, filterTerm, filterValue); } From 5222e57a3e2222439ce35c4a40a687821b44b34d Mon Sep 17 00:00:00 2001 From: Tiffany Forkner Date: Wed, 8 Jan 2025 15:10:43 -0500 Subject: [PATCH 2/4] test fix --- lib/lambda/search.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/lambda/search.test.ts b/lib/lambda/search.test.ts index 2d51b35d21..9e7e779fc7 100644 --- a/lib/lambda/search.test.ts +++ b/lib/lambda/search.test.ts @@ -29,7 +29,7 @@ describe("getSearchData Handler", () => { const body = JSON.parse(res.body); expect(body).toBeTruthy(); expect(body?.hits?.hits).toBeTruthy(); - expect(body?.hits?.hits?.length).toEqual(12); + expect(body?.hits?.hits?.length).toEqual(13); }); it("should handle errors during processing", async () => { From 99ea3e88b45caef8bd0bac6a47c3df296f4f384e Mon Sep 17 00:00:00 2001 From: Tiffany Forkner Date: Wed, 8 Jan 2025 15:14:40 -0500 Subject: [PATCH 3/4] fixing imports --- lib/lambda/sinkChangelog.ts | 4 ++-- lib/lambda/sinkMain.test.ts | 2 +- lib/lambda/sinkMainProcessors.test.ts | 2 +- lib/lambda/update/getPackageType.ts | 6 +++--- lib/lambda/update/updatePackage.ts | 2 +- lib/libs/api/package/getPackage.ts | 2 +- .../withdrawPackage/emailTemplates/ChipSpaCMS.tsx | 2 +- .../withdrawPackage/emailTemplates/ChipSpaState.tsx | 2 +- lib/libs/opensearch-lib.ts | 9 ++++++--- lib/libs/sink-lib.ts | 2 +- 10 files changed, 18 insertions(+), 15 deletions(-) diff --git a/lib/lambda/sinkChangelog.ts b/lib/lambda/sinkChangelog.ts index d2fe78a00c..038c003afd 100644 --- a/lib/lambda/sinkChangelog.ts +++ b/lib/lambda/sinkChangelog.ts @@ -1,13 +1,13 @@ import { Handler } from "aws-lambda"; import { decodeBase64WithUtf8 } from "shared-utils"; import { KafkaEvent, KafkaRecord, opensearch } from "shared-types"; -import { ErrorType, bulkUpdateDataWrapper, getTopic, logError } from "../libs/sink-lib"; +import { ErrorType, bulkUpdateDataWrapper, getTopic, logError } from "libs/sink-lib"; import { transformUpdateValuesSchema, transformDeleteSchema, transformedUpdateIdSchema, } from "./update/adminChangeSchemas"; -import { getPackageChangelog } from "lib/libs/api/package"; +import { getPackageChangelog } from "libs/api/package"; // One notable difference between this handler and sinkMain's... // The order in which records are processed for the changelog doesn't matter. diff --git a/lib/lambda/sinkMain.test.ts b/lib/lambda/sinkMain.test.ts index 1efa64a139..54516cd6ff 100644 --- a/lib/lambda/sinkMain.test.ts +++ b/lib/lambda/sinkMain.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect, vi, afterEach } from "vitest"; import { handler } from "./sinkMain"; import * as sinkMainProcessors from "./sinkMainProcessors"; -import { KafkaEvent } from "lib/packages/shared-types"; +import { KafkaEvent } from "shared-types"; const createKafkaEvent = (records: KafkaEvent["records"]) => ({ eventSource: "SelfManagedKafka", diff --git a/lib/lambda/sinkMainProcessors.test.ts b/lib/lambda/sinkMainProcessors.test.ts index 4e4f31f5ee..c40744308a 100644 --- a/lib/lambda/sinkMainProcessors.test.ts +++ b/lib/lambda/sinkMainProcessors.test.ts @@ -7,7 +7,7 @@ import { import * as sinkLib from "libs"; import { Document, seatool } from "shared-types/opensearch/main"; import { offsetToUtc } from "shared-utils"; -import { KafkaRecord } from "lib/packages/shared-types"; +import { KafkaRecord } from "shared-types"; const convertObjToBase64 = (obj: object) => Buffer.from(JSON.stringify(obj)).toString("base64"); diff --git a/lib/lambda/update/getPackageType.ts b/lib/lambda/update/getPackageType.ts index 7383efae94..f1eca6e296 100644 --- a/lib/lambda/update/getPackageType.ts +++ b/lib/lambda/update/getPackageType.ts @@ -1,6 +1,6 @@ -import { response } from "lib/libs/handler-lib"; -import { events } from "lib/packages/shared-types"; -import { getPackageChangelog } from "lib/libs/api/package"; +import { response } from "libs/handler-lib"; +import { events } from "shared-types"; +import { getPackageChangelog } from "libs/api/package"; export const getPackageType = async (packageId: string) => { // use event of current package to determine how ID should be formatted diff --git a/lib/lambda/update/updatePackage.ts b/lib/lambda/update/updatePackage.ts index 24592a66a6..dd9c4109f5 100644 --- a/lib/lambda/update/updatePackage.ts +++ b/lib/lambda/update/updatePackage.ts @@ -4,7 +4,7 @@ import { getPackage } from "libs/api/package"; import { produceMessage } from "libs/api/kafka"; import { ItemResult } from "shared-types/opensearch/main"; import { getPackageType } from "./getPackageType"; -import { events } from "lib/packages/shared-types"; +import { events } from "shared-types"; import { z } from "zod"; const sendDeleteMessage = async (packageId: string) => { diff --git a/lib/libs/api/package/getPackage.ts b/lib/libs/api/package/getPackage.ts index b1033356d7..5ca6d28c20 100644 --- a/lib/libs/api/package/getPackage.ts +++ b/lib/libs/api/package/getPackage.ts @@ -1,4 +1,4 @@ -import { ItemResult } from "lib/packages/shared-types/opensearch/main"; +import { ItemResult } from "shared-types/opensearch/main"; import * as os from "libs/opensearch-lib"; import { getDomainAndNamespace } from "../../utils"; diff --git a/lib/libs/email/content/withdrawPackage/emailTemplates/ChipSpaCMS.tsx b/lib/libs/email/content/withdrawPackage/emailTemplates/ChipSpaCMS.tsx index af88ecdedd..755e587165 100644 --- a/lib/libs/email/content/withdrawPackage/emailTemplates/ChipSpaCMS.tsx +++ b/lib/libs/email/content/withdrawPackage/emailTemplates/ChipSpaCMS.tsx @@ -1,4 +1,4 @@ -import { CommonEmailVariables, Events } from "lib/packages/shared-types"; +import { CommonEmailVariables, Events } from "shared-types"; import { BasicFooter, Divider, PackageDetails } from "../../email-components"; import { BaseEmailTemplate } from "../../email-templates"; diff --git a/lib/libs/email/content/withdrawPackage/emailTemplates/ChipSpaState.tsx b/lib/libs/email/content/withdrawPackage/emailTemplates/ChipSpaState.tsx index e7e3ed7110..a60d8fb927 100644 --- a/lib/libs/email/content/withdrawPackage/emailTemplates/ChipSpaState.tsx +++ b/lib/libs/email/content/withdrawPackage/emailTemplates/ChipSpaState.tsx @@ -1,4 +1,4 @@ -import { CommonEmailVariables, Events } from "lib/packages/shared-types"; +import { CommonEmailVariables, Events } from "shared-types"; import { BasicFooter, FollowUpNotice, Divider, PackageDetails } from "../../email-components"; import { BaseEmailTemplate } from "../../email-templates"; diff --git a/lib/libs/opensearch-lib.ts b/lib/libs/opensearch-lib.ts index 25ef6020c6..8a8edc3ff0 100644 --- a/lib/libs/opensearch-lib.ts +++ b/lib/libs/opensearch-lib.ts @@ -4,7 +4,7 @@ import { Client, Connection, errors as OpensearchErrors } from "@opensearch-proj import * as aws4 from "aws4"; import { aws4Interceptor } from "aws4-axios"; import axios from "axios"; -import { ItemResult, Document as OSDocument } from "lib/packages/shared-types/opensearch/main"; +import { ItemResult, Document as OSDocument } from "shared-types/opensearch/main"; import { opensearch } from "shared-types"; import { getDomainAndNamespace } from "./sink-lib"; @@ -185,9 +185,12 @@ export async function getItem( const response = await client.get({ id, index }); return decodeUtf8(response).body; } catch (error) { - if (error instanceof OpensearchErrors.ResponseError && error.statusCode === 404 || error.meta?.statusCode === 404) { + if ( + (error instanceof OpensearchErrors.ResponseError && error.statusCode === 404) || + error.meta?.statusCode === 404 + ) { console.log("Error (404) retrieving in OpenSearch:", error); - return undefined + return undefined; } throw error; } diff --git a/lib/libs/sink-lib.ts b/lib/libs/sink-lib.ts index 2eb6cceb8b..524e8a3cb8 100644 --- a/lib/libs/sink-lib.ts +++ b/lib/libs/sink-lib.ts @@ -2,7 +2,7 @@ import pino from "pino"; const logger = pino(); import * as os from "./opensearch-lib"; -import { BaseIndex } from "lib/packages/shared-types/opensearch"; +import { BaseIndex } from "shared-types/opensearch"; import { getDomainAndNamespace } from "./utils"; export function getTopic(topicPartition: string) { From 2e5813f0d4e13d15f8c5af3372c77e26de405471 Mon Sep 17 00:00:00 2001 From: Tiffany Forkner Date: Wed, 8 Jan 2025 15:32:15 -0500 Subject: [PATCH 4/4] fixed import --- lib/libs/opensearch-lib.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/libs/opensearch-lib.ts b/lib/libs/opensearch-lib.ts index 8a8edc3ff0..521b17d969 100644 --- a/lib/libs/opensearch-lib.ts +++ b/lib/libs/opensearch-lib.ts @@ -6,7 +6,7 @@ import { aws4Interceptor } from "aws4-axios"; import axios from "axios"; import { ItemResult, Document as OSDocument } from "shared-types/opensearch/main"; import { opensearch } from "shared-types"; -import { getDomainAndNamespace } from "./sink-lib"; +import { getDomainAndNamespace } from "./utils"; let client: Client;