@kadoa/node-sdk 0.13.0 → 0.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/index.global.js +13 -13
- package/dist/browser/index.global.js.map +1 -1
- package/dist/index.d.mts +935 -835
- package/dist/index.d.ts +935 -835
- package/dist/index.js +1254 -1514
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1238 -1513
- package/dist/index.mjs.map +1 -1
- package/package.json +68 -65
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var globalAxios5 = require('axios');
|
|
4
|
-
var uuid = require('uuid');
|
|
5
|
-
var url = require('url');
|
|
6
4
|
var createDebug = require('debug');
|
|
7
5
|
var esToolkit = require('es-toolkit');
|
|
8
|
-
var
|
|
6
|
+
var url = require('url');
|
|
9
7
|
var assert = require('assert');
|
|
8
|
+
var zod = require('zod');
|
|
9
|
+
var uuid = require('uuid');
|
|
10
10
|
|
|
11
11
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
12
|
|
|
@@ -21,7 +21,120 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
21
21
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
22
22
|
});
|
|
23
23
|
|
|
24
|
-
// src/
|
|
24
|
+
// src/domains/extraction/extraction.acl.ts
|
|
25
|
+
var FetchDataOptions = class {
|
|
26
|
+
};
|
|
27
|
+
var SchemaFieldDataType = {
|
|
28
|
+
Text: "TEXT",
|
|
29
|
+
Number: "NUMBER",
|
|
30
|
+
Date: "DATE",
|
|
31
|
+
Url: "URL",
|
|
32
|
+
Email: "EMAIL",
|
|
33
|
+
Image: "IMAGE",
|
|
34
|
+
Video: "VIDEO",
|
|
35
|
+
Phone: "PHONE",
|
|
36
|
+
Boolean: "BOOLEAN",
|
|
37
|
+
Location: "LOCATION",
|
|
38
|
+
Array: "ARRAY",
|
|
39
|
+
Object: "OBJECT"
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// src/runtime/pagination/paginator.ts
|
|
43
|
+
var PagedIterator = class {
|
|
44
|
+
constructor(fetchPage) {
|
|
45
|
+
this.fetchPage = fetchPage;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Fetch all items across all pages
|
|
49
|
+
* @param options Base options (page will be overridden)
|
|
50
|
+
* @returns Array of all items
|
|
51
|
+
*/
|
|
52
|
+
async fetchAll(options = {}) {
|
|
53
|
+
const allItems = [];
|
|
54
|
+
let currentPage = 1;
|
|
55
|
+
let hasMore = true;
|
|
56
|
+
while (hasMore) {
|
|
57
|
+
const result = await this.fetchPage({ ...options, page: currentPage });
|
|
58
|
+
allItems.push(...result.data);
|
|
59
|
+
const pagination = result.pagination;
|
|
60
|
+
hasMore = pagination.page !== void 0 && pagination.totalPages !== void 0 && pagination.page < pagination.totalPages;
|
|
61
|
+
currentPage++;
|
|
62
|
+
}
|
|
63
|
+
return allItems;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Create an async iterator for pages
|
|
67
|
+
* @param options Base options (page will be overridden)
|
|
68
|
+
* @returns Async generator that yields pages
|
|
69
|
+
*/
|
|
70
|
+
async *pages(options = {}) {
|
|
71
|
+
let currentPage = 1;
|
|
72
|
+
let hasMore = true;
|
|
73
|
+
while (hasMore) {
|
|
74
|
+
const result = await this.fetchPage({ ...options, page: currentPage });
|
|
75
|
+
yield result;
|
|
76
|
+
const pagination = result.pagination;
|
|
77
|
+
hasMore = pagination.page !== void 0 && pagination.totalPages !== void 0 && pagination.page < pagination.totalPages;
|
|
78
|
+
currentPage++;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Create an async iterator for individual items
|
|
83
|
+
* @param options Base options (page will be overridden)
|
|
84
|
+
* @returns Async generator that yields items
|
|
85
|
+
*/
|
|
86
|
+
async *items(options = {}) {
|
|
87
|
+
for await (const page of this.pages(options)) {
|
|
88
|
+
for (const item of page.data) {
|
|
89
|
+
yield item;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// src/domains/extraction/services/data-fetcher.service.ts
|
|
96
|
+
var DataFetcherService = class {
|
|
97
|
+
constructor(workflowsApi) {
|
|
98
|
+
this.workflowsApi = workflowsApi;
|
|
99
|
+
this.defaultLimit = 100;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Fetch a page of workflow data
|
|
103
|
+
*/
|
|
104
|
+
async fetchData(options) {
|
|
105
|
+
const response = await this.workflowsApi.v4WorkflowsWorkflowIdDataGet({
|
|
106
|
+
...options,
|
|
107
|
+
page: options.page ?? 1,
|
|
108
|
+
limit: options.limit ?? this.defaultLimit
|
|
109
|
+
});
|
|
110
|
+
const result = response.data;
|
|
111
|
+
return result;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Fetch all pages of workflow data
|
|
115
|
+
*/
|
|
116
|
+
async fetchAllData(options) {
|
|
117
|
+
const iterator = new PagedIterator(
|
|
118
|
+
(pageOptions) => this.fetchData({ ...options, ...pageOptions })
|
|
119
|
+
);
|
|
120
|
+
return iterator.fetchAll({ limit: options.limit ?? this.defaultLimit });
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Create an async iterator for paginated data fetching
|
|
124
|
+
*/
|
|
125
|
+
async *fetchDataPages(options) {
|
|
126
|
+
const iterator = new PagedIterator(
|
|
127
|
+
(pageOptions) => this.fetchData({ ...options, ...pageOptions })
|
|
128
|
+
);
|
|
129
|
+
for await (const page of iterator.pages({
|
|
130
|
+
limit: options.limit ?? this.defaultLimit
|
|
131
|
+
})) {
|
|
132
|
+
yield page;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
// src/runtime/exceptions/base.exception.ts
|
|
25
138
|
var KadoaErrorCode = {
|
|
26
139
|
AUTH_ERROR: "AUTH_ERROR",
|
|
27
140
|
VALIDATION_ERROR: "VALIDATION_ERROR",
|
|
@@ -204,6 +317,128 @@ var KadoaHttpException = class _KadoaHttpException extends KadoaSdkException {
|
|
|
204
317
|
return "UNKNOWN";
|
|
205
318
|
}
|
|
206
319
|
};
|
|
320
|
+
var createLogger = (namespace) => createDebug__default.default(`kadoa:${namespace}`);
|
|
321
|
+
var logger = {
|
|
322
|
+
client: createLogger("client"),
|
|
323
|
+
wss: createLogger("wss"),
|
|
324
|
+
extraction: createLogger("extraction"),
|
|
325
|
+
http: createLogger("http"),
|
|
326
|
+
workflow: createLogger("workflow"),
|
|
327
|
+
crawl: createLogger("crawl"),
|
|
328
|
+
notifications: createLogger("notifications"),
|
|
329
|
+
schemas: createLogger("schemas"),
|
|
330
|
+
validation: createLogger("validation")
|
|
331
|
+
};
|
|
332
|
+
var _SchemaBuilder = class _SchemaBuilder {
|
|
333
|
+
constructor() {
|
|
334
|
+
this.fields = [];
|
|
335
|
+
}
|
|
336
|
+
entity(entityName) {
|
|
337
|
+
this.entityName = entityName;
|
|
338
|
+
return this;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Add a structured field to the schema
|
|
342
|
+
* @param name - Field name (alphanumeric only)
|
|
343
|
+
* @param description - Field description
|
|
344
|
+
* @param dataType - Data type (STRING, NUMBER, BOOLEAN, etc.)
|
|
345
|
+
* @param options - Optional field configuration
|
|
346
|
+
*/
|
|
347
|
+
field(name, description, dataType, options) {
|
|
348
|
+
this.validateFieldName(name);
|
|
349
|
+
const requiresExample = _SchemaBuilder.TYPES_REQUIRING_EXAMPLE.includes(dataType);
|
|
350
|
+
if (requiresExample && !options?.example) {
|
|
351
|
+
throw new KadoaSdkException(
|
|
352
|
+
`Field "${name}" with type ${dataType} requires an example`,
|
|
353
|
+
{ code: "VALIDATION_ERROR", details: { name, dataType } }
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
this.fields.push({
|
|
357
|
+
name,
|
|
358
|
+
description,
|
|
359
|
+
dataType,
|
|
360
|
+
fieldType: "SCHEMA",
|
|
361
|
+
example: options?.example,
|
|
362
|
+
isKey: options?.isKey
|
|
363
|
+
});
|
|
364
|
+
return this;
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Add a classification field to categorize content
|
|
368
|
+
* @param name - Field name (alphanumeric only)
|
|
369
|
+
* @param description - Field description
|
|
370
|
+
* @param categories - Array of category definitions
|
|
371
|
+
*/
|
|
372
|
+
classify(name, description, categories) {
|
|
373
|
+
this.validateFieldName(name);
|
|
374
|
+
this.fields.push({
|
|
375
|
+
name,
|
|
376
|
+
description,
|
|
377
|
+
fieldType: "CLASSIFICATION",
|
|
378
|
+
categories
|
|
379
|
+
});
|
|
380
|
+
return this;
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Add raw page content to extract
|
|
384
|
+
* @param name - Raw content format(s): "html", "markdown", or "url"
|
|
385
|
+
*/
|
|
386
|
+
raw(name) {
|
|
387
|
+
const names = Array.isArray(name) ? name : [name];
|
|
388
|
+
for (const name2 of names) {
|
|
389
|
+
const fieldName = `raw${esToolkit.upperFirst(esToolkit.camelCase(name2))}`;
|
|
390
|
+
if (this.fields.some((field) => field.name === fieldName)) {
|
|
391
|
+
continue;
|
|
392
|
+
}
|
|
393
|
+
this.fields.push({
|
|
394
|
+
name: fieldName,
|
|
395
|
+
description: `Raw page content in ${name2.toUpperCase()} format`,
|
|
396
|
+
fieldType: "METADATA",
|
|
397
|
+
metadataKey: name2
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
return this;
|
|
401
|
+
}
|
|
402
|
+
build() {
|
|
403
|
+
if (!this.entityName) {
|
|
404
|
+
throw new KadoaSdkException("Entity name is required", {
|
|
405
|
+
code: "VALIDATION_ERROR",
|
|
406
|
+
details: { entityName: this.entityName }
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
return {
|
|
410
|
+
entityName: this.entityName,
|
|
411
|
+
fields: this.fields
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
validateFieldName(name) {
|
|
415
|
+
if (!_SchemaBuilder.FIELD_NAME_PATTERN.test(name)) {
|
|
416
|
+
throw new KadoaSdkException(
|
|
417
|
+
`Field name "${name}" must be alphanumeric only (no underscores or special characters)`,
|
|
418
|
+
{
|
|
419
|
+
code: "VALIDATION_ERROR",
|
|
420
|
+
details: { name, pattern: "^[A-Za-z0-9]+$" }
|
|
421
|
+
}
|
|
422
|
+
);
|
|
423
|
+
}
|
|
424
|
+
const lowerName = name.toLowerCase();
|
|
425
|
+
if (this.fields.some((f) => f.name.toLowerCase() === lowerName)) {
|
|
426
|
+
throw new KadoaSdkException(`Duplicate field name: "${name}"`, {
|
|
427
|
+
code: "VALIDATION_ERROR",
|
|
428
|
+
details: { name }
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
};
|
|
433
|
+
_SchemaBuilder.FIELD_NAME_PATTERN = /^[A-Za-z0-9]+$/;
|
|
434
|
+
_SchemaBuilder.TYPES_REQUIRING_EXAMPLE = [
|
|
435
|
+
"STRING",
|
|
436
|
+
"IMAGE",
|
|
437
|
+
"LINK",
|
|
438
|
+
"OBJECT",
|
|
439
|
+
"ARRAY"
|
|
440
|
+
];
|
|
441
|
+
var SchemaBuilder = _SchemaBuilder;
|
|
207
442
|
var BASE_PATH = "https://api.kadoa.com".replace(/\/+$/, "");
|
|
208
443
|
var BaseAPI = class {
|
|
209
444
|
constructor(configuration, basePath = BASE_PATH, axios2 = globalAxios5__default.default) {
|
|
@@ -2616,7 +2851,7 @@ var WorkflowsApiAxiosParamCreator = function(configuration) {
|
|
|
2616
2851
|
/**
|
|
2617
2852
|
* Retrieves a list of workflows with pagination and search capabilities
|
|
2618
2853
|
* @summary Get a list of workflows
|
|
2619
|
-
* @param {string} [search] Search term to filter workflows by name or
|
|
2854
|
+
* @param {string} [search] Search term to filter workflows by name, URL, or workflow ID
|
|
2620
2855
|
* @param {number} [skip] Number of items to skip
|
|
2621
2856
|
* @param {number} [limit] Maximum number of items to return
|
|
2622
2857
|
* @param {V4WorkflowsGetStateEnum} [state] Filter workflows by state
|
|
@@ -3450,7 +3685,7 @@ var WorkflowsApiFp = function(configuration) {
|
|
|
3450
3685
|
/**
|
|
3451
3686
|
* Retrieves a list of workflows with pagination and search capabilities
|
|
3452
3687
|
* @summary Get a list of workflows
|
|
3453
|
-
* @param {string} [search] Search term to filter workflows by name or
|
|
3688
|
+
* @param {string} [search] Search term to filter workflows by name, URL, or workflow ID
|
|
3454
3689
|
* @param {number} [skip] Number of items to skip
|
|
3455
3690
|
* @param {number} [limit] Maximum number of items to return
|
|
3456
3691
|
* @param {V4WorkflowsGetStateEnum} [state] Filter workflows by state
|
|
@@ -4058,809 +4293,277 @@ var Configuration = class {
|
|
|
4058
4293
|
}
|
|
4059
4294
|
};
|
|
4060
4295
|
|
|
4061
|
-
// src/
|
|
4062
|
-
var
|
|
4063
|
-
var
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
// src/internal/runtime/config/constants.ts
|
|
4067
|
-
var PUBLIC_API_URI = process.env.KADOA_PUBLIC_API_URI ?? "https://api.kadoa.com";
|
|
4068
|
-
var WSS_API_URI = process.env.KADOA_WSS_API_URI ?? "wss://realtime.kadoa.com";
|
|
4069
|
-
var REALTIME_API_URI = process.env.KADOA_REALTIME_API_URI ?? "https://realtime.kadoa.com";
|
|
4070
|
-
var createLogger = (namespace) => createDebug__default.default(`kadoa:${namespace}`);
|
|
4071
|
-
var logger = {
|
|
4072
|
-
client: createLogger("client"),
|
|
4073
|
-
wss: createLogger("wss"),
|
|
4074
|
-
extraction: createLogger("extraction"),
|
|
4075
|
-
http: createLogger("http"),
|
|
4076
|
-
workflow: createLogger("workflow"),
|
|
4077
|
-
crawl: createLogger("crawl"),
|
|
4078
|
-
notifications: createLogger("notifications"),
|
|
4079
|
-
schemas: createLogger("schemas"),
|
|
4080
|
-
validation: createLogger("validation")
|
|
4081
|
-
};
|
|
4082
|
-
|
|
4083
|
-
// src/internal/domains/realtime/realtime.ts
|
|
4084
|
-
var debug = logger.wss;
|
|
4085
|
-
if (typeof WebSocket === "undefined") {
|
|
4086
|
-
global.WebSocket = __require("ws");
|
|
4087
|
-
}
|
|
4088
|
-
var Realtime = class {
|
|
4089
|
-
constructor(config) {
|
|
4090
|
-
this.lastHeartbeat = Date.now();
|
|
4091
|
-
this.isConnecting = false;
|
|
4092
|
-
this.eventListeners = /* @__PURE__ */ new Set();
|
|
4093
|
-
this.connectionListeners = /* @__PURE__ */ new Set();
|
|
4094
|
-
this.errorListeners = /* @__PURE__ */ new Set();
|
|
4095
|
-
if (!config.teamApiKey.startsWith("tk-")) {
|
|
4096
|
-
throw new KadoaSdkException(
|
|
4097
|
-
"Realtime connection requires a team API key (starting with 'tk-'). Provided key does not appear to be a team API key.",
|
|
4098
|
-
{
|
|
4099
|
-
code: "AUTH_ERROR",
|
|
4100
|
-
details: { providedKeyPrefix: config.teamApiKey.substring(0, 3) }
|
|
4101
|
-
}
|
|
4102
|
-
);
|
|
4103
|
-
}
|
|
4104
|
-
this.teamApiKey = config.teamApiKey;
|
|
4105
|
-
this.heartbeatInterval = config.heartbeatInterval || 1e4;
|
|
4106
|
-
this.reconnectDelay = config.reconnectDelay || 5e3;
|
|
4107
|
-
this.missedHeartbeatsLimit = config.missedHeartbeatsLimit || 3e4;
|
|
4108
|
-
}
|
|
4109
|
-
async connect() {
|
|
4110
|
-
if (this.isConnecting) return;
|
|
4111
|
-
this.isConnecting = true;
|
|
4112
|
-
try {
|
|
4113
|
-
const response = await fetch(`${PUBLIC_API_URI}/v4/oauth2/token`, {
|
|
4114
|
-
method: "POST",
|
|
4115
|
-
headers: {
|
|
4116
|
-
"Content-Type": "application/json",
|
|
4117
|
-
"x-api-key": `${this.teamApiKey}`,
|
|
4118
|
-
"x-sdk-version": SDK_VERSION
|
|
4119
|
-
}
|
|
4120
|
-
});
|
|
4121
|
-
const { access_token, team_id } = await response.json();
|
|
4122
|
-
this.socket = new WebSocket(
|
|
4123
|
-
`${WSS_API_URI}?access_token=${access_token}`
|
|
4124
|
-
);
|
|
4125
|
-
this.socket.onopen = () => {
|
|
4126
|
-
this.isConnecting = false;
|
|
4127
|
-
this.lastHeartbeat = Date.now();
|
|
4128
|
-
if (this.socket?.readyState === WebSocket.OPEN) {
|
|
4129
|
-
this.socket.send(
|
|
4130
|
-
JSON.stringify({
|
|
4131
|
-
action: "subscribe",
|
|
4132
|
-
channel: team_id
|
|
4133
|
-
})
|
|
4134
|
-
);
|
|
4135
|
-
debug("Connected to WebSocket");
|
|
4136
|
-
this.notifyConnectionListeners(true);
|
|
4137
|
-
}
|
|
4138
|
-
this.startHeartbeatCheck();
|
|
4139
|
-
};
|
|
4140
|
-
this.socket.onmessage = (event) => {
|
|
4141
|
-
try {
|
|
4142
|
-
const data = JSON.parse(event.data);
|
|
4143
|
-
if (data.type === "heartbeat") {
|
|
4144
|
-
this.handleHeartbeat();
|
|
4145
|
-
} else {
|
|
4146
|
-
if (data?.id) {
|
|
4147
|
-
fetch(`${REALTIME_API_URI}/api/v1/events/ack`, {
|
|
4148
|
-
method: "POST",
|
|
4149
|
-
headers: { "Content-Type": "application/json" },
|
|
4150
|
-
body: JSON.stringify({ id: data.id })
|
|
4151
|
-
});
|
|
4152
|
-
}
|
|
4153
|
-
this.notifyEventListeners(data);
|
|
4154
|
-
}
|
|
4155
|
-
} catch (err) {
|
|
4156
|
-
debug("Failed to parse incoming message: %O", err);
|
|
4157
|
-
}
|
|
4158
|
-
};
|
|
4159
|
-
this.socket.onclose = () => {
|
|
4160
|
-
debug("WebSocket disconnected. Attempting to reconnect...");
|
|
4161
|
-
this.isConnecting = false;
|
|
4162
|
-
this.stopHeartbeatCheck();
|
|
4163
|
-
this.notifyConnectionListeners(false, "Connection closed");
|
|
4164
|
-
setTimeout(() => this.connect(), this.reconnectDelay);
|
|
4165
|
-
};
|
|
4166
|
-
this.socket.onerror = (error) => {
|
|
4167
|
-
debug("WebSocket error: %O", error);
|
|
4168
|
-
this.isConnecting = false;
|
|
4169
|
-
this.notifyErrorListeners(error);
|
|
4170
|
-
};
|
|
4171
|
-
} catch (err) {
|
|
4172
|
-
debug("Failed to connect: %O", err);
|
|
4173
|
-
this.isConnecting = false;
|
|
4174
|
-
setTimeout(() => this.connect(), this.reconnectDelay);
|
|
4175
|
-
}
|
|
4176
|
-
}
|
|
4177
|
-
handleHeartbeat() {
|
|
4178
|
-
debug("Heartbeat received");
|
|
4179
|
-
this.lastHeartbeat = Date.now();
|
|
4180
|
-
}
|
|
4181
|
-
notifyEventListeners(event) {
|
|
4182
|
-
this.eventListeners.forEach((listener) => {
|
|
4183
|
-
try {
|
|
4184
|
-
listener(event);
|
|
4185
|
-
} catch (error) {
|
|
4186
|
-
debug("Error in event listener: %O", error);
|
|
4187
|
-
}
|
|
4188
|
-
});
|
|
4189
|
-
}
|
|
4190
|
-
notifyConnectionListeners(connected, reason) {
|
|
4191
|
-
this.connectionListeners.forEach((listener) => {
|
|
4192
|
-
try {
|
|
4193
|
-
listener(connected, reason);
|
|
4194
|
-
} catch (error) {
|
|
4195
|
-
debug("Error in connection listener: %O", error);
|
|
4196
|
-
}
|
|
4197
|
-
});
|
|
4198
|
-
}
|
|
4199
|
-
notifyErrorListeners(error) {
|
|
4200
|
-
this.errorListeners.forEach((listener) => {
|
|
4201
|
-
try {
|
|
4202
|
-
listener(error);
|
|
4203
|
-
} catch (error2) {
|
|
4204
|
-
debug("Error in error listener: %O", error2);
|
|
4205
|
-
}
|
|
4206
|
-
});
|
|
4207
|
-
}
|
|
4208
|
-
startHeartbeatCheck() {
|
|
4209
|
-
this.missedHeartbeatCheckTimer = setInterval(() => {
|
|
4210
|
-
if (Date.now() - this.lastHeartbeat > this.missedHeartbeatsLimit) {
|
|
4211
|
-
debug("No heartbeat received in 30 seconds! Closing connection.");
|
|
4212
|
-
this.socket?.close();
|
|
4213
|
-
}
|
|
4214
|
-
}, this.heartbeatInterval);
|
|
4215
|
-
}
|
|
4216
|
-
stopHeartbeatCheck() {
|
|
4217
|
-
if (this.missedHeartbeatCheckTimer) {
|
|
4218
|
-
clearInterval(this.missedHeartbeatCheckTimer);
|
|
4219
|
-
}
|
|
4220
|
-
}
|
|
4221
|
-
/**
|
|
4222
|
-
* Subscribe to realtime events
|
|
4223
|
-
* @param listener Function to handle incoming events
|
|
4224
|
-
* @returns Function to unsubscribe
|
|
4225
|
-
*/
|
|
4226
|
-
onEvent(listener) {
|
|
4227
|
-
this.eventListeners.add(listener);
|
|
4228
|
-
return () => {
|
|
4229
|
-
this.eventListeners.delete(listener);
|
|
4230
|
-
};
|
|
4296
|
+
// src/domains/schemas/schemas.service.ts
|
|
4297
|
+
var debug = logger.schemas;
|
|
4298
|
+
var SchemasService = class {
|
|
4299
|
+
constructor(client) {
|
|
4300
|
+
this.schemasApi = new SchemasApi(client.configuration);
|
|
4231
4301
|
}
|
|
4232
4302
|
/**
|
|
4233
|
-
*
|
|
4234
|
-
* @param listener Function to handle connection state changes
|
|
4235
|
-
* @returns Function to unsubscribe
|
|
4303
|
+
* Create a schema builder with fluent API and inline create support.
|
|
4236
4304
|
*/
|
|
4237
|
-
|
|
4238
|
-
this
|
|
4239
|
-
return
|
|
4240
|
-
|
|
4241
|
-
|
|
4305
|
+
builder(entityName) {
|
|
4306
|
+
const service = this;
|
|
4307
|
+
return new class extends SchemaBuilder {
|
|
4308
|
+
constructor() {
|
|
4309
|
+
super();
|
|
4310
|
+
this.entity(entityName);
|
|
4311
|
+
}
|
|
4312
|
+
async create(name) {
|
|
4313
|
+
const built = this.build();
|
|
4314
|
+
return service.createSchema({
|
|
4315
|
+
name: name || built.entityName,
|
|
4316
|
+
entity: built.entityName,
|
|
4317
|
+
fields: built.fields
|
|
4318
|
+
});
|
|
4319
|
+
}
|
|
4320
|
+
}();
|
|
4242
4321
|
}
|
|
4243
4322
|
/**
|
|
4244
|
-
*
|
|
4245
|
-
* @param listener Function to handle errors
|
|
4246
|
-
* @returns Function to unsubscribe
|
|
4323
|
+
* Get a schema by ID
|
|
4247
4324
|
*/
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
};
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4325
|
+
async getSchema(schemaId) {
|
|
4326
|
+
debug("Fetching schema with ID: %s", schemaId);
|
|
4327
|
+
const response = await this.schemasApi.v4SchemasSchemaIdGet({
|
|
4328
|
+
schemaId
|
|
4329
|
+
});
|
|
4330
|
+
const schemaData = response.data.data;
|
|
4331
|
+
if (!schemaData) {
|
|
4332
|
+
throw new KadoaSdkException(
|
|
4333
|
+
`${ERROR_MESSAGES.SCHEMA_NOT_FOUND}: ${schemaId}`,
|
|
4334
|
+
{
|
|
4335
|
+
code: KadoaErrorCode.NOT_FOUND,
|
|
4336
|
+
details: { schemaId }
|
|
4337
|
+
}
|
|
4338
|
+
);
|
|
4259
4339
|
}
|
|
4260
|
-
|
|
4261
|
-
this.connectionListeners.clear();
|
|
4262
|
-
this.errorListeners.clear();
|
|
4263
|
-
}
|
|
4264
|
-
isConnected() {
|
|
4265
|
-
return this.socket?.readyState === WebSocket.OPEN;
|
|
4266
|
-
}
|
|
4267
|
-
};
|
|
4268
|
-
|
|
4269
|
-
// src/modules/extraction.module.ts
|
|
4270
|
-
var ExtractionModule = class {
|
|
4271
|
-
constructor(extractionService, dataFetcherService, channelsService, settingsService, workflowsCoreService) {
|
|
4272
|
-
this.extractionService = extractionService;
|
|
4273
|
-
this.dataFetcherService = dataFetcherService;
|
|
4274
|
-
this.channelsService = channelsService;
|
|
4275
|
-
this.settingsService = settingsService;
|
|
4276
|
-
this.workflowsCoreService = workflowsCoreService;
|
|
4340
|
+
return schemaData;
|
|
4277
4341
|
}
|
|
4278
4342
|
/**
|
|
4279
|
-
*
|
|
4280
|
-
*
|
|
4281
|
-
* @param options Extraction configuration options including optional notification settings
|
|
4282
|
-
* @returns ExtractionResult containing workflow ID, workflow details, and first page of extracted data
|
|
4283
|
-
*
|
|
4284
|
-
* @example Simple extraction with AI detection
|
|
4285
|
-
* ```typescript
|
|
4286
|
-
* const result = await client.extraction.run({
|
|
4287
|
-
* urls: ['https://example.com'],
|
|
4288
|
-
* name: 'My Extraction'
|
|
4289
|
-
* });
|
|
4290
|
-
* ```
|
|
4291
|
-
*
|
|
4292
|
-
* @example With notifications
|
|
4293
|
-
* ```typescript
|
|
4294
|
-
* const result = await client.extraction.run({
|
|
4295
|
-
* urls: ['https://example.com'],
|
|
4296
|
-
* name: 'My Extraction',
|
|
4297
|
-
* notifications: {
|
|
4298
|
-
* events: ['workflow_completed', 'workflow_failed'],
|
|
4299
|
-
* channels: {
|
|
4300
|
-
* email: true,
|
|
4301
|
-
* slack: { channelId: 'slack-channel-id' }
|
|
4302
|
-
* }
|
|
4303
|
-
* }
|
|
4304
|
-
* });
|
|
4305
|
-
* ```
|
|
4306
|
-
*
|
|
4307
|
-
* @see {@link KadoaClient.extract} For more flexible extraction configuration using the builder API
|
|
4343
|
+
* List all schemas
|
|
4308
4344
|
*/
|
|
4309
|
-
async
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
mode: "run"
|
|
4313
|
-
});
|
|
4345
|
+
async listSchemas() {
|
|
4346
|
+
const response = await this.schemasApi.v4SchemasGet();
|
|
4347
|
+
return response.data.data;
|
|
4314
4348
|
}
|
|
4315
4349
|
/**
|
|
4316
|
-
*
|
|
4317
|
-
*
|
|
4318
|
-
* @param options Extraction configuration options including optional notification settings
|
|
4319
|
-
* @returns SubmitExtractionResult containing workflow ID
|
|
4320
|
-
*
|
|
4321
|
-
* @example
|
|
4322
|
-
* ```typescript
|
|
4323
|
-
* const result = await client.extraction.submit({
|
|
4324
|
-
* urls: ['https://example.com'],
|
|
4325
|
-
* name: 'My Extraction',
|
|
4326
|
-
* notifications: {
|
|
4327
|
-
* events: 'all',
|
|
4328
|
-
* channels: {
|
|
4329
|
-
* email: true
|
|
4330
|
-
* }
|
|
4331
|
-
* }
|
|
4332
|
-
* });
|
|
4333
|
-
* ```
|
|
4334
|
-
*
|
|
4335
|
-
* @see {@link KadoaClient.extract} For more flexible extraction configuration using the builder API
|
|
4350
|
+
* Create a new schema
|
|
4336
4351
|
*/
|
|
4337
|
-
async
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4352
|
+
async createSchema(body) {
|
|
4353
|
+
debug("Creating schema with name: %s", body.name);
|
|
4354
|
+
const response = await this.schemasApi.v4SchemasPost({
|
|
4355
|
+
createSchemaBody: body
|
|
4341
4356
|
});
|
|
4357
|
+
const schemaId = response.data.schemaId;
|
|
4358
|
+
if (!schemaId) {
|
|
4359
|
+
throw new KadoaSdkException(ERROR_MESSAGES.SCHEMA_CREATE_FAILED, {
|
|
4360
|
+
code: KadoaErrorCode.INTERNAL_ERROR
|
|
4361
|
+
});
|
|
4362
|
+
}
|
|
4363
|
+
return this.getSchema(schemaId);
|
|
4342
4364
|
}
|
|
4343
4365
|
/**
|
|
4344
|
-
*
|
|
4366
|
+
* Update an existing schema
|
|
4345
4367
|
*/
|
|
4346
|
-
async
|
|
4347
|
-
|
|
4368
|
+
async updateSchema(schemaId, body) {
|
|
4369
|
+
debug("Updating schema with ID: %s", schemaId);
|
|
4370
|
+
await this.schemasApi.v4SchemasSchemaIdPut({
|
|
4371
|
+
schemaId,
|
|
4372
|
+
updateSchemaBody: body
|
|
4373
|
+
});
|
|
4374
|
+
return this.getSchema(schemaId);
|
|
4348
4375
|
}
|
|
4349
4376
|
/**
|
|
4350
|
-
*
|
|
4377
|
+
* Delete a schema
|
|
4351
4378
|
*/
|
|
4352
|
-
async
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
);
|
|
4357
|
-
return this.workflowsCoreService.waitForJobCompletion(
|
|
4358
|
-
workflowId,
|
|
4359
|
-
result.jobId
|
|
4360
|
-
);
|
|
4379
|
+
async deleteSchema(schemaId) {
|
|
4380
|
+
debug("Deleting schema with ID: %s", schemaId);
|
|
4381
|
+
await this.schemasApi.v4SchemasSchemaIdDelete({
|
|
4382
|
+
schemaId
|
|
4383
|
+
});
|
|
4361
4384
|
}
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
* // Fetch first page
|
|
4371
|
-
* const firstPage = await client.extraction.fetchData({
|
|
4372
|
-
* workflowId: 'workflow-id',
|
|
4373
|
-
* page: 1,
|
|
4374
|
-
* limit: 100
|
|
4375
|
-
* });
|
|
4376
|
-
*
|
|
4377
|
-
* // Iterate through all pages
|
|
4378
|
-
* for await (const page of client.extraction.fetchDataPages({ workflowId: 'workflow-id' })) {
|
|
4379
|
-
* console.log(`Processing ${page.data.length} records`);
|
|
4380
|
-
* }
|
|
4381
|
-
* ```
|
|
4382
|
-
*/
|
|
4383
|
-
async fetchData(options) {
|
|
4384
|
-
return this.dataFetcherService.fetchData(options);
|
|
4385
|
+
};
|
|
4386
|
+
|
|
4387
|
+
// src/domains/extraction/services/entity-resolver.service.ts
|
|
4388
|
+
var ENTITY_API_ENDPOINT = "/v4/entity";
|
|
4389
|
+
var EntityResolverService = class {
|
|
4390
|
+
constructor(client) {
|
|
4391
|
+
this.client = client;
|
|
4392
|
+
this.schemasService = new SchemasService(client);
|
|
4385
4393
|
}
|
|
4386
4394
|
/**
|
|
4387
|
-
*
|
|
4388
|
-
*
|
|
4389
|
-
* @param options Options for fetching data
|
|
4390
|
-
* @returns All workflow data combined from all pages
|
|
4395
|
+
* Resolves entity and fields from the provided entity configuration
|
|
4391
4396
|
*
|
|
4392
|
-
* @
|
|
4393
|
-
*
|
|
4394
|
-
*
|
|
4395
|
-
* workflowId: 'workflow-id'
|
|
4396
|
-
* });
|
|
4397
|
-
* ```
|
|
4397
|
+
* @param entityConfig The entity configuration to resolve
|
|
4398
|
+
* @param options Additional options for AI detection
|
|
4399
|
+
* @returns Resolved entity with fields
|
|
4398
4400
|
*/
|
|
4399
|
-
async
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
|
|
4426
|
-
|
|
4427
|
-
|
|
4428
|
-
|
|
4429
|
-
|
|
4430
|
-
|
|
4401
|
+
async resolveEntity(entityConfig, options) {
|
|
4402
|
+
if (entityConfig === "ai-detection") {
|
|
4403
|
+
if (!options?.link) {
|
|
4404
|
+
throw new KadoaSdkException(ERROR_MESSAGES.LINK_REQUIRED, {
|
|
4405
|
+
code: "VALIDATION_ERROR",
|
|
4406
|
+
details: { entityConfig, options }
|
|
4407
|
+
});
|
|
4408
|
+
}
|
|
4409
|
+
const entityPrediction = await this.fetchEntityFields({
|
|
4410
|
+
link: options.link,
|
|
4411
|
+
location: options.location,
|
|
4412
|
+
navigationMode: options.navigationMode
|
|
4413
|
+
});
|
|
4414
|
+
return {
|
|
4415
|
+
entity: entityPrediction.entity,
|
|
4416
|
+
fields: entityPrediction.fields
|
|
4417
|
+
};
|
|
4418
|
+
} else if (entityConfig) {
|
|
4419
|
+
if ("schemaId" in entityConfig) {
|
|
4420
|
+
const schema = await this.schemasService.getSchema(
|
|
4421
|
+
entityConfig.schemaId
|
|
4422
|
+
);
|
|
4423
|
+
return {
|
|
4424
|
+
entity: schema.entity ?? "",
|
|
4425
|
+
fields: schema.schema
|
|
4426
|
+
};
|
|
4427
|
+
} else if ("name" in entityConfig && "fields" in entityConfig) {
|
|
4428
|
+
return {
|
|
4429
|
+
entity: entityConfig.name,
|
|
4430
|
+
fields: entityConfig.fields
|
|
4431
|
+
};
|
|
4432
|
+
}
|
|
4433
|
+
}
|
|
4434
|
+
throw new KadoaSdkException(ERROR_MESSAGES.ENTITY_INVARIANT_VIOLATION, {
|
|
4435
|
+
details: {
|
|
4436
|
+
entity: entityConfig
|
|
4437
|
+
}
|
|
4438
|
+
});
|
|
4431
4439
|
}
|
|
4432
4440
|
/**
|
|
4433
|
-
*
|
|
4434
|
-
*
|
|
4435
|
-
*
|
|
4436
|
-
* @returns Array of notification settings
|
|
4441
|
+
* Fetches entity fields dynamically from the /v4/entity endpoint.
|
|
4442
|
+
* This is a workaround implementation using native fetch since the endpoint
|
|
4443
|
+
* is not yet included in the OpenAPI specification.
|
|
4437
4444
|
*
|
|
4438
|
-
* @
|
|
4439
|
-
*
|
|
4440
|
-
* const settings = await client.extraction.getNotificationSettings('workflow-id');
|
|
4441
|
-
* ```
|
|
4445
|
+
* @param options Request options including the link to analyze
|
|
4446
|
+
* @returns EntityPrediction containing the detected entity type and fields
|
|
4442
4447
|
*/
|
|
4443
|
-
async
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
this.channelSetupService = channelSetupService;
|
|
4454
|
-
}
|
|
4455
|
-
async setupForWorkflow(requestData) {
|
|
4456
|
-
const existingSettings = await this.settingsService.listSettings({
|
|
4457
|
-
workflowId: requestData.workflowId
|
|
4448
|
+
async fetchEntityFields(options) {
|
|
4449
|
+
this.validateEntityOptions(options);
|
|
4450
|
+
const url = `${this.client.baseUrl}${ENTITY_API_ENDPOINT}`;
|
|
4451
|
+
const requestBody = options;
|
|
4452
|
+
const response = await this.client.axiosInstance.post(url, requestBody, {
|
|
4453
|
+
headers: {
|
|
4454
|
+
"Content-Type": "application/json",
|
|
4455
|
+
Accept: "application/json",
|
|
4456
|
+
"x-api-key": this.client.apiKey
|
|
4457
|
+
}
|
|
4458
4458
|
});
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
|
|
4459
|
+
const data = response.data;
|
|
4460
|
+
if (!data.success || !data.entityPrediction || data.entityPrediction.length === 0) {
|
|
4461
|
+
throw new KadoaSdkException(ERROR_MESSAGES.NO_PREDICTIONS, {
|
|
4462
|
+
code: "NOT_FOUND",
|
|
4462
4463
|
details: {
|
|
4463
|
-
|
|
4464
|
+
success: data.success,
|
|
4465
|
+
hasPredictions: !!data.entityPrediction,
|
|
4466
|
+
predictionCount: data.entityPrediction?.length || 0,
|
|
4467
|
+
link: options.link
|
|
4464
4468
|
}
|
|
4465
4469
|
});
|
|
4466
4470
|
}
|
|
4467
|
-
return
|
|
4468
|
-
workflowId: requestData.workflowId,
|
|
4469
|
-
events: requestData.events,
|
|
4470
|
-
channels: requestData.channels
|
|
4471
|
-
});
|
|
4471
|
+
return data.entityPrediction[0];
|
|
4472
4472
|
}
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4473
|
+
/**
|
|
4474
|
+
* Validates entity request options
|
|
4475
|
+
*/
|
|
4476
|
+
validateEntityOptions(options) {
|
|
4477
|
+
if (!options.link) {
|
|
4478
|
+
throw new KadoaSdkException(ERROR_MESSAGES.LINK_REQUIRED, {
|
|
4479
|
+
code: "VALIDATION_ERROR",
|
|
4480
|
+
details: { options }
|
|
4478
4481
|
});
|
|
4479
4482
|
}
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4483
|
+
}
|
|
4484
|
+
};
|
|
4485
|
+
var debug2 = logger.extraction;
|
|
4486
|
+
var SUCCESSFUL_RUN_STATES = /* @__PURE__ */ new Set(["FINISHED", "SUCCESS"]);
|
|
4487
|
+
var DEFAULT_OPTIONS = {
|
|
4488
|
+
mode: "run",
|
|
4489
|
+
pollingInterval: 5e3,
|
|
4490
|
+
maxWaitTime: 3e5,
|
|
4491
|
+
navigationMode: "single-page",
|
|
4492
|
+
location: { type: "auto" },
|
|
4493
|
+
name: "Untitled Workflow",
|
|
4494
|
+
bypassPreview: true,
|
|
4495
|
+
autoStart: true
|
|
4496
|
+
};
|
|
4497
|
+
var ExtractionService = class {
|
|
4498
|
+
constructor(workflowsCoreService, dataFetcherService, entityResolverService, notificationSetupService, notificationChannelsService, notificationSettingsService) {
|
|
4499
|
+
this.workflowsCoreService = workflowsCoreService;
|
|
4500
|
+
this.dataFetcherService = dataFetcherService;
|
|
4501
|
+
this.entityResolverService = entityResolverService;
|
|
4502
|
+
this.notificationSetupService = notificationSetupService;
|
|
4503
|
+
this.notificationChannelsService = notificationChannelsService;
|
|
4504
|
+
this.notificationSettingsService = notificationSettingsService;
|
|
4484
4505
|
}
|
|
4485
4506
|
/**
|
|
4486
|
-
*
|
|
4507
|
+
* Run an extraction workflow and wait for completion.
|
|
4487
4508
|
*/
|
|
4488
|
-
|
|
4489
|
-
return this.
|
|
4509
|
+
async run(options) {
|
|
4510
|
+
return await this.executeExtraction({ ...options, mode: "run" });
|
|
4490
4511
|
}
|
|
4491
4512
|
/**
|
|
4492
|
-
*
|
|
4513
|
+
* Submit an extraction workflow for asynchronous processing.
|
|
4493
4514
|
*/
|
|
4494
|
-
|
|
4495
|
-
return this.
|
|
4496
|
-
}
|
|
4497
|
-
};
|
|
4498
|
-
var _SchemaBuilder = class _SchemaBuilder {
|
|
4499
|
-
constructor() {
|
|
4500
|
-
this.fields = [];
|
|
4501
|
-
}
|
|
4502
|
-
entity(entityName) {
|
|
4503
|
-
this.entityName = entityName;
|
|
4504
|
-
return this;
|
|
4515
|
+
async submit(options) {
|
|
4516
|
+
return await this.executeExtraction({ ...options, mode: "submit" });
|
|
4505
4517
|
}
|
|
4506
4518
|
/**
|
|
4507
|
-
*
|
|
4508
|
-
* @param name - Field name (alphanumeric only)
|
|
4509
|
-
* @param description - Field description
|
|
4510
|
-
* @param dataType - Data type (STRING, NUMBER, BOOLEAN, etc.)
|
|
4511
|
-
* @param options - Optional field configuration
|
|
4519
|
+
* Trigger a workflow run without waiting for completion.
|
|
4512
4520
|
*/
|
|
4513
|
-
|
|
4514
|
-
this.
|
|
4515
|
-
const requiresExample = _SchemaBuilder.TYPES_REQUIRING_EXAMPLE.includes(dataType);
|
|
4516
|
-
if (requiresExample && !options?.example) {
|
|
4517
|
-
throw new KadoaSdkException(
|
|
4518
|
-
`Field "${name}" with type ${dataType} requires an example`,
|
|
4519
|
-
{ code: "VALIDATION_ERROR", details: { name, dataType } }
|
|
4520
|
-
);
|
|
4521
|
-
}
|
|
4522
|
-
this.fields.push({
|
|
4523
|
-
name,
|
|
4524
|
-
description,
|
|
4525
|
-
dataType,
|
|
4526
|
-
fieldType: "SCHEMA",
|
|
4527
|
-
example: options?.example,
|
|
4528
|
-
isKey: options?.isKey
|
|
4529
|
-
});
|
|
4530
|
-
return this;
|
|
4521
|
+
async runJob(workflowId, input) {
|
|
4522
|
+
return await this.workflowsCoreService.runWorkflow(workflowId, input);
|
|
4531
4523
|
}
|
|
4532
4524
|
/**
|
|
4533
|
-
*
|
|
4534
|
-
* @param name - Field name (alphanumeric only)
|
|
4535
|
-
* @param description - Field description
|
|
4536
|
-
* @param categories - Array of category definitions
|
|
4525
|
+
* Trigger a workflow run and wait for the job to complete.
|
|
4537
4526
|
*/
|
|
4538
|
-
|
|
4539
|
-
this.
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4527
|
+
async runJobAndWait(workflowId, input) {
|
|
4528
|
+
const result = await this.workflowsCoreService.runWorkflow(
|
|
4529
|
+
workflowId,
|
|
4530
|
+
input
|
|
4531
|
+
);
|
|
4532
|
+
return await this.workflowsCoreService.waitForJobCompletion(
|
|
4533
|
+
workflowId,
|
|
4534
|
+
result.jobId || ""
|
|
4535
|
+
);
|
|
4547
4536
|
}
|
|
4548
4537
|
/**
|
|
4549
|
-
*
|
|
4550
|
-
* @param name - Raw content format(s): "html", "markdown", or "url"
|
|
4538
|
+
* Fetch a single page of extraction data.
|
|
4551
4539
|
*/
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
for (const name2 of names) {
|
|
4555
|
-
const fieldName = `raw${esToolkit.upperFirst(esToolkit.camelCase(name2))}`;
|
|
4556
|
-
if (this.fields.some((field) => field.name === fieldName)) {
|
|
4557
|
-
continue;
|
|
4558
|
-
}
|
|
4559
|
-
this.fields.push({
|
|
4560
|
-
name: fieldName,
|
|
4561
|
-
description: `Raw page content in ${name2.toUpperCase()} format`,
|
|
4562
|
-
fieldType: "METADATA",
|
|
4563
|
-
metadataKey: name2
|
|
4564
|
-
});
|
|
4565
|
-
}
|
|
4566
|
-
return this;
|
|
4567
|
-
}
|
|
4568
|
-
build() {
|
|
4569
|
-
if (!this.entityName) {
|
|
4570
|
-
throw new KadoaSdkException("Entity name is required", {
|
|
4571
|
-
code: "VALIDATION_ERROR",
|
|
4572
|
-
details: { entityName: this.entityName }
|
|
4573
|
-
});
|
|
4574
|
-
}
|
|
4575
|
-
return {
|
|
4576
|
-
entityName: this.entityName,
|
|
4577
|
-
fields: this.fields
|
|
4578
|
-
};
|
|
4579
|
-
}
|
|
4580
|
-
validateFieldName(name) {
|
|
4581
|
-
if (!_SchemaBuilder.FIELD_NAME_PATTERN.test(name)) {
|
|
4582
|
-
throw new KadoaSdkException(
|
|
4583
|
-
`Field name "${name}" must be alphanumeric only (no underscores or special characters)`,
|
|
4584
|
-
{
|
|
4585
|
-
code: "VALIDATION_ERROR",
|
|
4586
|
-
details: { name, pattern: "^[A-Za-z0-9]+$" }
|
|
4587
|
-
}
|
|
4588
|
-
);
|
|
4589
|
-
}
|
|
4590
|
-
const lowerName = name.toLowerCase();
|
|
4591
|
-
if (this.fields.some((f) => f.name.toLowerCase() === lowerName)) {
|
|
4592
|
-
throw new KadoaSdkException(`Duplicate field name: "${name}"`, {
|
|
4593
|
-
code: "VALIDATION_ERROR",
|
|
4594
|
-
details: { name }
|
|
4595
|
-
});
|
|
4596
|
-
}
|
|
4597
|
-
}
|
|
4598
|
-
};
|
|
4599
|
-
_SchemaBuilder.FIELD_NAME_PATTERN = /^[A-Za-z0-9]+$/;
|
|
4600
|
-
_SchemaBuilder.TYPES_REQUIRING_EXAMPLE = [
|
|
4601
|
-
"STRING",
|
|
4602
|
-
"IMAGE",
|
|
4603
|
-
"LINK",
|
|
4604
|
-
"OBJECT",
|
|
4605
|
-
"ARRAY"
|
|
4606
|
-
];
|
|
4607
|
-
var SchemaBuilder = _SchemaBuilder;
|
|
4608
|
-
|
|
4609
|
-
// src/modules/schemas.module.ts
|
|
4610
|
-
var SchemaBuilderWithCreate = class extends SchemaBuilder {
|
|
4611
|
-
constructor(entityName, service) {
|
|
4612
|
-
super();
|
|
4613
|
-
this.service = service;
|
|
4614
|
-
this.entity(entityName);
|
|
4540
|
+
async fetchData(options) {
|
|
4541
|
+
return await this.dataFetcherService.fetchData(options);
|
|
4615
4542
|
}
|
|
4616
4543
|
/**
|
|
4617
|
-
*
|
|
4618
|
-
* @param name - Optional schema name (defaults to entity name)
|
|
4619
|
-
* @returns Promise resolving to the created schema
|
|
4544
|
+
* Fetch all extraction data across all pages.
|
|
4620
4545
|
*/
|
|
4621
|
-
async
|
|
4622
|
-
|
|
4623
|
-
return this.service.createSchema({
|
|
4624
|
-
name: name || built.entityName,
|
|
4625
|
-
entity: built.entityName,
|
|
4626
|
-
fields: built.fields
|
|
4627
|
-
});
|
|
4628
|
-
}
|
|
4629
|
-
};
|
|
4630
|
-
var SchemasModule = class {
|
|
4631
|
-
constructor(service) {
|
|
4632
|
-
this.service = service;
|
|
4546
|
+
async fetchAllData(options) {
|
|
4547
|
+
return await this.dataFetcherService.fetchAllData(options);
|
|
4633
4548
|
}
|
|
4634
4549
|
/**
|
|
4635
|
-
*
|
|
4636
|
-
* @param entityName - The name of the entity this schema represents
|
|
4637
|
-
* @returns A new SchemaBuilder instance with the entity name already set
|
|
4638
|
-
* @example Build then create
|
|
4639
|
-
* ```typescript
|
|
4640
|
-
* const schema = kadoa.schema.builder("Product")
|
|
4641
|
-
* .field("title", "Product name", "STRING", { example: "iPhone 15" })
|
|
4642
|
-
* .field("price", "Product price", "NUMBER")
|
|
4643
|
-
* .build();
|
|
4644
|
-
*
|
|
4645
|
-
* await kadoa.schema.create(schema);
|
|
4646
|
-
* ```
|
|
4647
|
-
*
|
|
4648
|
-
* @example Fluent chain with create
|
|
4649
|
-
* ```typescript
|
|
4650
|
-
* const schema = await kadoa.schema.builder("Product")
|
|
4651
|
-
* .field("title", "Product name", "STRING", { example: "iPhone 15" })
|
|
4652
|
-
* .field("price", "Product price", "NUMBER")
|
|
4653
|
-
* .create("Product Schema");
|
|
4654
|
-
* ```
|
|
4655
|
-
*/
|
|
4656
|
-
builder(entityName) {
|
|
4657
|
-
return new SchemaBuilderWithCreate(entityName, this.service);
|
|
4658
|
-
}
|
|
4659
|
-
/**
|
|
4660
|
-
* Get a schema by ID
|
|
4661
|
-
*/
|
|
4662
|
-
async get(schemaId) {
|
|
4663
|
-
return this.service.getSchema(schemaId);
|
|
4664
|
-
}
|
|
4665
|
-
/**
|
|
4666
|
-
* List all schemas
|
|
4667
|
-
*/
|
|
4668
|
-
async list() {
|
|
4669
|
-
return this.service.listSchemas();
|
|
4670
|
-
}
|
|
4671
|
-
/**
|
|
4672
|
-
* Create a new schema from a body
|
|
4673
|
-
*/
|
|
4674
|
-
async create(body) {
|
|
4675
|
-
return this.service.createSchema(body);
|
|
4676
|
-
}
|
|
4677
|
-
/**
|
|
4678
|
-
* Update an existing schema
|
|
4679
|
-
*/
|
|
4680
|
-
async update(schemaId, body) {
|
|
4681
|
-
return this.service.updateSchema(schemaId, body);
|
|
4682
|
-
}
|
|
4683
|
-
/**
|
|
4684
|
-
* Delete a schema
|
|
4685
|
-
*/
|
|
4686
|
-
async delete(schemaId) {
|
|
4687
|
-
return this.service.deleteSchema(schemaId);
|
|
4688
|
-
}
|
|
4689
|
-
};
|
|
4690
|
-
|
|
4691
|
-
// src/modules/user.module.ts
|
|
4692
|
-
var UserModule = class {
|
|
4693
|
-
constructor(userService) {
|
|
4694
|
-
this.userService = userService;
|
|
4695
|
-
}
|
|
4696
|
-
/**
|
|
4697
|
-
* Get the underlying UserService instance
|
|
4698
|
-
* @returns UserService instance
|
|
4699
|
-
*/
|
|
4700
|
-
get service() {
|
|
4701
|
-
return this.userService;
|
|
4702
|
-
}
|
|
4703
|
-
/**
|
|
4704
|
-
* Get current user details
|
|
4705
|
-
* @returns KadoaUser details
|
|
4706
|
-
*/
|
|
4707
|
-
async getCurrentUser() {
|
|
4708
|
-
return this.userService.getCurrentUser();
|
|
4709
|
-
}
|
|
4710
|
-
};
|
|
4711
|
-
|
|
4712
|
-
// src/modules/validation.module.ts
|
|
4713
|
-
var ValidationModule = class {
|
|
4714
|
-
constructor(coreService, rulesService) {
|
|
4715
|
-
this.coreService = coreService;
|
|
4716
|
-
this.rulesService = rulesService;
|
|
4717
|
-
}
|
|
4718
|
-
listRules(options) {
|
|
4719
|
-
return this.rulesService.listRules(options);
|
|
4720
|
-
}
|
|
4721
|
-
getRuleByName(name) {
|
|
4722
|
-
return this.rulesService.getRuleByName(name);
|
|
4723
|
-
}
|
|
4724
|
-
createRule(data) {
|
|
4725
|
-
return this.rulesService.createRule(data);
|
|
4726
|
-
}
|
|
4727
|
-
generateRule(data) {
|
|
4728
|
-
return this.rulesService.generateRule(data);
|
|
4729
|
-
}
|
|
4730
|
-
generateRules(data) {
|
|
4731
|
-
return this.rulesService.generateRules(data);
|
|
4732
|
-
}
|
|
4733
|
-
bulkApproveRules(data) {
|
|
4734
|
-
return this.rulesService.bulkApproveRules(data);
|
|
4735
|
-
}
|
|
4736
|
-
bulkDeleteRules(data) {
|
|
4737
|
-
return this.rulesService.bulkDeleteRules(data);
|
|
4738
|
-
}
|
|
4739
|
-
deleteAllRules(data) {
|
|
4740
|
-
return this.rulesService.deleteAllRules(data);
|
|
4741
|
-
}
|
|
4742
|
-
listWorkflowValidations(workflowId, jobId) {
|
|
4743
|
-
return this.coreService.listWorkflowValidations({ workflowId, jobId });
|
|
4744
|
-
}
|
|
4745
|
-
scheduleValidation(workflowId, jobId) {
|
|
4746
|
-
return this.coreService.scheduleValidation(workflowId, jobId);
|
|
4747
|
-
}
|
|
4748
|
-
waitUntilCompleted(validationId, options) {
|
|
4749
|
-
return this.coreService.waitUntilCompleted(validationId, options);
|
|
4750
|
-
}
|
|
4751
|
-
getValidationDetails(validationId) {
|
|
4752
|
-
return this.coreService.getValidationDetails(validationId);
|
|
4753
|
-
}
|
|
4754
|
-
getLatestValidation(workflowId, jobId) {
|
|
4755
|
-
return this.coreService.getLatestValidation(workflowId, jobId);
|
|
4756
|
-
}
|
|
4757
|
-
getValidationAnomalies(validationId) {
|
|
4758
|
-
return this.coreService.getValidationAnomalies(validationId);
|
|
4759
|
-
}
|
|
4760
|
-
getValidationAnomaliesByRule(validationId, ruleName) {
|
|
4761
|
-
return this.coreService.getValidationAnomaliesByRule(
|
|
4762
|
-
validationId,
|
|
4763
|
-
ruleName
|
|
4764
|
-
);
|
|
4765
|
-
}
|
|
4766
|
-
toggleValidationEnabled(workflowId) {
|
|
4767
|
-
return this.coreService.toggleValidationEnabled(workflowId);
|
|
4768
|
-
}
|
|
4769
|
-
};
|
|
4770
|
-
|
|
4771
|
-
// src/modules/workflows.module.ts
|
|
4772
|
-
var WorkflowsModule = class {
|
|
4773
|
-
constructor(core) {
|
|
4774
|
-
this.core = core;
|
|
4775
|
-
}
|
|
4776
|
-
async get(workflowId) {
|
|
4777
|
-
return this.core.get(workflowId);
|
|
4778
|
-
}
|
|
4779
|
-
async list(filters) {
|
|
4780
|
-
return this.core.list(filters);
|
|
4781
|
-
}
|
|
4782
|
-
async getByName(name) {
|
|
4783
|
-
return this.core.getByName(name);
|
|
4784
|
-
}
|
|
4785
|
-
async create(input) {
|
|
4786
|
-
return this.core.create(input);
|
|
4787
|
-
}
|
|
4788
|
-
async cancel(workflowId) {
|
|
4789
|
-
return this.core.cancel(workflowId);
|
|
4790
|
-
}
|
|
4791
|
-
async approve(workflowId) {
|
|
4792
|
-
return this.core.resume(workflowId);
|
|
4793
|
-
}
|
|
4794
|
-
async resume(workflowId) {
|
|
4795
|
-
return this.core.resume(workflowId);
|
|
4796
|
-
}
|
|
4797
|
-
async wait(workflowId, options) {
|
|
4798
|
-
return this.core.wait(workflowId, options);
|
|
4799
|
-
}
|
|
4800
|
-
/**
|
|
4801
|
-
* Get job status directly without polling workflow details
|
|
4550
|
+
* Iterate through extraction data pages.
|
|
4802
4551
|
*/
|
|
4803
|
-
|
|
4804
|
-
return this.
|
|
4552
|
+
fetchDataPages(options) {
|
|
4553
|
+
return this.dataFetcherService.fetchDataPages(options);
|
|
4805
4554
|
}
|
|
4806
4555
|
/**
|
|
4807
|
-
*
|
|
4556
|
+
* List notification channels for a workflow.
|
|
4808
4557
|
*/
|
|
4809
|
-
async
|
|
4810
|
-
return this.
|
|
4811
|
-
}
|
|
4812
|
-
};
|
|
4813
|
-
|
|
4814
|
-
// src/internal/domains/user/user.service.ts
|
|
4815
|
-
var UserService = class {
|
|
4816
|
-
constructor(client) {
|
|
4817
|
-
this.client = client;
|
|
4558
|
+
async getNotificationChannels(workflowId) {
|
|
4559
|
+
return await this.notificationChannelsService.listChannels({ workflowId });
|
|
4818
4560
|
}
|
|
4819
4561
|
/**
|
|
4820
|
-
*
|
|
4821
|
-
* @returns User details
|
|
4562
|
+
* List notification settings for a workflow.
|
|
4822
4563
|
*/
|
|
4823
|
-
async
|
|
4824
|
-
|
|
4825
|
-
baseURL: this.client.baseUrl,
|
|
4826
|
-
headers: {
|
|
4827
|
-
"x-api-key": this.client.apiKey,
|
|
4828
|
-
"Content-Type": "application/json"
|
|
4829
|
-
}
|
|
4830
|
-
});
|
|
4831
|
-
const userData = response.data;
|
|
4832
|
-
if (!userData || !userData.userId) {
|
|
4833
|
-
throw new KadoaSdkException("Invalid user data received");
|
|
4834
|
-
}
|
|
4835
|
-
return {
|
|
4836
|
-
userId: userData.userId,
|
|
4837
|
-
email: userData.email,
|
|
4838
|
-
featureFlags: userData.featureFlags || []
|
|
4839
|
-
};
|
|
4840
|
-
}
|
|
4841
|
-
};
|
|
4842
|
-
var debug2 = logger.extraction;
|
|
4843
|
-
var SUCCESSFUL_RUN_STATES = /* @__PURE__ */ new Set(["FINISHED", "SUCCESS"]);
|
|
4844
|
-
var DEFAULT_OPTIONS = {
|
|
4845
|
-
mode: "run",
|
|
4846
|
-
pollingInterval: 5e3,
|
|
4847
|
-
maxWaitTime: 3e5,
|
|
4848
|
-
navigationMode: "single-page",
|
|
4849
|
-
location: { type: "auto" },
|
|
4850
|
-
name: "Untitled Workflow",
|
|
4851
|
-
bypassPreview: true,
|
|
4852
|
-
autoStart: true
|
|
4853
|
-
};
|
|
4854
|
-
var ExtractionService = class {
|
|
4855
|
-
constructor(workflowsCoreService, dataFetcherService, entityResolverService, notificationSetupService) {
|
|
4856
|
-
this.workflowsCoreService = workflowsCoreService;
|
|
4857
|
-
this.dataFetcherService = dataFetcherService;
|
|
4858
|
-
this.entityResolverService = entityResolverService;
|
|
4859
|
-
this.notificationSetupService = notificationSetupService;
|
|
4564
|
+
async getNotificationSettings(workflowId) {
|
|
4565
|
+
return await this.notificationSettingsService.listSettings({ workflowId });
|
|
4860
4566
|
}
|
|
4861
|
-
/**
|
|
4862
|
-
* execute extraction workflow
|
|
4863
|
-
*/
|
|
4864
4567
|
async executeExtraction(options) {
|
|
4865
4568
|
this.validateOptions(options);
|
|
4866
4569
|
const config = esToolkit.merge(
|
|
@@ -4983,96 +4686,270 @@ var ExtractionService = class {
|
|
|
4983
4686
|
return runState ? SUCCESSFUL_RUN_STATES.has(runState.toUpperCase()) : false;
|
|
4984
4687
|
}
|
|
4985
4688
|
};
|
|
4986
|
-
var
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
recipients: zod.z.array(zod.z.email()).min(1, "Recipients are required for email channel"),
|
|
4994
|
-
from: zod.z.email().refine(
|
|
4995
|
-
(email) => email.endsWith("@kadoa.com"),
|
|
4996
|
-
"From email address must end with @kadoa.com"
|
|
4997
|
-
).optional()
|
|
4998
|
-
});
|
|
4999
|
-
var _NotificationChannelsService = class _NotificationChannelsService {
|
|
5000
|
-
constructor(notificationsApi, userService) {
|
|
5001
|
-
this.api = notificationsApi;
|
|
5002
|
-
this.userService = userService;
|
|
4689
|
+
var debug3 = logger.extraction;
|
|
4690
|
+
var ExtractionBuilderService = class {
|
|
4691
|
+
constructor(workflowsCoreService, entityResolverService, dataFetcherService, notificationSetupService) {
|
|
4692
|
+
this.workflowsCoreService = workflowsCoreService;
|
|
4693
|
+
this.entityResolverService = entityResolverService;
|
|
4694
|
+
this.dataFetcherService = dataFetcherService;
|
|
4695
|
+
this.notificationSetupService = notificationSetupService;
|
|
5003
4696
|
}
|
|
5004
|
-
|
|
5005
|
-
|
|
5006
|
-
|
|
5007
|
-
if (!data) {
|
|
5008
|
-
throw KadoaHttpException.wrap(response, {
|
|
5009
|
-
message: "Failed to list channels"
|
|
5010
|
-
});
|
|
5011
|
-
}
|
|
5012
|
-
return data;
|
|
4697
|
+
get options() {
|
|
4698
|
+
assert__default.default(this._options, "Options are not set");
|
|
4699
|
+
return this._options;
|
|
5013
4700
|
}
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
* This is useful for finding workspace-level channels like WebSocket channels
|
|
5017
|
-
* that might not be associated with a specific workflow
|
|
5018
|
-
*/
|
|
5019
|
-
async listAllChannels(workflowId) {
|
|
5020
|
-
if (!workflowId) {
|
|
5021
|
-
return this.listChannels({});
|
|
5022
|
-
}
|
|
5023
|
-
const [workflowChannels, workspaceChannels] = await Promise.all([
|
|
5024
|
-
this.listChannels({ workflowId }),
|
|
5025
|
-
this.listChannels({})
|
|
5026
|
-
]);
|
|
5027
|
-
const allChannels = [...workflowChannels];
|
|
5028
|
-
workspaceChannels.forEach((channel) => {
|
|
5029
|
-
if (!allChannels.find((c) => c.id === channel.id)) {
|
|
5030
|
-
allChannels.push(channel);
|
|
5031
|
-
}
|
|
5032
|
-
});
|
|
5033
|
-
return allChannels;
|
|
4701
|
+
get notificationOptions() {
|
|
4702
|
+
return this._notificationOptions;
|
|
5034
4703
|
}
|
|
5035
|
-
|
|
5036
|
-
|
|
5037
|
-
channelId
|
|
5038
|
-
});
|
|
5039
|
-
if (response.status !== 200) {
|
|
5040
|
-
throw KadoaHttpException.wrap(response, {
|
|
5041
|
-
message: "Failed to delete channel"
|
|
5042
|
-
});
|
|
5043
|
-
}
|
|
4704
|
+
get monitoringOptions() {
|
|
4705
|
+
return this._monitoringOptions;
|
|
5044
4706
|
}
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
|
|
5052
|
-
|
|
5053
|
-
|
|
5054
|
-
|
|
5055
|
-
|
|
5056
|
-
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
|
|
4707
|
+
get workflowId() {
|
|
4708
|
+
assert__default.default(this._workflowId, "Workflow ID is not set");
|
|
4709
|
+
return this._workflowId;
|
|
4710
|
+
}
|
|
4711
|
+
get jobId() {
|
|
4712
|
+
assert__default.default(this._jobId, "Job ID is not set");
|
|
4713
|
+
return this._jobId;
|
|
4714
|
+
}
|
|
4715
|
+
extract({
|
|
4716
|
+
urls,
|
|
4717
|
+
name,
|
|
4718
|
+
description,
|
|
4719
|
+
navigationMode,
|
|
4720
|
+
extraction
|
|
4721
|
+
}) {
|
|
4722
|
+
let entity = "ai-detection";
|
|
4723
|
+
if (extraction) {
|
|
4724
|
+
const result = extraction(new SchemaBuilder());
|
|
4725
|
+
if ("schemaId" in result) {
|
|
4726
|
+
entity = { schemaId: result.schemaId };
|
|
4727
|
+
} else {
|
|
4728
|
+
const builtSchema = result.build();
|
|
4729
|
+
entity = { name: builtSchema.entityName, fields: builtSchema.fields };
|
|
5062
4730
|
}
|
|
5063
|
-
return data;
|
|
5064
4731
|
}
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
4732
|
+
this._options = {
|
|
4733
|
+
urls,
|
|
4734
|
+
name,
|
|
4735
|
+
description,
|
|
4736
|
+
navigationMode: navigationMode || "single-page",
|
|
4737
|
+
entity,
|
|
4738
|
+
bypassPreview: false
|
|
4739
|
+
};
|
|
4740
|
+
return this;
|
|
5068
4741
|
}
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
|
|
4742
|
+
withNotifications(options) {
|
|
4743
|
+
this._notificationOptions = options;
|
|
4744
|
+
return this;
|
|
4745
|
+
}
|
|
4746
|
+
withMonitoring(options) {
|
|
4747
|
+
this._monitoringOptions = options;
|
|
4748
|
+
return this;
|
|
4749
|
+
}
|
|
4750
|
+
bypassPreview() {
|
|
4751
|
+
assert__default.default(this._options, "Options are not set");
|
|
4752
|
+
this._options.bypassPreview = true;
|
|
4753
|
+
return this;
|
|
4754
|
+
}
|
|
4755
|
+
setInterval(options) {
|
|
4756
|
+
assert__default.default(this._options, "Options are not set");
|
|
4757
|
+
if ("interval" in options) {
|
|
4758
|
+
this._options.interval = options.interval;
|
|
4759
|
+
} else {
|
|
4760
|
+
this._options.interval = "CUSTOM";
|
|
4761
|
+
this._options.schedules = options.schedules;
|
|
4762
|
+
}
|
|
4763
|
+
return this;
|
|
4764
|
+
}
|
|
4765
|
+
setLocation(options) {
|
|
4766
|
+
assert__default.default(this._options, "Options are not set");
|
|
4767
|
+
this._options.location = options;
|
|
4768
|
+
return this;
|
|
4769
|
+
}
|
|
4770
|
+
async create() {
|
|
4771
|
+
assert__default.default(this._options, "Options are not set");
|
|
4772
|
+
const { urls, name, description, navigationMode, entity } = this.options;
|
|
4773
|
+
const resolvedEntity = typeof entity === "object" && "schemaId" in entity ? void 0 : await this.entityResolverService.resolveEntity(entity, {
|
|
4774
|
+
link: urls[0],
|
|
4775
|
+
location: this._options.location,
|
|
4776
|
+
navigationMode
|
|
4777
|
+
});
|
|
4778
|
+
if (!resolvedEntity) {
|
|
4779
|
+
throw new KadoaSdkException(ERROR_MESSAGES.ENTITY_FETCH_FAILED, {
|
|
4780
|
+
code: "VALIDATION_ERROR",
|
|
4781
|
+
details: { entity }
|
|
4782
|
+
});
|
|
4783
|
+
}
|
|
4784
|
+
const workflow = await this.workflowsCoreService.create({
|
|
4785
|
+
urls,
|
|
4786
|
+
name,
|
|
4787
|
+
description,
|
|
4788
|
+
navigationMode,
|
|
4789
|
+
monitoring: this._monitoringOptions,
|
|
4790
|
+
schemaId: typeof entity === "object" && "schemaId" in entity ? entity.schemaId : void 0,
|
|
4791
|
+
entity: resolvedEntity.entity,
|
|
4792
|
+
fields: resolvedEntity.fields,
|
|
4793
|
+
autoStart: false,
|
|
4794
|
+
interval: this._options.interval,
|
|
4795
|
+
schedules: this._options.schedules
|
|
4796
|
+
});
|
|
4797
|
+
if (this._notificationOptions) {
|
|
4798
|
+
await this.notificationSetupService.setup({
|
|
4799
|
+
...this._notificationOptions,
|
|
4800
|
+
workflowId: workflow.id
|
|
4801
|
+
});
|
|
4802
|
+
}
|
|
4803
|
+
this._workflowId = workflow.id;
|
|
4804
|
+
return this;
|
|
4805
|
+
}
|
|
4806
|
+
async run(options) {
|
|
4807
|
+
assert__default.default(this._options, "Options are not set");
|
|
4808
|
+
assert__default.default(this._workflowId, "Workflow ID is not set");
|
|
4809
|
+
const startedJob = await this.workflowsCoreService.runWorkflow(
|
|
4810
|
+
this._workflowId,
|
|
4811
|
+
{ variables: options?.variables, limit: options?.limit }
|
|
4812
|
+
);
|
|
4813
|
+
assert__default.default(startedJob.jobId, "Job ID is not set");
|
|
4814
|
+
debug3("Job started: %O", startedJob);
|
|
4815
|
+
this._jobId = startedJob.jobId;
|
|
4816
|
+
const finishedJob = await this.workflowsCoreService.waitForJobCompletion(
|
|
4817
|
+
this._workflowId,
|
|
4818
|
+
startedJob.jobId
|
|
4819
|
+
);
|
|
4820
|
+
debug3("Job finished: %O", finishedJob);
|
|
4821
|
+
return this;
|
|
4822
|
+
}
|
|
4823
|
+
async submit(options) {
|
|
4824
|
+
assert__default.default(this._options, "Options are not set");
|
|
4825
|
+
assert__default.default(this._workflowId, "Workflow ID is not set");
|
|
4826
|
+
const submittedJob = await this.workflowsCoreService.runWorkflow(
|
|
4827
|
+
this._workflowId,
|
|
4828
|
+
{ variables: options?.variables, limit: options?.limit }
|
|
4829
|
+
);
|
|
4830
|
+
assert__default.default(submittedJob.jobId, "Job ID is not set");
|
|
4831
|
+
debug3("Job submitted: %O", submittedJob);
|
|
4832
|
+
this._jobId = submittedJob.jobId;
|
|
4833
|
+
return {
|
|
4834
|
+
workflowId: this._workflowId,
|
|
4835
|
+
jobId: this._jobId
|
|
4836
|
+
};
|
|
4837
|
+
}
|
|
4838
|
+
async fetchData(options) {
|
|
4839
|
+
assert__default.default(this._workflowId, "Workflow ID is not set");
|
|
4840
|
+
assert__default.default(this._jobId, "Job ID is not set");
|
|
4841
|
+
return this.dataFetcherService.fetchData({
|
|
4842
|
+
workflowId: this._workflowId,
|
|
4843
|
+
runId: this._jobId,
|
|
4844
|
+
page: options.page ?? 1,
|
|
4845
|
+
limit: options.limit ?? 100,
|
|
4846
|
+
...options
|
|
4847
|
+
});
|
|
4848
|
+
}
|
|
4849
|
+
async fetchAllData(options) {
|
|
4850
|
+
assert__default.default(this._jobId, "Job ID is not set");
|
|
4851
|
+
assert__default.default(this._workflowId, "Workflow ID is not set");
|
|
4852
|
+
return this.dataFetcherService.fetchAllData({
|
|
4853
|
+
workflowId: this._workflowId,
|
|
4854
|
+
runId: this._jobId,
|
|
4855
|
+
...options
|
|
4856
|
+
});
|
|
4857
|
+
}
|
|
4858
|
+
};
|
|
4859
|
+
|
|
4860
|
+
// src/domains/notifications/notifications.acl.ts
|
|
4861
|
+
var NotificationChannelType = {
|
|
4862
|
+
EMAIL: "EMAIL",
|
|
4863
|
+
SLACK: "SLACK",
|
|
4864
|
+
WEBHOOK: "WEBHOOK",
|
|
4865
|
+
WEBSOCKET: "WEBSOCKET"
|
|
4866
|
+
};
|
|
4867
|
+
|
|
4868
|
+
// src/domains/notifications/notification-channels.service.ts
|
|
4869
|
+
var emailChannelConfigSchema = zod.z.object({
|
|
4870
|
+
recipients: zod.z.array(zod.z.email()).min(1, "Recipients are required for email channel"),
|
|
4871
|
+
from: zod.z.email().refine(
|
|
4872
|
+
(email) => email.endsWith("@kadoa.com"),
|
|
4873
|
+
"From email address must end with @kadoa.com"
|
|
4874
|
+
).optional()
|
|
4875
|
+
});
|
|
4876
|
+
var _NotificationChannelsService = class _NotificationChannelsService {
|
|
4877
|
+
constructor(notificationsApi, userService) {
|
|
4878
|
+
this.api = notificationsApi;
|
|
4879
|
+
this.userService = userService;
|
|
4880
|
+
}
|
|
4881
|
+
async listChannels(filters) {
|
|
4882
|
+
const response = await this.api.v5NotificationsChannelsGet(filters);
|
|
4883
|
+
const data = response.data.data?.channels;
|
|
4884
|
+
if (!data) {
|
|
4885
|
+
throw KadoaHttpException.wrap(response, {
|
|
4886
|
+
message: "Failed to list channels"
|
|
4887
|
+
});
|
|
4888
|
+
}
|
|
4889
|
+
return data;
|
|
4890
|
+
}
|
|
4891
|
+
/**
|
|
4892
|
+
* List all channels (both workflow-specific and workspace-level)
|
|
4893
|
+
* This is useful for finding workspace-level channels like WebSocket channels
|
|
4894
|
+
* that might not be associated with a specific workflow
|
|
4895
|
+
*/
|
|
4896
|
+
async listAllChannels(workflowId) {
|
|
4897
|
+
if (!workflowId) {
|
|
4898
|
+
return this.listChannels({});
|
|
4899
|
+
}
|
|
4900
|
+
const [workflowChannels, workspaceChannels] = await Promise.all([
|
|
4901
|
+
this.listChannels({ workflowId }),
|
|
4902
|
+
this.listChannels({})
|
|
4903
|
+
]);
|
|
4904
|
+
const allChannels = [...workflowChannels];
|
|
4905
|
+
workspaceChannels.forEach((channel) => {
|
|
4906
|
+
if (!allChannels.find((c) => c.id === channel.id)) {
|
|
4907
|
+
allChannels.push(channel);
|
|
4908
|
+
}
|
|
4909
|
+
});
|
|
4910
|
+
return allChannels;
|
|
4911
|
+
}
|
|
4912
|
+
async deleteChannel(channelId) {
|
|
4913
|
+
const response = await this.api.v5NotificationsChannelsChannelIdDelete({
|
|
4914
|
+
channelId
|
|
4915
|
+
});
|
|
4916
|
+
if (response.status !== 200) {
|
|
4917
|
+
throw KadoaHttpException.wrap(response, {
|
|
4918
|
+
message: "Failed to delete channel"
|
|
4919
|
+
});
|
|
4920
|
+
}
|
|
4921
|
+
}
|
|
4922
|
+
async createChannel(type, config) {
|
|
4923
|
+
const payload = await this.buildPayload(
|
|
4924
|
+
esToolkit.merge(config || {}, {
|
|
4925
|
+
name: _NotificationChannelsService.DEFAULT_CHANNEL_NAME,
|
|
4926
|
+
channelType: type,
|
|
4927
|
+
config: {}
|
|
4928
|
+
})
|
|
4929
|
+
);
|
|
4930
|
+
const response = await this.api.v5NotificationsChannelsPost({
|
|
4931
|
+
v5NotificationsChannelsPostRequest: payload
|
|
4932
|
+
});
|
|
4933
|
+
if (response.status === 201) {
|
|
4934
|
+
const data = response.data.data?.channel;
|
|
4935
|
+
if (!data) {
|
|
4936
|
+
throw KadoaHttpException.wrap(response, {
|
|
4937
|
+
message: "Failed to create default channels"
|
|
4938
|
+
});
|
|
4939
|
+
}
|
|
4940
|
+
return data;
|
|
4941
|
+
}
|
|
4942
|
+
throw KadoaHttpException.wrap(response, {
|
|
4943
|
+
message: "Failed to create default channels"
|
|
4944
|
+
});
|
|
4945
|
+
}
|
|
4946
|
+
async buildPayload(request) {
|
|
4947
|
+
let config;
|
|
4948
|
+
switch (request.channelType) {
|
|
4949
|
+
case NotificationChannelType.EMAIL:
|
|
4950
|
+
config = await this.buildEmailChannelConfig(
|
|
4951
|
+
request.config
|
|
4952
|
+
);
|
|
5076
4953
|
break;
|
|
5077
4954
|
case NotificationChannelType.SLACK:
|
|
5078
4955
|
config = await this.buildSlackChannelConfig(
|
|
@@ -5133,7 +5010,7 @@ var _NotificationChannelsService = class _NotificationChannelsService {
|
|
|
5133
5010
|
_NotificationChannelsService.DEFAULT_CHANNEL_NAME = "default";
|
|
5134
5011
|
var NotificationChannelsService = _NotificationChannelsService;
|
|
5135
5012
|
|
|
5136
|
-
// src/
|
|
5013
|
+
// src/domains/notifications/notification-settings.service.ts
|
|
5137
5014
|
var NotificationSettingsService = class {
|
|
5138
5015
|
constructor(notificationsApi) {
|
|
5139
5016
|
this.api = notificationsApi;
|
|
@@ -5168,410 +5045,56 @@ var NotificationSettingsService = class {
|
|
|
5168
5045
|
settingsId
|
|
5169
5046
|
});
|
|
5170
5047
|
if (response.status !== 200) {
|
|
5171
|
-
throw KadoaHttpException.wrap(response, {
|
|
5172
|
-
message: "Failed to delete notification settings"
|
|
5173
|
-
});
|
|
5174
|
-
}
|
|
5175
|
-
}
|
|
5176
|
-
};
|
|
5177
|
-
|
|
5178
|
-
// src/internal/runtime/pagination/paginator.ts
|
|
5179
|
-
var PagedIterator = class {
|
|
5180
|
-
constructor(fetchPage) {
|
|
5181
|
-
this.fetchPage = fetchPage;
|
|
5182
|
-
}
|
|
5183
|
-
/**
|
|
5184
|
-
* Fetch all items across all pages
|
|
5185
|
-
* @param options Base options (page will be overridden)
|
|
5186
|
-
* @returns Array of all items
|
|
5187
|
-
*/
|
|
5188
|
-
async fetchAll(options = {}) {
|
|
5189
|
-
const allItems = [];
|
|
5190
|
-
let currentPage = 1;
|
|
5191
|
-
let hasMore = true;
|
|
5192
|
-
while (hasMore) {
|
|
5193
|
-
const result = await this.fetchPage({ ...options, page: currentPage });
|
|
5194
|
-
allItems.push(...result.data);
|
|
5195
|
-
const pagination = result.pagination;
|
|
5196
|
-
hasMore = pagination.page !== void 0 && pagination.totalPages !== void 0 && pagination.page < pagination.totalPages;
|
|
5197
|
-
currentPage++;
|
|
5198
|
-
}
|
|
5199
|
-
return allItems;
|
|
5200
|
-
}
|
|
5201
|
-
/**
|
|
5202
|
-
* Create an async iterator for pages
|
|
5203
|
-
* @param options Base options (page will be overridden)
|
|
5204
|
-
* @returns Async generator that yields pages
|
|
5205
|
-
*/
|
|
5206
|
-
async *pages(options = {}) {
|
|
5207
|
-
let currentPage = 1;
|
|
5208
|
-
let hasMore = true;
|
|
5209
|
-
while (hasMore) {
|
|
5210
|
-
const result = await this.fetchPage({ ...options, page: currentPage });
|
|
5211
|
-
yield result;
|
|
5212
|
-
const pagination = result.pagination;
|
|
5213
|
-
hasMore = pagination.page !== void 0 && pagination.totalPages !== void 0 && pagination.page < pagination.totalPages;
|
|
5214
|
-
currentPage++;
|
|
5215
|
-
}
|
|
5216
|
-
}
|
|
5217
|
-
/**
|
|
5218
|
-
* Create an async iterator for individual items
|
|
5219
|
-
* @param options Base options (page will be overridden)
|
|
5220
|
-
* @returns Async generator that yields items
|
|
5221
|
-
*/
|
|
5222
|
-
async *items(options = {}) {
|
|
5223
|
-
for await (const page of this.pages(options)) {
|
|
5224
|
-
for (const item of page.data) {
|
|
5225
|
-
yield item;
|
|
5226
|
-
}
|
|
5227
|
-
}
|
|
5228
|
-
}
|
|
5229
|
-
};
|
|
5230
|
-
|
|
5231
|
-
// src/internal/domains/extraction/services/data-fetcher.service.ts
|
|
5232
|
-
var DataFetcherService = class {
|
|
5233
|
-
constructor(workflowsApi) {
|
|
5234
|
-
this.workflowsApi = workflowsApi;
|
|
5235
|
-
this.defaultLimit = 100;
|
|
5236
|
-
}
|
|
5237
|
-
/**
|
|
5238
|
-
* Fetch a page of workflow data
|
|
5239
|
-
*/
|
|
5240
|
-
async fetchData(options) {
|
|
5241
|
-
const response = await this.workflowsApi.v4WorkflowsWorkflowIdDataGet({
|
|
5242
|
-
...options,
|
|
5243
|
-
page: options.page ?? 1,
|
|
5244
|
-
limit: options.limit ?? this.defaultLimit
|
|
5245
|
-
});
|
|
5246
|
-
const result = response.data;
|
|
5247
|
-
return result;
|
|
5248
|
-
}
|
|
5249
|
-
/**
|
|
5250
|
-
* Fetch all pages of workflow data
|
|
5251
|
-
*/
|
|
5252
|
-
async fetchAllData(options) {
|
|
5253
|
-
const iterator = new PagedIterator(
|
|
5254
|
-
(pageOptions) => this.fetchData({ ...options, ...pageOptions })
|
|
5255
|
-
);
|
|
5256
|
-
return iterator.fetchAll({ limit: options.limit ?? this.defaultLimit });
|
|
5257
|
-
}
|
|
5258
|
-
/**
|
|
5259
|
-
* Create an async iterator for paginated data fetching
|
|
5260
|
-
*/
|
|
5261
|
-
async *fetchDataPages(options) {
|
|
5262
|
-
const iterator = new PagedIterator(
|
|
5263
|
-
(pageOptions) => this.fetchData({ ...options, ...pageOptions })
|
|
5264
|
-
);
|
|
5265
|
-
for await (const page of iterator.pages({
|
|
5266
|
-
limit: options.limit ?? this.defaultLimit
|
|
5267
|
-
})) {
|
|
5268
|
-
yield page;
|
|
5269
|
-
}
|
|
5270
|
-
}
|
|
5271
|
-
};
|
|
5272
|
-
|
|
5273
|
-
// src/internal/runtime/utils/polling.ts
|
|
5274
|
-
var DEFAULT_POLLING_OPTIONS = {
|
|
5275
|
-
pollIntervalMs: 1e3,
|
|
5276
|
-
timeoutMs: 5 * 60 * 1e3
|
|
5277
|
-
};
|
|
5278
|
-
var POLLING_ERROR_CODES = {
|
|
5279
|
-
ABORTED: "ABORTED",
|
|
5280
|
-
TIMEOUT: "TIMEOUT"
|
|
5281
|
-
};
|
|
5282
|
-
async function pollUntil(pollFn, isComplete, options = {}) {
|
|
5283
|
-
const internalOptions = {
|
|
5284
|
-
...DEFAULT_POLLING_OPTIONS,
|
|
5285
|
-
...options
|
|
5286
|
-
};
|
|
5287
|
-
const pollInterval = Math.max(250, internalOptions.pollIntervalMs);
|
|
5288
|
-
const timeoutMs = internalOptions.timeoutMs;
|
|
5289
|
-
const start = Date.now();
|
|
5290
|
-
let attempts = 0;
|
|
5291
|
-
while (Date.now() - start < timeoutMs) {
|
|
5292
|
-
if (internalOptions.abortSignal?.aborted) {
|
|
5293
|
-
throw new KadoaSdkException("Polling operation was aborted", {
|
|
5294
|
-
code: POLLING_ERROR_CODES.ABORTED
|
|
5295
|
-
});
|
|
5296
|
-
}
|
|
5297
|
-
attempts++;
|
|
5298
|
-
const current = await pollFn();
|
|
5299
|
-
if (isComplete(current)) {
|
|
5300
|
-
return {
|
|
5301
|
-
result: current,
|
|
5302
|
-
attempts,
|
|
5303
|
-
duration: Date.now() - start
|
|
5304
|
-
};
|
|
5305
|
-
}
|
|
5306
|
-
await new Promise((resolve) => setTimeout(resolve, pollInterval));
|
|
5307
|
-
}
|
|
5308
|
-
throw new KadoaSdkException(
|
|
5309
|
-
`Polling operation timed out after ${timeoutMs}ms`,
|
|
5310
|
-
{
|
|
5311
|
-
code: POLLING_ERROR_CODES.TIMEOUT,
|
|
5312
|
-
details: {
|
|
5313
|
-
timeoutMs,
|
|
5314
|
-
attempts,
|
|
5315
|
-
duration: Date.now() - start
|
|
5316
|
-
}
|
|
5317
|
-
}
|
|
5318
|
-
);
|
|
5319
|
-
}
|
|
5320
|
-
|
|
5321
|
-
// src/internal/domains/workflows/types.ts
|
|
5322
|
-
var TERMINAL_JOB_STATES = /* @__PURE__ */ new Set([
|
|
5323
|
-
"FINISHED",
|
|
5324
|
-
"FAILED",
|
|
5325
|
-
"NOT_SUPPORTED",
|
|
5326
|
-
"FAILED_INSUFFICIENT_FUNDS"
|
|
5327
|
-
]);
|
|
5328
|
-
|
|
5329
|
-
// src/internal/domains/workflows/workflows-core.service.ts
|
|
5330
|
-
var TERMINAL_RUN_STATES = /* @__PURE__ */ new Set([
|
|
5331
|
-
"FINISHED",
|
|
5332
|
-
"SUCCESS",
|
|
5333
|
-
"FAILED",
|
|
5334
|
-
"ERROR",
|
|
5335
|
-
"STOPPED",
|
|
5336
|
-
"CANCELLED"
|
|
5337
|
-
]);
|
|
5338
|
-
var debug3 = logger.workflow;
|
|
5339
|
-
var WorkflowsCoreService = class {
|
|
5340
|
-
constructor(workflowsApi) {
|
|
5341
|
-
this.workflowsApi = workflowsApi;
|
|
5342
|
-
}
|
|
5343
|
-
async create(input) {
|
|
5344
|
-
const request = {
|
|
5345
|
-
urls: input.urls,
|
|
5346
|
-
name: input.name,
|
|
5347
|
-
schemaId: input.schemaId,
|
|
5348
|
-
description: input.description,
|
|
5349
|
-
navigationMode: input.navigationMode,
|
|
5350
|
-
entity: input.entity,
|
|
5351
|
-
fields: input.fields,
|
|
5352
|
-
bypassPreview: input.bypassPreview ?? true,
|
|
5353
|
-
tags: input.tags,
|
|
5354
|
-
interval: input.interval,
|
|
5355
|
-
monitoring: input.monitoring,
|
|
5356
|
-
location: input.location,
|
|
5357
|
-
autoStart: input.autoStart,
|
|
5358
|
-
schedules: input.schedules
|
|
5359
|
-
};
|
|
5360
|
-
const response = await this.workflowsApi.v4WorkflowsPost({
|
|
5361
|
-
createWorkflowBody: request
|
|
5362
|
-
});
|
|
5363
|
-
const workflowId = response.data?.workflowId;
|
|
5364
|
-
if (!workflowId) {
|
|
5365
|
-
throw new KadoaSdkException(ERROR_MESSAGES.NO_WORKFLOW_ID, {
|
|
5366
|
-
code: "INTERNAL_ERROR",
|
|
5367
|
-
details: {
|
|
5368
|
-
response: response.data
|
|
5369
|
-
}
|
|
5370
|
-
});
|
|
5371
|
-
}
|
|
5372
|
-
return { id: workflowId };
|
|
5373
|
-
}
|
|
5374
|
-
async get(id) {
|
|
5375
|
-
const response = await this.workflowsApi.v4WorkflowsWorkflowIdGet({
|
|
5376
|
-
workflowId: id
|
|
5377
|
-
});
|
|
5378
|
-
return response.data;
|
|
5379
|
-
}
|
|
5380
|
-
async list(filters) {
|
|
5381
|
-
const response = await this.workflowsApi.v4WorkflowsGet(filters);
|
|
5382
|
-
return response.data?.workflows ?? [];
|
|
5383
|
-
}
|
|
5384
|
-
async getByName(name) {
|
|
5385
|
-
const response = await this.workflowsApi.v4WorkflowsGet({
|
|
5386
|
-
search: name
|
|
5387
|
-
});
|
|
5388
|
-
return response.data?.workflows?.[0];
|
|
5389
|
-
}
|
|
5390
|
-
async cancel(id) {
|
|
5391
|
-
await this.workflowsApi.v4WorkflowsWorkflowIdDelete({
|
|
5392
|
-
workflowId: id
|
|
5393
|
-
});
|
|
5394
|
-
}
|
|
5395
|
-
async resume(id) {
|
|
5396
|
-
await this.workflowsApi.v4WorkflowsWorkflowIdResumePut({
|
|
5397
|
-
workflowId: id
|
|
5398
|
-
});
|
|
5399
|
-
}
|
|
5400
|
-
/**
|
|
5401
|
-
* Wait for a workflow to reach the target state or a terminal state if no target state is provided
|
|
5402
|
-
*/
|
|
5403
|
-
async wait(id, options) {
|
|
5404
|
-
let last;
|
|
5405
|
-
const result = await pollUntil(
|
|
5406
|
-
async () => {
|
|
5407
|
-
const current = await this.get(id);
|
|
5408
|
-
if (last?.state !== current.state || last?.runState !== current.runState) {
|
|
5409
|
-
debug3(
|
|
5410
|
-
"workflow %s state: [workflowState: %s, jobState: %s]",
|
|
5411
|
-
id,
|
|
5412
|
-
current.state,
|
|
5413
|
-
current.runState
|
|
5414
|
-
);
|
|
5415
|
-
}
|
|
5416
|
-
last = current;
|
|
5417
|
-
return current;
|
|
5418
|
-
},
|
|
5419
|
-
(current) => {
|
|
5420
|
-
if (options?.targetState && current.state === options.targetState) {
|
|
5421
|
-
return true;
|
|
5422
|
-
}
|
|
5423
|
-
if (current.runState && TERMINAL_RUN_STATES.has(current.runState.toUpperCase()) && current.state !== "QUEUED") {
|
|
5424
|
-
return true;
|
|
5425
|
-
}
|
|
5426
|
-
return false;
|
|
5427
|
-
},
|
|
5428
|
-
options
|
|
5429
|
-
);
|
|
5430
|
-
return result.result;
|
|
5431
|
-
}
|
|
5432
|
-
/**
|
|
5433
|
-
* Run a workflow with variables and optional limit
|
|
5434
|
-
*/
|
|
5435
|
-
async runWorkflow(workflowId, input) {
|
|
5436
|
-
const response = await this.workflowsApi.v4WorkflowsWorkflowIdRunPut({
|
|
5437
|
-
workflowId,
|
|
5438
|
-
v4WorkflowsWorkflowIdRunPutRequest: {
|
|
5439
|
-
variables: input.variables,
|
|
5440
|
-
limit: input.limit
|
|
5441
|
-
}
|
|
5442
|
-
});
|
|
5443
|
-
const jobId = response.data?.jobId;
|
|
5444
|
-
if (!jobId) {
|
|
5445
|
-
throw new KadoaSdkException(ERROR_MESSAGES.NO_WORKFLOW_ID, {
|
|
5446
|
-
code: "INTERNAL_ERROR",
|
|
5447
|
-
details: {
|
|
5448
|
-
response: response.data
|
|
5449
|
-
}
|
|
5450
|
-
});
|
|
5451
|
-
}
|
|
5452
|
-
return {
|
|
5453
|
-
jobId,
|
|
5454
|
-
message: response.data?.message,
|
|
5455
|
-
status: response.data?.status
|
|
5456
|
-
};
|
|
5457
|
-
}
|
|
5458
|
-
/**
|
|
5459
|
-
* Get job status directly without polling workflow details
|
|
5460
|
-
*/
|
|
5461
|
-
async getJobStatus(workflowId, jobId) {
|
|
5462
|
-
const response = await this.workflowsApi.v4WorkflowsWorkflowIdJobsJobIdGet({
|
|
5463
|
-
workflowId,
|
|
5464
|
-
jobId
|
|
5465
|
-
});
|
|
5466
|
-
return response.data;
|
|
5467
|
-
}
|
|
5468
|
-
/**
|
|
5469
|
-
* Wait for a job to reach the target state or a terminal state
|
|
5470
|
-
*/
|
|
5471
|
-
async waitForJobCompletion(workflowId, jobId, options) {
|
|
5472
|
-
let last;
|
|
5473
|
-
const result = await pollUntil(
|
|
5474
|
-
async () => {
|
|
5475
|
-
const current = await this.getJobStatus(workflowId, jobId);
|
|
5476
|
-
if (last?.state !== current.state) {
|
|
5477
|
-
debug3("job %s state: %s", jobId, current.state);
|
|
5478
|
-
}
|
|
5479
|
-
last = current;
|
|
5480
|
-
return current;
|
|
5481
|
-
},
|
|
5482
|
-
(current) => {
|
|
5483
|
-
if (options?.targetStatus && current.state === options.targetStatus) {
|
|
5484
|
-
return true;
|
|
5485
|
-
}
|
|
5486
|
-
if (current.state && TERMINAL_JOB_STATES.has(current.state)) {
|
|
5487
|
-
return true;
|
|
5488
|
-
}
|
|
5489
|
-
return false;
|
|
5490
|
-
},
|
|
5491
|
-
options
|
|
5492
|
-
);
|
|
5493
|
-
return result.result;
|
|
5494
|
-
}
|
|
5495
|
-
};
|
|
5496
|
-
|
|
5497
|
-
// src/internal/domains/schemas/schemas.service.ts
|
|
5498
|
-
var debug4 = logger.schemas;
|
|
5499
|
-
var SchemasService = class {
|
|
5500
|
-
constructor(client) {
|
|
5501
|
-
this.schemasApi = new SchemasApi(client.configuration);
|
|
5502
|
-
}
|
|
5503
|
-
/**
|
|
5504
|
-
* Get a schema by ID
|
|
5505
|
-
*/
|
|
5506
|
-
async getSchema(schemaId) {
|
|
5507
|
-
debug4("Fetching schema with ID: %s", schemaId);
|
|
5508
|
-
const response = await this.schemasApi.v4SchemasSchemaIdGet({
|
|
5509
|
-
schemaId
|
|
5510
|
-
});
|
|
5511
|
-
const schemaData = response.data.data;
|
|
5512
|
-
if (!schemaData) {
|
|
5513
|
-
throw new KadoaSdkException(
|
|
5514
|
-
`${ERROR_MESSAGES.SCHEMA_NOT_FOUND}: ${schemaId}`,
|
|
5515
|
-
{
|
|
5516
|
-
code: KadoaErrorCode.NOT_FOUND,
|
|
5517
|
-
details: { schemaId }
|
|
5518
|
-
}
|
|
5519
|
-
);
|
|
5048
|
+
throw KadoaHttpException.wrap(response, {
|
|
5049
|
+
message: "Failed to delete notification settings"
|
|
5050
|
+
});
|
|
5520
5051
|
}
|
|
5521
|
-
return schemaData;
|
|
5522
5052
|
}
|
|
5523
|
-
|
|
5524
|
-
|
|
5525
|
-
|
|
5526
|
-
|
|
5527
|
-
|
|
5528
|
-
|
|
5053
|
+
};
|
|
5054
|
+
|
|
5055
|
+
// src/domains/notifications/notification-setup.service.ts
|
|
5056
|
+
var debug4 = logger.notifications;
|
|
5057
|
+
var NotificationSetupService = class {
|
|
5058
|
+
constructor(channelsService, settingsService) {
|
|
5059
|
+
this.channelsService = channelsService;
|
|
5060
|
+
this.settingsService = settingsService;
|
|
5529
5061
|
}
|
|
5530
5062
|
/**
|
|
5531
|
-
*
|
|
5063
|
+
* Setup notification settings for a specific workflow ensuring no duplicates exist.
|
|
5532
5064
|
*/
|
|
5533
|
-
async
|
|
5534
|
-
|
|
5535
|
-
|
|
5536
|
-
createSchemaBody: body
|
|
5065
|
+
async setupForWorkflow(requestData) {
|
|
5066
|
+
const existingSettings = await this.settingsService.listSettings({
|
|
5067
|
+
workflowId: requestData.workflowId
|
|
5537
5068
|
});
|
|
5538
|
-
|
|
5539
|
-
|
|
5540
|
-
|
|
5541
|
-
|
|
5069
|
+
if (existingSettings.length > 0) {
|
|
5070
|
+
throw new KadoaSdkException("Settings already exist", {
|
|
5071
|
+
code: KadoaErrorCode.BAD_REQUEST,
|
|
5072
|
+
details: {
|
|
5073
|
+
workflowId: requestData.workflowId
|
|
5074
|
+
}
|
|
5542
5075
|
});
|
|
5543
5076
|
}
|
|
5544
|
-
return this.
|
|
5545
|
-
|
|
5546
|
-
|
|
5547
|
-
|
|
5548
|
-
*/
|
|
5549
|
-
async updateSchema(schemaId, body) {
|
|
5550
|
-
debug4("Updating schema with ID: %s", schemaId);
|
|
5551
|
-
await this.schemasApi.v4SchemasSchemaIdPut({
|
|
5552
|
-
schemaId,
|
|
5553
|
-
updateSchemaBody: body
|
|
5077
|
+
return this.setup({
|
|
5078
|
+
workflowId: requestData.workflowId,
|
|
5079
|
+
events: requestData.events,
|
|
5080
|
+
channels: requestData.channels
|
|
5554
5081
|
});
|
|
5555
|
-
return this.getSchema(schemaId);
|
|
5556
5082
|
}
|
|
5557
5083
|
/**
|
|
5558
|
-
*
|
|
5084
|
+
* Setup notification settings at the workspace level ensuring no duplicates exist.
|
|
5559
5085
|
*/
|
|
5560
|
-
async
|
|
5561
|
-
|
|
5562
|
-
|
|
5563
|
-
|
|
5086
|
+
async setupForWorkspace(requestData) {
|
|
5087
|
+
const existingSettings = await this.settingsService.listSettings({});
|
|
5088
|
+
if (existingSettings.length > 0) {
|
|
5089
|
+
throw new KadoaSdkException("Workspace settings already exist", {
|
|
5090
|
+
code: KadoaErrorCode.BAD_REQUEST
|
|
5091
|
+
});
|
|
5092
|
+
}
|
|
5093
|
+
return this.setup({
|
|
5094
|
+
events: requestData.events,
|
|
5095
|
+
channels: requestData.channels
|
|
5564
5096
|
});
|
|
5565
5097
|
}
|
|
5566
|
-
};
|
|
5567
|
-
|
|
5568
|
-
// src/internal/domains/notifications/notification-setup.service.ts
|
|
5569
|
-
var debug5 = logger.notifications;
|
|
5570
|
-
var NotificationSetupService = class {
|
|
5571
|
-
constructor(channelsService, settingsService) {
|
|
5572
|
-
this.channelsService = channelsService;
|
|
5573
|
-
this.settingsService = settingsService;
|
|
5574
|
-
}
|
|
5575
5098
|
/**
|
|
5576
5099
|
* Complete workflow notification setup including channels and settings
|
|
5577
5100
|
*
|
|
@@ -5579,10 +5102,10 @@ var NotificationSetupService = class {
|
|
|
5579
5102
|
* @returns Array of created notification settings
|
|
5580
5103
|
*/
|
|
5581
5104
|
async setup(requestData) {
|
|
5582
|
-
requestData.workflowId ?
|
|
5105
|
+
requestData.workflowId ? debug4(
|
|
5583
5106
|
"Setting up notifications for workflow %s",
|
|
5584
5107
|
requestData.workflowId
|
|
5585
|
-
) :
|
|
5108
|
+
) : debug4("Setting up notifications for workspace");
|
|
5586
5109
|
const channels = await this.setupChannels({
|
|
5587
5110
|
workflowId: requestData.workflowId,
|
|
5588
5111
|
channels: requestData.channels || {}
|
|
@@ -5590,7 +5113,7 @@ var NotificationSetupService = class {
|
|
|
5590
5113
|
const events = requestData.events || "all";
|
|
5591
5114
|
const eventTypes = events === "all" ? await this.settingsService.listAllEvents() : events;
|
|
5592
5115
|
const channelIds = channels.map((channel) => channel.id).filter(Boolean);
|
|
5593
|
-
|
|
5116
|
+
debug4(
|
|
5594
5117
|
"Creating notification settings for workflow %s: %O",
|
|
5595
5118
|
requestData.workflowId,
|
|
5596
5119
|
{
|
|
@@ -5609,7 +5132,7 @@ var NotificationSetupService = class {
|
|
|
5609
5132
|
});
|
|
5610
5133
|
})
|
|
5611
5134
|
);
|
|
5612
|
-
|
|
5135
|
+
debug4(
|
|
5613
5136
|
requestData.workflowId ? "Successfully setup notifications for workflow %s" : "Successfully setup notifications for workspace",
|
|
5614
5137
|
requestData.workflowId
|
|
5615
5138
|
);
|
|
@@ -5691,7 +5214,7 @@ var NotificationSetupService = class {
|
|
|
5691
5214
|
(channel2) => channel2.channelType === channelType && channel2.name === NotificationChannelsService.DEFAULT_CHANNEL_NAME
|
|
5692
5215
|
);
|
|
5693
5216
|
if (existingChannel) {
|
|
5694
|
-
|
|
5217
|
+
debug4("Using existing default channel: %O", {
|
|
5695
5218
|
workflowId,
|
|
5696
5219
|
channelType,
|
|
5697
5220
|
channelId: existingChannel.id
|
|
@@ -5699,7 +5222,7 @@ var NotificationSetupService = class {
|
|
|
5699
5222
|
return existingChannel;
|
|
5700
5223
|
}
|
|
5701
5224
|
const channel = await this.channelsService.createChannel(channelType);
|
|
5702
|
-
|
|
5225
|
+
debug4("Created default channel %O", {
|
|
5703
5226
|
workflowId,
|
|
5704
5227
|
channelType,
|
|
5705
5228
|
channel
|
|
@@ -5724,7 +5247,7 @@ var NotificationSetupService = class {
|
|
|
5724
5247
|
(channel2) => channel2.channelType === channelType && (channel2.name || NotificationChannelsService.DEFAULT_CHANNEL_NAME) === channelName
|
|
5725
5248
|
);
|
|
5726
5249
|
if (existingChannel) {
|
|
5727
|
-
|
|
5250
|
+
debug4("Using existing channel: %O", {
|
|
5728
5251
|
workflowId,
|
|
5729
5252
|
channelType,
|
|
5730
5253
|
channelName,
|
|
@@ -5736,7 +5259,7 @@ var NotificationSetupService = class {
|
|
|
5736
5259
|
name: channelName,
|
|
5737
5260
|
config
|
|
5738
5261
|
});
|
|
5739
|
-
|
|
5262
|
+
debug4("Created channel with custom config %O", {
|
|
5740
5263
|
workflowId,
|
|
5741
5264
|
channelType,
|
|
5742
5265
|
channelName,
|
|
@@ -5749,7 +5272,280 @@ var NotificationSetupService = class {
|
|
|
5749
5272
|
}
|
|
5750
5273
|
};
|
|
5751
5274
|
|
|
5752
|
-
// src/
|
|
5275
|
+
// src/runtime/config/constants.ts
|
|
5276
|
+
var PUBLIC_API_URI = process.env.KADOA_PUBLIC_API_URI ?? "https://api.kadoa.com";
|
|
5277
|
+
var WSS_API_URI = process.env.KADOA_WSS_API_URI ?? "wss://realtime.kadoa.com";
|
|
5278
|
+
var REALTIME_API_URI = process.env.KADOA_REALTIME_API_URI ?? "https://realtime.kadoa.com";
|
|
5279
|
+
|
|
5280
|
+
// src/version.ts
|
|
5281
|
+
var SDK_VERSION = "0.14.1";
|
|
5282
|
+
var SDK_NAME = "kadoa-node-sdk";
|
|
5283
|
+
var SDK_LANGUAGE = "node";
|
|
5284
|
+
|
|
5285
|
+
// src/domains/realtime/realtime.ts
|
|
5286
|
+
var debug5 = logger.wss;
|
|
5287
|
+
if (typeof WebSocket === "undefined") {
|
|
5288
|
+
global.WebSocket = __require("ws");
|
|
5289
|
+
}
|
|
5290
|
+
var Realtime = class {
|
|
5291
|
+
constructor(config) {
|
|
5292
|
+
this.lastHeartbeat = Date.now();
|
|
5293
|
+
this.isConnecting = false;
|
|
5294
|
+
this.eventListeners = /* @__PURE__ */ new Set();
|
|
5295
|
+
this.connectionListeners = /* @__PURE__ */ new Set();
|
|
5296
|
+
this.errorListeners = /* @__PURE__ */ new Set();
|
|
5297
|
+
if (!config.teamApiKey.startsWith("tk-")) {
|
|
5298
|
+
throw new KadoaSdkException(
|
|
5299
|
+
"Realtime connection requires a team API key (starting with 'tk-'). Provided key does not appear to be a team API key.",
|
|
5300
|
+
{
|
|
5301
|
+
code: "AUTH_ERROR",
|
|
5302
|
+
details: { providedKeyPrefix: config.teamApiKey.substring(0, 3) }
|
|
5303
|
+
}
|
|
5304
|
+
);
|
|
5305
|
+
}
|
|
5306
|
+
this.teamApiKey = config.teamApiKey;
|
|
5307
|
+
this.heartbeatInterval = config.heartbeatInterval || 1e4;
|
|
5308
|
+
this.reconnectDelay = config.reconnectDelay || 5e3;
|
|
5309
|
+
this.missedHeartbeatsLimit = config.missedHeartbeatsLimit || 3e4;
|
|
5310
|
+
}
|
|
5311
|
+
async connect() {
|
|
5312
|
+
if (this.isConnecting) return;
|
|
5313
|
+
this.isConnecting = true;
|
|
5314
|
+
try {
|
|
5315
|
+
const response = await fetch(`${PUBLIC_API_URI}/v4/oauth2/token`, {
|
|
5316
|
+
method: "POST",
|
|
5317
|
+
headers: {
|
|
5318
|
+
"Content-Type": "application/json",
|
|
5319
|
+
"x-api-key": `${this.teamApiKey}`,
|
|
5320
|
+
"x-sdk-version": SDK_VERSION
|
|
5321
|
+
}
|
|
5322
|
+
});
|
|
5323
|
+
const { access_token, team_id } = await response.json();
|
|
5324
|
+
this.socket = new WebSocket(
|
|
5325
|
+
`${WSS_API_URI}?access_token=${access_token}`
|
|
5326
|
+
);
|
|
5327
|
+
this.socket.onopen = () => {
|
|
5328
|
+
this.isConnecting = false;
|
|
5329
|
+
this.lastHeartbeat = Date.now();
|
|
5330
|
+
if (this.socket?.readyState === WebSocket.OPEN) {
|
|
5331
|
+
this.socket.send(
|
|
5332
|
+
JSON.stringify({
|
|
5333
|
+
action: "subscribe",
|
|
5334
|
+
channel: team_id
|
|
5335
|
+
})
|
|
5336
|
+
);
|
|
5337
|
+
debug5("Connected to WebSocket");
|
|
5338
|
+
this.notifyConnectionListeners(true);
|
|
5339
|
+
}
|
|
5340
|
+
this.startHeartbeatCheck();
|
|
5341
|
+
};
|
|
5342
|
+
this.socket.onmessage = (event) => {
|
|
5343
|
+
try {
|
|
5344
|
+
const data = JSON.parse(event.data);
|
|
5345
|
+
if (data.type === "heartbeat") {
|
|
5346
|
+
this.handleHeartbeat();
|
|
5347
|
+
} else {
|
|
5348
|
+
if (data?.id) {
|
|
5349
|
+
fetch(`${REALTIME_API_URI}/api/v1/events/ack`, {
|
|
5350
|
+
method: "POST",
|
|
5351
|
+
headers: { "Content-Type": "application/json" },
|
|
5352
|
+
body: JSON.stringify({ id: data.id })
|
|
5353
|
+
});
|
|
5354
|
+
}
|
|
5355
|
+
this.notifyEventListeners(data);
|
|
5356
|
+
}
|
|
5357
|
+
} catch (err) {
|
|
5358
|
+
debug5("Failed to parse incoming message: %O", err);
|
|
5359
|
+
}
|
|
5360
|
+
};
|
|
5361
|
+
this.socket.onclose = () => {
|
|
5362
|
+
debug5("WebSocket disconnected. Attempting to reconnect...");
|
|
5363
|
+
this.isConnecting = false;
|
|
5364
|
+
this.stopHeartbeatCheck();
|
|
5365
|
+
this.notifyConnectionListeners(false, "Connection closed");
|
|
5366
|
+
setTimeout(() => this.connect(), this.reconnectDelay);
|
|
5367
|
+
};
|
|
5368
|
+
this.socket.onerror = (error) => {
|
|
5369
|
+
debug5("WebSocket error: %O", error);
|
|
5370
|
+
this.isConnecting = false;
|
|
5371
|
+
this.notifyErrorListeners(error);
|
|
5372
|
+
};
|
|
5373
|
+
} catch (err) {
|
|
5374
|
+
debug5("Failed to connect: %O", err);
|
|
5375
|
+
this.isConnecting = false;
|
|
5376
|
+
setTimeout(() => this.connect(), this.reconnectDelay);
|
|
5377
|
+
}
|
|
5378
|
+
}
|
|
5379
|
+
handleHeartbeat() {
|
|
5380
|
+
debug5("Heartbeat received");
|
|
5381
|
+
this.lastHeartbeat = Date.now();
|
|
5382
|
+
}
|
|
5383
|
+
notifyEventListeners(event) {
|
|
5384
|
+
this.eventListeners.forEach((listener) => {
|
|
5385
|
+
try {
|
|
5386
|
+
listener(event);
|
|
5387
|
+
} catch (error) {
|
|
5388
|
+
debug5("Error in event listener: %O", error);
|
|
5389
|
+
}
|
|
5390
|
+
});
|
|
5391
|
+
}
|
|
5392
|
+
notifyConnectionListeners(connected, reason) {
|
|
5393
|
+
this.connectionListeners.forEach((listener) => {
|
|
5394
|
+
try {
|
|
5395
|
+
listener(connected, reason);
|
|
5396
|
+
} catch (error) {
|
|
5397
|
+
debug5("Error in connection listener: %O", error);
|
|
5398
|
+
}
|
|
5399
|
+
});
|
|
5400
|
+
}
|
|
5401
|
+
notifyErrorListeners(error) {
|
|
5402
|
+
this.errorListeners.forEach((listener) => {
|
|
5403
|
+
try {
|
|
5404
|
+
listener(error);
|
|
5405
|
+
} catch (error2) {
|
|
5406
|
+
debug5("Error in error listener: %O", error2);
|
|
5407
|
+
}
|
|
5408
|
+
});
|
|
5409
|
+
}
|
|
5410
|
+
startHeartbeatCheck() {
|
|
5411
|
+
this.missedHeartbeatCheckTimer = setInterval(() => {
|
|
5412
|
+
if (Date.now() - this.lastHeartbeat > this.missedHeartbeatsLimit) {
|
|
5413
|
+
debug5("No heartbeat received in 30 seconds! Closing connection.");
|
|
5414
|
+
this.socket?.close();
|
|
5415
|
+
}
|
|
5416
|
+
}, this.heartbeatInterval);
|
|
5417
|
+
}
|
|
5418
|
+
stopHeartbeatCheck() {
|
|
5419
|
+
if (this.missedHeartbeatCheckTimer) {
|
|
5420
|
+
clearInterval(this.missedHeartbeatCheckTimer);
|
|
5421
|
+
}
|
|
5422
|
+
}
|
|
5423
|
+
/**
|
|
5424
|
+
* Subscribe to realtime events
|
|
5425
|
+
* @param listener Function to handle incoming events
|
|
5426
|
+
* @returns Function to unsubscribe
|
|
5427
|
+
*/
|
|
5428
|
+
onEvent(listener) {
|
|
5429
|
+
this.eventListeners.add(listener);
|
|
5430
|
+
return () => {
|
|
5431
|
+
this.eventListeners.delete(listener);
|
|
5432
|
+
};
|
|
5433
|
+
}
|
|
5434
|
+
/**
|
|
5435
|
+
* Subscribe to connection state changes
|
|
5436
|
+
* @param listener Function to handle connection state changes
|
|
5437
|
+
* @returns Function to unsubscribe
|
|
5438
|
+
*/
|
|
5439
|
+
onConnection(listener) {
|
|
5440
|
+
this.connectionListeners.add(listener);
|
|
5441
|
+
return () => {
|
|
5442
|
+
this.connectionListeners.delete(listener);
|
|
5443
|
+
};
|
|
5444
|
+
}
|
|
5445
|
+
/**
|
|
5446
|
+
* Subscribe to errors
|
|
5447
|
+
* @param listener Function to handle errors
|
|
5448
|
+
* @returns Function to unsubscribe
|
|
5449
|
+
*/
|
|
5450
|
+
onError(listener) {
|
|
5451
|
+
this.errorListeners.add(listener);
|
|
5452
|
+
return () => {
|
|
5453
|
+
this.errorListeners.delete(listener);
|
|
5454
|
+
};
|
|
5455
|
+
}
|
|
5456
|
+
close() {
|
|
5457
|
+
if (this.socket) {
|
|
5458
|
+
this.stopHeartbeatCheck();
|
|
5459
|
+
this.socket.close();
|
|
5460
|
+
this.socket = void 0;
|
|
5461
|
+
}
|
|
5462
|
+
this.eventListeners.clear();
|
|
5463
|
+
this.connectionListeners.clear();
|
|
5464
|
+
this.errorListeners.clear();
|
|
5465
|
+
}
|
|
5466
|
+
isConnected() {
|
|
5467
|
+
return this.socket?.readyState === WebSocket.OPEN;
|
|
5468
|
+
}
|
|
5469
|
+
};
|
|
5470
|
+
|
|
5471
|
+
// src/domains/user/user.service.ts
|
|
5472
|
+
var UserService = class {
|
|
5473
|
+
constructor(client) {
|
|
5474
|
+
this.client = client;
|
|
5475
|
+
}
|
|
5476
|
+
/**
|
|
5477
|
+
* Get current user details
|
|
5478
|
+
* @returns User details
|
|
5479
|
+
*/
|
|
5480
|
+
async getCurrentUser() {
|
|
5481
|
+
const response = await this.client.axiosInstance.get("/v5/user", {
|
|
5482
|
+
baseURL: this.client.baseUrl,
|
|
5483
|
+
headers: {
|
|
5484
|
+
"x-api-key": this.client.apiKey,
|
|
5485
|
+
"Content-Type": "application/json"
|
|
5486
|
+
}
|
|
5487
|
+
});
|
|
5488
|
+
const userData = response.data;
|
|
5489
|
+
if (!userData || !userData.userId) {
|
|
5490
|
+
throw new KadoaSdkException("Invalid user data received");
|
|
5491
|
+
}
|
|
5492
|
+
return {
|
|
5493
|
+
userId: userData.userId,
|
|
5494
|
+
email: userData.email,
|
|
5495
|
+
featureFlags: userData.featureFlags || []
|
|
5496
|
+
};
|
|
5497
|
+
}
|
|
5498
|
+
};
|
|
5499
|
+
|
|
5500
|
+
// src/runtime/utils/polling.ts
|
|
5501
|
+
var DEFAULT_POLLING_OPTIONS = {
|
|
5502
|
+
pollIntervalMs: 1e3,
|
|
5503
|
+
timeoutMs: 5 * 60 * 1e3
|
|
5504
|
+
};
|
|
5505
|
+
var POLLING_ERROR_CODES = {
|
|
5506
|
+
ABORTED: "ABORTED",
|
|
5507
|
+
TIMEOUT: "TIMEOUT"
|
|
5508
|
+
};
|
|
5509
|
+
async function pollUntil(pollFn, isComplete, options = {}) {
|
|
5510
|
+
const internalOptions = {
|
|
5511
|
+
...DEFAULT_POLLING_OPTIONS,
|
|
5512
|
+
...options
|
|
5513
|
+
};
|
|
5514
|
+
const pollInterval = Math.max(250, internalOptions.pollIntervalMs);
|
|
5515
|
+
const timeoutMs = internalOptions.timeoutMs;
|
|
5516
|
+
const start = Date.now();
|
|
5517
|
+
let attempts = 0;
|
|
5518
|
+
while (Date.now() - start < timeoutMs) {
|
|
5519
|
+
if (internalOptions.abortSignal?.aborted) {
|
|
5520
|
+
throw new KadoaSdkException("Polling operation was aborted", {
|
|
5521
|
+
code: POLLING_ERROR_CODES.ABORTED
|
|
5522
|
+
});
|
|
5523
|
+
}
|
|
5524
|
+
attempts++;
|
|
5525
|
+
const current = await pollFn();
|
|
5526
|
+
if (isComplete(current)) {
|
|
5527
|
+
return {
|
|
5528
|
+
result: current,
|
|
5529
|
+
attempts,
|
|
5530
|
+
duration: Date.now() - start
|
|
5531
|
+
};
|
|
5532
|
+
}
|
|
5533
|
+
await new Promise((resolve) => setTimeout(resolve, pollInterval));
|
|
5534
|
+
}
|
|
5535
|
+
throw new KadoaSdkException(
|
|
5536
|
+
`Polling operation timed out after ${timeoutMs}ms`,
|
|
5537
|
+
{
|
|
5538
|
+
code: POLLING_ERROR_CODES.TIMEOUT,
|
|
5539
|
+
details: {
|
|
5540
|
+
timeoutMs,
|
|
5541
|
+
attempts,
|
|
5542
|
+
duration: Date.now() - start
|
|
5543
|
+
}
|
|
5544
|
+
}
|
|
5545
|
+
);
|
|
5546
|
+
}
|
|
5547
|
+
|
|
5548
|
+
// src/domains/validation/validation-core.service.ts
|
|
5753
5549
|
var ValidationCoreService = class {
|
|
5754
5550
|
constructor(client) {
|
|
5755
5551
|
this.validationApi = new DataValidationApi(
|
|
@@ -5823,7 +5619,7 @@ var ValidationCoreService = class {
|
|
|
5823
5619
|
}
|
|
5824
5620
|
);
|
|
5825
5621
|
}
|
|
5826
|
-
if (response.status !== 200 || response.data
|
|
5622
|
+
if (response.status !== 200 || response.data?.error) {
|
|
5827
5623
|
throw KadoaHttpException.wrap(response.data, {
|
|
5828
5624
|
message: "Failed to get latest validation"
|
|
5829
5625
|
});
|
|
@@ -5982,292 +5778,222 @@ var ValidationRulesService = class {
|
|
|
5982
5778
|
bulkDeleteRules: data
|
|
5983
5779
|
});
|
|
5984
5780
|
if (response.status !== 200 || response.data.error) {
|
|
5985
|
-
throw KadoaHttpException.wrap(response.data.data, {
|
|
5986
|
-
message: response.data.message || "Failed to bulk delete validation rules"
|
|
5987
|
-
});
|
|
5988
|
-
}
|
|
5989
|
-
return response.data.data;
|
|
5990
|
-
}
|
|
5991
|
-
async deleteAllRules(data) {
|
|
5992
|
-
const response = await this.validationApi.v4DataValidationRulesActionsDeleteAllDelete({
|
|
5993
|
-
deleteRuleWithReason: data
|
|
5994
|
-
});
|
|
5995
|
-
if (response.status !== 200 || response.data.error) {
|
|
5996
|
-
throw KadoaHttpException.wrap(response.data.data, {
|
|
5997
|
-
message: response.data.message || "Failed to delete all validation rules"
|
|
5998
|
-
});
|
|
5999
|
-
}
|
|
6000
|
-
return response.data.data;
|
|
6001
|
-
}
|
|
6002
|
-
};
|
|
6003
|
-
|
|
6004
|
-
// src/internal/domains/extraction/services/entity-resolver.service.ts
|
|
6005
|
-
var ENTITY_API_ENDPOINT = "/v4/entity";
|
|
6006
|
-
var EntityResolverService = class {
|
|
6007
|
-
constructor(client) {
|
|
6008
|
-
this.client = client;
|
|
6009
|
-
this.schemasService = new SchemasService(client);
|
|
6010
|
-
}
|
|
6011
|
-
/**
|
|
6012
|
-
* Resolves entity and fields from the provided entity configuration
|
|
6013
|
-
*
|
|
6014
|
-
* @param entityConfig The entity configuration to resolve
|
|
6015
|
-
* @param options Additional options for AI detection
|
|
6016
|
-
* @returns Resolved entity with fields
|
|
6017
|
-
*/
|
|
6018
|
-
async resolveEntity(entityConfig, options) {
|
|
6019
|
-
if (entityConfig === "ai-detection") {
|
|
6020
|
-
if (!options?.link) {
|
|
6021
|
-
throw new KadoaSdkException(ERROR_MESSAGES.LINK_REQUIRED, {
|
|
6022
|
-
code: "VALIDATION_ERROR",
|
|
6023
|
-
details: { entityConfig, options }
|
|
6024
|
-
});
|
|
6025
|
-
}
|
|
6026
|
-
const entityPrediction = await this.fetchEntityFields({
|
|
6027
|
-
link: options.link,
|
|
6028
|
-
location: options.location,
|
|
6029
|
-
navigationMode: options.navigationMode
|
|
6030
|
-
});
|
|
6031
|
-
return {
|
|
6032
|
-
entity: entityPrediction.entity,
|
|
6033
|
-
fields: entityPrediction.fields
|
|
6034
|
-
};
|
|
6035
|
-
} else if (entityConfig) {
|
|
6036
|
-
if ("schemaId" in entityConfig) {
|
|
6037
|
-
const schema = await this.schemasService.getSchema(
|
|
6038
|
-
entityConfig.schemaId
|
|
6039
|
-
);
|
|
6040
|
-
return {
|
|
6041
|
-
entity: schema.entity ?? "",
|
|
6042
|
-
fields: schema.schema
|
|
6043
|
-
};
|
|
6044
|
-
} else if ("name" in entityConfig && "fields" in entityConfig) {
|
|
6045
|
-
return {
|
|
6046
|
-
entity: entityConfig.name,
|
|
6047
|
-
fields: entityConfig.fields
|
|
6048
|
-
};
|
|
6049
|
-
}
|
|
6050
|
-
}
|
|
6051
|
-
throw new KadoaSdkException(ERROR_MESSAGES.ENTITY_INVARIANT_VIOLATION, {
|
|
6052
|
-
details: {
|
|
6053
|
-
entity: entityConfig
|
|
6054
|
-
}
|
|
6055
|
-
});
|
|
6056
|
-
}
|
|
6057
|
-
/**
|
|
6058
|
-
* Fetches entity fields dynamically from the /v4/entity endpoint.
|
|
6059
|
-
* This is a workaround implementation using native fetch since the endpoint
|
|
6060
|
-
* is not yet included in the OpenAPI specification.
|
|
6061
|
-
*
|
|
6062
|
-
* @param options Request options including the link to analyze
|
|
6063
|
-
* @returns EntityPrediction containing the detected entity type and fields
|
|
6064
|
-
*/
|
|
6065
|
-
async fetchEntityFields(options) {
|
|
6066
|
-
this.validateEntityOptions(options);
|
|
6067
|
-
const url = `${this.client.baseUrl}${ENTITY_API_ENDPOINT}`;
|
|
6068
|
-
const requestBody = options;
|
|
6069
|
-
const response = await this.client.axiosInstance.post(url, requestBody, {
|
|
6070
|
-
headers: {
|
|
6071
|
-
"Content-Type": "application/json",
|
|
6072
|
-
Accept: "application/json",
|
|
6073
|
-
"x-api-key": this.client.apiKey
|
|
6074
|
-
}
|
|
6075
|
-
});
|
|
6076
|
-
const data = response.data;
|
|
6077
|
-
if (!data.success || !data.entityPrediction || data.entityPrediction.length === 0) {
|
|
6078
|
-
throw new KadoaSdkException(ERROR_MESSAGES.NO_PREDICTIONS, {
|
|
6079
|
-
code: "NOT_FOUND",
|
|
6080
|
-
details: {
|
|
6081
|
-
success: data.success,
|
|
6082
|
-
hasPredictions: !!data.entityPrediction,
|
|
6083
|
-
predictionCount: data.entityPrediction?.length || 0,
|
|
6084
|
-
link: options.link
|
|
6085
|
-
}
|
|
6086
|
-
});
|
|
6087
|
-
}
|
|
6088
|
-
return data.entityPrediction[0];
|
|
6089
|
-
}
|
|
6090
|
-
/**
|
|
6091
|
-
* Validates entity request options
|
|
6092
|
-
*/
|
|
6093
|
-
validateEntityOptions(options) {
|
|
6094
|
-
if (!options.link) {
|
|
6095
|
-
throw new KadoaSdkException(ERROR_MESSAGES.LINK_REQUIRED, {
|
|
6096
|
-
code: "VALIDATION_ERROR",
|
|
6097
|
-
details: { options }
|
|
6098
|
-
});
|
|
6099
|
-
}
|
|
6100
|
-
}
|
|
6101
|
-
};
|
|
6102
|
-
var debug7 = logger.extraction;
|
|
6103
|
-
var ExtractionBuilderService = class {
|
|
6104
|
-
constructor(workflowsCoreService, entityResolverService, dataFetcherService, notificationSetupService) {
|
|
6105
|
-
this.workflowsCoreService = workflowsCoreService;
|
|
6106
|
-
this.entityResolverService = entityResolverService;
|
|
6107
|
-
this.dataFetcherService = dataFetcherService;
|
|
6108
|
-
this.notificationSetupService = notificationSetupService;
|
|
6109
|
-
}
|
|
6110
|
-
get options() {
|
|
6111
|
-
assert__default.default(this._options, "Options are not set");
|
|
6112
|
-
return this._options;
|
|
6113
|
-
}
|
|
6114
|
-
get notificationOptions() {
|
|
6115
|
-
return this._notificationOptions;
|
|
6116
|
-
}
|
|
6117
|
-
get monitoringOptions() {
|
|
6118
|
-
return this._monitoringOptions;
|
|
6119
|
-
}
|
|
6120
|
-
get workflowId() {
|
|
6121
|
-
assert__default.default(this._workflowId, "Workflow ID is not set");
|
|
6122
|
-
return this._workflowId;
|
|
6123
|
-
}
|
|
6124
|
-
get jobId() {
|
|
6125
|
-
assert__default.default(this._jobId, "Job ID is not set");
|
|
6126
|
-
return this._jobId;
|
|
6127
|
-
}
|
|
6128
|
-
extract({
|
|
6129
|
-
urls,
|
|
6130
|
-
name,
|
|
6131
|
-
description,
|
|
6132
|
-
navigationMode,
|
|
6133
|
-
extraction
|
|
6134
|
-
}) {
|
|
6135
|
-
let entity = "ai-detection";
|
|
6136
|
-
if (extraction) {
|
|
6137
|
-
const result = extraction(new SchemaBuilder());
|
|
6138
|
-
if ("schemaId" in result) {
|
|
6139
|
-
entity = { schemaId: result.schemaId };
|
|
6140
|
-
} else {
|
|
6141
|
-
const builtSchema = result.build();
|
|
6142
|
-
entity = { name: builtSchema.entityName, fields: builtSchema.fields };
|
|
6143
|
-
}
|
|
6144
|
-
}
|
|
6145
|
-
this._options = {
|
|
6146
|
-
urls,
|
|
6147
|
-
name,
|
|
6148
|
-
description,
|
|
6149
|
-
navigationMode: navigationMode || "single-page",
|
|
6150
|
-
entity,
|
|
6151
|
-
bypassPreview: false
|
|
6152
|
-
};
|
|
6153
|
-
return this;
|
|
6154
|
-
}
|
|
6155
|
-
withNotifications(options) {
|
|
6156
|
-
this._notificationOptions = options;
|
|
6157
|
-
return this;
|
|
6158
|
-
}
|
|
6159
|
-
withMonitoring(options) {
|
|
6160
|
-
this._monitoringOptions = options;
|
|
6161
|
-
return this;
|
|
6162
|
-
}
|
|
6163
|
-
bypassPreview() {
|
|
6164
|
-
assert__default.default(this._options, "Options are not set");
|
|
6165
|
-
this._options.bypassPreview = true;
|
|
6166
|
-
return this;
|
|
6167
|
-
}
|
|
6168
|
-
setInterval(options) {
|
|
6169
|
-
assert__default.default(this._options, "Options are not set");
|
|
6170
|
-
if ("interval" in options) {
|
|
6171
|
-
this._options.interval = options.interval;
|
|
6172
|
-
} else {
|
|
6173
|
-
this._options.interval = "CUSTOM";
|
|
6174
|
-
this._options.schedules = options.schedules;
|
|
5781
|
+
throw KadoaHttpException.wrap(response.data.data, {
|
|
5782
|
+
message: response.data.message || "Failed to bulk delete validation rules"
|
|
5783
|
+
});
|
|
6175
5784
|
}
|
|
6176
|
-
return
|
|
6177
|
-
}
|
|
6178
|
-
setLocation(options) {
|
|
6179
|
-
assert__default.default(this._options, "Options are not set");
|
|
6180
|
-
this._options.location = options;
|
|
6181
|
-
return this;
|
|
5785
|
+
return response.data.data;
|
|
6182
5786
|
}
|
|
6183
|
-
async
|
|
6184
|
-
|
|
6185
|
-
|
|
6186
|
-
const resolvedEntity = typeof entity === "object" && "schemaId" in entity ? void 0 : await this.entityResolverService.resolveEntity(entity, {
|
|
6187
|
-
link: urls[0],
|
|
6188
|
-
location: this._options.location,
|
|
6189
|
-
navigationMode
|
|
5787
|
+
async deleteAllRules(data) {
|
|
5788
|
+
const response = await this.validationApi.v4DataValidationRulesActionsDeleteAllDelete({
|
|
5789
|
+
deleteRuleWithReason: data
|
|
6190
5790
|
});
|
|
6191
|
-
if (
|
|
6192
|
-
throw
|
|
6193
|
-
|
|
6194
|
-
details: { entity }
|
|
5791
|
+
if (response.status !== 200 || response.data.error) {
|
|
5792
|
+
throw KadoaHttpException.wrap(response.data.data, {
|
|
5793
|
+
message: response.data.message || "Failed to delete all validation rules"
|
|
6195
5794
|
});
|
|
6196
5795
|
}
|
|
6197
|
-
|
|
6198
|
-
|
|
6199
|
-
|
|
6200
|
-
|
|
6201
|
-
|
|
6202
|
-
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
|
|
6208
|
-
|
|
5796
|
+
return response.data.data;
|
|
5797
|
+
}
|
|
5798
|
+
};
|
|
5799
|
+
|
|
5800
|
+
// src/domains/workflows/workflows.acl.ts
|
|
5801
|
+
var JobStateEnum = {
|
|
5802
|
+
Finished: "FINISHED",
|
|
5803
|
+
Failed: "FAILED",
|
|
5804
|
+
NotSupported: "NOT_SUPPORTED",
|
|
5805
|
+
FailedInsufficientFunds: "FAILED_INSUFFICIENT_FUNDS"
|
|
5806
|
+
};
|
|
5807
|
+
|
|
5808
|
+
// src/domains/workflows/workflows-core.service.ts
|
|
5809
|
+
var TERMINAL_JOB_STATES = /* @__PURE__ */ new Set([
|
|
5810
|
+
JobStateEnum.Finished,
|
|
5811
|
+
JobStateEnum.Failed,
|
|
5812
|
+
JobStateEnum.NotSupported,
|
|
5813
|
+
JobStateEnum.FailedInsufficientFunds
|
|
5814
|
+
]);
|
|
5815
|
+
var TERMINAL_RUN_STATES = /* @__PURE__ */ new Set([
|
|
5816
|
+
"FINISHED",
|
|
5817
|
+
"SUCCESS",
|
|
5818
|
+
"FAILED",
|
|
5819
|
+
"ERROR",
|
|
5820
|
+
"STOPPED",
|
|
5821
|
+
"CANCELLED"
|
|
5822
|
+
]);
|
|
5823
|
+
var debug6 = logger.workflow;
|
|
5824
|
+
var WorkflowsCoreService = class {
|
|
5825
|
+
constructor(workflowsApi) {
|
|
5826
|
+
this.workflowsApi = workflowsApi;
|
|
5827
|
+
}
|
|
5828
|
+
async create(input) {
|
|
5829
|
+
const request = {
|
|
5830
|
+
urls: input.urls,
|
|
5831
|
+
name: input.name,
|
|
5832
|
+
schemaId: input.schemaId,
|
|
5833
|
+
description: input.description,
|
|
5834
|
+
navigationMode: input.navigationMode,
|
|
5835
|
+
entity: input.entity,
|
|
5836
|
+
fields: input.fields,
|
|
5837
|
+
bypassPreview: input.bypassPreview ?? true,
|
|
5838
|
+
tags: input.tags,
|
|
5839
|
+
interval: input.interval,
|
|
5840
|
+
monitoring: input.monitoring,
|
|
5841
|
+
location: input.location,
|
|
5842
|
+
autoStart: input.autoStart,
|
|
5843
|
+
schedules: input.schedules
|
|
5844
|
+
};
|
|
5845
|
+
const response = await this.workflowsApi.v4WorkflowsPost({
|
|
5846
|
+
createWorkflowBody: request
|
|
6209
5847
|
});
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
|
|
6213
|
-
|
|
5848
|
+
const workflowId = response.data?.workflowId;
|
|
5849
|
+
if (!workflowId) {
|
|
5850
|
+
throw new KadoaSdkException(ERROR_MESSAGES.NO_WORKFLOW_ID, {
|
|
5851
|
+
code: "INTERNAL_ERROR",
|
|
5852
|
+
details: {
|
|
5853
|
+
response: response.data
|
|
5854
|
+
}
|
|
6214
5855
|
});
|
|
6215
5856
|
}
|
|
6216
|
-
|
|
6217
|
-
return this;
|
|
5857
|
+
return { id: workflowId };
|
|
6218
5858
|
}
|
|
6219
|
-
async
|
|
6220
|
-
|
|
6221
|
-
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
{ variables: options?.variables, limit: options?.limit }
|
|
6225
|
-
);
|
|
6226
|
-
debug7("Job started: %O", startedJob);
|
|
6227
|
-
this._jobId = startedJob.jobId;
|
|
6228
|
-
const finishedJob = await this.workflowsCoreService.waitForJobCompletion(
|
|
6229
|
-
this._workflowId,
|
|
6230
|
-
startedJob.jobId
|
|
6231
|
-
);
|
|
6232
|
-
debug7("Job finished: %O", finishedJob);
|
|
6233
|
-
return this;
|
|
5859
|
+
async get(id) {
|
|
5860
|
+
const response = await this.workflowsApi.v4WorkflowsWorkflowIdGet({
|
|
5861
|
+
workflowId: id
|
|
5862
|
+
});
|
|
5863
|
+
return response.data;
|
|
6234
5864
|
}
|
|
6235
|
-
async
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
|
|
6239
|
-
|
|
6240
|
-
|
|
5865
|
+
async list(filters) {
|
|
5866
|
+
const response = await this.workflowsApi.v4WorkflowsGet(filters);
|
|
5867
|
+
return response.data?.workflows ?? [];
|
|
5868
|
+
}
|
|
5869
|
+
async getByName(name) {
|
|
5870
|
+
const response = await this.workflowsApi.v4WorkflowsGet({
|
|
5871
|
+
search: name
|
|
5872
|
+
});
|
|
5873
|
+
return response.data?.workflows?.[0];
|
|
5874
|
+
}
|
|
5875
|
+
async cancel(id) {
|
|
5876
|
+
await this.workflowsApi.v4WorkflowsWorkflowIdDelete({
|
|
5877
|
+
workflowId: id
|
|
5878
|
+
});
|
|
5879
|
+
}
|
|
5880
|
+
async resume(id) {
|
|
5881
|
+
await this.workflowsApi.v4WorkflowsWorkflowIdResumePut({
|
|
5882
|
+
workflowId: id
|
|
5883
|
+
});
|
|
5884
|
+
}
|
|
5885
|
+
/**
|
|
5886
|
+
* Wait for a workflow to reach the target state or a terminal state if no target state is provided
|
|
5887
|
+
*/
|
|
5888
|
+
async wait(id, options) {
|
|
5889
|
+
let last;
|
|
5890
|
+
const result = await pollUntil(
|
|
5891
|
+
async () => {
|
|
5892
|
+
const current = await this.get(id);
|
|
5893
|
+
if (last?.state !== current.state || last?.runState !== current.runState) {
|
|
5894
|
+
debug6(
|
|
5895
|
+
"workflow %s state: [workflowState: %s, jobState: %s]",
|
|
5896
|
+
id,
|
|
5897
|
+
current.state,
|
|
5898
|
+
current.runState
|
|
5899
|
+
);
|
|
5900
|
+
}
|
|
5901
|
+
last = current;
|
|
5902
|
+
return current;
|
|
5903
|
+
},
|
|
5904
|
+
(current) => {
|
|
5905
|
+
if (options?.targetState && current.state === options.targetState) {
|
|
5906
|
+
return true;
|
|
5907
|
+
}
|
|
5908
|
+
if (current.runState && TERMINAL_RUN_STATES.has(current.runState.toUpperCase()) && current.state !== "QUEUED") {
|
|
5909
|
+
return true;
|
|
5910
|
+
}
|
|
5911
|
+
return false;
|
|
5912
|
+
},
|
|
5913
|
+
options
|
|
6241
5914
|
);
|
|
6242
|
-
|
|
6243
|
-
|
|
5915
|
+
return result.result;
|
|
5916
|
+
}
|
|
5917
|
+
/**
|
|
5918
|
+
* Run a workflow with variables and optional limit
|
|
5919
|
+
*/
|
|
5920
|
+
async runWorkflow(workflowId, input) {
|
|
5921
|
+
const response = await this.workflowsApi.v4WorkflowsWorkflowIdRunPut({
|
|
5922
|
+
workflowId,
|
|
5923
|
+
v4WorkflowsWorkflowIdRunPutRequest: {
|
|
5924
|
+
variables: input.variables,
|
|
5925
|
+
limit: input.limit
|
|
5926
|
+
}
|
|
5927
|
+
});
|
|
5928
|
+
const jobId = response.data?.jobId;
|
|
5929
|
+
if (!jobId) {
|
|
5930
|
+
throw new KadoaSdkException(ERROR_MESSAGES.NO_WORKFLOW_ID, {
|
|
5931
|
+
code: "INTERNAL_ERROR",
|
|
5932
|
+
details: {
|
|
5933
|
+
response: response.data
|
|
5934
|
+
}
|
|
5935
|
+
});
|
|
5936
|
+
}
|
|
6244
5937
|
return {
|
|
6245
|
-
|
|
6246
|
-
|
|
5938
|
+
jobId,
|
|
5939
|
+
message: response.data?.message,
|
|
5940
|
+
status: response.data?.status
|
|
6247
5941
|
};
|
|
6248
5942
|
}
|
|
6249
|
-
|
|
6250
|
-
|
|
6251
|
-
|
|
6252
|
-
|
|
6253
|
-
|
|
6254
|
-
|
|
6255
|
-
|
|
6256
|
-
limit: options.limit ?? 100,
|
|
6257
|
-
...options
|
|
5943
|
+
/**
|
|
5944
|
+
* Get job status directly without polling workflow details
|
|
5945
|
+
*/
|
|
5946
|
+
async getJobStatus(workflowId, jobId) {
|
|
5947
|
+
const response = await this.workflowsApi.v4WorkflowsWorkflowIdJobsJobIdGet({
|
|
5948
|
+
workflowId,
|
|
5949
|
+
jobId
|
|
6258
5950
|
});
|
|
5951
|
+
return response.data;
|
|
6259
5952
|
}
|
|
6260
|
-
|
|
6261
|
-
|
|
6262
|
-
|
|
6263
|
-
|
|
6264
|
-
|
|
6265
|
-
|
|
6266
|
-
|
|
6267
|
-
|
|
5953
|
+
/**
|
|
5954
|
+
* Wait for a job to reach the target state or a terminal state
|
|
5955
|
+
*/
|
|
5956
|
+
async waitForJobCompletion(workflowId, jobId, options) {
|
|
5957
|
+
let last;
|
|
5958
|
+
const result = await pollUntil(
|
|
5959
|
+
async () => {
|
|
5960
|
+
const current = await this.getJobStatus(workflowId, jobId);
|
|
5961
|
+
if (last?.state !== current.state) {
|
|
5962
|
+
debug6("job %s state: %s", jobId, current.state);
|
|
5963
|
+
}
|
|
5964
|
+
last = current;
|
|
5965
|
+
return current;
|
|
5966
|
+
},
|
|
5967
|
+
(current) => {
|
|
5968
|
+
if (options?.targetStatus && current.state === options.targetStatus) {
|
|
5969
|
+
return true;
|
|
5970
|
+
}
|
|
5971
|
+
if (current.state && TERMINAL_JOB_STATES.has(current.state)) {
|
|
5972
|
+
return true;
|
|
5973
|
+
}
|
|
5974
|
+
return false;
|
|
5975
|
+
},
|
|
5976
|
+
options
|
|
5977
|
+
);
|
|
5978
|
+
return result.result;
|
|
6268
5979
|
}
|
|
6269
5980
|
};
|
|
6270
5981
|
|
|
5982
|
+
// src/domains/validation/validation.facade.ts
|
|
5983
|
+
function createValidationDomain(core, rules) {
|
|
5984
|
+
return {
|
|
5985
|
+
rules,
|
|
5986
|
+
schedule: (workflowId, jobId) => core.scheduleValidation(workflowId, jobId),
|
|
5987
|
+
listWorkflowValidations: (filters) => core.listWorkflowValidations(filters),
|
|
5988
|
+
getValidationDetails: (validationId) => core.getValidationDetails(validationId),
|
|
5989
|
+
toggleEnabled: (workflowId) => core.toggleValidationEnabled(workflowId),
|
|
5990
|
+
getLatest: (workflowId, jobId) => core.getLatestValidation(workflowId, jobId),
|
|
5991
|
+
getAnomalies: (validationId) => core.getValidationAnomalies(validationId),
|
|
5992
|
+
getAnomaliesByRule: (validationId, ruleName) => core.getValidationAnomaliesByRule(validationId, ruleName),
|
|
5993
|
+
waitUntilCompleted: (validationId, options) => core.waitUntilCompleted(validationId, options)
|
|
5994
|
+
};
|
|
5995
|
+
}
|
|
5996
|
+
|
|
6271
5997
|
// src/kadoa-client.ts
|
|
6272
5998
|
var KadoaClient = class {
|
|
6273
5999
|
constructor(config) {
|
|
@@ -6344,7 +6070,9 @@ var KadoaClient = class {
|
|
|
6344
6070
|
workflowsCoreService,
|
|
6345
6071
|
dataFetcherService,
|
|
6346
6072
|
entityResolverService,
|
|
6347
|
-
channelSetupService
|
|
6073
|
+
channelSetupService,
|
|
6074
|
+
channelsService,
|
|
6075
|
+
settingsService
|
|
6348
6076
|
);
|
|
6349
6077
|
this._extractionBuilderService = new ExtractionBuilderService(
|
|
6350
6078
|
workflowsCoreService,
|
|
@@ -6352,22 +6080,19 @@ var KadoaClient = class {
|
|
|
6352
6080
|
dataFetcherService,
|
|
6353
6081
|
channelSetupService
|
|
6354
6082
|
);
|
|
6355
|
-
this.user =
|
|
6356
|
-
this.extraction =
|
|
6357
|
-
|
|
6358
|
-
|
|
6359
|
-
|
|
6360
|
-
|
|
6361
|
-
|
|
6362
|
-
|
|
6363
|
-
|
|
6364
|
-
|
|
6365
|
-
|
|
6366
|
-
|
|
6367
|
-
|
|
6368
|
-
channelSetupService
|
|
6369
|
-
);
|
|
6370
|
-
this.validation = new ValidationModule(coreService, rulesService);
|
|
6083
|
+
this.user = userService;
|
|
6084
|
+
this.extraction = extractionService;
|
|
6085
|
+
this.workflow = workflowsCoreService;
|
|
6086
|
+
this.schema = schemasService;
|
|
6087
|
+
this.notification = {
|
|
6088
|
+
channels: channelsService,
|
|
6089
|
+
settings: settingsService,
|
|
6090
|
+
setup: channelSetupService,
|
|
6091
|
+
configure: (options) => channelSetupService.setup(options),
|
|
6092
|
+
setupForWorkflow: (request) => channelSetupService.setupForWorkflow(request),
|
|
6093
|
+
setupForWorkspace: (request) => channelSetupService.setupForWorkspace(request)
|
|
6094
|
+
};
|
|
6095
|
+
this.validation = createValidationDomain(coreService, rulesService);
|
|
6371
6096
|
if (config.enableRealtime && config.realtimeConfig?.autoConnect !== false) {
|
|
6372
6097
|
this.connectRealtime();
|
|
6373
6098
|
}
|
|
@@ -6506,13 +6231,28 @@ var KadoaClient = class {
|
|
|
6506
6231
|
}
|
|
6507
6232
|
};
|
|
6508
6233
|
|
|
6234
|
+
exports.DataFetcherService = DataFetcherService;
|
|
6509
6235
|
exports.ERROR_MESSAGES = ERROR_MESSAGES;
|
|
6236
|
+
exports.EntityResolverService = EntityResolverService;
|
|
6237
|
+
exports.ExtractionBuilderService = ExtractionBuilderService;
|
|
6238
|
+
exports.ExtractionService = ExtractionService;
|
|
6239
|
+
exports.FetchDataOptions = FetchDataOptions;
|
|
6510
6240
|
exports.KadoaClient = KadoaClient;
|
|
6511
6241
|
exports.KadoaHttpException = KadoaHttpException;
|
|
6512
6242
|
exports.KadoaSdkException = KadoaSdkException;
|
|
6243
|
+
exports.NotificationChannelType = NotificationChannelType;
|
|
6244
|
+
exports.NotificationChannelsService = NotificationChannelsService;
|
|
6245
|
+
exports.NotificationSettingsEventTypeEnum = V5NotificationsSettingsGetEventTypeEnum;
|
|
6246
|
+
exports.NotificationSettingsService = NotificationSettingsService;
|
|
6247
|
+
exports.NotificationSetupService = NotificationSetupService;
|
|
6248
|
+
exports.Realtime = Realtime;
|
|
6513
6249
|
exports.SchemaBuilder = SchemaBuilder;
|
|
6514
|
-
exports.
|
|
6515
|
-
exports.
|
|
6250
|
+
exports.SchemaFieldDataType = SchemaFieldDataType;
|
|
6251
|
+
exports.SchemasService = SchemasService;
|
|
6252
|
+
exports.UserService = UserService;
|
|
6253
|
+
exports.ValidationCoreService = ValidationCoreService;
|
|
6254
|
+
exports.ValidationRulesService = ValidationRulesService;
|
|
6255
|
+
exports.WorkflowsCoreService = WorkflowsCoreService;
|
|
6516
6256
|
exports.pollUntil = pollUntil;
|
|
6517
6257
|
//# sourceMappingURL=index.js.map
|
|
6518
6258
|
//# sourceMappingURL=index.js.map
|