@codeguide/core 0.0.1
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/__tests__/authentication.test.ts +259 -0
- package/__tests__/codeguide.test.ts +293 -0
- package/__tests__/services/base/base-service.test.ts +334 -0
- package/__tests__/services/generation/generation-service.test.ts +294 -0
- package/__tests__/services/usage/usage-service.test.ts +385 -0
- package/__tests__/simple.test.ts +10 -0
- package/__tests__/test-service.ts +37 -0
- package/api-service.ts +67 -0
- package/codeguide.ts +70 -0
- package/dist/__tests__/test-service.d.ts +12 -0
- package/dist/__tests__/test-service.js +32 -0
- package/dist/api-service.d.ts +8 -0
- package/dist/api-service.js +64 -0
- package/dist/codeguide.d.ts +14 -0
- package/dist/codeguide.js +53 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +31 -0
- package/dist/services/base/base-service.d.ts +30 -0
- package/dist/services/base/base-service.js +187 -0
- package/dist/services/base/index.d.ts +1 -0
- package/dist/services/base/index.js +5 -0
- package/dist/services/generation/generation-service.d.ts +15 -0
- package/dist/services/generation/generation-service.js +40 -0
- package/dist/services/generation/generation-types.d.ts +111 -0
- package/dist/services/generation/generation-types.js +2 -0
- package/dist/services/generation/index.d.ts +2 -0
- package/dist/services/generation/index.js +20 -0
- package/dist/services/index.d.ts +11 -0
- package/dist/services/index.js +45 -0
- package/dist/services/projects/index.d.ts +2 -0
- package/dist/services/projects/index.js +20 -0
- package/dist/services/projects/project-service.d.ts +14 -0
- package/dist/services/projects/project-service.js +53 -0
- package/dist/services/projects/project-types.d.ts +97 -0
- package/dist/services/projects/project-types.js +2 -0
- package/dist/services/repository-analysis/index.d.ts +2 -0
- package/dist/services/repository-analysis/index.js +20 -0
- package/dist/services/repository-analysis/repository-service.d.ts +10 -0
- package/dist/services/repository-analysis/repository-service.js +31 -0
- package/dist/services/repository-analysis/repository-types.d.ts +90 -0
- package/dist/services/repository-analysis/repository-types.js +2 -0
- package/dist/services/tasks/index.d.ts +2 -0
- package/dist/services/tasks/index.js +20 -0
- package/dist/services/tasks/task-service.d.ts +30 -0
- package/dist/services/tasks/task-service.js +105 -0
- package/dist/services/tasks/task-types.d.ts +144 -0
- package/dist/services/tasks/task-types.js +2 -0
- package/dist/services/usage/index.d.ts +2 -0
- package/dist/services/usage/index.js +20 -0
- package/dist/services/usage/usage-service.d.ts +14 -0
- package/dist/services/usage/usage-service.js +68 -0
- package/dist/services/usage/usage-types.d.ts +133 -0
- package/dist/services/usage/usage-types.js +2 -0
- package/dist/types.d.ts +42 -0
- package/dist/types.js +2 -0
- package/index.ts +12 -0
- package/jest.config.json +19 -0
- package/package.json +45 -0
- package/services/README.md +113 -0
- package/services/base/base-service.ts +230 -0
- package/services/base/index.ts +1 -0
- package/services/generation/generation-service.ts +81 -0
- package/services/generation/generation-types.ts +131 -0
- package/services/generation/index.ts +2 -0
- package/services/index.ts +22 -0
- package/services/projects/index.ts +2 -0
- package/services/projects/project-service.ts +67 -0
- package/services/projects/project-types.ts +108 -0
- package/services/repository-analysis/index.ts +2 -0
- package/services/repository-analysis/repository-service.ts +42 -0
- package/services/repository-analysis/repository-types.ts +99 -0
- package/services/tasks/index.ts +2 -0
- package/services/tasks/task-service.ts +143 -0
- package/services/tasks/task-types.ts +165 -0
- package/services/usage/index.ts +2 -0
- package/services/usage/usage-service.ts +96 -0
- package/services/usage/usage-types.ts +147 -0
- package/tsconfig.json +10 -0
- package/types.ts +51 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UsageService = void 0;
|
|
4
|
+
const base_service_1 = require("../base/base-service");
|
|
5
|
+
class UsageService extends base_service_1.BaseService {
|
|
6
|
+
async trackUsage(request) {
|
|
7
|
+
return this.post('/usage/track', request);
|
|
8
|
+
}
|
|
9
|
+
async getCreditBalance() {
|
|
10
|
+
return this.get('/usage/credit-balance');
|
|
11
|
+
}
|
|
12
|
+
async checkCredits(params) {
|
|
13
|
+
const queryParams = new URLSearchParams();
|
|
14
|
+
if (params.input_tokens !== undefined)
|
|
15
|
+
queryParams.append('input_tokens', params.input_tokens.toString());
|
|
16
|
+
if (params.output_tokens !== undefined)
|
|
17
|
+
queryParams.append('output_tokens', params.output_tokens.toString());
|
|
18
|
+
if (params.call_seconds !== undefined)
|
|
19
|
+
queryParams.append('call_seconds', params.call_seconds.toString());
|
|
20
|
+
const url = `/usage/credit-check?${queryParams.toString()}`;
|
|
21
|
+
return this.get(url);
|
|
22
|
+
}
|
|
23
|
+
async getUsageSummary(params) {
|
|
24
|
+
const queryParams = new URLSearchParams();
|
|
25
|
+
if (params?.start_date)
|
|
26
|
+
queryParams.append('start_date', params.start_date);
|
|
27
|
+
if (params?.end_date)
|
|
28
|
+
queryParams.append('end_date', params.end_date);
|
|
29
|
+
const url = `/usage/summary${queryParams.toString() ? `?${queryParams.toString()}` : ''}`;
|
|
30
|
+
return this.get(url);
|
|
31
|
+
}
|
|
32
|
+
async getAuthorization() {
|
|
33
|
+
return this.get('/usage/authorization');
|
|
34
|
+
}
|
|
35
|
+
async getFreeUserStatus() {
|
|
36
|
+
return this.get('/usage/free-user-status');
|
|
37
|
+
}
|
|
38
|
+
async calculateUsageCost(params) {
|
|
39
|
+
const queryParams = new URLSearchParams();
|
|
40
|
+
queryParams.append('model_key', params.model_key);
|
|
41
|
+
if (params.input_tokens !== undefined)
|
|
42
|
+
queryParams.append('input_tokens', params.input_tokens.toString());
|
|
43
|
+
if (params.output_tokens !== undefined)
|
|
44
|
+
queryParams.append('output_tokens', params.output_tokens.toString());
|
|
45
|
+
if (params.call_seconds !== undefined)
|
|
46
|
+
queryParams.append('call_seconds', params.call_seconds.toString());
|
|
47
|
+
if (params.cost_amount !== undefined)
|
|
48
|
+
queryParams.append('cost_amount', params.cost_amount.toString());
|
|
49
|
+
const url = `/usage/calculate?${queryParams.toString()}`;
|
|
50
|
+
return this.get(url);
|
|
51
|
+
}
|
|
52
|
+
async trackCodespaceUsage(request) {
|
|
53
|
+
return this.post('/usage/codespace/track', request);
|
|
54
|
+
}
|
|
55
|
+
async getCodespaceTaskUsage(codespaceTaskId) {
|
|
56
|
+
return this.get(`/usage/codespace/task/${codespaceTaskId}`);
|
|
57
|
+
}
|
|
58
|
+
async healthCheck() {
|
|
59
|
+
try {
|
|
60
|
+
const response = await this.get('/usage/health');
|
|
61
|
+
return response.status === 'healthy';
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.UsageService = UsageService;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
export interface TrackUsageRequest {
|
|
2
|
+
model_key: string;
|
|
3
|
+
input_tokens: number;
|
|
4
|
+
output_tokens: number;
|
|
5
|
+
call_seconds?: number;
|
|
6
|
+
cost_amount?: number;
|
|
7
|
+
}
|
|
8
|
+
export interface TrackUsageResponse {
|
|
9
|
+
success: boolean;
|
|
10
|
+
credits_used: number;
|
|
11
|
+
remaining_credits: number;
|
|
12
|
+
message: string;
|
|
13
|
+
}
|
|
14
|
+
export interface CreditBalanceResponse {
|
|
15
|
+
user_id: string;
|
|
16
|
+
total_consumed: number;
|
|
17
|
+
total_allotted: number;
|
|
18
|
+
remaining_credits: number;
|
|
19
|
+
utilization_percentage: number;
|
|
20
|
+
billing_cycle_start: string;
|
|
21
|
+
billing_cycle_end: string;
|
|
22
|
+
subscription: {
|
|
23
|
+
plan: string;
|
|
24
|
+
status: string;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export interface CreditCheckRequest {
|
|
28
|
+
model_key: string;
|
|
29
|
+
input_tokens?: number;
|
|
30
|
+
output_tokens?: number;
|
|
31
|
+
call_seconds?: number;
|
|
32
|
+
}
|
|
33
|
+
export interface CreditCheckResponse {
|
|
34
|
+
has_sufficient_credits: boolean;
|
|
35
|
+
estimated_cost: number;
|
|
36
|
+
remaining_credits: number;
|
|
37
|
+
model_key: string;
|
|
38
|
+
}
|
|
39
|
+
export interface UsageSummaryRequest {
|
|
40
|
+
start_date?: string;
|
|
41
|
+
end_date?: string;
|
|
42
|
+
}
|
|
43
|
+
export interface UsageSummaryResponse {
|
|
44
|
+
user_id: string;
|
|
45
|
+
period: {
|
|
46
|
+
start_date: string;
|
|
47
|
+
end_date: string;
|
|
48
|
+
};
|
|
49
|
+
usage_summary: {
|
|
50
|
+
total_credits_used: number;
|
|
51
|
+
total_calls: number;
|
|
52
|
+
model_breakdown: Record<string, any>;
|
|
53
|
+
daily_usage: Array<{
|
|
54
|
+
date: string;
|
|
55
|
+
credits_used: number;
|
|
56
|
+
calls: number;
|
|
57
|
+
}>;
|
|
58
|
+
};
|
|
59
|
+
subscription: {
|
|
60
|
+
plan: string;
|
|
61
|
+
status: string;
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
export interface AuthorizationResponse {
|
|
65
|
+
user_id: string;
|
|
66
|
+
subscription: {
|
|
67
|
+
plan: string;
|
|
68
|
+
status: string;
|
|
69
|
+
features: string[];
|
|
70
|
+
};
|
|
71
|
+
usage_limits: {
|
|
72
|
+
monthly_credits: number;
|
|
73
|
+
max_calls_per_day: number;
|
|
74
|
+
};
|
|
75
|
+
permissions: string[];
|
|
76
|
+
}
|
|
77
|
+
export interface FreeUserStatusResponse {
|
|
78
|
+
is_free_user: boolean;
|
|
79
|
+
has_available_credits: boolean;
|
|
80
|
+
credits_remaining: number;
|
|
81
|
+
credits_expire_at?: string;
|
|
82
|
+
}
|
|
83
|
+
export interface CalculateUsageRequest {
|
|
84
|
+
model_key: string;
|
|
85
|
+
input_tokens?: number;
|
|
86
|
+
output_tokens?: number;
|
|
87
|
+
call_seconds?: number;
|
|
88
|
+
cost_amount?: number;
|
|
89
|
+
}
|
|
90
|
+
export interface CalculateUsageResponse {
|
|
91
|
+
model_key: string;
|
|
92
|
+
estimated_cost: number;
|
|
93
|
+
calculation_breakdown: {
|
|
94
|
+
input_cost: number;
|
|
95
|
+
output_cost: number;
|
|
96
|
+
time_cost: number;
|
|
97
|
+
total_cost: number;
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
export interface TrackCodespaceUsageRequest {
|
|
101
|
+
codespace_task_id: string;
|
|
102
|
+
model_key: string;
|
|
103
|
+
input_tokens: number;
|
|
104
|
+
output_tokens: number;
|
|
105
|
+
call_seconds?: number;
|
|
106
|
+
cost_amount?: number;
|
|
107
|
+
}
|
|
108
|
+
export interface TrackCodespaceUsageResponse {
|
|
109
|
+
id: string;
|
|
110
|
+
codespace_task_id: string;
|
|
111
|
+
user_id: string;
|
|
112
|
+
model_key: string;
|
|
113
|
+
input_tokens: number;
|
|
114
|
+
output_tokens: number;
|
|
115
|
+
call_seconds: number;
|
|
116
|
+
cost_amount: number;
|
|
117
|
+
created_at: string;
|
|
118
|
+
}
|
|
119
|
+
export interface CodespaceTaskUsageResponse {
|
|
120
|
+
codespace_task_id: string;
|
|
121
|
+
total_usage: {
|
|
122
|
+
total_input_tokens: number;
|
|
123
|
+
total_output_tokens: number;
|
|
124
|
+
total_call_seconds: number;
|
|
125
|
+
total_cost: number;
|
|
126
|
+
};
|
|
127
|
+
usage_records: TrackCodespaceUsageResponse[];
|
|
128
|
+
}
|
|
129
|
+
export interface HealthResponse {
|
|
130
|
+
status: string;
|
|
131
|
+
timestamp: string;
|
|
132
|
+
version: string;
|
|
133
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export interface CodeGuideRequest {
|
|
2
|
+
prompt: string;
|
|
3
|
+
language?: string;
|
|
4
|
+
context?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface CodeGuideResponse {
|
|
7
|
+
id?: string;
|
|
8
|
+
response?: string;
|
|
9
|
+
refined_prompt?: string;
|
|
10
|
+
content?: string;
|
|
11
|
+
timestamp: string;
|
|
12
|
+
language?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface APIServiceConfig {
|
|
15
|
+
baseUrl: string;
|
|
16
|
+
databaseApiKey?: string;
|
|
17
|
+
apiKey?: string;
|
|
18
|
+
userId?: string;
|
|
19
|
+
jwtToken?: string;
|
|
20
|
+
timeout?: number;
|
|
21
|
+
}
|
|
22
|
+
export interface AuthenticationMethod {
|
|
23
|
+
type: 'database-api-key' | 'legacy-api-key' | 'clerk-jwt';
|
|
24
|
+
priority: number;
|
|
25
|
+
headers: Record<string, string>;
|
|
26
|
+
}
|
|
27
|
+
export interface AuthenticationResult {
|
|
28
|
+
success: boolean;
|
|
29
|
+
method?: AuthenticationMethod;
|
|
30
|
+
user?: {
|
|
31
|
+
id: string;
|
|
32
|
+
email?: string;
|
|
33
|
+
subscriptionStatus?: string;
|
|
34
|
+
creditsRemaining?: number;
|
|
35
|
+
};
|
|
36
|
+
error?: string;
|
|
37
|
+
}
|
|
38
|
+
export interface CodeGuideOptions {
|
|
39
|
+
language?: string;
|
|
40
|
+
context?: string;
|
|
41
|
+
verbose?: boolean;
|
|
42
|
+
}
|
package/dist/types.js
ADDED
package/index.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import dotenv from 'dotenv'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
|
|
4
|
+
// Load environment variables from project root
|
|
5
|
+
dotenv.config({
|
|
6
|
+
path: path.resolve(__dirname, '../../../.env'),
|
|
7
|
+
quiet: true,
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
export { CodeGuide } from './codeguide'
|
|
11
|
+
export * from './services'
|
|
12
|
+
export * from './types'
|
package/jest.config.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"preset": "ts-jest",
|
|
3
|
+
"testEnvironment": "node",
|
|
4
|
+
"roots": ["<rootDir>"],
|
|
5
|
+
"testMatch": ["**/__tests__/**/*.test.ts"],
|
|
6
|
+
"transform": {
|
|
7
|
+
"^.+\\.ts$": "ts-jest"
|
|
8
|
+
},
|
|
9
|
+
"collectCoverageFrom": [
|
|
10
|
+
"**/*.ts",
|
|
11
|
+
"!**/*.d.ts",
|
|
12
|
+
"!**/index.ts",
|
|
13
|
+
"!**/node_modules/**",
|
|
14
|
+
"!**/__tests__/**"
|
|
15
|
+
],
|
|
16
|
+
"coverageDirectory": "coverage",
|
|
17
|
+
"coverageReporters": ["text", "lcov"],
|
|
18
|
+
"setupFilesAfterEnv": ["<rootDir>/../../jest.setup.js"]
|
|
19
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@codeguide/core",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Core package for code guidance with programmatic API",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"test": "jest --config=jest.config.json",
|
|
10
|
+
"test:watch": "jest --config=jest.config.json --watch",
|
|
11
|
+
"test:coverage": "jest --config=jest.config.json --coverage"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"api",
|
|
15
|
+
"typescript",
|
|
16
|
+
"code",
|
|
17
|
+
"development",
|
|
18
|
+
"productivity",
|
|
19
|
+
"ai",
|
|
20
|
+
"sdk"
|
|
21
|
+
],
|
|
22
|
+
"author": "CodeGuide Team",
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "https://github.com/CodeGuide-dev/codeguide.git"
|
|
26
|
+
},
|
|
27
|
+
"bugs": {
|
|
28
|
+
"url": "https://github.com/CodeGuide-dev/codeguide/issues"
|
|
29
|
+
},
|
|
30
|
+
"homepage": "https://github.com/CodeGuide-dev/codeguide#readme",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"axios": "^1.6.0",
|
|
34
|
+
"dotenv": "^17.2.2"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/node": "^20.0.0",
|
|
38
|
+
"typescript": "^5.0.0",
|
|
39
|
+
"jest": "^29.0.0",
|
|
40
|
+
"@types/jest": "^29.0.0",
|
|
41
|
+
"ts-jest": "^29.0.0",
|
|
42
|
+
"axios-mock-adapter": "^1.22.0",
|
|
43
|
+
"@types/dotenv": "^6.1.1"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# CodeGuide API Services
|
|
2
|
+
|
|
3
|
+
This directory contains modular services for interacting with different CodeGuide API endpoints.
|
|
4
|
+
|
|
5
|
+
## Available Services
|
|
6
|
+
|
|
7
|
+
### 1. GenerationService (`/generate`)
|
|
8
|
+
|
|
9
|
+
Handles AI-powered content generation:
|
|
10
|
+
|
|
11
|
+
- `refinePrompt()` - Refine user prompts
|
|
12
|
+
- `generateTitle()` - Generate project titles
|
|
13
|
+
- `generateQuestionnaire()` - Generate questionnaires
|
|
14
|
+
- `generatePRD()` - Generate Project Requirements Documents
|
|
15
|
+
- `generateCategory()` - Suggest project categories
|
|
16
|
+
- `generateOutline()` - Generate document outlines
|
|
17
|
+
- `generateDocument()` - Generate custom documents
|
|
18
|
+
- `generateMultipleDocuments()` - Generate multiple documents in parallel
|
|
19
|
+
- `startBackgroundGeneration()` - Start background generation jobs
|
|
20
|
+
- `getBackgroundGenerationStatus()` - Check background job status
|
|
21
|
+
|
|
22
|
+
### 2. ProjectService (`/projects`)
|
|
23
|
+
|
|
24
|
+
Manages projects:
|
|
25
|
+
|
|
26
|
+
- `getAllProjects()` - Get all user projects
|
|
27
|
+
- `getPaginatedProjects()` - Get paginated projects with filtering
|
|
28
|
+
- `getProjectById()` - Get specific project
|
|
29
|
+
- `createProject()` - Create new project
|
|
30
|
+
- `updateProject()` - Update existing project
|
|
31
|
+
- `deleteProject()` - Delete project
|
|
32
|
+
|
|
33
|
+
### 3. UsageService (`/usage`)
|
|
34
|
+
|
|
35
|
+
Handles usage tracking and credits:
|
|
36
|
+
|
|
37
|
+
- `trackUsage()` - Track API usage
|
|
38
|
+
- `getCreditBalance()` - Get current credit balance
|
|
39
|
+
- `checkCredits()` - Check if sufficient credits available
|
|
40
|
+
- `getUsageSummary()` - Get detailed usage summary
|
|
41
|
+
- `getAuthorization()` - Get user authorization status
|
|
42
|
+
- `getFreeUserStatus()` - Check free user status
|
|
43
|
+
- `calculateUsageCost()` - Calculate usage costs
|
|
44
|
+
- `trackCodespaceUsage()` - Track codespace usage
|
|
45
|
+
- `getCodespaceTaskUsage()` - Get codespace usage details
|
|
46
|
+
- `healthCheck()` - Check API health
|
|
47
|
+
|
|
48
|
+
### 4. RepositoryAnalysisService (`/repository-analysis`)
|
|
49
|
+
|
|
50
|
+
Analyzes GitHub repositories:
|
|
51
|
+
|
|
52
|
+
- `analyzeRepository()` - Start repository analysis
|
|
53
|
+
- `getAnalysisStatus()` - Check analysis status
|
|
54
|
+
- `getAnalysisResult()` - Get analysis results
|
|
55
|
+
- `listRepositories()` - List analyzed repositories
|
|
56
|
+
- `getRepositoryDetails()` - Get repository details
|
|
57
|
+
- `deleteRepository()` - Delete repository analysis
|
|
58
|
+
|
|
59
|
+
### 5. TaskService (`/task-groups`, `/project-tasks`)
|
|
60
|
+
|
|
61
|
+
Manages task groups and project tasks:
|
|
62
|
+
|
|
63
|
+
- **Task Groups**: CRUD operations for task groups
|
|
64
|
+
- **Project Tasks**: CRUD operations for project tasks
|
|
65
|
+
- **Pagination**: Support for paginated results
|
|
66
|
+
- **Filtering**: Filter by status, project, parent task, etc.
|
|
67
|
+
|
|
68
|
+
### 6. BaseService
|
|
69
|
+
|
|
70
|
+
Base class providing common functionality:
|
|
71
|
+
|
|
72
|
+
- HTTP client setup with proper headers
|
|
73
|
+
- Error handling with standardized responses
|
|
74
|
+
- Authentication handling (API Key + User ID)
|
|
75
|
+
- Request/response interceptors
|
|
76
|
+
- Common HTTP methods (GET, POST, PUT, DELETE)
|
|
77
|
+
|
|
78
|
+
## Usage Example
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
import { CodeGuide, APIServiceConfig } from '@codeguide/core'
|
|
82
|
+
|
|
83
|
+
const config: APIServiceConfig = {
|
|
84
|
+
baseUrl: 'https://api.codeguide.app',
|
|
85
|
+
apiKey: 'your-api-key',
|
|
86
|
+
userId: 'your-user-id',
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const codeguide = new CodeGuide(config)
|
|
90
|
+
|
|
91
|
+
// Use different services
|
|
92
|
+
const projects = await codeguide.projects.getAllProjects()
|
|
93
|
+
const creditBalance = await codeguide.usage.getCreditBalance()
|
|
94
|
+
const refinedPrompt = await codeguide.generation.refinePrompt({
|
|
95
|
+
user_prompt: 'How do I create a React component?',
|
|
96
|
+
})
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Configuration
|
|
100
|
+
|
|
101
|
+
All services accept the same configuration:
|
|
102
|
+
|
|
103
|
+
- `baseUrl`: API base URL (defaults to https://api.codeguide.app)
|
|
104
|
+
- `apiKey`: API key for authentication
|
|
105
|
+
- `userId`: User ID for authentication
|
|
106
|
+
- `timeout`: Request timeout (default: 3600000ms / 1 hour)
|
|
107
|
+
|
|
108
|
+
## Authentication
|
|
109
|
+
|
|
110
|
+
Services use the CodeGuide API authentication scheme:
|
|
111
|
+
|
|
112
|
+
- Primary: `X-API-Key` + `X-User-ID` headers
|
|
113
|
+
- Fallback: `Authorization: Bearer <token>`
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import axios, { AxiosInstance, AxiosResponse } from 'axios'
|
|
2
|
+
import { APIServiceConfig, AuthenticationMethod, AuthenticationResult } from '../../types'
|
|
3
|
+
|
|
4
|
+
export abstract class BaseService {
|
|
5
|
+
protected client: AxiosInstance
|
|
6
|
+
protected config: APIServiceConfig
|
|
7
|
+
|
|
8
|
+
constructor(config: APIServiceConfig) {
|
|
9
|
+
this.config = config
|
|
10
|
+
|
|
11
|
+
// Ensure baseUrl includes the API version
|
|
12
|
+
const baseUrl = config.baseUrl
|
|
13
|
+
|
|
14
|
+
this.client = axios.create({
|
|
15
|
+
baseURL: baseUrl,
|
|
16
|
+
timeout: config.timeout || 3600000, // 1 hour timeout for document generation
|
|
17
|
+
headers: this.getAuthenticationHeaders(),
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
this.setupInterceptors()
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Determine and return authentication headers based on priority
|
|
25
|
+
* Priority: 1. Database API Key, 2. Legacy API Key, 3. Clerk JWT
|
|
26
|
+
*/
|
|
27
|
+
private getAuthenticationHeaders(): Record<string, string> {
|
|
28
|
+
const headers: Record<string, string> = {
|
|
29
|
+
'Content-Type': 'application/json',
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Priority 1: Database API Key (format: sk_...)
|
|
33
|
+
if (this.config.databaseApiKey && this.config.databaseApiKey.startsWith('sk_')) {
|
|
34
|
+
headers['Authorization'] = `Bearer ${this.config.databaseApiKey}`
|
|
35
|
+
return headers
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return headers
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Get the current authentication method being used
|
|
43
|
+
*/
|
|
44
|
+
public getAuthenticationMethod(): AuthenticationMethod | null {
|
|
45
|
+
// Priority 1: Database API Key
|
|
46
|
+
if (this.config.databaseApiKey && this.config.databaseApiKey.startsWith('sk_')) {
|
|
47
|
+
return {
|
|
48
|
+
type: 'database-api-key',
|
|
49
|
+
priority: 1,
|
|
50
|
+
headers: {
|
|
51
|
+
Authorization: `Bearer ${this.config.databaseApiKey}`,
|
|
52
|
+
'Content-Type': 'application/json',
|
|
53
|
+
},
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Priority 2: Legacy API Key + User ID
|
|
58
|
+
if (this.config.apiKey && this.config.userId) {
|
|
59
|
+
return {
|
|
60
|
+
type: 'legacy-api-key',
|
|
61
|
+
priority: 2,
|
|
62
|
+
headers: {
|
|
63
|
+
'X-API-Key': this.config.apiKey,
|
|
64
|
+
'X-User-ID': this.config.userId,
|
|
65
|
+
'Content-Type': 'application/json',
|
|
66
|
+
},
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Priority 3: Clerk JWT Token
|
|
71
|
+
if (this.config.jwtToken) {
|
|
72
|
+
return {
|
|
73
|
+
type: 'clerk-jwt',
|
|
74
|
+
priority: 3,
|
|
75
|
+
headers: {
|
|
76
|
+
Authorization: `Bearer ${this.config.jwtToken}`,
|
|
77
|
+
'Content-Type': 'application/json',
|
|
78
|
+
},
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Fallback: Legacy API key without user ID
|
|
83
|
+
if (this.config.apiKey) {
|
|
84
|
+
return {
|
|
85
|
+
type: 'legacy-api-key',
|
|
86
|
+
priority: 2,
|
|
87
|
+
headers: {
|
|
88
|
+
'X-API-Key': this.config.apiKey,
|
|
89
|
+
'Content-Type': 'application/json',
|
|
90
|
+
},
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return null
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Validate the current authentication configuration
|
|
99
|
+
*/
|
|
100
|
+
public validateAuthentication(): AuthenticationResult {
|
|
101
|
+
const method = this.getAuthenticationMethod()
|
|
102
|
+
|
|
103
|
+
if (!method) {
|
|
104
|
+
return {
|
|
105
|
+
success: false,
|
|
106
|
+
error:
|
|
107
|
+
'No authentication method configured. Please provide either databaseApiKey, apiKey + userId, or jwtToken.',
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Validate database API key format
|
|
112
|
+
if (method.type === 'database-api-key') {
|
|
113
|
+
if (!this.config.databaseApiKey?.startsWith('sk_')) {
|
|
114
|
+
return {
|
|
115
|
+
success: false,
|
|
116
|
+
error: 'Database API key must start with "sk_"',
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Validate legacy API key requires user ID
|
|
122
|
+
if (method.type === 'legacy-api-key' && !this.config.userId) {
|
|
123
|
+
return {
|
|
124
|
+
success: false,
|
|
125
|
+
error: 'Legacy API key authentication requires both apiKey and userId',
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
success: true,
|
|
131
|
+
method,
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
private setupInterceptors(): void {
|
|
136
|
+
this.client.interceptors.response.use(
|
|
137
|
+
(response: AxiosResponse) => response,
|
|
138
|
+
error => {
|
|
139
|
+
if (axios.isAxiosError(error)) {
|
|
140
|
+
const authMethod = this.getAuthenticationMethod()
|
|
141
|
+
const status = error.response?.status
|
|
142
|
+
const detail = error.response?.data?.detail
|
|
143
|
+
const message = error.response?.data?.message || error.message
|
|
144
|
+
|
|
145
|
+
// Handle authentication-specific errors
|
|
146
|
+
if (status === 401) {
|
|
147
|
+
if (authMethod?.type === 'database-api-key') {
|
|
148
|
+
throw new Error(
|
|
149
|
+
`Database API key authentication failed: ${this.formatErrorMessage(detail, 'Invalid, expired, or inactive API key')}`
|
|
150
|
+
)
|
|
151
|
+
} else if (authMethod?.type === 'legacy-api-key') {
|
|
152
|
+
throw new Error(
|
|
153
|
+
`Legacy API key authentication failed: ${this.formatErrorMessage(detail, 'Invalid API key or user ID')}`
|
|
154
|
+
)
|
|
155
|
+
} else if (authMethod?.type === 'clerk-jwt') {
|
|
156
|
+
throw new Error(
|
|
157
|
+
`Clerk JWT authentication failed: ${this.formatErrorMessage(detail, 'Invalid or expired token')}`
|
|
158
|
+
)
|
|
159
|
+
} else {
|
|
160
|
+
throw new Error(
|
|
161
|
+
`Authentication failed: ${this.formatErrorMessage(detail || message, 'Authentication failed')}`
|
|
162
|
+
)
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Handle subscription/permission errors
|
|
167
|
+
if (status === 403) {
|
|
168
|
+
throw new Error(
|
|
169
|
+
`Access denied: ${this.formatErrorMessage(detail, 'Insufficient permissions or subscription required')}`
|
|
170
|
+
)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Handle rate limiting
|
|
174
|
+
if (status === 429) {
|
|
175
|
+
throw new Error(
|
|
176
|
+
`Rate limit exceeded: ${this.formatErrorMessage(detail, 'Too many requests. Please try again later.')}`
|
|
177
|
+
)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Handle usage limit errors
|
|
181
|
+
if (detail?.includes('credits') || detail?.includes('usage')) {
|
|
182
|
+
throw new Error(
|
|
183
|
+
`Usage limit exceeded: ${this.formatErrorMessage(detail, 'Usage limit exceeded')}`
|
|
184
|
+
)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Generic API error
|
|
188
|
+
throw new Error(
|
|
189
|
+
`API Error: ${this.formatErrorMessage(detail || message, 'Unknown API error')}`
|
|
190
|
+
)
|
|
191
|
+
}
|
|
192
|
+
throw error
|
|
193
|
+
}
|
|
194
|
+
)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
protected async get<T>(url: string, config?: any): Promise<T> {
|
|
198
|
+
const response = await this.client.get<T>(url, config)
|
|
199
|
+
return response.data
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Safely format error message to avoid [object Object]
|
|
204
|
+
*/
|
|
205
|
+
private formatErrorMessage(value: any, fallback: string): string {
|
|
206
|
+
if (value && typeof value === 'object') {
|
|
207
|
+
return JSON.stringify(value)
|
|
208
|
+
}
|
|
209
|
+
return value || fallback
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
protected async post<T>(url: string, data?: any, config?: any): Promise<T> {
|
|
213
|
+
const response = await this.client.post<T>(url, data, config)
|
|
214
|
+
return response.data
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
protected async put<T>(url: string, data?: any, config?: any): Promise<T> {
|
|
218
|
+
const response = await this.client.put<T>(url, data, config)
|
|
219
|
+
return response.data
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
protected async delete<T>(url: string, config?: any): Promise<T> {
|
|
223
|
+
const response = await this.client.delete<T>(url, config)
|
|
224
|
+
return response.data
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
protected buildUrl(endpoint: string): string {
|
|
228
|
+
return endpoint.startsWith('/') ? endpoint : `/${endpoint}`
|
|
229
|
+
}
|
|
230
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { BaseService } from './base-service'
|