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