@drawbridge/drawbridge-utils 0.0.116 → 0.0.118
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/connections/index.cjs +293 -294
- package/dist/connections/index.d.cts +344 -316
- package/dist/connections/index.d.ts +344 -316
- package/dist/connections/index.js +293 -294
- package/dist/providers.cjs +3336 -0
- package/dist/providers.d.cts +317 -0
- package/dist/providers.d.ts +317 -0
- package/dist/providers.js +3291 -0
- package/package.json +6 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { authToken } from './oauth.cjs';
|
|
2
2
|
export { consentUrl, pkcePair } from './oauth.cjs';
|
|
3
|
-
import { channels } from '../pricing.cjs';
|
|
4
3
|
import { request } from '../http.cjs';
|
|
4
|
+
import { channels } from '../pricing.cjs';
|
|
5
5
|
import crypto, { createHmac, timingSafeEqual } from 'node:crypto';
|
|
6
6
|
import { safeRequest } from '../safe-http.cjs';
|
|
7
7
|
import '../plans.cjs';
|
|
@@ -775,231 +775,18 @@ var attentive = {
|
|
|
775
775
|
title : 'Attentive'
|
|
776
776
|
};
|
|
777
777
|
|
|
778
|
-
//
|
|
779
|
-
//
|
|
780
|
-
//
|
|
781
|
-
// A .js wrapper around otherwise untouched SVG so `node --test` can run against
|
|
782
|
-
// lib/ directly. A bare .svg import would need a bundler loader and force the
|
|
783
|
-
// tests onto dist/, which is a worse trade than one line of wrapper.
|
|
784
|
-
var icon$3 = `<svg width="500" height="500" viewBox="0 0 500 500" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
785
|
-
<rect width="500" height="500" fill="#BAEC5F"/>
|
|
786
|
-
<g clip-path="url(#clip0_2115_2832)">
|
|
787
|
-
<path d="M140.224 127.586L174.803 188.73V311.176L140 372.32L176.084 392.031L216.111 321.753V178.278L176.341 108L140.224 127.586Z" fill="#0D1314"/>
|
|
788
|
-
<path d="M360.001 127.523L323.693 108.282L284.948 178.498V321.596L322.923 391.749L359.393 372.79L326.224 311.52V188.73L360.001 127.523Z" fill="#0D1314"/>
|
|
789
|
-
</g>
|
|
790
|
-
<defs>
|
|
791
|
-
<clipPath id="clip0_2115_2832">
|
|
792
|
-
<rect width="220" height="284" fill="white" transform="translate(140 108)"/>
|
|
793
|
-
</clipPath>
|
|
794
|
-
</defs>
|
|
795
|
-
</svg>`;
|
|
796
|
-
|
|
797
|
-
// Drawbridge itself — the PRIVATE connection.
|
|
798
|
-
//
|
|
799
|
-
// Nobody connects this. There is no credential, no consent, and no card on the
|
|
800
|
-
// connections page. It exists because a workflow step points at a hook, and the
|
|
801
|
-
// six most common steps — sending an email, alerting a member, syncing a segment
|
|
802
|
-
// — are things Drawbridge does rather than things a vendor does.
|
|
778
|
+
// DRAWBRIDGE'S OWN HUBSPOT PORTAL, kept in step with account signups so the
|
|
779
|
+
// campaign a customer arrived on is on their contact record.
|
|
803
780
|
//
|
|
804
|
-
//
|
|
805
|
-
// a
|
|
806
|
-
//
|
|
807
|
-
//
|
|
781
|
+
// It sits beside lib/sendgrid.js and lib/twilio.js because it is the same kind
|
|
782
|
+
// of thing: a vendor client for an account DRAWBRIDGE holds, not one a merchant
|
|
783
|
+
// connects. It used to be a connection manifest of its own, which read as though
|
|
784
|
+
// HubSpot were a vendor a merchant could pick — it never was, and the slug is
|
|
785
|
+
// better kept free for the day a merchant-facing HubSpot connection exists.
|
|
808
786
|
//
|
|
809
|
-
//
|
|
810
|
-
//
|
|
811
|
-
// A private one is always present, in every deployment, for every organization —
|
|
812
|
-
// so it declares neither, and build() knows not to ask.
|
|
813
|
-
var drawbridge = {
|
|
814
|
-
auth : {
|
|
815
|
-
type : 'none'
|
|
816
|
-
},
|
|
817
|
-
content : {
|
|
818
|
-
confirm : 'This connection is part of Drawbridge and cannot be disconnected.',
|
|
819
|
-
description : [
|
|
820
|
-
'Drawbridge sends your notification email and SMS, keeps your segments in sync, and posts to your own endpoints. These are built in rather than connected, so there is nothing here to set up.'
|
|
821
|
-
],
|
|
822
|
-
excerpt : 'The steps Drawbridge runs itself.',
|
|
823
|
-
guide : [
|
|
824
|
-
'Nothing to do. These steps are available in every workflow builder.'
|
|
825
|
-
]
|
|
826
|
-
},
|
|
827
|
-
exclusive : false,
|
|
828
|
-
fields : [],
|
|
829
|
-
group : 'developer',
|
|
830
|
-
// EVERY BODY LIVES IN drawbridge-sync. Sending needs the provider clients, the
|
|
831
|
-
// suppression collection and the queues; segment sync needs the streams. A
|
|
832
|
-
// published package carrying those makes every consumer carry them, which is
|
|
833
|
-
// the reason `{}` exists as an answer.
|
|
834
|
-
hooks : {
|
|
835
|
-
auth : {
|
|
836
|
-
// Nothing to connect, revoke, probe or re-scope.
|
|
837
|
-
connect : false,
|
|
838
|
-
disconnect : false,
|
|
839
|
-
probe : false,
|
|
840
|
-
scopes : false,
|
|
841
|
-
token : false
|
|
842
|
-
},
|
|
843
|
-
commerce : false,
|
|
844
|
-
contacts : { remove : false, sync : false },
|
|
845
|
-
email : {
|
|
846
|
-
digest : {},
|
|
847
|
-
// To organization members. NEVER suppressed and never billed: an
|
|
848
|
-
// entrant's opt-out must not silence an alert to staff, and staff mail is
|
|
849
|
-
// not a metered send.
|
|
850
|
-
notify : {},
|
|
851
|
-
// To a lead. Suppression applies and the send is billed.
|
|
852
|
-
send : {}
|
|
853
|
-
},
|
|
854
|
-
inbound : false,
|
|
855
|
-
lifecycle : false,
|
|
856
|
-
resources : {
|
|
857
|
-
audiences : false,
|
|
858
|
-
prices : false,
|
|
859
|
-
products : false,
|
|
860
|
-
promotions : false
|
|
861
|
-
},
|
|
862
|
-
segment : { sync : {} },
|
|
863
|
-
sms : { send : {} },
|
|
864
|
-
webhook : false
|
|
865
|
-
},
|
|
866
|
-
icon: icon$3,
|
|
867
|
-
// PRIVATE: never in the catalog, always available to the builder.
|
|
868
|
-
private : true,
|
|
869
|
-
requires : [],
|
|
870
|
-
slug : 'drawbridge',
|
|
871
|
-
// Always on. There is no credential that could go bad and no configuration a
|
|
872
|
-
// merchant could leave half-finished.
|
|
873
|
-
status : () => 'active',
|
|
874
|
-
// DERIVED FROM drawbridge-api/lib/workflows.js, not invented. Every value
|
|
875
|
-
// below — trigger, billable, settings — is what that catalog and the workflow
|
|
876
|
-
// route already enforce today, because this replaces them rather than
|
|
877
|
-
// competing with them.
|
|
878
|
-
//
|
|
879
|
-
// NOT HERE, deliberately:
|
|
880
|
-
//
|
|
881
|
-
// step.segment.sync a SYSTEM step, dispatched by drawbridge-sync rather
|
|
882
|
-
// than offered in the builder. It fans out, so the shell
|
|
883
|
-
// opens its step document and the chunks close it.
|
|
884
|
-
steps : {
|
|
787
|
+
// The hooks are wired into the private `drawbridge` manifest's contacts slot;
|
|
788
|
+
// drawbridge-sync's user stream calls them by that name.
|
|
885
789
|
|
|
886
|
-
email : {
|
|
887
|
-
|
|
888
|
-
// SCHEDULE-TRIGGERED, not lead-triggered: it is offered under Daily,
|
|
889
|
-
// Weekly and Monthly. Those triggers had offered no steps at all, so a
|
|
890
|
-
// scheduled workflow was selectable and inert until this landed.
|
|
891
|
-
digest : () => ({
|
|
892
|
-
hook : 'email.digest',
|
|
893
|
-
key : 'Email — Digest',
|
|
894
|
-
queue : 'notification',
|
|
895
|
-
settings : {
|
|
896
|
-
// The organization OWNER is always a recipient, resolved in sync,
|
|
897
|
-
// so this is additional recipients rather than the list. It cannot
|
|
898
|
-
// be required: the members endpoint is owner-gated and the owner is
|
|
899
|
-
// not a member document, so a solo merchant has nothing to pick and
|
|
900
|
-
// could never save the step.
|
|
901
|
-
members : { of : 'string', type : 'array' },
|
|
902
|
-
message : { required : true, type : 'string' },
|
|
903
|
-
subject : { required : true, type : 'string' }
|
|
904
|
-
},
|
|
905
|
-
triggers : [ 'schedule.day', 'schedule.week', 'schedule.month' ],
|
|
906
|
-
usage : { actions : 0 }
|
|
907
|
-
}),
|
|
908
|
-
|
|
909
|
-
// To organization MEMBERS. Never suppressed — an entrant's opt-out must
|
|
910
|
-
// not silence an alert to staff — and not billed.
|
|
911
|
-
notify : () => ({
|
|
912
|
-
hook : 'email.notify',
|
|
913
|
-
key : 'Email — Notification',
|
|
914
|
-
queue : 'notification',
|
|
915
|
-
settings : {
|
|
916
|
-
members : { of : 'string', type : 'array' },
|
|
917
|
-
message : { required : true, type : 'string' },
|
|
918
|
-
subject : { required : true, type : 'string' }
|
|
919
|
-
},
|
|
920
|
-
triggers : [ 'lead.insert' ],
|
|
921
|
-
// Zero is a PRICE, and a deliberate one. Declared rather than omitted
|
|
922
|
-
// so "this is free" and "nobody decided" stay different statements;
|
|
923
|
-
// completeStep bills only when actions > 0.
|
|
924
|
-
usage : { actions : 0 }
|
|
925
|
-
}),
|
|
926
|
-
|
|
927
|
-
// To a LEAD. Suppression applies and the send is billed.
|
|
928
|
-
send : () => ({
|
|
929
|
-
hook : 'email.send',
|
|
930
|
-
key : 'Email — Send email',
|
|
931
|
-
queue : 'notification',
|
|
932
|
-
settings : {
|
|
933
|
-
message : { required : true, type : 'string' },
|
|
934
|
-
subject : { required : true, type : 'string' }
|
|
935
|
-
},
|
|
936
|
-
triggers : [ 'lead.insert' ],
|
|
937
|
-
// ONE SOURCE FOR THE PRICE. lib/pricing.js is the index of every
|
|
938
|
-
// customer-facing number; the handler read it too, so the same fact
|
|
939
|
-
// was stated in two places and only one of them was reviewed.
|
|
940
|
-
usage : { actions : channels.email.actionsPerSend }
|
|
941
|
-
})
|
|
942
|
-
|
|
943
|
-
},
|
|
944
|
-
|
|
945
|
-
// WITHDRAWN, which is a third thing from builder and system: declared,
|
|
946
|
-
// routed and runnable, but never offered.
|
|
947
|
-
//
|
|
948
|
-
// It went when the twilio connection did — a connection-gated step with no
|
|
949
|
-
// connection to gate on could only ever render permanently disabled. Stored
|
|
950
|
-
// workflows still carry it, so it must keep running, and enums.step.type
|
|
951
|
-
// keeps it for the same reason.
|
|
952
|
-
//
|
|
953
|
-
// NO TRIGGERS is what keeps it out of the builder: the catalog derives from
|
|
954
|
-
// triggers, so a step with none is unreachable by a merchant without a
|
|
955
|
-
// second list saying so.
|
|
956
|
-
//
|
|
957
|
-
// Platform SMS returns as a base step the way email did. That is this entry
|
|
958
|
-
// gaining triggers, not a new one.
|
|
959
|
-
sms : {
|
|
960
|
-
|
|
961
|
-
send : () => ({
|
|
962
|
-
hook : 'sms.send',
|
|
963
|
-
key : 'Send an SMS',
|
|
964
|
-
queue : 'notification',
|
|
965
|
-
settings : {
|
|
966
|
-
message : { required : true, type : 'string' },
|
|
967
|
-
subject : { required : true, type : 'string' }
|
|
968
|
-
},
|
|
969
|
-
// Priced per SEGMENT and billed from the first, which the send
|
|
970
|
-
// resolves from the message length. This is the floor.
|
|
971
|
-
usage : { actions : channels.sms.actionsPerSegment },
|
|
972
|
-
withdrawn : true
|
|
973
|
-
})
|
|
974
|
-
|
|
975
|
-
},
|
|
976
|
-
|
|
977
|
-
segment : {
|
|
978
|
-
|
|
979
|
-
// FANS OUT. It evaluates every contact in the organization against every
|
|
980
|
-
// segment, which is too much for one job — so the hook returns chunks and
|
|
981
|
-
// the shell defers completion: openStep writes the document with a slot
|
|
982
|
-
// per chunk, and whichever chunk lands last closes it and resumes the
|
|
983
|
-
// chain.
|
|
984
|
-
//
|
|
985
|
-
// It carries a hook like every other step. An earlier version declared
|
|
986
|
-
// none, on the theory that fan-out was a second protocol the shell could
|
|
987
|
-
// not run; it is the same protocol with the ending deferred, and a step
|
|
988
|
-
// declaring no hook is silently SKIPPED by the runner.
|
|
989
|
-
sync : () => ({
|
|
990
|
-
description : 'Recalculates segment membership on a daily schedule.',
|
|
991
|
-
hook : 'segment.sync',
|
|
992
|
-
key : 'Segment Sync',
|
|
993
|
-
queue : 'segment',
|
|
994
|
-
system : true
|
|
995
|
-
})
|
|
996
|
-
|
|
997
|
-
}
|
|
998
|
-
|
|
999
|
-
},
|
|
1000
|
-
tasks : () => [],
|
|
1001
|
-
title : 'Drawbridge'
|
|
1002
|
-
};
|
|
1003
790
|
|
|
1004
791
|
// HubSpot — PRIVATE, and Drawbridge's own CRM rather than a merchant's.
|
|
1005
792
|
//
|
|
@@ -1220,35 +1007,7 @@ const lookup = async ({ email, fetcher, token }) => {
|
|
|
1220
1007
|
|
|
1221
1008
|
};
|
|
1222
1009
|
|
|
1223
|
-
|
|
1224
|
-
auth : {
|
|
1225
|
-
// A Private App token from our own portal. Nothing to connect, nothing to
|
|
1226
|
-
// consent to, and no merchant involved.
|
|
1227
|
-
type : 'none'
|
|
1228
|
-
},
|
|
1229
|
-
content : {
|
|
1230
|
-
confirm : 'This connection is part of Drawbridge and cannot be disconnected.',
|
|
1231
|
-
description : [
|
|
1232
|
-
'Drawbridge keeps its own HubSpot portal in step with account signups, so the campaign a customer arrived on is on their contact record.'
|
|
1233
|
-
],
|
|
1234
|
-
excerpt : 'Drawbridge\'s own CRM sync.',
|
|
1235
|
-
guide : [
|
|
1236
|
-
'Nothing to do. This is internal to Drawbridge.'
|
|
1237
|
-
]
|
|
1238
|
-
},
|
|
1239
|
-
exclusive : false,
|
|
1240
|
-
fields : [],
|
|
1241
|
-
group : 'contacts',
|
|
1242
|
-
hooks : {
|
|
1243
|
-
auth : {
|
|
1244
|
-
connect : false,
|
|
1245
|
-
disconnect : false,
|
|
1246
|
-
probe : false,
|
|
1247
|
-
scopes : false,
|
|
1248
|
-
token : false
|
|
1249
|
-
},
|
|
1250
|
-
commerce : false,
|
|
1251
|
-
contacts : {
|
|
1010
|
+
const contacts = {
|
|
1252
1011
|
|
|
1253
1012
|
// FORGET A CONTACT, by id or by email. Account deletion — the caller had
|
|
1254
1013
|
// to search then remove, which is one round trip it should not have to
|
|
@@ -1314,8 +1073,92 @@ var hubspot = {
|
|
|
1314
1073
|
|
|
1315
1074
|
}
|
|
1316
1075
|
|
|
1076
|
+
};
|
|
1077
|
+
|
|
1078
|
+
// Drawbridge, exported from the brand kit and left as authored — the fills are the
|
|
1079
|
+
// vendor's own mark, not a recolour.
|
|
1080
|
+
//
|
|
1081
|
+
// A .js wrapper around otherwise untouched SVG so `node --test` can run against
|
|
1082
|
+
// lib/ directly. A bare .svg import would need a bundler loader and force the
|
|
1083
|
+
// tests onto dist/, which is a worse trade than one line of wrapper.
|
|
1084
|
+
var icon$3 = `<svg width="500" height="500" viewBox="0 0 500 500" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
1085
|
+
<rect width="500" height="500" fill="#BAEC5F"/>
|
|
1086
|
+
<g clip-path="url(#clip0_2115_2832)">
|
|
1087
|
+
<path d="M140.224 127.586L174.803 188.73V311.176L140 372.32L176.084 392.031L216.111 321.753V178.278L176.341 108L140.224 127.586Z" fill="#0D1314"/>
|
|
1088
|
+
<path d="M360.001 127.523L323.693 108.282L284.948 178.498V321.596L322.923 391.749L359.393 372.79L326.224 311.52V188.73L360.001 127.523Z" fill="#0D1314"/>
|
|
1089
|
+
</g>
|
|
1090
|
+
<defs>
|
|
1091
|
+
<clipPath id="clip0_2115_2832">
|
|
1092
|
+
<rect width="220" height="284" fill="white" transform="translate(140 108)"/>
|
|
1093
|
+
</clipPath>
|
|
1094
|
+
</defs>
|
|
1095
|
+
</svg>`;
|
|
1096
|
+
|
|
1097
|
+
// Drawbridge itself — the PRIVATE connection.
|
|
1098
|
+
//
|
|
1099
|
+
// Nobody connects this. There is no credential, no consent, and no card on the
|
|
1100
|
+
// connections page. It exists because a workflow step points at a hook, and the
|
|
1101
|
+
// six most common steps — sending an email, alerting a member, syncing a segment
|
|
1102
|
+
// — are things Drawbridge does rather than things a vendor does.
|
|
1103
|
+
//
|
|
1104
|
+
// Before this, those steps were the exception: every other step resolved through
|
|
1105
|
+
// a manifest and these resolved through a hardcoded registry in drawbridge-sync.
|
|
1106
|
+
// One exception is all it takes for "every step is a declaration pointing at a
|
|
1107
|
+
// hook" to stop being a rule somebody can rely on.
|
|
1108
|
+
//
|
|
1109
|
+
// PRIVATE is a real distinction, not a flag to hide a card. A public connection
|
|
1110
|
+
// answers "can this merchant connect it" through `requires` and a plan feature.
|
|
1111
|
+
// A private one is always present, in every deployment, for every organization —
|
|
1112
|
+
// so it declares neither, and build() knows not to ask.
|
|
1113
|
+
var drawbridge = {
|
|
1114
|
+
auth : {
|
|
1115
|
+
type : 'none'
|
|
1116
|
+
},
|
|
1117
|
+
content : {
|
|
1118
|
+
confirm : 'This connection is part of Drawbridge and cannot be disconnected.',
|
|
1119
|
+
description : [
|
|
1120
|
+
'Drawbridge sends your notification email and SMS, keeps your segments in sync, and posts to your own endpoints. These are built in rather than connected, so there is nothing here to set up.'
|
|
1121
|
+
],
|
|
1122
|
+
excerpt : 'The steps Drawbridge runs itself.',
|
|
1123
|
+
guide : [
|
|
1124
|
+
'Nothing to do. These steps are available in every workflow builder.'
|
|
1125
|
+
]
|
|
1126
|
+
},
|
|
1127
|
+
exclusive : false,
|
|
1128
|
+
fields : [],
|
|
1129
|
+
group : 'developer',
|
|
1130
|
+
// EVERY BODY LIVES IN drawbridge-sync. Sending needs the provider clients, the
|
|
1131
|
+
// suppression collection and the queues; segment sync needs the streams. A
|
|
1132
|
+
// published package carrying those makes every consumer carry them, which is
|
|
1133
|
+
// the reason `{}` exists as an answer.
|
|
1134
|
+
hooks : {
|
|
1135
|
+
auth : {
|
|
1136
|
+
// Nothing to connect, revoke, probe or re-scope.
|
|
1137
|
+
connect : false,
|
|
1138
|
+
disconnect : false,
|
|
1139
|
+
probe : false,
|
|
1140
|
+
scopes : false,
|
|
1141
|
+
token : false
|
|
1142
|
+
},
|
|
1143
|
+
commerce : false,
|
|
1144
|
+
// DRAWBRIDGE'S OWN CRM. Not a merchant's — this keeps our HubSpot portal in
|
|
1145
|
+
// step with account signups, and drawbridge-sync's user stream calls it.
|
|
1146
|
+
//
|
|
1147
|
+
// A real implementation here rather than `{}` because the bodies are pure
|
|
1148
|
+
// HTTP against a token: no controller, no queue, nothing that would have to
|
|
1149
|
+
// live in the service. lib/hubspot.js holds them, beside lib/sendgrid.js
|
|
1150
|
+
// and lib/twilio.js, which are the same kind of thing — vendor clients for
|
|
1151
|
+
// accounts DRAWBRIDGE holds rather than ones a merchant connects.
|
|
1152
|
+
contacts,
|
|
1153
|
+
email : {
|
|
1154
|
+
digest : {},
|
|
1155
|
+
// To organization members. NEVER suppressed and never billed: an
|
|
1156
|
+
// entrant's opt-out must not silence an alert to staff, and staff mail is
|
|
1157
|
+
// not a metered send.
|
|
1158
|
+
notify : {},
|
|
1159
|
+
// To a lead. Suppression applies and the send is billed.
|
|
1160
|
+
send : {}
|
|
1317
1161
|
},
|
|
1318
|
-
email : false,
|
|
1319
1162
|
inbound : false,
|
|
1320
1163
|
lifecycle : false,
|
|
1321
1164
|
resources : {
|
|
@@ -1324,22 +1167,157 @@ var hubspot = {
|
|
|
1324
1167
|
products : false,
|
|
1325
1168
|
promotions : false
|
|
1326
1169
|
},
|
|
1327
|
-
segment :
|
|
1328
|
-
sms :
|
|
1170
|
+
segment : { sync : {} },
|
|
1171
|
+
sms : { send : {} },
|
|
1329
1172
|
webhook : false
|
|
1330
1173
|
},
|
|
1331
1174
|
icon: icon$3,
|
|
1332
|
-
//
|
|
1175
|
+
// PRIVATE: never in the catalog, always available to the builder.
|
|
1333
1176
|
private : true,
|
|
1334
|
-
//
|
|
1335
|
-
//
|
|
1336
|
-
requires :
|
|
1337
|
-
|
|
1177
|
+
// NOTHING, and HUBSPOT_ACCESS_TOKEN in particular must not be here.
|
|
1178
|
+
//
|
|
1179
|
+
// `requires` gates AVAILABILITY: a name in it that is unset removes the whole
|
|
1180
|
+
// connection. This one is private and contributes every base workflow step —
|
|
1181
|
+
// email.send, sms.send, segment.sync — so gating it on a CRM token would take
|
|
1182
|
+
// all of them away from any deployment without a HubSpot portal, to protect a
|
|
1183
|
+
// sync that is best-effort and already no-ops without a token.
|
|
1184
|
+
//
|
|
1185
|
+
// The test 'a vendor is only available when its environment is configured'
|
|
1186
|
+
// caught exactly that: availableConnections({}) went from [ 'drawbridge' ] to
|
|
1187
|
+
// empty the moment this was added.
|
|
1188
|
+
requires : [],
|
|
1189
|
+
slug : 'drawbridge',
|
|
1190
|
+
// Always on. There is no credential that could go bad and no configuration a
|
|
1191
|
+
// merchant could leave half-finished.
|
|
1338
1192
|
status : () => 'active',
|
|
1339
|
-
//
|
|
1340
|
-
|
|
1193
|
+
// DERIVED FROM drawbridge-api/lib/workflows.js, not invented. Every value
|
|
1194
|
+
// below — trigger, billable, settings — is what that catalog and the workflow
|
|
1195
|
+
// route already enforce today, because this replaces them rather than
|
|
1196
|
+
// competing with them.
|
|
1197
|
+
//
|
|
1198
|
+
// NOT HERE, deliberately:
|
|
1199
|
+
//
|
|
1200
|
+
// step.segment.sync a SYSTEM step, dispatched by drawbridge-sync rather
|
|
1201
|
+
// than offered in the builder. It fans out, so the shell
|
|
1202
|
+
// opens its step document and the chunks close it.
|
|
1203
|
+
steps : {
|
|
1204
|
+
|
|
1205
|
+
email : {
|
|
1206
|
+
|
|
1207
|
+
// SCHEDULE-TRIGGERED, not lead-triggered: it is offered under Daily,
|
|
1208
|
+
// Weekly and Monthly. Those triggers had offered no steps at all, so a
|
|
1209
|
+
// scheduled workflow was selectable and inert until this landed.
|
|
1210
|
+
digest : () => ({
|
|
1211
|
+
hook : 'email.digest',
|
|
1212
|
+
key : 'Email — Digest',
|
|
1213
|
+
queue : 'notification',
|
|
1214
|
+
settings : {
|
|
1215
|
+
// The organization OWNER is always a recipient, resolved in sync,
|
|
1216
|
+
// so this is additional recipients rather than the list. It cannot
|
|
1217
|
+
// be required: the members endpoint is owner-gated and the owner is
|
|
1218
|
+
// not a member document, so a solo merchant has nothing to pick and
|
|
1219
|
+
// could never save the step.
|
|
1220
|
+
members : { of : 'string', type : 'array' },
|
|
1221
|
+
message : { required : true, type : 'string' },
|
|
1222
|
+
subject : { required : true, type : 'string' }
|
|
1223
|
+
},
|
|
1224
|
+
triggers : [ 'schedule.day', 'schedule.week', 'schedule.month' ],
|
|
1225
|
+
usage : { actions : 0 }
|
|
1226
|
+
}),
|
|
1227
|
+
|
|
1228
|
+
// To organization MEMBERS. Never suppressed — an entrant's opt-out must
|
|
1229
|
+
// not silence an alert to staff — and not billed.
|
|
1230
|
+
notify : () => ({
|
|
1231
|
+
hook : 'email.notify',
|
|
1232
|
+
key : 'Email — Notification',
|
|
1233
|
+
queue : 'notification',
|
|
1234
|
+
settings : {
|
|
1235
|
+
members : { of : 'string', type : 'array' },
|
|
1236
|
+
message : { required : true, type : 'string' },
|
|
1237
|
+
subject : { required : true, type : 'string' }
|
|
1238
|
+
},
|
|
1239
|
+
triggers : [ 'lead.insert' ],
|
|
1240
|
+
// Zero is a PRICE, and a deliberate one. Declared rather than omitted
|
|
1241
|
+
// so "this is free" and "nobody decided" stay different statements;
|
|
1242
|
+
// completeStep bills only when actions > 0.
|
|
1243
|
+
usage : { actions : 0 }
|
|
1244
|
+
}),
|
|
1245
|
+
|
|
1246
|
+
// To a LEAD. Suppression applies and the send is billed.
|
|
1247
|
+
send : () => ({
|
|
1248
|
+
hook : 'email.send',
|
|
1249
|
+
key : 'Email — Send email',
|
|
1250
|
+
queue : 'notification',
|
|
1251
|
+
settings : {
|
|
1252
|
+
message : { required : true, type : 'string' },
|
|
1253
|
+
subject : { required : true, type : 'string' }
|
|
1254
|
+
},
|
|
1255
|
+
triggers : [ 'lead.insert' ],
|
|
1256
|
+
// ONE SOURCE FOR THE PRICE. lib/pricing.js is the index of every
|
|
1257
|
+
// customer-facing number; the handler read it too, so the same fact
|
|
1258
|
+
// was stated in two places and only one of them was reviewed.
|
|
1259
|
+
usage : { actions : channels.email.actionsPerSend }
|
|
1260
|
+
})
|
|
1261
|
+
|
|
1262
|
+
},
|
|
1263
|
+
|
|
1264
|
+
// WITHDRAWN, which is a third thing from builder and system: declared,
|
|
1265
|
+
// routed and runnable, but never offered.
|
|
1266
|
+
//
|
|
1267
|
+
// It went when the twilio connection did — a connection-gated step with no
|
|
1268
|
+
// connection to gate on could only ever render permanently disabled. Stored
|
|
1269
|
+
// workflows still carry it, so it must keep running, and enums.step.type
|
|
1270
|
+
// keeps it for the same reason.
|
|
1271
|
+
//
|
|
1272
|
+
// NO TRIGGERS is what keeps it out of the builder: the catalog derives from
|
|
1273
|
+
// triggers, so a step with none is unreachable by a merchant without a
|
|
1274
|
+
// second list saying so.
|
|
1275
|
+
//
|
|
1276
|
+
// Platform SMS returns as a base step the way email did. That is this entry
|
|
1277
|
+
// gaining triggers, not a new one.
|
|
1278
|
+
sms : {
|
|
1279
|
+
|
|
1280
|
+
send : () => ({
|
|
1281
|
+
hook : 'sms.send',
|
|
1282
|
+
key : 'Send an SMS',
|
|
1283
|
+
queue : 'notification',
|
|
1284
|
+
settings : {
|
|
1285
|
+
message : { required : true, type : 'string' },
|
|
1286
|
+
subject : { required : true, type : 'string' }
|
|
1287
|
+
},
|
|
1288
|
+
// Priced per SEGMENT and billed from the first, which the send
|
|
1289
|
+
// resolves from the message length. This is the floor.
|
|
1290
|
+
usage : { actions : channels.sms.actionsPerSegment },
|
|
1291
|
+
withdrawn : true
|
|
1292
|
+
})
|
|
1293
|
+
|
|
1294
|
+
},
|
|
1295
|
+
|
|
1296
|
+
segment : {
|
|
1297
|
+
|
|
1298
|
+
// FANS OUT. It evaluates every contact in the organization against every
|
|
1299
|
+
// segment, which is too much for one job — so the hook returns chunks and
|
|
1300
|
+
// the shell defers completion: openStep writes the document with a slot
|
|
1301
|
+
// per chunk, and whichever chunk lands last closes it and resumes the
|
|
1302
|
+
// chain.
|
|
1303
|
+
//
|
|
1304
|
+
// It carries a hook like every other step. An earlier version declared
|
|
1305
|
+
// none, on the theory that fan-out was a second protocol the shell could
|
|
1306
|
+
// not run; it is the same protocol with the ending deferred, and a step
|
|
1307
|
+
// declaring no hook is silently SKIPPED by the runner.
|
|
1308
|
+
sync : () => ({
|
|
1309
|
+
description : 'Recalculates segment membership on a daily schedule.',
|
|
1310
|
+
hook : 'segment.sync',
|
|
1311
|
+
key : 'Segment Sync',
|
|
1312
|
+
queue : 'segment',
|
|
1313
|
+
system : true
|
|
1314
|
+
})
|
|
1315
|
+
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1318
|
+
},
|
|
1341
1319
|
tasks : () => [],
|
|
1342
|
-
title : '
|
|
1320
|
+
title : 'Drawbridge'
|
|
1343
1321
|
};
|
|
1344
1322
|
|
|
1345
1323
|
// Klaviyo, exported from the brand kit and left as authored — the fills are the
|
|
@@ -1944,15 +1922,16 @@ var icon$1 = `<svg width="500" height="500" viewBox="0 0 500 500" fill="none" xm
|
|
|
1944
1922
|
<path d="M360.476 284.243C360.35 283.835 359.618 281.204 358.647 278.052L356.621 272.648C360.575 266.696 360.645 261.405 360.124 258.393C359.531 254.519 357.693 250.944 354.89 248.205C351.766 244.94 345.363 241.563 336.385 239.044L331.671 237.736C331.643 237.524 331.418 226.619 331.235 221.933C331.08 218.555 330.798 213.264 329.152 208.058C327.182 200.993 323.791 194.858 319.527 190.876C331.277 178.717 338.594 165.307 338.58 153.81C338.538 131.703 311.379 124.976 277.902 138.851L270.824 141.863C270.795 141.835 258.004 129.283 257.821 129.128C219.63 95.8334 100.327 228.476 138.49 260.687L146.835 267.737C144.581 273.775 143.781 280.259 144.499 286.664C145.414 295.543 149.973 304.029 157.375 310.6C164.411 316.82 173.684 320.788 182.648 320.774C197.494 354.998 231.408 375.965 271.175 377.161C313.842 378.427 349.641 358.403 364.67 322.435C365.641 319.916 369.806 308.546 369.806 298.513C369.792 288.409 364.093 284.229 360.476 284.243ZM185.913 311.149C184.613 311.381 183.293 311.48 181.973 311.445C169.083 311.079 155.166 299.483 153.787 285.735C152.253 270.537 160.02 258.829 173.783 256.071C175.415 255.72 177.414 255.537 179.552 255.635C187.264 256.085 198.606 261.996 201.209 278.784C203.517 293.63 199.858 308.785 185.913 311.149ZM171.545 246.953C163.179 248.499 155.744 253.244 150.817 260.18C148.045 257.873 142.909 253.426 142.008 251.681C134.635 237.693 150.043 210.478 160.823 195.111C187.405 157.145 229.086 128.424 248.393 133.603C251.517 134.503 261.902 146.563 261.902 146.563C261.902 146.563 242.623 157.244 224.724 172.16C200.646 190.735 182.423 217.697 171.545 246.953ZM306.792 305.464C306.937 305.403 307.057 305.295 307.134 305.157C307.211 305.019 307.239 304.86 307.214 304.704C307.205 304.61 307.178 304.519 307.133 304.436C307.088 304.353 307.027 304.28 306.954 304.221C306.88 304.162 306.796 304.118 306.705 304.092C306.614 304.066 306.519 304.059 306.426 304.071C306.426 304.071 286.246 307.054 267.179 300.089C269.247 293.348 274.792 295.754 283.137 296.444C296.108 297.209 309.116 295.802 321.623 292.279C330.25 289.788 341.592 284.905 350.401 277.953C353.384 284.497 354.425 291.674 354.425 291.674C354.425 291.674 356.719 291.265 358.647 292.447C360.476 293.573 361.799 295.895 360.898 301.89C359.027 313.119 354.271 322.224 346.235 330.611C341.236 336.036 335.277 340.492 328.659 343.754C324.983 345.691 321.151 347.32 317.205 348.623C286.964 358.487 256.006 347.638 246.029 324.321C245.224 322.535 244.556 320.691 244.03 318.804C239.781 303.438 243.383 285.032 254.655 273.408C255.372 272.676 256.09 271.804 256.09 270.706C256.09 269.806 255.499 268.835 255.007 268.131C251.066 262.418 237.374 252.666 240.132 233.795C242.088 220.23 253.951 210.689 265.012 211.252L267.826 211.421C272.611 211.702 276.79 212.307 280.73 212.49C287.344 212.758 293.268 211.801 300.304 205.947C302.683 203.949 304.582 202.246 307.791 201.711C308.128 201.627 308.973 201.359 310.647 201.416C312.365 201.485 314.032 202.015 315.474 202.949C321.103 206.693 321.905 215.783 322.214 222.439C322.383 226.225 322.848 235.414 322.988 238.031C323.354 244.054 324.944 244.912 328.125 245.954C329.94 246.573 331.615 246.995 334.077 247.713C341.521 249.781 345.968 251.934 348.754 254.65C350.198 256.049 351.13 257.893 351.4 259.885C352.315 266.316 346.432 274.252 330.925 281.457C313.954 289.324 293.367 291.322 279.154 289.732L274.173 289.169C262.774 287.649 256.315 302.34 263.14 312.402C267.545 318.889 279.52 323.11 291.523 323.11C319.006 323.139 340.142 311.402 348.023 301.242L348.642 300.356C349.008 299.765 348.712 299.469 348.22 299.779C341.817 304.169 313.279 321.619 282.771 316.384C282.771 316.384 279.056 315.765 275.678 314.442C273.005 313.429 267.362 310.811 266.686 305.042C291.27 312.683 306.792 305.478 306.792 305.464ZM220.671 194.971C230.127 184.051 241.765 174.538 252.206 169.219C252.558 169.022 252.938 169.43 252.741 169.754C251.46 172 250.476 174.403 249.814 176.902C249.73 177.282 250.138 177.592 250.461 177.353C256.963 172.934 268.248 168.192 278.155 167.601C278.251 167.584 278.351 167.601 278.436 167.65C278.521 167.698 278.586 167.775 278.621 167.866C278.656 167.957 278.658 168.058 278.627 168.151C278.596 168.244 278.533 168.323 278.451 168.375C276.809 169.634 275.342 171.105 274.088 172.751C273.891 173.032 274.074 173.44 274.426 173.44C281.378 173.483 291.186 175.903 297.56 179.491C297.982 179.745 297.673 180.575 297.209 180.462C287.527 178.253 271.724 176.564 255.288 180.575C240.597 184.149 229.396 189.666 221.248 195.618C220.826 195.899 220.333 195.351 220.671 194.971Z" fill="#231E15"/>
|
|
1945
1923
|
</svg>`;
|
|
1946
1924
|
|
|
1947
|
-
// EVERY ACCOUNT LIVES BEHIND A DATA-CENTRE PREFIX,
|
|
1948
|
-
//
|
|
1949
|
-
// call
|
|
1950
|
-
//
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1925
|
+
// EVERY ACCOUNT LIVES BEHIND A DATA-CENTRE PREFIX — us1, us19 — and there is no
|
|
1926
|
+
// fixed host to call. Mailchimp's oldest quirk, and the reason its OAuth needs a
|
|
1927
|
+
// metadata call the other vendors do not.
|
|
1928
|
+
//
|
|
1929
|
+
// Under keys the prefix was the key's own suffix (`...-us19`). Under OAuth it is
|
|
1930
|
+
// whatever auth.connect stored from /oauth2/metadata, which is why that hook is
|
|
1931
|
+
// not enrichment: without `dc` there is nowhere to send a request.
|
|
1932
|
+
const base = ( dc ) => {
|
|
1954
1933
|
|
|
1955
|
-
if( ! dc
|
|
1934
|
+
if( ! dc ) throw new Error( 'This Mailchimp connection has no data centre stored, so there is no host to call' );
|
|
1956
1935
|
|
|
1957
1936
|
return 'https://' + dc + '.api.mailchimp.com/3.0';
|
|
1958
1937
|
|
|
@@ -1960,40 +1939,54 @@ const base = ( apiKey ) => {
|
|
|
1960
1939
|
|
|
1961
1940
|
// Mailchimp — contact sync, not a sender.
|
|
1962
1941
|
var mailchimp = {
|
|
1963
|
-
//
|
|
1964
|
-
//
|
|
1965
|
-
//
|
|
1942
|
+
// OAUTH 2, authorization code. Every url below is quoted from
|
|
1943
|
+
// mailchimp.com/developer/marketing/guides/access-user-data-oauth-2/ rather
|
|
1944
|
+
// than remembered.
|
|
1966
1945
|
//
|
|
1967
|
-
//
|
|
1968
|
-
//
|
|
1969
|
-
//
|
|
1946
|
+
// THE METADATA CALL IS MAILCHIMP'S QUIRK and cannot be skipped: an access
|
|
1947
|
+
// token alone cannot call the Marketing API, because every account lives
|
|
1948
|
+
// behind a data-centre prefix (us1, us19...) that only GET
|
|
1949
|
+
// login.mailchimp.com/oauth2/metadata returns — and every subsequent request
|
|
1950
|
+
// needs it in the HOST. That is why auth.connect below is a real function:
|
|
1951
|
+
// the standard exchange does not know where to send anything afterwards.
|
|
1970
1952
|
//
|
|
1971
|
-
//
|
|
1972
|
-
//
|
|
1973
|
-
//
|
|
1974
|
-
//
|
|
1953
|
+
// No PKCE. No scopes — the docs describe none. And no refresh token: "Mailchimp
|
|
1954
|
+
// Marketing access tokens do not expire, so you don't need to use a
|
|
1955
|
+
// refresh_token", so tokenSettings stores no expiry and isStale reads that as
|
|
1956
|
+
// nothing to refresh toward.
|
|
1975
1957
|
//
|
|
1976
|
-
//
|
|
1977
|
-
//
|
|
1978
|
-
//
|
|
1958
|
+
// auth.token stays false: the exchange is POST form-encoded with grant_type,
|
|
1959
|
+
// client_id, client_secret, redirect_uri and code, which is exactly the
|
|
1960
|
+
// runner's default — nothing to wrap.
|
|
1979
1961
|
auth : {
|
|
1980
|
-
|
|
1962
|
+
oauth : {
|
|
1963
|
+
client : {
|
|
1964
|
+
id : 'MAILCHIMP_OAUTH_CLIENT_ID',
|
|
1965
|
+
secret : 'MAILCHIMP_OAUTH_CLIENT_SECRET'
|
|
1966
|
+
},
|
|
1967
|
+
urls : {
|
|
1968
|
+
authorize : 'https://login.mailchimp.com/oauth2/authorize',
|
|
1969
|
+
redirect : '/api/connection/mailchimp/callback',
|
|
1970
|
+
token : 'https://login.mailchimp.com/oauth2/token'
|
|
1971
|
+
}
|
|
1972
|
+
},
|
|
1973
|
+
type : 'oauth'
|
|
1981
1974
|
},
|
|
1982
1975
|
// EVERYTHING A MERCHANT READS. `errors` belongs in here rather than at the
|
|
1983
1976
|
// top level because the connection DOCUMENT carries its own `errors` array
|
|
1984
1977
|
// and the document is spread OVER the resolved manifest downstream — a
|
|
1985
1978
|
// top-level one would be replaced by that array and never render.
|
|
1986
1979
|
content : {
|
|
1987
|
-
confirm : 'Disconnecting removes
|
|
1980
|
+
confirm : 'Disconnecting removes Drawbridge\'s stored Mailchimp access. You can also remove Drawbridge from the Authorized Apps page in your Mailchimp account. Your contacts stay in both Drawbridge and Mailchimp — neither list is deleted.',
|
|
1988
1981
|
description : [
|
|
1989
1982
|
'Drawbridge no longer sends email through Mailchimp. Notification email now sends from Drawbridge itself, and verifying a domain under Networking in your organization settings puts your own brand in the from line.',
|
|
1990
|
-
'This connection is becoming the way your Drawbridge contacts sync into a Mailchimp audience. Audience syncing is not live yet, so
|
|
1983
|
+
'This connection is becoming the way your Drawbridge contacts sync into a Mailchimp audience. Audience syncing is not live yet, so connecting today does nothing except choose the audience it will use when it ships.'
|
|
1991
1984
|
],
|
|
1992
1985
|
excerpt : 'Sync your Drawbridge contacts into a Mailchimp audience.',
|
|
1993
1986
|
guide : [
|
|
1994
|
-
'
|
|
1995
|
-
'
|
|
1996
|
-
'
|
|
1987
|
+
'Press Connect. Drawbridge sends you to Mailchimp to approve access.',
|
|
1988
|
+
'Sign in to Mailchimp if you are not already, and choose the account to connect.',
|
|
1989
|
+
'You come back here to pick the audience your contacts should sync into.'
|
|
1997
1990
|
]
|
|
1998
1991
|
},
|
|
1999
1992
|
// Mailchimp and SendGrid shared a group while they were SENDERS, where an org
|
|
@@ -2003,15 +1996,6 @@ var mailchimp = {
|
|
|
2003
1996
|
exclusive : false,
|
|
2004
1997
|
feature : 'organization:connection:mailchimp',
|
|
2005
1998
|
fields : [
|
|
2006
|
-
{
|
|
2007
|
-
input : 'password',
|
|
2008
|
-
key : 'apiKey',
|
|
2009
|
-
label : 'Mailchimp API key',
|
|
2010
|
-
message : 'Your Mailchimp API key',
|
|
2011
|
-
placeholder : '••••••••••••••••••••••••••••••••-us1',
|
|
2012
|
-
redact : true,
|
|
2013
|
-
required : true
|
|
2014
|
-
},
|
|
2015
1999
|
{
|
|
2016
2000
|
input : 'select',
|
|
2017
2001
|
key : 'audience',
|
|
@@ -2031,20 +2015,55 @@ var mailchimp = {
|
|
|
2031
2015
|
hooks : {
|
|
2032
2016
|
|
|
2033
2017
|
auth : {
|
|
2034
|
-
//
|
|
2035
|
-
//
|
|
2036
|
-
//
|
|
2037
|
-
//
|
|
2038
|
-
//
|
|
2039
|
-
//
|
|
2040
|
-
|
|
2018
|
+
// WHERE THE ACCOUNT LIVES. Not enrichment — without this the connection
|
|
2019
|
+
// is unusable, because the Marketing API host is per-account and only
|
|
2020
|
+
// this call knows it. The callback merges what this returns into the
|
|
2021
|
+
// stored settings, which is how `dc` reaches every later request.
|
|
2022
|
+
//
|
|
2023
|
+
// The header here is `OAuth <token>`, not Bearer — that is specific to
|
|
2024
|
+
// the metadata endpoint. Marketing API calls take Bearer; see the
|
|
2025
|
+
// audiences hook.
|
|
2026
|
+
connect : async ({ fetcher = fetch, tokens }) => {
|
|
2027
|
+
|
|
2028
|
+
const response = await fetcher( 'https://login.mailchimp.com/oauth2/metadata', {
|
|
2029
|
+
headers : {
|
|
2030
|
+
authorization : 'OAuth ' + tokens?.accessToken
|
|
2031
|
+
},
|
|
2032
|
+
signal : AbortSignal.timeout( 15000 )
|
|
2033
|
+
});
|
|
2034
|
+
|
|
2035
|
+
if( ! response.ok ){
|
|
2036
|
+
|
|
2037
|
+
throw Object.assign(
|
|
2038
|
+
new Error( 'Mailchimp would not say which data centre this account is on (' + response.status + ')' ),
|
|
2039
|
+
{ status : response.status }
|
|
2040
|
+
);
|
|
2041
|
+
|
|
2042
|
+
}
|
|
2043
|
+
|
|
2044
|
+
const body = await response.json();
|
|
2045
|
+
|
|
2046
|
+
// No dc means no host to call. Failing here is better than storing a
|
|
2047
|
+
// connection that reads Active and 404s on its first request.
|
|
2048
|
+
if( ! body?.dc ) throw new Error( 'Mailchimp returned no data centre for this account' );
|
|
2049
|
+
|
|
2050
|
+
return { dc : body.dc };
|
|
2051
|
+
|
|
2052
|
+
},
|
|
2053
|
+
// Nothing to call. A merchant revokes Drawbridge from Mailchimp's own
|
|
2054
|
+
// Authorized Apps page; the docs describe no revocation endpoint for us
|
|
2055
|
+
// to call on their behalf.
|
|
2041
2056
|
disconnect : false,
|
|
2042
2057
|
probe : false,
|
|
2043
2058
|
scopes : false,
|
|
2044
|
-
//
|
|
2045
|
-
//
|
|
2046
|
-
//
|
|
2047
|
-
|
|
2059
|
+
// The plain exchange. Mailchimp takes the client as FORM FIELDS
|
|
2060
|
+
// (grant_type, client_id, client_secret, redirect_uri, code), which is
|
|
2061
|
+
// the runner's default — so no `basic : true` as Klaviyo needs.
|
|
2062
|
+
//
|
|
2063
|
+
// build() requires an oauth manifest to name this explicitly rather than
|
|
2064
|
+
// letting it default, which caught this file declaring `false` on the
|
|
2065
|
+
// first import after the conversion.
|
|
2066
|
+
token : authToken
|
|
2048
2067
|
},
|
|
2049
2068
|
commerce : false,
|
|
2050
2069
|
contacts : { remove : false, sync : false },
|
|
@@ -2067,18 +2086,21 @@ var mailchimp = {
|
|
|
2067
2086
|
// successful — the same silent truncation Klaviyo has, at a different
|
|
2068
2087
|
// number. Paged against total_items so an account past a thousand still
|
|
2069
2088
|
// resolves.
|
|
2070
|
-
audiences : async ({ cursor, fetcher = fetch, limit = 100, search, settings }) => {
|
|
2089
|
+
audiences : async ({ cursor, fetcher = fetch, limit = 100, search, settings, token }) => {
|
|
2071
2090
|
|
|
2072
|
-
|
|
2091
|
+
// Bearer, not Basic. Mailchimp's fundamentals doc states "API keys and
|
|
2092
|
+
// OAuth 2 tokens can be used to make authenticated requests the same
|
|
2093
|
+
// way", so one header serves both — the Basic form this used under
|
|
2094
|
+
// keys was never OAuth-compatible.
|
|
2095
|
+
const dc = settings?.dc;
|
|
2073
2096
|
|
|
2074
2097
|
const count = Math.min( limit, 1000 );
|
|
2075
2098
|
const offset = Number( cursor || 0 );
|
|
2076
2099
|
|
|
2077
2100
|
const response = await fetcher(
|
|
2078
|
-
base(
|
|
2101
|
+
base( dc ) + '/lists?count=' + count + '&offset=' + offset + '&fields=lists.id,lists.name,total_items',
|
|
2079
2102
|
{
|
|
2080
|
-
|
|
2081
|
-
headers : { authorization : 'Basic ' + Buffer.from( 'drawbridge:' + key ).toString( 'base64' ) },
|
|
2103
|
+
headers : { authorization : 'Bearer ' + token },
|
|
2082
2104
|
signal : AbortSignal.timeout( 15000 )
|
|
2083
2105
|
}
|
|
2084
2106
|
);
|
|
@@ -2128,6 +2150,13 @@ var mailchimp = {
|
|
|
2128
2150
|
webhook : false
|
|
2129
2151
|
},
|
|
2130
2152
|
icon: icon$1,
|
|
2153
|
+
// The OAuth client this deployment registered. Without both, the vendor drops
|
|
2154
|
+
// out of availableConnections rather than offering a Connect button that
|
|
2155
|
+
// cannot complete.
|
|
2156
|
+
requires : [
|
|
2157
|
+
'MAILCHIMP_OAUTH_CLIENT_ID',
|
|
2158
|
+
'MAILCHIMP_OAUTH_CLIENT_SECRET'
|
|
2159
|
+
],
|
|
2131
2160
|
slug : 'mailchimp',
|
|
2132
2161
|
// A key with no audience chosen is authenticated and inert. Mailchimp also
|
|
2133
2162
|
// needs its merge fields created on that audience before any Drawbridge total
|
|
@@ -3289,7 +3318,6 @@ const stepLabels = ( catalog = connections ) => Object.fromEntries(
|
|
|
3289
3318
|
const connections = Object.freeze({
|
|
3290
3319
|
attentive : build( attentive ),
|
|
3291
3320
|
drawbridge : build( drawbridge ),
|
|
3292
|
-
hubspot : build( hubspot ),
|
|
3293
3321
|
klaviyo : build( klaviyo ),
|
|
3294
3322
|
mailchimp : build( mailchimp ),
|
|
3295
3323
|
shopify : build( shopify ),
|