@rynko/sdk 1.2.0 → 1.2.2
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/README.md +50 -27
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -77,7 +77,7 @@ console.log('Download URL:', completed.downloadUrl);
|
|
|
77
77
|
- **PDF generation** - Generate PDF documents from templates
|
|
78
78
|
- **Excel generation** - Generate Excel spreadsheets from templates
|
|
79
79
|
- **Batch generation** - Generate multiple documents in a single request
|
|
80
|
-
- **
|
|
80
|
+
- **Environment support** - Generate documents in specific environments
|
|
81
81
|
- **Webhook verification** - Secure HMAC signature verification for incoming webhooks
|
|
82
82
|
- **Polling utility** - Built-in `waitForCompletion()` method with configurable timeout
|
|
83
83
|
- **Automatic retries** - Configurable retry logic for transient failures
|
|
@@ -104,7 +104,7 @@ const rynko = new Rynko({
|
|
|
104
104
|
// Verify authentication
|
|
105
105
|
const user = await rynko.me();
|
|
106
106
|
console.log('Authenticated as:', user.email);
|
|
107
|
-
console.log('
|
|
107
|
+
console.log('Project:', user.teamName);
|
|
108
108
|
```
|
|
109
109
|
|
|
110
110
|
### Verify API Key
|
|
@@ -189,7 +189,6 @@ const job = await rynko.documents.generate({
|
|
|
189
189
|
|
|
190
190
|
// Optional settings
|
|
191
191
|
filename: 'contract-acme-2026', // Custom filename (without extension)
|
|
192
|
-
workspaceId: 'ws_abc123', // Generate in specific workspace
|
|
193
192
|
webhookUrl: 'https://your-app.com/webhooks/document-ready', // Webhook notification
|
|
194
193
|
metadata: { // Custom metadata (passed to webhook)
|
|
195
194
|
orderId: 'ORD-12345',
|
|
@@ -205,25 +204,31 @@ const job = await rynko.documents.generate({
|
|
|
205
204
|
Generate multiple documents from a single template:
|
|
206
205
|
|
|
207
206
|
```typescript
|
|
208
|
-
// Each object in the documents array
|
|
207
|
+
// Each object in the documents array requires a `variables` property
|
|
209
208
|
const batch = await rynko.documents.generateBatch({
|
|
210
209
|
templateId: 'tmpl_invoice',
|
|
211
210
|
format: 'pdf',
|
|
212
211
|
documents: [
|
|
213
212
|
{
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
213
|
+
variables: {
|
|
214
|
+
invoiceNumber: 'INV-001',
|
|
215
|
+
customerName: 'John Doe',
|
|
216
|
+
total: 150.00,
|
|
217
|
+
},
|
|
217
218
|
},
|
|
218
219
|
{
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
220
|
+
variables: {
|
|
221
|
+
invoiceNumber: 'INV-002',
|
|
222
|
+
customerName: 'Jane Smith',
|
|
223
|
+
total: 275.50,
|
|
224
|
+
},
|
|
222
225
|
},
|
|
223
226
|
{
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
+
variables: {
|
|
228
|
+
invoiceNumber: 'INV-003',
|
|
229
|
+
customerName: 'Bob Wilson',
|
|
230
|
+
total: 89.99,
|
|
231
|
+
},
|
|
227
232
|
},
|
|
228
233
|
],
|
|
229
234
|
webhookUrl: 'https://your-app.com/webhooks/batch-complete',
|
|
@@ -317,7 +322,7 @@ const { data: invoiceJobs } = await rynko.documents.listJobs({
|
|
|
317
322
|
templateId: 'tmpl_invoice',
|
|
318
323
|
});
|
|
319
324
|
|
|
320
|
-
// Filter by
|
|
325
|
+
// Filter by environment
|
|
321
326
|
const { data: workspaceJobs } = await rynko.documents.listJobs({
|
|
322
327
|
workspaceId: 'ws_abc123',
|
|
323
328
|
});
|
|
@@ -432,14 +437,15 @@ import { verifyWebhookSignature, WebhookSignatureError } from '@rynko/sdk';
|
|
|
432
437
|
// Express.js example
|
|
433
438
|
app.post('/webhooks/rynko', express.raw({ type: 'application/json' }), (req, res) => {
|
|
434
439
|
const signature = req.headers['x-rynko-signature'] as string;
|
|
435
|
-
const timestamp = req.headers['x-rynko-timestamp'] as string;
|
|
436
440
|
|
|
437
441
|
try {
|
|
442
|
+
// The signature header contains both timestamp and signature: t=<ts>,v1=<hex>
|
|
443
|
+
// Timestamp is validated automatically (default tolerance: 5 minutes)
|
|
438
444
|
const event = verifyWebhookSignature({
|
|
439
445
|
payload: req.body.toString(),
|
|
440
446
|
signature,
|
|
441
|
-
timestamp, // Optional but recommended for replay protection
|
|
442
447
|
secret: process.env.WEBHOOK_SECRET!,
|
|
448
|
+
tolerance: 300, // Optional: tolerance in seconds (default: 300)
|
|
443
449
|
});
|
|
444
450
|
|
|
445
451
|
// Process the verified event
|
|
@@ -459,8 +465,8 @@ app.post('/webhooks/rynko', express.raw({ type: 'application/json' }), (req, res
|
|
|
459
465
|
break;
|
|
460
466
|
|
|
461
467
|
case 'document.failed':
|
|
462
|
-
const { jobId: failedJobId,
|
|
463
|
-
console.error(`Document ${failedJobId} failed: ${
|
|
468
|
+
const { jobId: failedJobId, errorMessage, errorCode, metadata: failedMeta } = event.data;
|
|
469
|
+
console.error(`Document ${failedJobId} failed: ${errorMessage}`);
|
|
464
470
|
// Access metadata for correlation
|
|
465
471
|
if (failedMeta) {
|
|
466
472
|
console.log(`Failed order: ${failedMeta.orderId}`);
|
|
@@ -468,9 +474,14 @@ app.post('/webhooks/rynko', express.raw({ type: 'application/json' }), (req, res
|
|
|
468
474
|
// Handle failure (retry, notify user, etc.)
|
|
469
475
|
break;
|
|
470
476
|
|
|
477
|
+
case 'batch.completed':
|
|
478
|
+
const { batchId, totalJobs, completedJobs, failedJobs } = event.data;
|
|
479
|
+
console.log(`Batch ${batchId} done: ${completedJobs}/${totalJobs} succeeded, ${failedJobs} failed`);
|
|
480
|
+
break;
|
|
481
|
+
|
|
471
482
|
case 'document.downloaded':
|
|
472
|
-
const { jobId: downloadedJobId } = event.data;
|
|
473
|
-
console.log(`Document ${downloadedJobId}
|
|
483
|
+
const { jobId: downloadedJobId, downloadedAt } = event.data;
|
|
484
|
+
console.log(`Document ${downloadedJobId} downloaded at ${downloadedAt}`);
|
|
474
485
|
break;
|
|
475
486
|
|
|
476
487
|
default:
|
|
@@ -495,8 +506,9 @@ app.post('/webhooks/rynko', express.raw({ type: 'application/json' }), (req, res
|
|
|
495
506
|
| Event | Description | Payload |
|
|
496
507
|
|-------|-------------|---------|
|
|
497
508
|
| `document.generated` | Document successfully generated | `jobId`, `templateId`, `format`, `downloadUrl`, `fileSize`, `metadata` |
|
|
498
|
-
| `document.failed` | Document generation failed | `jobId`, `templateId`, `
|
|
509
|
+
| `document.failed` | Document generation failed | `jobId`, `templateId`, `errorMessage`, `errorCode`, `metadata` |
|
|
499
510
|
| `document.downloaded` | Document was downloaded | `jobId`, `downloadedAt` |
|
|
511
|
+
| `batch.completed` | Batch generation finished | `batchId`, `templateId`, `format`, `totalJobs`, `completedJobs`, `failedJobs`, `metadata` |
|
|
500
512
|
|
|
501
513
|
#### Webhook Headers
|
|
502
514
|
|
|
@@ -504,7 +516,7 @@ Rynko sends these headers with each webhook request:
|
|
|
504
516
|
|
|
505
517
|
| Header | Description |
|
|
506
518
|
|--------|-------------|
|
|
507
|
-
| `X-Rynko-Signature` | HMAC-SHA256 signature (format: `v1=<hex>`) |
|
|
519
|
+
| `X-Rynko-Signature` | HMAC-SHA256 signature (format: `t=<timestamp>,v1=<hex>`) |
|
|
508
520
|
| `X-Rynko-Timestamp` | Unix timestamp when the webhook was sent |
|
|
509
521
|
| `X-Rynko-Event-Id` | Unique event identifier |
|
|
510
522
|
| `X-Rynko-Event-Type` | Event type (e.g., `document.generated`) |
|
|
@@ -516,14 +528,14 @@ For advanced use cases, you can use the low-level signature utilities:
|
|
|
516
528
|
```typescript
|
|
517
529
|
import { parseSignatureHeader, computeSignature } from '@rynko/sdk';
|
|
518
530
|
|
|
519
|
-
// Parse the signature header
|
|
520
|
-
const { timestamp,
|
|
531
|
+
// Parse the signature header (format: t=<timestamp>,v1=<hex>)
|
|
532
|
+
const { timestamp, signature } = parseSignatureHeader(signatureHeader);
|
|
521
533
|
|
|
522
534
|
// Compute expected signature
|
|
523
535
|
const expectedSignature = computeSignature(timestamp, payload, secret);
|
|
524
536
|
|
|
525
537
|
// Compare signatures
|
|
526
|
-
const isValid =
|
|
538
|
+
const isValid = signature === expectedSignature;
|
|
527
539
|
```
|
|
528
540
|
|
|
529
541
|
## Configuration
|
|
@@ -543,6 +555,17 @@ const rynko = new Rynko({
|
|
|
543
555
|
headers: {
|
|
544
556
|
'X-Custom-Header': 'value',
|
|
545
557
|
},
|
|
558
|
+
|
|
559
|
+
// Optional: Retry configuration (enabled by default)
|
|
560
|
+
retry: {
|
|
561
|
+
maxAttempts: 5, // Maximum retry attempts (default: 5)
|
|
562
|
+
initialDelayMs: 1000, // Initial delay between retries (default: 1000)
|
|
563
|
+
maxDelayMs: 30000, // Maximum delay between retries (default: 30000)
|
|
564
|
+
maxJitterMs: 1000, // Maximum jitter to add (default: 1000)
|
|
565
|
+
retryableStatuses: [429, 503, 504], // HTTP status codes to retry (default)
|
|
566
|
+
},
|
|
567
|
+
// Or disable retry entirely:
|
|
568
|
+
// retry: false,
|
|
546
569
|
});
|
|
547
570
|
```
|
|
548
571
|
|
|
@@ -675,7 +698,7 @@ const options: GenerateDocumentOptions = {
|
|
|
675
698
|
invoiceNumber: 'INV-001',
|
|
676
699
|
items: [{ name: 'Widget', price: 29.99 }],
|
|
677
700
|
},
|
|
678
|
-
|
|
701
|
+
metadata: { orderId: 'ORD-12345' }, // Optional: custom metadata
|
|
679
702
|
};
|
|
680
703
|
|
|
681
704
|
const result: GenerateDocumentResponse = await rynko.documents.generate(options);
|
|
@@ -723,7 +746,7 @@ const result: GenerateDocumentResponse = await rynko.documents.generate(options)
|
|
|
723
746
|
| Function | Returns | Description |
|
|
724
747
|
|----------|---------|-------------|
|
|
725
748
|
| `verifyWebhookSignature(options)` | `WebhookEvent` | Verify signature and parse webhook event |
|
|
726
|
-
| `parseSignatureHeader(header)` | `{ timestamp:
|
|
749
|
+
| `parseSignatureHeader(header)` | `{ timestamp: number; signature: string }` | Parse signature header |
|
|
727
750
|
| `computeSignature(timestamp, payload, secret)` | `string` | Compute expected signature |
|
|
728
751
|
|
|
729
752
|
## Examples
|
package/dist/index.d.mts
CHANGED
|
@@ -159,7 +159,7 @@ interface ListDocumentJobsOptions {
|
|
|
159
159
|
format?: 'pdf' | 'excel' | 'csv';
|
|
160
160
|
/** Filter by template ID */
|
|
161
161
|
templateId?: string;
|
|
162
|
-
/** Filter by
|
|
162
|
+
/** Filter by environment ID */
|
|
163
163
|
workspaceId?: string;
|
|
164
164
|
/** Filter by date range start */
|
|
165
165
|
dateFrom?: string | Date;
|
|
@@ -205,7 +205,7 @@ interface WebhookSubscription {
|
|
|
205
205
|
createdAt: string;
|
|
206
206
|
updatedAt: string;
|
|
207
207
|
}
|
|
208
|
-
type WebhookEventType = 'document.
|
|
208
|
+
type WebhookEventType = 'document.generated' | 'document.failed' | 'document.downloaded' | 'batch.completed';
|
|
209
209
|
/** Data payload for document webhook events */
|
|
210
210
|
interface DocumentWebhookData {
|
|
211
211
|
/** Job ID */
|
package/dist/index.d.ts
CHANGED
|
@@ -159,7 +159,7 @@ interface ListDocumentJobsOptions {
|
|
|
159
159
|
format?: 'pdf' | 'excel' | 'csv';
|
|
160
160
|
/** Filter by template ID */
|
|
161
161
|
templateId?: string;
|
|
162
|
-
/** Filter by
|
|
162
|
+
/** Filter by environment ID */
|
|
163
163
|
workspaceId?: string;
|
|
164
164
|
/** Filter by date range start */
|
|
165
165
|
dateFrom?: string | Date;
|
|
@@ -205,7 +205,7 @@ interface WebhookSubscription {
|
|
|
205
205
|
createdAt: string;
|
|
206
206
|
updatedAt: string;
|
|
207
207
|
}
|
|
208
|
-
type WebhookEventType = 'document.
|
|
208
|
+
type WebhookEventType = 'document.generated' | 'document.failed' | 'document.downloaded' | 'batch.completed';
|
|
209
209
|
/** Data payload for document webhook events */
|
|
210
210
|
interface DocumentWebhookData {
|
|
211
211
|
/** Job ID */
|