@automate.ax/integration-contracts 0.120.0 → 0.122.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/google-drive/index.d.ts +1044 -0
- package/dist/google-drive/index.js +188 -0
- package/dist/hubspot/api.d.ts +41 -0
- package/dist/hubspot/api.js +116 -0
- package/dist/hubspot/events.d.ts +4488 -0
- package/dist/hubspot/events.js +130 -0
- package/dist/hubspot/index.d.ts +3 -0
- package/dist/hubspot/index.js +3 -0
- package/dist/hubspot/schemas.d.ts +198 -0
- package/dist/hubspot/schemas.js +153 -0
- package/dist/linear/schemas.d.ts +4 -4
- package/dist/triggers.d.ts +3 -1
- package/dist/whatsapp/index.d.ts +2 -2
- package/dist/whatsapp/schemas.d.ts +5 -5
- package/package.json +15 -3
- package/src/google-drive/index.ts +329 -0
- package/src/hubspot/api.ts +147 -0
- package/src/hubspot/events.ts +193 -0
- package/src/hubspot/index.ts +3 -0
- package/src/hubspot/schemas.ts +189 -0
- package/src/triggers.ts +4 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const GOOGLE_DRIVE_TRIGGER_CONFIG_SCHEMA = z.object({
|
|
3
|
+
includeDescendants: z.boolean().optional(),
|
|
4
|
+
resourceId: z.string().min(1),
|
|
5
|
+
resourceType: z.enum(["file", "drive"]),
|
|
6
|
+
});
|
|
7
|
+
const GOOGLE_DRIVE_ACTION_SCHEMA = z.enum([
|
|
8
|
+
"cancelled",
|
|
9
|
+
"completed",
|
|
10
|
+
"contentChanged",
|
|
11
|
+
"created",
|
|
12
|
+
"deleted",
|
|
13
|
+
"edited",
|
|
14
|
+
"moved",
|
|
15
|
+
"reopened",
|
|
16
|
+
"renamed",
|
|
17
|
+
"reset",
|
|
18
|
+
"resolved",
|
|
19
|
+
"responded",
|
|
20
|
+
"reviewersChanged",
|
|
21
|
+
"trashed",
|
|
22
|
+
"untrashed",
|
|
23
|
+
]);
|
|
24
|
+
const GOOGLE_DRIVE_RESOURCE_TYPE_SCHEMA = z.enum([
|
|
25
|
+
"accessProposal",
|
|
26
|
+
"approval",
|
|
27
|
+
"comment",
|
|
28
|
+
"file",
|
|
29
|
+
"permission",
|
|
30
|
+
"reply",
|
|
31
|
+
]);
|
|
32
|
+
const GOOGLE_DRIVE_EVENT_BASE_SCHEMA = z.object({
|
|
33
|
+
action: GOOGLE_DRIVE_ACTION_SCHEMA,
|
|
34
|
+
assigneeEmailAddress: z.email().optional(),
|
|
35
|
+
commentId: z.string().optional(),
|
|
36
|
+
dueAt: z.date().optional(),
|
|
37
|
+
eventId: z.string(),
|
|
38
|
+
eventType: z.string(),
|
|
39
|
+
fileId: z.string().min(1),
|
|
40
|
+
initiatorEmailAddress: z.email().optional(),
|
|
41
|
+
mentionedEmailAddresses: z.email().array(),
|
|
42
|
+
mimeType: z.string().optional(),
|
|
43
|
+
occurredAt: z.date(),
|
|
44
|
+
parentId: z.string().optional(),
|
|
45
|
+
previousParentId: z.string().optional(),
|
|
46
|
+
resourceId: z.string().optional(),
|
|
47
|
+
resourceIds: z.string().array(),
|
|
48
|
+
resourceType: GOOGLE_DRIVE_RESOURCE_TYPE_SCHEMA,
|
|
49
|
+
reviewerEmailAddresses: z.email().array(),
|
|
50
|
+
reviewerResponse: z.string().optional(),
|
|
51
|
+
status: z.string().optional(),
|
|
52
|
+
version: z.string().optional(),
|
|
53
|
+
});
|
|
54
|
+
const GOOGLE_DRIVE_TRIGGER_TYPES = [
|
|
55
|
+
"googleDrive.accessProposal.created",
|
|
56
|
+
"googleDrive.accessProposal.resolved",
|
|
57
|
+
"googleDrive.approval.cancelled",
|
|
58
|
+
"googleDrive.approval.completed",
|
|
59
|
+
"googleDrive.approval.created",
|
|
60
|
+
"googleDrive.approval.reset",
|
|
61
|
+
"googleDrive.approval.responded",
|
|
62
|
+
"googleDrive.approval.reviewersChanged",
|
|
63
|
+
"googleDrive.comment.created",
|
|
64
|
+
"googleDrive.comment.deleted",
|
|
65
|
+
"googleDrive.comment.edited",
|
|
66
|
+
"googleDrive.comment.reopened",
|
|
67
|
+
"googleDrive.comment.resolved",
|
|
68
|
+
"googleDrive.file.contentChanged",
|
|
69
|
+
"googleDrive.file.created",
|
|
70
|
+
"googleDrive.file.deleted",
|
|
71
|
+
"googleDrive.file.moved",
|
|
72
|
+
"googleDrive.file.renamed",
|
|
73
|
+
"googleDrive.file.trashed",
|
|
74
|
+
"googleDrive.file.untrashed",
|
|
75
|
+
"googleDrive.permission.created",
|
|
76
|
+
"googleDrive.permission.deleted",
|
|
77
|
+
"googleDrive.permission.edited",
|
|
78
|
+
"googleDrive.reply.created",
|
|
79
|
+
"googleDrive.reply.deleted",
|
|
80
|
+
"googleDrive.reply.edited",
|
|
81
|
+
];
|
|
82
|
+
export const GOOGLE_DRIVE_PROVIDER_EVENT_TYPES = {
|
|
83
|
+
"googleDrive.accessProposal.created": "google.workspace.drive.accessproposal.v3.created",
|
|
84
|
+
"googleDrive.accessProposal.resolved": "google.workspace.drive.accessproposal.v3.resolved",
|
|
85
|
+
"googleDrive.approval.cancelled": "google.workspace.drive.approval.v3.cancelled",
|
|
86
|
+
"googleDrive.approval.completed": "google.workspace.drive.approval.v3.completed",
|
|
87
|
+
"googleDrive.approval.created": "google.workspace.drive.approval.v3.created",
|
|
88
|
+
"googleDrive.approval.reset": "google.workspace.drive.approval.v3.reset",
|
|
89
|
+
"googleDrive.approval.responded": "google.workspace.drive.approval.v3.responded",
|
|
90
|
+
"googleDrive.approval.reviewersChanged": "google.workspace.drive.approval.v3.reviewersChanged",
|
|
91
|
+
"googleDrive.comment.created": "google.workspace.drive.comment.v3.created",
|
|
92
|
+
"googleDrive.comment.deleted": "google.workspace.drive.comment.v3.deleted",
|
|
93
|
+
"googleDrive.comment.edited": "google.workspace.drive.comment.v3.edited",
|
|
94
|
+
"googleDrive.comment.reopened": "google.workspace.drive.comment.v3.reopened",
|
|
95
|
+
"googleDrive.comment.resolved": "google.workspace.drive.comment.v3.resolved",
|
|
96
|
+
"googleDrive.file.contentChanged": "google.workspace.drive.file.v3.contentChanged",
|
|
97
|
+
"googleDrive.file.created": "google.workspace.drive.file.v3.created",
|
|
98
|
+
"googleDrive.file.deleted": "google.workspace.drive.file.v3.deleted",
|
|
99
|
+
"googleDrive.file.moved": "google.workspace.drive.file.v3.moved",
|
|
100
|
+
"googleDrive.file.renamed": "google.workspace.drive.file.v3.renamed",
|
|
101
|
+
"googleDrive.file.trashed": "google.workspace.drive.file.v3.trashed",
|
|
102
|
+
"googleDrive.file.untrashed": "google.workspace.drive.file.v3.untrashed",
|
|
103
|
+
"googleDrive.permission.created": "google.workspace.drive.permission.v3.created",
|
|
104
|
+
"googleDrive.permission.deleted": "google.workspace.drive.permission.v3.deleted",
|
|
105
|
+
"googleDrive.permission.edited": "google.workspace.drive.permission.v3.edited",
|
|
106
|
+
"googleDrive.reply.created": "google.workspace.drive.reply.v3.created",
|
|
107
|
+
"googleDrive.reply.deleted": "google.workspace.drive.reply.v3.deleted",
|
|
108
|
+
"googleDrive.reply.edited": "google.workspace.drive.reply.v3.edited",
|
|
109
|
+
};
|
|
110
|
+
export const GOOGLE_DRIVE_EVENT_SCHEMA = GOOGLE_DRIVE_EVENT_BASE_SCHEMA.extend({
|
|
111
|
+
eventType: z.enum(GOOGLE_DRIVE_TRIGGER_TYPES),
|
|
112
|
+
});
|
|
113
|
+
/**
|
|
114
|
+
* Builds one semantic Drive trigger contract with literal discriminants.
|
|
115
|
+
*
|
|
116
|
+
* @param eventType - Exact internal event type.
|
|
117
|
+
* @param resourceType - Exact event resource family.
|
|
118
|
+
* @param action - Exact event action.
|
|
119
|
+
*/
|
|
120
|
+
function googleDriveSemanticTriggerContract(eventType, resourceType, action) {
|
|
121
|
+
return {
|
|
122
|
+
configSchema: GOOGLE_DRIVE_TRIGGER_CONFIG_SCHEMA,
|
|
123
|
+
eventSchema: GOOGLE_DRIVE_EVENT_BASE_SCHEMA.extend({
|
|
124
|
+
action: z.literal(action),
|
|
125
|
+
eventType: z.literal(eventType),
|
|
126
|
+
resourceType: z.literal(resourceType),
|
|
127
|
+
}),
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
/** Exact semantic trigger contract map used by authoring inference. */
|
|
131
|
+
const googleDriveSemanticTriggerContracts = {
|
|
132
|
+
"googleDrive.accessProposal.created": googleDriveSemanticTriggerContract("googleDrive.accessProposal.created", "accessProposal", "created"),
|
|
133
|
+
"googleDrive.accessProposal.resolved": googleDriveSemanticTriggerContract("googleDrive.accessProposal.resolved", "accessProposal", "resolved"),
|
|
134
|
+
"googleDrive.approval.cancelled": googleDriveSemanticTriggerContract("googleDrive.approval.cancelled", "approval", "cancelled"),
|
|
135
|
+
"googleDrive.approval.completed": googleDriveSemanticTriggerContract("googleDrive.approval.completed", "approval", "completed"),
|
|
136
|
+
"googleDrive.approval.created": googleDriveSemanticTriggerContract("googleDrive.approval.created", "approval", "created"),
|
|
137
|
+
"googleDrive.approval.reset": googleDriveSemanticTriggerContract("googleDrive.approval.reset", "approval", "reset"),
|
|
138
|
+
"googleDrive.approval.responded": googleDriveSemanticTriggerContract("googleDrive.approval.responded", "approval", "responded"),
|
|
139
|
+
"googleDrive.approval.reviewersChanged": googleDriveSemanticTriggerContract("googleDrive.approval.reviewersChanged", "approval", "reviewersChanged"),
|
|
140
|
+
"googleDrive.comment.created": googleDriveSemanticTriggerContract("googleDrive.comment.created", "comment", "created"),
|
|
141
|
+
"googleDrive.comment.deleted": googleDriveSemanticTriggerContract("googleDrive.comment.deleted", "comment", "deleted"),
|
|
142
|
+
"googleDrive.comment.edited": googleDriveSemanticTriggerContract("googleDrive.comment.edited", "comment", "edited"),
|
|
143
|
+
"googleDrive.comment.reopened": googleDriveSemanticTriggerContract("googleDrive.comment.reopened", "comment", "reopened"),
|
|
144
|
+
"googleDrive.comment.resolved": googleDriveSemanticTriggerContract("googleDrive.comment.resolved", "comment", "resolved"),
|
|
145
|
+
"googleDrive.file.contentChanged": googleDriveSemanticTriggerContract("googleDrive.file.contentChanged", "file", "contentChanged"),
|
|
146
|
+
"googleDrive.file.created": googleDriveSemanticTriggerContract("googleDrive.file.created", "file", "created"),
|
|
147
|
+
"googleDrive.file.deleted": googleDriveSemanticTriggerContract("googleDrive.file.deleted", "file", "deleted"),
|
|
148
|
+
"googleDrive.file.moved": googleDriveSemanticTriggerContract("googleDrive.file.moved", "file", "moved"),
|
|
149
|
+
"googleDrive.file.renamed": googleDriveSemanticTriggerContract("googleDrive.file.renamed", "file", "renamed"),
|
|
150
|
+
"googleDrive.file.trashed": googleDriveSemanticTriggerContract("googleDrive.file.trashed", "file", "trashed"),
|
|
151
|
+
"googleDrive.file.untrashed": googleDriveSemanticTriggerContract("googleDrive.file.untrashed", "file", "untrashed"),
|
|
152
|
+
"googleDrive.permission.created": googleDriveSemanticTriggerContract("googleDrive.permission.created", "permission", "created"),
|
|
153
|
+
"googleDrive.permission.deleted": googleDriveSemanticTriggerContract("googleDrive.permission.deleted", "permission", "deleted"),
|
|
154
|
+
"googleDrive.permission.edited": googleDriveSemanticTriggerContract("googleDrive.permission.edited", "permission", "edited"),
|
|
155
|
+
"googleDrive.reply.created": googleDriveSemanticTriggerContract("googleDrive.reply.created", "reply", "created"),
|
|
156
|
+
"googleDrive.reply.deleted": googleDriveSemanticTriggerContract("googleDrive.reply.deleted", "reply", "deleted"),
|
|
157
|
+
"googleDrive.reply.edited": googleDriveSemanticTriggerContract("googleDrive.reply.edited", "reply", "edited"),
|
|
158
|
+
};
|
|
159
|
+
export const googleDriveTriggerContracts = {
|
|
160
|
+
"googleDrive.event": {
|
|
161
|
+
configSchema: GOOGLE_DRIVE_TRIGGER_CONFIG_SCHEMA,
|
|
162
|
+
eventSchema: GOOGLE_DRIVE_EVENT_SCHEMA,
|
|
163
|
+
},
|
|
164
|
+
...googleDriveSemanticTriggerContracts,
|
|
165
|
+
};
|
|
166
|
+
/**
|
|
167
|
+
* Resolves an internal semantic event type from a provider CloudEvent type.
|
|
168
|
+
*
|
|
169
|
+
* @param providerEventType - Provider CloudEvent type.
|
|
170
|
+
*/
|
|
171
|
+
export function toGoogleDriveTriggerType(providerEventType) {
|
|
172
|
+
// Keep the candidate separate so Zod performs the only narrowing.
|
|
173
|
+
const candidate = Object.entries(GOOGLE_DRIVE_PROVIDER_EVENT_TYPES).find(([, value]) => value === providerEventType)?.[0];
|
|
174
|
+
const result = z.enum(GOOGLE_DRIVE_TRIGGER_TYPES).safeParse(candidate);
|
|
175
|
+
return result.success ? result.data : undefined;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Splits one internal event type into its resource and action discriminants.
|
|
179
|
+
*
|
|
180
|
+
* @param eventType - Stable internal semantic event type.
|
|
181
|
+
*/
|
|
182
|
+
export function parseGoogleDriveTriggerType(eventType) {
|
|
183
|
+
const [, resourceType, ...actionParts] = eventType.split(".");
|
|
184
|
+
return {
|
|
185
|
+
action: GOOGLE_DRIVE_ACTION_SCHEMA.parse(actionParts.join(".")),
|
|
186
|
+
resourceType: GOOGLE_DRIVE_RESOURCE_TYPE_SCHEMA.parse(resourceType),
|
|
187
|
+
};
|
|
188
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type Encodable } from "@automate.ax/codec";
|
|
2
|
+
import * as z from "zod";
|
|
3
|
+
export declare const HUBSPOT_VALUE_SCHEMA: z.ZodCustom<Encodable, Encodable>;
|
|
4
|
+
interface HubSpotRequestOptions<TSchema extends z.ZodType> {
|
|
5
|
+
body?: Encodable;
|
|
6
|
+
method?: "DELETE" | "GET" | "PATCH" | "POST" | "PUT";
|
|
7
|
+
query?: Record<string, boolean | number | string | readonly string[] | null | undefined>;
|
|
8
|
+
responseSchema: TSchema;
|
|
9
|
+
}
|
|
10
|
+
/** Error returned by a rejected HubSpot API request. */
|
|
11
|
+
export declare class HubSpotApiError extends Error {
|
|
12
|
+
readonly category?: string;
|
|
13
|
+
readonly correlationId?: string;
|
|
14
|
+
readonly details: Encodable;
|
|
15
|
+
readonly retryAfter?: string;
|
|
16
|
+
readonly status: number;
|
|
17
|
+
readonly subCategory?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Creates an error from one rejected HubSpot response.
|
|
20
|
+
*
|
|
21
|
+
* @param status - HTTP response status.
|
|
22
|
+
* @param details - Codec-safe provider response.
|
|
23
|
+
* @param retryAfter - Provider retry timing, when present.
|
|
24
|
+
*/
|
|
25
|
+
constructor(status: number, details: Encodable, retryAfter?: string);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Creates a minimal authenticated HubSpot REST client.
|
|
29
|
+
*
|
|
30
|
+
* @param secret - Stored OAuth or private-app token.
|
|
31
|
+
*/
|
|
32
|
+
export declare function getHubSpotApi(secret: unknown): {
|
|
33
|
+
/**
|
|
34
|
+
* Sends one request below HubSpot's API origin.
|
|
35
|
+
*
|
|
36
|
+
* @param path - Relative provider API path.
|
|
37
|
+
* @param options - Method, query, body, and response schema.
|
|
38
|
+
*/
|
|
39
|
+
request<TSchema extends z.ZodType>(path: string, options: HubSpotRequestOptions<TSchema>): Promise<z.output<TSchema>>;
|
|
40
|
+
};
|
|
41
|
+
export {};
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { isEncodable } from "@automate.ax/codec";
|
|
2
|
+
import * as z from "zod";
|
|
3
|
+
const HUBSPOT_API_ORIGIN = "https://api.hubapi.com/";
|
|
4
|
+
const HUBSPOT_API_URL = new URL(HUBSPOT_API_ORIGIN);
|
|
5
|
+
const HUBSPOT_SECRET_SCHEMA = z.object({ accessToken: z.string().min(1) });
|
|
6
|
+
const HUBSPOT_ERROR_SCHEMA = z.looseObject({
|
|
7
|
+
category: z.string().optional(),
|
|
8
|
+
correlationId: z.string().optional(),
|
|
9
|
+
message: z.string().optional(),
|
|
10
|
+
subCategory: z.string().optional(),
|
|
11
|
+
});
|
|
12
|
+
export const HUBSPOT_VALUE_SCHEMA = z.custom(isEncodable, {
|
|
13
|
+
message: "Expected a codec-safe HubSpot value.",
|
|
14
|
+
});
|
|
15
|
+
/** Error returned by a rejected HubSpot API request. */
|
|
16
|
+
export class HubSpotApiError extends Error {
|
|
17
|
+
category;
|
|
18
|
+
correlationId;
|
|
19
|
+
details;
|
|
20
|
+
retryAfter;
|
|
21
|
+
status;
|
|
22
|
+
subCategory;
|
|
23
|
+
/**
|
|
24
|
+
* Creates an error from one rejected HubSpot response.
|
|
25
|
+
*
|
|
26
|
+
* @param status - HTTP response status.
|
|
27
|
+
* @param details - Codec-safe provider response.
|
|
28
|
+
* @param retryAfter - Provider retry timing, when present.
|
|
29
|
+
*/
|
|
30
|
+
constructor(status, details, retryAfter) {
|
|
31
|
+
const providerError = HUBSPOT_ERROR_SCHEMA.safeParse(details);
|
|
32
|
+
super(providerError.success && providerError.data.message
|
|
33
|
+
? `HubSpot API request failed (${status}): ${providerError.data.message}`
|
|
34
|
+
: `HubSpot API request failed (${status}).`);
|
|
35
|
+
this.name = "HubSpotApiError";
|
|
36
|
+
this.category = providerError.success
|
|
37
|
+
? providerError.data.category
|
|
38
|
+
: undefined;
|
|
39
|
+
this.correlationId = providerError.success
|
|
40
|
+
? providerError.data.correlationId
|
|
41
|
+
: undefined;
|
|
42
|
+
this.details = details;
|
|
43
|
+
this.retryAfter = retryAfter;
|
|
44
|
+
this.status = status;
|
|
45
|
+
this.subCategory = providerError.success
|
|
46
|
+
? providerError.data.subCategory
|
|
47
|
+
: undefined;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Creates a minimal authenticated HubSpot REST client.
|
|
52
|
+
*
|
|
53
|
+
* @param secret - Stored OAuth or private-app token.
|
|
54
|
+
*/
|
|
55
|
+
export function getHubSpotApi(secret) {
|
|
56
|
+
const { accessToken } = HUBSPOT_SECRET_SCHEMA.parse(secret);
|
|
57
|
+
return {
|
|
58
|
+
/**
|
|
59
|
+
* Sends one request below HubSpot's API origin.
|
|
60
|
+
*
|
|
61
|
+
* @param path - Relative provider API path.
|
|
62
|
+
* @param options - Method, query, body, and response schema.
|
|
63
|
+
*/
|
|
64
|
+
async request(path, options) {
|
|
65
|
+
const normalizedPath = path.replace(/^\/+/, "");
|
|
66
|
+
if (!normalizedPath ||
|
|
67
|
+
normalizedPath.includes("://") ||
|
|
68
|
+
normalizedPath.includes("\\")) {
|
|
69
|
+
throw new TypeError("HubSpot API paths must be relative.");
|
|
70
|
+
}
|
|
71
|
+
const url = new URL(normalizedPath, HUBSPOT_API_ORIGIN);
|
|
72
|
+
if (url.origin !== HUBSPOT_API_URL.origin) {
|
|
73
|
+
throw new TypeError("HubSpot API paths must remain on api.hubapi.com.");
|
|
74
|
+
}
|
|
75
|
+
for (const [key, value] of Object.entries(options.query ?? {})) {
|
|
76
|
+
if (value == null)
|
|
77
|
+
continue;
|
|
78
|
+
url.searchParams.set(key, Array.isArray(value) ? value.join(",") : String(value));
|
|
79
|
+
}
|
|
80
|
+
const headers = new Headers({
|
|
81
|
+
Accept: "application/json",
|
|
82
|
+
Authorization: `Bearer ${accessToken}`,
|
|
83
|
+
});
|
|
84
|
+
if (options.body !== undefined) {
|
|
85
|
+
headers.set("Content-Type", "application/json");
|
|
86
|
+
}
|
|
87
|
+
const response = await fetch(url, {
|
|
88
|
+
body: options.body === undefined ? undefined : JSON.stringify(options.body),
|
|
89
|
+
headers,
|
|
90
|
+
method: options.method ?? "GET",
|
|
91
|
+
});
|
|
92
|
+
const text = await response.text();
|
|
93
|
+
const parsed = text ? parseJson(text) : undefined;
|
|
94
|
+
if (response.ok && !text)
|
|
95
|
+
return options.responseSchema.parse(undefined);
|
|
96
|
+
const encodable = HUBSPOT_VALUE_SCHEMA.safeParse(parsed);
|
|
97
|
+
if (!response.ok || !encodable.success) {
|
|
98
|
+
throw new HubSpotApiError(response.status, encodable.success ? encodable.data : { response: text }, response.headers.get("Retry-After") ?? undefined);
|
|
99
|
+
}
|
|
100
|
+
return options.responseSchema.parse(parsed);
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Parses a response body while preserving non-JSON error text.
|
|
106
|
+
*
|
|
107
|
+
* @param value - Raw response body.
|
|
108
|
+
*/
|
|
109
|
+
function parseJson(value) {
|
|
110
|
+
try {
|
|
111
|
+
return JSON.parse(value);
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
return { response: value };
|
|
115
|
+
}
|
|
116
|
+
}
|