@outseta/n8n-nodes-outseta 0.0.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,1623 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
function __accessProp(key) {
|
|
6
|
+
return this[key];
|
|
7
|
+
}
|
|
8
|
+
var __toCommonJS = (from) => {
|
|
9
|
+
var entry = (__moduleCache ??= new WeakMap).get(from), desc;
|
|
10
|
+
if (entry)
|
|
11
|
+
return entry;
|
|
12
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (var key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(entry, key))
|
|
16
|
+
__defProp(entry, key, {
|
|
17
|
+
get: __accessProp.bind(from, key),
|
|
18
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
__moduleCache.set(from, entry);
|
|
22
|
+
return entry;
|
|
23
|
+
};
|
|
24
|
+
var __moduleCache;
|
|
25
|
+
var __returnValue = (v) => v;
|
|
26
|
+
function __exportSetter(name, newValue) {
|
|
27
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
28
|
+
}
|
|
29
|
+
var __export = (target, all) => {
|
|
30
|
+
for (var name in all)
|
|
31
|
+
__defProp(target, name, {
|
|
32
|
+
get: all[name],
|
|
33
|
+
enumerable: true,
|
|
34
|
+
configurable: true,
|
|
35
|
+
set: __exportSetter.bind(all, name)
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// src/nodes/Outseta/Outseta.node.ts
|
|
40
|
+
var exports_Outseta_node = {};
|
|
41
|
+
__export(exports_Outseta_node, {
|
|
42
|
+
Outseta: () => Outseta
|
|
43
|
+
});
|
|
44
|
+
module.exports = __toCommonJS(exports_Outseta_node);
|
|
45
|
+
var import_n8n_workflow = require("n8n-workflow");
|
|
46
|
+
|
|
47
|
+
// ../../node_modules/ky/distribution/errors/HTTPError.js
|
|
48
|
+
class HTTPError extends Error {
|
|
49
|
+
response;
|
|
50
|
+
request;
|
|
51
|
+
options;
|
|
52
|
+
constructor(response, request, options) {
|
|
53
|
+
const code = response.status || response.status === 0 ? response.status : "";
|
|
54
|
+
const title = response.statusText ?? "";
|
|
55
|
+
const status = `${code} ${title}`.trim();
|
|
56
|
+
const reason = status ? `status code ${status}` : "an unknown error";
|
|
57
|
+
super(`Request failed with ${reason}: ${request.method} ${request.url}`);
|
|
58
|
+
this.name = "HTTPError";
|
|
59
|
+
this.response = response;
|
|
60
|
+
this.request = request;
|
|
61
|
+
this.options = options;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// ../../node_modules/ky/distribution/errors/NonError.js
|
|
66
|
+
class NonError extends Error {
|
|
67
|
+
name = "NonError";
|
|
68
|
+
value;
|
|
69
|
+
constructor(value) {
|
|
70
|
+
let message = "Non-error value was thrown";
|
|
71
|
+
try {
|
|
72
|
+
if (typeof value === "string") {
|
|
73
|
+
message = value;
|
|
74
|
+
} else if (value && typeof value === "object" && "message" in value && typeof value.message === "string") {
|
|
75
|
+
message = value.message;
|
|
76
|
+
}
|
|
77
|
+
} catch {}
|
|
78
|
+
super(message);
|
|
79
|
+
this.value = value;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// ../../node_modules/ky/distribution/errors/ForceRetryError.js
|
|
84
|
+
class ForceRetryError extends Error {
|
|
85
|
+
name = "ForceRetryError";
|
|
86
|
+
customDelay;
|
|
87
|
+
code;
|
|
88
|
+
customRequest;
|
|
89
|
+
constructor(options) {
|
|
90
|
+
const cause = options?.cause ? options.cause instanceof Error ? options.cause : new NonError(options.cause) : undefined;
|
|
91
|
+
super(options?.code ? `Forced retry: ${options.code}` : "Forced retry", cause ? { cause } : undefined);
|
|
92
|
+
this.customDelay = options?.delay;
|
|
93
|
+
this.code = options?.code;
|
|
94
|
+
this.customRequest = options?.request;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ../../node_modules/ky/distribution/core/constants.js
|
|
99
|
+
var supportsRequestStreams = (() => {
|
|
100
|
+
let duplexAccessed = false;
|
|
101
|
+
let hasContentType = false;
|
|
102
|
+
const supportsReadableStream = typeof globalThis.ReadableStream === "function";
|
|
103
|
+
const supportsRequest = typeof globalThis.Request === "function";
|
|
104
|
+
if (supportsReadableStream && supportsRequest) {
|
|
105
|
+
try {
|
|
106
|
+
hasContentType = new globalThis.Request("https://empty.invalid", {
|
|
107
|
+
body: new globalThis.ReadableStream,
|
|
108
|
+
method: "POST",
|
|
109
|
+
get duplex() {
|
|
110
|
+
duplexAccessed = true;
|
|
111
|
+
return "half";
|
|
112
|
+
}
|
|
113
|
+
}).headers.has("Content-Type");
|
|
114
|
+
} catch (error) {
|
|
115
|
+
if (error instanceof Error && error.message === "unsupported BodyInit type") {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
throw error;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return duplexAccessed && !hasContentType;
|
|
122
|
+
})();
|
|
123
|
+
var supportsAbortController = typeof globalThis.AbortController === "function";
|
|
124
|
+
var supportsAbortSignal = typeof globalThis.AbortSignal === "function" && typeof globalThis.AbortSignal.any === "function";
|
|
125
|
+
var supportsResponseStreams = typeof globalThis.ReadableStream === "function";
|
|
126
|
+
var supportsFormData = typeof globalThis.FormData === "function";
|
|
127
|
+
var requestMethods = ["get", "post", "put", "patch", "head", "delete"];
|
|
128
|
+
var validate = () => {
|
|
129
|
+
return;
|
|
130
|
+
};
|
|
131
|
+
validate();
|
|
132
|
+
var responseTypes = {
|
|
133
|
+
json: "application/json",
|
|
134
|
+
text: "text/*",
|
|
135
|
+
formData: "multipart/form-data",
|
|
136
|
+
arrayBuffer: "*/*",
|
|
137
|
+
blob: "*/*",
|
|
138
|
+
bytes: "*/*"
|
|
139
|
+
};
|
|
140
|
+
var maxSafeTimeout = 2147483647;
|
|
141
|
+
var usualFormBoundarySize = new TextEncoder().encode("------WebKitFormBoundaryaxpyiPgbbPti10Rw").length;
|
|
142
|
+
var stop = Symbol("stop");
|
|
143
|
+
|
|
144
|
+
class RetryMarker {
|
|
145
|
+
options;
|
|
146
|
+
constructor(options) {
|
|
147
|
+
this.options = options;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
var retry = (options) => new RetryMarker(options);
|
|
151
|
+
var kyOptionKeys = {
|
|
152
|
+
json: true,
|
|
153
|
+
parseJson: true,
|
|
154
|
+
stringifyJson: true,
|
|
155
|
+
searchParams: true,
|
|
156
|
+
prefixUrl: true,
|
|
157
|
+
retry: true,
|
|
158
|
+
timeout: true,
|
|
159
|
+
hooks: true,
|
|
160
|
+
throwHttpErrors: true,
|
|
161
|
+
onDownloadProgress: true,
|
|
162
|
+
onUploadProgress: true,
|
|
163
|
+
fetch: true,
|
|
164
|
+
context: true
|
|
165
|
+
};
|
|
166
|
+
var vendorSpecificOptions = {
|
|
167
|
+
next: true
|
|
168
|
+
};
|
|
169
|
+
var requestOptionsRegistry = {
|
|
170
|
+
method: true,
|
|
171
|
+
headers: true,
|
|
172
|
+
body: true,
|
|
173
|
+
mode: true,
|
|
174
|
+
credentials: true,
|
|
175
|
+
cache: true,
|
|
176
|
+
redirect: true,
|
|
177
|
+
referrer: true,
|
|
178
|
+
referrerPolicy: true,
|
|
179
|
+
integrity: true,
|
|
180
|
+
keepalive: true,
|
|
181
|
+
signal: true,
|
|
182
|
+
window: true,
|
|
183
|
+
duplex: true
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
// ../../node_modules/ky/distribution/utils/body.js
|
|
187
|
+
var getBodySize = (body) => {
|
|
188
|
+
if (!body) {
|
|
189
|
+
return 0;
|
|
190
|
+
}
|
|
191
|
+
if (body instanceof FormData) {
|
|
192
|
+
let size = 0;
|
|
193
|
+
for (const [key, value] of body) {
|
|
194
|
+
size += usualFormBoundarySize;
|
|
195
|
+
size += new TextEncoder().encode(`Content-Disposition: form-data; name="${key}"`).length;
|
|
196
|
+
size += typeof value === "string" ? new TextEncoder().encode(value).length : value.size;
|
|
197
|
+
}
|
|
198
|
+
return size;
|
|
199
|
+
}
|
|
200
|
+
if (body instanceof Blob) {
|
|
201
|
+
return body.size;
|
|
202
|
+
}
|
|
203
|
+
if (body instanceof ArrayBuffer) {
|
|
204
|
+
return body.byteLength;
|
|
205
|
+
}
|
|
206
|
+
if (typeof body === "string") {
|
|
207
|
+
return new TextEncoder().encode(body).length;
|
|
208
|
+
}
|
|
209
|
+
if (body instanceof URLSearchParams) {
|
|
210
|
+
return new TextEncoder().encode(body.toString()).length;
|
|
211
|
+
}
|
|
212
|
+
if ("byteLength" in body) {
|
|
213
|
+
return body.byteLength;
|
|
214
|
+
}
|
|
215
|
+
if (typeof body === "object" && body !== null) {
|
|
216
|
+
try {
|
|
217
|
+
const jsonString = JSON.stringify(body);
|
|
218
|
+
return new TextEncoder().encode(jsonString).length;
|
|
219
|
+
} catch {
|
|
220
|
+
return 0;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return 0;
|
|
224
|
+
};
|
|
225
|
+
var withProgress = (stream, totalBytes, onProgress) => {
|
|
226
|
+
let previousChunk;
|
|
227
|
+
let transferredBytes = 0;
|
|
228
|
+
return stream.pipeThrough(new TransformStream({
|
|
229
|
+
transform(currentChunk, controller) {
|
|
230
|
+
controller.enqueue(currentChunk);
|
|
231
|
+
if (previousChunk) {
|
|
232
|
+
transferredBytes += previousChunk.byteLength;
|
|
233
|
+
let percent = totalBytes === 0 ? 0 : transferredBytes / totalBytes;
|
|
234
|
+
if (percent >= 1) {
|
|
235
|
+
percent = 1 - Number.EPSILON;
|
|
236
|
+
}
|
|
237
|
+
onProgress?.({ percent, totalBytes: Math.max(totalBytes, transferredBytes), transferredBytes }, previousChunk);
|
|
238
|
+
}
|
|
239
|
+
previousChunk = currentChunk;
|
|
240
|
+
},
|
|
241
|
+
flush() {
|
|
242
|
+
if (previousChunk) {
|
|
243
|
+
transferredBytes += previousChunk.byteLength;
|
|
244
|
+
onProgress?.({ percent: 1, totalBytes: Math.max(totalBytes, transferredBytes), transferredBytes }, previousChunk);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}));
|
|
248
|
+
};
|
|
249
|
+
var streamResponse = (response, onDownloadProgress) => {
|
|
250
|
+
if (!response.body) {
|
|
251
|
+
return response;
|
|
252
|
+
}
|
|
253
|
+
if (response.status === 204) {
|
|
254
|
+
return new Response(null, {
|
|
255
|
+
status: response.status,
|
|
256
|
+
statusText: response.statusText,
|
|
257
|
+
headers: response.headers
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
const totalBytes = Math.max(0, Number(response.headers.get("content-length")) || 0);
|
|
261
|
+
return new Response(withProgress(response.body, totalBytes, onDownloadProgress), {
|
|
262
|
+
status: response.status,
|
|
263
|
+
statusText: response.statusText,
|
|
264
|
+
headers: response.headers
|
|
265
|
+
});
|
|
266
|
+
};
|
|
267
|
+
var streamRequest = (request, onUploadProgress, originalBody) => {
|
|
268
|
+
if (!request.body) {
|
|
269
|
+
return request;
|
|
270
|
+
}
|
|
271
|
+
const totalBytes = getBodySize(originalBody ?? request.body);
|
|
272
|
+
return new Request(request, {
|
|
273
|
+
duplex: "half",
|
|
274
|
+
body: withProgress(request.body, totalBytes, onUploadProgress)
|
|
275
|
+
});
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
// ../../node_modules/ky/distribution/utils/is.js
|
|
279
|
+
var isObject = (value) => value !== null && typeof value === "object";
|
|
280
|
+
|
|
281
|
+
// ../../node_modules/ky/distribution/utils/merge.js
|
|
282
|
+
var validateAndMerge = (...sources) => {
|
|
283
|
+
for (const source of sources) {
|
|
284
|
+
if ((!isObject(source) || Array.isArray(source)) && source !== undefined) {
|
|
285
|
+
throw new TypeError("The `options` argument must be an object");
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return deepMerge({}, ...sources);
|
|
289
|
+
};
|
|
290
|
+
var mergeHeaders = (source1 = {}, source2 = {}) => {
|
|
291
|
+
const result = new globalThis.Headers(source1);
|
|
292
|
+
const isHeadersInstance = source2 instanceof globalThis.Headers;
|
|
293
|
+
const source = new globalThis.Headers(source2);
|
|
294
|
+
for (const [key, value] of source.entries()) {
|
|
295
|
+
if (isHeadersInstance && value === "undefined" || value === undefined) {
|
|
296
|
+
result.delete(key);
|
|
297
|
+
} else {
|
|
298
|
+
result.set(key, value);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
return result;
|
|
302
|
+
};
|
|
303
|
+
function newHookValue(original, incoming, property) {
|
|
304
|
+
return Object.hasOwn(incoming, property) && incoming[property] === undefined ? [] : deepMerge(original[property] ?? [], incoming[property] ?? []);
|
|
305
|
+
}
|
|
306
|
+
var mergeHooks = (original = {}, incoming = {}) => ({
|
|
307
|
+
beforeRequest: newHookValue(original, incoming, "beforeRequest"),
|
|
308
|
+
beforeRetry: newHookValue(original, incoming, "beforeRetry"),
|
|
309
|
+
afterResponse: newHookValue(original, incoming, "afterResponse"),
|
|
310
|
+
beforeError: newHookValue(original, incoming, "beforeError")
|
|
311
|
+
});
|
|
312
|
+
var appendSearchParameters = (target, source) => {
|
|
313
|
+
const result = new URLSearchParams;
|
|
314
|
+
for (const input of [target, source]) {
|
|
315
|
+
if (input === undefined) {
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
if (input instanceof URLSearchParams) {
|
|
319
|
+
for (const [key, value] of input.entries()) {
|
|
320
|
+
result.append(key, value);
|
|
321
|
+
}
|
|
322
|
+
} else if (Array.isArray(input)) {
|
|
323
|
+
for (const pair of input) {
|
|
324
|
+
if (!Array.isArray(pair) || pair.length !== 2) {
|
|
325
|
+
throw new TypeError("Array search parameters must be provided in [[key, value], ...] format");
|
|
326
|
+
}
|
|
327
|
+
result.append(String(pair[0]), String(pair[1]));
|
|
328
|
+
}
|
|
329
|
+
} else if (isObject(input)) {
|
|
330
|
+
for (const [key, value] of Object.entries(input)) {
|
|
331
|
+
if (value !== undefined) {
|
|
332
|
+
result.append(key, String(value));
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
} else {
|
|
336
|
+
const parameters = new URLSearchParams(input);
|
|
337
|
+
for (const [key, value] of parameters.entries()) {
|
|
338
|
+
result.append(key, value);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
return result;
|
|
343
|
+
};
|
|
344
|
+
var deepMerge = (...sources) => {
|
|
345
|
+
let returnValue = {};
|
|
346
|
+
let headers = {};
|
|
347
|
+
let hooks = {};
|
|
348
|
+
let searchParameters;
|
|
349
|
+
const signals = [];
|
|
350
|
+
for (const source of sources) {
|
|
351
|
+
if (Array.isArray(source)) {
|
|
352
|
+
if (!Array.isArray(returnValue)) {
|
|
353
|
+
returnValue = [];
|
|
354
|
+
}
|
|
355
|
+
returnValue = [...returnValue, ...source];
|
|
356
|
+
} else if (isObject(source)) {
|
|
357
|
+
for (let [key, value] of Object.entries(source)) {
|
|
358
|
+
if (key === "signal" && value instanceof globalThis.AbortSignal) {
|
|
359
|
+
signals.push(value);
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
if (key === "context") {
|
|
363
|
+
if (value !== undefined && value !== null && (!isObject(value) || Array.isArray(value))) {
|
|
364
|
+
throw new TypeError("The `context` option must be an object");
|
|
365
|
+
}
|
|
366
|
+
returnValue = {
|
|
367
|
+
...returnValue,
|
|
368
|
+
context: value === undefined || value === null ? {} : { ...returnValue.context, ...value }
|
|
369
|
+
};
|
|
370
|
+
continue;
|
|
371
|
+
}
|
|
372
|
+
if (key === "searchParams") {
|
|
373
|
+
if (value === undefined || value === null) {
|
|
374
|
+
searchParameters = undefined;
|
|
375
|
+
} else {
|
|
376
|
+
searchParameters = searchParameters === undefined ? value : appendSearchParameters(searchParameters, value);
|
|
377
|
+
}
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
if (isObject(value) && key in returnValue) {
|
|
381
|
+
value = deepMerge(returnValue[key], value);
|
|
382
|
+
}
|
|
383
|
+
returnValue = { ...returnValue, [key]: value };
|
|
384
|
+
}
|
|
385
|
+
if (isObject(source.hooks)) {
|
|
386
|
+
hooks = mergeHooks(hooks, source.hooks);
|
|
387
|
+
returnValue.hooks = hooks;
|
|
388
|
+
}
|
|
389
|
+
if (isObject(source.headers)) {
|
|
390
|
+
headers = mergeHeaders(headers, source.headers);
|
|
391
|
+
returnValue.headers = headers;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
if (searchParameters !== undefined) {
|
|
396
|
+
returnValue.searchParams = searchParameters;
|
|
397
|
+
}
|
|
398
|
+
if (signals.length > 0) {
|
|
399
|
+
if (signals.length === 1) {
|
|
400
|
+
returnValue.signal = signals[0];
|
|
401
|
+
} else if (supportsAbortSignal) {
|
|
402
|
+
returnValue.signal = AbortSignal.any(signals);
|
|
403
|
+
} else {
|
|
404
|
+
returnValue.signal = signals.at(-1);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
return returnValue;
|
|
408
|
+
};
|
|
409
|
+
|
|
410
|
+
// ../../node_modules/ky/distribution/utils/normalize.js
|
|
411
|
+
var normalizeRequestMethod = (input) => requestMethods.includes(input) ? input.toUpperCase() : input;
|
|
412
|
+
var retryMethods = ["get", "put", "head", "delete", "options", "trace"];
|
|
413
|
+
var retryStatusCodes = [408, 413, 429, 500, 502, 503, 504];
|
|
414
|
+
var retryAfterStatusCodes = [413, 429, 503];
|
|
415
|
+
var defaultRetryOptions = {
|
|
416
|
+
limit: 2,
|
|
417
|
+
methods: retryMethods,
|
|
418
|
+
statusCodes: retryStatusCodes,
|
|
419
|
+
afterStatusCodes: retryAfterStatusCodes,
|
|
420
|
+
maxRetryAfter: Number.POSITIVE_INFINITY,
|
|
421
|
+
backoffLimit: Number.POSITIVE_INFINITY,
|
|
422
|
+
delay: (attemptCount) => 0.3 * 2 ** (attemptCount - 1) * 1000,
|
|
423
|
+
jitter: undefined,
|
|
424
|
+
retryOnTimeout: false
|
|
425
|
+
};
|
|
426
|
+
var normalizeRetryOptions = (retry2 = {}) => {
|
|
427
|
+
if (typeof retry2 === "number") {
|
|
428
|
+
return {
|
|
429
|
+
...defaultRetryOptions,
|
|
430
|
+
limit: retry2
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
if (retry2.methods && !Array.isArray(retry2.methods)) {
|
|
434
|
+
throw new Error("retry.methods must be an array");
|
|
435
|
+
}
|
|
436
|
+
retry2.methods &&= retry2.methods.map((method) => method.toLowerCase());
|
|
437
|
+
if (retry2.statusCodes && !Array.isArray(retry2.statusCodes)) {
|
|
438
|
+
throw new Error("retry.statusCodes must be an array");
|
|
439
|
+
}
|
|
440
|
+
const normalizedRetry = Object.fromEntries(Object.entries(retry2).filter(([, value]) => value !== undefined));
|
|
441
|
+
return {
|
|
442
|
+
...defaultRetryOptions,
|
|
443
|
+
...normalizedRetry
|
|
444
|
+
};
|
|
445
|
+
};
|
|
446
|
+
|
|
447
|
+
// ../../node_modules/ky/distribution/errors/TimeoutError.js
|
|
448
|
+
class TimeoutError extends Error {
|
|
449
|
+
request;
|
|
450
|
+
constructor(request) {
|
|
451
|
+
super(`Request timed out: ${request.method} ${request.url}`);
|
|
452
|
+
this.name = "TimeoutError";
|
|
453
|
+
this.request = request;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// ../../node_modules/ky/distribution/utils/timeout.js
|
|
458
|
+
async function timeout(request, init, abortController, options) {
|
|
459
|
+
return new Promise((resolve, reject) => {
|
|
460
|
+
const timeoutId = setTimeout(() => {
|
|
461
|
+
if (abortController) {
|
|
462
|
+
abortController.abort();
|
|
463
|
+
}
|
|
464
|
+
reject(new TimeoutError(request));
|
|
465
|
+
}, options.timeout);
|
|
466
|
+
options.fetch(request, init).then(resolve).catch(reject).then(() => {
|
|
467
|
+
clearTimeout(timeoutId);
|
|
468
|
+
});
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// ../../node_modules/ky/distribution/utils/delay.js
|
|
473
|
+
async function delay(ms, { signal }) {
|
|
474
|
+
return new Promise((resolve, reject) => {
|
|
475
|
+
if (signal) {
|
|
476
|
+
signal.throwIfAborted();
|
|
477
|
+
signal.addEventListener("abort", abortHandler, { once: true });
|
|
478
|
+
}
|
|
479
|
+
function abortHandler() {
|
|
480
|
+
clearTimeout(timeoutId);
|
|
481
|
+
reject(signal.reason);
|
|
482
|
+
}
|
|
483
|
+
const timeoutId = setTimeout(() => {
|
|
484
|
+
signal?.removeEventListener("abort", abortHandler);
|
|
485
|
+
resolve();
|
|
486
|
+
}, ms);
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
// ../../node_modules/ky/distribution/utils/options.js
|
|
491
|
+
var findUnknownOptions = (request, options) => {
|
|
492
|
+
const unknownOptions = {};
|
|
493
|
+
for (const key in options) {
|
|
494
|
+
if (!Object.hasOwn(options, key)) {
|
|
495
|
+
continue;
|
|
496
|
+
}
|
|
497
|
+
if (!(key in requestOptionsRegistry) && !(key in kyOptionKeys) && (!(key in request) || (key in vendorSpecificOptions))) {
|
|
498
|
+
unknownOptions[key] = options[key];
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
return unknownOptions;
|
|
502
|
+
};
|
|
503
|
+
var hasSearchParameters = (search) => {
|
|
504
|
+
if (search === undefined) {
|
|
505
|
+
return false;
|
|
506
|
+
}
|
|
507
|
+
if (Array.isArray(search)) {
|
|
508
|
+
return search.length > 0;
|
|
509
|
+
}
|
|
510
|
+
if (search instanceof URLSearchParams) {
|
|
511
|
+
return search.size > 0;
|
|
512
|
+
}
|
|
513
|
+
if (typeof search === "object") {
|
|
514
|
+
return Object.keys(search).length > 0;
|
|
515
|
+
}
|
|
516
|
+
if (typeof search === "string") {
|
|
517
|
+
return search.trim().length > 0;
|
|
518
|
+
}
|
|
519
|
+
return Boolean(search);
|
|
520
|
+
};
|
|
521
|
+
|
|
522
|
+
// ../../node_modules/ky/distribution/utils/type-guards.js
|
|
523
|
+
function isHTTPError(error) {
|
|
524
|
+
return error instanceof HTTPError || error?.name === HTTPError.name;
|
|
525
|
+
}
|
|
526
|
+
function isTimeoutError(error) {
|
|
527
|
+
return error instanceof TimeoutError || error?.name === TimeoutError.name;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
// ../../node_modules/ky/distribution/core/Ky.js
|
|
531
|
+
class Ky {
|
|
532
|
+
static create(input, options) {
|
|
533
|
+
const ky = new Ky(input, options);
|
|
534
|
+
const function_ = async () => {
|
|
535
|
+
if (typeof ky.#options.timeout === "number" && ky.#options.timeout > maxSafeTimeout) {
|
|
536
|
+
throw new RangeError(`The \`timeout\` option cannot be greater than ${maxSafeTimeout}`);
|
|
537
|
+
}
|
|
538
|
+
await Promise.resolve();
|
|
539
|
+
let response = await ky.#fetch();
|
|
540
|
+
for (const hook of ky.#options.hooks.afterResponse) {
|
|
541
|
+
const clonedResponse = ky.#decorateResponse(response.clone());
|
|
542
|
+
let modifiedResponse;
|
|
543
|
+
try {
|
|
544
|
+
modifiedResponse = await hook(ky.request, ky.#getNormalizedOptions(), clonedResponse, { retryCount: ky.#retryCount });
|
|
545
|
+
} catch (error) {
|
|
546
|
+
ky.#cancelResponseBody(clonedResponse);
|
|
547
|
+
ky.#cancelResponseBody(response);
|
|
548
|
+
throw error;
|
|
549
|
+
}
|
|
550
|
+
if (modifiedResponse instanceof RetryMarker) {
|
|
551
|
+
ky.#cancelResponseBody(clonedResponse);
|
|
552
|
+
ky.#cancelResponseBody(response);
|
|
553
|
+
throw new ForceRetryError(modifiedResponse.options);
|
|
554
|
+
}
|
|
555
|
+
const nextResponse = modifiedResponse instanceof globalThis.Response ? modifiedResponse : response;
|
|
556
|
+
if (clonedResponse !== nextResponse) {
|
|
557
|
+
ky.#cancelResponseBody(clonedResponse);
|
|
558
|
+
}
|
|
559
|
+
if (response !== nextResponse) {
|
|
560
|
+
ky.#cancelResponseBody(response);
|
|
561
|
+
}
|
|
562
|
+
response = nextResponse;
|
|
563
|
+
}
|
|
564
|
+
ky.#decorateResponse(response);
|
|
565
|
+
if (!response.ok && (typeof ky.#options.throwHttpErrors === "function" ? ky.#options.throwHttpErrors(response.status) : ky.#options.throwHttpErrors)) {
|
|
566
|
+
let error = new HTTPError(response, ky.request, ky.#getNormalizedOptions());
|
|
567
|
+
for (const hook of ky.#options.hooks.beforeError) {
|
|
568
|
+
error = await hook(error, { retryCount: ky.#retryCount });
|
|
569
|
+
}
|
|
570
|
+
throw error;
|
|
571
|
+
}
|
|
572
|
+
if (ky.#options.onDownloadProgress) {
|
|
573
|
+
if (typeof ky.#options.onDownloadProgress !== "function") {
|
|
574
|
+
throw new TypeError("The `onDownloadProgress` option must be a function");
|
|
575
|
+
}
|
|
576
|
+
if (!supportsResponseStreams) {
|
|
577
|
+
throw new Error("Streams are not supported in your environment. `ReadableStream` is missing.");
|
|
578
|
+
}
|
|
579
|
+
const progressResponse = response.clone();
|
|
580
|
+
ky.#cancelResponseBody(response);
|
|
581
|
+
return streamResponse(progressResponse, ky.#options.onDownloadProgress);
|
|
582
|
+
}
|
|
583
|
+
return response;
|
|
584
|
+
};
|
|
585
|
+
const result = ky.#retry(function_).finally(() => {
|
|
586
|
+
const originalRequest = ky.#originalRequest;
|
|
587
|
+
ky.#cancelBody(originalRequest?.body ?? undefined);
|
|
588
|
+
ky.#cancelBody(ky.request.body ?? undefined);
|
|
589
|
+
});
|
|
590
|
+
for (const [type, mimeType] of Object.entries(responseTypes)) {
|
|
591
|
+
if (type === "bytes" && typeof globalThis.Response?.prototype?.bytes !== "function") {
|
|
592
|
+
continue;
|
|
593
|
+
}
|
|
594
|
+
result[type] = async () => {
|
|
595
|
+
ky.request.headers.set("accept", ky.request.headers.get("accept") || mimeType);
|
|
596
|
+
const response = await result;
|
|
597
|
+
if (type === "json") {
|
|
598
|
+
if (response.status === 204) {
|
|
599
|
+
return "";
|
|
600
|
+
}
|
|
601
|
+
const text = await response.text();
|
|
602
|
+
if (text === "") {
|
|
603
|
+
return "";
|
|
604
|
+
}
|
|
605
|
+
if (options.parseJson) {
|
|
606
|
+
return options.parseJson(text);
|
|
607
|
+
}
|
|
608
|
+
return JSON.parse(text);
|
|
609
|
+
}
|
|
610
|
+
return response[type]();
|
|
611
|
+
};
|
|
612
|
+
}
|
|
613
|
+
return result;
|
|
614
|
+
}
|
|
615
|
+
static #normalizeSearchParams(searchParams) {
|
|
616
|
+
if (searchParams && typeof searchParams === "object" && !Array.isArray(searchParams) && !(searchParams instanceof URLSearchParams)) {
|
|
617
|
+
return Object.fromEntries(Object.entries(searchParams).filter(([, value]) => value !== undefined));
|
|
618
|
+
}
|
|
619
|
+
return searchParams;
|
|
620
|
+
}
|
|
621
|
+
request;
|
|
622
|
+
#abortController;
|
|
623
|
+
#retryCount = 0;
|
|
624
|
+
#input;
|
|
625
|
+
#options;
|
|
626
|
+
#originalRequest;
|
|
627
|
+
#userProvidedAbortSignal;
|
|
628
|
+
#cachedNormalizedOptions;
|
|
629
|
+
constructor(input, options = {}) {
|
|
630
|
+
this.#input = input;
|
|
631
|
+
this.#options = {
|
|
632
|
+
...options,
|
|
633
|
+
headers: mergeHeaders(this.#input.headers, options.headers),
|
|
634
|
+
hooks: mergeHooks({
|
|
635
|
+
beforeRequest: [],
|
|
636
|
+
beforeRetry: [],
|
|
637
|
+
beforeError: [],
|
|
638
|
+
afterResponse: []
|
|
639
|
+
}, options.hooks),
|
|
640
|
+
method: normalizeRequestMethod(options.method ?? this.#input.method ?? "GET"),
|
|
641
|
+
prefixUrl: String(options.prefixUrl || ""),
|
|
642
|
+
retry: normalizeRetryOptions(options.retry),
|
|
643
|
+
throwHttpErrors: options.throwHttpErrors ?? true,
|
|
644
|
+
timeout: options.timeout ?? 1e4,
|
|
645
|
+
fetch: options.fetch ?? globalThis.fetch.bind(globalThis),
|
|
646
|
+
context: options.context ?? {}
|
|
647
|
+
};
|
|
648
|
+
if (typeof this.#input !== "string" && !(this.#input instanceof URL || this.#input instanceof globalThis.Request)) {
|
|
649
|
+
throw new TypeError("`input` must be a string, URL, or Request");
|
|
650
|
+
}
|
|
651
|
+
if (this.#options.prefixUrl && typeof this.#input === "string") {
|
|
652
|
+
if (this.#input.startsWith("/")) {
|
|
653
|
+
throw new Error("`input` must not begin with a slash when using `prefixUrl`");
|
|
654
|
+
}
|
|
655
|
+
if (!this.#options.prefixUrl.endsWith("/")) {
|
|
656
|
+
this.#options.prefixUrl += "/";
|
|
657
|
+
}
|
|
658
|
+
this.#input = this.#options.prefixUrl + this.#input;
|
|
659
|
+
}
|
|
660
|
+
if (supportsAbortController && supportsAbortSignal) {
|
|
661
|
+
this.#userProvidedAbortSignal = this.#options.signal ?? this.#input.signal;
|
|
662
|
+
this.#abortController = new globalThis.AbortController;
|
|
663
|
+
this.#options.signal = this.#userProvidedAbortSignal ? AbortSignal.any([this.#userProvidedAbortSignal, this.#abortController.signal]) : this.#abortController.signal;
|
|
664
|
+
}
|
|
665
|
+
if (supportsRequestStreams) {
|
|
666
|
+
this.#options.duplex = "half";
|
|
667
|
+
}
|
|
668
|
+
if (this.#options.json !== undefined) {
|
|
669
|
+
this.#options.body = this.#options.stringifyJson?.(this.#options.json) ?? JSON.stringify(this.#options.json);
|
|
670
|
+
this.#options.headers.set("content-type", this.#options.headers.get("content-type") ?? "application/json");
|
|
671
|
+
}
|
|
672
|
+
const userProvidedContentType = options.headers && new globalThis.Headers(options.headers).has("content-type");
|
|
673
|
+
if (this.#input instanceof globalThis.Request && (supportsFormData && this.#options.body instanceof globalThis.FormData || this.#options.body instanceof URLSearchParams) && !userProvidedContentType) {
|
|
674
|
+
this.#options.headers.delete("content-type");
|
|
675
|
+
}
|
|
676
|
+
this.request = new globalThis.Request(this.#input, this.#options);
|
|
677
|
+
if (hasSearchParameters(this.#options.searchParams)) {
|
|
678
|
+
const textSearchParams = typeof this.#options.searchParams === "string" ? this.#options.searchParams.replace(/^\?/, "") : new URLSearchParams(Ky.#normalizeSearchParams(this.#options.searchParams)).toString();
|
|
679
|
+
const searchParams = "?" + textSearchParams;
|
|
680
|
+
const url = this.request.url.replace(/(?:\?.*?)?(?=#|$)/, searchParams);
|
|
681
|
+
this.request = new globalThis.Request(url, this.#options);
|
|
682
|
+
}
|
|
683
|
+
if (this.#options.onUploadProgress) {
|
|
684
|
+
if (typeof this.#options.onUploadProgress !== "function") {
|
|
685
|
+
throw new TypeError("The `onUploadProgress` option must be a function");
|
|
686
|
+
}
|
|
687
|
+
if (!supportsRequestStreams) {
|
|
688
|
+
throw new Error("Request streams are not supported in your environment. The `duplex` option for `Request` is not available.");
|
|
689
|
+
}
|
|
690
|
+
this.request = this.#wrapRequestWithUploadProgress(this.request, this.#options.body ?? undefined);
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
#calculateDelay() {
|
|
694
|
+
const retryDelay = this.#options.retry.delay(this.#retryCount);
|
|
695
|
+
let jitteredDelay = retryDelay;
|
|
696
|
+
if (this.#options.retry.jitter === true) {
|
|
697
|
+
jitteredDelay = Math.random() * retryDelay;
|
|
698
|
+
} else if (typeof this.#options.retry.jitter === "function") {
|
|
699
|
+
jitteredDelay = this.#options.retry.jitter(retryDelay);
|
|
700
|
+
if (!Number.isFinite(jitteredDelay) || jitteredDelay < 0) {
|
|
701
|
+
jitteredDelay = retryDelay;
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
const backoffLimit = this.#options.retry.backoffLimit ?? Number.POSITIVE_INFINITY;
|
|
705
|
+
return Math.min(backoffLimit, jitteredDelay);
|
|
706
|
+
}
|
|
707
|
+
async#calculateRetryDelay(error) {
|
|
708
|
+
this.#retryCount++;
|
|
709
|
+
if (this.#retryCount > this.#options.retry.limit) {
|
|
710
|
+
throw error;
|
|
711
|
+
}
|
|
712
|
+
const errorObject = error instanceof Error ? error : new NonError(error);
|
|
713
|
+
if (errorObject instanceof ForceRetryError) {
|
|
714
|
+
return errorObject.customDelay ?? this.#calculateDelay();
|
|
715
|
+
}
|
|
716
|
+
if (!this.#options.retry.methods.includes(this.request.method.toLowerCase())) {
|
|
717
|
+
throw error;
|
|
718
|
+
}
|
|
719
|
+
if (this.#options.retry.shouldRetry !== undefined) {
|
|
720
|
+
const result = await this.#options.retry.shouldRetry({ error: errorObject, retryCount: this.#retryCount });
|
|
721
|
+
if (result === false) {
|
|
722
|
+
throw error;
|
|
723
|
+
}
|
|
724
|
+
if (result === true) {
|
|
725
|
+
return this.#calculateDelay();
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
if (isTimeoutError(error) && !this.#options.retry.retryOnTimeout) {
|
|
729
|
+
throw error;
|
|
730
|
+
}
|
|
731
|
+
if (isHTTPError(error)) {
|
|
732
|
+
if (!this.#options.retry.statusCodes.includes(error.response.status)) {
|
|
733
|
+
throw error;
|
|
734
|
+
}
|
|
735
|
+
const retryAfter = error.response.headers.get("Retry-After") ?? error.response.headers.get("RateLimit-Reset") ?? error.response.headers.get("X-RateLimit-Retry-After") ?? error.response.headers.get("X-RateLimit-Reset") ?? error.response.headers.get("X-Rate-Limit-Reset");
|
|
736
|
+
if (retryAfter && this.#options.retry.afterStatusCodes.includes(error.response.status)) {
|
|
737
|
+
let after = Number(retryAfter) * 1000;
|
|
738
|
+
if (Number.isNaN(after)) {
|
|
739
|
+
after = Date.parse(retryAfter) - Date.now();
|
|
740
|
+
} else if (after >= Date.parse("2024-01-01")) {
|
|
741
|
+
after -= Date.now();
|
|
742
|
+
}
|
|
743
|
+
const max = this.#options.retry.maxRetryAfter ?? after;
|
|
744
|
+
return after < max ? after : max;
|
|
745
|
+
}
|
|
746
|
+
if (error.response.status === 413) {
|
|
747
|
+
throw error;
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
return this.#calculateDelay();
|
|
751
|
+
}
|
|
752
|
+
#decorateResponse(response) {
|
|
753
|
+
if (this.#options.parseJson) {
|
|
754
|
+
response.json = async () => this.#options.parseJson(await response.text());
|
|
755
|
+
}
|
|
756
|
+
return response;
|
|
757
|
+
}
|
|
758
|
+
#cancelBody(body) {
|
|
759
|
+
if (!body) {
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
762
|
+
body.cancel().catch(() => {
|
|
763
|
+
return;
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
#cancelResponseBody(response) {
|
|
767
|
+
this.#cancelBody(response.body ?? undefined);
|
|
768
|
+
}
|
|
769
|
+
async#retry(function_) {
|
|
770
|
+
try {
|
|
771
|
+
return await function_();
|
|
772
|
+
} catch (error) {
|
|
773
|
+
const ms = Math.min(await this.#calculateRetryDelay(error), maxSafeTimeout);
|
|
774
|
+
if (this.#retryCount < 1) {
|
|
775
|
+
throw error;
|
|
776
|
+
}
|
|
777
|
+
await delay(ms, this.#userProvidedAbortSignal ? { signal: this.#userProvidedAbortSignal } : {});
|
|
778
|
+
if (error instanceof ForceRetryError && error.customRequest) {
|
|
779
|
+
const managedRequest = this.#options.signal ? new globalThis.Request(error.customRequest, { signal: this.#options.signal }) : new globalThis.Request(error.customRequest);
|
|
780
|
+
this.#assignRequest(managedRequest);
|
|
781
|
+
}
|
|
782
|
+
for (const hook of this.#options.hooks.beforeRetry) {
|
|
783
|
+
const hookResult = await hook({
|
|
784
|
+
request: this.request,
|
|
785
|
+
options: this.#getNormalizedOptions(),
|
|
786
|
+
error,
|
|
787
|
+
retryCount: this.#retryCount
|
|
788
|
+
});
|
|
789
|
+
if (hookResult instanceof globalThis.Request) {
|
|
790
|
+
this.#assignRequest(hookResult);
|
|
791
|
+
break;
|
|
792
|
+
}
|
|
793
|
+
if (hookResult instanceof globalThis.Response) {
|
|
794
|
+
return hookResult;
|
|
795
|
+
}
|
|
796
|
+
if (hookResult === stop) {
|
|
797
|
+
return;
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
return this.#retry(function_);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
async#fetch() {
|
|
804
|
+
if (this.#abortController?.signal.aborted) {
|
|
805
|
+
this.#abortController = new globalThis.AbortController;
|
|
806
|
+
this.#options.signal = this.#userProvidedAbortSignal ? AbortSignal.any([this.#userProvidedAbortSignal, this.#abortController.signal]) : this.#abortController.signal;
|
|
807
|
+
this.request = new globalThis.Request(this.request, { signal: this.#options.signal });
|
|
808
|
+
}
|
|
809
|
+
for (const hook of this.#options.hooks.beforeRequest) {
|
|
810
|
+
const result = await hook(this.request, this.#getNormalizedOptions(), { retryCount: this.#retryCount });
|
|
811
|
+
if (result instanceof Response) {
|
|
812
|
+
return result;
|
|
813
|
+
}
|
|
814
|
+
if (result instanceof globalThis.Request) {
|
|
815
|
+
this.#assignRequest(result);
|
|
816
|
+
break;
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
const nonRequestOptions = findUnknownOptions(this.request, this.#options);
|
|
820
|
+
this.#originalRequest = this.request;
|
|
821
|
+
this.request = this.#originalRequest.clone();
|
|
822
|
+
if (this.#options.timeout === false) {
|
|
823
|
+
return this.#options.fetch(this.#originalRequest, nonRequestOptions);
|
|
824
|
+
}
|
|
825
|
+
return timeout(this.#originalRequest, nonRequestOptions, this.#abortController, this.#options);
|
|
826
|
+
}
|
|
827
|
+
#getNormalizedOptions() {
|
|
828
|
+
if (!this.#cachedNormalizedOptions) {
|
|
829
|
+
const { hooks, ...normalizedOptions } = this.#options;
|
|
830
|
+
this.#cachedNormalizedOptions = Object.freeze(normalizedOptions);
|
|
831
|
+
}
|
|
832
|
+
return this.#cachedNormalizedOptions;
|
|
833
|
+
}
|
|
834
|
+
#assignRequest(request) {
|
|
835
|
+
this.#cachedNormalizedOptions = undefined;
|
|
836
|
+
this.request = this.#wrapRequestWithUploadProgress(request);
|
|
837
|
+
}
|
|
838
|
+
#wrapRequestWithUploadProgress(request, originalBody) {
|
|
839
|
+
if (!this.#options.onUploadProgress || !request.body) {
|
|
840
|
+
return request;
|
|
841
|
+
}
|
|
842
|
+
return streamRequest(request, this.#options.onUploadProgress, originalBody ?? this.#options.body ?? undefined);
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
// ../../node_modules/ky/distribution/index.js
|
|
847
|
+
/*! MIT License © Sindre Sorhus */
|
|
848
|
+
var createInstance = (defaults) => {
|
|
849
|
+
const ky = (input, options) => Ky.create(input, validateAndMerge(defaults, options));
|
|
850
|
+
for (const method of requestMethods) {
|
|
851
|
+
ky[method] = (input, options) => Ky.create(input, validateAndMerge(defaults, options, { method }));
|
|
852
|
+
}
|
|
853
|
+
ky.create = (newDefaults) => createInstance(validateAndMerge(newDefaults));
|
|
854
|
+
ky.extend = (newDefaults) => {
|
|
855
|
+
if (typeof newDefaults === "function") {
|
|
856
|
+
newDefaults = newDefaults(defaults ?? {});
|
|
857
|
+
}
|
|
858
|
+
return createInstance(validateAndMerge(defaults, newDefaults));
|
|
859
|
+
};
|
|
860
|
+
ky.stop = stop;
|
|
861
|
+
ky.retry = retry;
|
|
862
|
+
return ky;
|
|
863
|
+
};
|
|
864
|
+
var ky = createInstance();
|
|
865
|
+
var distribution_default = ky;
|
|
866
|
+
|
|
867
|
+
// ../api-client/dist/index.js
|
|
868
|
+
function createClient(creds) {
|
|
869
|
+
return distribution_default.create({
|
|
870
|
+
prefixUrl: `https://${creds.subdomain}.outseta.com/api/v1/`,
|
|
871
|
+
headers: {
|
|
872
|
+
Authorization: `Outseta ${creds.apiKey}:${creds.apiSecret}`
|
|
873
|
+
},
|
|
874
|
+
retry: { limit: 3, statusCodes: [408, 429, 500, 502, 503, 504] }
|
|
875
|
+
});
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
// src/nodes/Outseta/Outseta.node.ts
|
|
879
|
+
class Outseta {
|
|
880
|
+
description = {
|
|
881
|
+
displayName: "Outseta",
|
|
882
|
+
name: "outseta",
|
|
883
|
+
icon: "file:outseta.svg",
|
|
884
|
+
group: ["transform"],
|
|
885
|
+
version: 1,
|
|
886
|
+
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
|
887
|
+
description: "Interact with the Outseta REST API",
|
|
888
|
+
defaults: {
|
|
889
|
+
name: "Outseta"
|
|
890
|
+
},
|
|
891
|
+
inputs: [import_n8n_workflow.NodeConnectionTypes.Main],
|
|
892
|
+
outputs: [import_n8n_workflow.NodeConnectionTypes.Main],
|
|
893
|
+
credentials: [
|
|
894
|
+
{
|
|
895
|
+
name: "outsetaApi",
|
|
896
|
+
required: true
|
|
897
|
+
}
|
|
898
|
+
],
|
|
899
|
+
properties: [
|
|
900
|
+
{
|
|
901
|
+
displayName: "Resource",
|
|
902
|
+
name: "resource",
|
|
903
|
+
type: "options",
|
|
904
|
+
noDataExpression: true,
|
|
905
|
+
options: [
|
|
906
|
+
{ name: "Account", value: "account" },
|
|
907
|
+
{ name: "Person", value: "person" },
|
|
908
|
+
{ name: "Plan", value: "plan" },
|
|
909
|
+
{ name: "Plan Family", value: "planFamily" },
|
|
910
|
+
{ name: "Subscription", value: "subscription" },
|
|
911
|
+
{ name: "Email List", value: "emailList" }
|
|
912
|
+
],
|
|
913
|
+
default: "account"
|
|
914
|
+
},
|
|
915
|
+
{
|
|
916
|
+
displayName: "Operation",
|
|
917
|
+
name: "operation",
|
|
918
|
+
type: "options",
|
|
919
|
+
noDataExpression: true,
|
|
920
|
+
displayOptions: { show: { resource: ["account"] } },
|
|
921
|
+
options: [
|
|
922
|
+
{ name: "Get Many", value: "getMany", description: "Get many accounts", action: "Get many accounts" },
|
|
923
|
+
{ name: "Register", value: "register", description: "Register a new account (person + account + subscription)", action: "Register an account" },
|
|
924
|
+
{ name: "Add Person", value: "addPerson", description: "Add an existing person to an account", action: "Add person to account" }
|
|
925
|
+
],
|
|
926
|
+
default: "getMany"
|
|
927
|
+
},
|
|
928
|
+
{
|
|
929
|
+
displayName: "Operation",
|
|
930
|
+
name: "operation",
|
|
931
|
+
type: "options",
|
|
932
|
+
noDataExpression: true,
|
|
933
|
+
displayOptions: { show: { resource: ["person"] } },
|
|
934
|
+
options: [
|
|
935
|
+
{ name: "Get Many", value: "getMany", description: "Get many people", action: "Get many people" },
|
|
936
|
+
{ name: "Create", value: "create", description: "Create a person", action: "Create a person" }
|
|
937
|
+
],
|
|
938
|
+
default: "getMany"
|
|
939
|
+
},
|
|
940
|
+
{
|
|
941
|
+
displayName: "Operation",
|
|
942
|
+
name: "operation",
|
|
943
|
+
type: "options",
|
|
944
|
+
noDataExpression: true,
|
|
945
|
+
displayOptions: { show: { resource: ["plan"] } },
|
|
946
|
+
options: [
|
|
947
|
+
{ name: "Get Many", value: "getMany", description: "Get many plans", action: "Get many plans" },
|
|
948
|
+
{ name: "Create", value: "create", description: "Create a plan", action: "Create a plan" }
|
|
949
|
+
],
|
|
950
|
+
default: "getMany"
|
|
951
|
+
},
|
|
952
|
+
{
|
|
953
|
+
displayName: "Operation",
|
|
954
|
+
name: "operation",
|
|
955
|
+
type: "options",
|
|
956
|
+
noDataExpression: true,
|
|
957
|
+
displayOptions: { show: { resource: ["planFamily"] } },
|
|
958
|
+
options: [
|
|
959
|
+
{ name: "Get Many", value: "getMany", description: "Get many plan families", action: "Get many plan families" },
|
|
960
|
+
{ name: "Create", value: "create", description: "Create a plan family", action: "Create a plan family" }
|
|
961
|
+
],
|
|
962
|
+
default: "getMany"
|
|
963
|
+
},
|
|
964
|
+
{
|
|
965
|
+
displayName: "Operation",
|
|
966
|
+
name: "operation",
|
|
967
|
+
type: "options",
|
|
968
|
+
noDataExpression: true,
|
|
969
|
+
displayOptions: { show: { resource: ["subscription"] } },
|
|
970
|
+
options: [
|
|
971
|
+
{ name: "Preview Change", value: "previewChange", description: "Preview a subscription plan change", action: "Preview subscription change" },
|
|
972
|
+
{ name: "Change", value: "change", description: "Change a subscription plan", action: "Change subscription" }
|
|
973
|
+
],
|
|
974
|
+
default: "previewChange"
|
|
975
|
+
},
|
|
976
|
+
{
|
|
977
|
+
displayName: "Operation",
|
|
978
|
+
name: "operation",
|
|
979
|
+
type: "options",
|
|
980
|
+
noDataExpression: true,
|
|
981
|
+
displayOptions: { show: { resource: ["emailList"] } },
|
|
982
|
+
options: [
|
|
983
|
+
{ name: "Get Many", value: "getMany", description: "Get many email lists", action: "Get many email lists" },
|
|
984
|
+
{ name: "Create", value: "create", description: "Create an email list", action: "Create an email list" },
|
|
985
|
+
{ name: "Get Subscribers", value: "getSubscribers", description: "Get subscribers of an email list", action: "Get email list subscribers" },
|
|
986
|
+
{ name: "Subscribe Person", value: "subscribePerson", description: "Subscribe a person to an email list", action: "Subscribe person to email list" }
|
|
987
|
+
],
|
|
988
|
+
default: "getMany"
|
|
989
|
+
},
|
|
990
|
+
{
|
|
991
|
+
displayName: "Search Term",
|
|
992
|
+
name: "q",
|
|
993
|
+
type: "string",
|
|
994
|
+
default: "",
|
|
995
|
+
description: "Search term to filter results",
|
|
996
|
+
displayOptions: { show: { operation: ["getMany"] } }
|
|
997
|
+
},
|
|
998
|
+
{
|
|
999
|
+
displayName: "Limit",
|
|
1000
|
+
name: "limit",
|
|
1001
|
+
type: "number",
|
|
1002
|
+
typeOptions: { minValue: 1, maxValue: 100 },
|
|
1003
|
+
default: 25,
|
|
1004
|
+
description: "Max number of results to return",
|
|
1005
|
+
displayOptions: { show: { operation: ["getMany"] } }
|
|
1006
|
+
},
|
|
1007
|
+
{
|
|
1008
|
+
displayName: "Offset",
|
|
1009
|
+
name: "offset",
|
|
1010
|
+
type: "number",
|
|
1011
|
+
typeOptions: { minValue: 0 },
|
|
1012
|
+
default: 0,
|
|
1013
|
+
description: "Page offset (0-based)",
|
|
1014
|
+
displayOptions: { show: { operation: ["getMany"] } }
|
|
1015
|
+
},
|
|
1016
|
+
{
|
|
1017
|
+
displayName: "Fields",
|
|
1018
|
+
name: "fields",
|
|
1019
|
+
type: "string",
|
|
1020
|
+
default: "*,*.*",
|
|
1021
|
+
description: 'Fields to include in the response. Use "*" for root fields, "*,*.*" for nested objects, or specific paths like "Uid,Name,CurrentSubscription.Plan.*".',
|
|
1022
|
+
displayOptions: { show: { operation: ["getMany"] } }
|
|
1023
|
+
},
|
|
1024
|
+
{
|
|
1025
|
+
displayName: "Order By",
|
|
1026
|
+
name: "orderBy",
|
|
1027
|
+
type: "string",
|
|
1028
|
+
default: "",
|
|
1029
|
+
description: 'Field to order results by (e.g. "Name", "Created")',
|
|
1030
|
+
displayOptions: { show: { operation: ["getMany"] } }
|
|
1031
|
+
},
|
|
1032
|
+
{
|
|
1033
|
+
displayName: "Order Direction",
|
|
1034
|
+
name: "orderDirection",
|
|
1035
|
+
type: "options",
|
|
1036
|
+
options: [
|
|
1037
|
+
{ name: "Ascending", value: "ASC" },
|
|
1038
|
+
{ name: "Descending", value: "DESC" }
|
|
1039
|
+
],
|
|
1040
|
+
default: "ASC",
|
|
1041
|
+
displayOptions: { show: { operation: ["getMany"] } }
|
|
1042
|
+
},
|
|
1043
|
+
{
|
|
1044
|
+
displayName: "Filters",
|
|
1045
|
+
name: "filters",
|
|
1046
|
+
type: "fixedCollection",
|
|
1047
|
+
typeOptions: { multipleValues: true },
|
|
1048
|
+
default: {},
|
|
1049
|
+
placeholder: "Add Filter",
|
|
1050
|
+
displayOptions: { show: { operation: ["getMany"] } },
|
|
1051
|
+
options: [
|
|
1052
|
+
{
|
|
1053
|
+
name: "filterValues",
|
|
1054
|
+
displayName: "Filter",
|
|
1055
|
+
values: [
|
|
1056
|
+
{
|
|
1057
|
+
displayName: "Field",
|
|
1058
|
+
name: "field",
|
|
1059
|
+
type: "string",
|
|
1060
|
+
default: "",
|
|
1061
|
+
description: "Field name to filter on"
|
|
1062
|
+
},
|
|
1063
|
+
{
|
|
1064
|
+
displayName: "Operator",
|
|
1065
|
+
name: "operator",
|
|
1066
|
+
type: "options",
|
|
1067
|
+
options: [
|
|
1068
|
+
{ name: "Equals", value: "" },
|
|
1069
|
+
{ name: "Greater Than", value: "gt" },
|
|
1070
|
+
{ name: "Greater Than or Equal", value: "gte" },
|
|
1071
|
+
{ name: "Less Than", value: "lt" },
|
|
1072
|
+
{ name: "Less Than or Equal", value: "lte" },
|
|
1073
|
+
{ name: "Not Equal", value: "ne" },
|
|
1074
|
+
{ name: "Is Null", value: "isnull" }
|
|
1075
|
+
],
|
|
1076
|
+
default: ""
|
|
1077
|
+
},
|
|
1078
|
+
{
|
|
1079
|
+
displayName: "Value",
|
|
1080
|
+
name: "value",
|
|
1081
|
+
type: "string",
|
|
1082
|
+
default: "",
|
|
1083
|
+
description: "Value to filter by"
|
|
1084
|
+
}
|
|
1085
|
+
]
|
|
1086
|
+
}
|
|
1087
|
+
]
|
|
1088
|
+
},
|
|
1089
|
+
{
|
|
1090
|
+
displayName: "Email",
|
|
1091
|
+
name: "email",
|
|
1092
|
+
type: "string",
|
|
1093
|
+
placeholder: "name@email.com",
|
|
1094
|
+
required: true,
|
|
1095
|
+
default: "",
|
|
1096
|
+
displayOptions: { show: { resource: ["account"], operation: ["register"] } },
|
|
1097
|
+
description: "Email address of the person signing up"
|
|
1098
|
+
},
|
|
1099
|
+
{
|
|
1100
|
+
displayName: "Plan UID",
|
|
1101
|
+
name: "planUid",
|
|
1102
|
+
type: "string",
|
|
1103
|
+
required: true,
|
|
1104
|
+
default: "",
|
|
1105
|
+
displayOptions: { show: { resource: ["account"], operation: ["register"] } },
|
|
1106
|
+
description: "The UID of the plan for the subscription"
|
|
1107
|
+
},
|
|
1108
|
+
{
|
|
1109
|
+
displayName: "First Name",
|
|
1110
|
+
name: "firstName",
|
|
1111
|
+
type: "string",
|
|
1112
|
+
default: "",
|
|
1113
|
+
displayOptions: { show: { resource: ["account"], operation: ["register"] } }
|
|
1114
|
+
},
|
|
1115
|
+
{
|
|
1116
|
+
displayName: "Last Name",
|
|
1117
|
+
name: "lastName",
|
|
1118
|
+
type: "string",
|
|
1119
|
+
default: "",
|
|
1120
|
+
displayOptions: { show: { resource: ["account"], operation: ["register"] } }
|
|
1121
|
+
},
|
|
1122
|
+
{
|
|
1123
|
+
displayName: "Account Name",
|
|
1124
|
+
name: "accountName",
|
|
1125
|
+
type: "string",
|
|
1126
|
+
default: "",
|
|
1127
|
+
displayOptions: { show: { resource: ["account"], operation: ["register"] } }
|
|
1128
|
+
},
|
|
1129
|
+
{
|
|
1130
|
+
displayName: "Billing Renewal Term",
|
|
1131
|
+
name: "billingRenewalTerm",
|
|
1132
|
+
type: "options",
|
|
1133
|
+
options: [
|
|
1134
|
+
{ name: "Monthly", value: 1 },
|
|
1135
|
+
{ name: "Annual", value: 2 },
|
|
1136
|
+
{ name: "Quarterly", value: 3 }
|
|
1137
|
+
],
|
|
1138
|
+
default: 1,
|
|
1139
|
+
displayOptions: { show: { resource: ["account"], operation: ["register"] } }
|
|
1140
|
+
},
|
|
1141
|
+
{
|
|
1142
|
+
displayName: "Account UID",
|
|
1143
|
+
name: "accountUid",
|
|
1144
|
+
type: "string",
|
|
1145
|
+
required: true,
|
|
1146
|
+
default: "",
|
|
1147
|
+
displayOptions: { show: { resource: ["account"], operation: ["addPerson"] } },
|
|
1148
|
+
description: "UID of the account to add the person to"
|
|
1149
|
+
},
|
|
1150
|
+
{
|
|
1151
|
+
displayName: "Person UID",
|
|
1152
|
+
name: "personUid",
|
|
1153
|
+
type: "string",
|
|
1154
|
+
required: true,
|
|
1155
|
+
default: "",
|
|
1156
|
+
displayOptions: { show: { resource: ["account"], operation: ["addPerson"] } },
|
|
1157
|
+
description: "UID of the person to add"
|
|
1158
|
+
},
|
|
1159
|
+
{
|
|
1160
|
+
displayName: "Is Primary",
|
|
1161
|
+
name: "isPrimary",
|
|
1162
|
+
type: "boolean",
|
|
1163
|
+
default: false,
|
|
1164
|
+
displayOptions: { show: { resource: ["account"], operation: ["addPerson"] } },
|
|
1165
|
+
description: "Whether this person should be the primary contact"
|
|
1166
|
+
},
|
|
1167
|
+
{
|
|
1168
|
+
displayName: "Send Welcome Email",
|
|
1169
|
+
name: "sendWelcomeEmail",
|
|
1170
|
+
type: "boolean",
|
|
1171
|
+
default: false,
|
|
1172
|
+
displayOptions: { show: { resource: ["account"], operation: ["addPerson"] } }
|
|
1173
|
+
},
|
|
1174
|
+
{
|
|
1175
|
+
displayName: "Email",
|
|
1176
|
+
name: "email",
|
|
1177
|
+
type: "string",
|
|
1178
|
+
placeholder: "name@email.com",
|
|
1179
|
+
required: true,
|
|
1180
|
+
default: "",
|
|
1181
|
+
displayOptions: { show: { resource: ["person"], operation: ["create"] } }
|
|
1182
|
+
},
|
|
1183
|
+
{
|
|
1184
|
+
displayName: "First Name",
|
|
1185
|
+
name: "firstName",
|
|
1186
|
+
type: "string",
|
|
1187
|
+
default: "",
|
|
1188
|
+
displayOptions: { show: { resource: ["person"], operation: ["create"] } }
|
|
1189
|
+
},
|
|
1190
|
+
{
|
|
1191
|
+
displayName: "Last Name",
|
|
1192
|
+
name: "lastName",
|
|
1193
|
+
type: "string",
|
|
1194
|
+
default: "",
|
|
1195
|
+
displayOptions: { show: { resource: ["person"], operation: ["create"] } }
|
|
1196
|
+
},
|
|
1197
|
+
{
|
|
1198
|
+
displayName: "Name",
|
|
1199
|
+
name: "planName",
|
|
1200
|
+
type: "string",
|
|
1201
|
+
required: true,
|
|
1202
|
+
default: "",
|
|
1203
|
+
displayOptions: { show: { resource: ["plan"], operation: ["create"] } },
|
|
1204
|
+
description: "Name of the plan"
|
|
1205
|
+
},
|
|
1206
|
+
{
|
|
1207
|
+
displayName: "Plan Family UID",
|
|
1208
|
+
name: "planFamilyUid",
|
|
1209
|
+
type: "string",
|
|
1210
|
+
required: true,
|
|
1211
|
+
default: "",
|
|
1212
|
+
displayOptions: { show: { resource: ["plan"], operation: ["create"] } }
|
|
1213
|
+
},
|
|
1214
|
+
{
|
|
1215
|
+
displayName: "Is Active",
|
|
1216
|
+
name: "isActive",
|
|
1217
|
+
type: "boolean",
|
|
1218
|
+
default: true,
|
|
1219
|
+
displayOptions: { show: { resource: ["plan"], operation: ["create"] } }
|
|
1220
|
+
},
|
|
1221
|
+
{
|
|
1222
|
+
displayName: "Account Registration Mode",
|
|
1223
|
+
name: "accountRegistrationMode",
|
|
1224
|
+
type: "options",
|
|
1225
|
+
options: [
|
|
1226
|
+
{ name: "Individual", value: "Individual" },
|
|
1227
|
+
{ name: "Team", value: "Team" }
|
|
1228
|
+
],
|
|
1229
|
+
default: "Individual",
|
|
1230
|
+
displayOptions: { show: { resource: ["plan"], operation: ["create"] } }
|
|
1231
|
+
},
|
|
1232
|
+
{
|
|
1233
|
+
displayName: "Trial Period Days",
|
|
1234
|
+
name: "trialPeriodDays",
|
|
1235
|
+
type: "number",
|
|
1236
|
+
default: 0,
|
|
1237
|
+
displayOptions: { show: { resource: ["plan"], operation: ["create"] } }
|
|
1238
|
+
},
|
|
1239
|
+
{
|
|
1240
|
+
displayName: "Monthly Rate",
|
|
1241
|
+
name: "monthlyRate",
|
|
1242
|
+
type: "number",
|
|
1243
|
+
typeOptions: { numberPrecision: 2 },
|
|
1244
|
+
default: 0,
|
|
1245
|
+
displayOptions: { show: { resource: ["plan"], operation: ["create"] } }
|
|
1246
|
+
},
|
|
1247
|
+
{
|
|
1248
|
+
displayName: "Annual Rate",
|
|
1249
|
+
name: "annualRate",
|
|
1250
|
+
type: "number",
|
|
1251
|
+
typeOptions: { numberPrecision: 2 },
|
|
1252
|
+
default: 0,
|
|
1253
|
+
displayOptions: { show: { resource: ["plan"], operation: ["create"] } }
|
|
1254
|
+
},
|
|
1255
|
+
{
|
|
1256
|
+
displayName: "Quarterly Rate",
|
|
1257
|
+
name: "quarterlyRate",
|
|
1258
|
+
type: "number",
|
|
1259
|
+
typeOptions: { numberPrecision: 2 },
|
|
1260
|
+
default: 0,
|
|
1261
|
+
displayOptions: { show: { resource: ["plan"], operation: ["create"] } }
|
|
1262
|
+
},
|
|
1263
|
+
{
|
|
1264
|
+
displayName: "One-Time Rate",
|
|
1265
|
+
name: "oneTimeRate",
|
|
1266
|
+
type: "number",
|
|
1267
|
+
typeOptions: { numberPrecision: 2 },
|
|
1268
|
+
default: 0,
|
|
1269
|
+
displayOptions: { show: { resource: ["plan"], operation: ["create"] } }
|
|
1270
|
+
},
|
|
1271
|
+
{
|
|
1272
|
+
displayName: "Name",
|
|
1273
|
+
name: "planFamilyName",
|
|
1274
|
+
type: "string",
|
|
1275
|
+
required: true,
|
|
1276
|
+
default: "",
|
|
1277
|
+
displayOptions: { show: { resource: ["planFamily"], operation: ["create"] } }
|
|
1278
|
+
},
|
|
1279
|
+
{
|
|
1280
|
+
displayName: "Is Default",
|
|
1281
|
+
name: "isDefault",
|
|
1282
|
+
type: "boolean",
|
|
1283
|
+
default: false,
|
|
1284
|
+
displayOptions: { show: { resource: ["planFamily"], operation: ["create"] } }
|
|
1285
|
+
},
|
|
1286
|
+
{
|
|
1287
|
+
displayName: "Is Active",
|
|
1288
|
+
name: "isActivePlanFamily",
|
|
1289
|
+
type: "boolean",
|
|
1290
|
+
default: true,
|
|
1291
|
+
displayOptions: { show: { resource: ["planFamily"], operation: ["create"] } }
|
|
1292
|
+
},
|
|
1293
|
+
{
|
|
1294
|
+
displayName: "Account UID",
|
|
1295
|
+
name: "accountUid",
|
|
1296
|
+
type: "string",
|
|
1297
|
+
required: true,
|
|
1298
|
+
default: "",
|
|
1299
|
+
displayOptions: { show: { resource: ["subscription"] } },
|
|
1300
|
+
description: "UID of the account whose subscription to change"
|
|
1301
|
+
},
|
|
1302
|
+
{
|
|
1303
|
+
displayName: "New Plan UID",
|
|
1304
|
+
name: "planUid",
|
|
1305
|
+
type: "string",
|
|
1306
|
+
default: "",
|
|
1307
|
+
displayOptions: { show: { resource: ["subscription"] } },
|
|
1308
|
+
description: "UID of the plan to change to (leave empty to keep current plan)"
|
|
1309
|
+
},
|
|
1310
|
+
{
|
|
1311
|
+
displayName: "Billing Renewal Term",
|
|
1312
|
+
name: "billingRenewalTerm",
|
|
1313
|
+
type: "options",
|
|
1314
|
+
options: [
|
|
1315
|
+
{ name: "Keep Current", value: 0 },
|
|
1316
|
+
{ name: "Monthly", value: 1 },
|
|
1317
|
+
{ name: "Annual", value: 2 },
|
|
1318
|
+
{ name: "Quarterly", value: 3 }
|
|
1319
|
+
],
|
|
1320
|
+
default: 0,
|
|
1321
|
+
displayOptions: { show: { resource: ["subscription"] } },
|
|
1322
|
+
description: "Billing renewal term (0 = keep current)"
|
|
1323
|
+
},
|
|
1324
|
+
{
|
|
1325
|
+
displayName: "Start Immediately",
|
|
1326
|
+
name: "startImmediately",
|
|
1327
|
+
type: "boolean",
|
|
1328
|
+
default: false,
|
|
1329
|
+
displayOptions: { show: { resource: ["subscription"] } }
|
|
1330
|
+
},
|
|
1331
|
+
{
|
|
1332
|
+
displayName: "Name",
|
|
1333
|
+
name: "emailListName",
|
|
1334
|
+
type: "string",
|
|
1335
|
+
required: true,
|
|
1336
|
+
default: "",
|
|
1337
|
+
displayOptions: { show: { resource: ["emailList"], operation: ["create"] } }
|
|
1338
|
+
},
|
|
1339
|
+
{
|
|
1340
|
+
displayName: "Description",
|
|
1341
|
+
name: "emailListDescription",
|
|
1342
|
+
type: "string",
|
|
1343
|
+
default: "",
|
|
1344
|
+
displayOptions: { show: { resource: ["emailList"], operation: ["create"] } }
|
|
1345
|
+
},
|
|
1346
|
+
{
|
|
1347
|
+
displayName: "Is Internal",
|
|
1348
|
+
name: "isInternal",
|
|
1349
|
+
type: "boolean",
|
|
1350
|
+
default: false,
|
|
1351
|
+
displayOptions: { show: { resource: ["emailList"], operation: ["create"] } },
|
|
1352
|
+
description: "Internal lists do not support double opt-in or welcome emails"
|
|
1353
|
+
},
|
|
1354
|
+
{
|
|
1355
|
+
displayName: "Requires Double Opt-In",
|
|
1356
|
+
name: "requiresDoubleOptIn",
|
|
1357
|
+
type: "boolean",
|
|
1358
|
+
default: true,
|
|
1359
|
+
displayOptions: { show: { resource: ["emailList"], operation: ["create"] } }
|
|
1360
|
+
},
|
|
1361
|
+
{
|
|
1362
|
+
displayName: "Welcome Email",
|
|
1363
|
+
name: "welcomeEmail",
|
|
1364
|
+
type: "fixedCollection",
|
|
1365
|
+
default: {},
|
|
1366
|
+
displayOptions: { show: { resource: ["emailList"], operation: ["create"] } },
|
|
1367
|
+
description: "Optional welcome email configuration (only for non-internal lists)",
|
|
1368
|
+
options: [
|
|
1369
|
+
{
|
|
1370
|
+
name: "welcomeValues",
|
|
1371
|
+
displayName: "Welcome Email",
|
|
1372
|
+
values: [
|
|
1373
|
+
{ displayName: "From Name", name: "fromName", type: "string", default: "" },
|
|
1374
|
+
{ displayName: "From Email", name: "fromEmail", type: "string", default: "" },
|
|
1375
|
+
{ displayName: "Subject", name: "subject", type: "string", default: "" },
|
|
1376
|
+
{ displayName: "Body (HTML)", name: "body", type: "string", typeOptions: { rows: 5 }, default: "" }
|
|
1377
|
+
]
|
|
1378
|
+
}
|
|
1379
|
+
]
|
|
1380
|
+
},
|
|
1381
|
+
{
|
|
1382
|
+
displayName: "List UID",
|
|
1383
|
+
name: "listUid",
|
|
1384
|
+
type: "string",
|
|
1385
|
+
required: true,
|
|
1386
|
+
default: "",
|
|
1387
|
+
displayOptions: { show: { resource: ["emailList"], operation: ["getSubscribers"] } }
|
|
1388
|
+
},
|
|
1389
|
+
{
|
|
1390
|
+
displayName: "List UID",
|
|
1391
|
+
name: "listUid",
|
|
1392
|
+
type: "string",
|
|
1393
|
+
required: true,
|
|
1394
|
+
default: "",
|
|
1395
|
+
displayOptions: { show: { resource: ["emailList"], operation: ["subscribePerson"] } }
|
|
1396
|
+
},
|
|
1397
|
+
{
|
|
1398
|
+
displayName: "Person UID",
|
|
1399
|
+
name: "personUid",
|
|
1400
|
+
type: "string",
|
|
1401
|
+
required: true,
|
|
1402
|
+
default: "",
|
|
1403
|
+
displayOptions: { show: { resource: ["emailList"], operation: ["subscribePerson"] } }
|
|
1404
|
+
},
|
|
1405
|
+
{
|
|
1406
|
+
displayName: "Send Welcome Email",
|
|
1407
|
+
name: "sendWelcomeEmail",
|
|
1408
|
+
type: "boolean",
|
|
1409
|
+
default: false,
|
|
1410
|
+
displayOptions: { show: { resource: ["emailList"], operation: ["subscribePerson"] } }
|
|
1411
|
+
}
|
|
1412
|
+
]
|
|
1413
|
+
};
|
|
1414
|
+
async execute() {
|
|
1415
|
+
const items = this.getInputData();
|
|
1416
|
+
const returnData = [];
|
|
1417
|
+
const credentials = await this.getCredentials("outsetaApi");
|
|
1418
|
+
const client = createClient({
|
|
1419
|
+
subdomain: credentials.subdomain,
|
|
1420
|
+
apiKey: credentials.apiKey,
|
|
1421
|
+
apiSecret: credentials.apiSecret
|
|
1422
|
+
});
|
|
1423
|
+
for (let i = 0;i < items.length; i++) {
|
|
1424
|
+
try {
|
|
1425
|
+
const resource = this.getNodeParameter("resource", i);
|
|
1426
|
+
const operation = this.getNodeParameter("operation", i);
|
|
1427
|
+
let responseData;
|
|
1428
|
+
if (resource === "account") {
|
|
1429
|
+
if (operation === "getMany") {
|
|
1430
|
+
responseData = await makeListRequest(client, this, i, "crm/accounts");
|
|
1431
|
+
} else if (operation === "register") {
|
|
1432
|
+
const body = {
|
|
1433
|
+
Name: this.getNodeParameter("accountName", i, "") || undefined,
|
|
1434
|
+
Subscriptions: [
|
|
1435
|
+
{
|
|
1436
|
+
BillingRenewalTerm: this.getNodeParameter("billingRenewalTerm", i),
|
|
1437
|
+
Plan: { Uid: this.getNodeParameter("planUid", i) }
|
|
1438
|
+
}
|
|
1439
|
+
],
|
|
1440
|
+
PersonAccount: [
|
|
1441
|
+
{
|
|
1442
|
+
IsPrimary: true,
|
|
1443
|
+
Person: {
|
|
1444
|
+
Email: this.getNodeParameter("email", i),
|
|
1445
|
+
FirstName: this.getNodeParameter("firstName", i, "") || undefined,
|
|
1446
|
+
LastName: this.getNodeParameter("lastName", i, "") || undefined
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
]
|
|
1450
|
+
};
|
|
1451
|
+
responseData = await request(client, "post", "crm/registrations", body);
|
|
1452
|
+
} else if (operation === "addPerson") {
|
|
1453
|
+
const accountUid = this.getNodeParameter("accountUid", i);
|
|
1454
|
+
const body = {
|
|
1455
|
+
Account: { Uid: accountUid },
|
|
1456
|
+
Person: { Uid: this.getNodeParameter("personUid", i) },
|
|
1457
|
+
IsPrimary: this.getNodeParameter("isPrimary", i)
|
|
1458
|
+
};
|
|
1459
|
+
const searchParams = {
|
|
1460
|
+
sendWelcomeEmail: String(this.getNodeParameter("sendWelcomeEmail", i))
|
|
1461
|
+
};
|
|
1462
|
+
responseData = await request(client, "post", `crm/accounts/${accountUid}/memberships`, body, searchParams);
|
|
1463
|
+
} else {
|
|
1464
|
+
throw new Error(`Unknown operation: ${operation}`);
|
|
1465
|
+
}
|
|
1466
|
+
} else if (resource === "person") {
|
|
1467
|
+
if (operation === "getMany") {
|
|
1468
|
+
responseData = await makeListRequest(client, this, i, "crm/people");
|
|
1469
|
+
} else if (operation === "create") {
|
|
1470
|
+
const body = {
|
|
1471
|
+
Email: this.getNodeParameter("email", i),
|
|
1472
|
+
FirstName: this.getNodeParameter("firstName", i, "") || undefined,
|
|
1473
|
+
LastName: this.getNodeParameter("lastName", i, "") || undefined
|
|
1474
|
+
};
|
|
1475
|
+
responseData = await request(client, "post", "crm/people", body);
|
|
1476
|
+
} else {
|
|
1477
|
+
throw new Error(`Unknown operation: ${operation}`);
|
|
1478
|
+
}
|
|
1479
|
+
} else if (resource === "plan") {
|
|
1480
|
+
if (operation === "getMany") {
|
|
1481
|
+
responseData = await makeListRequest(client, this, i, "billing/plans");
|
|
1482
|
+
} else if (operation === "create") {
|
|
1483
|
+
const body = {
|
|
1484
|
+
Name: this.getNodeParameter("planName", i),
|
|
1485
|
+
PlanFamily: { Uid: this.getNodeParameter("planFamilyUid", i) },
|
|
1486
|
+
IsActive: this.getNodeParameter("isActive", i),
|
|
1487
|
+
AccountRegistrationMode: this.getNodeParameter("accountRegistrationMode", i),
|
|
1488
|
+
TrialPeriodDays: this.getNodeParameter("trialPeriodDays", i, 0) || undefined,
|
|
1489
|
+
MonthlyRate: this.getNodeParameter("monthlyRate", i, 0) || undefined,
|
|
1490
|
+
AnnualRate: this.getNodeParameter("annualRate", i, 0) || undefined,
|
|
1491
|
+
QuarterlyRate: this.getNodeParameter("quarterlyRate", i, 0) || undefined,
|
|
1492
|
+
OneTimeRate: this.getNodeParameter("oneTimeRate", i, 0) || undefined
|
|
1493
|
+
};
|
|
1494
|
+
responseData = await request(client, "post", "billing/plans", body);
|
|
1495
|
+
} else {
|
|
1496
|
+
throw new Error(`Unknown operation: ${operation}`);
|
|
1497
|
+
}
|
|
1498
|
+
} else if (resource === "planFamily") {
|
|
1499
|
+
if (operation === "getMany") {
|
|
1500
|
+
responseData = await makeListRequest(client, this, i, "billing/planfamilies");
|
|
1501
|
+
} else if (operation === "create") {
|
|
1502
|
+
const body = {
|
|
1503
|
+
Name: this.getNodeParameter("planFamilyName", i),
|
|
1504
|
+
IsDefault: this.getNodeParameter("isDefault", i),
|
|
1505
|
+
IsActive: this.getNodeParameter("isActivePlanFamily", i)
|
|
1506
|
+
};
|
|
1507
|
+
responseData = await request(client, "post", "billing/planfamilies", body);
|
|
1508
|
+
} else {
|
|
1509
|
+
throw new Error(`Unknown operation: ${operation}`);
|
|
1510
|
+
}
|
|
1511
|
+
} else if (resource === "subscription") {
|
|
1512
|
+
const accountUid = this.getNodeParameter("accountUid", i);
|
|
1513
|
+
const accountData = await request(client, "get", `crm/accounts/${accountUid}`, undefined, {
|
|
1514
|
+
fields: "Uid,Name,CurrentSubscription.*"
|
|
1515
|
+
});
|
|
1516
|
+
const currentSubscription = accountData.CurrentSubscription;
|
|
1517
|
+
if (!currentSubscription) {
|
|
1518
|
+
throw new Error(`Account ${accountUid} does not have an active subscription`);
|
|
1519
|
+
}
|
|
1520
|
+
const billingRenewalTerm = this.getNodeParameter("billingRenewalTerm", i);
|
|
1521
|
+
const planUid = this.getNodeParameter("planUid", i, "");
|
|
1522
|
+
const body = {
|
|
1523
|
+
Plan: { Uid: planUid || currentSubscription.Plan?.Uid },
|
|
1524
|
+
BillingRenewalTerm: billingRenewalTerm || currentSubscription.BillingRenewalTerm,
|
|
1525
|
+
Account: { Uid: accountUid }
|
|
1526
|
+
};
|
|
1527
|
+
const searchParams = {
|
|
1528
|
+
startImmediately: String(this.getNodeParameter("startImmediately", i))
|
|
1529
|
+
};
|
|
1530
|
+
const subUid = currentSubscription.Uid;
|
|
1531
|
+
const endpoint = operation === "previewChange" ? `billing/subscriptions/${subUid}/changesubscriptionpreview` : `billing/subscriptions/${subUid}/changeSubscription`;
|
|
1532
|
+
responseData = await request(client, "put", endpoint, body, searchParams);
|
|
1533
|
+
} else if (resource === "emailList") {
|
|
1534
|
+
if (operation === "getMany") {
|
|
1535
|
+
responseData = await makeListRequest(client, this, i, "email/lists");
|
|
1536
|
+
} else if (operation === "create") {
|
|
1537
|
+
const body = {
|
|
1538
|
+
Name: this.getNodeParameter("emailListName", i),
|
|
1539
|
+
Description: this.getNodeParameter("emailListDescription", i, "") || undefined,
|
|
1540
|
+
IsInternal: this.getNodeParameter("isInternal", i),
|
|
1541
|
+
RequiresDoubleOptIn: this.getNodeParameter("requiresDoubleOptIn", i)
|
|
1542
|
+
};
|
|
1543
|
+
const welcomeEmail = this.getNodeParameter("welcomeEmail", i, {});
|
|
1544
|
+
const welcomeValues = welcomeEmail.welcomeValues ?? {};
|
|
1545
|
+
if (welcomeValues.fromName) {
|
|
1546
|
+
body.WelcomeFromName = welcomeValues.fromName;
|
|
1547
|
+
body.WelcomeFromEmail = welcomeValues.fromEmail;
|
|
1548
|
+
body.WelcomeSubject = welcomeValues.subject;
|
|
1549
|
+
body.WelcomeBody = welcomeValues.body;
|
|
1550
|
+
}
|
|
1551
|
+
responseData = await request(client, "post", "email/lists", body);
|
|
1552
|
+
} else if (operation === "getSubscribers") {
|
|
1553
|
+
const listUid = this.getNodeParameter("listUid", i);
|
|
1554
|
+
responseData = await request(client, "get", `email/lists/${listUid}/subscriptions`);
|
|
1555
|
+
} else if (operation === "subscribePerson") {
|
|
1556
|
+
const listUid = this.getNodeParameter("listUid", i);
|
|
1557
|
+
const body = {
|
|
1558
|
+
EmailList: { Uid: listUid },
|
|
1559
|
+
Person: { Uid: this.getNodeParameter("personUid", i) },
|
|
1560
|
+
SendWelcomeEmail: this.getNodeParameter("sendWelcomeEmail", i)
|
|
1561
|
+
};
|
|
1562
|
+
responseData = await request(client, "post", `email/lists/${listUid}/subscriptions`, body);
|
|
1563
|
+
} else {
|
|
1564
|
+
throw new Error(`Unknown operation: ${operation}`);
|
|
1565
|
+
}
|
|
1566
|
+
} else {
|
|
1567
|
+
throw new Error(`Unknown resource: ${resource}`);
|
|
1568
|
+
}
|
|
1569
|
+
if (Array.isArray(responseData)) {
|
|
1570
|
+
returnData.push(...responseData.map((item) => ({ json: item })));
|
|
1571
|
+
} else {
|
|
1572
|
+
returnData.push({ json: responseData });
|
|
1573
|
+
}
|
|
1574
|
+
} catch (error) {
|
|
1575
|
+
if (this.continueOnFail()) {
|
|
1576
|
+
returnData.push({
|
|
1577
|
+
json: { error: error.message },
|
|
1578
|
+
pairedItem: { item: i }
|
|
1579
|
+
});
|
|
1580
|
+
continue;
|
|
1581
|
+
}
|
|
1582
|
+
throw error;
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1585
|
+
return [returnData];
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
async function request(client, method, endpoint, body, searchParams) {
|
|
1589
|
+
const options = {};
|
|
1590
|
+
if (body)
|
|
1591
|
+
options.json = body;
|
|
1592
|
+
if (searchParams)
|
|
1593
|
+
options.searchParams = searchParams;
|
|
1594
|
+
return await client[method](endpoint, options).json();
|
|
1595
|
+
}
|
|
1596
|
+
async function makeListRequest(client, ctx, itemIndex, endpoint) {
|
|
1597
|
+
const searchParams = {};
|
|
1598
|
+
const q = ctx.getNodeParameter("q", itemIndex, "");
|
|
1599
|
+
if (q)
|
|
1600
|
+
searchParams.q = q;
|
|
1601
|
+
const limit = ctx.getNodeParameter("limit", itemIndex, 25);
|
|
1602
|
+
searchParams.limit = String(limit);
|
|
1603
|
+
const offset = ctx.getNodeParameter("offset", itemIndex, 0);
|
|
1604
|
+
searchParams.offset = String(offset);
|
|
1605
|
+
const fields = ctx.getNodeParameter("fields", itemIndex, "*,*.*");
|
|
1606
|
+
if (fields)
|
|
1607
|
+
searchParams.fields = fields;
|
|
1608
|
+
const orderBy = ctx.getNodeParameter("orderBy", itemIndex, "");
|
|
1609
|
+
const orderDirection = ctx.getNodeParameter("orderDirection", itemIndex, "ASC");
|
|
1610
|
+
if (orderBy) {
|
|
1611
|
+
searchParams.orderBy = `${orderBy}+${orderDirection}`;
|
|
1612
|
+
}
|
|
1613
|
+
const filtersData = ctx.getNodeParameter("filters", itemIndex, {});
|
|
1614
|
+
const filterValues = filtersData.filterValues ?? [];
|
|
1615
|
+
for (const filter of filterValues) {
|
|
1616
|
+
const field = filter.field;
|
|
1617
|
+
const operator = filter.operator;
|
|
1618
|
+
const value = filter.value;
|
|
1619
|
+
const paramKey = operator ? `${field}__${operator}` : field;
|
|
1620
|
+
searchParams[paramKey] = value;
|
|
1621
|
+
}
|
|
1622
|
+
return await request(client, "get", endpoint, undefined, searchParams);
|
|
1623
|
+
}
|