@goodsamsoftware/freshbooks-mcp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +357 -0
- package/dist/auth/config.d.ts +57 -0
- package/dist/auth/config.d.ts.map +1 -0
- package/dist/auth/config.js +118 -0
- package/dist/auth/config.js.map +1 -0
- package/dist/auth/index.d.ts +47 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +46 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/oauth.d.ts +93 -0
- package/dist/auth/oauth.d.ts.map +1 -0
- package/dist/auth/oauth.js +279 -0
- package/dist/auth/oauth.js.map +1 -0
- package/dist/auth/token-store.d.ts +80 -0
- package/dist/auth/token-store.d.ts.map +1 -0
- package/dist/auth/token-store.js +204 -0
- package/dist/auth/token-store.js.map +1 -0
- package/dist/auth/types.d.ts +76 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +20 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/client/freshbooks-client.d.ts +99 -0
- package/dist/client/freshbooks-client.d.ts.map +1 -0
- package/dist/client/freshbooks-client.js +283 -0
- package/dist/client/freshbooks-client.js.map +1 -0
- package/dist/client/index.d.ts +5 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +5 -0
- package/dist/client/index.js.map +1 -0
- package/dist/config/index.d.ts +17 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +81 -0
- package/dist/config/index.js.map +1 -0
- package/dist/errors/documentation.d.ts +57 -0
- package/dist/errors/documentation.d.ts.map +1 -0
- package/dist/errors/documentation.js +390 -0
- package/dist/errors/documentation.js.map +1 -0
- package/dist/errors/error-codes.d.ts +45 -0
- package/dist/errors/error-codes.d.ts.map +1 -0
- package/dist/errors/error-codes.js +94 -0
- package/dist/errors/error-codes.js.map +1 -0
- package/dist/errors/error-handler.d.ts +127 -0
- package/dist/errors/error-handler.d.ts.map +1 -0
- package/dist/errors/error-handler.js +283 -0
- package/dist/errors/error-handler.js.map +1 -0
- package/dist/errors/error-mapper.d.ts +68 -0
- package/dist/errors/error-mapper.d.ts.map +1 -0
- package/dist/errors/error-mapper.js +449 -0
- package/dist/errors/error-mapper.js.map +1 -0
- package/dist/errors/index.d.ts +37 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +41 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/errors/response-formatter.d.ts +109 -0
- package/dist/errors/response-formatter.d.ts.map +1 -0
- package/dist/errors/response-formatter.js +232 -0
- package/dist/errors/response-formatter.js.map +1 -0
- package/dist/errors/types.d.ts +194 -0
- package/dist/errors/types.d.ts.map +1 -0
- package/dist/errors/types.js +134 -0
- package/dist/errors/types.js.map +1 -0
- package/dist/server.d.ts +10 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +263 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/base-tool.d.ts +146 -0
- package/dist/tools/base-tool.d.ts.map +1 -0
- package/dist/tools/base-tool.js +161 -0
- package/dist/tools/base-tool.js.map +1 -0
- package/dist/tools/bill/bill-archive.d.ts +40 -0
- package/dist/tools/bill/bill-archive.d.ts.map +1 -0
- package/dist/tools/bill/bill-archive.js +68 -0
- package/dist/tools/bill/bill-archive.js.map +1 -0
- package/dist/tools/bill/bill-create.d.ts +178 -0
- package/dist/tools/bill/bill-create.d.ts.map +1 -0
- package/dist/tools/bill/bill-create.js +70 -0
- package/dist/tools/bill/bill-create.js.map +1 -0
- package/dist/tools/bill/bill-delete.d.ts +40 -0
- package/dist/tools/bill/bill-delete.d.ts.map +1 -0
- package/dist/tools/bill/bill-delete.js +67 -0
- package/dist/tools/bill/bill-delete.js.map +1 -0
- package/dist/tools/bill/bill-list.d.ts +249 -0
- package/dist/tools/bill/bill-list.d.ts.map +1 -0
- package/dist/tools/bill/bill-list.js +114 -0
- package/dist/tools/bill/bill-list.js.map +1 -0
- package/dist/tools/bill/bill-single.d.ts +142 -0
- package/dist/tools/bill/bill-single.d.ts.map +1 -0
- package/dist/tools/bill/bill-single.js +62 -0
- package/dist/tools/bill/bill-single.js.map +1 -0
- package/dist/tools/bill/index.d.ts +11 -0
- package/dist/tools/bill/index.d.ts.map +1 -0
- package/dist/tools/bill/index.js +13 -0
- package/dist/tools/bill/index.js.map +1 -0
- package/dist/tools/bill/schemas.d.ts +609 -0
- package/dist/tools/bill/schemas.d.ts.map +1 -0
- package/dist/tools/bill/schemas.js +124 -0
- package/dist/tools/bill/schemas.js.map +1 -0
- package/dist/tools/bill-payment/billpayment-create.d.ts +103 -0
- package/dist/tools/bill-payment/billpayment-create.d.ts.map +1 -0
- package/dist/tools/bill-payment/billpayment-create.js +67 -0
- package/dist/tools/bill-payment/billpayment-create.js.map +1 -0
- package/dist/tools/bill-payment/billpayment-delete.d.ts +40 -0
- package/dist/tools/bill-payment/billpayment-delete.d.ts.map +1 -0
- package/dist/tools/bill-payment/billpayment-delete.js +67 -0
- package/dist/tools/bill-payment/billpayment-delete.js.map +1 -0
- package/dist/tools/bill-payment/billpayment-list.d.ts +148 -0
- package/dist/tools/bill-payment/billpayment-list.d.ts.map +1 -0
- package/dist/tools/bill-payment/billpayment-list.js +111 -0
- package/dist/tools/bill-payment/billpayment-list.js.map +1 -0
- package/dist/tools/bill-payment/billpayment-single.d.ts +76 -0
- package/dist/tools/bill-payment/billpayment-single.d.ts.map +1 -0
- package/dist/tools/bill-payment/billpayment-single.js +62 -0
- package/dist/tools/bill-payment/billpayment-single.js.map +1 -0
- package/dist/tools/bill-payment/billpayment-update.d.ts +103 -0
- package/dist/tools/bill-payment/billpayment-update.d.ts.map +1 -0
- package/dist/tools/bill-payment/billpayment-update.js +67 -0
- package/dist/tools/bill-payment/billpayment-update.js.map +1 -0
- package/dist/tools/bill-payment/index.d.ts +11 -0
- package/dist/tools/bill-payment/index.d.ts.map +1 -0
- package/dist/tools/bill-payment/index.js +13 -0
- package/dist/tools/bill-payment/index.js.map +1 -0
- package/dist/tools/bill-payment/schemas.d.ts +381 -0
- package/dist/tools/bill-payment/schemas.d.ts.map +1 -0
- package/dist/tools/bill-payment/schemas.js +113 -0
- package/dist/tools/bill-payment/schemas.js.map +1 -0
- package/dist/tools/bill-vendor/billvendor-create.d.ts +139 -0
- package/dist/tools/bill-vendor/billvendor-create.d.ts.map +1 -0
- package/dist/tools/bill-vendor/billvendor-create.js +72 -0
- package/dist/tools/bill-vendor/billvendor-create.js.map +1 -0
- package/dist/tools/bill-vendor/billvendor-delete.d.ts +40 -0
- package/dist/tools/bill-vendor/billvendor-delete.d.ts.map +1 -0
- package/dist/tools/bill-vendor/billvendor-delete.js +67 -0
- package/dist/tools/bill-vendor/billvendor-delete.js.map +1 -0
- package/dist/tools/bill-vendor/billvendor-list.d.ts +179 -0
- package/dist/tools/bill-vendor/billvendor-list.d.ts.map +1 -0
- package/dist/tools/bill-vendor/billvendor-list.js +109 -0
- package/dist/tools/bill-vendor/billvendor-list.js.map +1 -0
- package/dist/tools/bill-vendor/billvendor-single.d.ts +94 -0
- package/dist/tools/bill-vendor/billvendor-single.d.ts.map +1 -0
- package/dist/tools/bill-vendor/billvendor-single.js +62 -0
- package/dist/tools/bill-vendor/billvendor-single.js.map +1 -0
- package/dist/tools/bill-vendor/billvendor-update.d.ts +142 -0
- package/dist/tools/bill-vendor/billvendor-update.d.ts.map +1 -0
- package/dist/tools/bill-vendor/billvendor-update.js +72 -0
- package/dist/tools/bill-vendor/billvendor-update.js.map +1 -0
- package/dist/tools/bill-vendor/index.d.ts +11 -0
- package/dist/tools/bill-vendor/index.d.ts.map +1 -0
- package/dist/tools/bill-vendor/index.js +13 -0
- package/dist/tools/bill-vendor/index.js.map +1 -0
- package/dist/tools/bill-vendor/schemas.d.ts +483 -0
- package/dist/tools/bill-vendor/schemas.d.ts.map +1 -0
- package/dist/tools/bill-vendor/schemas.js +136 -0
- package/dist/tools/bill-vendor/schemas.js.map +1 -0
- package/dist/tools/callback/callback-create.d.ts +52 -0
- package/dist/tools/callback/callback-create.d.ts.map +1 -0
- package/dist/tools/callback/callback-create.js +73 -0
- package/dist/tools/callback/callback-create.js.map +1 -0
- package/dist/tools/callback/callback-delete.d.ts +37 -0
- package/dist/tools/callback/callback-delete.d.ts.map +1 -0
- package/dist/tools/callback/callback-delete.js +57 -0
- package/dist/tools/callback/callback-delete.js.map +1 -0
- package/dist/tools/callback/callback-list.d.ts +100 -0
- package/dist/tools/callback/callback-list.d.ts.map +1 -0
- package/dist/tools/callback/callback-list.js +84 -0
- package/dist/tools/callback/callback-list.js.map +1 -0
- package/dist/tools/callback/callback-resend-verification.d.ts +49 -0
- package/dist/tools/callback/callback-resend-verification.d.ts.map +1 -0
- package/dist/tools/callback/callback-resend-verification.js +63 -0
- package/dist/tools/callback/callback-resend-verification.js.map +1 -0
- package/dist/tools/callback/callback-single.d.ts +49 -0
- package/dist/tools/callback/callback-single.d.ts.map +1 -0
- package/dist/tools/callback/callback-single.js +53 -0
- package/dist/tools/callback/callback-single.js.map +1 -0
- package/dist/tools/callback/callback-update.d.ts +55 -0
- package/dist/tools/callback/callback-update.d.ts.map +1 -0
- package/dist/tools/callback/callback-update.js +62 -0
- package/dist/tools/callback/callback-update.js.map +1 -0
- package/dist/tools/callback/callback-verify.d.ts +43 -0
- package/dist/tools/callback/callback-verify.d.ts.map +1 -0
- package/dist/tools/callback/callback-verify.js +69 -0
- package/dist/tools/callback/callback-verify.js.map +1 -0
- package/dist/tools/callback/index.d.ts +13 -0
- package/dist/tools/callback/index.d.ts.map +1 -0
- package/dist/tools/callback/index.js +15 -0
- package/dist/tools/callback/index.js.map +1 -0
- package/dist/tools/callback/schemas.d.ts +284 -0
- package/dist/tools/callback/schemas.d.ts.map +1 -0
- package/dist/tools/callback/schemas.js +114 -0
- package/dist/tools/callback/schemas.js.map +1 -0
- package/dist/tools/client/client-create.d.ts +211 -0
- package/dist/tools/client/client-create.d.ts.map +1 -0
- package/dist/tools/client/client-create.js +147 -0
- package/dist/tools/client/client-create.js.map +1 -0
- package/dist/tools/client/client-delete.d.ts +40 -0
- package/dist/tools/client/client-delete.d.ts.map +1 -0
- package/dist/tools/client/client-delete.js +73 -0
- package/dist/tools/client/client-delete.js.map +1 -0
- package/dist/tools/client/client-list.d.ts +264 -0
- package/dist/tools/client/client-list.d.ts.map +1 -0
- package/dist/tools/client/client-list.js +131 -0
- package/dist/tools/client/client-list.js.map +1 -0
- package/dist/tools/client/client-single.d.ts +133 -0
- package/dist/tools/client/client-single.d.ts.map +1 -0
- package/dist/tools/client/client-single.js +67 -0
- package/dist/tools/client/client-single.js.map +1 -0
- package/dist/tools/client/client-update.d.ts +217 -0
- package/dist/tools/client/client-update.d.ts.map +1 -0
- package/dist/tools/client/client-update.js +146 -0
- package/dist/tools/client/client-update.js.map +1 -0
- package/dist/tools/client/index.d.ts +11 -0
- package/dist/tools/client/index.d.ts.map +1 -0
- package/dist/tools/client/index.js +13 -0
- package/dist/tools/client/index.js.map +1 -0
- package/dist/tools/client/schemas.d.ts +759 -0
- package/dist/tools/client/schemas.d.ts.map +1 -0
- package/dist/tools/client/schemas.js +241 -0
- package/dist/tools/client/schemas.js.map +1 -0
- package/dist/tools/credit-note/creditnote-create.d.ts +448 -0
- package/dist/tools/credit-note/creditnote-create.d.ts.map +1 -0
- package/dist/tools/credit-note/creditnote-create.js +88 -0
- package/dist/tools/credit-note/creditnote-create.js.map +1 -0
- package/dist/tools/credit-note/creditnote-delete.d.ts +37 -0
- package/dist/tools/credit-note/creditnote-delete.d.ts.map +1 -0
- package/dist/tools/credit-note/creditnote-delete.js +57 -0
- package/dist/tools/credit-note/creditnote-delete.js.map +1 -0
- package/dist/tools/credit-note/creditnote-list.d.ts +627 -0
- package/dist/tools/credit-note/creditnote-list.d.ts.map +1 -0
- package/dist/tools/credit-note/creditnote-list.js +106 -0
- package/dist/tools/credit-note/creditnote-list.js.map +1 -0
- package/dist/tools/credit-note/creditnote-single.d.ts +358 -0
- package/dist/tools/credit-note/creditnote-single.d.ts.map +1 -0
- package/dist/tools/credit-note/creditnote-single.js +60 -0
- package/dist/tools/credit-note/creditnote-single.js.map +1 -0
- package/dist/tools/credit-note/creditnote-update.d.ts +442 -0
- package/dist/tools/credit-note/creditnote-update.d.ts.map +1 -0
- package/dist/tools/credit-note/creditnote-update.js +82 -0
- package/dist/tools/credit-note/creditnote-update.js.map +1 -0
- package/dist/tools/credit-note/index.d.ts +11 -0
- package/dist/tools/credit-note/index.d.ts.map +1 -0
- package/dist/tools/credit-note/index.js +13 -0
- package/dist/tools/credit-note/index.js.map +1 -0
- package/dist/tools/credit-note/schemas.d.ts +1599 -0
- package/dist/tools/credit-note/schemas.d.ts.map +1 -0
- package/dist/tools/credit-note/schemas.js +196 -0
- package/dist/tools/credit-note/schemas.js.map +1 -0
- package/dist/tools/expense/expense-create.d.ts +196 -0
- package/dist/tools/expense/expense-create.d.ts.map +1 -0
- package/dist/tools/expense/expense-create.js +103 -0
- package/dist/tools/expense/expense-create.js.map +1 -0
- package/dist/tools/expense/expense-delete.d.ts +40 -0
- package/dist/tools/expense/expense-delete.d.ts.map +1 -0
- package/dist/tools/expense/expense-delete.js +73 -0
- package/dist/tools/expense/expense-delete.js.map +1 -0
- package/dist/tools/expense/expense-list.d.ts +264 -0
- package/dist/tools/expense/expense-list.d.ts.map +1 -0
- package/dist/tools/expense/expense-list.js +126 -0
- package/dist/tools/expense/expense-list.js.map +1 -0
- package/dist/tools/expense/expense-single.d.ts +145 -0
- package/dist/tools/expense/expense-single.d.ts.map +1 -0
- package/dist/tools/expense/expense-single.js +63 -0
- package/dist/tools/expense/expense-single.js.map +1 -0
- package/dist/tools/expense/expense-update.d.ts +199 -0
- package/dist/tools/expense/expense-update.d.ts.map +1 -0
- package/dist/tools/expense/expense-update.js +108 -0
- package/dist/tools/expense/expense-update.js.map +1 -0
- package/dist/tools/expense/index.d.ts +11 -0
- package/dist/tools/expense/index.d.ts.map +1 -0
- package/dist/tools/expense/index.js +13 -0
- package/dist/tools/expense/index.js.map +1 -0
- package/dist/tools/expense/schemas.d.ts +667 -0
- package/dist/tools/expense/schemas.d.ts.map +1 -0
- package/dist/tools/expense/schemas.js +142 -0
- package/dist/tools/expense/schemas.js.map +1 -0
- package/dist/tools/expense-category/expensecategory-list.d.ts +113 -0
- package/dist/tools/expense-category/expensecategory-list.d.ts.map +1 -0
- package/dist/tools/expense-category/expensecategory-list.js +113 -0
- package/dist/tools/expense-category/expensecategory-list.js.map +1 -0
- package/dist/tools/expense-category/expensecategory-single.d.ts +58 -0
- package/dist/tools/expense-category/expensecategory-single.d.ts.map +1 -0
- package/dist/tools/expense-category/expensecategory-single.js +66 -0
- package/dist/tools/expense-category/expensecategory-single.js.map +1 -0
- package/dist/tools/expense-category/index.d.ts +9 -0
- package/dist/tools/expense-category/index.d.ts.map +1 -0
- package/dist/tools/expense-category/index.js +11 -0
- package/dist/tools/expense-category/index.js.map +1 -0
- package/dist/tools/expense-category/schemas.d.ts +184 -0
- package/dist/tools/expense-category/schemas.d.ts.map +1 -0
- package/dist/tools/expense-category/schemas.js +58 -0
- package/dist/tools/expense-category/schemas.js.map +1 -0
- package/dist/tools/index.d.ts +53 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +98 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/invoice/index.d.ts +12 -0
- package/dist/tools/invoice/index.d.ts.map +1 -0
- package/dist/tools/invoice/index.js +14 -0
- package/dist/tools/invoice/index.js.map +1 -0
- package/dist/tools/invoice/invoice-create.d.ts +367 -0
- package/dist/tools/invoice/invoice-create.d.ts.map +1 -0
- package/dist/tools/invoice/invoice-create.js +115 -0
- package/dist/tools/invoice/invoice-create.js.map +1 -0
- package/dist/tools/invoice/invoice-delete.d.ts +40 -0
- package/dist/tools/invoice/invoice-delete.d.ts.map +1 -0
- package/dist/tools/invoice/invoice-delete.js +75 -0
- package/dist/tools/invoice/invoice-delete.js.map +1 -0
- package/dist/tools/invoice/invoice-list.d.ts +439 -0
- package/dist/tools/invoice/invoice-list.d.ts.map +1 -0
- package/dist/tools/invoice/invoice-list.js +126 -0
- package/dist/tools/invoice/invoice-list.js.map +1 -0
- package/dist/tools/invoice/invoice-share-link.d.ts +40 -0
- package/dist/tools/invoice/invoice-share-link.d.ts.map +1 -0
- package/dist/tools/invoice/invoice-share-link.js +89 -0
- package/dist/tools/invoice/invoice-share-link.js.map +1 -0
- package/dist/tools/invoice/invoice-single.d.ts +265 -0
- package/dist/tools/invoice/invoice-single.d.ts.map +1 -0
- package/dist/tools/invoice/invoice-single.js +66 -0
- package/dist/tools/invoice/invoice-single.js.map +1 -0
- package/dist/tools/invoice/invoice-update.d.ts +373 -0
- package/dist/tools/invoice/invoice-update.d.ts.map +1 -0
- package/dist/tools/invoice/invoice-update.js +122 -0
- package/dist/tools/invoice/invoice-update.js.map +1 -0
- package/dist/tools/invoice/schemas.d.ts +1414 -0
- package/dist/tools/invoice/schemas.d.ts.map +1 -0
- package/dist/tools/invoice/schemas.js +269 -0
- package/dist/tools/invoice/schemas.js.map +1 -0
- package/dist/tools/item/index.d.ts +10 -0
- package/dist/tools/item/index.d.ts.map +1 -0
- package/dist/tools/item/index.js +12 -0
- package/dist/tools/item/index.js.map +1 -0
- package/dist/tools/item/item-create.d.ts +136 -0
- package/dist/tools/item/item-create.d.ts.map +1 -0
- package/dist/tools/item/item-create.js +71 -0
- package/dist/tools/item/item-create.js.map +1 -0
- package/dist/tools/item/item-list.d.ts +178 -0
- package/dist/tools/item/item-list.d.ts.map +1 -0
- package/dist/tools/item/item-list.js +112 -0
- package/dist/tools/item/item-list.js.map +1 -0
- package/dist/tools/item/item-single.d.ts +94 -0
- package/dist/tools/item/item-single.d.ts.map +1 -0
- package/dist/tools/item/item-single.js +62 -0
- package/dist/tools/item/item-single.js.map +1 -0
- package/dist/tools/item/item-update.d.ts +139 -0
- package/dist/tools/item/item-update.d.ts.map +1 -0
- package/dist/tools/item/item-update.js +74 -0
- package/dist/tools/item/item-update.js.map +1 -0
- package/dist/tools/item/schemas.d.ts +454 -0
- package/dist/tools/item/schemas.d.ts.map +1 -0
- package/dist/tools/item/schemas.js +116 -0
- package/dist/tools/item/schemas.js.map +1 -0
- package/dist/tools/journal-entry/index.d.ts +7 -0
- package/dist/tools/journal-entry/index.d.ts.map +1 -0
- package/dist/tools/journal-entry/index.js +9 -0
- package/dist/tools/journal-entry/index.js.map +1 -0
- package/dist/tools/journal-entry/journalentry-create.d.ts +114 -0
- package/dist/tools/journal-entry/journalentry-create.d.ts.map +1 -0
- package/dist/tools/journal-entry/journalentry-create.js +98 -0
- package/dist/tools/journal-entry/journalentry-create.js.map +1 -0
- package/dist/tools/journal-entry/schemas.d.ts +182 -0
- package/dist/tools/journal-entry/schemas.d.ts.map +1 -0
- package/dist/tools/journal-entry/schemas.js +43 -0
- package/dist/tools/journal-entry/schemas.js.map +1 -0
- package/dist/tools/journal-entry-account/index.d.ts +7 -0
- package/dist/tools/journal-entry-account/index.d.ts.map +1 -0
- package/dist/tools/journal-entry-account/index.js +9 -0
- package/dist/tools/journal-entry-account/index.js.map +1 -0
- package/dist/tools/journal-entry-account/journalentryaccount-list.d.ts +190 -0
- package/dist/tools/journal-entry-account/journalentryaccount-list.d.ts.map +1 -0
- package/dist/tools/journal-entry-account/journalentryaccount-list.js +102 -0
- package/dist/tools/journal-entry-account/journalentryaccount-list.js.map +1 -0
- package/dist/tools/journal-entry-account/schemas.d.ts +344 -0
- package/dist/tools/journal-entry-account/schemas.d.ts.map +1 -0
- package/dist/tools/journal-entry-account/schemas.js +65 -0
- package/dist/tools/journal-entry-account/schemas.js.map +1 -0
- package/dist/tools/metadata.d.ts +49 -0
- package/dist/tools/metadata.d.ts.map +1 -0
- package/dist/tools/metadata.js +317 -0
- package/dist/tools/metadata.js.map +1 -0
- package/dist/tools/other-income/index.d.ts +11 -0
- package/dist/tools/other-income/index.d.ts.map +1 -0
- package/dist/tools/other-income/index.js +13 -0
- package/dist/tools/other-income/index.js.map +1 -0
- package/dist/tools/other-income/otherincome-create.d.ts +152 -0
- package/dist/tools/other-income/otherincome-create.d.ts.map +1 -0
- package/dist/tools/other-income/otherincome-create.js +89 -0
- package/dist/tools/other-income/otherincome-create.js.map +1 -0
- package/dist/tools/other-income/otherincome-delete.d.ts +37 -0
- package/dist/tools/other-income/otherincome-delete.d.ts.map +1 -0
- package/dist/tools/other-income/otherincome-delete.js +57 -0
- package/dist/tools/other-income/otherincome-delete.js.map +1 -0
- package/dist/tools/other-income/otherincome-list.d.ts +186 -0
- package/dist/tools/other-income/otherincome-list.d.ts.map +1 -0
- package/dist/tools/other-income/otherincome-list.js +107 -0
- package/dist/tools/other-income/otherincome-list.js.map +1 -0
- package/dist/tools/other-income/otherincome-single.d.ts +99 -0
- package/dist/tools/other-income/otherincome-single.d.ts.map +1 -0
- package/dist/tools/other-income/otherincome-single.js +53 -0
- package/dist/tools/other-income/otherincome-single.js.map +1 -0
- package/dist/tools/other-income/otherincome-update.d.ts +155 -0
- package/dist/tools/other-income/otherincome-update.d.ts.map +1 -0
- package/dist/tools/other-income/otherincome-update.js +84 -0
- package/dist/tools/other-income/otherincome-update.js.map +1 -0
- package/dist/tools/other-income/schemas.d.ts +510 -0
- package/dist/tools/other-income/schemas.d.ts.map +1 -0
- package/dist/tools/other-income/schemas.js +141 -0
- package/dist/tools/other-income/schemas.js.map +1 -0
- package/dist/tools/payment/index.d.ts +11 -0
- package/dist/tools/payment/index.d.ts.map +1 -0
- package/dist/tools/payment/index.js +13 -0
- package/dist/tools/payment/index.js.map +1 -0
- package/dist/tools/payment/payment-create.d.ts +127 -0
- package/dist/tools/payment/payment-create.d.ts.map +1 -0
- package/dist/tools/payment/payment-create.js +84 -0
- package/dist/tools/payment/payment-create.js.map +1 -0
- package/dist/tools/payment/payment-delete.d.ts +40 -0
- package/dist/tools/payment/payment-delete.d.ts.map +1 -0
- package/dist/tools/payment/payment-delete.js +67 -0
- package/dist/tools/payment/payment-delete.js.map +1 -0
- package/dist/tools/payment/payment-list.d.ts +186 -0
- package/dist/tools/payment/payment-list.d.ts.map +1 -0
- package/dist/tools/payment/payment-list.js +113 -0
- package/dist/tools/payment/payment-list.js.map +1 -0
- package/dist/tools/payment/payment-single.d.ts +97 -0
- package/dist/tools/payment/payment-single.d.ts.map +1 -0
- package/dist/tools/payment/payment-single.js +62 -0
- package/dist/tools/payment/payment-single.js.map +1 -0
- package/dist/tools/payment/payment-update.d.ts +124 -0
- package/dist/tools/payment/payment-update.d.ts.map +1 -0
- package/dist/tools/payment/payment-update.js +79 -0
- package/dist/tools/payment/payment-update.js.map +1 -0
- package/dist/tools/payment/schemas.d.ts +445 -0
- package/dist/tools/payment/schemas.d.ts.map +1 -0
- package/dist/tools/payment/schemas.js +126 -0
- package/dist/tools/payment/schemas.js.map +1 -0
- package/dist/tools/payment-options/index.d.ts +9 -0
- package/dist/tools/payment-options/index.d.ts.map +1 -0
- package/dist/tools/payment-options/index.js +11 -0
- package/dist/tools/payment-options/index.js.map +1 -0
- package/dist/tools/payment-options/paymentoptions-create.d.ts +91 -0
- package/dist/tools/payment-options/paymentoptions-create.d.ts.map +1 -0
- package/dist/tools/payment-options/paymentoptions-create.js +71 -0
- package/dist/tools/payment-options/paymentoptions-create.js.map +1 -0
- package/dist/tools/payment-options/paymentoptions-default.d.ts +43 -0
- package/dist/tools/payment-options/paymentoptions-default.d.ts.map +1 -0
- package/dist/tools/payment-options/paymentoptions-default.js +64 -0
- package/dist/tools/payment-options/paymentoptions-default.js.map +1 -0
- package/dist/tools/payment-options/paymentoptions-single.d.ts +76 -0
- package/dist/tools/payment-options/paymentoptions-single.d.ts.map +1 -0
- package/dist/tools/payment-options/paymentoptions-single.js +58 -0
- package/dist/tools/payment-options/paymentoptions-single.js.map +1 -0
- package/dist/tools/payment-options/schemas.d.ts +197 -0
- package/dist/tools/payment-options/schemas.d.ts.map +1 -0
- package/dist/tools/payment-options/schemas.js +69 -0
- package/dist/tools/payment-options/schemas.js.map +1 -0
- package/dist/tools/project/index.d.ts +11 -0
- package/dist/tools/project/index.d.ts.map +1 -0
- package/dist/tools/project/index.js +13 -0
- package/dist/tools/project/index.js.map +1 -0
- package/dist/tools/project/project-create.d.ts +142 -0
- package/dist/tools/project/project-create.d.ts.map +1 -0
- package/dist/tools/project/project-create.js +100 -0
- package/dist/tools/project/project-create.js.map +1 -0
- package/dist/tools/project/project-delete.d.ts +44 -0
- package/dist/tools/project/project-delete.d.ts.map +1 -0
- package/dist/tools/project/project-delete.js +80 -0
- package/dist/tools/project/project-delete.js.map +1 -0
- package/dist/tools/project/project-list.d.ts +227 -0
- package/dist/tools/project/project-list.d.ts.map +1 -0
- package/dist/tools/project/project-list.js +118 -0
- package/dist/tools/project/project-list.js.map +1 -0
- package/dist/tools/project/project-single.d.ts +115 -0
- package/dist/tools/project/project-single.d.ts.map +1 -0
- package/dist/tools/project/project-single.js +63 -0
- package/dist/tools/project/project-single.js.map +1 -0
- package/dist/tools/project/project-update.d.ts +151 -0
- package/dist/tools/project/project-update.d.ts.map +1 -0
- package/dist/tools/project/project-update.js +106 -0
- package/dist/tools/project/project-update.js.map +1 -0
- package/dist/tools/project/schemas.d.ts +588 -0
- package/dist/tools/project/schemas.d.ts.map +1 -0
- package/dist/tools/project/schemas.js +196 -0
- package/dist/tools/project/schemas.js.map +1 -0
- package/dist/tools/report/index.d.ts +9 -0
- package/dist/tools/report/index.d.ts.map +1 -0
- package/dist/tools/report/index.js +11 -0
- package/dist/tools/report/index.js.map +1 -0
- package/dist/tools/report/report-payments-collected.d.ts +118 -0
- package/dist/tools/report/report-payments-collected.d.ts.map +1 -0
- package/dist/tools/report/report-payments-collected.js +89 -0
- package/dist/tools/report/report-payments-collected.js.map +1 -0
- package/dist/tools/report/report-profit-loss.d.ts +139 -0
- package/dist/tools/report/report-profit-loss.d.ts.map +1 -0
- package/dist/tools/report/report-profit-loss.js +98 -0
- package/dist/tools/report/report-profit-loss.js.map +1 -0
- package/dist/tools/report/report-tax-summary.d.ts +155 -0
- package/dist/tools/report/report-tax-summary.d.ts.map +1 -0
- package/dist/tools/report/report-tax-summary.js +100 -0
- package/dist/tools/report/report-tax-summary.js.map +1 -0
- package/dist/tools/report/schemas.d.ts +859 -0
- package/dist/tools/report/schemas.d.ts.map +1 -0
- package/dist/tools/report/schemas.js +126 -0
- package/dist/tools/report/schemas.js.map +1 -0
- package/dist/tools/service/index.d.ts +12 -0
- package/dist/tools/service/index.d.ts.map +1 -0
- package/dist/tools/service/index.js +14 -0
- package/dist/tools/service/index.js.map +1 -0
- package/dist/tools/service/schemas.d.ts +159 -0
- package/dist/tools/service/schemas.d.ts.map +1 -0
- package/dist/tools/service/schemas.js +62 -0
- package/dist/tools/service/schemas.js.map +1 -0
- package/dist/tools/service/service-create.d.ts +52 -0
- package/dist/tools/service/service-create.d.ts.map +1 -0
- package/dist/tools/service/service-create.js +82 -0
- package/dist/tools/service/service-create.js.map +1 -0
- package/dist/tools/service/service-list.d.ts +119 -0
- package/dist/tools/service/service-list.d.ts.map +1 -0
- package/dist/tools/service/service-list.js +99 -0
- package/dist/tools/service/service-list.js.map +1 -0
- package/dist/tools/service/service-rate-get.d.ts +63 -0
- package/dist/tools/service/service-rate-get.d.ts.map +1 -0
- package/dist/tools/service/service-rate-get.js +66 -0
- package/dist/tools/service/service-rate-get.js.map +1 -0
- package/dist/tools/service/service-rate-set.d.ts +76 -0
- package/dist/tools/service/service-rate-set.d.ts.map +1 -0
- package/dist/tools/service/service-rate-set.js +91 -0
- package/dist/tools/service/service-rate-set.js.map +1 -0
- package/dist/tools/service/service-single.d.ts +45 -0
- package/dist/tools/service/service-single.d.ts.map +1 -0
- package/dist/tools/service/service-single.js +63 -0
- package/dist/tools/service/service-single.js.map +1 -0
- package/dist/tools/task/index.d.ts +12 -0
- package/dist/tools/task/index.d.ts.map +1 -0
- package/dist/tools/task/index.js +14 -0
- package/dist/tools/task/index.js.map +1 -0
- package/dist/tools/task/schemas.d.ts +299 -0
- package/dist/tools/task/schemas.d.ts.map +1 -0
- package/dist/tools/task/schemas.js +89 -0
- package/dist/tools/task/schemas.js.map +1 -0
- package/dist/tools/task/task-create.d.ts +101 -0
- package/dist/tools/task/task-create.d.ts.map +1 -0
- package/dist/tools/task/task-create.js +77 -0
- package/dist/tools/task/task-create.js.map +1 -0
- package/dist/tools/task/task-delete.d.ts +39 -0
- package/dist/tools/task/task-delete.d.ts.map +1 -0
- package/dist/tools/task/task-delete.js +70 -0
- package/dist/tools/task/task-delete.js.map +1 -0
- package/dist/tools/task/task-list.d.ts +157 -0
- package/dist/tools/task/task-list.d.ts.map +1 -0
- package/dist/tools/task/task-list.js +78 -0
- package/dist/tools/task/task-list.js.map +1 -0
- package/dist/tools/task/task-single.d.ts +77 -0
- package/dist/tools/task/task-single.d.ts.map +1 -0
- package/dist/tools/task/task-single.js +56 -0
- package/dist/tools/task/task-single.js.map +1 -0
- package/dist/tools/task/task-update.d.ts +107 -0
- package/dist/tools/task/task-update.d.ts.map +1 -0
- package/dist/tools/task/task-update.js +87 -0
- package/dist/tools/task/task-update.js.map +1 -0
- package/dist/tools/time-entry/index.d.ts +11 -0
- package/dist/tools/time-entry/index.d.ts.map +1 -0
- package/dist/tools/time-entry/index.js +11 -0
- package/dist/tools/time-entry/index.js.map +1 -0
- package/dist/tools/time-entry/schemas.d.ts +598 -0
- package/dist/tools/time-entry/schemas.d.ts.map +1 -0
- package/dist/tools/time-entry/schemas.js +217 -0
- package/dist/tools/time-entry/schemas.js.map +1 -0
- package/dist/tools/time-entry/timeentry-create.d.ts +142 -0
- package/dist/tools/time-entry/timeentry-create.d.ts.map +1 -0
- package/dist/tools/time-entry/timeentry-create.js +137 -0
- package/dist/tools/time-entry/timeentry-create.js.map +1 -0
- package/dist/tools/time-entry/timeentry-delete.d.ts +43 -0
- package/dist/tools/time-entry/timeentry-delete.d.ts.map +1 -0
- package/dist/tools/time-entry/timeentry-delete.js +93 -0
- package/dist/tools/time-entry/timeentry-delete.js.map +1 -0
- package/dist/tools/time-entry/timeentry-list.d.ts +232 -0
- package/dist/tools/time-entry/timeentry-list.d.ts.map +1 -0
- package/dist/tools/time-entry/timeentry-list.js +154 -0
- package/dist/tools/time-entry/timeentry-list.js.map +1 -0
- package/dist/tools/time-entry/timeentry-single.d.ts +109 -0
- package/dist/tools/time-entry/timeentry-single.d.ts.map +1 -0
- package/dist/tools/time-entry/timeentry-single.js +75 -0
- package/dist/tools/time-entry/timeentry-single.js.map +1 -0
- package/dist/tools/time-entry/timeentry-update.d.ts +145 -0
- package/dist/tools/time-entry/timeentry-update.d.ts.map +1 -0
- package/dist/tools/time-entry/timeentry-update.js +174 -0
- package/dist/tools/time-entry/timeentry-update.js.map +1 -0
- package/dist/tools/timer/index.d.ts +16 -0
- package/dist/tools/timer/index.d.ts.map +1 -0
- package/dist/tools/timer/index.js +19 -0
- package/dist/tools/timer/index.js.map +1 -0
- package/dist/tools/timer/schemas.d.ts +520 -0
- package/dist/tools/timer/schemas.d.ts.map +1 -0
- package/dist/tools/timer/schemas.js +109 -0
- package/dist/tools/timer/schemas.js.map +1 -0
- package/dist/tools/timer/timer-current.d.ts +170 -0
- package/dist/tools/timer/timer-current.d.ts.map +1 -0
- package/dist/tools/timer/timer-current.js +134 -0
- package/dist/tools/timer/timer-current.js.map +1 -0
- package/dist/tools/timer/timer-discard.d.ts +54 -0
- package/dist/tools/timer/timer-discard.d.ts.map +1 -0
- package/dist/tools/timer/timer-discard.js +115 -0
- package/dist/tools/timer/timer-discard.js.map +1 -0
- package/dist/tools/timer/timer-start.d.ts +135 -0
- package/dist/tools/timer/timer-start.d.ts.map +1 -0
- package/dist/tools/timer/timer-start.js +129 -0
- package/dist/tools/timer/timer-start.js.map +1 -0
- package/dist/tools/timer/timer-stop.d.ts +123 -0
- package/dist/tools/timer/timer-stop.d.ts.map +1 -0
- package/dist/tools/timer/timer-stop.js +165 -0
- package/dist/tools/timer/timer-stop.js.map +1 -0
- package/dist/tools/types.d.ts +49 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +61 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/tools/user/index.d.ts +7 -0
- package/dist/tools/user/index.d.ts.map +1 -0
- package/dist/tools/user/index.js +9 -0
- package/dist/tools/user/index.js.map +1 -0
- package/dist/tools/user/schemas.d.ts +258 -0
- package/dist/tools/user/schemas.d.ts.map +1 -0
- package/dist/tools/user/schemas.js +51 -0
- package/dist/tools/user/schemas.js.map +1 -0
- package/dist/tools/user/user-me.d.ts +129 -0
- package/dist/tools/user/user-me.d.ts.map +1 -0
- package/dist/tools/user/user-me.js +63 -0
- package/dist/tools/user/user-me.js.map +1 -0
- package/dist/types/freshbooks.d.ts +276 -0
- package/dist/types/freshbooks.d.ts.map +1 -0
- package/dist/types/freshbooks.js +6 -0
- package/dist/types/freshbooks.js.map +1 -0
- package/dist/types/index.d.ts +92 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +6 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logger.d.ts +54 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +133 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/pagination.d.ts +39 -0
- package/dist/utils/pagination.d.ts.map +1 -0
- package/dist/utils/pagination.js +62 -0
- package/dist/utils/pagination.js.map +1 -0
- package/package.json +88 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FreshBooks OAuth2 Implementation
|
|
3
|
+
*
|
|
4
|
+
* Handles the complete OAuth2 Authorization Code flow for FreshBooks API:
|
|
5
|
+
* - Authorization URL generation
|
|
6
|
+
* - Authorization code exchange
|
|
7
|
+
* - Token refresh
|
|
8
|
+
* - Token management
|
|
9
|
+
* - Session status
|
|
10
|
+
*/
|
|
11
|
+
import { OAuthConfig, TokenData, AuthStatus, TokenStore } from './types.js';
|
|
12
|
+
/**
|
|
13
|
+
* FreshBooks OAuth2 client
|
|
14
|
+
*
|
|
15
|
+
* Manages the complete OAuth2 flow for FreshBooks API authentication.
|
|
16
|
+
* Handles authorization, token exchange, refresh, and revocation.
|
|
17
|
+
*/
|
|
18
|
+
export declare class FreshBooksOAuth {
|
|
19
|
+
private config;
|
|
20
|
+
private tokenStore;
|
|
21
|
+
private static readonly AUTH_URL;
|
|
22
|
+
private static readonly TOKEN_URL;
|
|
23
|
+
private static readonly REVOKE_URL;
|
|
24
|
+
private static readonly EXPIRY_BUFFER_SECONDS;
|
|
25
|
+
constructor(config: OAuthConfig, tokenStore: TokenStore);
|
|
26
|
+
/**
|
|
27
|
+
* Generate OAuth2 authorization URL
|
|
28
|
+
*
|
|
29
|
+
* User must visit this URL to authorize the application.
|
|
30
|
+
* After authorization, FreshBooks redirects to the redirect_uri with an authorization code.
|
|
31
|
+
*
|
|
32
|
+
* @param state Optional state parameter for CSRF protection
|
|
33
|
+
* @returns Authorization URL for user to visit
|
|
34
|
+
*/
|
|
35
|
+
generateAuthorizationUrl(state?: string): string;
|
|
36
|
+
/**
|
|
37
|
+
* Exchange authorization code for access tokens
|
|
38
|
+
*
|
|
39
|
+
* After user authorizes the application, exchange the authorization code
|
|
40
|
+
* for access and refresh tokens.
|
|
41
|
+
*
|
|
42
|
+
* @param code Authorization code from OAuth redirect
|
|
43
|
+
* @returns Token data including access and refresh tokens
|
|
44
|
+
* @throws OAuthError if exchange fails
|
|
45
|
+
*/
|
|
46
|
+
exchangeCode(code: string): Promise<TokenData>;
|
|
47
|
+
/**
|
|
48
|
+
* Refresh expired access token using refresh token
|
|
49
|
+
*
|
|
50
|
+
* @returns New token data with refreshed access token
|
|
51
|
+
* @throws OAuthError if refresh fails or no refresh token available
|
|
52
|
+
*/
|
|
53
|
+
refreshAccessToken(): Promise<TokenData>;
|
|
54
|
+
/**
|
|
55
|
+
* Get valid access token, automatically refreshing if needed
|
|
56
|
+
*
|
|
57
|
+
* This is the primary method for obtaining tokens for API requests.
|
|
58
|
+
* Automatically handles token refresh if token is expired or about to expire.
|
|
59
|
+
*
|
|
60
|
+
* @returns Valid access token
|
|
61
|
+
* @throws OAuthError if not authenticated or refresh fails
|
|
62
|
+
*/
|
|
63
|
+
getValidToken(): Promise<string>;
|
|
64
|
+
/**
|
|
65
|
+
* Revoke current authentication tokens
|
|
66
|
+
*
|
|
67
|
+
* Revokes the access token with FreshBooks and clears local storage.
|
|
68
|
+
* Best effort - continues to clear local storage even if revocation fails.
|
|
69
|
+
*/
|
|
70
|
+
revokeToken(): Promise<void>;
|
|
71
|
+
/**
|
|
72
|
+
* Get current authentication status
|
|
73
|
+
*
|
|
74
|
+
* @returns Authentication status including validity and expiration
|
|
75
|
+
*/
|
|
76
|
+
getStatus(): Promise<AuthStatus>;
|
|
77
|
+
/**
|
|
78
|
+
* Update account and business selection in token data
|
|
79
|
+
*
|
|
80
|
+
* @param accountId FreshBooks account ID
|
|
81
|
+
* @param businessId FreshBooks business ID
|
|
82
|
+
*/
|
|
83
|
+
setActiveAccount(accountId: string, businessId?: number): Promise<void>;
|
|
84
|
+
/**
|
|
85
|
+
* Parse OAuth token response into TokenData
|
|
86
|
+
*/
|
|
87
|
+
private parseTokenResponse;
|
|
88
|
+
/**
|
|
89
|
+
* Map OAuth error codes to internal error codes
|
|
90
|
+
*/
|
|
91
|
+
private mapErrorCode;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=oauth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../src/auth/oauth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAc,UAAU,EAAE,MAAM,YAAY,CAAC;AAqBxF;;;;;GAKG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,UAAU,CAAa;IAG/B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAA4D;IAC5F,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAiD;IAClF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAkD;IAGpF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,qBAAqB,CAAO;gBAExC,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU;IAKvD;;;;;;;;OAQG;IACH,wBAAwB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM;IAoBhD;;;;;;;;;OASG;IACG,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IA6CpD;;;;;OAKG;IACG,kBAAkB,IAAI,OAAO,CAAC,SAAS,CAAC;IAiE9C;;;;;;;;OAQG;IACG,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAuBtC;;;;;OAKG;IACG,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAyBlC;;;;OAIG;IACG,SAAS,IAAI,OAAO,CAAC,UAAU,CAAC;IAqCtC;;;;;OAKG;IACG,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB7E;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAS1B;;OAEG;IACH,OAAO,CAAC,YAAY;CAWrB"}
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FreshBooks OAuth2 Implementation
|
|
3
|
+
*
|
|
4
|
+
* Handles the complete OAuth2 Authorization Code flow for FreshBooks API:
|
|
5
|
+
* - Authorization URL generation
|
|
6
|
+
* - Authorization code exchange
|
|
7
|
+
* - Token refresh
|
|
8
|
+
* - Token management
|
|
9
|
+
* - Session status
|
|
10
|
+
*/
|
|
11
|
+
import { OAuthError } from './types.js';
|
|
12
|
+
/**
|
|
13
|
+
* FreshBooks OAuth2 client
|
|
14
|
+
*
|
|
15
|
+
* Manages the complete OAuth2 flow for FreshBooks API authentication.
|
|
16
|
+
* Handles authorization, token exchange, refresh, and revocation.
|
|
17
|
+
*/
|
|
18
|
+
export class FreshBooksOAuth {
|
|
19
|
+
config;
|
|
20
|
+
tokenStore;
|
|
21
|
+
// FreshBooks OAuth2 endpoints
|
|
22
|
+
static AUTH_URL = 'https://my.freshbooks.com/service/auth/oauth/authorize';
|
|
23
|
+
static TOKEN_URL = 'https://api.freshbooks.com/auth/oauth/token';
|
|
24
|
+
static REVOKE_URL = 'https://api.freshbooks.com/auth/oauth/revoke';
|
|
25
|
+
// Token expiration buffer (refresh if expires in less than 5 minutes)
|
|
26
|
+
static EXPIRY_BUFFER_SECONDS = 300;
|
|
27
|
+
constructor(config, tokenStore) {
|
|
28
|
+
this.config = config;
|
|
29
|
+
this.tokenStore = tokenStore;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Generate OAuth2 authorization URL
|
|
33
|
+
*
|
|
34
|
+
* User must visit this URL to authorize the application.
|
|
35
|
+
* After authorization, FreshBooks redirects to the redirect_uri with an authorization code.
|
|
36
|
+
*
|
|
37
|
+
* @param state Optional state parameter for CSRF protection
|
|
38
|
+
* @returns Authorization URL for user to visit
|
|
39
|
+
*/
|
|
40
|
+
generateAuthorizationUrl(state) {
|
|
41
|
+
const params = new URLSearchParams({
|
|
42
|
+
client_id: this.config.clientId,
|
|
43
|
+
response_type: 'code',
|
|
44
|
+
redirect_uri: this.config.redirectUri,
|
|
45
|
+
});
|
|
46
|
+
// Add scopes if configured
|
|
47
|
+
if (this.config.scopes?.length) {
|
|
48
|
+
params.set('scope', this.config.scopes.join(' '));
|
|
49
|
+
}
|
|
50
|
+
// Add state parameter for CSRF protection
|
|
51
|
+
if (state) {
|
|
52
|
+
params.set('state', state);
|
|
53
|
+
}
|
|
54
|
+
return `${FreshBooksOAuth.AUTH_URL}?${params.toString()}`;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Exchange authorization code for access tokens
|
|
58
|
+
*
|
|
59
|
+
* After user authorizes the application, exchange the authorization code
|
|
60
|
+
* for access and refresh tokens.
|
|
61
|
+
*
|
|
62
|
+
* @param code Authorization code from OAuth redirect
|
|
63
|
+
* @returns Token data including access and refresh tokens
|
|
64
|
+
* @throws OAuthError if exchange fails
|
|
65
|
+
*/
|
|
66
|
+
async exchangeCode(code) {
|
|
67
|
+
try {
|
|
68
|
+
const response = await fetch(FreshBooksOAuth.TOKEN_URL, {
|
|
69
|
+
method: 'POST',
|
|
70
|
+
headers: {
|
|
71
|
+
'Content-Type': 'application/json',
|
|
72
|
+
'Api-Version': 'alpha',
|
|
73
|
+
},
|
|
74
|
+
body: JSON.stringify({
|
|
75
|
+
grant_type: 'authorization_code',
|
|
76
|
+
client_id: this.config.clientId,
|
|
77
|
+
client_secret: this.config.clientSecret,
|
|
78
|
+
code,
|
|
79
|
+
redirect_uri: this.config.redirectUri,
|
|
80
|
+
}),
|
|
81
|
+
});
|
|
82
|
+
if (!response.ok) {
|
|
83
|
+
const error = await response.json();
|
|
84
|
+
throw new OAuthError(this.mapErrorCode(error.error), error.error_description || 'Failed to exchange authorization code', error);
|
|
85
|
+
}
|
|
86
|
+
const data = await response.json();
|
|
87
|
+
const tokenData = this.parseTokenResponse(data);
|
|
88
|
+
// Save tokens to store
|
|
89
|
+
await this.tokenStore.save(tokenData);
|
|
90
|
+
return tokenData;
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
if (error instanceof OAuthError) {
|
|
94
|
+
throw error;
|
|
95
|
+
}
|
|
96
|
+
throw new OAuthError('token_exchange_failed', 'Failed to exchange authorization code', error);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Refresh expired access token using refresh token
|
|
101
|
+
*
|
|
102
|
+
* @returns New token data with refreshed access token
|
|
103
|
+
* @throws OAuthError if refresh fails or no refresh token available
|
|
104
|
+
*/
|
|
105
|
+
async refreshAccessToken() {
|
|
106
|
+
const current = await this.tokenStore.get();
|
|
107
|
+
if (!current?.refreshToken) {
|
|
108
|
+
throw new OAuthError('no_refresh_token', 'No refresh token available. Please re-authenticate.');
|
|
109
|
+
}
|
|
110
|
+
try {
|
|
111
|
+
const response = await fetch(FreshBooksOAuth.TOKEN_URL, {
|
|
112
|
+
method: 'POST',
|
|
113
|
+
headers: {
|
|
114
|
+
'Content-Type': 'application/json',
|
|
115
|
+
'Api-Version': 'alpha',
|
|
116
|
+
},
|
|
117
|
+
body: JSON.stringify({
|
|
118
|
+
grant_type: 'refresh_token',
|
|
119
|
+
client_id: this.config.clientId,
|
|
120
|
+
client_secret: this.config.clientSecret,
|
|
121
|
+
refresh_token: current.refreshToken,
|
|
122
|
+
}),
|
|
123
|
+
});
|
|
124
|
+
if (!response.ok) {
|
|
125
|
+
const error = await response.json();
|
|
126
|
+
// If refresh token is invalid, clear all tokens
|
|
127
|
+
await this.tokenStore.clear();
|
|
128
|
+
throw new OAuthError(this.mapErrorCode(error.error), error.error_description || 'Failed to refresh access token', error);
|
|
129
|
+
}
|
|
130
|
+
const data = await response.json();
|
|
131
|
+
const tokenData = this.parseTokenResponse(data);
|
|
132
|
+
// Preserve account/business selection if set
|
|
133
|
+
if (current.accountId) {
|
|
134
|
+
tokenData.accountId = current.accountId;
|
|
135
|
+
}
|
|
136
|
+
if (current.businessId) {
|
|
137
|
+
tokenData.businessId = current.businessId;
|
|
138
|
+
}
|
|
139
|
+
// Save new tokens
|
|
140
|
+
await this.tokenStore.save(tokenData);
|
|
141
|
+
return tokenData;
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
if (error instanceof OAuthError) {
|
|
145
|
+
throw error;
|
|
146
|
+
}
|
|
147
|
+
throw new OAuthError('refresh_failed', 'Failed to refresh access token', error);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Get valid access token, automatically refreshing if needed
|
|
152
|
+
*
|
|
153
|
+
* This is the primary method for obtaining tokens for API requests.
|
|
154
|
+
* Automatically handles token refresh if token is expired or about to expire.
|
|
155
|
+
*
|
|
156
|
+
* @returns Valid access token
|
|
157
|
+
* @throws OAuthError if not authenticated or refresh fails
|
|
158
|
+
*/
|
|
159
|
+
async getValidToken() {
|
|
160
|
+
const token = await this.tokenStore.get();
|
|
161
|
+
if (!token) {
|
|
162
|
+
throw new OAuthError('not_authenticated', 'No authentication found. Please authenticate first.');
|
|
163
|
+
}
|
|
164
|
+
// Check if token is expired or about to expire
|
|
165
|
+
const now = Math.floor(Date.now() / 1000);
|
|
166
|
+
const expiresIn = token.expiresAt - now;
|
|
167
|
+
// Refresh if token expires within buffer period
|
|
168
|
+
if (expiresIn < FreshBooksOAuth.EXPIRY_BUFFER_SECONDS) {
|
|
169
|
+
const newToken = await this.refreshAccessToken();
|
|
170
|
+
return newToken.accessToken;
|
|
171
|
+
}
|
|
172
|
+
return token.accessToken;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Revoke current authentication tokens
|
|
176
|
+
*
|
|
177
|
+
* Revokes the access token with FreshBooks and clears local storage.
|
|
178
|
+
* Best effort - continues to clear local storage even if revocation fails.
|
|
179
|
+
*/
|
|
180
|
+
async revokeToken() {
|
|
181
|
+
const token = await this.tokenStore.get();
|
|
182
|
+
if (token?.accessToken) {
|
|
183
|
+
try {
|
|
184
|
+
// Attempt to revoke token with FreshBooks
|
|
185
|
+
await fetch(FreshBooksOAuth.REVOKE_URL, {
|
|
186
|
+
method: 'POST',
|
|
187
|
+
headers: {
|
|
188
|
+
'Content-Type': 'application/json',
|
|
189
|
+
'Authorization': `Bearer ${token.accessToken}`,
|
|
190
|
+
},
|
|
191
|
+
body: JSON.stringify({
|
|
192
|
+
token: token.accessToken,
|
|
193
|
+
}),
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
// Best effort - continue to clear local storage even if revocation fails
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
// Clear local token storage
|
|
201
|
+
await this.tokenStore.clear();
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Get current authentication status
|
|
205
|
+
*
|
|
206
|
+
* @returns Authentication status including validity and expiration
|
|
207
|
+
*/
|
|
208
|
+
async getStatus() {
|
|
209
|
+
const token = await this.tokenStore.get();
|
|
210
|
+
if (!token) {
|
|
211
|
+
return {
|
|
212
|
+
authenticated: false,
|
|
213
|
+
reason: 'no_token',
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
const now = Math.floor(Date.now() / 1000);
|
|
217
|
+
const expiresIn = token.expiresAt - now;
|
|
218
|
+
if (expiresIn <= 0) {
|
|
219
|
+
return {
|
|
220
|
+
authenticated: false,
|
|
221
|
+
reason: 'token_expired',
|
|
222
|
+
canRefresh: !!token.refreshToken,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
const status = {
|
|
226
|
+
authenticated: true,
|
|
227
|
+
expiresIn,
|
|
228
|
+
};
|
|
229
|
+
if (token.accountId) {
|
|
230
|
+
status.accountId = token.accountId;
|
|
231
|
+
}
|
|
232
|
+
if (token.businessId !== undefined) {
|
|
233
|
+
status.businessId = token.businessId;
|
|
234
|
+
}
|
|
235
|
+
return status;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Update account and business selection in token data
|
|
239
|
+
*
|
|
240
|
+
* @param accountId FreshBooks account ID
|
|
241
|
+
* @param businessId FreshBooks business ID
|
|
242
|
+
*/
|
|
243
|
+
async setActiveAccount(accountId, businessId) {
|
|
244
|
+
const token = await this.tokenStore.get();
|
|
245
|
+
if (!token) {
|
|
246
|
+
throw new OAuthError('not_authenticated', 'No authentication found. Please authenticate first.');
|
|
247
|
+
}
|
|
248
|
+
token.accountId = accountId;
|
|
249
|
+
if (businessId !== undefined) {
|
|
250
|
+
token.businessId = businessId;
|
|
251
|
+
}
|
|
252
|
+
await this.tokenStore.save(token);
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Parse OAuth token response into TokenData
|
|
256
|
+
*/
|
|
257
|
+
parseTokenResponse(data) {
|
|
258
|
+
return {
|
|
259
|
+
accessToken: data.access_token,
|
|
260
|
+
refreshToken: data.refresh_token,
|
|
261
|
+
expiresAt: Math.floor(Date.now() / 1000) + data.expires_in,
|
|
262
|
+
tokenType: data.token_type || 'Bearer',
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Map OAuth error codes to internal error codes
|
|
267
|
+
*/
|
|
268
|
+
mapErrorCode(errorCode) {
|
|
269
|
+
const errorMap = {
|
|
270
|
+
'invalid_grant': 'invalid_grant',
|
|
271
|
+
'invalid_client': 'invalid_client',
|
|
272
|
+
'invalid_request': 'invalid_request',
|
|
273
|
+
'unauthorized_client': 'unauthorized_client',
|
|
274
|
+
'unsupported_grant_type': 'unsupported_grant_type',
|
|
275
|
+
};
|
|
276
|
+
return errorMap[errorCode] || 'token_exchange_failed';
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
//# sourceMappingURL=oauth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../src/auth/oauth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FreshBooks OAuth2 Token Storage
|
|
3
|
+
*
|
|
4
|
+
* Provides secure encrypted file storage and environment-based storage for OAuth tokens.
|
|
5
|
+
*/
|
|
6
|
+
import { TokenData, TokenStore } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Encrypted file-based token storage using AES-256-GCM
|
|
9
|
+
*
|
|
10
|
+
* Tokens are encrypted at rest using a key derived from:
|
|
11
|
+
* - Machine-specific identifier (username + platform)
|
|
12
|
+
* - Optional password from environment variable
|
|
13
|
+
*
|
|
14
|
+
* This provides defense-in-depth: even if the token file is accessed,
|
|
15
|
+
* it cannot be decrypted without the correct machine context.
|
|
16
|
+
*/
|
|
17
|
+
export declare class EncryptedFileTokenStore implements TokenStore {
|
|
18
|
+
private filePath;
|
|
19
|
+
private encryptionKey;
|
|
20
|
+
constructor(filePath: string);
|
|
21
|
+
/**
|
|
22
|
+
* Derive encryption key from machine-specific data
|
|
23
|
+
*/
|
|
24
|
+
private getKey;
|
|
25
|
+
/**
|
|
26
|
+
* Generate machine-specific identifier for key derivation
|
|
27
|
+
*/
|
|
28
|
+
private getMachineId;
|
|
29
|
+
/**
|
|
30
|
+
* Save encrypted token data to file
|
|
31
|
+
*/
|
|
32
|
+
save(token: TokenData): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Retrieve and decrypt token data from file
|
|
35
|
+
*/
|
|
36
|
+
get(): Promise<TokenData | null>;
|
|
37
|
+
/**
|
|
38
|
+
* Clear all stored tokens
|
|
39
|
+
*/
|
|
40
|
+
clear(): Promise<void>;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Environment-based token storage for CI/testing
|
|
44
|
+
*
|
|
45
|
+
* Reads tokens from environment variables:
|
|
46
|
+
* - FRESHBOOKS_ACCESS_TOKEN (required)
|
|
47
|
+
* - FRESHBOOKS_REFRESH_TOKEN (optional)
|
|
48
|
+
* - FRESHBOOKS_TOKEN_EXPIRES (optional, unix timestamp)
|
|
49
|
+
* - FRESHBOOKS_ACCOUNT_ID (optional)
|
|
50
|
+
* - FRESHBOOKS_BUSINESS_ID (optional)
|
|
51
|
+
*
|
|
52
|
+
* This store is read-only and cannot persist token changes.
|
|
53
|
+
*/
|
|
54
|
+
export declare class EnvTokenStore implements TokenStore {
|
|
55
|
+
/**
|
|
56
|
+
* Retrieve token from environment variables
|
|
57
|
+
*/
|
|
58
|
+
get(): Promise<TokenData | null>;
|
|
59
|
+
/**
|
|
60
|
+
* Save operation not supported for environment store
|
|
61
|
+
*/
|
|
62
|
+
save(_token: TokenData): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Clear operation not supported for environment store
|
|
65
|
+
*/
|
|
66
|
+
clear(): Promise<void>;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* In-memory token storage for testing
|
|
70
|
+
*
|
|
71
|
+
* Stores tokens in memory only. Tokens are lost when process exits.
|
|
72
|
+
* Useful for unit tests and temporary operations.
|
|
73
|
+
*/
|
|
74
|
+
export declare class InMemoryTokenStore implements TokenStore {
|
|
75
|
+
private token;
|
|
76
|
+
get(): Promise<TokenData | null>;
|
|
77
|
+
save(token: TokenData): Promise<void>;
|
|
78
|
+
clear(): Promise<void>;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=token-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-store.d.ts","sourceRoot":"","sources":["../../src/auth/token-store.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAInD;;;;;;;;;GASG;AACH,qBAAa,uBAAwB,YAAW,UAAU;IACxD,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,aAAa,CAAuB;gBAEhC,QAAQ,EAAE,MAAM;IAI5B;;OAEG;YACW,MAAM;IAiBpB;;OAEG;IACH,OAAO,CAAC,YAAY;IASpB;;OAEG;IACG,IAAI,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAoC3C;;OAEG;IACG,GAAG,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAiCtC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAU7B;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,aAAc,YAAW,UAAU;IAC9C;;OAEG;IACG,GAAG,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAgCtC;;OAEG;IACG,IAAI,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAS5C;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAM7B;AAED;;;;;GAKG;AACH,qBAAa,kBAAmB,YAAW,UAAU;IACnD,OAAO,CAAC,KAAK,CAA0B;IAEjC,GAAG,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAIhC,IAAI,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FreshBooks OAuth2 Token Storage
|
|
3
|
+
*
|
|
4
|
+
* Provides secure encrypted file storage and environment-based storage for OAuth tokens.
|
|
5
|
+
*/
|
|
6
|
+
import { createCipheriv, createDecipheriv, randomBytes, scrypt } from 'crypto';
|
|
7
|
+
import { promises as fs } from 'fs';
|
|
8
|
+
import { promisify } from 'util';
|
|
9
|
+
import { dirname } from 'path';
|
|
10
|
+
const scryptAsync = promisify(scrypt);
|
|
11
|
+
/**
|
|
12
|
+
* Encrypted file-based token storage using AES-256-GCM
|
|
13
|
+
*
|
|
14
|
+
* Tokens are encrypted at rest using a key derived from:
|
|
15
|
+
* - Machine-specific identifier (username + platform)
|
|
16
|
+
* - Optional password from environment variable
|
|
17
|
+
*
|
|
18
|
+
* This provides defense-in-depth: even if the token file is accessed,
|
|
19
|
+
* it cannot be decrypted without the correct machine context.
|
|
20
|
+
*/
|
|
21
|
+
export class EncryptedFileTokenStore {
|
|
22
|
+
filePath;
|
|
23
|
+
encryptionKey = null;
|
|
24
|
+
constructor(filePath) {
|
|
25
|
+
this.filePath = filePath;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Derive encryption key from machine-specific data
|
|
29
|
+
*/
|
|
30
|
+
async getKey() {
|
|
31
|
+
if (this.encryptionKey) {
|
|
32
|
+
return this.encryptionKey;
|
|
33
|
+
}
|
|
34
|
+
// Use machine-specific salt
|
|
35
|
+
const machineId = this.getMachineId();
|
|
36
|
+
// Optional password from environment, or default
|
|
37
|
+
const password = process.env.FRESHBOOKS_TOKEN_PASSWORD || 'freshbooks-mcp-default-key';
|
|
38
|
+
// Derive 32-byte key using scrypt
|
|
39
|
+
this.encryptionKey = (await scryptAsync(password, machineId, 32));
|
|
40
|
+
return this.encryptionKey;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Generate machine-specific identifier for key derivation
|
|
44
|
+
*/
|
|
45
|
+
getMachineId() {
|
|
46
|
+
// Combine platform-specific data for unique salt
|
|
47
|
+
const username = process.env.USERNAME || process.env.USER || 'unknown';
|
|
48
|
+
const platform = process.platform;
|
|
49
|
+
const hostname = process.env.COMPUTERNAME || process.env.HOSTNAME || 'unknown';
|
|
50
|
+
return `${username}-${platform}-${hostname}-freshbooks-mcp`;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Save encrypted token data to file
|
|
54
|
+
*/
|
|
55
|
+
async save(token) {
|
|
56
|
+
const key = await this.getKey();
|
|
57
|
+
// Generate random IV for this encryption
|
|
58
|
+
const iv = randomBytes(16);
|
|
59
|
+
// Create cipher
|
|
60
|
+
const cipher = createCipheriv('aes-256-gcm', key, iv);
|
|
61
|
+
// Encrypt token data
|
|
62
|
+
const data = JSON.stringify(token);
|
|
63
|
+
const encrypted = Buffer.concat([
|
|
64
|
+
cipher.update(data, 'utf8'),
|
|
65
|
+
cipher.final(),
|
|
66
|
+
]);
|
|
67
|
+
// Get authentication tag
|
|
68
|
+
const authTag = cipher.getAuthTag();
|
|
69
|
+
// Store IV, auth tag, and encrypted data
|
|
70
|
+
const stored = {
|
|
71
|
+
iv: iv.toString('hex'),
|
|
72
|
+
authTag: authTag.toString('hex'),
|
|
73
|
+
data: encrypted.toString('hex'),
|
|
74
|
+
};
|
|
75
|
+
// Ensure directory exists
|
|
76
|
+
await fs.mkdir(dirname(this.filePath), { recursive: true });
|
|
77
|
+
// Write to file with restricted permissions
|
|
78
|
+
await fs.writeFile(this.filePath, JSON.stringify(stored), {
|
|
79
|
+
encoding: 'utf8',
|
|
80
|
+
mode: 0o600, // Owner read/write only
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Retrieve and decrypt token data from file
|
|
85
|
+
*/
|
|
86
|
+
async get() {
|
|
87
|
+
try {
|
|
88
|
+
// Read encrypted file
|
|
89
|
+
const content = await fs.readFile(this.filePath, 'utf8');
|
|
90
|
+
const stored = JSON.parse(content);
|
|
91
|
+
// Get decryption key
|
|
92
|
+
const key = await this.getKey();
|
|
93
|
+
// Parse stored components
|
|
94
|
+
const iv = Buffer.from(stored.iv, 'hex');
|
|
95
|
+
const authTag = Buffer.from(stored.authTag, 'hex');
|
|
96
|
+
const encrypted = Buffer.from(stored.data, 'hex');
|
|
97
|
+
// Create decipher
|
|
98
|
+
const decipher = createDecipheriv('aes-256-gcm', key, iv);
|
|
99
|
+
decipher.setAuthTag(authTag);
|
|
100
|
+
// Decrypt data
|
|
101
|
+
const decrypted = Buffer.concat([
|
|
102
|
+
decipher.update(encrypted),
|
|
103
|
+
decipher.final(),
|
|
104
|
+
]);
|
|
105
|
+
// Parse and return token data
|
|
106
|
+
return JSON.parse(decrypted.toString('utf8'));
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
// File doesn't exist, is corrupted, or decryption failed
|
|
110
|
+
// Return null to indicate no valid token
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Clear all stored tokens
|
|
116
|
+
*/
|
|
117
|
+
async clear() {
|
|
118
|
+
try {
|
|
119
|
+
await fs.unlink(this.filePath);
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
// File may not exist, ignore error
|
|
123
|
+
}
|
|
124
|
+
// Clear cached encryption key
|
|
125
|
+
this.encryptionKey = null;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Environment-based token storage for CI/testing
|
|
130
|
+
*
|
|
131
|
+
* Reads tokens from environment variables:
|
|
132
|
+
* - FRESHBOOKS_ACCESS_TOKEN (required)
|
|
133
|
+
* - FRESHBOOKS_REFRESH_TOKEN (optional)
|
|
134
|
+
* - FRESHBOOKS_TOKEN_EXPIRES (optional, unix timestamp)
|
|
135
|
+
* - FRESHBOOKS_ACCOUNT_ID (optional)
|
|
136
|
+
* - FRESHBOOKS_BUSINESS_ID (optional)
|
|
137
|
+
*
|
|
138
|
+
* This store is read-only and cannot persist token changes.
|
|
139
|
+
*/
|
|
140
|
+
export class EnvTokenStore {
|
|
141
|
+
/**
|
|
142
|
+
* Retrieve token from environment variables
|
|
143
|
+
*/
|
|
144
|
+
async get() {
|
|
145
|
+
const accessToken = process.env.FRESHBOOKS_ACCESS_TOKEN;
|
|
146
|
+
if (!accessToken) {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
const refreshToken = process.env.FRESHBOOKS_REFRESH_TOKEN || '';
|
|
150
|
+
const expiresAt = parseInt(process.env.FRESHBOOKS_TOKEN_EXPIRES || '0', 10);
|
|
151
|
+
const accountId = process.env.FRESHBOOKS_ACCOUNT_ID;
|
|
152
|
+
const businessId = process.env.FRESHBOOKS_BUSINESS_ID
|
|
153
|
+
? parseInt(process.env.FRESHBOOKS_BUSINESS_ID, 10)
|
|
154
|
+
: undefined;
|
|
155
|
+
const tokenData = {
|
|
156
|
+
accessToken,
|
|
157
|
+
refreshToken,
|
|
158
|
+
expiresAt,
|
|
159
|
+
tokenType: 'Bearer',
|
|
160
|
+
};
|
|
161
|
+
if (accountId) {
|
|
162
|
+
tokenData.accountId = accountId;
|
|
163
|
+
}
|
|
164
|
+
if (businessId !== undefined) {
|
|
165
|
+
tokenData.businessId = businessId;
|
|
166
|
+
}
|
|
167
|
+
return tokenData;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Save operation not supported for environment store
|
|
171
|
+
*/
|
|
172
|
+
async save(_token) {
|
|
173
|
+
// Environment store is read-only
|
|
174
|
+
// Tokens should be updated via environment variable configuration
|
|
175
|
+
console.error('Warning: EnvTokenStore is read-only. Cannot persist token updates. ' +
|
|
176
|
+
'Update FRESHBOOKS_ACCESS_TOKEN and related environment variables manually.');
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Clear operation not supported for environment store
|
|
180
|
+
*/
|
|
181
|
+
async clear() {
|
|
182
|
+
// Cannot clear environment variables
|
|
183
|
+
console.error('Warning: EnvTokenStore is read-only. Cannot clear environment variables.');
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* In-memory token storage for testing
|
|
188
|
+
*
|
|
189
|
+
* Stores tokens in memory only. Tokens are lost when process exits.
|
|
190
|
+
* Useful for unit tests and temporary operations.
|
|
191
|
+
*/
|
|
192
|
+
export class InMemoryTokenStore {
|
|
193
|
+
token = null;
|
|
194
|
+
async get() {
|
|
195
|
+
return this.token;
|
|
196
|
+
}
|
|
197
|
+
async save(token) {
|
|
198
|
+
this.token = token;
|
|
199
|
+
}
|
|
200
|
+
async clear() {
|
|
201
|
+
this.token = null;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=token-store.js.map
|