@codeguide/core 0.0.27 → 0.0.29

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.
Files changed (92) hide show
  1. package/README.md +50 -41
  2. package/__tests__/services/codespace/codespace-v2.test.ts +29 -18
  3. package/__tests__/services/usage/usage-service.test.ts +597 -85
  4. package/codeguide.ts +6 -0
  5. package/dist/codeguide.d.ts +3 -1
  6. package/dist/codeguide.js +2 -0
  7. package/dist/index.d.ts +4 -3
  8. package/dist/services/base/base-service.d.ts +21 -0
  9. package/dist/services/base/base-service.js +114 -0
  10. package/dist/services/codespace/codespace-service.d.ts +55 -1
  11. package/dist/services/codespace/codespace-service.js +260 -5
  12. package/dist/services/codespace/codespace-types.d.ts +193 -13
  13. package/dist/services/codespace/index.d.ts +1 -1
  14. package/dist/services/index.d.ts +4 -0
  15. package/dist/services/index.js +7 -1
  16. package/dist/services/projects/project-types.d.ts +66 -32
  17. package/dist/services/repository-analysis/repository-types.d.ts +1 -0
  18. package/dist/services/starter-kits/index.d.ts +2 -0
  19. package/dist/services/starter-kits/index.js +20 -0
  20. package/dist/services/starter-kits/starter-kits-service.d.ts +13 -0
  21. package/dist/services/starter-kits/starter-kits-service.js +27 -0
  22. package/dist/services/starter-kits/starter-kits-types.d.ts +34 -0
  23. package/dist/services/starter-kits/starter-kits-types.js +2 -0
  24. package/dist/services/tasks/task-service.d.ts +2 -1
  25. package/dist/services/tasks/task-service.js +8 -0
  26. package/dist/services/tasks/task-types.d.ts +26 -7
  27. package/dist/services/usage/usage-service.d.ts +5 -2
  28. package/dist/services/usage/usage-service.js +58 -9
  29. package/dist/services/usage/usage-types.d.ts +207 -34
  30. package/dist/services/users/index.d.ts +2 -0
  31. package/dist/services/users/index.js +20 -0
  32. package/dist/services/users/user-service.d.ts +12 -0
  33. package/dist/services/users/user-service.js +17 -0
  34. package/dist/services/users/user-types.d.ts +55 -0
  35. package/dist/services/users/user-types.js +2 -0
  36. package/docs/.vitepress/README.md +51 -0
  37. package/docs/.vitepress/config.ts +139 -0
  38. package/docs/.vitepress/theme/custom.css +80 -0
  39. package/docs/.vitepress/theme/index.ts +13 -0
  40. package/docs/.vitepress/tsconfig.json +19 -0
  41. package/docs/QUICKSTART.md +77 -0
  42. package/docs/README.md +134 -0
  43. package/docs/README_SETUP.md +46 -0
  44. package/docs/authentication.md +351 -0
  45. package/docs/codeguide-client.md +350 -0
  46. package/docs/codespace-models.md +1004 -0
  47. package/docs/codespace-service.md +558 -81
  48. package/docs/index.md +135 -0
  49. package/docs/package.json +14 -0
  50. package/docs/projects-service.md +688 -0
  51. package/docs/security-keys-service.md +773 -0
  52. package/docs/starter-kits-service.md +249 -0
  53. package/docs/task-service.md +955 -0
  54. package/docs/testsprite_tests/TC001_Homepage_Load_and_Hero_Section_Display.py +70 -0
  55. package/docs/testsprite_tests/TC002_Sidebar_Navigation_ExpandCollapse_Functionality.py +73 -0
  56. package/docs/testsprite_tests/TC003_Full_Text_Local_Search_with_Keyboard_Shortcut.py +90 -0
  57. package/docs/testsprite_tests/TC004_Dark_Mode_Toggle_and_Persistence.py +73 -0
  58. package/docs/testsprite_tests/TC005_Mobile_Responsiveness_and_Touch_Navigation.py +113 -0
  59. package/docs/testsprite_tests/TC006_GitHub_Integration_Edit_this_page_Links.py +73 -0
  60. package/docs/testsprite_tests/TC007_Syntax_Highlighting_and_Code_Copy_Functionality.py +73 -0
  61. package/docs/testsprite_tests/TC008_Auto_Generated_Table_of_Contents_Accuracy.py +73 -0
  62. package/docs/testsprite_tests/TC009_SEO_and_Content_Discoverability_Verification.py +73 -0
  63. package/docs/testsprite_tests/TC010_Accessibility_Compliance_WCAG_AA.py +73 -0
  64. package/docs/testsprite_tests/TC011_Local_Development_Workflow_Build_and_Hot_Reload.py +74 -0
  65. package/docs/testsprite_tests/TC012_Performance_Metrics_Compliance.py +73 -0
  66. package/docs/testsprite_tests/standard_prd.json +122 -0
  67. package/docs/testsprite_tests/testsprite-mcp-test-report.html +2508 -0
  68. package/docs/testsprite_tests/testsprite-mcp-test-report.md +273 -0
  69. package/docs/testsprite_tests/testsprite_frontend_test_plan.json +390 -0
  70. package/docs/usage-service.md +616 -0
  71. package/index.ts +11 -3
  72. package/package.json +16 -2
  73. package/plans/CODESPACE_LOGS_STREAMING_GUIDE.md +320 -0
  74. package/plans/CODESPACE_TASK_LOGS_API_COMPLETE_GUIDE.md +821 -0
  75. package/services/base/base-service.ts +130 -0
  76. package/services/codespace/codespace-service.ts +347 -8
  77. package/services/codespace/codespace-types.ts +263 -14
  78. package/services/codespace/index.ts +16 -1
  79. package/services/index.ts +4 -0
  80. package/services/projects/README.md +107 -34
  81. package/services/projects/project-types.ts +69 -32
  82. package/services/repository-analysis/repository-types.ts +1 -0
  83. package/services/starter-kits/index.ts +2 -0
  84. package/services/starter-kits/starter-kits-service.ts +33 -0
  85. package/services/starter-kits/starter-kits-types.ts +38 -0
  86. package/services/tasks/task-service.ts +10 -0
  87. package/services/tasks/task-types.ts +29 -7
  88. package/services/usage/usage-service.ts +59 -10
  89. package/services/usage/usage-types.ts +239 -34
  90. package/services/users/index.ts +2 -0
  91. package/services/users/user-service.ts +15 -0
  92. package/services/users/user-types.ts +59 -0
