@timesheet/sdk 1.0.6 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/CHANGELOG.md +73 -1
  2. package/README.md +103 -16
  3. package/dist/http/ApiClient.d.ts +1 -1
  4. package/dist/http/ApiClient.d.ts.map +1 -1
  5. package/dist/index.d.ts +5 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +2 -2
  8. package/dist/index.js.map +4 -4
  9. package/dist/index.mjs +2 -2
  10. package/dist/index.mjs.map +4 -4
  11. package/dist/models/Absence.d.ts +136 -0
  12. package/dist/models/Absence.d.ts.map +1 -0
  13. package/dist/models/Automation.d.ts +6 -1
  14. package/dist/models/Automation.d.ts.map +1 -1
  15. package/dist/models/Contract.d.ts +141 -0
  16. package/dist/models/Contract.d.ts.map +1 -0
  17. package/dist/models/Document.d.ts +192 -87
  18. package/dist/models/Document.d.ts.map +1 -1
  19. package/dist/models/Expense.d.ts +4 -3
  20. package/dist/models/Expense.d.ts.map +1 -1
  21. package/dist/models/Note.d.ts +3 -2
  22. package/dist/models/Note.d.ts.map +1 -1
  23. package/dist/models/Organization.d.ts +58 -1
  24. package/dist/models/Organization.d.ts.map +1 -1
  25. package/dist/models/Pause.d.ts +2 -2
  26. package/dist/models/Pause.d.ts.map +1 -1
  27. package/dist/models/Profile.d.ts +13 -1
  28. package/dist/models/Profile.d.ts.map +1 -1
  29. package/dist/models/Project.d.ts +52 -27
  30. package/dist/models/Project.d.ts.map +1 -1
  31. package/dist/models/Rate.d.ts +7 -6
  32. package/dist/models/Rate.d.ts.map +1 -1
  33. package/dist/models/Reports.d.ts +32 -15
  34. package/dist/models/Reports.d.ts.map +1 -1
  35. package/dist/models/Tag.d.ts +6 -2
  36. package/dist/models/Tag.d.ts.map +1 -1
  37. package/dist/models/Task.d.ts +14 -22
  38. package/dist/models/Task.d.ts.map +1 -1
  39. package/dist/models/Team.d.ts +55 -11
  40. package/dist/models/Team.d.ts.map +1 -1
  41. package/dist/models/Timer.d.ts +4 -0
  42. package/dist/models/Timer.d.ts.map +1 -1
  43. package/dist/models/Todo.d.ts +8 -7
  44. package/dist/models/Todo.d.ts.map +1 -1
  45. package/dist/models/Webhook.d.ts +3 -0
  46. package/dist/models/Webhook.d.ts.map +1 -1
  47. package/dist/models/common.d.ts +2 -0
  48. package/dist/models/common.d.ts.map +1 -1
  49. package/dist/models/index.d.ts +2 -0
  50. package/dist/models/index.d.ts.map +1 -1
  51. package/dist/resources/AbsenceResource.d.ts +18 -0
  52. package/dist/resources/AbsenceResource.d.ts.map +1 -0
  53. package/dist/resources/AbsenceTypeResource.d.ts +14 -0
  54. package/dist/resources/AbsenceTypeResource.d.ts.map +1 -0
  55. package/dist/resources/ContractResource.d.ts +18 -0
  56. package/dist/resources/ContractResource.d.ts.map +1 -0
  57. package/dist/resources/ContractTemplateResource.d.ts +14 -0
  58. package/dist/resources/ContractTemplateResource.d.ts.map +1 -0
  59. package/dist/resources/DocumentResource.d.ts.map +1 -1
  60. package/dist/resources/ExpenseResource.d.ts +1 -1
  61. package/dist/resources/ExpenseResource.d.ts.map +1 -1
  62. package/dist/resources/OrganizationResource.d.ts +6 -1
  63. package/dist/resources/OrganizationResource.d.ts.map +1 -1
  64. package/dist/resources/ProjectResource.d.ts +9 -1
  65. package/dist/resources/ProjectResource.d.ts.map +1 -1
  66. package/dist/resources/TagResource.d.ts +1 -2
  67. package/dist/resources/TagResource.d.ts.map +1 -1
  68. package/dist/resources/TaskResource.d.ts +4 -1
  69. package/dist/resources/TaskResource.d.ts.map +1 -1
  70. package/dist/resources/TeamResource.d.ts +8 -2
  71. package/dist/resources/TeamResource.d.ts.map +1 -1
  72. package/dist/resources/TodoResource.d.ts +1 -2
  73. package/dist/resources/TodoResource.d.ts.map +1 -1
  74. package/dist/resources/index.d.ts +4 -0
  75. package/dist/resources/index.d.ts.map +1 -1
  76. package/dist/resources/reports/ExportResource.d.ts +1 -1
  77. package/dist/resources/reports/ExportResource.d.ts.map +1 -1
  78. package/dist/version.d.ts +2 -0
  79. package/dist/version.d.ts.map +1 -0
  80. package/package.json +4 -1
package/CHANGELOG.md CHANGED
@@ -6,6 +6,74 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
8
 
9
+ ## [1.1.1] - 2026-05-24
10
+
11
+ ### Fixed
12
+ - `TodoResource.list()` and `TagResource.list()` now correctly parse the paginated wrapper response from `GET /v1/todos` and `GET /v1/tags`. 1.1.0 (Todo) and earlier (Tag) treated the response as a bare `Todo[]` / `Tag[]`, which silently produced a `NavigablePage` whose `.items` was the wrapper object instead of the actual items array. The backend has always returned the `ToDoList` / `TagList` wrapper; the bug was on the SDK side.
13
+
14
+ ## [1.1.0] - 2026-05-23
15
+
16
+ ### Added
17
+ - Team member management on `TeamResource`:
18
+ - `addMember()`, `updateMember()`, `removeMember()`, `removeInvitedMember()`
19
+ - `batchAddMembers()` for bulk member registration
20
+ - `getMemberStatus()` for retrieving members with current activity status
21
+ - Project member management on `ProjectResource`:
22
+ - `listMembers()`, `addMember()`, `getMember()`, `updateMember()`, `removeMember()`
23
+ - `updateMembers()` for full member-list replacement
24
+ - `batchAddMembers()` / `batchRemoveMembers()` for bulk operations
25
+ - E-invoicing fields on `Document` and `DocumentUpdateRequest`:
26
+ - VAT/tax IDs, registration and bank details (BIC, IBAN)
27
+ - Reverse charge, cash discount, payment term, delivery and due dates
28
+ - Order, project, procurement and contract references, cost center
29
+ - Government invoice flag, original invoice references
30
+ - E-invoice type, currency and document type fields
31
+ - QR code support on `Document` (`showQrCode`, `qrCodeType`, `qrCodeContent`, `qrCodeDescription`)
32
+ - Payment status flags on `Document` (`fullyPaid`, `partiallyPaid`)
33
+ - Absence file attachments: `fileName` and `fileUri` on `Absence`, `AbsenceCreateRequest`, `AbsenceUpdateRequest`
34
+ - Absence documentation tracking: `documentationStatus`, `documentationDueDate`, `requestedByMember` on `Absence`
35
+ - `ContractListParams.userId` and `ContractListParams.status` filters
36
+ - Extracted shared `TeamPermission` and `ProjectPermission` interfaces
37
+ - New types: `TeamMemberCreateRequest`, `TeamMemberUpdateRequest`, `TeamMemberProjectRegistration`, `MemberStatusParams`, `MemberStatusList`, `ProjectMemberCreateRequest`, `ProjectMemberUpdateRequest`, `ProjectMemberListParams`, `ProjectMemberList`, `ProjectRegistration`
38
+ - `Project.titleAndClient` and `Project.salaryVisible` convenience fields
39
+ - `DocumentListParams.organizationUnassigned` filter
40
+ - `ProjectListParams.empty` filter
41
+ - `TeamMemberListParams`: `withoutProjectMembers`, `userIds`, `withoutUserIds`
42
+ - `ListParams.search` (free-text search) and `ListParams.offset` (result offset) for all list endpoints
43
+ - `ApiClient.delete()` now accepts an optional request body for endpoints that support batch deletes
44
+ - Additional fields on `Contract`: `employmentModelName`, `holidayCollectionName`
45
+
46
+ ### Changed
47
+ - **BREAKING**: `AbsenceListParams` fields renamed from `startDateTime` / `endDateTime` to `startDate` / `endDate` to match the API
48
+ - **BREAKING**: `Document` monetary fields are now serialized as `string` (BigDecimal) instead of `number`: `taskSubtotal`, `expenseSubtotal`, `subtotal`, `tax`, `taxValue`, `taxSecond`, `taxSecondValue`, `discount`, `discountValue`, `discountSecondValue`, `total`, `payment`
49
+ - **BREAKING**: `TeamMember.uid` renamed to `TeamMember.id`; `user` field added for the linked user identifier
50
+ - **BREAKING**: `ProjectMember.uid` renamed to `ProjectMember.id`; `user` field added for the linked user identifier
51
+ - **BREAKING**: `TeamResource.getColleagues()` now returns `NavigablePage<Member>` instead of `NavigablePage<TeamMember>`
52
+ - **BREAKING**: `Contract.userId` removed; use `Contract.member` to access the associated user
53
+ - `Project.permission` and `Team.permission` now use the shared `TeamPermission` / `ProjectPermission` interfaces
54
+ - `ExportResource.getFields()` `scope` parameter changed from `'all' | 'project' | 'team'` to `'project' | 'team' | 'task' | 'todo'` (defaults to `'task'`)
55
+ - `Document.organization` (full `Organization` reference) now included alongside `organizationId`
56
+ - `TodoResource.list()` updated to handle the bare-array response from `GET /v1/todos`
57
+
58
+ ### Removed
59
+ - **BREAKING**: `ContractAmendment` and `ContractAmendmentCreateRequest` types removed
60
+ - **BREAKING**: `ContractResource.listAmendments()` and `ContractResource.createAmendment()` removed
61
+ - **BREAKING**: `ProjectListParams.statistics` removed (statistics are now always included)
62
+
63
+ ## [1.0.6] - 2026-01-27
64
+
65
+ ### Changed
66
+ - Replaced `tsup` / `rollup` with `esbuild` for builds to resolve native binary installation issues
67
+ - Type declarations are now emitted via `tsc` directly
68
+
69
+ ## [1.0.5] - 2026-01-27
70
+
71
+ ### Added
72
+ - `EventResource` for real-time Server-Sent Events (SSE) streaming
73
+ - File upload methods on `ExpenseResource` and `NoteResource` (`uploadFile()` and combined create-with-file helpers)
74
+ - `ApiClient.postMultipart()` for `multipart/form-data` requests
75
+ - `ApiClient.getBaseUrl()` and `ApiClient.getAuthHeaders()` to support SSE and custom transports
76
+
9
77
  ## [1.0.4] - 2026-01-04
10
78
 
11
79
  ### Added
@@ -100,7 +168,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
100
168
  - Removed complex mocking in favor of simple validation tests
101
169
  - Updated GitHub Actions to use non-deprecated action versions
102
170
 
103
- [Unreleased]: https://github.com/timesheetIO/timesheet-typescript/compare/v1.0.4...HEAD
171
+ [Unreleased]: https://github.com/timesheetIO/timesheet-typescript/compare/v1.1.1...HEAD
172
+ [1.1.1]: https://github.com/timesheetIO/timesheet-typescript/compare/v1.1.0...v1.1.1
173
+ [1.1.0]: https://github.com/timesheetIO/timesheet-typescript/compare/v1.0.6...v1.1.0
174
+ [1.0.6]: https://github.com/timesheetIO/timesheet-typescript/compare/v1.0.4...v1.0.6
175
+ [1.0.5]: https://github.com/timesheetIO/timesheet-typescript/compare/v1.0.4...v1.0.5
104
176
  [1.0.4]: https://github.com/timesheetIO/timesheet-typescript/compare/v1.0.3...v1.0.4
105
177
  [1.0.3]: https://github.com/timesheetIO/timesheet-typescript/compare/v1.0.2...v1.0.3
106
178
  [1.0.2]: https://github.com/timesheetIO/timesheet-typescript/compare/v1.0.1...v1.0.2
