@@ -8,12 +8,15 @@ import { LogClient } from './log';
8
8
import { RequestQueueClient } from './request_queue' ;
9
9
import { ApiClientOptionsWithOptionalResourcePath } from '../base/api_client' ;
10
10
import { ResourceClient } from '../base/resource_client' ;
11
+ import type { ApifyResponse } from '../http_client' ;
11
12
import {
12
13
pluckData ,
13
14
parseDateFields ,
14
15
cast ,
15
16
} from '../utils' ;
16
17
18
+ const RUN_CHARGE_IDEMPOTENCY_HEADER = 'idempotency-key' ;
19
+
17
20
export class RunClient extends ResourceClient {
18
21
/**
19
22
* @hidden
@@ -113,7 +116,7 @@ export class RunClient extends ResourceClient {
113
116
return cast ( parseDateFields ( pluckData ( response . data ) ) ) ;
114
117
}
115
118
116
- async update ( newFields : RunUpdateOptions ) : Promise < ActorRun > {
119
+ async update ( newFields : RunUpdateOptions ) : Promise < ActorRun > {
117
120
ow ( newFields , ow . object ) ;
118
121
119
122
return this . _update ( newFields ) ;
@@ -138,6 +141,36 @@ export class RunClient extends ResourceClient {
138
141
return cast ( parseDateFields ( pluckData ( response . data ) ) ) ;
139
142
}
140
143
144
+ /**
145
+ * https://docs.apify.com/api/v2#/reference/actor-runs/charge-run/charge-run
146
+ */
147
+ async charge ( options : RunChargeOptions ) : Promise < ApifyResponse < Record < string , never > > > {
148
+ ow ( options , ow . object . exactShape ( {
149
+ eventName : ow . string ,
150
+ count : ow . optional . number ,
151
+ idempotencyKey : ow . optional . string ,
152
+ } ) ) ;
153
+
154
+ const count = options . count ?? 1 ;
155
+ /** To avoid duplicates during the same milisecond, doesn't need to by crypto-secure. */
156
+ const randomSuffix = ( Math . random ( ) + 1 ) . toString ( 36 ) . slice ( 3 , 8 ) ;
157
+ const idempotencyKey = options . idempotencyKey ?? `${ this . id } -${ options . eventName } -${ Date . now ( ) } -${ randomSuffix } ` ;
158
+
159
+ const request : AxiosRequestConfig = {
160
+ url : this . _url ( 'charge' ) ,
161
+ method : 'POST' ,
162
+ data : {
163
+ eventName : options . eventName ,
164
+ count,
165
+ } ,
166
+ headers : {
167
+ [ RUN_CHARGE_IDEMPOTENCY_HEADER ] : idempotencyKey ,
168
+ } ,
169
+ } ;
170
+ const response = await this . httpClient . call ( request ) ;
171
+ return response ;
172
+ }
173
+
141
174
/**
142
175
* Returns a promise that resolves with the finished Run object when the provided actor run finishes
143
176
* or with the unfinished Run object when the `waitSecs` timeout lapses. The promise is NOT rejected
@@ -221,7 +254,7 @@ export interface RunMetamorphOptions {
221
254
}
222
255
export interface RunUpdateOptions {
223
256
statusMessage ?: string ;
224
- isStatusMessageTerminal ? : boolean ;
257
+ isStatusMessageTerminal ?: boolean ;
225
258
}
226
259
227
260
export interface RunResurrectOptions {
@@ -230,6 +263,15 @@ export interface RunResurrectOptions {
230
263
timeout ?: number ;
231
264
}
232
265
266
+ export type RunChargeOptions = {
267
+ /** Name of the event to charge. Must be defined in the Actor's pricing info else the API will throw. */
268
+ eventName : string ;
269
+ /** Defaults to 1 */
270
+ count ?: number ;
271
+ /** Defaults to runId-eventName-timestamp */
272
+ idempotencyKey ?: string ;
273
+ } ;
274
+
233
275
export interface RunWaitForFinishOptions {
234
276
/**
235
277
* Maximum time to wait for the run to finish, in seconds.
0 commit comments