@cosmoops/connect-sdk 0.27.0 → 0.28.0
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/CHANGELOG.md +49 -0
- package/dist/cjs/server/client.js +1 -1
- package/dist/esm/server/client.js +1 -1
- package/dist/types/server/client.d.ts +1 -1
- package/dist/types/types.d.ts +186 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,12 +3,61 @@
|
|
|
3
3
|
`@cosmoops/connect-sdk` follows semver, with the 0.x convention that **minor
|
|
4
4
|
versions may carry breaking changes** and patch versions never do.
|
|
5
5
|
|
|
6
|
+
## 0.28.0
|
|
7
|
+
|
|
8
|
+
Connect's webhook bus carried four events, all of them about billing and
|
|
9
|
+
deletion. It now carries the seven a system of record is actually built on —
|
|
10
|
+
calls, appointments and contacts — so the work your customers do inside
|
|
11
|
+
Connect can reach the product they do the rest of their work in.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- Seven webhook event types, with their payloads fully typed on
|
|
16
|
+
`ConnectWebhookEventMap`: `call.completed`, `call.missed`,
|
|
17
|
+
`booking.confirmed`, `booking.cancelled`, `booking.rescheduled`,
|
|
18
|
+
`contact.created` and `contact.updated`. Register handlers for them on
|
|
19
|
+
`createConnectWebhookHandler` exactly as you do the existing four.
|
|
20
|
+
- `ConnectCallDirection` and `ConnectContactSource`, the two unions those
|
|
21
|
+
payloads carry.
|
|
22
|
+
|
|
23
|
+
These are **activity** events rather than lifecycle ones, and the difference
|
|
24
|
+
decides who receives them: they are delivered only to applications the
|
|
25
|
+
workspace is actually subscribed to, so a lapsed customer stops emitting on
|
|
26
|
+
the same boundary that stops their access.
|
|
27
|
+
|
|
28
|
+
Three conventions are worth reading before you write a handler, each
|
|
29
|
+
documented on the types themselves. Phone numbers are E.164. A call event
|
|
30
|
+
identifies its party by `contactPhone` and deliberately carries no
|
|
31
|
+
`contactId` — Connect resolves a caller *by* the number and at the moment a
|
|
32
|
+
call ends it often has not, so the field would be `null` on most deliveries.
|
|
33
|
+
And `booking.rescheduled` carries `previousBookingId` as well as `bookingId`,
|
|
34
|
+
because Connect retires the old booking and writes a new one: reconcile on
|
|
35
|
+
the previous id or you will end up holding two appointments.
|
|
36
|
+
|
|
37
|
+
### Fixed
|
|
38
|
+
|
|
39
|
+
- `Booking` fixtures in the bundled tests compile again — the type gained a
|
|
40
|
+
required `hostMemberIds` in 0.27.0 and one fixture was missed. No runtime
|
|
41
|
+
change.
|
|
42
|
+
|
|
43
|
+
### A note on exhaustiveness
|
|
44
|
+
|
|
45
|
+
`ConnectWebhookEventType` is a union that grows, and this release grows it.
|
|
46
|
+
`createConnectWebhookHandler` is unaffected — its `on` map is partial and it
|
|
47
|
+
answers 200 to anything you have not registered. A hand-written `switch` with
|
|
48
|
+
an exhaustive `never` check on that union will now fail to compile until you
|
|
49
|
+
add the new members; that is the documented contract of this union rather than
|
|
50
|
+
a break, and it is the reason the handler exists.
|
|
51
|
+
|
|
6
52
|
## 0.27.0
|
|
7
53
|
|
|
8
54
|
A minor rather than a patch because `Booking` gains a required field, so a
|
|
9
55
|
hand-written object satisfying the old interface no longer type-checks. Nothing
|
|
10
56
|
you *read* from the API breaks.
|
|
11
57
|
|
|
58
|
+
0.26.1 was never published; its note below ships as part of this release, so the
|
|
59
|
+
registry goes 0.26.0 → 0.27.0.
|
|
60
|
+
|
|
12
61
|
### Added
|
|
13
62
|
|
|
14
63
|
- **`connect.scheduling.getBooking()`** - one appointment, by the id you
|
package/dist/types/types.d.ts
CHANGED
|
@@ -775,7 +775,7 @@ export interface EmitEventsResponse {
|
|
|
775
775
|
* `createConnectWebhookHandler` simply ignores anything you have not
|
|
776
776
|
* registered a handler for.
|
|
777
777
|
*/
|
|
778
|
-
export type ConnectWebhookEventType = "workspace.deletion_scheduled" | "workspace.deletion_cancelled" | "workspace.deleted" | "subscription.cancelled";
|
|
778
|
+
export type ConnectWebhookEventType = "workspace.deletion_scheduled" | "workspace.deletion_cancelled" | "workspace.deleted" | "subscription.cancelled" | "call.completed" | "call.missed" | "booking.confirmed" | "booking.cancelled" | "booking.rescheduled" | "contact.created" | "contact.updated";
|
|
779
779
|
/**
|
|
780
780
|
* A workspace's deletion has been confirmed and the grace window is running.
|
|
781
781
|
*
|
|
@@ -815,12 +815,197 @@ export interface SubscriptionCancelledEvent {
|
|
|
815
815
|
subscriptionId: string;
|
|
816
816
|
applicationId: string;
|
|
817
817
|
}
|
|
818
|
+
/** Which way a call went. */
|
|
819
|
+
export type ConnectCallDirection = "inbound" | "outbound";
|
|
820
|
+
/**
|
|
821
|
+
* A call ended.
|
|
822
|
+
*
|
|
823
|
+
* The event an external system of record is built on: it is what turns a
|
|
824
|
+
* conversation that happened in Connect's telephony into a row in your own
|
|
825
|
+
* timeline with nobody retyping it. Fires for every completed call, whether an
|
|
826
|
+
* agent answered it or a person did.
|
|
827
|
+
*/
|
|
828
|
+
export interface CallCompletedEvent {
|
|
829
|
+
workspaceId: string;
|
|
830
|
+
callId: string;
|
|
831
|
+
channelId: string | null;
|
|
832
|
+
/**
|
|
833
|
+
* E.164, and the only identity a call event carries.
|
|
834
|
+
*
|
|
835
|
+
* There is deliberately no `contactId`: Connect resolves a caller to a
|
|
836
|
+
* contact by number, and at the moment a call ends it may not have done so
|
|
837
|
+
* at all - the field would be `null` on most deliveries, which is a field
|
|
838
|
+
* that silently does nothing. Match on this instead. It is the same
|
|
839
|
+
* canonical form `contacts.lookupByPhone` takes, so resolving it is one call
|
|
840
|
+
* if you want the contact.
|
|
841
|
+
*/
|
|
842
|
+
contactPhone: string | null;
|
|
843
|
+
direction: ConnectCallDirection;
|
|
844
|
+
/** How it ended, as Connect's telephony reported it - `"completed"`, `"transferred"`, … */
|
|
845
|
+
outcome: string;
|
|
846
|
+
durationSeconds: number;
|
|
847
|
+
/**
|
|
848
|
+
* What the agent's skills captured during the conversation, keyed by the
|
|
849
|
+
* capture fields the agent declares.
|
|
850
|
+
*
|
|
851
|
+
* Shapeless on purpose - the keys and the value types are whatever that
|
|
852
|
+
* agent's `extractionSchema` declares, which Connect does not constrain.
|
|
853
|
+
* `{}` on most calls, since an unanswered or human-answered call extracts
|
|
854
|
+
* nothing, so treat every key as optional rather than checking the object
|
|
855
|
+
* for presence.
|
|
856
|
+
*/
|
|
857
|
+
extraction: Record<string, unknown>;
|
|
858
|
+
/** ISO-8601. */
|
|
859
|
+
occurredAt: string;
|
|
860
|
+
}
|
|
861
|
+
/**
|
|
862
|
+
* A call reached a channel and nothing answered it.
|
|
863
|
+
*
|
|
864
|
+
* Its own event rather than an `outcome` on the one above, because the action
|
|
865
|
+
* differs in kind: a completed call is something to file, a missed one is
|
|
866
|
+
* somebody to ring back. Treating this as a lead is the right thing to do
|
|
867
|
+
* with it.
|
|
868
|
+
*/
|
|
869
|
+
export interface CallMissedEvent {
|
|
870
|
+
workspaceId: string;
|
|
871
|
+
callId: string;
|
|
872
|
+
channelId: string | null;
|
|
873
|
+
/** E.164, and the only identity this carries - see `CallCompletedEvent.contactPhone`. */
|
|
874
|
+
contactPhone: string | null;
|
|
875
|
+
direction: ConnectCallDirection;
|
|
876
|
+
/** ISO-8601. */
|
|
877
|
+
occurredAt: string;
|
|
878
|
+
}
|
|
879
|
+
/**
|
|
880
|
+
* An appointment was booked and is holding its slot.
|
|
881
|
+
*
|
|
882
|
+
* Raised however it was booked - the customer's portal, the public booking
|
|
883
|
+
* page, a voice agent mid-call, or your own API call - so you get one shape
|
|
884
|
+
* for all four and never have to reconcile "did we create this, or did they?".
|
|
885
|
+
* Dedupe on `bookingId`, not on the envelope alone.
|
|
886
|
+
*/
|
|
887
|
+
export interface BookingConfirmedEvent {
|
|
888
|
+
workspaceId: string;
|
|
889
|
+
bookingId: string;
|
|
890
|
+
eventTypeId: string;
|
|
891
|
+
eventTypeName: string;
|
|
892
|
+
/** ISO-8601, UTC. Render it in `timezone`, which is the workspace's, not the viewer's. */
|
|
893
|
+
startAt: string;
|
|
894
|
+
endAt: string;
|
|
895
|
+
/** IANA zone the appointment was booked in. */
|
|
896
|
+
timezone: string;
|
|
897
|
+
attendeeName: string;
|
|
898
|
+
attendeeEmail: string | null;
|
|
899
|
+
/** E.164. */
|
|
900
|
+
attendeePhone: string | null;
|
|
901
|
+
contactId: string | null;
|
|
902
|
+
/** Connect user ids of the hosts. */
|
|
903
|
+
hostMemberIds: string[];
|
|
904
|
+
/** ISO-8601. */
|
|
905
|
+
occurredAt: string;
|
|
906
|
+
}
|
|
907
|
+
/** An appointment was cancelled. The slot is free and any prep against it is void. */
|
|
908
|
+
export interface BookingCancelledEvent {
|
|
909
|
+
workspaceId: string;
|
|
910
|
+
bookingId: string;
|
|
911
|
+
eventTypeId: string;
|
|
912
|
+
eventTypeName: string;
|
|
913
|
+
/** ISO-8601. The time it *was* going to happen. */
|
|
914
|
+
startAt: string;
|
|
915
|
+
attendeeName: string;
|
|
916
|
+
contactId: string | null;
|
|
917
|
+
/** ISO-8601. */
|
|
918
|
+
occurredAt: string;
|
|
919
|
+
}
|
|
920
|
+
/**
|
|
921
|
+
* An appointment moved.
|
|
922
|
+
*
|
|
923
|
+
* Connect retires the old booking and writes a new one rather than mutating
|
|
924
|
+
* it, so this carries **both ids**: `bookingId` is the row that now exists and
|
|
925
|
+
* `previousBookingId` is the one you are already holding. Reconcile on the
|
|
926
|
+
* previous id or you will end up with two appointments.
|
|
927
|
+
*/
|
|
928
|
+
export interface BookingRescheduledEvent {
|
|
929
|
+
workspaceId: string;
|
|
930
|
+
bookingId: string;
|
|
931
|
+
eventTypeId: string;
|
|
932
|
+
eventTypeName: string;
|
|
933
|
+
/** ISO-8601, the new time. */
|
|
934
|
+
startAt: string;
|
|
935
|
+
endAt: string;
|
|
936
|
+
previousBookingId: string;
|
|
937
|
+
/** ISO-8601, the time it was before. */
|
|
938
|
+
previousStartAt: string;
|
|
939
|
+
timezone: string;
|
|
940
|
+
attendeeName: string;
|
|
941
|
+
contactId: string | null;
|
|
942
|
+
/** ISO-8601. */
|
|
943
|
+
occurredAt: string;
|
|
944
|
+
}
|
|
945
|
+
/**
|
|
946
|
+
* How Connect came to know a contact.
|
|
947
|
+
*
|
|
948
|
+
* `extraction` is the interesting one: an agent's skill captured them from
|
|
949
|
+
* what was said, with nobody typing anything. `call` means the number was seen
|
|
950
|
+
* on a call. `manual` and `import` are the two a human stands behind, and
|
|
951
|
+
* Connect lets only those overwrite a field that already has a value.
|
|
952
|
+
*/
|
|
953
|
+
export type ConnectContactSource = "call" | "manual" | "import" | "api" | "extraction";
|
|
954
|
+
/**
|
|
955
|
+
* Connect learned about a person.
|
|
956
|
+
*
|
|
957
|
+
* The event with no equivalent anywhere else in this API: most often an agent
|
|
958
|
+
* captured them mid-call through the `contact-capture` skill, so the contact
|
|
959
|
+
* exists in Connect and your product has never heard of them. Without this the
|
|
960
|
+
* capture is invisible where the customer actually works.
|
|
961
|
+
*/
|
|
962
|
+
export interface ContactCreatedEvent {
|
|
963
|
+
workspaceId: string;
|
|
964
|
+
contactId: string;
|
|
965
|
+
name: string | null;
|
|
966
|
+
/** E.164. */
|
|
967
|
+
phone: string | null;
|
|
968
|
+
email: string | null;
|
|
969
|
+
company: string | null;
|
|
970
|
+
source: ConnectContactSource;
|
|
971
|
+
/** ISO-8601. */
|
|
972
|
+
occurredAt: string;
|
|
973
|
+
}
|
|
974
|
+
/**
|
|
975
|
+
* A known contact's details changed.
|
|
976
|
+
*
|
|
977
|
+
* `changed` names the fields that actually moved, so you can apply a patch
|
|
978
|
+
* rather than overwriting fields your own users may have curated - a customer
|
|
979
|
+
* who corrected a company name in your product should not have it replaced by
|
|
980
|
+
* what an agent heard over a bad line.
|
|
981
|
+
*/
|
|
982
|
+
export interface ContactUpdatedEvent {
|
|
983
|
+
workspaceId: string;
|
|
984
|
+
contactId: string;
|
|
985
|
+
name: string | null;
|
|
986
|
+
/** E.164. */
|
|
987
|
+
phone: string | null;
|
|
988
|
+
email: string | null;
|
|
989
|
+
company: string | null;
|
|
990
|
+
/** The field names that changed on this update. */
|
|
991
|
+
changed: string[];
|
|
992
|
+
source: ConnectContactSource;
|
|
993
|
+
/** ISO-8601. */
|
|
994
|
+
occurredAt: string;
|
|
995
|
+
}
|
|
818
996
|
/** Maps each event type to the shape of its `data`. */
|
|
819
997
|
export interface ConnectWebhookEventMap {
|
|
820
998
|
"workspace.deletion_scheduled": WorkspaceDeletionScheduledEvent;
|
|
821
999
|
"workspace.deletion_cancelled": WorkspaceDeletionCancelledEvent;
|
|
822
1000
|
"workspace.deleted": WorkspaceDeletedEvent;
|
|
823
1001
|
"subscription.cancelled": SubscriptionCancelledEvent;
|
|
1002
|
+
"call.completed": CallCompletedEvent;
|
|
1003
|
+
"call.missed": CallMissedEvent;
|
|
1004
|
+
"booking.confirmed": BookingConfirmedEvent;
|
|
1005
|
+
"booking.cancelled": BookingCancelledEvent;
|
|
1006
|
+
"booking.rescheduled": BookingRescheduledEvent;
|
|
1007
|
+
"contact.created": ContactCreatedEvent;
|
|
1008
|
+
"contact.updated": ContactUpdatedEvent;
|
|
824
1009
|
}
|
|
825
1010
|
/** The envelope, as it arrives on the wire. */
|
|
826
1011
|
export interface ConnectWebhookEnvelope<T extends ConnectWebhookEventType = ConnectWebhookEventType> {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmoops/connect-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.0",
|
|
4
4
|
"description": "Official server-side SDK for the CosmoOps Connect platform API - Login with Connect, entitlements, billing and metering.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"type": "commonjs",
|