@flowselections/layout-maker 1.62.3 → 1.63.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 (49) hide show
  1. package/dist-lib/components/BevestigDialog.d.ts +9 -0
  2. package/dist-lib/components/BevestigDialog.d.ts.map +1 -0
  3. package/dist-lib/components/BevestigDialog.js +24 -0
  4. package/dist-lib/components/LogosPage.d.ts.map +1 -1
  5. package/dist-lib/components/LogosPage.js +27 -5
  6. package/dist-lib/components/PrintenInstellenWizard.js +1 -1
  7. package/dist-lib/components/PrinterSetupWizard.d.ts.map +1 -1
  8. package/dist-lib/components/PrinterSetupWizard.js +3 -1
  9. package/dist-lib/components/PrintplekDetailPage.d.ts.map +1 -1
  10. package/dist-lib/components/PrintplekDetailPage.js +42 -4
  11. package/dist-lib/components/TestprintDialog.d.ts.map +1 -1
  12. package/dist-lib/components/TestprintDialog.js +15 -1
  13. package/dist-lib/components/WerkplekConfiguratiePage.js +2 -2
  14. package/dist-lib/components/WerkplekkenTab.d.ts.map +1 -1
  15. package/dist-lib/components/WerkplekkenTab.js +13 -6
  16. package/dist-lib/integrations/supabase/types.d.ts +125 -0
  17. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  18. package/dist-lib/lib/afbeeldingMaat.d.ts +10 -0
  19. package/dist-lib/lib/afbeeldingMaat.d.ts.map +1 -0
  20. package/dist-lib/lib/afbeeldingMaat.js +39 -0
  21. package/dist-lib/lib/etiketControle.d.ts +9 -1
  22. package/dist-lib/lib/etiketControle.d.ts.map +1 -1
  23. package/dist-lib/lib/etiketControle.js +21 -4
  24. package/dist-lib/lib/htmlNaarPdf.server.d.ts +4 -0
  25. package/dist-lib/lib/htmlNaarPdf.server.d.ts.map +1 -1
  26. package/dist-lib/lib/htmlNaarPdf.server.js +5 -1
  27. package/dist-lib/lib/htmlPdf.server.d.ts +6 -0
  28. package/dist-lib/lib/htmlPdf.server.d.ts.map +1 -1
  29. package/dist-lib/lib/htmlPdf.server.js +46 -10
  30. package/dist-lib/lib/logoLibrary.d.ts +25 -0
  31. package/dist-lib/lib/logoLibrary.d.ts.map +1 -1
  32. package/dist-lib/lib/logoLibrary.js +73 -1
  33. package/dist-lib/lib/opmaakLimiet.d.ts +8 -0
  34. package/dist-lib/lib/opmaakLimiet.d.ts.map +1 -0
  35. package/dist-lib/lib/opmaakLimiet.js +25 -0
  36. package/dist-lib/lib/printQueue.server.d.ts.map +1 -1
  37. package/dist-lib/lib/printQueue.server.js +81 -20
  38. package/dist-lib/lib/printService.functions.js +2 -2
  39. package/dist-lib/lib/printplekken.d.ts +17 -1
  40. package/dist-lib/lib/printplekken.d.ts.map +1 -1
  41. package/dist-lib/lib/printplekken.js +42 -3
  42. package/dist-lib/lib/profielHtml.js +1 -1
  43. package/dist-lib/lib/shellPoort.d.ts +1 -1
  44. package/dist-lib/lib/shellPoort.js +1 -1
  45. package/dist-lib/lib/stickerFormaat.d.ts +21 -0
  46. package/dist-lib/lib/stickerFormaat.d.ts.map +1 -0
  47. package/dist-lib/lib/stickerFormaat.js +39 -0
  48. package/dist-lib/lib/testprint.js +1 -1
  49. package/package.json +1 -1
