@voyant-travel/plugin-smartbill 0.119.2

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.
Files changed (96) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +324 -0
  3. package/dist/artifacts.d.ts +80 -0
  4. package/dist/artifacts.d.ts.map +1 -0
  5. package/dist/artifacts.js +295 -0
  6. package/dist/client/errors.d.ts +28 -0
  7. package/dist/client/errors.d.ts.map +1 -0
  8. package/dist/client/errors.js +32 -0
  9. package/dist/client/fetch.d.ts +4 -0
  10. package/dist/client/fetch.d.ts.map +1 -0
  11. package/dist/client/fetch.js +32 -0
  12. package/dist/client/rate-limit.d.ts +8 -0
  13. package/dist/client/rate-limit.d.ts.map +1 -0
  14. package/dist/client/rate-limit.js +54 -0
  15. package/dist/client/resilience.d.ts +36 -0
  16. package/dist/client/resilience.d.ts.map +1 -0
  17. package/dist/client/resilience.js +23 -0
  18. package/dist/client.d.ts +67 -0
  19. package/dist/client.d.ts.map +1 -0
  20. package/dist/client.js +234 -0
  21. package/dist/hono.d.ts +199 -0
  22. package/dist/hono.d.ts.map +1 -0
  23. package/dist/hono.js +77 -0
  24. package/dist/index.d.ts +22 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +10 -0
  27. package/dist/invoice-ui-data.d.ts +46 -0
  28. package/dist/invoice-ui-data.d.ts.map +1 -0
  29. package/dist/invoice-ui-data.js +62 -0
  30. package/dist/invoice-ui.d.ts +438 -0
  31. package/dist/invoice-ui.d.ts.map +1 -0
  32. package/dist/invoice-ui.js +97 -0
  33. package/dist/mapping.d.ts +50 -0
  34. package/dist/mapping.d.ts.map +1 -0
  35. package/dist/mapping.js +219 -0
  36. package/dist/mock/node.d.ts +4 -0
  37. package/dist/mock/node.d.ts.map +1 -0
  38. package/dist/mock/node.js +14 -0
  39. package/dist/mock/pdf.d.ts +7 -0
  40. package/dist/mock/pdf.d.ts.map +1 -0
  41. package/dist/mock/pdf.js +44 -0
  42. package/dist/mock/types.d.ts +94 -0
  43. package/dist/mock/types.d.ts.map +1 -0
  44. package/dist/mock/types.js +1 -0
  45. package/dist/mock.d.ts +4 -0
  46. package/dist/mock.d.ts.map +1 -0
  47. package/dist/mock.js +431 -0
  48. package/dist/plugin.d.ts +55 -0
  49. package/dist/plugin.d.ts.map +1 -0
  50. package/dist/plugin.js +192 -0
  51. package/dist/runtime.d.ts +25 -0
  52. package/dist/runtime.d.ts.map +1 -0
  53. package/dist/runtime.js +42 -0
  54. package/dist/settlement.d.ts +33 -0
  55. package/dist/settlement.d.ts.map +1 -0
  56. package/dist/settlement.js +65 -0
  57. package/dist/sync/events.d.ts +5 -0
  58. package/dist/sync/events.d.ts.map +1 -0
  59. package/dist/sync/events.js +96 -0
  60. package/dist/sync/helpers.d.ts +66 -0
  61. package/dist/sync/helpers.d.ts.map +1 -0
  62. package/dist/sync/helpers.js +353 -0
  63. package/dist/sync/invoice.d.ts +3 -0
  64. package/dist/sync/invoice.d.ts.map +1 -0
  65. package/dist/sync/invoice.js +25 -0
  66. package/dist/sync/types.d.ts +71 -0
  67. package/dist/sync/types.d.ts.map +1 -0
  68. package/dist/sync/types.js +1 -0
  69. package/dist/sync.d.ts +4 -0
  70. package/dist/sync.d.ts.map +1 -0
  71. package/dist/sync.js +2 -0
  72. package/dist/types.d.ts +189 -0
  73. package/dist/types.d.ts.map +1 -0
  74. package/dist/types.js +1 -0
  75. package/dist/validation.d.ts +39 -0
  76. package/dist/validation.d.ts.map +1 -0
  77. package/dist/validation.js +120 -0
  78. package/dist/workflow-candidates.d.ts +36 -0
  79. package/dist/workflow-candidates.d.ts.map +1 -0
  80. package/dist/workflow-candidates.js +182 -0
  81. package/dist/workflow-remote-discovery.d.ts +6 -0
  82. package/dist/workflow-remote-discovery.d.ts.map +1 -0
  83. package/dist/workflow-remote-discovery.js +83 -0
  84. package/dist/workflows/refs.d.ts +13 -0
  85. package/dist/workflows/refs.d.ts.map +1 -0
  86. package/dist/workflows/refs.js +51 -0
  87. package/dist/workflows/spaced-client.d.ts +5 -0
  88. package/dist/workflows/spaced-client.d.ts.map +1 -0
  89. package/dist/workflows/spaced-client.js +44 -0
  90. package/dist/workflows/types.d.ts +142 -0
  91. package/dist/workflows/types.d.ts.map +1 -0
  92. package/dist/workflows/types.js +1 -0
  93. package/dist/workflows.d.ts +5 -0
  94. package/dist/workflows.d.ts.map +1 -0
  95. package/dist/workflows.js +229 -0
  96. package/package.json +129 -0
