@flowselections/layout-maker 1.53.4 → 1.55.1
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/LivePrintstatusRegel.d.ts.map +1 -1
- package/dist-lib/components/LivePrintstatusRegel.js +17 -7
- package/dist-lib/components/PrintQueuePage.d.ts.map +1 -1
- package/dist-lib/components/PrintQueuePage.js +22 -6
- package/dist-lib/components/TestprintDialog.d.ts.map +1 -1
- package/dist-lib/components/TestprintDialog.js +3 -2
- package/dist-lib/index.d.ts +2 -1
- package/dist-lib/index.d.ts.map +1 -1
- package/dist-lib/index.js +1 -0
- package/dist-lib/integrations/supabase/types.d.ts +84 -0
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/foutTekst.d.ts +2 -0
- package/dist-lib/lib/foutTekst.d.ts.map +1 -1
- package/dist-lib/lib/foutTekst.js +13 -1
- package/dist-lib/lib/orderData.server.d.ts.map +1 -1
- package/dist-lib/lib/orderData.server.js +31 -3
- package/dist-lib/lib/pakbonHtml.d.ts +2 -0
- package/dist-lib/lib/pakbonHtml.d.ts.map +1 -1
- package/dist-lib/lib/pakbonHtml.js +23 -4
- package/dist-lib/lib/printApi.d.ts +20 -0
- package/dist-lib/lib/printApi.d.ts.map +1 -1
- package/dist-lib/lib/printApi.js +19 -0
- package/dist-lib/lib/printQueue.server.d.ts +11 -2
- package/dist-lib/lib/printQueue.server.d.ts.map +1 -1
- package/dist-lib/lib/printQueue.server.js +78 -19
- package/dist-lib/lib/printService.functions.d.ts +16 -0
- package/dist-lib/lib/printService.functions.d.ts.map +1 -1
- package/dist-lib/lib/printService.functions.js +7 -1
- package/dist-lib/lib/printnodeStatus.d.ts +2 -0
- package/dist-lib/lib/printnodeStatus.d.ts.map +1 -1
- package/dist-lib/lib/printnodeStatus.js +6 -0
- package/dist-lib/lib/printnodeWebhook.d.ts +9 -8
- package/dist-lib/lib/printnodeWebhook.d.ts.map +1 -1
- package/dist-lib/lib/printnodeWebhook.js +84 -58
- package/dist-lib/lib/printnodeWebhookBeheer.server.d.ts +35 -0
- package/dist-lib/lib/printnodeWebhookBeheer.server.d.ts.map +1 -1
- package/dist-lib/lib/printnodeWebhookBeheer.server.js +103 -2
- package/dist-lib/lib/printnodeWebhookRoute.d.ts +2 -0
- package/dist-lib/lib/printnodeWebhookRoute.d.ts.map +1 -0
- package/dist-lib/lib/printnodeWebhookRoute.js +5 -0
- package/package.json +13 -1
|
@@ -16,108 +16,134 @@ function gelijk(a, b) {
|
|
|
16
16
|
verschil |= a.charCodeAt(i) ^ b.charCodeAt(i);
|
|
17
17
|
return verschil === 0;
|
|
18
18
|
}
|
|
19
|
-
/**
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
export function controleerSecret(request, secret, veld) {
|
|
26
|
-
if (veld) {
|
|
27
|
-
const w = request.headers.get(veld);
|
|
28
|
-
return { ok: w != null && gelijk(w.trim(), secret), veld };
|
|
29
|
-
}
|
|
30
|
-
const treffers = [];
|
|
31
|
-
request.headers.forEach((waarde, naam) => {
|
|
32
|
-
if (gelijk(waarde.trim(), secret))
|
|
33
|
-
treffers.push(naam.toLowerCase());
|
|
34
|
-
});
|
|
35
|
-
return treffers.length === 1 ? { ok: true, veld: treffers[0] } : { ok: false, veld: null };
|
|
19
|
+
/** De kop waarin PrintNode het geheim meestuurt (hulptekst webhookpagina). */
|
|
20
|
+
export const SECRET_KOP = "x-printnode-webhook-secret";
|
|
21
|
+
/** Controleert alleen de kop X-PrintNode-Webhook-Secret, in constante tijd. */
|
|
22
|
+
export function controleerSecret(request, secret, _veld) {
|
|
23
|
+
const w = request.headers.get(SECRET_KOP);
|
|
24
|
+
return { ok: w != null && gelijk(w.trim(), secret), veld: SECRET_KOP };
|
|
36
25
|
}
|
|
37
26
|
/** @deprecated gebruik controleerSecret */
|
|
38
27
|
export function secretKlopt(request, secret) {
|
|
39
|
-
return controleerSecret(request, secret
|
|
28
|
+
return controleerSecret(request, secret).ok;
|
|
29
|
+
}
|
|
30
|
+
const wacht = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
31
|
+
/** Zoekt de opdracht op PrintNode-id; kort opnieuw als het id nog niet is opgeslagen. */
|
|
32
|
+
async function zoekJob(db, externId, pogingen = 3) {
|
|
33
|
+
for (let i = 0; i < pogingen; i++) {
|
|
34
|
+
const { data } = await db.from("print_jobs").select("id").eq("extern_job_id", externId).maybeSingle();
|
|
35
|
+
const id = data?.id;
|
|
36
|
+
if (id)
|
|
37
|
+
return id;
|
|
38
|
+
if (i < pogingen - 1)
|
|
39
|
+
await wacht(1500);
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
async function noteer(db, regel, bewaren) {
|
|
44
|
+
if (!bewaren)
|
|
45
|
+
return;
|
|
46
|
+
try {
|
|
47
|
+
await db.from("printnode_webhook_meldingen").insert(regel);
|
|
48
|
+
const { data } = await db.from("printnode_webhook_meldingen").select("id").order("id", { ascending: false }).range(19, 19);
|
|
49
|
+
const grens = data?.[0]?.id;
|
|
50
|
+
if (grens)
|
|
51
|
+
await db.from("printnode_webhook_meldingen").delete().lt("id", grens);
|
|
52
|
+
}
|
|
53
|
+
catch { /* vastleggen mag verwerking niet blokkeren */ }
|
|
40
54
|
}
|
|
41
55
|
/**
|
|
42
56
|
* Afhandeling van een webhookaanroep. Het geheim komt uit de eigen
|
|
43
57
|
* koppelingstabel (servicerol). `secretVoorTest` alleen voor tests.
|
|
58
|
+
* Elk geldig (geheim klopt) verzoek krijgt 2xx + OK-kop, ook bij onbekende
|
|
59
|
+
* opdrachten of een fout in één melding.
|
|
44
60
|
*/
|
|
45
|
-
export async function behandelPrintNodeWebhook(request, db, secretVoorTest) {
|
|
61
|
+
export async function behandelPrintNodeWebhook(request, db, secretVoorTest, opties = {}) {
|
|
46
62
|
let secret = secretVoorTest;
|
|
47
|
-
let veld = null;
|
|
48
63
|
const uitTabel = secretVoorTest === undefined;
|
|
49
64
|
if (uitTabel) {
|
|
50
65
|
try {
|
|
51
|
-
const { data } = await db.from("printnode_webhook_koppeling").select("geheim,
|
|
66
|
+
const { data } = await db.from("printnode_webhook_koppeling").select("geheim, status").eq("id", 1).maybeSingle();
|
|
52
67
|
const k = data;
|
|
53
|
-
if (k?.status === "aan" && k.geheim)
|
|
68
|
+
if (k?.status === "aan" && k.geheim)
|
|
54
69
|
secret = k.geheim;
|
|
55
|
-
veld = k.secret_veld ?? null;
|
|
56
|
-
}
|
|
57
70
|
}
|
|
58
71
|
catch { /* fail closed */ }
|
|
59
72
|
}
|
|
60
|
-
// Fail closed: zonder koppeling wordt niets verwerkt.
|
|
61
73
|
if (!secret) {
|
|
62
74
|
return Response.json({ ok: false, fout: "Live printstatus is niet gekoppeld." }, { status: 503 });
|
|
63
75
|
}
|
|
64
|
-
|
|
65
|
-
|
|
76
|
+
if (!controleerSecret(request, secret).ok) {
|
|
77
|
+
await noteer(db, { http_status: 401, antwoord: { fout: "Ongeldig secret" } }, uitTabel);
|
|
66
78
|
return Response.json({ ok: false, fout: "Ongeldig secret" }, { status: 401 });
|
|
79
|
+
}
|
|
67
80
|
if (uitTabel) {
|
|
68
81
|
try {
|
|
69
82
|
await db.from("printnode_webhook_koppeling").update({
|
|
70
|
-
laatst_ontvangen_op: new Date().toISOString(),
|
|
71
|
-
...(veld ? {} : { secret_veld: c.veld }),
|
|
83
|
+
laatst_ontvangen_op: new Date().toISOString(), secret_veld: SECRET_KOP,
|
|
72
84
|
}).eq("id", 1);
|
|
73
85
|
}
|
|
74
|
-
catch { /*
|
|
86
|
+
catch { /* niet blokkeren */ }
|
|
75
87
|
}
|
|
76
|
-
let
|
|
88
|
+
let berichten = [];
|
|
89
|
+
let jsonFout = false;
|
|
77
90
|
try {
|
|
78
|
-
body = await request.json();
|
|
91
|
+
const body = await request.json();
|
|
92
|
+
berichten = Array.isArray(body) ? body : [];
|
|
79
93
|
}
|
|
80
94
|
catch {
|
|
81
|
-
|
|
95
|
+
jsonFout = true;
|
|
82
96
|
}
|
|
83
|
-
const
|
|
84
|
-
const
|
|
97
|
+
const soorten = new Set();
|
|
98
|
+
const ids = [];
|
|
99
|
+
const nietGematcht = [];
|
|
100
|
+
const fouten = [];
|
|
85
101
|
let jobs = 0;
|
|
86
102
|
let computerBericht = false;
|
|
103
|
+
const pogingen = opties.wachtMs === 0 ? 1 : 3;
|
|
104
|
+
const { pasPrintNodeStatusToe } = await import("./printQueue.server.js");
|
|
87
105
|
for (const b of berichten.slice(0, 500)) {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
.
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
106
|
+
try {
|
|
107
|
+
const type = String(b?.type ?? "").toLowerCase();
|
|
108
|
+
if (type)
|
|
109
|
+
soorten.add(type);
|
|
110
|
+
if (type === "print job state") {
|
|
111
|
+
const d = b.data ?? {};
|
|
112
|
+
const externId = d["printJobId"];
|
|
113
|
+
const state = String(d["state"] ?? "").toLowerCase();
|
|
114
|
+
if ((typeof externId !== "number" && typeof externId !== "string") || !state)
|
|
115
|
+
continue;
|
|
116
|
+
ids.push(`${externId}:${state}`);
|
|
117
|
+
const id = await zoekJob(db, String(externId), pogingen);
|
|
118
|
+
if (!id) {
|
|
119
|
+
nietGematcht.push(String(externId));
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
await pasPrintNodeStatusToe(db, id, state, String(d["message"] ?? ""));
|
|
123
|
+
jobs++;
|
|
124
|
+
}
|
|
125
|
+
else if (type === "computer state") {
|
|
126
|
+
computerBericht = true;
|
|
127
|
+
}
|
|
105
128
|
}
|
|
106
|
-
|
|
107
|
-
|
|
129
|
+
catch (e) {
|
|
130
|
+
fouten.push(e instanceof Error ? e.message.slice(0, 200) : "onbekend");
|
|
108
131
|
}
|
|
109
132
|
}
|
|
110
|
-
// Een computerbericht bevat geen computer-id (alleen hostname). Om op id te
|
|
111
|
-
// matchen halen we de actuele lijst op en slaan die op per computer-id.
|
|
112
133
|
if (computerBericht) {
|
|
113
134
|
try {
|
|
114
135
|
await ververs(db);
|
|
115
136
|
}
|
|
116
137
|
catch (e) {
|
|
117
|
-
|
|
138
|
+
fouten.push(`computerstatus: ${e instanceof Error ? e.message.slice(0, 150) : "onbekend"}`);
|
|
118
139
|
}
|
|
119
140
|
}
|
|
120
|
-
|
|
141
|
+
const antwoord = { ok: true, jobs, computers: computerBericht, onbekend: nietGematcht.length, ...(jsonFout ? { waarschuwing: "Ongeldige JSON" } : {}), ...(fouten.length ? { fouten } : {}) };
|
|
142
|
+
await noteer(db, {
|
|
143
|
+
http_status: 200, soorten: [...soorten], printnode_ids: ids.slice(0, 50),
|
|
144
|
+
gematcht: jobs, niet_gematcht: nietGematcht.slice(0, 50), antwoord,
|
|
145
|
+
}, uitTabel);
|
|
146
|
+
return Response.json(antwoord, { headers: OK_KOP });
|
|
121
147
|
}
|
|
122
148
|
/** Haalt alle computers op bij PrintNode en slaat hun status op per id. */
|
|
123
149
|
export async function ververs(db) {
|
|
@@ -11,6 +11,16 @@ export interface Koppeling {
|
|
|
11
11
|
gekoppeld_op: string | null;
|
|
12
12
|
laatste_poging_op: string | null;
|
|
13
13
|
laatst_ontvangen_op: string | null;
|
|
14
|
+
bereikbaar?: string | null;
|
|
15
|
+
zelftest_op?: string | null;
|
|
16
|
+
zelftest_fout?: string | null;
|
|
17
|
+
pn_url?: string | null;
|
|
18
|
+
pn_geslaagd?: number | null;
|
|
19
|
+
pn_mislukt?: number | null;
|
|
20
|
+
pn_geslaagd_vorig?: number | null;
|
|
21
|
+
pn_opgehaald_op?: string | null;
|
|
22
|
+
pn_ontvangen?: number | null;
|
|
23
|
+
pn_weggegooid?: number | null;
|
|
14
24
|
}
|
|
15
25
|
export declare function leesKoppeling(db: Db): Promise<Koppeling | null>;
|
|
16
26
|
/** Het Shell-adres zoals de Logistiek Engine het bewaart en controleert. */
|
|
@@ -31,9 +41,34 @@ export declare function koppelWebhook(db: Db, opties?: {
|
|
|
31
41
|
* hem bij als het Shell-adres veranderd is. Na een fout eerst even wachten.
|
|
32
42
|
*/
|
|
33
43
|
export declare function zorgVoorWebhookKoppeling(db: Db): Promise<void>;
|
|
44
|
+
export type ZelftestUitkomst = "ja" | "nee" | "onbekend";
|
|
45
|
+
/**
|
|
46
|
+
* Beoordeelt het antwoord van de eigen webhookroute zonder geheim.
|
|
47
|
+
* JSON (401/503) = route bestaat. Alleen een echte 404 = niet bereikbaar.
|
|
48
|
+
*/
|
|
49
|
+
export declare function beoordeelZelftest(status: number, contentType: string | null): ZelftestUitkomst;
|
|
50
|
+
/** Leest counts uit GET /webhooks (successfulRequests, failedRequests, receivedEvents, droppedEvents). */
|
|
51
|
+
export declare function leesCounts(counts: unknown): {
|
|
52
|
+
geslaagd: number | null;
|
|
53
|
+
mislukt: number | null;
|
|
54
|
+
ontvangen: number | null;
|
|
55
|
+
weggegooid: number | null;
|
|
56
|
+
};
|
|
57
|
+
/** Zelftest naar het eigen adres + tellingen uit GET /webhooks (op webhookId). */
|
|
58
|
+
export declare function controleerBereikbaarheid(db: Db): Promise<void>;
|
|
59
|
+
/** Bepaalt wat het scherm toont: aan / uit / onbekend. */
|
|
60
|
+
export declare function weergaveStatus(k: Koppeling | null): "aan" | "uit" | "onbekend";
|
|
34
61
|
/** Veilige status voor het scherm: nooit het geheim. */
|
|
35
62
|
export declare function veiligeStatus(k: Koppeling | null): {
|
|
36
63
|
aan: boolean;
|
|
64
|
+
weergave: "aan" | "uit" | "onbekend";
|
|
65
|
+
nietBereikbaar: boolean;
|
|
66
|
+
pnUrl: string | null;
|
|
67
|
+
pnGeslaagd: number | null;
|
|
68
|
+
pnMislukt: number | null;
|
|
69
|
+
pnOntvangen: number | null;
|
|
70
|
+
pnWeggegooid: number | null;
|
|
71
|
+
pnOpgehaaldOp: string | null;
|
|
37
72
|
url: string | null;
|
|
38
73
|
fout: string | null;
|
|
39
74
|
melding: string | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"printnodeWebhookBeheer.server.d.ts","sourceRoot":"","sources":["../../src/lib/printnodeWebhookBeheer.server.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAG5D,KAAK,EAAE,GAAG,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAQxC,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"printnodeWebhookBeheer.server.d.ts","sourceRoot":"","sources":["../../src/lib/printnodeWebhookBeheer.server.ts"],"names":[],"mappings":"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"}
|
|
@@ -68,6 +68,7 @@ export async function koppelWebhook(db, opties = {}) {
|
|
|
68
68
|
geheim, secret_veld: null, webhook_id: webhookId, url: oordeel.url, status: "aan",
|
|
69
69
|
fout: null, melding: opties.melding ?? null, gekoppeld_op: nu, laatste_poging_op: nu,
|
|
70
70
|
});
|
|
71
|
+
await controleerBereikbaarheid(db);
|
|
71
72
|
return { ok: true, url: oordeel.url, bijgewerkt: !!bestaand };
|
|
72
73
|
}
|
|
73
74
|
catch (e) {
|
|
@@ -92,8 +93,12 @@ export async function zorgVoorWebhookKoppeling(db) {
|
|
|
92
93
|
return;
|
|
93
94
|
}
|
|
94
95
|
const gekoppeld = huidig?.status === "aan" && huidig.webhook_id != null && !!huidig.geheim;
|
|
95
|
-
if (gekoppeld && huidig.url === oordeel.url)
|
|
96
|
+
if (gekoppeld && huidig.url === oordeel.url) {
|
|
97
|
+
const oud = huidig.zelftest_op ? Date.now() - new Date(huidig.zelftest_op).getTime() : Infinity;
|
|
98
|
+
if (huidig.bereikbaar !== "ja" || oud > CONTROLE_INTERVAL_MIN * 60000)
|
|
99
|
+
await controleerBereikbaarheid(db);
|
|
96
100
|
return;
|
|
101
|
+
}
|
|
97
102
|
if (huidig?.fout && huidig.laatste_poging_op &&
|
|
98
103
|
Date.now() - new Date(huidig.laatste_poging_op).getTime() < WACHT_NA_FOUT_MIN * 60000)
|
|
99
104
|
return;
|
|
@@ -102,10 +107,106 @@ export async function zorgVoorWebhookKoppeling(db) {
|
|
|
102
107
|
melding: gewijzigd ? "Shell-adres gewijzigd, de printstatus wordt opnieuw gekoppeld." : null,
|
|
103
108
|
});
|
|
104
109
|
}
|
|
110
|
+
const CONTROLE_INTERVAL_MIN = 10;
|
|
111
|
+
const ZELFTEST_MS = 5000;
|
|
112
|
+
/**
|
|
113
|
+
* Beoordeelt het antwoord van de eigen webhookroute zonder geheim.
|
|
114
|
+
* JSON (401/503) = route bestaat. Alleen een echte 404 = niet bereikbaar.
|
|
115
|
+
*/
|
|
116
|
+
export function beoordeelZelftest(status, contentType) {
|
|
117
|
+
const json = (contentType ?? "").toLowerCase().includes("application/json");
|
|
118
|
+
if (json)
|
|
119
|
+
return "ja";
|
|
120
|
+
if (status === 404)
|
|
121
|
+
return "nee";
|
|
122
|
+
return "onbekend";
|
|
123
|
+
}
|
|
124
|
+
/** Leest counts uit GET /webhooks (successfulRequests, failedRequests, receivedEvents, droppedEvents). */
|
|
125
|
+
export function leesCounts(counts) {
|
|
126
|
+
const c = (counts && typeof counts === "object" ? counts : {});
|
|
127
|
+
const n = (k) => (typeof c[k] === "number" ? c[k] : null);
|
|
128
|
+
return {
|
|
129
|
+
geslaagd: n("successfulRequests"),
|
|
130
|
+
mislukt: n("failedRequests"),
|
|
131
|
+
ontvangen: n("receivedEvents"),
|
|
132
|
+
weggegooid: n("droppedEvents"),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/** Zelftest naar het eigen adres + tellingen uit GET /webhooks (op webhookId). */
|
|
136
|
+
export async function controleerBereikbaarheid(db) {
|
|
137
|
+
const k = await leesKoppeling(db);
|
|
138
|
+
if (!k?.url)
|
|
139
|
+
return;
|
|
140
|
+
const nu = new Date().toISOString();
|
|
141
|
+
let bereikbaar = "onbekend";
|
|
142
|
+
let fout = null;
|
|
143
|
+
try {
|
|
144
|
+
const ctl = new AbortController();
|
|
145
|
+
const t = setTimeout(() => ctl.abort(), ZELFTEST_MS);
|
|
146
|
+
const r = await fetch(k.url, {
|
|
147
|
+
method: "POST",
|
|
148
|
+
headers: { "Content-Type": "application/json" },
|
|
149
|
+
body: "[]",
|
|
150
|
+
signal: ctl.signal,
|
|
151
|
+
}).finally(() => clearTimeout(t));
|
|
152
|
+
bereikbaar = beoordeelZelftest(r.status, r.headers.get("content-type"));
|
|
153
|
+
if (bereikbaar !== "ja")
|
|
154
|
+
fout = `Zelftest gaf status ${r.status}`;
|
|
155
|
+
}
|
|
156
|
+
catch (e) {
|
|
157
|
+
fout = e instanceof Error ? e.message : "netwerkfout";
|
|
158
|
+
}
|
|
159
|
+
const velden = { zelftest_op: nu, zelftest_fout: fout };
|
|
160
|
+
try {
|
|
161
|
+
if (k.webhook_id != null) {
|
|
162
|
+
const { printnodeVraag } = await import("./printService.server.js");
|
|
163
|
+
const lijst = await printnodeVraag("/webhooks");
|
|
164
|
+
const w = (Array.isArray(lijst) ? lijst : []).find((x) => Number(x.webhookId) === Number(k.webhook_id));
|
|
165
|
+
if (w) {
|
|
166
|
+
const c = leesCounts(w.counts);
|
|
167
|
+
velden.pn_url = w.url ?? null;
|
|
168
|
+
velden.pn_geslaagd_vorig = k.pn_geslaagd ?? null;
|
|
169
|
+
velden.pn_geslaagd = c.geslaagd;
|
|
170
|
+
velden.pn_mislukt = c.mislukt;
|
|
171
|
+
velden.pn_ontvangen = c.ontvangen;
|
|
172
|
+
velden.pn_weggegooid = c.weggegooid;
|
|
173
|
+
velden.pn_opgehaald_op = nu;
|
|
174
|
+
if (c.geslaagd != null && k.pn_geslaagd != null && c.geslaagd > k.pn_geslaagd)
|
|
175
|
+
bereikbaar = "ja";
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
catch { /* tellingen zijn aanvullend */ }
|
|
180
|
+
// Bewijs van PrintNode zelf telt zwaarder dan de zelftest.
|
|
181
|
+
if (k.laatst_ontvangen_op)
|
|
182
|
+
bereikbaar = "ja";
|
|
183
|
+
velden.bereikbaar = bereikbaar;
|
|
184
|
+
await schrijf(db, velden);
|
|
185
|
+
}
|
|
186
|
+
/** Bepaalt wat het scherm toont: aan / uit / onbekend. */
|
|
187
|
+
export function weergaveStatus(k) {
|
|
188
|
+
const gekoppeld = k?.status === "aan" && !!k?.geheim;
|
|
189
|
+
if (!gekoppeld)
|
|
190
|
+
return "uit";
|
|
191
|
+
if (k?.laatst_ontvangen_op || k?.bereikbaar === "ja")
|
|
192
|
+
return "aan";
|
|
193
|
+
if (k?.bereikbaar === "nee")
|
|
194
|
+
return "uit";
|
|
195
|
+
return "onbekend";
|
|
196
|
+
}
|
|
105
197
|
/** Veilige status voor het scherm: nooit het geheim. */
|
|
106
198
|
export function veiligeStatus(k) {
|
|
199
|
+
const weergave = weergaveStatus(k);
|
|
107
200
|
return {
|
|
108
|
-
aan:
|
|
201
|
+
aan: weergave === "aan",
|
|
202
|
+
weergave,
|
|
203
|
+
nietBereikbaar: k?.status === "aan" && k?.bereikbaar === "nee" && !k?.laatst_ontvangen_op,
|
|
204
|
+
pnUrl: k?.pn_url ?? null,
|
|
205
|
+
pnGeslaagd: k?.pn_geslaagd ?? null,
|
|
206
|
+
pnMislukt: k?.pn_mislukt ?? null,
|
|
207
|
+
pnOntvangen: k?.pn_ontvangen ?? null,
|
|
208
|
+
pnWeggegooid: k?.pn_weggegooid ?? null,
|
|
209
|
+
pnOpgehaaldOp: k?.pn_opgehaald_op ?? null,
|
|
109
210
|
url: k?.url ?? null,
|
|
110
211
|
fout: k?.fout ?? null,
|
|
111
212
|
melding: k?.melding ?? null,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"printnodeWebhookRoute.d.ts","sourceRoot":"","sources":["../../src/lib/printnodeWebhookRoute.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// src/lib/printnodeWebhookRoute.ts — losse ingang voor de Shell
|
|
3
|
+
// (@flowselections/layout-maker/webhook), net als ./print en ./preview.
|
|
4
|
+
// ============================================================================
|
|
5
|
+
export { behandelPrintNodeWebhook } from "./printnodeWebhook.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flowselections/layout-maker",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.55.1",
|
|
4
4
|
"flowselections": {
|
|
5
5
|
"moduleId": "layout-maker",
|
|
6
6
|
"pages": [
|
|
@@ -66,6 +66,14 @@
|
|
|
66
66
|
"methods": [
|
|
67
67
|
"POST"
|
|
68
68
|
]
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"routePath": "/api/public/print/printnode-webhook",
|
|
72
|
+
"import": "@flowselections/layout-maker/webhook",
|
|
73
|
+
"handler": "behandelPrintNodeWebhook",
|
|
74
|
+
"methods": [
|
|
75
|
+
"POST"
|
|
76
|
+
]
|
|
69
77
|
}
|
|
70
78
|
]
|
|
71
79
|
},
|
|
@@ -87,6 +95,10 @@
|
|
|
87
95
|
"./preview": {
|
|
88
96
|
"types": "./dist-lib/lib/previewPdf.d.ts",
|
|
89
97
|
"default": "./dist-lib/lib/previewPdf.js"
|
|
98
|
+
},
|
|
99
|
+
"./webhook": {
|
|
100
|
+
"types": "./dist-lib/lib/printnodeWebhookRoute.d.ts",
|
|
101
|
+
"default": "./dist-lib/lib/printnodeWebhookRoute.js"
|
|
90
102
|
}
|
|
91
103
|
},
|
|
92
104
|
"files": [
|