@twentyhq/call-recorder 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/manifest.json +297 -0
- package/package.json +2 -2
- package/src/front-components/calendar-event-recording.front-component.mjs +269 -0
- package/src/front-components/calendar-event-recording.front-component.mjs.map +7 -0
- package/src/logic-functions/process-recall-webhook.mjs +1744 -0
- package/src/logic-functions/process-recall-webhook.mjs.map +7 -0
- package/src/logic-functions/recall-webhook.mjs +391 -0
- package/src/logic-functions/recall-webhook.mjs.map +7 -0
- package/src/logic-functions/reconcile-call-recorder-calendar-event.mjs +1602 -0
- package/src/logic-functions/reconcile-call-recorder-calendar-event.mjs.map +7 -0
- package/src/logic-functions/reconcile-stale-bot-state.mjs +2268 -0
- package/src/logic-functions/reconcile-stale-bot-state.mjs.map +7 -0
- package/.env.example +0 -5
- package/.nvmrc +0 -1
- package/.oxlintrc.json +0 -20
- package/AGENTS.md +0 -67
- package/CLAUDE.md +0 -67
- package/README.md +0 -24
- package/SETUP.md +0 -95
- package/src/__tests__/global-setup.ts +0 -100
- package/src/__tests__/schema.integration-test.ts +0 -104
- package/src/application-config.ts +0 -96
- package/src/constants/__tests__/call-recording-field-universal-identifiers.test.ts +0 -19
- package/src/constants/app-description.ts +0 -2
- package/src/constants/app-display-name.ts +0 -1
- package/src/constants/application-universal-identifier.ts +0 -2
- package/src/constants/calendar-event-reconciliation-logic-function-universal-identifier.ts +0 -2
- package/src/constants/calendar-event-record-page-layout-universal-identifier.ts +0 -2
- package/src/constants/calendar-event-recording-front-component-universal-identifier.ts +0 -2
- package/src/constants/calendar-event-recording-page-layout-tab-universal-identifier.ts +0 -2
- package/src/constants/calendar-event-recording-page-layout-widget-universal-identifier.ts +0 -2
- package/src/constants/call-recorder-everyone-left-timeout-seconds-app-variable-universal-identifier.ts +0 -2
- package/src/constants/call-recorder-failure-reason-on-call-recording-field-universal-identifier.ts +0 -2
- package/src/constants/call-recorder-join-early-minutes-app-variable-universal-identifier.ts +0 -2
- package/src/constants/call-recorder-name-app-variable-universal-identifier.ts +0 -2
- package/src/constants/call-recorder-noone-joined-timeout-seconds-app-variable-universal-identifier.ts +0 -2
- package/src/constants/call-recorder-preference-off-option-id.ts +0 -2
- package/src/constants/call-recorder-preference-on-calendar-event-field-universal-identifier.ts +0 -2
- package/src/constants/call-recorder-preference-on-calendar-event-view-field-universal-identifier.ts +0 -2
- package/src/constants/call-recorder-preference-on-option-id.ts +0 -2
- package/src/constants/call-recorder-preference.ts +0 -4
- package/src/constants/call-recorder-waiting-room-timeout-seconds-app-variable-universal-identifier.ts +0 -2
- package/src/constants/call-recording-audio-field-universal-identifier.ts +0 -2
- package/src/constants/call-recording-video-field-universal-identifier.ts +0 -2
- package/src/constants/default-role-universal-identifier.ts +0 -2
- package/src/constants/process-recall-webhook-logic-function-universal-identifier.ts +0 -2
- package/src/constants/recall-webhook-logic-function-universal-identifier.ts +0 -2
- package/src/constants/stale-bot-state-logic-function-universal-identifier.ts +0 -2
- package/src/default-role.ts +0 -69
- package/src/fields/call-recorder-failure-reason-on-call-recording.field.ts +0 -22
- package/src/fields/call-recorder-preference-on-calendar-event.field.ts +0 -41
- package/src/front-components/calendar-event-recording.front-component.tsx +0 -13
- package/src/front-components/components/CalendarEventRecording.tsx +0 -39
- package/src/front-components/components/CalendarEventRecordingBody.tsx +0 -96
- package/src/front-components/components/CalendarEventRecordingContent.tsx +0 -111
- package/src/front-components/components/RecordingTranscript.tsx +0 -92
- package/src/front-components/components/RecordingVideoPlayer.tsx +0 -52
- package/src/front-components/components/TranscriptEntryList.tsx +0 -61
- package/src/front-components/components/TranscriptEntryListItem.tsx +0 -115
- package/src/front-components/components/TranscriptErrorBox.tsx +0 -48
- package/src/front-components/components/TranscriptSpeakerAvatar.tsx +0 -141
- package/src/front-components/components/TranscriptSpeakerChip.tsx +0 -51
- package/src/front-components/constants/recording-theme-css-variables.ts +0 -40
- package/src/front-components/hooks/use-calendar-event-participants.ts +0 -172
- package/src/front-components/hooks/use-calendar-event-recording.ts +0 -155
- package/src/front-components/types/calendar-event-participant-by-speaker-name.type.ts +0 -6
- package/src/front-components/types/calendar-event-recording-participant.type.ts +0 -7
- package/src/front-components/types/transcript-entry.type.ts +0 -13
- package/src/front-components/utils/__tests__/find-active-transcript-entry-index.test.ts +0 -66
- package/src/front-components/utils/__tests__/format-transcript-timestamp.test.ts +0 -29
- package/src/front-components/utils/__tests__/get-speaker-name-match-keys.test.ts +0 -22
- package/src/front-components/utils/__tests__/parse-transcript-entries.test.ts +0 -162
- package/src/front-components/utils/build-calendar-event-participant-by-speaker-name.util.ts +0 -45
- package/src/front-components/utils/find-active-transcript-entry-index.util.ts +0 -77
- package/src/front-components/utils/format-transcript-timestamp.util.ts +0 -16
- package/src/front-components/utils/get-absolute-avatar-url.util.ts +0 -48
- package/src/front-components/utils/get-calendar-event-participant-for-speaker-name.util.ts +0 -24
- package/src/front-components/utils/get-speaker-name-match-keys.util.ts +0 -64
- package/src/front-components/utils/get-video-file-extension.util.ts +0 -23
- package/src/front-components/utils/parse-transcript-entries.util.ts +0 -85
- package/src/logic-functions/__tests__/process-recall-webhook.test.ts +0 -62
- package/src/logic-functions/__tests__/recall-webhook.test.ts +0 -180
- package/src/logic-functions/constants/call-recorder-everyone-left-timeout-seconds-env-var-name.ts +0 -2
- package/src/logic-functions/constants/call-recorder-everyone-left-timeout-seconds.ts +0 -1
- package/src/logic-functions/constants/call-recorder-join-early-minutes-env-var-name.ts +0 -2
- package/src/logic-functions/constants/call-recorder-name-env-var-name.ts +0 -1
- package/src/logic-functions/constants/call-recorder-noone-joined-timeout-seconds-env-var-name.ts +0 -2
- package/src/logic-functions/constants/call-recorder-noone-joined-timeout-seconds.ts +0 -1
- package/src/logic-functions/constants/call-recorder-recording-retention-hours-env-var-name.ts +0 -2
- package/src/logic-functions/constants/call-recorder-waiting-room-timeout-seconds-env-var-name.ts +0 -2
- package/src/logic-functions/constants/call-recorder-waiting-room-timeout-seconds.ts +0 -1
- package/src/logic-functions/constants/call-recording-micro-credits-per-hour.ts +0 -1
- package/src/logic-functions/constants/call-recording-request-status.ts +0 -5
- package/src/logic-functions/constants/call-recording-status.ts +0 -9
- package/src/logic-functions/constants/default-call-recorder-join-early-minutes.ts +0 -1
- package/src/logic-functions/constants/default-call-recorder-name.ts +0 -1
- package/src/logic-functions/constants/default-call-recorder-recording-retention-hours.ts +0 -2
- package/src/logic-functions/constants/default-recall-region.ts +0 -1
- package/src/logic-functions/constants/milliseconds-per-minute.ts +0 -1
- package/src/logic-functions/constants/non-terminal-call-recording-statuses.ts +0 -8
- package/src/logic-functions/constants/recall-api-key-env-var-name.ts +0 -1
- package/src/logic-functions/constants/recall-api-max-attempts.ts +0 -1
- package/src/logic-functions/constants/recall-api-retry-delay-ms.ts +0 -1
- package/src/logic-functions/constants/recall-bot-automatic-leave.ts +0 -74
- package/src/logic-functions/constants/recall-bot-everyone-left-min-activate-after-seconds.ts +0 -1
- package/src/logic-functions/constants/recall-bot-recording-config.ts +0 -34
- package/src/logic-functions/constants/recall-region-env-var-name.ts +0 -1
- package/src/logic-functions/constants/recall-webhook-secret-env-var-name.ts +0 -1
- package/src/logic-functions/constants/restricted-field-placeholder.ts +0 -3
- package/src/logic-functions/constants/stale-bot-state-cron-pattern.ts +0 -1
- package/src/logic-functions/constants/twenty-page-size.ts +0 -1
- package/src/logic-functions/data/__tests__/complete-call-recording-ingestion.test.ts +0 -55
- package/src/logic-functions/data/__tests__/fetch-all-nodes.test.ts +0 -43
- package/src/logic-functions/data/__tests__/get-current-workspace-id.test.ts +0 -38
- package/src/logic-functions/data/__tests__/strip-restricted-field-value.test.ts +0 -22
- package/src/logic-functions/data/complete-call-recording-ingestion.util.ts +0 -24
- package/src/logic-functions/data/create-call-recording.util.ts +0 -41
- package/src/logic-functions/data/fetch-all-nodes.util.ts +0 -44
- package/src/logic-functions/data/fetch-calendar-events-by-filter.util.ts +0 -80
- package/src/logic-functions/data/fetch-calendar-events-by-ids.util.ts +0 -20
- package/src/logic-functions/data/fetch-calendar-events-by-starts-at-values.util.ts +0 -19
- package/src/logic-functions/data/find-call-recordings-by-calendar-event-ids.util.ts +0 -17
- package/src/logic-functions/data/find-call-recordings-by-filter.util.ts +0 -102
- package/src/logic-functions/data/find-call-recordings-by-ids.util.ts +0 -17
- package/src/logic-functions/data/find-open-scheduled-call-recordings.util.ts +0 -14
- package/src/logic-functions/data/get-current-workspace-id.util.ts +0 -36
- package/src/logic-functions/data/strip-restricted-field-value.util.ts +0 -6
- package/src/logic-functions/data/update-call-recording.util.ts +0 -24
- package/src/logic-functions/domain/__tests__/build-call-recorder-policy-result.test.ts +0 -47
- package/src/logic-functions/domain/__tests__/compute-call-recording-charge.test.ts +0 -71
- package/src/logic-functions/domain/__tests__/compute-call-recording-id-for-meeting.test.ts +0 -37
- package/src/logic-functions/domain/__tests__/compute-real-meeting-key.test.ts +0 -88
- package/src/logic-functions/domain/__tests__/is-call-recording-ingestion-complete.test.ts +0 -59
- package/src/logic-functions/domain/__tests__/is-call-recording-status-downgrade.test.ts +0 -37
- package/src/logic-functions/domain/__tests__/resolve-call-recorder-policy-result.test.ts +0 -120
- package/src/logic-functions/domain/__tests__/should-complete-call-recording-ingestion.test.ts +0 -102
- package/src/logic-functions/domain/aggregate-call-recorder-policy-results-by-meeting.util.ts +0 -42
- package/src/logic-functions/domain/build-call-recorder-policy-result.util.ts +0 -53
- package/src/logic-functions/domain/build-failed-transcript-marker.util.ts +0 -13
- package/src/logic-functions/domain/build-pending-transcript-marker.util.ts +0 -13
- package/src/logic-functions/domain/build-recall-routing-metadata.util.ts +0 -12
- package/src/logic-functions/domain/build-transcript-failure-reason.util.ts +0 -7
- package/src/logic-functions/domain/compute-call-recording-charge.util.ts +0 -41
- package/src/logic-functions/domain/compute-call-recording-id-for-meeting.util.ts +0 -16
- package/src/logic-functions/domain/compute-real-meeting-key.util.ts +0 -48
- package/src/logic-functions/domain/compute-recall-bot-join-at.util.ts +0 -34
- package/src/logic-functions/domain/is-call-recording-ingestion-complete.util.ts +0 -19
- package/src/logic-functions/domain/is-call-recording-status-downgrade.util.ts +0 -37
- package/src/logic-functions/domain/is-recall-recording-done-signal.util.ts +0 -13
- package/src/logic-functions/domain/map-recall-status-code-to-call-recording-status.util.ts +0 -26
- package/src/logic-functions/domain/parse-transcript-marker.util.ts +0 -29
- package/src/logic-functions/domain/resolve-call-recorder-policy-result.util.ts +0 -72
- package/src/logic-functions/domain/should-complete-call-recording-ingestion.util.ts +0 -32
- package/src/logic-functions/flows/__tests__/charge-completed-call-recording.test.ts +0 -45
- package/src/logic-functions/flows/__tests__/complete-and-charge-call-recording.test.ts +0 -61
- package/src/logic-functions/flows/__tests__/converge-diverged-call-recordings.test.ts +0 -727
- package/src/logic-functions/flows/__tests__/download-transcript.test.ts +0 -74
- package/src/logic-functions/flows/__tests__/handle-recall-webhook.test.ts +0 -1301
- package/src/logic-functions/flows/__tests__/heal-call-recordings-missing-bot.test.ts +0 -225
- package/src/logic-functions/flows/__tests__/ingest-call-recording-media.test.ts +0 -153
- package/src/logic-functions/flows/__tests__/reap-orphaned-call-recorders.test.ts +0 -425
- package/src/logic-functions/flows/__tests__/reconcile-call-recorder.test.ts +0 -1007
- package/src/logic-functions/flows/cancel-call-recording-request.util.ts +0 -46
- package/src/logic-functions/flows/charge-completed-call-recording.util.ts +0 -31
- package/src/logic-functions/flows/complete-and-charge-call-recording.util.ts +0 -29
- package/src/logic-functions/flows/converge-diverged-call-recordings-result.type.ts +0 -8
- package/src/logic-functions/flows/converge-diverged-call-recordings.util.ts +0 -447
- package/src/logic-functions/flows/download-transcript.util.ts +0 -67
- package/src/logic-functions/flows/ensure-call-recorder.util.ts +0 -73
- package/src/logic-functions/flows/handle-recall-webhook.util.ts +0 -672
- package/src/logic-functions/flows/heal-call-recordings-missing-bot.util.ts +0 -82
- package/src/logic-functions/flows/ingest-call-recording-media.util.ts +0 -128
- package/src/logic-functions/flows/persist-call-recording-progress.util.ts +0 -58
- package/src/logic-functions/flows/reap-orphaned-call-recorders.util.ts +0 -183
- package/src/logic-functions/flows/reconcile-call-recorder.util.ts +0 -495
- package/src/logic-functions/flows/reconcile-call-recording-transcript-artifact-result.type.ts +0 -11
- package/src/logic-functions/flows/reconcile-call-recording-transcript-artifact.util.ts +0 -182
- package/src/logic-functions/flows/reschedule-call-recording-bot.util.ts +0 -69
- package/src/logic-functions/process-recall-webhook.ts +0 -23
- package/src/logic-functions/recall-api/__tests__/extract-recall-bot-convergence.test.ts +0 -153
- package/src/logic-functions/recall-api/__tests__/extract-recall-media-urls.test.ts +0 -67
- package/src/logic-functions/recall-api/__tests__/recall-bot-api.test.ts +0 -744
- package/src/logic-functions/recall-api/__tests__/verify-recall-webhook-signature.test.ts +0 -122
- package/src/logic-functions/recall-api/cancel-recall-bot.util.ts +0 -28
- package/src/logic-functions/recall-api/create-async-recall-transcript.util.ts +0 -47
- package/src/logic-functions/recall-api/eject-recall-bot.util.ts +0 -28
- package/src/logic-functions/recall-api/extract-recall-bot-convergence.util.ts +0 -149
- package/src/logic-functions/recall-api/extract-recall-bot-id.util.ts +0 -10
- package/src/logic-functions/recall-api/extract-recall-media-urls.util.ts +0 -30
- package/src/logic-functions/recall-api/extract-twenty-workspace-id-from-recall-webhook.util.ts +0 -8
- package/src/logic-functions/recall-api/get-recall-api-config.util.ts +0 -59
- package/src/logic-functions/recall-api/get-recall-bot.util.ts +0 -42
- package/src/logic-functions/recall-api/get-recall-recording.util.ts +0 -31
- package/src/logic-functions/recall-api/get-recall-webhook-bot-metadata.util.ts +0 -18
- package/src/logic-functions/recall-api/list-recall-transcripts.util.ts +0 -141
- package/src/logic-functions/recall-api/list-scheduled-recall-bots.util.ts +0 -106
- package/src/logic-functions/recall-api/normalize-recall-timestamp.util.ts +0 -14
- package/src/logic-functions/recall-api/parse-recall-webhook-event.util.ts +0 -88
- package/src/logic-functions/recall-api/recall-bot-api-request.util.ts +0 -165
- package/src/logic-functions/recall-api/recall-transcript-summary.type.ts +0 -5
- package/src/logic-functions/recall-api/reschedule-recall-bot.util.ts +0 -56
- package/src/logic-functions/recall-api/retrieve-recall-transcript.util.ts +0 -71
- package/src/logic-functions/recall-api/schedule-recall-bot.util.ts +0 -68
- package/src/logic-functions/recall-api/verify-recall-webhook-signature.util.ts +0 -109
- package/src/logic-functions/recall-webhook.ts +0 -90
- package/src/logic-functions/reconcile-call-recorder-calendar-event.ts +0 -178
- package/src/logic-functions/reconcile-stale-bot-state.ts +0 -106
- package/src/logic-functions/types/calendar-event-record.type.ts +0 -5
- package/src/logic-functions/types/call-recorder-policy-calendar-event-input.type.ts +0 -10
- package/src/logic-functions/types/call-recorder-policy-input.type.ts +0 -9
- package/src/logic-functions/types/call-recorder-policy-not-required-reason.type.ts +0 -5
- package/src/logic-functions/types/call-recorder-policy-required-reason.type.ts +0 -1
- package/src/logic-functions/types/call-recorder-policy-result-for-calendar-event.type.ts +0 -9
- package/src/logic-functions/types/call-recorder-policy-result-for-meeting.type.ts +0 -6
- package/src/logic-functions/types/call-recorder-policy-result.type.ts +0 -12
- package/src/logic-functions/types/call-recorder-reconciliation-result.type.ts +0 -16
- package/src/logic-functions/types/call-recording-media-file.type.ts +0 -1
- package/src/logic-functions/types/call-recording-record.type.ts +0 -15
- package/src/logic-functions/types/call-recording-update-fields.type.ts +0 -20
- package/src/logic-functions/types/files-field-value.type.ts +0 -1
- package/src/logic-functions/types/meeting-recording.type.ts +0 -7
- package/src/logic-functions/types/recall-bot-operation-result.type.ts +0 -19
- package/src/logic-functions/types/recall-routing-metadata.type.ts +0 -4
- package/src/logic-functions/types/removed-call-recorder-occurrence.type.ts +0 -6
- package/src/logic-functions/types/transcript-marker.type.ts +0 -6
- package/src/logic-functions/utils/as-record.util.ts +0 -6
- package/src/logic-functions/utils/get-application-variable-value.util.ts +0 -3
- package/src/logic-functions/utils/get-record-at-path.util.ts +0 -10
- package/src/logic-functions/utils/get-string.util.ts +0 -4
- package/src/logic-functions/utils/get-unique-sorted-ids.util.ts +0 -8
- package/src/logic-functions/utils/is-non-empty-string.util.ts +0 -5
- package/src/page-layouts/calendar-event-recording-tab.ts +0 -33
- package/src/view-fields/call-recorder-preference-on-calendar-event.view-field.ts +0 -27
- package/tsconfig.json +0 -42
- package/tsconfig.spec.json +0 -9
- package/vitest.config.ts +0 -31
- package/vitest.unit.config.ts +0 -14
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
import { createHmac } from 'crypto';
|
|
2
|
-
|
|
3
|
-
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
4
|
-
|
|
5
|
-
import { PROCESS_RECALL_WEBHOOK_LOGIC_FUNCTION_UNIVERSAL_IDENTIFIER } from 'src/constants/process-recall-webhook-logic-function-universal-identifier';
|
|
6
|
-
import recallWebhookLogicFunction, {
|
|
7
|
-
recallWebhookRouteHandler,
|
|
8
|
-
} from 'src/logic-functions/recall-webhook';
|
|
9
|
-
|
|
10
|
-
const getApplicationVariableValueMock = vi.hoisted(() => vi.fn());
|
|
11
|
-
|
|
12
|
-
vi.mock(
|
|
13
|
-
'src/logic-functions/utils/get-application-variable-value.util',
|
|
14
|
-
() => ({
|
|
15
|
-
getApplicationVariableValue: getApplicationVariableValueMock,
|
|
16
|
-
}),
|
|
17
|
-
);
|
|
18
|
-
|
|
19
|
-
const SECRET_BYTES = Buffer.from('entry-test-secret');
|
|
20
|
-
const SECRET = `whsec_${SECRET_BYTES.toString('base64')}`;
|
|
21
|
-
const WORKSPACE_ID = '123e4567-e89b-12d3-a456-426614174000';
|
|
22
|
-
const CALL_RECORDING_ID = 'call-recording-1';
|
|
23
|
-
|
|
24
|
-
type RecallWebhookRoutePayload = Parameters<
|
|
25
|
-
typeof recallWebhookRouteHandler
|
|
26
|
-
>[0];
|
|
27
|
-
|
|
28
|
-
const buildRoutePayload = (
|
|
29
|
-
overrides: Partial<RecallWebhookRoutePayload>,
|
|
30
|
-
): RecallWebhookRoutePayload =>
|
|
31
|
-
({
|
|
32
|
-
headers: {},
|
|
33
|
-
...overrides,
|
|
34
|
-
}) as RecallWebhookRoutePayload;
|
|
35
|
-
|
|
36
|
-
const buildSignedHeaders = (rawBody: string): Record<string, string> => {
|
|
37
|
-
const webhookId = 'msg_entry_test';
|
|
38
|
-
const webhookTimestamp = Math.floor(Date.now() / 1000).toString();
|
|
39
|
-
const signature = createHmac('sha256', SECRET_BYTES)
|
|
40
|
-
.update(`${webhookId}.${webhookTimestamp}.${rawBody}`)
|
|
41
|
-
.digest('base64');
|
|
42
|
-
|
|
43
|
-
return {
|
|
44
|
-
'webhook-id': webhookId,
|
|
45
|
-
'webhook-timestamp': webhookTimestamp,
|
|
46
|
-
'webhook-signature': `v1,${signature}`,
|
|
47
|
-
};
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const buildRecordingDoneWebhookBody = () => ({
|
|
51
|
-
event: 'recording.done',
|
|
52
|
-
data: {
|
|
53
|
-
bot: {
|
|
54
|
-
id: 'recall-bot-1',
|
|
55
|
-
metadata: {
|
|
56
|
-
twentyWorkspaceId: WORKSPACE_ID,
|
|
57
|
-
twentyCallRecordingId: CALL_RECORDING_ID,
|
|
58
|
-
},
|
|
59
|
-
},
|
|
60
|
-
recording: {
|
|
61
|
-
id: 'recall-recording-1',
|
|
62
|
-
},
|
|
63
|
-
},
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
describe('recallWebhookRouteHandler', () => {
|
|
67
|
-
beforeEach(() => {
|
|
68
|
-
getApplicationVariableValueMock.mockReset();
|
|
69
|
-
getApplicationVariableValueMock.mockReturnValue(SECRET);
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it('declares a server route trigger that forwards the webhook signature headers', () => {
|
|
73
|
-
expect(recallWebhookLogicFunction.success).toBe(true);
|
|
74
|
-
expect(
|
|
75
|
-
recallWebhookLogicFunction.config.httpRouteTriggerSettings,
|
|
76
|
-
).toBeUndefined();
|
|
77
|
-
expect(
|
|
78
|
-
'serverRouteTriggerSettings' in recallWebhookLogicFunction.config,
|
|
79
|
-
).toBe(true);
|
|
80
|
-
|
|
81
|
-
if (!('serverRouteTriggerSettings' in recallWebhookLogicFunction.config)) {
|
|
82
|
-
throw new Error('Expected a server route trigger');
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
expect(
|
|
86
|
-
recallWebhookLogicFunction.config.serverRouteTriggerSettings,
|
|
87
|
-
).toEqual({
|
|
88
|
-
forwardedRequestHeaders: [
|
|
89
|
-
'webhook-id',
|
|
90
|
-
'webhook-timestamp',
|
|
91
|
-
'webhook-signature',
|
|
92
|
-
'svix-id',
|
|
93
|
-
'svix-timestamp',
|
|
94
|
-
'svix-signature',
|
|
95
|
-
],
|
|
96
|
-
});
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
it('throws when the webhook secret is not configured', () => {
|
|
100
|
-
getApplicationVariableValueMock.mockReturnValue(undefined);
|
|
101
|
-
|
|
102
|
-
expect(() =>
|
|
103
|
-
recallWebhookRouteHandler(buildRoutePayload({ rawBody: '{}', body: {} })),
|
|
104
|
-
).toThrow('RECALL_WEBHOOK_SECRET');
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
it('throws when the raw body is not forwarded', () => {
|
|
108
|
-
expect(() =>
|
|
109
|
-
recallWebhookRouteHandler(buildRoutePayload({ body: {} })),
|
|
110
|
-
).toThrow('Raw request body');
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
it('throws when the signature is invalid', () => {
|
|
114
|
-
expect(() =>
|
|
115
|
-
recallWebhookRouteHandler(
|
|
116
|
-
buildRoutePayload({
|
|
117
|
-
rawBody: '{}',
|
|
118
|
-
body: {},
|
|
119
|
-
headers: {
|
|
120
|
-
'webhook-id': 'msg_entry_test',
|
|
121
|
-
'webhook-timestamp': Math.floor(Date.now() / 1000).toString(),
|
|
122
|
-
'webhook-signature': 'v1,not-a-real-signature',
|
|
123
|
-
},
|
|
124
|
-
}),
|
|
125
|
-
),
|
|
126
|
-
).toThrow('Invalid webhook signature');
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
it('throws when a correctly signed payload is empty', () => {
|
|
130
|
-
const rawBody = 'null';
|
|
131
|
-
|
|
132
|
-
expect(() =>
|
|
133
|
-
recallWebhookRouteHandler(
|
|
134
|
-
buildRoutePayload({
|
|
135
|
-
rawBody,
|
|
136
|
-
body: null,
|
|
137
|
-
headers: buildSignedHeaders(rawBody),
|
|
138
|
-
}),
|
|
139
|
-
),
|
|
140
|
-
).toThrow('Webhook payload was empty');
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
it('throws when the workspace id is missing from the bot metadata', () => {
|
|
144
|
-
const body = {
|
|
145
|
-
event: 'recording.done',
|
|
146
|
-
data: { bot: { id: 'recall-bot-1' } },
|
|
147
|
-
};
|
|
148
|
-
const rawBody = JSON.stringify(body);
|
|
149
|
-
|
|
150
|
-
expect(() =>
|
|
151
|
-
recallWebhookRouteHandler(
|
|
152
|
-
buildRoutePayload({
|
|
153
|
-
rawBody,
|
|
154
|
-
body,
|
|
155
|
-
headers: buildSignedHeaders(rawBody),
|
|
156
|
-
}),
|
|
157
|
-
),
|
|
158
|
-
).toThrow('workspace id');
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
it('resolves the target workspace for a correctly signed payload', () => {
|
|
162
|
-
const body = buildRecordingDoneWebhookBody();
|
|
163
|
-
const rawBody = JSON.stringify(body);
|
|
164
|
-
|
|
165
|
-
const result = recallWebhookRouteHandler(
|
|
166
|
-
buildRoutePayload({
|
|
167
|
-
rawBody,
|
|
168
|
-
body,
|
|
169
|
-
headers: buildSignedHeaders(rawBody),
|
|
170
|
-
}),
|
|
171
|
-
);
|
|
172
|
-
|
|
173
|
-
expect(result).toEqual({
|
|
174
|
-
workspaceId: WORKSPACE_ID,
|
|
175
|
-
targetLogicFunctionUniversalIdentifier:
|
|
176
|
-
PROCESS_RECALL_WEBHOOK_LOGIC_FUNCTION_UNIVERSAL_IDENTIFIER,
|
|
177
|
-
payload: body,
|
|
178
|
-
});
|
|
179
|
-
});
|
|
180
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const CALL_RECORDER_EVERYONE_LEFT_TIMEOUT_SECONDS = 2;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const CALL_RECORDER_NAME_ENV_VAR_NAME = 'CALL_RECORDER_NAME';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const CALL_RECORDER_NOONE_JOINED_TIMEOUT_SECONDS = 20 * 60;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const CALL_RECORDER_WAITING_ROOM_TIMEOUT_SECONDS = 1200;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const CALL_RECORDING_MICRO_CREDITS_PER_HOUR = 1_000_000;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
// Mirrors the core select options; guarded by the schema integration test.
|
|
2
|
-
export enum CallRecordingStatus {
|
|
3
|
-
SCHEDULED = 'SCHEDULED',
|
|
4
|
-
JOINING = 'JOINING',
|
|
5
|
-
RECORDING = 'RECORDING',
|
|
6
|
-
PROCESSING = 'PROCESSING',
|
|
7
|
-
COMPLETED = 'COMPLETED',
|
|
8
|
-
FAILED = 'FAILED',
|
|
9
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const DEFAULT_CALL_RECORDER_JOIN_EARLY_MINUTES = 1;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const DEFAULT_CALL_RECORDER_NAME = 'Twenty.com';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const DEFAULT_RECALL_REGION = 'eu-central-1';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const MILLISECONDS_PER_MINUTE = 60_000;
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { CallRecordingStatus } from 'src/logic-functions/constants/call-recording-status';
|
|
2
|
-
|
|
3
|
-
export const NON_TERMINAL_CALL_RECORDING_STATUSES = [
|
|
4
|
-
CallRecordingStatus.SCHEDULED,
|
|
5
|
-
CallRecordingStatus.JOINING,
|
|
6
|
-
CallRecordingStatus.RECORDING,
|
|
7
|
-
CallRecordingStatus.PROCESSING,
|
|
8
|
-
] satisfies CallRecordingStatus[];
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const RECALL_API_KEY_ENV_VAR_NAME = 'RECALL_API_KEY';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const RECALL_API_MAX_ATTEMPTS = 3;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const RECALL_API_RETRY_DELAY_MS = 500;
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { isUndefined } from '@sniptt/guards';
|
|
2
|
-
|
|
3
|
-
import { CALL_RECORDER_EVERYONE_LEFT_TIMEOUT_SECONDS_ENV_VAR_NAME } from 'src/logic-functions/constants/call-recorder-everyone-left-timeout-seconds-env-var-name';
|
|
4
|
-
import { CALL_RECORDER_NOONE_JOINED_TIMEOUT_SECONDS_ENV_VAR_NAME } from 'src/logic-functions/constants/call-recorder-noone-joined-timeout-seconds-env-var-name';
|
|
5
|
-
import { CALL_RECORDER_WAITING_ROOM_TIMEOUT_SECONDS_ENV_VAR_NAME } from 'src/logic-functions/constants/call-recorder-waiting-room-timeout-seconds-env-var-name';
|
|
6
|
-
import { RECALL_BOT_EVERYONE_LEFT_MIN_ACTIVATE_AFTER_SECONDS } from 'src/logic-functions/constants/recall-bot-everyone-left-min-activate-after-seconds';
|
|
7
|
-
import { getApplicationVariableValue } from 'src/logic-functions/utils/get-application-variable-value.util';
|
|
8
|
-
import { isNonEmptyString } from 'src/logic-functions/utils/is-non-empty-string.util';
|
|
9
|
-
|
|
10
|
-
type RecallBotAutomaticLeave = {
|
|
11
|
-
waiting_room_timeout?: number;
|
|
12
|
-
noone_joined_timeout?: number;
|
|
13
|
-
everyone_left_timeout?: {
|
|
14
|
-
timeout: number;
|
|
15
|
-
activate_after: number;
|
|
16
|
-
};
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export const getRecallBotAutomaticLeave = ():
|
|
20
|
-
| RecallBotAutomaticLeave
|
|
21
|
-
| undefined => {
|
|
22
|
-
const waitingRoomTimeoutSeconds = getOptionalPositiveIntegerVariable(
|
|
23
|
-
CALL_RECORDER_WAITING_ROOM_TIMEOUT_SECONDS_ENV_VAR_NAME,
|
|
24
|
-
);
|
|
25
|
-
const nooneJoinedTimeoutSeconds = getOptionalPositiveIntegerVariable(
|
|
26
|
-
CALL_RECORDER_NOONE_JOINED_TIMEOUT_SECONDS_ENV_VAR_NAME,
|
|
27
|
-
);
|
|
28
|
-
const everyoneLeftTimeoutSeconds = getOptionalPositiveIntegerVariable(
|
|
29
|
-
CALL_RECORDER_EVERYONE_LEFT_TIMEOUT_SECONDS_ENV_VAR_NAME,
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
const automaticLeave: RecallBotAutomaticLeave = {};
|
|
33
|
-
|
|
34
|
-
if (!isUndefined(waitingRoomTimeoutSeconds)) {
|
|
35
|
-
automaticLeave.waiting_room_timeout = waitingRoomTimeoutSeconds;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (!isUndefined(nooneJoinedTimeoutSeconds)) {
|
|
39
|
-
automaticLeave.noone_joined_timeout = nooneJoinedTimeoutSeconds;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (!isUndefined(everyoneLeftTimeoutSeconds)) {
|
|
43
|
-
automaticLeave.everyone_left_timeout = {
|
|
44
|
-
timeout: everyoneLeftTimeoutSeconds,
|
|
45
|
-
activate_after: RECALL_BOT_EVERYONE_LEFT_MIN_ACTIVATE_AFTER_SECONDS,
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return Object.keys(automaticLeave).length === 0 ? undefined : automaticLeave;
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
const getOptionalPositiveIntegerVariable = (
|
|
53
|
-
variableName: string,
|
|
54
|
-
): number | undefined => {
|
|
55
|
-
const rawValue = normalizeOptionalString(
|
|
56
|
-
getApplicationVariableValue(variableName),
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
if (isUndefined(rawValue)) {
|
|
60
|
-
return undefined;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const timeoutSeconds = Number(rawValue);
|
|
64
|
-
|
|
65
|
-
if (!Number.isInteger(timeoutSeconds) || timeoutSeconds <= 0) {
|
|
66
|
-
return undefined;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return timeoutSeconds;
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
const normalizeOptionalString = (
|
|
73
|
-
value: string | undefined,
|
|
74
|
-
): string | undefined => (isNonEmptyString(value) ? value.trim() : undefined);
|
package/src/logic-functions/constants/recall-bot-everyone-left-min-activate-after-seconds.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const RECALL_BOT_EVERYONE_LEFT_MIN_ACTIVATE_AFTER_SECONDS = 1;
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { CALL_RECORDER_RECORDING_RETENTION_HOURS_ENV_VAR_NAME } from 'src/logic-functions/constants/call-recorder-recording-retention-hours-env-var-name';
|
|
2
|
-
import { DEFAULT_CALL_RECORDER_RECORDING_RETENTION_HOURS } from 'src/logic-functions/constants/default-call-recorder-recording-retention-hours';
|
|
3
|
-
import { getApplicationVariableValue } from 'src/logic-functions/utils/get-application-variable-value.util';
|
|
4
|
-
import { isNonEmptyString } from 'src/logic-functions/utils/is-non-empty-string.util';
|
|
5
|
-
|
|
6
|
-
type RecallBotRecordingConfig = {
|
|
7
|
-
video_mixed_mp4: Record<string, never>;
|
|
8
|
-
audio_mixed_mp3: Record<string, never>;
|
|
9
|
-
retention: { type: 'timed'; hours: number };
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
// Recall only produces artifacts declared at bot creation; both gate COMPLETED.
|
|
13
|
-
export const getRecallBotRecordingConfig = (): RecallBotRecordingConfig => {
|
|
14
|
-
const configuredRecordingRetentionHours = getApplicationVariableValue(
|
|
15
|
-
CALL_RECORDER_RECORDING_RETENTION_HOURS_ENV_VAR_NAME,
|
|
16
|
-
);
|
|
17
|
-
|
|
18
|
-
const recordingRetentionHours = isNonEmptyString(
|
|
19
|
-
configuredRecordingRetentionHours,
|
|
20
|
-
)
|
|
21
|
-
? Number(configuredRecordingRetentionHours.trim())
|
|
22
|
-
: NaN;
|
|
23
|
-
|
|
24
|
-
const resolvedRecordingRetentionHours =
|
|
25
|
-
Number.isInteger(recordingRetentionHours) && recordingRetentionHours > 0
|
|
26
|
-
? recordingRetentionHours
|
|
27
|
-
: DEFAULT_CALL_RECORDER_RECORDING_RETENTION_HOURS;
|
|
28
|
-
|
|
29
|
-
return {
|
|
30
|
-
video_mixed_mp4: {},
|
|
31
|
-
audio_mixed_mp3: {},
|
|
32
|
-
retention: { type: 'timed', hours: resolvedRecordingRetentionHours },
|
|
33
|
-
};
|
|
34
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const RECALL_REGION_ENV_VAR_NAME = 'RECALL_REGION';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const RECALL_WEBHOOK_SECRET_ENV_VAR_NAME = 'RECALL_WEBHOOK_SECRET';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const STALE_BOT_STATE_CRON_PATTERN = '*/5 * * * *';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const TWENTY_PAGE_SIZE = 100;
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
-
|
|
3
|
-
import { completeCallRecordingIngestion } from 'src/logic-functions/data/complete-call-recording-ingestion.util';
|
|
4
|
-
|
|
5
|
-
describe('completeCallRecordingIngestion', () => {
|
|
6
|
-
it('guards the flip with non-terminal statuses and returns true when the row is claimed', async () => {
|
|
7
|
-
let capturedArgs: { filter: unknown; data: unknown } | undefined;
|
|
8
|
-
const mutation = vi.fn(async (mutationArg: any) => {
|
|
9
|
-
capturedArgs = mutationArg.updateCallRecordings.__args;
|
|
10
|
-
|
|
11
|
-
return { updateCallRecordings: [{ id: 'call-recording-1' }] };
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
const claimed = await completeCallRecordingIngestion(
|
|
15
|
-
{ mutation } as never,
|
|
16
|
-
{
|
|
17
|
-
id: 'call-recording-1',
|
|
18
|
-
},
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
expect(claimed).toBe(true);
|
|
22
|
-
expect(mutation).toHaveBeenCalledTimes(1);
|
|
23
|
-
expect(capturedArgs?.filter).toEqual({
|
|
24
|
-
id: { eq: 'call-recording-1' },
|
|
25
|
-
status: { in: ['SCHEDULED', 'JOINING', 'RECORDING', 'PROCESSING'] },
|
|
26
|
-
});
|
|
27
|
-
expect(capturedArgs?.data).toEqual({ status: 'COMPLETED' });
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it('returns false when the row was already COMPLETED, so the loser cannot charge', async () => {
|
|
31
|
-
const mutation = vi.fn(async () => ({ updateCallRecordings: [] }));
|
|
32
|
-
|
|
33
|
-
const claimed = await completeCallRecordingIngestion(
|
|
34
|
-
{ mutation } as never,
|
|
35
|
-
{
|
|
36
|
-
id: 'call-recording-1',
|
|
37
|
-
},
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
expect(claimed).toBe(false);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('returns false when the API omits the result list', async () => {
|
|
44
|
-
const mutation = vi.fn(async () => ({}));
|
|
45
|
-
|
|
46
|
-
const claimed = await completeCallRecordingIngestion(
|
|
47
|
-
{ mutation } as never,
|
|
48
|
-
{
|
|
49
|
-
id: 'call-recording-1',
|
|
50
|
-
},
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
expect(claimed).toBe(false);
|
|
54
|
-
});
|
|
55
|
-
});
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
-
|
|
3
|
-
import { fetchAllNodes } from 'src/logic-functions/data/fetch-all-nodes.util';
|
|
4
|
-
|
|
5
|
-
describe('fetchAllNodes', () => {
|
|
6
|
-
it('collects nodes across pages until hasNextPage is false', async () => {
|
|
7
|
-
const fetchPage = vi
|
|
8
|
-
.fn()
|
|
9
|
-
.mockResolvedValueOnce({
|
|
10
|
-
pageInfo: { hasNextPage: true, endCursor: 'cursor-1' },
|
|
11
|
-
edges: [{ node: 'node-1' }, { node: 'node-2' }],
|
|
12
|
-
})
|
|
13
|
-
.mockResolvedValueOnce({
|
|
14
|
-
pageInfo: { hasNextPage: false, endCursor: 'cursor-2' },
|
|
15
|
-
edges: [{ node: 'node-3' }],
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
const nodes = await fetchAllNodes<string>(fetchPage);
|
|
19
|
-
|
|
20
|
-
expect(nodes).toEqual(['node-1', 'node-2', 'node-3']);
|
|
21
|
-
expect(fetchPage).toHaveBeenNthCalledWith(1, undefined);
|
|
22
|
-
expect(fetchPage).toHaveBeenNthCalledWith(2, 'cursor-1');
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it('throws when hasNextPage is true without an endCursor', async () => {
|
|
26
|
-
const fetchPage = vi.fn().mockResolvedValue({
|
|
27
|
-
pageInfo: { hasNextPage: true, endCursor: null },
|
|
28
|
-
edges: [{ node: 'node-1' }],
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
await expect(fetchAllNodes<string>(fetchPage)).rejects.toThrow(
|
|
32
|
-
'Inconsistent pagination state: hasNextPage is true without an endCursor',
|
|
33
|
-
);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it('throws when the query returns no connection', async () => {
|
|
37
|
-
const fetchPage = vi.fn().mockResolvedValue(undefined);
|
|
38
|
-
|
|
39
|
-
await expect(fetchAllNodes<string>(fetchPage)).rejects.toThrow(
|
|
40
|
-
'Pagination query returned no connection',
|
|
41
|
-
);
|
|
42
|
-
});
|
|
43
|
-
});
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { afterEach, describe, expect, it } from 'vitest';
|
|
2
|
-
|
|
3
|
-
import { getCurrentWorkspaceId } from 'src/logic-functions/data/get-current-workspace-id.util';
|
|
4
|
-
|
|
5
|
-
const APP_ACCESS_TOKEN_ENV_VAR_NAME = 'TWENTY_APP_ACCESS_TOKEN';
|
|
6
|
-
const ORIGINAL_APP_ACCESS_TOKEN = process.env[APP_ACCESS_TOKEN_ENV_VAR_NAME];
|
|
7
|
-
const WORKSPACE_ID = '123e4567-e89b-12d3-a456-426614174000';
|
|
8
|
-
|
|
9
|
-
const restoreOriginalAppAccessToken = () => {
|
|
10
|
-
if (ORIGINAL_APP_ACCESS_TOKEN === undefined) {
|
|
11
|
-
delete process.env[APP_ACCESS_TOKEN_ENV_VAR_NAME];
|
|
12
|
-
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
process.env[APP_ACCESS_TOKEN_ENV_VAR_NAME] = ORIGINAL_APP_ACCESS_TOKEN;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const buildAccessToken = (payload: Record<string, unknown>): string =>
|
|
20
|
-
[
|
|
21
|
-
Buffer.from(JSON.stringify({ alg: 'none' })).toString('base64url'),
|
|
22
|
-
Buffer.from(JSON.stringify(payload)).toString('base64url'),
|
|
23
|
-
'signature',
|
|
24
|
-
].join('.');
|
|
25
|
-
|
|
26
|
-
describe('getCurrentWorkspaceId', () => {
|
|
27
|
-
afterEach(() => {
|
|
28
|
-
restoreOriginalAppAccessToken();
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it('reads the workspace id from the app access token payload', () => {
|
|
32
|
-
process.env[APP_ACCESS_TOKEN_ENV_VAR_NAME] = buildAccessToken({
|
|
33
|
-
workspaceId: WORKSPACE_ID,
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
expect(getCurrentWorkspaceId()).toBe(WORKSPACE_ID);
|
|
37
|
-
});
|
|
38
|
-
});
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
|
|
3
|
-
import { RESTRICTED_FIELD_PLACEHOLDER } from 'src/logic-functions/constants/restricted-field-placeholder';
|
|
4
|
-
import { stripRestrictedFieldValue } from 'src/logic-functions/data/strip-restricted-field-value.util';
|
|
5
|
-
|
|
6
|
-
describe('stripRestrictedFieldValue', () => {
|
|
7
|
-
it('drops the calendar visibility restriction placeholder', () => {
|
|
8
|
-
expect(
|
|
9
|
-
stripRestrictedFieldValue(RESTRICTED_FIELD_PLACEHOLDER),
|
|
10
|
-
).toBeUndefined();
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it('keeps regular values', () => {
|
|
14
|
-
expect(stripRestrictedFieldValue('Customer Discovery Call')).toBe(
|
|
15
|
-
'Customer Discovery Call',
|
|
16
|
-
);
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it('keeps undefined', () => {
|
|
20
|
-
expect(stripRestrictedFieldValue(undefined)).toBeUndefined();
|
|
21
|
-
});
|
|
22
|
-
});
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { type CoreApiClient } from 'twenty-client-sdk/core';
|
|
2
|
-
|
|
3
|
-
import { CallRecordingStatus } from 'src/logic-functions/constants/call-recording-status';
|
|
4
|
-
import { NON_TERMINAL_CALL_RECORDING_STATUSES } from 'src/logic-functions/constants/non-terminal-call-recording-statuses';
|
|
5
|
-
|
|
6
|
-
export const completeCallRecordingIngestion = async (
|
|
7
|
-
client: CoreApiClient,
|
|
8
|
-
{ id }: { id: string },
|
|
9
|
-
): Promise<boolean> => {
|
|
10
|
-
const result = await client.mutation({
|
|
11
|
-
updateCallRecordings: {
|
|
12
|
-
__args: {
|
|
13
|
-
filter: {
|
|
14
|
-
id: { eq: id },
|
|
15
|
-
status: { in: NON_TERMINAL_CALL_RECORDING_STATUSES },
|
|
16
|
-
},
|
|
17
|
-
data: { status: CallRecordingStatus.COMPLETED },
|
|
18
|
-
},
|
|
19
|
-
id: true,
|
|
20
|
-
},
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
return (result.updateCallRecordings ?? []).length > 0;
|
|
24
|
-
};
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { isUndefined } from '@sniptt/guards';
|
|
2
|
-
import { type CoreApiClient } from 'twenty-client-sdk/core';
|
|
3
|
-
|
|
4
|
-
import { type CallRecordingRequestStatus } from 'src/logic-functions/constants/call-recording-request-status';
|
|
5
|
-
import { type CallRecordingStatus } from 'src/logic-functions/constants/call-recording-status';
|
|
6
|
-
|
|
7
|
-
export type ScheduledCallRecordingFields = {
|
|
8
|
-
title: string | null;
|
|
9
|
-
status: CallRecordingStatus.SCHEDULED;
|
|
10
|
-
recordingRequestStatus: CallRecordingRequestStatus.REQUESTED;
|
|
11
|
-
calendarEventId: string;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export const createCallRecording = async (
|
|
15
|
-
client: CoreApiClient,
|
|
16
|
-
{
|
|
17
|
-
id,
|
|
18
|
-
data,
|
|
19
|
-
}: {
|
|
20
|
-
id: string;
|
|
21
|
-
data: ScheduledCallRecordingFields;
|
|
22
|
-
},
|
|
23
|
-
): Promise<string> => {
|
|
24
|
-
const mutationResult = await client.mutation({
|
|
25
|
-
createCallRecording: {
|
|
26
|
-
__args: {
|
|
27
|
-
data: { id, ...data },
|
|
28
|
-
},
|
|
29
|
-
id: true,
|
|
30
|
-
},
|
|
31
|
-
});
|
|
32
|
-
const createdCallRecordingId = mutationResult.createCallRecording?.id;
|
|
33
|
-
|
|
34
|
-
if (isUndefined(createdCallRecordingId)) {
|
|
35
|
-
throw new Error(
|
|
36
|
-
'createCallRecording mutation did not return a call recording id',
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return createdCallRecordingId;
|
|
41
|
-
};
|