@ktmcp-cli/billingo 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/api.js ADDED
@@ -0,0 +1,199 @@
1
+ import axios from 'axios';
2
+ import { getConfig } from './config.js';
3
+
4
+ const BILLINGO_BASE_URL = 'https://api.billingo.hu/v3';
5
+
6
+ /**
7
+ * Make an authenticated API request
8
+ */
9
+ async function apiRequest(method, endpoint, data = null, params = null) {
10
+ const apiKey = getConfig('apiKey');
11
+
12
+ if (!apiKey) {
13
+ throw new Error('API key not configured. Please run: billingohu config set --api-key <key>');
14
+ }
15
+
16
+ const config = {
17
+ method,
18
+ url: `${BILLINGO_BASE_URL}${endpoint}`,
19
+ headers: {
20
+ 'X-API-KEY': apiKey,
21
+ 'Accept': 'application/json',
22
+ 'Content-Type': 'application/json'
23
+ }
24
+ };
25
+
26
+ if (params) config.params = params;
27
+ if (data) config.data = data;
28
+
29
+ try {
30
+ const response = await axios(config);
31
+ return response.data;
32
+ } catch (error) {
33
+ handleApiError(error);
34
+ }
35
+ }
36
+
37
+ function handleApiError(error) {
38
+ if (error.response) {
39
+ const status = error.response.status;
40
+ const data = error.response.data;
41
+
42
+ if (status === 401) {
43
+ throw new Error('Authentication failed. Check your API key.');
44
+ } else if (status === 403) {
45
+ throw new Error('Access forbidden. Check your API permissions.');
46
+ } else if (status === 404) {
47
+ throw new Error('Resource not found.');
48
+ } else if (status === 429) {
49
+ throw new Error('Rate limit exceeded. Please wait before retrying.');
50
+ } else {
51
+ const message = data?.message || JSON.stringify(data);
52
+ throw new Error(`API Error (${status}): ${message}`);
53
+ }
54
+ } else if (error.request) {
55
+ throw new Error('No response from Billingo API. Check your internet connection.');
56
+ } else {
57
+ throw error;
58
+ }
59
+ }
60
+
61
+ // ============================================================
62
+ // DOCUMENTS (Invoices)
63
+ // ============================================================
64
+
65
+ export async function listDocuments({ page = 1, perPage = 25, type, status } = {}) {
66
+ const params = { page, per_page: perPage };
67
+ if (type) params.type = type;
68
+ if (status) params.status = status;
69
+
70
+ const data = await apiRequest('GET', '/documents', null, params);
71
+ return data.data || [];
72
+ }
73
+
74
+ export async function getDocument(documentId) {
75
+ const data = await apiRequest('GET', `/documents/${documentId}`);
76
+ return data.data || null;
77
+ }
78
+
79
+ export async function createDocument(documentData) {
80
+ const data = await apiRequest('POST', '/documents', documentData);
81
+ return data.data || null;
82
+ }
83
+
84
+ export async function downloadDocument(documentId) {
85
+ const data = await apiRequest('GET', `/documents/${documentId}/download`);
86
+ return data;
87
+ }
88
+
89
+ export async function sendDocument(documentId, emails) {
90
+ const data = await apiRequest('POST', `/documents/${documentId}/send`, { emails });
91
+ return data;
92
+ }
93
+
94
+ // ============================================================
95
+ // PARTNERS (Clients)
96
+ // ============================================================
97
+
98
+ export async function listPartners({ page = 1, perPage = 25, query } = {}) {
99
+ const params = { page, per_page: perPage };
100
+ if (query) params.query = query;
101
+
102
+ const data = await apiRequest('GET', '/partners', null, params);
103
+ return data.data || [];
104
+ }
105
+
106
+ export async function getPartner(partnerId) {
107
+ const data = await apiRequest('GET', `/partners/${partnerId}`);
108
+ return data.data || null;
109
+ }
110
+
111
+ export async function createPartner(partnerData) {
112
+ const data = await apiRequest('POST', '/partners', partnerData);
113
+ return data.data || null;
114
+ }
115
+
116
+ export async function updatePartner(partnerId, partnerData) {
117
+ const data = await apiRequest('PUT', `/partners/${partnerId}`, partnerData);
118
+ return data.data || null;
119
+ }
120
+
121
+ export async function deletePartner(partnerId) {
122
+ await apiRequest('DELETE', `/partners/${partnerId}`);
123
+ return true;
124
+ }
125
+
126
+ // ============================================================
127
+ // PRODUCTS
128
+ // ============================================================
129
+
130
+ export async function listProducts({ page = 1, perPage = 25 } = {}) {
131
+ const params = { page, per_page: perPage };
132
+ const data = await apiRequest('GET', '/products', null, params);
133
+ return data.data || [];
134
+ }
135
+
136
+ export async function getProduct(productId) {
137
+ const data = await apiRequest('GET', `/products/${productId}`);
138
+ return data.data || null;
139
+ }
140
+
141
+ export async function createProduct(productData) {
142
+ const data = await apiRequest('POST', '/products', productData);
143
+ return data.data || null;
144
+ }
145
+
146
+ export async function updateProduct(productId, productData) {
147
+ const data = await apiRequest('PUT', `/products/${productId}`, productData);
148
+ return data.data || null;
149
+ }
150
+
151
+ export async function deleteProduct(productId) {
152
+ await apiRequest('DELETE', `/products/${productId}`);
153
+ return true;
154
+ }
155
+
156
+ // ============================================================
157
+ // BANK ACCOUNTS
158
+ // ============================================================
159
+
160
+ export async function listBankAccounts({ page = 1, perPage = 25 } = {}) {
161
+ const params = { page, per_page: perPage };
162
+ const data = await apiRequest('GET', '/bank-accounts', null, params);
163
+ return data.data || [];
164
+ }
165
+
166
+ export async function getBankAccount(accountId) {
167
+ const data = await apiRequest('GET', `/bank-accounts/${accountId}`);
168
+ return data.data || null;
169
+ }
170
+
171
+ export async function createBankAccount(accountData) {
172
+ const data = await apiRequest('POST', '/bank-accounts', accountData);
173
+ return data.data || null;
174
+ }
175
+
176
+ export async function updateBankAccount(accountId, accountData) {
177
+ const data = await apiRequest('PUT', `/bank-accounts/${accountId}`, accountData);
178
+ return data.data || null;
179
+ }
180
+
181
+ export async function deleteBankAccount(accountId) {
182
+ await apiRequest('DELETE', `/bank-accounts/${accountId}`);
183
+ return true;
184
+ }
185
+
186
+ // ============================================================
187
+ // DOCUMENT BLOCKS (Invoice pads)
188
+ // ============================================================
189
+
190
+ export async function listDocumentBlocks({ page = 1, perPage = 25 } = {}) {
191
+ const params = { page, per_page: perPage };
192
+ const data = await apiRequest('GET', '/document-blocks', null, params);
193
+ return data.data || [];
194
+ }
195
+
196
+ export async function getDocumentBlock(blockId) {
197
+ const data = await apiRequest('GET', `/document-blocks/${blockId}`);
198
+ return data.data || null;
199
+ }
package/src/config.js ADDED
@@ -0,0 +1,34 @@
1
+ import Conf from 'conf';
2
+
3
+ const config = new Conf({
4
+ projectName: 'billingohu-cli',
5
+ schema: {
6
+ apiKey: {
7
+ type: 'string',
8
+ default: ''
9
+ }
10
+ }
11
+ });
12
+
13
+ export function getConfig(key) {
14
+ return config.get(key);
15
+ }
16
+
17
+ export function setConfig(key, value) {
18
+ config.set(key, value);
19
+ }
20
+
21
+ export function getAllConfig() {
22
+ return config.store;
23
+ }
24
+
25
+ export function clearConfig() {
26
+ config.clear();
27
+ }
28
+
29
+ export function isConfigured() {
30
+ const apiKey = config.get('apiKey');
31
+ return !!apiKey;
32
+ }
33
+
34
+ export default config;