UNPKG

@timesheet/sdk

Version:
2 lines 20.5 kB
"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}); //# sourceMappingURL=index.js.map