Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/actor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1497,7 +1497,12 @@ export class Actor<Data extends Dictionary = Dictionary> {
...storageClientOptions,
...options, // allow overriding the instance configuration
},
this,
{
config: this.config,
// Hand over the raw manager rather than the public getChargingManager(), which
// warns about a missing init() — a standalone client is a supported use case.
getChargingManager: () => this.chargingManager,
},
);
}

Expand Down
8 changes: 8 additions & 0 deletions src/charging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,14 @@ export class ChargingManager {
return dataset.id;
}

/**
* Whether {@link ChargingManager.init} has run. All charging operations (including
* {@link ChargingManager.getPricingInfo}) require an initialized manager.
*/
get isInitialized(): boolean {
return this.chargingState !== undefined;
}

/**
* Get information about the pricing for this Actor.
*/
Expand Down
7 changes: 6 additions & 1 deletion src/patched_apify_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,13 @@ export function createPatchedApifyClient(
httpClient: this.httpClient,
};

// Charging is only configured for an initialized Actor (a platform run). A
// standalone client from `Actor.newClient()` without `Actor.init()` has no
// charging state, so skip interception rather than letting getPricingInfo() throw.
const chargingManager = actor.getChargingManager();
const hasDefaultDatasetItemEvent =
DEFAULT_DATASET_ITEM_EVENT in actor.getChargingManager().getPricingInfo().perEventPrices;
chargingManager.isInitialized &&
DEFAULT_DATASET_ITEM_EVENT in chargingManager.getPricingInfo().perEventPrices;

if (!isDefaultDataset || !hasDefaultDatasetItemEvent) {
return new DatasetClient(datasetOptions);
Expand Down
21 changes: 21 additions & 0 deletions test/apify/charging.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -788,3 +788,24 @@ describe('ChargingManager', () => {
});
});
});

describe('Actor.newClient()', () => {
afterEach(() => {
// @ts-expect-error reset the singleton between tests
Actor._instance = undefined; // eslint-disable-line no-underscore-dangle
});

test('dataset() works without calling Actor.init()', () => {
// `Actor.newClient()` is documented as usable standalone (init() is only required on
// the platform). The charging-aware dataset() getter must not require an initialized
// ChargingManager, otherwise it throws "ChargingManager is not initialized".
const warningSpy = vitest.spyOn(log, 'warning');
const client = Actor.newClient({ token: 'test-token' });

expect(() => client.dataset('some-dataset-id')).not.toThrow();
// ...and it must not nag about a missing init() on this supported path.
expect(warningSpy).not.toHaveBeenCalledWith(expect.stringContaining('Actor.init()'));

warningSpy.mockRestore();
});
});
Loading