From f701d2f6b43a6661a1710172be62c37cd1e0943a Mon Sep 17 00:00:00 2001 From: Tom Richards Date: Wed, 14 Dec 2022 14:14:44 +0000 Subject: [PATCH] WIP - call out to Octopus Imaging API from `database-bridge-lambda` in `createItem` mutation if the `type` is `imaging-request` --- database-bridge-lambda/package.json | 6 ++-- database-bridge-lambda/run.ts | 33 ++++++++++++++----- .../src/imagingRequestCallout.ts | 27 +++++++++++++++ database-bridge-lambda/src/sql/Item.ts | 30 +++++++++++++++-- shared/octopusImaging.ts | 1 + 5 files changed, 84 insertions(+), 13 deletions(-) create mode 100644 database-bridge-lambda/src/imagingRequestCallout.ts create mode 100644 shared/octopusImaging.ts diff --git a/database-bridge-lambda/package.json b/database-bridge-lambda/package.json index 8966105b..93a72ff2 100644 --- a/database-bridge-lambda/package.json +++ b/database-bridge-lambda/package.json @@ -12,9 +12,11 @@ "devDependencies": { "@types/aws-lambda": "^8.10.102", "aws-sdk": "^2.840.0", - "ts-node-dev": "^1.0.0" + "ts-node-dev": "^1.0.0", + "@types/node-fetch": "2" }, "dependencies": { - "postgres": "^3.2.4" + "postgres": "^3.2.4", + "node-fetch": "2" } } diff --git a/database-bridge-lambda/run.ts b/database-bridge-lambda/run.ts index a78b2a05..c50311cd 100644 --- a/database-bridge-lambda/run.ts +++ b/database-bridge-lambda/run.ts @@ -4,6 +4,7 @@ import { createDatabaseTunnel } from "../shared/database/local/databaseTunnel"; import prompts from "prompts"; import { DatabaseOperation } from "../shared/graphql/operations"; import { getYourEmail } from "../shared/local/yourEmail"; +import { performImagingRequest } from "./src/imagingRequestCallout"; (async () => { const baseInput = { @@ -29,16 +30,30 @@ import { getYourEmail } from "../shared/local/yourEmail"; type: "select", name: "inputPayload", message: "Operation?", - choices: Object.entries(sampleInputs).map(([operation, sampleInput]) => ({ - title: operation, - value: { - ...baseInput, - arguments: sampleInput, - info: { fieldName: operation }, - } as AppSyncResolverEvent, - })), + choices: [ + { title: "SAMPLE IMAGING ORDER", value: "imaging-request" }, + ...Object.entries(sampleInputs).map(([operation, sampleInput]) => ({ + title: operation, + value: { + ...baseInput, + arguments: sampleInput, + info: { fieldName: operation }, + } as AppSyncResolverEvent, + })), + ], }); - console.log(JSON.stringify(await handler(inputPayload), null, 2)); + console.log( + JSON.stringify( + inputPayload === "imaging-request" + ? await performImagingRequest({ + item: {} as any, + existingPayload: {}, + }) + : await handler(inputPayload), + null, + 2 + ) + ); } })(); diff --git a/database-bridge-lambda/src/imagingRequestCallout.ts b/database-bridge-lambda/src/imagingRequestCallout.ts new file mode 100644 index 00000000..2376723f --- /dev/null +++ b/database-bridge-lambda/src/imagingRequestCallout.ts @@ -0,0 +1,27 @@ +import fetch from "node-fetch"; +import { Item } from "../../shared/graphql/graphql"; +import { pinboardConfigPromiseGetter } from "../../shared/awsIntegration"; + +export const performImagingRequest = async ({ + //TODO don't pass the whole item, just the fields we need + item, + existingPayload, +}: { + item: Item; + existingPayload: any; +}) => { + console.log("performImagingRequest", item, existingPayload); + const response = await fetch( + await pinboardConfigPromiseGetter("octopus/imaging/orderURL"), + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ bob: "hope", frank: " sinatra" }), + //TODO auth?? + } + ); + const responseJSON = (await response.json()) as { bob: string }; + return responseJSON.bob; +}; diff --git a/database-bridge-lambda/src/sql/Item.ts b/database-bridge-lambda/src/sql/Item.ts index 453f3da2..b0488472 100644 --- a/database-bridge-lambda/src/sql/Item.ts +++ b/database-bridge-lambda/src/sql/Item.ts @@ -4,6 +4,8 @@ import { PinboardIdWithClaimCounts, } from "../../../shared/graphql/graphql"; import { Sql } from "../../../shared/database/types"; +import { performImagingRequest } from "../imagingRequestCallout"; +import { IMAGING_REQUEST_ITEM_TYPE } from "../../../shared/octopusImaging"; const fragmentIndividualMentionsToMentionHandles = ( sql: Sql, @@ -57,10 +59,34 @@ export const createItem = async ( args: { input: CreateItemInput }, userEmail: string ) => - sql` + sql.begin(async (sql) => { + const insertResult = (await sql` INSERT INTO "Item" ${sql({ userEmail, ...args.input })} RETURNING ${fragmentItemFields(sql, userEmail)} - `.then((rows) => rows[0]); + `.then((rows) => rows[0])) as Item; + if ( + insertResult.type === IMAGING_REQUEST_ITEM_TYPE && + insertResult.payload + ) { + const existingPayload = JSON.parse(insertResult.payload); + // if this throws, the SQL transaction should be rolled back + const octopusImagingOrderId = await performImagingRequest({ + item: insertResult, + existingPayload, + }); + return sql` + UPDATE "Item" + SET "payload" = ${{ + ...existingPayload, + octopusImagingOrderId, + }}} + WHERE "id" = ${insertResult.id} + RETURNING ${fragmentItemFields(sql, userEmail)}`.then( + (rows) => rows[0] + ); + } + return insertResult; + }); export const listItems = ( sql: Sql, diff --git a/shared/octopusImaging.ts b/shared/octopusImaging.ts new file mode 100644 index 00000000..ccb8bb6c --- /dev/null +++ b/shared/octopusImaging.ts @@ -0,0 +1 @@ +export const IMAGING_REQUEST_ITEM_TYPE = "imaging-request";