@flowselections/layout-maker 1.7.1 → 1.7.3

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 (95) hide show
  1. package/README.md +69 -54
  2. package/dist-lib/components/AfdrukKnop.d.ts +1 -1
  3. package/dist-lib/components/AfdrukKnop.js +2 -2
  4. package/dist-lib/components/AiLayoutImportDialog.js +4 -4
  5. package/dist-lib/components/BlokOntwerperPage.js +5 -5
  6. package/dist-lib/components/ComputersLijst.js +2 -2
  7. package/dist-lib/components/DocumentSettingsPanel.d.ts +2 -2
  8. package/dist-lib/components/DocumentSettingsPanel.js +3 -3
  9. package/dist-lib/components/FormaatOrientatieBar.d.ts +1 -1
  10. package/dist-lib/components/FormaatOrientatieBar.js +2 -2
  11. package/dist-lib/components/LayoutsPage.js +4 -4
  12. package/dist-lib/components/LogoBibliotheekDialog.d.ts +1 -1
  13. package/dist-lib/components/LogoBibliotheekDialog.js +2 -2
  14. package/dist-lib/components/LogosPage.d.ts +1 -1
  15. package/dist-lib/components/LogosPage.js +2 -2
  16. package/dist-lib/components/NetwerkPrintersDialog.js +2 -2
  17. package/dist-lib/components/PakbonBuilderPage.js +8 -8
  18. package/dist-lib/components/PakbonPreview.d.ts +1 -1
  19. package/dist-lib/components/PakbonPreview.js +3 -3
  20. package/dist-lib/components/PakbonSectiesPanel.d.ts +1 -1
  21. package/dist-lib/components/PakbonSectiesPanel.js +4 -4
  22. package/dist-lib/components/PrintQueuePage.d.ts.map +1 -1
  23. package/dist-lib/components/PrintQueuePage.js +7 -6
  24. package/dist-lib/components/PrinterSetupWizard.js +6 -6
  25. package/dist-lib/components/PrintersPage.js +7 -7
  26. package/dist-lib/components/ProductiebonBlokkenPanel.d.ts +1 -1
  27. package/dist-lib/components/ProductiebonBlokkenPanel.js +1 -1
  28. package/dist-lib/components/ProductiebonBuilderPage.js +6 -6
  29. package/dist-lib/components/ProductiebonPreview.d.ts +1 -1
  30. package/dist-lib/components/ProductiebonPreview.js +2 -2
  31. package/dist-lib/components/WerkplekConfiguratiePage.js +7 -7
  32. package/dist-lib/index.d.ts +62 -47
  33. package/dist-lib/index.d.ts.map +1 -1
  34. package/dist-lib/index.js +47 -48
  35. package/dist-lib/integrations/supabase/auth-attacher.js +1 -1
  36. package/dist-lib/integrations/supabase/auth-middleware.d.ts +1302 -749
  37. package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
  38. package/dist-lib/integrations/supabase/client.d.ts +1 -1
  39. package/dist-lib/integrations/supabase/client.js +1 -1
  40. package/dist-lib/integrations/supabase/client.server.d.ts +1302 -749
  41. package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
  42. package/dist-lib/integrations/supabase/client.server.js +1 -1
  43. package/dist-lib/integrations/supabase/types.d.ts +685 -127
  44. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  45. package/dist-lib/lib/aiLayout.functions.d.ts +1385 -832
  46. package/dist-lib/lib/aiLayout.functions.d.ts.map +1 -1
  47. package/dist-lib/lib/aiLayout.functions.js +2 -2
  48. package/dist-lib/lib/aiLayout.server.d.ts +1 -1
  49. package/dist-lib/lib/aiLayout.server.js +9 -9
  50. package/dist-lib/lib/browserPrint.d.ts +1 -1
  51. package/dist-lib/lib/browserPrint.js +8 -8
  52. package/dist-lib/lib/directPrint.d.ts +1 -1
  53. package/dist-lib/lib/directPrint.js +4 -4
  54. package/dist-lib/lib/documentPdf.d.ts +1 -1
  55. package/dist-lib/lib/documentProfiles.d.ts +1 -1
  56. package/dist-lib/lib/formaatPrinters.js +1 -1
  57. package/dist-lib/lib/htmlNaarPdf.server.js +1 -1
  58. package/dist-lib/lib/layoutPreview.d.ts +1 -1
  59. package/dist-lib/lib/layoutPreview.js +8 -8
  60. package/dist-lib/lib/logoLibrary.js +1 -1
  61. package/dist-lib/lib/orderData.server.d.ts +2 -1
  62. package/dist-lib/lib/orderData.server.d.ts.map +1 -1
  63. package/dist-lib/lib/orderData.server.js +7 -8
  64. package/dist-lib/lib/pakbonBuilder.d.ts +1 -1
  65. package/dist-lib/lib/pakbonHtml.d.ts +1 -1
  66. package/dist-lib/lib/pakbonHtml.js +52 -52
  67. package/dist-lib/lib/printApi.d.ts +1 -1
  68. package/dist-lib/lib/printApi.js +3 -3
  69. package/dist-lib/lib/printQueue.server.d.ts +12 -3
  70. package/dist-lib/lib/printQueue.server.d.ts.map +1 -1
  71. package/dist-lib/lib/printQueue.server.js +66 -48
  72. package/dist-lib/lib/printService.functions.d.ts +5539 -24425
  73. package/dist-lib/lib/printService.functions.d.ts.map +1 -1
  74. package/dist-lib/lib/printService.functions.js +5 -31
  75. package/dist-lib/lib/printService.server.js +1 -1
  76. package/dist-lib/lib/productiebonBuilder.d.ts +1 -1
  77. package/dist-lib/lib/productiebonHtml.js +17 -17
  78. package/dist-lib/lib/profielHtml.js +20 -20
  79. package/dist-lib/lib/queueTick.d.ts +11 -3
  80. package/dist-lib/lib/queueTick.d.ts.map +1 -1
  81. package/dist-lib/lib/queueTick.js +68 -21
  82. package/dist-lib/lib/queueTickClient.d.ts +8 -0
  83. package/dist-lib/lib/queueTickClient.d.ts.map +1 -0
  84. package/dist-lib/lib/queueTickClient.js +37 -0
  85. package/dist-lib/lib/runnerRegistry.server.d.ts +3 -2
  86. package/dist-lib/lib/runnerRegistry.server.d.ts.map +1 -1
  87. package/dist-lib/lib/runnerRegistry.server.js +6 -8
  88. package/dist-lib/lib/supabaseAdmin.server.d.ts +5 -5
  89. package/dist-lib/lib/supabaseAdmin.server.js +43 -43
  90. package/dist-lib/lib/supabaseClient.d.ts +1 -1
  91. package/dist-lib/lib/testpagina.js +3 -3
  92. package/dist-lib/lib/useDocumentData.d.ts +1 -1
  93. package/dist-lib/lib/useDocumentData.js +1 -1
  94. package/dist-lib/lib/useNetwerkPrinters.js +1 -1
  95. package/package.json +9 -4
