tiime-sdk 2.2.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +35 -56
- package/dist/index.js +2 -2
- package/package.json +3 -1
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ interface AuthConfig {
|
|
|
7
7
|
password: string;
|
|
8
8
|
}
|
|
9
9
|
interface TiimeClientOptions {
|
|
10
|
-
companyId
|
|
10
|
+
companyId: number;
|
|
11
11
|
tokens?: AuthTokens;
|
|
12
12
|
email?: string;
|
|
13
13
|
password?: string;
|
|
@@ -436,28 +436,29 @@ interface MatchableDocument {
|
|
|
436
436
|
}[];
|
|
437
437
|
}
|
|
438
438
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
439
|
+
interface TokenStorage {
|
|
440
|
+
load(): AuthTokens | null;
|
|
441
|
+
save(tokens: AuthTokens): void;
|
|
442
|
+
clear(): void;
|
|
443
|
+
}
|
|
444
|
+
interface CredentialStorage {
|
|
445
|
+
load(): {
|
|
446
|
+
email: string;
|
|
447
|
+
password: string;
|
|
448
|
+
} | null;
|
|
449
|
+
save(email: string, password: string): void;
|
|
450
|
+
}
|
|
446
451
|
declare class TokenManager {
|
|
447
452
|
private tokens;
|
|
448
453
|
private credentials;
|
|
449
|
-
private
|
|
450
|
-
|
|
451
|
-
* @param options.tokens - Use these tokens directly (no disk I/O)
|
|
452
|
-
* @param options.email - Login with these credentials
|
|
453
|
-
* @param options.password - Login with these credentials
|
|
454
|
-
* @param options.persist - Save tokens/credentials to disk (default: true when no explicit auth)
|
|
455
|
-
*/
|
|
454
|
+
private tokenStorage;
|
|
455
|
+
private credentialStorage;
|
|
456
456
|
constructor(options?: {
|
|
457
457
|
tokens?: AuthTokens;
|
|
458
458
|
email?: string;
|
|
459
459
|
password?: string;
|
|
460
|
-
|
|
460
|
+
tokenStorage?: TokenStorage;
|
|
461
|
+
credentialStorage?: CredentialStorage;
|
|
461
462
|
});
|
|
462
463
|
login(email: string, password: string): Promise<AuthTokens>;
|
|
463
464
|
getValidToken(): Promise<string>;
|
|
@@ -468,8 +469,6 @@ declare class TokenManager {
|
|
|
468
469
|
expiresAt: Date | null;
|
|
469
470
|
};
|
|
470
471
|
private isExpired;
|
|
471
|
-
private loadFromDisk;
|
|
472
|
-
private saveToDisk;
|
|
473
472
|
}
|
|
474
473
|
|
|
475
474
|
interface FetchOptions {
|
|
@@ -480,10 +479,14 @@ interface FetchOptions {
|
|
|
480
479
|
}
|
|
481
480
|
type FetchFn = <T = unknown>(url: string, options?: FetchOptions) => Promise<T>;
|
|
482
481
|
|
|
483
|
-
declare class
|
|
484
|
-
|
|
485
|
-
|
|
482
|
+
declare class Resource {
|
|
483
|
+
protected fetch: FetchFn;
|
|
484
|
+
protected companyId: number;
|
|
486
485
|
constructor(fetch: FetchFn, companyId: number);
|
|
486
|
+
protected url(path: string): string;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
declare class BankAccountsResource extends Resource {
|
|
487
490
|
list(enabled?: boolean): Promise<BankAccount[]>;
|
|
488
491
|
get(bankAccountId: number): Promise<BankAccount>;
|
|
489
492
|
balance(): Promise<{
|
|
@@ -505,10 +508,7 @@ interface BankTransactionsListParams {
|
|
|
505
508
|
to?: string;
|
|
506
509
|
search?: string;
|
|
507
510
|
}
|
|
508
|
-
declare class BankTransactionsResource {
|
|
509
|
-
private fetch;
|
|
510
|
-
private companyId;
|
|
511
|
-
constructor(fetch: FetchFn, companyId: number);
|
|
511
|
+
declare class BankTransactionsResource extends Resource {
|
|
512
512
|
list(params?: BankTransactionsListParams): Promise<BankTransactionsResponse>;
|
|
513
513
|
listAll(params?: Omit<BankTransactionsListParams, "page">): Promise<BankTransaction[]>;
|
|
514
514
|
unimputed(): Promise<BankTransaction[]>;
|
|
@@ -535,20 +535,14 @@ interface ClientCreateParams {
|
|
|
535
535
|
siren_or_siret?: string;
|
|
536
536
|
professional?: boolean;
|
|
537
537
|
}
|
|
538
|
-
declare class ClientsResource {
|
|
539
|
-
private fetch;
|
|
540
|
-
private companyId;
|
|
541
|
-
constructor(fetch: FetchFn, companyId: number);
|
|
538
|
+
declare class ClientsResource extends Resource {
|
|
542
539
|
list(params?: ClientsListParams): Promise<Client[]>;
|
|
543
540
|
get(clientId: number): Promise<Client>;
|
|
544
541
|
create(params: ClientCreateParams): Promise<Client>;
|
|
545
542
|
search(query: string): Promise<Client[]>;
|
|
546
543
|
}
|
|
547
544
|
|
|
548
|
-
declare class CompanyResource {
|
|
549
|
-
private fetch;
|
|
550
|
-
private companyId;
|
|
551
|
-
constructor(fetch: FetchFn, companyId: number);
|
|
545
|
+
declare class CompanyResource extends Resource {
|
|
552
546
|
get(): Promise<Company>;
|
|
553
547
|
users(): Promise<unknown>;
|
|
554
548
|
appConfig(): Promise<unknown>;
|
|
@@ -565,10 +559,7 @@ interface DocumentsListParams {
|
|
|
565
559
|
page?: number;
|
|
566
560
|
pageSize?: number;
|
|
567
561
|
}
|
|
568
|
-
declare class DocumentsResource {
|
|
569
|
-
private fetch;
|
|
570
|
-
private companyId;
|
|
571
|
-
constructor(fetch: FetchFn, companyId: number);
|
|
562
|
+
declare class DocumentsResource extends Resource {
|
|
572
563
|
list(params?: DocumentsListParams): Promise<Document[]>;
|
|
573
564
|
categories(): Promise<DocumentCategory[]>;
|
|
574
565
|
preview(documentId: number): Promise<unknown>;
|
|
@@ -577,10 +568,7 @@ declare class DocumentsResource {
|
|
|
577
568
|
download(documentId: number): Promise<ArrayBuffer>;
|
|
578
569
|
}
|
|
579
570
|
|
|
580
|
-
declare class ExpenseReportsResource {
|
|
581
|
-
private fetch;
|
|
582
|
-
private companyId;
|
|
583
|
-
constructor(fetch: FetchFn, companyId: number);
|
|
571
|
+
declare class ExpenseReportsResource extends Resource {
|
|
584
572
|
list(sorts?: string): Promise<ExpenseReport[]>;
|
|
585
573
|
get(expenseReportId: number): Promise<ExpenseReport>;
|
|
586
574
|
create(params: ExpenseReportCreateParams): Promise<ExpenseReport>;
|
|
@@ -592,10 +580,7 @@ interface InvoicesListParams {
|
|
|
592
580
|
page?: number;
|
|
593
581
|
pageSize?: number;
|
|
594
582
|
}
|
|
595
|
-
declare class InvoicesResource {
|
|
596
|
-
private fetch;
|
|
597
|
-
private companyId;
|
|
598
|
-
constructor(fetch: FetchFn, companyId: number);
|
|
583
|
+
declare class InvoicesResource extends Resource {
|
|
599
584
|
list(params?: InvoicesListParams): Promise<Invoice[]>;
|
|
600
585
|
listAll(params?: {
|
|
601
586
|
sorts?: string;
|
|
@@ -614,19 +599,13 @@ declare class InvoicesResource {
|
|
|
614
599
|
}): Promise<Invoice>;
|
|
615
600
|
}
|
|
616
601
|
|
|
617
|
-
declare class LabelsResource {
|
|
618
|
-
private fetch;
|
|
619
|
-
private companyId;
|
|
620
|
-
constructor(fetch: FetchFn, companyId: number);
|
|
602
|
+
declare class LabelsResource extends Resource {
|
|
621
603
|
list(): Promise<Label[]>;
|
|
622
604
|
standard(): Promise<Label[]>;
|
|
623
605
|
tags(): Promise<Tag[]>;
|
|
624
606
|
}
|
|
625
607
|
|
|
626
|
-
declare class QuotationsResource {
|
|
627
|
-
private fetch;
|
|
628
|
-
private companyId;
|
|
629
|
-
constructor(fetch: FetchFn, companyId: number);
|
|
608
|
+
declare class QuotationsResource extends Resource {
|
|
630
609
|
list(expand?: string): Promise<Quotation[]>;
|
|
631
610
|
get(quotationId: number): Promise<Quotation>;
|
|
632
611
|
create(params: QuotationCreateParams): Promise<Quotation>;
|
|
@@ -635,7 +614,7 @@ declare class QuotationsResource {
|
|
|
635
614
|
}
|
|
636
615
|
|
|
637
616
|
declare class UsersResource {
|
|
638
|
-
|
|
617
|
+
protected fetch: FetchFn;
|
|
639
618
|
constructor(fetch: FetchFn);
|
|
640
619
|
me(): Promise<User>;
|
|
641
620
|
legalInformations(): Promise<unknown>;
|
|
@@ -646,7 +625,7 @@ declare class TiimeClient {
|
|
|
646
625
|
readonly fetch: FetchFn;
|
|
647
626
|
readonly tokenManager: TokenManager;
|
|
648
627
|
readonly companyId: number;
|
|
649
|
-
constructor(options
|
|
628
|
+
constructor(options: TiimeClientOptions & {
|
|
650
629
|
tokenManager?: TokenManager;
|
|
651
630
|
});
|
|
652
631
|
listCompanies(): Promise<Company[]>;
|
|
@@ -676,4 +655,4 @@ declare class TiimeError extends Error {
|
|
|
676
655
|
};
|
|
677
656
|
}
|
|
678
657
|
|
|
679
|
-
export { type AccountingPeriod, type Address, type ApeCode, type AuthConfig, type AuthTokens, type Bank, type BankAccount, type BankTransaction, type BankTransactionsResponse, type Client, type Company, type Country, type DashboardBlock, type Document, type DocumentCategory, type DocumentMatching, type ExpenseReport, type ExpenseReportCreateParams, type Imputation, type ImputationLabel, type ImputationParams, type Invoice, type InvoiceCreateParams, type InvoiceLine, type InvoiceSendParams, type Label, type LabelSuggestion, type MatchableDocument, type PaginatedResponse, type Quotation, type QuotationCreateParams, type QuotationSendParams, type Tag, TiimeClient, type TiimeClientOptions, TiimeError, TokenManager, type User, type VatSystem
|
|
658
|
+
export { type AccountingPeriod, type Address, type ApeCode, type AuthConfig, type AuthTokens, type Bank, type BankAccount, type BankTransaction, type BankTransactionsResponse, type Client, type Company, type Country, type CredentialStorage, type DashboardBlock, type Document, type DocumentCategory, type DocumentMatching, type ExpenseReport, type ExpenseReportCreateParams, type Imputation, type ImputationLabel, type ImputationParams, type Invoice, type InvoiceCreateParams, type InvoiceLine, type InvoiceSendParams, type Label, type LabelSuggestion, type MatchableDocument, type PaginatedResponse, type Quotation, type QuotationCreateParams, type QuotationSendParams, type Tag, TiimeClient, type TiimeClientOptions, TiimeError, TokenManager, type TokenStorage, type User, type VatSystem };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {execSync}from'child_process';import {existsSync,readFileSync,writeFileSync,mkdirSync}from'fs';import {homedir}from'os';import {join}from'path';var z=(s,e,t)=>{let n=new URL(e,s.endsWith("/")?s:`${s}/`);if(t)for(let[i,r]of Object.entries(t))r!=null&&n.searchParams.set(i,String(r));return n.href},U=s=>new Promise(e=>setTimeout(e,s)),J=s=>!!s?.includes("application/json")||!!s?.includes("+json"),D=s=>{let e=s.retry??0,t=s.retryDelay??500,n=new Set(s.retryStatusCodes??[]);return async(i,r)=>{let o=z(s.baseURL,i,r?.query),m=new Headers(s.headers);if(r?.headers)for(let[c,a]of Object.entries(r.headers))m.set(c,a);let u;r?.body!==void 0&&(r.body instanceof FormData?u=r.body:(m.set("Content-Type","application/json"),u=JSON.stringify(r.body))),s.onRequest&&await s.onRequest({options:{headers:m}});let h;for(let c=0;c<=e;c++){c>0&&await U(t);let a;try{a=await fetch(o,{method:r?.method??"GET",headers:m,body:u});}catch(l){if(h=l,c<e)continue;throw l}if(!a.ok&&n.has(a.status)&&(h=a,c<e))continue;if(!a.ok&&s.onResponseError){let l;try{l=await a.clone().json();}catch{}let L=Object.assign(a,{_data:l});s.onResponseError({request:o,response:L});}let R=a.headers.get("content-type");return a.status===204||!R?void 0:J(R)?a.json():a.arrayBuffer()}throw h}},q=async(s,e)=>{let t=await fetch(s,e);if(!t.ok)throw new Error(`HTTP ${t.status}: ${t.statusText}`);return t.json()};var Q="auth0.tiime.fr",G="iEbsbe3o66gcTBfGRa012kj1Rb6vjAND",K="https://chronos/",p=join(homedir(),".config","tiime"),f=join(p,"auth.json"),O=join(p,"config.json"),N="tiime-cli",B="tiime-credentials",V=(s,e)=>{try{let t=JSON.stringify({email:s,password:e});return execSync(`security add-generic-password -a "${N}" -s "${B}" -w '${t.replace(/'/g,"'\\''")}' -U`,{stdio:"ignore"}),!0}catch{return false}},W=()=>{try{let s=execSync(`security find-generic-password -a "${N}" -s "${B}" -w`,{encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim(),e=JSON.parse(s);return typeof e=="object"&&e!==null&&"email"in e&&"password"in e&&typeof e.email=="string"&&typeof e.password=="string"?e:null}catch{return null}},Y=(s,e)=>{existsSync(p)||mkdirSync(p,{recursive:true});let t=join(p,"credentials.json");writeFileSync(t,JSON.stringify({email:s,password:e},null,2),{mode:384});},X=()=>{try{let s=join(p,"credentials.json");if(existsSync(s)){let e=JSON.parse(readFileSync(s,"utf-8"));if(typeof e=="object"&&e!==null&&"email"in e&&"password"in e&&typeof e.email=="string"&&typeof e.password=="string")return e}}catch{}return null},Z=(s,e)=>{V(s,e)||Y(s,e);},ee=()=>W()??X(),A=s=>{if(s)return s;let e=process.env.TIIME_COMPANY_ID;if(e){let t=Number.parseInt(e,10);if(!Number.isNaN(t))return t}try{if(existsSync(O)){let t=JSON.parse(readFileSync(O,"utf-8"));if(t.companyId)return t.companyId}}catch{}throw new Error("No company ID configured. Set TIIME_COMPANY_ID env var, pass companyId option, or run `tiime company use --id <ID>`.")},y=class{tokens=null;credentials=null;persist;constructor(e={}){let t=e.tokens||e.email&&e.password;if(this.persist=e.persist??!t,e.tokens){this.tokens=e.tokens;return}if(e.email&&e.password){this.credentials={email:e.email,password:e.password};return}let n=process.env.TIIME_ACCESS_TOKEN;if(n){this.tokens={access_token:n,expires_at:Number.MAX_SAFE_INTEGER};return}let i=process.env.TIIME_EMAIL,r=process.env.TIIME_PASSWORD;if(i&&r){this.credentials={email:i,password:r};return}this.loadFromDisk();}async login(e,t){let n=await q(`https://${Q}/oauth/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({grant_type:"password",client_id:G,audience:K,scope:"openid email",username:e,password:t})});return this.tokens={access_token:n.access_token,expires_at:Date.now()+n.expires_in*1e3},this.persist&&(this.saveToDisk(),Z(e,t)),this.tokens}async getValidToken(){if(!this.tokens||this.isExpired()){let e=this.credentials??ee();if(e)return (await this.login(e.email,e.password)).access_token;throw new Error(this.tokens?"Token expired. Provide credentials via options, TIIME_EMAIL/TIIME_PASSWORD env vars, or run `tiime auth login`.":"Not authenticated. Provide credentials via options, TIIME_EMAIL/TIIME_PASSWORD env vars, or run `tiime auth login`.")}return this.tokens.access_token}isAuthenticated(){return this.tokens!==null&&!this.isExpired()}logout(){this.tokens=null,existsSync(f)&&writeFileSync(f,"{}");}getTokenInfo(){if(!this.tokens)return {email:null,expiresAt:null};try{return {email:JSON.parse(Buffer.from(this.tokens.access_token.split(".")[1],"base64").toString())["tiime/userEmail"]||null,expiresAt:new Date(this.tokens.expires_at)}}catch{return {email:null,expiresAt:new Date(this.tokens.expires_at)}}}isExpired(){return this.tokens?Date.now()>=this.tokens.expires_at-6e4:true}loadFromDisk(){try{if(existsSync(f)){let e=JSON.parse(readFileSync(f,"utf-8"));e.access_token&&e.expires_at&&(this.tokens=e);}}catch{}}saveToDisk(){existsSync(p)||mkdirSync(p,{recursive:true}),writeFileSync(f,JSON.stringify(this.tokens,null,2));}};var b=class extends Error{constructor(t,n,i,r){super(t);this.status=n;this.endpoint=i;this.details=r;this.name="TiimeError";}toJSON(){return {error:this.name,message:this.message,status:this.status,endpoint:this.endpoint,details:this.details}}};var _=class{constructor(e,t){this.fetch=e;this.companyId=t;}list(e){return this.fetch(`/companies/${this.companyId}/bank_accounts`,{query:e!==void 0?{enabled:e}:void 0})}get(e){return this.fetch(`/companies/${this.companyId}/bank_accounts/${e}`)}async balance(){return (await this.list(true)).map(t=>({name:t.name,balance_amount:t.balance_amount,currency:t.balance_currency}))}};var I=class{constructor(e,t){this.fetch=e;this.companyId=t;}list(e){let t=((e?.page??1)-1)*(e?.pageSize??100),n=t+(e?.pageSize??100),{page:i,pageSize:r,from:o,to:m,search:u,...h}=e??{},c={...h};return o&&(c.transaction_date_start=o),m&&(c.transaction_date_end=m),u&&(c.wording=u),this.fetch(`/companies/${this.companyId}/bank_transactions`,{query:{hide_refused:false,...c},headers:{Accept:"application/vnd.tiime.bank_transactions.v2+json",Range:`items=${t}-${n}`}})}async listAll(e){let t=e?.pageSize??200,n=[],i=1,r=true;for(;r;){let o=await this.list({...e,page:i,pageSize:t});n.push(...o.transactions),r=o.transactions.length===t,i++;}return n}unimputed(){return this.fetch(`/companies/${this.companyId}/bank_transactions/unimputed`)}get(e){return this.fetch(`/companies/${this.companyId}/bank_transactions/${e}`)}labelSuggestions(e){return this.fetch(`/companies/${this.companyId}/bank_transactions/${e}/label_suggestions`,{headers:{Accept:"application/vnd.tiime.bank_transactions.label_suggestions.v2+json"}})}impute(e,t){return this.fetch(`/companies/${this.companyId}/bank_transactions/${e}`,{method:"PATCH",body:{imputations:t}})}matchDocuments(e,t){return this.fetch(`/companies/${this.companyId}/bank_transactions/${e}/document_matchings`,{method:"PUT",body:{documents:t.map(n=>({id:n}))}})}getMatchings(e){return this.fetch(`/companies/${this.companyId}/bank_transactions/${e}/matchings`)}};var v=class{constructor(e,t){this.fetch=e;this.companyId=t;}list(e){return this.fetch(`/companies/${this.companyId}/clients`,{query:e,headers:{Accept:"application/vnd.tiime.timeline.v2+json",Range:"items=0-*"}})}get(e){return this.fetch(`/companies/${this.companyId}/clients/${e}`)}create(e){return this.fetch(`/companies/${this.companyId}/clients`,{method:"POST",body:e})}search(e){return this.fetch(`/companies/${this.companyId}/clients`,{query:{search:e},headers:{Accept:"application/vnd.tiime.timeline.v2+json",Range:"items=0-*"}})}};var k=class{constructor(e,t){this.fetch=e;this.companyId=t;}get(){return this.fetch(`/companies/${this.companyId}`)}users(){return this.fetch(`/companies/${this.companyId}/users`)}appConfig(){return this.fetch(`/companies/${this.companyId}/app_config`)}accountingPeriod(e=1){return this.fetch(`/companies/${this.companyId}/accounting_period/current`,{query:{range_year:e}})}tiles(e){return this.fetch(`/companies/${this.companyId}/tiles`,{query:{keys:e.join(",")}})}dashboardBlocks(e="monitoring"){return this.fetch(`/companies/${this.companyId}/dashboard_blocks`,{query:{sorts:"rank:asc",display_group:e}})}};var w=class{constructor(e,t){this.fetch=e;this.companyId=t;}list(e){let t=((e?.page??1)-1)*(e?.pageSize??25),n=t+(e?.pageSize??25),{page:i,pageSize:r,...o}=e??{};return this.fetch(`/companies/${this.companyId}/documents`,{query:{sorts:"created_at:desc",expand:"file_family,preview_available",...o},headers:{Accept:"application/vnd.tiime.documents.v2+json,application/vnd.tiime.docs.query+json,application/vnd.tiime.docs.imputation+json",Range:`items=${t}-${n}`}})}categories(){return this.fetch(`/companies/${this.companyId}/document_categories`,{headers:{Accept:"application/vnd.tiime.documents.v3+json"}})}preview(e){return this.fetch(`/companies/${this.companyId}/documents/${e}/preview`)}upload(e,t,n){let i=new FormData;return i.append("file",new Blob([e]),t),n&&i.append("type",n),this.fetch(`/companies/${this.companyId}/documents`,{method:"POST",body:i})}searchMatchable(e){return this.fetch(`/companies/${this.companyId}/documents`,{query:{matchable:true,q:e},headers:{Accept:"application/vnd.tiime.documents.v3+json,application/vnd.tiime.docs.imputation+json",Range:"items=0-25"}})}async download(e){return this.fetch(`/companies/${this.companyId}/documents/${e}/download`,{headers:{Accept:"application/octet-stream"}})}};var T=class{constructor(e,t){this.fetch=e;this.companyId=t;}list(e="metadata.date:desc"){return this.fetch(`/companies/${this.companyId}/expense_reports`,{query:{expand:"total_amount",sorts:e},headers:{Range:"items=0-25"}})}get(e){return this.fetch(`/companies/${this.companyId}/expense_reports/${e}`)}create(e){return this.fetch(`/companies/${this.companyId}/expense_reports`,{method:"POST",body:e})}};var te={template:"advanced",status:"draft",due_date_mode:"thirty_days",title_enabled:true,free_field_enabled:false,free_field:"",discount_enabled:false,bank_detail_enabled:true,payment_condition_enabled:true,payment_condition:"En cas de retard de paiement, une p\xE9nalit\xE9 de 3 fois le taux d'int\xE9r\xEAt l\xE9gal sera appliqu\xE9e, \xE0 laquelle s'ajoutera une indemnit\xE9 forfaitaire pour frais de recouvrement de 40\u20AC.",text_lines:[]},P=class{constructor(e,t){this.fetch=e;this.companyId=t;}list(e){let t=((e?.page??1)-1)*(e?.pageSize??25),n=t+(e?.pageSize??25),i={sorts:e?.sorts??"invoice_number:desc"};return e?.status&&(i.status=e.status),this.fetch(`/companies/${this.companyId}/invoices`,{query:i,headers:{Range:`items=${t}-${n}`}})}async listAll(e){let t=e?.pageSize??100,n=[],i=1,r=true;for(;r;){let o=await this.list({sorts:e?.sorts,status:e?.status,page:i,pageSize:t});n.push(...o),r=o.length===t,i++;}return n}get(e){return this.fetch(`/companies/${this.companyId}/invoices/${e}`)}create(e){let t={...te,...e,lines:e.lines?.map(n=>({...n}))};for(let n of t.lines??[])n.line_amount=n.quantity*n.unit_amount,n.sequence??=1,n.invoicing_category_type??="benefit",n.discount_description??="",n.discount_amount??=null,n.discount_percentage??=null;return this.fetch(`/companies/${this.companyId}/invoices`,{method:"POST",body:t})}update(e,t){return this.fetch(`/companies/${this.companyId}/invoices/${e}`,{method:"PUT",body:t})}send(e,t){return this.fetch(`/companies/${this.companyId}/invoices/${e}/send`,{method:"POST",body:t})}async downloadPdf(e){return this.fetch(`/companies/${this.companyId}/invoices/${e}/pdf`,{headers:{Accept:"application/pdf"}})}delete(e){return this.fetch(`/companies/${this.companyId}/invoices/${e}`,{method:"DELETE"})}async duplicate(e,t){let n=await this.get(e),i=new Date().toISOString().split("T")[0],r=n.lines.map(o=>({description:o.description,quantity:t?.quantity??o.quantity,unit_amount:o.unit_amount,vat_type:o.vat_type,invoicing_unit:o.invoicing_unit,invoicing_category_type:o.invoicing_category_type,article:o.article}));return this.create({client:n.client_id?{id:n.client_id}:null,emission_date:t?.emission_date??i,title:n.title,title_enabled:!!n.title,lines:r,status:"draft"})}};var $=class{constructor(e,t){this.fetch=e;this.companyId=t;}list(){return this.fetch(`/companies/${this.companyId}/labels`,{headers:{Accept:"application/vnd.tiime.labels.v2+json"}})}standard(){return this.fetch(`/companies/${this.companyId}/standard_labels`)}tags(){return this.fetch(`/companies/${this.companyId}/tags`,{query:{expand:"tag_detail"}})}};var C=class{constructor(e,t){this.fetch=e;this.companyId=t;}list(e="invoices"){return this.fetch(`/companies/${this.companyId}/quotations`,{query:{expand:e},headers:{Range:"items=0-25"}})}get(e){return this.fetch(`/companies/${this.companyId}/quotations/${e}`)}create(e){let t={...e,lines:e.lines?.map(n=>({...n}))};for(let n of t.lines??[])n.line_amount=n.quantity*n.unit_amount,n.sequence??=1,n.invoicing_category_type??="benefit",n.discount_description??="",n.discount_amount??=null,n.discount_percentage??=null;return this.fetch(`/companies/${this.companyId}/quotations`,{method:"POST",body:t})}async downloadPdf(e){return this.fetch(`/companies/${this.companyId}/quotations/${e}/pdf`,{headers:{Accept:"application/pdf"}})}send(e,t){return this.fetch(`/companies/${this.companyId}/quotations/${e}/send`,{method:"POST",body:t})}};var F=class{constructor(e){this.fetch=e;}me(){return this.fetch("/users/me")}legalInformations(){return this.fetch("/users/me/legal_informations")}settings(e){return this.fetch(`/users/me/companies/${e}/settings`)}};var ne="https://chronos-api.tiime-apps.com/v1",E=class{fetch;tokenManager;companyId;constructor(e={}){this.companyId=A(e.companyId),this.tokenManager=e.tokenManager??new y({tokens:e.tokens,email:e.email,password:e.password}),this.fetch=D({baseURL:ne,retry:2,retryDelay:500,retryStatusCodes:[408,429,500,502,503,504],headers:{"tiime-app":"tiime","tiime-app-version":"4.30.3","tiime-app-platform":"cli"},onRequest:async({options:t})=>{let n=await this.tokenManager.getValidToken();t.headers.set("Authorization",`Bearer ${n}`);},onResponseError:({request:t,response:n})=>{throw new b(n.statusText||`HTTP ${n.status}`,n.status,String(t),n._data)}});}listCompanies(){return this.fetch("/companies",{headers:{Accept:"application/vnd.tiime.companies.v2+json",Range:"items=0-101"}})}get users(){return new F(this.fetch)}get company(){return new k(this.fetch,this.companyId)}get clients(){return new v(this.fetch,this.companyId)}get invoices(){return new P(this.fetch,this.companyId)}get quotations(){return new C(this.fetch,this.companyId)}get bankAccounts(){return new _(this.fetch,this.companyId)}get bankTransactions(){return new I(this.fetch,this.companyId)}get documents(){return new w(this.fetch,this.companyId)}get expenseReports(){return new T(this.fetch,this.companyId)}get labels(){return new $(this.fetch,this.companyId)}};
|
|
2
|
-
export{
|
|
1
|
+
var E=(s,e,t)=>{let n=new URL(e,s.endsWith("/")?s:`${s}/`);if(t)for(let[r,i]of Object.entries(t))i!=null&&n.searchParams.set(r,String(i));return n.href},q=s=>new Promise(e=>setTimeout(e,s)),D=s=>!!s?.includes("application/json")||!!s?.includes("+json"),I=s=>{let e=s.retry??0,t=s.retryDelay??500,n=new Set(s.retryStatusCodes??[]);return async(r,i)=>{let o=E(s.baseURL,r,i?.query),h=new Headers(s.headers);if(i?.headers)for(let[u,c]of Object.entries(i.headers))h.set(u,c);let l;i?.body!==void 0&&(i.body instanceof FormData?l=i.body:(h.set("Content-Type","application/json"),l=JSON.stringify(i.body))),s.onRequest&&await s.onRequest({options:{headers:h}});let p;for(let u=0;u<=e;u++){u>0&&await q(t);let c;try{c=await fetch(o,{method:i?.method??"GET",headers:h,body:l});}catch(m){if(p=m,u<e)continue;throw m}if(!c.ok&&n.has(c.status)&&(p=c,u<e))continue;if(!c.ok&&s.onResponseError){let m;try{m=await c.clone().json();}catch{}let C=Object.assign(c,{_data:m});s.onResponseError({request:o,response:C});}let A=c.headers.get("content-type");return c.status===204||!A?void 0:D(A)?c.json():c.arrayBuffer()}throw p}},R=async(s,e)=>{let t=await fetch(s,e);if(!t.ok)throw new Error(`HTTP ${t.status}: ${t.statusText}`);return t.json()};var $="auth0.tiime.fr",B="iEbsbe3o66gcTBfGRa012kj1Rb6vjAND",M="https://chronos/",d=class{tokens=null;credentials=null;tokenStorage;credentialStorage;constructor(e={}){if(this.tokenStorage=e.tokenStorage??null,this.credentialStorage=e.credentialStorage??null,e.tokens){this.tokens=e.tokens;return}if(e.email&&e.password){this.credentials={email:e.email,password:e.password};return}let t=process.env.TIIME_ACCESS_TOKEN;if(t){this.tokens={access_token:t,expires_at:Number.MAX_SAFE_INTEGER};return}let n=process.env.TIIME_EMAIL,r=process.env.TIIME_PASSWORD;if(n&&r){this.credentials={email:n,password:r};return}this.tokenStorage&&(this.tokens=this.tokenStorage.load());}async login(e,t){let n=await R(`https://${$}/oauth/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({grant_type:"password",client_id:B,audience:M,scope:"openid email",username:e,password:t})});return this.tokens={access_token:n.access_token,expires_at:Date.now()+n.expires_in*1e3},this.tokenStorage?.save(this.tokens),this.credentialStorage?.save(e,t),this.tokens}async getValidToken(){if(!this.tokens||this.isExpired()){let e=this.credentials??this.credentialStorage?.load()??null;if(e)return (await this.login(e.email,e.password)).access_token;throw new Error(this.tokens?"Token expired. Provide credentials via options, TIIME_EMAIL/TIIME_PASSWORD env vars, or run `tiime auth login`.":"Not authenticated. Provide credentials via options, TIIME_EMAIL/TIIME_PASSWORD env vars, or run `tiime auth login`.")}return this.tokens.access_token}isAuthenticated(){return this.tokens!==null&&!this.isExpired()}logout(){this.tokens=null,this.tokenStorage?.clear();}getTokenInfo(){if(!this.tokens)return {email:null,expiresAt:null};try{return {email:JSON.parse(Buffer.from(this.tokens.access_token.split(".")[1],"base64").toString())["tiime/userEmail"]||null,expiresAt:new Date(this.tokens.expires_at)}}catch{return {email:null,expiresAt:new Date(this.tokens.expires_at)}}}isExpired(){return this.tokens?Date.now()>=this.tokens.expires_at-6e4:true}};var g=class extends Error{constructor(t,n,r,i){super(t);this.status=n;this.endpoint=r;this.details=i;this.name="TiimeError";}toJSON(){return {error:this.name,message:this.message,status:this.status,endpoint:this.endpoint,details:this.details}}};var a=class{constructor(e,t){this.fetch=e;this.companyId=t;}url(e){return `companies/${this.companyId}${e}`}};var f=class extends a{list(e){return this.fetch(this.url("/bank_accounts"),{query:e!==void 0?{enabled:e}:void 0})}get(e){return this.fetch(this.url(`/bank_accounts/${e}`))}async balance(){return (await this.list(true)).map(t=>({name:t.name,balance_amount:t.balance_amount,currency:t.balance_currency}))}};var y=class extends a{list(e){let t=((e?.page??1)-1)*(e?.pageSize??100),n=t+(e?.pageSize??100),{page:r,pageSize:i,from:o,to:h,search:l,...p}=e??{},u={...p};return o&&(u.transaction_date_start=o),h&&(u.transaction_date_end=h),l&&(u.wording=l),this.fetch(this.url("/bank_transactions"),{query:{hide_refused:false,...u},headers:{Accept:"application/vnd.tiime.bank_transactions.v2+json",Range:`items=${t}-${n}`}})}async listAll(e){let t=e?.pageSize??200,n=[],r=1,i=true;for(;i;){let o=await this.list({...e,page:r,pageSize:t});n.push(...o.transactions),i=o.transactions.length===t,r++;}return n}unimputed(){return this.fetch(this.url("/bank_transactions/unimputed"))}get(e){return this.fetch(this.url(`/bank_transactions/${e}`))}labelSuggestions(e){return this.fetch(this.url(`/bank_transactions/${e}/label_suggestions`),{headers:{Accept:"application/vnd.tiime.bank_transactions.label_suggestions.v2+json"}})}impute(e,t){return this.fetch(this.url(`/bank_transactions/${e}`),{method:"PATCH",body:{imputations:t}})}matchDocuments(e,t){return this.fetch(this.url(`/bank_transactions/${e}/document_matchings`),{method:"PUT",body:{documents:t.map(n=>({id:n}))}})}getMatchings(e){return this.fetch(this.url(`/bank_transactions/${e}/matchings`))}};var k=class extends a{list(e){return this.fetch(this.url("/clients"),{query:e,headers:{Accept:"application/vnd.tiime.timeline.v2+json",Range:"items=0-*"}})}get(e){return this.fetch(this.url(`/clients/${e}`))}create(e){return this.fetch(this.url("/clients"),{method:"POST",body:e})}search(e){return this.fetch(this.url("/clients"),{query:{search:e},headers:{Accept:"application/vnd.tiime.timeline.v2+json",Range:"items=0-*"}})}};var b=class extends a{get(){return this.fetch(this.url(""))}users(){return this.fetch(this.url("/users"))}appConfig(){return this.fetch(this.url("/app_config"))}accountingPeriod(e=1){return this.fetch(this.url("/accounting_period/current"),{query:{range_year:e}})}tiles(e){return this.fetch(this.url("/tiles"),{query:{keys:e.join(",")}})}dashboardBlocks(e="monitoring"){return this.fetch(this.url("/dashboard_blocks"),{query:{sorts:"rank:asc",display_group:e}})}};var _=class extends a{list(e){let t=((e?.page??1)-1)*(e?.pageSize??25),n=t+(e?.pageSize??25),{page:r,pageSize:i,...o}=e??{};return this.fetch(this.url("/documents"),{query:{sorts:"created_at:desc",expand:"file_family,preview_available",...o},headers:{Accept:"application/vnd.tiime.documents.v2+json,application/vnd.tiime.docs.query+json,application/vnd.tiime.docs.imputation+json",Range:`items=${t}-${n}`}})}categories(){return this.fetch(this.url("/document_categories"),{headers:{Accept:"application/vnd.tiime.documents.v3+json"}})}preview(e){return this.fetch(this.url(`/documents/${e}/preview`))}upload(e,t,n){let r=new FormData;return r.append("file",new Blob([e]),t),n&&r.append("type",n),this.fetch(this.url("/documents"),{method:"POST",body:r})}searchMatchable(e){return this.fetch(this.url("/documents"),{query:{matchable:true,q:e},headers:{Accept:"application/vnd.tiime.documents.v3+json,application/vnd.tiime.docs.imputation+json",Range:"items=0-25"}})}async download(e){return this.fetch(this.url(`/documents/${e}/download`),{headers:{Accept:"application/octet-stream"}})}};var v=class extends a{list(e="metadata.date:desc"){return this.fetch(this.url("/expense_reports"),{query:{expand:"total_amount",sorts:e},headers:{Range:"items=0-25"}})}get(e){return this.fetch(this.url(`/expense_reports/${e}`))}create(e){return this.fetch(this.url("/expense_reports"),{method:"POST",body:e})}};var w=class extends a{list(e){let t=((e?.page??1)-1)*(e?.pageSize??25),n=t+(e?.pageSize??25),r={sorts:e?.sorts??"invoice_number:desc"};return e?.status&&(r.status=e.status),this.fetch(this.url("/invoices"),{query:r,headers:{Range:`items=${t}-${n}`}})}async listAll(e){let t=e?.pageSize??100,n=[],r=1,i=true;for(;i;){let o=await this.list({sorts:e?.sorts,status:e?.status,page:r,pageSize:t});n.push(...o),i=o.length===t,r++;}return n}get(e){return this.fetch(this.url(`/invoices/${e}`))}create(e){let t={...e,lines:e.lines?.map(n=>({...n}))};for(let n of t.lines??[])n.line_amount=n.quantity*n.unit_amount,n.sequence??=1,n.invoicing_category_type??="benefit",n.discount_description??="",n.discount_amount??=null,n.discount_percentage??=null;return this.fetch(this.url("/invoices"),{method:"POST",body:t})}update(e,t){return this.fetch(this.url(`/invoices/${e}`),{method:"PUT",body:t})}send(e,t){return this.fetch(this.url(`/invoices/${e}/send`),{method:"POST",body:t})}async downloadPdf(e){return this.fetch(this.url(`/invoices/${e}/pdf`),{headers:{Accept:"application/pdf"}})}delete(e){return this.fetch(this.url(`/invoices/${e}`),{method:"DELETE"})}async duplicate(e,t){let n=await this.get(e),r=new Date().toISOString().split("T")[0],i=n.lines.map(o=>({description:o.description,quantity:t?.quantity??o.quantity,unit_amount:o.unit_amount,vat_type:o.vat_type,invoicing_unit:o.invoicing_unit,invoicing_category_type:o.invoicing_category_type,article:o.article}));return this.create({client:n.client_id?{id:n.client_id}:null,emission_date:t?.emission_date??r,title:n.title,title_enabled:!!n.title,lines:i,status:"draft"})}};var T=class extends a{list(){return this.fetch(this.url("/labels"),{headers:{Accept:"application/vnd.tiime.labels.v2+json"}})}standard(){return this.fetch(this.url("/standard_labels"))}tags(){return this.fetch(this.url("/tags"),{query:{expand:"tag_detail"}})}};var S=class extends a{list(e="invoices"){return this.fetch(this.url("/quotations"),{query:{expand:e},headers:{Range:"items=0-25"}})}get(e){return this.fetch(this.url(`/quotations/${e}`))}create(e){let t={...e,lines:e.lines?.map(n=>({...n}))};for(let n of t.lines??[])n.line_amount=n.quantity*n.unit_amount,n.sequence??=1,n.invoicing_category_type??="benefit",n.discount_description??="",n.discount_amount??=null,n.discount_percentage??=null;return this.fetch(this.url("/quotations"),{method:"POST",body:t})}async downloadPdf(e){return this.fetch(this.url(`/quotations/${e}/pdf`),{headers:{Accept:"application/pdf"}})}send(e,t){return this.fetch(this.url(`/quotations/${e}/send`),{method:"POST",body:t})}};var P=class{constructor(e){this.fetch=e;}me(){return this.fetch("users/me")}legalInformations(){return this.fetch("users/me/legal_informations")}settings(e){return this.fetch(`users/me/companies/${e}/settings`)}};var O="https://chronos-api.tiime-apps.com/v1",x=class{fetch;tokenManager;companyId;constructor(e){this.companyId=e.companyId,this.tokenManager=e.tokenManager??new d({tokens:e.tokens,email:e.email,password:e.password}),this.fetch=I({baseURL:O,retry:2,retryDelay:500,retryStatusCodes:[408,429,500,502,503,504],headers:{"tiime-app":"tiime","tiime-app-version":"4.30.3","tiime-app-platform":"cli"},onRequest:async({options:t})=>{let n=await this.tokenManager.getValidToken();t.headers.set("Authorization",`Bearer ${n}`);},onResponseError:({request:t,response:n})=>{throw new g(n.statusText||`HTTP ${n.status}`,n.status,String(t),n._data)}});}listCompanies(){return this.fetch("companies",{headers:{Accept:"application/vnd.tiime.companies.v2+json",Range:"items=0-101"}})}get users(){return new P(this.fetch)}get company(){return new b(this.fetch,this.companyId)}get clients(){return new k(this.fetch,this.companyId)}get invoices(){return new w(this.fetch,this.companyId)}get quotations(){return new S(this.fetch,this.companyId)}get bankAccounts(){return new f(this.fetch,this.companyId)}get bankTransactions(){return new y(this.fetch,this.companyId)}get documents(){return new _(this.fetch,this.companyId)}get expenseReports(){return new v(this.fetch,this.companyId)}get labels(){return new T(this.fetch,this.companyId)}};
|
|
2
|
+
export{x as TiimeClient,g as TiimeError,d as TokenManager};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tiime-sdk",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"description": "TypeScript SDK for Tiime accounting API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@biomejs/biome": "^2.4.6",
|
|
49
49
|
"@types/node": "^25.3.5",
|
|
50
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
50
51
|
"tsup": "^8.5.1",
|
|
51
52
|
"typescript": "^5.9.3",
|
|
52
53
|
"vitest": "^4.0.18"
|
|
@@ -56,6 +57,7 @@
|
|
|
56
57
|
"dev": "tsup --watch",
|
|
57
58
|
"lint": "biome check src/",
|
|
58
59
|
"format": "biome format --write src/",
|
|
60
|
+
"typecheck": "tsc",
|
|
59
61
|
"test": "vitest run",
|
|
60
62
|
"test:watch": "vitest",
|
|
61
63
|
"release": "changeset publish"
|