@zackbart/connecta 0.36.0 → 0.36.2
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/CHANGELOG.md +55 -0
- package/README.md +1 -1
- package/bin/version.mjs +1 -1
- package/dist/auth/downstream-oauth.js +3 -0
- package/dist/auth/oauth-authorization-params.js +52 -0
- package/dist/auth/static-oauth.js +1 -4
- package/dist/connectors/option-shapes.js +1 -0
- package/dist/connectors/remote-mcp.d.ts +4 -1
- package/dist/connectors/remote-mcp.js +12 -1
- package/dist/google.d.ts +13 -0
- package/dist/google.js +42 -0
- package/dist/http/hatch-paging.js +2 -2
- package/dist/http/paging.js +3 -88
- package/dist/http/provider.js +1 -2
- package/dist/http/tools.js +1 -23
- package/dist/program-writes.js +0 -1
- package/dist/providers/_shared/google/service-account.d.ts +1 -1
- package/dist/providers/_shared/google/service-account.js +20 -8
- package/dist/providers/_shared/sensitive-fields.js +0 -16
- package/dist/providers/breeze/api.js +2 -2
- package/dist/providers/ccb/api.js +1 -1
- package/dist/providers/cloudflare/api.js +8 -8
- package/dist/providers/cloudflare/lib/config.d.ts +2 -1
- package/dist/providers/docs/api.js +1 -1
- package/dist/providers/drive/api.js +1 -1
- package/dist/providers/drive/lib/hatch.js +1 -1
- package/dist/providers/drive/tools.js +1 -1
- package/dist/providers/forms/api.js +1 -1
- package/dist/providers/forms/lib/hatch.js +1 -1
- package/dist/providers/forms/tools.js +1 -1
- package/dist/providers/github/api.js +1 -1
- package/dist/providers/github/lib/discovery.js +2 -2
- package/dist/providers/gmail/api.js +1 -1
- package/dist/providers/granola/api.js +155 -0
- package/dist/providers/granola/index.d.ts +10 -0
- package/dist/providers/granola/index.js +68 -0
- package/dist/providers/granola/openapi.generated.js +30 -0
- package/dist/providers/granola/safety.js +37 -0
- package/dist/providers/granola/skill.generated.js +5 -0
- package/dist/providers/granola/tools.js +2 -0
- package/dist/providers/overflow/api.js +26 -26
- package/dist/providers/planning-center/api.js +4 -4
- package/dist/providers/planning-center/lib/constants.d.ts +1 -1
- package/dist/providers/planning-center/lib/json-api.js +2 -2
- package/dist/providers/quickbooks/lib/query.js +1 -1
- package/dist/providers/quickbooks/safety.js +1 -1
- package/dist/providers/sheets/api.js +1 -1
- package/dist/providers/sheets/lib/hatch.js +2 -2
- package/dist/providers/sheets/lib/requests.js +1 -1
- package/dist/providers/slides/api.js +1 -1
- package/dist/providers/stripe/api.js +7 -7
- package/dist/providers/tithely/api.js +2 -2
- package/dist/providers/vercel/api.js +12 -12
- package/dist/providers/vercel/lib/pin.js +1 -1
- package/dist/request-token.d.ts +7 -0
- package/dist/request-token.js +1 -0
- package/dist/routes/mcp.js +1 -1
- package/dist/runtime/admission.js +0 -12
- package/dist/storage/keys.js +2 -3
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/documentation/README.md +13 -12
- package/documentation/architecture.md +148 -76
- package/documentation/auth.md +198 -4
- package/documentation/code-mode.md +6 -6
- package/documentation/meta-tools.md +5 -2
- package/documentation/operator-tests.md +11 -2
- package/documentation/operator-ui.md +1 -2
- package/documentation/providers.md +110 -0
- package/package.json +10 -2
- package/templates/node/package.json +1 -1
|
@@ -314,7 +314,7 @@ export const getContributions = get("getContributions", "/contributions", {
|
|
|
314
314
|
},
|
|
315
315
|
success: GetContributionsResponse,
|
|
316
316
|
}).annotate(Summary, "List contributions (gifts), filtered by campaign, campus, status and dates");
|
|
317
|
-
|
|
317
|
+
const chargeCashPaymentMethod = post("chargeCashPaymentMethod", "/contributions", {
|
|
318
318
|
payload: ChargeCashPaymentMethodParams,
|
|
319
319
|
success: ChargeCashPaymentMethodResponse,
|
|
320
320
|
}).annotate(Summary, "Charge a donor's saved card, bank or wallet payment method for a cash gift");
|
|
@@ -322,7 +322,7 @@ export const getContributionById = get("getContributionById", "/contributions/:c
|
|
|
322
322
|
params: { "contributionId": Schema.String.pipe(Schema.annotateKey({ description: "contribution id." })) },
|
|
323
323
|
success: GetContributionResponse,
|
|
324
324
|
}).annotate(Summary, "Retrieve one contribution (gift) and its donor, campaign and settlement status");
|
|
325
|
-
|
|
325
|
+
const initiateRefund = post("initiateRefund", "/contributions/:contributionId/initiate-refund", {
|
|
326
326
|
params: {
|
|
327
327
|
"contributionId": Schema.String.pipe(Schema.annotateKey({ description: "The Id of the contribution to refund." })),
|
|
328
328
|
},
|
|
@@ -372,7 +372,7 @@ export const getRefunds = get("getRefunds", "/refunds", {
|
|
|
372
372
|
},
|
|
373
373
|
success: GetRefundsResponse,
|
|
374
374
|
}).annotate(Summary, "List refunds with contribution and deposit joins and cent amounts");
|
|
375
|
-
|
|
375
|
+
const getRefundById = get("getRefundById", "/refunds/:refundId", {
|
|
376
376
|
params: { "refundId": Schema.String.pipe(Schema.annotateKey({ description: "refund id." })) },
|
|
377
377
|
success: GetRefundResponse,
|
|
378
378
|
}).annotate(Summary, "Retrieve one refund and its contribution, status and cent amounts");
|
|
@@ -387,11 +387,11 @@ export const getChargebacks = get("getChargebacks", "/chargebacks", {
|
|
|
387
387
|
},
|
|
388
388
|
success: GetChargebacksResponse,
|
|
389
389
|
}).annotate(Summary, "List card disputes and ACH returns (chargebacks)");
|
|
390
|
-
|
|
390
|
+
const getChargebackById = get("getChargebackById", "/chargebacks/:chargebackId", {
|
|
391
391
|
params: { "chargebackId": Schema.String.pipe(Schema.annotateKey({ description: "chargeback id." })) },
|
|
392
392
|
success: GetChargebackResponse,
|
|
393
393
|
}).annotate(Summary, "Retrieve one chargeback (card dispute or ACH return)");
|
|
394
|
-
|
|
394
|
+
const getWebhooks = get("getWebhooks", "/webhooks", {
|
|
395
395
|
query: {
|
|
396
396
|
"limit": Schema.optionalKey(Schema.Finite.check(Schema.isGreaterThanOrEqualTo(1), Schema.isLessThanOrEqualTo(100))).pipe(Schema.annotateKey({ description: "The number of webhook subscriptions to return." })),
|
|
397
397
|
"page": Schema.optionalKey(Schema.Finite.check(Schema.isGreaterThanOrEqualTo(1))).pipe(Schema.annotateKey({ description: "The page number of webhook subscriptions to return." })),
|
|
@@ -402,11 +402,11 @@ export const getWebhooks = get("getWebhooks", "/webhooks", {
|
|
|
402
402
|
},
|
|
403
403
|
success: GetWebhooksResponse,
|
|
404
404
|
}).annotate(Summary, "List webhook subscriptions, destinations and enabled event names");
|
|
405
|
-
|
|
405
|
+
const getWebhookById = get("getWebhookById", "/webhooks/:webhookId", {
|
|
406
406
|
params: { "webhookId": Schema.String.pipe(Schema.annotateKey({ description: "webhook id." })) },
|
|
407
407
|
success: GetWebhookResponse,
|
|
408
408
|
}).annotate(Summary, "Retrieve one webhook subscription and its delivery destination");
|
|
409
|
-
|
|
409
|
+
const getWebhookEventLogs = get("getWebhookEventLogs", "/webhooks/:webhookId/event-logs", {
|
|
410
410
|
params: { "webhookId": Schema.String.pipe(Schema.annotateKey({ description: "webhook id." })) },
|
|
411
411
|
query: {
|
|
412
412
|
"limit": Schema.optionalKey(Schema.Finite.check(Schema.isGreaterThanOrEqualTo(1), Schema.isLessThanOrEqualTo(50))).pipe(Schema.annotateKey({ description: "The number of webhook event logs to return." })),
|
|
@@ -467,7 +467,7 @@ export const getDonorProfiles = get("getDonorProfiles", "/donors", {
|
|
|
467
467
|
},
|
|
468
468
|
success: GetDonorsResponse,
|
|
469
469
|
}).annotate(Summary, "List donor profiles, contact information and giving counts");
|
|
470
|
-
|
|
470
|
+
const createDonorProfile = post("createDonorProfile", "/donors", {
|
|
471
471
|
payload: CreateDonorProfileParams,
|
|
472
472
|
success: CreateDonorProfileResponse,
|
|
473
473
|
}).annotate(Summary, "Create a donor profile for a nonprofit");
|
|
@@ -475,12 +475,12 @@ export const getDonorProfile = get("getDonorProfile", "/donors/:donorId", {
|
|
|
475
475
|
params: { "donorId": Schema.String.pipe(Schema.annotateKey({ description: "The ID of the donor to fetch." })) },
|
|
476
476
|
success: GetDonorResponse,
|
|
477
477
|
}).annotate(Summary, "Retrieve a donor profile, phone, address and giving counts");
|
|
478
|
-
|
|
478
|
+
const updateDonorProfile = patch("updateDonorProfile", "/donors/:donorId", {
|
|
479
479
|
params: { "donorId": Schema.String.pipe(Schema.annotateKey({ description: "The ID of the donor to update." })) },
|
|
480
480
|
payload: UpdateDonorProfileParams,
|
|
481
481
|
success: Schema.Unknown,
|
|
482
482
|
}).annotate(Summary, "Update (edit) a donor's name, email or phone");
|
|
483
|
-
|
|
483
|
+
const createSubscription = post("createSubscription", "/subscriptions/:donorId", {
|
|
484
484
|
params: {
|
|
485
485
|
"donorId": Schema.String.pipe(Schema.annotateKey({ description: "The Id of the donor to create the subscription for." })),
|
|
486
486
|
},
|
|
@@ -526,14 +526,14 @@ export const getSubscriptions = get("getSubscriptions", "/subscriptions", {
|
|
|
526
526
|
},
|
|
527
527
|
success: GetSubscriptionsResponse,
|
|
528
528
|
}).annotate(Summary, "List recurring gifts (subscriptions) across donors");
|
|
529
|
-
|
|
529
|
+
const getSubscriptionById = get("getSubscriptionById", "/subscriptions/:donorId/:subscriptionId", {
|
|
530
530
|
params: {
|
|
531
531
|
"donorId": Schema.String.pipe(Schema.annotateKey({ description: "The Id of the donor to get the subscription for." })),
|
|
532
532
|
"subscriptionId": Schema.String.pipe(Schema.annotateKey({ description: "The Id of the subscription to get." })),
|
|
533
533
|
},
|
|
534
534
|
success: GetSubscriptionResponse,
|
|
535
535
|
}).annotate(Summary, "Retrieve one donor's recurring gift and payment schedule");
|
|
536
|
-
|
|
536
|
+
const updateSubscriptionById = patch("updateSubscriptionById", "/subscriptions/:donorId/:subscriptionId", {
|
|
537
537
|
params: {
|
|
538
538
|
"donorId": Schema.String.pipe(Schema.annotateKey({ description: "The Id of the donor to update the subscription for." })),
|
|
539
539
|
"subscriptionId": Schema.String.pipe(Schema.annotateKey({ description: "The Id of the subscription to update." })),
|
|
@@ -541,7 +541,7 @@ export const updateSubscriptionById = patch("updateSubscriptionById", "/subscrip
|
|
|
541
541
|
payload: UpdateSubscriptionRequest,
|
|
542
542
|
success: Schema.Unknown,
|
|
543
543
|
}).annotate(Summary, "Update a recurring gift, payment method, schedule or dollar amount");
|
|
544
|
-
|
|
544
|
+
const cancelSubscription = del("cancelSubscription", "/subscriptions/:donorId/:subscriptionId", {
|
|
545
545
|
params: {
|
|
546
546
|
"donorId": Schema.String.pipe(Schema.annotateKey({ description: "The Id of the donor to cancel the subscription for." })),
|
|
547
547
|
"subscriptionId": Schema.String.pipe(Schema.annotateKey({ description: "The Id of the subscription to cancel." })),
|
|
@@ -584,7 +584,7 @@ export const getCampaigns = get("getCampaigns", "/campaigns", {
|
|
|
584
584
|
},
|
|
585
585
|
success: GetCampaignsResponse,
|
|
586
586
|
}).annotate(Summary, "List campaigns and subcampaigns, with parent and giving relationships");
|
|
587
|
-
|
|
587
|
+
const getCampaignById = get("getCampaignById", "/campaigns/:campaignId", {
|
|
588
588
|
params: {
|
|
589
589
|
"campaignId": Schema.String.pipe(Schema.annotateKey({ description: "The Id of the campaign/subcampaign to get." })),
|
|
590
590
|
},
|
|
@@ -600,15 +600,15 @@ export const getLocations = get("getLocations", "/locations", {
|
|
|
600
600
|
},
|
|
601
601
|
success: GetLocationsResponse,
|
|
602
602
|
}).annotate(Summary, "List nonprofit locations (campuses)");
|
|
603
|
-
|
|
603
|
+
const getLocationById = get("getLocationById", "/locations/:locationId", {
|
|
604
604
|
params: { "locationId": Schema.String.pipe(Schema.annotateKey({ description: "The Id of the location to get." })) },
|
|
605
605
|
success: GetLocationByIdResponse,
|
|
606
606
|
}).annotate(Summary, "Retrieve a nonprofit location (campus)");
|
|
607
|
-
|
|
607
|
+
const authorizePayment = post("authorizePayment", "/payments/authorize", {
|
|
608
608
|
payload: AuthorizePaymentRequest,
|
|
609
609
|
success: AuthorizePaymentResponse,
|
|
610
610
|
}).annotate(Summary, "Authorize a payment, or save a payment method with zero amountInCents");
|
|
611
|
-
|
|
611
|
+
const getDestinations = get("getDestinations", "/tap/destinations", {
|
|
612
612
|
query: {
|
|
613
613
|
"limit": Schema.optionalKey(Schema.Finite.check(Schema.isGreaterThanOrEqualTo(1), Schema.isLessThanOrEqualTo(100))).pipe(Schema.annotateKey({ description: "The number of tap destinations to return." })),
|
|
614
614
|
"page": Schema.optionalKey(Schema.Finite.check(Schema.isGreaterThanOrEqualTo(1))).pipe(Schema.annotateKey({ description: "The page number of the tap destinations to return." })),
|
|
@@ -620,13 +620,13 @@ export const getDestinations = get("getDestinations", "/tap/destinations", {
|
|
|
620
620
|
},
|
|
621
621
|
success: GetTapDestinationsResponse,
|
|
622
622
|
}).annotate(Summary, "List Tap-to-give destinations and configured URLs or messages");
|
|
623
|
-
|
|
623
|
+
const getDestinationById = get("getDestinationById", "/tap/destinations/:destinationId", {
|
|
624
624
|
params: {
|
|
625
625
|
"destinationId": Schema.String.pipe(Schema.annotateKey({ description: "The ID of the tap destination." })),
|
|
626
626
|
},
|
|
627
627
|
success: GetTapDestinationByIdResponse,
|
|
628
628
|
}).annotate(Summary, "Retrieve a Tap-to-give destination URL or message");
|
|
629
|
-
|
|
629
|
+
const getDevices = get("getDevices", "/tap/devices", {
|
|
630
630
|
query: {
|
|
631
631
|
"limit": Schema.optionalKey(Schema.Finite.check(Schema.isGreaterThanOrEqualTo(1), Schema.isLessThanOrEqualTo(100))).pipe(Schema.annotateKey({ description: "The number of tap devices to return." })),
|
|
632
632
|
"page": Schema.optionalKey(Schema.Finite.check(Schema.isGreaterThanOrEqualTo(1))).pipe(Schema.annotateKey({ description: "The page number of the tap devices to return." })),
|
|
@@ -657,11 +657,11 @@ export const getDevices = get("getDevices", "/tap/devices", {
|
|
|
657
657
|
},
|
|
658
658
|
success: GetTapDevicesResponse,
|
|
659
659
|
}).annotate(Summary, "List Tap-to-give devices, groups and current destinations");
|
|
660
|
-
|
|
660
|
+
const getDeviceById = get("getDeviceById", "/tap/devices/:deviceId", {
|
|
661
661
|
params: { "deviceId": Schema.String.pipe(Schema.annotateKey({ description: "The ID of the tap device." })) },
|
|
662
662
|
success: GetTapDeviceByIdResponse,
|
|
663
663
|
}).annotate(Summary, "Retrieve a Tap-to-give device and its current destination");
|
|
664
|
-
|
|
664
|
+
const getEvents = get("getEvents", "/tap/events", {
|
|
665
665
|
query: {
|
|
666
666
|
"limit": Schema.optionalKey(Schema.Finite.check(Schema.isGreaterThanOrEqualTo(1), Schema.isLessThanOrEqualTo(100))).pipe(Schema.annotateKey({ description: "The number of tap events to return." })),
|
|
667
667
|
"page": Schema.optionalKey(Schema.Finite.check(Schema.isGreaterThanOrEqualTo(1))).pipe(Schema.annotateKey({ description: "The page number of the tap events to return." })),
|
|
@@ -682,7 +682,7 @@ export const getEvents = get("getEvents", "/tap/events", {
|
|
|
682
682
|
},
|
|
683
683
|
success: GetTapEventsResponse,
|
|
684
684
|
}).annotate(Summary, "List Tap-to-give engagement events (taps, not donations)");
|
|
685
|
-
|
|
685
|
+
const getGroups = get("getGroups", "/tap/groups", {
|
|
686
686
|
query: {
|
|
687
687
|
"limit": Schema.optionalKey(Schema.Finite.check(Schema.isGreaterThanOrEqualTo(1), Schema.isLessThanOrEqualTo(100))).pipe(Schema.annotateKey({ description: "The number of tap groups to return." })),
|
|
688
688
|
"page": Schema.optionalKey(Schema.Finite.check(Schema.isGreaterThanOrEqualTo(1))).pipe(Schema.annotateKey({ description: "The page number of the tap groups to return." })),
|
|
@@ -693,11 +693,11 @@ export const getGroups = get("getGroups", "/tap/groups", {
|
|
|
693
693
|
},
|
|
694
694
|
success: GetTapGroupsResponse,
|
|
695
695
|
}).annotate(Summary, "List Tap-to-give device groups");
|
|
696
|
-
|
|
696
|
+
const getGroupById = get("getGroupById", "/tap/groups/:groupId", {
|
|
697
697
|
params: { "groupId": Schema.String.pipe(Schema.annotateKey({ description: "The ID of the tap group." })) },
|
|
698
698
|
success: GetTapGroupByIdResponse,
|
|
699
699
|
}).annotate(Summary, "Retrieve a Tap-to-give group and its devices and destination");
|
|
700
|
-
|
|
700
|
+
const health = get("health", "/health", {
|
|
701
701
|
success: Schema.String,
|
|
702
702
|
}).annotate(Summary, "Read the API health text (not an authenticated credential check)");
|
|
703
703
|
export const OverflowApi = {
|
|
@@ -808,7 +808,7 @@ function pageNumber(value) {
|
|
|
808
808
|
throw new ConnectorCallError("invalid_args", "This Overflow cursor contains no valid page number.");
|
|
809
809
|
return page;
|
|
810
810
|
}
|
|
811
|
-
|
|
811
|
+
const overflowPage = {
|
|
812
812
|
param: "page",
|
|
813
813
|
in: "query",
|
|
814
814
|
decode: pageNumber,
|
|
@@ -823,7 +823,7 @@ export const overflowPage = {
|
|
|
823
823
|
return more ? current + 1 : null;
|
|
824
824
|
},
|
|
825
825
|
};
|
|
826
|
-
|
|
826
|
+
const overflowEventPage = {
|
|
827
827
|
param: "cursor",
|
|
828
828
|
in: "query",
|
|
829
829
|
decode(cursor) {
|
|
@@ -13,7 +13,7 @@ import { TABLE } from "./safety.js";
|
|
|
13
13
|
import { excludedApps, series } from "./lib/guide.js";
|
|
14
14
|
import { asRecord, asArray, resources, attribute, pageOf } from "./lib/json-api.js";
|
|
15
15
|
import { PLANNING_CENTER_API_BASE_URL, PLANNING_CENTER_APPS, PLANNING_CENTER_API_VERSIONS, DEFAULT_USER_AGENT, } from "./lib/constants.js";
|
|
16
|
-
export { PLANNING_CENTER_API_BASE_URL, PLANNING_CENTER_APPS, PLANNING_CENTER_API_VERSIONS, MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE, PLANNING_CENTER_MAX_RESPONSE_BYTES, PLANNING_CENTER_ADMISSION,
|
|
16
|
+
export { PLANNING_CENTER_API_BASE_URL, PLANNING_CENTER_APPS, PLANNING_CENTER_API_VERSIONS, MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE, PLANNING_CENTER_MAX_RESPONSE_BYTES, PLANNING_CENTER_ADMISSION, } from "./lib/constants.js";
|
|
17
17
|
export const CREDENTIAL = {
|
|
18
18
|
label: "Planning Center personal access token",
|
|
19
19
|
description: "Create one at api.planningcenteronline.com/oauth/applications → Personal Access Tokens. It acts with the permissions of the user who creates it, in every product that user can open, so create it as a user whose access matches this connection's purpose.",
|
|
@@ -59,7 +59,7 @@ export function isApp(value) {
|
|
|
59
59
|
* normalization the guarded transport applies — so `..` cannot carry a request
|
|
60
60
|
* from `/people/v2` to `/oauth` or anywhere else outside a product.
|
|
61
61
|
*/
|
|
62
|
-
|
|
62
|
+
function appForPath(path, apps) {
|
|
63
63
|
let normalized;
|
|
64
64
|
if (path.startsWith("/") && !path.startsWith("//")) {
|
|
65
65
|
try {
|
|
@@ -269,7 +269,7 @@ export const errors = {
|
|
|
269
269
|
/** All ten product pins retain their own public URL and version. */
|
|
270
270
|
export const PCO_PREFIX = "pco";
|
|
271
271
|
export const PCO_INDEX = new PlanningCenterIndex(openapi);
|
|
272
|
-
|
|
272
|
+
const getPeopleMe = get("getPeopleMe", "/people/v2/me", {
|
|
273
273
|
success: Schema.Unknown,
|
|
274
274
|
query: { include: Schema.String },
|
|
275
275
|
headers: { "X-PCO-API-Version": Schema.String },
|
|
@@ -317,7 +317,7 @@ export const PCO_NAMED = {
|
|
|
317
317
|
"POST /people/v2/people/{person_id}/workflow_cards/{workflow_card_id}/restore": "apply_workflow_card_action",
|
|
318
318
|
};
|
|
319
319
|
/** Native collection offset metadata, read only after response safety. */
|
|
320
|
-
|
|
320
|
+
const pcoPage = {
|
|
321
321
|
param: "offset",
|
|
322
322
|
in: "query",
|
|
323
323
|
total: (data) => pageOf(asRecord(data)).totalCount ?? undefined,
|
|
@@ -55,4 +55,4 @@ export declare const PLANNING_CENTER_MAX_RESPONSE_BYTES: number;
|
|
|
55
55
|
*/
|
|
56
56
|
export declare const PLANNING_CENTER_ADMISSION: ConnectorCallAdmissionPolicy;
|
|
57
57
|
/** Planning Center refuses a request without a descriptive one (HTTP 403). */
|
|
58
|
-
export declare const DEFAULT_USER_AGENT = "connecta/0.36.
|
|
58
|
+
export declare const DEFAULT_USER_AGENT = "connecta/0.36.2 (+https://github.com/zackbart/connecta)";
|
|
@@ -8,7 +8,7 @@ export function asArray(value) {
|
|
|
8
8
|
export function compact(value) {
|
|
9
9
|
return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined));
|
|
10
10
|
}
|
|
11
|
-
|
|
11
|
+
function isResource(value) {
|
|
12
12
|
const record = asRecord(value);
|
|
13
13
|
return typeof record["id"] === "string" && typeof record["type"] === "string";
|
|
14
14
|
}
|
|
@@ -22,7 +22,7 @@ export function indexIncluded(document) {
|
|
|
22
22
|
}
|
|
23
23
|
return index;
|
|
24
24
|
}
|
|
25
|
-
|
|
25
|
+
function relationshipData(resource, name) {
|
|
26
26
|
return resource.relationships?.[name]?.data;
|
|
27
27
|
}
|
|
28
28
|
/** The related id, `null` when Planning Center says there is none. */
|
|
@@ -123,7 +123,7 @@ function pick(value, keys) {
|
|
|
123
123
|
return Object.fromEntries(keys.flatMap((key) => source[key] === undefined || scalar(source[key]) === undefined ? [] : [[key, scalar(source[key])]]));
|
|
124
124
|
}
|
|
125
125
|
/** Closed accounting projection: unknown fields never become a way around privacy. SyncToken is a version, not a credential. */
|
|
126
|
-
|
|
126
|
+
function safeRecord(value) {
|
|
127
127
|
const source = object(value), out = pick(source, scalars);
|
|
128
128
|
for (const key of references)
|
|
129
129
|
if (source[key])
|
|
@@ -15,7 +15,7 @@ export const SHEETS = {
|
|
|
15
15
|
};
|
|
16
16
|
const SpreadsheetId = { spreadsheetId: Schema.String };
|
|
17
17
|
const optionalString = Schema.optionalKey(Schema.String);
|
|
18
|
-
|
|
18
|
+
const getSpreadsheet = get("getSpreadsheet", "/spreadsheets/:spreadsheetId", {
|
|
19
19
|
params: SpreadsheetId,
|
|
20
20
|
query: { includeGridData: optionalString, fields: optionalString },
|
|
21
21
|
success: Schema.Unknown,
|
|
@@ -23,7 +23,7 @@ export const sheetsIndex = new OperationIndex(sheetsDiscovery, {
|
|
|
23
23
|
pathMatching: "uri-template",
|
|
24
24
|
});
|
|
25
25
|
/** Decode range colons only. Encoded actions, ids and unreserved bytes still fail the shared backstop. */
|
|
26
|
-
|
|
26
|
+
function sheetsPath(path) {
|
|
27
27
|
const match = /^(\/spreadsheets\/[A-Za-z0-9_-]+\/values\/)([^/?#]+)$/.exec(path);
|
|
28
28
|
if (!match)
|
|
29
29
|
return path;
|
|
@@ -37,7 +37,7 @@ export function sheetsPath(path) {
|
|
|
37
37
|
}
|
|
38
38
|
const record = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
39
39
|
/** Same scalar, range and write-cell ceilings as the named workflows, including filter-selected writes. */
|
|
40
|
-
|
|
40
|
+
function sheetsRequestProblem(call) {
|
|
41
41
|
const body = record(call.body);
|
|
42
42
|
if (call.op.path === "/spreadsheets/{spreadsheetId}:batchUpdate") {
|
|
43
43
|
const requests = body["requests"];
|
|
@@ -23,7 +23,7 @@ const ReadQuery = {
|
|
|
23
23
|
commentsViewMode: Schema.optionalKey(Schema.String),
|
|
24
24
|
};
|
|
25
25
|
// Discovery calls this one parameter `presentationsId` (plural).
|
|
26
|
-
|
|
26
|
+
const getPresentation = get("getPresentation", "/presentations/:presentationsId", {
|
|
27
27
|
params: { presentationsId: Schema.String },
|
|
28
28
|
query: ReadQuery,
|
|
29
29
|
success: Schema.Unknown,
|
|
@@ -115,7 +115,7 @@ export const READ_CAP_MS = 60_000;
|
|
|
115
115
|
* /v1/tax/calculations` is deliberately absent: it persists a Calculation
|
|
116
116
|
* object a later Tax Transaction can reference, and Stripe bills each call.
|
|
117
117
|
*/
|
|
118
|
-
|
|
118
|
+
const READ_POSTS = [
|
|
119
119
|
["POST", "/v1/invoices/create_preview", "Computes an upcoming invoice; Stripe persists nothing."],
|
|
120
120
|
];
|
|
121
121
|
function invalid(message) {
|
|
@@ -126,7 +126,7 @@ function invalid(message) {
|
|
|
126
126
|
* The key's own prefix carries its mode, so a live key in a sandbox
|
|
127
127
|
* connector (or the reverse) is refused before any request leaves.
|
|
128
128
|
*/
|
|
129
|
-
|
|
129
|
+
function stripeKeyProblem(key, mode) {
|
|
130
130
|
if (/^(?:sk|rk)_org_/.test(key)) {
|
|
131
131
|
return "This is a Stripe organization key, which needs a Stripe-Context header this connector does not send. Use one account's secret or restricted key.";
|
|
132
132
|
}
|
|
@@ -213,7 +213,7 @@ function expansions(call) {
|
|
|
213
213
|
* secret's value, or a full Issuing card number or CVC, which an Issuing
|
|
214
214
|
* authorization, transaction, or token can embed as well as the card itself.
|
|
215
215
|
*/
|
|
216
|
-
|
|
216
|
+
function refuse(call) {
|
|
217
217
|
const expanded = expansions(call);
|
|
218
218
|
if (/^\/v1\/apps\/secrets(?:\/|$)/.test(call.path) && expanded.some((path) => /(?:^|\.)payload$/.test(path))) {
|
|
219
219
|
return "Stripe Apps secret values are not returned through Connecta. Read the secret's metadata without expanding payload.";
|
|
@@ -225,7 +225,7 @@ export function refuse(call) {
|
|
|
225
225
|
return undefined;
|
|
226
226
|
}
|
|
227
227
|
export const stripeIndex = new OperationIndex(openapi, { vendor: "stripe", title: "Stripe" });
|
|
228
|
-
|
|
228
|
+
const stripeSafety = valueSafety(STRIPE_VALUE_SAFETY, () => stripeIndex);
|
|
229
229
|
function operationRefusal(op) {
|
|
230
230
|
return (checkServer(op.server) ??
|
|
231
231
|
stripeSafety.refusal(op.method, op.path) ??
|
|
@@ -268,11 +268,11 @@ export const safety = () => ({
|
|
|
268
268
|
reviewed: restSafety(stripeSafety, stripeIndex),
|
|
269
269
|
sensitiveFields: { names: [], choice: "drop" },
|
|
270
270
|
});
|
|
271
|
-
|
|
271
|
+
const getAccount = get("getAccount", "/v1/account", {
|
|
272
272
|
headers: Schema.Struct({ "Stripe-Account": Schema.optionalKey(Schema.String) }),
|
|
273
273
|
success: Schema.Unknown,
|
|
274
274
|
});
|
|
275
|
-
|
|
275
|
+
const getBalance = get("getBalance", "/v1/balance", { success: Schema.Unknown });
|
|
276
276
|
const RESPONSE_MEDIA = { "GET /v1/quotes/{quote}/pdf": ["application/pdf"] };
|
|
277
277
|
export const StripeApi = {
|
|
278
278
|
...indexedVendor("stripe", stripeIndex, [getAccount, getBalance]),
|
|
@@ -317,7 +317,7 @@ export function connectedAccount(options) {
|
|
|
317
317
|
throw new Error('stripe() connectedAccount must be a Stripe account id ("acct_...").');
|
|
318
318
|
return account;
|
|
319
319
|
}
|
|
320
|
-
|
|
320
|
+
function checkServer(server) {
|
|
321
321
|
if (server === undefined || server === FILES_ORIGIN)
|
|
322
322
|
return undefined;
|
|
323
323
|
return server === METER_EVENTS_ORIGIN
|
|
@@ -162,7 +162,7 @@ export const listOrganizations = get("listOrganizations", "/organizations-list",
|
|
|
162
162
|
query: PageQuery,
|
|
163
163
|
success: Rows(OrganizationRecord),
|
|
164
164
|
}).annotate(Summary, "List all organizations these keys manage");
|
|
165
|
-
|
|
165
|
+
const getOrganization = get("getOrganization", "/organizations/:organization_id", {
|
|
166
166
|
params: id("organization_id"),
|
|
167
167
|
success: Single("organization_id", OrganizationRecord),
|
|
168
168
|
}).annotate(Summary, "Retrieve an organization");
|
|
@@ -174,7 +174,7 @@ export const listAllAccounts = get("listAllAccounts", "/accounts-list-all", {
|
|
|
174
174
|
query: PageQuery,
|
|
175
175
|
success: Rows(AccountRecord),
|
|
176
176
|
}).annotate(Summary, "List all donor accounts");
|
|
177
|
-
|
|
177
|
+
const getAccount = get("getAccount", "/accounts/:account_id", {
|
|
178
178
|
params: id("account_id"),
|
|
179
179
|
success: Single("account_id", AccountRecord),
|
|
180
180
|
}).annotate(Summary, "Retrieve a donor account");
|
|
@@ -17,7 +17,7 @@ import { pinAdmission, pinOptions, pinQuery, pinRoute, readPinnedTeam } from "./
|
|
|
17
17
|
export const MAX_RESPONSE_BYTES = 8 * 1024 * 1024;
|
|
18
18
|
export const READ_CAP_MS = 60_000;
|
|
19
19
|
/** POSTs that only read, admitted by `vercel_api_read`. */
|
|
20
|
-
|
|
20
|
+
const READ_POSTS = [
|
|
21
21
|
["POST", "/v2/observability/query", "Runs an Observability metrics query; Vercel persists nothing."],
|
|
22
22
|
["POST", "/v1/registrar/domains/availability", "Checks availability for a list of domains; buys nothing."],
|
|
23
23
|
["POST", "/v1/registrar/domains/price", "Quotes registrar prices for a list of domains; buys nothing."],
|
|
@@ -39,7 +39,7 @@ export function invalid(message) {
|
|
|
39
39
|
export function compact(value) {
|
|
40
40
|
return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined));
|
|
41
41
|
}
|
|
42
|
-
|
|
42
|
+
function truthy(value) {
|
|
43
43
|
return value === true || value === 1 || (typeof value === "string" && /^(?:1|true)$/i.test(value.trim()));
|
|
44
44
|
}
|
|
45
45
|
/**
|
|
@@ -155,34 +155,34 @@ class VercelIndex extends OperationIndex {
|
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
157
|
export const vercelIndex = new VercelIndex(discoveryIndex(openapi), { vendor: "vercel", title: "Vercel" });
|
|
158
|
-
|
|
158
|
+
const vercelSafety = valueSafety(VERCEL_VALUE_SAFETY, () => vercelIndex);
|
|
159
159
|
const Query = Schema.Record(Schema.String, Schema.Union([Schema.String, Schema.Array(Schema.String)]));
|
|
160
160
|
const params = (...names) => Schema.Struct(Object.fromEntries(names.map((name) => [name, Schema.String])));
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
161
|
+
const currentUser = get("currentUser", "/v2/user", { success: Schema.Unknown });
|
|
162
|
+
const teams = get("teams", "/v2/teams", { query: Query, success: Schema.Unknown });
|
|
163
|
+
const projectEnv = get("projectEnv", "/v10/projects/:idOrName/env", {
|
|
164
164
|
params: params("idOrName"),
|
|
165
165
|
query: Query,
|
|
166
166
|
success: Schema.Unknown,
|
|
167
167
|
});
|
|
168
|
-
|
|
168
|
+
const upsertEnv = post("upsertEnv", "/v10/projects/:idOrName/env", {
|
|
169
169
|
params: params("idOrName"),
|
|
170
170
|
query: Query,
|
|
171
171
|
payload: Schema.Unknown,
|
|
172
172
|
success: Schema.Unknown,
|
|
173
173
|
});
|
|
174
|
-
|
|
174
|
+
const updateEnv = patch("updateEnv", "/v9/projects/:idOrName/env/:id", {
|
|
175
175
|
params: params("idOrName", "id"),
|
|
176
176
|
query: Query,
|
|
177
177
|
payload: Schema.Unknown,
|
|
178
178
|
success: Schema.Unknown,
|
|
179
179
|
});
|
|
180
|
-
|
|
180
|
+
const buildLogs = get("buildLogs", "/v3/deployments/:idOrUrl/events", {
|
|
181
181
|
params: params("idOrUrl"),
|
|
182
182
|
query: Query,
|
|
183
183
|
success: Schema.Unknown,
|
|
184
184
|
});
|
|
185
|
-
|
|
185
|
+
const runtimeLogs = get("runtimeLogs", "/v1/projects/:projectId/deployments/:deploymentId/runtime-logs", {
|
|
186
186
|
params: params("projectId", "deploymentId"),
|
|
187
187
|
query: Query,
|
|
188
188
|
success: Schema.Unknown,
|
|
@@ -294,7 +294,7 @@ export const refuse = (call) => {
|
|
|
294
294
|
}
|
|
295
295
|
return undefined;
|
|
296
296
|
};
|
|
297
|
-
|
|
297
|
+
function scope(call, teamId, pin) {
|
|
298
298
|
if (pin)
|
|
299
299
|
return { ...call, query: pinQuery(vercelIndex, call, pin) };
|
|
300
300
|
const query = { ...call.query };
|
|
@@ -374,7 +374,7 @@ export function queryOf(call) {
|
|
|
374
374
|
export function queryPairs(call) {
|
|
375
375
|
return Object.entries(queryOf(call)).flatMap(([key, value]) => (Array.isArray(value) ? value : [value]).map((value) => [key, value]));
|
|
376
376
|
}
|
|
377
|
-
|
|
377
|
+
function sendVercel(connection, call, options, sendOptions) {
|
|
378
378
|
return checked(() => {
|
|
379
379
|
const server = checkServer(call.op.server);
|
|
380
380
|
if (server)
|
|
@@ -34,7 +34,7 @@ const object = (value) => value !== null && typeof value === "object" && !Array.
|
|
|
34
34
|
const fail = (reason) => {
|
|
35
35
|
throw new ConnectorCallError("provider_permission_denied", `Vercel team pin: ${reason} Not sent to the requested resource.`, { retryable: false });
|
|
36
36
|
};
|
|
37
|
-
|
|
37
|
+
function validatePin(options) {
|
|
38
38
|
if (options.pin === undefined)
|
|
39
39
|
return;
|
|
40
40
|
const id = options.pin?.teamId;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ConnectorContext } from "./types.js";
|
|
2
|
+
/** A request-local Bearer resolver with optional cache invalidation on HTTP 401. */
|
|
3
|
+
export interface RequestToken {
|
|
4
|
+
(ctx: ConnectorContext): Promise<string>;
|
|
5
|
+
/** Drop only the rejected token. This hook never authorizes replay. */
|
|
6
|
+
invalidate?: (rejected: string, ctx: ConnectorContext) => Promise<void>;
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/routes/mcp.js
CHANGED
|
@@ -268,7 +268,7 @@ function scopedToBody(handler, signal) {
|
|
|
268
268
|
* The request's admission permit, owned by its Scope.
|
|
269
269
|
*
|
|
270
270
|
* Admission goes through the controller's Promise rather than its Effect
|
|
271
|
-
* program
|
|
271
|
+
* program, on purpose. The pool is shared by every request
|
|
272
272
|
* in the isolate, and a queued request is handed its permit from inside the
|
|
273
273
|
* request whose body just ended. A fiber resumed there would authorize and
|
|
274
274
|
* serve this request in that one's I/O context, which workerd refuses;
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
// read its private bookkeeping, and one that emits nothing into the `.d.ts`.
|
|
8
8
|
// Promise callers keep `acquire()`, which runs the same program through
|
|
9
9
|
// runEdge; Effect callers come through this module and never see a Promise.
|
|
10
|
-
import { Effect } from "effect";
|
|
11
10
|
let program;
|
|
12
11
|
/**
|
|
13
12
|
* Install the controller's admission program. Called once, by
|
|
@@ -32,14 +31,3 @@ export function admit(controller, options = {}) {
|
|
|
32
31
|
}
|
|
33
32
|
return program(controller, options.signal, options.wait !== false);
|
|
34
33
|
}
|
|
35
|
-
/**
|
|
36
|
-
* A lease owned by the enclosing Scope: released when the scope closes, on
|
|
37
|
-
* success, failure, or interruption alike. The wait itself stays
|
|
38
|
-
* interruptible — a queued request whose caller left must not hold its place
|
|
39
|
-
* in line until the queue timeout.
|
|
40
|
-
*/
|
|
41
|
-
export function acquireScoped(controller, options = {}) {
|
|
42
|
-
return Effect.acquireRelease(admit(controller, options), (lease) => Effect.sync(() => lease.release()), {
|
|
43
|
-
interruptible: true,
|
|
44
|
-
});
|
|
45
|
-
}
|
package/dist/storage/keys.js
CHANGED
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
//
|
|
3
3
|
// A deployment has one KVStorage (D1 on Workers, SQLite on Node, memory in
|
|
4
4
|
// tests), and every subsystem shares it. Sharing is safe because no two
|
|
5
|
-
// families claim overlapping keys
|
|
6
|
-
//
|
|
7
|
-
// spells one of these prefixes itself.
|
|
5
|
+
// families claim overlapping keys. Build every key here; persistence journeys
|
|
6
|
+
// check actual isolation through the deployment and its physical database.
|
|
8
7
|
//
|
|
9
8
|
// Each family records:
|
|
10
9
|
//
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const CONNECTA_VERSION = "0.36.
|
|
1
|
+
export declare const CONNECTA_VERSION = "0.36.2";
|
package/dist/version.js
CHANGED
package/documentation/README.md
CHANGED
|
@@ -8,18 +8,19 @@ For a new deployment, start with [Deploying Connecta](./deploying.md).
|
|
|
8
8
|
|
|
9
9
|
## Operator tasks
|
|
10
10
|
|
|
11
|
-
| Task
|
|
12
|
-
|
|
|
13
|
-
| Add or remove a connector
|
|
14
|
-
| Set up a maintained provider
|
|
15
|
-
| Inspect maintained API sources and tools
|
|
16
|
-
| Organize an agent's pools and tiers
|
|
17
|
-
| Add a person (maintainer or pool member)
|
|
18
|
-
| Connect a
|
|
19
|
-
|
|
|
20
|
-
|
|
|
21
|
-
|
|
|
22
|
-
|
|
|
11
|
+
| Task | Self-contained procedure |
|
|
12
|
+
| ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------- |
|
|
13
|
+
| Add or remove a connector | [Change the connector roster](./integrating.md#add-or-remove-a-connector) |
|
|
14
|
+
| Set up a maintained provider | [Maintained provider setup](./providers.md) |
|
|
15
|
+
| Inspect maintained API sources and tools | [API sources and tool inventory](./providers.md#api-sources-and-tool-inventory) |
|
|
16
|
+
| Organize an agent's pools and tiers | [Organizing an agent's pools](./auth.md#organizing-an-agents-pools) |
|
|
17
|
+
| Add a person (maintainer or pool member) | [Add a person](./auth.md#add-a-person), [member page](./operator-ui.md#use-the-member-page) |
|
|
18
|
+
| Connect Google hosted MCP with a service account | [Google tokens and shared-agent/personal-people setup](./auth.md#google-service-account-tokens-and-hosted-mcp) |
|
|
19
|
+
| Connect a shared credential | [Connect a shared credential](./auth.md#connect-a-shared-credential) |
|
|
20
|
+
| Issue, rotate, or revoke an agent token | [Manage an agent token](./auth.md#issue-rotate-or-revoke-an-agent-token) |
|
|
21
|
+
| Upgrade between versions | [Upgrade an existing deployment](./deploying.md#upgrade-an-existing-deployment), including [migration to 0.33](./migration-0.33.md) |
|
|
22
|
+
| Diagnose with `connecta doctor` | [Verify and diagnose](./deploying.md#verify-and-diagnose) |
|
|
23
|
+
| Connect a client with tool search | [Native tool surface](./meta-tools.md#native-tool-surface), [Eve agents](./meta-tools.md#eve-agents) |
|
|
23
24
|
|
|
24
25
|
For removed hosted presets and the former hosted modes of Stripe, Vercel,
|
|
25
26
|
Cloudflare, and GitHub, use [Migrate hosted MCP presets](./hosted-mcp-migration.md).
|