embark-cli 1.1.7
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/.claude/CLAUDE.md +33 -0
- package/.claude/settings.local.json +32 -0
- package/.github/WORKFLOWS.md +147 -0
- package/.github/workflows/ci.yml +49 -0
- package/.github/workflows/publish.yml +109 -0
- package/.idea/embark-remote-mcp.iml +9 -0
- package/.idea/encodings.xml +4 -0
- package/.idea/indexLayout.xml +8 -0
- package/.idea/vcs.xml +6 -0
- package/.mcp.json +14 -0
- package/GIT_DISCOVERY.md +231 -0
- package/INTEGRATION_TESTING.md +243 -0
- package/MULTI_REPOSITORY_SEARCH.md +242 -0
- package/README.md +434 -0
- package/dist/auth/auth-helper.d.ts +3 -0
- package/dist/auth/auth-helper.d.ts.map +1 -0
- package/dist/auth/auth-helper.js +171 -0
- package/dist/auth/auth-helper.js.map +1 -0
- package/dist/auth/index.d.ts +4 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +24 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/jba-login.d.ts +17 -0
- package/dist/auth/jba-login.d.ts.map +1 -0
- package/dist/auth/jba-login.js +345 -0
- package/dist/auth/jba-login.js.map +1 -0
- package/dist/auth/types.d.ts +16 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +3 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/config.d.ts +26 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +54 -0
- package/dist/config.js.map +1 -0
- package/dist/embark-client.d.ts +56 -0
- package/dist/embark-client.d.ts.map +1 -0
- package/dist/embark-client.js +543 -0
- package/dist/embark-client.js.map +1 -0
- package/dist/git-utils.d.ts +47 -0
- package/dist/git-utils.d.ts.map +1 -0
- package/dist/git-utils.js +232 -0
- package/dist/git-utils.js.map +1 -0
- package/dist/handlers.d.ts +80 -0
- package/dist/handlers.d.ts.map +1 -0
- package/dist/handlers.js +301 -0
- package/dist/handlers.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +165 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +4 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +92 -0
- package/dist/logger.js.map +1 -0
- package/dist/stats-server.d.ts +3 -0
- package/dist/stats-server.d.ts.map +1 -0
- package/dist/stats-server.js +623 -0
- package/dist/stats-server.js.map +1 -0
- package/dist/stats.d.ts +118 -0
- package/dist/stats.d.ts.map +1 -0
- package/dist/stats.js +206 -0
- package/dist/stats.js.map +1 -0
- package/dist/tools.d.ts +9 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +62 -0
- package/dist/tools.js.map +1 -0
- package/package.json +47 -0
- package/test-git-discovery.mjs +322 -0
- package/test-multi-repo-filters.mjs +151 -0
- package/test-multiple-roots.mjs +436 -0
- package/test-roots.mjs +306 -0
- package/test-snippet-extraction.mjs +136 -0
- package/watch-logs.sh +78 -0
package/README.md
ADDED
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
# Embark MCP Server
|
|
2
|
+
|
|
3
|
+
A Model Context Protocol (MCP) server that provides a proxy interface to Embark's semantic code search capabilities. This server enables LLM applications to search through code repositories using Embark's powerful indexing and similarity search.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Semantic Code Search**: Search for code using natural language queries through Embark's semantic search engine
|
|
8
|
+
- **Multi-Repository Search**: Search across multiple Git repositories simultaneously with filtering options
|
|
9
|
+
- **Dependency-Based Search**: Search for code that uses specific dependencies and libraries
|
|
10
|
+
- **MCP Protocol Compliance**: Fully compatible with the Model Context Protocol standard
|
|
11
|
+
- **JetBrains Account Authentication**: Secure authentication with Embark's API using JetBrains Account OAuth
|
|
12
|
+
- **Configurable Repositories**: Search across different code repositories with include/exclude filters
|
|
13
|
+
- **Fallback JWT Support**: Supports `GRAZIE_JWT_TOKEN` for non-interactive environments
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
1. Clone the repository:
|
|
18
|
+
```bash
|
|
19
|
+
git clone <repository-url>
|
|
20
|
+
cd embark-mcp
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
2. Install dependencies:
|
|
24
|
+
```bash
|
|
25
|
+
npm install
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
3. Build the project:
|
|
29
|
+
```bash
|
|
30
|
+
npm run build
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Configuration
|
|
34
|
+
|
|
35
|
+
### Authentication
|
|
36
|
+
|
|
37
|
+
This server uses JetBrains Account OAuth for authentication by default.
|
|
38
|
+
|
|
39
|
+
#### First-Time Authorization
|
|
40
|
+
|
|
41
|
+
The OAuth flow is triggered when you first use a search tool. To manually trigger the authorization before using it with Claude Desktop:
|
|
42
|
+
|
|
43
|
+
1. Start the server: `npx embark-mcp`
|
|
44
|
+
2. In another terminal, trigger a search to start the OAuth flow:
|
|
45
|
+
```bash
|
|
46
|
+
echo '{"method": "tools/call", "params": {"name": "semantic_code_search", "arguments": {"text": "test"}}}' | npx embark-mcp
|
|
47
|
+
```
|
|
48
|
+
3. The server will automatically open a browser window to `https://account.jetbrains.com`
|
|
49
|
+
4. Log in with your JetBrains Account credentials
|
|
50
|
+
5. Review and accept the authorization request for Embark access
|
|
51
|
+
6. The browser will redirect to a success page showing "Authorization successful, return to the terminal"
|
|
52
|
+
7. Return to your terminal - the server should now be authenticated
|
|
53
|
+
|
|
54
|
+
The authorization tokens are securely saved in `~/.jbaccount` for future sessions, so you only need to do this once.
|
|
55
|
+
|
|
56
|
+
### Environment Variables
|
|
57
|
+
|
|
58
|
+
#### Authentication
|
|
59
|
+
- `GRAZIE_JWT_TOKEN` (optional): JWT authentication token for Embark API. If provided, it will be used instead of the OAuth flow. This is useful for non-interactive environments.
|
|
60
|
+
- `JETBRAINS_AI_URL` (optional): Base URL for JetBrains AI API (defaults to `https://api.jetbrains.ai`, can be set to `https://api.stgn.jetbrains.ai/` for staging).
|
|
61
|
+
|
|
62
|
+
#### Repository Configuration
|
|
63
|
+
- `REPOSITORY_GIT_REMOTE_URL` (optional): Default repository Git remote URL to search in (can be overridden per search request)
|
|
64
|
+
- `REPOSITORY_ID` (optional): Alternative way to specify default repository (fallback for `REPOSITORY_GIT_REMOTE_URL`)
|
|
65
|
+
- `REPOSITORY_REVISION` (optional): Default repository revision (commit hash, branch name, or tag) to search in. If not set, searches the latest indexed version.
|
|
66
|
+
|
|
67
|
+
#### Multi-Repository Filtering
|
|
68
|
+
- `INCLUDE_REPOSITORY_URLS` (optional): Comma-separated list of Git repository URLs to add to searches. These repositories are searched in addition to any discovered from workspace roots. Useful when your working directory does not contain all repos you want to search. Example: `"https://github.com/owner/repo1.git,https://github.com/owner/repo2.git"`
|
|
69
|
+
- `EXCLUDE_REPOSITORY_URLS` (optional): Comma-separated list of Git repository URLs to exclude from searches. When set, these repositories will be skipped. Example: `"https://github.com/owner/large-repo.git"`
|
|
70
|
+
|
|
71
|
+
#### Other Options
|
|
72
|
+
- `TYPE_TOKEN` (optional): Endpoint type token, either `USER` (default) or `APPLICATION`. When set to `APPLICATION`, the server uses `/application/*` endpoints instead of `/user/*` endpoints.
|
|
73
|
+
- `ENABLE_REMOTE_LOGS` (optional): When set to `true`, includes `logAllowed=true` parameter in Embark API requests to enable remote logging for debugging purposes. Defaults to `false`.
|
|
74
|
+
|
|
75
|
+
**Note**: See [MULTI_REPOSITORY_SEARCH.md](MULTI_REPOSITORY_SEARCH.md) for detailed documentation on multi-repository search and filtering.
|
|
76
|
+
|
|
77
|
+
### Setting up Fallback Authentication (Optional)
|
|
78
|
+
|
|
79
|
+
If you need to use the server in a non-interactive environment, you can use a JWT token.
|
|
80
|
+
|
|
81
|
+
1. Obtain a JWT token from your Embark service administrator
|
|
82
|
+
2. Set the token as an environment variable:
|
|
83
|
+
```bash
|
|
84
|
+
export GRAZIE_JWT_TOKEN="your-jwt-token-here"
|
|
85
|
+
export REPOSITORY_GIT_REMOTE_URL="https://github.com/owner/repo.git" # optional default repository
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Usage
|
|
89
|
+
|
|
90
|
+
### Running the Server
|
|
91
|
+
|
|
92
|
+
#### Using npx (Recommended)
|
|
93
|
+
|
|
94
|
+
You can run the server directly using `npx` without cloning the repository:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
# Optional: set a default repository
|
|
98
|
+
export REPOSITORY_GIT_REMOTE_URL="https://github.com/owner/repo.git"
|
|
99
|
+
|
|
100
|
+
# Run the server and follow the on-screen instructions for OAuth login
|
|
101
|
+
npx embark-mcp
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
If you are using fallback JWT authentication:
|
|
105
|
+
```bash
|
|
106
|
+
# Set your authentication token
|
|
107
|
+
export GRAZIE_JWT_TOKEN="your-jwt-token-here"
|
|
108
|
+
export REPOSITORY_GIT_REMOTE_URL="https://github.com/owner/repo.git" # optional
|
|
109
|
+
|
|
110
|
+
# Run the server
|
|
111
|
+
npx embark-mcp
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
#### Running from Source
|
|
115
|
+
|
|
116
|
+
Start the MCP server:
|
|
117
|
+
```bash
|
|
118
|
+
npm start
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Or for development with auto-reload:
|
|
122
|
+
```bash
|
|
123
|
+
npm run dev
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Integrating with Claude Desktop
|
|
127
|
+
|
|
128
|
+
Add the server to your Claude Desktop configuration file:
|
|
129
|
+
|
|
130
|
+
**macOS/Linux**: `~/.config/claude/claude_desktop_config.json`
|
|
131
|
+
**Windows**: `%APPDATA%/Claude/claude_desktop_config.json`
|
|
132
|
+
|
|
133
|
+
#### Using npx (Recommended)
|
|
134
|
+
|
|
135
|
+
```json
|
|
136
|
+
{
|
|
137
|
+
"mcpServers": {
|
|
138
|
+
"embark-mcp": {
|
|
139
|
+
"command": "npx",
|
|
140
|
+
"args": ["embark-mcp"],
|
|
141
|
+
"env": {
|
|
142
|
+
"JETBRAINS_AI_URL": "https://api.jetbrains.ai",
|
|
143
|
+
"REPOSITORY_GIT_REMOTE_URL": "https://github.com/owner/repo.git",
|
|
144
|
+
"REPOSITORY_REVISION": "main",
|
|
145
|
+
"TYPE_TOKEN": "USER",
|
|
146
|
+
"ENABLE_LOCAL_LOGS": true,
|
|
147
|
+
"ENABLE_REMOTE_LOGS": "false"
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
**Note**: For the OAuth flow to work with Claude Desktop, you must complete the initial authorization process first. Follow the steps in the "First-Time Authorization" section above to trigger the OAuth flow and save the tokens before Claude Desktop attempts to use the server.
|
|
154
|
+
|
|
155
|
+
#### Using Local Installation
|
|
156
|
+
|
|
157
|
+
```json
|
|
158
|
+
{
|
|
159
|
+
"mcpServers": {
|
|
160
|
+
"embark-mcp": {
|
|
161
|
+
"command": "node",
|
|
162
|
+
"args": ["/path/to/embark-mcp/dist/index.js"],
|
|
163
|
+
"env": {
|
|
164
|
+
"REPOSITORY_GIT_REMOTE_URL": "https://github.com/owner/repo.git"
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Available Tools
|
|
172
|
+
|
|
173
|
+
#### `semantic_code_search`
|
|
174
|
+
|
|
175
|
+
Search for code using Embark's semantic search engine.
|
|
176
|
+
|
|
177
|
+
**Parameters:**
|
|
178
|
+
- `text` (required): The text/code to search for. Use detailed, descriptive natural language queries for best results. Examples: "function that validates user email addresses and returns boolean", "error handling middleware for HTTP requests with logging", "React component that renders a modal dialog with close button".
|
|
179
|
+
- `pathFilter` (optional): A specific directory or file to narrow the search. If not provided, the whole codebase is searched. Examples: "path/to/module", "path/to/module/submodule", "path/to/file/example.kt".
|
|
180
|
+
- `repositoryGitRemoteUrl` (optional): The repository Git remote URL to search in (defaults to `REPOSITORY_GIT_REMOTE_URL` environment variable)
|
|
181
|
+
|
|
182
|
+
**Example:**
|
|
183
|
+
```
|
|
184
|
+
{'text': 'Search for "authentication middleware" in the codebase', 'pathFilter': 'src'}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
**Response Format:**
|
|
188
|
+
```
|
|
189
|
+
Found 10 results for "authentication middleware" in repository "https://github.com/owner/repo.git" (revision: "5e7f1ab4bf58e473e5d7f878eb2b499d7deabd29", pathFilter: "src")
|
|
190
|
+
|
|
191
|
+
1. File=src/middleware/auth.js, offset=120:340, similarity=0.892, type=FUNCTION
|
|
192
|
+
Snippet:
|
|
193
|
+
"""
|
|
194
|
+
export function authMiddleware(req, res, next) {
|
|
195
|
+
const token = req.headers['authorization'];
|
|
196
|
+
if (!token) return res.status(401).send('Missing token');
|
|
197
|
+
try {
|
|
198
|
+
req.user = verifyToken(token);
|
|
199
|
+
next();
|
|
200
|
+
} catch (err) {
|
|
201
|
+
res.status(403).send('Invalid token');
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
"""
|
|
205
|
+
2. File=src/security/middleware.ts, offset=45:180, similarity=0.834, type=CLASS
|
|
206
|
+
Snippet:
|
|
207
|
+
"""
|
|
208
|
+
export class SecurityMiddleware {
|
|
209
|
+
constructor(private readonly secret: string) {}
|
|
210
|
+
handle(req: Request, res: Response, next: NextFunction) {
|
|
211
|
+
if (!req.headers['x-api-key']) {
|
|
212
|
+
res.status(401).json({ error: 'Unauthorized' });
|
|
213
|
+
} else {
|
|
214
|
+
next();
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
"""
|
|
219
|
+
3. File=src/routes/auth.js, offset=890:1120, similarity=0.776, type=FUNCTION
|
|
220
|
+
Snippet:
|
|
221
|
+
"""
|
|
222
|
+
router.post('/login', async (req, res) => {
|
|
223
|
+
const { username, password } = req.body;
|
|
224
|
+
const token = await authenticate(username, password);
|
|
225
|
+
res.json({ token });
|
|
226
|
+
});
|
|
227
|
+
"""
|
|
228
|
+
...
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
#### `search_in_dependencies`
|
|
232
|
+
|
|
233
|
+
Search for code that uses specific dependencies using Embark's semantic search.
|
|
234
|
+
|
|
235
|
+
**Parameters:**
|
|
236
|
+
- `text` (required): The search query describing what to look for in relation to dependencies
|
|
237
|
+
- `dependencies` (required): Array of dependency objects with the following structure:
|
|
238
|
+
- `dependency` (required): The dependency name
|
|
239
|
+
- `version` (required): The dependency version
|
|
240
|
+
|
|
241
|
+
**Example:**
|
|
242
|
+
```
|
|
243
|
+
Search for code that uses React hooks with specific dependencies
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
**Dependencies Parameter Example:**
|
|
247
|
+
```json
|
|
248
|
+
[
|
|
249
|
+
{"dependency": "react", "version": "18.0.0"},
|
|
250
|
+
{"dependency": "react-hooks", "version": "1.0.0"}
|
|
251
|
+
]
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
**Response Format:**
|
|
255
|
+
```
|
|
256
|
+
Found 3 results for "React hooks usage" with dependencies [react:18.0.0, react-hooks:1.0.0] in repository "https://github.com/owner/repo.git":
|
|
257
|
+
|
|
258
|
+
1. File=src/components/UserProfile.tsx, offset=45:180, similarity=0.891, type=FUNCTION
|
|
259
|
+
2. File=src/hooks/useAuth.ts, offset=12:95, similarity=0.834, type=FUNCTION
|
|
260
|
+
3. File=src/pages/Dashboard.tsx, offset=200:350, similarity=0.776, type=FUNCTION
|
|
261
|
+
|
|
262
|
+
Timings: search: 120ms, total: 150ms
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## API Reference
|
|
266
|
+
|
|
267
|
+
### Embark API Integration
|
|
268
|
+
|
|
269
|
+
This server integrates with Embark's REST API endpoints:
|
|
270
|
+
|
|
271
|
+
#### Semantic Code Search
|
|
272
|
+
- **Endpoint**: `/user/v5/indexing/search` (or `/application/v5/indexing/search` when `TYPE_TOKEN=APPLICATION`)
|
|
273
|
+
- **Method**: POST
|
|
274
|
+
- **Authentication**: Bearer token from JetBrains Account OAuth or `GRAZIE_JWT_TOKEN` via `grazie-authenticate-jwt` header
|
|
275
|
+
- **Request Body**:
|
|
276
|
+
```json
|
|
277
|
+
{
|
|
278
|
+
"text": "search query",
|
|
279
|
+
"repository": "https://github.com/owner/repo.git",
|
|
280
|
+
"revision": "main", // optional: commit hash, branch name, or tag
|
|
281
|
+
"pathFilter": "dir" // optional: a file or a dir
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
#### Dependencies Search
|
|
286
|
+
- **Endpoint**: `/search-dependencies`
|
|
287
|
+
- **Method**: POST
|
|
288
|
+
- **Authentication**: Bearer token from JetBrains Account OAuth or `GRAZIE_JWT_TOKEN` via `grazie-authenticate-jwt` header
|
|
289
|
+
- **Request Body**:
|
|
290
|
+
```json
|
|
291
|
+
{
|
|
292
|
+
"index": "ProductionIndices.CodeBlocks",
|
|
293
|
+
"text": "search query",
|
|
294
|
+
"dependencies": [
|
|
295
|
+
{"dependency": "react", "version": "18.0.0"}
|
|
296
|
+
],
|
|
297
|
+
"maxResults": 10,
|
|
298
|
+
"minScore": 0.0,
|
|
299
|
+
"logAllowed": false,
|
|
300
|
+
"searchPipelineConfig": "SearchPipelineConfig.SearchOnly"
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### Response Structure
|
|
305
|
+
|
|
306
|
+
#### Semantic Code Search Response
|
|
307
|
+
|
|
308
|
+
Embark returns search results with the following structure:
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
interface SearchResponse {
|
|
312
|
+
searchResponse: {
|
|
313
|
+
res: Array<{
|
|
314
|
+
scoredText: {
|
|
315
|
+
text: string;
|
|
316
|
+
similarity: number;
|
|
317
|
+
};
|
|
318
|
+
sourcePosition: {
|
|
319
|
+
relativePath: string;
|
|
320
|
+
startOffset: number;
|
|
321
|
+
endOffset: number;
|
|
322
|
+
};
|
|
323
|
+
indexItemType: string;
|
|
324
|
+
}>;
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
#### Dependencies Search Response
|
|
330
|
+
|
|
331
|
+
The dependencies search endpoint returns results with timing information:
|
|
332
|
+
|
|
333
|
+
```typescript
|
|
334
|
+
interface DependenciesSearchResponse {
|
|
335
|
+
results: Array<{
|
|
336
|
+
searchResult: {
|
|
337
|
+
sourcePosition: {
|
|
338
|
+
relativePath: string;
|
|
339
|
+
startOffset: number;
|
|
340
|
+
endOffset: number;
|
|
341
|
+
};
|
|
342
|
+
indexItemType: string;
|
|
343
|
+
similarity: number;
|
|
344
|
+
};
|
|
345
|
+
content: string;
|
|
346
|
+
}>;
|
|
347
|
+
timings: {
|
|
348
|
+
[key: string]: number; // timing in milliseconds
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
## Development
|
|
354
|
+
|
|
355
|
+
### Building
|
|
356
|
+
|
|
357
|
+
```bash
|
|
358
|
+
npm run build
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### Development Mode
|
|
362
|
+
|
|
363
|
+
```bash
|
|
364
|
+
npm run dev
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### Watch Mode
|
|
368
|
+
|
|
369
|
+
```bash
|
|
370
|
+
npm run watch
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
## Troubleshooting
|
|
374
|
+
|
|
375
|
+
### Common Issues
|
|
376
|
+
|
|
377
|
+
1. **OAuth Error**:
|
|
378
|
+
- Ensure your browser is available to complete the login flow.
|
|
379
|
+
- If behind a firewall, ensure that `https://www.jetbrains.com` and `http://localhost:62345` (or a nearby port) are accessible.
|
|
380
|
+
- If the browser doesn't open automatically, copy the URL from the terminal and open it manually.
|
|
381
|
+
2. **Authentication Error (JWT)**: Ensure your `GRAZIE_JWT_TOKEN` is valid and not expired. This is only relevant if you are using fallback authentication.
|
|
382
|
+
3. **Connection Error**: Check that the `JETBRAINS_AI_URL` is correct and accessible.
|
|
383
|
+
4. **No Results**: Verify the repository name exists and is accessible with your token.
|
|
384
|
+
|
|
385
|
+
### Error Messages
|
|
386
|
+
|
|
387
|
+
- `Failed to get authorization code`: The OAuth flow was not completed successfully.
|
|
388
|
+
- `Embark API error (401)`: Invalid or expired token (either from OAuth or JWT).
|
|
389
|
+
- `Embark API error (404)`: Repository not found or not accessible.
|
|
390
|
+
|
|
391
|
+
## License
|
|
392
|
+
|
|
393
|
+
MIT
|
|
394
|
+
|
|
395
|
+
## Contributing
|
|
396
|
+
|
|
397
|
+
1. Fork the repository
|
|
398
|
+
2. Create a feature branch
|
|
399
|
+
3. Make your changes
|
|
400
|
+
4. Submit a pull request
|
|
401
|
+
|
|
402
|
+
## Support
|
|
403
|
+
|
|
404
|
+
For issues related to:
|
|
405
|
+
- **This MCP server**: Open an issue in this repository
|
|
406
|
+
- **Embark API**: Contact your Embark service administrator
|
|
407
|
+
- **Model Context Protocol**: See the [official MCP documentation](https://modelcontextprotocol.io/)
|
|
408
|
+
## Usage Analytics & Dashboard
|
|
409
|
+
|
|
410
|
+
The MCP server records structured JSON stats for each server initialization, Embark API call, and search invocation. Files are grouped per calendar day and stored under `~/.embark/stats/YYYY-MM-DD.json`, making it easy to audit historical usage or inspect failure cases.
|
|
411
|
+
|
|
412
|
+
### Launching the Local Dashboard
|
|
413
|
+
|
|
414
|
+
For a one-liner that starts the dashboard server and opens it in your default browser:
|
|
415
|
+
|
|
416
|
+
```bash
|
|
417
|
+
npx embark-mcp stats --port 43210
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
If you prefer to start the server without opening a browser automatically, use:
|
|
421
|
+
|
|
422
|
+
```bash
|
|
423
|
+
npx embark-mcp stats-server --port 43210
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
The dashboard renders:
|
|
427
|
+
|
|
428
|
+
- Searches per day (semantic, dependency, multi-repo summaries)
|
|
429
|
+
- Estimated token usage per day
|
|
430
|
+
- Average response times
|
|
431
|
+
- Counts of error HTTP status codes
|
|
432
|
+
- A rolling feed of recent events for quick debugging
|
|
433
|
+
|
|
434
|
+
Data refreshes automatically every 15 seconds and never leaves your machine because everything is served directly from the local `~/.embark/stats` directory.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-helper.d.ts","sourceRoot":"","sources":["../../src/auth/auth-helper.ts"],"names":[],"mappings":"AA0IA,wBAAsB,YAAY,CAAC,YAAY,GAAE,OAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CA2CjF;AAED,wBAAgB,0BAA0B,IAAI,OAAO,CAWpD"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getAuthToken = getAuthToken;
|
|
7
|
+
exports.areJbaCredentialsAvailable = areJbaCredentialsAvailable;
|
|
8
|
+
const axios_1 = __importDefault(require("axios"));
|
|
9
|
+
const jba_login_js_1 = require("./jba-login.js");
|
|
10
|
+
const logger_js_1 = require("../logger.js");
|
|
11
|
+
const os_1 = require("os");
|
|
12
|
+
const path_1 = require("path");
|
|
13
|
+
const fs_1 = require("fs");
|
|
14
|
+
const GRAZIE_JWT_TOKEN = process.env.GRAZIE_JWT_TOKEN;
|
|
15
|
+
const JETBRAINS_AI_URL = process.env.JETBRAINS_AI_URL || 'https://api.jetbrains.ai';
|
|
16
|
+
const EMBARK_DIR = (0, path_1.join)((0, os_1.homedir)(), '.embark');
|
|
17
|
+
const LICENSES_CACHE_PATH = (0, path_1.join)(EMBARK_DIR, 'licenses.json');
|
|
18
|
+
function readLicensesFromCache() {
|
|
19
|
+
if ((0, fs_1.existsSync)(LICENSES_CACHE_PATH)) {
|
|
20
|
+
try {
|
|
21
|
+
const data = (0, fs_1.readFileSync)(LICENSES_CACHE_PATH, 'utf-8');
|
|
22
|
+
const licenses = JSON.parse(data);
|
|
23
|
+
(0, logger_js_1.logToFile)('info', '[AUTH] Licenses loaded from cache.');
|
|
24
|
+
return licenses;
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
(0, logger_js_1.logToFile)('error', '[AUTH] Failed to read or parse licenses cache.', { error });
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
function writeLicensesToCache(licenses) {
|
|
34
|
+
try {
|
|
35
|
+
if (!(0, fs_1.existsSync)(EMBARK_DIR)) {
|
|
36
|
+
(0, fs_1.mkdirSync)(EMBARK_DIR, { recursive: true });
|
|
37
|
+
}
|
|
38
|
+
(0, fs_1.writeFileSync)(LICENSES_CACHE_PATH, JSON.stringify(licenses, null, 2));
|
|
39
|
+
(0, logger_js_1.logToFile)('info', '[AUTH] Licenses saved to cache.');
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
(0, logger_js_1.logToFile)('error', '[AUTH] Failed to write licenses to cache.', { error });
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
async function fetchLicenses(jbaToken) {
|
|
46
|
+
(0, logger_js_1.logToFile)('info', '[AUTH] Fetching licenses from JetBrains Account');
|
|
47
|
+
try {
|
|
48
|
+
const response = await axios_1.default.get('https://account.jetbrains.com/services/account/assetsByIdToken', {
|
|
49
|
+
headers: {
|
|
50
|
+
'Authorization': `Bearer ${jbaToken}`
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
const assets = response.data.assets;
|
|
54
|
+
if (!assets || assets.length === 0) {
|
|
55
|
+
(0, logger_js_1.logToFile)('warn', '[AUTH] No assets found for the user.');
|
|
56
|
+
throw new Error('No assets found for your JetBrains Account.');
|
|
57
|
+
}
|
|
58
|
+
(0, logger_js_1.logToFile)('info', `[AUTH] Found ${assets.length} assets.`);
|
|
59
|
+
writeLicensesToCache(assets);
|
|
60
|
+
return assets;
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
(0, logger_js_1.logToFile)('error', '[AUTH] Failed to fetch licenses', { error });
|
|
64
|
+
if (axios_1.default.isAxiosError(error)) {
|
|
65
|
+
const status = error.response?.status;
|
|
66
|
+
const statusText = error.response?.statusText;
|
|
67
|
+
const responseData = error.response?.data;
|
|
68
|
+
(0, logger_js_1.logToFile)('error', 'JetBrains Account API error details', { status, statusText, responseData });
|
|
69
|
+
throw new Error(`JetBrains Account API error for licenses (${status}): ${statusText} - ${JSON.stringify(responseData)}`);
|
|
70
|
+
}
|
|
71
|
+
throw error;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async function getLicenseId(jbaLogin) {
|
|
75
|
+
const idToken = await jbaLogin.getValidIdToken();
|
|
76
|
+
let licenses = readLicensesFromCache();
|
|
77
|
+
if (!licenses) {
|
|
78
|
+
licenses = await fetchLicenses(idToken);
|
|
79
|
+
}
|
|
80
|
+
const validLicense = licenses.find(l => !l.suspended && !l.cancelled);
|
|
81
|
+
if (!validLicense || !validLicense.licenseId) {
|
|
82
|
+
throw new Error('No valid license found.');
|
|
83
|
+
}
|
|
84
|
+
(0, logger_js_1.logToFile)('info', '[AUTH] Selected license', { licenseId: validLicense.licenseId });
|
|
85
|
+
return validLicense.licenseId;
|
|
86
|
+
}
|
|
87
|
+
async function exchangeJbaForGrazieToken(jbaToken, licenseId) {
|
|
88
|
+
(0, logger_js_1.logToFile)('info', '[AUTH] Exchanging JBA token for Grazie token', { licenseId });
|
|
89
|
+
try {
|
|
90
|
+
const response = await axios_1.default.post(`${JETBRAINS_AI_URL}/auth/jetbrains-jwt/provide-access/license/v2`, {
|
|
91
|
+
licenseId: licenseId,
|
|
92
|
+
}, {
|
|
93
|
+
headers: {
|
|
94
|
+
'Authorization': `Bearer ${jbaToken}`,
|
|
95
|
+
'Content-Type': 'application/json',
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
const { token } = response.data;
|
|
99
|
+
if (!token) {
|
|
100
|
+
(0, logger_js_1.logToFile)('error', '[AUTH] Grazie token not found in response', { responseData: response.data });
|
|
101
|
+
throw new Error('Failed to get Grazie token');
|
|
102
|
+
}
|
|
103
|
+
(0, logger_js_1.logToFile)('info', '[AUTH] Successfully exchanged JBA token for Grazie token');
|
|
104
|
+
return token;
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
(0, logger_js_1.logToFile)('error', '[AUTH] Failed to exchange JBA token for Grazie token', { error });
|
|
108
|
+
if (axios_1.default.isAxiosError(error)) {
|
|
109
|
+
const status = error.response?.status;
|
|
110
|
+
const statusText = error.response?.statusText;
|
|
111
|
+
const responseData = error.response?.data;
|
|
112
|
+
(0, logger_js_1.logToFile)('error', 'Embark API error details', { status, statusText, responseData });
|
|
113
|
+
throw new Error(`Embark API error for token exchange (${status}): ${statusText} - ${JSON.stringify(responseData)}`);
|
|
114
|
+
}
|
|
115
|
+
throw error;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
async function getAuthToken(forceRefresh = false) {
|
|
119
|
+
(0, logger_js_1.logToFile)('info', '[AUTH] Getting auth token', { forceRefresh });
|
|
120
|
+
if (GRAZIE_JWT_TOKEN && !forceRefresh) {
|
|
121
|
+
(0, logger_js_1.logToFile)('info', '[AUTH] Using GRAZIE_JWT_TOKEN from environment');
|
|
122
|
+
return GRAZIE_JWT_TOKEN;
|
|
123
|
+
}
|
|
124
|
+
(0, logger_js_1.logToFile)('info', '[AUTH] Using JetBrains Account OAuth flow', { forceRefresh });
|
|
125
|
+
try {
|
|
126
|
+
const jbaLogin = new jba_login_js_1.JBALogin();
|
|
127
|
+
const licenseId = await getLicenseId(jbaLogin);
|
|
128
|
+
let idToken;
|
|
129
|
+
if (forceRefresh) {
|
|
130
|
+
(0, logger_js_1.logToFile)('info', '[AUTH] Force refreshing JBA token');
|
|
131
|
+
// Force refresh by using the refresh token
|
|
132
|
+
let account = jbaLogin.readAccount();
|
|
133
|
+
if (!account) {
|
|
134
|
+
(0, logger_js_1.logToFile)('info', '[AUTH] No account found for force refresh, getting new token');
|
|
135
|
+
account = await jbaLogin.login();
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
(0, logger_js_1.logToFile)('info', '[AUTH] Forcing token refresh using refresh token');
|
|
139
|
+
account = await jbaLogin.refreshToken(account);
|
|
140
|
+
}
|
|
141
|
+
if (!account.idToken) {
|
|
142
|
+
throw new Error('No ID token found after forced refresh');
|
|
143
|
+
}
|
|
144
|
+
idToken = account.idToken;
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
idToken = await jbaLogin.getValidIdToken();
|
|
148
|
+
}
|
|
149
|
+
(0, logger_js_1.logToFile)('info', '[AUTH] Using ID token to exchange for Grazie token');
|
|
150
|
+
const grazieToken = await exchangeJbaForGrazieToken(idToken, licenseId);
|
|
151
|
+
return grazieToken;
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
(0, logger_js_1.logToFile)('error', '[AUTH] Failed to get auth token', { error, forceRefresh });
|
|
155
|
+
throw error;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
function areJbaCredentialsAvailable() {
|
|
159
|
+
try {
|
|
160
|
+
const jbaLogin = new jba_login_js_1.JBALogin();
|
|
161
|
+
const account = jbaLogin.readAccount();
|
|
162
|
+
const available = account !== null;
|
|
163
|
+
(0, logger_js_1.logToFile)('info', `[AUTH] JBA credentials available: ${available}`);
|
|
164
|
+
return available;
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
(0, logger_js_1.logToFile)('error', '[AUTH] Failed to check for JBA credentials', { error });
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=auth-helper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-helper.js","sourceRoot":"","sources":["../../src/auth/auth-helper.ts"],"names":[],"mappings":";;;;;AA0IA,oCA2CC;AAED,gEAWC;AAlMD,kDAA0B;AAC1B,iDAA0C;AAC1C,4CAAyC;AACzC,2BAA6B;AAC7B,+BAA4B;AAC5B,2BAAwE;AAExE,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;AACtD,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,0BAA0B,CAAC;AAEpF,MAAM,UAAU,GAAG,IAAA,WAAI,EAAC,IAAA,YAAO,GAAE,EAAE,SAAS,CAAC,CAAC;AAC9C,MAAM,mBAAmB,GAAG,IAAA,WAAI,EAAC,UAAU,EAAE,eAAe,CAAC,CAAC;AAa9D,SAAS,qBAAqB;IAC1B,IAAI,IAAA,eAAU,EAAC,mBAAmB,CAAC,EAAE,CAAC;QAClC,IAAI,CAAC;YACD,MAAM,IAAI,GAAG,IAAA,iBAAY,EAAC,mBAAmB,EAAE,OAAO,CAAC,CAAC;YACxD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAClC,IAAA,qBAAS,EAAC,MAAM,EAAE,oCAAoC,CAAC,CAAC;YACxD,OAAO,QAAQ,CAAC;QACpB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,IAAA,qBAAS,EAAC,OAAO,EAAE,gDAAgD,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;YAChF,OAAO,IAAI,CAAC;QAChB,CAAC;IACL,CAAC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC;AAED,SAAS,oBAAoB,CAAC,QAAiB;IAC3C,IAAI,CAAC;QACD,IAAI,CAAC,IAAA,eAAU,EAAC,UAAU,CAAC,EAAE,CAAC;YAC1B,IAAA,cAAS,EAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/C,CAAC;QACD,IAAA,kBAAa,EAAC,mBAAmB,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACtE,IAAA,qBAAS,EAAC,MAAM,EAAE,iCAAiC,CAAC,CAAC;IACzD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,IAAA,qBAAS,EAAC,OAAO,EAAE,2CAA2C,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/E,CAAC;AACL,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,QAAgB;IACzC,IAAA,qBAAS,EAAC,MAAM,EAAE,iDAAiD,CAAC,CAAC;IACrE,IAAI,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,eAAK,CAAC,GAAG,CAAiB,gEAAgE,EAAE;YAC/G,OAAO,EAAE;gBACL,eAAe,EAAE,UAAU,QAAQ,EAAE;aACxC;SACJ,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;QACpC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjC,IAAA,qBAAS,EAAC,MAAM,EAAE,sCAAsC,CAAC,CAAC;YAC1D,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACnE,CAAC;QAED,IAAA,qBAAS,EAAC,MAAM,EAAE,gBAAgB,MAAM,CAAC,MAAM,UAAU,CAAC,CAAC;QAC3D,oBAAoB,CAAC,MAAM,CAAC,CAAC;QAC7B,OAAO,MAAM,CAAC;IAElB,CAAC;IAAC,OAAM,KAAK,EAAE,CAAC;QACZ,IAAA,qBAAS,EAAC,OAAO,EAAE,iCAAiC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QACjE,IAAI,eAAK,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5B,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC;YACtC,MAAM,UAAU,GAAG,KAAK,CAAC,QAAQ,EAAE,UAAU,CAAC;YAC9C,MAAM,YAAY,GAAG,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC;YAC1C,IAAA,qBAAS,EAAC,OAAO,EAAE,qCAAqC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,CAAC,CAAC;YAChG,MAAM,IAAI,KAAK,CAAC,6CAA6C,MAAM,MAAM,UAAU,MAAM,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QAC7H,CAAC;QACD,MAAM,KAAK,CAAC;IAChB,CAAC;AACL,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,QAAkB;IAC1C,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,eAAe,EAAE,CAAC;IACjD,IAAI,QAAQ,GAAG,qBAAqB,EAAE,CAAC;IACvC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACZ,QAAQ,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC;IAC5C,CAAC;IAED,MAAM,YAAY,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAEtE,IAAI,CAAC,YAAY,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC/C,CAAC;IAED,IAAA,qBAAS,EAAC,MAAM,EAAE,yBAAyB,EAAE,EAAE,SAAS,EAAE,YAAY,CAAC,SAAS,EAAE,CAAC,CAAC;IACpF,OAAO,YAAY,CAAC,SAAS,CAAC;AAClC,CAAC;AAED,KAAK,UAAU,yBAAyB,CAAC,QAAgB,EAAE,SAAiB;IAC1E,IAAA,qBAAS,EAAC,MAAM,EAAE,8CAA8C,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;IAEjF,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,eAAK,CAAC,IAAI,CAC/B,GAAG,gBAAgB,+CAA+C,EAClE;YACE,SAAS,EAAE,SAAS;SACrB,EACD;YACE,OAAO,EAAE;gBACP,eAAe,EAAE,UAAU,QAAQ,EAAE;gBACrC,cAAc,EAAE,kBAAkB;aACnC;SACF,CACF,CAAC;QAEF,MAAM,EAAE,KAAK,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC;QAChC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,IAAA,qBAAS,EAAC,OAAO,EAAE,2CAA2C,EAAE,EAAE,YAAY,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;YACjG,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAChD,CAAC;QAED,IAAA,qBAAS,EAAC,MAAM,EAAE,0DAA0D,CAAC,CAAC;QAC9E,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAA,qBAAS,EAAC,OAAO,EAAE,sDAAsD,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QACtF,IAAI,eAAK,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5B,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC;YACtC,MAAM,UAAU,GAAG,KAAK,CAAC,QAAQ,EAAE,UAAU,CAAC;YAC9C,MAAM,YAAY,GAAG,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC;YAC1C,IAAA,qBAAS,EAAC,OAAO,EAAE,0BAA0B,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,CAAC,CAAC;YACrF,MAAM,IAAI,KAAK,CAAC,wCAAwC,MAAM,MAAM,UAAU,MAAM,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QACxH,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,YAAY,CAAC,eAAwB,KAAK;IAC9D,IAAA,qBAAS,EAAC,MAAM,EAAE,2BAA2B,EAAE,EAAE,YAAY,EAAE,CAAC,CAAC;IAEjE,IAAI,gBAAgB,IAAI,CAAC,YAAY,EAAE,CAAC;QACtC,IAAA,qBAAS,EAAC,MAAM,EAAE,gDAAgD,CAAC,CAAC;QACpE,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAED,IAAA,qBAAS,EAAC,MAAM,EAAE,2CAA2C,EAAE,EAAE,YAAY,EAAE,CAAC,CAAC;IACjF,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI,uBAAQ,EAAE,CAAC;QAEhC,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,QAAQ,CAAC,CAAC;QAE/C,IAAI,OAAe,CAAC;QACpB,IAAI,YAAY,EAAE,CAAC;YACjB,IAAA,qBAAS,EAAC,MAAM,EAAE,mCAAmC,CAAC,CAAC;YACvD,2CAA2C;YAC3C,IAAI,OAAO,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;YACrC,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,IAAA,qBAAS,EAAC,MAAM,EAAE,8DAA8D,CAAC,CAAC;gBAClF,OAAO,GAAG,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC;YACnC,CAAC;iBAAM,CAAC;gBACN,IAAA,qBAAS,EAAC,MAAM,EAAE,kDAAkD,CAAC,CAAC;gBACtE,OAAO,GAAG,MAAM,QAAQ,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;YACjD,CAAC;YAED,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;gBACrB,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;YAC5D,CAAC;YACD,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAC5B,CAAC;aAAM,CAAC;YACN,OAAO,GAAG,MAAM,QAAQ,CAAC,eAAe,EAAE,CAAC;QAC7C,CAAC;QAED,IAAA,qBAAS,EAAC,MAAM,EAAE,oDAAoD,CAAC,CAAC;QACxE,MAAM,WAAW,GAAG,MAAM,yBAAyB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAExE,OAAO,WAAW,CAAC;IACrB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAA,qBAAS,EAAC,OAAO,EAAE,iCAAiC,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;QAC/E,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAgB,0BAA0B;IACxC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI,uBAAQ,EAAE,CAAC;QAChC,MAAM,OAAO,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;QACvC,MAAM,SAAS,GAAG,OAAO,KAAK,IAAI,CAAC;QACnC,IAAA,qBAAS,EAAC,MAAM,EAAE,qCAAqC,SAAS,EAAE,CAAC,CAAC;QACpE,OAAO,SAAS,CAAC;IACnB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAA,qBAAS,EAAC,OAAO,EAAE,4CAA4C,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAC5E,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAC5E,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.JBALogin = exports.areJbaCredentialsAvailable = exports.getAuthToken = void 0;
|
|
18
|
+
__exportStar(require("./types.js"), exports);
|
|
19
|
+
var auth_helper_js_1 = require("./auth-helper.js");
|
|
20
|
+
Object.defineProperty(exports, "getAuthToken", { enumerable: true, get: function () { return auth_helper_js_1.getAuthToken; } });
|
|
21
|
+
Object.defineProperty(exports, "areJbaCredentialsAvailable", { enumerable: true, get: function () { return auth_helper_js_1.areJbaCredentialsAvailable; } });
|
|
22
|
+
var jba_login_js_1 = require("./jba-login.js");
|
|
23
|
+
Object.defineProperty(exports, "JBALogin", { enumerable: true, get: function () { return jba_login_js_1.JBALogin; } });
|
|
24
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,6CAA2B;AAC3B,mDAA4E;AAAnE,8GAAA,YAAY,OAAA;AAAE,4HAAA,0BAA0B,OAAA;AACjD,+CAA0C;AAAjC,wGAAA,QAAQ,OAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { JbAccount, OAuthConfig } from './types.js';
|
|
2
|
+
export declare class JBALogin {
|
|
3
|
+
private readonly accountFilePath;
|
|
4
|
+
constructor();
|
|
5
|
+
loadConfig(): Promise<OAuthConfig>;
|
|
6
|
+
private sendPostRequest;
|
|
7
|
+
private openBrowser;
|
|
8
|
+
login(): Promise<JbAccount>;
|
|
9
|
+
private exchangeCodeForToken;
|
|
10
|
+
refreshToken(account: JbAccount): Promise<JbAccount>;
|
|
11
|
+
saveAccount(account: JbAccount): void;
|
|
12
|
+
readAccount(): JbAccount | null;
|
|
13
|
+
isTokenExpired(account: JbAccount): boolean;
|
|
14
|
+
getValidToken(): Promise<string>;
|
|
15
|
+
getValidIdToken(): Promise<string>;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=jba-login.d.ts.map
|