@timesheet/sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";var Y=Object.create;var z=Object.defineProperty;var V=Object.getOwnPropertyDescriptor;var B=Object.getOwnPropertyNames;var J=Object.getPrototypeOf,Z=Object.prototype.hasOwnProperty;var G=(r,e)=>{for(var t in e)z(r,t,{get:e[t],enumerable:!0})},_=(r,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let m of B(e))!Z.call(r,m)&&m!==t&&z(r,m,{get:()=>e[m],enumerable:!(s=V(e,m))||s.enumerable});return r};var c=(r,e,t)=>(t=r!=null?Y(J(r)):{},_(e||!r||!r.__esModule?z(t,"default",{value:r,enumerable:!0}):t,r)),X=r=>_(z({},"__esModule",{value:!0}),r);var se={};G(se,{ApiClient:()=>I,ApiKeyAuth:()=>S,AutomationResource:()=>A,DocumentResource:()=>$,ExpenseResource:()=>C,NavigablePage:()=>o,NoteResource:()=>w,OAuth2Auth:()=>d,OrganizationResource:()=>f,PauseResource:()=>D,ProfileResource:()=>k,ProjectResource:()=>y,RateResource:()=>R,Resource:()=>i,RetryConfig:()=>O,SettingsResource:()=>v,TagResource:()=>x,TaskResource:()=>b,TeamResource:()=>T,TimerResource:()=>N,TimesheetApiError:()=>h,TimesheetAuthError:()=>E,TimesheetClient:()=>j,TimesheetRateLimitError:()=>L,TodoResource:()=>U,WebhookResource:()=>q,createClient:()=>te});module.exports=X(se);var l=c(require("axios"));var h=class r extends Error{constructor(e,t,s,m){let n=t?m?`${e} (HTTP ${t}, Code: ${m})`:`${e} (HTTP ${t})`:e;super(n),this.name="TimesheetApiError",this.statusCode=t,this.responseBody=s,this.errorCode=m,typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,r)}};var E=class extends h{constructor(e,t=401,s){super(e,t,s,"authentication_error"),this.name="TimesheetAuthError"}};var L=class extends h{constructor(e,t){super(e,429,void 0,"rate_limit_exceeded"),this.name="TimesheetRateLimitError",this.retryAfter=t}getRetryAfterDate(){if(!this.retryAfter)return null;let e=Number(this.retryAfter);if(!isNaN(e))return new Date(e*1e3);let t=new Date(this.retryAfter);return isNaN(t.getTime())?null:t}};var I=class{constructor(e){this.config=e,this.httpClient=e.httpClient||l.default.create({baseURL:e.baseUrl,timeout:3e4,headers:{"User-Agent":"Timesheet-TypeScript-SDK/1.0.0","Content-Type":"application/json"}}),this.httpClient.interceptors.request.use(async t=>{if(t.url!=="/oauth/token"&&this.config.authentication){let s=await this.config.authentication.getAuthHeaders();if(s)for(let[m,n]of Object.entries(s))t.headers.set(m,n)}return t})}async request(e){let t=null,s=this.config.retryConfig;for(let m=0;m<=s.maxRetries;m++)try{return(await this.httpClient.request(e)).data}catch(n){if(t=n,l.default.isAxiosError(n)&&n.response?.status===401){let p=n.response.data;throw new E(p?.message||"Authentication failed",401,JSON.stringify(p))}if(l.default.isAxiosError(n)&&n.response?.status===429){let p=n.response.headers["retry-after"];throw new L("Rate limit exceeded",p)}let P=l.default.isAxiosError(n)?n.response?.status:void 0;if(m<s.maxRetries&&P&&s.retryableStatusCodes.includes(P)){let p=Math.min(s.initialDelay*Math.pow(s.backoffMultiplier,m),s.maxDelay);await this.sleep(p);continue}if(l.default.isAxiosError(n)){let p=n.response?.data;throw new h(p?.message||n.message,n.response?.status,JSON.stringify(p),p?.code)}else throw n instanceof Error?new h(n.message):new h("Unknown error occurred")}throw t||new Error("Unknown error")}async get(e,t){return this.request({method:"GET",url:e,params:t})}async post(e,t,s){return this.request({method:"POST",url:e,data:t,params:s})}async put(e,t,s){return this.request({method:"PUT",url:e,data:t,params:s})}async delete(e,t){return this.request({method:"DELETE",url:e,params:t})}sleep(e){return new Promise(t=>setTimeout(t,e))}};var S=class{constructor(e){this.apiKey=e;if(e===null)throw new Error("API key cannot be null");if(e===void 0)throw new Error("API key cannot be undefined");if(!e)throw new Error("API key cannot be empty");if(typeof e!="string")throw new Error("API key must be a string");if(e.trim().length===0)throw new Error("API key cannot be empty or whitespace");if(!this.isValidFormat(e))throw new Error("Invalid API key format")}isValidFormat(e){return/^ts_[a-zA-Z0-9]+\.[a-zA-Z0-9]+$/.test(e)}applyAuth(e){e.headers||(e.headers={}),e.headers.Authorization=`ApiKey ${this.apiKey}`}needsRefresh(){return!1}async refresh(){throw new Error("API keys cannot be refreshed")}async getAuthHeaders(){return{Authorization:`ApiKey ${this.apiKey}`}}isValid(){return typeof this.apiKey=="string"&&this.apiKey.trim().length>0&&this.isValidFormat(this.apiKey)}};var M=c(require("axios")),W=c(require("jsonwebtoken")),u=class u{constructor(e,t,s){t&&s?(this.clientId=e,this.clientSecret=t,this.refreshToken=s,this.accessToken=""):(this.accessToken=e,this.parseTokenExpiry())}applyAuth(e){e.headers||(e.headers={}),e.headers.Authorization=`Bearer ${this.accessToken}`}needsRefresh(){return this.refreshToken&&!this.accessToken?!0:!this.refreshToken||!this.tokenExpiry?!1:new Date(Date.now()+5*60*1e3)>=this.tokenExpiry}async refresh(){if(!this.refreshToken)throw new Error("Cannot refresh without refresh token");if(this.refreshPromise)return this.refreshPromise;this.refreshPromise=this.performRefresh();try{await this.refreshPromise}finally{this.refreshPromise=void 0}}async performRefresh(){try{let e=await M.default.post(u.TOKEN_ENDPOINT,new URLSearchParams({grant_type:"refresh_token",refresh_token:this.refreshToken,client_id:this.clientId,client_secret:this.clientSecret}),{headers:{"Content-Type":"application/x-www-form-urlencoded"}});this.accessToken=e.data.access_token,e.data.refresh_token&&(this.refreshToken=e.data.refresh_token),this.parseTokenExpiry()}catch(e){let t=e instanceof Error?e.message:"Unknown error";throw new Error(`Failed to refresh OAuth2 token: ${t}`)}}async getAuthHeaders(){return this.needsRefresh()&&await this.refresh(),{Authorization:`Bearer ${this.accessToken}`}}static async fromAuthorizationCode(e,t,s,m){try{let n=await M.default.post(u.TOKEN_ENDPOINT,new URLSearchParams({grant_type:"authorization_code",code:s,redirect_uri:m,client_id:e,client_secret:t}),{headers:{"Content-Type":"application/x-www-form-urlencoded"}}),P=n.data.access_token,p=n.data.refresh_token;return p?new u(e,t,p):new u(P)}catch(n){let P=n instanceof Error?n.message:"Unknown error";throw new Error(`Failed to exchange authorization code: ${P}`)}}static buildAuthorizationUrl(e,t,s){let m=new URLSearchParams({client_id:e,redirect_uri:t,response_type:"code"});return s&&m.append("state",s),`https://api.timesheet.io/oauth2/auth?${m.toString()}`}parseTokenExpiry(){try{let e=W.default.decode(this.accessToken);e&&e.exp&&(this.tokenExpiry=new Date(e.exp*1e3))}catch{this.tokenExpiry=new Date(Date.now()+60*60*1e3)}}};u.TOKEN_ENDPOINT="https://api.timesheet.io/oauth2/token";var d=u;var O=class r{constructor(e={}){this.maxRetries=e.maxRetries??3,this.initialDelay=e.initialDelay??100,this.maxDelay=e.maxDelay??1e4,this.backoffMultiplier=e.backoffMultiplier??2,this.retryableStatusCodes=e.retryableStatusCodes??[429,502,503,504]}static default(){return new r}};var o=class{constructor(e,t){this.items=e.items,this.params=e.params,this.nextPageLoader=t}get totalPages(){return Math.ceil((this.params?.count||0)/(this.params?.limit||25))}get hasNextPage(){return(this.params?.page||1)<this.totalPages}async nextPage(){if(!this.hasNextPage)throw new Error("No more pages available");if(!this.nextPageLoader)throw new Error("Next page loader not configured");return this.nextPageLoader((this.params.page||1)+1)}async*[Symbol.asyncIterator](){let e=this;for(;;){for(let t of e.items)yield t;if(!e.hasNextPage)break;e=await e.nextPage()}}async toArray(){let e=[];for await(let t of this)e.push(t);return e}};var i=class{constructor(e,t){this.http=e;typeof t=="string"?this.basePath=t:this.basePath=t.basePath}createNavigablePage(e,t){return new o(e,t)}};var f=class extends i{constructor(e){super(e,"/v1/organizations")}async list(e){let t=await this.http.get(this.basePath,e);return new o(t,s=>this.list({...e,page:s}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,s=>this.search({...e,page:s}))}};var T=class extends i{constructor(e){super(e,"/v1/teams")}async list(e){let t=await this.http.get(this.basePath,e);return new o(t,s=>this.list({...e,page:s}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,s=>this.search({...e,page:s}))}async listMembers(e,t){let s=await this.http.post(`${this.basePath}/${e}/members/list`,t);return this.createNavigablePage(s,m=>this.listMembers(e,{...t,page:m}))}async getMember(e,t){return this.http.get(`${this.basePath}/${e}/members/${t}`)}async getColleagues(e){let t=await this.http.post(`${this.basePath}/getColleagues`,e);return this.createNavigablePage(t,s=>this.getColleagues({...e,page:s}))}};var y=class extends i{constructor(e){super(e,"/v1/projects")}async list(e){let t=await this.http.get(this.basePath,e);return new o(t,s=>this.list({...e,page:s}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,s=>this.search({...e,page:s}))}};var g=c(require("dayjs")),F=c(require("dayjs/plugin/utc")),K=c(require("dayjs/plugin/timezone")),H=c(require("dayjs/plugin/customParseFormat"));g.default.extend(F.default);g.default.extend(K.default);g.default.extend(H.default);var Q="YYYY-MM-DDTHH:mm:ssZ",ee=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{2}:\d{2}$/,a={isValidTimestampFormat(r){return ee.test(r)},formatTimestamp(r){return typeof r=="string"&&this.isValidTimestampFormat(r)?r:(0,g.default)(r||new Date).format(Q)},parseTimestamp(r){return(0,g.default)(r).toDate()},formatDate(r){return(0,g.default)(r||new Date).format("YYYY-MM-DD")},now(){return this.formatTimestamp()}};var b=class extends i{constructor(e){super(e,"/v1/tasks")}async create(e){let t={...e,startDateTime:a.formatTimestamp(e.startDateTime),endDateTime:e.endDateTime?a.formatTimestamp(e.endDateTime):void 0};return this.http.post(this.basePath,t)}async update(e,t){let s={...t,startDateTime:t.startDateTime?a.formatTimestamp(t.startDateTime):void 0,endDateTime:t.endDateTime?a.formatTimestamp(t.endDateTime):void 0};return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,s)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,s=>this.search({...e,page:s}))}async updateStatus(e){return this.http.put(`${this.basePath}/updateStatus`,e)}async updateTimes(e){let t={...e,startDateTime:a.formatTimestamp(e.startDateTime),endDateTime:a.formatTimestamp(e.endDateTime)};return this.http.put(`${this.basePath}/updateTimes`,t)}};var R=class extends i{constructor(e){super(e,"/v1/rates")}async list(e){let t=await this.http.get(this.basePath,e);return new o(t,s=>this.list({...e,page:s}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,s=>this.search({...e,page:s}))}};var x=class extends i{constructor(e){super(e,"/v1/tags")}async list(e){let t=await this.http.get(this.basePath,e);return new o(t,s=>this.list({...e,page:s}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,s=>this.search({...e,page:s}))}};var C=class extends i{constructor(e){super(e,"/v1/expenses")}async list(e){let t=await this.http.get(this.basePath,e);return new o(t,s=>this.list({...e,page:s}))}async create(e){let t={...e,dateTime:a.formatTimestamp(e.dateTime)};return this.http.post(this.basePath,t)}async update(e,t){let s={...t,dateTime:t.dateTime?a.formatTimestamp(t.dateTime):void 0};return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,s)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,s=>this.search({...e,page:s}))}async updateStatus(e,t){return this.http.put(`${this.basePath}/${e}/status`,t)}};var w=class extends i{constructor(e){super(e,"/v1/notes")}async list(e){let t=await this.http.get(this.basePath,e);return new o(t,s=>this.list({...e,page:s}))}async create(e){let t={...e,dateTime:a.formatTimestamp(e.dateTime)};return this.http.post(this.basePath,t)}async update(e,t){let s={...t,dateTime:a.formatTimestamp(t.dateTime)};return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,s)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,s=>this.search({...e,page:s}))}};var D=class extends i{constructor(e){super(e,"/v1/pauses")}async list(e){let t=await this.http.get(this.basePath,e);return new o(t,s=>this.list({...e,page:s}))}async create(e){let t={...e,startDateTime:a.formatTimestamp(e.startDateTime),endDateTime:a.formatTimestamp(e.endDateTime)};return this.http.post(this.basePath,t)}async update(e,t){let s={...t,startDateTime:a.formatTimestamp(t.startDateTime),endDateTime:a.formatTimestamp(t.endDateTime)};return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,s)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,s=>this.search({...e,page:s}))}};var k=class{constructor(e){this.http=e}async getProfile(){return this.http.get("/v1/profiles/me")}async updateProfile(e){return this.http.put("/v1/profiles/me",e)}};var v=class{constructor(e){this.http=e}async get(){return this.http.get("/v1/settings")}async update(e){return this.http.put("/v1/settings",e)}};var A=class extends i{constructor(e){super(e,"/v1/automations")}async list(e){let t=await this.http.get(this.basePath,e);return new o(t,s=>this.list({...e,page:s}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,s=>this.search({...e,page:s}))}};var $=class extends i{constructor(e){super(e,"/v1/documents")}async list(e){let t=await this.http.get(this.basePath,e);return new o(t,s=>this.list({...e,page:s}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,s=>this.search({...e,page:s}))}};var N=class{constructor(e){this.http=e}async get(){return this.http.get("/v1/timer")}async start(e){let t={...e,startDateTime:e.startDateTime?a.formatTimestamp(e.startDateTime):a.formatTimestamp()};return this.http.post("/v1/timer/start",t)}async stop(e){let t=e?{...e,endDateTime:e.endDateTime?a.formatTimestamp(e.endDateTime):a.formatTimestamp()}:{endDateTime:a.formatTimestamp()};return this.http.post("/v1/timer/stop",t)}async pause(e){let t=e?{...e,startDateTime:e.startDateTime?a.formatTimestamp(e.startDateTime):a.formatTimestamp()}:{startDateTime:a.formatTimestamp()};return this.http.post("/v1/timer/pause",t)}async resume(e){let t=e?{...e,endDateTime:e.endDateTime?a.formatTimestamp(e.endDateTime):a.formatTimestamp()}:{endDateTime:a.formatTimestamp()};return this.http.post("/v1/timer/resume",t)}async update(e){let t={...e,startDateTime:e.startDateTime?a.formatTimestamp(e.startDateTime):void 0};return this.http.put("/v1/timer/update",t)}};var U=class extends i{constructor(e){super(e,"/v1/todos")}async list(e){let t=await this.http.get(this.basePath,e);return new o(t,s=>this.list({...e,page:s}))}async create(e){let t={...e,dueDate:e.dueDate?a.formatTimestamp(e.dueDate):void 0};return this.http.post(this.basePath,t)}async update(e,t){let s={...t,dueDate:t.dueDate?a.formatTimestamp(t.dueDate):void 0};return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,s)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,s=>this.search({...e,page:s}))}};var q=class extends i{constructor(e){super(e,"/v1/webhooks")}async list(e){let t=await this.http.get(this.basePath,e);return new o(t,s=>this.list({...e,page:s}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,s=>this.search({...e,page:s}))}};var j=class{constructor(e){let t=this.createAuthentication(e),s={baseUrl:e.baseUrl||"https://api.timesheet.io",authentication:t,retryConfig:e.retryConfig||O.default(),httpClient:e.httpClient};this.apiClient=new I(s),this.organizations=new f(this.apiClient),this.teams=new T(this.apiClient),this.projects=new y(this.apiClient),this.tasks=new b(this.apiClient),this.rates=new R(this.apiClient),this.tags=new x(this.apiClient),this.expenses=new C(this.apiClient),this.notes=new w(this.apiClient),this.pauses=new D(this.apiClient),this.profile=new k(this.apiClient),this.settings=new v(this.apiClient),this.automations=new A(this.apiClient),this.documents=new $(this.apiClient),this.timer=new N(this.apiClient),this.todos=new U(this.apiClient),this.webhooks=new q(this.apiClient)}createAuthentication(e){if(e.apiKey)return new S(e.apiKey);if(e.oauth2Token)return new d(e.oauth2Token);if(e.oauth2)return new d(e.oauth2.clientId,e.oauth2.clientSecret,e.oauth2.refreshToken);if(e.authentication)return e.authentication;throw new Error("Authentication must be configured")}};function te(r){return new j(r)}0&&(module.exports={ApiClient,ApiKeyAuth,AutomationResource,DocumentResource,ExpenseResource,NavigablePage,NoteResource,OAuth2Auth,OrganizationResource,PauseResource,ProfileResource,ProjectResource,RateResource,Resource,RetryConfig,SettingsResource,TagResource,TaskResource,TeamResource,TimerResource,TimesheetApiError,TimesheetAuthError,TimesheetClient,TimesheetRateLimitError,TodoResource,WebhookResource,createClient});
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../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/config/RetryConfig.ts","../src/models/Page.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"],"sourcesContent":["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 ExpenseResource,\n NoteResource,\n OrganizationResource,\n PauseResource,\n ProfileResource,\n ProjectResource,\n RateResource,\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\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\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\n const config: ClientConfig = {\n baseUrl: options.baseUrl || 'https://api.timesheet.io',\n authentication,\n retryConfig: options.retryConfig || RetryConfig.default(),\n httpClient: options.httpClient,\n };\n\n this.apiClient = new ApiClient(config);\n\n // Initialize 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 }\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 API.\n * @default 'https://api.timesheet.io'\n */\n baseUrl?: string;\n\n /**\n * Custom retry configuration.\n */\n retryConfig?: RetryConfig;\n\n /**\n * Custom HTTP client (axios instance).\n */\n httpClient?: AxiosInstance;\n}\n\n// Export convenience function\nexport function createClient(options: TimesheetClientOptions): TimesheetClient {\n return new TimesheetClient(options);\n}\n","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 * 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 * 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","/**\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 { 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±HH: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 ±HH: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 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","import type { ApiClient } from '../http';\nimport type { Note, NoteCreateRequest, NoteListParams, NoteUpdateRequest, Page } 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","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"],"mappings":"0jBAAA,IAAAA,GAAA,GAAAC,EAAAD,GAAA,eAAAE,EAAA,eAAAC,EAAA,uBAAAC,EAAA,qBAAAC,EAAA,oBAAAC,EAAA,kBAAAC,EAAA,iBAAAC,EAAA,eAAAC,EAAA,yBAAAC,EAAA,kBAAAC,EAAA,oBAAAC,EAAA,oBAAAC,EAAA,iBAAAC,EAAA,aAAAC,EAAA,gBAAAC,EAAA,qBAAAC,EAAA,gBAAAC,EAAA,iBAAAC,EAAA,iBAAAC,EAAA,kBAAAC,EAAA,sBAAAC,EAAA,uBAAAC,EAAA,oBAAAC,EAAA,4BAAAC,EAAA,iBAAAC,EAAA,oBAAAC,EAAA,iBAAAC,KAAA,eAAAC,EAAA7B,ICCA,IAAA8B,EAAkB,oBCEX,IAAMC,EAAN,MAAMC,UAA0B,KAAM,CAa3C,YAAYC,EAAiBC,EAAqBC,EAAuBC,EAAoB,CAC3F,IAAMC,EAAcH,EAChBE,EACE,GAAGH,CAAO,UAAUC,CAAU,WAAWE,CAAS,IAClD,GAAGH,CAAO,UAAUC,CAAU,IAChCD,EAEJ,MAAMI,CAAW,EAEjB,KAAK,KAAO,oBACZ,KAAK,WAAaH,EAClB,KAAK,aAAeC,EACpB,KAAK,UAAYC,EAGb,OAAO,MAAM,mBAAsB,YACrC,MAAM,kBAAkB,KAAMJ,CAAiB,CAEnD,CACF,EC9BO,IAAMM,EAAN,cAAiCC,CAAkB,CAQxD,YAAYC,EAAiBC,EAAqB,IAAKC,EAAuB,CAC5E,MAAMF,EAASC,EAAYC,EAAc,sBAAsB,EAC/D,KAAK,KAAO,oBACd,CACF,ECZO,IAAMC,EAAN,cAAsCC,CAAkB,CAS7D,YAAYC,EAAiBC,EAAqB,CAChD,MAAMD,EAAS,IAAK,OAAW,qBAAqB,EACpD,KAAK,KAAO,0BACZ,KAAK,WAAaC,CACpB,CAOA,mBAAiC,CAC/B,GAAI,CAAC,KAAK,WACR,OAAO,KAIT,IAAMC,EAAe,OAAO,KAAK,UAAU,EAC3C,GAAI,CAAC,MAAMA,CAAY,EACrB,OAAO,IAAI,KAAKA,EAAe,GAAI,EAIrC,IAAMC,EAAO,IAAI,KAAK,KAAK,UAAU,EACrC,OAAK,MAAMA,EAAK,QAAQ,CAAC,EAIlB,KAHEA,CAIX,CACF,EH/BO,IAAMC,EAAN,KAAgB,CAIrB,YAAYC,EAAsB,CAChC,KAAK,OAASA,EACd,KAAK,WACHA,EAAO,YACP,EAAAC,QAAM,OAAO,CACX,QAASD,EAAO,QAChB,QAAS,IACT,QAAS,CACP,aAAc,iCACd,eAAgB,kBAClB,CACF,CAAC,EAGH,KAAK,WAAW,aAAa,QAAQ,IAAI,MAAOA,GAAW,CAEzD,GAAIA,EAAO,MAAQ,gBAAkB,KAAK,OAAO,eAAgB,CAC/D,IAAME,EAAc,MAAM,KAAK,OAAO,eAAe,eAAe,EACpE,GAAIA,EAEF,OAAW,CAACC,EAAKC,CAAK,IAAK,OAAO,QAAQF,CAAW,EACnDF,EAAO,QAAQ,IAAIG,EAAKC,CAAK,CAGnC,CAEA,OAAOJ,CACT,CAAC,CACH,CAKA,MAAM,QAAWA,EAAwC,CACvD,IAAIK,EAA0B,KACxBC,EAAc,KAAK,OAAO,YAEhC,QAASC,EAAU,EAAGA,GAAWD,EAAY,WAAYC,IACvD,GAAI,CAEF,OADiB,MAAM,KAAK,WAAW,QAAWP,CAAM,GACxC,IAClB,OAASQ,EAAO,CAId,GAHAH,EAAYG,EAGR,EAAAP,QAAM,aAAgCO,CAAK,GAAKA,EAAM,UAAU,SAAW,IAAK,CAClF,IAAMC,EAAYD,EAAM,SAAS,KACjC,MAAM,IAAIE,EACRD,GAAW,SAAW,wBACtB,IACA,KAAK,UAAUA,CAAS,CAC1B,CACF,CAGA,GAAI,EAAAR,QAAM,aAAaO,CAAK,GAAKA,EAAM,UAAU,SAAW,IAAK,CAC/D,IAAMG,EAAaH,EAAM,SAAS,QAAQ,aAAa,EACvD,MAAM,IAAII,EAAwB,sBAAuBD,CAAU,CACrE,CAGA,IAAME,EAAS,EAAAZ,QAAM,aAAaO,CAAK,EAAIA,EAAM,UAAU,OAAS,OACpE,GACED,EAAUD,EAAY,YACtBO,GACAP,EAAY,qBAAqB,SAASO,CAAM,EAChD,CAEA,IAAMC,EAAQ,KAAK,IACjBR,EAAY,aAAe,KAAK,IAAIA,EAAY,kBAAmBC,CAAO,EAC1ED,EAAY,QACd,EAEA,MAAM,KAAK,MAAMQ,CAAK,EACtB,QACF,CAGA,GAAI,EAAAb,QAAM,aAAgCO,CAAK,EAAG,CAChD,IAAMC,EAAYD,EAAM,UAAU,KAClC,MAAM,IAAIO,EACRN,GAAW,SAAWD,EAAM,QAC5BA,EAAM,UAAU,OAChB,KAAK,UAAUC,CAAS,EACxBA,GAAW,IACb,CACF,KAAO,OAAID,aAAiB,MACpB,IAAIO,EAAkBP,EAAM,OAAO,EAEnC,IAAIO,EAAkB,wBAAwB,CAExD,CAIF,MAAMV,GAAa,IAAI,MAAM,eAAe,CAC9C,CAKA,MAAM,IAAoCW,EAAcC,EAAwB,CAC9E,OAAO,KAAK,QAAW,CACrB,OAAQ,MACR,IAAKD,EACL,OAAQC,CACV,CAAC,CACH,CAKA,MAAM,KAAqCD,EAAcE,EAAgBD,EAAwB,CAC/F,OAAO,KAAK,QAAW,CACrB,OAAQ,OACR,IAAKD,EACL,KAAAE,EACA,OAAQD,CACV,CAAC,CACH,CAKA,MAAM,IAAoCD,EAAcE,EAAgBD,EAAwB,CAC9F,OAAO,KAAK,QAAW,CACrB,OAAQ,MACR,IAAKD,EACL,KAAAE,EACA,OAAQD,CACV,CAAC,CACH,CAKA,MAAM,OAAuCD,EAAcC,EAAwB,CACjF,OAAO,KAAK,QAAW,CACrB,OAAQ,SACR,IAAKD,EACL,OAAQC,CACV,CAAC,CACH,CAKQ,MAAME,EAA2B,CACvC,OAAO,IAAI,QAASC,GAAY,WAAWA,EAASD,CAAE,CAAC,CACzD,CACF,EI9JO,IAAME,EAAN,KAA2C,CAChD,YAA6BC,EAAgB,CAAhB,YAAAA,EAC3B,GAAIA,IAAW,KACb,MAAM,IAAI,MAAM,wBAAwB,EAE1C,GAAIA,IAAW,OACb,MAAM,IAAI,MAAM,6BAA6B,EAE/C,GAAI,CAACA,EACH,MAAM,IAAI,MAAM,yBAAyB,EAE3C,GAAI,OAAOA,GAAW,SACpB,MAAM,IAAI,MAAM,0BAA0B,EAE5C,GAAIA,EAAO,KAAK,EAAE,SAAW,EAC3B,MAAM,IAAI,MAAM,uCAAuC,EAIzD,GAAI,CAAC,KAAK,cAAcA,CAAM,EAC5B,MAAM,IAAI,MAAM,wBAAwB,CAE5C,CAEQ,cAAcA,EAAyB,CAG7C,MADsB,kCACD,KAAKA,CAAM,CAClC,CAEA,UAAUC,EAAkC,CACrCA,EAAO,UACVA,EAAO,QAAU,CAAC,GAEpBA,EAAO,QAAQ,cAAmB,UAAU,KAAK,MAAM,EACzD,CAEA,cAAwB,CAEtB,MAAO,EACT,CAGA,MAAM,SAAyB,CAC7B,MAAM,IAAI,MAAM,8BAA8B,CAChD,CAGA,MAAM,gBAAkD,CACtD,MAAO,CACL,cAAe,UAAU,KAAK,MAAM,EACtC,CACF,CAEA,SAAmB,CACjB,OACE,OAAO,KAAK,QAAW,UACvB,KAAK,OAAO,KAAK,EAAE,OAAS,GAC5B,KAAK,cAAc,KAAK,MAAM,CAElC,CACF,ECrEA,IAAAC,EAAkB,oBAClBC,EAAgB,2BAQHC,EAAN,MAAMA,CAAqC,CA0BhD,YAAYC,EAA+BC,EAAuBC,EAAuB,CACnFD,GAAgBC,GAElB,KAAK,SAAWF,EAChB,KAAK,aAAeC,EACpB,KAAK,aAAeC,EACpB,KAAK,YAAc,KAInB,KAAK,YAAcF,EACnB,KAAK,iBAAiB,EAE1B,CAEA,UAAUG,EAAkC,CACrCA,EAAO,UACVA,EAAO,QAAU,CAAC,GAEpBA,EAAO,QAAQ,cAAmB,UAAU,KAAK,WAAW,EAC9D,CAEA,cAAwB,CAEtB,OAAI,KAAK,cAAgB,CAAC,KAAK,YACtB,GAGL,CAAC,KAAK,cAAgB,CAAC,KAAK,YACvB,GAGkB,IAAI,KAAK,KAAK,IAAI,EAAI,EAAI,GAAK,GAAI,GACjC,KAAK,WACpC,CAEA,MAAM,SAAyB,CAC7B,GAAI,CAAC,KAAK,aACR,MAAM,IAAI,MAAM,sCAAsC,EAIxD,GAAI,KAAK,eACP,OAAO,KAAK,eAGd,KAAK,eAAiB,KAAK,eAAe,EAC1C,GAAI,CACF,MAAM,KAAK,cACb,QAAE,CACA,KAAK,eAAiB,MACxB,CACF,CAEA,MAAc,gBAAgC,CAQ5C,GAAI,CACF,IAAMC,EAAW,MAAM,EAAAC,QAAM,KAC3BN,EAAW,eACX,IAAI,gBAAgB,CAClB,WAAY,gBACZ,cAAe,KAAK,aACpB,UAAW,KAAK,SAChB,cAAe,KAAK,YACtB,CAAC,EACD,CACE,QAAS,CACP,eAAgB,mCAClB,CACF,CACF,EAEA,KAAK,YAAcK,EAAS,KAAK,aAE7BA,EAAS,KAAK,gBAChB,KAAK,aAAeA,EAAS,KAAK,eAGpC,KAAK,iBAAiB,CACxB,OAASE,EAAO,CACd,IAAMC,EAAUD,aAAiB,MAAQA,EAAM,QAAU,gBACzD,MAAM,IAAI,MAAM,mCAAmCC,CAAO,EAAE,CAC9D,CACF,CAEA,MAAM,gBAAkD,CAEtD,OAAI,KAAK,aAAa,GACpB,MAAM,KAAK,QAAQ,EAGd,CACL,cAAe,UAAU,KAAK,WAAW,EAC3C,CACF,CAWA,aAAa,sBACXC,EACAP,EACAQ,EACAC,EACqB,CAQrB,GAAI,CACF,IAAMN,EAAW,MAAM,EAAAC,QAAM,KAC3BN,EAAW,eACX,IAAI,gBAAgB,CAClB,WAAY,qBACZ,KAAMU,EACN,aAAcC,EACd,UAAWF,EACX,cAAeP,CACjB,CAAC,EACD,CACE,QAAS,CACP,eAAgB,mCAClB,CACF,CACF,EAEMU,EAAcP,EAAS,KAAK,aAC5BF,EAAeE,EAAS,KAAK,cAEnC,OAAIF,EACK,IAAIH,EAAWS,EAAUP,EAAcC,CAAY,EAEnD,IAAIH,EAAWY,CAAW,CAErC,OAASL,EAAO,CACd,IAAMC,EAAUD,aAAiB,MAAQA,EAAM,QAAU,gBACzD,MAAM,IAAI,MAAM,0CAA0CC,CAAO,EAAE,CACrE,CACF,CAUA,OAAO,sBAAsBC,EAAkBE,EAAqBE,EAAwB,CAC1F,IAAMC,EAAS,IAAI,gBAAgB,CACjC,UAAWL,EACX,aAAcE,EACd,cAAe,MACjB,CAAC,EAED,OAAIE,GACFC,EAAO,OAAO,QAASD,CAAK,EAGvB,wCAAwCC,EAAO,SAAS,CAAC,EAClE,CAEQ,kBAAyB,CAQ/B,GAAI,CACF,IAAMC,EAAU,EAAAC,QAAI,OAAO,KAAK,WAAW,EACvCD,GAAWA,EAAQ,MACrB,KAAK,YAAc,IAAI,KAAKA,EAAQ,IAAM,GAAI,EAElD,MAAQ,CAEN,KAAK,YAAc,IAAI,KAAK,KAAK,IAAI,EAAI,GAAK,GAAK,GAAI,CACzD,CACF,CACF,EA7Naf,EACa,eAAiB,wCADpC,IAAMiB,EAANjB,ECPA,IAAMkB,EAAN,MAAMC,CAAY,CAOvB,YAAYC,EAAuC,CAAC,EAAG,CACrD,KAAK,WAAaA,EAAQ,YAAc,EACxC,KAAK,aAAeA,EAAQ,cAAgB,IAC5C,KAAK,SAAWA,EAAQ,UAAY,IACpC,KAAK,kBAAoBA,EAAQ,mBAAqB,EACtD,KAAK,qBAAuBA,EAAQ,sBAAwB,CAAC,IAAK,IAAK,IAAK,GAAG,CACjF,CAKA,OAAO,SAAuB,CAC5B,OAAO,IAAID,CACb,CACF,ECJO,IAAME,EAAN,KAA0C,CAM/C,YAAYC,EAAeC,EAA8D,CACvF,KAAK,MAAQD,EAAK,MAClB,KAAK,OAASA,EAAK,OACnB,KAAK,eAAiBC,CACxB,CAKA,IAAI,YAAqB,CACvB,OAAO,KAAK,MAAM,KAAK,QAAQ,OAAS,IAAM,KAAK,QAAQ,OAAS,GAAG,CACzE,CAKA,IAAI,aAAuB,CACzB,OAAQ,KAAK,QAAQ,MAAQ,GAAK,KAAK,UACzC,CAKA,MAAM,UAAsC,CAC1C,GAAI,CAAC,KAAK,YACR,MAAM,IAAI,MAAM,yBAAyB,EAE3C,GAAI,CAAC,KAAK,eACR,MAAM,IAAI,MAAM,iCAAiC,EAEnD,OAAO,KAAK,gBAAgB,KAAK,OAAO,MAAQ,GAAK,CAAC,CACxD,CAKA,OAAQ,OAAO,aAAa,GAAsB,CAEhD,IAAIC,EAAgC,KAEpC,OAAa,CACX,QAAWC,KAAQD,EAAY,MAC7B,MAAMC,EAGR,GAAI,CAACD,EAAY,YACf,MAGFA,EAAc,MAAMA,EAAY,SAAS,CAC3C,CACF,CAKA,MAAM,SAAwB,CAC5B,IAAME,EAAgB,CAAC,EAEvB,cAAiBD,KAAQ,KACvBC,EAAS,KAAKD,CAAI,EAGpB,OAAOC,CACT,CACF,EC7EO,IAAeC,EAAf,KAAwB,CAGnB,YACWC,EACnBC,EACA,CAFmB,UAAAD,EAGf,OAAOC,GAAW,SACpB,KAAK,SAAWA,EAEhB,KAAK,SAAWA,EAAO,QAE3B,CAOU,oBACRC,EACAC,EACkB,CAClB,OAAO,IAAIC,EAAcF,EAAMC,CAAc,CAC/C,CACF,ECzBO,IAAME,EAAN,cAAmCC,CAAS,CACjD,YAAYC,EAAmB,CAC7B,MAAMA,EAAQ,mBAAmB,CACnC,CAEA,MAAM,KAAKC,EAAuE,CAChF,IAAMC,EAAW,MAAM,KAAK,KAAK,IAC/B,KAAK,SACLD,CACF,EACA,OAAO,IAAIE,EAAcD,EAAWE,GAAS,KAAK,KAAK,CAAE,GAAGH,EAAQ,KAAAG,CAAK,CAAC,CAAC,CAC7E,CAEA,MAAM,OAAOC,EAAwD,CACnE,OAAO,KAAK,KAAK,KAAmB,KAAK,SAAUA,CAAI,CACzD,CAEA,MAAM,OAAOC,EAAYD,EAAwD,CAC/E,OAAO,KAAK,KAAK,IAAkB,GAAG,KAAK,QAAQ,IAAI,mBAAmBC,CAAE,CAAC,GAAID,CAAI,CACvF,CAEA,MAAM,IAAIC,EAAmC,CAC3C,OAAO,KAAK,KAAK,IAAkB,GAAG,KAAK,QAAQ,IAAI,mBAAmBA,CAAE,CAAC,EAAE,CACjF,CAEA,MAAM,OAAOA,EAA2B,CACtC,OAAO,KAAK,KAAK,OAAO,GAAG,KAAK,QAAQ,IAAI,mBAAmBA,CAAE,CAAC,EAAE,CACtE,CAMA,MAAM,OAAOL,EAAsE,CACjF,IAAMC,EAAW,MAAM,KAAK,KAAK,KAAyB,GAAG,KAAK,QAAQ,UAAWD,CAAM,EAC3F,OAAO,KAAK,oBAAoBC,EAAWE,GAAS,KAAK,OAAO,CAAE,GAAGH,EAAQ,KAAAG,CAAK,CAAC,CAAC,CACtF,CACF,ECtCO,IAAMG,EAAN,cAA2BC,CAAS,CACzC,YAAYC,EAAmB,CAC7B,MAAMA,EAAQ,WAAW,CAC3B,CAEA,MAAM,KAAKC,EAAuD,CAChE,IAAMC,EAAW,MAAM,KAAK,KAAK,IAAgC,KAAK,SAAUD,CAAM,EACtF,OAAO,IAAIE,EAAcD,EAAWE,GAAS,KAAK,KAAK,CAAE,GAAGH,EAAQ,KAAAG,CAAK,CAAC,CAAC,CAC7E,CAEA,MAAM,OAAOC,EAAwC,CACnD,OAAO,KAAK,KAAK,KAAW,KAAK,SAAUA,CAAI,CACjD,CAEA,MAAM,OAAOC,EAAYD,EAAwC,CAC/D,OAAO,KAAK,KAAK,IAAU,GAAG,KAAK,QAAQ,IAAI,mBAAmBC,CAAE,CAAC,GAAID,CAAI,CAC/E,CAEA,MAAM,IAAIC,EAA2B,CACnC,OAAO,KAAK,KAAK,IAAU,GAAG,KAAK,QAAQ,IAAI,mBAAmBA,CAAE,CAAC,EAAE,CACzE,CAEA,MAAM,OAAOA,EAA2B,CACtC,OAAO,KAAK,KAAK,OAAO,GAAG,KAAK,QAAQ,IAAI,mBAAmBA,CAAE,CAAC,EAAE,CACtE,CAMA,MAAM,OAAOL,EAAsD,CACjE,IAAMC,EAAW,MAAM,KAAK,KAAK,KAAiB,GAAG,KAAK,QAAQ,UAAWD,CAAM,EACnF,OAAO,KAAK,oBAAoBC,EAAWE,GAAS,KAAK,OAAO,CAAE,GAAGH,EAAQ,KAAAG,CAAK,CAAC,CAAC,CACtF,CAOA,MAAM,YACJG,EACAN,EACoC,CACpC,IAAMC,EAAW,MAAM,KAAK,KAAK,KAC/B,GAAG,KAAK,QAAQ,IAAIK,CAAM,gBAC1BN,CACF,EACA,OAAO,KAAK,oBAAoBC,EAAWE,GACzC,KAAK,YAAYG,EAAQ,CAAE,GAAGN,EAAQ,KAAAG,CAAK,CAAC,CAC9C,CACF,CAOA,MAAM,UAAUG,EAAgBC,EAAuC,CACrE,OAAO,KAAK,KAAK,IAAgB,GAAG,KAAK,QAAQ,IAAID,CAAM,YAAYC,CAAQ,EAAE,CACnF,CAMA,MAAM,cAAcP,EAAmE,CACrF,IAAMC,EAAW,MAAM,KAAK,KAAK,KAC/B,GAAG,KAAK,QAAQ,iBAChBD,CACF,EACA,OAAO,KAAK,oBAAoBC,EAAWE,GAAS,KAAK,cAAc,CAAE,GAAGH,EAAQ,KAAAG,CAAK,CAAC,CAAC,CAC7F,CACF,EC3EO,IAAMK,EAAN,cAA8BC,CAAS,CAC5C,YAAYC,EAAmB,CAC7B,MAAMA,EAAQ,cAAc,CAC9B,CAEA,MAAM,KAAKC,EAA6D,CACtE,IAAMC,EAAW,MAAM,KAAK,KAAK,IAAsC,KAAK,SAAUD,CAAM,EAC5F,OAAO,IAAIE,EAAcD,EAAWE,GAAS,KAAK,KAAK,CAAE,GAAGH,EAAQ,KAAAG,CAAK,CAAC,CAAC,CAC7E,CAEA,MAAM,OAAOC,EAA8C,CACzD,OAAO,KAAK,KAAK,KAAc,KAAK,SAAUA,CAAI,CACpD,CAEA,MAAM,OAAOC,EAAYD,EAA8C,CACrE,OAAO,KAAK,KAAK,IAAa,GAAG,KAAK,QAAQ,IAAI,mBAAmBC,CAAE,CAAC,GAAID,CAAI,CAClF,CAEA,MAAM,IAAIC,EAA8B,CACtC,OAAO,KAAK,KAAK,IAAa,GAAG,KAAK,QAAQ,IAAI,mBAAmBA,CAAE,CAAC,EAAE,CAC5E,CAEA,MAAM,OAAOA,EAA2B,CACtC,OAAO,KAAK,KAAK,OAAO,GAAG,KAAK,QAAQ,IAAI,mBAAmBA,CAAE,CAAC,EAAE,CACtE,CAMA,MAAM,OAAOL,EAA4D,CACvE,IAAMC,EAAW,MAAM,KAAK,KAAK,KAAoB,GAAG,KAAK,QAAQ,UAAWD,CAAM,EACtF,OAAO,KAAK,oBAAoBC,EAAWE,GAAS,KAAK,OAAO,CAAE,GAAGH,EAAQ,KAAAG,CAAK,CAAC,CAAC,CACtF,CACF,EC7CA,IAAAG,EAAkB,oBAClBC,EAAgB,+BAChBC,EAAqB,oCACrBC,EAA8B,6CAG9B,EAAAC,QAAM,OAAO,EAAAC,OAAG,EAChB,EAAAD,QAAM,OAAO,EAAAE,OAAQ,EACrB,EAAAF,QAAM,OAAO,EAAAG,OAAiB,EAG9B,IAAMC,EAAmB,uBACnBC,GAAkB,uDAEXC,EAAY,CAKvB,uBAAuBC,EAA4B,CACjD,OAAOF,GAAgB,KAAKE,CAAS,CACvC,EASA,gBAAgBC,EAA6C,CAE3D,OAAI,OAAOA,GAAU,UAAY,KAAK,uBAAuBA,CAAK,EACzDA,KAIS,EAAAR,SAAMQ,GAAS,IAAI,IAAM,EAI1B,OAAOJ,CAAgB,CAC1C,EASA,eAAeG,EAAyB,CACtC,SAAO,EAAAP,SAAMO,CAAS,EAAE,OAAO,CACjC,EAQA,WAAWC,EAA6C,CACtD,SAAO,EAAAR,SAAMQ,GAAS,IAAI,IAAM,EAAE,OAAO,YAAY,CACvD,EAOA,KAAc,CACZ,OAAO,KAAK,gBAAgB,CAC9B,CACF,EC3DO,IAAMC,EAAN,cAA2BC,CAAS,CACzC,YAAYC,EAAmB,CAC7B,MAAMA,EAAQ,WAAW,CAC3B,CAEA,MAAM,OAAOC,EAAwC,CACnD,IAAMC,EAAgB,CACpB,GAAGD,EACH,cAAeE,EAAU,gBAAgBF,EAAK,aAAa,EAC3D,YAAaA,EAAK,YAAcE,EAAU,gBAAgBF,EAAK,WAAW,EAAI,MAChF,EACA,OAAO,KAAK,KAAK,KAAW,KAAK,SAAUC,CAAa,CAC1D,CAEA,MAAM,OAAOE,EAAYH,EAAwC,CAC/D,IAAMC,EAAgB,CACpB,GAAGD,EACH,cAAeA,EAAK,cAAgBE,EAAU,gBAAgBF,EAAK,aAAa,EAAI,OACpF,YAAaA,EAAK,YAAcE,EAAU,gBAAgBF,EAAK,WAAW,EAAI,MAChF,EACA,OAAO,KAAK,KAAK,IAAU,GAAG,KAAK,QAAQ,IAAI,mBAAmBG,CAAE,CAAC,GAAIF,CAAa,CACxF,CAEA,MAAM,IAAIE,EAA2B,CACnC,OAAO,KAAK,KAAK,IAAU,GAAG,KAAK,QAAQ,IAAI,mBAAmBA,CAAE,CAAC,EAAE,CACzE,CAEA,MAAM,OAAOA,EAA2B,CACtC,OAAO,KAAK,KAAK,OAAO,GAAG,KAAK,QAAQ,IAAI,mBAAmBA,CAAE,CAAC,EAAE,CACtE,CAMA,MAAM,OAAOC,EAAsD,CACjE,IAAMC,EAAW,MAAM,KAAK,KAAK,KAAiB,GAAG,KAAK,QAAQ,UAAWD,CAAM,EACnF,OAAO,KAAK,oBAAoBC,EAAWC,GAAS,KAAK,OAAO,CAAE,GAAGF,EAAQ,KAAAE,CAAK,CAAC,CAAC,CACtF,CAMA,MAAM,aAAaN,EAA8C,CAC/D,OAAO,KAAK,KAAK,IAAU,GAAG,KAAK,QAAQ,gBAAiBA,CAAI,CAClE,CAMA,MAAM,YAAYA,EAA6C,CAC7D,IAAMC,EAAgB,CACpB,GAAGD,EACH,cAAeE,EAAU,gBAAgBF,EAAK,aAAa,EAC3D,YAAaE,EAAU,gBAAgBF,EAAK,WAAW,CACzD,EACA,OAAO,KAAK,KAAK,IAAU,GAAG,KAAK,QAAQ,eAAgBC,CAAa,CAC1E,CACF,ECrEO,IAAMM,EAAN,cAA2BC,CAAS,CACzC,YAAYC,EAAmB,CAC7B,MAAMA,EAAQ,WAAW,CAC3B,CAEA,MAAM,KAAKC,EAAuD,CAChE,IAAMC,EAAW,MAAM,KAAK,KAAK,IAAgC,KAAK,SAAUD,CAAM,EACtF,OAAO,IAAIE,EAAcD,EAAWE,GAAS,KAAK,KAAK,CAAE,GAAGH,EAAQ,KAAAG,CAAK,CAAC,CAAC,CAC7E,CAEA,MAAM,OAAOC,EAAwC,CACnD,OAAO,KAAK,KAAK,KAAW,KAAK,SAAUA,CAAI,CACjD,CAEA,MAAM,OAAOC,EAAYD,EAAwC,CAC/D,OAAO,KAAK,KAAK,IAAU,GAAG,KAAK,QAAQ,IAAI,mBAAmBC,CAAE,CAAC,GAAID,CAAI,CAC/E,CAEA,MAAM,IAAIC,EAA2B,CACnC,OAAO,KAAK,KAAK,IAAU,GAAG,KAAK,QAAQ,IAAI,mBAAmBA,CAAE,CAAC,EAAE,CACzE,CAEA,MAAM,OAAOA,EAA2B,CACtC,OAAO,KAAK,KAAK,OAAO,GAAG,KAAK,QAAQ,IAAI,mBAAmBA,CAAE,CAAC,EAAE,CACtE,CAMA,MAAM,OAAOL,EAAsD,CACjE,IAAMC,EAAW,MAAM,KAAK,KAAK,KAAiB,GAAG,KAAK,QAAQ,UAAWD,CAAM,EACnF,OAAO,KAAK,oBAAoBC,EAAWE,GAAS,KAAK,OAAO,CAAE,GAAGH,EAAQ,KAAAG,CAAK,CAAC,CAAC,CACtF,CACF,EClCO,IAAMG,EAAN,cAA0BC,CAAS,CACxC,YAAYC,EAAmB,CAC7B,MAAMA,EAAQ,UAAU,CAC1B,CAEA,MAAM,KAAKC,EAAqD,CAC9D,IAAMC,EAAW,MAAM,KAAK,KAAK,IAA8B,KAAK,SAAUD,CAAM,EACpF,OAAO,IAAIE,EAAcD,EAAWE,GAAS,KAAK,KAAK,CAAE,GAAGH,EAAQ,KAAAG,CAAK,CAAC,CAAC,CAC7E,CAEA,MAAM,OAAOC,EAAsC,CACjD,OAAO,KAAK,KAAK,KAAU,KAAK,SAAUA,CAAI,CAChD,CAEA,MAAM,OAAOC,EAAYD,EAAsC,CAC7D,OAAO,KAAK,KAAK,IAAS,GAAG,KAAK,QAAQ,IAAI,mBAAmBC,CAAE,CAAC,GAAID,CAAI,CAC9E,CAEA,MAAM,IAAIC,EAA0B,CAClC,OAAO,KAAK,KAAK,IAAS,GAAG,KAAK,QAAQ,IAAI,mBAAmBA,CAAE,CAAC,EAAE,CACxE,CAEA,MAAM,OAAOA,EAA2B,CACtC,OAAO,KAAK,KAAK,OAAO,GAAG,KAAK,QAAQ,IAAI,mBAAmBA,CAAE,CAAC,EAAE,CACtE,CAMA,MAAM,OAAOL,EAAoD,CAC/D,IAAMC,EAAW,MAAM,KAAK,KAAK,KAAgB,GAAG,KAAK,QAAQ,UAAWD,CAAM,EAClF,OAAO,KAAK,oBAAoBC,EAAWE,GAAS,KAAK,OAAO,CAAE,GAAGH,EAAQ,KAAAG,CAAK,CAAC,CAAC,CACtF,CACF,EC1BO,IAAMG,EAAN,cAA8BC,CAAS,CAC5C,YAAYC,EAAmB,CAC7B,MAAMA,EAAQ,cAAc,CAC9B,CAEA,MAAM,KAAKC,EAA6D,CACtE,IAAMC,EAAW,MAAM,KAAK,KAAK,IAAsC,KAAK,SAAUD,CAAM,EAC5F,OAAO,IAAIE,EAAcD,EAAWE,GAAS,KAAK,KAAK,CAAE,GAAGH,EAAQ,KAAAG,CAAK,CAAC,CAAC,CAC7E,CAEA,MAAM,OAAOC,EAA8C,CACzD,IAAMC,EAAgB,CACpB,GAAGD,EACH,SAAUE,EAAU,gBAAgBF,EAAK,QAAQ,CACnD,EACA,OAAO,KAAK,KAAK,KAAc,KAAK,SAAUC,CAAa,CAC7D,CAEA,MAAM,OAAOE,EAAYH,EAA8C,CACrE,IAAMC,EAAgB,CACpB,GAAGD,EACH,SAAUA,EAAK,SAAWE,EAAU,gBAAgBF,EAAK,QAAQ,EAAI,MACvE,EACA,OAAO,KAAK,KAAK,IAAa,GAAG,KAAK,QAAQ,IAAI,mBAAmBG,CAAE,CAAC,GAAIF,CAAa,CAC3F,CAEA,MAAM,IAAIE,EAA8B,CACtC,OAAO,KAAK,KAAK,IAAa,GAAG,KAAK,QAAQ,IAAI,mBAAmBA,CAAE,CAAC,EAAE,CAC5E,CAEA,MAAM,OAAOA,EAA2B,CACtC,OAAO,KAAK,KAAK,OAAO,GAAG,KAAK,QAAQ,IAAI,mBAAmBA,CAAE,CAAC,EAAE,CACtE,CAMA,MAAM,OAAOP,EAA4D,CACvE,IAAMC,EAAW,MAAM,KAAK,KAAK,KAAoB,GAAG,KAAK,QAAQ,UAAWD,CAAM,EACtF,OAAO,KAAK,oBAAoBC,EAAWE,GAAS,KAAK,OAAO,CAAE,GAAGH,EAAQ,KAAAG,CAAK,CAAC,CAAC,CACtF,CAQA,MAAM,aAAaI,EAAYH,EAAuC,CACpE,OAAO,KAAK,KAAK,IAAa,GAAG,KAAK,QAAQ,IAAIG,CAAE,UAAWH,CAAI,CACrE,CACF,EC3DO,IAAMI,EAAN,cAA2BC,CAAS,CACzC,YAAYC,EAAmB,CAC7B,MAAMA,EAAQ,WAAW,CAC3B,CAEA,MAAM,KAAKC,EAAuD,CAChE,IAAMC,EAAW,MAAM,KAAK,KAAK,IAAgC,KAAK,SAAUD,CAAM,EACtF,OAAO,IAAIE,EAAcD,EAAWE,GAAS,KAAK,KAAK,CAAE,GAAGH,EAAQ,KAAAG,CAAK,CAAC,CAAC,CAC7E,CAEA,MAAM,OAAOC,EAAwC,CACnD,IAAMC,EAAgB,CACpB,GAAGD,EACH,SAAUE,EAAU,gBAAgBF,EAAK,QAAQ,CACnD,EACA,OAAO,KAAK,KAAK,KAAW,KAAK,SAAUC,CAAa,CAC1D,CAEA,MAAM,OAAOE,EAAYH,EAAwC,CAC/D,IAAMC,EAAgB,CACpB,GAAGD,EACH,SAAUE,EAAU,gBAAgBF,EAAK,QAAQ,CACnD,EACA,OAAO,KAAK,KAAK,IAAU,GAAG,KAAK,QAAQ,IAAI,mBAAmBG,CAAE,CAAC,GAAIF,CAAa,CACxF,CAEA,MAAM,IAAIE,EAA2B,CACnC,OAAO,KAAK,KAAK,IAAU,GAAG,KAAK,QAAQ,IAAI,mBAAmBA,CAAE,CAAC,EAAE,CACzE,CAEA,MAAM,OAAOA,EAA2B,CACtC,OAAO,KAAK,KAAK,OAAO,GAAG,KAAK,QAAQ,IAAI,mBAAmBA,CAAE,CAAC,EAAE,CACtE,CAMA,MAAM,OAAOP,EAAsD,CACjE,IAAMC,EAAW,MAAM,KAAK,KAAK,KAAiB,GAAG,KAAK,QAAQ,UAAWD,CAAM,EACnF,OAAO,KAAK,oBAAoBC,EAAWE,GAAS,KAAK,OAAO,CAAE,GAAGH,EAAQ,KAAAG,CAAK,CAAC,CAAC,CACtF,CACF,ECpCO,IAAMK,EAAN,cAA4BC,CAAS,CAC1C,YAAYC,EAAmB,CAC7B,MAAMA,EAAQ,YAAY,CAC5B,CAEA,MAAM,KAAKC,EAAyD,CAClE,IAAMC,EAAW,MAAM,KAAK,KAAK,IAAkC,KAAK,SAAUD,CAAM,EACxF,OAAO,IAAIE,EAAcD,EAAWE,GAAS,KAAK,KAAK,CAAE,GAAGH,EAAQ,KAAAG,CAAK,CAAC,CAAC,CAC7E,CAEA,MAAM,OAAOC,EAA0C,CACrD,IAAMC,EAAgB,CACpB,GAAGD,EACH,cAAeE,EAAU,gBAAgBF,EAAK,aAAa,EAC3D,YAAaE,EAAU,gBAAgBF,EAAK,WAAW,CACzD,EACA,OAAO,KAAK,KAAK,KAAY,KAAK,SAAUC,CAAa,CAC3D,CAEA,MAAM,OAAOE,EAAYH,EAA0C,CACjE,IAAMC,EAAgB,CACpB,GAAGD,EACH,cAAeE,EAAU,gBAAgBF,EAAK,aAAa,EAC3D,YAAaE,EAAU,gBAAgBF,EAAK,WAAW,CACzD,EACA,OAAO,KAAK,KAAK,IAAW,GAAG,KAAK,QAAQ,IAAI,mBAAmBG,CAAE,CAAC,GAAIF,CAAa,CACzF,CAEA,MAAM,IAAIE,EAA4B,CACpC,OAAO,KAAK,KAAK,IAAW,GAAG,KAAK,QAAQ,IAAI,mBAAmBA,CAAE,CAAC,EAAE,CAC1E,CAEA,MAAM,OAAOA,EAA2B,CACtC,OAAO,KAAK,KAAK,OAAO,GAAG,KAAK,QAAQ,IAAI,mBAAmBA,CAAE,CAAC,EAAE,CACtE,CAMA,MAAM,OAAOP,EAAwD,CACnE,IAAMC,EAAW,MAAM,KAAK,KAAK,KAAkB,GAAG,KAAK,QAAQ,UAAWD,CAAM,EACpF,OAAO,KAAK,oBAAoBC,EAAWE,GAAS,KAAK,OAAO,CAAE,GAAGH,EAAQ,KAAAG,CAAK,CAAC,CAAC,CACtF,CACF,ECrDO,IAAMK,EAAN,KAAsB,CAC3B,YAA6BC,EAAiB,CAAjB,UAAAA,CAAkB,CAE/C,MAAM,YAA+B,CACnC,OAAO,KAAK,KAAK,IAAa,iBAAiB,CACjD,CAEA,MAAM,cAAcC,EAA8C,CAChE,OAAO,KAAK,KAAK,IAAa,kBAAmBA,CAAI,CACvD,CACF,ECVO,IAAMC,EAAN,KAAuB,CAC5B,YAA6BC,EAAiB,CAAjB,UAAAA,CAAkB,CAE/C,MAAM,KAAyB,CAC7B,OAAO,KAAK,KAAK,IAAc,cAAc,CAC/C,CAEA,MAAM,OAAOC,EAAgD,CAC3D,OAAO,KAAK,KAAK,IAAc,eAAgBA,CAAI,CACrD,CACF,ECFO,IAAMC,EAAN,cAAiCC,CAAS,CAC/C,YAAYC,EAAmB,CAC7B,MAAMA,EAAQ,iBAAiB,CACjC,CAEA,MAAM,KAAKC,EAAmE,CAC5E,IAAMC,EAAW,MAAM,KAAK,KAAK,IAC/B,KAAK,SACLD,CACF,EACA,OAAO,IAAIE,EAAcD,EAAWE,GAAS,KAAK,KAAK,CAAE,GAAGH,EAAQ,KAAAG,CAAK,CAAC,CAAC,CAC7E,CAEA,MAAM,OAAOC,EAAoD,CAC/D,OAAO,KAAK,KAAK,KAAiB,KAAK,SAAUA,CAAI,CACvD,CAEA,MAAM,OAAOC,EAAYD,EAAoD,CAC3E,OAAO,KAAK,KAAK,IAAgB,GAAG,KAAK,QAAQ,IAAI,mBAAmBC,CAAE,CAAC,GAAID,CAAI,CACrF,CAEA,MAAM,IAAIC,EAAiC,CACzC,OAAO,KAAK,KAAK,IAAgB,GAAG,KAAK,QAAQ,IAAI,mBAAmBA,CAAE,CAAC,EAAE,CAC/E,CAEA,MAAM,OAAOA,EAA2B,CACtC,OAAO,KAAK,KAAK,OAAO,GAAG,KAAK,QAAQ,IAAI,mBAAmBA,CAAE,CAAC,EAAE,CACtE,CAMA,MAAM,OAAOL,EAAkE,CAC7E,IAAMC,EAAW,MAAM,KAAK,KAAK,KAAuB,GAAG,KAAK,QAAQ,UAAWD,CAAM,EACzF,OAAO,KAAK,oBAAoBC,EAAWE,GAAS,KAAK,OAAO,CAAE,GAAGH,EAAQ,KAAAG,CAAK,CAAC,CAAC,CACtF,CACF,ECrCO,IAAMG,EAAN,cAA+BC,CAAS,CAC7C,YAAYC,EAAmB,CAC7B,MAAMA,EAAQ,eAAe,CAC/B,CAEA,MAAM,KAAKC,EAA+D,CACxE,IAAMC,EAAW,MAAM,KAAK,KAAK,IAAwC,KAAK,SAAUD,CAAM,EAC9F,OAAO,IAAIE,EAAcD,EAAWE,GAAS,KAAK,KAAK,CAAE,GAAGH,EAAQ,KAAAG,CAAK,CAAC,CAAC,CAC7E,CAEA,MAAM,OAAOC,EAAgD,CAC3D,OAAO,KAAK,KAAK,KAAe,KAAK,SAAUA,CAAI,CACrD,CAEA,MAAM,OAAOC,EAAYD,EAAgD,CACvE,OAAO,KAAK,KAAK,IAAc,GAAG,KAAK,QAAQ,IAAI,mBAAmBC,CAAE,CAAC,GAAID,CAAI,CACnF,CAEA,MAAM,IAAIC,EAA+B,CACvC,OAAO,KAAK,KAAK,IAAc,GAAG,KAAK,QAAQ,IAAI,mBAAmBA,CAAE,CAAC,EAAE,CAC7E,CAEA,MAAM,OAAOA,EAA2B,CACtC,OAAO,KAAK,KAAK,OAAO,GAAG,KAAK,QAAQ,IAAI,mBAAmBA,CAAE,CAAC,EAAE,CACtE,CAMA,MAAM,OAAOL,EAA8D,CACzE,IAAMC,EAAW,MAAM,KAAK,KAAK,KAAqB,GAAG,KAAK,QAAQ,UAAWD,CAAM,EACvF,OAAO,KAAK,oBAAoBC,EAAWE,GAAS,KAAK,OAAO,CAAE,GAAGH,EAAQ,KAAAG,CAAK,CAAC,CAAC,CACtF,CACF,EClCO,IAAMG,EAAN,KAAoB,CACzB,YAA6BC,EAAiB,CAAjB,UAAAA,CAAkB,CAE/C,MAAM,KAAsB,CAC1B,OAAO,KAAK,KAAK,IAAW,WAAW,CACzC,CAEA,MAAM,MAAMC,EAAyC,CAEnD,IAAMC,EAAgB,CACpB,GAAGD,EACH,cAAeA,EAAK,cAChBE,EAAU,gBAAgBF,EAAK,aAAa,EAC5CE,EAAU,gBAAgB,CAChC,EACA,OAAO,KAAK,KAAK,KAAY,kBAAmBD,CAAa,CAC/D,CAEA,MAAM,KAAKD,EAAyC,CAElD,IAAMC,EAAgBD,EAClB,CACE,GAAGA,EACH,YAAaA,EAAK,YACdE,EAAU,gBAAgBF,EAAK,WAAW,EAC1CE,EAAU,gBAAgB,CAChC,EACA,CAAE,YAAaA,EAAU,gBAAgB,CAAE,EAC/C,OAAO,KAAK,KAAK,KAAY,iBAAkBD,CAAa,CAC9D,CAEA,MAAM,MAAMD,EAA0C,CAEpD,IAAMC,EAAgBD,EAClB,CACE,GAAGA,EACH,cAAeA,EAAK,cAChBE,EAAU,gBAAgBF,EAAK,aAAa,EAC5CE,EAAU,gBAAgB,CAChC,EACA,CAAE,cAAeA,EAAU,gBAAgB,CAAE,EACjD,OAAO,KAAK,KAAK,KAAY,kBAAmBD,CAAa,CAC/D,CAEA,MAAM,OAAOD,EAA2C,CAEtD,IAAMC,EAAgBD,EAClB,CACE,GAAGA,EACH,YAAaA,EAAK,YACdE,EAAU,gBAAgBF,EAAK,WAAW,EAC1CE,EAAU,gBAAgB,CAChC,EACA,CAAE,YAAaA,EAAU,gBAAgB,CAAE,EAC/C,OAAO,KAAK,KAAK,KAAY,mBAAoBD,CAAa,CAChE,CAEA,MAAM,OAAOD,EAA0C,CAErD,IAAMC,EAAgB,CACpB,GAAGD,EACH,cAAeA,EAAK,cAAgBE,EAAU,gBAAgBF,EAAK,aAAa,EAAI,MACtF,EACA,OAAO,KAAK,KAAK,IAAW,mBAAoBC,CAAa,CAC/D,CACF,ECtEO,IAAME,EAAN,cAA2BC,CAAS,CACzC,YAAYC,EAAmB,CAC7B,MAAMA,EAAQ,WAAW,CAC3B,CAEA,MAAM,KAAKC,EAAuD,CAChE,IAAMC,EAAW,MAAM,KAAK,KAAK,IAAgC,KAAK,SAAUD,CAAM,EACtF,OAAO,IAAIE,EAAcD,EAAWE,GAAS,KAAK,KAAK,CAAE,GAAGH,EAAQ,KAAAG,CAAK,CAAC,CAAC,CAC7E,CAEA,MAAM,OAAOC,EAAwC,CACnD,IAAMC,EAAgB,CACpB,GAAGD,EACH,QAASA,EAAK,QAAUE,EAAU,gBAAgBF,EAAK,OAAO,EAAI,MACpE,EACA,OAAO,KAAK,KAAK,KAAW,KAAK,SAAUC,CAAa,CAC1D,CAEA,MAAM,OAAOE,EAAYH,EAAwC,CAC/D,IAAMC,EAAgB,CACpB,GAAGD,EACH,QAASA,EAAK,QAAUE,EAAU,gBAAgBF,EAAK,OAAO,EAAI,MACpE,EACA,OAAO,KAAK,KAAK,IAAU,GAAG,KAAK,QAAQ,IAAI,mBAAmBG,CAAE,CAAC,GAAIF,CAAa,CACxF,CAEA,MAAM,IAAIE,EAA2B,CACnC,OAAO,KAAK,KAAK,IAAU,GAAG,KAAK,QAAQ,IAAI,mBAAmBA,CAAE,CAAC,EAAE,CACzE,CAEA,MAAM,OAAOA,EAA2B,CACtC,OAAO,KAAK,KAAK,OAAO,GAAG,KAAK,QAAQ,IAAI,mBAAmBA,CAAE,CAAC,EAAE,CACtE,CAMA,MAAM,OAAOP,EAAsD,CACjE,IAAMC,EAAW,MAAM,KAAK,KAAK,KAAiB,GAAG,KAAK,QAAQ,UAAWD,CAAM,EACnF,OAAO,KAAK,oBAAoBC,EAAWE,GAAS,KAAK,OAAO,CAAE,GAAGH,EAAQ,KAAAG,CAAK,CAAC,CAAC,CACtF,CACF,ECrCO,IAAMK,EAAN,cAA8BC,CAAS,CAC5C,YAAYC,EAAmB,CAC7B,MAAMA,EAAQ,cAAc,CAC9B,CAEA,MAAM,KAAKC,EAA6D,CACtE,IAAMC,EAAW,MAAM,KAAK,KAAK,IAAsC,KAAK,SAAUD,CAAM,EAC5F,OAAO,IAAIE,EAAcD,EAAWE,GAAS,KAAK,KAAK,CAAE,GAAGH,EAAQ,KAAAG,CAAK,CAAC,CAAC,CAC7E,CAEA,MAAM,OAAOC,EAA8C,CACzD,OAAO,KAAK,KAAK,KAAc,KAAK,SAAUA,CAAI,CACpD,CAEA,MAAM,OAAOC,EAAYD,EAA8C,CACrE,OAAO,KAAK,KAAK,IAAa,GAAG,KAAK,QAAQ,IAAI,mBAAmBC,CAAE,CAAC,GAAID,CAAI,CAClF,CAEA,MAAM,IAAIC,EAA8B,CACtC,OAAO,KAAK,KAAK,IAAa,GAAG,KAAK,QAAQ,IAAI,mBAAmBA,CAAE,CAAC,EAAE,CAC5E,CAEA,MAAM,OAAOA,EAA2B,CACtC,OAAO,KAAK,KAAK,OAAO,GAAG,KAAK,QAAQ,IAAI,mBAAmBA,CAAE,CAAC,EAAE,CACtE,CAMA,MAAM,OAAOL,EAA4D,CACvE,IAAMC,EAAW,MAAM,KAAK,KAAK,KAAoB,GAAG,KAAK,QAAQ,UAAWD,CAAM,EACtF,OAAO,KAAK,oBAAoBC,EAAWE,GAAS,KAAK,OAAO,CAAE,GAAGH,EAAQ,KAAAG,CAAK,CAAC,CAAC,CACtF,CACF,E1BIO,IAAMG,EAAN,KAAsB,CA0B3B,YAAYC,EAAiC,CAC3C,IAAMC,EAAiB,KAAK,qBAAqBD,CAAO,EAElDE,EAAuB,CAC3B,QAASF,EAAQ,SAAW,2BAC5B,eAAAC,EACA,YAAaD,EAAQ,aAAeG,EAAY,QAAQ,EACxD,WAAYH,EAAQ,UACtB,EAEA,KAAK,UAAY,IAAII,EAAUF,CAAM,EAGrC,KAAK,cAAgB,IAAIG,EAAqB,KAAK,SAAS,EAC5D,KAAK,MAAQ,IAAIC,EAAa,KAAK,SAAS,EAC5C,KAAK,SAAW,IAAIC,EAAgB,KAAK,SAAS,EAClD,KAAK,MAAQ,IAAIC,EAAa,KAAK,SAAS,EAC5C,KAAK,MAAQ,IAAIC,EAAa,KAAK,SAAS,EAC5C,KAAK,KAAO,IAAIC,EAAY,KAAK,SAAS,EAC1C,KAAK,SAAW,IAAIC,EAAgB,KAAK,SAAS,EAClD,KAAK,MAAQ,IAAIC,EAAa,KAAK,SAAS,EAC5C,KAAK,OAAS,IAAIC,EAAc,KAAK,SAAS,EAC9C,KAAK,QAAU,IAAIC,EAAgB,KAAK,SAAS,EACjD,KAAK,SAAW,IAAIC,EAAiB,KAAK,SAAS,EACnD,KAAK,YAAc,IAAIC,EAAmB,KAAK,SAAS,EACxD,KAAK,UAAY,IAAIC,EAAiB,KAAK,SAAS,EACpD,KAAK,MAAQ,IAAIC,EAAc,KAAK,SAAS,EAC7C,KAAK,MAAQ,IAAIC,EAAa,KAAK,SAAS,EAC5C,KAAK,SAAW,IAAIC,EAAgB,KAAK,SAAS,CACpD,CAEQ,qBAAqBpB,EAAiD,CAC5E,GAAIA,EAAQ,OACV,OAAO,IAAIqB,EAAWrB,EAAQ,MAAM,EAC/B,GAAIA,EAAQ,YACjB,OAAO,IAAIsB,EAAWtB,EAAQ,WAAW,EACpC,GAAIA,EAAQ,OACjB,OAAO,IAAIsB,EACTtB,EAAQ,OAAO,SACfA,EAAQ,OAAO,aACfA,EAAQ,OAAO,YACjB,EACK,GAAIA,EAAQ,eACjB,OAAOA,EAAQ,eAEf,MAAM,IAAI,MAAM,mCAAmC,CAEvD,CACF,EAgDO,SAASuB,GAAavB,EAAkD,CAC7E,OAAO,IAAID,EAAgBC,CAAO,CACpC","names":["index_exports","__export","ApiClient","ApiKeyAuth","AutomationResource","DocumentResource","ExpenseResource","NavigablePage","NoteResource","OAuth2Auth","OrganizationResource","PauseResource","ProfileResource","ProjectResource","RateResource","Resource","RetryConfig","SettingsResource","TagResource","TaskResource","TeamResource","TimerResource","TimesheetApiError","TimesheetAuthError","TimesheetClient","TimesheetRateLimitError","TodoResource","WebhookResource","createClient","__toCommonJS","import_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","ms","resolve","ApiKeyAuth","apiKey","config","import_axios","import_jsonwebtoken","_OAuth2Auth","accessTokenOrClientId","clientSecret","refreshToken","config","response","axios","error","message","clientId","authorizationCode","redirectUri","accessToken","state","params","decoded","jwt","OAuth2Auth","RetryConfig","_RetryConfig","options","NavigablePage","data","nextPageLoader","currentPage","item","allItems","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","import_dayjs","import_utc","import_timezone","import_customParseFormat","dayjs","utc","timezone","customParseFormat","TIMESTAMP_FORMAT","TIMESTAMP_REGEX","DateUtils","timestamp","input","TaskResource","Resource","client","data","formattedData","DateUtils","id","params","response","page","RateResource","Resource","client","params","response","NavigablePage","page","data","id","TagResource","Resource","client","params","response","NavigablePage","page","data","id","ExpenseResource","Resource","client","params","response","NavigablePage","page","data","formattedData","DateUtils","id","NoteResource","Resource","client","params","response","NavigablePage","page","data","formattedData","DateUtils","id","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","response","NavigablePage","page","data","id","TimerResource","http","data","formattedData","DateUtils","TodoResource","Resource","client","params","response","NavigablePage","page","data","formattedData","DateUtils","id","WebhookResource","Resource","client","params","response","NavigablePage","page","data","id","TimesheetClient","options","authentication","config","RetryConfig","ApiClient","OrganizationResource","TeamResource","ProjectResource","TaskResource","RateResource","TagResource","ExpenseResource","NoteResource","PauseResource","ProfileResource","SettingsResource","AutomationResource","DocumentResource","TimerResource","TodoResource","WebhookResource","ApiKeyAuth","OAuth2Auth","createClient"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,2 @@
1
+ import P from"axios";var h=class r extends Error{constructor(e,t,s,m){let n=t?m?`${e} (HTTP ${t}, Code: ${m})`:`${e} (HTTP ${t})`:e;super(n),this.name="TimesheetApiError",this.statusCode=t,this.responseBody=s,this.errorCode=m,typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,r)}};var q=class extends h{constructor(e,t=401,s){super(e,t,s,"authentication_error"),this.name="TimesheetAuthError"}};var E=class extends h{constructor(e,t){super(e,429,void 0,"rate_limit_exceeded"),this.name="TimesheetRateLimitError",this.retryAfter=t}getRetryAfterDate(){if(!this.retryAfter)return null;let e=Number(this.retryAfter);if(!isNaN(e))return new Date(e*1e3);let t=new Date(this.retryAfter);return isNaN(t.getTime())?null:t}};var L=class{constructor(e){this.config=e,this.httpClient=e.httpClient||P.create({baseURL:e.baseUrl,timeout:3e4,headers:{"User-Agent":"Timesheet-TypeScript-SDK/1.0.0","Content-Type":"application/json"}}),this.httpClient.interceptors.request.use(async t=>{if(t.url!=="/oauth/token"&&this.config.authentication){let s=await this.config.authentication.getAuthHeaders();if(s)for(let[m,n]of Object.entries(s))t.headers.set(m,n)}return t})}async request(e){let t=null,s=this.config.retryConfig;for(let m=0;m<=s.maxRetries;m++)try{return(await this.httpClient.request(e)).data}catch(n){if(t=n,P.isAxiosError(n)&&n.response?.status===401){let p=n.response.data;throw new q(p?.message||"Authentication failed",401,JSON.stringify(p))}if(P.isAxiosError(n)&&n.response?.status===429){let p=n.response.headers["retry-after"];throw new E("Rate limit exceeded",p)}let u=P.isAxiosError(n)?n.response?.status:void 0;if(m<s.maxRetries&&u&&s.retryableStatusCodes.includes(u)){let p=Math.min(s.initialDelay*Math.pow(s.backoffMultiplier,m),s.maxDelay);await this.sleep(p);continue}if(P.isAxiosError(n)){let p=n.response?.data;throw new h(p?.message||n.message,n.response?.status,JSON.stringify(p),p?.code)}else throw n instanceof Error?new h(n.message):new h("Unknown error occurred")}throw t||new Error("Unknown error")}async get(e,t){return this.request({method:"GET",url:e,params:t})}async post(e,t,s){return this.request({method:"POST",url:e,data:t,params:s})}async put(e,t,s){return this.request({method:"PUT",url:e,data:t,params:s})}async delete(e,t){return this.request({method:"DELETE",url:e,params:t})}sleep(e){return new Promise(t=>setTimeout(t,e))}};var I=class{constructor(e){this.apiKey=e;if(e===null)throw new Error("API key cannot be null");if(e===void 0)throw new Error("API key cannot be undefined");if(!e)throw new Error("API key cannot be empty");if(typeof e!="string")throw new Error("API key must be a string");if(e.trim().length===0)throw new Error("API key cannot be empty or whitespace");if(!this.isValidFormat(e))throw new Error("Invalid API key format")}isValidFormat(e){return/^ts_[a-zA-Z0-9]+\.[a-zA-Z0-9]+$/.test(e)}applyAuth(e){e.headers||(e.headers={}),e.headers.Authorization=`ApiKey ${this.apiKey}`}needsRefresh(){return!1}async refresh(){throw new Error("API keys cannot be refreshed")}async getAuthHeaders(){return{Authorization:`ApiKey ${this.apiKey}`}}isValid(){return typeof this.apiKey=="string"&&this.apiKey.trim().length>0&&this.isValidFormat(this.apiKey)}};import z from"axios";import j from"jsonwebtoken";var c=class c{constructor(e,t,s){t&&s?(this.clientId=e,this.clientSecret=t,this.refreshToken=s,this.accessToken=""):(this.accessToken=e,this.parseTokenExpiry())}applyAuth(e){e.headers||(e.headers={}),e.headers.Authorization=`Bearer ${this.accessToken}`}needsRefresh(){return this.refreshToken&&!this.accessToken?!0:!this.refreshToken||!this.tokenExpiry?!1:new Date(Date.now()+5*60*1e3)>=this.tokenExpiry}async refresh(){if(!this.refreshToken)throw new Error("Cannot refresh without refresh token");if(this.refreshPromise)return this.refreshPromise;this.refreshPromise=this.performRefresh();try{await this.refreshPromise}finally{this.refreshPromise=void 0}}async performRefresh(){try{let e=await z.post(c.TOKEN_ENDPOINT,new URLSearchParams({grant_type:"refresh_token",refresh_token:this.refreshToken,client_id:this.clientId,client_secret:this.clientSecret}),{headers:{"Content-Type":"application/x-www-form-urlencoded"}});this.accessToken=e.data.access_token,e.data.refresh_token&&(this.refreshToken=e.data.refresh_token),this.parseTokenExpiry()}catch(e){let t=e instanceof Error?e.message:"Unknown error";throw new Error(`Failed to refresh OAuth2 token: ${t}`)}}async getAuthHeaders(){return this.needsRefresh()&&await this.refresh(),{Authorization:`Bearer ${this.accessToken}`}}static async fromAuthorizationCode(e,t,s,m){try{let n=await z.post(c.TOKEN_ENDPOINT,new URLSearchParams({grant_type:"authorization_code",code:s,redirect_uri:m,client_id:e,client_secret:t}),{headers:{"Content-Type":"application/x-www-form-urlencoded"}}),u=n.data.access_token,p=n.data.refresh_token;return p?new c(e,t,p):new c(u)}catch(n){let u=n instanceof Error?n.message:"Unknown error";throw new Error(`Failed to exchange authorization code: ${u}`)}}static buildAuthorizationUrl(e,t,s){let m=new URLSearchParams({client_id:e,redirect_uri:t,response_type:"code"});return s&&m.append("state",s),`https://api.timesheet.io/oauth2/auth?${m.toString()}`}parseTokenExpiry(){try{let e=j.decode(this.accessToken);e&&e.exp&&(this.tokenExpiry=new Date(e.exp*1e3))}catch{this.tokenExpiry=new Date(Date.now()+60*60*1e3)}}};c.TOKEN_ENDPOINT="https://api.timesheet.io/oauth2/token";var l=c;var S=class r{constructor(e={}){this.maxRetries=e.maxRetries??3,this.initialDelay=e.initialDelay??100,this.maxDelay=e.maxDelay??1e4,this.backoffMultiplier=e.backoffMultiplier??2,this.retryableStatusCodes=e.retryableStatusCodes??[429,502,503,504]}static default(){return new r}};var o=class{constructor(e,t){this.items=e.items,this.params=e.params,this.nextPageLoader=t}get totalPages(){return Math.ceil((this.params?.count||0)/(this.params?.limit||25))}get hasNextPage(){return(this.params?.page||1)<this.totalPages}async nextPage(){if(!this.hasNextPage)throw new Error("No more pages available");if(!this.nextPageLoader)throw new Error("Next page loader not configured");return this.nextPageLoader((this.params.page||1)+1)}async*[Symbol.asyncIterator](){let e=this;for(;;){for(let t of e.items)yield t;if(!e.hasNextPage)break;e=await e.nextPage()}}async toArray(){let e=[];for await(let t of this)e.push(t);return e}};var i=class{constructor(e,t){this.http=e;typeof t=="string"?this.basePath=t:this.basePath=t.basePath}createNavigablePage(e,t){return new o(e,t)}};var d=class extends i{constructor(e){super(e,"/v1/organizations")}async list(e){let t=await this.http.get(this.basePath,e);return new o(t,s=>this.list({...e,page:s}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,s=>this.search({...e,page:s}))}};var f=class extends i{constructor(e){super(e,"/v1/teams")}async list(e){let t=await this.http.get(this.basePath,e);return new o(t,s=>this.list({...e,page:s}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,s=>this.search({...e,page:s}))}async listMembers(e,t){let s=await this.http.post(`${this.basePath}/${e}/members/list`,t);return this.createNavigablePage(s,m=>this.listMembers(e,{...t,page:m}))}async getMember(e,t){return this.http.get(`${this.basePath}/${e}/members/${t}`)}async getColleagues(e){let t=await this.http.post(`${this.basePath}/getColleagues`,e);return this.createNavigablePage(t,s=>this.getColleagues({...e,page:s}))}};var T=class extends i{constructor(e){super(e,"/v1/projects")}async list(e){let t=await this.http.get(this.basePath,e);return new o(t,s=>this.list({...e,page:s}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,s=>this.search({...e,page:s}))}};import g from"dayjs";import M from"dayjs/plugin/utc";import _ from"dayjs/plugin/timezone";import W from"dayjs/plugin/customParseFormat";g.extend(M);g.extend(_);g.extend(W);var F="YYYY-MM-DDTHH:mm:ssZ",K=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{2}:\d{2}$/,a={isValidTimestampFormat(r){return K.test(r)},formatTimestamp(r){return typeof r=="string"&&this.isValidTimestampFormat(r)?r:g(r||new Date).format(F)},parseTimestamp(r){return g(r).toDate()},formatDate(r){return g(r||new Date).format("YYYY-MM-DD")},now(){return this.formatTimestamp()}};var y=class extends i{constructor(e){super(e,"/v1/tasks")}async create(e){let t={...e,startDateTime:a.formatTimestamp(e.startDateTime),endDateTime:e.endDateTime?a.formatTimestamp(e.endDateTime):void 0};return this.http.post(this.basePath,t)}async update(e,t){let s={...t,startDateTime:t.startDateTime?a.formatTimestamp(t.startDateTime):void 0,endDateTime:t.endDateTime?a.formatTimestamp(t.endDateTime):void 0};return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,s)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,s=>this.search({...e,page:s}))}async updateStatus(e){return this.http.put(`${this.basePath}/updateStatus`,e)}async updateTimes(e){let t={...e,startDateTime:a.formatTimestamp(e.startDateTime),endDateTime:a.formatTimestamp(e.endDateTime)};return this.http.put(`${this.basePath}/updateTimes`,t)}};var b=class extends i{constructor(e){super(e,"/v1/rates")}async list(e){let t=await this.http.get(this.basePath,e);return new o(t,s=>this.list({...e,page:s}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,s=>this.search({...e,page:s}))}};var R=class extends i{constructor(e){super(e,"/v1/tags")}async list(e){let t=await this.http.get(this.basePath,e);return new o(t,s=>this.list({...e,page:s}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,s=>this.search({...e,page:s}))}};var x=class extends i{constructor(e){super(e,"/v1/expenses")}async list(e){let t=await this.http.get(this.basePath,e);return new o(t,s=>this.list({...e,page:s}))}async create(e){let t={...e,dateTime:a.formatTimestamp(e.dateTime)};return this.http.post(this.basePath,t)}async update(e,t){let s={...t,dateTime:t.dateTime?a.formatTimestamp(t.dateTime):void 0};return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,s)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,s=>this.search({...e,page:s}))}async updateStatus(e,t){return this.http.put(`${this.basePath}/${e}/status`,t)}};var C=class extends i{constructor(e){super(e,"/v1/notes")}async list(e){let t=await this.http.get(this.basePath,e);return new o(t,s=>this.list({...e,page:s}))}async create(e){let t={...e,dateTime:a.formatTimestamp(e.dateTime)};return this.http.post(this.basePath,t)}async update(e,t){let s={...t,dateTime:a.formatTimestamp(t.dateTime)};return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,s)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,s=>this.search({...e,page:s}))}};var w=class extends i{constructor(e){super(e,"/v1/pauses")}async list(e){let t=await this.http.get(this.basePath,e);return new o(t,s=>this.list({...e,page:s}))}async create(e){let t={...e,startDateTime:a.formatTimestamp(e.startDateTime),endDateTime:a.formatTimestamp(e.endDateTime)};return this.http.post(this.basePath,t)}async update(e,t){let s={...t,startDateTime:a.formatTimestamp(t.startDateTime),endDateTime:a.formatTimestamp(t.endDateTime)};return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,s)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,s=>this.search({...e,page:s}))}};var D=class{constructor(e){this.http=e}async getProfile(){return this.http.get("/v1/profiles/me")}async updateProfile(e){return this.http.put("/v1/profiles/me",e)}};var k=class{constructor(e){this.http=e}async get(){return this.http.get("/v1/settings")}async update(e){return this.http.put("/v1/settings",e)}};var v=class extends i{constructor(e){super(e,"/v1/automations")}async list(e){let t=await this.http.get(this.basePath,e);return new o(t,s=>this.list({...e,page:s}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,s=>this.search({...e,page:s}))}};var A=class extends i{constructor(e){super(e,"/v1/documents")}async list(e){let t=await this.http.get(this.basePath,e);return new o(t,s=>this.list({...e,page:s}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,s=>this.search({...e,page:s}))}};var $=class{constructor(e){this.http=e}async get(){return this.http.get("/v1/timer")}async start(e){let t={...e,startDateTime:e.startDateTime?a.formatTimestamp(e.startDateTime):a.formatTimestamp()};return this.http.post("/v1/timer/start",t)}async stop(e){let t=e?{...e,endDateTime:e.endDateTime?a.formatTimestamp(e.endDateTime):a.formatTimestamp()}:{endDateTime:a.formatTimestamp()};return this.http.post("/v1/timer/stop",t)}async pause(e){let t=e?{...e,startDateTime:e.startDateTime?a.formatTimestamp(e.startDateTime):a.formatTimestamp()}:{startDateTime:a.formatTimestamp()};return this.http.post("/v1/timer/pause",t)}async resume(e){let t=e?{...e,endDateTime:e.endDateTime?a.formatTimestamp(e.endDateTime):a.formatTimestamp()}:{endDateTime:a.formatTimestamp()};return this.http.post("/v1/timer/resume",t)}async update(e){let t={...e,startDateTime:e.startDateTime?a.formatTimestamp(e.startDateTime):void 0};return this.http.put("/v1/timer/update",t)}};var N=class extends i{constructor(e){super(e,"/v1/todos")}async list(e){let t=await this.http.get(this.basePath,e);return new o(t,s=>this.list({...e,page:s}))}async create(e){let t={...e,dueDate:e.dueDate?a.formatTimestamp(e.dueDate):void 0};return this.http.post(this.basePath,t)}async update(e,t){let s={...t,dueDate:t.dueDate?a.formatTimestamp(t.dueDate):void 0};return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,s)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,s=>this.search({...e,page:s}))}};var U=class extends i{constructor(e){super(e,"/v1/webhooks")}async list(e){let t=await this.http.get(this.basePath,e);return new o(t,s=>this.list({...e,page:s}))}async create(e){return this.http.post(this.basePath,e)}async update(e,t){return this.http.put(`${this.basePath}/${encodeURIComponent(e)}`,t)}async get(e){return this.http.get(`${this.basePath}/${encodeURIComponent(e)}`)}async delete(e){return this.http.delete(`${this.basePath}/${encodeURIComponent(e)}`)}async search(e){let t=await this.http.post(`${this.basePath}/search`,e);return this.createNavigablePage(t,s=>this.search({...e,page:s}))}};var O=class{constructor(e){let t=this.createAuthentication(e),s={baseUrl:e.baseUrl||"https://api.timesheet.io",authentication:t,retryConfig:e.retryConfig||S.default(),httpClient:e.httpClient};this.apiClient=new L(s),this.organizations=new d(this.apiClient),this.teams=new f(this.apiClient),this.projects=new T(this.apiClient),this.tasks=new y(this.apiClient),this.rates=new b(this.apiClient),this.tags=new R(this.apiClient),this.expenses=new x(this.apiClient),this.notes=new C(this.apiClient),this.pauses=new w(this.apiClient),this.profile=new D(this.apiClient),this.settings=new k(this.apiClient),this.automations=new v(this.apiClient),this.documents=new A(this.apiClient),this.timer=new $(this.apiClient),this.todos=new N(this.apiClient),this.webhooks=new U(this.apiClient)}createAuthentication(e){if(e.apiKey)return new I(e.apiKey);if(e.oauth2Token)return new l(e.oauth2Token);if(e.oauth2)return new l(e.oauth2.clientId,e.oauth2.clientSecret,e.oauth2.refreshToken);if(e.authentication)return e.authentication;throw new Error("Authentication must be configured")}};function is(r){return new O(r)}export{L as ApiClient,I as ApiKeyAuth,v as AutomationResource,A as DocumentResource,x as ExpenseResource,o as NavigablePage,C as NoteResource,l as OAuth2Auth,d as OrganizationResource,w as PauseResource,D as ProfileResource,T as ProjectResource,b as RateResource,i as Resource,S as RetryConfig,k as SettingsResource,R as TagResource,y as TaskResource,f as TeamResource,$ as TimerResource,h as TimesheetApiError,q as TimesheetAuthError,O as TimesheetClient,E as TimesheetRateLimitError,N as TodoResource,U as WebhookResource,is as createClient};
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":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/config/RetryConfig.ts","../src/models/Page.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/index.ts"],"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 * 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 * 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","/**\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 { 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±HH: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 ±HH: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 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","import type { ApiClient } from '../http';\nimport type { Note, NoteCreateRequest, NoteListParams, NoteUpdateRequest, Page } 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","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 { 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 ExpenseResource,\n NoteResource,\n OrganizationResource,\n PauseResource,\n ProfileResource,\n ProjectResource,\n RateResource,\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\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\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\n const config: ClientConfig = {\n baseUrl: options.baseUrl || 'https://api.timesheet.io',\n authentication,\n retryConfig: options.retryConfig || RetryConfig.default(),\n httpClient: options.httpClient,\n };\n\n this.apiClient = new ApiClient(config);\n\n // Initialize 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 }\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 API.\n * @default 'https://api.timesheet.io'\n */\n baseUrl?: string;\n\n /**\n * Custom retry configuration.\n */\n retryConfig?: RetryConfig;\n\n /**\n * Custom HTTP client (axios instance).\n */\n httpClient?: AxiosInstance;\n}\n\n// Export convenience function\nexport function createClient(options: TimesheetClientOptions): TimesheetClient {\n return new TimesheetClient(options);\n}\n"],"mappings":"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","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","ms","resolve","ApiKeyAuth","apiKey","config","axios","jwt","_OAuth2Auth","accessTokenOrClientId","clientSecret","refreshToken","config","response","error","message","clientId","authorizationCode","redirectUri","accessToken","state","params","decoded","OAuth2Auth","RetryConfig","_RetryConfig","options","NavigablePage","data","nextPageLoader","currentPage","item","allItems","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","data","formattedData","DateUtils","id","params","response","page","RateResource","Resource","client","params","response","NavigablePage","page","data","id","TagResource","Resource","client","params","response","NavigablePage","page","data","id","ExpenseResource","Resource","client","params","response","NavigablePage","page","data","formattedData","DateUtils","id","NoteResource","Resource","client","params","response","NavigablePage","page","data","formattedData","DateUtils","id","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","response","NavigablePage","page","data","id","TimerResource","http","data","formattedData","DateUtils","TodoResource","Resource","client","params","response","NavigablePage","page","data","formattedData","DateUtils","id","WebhookResource","Resource","client","params","response","NavigablePage","page","data","id","TimesheetClient","options","authentication","config","RetryConfig","ApiClient","OrganizationResource","TeamResource","ProjectResource","TaskResource","RateResource","TagResource","ExpenseResource","NoteResource","PauseResource","ProfileResource","SettingsResource","AutomationResource","DocumentResource","TimerResource","TodoResource","WebhookResource","ApiKeyAuth","OAuth2Auth","createClient"]}