@dataferry/sdk 0.1.0

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.
@@ -0,0 +1,534 @@
1
+ /**
2
+ * DataFerry SDK types
3
+ *
4
+ * These types are inlined from @dataferry/common so the SDK
5
+ * has zero runtime and type-level dependencies.
6
+ */
7
+ type ExportStatus = 'pending' | 'processing' | 'completed' | 'failed' | 'expired';
8
+ type ExportFormat = 'csv';
9
+ interface ExportMetadata {
10
+ requestIp?: string;
11
+ userAgent?: string;
12
+ portalSessionId?: string;
13
+ custom?: Record<string, unknown>;
14
+ }
15
+ interface ExportJob {
16
+ id: string;
17
+ organizationId: string;
18
+ scopeId: string;
19
+ connectionId?: string;
20
+ status: ExportStatus;
21
+ format: ExportFormat;
22
+ selectedTables: string[];
23
+ storageKey: string | null;
24
+ downloadUrl: string | null;
25
+ downloadUrlExpiresAt: Date | null;
26
+ fileSizeBytes: number | null;
27
+ totalRows: number | null;
28
+ errorMessage: string | null;
29
+ errorCode: string | null;
30
+ createdAt: Date;
31
+ startedAt: Date | null;
32
+ completedAt: Date | null;
33
+ metadata: ExportMetadata;
34
+ }
35
+ interface CreateExportRequest {
36
+ scopeId: string;
37
+ connectionId?: string;
38
+ format?: ExportFormat;
39
+ tables?: string[];
40
+ webhookUrl?: string;
41
+ metadata?: Record<string, unknown>;
42
+ }
43
+ interface PortalSession {
44
+ id: string;
45
+ organizationId: string;
46
+ scopeId: string;
47
+ profileId: string;
48
+ token: string;
49
+ expiresAt: Date;
50
+ createdAt: Date;
51
+ metadata?: Record<string, unknown>;
52
+ }
53
+ interface CreatePortalSessionRequest {
54
+ profile: string;
55
+ scopeId?: string;
56
+ expiresIn?: number;
57
+ returnUrl?: string;
58
+ email?: string;
59
+ metadata?: Record<string, unknown>;
60
+ }
61
+ interface CreatePortalSessionResponse {
62
+ id: string;
63
+ url: string;
64
+ expiresAt: Date;
65
+ }
66
+ interface DatabaseConnection {
67
+ id: string;
68
+ organizationId: string;
69
+ name: string;
70
+ host: string;
71
+ port: string;
72
+ database: string;
73
+ user: string;
74
+ ssl: boolean;
75
+ lastTestedAt: Date | null;
76
+ lastTestSuccess: boolean | null;
77
+ createdAt: Date;
78
+ updatedAt: Date;
79
+ }
80
+ interface CreateConnectionRequest {
81
+ name: string;
82
+ host: string;
83
+ port?: string;
84
+ database: string;
85
+ user: string;
86
+ password: string;
87
+ ssl?: boolean;
88
+ }
89
+ interface UpdateConnectionRequest {
90
+ name?: string;
91
+ host?: string;
92
+ port?: string;
93
+ database?: string;
94
+ user?: string;
95
+ password?: string;
96
+ ssl?: boolean;
97
+ }
98
+ interface TestConnectionResult {
99
+ connected: boolean;
100
+ database?: string;
101
+ user?: string;
102
+ error?: string;
103
+ responseTimeMs?: number;
104
+ }
105
+ type OwnershipMode = 'direct_column' | 'fk_chain';
106
+ interface OwnershipEdge {
107
+ fromTable: string;
108
+ fromColumn: string;
109
+ toTable: string;
110
+ toColumn: string;
111
+ direction: 'direct' | 'inverse';
112
+ }
113
+ interface IncludedTable {
114
+ tableName: string;
115
+ label: string;
116
+ ownershipMode: OwnershipMode | null;
117
+ userColumn?: string;
118
+ ownershipPath?: OwnershipEdge[];
119
+ depth: number;
120
+ confidence: number;
121
+ includedColumns: string[] | null;
122
+ excludedColumns: string[];
123
+ }
124
+ interface TableGroup {
125
+ id: string;
126
+ label: string;
127
+ tableNames: string[];
128
+ }
129
+ interface SchemaConfig {
130
+ id: string;
131
+ organizationId: string;
132
+ anchorTable?: string;
133
+ anchorColumn?: string;
134
+ includedTables: IncludedTable[];
135
+ excludedTables: string[];
136
+ maxDepth: number;
137
+ createdAt: Date;
138
+ updatedAt: Date;
139
+ version: number;
140
+ groups?: TableGroup[];
141
+ }
142
+ type WebhookEvent = 'export.completed' | 'export.failed' | 'schema.updated';
143
+ interface WebhookStats {
144
+ totalDeliveries: number;
145
+ successfulDeliveries: number;
146
+ failedDeliveries: number;
147
+ lastDeliveryAt: Date | null;
148
+ lastSuccessAt: Date | null;
149
+ lastFailureReason: string | null;
150
+ }
151
+ interface WebhookEndpoint {
152
+ id: string;
153
+ organizationId: string;
154
+ url: string;
155
+ events: WebhookEvent[];
156
+ secret: string;
157
+ active: boolean;
158
+ createdAt: Date;
159
+ updatedAt: Date;
160
+ stats: WebhookStats;
161
+ }
162
+
163
+ /**
164
+ * Portal Sessions resource
165
+ */
166
+
167
+ declare class PortalSessions {
168
+ private readonly client;
169
+ constructor(client: Ferry);
170
+ /**
171
+ * Create a new portal session for an end user
172
+ *
173
+ * @example
174
+ * ```ts
175
+ * const session = await ferry.portalSessions.create({
176
+ * profile: 'default',
177
+ * scopeId: 'user_123',
178
+ * expiresIn: 3600,
179
+ * returnUrl: 'https://yourapp.com/settings',
180
+ * });
181
+ *
182
+ * // Redirect user to session.url
183
+ * ```
184
+ */
185
+ create(params: CreatePortalSessionRequest): Promise<CreatePortalSessionResponse>;
186
+ /**
187
+ * Get portal session details
188
+ *
189
+ * @example
190
+ * ```ts
191
+ * const session = await ferry.portalSessions.retrieve('ps_abc123');
192
+ * console.log(session.scopeId, session.expiresAt);
193
+ * ```
194
+ */
195
+ retrieve(sessionId: string): Promise<PortalSession & {
196
+ isExpired: boolean;
197
+ }>;
198
+ /**
199
+ * Revoke a portal session
200
+ *
201
+ * @example
202
+ * ```ts
203
+ * await ferry.portalSessions.revoke('ps_abc123');
204
+ * ```
205
+ */
206
+ revoke(sessionId: string): Promise<{
207
+ id: string;
208
+ }>;
209
+ }
210
+
211
+ /**
212
+ * Exports resource
213
+ */
214
+
215
+ interface ExportResponse {
216
+ id: string;
217
+ status: ExportStatus;
218
+ scopeId: string;
219
+ /** Database connection ID used for this export */
220
+ connectionId?: string;
221
+ /** Database connection name (if connection still exists) */
222
+ connectionName?: string;
223
+ format: string;
224
+ tables: string[];
225
+ downloadUrl?: string;
226
+ downloadUrlExpiresAt?: string;
227
+ fileSizeBytes?: number;
228
+ totalRows?: number;
229
+ errorMessage?: string;
230
+ errorCode?: string;
231
+ createdAt: string;
232
+ startedAt?: string;
233
+ completedAt?: string;
234
+ }
235
+ interface ListExportsParams extends Record<string, string | number | undefined> {
236
+ scopeId?: string;
237
+ /** Filter by database connection ID */
238
+ connectionId?: string;
239
+ status?: ExportStatus;
240
+ page?: number;
241
+ limit?: number;
242
+ }
243
+ declare class Exports {
244
+ private readonly client;
245
+ constructor(client: Ferry);
246
+ /**
247
+ * Create a new export job
248
+ *
249
+ * @example
250
+ * ```ts
251
+ * // Create export using primary connection
252
+ * const exportJob = await ferry.exports.create({
253
+ * scopeId: 'user_123',
254
+ * format: 'csv',
255
+ * tables: ['users', 'posts', 'comments'],
256
+ * });
257
+ *
258
+ * // Create export using specific connection
259
+ * const exportJob = await ferry.exports.create({
260
+ * scopeId: 'user_123',
261
+ * connectionId: 'conn_abc123',
262
+ * format: 'csv',
263
+ * tables: ['users', 'posts'],
264
+ * });
265
+ *
266
+ * console.log(exportJob.id, exportJob.status);
267
+ * ```
268
+ */
269
+ create(params: CreateExportRequest): Promise<ExportResponse>;
270
+ /**
271
+ * Get export job details
272
+ *
273
+ * @example
274
+ * ```ts
275
+ * const exportJob = await ferry.exports.retrieve('exp_abc123');
276
+ *
277
+ * if (exportJob.status === 'completed') {
278
+ * console.log('Download:', exportJob.downloadUrl);
279
+ * }
280
+ * ```
281
+ */
282
+ retrieve(exportId: string): Promise<ExportResponse>;
283
+ /**
284
+ * List exports
285
+ *
286
+ * @example
287
+ * ```ts
288
+ * // List all exports
289
+ * const { data, meta } = await ferry.exports.list();
290
+ *
291
+ * // Filter by scope
292
+ * const { data } = await ferry.exports.list({ scopeId: 'user_123' });
293
+ *
294
+ * // Filter by status
295
+ * const { data } = await ferry.exports.list({ status: 'completed' });
296
+ *
297
+ * // Filter by connection
298
+ * const { data } = await ferry.exports.list({ connectionId: 'conn_abc123' });
299
+ * ```
300
+ */
301
+ list(params?: ListExportsParams): Promise<{
302
+ data: ExportResponse[];
303
+ meta: {
304
+ page: number;
305
+ limit: number;
306
+ total: number;
307
+ totalPages: number;
308
+ } | undefined;
309
+ }>;
310
+ /**
311
+ * Wait for an export to complete
312
+ *
313
+ * @example
314
+ * ```ts
315
+ * const exportJob = await ferry.exports.create({ scopeId: 'user_123' });
316
+ * const completed = await ferry.exports.poll(exportJob.id, { maxWait: 300000 });
317
+ *
318
+ * if (completed.status === 'completed') {
319
+ * console.log('Download:', completed.downloadUrl);
320
+ * }
321
+ * ```
322
+ */
323
+ poll(exportId: string, options?: {
324
+ maxWait?: number;
325
+ interval?: number;
326
+ }): Promise<ExportResponse>;
327
+ }
328
+
329
+ /**
330
+ * Database Connections resource
331
+ */
332
+
333
+ declare class Connections {
334
+ private readonly client;
335
+ constructor(client: Ferry);
336
+ /**
337
+ * List all database connections for the organization
338
+ *
339
+ * @example
340
+ * ```ts
341
+ * const connections = await ferry.connections.list();
342
+ * for (const conn of connections) {
343
+ * console.log(conn.name);
344
+ * }
345
+ * ```
346
+ */
347
+ list(): Promise<DatabaseConnection[]>;
348
+ /**
349
+ * Create a new database connection
350
+ *
351
+ * @example
352
+ * ```ts
353
+ * const connection = await ferry.connections.create({
354
+ * name: 'Production DB',
355
+ * host: 'db.example.com',
356
+ * port: '5432',
357
+ * database: 'myapp',
358
+ * user: 'ferry_readonly',
359
+ * password: 'secret',
360
+ * ssl: true,
361
+ * });
362
+ * ```
363
+ */
364
+ create(params: CreateConnectionRequest): Promise<DatabaseConnection>;
365
+ /**
366
+ * Get a database connection by ID
367
+ *
368
+ * @example
369
+ * ```ts
370
+ * const connection = await ferry.connections.retrieve('conn_abc123');
371
+ * console.log(connection.host, connection.database);
372
+ * ```
373
+ */
374
+ retrieve(connectionId: string): Promise<DatabaseConnection>;
375
+ /**
376
+ * Update a database connection
377
+ *
378
+ * @example
379
+ * ```ts
380
+ * const connection = await ferry.connections.update('conn_abc123', {
381
+ * name: 'Production DB (Updated)',
382
+ * });
383
+ * ```
384
+ */
385
+ update(connectionId: string, params: UpdateConnectionRequest): Promise<DatabaseConnection>;
386
+ /**
387
+ * Delete a database connection
388
+ *
389
+ * @example
390
+ * ```ts
391
+ * const result = await ferry.connections.delete('conn_abc123');
392
+ * console.log(result.deleted); // true
393
+ * ```
394
+ */
395
+ delete(connectionId: string): Promise<{
396
+ id: string;
397
+ deleted: boolean;
398
+ }>;
399
+ /**
400
+ * Test a database connection
401
+ *
402
+ * @example
403
+ * ```ts
404
+ * const result = await ferry.connections.test('conn_abc123');
405
+ * if (result.connected) {
406
+ * console.log(`Connected to ${result.database} as ${result.user}`);
407
+ * } else {
408
+ * console.error(`Connection failed: ${result.error}`);
409
+ * }
410
+ * ```
411
+ */
412
+ test(connectionId: string): Promise<TestConnectionResult>;
413
+ }
414
+
415
+ /**
416
+ * DataFerry SDK client
417
+ */
418
+
419
+ interface FerryConfig {
420
+ /** API key for authentication */
421
+ apiKey: string;
422
+ /** Base URL for the DataFerry API (default: https://api.dataferry.dev) */
423
+ baseUrl?: string;
424
+ /** Request timeout in milliseconds (default: 30000) */
425
+ timeout?: number;
426
+ }
427
+ interface ApiResponse<T> {
428
+ success: boolean;
429
+ data?: T;
430
+ error?: {
431
+ code: string;
432
+ message: string;
433
+ details?: Record<string, unknown>;
434
+ };
435
+ meta?: {
436
+ page: number;
437
+ limit: number;
438
+ total: number;
439
+ totalPages: number;
440
+ };
441
+ }
442
+ /**
443
+ * Parameters for creating a portal session
444
+ */
445
+ interface CreatePortalSessionParams {
446
+ /** Export profile name (required) */
447
+ profile: string;
448
+ /** The scope ID for data filtering (optional for single-tenant mode) */
449
+ scopeId?: string;
450
+ /** Return URL after export completes */
451
+ returnUrl?: string;
452
+ /** Custom session duration in seconds (default: 3600) */
453
+ expiresIn?: number;
454
+ /** End-user email for export completion notifications */
455
+ email?: string;
456
+ /** Custom metadata to attach to the session */
457
+ metadata?: Record<string, unknown>;
458
+ }
459
+ /**
460
+ * Portal session response
461
+ */
462
+ interface PortalSessionResult {
463
+ /** Session ID */
464
+ id: string;
465
+ /** URL to redirect the user to */
466
+ url: string;
467
+ /** When the session expires */
468
+ expiresAt: Date;
469
+ }
470
+ declare class Ferry {
471
+ private readonly apiKey;
472
+ private readonly baseUrl;
473
+ private readonly timeout;
474
+ /** Portal session management */
475
+ readonly portalSessions: PortalSessions;
476
+ /** Export management */
477
+ readonly exports: Exports;
478
+ /** Database connection management */
479
+ readonly connections: Connections;
480
+ constructor(config: FerryConfig);
481
+ /**
482
+ * Create a portal session for an end user to export their data.
483
+ *
484
+ * This is the primary method for initiating a data export. It creates a
485
+ * secure session and returns a URL where the user can select and download
486
+ * their data.
487
+ *
488
+ * @example
489
+ * ```typescript
490
+ * const ferry = new Ferry({ apiKey: 'your-api-key' });
491
+ *
492
+ * // Create a session for a specific user
493
+ * const session = await ferry.createPortalSession({
494
+ * profile: 'default',
495
+ * scopeId: 'user_123',
496
+ * returnUrl: 'https://app.example.com/settings',
497
+ * });
498
+ *
499
+ * // Redirect the user to the portal
500
+ * res.redirect(session.url);
501
+ * ```
502
+ *
503
+ * @example
504
+ * ```typescript
505
+ * // Single-tenant mode (no scopeId required)
506
+ * const session = await ferry.createPortalSession({
507
+ * profile: 'default',
508
+ * returnUrl: 'https://app.example.com/settings',
509
+ * });
510
+ * ```
511
+ */
512
+ createPortalSession(params: CreatePortalSessionParams): Promise<PortalSessionResult>;
513
+ /**
514
+ * Make an authenticated API request
515
+ */
516
+ request<T>(method: string, path: string, body?: unknown): Promise<T>;
517
+ /**
518
+ * Make a paginated API request
519
+ */
520
+ requestPaginated<T>(path: string, params?: Record<string, string | number | undefined>): Promise<{
521
+ data: T[];
522
+ meta: ApiResponse<T>['meta'];
523
+ }>;
524
+ }
525
+ /**
526
+ * DataFerry SDK error
527
+ */
528
+ declare class FerryError extends Error {
529
+ readonly code: string;
530
+ readonly status: number;
531
+ constructor(message: string, code: string, status: number);
532
+ }
533
+
534
+ export { Connections, type CreateConnectionRequest, type CreateExportRequest, type CreatePortalSessionParams, type CreatePortalSessionRequest, type CreatePortalSessionResponse, type DatabaseConnection, type ExportFormat, type ExportJob, type ExportStatus, Exports, Ferry, type FerryConfig, FerryError, type PortalSessionResult, PortalSessions, type SchemaConfig, type TestConnectionResult, type UpdateConnectionRequest, type WebhookEndpoint, type WebhookEvent };