@@ -8,12 +8,15 @@ import { LogClient } from './log';
88import { RequestQueueClient } from './request_queue' ;
99import { ApiClientOptionsWithOptionalResourcePath } from '../base/api_client' ;
1010import { ResourceClient } from '../base/resource_client' ;
11+ import type { ApifyResponse } from '../http_client' ;
1112import {
1213 pluckData ,
1314 parseDateFields ,
1415 cast ,
1516} from '../utils' ;
1617
18+ const RUN_CHARGE_IDEMPOTENCY_HEADER = 'idempotency-key' ;
19+
1720export class RunClient extends ResourceClient {
1821 /**
1922 * @hidden
@@ -113,7 +116,7 @@ export class RunClient extends ResourceClient {
113116 return cast ( parseDateFields ( pluckData ( response . data ) ) ) ;
114117 }
115118
116- async update ( newFields : RunUpdateOptions ) : Promise < ActorRun > {
119+ async update ( newFields : RunUpdateOptions ) : Promise < ActorRun > {
117120 ow ( newFields , ow . object ) ;
118121
119122 return this . _update ( newFields ) ;
@@ -138,6 +141,36 @@ export class RunClient extends ResourceClient {
138141 return cast ( parseDateFields ( pluckData ( response . data ) ) ) ;
139142 }
140143
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+
141174 /**
142175 * Returns a promise that resolves with the finished Run object when the provided actor run finishes
143176 * or with the unfinished Run object when the `waitSecs` timeout lapses. The promise is NOT rejected
@@ -221,7 +254,7 @@ export interface RunMetamorphOptions {
221254}
222255export interface RunUpdateOptions {
223256 statusMessage ?: string ;
224- isStatusMessageTerminal ? : boolean ;
257+ isStatusMessageTerminal ?: boolean ;
225258}
226259
227260export interface RunResurrectOptions {
@@ -230,6 +263,15 @@ export interface RunResurrectOptions {
230263 timeout ?: number ;
231264}
232265
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+
233275export interface RunWaitForFinishOptions {
234276 /**
235277 * Maximum time to wait for the run to finish, in seconds.
0 commit comments