@dropby/server 0.4.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.
@@ -0,0 +1,882 @@
1
+ /** DropBy's id for one of your products, `prj_…`. */
2
+ type ProductId = `prj_${string}`;
3
+ /**
4
+ * DropBy's id for one of your end users, `act_…`. Your own id for them is their
5
+ * `externalId`.
6
+ */
7
+ type UserId = `act_${string}`;
8
+ /**
9
+ * DropBy's id for one of your customer accounts, `acc_…`. Your own id for it is
10
+ * its `externalId`.
11
+ */
12
+ type AccountId = `acc_${string}`;
13
+ /** The id of someone on your team in DropBy, `adm_…`. */
14
+ type TeamMemberId = `adm_${string}`;
15
+ /** The id of an ask, `ask_…`. */
16
+ type AskId = `ask_${string}`;
17
+ /** The id of one user's response to an ask, `asr_…`. */
18
+ type AskResponseId = `asr_${string}`;
19
+ /** The id of a chat attachment, `att_…`. */
20
+ type AttachmentId = `att_${string}`;
21
+ /** The id of an idea, `idea_…`. */
22
+ type IdeaId = `idea_${string}`;
23
+ /** The id of a chat message, `msg_…`. */
24
+ type MessageId = `msg_${string}`;
25
+ /** DropBy's id for a browser key, `pkey_…`. It names the key; it is not the key. */
26
+ type PublicKeyId = `pkey_${string}`;
27
+ /** A browser session token, `dbs_…`, as `browserSessions.create` returns it. */
28
+ type SessionToken = `dbs_${string}`;
29
+ /** The id of a chat thread, `thr_…`. */
30
+ type ThreadId = `thr_${string}`;
31
+ /**
32
+ * Which of a product's two environments: `live` for your real users, `test` for
33
+ * trying things.
34
+ */
35
+ type Environment = "live" | "test";
36
+ /**
37
+ * A flat attribute or context value. Strings are at most 500 characters, lists at
38
+ * most 20 items.
39
+ */
40
+ type AttributeValue = string | number | boolean | null | (string | number | boolean)[];
41
+ /** Flat facts about a user or account, key to value. */
42
+ type Attributes = Record<string, AttributeValue>;
43
+ /**
44
+ * An end user of your product, as your backend knows them. Keys besides the
45
+ * named ones are facts about this session that ask and feature flag rules can
46
+ * target as `user.<key>`. `attributes` are saved on the user instead, for
47
+ * audiences.
48
+ */
49
+ interface SessionUser {
50
+ id: string;
51
+ email?: string | undefined;
52
+ name?: string | undefined;
53
+ attributes?: Attributes | undefined;
54
+ [key: string]: AttributeValue | Attributes | undefined;
55
+ }
56
+ /**
57
+ * The customer account an end user belongs to. Keys besides the named ones are
58
+ * facts about this session that ask and feature flag rules can target as
59
+ * `account.<key>`. `attributes` are saved on the account instead, for audiences.
60
+ */
61
+ interface SessionAccount {
62
+ id: string;
63
+ domain?: string | undefined;
64
+ name?: string | undefined;
65
+ attributes?: Attributes | undefined;
66
+ [key: string]: AttributeValue | Attributes | undefined;
67
+ }
68
+ /** A user in a response: `id` is DropBy's, `externalId` is the id you gave them. */
69
+ interface UserReference {
70
+ id: UserId;
71
+ externalId: string;
72
+ name: string | null;
73
+ email: string | null;
74
+ }
75
+ /** An account in a response: `id` is DropBy's, `externalId` is the id you gave it. */
76
+ interface AccountReference {
77
+ id: AccountId;
78
+ externalId: string;
79
+ name: string | null;
80
+ domain: string | null;
81
+ }
82
+ /** A page of a list. Pass `nextCursor` back as `cursor` for the next page; null on the last. */
83
+ interface Page<Item> {
84
+ items: Item[];
85
+ nextCursor: string | null;
86
+ }
87
+ /** The context an end user had when they wrote, by namespace. */
88
+ interface ContextSnapshot {
89
+ user: Attributes;
90
+ account: Attributes;
91
+ device: Attributes;
92
+ context: Attributes;
93
+ }
94
+ /** Who a browser session is for, as your backend knows them. */
95
+ interface BrowserSessionInput {
96
+ /** The signed-in user, by your own id. */
97
+ user: SessionUser;
98
+ /** Omit for a user-only product: the session then has no account. */
99
+ account?: SessionAccount | undefined;
100
+ }
101
+ /** Return this to the browser: it is what `@dropby/browser`'s `auth` expects. */
102
+ interface BrowserSession {
103
+ sessionToken: SessionToken;
104
+ expiresAt: string;
105
+ }
106
+ /**
107
+ * Where an ask is: `draft` while you write it, `active` once published (users can
108
+ * answer it between its `startsAt` and `expiresAt`), `closed` after you close it.
109
+ */
110
+ type AskStatus = "draft" | "active" | "closed";
111
+ /** Which asks a list returns: every one not archived, those in one status, or the archived. */
112
+ type AskFilter = "all" | AskStatus | "archived";
113
+ /** How a list of asks is ordered: last changed, newest first, or most responses. */
114
+ type AskSort = "updated" | "newest" | "responses";
115
+ /** How many asks each filter holds, for tabs or badges. */
116
+ type AskCounts = Record<AskFilter, number>;
117
+ /** A choice in a choice question. `optionId` defaults to `option_1`, `option_2`, … in order. */
118
+ interface AskOptionInput {
119
+ /** Its id in the answers; lowercase snake case. */
120
+ optionId?: string | undefined;
121
+ /** The choice as the user reads it. */
122
+ label: string;
123
+ }
124
+ /**
125
+ * A question in an ask. `fieldId` and `optionId` are lowercase snake case and
126
+ * default to `field_1`, `field_2`, … and `option_1`, `option_2`, … in order.
127
+ */
128
+ type AskFieldInput = {
129
+ /** The kind of question. */
130
+ type: "single_choice";
131
+ /** Its id in the answers; defaults to `field_1`, `field_2`, … in order. */
132
+ fieldId?: string | undefined;
133
+ /** The question as the user reads it. */
134
+ label: string;
135
+ /** Whether it must be answered to submit. */
136
+ required: boolean;
137
+ /** The choices, 2 to 10. */
138
+ options: AskOptionInput[];
139
+ } | {
140
+ /** The kind of question. */
141
+ type: "multi_choice";
142
+ /** Its id in the answers; defaults to `field_1`, `field_2`, … in order. */
143
+ fieldId?: string | undefined;
144
+ /** The question as the user reads it. */
145
+ label: string;
146
+ /** Whether it must be answered to submit. */
147
+ required: boolean;
148
+ /** The choices, 2 to 10. */
149
+ options: AskOptionInput[];
150
+ /** How many choices can be picked, 1 to 10; all of them by default. */
151
+ maxSelections?: number | undefined;
152
+ } | {
153
+ /** The kind of question. */
154
+ type: "short_text";
155
+ /** Its id in the answers; defaults to `field_1`, `field_2`, … in order. */
156
+ fieldId?: string | undefined;
157
+ /** The question as the user reads it. */
158
+ label: string;
159
+ /** Whether it must be answered to submit. */
160
+ required: boolean;
161
+ /** Hint text shown in the empty box. */
162
+ placeholder?: string | undefined;
163
+ /**
164
+ * The longest answer: up to 240 characters for short text, 2000 for long;
165
+ * the most allowed by default.
166
+ */
167
+ maxLength?: number | undefined;
168
+ } | {
169
+ /** The kind of question. */
170
+ type: "long_text";
171
+ /** Its id in the answers; defaults to `field_1`, `field_2`, … in order. */
172
+ fieldId?: string | undefined;
173
+ /** The question as the user reads it. */
174
+ label: string;
175
+ /** Whether it must be answered to submit. */
176
+ required: boolean;
177
+ /** Hint text shown in the empty box. */
178
+ placeholder?: string | undefined;
179
+ /**
180
+ * The longest answer: up to 240 characters for short text, 2000 for long;
181
+ * the most allowed by default.
182
+ */
183
+ maxLength?: number | undefined;
184
+ } | {
185
+ /** The kind of question. */
186
+ type: "rating";
187
+ /** Its id in the answers; defaults to `field_1`, `field_2`, … in order. */
188
+ fieldId?: string | undefined;
189
+ /** The question as the user reads it. */
190
+ label: string;
191
+ /** Whether it must be answered to submit. */
192
+ required: boolean;
193
+ /** The lowest rating, 0 or 1. */
194
+ min: 0 | 1;
195
+ /** The highest rating; always 10. */
196
+ max: 10;
197
+ /** What the lowest rating means, such as `not likely`. */
198
+ minLabel?: string | undefined;
199
+ /** What the highest rating means, such as `very likely`. */
200
+ maxLabel?: string | undefined;
201
+ };
202
+ /**
203
+ * Who an ask goes to, by your own ids. A user target without `accountId` matches
204
+ * the user in any account.
205
+ */
206
+ type AskTarget = {
207
+ type: "user";
208
+ id: string;
209
+ accountId?: string | undefined;
210
+ } | {
211
+ type: "account";
212
+ id: string;
213
+ };
214
+ /** How a targeting rule compares a field with its value. */
215
+ type TargetingOperator = "eq" | "neq" | "in" | "exists" | "contains" | "gt" | "gte" | "lt" | "lte";
216
+ /** `field` is `<user|account|device|context>.<key>`. */
217
+ type TargetingRule = {
218
+ all: TargetingRule[];
219
+ } | {
220
+ any: TargetingRule[];
221
+ } | {
222
+ not: TargetingRule;
223
+ } | {
224
+ field: string;
225
+ op: TargetingOperator;
226
+ value?: AttributeValue | AttributeValue[] | undefined;
227
+ };
228
+ /** An ask needs `targets`, a `targetingRule`, or both. */
229
+ interface AskInput {
230
+ /** The ask's title, up to 180 characters. */
231
+ title: string;
232
+ /** The questions, 1 to 8. */
233
+ fields: AskFieldInput[];
234
+ /** Up to 50 users or accounts it goes to. */
235
+ targets?: AskTarget[] | undefined;
236
+ /** A rule on user, account, device and context facts; users it matches get the ask. */
237
+ targetingRule?: TargetingRule | undefined;
238
+ /** Whether the user can dismiss it without answering; true by default. */
239
+ dismissible?: boolean | undefined;
240
+ /** When it starts showing, as an ISO 8601 time; now when omitted or null. */
241
+ startsAt?: string | null | undefined;
242
+ /** When it stops showing, as an ISO 8601 time; never when omitted or null. */
243
+ expiresAt?: string | null | undefined;
244
+ }
245
+ /** A choice in a choice question, with its id filled in. */
246
+ interface AskOption {
247
+ optionId: string;
248
+ label: string;
249
+ }
250
+ /** A question as the ask holds it: ids filled in, unset optional properties null. */
251
+ type AskField = {
252
+ type: "single_choice";
253
+ fieldId: string;
254
+ label: string;
255
+ required: boolean;
256
+ options: AskOption[];
257
+ } | {
258
+ type: "multi_choice";
259
+ fieldId: string;
260
+ label: string;
261
+ required: boolean;
262
+ options: AskOption[];
263
+ maxSelections: number;
264
+ } | {
265
+ type: "short_text";
266
+ fieldId: string;
267
+ label: string;
268
+ required: boolean;
269
+ placeholder: string | null;
270
+ maxLength: number;
271
+ } | {
272
+ type: "long_text";
273
+ fieldId: string;
274
+ label: string;
275
+ required: boolean;
276
+ placeholder: string | null;
277
+ maxLength: number;
278
+ } | {
279
+ type: "rating";
280
+ fieldId: string;
281
+ label: string;
282
+ required: boolean;
283
+ min: 0 | 1;
284
+ max: 10;
285
+ minLabel: string | null;
286
+ maxLabel: string | null;
287
+ };
288
+ /** A question or survey you put to some of your users, with its counts. */
289
+ interface Ask {
290
+ askId: AskId;
291
+ productId: ProductId;
292
+ env: Environment;
293
+ title: string;
294
+ status: AskStatus;
295
+ dismissible: boolean;
296
+ /** The questions; empty on a draft, whose questions are unfinished. */
297
+ fields: AskField[];
298
+ targetCount: number;
299
+ responseCount: number;
300
+ dismissedCount: number;
301
+ createdAt: string;
302
+ startsAt: string | null;
303
+ expiresAt: string | null;
304
+ updatedAt: string;
305
+ closedAt: string | null;
306
+ archivedAt: string | null;
307
+ }
308
+ /** A page of asks, with how many each filter holds. */
309
+ interface AskPage extends Page<Ask> {
310
+ counts: AskCounts;
311
+ }
312
+ /** One answer in a response: the field it answers and its value. */
313
+ interface AskAnswer {
314
+ fieldId: string;
315
+ /** Text, the chosen option ids, or a rating. */
316
+ value: string | string[] | number;
317
+ }
318
+ /** One user's answers to an ask, or their dismissal. */
319
+ interface AskResponse {
320
+ responseId: AskResponseId;
321
+ askId: AskId;
322
+ productId: ProductId;
323
+ env: Environment;
324
+ kind: "answered" | "dismissed";
325
+ user: UserReference;
326
+ account: AccountReference | null;
327
+ answers: AskAnswer[];
328
+ /** The page context the user had when they answered. */
329
+ context: Attributes;
330
+ createdAt: string;
331
+ }
332
+ /** How many answers chose one option. */
333
+ interface AskOptionCount {
334
+ optionId: string;
335
+ label: string;
336
+ count: number;
337
+ }
338
+ /** One user's written answer, from a text field's summary. */
339
+ interface AskTextSample {
340
+ responseId: AskResponseId;
341
+ user: UserReference;
342
+ account: AccountReference | null;
343
+ value: string;
344
+ createdAt: string;
345
+ }
346
+ /** Every response to one field, summarised. */
347
+ type AskFieldSummary = {
348
+ type: "single_choice";
349
+ fieldId: string;
350
+ label: string;
351
+ answerCount: number;
352
+ skippedCount: number;
353
+ options: AskOptionCount[];
354
+ } | {
355
+ type: "multi_choice";
356
+ fieldId: string;
357
+ label: string;
358
+ answerCount: number;
359
+ skippedCount: number;
360
+ selectionCount: number;
361
+ options: AskOptionCount[];
362
+ } | {
363
+ type: "rating";
364
+ fieldId: string;
365
+ label: string;
366
+ answerCount: number;
367
+ skippedCount: number;
368
+ average: number | null;
369
+ counts: {
370
+ value: number;
371
+ count: number;
372
+ }[];
373
+ } | {
374
+ type: "short_text";
375
+ fieldId: string;
376
+ label: string;
377
+ answerCount: number;
378
+ skippedCount: number;
379
+ samples: AskTextSample[];
380
+ } | {
381
+ type: "long_text";
382
+ fieldId: string;
383
+ label: string;
384
+ answerCount: number;
385
+ skippedCount: number;
386
+ samples: AskTextSample[];
387
+ };
388
+ /** An ask with every question's answers summarised. */
389
+ interface AskDetail {
390
+ ask: Ask;
391
+ /** Every question's answers, summarised, in question order. */
392
+ fieldSummaries: AskFieldSummary[];
393
+ }
394
+ /**
395
+ * Where an idea is on your board. Only `open`, `planned`, `building` and `done`
396
+ * can be public; `duplicate` ones were merged into another.
397
+ */
398
+ type IdeaStatus = "under_review" | "open" | "planned" | "building" | "done" | "not_planned" | "duplicate";
399
+ /** Whether other users can see an idea on the public board. */
400
+ type IdeaVisibility = "private" | "public";
401
+ /** Which ideas a list returns: every one not archived, those in one status, or the archived. */
402
+ type IdeaFilter = "all" | IdeaStatus | "archived";
403
+ /** How a list of ideas is ordered: most votes, or newest first. */
404
+ type IdeaSort = "votes" | "newest";
405
+ /** How many ideas each filter holds, for tabs or badges. */
406
+ type IdeaCounts = Record<IdeaFilter, number>;
407
+ /** An idea a user posted, or your team created, with its vote count. */
408
+ interface Idea {
409
+ ideaId: IdeaId;
410
+ productId: ProductId;
411
+ env: Environment;
412
+ status: IdeaStatus;
413
+ visibility: IdeaVisibility;
414
+ votingEnabled: boolean;
415
+ title: string;
416
+ description: string | null;
417
+ /** Your team's public reply, shown with the idea. */
418
+ teamResponse: {
419
+ text: string;
420
+ updatedAt: string;
421
+ } | null;
422
+ /** Set when the idea is a duplicate: the idea it was merged into. */
423
+ canonicalIdeaId: IdeaId | null;
424
+ voteCount: number;
425
+ /** How many ideas were merged directly into this one. */
426
+ duplicateCount: number;
427
+ /** Who posted it; null when your team created it. */
428
+ user: UserReference | null;
429
+ account: AccountReference | null;
430
+ createdAt: string;
431
+ updatedAt: string;
432
+ archivedAt: string | null;
433
+ }
434
+ /** A page of ideas, with how many each filter holds. */
435
+ interface IdeaPage extends Page<Idea> {
436
+ counts: IdeaCounts;
437
+ }
438
+ /** A user who voted for an idea, and when. */
439
+ interface IdeaVoter {
440
+ user: UserReference;
441
+ account: AccountReference | null;
442
+ votedAt: string;
443
+ }
444
+ /**
445
+ * An idea with what was first written, where it came from, its first voters and
446
+ * the ideas merged into it.
447
+ */
448
+ interface IdeaDetail {
449
+ idea: Idea;
450
+ /** The chat thread the idea was created from. */
451
+ sourceThreadId: ThreadId | null;
452
+ /** The context the user had when they posted it. */
453
+ contextSnapshot: ContextSnapshot | null;
454
+ /** What was first written, kept through later edits. */
455
+ original: {
456
+ title: string;
457
+ description: string | null;
458
+ };
459
+ canonicalIdea: Idea | null;
460
+ /** Newest vote first; more through `listVoters`. */
461
+ voters: Page<IdeaVoter>;
462
+ /** The ideas merged into this one, oldest first; more through `listDuplicates`. */
463
+ duplicates: Page<Idea>;
464
+ }
465
+ /** A new idea created by your team. */
466
+ interface IdeaInput {
467
+ /** Up to 180 characters. */
468
+ title: string;
469
+ /** Up to 5000 characters. */
470
+ description?: string | undefined;
471
+ /**
472
+ * `under_review` by default. A new idea starts private with voting off; `update`
473
+ * changes that.
474
+ */
475
+ status?: Exclude<IdeaStatus, "duplicate"> | undefined;
476
+ /** The chat thread the idea came from. */
477
+ sourceThreadId?: string | undefined;
478
+ }
479
+ /**
480
+ * Any of an idea's settings, applied together in a fixed order. An omitted field
481
+ * is unchanged; null clears `description` and `teamResponse`.
482
+ */
483
+ interface IdeaUpdate {
484
+ /** Up to 180 characters. */
485
+ title?: string | undefined;
486
+ /** Up to 5000 characters; null removes it. */
487
+ description?: string | null | undefined;
488
+ /**
489
+ * Moves the idea. A status other than `open`, `planned`, `building` or `done`
490
+ * also makes it private and turns voting off.
491
+ */
492
+ status?: Exclude<IdeaStatus, "duplicate"> | undefined;
493
+ /** Whether other users can see it on the public board; `public` needs one of those statuses. */
494
+ visibility?: IdeaVisibility | undefined;
495
+ /** Whether users can vote on it; only a public idea can take votes. */
496
+ votingEnabled?: boolean | undefined;
497
+ /** Your team's public reply; null removes it. */
498
+ teamResponse?: {
499
+ text: string;
500
+ } | null | undefined;
501
+ /** Archives it, or brings it back; archived ideas leave the `all` list. */
502
+ archived?: boolean | undefined;
503
+ }
504
+ /**
505
+ * Where a conversation is: `open` waiting on your team, `replied` waiting on the
506
+ * user, `closed` done until a new message reopens it.
507
+ */
508
+ type ChatThreadStatus = "open" | "replied" | "closed";
509
+ /**
510
+ * Which conversations a list returns: every one, those in one status, or those
511
+ * with messages your team has not read.
512
+ */
513
+ type ChatThreadFilter = "all" | "open" | "replied" | "closed" | "unread";
514
+ /** How many conversations each filter holds, for tabs or badges. */
515
+ type ChatThreadCounts = Record<ChatThreadFilter, number>;
516
+ /** The file types a chat message can carry. */
517
+ type ChatAttachmentContentType = "image/png" | "image/jpeg" | "image/webp" | "image/gif" | "application/pdf" | "text/plain" | "text/csv";
518
+ /** A file attached to a chat message. Download it with `chat.getAttachmentDownload`. */
519
+ interface ChatAttachment {
520
+ attachmentId: AttachmentId;
521
+ fileName: string;
522
+ contentType: ChatAttachmentContentType;
523
+ byteSize: number;
524
+ kind: "image" | "file";
525
+ }
526
+ /** One message in a conversation, from the user, your team or DropBy itself. */
527
+ interface ChatMessage {
528
+ messageId: MessageId;
529
+ threadId: ThreadId;
530
+ /** The message's position in its thread, from 1. */
531
+ sequence: number;
532
+ authorType: "user" | "team" | "system";
533
+ text: string;
534
+ /** The key the user's message was sent with; null on team and system messages. */
535
+ clientMessageId: string | null;
536
+ /** Who on your team wrote it; `id` is null for replies sent through the API. */
537
+ teamMember: {
538
+ id: TeamMemberId | null;
539
+ name: string | null;
540
+ } | null;
541
+ attachments: ChatAttachment[];
542
+ createdAt: string;
543
+ }
544
+ /** How far the user has read your team's replies. */
545
+ interface ChatUserSeen {
546
+ lastSeenAt: string | null;
547
+ lastSeenTeamMessageId: MessageId | null;
548
+ unreadTeamMessageCount: number;
549
+ }
550
+ /** How far your team has read the user's messages. */
551
+ interface ChatTeamSeen {
552
+ lastSeenAt: string | null;
553
+ lastSeenUserMessageId: MessageId | null;
554
+ unreadUserMessageCount: number;
555
+ }
556
+ /** A conversation. The same shape from every method; its messages page separately. */
557
+ interface ChatThread {
558
+ threadId: ThreadId;
559
+ productId: ProductId;
560
+ env: Environment;
561
+ user: UserReference;
562
+ account: AccountReference | null;
563
+ status: ChatThreadStatus;
564
+ userSeen: ChatUserSeen;
565
+ teamSeen: ChatTeamSeen;
566
+ messageCount: number;
567
+ lastMessagePreview: string;
568
+ lastAuthorType: ChatMessage["authorType"];
569
+ createdAt: string;
570
+ updatedAt: string;
571
+ }
572
+ /** A page of conversations, with how many each filter holds. */
573
+ interface ChatThreadPage extends Page<ChatThread> {
574
+ counts: ChatThreadCounts;
575
+ }
576
+ /** A conversation with its newest messages. */
577
+ interface ChatThreadDetail {
578
+ thread: ChatThread;
579
+ /** The newest messages; pages run back from them, each oldest first. */
580
+ messages: Page<ChatMessage>;
581
+ /** The context the user had when they started the thread. */
582
+ contextSnapshot: ContextSnapshot | null;
583
+ }
584
+ /** A conversation your backend starts on a user's behalf, with its first message. */
585
+ interface ChatThreadInput {
586
+ /** The user the conversation is with, by your own id. */
587
+ user: SessionUser;
588
+ /** The account the conversation belongs to. */
589
+ account?: SessionAccount | undefined;
590
+ /** The first message, as the user's, 1 to 5000 characters. */
591
+ message: {
592
+ text: string;
593
+ };
594
+ }
595
+ /** A reply from your team. */
596
+ interface ChatReplyInput {
597
+ /** The reply, 1 to 5000 characters. */
598
+ text: string;
599
+ /** The name shown as the reply's author. */
600
+ authorName?: string | undefined;
601
+ }
602
+ /** `replied` is set by a reply; `open` reopens a replied or closed thread. */
603
+ interface ChatThreadUpdate {
604
+ /** `closed` closes the conversation; `open` reopens it. */
605
+ status?: "open" | "closed" | undefined;
606
+ }
607
+ /**
608
+ * Who to resolve feature flags for. Flag rules on `context` or `device` see
609
+ * those fields as missing here.
610
+ */
611
+ interface ConfigEvaluationInput {
612
+ /** Omit to evaluate without per-user overrides. */
613
+ user?: SessionUser | undefined;
614
+ /** Omit to evaluate without per-account overrides. */
615
+ account?: SessionAccount | undefined;
616
+ }
617
+ /**
618
+ * Every feature flag resolved for one user and account, and the configuration
619
+ * version it came from.
620
+ */
621
+ interface EvaluatedConfig {
622
+ configVersion: number;
623
+ config: Record<string, string | number | boolean>;
624
+ }
625
+ /** Options for `createDropByServer`. */
626
+ interface DropByServerOptions {
627
+ /** Your product's secret key, `sk_live_…` or `sk_test_…`. Never send it to a browser. */
628
+ secretKey: string;
629
+ /** The API origin. Defaults to `https://api.dropby.chat`. */
630
+ apiBaseUrl?: string | undefined;
631
+ /** A `fetch` to use instead of the global one. */
632
+ fetch?: typeof fetch | undefined;
633
+ /** How long one attempt may take, body included. Defaults to 30000. */
634
+ timeoutMs?: number | undefined;
635
+ /**
636
+ * How many times a failed call is tried again (0 to 10, default 2): after a
637
+ * network error, a timeout, a 408, a 429 or a 5xx. Every call is safe to repeat.
638
+ */
639
+ maxRetries?: number | undefined;
640
+ }
641
+ /**
642
+ * Pages take the `nextCursor` of the page before; a cursor is valid only with the
643
+ * same filter and sort. `limit` is 1 to 100, 50 by default.
644
+ */
645
+ interface PageOptions {
646
+ /** How many items a page holds, 1 to 100; 50 by default. */
647
+ limit?: number | undefined;
648
+ /** The `nextCursor` of the page before; omit for the first page. */
649
+ cursor?: string | undefined;
650
+ }
651
+ /** Which page of asks to list, filtered and sorted. */
652
+ interface ListAsksOptions extends PageOptions {
653
+ /** Which asks: `all` by default. */
654
+ filter?: AskFilter | undefined;
655
+ /** Their order: `updated` by default. */
656
+ sort?: AskSort | undefined;
657
+ }
658
+ /** Which page of ideas to list, filtered and sorted. */
659
+ interface ListIdeasOptions extends PageOptions {
660
+ /** Which ideas: `all` by default. */
661
+ filter?: IdeaFilter | undefined;
662
+ /** Their order: `votes` by default. */
663
+ sort?: IdeaSort | undefined;
664
+ }
665
+ /** Which page of conversations to list, filtered. */
666
+ interface ListChatThreadsOptions extends PageOptions {
667
+ /** Which conversations: `all` by default. */
668
+ filter?: ChatThreadFilter | undefined;
669
+ }
670
+ /**
671
+ * For a create or reply: a repeat with the same key returns the original instead
672
+ * of posting again.
673
+ */
674
+ interface WriteOptions {
675
+ /**
676
+ * 1 to 128 visible ASCII characters, such as a UUID. One is generated for each
677
+ * call when none is given; pass your own when you retry a whole call yourself.
678
+ */
679
+ idempotencyKey?: string | undefined;
680
+ }
681
+ /** Browser sessions, minted by your backend for the users it has signed in. */
682
+ interface DropByBrowserSessionsClient {
683
+ /** Mints a short-lived browser session for a user your backend has authenticated. */
684
+ create(input: BrowserSessionInput): Promise<{
685
+ session: BrowserSession;
686
+ }>;
687
+ }
688
+ /** Asks: questions and surveys you put to your users, and their answers. */
689
+ interface DropByAsksClient {
690
+ /** Creates an ask for the users it targets. */
691
+ create(input: AskInput, options?: WriteOptions): Promise<{
692
+ ask: Ask;
693
+ }>;
694
+ /** A page of asks, with how many each filter holds. */
695
+ list(options?: ListAsksOptions): Promise<AskPage>;
696
+ /** The ask with every question's answers summarised. */
697
+ get(askId: string): Promise<AskDetail>;
698
+ /** Newest first. */
699
+ listResponses(askId: string, options?: PageOptions): Promise<Page<AskResponse>>;
700
+ }
701
+ /** Ideas: your users' feature requests, their votes, and your team's replies. */
702
+ interface DropByIdeasClient {
703
+ /** A page of ideas, with how many each filter holds. */
704
+ list(options?: ListIdeasOptions): Promise<IdeaPage>;
705
+ /** The idea with its first page of voters and of duplicates. */
706
+ get(ideaId: string): Promise<IdeaDetail>;
707
+ /** Newest vote first. */
708
+ listVoters(ideaId: string, options?: PageOptions): Promise<Page<IdeaVoter>>;
709
+ /** The ideas merged into this one, oldest first. */
710
+ listDuplicates(ideaId: string, options?: PageOptions): Promise<Page<Idea>>;
711
+ /** Creates an idea as your team. */
712
+ create(input: IdeaInput, options?: WriteOptions): Promise<{
713
+ idea: Idea;
714
+ }>;
715
+ /** Changes any of the idea's settings in one step; repeating it changes nothing. */
716
+ update(ideaId: string, changes: IdeaUpdate): Promise<{
717
+ idea: Idea;
718
+ }>;
719
+ /**
720
+ * Marks `ideaId` a duplicate of `canonicalIdeaId`; returns both. Repeating it
721
+ * changes nothing.
722
+ */
723
+ merge(ideaId: string, input: {
724
+ canonicalIdeaId: string;
725
+ }): Promise<{
726
+ idea: Idea;
727
+ canonicalIdea: Idea;
728
+ }>;
729
+ }
730
+ /** Support chat: conversations with your users, and your team's replies. */
731
+ interface DropByChatClient {
732
+ /** A page of conversations, with how many each filter holds. */
733
+ list(options?: ListChatThreadsOptions): Promise<ChatThreadPage>;
734
+ /** The thread with its newest messages. */
735
+ get(threadId: string): Promise<ChatThreadDetail>;
736
+ /** Pages run from the newest messages back; each page reads oldest first. */
737
+ listMessages(threadId: string, options?: PageOptions): Promise<Page<ChatMessage>>;
738
+ /** Starts a conversation on behalf of a user. */
739
+ create(input: ChatThreadInput, options?: WriteOptions): Promise<{
740
+ thread: ChatThread;
741
+ message: ChatMessage;
742
+ }>;
743
+ /** Replies as your team. */
744
+ reply(threadId: string, input: ChatReplyInput, options?: WriteOptions): Promise<{
745
+ thread: ChatThread;
746
+ message: ChatMessage;
747
+ }>;
748
+ /** Closes a conversation, or opens it again. */
749
+ update(threadId: string, changes: ChatThreadUpdate): Promise<{
750
+ thread: ChatThread;
751
+ }>;
752
+ /** A short-lived download link for a message attachment. */
753
+ getAttachmentDownload(attachmentId: string): Promise<{
754
+ download: {
755
+ url: string;
756
+ expiresAt: string;
757
+ };
758
+ }>;
759
+ }
760
+ /** Feature flags, resolved on your server. */
761
+ interface DropByConfigClient {
762
+ /** Resolves every feature flag for a user and account. */
763
+ evaluate(input: ConfigEvaluationInput): Promise<EvaluatedConfig>;
764
+ }
765
+ /**
766
+ * A client for DropBy's server API, from `createDropByServer`. Calls retry network
767
+ * errors, timeouts, 408, 429 and 5xx up to `maxRetries` times, and reject with a
768
+ * `DropByError`; a `Retry-After` over 10 seconds rejects at once.
769
+ */
770
+ interface DropByServer {
771
+ /** Asks: questions and surveys, and their answers. */
772
+ readonly asks: DropByAsksClient;
773
+ /** Browser sessions for the users your backend has signed in. */
774
+ readonly browserSessions: DropByBrowserSessionsClient;
775
+ /** Support chat: conversations and your team's replies. */
776
+ readonly chat: DropByChatClient;
777
+ /** Feature flags, resolved on your server. */
778
+ readonly config: DropByConfigClient;
779
+ /** Ideas: feature requests, votes and your team's replies. */
780
+ readonly ideas: DropByIdeasClient;
781
+ }
782
+ /** A client for your backend, holding your secret key. Never send it to a browser. */
783
+ export declare function createDropByServer(options: DropByServerOptions): DropByServer;
784
+ /**
785
+ * What went wrong, to branch on: the API's codes, and those the client raises
786
+ * itself (`invalid_input`, `network_error`, `timeout`, `invalid_response`,
787
+ * `request_failed`). Open to codes the API adds.
788
+ */
789
+ type DropByErrorCode = "bad_request" | "unauthorized" | "forbidden" | "not_found" | "conflict" | "idea_archived" | "idea_merged" | "idempotency_key_reused" | "rate_limited" | "unavailable" | "internal_error" | "request_failed" | "invalid_input" | "network_error" | "timeout" | "invalid_response" | (string & {});
790
+ /** What a `DropByError` carries besides its code and message. */
791
+ interface DropByErrorOptions {
792
+ /** The HTTP status; undefined when no response arrived. */
793
+ status?: number | undefined;
794
+ /** The seconds the API asked to wait before retrying, when it said. */
795
+ retryAfter?: number | undefined;
796
+ /** The error underneath, such as the failed `fetch`. */
797
+ cause?: unknown;
798
+ }
799
+ /**
800
+ * Every error the client throws. Branch on `code`; `status` is the HTTP status
801
+ * when a response arrived, and `retryAfter` the wait the API asked for.
802
+ */
803
+ export declare class DropByError extends Error {
804
+ /** Always `"DropByError"`. */
805
+ readonly name = "DropByError";
806
+ /** What went wrong, to branch on. */
807
+ readonly code: DropByErrorCode;
808
+ /** The HTTP status; undefined when no response arrived. */
809
+ readonly status: number | undefined;
810
+ /** The seconds the API asked to wait before retrying, when it said. */
811
+ readonly retryAfter: number | undefined;
812
+ constructor(code: DropByErrorCode, message: string, options?: DropByErrorOptions);
813
+ }
814
+ /**
815
+ * The user an identity proof vouches for. Only these fields go into the proof,
816
+ * which the browser can read.
817
+ */
818
+ interface IdentityProofUser {
819
+ /** Your own id for the user, 1 to 256 characters. */
820
+ id: string;
821
+ /** Shown to your team. */
822
+ name?: string | undefined;
823
+ /** Shown to your team. */
824
+ email?: string | undefined;
825
+ /** Saved on the user, for audiences. */
826
+ attributes?: Attributes | undefined;
827
+ }
828
+ /**
829
+ * The account an identity proof vouches for. Only these fields go into the
830
+ * proof, which the browser can read.
831
+ */
832
+ interface IdentityProofAccount {
833
+ /** Your own id for the account, 1 to 256 characters. */
834
+ id: string;
835
+ /** Shown to your team. */
836
+ name?: string | undefined;
837
+ /** The account's web domain. */
838
+ domain?: string | undefined;
839
+ /** Saved on the account, for audiences. */
840
+ attributes?: Attributes | undefined;
841
+ }
842
+ /**
843
+ * What `createIdentityProof` signs: the browser key it is for, the environment,
844
+ * and who the user is. `secret` is the browser key's identity secret; keep it on
845
+ * your server.
846
+ */
847
+ interface CreateIdentityProofOptions {
848
+ /** The browser key's identity secret, 64 lowercase hex characters, from the dashboard. */
849
+ secret: string;
850
+ /** `prj_…`, as the dashboard lists it. */
851
+ productId: string;
852
+ /** `pkey_…`, the browser key the proof is for. */
853
+ publicKeyId: string;
854
+ /** The environment the browser key belongs to. */
855
+ env: Environment;
856
+ /** Who the proof vouches for. */
857
+ user: IdentityProofUser;
858
+ /** Omit for a user-only product: the session then has no account. */
859
+ account?: IdentityProofAccount | undefined;
860
+ /** 1 to 900 seconds; defaults to 900. */
861
+ ttlSeconds?: number | undefined;
862
+ }
863
+ /**
864
+ * Signs the identity of an end user your backend has authenticated, for your
865
+ * session endpoint to return to the browser. Never expose the secret.
866
+ */
867
+ export declare function createIdentityProof(options: CreateIdentityProofOptions): Promise<string>;
868
+ /** The environment variables `identityProofOptionsFromEnv` reads. */
869
+ type IdentityProofEnvVariable = "DROPBY_PRODUCT_ID" | "DROPBY_PUBLIC_KEY_ID" | "DROPBY_ENV" | "DROPBY_IDENTITY_SECRET";
870
+ /**
871
+ * The identity proof settings read from the environment, ready to spread into
872
+ * `createIdentityProof`.
873
+ */
874
+ type IdentityProofEnvOptions = Pick<CreateIdentityProofOptions, "secret" | "productId" | "publicKeyId" | "env">;
875
+ /**
876
+ * Reads the identity proof settings the dashboard lists: `DROPBY_PRODUCT_ID`,
877
+ * `DROPBY_PUBLIC_KEY_ID`, `DROPBY_ENV` and `DROPBY_IDENTITY_SECRET`. Pass
878
+ * `process.env`, or a Workers `env`. Throws naming the first missing or invalid
879
+ * variable; the message never includes a value, since one is the secret.
880
+ */
881
+ export declare function identityProofOptionsFromEnv(vars: Readonly<Partial<Record<IdentityProofEnvVariable, unknown>>>): IdentityProofEnvOptions;
882
+ export type { AccountId, AccountReference, Ask, AskAnswer, AskCounts, AskDetail, AskField, AskFieldInput, AskFieldSummary, AskFilter, AskId, AskInput, AskOption, AskOptionCount, AskOptionInput, AskPage, AskResponse, AskResponseId, AskSort, AskStatus, AskTarget, AskTextSample, AttachmentId, AttributeValue, Attributes, BrowserSession, BrowserSessionInput, ChatAttachment, ChatAttachmentContentType, ChatMessage, ChatReplyInput, ChatTeamSeen, ChatThread, ChatThreadCounts, ChatThreadDetail, ChatThreadFilter, ChatThreadInput, ChatThreadPage, ChatThreadStatus, ChatThreadUpdate, ChatUserSeen, ConfigEvaluationInput, ContextSnapshot, CreateIdentityProofOptions, DropByErrorCode, DropByErrorOptions, DropByServer, DropByServerOptions, Environment, EvaluatedConfig, Idea, IdeaCounts, IdeaDetail, IdeaFilter, IdeaId, IdeaInput, IdeaPage, IdeaSort, IdeaStatus, IdeaUpdate, IdeaVisibility, IdeaVoter, IdentityProofAccount, IdentityProofEnvOptions, IdentityProofEnvVariable, IdentityProofUser, ListAsksOptions, ListChatThreadsOptions, ListIdeasOptions, MessageId, Page, PageOptions, ProductId, PublicKeyId, SessionAccount, SessionToken, SessionUser, TargetingOperator, TargetingRule, TeamMemberId, ThreadId, UserId, UserReference, WriteOptions };