@@ -2,13 +2,11 @@
2
2
  // src/lib/printService.functions.ts — server functions voor achtergrondprinten
3
3
  // ============================================================================
4
4
  import { createServerFn } from "@tanstack/react-start";
5
- import { requireSupabaseAuth } from "../integrations/supabase/auth-middleware";
5
+ import { requireSupabaseAuth } from "../integrations/supabase/auth-middleware.js";
6
6
  export const netwerkPrinters = createServerFn({ method: "POST" })
7
7
  .middleware([requireSupabaseAuth])
8
8
  .handler(async () => {
9
- const { meldRunnerAan } = await import("./runnerRegistry.server");
10
- void meldRunnerAan();
11
- const { haalNetwerkPrinters } = await import("./printService.server");
9
+ const { haalNetwerkPrinters } = await import("./printService.server.js");
12
10
  try {
13
11
  return { ok: true, printers: await haalNetwerkPrinters() };
14
12
  }
@@ -32,7 +30,7 @@ export const verstuurPrintOpdracht = createServerFn({ method: "POST" })
32
30
  };
33
31
  })
34
32
  .handler(async ({ data }) => {
35
- const { stuurPdfNaarPrinter } = await import("./printService.server");
33
+ const { stuurPdfNaarPrinter } = await import("./printService.server.js");
36
34
  try {
37
35
  return { ok: true, externJobId: await stuurPdfNaarPrinter(data) };
38
36
  }
@@ -46,7 +44,7 @@ export const printStatus = createServerFn({ method: "POST" })
46
44
  externJobId: String(input?.externJobId ?? "").slice(0, 40),
47
45
  }))
48
46
  .handler(async ({ data }) => {
49
- const { opdrachtStatus } = await import("./printService.server");
47
+ const { opdrachtStatus } = await import("./printService.server.js");
50
48
  try {
51
49
  return { ok: true, status: await opdrachtStatus(data.externJobId) };
52
50
  }
@@ -57,9 +55,7 @@ export const printStatus = createServerFn({ method: "POST" })
57
55
  export const netwerkComputers = createServerFn({ method: "POST" })
58
56
  .middleware([requireSupabaseAuth])
59
57
  .handler(async () => {
60
- const { meldRunnerAan } = await import("./runnerRegistry.server");
61
- void meldRunnerAan();
62
- const { haalComputers } = await import("./printService.server");
58
+ const { haalComputers } = await import("./printService.server.js");
63
59
  try {
64
60
  return { ok: true, computers: await haalComputers() };
65
61
  }
@@ -70,25 +66,3 @@ export const netwerkComputers = createServerFn({ method: "POST" })
70
66
  };
71
67
  }
72
68
  });
73
- /**
74
- * Vangnet: verwerkt direct een paar wachtende opdrachten. Wordt aangeroepen
75
- * zolang de printwachtrij-pagina openstaat, zodat een verse installatie meteen
76
- * print — ook voor de eerste cron-ronde.
77
- */
78
- export const wachtrijTick = createServerFn({ method: "POST" })
79
- .middleware([requireSupabaseAuth])
80
- .handler(async () => {
81
- try {
82
- const { adminConfiguratieFout } = await import("./supabaseAdmin.server");
83
- const configFout = adminConfiguratieFout();
84
- if (configFout)
85
- return { ok: false, fout: configFout };
86
- const { meldRunnerAan } = await import("./runnerRegistry.server");
87
- await meldRunnerAan();
88
- const { verwerkWachtrij } = await import("./printQueue.server");
89
- return { ok: true, ...(await verwerkWachtrij(3)) };
90
- }
91
- catch (e) {
92
- return { ok: false, fout: e instanceof Error ? e.message : "Verwerken mislukt" };
93
- }
94
- });
@@ -10,7 +10,7 @@
10
10
  // 3. meegestuurde render_html -> die opmaak printen
