noxctl 0.4.1 → 0.5.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/README.md +3 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +117 -2
- package/dist/cli.js.map +1 -1
- package/dist/fortnox-client.d.ts +29 -1
- package/dist/fortnox-client.d.ts.map +1 -1
- package/dist/fortnox-client.js +177 -59
- package/dist/fortnox-client.js.map +1 -1
- package/dist/operations/invoices.d.ts +38 -0
- package/dist/operations/invoices.d.ts.map +1 -1
- package/dist/operations/invoices.js +54 -3
- package/dist/operations/invoices.js.map +1 -1
- package/dist/tools/invoices.d.ts.map +1 -1
- package/dist/tools/invoices.js +136 -1
- package/dist/tools/invoices.js.map +1 -1
- package/package.json +1 -1
package/dist/fortnox-client.js
CHANGED
|
@@ -60,8 +60,8 @@ export class FortnoxApiError extends Error {
|
|
|
60
60
|
}
|
|
61
61
|
export class FortnoxRequestTimeoutError extends Error {
|
|
62
62
|
outcomeUnknown;
|
|
63
|
-
constructor(method, endpoint, timeoutMs) {
|
|
64
|
-
const mutation = !['GET', 'HEAD', 'OPTIONS'].includes(method);
|
|
63
|
+
constructor(method, endpoint, timeoutMs, isMutation) {
|
|
64
|
+
const mutation = isMutation ?? !['GET', 'HEAD', 'OPTIONS'].includes(method);
|
|
65
65
|
const suffix = mutation
|
|
66
66
|
? ' The outcome is unknown; verify the result in Fortnox before retrying to avoid duplicate side effects.'
|
|
67
67
|
: ' It is safe to retry the read request.';
|
|
@@ -197,73 +197,191 @@ async function retryWithBackoff(fn, retryable, maxRetries = MAX_RETRIES) {
|
|
|
197
197
|
}
|
|
198
198
|
throw new Error('Unreachable');
|
|
199
199
|
}
|
|
200
|
-
|
|
200
|
+
// Issue the HTTP request and translate a non-2xx answer into a FortnoxApiError.
|
|
201
|
+
// Returns the raw Response so callers can decide how to read the body.
|
|
202
|
+
async function sendRequest(endpoint, options, method, timeoutMs) {
|
|
203
|
+
await waitForRateLimit();
|
|
204
|
+
const token = await getValidToken();
|
|
205
|
+
const url = new URL(`${BASE_URL}/${endpoint}`);
|
|
206
|
+
if (options.params) {
|
|
207
|
+
for (const [key, value] of Object.entries(options.params)) {
|
|
208
|
+
if (value !== undefined) {
|
|
209
|
+
url.searchParams.set(key, String(value));
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
// Accept is always application/json, even for the endpoints that answer with a
|
|
214
|
+
// PDF. This looks wrong but is not: Fortnox rejects Accept: application/pdf (and
|
|
215
|
+
// application/octet-stream) on its PDF endpoints with
|
|
216
|
+
// {"ErrorInformation":{"error":1,"message":"Invalid response type","code":1000030}}.
|
|
217
|
+
// Do not "fix" this header.
|
|
218
|
+
const headers = {
|
|
219
|
+
Authorization: `Bearer ${token}`,
|
|
220
|
+
Accept: 'application/json',
|
|
221
|
+
};
|
|
222
|
+
const fetchOptions = {
|
|
223
|
+
method,
|
|
224
|
+
headers,
|
|
225
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
226
|
+
};
|
|
227
|
+
if (options.rawBody !== undefined) {
|
|
228
|
+
// A raw body (e.g. FormData for a multipart file upload): do NOT set
|
|
229
|
+
// Content-Type — fetch/undici derives it (and the multipart boundary)
|
|
230
|
+
// from the body itself.
|
|
231
|
+
fetchOptions.body = options.rawBody;
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
headers['Content-Type'] = 'application/json';
|
|
235
|
+
if (options.body) {
|
|
236
|
+
fetchOptions.body = JSON.stringify(options.body);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
const response = await fetch(url.toString(), fetchOptions);
|
|
240
|
+
if (!response.ok) {
|
|
241
|
+
let errorMessage = `HTTP ${response.status}`;
|
|
242
|
+
let details;
|
|
243
|
+
try {
|
|
244
|
+
const errorBody = (await response.json());
|
|
245
|
+
if (errorBody?.ErrorInformation) {
|
|
246
|
+
errorMessage = errorBody.ErrorInformation.message || errorMessage;
|
|
247
|
+
details = `Error code: ${errorBody.ErrorInformation.code}`;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
catch {
|
|
251
|
+
// ignore parse errors
|
|
252
|
+
}
|
|
253
|
+
throw new FortnoxApiError(response.status, errorMessage, details, endpoint, retryAfterDelay(response));
|
|
254
|
+
}
|
|
255
|
+
return response;
|
|
256
|
+
}
|
|
257
|
+
// Shared retry/timeout envelope; `readBody` turns a successful Response into T.
|
|
258
|
+
async function request(endpoint, options, readBody) {
|
|
201
259
|
const method = (options.method || 'GET').toUpperCase();
|
|
202
|
-
const
|
|
260
|
+
const isMutation = options.mutation ?? !(method === 'GET' || method === 'HEAD' || method === 'OPTIONS');
|
|
261
|
+
const retryable = !isMutation;
|
|
203
262
|
const timeoutMs = options.rawBody === undefined ? REQUEST_TIMEOUT_MS : UPLOAD_TIMEOUT_MS;
|
|
204
263
|
try {
|
|
205
|
-
return await retryWithBackoff(async () =>
|
|
206
|
-
await waitForRateLimit();
|
|
207
|
-
const token = await getValidToken();
|
|
208
|
-
const url = new URL(`${BASE_URL}/${endpoint}`);
|
|
209
|
-
if (options.params) {
|
|
210
|
-
for (const [key, value] of Object.entries(options.params)) {
|
|
211
|
-
if (value !== undefined) {
|
|
212
|
-
url.searchParams.set(key, String(value));
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
const headers = {
|
|
217
|
-
Authorization: `Bearer ${token}`,
|
|
218
|
-
Accept: 'application/json',
|
|
219
|
-
};
|
|
220
|
-
const fetchOptions = {
|
|
221
|
-
method,
|
|
222
|
-
headers,
|
|
223
|
-
signal: AbortSignal.timeout(timeoutMs),
|
|
224
|
-
};
|
|
225
|
-
if (options.rawBody !== undefined) {
|
|
226
|
-
// A raw body (e.g. FormData for a multipart file upload): do NOT set
|
|
227
|
-
// Content-Type — fetch/undici derives it (and the multipart boundary)
|
|
228
|
-
// from the body itself.
|
|
229
|
-
fetchOptions.body = options.rawBody;
|
|
230
|
-
}
|
|
231
|
-
else {
|
|
232
|
-
headers['Content-Type'] = 'application/json';
|
|
233
|
-
if (options.body) {
|
|
234
|
-
fetchOptions.body = JSON.stringify(options.body);
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
const response = await fetch(url.toString(), fetchOptions);
|
|
238
|
-
if (!response.ok) {
|
|
239
|
-
let errorMessage = `HTTP ${response.status}`;
|
|
240
|
-
let details;
|
|
241
|
-
try {
|
|
242
|
-
const errorBody = (await response.json());
|
|
243
|
-
if (errorBody?.ErrorInformation) {
|
|
244
|
-
errorMessage = errorBody.ErrorInformation.message || errorMessage;
|
|
245
|
-
details = `Error code: ${errorBody.ErrorInformation.code}`;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
catch {
|
|
249
|
-
// ignore parse errors
|
|
250
|
-
}
|
|
251
|
-
throw new FortnoxApiError(response.status, errorMessage, details, endpoint, retryAfterDelay(response));
|
|
252
|
-
}
|
|
253
|
-
// Some endpoints return empty responses (e.g., DELETE)
|
|
254
|
-
const text = await response.text();
|
|
255
|
-
if (!text)
|
|
256
|
-
return undefined;
|
|
257
|
-
return JSON.parse(text);
|
|
258
|
-
}, retryable);
|
|
264
|
+
return await retryWithBackoff(async () => readBody(await sendRequest(endpoint, options, method, timeoutMs)), retryable);
|
|
259
265
|
}
|
|
260
266
|
catch (err) {
|
|
261
267
|
if (isTimeoutError(err)) {
|
|
262
|
-
throw new FortnoxRequestTimeoutError(method, endpoint, timeoutMs);
|
|
268
|
+
throw new FortnoxRequestTimeoutError(method, endpoint, timeoutMs, isMutation);
|
|
263
269
|
}
|
|
264
270
|
throw err;
|
|
265
271
|
}
|
|
266
272
|
}
|
|
273
|
+
export async function fortnoxRequest(endpoint, options = {}) {
|
|
274
|
+
return request(endpoint, options, async (response) => {
|
|
275
|
+
// Some endpoints return empty responses (e.g., DELETE)
|
|
276
|
+
const text = await response.text();
|
|
277
|
+
if (!text)
|
|
278
|
+
return undefined;
|
|
279
|
+
return JSON.parse(text);
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
// Summarize an unexpected (non-binary) body for an error message, preferring the
|
|
283
|
+
// Fortnox error envelope when the body turns out to be one.
|
|
284
|
+
function describeUnexpectedBody(buf) {
|
|
285
|
+
const text = buf.toString('utf-8', 0, 2000).trim();
|
|
286
|
+
try {
|
|
287
|
+
const parsed = JSON.parse(text);
|
|
288
|
+
const info = parsed?.ErrorInformation;
|
|
289
|
+
if (info?.message) {
|
|
290
|
+
return info.code === undefined ? info.message : `${info.message} (code ${info.code})`;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
catch {
|
|
294
|
+
// not JSON — fall through to the raw excerpt
|
|
295
|
+
}
|
|
296
|
+
return text.slice(0, 200) || '<empty body>';
|
|
297
|
+
}
|
|
298
|
+
const PDF_MAGIC = '%PDF-';
|
|
299
|
+
const PDF_TRAILER = '%%EOF';
|
|
300
|
+
function startsWithPdfMagic(buf) {
|
|
301
|
+
return buf.subarray(0, PDF_MAGIC.length).toString('latin1') === PDF_MAGIC;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* A PDF that both starts with the magic number and carries its end-of-file
|
|
305
|
+
* trailer, i.e. one that was not cut short in transit. Used where a *partial*
|
|
306
|
+
* document would be worse than none — replacing an already-saved copy, say.
|
|
307
|
+
* The trailer may be followed by whitespace, so search the tail rather than
|
|
308
|
+
* requiring it at the very end.
|
|
309
|
+
*/
|
|
310
|
+
function isCompletePdf(buf) {
|
|
311
|
+
if (!startsWithPdfMagic(buf))
|
|
312
|
+
return false;
|
|
313
|
+
const tail = buf.subarray(Math.max(0, buf.length - 1024)).toString('latin1');
|
|
314
|
+
return tail.includes(PDF_TRAILER);
|
|
315
|
+
}
|
|
316
|
+
/** Fortnox can answer 2xx with an error envelope; detect one in a raw body. */
|
|
317
|
+
function fortnoxErrorInBody(buf) {
|
|
318
|
+
if (startsWithPdfMagic(buf))
|
|
319
|
+
return undefined;
|
|
320
|
+
try {
|
|
321
|
+
const parsed = JSON.parse(buf.toString('utf-8', 0, 4096));
|
|
322
|
+
const info = parsed?.ErrorInformation;
|
|
323
|
+
return info?.message ? { message: info.message, code: info.code } : undefined;
|
|
324
|
+
}
|
|
325
|
+
catch {
|
|
326
|
+
return undefined;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Fetch a PDF from one of Fortnox's document endpoints. Shares rate limiting,
|
|
331
|
+
* retries, timeouts and error mapping with `fortnoxRequest`.
|
|
332
|
+
*
|
|
333
|
+
* The returned bytes are validated by their magic number rather than by the
|
|
334
|
+
* Content-Type header: Fortnox can answer 200 with a JSON error envelope, and a
|
|
335
|
+
* proxy can return an HTML error page, either of which would otherwise be saved
|
|
336
|
+
* as `invoice-1001.pdf` and look like success until someone opened the file.
|
|
337
|
+
*/
|
|
338
|
+
export async function fortnoxRequestPdf(endpoint, options = {}) {
|
|
339
|
+
return request(endpoint, options, async (response) => {
|
|
340
|
+
const buf = Buffer.from(await response.arrayBuffer());
|
|
341
|
+
if (!startsWithPdfMagic(buf)) {
|
|
342
|
+
const contentType = response.headers?.get?.('content-type') || 'an unknown content type';
|
|
343
|
+
throw new Error(`Fortnox returned ${contentType} that is not a PDF for ${endpoint}: ${describeUnexpectedBody(buf)}`);
|
|
344
|
+
}
|
|
345
|
+
return buf;
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* For endpoints where the PDF is a by-product of a state change — Fortnox's
|
|
350
|
+
* `/print` both returns the document and sets `Sent`.
|
|
351
|
+
*
|
|
352
|
+
* Once the server has answered 2xx the mutation has happened, so nothing about
|
|
353
|
+
* the body may raise: a truncated or malformed payload is reported as "no PDF"
|
|
354
|
+
* rather than as an error, because throwing here would turn a completed
|
|
355
|
+
* accounting change into a reported failure. Always treated as a mutation, so
|
|
356
|
+
* it is never auto-retried.
|
|
357
|
+
*/
|
|
358
|
+
export async function fortnoxRequestPdfFromMutation(endpoint, options = {}) {
|
|
359
|
+
return request(endpoint, { ...options, mutation: true }, async (response) => {
|
|
360
|
+
let buf;
|
|
361
|
+
try {
|
|
362
|
+
buf = Buffer.from(await response.arrayBuffer());
|
|
363
|
+
}
|
|
364
|
+
catch {
|
|
365
|
+
// Body unreadable (truncated stream, aborted transfer). The status line
|
|
366
|
+
// already said the action succeeded; report it as such.
|
|
367
|
+
return undefined;
|
|
368
|
+
}
|
|
369
|
+
if (isCompletePdf(buf))
|
|
370
|
+
return buf;
|
|
371
|
+
// A well-formed Fortnox error envelope is positive evidence that the action
|
|
372
|
+
// did NOT happen — unlike an unreadable body, which is merely inconclusive.
|
|
373
|
+
// Fortnox can send these with a 2xx status, so this has to be checked here
|
|
374
|
+
// rather than left to the status code.
|
|
375
|
+
const failure = fortnoxErrorInBody(buf);
|
|
376
|
+
if (failure) {
|
|
377
|
+
throw new FortnoxApiError(response.status, failure.message, `Error code: ${failure.code}`, endpoint);
|
|
378
|
+
}
|
|
379
|
+
// Something else came back — an incomplete PDF, or a payload we cannot
|
|
380
|
+
// interpret. Inconclusive, so treat the action as done but offer no
|
|
381
|
+
// document: callers must not overwrite a good file with this.
|
|
382
|
+
return undefined;
|
|
383
|
+
});
|
|
384
|
+
}
|
|
267
385
|
/**
|
|
268
386
|
* Fetch all pages of a paginated Fortnox list endpoint.
|
|
269
387
|
* `dataKey` is the envelope key (e.g. "Invoices", "Customers").
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fortnox-client.js","sourceRoot":"","sources":["../src/fortnox-client.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"fortnox-client.js","sourceRoot":"","sources":["../src/fortnox-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -26,6 +26,44 @@ export interface SendEmailOptions {
|
|
|
26
26
|
bcc?: string;
|
|
27
27
|
}
|
|
28
28
|
export declare function sendInvoice(documentNumber: string, method?: SendMethod, emailOptions?: SendEmailOptions): Promise<Record<string, unknown>>;
|
|
29
|
+
/**
|
|
30
|
+
* Fetch an invoice as a PDF. Always uses /preview, which returns the same
|
|
31
|
+
* document as /print but leaves the invoice untouched.
|
|
32
|
+
*
|
|
33
|
+
* Marking the invoice as sent is deliberately NOT folded in here: callers that
|
|
34
|
+
* want both run this first, write the bytes out, and only then call
|
|
35
|
+
* `markInvoicePrinted`. Doing it the other way round means a full disk or a bad
|
|
36
|
+
* path leaves an invoice flagged as sent with no PDF to show for it.
|
|
37
|
+
*/
|
|
38
|
+
export declare function getInvoicePdf(documentNumber: string): Promise<Buffer>;
|
|
39
|
+
export interface MarkInvoicePrintedResult {
|
|
40
|
+
/** The invoice's state after printing. */
|
|
41
|
+
invoice: Record<string, unknown>;
|
|
42
|
+
/**
|
|
43
|
+
* Whether that state was actually read back from Fortnox. When false, the
|
|
44
|
+
* print request was accepted but its effect could not be confirmed — callers
|
|
45
|
+
* must report the outcome as unknown rather than as sent.
|
|
46
|
+
*/
|
|
47
|
+
confirmed: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* The document Fortnox generated for this print action, when it came back
|
|
50
|
+
* intact. Callers saving a copy should prefer these bytes over a separately
|
|
51
|
+
* fetched /preview: the two are distinct requests, so a concurrent edit could
|
|
52
|
+
* otherwise leave the saved file a version behind the one marked as sent.
|
|
53
|
+
*/
|
|
54
|
+
pdf?: Buffer;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Mark an invoice as sent via Fortnox's /print action, and report its resulting
|
|
58
|
+
* state. /print is a GET that changes data, so it is flagged as a mutation to
|
|
59
|
+
* keep it out of the automatic retry path.
|
|
60
|
+
*
|
|
61
|
+
* Once the /print request succeeds the invoice has been changed, so from that
|
|
62
|
+
* point on this function does not throw: neither a malformed PDF body nor a
|
|
63
|
+
* failed read-back may turn a completed accounting change into a reported
|
|
64
|
+
* failure.
|
|
65
|
+
*/
|
|
66
|
+
export declare function markInvoicePrinted(documentNumber: string): Promise<MarkInvoicePrintedResult>;
|
|
29
67
|
export declare function bookkeepInvoice(documentNumber: string): Promise<Record<string, unknown>>;
|
|
30
68
|
export declare function creditInvoice(documentNumber: string): Promise<Record<string, unknown>>;
|
|
31
69
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"invoices.d.ts","sourceRoot":"","sources":["../../src/operations/invoices.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"invoices.d.ts","sourceRoot":"","sources":["../../src/operations/invoices.ts"],"names":[],"mappings":"AAYA,UAAU,gBAAgB;IACxB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IACpC,eAAe,CAAC,EAAE;QAAE,iBAAiB,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE,CAAC;CAChG;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,wBAAsB,YAAY,CAAC,MAAM,GAAE,kBAAuB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAuB7F;AAED,wBAAsB,UAAU,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAGzF;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAMlC;AAED,wBAAsB,aAAa,CACjC,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAUlC;AAED,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,OAAO,GAAG,UAAU,CAAC;AAExD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAsB,WAAW,CAC/B,cAAc,EAAE,MAAM,EACtB,MAAM,GAAE,UAAoB,EAC5B,YAAY,CAAC,EAAE,gBAAgB,GAC9B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CA8BlC;AAED;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAE3E;AAED,MAAM,WAAW,wBAAwB;IACvC,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC;;;;OAIG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB;;;;;OAKG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;GASG;AACH,wBAAsB,kBAAkB,CACtC,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,wBAAwB,CAAC,CAuBnC;AAED,wBAAsB,eAAe,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAQ9F;AAED,wBAAsB,aAAa,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAQ5F"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { fortnoxRequest, fetchAllPages } from '../fortnox-client.js';
|
|
1
|
+
import { fortnoxRequest, fortnoxRequestPdf, fortnoxRequestPdfFromMutation, fetchAllPages, } from '../fortnox-client.js';
|
|
2
2
|
import { documentSegment } from '../identifiers.js';
|
|
3
3
|
export async function listInvoices(params = {}) {
|
|
4
4
|
const queryParams = {
|
|
@@ -55,10 +55,61 @@ export async function sendInvoice(documentNumber, method = 'email', emailOptions
|
|
|
55
55
|
body: { Invoice: { EmailInformation: emailInfo } },
|
|
56
56
|
});
|
|
57
57
|
}
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
if (method === 'print') {
|
|
59
|
+
return (await markInvoicePrinted(documentNumber)).invoice;
|
|
60
|
+
}
|
|
61
|
+
// Exhaustive on purpose: no silent fallback. 'email' and 'einvoice' both send
|
|
62
|
+
// the invoice to the customer, so an unrecognised method must fail loudly
|
|
63
|
+
// rather than pick one of them.
|
|
64
|
+
if (method !== 'email' && method !== 'einvoice') {
|
|
65
|
+
throw new Error(`Unsupported send method: ${String(method)}`);
|
|
66
|
+
}
|
|
67
|
+
const data = await fortnoxRequest(`invoices/${documentId}/${method}`);
|
|
60
68
|
return data?.Invoice || {};
|
|
61
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Fetch an invoice as a PDF. Always uses /preview, which returns the same
|
|
72
|
+
* document as /print but leaves the invoice untouched.
|
|
73
|
+
*
|
|
74
|
+
* Marking the invoice as sent is deliberately NOT folded in here: callers that
|
|
75
|
+
* want both run this first, write the bytes out, and only then call
|
|
76
|
+
* `markInvoicePrinted`. Doing it the other way round means a full disk or a bad
|
|
77
|
+
* path leaves an invoice flagged as sent with no PDF to show for it.
|
|
78
|
+
*/
|
|
79
|
+
export async function getInvoicePdf(documentNumber) {
|
|
80
|
+
return fortnoxRequestPdf(`invoices/${documentSegment(documentNumber)}/preview`);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Mark an invoice as sent via Fortnox's /print action, and report its resulting
|
|
84
|
+
* state. /print is a GET that changes data, so it is flagged as a mutation to
|
|
85
|
+
* keep it out of the automatic retry path.
|
|
86
|
+
*
|
|
87
|
+
* Once the /print request succeeds the invoice has been changed, so from that
|
|
88
|
+
* point on this function does not throw: neither a malformed PDF body nor a
|
|
89
|
+
* failed read-back may turn a completed accounting change into a reported
|
|
90
|
+
* failure.
|
|
91
|
+
*/
|
|
92
|
+
export async function markInvoicePrinted(documentNumber) {
|
|
93
|
+
const documentId = documentSegment(documentNumber);
|
|
94
|
+
const pdf = await fortnoxRequestPdfFromMutation(`invoices/${documentId}/print`);
|
|
95
|
+
try {
|
|
96
|
+
return { invoice: await getInvoice(documentNumber), confirmed: true, pdf };
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
// Fortnox accepted the print request, so the change has most likely been
|
|
100
|
+
// applied — but "most likely" is not "confirmed". Deliberately no
|
|
101
|
+
// `Sent: true` here: synthesizing it would present an unverified outcome as
|
|
102
|
+
// established fact about someone's accounting records.
|
|
103
|
+
return {
|
|
104
|
+
invoice: {
|
|
105
|
+
DocumentNumber: documentNumber,
|
|
106
|
+
Note: `Fortnox accepted the print request, but reading the invoice back failed, so its sent status could not be confirmed: ${err instanceof Error ? err.message : String(err)}`,
|
|
107
|
+
},
|
|
108
|
+
confirmed: false,
|
|
109
|
+
pdf,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
62
113
|
export async function bookkeepInvoice(documentNumber) {
|
|
63
114
|
const data = await fortnoxRequest(`invoices/${documentSegment(documentNumber)}/bookkeep`, {
|
|
64
115
|
method: 'PUT',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"invoices.js","sourceRoot":"","sources":["../../src/operations/invoices.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"invoices.js","sourceRoot":"","sources":["../../src/operations/invoices.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"invoices.d.ts","sourceRoot":"","sources":["../../src/tools/invoices.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"invoices.d.ts","sourceRoot":"","sources":["../../src/tools/invoices.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAkGpE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAgU5D"}
|
package/dist/tools/invoices.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import {
|
|
2
|
+
import { closeSync, constants as fsConstants, lstatSync, mkdtempSync, openSync, writeSync, } from 'node:fs';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import { join, resolve } from 'node:path';
|
|
5
|
+
import { listInvoices, getInvoice, createInvoice, updateInvoice, sendInvoice, getInvoicePdf, markInvoicePrinted, bookkeepInvoice, creditInvoice, } from '../operations/invoices.js';
|
|
3
6
|
import { invoiceListColumns, invoiceDetailColumns, invoiceConfirmColumns } from '../views.js';
|
|
4
7
|
import { confirmationResponse, detailResponse, dryRunResponse, listResponse, requireConfirmation, } from '../tool-output.js';
|
|
5
8
|
const InvoiceRowSchema = z.object({
|
|
@@ -13,6 +16,52 @@ const InvoiceRowSchema = z.object({
|
|
|
13
16
|
Discount: z.number().optional().describe('Rabatt i procent'),
|
|
14
17
|
});
|
|
15
18
|
const DocumentNumberSchema = z.string().regex(/^\d+$/, 'Document number must be numeric');
|
|
19
|
+
/**
|
|
20
|
+
* Write a PDF to `target`, refusing to write through a symlink.
|
|
21
|
+
*
|
|
22
|
+
* These paths come from tool arguments, i.e. they are model-generated and can be
|
|
23
|
+
* influenced by whatever the model just read. `O_EXCL` already refuses to follow
|
|
24
|
+
* a symlink; `O_NOFOLLOW` gives the overwrite path the same guarantee, so
|
|
25
|
+
* "replace this file" can never silently truncate a symlink's target instead.
|
|
26
|
+
* O_NOFOLLOW is POSIX-only, so Windows falls back to an explicit lstat check.
|
|
27
|
+
*/
|
|
28
|
+
function writePdf(target, pdf, overwrite) {
|
|
29
|
+
const { O_WRONLY, O_CREAT, O_TRUNC, O_EXCL, O_NOFOLLOW } = fsConstants;
|
|
30
|
+
const flags = overwrite
|
|
31
|
+
? O_WRONLY | O_CREAT | O_TRUNC | (O_NOFOLLOW ?? 0)
|
|
32
|
+
: O_WRONLY | O_CREAT | O_EXCL;
|
|
33
|
+
// Windows has no O_NOFOLLOW, so the flag above degrades to a no-op there.
|
|
34
|
+
// Check explicitly instead. This is a TOCTOU-racy fallback rather than an
|
|
35
|
+
// atomic guarantee, but it closes the ordinary case on the one platform the
|
|
36
|
+
// kernel flag cannot cover.
|
|
37
|
+
if (overwrite && !O_NOFOLLOW && lstatSync(target, { throwIfNoEntry: false })?.isSymbolicLink()) {
|
|
38
|
+
throw new Error(`${target} is a symbolic link. Refusing to write through it — pass the real path instead.`);
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
const fd = openSync(target, flags, 0o600);
|
|
42
|
+
try {
|
|
43
|
+
// writeSync may return a short count; keep going until the whole buffer
|
|
44
|
+
// has landed. writeFileSync used to do this loop internally.
|
|
45
|
+
let written = 0;
|
|
46
|
+
while (written < pdf.length) {
|
|
47
|
+
written += writeSync(fd, pdf, written, pdf.length - written);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
closeSync(fd);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
const code = err.code;
|
|
56
|
+
if (code === 'EEXIST') {
|
|
57
|
+
throw new Error(`${target} already exists. Pass a different outputPath, or overwrite: true to replace it.`);
|
|
58
|
+
}
|
|
59
|
+
if (code === 'ELOOP') {
|
|
60
|
+
throw new Error(`${target} is a symbolic link. Refusing to write through it — pass the real path instead.`);
|
|
61
|
+
}
|
|
62
|
+
throw err;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
16
65
|
export function registerInvoiceTools(server) {
|
|
17
66
|
server.tool('fortnox_list_invoices', 'Lista/filtrera fakturor i Fortnox. Returnerar: DocumentNumber, CustomerName, InvoiceDate, DueDate, Total, Balance.', {
|
|
18
67
|
filter: z
|
|
@@ -128,6 +177,92 @@ export function registerInvoiceTools(server) {
|
|
|
128
177
|
const invoice = await sendInvoice(documentNumber, sendMethod, emailOptions);
|
|
129
178
|
return confirmationResponse(`Faktura ${documentNumber} skickad via ${sendMethod}.`, invoice, invoiceConfirmColumns, includeRaw);
|
|
130
179
|
});
|
|
180
|
+
server.tool('fortnox_invoice_pdf', 'Hämta en faktura som PDF och spara den på disk. Returnerar sökvägen till filen (inte PDF-innehållet). PDF:en hämtas alltid via Fortnox /preview, vilket INTE ändrar fakturan. Med markSent anropas /print efteråt, efter att filen skrivits.', {
|
|
181
|
+
documentNumber: DocumentNumberSchema.describe('Fakturanummer'),
|
|
182
|
+
outputPath: z
|
|
183
|
+
.string()
|
|
184
|
+
.optional()
|
|
185
|
+
.describe('Sökväg att spara PDF:en till. Skriver inte över en befintlig fil om inte overwrite är satt. Utelämnas: en ny privat temp-katalog används.'),
|
|
186
|
+
overwrite: z
|
|
187
|
+
.boolean()
|
|
188
|
+
.optional()
|
|
189
|
+
.describe('Tillåt att en befintlig fil på outputPath skrivs över'),
|
|
190
|
+
markSent: z
|
|
191
|
+
.boolean()
|
|
192
|
+
.optional()
|
|
193
|
+
.describe('Markera även fakturan som skickad i Fortnox (använder /print)'),
|
|
194
|
+
confirm: z
|
|
195
|
+
.boolean()
|
|
196
|
+
.optional()
|
|
197
|
+
.describe('Bekräfta — krävs endast när markSent är satt, eftersom den ändrar fakturan'),
|
|
198
|
+
dryRun: z.boolean().optional().describe('Visa åtgärden utan att hämta PDF:en'),
|
|
199
|
+
}, async ({ documentNumber, outputPath, overwrite, markSent, confirm, dryRun }) => {
|
|
200
|
+
const action = markSent
|
|
201
|
+
? `download invoice ${documentNumber} as PDF and mark it as sent`
|
|
202
|
+
: `download invoice ${documentNumber} as PDF`;
|
|
203
|
+
if (dryRun)
|
|
204
|
+
return dryRunResponse(action);
|
|
205
|
+
// Only the /print variant changes the invoice; a plain download is read-only.
|
|
206
|
+
if (markSent && !confirm)
|
|
207
|
+
requireConfirmation(action);
|
|
208
|
+
// Arguments here are agent-generated, so a stray path must not silently
|
|
209
|
+
// truncate an existing file. Without an explicit path we use a fresh
|
|
210
|
+
// private directory rather than a predictable, clobber-prone temp name.
|
|
211
|
+
const target = outputPath
|
|
212
|
+
? resolve(outputPath)
|
|
213
|
+
: join(mkdtempSync(join(tmpdir(), 'noxctl-')), `invoice-${documentNumber}.pdf`);
|
|
214
|
+
const pdf = await getInvoicePdf(documentNumber);
|
|
215
|
+
writePdf(target, pdf, overwrite);
|
|
216
|
+
// Only now that the PDF is safely on disk do we change anything in Fortnox.
|
|
217
|
+
// If that fails, the download still succeeded — say so, or the caller has
|
|
218
|
+
// no idea a usable file is sitting there.
|
|
219
|
+
let printed;
|
|
220
|
+
if (markSent) {
|
|
221
|
+
try {
|
|
222
|
+
printed = await markInvoicePrinted(documentNumber);
|
|
223
|
+
}
|
|
224
|
+
catch (err) {
|
|
225
|
+
throw new Error(`Faktura ${documentNumber} sparades som PDF: ${target} (${pdf.length} bytes), men kunde inte markeras som skickad: ${err instanceof Error ? err.message : String(err)}`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
// Prefer the document /print actually produced, so the saved copy matches
|
|
229
|
+
// the version that was marked as sent. Best-effort: the /preview copy is
|
|
230
|
+
// already on disk, and the invoice is already flagged, so a failure here
|
|
231
|
+
// must not be raised as if the whole operation failed.
|
|
232
|
+
let bytes = pdf.length;
|
|
233
|
+
let refreshNote = '';
|
|
234
|
+
if (printed?.pdf) {
|
|
235
|
+
try {
|
|
236
|
+
writePdf(target, printed.pdf, true);
|
|
237
|
+
bytes = printed.pdf.length;
|
|
238
|
+
}
|
|
239
|
+
catch (err) {
|
|
240
|
+
refreshNote = ` Den sparade filen är /preview-versionen; kunde inte skriva om den med den utskrivna versionen: ${err instanceof Error ? err.message : String(err)}`;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
// Only state that the invoice is sent if Fortnox confirmed it. Asking for
|
|
244
|
+
// markSent is not evidence that it took effect.
|
|
245
|
+
let sentNote = '';
|
|
246
|
+
if (printed && !printed.confirmed) {
|
|
247
|
+
sentNote = ` ${String(printed.invoice.Note)}`;
|
|
248
|
+
}
|
|
249
|
+
else if (printed && printed.invoice.Sent === true) {
|
|
250
|
+
sentNote = ' Fakturan är nu markerad som skickad.';
|
|
251
|
+
}
|
|
252
|
+
else if (printed) {
|
|
253
|
+
sentNote = ' Varning: Fortnox rapporterar fortfarande fakturan som ej skickad.';
|
|
254
|
+
}
|
|
255
|
+
return confirmationResponse(`Faktura ${documentNumber} sparad som PDF: ${target} (${bytes} bytes).` +
|
|
256
|
+
sentNote +
|
|
257
|
+
refreshNote, {
|
|
258
|
+
DocumentNumber: documentNumber,
|
|
259
|
+
Path: target,
|
|
260
|
+
Bytes: bytes,
|
|
261
|
+
// Report what Fortnox says, not what we asked for; undefined means
|
|
262
|
+
// "not checked" or "could not be confirmed".
|
|
263
|
+
Sent: printed?.confirmed ? printed.invoice.Sent : undefined,
|
|
264
|
+
});
|
|
265
|
+
});
|
|
131
266
|
server.tool('fortnox_bookkeep_invoice', 'Bokför en faktura i Fortnox', {
|
|
132
267
|
documentNumber: DocumentNumberSchema.describe('Fakturanummer att bokföra'),
|
|
133
268
|
confirm: z.boolean().optional().describe('Bekräfta att fakturan ska bokföras'),
|