@datalayer/core
Version:
[](https://datalayer.io)
136 lines (135 loc) • 3.86 kB
JavaScript
/*
* Copyright (c) 2023-2025 Datalayer, Inc.
* Distributed under the terms of the Modified BSD License.
*/
/**
* Credits model for the Datalayer SDK.
*
* @module models/CreditsDTO
*/
import { validateJSON } from '../api/utils/validation';
/**
* Credits model representing user's available credits and usage.
*
* @example
* ```typescript
* const credits = await sdk.getCredits();
* console.log(`Available: ${credits.available}`);
* console.log(`Quota: ${credits.quota || 'unlimited'}`);
*
* // Calculate maximum runtime for an environment
* const maxMinutes = credits.calculateMaxRuntimeMinutes(environment.burningRate);
* ```
*/
export class CreditsDTO {
/** @internal */
_data;
_reservations;
constructor(data, reservations = []) {
this._data = data;
this._reservations = reservations;
}
/**
* Available credits for the user.
*/
get available() {
return this._data.credits;
}
/**
* Credit quota for the user.
* Returns null if unlimited.
*/
get quota() {
return this._data.quota;
}
/**
* Last update timestamp.
*/
get lastUpdate() {
return this._data.last_update;
}
/**
* Active credit reservations.
*/
get reservations() {
return [...this._reservations];
}
/**
* Total reserved credits across all reservations.
*/
get totalReserved() {
return this._reservations.reduce((sum, r) => sum + r.credits, 0);
}
/**
* Net available credits (available minus reserved).
*/
get netAvailable() {
return Math.max(0, this.available - this.totalReserved);
}
/**
* Get runtime reservations (reservations that start with 'runtime-').
*/
get runtimeReservations() {
return this._reservations.filter(r => r.id.startsWith('runtime-'));
}
/**
* Check if there are any active runtime reservations.
*/
get hasActiveRuntimes() {
return this.runtimeReservations.length > 0;
}
/**
* Calculate maximum runtime in minutes based on environment burning rate.
*
* @param burningRate - Credits consumed per hour
* @returns Maximum runtime in minutes
*/
calculateMaxRuntimeMinutes(burningRate) {
if (burningRate <= 0)
return 0;
const burningRatePerMinute = burningRate * 60;
return Math.floor(this.netAvailable / burningRatePerMinute);
}
/**
* Calculate credits needed for runtime duration.
*
* @param minutes - Runtime duration in minutes
* @param burningRate - Credits consumed per hour
* @returns Credits needed
*/
calculateCreditsFromMinutes(minutes, burningRate) {
const burningRatePerMinute = burningRate * 60;
return minutes * burningRatePerMinute;
}
/**
* Check if user has enough credits for runtime.
*
* @param minutes - Runtime duration in minutes
* @param burningRate - Credits consumed per hour
* @returns True if user has enough credits
*/
hasEnoughCreditsForRuntime(minutes, burningRate) {
const creditsNeeded = this.calculateCreditsFromMinutes(minutes, burningRate);
return this.netAvailable >= creditsNeeded;
}
/**
* Convert to JSON representation.
*/
toJSON() {
// FIXME
const obj = {
...this._data,
reservations: this._reservations,
};
validateJSON(obj, 'Credits');
return obj;
}
/**
* String representation of credits.
*/
toString() {
const quotaStr = this.quota !== null ? ` of ${this.quota}` : '';
const reservedStr = this.totalReserved > 0 ? ` (${this.totalReserved} reserved)` : '';
return `Credits: ${this.available}${quotaStr}${reservedStr}`;
}
}