package/dist/client.js ADDED
@@ -0,0 +1,234 @@
1
+ import { createCircuitBreaker, resilientFetch } from "@voyant-travel/utils/resilience";
2
+ import { SmartbillApiError, SmartbillRateLimitCircuitOpenError, SmartbillRateLimitError, } from "./client/errors.js";
3
+ import { asResilientFetch, createGlobalSmartbillFetch } from "./client/fetch.js";
4
+ import { parseSmartbillRateLimit } from "./client/rate-limit.js";
5
+ import { surfacingRetry } from "./client/resilience.js";
6
+ export { SmartbillApiError, SmartbillRateLimitCircuitOpenError, SmartbillRateLimitError, } from "./client/errors.js";
7
+ function isRecord(value) {
8
+ return typeof value === "object" && value !== null;
9
+ }
10
+ export function createSmartbillClient(options) {
11
+ const apiUrl = (options.apiUrl ?? "https://ws.smartbill.ro/SBORO/api").replace(/\/$/, "");
12
+ const fetchImpl = options.fetch ?? createGlobalSmartbillFetch();
13
+ const now = options.rateLimit?.now ?? (() => new Date());
14
+ let rateLimitCircuitOpenUntil;
15
+ const resilience = options.resilience ?? {};
16
+ // One breaker per upstream SmartBill account — the client is a per-worker
17
+ // singleton, so a per-instance breaker has the right scope.
18
+ const breaker = resilience.breaker ?? createCircuitBreaker();
19
+ const timeoutMs = resilience.timeoutMs ?? 10_000;
20
+ const retryTuning = resilience.retry === false ? undefined : resilience.retry;
21
+ function maxAttemptsFor(retryable) {
22
+ return retryable && resilience.retry !== false ? (retryTuning?.attempts ?? 3) : 1;
23
+ }
24
+ function authHeader() {
25
+ return `Basic ${btoa(`${options.username}:${options.apiToken}`)}`;
26
+ }
27
+ function headers() {
28
+ return {
29
+ Authorization: authHeader(),
30
+ "Content-Type": "application/json",
31
+ Accept: "application/json",
32
+ };
33
+ }
34
+ async function request(operation, method, path, body, requestOptions) {
35
+ if (!fetchImpl) {
36
+ throw new Error("SmartBill client requires a fetch implementation");
37
+ }
38
+ assertRateLimitCircuitClosed(operation);
39
+ const init = {
40
+ method,
41
+ headers: headers(),
42
+ };
43
+ if (body !== undefined)
44
+ init.body = JSON.stringify(body);
45
+ // Default policy: GET/PUT/DELETE are idempotent against SmartBill (state
46
+ // setters, lookups), POSTs create documents and must not retry. Call
47
+ // sites override where the HTTP method is misleading (e.g. reverse).
48
+ const retryable = requestOptions?.retryable ?? method !== "POST";
49
+ const response = await resilientFetch(`${apiUrl}${path}`, init, {
50
+ timeoutMs,
51
+ breaker,
52
+ // Per-operation policy above already gates retries via attempts.
53
+ retryNonIdempotent: true,
54
+ retry: surfacingRetry(maxAttemptsFor(retryable), retryTuning),
55
+ fetchImpl: asResilientFetch(fetchImpl),
56
+ });
57
+ let text = "";
58
+ let parsed = null;
59
+ try {
60
+ text = await response.text();
61
+ parsed = text ? JSON.parse(text) : null;
62
+ }
63
+ catch {
64
+ // leave parsed as null, surface text
65
+ }
66
+ if (!response.ok) {
67
+ throw buildApiError(operation, response.status, text, parsed);
68
+ }
69
+ const envelope = (parsed ?? {});
70
+ if (envelope.status === "Error" || envelope.errorText) {
71
+ throw buildApiError(operation, response.status, text, parsed);
72
+ }
73
+ return envelope;
74
+ }
75
+ async function fetchPdf(operation, path) {
76
+ if (!fetchImpl) {
77
+ throw new Error("SmartBill client requires a fetch implementation");
78
+ }
79
+ assertRateLimitCircuitClosed(operation);
80
+ const response = await resilientFetch(`${apiUrl}${path}`, {
81
+ method: "GET",
82
+ headers: { ...headers(), Accept: "application/octet-stream" },
83
+ }, {
84
+ timeoutMs,
85
+ breaker,
86
+ // PDF downloads are pure reads — always safe to retry.
87
+ retry: surfacingRetry(maxAttemptsFor(true), retryTuning),
88
+ fetchImpl: asResilientFetch(fetchImpl),
89
+ });
90
+ if (!response.ok) {
91
+ const text = await response.text().catch(() => "");
92
+ throw buildApiError(operation, response.status, text, parseJson(text));
93
+ }
94
+ const buffer = await response.arrayBuffer();
95
+ const contentType = response.headers?.get("content-type") ?? "application/pdf";
96
+ return { bytes: new Uint8Array(buffer), contentType };
97
+ }
98
+ function pdfQuery(companyVatCode, seriesName, number) {
99
+ return `cif=${encodeURIComponent(companyVatCode)}&seriesname=${encodeURIComponent(seriesName)}&number=${encodeURIComponent(number)}`;
100
+ }
101
+ function assertRateLimitCircuitClosed(operation) {
102
+ if (!options.rateLimit?.circuitBreaker || !rateLimitCircuitOpenUntil)
103
+ return;
104
+ const currentTime = now();
105
+ if (currentTime.getTime() >= rateLimitCircuitOpenUntil.getTime()) {
106
+ rateLimitCircuitOpenUntil = undefined;
107
+ return;
108
+ }
109
+ throw new SmartbillRateLimitCircuitOpenError({
110
+ operation,
111
+ retryAfterAt: rateLimitCircuitOpenUntil,
112
+ retryAfterMs: rateLimitCircuitOpenUntil.getTime() - currentTime.getTime(),
113
+ });
114
+ }
115
+ function buildApiError(operation, status, text, parsed) {
116
+ const rateLimit = parseSmartbillRateLimit(status, parsed, now());
117
+ if (rateLimit) {
118
+ if (options.rateLimit?.circuitBreaker && rateLimit.retryAfterAt) {
119
+ rateLimitCircuitOpenUntil = rateLimit.retryAfterAt;
120
+ }
121
+ return new SmartbillRateLimitError(`SmartBill ${operation} rate-limited: ${rateLimit.errorText}`, {
122
+ operation,
123
+ status,
124
+ body: text,
125
+ response: parsed,
126
+ retryAfterMs: rateLimit.retryAfterMs,
127
+ retryAfterAt: rateLimit.retryAfterAt,
128
+ blockedAt: rateLimit.blockedAt,
129
+ });
130
+ }
131
+ const envelope = isRecord(parsed) ? parsed : null;
132
+ const message = envelope?.errorText || envelope?.message
133
+ ? `SmartBill ${operation} failed: ${envelope.errorText ?? envelope.message ?? "Error"}`
134
+ : `SmartBill ${operation} failed (${status}): ${text}`;
135
+ return new SmartbillApiError(message, {
136
+ operation,
137
+ status,
138
+ body: text,
139
+ response: parsed,
140
+ });
141
+ }
142
+ function parseJson(text) {
143
+ try {
144
+ return text ? JSON.parse(text) : null;
145
+ }
146
+ catch {
147
+ return null;
148
+ }
149
+ }
150
+ async function createInvoice(body) {
151
+ // No retry: POST creates an invoice and SmartBill has no idempotency
152
+ // keys — a duplicate invoice is worse than a failed sync (the outbox
153
+ // redelivers, and external-ref dedup skips already-created invoices).
154
+ return request("createInvoice", "POST", "/invoice", body);
155
+ }
156
+ async function createProforma(body) {
157
+ // No retry: creates a proforma document (same reasoning as createInvoice).
158
+ return request("createProforma", "POST", "/estimate", body);
159
+ }
160
+ async function convertEstimateToInvoice(companyVatCode, estimateSeriesName, estimateNumber, body) {
161
+ // No retry: POST creates the converted invoice (no idempotency keys).
162
+ return request("convertEstimateToInvoice", "POST", "/invoice", {
163
+ ...body,
164
+ companyVatCode,
165
+ useEstimateDetails: true,
166
+ estimate: {
167
+ seriesName: estimateSeriesName,
168
+ number: estimateNumber,
169
+ },
170
+ useStock: body.useStock ?? false,
171
+ });
172
+ }
173
+ async function cancelInvoice(companyVatCode, seriesName, number) {
174
+ // Retried: cancel is an idempotent state-setter (cancelling twice is a no-op).
175
+ return request("cancelInvoice", "PUT", "/invoice/cancel", {
176
+ companyVatCode,
177
+ seriesName,
178
+ number,
179
+ });
180
+ }
181
+ async function restoreInvoice(companyVatCode, seriesName, number) {
182
+ return request("restoreInvoice", "PUT", "/invoice/restore", {
183
+ companyVatCode,
184
+ seriesName,
185
+ number,
186
+ });
187
+ }
188
+ async function deleteInvoice(companyVatCode, seriesName, number) {
189
+ return request("deleteInvoice", "DELETE", `/invoice?${pdfQuery(companyVatCode, seriesName, number)}`);
190
+ }
191
+ async function reverseInvoice(companyVatCode, seriesName, number) {
192
+ // No retry despite the PUT: reversing issues a NEW credit-note style
193
+ // reversal invoice, so a retried ambiguous failure could double-reverse.
194
+ return request("reverseInvoice", "PUT", "/invoice/reverse", {
195
+ companyVatCode,
196
+ seriesName,
197
+ number,
198
+ }, { retryable: false });
199
+ }
200
+ async function viewInvoicePdf(companyVatCode, seriesName, number) {
201
+ return fetchPdf("viewInvoicePdf", `/invoice/pdf?${pdfQuery(companyVatCode, seriesName, number)}`);
202
+ }
203
+ async function viewEstimatePdf(companyVatCode, seriesName, number) {
204
+ return fetchPdf("viewEstimatePdf", `/estimate/pdf?${pdfQuery(companyVatCode, seriesName, number)}`);
205
+ }
206
+ async function getPaymentStatus(companyVatCode, seriesName, number) {
207
+ return request("getPaymentStatus", "GET", `/invoice/paymentstatus?${pdfQuery(companyVatCode, seriesName, number)}`);
208
+ }
209
+ async function listTaxes() {
210
+ return request("listTaxes", "GET", "/tax");
211
+ }
212
+ async function listSeries() {
213
+ return request("listSeries", "GET", "/series");
214
+ }
215
+ async function listEstimateInvoices(companyVatCode, seriesName, number) {
216
+ return request("listEstimateInvoices", "GET", `/estimate/invoices?${pdfQuery(companyVatCode, seriesName, number)}`);
217
+ }
218
+ return {
219
+ createInvoice,
220
+ createProforma,
221
+ convertEstimateToInvoice,
222
+ cancelInvoice,
223
+ restoreInvoice,
224
+ deleteInvoice,
225
+ reverseInvoice,
226
+ viewInvoicePdf,
227
+ viewPdf: viewInvoicePdf,
228
+ viewEstimatePdf,
229
+ getPaymentStatus,
230
+ listTaxes,
231
+ listSeries,
232
+ listEstimateInvoices,
233
+ };
234
+ }
package/dist/hono.d.ts ADDED
@@ -0,0 +1,199 @@
1
+ import type { ModuleContainer } from "@voyant-travel/core";
2
+ import type { HonoModule } from "@voyant-travel/hono/module";
3
+ import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
4
+ import type { SmartbillPluginOptions } from "./plugin.js";
5
+ type Env = {
6
+ Bindings: Record<string, unknown>;
7
+ Variables: {
8
+ container?: ModuleContainer;
9
+ db: PostgresJsDatabase;
10
+ userId?: string;
11
+ };
12
+ };
13
+ export interface SmartbillAdminModuleOptions {
14
+ pluginOptions: SmartbillPluginOptions | SmartbillPluginOptionsResolver;
15
+ }
16
+ export type SmartbillPluginOptionsResolver = (bindings: Record<string, unknown>) => SmartbillPluginOptions;
17
+ export interface SmartbillAdminRouteRuntime {
18
+ pluginOptions: SmartbillPluginOptions;
19
+ }
20
+ export declare const SMARTBILL_ADMIN_RUNTIME_CONTAINER_KEY = "providers.smartbill.adminRuntime";
21
+ export declare function createSmartbillAdminRoutes(options: SmartbillAdminModuleOptions): import("hono/hono-base").HonoBase<Env, {
22
+ "/invoices/:id/sync": {
23
+ $post: {
24
+ input: {
25
+ param: {
26
+ id: string;
27
+ };
28
+ };
29
+ output: {
30
+ error: string;
31
+ };
32
+ outputFormat: "json";
33
+ status: 404;
34
+ } | {
35
+ input: {
36
+ param: {
37
+ id: string;
38
+ };
39
+ };
40
+ output: {
41
+ error: string;
42
+ };
43
+ outputFormat: "json";
44
+ status: 409;
45
+ } | {
46
+ input: {
47
+ param: {
48
+ id: string;
49
+ };
50
+ };
51
+ output: {
52
+ data: {
53
+ status: "existing_ref";
54
+ invoiceId: string;
55
+ documentType: import("./artifacts.js").SmartbillDocumentType;
56
+ externalRef: {
57
+ metadata: import("hono/utils/types").JSONValue;
58
+ id: string;
59
+ externalId: string | null;
60
+ externalNumber: string | null;
61
+ externalUrl: string | null;
62
+ invoiceId: string;
63
+ };
64
+ artifact: {
65
+ status: "skipped";
66
+ reason: "missing_db" | "missing_invoice" | "missing_document_storage" | "missing_smartbill_reference";
67
+ } | {
68
+ status: "registered_ref";
69
+ reason?: "missing_number" | undefined;
70
+ } | {
71
+ status: "already_exists";
72
+ attachment: {
73
+ metadata: import("hono/utils/types").JSONValue;
74
+ id: string;
75
+ name: string;
76
+ createdAt: string;
77
+ storageKey: string | null;
78
+ kind: string;
79
+ fileSize: number | null;
80
+ checksum: string | null;
81
+ mimeType: string | null;
82
+ invoiceId: string;
83
+ } | null;
84
+ } | {
85
+ status: "persisted";
86
+ rendition: {
87
+ metadata: import("hono/utils/types").JSONValue;
88
+ format: "json" | "html" | "pdf" | "xml";
89
+ id: string;
90
+ status: "failed" | "pending" | "ready" | "stale";
91
+ createdAt: string;
92
+ updatedAt: string;
93
+ storageKey: string | null;
94
+ errorMessage: string | null;
95
+ language: string | null;
96
+ templateId: string | null;
97
+ fileSize: number | null;
98
+ checksum: string | null;
99
+ generatedAt: string | null;
100
+ invoiceId: string;
101
+ } | null;
102
+ attachment: {
103
+ metadata: import("hono/utils/types").JSONValue;
104
+ id: string;
105
+ name: string;
106
+ createdAt: string;
107
+ storageKey: string | null;
108
+ kind: string;
109
+ fileSize: number | null;
110
+ checksum: string | null;
111
+ mimeType: string | null;
112
+ invoiceId: string;
113
+ } | null;
114
+ } | null;
115
+ } | {
116
+ status: "created";
117
+ invoiceId: string;
118
+ documentType: import("./artifacts.js").SmartbillDocumentType;
119
+ result: {
120
+ number?: string | undefined;
121
+ series?: string | undefined;
122
+ url?: string | undefined;
123
+ status?: string | undefined;
124
+ message?: string | undefined;
125
+ errorText?: string | undefined;
126
+ };
127
+ artifact: {
128
+ status: "skipped";
129
+ reason: "missing_db" | "missing_invoice" | "missing_document_storage" | "missing_smartbill_reference";
130
+ } | {
131
+ status: "registered_ref";
132
+ reason?: "missing_number" | undefined;
133
+ } | {
134
+ status: "already_exists";
135
+ attachment: {
136
+ metadata: import("hono/utils/types").JSONValue;
137
+ id: string;
138
+ name: string;
139
+ createdAt: string;
140
+ storageKey: string | null;
141
+ kind: string;
142
+ fileSize: number | null;
143
+ checksum: string | null;
144
+ mimeType: string | null;
145
+ invoiceId: string;
146
+ } | null;
147
+ } | {
148
+ status: "persisted";
149
+ rendition: {
150
+ metadata: import("hono/utils/types").JSONValue;
151
+ format: "json" | "html" | "pdf" | "xml";
152
+ id: string;
153
+ status: "failed" | "pending" | "ready" | "stale";
154
+ createdAt: string;
155
+ updatedAt: string;
156
+ storageKey: string | null;
157
+ errorMessage: string | null;
158
+ language: string | null;
159
+ templateId: string | null;
160
+ fileSize: number | null;
161
+ checksum: string | null;
162
+ generatedAt: string | null;
163
+ invoiceId: string;
164
+ } | null;
165
+ attachment: {
166
+ metadata: import("hono/utils/types").JSONValue;
167
+ id: string;
168
+ name: string;
169
+ createdAt: string;
170
+ storageKey: string | null;
171
+ kind: string;
172
+ fileSize: number | null;
173
+ checksum: string | null;
174
+ mimeType: string | null;
175
+ invoiceId: string;
176
+ } | null;
177
+ } | null;
178
+ };
179
+ };
180
+ outputFormat: "json";
181
+ status: 200 | 201;
182
+ } | {
183
+ input: {
184
+ param: {
185
+ id: string;
186
+ };
187
+ };
188
+ output: {
189
+ error: string;
190
+ };
191
+ outputFormat: "json";
192
+ status: 502;
193
+ };
194
+ };
195
+ }, "/", "/invoices/:id/sync">;
196
+ export declare function createSmartbillAdminModule(options: SmartbillAdminModuleOptions): HonoModule;
197
+ export declare function buildSmartbillAdminRouteRuntime(bindings: Record<string, unknown>, options: SmartbillAdminModuleOptions): SmartbillAdminRouteRuntime;
198
+ export {};
199
+ //# sourceMappingURL=hono.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hono.d.ts","sourceRoot":"","sources":["../src/hono.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAU,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAKlE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AAC5D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAGjE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AAGzD,KAAK,GAAG,GAAG;IACT,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACjC,SAAS,EAAE;QACT,SAAS,CAAC,EAAE,eAAe,CAAA;QAC3B,EAAE,EAAE,kBAAkB,CAAA;QACtB,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,CAAA;CACF,CAAA;AAED,MAAM,WAAW,2BAA2B;IAC1C,aAAa,EAAE,sBAAsB,GAAG,8BAA8B,CAAA;CACvE;AAED,MAAM,MAAM,8BAA8B,GAAG,CAC3C,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC9B,sBAAsB,CAAA;AAE3B,MAAM,WAAW,0BAA0B;IACzC,aAAa,EAAE,sBAAsB,CAAA;CACtC;AAED,eAAO,MAAM,qCAAqC,qCAAqC,CAAA;AAEvF,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8BAyB9E;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,2BAA2B,GAAG,UAAU,CAe3F;AAED,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,OAAO,EAAE,2BAA2B,GACnC,0BAA0B,CAO5B"}
package/dist/hono.js ADDED
@@ -0,0 +1,77 @@
1
+ import { FINANCE_ROUTE_RUNTIME_CONTAINER_KEY, } from "@voyant-travel/finance";
2
+ import { Hono } from "hono";
3
+ import { syncSmartbillInvoice } from "./sync.js";
4
+ export const SMARTBILL_ADMIN_RUNTIME_CONTAINER_KEY = "providers.smartbill.adminRuntime";
5
+ export function createSmartbillAdminRoutes(options) {
6
+ return new Hono().post("/invoices/:id/sync", async (c) => {
7
+ try {
8
+ const runtime = resolveSmartbillAdminRouteRuntime(c, options);
9
+ const financeRuntime = resolveFinanceRouteRuntime(c.var.container);
10
+ const result = await syncSmartbillInvoice({
11
+ db: c.get("db"),
12
+ invoiceId: c.req.param("id"),
13
+ pluginOptions: runtime.pluginOptions,
14
+ issueRuntime: financeRuntime,
15
+ });
16
+ if (result.status === "not_found") {
17
+ return c.json({ error: "Invoice not found" }, 404);
18
+ }
19
+ if (result.status === "unsupported_document_type") {
20
+ return c.json({ error: `SmartBill sync does not support ${result.invoiceType}` }, 409);
21
+ }
22
+ return c.json({ data: result }, result.status === "created" ? 201 : 200);
23
+ }
24
+ catch (error) {
25
+ const message = error instanceof Error ? error.message : "SmartBill sync failed";
26
+ return c.json({ error: message }, 502);
27
+ }
28
+ });
29
+ }
30
+ export function createSmartbillAdminModule(options) {
31
+ const module = {
32
+ name: "smartbill",
33
+ bootstrap: ({ bindings, container }) => {
34
+ container.register(SMARTBILL_ADMIN_RUNTIME_CONTAINER_KEY, buildSmartbillAdminRouteRuntime(bindings, options));
35
+ },
36
+ };
37
+ return {
38
+ module,
39
+ adminRoutes: createSmartbillAdminRoutes(options),
40
+ };
41
+ }
42
+ export function buildSmartbillAdminRouteRuntime(bindings, options) {
43
+ return {
44
+ pluginOptions: typeof options.pluginOptions === "function"
45
+ ? options.pluginOptions(bindings)
46
+ : options.pluginOptions,
47
+ };
48
+ }
49
+ function resolveSmartbillAdminRouteRuntime(c, options) {
50
+ if (c.var.container) {
51
+ try {
52
+ return c.var.container.resolve(SMARTBILL_ADMIN_RUNTIME_CONTAINER_KEY);
53
+ }
54
+ catch {
55
+ // Fall through for tests and minimal apps that mount routes without bootstrap.
56
+ }
57
+ }
58
+ return buildSmartbillAdminRouteRuntime(c.env, options);
59
+ }
60
+ function resolveFinanceRouteRuntime(container) {
61
+ if (!container)
62
+ return undefined;
63
+ try {
64
+ const runtime = container.resolve(FINANCE_ROUTE_RUNTIME_CONTAINER_KEY);
65
+ return {
66
+ invoiceFxSettings: runtime.invoiceFxSettings,
67
+ resolveInvoiceFxSettings: runtime.resolveInvoiceFxSettings,
68
+ updateInvoiceFxSettings: runtime.updateInvoiceFxSettings,
69
+ resolveInvoiceExchangeRate: runtime.resolveInvoiceExchangeRate,
70
+ resolveInvoiceExchangeRateResolver: runtime.resolveInvoiceExchangeRateResolver,
71
+ onInvoiceFxResolutionError: runtime.onInvoiceFxResolutionError,
72
+ };
73
+ }
74
+ catch {
75
+ return undefined;
76
+ }
77
+ }
@@ -0,0 +1,22 @@
1
+ export type { RetrySmartbillInvoiceArtifactInput, SmartbillArtifactPersistenceOptions, SmartbillArtifactPersistenceResult, SmartbillArtifactPersistenceRuntime, SmartbillArtifactStorageContext, SmartbillDbResolver, SmartbillDocumentStorageResolver, SmartbillDocumentType, SmartbillExternalRef, SmartbillStorageKeyPrefixResolver, } from "./artifacts.js";
2
+ export { retrySmartbillInvoiceArtifact } from "./artifacts.js";
3
+ export type { SmartbillApiErrorOptions, SmartbillClientApi, SmartbillClientOptions, } from "./client.js";
4
+ export { createSmartbillClient, SmartbillApiError, SmartbillRateLimitCircuitOpenError, SmartbillRateLimitError, } from "./client.js";
5
+ export type { SmartbillAdminModuleOptions, SmartbillAdminRouteRuntime, SmartbillPluginOptionsResolver, } from "./hono.js";
6
+ export { buildSmartbillAdminRouteRuntime, createSmartbillAdminModule, createSmartbillAdminRoutes, SMARTBILL_ADMIN_RUNTIME_CONTAINER_KEY, } from "./hono.js";
7
+ export type { SmartbillEventValue, SmartbillMappingOptions, SmartbillMaybePromise, } from "./mapping.js";
8
+ export { mapClient, mapLineItems, mapVoyantInvoiceToSmartbill, mapVoyantInvoiceToSmartbillAsync, } from "./mapping.js";
9
+ export type { SmartbillMockDocument, SmartbillMockDocumentKind, SmartbillMockDocumentStatus, SmartbillMockListenOptions, SmartbillMockRequest, SmartbillMockResponse, SmartbillMockSeries, SmartbillMockServer, SmartbillMockServerHandle, SmartbillMockServerOptions, SmartbillMockTax, } from "./mock.js";
10
+ export { createSmartbillMockServer } from "./mock.js";
11
+ export type { SmartbillErrorHandler, SmartbillIdempotencyOptions, SmartbillInvoiceNumberWriteBackFormatter, SmartbillLogger, SmartbillMapFn, SmartbillPluginOptions, SmartbillSyncEventNames, } from "./plugin.js";
12
+ export { smartbillPlugin } from "./plugin.js";
13
+ export type { ResolvedSmartbillSyncEventNames, SmartbillSyncRuntime } from "./runtime.js";
14
+ export { createSmartbillSyncRuntime } from "./runtime.js";
15
+ export type { SmartbillInvoiceSettlementPoller, SmartbillInvoiceSettlementPollerOptions, SmartbillSettlementExternalRef, SmartbillSettlementInvoice, SmartbillSettlementPollerContext, SmartbillSettlementPollerResult, SmartbillSettlementSeriesContext, } from "./settlement.js";
16
+ export { createSmartbillInvoiceSettlementPoller } from "./settlement.js";
17
+ export type { SyncSmartbillInvoiceEventInput, SyncSmartbillInvoiceEventResult, SyncSmartbillInvoiceInput, SyncSmartbillInvoiceResult, } from "./sync.js";
18
+ export { syncSmartbillInvoice, syncSmartbillInvoiceEvent } from "./sync.js";
19
+ export type { SmartbillClient, SmartbillEnvelope, SmartbillEstimateInvoicesResponse, SmartbillFetch, SmartbillInvoiceBody, SmartbillInvoiceResponse, SmartbillPaymentEntry, SmartbillPdfResponse, SmartbillProduct, SmartbillSeriesResponse, SmartbillStatusResponse, SmartbillTaxesResponse, VoyantInvoiceEvent, } from "./types.js";
20
+ export type { SmartbillCandidateExternalRefRecorder, SmartbillCandidateExternalRefRecorderContext, SmartbillCandidateInvoice, SmartbillDriftFinding, SmartbillDriftFindingType, SmartbillDriftReconciler, SmartbillDriftReconcilerOptions, SmartbillDriftReconcilerResult, SmartbillKnownLocalDriftFinding, SmartbillMissingLocalDriftFinding, SmartbillProformaConversion, SmartbillProformaConversionPoller, SmartbillProformaConversionPollerOptions, SmartbillProformaConversionPollerResult, SmartbillReferenceParts, SmartbillRemoteDocument, SmartbillRemoteDocumentAccessors, SmartbillRemoteDocumentStatus, SmartbillWorkflowCandidateSource, SmartbillWorkflowDocumentType, SmartbillWorkflowError, SmartbillWorkflowExternalRef, SmartbillWorkflowInvoice, SmartbillWorkflowLogger, } from "./workflows.js";
21
+ export { createSmartbillDriftReconciler, createSmartbillProformaConversionPoller, } from "./workflows.js";
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ export { retrySmartbillInvoiceArtifact } from "./artifacts.js";
2
+ export { createSmartbillClient, SmartbillApiError, SmartbillRateLimitCircuitOpenError, SmartbillRateLimitError, } from "./client.js";
3
+ export { buildSmartbillAdminRouteRuntime, createSmartbillAdminModule, createSmartbillAdminRoutes, SMARTBILL_ADMIN_RUNTIME_CONTAINER_KEY, } from "./hono.js";
4
+ export { mapClient, mapLineItems, mapVoyantInvoiceToSmartbill, mapVoyantInvoiceToSmartbillAsync, } from "./mapping.js";
5
+ export { createSmartbillMockServer } from "./mock.js";
6
+ export { smartbillPlugin } from "./plugin.js";
7
+ export { createSmartbillSyncRuntime } from "./runtime.js";
8
+ export { createSmartbillInvoiceSettlementPoller } from "./settlement.js";
9
+ export { syncSmartbillInvoice, syncSmartbillInvoiceEvent } from "./sync.js";
10
+ export { createSmartbillDriftReconciler, createSmartbillProformaConversionPoller, } from "./workflows.js";
@@ -0,0 +1,46 @@
1
+ import { z } from "zod";
2
+ export declare const smartbillInvoiceExternalRefSchema: z.ZodObject<{
3
+ id: z.ZodString;
4
+ invoiceId: z.ZodString;
5
+ provider: z.ZodString;
6
+ externalId: z.ZodNullable<z.ZodString>;
7
+ externalNumber: z.ZodNullable<z.ZodString>;
8
+ externalUrl: z.ZodNullable<z.ZodString>;
9
+ status: z.ZodNullable<z.ZodString>;
10
+ metadata: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
11
+ syncedAt: z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodDate]>>;
12
+ syncError: z.ZodNullable<z.ZodString>;
13
+ createdAt: z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodDate]>>;
14
+ updatedAt: z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodDate]>>;
15
+ }, z.core.$strip>;
16
+ export declare const smartbillInvoiceExternalRefsResponseSchema: z.ZodObject<{
17
+ data: z.ZodArray<z.ZodObject<{
18
+ id: z.ZodString;
19
+ invoiceId: z.ZodString;
20
+ provider: z.ZodString;
21
+ externalId: z.ZodNullable<z.ZodString>;
22
+ externalNumber: z.ZodNullable<z.ZodString>;
23
+ externalUrl: z.ZodNullable<z.ZodString>;
24
+ status: z.ZodNullable<z.ZodString>;
25
+ metadata: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
26
+ syncedAt: z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodDate]>>;
27
+ syncError: z.ZodNullable<z.ZodString>;
28
+ createdAt: z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodDate]>>;
29
+ updatedAt: z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodDate]>>;
30
+ }, z.core.$strip>>;
31
+ }, z.core.$strip>;
32
+ export type SmartbillInvoiceExternalRef = z.infer<typeof smartbillInvoiceExternalRefSchema>;
33
+ export interface SmartbillInvoiceReferenceParts {
34
+ companyVatCode: string | null;
35
+ seriesName: string | null;
36
+ number: string | null;
37
+ documentType: "invoice" | "proforma" | string | null;
38
+ }
39
+ export interface SmartbillInvoiceDocumentLink {
40
+ label: string;
41
+ href: string;
42
+ }
43
+ export declare function selectSmartbillInvoiceRef(refs: ReadonlyArray<SmartbillInvoiceExternalRef>): SmartbillInvoiceExternalRef | null;
44
+ export declare function resolveSmartbillInvoiceReferenceParts(ref: SmartbillInvoiceExternalRef | null | undefined): SmartbillInvoiceReferenceParts;
45
+ export declare function getSmartbillInvoiceDocumentLinks(ref: SmartbillInvoiceExternalRef | null | undefined): SmartbillInvoiceDocumentLink[];
46
+ //# sourceMappingURL=invoice-ui-data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invoice-ui-data.d.ts","sourceRoot":"","sources":["../src/invoice-ui-data.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,iCAAiC;;;;;;;;;;;;;iBAa5C,CAAA;AAEF,eAAO,MAAM,0CAA0C;;;;;;;;;;;;;;;iBAErD,CAAA;AAEF,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iCAAiC,CAAC,CAAA;AAE3F,MAAM,WAAW,8BAA8B;IAC7C,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,YAAY,EAAE,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,IAAI,CAAA;CACrD;AAED,MAAM,WAAW,4BAA4B;IAC3C,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;CACb;AAED,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,aAAa,CAAC,2BAA2B,CAAC,GAC/C,2BAA2B,GAAG,IAAI,CAEpC;AAED,wBAAgB,qCAAqC,CACnD,GAAG,EAAE,2BAA2B,GAAG,IAAI,GAAG,SAAS,GAClD,8BAA8B,CAYhC;AAED,wBAAgB,gCAAgC,CAC9C,GAAG,EAAE,2BAA2B,GAAG,IAAI,GAAG,SAAS,GAClD,4BAA4B,EAAE,CAchC"}