@spike-forms/sdk 0.2.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.
package/dist/index.js ADDED
@@ -0,0 +1,1569 @@
1
+ 'use strict';
2
+
3
+ // src/errors.ts
4
+ var SpikeError = class extends Error {
5
+ /** HTTP status code from the API response */
6
+ statusCode;
7
+ /** Error code from the API (e.g., 'INVALID_API_KEY', 'FORM_NOT_FOUND') */
8
+ code;
9
+ /** Request ID for debugging and support purposes */
10
+ requestId;
11
+ constructor(message, options) {
12
+ super(message);
13
+ this.name = "SpikeError";
14
+ this.statusCode = options?.statusCode;
15
+ this.code = options?.code;
16
+ this.requestId = options?.requestId;
17
+ if (Error.captureStackTrace) {
18
+ Error.captureStackTrace(this, this.constructor);
19
+ }
20
+ }
21
+ };
22
+ var AuthenticationError = class extends SpikeError {
23
+ constructor(message, options) {
24
+ super(message, { statusCode: 401, ...options });
25
+ this.name = "AuthenticationError";
26
+ }
27
+ };
28
+ var NotFoundError = class extends SpikeError {
29
+ constructor(message, options) {
30
+ super(message, { statusCode: 404, ...options });
31
+ this.name = "NotFoundError";
32
+ }
33
+ };
34
+ var RateLimitError = class extends SpikeError {
35
+ /** Number of seconds to wait before retrying the request */
36
+ retryAfter;
37
+ constructor(message, options) {
38
+ super(message, { statusCode: 429, code: options?.code, requestId: options?.requestId });
39
+ this.name = "RateLimitError";
40
+ this.retryAfter = options?.retryAfter;
41
+ }
42
+ };
43
+ var ValidationError = class extends SpikeError {
44
+ /** Field-specific validation error details */
45
+ details;
46
+ constructor(message, options) {
47
+ super(message, { statusCode: 400, code: options?.code, requestId: options?.requestId });
48
+ this.name = "ValidationError";
49
+ this.details = options?.details;
50
+ }
51
+ };
52
+ var NetworkError = class extends SpikeError {
53
+ constructor(message, options) {
54
+ super(message, { code: options?.code, requestId: options?.requestId });
55
+ this.name = "NetworkError";
56
+ }
57
+ };
58
+
59
+ // src/http.ts
60
+ var HttpClient = class {
61
+ apiKey;
62
+ baseUrl;
63
+ timeout;
64
+ constructor(config) {
65
+ this.apiKey = config.apiKey;
66
+ this.baseUrl = config.baseUrl;
67
+ this.timeout = config.timeout;
68
+ }
69
+ /**
70
+ * Make a GET request
71
+ */
72
+ async get(path, options) {
73
+ return this.request("GET", path, void 0, options);
74
+ }
75
+ /**
76
+ * Make a POST request with authentication
77
+ */
78
+ async post(path, body, options) {
79
+ return this.request("POST", path, body, options);
80
+ }
81
+ /**
82
+ * Make a PATCH request
83
+ */
84
+ async patch(path, body, options) {
85
+ return this.request("PATCH", path, body, options);
86
+ }
87
+ /**
88
+ * Make a PUT request
89
+ */
90
+ async put(path, body, options) {
91
+ return this.request("PUT", path, body, options);
92
+ }
93
+ /**
94
+ * Make a DELETE request
95
+ */
96
+ async delete(path, options) {
97
+ return this.request("DELETE", path, void 0, options);
98
+ }
99
+ /**
100
+ * Make a POST request without authentication (for public form submissions)
101
+ */
102
+ async postPublic(path, body, options) {
103
+ return this.request("POST", path, body, options, false);
104
+ }
105
+ /**
106
+ * Build a URL with query parameters
107
+ */
108
+ buildUrl(path, params) {
109
+ const url = new URL(path, this.baseUrl);
110
+ if (params) {
111
+ for (const [key, value] of Object.entries(params)) {
112
+ if (value !== void 0) {
113
+ url.searchParams.append(key, String(value));
114
+ }
115
+ }
116
+ }
117
+ return url.toString();
118
+ }
119
+ /**
120
+ * Make an HTTP request with timeout and error handling
121
+ */
122
+ async request(method, path, body, options, authenticated = true) {
123
+ const url = this.buildUrl(path, options?.params);
124
+ const controller = new AbortController();
125
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
126
+ try {
127
+ const headers = {
128
+ ...options?.headers
129
+ };
130
+ if (authenticated) {
131
+ headers["Authorization"] = `Bearer ${this.apiKey}`;
132
+ }
133
+ if (body !== void 0) {
134
+ headers["Content-Type"] = "application/json";
135
+ }
136
+ const response = await fetch(url, {
137
+ method,
138
+ headers,
139
+ body: body !== void 0 ? JSON.stringify(body) : void 0,
140
+ signal: controller.signal
141
+ });
142
+ clearTimeout(timeoutId);
143
+ if (!response.ok) {
144
+ await this.handleErrorResponse(response);
145
+ }
146
+ const text = await response.text();
147
+ if (!text) {
148
+ return {};
149
+ }
150
+ return JSON.parse(text);
151
+ } catch (error) {
152
+ clearTimeout(timeoutId);
153
+ if (error instanceof Error && error.name === "AbortError") {
154
+ throw new NetworkError(`Request timeout after ${this.timeout}ms`);
155
+ }
156
+ if (error instanceof SpikeError) {
157
+ throw error;
158
+ }
159
+ if (error instanceof Error) {
160
+ throw new NetworkError(error.message);
161
+ }
162
+ throw new NetworkError("An unknown network error occurred");
163
+ }
164
+ }
165
+ /**
166
+ * Handle error responses and throw appropriate SDK errors
167
+ */
168
+ async handleErrorResponse(response) {
169
+ let errorData = {};
170
+ const requestId = response.headers.get("x-request-id") ?? void 0;
171
+ try {
172
+ const text = await response.text();
173
+ if (text) {
174
+ errorData = JSON.parse(text);
175
+ }
176
+ } catch {
177
+ }
178
+ const message = errorData.error || errorData.message || response.statusText || "Request failed";
179
+ const code = errorData.code;
180
+ switch (response.status) {
181
+ case 400:
182
+ throw new ValidationError(message, {
183
+ code,
184
+ requestId,
185
+ details: errorData.details
186
+ });
187
+ case 401:
188
+ throw new AuthenticationError(message, {
189
+ code,
190
+ requestId
191
+ });
192
+ case 404:
193
+ throw new NotFoundError(message, {
194
+ code,
195
+ requestId
196
+ });
197
+ case 429: {
198
+ const retryAfterHeader = response.headers.get("Retry-After");
199
+ const retryAfter = retryAfterHeader ? parseInt(retryAfterHeader, 10) : void 0;
200
+ throw new RateLimitError(message, {
201
+ code,
202
+ requestId,
203
+ retryAfter: Number.isNaN(retryAfter) ? void 0 : retryAfter
204
+ });
205
+ }
206
+ default:
207
+ throw new SpikeError(message, {
208
+ statusCode: response.status,
209
+ code,
210
+ requestId
211
+ });
212
+ }
213
+ }
214
+ };
215
+
216
+ // src/resources/forms.ts
217
+ var FormsResource = class {
218
+ http;
219
+ /**
220
+ * Create a new FormsResource instance
221
+ * @param http - The HTTP client to use for API requests
222
+ */
223
+ constructor(http) {
224
+ this.http = http;
225
+ }
226
+ /**
227
+ * List all forms with optional pagination and filtering.
228
+ *
229
+ * @param params - Optional parameters for filtering and pagination
230
+ * @param params.limit - Maximum number of forms to return
231
+ * @param params.offset - Number of forms to skip for pagination
232
+ * @param params.project_id - Filter forms by project ID
233
+ * @param params.include_inactive - Include inactive forms in the results
234
+ * @returns Promise resolving to an array of forms
235
+ *
236
+ * @example
237
+ * ```typescript
238
+ * // Get all forms
239
+ * const forms = await client.forms.list();
240
+ *
241
+ * // Get forms with pagination
242
+ * const forms = await client.forms.list({ limit: 10, offset: 20 });
243
+ *
244
+ * // Get forms for a specific project
245
+ * const forms = await client.forms.list({ project_id: 'proj_123' });
246
+ *
247
+ * // Include inactive forms
248
+ * const forms = await client.forms.list({ include_inactive: true });
249
+ * ```
250
+ *
251
+ * @see Requirements 4.1
252
+ */
253
+ async list(params) {
254
+ return this.http.get("/forms", {
255
+ params
256
+ });
257
+ }
258
+ /**
259
+ * Create a new form.
260
+ *
261
+ * @param data - The form data to create
262
+ * @param data.name - Display name for the form (required)
263
+ * @param data.project_id - ID of the project to add the form to (optional)
264
+ * @returns Promise resolving to the created form
265
+ *
266
+ * @example
267
+ * ```typescript
268
+ * // Create a simple form
269
+ * const form = await client.forms.create({ name: 'Contact Form' });
270
+ *
271
+ * // Create a form in a project
272
+ * const form = await client.forms.create({
273
+ * name: 'Feedback Form',
274
+ * project_id: 'proj_123'
275
+ * });
276
+ * ```
277
+ *
278
+ * @see Requirements 4.2
279
+ */
280
+ async create(data) {
281
+ return this.http.post("/forms", data);
282
+ }
283
+ /**
284
+ * Get a single form by ID.
285
+ *
286
+ * @param id - The unique identifier of the form
287
+ * @returns Promise resolving to the form
288
+ * @throws NotFoundError if the form does not exist
289
+ *
290
+ * @example
291
+ * ```typescript
292
+ * const form = await client.forms.get('form_123');
293
+ * console.log(form.name, form.submission_count);
294
+ * ```
295
+ *
296
+ * @see Requirements 4.3
297
+ */
298
+ async get(id) {
299
+ return this.http.get(`/forms/${id}`);
300
+ }
301
+ /**
302
+ * Update a form's properties.
303
+ *
304
+ * @param id - The unique identifier of the form to update
305
+ * @param data - The properties to update
306
+ * @param data.name - New display name for the form
307
+ * @param data.project_id - ID of the project to move the form to (or null to remove from project)
308
+ * @param data.is_active - Whether the form should be active
309
+ * @returns Promise resolving to the updated form
310
+ * @throws NotFoundError if the form does not exist
311
+ *
312
+ * @example
313
+ * ```typescript
314
+ * // Update form name
315
+ * const form = await client.forms.update('form_123', { name: 'New Name' });
316
+ *
317
+ * // Deactivate a form
318
+ * const form = await client.forms.update('form_123', { is_active: false });
319
+ *
320
+ * // Move form to a different project
321
+ * const form = await client.forms.update('form_123', { project_id: 'proj_456' });
322
+ * ```
323
+ *
324
+ * @see Requirements 4.4
325
+ */
326
+ async update(id, data) {
327
+ return this.http.patch(`/forms/${id}`, data);
328
+ }
329
+ /**
330
+ * Delete a form by ID.
331
+ *
332
+ * @param id - The unique identifier of the form to delete
333
+ * @returns Promise resolving to a success response
334
+ * @throws NotFoundError if the form does not exist
335
+ *
336
+ * @example
337
+ * ```typescript
338
+ * await client.forms.delete('form_123');
339
+ * ```
340
+ *
341
+ * @see Requirements 4.5
342
+ */
343
+ async delete(id) {
344
+ return this.http.delete(`/forms/${id}`);
345
+ }
346
+ /**
347
+ * Submit data to a form. This is a public endpoint that does not require authentication.
348
+ *
349
+ * @param slug - The URL-friendly slug of the form
350
+ * @param data - The form data to submit as key-value pairs
351
+ * @returns Promise resolving to the submission response
352
+ * @throws NotFoundError if the form does not exist
353
+ * @throws ValidationError if the form is inactive or data is invalid
354
+ *
355
+ * @example
356
+ * ```typescript
357
+ * // Submit to a contact form
358
+ * const result = await client.forms.submit('contact-form', {
359
+ * name: 'John Doe',
360
+ * email: 'john@example.com',
361
+ * message: 'Hello!'
362
+ * });
363
+ *
364
+ * if (result.success) {
365
+ * console.log('Submission ID:', result.submission_id);
366
+ * }
367
+ * ```
368
+ *
369
+ * @see Requirements 4.6
370
+ */
371
+ async submit(slug, data) {
372
+ return this.http.postPublic(`/f/${slug}`, data);
373
+ }
374
+ /**
375
+ * Get the HTML template for a form.
376
+ *
377
+ * Returns the stored HTML from S3 or a default template if none exists.
378
+ *
379
+ * @param id - The unique identifier of the form
380
+ * @returns Promise resolving to the HTML content
381
+ * @throws NotFoundError if the form does not exist
382
+ *
383
+ * @example
384
+ * ```typescript
385
+ * const { html } = await client.forms.getHtml('form_123');
386
+ * console.log(html);
387
+ * ```
388
+ */
389
+ async getHtml(id) {
390
+ return this.http.get(`/forms/${id}/html`);
391
+ }
392
+ /**
393
+ * Save HTML template for a form to S3 storage.
394
+ *
395
+ * @param id - The unique identifier of the form
396
+ * @param html - The HTML content to save
397
+ * @returns Promise resolving to the save response with the S3 URL
398
+ * @throws NotFoundError if the form does not exist
399
+ *
400
+ * @example
401
+ * ```typescript
402
+ * const result = await client.forms.saveHtml('form_123', '<html>...</html>');
403
+ * if (result.success) {
404
+ * console.log('Saved to:', result.html_url);
405
+ * }
406
+ * ```
407
+ */
408
+ async saveHtml(id, html) {
409
+ return this.http.put(`/forms/${id}/html`, { html });
410
+ }
411
+ };
412
+
413
+ // src/resources/submissions.ts
414
+ var SubmissionsResource = class {
415
+ http;
416
+ /**
417
+ * Create a new SubmissionsResource instance
418
+ * @param http - The HTTP client to use for API requests
419
+ */
420
+ constructor(http) {
421
+ this.http = http;
422
+ }
423
+ /**
424
+ * List submissions for a form with optional filtering and pagination.
425
+ *
426
+ * @param formId - The unique identifier of the form
427
+ * @param params - Optional parameters for filtering and pagination
428
+ * @param params.limit - Maximum number of submissions to return
429
+ * @param params.offset - Number of submissions to skip for pagination
430
+ * @param params.since - Only return submissions created after this ISO 8601 timestamp
431
+ * @param params.order - Sort order for submissions ('asc' or 'desc')
432
+ * @param params.filter - Filter string for searching submissions
433
+ * @param params.is_spam - Filter by spam status
434
+ * @param params.is_read - Filter by read status
435
+ * @returns Promise resolving to an array of submissions
436
+ * @throws NotFoundError if the form does not exist
437
+ *
438
+ * @example
439
+ * ```typescript
440
+ * // Get all submissions for a form
441
+ * const submissions = await client.submissions.list('form_123');
442
+ *
443
+ * // Get submissions with pagination
444
+ * const submissions = await client.submissions.list('form_123', {
445
+ * limit: 10,
446
+ * offset: 20
447
+ * });
448
+ *
449
+ * // Get unread submissions
450
+ * const unread = await client.submissions.list('form_123', {
451
+ * is_read: false
452
+ * });
453
+ *
454
+ * // Get non-spam submissions since a date
455
+ * const recent = await client.submissions.list('form_123', {
456
+ * since: '2024-01-01T00:00:00Z',
457
+ * is_spam: false,
458
+ * order: 'desc'
459
+ * });
460
+ *
461
+ * // Search submissions
462
+ * const filtered = await client.submissions.list('form_123', {
463
+ * filter: 'john@example.com'
464
+ * });
465
+ * ```
466
+ *
467
+ * @see Requirements 5.1
468
+ */
469
+ async list(formId, params) {
470
+ return this.http.get(`/forms/${formId}/submissions`, {
471
+ params
472
+ });
473
+ }
474
+ /**
475
+ * Get submission statistics for a form.
476
+ *
477
+ * @param formId - The unique identifier of the form
478
+ * @returns Promise resolving to submission statistics
479
+ * @throws NotFoundError if the form does not exist
480
+ *
481
+ * @example
482
+ * ```typescript
483
+ * const stats = await client.submissions.getStats('form_123');
484
+ * console.log(`Total: ${stats.total}, Unread: ${stats.unread}, Spam: ${stats.spam}`);
485
+ * console.log(`Today: ${stats.today}, This week: ${stats.this_week}`);
486
+ * ```
487
+ *
488
+ * @see Requirements 5.2
489
+ */
490
+ async getStats(formId) {
491
+ return this.http.get(`/forms/${formId}/submissions/stats`);
492
+ }
493
+ /**
494
+ * Export all submissions for a form as JSON.
495
+ *
496
+ * @param formId - The unique identifier of the form
497
+ * @returns Promise resolving to an array of all submissions
498
+ * @throws NotFoundError if the form does not exist
499
+ *
500
+ * @example
501
+ * ```typescript
502
+ * // Export all submissions
503
+ * const allSubmissions = await client.submissions.export('form_123');
504
+ *
505
+ * // Process exported data
506
+ * for (const submission of allSubmissions) {
507
+ * console.log(submission.data);
508
+ * }
509
+ * ```
510
+ *
511
+ * @see Requirements 5.3
512
+ */
513
+ async export(formId) {
514
+ return this.http.get(`/forms/${formId}/submissions/export`);
515
+ }
516
+ /**
517
+ * Perform a bulk update operation on multiple submissions.
518
+ *
519
+ * @param formId - The unique identifier of the form
520
+ * @param data - The bulk update request
521
+ * @param data.action - The action to perform ('markRead', 'markUnread', 'star', 'unstar', 'markSpam', 'notSpam')
522
+ * @param data.submission_ids - Array of submission IDs to update
523
+ * @returns Promise resolving to a success response
524
+ * @throws NotFoundError if the form does not exist
525
+ * @throws ValidationError if the action is invalid or submission IDs are empty
526
+ *
527
+ * @example
528
+ * ```typescript
529
+ * // Mark submissions as read
530
+ * await client.submissions.bulkUpdate('form_123', {
531
+ * action: 'markRead',
532
+ * submission_ids: ['sub_1', 'sub_2', 'sub_3']
533
+ * });
534
+ *
535
+ * // Star submissions
536
+ * await client.submissions.bulkUpdate('form_123', {
537
+ * action: 'star',
538
+ * submission_ids: ['sub_1']
539
+ * });
540
+ *
541
+ * // Mark submissions as spam
542
+ * await client.submissions.bulkUpdate('form_123', {
543
+ * action: 'markSpam',
544
+ * submission_ids: ['sub_4', 'sub_5']
545
+ * });
546
+ *
547
+ * // Mark submissions as not spam
548
+ * await client.submissions.bulkUpdate('form_123', {
549
+ * action: 'notSpam',
550
+ * submission_ids: ['sub_6']
551
+ * });
552
+ * ```
553
+ *
554
+ * @see Requirements 5.4
555
+ */
556
+ async bulkUpdate(formId, data) {
557
+ return this.http.post(`/forms/${formId}/submissions/bulk`, data);
558
+ }
559
+ /**
560
+ * Delete multiple submissions from a form.
561
+ *
562
+ * @param formId - The unique identifier of the form
563
+ * @param submissionIds - Array of submission IDs to delete
564
+ * @returns Promise resolving to a success response
565
+ * @throws NotFoundError if the form does not exist
566
+ * @throws ValidationError if submission IDs are empty
567
+ *
568
+ * @example
569
+ * ```typescript
570
+ * // Delete multiple submissions
571
+ * await client.submissions.bulkDelete('form_123', ['sub_1', 'sub_2', 'sub_3']);
572
+ * ```
573
+ *
574
+ * @see Requirements 5.5
575
+ */
576
+ async bulkDelete(formId, submissionIds) {
577
+ return this.http.delete(`/forms/${formId}/submissions/bulk`, {
578
+ params: {
579
+ ids: submissionIds.join(",")
580
+ }
581
+ });
582
+ }
583
+ };
584
+
585
+ // src/resources/rules.ts
586
+ var RulesResource = class {
587
+ http;
588
+ /**
589
+ * Create a new RulesResource instance
590
+ * @param http - The HTTP client to use for API requests
591
+ */
592
+ constructor(http) {
593
+ this.http = http;
594
+ }
595
+ /**
596
+ * List all rules for a form.
597
+ *
598
+ * @param formId - The unique identifier of the form
599
+ * @returns Promise resolving to an array of rules
600
+ * @throws NotFoundError if the form does not exist
601
+ *
602
+ * @example
603
+ * ```typescript
604
+ * // Get all rules for a form
605
+ * const rules = await client.rules.list('form_123');
606
+ *
607
+ * // Filter active rules
608
+ * const activeRules = rules.filter(rule => rule.is_active);
609
+ *
610
+ * // Check rule conditions
611
+ * for (const rule of rules) {
612
+ * console.log(`Rule: ${rule.name}, Conditions: ${rule.conditions.length}`);
613
+ * }
614
+ * ```
615
+ *
616
+ * @see Requirements 6.1
617
+ */
618
+ async list(formId) {
619
+ return this.http.get(`/forms/${formId}/rules`);
620
+ }
621
+ /**
622
+ * Create a new rule for a form.
623
+ *
624
+ * @param formId - The unique identifier of the form
625
+ * @param data - The rule data to create
626
+ * @param data.name - Display name for the rule (required)
627
+ * @param data.conditions - Array of conditions that must be met (required)
628
+ * @param data.actions - Array of actions to take when conditions are met (required)
629
+ * @param data.is_active - Whether the rule should be active (defaults to true)
630
+ * @returns Promise resolving to the created rule
631
+ * @throws NotFoundError if the form does not exist
632
+ * @throws ValidationError if the rule data is invalid
633
+ *
634
+ * @example
635
+ * ```typescript
636
+ * // Create a simple email notification rule
637
+ * const rule = await client.rules.create('form_123', {
638
+ * name: 'Notify on VIP submission',
639
+ * conditions: [
640
+ * { field: 'email', operator: 'ends_with', value: '@vip.com' }
641
+ * ],
642
+ * actions: [
643
+ * { type: 'email', config: { to: 'sales@company.com', subject: 'VIP Lead!' } }
644
+ * ]
645
+ * });
646
+ *
647
+ * // Create a webhook rule with multiple conditions
648
+ * const webhookRule = await client.rules.create('form_123', {
649
+ * name: 'Send to CRM',
650
+ * conditions: [
651
+ * { field: 'type', operator: 'equals', value: 'enterprise' },
652
+ * { field: 'budget', operator: 'contains', value: '10000' }
653
+ * ],
654
+ * actions: [
655
+ * { type: 'webhook', config: { url: 'https://crm.example.com/leads' } }
656
+ * ],
657
+ * is_active: true
658
+ * });
659
+ *
660
+ * // Create an inactive rule (for testing)
661
+ * const testRule = await client.rules.create('form_123', {
662
+ * name: 'Test Rule',
663
+ * conditions: [{ field: 'test', operator: 'equals', value: 'true' }],
664
+ * actions: [{ type: 'slack', config: { channel: '#test' } }],
665
+ * is_active: false
666
+ * });
667
+ * ```
668
+ *
669
+ * @see Requirements 6.2
670
+ */
671
+ async create(formId, data) {
672
+ return this.http.post(`/forms/${formId}/rules`, data);
673
+ }
674
+ /**
675
+ * Update a rule's properties.
676
+ *
677
+ * @param formId - The unique identifier of the form
678
+ * @param ruleId - The unique identifier of the rule to update
679
+ * @param data - The properties to update
680
+ * @param data.name - New display name for the rule
681
+ * @param data.conditions - New conditions for the rule
682
+ * @param data.actions - New actions for the rule
683
+ * @param data.is_active - Whether the rule should be active
684
+ * @returns Promise resolving to the updated rule
685
+ * @throws NotFoundError if the form or rule does not exist
686
+ * @throws ValidationError if the update data is invalid
687
+ *
688
+ * @example
689
+ * ```typescript
690
+ * // Update rule name
691
+ * const rule = await client.rules.update('form_123', 'rule_456', {
692
+ * name: 'Updated Rule Name'
693
+ * });
694
+ *
695
+ * // Deactivate a rule
696
+ * const rule = await client.rules.update('form_123', 'rule_456', {
697
+ * is_active: false
698
+ * });
699
+ *
700
+ * // Update conditions
701
+ * const rule = await client.rules.update('form_123', 'rule_456', {
702
+ * conditions: [
703
+ * { field: 'email', operator: 'contains', value: '@newdomain.com' }
704
+ * ]
705
+ * });
706
+ *
707
+ * // Update actions
708
+ * const rule = await client.rules.update('form_123', 'rule_456', {
709
+ * actions: [
710
+ * { type: 'discord', config: { webhook_url: 'https://discord.com/api/webhooks/...' } }
711
+ * ]
712
+ * });
713
+ *
714
+ * // Update multiple properties at once
715
+ * const rule = await client.rules.update('form_123', 'rule_456', {
716
+ * name: 'New Name',
717
+ * is_active: true,
718
+ * conditions: [{ field: 'status', operator: 'equals', value: 'urgent' }],
719
+ * actions: [{ type: 'email', config: { to: 'urgent@company.com' } }]
720
+ * });
721
+ * ```
722
+ *
723
+ * @see Requirements 6.3
724
+ */
725
+ async update(formId, ruleId, data) {
726
+ return this.http.patch(`/forms/${formId}/rules/${ruleId}`, data);
727
+ }
728
+ /**
729
+ * Delete a rule by ID.
730
+ *
731
+ * @param formId - The unique identifier of the form
732
+ * @param ruleId - The unique identifier of the rule to delete
733
+ * @returns Promise resolving to a success response
734
+ * @throws NotFoundError if the form or rule does not exist
735
+ *
736
+ * @example
737
+ * ```typescript
738
+ * // Delete a rule
739
+ * await client.rules.delete('form_123', 'rule_456');
740
+ *
741
+ * // Delete multiple rules
742
+ * const ruleIds = ['rule_1', 'rule_2', 'rule_3'];
743
+ * for (const ruleId of ruleIds) {
744
+ * await client.rules.delete('form_123', ruleId);
745
+ * }
746
+ * ```
747
+ *
748
+ * @see Requirements 6.4
749
+ */
750
+ async delete(formId, ruleId) {
751
+ return this.http.delete(`/forms/${formId}/rules/${ruleId}`);
752
+ }
753
+ };
754
+
755
+ // src/resources/projects.ts
756
+ var ProjectsResource = class {
757
+ http;
758
+ /**
759
+ * Create a new ProjectsResource instance
760
+ * @param http - The HTTP client to use for API requests
761
+ */
762
+ constructor(http) {
763
+ this.http = http;
764
+ }
765
+ /**
766
+ * List all projects.
767
+ *
768
+ * @returns Promise resolving to an array of projects
769
+ *
770
+ * @example
771
+ * ```typescript
772
+ * const projects = await client.projects.list();
773
+ * console.log(`Found ${projects.length} projects`);
774
+ * ```
775
+ *
776
+ * @see Requirements 7.1
777
+ */
778
+ async list() {
779
+ const response = await this.http.get("/projects");
780
+ return response.projects;
781
+ }
782
+ /**
783
+ * Create a new project.
784
+ *
785
+ * @param data - The project data to create
786
+ * @param data.name - Display name for the project (required)
787
+ * @returns Promise resolving to the created project
788
+ *
789
+ * @example
790
+ * ```typescript
791
+ * const project = await client.projects.create({ name: 'Marketing Forms' });
792
+ * console.log('Created project:', project.id);
793
+ * ```
794
+ *
795
+ * @see Requirements 7.2
796
+ */
797
+ async create(data) {
798
+ return this.http.post("/projects", data);
799
+ }
800
+ /**
801
+ * Get a single project by ID.
802
+ *
803
+ * @param id - The unique identifier of the project
804
+ * @returns Promise resolving to the project
805
+ * @throws NotFoundError if the project does not exist
806
+ *
807
+ * @example
808
+ * ```typescript
809
+ * const project = await client.projects.get('proj_123');
810
+ * console.log(project.name, project.form_count);
811
+ * ```
812
+ *
813
+ * @see Requirements 7.3
814
+ */
815
+ async get(id) {
816
+ return this.http.get(`/projects/${id}`);
817
+ }
818
+ /**
819
+ * Update a project's properties.
820
+ *
821
+ * @param id - The unique identifier of the project to update
822
+ * @param data - The properties to update
823
+ * @param data.name - New display name for the project
824
+ * @returns Promise resolving to the updated project
825
+ * @throws NotFoundError if the project does not exist
826
+ *
827
+ * @example
828
+ * ```typescript
829
+ * const project = await client.projects.update('proj_123', { name: 'New Name' });
830
+ * console.log('Updated project:', project.name);
831
+ * ```
832
+ *
833
+ * @see Requirements 7.4
834
+ */
835
+ async update(id, data) {
836
+ return this.http.patch(`/projects/${id}`, data);
837
+ }
838
+ /**
839
+ * Delete a project by ID.
840
+ *
841
+ * @param id - The unique identifier of the project to delete
842
+ * @returns Promise resolving to a success response
843
+ * @throws NotFoundError if the project does not exist
844
+ *
845
+ * @example
846
+ * ```typescript
847
+ * await client.projects.delete('proj_123');
848
+ * ```
849
+ *
850
+ * @see Requirements 7.5
851
+ */
852
+ async delete(id) {
853
+ return this.http.delete(`/projects/${id}`);
854
+ }
855
+ };
856
+
857
+ // src/resources/teams.ts
858
+ var TeamsResource = class {
859
+ http;
860
+ /**
861
+ * Create a new TeamsResource instance
862
+ * @param http - The HTTP client to use for API requests
863
+ */
864
+ constructor(http) {
865
+ this.http = http;
866
+ }
867
+ /**
868
+ * List all teams.
869
+ *
870
+ * @returns Promise resolving to an array of teams
871
+ *
872
+ * @example
873
+ * ```typescript
874
+ * const teams = await client.teams.list();
875
+ * console.log(`Found ${teams.length} teams`);
876
+ * ```
877
+ *
878
+ * @see Requirements 8.1
879
+ */
880
+ async list() {
881
+ return this.http.get("/teams");
882
+ }
883
+ /**
884
+ * Create a new team.
885
+ *
886
+ * @param data - The team data to create
887
+ * @param data.name - Display name for the team (required)
888
+ * @returns Promise resolving to the created team
889
+ *
890
+ * @example
891
+ * ```typescript
892
+ * const team = await client.teams.create({ name: 'Marketing Team' });
893
+ * console.log('Created team:', team.id);
894
+ * ```
895
+ *
896
+ * @see Requirements 8.2
897
+ */
898
+ async create(data) {
899
+ return this.http.post("/teams", data);
900
+ }
901
+ /**
902
+ * Get a single team by ID.
903
+ *
904
+ * @param id - The unique identifier of the team
905
+ * @returns Promise resolving to the team
906
+ * @throws NotFoundError if the team does not exist
907
+ *
908
+ * @example
909
+ * ```typescript
910
+ * const team = await client.teams.get('team_123');
911
+ * console.log(team.name, team.member_count);
912
+ * ```
913
+ *
914
+ * @see Requirements 8.3
915
+ */
916
+ async get(id) {
917
+ return this.http.get(`/teams/${id}`);
918
+ }
919
+ /**
920
+ * Update a team's properties.
921
+ *
922
+ * @param id - The unique identifier of the team to update
923
+ * @param data - The properties to update
924
+ * @param data.name - New display name for the team
925
+ * @returns Promise resolving to the updated team
926
+ * @throws NotFoundError if the team does not exist
927
+ *
928
+ * @example
929
+ * ```typescript
930
+ * const team = await client.teams.update('team_123', { name: 'New Name' });
931
+ * console.log('Updated team:', team.name);
932
+ * ```
933
+ *
934
+ * @see Requirements 8.4
935
+ */
936
+ async update(id, data) {
937
+ return this.http.patch(`/teams/${id}`, data);
938
+ }
939
+ /**
940
+ * Delete a team by ID.
941
+ *
942
+ * @param id - The unique identifier of the team to delete
943
+ * @returns Promise resolving to a success response
944
+ * @throws NotFoundError if the team does not exist
945
+ *
946
+ * @example
947
+ * ```typescript
948
+ * await client.teams.delete('team_123');
949
+ * ```
950
+ *
951
+ * @see Requirements 8.5
952
+ */
953
+ async delete(id) {
954
+ return this.http.delete(`/teams/${id}`);
955
+ }
956
+ /**
957
+ * List all members of a team.
958
+ *
959
+ * @param teamId - The unique identifier of the team
960
+ * @returns Promise resolving to an array of team members
961
+ * @throws NotFoundError if the team does not exist
962
+ *
963
+ * @example
964
+ * ```typescript
965
+ * const members = await client.teams.listMembers('team_123');
966
+ * members.forEach(member => {
967
+ * console.log(`${member.user.name} (${member.role})`);
968
+ * });
969
+ * ```
970
+ *
971
+ * @see Requirements 8.6
972
+ */
973
+ async listMembers(teamId) {
974
+ return this.http.get(`/teams/${teamId}/members`);
975
+ }
976
+ /**
977
+ * Add a user to a team.
978
+ *
979
+ * @param teamId - The unique identifier of the team
980
+ * @param data - The member data
981
+ * @param data.email - Email address of the user to add
982
+ * @param data.role - Role to assign ('admin' or 'member')
983
+ * @returns Promise resolving to the created team member
984
+ * @throws NotFoundError if the team does not exist
985
+ * @throws ValidationError if the user is already a member
986
+ *
987
+ * @example
988
+ * ```typescript
989
+ * const member = await client.teams.addMember('team_123', {
990
+ * email: 'user@example.com',
991
+ * role: 'member'
992
+ * });
993
+ * console.log('Added member:', member.user.name);
994
+ * ```
995
+ *
996
+ * @see Requirements 8.7
997
+ */
998
+ async addMember(teamId, data) {
999
+ return this.http.post(`/teams/${teamId}/members`, data);
1000
+ }
1001
+ /**
1002
+ * Update a team member's role.
1003
+ *
1004
+ * @param teamId - The unique identifier of the team
1005
+ * @param memberId - The unique identifier of the team member
1006
+ * @param data - The properties to update
1007
+ * @param data.role - New role for the member ('admin' or 'member')
1008
+ * @returns Promise resolving to the updated team member
1009
+ * @throws NotFoundError if the team or member does not exist
1010
+ *
1011
+ * @example
1012
+ * ```typescript
1013
+ * const member = await client.teams.updateMember('team_123', 'member_456', {
1014
+ * role: 'admin'
1015
+ * });
1016
+ * console.log('Updated role to:', member.role);
1017
+ * ```
1018
+ *
1019
+ * @see Requirements 8.8
1020
+ */
1021
+ async updateMember(teamId, memberId, data) {
1022
+ return this.http.patch(`/teams/${teamId}/members/${memberId}`, data);
1023
+ }
1024
+ /**
1025
+ * Remove a member from a team.
1026
+ *
1027
+ * @param teamId - The unique identifier of the team
1028
+ * @param memberId - The unique identifier of the team member to remove
1029
+ * @returns Promise resolving to a success response
1030
+ * @throws NotFoundError if the team or member does not exist
1031
+ *
1032
+ * @example
1033
+ * ```typescript
1034
+ * await client.teams.removeMember('team_123', 'member_456');
1035
+ * ```
1036
+ *
1037
+ * @see Requirements 8.9
1038
+ */
1039
+ async removeMember(teamId, memberId) {
1040
+ return this.http.delete(`/teams/${teamId}/members/${memberId}`);
1041
+ }
1042
+ /**
1043
+ * List all pending invitations for a team.
1044
+ *
1045
+ * @param teamId - The unique identifier of the team
1046
+ * @returns Promise resolving to an array of pending invitations
1047
+ * @throws NotFoundError if the team does not exist
1048
+ *
1049
+ * @example
1050
+ * ```typescript
1051
+ * const invitations = await client.teams.listInvitations('team_123');
1052
+ * invitations.forEach(inv => {
1053
+ * console.log(`${inv.email} invited as ${inv.role}`);
1054
+ * });
1055
+ * ```
1056
+ *
1057
+ * @see Requirements 8.10
1058
+ */
1059
+ async listInvitations(teamId) {
1060
+ return this.http.get(`/teams/${teamId}/invitations`);
1061
+ }
1062
+ /**
1063
+ * Create a new invitation to join a team.
1064
+ *
1065
+ * @param teamId - The unique identifier of the team
1066
+ * @param data - The invitation data
1067
+ * @param data.email - Email address of the person to invite
1068
+ * @param data.role - Role to assign upon acceptance ('admin' or 'member')
1069
+ * @returns Promise resolving to the created invitation
1070
+ * @throws NotFoundError if the team does not exist
1071
+ * @throws ValidationError if an invitation already exists for this email
1072
+ *
1073
+ * @example
1074
+ * ```typescript
1075
+ * const invitation = await client.teams.invite('team_123', {
1076
+ * email: 'newuser@example.com',
1077
+ * role: 'member'
1078
+ * });
1079
+ * console.log('Invitation token:', invitation.token);
1080
+ * ```
1081
+ *
1082
+ * @see Requirements 8.11
1083
+ */
1084
+ async invite(teamId, data) {
1085
+ return this.http.post(`/teams/${teamId}/invitations`, data);
1086
+ }
1087
+ /**
1088
+ * Cancel a pending invitation.
1089
+ *
1090
+ * @param teamId - The unique identifier of the team
1091
+ * @param invitationId - The unique identifier of the invitation to cancel
1092
+ * @returns Promise resolving to a success response
1093
+ * @throws NotFoundError if the team or invitation does not exist
1094
+ *
1095
+ * @example
1096
+ * ```typescript
1097
+ * await client.teams.cancelInvitation('team_123', 'inv_456');
1098
+ * ```
1099
+ *
1100
+ * @see Requirements 8.12
1101
+ */
1102
+ async cancelInvitation(teamId, invitationId) {
1103
+ return this.http.delete(`/teams/${teamId}/invitations/${invitationId}`);
1104
+ }
1105
+ /**
1106
+ * Accept a team invitation using the invitation token.
1107
+ *
1108
+ * @param token - The unique invitation token
1109
+ * @returns Promise resolving to a success response
1110
+ * @throws NotFoundError if the invitation does not exist or has expired
1111
+ *
1112
+ * @example
1113
+ * ```typescript
1114
+ * await client.teams.acceptInvitation('inv_token_abc123');
1115
+ * ```
1116
+ *
1117
+ * @see Requirements 8.13
1118
+ */
1119
+ async acceptInvitation(token) {
1120
+ return this.http.post(`/invitations/${token}/accept`);
1121
+ }
1122
+ };
1123
+
1124
+ // src/resources/user.ts
1125
+ var UserResource = class {
1126
+ http;
1127
+ /**
1128
+ * Create a new UserResource instance
1129
+ * @param http - The HTTP client to use for API requests
1130
+ */
1131
+ constructor(http) {
1132
+ this.http = http;
1133
+ }
1134
+ /**
1135
+ * Get the current user profile.
1136
+ *
1137
+ * @returns Promise resolving to the current user
1138
+ *
1139
+ * @example
1140
+ * ```typescript
1141
+ * const user = await client.user.get();
1142
+ * console.log(`Hello, ${user.name}!`);
1143
+ * console.log(`2FA enabled: ${user.two_factor_enabled}`);
1144
+ * ```
1145
+ *
1146
+ * @see Requirements 9.1
1147
+ */
1148
+ async get() {
1149
+ return this.http.get("/user");
1150
+ }
1151
+ /**
1152
+ * Update the current user's profile properties.
1153
+ *
1154
+ * @param data - The properties to update
1155
+ * @param data.name - New display name for the user
1156
+ * @param data.email - New email address for the user
1157
+ * @returns Promise resolving to the updated user
1158
+ *
1159
+ * @example
1160
+ * ```typescript
1161
+ * const user = await client.user.update({ name: 'New Name' });
1162
+ * console.log('Updated name:', user.name);
1163
+ * ```
1164
+ *
1165
+ * @see Requirements 9.2
1166
+ */
1167
+ async update(data) {
1168
+ return this.http.patch("/user", data);
1169
+ }
1170
+ /**
1171
+ * Delete the current user's account.
1172
+ *
1173
+ * This action is irreversible and will delete all associated data.
1174
+ *
1175
+ * @returns Promise resolving to a success response
1176
+ *
1177
+ * @example
1178
+ * ```typescript
1179
+ * await client.user.delete();
1180
+ * console.log('Account deleted');
1181
+ * ```
1182
+ *
1183
+ * @see Requirements 9.3
1184
+ */
1185
+ async delete() {
1186
+ return this.http.delete("/user");
1187
+ }
1188
+ /**
1189
+ * Initiate two-factor authentication setup.
1190
+ *
1191
+ * Returns a secret and QR code for configuring an authenticator app.
1192
+ *
1193
+ * @returns Promise resolving to the 2FA setup response with secret and QR code
1194
+ *
1195
+ * @example
1196
+ * ```typescript
1197
+ * const setup = await client.user.setup2FA();
1198
+ * console.log('Secret:', setup.secret);
1199
+ * console.log('QR Code:', setup.qr_code);
1200
+ * // Display QR code to user for scanning with authenticator app
1201
+ * ```
1202
+ *
1203
+ * @see Requirements 9.4
1204
+ */
1205
+ async setup2FA() {
1206
+ return this.http.post("/user/2fa/setup");
1207
+ }
1208
+ /**
1209
+ * Enable two-factor authentication with a verification code.
1210
+ *
1211
+ * Call this after setup2FA to confirm the user has configured their
1212
+ * authenticator app correctly.
1213
+ *
1214
+ * @param code - The 6-digit verification code from the authenticator app
1215
+ * @returns Promise resolving to a success response
1216
+ * @throws ValidationError if the code is invalid
1217
+ *
1218
+ * @example
1219
+ * ```typescript
1220
+ * await client.user.enable2FA('123456');
1221
+ * console.log('2FA enabled successfully');
1222
+ * ```
1223
+ *
1224
+ * @see Requirements 9.5
1225
+ */
1226
+ async enable2FA(code) {
1227
+ return this.http.post("/user/2fa/enable", { code });
1228
+ }
1229
+ /**
1230
+ * Disable two-factor authentication.
1231
+ *
1232
+ * Requires a valid verification code to confirm the user's identity.
1233
+ *
1234
+ * @param code - The 6-digit verification code from the authenticator app
1235
+ * @returns Promise resolving to a success response
1236
+ * @throws ValidationError if the code is invalid
1237
+ *
1238
+ * @example
1239
+ * ```typescript
1240
+ * await client.user.disable2FA('123456');
1241
+ * console.log('2FA disabled');
1242
+ * ```
1243
+ *
1244
+ * @see Requirements 9.6
1245
+ */
1246
+ async disable2FA(code) {
1247
+ return this.http.post("/user/2fa/disable", { code });
1248
+ }
1249
+ /**
1250
+ * Verify a two-factor authentication code.
1251
+ *
1252
+ * Use this to verify a 2FA code during login or sensitive operations.
1253
+ *
1254
+ * @param code - The 6-digit verification code from the authenticator app
1255
+ * @returns Promise resolving to a success response
1256
+ * @throws ValidationError if the code is invalid
1257
+ *
1258
+ * @example
1259
+ * ```typescript
1260
+ * await client.user.verify2FA('123456');
1261
+ * console.log('2FA code verified');
1262
+ * ```
1263
+ *
1264
+ * @see Requirements 9.7
1265
+ */
1266
+ async verify2FA(code) {
1267
+ return this.http.post("/user/2fa/verify", { code });
1268
+ }
1269
+ /**
1270
+ * List all API keys for the current user.
1271
+ *
1272
+ * Note: The `key` field will only contain the full key value when
1273
+ * the key is first created. For existing keys, it may be masked.
1274
+ *
1275
+ * @returns Promise resolving to an array of API keys
1276
+ *
1277
+ * @example
1278
+ * ```typescript
1279
+ * const keys = await client.user.listApiKeys();
1280
+ * keys.forEach(key => {
1281
+ * console.log(`${key.name}: last used ${key.last_used_at || 'never'}`);
1282
+ * });
1283
+ * ```
1284
+ *
1285
+ * @see Requirements 9.8
1286
+ */
1287
+ async listApiKeys() {
1288
+ const response = await this.http.get("/user/api-keys");
1289
+ return response.apiKeys;
1290
+ }
1291
+ /**
1292
+ * Create a new API key.
1293
+ *
1294
+ * The returned API key will include the full key value in the `key` field.
1295
+ * This is the only time the full key is available - store it securely.
1296
+ *
1297
+ * @param data - The API key data
1298
+ * @param data.name - Display name for the API key (required)
1299
+ * @returns Promise resolving to the created API key with full key value
1300
+ *
1301
+ * @example
1302
+ * ```typescript
1303
+ * const apiKey = await client.user.createApiKey({ name: 'My Application' });
1304
+ * console.log('API Key created:', apiKey.key);
1305
+ * // Store this key securely - it won't be shown again!
1306
+ * ```
1307
+ *
1308
+ * @see Requirements 9.9
1309
+ */
1310
+ async createApiKey(data) {
1311
+ const response = await this.http.post("/user/api-keys", data);
1312
+ return response.apiKey;
1313
+ }
1314
+ /**
1315
+ * Delete an API key by ID.
1316
+ *
1317
+ * @param id - The unique identifier of the API key to delete
1318
+ * @returns Promise resolving to a success response
1319
+ * @throws NotFoundError if the API key does not exist
1320
+ *
1321
+ * @example
1322
+ * ```typescript
1323
+ * await client.user.deleteApiKey('key_123');
1324
+ * console.log('API key deleted');
1325
+ * ```
1326
+ *
1327
+ * @see Requirements 9.10
1328
+ */
1329
+ async deleteApiKey(id) {
1330
+ return this.http.delete(`/user/api-keys/${id}`);
1331
+ }
1332
+ };
1333
+
1334
+ // src/resources/billing.ts
1335
+ var BillingResource = class {
1336
+ http;
1337
+ /**
1338
+ * Create a new BillingResource instance
1339
+ * @param http - The HTTP client to use for API requests
1340
+ */
1341
+ constructor(http) {
1342
+ this.http = http;
1343
+ }
1344
+ /**
1345
+ * Create a Stripe checkout session for starting a new subscription.
1346
+ *
1347
+ * Returns a URL that the user should be redirected to in order to
1348
+ * complete the checkout process on Stripe's hosted checkout page.
1349
+ *
1350
+ * @param data - The checkout session configuration
1351
+ * @param data.price_id - The Stripe price ID for the subscription plan
1352
+ * @param data.success_url - URL to redirect to after successful checkout
1353
+ * @param data.cancel_url - URL to redirect to if checkout is cancelled
1354
+ * @returns Promise resolving to the checkout response with redirect URL
1355
+ *
1356
+ * @example
1357
+ * ```typescript
1358
+ * const checkout = await client.billing.createCheckout({
1359
+ * price_id: 'price_1234567890',
1360
+ * success_url: 'https://myapp.com/checkout/success',
1361
+ * cancel_url: 'https://myapp.com/checkout/cancel'
1362
+ * });
1363
+ *
1364
+ * // Redirect the user to complete checkout
1365
+ * window.location.href = checkout.url;
1366
+ * ```
1367
+ *
1368
+ * @see Requirements 10.1
1369
+ */
1370
+ async createCheckout(data) {
1371
+ return this.http.post("/billing/checkout", data);
1372
+ }
1373
+ /**
1374
+ * Create a Stripe billing portal session for managing an existing subscription.
1375
+ *
1376
+ * Returns a URL that the user should be redirected to in order to
1377
+ * access the Stripe billing portal where they can:
1378
+ * - View and update payment methods
1379
+ * - View billing history and invoices
1380
+ * - Upgrade, downgrade, or cancel their subscription
1381
+ *
1382
+ * @returns Promise resolving to the portal response with redirect URL
1383
+ *
1384
+ * @example
1385
+ * ```typescript
1386
+ * const portal = await client.billing.createPortal();
1387
+ *
1388
+ * // Redirect the user to the billing portal
1389
+ * window.location.href = portal.url;
1390
+ * ```
1391
+ *
1392
+ * @see Requirements 10.2
1393
+ */
1394
+ async createPortal() {
1395
+ return this.http.post("/billing/portal");
1396
+ }
1397
+ };
1398
+
1399
+ // src/resources/files.ts
1400
+ var FilesResource = class {
1401
+ http;
1402
+ /**
1403
+ * Create a new FilesResource instance
1404
+ * @param http - The HTTP client to use for API requests
1405
+ */
1406
+ constructor(http) {
1407
+ this.http = http;
1408
+ }
1409
+ /**
1410
+ * Get a signed download URL for a file.
1411
+ *
1412
+ * Returns a temporary signed URL that can be used to download the file.
1413
+ * The URL will expire at the time indicated in the response.
1414
+ *
1415
+ * @param id - The unique identifier of the file
1416
+ * @returns Promise resolving to the download response with signed URL and expiration
1417
+ *
1418
+ * @example
1419
+ * ```typescript
1420
+ * const download = await client.files.getDownloadUrl('file_abc123');
1421
+ *
1422
+ * // Use the signed URL to download the file
1423
+ * const response = await fetch(download.url);
1424
+ * const blob = await response.blob();
1425
+ *
1426
+ * // Check when the URL expires
1427
+ * console.log(`URL expires at: ${download.expires_at}`);
1428
+ * ```
1429
+ *
1430
+ * @see Requirements 11.1
1431
+ */
1432
+ async getDownloadUrl(id) {
1433
+ return this.http.get(`/files/${id}/download`);
1434
+ }
1435
+ /**
1436
+ * Delete a file by ID.
1437
+ *
1438
+ * Permanently removes the file from storage. This action cannot be undone.
1439
+ *
1440
+ * @param id - The unique identifier of the file to delete
1441
+ * @returns Promise resolving to a success response
1442
+ *
1443
+ * @example
1444
+ * ```typescript
1445
+ * const result = await client.files.delete('file_abc123');
1446
+ *
1447
+ * if (result.success) {
1448
+ * console.log('File deleted successfully');
1449
+ * }
1450
+ * ```
1451
+ *
1452
+ * @see Requirements 11.2
1453
+ */
1454
+ async delete(id) {
1455
+ return this.http.delete(`/files/${id}`);
1456
+ }
1457
+ };
1458
+
1459
+ // src/client.ts
1460
+ var DEFAULT_BASE_URL = "https://api.spike.ac";
1461
+ var DEFAULT_TIMEOUT = 3e4;
1462
+ var SpikeClient = class {
1463
+ /**
1464
+ * Resource for managing forms.
1465
+ * @see FormsResource
1466
+ */
1467
+ forms;
1468
+ /**
1469
+ * Resource for managing form submissions.
1470
+ * @see SubmissionsResource
1471
+ */
1472
+ submissions;
1473
+ /**
1474
+ * Resource for managing form rules.
1475
+ * @see RulesResource
1476
+ */
1477
+ rules;
1478
+ /**
1479
+ * Resource for managing projects.
1480
+ * @see ProjectsResource
1481
+ */
1482
+ projects;
1483
+ /**
1484
+ * Resource for managing teams.
1485
+ * @see TeamsResource
1486
+ */
1487
+ teams;
1488
+ /**
1489
+ * Resource for managing user profile and settings.
1490
+ * @see UserResource
1491
+ */
1492
+ user;
1493
+ /**
1494
+ * Resource for managing billing and subscriptions.
1495
+ * @see BillingResource
1496
+ */
1497
+ billing;
1498
+ /**
1499
+ * Resource for managing uploaded files.
1500
+ * @see FilesResource
1501
+ */
1502
+ files;
1503
+ /**
1504
+ * The HTTP client used for API requests.
1505
+ * @internal
1506
+ */
1507
+ http;
1508
+ /**
1509
+ * Create a new Spike client instance.
1510
+ *
1511
+ * @param config - Configuration options for the client
1512
+ * @throws ValidationError if the API key is missing or empty
1513
+ *
1514
+ * @example
1515
+ * ```typescript
1516
+ * // Basic usage with API key
1517
+ * const client = new SpikeClient({ apiKey: 'sk_live_abc123' });
1518
+ *
1519
+ * // With all configuration options
1520
+ * const client = new SpikeClient({
1521
+ * apiKey: 'sk_live_abc123',
1522
+ * baseUrl: 'https://spike.ac',
1523
+ * timeout: 30000
1524
+ * });
1525
+ * ```
1526
+ *
1527
+ * @see Requirements 1.1, 1.2, 1.3, 1.4, 1.5
1528
+ */
1529
+ constructor(config) {
1530
+ if (!config.apiKey) {
1531
+ throw new ValidationError("API key is required. Please provide a valid API key.");
1532
+ }
1533
+ this.http = new HttpClient({
1534
+ apiKey: config.apiKey,
1535
+ baseUrl: config.baseUrl ?? DEFAULT_BASE_URL,
1536
+ timeout: config.timeout ?? DEFAULT_TIMEOUT
1537
+ });
1538
+ this.forms = new FormsResource(this.http);
1539
+ this.submissions = new SubmissionsResource(this.http);
1540
+ this.rules = new RulesResource(this.http);
1541
+ this.projects = new ProjectsResource(this.http);
1542
+ this.teams = new TeamsResource(this.http);
1543
+ this.user = new UserResource(this.http);
1544
+ this.billing = new BillingResource(this.http);
1545
+ this.files = new FilesResource(this.http);
1546
+ }
1547
+ };
1548
+
1549
+ // src/index.ts
1550
+ var VERSION = "0.1.0";
1551
+
1552
+ exports.AuthenticationError = AuthenticationError;
1553
+ exports.BillingResource = BillingResource;
1554
+ exports.FilesResource = FilesResource;
1555
+ exports.FormsResource = FormsResource;
1556
+ exports.NetworkError = NetworkError;
1557
+ exports.NotFoundError = NotFoundError;
1558
+ exports.ProjectsResource = ProjectsResource;
1559
+ exports.RateLimitError = RateLimitError;
1560
+ exports.RulesResource = RulesResource;
1561
+ exports.SpikeClient = SpikeClient;
1562
+ exports.SpikeError = SpikeError;
1563
+ exports.SubmissionsResource = SubmissionsResource;
1564
+ exports.TeamsResource = TeamsResource;
1565
+ exports.UserResource = UserResource;
1566
+ exports.VERSION = VERSION;
1567
+ exports.ValidationError = ValidationError;
1568
+ //# sourceMappingURL=index.js.map
1569
+ //# sourceMappingURL=index.js.map