package/README.md CHANGED
@@ -13,6 +13,8 @@ The official TypeScript SDK for the [Timesheet API](https://timesheet.io), provi
13
13
  - ✅ **Type-Safe** - Full TypeScript support with comprehensive types
14
14
  - ✅ **Modern Architecture** - Promise-based with async/await support
15
15
  - ✅ **Authentication** - Built-in API Key, OAuth2, and OAuth 2.1 (PKCE) with automatic discovery (RFC 8414)
16
+ - ✅ **Real-Time Events** - Server-Sent Events (SSE) for live updates
17
+ - ✅ **File Uploads** - Multipart uploads for expense receipts and note attachments
16
18
  - ✅ **Error Handling** - Typed exceptions for better error management
17
19
  - ✅ **Pagination** - Automatic pagination with async iterators
18
20
  - ✅ **Retry Logic** - Configurable retry with exponential backoff
@@ -225,22 +227,28 @@ const client = new TimesheetClient({
225
227
  All API resources are available through the client:
226
228
 
227
229
  ```typescript
228
- client.tasks // Task management
229
- client.projects // Project management
230
- client.tags // Tag management
231
- client.teams // Team management
232
- client.organizations // Organization settings
233
- client.timer // Real-time time tracking
234
- client.rates // Billing rates
235
- client.expenses // Expense tracking
236
- client.notes // Note attachments
237
- client.pauses // Break time tracking
238
- client.documents // Document generation
239
- client.webhooks // Event notifications
240
- client.automations // Time tracking automation
241
- client.todos // Task management
242
- client.profile // User profile
243
- client.settings // User settings
230
+ client.tasks // Task management
231
+ client.projects // Project management (including project members)
232
+ client.tags // Tag management
233
+ client.teams // Team management (including team members)
234
+ client.organizations // Organization settings
235
+ client.timer // Real-time time tracking
236
+ client.rates // Billing rates
237
+ client.expenses // Expense tracking (with file upload)
238
+ client.notes // Note attachments (with file upload)
239
+ client.pauses // Break time tracking
240
+ client.documents // Document and invoice generation
241
+ client.webhooks // Webhook subscriptions
242
+ client.automations // Time tracking automation
243
+ client.todos // Todo management
244
+ client.events // Real-time SSE event streaming
245
+ client.absences // Absence requests and approvals
246
+ client.absenceTypes // Absence type configuration
247
+ client.contracts // Employment contracts
248
+ client.contractTemplates // Contract templates
249
+ client.profile // User profile
250
+ client.settings // User settings
251
+ client.reports // Reports API (documents, tasks, expenses, notes, exports)
244
252
  ```
245
253
 
246
254
  ## Examples
@@ -315,6 +323,85 @@ const stoppedTimer = await client.timer.stop({
315
323
  });
316
324
  ```
317
325
 
326
+ ### Real-Time Events (SSE)
327
+
328
+ Subscribe to live changes for tasks, projects, teams, and other entities via Server-Sent Events.
329
+
330
+ ```typescript
331
+ const subscription = await client.events.subscribe({
332
+ onConnected: (connectionId) => {
333
+ console.log('Connected with ID:', connectionId);
334
+ },
335
+ onEvent: (event) => {
336
+ switch (event.event) {
337
+ case 'task.create':
338
+ console.log('New task:', event.item);
339
+ break;
340
+ case 'task.update':
341
+ console.log('Task updated:', event.item);
342
+ break;
343
+ }
344
+ },
345
+ onError: (error) => {
346
+ console.error('SSE error:', error);
347
+ },
348
+ });
349
+
350
+ // Check connection status
351
+ const status = await client.events.getStatus();
352
+
353
+ // Close when done
354
+ subscription.close();
355
+ ```
356
+
357
+ ### File Uploads
358
+
359
+ Attach receipts to expenses and files to notes via `multipart/form-data` uploads.
360
+
361
+ ```typescript
362
+ // Upload a receipt to an existing expense
363
+ await client.expenses.uploadFile('expense-id', {
364
+ file: fileBuffer, // Buffer, Blob, or ReadableStream
365
+ filename: 'receipt.pdf',
366
+ contentType: 'application/pdf',
367
+ });
368
+
369
+ // Create a note with an attachment in one call
370
+ const note = await client.notes.createWithFile({
371
+ taskId: 'task-id',
372
+ description: 'Meeting notes',
373
+ file: fileBuffer,
374
+ filename: 'notes.pdf',
375
+ });
376
+ ```
377
+
378
+ ### Team and Project Members
379
+
380
+ ```typescript
381
+ // Add a member to a team
382
+ const teamMember = await client.teams.addMember('team-id', {
383
+ email: 'colleague@example.com',
384
+ permission: { role: 'manager' },
385
+ });
386
+
387
+ // Get team members with current activity status
388
+ const status = await client.teams.getMemberStatus({
389
+ teamId: 'team-id',
390
+ status: 'running', // all | active | inactive | running | idle
391
+ });
392
+
393
+ // Add a member to a project
394
+ await client.projects.addMember('project-id', {
395
+ userId: 'user-id',
396
+ permission: { role: 'member' },
397
+ });
398
+
399
+ // List project members
400
+ const members = await client.projects.listMembers('project-id', {
401
+ status: 'active',
402
+ });
403
+ ```
404
+
318
405
  ### Pagination
319
406
 
320
407
  ```typescript
@@ -9,7 +9,7 @@ export declare class ApiClient {
9
9
  get<T, P = Record<string, unknown>>(path: string, params?: P): Promise<T>;
10
10
  post<T, P = Record<string, unknown>>(path: string, data?: unknown, params?: P): Promise<T>;
11
11
  put<T, P = Record<string, unknown>>(path: string, data?: unknown, params?: P): Promise<T>;
12
- delete<T, P = Record<string, unknown>>(path: string, params?: P): Promise<T>;
12
+ delete<T, P = Record<string, unknown>>(path: string, params?: P, data?: unknown): Promise<T>;
13
13
  postMultipart<T>(path: string, formData: FormData): Promise<T>;
14
14
  private sleep;
15
15
  getBaseUrl(): string;
@@ -1 +1 @@
1
- {"version":3,"file":"ApiClient.d.ts","sourceRoot":"","sources":["../../src/http/ApiClient.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAiB,kBAAkB,EAAE,MAAM,OAAO,CAAC;AAE/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAW9C,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;gBAE/B,MAAM,EAAE,YAAY;IAiC1B,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,CAAC,CAAC;IAoElD,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAWzE,IAAI,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAY1F,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAYzF,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAa5E,aAAa,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC;IAcpE,OAAO,CAAC,KAAK;IAOb,UAAU,IAAI,MAAM;IAQd,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;CAMpE"}
1
+ {"version":3,"file":"ApiClient.d.ts","sourceRoot":"","sources":["../../src/http/ApiClient.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAiB,kBAAkB,EAAE,MAAM,OAAO,CAAC;AAE/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAY9C,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;gBAE/B,MAAM,EAAE,YAAY;IAiC1B,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,CAAC,CAAC;IAoElD,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAWzE,IAAI,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAY1F,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAazF,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACzC,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,CAAC,EACV,IAAI,CAAC,EAAE,OAAO,GACb,OAAO,CAAC,CAAC,CAAC;IAcP,aAAa,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC;IAcpE,OAAO,CAAC,KAAK;IAOb,UAAU,IAAI,MAAM;IAQd,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;CAMpE"}
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { Authentication } from './auth';
2
2
  import { RetryConfig } from './config';
3
3
  import type { AxiosInstance } from 'axios';
4
- import { AutomationResource, DocumentResource, EventResource, ExpenseResource, NoteResource, OrganizationResource, PauseResource, ProfileResource, ProjectResource, RateResource, ReportsClient, SettingsResource, TagResource, TaskResource, TeamResource, TimerResource, TodoResource, WebhookResource } from './resources';
4
+ import { AbsenceResource, AbsenceTypeResource, AutomationResource, ContractResource, ContractTemplateResource, DocumentResource, EventResource, ExpenseResource, NoteResource, OrganizationResource, PauseResource, ProfileResource, ProjectResource, RateResource, ReportsClient, SettingsResource, TagResource, TaskResource, TeamResource, TimerResource, TodoResource, WebhookResource } from './resources';
5
5
  export * from './auth';
6
6
  export * from './config';
7
7
  export * from './exceptions';
@@ -28,6 +28,10 @@ export declare class TimesheetClient {
28
28
  readonly todos: TodoResource;
29
29
  readonly webhooks: WebhookResource;
30
30
  readonly events: EventResource;
31
+ readonly absences: AbsenceResource;
32
+ readonly absenceTypes: AbsenceTypeResource;
33
+ readonly contracts: ContractResource;
34
+ readonly contractTemplates: ContractTemplateResource;
31
35
  readonly reports: ReportsClient;
32
36
  constructor(options: TimesheetClientOptions);
33
37
  private createAuthentication;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAG7C,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,eAAe,EACf,YAAY,EACZ,oBAAoB,EACpB,aAAa,EACb,eAAe,EACf,eAAe,EACf,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,eAAe,EAChB,MAAM,aAAa,CAAC;AAGrB,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,aAAa,CAAC;AAkB5B,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IACtC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAY;IAG7C,SAAgB,aAAa,EAAE,oBAAoB,CAAC;IACpD,SAAgB,KAAK,EAAE,YAAY,CAAC;IACpC,SAAgB,QAAQ,EAAE,eAAe,CAAC;IAC1C,SAAgB,KAAK,EAAE,YAAY,CAAC;IACpC,SAAgB,KAAK,EAAE,YAAY,CAAC;IACpC,SAAgB,IAAI,EAAE,WAAW,CAAC;IAClC,SAAgB,QAAQ,EAAE,eAAe,CAAC;IAC1C,SAAgB,KAAK,EAAE,YAAY,CAAC;IACpC,SAAgB,MAAM,EAAE,aAAa,CAAC;IACtC,SAAgB,OAAO,EAAE,eAAe,CAAC;IACzC,SAAgB,QAAQ,EAAE,gBAAgB,CAAC;IAC3C,SAAgB,WAAW,EAAE,kBAAkB,CAAC;IAChD,SAAgB,SAAS,EAAE,gBAAgB,CAAC;IAC5C,SAAgB,KAAK,EAAE,aAAa,CAAC;IACrC,SAAgB,KAAK,EAAE,YAAY,CAAC;IACpC,SAAgB,QAAQ,EAAE,eAAe,CAAC;IAC1C,SAAgB,MAAM,EAAE,aAAa,CAAC;IAqBtC,SAAgB,OAAO,EAAE,aAAa,CAAC;gBAO3B,OAAO,EAAE,sBAAsB;IA+C3C,OAAO,CAAC,oBAAoB;CAiB7B;AAKD,MAAM,WAAW,sBAAsB;IAIrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAKhB,WAAW,CAAC,EAAE,MAAM,CAAC;IAKrB,MAAM,CAAC,EAAE;QACP,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IAKF,cAAc,CAAC,EAAE,cAAc,CAAC;IAMhC,OAAO,CAAC,EAAE,MAAM,CAAC;IAMjB,cAAc,CAAC,EAAE,MAAM,CAAC;IAKxB,WAAW,CAAC,EAAE,WAAW,CAAC;IAK1B,UAAU,CAAC,EAAE,aAAa,CAAC;IAK3B,iBAAiB,CAAC,EAAE,aAAa,CAAC;CACnC;AAGD,wBAAgB,YAAY,CAAC,OAAO,EAAE,sBAAsB,GAAG,eAAe,CAE7E"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAG7C,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,wBAAwB,EACxB,gBAAgB,EAChB,aAAa,EACb,eAAe,EACf,YAAY,EACZ,oBAAoB,EACpB,aAAa,EACb,eAAe,EACf,eAAe,EACf,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,eAAe,EAChB,MAAM,aAAa,CAAC;AAGrB,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,aAAa,CAAC;AAkB5B,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IACtC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAY;IAG7C,SAAgB,aAAa,EAAE,oBAAoB,CAAC;IACpD,SAAgB,KAAK,EAAE,YAAY,CAAC;IACpC,SAAgB,QAAQ,EAAE,eAAe,CAAC;IAC1C,SAAgB,KAAK,EAAE,YAAY,CAAC;IACpC,SAAgB,KAAK,EAAE,YAAY,CAAC;IACpC,SAAgB,IAAI,EAAE,WAAW,CAAC;IAClC,SAAgB,QAAQ,EAAE,eAAe,CAAC;IAC1C,SAAgB,KAAK,EAAE,YAAY,CAAC;IACpC,SAAgB,MAAM,EAAE,aAAa,CAAC;IACtC,SAAgB,OAAO,EAAE,eAAe,CAAC;IACzC,SAAgB,QAAQ,EAAE,gBAAgB,CAAC;IAC3C,SAAgB,WAAW,EAAE,kBAAkB,CAAC;IAChD,SAAgB,SAAS,EAAE,gBAAgB,CAAC;IAC5C,SAAgB,KAAK,EAAE,aAAa,CAAC;IACrC,SAAgB,KAAK,EAAE,YAAY,CAAC;IACpC,SAAgB,QAAQ,EAAE,eAAe,CAAC;IAC1C,SAAgB,MAAM,EAAE,aAAa,CAAC;IACtC,SAAgB,QAAQ,EAAE,eAAe,CAAC;IAC1C,SAAgB,YAAY,EAAE,mBAAmB,CAAC;IAClD,SAAgB,SAAS,EAAE,gBAAgB,CAAC;IAC5C,SAAgB,iBAAiB,EAAE,wBAAwB,CAAC;IAqB5D,SAAgB,OAAO,EAAE,aAAa,CAAC;gBAO3B,OAAO,EAAE,sBAAsB;IAmD3C,OAAO,CAAC,oBAAoB;CAiB7B;AAKD,MAAM,WAAW,sBAAsB;IAIrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAKhB,WAAW,CAAC,EAAE,MAAM,CAAC;IAKrB,MAAM,CAAC,EAAE;QACP,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IAKF,cAAc,CAAC,EAAE,cAAc,CAAC;IAMhC,OAAO,CAAC,EAAE,MAAM,CAAC;IAMjB,cAAc,CAAC,EAAE,MAAM,CAAC;IAKxB,WAAW,CAAC,EAAE,WAAW,CAAC;IAK1B,UAAU,CAAC,EAAE,aAAa,CAAC;IAK3B,iBAAiB,CAAC,EAAE,aAAa,CAAC;CACnC;AAGD,wBAAgB,YAAY,CAAC,OAAO,EAAE,sBAAsB,GAAG,eAAe,CAE7E"}
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- "use strict";var xe=Object.create;var te=Object.defineProperty;var Ce=Object.getOwnPropertyDescriptor;var we=Object.getOwnPropertyNames;var Ee=Object.getPrototypeOf,ve=Object.prototype.hasOwnProperty;var ke=(s,e)=>{for(var t in e)te(s,t,{get:e[t],enumerable:!0})},ue=(s,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of we(e))!ve.call(s,i)&&i!==t&&te(s,i,{get:()=>e[i],enumerable:!(r=Ce(e,i))||r.enumerable});return s};var f=(s,e,t)=>(t=s!=null?xe(Ee(s)):{},ue(e||!s||!s.__esModule?te(t,"default",{value:s,enumerable:!0}):t,s)),Ae=s=>ue(te({},"__esModule",{value:!0}),s);var Se={};ke(Se,{ApiClient:()=>C,ApiKeyAuth:()=>X,AutomationResource:()=>_,DocumentReportResource:()=>W,DocumentResource:()=>L,EventResource:()=>j,ExpenseReportResource:()=>H,ExpenseResource:()=>N,ExportResource:()=>J,NavigablePage:()=>p,NoteReportResource:()=>K,NoteResource:()=>I,OAuth21Auth:()=>ce,OAuth2Auth:()=>w,OAuthDiscovery:()=>Q,OrganizationResource:()=>v,PauseResource:()=>q,ProfileResource:()=>S,ProjectResource:()=>A,RateResource:()=>$,ReportsClient:()=>V,Resource:()=>a,RetryConfig:()=>ee,SettingsResource:()=>O,TagResource:()=>U,TaskReportResource:()=>B,TaskResource:()=>D,TeamResource:()=>k,TimerResource:()=>M,TimesheetApiError:()=>d,TimesheetAuthError:()=>Y,TimesheetClient:()=>oe,TimesheetRateLimitError:()=>Z,TodoResource:()=>z,WebhookEvents:()=>$e,WebhookResource:()=>F,combineWebhookEvents:()=>Ue,createClient:()=>qe,discoverOAuth:()=>De,generateCodeChallenge:()=>ge,generateCodeVerifier:()=>de,generatePkceCodePair:()=>ae,getDefaultDiscovery:()=>Te,isValidCodeVerifier:()=>ne});module.exports=Ae(Se);var x=f(require("axios"));var d=class s extends Error{constructor(e,t,r,i){let o=t?i?`${e} (HTTP ${t}, Code: ${i})`:`${e} (HTTP ${t})`:e;super(o),this.name="TimesheetApiError",this.statusCode=t,this.responseBody=r,this.errorCode=i,typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,s)}};var Y=class extends d{constructor(e,t=401,r){super(e,t,r,"authentication_error"),this.name="TimesheetAuthError"}};var Z=class extends d{constructor(e,t){super(e,429,void 0,"rate_limit_exceeded"),this.name="TimesheetRateLimitError",this.retryAfter=t}getRetryAfterDate(){if(!this.retryAfter)return null;let e=Number(this.retryAfter);if(!isNaN(e))return new Date(e*1e3);let t=new Date(this.retryAfter);return isNaN(t.getTime())?null:t}};var C=class{constructor(e){this.config=e,this.httpClient=e.httpClient||x.default.create({baseURL:e.baseUrl,timeout:3e4,headers:{"User-Agent":"Timesheet-TypeScript-SDK/1.0.0","Content-Type":"application/json"}}),this.httpClient.interceptors.request.use(async t=>{if(t.url!=="/oauth/token"&&this.config.authentication){let r=await this.config.authentication.getAuthHeaders();if(r)for(let[i,o]of Object.entries(r))t.headers.set(i,o)}return t})}async request(e){let t=null,r=this.config.retryConfig;for(let i=0;i<=r.maxRetries;i++)try{return(await this.httpClient.request(e)).data}catch(o){if(t=o,x.default.isAxiosError(o)&&o.response?.status===401){let c=o.response.data;throw new Y(c?.message||"Authentication failed",401,JSON.stringify(c))}if(x.default.isAxiosError(o)&&o.response?.status===429){let c=o.response.headers["retry-after"];throw new Z("Rate limit exceeded",c)}let m=x.default.isAxiosError(o)?o.response?.status:void 0;if(i<r.maxRetries&&m&&r.retryableStatusCodes.includes(m)){let c=Math.min(r.initialDelay*Math.pow(r.backoffMultiplier,i),r.maxDelay);await this.sleep(c);continue}if(x.default.isAxiosError(o)){let c=o.response?.data;throw new d(c?.message||o.message,o.response?.status,JSON.stringify(c),c?.code)}else throw o instanceof Error?new d(o.message):new d("Unknown error occurred")}throw t||new Error("Unknown error")}async get(e,t){return this.request({method:"GET",url:e,params:t})}async post(e,t,r){return this.request({method:"POST",url:e,data:t,params:r})}async put(e,t,r){return this.request({method:"PUT",url:e,data:t,params:r})}async delete(e,t){return this.request({method:"DELETE",url:e,params:t})}async postMultipart(e,t){return this.request({method:"POST",url:e,data:t,headers:{"Content-Type":"multipart/form-data"}})}sleep(e){return new Promise(t=>setTimeout(t,e))}getBaseUrl(){return this.config.baseUrl}async getAuthHeaders(){if(this.config.authentication)return this.config.authentication.getAuthHeaders()}};var X=class{constructor(e){this.apiKey=e;if(e===null)throw new Error("API key cannot be null");if(e===void 0)throw new Error("API key cannot be undefined");if(!e)throw new Error("API key cannot be empty");if(typeof e!="string")throw new Error("API key must be a string");if(e.trim().length===0)throw new Error("API key cannot be empty or whitespace");if(!this.isValidFormat(e))throw new Error("Invalid API key format")}isValidFormat(e){return/^ts_[a-zA-Z0-9]+\.[a-zA-Z0-9]+$/.test(e)}applyAuth(e){e.headers||(e.headers={}),e.headers.Authorization=`ApiKey ${this.apiKey}`}needsRefresh(){return!1}async refresh(){throw new Error("API keys cannot be refreshed")}async getAuthHeaders(){return{Authorization:`ApiKey ${this.apiKey}`}}isValid(){return typeof this.apiKey=="string"&&this.apiKey.trim().length>0&&this.isValidFormat(this.apiKey)}};var ie=f(require("axios")),le=f(require("jsonwebtoken")),y=class y{constructor(e,t,r){t&&r?(this.clientId=e,this.clientSecret=t,this.refreshToken=r,this.accessToken=""):(this.accessToken=e,this.parseTokenExpiry())}applyAuth(e){e.headers||(e.headers={}),e.headers.Authorization=`Bearer ${this.accessToken}`}needsRefresh(){return this.refreshToken&&!this.accessToken?!0:!this.refreshToken||!this.tokenExpiry?!1:new Date(Date.now()+300*1e3)>=this.tokenExpiry}async refresh(){if(!this.refreshToken)throw new Error("Cannot refresh without refresh token");if(this.refreshPromise)return this.refreshPromise;this.refreshPromise=this.performRefresh();try{await this.refreshPromise}finally{this.refreshPromise=void 0}}async performRefresh(){try{let e=await ie.default.post(y.TOKEN_ENDPOINT,new URLSearchParams({grant_type:"refresh_token",refresh_token:this.refreshToken,client_id:this.clientId,client_secret:this.clientSecret}),{headers:{"Content-Type":"application/x-www-form-urlencoded"}});this.accessToken=e.data.access_token,e.data.refresh_token&&(this.refreshToken=e.data.refresh_token),this.parseTokenExpiry()}catch(e){let t=e instanceof Error?e.message:"Unknown error";throw new Error(`Failed to refresh OAuth2 token: ${t}`)}}async getAuthHeaders(){return this.needsRefresh()&&await this.refresh(),{Authorization:`Bearer ${this.accessToken}`}}static async fromAuthorizationCode(e,t,r,i){try{let o=await ie.default.post(y.TOKEN_ENDPOINT,new URLSearchParams({grant_type:"authorization_code",code:r,redirect_uri:i,client_id:e,client_secret:t}),{headers:{"Content-Type":"application/x-www-form-urlencoded"}}),m=o.data.access_token,c=o.data.refresh_token;return c?new y(e,t,c):new y(m)}catch(o){let m=o instanceof Error?o.message:"Unknown error";throw new Error(`Failed to exchange authorization code: ${m}`)}}static buildAuthorizationUrl(e,t,r){let i=new URLSearchParams({client_id:e,redirect_uri:t,response_type:"code"});return r&&i.append("state",r),`https://api.timesheet.io/oauth2/auth?${i.toString()}`}parseTokenExpiry(){try{let e=le.default.decode(this.accessToken);e&&e.exp&&(this.tokenExpiry=new Date(e.exp*1e3))}catch{this.tokenExpiry=new Date(Date.now()+3600*1e3)}}};y.TOKEN_ENDPOINT="https://api.timesheet.io/oauth2/token";var w=y;var pe=f(require("axios")),Pe=f(require("jsonwebtoken"));var re=require("crypto");function de(s=64){if(s<43||s>128)throw new Error("Code verifier length must be between 43 and 128 characters");let e=(0,re.randomBytes)(Math.ceil(s*3/4));return fe(e).slice(0,s)}function ge(s,e="S256"){if(e==="plain")return s;let t=(0,re.createHash)("sha256").update(s,"ascii").digest();return fe(t)}function ae(s="S256",e=64){let t=de(e),r=ge(t,s);return{codeVerifier:t,codeChallenge:r,codeChallengeMethod:s}}function ne(s){return s.length<43||s.length>128?!1:/^[A-Za-z0-9\-._~]+$/.test(s)}function fe(s){return s.toString("base64").replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}var P=class P{constructor(e){if(typeof e=="string")this.accessToken=e,this.tokenEndpoint=P.DEFAULT_TOKEN_ENDPOINT,this.parseTokenExpiry();else{let t=e;this.clientId=t.clientId,this.clientSecret=t.clientSecret,this.refreshToken=t.refreshToken,this.resource=t.resource,this.tokenEndpoint=t.tokenEndpoint??P.DEFAULT_TOKEN_ENDPOINT,this.accessToken=""}}applyAuth(e){e.headers||(e.headers={}),e.headers.Authorization=`Bearer ${this.accessToken}`}needsRefresh(){return this.refreshToken&&!this.accessToken?!0:!this.refreshToken||!this.tokenExpiry?!1:new Date(Date.now()+300*1e3)>=this.tokenExpiry}async refresh(){if(!this.refreshToken)throw new Error("Cannot refresh without refresh token");if(this.refreshPromise)return this.refreshPromise;this.refreshPromise=this.performRefresh();try{await this.refreshPromise}finally{this.refreshPromise=void 0}}async performRefresh(){try{let e=new URLSearchParams({grant_type:"refresh_token",refresh_token:this.refreshToken,client_id:this.clientId});this.clientSecret&&e.append("client_secret",this.clientSecret),this.resource&&e.append("resource",this.resource);let t=await pe.default.post(this.tokenEndpoint,e,{headers:{"Content-Type":"application/x-www-form-urlencoded"}});this.accessToken=t.data.access_token,t.data.refresh_token&&(this.refreshToken=t.data.refresh_token),this.parseTokenExpiry()}catch(e){let t=e instanceof Error?e.message:"Unknown error";throw new Error(`Failed to refresh OAuth 2.1 token: ${t}`)}}async getAuthHeaders(){return this.needsRefresh()&&await this.refresh(),{Authorization:`Bearer ${this.accessToken}`}}static async fromAuthorizationCode(e){let{clientId:t,clientSecret:r,authorizationCode:i,redirectUri:o,codeVerifier:m,resource:c,tokenEndpoint:g}=e,h=g??P.DEFAULT_TOKEN_ENDPOINT;if(!ne(m))throw new Error("Invalid code verifier: must be 43-128 characters using only A-Z, a-z, 0-9, -, ., _, ~");try{let u=new URLSearchParams({grant_type:"authorization_code",code:i,redirect_uri:o,client_id:t,code_verifier:m});r&&u.append("client_secret",r),c&&u.append("resource",c);let l=await pe.default.post(h,u,{headers:{"Content-Type":"application/x-www-form-urlencoded"}}),G=l.data.access_token,R=l.data.refresh_token;return R?new P({clientId:t,clientSecret:r,refreshToken:R,resource:c,tokenEndpoint:h}):new P(G)}catch(u){let l=u instanceof Error?u.message:"Unknown error";throw new Error(`Failed to exchange authorization code: ${l}`)}}static buildAuthorizationUrl(e){let{clientId:t,redirectUri:r,codeChallenge:i,codeChallengeMethod:o="S256",state:m,scope:c,resource:g,authorizationEndpoint:h}=e,u=h??P.DEFAULT_AUTH_ENDPOINT,l=new URLSearchParams({response_type:"code",client_id:t,redirect_uri:r,code_challenge:i,code_challenge_method:o});return m&&l.append("state",m),c&&l.append("scope",c),g&&l.append("resource",g),`${u}?${l.toString()}`}static generatePkce(e="S256"){return ae(e)}parseTokenExpiry(){try{let e=Pe.default.decode(this.accessToken);e&&e.exp&&(this.tokenExpiry=new Date(e.exp*1e3))}catch{this.tokenExpiry=new Date(Date.now()+3600*1e3)}}};P.DEFAULT_TOKEN_ENDPOINT="https://api.timesheet.io/oauth2/token",P.DEFAULT_AUTH_ENDPOINT="https://api.timesheet.io/oauth2/auth";var ce=P;var se=f(require("axios")),E=class E{constructor(e={}){this.cache=new Map;this.options={cacheTtl:e.cacheTtl??E.DEFAULT_CACHE_TTL,timeout:e.timeout??E.DEFAULT_TIMEOUT,fetchOpenIdConfig:e.fetchOpenIdConfig??!1,fetchProtectedResource:e.fetchProtectedResource??!1}}async discover(e){let t=this.normalizeIssuerUrl(e),r=this.getCached(t);if(r)return r;let i=await this.fetchAuthorizationServerMetadata(t),o={issuer:i.issuer,authorizationServer:i,fetchedAt:new Date};if(this.options.fetchOpenIdConfig)try{o.openIdConfiguration=await this.fetchOpenIdConfiguration(t)}catch{}if(this.options.fetchProtectedResource)try{o.protectedResource=await this.fetchProtectedResourceMetadata(t)}catch{}return this.setCache(t,o),o}async fetchAuthorizationServerMetadata(e){let t=`${this.normalizeIssuerUrl(e)}/.well-known/oauth-authorization-server`;try{let r=await se.default.get(t,{timeout:this.options.timeout,headers:{Accept:"application/json"}});return this.validateAuthorizationServerMetadata(r.data),r.data}catch(r){let i=r instanceof Error?r.message:"Unknown error";throw new Error(`Failed to fetch authorization server metadata from ${t}: ${i}`)}}async fetchOpenIdConfiguration(e){let t=`${this.normalizeIssuerUrl(e)}/.well-known/openid-configuration`;try{let r=await se.default.get(t,{timeout:this.options.timeout,headers:{Accept:"application/json"}});return this.validateOpenIdConfiguration(r.data),r.data}catch(r){let i=r instanceof Error?r.message:"Unknown error";throw new Error(`Failed to fetch OpenID configuration from ${t}: ${i}`)}}async fetchProtectedResourceMetadata(e){let t=`${this.normalizeIssuerUrl(e)}/.well-known/oauth-protected-resource`;try{let r=await se.default.get(t,{timeout:this.options.timeout,headers:{Accept:"application/json"}});return this.validateProtectedResourceMetadata(r.data),r.data}catch(r){let i=r instanceof Error?r.message:"Unknown error";throw new Error(`Failed to fetch protected resource metadata from ${t}: ${i}`)}}clearCache(){this.cache.clear()}clearCacheForIssuer(e){this.cache.delete(this.normalizeIssuerUrl(e))}isCached(e){return this.getCached(this.normalizeIssuerUrl(e))!==null}normalizeIssuerUrl(e){return e.replace(/\/+$/,"")}getCached(e){let t=this.cache.get(e);return t?new Date>=t.expiresAt?(this.cache.delete(e),null):t.result:null}setCache(e,t){let r=new Date(Date.now()+this.options.cacheTtl);this.cache.set(e,{result:t,expiresAt:r})}validateAuthorizationServerMetadata(e){if(!e.issuer)throw new Error("Authorization server metadata missing required field: issuer");if(!e.authorization_endpoint)throw new Error("Authorization server metadata missing required field: authorization_endpoint");if(!e.token_endpoint)throw new Error("Authorization server metadata missing required field: token_endpoint");if(!e.response_types_supported||e.response_types_supported.length===0)throw new Error("Authorization server metadata missing required field: response_types_supported")}validateOpenIdConfiguration(e){if(!e.issuer)throw new Error("OpenID configuration missing required field: issuer");if(!e.authorization_endpoint)throw new Error("OpenID configuration missing required field: authorization_endpoint");if(!e.token_endpoint)throw new Error("OpenID configuration missing required field: token_endpoint");if(!e.jwks_uri)throw new Error("OpenID configuration missing required field: jwks_uri")}validateProtectedResourceMetadata(e){if(!e.resource)throw new Error("Protected resource metadata missing required field: resource");if(!e.authorization_servers||e.authorization_servers.length===0)throw new Error("Protected resource metadata missing required field: authorization_servers")}};E.DEFAULT_CACHE_TTL=3600*1e3,E.DEFAULT_TIMEOUT=1e4;var Q=E,he=null;function Te(){return he||(he=new Q),he}async function De(s,e){return(e?new Q(e):Te()).discover(s)}var ee=class s{constructor(e={}){this.maxRetries=e.maxRetries??3,this.initialDelay=e.initialDelay??100,this.maxDelay=e.maxDelay??1e4,this.backoffMultiplier=e.backoffMultiplier??2,this.retryableStatusCodes=e.retryableStatusCodes??[429,502,503,504]}static default(){return new s}};var p=class{constructor(e,t){this.items=e.items,this.params=e.params,this.nextPageLoader=t}get totalPages(){return Math.ceil((this.params?.count||0)/(this.params?.limit||25))}get hasNextPage(){return(this.params?.page||1)<this.totalPages}async nextPage(){if(!this.hasNextPage)throw new Error("No more pages available");if(!this.nextPageLoader)throw new Error("Next page loader not configured");return this.nextPageLoader((this.params.page||1)+1)}async*[Symbol.asyncIterator](){let e=this;for(;;){for(let t of e.items)yield t;if(!e.hasNextPage)break;e=await e.nextPage()}}async toArray(){let e=[];for await(let t of this)e.push(t);return e}};var $e={TEAM_CREATE:"team.create",TEAM_UPDATE:"team.update",PROJECT_CREATE:"project.create",PROJECT_UPDATE:"project.update",TODO_CREATE:"todo.create",TODO_UPDATE:"todo.update",TASK_CREATE:"task.create",TASK_UPDATE:"task.update",TAG_CREATE:"tag.create",TAG_UPDATE:"tag.update",RATE_CREATE:"rate.create",RATE_UPDATE:"rate.update",TIMER_START:"timer.start",TIMER_STOP:"timer.stop",TIMER_PAUSE:"timer.pause",TIMER_RESUME:"timer.resume"};function Ue(...s){return s.join(",")}var a=class{constructor(e,t){this.http=e;typeof t=="string"?this.basePath=t:this.basePath=t.basePath}createNavigablePage(e,t){return new p(e,t)}};var v=class extends a{constructor(e){super(e,"/v1/organizations")}async list(e){let t=await this.http.get(this.basePath,e);return new p(t,r=>this.list({...e,page:r}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,r=>this.search({...e,page:r}))}};var k=class extends a{constructor(e){super(e,"/v1/teams")}async list(e){let t=await this.http.get(this.basePath,e);return new p(t,r=>this.list({...e,page:r}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,r=>this.search({...e,page:r}))}async listMembers(e,t){let r=await this.http.post(`${this.basePath}/${e}/members/list`,t);return this.createNavigablePage(r,i=>this.listMembers(e,{...t,page:i}))}async getMember(e,t){return this.http.get(`${this.basePath}/${e}/members/${t}`)}async getColleagues(e){let t=await this.http.post(`${this.basePath}/getColleagues`,e);return this.createNavigablePage(t,r=>this.getColleagues({...e,page:r}))}};var A=class extends a{constructor(e){super(e,"/v1/projects")}async list(e){let t=await this.http.get(this.basePath,e);return new p(t,r=>this.list({...e,page:r}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,r=>this.search({...e,page:r}))}};var b=f(require("dayjs")),ye=f(require("dayjs/plugin/utc")),be=f(require("dayjs/plugin/timezone")),Re=f(require("dayjs/plugin/customParseFormat"));b.default.extend(ye.default);b.default.extend(be.default);b.default.extend(Re.default);var Ne="YYYY-MM-DDTHH:mm:ssZ",Ie=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{2}:\d{2}$/,n={isValidTimestampFormat(s){return Ie.test(s)},formatTimestamp(s){return typeof s=="string"&&this.isValidTimestampFormat(s)?s:(0,b.default)(s||new Date).format(Ne)},parseTimestamp(s){return(0,b.default)(s).toDate()},formatDate(s){return(0,b.default)(s||new Date).format("YYYY-MM-DD")},now(){return this.formatTimestamp()}};var D=class extends a{constructor(e){super(e,"/v1/tasks")}async create(e){let t={...e,startDateTime:n.formatTimestamp(e.startDateTime),endDateTime:e.endDateTime?n.formatTimestamp(e.endDateTime):void 0};return this.http.post(this.basePath,t)}async update(e,t){let r={...t,startDateTime:t.startDateTime?n.formatTimestamp(t.startDateTime):void 0,endDateTime:t.endDateTime?n.formatTimestamp(t.endDateTime):void 0};return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,r)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,r=>this.search({...e,page:r}))}async updateStatus(e){return this.http.put(`${this.basePath}/updateStatus`,e)}async updateTimes(e){let t={...e,startDateTime:n.formatTimestamp(e.startDateTime),endDateTime:n.formatTimestamp(e.endDateTime)};return this.http.put(`${this.basePath}/updateTimes`,t)}};var $=class extends a{constructor(e){super(e,"/v1/rates")}async list(e){let t=await this.http.get(this.basePath,e);return new p(t,r=>this.list({...e,page:r}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,r=>this.search({...e,page:r}))}};var U=class extends a{constructor(e){super(e,"/v1/tags")}async list(e){let t=await this.http.get(this.basePath,e);return new p(t,r=>this.list({...e,page:r}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,r=>this.search({...e,page:r}))}};var N=class extends a{constructor(e){super(e,"/v1/expenses")}async list(e){let t=await this.http.get(this.basePath,e);return new p(t,r=>this.list({...e,page:r}))}async create(e){let t={...e,dateTime:n.formatTimestamp(e.dateTime)};return this.http.post(this.basePath,t)}async update(e,t){let r={...t,dateTime:t.dateTime?n.formatTimestamp(t.dateTime):void 0};return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,r)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,r=>this.search({...e,page:r}))}async updateStatus(e,t){return this.http.put(`${this.basePath}/${e}/status`,t)}async uploadFile(e,t){let r=new FormData;return r.append("file",t.file,t.fileName),this.http.postMultipart(`${this.basePath}/${encodeURIComponent(e)}/file`,r)}async createWithFile(e){let{file:t,...r}=e,i={...r,dateTime:n.formatTimestamp(r.dateTime)},o=new FormData;return o.append("data",new Blob([JSON.stringify(i)],{type:"application/json"})),t&&o.append("file",t.file,t.fileName),this.http.postMultipart(`${this.basePath}/with-file`,o)}async getFileUrl(e){return this.http.get(`${this.basePath}/getFileUrl/${encodeURIComponent(e)}`)}};var I=class extends a{constructor(e){super(e,"/v1/notes")}async list(e){let t=await this.http.get(this.basePath,e);return new p(t,r=>this.list({...e,page:r}))}async create(e){let t={...e,dateTime:n.formatTimestamp(e.dateTime)};return this.http.post(this.basePath,t)}async update(e,t){let r={...t,dateTime:n.formatTimestamp(t.dateTime)};return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,r)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,r=>this.search({...e,page:r}))}async uploadFile(e,t){let r=new FormData;return r.append("file",t.file,t.fileName),this.http.postMultipart(`${this.basePath}/${encodeURIComponent(e)}/file`,r)}async createWithFile(e){let{file:t,...r}=e,i={...r,dateTime:n.formatTimestamp(r.dateTime)},o=new FormData;return o.append("data",new Blob([JSON.stringify(i)],{type:"application/json"})),t&&o.append("file",t.file,t.fileName),this.http.postMultipart(`${this.basePath}/with-file`,o)}async getFileUrl(e){return this.http.get(`${this.basePath}/getFileUrl/${encodeURIComponent(e)}`)}};var q=class extends a{constructor(e){super(e,"/v1/pauses")}async list(e){let t=await this.http.get(this.basePath,e);return new p(t,r=>this.list({...e,page:r}))}async create(e){let t={...e,startDateTime:n.formatTimestamp(e.startDateTime),endDateTime:n.formatTimestamp(e.endDateTime)};return this.http.post(this.basePath,t)}async update(e,t){let r={...t,startDateTime:n.formatTimestamp(t.startDateTime),endDateTime:n.formatTimestamp(t.endDateTime)};return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,r)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,r=>this.search({...e,page:r}))}};var S=class{constructor(e){this.http=e}async getProfile(){return this.http.get("/v1/profiles/me")}async updateProfile(e){return this.http.put("/v1/profiles/me",e)}};var O=class{constructor(e){this.http=e}async get(){return this.http.get("/v1/settings")}async update(e){return this.http.put("/v1/settings",e)}};var _=class extends a{constructor(e){super(e,"/v1/automations")}async list(e){let t=await this.http.get(this.basePath,e);return new p(t,r=>this.list({...e,page:r}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,r=>this.search({...e,page:r}))}};var L=class extends a{constructor(e){super(e,"/v1/documents")}async list(e){let t=await this.http.get(this.basePath,e);return new p(t,r=>this.list({...e,page:r}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,r=>this.search({...e,page:r}))}};var M=class{constructor(e){this.http=e}async get(){return this.http.get("/v1/timer")}async start(e){let t={...e,startDateTime:e.startDateTime?n.formatTimestamp(e.startDateTime):n.formatTimestamp()};return this.http.post("/v1/timer/start",t)}async stop(e){let t=e?{...e,endDateTime:e.endDateTime?n.formatTimestamp(e.endDateTime):n.formatTimestamp()}:{endDateTime:n.formatTimestamp()};return this.http.post("/v1/timer/stop",t)}async pause(e){let t=e?{...e,startDateTime:e.startDateTime?n.formatTimestamp(e.startDateTime):n.formatTimestamp()}:{startDateTime:n.formatTimestamp()};return this.http.post("/v1/timer/pause",t)}async resume(e){let t=e?{...e,endDateTime:e.endDateTime?n.formatTimestamp(e.endDateTime):n.formatTimestamp()}:{endDateTime:n.formatTimestamp()};return this.http.post("/v1/timer/resume",t)}async update(e){let t={...e,startDateTime:e.startDateTime?n.formatTimestamp(e.startDateTime):void 0};return this.http.put("/v1/timer/update",t)}};var z=class extends a{constructor(e){super(e,"/v1/todos")}async list(e){let t=await this.http.get(this.basePath,e);return new p(t,r=>this.list({...e,page:r}))}async create(e){let t={...e,dueDate:e.dueDate?n.formatTimestamp(e.dueDate):void 0};return this.http.post(this.basePath,t)}async update(e,t){let r={...t,dueDate:t.dueDate?n.formatTimestamp(t.dueDate):void 0};return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,r)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,r=>this.search({...e,page:r}))}};var F=class extends a{constructor(e){super(e,"/v1/webhooks")}async list(e){let t=await this.http.get(this.basePath,e);return new p(t,r=>this.list({...e,page:r}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,r=>this.search({...e,page:r}))}};var j=class extends a{constructor(e){super(e,"/v1/events")}async getStatus(){return this.http.get(`${this.basePath}/status`)}getStreamUrl(){return`${this.http.getBaseUrl()}${this.basePath}/stream`}async subscribe(e){let t=this.getStreamUrl(),i={Accept:"text/event-stream","Cache-Control":"no-cache",...await this.http.getAuthHeaders()},o=new AbortController,m=!1,c=new Map,g={close:()=>{m=!1,o.abort(),e.onClose?.()},get isConnected(){return m},on:(h,u)=>{c.has(h)||c.set(h,new Set),c.get(h).add(u)},off:(h,u)=>{c.get(h)?.delete(u)}};return this.connectSse(t,i,o.signal,{...e,onConnected:h=>{m=!0,e.onConnected?.(h)},onEvent:h=>{e.onEvent?.(h),c.get(h.event)?.forEach(l=>l(h))},onError:h=>{e.onError?.(h),c.get("error")?.forEach(l=>l(h))},onClose:()=>{m=!1,e.onClose?.()}}),g}async connectSse(e,t,r,i){try{let o=await fetch(e,{method:"GET",headers:t,signal:r});if(!o.ok)throw new Error(`SSE connection failed: ${o.status} ${o.statusText}`);if(!o.body)throw new Error("SSE response has no body");let m=o.body.getReader(),c=new TextDecoder,g="",h="",u="",l="",G=!1;for(;!G;){let R=await m.read();if(G=R.done,G||!R.value){i.onClose?.();break}g+=c.decode(R.value,{stream:!0});let me=g.split(`
2
- `);g=me.pop()||"";for(let T of me)T.startsWith("event:")?h=T.slice(6).trim():T.startsWith("data:")?u=T.slice(5).trim():T.startsWith("id:")?l=T.slice(3).trim():T===""&&(u&&this.processEvent(h,u,l,i),h="",u="",l="")}}catch(o){if(r.aborted)return;i.onError?.(o)}}processEvent(e,t,r,i){try{let o=JSON.parse(t);if(e==="connected"){let m=o;i.onConnected?.(m.connectionId)}else i.onEvent?.(o)}catch{i.onError?.(new Error(`Failed to parse event data: ${t}`))}}};var W=class extends a{constructor(e){super(e,"/v1/documents")}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async getPdf(e){return this.http.request({method:"GET",url:`${this.basePath}/${encodeURIComponent(e)}/pdf`,responseType:"arraybuffer"})}async getXml(e){return this.http.request({method:"GET",url:`${this.basePath}/${encodeURIComponent(e)}/xml`,headers:{Accept:"application/xml"}})}};var B=class extends a{constructor(e){super(e,"/v1/tasks")}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async getPdf(e){return this.http.request({method:"GET",url:`${this.basePath}/${encodeURIComponent(e)}/pdf`,responseType:"arraybuffer"})}};var H=class extends a{constructor(e){super(e,"/v1/expenses")}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async getPdf(e){return this.http.request({method:"GET",url:`${this.basePath}/${encodeURIComponent(e)}/pdf`,responseType:"arraybuffer"})}};var K=class extends a{constructor(e){super(e,"/v1/notes")}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async getPdf(e){return this.http.request({method:"GET",url:`${this.basePath}/${encodeURIComponent(e)}/pdf`,responseType:"arraybuffer"})}};var J=class extends a{constructor(e){super(e,"/v1/export")}async generate(e){return this.http.post(`${this.basePath}/data`,e)}async send(e){return this.http.post(`${this.basePath}/send`,e)}async generateFromTemplate(e){return this.http.request({method:"POST",url:`${this.basePath}/from-template`,data:e,responseType:"arraybuffer"})}async getFields(e){return this.http.get(`${this.basePath}/fields`,e?{scope:e}:void 0)}async getReportTypes(){return this.http.get(`${this.basePath}/report-types`)}async listTemplates(e){let t=await this.http.get(`${this.basePath}/templates`,e);return new p(t,r=>this.listTemplates({...e,page:r}))}async searchTemplates(e){let t=await this.http.post(`${this.basePath}/templates/search`,e);return this.createNavigablePage(t,r=>this.searchTemplates({...e,page:r}))}async createTemplate(e){return this.http.post(`${this.basePath}/templates`,e)}async getTemplate(e){return this.http.get(`${this.basePath}/templates/${encodeURIComponent(e)}`)}async updateTemplate(e,t){return this.http.put(`${this.basePath}/templates/${encodeURIComponent(e)}`,t)}async deleteTemplate(e){return this.http.delete(`${this.basePath}/templates/${encodeURIComponent(e)}`)}async listCustomFields(e){return this.http.get(`${this.basePath}/custom-fields`,e?{scope:e}:void 0)}async createCustomField(e){return this.http.post(`${this.basePath}/custom-fields`,e)}async getCustomField(e){return this.http.get(`${this.basePath}/custom-fields/${encodeURIComponent(e)}`)}async updateCustomField(e,t){return this.http.put(`${this.basePath}/custom-fields/${encodeURIComponent(e)}`,t)}async deleteCustomField(e){return this.http.delete(`${this.basePath}/custom-fields/${encodeURIComponent(e)}`)}};var V=class{constructor(e){this.documents=new W(e),this.tasks=new B(e),this.expenses=new H(e),this.notes=new K(e),this.export=new J(e)}};var oe=class{constructor(e){let t=this.createAuthentication(e),r=e.retryConfig||ee.default(),i={baseUrl:e.baseUrl||"https://api.timesheet.io",authentication:t,retryConfig:r,httpClient:e.httpClient};this.apiClient=new C(i);let o={baseUrl:e.reportsBaseUrl||"https://reports.timesheet.io",authentication:t,retryConfig:r,httpClient:e.reportsHttpClient};this.reportsApiClient=new C(o),this.organizations=new v(this.apiClient),this.teams=new k(this.apiClient),this.projects=new A(this.apiClient),this.tasks=new D(this.apiClient),this.rates=new $(this.apiClient),this.tags=new U(this.apiClient),this.expenses=new N(this.apiClient),this.notes=new I(this.apiClient),this.pauses=new q(this.apiClient),this.profile=new S(this.apiClient),this.settings=new O(this.apiClient),this.automations=new _(this.apiClient),this.documents=new L(this.apiClient),this.timer=new M(this.apiClient),this.todos=new z(this.apiClient),this.webhooks=new F(this.apiClient),this.events=new j(this.apiClient),this.reports=new V(this.reportsApiClient)}createAuthentication(e){if(e.apiKey)return new X(e.apiKey);if(e.oauth2Token)return new w(e.oauth2Token);if(e.oauth2)return new w(e.oauth2.clientId,e.oauth2.clientSecret,e.oauth2.refreshToken);if(e.authentication)return e.authentication;throw new Error("Authentication must be configured")}};function qe(s){return new oe(s)}0&&(module.exports={ApiClient,ApiKeyAuth,AutomationResource,DocumentReportResource,DocumentResource,EventResource,ExpenseReportResource,ExpenseResource,ExportResource,NavigablePage,NoteReportResource,NoteResource,OAuth21Auth,OAuth2Auth,OAuthDiscovery,OrganizationResource,PauseResource,ProfileResource,ProjectResource,RateResource,ReportsClient,Resource,RetryConfig,SettingsResource,TagResource,TaskReportResource,TaskResource,TeamResource,TimerResource,TimesheetApiError,TimesheetAuthError,TimesheetClient,TimesheetRateLimitError,TodoResource,WebhookEvents,WebhookResource,combineWebhookEvents,createClient,discoverOAuth,generateCodeChallenge,generateCodeVerifier,generatePkceCodePair,getDefaultDiscovery,isValidCodeVerifier});
1
+ "use strict";var Ee=Object.create;var ae=Object.defineProperty;var $e=Object.getOwnPropertyDescriptor;var ke=Object.getOwnPropertyNames;var Ue=Object.getPrototypeOf,De=Object.prototype.hasOwnProperty;var Ie=(s,e)=>{for(var t in e)ae(s,t,{get:e[t],enumerable:!0})},Pe=(s,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of ke(e))!De.call(s,o)&&o!==t&&ae(s,o,{get:()=>e[o],enumerable:!(r=$e(e,o))||r.enumerable});return s};var P=(s,e,t)=>(t=s!=null?Ee(Ue(s)):{},Pe(e||!s||!s.__esModule?ae(t,"default",{value:s,enumerable:!0}):t,s)),Ne=s=>Pe(ae({},"__esModule",{value:!0}),s);var ze={};Ie(ze,{AbsenceResource:()=>W,AbsenceTypeResource:()=>B,ApiClient:()=>x,ApiKeyAuth:()=>re,AutomationResource:()=>O,ContractResource:()=>H,ContractTemplateResource:()=>K,DocumentReportResource:()=>V,DocumentResource:()=>L,EventResource:()=>j,ExpenseReportResource:()=>G,ExpenseResource:()=>I,ExportResource:()=>Z,NavigablePage:()=>c,NoteReportResource:()=>Y,NoteResource:()=>N,OAuth21Auth:()=>de,OAuth2Auth:()=>v,OAuthDiscovery:()=>se,OrganizationResource:()=>w,PauseResource:()=>q,ProfileResource:()=>M,ProjectResource:()=>$,RateResource:()=>U,ReportsClient:()=>X,Resource:()=>i,RetryConfig:()=>oe,SettingsResource:()=>S,TagResource:()=>D,TaskReportResource:()=>J,TaskResource:()=>k,TeamResource:()=>E,TimerResource:()=>_,TimesheetApiError:()=>l,TimesheetAuthError:()=>ee,TimesheetClient:()=>pe,TimesheetRateLimitError:()=>te,TodoResource:()=>z,WebhookEvents:()=>Me,WebhookResource:()=>F,combineWebhookEvents:()=>Se,createClient:()=>_e,discoverOAuth:()=>qe,generateCodeChallenge:()=>Te,generateCodeVerifier:()=>ye,generatePkceCodePair:()=>me,getDefaultDiscovery:()=>xe,isValidCodeVerifier:()=>he});module.exports=Ne(ze);var C=P(require("axios"));var l=class s extends Error{constructor(e,t,r,o){let a=t?o?`${e} (HTTP ${t}, Code: ${o})`:`${e} (HTTP ${t})`:e;super(a),this.name="TimesheetApiError",this.statusCode=t,this.responseBody=r,this.errorCode=o,typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,s)}};var ee=class extends l{constructor(e,t=401,r){super(e,t,r,"authentication_error"),this.name="TimesheetAuthError"}};var te=class extends l{constructor(e,t){super(e,429,void 0,"rate_limit_exceeded"),this.name="TimesheetRateLimitError",this.retryAfter=t}getRetryAfterDate(){if(!this.retryAfter)return null;let e=Number(this.retryAfter);if(!isNaN(e))return new Date(e*1e3);let t=new Date(this.retryAfter);return isNaN(t.getTime())?null:t}};var fe="1.1.1";var x=class{constructor(e){this.config=e,this.httpClient=e.httpClient||C.default.create({baseURL:e.baseUrl,timeout:3e4,headers:{"User-Agent":`Timesheet-TypeScript-SDK/${fe}`,"Content-Type":"application/json"}}),this.httpClient.interceptors.request.use(async t=>{if(t.url!=="/oauth/token"&&this.config.authentication){let r=await this.config.authentication.getAuthHeaders();if(r)for(let[o,a]of Object.entries(r))t.headers.set(o,a)}return t})}async request(e){let t=null,r=this.config.retryConfig;for(let o=0;o<=r.maxRetries;o++)try{return(await this.httpClient.request(e)).data}catch(a){if(t=a,C.default.isAxiosError(a)&&a.response?.status===401){let p=a.response.data;throw new ee(p?.message||"Authentication failed",401,JSON.stringify(p))}if(C.default.isAxiosError(a)&&a.response?.status===429){let p=a.response.headers["retry-after"];throw new te("Rate limit exceeded",p)}let m=C.default.isAxiosError(a)?a.response?.status:void 0;if(o<r.maxRetries&&m&&r.retryableStatusCodes.includes(m)){let p=Math.min(r.initialDelay*Math.pow(r.backoffMultiplier,o),r.maxDelay);await this.sleep(p);continue}if(C.default.isAxiosError(a)){let p=a.response?.data;throw new l(p?.message||a.message,a.response?.status,JSON.stringify(p),p?.code)}else throw a instanceof Error?new l(a.message):new l("Unknown error occurred")}throw t||new Error("Unknown error")}async get(e,t){return this.request({method:"GET",url:e,params:t})}async post(e,t,r){return this.request({method:"POST",url:e,data:t,params:r})}async put(e,t,r){return this.request({method:"PUT",url:e,data:t,params:r})}async delete(e,t,r){return this.request({method:"DELETE",url:e,data:r,params:t})}async postMultipart(e,t){return this.request({method:"POST",url:e,data:t,headers:{"Content-Type":"multipart/form-data"}})}sleep(e){return new Promise(t=>setTimeout(t,e))}getBaseUrl(){return this.config.baseUrl}async getAuthHeaders(){if(this.config.authentication)return this.config.authentication.getAuthHeaders()}};var re=class{constructor(e){this.apiKey=e;if(e===null)throw new Error("API key cannot be null");if(e===void 0)throw new Error("API key cannot be undefined");if(!e)throw new Error("API key cannot be empty");if(typeof e!="string")throw new Error("API key must be a string");if(e.trim().length===0)throw new Error("API key cannot be empty or whitespace");if(!this.isValidFormat(e))throw new Error("Invalid API key format")}isValidFormat(e){return/^ts_[a-zA-Z0-9]+\.[a-zA-Z0-9]+$/.test(e)}applyAuth(e){e.headers||(e.headers={}),e.headers.Authorization=`ApiKey ${this.apiKey}`}needsRefresh(){return!1}async refresh(){throw new Error("API keys cannot be refreshed")}async getAuthHeaders(){return{Authorization:`ApiKey ${this.apiKey}`}}isValid(){return typeof this.apiKey=="string"&&this.apiKey.trim().length>0&&this.isValidFormat(this.apiKey)}};var ce=P(require("axios")),be=P(require("jsonwebtoken")),y=class y{constructor(e,t,r){t&&r?(this.clientId=e,this.clientSecret=t,this.refreshToken=r,this.accessToken=""):(this.accessToken=e,this.parseTokenExpiry())}applyAuth(e){e.headers||(e.headers={}),e.headers.Authorization=`Bearer ${this.accessToken}`}needsRefresh(){return this.refreshToken&&!this.accessToken?!0:!this.refreshToken||!this.tokenExpiry?!1:new Date(Date.now()+300*1e3)>=this.tokenExpiry}async refresh(){if(!this.refreshToken)throw new Error("Cannot refresh without refresh token");if(this.refreshPromise)return this.refreshPromise;this.refreshPromise=this.performRefresh();try{await this.refreshPromise}finally{this.refreshPromise=void 0}}async performRefresh(){try{let e=await ce.default.post(y.TOKEN_ENDPOINT,new URLSearchParams({grant_type:"refresh_token",refresh_token:this.refreshToken,client_id:this.clientId,client_secret:this.clientSecret}),{headers:{"Content-Type":"application/x-www-form-urlencoded"}});this.accessToken=e.data.access_token,e.data.refresh_token&&(this.refreshToken=e.data.refresh_token),this.parseTokenExpiry()}catch(e){let t=e instanceof Error?e.message:"Unknown error";throw new Error(`Failed to refresh OAuth2 token: ${t}`)}}async getAuthHeaders(){return this.needsRefresh()&&await this.refresh(),{Authorization:`Bearer ${this.accessToken}`}}static async fromAuthorizationCode(e,t,r,o){try{let a=await ce.default.post(y.TOKEN_ENDPOINT,new URLSearchParams({grant_type:"authorization_code",code:r,redirect_uri:o,client_id:e,client_secret:t}),{headers:{"Content-Type":"application/x-www-form-urlencoded"}}),m=a.data.access_token,p=a.data.refresh_token;return p?new y(e,t,p):new y(m)}catch(a){let m=a instanceof Error?a.message:"Unknown error";throw new Error(`Failed to exchange authorization code: ${m}`)}}static buildAuthorizationUrl(e,t,r){let o=new URLSearchParams({client_id:e,redirect_uri:t,response_type:"code"});return r&&o.append("state",r),`https://api.timesheet.io/oauth2/auth?${o.toString()}`}parseTokenExpiry(){try{let e=be.default.decode(this.accessToken);e&&e.exp&&(this.tokenExpiry=new Date(e.exp*1e3))}catch{this.tokenExpiry=new Date(Date.now()+3600*1e3)}}};y.TOKEN_ENDPOINT="https://api.timesheet.io/oauth2/token";var v=y;var ue=P(require("axios")),Ce=P(require("jsonwebtoken"));var ie=require("crypto");function ye(s=64){if(s<43||s>128)throw new Error("Code verifier length must be between 43 and 128 characters");let e=(0,ie.randomBytes)(Math.ceil(s*3/4));return Re(e).slice(0,s)}function Te(s,e="S256"){if(e==="plain")return s;let t=(0,ie.createHash)("sha256").update(s,"ascii").digest();return Re(t)}function me(s="S256",e=64){let t=ye(e),r=Te(t,s);return{codeVerifier:t,codeChallenge:r,codeChallengeMethod:s}}function he(s){return s.length<43||s.length>128?!1:/^[A-Za-z0-9\-._~]+$/.test(s)}function Re(s){return s.toString("base64").replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}var f=class f{constructor(e){if(typeof e=="string")this.accessToken=e,this.tokenEndpoint=f.DEFAULT_TOKEN_ENDPOINT,this.parseTokenExpiry();else{let t=e;this.clientId=t.clientId,this.clientSecret=t.clientSecret,this.refreshToken=t.refreshToken,this.resource=t.resource,this.tokenEndpoint=t.tokenEndpoint??f.DEFAULT_TOKEN_ENDPOINT,this.accessToken=""}}applyAuth(e){e.headers||(e.headers={}),e.headers.Authorization=`Bearer ${this.accessToken}`}needsRefresh(){return this.refreshToken&&!this.accessToken?!0:!this.refreshToken||!this.tokenExpiry?!1:new Date(Date.now()+300*1e3)>=this.tokenExpiry}async refresh(){if(!this.refreshToken)throw new Error("Cannot refresh without refresh token");if(this.refreshPromise)return this.refreshPromise;this.refreshPromise=this.performRefresh();try{await this.refreshPromise}finally{this.refreshPromise=void 0}}async performRefresh(){try{let e=new URLSearchParams({grant_type:"refresh_token",refresh_token:this.refreshToken,client_id:this.clientId});this.clientSecret&&e.append("client_secret",this.clientSecret),this.resource&&e.append("resource",this.resource);let t=await ue.default.post(this.tokenEndpoint,e,{headers:{"Content-Type":"application/x-www-form-urlencoded"}});this.accessToken=t.data.access_token,t.data.refresh_token&&(this.refreshToken=t.data.refresh_token),this.parseTokenExpiry()}catch(e){let t=e instanceof Error?e.message:"Unknown error";throw new Error(`Failed to refresh OAuth 2.1 token: ${t}`)}}async getAuthHeaders(){return this.needsRefresh()&&await this.refresh(),{Authorization:`Bearer ${this.accessToken}`}}static async fromAuthorizationCode(e){let{clientId:t,clientSecret:r,authorizationCode:o,redirectUri:a,codeVerifier:m,resource:p,tokenEndpoint:g}=e,h=g??f.DEFAULT_TOKEN_ENDPOINT;if(!he(m))throw new Error("Invalid code verifier: must be 43-128 characters using only A-Z, a-z, 0-9, -, ., _, ~");try{let u=new URLSearchParams({grant_type:"authorization_code",code:o,redirect_uri:a,client_id:t,code_verifier:m});r&&u.append("client_secret",r),p&&u.append("resource",p);let d=await ue.default.post(h,u,{headers:{"Content-Type":"application/x-www-form-urlencoded"}}),Q=d.data.access_token,R=d.data.refresh_token;return R?new f({clientId:t,clientSecret:r,refreshToken:R,resource:p,tokenEndpoint:h}):new f(Q)}catch(u){let d=u instanceof Error?u.message:"Unknown error";throw new Error(`Failed to exchange authorization code: ${d}`)}}static buildAuthorizationUrl(e){let{clientId:t,redirectUri:r,codeChallenge:o,codeChallengeMethod:a="S256",state:m,scope:p,resource:g,authorizationEndpoint:h}=e,u=h??f.DEFAULT_AUTH_ENDPOINT,d=new URLSearchParams({response_type:"code",client_id:t,redirect_uri:r,code_challenge:o,code_challenge_method:a});return m&&d.append("state",m),p&&d.append("scope",p),g&&d.append("resource",g),`${u}?${d.toString()}`}static generatePkce(e="S256"){return me(e)}parseTokenExpiry(){try{let e=Ce.default.decode(this.accessToken);e&&e.exp&&(this.tokenExpiry=new Date(e.exp*1e3))}catch{this.tokenExpiry=new Date(Date.now()+3600*1e3)}}};f.DEFAULT_TOKEN_ENDPOINT="https://api.timesheet.io/oauth2/token",f.DEFAULT_AUTH_ENDPOINT="https://api.timesheet.io/oauth2/auth";var de=f;var ne=P(require("axios")),A=class A{constructor(e={}){this.cache=new Map;this.options={cacheTtl:e.cacheTtl??A.DEFAULT_CACHE_TTL,timeout:e.timeout??A.DEFAULT_TIMEOUT,fetchOpenIdConfig:e.fetchOpenIdConfig??!1,fetchProtectedResource:e.fetchProtectedResource??!1}}async discover(e){let t=this.normalizeIssuerUrl(e),r=this.getCached(t);if(r)return r;let o=await this.fetchAuthorizationServerMetadata(t),a={issuer:o.issuer,authorizationServer:o,fetchedAt:new Date};if(this.options.fetchOpenIdConfig)try{a.openIdConfiguration=await this.fetchOpenIdConfiguration(t)}catch{}if(this.options.fetchProtectedResource)try{a.protectedResource=await this.fetchProtectedResourceMetadata(t)}catch{}return this.setCache(t,a),a}async fetchAuthorizationServerMetadata(e){let t=`${this.normalizeIssuerUrl(e)}/.well-known/oauth-authorization-server`;try{let r=await ne.default.get(t,{timeout:this.options.timeout,headers:{Accept:"application/json"}});return this.validateAuthorizationServerMetadata(r.data),r.data}catch(r){let o=r instanceof Error?r.message:"Unknown error";throw new Error(`Failed to fetch authorization server metadata from ${t}: ${o}`)}}async fetchOpenIdConfiguration(e){let t=`${this.normalizeIssuerUrl(e)}/.well-known/openid-configuration`;try{let r=await ne.default.get(t,{timeout:this.options.timeout,headers:{Accept:"application/json"}});return this.validateOpenIdConfiguration(r.data),r.data}catch(r){let o=r instanceof Error?r.message:"Unknown error";throw new Error(`Failed to fetch OpenID configuration from ${t}: ${o}`)}}async fetchProtectedResourceMetadata(e){let t=`${this.normalizeIssuerUrl(e)}/.well-known/oauth-protected-resource`;try{let r=await ne.default.get(t,{timeout:this.options.timeout,headers:{Accept:"application/json"}});return this.validateProtectedResourceMetadata(r.data),r.data}catch(r){let o=r instanceof Error?r.message:"Unknown error";throw new Error(`Failed to fetch protected resource metadata from ${t}: ${o}`)}}clearCache(){this.cache.clear()}clearCacheForIssuer(e){this.cache.delete(this.normalizeIssuerUrl(e))}isCached(e){return this.getCached(this.normalizeIssuerUrl(e))!==null}normalizeIssuerUrl(e){return e.replace(/\/+$/,"")}getCached(e){let t=this.cache.get(e);return t?new Date>=t.expiresAt?(this.cache.delete(e),null):t.result:null}setCache(e,t){let r=new Date(Date.now()+this.options.cacheTtl);this.cache.set(e,{result:t,expiresAt:r})}validateAuthorizationServerMetadata(e){if(!e.issuer)throw new Error("Authorization server metadata missing required field: issuer");if(!e.authorization_endpoint)throw new Error("Authorization server metadata missing required field: authorization_endpoint");if(!e.token_endpoint)throw new Error("Authorization server metadata missing required field: token_endpoint");if(!e.response_types_supported||e.response_types_supported.length===0)throw new Error("Authorization server metadata missing required field: response_types_supported")}validateOpenIdConfiguration(e){if(!e.issuer)throw new Error("OpenID configuration missing required field: issuer");if(!e.authorization_endpoint)throw new Error("OpenID configuration missing required field: authorization_endpoint");if(!e.token_endpoint)throw new Error("OpenID configuration missing required field: token_endpoint");if(!e.jwks_uri)throw new Error("OpenID configuration missing required field: jwks_uri")}validateProtectedResourceMetadata(e){if(!e.resource)throw new Error("Protected resource metadata missing required field: resource");if(!e.authorization_servers||e.authorization_servers.length===0)throw new Error("Protected resource metadata missing required field: authorization_servers")}};A.DEFAULT_CACHE_TTL=3600*1e3,A.DEFAULT_TIMEOUT=1e4;var se=A,le=null;function xe(){return le||(le=new se),le}async function qe(s,e){return(e?new se(e):xe()).discover(s)}var oe=class s{constructor(e={}){this.maxRetries=e.maxRetries??3,this.initialDelay=e.initialDelay??100,this.maxDelay=e.maxDelay??1e4,this.backoffMultiplier=e.backoffMultiplier??2,this.retryableStatusCodes=e.retryableStatusCodes??[429,502,503,504]}static default(){return new s}};var c=class{constructor(e,t){this.items=e.items,this.params=e.params,this.nextPageLoader=t}get totalPages(){return Math.ceil((this.params?.count||0)/(this.params?.limit||25))}get hasNextPage(){return(this.params?.page||1)<this.totalPages}async nextPage(){if(!this.hasNextPage)throw new Error("No more pages available");if(!this.nextPageLoader)throw new Error("Next page loader not configured");return this.nextPageLoader((this.params.page||1)+1)}async*[Symbol.asyncIterator](){let e=this;for(;;){for(let t of e.items)yield t;if(!e.hasNextPage)break;e=await e.nextPage()}}async toArray(){let e=[];for await(let t of this)e.push(t);return e}};var Me={TEAM_CREATE:"team.create",TEAM_UPDATE:"team.update",PROJECT_CREATE:"project.create",PROJECT_UPDATE:"project.update",TODO_CREATE:"todo.create",TODO_UPDATE:"todo.update",TASK_CREATE:"task.create",TASK_UPDATE:"task.update",TAG_CREATE:"tag.create",TAG_UPDATE:"tag.update",RATE_CREATE:"rate.create",RATE_UPDATE:"rate.update",TIMER_START:"timer.start",TIMER_STOP:"timer.stop",TIMER_PAUSE:"timer.pause",TIMER_RESUME:"timer.resume"};function Se(...s){return s.join(",")}var i=class{constructor(e,t){this.http=e;typeof t=="string"?this.basePath=t:this.basePath=t.basePath}createNavigablePage(e,t){return new c(e,t)}};var w=class extends i{constructor(e){super(e,"/v1/organizations")}async list(e){let t=await this.http.get(this.basePath,e);return new c(t,r=>this.list({...e,page:r}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,r=>this.search({...e,page:r}))}async listMembers(e,t){let r=await this.http.post(`${this.basePath}/${encodeURIComponent(e)}/members/list`,t);return this.createNavigablePage(r,o=>this.listMembers(e,{...t,page:o}))}async getMember(e,t){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}/members/${encodeURIComponent(t)}`)}async addMember(e,t){return this.http.post(`${this.basePath}/${encodeURIComponent(e)}/members`,t)}async updateMember(e,t,r){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}/members/${encodeURIComponent(t)}`,r)}async removeMember(e,t){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}/members/${encodeURIComponent(t)}`)}};var E=class extends i{constructor(e){super(e,"/v1/teams")}async list(e){let t=await this.http.get(this.basePath,e);return new c(t,r=>this.list({...e,page:r}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,r=>this.search({...e,page:r}))}async listMembers(e,t){let r=await this.http.post(`${this.basePath}/${e}/members/list`,t);return this.createNavigablePage(r,o=>this.listMembers(e,{...t,page:o}))}async getMember(e,t){return this.http.get(`${this.basePath}/${e}/members/${t}`)}async getColleagues(e){let t=await this.http.post(`${this.basePath}/getColleagues`,e);return this.createNavigablePage(t,r=>this.getColleagues({...e,page:r}))}async addMember(e,t){return this.http.post(`${this.basePath}/${e}/members`,t)}async updateMember(e,t,r){return this.http.put(`${this.basePath}/${e}/members/${t}`,r)}async removeMember(e,t){return this.http.delete(`${this.basePath}/${e}/members/${t}`)}async removeInvitedMember(e,t){return this.http.delete(`${this.basePath}/${e}/members/${t}/invited`)}async batchAddMembers(e){return this.http.post(`${this.basePath}/batchTeamMembers`,e)}async getMemberStatus(e){let t=await this.http.post(`${this.basePath}/getMemberStatus`,e);return this.createNavigablePage(t,r=>this.getMemberStatus({...e,page:r}))}};var $=class extends i{constructor(e){super(e,"/v1/projects")}async list(e){let t=await this.http.get(this.basePath,e);return new c(t,r=>this.list({...e,page:r}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,r=>this.search({...e,page:r}))}async listMembers(e,t){let r=await this.http.post(`${this.basePath}/${encodeURIComponent(e)}/members/list`,t);return this.createNavigablePage(r,o=>this.listMembers(e,{...t,page:o}))}async addMember(e,t){return this.http.post(`${this.basePath}/${encodeURIComponent(e)}/members`,t)}async getMember(e,t){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}/members/${encodeURIComponent(t)}`)}async updateMember(e,t,r){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}/members/${encodeURIComponent(t)}`,r)}async updateMembers(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}/members`,t)}async removeMember(e,t){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}/members/${encodeURIComponent(t)}`)}async batchAddMembers(e,t){return this.http.post(`${this.basePath}/${encodeURIComponent(e)}/members/batch`,t)}async batchRemoveMembers(e,t){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}/members/batch`,void 0,t)}};var T=P(require("dayjs")),ve=P(require("dayjs/plugin/utc")),Ae=P(require("dayjs/plugin/timezone")),we=P(require("dayjs/plugin/customParseFormat"));T.default.extend(ve.default);T.default.extend(Ae.default);T.default.extend(we.default);var Oe="YYYY-MM-DDTHH:mm:ssZ",Le=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{2}:\d{2}$/,n={isValidTimestampFormat(s){return Le.test(s)},formatTimestamp(s){return typeof s=="string"&&this.isValidTimestampFormat(s)?s:(0,T.default)(s||new Date).format(Oe)},parseTimestamp(s){return(0,T.default)(s).toDate()},formatDate(s){return(0,T.default)(s||new Date).format("YYYY-MM-DD")},now(){return this.formatTimestamp()}};var k=class extends i{constructor(e){super(e,"/v1/tasks")}async list(e){let t=await this.http.get(this.basePath,e);return this.createNavigablePage(t,r=>this.list({...e,page:r}))}async create(e){let t={...e,startDateTime:n.formatTimestamp(e.startDateTime),endDateTime:e.endDateTime?n.formatTimestamp(e.endDateTime):void 0};return this.http.post(this.basePath,t)}async update(e,t){let r={...t,startDateTime:t.startDateTime?n.formatTimestamp(t.startDateTime):void 0,endDateTime:t.endDateTime?n.formatTimestamp(t.endDateTime):void 0};return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,r)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,r=>this.search({...e,page:r}))}async statistics(e){return this.http.post(`${this.basePath}/statistics`,e)}async updateStatus(e){return this.http.put(`${this.basePath}/updateStatus`,e)}async updateTimes(e){let t={...e,start:n.formatTimestamp(e.start),end:n.formatTimestamp(e.end)};return this.http.put(`${this.basePath}/updateTimes`,t)}async print(e){return this.http.request({method:"GET",url:`${this.basePath}/print/${encodeURIComponent(e)}`,responseType:"arraybuffer"})}};var U=class extends i{constructor(e){super(e,"/v1/rates")}async list(e){let t=await this.http.get(this.basePath,e);return new c(t,r=>this.list({...e,page:r}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,r=>this.search({...e,page:r}))}};var D=class extends i{constructor(e){super(e,"/v1/tags")}async list(e){let t=await this.http.get(this.basePath,e);return this.createNavigablePage(t,r=>this.list({...e,page:r}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,r=>this.search({...e,page:r}))}};var I=class extends i{constructor(e){super(e,"/v1/expenses")}async list(e){let t=await this.http.get(this.basePath,e);return new c(t,r=>this.list({...e,page:r}))}async create(e){let t={...e,dateTime:n.formatTimestamp(e.dateTime)};return this.http.post(this.basePath,t)}async update(e,t){let r={...t,dateTime:t.dateTime?n.formatTimestamp(t.dateTime):void 0};return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,r)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,r=>this.search({...e,page:r}))}async updateStatus(e){return this.http.put(`${this.basePath}/updateStatus`,e)}async uploadFile(e,t){let r=new FormData;return r.append("file",t.file,t.fileName),this.http.postMultipart(`${this.basePath}/${encodeURIComponent(e)}/file`,r)}async createWithFile(e){let{file:t,...r}=e,o={...r,dateTime:n.formatTimestamp(r.dateTime)},a=new FormData;return a.append("data",new Blob([JSON.stringify(o)],{type:"application/json"})),t&&a.append("file",t.file,t.fileName),this.http.postMultipart(`${this.basePath}/with-file`,a)}async getFileUrl(e){return this.http.get(`${this.basePath}/getFileUrl/${encodeURIComponent(e)}`)}};var N=class extends i{constructor(e){super(e,"/v1/notes")}async list(e){let t=await this.http.get(this.basePath,e);return new c(t,r=>this.list({...e,page:r}))}async create(e){let t={...e,dateTime:n.formatTimestamp(e.dateTime)};return this.http.post(this.basePath,t)}async update(e,t){let r={...t,dateTime:n.formatTimestamp(t.dateTime)};return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,r)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,r=>this.search({...e,page:r}))}async uploadFile(e,t){let r=new FormData;return r.append("file",t.file,t.fileName),this.http.postMultipart(`${this.basePath}/${encodeURIComponent(e)}/file`,r)}async createWithFile(e){let{file:t,...r}=e,o={...r,dateTime:n.formatTimestamp(r.dateTime)},a=new FormData;return a.append("data",new Blob([JSON.stringify(o)],{type:"application/json"})),t&&a.append("file",t.file,t.fileName),this.http.postMultipart(`${this.basePath}/with-file`,a)}async getFileUrl(e){return this.http.get(`${this.basePath}/getFileUrl/${encodeURIComponent(e)}`)}};var q=class extends i{constructor(e){super(e,"/v1/pauses")}async list(e){let t=await this.http.get(this.basePath,e);return new c(t,r=>this.list({...e,page:r}))}async create(e){let t={...e,startDateTime:n.formatTimestamp(e.startDateTime),endDateTime:n.formatTimestamp(e.endDateTime)};return this.http.post(this.basePath,t)}async update(e,t){let r={...t,startDateTime:n.formatTimestamp(t.startDateTime),endDateTime:n.formatTimestamp(t.endDateTime)};return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,r)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,r=>this.search({...e,page:r}))}};var M=class{constructor(e){this.http=e}async getProfile(){return this.http.get("/v1/profiles/me")}async updateProfile(e){return this.http.put("/v1/profiles/me",e)}};var S=class{constructor(e){this.http=e}async get(){return this.http.get("/v1/settings")}async update(e){return this.http.put("/v1/settings",e)}};var O=class extends i{constructor(e){super(e,"/v1/automations")}async list(e){let t=await this.http.get(this.basePath,e);return new c(t,r=>this.list({...e,page:r}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,r=>this.search({...e,page:r}))}};var L=class extends i{constructor(e){super(e,"/v1/documents")}async list(e){let{category:t,...r}=e??{},o=t!==void 0?{...r,type:t}:{...r},a=await this.http.get(this.basePath,o);return new c(a,m=>this.list({...e,page:m}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,r=>this.search({...e,page:r}))}};var _=class{constructor(e){this.http=e}async get(){return this.http.get("/v1/timer")}async start(e){let t={...e,startDateTime:e.startDateTime?n.formatTimestamp(e.startDateTime):n.formatTimestamp()};return this.http.post("/v1/timer/start",t)}async stop(e){let t=e?{...e,endDateTime:e.endDateTime?n.formatTimestamp(e.endDateTime):n.formatTimestamp()}:{endDateTime:n.formatTimestamp()};return this.http.post("/v1/timer/stop",t)}async pause(e){let t=e?{...e,startDateTime:e.startDateTime?n.formatTimestamp(e.startDateTime):n.formatTimestamp()}:{startDateTime:n.formatTimestamp()};return this.http.post("/v1/timer/pause",t)}async resume(e){let t=e?{...e,endDateTime:e.endDateTime?n.formatTimestamp(e.endDateTime):n.formatTimestamp()}:{endDateTime:n.formatTimestamp()};return this.http.post("/v1/timer/resume",t)}async update(e){let t={...e,startDateTime:e.startDateTime?n.formatTimestamp(e.startDateTime):void 0};return this.http.put("/v1/timer/update",t)}};var z=class extends i{constructor(e){super(e,"/v1/todos")}async list(e){let t=await this.http.get(this.basePath,e);return this.createNavigablePage(t,r=>this.list({...e,page:r}))}async create(e){let t={...e,dueDate:e.dueDate?n.formatTimestamp(e.dueDate):void 0};return this.http.post(this.basePath,t)}async update(e,t){let r={...t,dueDate:t.dueDate?n.formatTimestamp(t.dueDate):void 0};return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,r)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,r=>this.search({...e,page:r}))}};var F=class extends i{constructor(e){super(e,"/v1/webhooks")}async list(e){let t=await this.http.get(this.basePath,e);return new c(t,r=>this.list({...e,page:r}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,r=>this.search({...e,page:r}))}};var j=class extends i{constructor(e){super(e,"/v1/events")}async getStatus(){return this.http.get(`${this.basePath}/status`)}getStreamUrl(){return`${this.http.getBaseUrl()}${this.basePath}/stream`}async subscribe(e){let t=this.getStreamUrl(),o={Accept:"text/event-stream","Cache-Control":"no-cache",...await this.http.getAuthHeaders()},a=new AbortController,m=!1,p=new Map,g={close:()=>{m=!1,a.abort(),e.onClose?.()},get isConnected(){return m},on:(h,u)=>{p.has(h)||p.set(h,new Set),p.get(h).add(u)},off:(h,u)=>{p.get(h)?.delete(u)}};return this.connectSse(t,o,a.signal,{...e,onConnected:h=>{m=!0,e.onConnected?.(h)},onEvent:h=>{e.onEvent?.(h),p.get(h.event)?.forEach(d=>d(h))},onError:h=>{e.onError?.(h),p.get("error")?.forEach(d=>d(h))},onClose:()=>{m=!1,e.onClose?.()}}),g}async connectSse(e,t,r,o){try{let a=await fetch(e,{method:"GET",headers:t,signal:r});if(!a.ok)throw new Error(`SSE connection failed: ${a.status} ${a.statusText}`);if(!a.body)throw new Error("SSE response has no body");let m=a.body.getReader(),p=new TextDecoder,g="",h="",u="",d="",Q=!1;for(;!Q;){let R=await m.read();if(Q=R.done,Q||!R.value){o.onClose?.();break}g+=p.decode(R.value,{stream:!0});let ge=g.split(`
2
+ `);g=ge.pop()||"";for(let b of ge)b.startsWith("event:")?h=b.slice(6).trim():b.startsWith("data:")?u=b.slice(5).trim():b.startsWith("id:")?d=b.slice(3).trim():b===""&&(u&&this.processEvent(h,u,d,o),h="",u="",d="")}}catch(a){if(r.aborted)return;o.onError?.(a)}}processEvent(e,t,r,o){try{let a=JSON.parse(t);if(e==="connected"){let m=a;o.onConnected?.(m.connectionId)}else o.onEvent?.(a)}catch{o.onError?.(new Error(`Failed to parse event data: ${t}`))}}};var W=class extends i{constructor(e){super(e,"/v1/organizations")}orgPath(e){return`${this.basePath}/${encodeURIComponent(e)}/absences`}async list(e,t){let r=await this.http.get(this.orgPath(e),t);return this.createNavigablePage(r,o=>this.list(e,{...t,page:o}))}async search(e,t){let r=await this.http.post(`${this.orgPath(e)}/search`,t);return this.createNavigablePage(r,o=>this.search(e,{...t,page:o}))}async create(e,t){return this.http.post(this.orgPath(e),t)}async get(e,t){return this.http.get(`${this.orgPath(e)}/${encodeURIComponent(t)}`)}async update(e,t,r){return this.http.put(`${this.orgPath(e)}/${encodeURIComponent(t)}`,r)}async delete(e,t){return this.http.delete(`${this.orgPath(e)}/${encodeURIComponent(t)}`)}async approve(e,t){return this.http.post(`${this.orgPath(e)}/${encodeURIComponent(t)}/approve`)}async reject(e,t,r){return this.http.post(`${this.orgPath(e)}/${encodeURIComponent(t)}/reject`,r)}async cancel(e,t,r){return this.http.post(`${this.orgPath(e)}/${encodeURIComponent(t)}/cancel`,r)}};var B=class extends i{constructor(e){super(e,"/v1/organizations")}orgPath(e){return`${this.basePath}/${encodeURIComponent(e)}/absence-types`}async list(e,t){let r=await this.http.get(this.orgPath(e),t);return this.createNavigablePage(r,o=>this.list(e,{...t,page:o}))}async create(e,t){return this.http.post(this.orgPath(e),t)}async get(e,t){return this.http.get(`${this.orgPath(e)}/${encodeURIComponent(t)}`)}async update(e,t,r){return this.http.put(`${this.orgPath(e)}/${encodeURIComponent(t)}`,r)}async delete(e,t){return this.http.delete(`${this.orgPath(e)}/${encodeURIComponent(t)}`)}};var H=class extends i{constructor(e){super(e,"/v1/organizations")}orgPath(e){return`${this.basePath}/${encodeURIComponent(e)}/contracts`}async list(e,t){let r=await this.http.get(this.orgPath(e),t);return this.createNavigablePage(r,o=>this.list(e,{...t,page:o}))}async create(e,t){return this.http.post(this.orgPath(e),t)}async get(e,t){return this.http.get(`${this.orgPath(e)}/${encodeURIComponent(t)}`)}async update(e,t,r){return this.http.put(`${this.orgPath(e)}/${encodeURIComponent(t)}`,r)}async delete(e,t){return this.http.delete(`${this.orgPath(e)}/${encodeURIComponent(t)}`)}async activate(e,t){return this.http.put(`${this.orgPath(e)}/${encodeURIComponent(t)}/activate`)}async suspend(e,t){return this.http.put(`${this.orgPath(e)}/${encodeURIComponent(t)}/suspend`)}async reactivate(e,t){return this.http.put(`${this.orgPath(e)}/${encodeURIComponent(t)}/reactivate`)}async terminate(e,t){return this.http.put(`${this.orgPath(e)}/${encodeURIComponent(t)}/terminate`)}};var K=class extends i{constructor(e){super(e,"/v1/organizations")}orgPath(e){return`${this.basePath}/${encodeURIComponent(e)}/contract-templates`}async list(e,t){let r=await this.http.get(this.orgPath(e),t);return this.createNavigablePage(r,o=>this.list(e,{...t,page:o}))}async create(e,t){return this.http.post(this.orgPath(e),t)}async get(e,t){return this.http.get(`${this.orgPath(e)}/${encodeURIComponent(t)}`)}async update(e,t,r){return this.http.put(`${this.orgPath(e)}/${encodeURIComponent(t)}`,r)}async delete(e,t){return this.http.delete(`${this.orgPath(e)}/${encodeURIComponent(t)}`)}};var V=class extends i{constructor(e){super(e,"/v1/documents")}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async getPdf(e){return this.http.request({method:"GET",url:`${this.basePath}/${encodeURIComponent(e)}/pdf`,responseType:"arraybuffer"})}async getXml(e){return this.http.request({method:"GET",url:`${this.basePath}/${encodeURIComponent(e)}/xml`,headers:{Accept:"application/xml"}})}};var J=class extends i{constructor(e){super(e,"/v1/tasks")}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async getPdf(e){return this.http.request({method:"GET",url:`${this.basePath}/${encodeURIComponent(e)}/pdf`,responseType:"arraybuffer"})}};var G=class extends i{constructor(e){super(e,"/v1/expenses")}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async getPdf(e){return this.http.request({method:"GET",url:`${this.basePath}/${encodeURIComponent(e)}/pdf`,responseType:"arraybuffer"})}};var Y=class extends i{constructor(e){super(e,"/v1/notes")}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async getPdf(e){return this.http.request({method:"GET",url:`${this.basePath}/${encodeURIComponent(e)}/pdf`,responseType:"arraybuffer"})}};var Z=class extends i{constructor(e){super(e,"/v1/export")}async generate(e){return this.http.post(`${this.basePath}/data`,e)}async send(e){return this.http.post(`${this.basePath}/send`,e)}async generateFromTemplate(e){return this.http.request({method:"POST",url:`${this.basePath}/from-template`,data:e,responseType:"arraybuffer"})}async getFields(e){return this.http.get(`${this.basePath}/fields`,e?{scope:e}:void 0)}async getReportTypes(){return this.http.get(`${this.basePath}/report-types`)}async listTemplates(e){let t=await this.http.get(`${this.basePath}/templates`,e);return new c(t,r=>this.listTemplates({...e,page:r}))}async searchTemplates(e){let t=await this.http.post(`${this.basePath}/templates/search`,e);return this.createNavigablePage(t,r=>this.searchTemplates({...e,page:r}))}async createTemplate(e){return this.http.post(`${this.basePath}/templates`,e)}async getTemplate(e){return this.http.get(`${this.basePath}/templates/${encodeURIComponent(e)}`)}async updateTemplate(e,t){return this.http.put(`${this.basePath}/templates/${encodeURIComponent(e)}`,t)}async deleteTemplate(e){return this.http.delete(`${this.basePath}/templates/${encodeURIComponent(e)}`)}async listCustomFields(e){return this.http.get(`${this.basePath}/custom-fields`,e?{scope:e}:void 0)}async createCustomField(e){return this.http.post(`${this.basePath}/custom-fields`,e)}async getCustomField(e){return this.http.get(`${this.basePath}/custom-fields/${encodeURIComponent(e)}`)}async updateCustomField(e,t){return this.http.put(`${this.basePath}/custom-fields/${encodeURIComponent(e)}`,t)}async deleteCustomField(e){return this.http.delete(`${this.basePath}/custom-fields/${encodeURIComponent(e)}`)}};var X=class{constructor(e){this.documents=new V(e),this.tasks=new J(e),this.expenses=new G(e),this.notes=new Y(e),this.export=new Z(e)}};var pe=class{constructor(e){let t=this.createAuthentication(e),r=e.retryConfig||oe.default(),o={baseUrl:e.baseUrl||"https://api.timesheet.io",authentication:t,retryConfig:r,httpClient:e.httpClient};this.apiClient=new x(o);let a={baseUrl:e.reportsBaseUrl||"https://reports.timesheet.io",authentication:t,retryConfig:r,httpClient:e.reportsHttpClient};this.reportsApiClient=new x(a),this.organizations=new w(this.apiClient),this.teams=new E(this.apiClient),this.projects=new $(this.apiClient),this.tasks=new k(this.apiClient),this.rates=new U(this.apiClient),this.tags=new D(this.apiClient),this.expenses=new I(this.apiClient),this.notes=new N(this.apiClient),this.pauses=new q(this.apiClient),this.profile=new M(this.apiClient),this.settings=new S(this.apiClient),this.automations=new O(this.apiClient),this.documents=new L(this.apiClient),this.timer=new _(this.apiClient),this.todos=new z(this.apiClient),this.webhooks=new F(this.apiClient),this.events=new j(this.apiClient),this.absences=new W(this.apiClient),this.absenceTypes=new B(this.apiClient),this.contracts=new H(this.apiClient),this.contractTemplates=new K(this.apiClient),this.reports=new X(this.reportsApiClient)}createAuthentication(e){if(e.apiKey)return new re(e.apiKey);if(e.oauth2Token)return new v(e.oauth2Token);if(e.oauth2)return new v(e.oauth2.clientId,e.oauth2.clientSecret,e.oauth2.refreshToken);if(e.authentication)return e.authentication;throw new Error("Authentication must be configured")}};function _e(s){return new pe(s)}0&&(module.exports={AbsenceResource,AbsenceTypeResource,ApiClient,ApiKeyAuth,AutomationResource,ContractResource,ContractTemplateResource,DocumentReportResource,DocumentResource,EventResource,ExpenseReportResource,ExpenseResource,ExportResource,NavigablePage,NoteReportResource,NoteResource,OAuth21Auth,OAuth2Auth,OAuthDiscovery,OrganizationResource,PauseResource,ProfileResource,ProjectResource,RateResource,ReportsClient,Resource,RetryConfig,SettingsResource,TagResource,TaskReportResource,TaskResource,TeamResource,TimerResource,TimesheetApiError,TimesheetAuthError,TimesheetClient,TimesheetRateLimitError,TodoResource,WebhookEvents,WebhookResource,combineWebhookEvents,createClient,discoverOAuth,generateCodeChallenge,generateCodeVerifier,generatePkceCodePair,getDefaultDiscovery,isValidCodeVerifier});
3
3
  //# sourceMappingURL=index.js.map