tiime-sdk 2.1.2 → 2.2.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.d.ts CHANGED
@@ -1,5 +1,3 @@
1
- import { $Fetch } from 'ofetch';
2
-
3
1
  interface AuthTokens {
4
2
  access_token: string;
5
3
  expires_at: number;
@@ -474,10 +472,18 @@ declare class TokenManager {
474
472
  private saveToDisk;
475
473
  }
476
474
 
475
+ interface FetchOptions {
476
+ method?: string;
477
+ headers?: Record<string, string>;
478
+ body?: unknown;
479
+ query?: Record<string, unknown> | object;
480
+ }
481
+ type FetchFn = <T = unknown>(url: string, options?: FetchOptions) => Promise<T>;
482
+
477
483
  declare class BankAccountsResource {
478
484
  private fetch;
479
485
  private companyId;
480
- constructor(fetch: $Fetch, companyId: number);
486
+ constructor(fetch: FetchFn, companyId: number);
481
487
  list(enabled?: boolean): Promise<BankAccount[]>;
482
488
  get(bankAccountId: number): Promise<BankAccount>;
483
489
  balance(): Promise<{
@@ -502,7 +508,7 @@ interface BankTransactionsListParams {
502
508
  declare class BankTransactionsResource {
503
509
  private fetch;
504
510
  private companyId;
505
- constructor(fetch: $Fetch, companyId: number);
511
+ constructor(fetch: FetchFn, companyId: number);
506
512
  list(params?: BankTransactionsListParams): Promise<BankTransactionsResponse>;
507
513
  listAll(params?: Omit<BankTransactionsListParams, "page">): Promise<BankTransaction[]>;
508
514
  unimputed(): Promise<BankTransaction[]>;
@@ -532,7 +538,7 @@ interface ClientCreateParams {
532
538
  declare class ClientsResource {
533
539
  private fetch;
534
540
  private companyId;
535
- constructor(fetch: $Fetch, companyId: number);
541
+ constructor(fetch: FetchFn, companyId: number);
536
542
  list(params?: ClientsListParams): Promise<Client[]>;
537
543
  get(clientId: number): Promise<Client>;
538
544
  create(params: ClientCreateParams): Promise<Client>;
@@ -542,7 +548,7 @@ declare class ClientsResource {
542
548
  declare class CompanyResource {
543
549
  private fetch;
544
550
  private companyId;
545
- constructor(fetch: $Fetch, companyId: number);
551
+ constructor(fetch: FetchFn, companyId: number);
546
552
  get(): Promise<Company>;
547
553
  users(): Promise<unknown>;
548
554
  appConfig(): Promise<unknown>;
@@ -562,7 +568,7 @@ interface DocumentsListParams {
562
568
  declare class DocumentsResource {
563
569
  private fetch;
564
570
  private companyId;
565
- constructor(fetch: $Fetch, companyId: number);
571
+ constructor(fetch: FetchFn, companyId: number);
566
572
  list(params?: DocumentsListParams): Promise<Document[]>;
567
573
  categories(): Promise<DocumentCategory[]>;
568
574
  preview(documentId: number): Promise<unknown>;
@@ -574,7 +580,7 @@ declare class DocumentsResource {
574
580
  declare class ExpenseReportsResource {
575
581
  private fetch;
576
582
  private companyId;
577
- constructor(fetch: $Fetch, companyId: number);
583
+ constructor(fetch: FetchFn, companyId: number);
578
584
  list(sorts?: string): Promise<ExpenseReport[]>;
579
585
  get(expenseReportId: number): Promise<ExpenseReport>;
580
586
  create(params: ExpenseReportCreateParams): Promise<ExpenseReport>;
@@ -589,7 +595,7 @@ interface InvoicesListParams {
589
595
  declare class InvoicesResource {
590
596
  private fetch;
591
597
  private companyId;
592
- constructor(fetch: $Fetch, companyId: number);
598
+ constructor(fetch: FetchFn, companyId: number);
593
599
  list(params?: InvoicesListParams): Promise<Invoice[]>;
594
600
  listAll(params?: {
595
601
  sorts?: string;
@@ -611,7 +617,7 @@ declare class InvoicesResource {
611
617
  declare class LabelsResource {
612
618
  private fetch;
613
619
  private companyId;
614
- constructor(fetch: $Fetch, companyId: number);
620
+ constructor(fetch: FetchFn, companyId: number);
615
621
  list(): Promise<Label[]>;
616
622
  standard(): Promise<Label[]>;
617
623
  tags(): Promise<Tag[]>;
@@ -620,7 +626,7 @@ declare class LabelsResource {
620
626
  declare class QuotationsResource {
621
627
  private fetch;
622
628
  private companyId;
623
- constructor(fetch: $Fetch, companyId: number);
629
+ constructor(fetch: FetchFn, companyId: number);
624
630
  list(expand?: string): Promise<Quotation[]>;
625
631
  get(quotationId: number): Promise<Quotation>;
626
632
  create(params: QuotationCreateParams): Promise<Quotation>;
@@ -630,14 +636,14 @@ declare class QuotationsResource {
630
636
 
631
637
  declare class UsersResource {
632
638
  private fetch;
633
- constructor(fetch: $Fetch);
639
+ constructor(fetch: FetchFn);
634
640
  me(): Promise<User>;
635
641
  legalInformations(): Promise<unknown>;
636
642
  settings(companyId: number): Promise<unknown>;
637
643
  }
638
644
 
639
645
  declare class TiimeClient {
640
- readonly fetch: $Fetch;
646
+ readonly fetch: FetchFn;
641
647
  readonly tokenManager: TokenManager;
642
648
  readonly companyId: number;
643
649
  constructor(options?: TiimeClientOptions & {
package/dist/index.js CHANGED
@@ -1,820 +1,2 @@
1
- // src/auth.ts
2
- import { execSync } from "child_process";
3
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
4
- import { homedir } from "os";
5
- import { join } from "path";
6
- import { ofetch } from "ofetch";
7
- var AUTH0_DOMAIN = "auth0.tiime.fr";
8
- var AUTH0_CLIENT_ID = "iEbsbe3o66gcTBfGRa012kj1Rb6vjAND";
9
- var AUTH0_AUDIENCE = "https://chronos/";
10
- var CONFIG_DIR = join(homedir(), ".config", "tiime");
11
- var AUTH_FILE = join(CONFIG_DIR, "auth.json");
12
- var CONFIG_FILE = join(CONFIG_DIR, "config.json");
13
- var KEYCHAIN_ACCOUNT = "tiime-cli";
14
- var KEYCHAIN_SERVICE = "tiime-credentials";
15
- var saveCredentialsToKeychain = (email, password) => {
16
- try {
17
- const payload = JSON.stringify({ email, password });
18
- execSync(
19
- `security add-generic-password -a "${KEYCHAIN_ACCOUNT}" -s "${KEYCHAIN_SERVICE}" -w '${payload.replace(/'/g, "'\\''")}' -U`,
20
- { stdio: "ignore" }
21
- );
22
- return true;
23
- } catch {
24
- return false;
25
- }
26
- };
27
- var loadCredentialsFromKeychain = () => {
28
- try {
29
- const raw = execSync(
30
- `security find-generic-password -a "${KEYCHAIN_ACCOUNT}" -s "${KEYCHAIN_SERVICE}" -w`,
31
- { encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"] }
32
- ).trim();
33
- const data = JSON.parse(raw);
34
- if (typeof data === "object" && data !== null && "email" in data && "password" in data && typeof data.email === "string" && typeof data.password === "string") {
35
- return data;
36
- }
37
- return null;
38
- } catch {
39
- return null;
40
- }
41
- };
42
- var saveCredentialsToFile = (email, password) => {
43
- if (!existsSync(CONFIG_DIR)) {
44
- mkdirSync(CONFIG_DIR, { recursive: true });
45
- }
46
- const filePath = join(CONFIG_DIR, "credentials.json");
47
- writeFileSync(filePath, JSON.stringify({ email, password }, null, 2), {
48
- mode: 384
49
- });
50
- };
51
- var loadCredentialsFromFile = () => {
52
- try {
53
- const filePath = join(CONFIG_DIR, "credentials.json");
54
- if (existsSync(filePath)) {
55
- const data = JSON.parse(readFileSync(filePath, "utf-8"));
56
- if (typeof data === "object" && data !== null && "email" in data && "password" in data && typeof data.email === "string" && typeof data.password === "string") {
57
- return data;
58
- }
59
- }
60
- } catch {
61
- }
62
- return null;
63
- };
64
- var saveCredentials = (email, password) => {
65
- if (!saveCredentialsToKeychain(email, password)) {
66
- saveCredentialsToFile(email, password);
67
- }
68
- };
69
- var loadCredentials = () => {
70
- return loadCredentialsFromKeychain() ?? loadCredentialsFromFile();
71
- };
72
- var resolveCompanyId = (explicit) => {
73
- if (explicit) return explicit;
74
- const envId = process.env.TIIME_COMPANY_ID;
75
- if (envId) {
76
- const parsed = Number.parseInt(envId, 10);
77
- if (!Number.isNaN(parsed)) return parsed;
78
- }
79
- try {
80
- if (existsSync(CONFIG_FILE)) {
81
- const config = JSON.parse(readFileSync(CONFIG_FILE, "utf-8"));
82
- if (config.companyId) return config.companyId;
83
- }
84
- } catch {
85
- }
86
- throw new Error(
87
- "No company ID configured. Set TIIME_COMPANY_ID env var, pass companyId option, or run `tiime company use --id <ID>`."
88
- );
89
- };
90
- var TokenManager = class {
91
- tokens = null;
92
- credentials = null;
93
- persist;
94
- /**
95
- * @param options.tokens - Use these tokens directly (no disk I/O)
96
- * @param options.email - Login with these credentials
97
- * @param options.password - Login with these credentials
98
- * @param options.persist - Save tokens/credentials to disk (default: true when no explicit auth)
99
- */
100
- constructor(options = {}) {
101
- const hasExplicitAuth = options.tokens || options.email && options.password;
102
- this.persist = options.persist ?? !hasExplicitAuth;
103
- if (options.tokens) {
104
- this.tokens = options.tokens;
105
- return;
106
- }
107
- if (options.email && options.password) {
108
- this.credentials = { email: options.email, password: options.password };
109
- return;
110
- }
111
- const envToken = process.env.TIIME_ACCESS_TOKEN;
112
- if (envToken) {
113
- this.tokens = {
114
- access_token: envToken,
115
- // No expiry info from env — assume valid, never auto-refresh
116
- expires_at: Number.MAX_SAFE_INTEGER
117
- };
118
- return;
119
- }
120
- const envEmail = process.env.TIIME_EMAIL;
121
- const envPassword = process.env.TIIME_PASSWORD;
122
- if (envEmail && envPassword) {
123
- this.credentials = { email: envEmail, password: envPassword };
124
- return;
125
- }
126
- this.loadFromDisk();
127
- }
128
- async login(email, password) {
129
- const response = await ofetch(`https://${AUTH0_DOMAIN}/oauth/token`, {
130
- method: "POST",
131
- body: {
132
- grant_type: "password",
133
- client_id: AUTH0_CLIENT_ID,
134
- audience: AUTH0_AUDIENCE,
135
- scope: "openid email",
136
- username: email,
137
- password
138
- }
139
- });
140
- this.tokens = {
141
- access_token: response.access_token,
142
- expires_at: Date.now() + response.expires_in * 1e3
143
- };
144
- if (this.persist) {
145
- this.saveToDisk();
146
- saveCredentials(email, password);
147
- }
148
- return this.tokens;
149
- }
150
- async getValidToken() {
151
- if (!this.tokens || this.isExpired()) {
152
- const creds = this.credentials ?? loadCredentials();
153
- if (creds) {
154
- const tokens = await this.login(creds.email, creds.password);
155
- return tokens.access_token;
156
- }
157
- throw new Error(
158
- 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`."
159
- );
160
- }
161
- return this.tokens.access_token;
162
- }
163
- isAuthenticated() {
164
- return this.tokens !== null && !this.isExpired();
165
- }
166
- logout() {
167
- this.tokens = null;
168
- if (existsSync(AUTH_FILE)) {
169
- writeFileSync(AUTH_FILE, "{}");
170
- }
171
- }
172
- getTokenInfo() {
173
- if (!this.tokens) {
174
- return { email: null, expiresAt: null };
175
- }
176
- try {
177
- const payload = JSON.parse(
178
- Buffer.from(
179
- this.tokens.access_token.split(".")[1],
180
- "base64"
181
- ).toString()
182
- );
183
- return {
184
- email: payload["tiime/userEmail"] || null,
185
- expiresAt: new Date(this.tokens.expires_at)
186
- };
187
- } catch {
188
- return { email: null, expiresAt: new Date(this.tokens.expires_at) };
189
- }
190
- }
191
- isExpired() {
192
- if (!this.tokens) return true;
193
- return Date.now() >= this.tokens.expires_at - 6e4;
194
- }
195
- loadFromDisk() {
196
- try {
197
- if (existsSync(AUTH_FILE)) {
198
- const data = JSON.parse(readFileSync(AUTH_FILE, "utf-8"));
199
- if (data.access_token && data.expires_at) {
200
- this.tokens = data;
201
- }
202
- }
203
- } catch {
204
- }
205
- }
206
- saveToDisk() {
207
- if (!existsSync(CONFIG_DIR)) {
208
- mkdirSync(CONFIG_DIR, { recursive: true });
209
- }
210
- writeFileSync(AUTH_FILE, JSON.stringify(this.tokens, null, 2));
211
- }
212
- };
213
-
214
- // src/client.ts
215
- import { ofetch as ofetch2 } from "ofetch";
216
-
217
- // src/errors.ts
218
- var TiimeError = class extends Error {
219
- constructor(message, status, endpoint, details) {
220
- super(message);
221
- this.status = status;
222
- this.endpoint = endpoint;
223
- this.details = details;
224
- this.name = "TiimeError";
225
- }
226
- toJSON() {
227
- return {
228
- error: this.name,
229
- message: this.message,
230
- status: this.status,
231
- endpoint: this.endpoint,
232
- details: this.details
233
- };
234
- }
235
- };
236
-
237
- // src/resources/bank-accounts.ts
238
- var BankAccountsResource = class {
239
- constructor(fetch, companyId) {
240
- this.fetch = fetch;
241
- this.companyId = companyId;
242
- }
243
- list(enabled) {
244
- return this.fetch(
245
- `/companies/${this.companyId}/bank_accounts`,
246
- { query: enabled !== void 0 ? { enabled } : void 0 }
247
- );
248
- }
249
- get(bankAccountId) {
250
- return this.fetch(
251
- `/companies/${this.companyId}/bank_accounts/${bankAccountId}`
252
- );
253
- }
254
- async balance() {
255
- const accounts = await this.list(true);
256
- return accounts.map((a) => ({
257
- name: a.name,
258
- balance_amount: a.balance_amount,
259
- currency: a.balance_currency
260
- }));
261
- }
262
- };
263
-
264
- // src/resources/bank-transactions.ts
265
- var BankTransactionsResource = class {
266
- constructor(fetch, companyId) {
267
- this.fetch = fetch;
268
- this.companyId = companyId;
269
- }
270
- list(params) {
271
- const start = ((params?.page ?? 1) - 1) * (params?.pageSize ?? 100);
272
- const end = start + (params?.pageSize ?? 100);
273
- const { page: _, pageSize: __, from, to, search, ...rest } = params ?? {};
274
- const query = { ...rest };
275
- if (from) query.transaction_date_start = from;
276
- if (to) query.transaction_date_end = to;
277
- if (search) query.wording = search;
278
- return this.fetch(
279
- `/companies/${this.companyId}/bank_transactions`,
280
- {
281
- query: { hide_refused: false, ...query },
282
- headers: {
283
- Accept: "application/vnd.tiime.bank_transactions.v2+json",
284
- Range: `items=${start}-${end}`
285
- }
286
- }
287
- );
288
- }
289
- async listAll(params) {
290
- const pageSize = params?.pageSize ?? 200;
291
- const all = [];
292
- let page = 1;
293
- let hasMore = true;
294
- while (hasMore) {
295
- const response = await this.list({ ...params, page, pageSize });
296
- all.push(...response.transactions);
297
- hasMore = response.transactions.length === pageSize;
298
- page++;
299
- }
300
- return all;
301
- }
302
- unimputed() {
303
- return this.fetch(
304
- `/companies/${this.companyId}/bank_transactions/unimputed`
305
- );
306
- }
307
- get(transactionId) {
308
- return this.fetch(
309
- `/companies/${this.companyId}/bank_transactions/${transactionId}`
310
- );
311
- }
312
- labelSuggestions(transactionId) {
313
- return this.fetch(
314
- `/companies/${this.companyId}/bank_transactions/${transactionId}/label_suggestions`,
315
- {
316
- headers: {
317
- Accept: "application/vnd.tiime.bank_transactions.label_suggestions.v2+json"
318
- }
319
- }
320
- );
321
- }
322
- impute(transactionId, imputations) {
323
- return this.fetch(
324
- `/companies/${this.companyId}/bank_transactions/${transactionId}`,
325
- {
326
- method: "PATCH",
327
- body: { imputations }
328
- }
329
- );
330
- }
331
- matchDocuments(transactionId, documentIds) {
332
- return this.fetch(
333
- `/companies/${this.companyId}/bank_transactions/${transactionId}/document_matchings`,
334
- {
335
- method: "PUT",
336
- body: { documents: documentIds.map((id) => ({ id })) }
337
- }
338
- );
339
- }
340
- getMatchings(transactionId) {
341
- return this.fetch(
342
- `/companies/${this.companyId}/bank_transactions/${transactionId}/matchings`
343
- );
344
- }
345
- };
346
-
347
- // src/resources/clients.ts
348
- var ClientsResource = class {
349
- constructor(fetch, companyId) {
350
- this.fetch = fetch;
351
- this.companyId = companyId;
352
- }
353
- list(params) {
354
- return this.fetch(`/companies/${this.companyId}/clients`, {
355
- query: params,
356
- headers: {
357
- Accept: "application/vnd.tiime.timeline.v2+json",
358
- Range: "items=0-*"
359
- }
360
- });
361
- }
362
- get(clientId) {
363
- return this.fetch(
364
- `/companies/${this.companyId}/clients/${clientId}`
365
- );
366
- }
367
- create(params) {
368
- return this.fetch(`/companies/${this.companyId}/clients`, {
369
- method: "POST",
370
- body: params
371
- });
372
- }
373
- search(query) {
374
- return this.fetch(`/companies/${this.companyId}/clients`, {
375
- query: { search: query },
376
- headers: {
377
- Accept: "application/vnd.tiime.timeline.v2+json",
378
- Range: "items=0-*"
379
- }
380
- });
381
- }
382
- };
383
-
384
- // src/resources/company.ts
385
- var CompanyResource = class {
386
- constructor(fetch, companyId) {
387
- this.fetch = fetch;
388
- this.companyId = companyId;
389
- }
390
- get() {
391
- return this.fetch(`/companies/${this.companyId}`);
392
- }
393
- users() {
394
- return this.fetch(`/companies/${this.companyId}/users`);
395
- }
396
- appConfig() {
397
- return this.fetch(`/companies/${this.companyId}/app_config`);
398
- }
399
- accountingPeriod(rangeYear = 1) {
400
- return this.fetch(
401
- `/companies/${this.companyId}/accounting_period/current`,
402
- { query: { range_year: rangeYear } }
403
- );
404
- }
405
- tiles(keys) {
406
- return this.fetch(`/companies/${this.companyId}/tiles`, {
407
- query: { keys: keys.join(",") }
408
- });
409
- }
410
- dashboardBlocks(displayGroup = "monitoring") {
411
- return this.fetch(`/companies/${this.companyId}/dashboard_blocks`, {
412
- query: { sorts: "rank:asc", display_group: displayGroup }
413
- });
414
- }
415
- };
416
-
417
- // src/resources/documents.ts
418
- var DocumentsResource = class {
419
- constructor(fetch, companyId) {
420
- this.fetch = fetch;
421
- this.companyId = companyId;
422
- }
423
- list(params) {
424
- const start = ((params?.page ?? 1) - 1) * (params?.pageSize ?? 25);
425
- const end = start + (params?.pageSize ?? 25);
426
- const { page: _, pageSize: __, ...query } = params ?? {};
427
- return this.fetch(`/companies/${this.companyId}/documents`, {
428
- query: {
429
- sorts: "created_at:desc",
430
- expand: "file_family,preview_available",
431
- ...query
432
- },
433
- headers: {
434
- Accept: "application/vnd.tiime.documents.v2+json,application/vnd.tiime.docs.query+json,application/vnd.tiime.docs.imputation+json",
435
- Range: `items=${start}-${end}`
436
- }
437
- });
438
- }
439
- categories() {
440
- return this.fetch(
441
- `/companies/${this.companyId}/document_categories`,
442
- {
443
- headers: {
444
- Accept: "application/vnd.tiime.documents.v3+json"
445
- }
446
- }
447
- );
448
- }
449
- preview(documentId) {
450
- return this.fetch(
451
- `/companies/${this.companyId}/documents/${documentId}/preview`
452
- );
453
- }
454
- upload(file, filename, type) {
455
- const formData = new FormData();
456
- formData.append("file", new Blob([file]), filename);
457
- if (type) {
458
- formData.append("type", type);
459
- }
460
- return this.fetch(`/companies/${this.companyId}/documents`, {
461
- method: "POST",
462
- body: formData
463
- });
464
- }
465
- searchMatchable(query) {
466
- return this.fetch(
467
- `/companies/${this.companyId}/documents`,
468
- {
469
- query: { matchable: true, q: query },
470
- headers: {
471
- Accept: "application/vnd.tiime.documents.v3+json,application/vnd.tiime.docs.imputation+json",
472
- Range: "items=0-25"
473
- }
474
- }
475
- );
476
- }
477
- async download(documentId) {
478
- return this.fetch(
479
- `/companies/${this.companyId}/documents/${documentId}/download`,
480
- {
481
- headers: { Accept: "application/octet-stream" }
482
- }
483
- );
484
- }
485
- };
486
-
487
- // src/resources/expense-reports.ts
488
- var ExpenseReportsResource = class {
489
- constructor(fetch, companyId) {
490
- this.fetch = fetch;
491
- this.companyId = companyId;
492
- }
493
- list(sorts = "metadata.date:desc") {
494
- return this.fetch(
495
- `/companies/${this.companyId}/expense_reports`,
496
- {
497
- query: { expand: "total_amount", sorts },
498
- headers: { Range: "items=0-25" }
499
- }
500
- );
501
- }
502
- get(expenseReportId) {
503
- return this.fetch(
504
- `/companies/${this.companyId}/expense_reports/${expenseReportId}`
505
- );
506
- }
507
- create(params) {
508
- return this.fetch(
509
- `/companies/${this.companyId}/expense_reports`,
510
- {
511
- method: "POST",
512
- body: params
513
- }
514
- );
515
- }
516
- };
517
-
518
- // src/resources/invoices.ts
519
- var DEFAULT_INVOICE_TEMPLATE = {
520
- template: "advanced",
521
- status: "draft",
522
- due_date_mode: "thirty_days",
523
- title_enabled: true,
524
- free_field_enabled: false,
525
- free_field: "",
526
- discount_enabled: false,
527
- bank_detail_enabled: true,
528
- payment_condition_enabled: true,
529
- 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.",
530
- text_lines: []
531
- };
532
- var InvoicesResource = class {
533
- constructor(fetch, companyId) {
534
- this.fetch = fetch;
535
- this.companyId = companyId;
536
- }
537
- list(params) {
538
- const start = ((params?.page ?? 1) - 1) * (params?.pageSize ?? 25);
539
- const end = start + (params?.pageSize ?? 25);
540
- const query = {
541
- sorts: params?.sorts ?? "invoice_number:desc"
542
- };
543
- if (params?.status) query.status = params.status;
544
- return this.fetch(`/companies/${this.companyId}/invoices`, {
545
- query,
546
- headers: { Range: `items=${start}-${end}` }
547
- });
548
- }
549
- async listAll(params) {
550
- const pageSize = params?.pageSize ?? 100;
551
- const all = [];
552
- let page = 1;
553
- let hasMore = true;
554
- while (hasMore) {
555
- const batch = await this.list({
556
- sorts: params?.sorts,
557
- status: params?.status,
558
- page,
559
- pageSize
560
- });
561
- all.push(...batch);
562
- hasMore = batch.length === pageSize;
563
- page++;
564
- }
565
- return all;
566
- }
567
- get(invoiceId) {
568
- return this.fetch(
569
- `/companies/${this.companyId}/invoices/${invoiceId}`
570
- );
571
- }
572
- create(params) {
573
- const body = {
574
- ...DEFAULT_INVOICE_TEMPLATE,
575
- ...params,
576
- lines: params.lines?.map((line) => ({ ...line }))
577
- };
578
- for (const line of body.lines ?? []) {
579
- line.line_amount = line.quantity * line.unit_amount;
580
- line.sequence ??= 1;
581
- line.invoicing_category_type ??= "benefit";
582
- line.discount_description ??= "";
583
- line.discount_amount ??= null;
584
- line.discount_percentage ??= null;
585
- }
586
- return this.fetch(`/companies/${this.companyId}/invoices`, {
587
- method: "POST",
588
- body
589
- });
590
- }
591
- update(invoiceId, params) {
592
- return this.fetch(
593
- `/companies/${this.companyId}/invoices/${invoiceId}`,
594
- {
595
- method: "PUT",
596
- body: params
597
- }
598
- );
599
- }
600
- send(invoiceId, params) {
601
- return this.fetch(
602
- `/companies/${this.companyId}/invoices/${invoiceId}/send`,
603
- {
604
- method: "POST",
605
- body: params
606
- }
607
- );
608
- }
609
- async downloadPdf(invoiceId) {
610
- return this.fetch(
611
- `/companies/${this.companyId}/invoices/${invoiceId}/pdf`,
612
- {
613
- headers: { Accept: "application/pdf" }
614
- }
615
- );
616
- }
617
- delete(invoiceId) {
618
- return this.fetch(
619
- `/companies/${this.companyId}/invoices/${invoiceId}`,
620
- { method: "DELETE" }
621
- );
622
- }
623
- async duplicate(invoiceId, overrides) {
624
- const source = await this.get(invoiceId);
625
- const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
626
- const lines = source.lines.map((l) => ({
627
- description: l.description,
628
- quantity: overrides?.quantity ?? l.quantity,
629
- unit_amount: l.unit_amount,
630
- vat_type: l.vat_type,
631
- invoicing_unit: l.invoicing_unit,
632
- invoicing_category_type: l.invoicing_category_type,
633
- article: l.article
634
- }));
635
- return this.create({
636
- client: source.client_id ? { id: source.client_id } : null,
637
- emission_date: overrides?.emission_date ?? today,
638
- title: source.title,
639
- title_enabled: !!source.title,
640
- lines,
641
- status: "draft"
642
- });
643
- }
644
- };
645
-
646
- // src/resources/labels.ts
647
- var LabelsResource = class {
648
- constructor(fetch, companyId) {
649
- this.fetch = fetch;
650
- this.companyId = companyId;
651
- }
652
- list() {
653
- return this.fetch(`/companies/${this.companyId}/labels`, {
654
- headers: {
655
- Accept: "application/vnd.tiime.labels.v2+json"
656
- }
657
- });
658
- }
659
- standard() {
660
- return this.fetch(`/companies/${this.companyId}/standard_labels`);
661
- }
662
- tags() {
663
- return this.fetch(`/companies/${this.companyId}/tags`, {
664
- query: { expand: "tag_detail" }
665
- });
666
- }
667
- };
668
-
669
- // src/resources/quotations.ts
670
- var QuotationsResource = class {
671
- constructor(fetch, companyId) {
672
- this.fetch = fetch;
673
- this.companyId = companyId;
674
- }
675
- list(expand = "invoices") {
676
- return this.fetch(`/companies/${this.companyId}/quotations`, {
677
- query: { expand },
678
- headers: { Range: "items=0-25" }
679
- });
680
- }
681
- get(quotationId) {
682
- return this.fetch(
683
- `/companies/${this.companyId}/quotations/${quotationId}`
684
- );
685
- }
686
- create(params) {
687
- const body = {
688
- ...params,
689
- lines: params.lines?.map((line) => ({ ...line }))
690
- };
691
- for (const line of body.lines ?? []) {
692
- line.line_amount = line.quantity * line.unit_amount;
693
- line.sequence ??= 1;
694
- line.invoicing_category_type ??= "benefit";
695
- line.discount_description ??= "";
696
- line.discount_amount ??= null;
697
- line.discount_percentage ??= null;
698
- }
699
- return this.fetch(`/companies/${this.companyId}/quotations`, {
700
- method: "POST",
701
- body
702
- });
703
- }
704
- async downloadPdf(quotationId) {
705
- return this.fetch(
706
- `/companies/${this.companyId}/quotations/${quotationId}/pdf`,
707
- {
708
- headers: { Accept: "application/pdf" }
709
- }
710
- );
711
- }
712
- send(quotationId, params) {
713
- return this.fetch(
714
- `/companies/${this.companyId}/quotations/${quotationId}/send`,
715
- {
716
- method: "POST",
717
- body: params
718
- }
719
- );
720
- }
721
- };
722
-
723
- // src/resources/users.ts
724
- var UsersResource = class {
725
- constructor(fetch) {
726
- this.fetch = fetch;
727
- }
728
- me() {
729
- return this.fetch("/users/me");
730
- }
731
- legalInformations() {
732
- return this.fetch("/users/me/legal_informations");
733
- }
734
- settings(companyId) {
735
- return this.fetch(`/users/me/companies/${companyId}/settings`);
736
- }
737
- };
738
-
739
- // src/client.ts
740
- var BASE_URL = "https://chronos-api.tiime-apps.com/v1";
741
- var TiimeClient = class {
742
- fetch;
743
- tokenManager;
744
- companyId;
745
- constructor(options = {}) {
746
- this.companyId = resolveCompanyId(options.companyId);
747
- this.tokenManager = options.tokenManager ?? new TokenManager({
748
- tokens: options.tokens,
749
- email: options.email,
750
- password: options.password
751
- });
752
- this.fetch = ofetch2.create({
753
- baseURL: BASE_URL,
754
- retry: 2,
755
- retryDelay: 500,
756
- retryStatusCodes: [408, 429, 500, 502, 503, 504],
757
- headers: {
758
- "tiime-app": "tiime",
759
- "tiime-app-version": "4.30.3",
760
- "tiime-app-platform": "cli"
761
- },
762
- onRequest: async ({ options: options2 }) => {
763
- const token = await this.tokenManager.getValidToken();
764
- options2.headers.set("Authorization", `Bearer ${token}`);
765
- },
766
- onResponseError: ({ request, response }) => {
767
- throw new TiimeError(
768
- response.statusText || `HTTP ${response.status}`,
769
- response.status,
770
- String(request),
771
- response._data
772
- );
773
- }
774
- });
775
- }
776
- listCompanies() {
777
- return this.fetch("/companies", {
778
- headers: {
779
- Accept: "application/vnd.tiime.companies.v2+json",
780
- Range: "items=0-101"
781
- }
782
- });
783
- }
784
- get users() {
785
- return new UsersResource(this.fetch);
786
- }
787
- get company() {
788
- return new CompanyResource(this.fetch, this.companyId);
789
- }
790
- get clients() {
791
- return new ClientsResource(this.fetch, this.companyId);
792
- }
793
- get invoices() {
794
- return new InvoicesResource(this.fetch, this.companyId);
795
- }
796
- get quotations() {
797
- return new QuotationsResource(this.fetch, this.companyId);
798
- }
799
- get bankAccounts() {
800
- return new BankAccountsResource(this.fetch, this.companyId);
801
- }
802
- get bankTransactions() {
803
- return new BankTransactionsResource(this.fetch, this.companyId);
804
- }
805
- get documents() {
806
- return new DocumentsResource(this.fetch, this.companyId);
807
- }
808
- get expenseReports() {
809
- return new ExpenseReportsResource(this.fetch, this.companyId);
810
- }
811
- get labels() {
812
- return new LabelsResource(this.fetch, this.companyId);
813
- }
814
- };
815
- export {
816
- TiimeClient,
817
- TiimeError,
818
- TokenManager,
819
- resolveCompanyId
820
- };
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{E as TiimeClient,b as TiimeError,y as TokenManager,A as resolveCompanyId};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tiime-sdk",
3
- "version": "2.1.2",
3
+ "version": "2.2.0",
4
4
  "description": "TypeScript SDK for Tiime accounting API",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -44,9 +44,6 @@
44
44
  "engines": {
45
45
  "node": ">=20"
46
46
  },
47
- "dependencies": {
48
- "ofetch": "^1.5.1"
49
- },
50
47
  "devDependencies": {
51
48
  "@biomejs/biome": "^2.4.6",
52
49
  "@types/node": "^25.3.5",