@timesheet/sdk 1.0.6 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +67 -1
- package/README.md +103 -16
- package/dist/http/ApiClient.d.ts +1 -1
- package/dist/http/ApiClient.d.ts.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +4 -4
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +4 -4
- package/dist/models/Absence.d.ts +136 -0
- package/dist/models/Absence.d.ts.map +1 -0
- package/dist/models/Automation.d.ts +6 -1
- package/dist/models/Automation.d.ts.map +1 -1
- package/dist/models/Contract.d.ts +141 -0
- package/dist/models/Contract.d.ts.map +1 -0
- package/dist/models/Document.d.ts +192 -87
- package/dist/models/Document.d.ts.map +1 -1
- package/dist/models/Expense.d.ts +4 -3
- package/dist/models/Expense.d.ts.map +1 -1
- package/dist/models/Note.d.ts +3 -2
- package/dist/models/Note.d.ts.map +1 -1
- package/dist/models/Organization.d.ts +58 -1
- package/dist/models/Organization.d.ts.map +1 -1
- package/dist/models/Pause.d.ts +2 -2
- package/dist/models/Pause.d.ts.map +1 -1
- package/dist/models/Profile.d.ts +13 -1
- package/dist/models/Profile.d.ts.map +1 -1
- package/dist/models/Project.d.ts +52 -27
- package/dist/models/Project.d.ts.map +1 -1
- package/dist/models/Rate.d.ts +7 -6
- package/dist/models/Rate.d.ts.map +1 -1
- package/dist/models/Reports.d.ts +32 -15
- package/dist/models/Reports.d.ts.map +1 -1
- package/dist/models/Tag.d.ts +6 -2
- package/dist/models/Tag.d.ts.map +1 -1
- package/dist/models/Task.d.ts +14 -22
- package/dist/models/Task.d.ts.map +1 -1
- package/dist/models/Team.d.ts +55 -11
- package/dist/models/Team.d.ts.map +1 -1
- package/dist/models/Timer.d.ts +4 -0
- package/dist/models/Timer.d.ts.map +1 -1
- package/dist/models/Todo.d.ts +8 -7
- package/dist/models/Todo.d.ts.map +1 -1
- package/dist/models/Webhook.d.ts +3 -0
- package/dist/models/Webhook.d.ts.map +1 -1
- package/dist/models/common.d.ts +2 -0
- package/dist/models/common.d.ts.map +1 -1
- package/dist/models/index.d.ts +2 -0
- package/dist/models/index.d.ts.map +1 -1
- package/dist/resources/AbsenceResource.d.ts +18 -0
- package/dist/resources/AbsenceResource.d.ts.map +1 -0
- package/dist/resources/AbsenceTypeResource.d.ts +14 -0
- package/dist/resources/AbsenceTypeResource.d.ts.map +1 -0
- package/dist/resources/ContractResource.d.ts +18 -0
- package/dist/resources/ContractResource.d.ts.map +1 -0
- package/dist/resources/ContractTemplateResource.d.ts +14 -0
- package/dist/resources/ContractTemplateResource.d.ts.map +1 -0
- package/dist/resources/DocumentResource.d.ts.map +1 -1
- package/dist/resources/ExpenseResource.d.ts +1 -1
- package/dist/resources/ExpenseResource.d.ts.map +1 -1
- package/dist/resources/OrganizationResource.d.ts +6 -1
- package/dist/resources/OrganizationResource.d.ts.map +1 -1
- package/dist/resources/ProjectResource.d.ts +9 -1
- package/dist/resources/ProjectResource.d.ts.map +1 -1
- package/dist/resources/TagResource.d.ts.map +1 -1
- package/dist/resources/TaskResource.d.ts +4 -1
- package/dist/resources/TaskResource.d.ts.map +1 -1
- package/dist/resources/TeamResource.d.ts +8 -2
- package/dist/resources/TeamResource.d.ts.map +1 -1
- package/dist/resources/TodoResource.d.ts.map +1 -1
- package/dist/resources/index.d.ts +4 -0
- package/dist/resources/index.d.ts.map +1 -1
- package/dist/resources/reports/ExportResource.d.ts +1 -1
- package/dist/resources/reports/ExportResource.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/http/ApiClient.ts", "../src/exceptions/TimesheetApiError.ts", "../src/exceptions/TimesheetAuthError.ts", "../src/exceptions/TimesheetRateLimitError.ts", "../src/auth/ApiKeyAuth.ts", "../src/auth/OAuth2Auth.ts", "../src/auth/OAuth21Auth.ts", "../src/auth/pkce.ts", "../src/auth/OAuthDiscovery.ts", "../src/config/RetryConfig.ts", "../src/models/Page.ts", "../src/models/Webhook.ts", "../src/resources/Resource.ts", "../src/resources/OrganizationResource.ts", "../src/resources/TeamResource.ts", "../src/resources/ProjectResource.ts", "../src/utils/date.ts", "../src/resources/TaskResource.ts", "../src/resources/RateResource.ts", "../src/resources/TagResource.ts", "../src/resources/ExpenseResource.ts", "../src/resources/NoteResource.ts", "../src/resources/PauseResource.ts", "../src/resources/ProfileResource.ts", "../src/resources/SettingsResource.ts", "../src/resources/AutomationResource.ts", "../src/resources/DocumentResource.ts", "../src/resources/TimerResource.ts", "../src/resources/TodoResource.ts", "../src/resources/WebhookResource.ts", "../src/resources/EventResource.ts", "../src/resources/reports/DocumentReportResource.ts", "../src/resources/reports/TaskReportResource.ts", "../src/resources/reports/ExpenseReportResource.ts", "../src/resources/reports/NoteReportResource.ts", "../src/resources/reports/ExportResource.ts", "../src/resources/reports/ReportsClient.ts", "../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["import type { AxiosInstance, AxiosRequestConfig } from 'axios';\nimport axios from 'axios';\nimport type { ClientConfig } from '../config';\nimport { TimesheetApiError, TimesheetAuthError, TimesheetRateLimitError } from '../exceptions';\n\ninterface ErrorResponseData {\n message?: string;\n code?: string;\n}\n\n/**\n * HTTP client for making API requests.\n */\nexport class ApiClient {\n private readonly config: ClientConfig;\n private readonly httpClient: AxiosInstance;\n\n constructor(config: ClientConfig) {\n this.config = config;\n this.httpClient =\n config.httpClient ||\n axios.create({\n baseURL: config.baseUrl,\n timeout: 30000,\n headers: {\n 'User-Agent': 'Timesheet-TypeScript-SDK/1.0.0',\n 'Content-Type': 'application/json',\n },\n });\n\n // Request interceptor for authentication\n this.httpClient.interceptors.request.use(async (config) => {\n // Add authentication headers if configured\n if (config.url !== '/oauth/token' && this.config.authentication) {\n const authHeaders = await this.config.authentication.getAuthHeaders();\n if (authHeaders) {\n // Set headers directly to avoid type issues\n for (const [key, value] of Object.entries(authHeaders)) {\n config.headers.set(key, value);\n }\n }\n }\n\n return config;\n });\n }\n\n /**\n * Makes an HTTP request with retry support.\n */\n async request<T>(config: AxiosRequestConfig): Promise<T> {\n let lastError: Error | null = null;\n const retryConfig = this.config.retryConfig;\n\n for (let attempt = 0; attempt <= retryConfig.maxRetries; attempt++) {\n try {\n const response = await this.httpClient.request<T>(config);\n return response.data;\n } catch (error) {\n lastError = error as Error;\n\n // Handle authentication errors\n if (axios.isAxiosError<ErrorResponseData>(error) && error.response?.status === 401) {\n const errorData = error.response.data;\n throw new TimesheetAuthError(\n errorData?.message || 'Authentication failed',\n 401,\n JSON.stringify(errorData),\n );\n }\n\n // Handle rate limit errors\n if (axios.isAxiosError(error) && error.response?.status === 429) {\n const retryAfter = error.response.headers['retry-after'] as string | undefined;\n throw new TimesheetRateLimitError('Rate limit exceeded', retryAfter);\n }\n\n // Check if we should retry\n const status = axios.isAxiosError(error) ? error.response?.status : undefined;\n if (\n attempt < retryConfig.maxRetries &&\n status &&\n retryConfig.retryableStatusCodes.includes(status)\n ) {\n // Calculate delay with exponential backoff\n const delay = Math.min(\n retryConfig.initialDelay * Math.pow(retryConfig.backoffMultiplier, attempt),\n retryConfig.maxDelay,\n );\n\n await this.sleep(delay);\n continue;\n }\n\n // Non-retryable error\n if (axios.isAxiosError<ErrorResponseData>(error)) {\n const errorData = error.response?.data;\n throw new TimesheetApiError(\n errorData?.message || error.message,\n error.response?.status,\n JSON.stringify(errorData),\n errorData?.code,\n );\n } else if (error instanceof Error) {\n throw new TimesheetApiError(error.message);\n } else {\n throw new TimesheetApiError('Unknown error occurred');\n }\n }\n }\n\n // This should never happen, but TypeScript needs it\n throw lastError || new Error('Unknown error');\n }\n\n /**\n * GET request.\n */\n async get<T, P = Record<string, unknown>>(path: string, params?: P): Promise<T> {\n return this.request<T>({\n method: 'GET',\n url: path,\n params: params as Record<string, unknown>,\n });\n }\n\n /**\n * POST request.\n */\n async post<T, P = Record<string, unknown>>(path: string, data?: unknown, params?: P): Promise<T> {\n return this.request<T>({\n method: 'POST',\n url: path,\n data,\n params: params as Record<string, unknown>,\n });\n }\n\n /**\n * PUT request.\n */\n async put<T, P = Record<string, unknown>>(path: string, data?: unknown, params?: P): Promise<T> {\n return this.request<T>({\n method: 'PUT',\n url: path,\n data,\n params: params as Record<string, unknown>,\n });\n }\n\n /**\n * DELETE request.\n */\n async delete<T, P = Record<string, unknown>>(path: string, params?: P): Promise<T> {\n return this.request<T>({\n method: 'DELETE',\n url: path,\n params: params as Record<string, unknown>,\n });\n }\n\n /**\n * POST multipart/form-data request for file uploads.\n * @param path API endpoint path\n * @param formData FormData containing file and optional JSON data\n */\n async postMultipart<T>(path: string, formData: FormData): Promise<T> {\n return this.request<T>({\n method: 'POST',\n url: path,\n data: formData,\n headers: {\n 'Content-Type': 'multipart/form-data',\n },\n });\n }\n\n /**\n * Sleep for the specified number of milliseconds.\n */\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n /**\n * Get the base URL for the API.\n */\n getBaseUrl(): string {\n return this.config.baseUrl;\n }\n\n /**\n * Get authentication headers for SSE connections.\n * @returns Promise resolving to auth headers or undefined\n */\n async getAuthHeaders(): Promise<Record<string, string> | undefined> {\n if (this.config.authentication) {\n return this.config.authentication.getAuthHeaders();\n }\n return undefined;\n }\n}\n", "/**\n * Base exception for all Timesheet API errors.\n */\nexport class TimesheetApiError extends Error {\n public readonly statusCode?: number;\n public readonly responseBody?: string;\n public readonly errorCode?: string;\n\n /**\n * Creates a new TimesheetApiError.\n *\n * @param message The error message\n * @param statusCode Optional HTTP status code\n * @param responseBody Optional response body\n * @param errorCode Optional API error code\n */\n constructor(message: string, statusCode?: number, responseBody?: string, errorCode?: string) {\n const fullMessage = statusCode\n ? errorCode\n ? `${message} (HTTP ${statusCode}, Code: ${errorCode})`\n : `${message} (HTTP ${statusCode})`\n : message;\n\n super(fullMessage);\n\n this.name = 'TimesheetApiError';\n this.statusCode = statusCode;\n this.responseBody = responseBody;\n this.errorCode = errorCode;\n\n // Maintains proper stack trace for where our error was thrown\n if (typeof Error.captureStackTrace === 'function') {\n Error.captureStackTrace(this, TimesheetApiError);\n }\n }\n}\n", "import { TimesheetApiError } from './TimesheetApiError';\n\n/**\n * Exception thrown when authentication fails.\n */\nexport class TimesheetAuthError extends TimesheetApiError {\n /**\n * Creates a new authentication exception.\n *\n * @param message The error message\n * @param statusCode The HTTP status code (usually 401)\n * @param responseBody The response body\n */\n constructor(message: string, statusCode: number = 401, responseBody?: string) {\n super(message, statusCode, responseBody, 'authentication_error');\n this.name = 'TimesheetAuthError';\n }\n}\n", "import { TimesheetApiError } from './TimesheetApiError';\n\n/**\n * Exception thrown when rate limit is exceeded.\n */\nexport class TimesheetRateLimitError extends TimesheetApiError {\n public readonly retryAfter?: string;\n\n /**\n * Creates a new rate limit exception.\n *\n * @param message The error message\n * @param retryAfter The retry-after header value\n */\n constructor(message: string, retryAfter?: string) {\n super(message, 429, undefined, 'rate_limit_exceeded');\n this.name = 'TimesheetRateLimitError';\n this.retryAfter = retryAfter;\n }\n\n /**\n * Parses the retry-after value as a Date.\n *\n * @returns The retry-after time as a Date, or null if parsing fails\n */\n getRetryAfterDate(): Date | null {\n if (!this.retryAfter) {\n return null;\n }\n\n // Try to parse as epoch seconds\n const epochSeconds = Number(this.retryAfter);\n if (!isNaN(epochSeconds)) {\n return new Date(epochSeconds * 1000);\n }\n\n // Try to parse as ISO string\n const date = new Date(this.retryAfter);\n if (!isNaN(date.getTime())) {\n return date;\n }\n\n return null;\n }\n}\n", "import type { AxiosRequestConfig } from 'axios';\nimport type { Authentication } from './Authentication';\n\n/**\n * API Key authentication implementation.\n *\n * Uses the ApiKey scheme in the Authorization header.\n * Format: `Authorization: ApiKey {api_key}`\n */\nexport class ApiKeyAuth implements Authentication {\n constructor(private readonly apiKey: string) {\n if (apiKey === null) {\n throw new Error('API key cannot be null');\n }\n if (apiKey === undefined) {\n throw new Error('API key cannot be undefined');\n }\n if (!apiKey) {\n throw new Error('API key cannot be empty');\n }\n if (typeof apiKey !== 'string') {\n throw new Error('API key must be a string');\n }\n if (apiKey.trim().length === 0) {\n throw new Error('API key cannot be empty or whitespace');\n }\n\n // Validate API key format: should be ts_{prefix}.{secret}\n if (!this.isValidFormat(apiKey)) {\n throw new Error('Invalid API key format');\n }\n }\n\n private isValidFormat(apiKey: string): boolean {\n // API key format: ts_{prefix}.{secret}\n const apiKeyPattern = /^ts_[a-zA-Z0-9]+\\.[a-zA-Z0-9]+$/;\n return apiKeyPattern.test(apiKey);\n }\n\n applyAuth(config: AxiosRequestConfig): void {\n if (!config.headers) {\n config.headers = {};\n }\n config.headers['Authorization'] = `ApiKey ${this.apiKey}`;\n }\n\n needsRefresh(): boolean {\n // API keys don't need refresh\n return false;\n }\n\n // eslint-disable-next-line @typescript-eslint/require-await\n async refresh(): Promise<void> {\n throw new Error('API keys cannot be refreshed');\n }\n\n // eslint-disable-next-line @typescript-eslint/require-await\n async getAuthHeaders(): Promise<Record<string, string>> {\n return {\n Authorization: `ApiKey ${this.apiKey}`,\n };\n }\n\n isValid(): boolean {\n return (\n typeof this.apiKey === 'string' &&\n this.apiKey.trim().length > 0 &&\n this.isValidFormat(this.apiKey)\n );\n }\n}\n", "import type { AxiosRequestConfig } from 'axios';\nimport axios from 'axios';\nimport jwt from 'jsonwebtoken';\nimport type { Authentication } from './Authentication';\n\n/**\n * OAuth2 authentication implementation with automatic token refresh.\n *\n * Supports both simple bearer token authentication and full OAuth2 flow with refresh tokens.\n */\nexport class OAuth2Auth implements Authentication {\n private static readonly TOKEN_ENDPOINT = 'https://api.timesheet.io/oauth2/token';\n\n private accessToken: string;\n private refreshToken?: string;\n private readonly clientId?: string;\n private readonly clientSecret?: string;\n private tokenExpiry?: Date;\n private refreshPromise?: Promise<void>;\n\n /**\n * Creates OAuth2 authentication with a simple bearer token.\n *\n * @param accessToken The OAuth2 access token\n */\n constructor(accessToken: string);\n\n /**\n * Creates OAuth2 authentication with refresh capability.\n *\n * @param clientId The OAuth2 client ID\n * @param clientSecret The OAuth2 client secret\n * @param refreshToken The OAuth2 refresh token\n */\n constructor(clientId: string, clientSecret: string, refreshToken: string);\n\n constructor(accessTokenOrClientId: string, clientSecret?: string, refreshToken?: string) {\n if (clientSecret && refreshToken) {\n // OAuth2 with refresh\n this.clientId = accessTokenOrClientId;\n this.clientSecret = clientSecret;\n this.refreshToken = refreshToken;\n this.accessToken = ''; // Will be set by refresh()\n // Don't call refresh here - let it happen lazily when needed\n } else {\n // Simple bearer token\n this.accessToken = accessTokenOrClientId;\n this.parseTokenExpiry();\n }\n }\n\n applyAuth(config: AxiosRequestConfig): void {\n if (!config.headers) {\n config.headers = {};\n }\n config.headers['Authorization'] = `Bearer ${this.accessToken}`;\n }\n\n needsRefresh(): boolean {\n // If we have refresh capabilities but no access token, we need to refresh\n if (this.refreshToken && !this.accessToken) {\n return true;\n }\n\n if (!this.refreshToken || !this.tokenExpiry) {\n return false;\n }\n // Refresh if token expires in less than 5 minutes\n const fiveMinutesFromNow = new Date(Date.now() + 5 * 60 * 1000);\n return fiveMinutesFromNow >= this.tokenExpiry;\n }\n\n async refresh(): Promise<void> {\n if (!this.refreshToken) {\n throw new Error('Cannot refresh without refresh token');\n }\n\n // Prevent multiple concurrent refresh attempts\n if (this.refreshPromise) {\n return this.refreshPromise;\n }\n\n this.refreshPromise = this.performRefresh();\n try {\n await this.refreshPromise;\n } finally {\n this.refreshPromise = undefined;\n }\n }\n\n private async performRefresh(): Promise<void> {\n interface TokenResponse {\n access_token: string;\n refresh_token?: string;\n token_type?: string;\n expires_in?: number;\n }\n\n try {\n const response = await axios.post<TokenResponse>(\n OAuth2Auth.TOKEN_ENDPOINT,\n new URLSearchParams({\n grant_type: 'refresh_token',\n refresh_token: this.refreshToken!,\n client_id: this.clientId!,\n client_secret: this.clientSecret!,\n }),\n {\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n },\n );\n\n this.accessToken = response.data.access_token;\n\n if (response.data.refresh_token) {\n this.refreshToken = response.data.refresh_token;\n }\n\n this.parseTokenExpiry();\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n throw new Error(`Failed to refresh OAuth2 token: ${message}`);\n }\n }\n\n async getAuthHeaders(): Promise<Record<string, string>> {\n // Ensure we have a valid token before returning headers\n if (this.needsRefresh()) {\n await this.refresh();\n }\n\n return {\n Authorization: `Bearer ${this.accessToken}`,\n };\n }\n\n /**\n * Performs the OAuth2 authorization code flow.\n *\n * @param clientId The OAuth2 client ID\n * @param clientSecret The OAuth2 client secret\n * @param authorizationCode The authorization code from the OAuth2 flow\n * @param redirectUri The redirect URI used in the authorization request\n * @returns A new OAuth2Auth instance with the obtained tokens\n */\n static async fromAuthorizationCode(\n clientId: string,\n clientSecret: string,\n authorizationCode: string,\n redirectUri: string,\n ): Promise<OAuth2Auth> {\n interface TokenResponse {\n access_token: string;\n refresh_token?: string;\n token_type?: string;\n expires_in?: number;\n }\n\n try {\n const response = await axios.post<TokenResponse>(\n OAuth2Auth.TOKEN_ENDPOINT,\n new URLSearchParams({\n grant_type: 'authorization_code',\n code: authorizationCode,\n redirect_uri: redirectUri,\n client_id: clientId,\n client_secret: clientSecret,\n }),\n {\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n },\n );\n\n const accessToken = response.data.access_token;\n const refreshToken = response.data.refresh_token;\n\n if (refreshToken) {\n return new OAuth2Auth(clientId, clientSecret, refreshToken);\n } else {\n return new OAuth2Auth(accessToken);\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n throw new Error(`Failed to exchange authorization code: ${message}`);\n }\n }\n\n /**\n * Builds the OAuth2 authorization URL.\n *\n * @param clientId The OAuth2 client ID\n * @param redirectUri The redirect URI for the OAuth2 flow\n * @param state Optional state parameter for CSRF protection\n * @returns The authorization URL\n */\n static buildAuthorizationUrl(clientId: string, redirectUri: string, state?: string): string {\n const params = new URLSearchParams({\n client_id: clientId,\n redirect_uri: redirectUri,\n response_type: 'code',\n });\n\n if (state) {\n params.append('state', state);\n }\n\n return `https://api.timesheet.io/oauth2/auth?${params.toString()}`;\n }\n\n private parseTokenExpiry(): void {\n interface JWTPayload {\n exp?: number;\n iat?: number;\n sub?: string;\n [key: string]: unknown;\n }\n\n try {\n const decoded = jwt.decode(this.accessToken) as JWTPayload | null;\n if (decoded && decoded.exp) {\n this.tokenExpiry = new Date(decoded.exp * 1000);\n }\n } catch {\n // If we can't parse the JWT, assume it expires in 1 hour\n this.tokenExpiry = new Date(Date.now() + 60 * 60 * 1000);\n }\n }\n}\n", "import type { AxiosRequestConfig } from 'axios';\nimport axios from 'axios';\nimport jwt from 'jsonwebtoken';\nimport type { Authentication } from './Authentication';\nimport {\n generatePkceCodePair,\n isValidCodeVerifier,\n type CodeChallengeMethod,\n type PkceCodePair,\n} from './pkce';\n\n/**\n * Options for building an OAuth 2.1 authorization URL.\n */\nexport interface AuthorizationUrlOptions {\n /** The OAuth2 client ID */\n clientId: string;\n /** The redirect URI for the OAuth2 flow */\n redirectUri: string;\n /** The PKCE code challenge (required for OAuth 2.1) */\n codeChallenge: string;\n /** The code challenge method (default: 'S256') */\n codeChallengeMethod?: CodeChallengeMethod;\n /** Optional state parameter for CSRF protection */\n state?: string;\n /** Optional scope parameter */\n scope?: string;\n /** Optional resource indicator (RFC 8707) */\n resource?: string;\n /** Custom authorization endpoint URL (overrides default) */\n authorizationEndpoint?: string;\n}\n\n/**\n * Options for exchanging an authorization code for tokens.\n */\nexport interface TokenExchangeOptions {\n /** The OAuth2 client ID */\n clientId: string;\n /** The OAuth2 client secret (optional for public clients with PKCE) */\n clientSecret?: string;\n /** The authorization code from the OAuth2 flow */\n authorizationCode: string;\n /** The redirect URI used in the authorization request */\n redirectUri: string;\n /** The PKCE code verifier (required for OAuth 2.1) */\n codeVerifier: string;\n /** Optional resource indicator (RFC 8707) */\n resource?: string;\n /** Custom token endpoint URL (overrides default) */\n tokenEndpoint?: string;\n}\n\n/**\n * Options for creating OAuth21Auth with refresh capability.\n */\nexport interface OAuth21RefreshOptions {\n /** The OAuth2 client ID */\n clientId: string;\n /** The OAuth2 client secret (optional for public clients) */\n clientSecret?: string;\n /** The OAuth2 refresh token */\n refreshToken: string;\n /** Optional resource indicator (RFC 8707) */\n resource?: string;\n /** Custom token endpoint URL (overrides default) */\n tokenEndpoint?: string;\n}\n\n/**\n * Token response from the OAuth 2.1 server.\n */\ninterface TokenResponse {\n access_token: string;\n refresh_token?: string;\n token_type?: string;\n expires_in?: number;\n scope?: string;\n}\n\n/**\n * OAuth 2.1 authentication implementation with PKCE support.\n *\n * OAuth 2.1 is the next evolution of OAuth 2.0, consolidating best practices:\n * - PKCE is REQUIRED for all clients (not just public clients)\n * - Implicit flow is removed\n * - Resource Owner Password Credentials grant is removed\n *\n * This implementation supports:\n * - Authorization code flow with PKCE (S256)\n * - Refresh token flow\n * - Automatic token refresh\n * - Resource indicators (RFC 8707)\n *\n * @example\n * ```typescript\n * // Step 1: Generate PKCE parameters\n * import { generatePkceCodePair } from '@timesheet/sdk';\n * const pkce = generatePkceCodePair();\n *\n * // Step 2: Build authorization URL and redirect user\n * const authUrl = OAuth21Auth.buildAuthorizationUrl({\n * clientId: 'your-client-id',\n * redirectUri: 'https://your-app.com/callback',\n * codeChallenge: pkce.codeChallenge,\n * codeChallengeMethod: pkce.codeChallengeMethod,\n * state: 'random-state-for-csrf',\n * });\n *\n * // Step 3: After user authorizes, exchange code for tokens\n * const auth = await OAuth21Auth.fromAuthorizationCode({\n * clientId: 'your-client-id',\n * authorizationCode: codeFromCallback,\n * redirectUri: 'https://your-app.com/callback',\n * codeVerifier: pkce.codeVerifier,\n * });\n *\n * // Step 4: Use with TimesheetClient\n * const client = new TimesheetClient({ auth });\n * ```\n */\nexport class OAuth21Auth implements Authentication {\n private static readonly DEFAULT_TOKEN_ENDPOINT = 'https://api.timesheet.io/oauth2/token';\n private static readonly DEFAULT_AUTH_ENDPOINT = 'https://api.timesheet.io/oauth2/auth';\n\n private accessToken: string;\n private refreshToken?: string;\n private readonly clientId?: string;\n private readonly clientSecret?: string;\n private readonly resource?: string;\n private readonly tokenEndpoint: string;\n private tokenExpiry?: Date;\n private refreshPromise?: Promise<void>;\n\n /**\n * Creates OAuth 2.1 authentication with a simple bearer token.\n * Use this when you already have an access token.\n *\n * @param accessToken The OAuth2 access token\n */\n constructor(accessToken: string);\n\n /**\n * Creates OAuth 2.1 authentication with refresh capability.\n *\n * @param options The refresh options including clientId, refreshToken, etc.\n */\n constructor(options: OAuth21RefreshOptions);\n\n constructor(accessTokenOrOptions: string | OAuth21RefreshOptions) {\n if (typeof accessTokenOrOptions === 'string') {\n // Simple bearer token\n this.accessToken = accessTokenOrOptions;\n this.tokenEndpoint = OAuth21Auth.DEFAULT_TOKEN_ENDPOINT;\n this.parseTokenExpiry();\n } else {\n // OAuth 2.1 with refresh\n const options = accessTokenOrOptions;\n this.clientId = options.clientId;\n this.clientSecret = options.clientSecret;\n this.refreshToken = options.refreshToken;\n this.resource = options.resource;\n this.tokenEndpoint = options.tokenEndpoint ?? OAuth21Auth.DEFAULT_TOKEN_ENDPOINT;\n this.accessToken = ''; // Will be set by refresh()\n }\n }\n\n applyAuth(config: AxiosRequestConfig): void {\n if (!config.headers) {\n config.headers = {};\n }\n config.headers['Authorization'] = `Bearer ${this.accessToken}`;\n }\n\n needsRefresh(): boolean {\n // If we have refresh capabilities but no access token, we need to refresh\n if (this.refreshToken && !this.accessToken) {\n return true;\n }\n\n if (!this.refreshToken || !this.tokenExpiry) {\n return false;\n }\n // Refresh if token expires in less than 5 minutes\n const fiveMinutesFromNow = new Date(Date.now() + 5 * 60 * 1000);\n return fiveMinutesFromNow >= this.tokenExpiry;\n }\n\n async refresh(): Promise<void> {\n if (!this.refreshToken) {\n throw new Error('Cannot refresh without refresh token');\n }\n\n // Prevent multiple concurrent refresh attempts\n if (this.refreshPromise) {\n return this.refreshPromise;\n }\n\n this.refreshPromise = this.performRefresh();\n try {\n await this.refreshPromise;\n } finally {\n this.refreshPromise = undefined;\n }\n }\n\n private async performRefresh(): Promise<void> {\n try {\n const params = new URLSearchParams({\n grant_type: 'refresh_token',\n refresh_token: this.refreshToken!,\n client_id: this.clientId!,\n });\n\n // Client secret is optional for public clients using PKCE\n if (this.clientSecret) {\n params.append('client_secret', this.clientSecret);\n }\n\n // Include resource indicator if specified\n if (this.resource) {\n params.append('resource', this.resource);\n }\n\n const response = await axios.post<TokenResponse>(this.tokenEndpoint, params, {\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n });\n\n this.accessToken = response.data.access_token;\n\n if (response.data.refresh_token) {\n this.refreshToken = response.data.refresh_token;\n }\n\n this.parseTokenExpiry();\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n throw new Error(`Failed to refresh OAuth 2.1 token: ${message}`);\n }\n }\n\n async getAuthHeaders(): Promise<Record<string, string>> {\n // Ensure we have a valid token before returning headers\n if (this.needsRefresh()) {\n await this.refresh();\n }\n\n return {\n Authorization: `Bearer ${this.accessToken}`,\n };\n }\n\n /**\n * Performs the OAuth 2.1 authorization code flow with PKCE.\n *\n * @param options The token exchange options\n * @returns A new OAuth21Auth instance with the obtained tokens\n * @throws Error if the code verifier is invalid or token exchange fails\n */\n static async fromAuthorizationCode(options: TokenExchangeOptions): Promise<OAuth21Auth> {\n const {\n clientId,\n clientSecret,\n authorizationCode,\n redirectUri,\n codeVerifier,\n resource,\n tokenEndpoint,\n } = options;\n\n const effectiveTokenEndpoint = tokenEndpoint ?? OAuth21Auth.DEFAULT_TOKEN_ENDPOINT;\n\n // Validate code verifier\n if (!isValidCodeVerifier(codeVerifier)) {\n throw new Error(\n 'Invalid code verifier: must be 43-128 characters using only A-Z, a-z, 0-9, -, ., _, ~',\n );\n }\n\n try {\n const params = new URLSearchParams({\n grant_type: 'authorization_code',\n code: authorizationCode,\n redirect_uri: redirectUri,\n client_id: clientId,\n code_verifier: codeVerifier,\n });\n\n // Client secret is optional for public clients using PKCE\n if (clientSecret) {\n params.append('client_secret', clientSecret);\n }\n\n // Include resource indicator if specified\n if (resource) {\n params.append('resource', resource);\n }\n\n const response = await axios.post<TokenResponse>(effectiveTokenEndpoint, params, {\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n });\n\n const accessToken = response.data.access_token;\n const refreshToken = response.data.refresh_token;\n\n if (refreshToken) {\n return new OAuth21Auth({\n clientId,\n clientSecret,\n refreshToken,\n resource,\n tokenEndpoint: effectiveTokenEndpoint,\n });\n } else {\n return new OAuth21Auth(accessToken);\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n throw new Error(`Failed to exchange authorization code: ${message}`);\n }\n }\n\n /**\n * Builds the OAuth 2.1 authorization URL with PKCE.\n *\n * @param options The authorization URL options\n * @returns The authorization URL\n */\n static buildAuthorizationUrl(options: AuthorizationUrlOptions): string {\n const {\n clientId,\n redirectUri,\n codeChallenge,\n codeChallengeMethod = 'S256',\n state,\n scope,\n resource,\n authorizationEndpoint,\n } = options;\n\n const effectiveAuthEndpoint = authorizationEndpoint ?? OAuth21Auth.DEFAULT_AUTH_ENDPOINT;\n\n const params = new URLSearchParams({\n response_type: 'code',\n client_id: clientId,\n redirect_uri: redirectUri,\n code_challenge: codeChallenge,\n code_challenge_method: codeChallengeMethod,\n });\n\n if (state) {\n params.append('state', state);\n }\n\n if (scope) {\n params.append('scope', scope);\n }\n\n if (resource) {\n params.append('resource', resource);\n }\n\n return `${effectiveAuthEndpoint}?${params.toString()}`;\n }\n\n /**\n * Generates a complete PKCE code pair for use in OAuth 2.1 flow.\n *\n * This is a convenience method that wraps the generatePkceCodePair function.\n *\n * @param method The challenge method ('S256' or 'plain', default: 'S256')\n * @returns A PKCE code pair with verifier, challenge, and method\n *\n * @example\n * ```typescript\n * const pkce = OAuth21Auth.generatePkce();\n *\n * // Store verifier securely (e.g., in session)\n * sessionStorage.setItem('pkce_verifier', pkce.codeVerifier);\n *\n * // Use challenge in authorization URL\n * const authUrl = OAuth21Auth.buildAuthorizationUrl({\n * clientId: 'your-client-id',\n * redirectUri: 'https://your-app.com/callback',\n * codeChallenge: pkce.codeChallenge,\n * codeChallengeMethod: pkce.codeChallengeMethod,\n * });\n * ```\n */\n static generatePkce(method: CodeChallengeMethod = 'S256'): PkceCodePair {\n return generatePkceCodePair(method);\n }\n\n private parseTokenExpiry(): void {\n interface JWTPayload {\n exp?: number;\n iat?: number;\n sub?: string;\n [key: string]: unknown;\n }\n\n try {\n const decoded = jwt.decode(this.accessToken) as JWTPayload | null;\n if (decoded && decoded.exp) {\n this.tokenExpiry = new Date(decoded.exp * 1000);\n }\n } catch {\n // If we can't parse the JWT, assume it expires in 1 hour\n this.tokenExpiry = new Date(Date.now() + 60 * 60 * 1000);\n }\n }\n}\n", "import { randomBytes, createHash } from 'crypto';\n\n/**\n * PKCE (Proof Key for Code Exchange) utilities for OAuth 2.1.\n *\n * Implements RFC 7636 with S256 challenge method as required by OAuth 2.1.\n */\n\n/**\n * Supported PKCE code challenge methods.\n * OAuth 2.1 requires S256 - plain is only for legacy compatibility.\n */\nexport type CodeChallengeMethod = 'S256' | 'plain';\n\n/**\n * PKCE code pair containing verifier and challenge.\n */\nexport interface PkceCodePair {\n /** The code verifier - a cryptographically random string (43-128 chars) */\n codeVerifier: string;\n /** The code challenge - derived from the verifier using the challenge method */\n codeChallenge: string;\n /** The challenge method used (S256 or plain) */\n codeChallengeMethod: CodeChallengeMethod;\n}\n\n/**\n * Generates a cryptographically random code verifier.\n *\n * The verifier is a high-entropy random string between 43-128 characters\n * using unreserved URI characters (A-Z, a-z, 0-9, -, ., _, ~).\n *\n * @param length The length of the verifier (default: 64, min: 43, max: 128)\n * @returns A random code verifier string\n */\nexport function generateCodeVerifier(length: number = 64): string {\n if (length < 43 || length > 128) {\n throw new Error('Code verifier length must be between 43 and 128 characters');\n }\n\n // Generate random bytes and encode as base64url\n const buffer = randomBytes(Math.ceil((length * 3) / 4));\n return base64UrlEncode(buffer).slice(0, length);\n}\n\n/**\n * Generates a code challenge from a code verifier.\n *\n * For S256 (recommended by OAuth 2.1):\n * code_challenge = BASE64URL(SHA256(code_verifier))\n *\n * For plain (legacy, not recommended):\n * code_challenge = code_verifier\n *\n * @param codeVerifier The code verifier string\n * @param method The challenge method ('S256' or 'plain', default: 'S256')\n * @returns The code challenge string\n */\nexport function generateCodeChallenge(\n codeVerifier: string,\n method: CodeChallengeMethod = 'S256',\n): string {\n if (method === 'plain') {\n return codeVerifier;\n }\n\n // S256: BASE64URL(SHA256(ASCII(code_verifier)))\n const hash = createHash('sha256').update(codeVerifier, 'ascii').digest();\n return base64UrlEncode(hash);\n}\n\n/**\n * Generates a complete PKCE code pair (verifier and challenge).\n *\n * This is the recommended way to generate PKCE parameters for OAuth 2.1.\n *\n * @param method The challenge method ('S256' or 'plain', default: 'S256')\n * @param verifierLength The length of the verifier (default: 64)\n * @returns A complete PKCE code pair\n *\n * @example\n * ```typescript\n * const pkce = generatePkceCodePair();\n *\n * // Use codeChallenge in authorization request\n * const authUrl = OAuth21Auth.buildAuthorizationUrl({\n * clientId: 'your-client-id',\n * redirectUri: 'https://your-app.com/callback',\n * codeChallenge: pkce.codeChallenge,\n * codeChallengeMethod: pkce.codeChallengeMethod,\n * });\n *\n * // Later, use codeVerifier in token exchange\n * const auth = await OAuth21Auth.fromAuthorizationCode({\n * clientId: 'your-client-id',\n * authorizationCode: code,\n * redirectUri: 'https://your-app.com/callback',\n * codeVerifier: pkce.codeVerifier,\n * });\n * ```\n */\nexport function generatePkceCodePair(\n method: CodeChallengeMethod = 'S256',\n verifierLength: number = 64,\n): PkceCodePair {\n const codeVerifier = generateCodeVerifier(verifierLength);\n const codeChallenge = generateCodeChallenge(codeVerifier, method);\n\n return {\n codeVerifier,\n codeChallenge,\n codeChallengeMethod: method,\n };\n}\n\n/**\n * Validates a code verifier format.\n *\n * @param codeVerifier The code verifier to validate\n * @returns True if valid, false otherwise\n */\nexport function isValidCodeVerifier(codeVerifier: string): boolean {\n if (codeVerifier.length < 43 || codeVerifier.length > 128) {\n return false;\n }\n\n // Must only contain unreserved characters: A-Z, a-z, 0-9, -, ., _, ~\n const validChars = /^[A-Za-z0-9\\-._~]+$/;\n return validChars.test(codeVerifier);\n}\n\n/**\n * Base64URL encodes a buffer (RFC 4648 Section 5).\n *\n * @param buffer The buffer to encode\n * @returns Base64URL encoded string (no padding)\n */\nfunction base64UrlEncode(buffer: Buffer): string {\n return buffer.toString('base64').replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n", "import axios from 'axios';\nimport type {\n AuthorizationServerMetadata,\n OpenIdConfiguration,\n ProtectedResourceMetadata,\n OAuthDiscoveryResult,\n} from './OAuthMetadata';\n\n/**\n * Options for OAuth discovery\n */\nexport interface OAuthDiscoveryOptions {\n /** Cache TTL in milliseconds (default: 1 hour) */\n cacheTtl?: number;\n\n /** Request timeout in milliseconds (default: 10000) */\n timeout?: number;\n\n /** Whether to also fetch OpenID configuration (default: false) */\n fetchOpenIdConfig?: boolean;\n\n /** Whether to also fetch protected resource metadata (default: false) */\n fetchProtectedResource?: boolean;\n}\n\n/**\n * Cached metadata entry\n */\ninterface CacheEntry {\n result: OAuthDiscoveryResult;\n expiresAt: Date;\n}\n\n/**\n * OAuth 2.1 Discovery Service\n *\n * Implements RFC 8414 (OAuth 2.0 Authorization Server Metadata) for automatic\n * discovery of OAuth endpoints from well-known URLs.\n *\n * Supports:\n * - /.well-known/oauth-authorization-server (RFC 8414)\n * - /.well-known/oauth-protected-resource (RFC 9728)\n * - /.well-known/openid-configuration (OpenID Connect Discovery)\n *\n * @example\n * ```typescript\n * // Discover OAuth endpoints from issuer URL\n * const discovery = new OAuthDiscovery();\n * const metadata = await discovery.discover('https://api.timesheet.io');\n *\n * console.log(metadata.authorizationServer.authorization_endpoint);\n * console.log(metadata.authorizationServer.token_endpoint);\n * ```\n */\nexport class OAuthDiscovery {\n private static readonly DEFAULT_CACHE_TTL = 60 * 60 * 1000; // 1 hour\n private static readonly DEFAULT_TIMEOUT = 10000; // 10 seconds\n\n private readonly cache: Map<string, CacheEntry> = new Map();\n private readonly options: Required<OAuthDiscoveryOptions>;\n\n constructor(options: OAuthDiscoveryOptions = {}) {\n this.options = {\n cacheTtl: options.cacheTtl ?? OAuthDiscovery.DEFAULT_CACHE_TTL,\n timeout: options.timeout ?? OAuthDiscovery.DEFAULT_TIMEOUT,\n fetchOpenIdConfig: options.fetchOpenIdConfig ?? false,\n fetchProtectedResource: options.fetchProtectedResource ?? false,\n };\n }\n\n /**\n * Discover OAuth metadata from an issuer URL.\n *\n * @param issuerUrl The OAuth authorization server issuer URL\n * @returns Discovery result containing all fetched metadata\n * @throws Error if discovery fails\n *\n * @example\n * ```typescript\n * const discovery = new OAuthDiscovery();\n * const result = await discovery.discover('https://api.timesheet.io');\n *\n * // Use discovered endpoints\n * const authUrl = result.authorizationServer.authorization_endpoint;\n * const tokenUrl = result.authorizationServer.token_endpoint;\n * ```\n */\n async discover(issuerUrl: string): Promise<OAuthDiscoveryResult> {\n const normalizedUrl = this.normalizeIssuerUrl(issuerUrl);\n\n // Check cache first\n const cached = this.getCached(normalizedUrl);\n if (cached) {\n return cached;\n }\n\n // Fetch authorization server metadata (required)\n const authServerMetadata = await this.fetchAuthorizationServerMetadata(normalizedUrl);\n\n const result: OAuthDiscoveryResult = {\n issuer: authServerMetadata.issuer,\n authorizationServer: authServerMetadata,\n fetchedAt: new Date(),\n };\n\n // Optionally fetch OpenID configuration\n if (this.options.fetchOpenIdConfig) {\n try {\n result.openIdConfiguration = await this.fetchOpenIdConfiguration(normalizedUrl);\n } catch {\n // OpenID configuration is optional, continue without it\n }\n }\n\n // Optionally fetch protected resource metadata\n if (this.options.fetchProtectedResource) {\n try {\n result.protectedResource = await this.fetchProtectedResourceMetadata(normalizedUrl);\n } catch {\n // Protected resource metadata is optional, continue without it\n }\n }\n\n // Cache the result\n this.setCache(normalizedUrl, result);\n\n return result;\n }\n\n /**\n * Fetch Authorization Server Metadata (RFC 8414)\n *\n * @param issuerUrl The OAuth authorization server issuer URL\n * @returns Authorization server metadata\n */\n async fetchAuthorizationServerMetadata(issuerUrl: string): Promise<AuthorizationServerMetadata> {\n const url = `${this.normalizeIssuerUrl(issuerUrl)}/.well-known/oauth-authorization-server`;\n\n try {\n const response = await axios.get<AuthorizationServerMetadata>(url, {\n timeout: this.options.timeout,\n headers: {\n Accept: 'application/json',\n },\n });\n\n this.validateAuthorizationServerMetadata(response.data);\n return response.data;\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n throw new Error(`Failed to fetch authorization server metadata from ${url}: ${message}`);\n }\n }\n\n /**\n * Fetch OpenID Connect Discovery Configuration\n *\n * @param issuerUrl The OpenID Provider issuer URL\n * @returns OpenID Connect configuration\n */\n async fetchOpenIdConfiguration(issuerUrl: string): Promise<OpenIdConfiguration> {\n const url = `${this.normalizeIssuerUrl(issuerUrl)}/.well-known/openid-configuration`;\n\n try {\n const response = await axios.get<OpenIdConfiguration>(url, {\n timeout: this.options.timeout,\n headers: {\n Accept: 'application/json',\n },\n });\n\n this.validateOpenIdConfiguration(response.data);\n return response.data;\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n throw new Error(`Failed to fetch OpenID configuration from ${url}: ${message}`);\n }\n }\n\n /**\n * Fetch Protected Resource Metadata (RFC 9728)\n *\n * @param resourceUrl The protected resource URL\n * @returns Protected resource metadata\n */\n async fetchProtectedResourceMetadata(resourceUrl: string): Promise<ProtectedResourceMetadata> {\n const url = `${this.normalizeIssuerUrl(resourceUrl)}/.well-known/oauth-protected-resource`;\n\n try {\n const response = await axios.get<ProtectedResourceMetadata>(url, {\n timeout: this.options.timeout,\n headers: {\n Accept: 'application/json',\n },\n });\n\n this.validateProtectedResourceMetadata(response.data);\n return response.data;\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n throw new Error(`Failed to fetch protected resource metadata from ${url}: ${message}`);\n }\n }\n\n /**\n * Clear the metadata cache\n */\n clearCache(): void {\n this.cache.clear();\n }\n\n /**\n * Clear a specific issuer from the cache\n */\n clearCacheForIssuer(issuerUrl: string): void {\n this.cache.delete(this.normalizeIssuerUrl(issuerUrl));\n }\n\n /**\n * Check if a specific issuer's metadata is cached\n */\n isCached(issuerUrl: string): boolean {\n const cached = this.getCached(this.normalizeIssuerUrl(issuerUrl));\n return cached !== null;\n }\n\n private normalizeIssuerUrl(url: string): string {\n // Remove trailing slash\n return url.replace(/\\/+$/, '');\n }\n\n private getCached(issuerUrl: string): OAuthDiscoveryResult | null {\n const entry = this.cache.get(issuerUrl);\n if (!entry) {\n return null;\n }\n\n if (new Date() >= entry.expiresAt) {\n this.cache.delete(issuerUrl);\n return null;\n }\n\n return entry.result;\n }\n\n private setCache(issuerUrl: string, result: OAuthDiscoveryResult): void {\n const expiresAt = new Date(Date.now() + this.options.cacheTtl);\n this.cache.set(issuerUrl, { result, expiresAt });\n }\n\n private validateAuthorizationServerMetadata(metadata: AuthorizationServerMetadata): void {\n if (!metadata.issuer) {\n throw new Error('Authorization server metadata missing required field: issuer');\n }\n if (!metadata.authorization_endpoint) {\n throw new Error(\n 'Authorization server metadata missing required field: authorization_endpoint',\n );\n }\n if (!metadata.token_endpoint) {\n throw new Error('Authorization server metadata missing required field: token_endpoint');\n }\n if (!metadata.response_types_supported || metadata.response_types_supported.length === 0) {\n throw new Error(\n 'Authorization server metadata missing required field: response_types_supported',\n );\n }\n }\n\n private validateOpenIdConfiguration(config: OpenIdConfiguration): void {\n if (!config.issuer) {\n throw new Error('OpenID configuration missing required field: issuer');\n }\n if (!config.authorization_endpoint) {\n throw new Error('OpenID configuration missing required field: authorization_endpoint');\n }\n if (!config.token_endpoint) {\n throw new Error('OpenID configuration missing required field: token_endpoint');\n }\n if (!config.jwks_uri) {\n throw new Error('OpenID configuration missing required field: jwks_uri');\n }\n }\n\n private validateProtectedResourceMetadata(metadata: ProtectedResourceMetadata): void {\n if (!metadata.resource) {\n throw new Error('Protected resource metadata missing required field: resource');\n }\n if (!metadata.authorization_servers || metadata.authorization_servers.length === 0) {\n throw new Error('Protected resource metadata missing required field: authorization_servers');\n }\n }\n}\n\n/**\n * Singleton instance for convenience\n */\nlet defaultDiscovery: OAuthDiscovery | null = null;\n\n/**\n * Get the default OAuthDiscovery instance\n */\nexport function getDefaultDiscovery(): OAuthDiscovery {\n if (!defaultDiscovery) {\n defaultDiscovery = new OAuthDiscovery();\n }\n return defaultDiscovery;\n}\n\n/**\n * Convenience function to discover OAuth metadata\n *\n * @param issuerUrl The OAuth authorization server issuer URL\n * @param options Discovery options\n * @returns Discovery result\n *\n * @example\n * ```typescript\n * import { discoverOAuth } from '@timesheet/sdk';\n *\n * const metadata = await discoverOAuth('https://api.timesheet.io');\n * console.log(metadata.authorizationServer.token_endpoint);\n * ```\n */\nexport async function discoverOAuth(\n issuerUrl: string,\n options?: OAuthDiscoveryOptions,\n): Promise<OAuthDiscoveryResult> {\n const discovery = options ? new OAuthDiscovery(options) : getDefaultDiscovery();\n return discovery.discover(issuerUrl);\n}\n", "/**\n * Configuration for automatic retry behavior.\n */\nexport class RetryConfig {\n public readonly maxRetries: number;\n public readonly initialDelay: number;\n public readonly maxDelay: number;\n public readonly backoffMultiplier: number;\n public readonly retryableStatusCodes: number[];\n\n constructor(options: Partial<RetryConfigOptions> = {}) {\n this.maxRetries = options.maxRetries ?? 3;\n this.initialDelay = options.initialDelay ?? 100;\n this.maxDelay = options.maxDelay ?? 10000;\n this.backoffMultiplier = options.backoffMultiplier ?? 2.0;\n this.retryableStatusCodes = options.retryableStatusCodes ?? [429, 502, 503, 504];\n }\n\n /**\n * Returns the default retry configuration.\n */\n static default(): RetryConfig {\n return new RetryConfig();\n }\n}\n\n/**\n * Options for RetryConfig constructor.\n */\nexport interface RetryConfigOptions {\n /**\n * Maximum number of retry attempts.\n * @default 3\n */\n maxRetries: number;\n\n /**\n * Initial delay before the first retry in milliseconds.\n * @default 100\n */\n initialDelay: number;\n\n /**\n * Maximum delay between retries in milliseconds.\n * @default 10000\n */\n maxDelay: number;\n\n /**\n * Backoff multiplier for exponential backoff.\n * @default 2.0\n */\n backoffMultiplier: number;\n\n /**\n * HTTP status codes that should trigger a retry.\n * @default [429, 502, 503, 504]\n */\n retryableStatusCodes: number[];\n}\n", "import type { ListParams } from './common';\n\n/**\n * Represents a page of results with pagination support.\n */\nexport interface Page<T> {\n /**\n * The items in this page.\n */\n items: T[];\n\n /**\n * Pagination and sorting parameters.\n */\n params: ListParams;\n}\n\n/**\n * Extended page with navigation methods.\n */\nexport class NavigablePage<T> implements Page<T> {\n items: T[];\n params: ListParams;\n\n private readonly nextPageLoader?: (page: number) => Promise<NavigablePage<T>>;\n\n constructor(data: Page<T>, nextPageLoader?: (page: number) => Promise<NavigablePage<T>>) {\n this.items = data.items;\n this.params = data.params;\n this.nextPageLoader = nextPageLoader;\n }\n\n /**\n * Gets the total number of pages.\n */\n get totalPages(): number {\n return Math.ceil((this.params?.count || 0) / (this.params?.limit || 25));\n }\n\n /**\n * Checks if there is a next page.\n */\n get hasNextPage(): boolean {\n return (this.params?.page || 1) < this.totalPages;\n }\n\n /**\n * Loads the next page.\n */\n async nextPage(): Promise<NavigablePage<T>> {\n if (!this.hasNextPage) {\n throw new Error('No more pages available');\n }\n if (!this.nextPageLoader) {\n throw new Error('Next page loader not configured');\n }\n return this.nextPageLoader((this.params.page || 1) + 1);\n }\n\n /**\n * Returns an async iterator for auto-pagination.\n */\n async *[Symbol.asyncIterator](): AsyncIterator<T> {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n let currentPage: NavigablePage<T> = this;\n\n while (true) {\n for (const item of currentPage.items) {\n yield item;\n }\n\n if (!currentPage.hasNextPage) {\n break;\n }\n\n currentPage = await currentPage.nextPage();\n }\n }\n\n /**\n * Converts all pages to an array (loads all pages).\n */\n async toArray(): Promise<T[]> {\n const allItems: T[] = [];\n\n for await (const item of this) {\n allItems.push(item);\n }\n\n return allItems;\n }\n}\n", "import type { ListParams } from './common';\n\n/**\n * Webhook event types\n */\nexport type WebhookEventType =\n | 'team.create'\n | 'team.update'\n | 'project.create'\n | 'project.update'\n | 'todo.create'\n | 'todo.update'\n | 'task.create'\n | 'task.update'\n | 'tag.create'\n | 'tag.update'\n | 'rate.create'\n | 'rate.update'\n | 'timer.start'\n | 'timer.stop'\n | 'timer.pause'\n | 'timer.resume';\n\n/**\n * Constants for webhook event types\n */\nexport const WebhookEvents = {\n TEAM_CREATE: 'team.create' as const,\n TEAM_UPDATE: 'team.update' as const,\n PROJECT_CREATE: 'project.create' as const,\n PROJECT_UPDATE: 'project.update' as const,\n TODO_CREATE: 'todo.create' as const,\n TODO_UPDATE: 'todo.update' as const,\n TASK_CREATE: 'task.create' as const,\n TASK_UPDATE: 'task.update' as const,\n TAG_CREATE: 'tag.create' as const,\n TAG_UPDATE: 'tag.update' as const,\n RATE_CREATE: 'rate.create' as const,\n RATE_UPDATE: 'rate.update' as const,\n TIMER_START: 'timer.start' as const,\n TIMER_STOP: 'timer.stop' as const,\n TIMER_PAUSE: 'timer.pause' as const,\n TIMER_RESUME: 'timer.resume' as const,\n} as const;\n\n/**\n * Helper function to combine multiple webhook events into a comma-separated string\n * @param events - One or more webhook event types\n * @returns Comma-separated event string\n *\n * @example\n * ```typescript\n * combineWebhookEvents('timer.start', 'timer.stop') // Returns: 'timer.start,timer.stop'\n * combineWebhookEvents(WebhookEvents.TIMER_START, WebhookEvents.TIMER_STOP)\n * ```\n */\nexport function combineWebhookEvents(...events: WebhookEventType[]): string {\n return events.join(',');\n}\n\nexport interface Webhook {\n id: string;\n target: string;\n /**\n * Event type(s) that trigger this webhook.\n * Can be a single event (e.g., 'timer.start') or multiple comma-separated events (e.g., 'timer.start,timer.stop')\n * @see WebhookEventType for valid event types\n */\n event: string;\n created?: number;\n lastUpdate?: number;\n}\n\nexport interface WebhookList {\n items: Webhook[];\n params: WebhookListParams;\n}\n\nexport interface WebhookCreateRequest {\n target: string;\n event: string;\n}\n\nexport interface WebhookUpdateRequest {\n target?: string;\n event?: string;\n}\n\nexport interface WebhookListParams extends ListParams {\n sort?: 'created' | 'lastUpdate' | 'target' | 'event';\n order?: 'asc' | 'desc';\n event?: string;\n}\n", "import type { ApiClient } from '../http';\nimport type { Page } from '../models';\nimport { NavigablePage } from '../models';\n\n/**\n * Configuration for resource endpoints\n */\nexport interface ResourceConfig {\n basePath: string;\n}\n\n/**\n * Base resource class that provides common functionality for all API resources.\n */\nexport abstract class Resource {\n protected readonly basePath: string;\n\n protected constructor(\n protected readonly http: ApiClient,\n config: ResourceConfig | string,\n ) {\n if (typeof config === 'string') {\n this.basePath = config;\n } else {\n this.basePath = config.basePath;\n }\n }\n\n /**\n * Creates a NavigablePage from a Page response\n * @param page The page response\n * @param nextPageLoader Function to load the next page\n */\n protected createNavigablePage<R>(\n page: Page<R>,\n nextPageLoader: (page: number) => Promise<NavigablePage<R>>,\n ): NavigablePage<R> {\n return new NavigablePage(page, nextPageLoader);\n }\n}\n", "import type { ApiClient } from '../http';\nimport type {\n Organization,\n OrganizationCreateRequest,\n OrganizationListParams,\n OrganizationUpdateRequest,\n Page,\n} from '../models';\nimport { NavigablePage } from '../models';\nimport { Resource } from './Resource';\n\n/**\n * Resource for managing organizations.\n */\nexport class OrganizationResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/organizations');\n }\n\n async list(params?: OrganizationListParams): Promise<NavigablePage<Organization>> {\n const response = await this.http.get<Page<Organization>, OrganizationListParams>(\n this.basePath,\n params,\n );\n return new NavigablePage(response, (page) => this.list({ ...params, page }));\n }\n\n async create(data: OrganizationCreateRequest): Promise<Organization> {\n return this.http.post<Organization>(this.basePath, data);\n }\n\n async update(id: string, data: OrganizationUpdateRequest): Promise<Organization> {\n return this.http.put<Organization>(`${this.basePath}/${encodeURIComponent(id)}`, data);\n }\n\n async get(id: string): Promise<Organization> {\n return this.http.get<Organization>(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n async delete(id: string): Promise<void> {\n return this.http.delete(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n /**\n * Search organizations with parameters using POST\n * @param params Search parameters\n */\n async search(params: OrganizationListParams): Promise<NavigablePage<Organization>> {\n const response = await this.http.post<Page<Organization>>(`${this.basePath}/search`, params);\n return this.createNavigablePage(response, (page) => this.search({ ...params, page }));\n }\n}\n", "import type { ApiClient } from '../http';\nimport type {\n Page,\n Team,\n TeamCreateRequest,\n TeamListParams,\n TeamMember,\n TeamMemberListParams,\n TeamUpdateRequest,\n} from '../models';\nimport { NavigablePage } from '../models';\nimport { Resource } from './Resource';\n\nexport class TeamResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/teams');\n }\n\n async list(params?: TeamListParams): Promise<NavigablePage<Team>> {\n const response = await this.http.get<Page<Team>, TeamListParams>(this.basePath, params);\n return new NavigablePage(response, (page) => this.list({ ...params, page }));\n }\n\n async create(data: TeamCreateRequest): Promise<Team> {\n return this.http.post<Team>(this.basePath, data);\n }\n\n async update(id: string, data: TeamUpdateRequest): Promise<Team> {\n return this.http.put<Team>(`${this.basePath}/${encodeURIComponent(id)}`, data);\n }\n\n async get(id: string): Promise<Team> {\n return this.http.get<Team>(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n async delete(id: string): Promise<void> {\n return this.http.delete(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n /**\n * Search teams with parameters using POST\n * @param params Search parameters\n */\n async search(params: TeamListParams): Promise<NavigablePage<Team>> {\n const response = await this.http.post<Page<Team>>(`${this.basePath}/search`, params);\n return this.createNavigablePage(response, (page) => this.search({ ...params, page }));\n }\n\n /**\n * List team members\n * @param teamId Team identifier\n * @param params List parameters\n */\n async listMembers(\n teamId: string,\n params: TeamMemberListParams,\n ): Promise<NavigablePage<TeamMember>> {\n const response = await this.http.post<Page<TeamMember>>(\n `${this.basePath}/${teamId}/members/list`,\n params,\n );\n return this.createNavigablePage(response, (page) =>\n this.listMembers(teamId, { ...params, page }),\n );\n }\n\n /**\n * Get team member\n * @param teamId Team identifier\n * @param memberId Member identifier\n */\n async getMember(teamId: string, memberId: string): Promise<TeamMember> {\n return this.http.get<TeamMember>(`${this.basePath}/${teamId}/members/${memberId}`);\n }\n\n /**\n * Get colleagues\n * @param params Parameters for filtering colleagues\n */\n async getColleagues(params?: TeamMemberListParams): Promise<NavigablePage<TeamMember>> {\n const response = await this.http.post<Page<TeamMember>>(\n `${this.basePath}/getColleagues`,\n params,\n );\n return this.createNavigablePage(response, (page) => this.getColleagues({ ...params, page }));\n }\n}\n", "import type { ApiClient } from '../http';\nimport type {\n Page,\n Project,\n ProjectCreateRequest,\n ProjectListParams,\n ProjectUpdateRequest,\n} from '../models';\nimport { NavigablePage } from '../models';\nimport { Resource } from './Resource';\n\nexport class ProjectResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/projects');\n }\n\n async list(params?: ProjectListParams): Promise<NavigablePage<Project>> {\n const response = await this.http.get<Page<Project>, ProjectListParams>(this.basePath, params);\n return new NavigablePage(response, (page) => this.list({ ...params, page }));\n }\n\n async create(data: ProjectCreateRequest): Promise<Project> {\n return this.http.post<Project>(this.basePath, data);\n }\n\n async update(id: string, data: ProjectUpdateRequest): Promise<Project> {\n return this.http.put<Project>(`${this.basePath}/${encodeURIComponent(id)}`, data);\n }\n\n async get(id: string): Promise<Project> {\n return this.http.get<Project>(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n async delete(id: string): Promise<void> {\n return this.http.delete(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n /**\n * Search projects with parameters using POST\n * @param params Search parameters\n */\n async search(params: ProjectListParams): Promise<NavigablePage<Project>> {\n const response = await this.http.post<Page<Project>>(`${this.basePath}/search`, params);\n return this.createNavigablePage(response, (page) => this.search({ ...params, page }));\n }\n}\n", "import dayjs from 'dayjs';\nimport utc from 'dayjs/plugin/utc';\nimport timezone from 'dayjs/plugin/timezone';\nimport customParseFormat from 'dayjs/plugin/customParseFormat';\n\n// Extend dayjs with necessary plugins\ndayjs.extend(utc);\ndayjs.extend(timezone);\ndayjs.extend(customParseFormat);\n\n// The expected format for Timesheet API: YYYY-MM-DDTHH:mm:ss\u00B1HH:mm\nconst TIMESTAMP_FORMAT = 'YYYY-MM-DDTHH:mm:ssZ';\nconst TIMESTAMP_REGEX = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}[+-]\\d{2}:\\d{2}$/;\n\nexport const DateUtils = {\n /**\n * Validates if a timestamp string is in the correct format with timezone offset\n * (e.g. 2025-05-31T16:45:51+02:00)\n */\n isValidTimestampFormat(timestamp: string): boolean {\n return TIMESTAMP_REGEX.test(timestamp);\n },\n\n /**\n * Formats a date or timestamp string into the ISO 8601 format with timezone offset\n * that the Timesheet API expects (e.g. 2025-05-31T16:45:51+02:00)\n *\n * @param input Date object, timestamp string, or undefined for current time\n * @returns Formatted date string without milliseconds\n */\n formatTimestamp(input?: Date | string | dayjs.Dayjs): string {\n // If input is a string and already in correct format, return it\n if (typeof input === 'string' && this.isValidTimestampFormat(input)) {\n return input;\n }\n\n // Convert to dayjs object\n const dayjsDate = dayjs(input || new Date());\n\n // Format with timezone offset (no milliseconds)\n // dayjs's format 'Z' gives \u00B1HH:mm format\n return dayjsDate.format(TIMESTAMP_FORMAT);\n },\n\n /**\n * Parses a timestamp string into a Date object.\n * Accepts both UTC ('Z') and timezone offset formats.\n *\n * @param timestamp Timestamp string to parse\n * @returns Date object\n */\n parseTimestamp(timestamp: string): Date {\n return dayjs(timestamp).toDate();\n },\n\n /**\n * Formats a date string to YYYY-MM-DD format\n *\n * @param input Date object, timestamp string, or undefined for current date\n * @returns Date string in YYYY-MM-DD format\n */\n formatDate(input?: Date | string | dayjs.Dayjs): string {\n return dayjs(input || new Date()).format('YYYY-MM-DD');\n },\n\n /**\n * Gets the current timestamp in the correct format\n *\n * @returns Current timestamp with timezone offset\n */\n now(): string {\n return this.formatTimestamp();\n },\n};\n", "import type { ApiClient } from '../http';\nimport type {\n NavigablePage,\n Page,\n Task,\n TaskCreateRequest,\n TaskListParams,\n TaskStatusUpdateRequest,\n TaskTimesUpdateRequest,\n TaskUpdateRequest,\n} from '../models';\nimport { DateUtils } from '../utils/date';\nimport { Resource } from './Resource';\n\nexport class TaskResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/tasks');\n }\n\n async create(data: TaskCreateRequest): Promise<Task> {\n const formattedData = {\n ...data,\n startDateTime: DateUtils.formatTimestamp(data.startDateTime),\n endDateTime: data.endDateTime ? DateUtils.formatTimestamp(data.endDateTime) : undefined,\n };\n return this.http.post<Task>(this.basePath, formattedData);\n }\n\n async update(id: string, data: TaskUpdateRequest): Promise<Task> {\n const formattedData = {\n ...data,\n startDateTime: data.startDateTime ? DateUtils.formatTimestamp(data.startDateTime) : undefined,\n endDateTime: data.endDateTime ? DateUtils.formatTimestamp(data.endDateTime) : undefined,\n };\n return this.http.put<Task>(`${this.basePath}/${encodeURIComponent(id)}`, formattedData);\n }\n\n async get(id: string): Promise<Task> {\n return this.http.get<Task>(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n async delete(id: string): Promise<void> {\n return this.http.delete(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n /**\n * Search tasks with parameters using POST\n * @param params Search parameters\n */\n async search(params: TaskListParams): Promise<NavigablePage<Task>> {\n const response = await this.http.post<Page<Task>>(`${this.basePath}/search`, params);\n return this.createNavigablePage(response, (page) => this.search({ ...params, page }));\n }\n\n /**\n * Update task status (billable, paid, billed)\n * @param data Status update data\n */\n async updateStatus(data: TaskStatusUpdateRequest): Promise<Task> {\n return this.http.put<Task>(`${this.basePath}/updateStatus`, data);\n }\n\n /**\n * Update task times\n * @param data Times update data\n */\n async updateTimes(data: TaskTimesUpdateRequest): Promise<Task> {\n const formattedData = {\n ...data,\n startDateTime: DateUtils.formatTimestamp(data.startDateTime),\n endDateTime: DateUtils.formatTimestamp(data.endDateTime),\n };\n return this.http.put<Task>(`${this.basePath}/updateTimes`, formattedData);\n }\n}\n", "import type { ApiClient } from '../http';\nimport type { Page, Rate, RateCreateRequest, RateListParams, RateUpdateRequest } from '../models';\nimport { NavigablePage } from '../models';\nimport { Resource } from './Resource';\n\nexport class RateResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/rates');\n }\n\n async list(params?: RateListParams): Promise<NavigablePage<Rate>> {\n const response = await this.http.get<Page<Rate>, RateListParams>(this.basePath, params);\n return new NavigablePage(response, (page) => this.list({ ...params, page }));\n }\n\n async create(data: RateCreateRequest): Promise<Rate> {\n return this.http.post<Rate>(this.basePath, data);\n }\n\n async update(id: string, data: RateUpdateRequest): Promise<Rate> {\n return this.http.put<Rate>(`${this.basePath}/${encodeURIComponent(id)}`, data);\n }\n\n async get(id: string): Promise<Rate> {\n return this.http.get<Rate>(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n async delete(id: string): Promise<void> {\n return this.http.delete(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n /**\n * Search rates with parameters using POST\n * @param params Search parameters\n */\n async search(params: RateListParams): Promise<NavigablePage<Rate>> {\n const response = await this.http.post<Page<Rate>>(`${this.basePath}/search`, params);\n return this.createNavigablePage(response, (page) => this.search({ ...params, page }));\n }\n}\n", "import type { ApiClient } from '../http';\nimport type { Page, Tag, TagCreateRequest, TagListParams, TagUpdateRequest } from '../models';\nimport { NavigablePage } from '../models';\nimport { Resource } from './Resource';\n\nexport class TagResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/tags');\n }\n\n async list(params?: TagListParams): Promise<NavigablePage<Tag>> {\n const response = await this.http.get<Page<Tag>, TagListParams>(this.basePath, params);\n return new NavigablePage(response, (page) => this.list({ ...params, page }));\n }\n\n async create(data: TagCreateRequest): Promise<Tag> {\n return this.http.post<Tag>(this.basePath, data);\n }\n\n async update(id: string, data: TagUpdateRequest): Promise<Tag> {\n return this.http.put<Tag>(`${this.basePath}/${encodeURIComponent(id)}`, data);\n }\n\n async get(id: string): Promise<Tag> {\n return this.http.get<Tag>(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n async delete(id: string): Promise<void> {\n return this.http.delete(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n /**\n * Search tags with parameters using POST\n * @param params Search parameters\n */\n async search(params: TagListParams): Promise<NavigablePage<Tag>> {\n const response = await this.http.post<Page<Tag>>(`${this.basePath}/search`, params);\n return this.createNavigablePage(response, (page) => this.search({ ...params, page }));\n }\n}\n", "import type { ApiClient } from '../http';\nimport type {\n Expense,\n ExpenseCreateRequest,\n ExpenseCreateWithFileRequest,\n ExpenseFileUpload,\n ExpenseListParams,\n ExpenseStatus,\n ExpenseUpdateRequest,\n Page,\n} from '../models';\nimport { NavigablePage } from '../models';\nimport { DateUtils } from '../utils/date';\nimport { Resource } from './Resource';\n\nexport class ExpenseResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/expenses');\n }\n\n async list(params?: ExpenseListParams): Promise<NavigablePage<Expense>> {\n const response = await this.http.get<Page<Expense>, ExpenseListParams>(this.basePath, params);\n return new NavigablePage(response, (page) => this.list({ ...params, page }));\n }\n\n async create(data: ExpenseCreateRequest): Promise<Expense> {\n const formattedData = {\n ...data,\n dateTime: DateUtils.formatTimestamp(data.dateTime),\n };\n return this.http.post<Expense>(this.basePath, formattedData);\n }\n\n async update(id: string, data: ExpenseUpdateRequest): Promise<Expense> {\n const formattedData = {\n ...data,\n dateTime: data.dateTime ? DateUtils.formatTimestamp(data.dateTime) : undefined,\n };\n return this.http.put<Expense>(`${this.basePath}/${encodeURIComponent(id)}`, formattedData);\n }\n\n async get(id: string): Promise<Expense> {\n return this.http.get<Expense>(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n async delete(id: string): Promise<void> {\n return this.http.delete(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n /**\n * Search expenses with parameters using POST\n * @param params Search parameters\n */\n async search(params: ExpenseListParams): Promise<NavigablePage<Expense>> {\n const response = await this.http.post<Page<Expense>>(`${this.basePath}/search`, params);\n return this.createNavigablePage(response, (page) => this.search({ ...params, page }));\n }\n\n /**\n * Update expense status\n * @param id Expense ID\n * @param data Status update data\n * @returns Updated expense\n */\n async updateStatus(id: string, data: ExpenseStatus): Promise<Expense> {\n return this.http.put<Expense>(`${this.basePath}/${id}/status`, data);\n }\n\n /**\n * Upload a file to an existing expense\n * @param id Expense ID\n * @param file File to upload\n * @returns Updated expense with file attachment\n */\n async uploadFile(id: string, file: ExpenseFileUpload): Promise<Expense> {\n const formData = new FormData();\n formData.append('file', file.file, file.fileName);\n return this.http.postMultipart<Expense>(\n `${this.basePath}/${encodeURIComponent(id)}/file`,\n formData,\n );\n }\n\n /**\n * Create an expense with a file attachment in a single request\n * @param data Expense data including optional file\n * @returns Created expense\n */\n async createWithFile(data: ExpenseCreateWithFileRequest): Promise<Expense> {\n const { file, ...expenseData } = data;\n const formattedData = {\n ...expenseData,\n dateTime: DateUtils.formatTimestamp(expenseData.dateTime),\n };\n\n const formData = new FormData();\n formData.append(\n 'data',\n new Blob([JSON.stringify(formattedData)], { type: 'application/json' }),\n );\n\n if (file) {\n formData.append('file', file.file, file.fileName);\n }\n\n return this.http.postMultipart<Expense>(`${this.basePath}/with-file`, formData);\n }\n\n /**\n * Get the signed URL for an expense file attachment\n * @param id Expense ID\n * @returns File URL response\n */\n async getFileUrl(id: string): Promise<{ url: string }> {\n return this.http.get<{ url: string }>(`${this.basePath}/getFileUrl/${encodeURIComponent(id)}`);\n }\n}\n", "import type { ApiClient } from '../http';\nimport type {\n Note,\n NoteCreateRequest,\n NoteCreateWithFileRequest,\n NoteFileUpload,\n NoteListParams,\n NoteUpdateRequest,\n Page,\n} from '../models';\nimport { NavigablePage } from '../models';\nimport { DateUtils } from '../utils/date';\nimport { Resource } from './Resource';\n\nexport class NoteResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/notes');\n }\n\n async list(params?: NoteListParams): Promise<NavigablePage<Note>> {\n const response = await this.http.get<Page<Note>, NoteListParams>(this.basePath, params);\n return new NavigablePage(response, (page) => this.list({ ...params, page }));\n }\n\n async create(data: NoteCreateRequest): Promise<Note> {\n const formattedData = {\n ...data,\n dateTime: DateUtils.formatTimestamp(data.dateTime),\n };\n return this.http.post<Note>(this.basePath, formattedData);\n }\n\n async update(id: string, data: NoteUpdateRequest): Promise<Note> {\n const formattedData = {\n ...data,\n dateTime: DateUtils.formatTimestamp(data.dateTime),\n };\n return this.http.put<Note>(`${this.basePath}/${encodeURIComponent(id)}`, formattedData);\n }\n\n async get(id: string): Promise<Note> {\n return this.http.get<Note>(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n async delete(id: string): Promise<void> {\n return this.http.delete(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n /**\n * Search notes with parameters using POST\n * @param params Search parameters\n */\n async search(params: NoteListParams): Promise<NavigablePage<Note>> {\n const response = await this.http.post<Page<Note>>(`${this.basePath}/search`, params);\n return this.createNavigablePage(response, (page) => this.search({ ...params, page }));\n }\n\n /**\n * Upload a file to an existing note\n * @param id Note ID\n * @param file File to upload\n * @returns Updated note with file attachment\n */\n async uploadFile(id: string, file: NoteFileUpload): Promise<Note> {\n const formData = new FormData();\n formData.append('file', file.file, file.fileName);\n return this.http.postMultipart<Note>(\n `${this.basePath}/${encodeURIComponent(id)}/file`,\n formData,\n );\n }\n\n /**\n * Create a note with a file attachment in a single request\n * @param data Note data including optional file\n * @returns Created note\n */\n async createWithFile(data: NoteCreateWithFileRequest): Promise<Note> {\n const { file, ...noteData } = data;\n const formattedData = {\n ...noteData,\n dateTime: DateUtils.formatTimestamp(noteData.dateTime),\n };\n\n const formData = new FormData();\n formData.append(\n 'data',\n new Blob([JSON.stringify(formattedData)], { type: 'application/json' }),\n );\n\n if (file) {\n formData.append('file', file.file, file.fileName);\n }\n\n return this.http.postMultipart<Note>(`${this.basePath}/with-file`, formData);\n }\n\n /**\n * Get the signed URL for a note file attachment\n * @param id Note ID\n * @returns File URL response\n */\n async getFileUrl(id: string): Promise<{ url: string }> {\n return this.http.get<{ url: string }>(`${this.basePath}/getFileUrl/${encodeURIComponent(id)}`);\n }\n}\n", "import type { ApiClient } from '../http';\nimport type {\n Page,\n Pause,\n PauseCreateRequest,\n PauseListParams,\n PauseUpdateRequest,\n} from '../models';\nimport { NavigablePage } from '../models';\nimport { DateUtils } from '../utils/date';\nimport { Resource } from './Resource';\n\nexport class PauseResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/pauses');\n }\n\n async list(params?: PauseListParams): Promise<NavigablePage<Pause>> {\n const response = await this.http.get<Page<Pause>, PauseListParams>(this.basePath, params);\n return new NavigablePage(response, (page) => this.list({ ...params, page }));\n }\n\n async create(data: PauseCreateRequest): Promise<Pause> {\n const formattedData = {\n ...data,\n startDateTime: DateUtils.formatTimestamp(data.startDateTime),\n endDateTime: DateUtils.formatTimestamp(data.endDateTime),\n };\n return this.http.post<Pause>(this.basePath, formattedData);\n }\n\n async update(id: string, data: PauseUpdateRequest): Promise<Pause> {\n const formattedData = {\n ...data,\n startDateTime: DateUtils.formatTimestamp(data.startDateTime),\n endDateTime: DateUtils.formatTimestamp(data.endDateTime),\n };\n return this.http.put<Pause>(`${this.basePath}/${encodeURIComponent(id)}`, formattedData);\n }\n\n async get(id: string): Promise<Pause> {\n return this.http.get<Pause>(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n async delete(id: string): Promise<void> {\n return this.http.delete(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n /**\n * Search pauses with parameters using POST\n * @param params Search parameters\n */\n async search(params: PauseListParams): Promise<NavigablePage<Pause>> {\n const response = await this.http.post<Page<Pause>>(`${this.basePath}/search`, params);\n return this.createNavigablePage(response, (page) => this.search({ ...params, page }));\n }\n}\n", "import type { ApiClient } from '../http';\nimport type { Profile, ProfileUpdateRequest } from '../models';\n\nexport class ProfileResource {\n constructor(private readonly http: ApiClient) {}\n\n async getProfile(): Promise<Profile> {\n return this.http.get<Profile>('/v1/profiles/me');\n }\n\n async updateProfile(data: ProfileUpdateRequest): Promise<Profile> {\n return this.http.put<Profile>('/v1/profiles/me', data);\n }\n}\n", "import type { ApiClient } from '../http';\nimport type { Settings, SettingsUpdateRequest } from '../models';\n\nexport class SettingsResource {\n constructor(private readonly http: ApiClient) {}\n\n async get(): Promise<Settings> {\n return this.http.get<Settings>('/v1/settings');\n }\n\n async update(data: SettingsUpdateRequest): Promise<Settings> {\n return this.http.put<Settings>('/v1/settings', data);\n }\n}\n", "import type { ApiClient } from '../http';\nimport type {\n Automation,\n AutomationCreateRequest,\n AutomationListParams,\n AutomationUpdateRequest,\n Page,\n} from '../models';\nimport { NavigablePage } from '../models';\nimport { Resource } from './Resource';\n\nexport class AutomationResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/automations');\n }\n\n async list(params?: AutomationListParams): Promise<NavigablePage<Automation>> {\n const response = await this.http.get<Page<Automation>, AutomationListParams>(\n this.basePath,\n params,\n );\n return new NavigablePage(response, (page) => this.list({ ...params, page }));\n }\n\n async create(data: AutomationCreateRequest): Promise<Automation> {\n return this.http.post<Automation>(this.basePath, data);\n }\n\n async update(id: string, data: AutomationUpdateRequest): Promise<Automation> {\n return this.http.put<Automation>(`${this.basePath}/${encodeURIComponent(id)}`, data);\n }\n\n async get(id: string): Promise<Automation> {\n return this.http.get<Automation>(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n async delete(id: string): Promise<void> {\n return this.http.delete(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n /**\n * Search automations with parameters using POST\n * @param params Search parameters\n */\n async search(params: AutomationListParams): Promise<NavigablePage<Automation>> {\n const response = await this.http.post<Page<Automation>>(`${this.basePath}/search`, params);\n return this.createNavigablePage(response, (page) => this.search({ ...params, page }));\n }\n}\n", "import type { ApiClient } from '../http';\nimport type {\n Document,\n DocumentCreateRequest,\n DocumentListParams,\n DocumentUpdateRequest,\n Page,\n} from '../models';\nimport { NavigablePage } from '../models';\nimport { Resource } from './Resource';\n\nexport class DocumentResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/documents');\n }\n\n async list(params?: DocumentListParams): Promise<NavigablePage<Document>> {\n const response = await this.http.get<Page<Document>, DocumentListParams>(this.basePath, params);\n return new NavigablePage(response, (page) => this.list({ ...params, page }));\n }\n\n async create(data: DocumentCreateRequest): Promise<Document> {\n return this.http.post<Document>(this.basePath, data);\n }\n\n async update(id: string, data: DocumentUpdateRequest): Promise<Document> {\n return this.http.put<Document>(`${this.basePath}/${encodeURIComponent(id)}`, data);\n }\n\n async get(id: string): Promise<Document> {\n return this.http.get<Document>(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n async delete(id: string): Promise<void> {\n return this.http.delete(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n /**\n * Search documents with parameters using POST\n * @param params Search parameters\n */\n async search(params: DocumentListParams): Promise<NavigablePage<Document>> {\n const response = await this.http.post<Page<Document>>(`${this.basePath}/search`, params);\n return this.createNavigablePage(response, (page) => this.search({ ...params, page }));\n }\n}\n", "import type { ApiClient } from '../http';\nimport type {\n Timer,\n TimerPauseRequest,\n TimerResumeRequest,\n TimerStartRequest,\n TimerStopRequest,\n TimerUpdateRequest,\n} from '../models';\nimport { DateUtils } from '../utils/date';\n\nexport class TimerResource {\n constructor(private readonly http: ApiClient) {}\n\n async get(): Promise<Timer> {\n return this.http.get<Timer>('/v1/timer');\n }\n\n async start(data: TimerStartRequest): Promise<Timer> {\n // Format startDateTime if provided\n const formattedData = {\n ...data,\n startDateTime: data.startDateTime\n ? DateUtils.formatTimestamp(data.startDateTime)\n : DateUtils.formatTimestamp(),\n };\n return this.http.post<Timer>('/v1/timer/start', formattedData);\n }\n\n async stop(data?: TimerStopRequest): Promise<Timer> {\n // Format endDateTime if provided\n const formattedData = data\n ? {\n ...data,\n endDateTime: data.endDateTime\n ? DateUtils.formatTimestamp(data.endDateTime)\n : DateUtils.formatTimestamp(),\n }\n : { endDateTime: DateUtils.formatTimestamp() };\n return this.http.post<Timer>('/v1/timer/stop', formattedData);\n }\n\n async pause(data?: TimerPauseRequest): Promise<Timer> {\n // Format startDateTime if provided\n const formattedData = data\n ? {\n ...data,\n startDateTime: data.startDateTime\n ? DateUtils.formatTimestamp(data.startDateTime)\n : DateUtils.formatTimestamp(),\n }\n : { startDateTime: DateUtils.formatTimestamp() };\n return this.http.post<Timer>('/v1/timer/pause', formattedData);\n }\n\n async resume(data?: TimerResumeRequest): Promise<Timer> {\n // Format endDateTime if provided\n const formattedData = data\n ? {\n ...data,\n endDateTime: data.endDateTime\n ? DateUtils.formatTimestamp(data.endDateTime)\n : DateUtils.formatTimestamp(),\n }\n : { endDateTime: DateUtils.formatTimestamp() };\n return this.http.post<Timer>('/v1/timer/resume', formattedData);\n }\n\n async update(data: TimerUpdateRequest): Promise<Timer> {\n // Format startDateTime if provided\n const formattedData = {\n ...data,\n startDateTime: data.startDateTime ? DateUtils.formatTimestamp(data.startDateTime) : undefined,\n };\n return this.http.put<Timer>('/v1/timer/update', formattedData);\n }\n}\n", "import type { ApiClient } from '../http';\nimport type { Page, Todo, TodoCreateRequest, TodoListParams, TodoUpdateRequest } from '../models';\nimport { NavigablePage } from '../models';\nimport { DateUtils } from '../utils/date';\nimport { Resource } from './Resource';\n\nexport class TodoResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/todos');\n }\n\n async list(params?: TodoListParams): Promise<NavigablePage<Todo>> {\n const response = await this.http.get<Page<Todo>, TodoListParams>(this.basePath, params);\n return new NavigablePage(response, (page) => this.list({ ...params, page }));\n }\n\n async create(data: TodoCreateRequest): Promise<Todo> {\n const formattedData = {\n ...data,\n dueDate: data.dueDate ? DateUtils.formatTimestamp(data.dueDate) : undefined,\n };\n return this.http.post<Todo>(this.basePath, formattedData);\n }\n\n async update(id: string, data: TodoUpdateRequest): Promise<Todo> {\n const formattedData = {\n ...data,\n dueDate: data.dueDate ? DateUtils.formatTimestamp(data.dueDate) : undefined,\n };\n return this.http.put<Todo>(`${this.basePath}/${encodeURIComponent(id)}`, formattedData);\n }\n\n async get(id: string): Promise<Todo> {\n return this.http.get<Todo>(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n async delete(id: string): Promise<void> {\n return this.http.delete(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n /**\n * Search todos with parameters using POST\n * @param params Search parameters\n */\n async search(params: TodoListParams): Promise<NavigablePage<Todo>> {\n const response = await this.http.post<Page<Todo>>(`${this.basePath}/search`, params);\n return this.createNavigablePage(response, (page) => this.search({ ...params, page }));\n }\n}\n", "import type { ApiClient } from '../http';\nimport type {\n Page,\n Webhook,\n WebhookCreateRequest,\n WebhookListParams,\n WebhookUpdateRequest,\n} from '../models';\nimport { NavigablePage } from '../models';\nimport { Resource } from './Resource';\n\nexport class WebhookResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/webhooks');\n }\n\n async list(params?: WebhookListParams): Promise<NavigablePage<Webhook>> {\n const response = await this.http.get<Page<Webhook>, WebhookListParams>(this.basePath, params);\n return new NavigablePage(response, (page) => this.list({ ...params, page }));\n }\n\n async create(data: WebhookCreateRequest): Promise<Webhook> {\n return this.http.post<Webhook>(this.basePath, data);\n }\n\n async update(id: string, data: WebhookUpdateRequest): Promise<Webhook> {\n return this.http.put<Webhook>(`${this.basePath}/${encodeURIComponent(id)}`, data);\n }\n\n async get(id: string): Promise<Webhook> {\n return this.http.get<Webhook>(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n async delete(id: string): Promise<void> {\n return this.http.delete(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n /**\n * Search webhooks with parameters using POST\n * @param params Search parameters\n */\n async search(params: WebhookListParams): Promise<NavigablePage<Webhook>> {\n const response = await this.http.post<Page<Webhook>>(`${this.basePath}/search`, params);\n return this.createNavigablePage(response, (page) => this.search({ ...params, page }));\n }\n}\n", "import type { ApiClient } from '../http';\nimport type { EventData, EventType, SseStatus, SseSubscription } from '../models';\nimport { Resource } from './Resource';\n\n/**\n * EventResource provides access to Server-Sent Events (SSE) for real-time updates.\n *\n * @example\n * ```typescript\n * // Subscribe to events\n * const subscription = await client.events.subscribe({\n * onEvent: (event) => {\n * console.log('Received event:', event.event, event.item);\n * },\n * onError: (error) => {\n * console.error('SSE error:', error);\n * }\n * });\n *\n * // Later, close the connection\n * subscription.close();\n * ```\n */\nexport class EventResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/events');\n }\n\n /**\n * Get the current SSE connection status for the authenticated user.\n * @returns Status including whether connected and connection count\n */\n async getStatus(): Promise<SseStatus> {\n return this.http.get<SseStatus>(`${this.basePath}/status`);\n }\n\n /**\n * Get the full URL for the SSE stream endpoint.\n * Useful if you want to use a custom EventSource implementation.\n * @returns The full URL to the SSE stream endpoint\n */\n getStreamUrl(): string {\n return `${this.http.getBaseUrl()}${this.basePath}/stream`;\n }\n\n /**\n * Subscribe to real-time events via Server-Sent Events.\n *\n * This method establishes an SSE connection to receive real-time updates\n * for entity changes (tasks, projects, teams, etc.).\n *\n * Note: This uses fetch with ReadableStream for broad compatibility.\n * For browser environments, you may also use getStreamUrl() with EventSource.\n *\n * @param options Subscription options including event handlers\n * @returns A subscription object with close() method\n *\n * @example\n * ```typescript\n * const subscription = await client.events.subscribe({\n * onEvent: (event) => {\n * switch (event.event) {\n * case 'task.create':\n * console.log('New task created:', event.item);\n * break;\n * case 'task.update':\n * console.log('Task updated:', event.item);\n * break;\n * }\n * },\n * onConnected: (connectionId) => {\n * console.log('Connected with ID:', connectionId);\n * },\n * onError: (error) => {\n * console.error('Error:', error);\n * },\n * onClose: () => {\n * console.log('Connection closed');\n * }\n * });\n *\n * // Close when done\n * subscription.close();\n * ```\n */\n async subscribe(options: SubscribeOptions): Promise<SseSubscription> {\n const url = this.getStreamUrl();\n const authHeaders = await this.http.getAuthHeaders();\n\n const headers: Record<string, string> = {\n Accept: 'text/event-stream',\n 'Cache-Control': 'no-cache',\n ...authHeaders,\n };\n\n const abortController = new AbortController();\n let isConnected = false;\n const eventHandlers = new Map<string, Set<(data: unknown) => void>>();\n\n const subscription: SseSubscription = {\n close: () => {\n isConnected = false;\n abortController.abort();\n options.onClose?.();\n },\n get isConnected() {\n return isConnected;\n },\n on: (event: EventType | 'error', handler: (data: unknown) => void) => {\n if (!eventHandlers.has(event)) {\n eventHandlers.set(event, new Set());\n }\n eventHandlers.get(event)!.add(handler);\n },\n off: (event: EventType | 'error', handler: (data: unknown) => void) => {\n eventHandlers.get(event)?.delete(handler);\n },\n };\n\n // Start the SSE connection (intentionally not awaited - runs in background)\n void this.connectSse(url, headers, abortController.signal, {\n ...options,\n onConnected: (connectionId) => {\n isConnected = true;\n options.onConnected?.(connectionId);\n },\n onEvent: (event) => {\n options.onEvent?.(event);\n // Also emit to registered handlers\n const handlers = eventHandlers.get(event.event as EventType);\n handlers?.forEach((handler) => handler(event));\n },\n onError: (error) => {\n options.onError?.(error);\n const handlers = eventHandlers.get('error');\n handlers?.forEach((handler) => handler(error));\n },\n onClose: () => {\n isConnected = false;\n options.onClose?.();\n },\n });\n\n return subscription;\n }\n\n /**\n * Internal method to establish and manage the SSE connection.\n */\n private async connectSse(\n url: string,\n headers: Record<string, string>,\n signal: AbortSignal,\n options: SubscribeOptions,\n ): Promise<void> {\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers,\n signal,\n });\n\n if (!response.ok) {\n throw new Error(`SSE connection failed: ${response.status} ${response.statusText}`);\n }\n\n if (!response.body) {\n throw new Error('SSE response has no body');\n }\n\n const reader = response.body.getReader() as ReadableStreamDefaultReader<Uint8Array>;\n const decoder = new TextDecoder();\n let buffer = '';\n\n // Current event being parsed\n let eventType = '';\n let eventData = '';\n let eventId = '';\n\n let done = false;\n while (!done) {\n const result = await reader.read();\n done = result.done;\n\n if (done || !result.value) {\n options.onClose?.();\n break;\n }\n\n buffer += decoder.decode(result.value, { stream: true });\n\n // Process complete lines\n const lines = buffer.split('\\n');\n buffer = lines.pop() || ''; // Keep incomplete line in buffer\n\n for (const line of lines) {\n if (line.startsWith('event:')) {\n eventType = line.slice(6).trim();\n } else if (line.startsWith('data:')) {\n eventData = line.slice(5).trim();\n } else if (line.startsWith('id:')) {\n eventId = line.slice(3).trim();\n } else if (line === '') {\n // Empty line signals end of event\n if (eventData) {\n this.processEvent(eventType, eventData, eventId, options);\n }\n // Reset for next event\n eventType = '';\n eventData = '';\n eventId = '';\n }\n }\n }\n } catch (error) {\n if (signal.aborted) {\n // Connection was intentionally closed\n return;\n }\n options.onError?.(error);\n }\n }\n\n /**\n * Process a received SSE event.\n */\n private processEvent(\n eventType: string,\n eventData: string,\n _eventId: string,\n options: SubscribeOptions,\n ): void {\n try {\n const data: unknown = JSON.parse(eventData);\n\n if (eventType === 'connected') {\n const connectedData = data as { connectionId: string };\n options.onConnected?.(connectedData.connectionId);\n } else {\n options.onEvent?.(data as EventData);\n }\n } catch {\n options.onError?.(new Error(`Failed to parse event data: ${eventData}`));\n }\n }\n}\n\n/**\n * Options for subscribing to SSE events\n */\nexport interface SubscribeOptions {\n /**\n * Called when an event is received\n */\n onEvent?: (event: EventData) => void;\n\n /**\n * Called when the connection is established\n */\n onConnected?: (connectionId: string) => void;\n\n /**\n * Called when an error occurs\n */\n onError?: (error: unknown) => void;\n\n /**\n * Called when the connection is closed\n */\n onClose?: () => void;\n}\n", "import type { ApiClient } from '../../http';\nimport type { DocumentReport } from '../../models';\nimport { Resource } from '../Resource';\n\n/**\n * Resource for generating document reports and PDFs.\n * Accesses the Reports API at reports.timesheet.io.\n */\nexport class DocumentReportResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/documents');\n }\n\n /**\n * Generate document report data in JSON format.\n * Returns a DocumentReport entity containing all document data.\n * @param documentId Unique identifier of the document\n */\n async get(documentId: string): Promise<DocumentReport> {\n return this.http.get<DocumentReport>(`${this.basePath}/${encodeURIComponent(documentId)}`);\n }\n\n /**\n * Generate and download a PDF report for a specific document.\n * The PDF includes all document data (tasks, expenses, notes) formatted\n * according to user settings and document template.\n * @param documentId Unique identifier of the document\n * @returns ArrayBuffer containing the PDF file data\n */\n async getPdf(documentId: string): Promise<ArrayBuffer> {\n return this.http.request<ArrayBuffer>({\n method: 'GET',\n url: `${this.basePath}/${encodeURIComponent(documentId)}/pdf`,\n responseType: 'arraybuffer',\n });\n }\n\n /**\n * Generate XML representation of the document.\n * Returns Zugferd/XRechnung, ebInterface, or plain DocumentReport XML\n * based on the document's eInvoiceType configuration.\n * @param documentId Unique identifier of the document\n * @returns String containing the XML data\n */\n async getXml(documentId: string): Promise<string> {\n return this.http.request<string>({\n method: 'GET',\n url: `${this.basePath}/${encodeURIComponent(documentId)}/xml`,\n headers: {\n Accept: 'application/xml',\n },\n });\n }\n}\n", "import type { ApiClient } from '../../http';\nimport type { TaskReportItem } from '../../models';\nimport { Resource } from '../Resource';\n\n/**\n * Resource for generating task reports and PDFs.\n * Accesses the Reports API at reports.timesheet.io.\n */\nexport class TaskReportResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/tasks');\n }\n\n /**\n * Generate task report data in JSON format.\n * Returns a TaskReportItem entity containing formatted task information\n * including time tracking, rates, project details, and signatures.\n * @param taskId Unique identifier of the task\n */\n async get(taskId: string): Promise<TaskReportItem> {\n return this.http.get<TaskReportItem>(`${this.basePath}/${encodeURIComponent(taskId)}`);\n }\n\n /**\n * Generate and download a PDF report for a specific task.\n * The PDF includes task details, time tracking information, project context,\n * and any associated signatures formatted according to user settings.\n * @param taskId Unique identifier of the task\n * @returns ArrayBuffer containing the PDF file data\n */\n async getPdf(taskId: string): Promise<ArrayBuffer> {\n return this.http.request<ArrayBuffer>({\n method: 'GET',\n url: `${this.basePath}/${encodeURIComponent(taskId)}/pdf`,\n responseType: 'arraybuffer',\n });\n }\n}\n", "import type { ApiClient } from '../../http';\nimport type { ExpenseReportItem } from '../../models';\nimport { Resource } from '../Resource';\n\n/**\n * Resource for generating expense reports and PDFs.\n * Accesses the Reports API at reports.timesheet.io.\n */\nexport class ExpenseReportResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/expenses');\n }\n\n /**\n * Generate expense report data in JSON format.\n * Returns an ExpenseReportItem entity containing formatted expense information\n * including amounts, descriptions, receipts, and timestamps.\n * @param expenseId Unique identifier of the expense\n */\n async get(expenseId: string): Promise<ExpenseReportItem> {\n return this.http.get<ExpenseReportItem>(`${this.basePath}/${encodeURIComponent(expenseId)}`);\n }\n\n /**\n * Generate and download a PDF report for a specific expense.\n * The PDF includes expense details, amounts, receipt images,\n * and formatting according to user settings.\n * @param expenseId Unique identifier of the expense\n * @returns ArrayBuffer containing the PDF file data\n */\n async getPdf(expenseId: string): Promise<ArrayBuffer> {\n return this.http.request<ArrayBuffer>({\n method: 'GET',\n url: `${this.basePath}/${encodeURIComponent(expenseId)}/pdf`,\n responseType: 'arraybuffer',\n });\n }\n}\n", "import type { ApiClient } from '../../http';\nimport type { NoteReportItem } from '../../models';\nimport { Resource } from '../Resource';\n\n/**\n * Resource for generating note reports and PDFs.\n * Accesses the Reports API at reports.timesheet.io.\n */\nexport class NoteReportResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/notes');\n }\n\n /**\n * Generate note report data in JSON format.\n * Returns a NoteReportItem entity containing formatted note information\n * including content, attachments, timestamps, and author details.\n * @param noteId Unique identifier of the note\n */\n async get(noteId: string): Promise<NoteReportItem> {\n return this.http.get<NoteReportItem>(`${this.basePath}/${encodeURIComponent(noteId)}`);\n }\n\n /**\n * Generate and download a PDF report for a specific note.\n * The PDF includes note content, metadata, attached images,\n * and formatting according to user settings.\n * @param noteId Unique identifier of the note\n * @returns ArrayBuffer containing the PDF file data\n */\n async getPdf(noteId: string): Promise<ArrayBuffer> {\n return this.http.request<ArrayBuffer>({\n method: 'GET',\n url: `${this.basePath}/${encodeURIComponent(noteId)}/pdf`,\n responseType: 'arraybuffer',\n });\n }\n}\n", "import type { ApiClient } from '../../http';\nimport type {\n CustomExportField,\n CustomExportFieldCreateRequest,\n CustomExportFieldsResponse,\n CustomExportFieldUpdateRequest,\n ExportFieldsResponse,\n ExportParams,\n ExportReportsResponse,\n ExportTemplate,\n ExportTemplateCreateRequest,\n ExportTemplateListParams,\n ExportTemplateParams,\n ExportTemplateUpdateRequest,\n FileResponse,\n Page,\n} from '../../models';\nimport { NavigablePage } from '../../models';\nimport { Resource } from '../Resource';\n\n/**\n * Resource for generating timesheet exports in various formats.\n * Accesses the Reports API at reports.timesheet.io.\n */\nexport class ExportResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/export');\n }\n\n // ============================================================================\n // Export Generation\n // ============================================================================\n\n /**\n * Generate and download a timesheet export.\n * Creates an export file based on the provided parameters and returns\n * a signed URL to download it. Supports Excel, CSV, and PDF formats.\n * @param params Export configuration parameters\n * @returns FileResponse with download URL\n */\n async generate(params: ExportParams): Promise<FileResponse> {\n return this.http.post<FileResponse>(`${this.basePath}/data`, params);\n }\n\n /**\n * Generate and email a timesheet export.\n * Creates an export file and sends it via email to the specified address.\n * The email field in params must be provided.\n * @param params Export configuration parameters (must include email)\n */\n async send(params: ExportParams): Promise<void> {\n return this.http.post<void>(`${this.basePath}/send`, params);\n }\n\n /**\n * Generate export from a saved template.\n * Creates an export file using a previously saved template with custom\n * start and end dates. The template defines the report type, format,\n * filters, and field selection.\n * @param params Template ID and date range\n * @returns ArrayBuffer containing the export file data\n */\n async generateFromTemplate(params: ExportTemplateParams): Promise<ArrayBuffer> {\n return this.http.request<ArrayBuffer>({\n method: 'POST',\n url: `${this.basePath}/from-template`,\n data: params,\n responseType: 'arraybuffer',\n });\n }\n\n // ============================================================================\n // Export Configuration\n // ============================================================================\n\n /**\n * Get available export fields.\n * Returns the list of available export fields from the field registry.\n * @param scope Optional scope filter: 'all', 'project', or 'team'\n */\n async getFields(scope?: 'all' | 'project' | 'team'): Promise<ExportFieldsResponse> {\n return this.http.get<ExportFieldsResponse, Record<string, unknown>>(\n `${this.basePath}/fields`,\n scope ? { scope } : undefined,\n );\n }\n\n /**\n * Get available report types.\n * Returns the list of available export report types with metadata.\n */\n async getReportTypes(): Promise<ExportReportsResponse> {\n return this.http.get<ExportReportsResponse>(`${this.basePath}/report-types`);\n }\n\n // ============================================================================\n // Export Templates\n // ============================================================================\n\n /**\n * Get user's export templates.\n * Returns a paginated list of export templates created by the authenticated user.\n * @param params Optional pagination and sorting parameters\n */\n async listTemplates(params?: ExportTemplateListParams): Promise<NavigablePage<ExportTemplate>> {\n const response = await this.http.get<Page<ExportTemplate>, Record<string, unknown>>(\n `${this.basePath}/templates`,\n params as Record<string, unknown>,\n );\n return new NavigablePage(response, (page) => this.listTemplates({ ...params, page }));\n }\n\n /**\n * Search export templates.\n * Performs an advanced search for export templates based on the provided parameters.\n * @param params Search parameters including filters, pagination, and sorting\n */\n async searchTemplates(params: ExportTemplateListParams): Promise<NavigablePage<ExportTemplate>> {\n const response = await this.http.post<Page<ExportTemplate>>(\n `${this.basePath}/templates/search`,\n params,\n );\n return this.createNavigablePage(response, (page) => this.searchTemplates({ ...params, page }));\n }\n\n /**\n * Create an export template.\n * Creates a new export template from the provided data.\n * @param data Template creation data\n */\n async createTemplate(data: ExportTemplateCreateRequest): Promise<ExportTemplate> {\n return this.http.post<ExportTemplate>(`${this.basePath}/templates`, data);\n }\n\n /**\n * Get a single export template.\n * Retrieves a specific export template by ID with resolved JSON fields.\n * @param templateId Template ID\n */\n async getTemplate(templateId: string): Promise<ExportTemplate> {\n return this.http.get<ExportTemplate>(\n `${this.basePath}/templates/${encodeURIComponent(templateId)}`,\n );\n }\n\n /**\n * Update an export template.\n * Updates an existing export template with new data.\n * @param templateId Template ID\n * @param data Updated template data\n */\n async updateTemplate(\n templateId: string,\n data: ExportTemplateUpdateRequest,\n ): Promise<ExportTemplate> {\n return this.http.put<ExportTemplate>(\n `${this.basePath}/templates/${encodeURIComponent(templateId)}`,\n data,\n );\n }\n\n /**\n * Delete an export template.\n * @param templateId Template ID\n */\n async deleteTemplate(templateId: string): Promise<void> {\n return this.http.delete(`${this.basePath}/templates/${encodeURIComponent(templateId)}`);\n }\n\n // ============================================================================\n // Custom Export Fields\n // ============================================================================\n\n /**\n * Get user's custom export fields.\n * Returns all custom export fields created by the authenticated user.\n * @param scope Optional scope filter: 'TASK', 'PROJECT', or 'TEAM'\n */\n async listCustomFields(scope?: 'TASK' | 'PROJECT' | 'TEAM'): Promise<CustomExportFieldsResponse> {\n return this.http.get<CustomExportFieldsResponse, Record<string, unknown>>(\n `${this.basePath}/custom-fields`,\n scope ? { scope } : undefined,\n );\n }\n\n /**\n * Create a custom export field.\n * Creates a new custom export field that can be used in exports.\n * @param data Custom field creation data\n */\n async createCustomField(data: CustomExportFieldCreateRequest): Promise<CustomExportField> {\n return this.http.post<CustomExportField>(`${this.basePath}/custom-fields`, data);\n }\n\n /**\n * Get a single custom export field.\n * Retrieves a specific custom export field by ID.\n * @param fieldId Field ID\n */\n async getCustomField(fieldId: string): Promise<CustomExportField> {\n return this.http.get<CustomExportField>(\n `${this.basePath}/custom-fields/${encodeURIComponent(fieldId)}`,\n );\n }\n\n /**\n * Update a custom export field.\n * Updates an existing custom export field.\n * @param fieldId Field ID\n * @param data Updated field data\n */\n async updateCustomField(\n fieldId: string,\n data: CustomExportFieldUpdateRequest,\n ): Promise<CustomExportField> {\n return this.http.put<CustomExportField>(\n `${this.basePath}/custom-fields/${encodeURIComponent(fieldId)}`,\n data,\n );\n }\n\n /**\n * Delete a custom export field (soft delete).\n * @param fieldId Field ID\n */\n async deleteCustomField(fieldId: string): Promise<void> {\n return this.http.delete(`${this.basePath}/custom-fields/${encodeURIComponent(fieldId)}`);\n }\n}\n", "import type { ApiClient } from '../../http';\nimport { DocumentReportResource } from './DocumentReportResource';\nimport { TaskReportResource } from './TaskReportResource';\nimport { ExpenseReportResource } from './ExpenseReportResource';\nimport { NoteReportResource } from './NoteReportResource';\nimport { ExportResource } from './ExportResource';\n\n/**\n * Reports API client providing access to PDF generation, exports, and report data.\n *\n * This client accesses the Reports API (reports.timesheet.io) which provides:\n * - Document, task, expense, and note PDF generation\n * - Timesheet exports in Excel, CSV, and PDF formats\n * - Export templates for saving export configurations\n * - Custom export fields for personalized exports\n *\n * @example\n * ```typescript\n * // Access via main client\n * const client = new TimesheetClient({ apiKey: 'your-api-key' });\n *\n * // Generate a document PDF\n * const pdfData = await client.reports.documents.getPdf('doc_123');\n *\n * // Generate a timesheet export\n * const exportResult = await client.reports.export.generate({\n * report: 1,\n * startDate: '2024-01-01',\n * endDate: '2024-01-31',\n * format: 'xlsx'\n * });\n *\n * // Get task report data\n * const taskReport = await client.reports.tasks.get('task_456');\n * ```\n */\nexport class ReportsClient {\n /**\n * Document report generation endpoints.\n * Generate document PDFs, XML (e-invoicing), and report data.\n */\n public readonly documents: DocumentReportResource;\n\n /**\n * Task report generation endpoints.\n * Generate task PDFs and report data.\n */\n public readonly tasks: TaskReportResource;\n\n /**\n * Expense report generation endpoints.\n * Generate expense PDFs and report data.\n */\n public readonly expenses: ExpenseReportResource;\n\n /**\n * Note report generation endpoints.\n * Generate note PDFs and report data.\n */\n public readonly notes: NoteReportResource;\n\n /**\n * Export generation endpoints.\n * Generate timesheet exports, manage templates, and custom fields.\n */\n public readonly export: ExportResource;\n\n /**\n * Creates a new ReportsClient instance.\n * @param apiClient ApiClient configured for the Reports API\n */\n constructor(apiClient: ApiClient) {\n this.documents = new DocumentReportResource(apiClient);\n this.tasks = new TaskReportResource(apiClient);\n this.expenses = new ExpenseReportResource(apiClient);\n this.notes = new NoteReportResource(apiClient);\n this.export = new ExportResource(apiClient);\n }\n}\n", "import { ApiClient } from './http';\nimport type { Authentication } from './auth';\nimport { ApiKeyAuth, OAuth2Auth } from './auth';\nimport type { ClientConfig } from './config';\nimport { RetryConfig } from './config';\nimport type { AxiosInstance } from 'axios';\nimport {\n AutomationResource,\n DocumentResource,\n EventResource,\n ExpenseResource,\n NoteResource,\n OrganizationResource,\n PauseResource,\n ProfileResource,\n ProjectResource,\n RateResource,\n ReportsClient,\n SettingsResource,\n TagResource,\n TaskResource,\n TeamResource,\n TimerResource,\n TodoResource,\n WebhookResource,\n} from './resources';\n\n// Export all modules\nexport * from './auth';\nexport * from './config';\nexport * from './exceptions';\nexport * from './models';\nexport * from './http';\nexport * from './resources';\n\n/**\n * Main entry point for the Timesheet SDK.\n *\n * @example\n * ```typescript\n * // Using API Key\n * const client = new TimesheetClient({\n * apiKey: 'your-api-key'\n * });\n *\n * // Using OAuth2\n * const client = new TimesheetClient({\n * oauth2Token: 'your-access-token'\n * });\n * ```\n */\nexport class TimesheetClient {\n private readonly apiClient: ApiClient;\n private readonly reportsApiClient: ApiClient;\n\n // Resource APIs\n public readonly organizations: OrganizationResource;\n public readonly teams: TeamResource;\n public readonly projects: ProjectResource;\n public readonly tasks: TaskResource;\n public readonly rates: RateResource;\n public readonly tags: TagResource;\n public readonly expenses: ExpenseResource;\n public readonly notes: NoteResource;\n public readonly pauses: PauseResource;\n public readonly profile: ProfileResource;\n public readonly settings: SettingsResource;\n public readonly automations: AutomationResource;\n public readonly documents: DocumentResource;\n public readonly timer: TimerResource;\n public readonly todos: TodoResource;\n public readonly webhooks: WebhookResource;\n public readonly events: EventResource;\n\n /**\n * Reports API for PDF generation, exports, and report data.\n * Provides access to document, task, expense, and note report generation,\n * as well as timesheet exports in various formats.\n *\n * @example\n * ```typescript\n * // Generate a document PDF\n * const pdfData = await client.reports.documents.getPdf('doc_123');\n *\n * // Generate a timesheet export\n * const exportResult = await client.reports.export.generate({\n * report: 1,\n * startDate: '2024-01-01',\n * endDate: '2024-01-31',\n * format: 'xlsx'\n * });\n * ```\n */\n public readonly reports: ReportsClient;\n\n /**\n * Creates a new TimesheetClient instance.\n *\n * @param options Configuration options\n */\n constructor(options: TimesheetClientOptions) {\n const authentication = this.createAuthentication(options);\n const retryConfig = options.retryConfig || RetryConfig.default();\n\n // Main API client (api.timesheet.io)\n const config: ClientConfig = {\n baseUrl: options.baseUrl || 'https://api.timesheet.io',\n authentication,\n retryConfig,\n httpClient: options.httpClient,\n };\n\n this.apiClient = new ApiClient(config);\n\n // Reports API client (reports.timesheet.io)\n const reportsConfig: ClientConfig = {\n baseUrl: options.reportsBaseUrl || 'https://reports.timesheet.io',\n authentication,\n retryConfig,\n httpClient: options.reportsHttpClient,\n };\n\n this.reportsApiClient = new ApiClient(reportsConfig);\n\n // Initialize main API resources\n this.organizations = new OrganizationResource(this.apiClient);\n this.teams = new TeamResource(this.apiClient);\n this.projects = new ProjectResource(this.apiClient);\n this.tasks = new TaskResource(this.apiClient);\n this.rates = new RateResource(this.apiClient);\n this.tags = new TagResource(this.apiClient);\n this.expenses = new ExpenseResource(this.apiClient);\n this.notes = new NoteResource(this.apiClient);\n this.pauses = new PauseResource(this.apiClient);\n this.profile = new ProfileResource(this.apiClient);\n this.settings = new SettingsResource(this.apiClient);\n this.automations = new AutomationResource(this.apiClient);\n this.documents = new DocumentResource(this.apiClient);\n this.timer = new TimerResource(this.apiClient);\n this.todos = new TodoResource(this.apiClient);\n this.webhooks = new WebhookResource(this.apiClient);\n this.events = new EventResource(this.apiClient);\n\n // Initialize reports API resources\n this.reports = new ReportsClient(this.reportsApiClient);\n }\n\n private createAuthentication(options: TimesheetClientOptions): Authentication {\n if (options.apiKey) {\n return new ApiKeyAuth(options.apiKey);\n } else if (options.oauth2Token) {\n return new OAuth2Auth(options.oauth2Token);\n } else if (options.oauth2) {\n return new OAuth2Auth(\n options.oauth2.clientId,\n options.oauth2.clientSecret,\n options.oauth2.refreshToken,\n );\n } else if (options.authentication) {\n return options.authentication;\n } else {\n throw new Error('Authentication must be configured');\n }\n }\n}\n\n/**\n * Configuration options for TimesheetClient.\n */\nexport interface TimesheetClientOptions {\n /**\n * API key for authentication.\n */\n apiKey?: string;\n\n /**\n * OAuth2 bearer token for authentication.\n */\n oauth2Token?: string;\n\n /**\n * OAuth2 configuration with refresh capability.\n */\n oauth2?: {\n clientId: string;\n clientSecret: string;\n refreshToken: string;\n };\n\n /**\n * Custom authentication implementation.\n */\n authentication?: Authentication;\n\n /**\n * Custom base URL for the main API.\n * @default 'https://api.timesheet.io'\n */\n baseUrl?: string;\n\n /**\n * Custom base URL for the Reports API.\n * @default 'https://reports.timesheet.io'\n */\n reportsBaseUrl?: string;\n\n /**\n * Custom retry configuration.\n */\n retryConfig?: RetryConfig;\n\n /**\n * Custom HTTP client (axios instance) for the main API.\n */\n httpClient?: AxiosInstance;\n\n /**\n * Custom HTTP client (axios instance) for the Reports API.\n */\n reportsHttpClient?: AxiosInstance;\n}\n\n// Export convenience function\nexport function createClient(options: TimesheetClientOptions): TimesheetClient {\n return new TimesheetClient(options);\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["axios", "TimesheetApiError", "_TimesheetApiError", "message", "statusCode", "responseBody", "errorCode", "fullMessage", "TimesheetAuthError", "TimesheetApiError", "message", "statusCode", "responseBody", "TimesheetRateLimitError", "TimesheetApiError", "message", "retryAfter", "epochSeconds", "date", "ApiClient", "config", "axios", "authHeaders", "key", "value", "lastError", "retryConfig", "attempt", "error", "errorData", "TimesheetAuthError", "retryAfter", "TimesheetRateLimitError", "status", "delay", "TimesheetApiError", "path", "params", "data", "formData", "ms", "resolve", "ApiKeyAuth", "apiKey", "config", "axios", "jwt", "_OAuth2Auth", "accessTokenOrClientId", "clientSecret", "refreshToken", "config", "response", "error", "message", "clientId", "authorizationCode", "redirectUri", "accessToken", "state", "params", "decoded", "OAuth2Auth", "axios", "jwt", "randomBytes", "createHash", "generateCodeVerifier", "length", "buffer", "base64UrlEncode", "generateCodeChallenge", "codeVerifier", "method", "hash", "generatePkceCodePair", "verifierLength", "codeChallenge", "isValidCodeVerifier", "_OAuth21Auth", "accessTokenOrOptions", "options", "config", "params", "response", "axios", "error", "message", "clientId", "clientSecret", "authorizationCode", "redirectUri", "codeVerifier", "resource", "tokenEndpoint", "effectiveTokenEndpoint", "isValidCodeVerifier", "accessToken", "refreshToken", "codeChallenge", "codeChallengeMethod", "state", "scope", "authorizationEndpoint", "effectiveAuthEndpoint", "method", "generatePkceCodePair", "decoded", "jwt", "OAuth21Auth", "axios", "_OAuthDiscovery", "options", "issuerUrl", "normalizedUrl", "cached", "authServerMetadata", "result", "url", "response", "error", "message", "resourceUrl", "entry", "expiresAt", "metadata", "config", "OAuthDiscovery", "defaultDiscovery", "getDefaultDiscovery", "discoverOAuth", "RetryConfig", "_RetryConfig", "options", "NavigablePage", "data", "nextPageLoader", "currentPage", "item", "allItems", "WebhookEvents", "combineWebhookEvents", "events", "Resource", "http", "config", "page", "nextPageLoader", "NavigablePage", "OrganizationResource", "Resource", "client", "params", "response", "NavigablePage", "page", "data", "id", "TeamResource", "Resource", "client", "params", "response", "NavigablePage", "page", "data", "id", "teamId", "memberId", "ProjectResource", "Resource", "client", "params", "response", "NavigablePage", "page", "data", "id", "dayjs", "utc", "timezone", "customParseFormat", "TIMESTAMP_FORMAT", "TIMESTAMP_REGEX", "DateUtils", "timestamp", "input", "TaskResource", "Resource", "client", "
|
|
3
|
+
"sources": ["../src/http/ApiClient.ts", "../src/exceptions/TimesheetApiError.ts", "../src/exceptions/TimesheetAuthError.ts", "../src/exceptions/TimesheetRateLimitError.ts", "../src/auth/ApiKeyAuth.ts", "../src/auth/OAuth2Auth.ts", "../src/auth/OAuth21Auth.ts", "../src/auth/pkce.ts", "../src/auth/OAuthDiscovery.ts", "../src/config/RetryConfig.ts", "../src/models/Page.ts", "../src/models/Webhook.ts", "../src/resources/Resource.ts", "../src/resources/OrganizationResource.ts", "../src/resources/TeamResource.ts", "../src/resources/ProjectResource.ts", "../src/utils/date.ts", "../src/resources/TaskResource.ts", "../src/resources/RateResource.ts", "../src/resources/TagResource.ts", "../src/resources/ExpenseResource.ts", "../src/resources/NoteResource.ts", "../src/resources/PauseResource.ts", "../src/resources/ProfileResource.ts", "../src/resources/SettingsResource.ts", "../src/resources/AutomationResource.ts", "../src/resources/DocumentResource.ts", "../src/resources/TimerResource.ts", "../src/resources/TodoResource.ts", "../src/resources/WebhookResource.ts", "../src/resources/EventResource.ts", "../src/resources/AbsenceResource.ts", "../src/resources/AbsenceTypeResource.ts", "../src/resources/ContractResource.ts", "../src/resources/ContractTemplateResource.ts", "../src/resources/reports/DocumentReportResource.ts", "../src/resources/reports/TaskReportResource.ts", "../src/resources/reports/ExpenseReportResource.ts", "../src/resources/reports/NoteReportResource.ts", "../src/resources/reports/ExportResource.ts", "../src/resources/reports/ReportsClient.ts", "../src/index.ts"],
|
|
4
|
+
"sourcesContent": ["import type { AxiosInstance, AxiosRequestConfig } from 'axios';\nimport axios from 'axios';\nimport type { ClientConfig } from '../config';\nimport { TimesheetApiError, TimesheetAuthError, TimesheetRateLimitError } from '../exceptions';\n\ninterface ErrorResponseData {\n message?: string;\n code?: string;\n}\n\n/**\n * HTTP client for making API requests.\n */\nexport class ApiClient {\n private readonly config: ClientConfig;\n private readonly httpClient: AxiosInstance;\n\n constructor(config: ClientConfig) {\n this.config = config;\n this.httpClient =\n config.httpClient ||\n axios.create({\n baseURL: config.baseUrl,\n timeout: 30000,\n headers: {\n 'User-Agent': 'Timesheet-TypeScript-SDK/1.1.0',\n 'Content-Type': 'application/json',\n },\n });\n\n // Request interceptor for authentication\n this.httpClient.interceptors.request.use(async (config) => {\n // Add authentication headers if configured\n if (config.url !== '/oauth/token' && this.config.authentication) {\n const authHeaders = await this.config.authentication.getAuthHeaders();\n if (authHeaders) {\n // Set headers directly to avoid type issues\n for (const [key, value] of Object.entries(authHeaders)) {\n config.headers.set(key, value);\n }\n }\n }\n\n return config;\n });\n }\n\n /**\n * Makes an HTTP request with retry support.\n */\n async request<T>(config: AxiosRequestConfig): Promise<T> {\n let lastError: Error | null = null;\n const retryConfig = this.config.retryConfig;\n\n for (let attempt = 0; attempt <= retryConfig.maxRetries; attempt++) {\n try {\n const response = await this.httpClient.request<T>(config);\n return response.data;\n } catch (error) {\n lastError = error as Error;\n\n // Handle authentication errors\n if (axios.isAxiosError<ErrorResponseData>(error) && error.response?.status === 401) {\n const errorData = error.response.data;\n throw new TimesheetAuthError(\n errorData?.message || 'Authentication failed',\n 401,\n JSON.stringify(errorData),\n );\n }\n\n // Handle rate limit errors\n if (axios.isAxiosError(error) && error.response?.status === 429) {\n const retryAfter = error.response.headers['retry-after'] as string | undefined;\n throw new TimesheetRateLimitError('Rate limit exceeded', retryAfter);\n }\n\n // Check if we should retry\n const status = axios.isAxiosError(error) ? error.response?.status : undefined;\n if (\n attempt < retryConfig.maxRetries &&\n status &&\n retryConfig.retryableStatusCodes.includes(status)\n ) {\n // Calculate delay with exponential backoff\n const delay = Math.min(\n retryConfig.initialDelay * Math.pow(retryConfig.backoffMultiplier, attempt),\n retryConfig.maxDelay,\n );\n\n await this.sleep(delay);\n continue;\n }\n\n // Non-retryable error\n if (axios.isAxiosError<ErrorResponseData>(error)) {\n const errorData = error.response?.data;\n throw new TimesheetApiError(\n errorData?.message || error.message,\n error.response?.status,\n JSON.stringify(errorData),\n errorData?.code,\n );\n } else if (error instanceof Error) {\n throw new TimesheetApiError(error.message);\n } else {\n throw new TimesheetApiError('Unknown error occurred');\n }\n }\n }\n\n // This should never happen, but TypeScript needs it\n throw lastError || new Error('Unknown error');\n }\n\n /**\n * GET request.\n */\n async get<T, P = Record<string, unknown>>(path: string, params?: P): Promise<T> {\n return this.request<T>({\n method: 'GET',\n url: path,\n params: params as Record<string, unknown>,\n });\n }\n\n /**\n * POST request.\n */\n async post<T, P = Record<string, unknown>>(path: string, data?: unknown, params?: P): Promise<T> {\n return this.request<T>({\n method: 'POST',\n url: path,\n data,\n params: params as Record<string, unknown>,\n });\n }\n\n /**\n * PUT request.\n */\n async put<T, P = Record<string, unknown>>(path: string, data?: unknown, params?: P): Promise<T> {\n return this.request<T>({\n method: 'PUT',\n url: path,\n data,\n params: params as Record<string, unknown>,\n });\n }\n\n /**\n * DELETE request. Supports an optional request body for endpoints that\n * accept a payload (e.g. batch deletions).\n */\n async delete<T, P = Record<string, unknown>>(\n path: string,\n params?: P,\n data?: unknown,\n ): Promise<T> {\n return this.request<T>({\n method: 'DELETE',\n url: path,\n data,\n params: params as Record<string, unknown>,\n });\n }\n\n /**\n * POST multipart/form-data request for file uploads.\n * @param path API endpoint path\n * @param formData FormData containing file and optional JSON data\n */\n async postMultipart<T>(path: string, formData: FormData): Promise<T> {\n return this.request<T>({\n method: 'POST',\n url: path,\n data: formData,\n headers: {\n 'Content-Type': 'multipart/form-data',\n },\n });\n }\n\n /**\n * Sleep for the specified number of milliseconds.\n */\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n /**\n * Get the base URL for the API.\n */\n getBaseUrl(): string {\n return this.config.baseUrl;\n }\n\n /**\n * Get authentication headers for SSE connections.\n * @returns Promise resolving to auth headers or undefined\n */\n async getAuthHeaders(): Promise<Record<string, string> | undefined> {\n if (this.config.authentication) {\n return this.config.authentication.getAuthHeaders();\n }\n return undefined;\n }\n}\n", "/**\n * Base exception for all Timesheet API errors.\n */\nexport class TimesheetApiError extends Error {\n public readonly statusCode?: number;\n public readonly responseBody?: string;\n public readonly errorCode?: string;\n\n /**\n * Creates a new TimesheetApiError.\n *\n * @param message The error message\n * @param statusCode Optional HTTP status code\n * @param responseBody Optional response body\n * @param errorCode Optional API error code\n */\n constructor(message: string, statusCode?: number, responseBody?: string, errorCode?: string) {\n const fullMessage = statusCode\n ? errorCode\n ? `${message} (HTTP ${statusCode}, Code: ${errorCode})`\n : `${message} (HTTP ${statusCode})`\n : message;\n\n super(fullMessage);\n\n this.name = 'TimesheetApiError';\n this.statusCode = statusCode;\n this.responseBody = responseBody;\n this.errorCode = errorCode;\n\n // Maintains proper stack trace for where our error was thrown\n if (typeof Error.captureStackTrace === 'function') {\n Error.captureStackTrace(this, TimesheetApiError);\n }\n }\n}\n", "import { TimesheetApiError } from './TimesheetApiError';\n\n/**\n * Exception thrown when authentication fails.\n */\nexport class TimesheetAuthError extends TimesheetApiError {\n /**\n * Creates a new authentication exception.\n *\n * @param message The error message\n * @param statusCode The HTTP status code (usually 401)\n * @param responseBody The response body\n */\n constructor(message: string, statusCode: number = 401, responseBody?: string) {\n super(message, statusCode, responseBody, 'authentication_error');\n this.name = 'TimesheetAuthError';\n }\n}\n", "import { TimesheetApiError } from './TimesheetApiError';\n\n/**\n * Exception thrown when rate limit is exceeded.\n */\nexport class TimesheetRateLimitError extends TimesheetApiError {\n public readonly retryAfter?: string;\n\n /**\n * Creates a new rate limit exception.\n *\n * @param message The error message\n * @param retryAfter The retry-after header value\n */\n constructor(message: string, retryAfter?: string) {\n super(message, 429, undefined, 'rate_limit_exceeded');\n this.name = 'TimesheetRateLimitError';\n this.retryAfter = retryAfter;\n }\n\n /**\n * Parses the retry-after value as a Date.\n *\n * @returns The retry-after time as a Date, or null if parsing fails\n */\n getRetryAfterDate(): Date | null {\n if (!this.retryAfter) {\n return null;\n }\n\n // Try to parse as epoch seconds\n const epochSeconds = Number(this.retryAfter);\n if (!isNaN(epochSeconds)) {\n return new Date(epochSeconds * 1000);\n }\n\n // Try to parse as ISO string\n const date = new Date(this.retryAfter);\n if (!isNaN(date.getTime())) {\n return date;\n }\n\n return null;\n }\n}\n", "import type { AxiosRequestConfig } from 'axios';\nimport type { Authentication } from './Authentication';\n\n/**\n * API Key authentication implementation.\n *\n * Uses the ApiKey scheme in the Authorization header.\n * Format: `Authorization: ApiKey {api_key}`\n */\nexport class ApiKeyAuth implements Authentication {\n constructor(private readonly apiKey: string) {\n if (apiKey === null) {\n throw new Error('API key cannot be null');\n }\n if (apiKey === undefined) {\n throw new Error('API key cannot be undefined');\n }\n if (!apiKey) {\n throw new Error('API key cannot be empty');\n }\n if (typeof apiKey !== 'string') {\n throw new Error('API key must be a string');\n }\n if (apiKey.trim().length === 0) {\n throw new Error('API key cannot be empty or whitespace');\n }\n\n // Validate API key format: should be ts_{prefix}.{secret}\n if (!this.isValidFormat(apiKey)) {\n throw new Error('Invalid API key format');\n }\n }\n\n private isValidFormat(apiKey: string): boolean {\n // API key format: ts_{prefix}.{secret}\n const apiKeyPattern = /^ts_[a-zA-Z0-9]+\\.[a-zA-Z0-9]+$/;\n return apiKeyPattern.test(apiKey);\n }\n\n applyAuth(config: AxiosRequestConfig): void {\n if (!config.headers) {\n config.headers = {};\n }\n config.headers['Authorization'] = `ApiKey ${this.apiKey}`;\n }\n\n needsRefresh(): boolean {\n // API keys don't need refresh\n return false;\n }\n\n // eslint-disable-next-line @typescript-eslint/require-await\n async refresh(): Promise<void> {\n throw new Error('API keys cannot be refreshed');\n }\n\n // eslint-disable-next-line @typescript-eslint/require-await\n async getAuthHeaders(): Promise<Record<string, string>> {\n return {\n Authorization: `ApiKey ${this.apiKey}`,\n };\n }\n\n isValid(): boolean {\n return (\n typeof this.apiKey === 'string' &&\n this.apiKey.trim().length > 0 &&\n this.isValidFormat(this.apiKey)\n );\n }\n}\n", "import type { AxiosRequestConfig } from 'axios';\nimport axios from 'axios';\nimport jwt from 'jsonwebtoken';\nimport type { Authentication } from './Authentication';\n\n/**\n * OAuth2 authentication implementation with automatic token refresh.\n *\n * Supports both simple bearer token authentication and full OAuth2 flow with refresh tokens.\n */\nexport class OAuth2Auth implements Authentication {\n private static readonly TOKEN_ENDPOINT = 'https://api.timesheet.io/oauth2/token';\n\n private accessToken: string;\n private refreshToken?: string;\n private readonly clientId?: string;\n private readonly clientSecret?: string;\n private tokenExpiry?: Date;\n private refreshPromise?: Promise<void>;\n\n /**\n * Creates OAuth2 authentication with a simple bearer token.\n *\n * @param accessToken The OAuth2 access token\n */\n constructor(accessToken: string);\n\n /**\n * Creates OAuth2 authentication with refresh capability.\n *\n * @param clientId The OAuth2 client ID\n * @param clientSecret The OAuth2 client secret\n * @param refreshToken The OAuth2 refresh token\n */\n constructor(clientId: string, clientSecret: string, refreshToken: string);\n\n constructor(accessTokenOrClientId: string, clientSecret?: string, refreshToken?: string) {\n if (clientSecret && refreshToken) {\n // OAuth2 with refresh\n this.clientId = accessTokenOrClientId;\n this.clientSecret = clientSecret;\n this.refreshToken = refreshToken;\n this.accessToken = ''; // Will be set by refresh()\n // Don't call refresh here - let it happen lazily when needed\n } else {\n // Simple bearer token\n this.accessToken = accessTokenOrClientId;\n this.parseTokenExpiry();\n }\n }\n\n applyAuth(config: AxiosRequestConfig): void {\n if (!config.headers) {\n config.headers = {};\n }\n config.headers['Authorization'] = `Bearer ${this.accessToken}`;\n }\n\n needsRefresh(): boolean {\n // If we have refresh capabilities but no access token, we need to refresh\n if (this.refreshToken && !this.accessToken) {\n return true;\n }\n\n if (!this.refreshToken || !this.tokenExpiry) {\n return false;\n }\n // Refresh if token expires in less than 5 minutes\n const fiveMinutesFromNow = new Date(Date.now() + 5 * 60 * 1000);\n return fiveMinutesFromNow >= this.tokenExpiry;\n }\n\n async refresh(): Promise<void> {\n if (!this.refreshToken) {\n throw new Error('Cannot refresh without refresh token');\n }\n\n // Prevent multiple concurrent refresh attempts\n if (this.refreshPromise) {\n return this.refreshPromise;\n }\n\n this.refreshPromise = this.performRefresh();\n try {\n await this.refreshPromise;\n } finally {\n this.refreshPromise = undefined;\n }\n }\n\n private async performRefresh(): Promise<void> {\n interface TokenResponse {\n access_token: string;\n refresh_token?: string;\n token_type?: string;\n expires_in?: number;\n }\n\n try {\n const response = await axios.post<TokenResponse>(\n OAuth2Auth.TOKEN_ENDPOINT,\n new URLSearchParams({\n grant_type: 'refresh_token',\n refresh_token: this.refreshToken!,\n client_id: this.clientId!,\n client_secret: this.clientSecret!,\n }),\n {\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n },\n );\n\n this.accessToken = response.data.access_token;\n\n if (response.data.refresh_token) {\n this.refreshToken = response.data.refresh_token;\n }\n\n this.parseTokenExpiry();\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n throw new Error(`Failed to refresh OAuth2 token: ${message}`);\n }\n }\n\n async getAuthHeaders(): Promise<Record<string, string>> {\n // Ensure we have a valid token before returning headers\n if (this.needsRefresh()) {\n await this.refresh();\n }\n\n return {\n Authorization: `Bearer ${this.accessToken}`,\n };\n }\n\n /**\n * Performs the OAuth2 authorization code flow.\n *\n * @param clientId The OAuth2 client ID\n * @param clientSecret The OAuth2 client secret\n * @param authorizationCode The authorization code from the OAuth2 flow\n * @param redirectUri The redirect URI used in the authorization request\n * @returns A new OAuth2Auth instance with the obtained tokens\n */\n static async fromAuthorizationCode(\n clientId: string,\n clientSecret: string,\n authorizationCode: string,\n redirectUri: string,\n ): Promise<OAuth2Auth> {\n interface TokenResponse {\n access_token: string;\n refresh_token?: string;\n token_type?: string;\n expires_in?: number;\n }\n\n try {\n const response = await axios.post<TokenResponse>(\n OAuth2Auth.TOKEN_ENDPOINT,\n new URLSearchParams({\n grant_type: 'authorization_code',\n code: authorizationCode,\n redirect_uri: redirectUri,\n client_id: clientId,\n client_secret: clientSecret,\n }),\n {\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n },\n );\n\n const accessToken = response.data.access_token;\n const refreshToken = response.data.refresh_token;\n\n if (refreshToken) {\n return new OAuth2Auth(clientId, clientSecret, refreshToken);\n } else {\n return new OAuth2Auth(accessToken);\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n throw new Error(`Failed to exchange authorization code: ${message}`);\n }\n }\n\n /**\n * Builds the OAuth2 authorization URL.\n *\n * @param clientId The OAuth2 client ID\n * @param redirectUri The redirect URI for the OAuth2 flow\n * @param state Optional state parameter for CSRF protection\n * @returns The authorization URL\n */\n static buildAuthorizationUrl(clientId: string, redirectUri: string, state?: string): string {\n const params = new URLSearchParams({\n client_id: clientId,\n redirect_uri: redirectUri,\n response_type: 'code',\n });\n\n if (state) {\n params.append('state', state);\n }\n\n return `https://api.timesheet.io/oauth2/auth?${params.toString()}`;\n }\n\n private parseTokenExpiry(): void {\n interface JWTPayload {\n exp?: number;\n iat?: number;\n sub?: string;\n [key: string]: unknown;\n }\n\n try {\n const decoded = jwt.decode(this.accessToken) as JWTPayload | null;\n if (decoded && decoded.exp) {\n this.tokenExpiry = new Date(decoded.exp * 1000);\n }\n } catch {\n // If we can't parse the JWT, assume it expires in 1 hour\n this.tokenExpiry = new Date(Date.now() + 60 * 60 * 1000);\n }\n }\n}\n", "import type { AxiosRequestConfig } from 'axios';\nimport axios from 'axios';\nimport jwt from 'jsonwebtoken';\nimport type { Authentication } from './Authentication';\nimport {\n generatePkceCodePair,\n isValidCodeVerifier,\n type CodeChallengeMethod,\n type PkceCodePair,\n} from './pkce';\n\n/**\n * Options for building an OAuth 2.1 authorization URL.\n */\nexport interface AuthorizationUrlOptions {\n /** The OAuth2 client ID */\n clientId: string;\n /** The redirect URI for the OAuth2 flow */\n redirectUri: string;\n /** The PKCE code challenge (required for OAuth 2.1) */\n codeChallenge: string;\n /** The code challenge method (default: 'S256') */\n codeChallengeMethod?: CodeChallengeMethod;\n /** Optional state parameter for CSRF protection */\n state?: string;\n /** Optional scope parameter */\n scope?: string;\n /** Optional resource indicator (RFC 8707) */\n resource?: string;\n /** Custom authorization endpoint URL (overrides default) */\n authorizationEndpoint?: string;\n}\n\n/**\n * Options for exchanging an authorization code for tokens.\n */\nexport interface TokenExchangeOptions {\n /** The OAuth2 client ID */\n clientId: string;\n /** The OAuth2 client secret (optional for public clients with PKCE) */\n clientSecret?: string;\n /** The authorization code from the OAuth2 flow */\n authorizationCode: string;\n /** The redirect URI used in the authorization request */\n redirectUri: string;\n /** The PKCE code verifier (required for OAuth 2.1) */\n codeVerifier: string;\n /** Optional resource indicator (RFC 8707) */\n resource?: string;\n /** Custom token endpoint URL (overrides default) */\n tokenEndpoint?: string;\n}\n\n/**\n * Options for creating OAuth21Auth with refresh capability.\n */\nexport interface OAuth21RefreshOptions {\n /** The OAuth2 client ID */\n clientId: string;\n /** The OAuth2 client secret (optional for public clients) */\n clientSecret?: string;\n /** The OAuth2 refresh token */\n refreshToken: string;\n /** Optional resource indicator (RFC 8707) */\n resource?: string;\n /** Custom token endpoint URL (overrides default) */\n tokenEndpoint?: string;\n}\n\n/**\n * Token response from the OAuth 2.1 server.\n */\ninterface TokenResponse {\n access_token: string;\n refresh_token?: string;\n token_type?: string;\n expires_in?: number;\n scope?: string;\n}\n\n/**\n * OAuth 2.1 authentication implementation with PKCE support.\n *\n * OAuth 2.1 is the next evolution of OAuth 2.0, consolidating best practices:\n * - PKCE is REQUIRED for all clients (not just public clients)\n * - Implicit flow is removed\n * - Resource Owner Password Credentials grant is removed\n *\n * This implementation supports:\n * - Authorization code flow with PKCE (S256)\n * - Refresh token flow\n * - Automatic token refresh\n * - Resource indicators (RFC 8707)\n *\n * @example\n * ```typescript\n * // Step 1: Generate PKCE parameters\n * import { generatePkceCodePair } from '@timesheet/sdk';\n * const pkce = generatePkceCodePair();\n *\n * // Step 2: Build authorization URL and redirect user\n * const authUrl = OAuth21Auth.buildAuthorizationUrl({\n * clientId: 'your-client-id',\n * redirectUri: 'https://your-app.com/callback',\n * codeChallenge: pkce.codeChallenge,\n * codeChallengeMethod: pkce.codeChallengeMethod,\n * state: 'random-state-for-csrf',\n * });\n *\n * // Step 3: After user authorizes, exchange code for tokens\n * const auth = await OAuth21Auth.fromAuthorizationCode({\n * clientId: 'your-client-id',\n * authorizationCode: codeFromCallback,\n * redirectUri: 'https://your-app.com/callback',\n * codeVerifier: pkce.codeVerifier,\n * });\n *\n * // Step 4: Use with TimesheetClient\n * const client = new TimesheetClient({ auth });\n * ```\n */\nexport class OAuth21Auth implements Authentication {\n private static readonly DEFAULT_TOKEN_ENDPOINT = 'https://api.timesheet.io/oauth2/token';\n private static readonly DEFAULT_AUTH_ENDPOINT = 'https://api.timesheet.io/oauth2/auth';\n\n private accessToken: string;\n private refreshToken?: string;\n private readonly clientId?: string;\n private readonly clientSecret?: string;\n private readonly resource?: string;\n private readonly tokenEndpoint: string;\n private tokenExpiry?: Date;\n private refreshPromise?: Promise<void>;\n\n /**\n * Creates OAuth 2.1 authentication with a simple bearer token.\n * Use this when you already have an access token.\n *\n * @param accessToken The OAuth2 access token\n */\n constructor(accessToken: string);\n\n /**\n * Creates OAuth 2.1 authentication with refresh capability.\n *\n * @param options The refresh options including clientId, refreshToken, etc.\n */\n constructor(options: OAuth21RefreshOptions);\n\n constructor(accessTokenOrOptions: string | OAuth21RefreshOptions) {\n if (typeof accessTokenOrOptions === 'string') {\n // Simple bearer token\n this.accessToken = accessTokenOrOptions;\n this.tokenEndpoint = OAuth21Auth.DEFAULT_TOKEN_ENDPOINT;\n this.parseTokenExpiry();\n } else {\n // OAuth 2.1 with refresh\n const options = accessTokenOrOptions;\n this.clientId = options.clientId;\n this.clientSecret = options.clientSecret;\n this.refreshToken = options.refreshToken;\n this.resource = options.resource;\n this.tokenEndpoint = options.tokenEndpoint ?? OAuth21Auth.DEFAULT_TOKEN_ENDPOINT;\n this.accessToken = ''; // Will be set by refresh()\n }\n }\n\n applyAuth(config: AxiosRequestConfig): void {\n if (!config.headers) {\n config.headers = {};\n }\n config.headers['Authorization'] = `Bearer ${this.accessToken}`;\n }\n\n needsRefresh(): boolean {\n // If we have refresh capabilities but no access token, we need to refresh\n if (this.refreshToken && !this.accessToken) {\n return true;\n }\n\n if (!this.refreshToken || !this.tokenExpiry) {\n return false;\n }\n // Refresh if token expires in less than 5 minutes\n const fiveMinutesFromNow = new Date(Date.now() + 5 * 60 * 1000);\n return fiveMinutesFromNow >= this.tokenExpiry;\n }\n\n async refresh(): Promise<void> {\n if (!this.refreshToken) {\n throw new Error('Cannot refresh without refresh token');\n }\n\n // Prevent multiple concurrent refresh attempts\n if (this.refreshPromise) {\n return this.refreshPromise;\n }\n\n this.refreshPromise = this.performRefresh();\n try {\n await this.refreshPromise;\n } finally {\n this.refreshPromise = undefined;\n }\n }\n\n private async performRefresh(): Promise<void> {\n try {\n const params = new URLSearchParams({\n grant_type: 'refresh_token',\n refresh_token: this.refreshToken!,\n client_id: this.clientId!,\n });\n\n // Client secret is optional for public clients using PKCE\n if (this.clientSecret) {\n params.append('client_secret', this.clientSecret);\n }\n\n // Include resource indicator if specified\n if (this.resource) {\n params.append('resource', this.resource);\n }\n\n const response = await axios.post<TokenResponse>(this.tokenEndpoint, params, {\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n });\n\n this.accessToken = response.data.access_token;\n\n if (response.data.refresh_token) {\n this.refreshToken = response.data.refresh_token;\n }\n\n this.parseTokenExpiry();\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n throw new Error(`Failed to refresh OAuth 2.1 token: ${message}`);\n }\n }\n\n async getAuthHeaders(): Promise<Record<string, string>> {\n // Ensure we have a valid token before returning headers\n if (this.needsRefresh()) {\n await this.refresh();\n }\n\n return {\n Authorization: `Bearer ${this.accessToken}`,\n };\n }\n\n /**\n * Performs the OAuth 2.1 authorization code flow with PKCE.\n *\n * @param options The token exchange options\n * @returns A new OAuth21Auth instance with the obtained tokens\n * @throws Error if the code verifier is invalid or token exchange fails\n */\n static async fromAuthorizationCode(options: TokenExchangeOptions): Promise<OAuth21Auth> {\n const {\n clientId,\n clientSecret,\n authorizationCode,\n redirectUri,\n codeVerifier,\n resource,\n tokenEndpoint,\n } = options;\n\n const effectiveTokenEndpoint = tokenEndpoint ?? OAuth21Auth.DEFAULT_TOKEN_ENDPOINT;\n\n // Validate code verifier\n if (!isValidCodeVerifier(codeVerifier)) {\n throw new Error(\n 'Invalid code verifier: must be 43-128 characters using only A-Z, a-z, 0-9, -, ., _, ~',\n );\n }\n\n try {\n const params = new URLSearchParams({\n grant_type: 'authorization_code',\n code: authorizationCode,\n redirect_uri: redirectUri,\n client_id: clientId,\n code_verifier: codeVerifier,\n });\n\n // Client secret is optional for public clients using PKCE\n if (clientSecret) {\n params.append('client_secret', clientSecret);\n }\n\n // Include resource indicator if specified\n if (resource) {\n params.append('resource', resource);\n }\n\n const response = await axios.post<TokenResponse>(effectiveTokenEndpoint, params, {\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n });\n\n const accessToken = response.data.access_token;\n const refreshToken = response.data.refresh_token;\n\n if (refreshToken) {\n return new OAuth21Auth({\n clientId,\n clientSecret,\n refreshToken,\n resource,\n tokenEndpoint: effectiveTokenEndpoint,\n });\n } else {\n return new OAuth21Auth(accessToken);\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n throw new Error(`Failed to exchange authorization code: ${message}`);\n }\n }\n\n /**\n * Builds the OAuth 2.1 authorization URL with PKCE.\n *\n * @param options The authorization URL options\n * @returns The authorization URL\n */\n static buildAuthorizationUrl(options: AuthorizationUrlOptions): string {\n const {\n clientId,\n redirectUri,\n codeChallenge,\n codeChallengeMethod = 'S256',\n state,\n scope,\n resource,\n authorizationEndpoint,\n } = options;\n\n const effectiveAuthEndpoint = authorizationEndpoint ?? OAuth21Auth.DEFAULT_AUTH_ENDPOINT;\n\n const params = new URLSearchParams({\n response_type: 'code',\n client_id: clientId,\n redirect_uri: redirectUri,\n code_challenge: codeChallenge,\n code_challenge_method: codeChallengeMethod,\n });\n\n if (state) {\n params.append('state', state);\n }\n\n if (scope) {\n params.append('scope', scope);\n }\n\n if (resource) {\n params.append('resource', resource);\n }\n\n return `${effectiveAuthEndpoint}?${params.toString()}`;\n }\n\n /**\n * Generates a complete PKCE code pair for use in OAuth 2.1 flow.\n *\n * This is a convenience method that wraps the generatePkceCodePair function.\n *\n * @param method The challenge method ('S256' or 'plain', default: 'S256')\n * @returns A PKCE code pair with verifier, challenge, and method\n *\n * @example\n * ```typescript\n * const pkce = OAuth21Auth.generatePkce();\n *\n * // Store verifier securely (e.g., in session)\n * sessionStorage.setItem('pkce_verifier', pkce.codeVerifier);\n *\n * // Use challenge in authorization URL\n * const authUrl = OAuth21Auth.buildAuthorizationUrl({\n * clientId: 'your-client-id',\n * redirectUri: 'https://your-app.com/callback',\n * codeChallenge: pkce.codeChallenge,\n * codeChallengeMethod: pkce.codeChallengeMethod,\n * });\n * ```\n */\n static generatePkce(method: CodeChallengeMethod = 'S256'): PkceCodePair {\n return generatePkceCodePair(method);\n }\n\n private parseTokenExpiry(): void {\n interface JWTPayload {\n exp?: number;\n iat?: number;\n sub?: string;\n [key: string]: unknown;\n }\n\n try {\n const decoded = jwt.decode(this.accessToken) as JWTPayload | null;\n if (decoded && decoded.exp) {\n this.tokenExpiry = new Date(decoded.exp * 1000);\n }\n } catch {\n // If we can't parse the JWT, assume it expires in 1 hour\n this.tokenExpiry = new Date(Date.now() + 60 * 60 * 1000);\n }\n }\n}\n", "import { randomBytes, createHash } from 'crypto';\n\n/**\n * PKCE (Proof Key for Code Exchange) utilities for OAuth 2.1.\n *\n * Implements RFC 7636 with S256 challenge method as required by OAuth 2.1.\n */\n\n/**\n * Supported PKCE code challenge methods.\n * OAuth 2.1 requires S256 - plain is only for legacy compatibility.\n */\nexport type CodeChallengeMethod = 'S256' | 'plain';\n\n/**\n * PKCE code pair containing verifier and challenge.\n */\nexport interface PkceCodePair {\n /** The code verifier - a cryptographically random string (43-128 chars) */\n codeVerifier: string;\n /** The code challenge - derived from the verifier using the challenge method */\n codeChallenge: string;\n /** The challenge method used (S256 or plain) */\n codeChallengeMethod: CodeChallengeMethod;\n}\n\n/**\n * Generates a cryptographically random code verifier.\n *\n * The verifier is a high-entropy random string between 43-128 characters\n * using unreserved URI characters (A-Z, a-z, 0-9, -, ., _, ~).\n *\n * @param length The length of the verifier (default: 64, min: 43, max: 128)\n * @returns A random code verifier string\n */\nexport function generateCodeVerifier(length: number = 64): string {\n if (length < 43 || length > 128) {\n throw new Error('Code verifier length must be between 43 and 128 characters');\n }\n\n // Generate random bytes and encode as base64url\n const buffer = randomBytes(Math.ceil((length * 3) / 4));\n return base64UrlEncode(buffer).slice(0, length);\n}\n\n/**\n * Generates a code challenge from a code verifier.\n *\n * For S256 (recommended by OAuth 2.1):\n * code_challenge = BASE64URL(SHA256(code_verifier))\n *\n * For plain (legacy, not recommended):\n * code_challenge = code_verifier\n *\n * @param codeVerifier The code verifier string\n * @param method The challenge method ('S256' or 'plain', default: 'S256')\n * @returns The code challenge string\n */\nexport function generateCodeChallenge(\n codeVerifier: string,\n method: CodeChallengeMethod = 'S256',\n): string {\n if (method === 'plain') {\n return codeVerifier;\n }\n\n // S256: BASE64URL(SHA256(ASCII(code_verifier)))\n const hash = createHash('sha256').update(codeVerifier, 'ascii').digest();\n return base64UrlEncode(hash);\n}\n\n/**\n * Generates a complete PKCE code pair (verifier and challenge).\n *\n * This is the recommended way to generate PKCE parameters for OAuth 2.1.\n *\n * @param method The challenge method ('S256' or 'plain', default: 'S256')\n * @param verifierLength The length of the verifier (default: 64)\n * @returns A complete PKCE code pair\n *\n * @example\n * ```typescript\n * const pkce = generatePkceCodePair();\n *\n * // Use codeChallenge in authorization request\n * const authUrl = OAuth21Auth.buildAuthorizationUrl({\n * clientId: 'your-client-id',\n * redirectUri: 'https://your-app.com/callback',\n * codeChallenge: pkce.codeChallenge,\n * codeChallengeMethod: pkce.codeChallengeMethod,\n * });\n *\n * // Later, use codeVerifier in token exchange\n * const auth = await OAuth21Auth.fromAuthorizationCode({\n * clientId: 'your-client-id',\n * authorizationCode: code,\n * redirectUri: 'https://your-app.com/callback',\n * codeVerifier: pkce.codeVerifier,\n * });\n * ```\n */\nexport function generatePkceCodePair(\n method: CodeChallengeMethod = 'S256',\n verifierLength: number = 64,\n): PkceCodePair {\n const codeVerifier = generateCodeVerifier(verifierLength);\n const codeChallenge = generateCodeChallenge(codeVerifier, method);\n\n return {\n codeVerifier,\n codeChallenge,\n codeChallengeMethod: method,\n };\n}\n\n/**\n * Validates a code verifier format.\n *\n * @param codeVerifier The code verifier to validate\n * @returns True if valid, false otherwise\n */\nexport function isValidCodeVerifier(codeVerifier: string): boolean {\n if (codeVerifier.length < 43 || codeVerifier.length > 128) {\n return false;\n }\n\n // Must only contain unreserved characters: A-Z, a-z, 0-9, -, ., _, ~\n const validChars = /^[A-Za-z0-9\\-._~]+$/;\n return validChars.test(codeVerifier);\n}\n\n/**\n * Base64URL encodes a buffer (RFC 4648 Section 5).\n *\n * @param buffer The buffer to encode\n * @returns Base64URL encoded string (no padding)\n */\nfunction base64UrlEncode(buffer: Buffer): string {\n return buffer.toString('base64').replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n", "import axios from 'axios';\nimport type {\n AuthorizationServerMetadata,\n OpenIdConfiguration,\n ProtectedResourceMetadata,\n OAuthDiscoveryResult,\n} from './OAuthMetadata';\n\n/**\n * Options for OAuth discovery\n */\nexport interface OAuthDiscoveryOptions {\n /** Cache TTL in milliseconds (default: 1 hour) */\n cacheTtl?: number;\n\n /** Request timeout in milliseconds (default: 10000) */\n timeout?: number;\n\n /** Whether to also fetch OpenID configuration (default: false) */\n fetchOpenIdConfig?: boolean;\n\n /** Whether to also fetch protected resource metadata (default: false) */\n fetchProtectedResource?: boolean;\n}\n\n/**\n * Cached metadata entry\n */\ninterface CacheEntry {\n result: OAuthDiscoveryResult;\n expiresAt: Date;\n}\n\n/**\n * OAuth 2.1 Discovery Service\n *\n * Implements RFC 8414 (OAuth 2.0 Authorization Server Metadata) for automatic\n * discovery of OAuth endpoints from well-known URLs.\n *\n * Supports:\n * - /.well-known/oauth-authorization-server (RFC 8414)\n * - /.well-known/oauth-protected-resource (RFC 9728)\n * - /.well-known/openid-configuration (OpenID Connect Discovery)\n *\n * @example\n * ```typescript\n * // Discover OAuth endpoints from issuer URL\n * const discovery = new OAuthDiscovery();\n * const metadata = await discovery.discover('https://api.timesheet.io');\n *\n * console.log(metadata.authorizationServer.authorization_endpoint);\n * console.log(metadata.authorizationServer.token_endpoint);\n * ```\n */\nexport class OAuthDiscovery {\n private static readonly DEFAULT_CACHE_TTL = 60 * 60 * 1000; // 1 hour\n private static readonly DEFAULT_TIMEOUT = 10000; // 10 seconds\n\n private readonly cache: Map<string, CacheEntry> = new Map();\n private readonly options: Required<OAuthDiscoveryOptions>;\n\n constructor(options: OAuthDiscoveryOptions = {}) {\n this.options = {\n cacheTtl: options.cacheTtl ?? OAuthDiscovery.DEFAULT_CACHE_TTL,\n timeout: options.timeout ?? OAuthDiscovery.DEFAULT_TIMEOUT,\n fetchOpenIdConfig: options.fetchOpenIdConfig ?? false,\n fetchProtectedResource: options.fetchProtectedResource ?? false,\n };\n }\n\n /**\n * Discover OAuth metadata from an issuer URL.\n *\n * @param issuerUrl The OAuth authorization server issuer URL\n * @returns Discovery result containing all fetched metadata\n * @throws Error if discovery fails\n *\n * @example\n * ```typescript\n * const discovery = new OAuthDiscovery();\n * const result = await discovery.discover('https://api.timesheet.io');\n *\n * // Use discovered endpoints\n * const authUrl = result.authorizationServer.authorization_endpoint;\n * const tokenUrl = result.authorizationServer.token_endpoint;\n * ```\n */\n async discover(issuerUrl: string): Promise<OAuthDiscoveryResult> {\n const normalizedUrl = this.normalizeIssuerUrl(issuerUrl);\n\n // Check cache first\n const cached = this.getCached(normalizedUrl);\n if (cached) {\n return cached;\n }\n\n // Fetch authorization server metadata (required)\n const authServerMetadata = await this.fetchAuthorizationServerMetadata(normalizedUrl);\n\n const result: OAuthDiscoveryResult = {\n issuer: authServerMetadata.issuer,\n authorizationServer: authServerMetadata,\n fetchedAt: new Date(),\n };\n\n // Optionally fetch OpenID configuration\n if (this.options.fetchOpenIdConfig) {\n try {\n result.openIdConfiguration = await this.fetchOpenIdConfiguration(normalizedUrl);\n } catch {\n // OpenID configuration is optional, continue without it\n }\n }\n\n // Optionally fetch protected resource metadata\n if (this.options.fetchProtectedResource) {\n try {\n result.protectedResource = await this.fetchProtectedResourceMetadata(normalizedUrl);\n } catch {\n // Protected resource metadata is optional, continue without it\n }\n }\n\n // Cache the result\n this.setCache(normalizedUrl, result);\n\n return result;\n }\n\n /**\n * Fetch Authorization Server Metadata (RFC 8414)\n *\n * @param issuerUrl The OAuth authorization server issuer URL\n * @returns Authorization server metadata\n */\n async fetchAuthorizationServerMetadata(issuerUrl: string): Promise<AuthorizationServerMetadata> {\n const url = `${this.normalizeIssuerUrl(issuerUrl)}/.well-known/oauth-authorization-server`;\n\n try {\n const response = await axios.get<AuthorizationServerMetadata>(url, {\n timeout: this.options.timeout,\n headers: {\n Accept: 'application/json',\n },\n });\n\n this.validateAuthorizationServerMetadata(response.data);\n return response.data;\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n throw new Error(`Failed to fetch authorization server metadata from ${url}: ${message}`);\n }\n }\n\n /**\n * Fetch OpenID Connect Discovery Configuration\n *\n * @param issuerUrl The OpenID Provider issuer URL\n * @returns OpenID Connect configuration\n */\n async fetchOpenIdConfiguration(issuerUrl: string): Promise<OpenIdConfiguration> {\n const url = `${this.normalizeIssuerUrl(issuerUrl)}/.well-known/openid-configuration`;\n\n try {\n const response = await axios.get<OpenIdConfiguration>(url, {\n timeout: this.options.timeout,\n headers: {\n Accept: 'application/json',\n },\n });\n\n this.validateOpenIdConfiguration(response.data);\n return response.data;\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n throw new Error(`Failed to fetch OpenID configuration from ${url}: ${message}`);\n }\n }\n\n /**\n * Fetch Protected Resource Metadata (RFC 9728)\n *\n * @param resourceUrl The protected resource URL\n * @returns Protected resource metadata\n */\n async fetchProtectedResourceMetadata(resourceUrl: string): Promise<ProtectedResourceMetadata> {\n const url = `${this.normalizeIssuerUrl(resourceUrl)}/.well-known/oauth-protected-resource`;\n\n try {\n const response = await axios.get<ProtectedResourceMetadata>(url, {\n timeout: this.options.timeout,\n headers: {\n Accept: 'application/json',\n },\n });\n\n this.validateProtectedResourceMetadata(response.data);\n return response.data;\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n throw new Error(`Failed to fetch protected resource metadata from ${url}: ${message}`);\n }\n }\n\n /**\n * Clear the metadata cache\n */\n clearCache(): void {\n this.cache.clear();\n }\n\n /**\n * Clear a specific issuer from the cache\n */\n clearCacheForIssuer(issuerUrl: string): void {\n this.cache.delete(this.normalizeIssuerUrl(issuerUrl));\n }\n\n /**\n * Check if a specific issuer's metadata is cached\n */\n isCached(issuerUrl: string): boolean {\n const cached = this.getCached(this.normalizeIssuerUrl(issuerUrl));\n return cached !== null;\n }\n\n private normalizeIssuerUrl(url: string): string {\n // Remove trailing slash\n return url.replace(/\\/+$/, '');\n }\n\n private getCached(issuerUrl: string): OAuthDiscoveryResult | null {\n const entry = this.cache.get(issuerUrl);\n if (!entry) {\n return null;\n }\n\n if (new Date() >= entry.expiresAt) {\n this.cache.delete(issuerUrl);\n return null;\n }\n\n return entry.result;\n }\n\n private setCache(issuerUrl: string, result: OAuthDiscoveryResult): void {\n const expiresAt = new Date(Date.now() + this.options.cacheTtl);\n this.cache.set(issuerUrl, { result, expiresAt });\n }\n\n private validateAuthorizationServerMetadata(metadata: AuthorizationServerMetadata): void {\n if (!metadata.issuer) {\n throw new Error('Authorization server metadata missing required field: issuer');\n }\n if (!metadata.authorization_endpoint) {\n throw new Error(\n 'Authorization server metadata missing required field: authorization_endpoint',\n );\n }\n if (!metadata.token_endpoint) {\n throw new Error('Authorization server metadata missing required field: token_endpoint');\n }\n if (!metadata.response_types_supported || metadata.response_types_supported.length === 0) {\n throw new Error(\n 'Authorization server metadata missing required field: response_types_supported',\n );\n }\n }\n\n private validateOpenIdConfiguration(config: OpenIdConfiguration): void {\n if (!config.issuer) {\n throw new Error('OpenID configuration missing required field: issuer');\n }\n if (!config.authorization_endpoint) {\n throw new Error('OpenID configuration missing required field: authorization_endpoint');\n }\n if (!config.token_endpoint) {\n throw new Error('OpenID configuration missing required field: token_endpoint');\n }\n if (!config.jwks_uri) {\n throw new Error('OpenID configuration missing required field: jwks_uri');\n }\n }\n\n private validateProtectedResourceMetadata(metadata: ProtectedResourceMetadata): void {\n if (!metadata.resource) {\n throw new Error('Protected resource metadata missing required field: resource');\n }\n if (!metadata.authorization_servers || metadata.authorization_servers.length === 0) {\n throw new Error('Protected resource metadata missing required field: authorization_servers');\n }\n }\n}\n\n/**\n * Singleton instance for convenience\n */\nlet defaultDiscovery: OAuthDiscovery | null = null;\n\n/**\n * Get the default OAuthDiscovery instance\n */\nexport function getDefaultDiscovery(): OAuthDiscovery {\n if (!defaultDiscovery) {\n defaultDiscovery = new OAuthDiscovery();\n }\n return defaultDiscovery;\n}\n\n/**\n * Convenience function to discover OAuth metadata\n *\n * @param issuerUrl The OAuth authorization server issuer URL\n * @param options Discovery options\n * @returns Discovery result\n *\n * @example\n * ```typescript\n * import { discoverOAuth } from '@timesheet/sdk';\n *\n * const metadata = await discoverOAuth('https://api.timesheet.io');\n * console.log(metadata.authorizationServer.token_endpoint);\n * ```\n */\nexport async function discoverOAuth(\n issuerUrl: string,\n options?: OAuthDiscoveryOptions,\n): Promise<OAuthDiscoveryResult> {\n const discovery = options ? new OAuthDiscovery(options) : getDefaultDiscovery();\n return discovery.discover(issuerUrl);\n}\n", "/**\n * Configuration for automatic retry behavior.\n */\nexport class RetryConfig {\n public readonly maxRetries: number;\n public readonly initialDelay: number;\n public readonly maxDelay: number;\n public readonly backoffMultiplier: number;\n public readonly retryableStatusCodes: number[];\n\n constructor(options: Partial<RetryConfigOptions> = {}) {\n this.maxRetries = options.maxRetries ?? 3;\n this.initialDelay = options.initialDelay ?? 100;\n this.maxDelay = options.maxDelay ?? 10000;\n this.backoffMultiplier = options.backoffMultiplier ?? 2.0;\n this.retryableStatusCodes = options.retryableStatusCodes ?? [429, 502, 503, 504];\n }\n\n /**\n * Returns the default retry configuration.\n */\n static default(): RetryConfig {\n return new RetryConfig();\n }\n}\n\n/**\n * Options for RetryConfig constructor.\n */\nexport interface RetryConfigOptions {\n /**\n * Maximum number of retry attempts.\n * @default 3\n */\n maxRetries: number;\n\n /**\n * Initial delay before the first retry in milliseconds.\n * @default 100\n */\n initialDelay: number;\n\n /**\n * Maximum delay between retries in milliseconds.\n * @default 10000\n */\n maxDelay: number;\n\n /**\n * Backoff multiplier for exponential backoff.\n * @default 2.0\n */\n backoffMultiplier: number;\n\n /**\n * HTTP status codes that should trigger a retry.\n * @default [429, 502, 503, 504]\n */\n retryableStatusCodes: number[];\n}\n", "import type { ListParams } from './common';\n\n/**\n * Represents a page of results with pagination support.\n */\nexport interface Page<T> {\n /**\n * The items in this page.\n */\n items: T[];\n\n /**\n * Pagination and sorting parameters.\n */\n params: ListParams;\n}\n\n/**\n * Extended page with navigation methods.\n */\nexport class NavigablePage<T> implements Page<T> {\n items: T[];\n params: ListParams;\n\n private readonly nextPageLoader?: (page: number) => Promise<NavigablePage<T>>;\n\n constructor(data: Page<T>, nextPageLoader?: (page: number) => Promise<NavigablePage<T>>) {\n this.items = data.items;\n this.params = data.params;\n this.nextPageLoader = nextPageLoader;\n }\n\n /**\n * Gets the total number of pages.\n */\n get totalPages(): number {\n return Math.ceil((this.params?.count || 0) / (this.params?.limit || 25));\n }\n\n /**\n * Checks if there is a next page.\n */\n get hasNextPage(): boolean {\n return (this.params?.page || 1) < this.totalPages;\n }\n\n /**\n * Loads the next page.\n */\n async nextPage(): Promise<NavigablePage<T>> {\n if (!this.hasNextPage) {\n throw new Error('No more pages available');\n }\n if (!this.nextPageLoader) {\n throw new Error('Next page loader not configured');\n }\n return this.nextPageLoader((this.params.page || 1) + 1);\n }\n\n /**\n * Returns an async iterator for auto-pagination.\n */\n async *[Symbol.asyncIterator](): AsyncIterator<T> {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n let currentPage: NavigablePage<T> = this;\n\n while (true) {\n for (const item of currentPage.items) {\n yield item;\n }\n\n if (!currentPage.hasNextPage) {\n break;\n }\n\n currentPage = await currentPage.nextPage();\n }\n }\n\n /**\n * Converts all pages to an array (loads all pages).\n */\n async toArray(): Promise<T[]> {\n const allItems: T[] = [];\n\n for await (const item of this) {\n allItems.push(item);\n }\n\n return allItems;\n }\n}\n", "import type { ListParams } from './common';\n\n/**\n * Webhook event types\n */\nexport type WebhookEventType =\n | 'team.create'\n | 'team.update'\n | 'project.create'\n | 'project.update'\n | 'todo.create'\n | 'todo.update'\n | 'task.create'\n | 'task.update'\n | 'tag.create'\n | 'tag.update'\n | 'rate.create'\n | 'rate.update'\n | 'timer.start'\n | 'timer.stop'\n | 'timer.pause'\n | 'timer.resume';\n\n/**\n * Constants for webhook event types\n */\nexport const WebhookEvents = {\n TEAM_CREATE: 'team.create' as const,\n TEAM_UPDATE: 'team.update' as const,\n PROJECT_CREATE: 'project.create' as const,\n PROJECT_UPDATE: 'project.update' as const,\n TODO_CREATE: 'todo.create' as const,\n TODO_UPDATE: 'todo.update' as const,\n TASK_CREATE: 'task.create' as const,\n TASK_UPDATE: 'task.update' as const,\n TAG_CREATE: 'tag.create' as const,\n TAG_UPDATE: 'tag.update' as const,\n RATE_CREATE: 'rate.create' as const,\n RATE_UPDATE: 'rate.update' as const,\n TIMER_START: 'timer.start' as const,\n TIMER_STOP: 'timer.stop' as const,\n TIMER_PAUSE: 'timer.pause' as const,\n TIMER_RESUME: 'timer.resume' as const,\n} as const;\n\n/**\n * Helper function to combine multiple webhook events into a comma-separated string\n * @param events - One or more webhook event types\n * @returns Comma-separated event string\n *\n * @example\n * ```typescript\n * combineWebhookEvents('timer.start', 'timer.stop') // Returns: 'timer.start,timer.stop'\n * combineWebhookEvents(WebhookEvents.TIMER_START, WebhookEvents.TIMER_STOP)\n * ```\n */\nexport function combineWebhookEvents(...events: WebhookEventType[]): string {\n return events.join(',');\n}\n\nexport interface Webhook {\n id: string;\n target: string;\n /**\n * Event type(s) that trigger this webhook.\n * Can be a single event (e.g., 'timer.start') or multiple comma-separated events (e.g., 'timer.start,timer.stop')\n * @see WebhookEventType for valid event types\n */\n event: string;\n user?: string;\n deleted?: boolean;\n created?: number;\n lastUpdate?: number;\n}\n\nexport interface WebhookList {\n items: Webhook[];\n params: WebhookListParams;\n}\n\nexport interface WebhookCreateRequest {\n target: string;\n event: string;\n}\n\nexport interface WebhookUpdateRequest {\n target?: string;\n event?: string;\n deleted?: boolean;\n}\n\nexport interface WebhookListParams extends ListParams {\n sort?: 'created' | 'lastUpdate' | 'target' | 'event';\n order?: 'asc' | 'desc';\n event?: string;\n}\n", "import type { ApiClient } from '../http';\nimport type { Page } from '../models';\nimport { NavigablePage } from '../models';\n\n/**\n * Configuration for resource endpoints\n */\nexport interface ResourceConfig {\n basePath: string;\n}\n\n/**\n * Base resource class that provides common functionality for all API resources.\n */\nexport abstract class Resource {\n protected readonly basePath: string;\n\n protected constructor(\n protected readonly http: ApiClient,\n config: ResourceConfig | string,\n ) {\n if (typeof config === 'string') {\n this.basePath = config;\n } else {\n this.basePath = config.basePath;\n }\n }\n\n /**\n * Creates a NavigablePage from a Page response\n * @param page The page response\n * @param nextPageLoader Function to load the next page\n */\n protected createNavigablePage<R>(\n page: Page<R>,\n nextPageLoader: (page: number) => Promise<NavigablePage<R>>,\n ): NavigablePage<R> {\n return new NavigablePage(page, nextPageLoader);\n }\n}\n", "import type { ApiClient } from '../http';\nimport type {\n Organization,\n OrganizationCreateRequest,\n OrganizationListParams,\n OrganizationMember,\n OrganizationMemberCreateRequest,\n OrganizationMemberListParams,\n OrganizationMemberUpdateRequest,\n OrganizationUpdateRequest,\n Page,\n} from '../models';\nimport { NavigablePage } from '../models';\nimport { Resource } from './Resource';\n\n/**\n * Resource for managing organizations and their members.\n */\nexport class OrganizationResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/organizations');\n }\n\n async list(params?: OrganizationListParams): Promise<NavigablePage<Organization>> {\n const response = await this.http.get<Page<Organization>, OrganizationListParams>(\n this.basePath,\n params,\n );\n return new NavigablePage(response, (page) => this.list({ ...params, page }));\n }\n\n async create(data: OrganizationCreateRequest): Promise<Organization> {\n return this.http.post<Organization>(this.basePath, data);\n }\n\n async update(id: string, data: OrganizationUpdateRequest): Promise<Organization> {\n return this.http.put<Organization>(`${this.basePath}/${encodeURIComponent(id)}`, data);\n }\n\n async get(id: string): Promise<Organization> {\n return this.http.get<Organization>(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n async delete(id: string): Promise<void> {\n return this.http.delete(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n /**\n * Search organizations with parameters using POST\n * @param params Search parameters\n */\n async search(params: OrganizationListParams): Promise<NavigablePage<Organization>> {\n const response = await this.http.post<Page<Organization>>(`${this.basePath}/search`, params);\n return this.createNavigablePage(response, (page) => this.search({ ...params, page }));\n }\n\n /**\n * List members of an organization\n */\n async listMembers(\n organizationId: string,\n params?: OrganizationMemberListParams,\n ): Promise<NavigablePage<OrganizationMember>> {\n const response = await this.http.post<Page<OrganizationMember>>(\n `${this.basePath}/${encodeURIComponent(organizationId)}/members/list`,\n params,\n );\n return this.createNavigablePage(response, (page) =>\n this.listMembers(organizationId, { ...params, page }),\n );\n }\n\n /**\n * Get a specific member of an organization\n */\n async getMember(organizationId: string, permissionId: string): Promise<OrganizationMember> {\n return this.http.get<OrganizationMember>(\n `${this.basePath}/${encodeURIComponent(organizationId)}/members/${encodeURIComponent(permissionId)}`,\n );\n }\n\n /**\n * Add a member to an organization\n */\n async addMember(\n organizationId: string,\n data: OrganizationMemberCreateRequest,\n ): Promise<OrganizationMember> {\n return this.http.post<OrganizationMember>(\n `${this.basePath}/${encodeURIComponent(organizationId)}/members`,\n data,\n );\n }\n\n /**\n * Update a member's permissions in an organization\n */\n async updateMember(\n organizationId: string,\n permissionId: string,\n data: OrganizationMemberUpdateRequest,\n ): Promise<OrganizationMember> {\n return this.http.put<OrganizationMember>(\n `${this.basePath}/${encodeURIComponent(organizationId)}/members/${encodeURIComponent(permissionId)}`,\n data,\n );\n }\n\n /**\n * Remove a member from an organization\n */\n async removeMember(organizationId: string, permissionId: string): Promise<void> {\n return this.http.delete(\n `${this.basePath}/${encodeURIComponent(organizationId)}/members/${encodeURIComponent(permissionId)}`,\n );\n }\n}\n", "import type { ApiClient } from '../http';\nimport type {\n Member,\n MemberStatusParams,\n Page,\n Team,\n TeamCreateRequest,\n TeamListParams,\n TeamMember,\n TeamMemberCreateRequest,\n TeamMemberListParams,\n TeamMemberUpdateRequest,\n TeamUpdateRequest,\n} from '../models';\nimport { NavigablePage } from '../models';\nimport { Resource } from './Resource';\n\nexport class TeamResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/teams');\n }\n\n async list(params?: TeamListParams): Promise<NavigablePage<Team>> {\n const response = await this.http.get<Page<Team>, TeamListParams>(this.basePath, params);\n return new NavigablePage(response, (page) => this.list({ ...params, page }));\n }\n\n async create(data: TeamCreateRequest): Promise<Team> {\n return this.http.post<Team>(this.basePath, data);\n }\n\n async update(id: string, data: TeamUpdateRequest): Promise<Team> {\n return this.http.put<Team>(`${this.basePath}/${encodeURIComponent(id)}`, data);\n }\n\n async get(id: string): Promise<Team> {\n return this.http.get<Team>(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n async delete(id: string): Promise<void> {\n return this.http.delete(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n /**\n * Search teams with parameters using POST\n * @param params Search parameters\n */\n async search(params: TeamListParams): Promise<NavigablePage<Team>> {\n const response = await this.http.post<Page<Team>>(`${this.basePath}/search`, params);\n return this.createNavigablePage(response, (page) => this.search({ ...params, page }));\n }\n\n /**\n * List team members\n * @param teamId Team identifier\n * @param params List parameters\n */\n async listMembers(\n teamId: string,\n params: TeamMemberListParams,\n ): Promise<NavigablePage<TeamMember>> {\n const response = await this.http.post<Page<TeamMember>>(\n `${this.basePath}/${teamId}/members/list`,\n params,\n );\n return this.createNavigablePage(response, (page) =>\n this.listMembers(teamId, { ...params, page }),\n );\n }\n\n /**\n * Get team member\n * @param teamId Team identifier\n * @param memberId Member identifier\n */\n async getMember(teamId: string, memberId: string): Promise<TeamMember> {\n return this.http.get<TeamMember>(`${this.basePath}/${teamId}/members/${memberId}`);\n }\n\n /**\n * Get colleagues\n * @param params Parameters for filtering colleagues\n */\n async getColleagues(params?: TeamMemberListParams): Promise<NavigablePage<Member>> {\n const response = await this.http.post<Page<Member>>(`${this.basePath}/getColleagues`, params);\n return this.createNavigablePage(response, (page) => this.getColleagues({ ...params, page }));\n }\n\n /**\n * Add (register) a member to a team.\n * @param teamId Team identifier\n * @param data Member details including email and permission level\n */\n async addMember(teamId: string, data: TeamMemberCreateRequest): Promise<TeamMember> {\n return this.http.post<TeamMember>(`${this.basePath}/${teamId}/members`, data);\n }\n\n /**\n * Update a team member, including permission level and project registrations.\n * @param teamId Team identifier\n * @param memberId Team member identifier\n * @param data Updated member details\n */\n async updateMember(\n teamId: string,\n memberId: string,\n data: TeamMemberUpdateRequest,\n ): Promise<TeamMember> {\n return this.http.put<TeamMember>(`${this.basePath}/${teamId}/members/${memberId}`, data);\n }\n\n /**\n * Remove a member from a team.\n * @param teamId Team identifier\n * @param memberId Team member identifier\n */\n async removeMember(teamId: string, memberId: string): Promise<void> {\n return this.http.delete<void>(`${this.basePath}/${teamId}/members/${memberId}`);\n }\n\n /**\n * Permanently delete an invited team member and their profile. The member\n * must still be in invited status (account not yet activated).\n * @param teamId Team identifier\n * @param memberId Team member identifier\n */\n async removeInvitedMember(teamId: string, memberId: string): Promise<void> {\n return this.http.delete<void>(`${this.basePath}/${teamId}/members/${memberId}/invited`);\n }\n\n /**\n * Create multiple team members in a single operation. Each member object\n * carries its own team identifier.\n * @param members Member creation objects\n */\n async batchAddMembers(members: TeamMemberCreateRequest[]): Promise<void> {\n return this.http.post<void>(`${this.basePath}/batchTeamMembers`, members);\n }\n\n /**\n * Get team members with their current activity status. Results are sorted\n * with currently-working members first.\n * @param params Filter parameters (organization, team, project, users, status)\n */\n async getMemberStatus(params: MemberStatusParams): Promise<NavigablePage<Member>> {\n const response = await this.http.post<Page<Member>>(`${this.basePath}/getMemberStatus`, params);\n return this.createNavigablePage(response, (page) => this.getMemberStatus({ ...params, page }));\n }\n}\n", "import type { ApiClient } from '../http';\nimport type {\n Page,\n Project,\n ProjectCreateRequest,\n ProjectListParams,\n ProjectMember,\n ProjectMemberCreateRequest,\n ProjectMemberListParams,\n ProjectMemberUpdateRequest,\n ProjectRegistration,\n ProjectUpdateRequest,\n} from '../models';\nimport { NavigablePage } from '../models';\nimport { Resource } from './Resource';\n\nexport class ProjectResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/projects');\n }\n\n async list(params?: ProjectListParams): Promise<NavigablePage<Project>> {\n const response = await this.http.get<Page<Project>, ProjectListParams>(this.basePath, params);\n return new NavigablePage(response, (page) => this.list({ ...params, page }));\n }\n\n async create(data: ProjectCreateRequest): Promise<Project> {\n return this.http.post<Project>(this.basePath, data);\n }\n\n async update(id: string, data: ProjectUpdateRequest): Promise<Project> {\n return this.http.put<Project>(`${this.basePath}/${encodeURIComponent(id)}`, data);\n }\n\n async get(id: string): Promise<Project> {\n return this.http.get<Project>(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n async delete(id: string): Promise<void> {\n return this.http.delete(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n /**\n * Search projects with parameters using POST\n * @param params Search parameters\n */\n async search(params: ProjectListParams): Promise<NavigablePage<Project>> {\n const response = await this.http.post<Page<Project>>(`${this.basePath}/search`, params);\n return this.createNavigablePage(response, (page) => this.search({ ...params, page }));\n }\n\n /**\n * List members of a project.\n * @param projectId Project identifier\n * @param params Filter, pagination, and sorting parameters\n */\n async listMembers(\n projectId: string,\n params: ProjectMemberListParams,\n ): Promise<NavigablePage<ProjectMember>> {\n const response = await this.http.post<Page<ProjectMember>>(\n `${this.basePath}/${encodeURIComponent(projectId)}/members/list`,\n params,\n );\n return this.createNavigablePage(response, (page) =>\n this.listMembers(projectId, { ...params, page }),\n );\n }\n\n /**\n * Add a member to a project. The user must already belong to the\n * associated team if the project belongs to a team.\n * @param projectId Project identifier\n * @param data Member details including user identifier and permission level\n */\n async addMember(projectId: string, data: ProjectMemberCreateRequest): Promise<ProjectMember> {\n return this.http.post<ProjectMember>(\n `${this.basePath}/${encodeURIComponent(projectId)}/members`,\n data,\n );\n }\n\n /**\n * Get a single project member.\n * @param projectId Project identifier\n * @param memberId Project member identifier\n */\n async getMember(projectId: string, memberId: string): Promise<ProjectMember> {\n return this.http.get<ProjectMember>(\n `${this.basePath}/${encodeURIComponent(projectId)}/members/${encodeURIComponent(memberId)}`,\n );\n }\n\n /**\n * Update a project member's permission level.\n * @param projectId Project identifier\n * @param memberId Project member identifier\n * @param data Updated member details\n */\n async updateMember(\n projectId: string,\n memberId: string,\n data: ProjectMemberUpdateRequest,\n ): Promise<ProjectMember> {\n return this.http.put<ProjectMember>(\n `${this.basePath}/${encodeURIComponent(projectId)}/members/${encodeURIComponent(memberId)}`,\n data,\n );\n }\n\n /**\n * Replace the full member list of a project. Members not included in the\n * registration list are removed. The project owner cannot be removed or\n * downgraded through this endpoint.\n * @param projectId Project identifier\n * @param registrations Full set of project member registrations\n */\n async updateMembers(projectId: string, registrations: ProjectRegistration[]): Promise<void> {\n return this.http.put<void>(\n `${this.basePath}/${encodeURIComponent(projectId)}/members`,\n registrations,\n );\n }\n\n /**\n * Remove a member from a project.\n * @param projectId Project identifier\n * @param memberId Project member identifier\n */\n async removeMember(projectId: string, memberId: string): Promise<void> {\n return this.http.delete<void>(\n `${this.basePath}/${encodeURIComponent(projectId)}/members/${encodeURIComponent(memberId)}`,\n );\n }\n\n /**\n * Add multiple members to a project in a single operation.\n * @param projectId Project identifier\n * @param members Member creation objects\n */\n async batchAddMembers(projectId: string, members: ProjectMemberCreateRequest[]): Promise<void> {\n return this.http.post<void>(\n `${this.basePath}/${encodeURIComponent(projectId)}/members/batch`,\n members,\n );\n }\n\n /**\n * Remove multiple members from a project in a single operation.\n * @param projectId Project identifier\n * @param memberIds Identifiers of the project members to remove\n */\n async batchRemoveMembers(projectId: string, memberIds: string[]): Promise<void> {\n return this.http.delete<void>(\n `${this.basePath}/${encodeURIComponent(projectId)}/members/batch`,\n undefined,\n memberIds,\n );\n }\n}\n", "import dayjs from 'dayjs';\nimport utc from 'dayjs/plugin/utc';\nimport timezone from 'dayjs/plugin/timezone';\nimport customParseFormat from 'dayjs/plugin/customParseFormat';\n\n// Extend dayjs with necessary plugins\ndayjs.extend(utc);\ndayjs.extend(timezone);\ndayjs.extend(customParseFormat);\n\n// The expected format for Timesheet API: YYYY-MM-DDTHH:mm:ss\u00B1HH:mm\nconst TIMESTAMP_FORMAT = 'YYYY-MM-DDTHH:mm:ssZ';\nconst TIMESTAMP_REGEX = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}[+-]\\d{2}:\\d{2}$/;\n\nexport const DateUtils = {\n /**\n * Validates if a timestamp string is in the correct format with timezone offset\n * (e.g. 2025-05-31T16:45:51+02:00)\n */\n isValidTimestampFormat(timestamp: string): boolean {\n return TIMESTAMP_REGEX.test(timestamp);\n },\n\n /**\n * Formats a date or timestamp string into the ISO 8601 format with timezone offset\n * that the Timesheet API expects (e.g. 2025-05-31T16:45:51+02:00)\n *\n * @param input Date object, timestamp string, or undefined for current time\n * @returns Formatted date string without milliseconds\n */\n formatTimestamp(input?: Date | string | dayjs.Dayjs): string {\n // If input is a string and already in correct format, return it\n if (typeof input === 'string' && this.isValidTimestampFormat(input)) {\n return input;\n }\n\n // Convert to dayjs object\n const dayjsDate = dayjs(input || new Date());\n\n // Format with timezone offset (no milliseconds)\n // dayjs's format 'Z' gives \u00B1HH:mm format\n return dayjsDate.format(TIMESTAMP_FORMAT);\n },\n\n /**\n * Parses a timestamp string into a Date object.\n * Accepts both UTC ('Z') and timezone offset formats.\n *\n * @param timestamp Timestamp string to parse\n * @returns Date object\n */\n parseTimestamp(timestamp: string): Date {\n return dayjs(timestamp).toDate();\n },\n\n /**\n * Formats a date string to YYYY-MM-DD format\n *\n * @param input Date object, timestamp string, or undefined for current date\n * @returns Date string in YYYY-MM-DD format\n */\n formatDate(input?: Date | string | dayjs.Dayjs): string {\n return dayjs(input || new Date()).format('YYYY-MM-DD');\n },\n\n /**\n * Gets the current timestamp in the correct format\n *\n * @returns Current timestamp with timezone offset\n */\n now(): string {\n return this.formatTimestamp();\n },\n};\n", "import type { ApiClient } from '../http';\nimport type {\n NavigablePage,\n Page,\n Task,\n TaskCreateRequest,\n TaskListParams,\n TaskStatistic,\n TaskStatusUpdateRequest,\n TaskTimesUpdateRequest,\n TaskUpdateRequest,\n} from '../models';\nimport { DateUtils } from '../utils/date';\nimport { Resource } from './Resource';\n\nexport class TaskResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/tasks');\n }\n\n /**\n * List tasks with pagination and sorting.\n * @param params Pagination, sorting, and optional organization filter\n */\n async list(params?: TaskListParams): Promise<NavigablePage<Task>> {\n const response = await this.http.get<Page<Task>, TaskListParams>(this.basePath, params);\n return this.createNavigablePage(response, (page) => this.list({ ...params, page }));\n }\n\n async create(data: TaskCreateRequest): Promise<Task> {\n const formattedData = {\n ...data,\n startDateTime: DateUtils.formatTimestamp(data.startDateTime),\n endDateTime: data.endDateTime ? DateUtils.formatTimestamp(data.endDateTime) : undefined,\n };\n return this.http.post<Task>(this.basePath, formattedData);\n }\n\n async update(id: string, data: TaskUpdateRequest): Promise<Task> {\n const formattedData = {\n ...data,\n startDateTime: data.startDateTime ? DateUtils.formatTimestamp(data.startDateTime) : undefined,\n endDateTime: data.endDateTime ? DateUtils.formatTimestamp(data.endDateTime) : undefined,\n };\n return this.http.put<Task>(`${this.basePath}/${encodeURIComponent(id)}`, formattedData);\n }\n\n async get(id: string): Promise<Task> {\n return this.http.get<Task>(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n async delete(id: string): Promise<void> {\n return this.http.delete(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n /**\n * Search tasks with parameters using POST\n * @param params Search parameters\n */\n async search(params: TaskListParams): Promise<NavigablePage<Task>> {\n const response = await this.http.post<Page<Task>>(`${this.basePath}/search`, params);\n return this.createNavigablePage(response, (page) => this.search({ ...params, page }));\n }\n\n /**\n * Get aggregated task statistics (duration, salary, expenses, mileage) for\n * tasks matching the given filter, without returning the individual tasks.\n * @param params Filter parameters\n */\n async statistics(params: TaskListParams): Promise<TaskStatistic> {\n return this.http.post<TaskStatistic>(`${this.basePath}/statistics`, params);\n }\n\n /**\n * Update task status (billable, paid, billed)\n * @param data Status update data\n */\n async updateStatus(data: TaskStatusUpdateRequest): Promise<Task> {\n return this.http.put<Task>(`${this.basePath}/updateStatus`, data);\n }\n\n /**\n * Update task times\n * @param data Times update data\n */\n async updateTimes(data: TaskTimesUpdateRequest): Promise<Task> {\n const formattedData = {\n ...data,\n start: DateUtils.formatTimestamp(data.start),\n end: DateUtils.formatTimestamp(data.end),\n };\n return this.http.put<Task>(`${this.basePath}/updateTimes`, formattedData);\n }\n\n /**\n * Generate a printable PDF work record for a task, including its details,\n * times, expenses, and notes.\n * @param id Task identifier\n * @returns ArrayBuffer containing the PDF document\n */\n async print(id: string): Promise<ArrayBuffer> {\n return this.http.request<ArrayBuffer>({\n method: 'GET',\n url: `${this.basePath}/print/${encodeURIComponent(id)}`,\n responseType: 'arraybuffer',\n });\n }\n}\n", "import type { ApiClient } from '../http';\nimport type { Page, Rate, RateCreateRequest, RateListParams, RateUpdateRequest } from '../models';\nimport { NavigablePage } from '../models';\nimport { Resource } from './Resource';\n\nexport class RateResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/rates');\n }\n\n async list(params?: RateListParams): Promise<NavigablePage<Rate>> {\n const response = await this.http.get<Page<Rate>, RateListParams>(this.basePath, params);\n return new NavigablePage(response, (page) => this.list({ ...params, page }));\n }\n\n async create(data: RateCreateRequest): Promise<Rate> {\n return this.http.post<Rate>(this.basePath, data);\n }\n\n async update(id: string, data: RateUpdateRequest): Promise<Rate> {\n return this.http.put<Rate>(`${this.basePath}/${encodeURIComponent(id)}`, data);\n }\n\n async get(id: string): Promise<Rate> {\n return this.http.get<Rate>(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n async delete(id: string): Promise<void> {\n return this.http.delete(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n /**\n * Search rates with parameters using POST\n * @param params Search parameters\n */\n async search(params: RateListParams): Promise<NavigablePage<Rate>> {\n const response = await this.http.post<Page<Rate>>(`${this.basePath}/search`, params);\n return this.createNavigablePage(response, (page) => this.search({ ...params, page }));\n }\n}\n", "import type { ApiClient } from '../http';\nimport type { Page, Tag, TagCreateRequest, TagListParams, TagUpdateRequest } from '../models';\nimport { NavigablePage } from '../models';\nimport { Resource } from './Resource';\n\nexport class TagResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/tags');\n }\n\n async list(params?: TagListParams): Promise<NavigablePage<Tag>> {\n // GET /v1/tags returns a bare array, not a paged object.\n const items = await this.http.get<Tag[], TagListParams>(this.basePath, params);\n return new NavigablePage({ items: items ?? [], params: params ?? {} }, (page) =>\n this.list({ ...params, page }),\n );\n }\n\n async create(data: TagCreateRequest): Promise<Tag> {\n return this.http.post<Tag>(this.basePath, data);\n }\n\n async update(id: string, data: TagUpdateRequest): Promise<Tag> {\n return this.http.put<Tag>(`${this.basePath}/${encodeURIComponent(id)}`, data);\n }\n\n async get(id: string): Promise<Tag> {\n return this.http.get<Tag>(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n async delete(id: string): Promise<void> {\n return this.http.delete(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n /**\n * Search tags with parameters using POST\n * @param params Search parameters\n */\n async search(params: TagListParams): Promise<NavigablePage<Tag>> {\n const response = await this.http.post<Page<Tag>>(`${this.basePath}/search`, params);\n return this.createNavigablePage(response, (page) => this.search({ ...params, page }));\n }\n}\n", "import type { ApiClient } from '../http';\nimport type {\n Expense,\n ExpenseCreateRequest,\n ExpenseCreateWithFileRequest,\n ExpenseFileUpload,\n ExpenseListParams,\n ExpenseStatus,\n ExpenseUpdateRequest,\n Page,\n} from '../models';\nimport { NavigablePage } from '../models';\nimport { DateUtils } from '../utils/date';\nimport { Resource } from './Resource';\n\nexport class ExpenseResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/expenses');\n }\n\n async list(params?: ExpenseListParams): Promise<NavigablePage<Expense>> {\n const response = await this.http.get<Page<Expense>, ExpenseListParams>(this.basePath, params);\n return new NavigablePage(response, (page) => this.list({ ...params, page }));\n }\n\n async create(data: ExpenseCreateRequest): Promise<Expense> {\n const formattedData = {\n ...data,\n dateTime: DateUtils.formatTimestamp(data.dateTime),\n };\n return this.http.post<Expense>(this.basePath, formattedData);\n }\n\n async update(id: string, data: ExpenseUpdateRequest): Promise<Expense> {\n const formattedData = {\n ...data,\n dateTime: data.dateTime ? DateUtils.formatTimestamp(data.dateTime) : undefined,\n };\n return this.http.put<Expense>(`${this.basePath}/${encodeURIComponent(id)}`, formattedData);\n }\n\n async get(id: string): Promise<Expense> {\n return this.http.get<Expense>(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n async delete(id: string): Promise<void> {\n return this.http.delete(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n /**\n * Search expenses with parameters using POST\n * @param params Search parameters\n */\n async search(params: ExpenseListParams): Promise<NavigablePage<Expense>> {\n const response = await this.http.post<Page<Expense>>(`${this.basePath}/search`, params);\n return this.createNavigablePage(response, (page) => this.search({ ...params, page }));\n }\n\n /**\n * Update expense status\n * @param data Status update data (must include the expense id)\n * @returns Updated expense\n */\n async updateStatus(data: ExpenseStatus): Promise<Expense> {\n return this.http.put<Expense>(`${this.basePath}/updateStatus`, data);\n }\n\n /**\n * Upload a file to an existing expense\n * @param id Expense ID\n * @param file File to upload\n * @returns Updated expense with file attachment\n */\n async uploadFile(id: string, file: ExpenseFileUpload): Promise<Expense> {\n const formData = new FormData();\n formData.append('file', file.file, file.fileName);\n return this.http.postMultipart<Expense>(\n `${this.basePath}/${encodeURIComponent(id)}/file`,\n formData,\n );\n }\n\n /**\n * Create an expense with a file attachment in a single request\n * @param data Expense data including optional file\n * @returns Created expense\n */\n async createWithFile(data: ExpenseCreateWithFileRequest): Promise<Expense> {\n const { file, ...expenseData } = data;\n const formattedData = {\n ...expenseData,\n dateTime: DateUtils.formatTimestamp(expenseData.dateTime),\n };\n\n const formData = new FormData();\n formData.append(\n 'data',\n new Blob([JSON.stringify(formattedData)], { type: 'application/json' }),\n );\n\n if (file) {\n formData.append('file', file.file, file.fileName);\n }\n\n return this.http.postMultipart<Expense>(`${this.basePath}/with-file`, formData);\n }\n\n /**\n * Get the signed URL for an expense file attachment\n * @param id Expense ID\n * @returns File URL response\n */\n async getFileUrl(id: string): Promise<{ url: string }> {\n return this.http.get<{ url: string }>(`${this.basePath}/getFileUrl/${encodeURIComponent(id)}`);\n }\n}\n", "import type { ApiClient } from '../http';\nimport type {\n Note,\n NoteCreateRequest,\n NoteCreateWithFileRequest,\n NoteFileUpload,\n NoteListParams,\n NoteUpdateRequest,\n Page,\n} from '../models';\nimport { NavigablePage } from '../models';\nimport { DateUtils } from '../utils/date';\nimport { Resource } from './Resource';\n\nexport class NoteResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/notes');\n }\n\n async list(params?: NoteListParams): Promise<NavigablePage<Note>> {\n const response = await this.http.get<Page<Note>, NoteListParams>(this.basePath, params);\n return new NavigablePage(response, (page) => this.list({ ...params, page }));\n }\n\n async create(data: NoteCreateRequest): Promise<Note> {\n const formattedData = {\n ...data,\n dateTime: DateUtils.formatTimestamp(data.dateTime),\n };\n return this.http.post<Note>(this.basePath, formattedData);\n }\n\n async update(id: string, data: NoteUpdateRequest): Promise<Note> {\n const formattedData = {\n ...data,\n dateTime: DateUtils.formatTimestamp(data.dateTime),\n };\n return this.http.put<Note>(`${this.basePath}/${encodeURIComponent(id)}`, formattedData);\n }\n\n async get(id: string): Promise<Note> {\n return this.http.get<Note>(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n async delete(id: string): Promise<void> {\n return this.http.delete(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n /**\n * Search notes with parameters using POST\n * @param params Search parameters\n */\n async search(params: NoteListParams): Promise<NavigablePage<Note>> {\n const response = await this.http.post<Page<Note>>(`${this.basePath}/search`, params);\n return this.createNavigablePage(response, (page) => this.search({ ...params, page }));\n }\n\n /**\n * Upload a file to an existing note\n * @param id Note ID\n * @param file File to upload\n * @returns Updated note with file attachment\n */\n async uploadFile(id: string, file: NoteFileUpload): Promise<Note> {\n const formData = new FormData();\n formData.append('file', file.file, file.fileName);\n return this.http.postMultipart<Note>(\n `${this.basePath}/${encodeURIComponent(id)}/file`,\n formData,\n );\n }\n\n /**\n * Create a note with a file attachment in a single request\n * @param data Note data including optional file\n * @returns Created note\n */\n async createWithFile(data: NoteCreateWithFileRequest): Promise<Note> {\n const { file, ...noteData } = data;\n const formattedData = {\n ...noteData,\n dateTime: DateUtils.formatTimestamp(noteData.dateTime),\n };\n\n const formData = new FormData();\n formData.append(\n 'data',\n new Blob([JSON.stringify(formattedData)], { type: 'application/json' }),\n );\n\n if (file) {\n formData.append('file', file.file, file.fileName);\n }\n\n return this.http.postMultipart<Note>(`${this.basePath}/with-file`, formData);\n }\n\n /**\n * Get the signed URL for a note file attachment\n * @param id Note ID\n * @returns File URL response\n */\n async getFileUrl(id: string): Promise<{ url: string }> {\n return this.http.get<{ url: string }>(`${this.basePath}/getFileUrl/${encodeURIComponent(id)}`);\n }\n}\n", "import type { ApiClient } from '../http';\nimport type {\n Page,\n Pause,\n PauseCreateRequest,\n PauseListParams,\n PauseUpdateRequest,\n} from '../models';\nimport { NavigablePage } from '../models';\nimport { DateUtils } from '../utils/date';\nimport { Resource } from './Resource';\n\nexport class PauseResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/pauses');\n }\n\n async list(params?: PauseListParams): Promise<NavigablePage<Pause>> {\n const response = await this.http.get<Page<Pause>, PauseListParams>(this.basePath, params);\n return new NavigablePage(response, (page) => this.list({ ...params, page }));\n }\n\n async create(data: PauseCreateRequest): Promise<Pause> {\n const formattedData = {\n ...data,\n startDateTime: DateUtils.formatTimestamp(data.startDateTime),\n endDateTime: DateUtils.formatTimestamp(data.endDateTime),\n };\n return this.http.post<Pause>(this.basePath, formattedData);\n }\n\n async update(id: string, data: PauseUpdateRequest): Promise<Pause> {\n const formattedData = {\n ...data,\n startDateTime: DateUtils.formatTimestamp(data.startDateTime),\n endDateTime: DateUtils.formatTimestamp(data.endDateTime),\n };\n return this.http.put<Pause>(`${this.basePath}/${encodeURIComponent(id)}`, formattedData);\n }\n\n async get(id: string): Promise<Pause> {\n return this.http.get<Pause>(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n async delete(id: string): Promise<void> {\n return this.http.delete(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n /**\n * Search pauses with parameters using POST\n * @param params Search parameters\n */\n async search(params: PauseListParams): Promise<NavigablePage<Pause>> {\n const response = await this.http.post<Page<Pause>>(`${this.basePath}/search`, params);\n return this.createNavigablePage(response, (page) => this.search({ ...params, page }));\n }\n}\n", "import type { ApiClient } from '../http';\nimport type { Profile, ProfileUpdateRequest } from '../models';\n\nexport class ProfileResource {\n constructor(private readonly http: ApiClient) {}\n\n async getProfile(): Promise<Profile> {\n return this.http.get<Profile>('/v1/profiles/me');\n }\n\n async updateProfile(data: ProfileUpdateRequest): Promise<Profile> {\n return this.http.put<Profile>('/v1/profiles/me', data);\n }\n}\n", "import type { ApiClient } from '../http';\nimport type { Settings, SettingsUpdateRequest } from '../models';\n\nexport class SettingsResource {\n constructor(private readonly http: ApiClient) {}\n\n async get(): Promise<Settings> {\n return this.http.get<Settings>('/v1/settings');\n }\n\n async update(data: SettingsUpdateRequest): Promise<Settings> {\n return this.http.put<Settings>('/v1/settings', data);\n }\n}\n", "import type { ApiClient } from '../http';\nimport type {\n Automation,\n AutomationCreateRequest,\n AutomationListParams,\n AutomationUpdateRequest,\n Page,\n} from '../models';\nimport { NavigablePage } from '../models';\nimport { Resource } from './Resource';\n\nexport class AutomationResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/automations');\n }\n\n async list(params?: AutomationListParams): Promise<NavigablePage<Automation>> {\n const response = await this.http.get<Page<Automation>, AutomationListParams>(\n this.basePath,\n params,\n );\n return new NavigablePage(response, (page) => this.list({ ...params, page }));\n }\n\n async create(data: AutomationCreateRequest): Promise<Automation> {\n return this.http.post<Automation>(this.basePath, data);\n }\n\n async update(id: string, data: AutomationUpdateRequest): Promise<Automation> {\n return this.http.put<Automation>(`${this.basePath}/${encodeURIComponent(id)}`, data);\n }\n\n async get(id: string): Promise<Automation> {\n return this.http.get<Automation>(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n async delete(id: string): Promise<void> {\n return this.http.delete(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n /**\n * Search automations with parameters using POST\n * @param params Search parameters\n */\n async search(params: AutomationListParams): Promise<NavigablePage<Automation>> {\n const response = await this.http.post<Page<Automation>>(`${this.basePath}/search`, params);\n return this.createNavigablePage(response, (page) => this.search({ ...params, page }));\n }\n}\n", "import type { ApiClient } from '../http';\nimport type {\n Document,\n DocumentCreateRequest,\n DocumentListParams,\n DocumentUpdateRequest,\n Page,\n} from '../models';\nimport { NavigablePage } from '../models';\nimport { Resource } from './Resource';\n\nexport class DocumentResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/documents');\n }\n\n async list(params?: DocumentListParams): Promise<NavigablePage<Document>> {\n // GET /v1/documents expects the category filter as the `type` query param.\n const { category, ...rest } = params ?? {};\n const query: Record<string, unknown> =\n category !== undefined ? { ...rest, type: category } : { ...rest };\n const response = await this.http.get<Page<Document>, Record<string, unknown>>(\n this.basePath,\n query,\n );\n return new NavigablePage(response, (page) => this.list({ ...params, page }));\n }\n\n async create(data: DocumentCreateRequest): Promise<Document> {\n return this.http.post<Document>(this.basePath, data);\n }\n\n async update(id: string, data: DocumentUpdateRequest): Promise<Document> {\n return this.http.put<Document>(`${this.basePath}/${encodeURIComponent(id)}`, data);\n }\n\n async get(id: string): Promise<Document> {\n return this.http.get<Document>(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n async delete(id: string): Promise<void> {\n return this.http.delete(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n /**\n * Search documents with parameters using POST\n * @param params Search parameters\n */\n async search(params: DocumentListParams): Promise<NavigablePage<Document>> {\n const response = await this.http.post<Page<Document>>(`${this.basePath}/search`, params);\n return this.createNavigablePage(response, (page) => this.search({ ...params, page }));\n }\n}\n", "import type { ApiClient } from '../http';\nimport type {\n Timer,\n TimerPauseRequest,\n TimerResumeRequest,\n TimerStartRequest,\n TimerStopRequest,\n TimerUpdateRequest,\n} from '../models';\nimport { DateUtils } from '../utils/date';\n\nexport class TimerResource {\n constructor(private readonly http: ApiClient) {}\n\n async get(): Promise<Timer> {\n return this.http.get<Timer>('/v1/timer');\n }\n\n async start(data: TimerStartRequest): Promise<Timer> {\n // Format startDateTime if provided\n const formattedData = {\n ...data,\n startDateTime: data.startDateTime\n ? DateUtils.formatTimestamp(data.startDateTime)\n : DateUtils.formatTimestamp(),\n };\n return this.http.post<Timer>('/v1/timer/start', formattedData);\n }\n\n async stop(data?: TimerStopRequest): Promise<Timer> {\n // Format endDateTime if provided\n const formattedData = data\n ? {\n ...data,\n endDateTime: data.endDateTime\n ? DateUtils.formatTimestamp(data.endDateTime)\n : DateUtils.formatTimestamp(),\n }\n : { endDateTime: DateUtils.formatTimestamp() };\n return this.http.post<Timer>('/v1/timer/stop', formattedData);\n }\n\n async pause(data?: TimerPauseRequest): Promise<Timer> {\n // Format startDateTime if provided\n const formattedData = data\n ? {\n ...data,\n startDateTime: data.startDateTime\n ? DateUtils.formatTimestamp(data.startDateTime)\n : DateUtils.formatTimestamp(),\n }\n : { startDateTime: DateUtils.formatTimestamp() };\n return this.http.post<Timer>('/v1/timer/pause', formattedData);\n }\n\n async resume(data?: TimerResumeRequest): Promise<Timer> {\n // Format endDateTime if provided\n const formattedData = data\n ? {\n ...data,\n endDateTime: data.endDateTime\n ? DateUtils.formatTimestamp(data.endDateTime)\n : DateUtils.formatTimestamp(),\n }\n : { endDateTime: DateUtils.formatTimestamp() };\n return this.http.post<Timer>('/v1/timer/resume', formattedData);\n }\n\n async update(data: TimerUpdateRequest): Promise<Timer> {\n // Format startDateTime if provided\n const formattedData = {\n ...data,\n startDateTime: data.startDateTime ? DateUtils.formatTimestamp(data.startDateTime) : undefined,\n };\n return this.http.put<Timer>('/v1/timer/update', formattedData);\n }\n}\n", "import type { ApiClient } from '../http';\nimport type { Page, Todo, TodoCreateRequest, TodoListParams, TodoUpdateRequest } from '../models';\nimport { NavigablePage } from '../models';\nimport { DateUtils } from '../utils/date';\nimport { Resource } from './Resource';\n\nexport class TodoResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/todos');\n }\n\n async list(params?: TodoListParams): Promise<NavigablePage<Todo>> {\n // GET /v1/todos returns a bare array, not a paged object.\n const items = await this.http.get<Todo[], TodoListParams>(this.basePath, params);\n return new NavigablePage({ items: items ?? [], params: params ?? {} }, (page) =>\n this.list({ ...params, page }),\n );\n }\n\n async create(data: TodoCreateRequest): Promise<Todo> {\n const formattedData = {\n ...data,\n dueDate: data.dueDate ? DateUtils.formatTimestamp(data.dueDate) : undefined,\n };\n return this.http.post<Todo>(this.basePath, formattedData);\n }\n\n async update(id: string, data: TodoUpdateRequest): Promise<Todo> {\n const formattedData = {\n ...data,\n dueDate: data.dueDate ? DateUtils.formatTimestamp(data.dueDate) : undefined,\n };\n return this.http.put<Todo>(`${this.basePath}/${encodeURIComponent(id)}`, formattedData);\n }\n\n async get(id: string): Promise<Todo> {\n return this.http.get<Todo>(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n async delete(id: string): Promise<void> {\n return this.http.delete(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n /**\n * Search todos with parameters using POST\n * @param params Search parameters\n */\n async search(params: TodoListParams): Promise<NavigablePage<Todo>> {\n const response = await this.http.post<Page<Todo>>(`${this.basePath}/search`, params);\n return this.createNavigablePage(response, (page) => this.search({ ...params, page }));\n }\n}\n", "import type { ApiClient } from '../http';\nimport type {\n Page,\n Webhook,\n WebhookCreateRequest,\n WebhookListParams,\n WebhookUpdateRequest,\n} from '../models';\nimport { NavigablePage } from '../models';\nimport { Resource } from './Resource';\n\nexport class WebhookResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/webhooks');\n }\n\n async list(params?: WebhookListParams): Promise<NavigablePage<Webhook>> {\n const response = await this.http.get<Page<Webhook>, WebhookListParams>(this.basePath, params);\n return new NavigablePage(response, (page) => this.list({ ...params, page }));\n }\n\n async create(data: WebhookCreateRequest): Promise<Webhook> {\n return this.http.post<Webhook>(this.basePath, data);\n }\n\n async update(id: string, data: WebhookUpdateRequest): Promise<Webhook> {\n return this.http.put<Webhook>(`${this.basePath}/${encodeURIComponent(id)}`, data);\n }\n\n async get(id: string): Promise<Webhook> {\n return this.http.get<Webhook>(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n async delete(id: string): Promise<void> {\n return this.http.delete(`${this.basePath}/${encodeURIComponent(id)}`);\n }\n\n /**\n * Search webhooks with parameters using POST\n * @param params Search parameters\n */\n async search(params: WebhookListParams): Promise<NavigablePage<Webhook>> {\n const response = await this.http.post<Page<Webhook>>(`${this.basePath}/search`, params);\n return this.createNavigablePage(response, (page) => this.search({ ...params, page }));\n }\n}\n", "import type { ApiClient } from '../http';\nimport type { EventData, EventType, SseStatus, SseSubscription } from '../models';\nimport { Resource } from './Resource';\n\n/**\n * EventResource provides access to Server-Sent Events (SSE) for real-time updates.\n *\n * @example\n * ```typescript\n * // Subscribe to events\n * const subscription = await client.events.subscribe({\n * onEvent: (event) => {\n * console.log('Received event:', event.event, event.item);\n * },\n * onError: (error) => {\n * console.error('SSE error:', error);\n * }\n * });\n *\n * // Later, close the connection\n * subscription.close();\n * ```\n */\nexport class EventResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/events');\n }\n\n /**\n * Get the current SSE connection status for the authenticated user.\n * @returns Status including whether connected and connection count\n */\n async getStatus(): Promise<SseStatus> {\n return this.http.get<SseStatus>(`${this.basePath}/status`);\n }\n\n /**\n * Get the full URL for the SSE stream endpoint.\n * Useful if you want to use a custom EventSource implementation.\n * @returns The full URL to the SSE stream endpoint\n */\n getStreamUrl(): string {\n return `${this.http.getBaseUrl()}${this.basePath}/stream`;\n }\n\n /**\n * Subscribe to real-time events via Server-Sent Events.\n *\n * This method establishes an SSE connection to receive real-time updates\n * for entity changes (tasks, projects, teams, etc.).\n *\n * Note: This uses fetch with ReadableStream for broad compatibility.\n * For browser environments, you may also use getStreamUrl() with EventSource.\n *\n * @param options Subscription options including event handlers\n * @returns A subscription object with close() method\n *\n * @example\n * ```typescript\n * const subscription = await client.events.subscribe({\n * onEvent: (event) => {\n * switch (event.event) {\n * case 'task.create':\n * console.log('New task created:', event.item);\n * break;\n * case 'task.update':\n * console.log('Task updated:', event.item);\n * break;\n * }\n * },\n * onConnected: (connectionId) => {\n * console.log('Connected with ID:', connectionId);\n * },\n * onError: (error) => {\n * console.error('Error:', error);\n * },\n * onClose: () => {\n * console.log('Connection closed');\n * }\n * });\n *\n * // Close when done\n * subscription.close();\n * ```\n */\n async subscribe(options: SubscribeOptions): Promise<SseSubscription> {\n const url = this.getStreamUrl();\n const authHeaders = await this.http.getAuthHeaders();\n\n const headers: Record<string, string> = {\n Accept: 'text/event-stream',\n 'Cache-Control': 'no-cache',\n ...authHeaders,\n };\n\n const abortController = new AbortController();\n let isConnected = false;\n const eventHandlers = new Map<string, Set<(data: unknown) => void>>();\n\n const subscription: SseSubscription = {\n close: () => {\n isConnected = false;\n abortController.abort();\n options.onClose?.();\n },\n get isConnected() {\n return isConnected;\n },\n on: (event: EventType | 'error', handler: (data: unknown) => void) => {\n if (!eventHandlers.has(event)) {\n eventHandlers.set(event, new Set());\n }\n eventHandlers.get(event)!.add(handler);\n },\n off: (event: EventType | 'error', handler: (data: unknown) => void) => {\n eventHandlers.get(event)?.delete(handler);\n },\n };\n\n // Start the SSE connection (intentionally not awaited - runs in background)\n void this.connectSse(url, headers, abortController.signal, {\n ...options,\n onConnected: (connectionId) => {\n isConnected = true;\n options.onConnected?.(connectionId);\n },\n onEvent: (event) => {\n options.onEvent?.(event);\n // Also emit to registered handlers\n const handlers = eventHandlers.get(event.event as EventType);\n handlers?.forEach((handler) => handler(event));\n },\n onError: (error) => {\n options.onError?.(error);\n const handlers = eventHandlers.get('error');\n handlers?.forEach((handler) => handler(error));\n },\n onClose: () => {\n isConnected = false;\n options.onClose?.();\n },\n });\n\n return subscription;\n }\n\n /**\n * Internal method to establish and manage the SSE connection.\n */\n private async connectSse(\n url: string,\n headers: Record<string, string>,\n signal: AbortSignal,\n options: SubscribeOptions,\n ): Promise<void> {\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers,\n signal,\n });\n\n if (!response.ok) {\n throw new Error(`SSE connection failed: ${response.status} ${response.statusText}`);\n }\n\n if (!response.body) {\n throw new Error('SSE response has no body');\n }\n\n const reader = response.body.getReader() as ReadableStreamDefaultReader<Uint8Array>;\n const decoder = new TextDecoder();\n let buffer = '';\n\n // Current event being parsed\n let eventType = '';\n let eventData = '';\n let eventId = '';\n\n let done = false;\n while (!done) {\n const result = await reader.read();\n done = result.done;\n\n if (done || !result.value) {\n options.onClose?.();\n break;\n }\n\n buffer += decoder.decode(result.value, { stream: true });\n\n // Process complete lines\n const lines = buffer.split('\\n');\n buffer = lines.pop() || ''; // Keep incomplete line in buffer\n\n for (const line of lines) {\n if (line.startsWith('event:')) {\n eventType = line.slice(6).trim();\n } else if (line.startsWith('data:')) {\n eventData = line.slice(5).trim();\n } else if (line.startsWith('id:')) {\n eventId = line.slice(3).trim();\n } else if (line === '') {\n // Empty line signals end of event\n if (eventData) {\n this.processEvent(eventType, eventData, eventId, options);\n }\n // Reset for next event\n eventType = '';\n eventData = '';\n eventId = '';\n }\n }\n }\n } catch (error) {\n if (signal.aborted) {\n // Connection was intentionally closed\n return;\n }\n options.onError?.(error);\n }\n }\n\n /**\n * Process a received SSE event.\n */\n private processEvent(\n eventType: string,\n eventData: string,\n _eventId: string,\n options: SubscribeOptions,\n ): void {\n try {\n const data: unknown = JSON.parse(eventData);\n\n if (eventType === 'connected') {\n const connectedData = data as { connectionId: string };\n options.onConnected?.(connectedData.connectionId);\n } else {\n options.onEvent?.(data as EventData);\n }\n } catch {\n options.onError?.(new Error(`Failed to parse event data: ${eventData}`));\n }\n }\n}\n\n/**\n * Options for subscribing to SSE events\n */\nexport interface SubscribeOptions {\n /**\n * Called when an event is received\n */\n onEvent?: (event: EventData) => void;\n\n /**\n * Called when the connection is established\n */\n onConnected?: (connectionId: string) => void;\n\n /**\n * Called when an error occurs\n */\n onError?: (error: unknown) => void;\n\n /**\n * Called when the connection is closed\n */\n onClose?: () => void;\n}\n", "import type { ApiClient } from '../http';\nimport type {\n Absence,\n AbsenceCreateRequest,\n AbsenceListParams,\n AbsenceReasonRequest,\n AbsenceUpdateRequest,\n Page,\n} from '../models';\nimport type { NavigablePage } from '../models';\nimport { Resource } from './Resource';\n\n/**\n * Resource for managing absences within an organization.\n *\n * All methods require an organizationId since absences are scoped to organizations.\n */\nexport class AbsenceResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/organizations');\n }\n\n private orgPath(organizationId: string): string {\n return `${this.basePath}/${encodeURIComponent(organizationId)}/absences`;\n }\n\n async list(organizationId: string, params?: AbsenceListParams): Promise<NavigablePage<Absence>> {\n const response = await this.http.get<Page<Absence>, AbsenceListParams>(\n this.orgPath(organizationId),\n params,\n );\n return this.createNavigablePage(response, (page) =>\n this.list(organizationId, { ...params, page }),\n );\n }\n\n async search(organizationId: string, params: AbsenceListParams): Promise<NavigablePage<Absence>> {\n const response = await this.http.post<Page<Absence>>(\n `${this.orgPath(organizationId)}/search`,\n params,\n );\n return this.createNavigablePage(response, (page) =>\n this.search(organizationId, { ...params, page }),\n );\n }\n\n async create(organizationId: string, data: AbsenceCreateRequest): Promise<Absence> {\n return this.http.post<Absence>(this.orgPath(organizationId), data);\n }\n\n async get(organizationId: string, id: string): Promise<Absence> {\n return this.http.get<Absence>(`${this.orgPath(organizationId)}/${encodeURIComponent(id)}`);\n }\n\n async update(organizationId: string, id: string, data: AbsenceUpdateRequest): Promise<Absence> {\n return this.http.put<Absence>(\n `${this.orgPath(organizationId)}/${encodeURIComponent(id)}`,\n data,\n );\n }\n\n async delete(organizationId: string, id: string): Promise<void> {\n return this.http.delete(`${this.orgPath(organizationId)}/${encodeURIComponent(id)}`);\n }\n\n async approve(organizationId: string, id: string): Promise<Absence> {\n return this.http.post<Absence>(\n `${this.orgPath(organizationId)}/${encodeURIComponent(id)}/approve`,\n );\n }\n\n async reject(organizationId: string, id: string, data: AbsenceReasonRequest): Promise<Absence> {\n return this.http.post<Absence>(\n `${this.orgPath(organizationId)}/${encodeURIComponent(id)}/reject`,\n data,\n );\n }\n\n async cancel(organizationId: string, id: string, data: AbsenceReasonRequest): Promise<Absence> {\n return this.http.post<Absence>(\n `${this.orgPath(organizationId)}/${encodeURIComponent(id)}/cancel`,\n data,\n );\n }\n}\n", "import type { ApiClient } from '../http';\nimport type {\n AbsenceType,\n AbsenceTypeCreateRequest,\n AbsenceTypeListParams,\n AbsenceTypeUpdateRequest,\n Page,\n} from '../models';\nimport type { NavigablePage } from '../models';\nimport { Resource } from './Resource';\n\n/**\n * Resource for managing absence types within an organization.\n */\nexport class AbsenceTypeResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/organizations');\n }\n\n private orgPath(organizationId: string): string {\n return `${this.basePath}/${encodeURIComponent(organizationId)}/absence-types`;\n }\n\n async list(\n organizationId: string,\n params?: AbsenceTypeListParams,\n ): Promise<NavigablePage<AbsenceType>> {\n const response = await this.http.get<Page<AbsenceType>, AbsenceTypeListParams>(\n this.orgPath(organizationId),\n params,\n );\n return this.createNavigablePage(response, (page) =>\n this.list(organizationId, { ...params, page }),\n );\n }\n\n async create(organizationId: string, data: AbsenceTypeCreateRequest): Promise<AbsenceType> {\n return this.http.post<AbsenceType>(this.orgPath(organizationId), data);\n }\n\n async get(organizationId: string, id: string): Promise<AbsenceType> {\n return this.http.get<AbsenceType>(`${this.orgPath(organizationId)}/${encodeURIComponent(id)}`);\n }\n\n async update(\n organizationId: string,\n id: string,\n data: AbsenceTypeUpdateRequest,\n ): Promise<AbsenceType> {\n return this.http.put<AbsenceType>(\n `${this.orgPath(organizationId)}/${encodeURIComponent(id)}`,\n data,\n );\n }\n\n async delete(organizationId: string, id: string): Promise<void> {\n return this.http.delete(`${this.orgPath(organizationId)}/${encodeURIComponent(id)}`);\n }\n}\n", "import type { ApiClient } from '../http';\nimport type {\n Contract,\n ContractCreateRequest,\n ContractListParams,\n ContractUpdateRequest,\n Page,\n} from '../models';\nimport type { NavigablePage } from '../models';\nimport { Resource } from './Resource';\n\n/**\n * Resource for managing contracts within an organization.\n */\nexport class ContractResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/organizations');\n }\n\n private orgPath(organizationId: string): string {\n return `${this.basePath}/${encodeURIComponent(organizationId)}/contracts`;\n }\n\n async list(\n organizationId: string,\n params?: ContractListParams,\n ): Promise<NavigablePage<Contract>> {\n const response = await this.http.get<Page<Contract>, ContractListParams>(\n this.orgPath(organizationId),\n params,\n );\n return this.createNavigablePage(response, (page) =>\n this.list(organizationId, { ...params, page }),\n );\n }\n\n async create(organizationId: string, data: ContractCreateRequest): Promise<Contract> {\n return this.http.post<Contract>(this.orgPath(organizationId), data);\n }\n\n async get(organizationId: string, id: string): Promise<Contract> {\n return this.http.get<Contract>(`${this.orgPath(organizationId)}/${encodeURIComponent(id)}`);\n }\n\n async update(organizationId: string, id: string, data: ContractUpdateRequest): Promise<Contract> {\n return this.http.put<Contract>(\n `${this.orgPath(organizationId)}/${encodeURIComponent(id)}`,\n data,\n );\n }\n\n async delete(organizationId: string, id: string): Promise<void> {\n return this.http.delete(`${this.orgPath(organizationId)}/${encodeURIComponent(id)}`);\n }\n\n /**\n * Activate a contract\n */\n async activate(organizationId: string, id: string): Promise<Contract> {\n return this.http.put<Contract>(\n `${this.orgPath(organizationId)}/${encodeURIComponent(id)}/activate`,\n );\n }\n\n /**\n * Suspend a contract\n */\n async suspend(organizationId: string, id: string): Promise<Contract> {\n return this.http.put<Contract>(\n `${this.orgPath(organizationId)}/${encodeURIComponent(id)}/suspend`,\n );\n }\n\n /**\n * Reactivate a suspended contract\n */\n async reactivate(organizationId: string, id: string): Promise<Contract> {\n return this.http.put<Contract>(\n `${this.orgPath(organizationId)}/${encodeURIComponent(id)}/reactivate`,\n );\n }\n\n /**\n * Terminate a contract\n */\n async terminate(organizationId: string, id: string): Promise<Contract> {\n return this.http.put<Contract>(\n `${this.orgPath(organizationId)}/${encodeURIComponent(id)}/terminate`,\n );\n }\n}\n", "import type { ApiClient } from '../http';\nimport type {\n ContractTemplate,\n ContractTemplateCreateRequest,\n ContractTemplateListParams,\n ContractTemplateUpdateRequest,\n Page,\n} from '../models';\nimport type { NavigablePage } from '../models';\nimport { Resource } from './Resource';\n\n/**\n * Resource for managing contract templates within an organization.\n */\nexport class ContractTemplateResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/organizations');\n }\n\n private orgPath(organizationId: string): string {\n return `${this.basePath}/${encodeURIComponent(organizationId)}/contract-templates`;\n }\n\n async list(\n organizationId: string,\n params?: ContractTemplateListParams,\n ): Promise<NavigablePage<ContractTemplate>> {\n const response = await this.http.get<Page<ContractTemplate>, ContractTemplateListParams>(\n this.orgPath(organizationId),\n params,\n );\n return this.createNavigablePage(response, (page) =>\n this.list(organizationId, { ...params, page }),\n );\n }\n\n async create(\n organizationId: string,\n data: ContractTemplateCreateRequest,\n ): Promise<ContractTemplate> {\n return this.http.post<ContractTemplate>(this.orgPath(organizationId), data);\n }\n\n async get(organizationId: string, id: string): Promise<ContractTemplate> {\n return this.http.get<ContractTemplate>(\n `${this.orgPath(organizationId)}/${encodeURIComponent(id)}`,\n );\n }\n\n async update(\n organizationId: string,\n id: string,\n data: ContractTemplateUpdateRequest,\n ): Promise<ContractTemplate> {\n return this.http.put<ContractTemplate>(\n `${this.orgPath(organizationId)}/${encodeURIComponent(id)}`,\n data,\n );\n }\n\n async delete(organizationId: string, id: string): Promise<void> {\n return this.http.delete(`${this.orgPath(organizationId)}/${encodeURIComponent(id)}`);\n }\n}\n", "import type { ApiClient } from '../../http';\nimport type { DocumentReport } from '../../models';\nimport { Resource } from '../Resource';\n\n/**\n * Resource for generating document reports and PDFs.\n * Accesses the Reports API at reports.timesheet.io.\n */\nexport class DocumentReportResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/documents');\n }\n\n /**\n * Generate document report data in JSON format.\n * Returns a DocumentReport entity containing all document data.\n * @param documentId Unique identifier of the document\n */\n async get(documentId: string): Promise<DocumentReport> {\n return this.http.get<DocumentReport>(`${this.basePath}/${encodeURIComponent(documentId)}`);\n }\n\n /**\n * Generate and download a PDF report for a specific document.\n * The PDF includes all document data (tasks, expenses, notes) formatted\n * according to user settings and document template.\n * @param documentId Unique identifier of the document\n * @returns ArrayBuffer containing the PDF file data\n */\n async getPdf(documentId: string): Promise<ArrayBuffer> {\n return this.http.request<ArrayBuffer>({\n method: 'GET',\n url: `${this.basePath}/${encodeURIComponent(documentId)}/pdf`,\n responseType: 'arraybuffer',\n });\n }\n\n /**\n * Generate XML representation of the document.\n * Returns Zugferd/XRechnung, ebInterface, or plain DocumentReport XML\n * based on the document's eInvoiceType configuration.\n * @param documentId Unique identifier of the document\n * @returns String containing the XML data\n */\n async getXml(documentId: string): Promise<string> {\n return this.http.request<string>({\n method: 'GET',\n url: `${this.basePath}/${encodeURIComponent(documentId)}/xml`,\n headers: {\n Accept: 'application/xml',\n },\n });\n }\n}\n", "import type { ApiClient } from '../../http';\nimport type { TaskReportItem } from '../../models';\nimport { Resource } from '../Resource';\n\n/**\n * Resource for generating task reports and PDFs.\n * Accesses the Reports API at reports.timesheet.io.\n */\nexport class TaskReportResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/tasks');\n }\n\n /**\n * Generate task report data in JSON format.\n * Returns a TaskReportItem entity containing formatted task information\n * including time tracking, rates, project details, and signatures.\n * @param taskId Unique identifier of the task\n */\n async get(taskId: string): Promise<TaskReportItem> {\n return this.http.get<TaskReportItem>(`${this.basePath}/${encodeURIComponent(taskId)}`);\n }\n\n /**\n * Generate and download a PDF report for a specific task.\n * The PDF includes task details, time tracking information, project context,\n * and any associated signatures formatted according to user settings.\n * @param taskId Unique identifier of the task\n * @returns ArrayBuffer containing the PDF file data\n */\n async getPdf(taskId: string): Promise<ArrayBuffer> {\n return this.http.request<ArrayBuffer>({\n method: 'GET',\n url: `${this.basePath}/${encodeURIComponent(taskId)}/pdf`,\n responseType: 'arraybuffer',\n });\n }\n}\n", "import type { ApiClient } from '../../http';\nimport type { ExpenseReportItem } from '../../models';\nimport { Resource } from '../Resource';\n\n/**\n * Resource for generating expense reports and PDFs.\n * Accesses the Reports API at reports.timesheet.io.\n */\nexport class ExpenseReportResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/expenses');\n }\n\n /**\n * Generate expense report data in JSON format.\n * Returns an ExpenseReportItem entity containing formatted expense information\n * including amounts, descriptions, receipts, and timestamps.\n * @param expenseId Unique identifier of the expense\n */\n async get(expenseId: string): Promise<ExpenseReportItem> {\n return this.http.get<ExpenseReportItem>(`${this.basePath}/${encodeURIComponent(expenseId)}`);\n }\n\n /**\n * Generate and download a PDF report for a specific expense.\n * The PDF includes expense details, amounts, receipt images,\n * and formatting according to user settings.\n * @param expenseId Unique identifier of the expense\n * @returns ArrayBuffer containing the PDF file data\n */\n async getPdf(expenseId: string): Promise<ArrayBuffer> {\n return this.http.request<ArrayBuffer>({\n method: 'GET',\n url: `${this.basePath}/${encodeURIComponent(expenseId)}/pdf`,\n responseType: 'arraybuffer',\n });\n }\n}\n", "import type { ApiClient } from '../../http';\nimport type { NoteReportItem } from '../../models';\nimport { Resource } from '../Resource';\n\n/**\n * Resource for generating note reports and PDFs.\n * Accesses the Reports API at reports.timesheet.io.\n */\nexport class NoteReportResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/notes');\n }\n\n /**\n * Generate note report data in JSON format.\n * Returns a NoteReportItem entity containing formatted note information\n * including content, attachments, timestamps, and author details.\n * @param noteId Unique identifier of the note\n */\n async get(noteId: string): Promise<NoteReportItem> {\n return this.http.get<NoteReportItem>(`${this.basePath}/${encodeURIComponent(noteId)}`);\n }\n\n /**\n * Generate and download a PDF report for a specific note.\n * The PDF includes note content, metadata, attached images,\n * and formatting according to user settings.\n * @param noteId Unique identifier of the note\n * @returns ArrayBuffer containing the PDF file data\n */\n async getPdf(noteId: string): Promise<ArrayBuffer> {\n return this.http.request<ArrayBuffer>({\n method: 'GET',\n url: `${this.basePath}/${encodeURIComponent(noteId)}/pdf`,\n responseType: 'arraybuffer',\n });\n }\n}\n", "import type { ApiClient } from '../../http';\nimport type {\n CustomExportField,\n CustomExportFieldCreateRequest,\n CustomExportFieldsResponse,\n CustomExportFieldUpdateRequest,\n ExportFieldsResponse,\n ExportParams,\n ExportReportsResponse,\n ExportTemplate,\n ExportTemplateCreateRequest,\n ExportTemplateListParams,\n ExportTemplateParams,\n ExportTemplateUpdateRequest,\n FileResponse,\n Page,\n} from '../../models';\nimport { NavigablePage } from '../../models';\nimport { Resource } from '../Resource';\n\n/**\n * Resource for generating timesheet exports in various formats.\n * Accesses the Reports API at reports.timesheet.io.\n */\nexport class ExportResource extends Resource {\n constructor(client: ApiClient) {\n super(client, '/v1/export');\n }\n\n // ============================================================================\n // Export Generation\n // ============================================================================\n\n /**\n * Generate and download a timesheet export.\n * Creates an export file based on the provided parameters and returns\n * a signed URL to download it. Supports Excel, CSV, and PDF formats.\n * @param params Export configuration parameters\n * @returns FileResponse with download URL\n */\n async generate(params: ExportParams): Promise<FileResponse> {\n return this.http.post<FileResponse>(`${this.basePath}/data`, params);\n }\n\n /**\n * Generate and email a timesheet export.\n * Creates an export file and sends it via email to the specified address.\n * The email field in params must be provided.\n * @param params Export configuration parameters (must include email)\n */\n async send(params: ExportParams): Promise<void> {\n return this.http.post<void>(`${this.basePath}/send`, params);\n }\n\n /**\n * Generate export from a saved template.\n * Creates an export file using a previously saved template with custom\n * start and end dates. The template defines the report type, format,\n * filters, and field selection.\n * @param params Template ID and date range\n * @returns ArrayBuffer containing the export file data\n */\n async generateFromTemplate(params: ExportTemplateParams): Promise<ArrayBuffer> {\n return this.http.request<ArrayBuffer>({\n method: 'POST',\n url: `${this.basePath}/from-template`,\n data: params,\n responseType: 'arraybuffer',\n });\n }\n\n // ============================================================================\n // Export Configuration\n // ============================================================================\n\n /**\n * Get available export fields.\n * Returns the list of available export fields from the field registry.\n * @param scope Optional scope filter: 'project', 'team', 'task', or 'todo' (defaults to 'task')\n */\n async getFields(scope?: 'project' | 'team' | 'task' | 'todo'): Promise<ExportFieldsResponse> {\n return this.http.get<ExportFieldsResponse, Record<string, unknown>>(\n `${this.basePath}/fields`,\n scope ? { scope } : undefined,\n );\n }\n\n /**\n * Get available report types.\n * Returns the list of available export report types with metadata.\n */\n async getReportTypes(): Promise<ExportReportsResponse> {\n return this.http.get<ExportReportsResponse>(`${this.basePath}/report-types`);\n }\n\n // ============================================================================\n // Export Templates\n // ============================================================================\n\n /**\n * Get user's export templates.\n * Returns a paginated list of export templates created by the authenticated user.\n * @param params Optional pagination and sorting parameters\n */\n async listTemplates(params?: ExportTemplateListParams): Promise<NavigablePage<ExportTemplate>> {\n const response = await this.http.get<Page<ExportTemplate>, Record<string, unknown>>(\n `${this.basePath}/templates`,\n params as Record<string, unknown>,\n );\n return new NavigablePage(response, (page) => this.listTemplates({ ...params, page }));\n }\n\n /**\n * Search export templates.\n * Performs an advanced search for export templates based on the provided parameters.\n * @param params Search parameters including filters, pagination, and sorting\n */\n async searchTemplates(params: ExportTemplateListParams): Promise<NavigablePage<ExportTemplate>> {\n const response = await this.http.post<Page<ExportTemplate>>(\n `${this.basePath}/templates/search`,\n params,\n );\n return this.createNavigablePage(response, (page) => this.searchTemplates({ ...params, page }));\n }\n\n /**\n * Create an export template.\n * Creates a new export template from the provided data.\n * @param data Template creation data\n */\n async createTemplate(data: ExportTemplateCreateRequest): Promise<ExportTemplate> {\n return this.http.post<ExportTemplate>(`${this.basePath}/templates`, data);\n }\n\n /**\n * Get a single export template.\n * Retrieves a specific export template by ID with resolved JSON fields.\n * @param templateId Template ID\n */\n async getTemplate(templateId: string): Promise<ExportTemplate> {\n return this.http.get<ExportTemplate>(\n `${this.basePath}/templates/${encodeURIComponent(templateId)}`,\n );\n }\n\n /**\n * Update an export template.\n * Updates an existing export template with new data.\n * @param templateId Template ID\n * @param data Updated template data\n */\n async updateTemplate(\n templateId: string,\n data: ExportTemplateUpdateRequest,\n ): Promise<ExportTemplate> {\n return this.http.put<ExportTemplate>(\n `${this.basePath}/templates/${encodeURIComponent(templateId)}`,\n data,\n );\n }\n\n /**\n * Delete an export template.\n * @param templateId Template ID\n */\n async deleteTemplate(templateId: string): Promise<void> {\n return this.http.delete(`${this.basePath}/templates/${encodeURIComponent(templateId)}`);\n }\n\n // ============================================================================\n // Custom Export Fields\n // ============================================================================\n\n /**\n * Get user's custom export fields.\n * Returns all custom export fields created by the authenticated user.\n * @param scope Optional scope filter: 'TASK', 'PROJECT', or 'TEAM'\n */\n async listCustomFields(scope?: 'TASK' | 'PROJECT' | 'TEAM'): Promise<CustomExportFieldsResponse> {\n return this.http.get<CustomExportFieldsResponse, Record<string, unknown>>(\n `${this.basePath}/custom-fields`,\n scope ? { scope } : undefined,\n );\n }\n\n /**\n * Create a custom export field.\n * Creates a new custom export field that can be used in exports.\n * @param data Custom field creation data\n */\n async createCustomField(data: CustomExportFieldCreateRequest): Promise<CustomExportField> {\n return this.http.post<CustomExportField>(`${this.basePath}/custom-fields`, data);\n }\n\n /**\n * Get a single custom export field.\n * Retrieves a specific custom export field by ID.\n * @param fieldId Field ID\n */\n async getCustomField(fieldId: string): Promise<CustomExportField> {\n return this.http.get<CustomExportField>(\n `${this.basePath}/custom-fields/${encodeURIComponent(fieldId)}`,\n );\n }\n\n /**\n * Update a custom export field.\n * Updates an existing custom export field.\n * @param fieldId Field ID\n * @param data Updated field data\n */\n async updateCustomField(\n fieldId: string,\n data: CustomExportFieldUpdateRequest,\n ): Promise<CustomExportField> {\n return this.http.put<CustomExportField>(\n `${this.basePath}/custom-fields/${encodeURIComponent(fieldId)}`,\n data,\n );\n }\n\n /**\n * Delete a custom export field (soft delete).\n * @param fieldId Field ID\n */\n async deleteCustomField(fieldId: string): Promise<void> {\n return this.http.delete(`${this.basePath}/custom-fields/${encodeURIComponent(fieldId)}`);\n }\n}\n", "import type { ApiClient } from '../../http';\nimport { DocumentReportResource } from './DocumentReportResource';\nimport { TaskReportResource } from './TaskReportResource';\nimport { ExpenseReportResource } from './ExpenseReportResource';\nimport { NoteReportResource } from './NoteReportResource';\nimport { ExportResource } from './ExportResource';\n\n/**\n * Reports API client providing access to PDF generation, exports, and report data.\n *\n * This client accesses the Reports API (reports.timesheet.io) which provides:\n * - Document, task, expense, and note PDF generation\n * - Timesheet exports in Excel, CSV, and PDF formats\n * - Export templates for saving export configurations\n * - Custom export fields for personalized exports\n *\n * @example\n * ```typescript\n * // Access via main client\n * const client = new TimesheetClient({ apiKey: 'your-api-key' });\n *\n * // Generate a document PDF\n * const pdfData = await client.reports.documents.getPdf('doc_123');\n *\n * // Generate a timesheet export\n * const exportResult = await client.reports.export.generate({\n * report: 1,\n * startDate: '2024-01-01',\n * endDate: '2024-01-31',\n * format: 'xlsx'\n * });\n *\n * // Get task report data\n * const taskReport = await client.reports.tasks.get('task_456');\n * ```\n */\nexport class ReportsClient {\n /**\n * Document report generation endpoints.\n * Generate document PDFs, XML (e-invoicing), and report data.\n */\n public readonly documents: DocumentReportResource;\n\n /**\n * Task report generation endpoints.\n * Generate task PDFs and report data.\n */\n public readonly tasks: TaskReportResource;\n\n /**\n * Expense report generation endpoints.\n * Generate expense PDFs and report data.\n */\n public readonly expenses: ExpenseReportResource;\n\n /**\n * Note report generation endpoints.\n * Generate note PDFs and report data.\n */\n public readonly notes: NoteReportResource;\n\n /**\n * Export generation endpoints.\n * Generate timesheet exports, manage templates, and custom fields.\n */\n public readonly export: ExportResource;\n\n /**\n * Creates a new ReportsClient instance.\n * @param apiClient ApiClient configured for the Reports API\n */\n constructor(apiClient: ApiClient) {\n this.documents = new DocumentReportResource(apiClient);\n this.tasks = new TaskReportResource(apiClient);\n this.expenses = new ExpenseReportResource(apiClient);\n this.notes = new NoteReportResource(apiClient);\n this.export = new ExportResource(apiClient);\n }\n}\n", "import { ApiClient } from './http';\nimport type { Authentication } from './auth';\nimport { ApiKeyAuth, OAuth2Auth } from './auth';\nimport type { ClientConfig } from './config';\nimport { RetryConfig } from './config';\nimport type { AxiosInstance } from 'axios';\nimport {\n AbsenceResource,\n AbsenceTypeResource,\n AutomationResource,\n ContractResource,\n ContractTemplateResource,\n DocumentResource,\n EventResource,\n ExpenseResource,\n NoteResource,\n OrganizationResource,\n PauseResource,\n ProfileResource,\n ProjectResource,\n RateResource,\n ReportsClient,\n SettingsResource,\n TagResource,\n TaskResource,\n TeamResource,\n TimerResource,\n TodoResource,\n WebhookResource,\n} from './resources';\n\n// Export all modules\nexport * from './auth';\nexport * from './config';\nexport * from './exceptions';\nexport * from './models';\nexport * from './http';\nexport * from './resources';\n\n/**\n * Main entry point for the Timesheet SDK.\n *\n * @example\n * ```typescript\n * // Using API Key\n * const client = new TimesheetClient({\n * apiKey: 'your-api-key'\n * });\n *\n * // Using OAuth2\n * const client = new TimesheetClient({\n * oauth2Token: 'your-access-token'\n * });\n * ```\n */\nexport class TimesheetClient {\n private readonly apiClient: ApiClient;\n private readonly reportsApiClient: ApiClient;\n\n // Resource APIs\n public readonly organizations: OrganizationResource;\n public readonly teams: TeamResource;\n public readonly projects: ProjectResource;\n public readonly tasks: TaskResource;\n public readonly rates: RateResource;\n public readonly tags: TagResource;\n public readonly expenses: ExpenseResource;\n public readonly notes: NoteResource;\n public readonly pauses: PauseResource;\n public readonly profile: ProfileResource;\n public readonly settings: SettingsResource;\n public readonly automations: AutomationResource;\n public readonly documents: DocumentResource;\n public readonly timer: TimerResource;\n public readonly todos: TodoResource;\n public readonly webhooks: WebhookResource;\n public readonly events: EventResource;\n public readonly absences: AbsenceResource;\n public readonly absenceTypes: AbsenceTypeResource;\n public readonly contracts: ContractResource;\n public readonly contractTemplates: ContractTemplateResource;\n\n /**\n * Reports API for PDF generation, exports, and report data.\n * Provides access to document, task, expense, and note report generation,\n * as well as timesheet exports in various formats.\n *\n * @example\n * ```typescript\n * // Generate a document PDF\n * const pdfData = await client.reports.documents.getPdf('doc_123');\n *\n * // Generate a timesheet export\n * const exportResult = await client.reports.export.generate({\n * report: 1,\n * startDate: '2024-01-01',\n * endDate: '2024-01-31',\n * format: 'xlsx'\n * });\n * ```\n */\n public readonly reports: ReportsClient;\n\n /**\n * Creates a new TimesheetClient instance.\n *\n * @param options Configuration options\n */\n constructor(options: TimesheetClientOptions) {\n const authentication = this.createAuthentication(options);\n const retryConfig = options.retryConfig || RetryConfig.default();\n\n // Main API client (api.timesheet.io)\n const config: ClientConfig = {\n baseUrl: options.baseUrl || 'https://api.timesheet.io',\n authentication,\n retryConfig,\n httpClient: options.httpClient,\n };\n\n this.apiClient = new ApiClient(config);\n\n // Reports API client (reports.timesheet.io)\n const reportsConfig: ClientConfig = {\n baseUrl: options.reportsBaseUrl || 'https://reports.timesheet.io',\n authentication,\n retryConfig,\n httpClient: options.reportsHttpClient,\n };\n\n this.reportsApiClient = new ApiClient(reportsConfig);\n\n // Initialize main API resources\n this.organizations = new OrganizationResource(this.apiClient);\n this.teams = new TeamResource(this.apiClient);\n this.projects = new ProjectResource(this.apiClient);\n this.tasks = new TaskResource(this.apiClient);\n this.rates = new RateResource(this.apiClient);\n this.tags = new TagResource(this.apiClient);\n this.expenses = new ExpenseResource(this.apiClient);\n this.notes = new NoteResource(this.apiClient);\n this.pauses = new PauseResource(this.apiClient);\n this.profile = new ProfileResource(this.apiClient);\n this.settings = new SettingsResource(this.apiClient);\n this.automations = new AutomationResource(this.apiClient);\n this.documents = new DocumentResource(this.apiClient);\n this.timer = new TimerResource(this.apiClient);\n this.todos = new TodoResource(this.apiClient);\n this.webhooks = new WebhookResource(this.apiClient);\n this.events = new EventResource(this.apiClient);\n this.absences = new AbsenceResource(this.apiClient);\n this.absenceTypes = new AbsenceTypeResource(this.apiClient);\n this.contracts = new ContractResource(this.apiClient);\n this.contractTemplates = new ContractTemplateResource(this.apiClient);\n\n // Initialize reports API resources\n this.reports = new ReportsClient(this.reportsApiClient);\n }\n\n private createAuthentication(options: TimesheetClientOptions): Authentication {\n if (options.apiKey) {\n return new ApiKeyAuth(options.apiKey);\n } else if (options.oauth2Token) {\n return new OAuth2Auth(options.oauth2Token);\n } else if (options.oauth2) {\n return new OAuth2Auth(\n options.oauth2.clientId,\n options.oauth2.clientSecret,\n options.oauth2.refreshToken,\n );\n } else if (options.authentication) {\n return options.authentication;\n } else {\n throw new Error('Authentication must be configured');\n }\n }\n}\n\n/**\n * Configuration options for TimesheetClient.\n */\nexport interface TimesheetClientOptions {\n /**\n * API key for authentication.\n */\n apiKey?: string;\n\n /**\n * OAuth2 bearer token for authentication.\n */\n oauth2Token?: string;\n\n /**\n * OAuth2 configuration with refresh capability.\n */\n oauth2?: {\n clientId: string;\n clientSecret: string;\n refreshToken: string;\n };\n\n /**\n * Custom authentication implementation.\n */\n authentication?: Authentication;\n\n /**\n * Custom base URL for the main API.\n * @default 'https://api.timesheet.io'\n */\n baseUrl?: string;\n\n /**\n * Custom base URL for the Reports API.\n * @default 'https://reports.timesheet.io'\n */\n reportsBaseUrl?: string;\n\n /**\n * Custom retry configuration.\n */\n retryConfig?: RetryConfig;\n\n /**\n * Custom HTTP client (axios instance) for the main API.\n */\n httpClient?: AxiosInstance;\n\n /**\n * Custom HTTP client (axios instance) for the Reports API.\n */\n reportsHttpClient?: AxiosInstance;\n}\n\n// Export convenience function\nexport function createClient(options: TimesheetClientOptions): TimesheetClient {\n return new TimesheetClient(options);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["axios", "TimesheetApiError", "_TimesheetApiError", "message", "statusCode", "responseBody", "errorCode", "fullMessage", "TimesheetAuthError", "TimesheetApiError", "message", "statusCode", "responseBody", "TimesheetRateLimitError", "TimesheetApiError", "message", "retryAfter", "epochSeconds", "date", "ApiClient", "config", "axios", "authHeaders", "key", "value", "lastError", "retryConfig", "attempt", "error", "errorData", "TimesheetAuthError", "retryAfter", "TimesheetRateLimitError", "status", "delay", "TimesheetApiError", "path", "params", "data", "formData", "ms", "resolve", "ApiKeyAuth", "apiKey", "config", "axios", "jwt", "_OAuth2Auth", "accessTokenOrClientId", "clientSecret", "refreshToken", "config", "response", "error", "message", "clientId", "authorizationCode", "redirectUri", "accessToken", "state", "params", "decoded", "OAuth2Auth", "axios", "jwt", "randomBytes", "createHash", "generateCodeVerifier", "length", "buffer", "base64UrlEncode", "generateCodeChallenge", "codeVerifier", "method", "hash", "generatePkceCodePair", "verifierLength", "codeChallenge", "isValidCodeVerifier", "_OAuth21Auth", "accessTokenOrOptions", "options", "config", "params", "response", "axios", "error", "message", "clientId", "clientSecret", "authorizationCode", "redirectUri", "codeVerifier", "resource", "tokenEndpoint", "effectiveTokenEndpoint", "isValidCodeVerifier", "accessToken", "refreshToken", "codeChallenge", "codeChallengeMethod", "state", "scope", "authorizationEndpoint", "effectiveAuthEndpoint", "method", "generatePkceCodePair", "decoded", "jwt", "OAuth21Auth", "axios", "_OAuthDiscovery", "options", "issuerUrl", "normalizedUrl", "cached", "authServerMetadata", "result", "url", "response", "error", "message", "resourceUrl", "entry", "expiresAt", "metadata", "config", "OAuthDiscovery", "defaultDiscovery", "getDefaultDiscovery", "discoverOAuth", "RetryConfig", "_RetryConfig", "options", "NavigablePage", "data", "nextPageLoader", "currentPage", "item", "allItems", "WebhookEvents", "combineWebhookEvents", "events", "Resource", "http", "config", "page", "nextPageLoader", "NavigablePage", "OrganizationResource", "Resource", "client", "params", "response", "NavigablePage", "page", "data", "id", "organizationId", "permissionId", "TeamResource", "Resource", "client", "params", "response", "NavigablePage", "page", "data", "id", "teamId", "memberId", "members", "ProjectResource", "Resource", "client", "params", "response", "NavigablePage", "page", "data", "id", "projectId", "memberId", "registrations", "members", "memberIds", "dayjs", "utc", "timezone", "customParseFormat", "TIMESTAMP_FORMAT", "TIMESTAMP_REGEX", "DateUtils", "timestamp", "input", "TaskResource", "Resource", "client", "params", "response", "page", "data", "formattedData", "DateUtils", "id", "RateResource", "Resource", "client", "params", "response", "NavigablePage", "page", "data", "id", "TagResource", "Resource", "client", "params", "items", "NavigablePage", "page", "data", "id", "response", "ExpenseResource", "Resource", "client", "params", "response", "NavigablePage", "page", "data", "formattedData", "DateUtils", "id", "file", "formData", "expenseData", "NoteResource", "Resource", "client", "params", "response", "NavigablePage", "page", "data", "formattedData", "DateUtils", "id", "file", "formData", "noteData", "PauseResource", "Resource", "client", "params", "response", "NavigablePage", "page", "data", "formattedData", "DateUtils", "id", "ProfileResource", "http", "data", "SettingsResource", "http", "data", "AutomationResource", "Resource", "client", "params", "response", "NavigablePage", "page", "data", "id", "DocumentResource", "Resource", "client", "params", "category", "rest", "query", "response", "NavigablePage", "page", "data", "id", "TimerResource", "http", "data", "formattedData", "DateUtils", "TodoResource", "Resource", "client", "params", "items", "NavigablePage", "page", "data", "formattedData", "DateUtils", "id", "response", "WebhookResource", "Resource", "client", "params", "response", "NavigablePage", "page", "data", "id", "EventResource", "Resource", "client", "options", "url", "headers", "abortController", "isConnected", "eventHandlers", "subscription", "event", "handler", "connectionId", "error", "signal", "response", "reader", "decoder", "buffer", "eventType", "eventData", "eventId", "done", "result", "lines", "line", "_eventId", "data", "connectedData", "AbsenceResource", "Resource", "client", "organizationId", "params", "response", "page", "data", "id", "AbsenceTypeResource", "Resource", "client", "organizationId", "params", "response", "page", "data", "id", "ContractResource", "Resource", "client", "organizationId", "params", "response", "page", "data", "id", "ContractTemplateResource", "Resource", "client", "organizationId", "params", "response", "page", "data", "id", "DocumentReportResource", "Resource", "client", "documentId", "TaskReportResource", "Resource", "client", "taskId", "ExpenseReportResource", "Resource", "client", "expenseId", "NoteReportResource", "Resource", "client", "noteId", "ExportResource", "Resource", "client", "params", "scope", "response", "NavigablePage", "page", "data", "templateId", "fieldId", "ReportsClient", "apiClient", "DocumentReportResource", "TaskReportResource", "ExpenseReportResource", "NoteReportResource", "ExportResource", "TimesheetClient", "options", "authentication", "retryConfig", "RetryConfig", "config", "ApiClient", "reportsConfig", "OrganizationResource", "TeamResource", "ProjectResource", "TaskResource", "RateResource", "TagResource", "ExpenseResource", "NoteResource", "PauseResource", "ProfileResource", "SettingsResource", "AutomationResource", "DocumentResource", "TimerResource", "TodoResource", "WebhookResource", "EventResource", "AbsenceResource", "AbsenceTypeResource", "ContractResource", "ContractTemplateResource", "ReportsClient", "ApiKeyAuth", "OAuth2Auth", "createClient"]
|
|
7
7
|
}
|