@flowselections/twinfield-authenticatie-module-15-06-2026 1.3.19 → 1.3.20
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 +57 -4
- package/dist-lib/integrations/supabase/auth-middleware.d.ts +4442 -746
- package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.d.ts +4442 -746
- package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.js +1 -1
- package/dist-lib/integrations/supabase/client.server.d.ts +4442 -746
- package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.server.js +1 -1
- package/dist-lib/integrations/supabase/twinfield-admin.server.d.ts +4442 -746
- package/dist-lib/integrations/supabase/twinfield-admin.server.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.d.ts +4501 -746
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/accounting/twinfield/actions.functions.d.ts +18515 -35
- package/dist-lib/lib/accounting/twinfield/actions.functions.d.ts.map +1 -1
- package/dist-lib/lib/accounting/twinfield/actions.functions.js +1 -1
- package/dist-lib/lib/accounting/twinfield/client.server.d.ts +1 -1
- package/dist-lib/lib/accounting/twinfield/client.server.js +2 -2
- package/dist-lib/lib/accounting/twinfield/conformance.functions.d.ts +4442 -746
- package/dist-lib/lib/accounting/twinfield/conformance.functions.d.ts.map +1 -1
- package/dist-lib/lib/accounting/twinfield/fetch.server.js +1 -1
- package/dist-lib/lib/accounting/twinfield/mapping.js +1 -1
- package/dist-lib/lib/accounting/twinfield/push.server.js +1 -1
- package/dist-lib/lib/accounting/twinfield/session.server.js +1 -1
- package/dist-lib/lib/accounting/twinfield/writes.functions.d.ts +11109 -21
- package/dist-lib/lib/accounting/twinfield/writes.functions.d.ts.map +1 -1
- package/dist-lib/lib/accounting/twinfield/writes.functions.js +2 -2
- package/dist-lib/lib/handlers/api-handlers.js +9 -9
- package/dist-lib/lib/handlers/cron-handlers.d.ts +1 -0
- package/dist-lib/lib/handlers/cron-handlers.d.ts.map +1 -1
- package/dist-lib/lib/handlers/cron-handlers.js +21 -9
- package/dist-lib/lib/handlers/index.d.ts +1 -1
- package/dist-lib/lib/handlers/index.d.ts.map +1 -1
- package/dist-lib/lib/handlers/index.js +1 -1
- package/dist-lib/lib/twinfield-adapter.functions.d.ts +7406 -14
- package/dist-lib/lib/twinfield-adapter.functions.d.ts.map +1 -1
- package/dist-lib/lib/twinfield-sync.functions.d.ts +80592 -75
- package/dist-lib/lib/twinfield-sync.functions.d.ts.map +1 -1
- package/dist-lib/lib/twinfield-sync.functions.js +58 -2
- package/dist-lib/lib/twinfield-sync.server.d.ts +18 -10
- package/dist-lib/lib/twinfield-sync.server.d.ts.map +1 -1
- package/dist-lib/lib/twinfield-sync.server.js +166 -31
- package/dist-lib/lib/twinfield-token.server.js +2 -2
- package/dist-lib/lib/twinfield.functions.d.ts +55545 -105
- package/dist-lib/lib/twinfield.functions.d.ts.map +1 -1
- package/dist-lib/lib/twinfield.functions.js +10 -10
- package/package.json +10 -2
- package/public/flowselections-assets/twinfield-authenticatie/consumer-api.md +27 -0
- package/public/flowselections-assets/twinfield-authenticatie/schema.sql +1 -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":"AAobA,wBAAgB,yBAAyB,CAAC,EACxC,eAAsB,GACvB,GAAE;IACD,eAAe,CAAC,EAAE,OAAO,CAAC;CACtB,+BA+WL"}
|
|
@@ -5,7 +5,7 @@ import { Card, Button, Badge, Select, SelectContent, SelectItem, SelectTrigger,
|
|
|
5
5
|
import { ChevronUp, ChevronDown, Link2, Unlink } from "lucide-react";
|
|
6
6
|
const twinfieldLogo = "/flowselections-assets/twinfield-authenticatie/twinfield-logo.svg";
|
|
7
7
|
import { startTwinfieldOAuth, syncTwinfieldCentralAccounts, listTwinfieldConnections, disconnectTwinfieldConnection, setTwinfieldConnectionOffice, listTwinfieldOfficesForConnection, } from "../../lib/twinfield.functions.js";
|
|
8
|
-
import { triggerTwinfieldSync, getTwinfieldSyncState, } from "../../lib/twinfield-sync.functions.js";
|
|
8
|
+
import { triggerTwinfieldSync, getTwinfieldSyncState, getTwinfieldPublicBaseUrl, setTwinfieldPublicBaseUrl, } from "../../lib/twinfield-sync.functions.js";
|
|
9
9
|
import { listTwinfieldPushQueue, retryTwinfieldQueueItem, } from "../../lib/twinfield-adapter.functions.js";
|
|
10
10
|
import { cn } from "../../lib/utils.js";
|
|
11
11
|
/** PostgREST meldt ontbrekende kolommen als schema-cachefout. Dat betekent in de
|
|
@@ -169,7 +169,7 @@ function ConnectionCard({ conn, onChanged, onDisconnected, }) {
|
|
|
169
169
|
try {
|
|
170
170
|
const res = await trigger({ data: { entity_type: entity } });
|
|
171
171
|
if (res.ok) {
|
|
172
|
-
toast.success(`${entity === "customers" ? "Debiteuren" : "Verkoopfacturen"} bijgewerkt (${res.upserted} rij(en)).`);
|
|
172
|
+
toast.success(`${entity === "customers" ? "Debiteuren" : entity === "invoices" ? "Verkoopfacturen" : "Grootboekrekeningen"} bijgewerkt (${res.upserted} rij(en)).`);
|
|
173
173
|
}
|
|
174
174
|
else {
|
|
175
175
|
toast.error(`Bijwerken mislukt: ${res.error ?? "onbekende fout"}`);
|
|
@@ -195,7 +195,7 @@ function ConnectionCard({ conn, onChanged, onDisconnected, }) {
|
|
|
195
195
|
return null;
|
|
196
196
|
return (_jsxs("span", { className: "flex items-baseline gap-2 truncate", children: [_jsx("span", { className: "truncate", children: selected.name ?? selected.code }), _jsx("span", { className: "text-[11px] text-muted-foreground font-mono", children: selected.code })] }));
|
|
197
197
|
})() }) }), _jsx(SelectContent, { children: offices.map((o) => (_jsx(SelectItem, { value: o.code, children: _jsxs("div", { className: "flex flex-col", children: [_jsx("span", { children: o.name ?? o.code }), _jsx("span", { className: "text-[11px] text-muted-foreground font-mono", children: o.code })] }) }, o.code))) })] })) : loadingOffices ? (_jsx("div", { className: "text-xs text-muted-foreground", children: "Administraties ophalen\u2026" })) : officesStatus === "error" ? (_jsxs("div", { className: "space-y-1.5", children: [_jsx("div", { className: "text-xs text-destructive", children: officesMessage ?? "Administraties konden niet opgehaald worden." }), _jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsx(Button, { size: "sm", variant: "outline", onClick: () => setOfficesReload((n) => n + 1), children: "Opnieuw proberen" }), needsReauth && (_jsxs(Button, { size: "sm", onClick: handleReauthorize, disabled: reauthorizing, children: [_jsx(Link2, { className: "h-4 w-4 mr-1.5" }), reauthorizing ? "Bezig…" : "Opnieuw autoriseren"] }))] })] })) : (_jsx("div", { className: "text-xs text-muted-foreground", children: officesMessage ??
|
|
198
|
-
"Dit Twinfield-account heeft geen administraties. Koppel een account met toegang tot een administratie." }))] }), effectiveOfficeCode && (_jsxs("div", { className: "flex flex-wrap gap-2 pt-1", children: [_jsx(Button, { size: "sm", variant: "outline", onClick: () => runSync("customers"), disabled: busy === "customers", children: busy === "customers" ? "Debiteuren…" : "Debiteuren bijwerken" }), _jsx(Button, { size: "sm", variant: "outline", onClick: () => runSync("invoices"), disabled: busy === "invoices", children: busy === "invoices" ? "Facturen…" : "Facturen bijwerken" })] }))] }));
|
|
198
|
+
"Dit Twinfield-account heeft geen administraties. Koppel een account met toegang tot een administratie." }))] }), effectiveOfficeCode && (_jsxs("div", { className: "flex flex-wrap gap-2 pt-1", children: [_jsx(Button, { size: "sm", variant: "outline", onClick: () => runSync("customers"), disabled: busy === "customers", children: busy === "customers" ? "Debiteuren…" : "Debiteuren bijwerken" }), _jsx(Button, { size: "sm", variant: "outline", onClick: () => runSync("invoices"), disabled: busy === "invoices", children: busy === "invoices" ? "Facturen…" : "Facturen bijwerken" }), _jsx(Button, { size: "sm", variant: "outline", onClick: () => runSync("ledger-accounts"), disabled: busy === "ledger-accounts", children: busy === "ledger-accounts" ? "Grootboek…" : "Grootboekrekeningen bijwerken" })] }))] }));
|
|
199
199
|
}
|
|
200
200
|
export function TwinfieldAuthSettingsCard({ defaultExpanded = true, } = {}) {
|
|
201
201
|
const startOAuth = useServerFn(startTwinfieldOAuth);
|
|
@@ -301,7 +301,7 @@ export function TwinfieldAuthSettingsCard({ defaultExpanded = true, } = {}) {
|
|
|
301
301
|
? "Koppeling controleren…"
|
|
302
302
|
: anyConnected
|
|
303
303
|
? "Verbonden"
|
|
304
|
-
: "Niet verbonden" })] })] }), _jsx("p", { className: "text-sm text-muted-foreground", children: "E\u00E9n Twinfield-account per omgeving. Verbreek eerst de huidige koppeling om te wisselen naar een ander account." })] })] }), _jsx("button", { type: "button", onClick: () => setIsExpanded((v) => !v), className: "shrink-0 p-1 rounded-md hover:bg-muted transition-colors", "aria-label": isExpanded ? "Samenvouwen" : "Uitklappen", children: isExpanded ? (_jsx(ChevronUp, { className: "h-5 w-5 text-muted-foreground" })) : (_jsx(ChevronDown, { className: "h-5 w-5 text-muted-foreground" })) })] }), isExpanded && (_jsxs("div", { className: "space-y-6 p-6", children: [centralNotice && (_jsx("div", { className: "rounded-lg border bg-muted/30 px-4 py-3 text-sm text-muted-foreground", "aria-live": "polite", children: centralNotice })), !hasAny && !loading && (_jsxs("div", { className: "rounded-lg border border-dashed p-8 text-center space-y-4", children: [_jsxs("div", { children: [_jsx("h3", { className: "text-base font-semibold text-foreground", children: "Nog niet verbonden met Twinfield" }), _jsx("p", { className: "text-sm text-muted-foreground mt-1", children: "Log in bij Twinfield en geef eenmalig toestemming. Wij bewaren de toegang veilig en verversen tokens automatisch." })] }), _jsxs(Button, { size: "lg", onClick: handleConnect, disabled: connecting, children: [_jsx(Link2, { className: "h-4 w-4 mr-2" }), connecting ? "Koppelen…" : "Verbind met Twinfield"] })] })), hasAny && (_jsxs("div", { className: "space-y-3", children: [_jsx("h3", { className: "text-base font-semibold text-foreground", children: "Gekoppelde administratie" }), _jsx("div", { className: "space-y-3", children: connections.map((c) => (_jsx(ConnectionCard, { conn: c, onChanged: () => loadAll(), onDisconnected: async () => {
|
|
304
|
+
: "Niet verbonden" })] })] }), _jsx("p", { className: "text-sm text-muted-foreground", children: "E\u00E9n Twinfield-account per omgeving. Verbreek eerst de huidige koppeling om te wisselen naar een ander account." })] })] }), _jsx("button", { type: "button", onClick: () => setIsExpanded((v) => !v), className: "shrink-0 p-1 rounded-md hover:bg-muted transition-colors", "aria-label": isExpanded ? "Samenvouwen" : "Uitklappen", children: isExpanded ? (_jsx(ChevronUp, { className: "h-5 w-5 text-muted-foreground" })) : (_jsx(ChevronDown, { className: "h-5 w-5 text-muted-foreground" })) })] }), isExpanded && (_jsxs("div", { className: "space-y-6 p-6", children: [_jsx(ShellAddressSection, {}), centralNotice && (_jsx("div", { className: "rounded-lg border bg-muted/30 px-4 py-3 text-sm text-muted-foreground", "aria-live": "polite", children: centralNotice })), !hasAny && !loading && (_jsxs("div", { className: "rounded-lg border border-dashed p-8 text-center space-y-4", children: [_jsxs("div", { children: [_jsx("h3", { className: "text-base font-semibold text-foreground", children: "Nog niet verbonden met Twinfield" }), _jsx("p", { className: "text-sm text-muted-foreground mt-1", children: "Log in bij Twinfield en geef eenmalig toestemming. Wij bewaren de toegang veilig en verversen tokens automatisch." })] }), _jsxs(Button, { size: "lg", onClick: handleConnect, disabled: connecting, children: [_jsx(Link2, { className: "h-4 w-4 mr-2" }), connecting ? "Koppelen…" : "Verbind met Twinfield"] })] })), hasAny && (_jsxs("div", { className: "space-y-3", children: [_jsx("h3", { className: "text-base font-semibold text-foreground", children: "Gekoppelde administratie" }), _jsx("div", { className: "space-y-3", children: connections.map((c) => (_jsx(ConnectionCard, { conn: c, onChanged: () => loadAll(), onDisconnected: async () => {
|
|
305
305
|
// Optimistisch: verwijder rij direct uit UI en sla Central-sync over,
|
|
306
306
|
// anders wordt de rij vanuit Central Auth meteen opnieuw opgehaald.
|
|
307
307
|
setConnections((prev) => prev.filter((row) => row.id !== c.id));
|
|
@@ -348,3 +348,56 @@ export function TwinfieldAuthSettingsCard({ defaultExpanded = true, } = {}) {
|
|
|
348
348
|
}, children: retrying === q.id ? "Bezig…" : "Opnieuw" }))] }, q.id));
|
|
349
349
|
}) })] }))] }))] }));
|
|
350
350
|
}
|
|
351
|
+
function formatTs(ts) {
|
|
352
|
+
if (!ts)
|
|
353
|
+
return "nog nooit";
|
|
354
|
+
const d = new Date(ts);
|
|
355
|
+
return isNaN(d.getTime()) ? "onbekend" : d.toLocaleString("nl-NL");
|
|
356
|
+
}
|
|
357
|
+
function ShellAddressSection() {
|
|
358
|
+
const load = useServerFn(getTwinfieldPublicBaseUrl);
|
|
359
|
+
const save = useServerFn(setTwinfieldPublicBaseUrl);
|
|
360
|
+
const [envSet, setEnvSet] = useState(false);
|
|
361
|
+
const [value, setValue] = useState("");
|
|
362
|
+
const [saving, setSaving] = useState(false);
|
|
363
|
+
const [jobs, setJobs] = useState([]);
|
|
364
|
+
const refresh = () => load()
|
|
365
|
+
.then((r) => {
|
|
366
|
+
setEnvSet(!!r?.env_set);
|
|
367
|
+
setValue(r?.stored ?? "");
|
|
368
|
+
setJobs(Array.isArray(r?.job_states) ? r.job_states : []);
|
|
369
|
+
})
|
|
370
|
+
.catch(() => { });
|
|
371
|
+
useEffect(() => {
|
|
372
|
+
void refresh();
|
|
373
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
374
|
+
}, []);
|
|
375
|
+
const onSave = async () => {
|
|
376
|
+
setSaving(true);
|
|
377
|
+
try {
|
|
378
|
+
const r = await save({ data: { url: value } });
|
|
379
|
+
if (r.ok)
|
|
380
|
+
toast.success(`Taken geregistreerd op ${r.base_url}`);
|
|
381
|
+
else
|
|
382
|
+
toast.error(r.error);
|
|
383
|
+
await refresh();
|
|
384
|
+
}
|
|
385
|
+
catch (e) {
|
|
386
|
+
toast.error(e?.message ?? "Opslaan mislukt");
|
|
387
|
+
}
|
|
388
|
+
finally {
|
|
389
|
+
setSaving(false);
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
const job = (k) => jobs.find((j) => j.entity_type === k);
|
|
393
|
+
const rows = [
|
|
394
|
+
["open_payments", "Betaalstatus (elk uur)"],
|
|
395
|
+
["invoices_reconcile", "Nachtelijke herscan"],
|
|
396
|
+
];
|
|
397
|
+
return (_jsxs("div", { className: "rounded-lg border p-4 space-y-3", children: [_jsxs("div", { children: [_jsx("h3", { className: "text-sm font-semibold text-foreground", children: "Shell-adres voor achtergrondtaken" }), _jsx("p", { className: "text-xs text-muted-foreground mt-1", children: envSet
|
|
398
|
+
? "Ingesteld via de omgevingsvariabele PUBLIC_BASE_URL; die gaat voor op dit veld."
|
|
399
|
+
: "Het publieke adres van deze shell. Zonder adres worden er geen taken ingepland." })] }), _jsxs("div", { className: "flex gap-2", children: [_jsx("input", { type: "url", value: value, onChange: (e) => setValue(e.target.value), placeholder: "https://\u2026", className: "flex-1 rounded-md border bg-background px-3 py-2 text-sm" }), _jsx(Button, { onClick: onSave, disabled: saving || value.trim().length < 8, children: saving ? "Bezig…" : "Opslaan en taken registreren" })] }), _jsx("div", { className: "space-y-1 text-xs", children: rows.map(([k, label]) => {
|
|
400
|
+
const j = job(k);
|
|
401
|
+
return (_jsxs("div", { className: "flex flex-wrap justify-between gap-2", children: [_jsx("span", { className: "text-muted-foreground", children: label }), _jsxs("span", { className: j?.last_error ? "text-destructive" : "text-foreground", children: [formatTs(j?.last_synced_at), j?.last_error ? ` — ${j.last_error}` : ""] })] }, k));
|
|
402
|
+
}) })] }));
|
|
403
|
+
}
|