fauna-api 1.0.682 → 1.0.686
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/dist/src/cicada/contacts.d.ts +19 -25
- package/dist/src/cicada/contacts.js +17 -5
- package/dist/src/cicada/inboxes.d.ts +16 -0
- package/dist/src/cicada/inboxes.js +10 -0
- package/dist/src/ui/integrations.js +74 -0
- package/dist/src/ui/ui.css +137 -0
- package/package.json +1 -1
|
@@ -1,31 +1,25 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
export type
|
|
4
|
-
|
|
5
|
-
handle
|
|
6
|
-
|
|
7
|
-
};
|
|
8
|
-
export type Slack = {
|
|
9
|
-
displayName: string;
|
|
10
|
-
email: string;
|
|
11
|
-
headline: string;
|
|
12
|
-
};
|
|
13
|
-
export type Email = {
|
|
14
|
-
email: string;
|
|
1
|
+
import { Credentials, ApiKey } from "../authentification.js";
|
|
2
|
+
export type AddressKind = 'email' | 'phone' | 'discord';
|
|
3
|
+
export type Address = {
|
|
4
|
+
kind: AddressKind;
|
|
5
|
+
/** Lowercase email, E.164 phone (+12395551234), or Discord handle without @. */
|
|
6
|
+
value: string;
|
|
15
7
|
};
|
|
16
|
-
export type SMS = {
|
|
17
|
-
phone: string;
|
|
18
|
-
};
|
|
19
|
-
export type Identity = Discord | Slack | Email | SMS;
|
|
20
8
|
export type Contact = {
|
|
21
|
-
|
|
9
|
+
id: string;
|
|
10
|
+
displayName: string;
|
|
11
|
+
addresses: Address[];
|
|
12
|
+
/** One of its emails belongs to a Fauna account: the verified badge. */
|
|
22
13
|
registered: boolean;
|
|
23
|
-
|
|
14
|
+
/** That Fauna account's picture. */
|
|
15
|
+
icon?: string;
|
|
24
16
|
};
|
|
17
|
+
/** Every contact, sorted by display name. */
|
|
25
18
|
export declare function list(authorization: Credentials | ApiKey): Promise<Contact[]>;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
19
|
+
/** Creates a contact, or with `id` renames one and replaces its addresses. */
|
|
20
|
+
export declare function save(authorization: Credentials | ApiKey, contact: {
|
|
21
|
+
id?: string;
|
|
22
|
+
displayName: string;
|
|
23
|
+
addresses: Address[];
|
|
31
24
|
}): Promise<Contact>;
|
|
25
|
+
export declare function remove(authorization: Credentials | ApiKey, id: string): Promise<void>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Cicada } from "./index.js";
|
|
2
|
+
/** Every contact, sorted by display name. */
|
|
2
3
|
export async function list(authorization) {
|
|
3
4
|
const response = await fetch(`${Cicada.getURL()}/cicada/contacts`, {
|
|
4
5
|
method: "POST",
|
|
@@ -11,18 +12,29 @@ export async function list(authorization) {
|
|
|
11
12
|
throw new Error(await response.text());
|
|
12
13
|
return await response.json();
|
|
13
14
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const response = await fetch(`${Cicada.getURL()}/cicada/contacts/create`, {
|
|
15
|
+
/** Creates a contact, or with `id` renames one and replaces its addresses. */
|
|
16
|
+
export async function save(authorization, contact) {
|
|
17
|
+
const response = await fetch(`${Cicada.getURL()}/cicada/contacts/save`, {
|
|
18
18
|
method: "POST",
|
|
19
19
|
headers: {
|
|
20
20
|
"Content-Type": "application/json",
|
|
21
21
|
"Authorization": 'email' in authorization ? `Token ${authorization.token}` : `ApiKey ${authorization.id}`
|
|
22
22
|
},
|
|
23
|
-
body: JSON.stringify(
|
|
23
|
+
body: JSON.stringify(contact)
|
|
24
24
|
});
|
|
25
25
|
if (!response.ok)
|
|
26
26
|
throw new Error(await response.text());
|
|
27
27
|
return await response.json();
|
|
28
28
|
}
|
|
29
|
+
export async function remove(authorization, id) {
|
|
30
|
+
const response = await fetch(`${Cicada.getURL()}/cicada/contacts/delete`, {
|
|
31
|
+
method: "POST",
|
|
32
|
+
headers: {
|
|
33
|
+
"Content-Type": "application/json",
|
|
34
|
+
"Authorization": 'email' in authorization ? `Token ${authorization.token}` : `ApiKey ${authorization.id}`
|
|
35
|
+
},
|
|
36
|
+
body: JSON.stringify({ id })
|
|
37
|
+
});
|
|
38
|
+
if (!response.ok)
|
|
39
|
+
throw new Error(await response.text());
|
|
40
|
+
}
|
|
@@ -12,6 +12,8 @@ export type Inbox = {
|
|
|
12
12
|
name: string;
|
|
13
13
|
createdAt: Date;
|
|
14
14
|
group?: InboxGroup;
|
|
15
|
+
/** An agent is on for this inbox. */
|
|
16
|
+
agent?: boolean;
|
|
15
17
|
};
|
|
16
18
|
export type InboxAccount = {
|
|
17
19
|
platform: Platform;
|
|
@@ -46,3 +48,17 @@ export declare function setAgent(authorization: Credentials | ApiKey, inbox: str
|
|
|
46
48
|
dailyLimit: number;
|
|
47
49
|
}): Promise<AgentSettings>;
|
|
48
50
|
export declare function clearAgent(authorization: Credentials | ApiKey, inbox: string): Promise<void>;
|
|
51
|
+
/**
|
|
52
|
+
* Has the inbox's agent phone `to` from one of the inbox's lines (`from`, or its first)
|
|
53
|
+
* and follow `directions`. Returns once the call is placed; the transcript lands on the
|
|
54
|
+
* thread with that number. Owners only; counts toward the agent's daily limit.
|
|
55
|
+
*/
|
|
56
|
+
export declare function agentCall(authorization: Credentials, inbox: string, call: {
|
|
57
|
+
to: string;
|
|
58
|
+
directions: string;
|
|
59
|
+
from?: string;
|
|
60
|
+
}): Promise<{
|
|
61
|
+
calling: string;
|
|
62
|
+
from: string;
|
|
63
|
+
callId: string;
|
|
64
|
+
}>;
|
|
@@ -25,6 +25,7 @@ function wrapInbox(raw) {
|
|
|
25
25
|
name: raw.name,
|
|
26
26
|
createdAt: new Date(raw.createdAt),
|
|
27
27
|
...(group ? { group } : {}),
|
|
28
|
+
...(raw.agent ? { agent: true } : {}),
|
|
28
29
|
};
|
|
29
30
|
}
|
|
30
31
|
export async function list(authorization) {
|
|
@@ -80,3 +81,12 @@ export async function setAgent(authorization, inbox, settings) {
|
|
|
80
81
|
export async function clearAgent(authorization, inbox) {
|
|
81
82
|
await post(authorization, '/cicada/inboxes/agent/clear', { inbox });
|
|
82
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* Has the inbox's agent phone `to` from one of the inbox's lines (`from`, or its first)
|
|
86
|
+
* and follow `directions`. Returns once the call is placed; the transcript lands on the
|
|
87
|
+
* thread with that number. Owners only; counts toward the agent's daily limit.
|
|
88
|
+
*/
|
|
89
|
+
export async function agentCall(authorization, inbox, call) {
|
|
90
|
+
const response = await post(authorization, '/cicada/inboxes/agent/call', { inbox, ...call });
|
|
91
|
+
return await response.json();
|
|
92
|
+
}
|
|
@@ -75,6 +75,77 @@ export function createConnections(credentials, options = {}) {
|
|
|
75
75
|
fail(err);
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
|
+
// Twilio delivers new texts only to the number's own "A message comes in" webhook,
|
|
79
|
+
// which Fauna doesn't set, so a linked number shows where to point it.
|
|
80
|
+
function buildTwilioWebhookNote() {
|
|
81
|
+
const url = `${new URL(Fauna.getURL()).origin}/integrations/twilio/webhook`;
|
|
82
|
+
const note = document.createElement('div');
|
|
83
|
+
note.className = 'connection-card-note';
|
|
84
|
+
const head = document.createElement('div');
|
|
85
|
+
head.className = 'connection-card-note-head';
|
|
86
|
+
head.innerHTML = '<span class="material-symbols-outlined connection-card-note-icon">error</span>';
|
|
87
|
+
const title = document.createElement('span');
|
|
88
|
+
title.className = 'connection-card-note-title';
|
|
89
|
+
title.textContent = 'Set the webhook in Twilio';
|
|
90
|
+
title.title = 'New texts only reach Fauna once Twilio sends them to this webhook.';
|
|
91
|
+
head.appendChild(title);
|
|
92
|
+
const open = document.createElement('a');
|
|
93
|
+
open.className = 'connection-card-note-link';
|
|
94
|
+
open.href = 'https://console.twilio.com/us1/develop/phone-numbers/manage/incoming';
|
|
95
|
+
open.target = '_blank';
|
|
96
|
+
open.rel = 'noopener';
|
|
97
|
+
open.innerHTML = 'Open<span class="material-symbols-outlined">open_in_new</span>';
|
|
98
|
+
head.appendChild(open);
|
|
99
|
+
note.appendChild(head);
|
|
100
|
+
const steps = document.createElement('ol');
|
|
101
|
+
steps.className = 'connection-card-note-steps';
|
|
102
|
+
for (const path of [
|
|
103
|
+
['Active numbers', 'your number'],
|
|
104
|
+
['Messaging', 'A message comes in'],
|
|
105
|
+
['Webhook, HTTP POST, this URL'],
|
|
106
|
+
]) {
|
|
107
|
+
const step = document.createElement('li');
|
|
108
|
+
path.forEach((part, i) => {
|
|
109
|
+
if (i) {
|
|
110
|
+
const arrow = document.createElement('span');
|
|
111
|
+
arrow.className = 'material-symbols-outlined connection-card-note-arrow';
|
|
112
|
+
arrow.textContent = 'arrow_forward';
|
|
113
|
+
step.appendChild(arrow);
|
|
114
|
+
}
|
|
115
|
+
const text = document.createElement('span');
|
|
116
|
+
text.textContent = part;
|
|
117
|
+
step.appendChild(text);
|
|
118
|
+
});
|
|
119
|
+
steps.appendChild(step);
|
|
120
|
+
}
|
|
121
|
+
note.appendChild(steps);
|
|
122
|
+
const copy = document.createElement('button');
|
|
123
|
+
copy.type = 'button';
|
|
124
|
+
copy.className = 'connection-card-note-url';
|
|
125
|
+
copy.title = `Copy ${url}`;
|
|
126
|
+
const code = document.createElement('code');
|
|
127
|
+
code.textContent = url;
|
|
128
|
+
const icon = document.createElement('span');
|
|
129
|
+
icon.className = 'material-symbols-outlined';
|
|
130
|
+
icon.textContent = 'content_copy';
|
|
131
|
+
copy.append(code, icon);
|
|
132
|
+
copy.onclick = async () => {
|
|
133
|
+
try {
|
|
134
|
+
await navigator.clipboard.writeText(url);
|
|
135
|
+
icon.textContent = 'check';
|
|
136
|
+
copy.classList.add('copied');
|
|
137
|
+
setTimeout(() => {
|
|
138
|
+
icon.textContent = 'content_copy';
|
|
139
|
+
copy.classList.remove('copied');
|
|
140
|
+
}, 1600);
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
fail(err);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
note.appendChild(copy);
|
|
147
|
+
return note;
|
|
148
|
+
}
|
|
78
149
|
// One card per platform. `accounts` are the already-linked accounts for this
|
|
79
150
|
// platform (possibly several); each gets a labeled row with an unlink action.
|
|
80
151
|
function buildCard(platform, accounts) {
|
|
@@ -141,6 +212,9 @@ export function createConnections(credentials, options = {}) {
|
|
|
141
212
|
}
|
|
142
213
|
card.appendChild(accountsBox);
|
|
143
214
|
}
|
|
215
|
+
if (platform === Fauna.Integrations.Platform.TWILIO && accounts.length) {
|
|
216
|
+
card.appendChild(buildTwilioWebhookNote());
|
|
217
|
+
}
|
|
144
218
|
// Connect / add-another action.
|
|
145
219
|
const connectBtn = document.createElement('button');
|
|
146
220
|
connectBtn.type = 'button';
|
package/dist/src/ui/ui.css
CHANGED
|
@@ -2417,6 +2417,143 @@ button.chat-message-file {
|
|
|
2417
2417
|
color: color-mix(in srgb, var(--text, #1a1a18) 70%, transparent);
|
|
2418
2418
|
}
|
|
2419
2419
|
|
|
2420
|
+
.connection-card-note {
|
|
2421
|
+
display: flex;
|
|
2422
|
+
flex-direction: column;
|
|
2423
|
+
gap: 8px;
|
|
2424
|
+
|
|
2425
|
+
padding: 10px 12px 12px;
|
|
2426
|
+
|
|
2427
|
+
border: 1px solid color-mix(in srgb, #f59e0b 34%, transparent);
|
|
2428
|
+
border-radius: 10px;
|
|
2429
|
+
background: color-mix(in srgb, #f59e0b 9%, transparent);
|
|
2430
|
+
}
|
|
2431
|
+
.connection-card-note-head {
|
|
2432
|
+
display: flex;
|
|
2433
|
+
align-items: center;
|
|
2434
|
+
gap: 7px;
|
|
2435
|
+
}
|
|
2436
|
+
.connection-card-note-icon {
|
|
2437
|
+
flex: 0 0 auto;
|
|
2438
|
+
font-size: 18px !important;
|
|
2439
|
+
color: #d97706;
|
|
2440
|
+
}
|
|
2441
|
+
.connection-card-note-title {
|
|
2442
|
+
flex: 1;
|
|
2443
|
+
min-width: 0;
|
|
2444
|
+
|
|
2445
|
+
font-size: 12.5px;
|
|
2446
|
+
font-weight: 600;
|
|
2447
|
+
line-height: 1.3;
|
|
2448
|
+
color: var(--text, #1a1a18);
|
|
2449
|
+
}
|
|
2450
|
+
.connection-card-note-link {
|
|
2451
|
+
display: inline-flex;
|
|
2452
|
+
align-items: center;
|
|
2453
|
+
gap: 2px;
|
|
2454
|
+
|
|
2455
|
+
font-size: 12px;
|
|
2456
|
+
font-weight: 600;
|
|
2457
|
+
white-space: nowrap;
|
|
2458
|
+
text-decoration: none;
|
|
2459
|
+
color: var(--connection-note-accent, #b45309);
|
|
2460
|
+
}
|
|
2461
|
+
.connection-card-note-link span {
|
|
2462
|
+
font-size: 14px !important;
|
|
2463
|
+
}
|
|
2464
|
+
.connection-card-note-link:hover {
|
|
2465
|
+
text-decoration: underline;
|
|
2466
|
+
}
|
|
2467
|
+
.connection-card-note-steps {
|
|
2468
|
+
display: flex;
|
|
2469
|
+
flex-direction: column;
|
|
2470
|
+
gap: 5px;
|
|
2471
|
+
|
|
2472
|
+
margin: 0;
|
|
2473
|
+
padding: 0 0 0 25px;
|
|
2474
|
+
|
|
2475
|
+
list-style: none;
|
|
2476
|
+
counter-reset: connection-step;
|
|
2477
|
+
}
|
|
2478
|
+
.connection-card-note-steps li {
|
|
2479
|
+
position: relative;
|
|
2480
|
+
|
|
2481
|
+
display: flex;
|
|
2482
|
+
flex-wrap: wrap;
|
|
2483
|
+
align-items: center;
|
|
2484
|
+
gap: 2px 4px;
|
|
2485
|
+
|
|
2486
|
+
font-size: 12px;
|
|
2487
|
+
line-height: 16px;
|
|
2488
|
+
color: color-mix(in srgb, var(--text, #1a1a18) 78%, transparent);
|
|
2489
|
+
|
|
2490
|
+
counter-increment: connection-step;
|
|
2491
|
+
}
|
|
2492
|
+
.connection-card-note-steps li::before {
|
|
2493
|
+
content: counter(connection-step);
|
|
2494
|
+
|
|
2495
|
+
position: absolute;
|
|
2496
|
+
left: -25px;
|
|
2497
|
+
top: 0;
|
|
2498
|
+
|
|
2499
|
+
display: flex;
|
|
2500
|
+
align-items: center;
|
|
2501
|
+
justify-content: center;
|
|
2502
|
+
|
|
2503
|
+
width: 16px;
|
|
2504
|
+
height: 16px;
|
|
2505
|
+
|
|
2506
|
+
border-radius: 50%;
|
|
2507
|
+
background: color-mix(in srgb, #f59e0b 20%, transparent);
|
|
2508
|
+
color: var(--connection-note-accent, #b45309);
|
|
2509
|
+
|
|
2510
|
+
font-size: 10px;
|
|
2511
|
+
font-weight: 700;
|
|
2512
|
+
}
|
|
2513
|
+
.connection-card-note-arrow {
|
|
2514
|
+
font-size: 13px !important;
|
|
2515
|
+
color: color-mix(in srgb, var(--text, #1a1a18) 38%, transparent);
|
|
2516
|
+
}
|
|
2517
|
+
.connection-card-note-url {
|
|
2518
|
+
display: flex;
|
|
2519
|
+
align-items: center;
|
|
2520
|
+
gap: 8px;
|
|
2521
|
+
|
|
2522
|
+
width: 100%;
|
|
2523
|
+
padding: 6px 8px 6px 10px;
|
|
2524
|
+
|
|
2525
|
+
border: 1px solid color-mix(in srgb, var(--text, #1a1a18) 12%, transparent);
|
|
2526
|
+
border-radius: 8px;
|
|
2527
|
+
background: var(--surface, #fff);
|
|
2528
|
+
color: var(--text, #1a1a18);
|
|
2529
|
+
|
|
2530
|
+
cursor: pointer;
|
|
2531
|
+
text-align: left;
|
|
2532
|
+
transition: border-color 0.15s ease;
|
|
2533
|
+
}
|
|
2534
|
+
.connection-card-note-url code {
|
|
2535
|
+
flex: 1;
|
|
2536
|
+
min-width: 0;
|
|
2537
|
+
|
|
2538
|
+
overflow: hidden;
|
|
2539
|
+
text-overflow: ellipsis;
|
|
2540
|
+
white-space: nowrap;
|
|
2541
|
+
|
|
2542
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
2543
|
+
font-size: 11.5px;
|
|
2544
|
+
}
|
|
2545
|
+
.connection-card-note-url span {
|
|
2546
|
+
font-size: 15px !important;
|
|
2547
|
+
color: color-mix(in srgb, var(--text, #1a1a18) 50%, transparent);
|
|
2548
|
+
transition: color 0.15s ease;
|
|
2549
|
+
}
|
|
2550
|
+
.connection-card-note-url:hover {
|
|
2551
|
+
border-color: color-mix(in srgb, var(--text, #1a1a18) 26%, transparent);
|
|
2552
|
+
}
|
|
2553
|
+
.connection-card-note-url.copied span {
|
|
2554
|
+
color: #16a34a;
|
|
2555
|
+
}
|
|
2556
|
+
|
|
2420
2557
|
|
|
2421
2558
|
/* Social sign-in buttons (UI.Authentification.createOAuthButtons).
|
|
2422
2559
|
Themed via --oauth-* custom properties so each app can recolor without
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fauna-api",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.686",
|
|
4
4
|
"description": "The Fauna SDK: accounts, Drive, groups, calendar, chats, payments and every Fauna app (Parrot, Marmot, Magpie, Cicada, Ant, Termite), plus React UI.",
|
|
5
5
|
"homepage": "https://docs.faunakit.com",
|
|
6
6
|
"repository": {
|