@railtownai/railengine 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/LICENSE +21 -0
- package/README.md +570 -0
- package/dist/cjs/index.js +892 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/esm/index.js +890 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/types/auth.d.ts +24 -0
- package/dist/types/auth.d.ts.map +1 -0
- package/dist/types/client.d.ts +196 -0
- package/dist/types/client.d.ts.map +1 -0
- package/dist/types/embeddings.d.ts +17 -0
- package/dist/types/embeddings.d.ts.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/indexing.d.ts +17 -0
- package/dist/types/indexing.d.ts.map +1 -0
- package/dist/types/storage.d.ts +63 -0
- package/dist/types/storage.d.ts.map +1 -0
- package/package.json +47 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Railtown AI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,570 @@
|
|
|
1
|
+
# @railtownai/railengine
|
|
2
|
+
|
|
3
|
+
JavaScript/TypeScript SDK for Railtown AI Rail Engine - Retrieval package. This package provides a simple interface for reading and searching data from Rail Engine.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @railtownai/railengine
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
- Node.js 20+
|
|
14
|
+
- TypeScript 5.0+ (optional, but recommended)
|
|
15
|
+
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
### Basic Usage
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
import { RailEngine } from "@railtownai/railengine";
|
|
22
|
+
|
|
23
|
+
// Initialize client
|
|
24
|
+
const client = new RailEngine({
|
|
25
|
+
pat: "your-pat-token",
|
|
26
|
+
engineId: "your-engine-id"
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// Search vector store
|
|
30
|
+
const results = client.searchVectorStore("engine-id", "VectorStore1", "search query");
|
|
31
|
+
for await (const result of results) {
|
|
32
|
+
console.log(result);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Get storage document by EventId
|
|
36
|
+
const document = await client.getStorageDocumentByEventId("engine-id", "event-id");
|
|
37
|
+
console.log(document);
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Using Environment Variables
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
import { RailEngine } from "@railtownai/railengine";
|
|
44
|
+
|
|
45
|
+
// ENGINE_PAT and ENGINE_ID are read from environment variables automatically
|
|
46
|
+
const client = new RailEngine();
|
|
47
|
+
|
|
48
|
+
// Use client.engineId if you need it
|
|
49
|
+
const results = client.searchVectorStore(client.engineId, "VectorStore1", "query");
|
|
50
|
+
for await (const result of results) {
|
|
51
|
+
console.log(result);
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Authentication Configuration
|
|
56
|
+
|
|
57
|
+
The retrieval package uses PAT (Personal Access Token) for authentication.
|
|
58
|
+
|
|
59
|
+
### Environment Variables
|
|
60
|
+
|
|
61
|
+
- `ENGINE_PAT` - Personal Access Token (required)
|
|
62
|
+
- `ENGINE_ID` - Engine ID (optional, but required if not provided via constructor)
|
|
63
|
+
- `RAILTOWN_API_URL` - Base API URL (optional, defaults to `https://cndr.railtown.ai/api`)
|
|
64
|
+
|
|
65
|
+
### Setting Environment Variables
|
|
66
|
+
|
|
67
|
+
#### Windows (PowerShell)
|
|
68
|
+
|
|
69
|
+
```powershell
|
|
70
|
+
$env:ENGINE_PAT="<your-pat-token>"
|
|
71
|
+
$env:ENGINE_ID="<your-engine-id>"
|
|
72
|
+
$env:RAILTOWN_API_URL="https://cndr.railtown.ai/api" # Optional
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
#### Windows (Command Prompt)
|
|
76
|
+
|
|
77
|
+
```cmd
|
|
78
|
+
set ENGINE_PAT=<your-pat-token>
|
|
79
|
+
set ENGINE_ID=<your-engine-id>
|
|
80
|
+
set RAILTOWN_API_URL=https://cndr.railtown.ai/api
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
#### macOS/Linux
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
export ENGINE_PAT="<your-pat-token>"
|
|
87
|
+
export ENGINE_ID="<your-engine-id>"
|
|
88
|
+
export RAILTOWN_API_URL="https://cndr.railtown.ai/api" # Optional
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
#### .env file
|
|
92
|
+
|
|
93
|
+
Create a `.env` file in your project root:
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
ENGINE_PAT=<your-pat-token>
|
|
97
|
+
ENGINE_ID=<your-engine-id>
|
|
98
|
+
RAILTOWN_API_URL=https://cndr.railtown.ai/api
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Then use a package like `dotenv` to load it:
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
import "dotenv/config";
|
|
105
|
+
import { RailEngine } from "@railtownai/railengine";
|
|
106
|
+
|
|
107
|
+
const client = new RailEngine(); // Reads from environment variables
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Configuration Priority
|
|
111
|
+
|
|
112
|
+
1. Constructor parameters (highest priority)
|
|
113
|
+
2. Environment variables
|
|
114
|
+
3. Default values (where applicable)
|
|
115
|
+
|
|
116
|
+
**Note**: If `ENGINE_ID` is set in environment variables, you don't need to specify it in client initialization. If `ENGINE_ID` is NOT set in environment variables, you MUST specify it in client initialization.
|
|
117
|
+
|
|
118
|
+
## Zod Schema Support
|
|
119
|
+
|
|
120
|
+
You can provide a Zod schema during client initialization to automatically validate retrieved data:
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
import { z } from "zod";
|
|
124
|
+
import { RailEngine } from "@railtownai/railengine";
|
|
125
|
+
|
|
126
|
+
const FoodDiaryItemSchema = z.object({
|
|
127
|
+
food_name: z.string(),
|
|
128
|
+
calories: z.number(),
|
|
129
|
+
carbs: z.number(),
|
|
130
|
+
proteins: z.number(),
|
|
131
|
+
fats: z.number()
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
type FoodDiaryItem = z.infer<typeof FoodDiaryItemSchema>;
|
|
135
|
+
|
|
136
|
+
// Initialize with schema
|
|
137
|
+
const client = new RailEngine({
|
|
138
|
+
pat: "your-pat-token",
|
|
139
|
+
engineId: "your-engine-id",
|
|
140
|
+
schema: FoodDiaryItemSchema
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// Results automatically validated against FoodDiaryItemSchema
|
|
144
|
+
const results = client.searchVectorStore("engine-id", "VectorStore1", "apple");
|
|
145
|
+
for await (const item of results) {
|
|
146
|
+
// item is FoodDiaryItem
|
|
147
|
+
console.log(item.food_name, item.calories);
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Overriding Schema Per Call
|
|
152
|
+
|
|
153
|
+
You can override the default schema on individual method calls:
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
const FoodSummarySchema = z.object({
|
|
157
|
+
name: z.string(),
|
|
158
|
+
cal: z.number()
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
const results = client.searchVectorStore("engine-id", "VectorStore1", "apple", {
|
|
162
|
+
schema: FoodSummarySchema // Override default schema
|
|
163
|
+
});
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Client-Side Filtering
|
|
167
|
+
|
|
168
|
+
All retrieval methods support optional client-side filtering via `filterFn`:
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
// Filter results by CustomerKey pattern
|
|
172
|
+
const results = client.searchVectorStore("engine-id", "VectorStore1", "query", {
|
|
173
|
+
filterFn: (item) => {
|
|
174
|
+
const customerKey = (item as { CustomerKey?: string }).CustomerKey || "";
|
|
175
|
+
return customerKey.startsWith("doc-");
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
for await (const result of results) {
|
|
180
|
+
console.log(result);
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Filtering with Pagination
|
|
185
|
+
|
|
186
|
+
Filtering works seamlessly with pagination - filters are applied across all pages automatically:
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
// List documents and filter by version
|
|
190
|
+
const documents = client.listStorageDocuments("engine-id", {
|
|
191
|
+
filterFn: (doc) => ((doc as { Version?: number }).Version || 0) > 1
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
for await (const doc of documents) {
|
|
195
|
+
console.log(doc);
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## API Methods
|
|
200
|
+
|
|
201
|
+
### Embeddings API
|
|
202
|
+
|
|
203
|
+
#### searchVectorStore
|
|
204
|
+
|
|
205
|
+
Search a vector store using semantic similarity.
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
const results = client.searchVectorStore(
|
|
209
|
+
engineId: string,
|
|
210
|
+
vectorStore: string,
|
|
211
|
+
query: string,
|
|
212
|
+
options?: {
|
|
213
|
+
filterFn?: (item: T | Record<string, unknown>) => boolean;
|
|
214
|
+
schema?: z.ZodSchema<unknown>;
|
|
215
|
+
}
|
|
216
|
+
): AsyncIterable<T | Record<string, unknown>>
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
**Example:**
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
const results = client.searchVectorStore("engine-id", "VectorStore1", "apple");
|
|
223
|
+
for await (const result of results) {
|
|
224
|
+
console.log(result);
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Storage API
|
|
229
|
+
|
|
230
|
+
#### getStorageDocumentByEventId
|
|
231
|
+
|
|
232
|
+
Get a single storage document by EventId.
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
const document = await client.getStorageDocumentByEventId(
|
|
236
|
+
engineId: string,
|
|
237
|
+
eventId: string,
|
|
238
|
+
options?: {
|
|
239
|
+
filterFn?: (document: T | Record<string, unknown>) => boolean;
|
|
240
|
+
schema?: z.ZodSchema<unknown>;
|
|
241
|
+
}
|
|
242
|
+
): Promise<T | Record<string, unknown> | null>
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
**Example:**
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
const document = await client.getStorageDocumentByEventId("engine-id", "event-id");
|
|
249
|
+
if (document) {
|
|
250
|
+
console.log(document);
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
#### getStorageDocumentByCustomerKey
|
|
255
|
+
|
|
256
|
+
Get storage documents by CustomerKey with automatic pagination.
|
|
257
|
+
|
|
258
|
+
```typescript
|
|
259
|
+
const documents = client.getStorageDocumentByCustomerKey(
|
|
260
|
+
engineId: string,
|
|
261
|
+
customerKey: string,
|
|
262
|
+
options?: {
|
|
263
|
+
pageNumber?: number; // Default: 1
|
|
264
|
+
pageSize?: number; // Default: 25, max: 100
|
|
265
|
+
filterFn?: (item: T | Record<string, unknown>) => boolean;
|
|
266
|
+
schema?: z.ZodSchema<unknown>;
|
|
267
|
+
}
|
|
268
|
+
): AsyncIterable<T | Record<string, unknown>>
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
**Example:**
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
const documents = client.getStorageDocumentByCustomerKey("engine-id", "doc-123", {
|
|
275
|
+
pageSize: 50
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
for await (const doc of documents) {
|
|
279
|
+
console.log(doc);
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
#### queryStorageByJsonPath
|
|
284
|
+
|
|
285
|
+
Query storage documents using JSONPath.
|
|
286
|
+
|
|
287
|
+
```typescript
|
|
288
|
+
const documents = client.queryStorageByJsonPath(
|
|
289
|
+
engineId: string,
|
|
290
|
+
jsonPathQuery: string,
|
|
291
|
+
options?: {
|
|
292
|
+
filterFn?: (item: T | Record<string, unknown>) => boolean;
|
|
293
|
+
schema?: z.ZodSchema<unknown>;
|
|
294
|
+
}
|
|
295
|
+
): AsyncIterable<T | Record<string, unknown>>
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
**Example:**
|
|
299
|
+
|
|
300
|
+
```typescript
|
|
301
|
+
const documents = client.queryStorageByJsonPath("engine-id", "$.status:active");
|
|
302
|
+
for await (const doc of documents) {
|
|
303
|
+
console.log(doc);
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
#### listStorageDocuments
|
|
308
|
+
|
|
309
|
+
List storage documents with automatic pagination.
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
const documents = client.listStorageDocuments(
|
|
313
|
+
engineId: string,
|
|
314
|
+
options?: {
|
|
315
|
+
customerKey?: string;
|
|
316
|
+
pageNumber?: number; // Default: 1
|
|
317
|
+
pageSize?: number; // Default: 100, max: 100
|
|
318
|
+
filterFn?: (item: T | Record<string, unknown>) => boolean;
|
|
319
|
+
schema?: z.ZodSchema<unknown>;
|
|
320
|
+
}
|
|
321
|
+
): AsyncIterable<T | Record<string, unknown>>
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
**Example:**
|
|
325
|
+
|
|
326
|
+
```typescript
|
|
327
|
+
// List all documents
|
|
328
|
+
const documents = client.listStorageDocuments("engine-id");
|
|
329
|
+
|
|
330
|
+
// List documents filtered by customerKey
|
|
331
|
+
const filtered = client.listStorageDocuments("engine-id", {
|
|
332
|
+
customerKey: "doc-123"
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
for await (const doc of documents) {
|
|
336
|
+
console.log(doc);
|
|
337
|
+
}
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### Indexing API
|
|
341
|
+
|
|
342
|
+
#### searchIndex
|
|
343
|
+
|
|
344
|
+
Search index using Azure Search.
|
|
345
|
+
|
|
346
|
+
```typescript
|
|
347
|
+
const results = client.searchIndex(
|
|
348
|
+
projectId: string,
|
|
349
|
+
engineId: string,
|
|
350
|
+
query: Record<string, unknown>,
|
|
351
|
+
options?: {
|
|
352
|
+
filterFn?: (item: T | Record<string, unknown>) => boolean;
|
|
353
|
+
schema?: z.ZodSchema<unknown>;
|
|
354
|
+
}
|
|
355
|
+
): AsyncIterable<T | Record<string, unknown>>
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
**Example:**
|
|
359
|
+
|
|
360
|
+
```typescript
|
|
361
|
+
const results = client.searchIndex("project-id", "engine-id", {
|
|
362
|
+
search: "example query"
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
for await (const result of results) {
|
|
366
|
+
console.log(result);
|
|
367
|
+
}
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
## Pagination
|
|
371
|
+
|
|
372
|
+
Pagination is handled automatically by the SDK. Methods that return multiple results use async iterables that handle pagination internally:
|
|
373
|
+
|
|
374
|
+
```typescript
|
|
375
|
+
// Automatically handles pagination - you don't need to manage pages manually
|
|
376
|
+
const documents = client.listStorageDocuments("engine-id", {
|
|
377
|
+
pageSize: 100
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
// Iterate through all pages automatically
|
|
381
|
+
for await (const document of documents) {
|
|
382
|
+
console.log(document);
|
|
383
|
+
}
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
Filtering is applied across all pages automatically:
|
|
387
|
+
|
|
388
|
+
```typescript
|
|
389
|
+
// Filter is applied to all pages, not just the first page
|
|
390
|
+
const documents = client.listStorageDocuments("engine-id", {
|
|
391
|
+
filterFn: (doc) => {
|
|
392
|
+
const customerKey = (doc as { CustomerKey?: string }).CustomerKey || "";
|
|
393
|
+
return customerKey.startsWith("doc-");
|
|
394
|
+
}
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
for await (const doc of documents) {
|
|
398
|
+
// All documents from all pages that match the filter
|
|
399
|
+
console.log(doc);
|
|
400
|
+
}
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
## Complete Examples
|
|
404
|
+
|
|
405
|
+
### Example: Building a Simple Agent
|
|
406
|
+
|
|
407
|
+
```typescript
|
|
408
|
+
import { RailEngine } from "@railtownai/railengine";
|
|
409
|
+
import { z } from "zod";
|
|
410
|
+
|
|
411
|
+
const DocumentSchema = z.object({
|
|
412
|
+
id: z.string(),
|
|
413
|
+
title: z.string(),
|
|
414
|
+
content: z.string(),
|
|
415
|
+
tags: z.array(z.string())
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
const client = new RailEngine({
|
|
419
|
+
pat: process.env.ENGINE_PAT!,
|
|
420
|
+
engineId: process.env.ENGINE_ID!,
|
|
421
|
+
schema: DocumentSchema
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
async function searchDocuments(query: string) {
|
|
425
|
+
// Search vector store
|
|
426
|
+
const vectorResults = client.searchVectorStore(client.engineId, "VectorStore1", query, {
|
|
427
|
+
filterFn: (doc) => {
|
|
428
|
+
const tags = (doc as { tags?: string[] }).tags || [];
|
|
429
|
+
return tags.includes("public");
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
const results: unknown[] = [];
|
|
434
|
+
for await (const result of vectorResults) {
|
|
435
|
+
results.push(result);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
return results;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// Usage
|
|
442
|
+
const docs = await searchDocuments("machine learning");
|
|
443
|
+
console.log(`Found ${docs.length} documents`);
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
### Example: Retrieving and Filtering Documents
|
|
447
|
+
|
|
448
|
+
```typescript
|
|
449
|
+
import { RailEngine } from "@railtownai/railengine";
|
|
450
|
+
|
|
451
|
+
const client = new RailEngine({
|
|
452
|
+
pat: process.env.ENGINE_PAT!,
|
|
453
|
+
engineId: process.env.ENGINE_ID!
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
// Get document by EventId
|
|
457
|
+
const doc = await client.getStorageDocumentByEventId("engine-id", "event-123");
|
|
458
|
+
if (doc) {
|
|
459
|
+
console.log("Found document:", doc);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
// Get documents by CustomerKey with filtering
|
|
463
|
+
const customerDocs = client.getStorageDocumentByCustomerKey("engine-id", "customer-123", {
|
|
464
|
+
filterFn: (doc) => {
|
|
465
|
+
const version = (doc as { Version?: number }).Version || 0;
|
|
466
|
+
const status = (doc as { Status?: string }).Status;
|
|
467
|
+
return version > 1 && status === "active";
|
|
468
|
+
}
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
for await (const doc of customerDocs) {
|
|
472
|
+
console.log("Customer document:", doc);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// Query using JSONPath
|
|
476
|
+
const activeDocs = client.queryStorageByJsonPath("engine-id", "$.status:active", {
|
|
477
|
+
filterFn: (doc) => {
|
|
478
|
+
const dateCreated = (doc as { DateCreated?: string }).DateCreated;
|
|
479
|
+
return dateCreated ? new Date(dateCreated) > new Date("2024-01-01") : false;
|
|
480
|
+
}
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
for await (const doc of activeDocs) {
|
|
484
|
+
console.log("Active document:", doc);
|
|
485
|
+
}
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
## API Reference
|
|
489
|
+
|
|
490
|
+
### RailEngine
|
|
491
|
+
|
|
492
|
+
Main client class for retrieving data from Rail Engine.
|
|
493
|
+
|
|
494
|
+
#### Constructor
|
|
495
|
+
|
|
496
|
+
```typescript
|
|
497
|
+
new RailEngine(options?: RailEngineOptions<T>)
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
**Options:**
|
|
501
|
+
|
|
502
|
+
- `pat?: string` - Personal Access Token. If not provided, reads from `ENGINE_PAT` environment variable.
|
|
503
|
+
- `engineId?: string` - Engine ID. If not provided, reads from `ENGINE_ID` environment variable.
|
|
504
|
+
- `apiUrl?: string` - Base API URL. If not provided, reads from `RAILTOWN_API_URL` environment variable or defaults to production.
|
|
505
|
+
- `schema?: z.ZodSchema<T>` - Optional Zod schema for validating retrieved data.
|
|
506
|
+
- `timeout?: number` - Request timeout in milliseconds. Defaults to 30000 (30 seconds).
|
|
507
|
+
|
|
508
|
+
**Example:**
|
|
509
|
+
|
|
510
|
+
```typescript
|
|
511
|
+
const client = new RailEngine({
|
|
512
|
+
pat: "your-pat-token",
|
|
513
|
+
engineId: "your-engine-id",
|
|
514
|
+
schema: MySchema,
|
|
515
|
+
timeout: 60000
|
|
516
|
+
});
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
#### Properties
|
|
520
|
+
|
|
521
|
+
- `pat: string` - Personal Access Token for authentication
|
|
522
|
+
- `engineId: string` - Engine identifier
|
|
523
|
+
- `apiUrl: string` - Base API URL (normalized)
|
|
524
|
+
|
|
525
|
+
#### Methods
|
|
526
|
+
|
|
527
|
+
All methods are documented above in the API Methods section.
|
|
528
|
+
|
|
529
|
+
## Error Handling
|
|
530
|
+
|
|
531
|
+
The SDK uses graceful error handling for read operations:
|
|
532
|
+
|
|
533
|
+
- **Read operations** return `null` or empty iterables on errors (graceful degradation)
|
|
534
|
+
- **Configuration errors** (missing PAT, engineId) throw exceptions
|
|
535
|
+
|
|
536
|
+
The SDK uses custom exception classes for different error scenarios:
|
|
537
|
+
|
|
538
|
+
- `RailtownError` - Base error class
|
|
539
|
+
- `RailtownUnauthorizedError` - Authentication failed (401)
|
|
540
|
+
- `RailtownNotFoundError` - Resource not found (404)
|
|
541
|
+
- `RailtownBadRequestError` - Bad request (400)
|
|
542
|
+
- `RailtownConflictError` - Conflict (409)
|
|
543
|
+
- `RailtownServerError` - Server error (500+)
|
|
544
|
+
|
|
545
|
+
**Example:**
|
|
546
|
+
|
|
547
|
+
```typescript
|
|
548
|
+
import { RailEngine, RailtownUnauthorizedError, RailtownBadRequestError } from "@railtownai/railengine";
|
|
549
|
+
|
|
550
|
+
try {
|
|
551
|
+
const client = new RailEngine({
|
|
552
|
+
pat: "invalid-pat",
|
|
553
|
+
engineId: "engine-id"
|
|
554
|
+
});
|
|
555
|
+
} catch (error) {
|
|
556
|
+
if (error instanceof RailtownBadRequestError) {
|
|
557
|
+
console.error("Invalid configuration:", error.message);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
// Read operations return null/empty on error
|
|
562
|
+
const document = await client.getStorageDocumentByEventId("engine-id", "event-id");
|
|
563
|
+
if (document === null) {
|
|
564
|
+
console.log("Document not found or error occurred");
|
|
565
|
+
}
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
## License
|
|
569
|
+
|
|
570
|
+
See [LICENSE](../../LICENSE) file for details.
|