@drawbridge/drawbridge-utils 0.0.114 → 0.0.115
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 +263 -2
- package/dist/connections/index.d.cts +340 -3
- package/dist/connections/index.d.ts +340 -3
- package/dist/connections/index.js +262 -2
- package/dist/features.cjs +15 -0
- package/dist/features.d.cts +15 -0
- package/dist/features.d.ts +15 -0
- package/dist/features.js +15 -0
- package/dist/fields-validate.js +1 -1
- package/dist/phone.cjs +12 -0
- package/dist/phone.d.cts +30 -2
- package/dist/phone.d.ts +30 -2
- package/dist/phone.js +12 -1
- package/dist/plans.cjs +17 -0
- package/dist/plans.d.cts +2 -0
- package/dist/plans.d.ts +2 -0
- package/dist/plans.js +17 -0
- package/dist/pricing.cjs +17 -0
- package/dist/pricing.js +17 -0
- package/package.json +2 -2
|
@@ -519,6 +519,249 @@ const accessToken = async ({
|
|
|
519
519
|
|
|
520
520
|
};
|
|
521
521
|
|
|
522
|
+
// Attentive, exported from the brand kit and left as authored — the yellow
|
|
523
|
+
// field and the mark's fills are the vendor's own, not a recolour.
|
|
524
|
+
//
|
|
525
|
+
// A .js wrapper around otherwise untouched SVG so `node --test` can run against
|
|
526
|
+
// lib/ directly. A bare .svg import would need a bundler loader and force the
|
|
527
|
+
// tests through dist.
|
|
528
|
+
var icon$4 = `<svg width="500" height="500" viewBox="0 0 500 500" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
529
|
+
<rect width="500" height="500" fill="#FFD967"/>
|
|
530
|
+
<path d="M239.369 127.404C260.863 122.013 284.964 132.569 295.576 152.039C321.796 201.286 347.928 250.567 374.131 299.825C380.149 311.989 381.244 326.564 376.733 339.41C371.446 355.097 358.039 367.69 342.107 372.089C326.274 376.67 308.351 372.871 295.741 362.255C288.865 356.892 284.161 349.359 280.354 341.629C261.869 306.95 243.478 272.217 225.071 237.501C214.409 218.614 187.221 212.656 169.622 225.315C168.104 227.309 164.159 226.857 164.72 223.796C176.911 202.569 189.361 181.497 201.662 160.331C205.183 154.428 208.214 148.129 212.967 143.091C219.844 135.272 229.263 129.782 239.374 127.404" fill="#1E1C1C"/>
|
|
531
|
+
<path d="M166.04 261.805C180.228 259.107 195.528 261.893 207.581 269.971C218.512 277.079 226.908 288.136 230.604 300.657C234.835 314.103 233.614 329.124 227.485 341.788C220.097 356.875 205.782 368.543 189.317 372.089C173.957 375.652 157.089 372.386 144.304 363.103C132.971 355.295 124.912 342.989 121.891 329.581C118.943 316.636 120.725 302.656 127.002 290.938C134.699 275.951 149.503 264.933 166.046 261.811" fill="#1E1C1C"/>
|
|
532
|
+
</svg>`;
|
|
533
|
+
|
|
534
|
+
// Attentive — SMS-first marketing, installed as a distributed Attentive app.
|
|
535
|
+
//
|
|
536
|
+
// EVERY VENDOR FACT BELOW IS CITED from docs.attentive.com (fetched 2026-09-01):
|
|
537
|
+
//
|
|
538
|
+
// authorize docs.attentive.com/docs/authentication — the install prompt is
|
|
539
|
+
// ui.attentivemobile.com/integrations/oauth-install, documented
|
|
540
|
+
// with `client_id` and `redirect_uri` parameters.
|
|
541
|
+
//
|
|
542
|
+
// token docs.attentive.com/reference/createtokenviaauthorizationcode.md —
|
|
543
|
+
// POST api.attentivemobile.com/v1/authorization-codes/tokens, all
|
|
544
|
+
// parameters as FORM FIELDS (grant_type, code, redirect_uri,
|
|
545
|
+
// client_id, client_secret). Credentials in the body is our
|
|
546
|
+
// runner's default, so unlike Klaviyo there is nothing to wrap
|
|
547
|
+
// for auth — see hooks.auth.token for what IS wrapped, and why.
|
|
548
|
+
//
|
|
549
|
+
// response { access_token, id_token, token_type : "Bearer",
|
|
550
|
+
// expires_in : 900 } — and NO refresh_token, which matters below.
|
|
551
|
+
//
|
|
552
|
+
// scopes events:write, ecommerce:write, subscriptions:write,
|
|
553
|
+
// attributes:write, privacy_requests:write; the segments API
|
|
554
|
+
// takes segments:read or segments:write. Scopes ride on the app's
|
|
555
|
+
// registration (the generated distribution URL carries them), not
|
|
556
|
+
// on each consent — so none are declared here.
|
|
557
|
+
//
|
|
558
|
+
// segments docs.attentive.com/reference/listsegments.md —
|
|
559
|
+
// GET api.attentivemobile.com/v2/segments with `name` (partial
|
|
560
|
+
// match), `cursor` and `limit` (1-1000, default 20); responds
|
|
561
|
+
// { segments : [ { externalId, name, ... } ], cursor, hasMore }.
|
|
562
|
+
//
|
|
563
|
+
// DORMANT UNTIL REGISTERED. `requires` names the client credentials that only
|
|
564
|
+
// exist once the Attentive app is created (their console: enable distribution,
|
|
565
|
+
// set the redirect URL, Generate Credentials). Until those env vars land, no
|
|
566
|
+
// deployment offers this connection — the manifest ships complete and inert.
|
|
567
|
+
//
|
|
568
|
+
// THREE THINGS TO VERIFY AT REGISTRATION, because the docs conflict or are
|
|
569
|
+
// silent, and only a live install answers them:
|
|
570
|
+
//
|
|
571
|
+
// 1. TOKEN LIFETIME. The auth overview says access tokens "do not expire";
|
|
572
|
+
// the token response carries expires_in : 900 and no refresh_token. If
|
|
573
|
+
// the token really died at 15 minutes with nothing to renew it, every
|
|
574
|
+
// connection would need reconnecting a quarter-hour after consent.
|
|
575
|
+
// hooks.auth.token below models the overview's answer — see its comment.
|
|
576
|
+
//
|
|
577
|
+
// 2. STATE ECHO. Our callback requires the parked `state` to round-trip, and
|
|
578
|
+
// their authorize URL is documented with only client_id and redirect_uri.
|
|
579
|
+
// If the consent drops unknown params, the flow breaks at the callback.
|
|
580
|
+
//
|
|
581
|
+
// 3. PER-ENVIRONMENT REDIRECTS. The redirect must byte-match the app's
|
|
582
|
+
// registration, and dev and prod have different callback hosts — one app
|
|
583
|
+
// with multiple redirect URLs, or two apps like Shopify's two tomls.
|
|
584
|
+
var attentive = {
|
|
585
|
+
auth : {
|
|
586
|
+
oauth : {
|
|
587
|
+
// NAMES of the env vars holding OUR app's client — set at registration,
|
|
588
|
+
// never before. No `headers` on the client: Attentive takes credentials
|
|
589
|
+
// as form fields, which is the runner's default.
|
|
590
|
+
client : {
|
|
591
|
+
id : 'ATTENTIVE_OAUTH_CLIENT_ID',
|
|
592
|
+
secret : 'ATTENTIVE_OAUTH_CLIENT_SECRET'
|
|
593
|
+
},
|
|
594
|
+
urls : {
|
|
595
|
+
authorize : 'https://ui.attentivemobile.com/integrations/oauth-install',
|
|
596
|
+
redirect : '/api/connection/attentive/callback',
|
|
597
|
+
token : 'https://api.attentivemobile.com/v1/authorization-codes/tokens'
|
|
598
|
+
}
|
|
599
|
+
},
|
|
600
|
+
type : 'oauth'
|
|
601
|
+
},
|
|
602
|
+
// EVERYTHING A MERCHANT READS. `errors` would live in here too — the
|
|
603
|
+
// connection DOCUMENT carries its own `errors` array and is spread OVER the
|
|
604
|
+
// resolved manifest downstream, so a top-level one would never render.
|
|
605
|
+
content : {
|
|
606
|
+
confirm : 'Disconnecting revokes Drawbridge\'s access to your Attentive account. Your subscribers stay in both Attentive and Drawbridge — neither list is deleted.',
|
|
607
|
+
description : [
|
|
608
|
+
'Attentive is where your SMS marketing lives, and this connection is becoming the way your Drawbridge contacts sync into an Attentive segment.',
|
|
609
|
+
'You authorize Drawbridge from inside Attentive and can revoke that access there at any time. Drawbridge never sees or stores your Attentive password.',
|
|
610
|
+
'Subscriber syncing is not live yet, so connecting today does nothing except choose the segment it will use when it ships.'
|
|
611
|
+
],
|
|
612
|
+
excerpt : 'Sync your Drawbridge contacts into an Attentive segment.',
|
|
613
|
+
guide : [
|
|
614
|
+
'Press Connect. Drawbridge sends you to Attentive to approve access.',
|
|
615
|
+
'Sign in to Attentive if you are not already, and authorize the permissions listed.',
|
|
616
|
+
'You are returned here — choose which Attentive segment your contacts should sync into.'
|
|
617
|
+
]
|
|
618
|
+
},
|
|
619
|
+
// A contact destination, like Klaviyo and Mailchimp — a merchant could
|
|
620
|
+
// reasonably keep several up to date at once.
|
|
621
|
+
exclusive : false,
|
|
622
|
+
feature : 'organization:connection:attentive',
|
|
623
|
+
fields : [
|
|
624
|
+
{
|
|
625
|
+
input : 'select',
|
|
626
|
+
key : 'segment',
|
|
627
|
+
label : 'Attentive segment',
|
|
628
|
+
message : 'Contacts your campaigns collect are synced into this segment.',
|
|
629
|
+
hook : 'resources.audiences',
|
|
630
|
+
required : true
|
|
631
|
+
// No `search : false` here, and that is a first: /v2/segments takes a
|
|
632
|
+
// `name` filter (partial match, cited above), so this picker searches
|
|
633
|
+
// the ACCOUNT — Klaviyo and Mailchimp can only match the fetched page.
|
|
634
|
+
}
|
|
635
|
+
],
|
|
636
|
+
group : 'contacts',
|
|
637
|
+
// A HOOK'S VALUE IS ITS ANSWER. The consent is stored and can be revoked;
|
|
638
|
+
// nothing else is built yet, because subscriber sync has not shipped. Every
|
|
639
|
+
// false here is "not yet" rather than "never" — when the sync lands, probe
|
|
640
|
+
// and contacts.sync are the first to flip.
|
|
641
|
+
hooks : {
|
|
642
|
+
|
|
643
|
+
auth : {
|
|
644
|
+
// The exchange already yields the tokens, and Attentive documents no
|
|
645
|
+
// account-identity endpoint to enrich them with — Klaviyo's connect
|
|
646
|
+
// reads the account name back; this has nothing cited to read. The
|
|
647
|
+
// callback stores the tokens and skips enrichment on `unimplemented`.
|
|
648
|
+
connect : {},
|
|
649
|
+
disconnect : {},
|
|
650
|
+
probe : false,
|
|
651
|
+
scopes : false,
|
|
652
|
+
// THE ONE THING WRAPPED, and it is about the response rather than the
|
|
653
|
+
// request. Attentive's token reply carries expires_in : 900 while their
|
|
654
|
+
// auth overview says access tokens "do not expire" — and no refresh
|
|
655
|
+
// token exists to renew with. Storing that expiry would have
|
|
656
|
+
// accessToken() declaring the credential spent fifteen minutes after
|
|
657
|
+
// consent, with nothing to renew it: every connection would demand
|
|
658
|
+
// reconnecting four times an hour.
|
|
659
|
+
//
|
|
660
|
+
// The overview's answer is modelled — the expiry is dropped, so the
|
|
661
|
+
// token is treated as long-lived. Registration item 1 in the header is
|
|
662
|
+
// the live exchange that proves this right or wrong.
|
|
663
|
+
token : async ( args ) => {
|
|
664
|
+
|
|
665
|
+
const minted = await authToken( args );
|
|
666
|
+
|
|
667
|
+
return { ...minted, expiresIn : null };
|
|
668
|
+
|
|
669
|
+
}
|
|
670
|
+
},
|
|
671
|
+
commerce : false,
|
|
672
|
+
contacts : { remove : false, sync : false },
|
|
673
|
+
email : false,
|
|
674
|
+
inbound : false,
|
|
675
|
+
lifecycle : false,
|
|
676
|
+
resources : {
|
|
677
|
+
|
|
678
|
+
// The segments a merchant can sync into, for the picker on their
|
|
679
|
+
// connection.
|
|
680
|
+
//
|
|
681
|
+
// GET /v2/segments (cited in the header). `limit` caps at 1000 in their
|
|
682
|
+
// own spec, defaulting to 20 — low enough that leaving it unset would
|
|
683
|
+
// show a picker quietly missing most of a real account. The response's
|
|
684
|
+
// only identifier is `externalId`, so an entry without one cannot be
|
|
685
|
+
// stored and is dropped.
|
|
686
|
+
audiences : async ({ cursor, fetcher = fetch, limit = 100, search, token }) => {
|
|
687
|
+
|
|
688
|
+
const query = new URLSearchParams({
|
|
689
|
+
limit : String( Math.min( limit, 1000 ) ),
|
|
690
|
+
...( cursor && { cursor } ),
|
|
691
|
+
...( search?.value && { name : String( search.value ).trim() } )
|
|
692
|
+
});
|
|
693
|
+
|
|
694
|
+
const response = await fetcher(
|
|
695
|
+
'https://api.attentivemobile.com/v2/segments?' + query,
|
|
696
|
+
{
|
|
697
|
+
headers : { authorization : 'Bearer ' + token },
|
|
698
|
+
signal : AbortSignal.timeout( 15000 )
|
|
699
|
+
}
|
|
700
|
+
);
|
|
701
|
+
|
|
702
|
+
if( ! response.ok ){
|
|
703
|
+
|
|
704
|
+
throw Object.assign(
|
|
705
|
+
new Error( 'Attentive refused the request (' + response.status + ')' ),
|
|
706
|
+
{ status : response.status }
|
|
707
|
+
);
|
|
708
|
+
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
const body = await response.json();
|
|
712
|
+
|
|
713
|
+
return {
|
|
714
|
+
items : ( body?.segments || [] )
|
|
715
|
+
.filter( ( segment ) => segment?.externalId )
|
|
716
|
+
.map( ( segment ) => ({ id : segment.externalId, title : segment?.name || segment.externalId }) ),
|
|
717
|
+
pageInfo : {
|
|
718
|
+
endCursor : body?.hasMore ? ( body?.cursor || null ) : null,
|
|
719
|
+
hasNextPage : Boolean( body?.hasMore )
|
|
720
|
+
}
|
|
721
|
+
};
|
|
722
|
+
|
|
723
|
+
},
|
|
724
|
+
prices : false,
|
|
725
|
+
products : false,
|
|
726
|
+
promotions : false
|
|
727
|
+
|
|
728
|
+
},
|
|
729
|
+
segment : false,
|
|
730
|
+
sms : false,
|
|
731
|
+
webhook : false
|
|
732
|
+
|
|
733
|
+
},
|
|
734
|
+
icon: icon$4,
|
|
735
|
+
requires : [
|
|
736
|
+
'ATTENTIVE_OAUTH_CLIENT_ID',
|
|
737
|
+
'ATTENTIVE_OAUTH_CLIENT_SECRET'
|
|
738
|
+
],
|
|
739
|
+
slug : 'attentive',
|
|
740
|
+
// A consent with no segment chosen is authenticated and inert — the sync,
|
|
741
|
+
// when it ships, needs somewhere to put people.
|
|
742
|
+
status : ( data ) => ( data?.settings?.segment ? data.status : 'pending' ),
|
|
743
|
+
// No steps: subscriber sync has not shipped, so this vendor contributes
|
|
744
|
+
// nothing to a workflow yet. An empty steps object is the honest declaration.
|
|
745
|
+
steps : {},
|
|
746
|
+
tasks : ( data ) => [
|
|
747
|
+
...( data?.settings?.segment
|
|
748
|
+
? []
|
|
749
|
+
: [
|
|
750
|
+
{
|
|
751
|
+
message : 'Choose which Attentive segment your contacts should sync into. Until you do, nothing is being synced.',
|
|
752
|
+
title : 'Choose a segment'
|
|
753
|
+
}
|
|
754
|
+
]
|
|
755
|
+
),
|
|
756
|
+
{
|
|
757
|
+
message : 'Contact syncing to Attentive segments has not shipped yet. Nothing is being sent to Attentive right now.',
|
|
758
|
+
title : 'Subscriber sync not available yet',
|
|
759
|
+
type : 'warning'
|
|
760
|
+
}
|
|
761
|
+
],
|
|
762
|
+
title : 'Attentive'
|
|
763
|
+
};
|
|
764
|
+
|
|
522
765
|
// Drawbridge, exported from the brand kit and left as authored — the fills are the
|
|
523
766
|
// vendor's own mark, not a recolour.
|
|
524
767
|
//
|
|
@@ -2144,8 +2387,68 @@ var shopify = {
|
|
|
2144
2387
|
// variant and arrives with it, so there is nothing for prices to answer
|
|
2145
2388
|
// that products does not already.
|
|
2146
2389
|
prices : false,
|
|
2147
|
-
|
|
2148
|
-
|
|
2390
|
+
|
|
2391
|
+
// WHAT THE VENDOR ANSWERS, shaped for a picker. Both of these were api
|
|
2392
|
+
// ROUTES — /organization/:organization/shopify/products and
|
|
2393
|
+
// .../connection/:id/shopify/discounts — vendor-named urls in a service
|
|
2394
|
+
// that is supposed to have none, reachable only by knowing the path.
|
|
2395
|
+
// They are the same two questions every other vendor answers through
|
|
2396
|
+
// resources.*, so they answer them the same way now.
|
|
2397
|
+
//
|
|
2398
|
+
// `shopify` is INJECTED: this package cannot import @drawbridge/shopify,
|
|
2399
|
+
// which depends on it. What arrives is the SDK's pure HTTP namespaces
|
|
2400
|
+
// and nothing else — no controller, no collection access. Resolving the
|
|
2401
|
+
// credential is the caller's job because it is Drawbridge's job: the
|
|
2402
|
+
// admin token refreshes and writes itself back, which is service work,
|
|
2403
|
+
// not vendor work.
|
|
2404
|
+
products : async ({ cursor, limit = 100, search, settings, shopify, sort }) => {
|
|
2405
|
+
|
|
2406
|
+
const products = await shopify.storefront.getProducts({
|
|
2407
|
+
cursor,
|
|
2408
|
+
domain : settings?.domain,
|
|
2409
|
+
limit : Number( limit ),
|
|
2410
|
+
search : search?.value || null,
|
|
2411
|
+
sort,
|
|
2412
|
+
storefrontAccessToken : settings?.storefrontAccessToken
|
|
2413
|
+
});
|
|
2414
|
+
|
|
2415
|
+
return {
|
|
2416
|
+
items : ( products?.edges || [] ).map( ( edge ) => edge.node ),
|
|
2417
|
+
pageInfo : {
|
|
2418
|
+
endCursor : products?.pageInfo?.endCursor || null,
|
|
2419
|
+
hasNextPage : Boolean( products?.pageInfo?.hasNextPage ),
|
|
2420
|
+
hasPreviousPage : Boolean( products?.pageInfo?.hasPreviousPage ),
|
|
2421
|
+
startCursor : products?.pageInfo?.startCursor || null
|
|
2422
|
+
}
|
|
2423
|
+
};
|
|
2424
|
+
|
|
2425
|
+
},
|
|
2426
|
+
|
|
2427
|
+
promotions : async ({ cursor, limit = 100, search, settings, shopify }) => {
|
|
2428
|
+
|
|
2429
|
+
const discounts = await shopify.admin.getDiscounts({
|
|
2430
|
+
adminAccessToken : settings?.adminAccessToken,
|
|
2431
|
+
cursor,
|
|
2432
|
+
domain : settings?.domain,
|
|
2433
|
+
limit : Number( limit ),
|
|
2434
|
+
search : search?.value || null
|
|
2435
|
+
});
|
|
2436
|
+
|
|
2437
|
+
return {
|
|
2438
|
+
// The GLOBAL id is what Shopify returns and the bare id is what a
|
|
2439
|
+
// picker stores, which is why the tail is taken here rather than by
|
|
2440
|
+
// each caller that happened to remember.
|
|
2441
|
+
items : ( discounts?.edges || [] ).map( ( edge ) => ({
|
|
2442
|
+
id : String( edge?.node?.id || '' ).split( '/' ).pop(),
|
|
2443
|
+
title : edge?.node?.codeDiscount?.title
|
|
2444
|
+
}) ),
|
|
2445
|
+
pageInfo : {
|
|
2446
|
+
endCursor : discounts?.pageInfo?.endCursor || null,
|
|
2447
|
+
hasNextPage : Boolean( discounts?.pageInfo?.hasNextPage )
|
|
2448
|
+
}
|
|
2449
|
+
};
|
|
2450
|
+
|
|
2451
|
+
}
|
|
2149
2452
|
}
|
|
2150
2453
|
,
|
|
2151
2454
|
|
|
@@ -2945,6 +3248,7 @@ const stepLabels = ( catalog = connections ) => Object.fromEntries(
|
|
|
2945
3248
|
);
|
|
2946
3249
|
|
|
2947
3250
|
const connections = Object.freeze({
|
|
3251
|
+
attentive : build( attentive ),
|
|
2948
3252
|
drawbridge : build( drawbridge ),
|
|
2949
3253
|
hubspot : build( hubspot ),
|
|
2950
3254
|
klaviyo : build( klaviyo ),
|
|
@@ -3140,6 +3444,39 @@ const stepQueues = ( env = {} ) => Object.fromEntries(
|
|
|
3140
3444
|
connectionSteps( env ).map( ( step ) => [ step.type, step.queue ] )
|
|
3141
3445
|
);
|
|
3142
3446
|
|
|
3447
|
+
// THE WHOLE ROUTING TABLE: live step types plus the retired ones still stored
|
|
3448
|
+
// on workflow documents.
|
|
3449
|
+
//
|
|
3450
|
+
// Both halves were already facts here — stepQueues answers new→queue and
|
|
3451
|
+
// RETIRED answers old→new — but the composition of the two lived in sync as a
|
|
3452
|
+
// hand-written block of `step.shopify.* : 'connection'` literals. That block
|
|
3453
|
+
// and this file had to be edited together and nothing said so, which is the
|
|
3454
|
+
// exact shape of the drift that orphans a queue: retire a step type here,
|
|
3455
|
+
// forget the literal there, and the dispatcher logs unknown-step-type while
|
|
3456
|
+
// the work silently stops.
|
|
3457
|
+
//
|
|
3458
|
+
// A retired type routes wherever its REPLACEMENT routes, because that is what
|
|
3459
|
+
// retiring meant — same work, new name. So there is no second table to keep;
|
|
3460
|
+
// moving a live step to a different queue moves its aliases with it.
|
|
3461
|
+
//
|
|
3462
|
+
// Retired entries whose replacement is not currently live (a vendor gated off
|
|
3463
|
+
// by env) are omitted rather than guessed: no queue exists to route them to,
|
|
3464
|
+
// and a made-up destination is worse than a clean unknown-step-type.
|
|
3465
|
+
const stepRoutes = ( env = {} ) => {
|
|
3466
|
+
|
|
3467
|
+
const live = stepQueues( env );
|
|
3468
|
+
|
|
3469
|
+
return Object.freeze({
|
|
3470
|
+
...live,
|
|
3471
|
+
...Object.fromEntries(
|
|
3472
|
+
Object.entries( RETIRED )
|
|
3473
|
+
.filter( ( [ , replacement ] ) => live[ replacement ] )
|
|
3474
|
+
.map( ( [ retired, replacement ] ) => [ retired, live[ replacement ] ] )
|
|
3475
|
+
)
|
|
3476
|
+
});
|
|
3477
|
+
|
|
3478
|
+
};
|
|
3479
|
+
|
|
3143
3480
|
// Merchant-facing scope-drift copy.
|
|
3144
3481
|
//
|
|
3145
3482
|
// THIS IS A CROSS-REPO CONTRACT. drawbridge-sync writes it onto the connection
|
|
@@ -3277,4 +3614,4 @@ const resolveConnection = ( item, data, env = {} ) => {
|
|
|
3277
3614
|
|
|
3278
3615
|
};
|
|
3279
3616
|
|
|
3280
|
-
export { AUTH_TYPES, GROUPS, HOOKS, HOOK_NAMES, INPUTS, OAUTH_FIELDS, OUTCOMES, RETIRED, STATUSES, STEPS, STEP_TYPES, accessToken, authToken, availableConnections, build, catalogConnections, connectFields, connectionSteps, connections, hookSupport, isStale, mergeSettings, projectConnection, publicConnectionKeys, publicSettingsBySlug, redactSettings, resolveConnection, runHook, scopesMessage, stepLabels, stepQueues, tokenSettings };
|
|
3617
|
+
export { AUTH_TYPES, GROUPS, HOOKS, HOOK_NAMES, INPUTS, OAUTH_FIELDS, OUTCOMES, RETIRED, STATUSES, STEPS, STEP_TYPES, accessToken, authToken, availableConnections, build, catalogConnections, connectFields, connectionSteps, connections, hookSupport, isStale, mergeSettings, projectConnection, publicConnectionKeys, publicSettingsBySlug, redactSettings, resolveConnection, runHook, scopesMessage, stepLabels, stepQueues, stepRoutes, tokenSettings };
|