@@ -4,13 +4,21 @@ import axios from 'axios'
4
4
  import MockAdapter from 'axios-mock-adapter'
5
5
  import {
6
6
  TrackUsageRequest,
7
+ TrackUsageResponse,
7
8
  CreditBalanceResponse,
9
+ CreditBalanceData,
8
10
  CreditCheckResponse,
9
11
  UsageSummaryResponse,
10
12
  AuthorizationResponse,
11
13
  CalculateUsageResponse,
12
14
  TrackCodespaceUsageResponse,
13
15
  CodespaceTaskUsageResponse,
16
+ DashboardAnalyticsRequest,
17
+ DashboardAnalyticsResponse,
18
+ UsageDetailsRequest,
19
+ UsageDetailsResponse,
20
+ ServiceBreakdownRequest,
21
+ ServiceBreakdownResponse,
14
22
  } from '../../../services/usage/usage-types'
15
23
 
16
24
  describe('UsageService', () => {
@@ -19,12 +27,12 @@ describe('UsageService', () => {
19
27
  let config: APIServiceConfig
20
28
 
21
29
  beforeEach(() => {
22
- mockAxios = new MockAdapter(axios)
23
30
  config = {
24
31
  baseUrl: 'https://api.codeguide.app',
25
32
  databaseApiKey: 'sk_test123',
26
33
  }
27
34
  usageService = new UsageService(config)
35
+ mockAxios = new MockAdapter((usageService as any).client)
28
36
  })
29
37
 
30
38
  afterEach(() => {
@@ -48,7 +56,7 @@ describe('UsageService', () => {
48
56
  message: 'Usage tracked successfully',
49
57
  }
50
58
 
51
- mockAxios.onPost('/v1/usage/track', request).reply(200, response)
59
+ mockAxios.onPost('/usage/track', request).reply(200, response)
52
60
 
53
61
  const result = await usageService.trackUsage(request)
54
62
 
@@ -62,7 +70,7 @@ describe('UsageService', () => {
62
70
  output_tokens: 50,
63
71
  }
64
72
 
65
- mockAxios.onPost('/v1/usage/track', request).reply(400, {
73
+ mockAxios.onPost('/usage/track', request).reply(400, {
66
74
  detail: 'Invalid request',
67
75
  })
68
76
 
@@ -72,7 +80,7 @@ describe('UsageService', () => {
72
80
 
73
81
  describe('getCreditBalance', () => {
74
82
  it('should get credit balance successfully', async () => {
75
- const response: CreditBalanceResponse = {
83
+ const creditBalanceData: CreditBalanceData = {
76
84
  user_id: 'user123',
77
85
  total_consumed: 10.5,
78
86
  total_allotted: 100,
@@ -86,7 +94,11 @@ describe('UsageService', () => {
86
94
  },
87
95
  }
88
96
 
89
- mockAxios.onGet('/v1/usage/credit-balance').reply(200, response)
97
+ const response: CreditBalanceResponse = {
98
+ data: creditBalanceData,
99
+ }
100
+
101
+ mockAxios.onGet('/usage/credit-balance').reply(200, response)
90
102
 
91
103
  const result = await usageService.getCreditBalance()
92
104
 
@@ -112,7 +124,7 @@ describe('UsageService', () => {
112
124
 
113
125
  mockAxios
114
126
  .onGet(
115
- '/v1/usage/credit-check?model_key=gpt-4&input_tokens=100&output_tokens=50&call_seconds=2'
127
+ '/usage/credit-check?model_key=gpt-4&input_tokens=100&output_tokens=50&call_seconds=2'
116
128
  )
117
129
  .reply(200, response)
118
130
 
@@ -135,7 +147,7 @@ describe('UsageService', () => {
135
147
  }
136
148
 
137
149
  mockAxios
138
- .onGet('/v1/usage/credit-check?model_key=gpt-4&input_tokens=100')
150
+ .onGet('/usage/credit-check?model_key=gpt-4&input_tokens=100')
139
151
  .reply(200, response)
140
152
 
141
153
  const result = await usageService.checkCredits(params)
@@ -144,94 +156,180 @@ describe('UsageService', () => {
144
156
  })
145
157
  })
146
158
 
147
- describe('getUsageSummary', () => {
148
- it('should get usage summary with date range', async () => {
149
- const params = {
150
- start_date: '2024-01-01',
151
- end_date: '2024-01-31',
152
- }
153
-
154
- const response: UsageSummaryResponse = {
155
- user_id: 'user123',
156
- period: {
157
- start_date: '2024-01-01',
158
- end_date: '2024-01-31',
159
- },
160
- usage_summary: {
161
- total_credits_used: 15.5,
162
- total_calls: 42,
163
- model_breakdown: {
164
- 'gpt-4': { calls: 20, credits: 12.0 },
165
- 'gpt-3.5': { calls: 22, credits: 3.5 },
159
+
160
+ describe('getAuthorization', () => {
161
+ it('should get authorization info successfully', async () => {
162
+ const response: AuthorizationResponse = {
163
+ success: true,
164
+ data: {
165
+ user_id: 'user_32CKVjVlcRfh4HAqpVckgILey0Z',
166
+ subscription: null,
167
+ credit_balance: {
168
+ total_allotted: 500,
169
+ total_consumed: 0,
170
+ remaining_credits: 500,
171
+ is_over_limit: false,
172
+ utilization_percentage: 0.0,
173
+ billing_cycle_start: '2025-11-03',
174
+ billing_cycle_end: '2025-11-10',
175
+ },
176
+ has_active_subscription: false,
177
+ has_previous_subscriptions: false,
178
+ is_within_credit_limit: true,
179
+ authorization_level: 'free',
180
+ restrictions: [],
181
+ can_create_tasks: true,
182
+ can_analyze_repos: true,
183
+ can_access_previous_projects: false,
184
+ plan_limits: {
185
+ plan_type: 'free',
186
+ limits: {
187
+ codespace_tasks: {
188
+ allowed: true,
189
+ current_usage: 0,
190
+ limit: 2,
191
+ remaining: 2,
192
+ period_type: 'lifetime',
193
+ period_start: null,
194
+ period_end: null,
195
+ message: 'Can create 2 more codespace tasks. 2 codespace tasks (lifetime limit)',
196
+ is_unlimited: false,
197
+ },
198
+ api_calls: {
199
+ limit: 500,
200
+ period: '7_days',
201
+ description: '500 API credits (valid for 7 days)',
202
+ is_unlimited: false,
203
+ },
204
+ storage_gb: {
205
+ limit: 1,
206
+ period: 'lifetime',
207
+ description: '1 GB storage',
208
+ is_unlimited: false,
209
+ },
210
+ projects: {
211
+ limit: 3,
212
+ period: 'lifetime',
213
+ description: '3 projects maximum',
214
+ is_unlimited: false,
215
+ },
216
+ collaborators: {
217
+ limit: 0,
218
+ period: 'lifetime',
219
+ description: 'No team collaboration',
220
+ is_unlimited: false,
221
+ },
222
+ },
223
+ },
224
+ codespace_task_limit: {
225
+ allowed: true,
226
+ current_usage: 0,
227
+ limit: 2,
228
+ remaining: 2,
229
+ period_type: 'lifetime',
230
+ period_start: null,
231
+ period_end: null,
232
+ message: 'Can create 2 more codespace tasks. 2 codespace tasks (lifetime limit)',
233
+ is_unlimited: false,
166
234
  },
167
- daily_usage: [
168
- { date: '2024-01-01', credits_used: 1.5, calls: 5 },
169
- { date: '2024-01-02', credits_used: 2.0, calls: 8 },
170
- ],
171
- },
172
- subscription: {
173
- plan: 'pro',
174
- status: 'active',
175
- },
176
- }
177
-
178
- mockAxios
179
- .onGet('/v1/usage/summary?start_date=2024-01-01&end_date=2024-01-31')
180
- .reply(200, response)
181
-
182
- const result = await usageService.getUsageSummary(params)
183
-
184
- expect(result).toEqual(response)
185
- })
186
-
187
- it('should get usage summary without date range', async () => {
188
- const response: UsageSummaryResponse = {
189
- user_id: 'user123',
190
- period: {
191
- start_date: '2024-01-01',
192
- end_date: '2024-01-31',
193
- },
194
- usage_summary: {
195
- total_credits_used: 15.5,
196
- total_calls: 42,
197
- model_breakdown: {},
198
- daily_usage: [],
199
- },
200
- subscription: {
201
- plan: 'pro',
202
- status: 'active',
203
235
  },
236
+ message: 'Authorization status retrieved successfully',
204
237
  }
205
238
 
206
- mockAxios.onGet('/v1/usage/summary').reply(200, response)
239
+ mockAxios.onGet('/usage/authorization').reply(200, response)
207
240
 
208
- const result = await usageService.getUsageSummary()
241
+ const result = await usageService.getAuthorization()
209
242
 
210
243
  expect(result).toEqual(response)
211
244
  })
212
- })
213
245
 
214
- describe('getAuthorization', () => {
215
- it('should get authorization info successfully', async () => {
246
+ it('should get authorization info for subscribed user successfully', async () => {
216
247
  const response: AuthorizationResponse = {
217
- user_id: 'user123',
218
- subscription: {
219
- plan: 'pro',
220
- status: 'active',
221
- features: ['api-access', 'priority-queue'],
222
- },
223
- usage_limits: {
224
- monthly_credits: 100,
225
- max_calls_per_day: 1000,
248
+ success: true,
249
+ data: {
250
+ user_id: 'user_2qaB6nlVH3R9QXhQZpt1nmVDymN',
251
+ subscription: {
252
+ id: 'sub_1RbggdFb0vIg7N8EFOPTEhDh',
253
+ status: 'active',
254
+ interval: 'month',
255
+ current_period_start: '2025-10-19T11:31:19+00:00',
256
+ current_period_end: '2025-11-19T11:31:19+00:00',
257
+ price_id: 'price_1QYtmGFb0vIg7N8E71nw8g27',
258
+ product_name: null,
259
+ plan_name: 'Monthly Plan',
260
+ },
261
+ credit_balance: {
262
+ total_allotted: 5000,
263
+ total_consumed: 658,
264
+ remaining_credits: 4342,
265
+ is_over_limit: false,
266
+ utilization_percentage: 13.16,
267
+ billing_cycle_start: '2025-10-19',
268
+ billing_cycle_end: '2025-11-19',
269
+ },
270
+ has_active_subscription: true,
271
+ has_previous_subscriptions: true,
272
+ is_within_credit_limit: true,
273
+ authorization_level: 'basic',
274
+ restrictions: [],
275
+ can_create_tasks: true,
276
+ can_analyze_repos: true,
277
+ can_access_previous_projects: true,
278
+ plan_limits: {
279
+ plan_type: 'basic',
280
+ limits: {
281
+ codespace_tasks: {
282
+ allowed: true,
283
+ current_usage: 0,
284
+ limit: -1,
285
+ remaining: -1,
286
+ period_type: 'monthly',
287
+ period_start: null,
288
+ period_end: null,
289
+ message: 'Unlimited codespace tasks',
290
+ is_unlimited: true,
291
+ },
292
+ api_calls: {
293
+ limit: 5000,
294
+ period: 'monthly',
295
+ description: '5000 API credits per month',
296
+ is_unlimited: false,
297
+ },
298
+ storage_gb: {
299
+ limit: 10,
300
+ period: 'lifetime',
301
+ description: '10 GB storage',
302
+ is_unlimited: false,
303
+ },
304
+ projects: {
305
+ limit: 20,
306
+ period: 'lifetime',
307
+ description: '20 projects maximum',
308
+ is_unlimited: false,
309
+ },
310
+ collaborators: {
311
+ limit: 3,
312
+ period: 'monthly',
313
+ description: '3 team collaborators',
314
+ is_unlimited: false,
315
+ },
316
+ },
317
+ },
318
+ codespace_task_limit: null,
226
319
  },
227
- permissions: ['read', 'write', 'delete'],
320
+ message: 'Authorization status retrieved successfully',
228
321
  }
229
322
 
230
- mockAxios.onGet('/v1/usage/authorization').reply(200, response)
323
+ mockAxios.onGet('/usage/authorization').reply(200, response)
231
324
 
232
325
  const result = await usageService.getAuthorization()
233
326
 
234
327
  expect(result).toEqual(response)
328
+ expect(result.data.has_active_subscription).toBe(true)
329
+ expect(result.data.subscription).not.toBeNull()
330
+ expect(result.data.subscription?.plan_name).toBe('Monthly Plan')
331
+ expect(result.data.codespace_task_limit).toBeNull()
332
+ expect(result.data.plan_limits.limits.codespace_tasks.is_unlimited).toBe(true)
235
333
  })
236
334
  })
237
335
 
@@ -244,7 +342,7 @@ describe('UsageService', () => {
244
342
  credits_expire_at: '2024-12-31',
245
343
  }
246
344
 
247
- mockAxios.onGet('/v1/usage/free-user-status').reply(200, response)
345
+ mockAxios.onGet('/usage/free-user-status').reply(200, response)
248
346
 
249
347
  const result = await usageService.getFreeUserStatus()
250
348
 
@@ -275,7 +373,7 @@ describe('UsageService', () => {
275
373
 
276
374
  mockAxios
277
375
  .onGet(
278
- '/v1/usage/calculate?model_key=gpt-4&input_tokens=100&output_tokens=50&call_seconds=2&cost_amount=0.05'
376
+ '/usage/calculate?model_key=gpt-4&input_tokens=100&output_tokens=50&call_seconds=2&cost_amount=0.05'
279
377
  )
280
378
  .reply(200, response)
281
379
 
@@ -308,7 +406,7 @@ describe('UsageService', () => {
308
406
  created_at: '2024-01-01T00:00:00Z',
309
407
  }
310
408
 
311
- mockAxios.onPost('/v1/usage/codespace/track', request).reply(200, response)
409
+ mockAxios.onPost('/usage/codespace/track', request).reply(200, response)
312
410
 
313
411
  const result = await usageService.trackCodespaceUsage(request)
314
412
 
@@ -341,7 +439,7 @@ describe('UsageService', () => {
341
439
  ],
342
440
  }
343
441
 
344
- mockAxios.onGet('/v1/usage/codespace/task/task123').reply(200, response)
442
+ mockAxios.onGet('/usage/codespace/task/task123').reply(200, response)
345
443
 
346
444
  const result = await usageService.getCodespaceTaskUsage('task123')
347
445
 
@@ -351,7 +449,7 @@ describe('UsageService', () => {
351
449
 
352
450
  describe('healthCheck', () => {
353
451
  it('should return true when API is healthy', async () => {
354
- mockAxios.onGet('/v1/usage/health').reply(200, {
452
+ mockAxios.onGet('/usage/health').reply(200, {
355
453
  status: 'healthy',
356
454
  timestamp: '2024-01-01T00:00:00Z',
357
455
  version: '1.0.0',
@@ -363,7 +461,7 @@ describe('UsageService', () => {
363
461
  })
364
462
 
365
463
  it('should return false when API is not healthy', async () => {
366
- mockAxios.onGet('/v1/usage/health').reply(200, {
464
+ mockAxios.onGet('/usage/health').reply(200, {
367
465
  status: 'unhealthy',
368
466
  timestamp: '2024-01-01T00:00:00Z',
369
467
  version: '1.0.0',
@@ -375,11 +473,425 @@ describe('UsageService', () => {
375
473
  })
376
474
 
377
475
  it('should return false when health check fails', async () => {
378
- mockAxios.onGet('/v1/usage/health').reply(500)
476
+ mockAxios.onGet('/usage/health').reply(500)
379
477
 
380
478
  const result = await usageService.healthCheck()
381
479
 
382
480
  expect(result).toBe(false)
383
481
  })
384
482
  })
483
+
484
+ // Dashboard Analytics Tests
485
+ describe('getDashboardAnalytics', () => {
486
+ it('should get dashboard analytics with period parameter', async () => {
487
+ const params: DashboardAnalyticsRequest = {
488
+ period: '7d'
489
+ }
490
+
491
+ const response: DashboardAnalyticsResponse = {
492
+ status: 'success',
493
+ data: {
494
+ period: {
495
+ start: '2024-01-25',
496
+ end: '2024-01-31',
497
+ label: '7d'
498
+ },
499
+ daily_usage: [
500
+ {
501
+ date: '2024-01-25',
502
+ credits_consumed: 1250,
503
+ cost_usd: 3.75,
504
+ requests_count: 15,
505
+ average_credits_per_request: 83.33
506
+ }
507
+ ],
508
+ totals: {
509
+ credits_consumed: 13870,
510
+ cost_usd: 41.61,
511
+ requests_count: 142
512
+ },
513
+ averages: {
514
+ daily_credits: 1981.43,
515
+ daily_requests: 20.29
516
+ },
517
+ trends: {
518
+ credits_consumed: 15.7,
519
+ requests_count: 8.3
520
+ },
521
+ top_services: [
522
+ {
523
+ service_type: 'docs',
524
+ credits_consumed: 5230,
525
+ requests_count: 58
526
+ }
527
+ ]
528
+ }
529
+ }
530
+
531
+ mockAxios.onGet('/usage/dashboard/analytics?period=7d').reply(200, response)
532
+
533
+ const result = await usageService.getDashboardAnalytics(params)
534
+
535
+ expect(result).toEqual(response)
536
+ })
537
+
538
+ it('should get dashboard analytics with all parameters', async () => {
539
+ const params: DashboardAnalyticsRequest = {
540
+ start_date: '2024-01-01',
541
+ end_date: '2024-01-31',
542
+ service_type: 'docs'
543
+ }
544
+
545
+ const response: DashboardAnalyticsResponse = {
546
+ status: 'success',
547
+ data: {
548
+ period: {
549
+ start: '2024-01-01',
550
+ end: '2024-01-31',
551
+ label: 'custom'
552
+ },
553
+ daily_usage: [],
554
+ totals: {
555
+ credits_consumed: 5000,
556
+ cost_usd: 15.0,
557
+ requests_count: 45
558
+ },
559
+ averages: {
560
+ daily_credits: 161.29,
561
+ daily_requests: 1.45
562
+ },
563
+ trends: {
564
+ credits_consumed: 12.5,
565
+ requests_count: 5.2
566
+ },
567
+ top_services: [
568
+ {
569
+ service_type: 'docs',
570
+ credits_consumed: 5000,
571
+ requests_count: 45
572
+ }
573
+ ]
574
+ }
575
+ }
576
+
577
+ mockAxios.onGet('/usage/dashboard/analytics?start_date=2024-01-01&end_date=2024-01-31&service_type=docs').reply(200, response)
578
+
579
+ const result = await usageService.getDashboardAnalytics(params)
580
+
581
+ expect(result).toEqual(response)
582
+ })
583
+
584
+ it('should get dashboard analytics without parameters', async () => {
585
+ const response: DashboardAnalyticsResponse = {
586
+ status: 'success',
587
+ data: {
588
+ period: {
589
+ start: '2024-01-01',
590
+ end: '2024-01-07',
591
+ label: '7d'
592
+ },
593
+ daily_usage: [],
594
+ totals: {
595
+ credits_consumed: 1000,
596
+ cost_usd: 3.0,
597
+ requests_count: 10
598
+ },
599
+ averages: {
600
+ daily_credits: 142.86,
601
+ daily_requests: 1.43
602
+ },
603
+ trends: {
604
+ credits_consumed: 5.0,
605
+ requests_count: 2.0
606
+ },
607
+ top_services: []
608
+ }
609
+ }
610
+
611
+ mockAxios.onGet('/usage/dashboard/analytics').reply(200, response)
612
+
613
+ const result = await usageService.getDashboardAnalytics()
614
+
615
+ expect(result).toEqual(response)
616
+ })
617
+ })
618
+
619
+ describe('getUsageDetails', () => {
620
+ it('should get usage details with pagination parameters', async () => {
621
+ const params: UsageDetailsRequest = {
622
+ page: 1,
623
+ page_size: 25,
624
+ sort_by: 'credits_consumed',
625
+ sort_order: 'desc'
626
+ }
627
+
628
+ const response: UsageDetailsResponse = {
629
+ status: 'success',
630
+ data: [
631
+ {
632
+ id: 'rec_123456789',
633
+ created_at: '2024-01-31T14:30:15.123Z',
634
+ service_type: 'docs',
635
+ model_name: 'GPT-4',
636
+ usage_type: 'output_tokens',
637
+ units_consumed: 1250,
638
+ credits_consumed: 156,
639
+ cost_amount: 0.468
640
+ }
641
+ ],
642
+ pagination: {
643
+ page: 1,
644
+ page_size: 25,
645
+ total_count: 142,
646
+ total_pages: 6,
647
+ has_next: true,
648
+ has_prev: false
649
+ },
650
+ filters: {
651
+ period: null,
652
+ start_date: null,
653
+ end_date: null,
654
+ service_type: null
655
+ }
656
+ }
657
+
658
+ mockAxios.onGet('/usage/dashboard/details?page=1&page_size=25&sort_by=credits_consumed&sort_order=desc').reply(200, response)
659
+
660
+ const result = await usageService.getUsageDetails(params)
661
+
662
+ expect(result).toEqual(response)
663
+ })
664
+
665
+ it('should get usage details with filtering parameters', async () => {
666
+ const params: UsageDetailsRequest = {
667
+ period: '1m',
668
+ service_type: 'chat'
669
+ }
670
+
671
+ const response: UsageDetailsResponse = {
672
+ status: 'success',
673
+ data: [
674
+ {
675
+ id: 'rec_123456790',
676
+ created_at: '2024-01-30T10:15:20.456Z',
677
+ service_type: 'chat',
678
+ model_name: 'GPT-3.5 Turbo',
679
+ usage_type: 'input_tokens',
680
+ units_consumed: 890,
681
+ credits_consumed: 89,
682
+ cost_amount: null
683
+ }
684
+ ],
685
+ pagination: {
686
+ page: 1,
687
+ page_size: 50,
688
+ total_count: 25,
689
+ total_pages: 1,
690
+ has_next: false,
691
+ has_prev: false
692
+ },
693
+ filters: {
694
+ period: '1m',
695
+ start_date: null,
696
+ end_date: null,
697
+ service_type: 'chat'
698
+ }
699
+ }
700
+
701
+ mockAxios.onGet('/usage/dashboard/details?period=1m&service_type=chat').reply(200, response)
702
+
703
+ const result = await usageService.getUsageDetails(params)
704
+
705
+ expect(result).toEqual(response)
706
+ })
707
+ })
708
+
709
+ describe('getUsageSummary', () => {
710
+ it('should get usage summary dashboard with period parameter', async () => {
711
+ const params = {
712
+ period: '7d' as const
713
+ }
714
+
715
+ const response: UsageSummaryResponse = {
716
+ status: 'success',
717
+ data: {
718
+ current_period: {
719
+ credits_consumed: 13870,
720
+ cost_usd: 41.61,
721
+ requests_count: 142
722
+ },
723
+ previous_period: {
724
+ credits_consumed: 11990,
725
+ cost_usd: 35.97,
726
+ requests_count: 131
727
+ },
728
+ billing_cycle: {
729
+ total_allotted: 50000,
730
+ total_consumed: 28450,
731
+ remaining_credits: 21550
732
+ },
733
+ utilization_percentage: 56.9,
734
+ remaining_credits: 21550,
735
+ daily_average: 1981.43,
736
+ projected_monthly: 59443
737
+ }
738
+ }
739
+
740
+ mockAxios.onGet('/usage/dashboard/summary?period=7d').reply(200, response)
741
+
742
+ const result = await usageService.getUsageSummary(params)
743
+
744
+ expect(result).toEqual(response)
745
+ })
746
+
747
+ it('should get usage summary dashboard with custom date range', async () => {
748
+ const params = {
749
+ start_date: '2024-01-01',
750
+ end_date: '2024-01-31'
751
+ }
752
+
753
+ const response: UsageSummaryResponse = {
754
+ status: 'success',
755
+ data: {
756
+ current_period: {
757
+ credits_consumed: 25000,
758
+ cost_usd: 75.0,
759
+ requests_count: 300
760
+ },
761
+ previous_period: {
762
+ credits_consumed: 22000,
763
+ cost_usd: 66.0,
764
+ requests_count: 275
765
+ },
766
+ billing_cycle: {
767
+ total_allotted: 50000,
768
+ total_consumed: 47000,
769
+ remaining_credits: 3000
770
+ },
771
+ utilization_percentage: 94.0,
772
+ remaining_credits: 3000,
773
+ daily_average: 806.45,
774
+ projected_monthly: 25000
775
+ }
776
+ }
777
+
778
+ mockAxios.onGet('/usage/dashboard/summary?start_date=2024-01-01&end_date=2024-01-31').reply(200, response)
779
+
780
+ const result = await usageService.getUsageSummary(params)
781
+
782
+ expect(result).toEqual(response)
783
+ })
784
+ })
785
+
786
+ describe('getServiceBreakdown', () => {
787
+ it('should get service breakdown with period parameter', async () => {
788
+ const params: ServiceBreakdownRequest = {
789
+ period: '7d'
790
+ }
791
+
792
+ const response: ServiceBreakdownResponse = {
793
+ status: 'success',
794
+ data: {
795
+ period: {
796
+ start: '2024-01-25',
797
+ end: '2024-01-31',
798
+ label: '7d'
799
+ },
800
+ services: [
801
+ {
802
+ service_type: 'docs',
803
+ credits_consumed: 5230,
804
+ percentage: 37.71,
805
+ cost_usd: 15.69,
806
+ requests_count: 58,
807
+ trend: 12.5
808
+ },
809
+ {
810
+ service_type: 'chat',
811
+ credits_consumed: 4120,
812
+ percentage: 29.71,
813
+ cost_usd: 12.36,
814
+ requests_count: 47,
815
+ trend: -5.2
816
+ }
817
+ ],
818
+ total_credits: 13870,
819
+ total_cost: 41.61
820
+ }
821
+ }
822
+
823
+ mockAxios.onGet('/usage/dashboard/services?period=7d').reply(200, response)
824
+
825
+ const result = await usageService.getServiceBreakdown(params)
826
+
827
+ expect(result).toEqual(response)
828
+ })
829
+
830
+ it('should get service breakdown with custom date range', async () => {
831
+ const params: ServiceBreakdownRequest = {
832
+ start_date: '2024-01-01',
833
+ end_date: '2024-01-31'
834
+ }
835
+
836
+ const response: ServiceBreakdownResponse = {
837
+ status: 'success',
838
+ data: {
839
+ period: {
840
+ start: '2024-01-01',
841
+ end: '2024-01-31',
842
+ label: 'custom'
843
+ },
844
+ services: [
845
+ {
846
+ service_type: 'codespace_task',
847
+ credits_consumed: 15000,
848
+ percentage: 60.0,
849
+ cost_usd: 45.0,
850
+ requests_count: 25,
851
+ trend: 28.4
852
+ }
853
+ ],
854
+ total_credits: 25000,
855
+ total_cost: 75.0
856
+ }
857
+ }
858
+
859
+ mockAxios.onGet('/usage/dashboard/services?start_date=2024-01-01&end_date=2024-01-31').reply(200, response)
860
+
861
+ const result = await usageService.getServiceBreakdown(params)
862
+
863
+ expect(result).toEqual(response)
864
+ })
865
+
866
+ it('should get service breakdown without parameters', async () => {
867
+ const response: ServiceBreakdownResponse = {
868
+ status: 'success',
869
+ data: {
870
+ period: {
871
+ start: '2024-01-01',
872
+ end: '2024-01-07',
873
+ label: '7d'
874
+ },
875
+ services: [
876
+ {
877
+ service_type: 'api',
878
+ credits_consumed: 700,
879
+ percentage: 100.0,
880
+ cost_usd: 2.10,
881
+ requests_count: 5,
882
+ trend: 0.0
883
+ }
884
+ ],
885
+ total_credits: 700,
886
+ total_cost: 2.10
887
+ }
888
+ }
889
+
890
+ mockAxios.onGet('/usage/dashboard/services').reply(200, response)
891
+
892
+ const result = await usageService.getServiceBreakdown()
893
+
894
+ expect(result).toEqual(response)
895
+ })
896
+ })
385
897
  })