@@ -0,0 +1,10 @@
1
+ /** Meer pixels dan dit laadt de server niet (ruim genoeg voor 300 dpi op A4-breedte). */
2
+ export declare const MAX_BEELD_PIXELS = 4000000;
3
+ /** Tijdslimiet voor het ophalen van één bestand. */
4
+ export declare const OPHAAL_LIMIET_MS = 10000;
5
+ export declare function beeldAfmeting(b: Uint8Array): {
6
+ breedte: number;
7
+ hoogte: number;
8
+ } | null;
9
+ export declare function teGrootBeeld(b: Uint8Array): string | null;
10
+ //# sourceMappingURL=afbeeldingMaat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"afbeeldingMaat.d.ts","sourceRoot":"","sources":["../../src/lib/afbeeldingMaat.ts"],"names":[],"mappings":"AAMA,yFAAyF;AACzF,eAAO,MAAM,gBAAgB,UAAY,CAAC;AAE1C,oDAAoD;AACpD,eAAO,MAAM,gBAAgB,QAAS,CAAC;AAEvC,wBAAgB,aAAa,CAAC,CAAC,EAAE,UAAU,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAoBvF;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAMzD"}
@@ -0,0 +1,39 @@
1
+ // ============================================================================
2
+ // src/lib/afbeeldingMaat.ts — afmeting (pixels) van een PNG/JPEG uit de kop,
3
+ // zonder het hele plaatje te decoderen. Een te groot plaatje (bijv. een logo
4
+ // van 5472 × 3648 px) laat de printronde op de server vastlopen.
5
+ // ============================================================================
6
+ /** Meer pixels dan dit laadt de server niet (ruim genoeg voor 300 dpi op A4-breedte). */
7
+ export const MAX_BEELD_PIXELS = 4000000;
8
+ /** Tijdslimiet voor het ophalen van één bestand. */
9
+ export const OPHAAL_LIMIET_MS = 10000;
10
+ export function beeldAfmeting(b) {
11
+ // PNG: 8 bytes handtekening, dan IHDR met breedte/hoogte.
12
+ if (b.length >= 24 && b[0] === 0x89 && b[1] === 0x50 && b[2] === 0x4e && b[3] === 0x47) {
13
+ const lees = (i) => ((b[i] << 24) | (b[i + 1] << 16) | (b[i + 2] << 8) | b[i + 3]) >>> 0;
14
+ return { breedte: lees(16), hoogte: lees(20) };
15
+ }
16
+ // JPEG: zoek het SOF-segment.
17
+ if (b.length > 4 && b[0] === 0xff && b[1] === 0xd8) {
18
+ let i = 2;
19
+ while (i + 9 < b.length) {
20
+ if (b[i] !== 0xff)
21
+ return null;
22
+ const m = b[i + 1];
23
+ const len = (b[i + 2] << 8) | b[i + 3];
24
+ if (m >= 0xc0 && m <= 0xcf && m !== 0xc4 && m !== 0xc8 && m !== 0xcc) {
25
+ return { hoogte: (b[i + 5] << 8) | b[i + 6], breedte: (b[i + 7] << 8) | b[i + 8] };
26
+ }
27
+ i += 2 + len;
28
+ }
29
+ }
30
+ return null;
31
+ }
32
+ export function teGrootBeeld(b) {
33
+ const a = beeldAfmeting(b);
34
+ if (!a)
35
+ return null;
36
+ return a.breedte * a.hoogte > MAX_BEELD_PIXELS
37
+ ? `Afbeelding te groot (${a.breedte} × ${a.hoogte} px); maximaal ${MAX_BEELD_PIXELS / 1000000} miljoen pixels`
38
+ : null;
39
+ }
@@ -3,7 +3,13 @@ export interface GeladenEtiket {
3
3
  naam: string;
4
4
  breedte_mm: number;
5
5
  hoogte_mm: number;
6
+ /** Vaste maat uit de standaardlijst: de printer kent geen formaatnaam, dus geen `paper` meesturen. */
7
+ standaard?: boolean;
6
8
  }
9
+ /** Vaste etiketmaten die altijd in de keuzelijst staan (naast wat de printer meldt). */
10
+ export declare const STANDAARD_ETIKETTEN: GeladenEtiket[];
11
+ /** Formaten van de printer plus de standaardmaten die de printer zelf niet meldt. */
12
+ export declare function etiketOptiesMetStandaard(papers: unknown): GeladenEtiket[];
7
13
  export type EtiketUitkomst = {
8
14
  ok: true;
9
15
  paper: string;
@@ -35,7 +41,9 @@ export declare function etiketPast(doc: {
35
41
  breedte_mm: number;
36
42
  hoogte_mm: number;
37
43
  soortLabel: string;
38
- }, geladen: GeladenEtiket | null, printerNaam: string): EtiketUitkomst;
44
+ }, geladen: GeladenEtiket | null, printerNaam: string,
45
+ /** Klantsticker: melding met maat, printer en wat je moet inleggen. */
46
+ sticker?: boolean): EtiketUitkomst;
39
47
  /** Leest de paginagrootte (mm) van de eerste pagina uit een PDF (MediaBox). */
