ugcinc 4.5.91 → 4.5.93
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/automations/graph-controller.js +44 -2
- package/dist/automations/nodes/api-request.d.ts +11 -1
- package/dist/automations/nodes/api-request.js +39 -25
- package/dist/automations/nodes/index.d.ts +1 -1
- package/dist/automations/types.d.ts +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/stats.d.ts +21 -5
- package/dist/stats.js +7 -0
- package/package.json +1 -1
|
@@ -846,10 +846,52 @@ function validateWorkflow({ nodes, }) {
|
|
|
846
846
|
}
|
|
847
847
|
}
|
|
848
848
|
}
|
|
849
|
-
// 7. Check for
|
|
849
|
+
// 7. Check for duplicate port names across input nodes
|
|
850
|
+
const inputPortSeen = new Map(); // portName -> first nodeId
|
|
851
|
+
for (const node of nodes) {
|
|
852
|
+
if (node.type !== 'input')
|
|
853
|
+
continue;
|
|
854
|
+
const outputs = node.config.outputs ?? [];
|
|
855
|
+
for (const output of outputs) {
|
|
856
|
+
const existing = inputPortSeen.get(output.id);
|
|
857
|
+
if (existing) {
|
|
858
|
+
errors.push({
|
|
859
|
+
type: 'duplicate_port_name',
|
|
860
|
+
nodeId: node.id,
|
|
861
|
+
portId: output.id,
|
|
862
|
+
message: `Duplicate input port name '${output.id}' — each input port must have a unique name across all input nodes`,
|
|
863
|
+
});
|
|
864
|
+
}
|
|
865
|
+
else {
|
|
866
|
+
inputPortSeen.set(output.id, node.id);
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
// 8. Check for duplicate port names across output (passthrough) nodes
|
|
871
|
+
const outputPortSeen = new Map(); // portName -> first nodeId
|
|
872
|
+
for (const node of nodes) {
|
|
873
|
+
if (node.type !== 'passthrough')
|
|
874
|
+
continue;
|
|
875
|
+
const inputs = node.config.inputs ?? [];
|
|
876
|
+
for (const input of inputs) {
|
|
877
|
+
const existing = outputPortSeen.get(input.id);
|
|
878
|
+
if (existing) {
|
|
879
|
+
errors.push({
|
|
880
|
+
type: 'duplicate_port_name',
|
|
881
|
+
nodeId: node.id,
|
|
882
|
+
portId: input.id,
|
|
883
|
+
message: `Duplicate output port name '${input.id}' — each output port must have a unique name across all output nodes`,
|
|
884
|
+
});
|
|
885
|
+
}
|
|
886
|
+
else {
|
|
887
|
+
outputPortSeen.set(input.id, node.id);
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
// 9. Check for circular dependencies
|
|
850
892
|
const circularErrors = detectCircularDependencies(nodes);
|
|
851
893
|
errors.push(...circularErrors);
|
|
852
|
-
//
|
|
894
|
+
// 10. Check for for-each context boundary violations
|
|
853
895
|
const boundaryErrors = validateForEachContextBoundaries(nodes);
|
|
854
896
|
errors.push(...boundaryErrors);
|
|
855
897
|
return errors;
|
|
@@ -10,12 +10,22 @@ export interface HeaderEntry {
|
|
|
10
10
|
key: string;
|
|
11
11
|
value: string;
|
|
12
12
|
}
|
|
13
|
+
export type ApiRequestOutputPrimitiveType = 'string' | 'number' | 'boolean' | 'image';
|
|
14
|
+
export type ApiRequestArrayItemType = ApiRequestOutputPrimitiveType | 'object';
|
|
15
|
+
export type ApiRequestOutputType = ApiRequestOutputPrimitiveType | 'object' | 'array';
|
|
16
|
+
export interface ApiRequestOutputField {
|
|
17
|
+
name: string;
|
|
18
|
+
type: ApiRequestOutputType;
|
|
19
|
+
items?: ApiRequestArrayItemType;
|
|
20
|
+
objectSchema?: ObjectSchemaField[];
|
|
21
|
+
required?: boolean;
|
|
22
|
+
}
|
|
13
23
|
declare const definition: import("./types").NodeDefinition<"api-request", "generator", {
|
|
14
24
|
url: string;
|
|
15
25
|
method: HttpMethod;
|
|
16
26
|
headers: HeaderEntry[];
|
|
17
27
|
body: string;
|
|
18
|
-
outputFields:
|
|
28
|
+
outputFields: ApiRequestOutputField[];
|
|
19
29
|
outputMode: OutputMode;
|
|
20
30
|
selectionMode: SelectionMode | null;
|
|
21
31
|
}, ApiRequestNodeInputs, ApiRequestNodeOutputs, false>;
|
|
@@ -8,6 +8,41 @@ const types_1 = require("./types");
|
|
|
8
8
|
// =============================================================================
|
|
9
9
|
const HttpMethods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'];
|
|
10
10
|
exports.HttpMethods = HttpMethods;
|
|
11
|
+
function getArrayItemPortType(items) {
|
|
12
|
+
switch (items) {
|
|
13
|
+
case 'number':
|
|
14
|
+
return 'number';
|
|
15
|
+
case 'boolean':
|
|
16
|
+
return 'boolean';
|
|
17
|
+
case 'object':
|
|
18
|
+
return 'object';
|
|
19
|
+
case 'image':
|
|
20
|
+
return 'image';
|
|
21
|
+
default:
|
|
22
|
+
return 'text';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function getOutputPortShape(field) {
|
|
26
|
+
if (field.type === 'array') {
|
|
27
|
+
return {
|
|
28
|
+
type: getArrayItemPortType(field.items),
|
|
29
|
+
isArray: true,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
if (field.type === 'object') {
|
|
33
|
+
return { type: 'object', isArray: false };
|
|
34
|
+
}
|
|
35
|
+
if (field.type === 'number') {
|
|
36
|
+
return { type: 'number', isArray: false };
|
|
37
|
+
}
|
|
38
|
+
if (field.type === 'boolean') {
|
|
39
|
+
return { type: 'boolean', isArray: false };
|
|
40
|
+
}
|
|
41
|
+
if (field.type === 'image') {
|
|
42
|
+
return { type: 'image', isArray: false };
|
|
43
|
+
}
|
|
44
|
+
return { type: 'text', isArray: false };
|
|
45
|
+
}
|
|
11
46
|
// =============================================================================
|
|
12
47
|
// Node Definition
|
|
13
48
|
// =============================================================================
|
|
@@ -15,7 +50,7 @@ const definition = (0, types_1.defineNode)({
|
|
|
15
50
|
nodeId: 'api-request',
|
|
16
51
|
label: 'API Request',
|
|
17
52
|
description: 'Make HTTP requests to external APIs',
|
|
18
|
-
guide: 'Makes HTTP requests to external APIs and returns parsed response data. Use when you need to fetch data from or send data to external services. Configure URL, method (GET/POST/PUT/PATCH/DELETE), headers, and body. Supports template variables ({{var}}) in URL, header values, and body for dynamic values from upstream nodes. Define output fields to extract specific data from JSON responses. Use cases: fetching external data, triggering webhooks, integrating third-party APIs, sending data to external services.',
|
|
53
|
+
guide: 'Makes HTTP requests to external APIs and returns parsed response data. Use when you need to fetch data from or send data to external services. Configure URL, method (GET/POST/PUT/PATCH/DELETE), headers, and body. Supports template variables ({{var}}) in URL, header values, and body for dynamic values from upstream nodes. Define output fields to extract specific data from JSON responses, including typed arrays and image URL fields that should flow into image ports. Use cases: fetching external data, triggering webhooks, integrating third-party APIs, sending data to external services.',
|
|
19
54
|
type: 'generator',
|
|
20
55
|
category: 'Generation',
|
|
21
56
|
outputModes: ['per-input', 'single'],
|
|
@@ -49,32 +84,11 @@ const definition = (0, types_1.defineNode)({
|
|
|
49
84
|
// Output ports from outputFields
|
|
50
85
|
const outputFields = (config?.outputFields ?? [{ name: 'response', type: 'string' }]);
|
|
51
86
|
const outputs = outputFields.map(f => {
|
|
52
|
-
|
|
53
|
-
let pIsArray;
|
|
54
|
-
if (f.type === 'array') {
|
|
55
|
-
pType = f.items === 'object' ? 'object' : 'text';
|
|
56
|
-
pIsArray = true;
|
|
57
|
-
}
|
|
58
|
-
else if (f.type === 'object') {
|
|
59
|
-
pType = 'object';
|
|
60
|
-
pIsArray = false;
|
|
61
|
-
}
|
|
62
|
-
else if (f.type === 'number') {
|
|
63
|
-
pType = 'number';
|
|
64
|
-
pIsArray = false;
|
|
65
|
-
}
|
|
66
|
-
else if (f.type === 'boolean') {
|
|
67
|
-
pType = 'boolean';
|
|
68
|
-
pIsArray = false;
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
pType = 'text';
|
|
72
|
-
pIsArray = false;
|
|
73
|
-
}
|
|
87
|
+
const { type, isArray } = getOutputPortShape(f);
|
|
74
88
|
return {
|
|
75
89
|
id: f.name,
|
|
76
|
-
type
|
|
77
|
-
isArray
|
|
90
|
+
type,
|
|
91
|
+
isArray,
|
|
78
92
|
required: f.required ?? true,
|
|
79
93
|
...(f.objectSchema && { objectSchema: f.objectSchema }),
|
|
80
94
|
};
|
|
@@ -18,7 +18,7 @@ export declare const nodeDefinitions: {
|
|
|
18
18
|
method: import("./api-request").HttpMethod;
|
|
19
19
|
headers: import("./api-request").HeaderEntry[];
|
|
20
20
|
body: string;
|
|
21
|
-
outputFields: import("./
|
|
21
|
+
outputFields: import("./api-request").ApiRequestOutputField[];
|
|
22
22
|
outputMode: import("./types").OutputMode;
|
|
23
23
|
selectionMode: import("./types").SelectionMode | null;
|
|
24
24
|
}, import("./api-request").ApiRequestNodeInputs, import("./api-request").ApiRequestNodeOutputs, false> & {
|
|
@@ -538,7 +538,7 @@ export declare function isAsyncExecutor(executor: AnyNodeExecutor | AnyAsyncNode
|
|
|
538
538
|
/**
|
|
539
539
|
* Validation error types for automation workflows
|
|
540
540
|
*/
|
|
541
|
-
export type ValidationErrorType = 'missing_trigger' | 'missing_terminal' | 'missing_required_input' | 'type_mismatch' | 'empty_media_pool' | 'empty_account_pool' | 'circular_dependency' | 'for_each_boundary_violation' | 'invalid_node_config';
|
|
541
|
+
export type ValidationErrorType = 'missing_trigger' | 'missing_terminal' | 'missing_required_input' | 'type_mismatch' | 'empty_media_pool' | 'empty_account_pool' | 'circular_dependency' | 'for_each_boundary_violation' | 'invalid_node_config' | 'duplicate_port_name';
|
|
542
542
|
/**
|
|
543
543
|
* Structured validation error with location info for UI highlighting
|
|
544
544
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -28,7 +28,7 @@ export type { ClientConfig } from './base';
|
|
|
28
28
|
export type { Account, AccountStat, AccountTask, EditProfileInfo, GetAccountsParams, GetAccountStatsParams, GetAccountStatusParams, AccountInfoUpdate, UpdateAccountInfoParams, AccountInfoUpdateResult, UpdateAccountInfoResponse, AccountSocialUpdate, UpdateAccountSocialParams, AccountSocialUpdateResult, UpdateAccountSocialResponse, DeleteAccountPostsParams, DeleteAccountPostsResponse, ResetWarmupParams, ResetWarmupResponse, NicheSwitchUpdate, NicheSwitchParams, NicheSwitchResult, NicheSwitchResponse, CreateAccountInput, CreateAccountsParams, CreateAccountResult, CreateAccountsResponse, TroubleshootFailReason, TroubleshootAccount, TroubleshootParams, } from './accounts';
|
|
29
29
|
export type { TaskType, Task, GetTasksParams } from './tasks';
|
|
30
30
|
export type { PostType, PostStatus, Post, PostStat, GetPostsParams, CreateDraftParams, CreateSlideshowParams, GetPostStatsParams, GetPostStatusParams, CreateVideoParams, UpdatePostParams, DeletePostsParams, DeletePostsResponse, RetryPostsParams, SetPostStatusParams, SetPostStatusResponse, PreviewScheduleEntry, PreviewScheduleParams, PreviewScheduleResult, } from './posts';
|
|
31
|
-
export type { RefreshStatsParams, RefreshStatsError, RefreshStatsResponse, RefreshStartEvent, RefreshProgressEvent, RefreshDoneEvent, RefreshStreamEvent, DailyAggregatedStat, GetDailyAggregatedStatsParams, DailyAccountStat, GetDailyAccountStatsParams, DailyPostStat, GetDailyPostStatsParams, DashboardDailyStat, GetDashboardDailyStatsParams, TopAccount, GetTopAccountsParams, TopPost, GetTopPostsParams, } from './stats';
|
|
31
|
+
export type { RefreshStatsParams, RefreshStatsError, RefreshStatsResponse, RefreshStatsProgressResponse, RefreshStartEvent, RefreshProgressEvent, RefreshDoneEvent, RefreshStreamEvent, DailyAggregatedStat, GetDailyAggregatedStatsParams, DailyAccountStat, GetDailyAccountStatsParams, DailyPostStat, GetDailyPostStatsParams, DashboardDailyStat, GetDashboardDailyStatsParams, TopAccount, GetTopAccountsParams, TopPost, GetTopPostsParams, } from './stats';
|
|
32
32
|
export type { Org, ApiKey, DeleteApiKeyParams, EditApiKeyParams, IntegrationKey, IntegrationProvider, UpsertIntegrationKeyParams, DeleteIntegrationKeyParams } from './org';
|
|
33
33
|
export type { UserMedia, MediaUse, SocialAudio, Media, GetMediaParams, GetSocialAudioParams, UploadMediaParams, UploadMediaResponse, MediaTagUpdate, UpdateMediaTagsParams, MediaTagUpdateResult, UpdateMediaTagsResponse, UpdateMediaTagParams, UpdateMediaNameParams, DeleteMediaParams, DeleteMediaResponse, CreateSocialAudioParams, ImportTextParams, ImportTextResponse, CreateMediaFromUrlParams, GetMediaUseParams, GetMediaUseResponse, FilterMediaParams, FilterMediaResponse, GetUploadTokenParams, UploadTokenResponse, } from './media';
|
|
34
34
|
export type { CommentStatus, Comment, CreateCommentParams, CreateCommentResponse, GetCommentsParams, } from './comments';
|
|
@@ -38,7 +38,7 @@ export type { VideoEditorNodeConfig, VideoEditorChannel, VideoEditorSegment, Vid
|
|
|
38
38
|
export type { ImageEditorNodeConfig, ImageComposerNodeConfig, ImageComposerRenderInput } from './automations/nodes/image-composer';
|
|
39
39
|
export { prepareImageComposerInput } from './automations/nodes/image-composer';
|
|
40
40
|
export type { AccountNodeConfig } from './automations/nodes/account';
|
|
41
|
-
export type { ApiRequestNodeConfig, HeaderEntry, HttpMethod } from './automations/nodes/api-request';
|
|
41
|
+
export type { ApiRequestNodeConfig, ApiRequestOutputField, ApiRequestOutputType, ApiRequestArrayItemType, HeaderEntry, HttpMethod, } from './automations/nodes/api-request';
|
|
42
42
|
export { HttpMethods } from './automations/nodes/api-request';
|
|
43
43
|
export type { AutoCaptionNodeConfig, AutoCaptionPreset, AutoCaptionFontWeight, AutoCaptionPosition, } from './automations/nodes/auto-caption';
|
|
44
44
|
export { nodeConfigToCaptionStyle } from './automations/nodes/auto-caption';
|
package/dist/stats.d.ts
CHANGED
|
@@ -12,11 +12,23 @@ export interface RefreshStatsError {
|
|
|
12
12
|
error: string;
|
|
13
13
|
}
|
|
14
14
|
export interface RefreshStatsResponse {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
batchId: string;
|
|
16
|
+
batchCreatedAtMs: number;
|
|
17
|
+
queuedAccounts: number;
|
|
18
|
+
totalAccounts: number;
|
|
19
|
+
totalPosts: number;
|
|
20
|
+
}
|
|
21
|
+
export interface RefreshStatsProgressResponse {
|
|
22
|
+
batchId: string;
|
|
23
|
+
batchCreatedAtMs: number;
|
|
24
|
+
totalAccounts: number;
|
|
25
|
+
completedAccounts: number;
|
|
26
|
+
failedAccounts: number;
|
|
27
|
+
activeAccounts: number;
|
|
28
|
+
queuedAccounts: number;
|
|
29
|
+
done: boolean;
|
|
30
|
+
totalPosts: number;
|
|
31
|
+
completedPosts: number;
|
|
20
32
|
}
|
|
21
33
|
export interface DailyAggregatedStat {
|
|
22
34
|
date: Date | string;
|
|
@@ -358,6 +370,10 @@ export declare class StatsClient extends BaseClient {
|
|
|
358
370
|
* Note: Can only be called once per hour per organization (or per org_group if specified)
|
|
359
371
|
*/
|
|
360
372
|
refresh(params?: RefreshStatsParams): Promise<ApiResponse<RefreshStatsResponse>>;
|
|
373
|
+
getRefreshProgress(params: {
|
|
374
|
+
batchId: string;
|
|
375
|
+
org_group?: string;
|
|
376
|
+
}): Promise<ApiResponse<RefreshStatsProgressResponse>>;
|
|
361
377
|
/**
|
|
362
378
|
* Refresh stats with NDJSON streaming progress.
|
|
363
379
|
* Returns the raw Response so the caller can read the stream.
|
package/dist/stats.js
CHANGED
|
@@ -209,6 +209,13 @@ class StatsClient extends base_1.BaseClient {
|
|
|
209
209
|
async refresh(params) {
|
|
210
210
|
return this.post('/stats/refresh', params ?? {});
|
|
211
211
|
}
|
|
212
|
+
async getRefreshProgress(params) {
|
|
213
|
+
const searchParams = new URLSearchParams({ batchId: params.batchId });
|
|
214
|
+
if (params.org_group) {
|
|
215
|
+
searchParams.set('org_group', params.org_group);
|
|
216
|
+
}
|
|
217
|
+
return this.get(`/stats/refresh/progress?${searchParams.toString()}`);
|
|
218
|
+
}
|
|
212
219
|
/**
|
|
213
220
|
* Refresh stats with NDJSON streaming progress.
|
|
214
221
|
* Returns the raw Response so the caller can read the stream.
|