@automate.ax/integration-contracts 0.87.5 → 0.88.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/close/api.d.ts +54 -0
- package/dist/close/api.js +191 -0
- package/dist/close/events.d.ts +3216 -0
- package/dist/close/events.js +575 -0
- package/dist/close/index.d.ts +3 -0
- package/dist/close/index.js +3 -0
- package/dist/close/schemas.d.ts +1900 -0
- package/dist/close/schemas.js +950 -0
- package/dist/github/resources.d.ts +242 -242
- package/dist/google-calendar/schemas.d.ts +3 -3
- package/dist/google-forms/event-schemas.d.ts +4 -4
- package/dist/google-forms/google-forms.d.ts +4 -4
- package/dist/google-forms/index.d.ts +4 -4
- package/dist/google-forms/schemas.d.ts +14 -14
- package/dist/linear/schemas.d.ts +24 -24
- package/dist/triggers.d.ts +2 -1
- package/dist/whatsapp/index.d.ts +6 -6
- package/dist/whatsapp/schemas.d.ts +11 -11
- package/package.json +8 -2
- package/src/close/api.ts +240 -0
- package/src/close/events.ts +755 -0
- package/src/close/index.ts +3 -0
- package/src/close/schemas.ts +995 -0
- package/src/triggers.ts +2 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { type Encodable } from "@automate.ax/codec";
|
|
2
|
+
import * as z from "zod";
|
|
3
|
+
export declare const CLOSE_VALUE_SCHEMA: z.ZodCustom<Encodable, Encodable>;
|
|
4
|
+
export declare const CLOSE_OBJECT_SCHEMA: z.ZodCustom<Record<string, Encodable>, Record<string, Encodable>>;
|
|
5
|
+
export declare const CLOSE_RESPONSE_SCHEMA: z.ZodUnion<readonly [z.ZodCustom<Encodable, Encodable>, z.ZodPipe<z.ZodUndefined, z.ZodTransform<null, undefined>>]>;
|
|
6
|
+
interface CloseRequestOptions<TSchema extends z.ZodType> {
|
|
7
|
+
body?: Encodable;
|
|
8
|
+
method?: "DELETE" | "GET" | "POST" | "PUT";
|
|
9
|
+
query?: Record<string, boolean | number | string | readonly string[] | null | undefined>;
|
|
10
|
+
responseSchema: TSchema;
|
|
11
|
+
}
|
|
12
|
+
/** Error returned by a rejected Close API request. */
|
|
13
|
+
export declare class CloseApiError extends Error {
|
|
14
|
+
readonly details: Encodable;
|
|
15
|
+
readonly status: number;
|
|
16
|
+
/**
|
|
17
|
+
* Creates an error from a rejected Close response.
|
|
18
|
+
*
|
|
19
|
+
* @param status - HTTP response status.
|
|
20
|
+
* @param details - Codec-safe response details.
|
|
21
|
+
*/
|
|
22
|
+
constructor(status: number, details: Encodable);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Creates a minimal authenticated Close REST client.
|
|
26
|
+
*
|
|
27
|
+
* @param secret - Stored Close OAuth token or API key.
|
|
28
|
+
*/
|
|
29
|
+
export declare function getCloseApi(secret: unknown): {
|
|
30
|
+
/**
|
|
31
|
+
* Sends one JSON request to a path below Close's `/api/v1/` root.
|
|
32
|
+
*
|
|
33
|
+
* Query keys are provider-native so callers can use Close's
|
|
34
|
+
* double-underscore filters. Request bodies and responses use public
|
|
35
|
+
* camelCase keys.
|
|
36
|
+
*
|
|
37
|
+
* @param path - Relative path below Close's API root.
|
|
38
|
+
* @param options - Request method, query, body, and response schema.
|
|
39
|
+
*/
|
|
40
|
+
request<TSchema extends z.ZodType>(path: string, options: CloseRequestOptions<TSchema>): Promise<z.output<TSchema>>;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Converts a public camelCase value into Close's provider-native JSON keys.
|
|
44
|
+
*
|
|
45
|
+
* @param value - Codec-safe public value.
|
|
46
|
+
*/
|
|
47
|
+
export declare function toClose(value: Encodable): Encodable;
|
|
48
|
+
/**
|
|
49
|
+
* Converts Close's provider-native JSON keys to public camelCase keys.
|
|
50
|
+
*
|
|
51
|
+
* @param value - Raw provider value.
|
|
52
|
+
*/
|
|
53
|
+
export declare function fromClose(value: unknown): Encodable;
|
|
54
|
+
export {};
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { isEncodable } from "@automate.ax/codec";
|
|
2
|
+
import * as z from "zod";
|
|
3
|
+
const CLOSE_API_ORIGIN = "https://api.close.com/api/v1/";
|
|
4
|
+
const CLOSE_API_URL = new URL(CLOSE_API_ORIGIN);
|
|
5
|
+
const CLOSE_SECRET_SCHEMA = z.union([
|
|
6
|
+
z.object({ accessToken: z.string().min(1) }),
|
|
7
|
+
z.object({ apiKey: z.string().min(1) }),
|
|
8
|
+
]);
|
|
9
|
+
export const CLOSE_VALUE_SCHEMA = z.custom(isEncodable, {
|
|
10
|
+
message: "Expected a codec-safe Close value.",
|
|
11
|
+
});
|
|
12
|
+
export const CLOSE_OBJECT_SCHEMA = z.custom((value) => isPlainObject(value) && isEncodable(value), { message: "Expected a codec-safe Close object." });
|
|
13
|
+
export const CLOSE_RESPONSE_SCHEMA = z.union([
|
|
14
|
+
CLOSE_VALUE_SCHEMA,
|
|
15
|
+
z.undefined().transform(() => null),
|
|
16
|
+
]);
|
|
17
|
+
/** Error returned by a rejected Close API request. */
|
|
18
|
+
export class CloseApiError extends Error {
|
|
19
|
+
details;
|
|
20
|
+
status;
|
|
21
|
+
/**
|
|
22
|
+
* Creates an error from a rejected Close response.
|
|
23
|
+
*
|
|
24
|
+
* @param status - HTTP response status.
|
|
25
|
+
* @param details - Codec-safe response details.
|
|
26
|
+
*/
|
|
27
|
+
constructor(status, details) {
|
|
28
|
+
super(`Close API request failed (${status}).`);
|
|
29
|
+
this.name = "CloseApiError";
|
|
30
|
+
this.details = details;
|
|
31
|
+
this.status = status;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Creates a minimal authenticated Close REST client.
|
|
36
|
+
*
|
|
37
|
+
* @param secret - Stored Close OAuth token or API key.
|
|
38
|
+
*/
|
|
39
|
+
export function getCloseApi(secret) {
|
|
40
|
+
const credentials = CLOSE_SECRET_SCHEMA.parse(secret);
|
|
41
|
+
return {
|
|
42
|
+
/**
|
|
43
|
+
* Sends one JSON request to a path below Close's `/api/v1/` root.
|
|
44
|
+
*
|
|
45
|
+
* Query keys are provider-native so callers can use Close's
|
|
46
|
+
* double-underscore filters. Request bodies and responses use public
|
|
47
|
+
* camelCase keys.
|
|
48
|
+
*
|
|
49
|
+
* @param path - Relative path below Close's API root.
|
|
50
|
+
* @param options - Request method, query, body, and response schema.
|
|
51
|
+
*/
|
|
52
|
+
async request(path, options) {
|
|
53
|
+
const normalizedPath = path.replace(/^\/+/, "");
|
|
54
|
+
if (!normalizedPath ||
|
|
55
|
+
normalizedPath.includes("://") ||
|
|
56
|
+
normalizedPath.includes("\\")) {
|
|
57
|
+
throw new TypeError("Close API paths must be relative to /api/v1/.");
|
|
58
|
+
}
|
|
59
|
+
const url = new URL(normalizedPath, CLOSE_API_ORIGIN);
|
|
60
|
+
if (url.origin !== CLOSE_API_URL.origin ||
|
|
61
|
+
!url.pathname.startsWith(CLOSE_API_URL.pathname)) {
|
|
62
|
+
throw new TypeError("Close API paths must remain below /api/v1/.");
|
|
63
|
+
}
|
|
64
|
+
for (const [key, value] of Object.entries(options.query ?? {})) {
|
|
65
|
+
if (value == null)
|
|
66
|
+
continue;
|
|
67
|
+
url.searchParams.set(key, Array.isArray(value) ? value.join(",") : String(value));
|
|
68
|
+
}
|
|
69
|
+
const headers = new Headers({ Accept: "application/json" });
|
|
70
|
+
headers.set("Authorization", "accessToken" in credentials
|
|
71
|
+
? `Bearer ${credentials.accessToken}`
|
|
72
|
+
: `Basic ${btoa(`${credentials.apiKey}:`)}`);
|
|
73
|
+
if (options.body !== undefined) {
|
|
74
|
+
headers.set("Content-Type", "application/json");
|
|
75
|
+
}
|
|
76
|
+
const response = await fetch(url, {
|
|
77
|
+
body: options.body === undefined
|
|
78
|
+
? undefined
|
|
79
|
+
: JSON.stringify(toClose(options.body)),
|
|
80
|
+
headers,
|
|
81
|
+
method: options.method ?? "GET",
|
|
82
|
+
});
|
|
83
|
+
const text = await response.text();
|
|
84
|
+
const result = CLOSE_RESPONSE_SCHEMA.safeParse(fromClose(text ? parseJson(text) : null));
|
|
85
|
+
if (!response.ok || !result.success) {
|
|
86
|
+
throw new CloseApiError(response.status, result.success ? result.data : { response: text });
|
|
87
|
+
}
|
|
88
|
+
return options.responseSchema.parse(result.data);
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Converts a public camelCase value into Close's provider-native JSON keys.
|
|
94
|
+
*
|
|
95
|
+
* @param value - Codec-safe public value.
|
|
96
|
+
*/
|
|
97
|
+
export function toClose(value) {
|
|
98
|
+
if (value instanceof Date)
|
|
99
|
+
return value.toISOString();
|
|
100
|
+
if (Array.isArray(value))
|
|
101
|
+
return value.map(toClose);
|
|
102
|
+
if (!isPlainObject(value))
|
|
103
|
+
return value;
|
|
104
|
+
return Object.fromEntries(Object.entries(value).flatMap(([key, item]) => {
|
|
105
|
+
if (key === "customFields" && isPlainObject(item)) {
|
|
106
|
+
return Object.entries(item).map(([fieldId, fieldValue]) => [
|
|
107
|
+
`custom.${fieldId}`,
|
|
108
|
+
toClose(fieldValue),
|
|
109
|
+
]);
|
|
110
|
+
}
|
|
111
|
+
return [[toSnakeCase(key), toClose(item)]];
|
|
112
|
+
}));
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Converts Close's provider-native JSON keys to public camelCase keys.
|
|
116
|
+
*
|
|
117
|
+
* @param value - Raw provider value.
|
|
118
|
+
*/
|
|
119
|
+
export function fromClose(value) {
|
|
120
|
+
if (Array.isArray(value))
|
|
121
|
+
return value.map(fromClose);
|
|
122
|
+
if (!isPlainObject(value))
|
|
123
|
+
return CLOSE_VALUE_SCHEMA.parse(value);
|
|
124
|
+
const customFields = {};
|
|
125
|
+
// Collect flattened custom fields while normalizing the ordinary entries.
|
|
126
|
+
const entries = Object.entries(value).flatMap(([key, item]) => {
|
|
127
|
+
if (key.startsWith("custom.")) {
|
|
128
|
+
customFields[key.slice("custom.".length)] = fromClose(item);
|
|
129
|
+
return [];
|
|
130
|
+
}
|
|
131
|
+
return [
|
|
132
|
+
[
|
|
133
|
+
key === "date_created"
|
|
134
|
+
? "createdAt"
|
|
135
|
+
: key === "date_updated"
|
|
136
|
+
? "updatedAt"
|
|
137
|
+
: key === "_type"
|
|
138
|
+
? "type"
|
|
139
|
+
: key === "__object_type"
|
|
140
|
+
? "objectType"
|
|
141
|
+
: toCamelCase(key),
|
|
142
|
+
fromClose(item),
|
|
143
|
+
],
|
|
144
|
+
];
|
|
145
|
+
});
|
|
146
|
+
return Object.fromEntries([
|
|
147
|
+
...entries,
|
|
148
|
+
...(Object.keys(customFields).length > 0
|
|
149
|
+
? [["customFields", customFields]]
|
|
150
|
+
: []),
|
|
151
|
+
]);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Parses a response body while preserving non-JSON error text.
|
|
155
|
+
*
|
|
156
|
+
* @param value - Raw response text.
|
|
157
|
+
*/
|
|
158
|
+
function parseJson(value) {
|
|
159
|
+
try {
|
|
160
|
+
return JSON.parse(value);
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
return { response: value };
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Checks whether a value is a non-array object.
|
|
168
|
+
*
|
|
169
|
+
* @param value - Candidate value.
|
|
170
|
+
*/
|
|
171
|
+
function isPlainObject(value) {
|
|
172
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Converts one provider key to public camelCase.
|
|
176
|
+
*
|
|
177
|
+
* @param value - Provider key.
|
|
178
|
+
*/
|
|
179
|
+
function toCamelCase(value) {
|
|
180
|
+
return value.replace(/_([a-z0-9])/g, (_match, character) => character.toUpperCase());
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Converts one public key to provider snake_case.
|
|
184
|
+
*
|
|
185
|
+
* @param value - Public key.
|
|
186
|
+
*/
|
|
187
|
+
function toSnakeCase(value) {
|
|
188
|
+
return value
|
|
189
|
+
.replace(/([a-zA-Z])([0-9])/g, "$1_$2")
|
|
190
|
+
.replace(/[A-Z]/g, (character) => `_${character.toLowerCase()}`);
|
|
191
|
+
}
|