@robosystems/client 0.1.20 → 0.1.22
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/LICENSE +1 -1
- package/README.md +10 -423
- package/bin/create-feature +7 -17
- package/extensions/CopyClient.d.ts +1 -0
- package/extensions/CopyClient.js +3 -0
- package/extensions/CopyClient.ts +5 -0
- package/extensions/OperationClient.d.ts +1 -0
- package/extensions/OperationClient.ts +2 -0
- package/extensions/QueryClient.d.ts +1 -0
- package/extensions/QueryClient.js +1 -0
- package/extensions/QueryClient.ts +3 -0
- package/extensions/SSEClient.d.ts +14 -0
- package/extensions/SSEClient.js +7 -1
- package/extensions/SSEClient.ts +22 -1
- package/extensions/config.d.ts +25 -0
- package/extensions/config.js +78 -0
- package/extensions/config.ts +84 -0
- package/extensions/hooks.js +16 -0
- package/extensions/hooks.ts +27 -1
- package/extensions/index.d.ts +2 -0
- package/extensions/index.js +14 -0
- package/extensions/index.ts +28 -1
- package/package.json +2 -2
- package/sdk/sdk.gen.d.ts +40 -15
- package/sdk/sdk.gen.js +100 -33
- package/sdk/sdk.gen.ts +99 -32
- package/sdk/types.gen.d.ts +748 -100
- package/sdk/types.gen.ts +785 -108
- package/sdk-extensions/CopyClient.d.ts +1 -0
- package/sdk-extensions/CopyClient.js +3 -0
- package/sdk-extensions/CopyClient.ts +5 -0
- package/sdk-extensions/OperationClient.d.ts +1 -0
- package/sdk-extensions/OperationClient.ts +2 -0
- package/sdk-extensions/QueryClient.d.ts +1 -0
- package/sdk-extensions/QueryClient.js +1 -0
- package/sdk-extensions/QueryClient.ts +3 -0
- package/sdk-extensions/SSEClient.d.ts +14 -0
- package/sdk-extensions/SSEClient.js +7 -1
- package/sdk-extensions/SSEClient.ts +22 -1
- package/sdk-extensions/config.d.ts +25 -0
- package/sdk-extensions/config.js +78 -0
- package/sdk-extensions/config.ts +84 -0
- package/sdk-extensions/hooks.js +16 -0
- package/sdk-extensions/hooks.ts +27 -1
- package/sdk-extensions/index.d.ts +2 -0
- package/sdk-extensions/index.js +14 -0
- package/sdk-extensions/index.ts +28 -1
- package/sdk.gen.d.ts +40 -15
- package/sdk.gen.js +100 -33
- package/sdk.gen.ts +99 -32
- package/types.gen.d.ts +748 -100
- package/types.gen.ts +785 -108
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -3,451 +3,38 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/@robosystems/client)
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
5
|
|
|
6
|
-
Official TypeScript Client for the RoboSystems Financial Knowledge Graph API. Access comprehensive financial data including accounting
|
|
6
|
+
Official TypeScript Client for the RoboSystems Financial Knowledge Graph API. Access comprehensive financial data including accounting transactions, financial reports, and advanced graph analytics through a type-safe, modern TypeScript interface.
|
|
7
7
|
|
|
8
8
|
## Features
|
|
9
9
|
|
|
10
10
|
- **Type-safe API client** with full TypeScript types
|
|
11
|
-
- **Auto-generated from OpenAPI** for always up-to-date types
|
|
12
11
|
- **Browser & Node.js support** with different auth strategies
|
|
13
12
|
- **React hooks** for seamless UI integration
|
|
14
|
-
- **
|
|
15
|
-
- **
|
|
16
|
-
- **Financial AI Agent** integration
|
|
13
|
+
- **Streaming support** for memory-efficient processing of large result sets
|
|
14
|
+
- **Financial AI Agent** integration for natural language queries
|
|
17
15
|
- **Comprehensive error handling** with typed errors
|
|
18
16
|
|
|
19
17
|
## Installation
|
|
20
18
|
|
|
21
19
|
```bash
|
|
22
20
|
npm install @robosystems/client
|
|
23
|
-
# or
|
|
24
|
-
yarn add @robosystems/client
|
|
25
|
-
# or
|
|
26
|
-
pnpm add @robosystems/client
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
## Quick Start
|
|
30
|
-
|
|
31
|
-
### Browser Usage (with cookies)
|
|
32
|
-
|
|
33
|
-
```typescript
|
|
34
|
-
import { client, getUserMe, listCompanies, executeCypherQuery } from '@robosystems/client'
|
|
35
|
-
|
|
36
|
-
// Configure the client
|
|
37
|
-
client.setConfig({
|
|
38
|
-
baseUrl: 'https://api.robosystems.ai',
|
|
39
|
-
credentials: 'include',
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
// Use with cookie-based authentication (browser)
|
|
43
|
-
const { data: user, error } = await getCurrentUser()
|
|
44
|
-
if (user) {
|
|
45
|
-
console.log('Logged in as:', user.email)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// List companies in a graph
|
|
49
|
-
const { data: companies } = await listCompanies({
|
|
50
|
-
path: { graph_id: 'your-graph-id' },
|
|
51
|
-
query: { limit: 10 },
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
// Execute a Cypher query
|
|
55
|
-
const { data: result } = await executeCypherQuery({
|
|
56
|
-
path: { graph_id: 'your-graph-id' },
|
|
57
|
-
body: {
|
|
58
|
-
query: 'MATCH (c:Company)-[:HAS_FILING]->(f:Filing) RETURN c.name, f.form_type LIMIT 5',
|
|
59
|
-
},
|
|
60
|
-
})
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
### Server Usage (with API key)
|
|
64
|
-
|
|
65
|
-
```typescript
|
|
66
|
-
import { client, getUserGraphs, listCompanies } from '@robosystems/client'
|
|
67
|
-
|
|
68
|
-
// Configure with API key for server-side usage
|
|
69
|
-
client.setConfig({
|
|
70
|
-
baseUrl: 'https://api.robosystems.ai',
|
|
71
|
-
headers: {
|
|
72
|
-
'X-API-Key': process.env.ROBOSYSTEMS_API_KEY!,
|
|
73
|
-
},
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
// Fetch user's graphs
|
|
77
|
-
const { data: graphs, error } = await getUserGraphs()
|
|
78
|
-
|
|
79
|
-
// Work with financial data
|
|
80
|
-
if (graphs?.graphs.length) {
|
|
81
|
-
const graphId = graphs.graphs[0].graph_id
|
|
82
|
-
const { data: companies } = await listCompanies({
|
|
83
|
-
path: { graph_id: graphId },
|
|
84
|
-
})
|
|
85
|
-
}
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
## Key API Endpoints
|
|
89
|
-
|
|
90
|
-
### Authentication & User Management
|
|
91
|
-
|
|
92
|
-
```typescript
|
|
93
|
-
import {
|
|
94
|
-
registerUser,
|
|
95
|
-
loginUser,
|
|
96
|
-
logoutUser,
|
|
97
|
-
getCurrentUser,
|
|
98
|
-
createUserApiKey,
|
|
99
|
-
} from '@robosystems/client'
|
|
100
|
-
|
|
101
|
-
// Register a new user
|
|
102
|
-
const { data, error } = await registerUser({
|
|
103
|
-
body: {
|
|
104
|
-
email: 'user@example.com',
|
|
105
|
-
password: 'secure-password',
|
|
106
|
-
name: 'John Doe',
|
|
107
|
-
},
|
|
108
|
-
})
|
|
109
|
-
|
|
110
|
-
// Sign in
|
|
111
|
-
const { data: session } = await loginUser({
|
|
112
|
-
body: {
|
|
113
|
-
username: 'user@example.com',
|
|
114
|
-
password: 'secure-password',
|
|
115
|
-
},
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
// Get current user
|
|
119
|
-
const { data: user } = await getCurrentUser()
|
|
120
|
-
|
|
121
|
-
// Create API key for programmatic access
|
|
122
|
-
const { data: apiKey } = await createUserApiKey({
|
|
123
|
-
body: {
|
|
124
|
-
key_name: 'Production Server',
|
|
125
|
-
key_type: 'user',
|
|
126
|
-
},
|
|
127
|
-
})
|
|
128
|
-
console.log('Save this key securely:', apiKey.key)
|
|
129
|
-
|
|
130
|
-
// Sign out
|
|
131
|
-
await logoutUser()
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
### Company & Financial Data
|
|
135
|
-
|
|
136
|
-
```typescript
|
|
137
|
-
import {
|
|
138
|
-
listCompanies,
|
|
139
|
-
getCompany,
|
|
140
|
-
createCompany,
|
|
141
|
-
createConnection,
|
|
142
|
-
syncConnection,
|
|
143
|
-
} from '@robosystems/client'
|
|
144
|
-
|
|
145
|
-
// List companies with pagination
|
|
146
|
-
const { data: companies } = await listCompanies({
|
|
147
|
-
path: { graph_id: 'your-graph-id' },
|
|
148
|
-
query: { limit: 20, offset: 0 },
|
|
149
|
-
})
|
|
150
|
-
console.log(`Found ${companies.total} companies`)
|
|
151
|
-
|
|
152
|
-
// Get specific company details
|
|
153
|
-
const { data: company } = await getCompany({
|
|
154
|
-
path: {
|
|
155
|
-
graph_id: 'your-graph-id',
|
|
156
|
-
company_id: 'AAPL',
|
|
157
|
-
},
|
|
158
|
-
})
|
|
159
|
-
|
|
160
|
-
// Create new company
|
|
161
|
-
const { data: newCompany } = await createCompany({
|
|
162
|
-
path: { graph_id: 'your-graph-id' },
|
|
163
|
-
body: {
|
|
164
|
-
identifier: 'MSFT',
|
|
165
|
-
name: 'Microsoft Corporation',
|
|
166
|
-
metadata: { industry: 'Technology' },
|
|
167
|
-
},
|
|
168
|
-
})
|
|
169
|
-
|
|
170
|
-
// Create data connection (QuickBooks, etc.)
|
|
171
|
-
const { data: connection } = await createConnection({
|
|
172
|
-
path: { graph_id: 'your-graph-id' },
|
|
173
|
-
body: {
|
|
174
|
-
name: 'QuickBooks Integration',
|
|
175
|
-
connection_type: 'quickbooks',
|
|
176
|
-
config: { company_id: '123456' },
|
|
177
|
-
},
|
|
178
|
-
})
|
|
179
|
-
|
|
180
|
-
// Sync data from connection
|
|
181
|
-
const { data: syncResult } = await syncConnection({
|
|
182
|
-
path: {
|
|
183
|
-
graph_id: 'your-graph-id',
|
|
184
|
-
connection_id: connection.id,
|
|
185
|
-
},
|
|
186
|
-
})
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
### Graph Queries & Analytics
|
|
190
|
-
|
|
191
|
-
```typescript
|
|
192
|
-
import {
|
|
193
|
-
executeCypherQuery,
|
|
194
|
-
executeReadOnlyCypherQuery,
|
|
195
|
-
getGraphMetrics,
|
|
196
|
-
} from '@robosystems/client'
|
|
197
|
-
|
|
198
|
-
// Execute parameterized Cypher queries
|
|
199
|
-
const { data: results } = await executeCypherQuery({
|
|
200
|
-
path: { graph_id: 'your-graph-id' },
|
|
201
|
-
body: {
|
|
202
|
-
query: `
|
|
203
|
-
MATCH (c:Company {ticker: $ticker})-[:HAS_METRIC]->(m:Metric)
|
|
204
|
-
WHERE m.fiscal_year >= $start_year
|
|
205
|
-
RETURN m.name, m.value, m.fiscal_year
|
|
206
|
-
ORDER BY m.fiscal_year DESC
|
|
207
|
-
`,
|
|
208
|
-
parameters: { ticker: 'AAPL', start_year: 2020 },
|
|
209
|
-
},
|
|
210
|
-
})
|
|
211
|
-
|
|
212
|
-
// Read-only queries for better performance
|
|
213
|
-
const { data: readOnlyResult } = await executeReadOnlyCypherQuery({
|
|
214
|
-
path: { graph_id: 'your-graph-id' },
|
|
215
|
-
body: { query: 'MATCH (n) RETURN count(n) as total' },
|
|
216
|
-
})
|
|
217
|
-
|
|
218
|
-
// Get graph analytics
|
|
219
|
-
const { data: metrics } = await getGraphMetrics({
|
|
220
|
-
path: { graph_id: 'your-graph-id' },
|
|
221
|
-
})
|
|
222
|
-
console.log(`Total nodes: ${metrics.total_nodes}`)
|
|
223
|
-
console.log(`Total relationships: ${metrics.total_relationships}`)
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
### Financial AI Agent
|
|
227
|
-
|
|
228
|
-
```typescript
|
|
229
|
-
import { queryFinancialAgent } from '@robosystems/client'
|
|
230
|
-
|
|
231
|
-
// Natural language financial queries
|
|
232
|
-
const { data: agentResponse } = await queryFinancialAgent({
|
|
233
|
-
path: { graph_id: 'your-graph-id' },
|
|
234
|
-
body: {
|
|
235
|
-
query: "What was Apple's revenue growth over the last 3 years?",
|
|
236
|
-
include_reasoning: true,
|
|
237
|
-
max_tokens: 1000,
|
|
238
|
-
},
|
|
239
|
-
})
|
|
240
|
-
|
|
241
|
-
console.log('Answer:', agentResponse.answer)
|
|
242
|
-
if (agentResponse.reasoning) {
|
|
243
|
-
console.log('Reasoning:', agentResponse.reasoning)
|
|
244
|
-
}
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
## Advanced Features
|
|
248
|
-
|
|
249
|
-
### Billing & Credit Management
|
|
250
|
-
|
|
251
|
-
```typescript
|
|
252
|
-
import { getCreditSummary, checkCreditBalance, getCurrentGraphBill } from '@robosystems/client'
|
|
253
|
-
|
|
254
|
-
// Monitor credits and usage for a specific graph
|
|
255
|
-
const { data: creditSummary } = await getCreditSummary({
|
|
256
|
-
path: { graph_id: 'your-graph-id' },
|
|
257
|
-
})
|
|
258
|
-
console.log(`Available credits: ${creditSummary.available_credits.toLocaleString()}`)
|
|
259
|
-
console.log(
|
|
260
|
-
`Monthly usage: ${creditSummary.used_credits.toLocaleString()}/${creditSummary.total_credits.toLocaleString()}`
|
|
261
|
-
)
|
|
262
|
-
|
|
263
|
-
// Check credit requirements before operations
|
|
264
|
-
const { data: creditCheck } = await checkCreditBalance({
|
|
265
|
-
path: { graph_id: 'your-graph-id' },
|
|
266
|
-
body: {
|
|
267
|
-
operation_type: 'query',
|
|
268
|
-
estimated_credits: 100,
|
|
269
|
-
},
|
|
270
|
-
})
|
|
271
|
-
|
|
272
|
-
if (creditCheck.has_sufficient_credits) {
|
|
273
|
-
// Proceed with operation
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
// Get billing information
|
|
277
|
-
const { data: currentBill } = await getCurrentGraphBill({
|
|
278
|
-
path: { graph_id: 'your-graph-id' },
|
|
279
|
-
})
|
|
280
|
-
```
|
|
281
|
-
|
|
282
|
-
### MCP Tools Integration
|
|
283
|
-
|
|
284
|
-
```typescript
|
|
285
|
-
import { listMcpTools, callMcpTool } from '@robosystems/client'
|
|
286
|
-
|
|
287
|
-
// List available MCP tools
|
|
288
|
-
const { data: tools } = await listMcpTools({
|
|
289
|
-
path: { graph_id: 'your-graph-id' },
|
|
290
|
-
})
|
|
291
|
-
tools.tools.forEach((tool) => {
|
|
292
|
-
console.log(`${tool.name}: ${tool.description}`)
|
|
293
|
-
})
|
|
294
|
-
|
|
295
|
-
// Call an MCP tool
|
|
296
|
-
const { data: toolResult } = await callMcpTool({
|
|
297
|
-
path: { graph_id: 'your-graph-id' },
|
|
298
|
-
body: {
|
|
299
|
-
name: 'analyze_financial_statement',
|
|
300
|
-
arguments: {
|
|
301
|
-
company_id: 'AAPL',
|
|
302
|
-
statement_type: 'income',
|
|
303
|
-
fiscal_year: 2023,
|
|
304
|
-
},
|
|
305
|
-
},
|
|
306
|
-
})
|
|
307
|
-
console.log('Analysis result:', toolResult.content)
|
|
308
|
-
```
|
|
309
|
-
|
|
310
|
-
## Advanced Features
|
|
311
|
-
|
|
312
|
-
### Error Handling
|
|
313
|
-
|
|
314
|
-
```typescript
|
|
315
|
-
import { listCompanies } from '@robosystems/client'
|
|
316
|
-
import type { ErrorResponse } from '@robosystems/client'
|
|
317
|
-
|
|
318
|
-
try {
|
|
319
|
-
const { data, error } = await listCompanies({
|
|
320
|
-
path: { graph_id: 'your-graph-id' },
|
|
321
|
-
})
|
|
322
|
-
|
|
323
|
-
if (error) {
|
|
324
|
-
const apiError = error as ErrorResponse
|
|
325
|
-
|
|
326
|
-
switch (apiError.status) {
|
|
327
|
-
case 400:
|
|
328
|
-
console.error('Validation error:', apiError.detail)
|
|
329
|
-
break
|
|
330
|
-
case 401:
|
|
331
|
-
console.error('Authentication failed - check your API key')
|
|
332
|
-
break
|
|
333
|
-
case 403:
|
|
334
|
-
console.error('Permission denied - check graph access')
|
|
335
|
-
break
|
|
336
|
-
case 429:
|
|
337
|
-
console.error('Rate limit exceeded - retry later')
|
|
338
|
-
break
|
|
339
|
-
case 503:
|
|
340
|
-
console.error('Service temporarily unavailable')
|
|
341
|
-
break
|
|
342
|
-
default:
|
|
343
|
-
console.error('API Error:', apiError.detail || apiError.message)
|
|
344
|
-
}
|
|
345
|
-
} else if (data) {
|
|
346
|
-
console.log(`Found ${data.total} companies`)
|
|
347
|
-
}
|
|
348
|
-
} catch (err) {
|
|
349
|
-
// Network errors
|
|
350
|
-
console.error('Network Error:', err)
|
|
351
|
-
}
|
|
352
|
-
```
|
|
353
|
-
|
|
354
|
-
### TypeScript Types
|
|
355
|
-
|
|
356
|
-
All API responses and requests are fully typed:
|
|
357
|
-
|
|
358
|
-
```typescript
|
|
359
|
-
import type {
|
|
360
|
-
User,
|
|
361
|
-
Graph,
|
|
362
|
-
Company,
|
|
363
|
-
CompanyCreate,
|
|
364
|
-
CypherQueryRequest,
|
|
365
|
-
CypherQueryResponse,
|
|
366
|
-
AgentQueryRequest,
|
|
367
|
-
AgentQueryResponse,
|
|
368
|
-
ErrorResponse,
|
|
369
|
-
PaginatedResponse,
|
|
370
|
-
} from '@robosystems/client'
|
|
371
|
-
|
|
372
|
-
// Type-safe function example
|
|
373
|
-
function processCompany(company: Company): void {
|
|
374
|
-
console.log(`Company: ${company.name} (${company.identifier})`)
|
|
375
|
-
if (company.metadata) {
|
|
376
|
-
console.log('Industry:', company.metadata.industry)
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
// Type-safe query builder
|
|
381
|
-
function buildMetricQuery(ticker: string, startYear: number): CypherQueryRequest {
|
|
382
|
-
return {
|
|
383
|
-
query: `
|
|
384
|
-
MATCH (c:Company {ticker: $ticker})-[:HAS_METRIC]->(m:Metric)
|
|
385
|
-
WHERE m.fiscal_year >= $start_year
|
|
386
|
-
RETURN m
|
|
387
|
-
`,
|
|
388
|
-
parameters: { ticker, start_year: startYear },
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
```
|
|
392
|
-
|
|
393
|
-
## Environment Configuration
|
|
394
|
-
|
|
395
|
-
### Next.js App Router
|
|
396
|
-
|
|
397
|
-
```typescript
|
|
398
|
-
// app/api/robosystems/route.ts
|
|
399
|
-
import { client } from '@robosystems/client'
|
|
400
|
-
|
|
401
|
-
// Configure for server-side API routes
|
|
402
|
-
client.setConfig({
|
|
403
|
-
baseUrl: process.env.ROBOSYSTEMS_API_URL || 'https://api.robosystems.ai',
|
|
404
|
-
headers: {
|
|
405
|
-
'X-API-Key': process.env.ROBOSYSTEMS_API_KEY!,
|
|
406
|
-
},
|
|
407
|
-
})
|
|
408
|
-
```
|
|
409
|
-
|
|
410
|
-
### React SPA
|
|
411
|
-
|
|
412
|
-
```typescript
|
|
413
|
-
// src/lib/robosystems.ts
|
|
414
|
-
import { client } from '@robosystems/client'
|
|
415
|
-
|
|
416
|
-
// Configure for browser with cookies
|
|
417
|
-
client.setConfig({
|
|
418
|
-
baseUrl: import.meta.env.VITE_ROBOSYSTEMS_API_URL || 'https://api.robosystems.ai',
|
|
419
|
-
credentials: 'include',
|
|
420
|
-
})
|
|
421
|
-
```
|
|
422
|
-
|
|
423
|
-
### Node.js Script
|
|
424
|
-
|
|
425
|
-
```typescript
|
|
426
|
-
// scripts/analyze.ts
|
|
427
|
-
import { client } from '@robosystems/client'
|
|
428
|
-
import dotenv from 'dotenv'
|
|
429
|
-
|
|
430
|
-
dotenv.config()
|
|
431
|
-
|
|
432
|
-
client.setConfig({
|
|
433
|
-
baseUrl: process.env.ROBOSYSTEMS_API_URL || 'https://api.robosystems.ai',
|
|
434
|
-
headers: {
|
|
435
|
-
'X-API-Key': process.env.ROBOSYSTEMS_API_KEY!,
|
|
436
|
-
},
|
|
437
|
-
})
|
|
438
21
|
```
|
|
439
22
|
|
|
440
23
|
## API Reference
|
|
441
24
|
|
|
442
|
-
-
|
|
25
|
+
- API reference: [https://api.robosystems.ai](https://api.robosystems.ai)
|
|
26
|
+
- API documentation: [https://api.robosystems.ai/docs](https://api.robosystems.ai/docs)
|
|
443
27
|
- OpenAPI specification: [https://api.robosystems.ai/openapi.json](https://api.robosystems.ai/openapi.json)
|
|
444
28
|
|
|
445
29
|
## Support
|
|
446
30
|
|
|
447
|
-
- Issues: [
|
|
31
|
+
- Issues: [Issues](https://github.com/RoboFinSystems/robosystems-typescript-client/issues)
|
|
32
|
+
- Discussions: [Discussions](https://github.com/RoboFinSystems/robosystems-typescript-client/discussions)
|
|
33
|
+
- Projects: [Projects](https://github.com/RoboFinSystems/robosystems-typescript-client/projects)
|
|
34
|
+
- Wiki: [Wiki](https://github.com/RoboFinSystems/robosystems-typescript-client/wiki)
|
|
448
35
|
|
|
449
36
|
## License
|
|
450
37
|
|
|
451
38
|
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
452
39
|
|
|
453
|
-
MIT © 2025
|
|
40
|
+
MIT © 2025 RFS LLC
|
package/bin/create-feature
CHANGED
|
@@ -39,16 +39,9 @@ echo ""
|
|
|
39
39
|
|
|
40
40
|
# Check for uncommitted changes
|
|
41
41
|
if ! git diff --quiet || ! git diff --cached --quiet; then
|
|
42
|
-
echo "⚠️ You have uncommitted changes."
|
|
43
|
-
|
|
44
|
-
echo
|
|
45
|
-
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
46
|
-
git stash push -m "Auto-stash before creating branch $FULL_BRANCH"
|
|
47
|
-
echo "✅ Changes stashed"
|
|
48
|
-
else
|
|
49
|
-
echo "❌ Please commit or stash your changes first"
|
|
50
|
-
exit 1
|
|
51
|
-
fi
|
|
42
|
+
echo "⚠️ You have uncommitted changes. Auto-stashing..."
|
|
43
|
+
git stash push -m "Auto-stash before creating branch $FULL_BRANCH"
|
|
44
|
+
echo "✅ Changes stashed"
|
|
52
45
|
fi
|
|
53
46
|
|
|
54
47
|
# Fetch latest changes from remote
|
|
@@ -92,13 +85,10 @@ echo " 2. Push your changes: git push"
|
|
|
92
85
|
echo " 3. Create a PR: gh pr create --base $BASE_BRANCH --title \"Your PR title\" --body \"Your PR description\""
|
|
93
86
|
echo " or use: npm run pr:create"
|
|
94
87
|
|
|
95
|
-
# Check if we had stashed changes
|
|
88
|
+
# Check if we had stashed changes and auto-apply them
|
|
96
89
|
if git stash list | grep -q "Auto-stash before creating branch $FULL_BRANCH"; then
|
|
97
90
|
echo ""
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
git stash pop
|
|
102
|
-
echo "✅ Stashed changes applied"
|
|
103
|
-
fi
|
|
91
|
+
echo "Auto-applying stashed changes..."
|
|
92
|
+
git stash pop
|
|
93
|
+
echo "✅ Stashed changes applied"
|
|
104
94
|
fi
|
package/extensions/CopyClient.js
CHANGED
package/extensions/CopyClient.ts
CHANGED
|
@@ -53,12 +53,14 @@ export class CopyClient {
|
|
|
53
53
|
baseUrl: string
|
|
54
54
|
credentials?: 'include' | 'same-origin' | 'omit'
|
|
55
55
|
headers?: Record<string, string>
|
|
56
|
+
token?: string // JWT token for authentication
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
constructor(config: {
|
|
59
60
|
baseUrl: string
|
|
60
61
|
credentials?: 'include' | 'same-origin' | 'omit'
|
|
61
62
|
headers?: Record<string, string>
|
|
63
|
+
token?: string // JWT token for authentication
|
|
62
64
|
}) {
|
|
63
65
|
this.config = config
|
|
64
66
|
}
|
|
@@ -111,6 +113,9 @@ export class CopyClient {
|
|
|
111
113
|
url: '/v1/{graph_id}/copy' as const,
|
|
112
114
|
path: { graph_id: graphId },
|
|
113
115
|
body: request,
|
|
116
|
+
query: {
|
|
117
|
+
token: this.config.token, // Pass JWT token for SSE authentication
|
|
118
|
+
},
|
|
114
119
|
}
|
|
115
120
|
|
|
116
121
|
try {
|
|
@@ -34,6 +34,7 @@ export class OperationClient {
|
|
|
34
34
|
baseUrl: string
|
|
35
35
|
credentials?: 'include' | 'same-origin' | 'omit'
|
|
36
36
|
headers?: Record<string, string>
|
|
37
|
+
token?: string // JWT token for authentication
|
|
37
38
|
maxRetries?: number
|
|
38
39
|
retryDelay?: number
|
|
39
40
|
}
|
|
@@ -44,6 +45,7 @@ export class OperationClient {
|
|
|
44
45
|
baseUrl: string
|
|
45
46
|
credentials?: 'include' | 'same-origin' | 'omit'
|
|
46
47
|
headers?: Record<string, string>
|
|
48
|
+
token?: string // JWT token for authentication
|
|
47
49
|
maxRetries?: number
|
|
48
50
|
retryDelay?: number
|
|
49
51
|
}) {
|
|
@@ -33,6 +33,7 @@ export declare class QueryClient {
|
|
|
33
33
|
baseUrl: string;
|
|
34
34
|
credentials?: 'include' | 'same-origin' | 'omit';
|
|
35
35
|
headers?: Record<string, string>;
|
|
36
|
+
token?: string;
|
|
36
37
|
});
|
|
37
38
|
executeQuery(graphId: string, request: QueryRequest, options?: QueryOptions): Promise<QueryResult | AsyncIterableIterator<any>>;
|
|
38
39
|
private streamQueryResults;
|
|
@@ -47,12 +47,14 @@ export class QueryClient {
|
|
|
47
47
|
baseUrl: string
|
|
48
48
|
credentials?: 'include' | 'same-origin' | 'omit'
|
|
49
49
|
headers?: Record<string, string>
|
|
50
|
+
token?: string // JWT token for authentication
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
constructor(config: {
|
|
53
54
|
baseUrl: string
|
|
54
55
|
credentials?: 'include' | 'same-origin' | 'omit'
|
|
55
56
|
headers?: Record<string, string>
|
|
57
|
+
token?: string // JWT token for authentication
|
|
56
58
|
}) {
|
|
57
59
|
this.config = config
|
|
58
60
|
}
|
|
@@ -72,6 +74,7 @@ export class QueryClient {
|
|
|
72
74
|
query: {
|
|
73
75
|
mode: options.mode,
|
|
74
76
|
test_mode: options.testMode,
|
|
77
|
+
token: this.config.token, // Pass JWT token for SSE authentication
|
|
75
78
|
},
|
|
76
79
|
}
|
|
77
80
|
|
|
@@ -1,11 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Core SSE (Server-Sent Events) client for RoboSystems API
|
|
3
3
|
* Provides automatic reconnection, event replay, and type-safe event handling
|
|
4
|
+
*
|
|
5
|
+
* SECURITY NOTE: When using JWT authentication, tokens are passed as query parameters
|
|
6
|
+
* due to EventSource API limitations. This means tokens may appear in:
|
|
7
|
+
* - Server access logs
|
|
8
|
+
* - Proxy logs
|
|
9
|
+
* - Browser history
|
|
10
|
+
* - Referer headers
|
|
11
|
+
*
|
|
12
|
+
* For production environments with sensitive data, consider:
|
|
13
|
+
* - Using cookie-based authentication instead
|
|
14
|
+
* - Implementing a WebSocket-based alternative
|
|
15
|
+
* - Using short-lived tokens that expire quickly
|
|
16
|
+
* - Ensuring all connections use HTTPS
|
|
4
17
|
*/
|
|
5
18
|
export interface SSEConfig {
|
|
6
19
|
baseUrl: string;
|
|
7
20
|
credentials?: 'include' | 'same-origin' | 'omit';
|
|
8
21
|
headers?: Record<string, string>;
|
|
22
|
+
token?: string;
|
|
9
23
|
maxRetries?: number;
|
|
10
24
|
retryDelay?: number;
|
|
11
25
|
heartbeatInterval?: number;
|
package/extensions/SSEClient.js
CHANGED
|
@@ -28,7 +28,13 @@ class SSEClient {
|
|
|
28
28
|
}
|
|
29
29
|
async connect(operationId, fromSequence = 0) {
|
|
30
30
|
return new Promise((resolve, reject) => {
|
|
31
|
-
|
|
31
|
+
let url = `${this.config.baseUrl}/v1/operations/${operationId}/stream?from_sequence=${fromSequence}`;
|
|
32
|
+
// Add JWT token as query parameter if provided
|
|
33
|
+
// WARNING: EventSource API doesn't support custom headers, so tokens are passed via query param
|
|
34
|
+
// This has security implications - see class documentation
|
|
35
|
+
if (this.config.token) {
|
|
36
|
+
url += `&token=${encodeURIComponent(this.config.token)}`;
|
|
37
|
+
}
|
|
32
38
|
this.eventSource = new EventSource(url, {
|
|
33
39
|
withCredentials: this.config.credentials === 'include',
|
|
34
40
|
});
|