@automate.ax/integration-contracts 0.119.10 → 0.121.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.
@@ -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
+ }