@jskit-ai/connectors-catalog 0.1.67 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1722 -0
- package/README.md +11 -0
- package/locales/en.json +3139 -0
- package/package.json +7 -6
- package/src/server/ai.js +4 -4
- package/src/server/amazon-redshift.js +5 -5
- package/src/server/apify.js +1 -1
- package/src/server/apollo-io.js +1 -1
- package/src/server/asana.js +3 -3
- package/src/server/ashby.js +3 -3
- package/src/server/attention.js +2 -2
- package/src/server/aws-athena.js +3 -3
- package/src/server/aws-s3.js +1 -1
- package/src/server/awsTransport.js +9 -9
- package/src/server/brevo.js +3 -3
- package/src/server/calendly.js +2 -2
- package/src/server/chargebee.js +1 -1
- package/src/server/databricks.js +2 -2
- package/src/server/dbt-semantic-layer.js +8 -8
- package/src/server/elevenlabs.js +4 -4
- package/src/server/firebase-cloud-messaging.js +8 -8
- package/src/server/firecrawl.js +2 -2
- package/src/server/gatewayapi.js +4 -4
- package/src/server/github-api.js +3 -3
- package/src/server/gitlab-api.js +1 -1
- package/src/server/gmail.js +1 -1
- package/src/server/gong.js +4 -4
- package/src/server/google-ads-search.js +16 -16
- package/src/server/google-ads.js +7 -7
- package/src/server/google-drive.js +8 -6
- package/src/server/google-maps-platform.js +5 -5
- package/src/server/google-search-console.js +1 -1
- package/src/server/google-sheets.js +3 -2
- package/src/server/google.js +3 -2
- package/src/server/granola.js +5 -5
- package/src/server/hubspot.js +5 -3
- package/src/server/inngest.js +4 -4
- package/src/server/klipy.js +1 -1
- package/src/server/lightspeed.js +4 -4
- package/src/server/linear.js +2 -2
- package/src/server/linkedin.js +6 -6
- package/src/server/mapbox.js +1 -1
- package/src/server/mcpRegistration.js +3 -2
- package/src/server/mcpTransport.js +1 -1
- package/src/server/microsoft-fabric.js +3 -3
- package/src/server/microsoft-onedrive.js +1 -1
- package/src/server/microsoft-onenote.js +1 -1
- package/src/server/microsoft-outlook.js +1 -1
- package/src/server/microsoft.js +4 -3
- package/src/server/n8n.js +4 -4
- package/src/server/oura.js +1 -1
- package/src/server/paddle.js +1 -1
- package/src/server/pipedrive.js +4 -4
- package/src/server/posthog.js +3 -3
- package/src/server/salesforce.js +8 -8
- package/src/server/semrush.js +25 -25
- package/src/server/shopify.js +6 -6
- package/src/server/slack.js +10 -10
- package/src/server/snowflake.js +5 -5
- package/src/server/tally.js +1 -1
- package/src/server/telegram.js +1 -1
- package/src/server/tiktok.js +14 -14
- package/src/server/twilio.js +3 -3
- package/src/server/twitch.js +22 -21
- package/src/server/wave.js +34 -34
- package/src/server/wix.js +73 -73
- package/src/server/wiz.js +18 -18
- package/src/server/woocommerce.js +23 -23
- package/src/server/wordpress-com.js +3 -3
- package/src/server/wordpress-self-hosted.js +2 -2
- package/src/server/workday.js +3 -3
- package/src/server/x-twitter.js +6 -6
- package/src/server/xero.js +15 -15
- package/src/server/zoho-books.js +8 -8
- package/src/server/zoho-crm.js +5 -5
- package/src/server/zohoOAuth.js +1 -1
- package/src/shared/ai.js +24 -13
- package/src/shared/algolia.js +4 -4
- package/src/shared/amazon-redshift.js +16 -16
- package/src/shared/amplitude.js +6 -6
- package/src/shared/atlassian.js +19 -19
- package/src/shared/aws.js +18 -18
- package/src/shared/canva.js +18 -18
- package/src/shared/chargebee.js +3 -3
- package/src/shared/clickhouse.js +9 -9
- package/src/shared/confidence.js +6 -6
- package/src/shared/databricks.js +8 -8
- package/src/shared/dbt-semantic-layer.js +7 -7
- package/src/shared/english-ai.js +6 -0
- package/src/shared/english-definitions.js +34 -0
- package/src/shared/english-texts.js +7 -0
- package/src/shared/figma.js +2 -2
- package/src/shared/firebase-cloud-messaging.js +11 -11
- package/src/shared/firecrawl.js +1 -1
- package/src/shared/gemini-enterprise.js +7 -7
- package/src/shared/gong.js +5 -5
- package/src/shared/google-ads.js +5 -5
- package/src/shared/google-maps-platform.js +7 -7
- package/src/shared/google.js +40 -40
- package/src/shared/granola.js +5 -5
- package/src/shared/hex.js +7 -7
- package/src/shared/inngest.js +8 -8
- package/src/shared/lightspeed.js +52 -52
- package/src/shared/linkedin.js +6 -6
- package/src/shared/logo-dev.js +3 -3
- package/src/shared/mapbox.js +6 -6
- package/src/shared/mcp.js +9 -9
- package/src/shared/microsoft-fabric.js +9 -9
- package/src/shared/microsoft.js +52 -52
- package/src/shared/miro.js +5 -5
- package/src/shared/oura.js +5 -5
- package/src/shared/posthog.js +9 -9
- package/src/shared/prestashop.js +5 -5
- package/src/shared/resend.js +1 -1
- package/src/shared/salesforce.js +8 -8
- package/src/shared/semrush.js +6 -6
- package/src/shared/shopify.js +26 -26
- package/src/shared/slack.js +61 -61
- package/src/shared/snowflake.js +15 -15
- package/src/shared/tiktok.js +7 -7
- package/src/shared/tokens.js +126 -126
- package/src/shared/twilio.js +7 -7
- package/src/shared/twitch.js +24 -24
- package/src/shared/wave.js +33 -33
- package/src/shared/wix.js +5 -5
- package/src/shared/wiz.js +14 -14
- package/src/shared/wordpress-com.js +9 -9
- package/src/shared/wordpress.js +11 -11
- package/src/shared/workday.js +8 -8
- package/src/shared/x-twitter.js +5 -5
- package/src/shared/xero.js +25 -25
- package/src/shared/zoho-books.js +10 -10
- package/src/shared/zoho-crm.js +16 -16
- package/src/shared/zoho-regions.js +8 -8
- package/test/englishDefinitions.test.js +37 -0
- package/test/i18nCatalog.test.js +16 -0
- package/test/shopify.test.js +3 -1
package/src/server/wix.js
CHANGED
|
@@ -15,8 +15,8 @@ function serializeNativeJson(value) {
|
|
|
15
15
|
const guid = (value) => typeof value === "string" && /^[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}$/iu.test(value);
|
|
16
16
|
// Results are checked against the operation's own request; a different record is reported with what Wix got wrong.
|
|
17
17
|
const requestPath = (request, index) => decodeURIComponent(new URL(request.url).pathname.split("/").at(index));
|
|
18
|
-
function sameRecord(matches, message) {
|
|
19
|
-
if (!matches) throw new ConnectorError("connector_response_invalid", message, { statusCode: 502 });
|
|
18
|
+
function sameRecord(matches, message, codes) {
|
|
19
|
+
if (!matches) throw new ConnectorError("connector_response_invalid", message, { statusCode: 502, ...codes });
|
|
20
20
|
return true;
|
|
21
21
|
}
|
|
22
22
|
const cursor = (value) => typeof value === "string" && value.length > 0 && value.length <= 16000 && !/[\p{Cc}]/u.test(value);
|
|
@@ -77,14 +77,14 @@ function contactOperation(action) {
|
|
|
77
77
|
const { contactId, ...body } = validateSchemaPayload({ schema, mode: "replace" }, input, { statusCode: 422 });
|
|
78
78
|
if (action !== "get" && (!Object.keys(body.info).length || (action === "create" &&
|
|
79
79
|
!(body.info.name?.first || body.info.name?.last || body.info.emails?.items?.length || body.info.phones?.items?.length)))) {
|
|
80
|
-
throw new ConnectorError("connector_input_invalid", "Provide contact details; creation requires a name, email or phone.", { statusCode: 422 });
|
|
80
|
+
throw new ConnectorError("connector_input_invalid", "Provide contact details; creation requires a name, email or phone.", { statusCode: 422, messageCode: "connectors.wix.provideContactDetailsCreationRequires" });
|
|
81
81
|
}
|
|
82
82
|
return { method: action === "get" ? "GET" : action === "create" ? "POST" : "PATCH",
|
|
83
83
|
url: `https://www.wixapis.com/contacts/v4/contacts${contactId ? `/${contactId}` : ""}`,
|
|
84
84
|
...(action === "get" ? {} : { body }) };
|
|
85
85
|
},
|
|
86
86
|
validateResult: (value, request) => validContact(value?.contact) && (action === "create" ||
|
|
87
|
-
sameRecord(value.contact.id === requestPath(request, -1), "Wix returned a different contact. Check the operation outcome before retrying."))
|
|
87
|
+
sameRecord(value.contact.id === requestPath(request, -1), "Wix returned a different contact. Check the operation outcome before retrying.", { messageCode: "connectors.wix.returnedDifferentContactCheckOperation" }))
|
|
88
88
|
};
|
|
89
89
|
}
|
|
90
90
|
const servicePagingSchema = createSchema({ limit: { type: "integer", min: 1, max: 100, defaultTo: 20 }, offset: { type: "integer", min: 0, max: 100000, defaultTo: 0 } });
|
|
@@ -125,8 +125,8 @@ function requestedAvailability(value, requested, events) {
|
|
|
125
125
|
const slots = value.timeSlots ?? [value.timeSlot];
|
|
126
126
|
sameRecord(!(requested.timeZone && value.timeZone !== requested.timeZone || slots.some(slot => requested.serviceId && slot.serviceId !== requested.serviceId ||
|
|
127
127
|
requested.localStartDate && (slot.localStartDate !== requested.localStartDate || slot.localEndDate !== requested.localEndDate))),
|
|
128
|
-
"Wix returned availability for a different service, time or time zone.");
|
|
129
|
-
return !events || !requested.serviceIds || sameRecord(slots.every(slot => requested.serviceIds.includes(slot.serviceId)), "Wix returned a class slot for a different service.");
|
|
128
|
+
"Wix returned availability for a different service, time or time zone.", { messageCode: "connectors.wix.returnedAvailabilityDifferentServiceTime" });
|
|
129
|
+
return !events || !requested.serviceIds || sameRecord(slots.every(slot => requested.serviceIds.includes(slot.serviceId)), "Wix returned a class slot for a different service.", { messageCode: "connectors.wix.returnedClassSlotDifferentService" });
|
|
130
130
|
}
|
|
131
131
|
function availabilityOperation(action, events = false) {
|
|
132
132
|
const schema = createSchema({
|
|
@@ -164,13 +164,13 @@ function availabilityOperation(action, events = false) {
|
|
|
164
164
|
scopes: [],
|
|
165
165
|
request(input) {
|
|
166
166
|
const { limit, cursor: next, ...body } = validateSchemaPayload({ schema, mode: "replace" }, input, { statusCode: 422 });
|
|
167
|
-
if (next && Object.keys(body).length) throw new ConnectorError("connector_input_invalid", "Use only cursor and limit for the next availability page.", { statusCode: 422 });
|
|
168
|
-
if (body.customerChoices && !Object.keys(body.customerChoices).length) throw new ConnectorError("connector_input_invalid", "Select a duration or add-ons before supplying customer choices.", { statusCode: 422 });
|
|
167
|
+
if (next && Object.keys(body).length) throw new ConnectorError("connector_input_invalid", "Use only cursor and limit for the next availability page.", { statusCode: 422, messageCode: "connectors.wix.useCursorLimitNextAvailability" });
|
|
168
|
+
if (body.customerChoices && !Object.keys(body.customerChoices).length) throw new ConnectorError("connector_input_invalid", "Select a duration or add-ons before supplying customer choices.", { statusCode: 422, messageCode: "connectors.wix.selectDurationAddOnsSupplying" });
|
|
169
169
|
if (!next && (!body.serviceId || !body.timeZone || (action === "list" ? !body.fromLocalDate || !body.toLocalDate || body.fromLocalDate >= body.toLocalDate : body.localStartDate >= body.localEndDate))) {
|
|
170
|
-
throw new ConnectorError("connector_input_invalid", "Choose the service, time zone and an increasing local date range.", { statusCode: 422 });
|
|
170
|
+
throw new ConnectorError("connector_input_invalid", "Choose the service, time zone and an increasing local date range.", { statusCode: 422, messageCode: "connectors.wix.chooseServiceTimeZoneIncreasing" });
|
|
171
171
|
}
|
|
172
172
|
const locations = body.locations ?? (body.location ? [body.location] : []);
|
|
173
|
-
if (locations.some(location => location.locationType === "BUSINESS" && !location.id)) throw new ConnectorError("connector_input_invalid", "Choose the business location ID.", { statusCode: 422 });
|
|
173
|
+
if (locations.some(location => location.locationType === "BUSINESS" && !location.id)) throw new ConnectorError("connector_input_invalid", "Choose the business location ID.", { statusCode: 422, messageCode: "connectors.wix.chooseBusinessLocationId" });
|
|
174
174
|
const { serviceId, ...eventBody } = body;
|
|
175
175
|
return { method: "POST", url: `https://www.wixapis.com/_api/service-availability/v2/time-slots${events ? "/event" : action === "get" ? "/get" : ""}`,
|
|
176
176
|
body: action === "get" ? body : next ? { cursorPaging: { limit, cursor: next } } : { ...(events ? { ...eventBody, serviceIds: [serviceId], includeNonBookable: false } : { ...body, bookable: true }), cursorPaging: { limit } } };
|
|
@@ -208,7 +208,7 @@ function productReadOperation(version, action) {
|
|
|
208
208
|
return { method: "POST", url: `${base}/query`,
|
|
209
209
|
body: version === 1 ? { query: { paging }, includeVariants } : { query: { cursorPaging: paging } } };
|
|
210
210
|
},
|
|
211
|
-
validateResult: (value, request) => action === "get" ? validProduct(value?.product) && sameRecord(value.product.id === requestPath(request, -1), "Wix returned a different product.") : Array.isArray(value?.products) && value.products.length <= 100 && value.products.every(validProduct) &&
|
|
211
|
+
validateResult: (value, request) => action === "get" ? validProduct(value?.product) && sameRecord(value.product.id === requestPath(request, -1), "Wix returned a different product.", { messageCode: "connectors.wix.returnedDifferentProduct" }) : Array.isArray(value?.products) && value.products.length <= 100 && value.products.every(validProduct) &&
|
|
212
212
|
(version === 1 ? (value.totalResults === undefined || Number.isSafeInteger(value.totalResults) && value.totalResults >= 0) &&
|
|
213
213
|
(value.metadata === undefined || value.metadata && typeof value.metadata === "object" && !Array.isArray(value.metadata) &&
|
|
214
214
|
["items", "offset"].every(key => value.metadata[key] === undefined || Number.isSafeInteger(value.metadata[key]) && value.metadata[key] >= 0)) :
|
|
@@ -321,17 +321,17 @@ function locationWriteOperation(action) {
|
|
|
321
321
|
scopes: [],
|
|
322
322
|
request(input) {
|
|
323
323
|
const { locationId, ...location } = validateSchemaPayload({ schema, mode: "replace" }, input, { statusCode: 422 });
|
|
324
|
-
if (!Object.keys(location.address).length) throw new ConnectorError("connector_input_invalid", "Provide the location address.", { statusCode: 422 });
|
|
324
|
+
if (!Object.keys(location.address).length) throw new ConnectorError("connector_input_invalid", "Provide the location address.", { statusCode: 422, messageCode: "connectors.wix.provideLocationAddress" });
|
|
325
325
|
if (location.businessSchedule && (["periods", "specialHourPeriod"].some(key => location.businessSchedule[key] !== undefined &&
|
|
326
326
|
(!Array.isArray(location.businessSchedule[key]) || location.businessSchedule[key].length > 100)) ||
|
|
327
327
|
Object.keys(location.businessSchedule).some(key => !["periods", "specialHourPeriod"].includes(key)))) {
|
|
328
|
-
throw new ConnectorError("connector_input_invalid", "Use native businessSchedule periods and specialHourPeriod arrays with at most 100 entries each.", { statusCode: 422 });
|
|
328
|
+
throw new ConnectorError("connector_input_invalid", "Use native businessSchedule periods and specialHourPeriod arrays with at most 100 entries each.", { statusCode: 422, messageCode: "connectors.wix.businessScheduleLimits" });
|
|
329
329
|
}
|
|
330
330
|
return { method: action === "create" ? "POST" : "PUT", url: `https://www.wixapis.com/locations/v1/locations${locationId ? `/${locationId}` : ""}`,
|
|
331
331
|
body: { location: { ...(locationId ? { id: locationId } : {}), ...location } } };
|
|
332
332
|
},
|
|
333
333
|
validateResult: (value, request) => validLocation(value?.location) && typeof value.location.revision === "string" && /^\d{1,19}$/u.test(value.location.revision) &&
|
|
334
|
-
(action === "create" || sameRecord(value.location.id === requestPath(request, -1), "Wix returned a different business location."))
|
|
334
|
+
(action === "create" || sameRecord(value.location.id === requestPath(request, -1), "Wix returned a different business location.", { messageCode: "connectors.wix.returnedDifferentBusinessLocation" }))
|
|
335
335
|
};
|
|
336
336
|
}
|
|
337
337
|
function locationActionOperation(action) {
|
|
@@ -343,7 +343,7 @@ function locationActionOperation(action) {
|
|
|
343
343
|
return { method: "POST", url: `https://www.wixapis.com/locations/v1/locations/${locationId}/${action}`,
|
|
344
344
|
body: {} };
|
|
345
345
|
},
|
|
346
|
-
validateResult: (value, request) => validLocation(value?.location) && sameRecord(value.location.id === requestPath(request, -2), "Wix returned a different business location.") &&
|
|
346
|
+
validateResult: (value, request) => validLocation(value?.location) && sameRecord(value.location.id === requestPath(request, -2), "Wix returned a different business location.", { messageCode: "connectors.wix.returnedDifferentBusinessLocation" }) &&
|
|
347
347
|
(action === "archive" ? value.location.archived === true : value.location.default === true)
|
|
348
348
|
};
|
|
349
349
|
}
|
|
@@ -467,13 +467,13 @@ function bookingConfirmationOperation(action) {
|
|
|
467
467
|
scopes: [],
|
|
468
468
|
request(input) {
|
|
469
469
|
const { bookingId, paymentStatus, revision, notifyParticipants, message } = validateSchemaPayload({ schema, mode: "replace" }, input, { statusCode: 422 });
|
|
470
|
-
if (message !== undefined && !notifyParticipants) throw new ConnectorError("connector_input_invalid", "Enable participant notification before supplying a message.", { statusCode: 422 });
|
|
470
|
+
if (message !== undefined && !notifyParticipants) throw new ConnectorError("connector_input_invalid", "Enable participant notification before supplying a message.", { statusCode: 422, messageCode: "connectors.wix.enableParticipantNotificationSupplyingMessage" });
|
|
471
471
|
return { method: "POST", url: automatic ? `https://www.wixapis.com/bookings/v2/confirmation/${bookingId}:confirmOrDecline` :
|
|
472
472
|
`https://www.wixapis.com/_api/bookings-service/v2/bookings/${bookingId}/${action}`,
|
|
473
473
|
body: automatic ? { paymentStatus } : { revision, participantNotification: { notifyParticipants, ...(message === undefined ? {} : { message }) } } };
|
|
474
474
|
},
|
|
475
475
|
validateResult: (value, request) => guid(value?.booking?.id) &&
|
|
476
|
-
sameRecord(value.booking.id === (automatic ? requestPath(request, -1).split(":")[0] : requestPath(request, -2)), "Wix returned a different booking. Check the operation outcome before retrying.") &&
|
|
476
|
+
sameRecord(value.booking.id === (automatic ? requestPath(request, -1).split(":")[0] : requestPath(request, -2)), "Wix returned a different booking. Check the operation outcome before retrying.", { messageCode: "connectors.wix.returnedDifferentBookingCheckOperation" }) &&
|
|
477
477
|
typeof value.booking.revision === "string" && /^\d{1,19}$/u.test(value.booking.revision) &&
|
|
478
478
|
BigInt(value.booking.revision) <= 9223372036854775807n && (automatic ? ["CONFIRMED", "PENDING", "DECLINED"].includes(value.booking.status) : value.booking.status === (action === "confirm" ? "CONFIRMED" : "DECLINED"))
|
|
479
479
|
};
|
|
@@ -501,12 +501,12 @@ function fulfillmentWriteOperation(update) {
|
|
|
501
501
|
request(input) {
|
|
502
502
|
const { orderId, fulfillmentId, ...fulfillment } = validateSchemaPayload({ schema, mode: "replace" }, input, { statusCode: 422 });
|
|
503
503
|
if (!Object.keys(fulfillment).length || fulfillment.trackingInfo && !Object.keys(fulfillment.trackingInfo).length) {
|
|
504
|
-
throw new ConnectorError("connector_input_invalid", "Supply the fulfillment properties to write.", { statusCode: 422 });
|
|
504
|
+
throw new ConnectorError("connector_input_invalid", "Supply the fulfillment properties to write.", { statusCode: 422, messageCode: "connectors.wix.supplyFulfillmentPropertiesWrite" });
|
|
505
505
|
}
|
|
506
506
|
const tracking = fulfillment.trackingInfo;
|
|
507
507
|
if (!update && tracking && (!tracking.trackingNumber || !tracking.shippingProvider ||
|
|
508
508
|
!["fedex", "ups", "usps", "dhl", "canadaPost"].includes(tracking.shippingProvider) && !tracking.trackingLink)) {
|
|
509
|
-
throw new ConnectorError("connector_input_invalid", "Supply tracking number and provider; custom carriers also require a tracking URL.", { statusCode: 422 });
|
|
509
|
+
throw new ConnectorError("connector_input_invalid", "Supply tracking number and provider; custom carriers also require a tracking URL.", { statusCode: 422, messageCode: "connectors.wix.supplyTrackingNumberProviderCustom" });
|
|
510
510
|
}
|
|
511
511
|
return { method: update ? "PATCH" : "POST", url: update
|
|
512
512
|
? `https://www.wixapis.com/ecom/v1/fulfillments/${fulfillmentId}/orders/${encodeURIComponent(orderId)}`
|
|
@@ -514,12 +514,12 @@ function fulfillmentWriteOperation(update) {
|
|
|
514
514
|
body: { fulfillment } };
|
|
515
515
|
},
|
|
516
516
|
validateResult: (value, request) => typeof value?.orderWithFulfillments?.orderId === "string" &&
|
|
517
|
-
sameRecord(value.orderWithFulfillments.orderId === requestPath(request, update ? -1 : -2), "Wix returned fulfillments for a different order.") &&
|
|
517
|
+
sameRecord(value.orderWithFulfillments.orderId === requestPath(request, update ? -1 : -2), "Wix returned fulfillments for a different order.", { messageCode: "connectors.wix.returnedFulfillmentsDifferentOrder" }) &&
|
|
518
518
|
Array.isArray(value.orderWithFulfillments.fulfillments) &&
|
|
519
519
|
value.orderWithFulfillments.fulfillments.every(item => guid(item?.id) && Array.isArray(item.lineItems) && item.lineItems.length <= 300 &&
|
|
520
520
|
item.lineItems.every(line => guid(line?.id) && Number.isInteger(line.quantity) && line.quantity >= 1 && line.quantity <= 100000)) &&
|
|
521
521
|
(update ? sameRecord(value.orderWithFulfillments.fulfillments.some(item => item.id === requestPath(request, -3)),
|
|
522
|
-
"Wix did not return the updated fulfillment. Inspect the order before retrying.") :
|
|
522
|
+
"Wix did not return the updated fulfillment. Inspect the order before retrying.", { messageCode: "connectors.wix.didNotReturnUpdatedFulfillment" }) :
|
|
523
523
|
guid(value.fulfillmentId) && value.orderWithFulfillments.fulfillments.some(item => item.id === value.fulfillmentId))
|
|
524
524
|
};
|
|
525
525
|
}
|
|
@@ -559,22 +559,22 @@ const wixRuntime = {
|
|
|
559
559
|
scopes: [],
|
|
560
560
|
request(input) {
|
|
561
561
|
const { bookingId, revision, slot, notifyParticipants, message } = validateSchemaPayload({ schema: bookingRescheduleSchema, mode: "replace" }, input, { statusCode: 422 });
|
|
562
|
-
if (message !== undefined && !notifyParticipants) throw new ConnectorError("connector_input_invalid", "Enable participant notification before supplying a message.", { statusCode: 422 });
|
|
562
|
+
if (message !== undefined && !notifyParticipants) throw new ConnectorError("connector_input_invalid", "Enable participant notification before supplying a message.", { statusCode: 422, messageCode: "connectors.wix.enableParticipantNotificationSupplyingMessage" });
|
|
563
563
|
if (slot.eventId !== undefined) {
|
|
564
564
|
if (Object.keys(slot).length !== 1 || typeof slot.eventId !== "string" || slot.eventId.length < 36 || slot.eventId.length > 250 || /[\p{Cc}]/u.test(slot.eventId)) {
|
|
565
|
-
throw new ConnectorError("connector_input_invalid", "For a class, supply only the selected eventId in slot.", { statusCode: 422 });
|
|
565
|
+
throw new ConnectorError("connector_input_invalid", "For a class, supply only the selected eventId in slot.", { statusCode: 422, messageCode: "connectors.wix.classSupplySelectedEventidSlot" });
|
|
566
566
|
}
|
|
567
567
|
} else {
|
|
568
568
|
let validTimeZone = false;
|
|
569
569
|
try { validTimeZone = typeof slot.timezone === "string" && !!new Intl.DateTimeFormat("en", { timeZone: slot.timezone }); } catch {}
|
|
570
570
|
if (!guid(slot.serviceId) || !guid(slot.scheduleId) || !localDate(slot.startDate) || !localDate(slot.endDate) || slot.startDate >= slot.endDate || !validTimeZone) {
|
|
571
|
-
throw new ConnectorError("connector_input_invalid", "For an appointment, supply its service/schedule IDs, increasing local slot dates and IANA timezone. Courses cannot be rescheduled.", { statusCode: 422 });
|
|
571
|
+
throw new ConnectorError("connector_input_invalid", "For an appointment, supply its service/schedule IDs, increasing local slot dates and IANA timezone. Courses cannot be rescheduled.", { statusCode: 422, messageCode: "connectors.wix.appointmentSupplyServiceScheduleIds" });
|
|
572
572
|
}
|
|
573
573
|
}
|
|
574
574
|
return { method: "POST", url: `https://www.wixapis.com/_api/bookings-service/v2/bookings/${bookingId}/reschedule`,
|
|
575
575
|
body: { revision, slot, participantNotification: { notifyParticipants, ...(message === undefined ? {} : { message }) } } };
|
|
576
576
|
},
|
|
577
|
-
validateResult: (value, request) => guid(value?.booking?.id) && sameRecord(value.booking.id === requestPath(request, -2), "Wix returned a different booking. Check the operation outcome before retrying.") && typeof value.booking.revision === "string" && /^\d{1,19}$/u.test(value.booking.revision) &&
|
|
577
|
+
validateResult: (value, request) => guid(value?.booking?.id) && sameRecord(value.booking.id === requestPath(request, -2), "Wix returned a different booking. Check the operation outcome before retrying.", { messageCode: "connectors.wix.returnedDifferentBookingCheckOperation" }) && typeof value.booking.revision === "string" && /^\d{1,19}$/u.test(value.booking.revision) &&
|
|
578
578
|
BigInt(value.booking.revision) <= 9223372036854775807n && typeof value.booking.status === "string" && value.booking.status.length > 0
|
|
579
579
|
},
|
|
580
580
|
"bookings.confirm": bookingConfirmationOperation("confirm"),
|
|
@@ -600,7 +600,7 @@ const wixRuntime = {
|
|
|
600
600
|
},
|
|
601
601
|
validateResult(value, request) {
|
|
602
602
|
const variants = value?.serviceVariants;
|
|
603
|
-
return guid(variants?.id) && guid(variants.serviceId) && sameRecord(variants.serviceId === requestPath(request, -1), "Wix returned variants for a different service.") &&
|
|
603
|
+
return guid(variants?.id) && guid(variants.serviceId) && sameRecord(variants.serviceId === requestPath(request, -1), "Wix returned variants for a different service.", { messageCode: "connectors.wix.returnedVariantsDifferentService" }) &&
|
|
604
604
|
Array.isArray(variants.options?.values) && variants.options.values.every(option => guid(option?.id) && typeof option.type === "string") &&
|
|
605
605
|
Array.isArray(variants.variants?.values) && variants.variants.values.every(variant =>
|
|
606
606
|
Array.isArray(variant?.choices) && variant.choices.every(choice => guid(choice?.optionId)));
|
|
@@ -612,13 +612,13 @@ const wixRuntime = {
|
|
|
612
612
|
scopes: [],
|
|
613
613
|
request(input) {
|
|
614
614
|
const { serviceId, locations, removedLocationAction: action, moveToLocation, notifyParticipants, notificationMessage } = validateSchemaPayload({ schema: setServiceLocationsSchema, mode: "replace" }, input, { statusCode: 422 });
|
|
615
|
-
if ((action === "MOVE_TO_LOCATION") !== (moveToLocation !== undefined)) throw new ConnectorError("connector_input_invalid", "Provide a destination only when moving future sessions.", { statusCode: 422 });
|
|
616
|
-
if (notificationMessage !== undefined && !notifyParticipants) throw new ConnectorError("connector_input_invalid", "Enable participant notification before supplying a message.", { statusCode: 422 });
|
|
615
|
+
if ((action === "MOVE_TO_LOCATION") !== (moveToLocation !== undefined)) throw new ConnectorError("connector_input_invalid", "Provide a destination only when moving future sessions.", { statusCode: 422, messageCode: "connectors.wix.provideDestinationMovingFutureSessions" });
|
|
616
|
+
if (notificationMessage !== undefined && !notifyParticipants) throw new ConnectorError("connector_input_invalid", "Enable participant notification before supplying a message.", { statusCode: 422, messageCode: "connectors.wix.enableParticipantNotificationSupplyingMessage" });
|
|
617
617
|
for (const location of [...locations, ...(moveToLocation ? [moveToLocation] : [])]) {
|
|
618
618
|
if (location.type === "BUSINESS" && (!location.business || location.custom) ||
|
|
619
619
|
location.type === "CUSTOM" && (!location.custom || location.business || !Object.keys(location.custom.address).length) ||
|
|
620
620
|
location.type === "CUSTOMER" && (location.business || location.custom)) {
|
|
621
|
-
throw new ConnectorError("connector_input_invalid", "Supply the details matching each service location type.", { statusCode: 422 });
|
|
621
|
+
throw new ConnectorError("connector_input_invalid", "Supply the details matching each service location type.", { statusCode: 422, messageCode: "connectors.wix.supplyDetailsMatchingServiceLocation" });
|
|
622
622
|
}
|
|
623
623
|
}
|
|
624
624
|
return { method: "POST", url: `https://www.wixapis.com/_api/bookings/v2/services/${serviceId}/locations`, body: {
|
|
@@ -626,35 +626,35 @@ const wixRuntime = {
|
|
|
626
626
|
participantNotification: { notifyParticipants, ...(notificationMessage !== undefined ? { message: notificationMessage } : {}) }
|
|
627
627
|
} };
|
|
628
628
|
},
|
|
629
|
-
validateResult: (value, request) => validService(value?.service) && sameRecord(value.service.id === requestPath(request, -2), "Wix returned a different booking service. Check the outcome before retrying.")
|
|
629
|
+
validateResult: (value, request) => validService(value?.service) && sameRecord(value.service.id === requestPath(request, -2), "Wix returned a different booking service. Check the outcome before retrying.", { messageCode: "connectors.wix.returnedDifferentBookingServiceCheck" })
|
|
630
630
|
},
|
|
631
631
|
"bookingServices.create": {
|
|
632
632
|
scopes: [],
|
|
633
633
|
request(input) {
|
|
634
634
|
const { service } = validateSchemaPayload({ schema: serviceCreateSchema, mode: "replace" }, input, { statusCode: 422 });
|
|
635
|
-
const invalid = message => { throw new ConnectorError("connector_input_invalid", message, { statusCode: 422 }); };
|
|
636
|
-
if (!["APPOINTMENT", "CLASS", "COURSE"].includes(service.type) || typeof service.name !== "string" || !service.name.trim() || service.name.length > 400) invalid("Provide a service type and name of up to 400 characters.");
|
|
637
|
-
if (["id", "revision", "createdByAppId", "createdDate", "updatedDate", "addOnGroups"].some(key => Object.hasOwn(service, key))) invalid("Do not send generated service identity fields or existing add-on groups when creating a service.");
|
|
638
|
-
if (!Number.isInteger(service.defaultCapacity) || service.defaultCapacity < 1 || service.defaultCapacity > 1000 || service.type === "APPOINTMENT" && service.defaultCapacity !== 1) invalid("Set appointment capacity to 1, or class/course capacity from 1 to 1000.");
|
|
635
|
+
const invalid = (message, codes) => { throw new ConnectorError("connector_input_invalid", message, { statusCode: 422, ...codes }); };
|
|
636
|
+
if (!["APPOINTMENT", "CLASS", "COURSE"].includes(service.type) || typeof service.name !== "string" || !service.name.trim() || service.name.length > 400) invalid("Provide a service type and name of up to 400 characters.", { messageCode: "connectors.wix.provideServiceTypeNameUp" });
|
|
637
|
+
if (["id", "revision", "createdByAppId", "createdDate", "updatedDate", "addOnGroups"].some(key => Object.hasOwn(service, key))) invalid("Do not send generated service identity fields or existing add-on groups when creating a service.", { messageCode: "connectors.wix.doNotSendGeneratedService" });
|
|
638
|
+
if (!Number.isInteger(service.defaultCapacity) || service.defaultCapacity < 1 || service.defaultCapacity > 1000 || service.type === "APPOINTMENT" && service.defaultCapacity !== 1) invalid("Set appointment capacity to 1, or class/course capacity from 1 to 1000.", { messageCode: "connectors.wix.setAppointmentCapacity1Class" });
|
|
639
639
|
const online = service.onlineBooking;
|
|
640
|
-
if (!online || typeof online.enabled !== "boolean" || ["requireManualApproval", "allowMultipleRequests"].some(key => online[key] !== undefined && typeof online[key] !== "boolean")) invalid("Provide explicit online-booking settings.");
|
|
640
|
+
if (!online || typeof online.enabled !== "boolean" || ["requireManualApproval", "allowMultipleRequests"].some(key => online[key] !== undefined && typeof online[key] !== "boolean")) invalid("Provide explicit online-booking settings.", { messageCode: "connectors.wix.provideExplicitOnlineBookingSettings" });
|
|
641
641
|
const payment = service.payment;
|
|
642
|
-
if (!payment || !["FIXED", "VARIED", "CUSTOM", "NO_FEE"].includes(payment.rateType)) invalid("Use FIXED, VARIED, CUSTOM or NO_FEE service payment settings.");
|
|
642
|
+
if (!payment || !["FIXED", "VARIED", "CUSTOM", "NO_FEE"].includes(payment.rateType)) invalid("Use FIXED, VARIED, CUSTOM or NO_FEE service payment settings.", { messageCode: "connectors.wix.useFixedVariedCustomNo" });
|
|
643
643
|
const options = payment.options;
|
|
644
|
-
if (!options || typeof options !== "object" || ["online", "inPerson", "deposit", "pricingPlan"].some(key => options[key] !== undefined && typeof options[key] !== "boolean") || !(options.online === true || options.inPerson === true)) invalid("Select in-person or online payment, including for a free service.");
|
|
645
|
-
if (online.requireManualApproval && options.pricingPlan || !online.enabled && options.online) invalid("Manual approval cannot use pricing plans; online payment requires online booking.");
|
|
644
|
+
if (!options || typeof options !== "object" || ["online", "inPerson", "deposit", "pricingPlan"].some(key => options[key] !== undefined && typeof options[key] !== "boolean") || !(options.online === true || options.inPerson === true)) invalid("Select in-person or online payment, including for a free service.", { messageCode: "connectors.wix.selectPersonOnlinePaymentIncluding" });
|
|
645
|
+
if (online.requireManualApproval && options.pricingPlan || !online.enabled && options.online) invalid("Manual approval cannot use pricing plans; online payment requires online booking.", { messageCode: "connectors.wix.manualApprovalCannotUsePricing" });
|
|
646
646
|
const priced = ["FIXED", "VARIED"].includes(payment.rateType);
|
|
647
|
-
if ((options.online || options.deposit) && !priced) invalid("Online and deposit payments require fixed or varied pricing.");
|
|
647
|
+
if ((options.online || options.deposit) && !priced) invalid("Online and deposit payments require fixed or varied pricing.", { messageCode: "connectors.wix.onlineDepositPaymentsRequireFixed" });
|
|
648
648
|
const rate = payment.rateType === "FIXED" ? payment.fixed : payment.varied;
|
|
649
649
|
const money = value => value && typeof value.value === "string" && value.value.length <= 30 && /^\d+(?:\.\d{1,2})?$/u.test(value.value) && /[1-9]/u.test(value.value) && /^[A-Z]{3}$/u.test(value.currency);
|
|
650
|
-
if (priced && !money(payment.rateType === "FIXED" ? rate?.price : rate?.defaultPrice)) invalid("Provide a positive decimal price string and three-letter currency code.");
|
|
651
|
-
if (payment.rateType === "CUSTOM" && (typeof payment.custom?.description !== "string" || !payment.custom.description.length || payment.custom.description.length > 50)) invalid("Describe the custom payment in up to 50 characters.");
|
|
652
|
-
if (options.deposit && (!options.online || options.inPerson || !money(rate?.deposit))) invalid("A deposit requires its amount, online payment and no in-person payment.");
|
|
650
|
+
if (priced && !money(payment.rateType === "FIXED" ? rate?.price : rate?.defaultPrice)) invalid("Provide a positive decimal price string and three-letter currency code.", { messageCode: "connectors.wix.providePositiveDecimalPriceString" });
|
|
651
|
+
if (payment.rateType === "CUSTOM" && (typeof payment.custom?.description !== "string" || !payment.custom.description.length || payment.custom.description.length > 50)) invalid("Describe the custom payment in up to 50 characters.", { messageCode: "connectors.wix.describeCustomPaymentUp50" });
|
|
652
|
+
if (options.deposit && (!options.online || options.inPerson || !money(rate?.deposit))) invalid("A deposit requires its amount, online payment and no in-person payment.", { messageCode: "connectors.wix.depositRequiresAmountOnlinePayment" });
|
|
653
653
|
const durations = service.schedule?.availabilityConstraints?.sessionDurations;
|
|
654
654
|
if (service.type === "APPOINTMENT") {
|
|
655
|
-
if (!Array.isArray(service.staffMemberIds) || !service.staffMemberIds.length || !service.staffMemberIds.every(guid)) invalid("Select at least one staff resource ID for the appointment service.");
|
|
656
|
-
if (!Array.isArray(durations) || !durations.length || !durations.every(value => Number.isInteger(value) && value > 0)) invalid("Provide appointment session durations in minutes.");
|
|
657
|
-
} else if (durations !== undefined) invalid("Class/course session durations belong to their sessions, not service availability constraints.");
|
|
655
|
+
if (!Array.isArray(service.staffMemberIds) || !service.staffMemberIds.length || !service.staffMemberIds.every(guid)) invalid("Select at least one staff resource ID for the appointment service.", { messageCode: "connectors.wix.selectLeastStaffResourceId" });
|
|
656
|
+
if (!Array.isArray(durations) || !durations.length || !durations.every(value => Number.isInteger(value) && value > 0)) invalid("Provide appointment session durations in minutes.", { messageCode: "connectors.wix.provideAppointmentSessionDurationsMinutes" });
|
|
657
|
+
} else if (durations !== undefined) invalid("Class/course session durations belong to their sessions, not service availability constraints.", { messageCode: "connectors.wix.classCourseSessionDurationsBelong" });
|
|
658
658
|
return { method: "POST", url: "https://www.wixapis.com/_api/bookings/v2/services", body: { service } };
|
|
659
659
|
},
|
|
660
660
|
validateResult: value => validService(value?.service)
|
|
@@ -668,7 +668,7 @@ const wixRuntime = {
|
|
|
668
668
|
return { method: "GET", url: url.href };
|
|
669
669
|
},
|
|
670
670
|
validateResult: (value, request) => value?.dataItem?.data && typeof value.dataItem.data === "object" && !Array.isArray(value.dataItem.data) &&
|
|
671
|
-
sameRecord(value.dataItem.id === requestPath(request, -1) && value.dataItem.dataCollectionId === new URL(request.url).searchParams.get("dataCollectionId"), "Wix returned a different CMS item or collection. Check write outcomes before retrying.")
|
|
671
|
+
sameRecord(value.dataItem.id === requestPath(request, -1) && value.dataItem.dataCollectionId === new URL(request.url).searchParams.get("dataCollectionId"), "Wix returned a different CMS item or collection. Check write outcomes before retrying.", { messageCode: "connectors.wix.returnedDifferentCmsItemCollection" })
|
|
672
672
|
},
|
|
673
673
|
"cmsItems.patch": {
|
|
674
674
|
scopes: [],
|
|
@@ -678,7 +678,7 @@ const wixRuntime = {
|
|
|
678
678
|
body: { dataCollectionId, patch: { dataItemId: itemId, fieldModifications }, ...(conditionFilter !== undefined ? { condition: { filter: conditionFilter } } : {}) } };
|
|
679
679
|
},
|
|
680
680
|
validateResult: (value, request) => value?.dataItem?.data && typeof value.dataItem.data === "object" && !Array.isArray(value.dataItem.data) &&
|
|
681
|
-
sameRecord(value.dataItem.id === requestPath(request, -1) && value.dataItem.dataCollectionId === request.body.dataCollectionId, "Wix returned a different CMS item or collection. Check write outcomes before retrying.")
|
|
681
|
+
sameRecord(value.dataItem.id === requestPath(request, -1) && value.dataItem.dataCollectionId === request.body.dataCollectionId, "Wix returned a different CMS item or collection. Check write outcomes before retrying.", { messageCode: "connectors.wix.returnedDifferentCmsItemCollection" })
|
|
682
682
|
},
|
|
683
683
|
"cmsItems.list": {
|
|
684
684
|
scopes: [],
|
|
@@ -692,7 +692,7 @@ const wixRuntime = {
|
|
|
692
692
|
validateResult: (value, request) => Array.isArray(value?.dataItems) && value.dataItems.length <= 100 && value.dataItems.every(item =>
|
|
693
693
|
typeof item?.id === "string" && item.id.length > 0 && collectionId(item.dataCollectionId) && item.data && typeof item.data === "object" && !Array.isArray(item.data)) &&
|
|
694
694
|
(value.pagingMetadata === undefined || value.pagingMetadata && typeof value.pagingMetadata === "object" && !Array.isArray(value.pagingMetadata)) &&
|
|
695
|
-
sameRecord(value.dataItems.every(item => item.dataCollectionId === request.body.dataCollectionId), "Wix returned items from a different CMS collection.")
|
|
695
|
+
sameRecord(value.dataItems.every(item => item.dataCollectionId === request.body.dataCollectionId), "Wix returned items from a different CMS collection.", { messageCode: "connectors.wix.returnedItemsDifferentCmsCollection" })
|
|
696
696
|
},
|
|
697
697
|
"cmsCollections.list": {
|
|
698
698
|
scopes: [],
|
|
@@ -714,7 +714,7 @@ const wixRuntime = {
|
|
|
714
714
|
return { method: "GET", url: `https://www.wixapis.com/wix-data/v2/collections/${id}?consistentRead=${value.consistentRead}` };
|
|
715
715
|
},
|
|
716
716
|
validateResult: (value, request) => validCollection(value?.collection) &&
|
|
717
|
-
sameRecord(value.collection.id === new URL(request.url).pathname.split("/").slice(4).map(decodeURIComponent).join("/"), "Wix returned a different CMS collection.")
|
|
717
|
+
sameRecord(value.collection.id === new URL(request.url).pathname.split("/").slice(4).map(decodeURIComponent).join("/"), "Wix returned a different CMS collection.", { messageCode: "connectors.wix.returnedDifferentCmsCollection" })
|
|
718
718
|
},
|
|
719
719
|
"locations.archive": locationActionOperation("archive"),
|
|
720
720
|
"locations.setDefault": locationActionOperation("set-default"),
|
|
@@ -737,7 +737,7 @@ const wixRuntime = {
|
|
|
737
737
|
const { locationId } = validateSchemaPayload({ schema: locationGetSchema, mode: "replace" }, input, { statusCode: 422 });
|
|
738
738
|
return { method: "GET", url: `https://www.wixapis.com/locations/v1/locations/${locationId}` };
|
|
739
739
|
},
|
|
740
|
-
validateResult: (value, request) => validLocation(value?.location) && sameRecord(value.location.id === requestPath(request, -1), "Wix returned a different business location.")
|
|
740
|
+
validateResult: (value, request) => validLocation(value?.location) && sameRecord(value.location.id === requestPath(request, -1), "Wix returned a different business location.", { messageCode: "connectors.wix.returnedDifferentBusinessLocation" })
|
|
741
741
|
},
|
|
742
742
|
"productsV1.list": productReadOperation(1, "list"),
|
|
743
743
|
"productsV1.get": productReadOperation(1, "get"),
|
|
@@ -745,12 +745,12 @@ const wixRuntime = {
|
|
|
745
745
|
scopes: [],
|
|
746
746
|
request(input) {
|
|
747
747
|
const { productId, price, ...changes } = validateSchemaPayload({ schema: productV1UpdateSchema, mode: "replace" }, input, { statusCode: 422 });
|
|
748
|
-
if (!Object.keys(changes).length && price === undefined) throw new ConnectorError("connector_input_invalid", "Provide a product name, visibility or base-price change.", { statusCode: 422 });
|
|
748
|
+
if (!Object.keys(changes).length && price === undefined) throw new ConnectorError("connector_input_invalid", "Provide a product name, visibility or base-price change.", { statusCode: 422, messageCode: "connectors.wix.provideProductNameVisibilityBase" });
|
|
749
749
|
return { method: "PATCH", url: `https://www.wixapis.com/stores/v1/products/${productId}`,
|
|
750
750
|
body: { product: { ...changes, ...(price === undefined ? {} : { priceData: { price } }) } } };
|
|
751
751
|
},
|
|
752
752
|
validateResult: (value, request) => guid(value?.product?.id) && typeof value.product.name === "string" && value.product.name.length > 0 &&
|
|
753
|
-
sameRecord(value.product.id === requestPath(request, -1), "Wix returned a different product.")
|
|
753
|
+
sameRecord(value.product.id === requestPath(request, -1), "Wix returned a different product.", { messageCode: "connectors.wix.returnedDifferentProduct" })
|
|
754
754
|
},
|
|
755
755
|
"productsV3.list": productReadOperation(3, "list"),
|
|
756
756
|
"productsV3.get": productReadOperation(3, "get"),
|
|
@@ -758,12 +758,12 @@ const wixRuntime = {
|
|
|
758
758
|
scopes: [],
|
|
759
759
|
request(input) {
|
|
760
760
|
const { productId, revision, ...changes } = validateSchemaPayload({ schema: productV3UpdateSchema, mode: "replace" }, input, { statusCode: 422 });
|
|
761
|
-
if (!Object.keys(changes).length) throw new ConnectorError("connector_input_invalid", "Provide a product name or visibility change.", { statusCode: 422 });
|
|
761
|
+
if (!Object.keys(changes).length) throw new ConnectorError("connector_input_invalid", "Provide a product name or visibility change.", { statusCode: 422, messageCode: "connectors.wix.provideProductNameVisibilityChange" });
|
|
762
762
|
return { method: "PATCH", url: `https://www.wixapis.com/stores/v3/products/${productId}`,
|
|
763
763
|
body: { product: { id: productId, revision, ...changes } } };
|
|
764
764
|
},
|
|
765
765
|
validateResult: (value, request) => guid(value?.product?.id) && typeof value.product.name === "string" && value.product.name.length > 0 &&
|
|
766
|
-
sameRecord(value.product.id === requestPath(request, -1), "Wix returned a different product.") &&
|
|
766
|
+
sameRecord(value.product.id === requestPath(request, -1), "Wix returned a different product.", { messageCode: "connectors.wix.returnedDifferentProduct" }) &&
|
|
767
767
|
typeof value.product.revision === "string" && /^\d{1,19}$/u.test(value.product.revision) && BigInt(value.product.revision) <= 9223372036854775807n
|
|
768
768
|
},
|
|
769
769
|
"catalog.version": {
|
|
@@ -777,7 +777,7 @@ const wixRuntime = {
|
|
|
777
777
|
scopes: [],
|
|
778
778
|
request(input) {
|
|
779
779
|
const { status, contactId, ...cursorPaging } = validateSchemaPayload({ schema: orderSearchSchema, mode: "replace" }, input, { statusCode: 422 });
|
|
780
|
-
if (cursorPaging.cursor && (status || contactId)) throw new ConnectorError("connector_input_invalid", "Use only cursor and limit for the next order page.", { statusCode: 422 });
|
|
780
|
+
if (cursorPaging.cursor && (status || contactId)) throw new ConnectorError("connector_input_invalid", "Use only cursor and limit for the next order page.", { statusCode: 422, messageCode: "connectors.wix.useCursorLimitNextOrder" });
|
|
781
781
|
const filter = { ...(status ? { status } : {}), ...(contactId ? { "buyerInfo.contactId": contactId } : {}) };
|
|
782
782
|
return { method: "POST", url: "https://www.wixapis.com/ecom/v1/orders/search",
|
|
783
783
|
body: { search: { cursorPaging, ...(Object.keys(filter).length ? { filter } : {}) } } };
|
|
@@ -794,7 +794,7 @@ const wixRuntime = {
|
|
|
794
794
|
request(input) {
|
|
795
795
|
const { orderId } = validateSchemaPayload({ schema: orderIdSchema, mode: "replace" }, input, { statusCode: 422 });
|
|
796
796
|
return { method: "GET", url: `https://www.wixapis.com/ecom/v1/orders/${encodeURIComponent(orderId)}` };
|
|
797
|
-
}, validateResult: (value, request) => validOrder(value?.order) && sameRecord(value.order.id === requestPath(request, -1), "Wix returned a different order.")
|
|
797
|
+
}, validateResult: (value, request) => validOrder(value?.order) && sameRecord(value.order.id === requestPath(request, -1), "Wix returned a different order.", { messageCode: "connectors.wix.returnedDifferentOrder" })
|
|
798
798
|
},
|
|
799
799
|
"orderFulfillments.create": fulfillmentWriteOperation(false),
|
|
800
800
|
"orderFulfillments.update": fulfillmentWriteOperation(true),
|
|
@@ -805,7 +805,7 @@ const wixRuntime = {
|
|
|
805
805
|
return { method: "GET", url: `https://www.wixapis.com/ecom/v1/fulfillments/orders/${encodeURIComponent(orderId)}` };
|
|
806
806
|
},
|
|
807
807
|
validateResult: (value, request) => guid(value?.orderWithFulfillments?.orderId) &&
|
|
808
|
-
sameRecord(value.orderWithFulfillments.orderId === requestPath(request, -1), "Wix returned fulfillments for a different order.") &&
|
|
808
|
+
sameRecord(value.orderWithFulfillments.orderId === requestPath(request, -1), "Wix returned fulfillments for a different order.", { messageCode: "connectors.wix.returnedFulfillmentsDifferentOrder" }) &&
|
|
809
809
|
Array.isArray(value.orderWithFulfillments.fulfillments) &&
|
|
810
810
|
value.orderWithFulfillments.fulfillments.every(item => guid(item?.id) && Array.isArray(item.lineItems) && item.lineItems.length <= 300 &&
|
|
811
811
|
item.lineItems.every(line => guid(line?.id) && Number.isInteger(line.quantity) && line.quantity >= 1 && line.quantity <= 100000))
|
|
@@ -819,7 +819,7 @@ const wixRuntime = {
|
|
|
819
819
|
url.searchParams.set("timeZone", timeZone);
|
|
820
820
|
return { method: "GET", url: url.href };
|
|
821
821
|
}, validateResult: (value, request) => validSlot(value?.timeSlot) && typeof value.timeSlot.eventInfo?.eventId === "string" && typeof value.timeZone === "string" &&
|
|
822
|
-
sameRecord(value.timeSlot.eventInfo.eventId === requestPath(request, -1) && value.timeZone === new URL(request.url).searchParams.get("timeZone"), "Wix returned a different event slot or time zone.")
|
|
822
|
+
sameRecord(value.timeSlot.eventInfo.eventId === requestPath(request, -1) && value.timeZone === new URL(request.url).searchParams.get("timeZone"), "Wix returned a different event slot or time zone.", { messageCode: "connectors.wix.returnedDifferentEventSlotTime" })
|
|
823
823
|
},
|
|
824
824
|
"forms.summary": {
|
|
825
825
|
scopes: [],
|
|
@@ -827,7 +827,7 @@ const wixRuntime = {
|
|
|
827
827
|
const { formId } = validateSchemaPayload({ schema: formSummarySchema, mode: "replace" }, input, { statusCode: 422 });
|
|
828
828
|
return { method: "GET", url: `https://www.wixapis.com/form-schema-service/v4/forms/${formId}/summary` };
|
|
829
829
|
},
|
|
830
|
-
validateResult: (value, request) => guid(value?.formSummary?.id) && sameRecord(value.formSummary.id === requestPath(request, -2), "Wix returned a different form summary.") &&
|
|
830
|
+
validateResult: (value, request) => guid(value?.formSummary?.id) && sameRecord(value.formSummary.id === requestPath(request, -2), "Wix returned a different form summary.", { messageCode: "connectors.wix.returnedDifferentFormSummary" }) &&
|
|
831
831
|
Array.isArray(value.formSummary.fields) && value.formSummary.fields.length <= 500 &&
|
|
832
832
|
value.formSummary.fields.every(field => guid(field?.id) && typeof field.target === "string" && field.target.length > 0 && field.target.length <= 200 &&
|
|
833
833
|
typeof field.type === "string" && field.type.length > 0 && (field.label === undefined || typeof field.label === "string" && field.label.length <= 350) &&
|
|
@@ -839,18 +839,18 @@ const wixRuntime = {
|
|
|
839
839
|
const value = validateSchemaPayload({ schema: bookingCreateSchema, mode: "replace" }, input, { statusCode: 422 });
|
|
840
840
|
const { kind, serviceId, timeZone, startDate, endDate, eventId, scheduleId, resourceId, location, totalParticipants, participantsChoices, bookedAddOns, formSubmission, notifyParticipants, sendSmsReminder } = value;
|
|
841
841
|
if (participantsChoices) {
|
|
842
|
-
if (totalParticipants !== undefined) throw new ConnectorError("connector_input_invalid", "Use participant choices or a fixed participant total, not both.", { statusCode: 422 });
|
|
842
|
+
if (totalParticipants !== undefined) throw new ConnectorError("connector_input_invalid", "Use participant choices or a fixed participant total, not both.", { statusCode: 422, messageCode: "connectors.wix.useParticipantChoicesFixedParticipant" });
|
|
843
843
|
if (participantsChoices.serviceChoices.reduce((total, group) => total + group.numberOfParticipants, 0) > 1000 ||
|
|
844
844
|
participantsChoices.serviceChoices.some(group => new Set(group.choices.map(choice => choice.optionId)).size !== group.choices.length ||
|
|
845
845
|
group.choices.some(choice => (choice.custom !== undefined) === (choice.duration !== undefined)))) {
|
|
846
|
-
throw new ConnectorError("connector_input_invalid", "Use at most 1000 participants, distinct options per group and exactly one custom or duration value per choice.", { statusCode: 422 });
|
|
846
|
+
throw new ConnectorError("connector_input_invalid", "Use at most 1000 participants, distinct options per group and exactly one custom or duration value per choice.", { statusCode: 422, messageCode: "connectors.wix.useMost1000ParticipantsDistinct" });
|
|
847
847
|
}
|
|
848
848
|
}
|
|
849
849
|
if (kind === "APPOINTMENT" ? !startDate || !endDate || startDate >= endDate || !resourceId || !location || eventId || scheduleId :
|
|
850
850
|
kind === "CLASS" ? !eventId || startDate || endDate || resourceId || location || scheduleId : !scheduleId || startDate || endDate || resourceId || location || eventId) {
|
|
851
|
-
throw new ConnectorError("connector_input_invalid", "Use appointment dates/resource/location, a class event ID, or a course schedule ID, matching the selected service type.", { statusCode: 422 });
|
|
851
|
+
throw new ConnectorError("connector_input_invalid", "Use appointment dates/resource/location, a class event ID, or a course schedule ID, matching the selected service type.", { statusCode: 422, messageCode: "connectors.wix.useAppointmentDatesResourceLocation" });
|
|
852
852
|
}
|
|
853
|
-
if (location?.locationType === "OWNER_BUSINESS" && !location.id) throw new ConnectorError("connector_input_invalid", "Choose the business location ID.", { statusCode: 422 });
|
|
853
|
+
if (location?.locationType === "OWNER_BUSINESS" && !location.id) throw new ConnectorError("connector_input_invalid", "Choose the business location ID.", { statusCode: 422, messageCode: "connectors.wix.chooseBusinessLocationId" });
|
|
854
854
|
const bookedEntity = kind === "COURSE" ? { schedule: { scheduleId, serviceId, timezone: timeZone } } :
|
|
855
855
|
{ slot: { serviceId, timezone: timeZone, ...(kind === "CLASS" ? { eventId } : { startDate, endDate, resource: { id: resourceId }, location }) } };
|
|
856
856
|
return { method: "POST", url: "https://www.wixapis.com/_api/bookings-service/v2/bookings",
|
|
@@ -878,18 +878,18 @@ const wixRuntime = {
|
|
|
878
878
|
["count", "offset", "total"].every(key => value.pagingMetadata[key] === undefined || Number.isSafeInteger(value.pagingMetadata[key]) && value.pagingMetadata[key] >= 0) &&
|
|
879
879
|
(value.pagingMetadata.count === undefined || value.pagingMetadata.count === value.extendedBookings.length)) &&
|
|
880
880
|
(!request.body.query.filter?.id || sameRecord(value.extendedBookings.length <= 1 && value.extendedBookings.every(record => record.booking.id === request.body.query.filter.id),
|
|
881
|
-
"Wix returned an unexpected booking for the requested ID."))
|
|
881
|
+
"Wix returned an unexpected booking for the requested ID.", { messageCode: "connectors.wix.returnedUnexpectedBookingRequestedId" }))
|
|
882
882
|
},
|
|
883
883
|
"bookings.cancel": {
|
|
884
884
|
scopes: [],
|
|
885
885
|
request(input) {
|
|
886
886
|
const { bookingId, revision, notifyParticipants, message, waiveCharges } = validateSchemaPayload({ schema: bookingCancelSchema, mode: "replace" }, input, { statusCode: 422 });
|
|
887
|
-
if (message && !notifyParticipants) throw new ConnectorError("connector_input_invalid", "Enable participant notification to send a cancellation message.", { statusCode: 422 });
|
|
887
|
+
if (message && !notifyParticipants) throw new ConnectorError("connector_input_invalid", "Enable participant notification to send a cancellation message.", { statusCode: 422, messageCode: "connectors.wix.enableParticipantNotificationSendCancellation" });
|
|
888
888
|
return { method: "POST", url: `https://www.wixapis.com/_api/bookings-service/v2/bookings/${bookingId}/cancel`,
|
|
889
889
|
body: { revision, waiveCharges,
|
|
890
890
|
participantNotification: { notifyParticipants, ...(message === undefined ? {} : { message }) } } };
|
|
891
891
|
},
|
|
892
|
-
validateResult: (value, request) => guid(value?.booking?.id) && sameRecord(value.booking.id === requestPath(request, -2), "Wix returned a different booking. Check the operation outcome before retrying.") && value.booking.status === "CANCELED" &&
|
|
892
|
+
validateResult: (value, request) => guid(value?.booking?.id) && sameRecord(value.booking.id === requestPath(request, -2), "Wix returned a different booking. Check the operation outcome before retrying.", { messageCode: "connectors.wix.returnedDifferentBookingCheckOperation" }) && value.booking.status === "CANCELED" &&
|
|
893
893
|
typeof value.booking.revision === "string" && /^\d{1,19}$/u.test(value.booking.revision) && BigInt(value.booking.revision) <= 9223372036854775807n
|
|
894
894
|
},
|
|
895
895
|
"bookingServices.list": {
|
|
@@ -908,19 +908,19 @@ const wixRuntime = {
|
|
|
908
908
|
request(input) {
|
|
909
909
|
const { serviceId } = validateSchemaPayload({ schema: serviceIdSchema, mode: "replace" }, input, { statusCode: 422 });
|
|
910
910
|
return { method: "GET", url: `https://www.wixapis.com/_api/bookings/v2/services/${serviceId}` };
|
|
911
|
-
}, validateResult: (value, request) => validService(value?.service) && sameRecord(value.service.id === requestPath(request, -1), "Wix returned a different booking service. Check the outcome before retrying.")
|
|
911
|
+
}, validateResult: (value, request) => validService(value?.service) && sameRecord(value.service.id === requestPath(request, -1), "Wix returned a different booking service. Check the outcome before retrying.", { messageCode: "connectors.wix.returnedDifferentBookingServiceCheck" })
|
|
912
912
|
},
|
|
913
913
|
"bookingServices.update": {
|
|
914
914
|
scopes: [],
|
|
915
915
|
request(input) {
|
|
916
916
|
const { serviceId, ...service } = validateSchemaPayload({ schema: serviceUpdateSchema, mode: "replace" }, input, { statusCode: 422 });
|
|
917
|
-
if (Object.keys(service).length < 2) throw new ConnectorError("connector_input_invalid", "Choose a service field to update.", { statusCode: 422 });
|
|
917
|
+
if (Object.keys(service).length < 2) throw new ConnectorError("connector_input_invalid", "Choose a service field to update.", { statusCode: 422, messageCode: "connectors.wix.chooseServiceFieldUpdate" });
|
|
918
918
|
if (["payment", "onlineBooking"].some(key => service[key] !== undefined && !Object.keys(service[key]).length) ||
|
|
919
919
|
service.schedule && !Object.keys(service.schedule.availabilityConstraints).length) {
|
|
920
|
-
throw new ConnectorError("connector_input_invalid", "Provide the selected service settings instead of an empty object.", { statusCode: 422 });
|
|
920
|
+
throw new ConnectorError("connector_input_invalid", "Provide the selected service settings instead of an empty object.", { statusCode: 422, messageCode: "connectors.wix.provideSelectedServiceSettingsInstead" });
|
|
921
921
|
}
|
|
922
922
|
return { method: "PATCH", url: `https://www.wixapis.com/_api/bookings/v2/services/${serviceId}`, body: { service: { id: serviceId, ...service } } };
|
|
923
|
-
}, validateResult: (value, request) => validService(value?.service) && sameRecord(value.service.id === requestPath(request, -1), "Wix returned a different booking service. Check the outcome before retrying.")
|
|
923
|
+
}, validateResult: (value, request) => validService(value?.service) && sameRecord(value.service.id === requestPath(request, -1), "Wix returned a different booking service. Check the outcome before retrying.", { messageCode: "connectors.wix.returnedDifferentBookingServiceCheck" })
|
|
924
924
|
},
|
|
925
925
|
"contacts.get": contactOperation("get"),
|
|
926
926
|
"contacts.create": contactOperation("create"),
|
|
@@ -962,10 +962,10 @@ function wixSiteOperation(operation) {
|
|
|
962
962
|
let siteId = settings.siteId, values = input;
|
|
963
963
|
if (input && Object.hasOwn(input, "siteId")) {
|
|
964
964
|
({ siteId, ...values } = input);
|
|
965
|
-
if (!guid(siteId)) throw new ConnectorError("connector_input_invalid", "Choose a valid Wix Site ID.", { statusCode: 422 });
|
|
965
|
+
if (!guid(siteId)) throw new ConnectorError("connector_input_invalid", "Choose a valid Wix Site ID.", { statusCode: 422, messageCode: "connectors.wix.chooseValidSiteId" });
|
|
966
966
|
const allowed = (settings.selectableSiteIds || "").split(",").map(id => id.trim().toLowerCase());
|
|
967
|
-
if (!allowed.includes(siteId.toLowerCase())) throw new ConnectorError("connector_input_invalid", "This site is not enabled in the project's Selectable Site IDs.", { statusCode: 422 });
|
|
968
|
-
} else if (!guid(siteId)) throw new ConnectorError("connector_input_invalid", "Configure the Wix Site ID first.", { statusCode: 422 });
|
|
967
|
+
if (!allowed.includes(siteId.toLowerCase())) throw new ConnectorError("connector_input_invalid", "This site is not enabled in the project's Selectable Site IDs.", { statusCode: 422, messageCode: "connectors.wix.siteNotEnabledProjectSelectable" });
|
|
968
|
+
} else if (!guid(siteId)) throw new ConnectorError("connector_input_invalid", "Configure the Wix Site ID first.", { statusCode: 422, messageCode: "connectors.wix.configureSiteIdFirst" });
|
|
969
969
|
const request = operation.request(values, { ...settings, siteId });
|
|
970
970
|
return { ...request, headers: { ...request.headers, "wix-site-id": siteId } };
|
|
971
971
|
}
|
package/src/server/wiz.js
CHANGED
|
@@ -8,15 +8,15 @@ import { validateIntegrationConfiguration } from "@jskit-ai/connectors-core/shar
|
|
|
8
8
|
import { wizDefinition } from "../shared/wiz.js";
|
|
9
9
|
|
|
10
10
|
const object = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
11
|
-
const failure = (code, message, statusCode = 502) => new ConnectorError(code, message, { statusCode });
|
|
11
|
+
const failure = (code, message, statusCode = 502, codes = {}) => new ConnectorError(code, message, { statusCode, ...codes });
|
|
12
12
|
|
|
13
13
|
// This process belongs to the scanner, not the application's chat/agent runtime.
|
|
14
14
|
async function runCli(executable, args, options, signal, timeoutMs) {
|
|
15
|
-
if (signal?.aborted) throw failure("connector_cancelled", "The Wiz scan was cancelled.", 499);
|
|
15
|
+
if (signal?.aborted) throw failure("connector_cancelled", "The Wiz scan was cancelled.", 499, { messageCode: "connectors.wiz.scanCancelled" });
|
|
16
16
|
return new Promise((resolve, reject) => {
|
|
17
17
|
let child;
|
|
18
18
|
try { child = spawn(executable, args, { ...options, shell: false, detached: true, stdio: "ignore" }); }
|
|
19
|
-
catch { reject(failure("connector_runner_unavailable", "The Wiz CLI could not be started.")); return; }
|
|
19
|
+
catch { reject(failure("connector_runner_unavailable", "The Wiz CLI could not be started.", 502, { messageCode: "connectors.wiz.cliCouldNotStarted" })); return; }
|
|
20
20
|
let cancelled = false; let timedOut = false; let startFailed = false;
|
|
21
21
|
const kill = () => {
|
|
22
22
|
if (!child.pid) return;
|
|
@@ -32,9 +32,9 @@ async function runCli(executable, args, options, signal, timeoutMs) {
|
|
|
32
32
|
// Wait for close before deleting reports/cache, including after cancellation.
|
|
33
33
|
child.once("close", (exitCode) => {
|
|
34
34
|
clearTimeout(timer); signal?.removeEventListener("abort", abort); kill();
|
|
35
|
-
if (cancelled) reject(failure("connector_cancelled", "The Wiz scan was cancelled.", 499));
|
|
36
|
-
else if (timedOut) reject(failure("connector_timeout", "The Wiz scan exceeded its time limit.", 504));
|
|
37
|
-
else if (startFailed) reject(failure("connector_runner_unavailable", "The Wiz CLI could not be started."));
|
|
35
|
+
if (cancelled) reject(failure("connector_cancelled", "The Wiz scan was cancelled.", 499, { messageCode: "connectors.wiz.scanCancelled" }));
|
|
36
|
+
else if (timedOut) reject(failure("connector_timeout", "The Wiz scan exceeded its time limit.", 504, { messageCode: "connectors.wiz.scanExceededTimeLimit" }));
|
|
37
|
+
else if (startFailed) reject(failure("connector_runner_unavailable", "The Wiz CLI could not be started.", 502, { messageCode: "connectors.wiz.cliCouldNotStarted" }));
|
|
38
38
|
else resolve(exitCode);
|
|
39
39
|
});
|
|
40
40
|
});
|
|
@@ -58,29 +58,29 @@ function createWizScanner({ configuration, authorize, resolveReference, resolveS
|
|
|
58
58
|
|
|
59
59
|
async function scan({ context, integrationId, signal }) {
|
|
60
60
|
const integration = Object.hasOwn(config.integrations, integrationId) ? config.integrations[integrationId] : null;
|
|
61
|
-
if (integration?.provider !== "wiz") throw failure("connector_not_found", "This Wiz integration is not configured.", 404);
|
|
61
|
+
if (integration?.provider !== "wiz") throw failure("connector_not_found", "This Wiz integration is not configured.", 404, { messageCode: "connectors.wiz.integrationNotConfigured" });
|
|
62
62
|
const owner = await authorize(context, { integrationId, operation: "source.scan", accountMode: "shared" });
|
|
63
|
-
if (!owner?.applicationId || !owner?.subjectId) throw failure("connector_access_denied", "Access to this source scan was denied.", 403);
|
|
63
|
+
if (!owner?.applicationId || !owner?.subjectId) throw failure("connector_access_denied", "Access to this source scan was denied.", 403, { messageCode: "connectors.wiz.accessSourceScanDenied" });
|
|
64
64
|
const registration = config.registrations[integration.authentication.registrationRef];
|
|
65
65
|
if (integration.settings.tokenUrl !== "https://auth.app.wiz.io/oauth/token") {
|
|
66
|
-
throw failure("connector_authentication_unsupported", "Auth0 scanning requires a verified compatible Wiz runner.", 501);
|
|
66
|
+
throw failure("connector_authentication_unsupported", "Auth0 scanning requires a verified compatible Wiz runner.", 501, { messageCode: "connectors.wiz.auth0ScanningRequiresVerifiedCompatible" });
|
|
67
67
|
}
|
|
68
|
-
if (signal?.aborted) throw failure("connector_cancelled", "The Wiz scan was cancelled.", 499);
|
|
68
|
+
if (signal?.aborted) throw failure("connector_cancelled", "The Wiz scan was cancelled.", 499, { messageCode: "connectors.wiz.scanCancelled" });
|
|
69
69
|
// The browser supplies no filesystem path. The trusted host selects an immutable
|
|
70
70
|
// source snapshot and revision after checking the requesting principal's access.
|
|
71
71
|
const target = await resolveScanTarget({ ...owner }, { integrationId, signal });
|
|
72
72
|
if (!object(target) || typeof target.directory !== "string" || !path.isAbsolute(target.directory) ||
|
|
73
73
|
target.directory.includes("\0") || typeof target.revision !== "string" || !target.revision.trim() || target.revision.length > 512) {
|
|
74
|
-
throw failure("connector_source_invalid", "The host must supply an absolute source directory and revision.", 422);
|
|
74
|
+
throw failure("connector_source_invalid", "The host must supply an absolute source directory and revision.", 422, { messageCode: "connectors.wiz.hostMustSupplyAbsoluteSource" });
|
|
75
75
|
}
|
|
76
76
|
let directory;
|
|
77
77
|
try { directory = await realpath(target.directory); if (!(await stat(directory)).isDirectory()) throw new Error(); }
|
|
78
|
-
catch { throw failure("connector_source_unavailable", "The authorised source directory is unavailable.", 422); }
|
|
78
|
+
catch { throw failure("connector_source_unavailable", "The authorised source directory is unavailable.", 422, { messageCode: "connectors.wiz.authorisedSourceDirectoryUnavailable" }); }
|
|
79
79
|
let secret;
|
|
80
80
|
try { secret = await resolveReference(registration.clientSecretRef, { ...owner }); }
|
|
81
|
-
catch { throw failure("connector_binding_missing", "The Wiz client-secret reference is unavailable.", 422); }
|
|
81
|
+
catch { throw failure("connector_binding_missing", "The Wiz client-secret reference is unavailable.", 422, { messageCode: "connectors.wiz.clientSecretReferenceUnavailable" }); }
|
|
82
82
|
if (typeof secret !== "string" || !secret.trim() || secret.includes("\0") || secret.length > 16384) {
|
|
83
|
-
throw failure("connector_binding_missing", "The Wiz client-secret reference is invalid.", 422);
|
|
83
|
+
throw failure("connector_binding_missing", "The Wiz client-secret reference is invalid.", 422, { messageCode: "connectors.wiz.clientSecretReferenceInvalid" });
|
|
84
84
|
}
|
|
85
85
|
const temporary = await mkdtemp(path.join(tmpdir(), "jskit-wiz-"));
|
|
86
86
|
try {
|
|
@@ -91,8 +91,8 @@ function createWizScanner({ configuration, authorize, resolveReference, resolveS
|
|
|
91
91
|
const exitCode = await runCli(executable, args, { cwd: temporary,
|
|
92
92
|
env: { ...env, HOME: temporary, TMPDIR: temporary, WIZ_DIR: temporary, WIZ_CLIENT_ID: registration.clientId, WIZ_CLIENT_SECRET: secret }
|
|
93
93
|
}, signal, timeoutMs);
|
|
94
|
-
if (exitCode === 3) throw failure("connector_authentication_failed", "Wiz rejected the service-account credentials.", 401);
|
|
95
|
-
if (exitCode !== 0 && exitCode !== 4) throw failure("connector_scan_failed", "Wiz could not complete the scan. Check the runner, policies and tenant access.");
|
|
94
|
+
if (exitCode === 3) throw failure("connector_authentication_failed", "Wiz rejected the service-account credentials.", 401, { messageCode: "connectors.wiz.rejectedServiceAccountCredentials" });
|
|
95
|
+
if (exitCode !== 0 && exitCode !== 4) throw failure("connector_scan_failed", "Wiz could not complete the scan. Check the runner, policies and tenant access.", 502, { messageCode: "connectors.wiz.couldNotCompleteScanCheck" });
|
|
96
96
|
let report;
|
|
97
97
|
try {
|
|
98
98
|
const file = await open(reportPath, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
|
|
@@ -101,11 +101,11 @@ function createWizScanner({ configuration, authorize, resolveReference, resolveS
|
|
|
101
101
|
if (!info.isFile() || info.size > maxReportBytes) throw new Error();
|
|
102
102
|
report = JSON.parse(await file.readFile("utf8"));
|
|
103
103
|
} finally { await file.close(); }
|
|
104
|
-
} catch { throw failure("connector_response_invalid", "Wiz did not produce a readable report within the configured size limit."); }
|
|
104
|
+
} catch { throw failure("connector_response_invalid", "Wiz did not produce a readable report within the configured size limit.", 502, { messageCode: "connectors.wiz.didNotProduceReadableReport" }); }
|
|
105
105
|
const verdict = report?.status?.verdict;
|
|
106
106
|
if (!object(report) || report.status?.state !== "SUCCESS" || !object(report.result) || !["PASSED_BY_POLICY", "WARN_BY_POLICY", "FAILED_BY_POLICY"].includes(verdict) ||
|
|
107
107
|
(exitCode === 4 && verdict !== "FAILED_BY_POLICY")) {
|
|
108
|
-
throw failure("connector_response_invalid", "Wiz returned an unsupported or inconsistent scan report.");
|
|
108
|
+
throw failure("connector_response_invalid", "Wiz returned an unsupported or inconsistent scan report.", 502, { messageCode: "connectors.wiz.returnedUnsupportedInconsistentScanReport" });
|
|
109
109
|
}
|
|
110
110
|
return { provider: "wiz", integrationId, revision: target.revision,
|
|
111
111
|
policyStatus: verdict === "FAILED_BY_POLICY" ? "blocked" : verdict === "WARN_BY_POLICY" ? "warning" : "passed", report };
|