@automate.ax/integration-contracts 0.145.2 → 0.146.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/dist/highlevel/api.d.ts +43 -0
- package/dist/highlevel/api.js +236 -0
- package/dist/highlevel/events.d.ts +1148 -0
- package/dist/highlevel/events.js +303 -0
- package/dist/highlevel/index.d.ts +6 -0
- package/dist/highlevel/index.js +4 -0
- package/dist/highlevel/openapi-operations.generated.json +10122 -0
- package/dist/highlevel/openapi-types.generated.d.ts +9158 -0
- package/dist/highlevel/openapi-types.generated.js +1 -0
- package/dist/highlevel/operation-manifest.d.ts +608 -0
- package/dist/highlevel/operation-manifest.js +98 -0
- package/dist/highlevel/schemas.d.ts +41 -0
- package/dist/highlevel/schemas.js +39 -0
- package/dist/highlevel/types.d.ts +41 -0
- package/dist/highlevel/types.js +1 -0
- package/dist/resend/action-schemas.d.ts +2 -2
- package/dist/triggers.d.ts +2 -1
- package/package.json +9 -2
- package/src/highlevel/api.ts +294 -0
- package/src/highlevel/events.ts +355 -0
- package/src/highlevel/index.ts +6 -0
- package/src/highlevel/openapi-operations.generated.json +10122 -0
- package/src/highlevel/openapi-types.generated.ts +9928 -0
- package/src/highlevel/operation-manifest.ts +740 -0
- package/src/highlevel/schemas.ts +85 -0
- package/src/highlevel/types.ts +91 -0
- package/src/triggers.ts +2 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/** Complete practical HighLevel CRM action surface. */
|
|
2
|
+
export const HIGH_LEVEL_OPERATION_DEFINITIONS = [
|
|
3
|
+
operation("contacts", "get-contacts", "listContacts", "listHighLevelContacts", "List HighLevel contacts", "Lists contacts in the connected sub-account.", "safe"),
|
|
4
|
+
operation("contacts", "get-contact", "getContact", "getHighLevelContact", "Get HighLevel contact", "Retrieves one contact by ID.", "safe"),
|
|
5
|
+
operation("contacts", "search-contacts-advanced", "searchContacts", "searchHighLevelContacts", "Search HighLevel contacts", "Searches contacts with HighLevel's advanced filters and sorting.", "safe"),
|
|
6
|
+
operation("contacts", "get-duplicate-contact", "findDuplicateContact", "findDuplicateHighLevelContact", "Find duplicate HighLevel contact", "Finds an existing contact by email or phone before creation.", "safe"),
|
|
7
|
+
operation("contacts", "create-contact", "createContact", "createHighLevelContact", "Create HighLevel contact", "Creates a contact in the connected sub-account.", "unsafe"),
|
|
8
|
+
operation("contacts", "upsert-contact", "upsertContact", "upsertHighLevelContact", "Upsert HighLevel contact", "Creates or updates a contact using HighLevel's duplicate-contact policy.", "unsafe"),
|
|
9
|
+
operation("contacts", "update-contact", "updateContact", "updateHighLevelContact", "Update HighLevel contact", "Updates one contact by ID.", "safe"),
|
|
10
|
+
operation("contacts", "delete-contact", "deleteContact", "deleteHighLevelContact", "Delete HighLevel contact", "Permanently deletes one contact by ID.", "safe"),
|
|
11
|
+
operation("contacts", "add-tags", "addContactTags", "addHighLevelContactTags", "Add HighLevel contact tags", "Adds tags to one contact.", "safe"),
|
|
12
|
+
operation("contacts", "remove-tags", "removeContactTags", "removeHighLevelContactTags", "Remove HighLevel contact tags", "Removes tags from one contact.", "safe"),
|
|
13
|
+
operation("contacts", "get-all-tasks", "listContactTasks", "listHighLevelContactTasks", "List HighLevel contact tasks", "Lists tasks attached to one contact.", "safe"),
|
|
14
|
+
operation("contacts", "get-task", "getContactTask", "getHighLevelContactTask", "Get HighLevel contact task", "Retrieves one task attached to a contact.", "safe"),
|
|
15
|
+
operation("contacts", "create-task", "createContactTask", "createHighLevelContactTask", "Create HighLevel contact task", "Creates a task attached to one contact.", "unsafe"),
|
|
16
|
+
operation("contacts", "update-task", "updateContactTask", "updateHighLevelContactTask", "Update HighLevel contact task", "Updates one contact task.", "safe"),
|
|
17
|
+
operation("contacts", "update-task-completed", "completeContactTask", "completeHighLevelContactTask", "Complete HighLevel contact task", "Marks one contact task complete or incomplete.", "safe"),
|
|
18
|
+
operation("contacts", "delete-task", "deleteContactTask", "deleteHighLevelContactTask", "Delete HighLevel contact task", "Deletes one contact task.", "safe"),
|
|
19
|
+
operation("contacts", "get-all-notes", "listContactNotes", "listHighLevelContactNotes", "List HighLevel contact notes", "Lists notes attached to one contact.", "safe"),
|
|
20
|
+
operation("contacts", "get-note", "getContactNote", "getHighLevelContactNote", "Get HighLevel contact note", "Retrieves one note attached to a contact.", "safe"),
|
|
21
|
+
operation("contacts", "create-note", "createContactNote", "createHighLevelContactNote", "Create HighLevel contact note", "Creates a note attached to one contact.", "unsafe"),
|
|
22
|
+
operation("contacts", "update-note", "updateContactNote", "updateHighLevelContactNote", "Update HighLevel contact note", "Updates one contact note.", "safe"),
|
|
23
|
+
operation("contacts", "delete-note", "deleteContactNote", "deleteHighLevelContactNote", "Delete HighLevel contact note", "Deletes one contact note.", "safe"),
|
|
24
|
+
operation("contacts", "add-contact-to-campaign", "addContactToCampaign", "addHighLevelContactToCampaign", "Add HighLevel contact to campaign", "Adds one contact to a campaign.", "unsafe"),
|
|
25
|
+
operation("contacts", "remove-contact-from-campaign", "removeContactFromCampaign", "removeHighLevelContactFromCampaign", "Remove HighLevel contact from campaign", "Removes one contact from a campaign.", "safe"),
|
|
26
|
+
operation("contacts", "add-contact-to-workflow", "addContactToWorkflow", "addHighLevelContactToWorkflow", "Add HighLevel contact to workflow", "Adds one contact to a workflow.", "unsafe"),
|
|
27
|
+
operation("contacts", "delete-contact-from-workflow", "removeContactFromWorkflow", "removeHighLevelContactFromWorkflow", "Remove HighLevel contact from workflow", "Removes one contact from a workflow.", "safe"),
|
|
28
|
+
operation("opportunities", "search-opportunity", "searchOpportunities", "searchHighLevelOpportunities", "Search HighLevel opportunities", "Searches opportunities with pipeline, status, owner, and pagination filters.", "safe"),
|
|
29
|
+
operation("opportunities", "get-opportunity", "getOpportunity", "getHighLevelOpportunity", "Get HighLevel opportunity", "Retrieves one opportunity by ID.", "safe"),
|
|
30
|
+
operation("opportunities", "create-opportunity", "createOpportunity", "createHighLevelOpportunity", "Create HighLevel opportunity", "Creates an opportunity in a pipeline.", "unsafe"),
|
|
31
|
+
operation("opportunities", "Upsert-opportunity", "upsertOpportunity", "upsertHighLevelOpportunity", "Upsert HighLevel opportunity", "Creates or updates an opportunity using HighLevel's matching rules.", "unsafe"),
|
|
32
|
+
operation("opportunities", "update-opportunity", "updateOpportunity", "updateHighLevelOpportunity", "Update HighLevel opportunity", "Updates one opportunity by ID.", "safe"),
|
|
33
|
+
operation("opportunities", "update-opportunity-status", "updateOpportunityStatus", "updateHighLevelOpportunityStatus", "Update HighLevel opportunity status", "Changes one opportunity's open, won, lost, or abandoned status.", "safe"),
|
|
34
|
+
operation("opportunities", "delete-opportunity", "deleteOpportunity", "deleteHighLevelOpportunity", "Delete HighLevel opportunity", "Deletes one opportunity by ID.", "safe"),
|
|
35
|
+
operation("opportunities", "get-pipelines", "listPipelines", "listHighLevelPipelines", "List HighLevel pipelines", "Lists the connected sub-account's opportunity pipelines and stages.", "safe"),
|
|
36
|
+
operation("opportunities", "get-lost-reason", "listOpportunityLostReasons", "listHighLevelOpportunityLostReasons", "List HighLevel opportunity lost reasons", "Lists configured reasons for lost opportunities.", "safe"),
|
|
37
|
+
operation("calendars", "get-calendars", "listCalendars", "listHighLevelCalendars", "List HighLevel calendars", "Lists calendars in the connected sub-account.", "safe"),
|
|
38
|
+
operation("calendars", "get-calendar", "getCalendar", "getHighLevelCalendar", "Get HighLevel calendar", "Retrieves one calendar by ID.", "safe"),
|
|
39
|
+
operation("calendars", "create-calendar", "createCalendar", "createHighLevelCalendar", "Create HighLevel calendar", "Creates a calendar in the connected sub-account.", "unsafe"),
|
|
40
|
+
operation("calendars", "update-calendar", "updateCalendar", "updateHighLevelCalendar", "Update HighLevel calendar", "Updates one calendar by ID.", "safe"),
|
|
41
|
+
operation("calendars", "delete-calendar", "deleteCalendar", "deleteHighLevelCalendar", "Delete HighLevel calendar", "Deletes one calendar by ID.", "safe"),
|
|
42
|
+
operation("calendars", "get-slots", "getCalendarFreeSlots", "getHighLevelCalendarFreeSlots", "Get HighLevel calendar free slots", "Returns available slots for a calendar and date range.", "safe"),
|
|
43
|
+
operation("calendars", "get-calendar-events", "listAppointments", "listHighLevelAppointments", "List HighLevel appointments", "Lists calendar events and appointments in a date range.", "safe"),
|
|
44
|
+
operation("calendars", "get-appointment", "getAppointment", "getHighLevelAppointment", "Get HighLevel appointment", "Retrieves one appointment by event ID.", "safe"),
|
|
45
|
+
operation("calendars", "create-appointment", "createAppointment", "createHighLevelAppointment", "Create HighLevel appointment", "Creates an appointment on a calendar.", "unsafe"),
|
|
46
|
+
operation("calendars", "edit-appointment", "updateAppointment", "updateHighLevelAppointment", "Update HighLevel appointment", "Updates one calendar appointment.", "safe"),
|
|
47
|
+
operation("calendars", "delete-event", "deleteAppointment", "deleteHighLevelAppointment", "Delete HighLevel appointment", "Deletes one calendar event or appointment.", "safe"),
|
|
48
|
+
operation("calendars", "get-blocked-slots", "listBlockedSlots", "listHighLevelBlockedSlots", "List HighLevel blocked slots", "Lists blocked calendar slots in a date range.", "safe"),
|
|
49
|
+
operation("calendars", "create-block-slot", "createBlockedSlot", "createHighLevelBlockedSlot", "Create HighLevel blocked slot", "Blocks a time range on a calendar.", "unsafe"),
|
|
50
|
+
operation("calendars", "edit-block-slot", "updateBlockedSlot", "updateHighLevelBlockedSlot", "Update HighLevel blocked slot", "Updates one blocked calendar slot.", "safe"),
|
|
51
|
+
operation("calendars", "getAllSchedules", "listSchedules", "listHighLevelSchedules", "List HighLevel schedules", "Lists availability schedules for the connected sub-account.", "safe"),
|
|
52
|
+
operation("calendars", "getScheduleById", "getSchedule", "getHighLevelSchedule", "Get HighLevel schedule", "Retrieves one availability schedule by ID.", "safe"),
|
|
53
|
+
operation("calendars", "createSchedule", "createSchedule", "createHighLevelSchedule", "Create HighLevel schedule", "Creates an availability schedule.", "unsafe"),
|
|
54
|
+
operation("calendars", "updateSchedule", "updateSchedule", "updateHighLevelSchedule", "Update HighLevel schedule", "Updates one availability schedule.", "safe"),
|
|
55
|
+
operation("calendars", "deleteSchedule", "deleteSchedule", "deleteHighLevelSchedule", "Delete HighLevel schedule", "Deletes one availability schedule.", "safe"),
|
|
56
|
+
operation("conversations", "search-conversation", "searchConversations", "searchHighLevelConversations", "Search HighLevel conversations", "Searches conversations by contact, assignment, status, and pagination.", "safe"),
|
|
57
|
+
operation("conversations", "get-conversation", "getConversation", "getHighLevelConversation", "Get HighLevel conversation", "Retrieves one conversation by ID.", "safe"),
|
|
58
|
+
operation("conversations", "create-conversation", "createConversation", "createHighLevelConversation", "Create HighLevel conversation", "Creates a conversation for a contact.", "unsafe"),
|
|
59
|
+
operation("conversations", "update-conversation", "updateConversation", "updateHighLevelConversation", "Update HighLevel conversation", "Updates assignment, status, or read state for one conversation.", "safe"),
|
|
60
|
+
operation("conversations", "delete-conversation", "deleteConversation", "deleteHighLevelConversation", "Delete HighLevel conversation", "Deletes one conversation by ID.", "safe"),
|
|
61
|
+
operation("conversations", "get-messages", "listMessages", "listHighLevelMessages", "List HighLevel messages", "Lists messages in one conversation.", "safe"),
|
|
62
|
+
operation("conversations", "get-message", "getMessage", "getHighLevelMessage", "Get HighLevel message", "Retrieves one message by ID.", "safe"),
|
|
63
|
+
operation("conversations", "send-a-new-message", "sendMessage", "sendHighLevelMessage", "Send HighLevel message", "Sends a supported message through a contact conversation.", "unsafe"),
|
|
64
|
+
operation("conversations", "cancel-scheduled-message", "cancelScheduledMessage", "cancelScheduledHighLevelMessage", "Cancel scheduled HighLevel message", "Cancels one scheduled message before delivery.", "safe"),
|
|
65
|
+
operation("conversations", "get-message-recording", "getMessageRecording", "getHighLevelMessageRecording", "Get HighLevel message recording", "Returns the recording for a voice or call message.", "safe"),
|
|
66
|
+
operation("conversations", "get-message-transcription", "getMessageTranscription", "getHighLevelMessageTranscription", "Get HighLevel message transcription", "Returns the transcription for a supported message.", "safe"),
|
|
67
|
+
operation("locations", "get-location", "getLocation", "getHighLevelLocation", "Get HighLevel location", "Retrieves the connected sub-account's location record.", "safe"),
|
|
68
|
+
operation("users", "get-user-by-location", "listUsers", "listHighLevelUsers", "List HighLevel users", "Lists users assigned to the connected sub-account.", "safe"),
|
|
69
|
+
operation("users", "get-user", "getUser", "getHighLevelUser", "Get HighLevel user", "Retrieves one user by ID.", "safe"),
|
|
70
|
+
operation("campaigns", "get-campaigns", "listCampaigns", "listHighLevelCampaigns", "List HighLevel campaigns", "Lists campaigns in the connected sub-account.", "safe"),
|
|
71
|
+
operation("workflows", "get-workflow", "listWorkflows", "listHighLevelWorkflows", "List HighLevel workflows", "Lists workflows in the connected sub-account.", "safe"),
|
|
72
|
+
operation("forms", "get-forms", "listForms", "listHighLevelForms", "List HighLevel forms", "Lists forms in the connected sub-account.", "safe"),
|
|
73
|
+
operation("forms", "get-forms-submissions", "listFormSubmissions", "listHighLevelFormSubmissions", "List HighLevel form submissions", "Lists form submissions with date and pagination filters.", "safe"),
|
|
74
|
+
operation("surveys", "get-surveys", "listSurveys", "listHighLevelSurveys", "List HighLevel surveys", "Lists surveys in the connected sub-account.", "safe"),
|
|
75
|
+
operation("surveys", "get-surveys-submissions", "listSurveySubmissions", "listHighLevelSurveySubmissions", "List HighLevel survey submissions", "Lists survey submissions with date and pagination filters.", "safe"),
|
|
76
|
+
];
|
|
77
|
+
/**
|
|
78
|
+
* Defines one public HighLevel action bound to an official operation.
|
|
79
|
+
*
|
|
80
|
+
* @param product - Provider OpenAPI product.
|
|
81
|
+
* @param operationId - Official operation identifier.
|
|
82
|
+
* @param alias - Public object alias.
|
|
83
|
+
* @param exportName - Named SDK export.
|
|
84
|
+
* @param title - Action title.
|
|
85
|
+
* @param description - Action description.
|
|
86
|
+
* @param replaySafety - Automatic replay classification.
|
|
87
|
+
*/
|
|
88
|
+
function operation(product, operationId, alias, exportName, title, description, replaySafety) {
|
|
89
|
+
return {
|
|
90
|
+
alias,
|
|
91
|
+
description,
|
|
92
|
+
exportName,
|
|
93
|
+
operationId,
|
|
94
|
+
product,
|
|
95
|
+
replaySafety,
|
|
96
|
+
title,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import type { HighLevelOperationKey } from "./operation-manifest.js";
|
|
3
|
+
import type { HighLevelOperationInput, HighLevelOperationOutput } from "./types.js";
|
|
4
|
+
interface HighLevelRuntimeOperation {
|
|
5
|
+
apiVersion: string;
|
|
6
|
+
bodyParameters: string[];
|
|
7
|
+
inputSchema: Record<string, unknown>;
|
|
8
|
+
locationPlacements: ("body" | "path" | "query")[];
|
|
9
|
+
locationParameterNames: Partial<Record<"body" | "path" | "query", string>>;
|
|
10
|
+
method: "DELETE" | "GET" | "PATCH" | "POST" | "PUT";
|
|
11
|
+
outputSchema: Record<string, unknown>;
|
|
12
|
+
path: string;
|
|
13
|
+
pathParameters: string[];
|
|
14
|
+
queryParameters: {
|
|
15
|
+
explode: boolean;
|
|
16
|
+
name: string;
|
|
17
|
+
providerName: string;
|
|
18
|
+
style: string;
|
|
19
|
+
}[];
|
|
20
|
+
responseMode: "binary" | "json";
|
|
21
|
+
requiredScope: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Returns the immutable runtime descriptor for one HighLevel operation.
|
|
25
|
+
*
|
|
26
|
+
* @param key - Frozen operation key.
|
|
27
|
+
*/
|
|
28
|
+
export declare function highLevelOperation<TKey extends HighLevelOperationKey>(key: TKey): Record<HighLevelOperationKey, HighLevelRuntimeOperation>[TKey];
|
|
29
|
+
/**
|
|
30
|
+
* Validates flattened input for one frozen HighLevel operation.
|
|
31
|
+
*
|
|
32
|
+
* @param key - Frozen operation key.
|
|
33
|
+
*/
|
|
34
|
+
export declare function highLevelOperationInputSchema<TKey extends HighLevelOperationKey>(key: TKey): z.ZodType<HighLevelOperationInput<TKey>>;
|
|
35
|
+
/**
|
|
36
|
+
* Validates the documented success response for one HighLevel operation.
|
|
37
|
+
*
|
|
38
|
+
* @param key - Frozen operation key.
|
|
39
|
+
*/
|
|
40
|
+
export declare function highLevelOperationOutputSchema<TKey extends HighLevelOperationKey>(key: TKey): z.ZodType<HighLevelOperationOutput<TKey>>;
|
|
41
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/* oxlint-disable typescript/no-unsafe-type-assertion -- Generated operation keys index a frozen external contract. */
|
|
2
|
+
import { Validator } from "@cfworker/json-schema";
|
|
3
|
+
import * as z from "zod";
|
|
4
|
+
import operationData from "./openapi-operations.generated.json" with { type: "json" };
|
|
5
|
+
const OPERATIONS = operationData.operations;
|
|
6
|
+
const VALIDATOR = new Validator({
|
|
7
|
+
$defs: operationData.definitions,
|
|
8
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
9
|
+
additionalProperties: false,
|
|
10
|
+
properties: Object.fromEntries(Object.entries(OPERATIONS).flatMap(([key, operation]) => [
|
|
11
|
+
[`${key}:input`, operation.inputSchema],
|
|
12
|
+
[`${key}:output`, operation.outputSchema],
|
|
13
|
+
])),
|
|
14
|
+
type: "object",
|
|
15
|
+
}, "2020-12");
|
|
16
|
+
/**
|
|
17
|
+
* Returns the immutable runtime descriptor for one HighLevel operation.
|
|
18
|
+
*
|
|
19
|
+
* @param key - Frozen operation key.
|
|
20
|
+
*/
|
|
21
|
+
export function highLevelOperation(key) {
|
|
22
|
+
return OPERATIONS[key];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Validates flattened input for one frozen HighLevel operation.
|
|
26
|
+
*
|
|
27
|
+
* @param key - Frozen operation key.
|
|
28
|
+
*/
|
|
29
|
+
export function highLevelOperationInputSchema(key) {
|
|
30
|
+
return z.custom((value) => VALIDATOR.validate({ [`${key}:input`]: value }).valid, { message: `Input does not match HighLevel operation ${key}.` });
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Validates the documented success response for one HighLevel operation.
|
|
34
|
+
*
|
|
35
|
+
* @param key - Frozen operation key.
|
|
36
|
+
*/
|
|
37
|
+
export function highLevelOperationOutputSchema(key) {
|
|
38
|
+
return z.custom((value) => VALIDATOR.validate({ [`${key}:output`]: value }).valid, { message: `Output does not match HighLevel operation ${key}.` });
|
|
39
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Encodable } from "@automate.ax/codec";
|
|
2
|
+
import type { HighLevelOperationMap } from "./openapi-types.generated";
|
|
3
|
+
import type { HighLevelOperationKey } from "./operation-manifest.js";
|
|
4
|
+
type Operation<TKey extends HighLevelOperationKey> = TKey extends keyof HighLevelOperationMap ? HighLevelOperationMap[TKey] : never;
|
|
5
|
+
type Parameters<TOperation, TLocation extends string> = TOperation extends {
|
|
6
|
+
parameters: infer TParameters;
|
|
7
|
+
} ? TLocation extends keyof TParameters ? NonNullable<TParameters[TLocation]> : object : object;
|
|
8
|
+
/** JSON request body from one generated OpenAPI operation. */
|
|
9
|
+
type JsonBody<TOperation> = TOperation extends {
|
|
10
|
+
requestBody: infer TBody;
|
|
11
|
+
} ? NonNullable<TBody> extends {
|
|
12
|
+
content: infer TContent;
|
|
13
|
+
} ? "application/json" extends keyof TContent ? TContent["application/json"] : object : object : object;
|
|
14
|
+
/** JSON payload from one generated response entry. */
|
|
15
|
+
type JsonResponse<TResponse> = TResponse extends {
|
|
16
|
+
content: infer TContent;
|
|
17
|
+
} ? "application/json" extends keyof TContent ? TContent["application/json"] : null : null;
|
|
18
|
+
/** First supported successful response for one operation. */
|
|
19
|
+
type SuccessResponse<TOperation> = TOperation extends {
|
|
20
|
+
responses: infer TResponses;
|
|
21
|
+
} ? JsonResponse<TResponses[Extract<keyof TResponses, 200 | 201 | 202 | 203 | 204 | "default">]> : never;
|
|
22
|
+
type SnakeToCamel<TValue extends string> = TValue extends `${infer THead}_${infer TTail}` ? `${THead}${Capitalize<SnakeToCamel<TTail>>}` : TValue;
|
|
23
|
+
type PublicKeys<TValue> = TValue extends unknown ? {
|
|
24
|
+
[TKey in keyof TValue as TKey extends string ? SnakeToCamel<TKey> : TKey]: TValue[TKey];
|
|
25
|
+
} : never;
|
|
26
|
+
type WithoutLocationId<TValue> = TValue extends unknown ? Omit<TValue, "locationId" | "location_id"> : never;
|
|
27
|
+
/** Flattens intersections for public editor display. */
|
|
28
|
+
type Simplify<TValue> = {
|
|
29
|
+
[TKey in keyof TValue]: TValue[TKey];
|
|
30
|
+
} & {};
|
|
31
|
+
type EncodableValue<TValue> = unknown extends TValue ? Encodable : TValue extends undefined | null | boolean | number | string ? TValue : TValue extends readonly (infer TItem)[] ? EncodableValue<TItem>[] : TValue extends object ? keyof TValue extends never ? Record<string, Encodable> : {
|
|
32
|
+
[TKey in keyof TValue]: EncodableValue<TValue[TKey]>;
|
|
33
|
+
} : never;
|
|
34
|
+
type HighLevelRawOperationInput<TKey extends HighLevelOperationKey> = Simplify<PublicKeys<WithoutLocationId<Parameters<Operation<TKey>, "path">>> & PublicKeys<WithoutLocationId<Parameters<Operation<TKey>, "query">>> & PublicKeys<WithoutLocationId<JsonBody<Operation<TKey>>>>>;
|
|
35
|
+
/** Flattened, location-safe input for one frozen HighLevel operation. */
|
|
36
|
+
export type HighLevelOperationInput<TKey extends HighLevelOperationKey> = {
|
|
37
|
+
[TField in keyof HighLevelRawOperationInput<TKey>]: EncodableValue<HighLevelRawOperationInput<TKey>[TField]>;
|
|
38
|
+
};
|
|
39
|
+
/** Documented successful JSON response for one frozen HighLevel operation. */
|
|
40
|
+
export type HighLevelOperationOutput<TKey extends HighLevelOperationKey> = EncodableValue<SuccessResponse<Operation<TKey>>>;
|
|
41
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -670,8 +670,8 @@ export declare const RESEND_CONTACT_TOPIC_SCHEMA: z.ZodObject<{
|
|
|
670
670
|
id: z.ZodString;
|
|
671
671
|
name: z.ZodString;
|
|
672
672
|
subscription: z.ZodEnum<{
|
|
673
|
-
opt_in: "opt_in";
|
|
674
673
|
opt_out: "opt_out";
|
|
674
|
+
opt_in: "opt_in";
|
|
675
675
|
}>;
|
|
676
676
|
}, z.core.$strip>;
|
|
677
677
|
export declare const RESEND_CONTACT_SEGMENT_DELETE_WIRE_SCHEMA: z.ZodObject<{
|
|
@@ -717,8 +717,8 @@ export declare const RESEND_CONTACT_TOPICS_UPDATE_SCHEMA: z.ZodObject<{
|
|
|
717
717
|
topics: z.ZodArray<z.ZodObject<{
|
|
718
718
|
id: z.ZodString;
|
|
719
719
|
subscription: z.ZodEnum<{
|
|
720
|
-
opt_in: "opt_in";
|
|
721
720
|
opt_out: "opt_out";
|
|
721
|
+
opt_in: "opt_in";
|
|
722
722
|
}>;
|
|
723
723
|
}, z.core.$strip>>;
|
|
724
724
|
}, z.core.$strip>;
|
package/dist/triggers.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ import type { googleMeetTriggerContracts } from "./google-meet/index.js";
|
|
|
21
21
|
import type { googleAdsTriggerContracts } from "./google-ads/index.js";
|
|
22
22
|
import type { googleSheetsTriggerContracts } from "./google-sheets/index.js";
|
|
23
23
|
import type { hubspotTriggerContracts } from "./hubspot/index.js";
|
|
24
|
+
import type { highLevelTriggerContracts } from "./highlevel/index.js";
|
|
24
25
|
import type { linearTriggerContracts } from "./linear/index.js";
|
|
25
26
|
import type { millionVerifierTriggerContracts } from "./millionverifier/index.js";
|
|
26
27
|
import type { metaAdsTriggerContracts } from "./meta-ads/index.js";
|
|
@@ -36,7 +37,7 @@ import type { vercelTriggerContracts } from "./vercel/index.js";
|
|
|
36
37
|
import type { webflowTriggerContracts } from "./webflow/index.js";
|
|
37
38
|
import type { whatsappTriggerContracts } from "./whatsapp/index.js";
|
|
38
39
|
import type { z } from "zod";
|
|
39
|
-
export type TriggerContractMap = typeof airtableTriggerContracts & typeof anthropicTriggerContracts & typeof apifyTriggerContracts & typeof axiomTriggerContracts & typeof automateTriggerContracts & typeof asanaTriggerContracts & typeof brevoTriggerContracts & typeof calcomTriggerContracts & typeof convexTriggerContracts & typeof discordTriggerContracts & typeof closeTriggerContracts & typeof clickUpTriggerContracts & typeof calendlyTriggerContracts & typeof cloudflareTriggerContracts & typeof githubTriggerContracts & typeof gmailTriggerContracts & typeof googleCalendarTriggerContracts & typeof googleDriveTriggerContracts & typeof googleFormsTriggerContracts & typeof googleMeetTriggerContracts & typeof googleAdsTriggerContracts & typeof googleSheetsTriggerContracts & typeof hubspotTriggerContracts & typeof linearTriggerContracts & typeof millionVerifierTriggerContracts & typeof metaAdsTriggerContracts & typeof notionTriggerContracts & typeof outlookTriggerContracts & typeof redditTriggerContracts & typeof resendTriggerContracts & typeof slackTriggerContracts & typeof stripeTriggerContracts & typeof teamsTriggerContracts & typeof trelloTriggerContracts & typeof vercelTriggerContracts & typeof webflowTriggerContracts & typeof whatsappTriggerContracts;
|
|
40
|
+
export type TriggerContractMap = typeof airtableTriggerContracts & typeof anthropicTriggerContracts & typeof apifyTriggerContracts & typeof axiomTriggerContracts & typeof automateTriggerContracts & typeof asanaTriggerContracts & typeof brevoTriggerContracts & typeof calcomTriggerContracts & typeof convexTriggerContracts & typeof discordTriggerContracts & typeof closeTriggerContracts & typeof clickUpTriggerContracts & typeof calendlyTriggerContracts & typeof cloudflareTriggerContracts & typeof githubTriggerContracts & typeof gmailTriggerContracts & typeof googleCalendarTriggerContracts & typeof googleDriveTriggerContracts & typeof googleFormsTriggerContracts & typeof googleMeetTriggerContracts & typeof googleAdsTriggerContracts & typeof googleSheetsTriggerContracts & typeof hubspotTriggerContracts & typeof highLevelTriggerContracts & typeof linearTriggerContracts & typeof millionVerifierTriggerContracts & typeof metaAdsTriggerContracts & typeof notionTriggerContracts & typeof outlookTriggerContracts & typeof redditTriggerContracts & typeof resendTriggerContracts & typeof slackTriggerContracts & typeof stripeTriggerContracts & typeof teamsTriggerContracts & typeof trelloTriggerContracts & typeof vercelTriggerContracts & typeof webflowTriggerContracts & typeof whatsappTriggerContracts;
|
|
40
41
|
export type IntegrationTriggerType = keyof TriggerContractMap;
|
|
41
42
|
/** Canonical authoring configuration for one integration trigger type. */
|
|
42
43
|
export type TriggerConfig<TType extends IntegrationTriggerType> = z.input<TriggerContractMap[TType]["configSchema"]> extends Record<string, never> ? object : z.input<TriggerContractMap[TType]["configSchema"]>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automate.ax/integration-contracts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.146.0",
|
|
4
4
|
"description": "Shared integration payload contracts and provider primitives for Automate.ax.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"./google-sheets": "./src/google-sheets/index.ts",
|
|
44
44
|
"./github": "./src/github/index.ts",
|
|
45
45
|
"./hubspot": "./src/hubspot/index.ts",
|
|
46
|
+
"./highlevel": "./src/highlevel/index.ts",
|
|
46
47
|
"./jobnimbus": "./src/jobnimbus/index.ts",
|
|
47
48
|
"./linear": "./src/linear/index.ts",
|
|
48
49
|
"./millionverifier": "./src/millionverifier/index.ts",
|
|
@@ -67,7 +68,7 @@
|
|
|
67
68
|
},
|
|
68
69
|
"dependencies": {
|
|
69
70
|
"@anthropic-ai/sdk": "0.123.0",
|
|
70
|
-
"@automate.ax/codec": "0.
|
|
71
|
+
"@automate.ax/codec": "0.146.0",
|
|
71
72
|
"@cfworker/json-schema": "^4.1.1",
|
|
72
73
|
"@googleapis/calendar": "^16.0.0",
|
|
73
74
|
"@googleapis/forms": "^6.0.1",
|
|
@@ -103,6 +104,7 @@
|
|
|
103
104
|
"scripts": {
|
|
104
105
|
"generate:github": "bun scripts/generate-github-webhook-schemas.ts",
|
|
105
106
|
"generate:calcom": "bun scripts/generate-calcom-openapi.ts",
|
|
107
|
+
"generate:highlevel": "bun scripts/generate-highlevel-openapi.ts",
|
|
106
108
|
"typecheck": "resource-broker run --pool automate-ax-validation --limit 2 --weight 1 -- tsc --noEmit",
|
|
107
109
|
"lint": "oxlint --type-aware --threads=2 && bun --bun eslint . --cache --cache-strategy content",
|
|
108
110
|
"lint:fix": "oxlint --type-aware --threads=2 --fix --fix-suggestions && bun --bun eslint . --fix --cache --cache-strategy content",
|
|
@@ -246,6 +248,11 @@
|
|
|
246
248
|
"types": "./dist/hubspot/index.d.ts",
|
|
247
249
|
"default": "./dist/hubspot/index.js"
|
|
248
250
|
},
|
|
251
|
+
"./highlevel": {
|
|
252
|
+
"bun": "./src/highlevel/index.ts",
|
|
253
|
+
"types": "./dist/highlevel/index.d.ts",
|
|
254
|
+
"default": "./dist/highlevel/index.js"
|
|
255
|
+
},
|
|
249
256
|
"./jobnimbus": {
|
|
250
257
|
"bun": "./src/jobnimbus/index.ts",
|
|
251
258
|
"types": "./dist/jobnimbus/index.d.ts",
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import { encodableSchema, type Encodable } from "@automate.ax/codec"
|
|
2
|
+
import * as z from "zod"
|
|
3
|
+
import type { HighLevelOperationKey } from "./operation-manifest"
|
|
4
|
+
import { highLevelOperation, highLevelOperationOutputSchema } from "./schemas"
|
|
5
|
+
import type { HighLevelOperationInput, HighLevelOperationOutput } from "./types"
|
|
6
|
+
|
|
7
|
+
const HIGH_LEVEL_API_BASE_URL = "https://services.leadconnectorhq.com/"
|
|
8
|
+
const HIGH_LEVEL_API_ORIGIN = new URL(HIGH_LEVEL_API_BASE_URL).origin
|
|
9
|
+
const HIGH_LEVEL_SECRET_SCHEMA = z.object({
|
|
10
|
+
accessToken: z.string().min(1),
|
|
11
|
+
locationId: z.string().min(1),
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
/** Resolved account accepted by the shared HighLevel API client. */
|
|
15
|
+
export interface HighLevelResolvedAccount {
|
|
16
|
+
connectionMethodId: string
|
|
17
|
+
secret: Record<string, unknown>
|
|
18
|
+
serviceId: "highlevel"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Structured error returned by a rejected HighLevel request. */
|
|
22
|
+
export class HighLevelApiError extends Error {
|
|
23
|
+
readonly body?: Encodable
|
|
24
|
+
readonly retryAfter?: string
|
|
25
|
+
readonly status: number
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Creates an error from one rejected HighLevel response.
|
|
29
|
+
*
|
|
30
|
+
* @param options - Rejected response details.
|
|
31
|
+
* @param options.body - Encodable provider error body.
|
|
32
|
+
* @param options.retryAfter - Provider retry timing.
|
|
33
|
+
* @param options.status - HTTP status.
|
|
34
|
+
*/
|
|
35
|
+
constructor(options: {
|
|
36
|
+
body?: Encodable
|
|
37
|
+
retryAfter?: string
|
|
38
|
+
status: number
|
|
39
|
+
}) {
|
|
40
|
+
super(
|
|
41
|
+
getErrorMessage(options.body) ??
|
|
42
|
+
`HighLevel API request failed with status ${options.status}.`,
|
|
43
|
+
)
|
|
44
|
+
this.name = "HighLevelApiError"
|
|
45
|
+
this.body = options.body
|
|
46
|
+
this.retryAfter = options.retryAfter
|
|
47
|
+
this.status = options.status
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Creates an authenticated client for the frozen HighLevel action surface.
|
|
53
|
+
*
|
|
54
|
+
* @param account - Resolved HighLevel account.
|
|
55
|
+
* @throws When the connection method or secret is invalid.
|
|
56
|
+
*/
|
|
57
|
+
export function getHighLevelApi(account: HighLevelResolvedAccount) {
|
|
58
|
+
const credentials = HIGH_LEVEL_SECRET_SCHEMA.parse(account.secret)
|
|
59
|
+
if (
|
|
60
|
+
account.connectionMethodId !== "oauth" &&
|
|
61
|
+
account.connectionMethodId !== "private-integration-token"
|
|
62
|
+
) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
`Unsupported HighLevel connection method: ${account.connectionMethodId}`,
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
/**
|
|
70
|
+
* Executes and validates one named HighLevel OpenAPI operation.
|
|
71
|
+
*
|
|
72
|
+
* @param key - Frozen operation key.
|
|
73
|
+
* @param input - Flattened operation input.
|
|
74
|
+
*/
|
|
75
|
+
async operation<TKey extends HighLevelOperationKey>(
|
|
76
|
+
key: TKey,
|
|
77
|
+
input: HighLevelOperationInput<TKey>,
|
|
78
|
+
): Promise<HighLevelOperationOutput<TKey>> {
|
|
79
|
+
const definition = highLevelOperation(key)
|
|
80
|
+
const pathValues = new Map<string, unknown>()
|
|
81
|
+
const queryValues = new Map<string, unknown>()
|
|
82
|
+
const bodyValues: Record<string, unknown> = {}
|
|
83
|
+
const inputRecord = input as Record<string, unknown>
|
|
84
|
+
|
|
85
|
+
for (const name of definition.pathParameters) {
|
|
86
|
+
pathValues.set(name, inputRecord[name])
|
|
87
|
+
}
|
|
88
|
+
for (const { name } of definition.queryParameters) {
|
|
89
|
+
queryValues.set(name, inputRecord[name])
|
|
90
|
+
}
|
|
91
|
+
for (const name of definition.bodyParameters) {
|
|
92
|
+
if (inputRecord[name] !== undefined)
|
|
93
|
+
bodyValues[name] = inputRecord[name]
|
|
94
|
+
}
|
|
95
|
+
for (const placement of definition.locationPlacements) {
|
|
96
|
+
if (placement === "path")
|
|
97
|
+
pathValues.set("locationId", credentials.locationId)
|
|
98
|
+
if (placement === "query")
|
|
99
|
+
queryValues.set("locationId", credentials.locationId)
|
|
100
|
+
if (placement === "body") bodyValues.locationId = credentials.locationId
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Resolve path placeholders before applying the fixed-origin guard.
|
|
104
|
+
const path = definition.path.replace(
|
|
105
|
+
/\{([^}]+)\}/g,
|
|
106
|
+
(_match, name: string) => encodePathSegment(pathValues.get(name), name),
|
|
107
|
+
)
|
|
108
|
+
const normalizedPath = path.replace(/^\/+/, "")
|
|
109
|
+
const url = new URL(normalizedPath, HIGH_LEVEL_API_BASE_URL)
|
|
110
|
+
if (
|
|
111
|
+
!normalizedPath ||
|
|
112
|
+
normalizedPath.includes("://") ||
|
|
113
|
+
normalizedPath.includes("\\") ||
|
|
114
|
+
normalizedPath.includes("?") ||
|
|
115
|
+
normalizedPath.includes("#") ||
|
|
116
|
+
url.origin !== HIGH_LEVEL_API_ORIGIN
|
|
117
|
+
) {
|
|
118
|
+
throw new TypeError(
|
|
119
|
+
"HighLevel API paths must remain provider-relative.",
|
|
120
|
+
)
|
|
121
|
+
}
|
|
122
|
+
for (const parameter of definition.queryParameters) {
|
|
123
|
+
appendQuery(
|
|
124
|
+
url,
|
|
125
|
+
{ ...parameter, name: parameter.providerName },
|
|
126
|
+
queryValues.get(parameter.name),
|
|
127
|
+
)
|
|
128
|
+
}
|
|
129
|
+
if (definition.locationPlacements.includes("query")) {
|
|
130
|
+
url.searchParams.set(
|
|
131
|
+
definition.locationParameterNames.query ?? "locationId",
|
|
132
|
+
credentials.locationId,
|
|
133
|
+
)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const hasBody =
|
|
137
|
+
definition.bodyParameters.length > 0 ||
|
|
138
|
+
definition.locationPlacements.includes("body")
|
|
139
|
+
const response = await fetch(url, {
|
|
140
|
+
body: hasBody ? JSON.stringify(bodyValues) : undefined,
|
|
141
|
+
headers: {
|
|
142
|
+
Accept: "application/json",
|
|
143
|
+
Authorization: `Bearer ${credentials.accessToken}`,
|
|
144
|
+
Version: definition.apiVersion,
|
|
145
|
+
...(hasBody ? { "Content-Type": "application/json" } : {}),
|
|
146
|
+
},
|
|
147
|
+
method: definition.method,
|
|
148
|
+
redirect: "error",
|
|
149
|
+
})
|
|
150
|
+
const parsed =
|
|
151
|
+
response.ok && definition.responseMode === "binary"
|
|
152
|
+
? {
|
|
153
|
+
contentType:
|
|
154
|
+
response.headers.get("Content-Type") ??
|
|
155
|
+
"application/octet-stream",
|
|
156
|
+
data: Buffer.from(await response.arrayBuffer()).toString(
|
|
157
|
+
"base64",
|
|
158
|
+
),
|
|
159
|
+
}
|
|
160
|
+
: await parseResponseText(response)
|
|
161
|
+
if (!response.ok) {
|
|
162
|
+
const body = encodableSchema.safeParse(parsed)
|
|
163
|
+
throw new HighLevelApiError({
|
|
164
|
+
...(body.success && { body: body.data }),
|
|
165
|
+
retryAfter: getRetryAfter(response.headers),
|
|
166
|
+
status: response.status,
|
|
167
|
+
})
|
|
168
|
+
}
|
|
169
|
+
return highLevelOperationOutputSchema(key).parse(parsed)
|
|
170
|
+
},
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Encodes one required path parameter.
|
|
176
|
+
*
|
|
177
|
+
* @param value - Parameter value.
|
|
178
|
+
* @param name - Parameter name.
|
|
179
|
+
* @throws When the value is not scalar.
|
|
180
|
+
*/
|
|
181
|
+
function encodePathSegment(value: unknown, name: string) {
|
|
182
|
+
if (typeof value !== "number" && typeof value !== "string") {
|
|
183
|
+
throw new TypeError(`HighLevel path parameter ${name} is required.`)
|
|
184
|
+
}
|
|
185
|
+
return encodeURIComponent(String(value))
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Appends one OpenAPI query parameter.
|
|
190
|
+
*
|
|
191
|
+
* @param url - Provider request URL.
|
|
192
|
+
* @param parameter - Query serialization metadata.
|
|
193
|
+
* @param parameter.explode - Whether array items repeat the query key.
|
|
194
|
+
* @param parameter.name - Query parameter name.
|
|
195
|
+
* @param parameter.style - OpenAPI serialization style.
|
|
196
|
+
* @param value - Parameter value.
|
|
197
|
+
* @throws When the value is not scalar or an array of scalars.
|
|
198
|
+
*/
|
|
199
|
+
function appendQuery(
|
|
200
|
+
url: URL,
|
|
201
|
+
parameter: { explode: boolean; name: string; style: string },
|
|
202
|
+
value: unknown,
|
|
203
|
+
) {
|
|
204
|
+
if (value == null) return
|
|
205
|
+
if (Array.isArray(value)) {
|
|
206
|
+
if (parameter.style === "form" && parameter.explode) {
|
|
207
|
+
for (const item of value)
|
|
208
|
+
url.searchParams.append(parameter.name, stringifyQueryValue(item))
|
|
209
|
+
} else {
|
|
210
|
+
url.searchParams.set(
|
|
211
|
+
parameter.name,
|
|
212
|
+
value.map(stringifyQueryValue).join(","),
|
|
213
|
+
)
|
|
214
|
+
}
|
|
215
|
+
return
|
|
216
|
+
}
|
|
217
|
+
url.searchParams.set(parameter.name, stringifyQueryValue(value))
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Converts one supported query value to text.
|
|
222
|
+
*
|
|
223
|
+
* @param value - Query value.
|
|
224
|
+
* @throws When the value is not scalar.
|
|
225
|
+
*/
|
|
226
|
+
function stringifyQueryValue(value: unknown) {
|
|
227
|
+
if (
|
|
228
|
+
typeof value !== "boolean" &&
|
|
229
|
+
typeof value !== "number" &&
|
|
230
|
+
typeof value !== "string"
|
|
231
|
+
) {
|
|
232
|
+
throw new TypeError("HighLevel query parameters must be scalar.")
|
|
233
|
+
}
|
|
234
|
+
return String(value)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Reads provider-directed retry timing.
|
|
239
|
+
*
|
|
240
|
+
* @param headers - Rejected response headers.
|
|
241
|
+
*/
|
|
242
|
+
function getRetryAfter(headers: Headers) {
|
|
243
|
+
const retryAfter = headers.get("Retry-After")
|
|
244
|
+
if (retryAfter) return retryAfter
|
|
245
|
+
const interval = headers.get("X-RateLimit-Interval-Milliseconds")
|
|
246
|
+
if (!interval || !/^\d+$/.test(interval)) return undefined
|
|
247
|
+
return String(Math.ceil(Number(interval) / 1_000))
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Extracts a provider error message.
|
|
252
|
+
*
|
|
253
|
+
* @param value - Encodable provider error body.
|
|
254
|
+
*/
|
|
255
|
+
function getErrorMessage(value: Encodable | undefined) {
|
|
256
|
+
if (!isPlainObject(value)) return undefined
|
|
257
|
+
for (const key of ["message", "error", "error_description"]) {
|
|
258
|
+
const candidate = value[key]
|
|
259
|
+
if (typeof candidate === "string" && candidate.trim()) return candidate
|
|
260
|
+
}
|
|
261
|
+
return undefined
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Narrows a value to a plain object.
|
|
266
|
+
*
|
|
267
|
+
* @param value - Candidate value.
|
|
268
|
+
*/
|
|
269
|
+
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
270
|
+
return typeof value === "object" && value !== null && !Array.isArray(value)
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Parses JSON while retaining non-JSON provider bodies.
|
|
275
|
+
*
|
|
276
|
+
* @param value - Response body text.
|
|
277
|
+
*/
|
|
278
|
+
function parseJson(value: string): unknown {
|
|
279
|
+
try {
|
|
280
|
+
return JSON.parse(value)
|
|
281
|
+
} catch {
|
|
282
|
+
return { response: value }
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Reads one text or JSON provider response.
|
|
288
|
+
*
|
|
289
|
+
* @param response - Provider response to decode.
|
|
290
|
+
*/
|
|
291
|
+
async function parseResponseText(response: Response) {
|
|
292
|
+
const text = await response.text()
|
|
293
|
+
return text ? parseJson(text) : null
|
|
294
|
+
}
|