11
11
  // 4. actieve layout van het documenttype -> vers renderen
12
12
  // ============================================================================
13
- import { printToegang, PrintToegangFout, vergeetPrintToegang } from "./centralAuth.server";
13
+ import { printToegang, PrintToegangFout, vergeetPrintToegang } from "./centralAuth.server.js";
14
14
  const BASIS = "https://api.printnode.com";
15
15
  const arr = (v) => (Array.isArray(v) ? v : []);
16
16
  function b64(tekst) {
@@ -1,4 +1,4 @@
1
- import type { InstellingDef } from "./documentProfiles";
1
+ import type { InstellingDef } from "./documentProfiles.js";
2
2
  export type ProductiebonBlokType = "productinfo" | "productfotos" | "samenstelling" | "instructies" | "productiestappen" | "fustinformatie" | "belading" | "visueleopbouw" | "materialen" | "controlepunten" | "extrainfo" | "qrblok" | "tekstblok";
3
3
  export interface ProductiebonVeld {
4
4
  key: string;
@@ -5,8 +5,8 @@
5
5
  // (config.productiebon.blokken). Wordt gebruikt door de printwachtrij zodat een
6
6
  // productiebon nooit als blanco vel bij de printer belandt.
7
7
  // ============================================================================
8
- import { DEMO_PRODUCTIEBON, ONDERDEEL_LABELS, FUST_LABELS, BELADING_LABELS, EXTRA_LABELS, leesProductiebonConfig, pbBlokZichtbaar, pbConditieContext, splitsLijst, vulPbVeldcodes, } from "./productiebonBuilder";
9
- import { esc } from "./pakbonHtml";
8
+ import { DEMO_PRODUCTIEBON, ONDERDEEL_LABELS, FUST_LABELS, BELADING_LABELS, EXTRA_LABELS, leesProductiebonConfig, pbBlokZichtbaar, pbConditieContext, splitsLijst, vulPbVeldcodes, } from "./productiebonBuilder.js";
9
+ import { esc } from "./pakbonHtml.js";
10
10
  const arr = (v) => (Array.isArray(v) ? v : []);
11
11
  /**
12
12
  * Vult ontbrekende onderdelen aan, zodat een module die maar een deel van de
@@ -147,20 +147,20 @@ export function renderProductiebonDocument(config, gegevens, opties = {}) {
147
147
  return inhoud ? `<div class="blok">${inhoud}</div>` : "";
148
148
  })
149
149
  .join("");
150
- return `<!doctype html><html lang="nl"><head><meta charset="utf-8" />
151
- <title>${esc(opties.titel ?? "Productiebon")}</title>
152
- <style>
153
- @page { size: ${b}mm ${h}mm; margin: ${marge}mm; }
154
- * { box-sizing: border-box; }
155
- html, body { margin: 0; padding: 0; }
156
- body { font-family: Arial, Helvetica, sans-serif; font-size: 9pt; color: #111827; line-height: 1.35; }
157
- .blok { margin-bottom: 2.5mm; }
158
- .sectitel { font-size: 90%; font-weight: 600; text-transform: uppercase; color: #6b7280; margin-bottom: 0.6mm; }
159
- .vet { font-weight: 600; }
160
- .kv { display: flex; justify-content: space-between; gap: 3mm; }
161
- .kv .k { color: #6b7280; }
162
- .tabel { width: 100%; border-collapse: collapse; table-layout: fixed; }
163
- .tabel th { text-align: left; font-weight: 600; }
164
- .regel { padding: 0.4mm 0; }
150
+ return `<!doctype html><html lang="nl"><head><meta charset="utf-8" />
151
+ <title>${esc(opties.titel ?? "Productiebon")}</title>
152
+ <style>
153
+ @page { size: ${b}mm ${h}mm; margin: ${marge}mm; }
154
+ * { box-sizing: border-box; }
155
+ html, body { margin: 0; padding: 0; }
156
+ body { font-family: Arial, Helvetica, sans-serif; font-size: 9pt; color: #111827; line-height: 1.35; }
157
+ .blok { margin-bottom: 2.5mm; }
158
+ .sectitel { font-size: 90%; font-weight: 600; text-transform: uppercase; color: #6b7280; margin-bottom: 0.6mm; }
159
+ .vet { font-weight: 600; }
160
+ .kv { display: flex; justify-content: space-between; gap: 3mm; }
161
+ .kv .k { color: #6b7280; }
162
+ .tabel { width: 100%; border-collapse: collapse; table-layout: fixed; }
163
+ .tabel th { text-align: left; font-weight: 600; }
164
+ .regel { padding: 0.4mm 0; }
165
165
  </style></head><body>${body}</body></html>`;
166
166
  }
@@ -7,8 +7,8 @@
7
7
  // keuzes. Deze renderer zet die instellingen om naar print-HTML, zodat élke
8
8
  // bestaande én toekomstige layout meteen afdrukbaar is zonder extra werk.
9
9
  // ============================================================================
10
- import { configWaarde, documentProfiel, } from "./documentProfiles";
11
- import { esc } from "./pakbonHtml";
10
+ import { configWaarde, documentProfiel, } from "./documentProfiles.js";
11
+ import { esc } from "./pakbonHtml.js";
12
12
  const arr = (v) => (Array.isArray(v) ? v : []);
13
13
  /** Instellingen die geen losse regel opleveren maar een eigen weergave hebben. */
14
14
  const SPECIAAL = new Set([
@@ -110,8 +110,8 @@ function regeltabel(regels) {
110
110
  const eenheid = r["eenheid"] ?? "";
111
111
  return `<tr><td>${esc(code)}</td><td>${esc(omschrijving)}</td><td style="text-align:right">${esc(aantal)}</td><td>${esc(eenheid)}</td></tr>`;
112
112
  };
113
- return `<table class="tabel"><colgroup><col style="width:20%" /><col style="width:52%" /><col style="width:16%" /><col style="width:12%" /></colgroup>
114
- <thead><tr class="onder"><th>Code</th><th>Omschrijving</th><th style="text-align:right">Aantal</th><th>Eenheid</th></tr></thead>
113
+ return `<table class="tabel"><colgroup><col style="width:20%" /><col style="width:52%" /><col style="width:16%" /><col style="width:12%" /></colgroup>
114
+ <thead><tr class="onder"><th>Code</th><th>Omschrijving</th><th style="text-align:right">Aantal</th><th>Eenheid</th></tr></thead>
115
115
  <tbody>${regels.map(rij).join("")}</tbody></table>`;
116
116
  }
117
117
  function totalenBlok(regels, velden) {
@@ -236,21 +236,21 @@ export function renderProfielDocument(documenttype, config, gegevens, opties = {
236
236
  .map((groep) => groepHtml(groep, cfg, velden, data, opties))
237
237
  .filter(Boolean)
238
238
  .join("");
239
- return `<!doctype html><html lang="nl"><head><meta charset="utf-8" />
240
- <title>${esc(opties.titel ?? profiel.label)}</title>
241
- <style>
242
- @page { size: ${b}mm ${h}mm; margin: ${marge}mm; }
243
- * { box-sizing: border-box; }
244
- html, body { margin: 0; padding: 0; }
245
- body { font-family: Arial, Helvetica, sans-serif; font-size: 9pt; color: #111827; line-height: 1.35; }
246
- .blok { margin-bottom: 2.5mm; }
247
- .kop { border-bottom: 0.3mm solid #d1d5db; padding-bottom: 1mm; }
248
- .sectitel { font-size: 90%; font-weight: 600; text-transform: uppercase; color: #6b7280; margin-bottom: 0.6mm; }
249
- .vet { font-weight: 600; }
250
- .klein { font-size: 85%; color: #6b7280; }
251
- .kv { display: flex; justify-content: space-between; gap: 3mm; }
252
- .kv .k { color: #6b7280; }
253
- .tabel { width: 100%; border-collapse: collapse; table-layout: fixed; }
254
- .tabel th { text-align: left; font-weight: 600; }
239
+ return `<!doctype html><html lang="nl"><head><meta charset="utf-8" />
240
+ <title>${esc(opties.titel ?? profiel.label)}</title>
241
+ <style>
242
+ @page { size: ${b}mm ${h}mm; margin: ${marge}mm; }
243
+ * { box-sizing: border-box; }
244
+ html, body { margin: 0; padding: 0; }
245
+ body { font-family: Arial, Helvetica, sans-serif; font-size: 9pt; color: #111827; line-height: 1.35; }
246
+ .blok { margin-bottom: 2.5mm; }
247
+ .kop { border-bottom: 0.3mm solid #d1d5db; padding-bottom: 1mm; }
248
+ .sectitel { font-size: 90%; font-weight: 600; text-transform: uppercase; color: #6b7280; margin-bottom: 0.6mm; }
249
+ .vet { font-weight: 600; }
250
+ .klein { font-size: 85%; color: #6b7280; }
251
+ .kv { display: flex; justify-content: space-between; gap: 3mm; }
252
+ .kv .k { color: #6b7280; }
253
+ .tabel { width: 100%; border-collapse: collapse; table-layout: fixed; }
254
+ .tabel th { text-align: left; font-weight: 600; }
255
255
  </style></head><body>${kop}${body}</body></html>`;
256
256
  }
@@ -1,6 +1,14 @@
1
+ import type { SupabaseClient } from "@supabase/supabase-js";
2
+ type Db = SupabaseClient<any, any, any>;
1
3
  /**
2
- * Verwerkt een tick-verzoek: controleert de sleutel, houdt de shell-registratie
3
- * levend en drukt een paar wachtende opdrachten af.
4
+ * Verwerkt een tick-verzoek: controleert het toegangsbewijs, houdt de
5
+ * shell-registratie levend en drukt een paar wachtende opdrachten af.
6
+ *
7
+ * Toegestane vormen, in deze volgorde:
8
+ * 1. een runner-sleutel uit print_queue_runners.tick_sleutel (printrunners);
9
+ * 2. SUPABASE_PUBLISHABLE_KEY (de achtergrondtaak/cron);
10
+ * 3. een geldig gebruikerstoken van een ingelogde gebruiker (knop in de UI).
4
11
  */
5
- export declare function behandelQueueTick(request: Request): Promise<Response>;
12
+ export declare function behandelQueueTick(request: Request, supabase: Db): Promise<Response>;
13
+ export {};
6
14
  //# sourceMappingURL=queueTick.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"queueTick.d.ts","sourceRoot":"","sources":["../../src/lib/queueTick.ts"],"names":[],"mappings":"AAcA;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAmC3E"}
1
+ {"version":3,"file":"queueTick.d.ts","sourceRoot":"","sources":["../../src/lib/queueTick.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,KAAK,EAAE,GAAG,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAiBxC;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAiFzF"}
@@ -1,8 +1,7 @@
1
1
  // ============================================================================
2
2
  // src/lib/queueTick.ts — afhandeling van /api/public/print/queue-tick.
3
- // Wordt door de module geleverd zodat elke shell dit eindpunt met een
4
- // routebestandje van drie regels kan hosten. Bovenaan staan géén server-only
5
- // imports: die worden pas binnen de handler dynamisch geladen.
3
+ // De shell levert de databaseverbinding aan; deze module maakt er zelf nooit
4
+ // een. Zo kan een module nooit naar de database van een andere klant schrijven.
6
5
  // ============================================================================
7
6
  function gelijk(a, b) {
8
7
  if (a.length !== b.length)
@@ -12,33 +11,81 @@ function gelijk(a, b) {
12
11
  verschil |= a.charCodeAt(i) ^ b.charCodeAt(i);
13
12
  return verschil === 0;
14
13
  }
14
+ /** Haalt het meegestuurde toegangsbewijs uit de headers. */
15
+ function leesSleutel(request) {
16
+ return (request.headers.get("apikey") ??
17
+ (request.headers.get("authorization") ?? "").replace(/^Bearer\s+/i, "")).trim();
18
+ }
15
19
  /**
16
- * Verwerkt een tick-verzoek: controleert de sleutel, houdt de shell-registratie
17
- * levend en drukt een paar wachtende opdrachten af.
20
+ * Verwerkt een tick-verzoek: controleert het toegangsbewijs, houdt de
21
+ * shell-registratie levend en drukt een paar wachtende opdrachten af.
22
+ *
23
+ * Toegestane vormen, in deze volgorde:
24
+ * 1. een runner-sleutel uit print_queue_runners.tick_sleutel (printrunners);
25
+ * 2. SUPABASE_PUBLISHABLE_KEY (de achtergrondtaak/cron);
26
+ * 3. een geldig gebruikerstoken van een ingelogde gebruiker (knop in de UI).
18
27
  */
19
- export async function behandelQueueTick(request) {
28
+ export async function behandelQueueTick(request, supabase) {
29
+ if (!supabase) {
30
+ return Response.json({ ok: false, fout: "Achtergrondprinten is niet ingesteld: de server kreeg geen databaseverbinding." }, { status: 500 });
31
+ }
32
+ const meegegeven = leesSleutel(request);
20
33
  const projectSleutel = process.env["SUPABASE_PUBLISHABLE_KEY"] ??
21
34
  process.env["VITE_SUPABASE_PUBLISHABLE_KEY"] ??
22
35
  "";
23
- const meegegeven = request.headers.get("apikey") ??
24
- (request.headers.get("authorization") ?? "").replace(/^Bearer\s+/i, "");
25
- const { isRunnerSleutel, meldRunnerAan } = await import("./runnerRegistry.server");
26
- const toegestaan = !!meegegeven &&
27
- ((!!projectSleutel && gelijk(projectSleutel, meegegeven)) ||
28
- (await isRunnerSleutel(meegegeven)));
36
+ const geprobeerd = [];
37
+ const ontbrekend = [];
38
+ let toegestaan = false;
39
+ const { isRunnerSleutel, meldRunnerAan } = await import("./runnerRegistry.server.js");
40
+ if (meegegeven) {
41
+ geprobeerd.push("runner-sleutel");
42
+ toegestaan = await isRunnerSleutel(supabase, meegegeven);
43
+ if (!toegestaan) {
44
+ geprobeerd.push("publishable-key");
45
+ if (!projectSleutel)
46
+ ontbrekend.push("SUPABASE_PUBLISHABLE_KEY");
47
+ else
48
+ toegestaan = gelijk(projectSleutel, meegegeven);
49
+ }
50
+ if (!toegestaan) {
51
+ geprobeerd.push("gebruikerstoken");
52
+ try {
53
+ const { data } = await supabase.auth.getUser(meegegeven);
54
+ toegestaan = !!data?.user?.id;
55
+ }
56
+ catch {
57
+ toegestaan = false;
58
+ }
59
+ }
60
+ }
61
+ else {
62
+ ontbrekend.push("toegangsbewijs in de apikey- of authorization-header");
63
+ }
29
64
  if (!toegestaan) {
30
- return new Response(JSON.stringify({ ok: false }), {
31
- status: 401,
32
- headers: { "Content-Type": "application/json" },
33
- });
65
+ // Eén regel in de serverlogboeken, zonder ooit een sleutelwaarde te tonen.
66
+ console.warn(`[printwachtrij] tick geweigerd (401). Geprobeerd: ${geprobeerd.join(", ") || "geen"}. ` +
67
+ `Ontbrekende configuratie: ${ontbrekend.join(", ") || "geen"}.`);
68
+ return Response.json({
69
+ ok: false,
70
+ fout: ontbrekend.length > 0
71
+ ? `Het printeindpunt weigerde het verzoek. Ontbrekende configuratie: ${ontbrekend.join(", ")}.`
72
+ : "Het printeindpunt weigerde het verzoek: geen geldig toegangsbewijs.",
73
+ geprobeerd,
74
+ ontbrekend,
75
+ }, { status: 401 });
76
+ }
77
+ const { controleerClient, verwerkWachtrij } = await import("./printQueue.server.js");
78
+ const configFout = await controleerClient(supabase);
79
+ if (configFout) {
80
+ console.warn(`[printwachtrij] ${configFout}`);
81
+ return Response.json({ ok: false, fout: configFout }, { status: 500 });
34
82
  }
35
- void meldRunnerAan();
36
- const { verwerkWachtrij } = await import("./printQueue.server");
83
+ void meldRunnerAan(supabase);
37
84
  try {
38
- const resultaat = await verwerkWachtrij(5);
39
- return Response.json({ ok: true, ...resultaat });
85
+ const resultaat = await verwerkWachtrij(supabase, 5);
86
+ return Response.json({ ok: true, ...resultaat, ontbrekend });
40
87
  }
41
88
  catch (e) {
42
- return new Response(JSON.stringify({ ok: false, fout: e instanceof Error ? e.message : "Mislukt" }), { status: 500, headers: { "Content-Type": "application/json" } });
89
+ return Response.json({ ok: false, fout: e instanceof Error ? e.message : "Mislukt" }, { status: 500 });
43
90
  }
44
91
  }
@@ -0,0 +1,8 @@
1
+ export declare const QUEUE_TICK_PAD = "/api/public/print/queue-tick";
2
+ export interface TickAntwoord {
3
+ ok: boolean;
4
+ fout?: string;
5
+ }
6
+ /** Laat de wachtrij één ronde draaien. Geeft nooit een fout terug, alleen uitleg. */
7
+ export declare function vraagWachtrijRonde(): Promise<TickAntwoord>;
8
+ //# sourceMappingURL=queueTickClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queueTickClient.d.ts","sourceRoot":"","sources":["../../src/lib/queueTickClient.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,cAAc,iCAAiC,CAAC;AAE7D,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qFAAqF;AACrF,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,YAAY,CAAC,CA2BhE"}
@@ -0,0 +1,37 @@
1
+ // ============================================================================
2
+ // src/lib/queueTickClient.ts — de browser vraagt de shell om een tickronde.
3
+ // ----------------------------------------------------------------------------
4
+ // De browser krijgt nooit een databaseverbinding en gebruikt ook nooit de
5
+ // publishable key als toegangsbewijs: hij stuurt het token van de ingelogde
6
+ // gebruiker mee naar /api/public/print/queue-tick.
7
+ // ============================================================================
8
+ import { supabase } from "./supabaseClient.js";
9
+ export const QUEUE_TICK_PAD = "/api/public/print/queue-tick";
10
+ /** Laat de wachtrij één ronde draaien. Geeft nooit een fout terug, alleen uitleg. */
11
+ export async function vraagWachtrijRonde() {
12
+ try {
13
+ const { data } = await supabase.auth.getSession();
14
+ const token = data.session?.access_token;
15
+ if (!token) {
16
+ return { ok: false, fout: "Je bent niet (meer) ingelogd, dus de printwachtrij kan niet draaien." };
17
+ }
18
+ const res = await fetch(QUEUE_TICK_PAD, {
19
+ method: "POST",
20
+ headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
21
+ body: "{}",
22
+ });
23
+ const antwoord = (await res.json().catch(() => null));
24
+ if (res.ok && antwoord?.ok !== false)
25
+ return { ok: true };
26
+ return {
27
+ ok: false,
28
+ fout: antwoord?.fout ??
29
+ (res.status === 404
30
+ ? "Het printeindpunt /api/public/print/queue-tick bestaat niet in deze shell."
31
+ : `Achtergrondprinten werkt nu niet (${res.status}).`),
32
+ };
33
+ }
34
+ catch (e) {
35
+ return { ok: false, fout: e instanceof Error ? e.message : "Achtergrondprinten werkt nu niet." };
36
+ }
37
+ }
@@ -1,10 +1,11 @@
1
+ import type { PrintDb } from "./printQueue.server.js";
1
2
  /** Het eigen webadres, afgeleid uit het inkomende verzoek. */
2
3
  export declare function eigenBasisUrl(): string | null;
3
4
  /**
4
5
  * Meldt deze shell aan (of houdt hem levend). Doet hooguit één keer per tien
5
6
  * minuten iets en laat fouten nooit doorwerken in de aanroeper.
6
7
  */
7
- export declare function meldRunnerAan(): Promise<void>;
8
+ export declare function meldRunnerAan(db: PrintDb): Promise<void>;
8
9
  /** Controleert of de meegegeven sleutel bij een geregistreerde shell hoort. */
9
- export declare function isRunnerSleutel(sleutel: string): Promise<boolean>;
10
+ export declare function isRunnerSleutel(db: PrintDb, sleutel: string): Promise<boolean>;
10
11
  //# sourceMappingURL=runnerRegistry.server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runnerRegistry.server.d.ts","sourceRoot":"","sources":["../../src/lib/runnerRegistry.server.ts"],"names":[],"mappings":"AAYA,8DAA8D;AAC9D,wBAAgB,aAAa,IAAI,MAAM,GAAG,IAAI,CAS7C;AAED;;;GAGG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAkCnD;AAED,+EAA+E;AAC/E,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAcvE"}
1
+ {"version":3,"file":"runnerRegistry.server.d.ts","sourceRoot":"","sources":["../../src/lib/runnerRegistry.server.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAMnD,8DAA8D;AAC9D,wBAAgB,aAAa,IAAI,MAAM,GAAG,IAAI,CAS7C;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAiC9D;AAED,+EAA+E;AAC/E,wBAAsB,eAAe,CAAC,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAapF"}
@@ -25,7 +25,7 @@ export function eigenBasisUrl() {
25
25
  * Meldt deze shell aan (of houdt hem levend). Doet hooguit één keer per tien
26
26
  * minuten iets en laat fouten nooit doorwerken in de aanroeper.
27
27
  */
28
- export async function meldRunnerAan() {
28
+ export async function meldRunnerAan(db) {
29
29
  const basis = eigenBasisUrl();
30
30
  if (!basis)
31
31
  return;
@@ -35,20 +35,19 @@ export async function meldRunnerAan() {
35
35
  laatsteUrl = basis;
36
36
  laatsteMelding = nu;
37
37
  try {
38
- const { adminDb: supabaseAdmin } = await import("./supabaseAdmin.server");
39
- const { data } = await supabaseAdmin
38
+ const { data } = await db
40
39
  .from("print_queue_runners")
41
40
  .select("id")
42
41
  .eq("basis_url", basis)
43
42
  .maybeSingle();
44
43
  if (data?.id) {
45
- await supabaseAdmin
44
+ await db
46
45
  .from("print_queue_runners")
47
46
  .update({ laatst_gezien: new Date().toISOString(), actief: true })
48
47
  .eq("id", data.id);
49
48
  return;
50
49
  }
51
- await supabaseAdmin.from("print_queue_runners").insert({
50
+ await db.from("print_queue_runners").insert({
52
51
  basis_url: basis,
53
52
  laatst_gezien: new Date().toISOString(),
54
53
  actief: true,
@@ -60,12 +59,11 @@ export async function meldRunnerAan() {
60
59
  }
61
60
  }
62
61
  /** Controleert of de meegegeven sleutel bij een geregistreerde shell hoort. */
63
- export async function isRunnerSleutel(sleutel) {
62
+ export async function isRunnerSleutel(db, sleutel) {
64
63
  if (!sleutel || sleutel.length < 20)
65
64
  return false;
66
65
  try {
67
- const { adminDb: supabaseAdmin } = await import("./supabaseAdmin.server");
68
- const { data } = await supabaseAdmin
66
+ const { data } = await db
69
67
  .from("print_queue_runners")
70
68
  .select("id")
71
69
  .eq("tick_sleutel", sleutel)
@@ -1,6 +1,6 @@
1
- import { type SupabaseClient } from "@supabase/supabase-js";
2
- /** Uitleg voor de gebruiker als de serverinstellingen ontbreken. */
3
- export declare function adminConfiguratieFout(): string | null;
4
- /** Lazy adminclient: pas bij het eerste gebruik worden de instellingen gelezen. */
5
- export declare const adminDb: SupabaseClient<any, any, any, any, any>;
1
+ import { type SupabaseClient } from "@supabase/supabase-js";
2
+ /** Uitleg voor de gebruiker als de serverinstellingen ontbreken. */
3
+ export declare function adminConfiguratieFout(): string | null;
4
+ /** Lazy adminclient: pas bij het eerste gebruik worden de instellingen gelezen. */
5
+ export declare const adminDb: SupabaseClient<any, any, any, any, any>;
6
6
  //# sourceMappingURL=supabaseAdmin.server.d.ts.map
@@ -1,43 +1,43 @@
1
- // ============================================================================
2
- // src/lib/supabaseAdmin.server.ts — adminclient die in elke shell werkt.
3
- // Leest de service-role sleutel uit meerdere mogelijke namen, zodat de module
4
- // niet afhankelijk is van hoe een shell zijn omgeving heeft ingericht.
5
- // ============================================================================
6
- import { createClient } from "@supabase/supabase-js";
7
- function lees(...namen) {
8
- for (const naam of namen) {
9
- const waarde = process.env[naam];
10
- if (waarde && waarde.trim().length > 0)
11
- return waarde.trim();
12
- }
13
- return undefined;
14
- }
15
- /** Uitleg voor de gebruiker als de serverinstellingen ontbreken. */
16
- export function adminConfiguratieFout() {
17
- const url = lees("SUPABASE_URL", "VITE_SUPABASE_URL");
18
- const key = lees("SERVICE_ROLE_KEY", "SUPABASE_SERVICE_ROLE_KEY");
19
- if (url && key)
20
- return null;
21
- const mist = [!url ? "SUPABASE_URL" : null, !key ? "SERVICE_ROLE_KEY" : null]
22
- .filter(Boolean)
23
- .join(" en ");
24
- return `Achtergrondprinten is niet ingesteld: ${mist} ontbreekt in deze omgeving.`;
25
- }
26
- function maakClient() {
27
- const url = lees("SUPABASE_URL", "VITE_SUPABASE_URL");
28
- const key = lees("SERVICE_ROLE_KEY", "SUPABASE_SERVICE_ROLE_KEY");
29
- if (!url || !key)
30
- throw new Error(adminConfiguratieFout() ?? "Serverinstellingen ontbreken.");
31
- return createClient(url, key, {
32
- auth: { storage: undefined, persistSession: false, autoRefreshToken: false },
33
- });
34
- }
35
- let _client;
36
- /** Lazy adminclient: pas bij het eerste gebruik worden de instellingen gelezen. */
37
- export const adminDb = new Proxy({}, {
38
- get(_t, prop, receiver) {
39
- if (!_client)
40
- _client = maakClient();
41
- return Reflect.get(_client, prop, receiver);
42
- },
43
- });
1
+ // ============================================================================
2
+ // src/lib/supabaseAdmin.server.ts — adminclient die in elke shell werkt.
3
+ // Leest de service-role sleutel uit meerdere mogelijke namen, zodat de module
4
+ // niet afhankelijk is van hoe een shell zijn omgeving heeft ingericht.
5
+ // ============================================================================
6
+ import { createClient } from "@supabase/supabase-js";
7
+ function lees(...namen) {
8
+ for (const naam of namen) {
9
+ const waarde = process.env[naam];
10
+ if (waarde && waarde.trim().length > 0)
11
+ return waarde.trim();
12
+ }
13
+ return undefined;
14
+ }
15
+ /** Uitleg voor de gebruiker als de serverinstellingen ontbreken. */
16
+ export function adminConfiguratieFout() {
17
+ const url = lees("SUPABASE_URL", "VITE_SUPABASE_URL");
18
+ const key = lees("SERVICE_ROLE_KEY", "SUPABASE_SERVICE_ROLE_KEY");
19
+ if (url && key)
20
+ return null;
21
+ const mist = [!url ? "SUPABASE_URL" : null, !key ? "SERVICE_ROLE_KEY" : null]
22
+ .filter(Boolean)
23
+ .join(" en ");
24
+ return `Achtergrondprinten is niet ingesteld: ${mist} ontbreekt in deze omgeving.`;
25
+ }
26
+ function maakClient() {
27
+ const url = lees("SUPABASE_URL", "VITE_SUPABASE_URL");
28
+ const key = lees("SERVICE_ROLE_KEY", "SUPABASE_SERVICE_ROLE_KEY");
29
+ if (!url || !key)
30
+ throw new Error(adminConfiguratieFout() ?? "Serverinstellingen ontbreken.");
31
+ return createClient(url, key, {
32
+ auth: { storage: undefined, persistSession: false, autoRefreshToken: false },
33
+ });
34
+ }
35
+ let _client;
36
+ /** Lazy adminclient: pas bij het eerste gebruik worden de instellingen gelezen. */
37
+ export const adminDb = new Proxy({}, {
38
+ get(_t, prop, receiver) {
39
+ if (!_client)
40
+ _client = maakClient();
41
+ return Reflect.get(_client, prop, receiver);
42
+ },
43
+ });
@@ -1,4 +1,4 @@
1
1
  import type { SupabaseClient } from "@supabase/supabase-js";
2
- import type { Database } from "../integrations/supabase/types";
2
+ import type { Database } from "../integrations/supabase/types.js";
3
3
  export declare const supabase: SupabaseClient<Database>;
4
4
  //# sourceMappingURL=supabaseClient.d.ts.map
@@ -2,10 +2,10 @@
2
2
  // src/lib/testpagina.ts — een testpagina naar een printer sturen
3
3
  // ============================================================================
4
4
  import { toast } from "@flowselections/core";
5
- import { drukAf } from "./browserPrint";
6
- import { printDirect } from "./directPrint";
5
+ import { drukAf } from "./browserPrint.js";
6
+ import { printDirect } from "./directPrint.js";
7
7
  export async function drukTestpaginaAf(printerId, naam) {
8
- const html = `<div style="padding:20mm;font-size:14pt"><h1 style="font-size:20pt">Testpagina</h1>
8
+ const html = `<div style="padding:20mm;font-size:14pt"><h1 style="font-size:20pt">Testpagina</h1>
9
9
  <p>Deze pagina hoort uit: <strong>${naam}</strong></p></div>`;
10
10
  const opdracht = {
11
11
  documenttype: "pakbon",
@@ -1,4 +1,4 @@
1
- import type { LayoutElementModel, LayoutModel, PageSettings } from "./documentTypes";
1
+ import type { LayoutElementModel, LayoutModel, PageSettings } from "./documentTypes.js";
2
2
  export interface PrinterModel {
3
3
  id: string;
4
4
  naam: string;
@@ -3,7 +3,7 @@
3
3
  // ============================================================================
4
4
  import { useCallback, useEffect, useState } from "react";
5
5
  import { toast } from "@flowselections/core";
6
- import { supabase } from "./supabaseClient";
6
+ import { supabase } from "./supabaseClient.js";
7
7
  const arr = (v) => (Array.isArray(v) ? v : []);
8
8
  // --- Layouts ---------------------------------------------------------------
9
9
  export function useLayouts() {
@@ -2,7 +2,7 @@
2
2
  // src/lib/useNetwerkPrinters.ts — printers die in het netwerk gevonden worden
3
3
  // ============================================================================
4
4
  import { useCallback, useEffect, useState } from "react";
5
- import { netwerkPrinters } from "./printService.functions";
5
+ import { netwerkPrinters } from "./printService.functions.js";
6
6
  export function useNetwerkPrinters() {
7
7
  const [gevonden, setGevonden] = useState([]);
8
8
  const [bezig, setBezig] = useState(false);