@flashbacktech/flashbackclient 0.0.96 → 0.0.98

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 CHANGED
@@ -12,6 +12,10 @@ TypeScript/JavaScript client for:
12
12
  npm install @flashbacktech/flashbackclient
13
13
  ```
14
14
 
15
+ ## Documentation
16
+
17
+ For comprehensive API documentation, examples, and usage instructions, see the [Documentation](./docs/index.md).
18
+
15
19
  ## Usage
16
20
 
17
21
  ### Client Library
@@ -1,7 +1,7 @@
1
1
  import { CreateUnitRequest, CreateUnitResponse, CreateRepoRequest, CreateRepoResponse, StorageUnit, CreateRepoKeyRequest, CreateRepoKeyResponse, GetUnitsResponse, GetReposResponse, GetRepoKeysResponse, UpdateUnitRequest, UpdateUnitResponse, ActionResponse, UpdateRepoRequest, UpdateRepoResponse, UpdateRepoKeyRequest, UpdateRepoKeyResponse, ValidateUnitRequest, ValidateUnitResponse, ValidateRepoUnitsRequest, ValidateRepoUnitsResponse, StorageUnitStatusResponse, GetUnitNodeStatsResponse, GetUnitNodeStatsRequest } from './types/storage';
2
2
  import { IApiClient, ProviderType } from './interfaces';
3
3
  import { ActivateResponse, DeactivateResponse, LoginBody, LoginResponse, LogoutResponse, OAuth2ResponseDTO, RefreshTokenErrorResponse, RefreshTokenResponse, RegisterBody, RegisterResponse } from './types/auth';
4
- import { StatsQueryParams, StatsResponse } from './types/stats';
4
+ import { StatsQueryParams, StatsResponse, NodeStatsMinuteResponse, NodeStatsDailyResponse, NodeStatsQueryParams, UnitStatsResponse, RepoStatsResponse } from './types/stats';
5
5
  interface ErrorResponse {
6
6
  message?: string;
7
7
  [key: string]: any;
@@ -63,5 +63,13 @@ export declare class ApiClient implements IApiClient {
63
63
  private validateDateRange;
64
64
  getDailyStats: (params: StatsQueryParams) => Promise<StatsResponse>;
65
65
  getMinuteStats: (params: StatsQueryParams) => Promise<StatsResponse>;
66
+ getNodeStatsMinute: (params?: NodeStatsQueryParams) => Promise<NodeStatsMinuteResponse>;
67
+ getNodeStatsDaily: (params?: NodeStatsQueryParams) => Promise<NodeStatsDailyResponse>;
68
+ getRepoStats: (params?: {
69
+ repoId?: string[];
70
+ }) => Promise<RepoStatsResponse>;
71
+ getUnitStats: (params?: {
72
+ unitId?: string[];
73
+ }) => Promise<UnitStatsResponse>;
66
74
  }
67
75
  export {};
@@ -137,7 +137,9 @@ class ApiClient {
137
137
  return this.makeRequest('auth/github', 'POST', { code });
138
138
  };
139
139
  this.refreshGoogleToken = async (refreshToken) => {
140
- return this.makeRequest('auth/google/refresh', 'POST', { refresh_token: refreshToken });
140
+ return this.makeRequest('auth/google/refresh', 'POST', {
141
+ refresh_token: refreshToken,
142
+ });
141
143
  };
142
144
  this.exchangeGoogleCode = async (code) => {
143
145
  return this.makeRequest('auth/google/exchange', 'POST', { code });
@@ -248,6 +250,43 @@ class ApiClient {
248
250
  queryParams.append('unitId', params.unitId.join(','));
249
251
  return this.makeRequest(`stats/minute?${queryParams.toString()}`, 'GET', null);
250
252
  };
253
+ this.getNodeStatsMinute = async (params) => {
254
+ const queryParams = new URLSearchParams();
255
+ if (params && params.unitId && params.unitId.length > 0) {
256
+ queryParams.append('unitId', params.unitId.join(','));
257
+ }
258
+ const response = await this.makeRequest(`stats/nodes/minute?${queryParams.toString() ? `?${queryParams.toString()}` : ''}`, 'GET', null);
259
+ // Process the response to convert lastUpdated strings to Date objects
260
+ const processedData = response.data.map((item) => ({
261
+ ...item,
262
+ lastUpdated: new Date(item.lastUpdated),
263
+ }));
264
+ return {
265
+ ...response,
266
+ data: processedData,
267
+ };
268
+ };
269
+ this.getNodeStatsDaily = async (params) => {
270
+ const queryParams = new URLSearchParams();
271
+ if (params && params.unitId && params.unitId.length > 0) {
272
+ queryParams.append('unitId', params.unitId.join(','));
273
+ }
274
+ return this.makeRequest(`stats/nodes/daily${queryParams.toString() ? `?${queryParams.toString()}` : ''}`, 'GET', null);
275
+ };
276
+ this.getRepoStats = async (params) => {
277
+ const queryParams = new URLSearchParams();
278
+ if (params && params.repoId && params.repoId.length > 0) {
279
+ queryParams.append('repoId', params.repoId.join(','));
280
+ }
281
+ return this.makeRequest(`repo/stats${queryParams.toString() ? `?${queryParams.toString()}` : ''}`, 'GET', null);
282
+ };
283
+ this.getUnitStats = async (params) => {
284
+ const queryParams = new URLSearchParams();
285
+ if (params && params.unitId && params.unitId.length > 0) {
286
+ queryParams.append('unitId', params.unitId.join(','));
287
+ }
288
+ return this.makeRequest(`unit/stats${queryParams.toString() ? `?${queryParams.toString()}` : ''}`, 'GET', null);
289
+ };
251
290
  this.baseURL = baseURL;
252
291
  this.headers = {};
253
292
  this.debug = false;
@@ -1,6 +1,7 @@
1
1
  import { ApiClient, HttpError } from './client';
2
2
  import * as ApiTypes from './types/storage';
3
3
  import * as AuthTypes from './types/auth';
4
+ import * as StatsTypes from './types/stats';
4
5
  import * as ApiInterfaces from './interfaces';
5
6
  import * as BridgeTypes from './types/bridge';
6
- export { ApiClient, ApiTypes, AuthTypes, ApiInterfaces, HttpError, BridgeTypes };
7
+ export { ApiClient, ApiTypes, AuthTypes, StatsTypes, ApiInterfaces, HttpError, BridgeTypes };
package/dist/api/index.js CHANGED
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.BridgeTypes = exports.HttpError = exports.ApiInterfaces = exports.AuthTypes = exports.ApiTypes = exports.ApiClient = void 0;
36
+ exports.BridgeTypes = exports.HttpError = exports.ApiInterfaces = exports.StatsTypes = exports.AuthTypes = exports.ApiTypes = exports.ApiClient = void 0;
37
37
  const client_1 = require("./client");
38
38
  Object.defineProperty(exports, "ApiClient", { enumerable: true, get: function () { return client_1.ApiClient; } });
39
39
  Object.defineProperty(exports, "HttpError", { enumerable: true, get: function () { return client_1.HttpError; } });
@@ -41,6 +41,8 @@ const ApiTypes = __importStar(require("./types/storage"));
41
41
  exports.ApiTypes = ApiTypes;
42
42
  const AuthTypes = __importStar(require("./types/auth"));
43
43
  exports.AuthTypes = AuthTypes;
44
+ const StatsTypes = __importStar(require("./types/stats"));
45
+ exports.StatsTypes = StatsTypes;
44
46
  const ApiInterfaces = __importStar(require("./interfaces"));
45
47
  exports.ApiInterfaces = ApiInterfaces;
46
48
  const BridgeTypes = __importStar(require("./types/bridge"));
@@ -1,6 +1,6 @@
1
- import { StorageUnit, CreateUnitRequest, CreateUnitResponse, CreateRepoRequest, CreateRepoResponse, CreateRepoKeyRequest, CreateRepoKeyResponse, GetUnitsResponse, GetReposResponse, GetRepoKeysResponse, UpdateUnitRequest, UpdateUnitResponse, ActionResponse, UpdateRepoResponse, UpdateRepoRequest, UpdateRepoKeyRequest, UpdateRepoKeyResponse, ValidateUnitRequest, ValidateUnitResponse, ValidateRepoUnitsRequest, ValidateRepoUnitsResponse, GetUnitNodeStatsRequest, GetUnitNodeStatsResponse } from "./types/storage";
2
- import { RegisterBody, LoginBody, RegisterResponse, LoginResponse, LogoutResponse, ActivateResponse, DeactivateResponse, RefreshTokenResponse, RefreshTokenErrorResponse } from "./types/auth";
3
- import { StatsQueryParams, StatsResponse } from "./types/stats";
1
+ import { StorageUnit, CreateUnitRequest, CreateUnitResponse, CreateRepoRequest, CreateRepoResponse, CreateRepoKeyRequest, CreateRepoKeyResponse, GetUnitsResponse, GetReposResponse, GetRepoKeysResponse, UpdateUnitRequest, UpdateUnitResponse, ActionResponse, UpdateRepoResponse, UpdateRepoRequest, UpdateRepoKeyRequest, UpdateRepoKeyResponse, ValidateUnitRequest, ValidateUnitResponse, ValidateRepoUnitsRequest, ValidateRepoUnitsResponse, GetUnitNodeStatsRequest, GetUnitNodeStatsResponse } from './types/storage';
2
+ import { RegisterBody, LoginBody, RegisterResponse, LoginResponse, LogoutResponse, ActivateResponse, DeactivateResponse, RefreshTokenResponse, RefreshTokenErrorResponse } from './types/auth';
3
+ import { StatsQueryParams, StatsResponse, NodeStatsMinuteResponse, NodeStatsDailyResponse, NodeStatsQueryParams } from './types/stats';
4
4
  export declare enum ProviderType {
5
5
  GOOGLE = "GOOGLE",
6
6
  GITHUB = "GITHUB",
@@ -34,4 +34,6 @@ export interface IApiClient {
34
34
  userDeactivate(): Promise<DeactivateResponse>;
35
35
  getDailyStats(params: StatsQueryParams): Promise<StatsResponse>;
36
36
  getMinuteStats(params: StatsQueryParams): Promise<StatsResponse>;
37
+ getNodeStatsMinute(params?: NodeStatsQueryParams): Promise<NodeStatsMinuteResponse>;
38
+ getNodeStatsDaily(params?: NodeStatsQueryParams): Promise<NodeStatsDailyResponse>;
37
39
  }
@@ -1,4 +1,4 @@
1
- import { ProviderType } from "../interfaces";
1
+ import { ProviderType } from '../interfaces';
2
2
  export interface AuthState {
3
3
  user: {
4
4
  email: string;
@@ -18,3 +18,55 @@ export interface StatsData {
18
18
  size_change: bigint;
19
19
  latency_ms: number;
20
20
  }
21
+ export interface NodeStatsMinuteResponse {
22
+ success: boolean;
23
+ data: NodeStatsMinuteData[];
24
+ message?: string;
25
+ }
26
+ export interface NodeStatsMinuteData {
27
+ nodeId: string;
28
+ unitId: string;
29
+ nodeStatus: string;
30
+ lastUpdated: Date;
31
+ latency_ms: number;
32
+ }
33
+ export interface NodeStatsDailyResponse {
34
+ success: boolean;
35
+ data: NodeStatsDailyData[];
36
+ message?: string;
37
+ }
38
+ export interface NodeStatsDailyData {
39
+ nodeId: string;
40
+ unitId: string;
41
+ day: number;
42
+ online: number;
43
+ latency_ms: number;
44
+ endpoint: string;
45
+ region: string;
46
+ storageType: string;
47
+ provider: string;
48
+ status: string;
49
+ version: string;
50
+ }
51
+ export interface NodeStatsQueryParams {
52
+ unitId?: string[];
53
+ }
54
+ export interface RepoStatsResponse {
55
+ success: boolean;
56
+ stats: {
57
+ repoId: string;
58
+ totalUploadBytes: string;
59
+ totalDownloadBytes: string;
60
+ totalSizeChange: string;
61
+ }[];
62
+ }
63
+ export interface UnitStatsResponse {
64
+ success: boolean;
65
+ stats: {
66
+ unitId: string;
67
+ totalCount: string;
68
+ totalUploadBytes: string;
69
+ totalDownloadBytes: string;
70
+ totalSizeChange: string;
71
+ }[];
72
+ }
@@ -1,4 +1,4 @@
1
- import { NodeStatusInfo, NodeStatusType } from "./bridge";
1
+ import { NodeStatusInfo, NodeStatusType } from './bridge';
2
2
  export declare enum StorageType {
3
3
  S3 = "S3",
4
4
  GCS = "GCS",
@@ -1,3 +1,3 @@
1
- import { FlashbackAuthClient } from "./oauth2";
2
- import { FlashbackGCSStorage, FlashbackStorageOptions } from "./storage";
1
+ import { FlashbackAuthClient } from './oauth2';
2
+ import { FlashbackGCSStorage, FlashbackStorageOptions } from './storage';
3
3
  export { FlashbackAuthClient, FlashbackGCSStorage, FlashbackStorageOptions };
@@ -33,7 +33,7 @@ class FlashbackAuthClient extends google_auth_library_1.OAuth2Client {
33
33
  await this.ensureValidToken();
34
34
  return {
35
35
  token: this._credentials?.access_token || null,
36
- res: null
36
+ res: null,
37
37
  };
38
38
  }
39
39
  async getRequestHeaders() {
@@ -44,7 +44,9 @@ class FlashbackAuthClient extends google_auth_library_1.OAuth2Client {
44
44
  }
45
45
  async ensureValidToken() {
46
46
  const now = Date.now();
47
- if (!this._credentials?.access_token || !this._credentials?.expiry_date || now >= this._credentials.expiry_date) {
47
+ if (!this._credentials?.access_token ||
48
+ !this._credentials?.expiry_date ||
49
+ now >= this._credentials.expiry_date) {
48
50
  await this.fetchToken();
49
51
  }
50
52
  }
@@ -57,7 +59,7 @@ class FlashbackAuthClient extends google_auth_library_1.OAuth2Client {
57
59
  const { access_token, expires_in } = response.data;
58
60
  this._credentials = {
59
61
  access_token,
60
- expiry_date: Date.now() + (expires_in * 1000) - 10000,
62
+ expiry_date: Date.now() + expires_in * 1000 - 10000,
61
63
  };
62
64
  }
63
65
  async request(opts) {
@@ -96,9 +96,10 @@ class FlashbackGCSStorage extends storage_1.Storage {
96
96
  expires,
97
97
  expiresPeriodInSeconds,
98
98
  accessibleAt: accessibleAt.toISOString(),
99
- contentType
99
+ contentType,
100
100
  });
101
- if (expiresPeriodInSeconds > 604800) { // 7 days in seconds
101
+ if (expiresPeriodInSeconds > 604800) {
102
+ // 7 days in seconds
102
103
  throw new Error('Max allowed expiration is seven days (604800 seconds).');
103
104
  }
104
105
  const extensionHeaders = {};
@@ -108,12 +109,11 @@ class FlashbackGCSStorage extends storage_1.Storage {
108
109
  }
109
110
  // Sort headers once and use the same order for both signedHeaders and canonicalHeaders
110
111
  const sortedHeaderKeys = Object.keys(extensionHeaders)
111
- .map(header => header.toLowerCase())
112
+ .map((header) => header.toLowerCase())
112
113
  .sort();
113
114
  const signedHeaders = sortedHeaderKeys.join(';');
114
- const canonicalHeaders = sortedHeaderKeys
115
- .map(key => `${key}:${extensionHeaders[key.toLowerCase()]}`)
116
- .join('\n') + '\n';
115
+ const canonicalHeaders = sortedHeaderKeys.map((key) => `${key}:${extensionHeaders[key.toLowerCase()]}`).join('\n') +
116
+ '\n';
117
117
  const datestamp = accessibleAt.toISOString().split('T')[0];
118
118
  const credentialScope = `${datestamp}/auto/storage/goog4_request`;
119
119
  const credential = `${this.credentials.client_email}/${credentialScope}`;
@@ -162,7 +162,9 @@ class FlashbackGCSStorage extends storage_1.Storage {
162
162
  sign.update(stringToSign);
163
163
  const signature = sign.sign(this.credentials.private_key, 'hex');
164
164
  this.doLog('Generated Signature:', signature);
165
- return [`${this.apiEndpoint}/${cfg.file.bucket.name}/${cfg.file.name}?${canonicalQueryString}&X-Goog-Signature=${signature}`];
165
+ return [
166
+ `${this.apiEndpoint}/${cfg.file.bucket.name}/${cfg.file.name}?${canonicalQueryString}&X-Goog-Signature=${signature}`,
167
+ ];
166
168
  }
167
169
  }
168
170
  exports.FlashbackGCSStorage = FlashbackGCSStorage;
@@ -18,6 +18,6 @@ function generateBlockID(blockIDPrefix, blockIndex) {
18
18
  blockIDPrefix = blockIDPrefix.slice(0, maxAllowedBlockIDPrefixLength);
19
19
  }
20
20
  const res = blockIDPrefix +
21
- blockIndex.toString().padStart(maxSourceStringLength - blockIDPrefix.length, "0");
22
- return Buffer.from(res).toString("base64");
21
+ blockIndex.toString().padStart(maxSourceStringLength - blockIDPrefix.length, '0');
22
+ return Buffer.from(res).toString('base64');
23
23
  }
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@flashbacktech/flashbackclient",
3
- "version": "0.0.96",
3
+ "version": "0.0.98",
4
+ "type": "module",
4
5
  "publishConfig": {
5
6
  "access": "public"
6
7
  },