@flowselections/twinfield-authenticatie-module-15-06-2026 1.3.12 → 1.3.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-lib/components/settings/TwinfieldAuthSettingsCard.d.ts.map +1 -1
- package/dist-lib/components/settings/TwinfieldAuthSettingsCard.js +36 -6
- package/dist-lib/integrations/supabase/auth-middleware.d.ts +1943 -146
- package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.d.ts +1943 -146
- package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.server.d.ts +1943 -146
- package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/twinfield-admin.server.d.ts +1943 -146
- package/dist-lib/integrations/supabase/twinfield-admin.server.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.d.ts +1958 -146
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.js +12 -1
- package/dist-lib/lib/accounting/twinfield/actions.functions.d.ts +9910 -925
- package/dist-lib/lib/accounting/twinfield/actions.functions.d.ts.map +1 -1
- package/dist-lib/lib/accounting/twinfield/conformance.functions.d.ts +1943 -146
- package/dist-lib/lib/accounting/twinfield/conformance.functions.d.ts.map +1 -1
- package/dist-lib/lib/accounting/twinfield/cron-lock.server.d.ts +16 -0
- package/dist-lib/lib/accounting/twinfield/cron-lock.server.d.ts.map +1 -0
- package/dist-lib/lib/accounting/twinfield/cron-lock.server.js +37 -0
- package/dist-lib/lib/accounting/twinfield/cron-run.server.d.ts +2 -0
- package/dist-lib/lib/accounting/twinfield/cron-run.server.d.ts.map +1 -0
- package/dist-lib/lib/accounting/twinfield/cron-run.server.js +25 -0
- package/dist-lib/lib/accounting/twinfield/mapping.d.ts.map +1 -1
- package/dist-lib/lib/accounting/twinfield/mapping.js +47 -26
- package/dist-lib/lib/accounting/twinfield/push.server.d.ts +17 -2
- package/dist-lib/lib/accounting/twinfield/push.server.d.ts.map +1 -1
- package/dist-lib/lib/accounting/twinfield/push.server.js +205 -14
- package/dist-lib/lib/accounting/twinfield/writes.functions.d.ts +5780 -389
- package/dist-lib/lib/accounting/twinfield/writes.functions.d.ts.map +1 -1
- package/dist-lib/lib/accounting/twinfield/writes.functions.js +5 -3
- package/dist-lib/lib/central/central-accounts.server.d.ts +11 -4
- package/dist-lib/lib/central/central-accounts.server.d.ts.map +1 -1
- package/dist-lib/lib/central/central-accounts.server.js +75 -34
- package/dist-lib/lib/central/central-config.server.d.ts +18 -0
- package/dist-lib/lib/central/central-config.server.d.ts.map +1 -1
- package/dist-lib/lib/central/central-config.server.js +76 -0
- package/dist-lib/lib/central/central-token.server.d.ts +19 -4
- package/dist-lib/lib/central/central-token.server.d.ts.map +1 -1
- package/dist-lib/lib/central/central-token.server.js +218 -51
- package/dist-lib/lib/twinfield-adapter.functions.d.ts +3715 -121
- package/dist-lib/lib/twinfield-adapter.functions.d.ts.map +1 -1
- package/dist-lib/lib/twinfield-sync.functions.d.ts +9910 -925
- package/dist-lib/lib/twinfield-sync.functions.d.ts.map +1 -1
- package/dist-lib/lib/twinfield-sync.functions.js +7 -4
- package/dist-lib/lib/twinfield-token.server.d.ts +2 -4
- package/dist-lib/lib/twinfield-token.server.d.ts.map +1 -1
- package/dist-lib/lib/twinfield-token.server.js +27 -18
- package/dist-lib/lib/twinfield.functions.d.ts +27142 -176
- package/dist-lib/lib/twinfield.functions.d.ts.map +1 -1
- package/dist-lib/lib/twinfield.functions.js +102 -55
- package/package.json +2 -2
- package/public/flowselections-assets/twinfield-authenticatie/schema.sql +601 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TwinfieldAuthSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/components/settings/TwinfieldAuthSettingsCard.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"TwinfieldAuthSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/components/settings/TwinfieldAuthSettingsCard.tsx"],"names":[],"mappings":"AAsZA,wBAAgB,yBAAyB,CAAC,EACxC,eAAsB,GACvB,GAAE;IACD,eAAe,CAAC,EAAE,OAAO,CAAC;CACtB,+BAqWL"}
|
|
@@ -8,6 +8,15 @@ import { startTwinfieldOAuth, syncTwinfieldCentralAccounts, listTwinfieldConnect
|
|
|
8
8
|
import { triggerTwinfieldSync, getTwinfieldSyncState, } from "../../lib/twinfield-sync.functions";
|
|
9
9
|
import { listTwinfieldPushQueue, retryTwinfieldQueueItem, } from "../../lib/twinfield-adapter.functions";
|
|
10
10
|
import { cn } from "../../lib/utils";
|
|
11
|
+
/** PostgREST meldt ontbrekende kolommen als schema-cachefout. Dat betekent in de
|
|
12
|
+
* praktijk dat het databaseschema van deze shell verouderd is. */
|
|
13
|
+
function friendlySyncError(message) {
|
|
14
|
+
const missingColumn = /Could not find the '([^']+)' column/i.exec(message);
|
|
15
|
+
if (missingColumn) {
|
|
16
|
+
return `Het databaseschema van deze omgeving is verouderd (veld "${missingColumn[1]}" ontbreekt). Draai het meegeleverde schema-script van de Twinfield-module op de database en probeer opnieuw.`;
|
|
17
|
+
}
|
|
18
|
+
return message;
|
|
19
|
+
}
|
|
11
20
|
function hasTwinfieldReturnParams() {
|
|
12
21
|
if (typeof window === "undefined")
|
|
13
22
|
return false;
|
|
@@ -97,7 +106,9 @@ function ConnectionCard({ conn, onChanged, onDisconnected, }) {
|
|
|
97
106
|
const handleReauthorize = async () => {
|
|
98
107
|
setReauthorizing(true);
|
|
99
108
|
try {
|
|
100
|
-
const res = await startOAuthForCard({
|
|
109
|
+
const res = await startOAuthForCard({
|
|
110
|
+
data: { returnPath: window.location.pathname, reauthorize: true },
|
|
111
|
+
});
|
|
101
112
|
if (!res?.url)
|
|
102
113
|
throw new Error("Kon geen koppelingsverzoek starten.");
|
|
103
114
|
window.location.href = res.url;
|
|
@@ -175,7 +186,10 @@ function ConnectionCard({ conn, onChanged, onDisconnected, }) {
|
|
|
175
186
|
const effectiveOfficeCode = conn.office_code ?? optimisticOffice?.code ?? null;
|
|
176
187
|
const effectiveOfficeName = conn.company_name ?? optimisticOffice?.name ?? null;
|
|
177
188
|
const displayName = effectiveOfficeName ?? effectiveOfficeCode ?? conn.company_code ?? "Nog geen administratie gekozen";
|
|
178
|
-
|
|
189
|
+
const cardNeedsReauth = conn.reauthorize_required ||
|
|
190
|
+
(Array.isArray(conn.missing_scopes) && conn.missing_scopes.length > 0) ||
|
|
191
|
+
needsReauth;
|
|
192
|
+
return (_jsxs("div", { className: "rounded-lg border p-4 space-y-4", children: [_jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [_jsx("span", { className: "font-semibold text-foreground truncate", children: displayName }), _jsx(Badge, { variant: cardNeedsReauth ? "destructive" : conn.connected ? "default" : "secondary", className: "font-normal", children: cardNeedsReauth ? "Autorisatie vereist" : conn.connected ? "Verbonden" : "Onvolledig" }), _jsx(Badge, { variant: "outline", className: "font-normal", children: conn.environment === "staging" || conn.environment === "sandbox" ? "Test" : "Live" })] }), _jsxs("div", { className: "mt-1 text-xs text-muted-foreground", children: [effectiveOfficeCode ? (_jsx("span", { className: "font-mono", children: effectiveOfficeCode })) : (_jsx("span", { children: "Kies hieronder een administratie om te kunnen synchroniseren." })), conn.connected_at && (_jsxs("span", { className: "ml-2", children: ["\u00B7 gekoppeld ", relativeTime(conn.connected_at)] }))] }), cardNeedsReauth && (_jsxs("div", { className: "mt-2 rounded-md border border-destructive/30 bg-destructive/5 px-3 py-2 text-xs text-destructive", children: [_jsxs("div", { className: "font-medium", children: ["Twinfield vraagt om her-autorisatie", conn.scope_state ? ` (${conn.scope_state})` : "", "."] }), Array.isArray(conn.missing_scopes) && conn.missing_scopes.length > 0 && (_jsxs("div", { className: "mt-0.5", children: ["Ontbrekende scopes: ", conn.missing_scopes.join(", ")] })), _jsxs(Button, { size: "sm", variant: "outline", className: "mt-2 border-destructive/50 text-destructive hover:bg-destructive/10", onClick: handleReauthorize, disabled: reauthorizing, children: [_jsx(Link2, { className: "h-3.5 w-3.5 mr-1.5" }), reauthorizing ? "Bezig…" : "Opnieuw autoriseren"] })] }))] }), _jsxs(Button, { size: "sm", variant: "ghost", onClick: handleDisconnect, disabled: disconnecting, className: "text-muted-foreground hover:text-destructive", children: [_jsx(Unlink, { className: "h-4 w-4 mr-1.5" }), disconnecting ? "Bezig…" : "Verbreken"] })] }), _jsxs("div", { className: "space-y-1.5", children: [_jsx("div", { className: "text-xs font-medium text-muted-foreground", children: "Administratie" }), offices.length > 0 ? (_jsxs(Select, { value: effectiveOfficeCode ?? undefined, onValueChange: handleOfficeChange, disabled: savingOffice, children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, { placeholder: "Kies een administratie", children: (() => {
|
|
179
193
|
const selected = offices.find((o) => o.code === effectiveOfficeCode);
|
|
180
194
|
if (!selected)
|
|
181
195
|
return null;
|
|
@@ -295,14 +309,30 @@ export function TwinfieldAuthSettingsCard({ defaultExpanded = true, } = {}) {
|
|
|
295
309
|
} }, c.id))) })] })), anyConnected && (_jsxs("div", { className: "rounded-lg border p-4 space-y-3", children: [_jsxs("div", { children: [_jsx("div", { className: "font-semibold text-foreground", children: "Automatische sync" }), _jsx("div", { className: "text-sm text-muted-foreground mt-0.5", children: "Debiteuren worden elke 15 minuten en verkoopfacturen elke 10 minuten automatisch bijgewerkt. Incomplete records worden elke 5 minuten aangevuld. Deze weergave ververst zichzelf elke 30 seconden." })] }), _jsx("div", { className: "grid grid-cols-2 gap-3", children: ["customers", "invoices"].map((k) => {
|
|
296
310
|
const s = stateFor(k);
|
|
297
311
|
const count = k === "customers" ? counts.customers : counts.invoices;
|
|
298
|
-
|
|
312
|
+
// Waarschuw zodra een sync langer dan het dubbele van zijn
|
|
313
|
+
// interval niets heeft gedaan (30 resp. 20 minuten).
|
|
314
|
+
const maxAgeMs = (k === "customers" ? 30 : 20) * 60 * 1000;
|
|
315
|
+
const last = s?.last_synced_at ? new Date(s.last_synced_at).getTime() : 0;
|
|
316
|
+
const isStale = !last || Date.now() - last > maxAgeMs;
|
|
317
|
+
return (_jsxs("div", { className: "rounded-md border bg-muted/30 px-3 py-2", children: [_jsx("div", { className: "text-xs text-muted-foreground", children: k === "customers" ? "Debiteuren" : "Verkoopfacturen" }), _jsxs("div", { className: "text-sm font-medium text-foreground mt-0.5", children: [count, " \u00B7 laatst ", relativeTime(s?.last_synced_at ?? null)] }), isStale && !s?.last_error && (_jsx("div", { className: "text-[11px] text-amber-700 mt-1", children: "Achterstand: deze sync heeft langer dan verwacht niets bijgewerkt. De volgende ronde herstelt dit automatisch." })), s?.last_error && (_jsx("div", { className: "text-[11px] text-amber-700 mt-1 break-all", children: friendlySyncError(s.last_error) }))] }, k));
|
|
299
318
|
}) })] })), anyConnected && pushQueue.length > 0 && (_jsxs("div", { className: "rounded-lg border p-4", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsxs("div", { children: [_jsx("div", { className: "font-semibold text-foreground", children: "Uitgaande facturen (push-wachtrij)" }), _jsx("div", { className: "text-sm text-muted-foreground mt-0.5", children: "Laatste 20 facturen die naar Twinfield zijn gestuurd." })] }), _jsx(Button, { size: "sm", variant: "outline", onClick: () => void loadAll(), children: "Vernieuwen" })] }), _jsx("div", { className: "mt-3 divide-y rounded-md border", children: pushQueue.map((q) => {
|
|
300
|
-
const
|
|
319
|
+
const isDone = q.status === "done" || q.status === "success";
|
|
320
|
+
const isFailed = q.status === "dead" || q.status === "error" || q.status === "failed";
|
|
321
|
+
const variant = isDone
|
|
301
322
|
? "default"
|
|
302
|
-
:
|
|
323
|
+
: isFailed
|
|
303
324
|
? "destructive"
|
|
304
325
|
: "secondary";
|
|
305
|
-
|
|
326
|
+
const label = isDone
|
|
327
|
+
? "Verstuurd"
|
|
328
|
+
: q.status === "dead"
|
|
329
|
+
? "Definitief mislukt"
|
|
330
|
+
: isFailed
|
|
331
|
+
? "Mislukt · wordt opnieuw geprobeerd"
|
|
332
|
+
: q.status === "processing"
|
|
333
|
+
? "Bezig"
|
|
334
|
+
: "In wachtrij";
|
|
335
|
+
return (_jsxs("div", { className: "flex items-start justify-between gap-3 px-3 py-2", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Badge, { variant: variant, children: label }), _jsxs("span", { className: "text-xs text-muted-foreground", children: ["poging ", q.attempts, "/5"] }), q.external_id && (_jsxs("span", { className: "text-xs font-mono text-foreground", children: ["#", q.external_id] }))] }), q.last_error && (_jsx("div", { className: "mt-1 text-xs text-muted-foreground break-all", children: q.last_error })), _jsx("div", { className: "mt-0.5 text-[11px] text-muted-foreground", children: relativeTime(q.updated_at ?? q.created_at) })] }), isFailed && (_jsx(Button, { size: "sm", variant: "outline", disabled: retrying === q.id, onClick: async () => {
|
|
306
336
|
setRetrying(q.id);
|
|
307
337
|
try {
|
|
308
338
|
await retryQueueItem({ data: { id: q.id } });
|