40
48
  export declare function pdfPaginaMm(pdfBase64: string): {
41
49
  breedte_mm: number;
@@ -1 +1 @@
1
- {"version":3,"file":"etiketControle.d.ts","sourceRoot":"","sources":["../../src/lib/etiketControle.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,aAAa;IAC5B,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,cAAc,GACtB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,mBAAmB,GAAG,qBAAqB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAKtF,eAAO,MAAM,SAAS,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,WAA2B,CAAC;AAC1E,yDAAyD;AACzD,eAAO,MAAM,MAAM,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,WACmC,CAAC;AAC/E,iDAAiD;AACjD,eAAO,MAAM,WAAW,GAAI,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,WAC3B,CAAC;AAG5D,4DAA4D;AAC5D,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,OAAO,GAAG,aAAa,GAAG,IAAI,CAQlE;AAED,+EAA+E;AAC/E,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,aAAa,EAAE,CAW7D;AAED;;;GAGG;AACH,wBAAgB,UAAU,CACxB,GAAG,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,EAClE,OAAO,EAAE,aAAa,GAAG,IAAI,EAC7B,WAAW,EAAE,MAAM,GAClB,cAAc,CA6BhB;AAED,+EAA+E;AAC/E,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAa/F"}
1
+ {"version":3,"file":"etiketControle.d.ts","sourceRoot":"","sources":["../../src/lib/etiketControle.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,aAAa;IAC5B,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,sGAAsG;IACtG,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,wFAAwF;AACxF,eAAO,MAAM,mBAAmB,EAAE,aAAa,EAG9C,CAAC;AAEF,qFAAqF;AACrF,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,OAAO,GAAG,aAAa,EAAE,CAMzE;AAED,MAAM,MAAM,cAAc,GACtB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,mBAAmB,GAAG,qBAAqB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAKtF,eAAO,MAAM,SAAS,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,WAA2B,CAAC;AAC1E,yDAAyD;AACzD,eAAO,MAAM,MAAM,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,WACmC,CAAC;AAC/E,iDAAiD;AACjD,eAAO,MAAM,WAAW,GAAI,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,WAC3B,CAAC;AAG5D,4DAA4D;AAC5D,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,OAAO,GAAG,aAAa,GAAG,IAAI,CAQlE;AAED,+EAA+E;AAC/E,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,aAAa,EAAE,CAW7D;AAED;;;GAGG;AACH,wBAAgB,UAAU,CACxB,GAAG,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,EAClE,OAAO,EAAE,aAAa,GAAG,IAAI,EAC7B,WAAW,EAAE,MAAM;AACnB,uEAAuE;AACvE,OAAO,UAAQ,GACd,cAAc,CAgChB;AAED,+EAA+E;AAC/E,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAa/F"}
@@ -6,6 +6,18 @@
6
6
  // rol die er écht in zit. Daarom kiest de beheerder per labelprinter het
7
7
  // "geladen etiket" en controleren we daartegen. Nooit stil schalen.
8
8
  // ============================================================================
9
+ /** Vaste etiketmaten die altijd in de keuzelijst staan (naast wat de printer meldt). */
10
+ export const STANDAARD_ETIKETTEN = [
11
+ { naam: "Etiket 40 × 40 mm", breedte_mm: 40, hoogte_mm: 40, standaard: true },
12
+ { naam: "Etiket 50 × 50 mm", breedte_mm: 50, hoogte_mm: 50, standaard: true },
13
+ ];
14
+ /** Formaten van de printer plus de standaardmaten die de printer zelf niet meldt. */
15
+ export function etiketOptiesMetStandaard(papers) {
16
+ const eigen = etiketOpties(papers);
17
+ const zelfde = (a, b) => (Math.abs(a.breedte_mm - b.breedte_mm) < 0.6 && Math.abs(a.hoogte_mm - b.hoogte_mm) < 0.6) ||
18
+ (Math.abs(a.breedte_mm - b.hoogte_mm) < 0.6 && Math.abs(a.hoogte_mm - b.breedte_mm) < 0.6);
19
+ return [...eigen, ...STANDAARD_ETIKETTEN.filter((s) => !eigen.some((e) => zelfde(e, s)))];
20
+ }
9
21
  const MARGE_MM = 2;
10
22
  const mm = (n) => Math.round(n * 10) / 10;
11
23
  export const maatTekst = (b, h) => `${mm(b)}×${mm(h)} mm`;
@@ -24,7 +36,7 @@ export function leesGeladenEtiket(v) {
24
36
  const naam = String(r.naam ?? "").trim();
25
37
  if (!naam || !(b > 0) || !(h > 0))
26
38
  return null;
27
- return { naam, breedte_mm: b, hoogte_mm: h };
39
+ return r.standaard === true ? { naam, breedte_mm: b, hoogte_mm: h, standaard: true } : { naam, breedte_mm: b, hoogte_mm: h };
28
40
  }
29
41
  /** PrintNode-formaten (tienden mm) als keuzelijst in mm, zonder lege maten. */
30
42
  export function etiketOpties(papers) {
@@ -46,7 +58,9 @@ export function etiketOpties(papers) {
46
58
  * Past een document van breedte×hoogte (mm) op het geladen etiket? Draaien
47
59
  * mag (liggend etiket, staande layout of andersom), schalen nooit.
48
60
  */
49
- export function etiketPast(doc, geladen, printerNaam) {
61
+ export function etiketPast(doc, geladen, printerNaam,
62
+ /** Klantsticker: melding met maat, printer en wat je moet inleggen. */
63
+ sticker = false) {
50
64
  if (!geladen) {
51
65
  return {
52
66
  ok: false,
@@ -61,7 +75,10 @@ export function etiketPast(doc, geladen, printerNaam) {
61
75
  return {
62
76
  ok: false,
63
77
  code: "FORMAAT_PAST_NIET",
64
- bericht: `Past niet op het etiket in de printer (${heel(b, h)} op ${heel(geladen.breedte_mm, geladen.hoogte_mm)}).`,
78
+ bericht: sticker
79
+ ? `Klantsticker ${heel(b, h)} past niet op het etiket in ${printerNaam} (${heel(geladen.breedte_mm, geladen.hoogte_mm)}). ` +
80
+ `Leg etiketten van minimaal ${heel(b, h)} in of kies een andere printer.`
81
+ : `Past niet op het etiket in de printer (${heel(b, h)} op ${heel(geladen.breedte_mm, geladen.hoogte_mm)}).`,
65
82
  };
66
83
  }
67
84
  const docLiggend = b > h;
@@ -69,7 +86,7 @@ export function etiketPast(doc, geladen, printerNaam) {
69
86
  const rotate = !recht || docLiggend !== etiketLiggend ? 90 : 0;
70
87
  return {
71
88
  ok: true,
72
- paper: geladen.naam,
89
+ paper: geladen.standaard ? "" : geladen.naam,
73
90
  rotate,
74
91
  uitleg: `geladen etiket ${geladen.naam.trim()} (${maatTekst(geladen.breedte_mm, geladen.hoogte_mm)})${rotate ? ", gedraaid" : ""}`,
75
92
  };
@@ -1,3 +1,5 @@
1
+ import { AfbeeldingInhoudFout } from "./htmlPdf.server.js";
2
+ export { AfbeeldingInhoudFout };
1
3
  export declare class PdfRenderFout extends Error {
2
4
  code: "niet_ingesteld" | "mislukt" | "afwijking";
3
5
  constructor(code: "niet_ingesteld" | "mislukt" | "afwijking", boodschap: string);
@@ -8,6 +10,8 @@ export interface PdfOpties {
8
10
  hoogteMm?: number;
9
11
  margeMm?: number;
10
12
  landschap?: boolean;
13
+ /** Melding per weggelaten decoratie-afbeelding (zoals een logo). */
14
+ bijOvergeslagen?: (src: string, reden: string) => void;
11
15
  }
12
16
  /** Levert de PDF als base64-tekst (zonder data:-prefix). */
13
17
  export declare function htmlNaarPdfServer(opties: PdfOpties): Promise<string>;
@@ -1 +1 @@
1
- {"version":3,"file":"htmlNaarPdf.server.d.ts","sourceRoot":"","sources":["../../src/lib/htmlNaarPdf.server.ts"],"names":[],"mappings":"AAQA,qBAAa,aAAc,SAAQ,KAAK;IAE7B,IAAI,EAAE,gBAAgB,GAAG,SAAS,GAAG,WAAW;gBAAhD,IAAI,EAAE,gBAAgB,GAAG,SAAS,GAAG,WAAW,EACvD,SAAS,EAAE,MAAM;CAKpB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,4DAA4D;AAC5D,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAqB1E"}
1
+ {"version":3,"file":"htmlNaarPdf.server.d.ts","sourceRoot":"","sources":["../../src/lib/htmlNaarPdf.server.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,oBAAoB,EAAqC,MAAM,kBAAkB,CAAC;AAC3F,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAEhC,qBAAa,aAAc,SAAQ,KAAK;IAE7B,IAAI,EAAE,gBAAgB,GAAG,SAAS,GAAG,WAAW;gBAAhD,IAAI,EAAE,gBAAgB,GAAG,SAAS,GAAG,WAAW,EACvD,SAAS,EAAE,MAAM;CAKpB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,oEAAoE;IACpE,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACxD;AAED,4DAA4D;AAC5D,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAuB1E"}
@@ -3,7 +3,8 @@
3
3
  // Gebruikt de eigen documentmaker (src/lib/htmlPdf.server.ts). Geen externe
4
4
  // dienst, geen browser en geen instellingen per shell nodig.
5
5
  // ============================================================================
6
- import { bytesNaarBase64, htmlNaarPdfBytes } from "./htmlPdf.server.js";
6
+ import { AfbeeldingInhoudFout, bytesNaarBase64, htmlNaarPdfBytes } from "./htmlPdf.server.js";
7
+ export { AfbeeldingInhoudFout };
7
8
  export class PdfRenderFout extends Error {
8
9
  constructor(code, boodschap) {
9
10
  super(boodschap);
@@ -23,12 +24,15 @@ export async function htmlNaarPdfServer(opties) {
23
24
  hoogteMm: opties.hoogteMm ?? 297,
24
25
  margeMm: opties.margeMm ?? 10,
25
26
  landschap: opties.landschap ?? false,
27
+ bijOvergeslagen: opties.bijOvergeslagen,
26
28
  });
27
29
  if (!bytes.length)
28
30
  throw new Error("De PDF is leeg gebleven.");
29
31
  return bytesNaarBase64(bytes);
30
32
  }
31
33
  catch (e) {
34
+ if (e instanceof AfbeeldingInhoudFout)
35
+ throw e;
32
36
  const melding = e instanceof Error ? e.message : "PDF maken mislukte.";
33
37
  throw new PdfRenderFout(melding.startsWith("Afdrukafwijking gevonden:") ? "afwijking" : "mislukt", melding.startsWith("Afdrukafwijking gevonden:") ? melding : `PDF maken mislukte: ${melding}`);
34
38
  }
@@ -1,3 +1,7 @@
1
+ /** De afbeelding is de inhoud zelf en kon niet worden gebruikt: niet printen. */
2
+ export declare class AfbeeldingInhoudFout extends Error {
3
+ name: string;
4
+ }
1
5
  import { type RGB } from "pdf-lib";
2
6
  export declare const MM = 2.834645669291339;
3
7
  export interface Knoop {
@@ -40,6 +44,8 @@ export interface DocumentPdfOpties {
40
44
  landschap?: boolean;
41
45
  /** Voettekst met paginanummers ("Pagina 1 van 3"). */
42
46
  paginanummers?: boolean;
47
+ /** Melding per weggelaten decoratie-afbeelding (voor het logboek). */
48
+ bijOvergeslagen?: (src: string, reden: string) => void;
43
49
  }
44
50
  export interface PdfRenderDiagnostiek {
45
51
  geldig: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"htmlPdf.server.d.ts","sourceRoot":"","sources":["../../src/lib/htmlPdf.server.ts"],"names":[],"mappings":"AAYA,OAAO,EAOL,KAAK,GAAG,EACT,MAAM,SAAS,CAAC;AAEjB,eAAO,MAAM,EAAE,oBAAoB,CAAC;AAIpC,MAAM,WAAW,KAAK;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,QAAQ,EAAE,KAAK,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAuBD,kEAAkE;AAClE,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAuC/C;AAUD,UAAU,SAAS;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AACD,UAAU,QAAQ;IAChB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED,sEAAsE;AACtE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMpD;AA2BD,yFAAyF;AACzF,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,EAAE,CAgClD;AAqBD,6EAA6E;AAC7E,wBAAgB,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAiBlE;AAKD,MAAM,WAAW,KAAK;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,OAAO,CAAC;IACb,KAAK,EAAE,GAAG,CAAC;IACX,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IACxC,mDAAmD;IACnD,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAypCD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,sDAAsD;IACtD,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,CA8BtE;AAED,+EAA+E;AAC/E,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,CA6ErF;AA0BD,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAQzD"}
1
+ {"version":3,"file":"htmlPdf.server.d.ts","sourceRoot":"","sources":["../../src/lib/htmlPdf.server.ts"],"names":[],"mappings":"AAcA,iFAAiF;AACjF,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,IAAI,SAA0B;CAC/B;AACD,OAAO,EAOL,KAAK,GAAG,EACT,MAAM,SAAS,CAAC;AAEjB,eAAO,MAAM,EAAE,oBAAoB,CAAC;AAIpC,MAAM,WAAW,KAAK;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,QAAQ,EAAE,KAAK,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAuBD,kEAAkE;AAClE,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAuC/C;AAUD,UAAU,SAAS;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AACD,UAAU,QAAQ;IAChB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED,sEAAsE;AACtE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMpD;AA2BD,yFAAyF;AACzF,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,EAAE,CAgClD;AAqBD,6EAA6E;AAC7E,wBAAgB,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAiBlE;AAKD,MAAM,WAAW,KAAK;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,OAAO,CAAC;IACb,KAAK,EAAE,GAAG,CAAC;IACX,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IACxC,mDAAmD;IACnD,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAkrCD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,sDAAsD;IACtD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,sEAAsE;IACtE,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACxD;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,CA8BtE;AAED,+EAA+E;AAC/E,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,CAmFrF;AA0BD,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAQzD"}
@@ -9,6 +9,14 @@
9
9
  // afbeeldingen, barcodes en QR-vlakken.
10
10
  // ============================================================================
11
11
  import { code128Bars } from "./code128.js";
12
+ import { OPHAAL_LIMIET_MS, teGrootBeeld } from "./afbeeldingMaat.js";
13
+ /** De afbeelding is de inhoud zelf en kon niet worden gebruikt: niet printen. */
14
+ export class AfbeeldingInhoudFout extends Error {
15
+ constructor() {
16
+ super(...arguments);
17
+ this.name = "AfbeeldingInhoudFout";
18
+ }
19
+ }
12
20
  import { PDFDocument, StandardFonts, rgb, } from "pdf-lib";
13
21
  export const MM = 2.834645669291339; // punten per millimeter
14
22
  const LEEG = new Set(["img", "br", "hr", "col", "meta", "link", "input"]);
@@ -788,6 +796,8 @@ async function tekenAfbeelding(ctx, n, vak, s) {
788
796
  const tk = ctx.tk;
789
797
  const src = n.attrs["src"] ?? "";
790
798
  const afb = ctx.afbeeldingen.get(src);
799
+ if (!afb && ctx.weglaten?.has(src))
800
+ return;
791
801
  const hoogte = lengte(eig(n)["height"]) ?? 18 * MM;
792
802
  if (!afb) {
793
803
  // Een leeg vlak vertelt niemand dat er iets misging: melding op de afdruk.
@@ -1249,17 +1259,22 @@ function base64NaarBytes(b64) {
1249
1259
  out[i] = bin.charCodeAt(i);
1250
1260
  return out;
1251
1261
  }
1252
- function verzamelBronnen(n, uit) {
1253
- if (n.tag === "img" && n.attrs["src"])
1262
+ function verzamelBronnen(n, uit, inhoud) {
1263
+ if (n.tag === "img" && n.attrs["src"]) {
1254
1264
  uit.add(n.attrs["src"]);
1265
+ if (n.attrs["data-inhoud"] === "1")
1266
+ inhoud.add(n.attrs["src"]);
1267
+ }
1255
1268
  for (const k of n.kinderen)
1256
- verzamelBronnen(k, uit);
1269
+ verzamelBronnen(k, uit, inhoud);
1257
1270
  }
1258
1271
  async function laadAfbeeldingen(pdf, wortel) {
1259
1272
  const bronnen = new Set();
1260
- verzamelBronnen(wortel, bronnen);
1273
+ const inhoud = new Set();
1274
+ verzamelBronnen(wortel, bronnen, inhoud);
1261
1275
  const beelden = new Map();
1262
- const fouten = new Map();
1276
+ const alleFouten = new Map();
1277
+ const fouten = { set: (s, r) => alleFouten.set(s, r) };
1263
1278
  await Promise.all([...bronnen].slice(0, 20).map(async (src) => {
1264
1279
  try {
1265
1280
  let bytes;
@@ -1274,7 +1289,14 @@ async function laadAfbeeldingen(pdf, wortel) {
1274
1289
  bytes = base64NaarBytes(src.slice(komma + 1));
1275
1290
  }
1276
1291
  else if (/^https?:/i.test(src)) {
1277
- const res = await fetch(src);
1292
+ let res;
1293
+ try {
1294
+ res = await fetch(src, { signal: AbortSignal.timeout(OPHAAL_LIMIET_MS) });
1295
+ }
1296
+ catch {
1297
+ fouten.set(src, `Afbeelding niet binnen ${OPHAAL_LIMIET_MS / 1000} seconden opgehaald`);
1298
+ return;
1299
+ }
1278
1300
  if (!res.ok) {
1279
1301
  fouten.set(src, `Afbeelding niet opgehaald (${res.status})`);
1280
1302
  return;
@@ -1291,6 +1313,11 @@ async function laadAfbeeldingen(pdf, wortel) {
1291
1313
  fouten.set(src, "Onbekende afbeeldingsbron");
1292
1314
  return;
1293
1315
  }
1316
+ const teGroot = teGrootBeeld(bytes);
1317
+ if (teGroot) {
1318
+ fouten.set(src, teGroot);
1319
+ return;
1320
+ }
1294
1321
  const afb = png ? await pdf.embedPng(bytes) : await pdf.embedJpg(bytes);
1295
1322
  beelden.set(src, afb);
1296
1323
  }
@@ -1298,7 +1325,11 @@ async function laadAfbeeldingen(pdf, wortel) {
1298
1325
  fouten.set(src, e instanceof Error ? `Afbeelding onleesbaar: ${e.message}` : "Afbeelding onleesbaar");
1299
1326
  }
1300
1327
  }));
1301
- return { beelden, fouten };
1328
+ const inhoudFouten = new Map();
1329
+ const overgeslagen = new Map();
1330
+ for (const [src, r] of alleFouten)
1331
+ (inhoud.has(src) ? inhoudFouten : overgeslagen).set(src, r);
1332
+ return { beelden, fouten: inhoudFouten, overgeslagen };
1302
1333
  }
1303
1334
  /**
1304
1335
  * Bewaakt constructies die de eigen PDF-motor niet hetzelfde kan uitleggen als
@@ -1367,13 +1398,18 @@ export async function htmlNaarPdfBytes(opties) {
1367
1398
  // De opmaak uit het <style>-blok wordt hier per element uitgerekend, zodat
1368
1399
  // het document er hetzelfde uitziet als in het voorbeeld op het scherm.
1369
1400
  stempelCss(wortel, ontleedCss(leesStylesheets(opties.html)));
1370
- const { beelden: afbeeldingen, fouten: beeldFouten } = await laadAfbeeldingen(pdf, wortel);
1401
+ const { beelden: afbeeldingen, fouten: beeldFouten, overgeslagen } = await laadAfbeeldingen(pdf, wortel);
1371
1402
  if (beeldFouten.size) {
1372
- throw new Error(`Afdrukafwijking gevonden: ${[...beeldFouten.values()].join(" ")}`);
1403
+ // De afbeelding is de inhoud zelf (sticker, productfoto): niet printen.
1404
+ throw new AfbeeldingInhoudFout(`De afbeelding van dit document kon niet worden gebruikt; er is niets geprint. (${[...beeldFouten.values()].join(" ")})`);
1373
1405
  }
1406
+ for (const [src, reden] of overgeslagen)
1407
+ opties.bijOvergeslagen?.(src, reden);
1408
+ // Decoratie (zoals een logo) wordt weggelaten in plaats van te blokkeren.
1409
+ const afbeeldingenWeg = new Set(overgeslagen.keys());
1374
1410
  const basis = basisGrootte(opties.html);
1375
1411
  const tk = new Tekenaar(pdf, breedte, hoogte, marge, normaal, vet);
1376
- const ctx = { tk, afbeeldingen, beeldFouten };
1412
+ const ctx = { tk, afbeeldingen, beeldFouten, weglaten: afbeeldingenWeg };
1377
1413
  const stijl = { grootte: basis, vet: false, kleur: DONKER, uitlijning: "left" };
1378
1414
  // vaste paginavoet (bijv. totalen op elke pagina) — als volwaardig blok
1379
1415
  const voetVak = { x: marge, breedte: breedte - marge * 2 };
@@ -33,6 +33,8 @@ export interface LogoModel {
33
33
  transparant: boolean;
34
34
  is_standaard: boolean;
35
35
  hash: string | null;
36
+ /** pad van het bewaarde origineel na verkleinen (terug te zetten) */
37
+ origineel_pad?: string | null;
36
38
  created_at: string;
37
39
  updated_at: string;
38
40
  /** tijdelijke, ondertekende weergave-URL */
@@ -76,6 +78,29 @@ export declare function maakLogo(input: UploadInput): Promise<LogoModel>;
76
78
  export declare function werkLogoBij(id: string, patch: Partial<LogoModel>): Promise<void>;
77
79
  /** Vervangt het bestand van een bestaand logo — alle layouts volgen automatisch. */
78
80
  export declare function vervangLogoBestand(logo: LogoModel, file: File): Promise<void>;
81
+ /** Maximale breedte van een logo in de bibliotheek; groter is op papier niet nodig. */
82
+ export declare const LOGO_MAX_BREEDTE = 1500;
83
+ /** Nieuwe maat bij verkleinen, of null als het logo al klein genoeg is. */
84
+ export declare function berekenVerkleining(breedte: number, hoogte: number, max?: number): {
85
+ breedte: number;
86
+ hoogte: number;
87
+ } | null;
88
+ export interface LogoVerkleining {
89
+ bestand: File;
90
+ verkleind: boolean;
91
+ van?: {
92
+ breedte: number;
93
+ hoogte: number;
94
+ };
95
+ naar?: {
96
+ breedte: number;
97
+ hoogte: number;
98
+ };
99
+ }
100
+ /** Verkleint een raster-logo (PNG/JPEG/WebP) tot maximaal 1500 px breed. SVG blijft ongewijzigd. */
101
+ export declare function verkleinLogoVoorUpload(file: File): Promise<LogoVerkleining>;
102
+ /** Zet het bewaarde originele bestand van een verkleind logo terug. */
103
+ export declare function zetOrigineelTerug(logo: LogoModel): Promise<void>;
79
104
  export declare function verwijderLogo(logo: LogoModel): Promise<void>;
80
105
  export declare function downloadLogo(logo: LogoModel): Promise<void>;
81
106
  export declare function formatteerBytes(n: number): string;
@@ -1 +1 @@
1
- {"version":3,"file":"logoLibrary.d.ts","sourceRoot":"","sources":["../../src/lib/logoLibrary.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"logoLibrary.d.ts","sourceRoot":"","sources":["../../src/lib/logoLibrary.ts"],"names":[],"mappings":"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"}
@@ -244,7 +244,79 @@ export async function vervangLogoBestand(logo, file) {
244
244
  .eq("id", logo.id);
245
245
  if (error)
246
246
  throw error;
247
- if (oud)
247
+ if (oud && oud !== logo.origineel_pad)
248
+ await supabase.storage.from(LOGO_BUCKET).remove([oud]);
249
+ }
250
+ /** Maximale breedte van een logo in de bibliotheek; groter is op papier niet nodig. */
251
+ export const LOGO_MAX_BREEDTE = 1500;
252
+ /** Nieuwe maat bij verkleinen, of null als het logo al klein genoeg is. */
253
+ export function berekenVerkleining(breedte, hoogte, max = LOGO_MAX_BREEDTE) {
254
+ if (!(breedte > max) || !(hoogte > 0))
255
+ return null;
256
+ return { breedte: max, hoogte: Math.max(1, Math.round((hoogte * max) / breedte)) };
257
+ }
258
+ /** Verkleint een raster-logo (PNG/JPEG/WebP) tot maximaal 1500 px breed. SVG blijft ongewijzigd. */
259
+ export async function verkleinLogoVoorUpload(file) {
260
+ if (file.type === "image/svg+xml" || typeof document === "undefined") {
261
+ return { bestand: file, verkleind: false };
262
+ }
263
+ const url = URL.createObjectURL(file);
264
+ try {
265
+ const img = await new Promise((resolve, reject) => {
266
+ const i = new Image();
267
+ i.onload = () => resolve(i);
268
+ i.onerror = () => reject(new Error("Afbeelding kon niet worden gelezen"));
269
+ i.src = url;
270
+ });
271
+ const van = { breedte: img.naturalWidth, hoogte: img.naturalHeight };
272
+ const naar = berekenVerkleining(van.breedte, van.hoogte);
273
+ if (!naar)
274
+ return { bestand: file, verkleind: false };
275
+ const c = document.createElement("canvas");
276
+ c.width = naar.breedte;
277
+ c.height = naar.hoogte;
278
+ const ctx = c.getContext("2d");
279
+ if (!ctx)
280
+ return { bestand: file, verkleind: false };
281
+ ctx.imageSmoothingQuality = "high";
282
+ ctx.drawImage(img, 0, 0, naar.breedte, naar.hoogte);
283
+ const type = file.type === "image/jpeg" || file.type === "image/webp" ? file.type : "image/png";
284
+ const blob = await new Promise((r) => c.toBlob(r, type, 0.92));
285
+ if (!blob)
286
+ return { bestand: file, verkleind: false };
287
+ return { bestand: new File([blob], file.name, { type }), verkleind: true, van, naar };
288
+ }
289
+ finally {
290
+ URL.revokeObjectURL(url);
291
+ }
292
+ }
293
+ /** Zet het bewaarde originele bestand van een verkleind logo terug. */
294
+ export async function zetOrigineelTerug(logo) {
295
+ const pad = logo.origineel_pad;
296
+ if (!pad)
297
+ throw new Error("Er is geen origineel bewaard voor dit logo");
298
+ const { data, error } = await supabase.storage.from(LOGO_BUCKET).download(pad);
299
+ if (error || !data)
300
+ throw vertaalOpslagFout(error ?? new Error("Origineel niet gevonden"));
301
+ const file = new File([data], pad, { type: data.type || "image/png" });
302
+ const { breedte, hoogte, transparant } = await leesAfmetingen(file);
303
+ const oud = logo.bestandspad ?? logo.bestand_url;
304
+ const { error: e2 } = await supabase
305
+ .from("layout_logos")
306
+ .update({
307
+ bestand_url: pad,
308
+ bestandspad: pad,
309
+ breedte,
310
+ hoogte,
311
+ bestandsgrootte: file.size,
312
+ transparant,
313
+ hash: await bestandHash(file),
314
+ origineel_pad: null,
315
+ })
316
+ .eq("id", logo.id);
317
+ if (e2)
318
+ throw e2;
319
+ if (oud && oud !== pad)
248
320
  await supabase.storage.from(LOGO_BUCKET).remove([oud]);
249
321
  }
250
322
  export async function verwijderLogo(logo) {
@@ -0,0 +1,8 @@
1
+ export declare const OPMAAK_LIMIET_MS = 30000;
2
+ export declare const OPMAAK_TE_LANG_TEKST = "Het opmaken van dit document duurde te lang. Probeer het opnieuw; blijft het gebeuren, neem contact op met beheer.";
3
+ export declare class OpmaakTeLangFout extends Error {
4
+ name: string;
5
+ constructor();
6
+ }
7
+ export declare function metTijdslimiet<T>(ms: number, werk: () => Promise<T>): Promise<T>;
8
+ //# sourceMappingURL=opmaakLimiet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opmaakLimiet.d.ts","sourceRoot":"","sources":["../../src/lib/opmaakLimiet.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,gBAAgB,QAAS,CAAC;AAEvC,eAAO,MAAM,oBAAoB,uHACqF,CAAC;AAEvH,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,IAAI,SAAsB;;CAI3B;AAED,wBAAsB,cAAc,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAUtF"}
@@ -0,0 +1,25 @@
1
+ // ============================================================================
2
+ // src/lib/opmaakLimiet.ts — het opmaken van één document mag niet langer dan
3
+ // 30 seconden duren. Daarna een duidelijke fout in plaats van 10 minuten stil.
4
+ // ============================================================================
5
+ export const OPMAAK_LIMIET_MS = 30000;
6
+ export const OPMAAK_TE_LANG_TEKST = "Het opmaken van dit document duurde te lang. Probeer het opnieuw; blijft het gebeuren, neem contact op met beheer.";
7
+ export class OpmaakTeLangFout extends Error {
8
+ constructor() {
9
+ super(OPMAAK_TE_LANG_TEKST);
10
+ this.name = "OpmaakTeLangFout";
11
+ }
12
+ }
13
+ export async function metTijdslimiet(ms, werk) {
14
+ let klok;
15
+ const grens = new Promise((_, weiger) => {
16
+ klok = setTimeout(() => weiger(new OpmaakTeLangFout()), ms);
17
+ });
18
+ try {
19
+ return await Promise.race([werk(), grens]);
20
+ }
21
+ finally {
22
+ if (klok)
23
+ clearTimeout(klok);
24
+ }
25
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"printQueue.server.d.ts","sourceRoot":"","sources":["../../src/lib/printQueue.server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"printQueue.server.d.ts","sourceRoot":"","sources":["../../src/lib/printQueue.server.ts"],"names":[],"mappings":"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"}