-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(awell): start cf and session with one action (#531)
- Loading branch information
Showing
7 changed files
with
229 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
12 changes: 12 additions & 0 deletions
12
extensions/awell/v1/actions/startCareFlowAndSession/config/dataPoints.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { type DataPointDefinition } from '@awell-health/extensions-core' | ||
|
||
export const dataPoints = { | ||
careFlowId: { | ||
key: 'careFlowId', | ||
valueType: 'string', | ||
}, | ||
sessionUrl: { | ||
key: 'sessionUrl', | ||
valueType: 'string', | ||
}, | ||
} satisfies Record<string, DataPointDefinition> |
97 changes: 97 additions & 0 deletions
97
extensions/awell/v1/actions/startCareFlowAndSession/config/fields.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import { type BaselineInfoInput } from '@awell-health/awell-sdk' | ||
import { type Field, FieldType } from '@awell-health/extensions-core' | ||
import { isEmpty, isNil } from 'lodash' | ||
import { z, type ZodTypeAny } from 'zod' | ||
|
||
export const fields = { | ||
careFlowDefinitionId: { | ||
id: 'careFlowDefinitionId', | ||
label: 'Care flow definition ID', | ||
description: 'The definition ID of the care flow to start', | ||
type: FieldType.STRING, | ||
required: true, | ||
}, | ||
stakeholderDefinitionId: { | ||
id: 'stakeholderDefinitionId', | ||
label: 'Stakeholder definition ID', | ||
description: | ||
'The definition ID of the stakeholder to start the session for', | ||
type: FieldType.STRING, | ||
required: true, | ||
}, | ||
baselineInfo: { | ||
id: 'baselineInfo', | ||
label: 'Baseline info', | ||
description: | ||
'Use baseline info to pass values for data points when starting a care flow. This needs to be an array of objects, please read the documentation for more info.', | ||
type: FieldType.JSON, | ||
required: false, | ||
}, | ||
} satisfies Record<string, Field> | ||
|
||
export const FieldsValidationSchema = z.object({ | ||
careFlowDefinitionId: z.string().min(1), | ||
stakeholderDefinitionId: z.string().min(1), | ||
baselineInfo: z | ||
.optional(z.string()) | ||
.transform((str, ctx): BaselineInfoInput[] | undefined => { | ||
if (isNil(str) || isEmpty(str)) return undefined | ||
|
||
try { | ||
const parsedJson = JSON.parse(str) | ||
|
||
if (isEmpty(parsedJson)) { | ||
return undefined | ||
} | ||
|
||
if (!Array.isArray(parsedJson)) { | ||
ctx.addIssue({ | ||
code: 'custom', | ||
message: `Baseline info should be an array, it's currently a ${typeof parsedJson}.`, | ||
}) | ||
return z.NEVER | ||
} | ||
|
||
const allObjectsHaveKeys = parsedJson.every((obj) => { | ||
if (typeof obj !== 'object') { | ||
ctx.addIssue({ | ||
code: 'custom', | ||
message: `Item "${String( | ||
obj | ||
)}" in baseline info array is not an object.`, | ||
}) | ||
return z.NEVER | ||
} | ||
|
||
return 'data_point_definition_id' in obj && 'value' in obj | ||
}) | ||
|
||
const allObjectValuesAreStrings = parsedJson.every((obj) => { | ||
return Object.values(obj).every((v) => typeof v === 'string') | ||
}) | ||
|
||
if (!allObjectsHaveKeys) { | ||
ctx.addIssue({ | ||
code: 'custom', | ||
message: | ||
'Every object in the baseline info array should (only) have a `data_point_definition_id` and `value` field.', | ||
}) | ||
return z.NEVER | ||
} | ||
|
||
if (!allObjectValuesAreStrings) { | ||
ctx.addIssue({ | ||
code: 'custom', | ||
message: | ||
'Not all baseline info values are strings. Given data point values are polymorphic, the value for a data point should always be sent as a string.', | ||
}) | ||
return z.NEVER | ||
} | ||
|
||
return parsedJson | ||
} catch (e) { | ||
ctx.addIssue({ code: 'custom', message: 'Invalid JSON.' }) | ||
return z.NEVER | ||
} | ||
}), | ||
} satisfies Record<keyof typeof fields, ZodTypeAny>) |
2 changes: 2 additions & 0 deletions
2
extensions/awell/v1/actions/startCareFlowAndSession/config/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export { fields, FieldsValidationSchema } from './fields' | ||
export { dataPoints } from './dataPoints' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { startCareFlowAndSession } from './startCareFlowAndSession' |
56 changes: 56 additions & 0 deletions
56
extensions/awell/v1/actions/startCareFlowAndSession/startCareFlowAndSession.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { TestHelpers } from '@awell-health/extensions-core' | ||
import { generateTestPayload } from '../../../../../tests' | ||
import { startCareFlowAndSession } from './startCareFlowAndSession' | ||
|
||
jest.mock('../../sdk/awellSdk') | ||
|
||
describe('Start care flow', () => { | ||
const { onComplete, onError, helpers, extensionAction, clearMocks } = | ||
TestHelpers.fromAction(startCareFlowAndSession) | ||
const sdkMock = { | ||
orchestration: { | ||
mutation: jest.fn().mockResolvedValue({ | ||
startHostedPathwaySession: { | ||
pathway_id: 'a-care-flow-id', | ||
session_url: 'a-session-url', | ||
}, | ||
}), | ||
}, | ||
} | ||
|
||
helpers.awellSdk = jest.fn().mockResolvedValue(sdkMock) | ||
|
||
beforeEach(() => { | ||
clearMocks() | ||
}) | ||
|
||
test('Should call the onComplete callback', async () => { | ||
await extensionAction.onEvent({ | ||
payload: generateTestPayload({ | ||
fields: { | ||
careFlowDefinitionId: 'definition-id', | ||
stakeholderDefinitionId: 'stakeholder-id', | ||
}, | ||
patient: { | ||
id: '123', | ||
}, | ||
settings: {}, | ||
}), | ||
onComplete, | ||
onError, | ||
helpers, | ||
}) | ||
|
||
expect(onComplete).toHaveBeenCalled() | ||
expect(onComplete).toHaveBeenCalledWith({ | ||
data_points: { | ||
careFlowId: 'a-care-flow-id', | ||
sessionUrl: 'a-session-url', | ||
}, | ||
events: expect.any(Array), | ||
}) | ||
expect(helpers.awellSdk).toHaveBeenCalledTimes(1) | ||
expect(sdkMock.orchestration.mutation).toHaveBeenCalledTimes(1) | ||
expect(onError).not.toHaveBeenCalled() | ||
}) | ||
}) |
60 changes: 60 additions & 0 deletions
60
extensions/awell/v1/actions/startCareFlowAndSession/startCareFlowAndSession.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import { type Action } from '@awell-health/extensions-core' | ||
import { type settings } from '../../../settings' | ||
import { Category, validate } from '@awell-health/extensions-core' | ||
import { fields, dataPoints, FieldsValidationSchema } from './config' | ||
import { z } from 'zod' | ||
import { addActivityEventLog } from '../../../../../src/lib/awell/addEventLog' | ||
|
||
export const startCareFlowAndSession: Action<typeof fields, typeof settings> = { | ||
key: 'startCareFlowAndSession', | ||
category: Category.WORKFLOW, | ||
title: 'Start Care flow and session', | ||
description: 'Start a new care flow and immediately create a session', | ||
fields, | ||
dataPoints, | ||
previewable: false, | ||
onEvent: async ({ payload, onComplete, onError, helpers }): Promise<void> => { | ||
const { | ||
fields: { careFlowDefinitionId, stakeholderDefinitionId, baselineInfo }, | ||
} = validate({ | ||
schema: z.object({ | ||
fields: FieldsValidationSchema, | ||
}), | ||
payload, | ||
}) | ||
|
||
const sdk = await helpers.awellSdk() | ||
|
||
const resp = await sdk.orchestration.mutation({ | ||
startHostedPathwaySession: { | ||
__args: { | ||
input: { | ||
patient_id: payload.patient.id, | ||
pathway_definition_id: careFlowDefinitionId, | ||
stakeholder_definition_id: stakeholderDefinitionId, | ||
data_points: baselineInfo, | ||
}, | ||
}, | ||
success: true, | ||
pathway_id: true, | ||
session_url: true, | ||
}, | ||
}) | ||
|
||
const { | ||
startHostedPathwaySession: { pathway_id, session_url }, | ||
} = resp | ||
|
||
await onComplete({ | ||
data_points: { | ||
careFlowId: pathway_id, | ||
sessionUrl: session_url, | ||
}, | ||
events: [ | ||
addActivityEventLog({ | ||
message: `Care flow started with instance id ${pathway_id}. Session URL is ${session_url}.`, | ||
}), | ||
], | ||
}) | ||
}, | ||
} |