ab-ecosystem-cpass 1.0.0 → 1.0.6
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/README.md +121 -21
- package/dist/client.d.ts +38 -0
- package/dist/client.js +49 -5
- package/dist/client.js.map +1 -1
- package/dist/http.d.ts +15 -0
- package/dist/http.js +21 -1
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts +11 -0
- package/dist/index.js +24 -1
- package/dist/index.js.map +1 -1
- package/dist/internal/bytes.d.ts +38 -0
- package/dist/internal/bytes.js +84 -0
- package/dist/internal/bytes.js.map +1 -0
- package/dist/internal/device.d.ts +24 -0
- package/dist/internal/device.js +91 -0
- package/dist/internal/device.js.map +1 -0
- package/dist/internal/md5.d.ts +4 -0
- package/dist/internal/md5.js +109 -0
- package/dist/internal/md5.js.map +1 -0
- package/dist/internal/receiver-file.d.ts +106 -0
- package/dist/internal/receiver-file.js +128 -0
- package/dist/internal/receiver-file.js.map +1 -0
- package/dist/realtime/client.d.ts +85 -0
- package/dist/realtime/client.js +126 -0
- package/dist/realtime/client.js.map +1 -0
- package/dist/realtime/events.d.ts +147 -0
- package/dist/realtime/events.js +3 -0
- package/dist/realtime/events.js.map +1 -0
- package/dist/realtime/inbox.d.ts +173 -0
- package/dist/realtime/inbox.js +263 -0
- package/dist/realtime/inbox.js.map +1 -0
- package/dist/realtime/index.d.ts +16 -0
- package/dist/realtime/index.js +37 -0
- package/dist/realtime/index.js.map +1 -0
- package/dist/resources/audience/contacts.d.ts +19 -3
- package/dist/resources/audience/contacts.js +19 -3
- package/dist/resources/audience/contacts.js.map +1 -1
- package/dist/resources/audience/inbox-media.d.ts +92 -0
- package/dist/resources/audience/inbox-media.js +127 -0
- package/dist/resources/audience/inbox-media.js.map +1 -0
- package/dist/resources/audience/notifications.d.ts +171 -0
- package/dist/resources/audience/notifications.js +215 -0
- package/dist/resources/audience/notifications.js.map +1 -0
- package/dist/resources/audience/scheduled-messages.d.ts +234 -0
- package/dist/resources/audience/scheduled-messages.js +259 -0
- package/dist/resources/audience/scheduled-messages.js.map +1 -0
- package/dist/resources/campaign-audience.d.ts +132 -0
- package/dist/resources/campaign-audience.js +224 -0
- package/dist/resources/campaign-audience.js.map +1 -0
- package/dist/resources/campaign-report-exports.d.ts +14 -0
- package/dist/resources/campaign-report-exports.js +28 -0
- package/dist/resources/campaign-report-exports.js.map +1 -0
- package/dist/resources/campaign-reports.d.ts +15 -0
- package/dist/resources/campaign-reports.js +25 -0
- package/dist/resources/campaign-reports.js.map +1 -0
- package/dist/resources/campaigns.d.ts +239 -0
- package/dist/resources/campaigns.js +300 -0
- package/dist/resources/campaigns.js.map +1 -0
- package/dist/types/audience.d.ts +93 -1
- package/dist/types/campaign.d.ts +229 -0
- package/dist/types/campaign.js +3 -0
- package/dist/types/campaign.js.map +1 -0
- package/dist/types/contact-filter.d.ts +3 -2
- package/dist/types/contact-filter.js +3 -2
- package/dist/types/contact-filter.js.map +1 -1
- package/dist/types/inbox.d.ts +391 -0
- package/dist/types/inbox.js +16 -0
- package/dist/types/inbox.js.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/scheduled-message.d.ts +221 -0
- package/dist/types/scheduled-message.js +16 -0
- package/dist/types/scheduled-message.js.map +1 -0
- package/docs/audience/contacts.md +34 -4
- package/docs/audience/notifications.md +263 -0
- package/docs/audience/scheduled-messages.md +557 -0
- package/docs/campaign/campaigns.md +489 -0
- package/docs/contact-filter.md +2 -1
- package/docs/inbox/chats.md +356 -0
- package/docs/inbox/connection.md +171 -0
- package/docs/inbox/media.md +202 -0
- package/docs/inbox/messages.md +338 -0
- package/docs/inbox/referrals.md +72 -0
- package/docs/inbox/sessions.md +74 -0
- package/package.json +28 -2
package/dist/types/audience.d.ts
CHANGED
|
@@ -97,6 +97,12 @@ export interface Contact {
|
|
|
97
97
|
*/
|
|
98
98
|
export interface CreateContactInput {
|
|
99
99
|
name?: Partial<ContactName>;
|
|
100
|
+
/**
|
|
101
|
+
* Creates the contact's WhatsApp identity with it, and writes its id to
|
|
102
|
+
* `profile.whatsapp`. Any shape is accepted -- `+91 98765 43210` -- and stored
|
|
103
|
+
* as digits only, which is the form an inbound message carries. Create-only.
|
|
104
|
+
*/
|
|
105
|
+
whatsapp?: string;
|
|
100
106
|
order?: string;
|
|
101
107
|
/** Contact tag ids. Default `[]`. */
|
|
102
108
|
tags?: ObjectId[];
|
|
@@ -115,7 +121,11 @@ export interface CreateContactInput {
|
|
|
115
121
|
blocked?: Partial<ContactBlocked>;
|
|
116
122
|
};
|
|
117
123
|
}
|
|
118
|
-
|
|
124
|
+
/**
|
|
125
|
+
* `whatsapp` is absent: changing a channel identity is a write to the profile
|
|
126
|
+
* collection, which a contact patch cannot express.
|
|
127
|
+
*/
|
|
128
|
+
export type UpdateContactInput = Partial<Omit<CreateContactInput, 'whatsapp'>>;
|
|
119
129
|
/**
|
|
120
130
|
* `search` matches the first and last name, plus the name and identifier of
|
|
121
131
|
* every channel identity. `segment` names a saved filter; `filter` carries
|
|
@@ -510,3 +520,85 @@ export interface WebhookEnvelope {
|
|
|
510
520
|
createdAt: IsoDate;
|
|
511
521
|
data: unknown;
|
|
512
522
|
}
|
|
523
|
+
/**
|
|
524
|
+
* Where a push notification can be delivered.
|
|
525
|
+
*
|
|
526
|
+
* It decides which half of the FCM payload the send path fills in -- `webpush`
|
|
527
|
+
* for a browser, `android`/`apns` for an app -- and it is the one thing about a
|
|
528
|
+
* device that cannot be inferred from its token. A registration token is an
|
|
529
|
+
* opaque string identifying a browser or app *instance*; nothing in it says what
|
|
530
|
+
* kind of thing that instance is.
|
|
531
|
+
*/
|
|
532
|
+
export type DevicePlatform = 'web' | 'android' | 'ios';
|
|
533
|
+
/**
|
|
534
|
+
* A subscribed device, as it reads back.
|
|
535
|
+
*
|
|
536
|
+
* The registration token is **never** returned. It is a send credential --
|
|
537
|
+
* anything holding one can push to that browser through the agency's Firebase
|
|
538
|
+
* project -- and the list exists so a user can recognise and revoke their own
|
|
539
|
+
* devices, which needs the label and the last-seen time and nothing more.
|
|
540
|
+
*/
|
|
541
|
+
export interface Device {
|
|
542
|
+
id: ObjectId;
|
|
543
|
+
platform: DevicePlatform;
|
|
544
|
+
/** Whatever `device_label` was sent on registration; `''` when none was. */
|
|
545
|
+
label: string;
|
|
546
|
+
/** The reseller frontend it registered from; `null` for the white-label one. */
|
|
547
|
+
clientId: string | null;
|
|
548
|
+
/**
|
|
549
|
+
* Last time a notification to this device succeeded, or it re-subscribed.
|
|
550
|
+
*
|
|
551
|
+
* The only signal that a device is still real: FCM does not revoke a token
|
|
552
|
+
* when an app is uninstalled or a browser's site data is cleared, it simply
|
|
553
|
+
* stops delivering to it. A device unseen for 60 days is pruned on that basis,
|
|
554
|
+
* which is another reason to call {@link Notifications.subscribe} on every app
|
|
555
|
+
* load rather than once.
|
|
556
|
+
*/
|
|
557
|
+
lastSeenAt: IsoDate;
|
|
558
|
+
createdAt: IsoDate;
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* What `notifications.subscribe()` takes. Mirrors the wire body field for field.
|
|
562
|
+
*
|
|
563
|
+
* There is deliberately no user field. The acting user comes from the verified
|
|
564
|
+
* token the client was constructed with; a body that could name its own user
|
|
565
|
+
* would let any caller point someone else's notifications at their browser.
|
|
566
|
+
*/
|
|
567
|
+
export interface SubscribeNotificationsInput {
|
|
568
|
+
/**
|
|
569
|
+
* The FCM registration token for this browser or app instance, from
|
|
570
|
+
* `getToken()`. 20..4096 characters -- a sanity check rather than a format,
|
|
571
|
+
* since Google publishes no shape for these.
|
|
572
|
+
*/
|
|
573
|
+
token: string;
|
|
574
|
+
/**
|
|
575
|
+
* Defaults to `'web'` when the SDK can see a DOM, and is otherwise required:
|
|
576
|
+
* a React Native runtime has a `navigator` but no `document`, and guessing
|
|
577
|
+
* `'web'` there would send the wrong half of every payload.
|
|
578
|
+
*/
|
|
579
|
+
platform?: DevicePlatform;
|
|
580
|
+
/**
|
|
581
|
+
* What the user would recognise this device as, for the device list -- up to
|
|
582
|
+
* 200 characters. Left out, the SDK derives something like `Chrome on Windows`
|
|
583
|
+
* from the user agent when it is running in a browser. Cosmetic, never matched
|
|
584
|
+
* on.
|
|
585
|
+
*/
|
|
586
|
+
device_label?: string;
|
|
587
|
+
/**
|
|
588
|
+
* The reseller client this frontend belongs to (`tpc_…`), when there is one.
|
|
589
|
+
*
|
|
590
|
+
* Rarely needed: the client id the `CrmClient` already sends is verified and
|
|
591
|
+
* wins. Supplying a *different* one is refused with 403 rather than ignored.
|
|
592
|
+
* Omitted by the white-label frontend, which has no client.
|
|
593
|
+
*/
|
|
594
|
+
tpc_id?: string;
|
|
595
|
+
}
|
|
596
|
+
/**
|
|
597
|
+
* `page` and `rows` only.
|
|
598
|
+
*
|
|
599
|
+
* The endpoint's schema accepts `search` because it shares the common list
|
|
600
|
+
* query, but the service does not apply it -- a device list is one person's few
|
|
601
|
+
* rows, so there is nothing to search. It is left out here rather than accepted
|
|
602
|
+
* and silently dropped.
|
|
603
|
+
*/
|
|
604
|
+
export type ListDevicesQuery = Pick<ListQuery, 'page' | 'rows'>;
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Campaign shapes. Declared here rather than imported from `@crm/contracts` so
|
|
3
|
+
* the published package has no private dependencies; they are kept in step with
|
|
4
|
+
* the zod schemas in `packages/contracts/src/campaign/`.
|
|
5
|
+
*/
|
|
6
|
+
import type { IsoDate, JsonObject } from './common';
|
|
7
|
+
import type { ContactFilterEntry } from './contact-filter';
|
|
8
|
+
export type CampaignStatus = 'pending' | 'processing' | 'completed' | 'failed' | 'cancelled';
|
|
9
|
+
/** What the campaign charges for. `payment` is the collect-a-payment flow. */
|
|
10
|
+
export type CampaignType = 'general' | 'payment';
|
|
11
|
+
export type CampaignTrigger = 'immediate' | 'schedule';
|
|
12
|
+
export type CampaignRepeatUnit = 'minutes' | 'hours' | 'days' | 'weeks' | 'months';
|
|
13
|
+
export interface CampaignRepeat {
|
|
14
|
+
every: number;
|
|
15
|
+
unit: CampaignRepeatUnit;
|
|
16
|
+
/** Inclusive: the last occurrence is the final one at or before this moment. */
|
|
17
|
+
until?: IsoDate;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* A bulk recipient list held in an uploaded file.
|
|
21
|
+
*
|
|
22
|
+
* This is what `campaigns.createBulk()` produces, and it is the only audience
|
|
23
|
+
* mode whose contents are not in the campaign document: the numbers live in an
|
|
24
|
+
* encrypted file and the campaign holds a pointer to it.
|
|
25
|
+
*/
|
|
26
|
+
export interface CampaignNumbersFilter {
|
|
27
|
+
/**
|
|
28
|
+
* HTTPS URL of the encrypted receiver file. Must be a public host -- the
|
|
29
|
+
* service that sends the campaign fetches it.
|
|
30
|
+
*/
|
|
31
|
+
numbers: string;
|
|
32
|
+
/**
|
|
33
|
+
* The secret the file was encrypted under, 32-128 hex characters.
|
|
34
|
+
*
|
|
35
|
+
* Named `hash` for historical reasons; it is a key, not a digest. Whatever
|
|
36
|
+
* reads the file derives the AES key from it. Treat it as a credential: anyone
|
|
37
|
+
* holding this and the URL can read the recipient list.
|
|
38
|
+
*/
|
|
39
|
+
hash: string;
|
|
40
|
+
}
|
|
41
|
+
/** Re-target by what happened to a previous campaign's messages. */
|
|
42
|
+
export interface CampaignRetargetStatusFilter {
|
|
43
|
+
type: 'status';
|
|
44
|
+
/** The campaign to re-target. */
|
|
45
|
+
cid: string;
|
|
46
|
+
/** Its numeric message id. A number, not a string. */
|
|
47
|
+
cmid: number;
|
|
48
|
+
status: 'all' | 'sent' | 'delivered' | 'read' | 'replied' | 'failed';
|
|
49
|
+
delivered?: boolean | null;
|
|
50
|
+
read?: boolean | null;
|
|
51
|
+
replied?: boolean | null;
|
|
52
|
+
/** Hours within which a reply counts. */
|
|
53
|
+
replied_in?: number | null;
|
|
54
|
+
reply_type?: string | null;
|
|
55
|
+
reply?: string[] | null;
|
|
56
|
+
}
|
|
57
|
+
/** Re-target an explicit set of previous recipients. */
|
|
58
|
+
export interface CampaignRetargetSelectionFilter {
|
|
59
|
+
type: 'selection';
|
|
60
|
+
records: string[];
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* One entry in a campaign's `filters`.
|
|
64
|
+
*
|
|
65
|
+
* The audience is one field with four modes, and the mode is decided by the
|
|
66
|
+
* **shape of the array** rather than by a selector:
|
|
67
|
+
*
|
|
68
|
+
* | `filters` | Audience |
|
|
69
|
+
* |---|---|
|
|
70
|
+
* | `[]` | every contact in the account |
|
|
71
|
+
* | `ContactFilterEntry[]` | a segment, built from contact conditions |
|
|
72
|
+
* | `[{numbers, hash}]` | a bulk list from an uploaded file |
|
|
73
|
+
* | `[{type: 'status' \| 'selection', …}]` | re-target of an earlier campaign |
|
|
74
|
+
*
|
|
75
|
+
* The modes cannot be mixed, and the three non-segment modes take exactly one
|
|
76
|
+
* entry -- everything downstream reads `filters[0]` and nothing else. The server
|
|
77
|
+
* rejects a mixture rather than guessing.
|
|
78
|
+
*/
|
|
79
|
+
export type CampaignFilter = CampaignNumbersFilter | CampaignRetargetStatusFilter | CampaignRetargetSelectionFilter | ContactFilterEntry;
|
|
80
|
+
/** Which of the four modes a `filters` array expresses. */
|
|
81
|
+
export type CampaignAudienceKind = 'all' | 'segment' | 'numbers' | 'retarget';
|
|
82
|
+
export interface CampaignMessage {
|
|
83
|
+
id?: string | number;
|
|
84
|
+
channel: {
|
|
85
|
+
id: string;
|
|
86
|
+
version?: string;
|
|
87
|
+
category?: string;
|
|
88
|
+
};
|
|
89
|
+
category?: string;
|
|
90
|
+
/** The provider payload. Shape is per channel type, so it is left open. */
|
|
91
|
+
message: JsonObject;
|
|
92
|
+
/** Save a reply to a contact field. */
|
|
93
|
+
replyStatus?: {
|
|
94
|
+
save: boolean;
|
|
95
|
+
fieldId: string;
|
|
96
|
+
};
|
|
97
|
+
polls?: string[];
|
|
98
|
+
/** Anything else the panel put here is carried through. */
|
|
99
|
+
[key: string]: unknown;
|
|
100
|
+
}
|
|
101
|
+
/** Who launched a campaign and from where. Stamped by the server; never sent. */
|
|
102
|
+
export interface CampaignTriggerInfo {
|
|
103
|
+
userIp?: string;
|
|
104
|
+
userType?: string;
|
|
105
|
+
psuid?: string;
|
|
106
|
+
userRefId?: string;
|
|
107
|
+
[key: string]: unknown;
|
|
108
|
+
}
|
|
109
|
+
export interface Campaign {
|
|
110
|
+
id: string;
|
|
111
|
+
version: string;
|
|
112
|
+
crmVersion: string;
|
|
113
|
+
name: string;
|
|
114
|
+
/**
|
|
115
|
+
* The dispatch route, as the sending service understands it -- `general`,
|
|
116
|
+
* `bulk_campaign`, `retarget`, and others. Distinct from `campaignType`.
|
|
117
|
+
*/
|
|
118
|
+
type: string;
|
|
119
|
+
campaignType: CampaignType;
|
|
120
|
+
trigger: CampaignTrigger;
|
|
121
|
+
triggerInfo: CampaignTriggerInfo;
|
|
122
|
+
channelType: string;
|
|
123
|
+
messagingPattern: string;
|
|
124
|
+
status: CampaignStatus;
|
|
125
|
+
filters: CampaignFilter[];
|
|
126
|
+
messages: CampaignMessage[];
|
|
127
|
+
showMessageInPanel: boolean;
|
|
128
|
+
isRepeating: boolean;
|
|
129
|
+
repeat?: CampaignRepeat;
|
|
130
|
+
parentBroadcastId?: string;
|
|
131
|
+
scheduleId?: string;
|
|
132
|
+
hidden: boolean;
|
|
133
|
+
scheduledAt?: IsoDate;
|
|
134
|
+
processedAt?: IsoDate;
|
|
135
|
+
completedAt?: IsoDate;
|
|
136
|
+
/**
|
|
137
|
+
* Recipients resolved at send time, not at creation.
|
|
138
|
+
*
|
|
139
|
+
* `0` until the campaign is processed. The audience is a stored query -- even a
|
|
140
|
+
* bulk list is a file the sender reads later -- so a scheduled campaign's final
|
|
141
|
+
* count can differ from what was shown when it was built.
|
|
142
|
+
*/
|
|
143
|
+
receivers: number;
|
|
144
|
+
totalMessages: number;
|
|
145
|
+
error?: string;
|
|
146
|
+
metaInfo: JsonObject[];
|
|
147
|
+
createdAt: IsoDate;
|
|
148
|
+
updatedAt: IsoDate;
|
|
149
|
+
}
|
|
150
|
+
export interface CreateCampaignInput {
|
|
151
|
+
name: string;
|
|
152
|
+
/** Defaults to `general`. `createBulk()` sets `bulk_campaign` itself. */
|
|
153
|
+
type?: string;
|
|
154
|
+
campaignType?: CampaignType;
|
|
155
|
+
trigger?: CampaignTrigger;
|
|
156
|
+
channelType?: string;
|
|
157
|
+
messagingPattern?: string;
|
|
158
|
+
/** The audience. `[]` means every contact. See {@link CampaignFilter}. */
|
|
159
|
+
filters?: CampaignFilter[];
|
|
160
|
+
messages: CampaignMessage[];
|
|
161
|
+
showMessageInPanel?: boolean;
|
|
162
|
+
isRepeating?: boolean;
|
|
163
|
+
repeat?: CampaignRepeat;
|
|
164
|
+
parentBroadcastId?: string;
|
|
165
|
+
hidden?: boolean;
|
|
166
|
+
/** Required when `trigger` is `schedule`. */
|
|
167
|
+
scheduledAt?: IsoDate;
|
|
168
|
+
}
|
|
169
|
+
export type UpdateCampaignInput = Partial<CreateCampaignInput>;
|
|
170
|
+
/**
|
|
171
|
+
* Declared as a type alias rather than an interface, and that is load-bearing:
|
|
172
|
+
* only an alias of an object literal gets TypeScript's implicit index signature,
|
|
173
|
+
* which is what lets it be passed as a request's query record.
|
|
174
|
+
*/
|
|
175
|
+
export type ListCampaignsQuery = {
|
|
176
|
+
limit: number;
|
|
177
|
+
cursor?: string;
|
|
178
|
+
status?: CampaignStatus;
|
|
179
|
+
campaignType?: CampaignType;
|
|
180
|
+
type?: string;
|
|
181
|
+
hidden?: boolean;
|
|
182
|
+
};
|
|
183
|
+
/** Delivery counts for one campaign. Every field is a running total. */
|
|
184
|
+
export interface CampaignMetrics {
|
|
185
|
+
queued: number;
|
|
186
|
+
sent: number;
|
|
187
|
+
delivered: number;
|
|
188
|
+
failed: number;
|
|
189
|
+
opened: number;
|
|
190
|
+
clicked: number;
|
|
191
|
+
unsubscribed: number;
|
|
192
|
+
}
|
|
193
|
+
export interface CampaignReport {
|
|
194
|
+
id: string;
|
|
195
|
+
campaignId: string;
|
|
196
|
+
metrics: CampaignMetrics;
|
|
197
|
+
/** When the metrics were last rolled up, which may lag the campaign. */
|
|
198
|
+
generatedAt: IsoDate;
|
|
199
|
+
createdAt: IsoDate;
|
|
200
|
+
updatedAt: IsoDate;
|
|
201
|
+
}
|
|
202
|
+
/** A report export shares the job lifecycle used across the platform. */
|
|
203
|
+
export type CampaignReportExportStatus = 'queued' | 'processing' | 'completed' | 'failed';
|
|
204
|
+
export interface CampaignReportExport {
|
|
205
|
+
id: string;
|
|
206
|
+
campaignId: string;
|
|
207
|
+
format: 'csv' | 'xlsx';
|
|
208
|
+
status: CampaignReportExportStatus;
|
|
209
|
+
rowCount: number;
|
|
210
|
+
/** Present once `status` is `completed`. Expires; see `expiresAt`. */
|
|
211
|
+
fileUrl?: string;
|
|
212
|
+
expiresAt?: IsoDate;
|
|
213
|
+
errorMessage?: string;
|
|
214
|
+
createdAt: IsoDate;
|
|
215
|
+
updatedAt: IsoDate;
|
|
216
|
+
}
|
|
217
|
+
export interface CreateCampaignReportExportInput {
|
|
218
|
+
campaignId: string;
|
|
219
|
+
/** Defaults to `csv`. */
|
|
220
|
+
format?: 'csv' | 'xlsx';
|
|
221
|
+
/** Narrows the rows by the period they fall in. */
|
|
222
|
+
from?: IsoDate;
|
|
223
|
+
to?: IsoDate;
|
|
224
|
+
}
|
|
225
|
+
/** A type alias, for the same reason as {@link ListCampaignsQuery}. */
|
|
226
|
+
export type GetCampaignReportQuery = {
|
|
227
|
+
from?: IsoDate;
|
|
228
|
+
to?: IsoDate;
|
|
229
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"campaign.js","sourceRoot":"","sources":["../../src/types/campaign.ts"],"names":[],"mappings":""}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The contact filter DSL.
|
|
3
3
|
*
|
|
4
|
-
* One vocabulary,
|
|
5
|
-
* `CrmTrigger`'s `filters`,
|
|
4
|
+
* One vocabulary, five callers: `GET /contacts?filter=`, a saved `Segment`, a
|
|
5
|
+
* `CrmTrigger`'s `filters`, an export's `config.filter`, and a scheduled
|
|
6
|
+
* message's `conditions`. Conditions are a
|
|
6
7
|
* flat list rather than a tree -- `and` binds tighter than `or`, so the list is
|
|
7
8
|
* split on every `or`, each run is `and`ed, and the runs are `or`ed together.
|
|
8
9
|
*/
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* The contact filter DSL.
|
|
4
4
|
*
|
|
5
|
-
* One vocabulary,
|
|
6
|
-
* `CrmTrigger`'s `filters`,
|
|
5
|
+
* One vocabulary, five callers: `GET /contacts?filter=`, a saved `Segment`, a
|
|
6
|
+
* `CrmTrigger`'s `filters`, an export's `config.filter`, and a scheduled
|
|
7
|
+
* message's `conditions`. Conditions are a
|
|
7
8
|
* flat list rather than a tree -- `and` binds tighter than `or`, so the list is
|
|
8
9
|
* split on every `or`, each run is `and`ed, and the runs are `or`ed together.
|
|
9
10
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contact-filter.js","sourceRoot":"","sources":["../../src/types/contact-filter.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"contact-filter.js","sourceRoot":"","sources":["../../src/types/contact-filter.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG"}
|