@rynko/sdk 1.0.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,616 @@
1
+ /**
2
+ * Rynko SDK Types
3
+ */
4
+ interface RetryConfig {
5
+ /** Maximum number of retry attempts (default: 5) */
6
+ maxAttempts?: number;
7
+ /** Initial delay between retries in milliseconds (default: 1000) */
8
+ initialDelayMs?: number;
9
+ /** Maximum delay between retries in milliseconds (default: 30000) */
10
+ maxDelayMs?: number;
11
+ /** Maximum jitter to add to delay in milliseconds (default: 1000) */
12
+ maxJitterMs?: number;
13
+ /** HTTP status codes that should trigger a retry (default: [429, 503, 504]) */
14
+ retryableStatuses?: number[];
15
+ }
16
+ interface RynkoConfig {
17
+ /** API Key for authentication */
18
+ apiKey: string;
19
+ /** Base URL for the API (default: https://api.rynko.dev) */
20
+ baseUrl?: string;
21
+ /** Request timeout in milliseconds (default: 30000) */
22
+ timeout?: number;
23
+ /** Custom headers to include in requests */
24
+ headers?: Record<string, string>;
25
+ /** Retry configuration for failed requests */
26
+ retry?: RetryConfig | false;
27
+ }
28
+ interface GenerateDocumentOptions {
29
+ /** Template ID to use */
30
+ templateId: string;
31
+ /** Output format */
32
+ format: 'pdf' | 'excel' | 'csv';
33
+ /** Template variables for content generation */
34
+ variables?: Record<string, unknown>;
35
+ /** Custom filename (without extension) */
36
+ filename?: string;
37
+ /** Webhook URL to receive completion notification */
38
+ webhookUrl?: string;
39
+ /** Custom metadata to pass through to webhook */
40
+ metadata?: Record<string, unknown>;
41
+ /** Use draft version instead of published version (for testing) */
42
+ useDraft?: boolean;
43
+ /** Force use of purchased credits instead of free quota */
44
+ useCredit?: boolean;
45
+ }
46
+ interface GenerateBatchOptions {
47
+ /** Template ID to use */
48
+ templateId: string;
49
+ /** Output format */
50
+ format: 'pdf' | 'excel' | 'csv';
51
+ /** List of variable sets (one per document) - each object contains the variables for that document */
52
+ documents: Record<string, unknown>[];
53
+ /** Webhook URL to receive batch completion notification */
54
+ webhookUrl?: string;
55
+ /** Custom metadata for the batch */
56
+ metadata?: Record<string, unknown>;
57
+ /** Use draft version instead of published version (for testing) */
58
+ useDraft?: boolean;
59
+ /** Force use of purchased credits instead of free quota */
60
+ useCredit?: boolean;
61
+ }
62
+ /**
63
+ * Response from document generation request.
64
+ * Note: This is an async operation - the document is queued for generation.
65
+ * Use `waitForCompletion()` or poll `getJob()` to get the downloadUrl once ready.
66
+ */
67
+ interface GenerateDocumentResponse {
68
+ /** Job ID for tracking */
69
+ jobId: string;
70
+ /** Job status (will be 'queued' for new requests) */
71
+ status: DocumentJobStatus;
72
+ /** URL to check job status */
73
+ statusUrl: string;
74
+ /** Estimated wait time in seconds */
75
+ estimatedWaitSeconds: number;
76
+ }
77
+ /**
78
+ * Response from batch document generation request.
79
+ * Note: This is an async operation - documents are queued for generation.
80
+ * Use `getBatch()` to poll for completion status.
81
+ */
82
+ interface GenerateBatchResponse {
83
+ /** Batch ID for tracking */
84
+ batchId: string;
85
+ /** Batch status (will be 'queued' for new requests) */
86
+ status: string;
87
+ /** Total jobs in batch */
88
+ totalJobs: number;
89
+ /** URL to check batch status */
90
+ statusUrl: string;
91
+ /** Estimated wait time in seconds */
92
+ estimatedWaitSeconds: number;
93
+ }
94
+ interface DocumentJob {
95
+ /** Job ID */
96
+ jobId: string;
97
+ /** Job status */
98
+ status: DocumentJobStatus;
99
+ /** Output format */
100
+ format: 'pdf' | 'excel' | 'csv';
101
+ /** Template ID used */
102
+ templateId: string;
103
+ /** Template name */
104
+ templateName?: string;
105
+ /** Custom filename */
106
+ filename?: string;
107
+ /** Signed download URL (available when completed) */
108
+ downloadUrl?: string;
109
+ /** When download URL expires */
110
+ downloadUrlExpiresAt?: string;
111
+ /** File size in bytes */
112
+ fileSize?: number;
113
+ /** Error message (if failed) */
114
+ errorMessage?: string;
115
+ /** Error code (if failed) */
116
+ errorCode?: string;
117
+ /** Custom metadata */
118
+ metadata?: Record<string, unknown>;
119
+ /** Whether a webhook was configured for this job */
120
+ hasWebhook?: boolean;
121
+ /** Whether webhook was successfully delivered */
122
+ webhookSent?: boolean;
123
+ /** Webhook delivery error if failed */
124
+ webhookError?: string;
125
+ /** Created timestamp */
126
+ createdAt: string;
127
+ /** When processing started */
128
+ processingAt?: string;
129
+ /** Completed timestamp */
130
+ completedAt?: string;
131
+ /** When file expires from storage */
132
+ expiresAt?: string;
133
+ }
134
+ type DocumentJobStatus = 'queued' | 'processing' | 'completed' | 'failed';
135
+ interface ListDocumentJobsOptions {
136
+ /** Filter by status */
137
+ status?: DocumentJobStatus;
138
+ /** Filter by format */
139
+ format?: 'pdf' | 'excel' | 'csv';
140
+ /** Filter by template ID */
141
+ templateId?: string;
142
+ /** Filter by workspace ID */
143
+ workspaceId?: string;
144
+ /** Filter by date range start */
145
+ dateFrom?: string | Date;
146
+ /** Filter by date range end */
147
+ dateTo?: string | Date;
148
+ /** Number of results per page (default: 20) */
149
+ limit?: number;
150
+ /** Page number (default: 1) */
151
+ page?: number;
152
+ /** Offset for pagination */
153
+ offset?: number;
154
+ }
155
+ interface Template {
156
+ id: string;
157
+ name: string;
158
+ type: 'pdf' | 'excel';
159
+ description?: string;
160
+ variables?: TemplateVariable[];
161
+ createdAt: string;
162
+ updatedAt: string;
163
+ }
164
+ interface TemplateVariable {
165
+ name: string;
166
+ type: string;
167
+ required?: boolean;
168
+ defaultValue?: unknown;
169
+ }
170
+ interface ListTemplatesOptions {
171
+ /** Number of results per page (default: 20) */
172
+ limit?: number;
173
+ /** Page number (default: 1) */
174
+ page?: number;
175
+ /** Search by template name */
176
+ search?: string;
177
+ }
178
+ interface WebhookSubscription {
179
+ id: string;
180
+ url: string;
181
+ events: WebhookEventType[];
182
+ description?: string;
183
+ isActive: boolean;
184
+ secret?: string;
185
+ createdAt: string;
186
+ updatedAt: string;
187
+ }
188
+ type WebhookEventType = 'document.generated' | 'document.failed' | 'document.downloaded';
189
+ interface WebhookEvent {
190
+ id: string;
191
+ type: WebhookEventType;
192
+ timestamp: string;
193
+ data: Record<string, unknown>;
194
+ }
195
+ interface ApiResponse<T> {
196
+ success: boolean;
197
+ data: T;
198
+ meta?: PaginationMeta;
199
+ }
200
+ interface PaginationMeta {
201
+ total: number;
202
+ page: number;
203
+ limit: number;
204
+ totalPages: number;
205
+ }
206
+ interface ApiError {
207
+ success: false;
208
+ error: string;
209
+ message: string;
210
+ statusCode: number;
211
+ }
212
+ interface User {
213
+ id: string;
214
+ email: string;
215
+ name?: string;
216
+ teamId?: string;
217
+ teamName?: string;
218
+ workspaceId?: string;
219
+ workspaceName?: string;
220
+ }
221
+
222
+ /**
223
+ * HTTP Client for Rynko SDK
224
+ */
225
+
226
+ interface HttpClientConfig {
227
+ baseUrl: string;
228
+ apiKey: string;
229
+ timeout: number;
230
+ headers?: Record<string, string>;
231
+ retry?: RetryConfig | false;
232
+ }
233
+ declare class HttpClient {
234
+ private config;
235
+ private retryConfig;
236
+ constructor(config: HttpClientConfig);
237
+ /**
238
+ * Calculate delay for exponential backoff with jitter
239
+ */
240
+ private calculateDelay;
241
+ /**
242
+ * Parse Retry-After header value to milliseconds
243
+ */
244
+ private parseRetryAfter;
245
+ /**
246
+ * Check if the status code should trigger a retry
247
+ */
248
+ private shouldRetry;
249
+ /**
250
+ * Sleep for the specified duration
251
+ */
252
+ private sleep;
253
+ private request;
254
+ get<T>(path: string, query?: Record<string, unknown>): Promise<T>;
255
+ post<T>(path: string, body?: unknown): Promise<T>;
256
+ put<T>(path: string, body?: unknown): Promise<T>;
257
+ patch<T>(path: string, body?: unknown): Promise<T>;
258
+ delete<T>(path: string): Promise<T>;
259
+ }
260
+ declare class RynkoError extends Error {
261
+ code: string;
262
+ statusCode: number;
263
+ constructor(message: string, code: string, statusCode: number);
264
+ }
265
+
266
+ /**
267
+ * Documents Resource
268
+ */
269
+
270
+ declare class DocumentsResource {
271
+ private http;
272
+ constructor(http: HttpClient);
273
+ /**
274
+ * Generate a document from a template
275
+ *
276
+ * @example
277
+ * ```typescript
278
+ * const result = await rynko.documents.generate({
279
+ * templateId: 'tmpl_abc123',
280
+ * format: 'pdf',
281
+ * variables: {
282
+ * customerName: 'John Doe',
283
+ * invoiceNumber: 'INV-001',
284
+ * amount: 150.00,
285
+ * },
286
+ * });
287
+ * console.log('Job ID:', result.jobId);
288
+ * console.log('Download URL:', result.downloadUrl);
289
+ * ```
290
+ */
291
+ generate(options: GenerateDocumentOptions): Promise<GenerateDocumentResponse>;
292
+ /**
293
+ * Generate a PDF document from a template
294
+ *
295
+ * @example
296
+ * ```typescript
297
+ * const result = await rynko.documents.generatePdf({
298
+ * templateId: 'tmpl_invoice',
299
+ * variables: {
300
+ * invoiceNumber: 'INV-001',
301
+ * total: 99.99,
302
+ * },
303
+ * });
304
+ * ```
305
+ */
306
+ generatePdf(options: Omit<GenerateDocumentOptions, 'format'>): Promise<GenerateDocumentResponse>;
307
+ /**
308
+ * Generate an Excel document from a template
309
+ *
310
+ * @example
311
+ * ```typescript
312
+ * const result = await rynko.documents.generateExcel({
313
+ * templateId: 'tmpl_report',
314
+ * variables: {
315
+ * reportDate: '2025-01-15',
316
+ * data: [{ name: 'Item 1', value: 100 }],
317
+ * },
318
+ * });
319
+ * ```
320
+ */
321
+ generateExcel(options: Omit<GenerateDocumentOptions, 'format'>): Promise<GenerateDocumentResponse>;
322
+ /**
323
+ * Generate multiple documents in a batch
324
+ *
325
+ * @example
326
+ * ```typescript
327
+ * const result = await rynko.documents.generateBatch({
328
+ * templateId: 'tmpl_invoice',
329
+ * format: 'pdf',
330
+ * documents: [
331
+ * { variables: { invoiceNumber: 'INV-001', total: 99.99 } },
332
+ * { variables: { invoiceNumber: 'INV-002', total: 149.99 } },
333
+ * ],
334
+ * });
335
+ * console.log('Batch ID:', result.batchId);
336
+ * ```
337
+ */
338
+ generateBatch(options: GenerateBatchOptions): Promise<GenerateBatchResponse>;
339
+ /**
340
+ * Get a document job by ID
341
+ *
342
+ * @example
343
+ * ```typescript
344
+ * const job = await rynko.documents.getJob('job_abc123');
345
+ * console.log('Status:', job.status);
346
+ * if (job.status === 'completed') {
347
+ * console.log('Download:', job.downloadUrl);
348
+ * }
349
+ * ```
350
+ */
351
+ getJob(jobId: string): Promise<DocumentJob>;
352
+ /**
353
+ * List document jobs with optional filters
354
+ *
355
+ * @example
356
+ * ```typescript
357
+ * const { data, meta } = await rynko.documents.listJobs({
358
+ * status: 'completed',
359
+ * limit: 10,
360
+ * });
361
+ * console.log(`Found ${meta.total} jobs`);
362
+ * ```
363
+ */
364
+ listJobs(options?: ListDocumentJobsOptions): Promise<{
365
+ data: DocumentJob[];
366
+ meta: PaginationMeta;
367
+ }>;
368
+ /**
369
+ * Wait for a document job to complete
370
+ *
371
+ * @example
372
+ * ```typescript
373
+ * const result = await rynko.documents.generate({
374
+ * templateId: 'tmpl_invoice',
375
+ * format: 'pdf',
376
+ * variables: { invoiceNumber: 'INV-001' },
377
+ * });
378
+ *
379
+ * // Wait for completion (polls every 1 second, max 30 seconds)
380
+ * const completedJob = await rynko.documents.waitForCompletion(result.jobId);
381
+ * console.log('Download URL:', completedJob.downloadUrl);
382
+ * ```
383
+ */
384
+ waitForCompletion(jobId: string, options?: {
385
+ pollInterval?: number;
386
+ timeout?: number;
387
+ }): Promise<DocumentJob>;
388
+ }
389
+
390
+ /**
391
+ * Templates Resource
392
+ */
393
+
394
+ declare class TemplatesResource {
395
+ private http;
396
+ constructor(http: HttpClient);
397
+ /**
398
+ * Get a template by ID
399
+ *
400
+ * @example
401
+ * ```typescript
402
+ * const template = await rynko.templates.get('tmpl_abc123');
403
+ * console.log('Template:', template.name);
404
+ * console.log('Variables:', template.variables);
405
+ * ```
406
+ */
407
+ get(id: string): Promise<Template>;
408
+ /**
409
+ * List templates with optional filters
410
+ *
411
+ * @example
412
+ * ```typescript
413
+ * // List all templates
414
+ * const { data } = await rynko.templates.list();
415
+ *
416
+ * // List with pagination
417
+ * const { data, meta } = await rynko.templates.list({ page: 1, limit: 10 });
418
+ * ```
419
+ */
420
+ list(options?: ListTemplatesOptions): Promise<{
421
+ data: Template[];
422
+ meta: PaginationMeta;
423
+ }>;
424
+ /**
425
+ * List only PDF templates
426
+ *
427
+ * Note: Filtering by type is done client-side based on outputFormats.
428
+ *
429
+ * @example
430
+ * ```typescript
431
+ * const { data } = await rynko.templates.listPdf();
432
+ * ```
433
+ */
434
+ listPdf(options?: Omit<ListTemplatesOptions, 'type'>): Promise<{
435
+ data: Template[];
436
+ meta: PaginationMeta;
437
+ }>;
438
+ /**
439
+ * List only Excel templates
440
+ *
441
+ * Note: Filtering by type is done client-side based on outputFormats.
442
+ *
443
+ * @example
444
+ * ```typescript
445
+ * const { data } = await rynko.templates.listExcel();
446
+ * ```
447
+ */
448
+ listExcel(options?: Omit<ListTemplatesOptions, 'type'>): Promise<{
449
+ data: Template[];
450
+ meta: PaginationMeta;
451
+ }>;
452
+ }
453
+
454
+ /**
455
+ * Webhooks Resource
456
+ *
457
+ * Provides read-only access to webhook subscriptions and signature verification.
458
+ * Webhook subscriptions are managed through the Rynko dashboard.
459
+ */
460
+
461
+ declare class WebhooksResource {
462
+ private http;
463
+ constructor(http: HttpClient);
464
+ /**
465
+ * Get a webhook subscription by ID
466
+ *
467
+ * @example
468
+ * ```typescript
469
+ * const webhook = await rynko.webhooks.get('wh_abc123');
470
+ * console.log('Events:', webhook.events);
471
+ * ```
472
+ */
473
+ get(id: string): Promise<WebhookSubscription>;
474
+ /**
475
+ * List all webhook subscriptions
476
+ *
477
+ * @example
478
+ * ```typescript
479
+ * const { data } = await rynko.webhooks.list();
480
+ * console.log('Active webhooks:', data.filter(w => w.isActive).length);
481
+ * ```
482
+ */
483
+ list(): Promise<{
484
+ data: WebhookSubscription[];
485
+ meta: PaginationMeta;
486
+ }>;
487
+ }
488
+
489
+ /**
490
+ * Rynko SDK Client
491
+ */
492
+
493
+ declare class Rynko {
494
+ private http;
495
+ /** Document generation operations */
496
+ documents: DocumentsResource;
497
+ /** Template operations */
498
+ templates: TemplatesResource;
499
+ /** Webhook operations */
500
+ webhooks: WebhooksResource;
501
+ /**
502
+ * Create a new Rynko client
503
+ *
504
+ * @example
505
+ * ```typescript
506
+ * import { Rynko } from '@rynko/sdk';
507
+ *
508
+ * const rynko = new Rynko({
509
+ * apiKey: process.env.RYNKO_API_KEY!,
510
+ * });
511
+ *
512
+ * // Generate a PDF
513
+ * const result = await rynko.documents.generate({
514
+ * templateId: 'tmpl_invoice',
515
+ * format: 'pdf',
516
+ * variables: { invoiceNumber: 'INV-001' },
517
+ * });
518
+ * ```
519
+ */
520
+ constructor(config: RynkoConfig);
521
+ /**
522
+ * Get the current authenticated user
523
+ *
524
+ * @example
525
+ * ```typescript
526
+ * const user = await rynko.me();
527
+ * console.log('Authenticated as:', user.email);
528
+ * ```
529
+ */
530
+ me(): Promise<User>;
531
+ /**
532
+ * Verify the API key is valid
533
+ *
534
+ * @example
535
+ * ```typescript
536
+ * const isValid = await rynko.verifyApiKey();
537
+ * if (!isValid) {
538
+ * throw new Error('Invalid API key');
539
+ * }
540
+ * ```
541
+ */
542
+ verifyApiKey(): Promise<boolean>;
543
+ }
544
+ /**
545
+ * Create a Rynko client
546
+ *
547
+ * @example
548
+ * ```typescript
549
+ * import { createClient } from '@rynko/sdk';
550
+ *
551
+ * const rynko = createClient({
552
+ * apiKey: process.env.RYNKO_API_KEY!,
553
+ * });
554
+ * ```
555
+ */
556
+ declare function createClient(config: RynkoConfig): Rynko;
557
+
558
+ /**
559
+ * Webhook Signature Verification Utilities
560
+ */
561
+
562
+ interface VerifyWebhookOptions {
563
+ /** Raw request body as string */
564
+ payload: string;
565
+ /** Signature from X-Rynko-Signature header */
566
+ signature: string;
567
+ /** Webhook secret from your subscription */
568
+ secret: string;
569
+ /** Timestamp tolerance in seconds (default: 300 = 5 minutes) */
570
+ tolerance?: number;
571
+ }
572
+ interface ParsedWebhookSignature {
573
+ timestamp: number;
574
+ signature: string;
575
+ }
576
+ /**
577
+ * Parse the webhook signature header
578
+ */
579
+ declare function parseSignatureHeader(header: string): ParsedWebhookSignature;
580
+ /**
581
+ * Compute the expected signature for a webhook payload
582
+ */
583
+ declare function computeSignature(timestamp: number, payload: string, secret: string): string;
584
+ /**
585
+ * Verify a webhook signature
586
+ *
587
+ * @example
588
+ * ```typescript
589
+ * import { verifyWebhookSignature } from '@rynko/sdk';
590
+ *
591
+ * app.post('/webhooks/rynko', (req, res) => {
592
+ * const signature = req.headers['x-rynko-signature'];
593
+ *
594
+ * try {
595
+ * const event = verifyWebhookSignature({
596
+ * payload: req.body, // raw body string
597
+ * signature,
598
+ * secret: process.env.WEBHOOK_SECRET,
599
+ * });
600
+ *
601
+ * // Process the verified event
602
+ * console.log('Received event:', event.type);
603
+ * res.status(200).send('OK');
604
+ * } catch (error) {
605
+ * console.error('Invalid signature:', error);
606
+ * res.status(400).send('Invalid signature');
607
+ * }
608
+ * });
609
+ * ```
610
+ */
611
+ declare function verifyWebhookSignature(options: VerifyWebhookOptions): WebhookEvent;
612
+ declare class WebhookSignatureError extends Error {
613
+ constructor(message: string);
614
+ }
615
+
616
+ export { type ApiError, type ApiResponse, type DocumentJob, type DocumentJobStatus, DocumentsResource, type GenerateBatchOptions, type GenerateBatchResponse, type GenerateDocumentOptions, type GenerateDocumentResponse, type ListDocumentJobsOptions, type ListTemplatesOptions, type PaginationMeta, type RetryConfig, Rynko, type RynkoConfig, RynkoError, type Template, type TemplateVariable, TemplatesResource, type User, type VerifyWebhookOptions, type WebhookEvent, type WebhookEventType, WebhookSignatureError, type WebhookSubscription, WebhooksResource, computeSignature, createClient, parseSignatureHeader, verifyWebhookSignature };