@tylerofnigma/sdk 0.0.0-stage → 0.1.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/LICENSE +232 -0
- package/README.md +242 -2
- package/dist/index.cjs +355 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +122 -0
- package/dist/index.d.ts +122 -0
- package/dist/index.js +341 -0
- package/dist/index.js.map +1 -0
- package/package.json +58 -4
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/constants/index.ts
|
|
4
|
+
var SDK_KEY_PREFIX = "apn_live_";
|
|
5
|
+
var DEFAULT_BASE_URL = "https://api.appnigma.ai";
|
|
6
|
+
var SDK_ROUTE_BASE = "/sdk/v1";
|
|
7
|
+
var REQUEST_ID_HEADER = "x-request-id";
|
|
8
|
+
var RETRY_AFTER_HEADER = "retry-after";
|
|
9
|
+
var NETWORK_ERROR_CODE = "NETWORK_ERROR";
|
|
10
|
+
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
11
|
+
var DEFAULT_MAX_RETRIES = 2;
|
|
12
|
+
var DEFAULT_MAX_RETRY_WAIT_MS = 3e4;
|
|
13
|
+
var RETRY_BACKOFF_MS = [500, 1e3];
|
|
14
|
+
var RETRY_JITTER_SHARE = 0.25;
|
|
15
|
+
var SDK_OBJECTS = ["contact", "company", "deal"];
|
|
16
|
+
var SDK_PLATFORMS = ["hubspot"];
|
|
17
|
+
var CONNECTION_STATUSES = ["connected", "needs_reconnect", "disconnected"];
|
|
18
|
+
var END_CUSTOMER_ID_PATTERN = /^[A-Za-z0-9._-]{1,100}$/;
|
|
19
|
+
var END_CUSTOMER_ID_RULE = "must be 1 to 100 characters: letters, digits, dot, dash or underscore";
|
|
20
|
+
var SDK_ERROR_CODES = [
|
|
21
|
+
"INVALID_INPUT",
|
|
22
|
+
"SDK_KEY_MISSING",
|
|
23
|
+
"SDK_KEY_INVALID",
|
|
24
|
+
"SDK_KEY_CANCELLED",
|
|
25
|
+
"MICROSERVER_NOT_ENABLED",
|
|
26
|
+
"END_CUSTOMER_NOT_FOUND",
|
|
27
|
+
"FUNCTION_NOT_FOUND",
|
|
28
|
+
"CONNECTION_NEEDS_RECONNECT",
|
|
29
|
+
"RATE_LIMITED",
|
|
30
|
+
"PLATFORM_RATE_LIMITED",
|
|
31
|
+
"PLATFORM_ERROR",
|
|
32
|
+
"TIMED_OUT",
|
|
33
|
+
"LOGIC_FAILED",
|
|
34
|
+
"INTERNAL_ERROR"
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
// src/sdk-error.ts
|
|
38
|
+
var SdkError = class extends Error {
|
|
39
|
+
code;
|
|
40
|
+
status;
|
|
41
|
+
requestId;
|
|
42
|
+
details;
|
|
43
|
+
constructor(init) {
|
|
44
|
+
super(init.message, init.cause === void 0 ? void 0 : { cause: init.cause });
|
|
45
|
+
this.name = "SdkError";
|
|
46
|
+
this.code = init.code;
|
|
47
|
+
this.status = init.status ?? null;
|
|
48
|
+
this.requestId = init.requestId ?? null;
|
|
49
|
+
this.details = init.details ?? {};
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// src/errors/index.ts
|
|
54
|
+
var isProblem = (value) => typeof value === "object" && value !== null && typeof value.field === "string" && typeof value.problem === "string";
|
|
55
|
+
var readProblems = (details) => {
|
|
56
|
+
const list = details.problems;
|
|
57
|
+
return Array.isArray(list) ? list.filter(isProblem) : [];
|
|
58
|
+
};
|
|
59
|
+
var SdkInputError = class extends SdkError {
|
|
60
|
+
problems;
|
|
61
|
+
constructor(init) {
|
|
62
|
+
super(init);
|
|
63
|
+
this.name = "SdkInputError";
|
|
64
|
+
this.problems = readProblems(this.details);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
var SdkAuthError = class extends SdkError {
|
|
68
|
+
constructor(init) {
|
|
69
|
+
super(init);
|
|
70
|
+
this.name = "SdkAuthError";
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
var SdkNotFoundError = class extends SdkError {
|
|
74
|
+
constructor(init) {
|
|
75
|
+
super(init);
|
|
76
|
+
this.name = "SdkNotFoundError";
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
var SdkReconnectError = class extends SdkError {
|
|
80
|
+
constructor(init) {
|
|
81
|
+
super(init);
|
|
82
|
+
this.name = "SdkReconnectError";
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
var SdkRateLimitError = class extends SdkError {
|
|
86
|
+
retryAfterSeconds;
|
|
87
|
+
constructor(init) {
|
|
88
|
+
super(init);
|
|
89
|
+
this.name = "SdkRateLimitError";
|
|
90
|
+
this.retryAfterSeconds = init.retryAfterSeconds ?? null;
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
var SdkServerError = class extends SdkError {
|
|
94
|
+
constructor(init) {
|
|
95
|
+
super(init);
|
|
96
|
+
this.name = "SdkServerError";
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
var SdkNetworkError = class extends SdkError {
|
|
100
|
+
constructor(init) {
|
|
101
|
+
super({ code: NETWORK_ERROR_CODE, message: init.message, status: null, requestId: null, cause: init.cause });
|
|
102
|
+
this.name = "SdkNetworkError";
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
var readErrorShape = (body) => {
|
|
106
|
+
if (typeof body !== "object" || body === null) return null;
|
|
107
|
+
const error = body.error;
|
|
108
|
+
if (typeof error !== "object" || error === null) return null;
|
|
109
|
+
const { code, message, details } = error;
|
|
110
|
+
if (typeof code !== "string" || code.length === 0) return null;
|
|
111
|
+
const detailsIsObject = typeof details === "object" && details !== null && !Array.isArray(details);
|
|
112
|
+
return {
|
|
113
|
+
code,
|
|
114
|
+
message: typeof message === "string" ? message : "",
|
|
115
|
+
details: detailsIsObject ? details : {}
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
var toSdkError = ({ status, body, requestId, retryAfterSeconds = null }) => {
|
|
119
|
+
const fallbackMessage = `The Appnigma API answered ${status}`;
|
|
120
|
+
const shape = readErrorShape(body) ?? { code: "INTERNAL_ERROR", message: fallbackMessage, details: {} };
|
|
121
|
+
const init = {
|
|
122
|
+
code: shape.code,
|
|
123
|
+
message: shape.message || fallbackMessage,
|
|
124
|
+
status,
|
|
125
|
+
requestId,
|
|
126
|
+
details: shape.details
|
|
127
|
+
};
|
|
128
|
+
switch (status) {
|
|
129
|
+
case 400:
|
|
130
|
+
return new SdkInputError(init);
|
|
131
|
+
case 401:
|
|
132
|
+
case 403:
|
|
133
|
+
return new SdkAuthError(init);
|
|
134
|
+
case 404:
|
|
135
|
+
return new SdkNotFoundError(init);
|
|
136
|
+
case 409:
|
|
137
|
+
return new SdkReconnectError(init);
|
|
138
|
+
case 429:
|
|
139
|
+
return new SdkRateLimitError({ ...init, retryAfterSeconds });
|
|
140
|
+
default:
|
|
141
|
+
return new SdkServerError(init);
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
// src/retry.ts
|
|
146
|
+
var sleep = (ms, signal) => new Promise((resolve) => {
|
|
147
|
+
if (signal?.aborted) {
|
|
148
|
+
resolve();
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const onAbort = () => {
|
|
152
|
+
clearTimeout(timer);
|
|
153
|
+
resolve();
|
|
154
|
+
};
|
|
155
|
+
const timer = setTimeout(() => {
|
|
156
|
+
signal?.removeEventListener("abort", onAbort);
|
|
157
|
+
resolve();
|
|
158
|
+
}, ms);
|
|
159
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
160
|
+
});
|
|
161
|
+
var isRetryableStatus = (status) => status === 429 || status >= 500;
|
|
162
|
+
var waitBeforeRetry = (answer, retryIndex, random) => {
|
|
163
|
+
if (answer?.retryAfterSeconds !== null && answer?.retryAfterSeconds !== void 0) return answer.retryAfterSeconds * 1e3;
|
|
164
|
+
const base = RETRY_BACKOFF_MS[Math.min(retryIndex, RETRY_BACKOFF_MS.length - 1)] ?? 0;
|
|
165
|
+
return base + Math.floor(base * RETRY_JITTER_SHARE * random());
|
|
166
|
+
};
|
|
167
|
+
var withRetries = async (run, policy, signal) => {
|
|
168
|
+
const random = policy.random ?? Math.random;
|
|
169
|
+
for (let retryIndex = 0; ; retryIndex += 1) {
|
|
170
|
+
const retriesLeft = retryIndex < policy.maxRetries;
|
|
171
|
+
let answer;
|
|
172
|
+
try {
|
|
173
|
+
answer = await run();
|
|
174
|
+
} catch (error) {
|
|
175
|
+
if (!(error instanceof SdkNetworkError) || signal?.aborted || !retriesLeft) throw error;
|
|
176
|
+
await policy.sleep(waitBeforeRetry(null, retryIndex, random), signal);
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
if (!isRetryableStatus(answer.status) || !retriesLeft) return answer;
|
|
180
|
+
const waitMs = waitBeforeRetry(answer, retryIndex, random);
|
|
181
|
+
if (waitMs > policy.maxRetryWaitMs) return answer;
|
|
182
|
+
await policy.sleep(waitMs, signal);
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
// src/transport.ts
|
|
187
|
+
var parseJson = (text) => {
|
|
188
|
+
try {
|
|
189
|
+
return JSON.parse(text);
|
|
190
|
+
} catch {
|
|
191
|
+
return void 0;
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
var readRetryAfterSeconds = (headers) => {
|
|
195
|
+
const value = headers.get(RETRY_AFTER_HEADER);
|
|
196
|
+
if (value === null) return null;
|
|
197
|
+
const seconds = Number(value);
|
|
198
|
+
return Number.isFinite(seconds) && seconds >= 0 ? seconds : null;
|
|
199
|
+
};
|
|
200
|
+
var describeCause = (cause) => cause instanceof Error ? cause.message : String(cause);
|
|
201
|
+
var rejectOnAbort = (signal) => {
|
|
202
|
+
let release = () => {
|
|
203
|
+
};
|
|
204
|
+
const promise = new Promise((_, reject) => {
|
|
205
|
+
if (signal.aborted) {
|
|
206
|
+
reject(signal.reason);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
const onAbort = () => reject(signal.reason);
|
|
210
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
211
|
+
release = () => signal.removeEventListener("abort", onAbort);
|
|
212
|
+
});
|
|
213
|
+
promise.catch(() => {
|
|
214
|
+
});
|
|
215
|
+
return { promise, release };
|
|
216
|
+
};
|
|
217
|
+
var createTransport = ({ baseUrl, key, fetchImplementation }) => {
|
|
218
|
+
const sendOnce = async ({ method, path, body, timeoutMs, signal: callerSignal }) => {
|
|
219
|
+
const url = `${baseUrl}${SDK_ROUTE_BASE}${path}`;
|
|
220
|
+
const headers = {
|
|
221
|
+
Authorization: `Bearer ${key}`,
|
|
222
|
+
Accept: "application/json"
|
|
223
|
+
};
|
|
224
|
+
if (body !== void 0) headers["Content-Type"] = "application/json";
|
|
225
|
+
const timeoutSignal = AbortSignal.timeout(timeoutMs);
|
|
226
|
+
const signal = callerSignal ? AbortSignal.any([timeoutSignal, callerSignal]) : timeoutSignal;
|
|
227
|
+
const abort = rejectOnAbort(signal);
|
|
228
|
+
const attempt = async () => {
|
|
229
|
+
const response = await fetchImplementation(url, {
|
|
230
|
+
method,
|
|
231
|
+
headers,
|
|
232
|
+
body: body === void 0 ? void 0 : JSON.stringify(body),
|
|
233
|
+
signal
|
|
234
|
+
});
|
|
235
|
+
const text = await response.text();
|
|
236
|
+
return {
|
|
237
|
+
status: response.status,
|
|
238
|
+
ok: response.ok,
|
|
239
|
+
requestId: response.headers.get(REQUEST_ID_HEADER),
|
|
240
|
+
retryAfterSeconds: readRetryAfterSeconds(response.headers),
|
|
241
|
+
json: parseJson(text)
|
|
242
|
+
};
|
|
243
|
+
};
|
|
244
|
+
try {
|
|
245
|
+
if (signal.aborted) throw signal.reason;
|
|
246
|
+
return await Promise.race([attempt(), abort.promise]);
|
|
247
|
+
} catch (cause) {
|
|
248
|
+
if (timeoutSignal.aborted) {
|
|
249
|
+
throw new SdkNetworkError({ message: `No answer from the Appnigma API within ${timeoutMs} ms`, cause });
|
|
250
|
+
}
|
|
251
|
+
if (callerSignal?.aborted) {
|
|
252
|
+
throw new SdkNetworkError({ message: "The call was aborted before the Appnigma API answered", cause });
|
|
253
|
+
}
|
|
254
|
+
throw new SdkNetworkError({ message: `Could not reach the Appnigma API: ${describeCause(cause)}`, cause });
|
|
255
|
+
} finally {
|
|
256
|
+
abort.release();
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
return sendOnce;
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
// src/client.ts
|
|
263
|
+
var readAnswer = (answer) => {
|
|
264
|
+
if (!answer.ok) {
|
|
265
|
+
throw toSdkError({
|
|
266
|
+
status: answer.status,
|
|
267
|
+
body: answer.json,
|
|
268
|
+
requestId: answer.requestId,
|
|
269
|
+
retryAfterSeconds: answer.retryAfterSeconds
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
if (answer.json === void 0) {
|
|
273
|
+
throw new SdkServerError({
|
|
274
|
+
code: "INTERNAL_ERROR",
|
|
275
|
+
message: `The Appnigma API answered ${answer.status} with a body that is not JSON`,
|
|
276
|
+
status: answer.status,
|
|
277
|
+
requestId: answer.requestId
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
return answer.json;
|
|
281
|
+
};
|
|
282
|
+
var refuseInput = (field, problem) => {
|
|
283
|
+
throw new SdkInputError({
|
|
284
|
+
code: "INVALID_INPUT",
|
|
285
|
+
message: `${field} ${problem}`,
|
|
286
|
+
details: { problems: [{ field, problem }] }
|
|
287
|
+
});
|
|
288
|
+
};
|
|
289
|
+
var checkTimeout = (timeoutMs) => {
|
|
290
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) refuseInput("timeoutMs", "must be a number of milliseconds above zero");
|
|
291
|
+
return timeoutMs;
|
|
292
|
+
};
|
|
293
|
+
var createClient = (options) => {
|
|
294
|
+
if (!options.key || !options.key.startsWith(SDK_KEY_PREFIX)) {
|
|
295
|
+
throw new SdkAuthError({
|
|
296
|
+
code: "SDK_KEY_MISSING",
|
|
297
|
+
message: `Create the client with your SDK key, it starts with ${SDK_KEY_PREFIX}`
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
const baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
301
|
+
if (!/^https?:\/\/\S+$/i.test(baseUrl)) refuseInput("baseUrl", "must be an http:// or https:// address");
|
|
302
|
+
const timeoutMs = checkTimeout(options.timeoutMs ?? DEFAULT_TIMEOUT_MS);
|
|
303
|
+
const maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
304
|
+
if (!Number.isInteger(maxRetries) || maxRetries < 0) refuseInput("maxRetries", "must be a whole number, 0 or more");
|
|
305
|
+
const maxRetryWaitMs = options.maxRetryWaitMs ?? DEFAULT_MAX_RETRY_WAIT_MS;
|
|
306
|
+
if (!Number.isFinite(maxRetryWaitMs) || maxRetryWaitMs < 0) refuseInput("maxRetryWaitMs", "must be a number of milliseconds, 0 or more");
|
|
307
|
+
const policy = { maxRetries, maxRetryWaitMs, sleep };
|
|
308
|
+
const sendOnce = createTransport({
|
|
309
|
+
baseUrl,
|
|
310
|
+
key: options.key,
|
|
311
|
+
fetchImplementation: options.fetchImplementation ?? fetch
|
|
312
|
+
});
|
|
313
|
+
const call = async (method, path, body, callOptions = {}) => {
|
|
314
|
+
const attemptTimeoutMs = callOptions.timeoutMs === void 0 ? timeoutMs : checkTimeout(callOptions.timeoutMs);
|
|
315
|
+
const signal = callOptions.signal;
|
|
316
|
+
const answer = await withRetries(
|
|
317
|
+
() => sendOnce({ method, path, body, timeoutMs: attemptTimeoutMs, signal }),
|
|
318
|
+
policy,
|
|
319
|
+
signal
|
|
320
|
+
);
|
|
321
|
+
return readAnswer(answer);
|
|
322
|
+
};
|
|
323
|
+
return {
|
|
324
|
+
post: (input, callOptions) => call("POST", "/post", input, callOptions),
|
|
325
|
+
pull: (input, callOptions) => call("POST", "/pull", input, callOptions),
|
|
326
|
+
connections: {
|
|
327
|
+
createLink: (input, callOptions) => call("POST", "/connections/link", input, callOptions),
|
|
328
|
+
// The id travels in the path, so it is checked here first: a bad one is
|
|
329
|
+
// refused as the server would refuse it, and never becomes a wrong route.
|
|
330
|
+
// Async so the refusal is a rejection, the way every other failure is.
|
|
331
|
+
get: async (endCustomerId, callOptions) => {
|
|
332
|
+
if (typeof endCustomerId !== "string" || !END_CUSTOMER_ID_PATTERN.test(endCustomerId)) {
|
|
333
|
+
refuseInput("endCustomerId", END_CUSTOMER_ID_RULE);
|
|
334
|
+
}
|
|
335
|
+
return call("GET", `/connections/${encodeURIComponent(endCustomerId)}`, void 0, callOptions);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
exports.CONNECTION_STATUSES = CONNECTION_STATUSES;
|
|
342
|
+
exports.SDK_ERROR_CODES = SDK_ERROR_CODES;
|
|
343
|
+
exports.SDK_OBJECTS = SDK_OBJECTS;
|
|
344
|
+
exports.SDK_PLATFORMS = SDK_PLATFORMS;
|
|
345
|
+
exports.SdkAuthError = SdkAuthError;
|
|
346
|
+
exports.SdkError = SdkError;
|
|
347
|
+
exports.SdkInputError = SdkInputError;
|
|
348
|
+
exports.SdkNetworkError = SdkNetworkError;
|
|
349
|
+
exports.SdkNotFoundError = SdkNotFoundError;
|
|
350
|
+
exports.SdkRateLimitError = SdkRateLimitError;
|
|
351
|
+
exports.SdkReconnectError = SdkReconnectError;
|
|
352
|
+
exports.SdkServerError = SdkServerError;
|
|
353
|
+
exports.createClient = createClient;
|
|
354
|
+
//# sourceMappingURL=index.cjs.map
|
|
355
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/constants/index.ts","../src/sdk-error.ts","../src/errors/index.ts","../src/retry.ts","../src/transport.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["const SDK_KEY_PREFIX = \"apn_live_\";\n\n// Where the SDK calls when no baseUrl is given (Q4).\nconst DEFAULT_BASE_URL = \"https://api.appnigma.ai\";\n\nconst SDK_ROUTE_BASE = \"/sdk/v1\";\n\nconst REQUEST_ID_HEADER = \"x-request-id\";\n\n// Sent by the server on 429, in seconds (sdk-error-response.ts).\nconst RETRY_AFTER_HEADER = \"retry-after\";\n\n// This package's own code for \"no answer arrived\". Not in brief 6.3, which\n// only lists codes the server can send.\nconst NETWORK_ERROR_CODE = \"NETWORK_ERROR\";\n\n// How long one attempt may take before it counts as a network failure.\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\n// Tries again after the first attempt: three attempts in all.\nconst DEFAULT_MAX_RETRIES = 2;\n\n// A Retry-After longer than this is reported, not waited for.\nconst DEFAULT_MAX_RETRY_WAIT_MS = 30_000;\n\n// The wait before each retry when the server sent no Retry-After.\nconst RETRY_BACKOFF_MS = [500, 1000] as const;\n\n// Up to this share of the backoff is added at random (jitter), so many\n// clients that failed together do not all try again in the same instant.\nconst RETRY_JITTER_SHARE = 0.25;\n\nconst SDK_OBJECTS = [\"contact\", \"company\", \"deal\"] as const;\n\nconst SDK_PLATFORMS = [\"hubspot\"] as const;\n\nconst CONNECTION_STATUSES = [\"connected\", \"needs_reconnect\", \"disconnected\"] as const;\n\n// Brief 6.2: an end customer id is 1 to 100 of letters, digits, dot, dash or\n// underscore. Checked before `connections.get` so a bad id never becomes a\n// wrong route.\nconst END_CUSTOMER_ID_PATTERN = /^[A-Za-z0-9._-]{1,100}$/;\nconst END_CUSTOMER_ID_RULE = \"must be 1 to 100 characters: letters, digits, dot, dash or underscore\";\n\n// Brief 6.3. The SDK keeps its own copy: it is published on its own and must\n// not depend on our server package.\nconst SDK_ERROR_CODES = [\n \"INVALID_INPUT\",\n \"SDK_KEY_MISSING\",\n \"SDK_KEY_INVALID\",\n \"SDK_KEY_CANCELLED\",\n \"MICROSERVER_NOT_ENABLED\",\n \"END_CUSTOMER_NOT_FOUND\",\n \"FUNCTION_NOT_FOUND\",\n \"CONNECTION_NEEDS_RECONNECT\",\n \"RATE_LIMITED\",\n \"PLATFORM_RATE_LIMITED\",\n \"PLATFORM_ERROR\",\n \"TIMED_OUT\",\n \"LOGIC_FAILED\",\n \"INTERNAL_ERROR\",\n] as const;\n\nexport {\n CONNECTION_STATUSES,\n DEFAULT_BASE_URL,\n DEFAULT_MAX_RETRIES,\n DEFAULT_MAX_RETRY_WAIT_MS,\n DEFAULT_TIMEOUT_MS,\n END_CUSTOMER_ID_PATTERN,\n END_CUSTOMER_ID_RULE,\n NETWORK_ERROR_CODE,\n REQUEST_ID_HEADER,\n RETRY_AFTER_HEADER,\n RETRY_BACKOFF_MS,\n RETRY_JITTER_SHARE,\n SDK_ERROR_CODES,\n SDK_KEY_PREFIX,\n SDK_OBJECTS,\n SDK_PLATFORMS,\n SDK_ROUTE_BASE,\n};\n","import type { SdkErrorCode, SdkErrorDetails } from \"./types/index.js\";\n\n// A code from brief 6.3, or whatever string a newer server sent. Keeping the\n// union open means an older package never misreports a code it has not met;\n// `(string & {})` keeps the known codes autocompleting.\ntype SdkErrorCodeValue = SdkErrorCode | (string & {});\n\ntype SdkErrorInit = {\n code: SdkErrorCodeValue;\n message: string;\n // Null when no answer arrived (a network failure, or a refusal at start).\n status?: number | null;\n requestId?: string | null;\n details?: SdkErrorDetails;\n cause?: unknown;\n};\n\n// Every failure the SDK raises, whether our server answered with an error or\n// could not be reached at all. Catch this for \"anything from Appnigma\", or one\n// of the subclasses in ./errors for one kind of failure.\nclass SdkError extends Error {\n readonly code: SdkErrorCodeValue;\n readonly status: number | null;\n readonly requestId: string | null;\n readonly details: SdkErrorDetails;\n\n constructor(init: SdkErrorInit) {\n super(init.message, init.cause === undefined ? undefined : { cause: init.cause });\n this.name = \"SdkError\";\n this.code = init.code;\n this.status = init.status ?? null;\n this.requestId = init.requestId ?? null;\n this.details = init.details ?? {};\n }\n}\n\nexport { SdkError };\nexport type { SdkErrorCodeValue, SdkErrorInit };\n","import { NETWORK_ERROR_CODE } from \"../constants/index.js\";\nimport { SdkError } from \"../sdk-error.js\";\nimport type { SdkErrorInit } from \"../sdk-error.js\";\nimport type { SdkErrorDetails, SdkProblem } from \"../types/index.js\";\n\n// Brief 6.3 is a table of statuses, so the type is chosen by status and never\n// by code: later tickets add codes (JOB_NOT_FOUND, CUSTOMER_API_ERROR) without\n// adding statuses, and this package must sort them right without an update.\n\nconst isProblem = (value: unknown): value is SdkProblem =>\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as SdkProblem).field === \"string\" &&\n typeof (value as SdkProblem).problem === \"string\";\n\nconst readProblems = (details: SdkErrorDetails): SdkProblem[] => {\n const list = details.problems;\n return Array.isArray(list) ? list.filter(isProblem) : [];\n};\n\n// 400. The server names each field it could not accept.\nclass SdkInputError extends SdkError {\n readonly problems: SdkProblem[];\n\n constructor(init: SdkErrorInit) {\n super(init);\n this.name = \"SdkInputError\";\n this.problems = readProblems(this.details);\n }\n}\n\n// 401 and 403, and a client started without a key.\nclass SdkAuthError extends SdkError {\n constructor(init: SdkErrorInit) {\n super(init);\n this.name = \"SdkAuthError\";\n }\n}\n\n// 404.\nclass SdkNotFoundError extends SdkError {\n constructor(init: SdkErrorInit) {\n super(init);\n this.name = \"SdkNotFoundError\";\n }\n}\n\n// 409. The end customer has to go through the connect flow again.\nclass SdkReconnectError extends SdkError {\n constructor(init: SdkErrorInit) {\n super(init);\n this.name = \"SdkReconnectError\";\n }\n}\n\n// 429. `retryAfterSeconds` is what the server's Retry-After header said, or\n// null when it sent none.\nclass SdkRateLimitError extends SdkError {\n readonly retryAfterSeconds: number | null;\n\n constructor(init: SdkErrorInit & { retryAfterSeconds?: number | null }) {\n super(init);\n this.name = \"SdkRateLimitError\";\n this.retryAfterSeconds = init.retryAfterSeconds ?? null;\n }\n}\n\n// Any 5xx, any status this package does not know, and any answer that is not\n// JSON. Our side is at fault, not the caller's input.\nclass SdkServerError extends SdkError {\n constructor(init: SdkErrorInit) {\n super(init);\n this.name = \"SdkServerError\";\n }\n}\n\n// No answer arrived: fetch threw, or the attempt ran out of time. `cause` is\n// the underlying error; status and requestId are null because nothing came\n// back to read them from.\nclass SdkNetworkError extends SdkError {\n constructor(init: { message: string; cause?: unknown }) {\n super({ code: NETWORK_ERROR_CODE, message: init.message, status: null, requestId: null, cause: init.cause });\n this.name = \"SdkNetworkError\";\n }\n}\n\ntype ToSdkErrorInput = {\n status: number;\n // The answer parsed as JSON, or undefined when the body was not JSON.\n body: unknown;\n requestId: string | null;\n retryAfterSeconds?: number | null;\n};\n\ntype ErrorShape = { code: string; message: string; details: SdkErrorDetails };\n\n// Our shape is `{ error: { code, message, details } }`. The code is kept as\n// the string the server sent, known to this package or not.\nconst readErrorShape = (body: unknown): ErrorShape | null => {\n if (typeof body !== \"object\" || body === null) return null;\n const error = (body as { error?: unknown }).error;\n if (typeof error !== \"object\" || error === null) return null;\n const { code, message, details } = error as { code?: unknown; message?: unknown; details?: unknown };\n if (typeof code !== \"string\" || code.length === 0) return null;\n const detailsIsObject = typeof details === \"object\" && details !== null && !Array.isArray(details);\n return {\n code,\n message: typeof message === \"string\" ? message : \"\",\n details: detailsIsObject ? (details as SdkErrorDetails) : {},\n };\n};\n\n// Turns a refusal from the server into the error type for its status.\nconst toSdkError = ({ status, body, requestId, retryAfterSeconds = null }: ToSdkErrorInput): SdkError => {\n const fallbackMessage = `The Appnigma API answered ${status}`;\n const shape = readErrorShape(body) ?? { code: \"INTERNAL_ERROR\", message: fallbackMessage, details: {} };\n const init: SdkErrorInit = {\n code: shape.code,\n message: shape.message || fallbackMessage,\n status,\n requestId,\n details: shape.details,\n };\n switch (status) {\n case 400:\n return new SdkInputError(init);\n case 401:\n case 403:\n return new SdkAuthError(init);\n case 404:\n return new SdkNotFoundError(init);\n case 409:\n return new SdkReconnectError(init);\n case 429:\n return new SdkRateLimitError({ ...init, retryAfterSeconds });\n default:\n return new SdkServerError(init);\n }\n};\n\nexport {\n SdkAuthError,\n SdkInputError,\n SdkNetworkError,\n SdkNotFoundError,\n SdkRateLimitError,\n SdkReconnectError,\n SdkServerError,\n toSdkError,\n};\nexport type { ToSdkErrorInput };\n","import { RETRY_BACKOFF_MS, RETRY_JITTER_SHARE } from \"./constants/index.js\";\nimport { SdkNetworkError } from \"./errors/index.js\";\nimport type { TransportAnswer } from \"./transport.js\";\n\n// Tries again only when trying again is safe (ticket acceptance 4): the\n// network failed, we answered 5xx, or we answered 429. Never on 400, 401,\n// 403, 404 or 409, because the same request would be refused the same way.\n//\n// Repeating `post` is safe only because the server upserts (brief decision\n// 12): a repeat of a request that did land changes nothing. If `post` ever\n// stops being an upsert, the retry on 5xx and on a network failure has to be\n// revisited here.\n\ntype Sleep = (ms: number, signal?: AbortSignal) => Promise<void>;\n\ntype RetryPolicy = {\n // How many times to try again after the first attempt. 0 means one attempt.\n maxRetries: number;\n // A wait longer than this is not waited for: the answer is handed back at\n // once so the caller learns the wait instead of sitting through it.\n maxRetryWaitMs: number;\n sleep: Sleep;\n // A number in [0, 1) for the jitter. Tests pin it; callers leave it.\n random?: () => number;\n};\n\n// Waits, but wakes early when the signal aborts so a caller's abort is not\n// stuck behind a long Retry-After. The next attempt then sees the aborted\n// signal and raises the proper error without touching the network.\nconst sleep: Sleep = (ms, signal) =>\n new Promise((resolve) => {\n if (signal?.aborted) {\n resolve();\n return;\n }\n const onAbort = (): void => {\n clearTimeout(timer);\n resolve();\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n\nconst isRetryableStatus = (status: number): boolean => status === 429 || status >= 500;\n\n// Retry-After wins when the server sent one and is taken as given: that wait\n// is the server's instruction. Otherwise the fixed backoff plus jitter, with\n// the last backoff repeated if there are more retries than steps.\nconst waitBeforeRetry = (answer: TransportAnswer | null, retryIndex: number, random: () => number): number => {\n if (answer?.retryAfterSeconds !== null && answer?.retryAfterSeconds !== undefined) return answer.retryAfterSeconds * 1000;\n const base = RETRY_BACKOFF_MS[Math.min(retryIndex, RETRY_BACKOFF_MS.length - 1)] ?? 0;\n return base + Math.floor(base * RETRY_JITTER_SHARE * random());\n};\n\n// Runs one attempt up to `maxRetries + 1` times. Returns the last answer, good\n// or bad, so the caller judges it; throws only when no answer ever came back.\nconst withRetries = async (\n run: () => Promise<TransportAnswer>,\n policy: RetryPolicy,\n signal?: AbortSignal,\n): Promise<TransportAnswer> => {\n const random = policy.random ?? Math.random;\n for (let retryIndex = 0; ; retryIndex += 1) {\n const retriesLeft = retryIndex < policy.maxRetries;\n let answer: TransportAnswer;\n try {\n answer = await run();\n } catch (error) {\n // Anything other than \"nothing came back\" is a bug, not a bad second.\n // A caller's own abort is their decision, not a bad second either.\n if (!(error instanceof SdkNetworkError) || signal?.aborted || !retriesLeft) throw error;\n await policy.sleep(waitBeforeRetry(null, retryIndex, random), signal);\n continue;\n }\n if (!isRetryableStatus(answer.status) || !retriesLeft) return answer;\n const waitMs = waitBeforeRetry(answer, retryIndex, random);\n if (waitMs > policy.maxRetryWaitMs) return answer;\n await policy.sleep(waitMs, signal);\n }\n};\n\nexport { isRetryableStatus, sleep, withRetries };\nexport type { RetryPolicy, Sleep };\n","import { REQUEST_ID_HEADER, RETRY_AFTER_HEADER, SDK_ROUTE_BASE } from \"./constants/index.js\";\nimport { SdkNetworkError } from \"./errors/index.js\";\n\n// One attempt at one request. Builds the URL and headers, runs it under a time\n// limit, reads the body, and reports what came back without judging it. The\n// client decides what an answer means; retries (step 3) decide whether to try\n// again. The only thing thrown here is SdkNetworkError: nothing came back.\n\ntype TransportConfig = {\n baseUrl: string;\n key: string;\n fetchImplementation: typeof fetch;\n};\n\ntype TransportRequest = {\n method: \"GET\" | \"POST\";\n // Below SDK_ROUTE_BASE, starting with a slash.\n path: string;\n body?: object;\n timeoutMs: number;\n // The caller's own signal. Aborting it stops the attempt at once.\n signal?: AbortSignal;\n};\n\ntype TransportAnswer = {\n status: number;\n ok: boolean;\n requestId: string | null;\n retryAfterSeconds: number | null;\n // The body parsed as JSON, or undefined when it did not parse.\n json: unknown;\n};\n\ntype SendOnce = (request: TransportRequest) => Promise<TransportAnswer>;\n\nconst parseJson = (text: string): unknown => {\n try {\n return JSON.parse(text) as unknown;\n } catch {\n return undefined;\n }\n};\n\n// Our server sends seconds. Anything else (an HTTP date from a proxy, junk)\n// reads as \"not given\" rather than as a wait.\nconst readRetryAfterSeconds = (headers: Headers): number | null => {\n const value = headers.get(RETRY_AFTER_HEADER);\n if (value === null) return null;\n const seconds = Number(value);\n return Number.isFinite(seconds) && seconds >= 0 ? seconds : null;\n};\n\nconst describeCause = (cause: unknown): string => (cause instanceof Error ? cause.message : String(cause));\n\n// Rejects the moment the signal aborts. A fetch honours its signal on its own,\n// but a stand-in fetch in a test may not, and reading the body must stop too,\n// so the attempt is raced against the signal rather than trusting fetch alone.\nconst rejectOnAbort = (signal: AbortSignal): { promise: Promise<never>; release: () => void } => {\n let release = (): void => {};\n const promise = new Promise<never>((_, reject) => {\n if (signal.aborted) {\n reject(signal.reason);\n return;\n }\n const onAbort = (): void => reject(signal.reason);\n signal.addEventListener(\"abort\", onAbort, { once: true });\n release = () => signal.removeEventListener(\"abort\", onAbort);\n });\n // A rejection nobody awaits yet must not count as unhandled.\n promise.catch(() => {});\n return { promise, release };\n};\n\nconst createTransport = ({ baseUrl, key, fetchImplementation }: TransportConfig): SendOnce => {\n const sendOnce: SendOnce = async ({ method, path, body, timeoutMs, signal: callerSignal }) => {\n const url = `${baseUrl}${SDK_ROUTE_BASE}${path}`;\n const headers: Record<string, string> = {\n Authorization: `Bearer ${key}`,\n Accept: \"application/json\",\n };\n if (body !== undefined) headers[\"Content-Type\"] = \"application/json\";\n\n const timeoutSignal = AbortSignal.timeout(timeoutMs);\n const signal = callerSignal ? AbortSignal.any([timeoutSignal, callerSignal]) : timeoutSignal;\n const abort = rejectOnAbort(signal);\n\n const attempt = async (): Promise<TransportAnswer> => {\n const response = await fetchImplementation(url, {\n method,\n headers,\n body: body === undefined ? undefined : JSON.stringify(body),\n signal,\n });\n const text = await response.text();\n return {\n status: response.status,\n ok: response.ok,\n requestId: response.headers.get(REQUEST_ID_HEADER),\n retryAfterSeconds: readRetryAfterSeconds(response.headers),\n json: parseJson(text),\n };\n };\n\n try {\n // A signal aborted before the call started means no attempt at all.\n if (signal.aborted) throw signal.reason;\n return await Promise.race([attempt(), abort.promise]);\n } catch (cause) {\n if (timeoutSignal.aborted) {\n throw new SdkNetworkError({ message: `No answer from the Appnigma API within ${timeoutMs} ms`, cause });\n }\n if (callerSignal?.aborted) {\n throw new SdkNetworkError({ message: \"The call was aborted before the Appnigma API answered\", cause });\n }\n throw new SdkNetworkError({ message: `Could not reach the Appnigma API: ${describeCause(cause)}`, cause });\n } finally {\n abort.release();\n }\n };\n\n return sendOnce;\n};\n\nexport { createTransport };\nexport type { SendOnce, TransportAnswer, TransportRequest };\n","import {\n DEFAULT_BASE_URL,\n DEFAULT_MAX_RETRIES,\n DEFAULT_MAX_RETRY_WAIT_MS,\n DEFAULT_TIMEOUT_MS,\n END_CUSTOMER_ID_PATTERN,\n END_CUSTOMER_ID_RULE,\n SDK_KEY_PREFIX,\n} from \"./constants/index.js\";\nimport { SdkAuthError, SdkInputError, SdkServerError, toSdkError } from \"./errors/index.js\";\nimport { sleep, withRetries } from \"./retry.js\";\nimport type { RetryPolicy } from \"./retry.js\";\nimport { createTransport } from \"./transport.js\";\nimport type { TransportAnswer, TransportRequest } from \"./transport.js\";\nimport type {\n CallOptions,\n CreateLinkInput,\n CreateLinkOutput,\n GetConnectionOutput,\n PostInput,\n PostOutput,\n PullInput,\n PullOutput,\n SdkClient,\n SdkClientOptions,\n} from \"./types/index.js\";\n\n// Turns one answer into the call's result, or into the error for its status.\n// A success whose body is not JSON is a server error (brief 6.3, \"an answer\n// that is not JSON\"): a proxy page or an empty body is never handed back as\n// data.\nconst readAnswer = <Output>(answer: TransportAnswer): Output => {\n if (!answer.ok) {\n throw toSdkError({\n status: answer.status,\n body: answer.json,\n requestId: answer.requestId,\n retryAfterSeconds: answer.retryAfterSeconds,\n });\n }\n if (answer.json === undefined) {\n throw new SdkServerError({\n code: \"INTERNAL_ERROR\",\n message: `The Appnigma API answered ${answer.status} with a body that is not JSON`,\n status: answer.status,\n requestId: answer.requestId,\n });\n }\n return answer.json as Output;\n};\n\n// A refusal made here, before any call, for a setting or an input the server\n// would refuse anyway. Same shape as the server's, so one catch handles both.\nconst refuseInput = (field: string, problem: string): never => {\n throw new SdkInputError({\n code: \"INVALID_INPUT\",\n message: `${field} ${problem}`,\n details: { problems: [{ field, problem }] },\n });\n};\n\nconst checkTimeout = (timeoutMs: number): number => {\n if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) refuseInput(\"timeoutMs\", \"must be a number of milliseconds above zero\");\n return timeoutMs;\n};\n\nconst createClient = (options: SdkClientOptions): SdkClient => {\n if (!options.key || !options.key.startsWith(SDK_KEY_PREFIX)) {\n throw new SdkAuthError({\n code: \"SDK_KEY_MISSING\",\n message: `Create the client with your SDK key, it starts with ${SDK_KEY_PREFIX}`,\n });\n }\n const baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n if (!/^https?:\\/\\/\\S+$/i.test(baseUrl)) refuseInput(\"baseUrl\", \"must be an http:// or https:// address\");\n const timeoutMs = checkTimeout(options.timeoutMs ?? DEFAULT_TIMEOUT_MS);\n const maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;\n if (!Number.isInteger(maxRetries) || maxRetries < 0) refuseInput(\"maxRetries\", \"must be a whole number, 0 or more\");\n const maxRetryWaitMs = options.maxRetryWaitMs ?? DEFAULT_MAX_RETRY_WAIT_MS;\n if (!Number.isFinite(maxRetryWaitMs) || maxRetryWaitMs < 0) refuseInput(\"maxRetryWaitMs\", \"must be a number of milliseconds, 0 or more\");\n const policy: RetryPolicy = { maxRetries, maxRetryWaitMs, sleep };\n\n const sendOnce = createTransport({\n baseUrl,\n key: options.key,\n fetchImplementation: options.fetchImplementation ?? fetch,\n });\n\n const call = async <Output>(\n method: TransportRequest[\"method\"],\n path: string,\n body: object | undefined,\n callOptions: CallOptions = {},\n ): Promise<Output> => {\n const attemptTimeoutMs = callOptions.timeoutMs === undefined ? timeoutMs : checkTimeout(callOptions.timeoutMs);\n const signal = callOptions.signal;\n const answer = await withRetries(\n () => sendOnce({ method, path, body, timeoutMs: attemptTimeoutMs, signal }),\n policy,\n signal,\n );\n return readAnswer<Output>(answer);\n };\n\n return {\n post: (input: PostInput, callOptions?: CallOptions) => call<PostOutput>(\"POST\", \"/post\", input, callOptions),\n pull: (input: PullInput, callOptions?: CallOptions) => call<PullOutput>(\"POST\", \"/pull\", input, callOptions),\n connections: {\n createLink: (input: CreateLinkInput, callOptions?: CallOptions) =>\n call<CreateLinkOutput>(\"POST\", \"/connections/link\", input, callOptions),\n // The id travels in the path, so it is checked here first: a bad one is\n // refused as the server would refuse it, and never becomes a wrong route.\n // Async so the refusal is a rejection, the way every other failure is.\n get: async (endCustomerId: string, callOptions?: CallOptions) => {\n if (typeof endCustomerId !== \"string\" || !END_CUSTOMER_ID_PATTERN.test(endCustomerId)) {\n refuseInput(\"endCustomerId\", END_CUSTOMER_ID_RULE);\n }\n return call<GetConnectionOutput>(\"GET\", `/connections/${encodeURIComponent(endCustomerId)}`, undefined, callOptions);\n },\n },\n };\n};\n\nexport { createClient };\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
declare const SDK_OBJECTS: readonly ["contact", "company", "deal"];
|
|
2
|
+
declare const SDK_PLATFORMS: readonly ["hubspot"];
|
|
3
|
+
declare const CONNECTION_STATUSES: readonly ["connected", "needs_reconnect", "disconnected"];
|
|
4
|
+
declare const SDK_ERROR_CODES: readonly ["INVALID_INPUT", "SDK_KEY_MISSING", "SDK_KEY_INVALID", "SDK_KEY_CANCELLED", "MICROSERVER_NOT_ENABLED", "END_CUSTOMER_NOT_FOUND", "FUNCTION_NOT_FOUND", "CONNECTION_NEEDS_RECONNECT", "RATE_LIMITED", "PLATFORM_RATE_LIMITED", "PLATFORM_ERROR", "TIMED_OUT", "LOGIC_FAILED", "INTERNAL_ERROR"];
|
|
5
|
+
|
|
6
|
+
type SdkObject = (typeof SDK_OBJECTS)[number];
|
|
7
|
+
type SdkPlatform = (typeof SDK_PLATFORMS)[number];
|
|
8
|
+
type ConnectionStatus = (typeof CONNECTION_STATUSES)[number];
|
|
9
|
+
type SdkErrorCode = (typeof SDK_ERROR_CODES)[number];
|
|
10
|
+
type RecordValue = string | number | boolean | null;
|
|
11
|
+
type SdkClientOptions = {
|
|
12
|
+
key: string;
|
|
13
|
+
baseUrl?: string;
|
|
14
|
+
timeoutMs?: number;
|
|
15
|
+
maxRetries?: number;
|
|
16
|
+
maxRetryWaitMs?: number;
|
|
17
|
+
fetchImplementation?: typeof fetch;
|
|
18
|
+
};
|
|
19
|
+
type PostInput = {
|
|
20
|
+
endCustomerId: string;
|
|
21
|
+
object: SdkObject;
|
|
22
|
+
record: Record<string, RecordValue>;
|
|
23
|
+
uniqueBy?: string;
|
|
24
|
+
};
|
|
25
|
+
type PostOutput = {
|
|
26
|
+
id: string;
|
|
27
|
+
created: boolean;
|
|
28
|
+
};
|
|
29
|
+
type PullInput = {
|
|
30
|
+
endCustomerId: string;
|
|
31
|
+
object: SdkObject;
|
|
32
|
+
limit?: number;
|
|
33
|
+
after?: string;
|
|
34
|
+
};
|
|
35
|
+
type PullOutput = {
|
|
36
|
+
records: Array<{
|
|
37
|
+
id: string;
|
|
38
|
+
properties: Record<string, string | null>;
|
|
39
|
+
}>;
|
|
40
|
+
next: string | null;
|
|
41
|
+
};
|
|
42
|
+
type CallOptions = {
|
|
43
|
+
timeoutMs?: number;
|
|
44
|
+
signal?: AbortSignal;
|
|
45
|
+
};
|
|
46
|
+
type CreateLinkInput = {
|
|
47
|
+
endCustomerId: string;
|
|
48
|
+
platform: SdkPlatform;
|
|
49
|
+
returnUrl: string;
|
|
50
|
+
};
|
|
51
|
+
type CreateLinkOutput = {
|
|
52
|
+
url: string;
|
|
53
|
+
expiresAt: string;
|
|
54
|
+
};
|
|
55
|
+
type GetConnectionOutput = {
|
|
56
|
+
endCustomerId: string;
|
|
57
|
+
platform: SdkPlatform;
|
|
58
|
+
status: ConnectionStatus;
|
|
59
|
+
};
|
|
60
|
+
type SdkProblem = {
|
|
61
|
+
field: string;
|
|
62
|
+
problem: string;
|
|
63
|
+
};
|
|
64
|
+
type SdkErrorDetails = Record<string, string | number | boolean | null | SdkProblem[]>;
|
|
65
|
+
type SdkClient = {
|
|
66
|
+
post: (input: PostInput, options?: CallOptions) => Promise<PostOutput>;
|
|
67
|
+
pull: (input: PullInput, options?: CallOptions) => Promise<PullOutput>;
|
|
68
|
+
connections: {
|
|
69
|
+
createLink: (input: CreateLinkInput, options?: CallOptions) => Promise<CreateLinkOutput>;
|
|
70
|
+
get: (endCustomerId: string, options?: CallOptions) => Promise<GetConnectionOutput>;
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
declare const createClient: (options: SdkClientOptions) => SdkClient;
|
|
75
|
+
|
|
76
|
+
type SdkErrorCodeValue = SdkErrorCode | (string & {});
|
|
77
|
+
type SdkErrorInit = {
|
|
78
|
+
code: SdkErrorCodeValue;
|
|
79
|
+
message: string;
|
|
80
|
+
status?: number | null;
|
|
81
|
+
requestId?: string | null;
|
|
82
|
+
details?: SdkErrorDetails;
|
|
83
|
+
cause?: unknown;
|
|
84
|
+
};
|
|
85
|
+
declare class SdkError extends Error {
|
|
86
|
+
readonly code: SdkErrorCodeValue;
|
|
87
|
+
readonly status: number | null;
|
|
88
|
+
readonly requestId: string | null;
|
|
89
|
+
readonly details: SdkErrorDetails;
|
|
90
|
+
constructor(init: SdkErrorInit);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
declare class SdkInputError extends SdkError {
|
|
94
|
+
readonly problems: SdkProblem[];
|
|
95
|
+
constructor(init: SdkErrorInit);
|
|
96
|
+
}
|
|
97
|
+
declare class SdkAuthError extends SdkError {
|
|
98
|
+
constructor(init: SdkErrorInit);
|
|
99
|
+
}
|
|
100
|
+
declare class SdkNotFoundError extends SdkError {
|
|
101
|
+
constructor(init: SdkErrorInit);
|
|
102
|
+
}
|
|
103
|
+
declare class SdkReconnectError extends SdkError {
|
|
104
|
+
constructor(init: SdkErrorInit);
|
|
105
|
+
}
|
|
106
|
+
declare class SdkRateLimitError extends SdkError {
|
|
107
|
+
readonly retryAfterSeconds: number | null;
|
|
108
|
+
constructor(init: SdkErrorInit & {
|
|
109
|
+
retryAfterSeconds?: number | null;
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
declare class SdkServerError extends SdkError {
|
|
113
|
+
constructor(init: SdkErrorInit);
|
|
114
|
+
}
|
|
115
|
+
declare class SdkNetworkError extends SdkError {
|
|
116
|
+
constructor(init: {
|
|
117
|
+
message: string;
|
|
118
|
+
cause?: unknown;
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export { CONNECTION_STATUSES, type CallOptions, type ConnectionStatus, type CreateLinkInput, type CreateLinkOutput, type GetConnectionOutput, type PostInput, type PostOutput, type PullInput, type PullOutput, SDK_ERROR_CODES, SDK_OBJECTS, SDK_PLATFORMS, SdkAuthError, type SdkClient, type SdkClientOptions, SdkError, type SdkErrorCode, type SdkErrorCodeValue, type SdkErrorDetails, SdkInputError, SdkNetworkError, SdkNotFoundError, type SdkObject, type SdkPlatform, type SdkProblem, SdkRateLimitError, SdkReconnectError, SdkServerError, createClient };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
declare const SDK_OBJECTS: readonly ["contact", "company", "deal"];
|
|
2
|
+
declare const SDK_PLATFORMS: readonly ["hubspot"];
|
|
3
|
+
declare const CONNECTION_STATUSES: readonly ["connected", "needs_reconnect", "disconnected"];
|
|
4
|
+
declare const SDK_ERROR_CODES: readonly ["INVALID_INPUT", "SDK_KEY_MISSING", "SDK_KEY_INVALID", "SDK_KEY_CANCELLED", "MICROSERVER_NOT_ENABLED", "END_CUSTOMER_NOT_FOUND", "FUNCTION_NOT_FOUND", "CONNECTION_NEEDS_RECONNECT", "RATE_LIMITED", "PLATFORM_RATE_LIMITED", "PLATFORM_ERROR", "TIMED_OUT", "LOGIC_FAILED", "INTERNAL_ERROR"];
|
|
5
|
+
|
|
6
|
+
type SdkObject = (typeof SDK_OBJECTS)[number];
|
|
7
|
+
type SdkPlatform = (typeof SDK_PLATFORMS)[number];
|
|
8
|
+
type ConnectionStatus = (typeof CONNECTION_STATUSES)[number];
|
|
9
|
+
type SdkErrorCode = (typeof SDK_ERROR_CODES)[number];
|
|
10
|
+
type RecordValue = string | number | boolean | null;
|
|
11
|
+
type SdkClientOptions = {
|
|
12
|
+
key: string;
|
|
13
|
+
baseUrl?: string;
|
|
14
|
+
timeoutMs?: number;
|
|
15
|
+
maxRetries?: number;
|
|
16
|
+
maxRetryWaitMs?: number;
|
|
17
|
+
fetchImplementation?: typeof fetch;
|
|
18
|
+
};
|
|
19
|
+
type PostInput = {
|
|
20
|
+
endCustomerId: string;
|
|
21
|
+
object: SdkObject;
|
|
22
|
+
record: Record<string, RecordValue>;
|
|
23
|
+
uniqueBy?: string;
|
|
24
|
+
};
|
|
25
|
+
type PostOutput = {
|
|
26
|
+
id: string;
|
|
27
|
+
created: boolean;
|
|
28
|
+
};
|
|
29
|
+
type PullInput = {
|
|
30
|
+
endCustomerId: string;
|
|
31
|
+
object: SdkObject;
|
|
32
|
+
limit?: number;
|
|
33
|
+
after?: string;
|
|
34
|
+
};
|
|
35
|
+
type PullOutput = {
|
|
36
|
+
records: Array<{
|
|
37
|
+
id: string;
|
|
38
|
+
properties: Record<string, string | null>;
|
|
39
|
+
}>;
|
|
40
|
+
next: string | null;
|
|
41
|
+
};
|
|
42
|
+
type CallOptions = {
|
|
43
|
+
timeoutMs?: number;
|
|
44
|
+
signal?: AbortSignal;
|
|
45
|
+
};
|
|
46
|
+
type CreateLinkInput = {
|
|
47
|
+
endCustomerId: string;
|
|
48
|
+
platform: SdkPlatform;
|
|
49
|
+
returnUrl: string;
|
|
50
|
+
};
|
|
51
|
+
type CreateLinkOutput = {
|
|
52
|
+
url: string;
|
|
53
|
+
expiresAt: string;
|
|
54
|
+
};
|
|
55
|
+
type GetConnectionOutput = {
|
|
56
|
+
endCustomerId: string;
|
|
57
|
+
platform: SdkPlatform;
|
|
58
|
+
status: ConnectionStatus;
|
|
59
|
+
};
|
|
60
|
+
type SdkProblem = {
|
|
61
|
+
field: string;
|
|
62
|
+
problem: string;
|
|
63
|
+
};
|
|
64
|
+
type SdkErrorDetails = Record<string, string | number | boolean | null | SdkProblem[]>;
|
|
65
|
+
type SdkClient = {
|
|
66
|
+
post: (input: PostInput, options?: CallOptions) => Promise<PostOutput>;
|
|
67
|
+
pull: (input: PullInput, options?: CallOptions) => Promise<PullOutput>;
|
|
68
|
+
connections: {
|
|
69
|
+
createLink: (input: CreateLinkInput, options?: CallOptions) => Promise<CreateLinkOutput>;
|
|
70
|
+
get: (endCustomerId: string, options?: CallOptions) => Promise<GetConnectionOutput>;
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
declare const createClient: (options: SdkClientOptions) => SdkClient;
|
|
75
|
+
|
|
76
|
+
type SdkErrorCodeValue = SdkErrorCode | (string & {});
|
|
77
|
+
type SdkErrorInit = {
|
|
78
|
+
code: SdkErrorCodeValue;
|
|
79
|
+
message: string;
|
|
80
|
+
status?: number | null;
|
|
81
|
+
requestId?: string | null;
|
|
82
|
+
details?: SdkErrorDetails;
|
|
83
|
+
cause?: unknown;
|
|
84
|
+
};
|
|
85
|
+
declare class SdkError extends Error {
|
|
86
|
+
readonly code: SdkErrorCodeValue;
|
|
87
|
+
readonly status: number | null;
|
|
88
|
+
readonly requestId: string | null;
|
|
89
|
+
readonly details: SdkErrorDetails;
|
|
90
|
+
constructor(init: SdkErrorInit);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
declare class SdkInputError extends SdkError {
|
|
94
|
+
readonly problems: SdkProblem[];
|
|
95
|
+
constructor(init: SdkErrorInit);
|
|
96
|
+
}
|
|
97
|
+
declare class SdkAuthError extends SdkError {
|
|
98
|
+
constructor(init: SdkErrorInit);
|
|
99
|
+
}
|
|
100
|
+
declare class SdkNotFoundError extends SdkError {
|
|
101
|
+
constructor(init: SdkErrorInit);
|
|
102
|
+
}
|
|
103
|
+
declare class SdkReconnectError extends SdkError {
|
|
104
|
+
constructor(init: SdkErrorInit);
|
|
105
|
+
}
|
|
106
|
+
declare class SdkRateLimitError extends SdkError {
|
|
107
|
+
readonly retryAfterSeconds: number | null;
|
|
108
|
+
constructor(init: SdkErrorInit & {
|
|
109
|
+
retryAfterSeconds?: number | null;
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
declare class SdkServerError extends SdkError {
|
|
113
|
+
constructor(init: SdkErrorInit);
|
|
114
|
+
}
|
|
115
|
+
declare class SdkNetworkError extends SdkError {
|
|
116
|
+
constructor(init: {
|
|
117
|
+
message: string;
|
|
118
|
+
cause?: unknown;
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export { CONNECTION_STATUSES, type CallOptions, type ConnectionStatus, type CreateLinkInput, type CreateLinkOutput, type GetConnectionOutput, type PostInput, type PostOutput, type PullInput, type PullOutput, SDK_ERROR_CODES, SDK_OBJECTS, SDK_PLATFORMS, SdkAuthError, type SdkClient, type SdkClientOptions, SdkError, type SdkErrorCode, type SdkErrorCodeValue, type SdkErrorDetails, SdkInputError, SdkNetworkError, SdkNotFoundError, type SdkObject, type SdkPlatform, type SdkProblem, SdkRateLimitError, SdkReconnectError, SdkServerError, createClient };
|