@hira-core/sdk 1.0.2 → 1.0.3
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/README.md +57 -46
- package/dist/index.d.ts +455 -12
- package/dist/index.js +17194 -1
- package/package.json +2 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,19 +1,37 @@
|
|
|
1
|
+
import * as _packages_shared from '@packages/shared';
|
|
2
|
+
import { ProfileOutputValue, IWorkerLogMessage, ProfileStatus, IWorkerOutputMessage } from '@packages/shared';
|
|
1
3
|
import * as puppeteer from 'puppeteer-core';
|
|
2
4
|
import { Browser, Page, Frame, ElementHandle } from 'puppeteer-core';
|
|
3
5
|
import { EventEmitter } from 'events';
|
|
4
|
-
import { IWorkerLogMessage, ProfileStatus } from '@packages/shared';
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Unified profile interface — provider-agnostic.
|
|
9
|
+
* Both GPM and Hidemium (and future providers) map their native profiles to this.
|
|
10
|
+
*/
|
|
11
|
+
interface IAntidetectProfile {
|
|
12
|
+
/** Unique ID (GPM: id, Hidemium: uuid) */
|
|
7
13
|
id: string;
|
|
14
|
+
/** Human-readable profile name */
|
|
8
15
|
name: string;
|
|
16
|
+
/** Which antidetect provider */
|
|
17
|
+
provider: "gpm" | "hidemium" | "genlogin";
|
|
18
|
+
/** Raw proxy string (format varies per provider) */
|
|
9
19
|
raw_proxy?: string;
|
|
20
|
+
/** Browser engine */
|
|
10
21
|
browser_type: "chromium" | "firefox";
|
|
22
|
+
/** Browser version string */
|
|
11
23
|
browser_version: string;
|
|
24
|
+
/** Group/folder ID (if supported) */
|
|
12
25
|
group_id?: string;
|
|
26
|
+
/** Local profile data path */
|
|
13
27
|
profile_path: string;
|
|
28
|
+
/** User note */
|
|
14
29
|
note: string;
|
|
30
|
+
/** ISO 8601 */
|
|
15
31
|
created_at: string;
|
|
16
32
|
}
|
|
33
|
+
/** @deprecated Use IAntidetectProfile instead */
|
|
34
|
+
type IGpmProfile = IAntidetectProfile;
|
|
17
35
|
type IInputType = "text" | "number" | "boolean" | "select" | "textarea";
|
|
18
36
|
type InputTypeMap = {
|
|
19
37
|
text: string;
|
|
@@ -34,21 +52,178 @@ interface IInputField {
|
|
|
34
52
|
value: string | number;
|
|
35
53
|
}[];
|
|
36
54
|
}
|
|
55
|
+
interface IOutputField {
|
|
56
|
+
index: number;
|
|
57
|
+
key: string;
|
|
58
|
+
label: string;
|
|
59
|
+
}
|
|
37
60
|
interface IFlowConfig {
|
|
38
61
|
globalInput: readonly IInputField[];
|
|
39
62
|
profileInput: readonly IInputField[];
|
|
63
|
+
output?: readonly IOutputField[];
|
|
40
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Generic duplicate finder cho string property — duyệt recursive qua array,
|
|
67
|
+
* extract giá trị của property `P` và check xem có xuất hiện > 1 lần không.
|
|
68
|
+
*/
|
|
69
|
+
type FindDuplicates<T extends readonly Record<string, any>[], P extends string, Seen extends string = never> = T extends readonly [
|
|
70
|
+
infer Head extends Record<string, any>,
|
|
71
|
+
...infer Tail extends Record<string, any>[]
|
|
72
|
+
] ? Head[P] extends string ? Head[P] extends Seen ? Head[P] | FindDuplicates<Tail, P, Seen> : FindDuplicates<Tail, P, Seen | Head[P]> : FindDuplicates<Tail, P, Seen> : never;
|
|
73
|
+
/**
|
|
74
|
+
* Duplicate finder cho number property (dùng cho output index).
|
|
75
|
+
* Convert number → template literal string để so sánh.
|
|
76
|
+
*/
|
|
77
|
+
type FindDuplicateNumbers<T extends readonly Record<string, any>[], P extends string, Seen extends number = never> = T extends readonly [
|
|
78
|
+
infer Head extends Record<string, any>,
|
|
79
|
+
...infer Tail extends Record<string, any>[]
|
|
80
|
+
] ? Head[P] extends number ? Head[P] extends Seen ? Head[P] | FindDuplicateNumbers<Tail, P, Seen> : FindDuplicateNumbers<Tail, P, Seen | Head[P]> : FindDuplicateNumbers<Tail, P, Seen> : never;
|
|
81
|
+
/**
|
|
82
|
+
* Duplicate finder cho string | number property (dùng cho options value).
|
|
83
|
+
*/
|
|
84
|
+
type FindDuplicateValues<T extends readonly Record<string, any>[], P extends string, Seen extends string | number = never> = T extends readonly [
|
|
85
|
+
infer Head extends Record<string, any>,
|
|
86
|
+
...infer Tail extends Record<string, any>[]
|
|
87
|
+
] ? Head[P] extends string | number ? Head[P] extends Seen ? Head[P] | FindDuplicateValues<Tail, P, Seen> : FindDuplicateValues<Tail, P, Seen | Head[P]> : FindDuplicateValues<Tail, P, Seen> : never;
|
|
88
|
+
type AssertUniqueKeysAndLabels<T extends readonly {
|
|
89
|
+
key: string;
|
|
90
|
+
label: string;
|
|
91
|
+
}[]> = FindDuplicates<T, "key"> extends never ? FindDuplicates<T, "label"> extends never ? T : readonly [
|
|
92
|
+
`❌ ERROR: Duplicate label(s) found: "${FindDuplicates<T, "label">}"`,
|
|
93
|
+
never
|
|
94
|
+
] : FindDuplicates<T, "label"> extends never ? readonly [
|
|
95
|
+
`❌ ERROR: Duplicate key(s) found: "${FindDuplicates<T, "key">}"`,
|
|
96
|
+
never
|
|
97
|
+
] : readonly [
|
|
98
|
+
`❌ ERROR: Duplicate key(s): "${FindDuplicates<T, "key">}" AND duplicate label(s): "${FindDuplicates<T, "label">}"`,
|
|
99
|
+
never
|
|
100
|
+
];
|
|
101
|
+
type AssertUniqueOutputFields<T extends readonly {
|
|
102
|
+
index: number;
|
|
103
|
+
key: string;
|
|
104
|
+
label: string;
|
|
105
|
+
}[]> = FindDuplicateNumbers<T, "index"> extends never ? AssertUniqueKeysAndLabels<T> : readonly [
|
|
106
|
+
`❌ ERROR: Duplicate index(es) found: ${FindDuplicateNumbers<T, "index">}`,
|
|
107
|
+
never
|
|
108
|
+
];
|
|
109
|
+
/**
|
|
110
|
+
* Check 1 options array: label unique + value unique.
|
|
111
|
+
* Trả T nếu OK, error tuple nếu duplicate.
|
|
112
|
+
*/
|
|
113
|
+
type AssertUniqueOptions<T extends readonly {
|
|
114
|
+
label: string;
|
|
115
|
+
value: string | number;
|
|
116
|
+
}[]> = FindDuplicates<T, "label"> extends never ? FindDuplicateValues<T, "value"> extends never ? T : readonly [
|
|
117
|
+
`❌ ERROR: Duplicate option value(s) found: "${FindDuplicateValues<T, "value">}"`,
|
|
118
|
+
never
|
|
119
|
+
] : FindDuplicateValues<T, "value"> extends never ? readonly [
|
|
120
|
+
`❌ ERROR: Duplicate option label(s) found: "${FindDuplicates<T, "label">}"`,
|
|
121
|
+
never
|
|
122
|
+
] : readonly [
|
|
123
|
+
`❌ ERROR: Duplicate option label(s): "${FindDuplicates<T, "label">}" AND duplicate option value(s): "${FindDuplicateValues<T, "value">}"`,
|
|
124
|
+
never
|
|
125
|
+
];
|
|
126
|
+
/**
|
|
127
|
+
* Map từng field trong input array — nếu field có `options`,
|
|
128
|
+
* validate options[].label + options[].value unique.
|
|
129
|
+
*/
|
|
130
|
+
type ValidateInputOptions<T extends readonly IInputField[]> = {
|
|
131
|
+
readonly [I in keyof T]: T[I] extends {
|
|
132
|
+
options: infer O extends readonly {
|
|
133
|
+
label: string;
|
|
134
|
+
value: string | number;
|
|
135
|
+
}[];
|
|
136
|
+
} ? Omit<T[I], "options"> & {
|
|
137
|
+
options: AssertUniqueOptions<O>;
|
|
138
|
+
} : T[I];
|
|
139
|
+
};
|
|
140
|
+
/**
|
|
141
|
+
* Validate unique key + label cho input array.
|
|
142
|
+
* Nếu key/label trùng → trả error tuple, ngược lại → validate options.
|
|
143
|
+
*/
|
|
144
|
+
type ValidateInputArray<T extends readonly IInputField[]> = FindDuplicates<T, "key"> extends never ? FindDuplicates<T, "label"> extends never ? ValidateInputOptions<T> : readonly [
|
|
145
|
+
`❌ ERROR: Duplicate label(s) found: "${FindDuplicates<T, "label">}"`,
|
|
146
|
+
never
|
|
147
|
+
] : FindDuplicates<T, "label"> extends never ? readonly [
|
|
148
|
+
`❌ ERROR: Duplicate key(s) found: "${FindDuplicates<T, "key">}"`,
|
|
149
|
+
never
|
|
150
|
+
] : readonly [
|
|
151
|
+
`❌ ERROR: Duplicate key(s): "${FindDuplicates<T, "key">}" AND duplicate label(s): "${FindDuplicates<T, "label">}"`,
|
|
152
|
+
never
|
|
153
|
+
];
|
|
154
|
+
/**
|
|
155
|
+
* StrictFlowConfig — kiểm tra tất cả constraints:
|
|
156
|
+
* - globalInput: unique key + label + options (label, value) per field
|
|
157
|
+
* - profileInput: unique key + label + options (label, value) per field
|
|
158
|
+
* - output: unique key + label + index
|
|
159
|
+
*/
|
|
160
|
+
type StrictFlowConfig<T extends IFlowConfig> = {
|
|
161
|
+
globalInput: ValidateInputArray<T["globalInput"]>;
|
|
162
|
+
profileInput: ValidateInputArray<T["profileInput"]>;
|
|
163
|
+
output: T["output"] extends readonly IOutputField[] ? AssertUniqueOutputFields<T["output"]> : T["output"];
|
|
164
|
+
};
|
|
165
|
+
/**
|
|
166
|
+
* Helper function — validate config at type level + return typed config.
|
|
167
|
+
* Dùng thay vì `as const satisfies IFlowConfig` để bắt duplicate key & label.
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* ```ts
|
|
171
|
+
* // ✅ OK — không trùng
|
|
172
|
+
* const config = defineFlowConfig({
|
|
173
|
+
* globalInput: [
|
|
174
|
+
* { key: "url", label: "URL", type: "text" },
|
|
175
|
+
* ],
|
|
176
|
+
* profileInput: [
|
|
177
|
+
* { key: "user", label: "User", type: "text" },
|
|
178
|
+
* ],
|
|
179
|
+
* output: [
|
|
180
|
+
* { index: 0, key: "status", label: "Status" },
|
|
181
|
+
* { index: 1, key: "title", label: "Title" },
|
|
182
|
+
* ],
|
|
183
|
+
* });
|
|
184
|
+
*
|
|
185
|
+
* // ❌ TS Error — duplicate key "url" in globalInput
|
|
186
|
+
* const bad = defineFlowConfig({
|
|
187
|
+
* globalInput: [
|
|
188
|
+
* { key: "url", label: "URL 1", type: "text" },
|
|
189
|
+
* { key: "url", label: "URL 2", type: "text" },
|
|
190
|
+
* ],
|
|
191
|
+
* ...
|
|
192
|
+
* });
|
|
193
|
+
*
|
|
194
|
+
* // ❌ TS Error — duplicate label "Status" in output
|
|
195
|
+
* const bad2 = defineFlowConfig({
|
|
196
|
+
* output: [
|
|
197
|
+
* { index: 0, key: "status1", label: "Status" },
|
|
198
|
+
* { index: 1, key: "status2", label: "Status" },
|
|
199
|
+
* ],
|
|
200
|
+
* ...
|
|
201
|
+
* });
|
|
202
|
+
* ```
|
|
203
|
+
*/
|
|
204
|
+
declare function defineFlowConfig<const T extends IFlowConfig>(config: T & StrictFlowConfig<T>): T;
|
|
41
205
|
type InferFields<T extends readonly IInputField[]> = {
|
|
42
206
|
[K in T[number] as K["key"]]: K["type"] extends keyof InputTypeMap ? InputTypeMap[K["type"]] : unknown;
|
|
43
207
|
};
|
|
44
208
|
type InferGlobalInput<T extends IFlowConfig> = InferFields<T["globalInput"]>;
|
|
45
209
|
type InferProfileInput<T extends IFlowConfig> = InferFields<T["profileInput"]>;
|
|
210
|
+
/** Extract valid output keys từ config output[] — dùng cho type-safety writeOutput */
|
|
211
|
+
type InferOutputKeys<T extends IFlowConfig> = T["output"] extends readonly IOutputField[] ? T["output"][number]["key"] : string;
|
|
212
|
+
/** Extract valid profileInput keys từ config — dùng cho type-safety writeProfileInput */
|
|
213
|
+
type InferProfileInputKeys<T extends IFlowConfig> = T["profileInput"] extends readonly IInputField[] ? T["profileInput"][number]["key"] : string;
|
|
214
|
+
/**
|
|
215
|
+
* Infer output object type từ config output[].
|
|
216
|
+
* Map mỗi key → ProfileOutputValue | null (null nếu chưa ghi).
|
|
217
|
+
* Dùng cho context.output — truy cập trực tiếp output.isLogined, output.titlePage...
|
|
218
|
+
*/
|
|
219
|
+
type InferOutput<T extends IFlowConfig> = T["output"] extends readonly IOutputField[] ? {
|
|
220
|
+
[K in T["output"][number]["key"]]: _packages_shared.ProfileOutputValue | null;
|
|
221
|
+
} : Record<string, _packages_shared.ProfileOutputValue | null>;
|
|
46
222
|
interface IProfileSetting<TProfileInput = Record<string, unknown>> {
|
|
47
223
|
profileName: string;
|
|
48
224
|
data?: TProfileInput;
|
|
49
225
|
}
|
|
50
226
|
interface IAntidetectConfig<TProfileInput = Record<string, unknown>> {
|
|
51
|
-
name: string;
|
|
52
227
|
profileSettings: IProfileSetting<TProfileInput>[];
|
|
53
228
|
}
|
|
54
229
|
interface IExecutionConfig {
|
|
@@ -56,6 +231,12 @@ interface IExecutionConfig {
|
|
|
56
231
|
delayBetweenProfilesMs?: number;
|
|
57
232
|
maxRetries?: number;
|
|
58
233
|
keepOpenOnError?: boolean;
|
|
234
|
+
/**
|
|
235
|
+
* Which antidetect browser to use.
|
|
236
|
+
* ⚠️ Server/Agent only — Agent inject vào global trước khi chạy Worker.
|
|
237
|
+
* Dev mode: dùng constructor `super(AntidetectProvider.GPM, ...)` trong flow class.
|
|
238
|
+
*/
|
|
239
|
+
antidetectProvider?: 'gpm' | 'hidemium' | 'genlogin' | 'adspower';
|
|
59
240
|
}
|
|
60
241
|
interface IBrowserWindowConfig {
|
|
61
242
|
width: number;
|
|
@@ -67,6 +248,44 @@ interface IFlowRunParams<TConfig extends IFlowConfig = IFlowConfig> {
|
|
|
67
248
|
execution: IExecutionConfig;
|
|
68
249
|
window: IBrowserWindowConfig;
|
|
69
250
|
globalInput?: InferGlobalInput<TConfig>;
|
|
251
|
+
/** Output definitions từ flow config — dùng để validate writeOutput key */
|
|
252
|
+
outputDefinitions?: IOutputField[];
|
|
253
|
+
/**
|
|
254
|
+
* Existing output entries từ lần chạy trước (lấy từ active output slot trên server).
|
|
255
|
+
* Mỗi entry = 1 profile, `data` chứa cipher/JSON của tất cả output keys.
|
|
256
|
+
* SDK nạp vào context.output để flow script đọc giá trị cũ trực tiếp.
|
|
257
|
+
*/
|
|
258
|
+
existingOutputEntries?: _packages_shared.IOutputSlotEntry[];
|
|
259
|
+
}
|
|
260
|
+
interface IEncryptedProfileSetting {
|
|
261
|
+
profileName: string;
|
|
262
|
+
/** AES-256-GCM cipher (base64) chứa toàn bộ profile fields */
|
|
263
|
+
data?: string;
|
|
264
|
+
}
|
|
265
|
+
interface IEncryptedAntidetectConfig {
|
|
266
|
+
name: string;
|
|
267
|
+
profileSettings: IEncryptedProfileSetting[];
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Params truyền từ Server → Agent khi dispatch flow.
|
|
271
|
+
* profiles[].data và globalInput đều ở dạng encrypted string.
|
|
272
|
+
* Agent decrypt trước khi chuyển thành IFlowRunParams để pass vào Worker.
|
|
273
|
+
*/
|
|
274
|
+
interface IEncryptedFlowRunParams {
|
|
275
|
+
antidetect: IEncryptedAntidetectConfig;
|
|
276
|
+
execution: IExecutionConfig;
|
|
277
|
+
window: IBrowserWindowConfig;
|
|
278
|
+
globalInput?: Record<string, unknown> | {
|
|
279
|
+
data: string;
|
|
280
|
+
};
|
|
281
|
+
/** Output definitions từ flow config — truyền nguyên (không encrypt) */
|
|
282
|
+
outputDefinitions?: IOutputField[];
|
|
283
|
+
/**
|
|
284
|
+
* Existing output entries từ active output slot.
|
|
285
|
+
* Server gửi nguyên bản — mỗi entry = { profileName, data (cipher/JSON) }.
|
|
286
|
+
* Agent decrypt `data` → parse JSON → build context.output.
|
|
287
|
+
*/
|
|
288
|
+
existingOutputEntries?: _packages_shared.IOutputSlotEntry[];
|
|
70
289
|
}
|
|
71
290
|
type FlowLogLevel = "info" | "warn" | "error" | "debug" | "success";
|
|
72
291
|
interface IFlowLogEntry {
|
|
@@ -85,21 +304,42 @@ interface ILogger {
|
|
|
85
304
|
debug(message: string, context?: LogContext): void;
|
|
86
305
|
success(message: string, context?: LogContext): void;
|
|
87
306
|
logWithProfile(level: string, message: string, profileName: string, context?: LogContext): void;
|
|
307
|
+
postOutput(outputType: "output" | "profileInput", key: string, value: _packages_shared.ProfileOutputValue, profileName: string, opts?: {
|
|
308
|
+
outputIndex?: number;
|
|
309
|
+
outputLabel?: string;
|
|
310
|
+
}): void;
|
|
88
311
|
}
|
|
89
312
|
interface IScriptContext<TConfig extends IFlowConfig = IFlowConfig> {
|
|
90
313
|
browser: Browser;
|
|
91
314
|
page: Page;
|
|
92
|
-
profile:
|
|
315
|
+
profile: IAntidetectProfile;
|
|
93
316
|
index: number;
|
|
94
317
|
globalInput: InferGlobalInput<TConfig>;
|
|
95
318
|
profileInput: InferProfileInput<TConfig>;
|
|
319
|
+
/**
|
|
320
|
+
* Output values cho profile hiện tại.
|
|
321
|
+
* Được pre-populate từ existing output entries (lần chạy trước).
|
|
322
|
+
* Truy cập trực tiếp: output.isLogined, output.titlePage...
|
|
323
|
+
* Giá trị null nếu key chưa được ghi.
|
|
324
|
+
* writeOutput() sẽ cập nhật object này real-time.
|
|
325
|
+
*/
|
|
326
|
+
output: InferOutput<TConfig>;
|
|
96
327
|
logger: ILogger;
|
|
97
328
|
}
|
|
329
|
+
/**
|
|
330
|
+
* Internal context — extends IScriptContext with SDK-internal fields.
|
|
331
|
+
* Flow developers KHÔNG cần biết fields này.
|
|
332
|
+
* Chỉ dùng nội bộ trong BrowserUtils, BaseFlow.
|
|
333
|
+
*/
|
|
334
|
+
interface IScriptContextInternal<TConfig extends IFlowConfig = IFlowConfig> extends IScriptContext<TConfig> {
|
|
335
|
+
/** Output definitions từ flow config — dùng để validate writeOutput key */
|
|
336
|
+
outputDefinitions?: IOutputField[];
|
|
337
|
+
}
|
|
98
338
|
interface IBrowserAdapter {
|
|
99
339
|
open(profileName: string, index: number, windowConfig?: IBrowserWindowConfig): Promise<{
|
|
100
340
|
browser: Browser;
|
|
101
341
|
page: Page;
|
|
102
|
-
profile:
|
|
342
|
+
profile: IAntidetectProfile;
|
|
103
343
|
}>;
|
|
104
344
|
close(profileId: string): Promise<void>;
|
|
105
345
|
}
|
|
@@ -141,6 +381,83 @@ interface IGpmListProfilesParams {
|
|
|
141
381
|
search?: string[];
|
|
142
382
|
}
|
|
143
383
|
|
|
384
|
+
/**
|
|
385
|
+
* Config cho 1 file Excel — dùng cho cả inputFile và outputFile.
|
|
386
|
+
* @template TKeys — union of valid key strings (autocomplete từ flow config)
|
|
387
|
+
*/
|
|
388
|
+
interface IExcelFileConfig<TKeys extends string> {
|
|
389
|
+
/** Đường dẫn tuyệt đối hoặc relative (relative → resolve cùng cấp caller) */
|
|
390
|
+
filePath: string;
|
|
391
|
+
/** Sheet index (0-based), mặc định 0 */
|
|
392
|
+
sheetIndex?: number;
|
|
393
|
+
/** Cột chứa tên profile, mặc định "A" */
|
|
394
|
+
profileNameColumn?: string;
|
|
395
|
+
/** Mapping: column letter → key. VD: { "B": "fa2Code", "C": "email" } */
|
|
396
|
+
columns: Record<string, TKeys>;
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Config tổng cho ExcelStorage.
|
|
400
|
+
* Có thể chỉ có inputFile, chỉ có outputFile, hoặc cả hai.
|
|
401
|
+
* Nếu 2 file trùng filePath → dùng chung 1 file Excel (chỉ khác cột).
|
|
402
|
+
*/
|
|
403
|
+
interface IExcelStorageConfig<TProfileInputKeys extends string = string, TOutputKeys extends string = string> {
|
|
404
|
+
/** File chứa profileInput — đọc bằng parseProfileSettings(), writeProfileInput ghi lại */
|
|
405
|
+
inputFile?: IExcelFileConfig<TProfileInputKeys>;
|
|
406
|
+
/** File chứa output — writeOutput ghi vào đây */
|
|
407
|
+
outputFile?: IExcelFileConfig<TOutputKeys>;
|
|
408
|
+
}
|
|
409
|
+
declare class ExcelStorage<TProfileInputKeys extends string = string, TOutputKeys extends string = string> {
|
|
410
|
+
private readonly config;
|
|
411
|
+
private readonly callerDir;
|
|
412
|
+
constructor(config: IExcelStorageConfig<TProfileInputKeys, TOutputKeys>, callerDir?: string);
|
|
413
|
+
/**
|
|
414
|
+
* Đọc Excel inputFile → trả về IProfileSetting[].
|
|
415
|
+
* Mỗi row = 1 profile, profileName lấy từ cột profileNameColumn,
|
|
416
|
+
* data lấy từ các cột đã mapping.
|
|
417
|
+
*/
|
|
418
|
+
parseProfileSettings(): Promise<IProfileSetting[]>;
|
|
419
|
+
/**
|
|
420
|
+
* Ghi output value vào outputFile.
|
|
421
|
+
* Tìm row theo profileName, ghi value vào cột tương ứng với key.
|
|
422
|
+
*/
|
|
423
|
+
writeOutputRow(profileName: string, key: TOutputKeys, value: ProfileOutputValue): Promise<void>;
|
|
424
|
+
/**
|
|
425
|
+
* Ghi profileInput value vào inputFile.
|
|
426
|
+
* Tìm row theo profileName, ghi value vào cột tương ứng với key.
|
|
427
|
+
*/
|
|
428
|
+
writeProfileInputRow(profileName: string, key: TProfileInputKeys, value: string | number | boolean): Promise<void>;
|
|
429
|
+
/**
|
|
430
|
+
* Đọc tất cả output cho 1 profile → trả về JSON object.
|
|
431
|
+
* Mỗi key trong outputFile.columns → 1 field trong kết quả.
|
|
432
|
+
*/
|
|
433
|
+
readOutputForProfile(profileName: string): Promise<Record<TOutputKeys, ProfileOutputValue | null>>;
|
|
434
|
+
get hasOutputFile(): boolean;
|
|
435
|
+
get hasInputFile(): boolean;
|
|
436
|
+
/**
|
|
437
|
+
* Ghi 1 giá trị vào cell Excel.
|
|
438
|
+
* Tìm row theo profileName, nếu không tìm thấy thì tạo row mới.
|
|
439
|
+
*/
|
|
440
|
+
private writeCell;
|
|
441
|
+
/**
|
|
442
|
+
* Convert column mapping object → array of { colNumber, key } for easier iteration.
|
|
443
|
+
*/
|
|
444
|
+
private buildColumnMap;
|
|
445
|
+
/**
|
|
446
|
+
* Lấy giá trị cell — handle các kiểu ExcelJS cell value.
|
|
447
|
+
*/
|
|
448
|
+
private getCellValue;
|
|
449
|
+
/**
|
|
450
|
+
* Serialize ProfileOutputValue → cell value.
|
|
451
|
+
* Array / Object → JSON string, primitive → giữ nguyên.
|
|
452
|
+
*/
|
|
453
|
+
private serializeValue;
|
|
454
|
+
/**
|
|
455
|
+
* Lazy load exceljs — tránh crash nếu không install.
|
|
456
|
+
* Handle CJS/ESM interop: dynamic import có thể trả { default: ExcelJS } hoặc ExcelJS trực tiếp.
|
|
457
|
+
*/
|
|
458
|
+
private loadExcelJS;
|
|
459
|
+
}
|
|
460
|
+
|
|
144
461
|
declare abstract class BaseFlow<TConfig extends IFlowConfig = IFlowConfig> {
|
|
145
462
|
protected logger: ILogger;
|
|
146
463
|
protected browserAdapter: IBrowserAdapter;
|
|
@@ -152,9 +469,17 @@ declare abstract class BaseFlow<TConfig extends IFlowConfig = IFlowConfig> {
|
|
|
152
469
|
run(params: IFlowRunParams<TConfig>): Promise<void>;
|
|
153
470
|
protected processProfileWithRetry(setting: IProfileSetting<Partial<InferProfileInput<TConfig>>>, index: number, params: IFlowRunParams<TConfig>): Promise<void>;
|
|
154
471
|
private processProfile;
|
|
155
|
-
abstract script(context: IScriptContext<TConfig>): Promise<
|
|
472
|
+
abstract script(context: IScriptContext<TConfig>): Promise<undefined>;
|
|
156
473
|
createProfileSetting(profileName: string, data?: Partial<InferProfileInput<TConfig>>): IProfileSetting<Partial<InferProfileInput<TConfig>>>;
|
|
157
474
|
createRunParams(params: IFlowRunParams<TConfig>): IFlowRunParams<TConfig>;
|
|
475
|
+
/**
|
|
476
|
+
* Tạo ExcelStorage với type-safe column mapping.
|
|
477
|
+
* TS tự gợi ý key values từ config.profileInput và config.output.
|
|
478
|
+
*
|
|
479
|
+
* @param config — inputFile / outputFile config với column mapping
|
|
480
|
+
* @param callerDir — thư mục gốc để resolve relative path (mặc định: cwd)
|
|
481
|
+
*/
|
|
482
|
+
createExcelStorage(config: IExcelStorageConfig<InferProfileInputKeys<TConfig>, InferOutputKeys<TConfig>>, callerDir?: string): ExcelStorage<InferProfileInputKeys<TConfig>, InferOutputKeys<TConfig>>;
|
|
158
483
|
}
|
|
159
484
|
type FlowRunParams<T extends BaseFlow<any>> = T extends BaseFlow<infer TConfig> ? IFlowRunParams<TConfig> : never;
|
|
160
485
|
type FlowProfileSetting<T extends BaseFlow<any>> = T extends BaseFlow<infer TConfig> ? IProfileSetting<Partial<InferProfileInput<TConfig>>> : never;
|
|
@@ -162,7 +487,8 @@ type FlowProfileSetting<T extends BaseFlow<any>> = T extends BaseFlow<infer TCon
|
|
|
162
487
|
declare enum AntidetectProvider {
|
|
163
488
|
GPM = "gpm",
|
|
164
489
|
HIDEMIUM = "hidemium",
|
|
165
|
-
GENLOGIN = "genlogin"
|
|
490
|
+
GENLOGIN = "genlogin",
|
|
491
|
+
ADSPOWER = "adspower"
|
|
166
492
|
}
|
|
167
493
|
declare abstract class AntidetectBaseFlow<TConfig extends IFlowConfig = IFlowConfig> extends BaseFlow<TConfig> {
|
|
168
494
|
protected provider: AntidetectProvider;
|
|
@@ -197,16 +523,85 @@ declare class GpmStandaloneAdapter implements IBrowserAdapter {
|
|
|
197
523
|
open(profileName: string, index: number, windowConfig: IBrowserWindowConfig): Promise<{
|
|
198
524
|
browser: puppeteer.Browser;
|
|
199
525
|
page: puppeteer.Page;
|
|
200
|
-
profile:
|
|
526
|
+
profile: IAntidetectProfile;
|
|
201
527
|
}>;
|
|
202
528
|
close(profileId: string): Promise<void>;
|
|
203
529
|
closeAll(delayBetweenMs?: number): Promise<void>;
|
|
204
530
|
}
|
|
205
531
|
|
|
206
|
-
|
|
532
|
+
interface IHidemiumProfile {
|
|
533
|
+
uuid: string;
|
|
534
|
+
name: string;
|
|
535
|
+
os: string;
|
|
536
|
+
browser: string;
|
|
537
|
+
version: string;
|
|
538
|
+
proxy: string;
|
|
539
|
+
resolution: string;
|
|
540
|
+
note: string;
|
|
541
|
+
created_at: string;
|
|
542
|
+
}
|
|
543
|
+
interface IHidemiumStartResult {
|
|
544
|
+
remote_port: number;
|
|
545
|
+
web_socket: string;
|
|
546
|
+
profile_path: string;
|
|
547
|
+
uuid: string;
|
|
548
|
+
}
|
|
549
|
+
interface IHidemiumListParams {
|
|
550
|
+
page?: number;
|
|
551
|
+
limit?: number;
|
|
552
|
+
search?: string;
|
|
553
|
+
orderName?: number;
|
|
554
|
+
}
|
|
555
|
+
interface IHidemiumCreateProfileParams {
|
|
556
|
+
name: string;
|
|
557
|
+
os?: "win" | "mac" | "lin" | "android";
|
|
558
|
+
browser?: "chrome" | "brave" | "edge" | "opera";
|
|
559
|
+
version?: string;
|
|
560
|
+
resolution?: string;
|
|
561
|
+
userAgent?: string;
|
|
562
|
+
language?: string;
|
|
563
|
+
}
|
|
564
|
+
declare class HidemiumService {
|
|
565
|
+
private api;
|
|
566
|
+
private apiUrl;
|
|
567
|
+
constructor(apiUrl?: string);
|
|
568
|
+
startProfile(uuid: string, command?: string, proxy?: string, maxRetries?: number, delayMs?: number): Promise<IHidemiumStartResult | null>;
|
|
569
|
+
stopProfile(uuid: string, maxRetries?: number, delayMs?: number): Promise<boolean>;
|
|
570
|
+
getProfiles(params?: IHidemiumListParams, isLocal?: boolean): Promise<IHidemiumProfile[]>;
|
|
571
|
+
createProfile(config: IHidemiumCreateProfileParams, isLocal?: boolean): Promise<any>;
|
|
572
|
+
deleteProfiles(uuids: string[]): Promise<boolean>;
|
|
573
|
+
updateProxy(uuid: string, proxy: string): Promise<boolean>;
|
|
574
|
+
checkHealth(): Promise<boolean>;
|
|
575
|
+
connectToBrowser(wsUrl: string, maxRetries?: number, delayMs?: number): Promise<Browser>;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
declare class HidemiumStandaloneAdapter implements IBrowserAdapter {
|
|
579
|
+
private apiUrl;
|
|
580
|
+
private screenResolution;
|
|
581
|
+
readonly service: HidemiumService;
|
|
582
|
+
private readonly openedProfiles;
|
|
583
|
+
private readonly pendingProfiles;
|
|
584
|
+
private readonly logger;
|
|
585
|
+
private readonly boundLoggers;
|
|
586
|
+
constructor(logger: ILogger);
|
|
587
|
+
private getBoundLogger;
|
|
588
|
+
open(profileName: string, index: number, windowConfig: IBrowserWindowConfig): Promise<{
|
|
589
|
+
browser: puppeteer.Browser;
|
|
590
|
+
page: puppeteer.Page;
|
|
591
|
+
profile: IAntidetectProfile;
|
|
592
|
+
}>;
|
|
593
|
+
close(profileId: string): Promise<void>;
|
|
594
|
+
closeAll(delayBetweenMs?: number): Promise<void>;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
declare class BrowserUtils<TConfig extends IFlowConfig = IFlowConfig> {
|
|
207
598
|
private ctx;
|
|
208
599
|
private logger;
|
|
209
|
-
|
|
600
|
+
/** Output definitions từ flow config — dùng để validate writeOutput key */
|
|
601
|
+
private readonly outputDefs;
|
|
602
|
+
/** Set chứa các key hợp lệ — build 1 lần từ outputDefs */
|
|
603
|
+
private readonly validOutputKeys;
|
|
604
|
+
constructor(context: IScriptContext<TConfig>);
|
|
210
605
|
private checkAbort;
|
|
211
606
|
sleep(ms: number): Promise<void>;
|
|
212
607
|
waitForElement(selector: string, timeout?: number, scope?: Frame): Promise<ElementHandle | null>;
|
|
@@ -233,9 +628,45 @@ declare class BrowserUtils {
|
|
|
233
628
|
switchToTabIndex(index: number): Promise<puppeteer.Page | null>;
|
|
234
629
|
closeCurrentTab(): Promise<void>;
|
|
235
630
|
closeOtherTabs(): Promise<void>;
|
|
631
|
+
/**
|
|
632
|
+
* Close ALL tabs (including the current one).
|
|
633
|
+
* Useful for full cleanup before flow ends.
|
|
634
|
+
*/
|
|
635
|
+
closeAllTabs(): Promise<void>;
|
|
636
|
+
/**
|
|
637
|
+
* Switch back to the default (initial) page — the page stored in context.
|
|
638
|
+
* Typically used after switchToPopup() to return to the main tab.
|
|
639
|
+
*/
|
|
640
|
+
switchToDefault(): Promise<puppeteer.Page>;
|
|
236
641
|
logConfig(config: Record<string, unknown>, label?: string): Promise<void>;
|
|
237
642
|
logProfileInput(): Promise<void>;
|
|
643
|
+
/**
|
|
644
|
+
* Log toàn bộ output hiện tại (bao gồm cả giá trị từ lần chạy trước và giá trị mới ghi).
|
|
645
|
+
* Dùng để debug — xem giá trị output hiện tại.
|
|
646
|
+
*/
|
|
647
|
+
logProfileOutput(): Promise<void>;
|
|
238
648
|
logGlobalInput(): Promise<void>;
|
|
649
|
+
/**
|
|
650
|
+
* Ghi kết quả tự do cho profile đang chạy.
|
|
651
|
+
* Gửi qua kênh riêng (type: "profile_output") — không lẫn log.
|
|
652
|
+
* Đồng thời log ra console/UI để flow dev dễ debug.
|
|
653
|
+
*
|
|
654
|
+
* ⚠️ Key phải được định nghĩa trong config.output[] — nếu không sẽ throw Error.
|
|
655
|
+
*
|
|
656
|
+
* value hợp lệ:
|
|
657
|
+
* - string | number | boolean
|
|
658
|
+
* - array tối đa 20 phần tử (primitive)
|
|
659
|
+
* - object 1 cấp tối đa 10 entry (value phải là primitive)
|
|
660
|
+
*/
|
|
661
|
+
writeOutput(key: InferOutputKeys<TConfig>, value: ProfileOutputValue): Promise<void>;
|
|
662
|
+
/**
|
|
663
|
+
* Cập nhật lại một field trong profileInput của profile đang chạy.
|
|
664
|
+
* key phải là field đã được định nghĩa trong profileInput schema.
|
|
665
|
+
* Kết quả được gửi về server để update AgentFlowConfig sau khi execution xong.
|
|
666
|
+
*/
|
|
667
|
+
writeProfileInput(key: InferProfileInputKeys<TConfig>, value: string | number | boolean): Promise<void>;
|
|
668
|
+
private sanitizeOutputValue;
|
|
669
|
+
private dispatchOutput;
|
|
239
670
|
private shortSelector;
|
|
240
671
|
private log;
|
|
241
672
|
private actionDelay;
|
|
@@ -246,6 +677,7 @@ declare class FlowLogger extends EventEmitter implements ILogger {
|
|
|
246
677
|
private _context?;
|
|
247
678
|
private parentPort;
|
|
248
679
|
private readonly isWorker;
|
|
680
|
+
private excelStorage;
|
|
249
681
|
constructor(_context?: string | undefined);
|
|
250
682
|
private serialize;
|
|
251
683
|
private dispatch;
|
|
@@ -259,8 +691,19 @@ declare class FlowLogger extends EventEmitter implements ILogger {
|
|
|
259
691
|
debug(message: string, context?: LogContext): void;
|
|
260
692
|
custom(label: string, message: string, color?: string): void;
|
|
261
693
|
logWithProfile(level: IWorkerLogMessage["level"], message: string, profileName: string, context?: LogContext): void;
|
|
262
|
-
createBoundLogger(profileName: string): ILogger
|
|
694
|
+
createBoundLogger(profileName: string): ILogger & {
|
|
695
|
+
muted: boolean;
|
|
696
|
+
};
|
|
263
697
|
profileEvent(profileName: string, message: string, status: ProfileStatus, context?: LogContext): void;
|
|
698
|
+
private buildOutputMsg;
|
|
699
|
+
postOutput(outputType: "output" | "profileInput", key: string, value: IWorkerOutputMessage["value"], profileName: string, opts?: {
|
|
700
|
+
outputIndex?: number;
|
|
701
|
+
outputLabel?: string;
|
|
702
|
+
}): void;
|
|
703
|
+
/**
|
|
704
|
+
* Attach ExcelStorage — FlowLogger sẽ tự ghi Excel khi postOutput (dev mode).
|
|
705
|
+
*/
|
|
706
|
+
setExcelStorage(storage: ExcelStorage<any, any>): void;
|
|
264
707
|
}
|
|
265
708
|
|
|
266
|
-
export { AntidetectBaseFlow, AntidetectProvider, BaseFlow, BrowserUtils, type FlowLogLevel, FlowLogger, type FlowProfileSetting, type FlowRunParams, GpmStandaloneAdapter, type IAntidetectConfig, type IBrowserAdapter, type IBrowserWindowConfig, type IExecutionConfig, type IFlowConfig, type IFlowLogEntry, type IFlowRunParams, type IGpmListProfilesParams, type IGpmProfile, type IGpmRes, type IGpmResListProfile, type IGpmStartProfileParams, type IInputField, type ILogger, type IProfileSetting, type IResGpmStartProfileData, type IScriptContext, type InferGlobalInput, type InferProfileInput, type LogContext };
|
|
709
|
+
export { AntidetectBaseFlow, AntidetectProvider, BaseFlow, BrowserUtils, ExcelStorage, type FlowLogLevel, FlowLogger, type FlowProfileSetting, type FlowRunParams, GpmStandaloneAdapter, HidemiumService, HidemiumStandaloneAdapter, type IAntidetectConfig, type IAntidetectProfile, type IBrowserAdapter, type IBrowserWindowConfig, type IEncryptedAntidetectConfig, type IEncryptedFlowRunParams, type IEncryptedProfileSetting, type IExcelFileConfig, type IExcelStorageConfig, type IExecutionConfig, type IFlowConfig, type IFlowLogEntry, type IFlowRunParams, type IGpmListProfilesParams, type IGpmProfile, type IGpmRes, type IGpmResListProfile, type IGpmStartProfileParams, type IHidemiumCreateProfileParams, type IHidemiumListParams, type IHidemiumProfile, type IHidemiumStartResult, type IInputField, type ILogger, type IOutputField, type IProfileSetting, type IResGpmStartProfileData, type IScriptContext, type IScriptContextInternal, type InferGlobalInput, type InferOutput, type InferOutputKeys, type InferProfileInput, type InferProfileInputKeys, type LogContext, type StrictFlowConfig, defineFlowConfig };
|