@flowselections/floriday-voorraad 1.0.110 → 1.0.113
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/voorraad/FustenPage.d.ts.map +1 -1
- package/dist-lib/components/voorraad/FustenPage.js +10 -6
- package/dist-lib/components/voorraad/PriceStatusBadge.d.ts.map +1 -1
- package/dist-lib/components/voorraad/PriceStatusBadge.js +6 -1
- package/dist-lib/components/voorraad/VoorraadPage.d.ts.map +1 -1
- package/dist-lib/components/voorraad/VoorraadPage.js +8 -37
- package/dist-lib/hooks/useNoPriceProducts.d.ts +10 -0
- package/dist-lib/hooks/useNoPriceProducts.d.ts.map +1 -0
- package/dist-lib/hooks/useNoPriceProducts.js +56 -0
- package/dist-lib/hooks/useStockPushJobs.d.ts.map +1 -1
- package/dist-lib/hooks/useStockPushJobs.js +6 -1
- package/dist-lib/hooks/useStockSyncHealth.d.ts.map +1 -1
- package/dist-lib/hooks/useStockSyncHealth.js +2 -9
- package/dist-lib/hooks/useVoorraadData.d.ts.map +1 -1
- package/dist-lib/hooks/useVoorraadData.js +45 -24
- package/dist-lib/integrations/supabase/types.d.ts +818 -122
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.js +1 -0
- package/dist-lib/lib/__tests__/fust-dimensions.test.d.ts +2 -0
- package/dist-lib/lib/__tests__/fust-dimensions.test.d.ts.map +1 -0
- package/dist-lib/lib/__tests__/fust-dimensions.test.js +27 -0
- package/dist-lib/lib/__tests__/request-guard.test.d.ts +2 -0
- package/dist-lib/lib/__tests__/request-guard.test.d.ts.map +1 -0
- package/dist-lib/lib/__tests__/request-guard.test.js +50 -0
- package/dist-lib/lib/fusten.d.ts +14 -3
- package/dist-lib/lib/fusten.d.ts.map +1 -1
- package/dist-lib/lib/fusten.js +38 -7
- package/dist-lib/lib/request-guard.d.ts +46 -0
- package/dist-lib/lib/request-guard.d.ts.map +1 -0
- package/dist-lib/lib/request-guard.js +100 -0
- package/package.json +1 -1
- package/sql/floriday-voorraad-schema.sql +186 -27
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fust-dimensions.test.d.ts","sourceRoot":"","sources":["../../../src/lib/__tests__/fust-dimensions.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
vi.mock("../../integrations/supabase/client", () => ({ supabase: {} }));
|
|
3
|
+
import { customPackageDimsOf, resolveFustDimensions } from "../fusten.js";
|
|
4
|
+
const fc = new Map([["18", { name: "Trayrand", lengthMm: 560, widthMm: 250, heightMm: 170 }]]);
|
|
5
|
+
const cp = new Map([["cp-1", { lengthMm: 400, widthMm: 300, heightMm: 120 }]]);
|
|
6
|
+
const base = { vbn_code: null, custom_package_id: null, length_mm: null, width_mm: null, height_mm: null };
|
|
7
|
+
describe("fustmaten: Floricode → Floriday custom package → handmatig → leeg", () => {
|
|
8
|
+
it("Floricode wint", () => {
|
|
9
|
+
const r = resolveFustDimensions({ ...base, vbn_code: 18, custom_package_id: "cp-1", length_mm: 1 }, fc, cp);
|
|
10
|
+
expect(r).toEqual({ length_mm: 560, width_mm: 250, height_mm: 170, source: "floricode" });
|
|
11
|
+
});
|
|
12
|
+
it("anders custom package", () => {
|
|
13
|
+
const r = resolveFustDimensions({ ...base, custom_package_id: "cp-1", length_mm: 1 }, fc, cp);
|
|
14
|
+
expect(r).toEqual({ length_mm: 400, width_mm: 300, height_mm: 120, source: "floriday" });
|
|
15
|
+
});
|
|
16
|
+
it("anders handmatig", () => {
|
|
17
|
+
const r = resolveFustDimensions({ ...base, custom_package_id: "onbekend", length_mm: 7 }, fc, cp);
|
|
18
|
+
expect(r.source).toBe("handmatig");
|
|
19
|
+
expect(r.length_mm).toBe(7);
|
|
20
|
+
});
|
|
21
|
+
it("anders leeg, nooit standaardwaarden", () => {
|
|
22
|
+
expect(resolveFustDimensions(base, fc, cp)).toEqual({ length_mm: null, width_mm: null, height_mm: null, source: "onbekend" });
|
|
23
|
+
});
|
|
24
|
+
it("leest mm uit data.dimensions", () => {
|
|
25
|
+
expect(customPackageDimsOf({ dimensions: { length: 400, width: 0, height: "120" } })).toEqual({ lengthMm: 400, widthMm: null, heightMm: 120 });
|
|
26
|
+
});
|
|
27
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-guard.test.d.ts","sourceRoot":"","sources":["../../../src/lib/__tests__/request-guard.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { createBundler, createRequestGuard } from "../request-guard.js";
|
|
3
|
+
describe("request guard", () => {
|
|
4
|
+
it("staat 30 aanvragen in 10 s toe en stopt de 31e", () => {
|
|
5
|
+
let t = 0;
|
|
6
|
+
const g = createRequestGuard(30, 10000, () => t);
|
|
7
|
+
const err = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
8
|
+
for (let i = 0; i < 30; i++)
|
|
9
|
+
expect(g.allow("products")).toBe(true);
|
|
10
|
+
expect(g.allow("products")).toBe(false);
|
|
11
|
+
expect(g.trips()[0].table).toBe("products");
|
|
12
|
+
expect(g.allow("trade_item_stock")).toBe(true);
|
|
13
|
+
err.mockRestore();
|
|
14
|
+
});
|
|
15
|
+
it("telt alleen binnen het venster", () => {
|
|
16
|
+
let t = 0;
|
|
17
|
+
const g = createRequestGuard(30, 10000, () => t);
|
|
18
|
+
for (let i = 0; i < 30; i++)
|
|
19
|
+
g.allow("products");
|
|
20
|
+
t = 10001;
|
|
21
|
+
expect(g.allow("products")).toBe(true);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
describe("bundler", () => {
|
|
25
|
+
it("10 seintjes binnen 2 s geven 1 herlaadactie", () => {
|
|
26
|
+
vi.useFakeTimers();
|
|
27
|
+
const run = vi.fn();
|
|
28
|
+
const b = createBundler(run, 2000, { isHidden: () => false });
|
|
29
|
+
for (let i = 0; i < 10; i++)
|
|
30
|
+
b.trigger();
|
|
31
|
+
vi.advanceTimersByTime(1999);
|
|
32
|
+
expect(run).toHaveBeenCalledTimes(1);
|
|
33
|
+
vi.useRealTimers();
|
|
34
|
+
});
|
|
35
|
+
it("verborgen tabblad: 0 herlaadacties, bij terugkeren 1", () => {
|
|
36
|
+
vi.useFakeTimers();
|
|
37
|
+
let hidden = true;
|
|
38
|
+
const run = vi.fn();
|
|
39
|
+
const b = createBundler(run, 2000, { isHidden: () => hidden });
|
|
40
|
+
for (let i = 0; i < 5; i++)
|
|
41
|
+
b.trigger();
|
|
42
|
+
vi.advanceTimersByTime(10000);
|
|
43
|
+
expect(run).toHaveBeenCalledTimes(0);
|
|
44
|
+
hidden = false;
|
|
45
|
+
b.flushIfPending();
|
|
46
|
+
vi.advanceTimersByTime(0);
|
|
47
|
+
expect(run).toHaveBeenCalledTimes(1);
|
|
48
|
+
vi.useRealTimers();
|
|
49
|
+
});
|
|
50
|
+
});
|
package/dist-lib/lib/fusten.d.ts
CHANGED
|
@@ -56,9 +56,20 @@ interface VbnCatalogEntry {
|
|
|
56
56
|
* (eigenaar Floriday-authenticatie). Lege maten blijven null.
|
|
57
57
|
*/
|
|
58
58
|
export declare function fetchFloricodeFustMap(): Promise<Map<string, VbnCatalogEntry>>;
|
|
59
|
-
export type FustDimensionSource = "floricode" | "handmatig" | "onbekend";
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
export type FustDimensionSource = "floricode" | "floriday" | "handmatig" | "onbekend";
|
|
60
|
+
export interface CustomPackageDims {
|
|
61
|
+
lengthMm: number | null;
|
|
62
|
+
widthMm: number | null;
|
|
63
|
+
heightMm: number | null;
|
|
64
|
+
}
|
|
65
|
+
/** Maten uit een Floriday custom package (data van floriday_packings_cache), in mm. */
|
|
66
|
+
export declare function customPackageDimsOf(data: any): CustomPackageDims;
|
|
67
|
+
/** Eigen fusten (Floriday custom packages) per floriday_id. */
|
|
68
|
+
export declare function fetchFloridayCustomPackageMap(): Promise<Map<string, CustomPackageDims>>;
|
|
69
|
+
/** Floricode → Floriday custom package → handmatig → leeg. Nooit standaardwaarden (gelijk aan voorraad_fust_dimensions). */
|
|
70
|
+
export declare function resolveFustDimensions(fust: Pick<FustType, "vbn_code" | "length_mm" | "width_mm" | "height_mm"> & {
|
|
71
|
+
custom_package_id?: string | null;
|
|
72
|
+
}, floricode: Map<string, VbnCatalogEntry> | null, customPackages?: Map<string, CustomPackageDims> | null): {
|
|
62
73
|
length_mm: number | null;
|
|
63
74
|
width_mm: number | null;
|
|
64
75
|
height_mm: number | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fusten.d.ts","sourceRoot":"","sources":["../../src/lib/fusten.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAEpE,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,+DAA+D;AAC/D,wBAAgB,oBAAoB,CAAC,CAAC,EAAE;IACtC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,GAAG,MAAM,GAAG,IAAI,CAIhB;AAMD,iEAAiE;AACjE,wBAAgB,SAAS,CAAC,CAAC,EAAE,OAAO,CAAC,yBAAyB,CAAC,GAAG,MAAM,GAAG,IAAI,CAO9E;AA8DD,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAenF;AAQD,MAAM,MAAM,mBAAmB,GAAG,WAAW,GAAG,WAAW,GAAG,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"fusten.d.ts","sourceRoot":"","sources":["../../src/lib/fusten.ts"],"names":[],"mappings":"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"}
|
package/dist-lib/lib/fusten.js
CHANGED
|
@@ -114,15 +114,42 @@ function positiveOrNull(v) {
|
|
|
114
114
|
const n = Number(v);
|
|
115
115
|
return Number.isFinite(n) && n > 0 ? Math.round(n) : null;
|
|
116
116
|
}
|
|
117
|
-
/**
|
|
118
|
-
export function
|
|
117
|
+
/** Maten uit een Floriday custom package (data van floriday_packings_cache), in mm. */
|
|
118
|
+
export function customPackageDimsOf(data) {
|
|
119
|
+
const d = data?.dimensions ?? data?.dimension ?? {};
|
|
120
|
+
return {
|
|
121
|
+
lengthMm: positiveOrNull(d.length ?? data?.lengthMm ?? data?.length),
|
|
122
|
+
widthMm: positiveOrNull(d.width ?? data?.widthMm ?? data?.width),
|
|
123
|
+
heightMm: positiveOrNull(d.height ?? data?.heightMm ?? data?.height),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/** Eigen fusten (Floriday custom packages) per floriday_id. */
|
|
127
|
+
export async function fetchFloridayCustomPackageMap() {
|
|
128
|
+
const map = new Map();
|
|
129
|
+
const { data, error } = await supabase
|
|
130
|
+
.from("floriday_packings_cache")
|
|
131
|
+
.select("floriday_id,data")
|
|
132
|
+
.eq("is_deleted", false);
|
|
133
|
+
if (error)
|
|
134
|
+
throw new Error(error.message);
|
|
135
|
+
for (const r of (data ?? [])) {
|
|
136
|
+
if (r?.floriday_id)
|
|
137
|
+
map.set(String(r.floriday_id), customPackageDimsOf(r.data));
|
|
138
|
+
}
|
|
139
|
+
return map;
|
|
140
|
+
}
|
|
141
|
+
/** Floricode → Floriday custom package → handmatig → leeg. Nooit standaardwaarden (gelijk aan voorraad_fust_dimensions). */
|
|
142
|
+
export function resolveFustDimensions(fust, floricode, customPackages) {
|
|
119
143
|
const fc = fust.vbn_code != null ? floricode?.get(String(fust.vbn_code)) : undefined;
|
|
120
|
-
|
|
144
|
+
const cp = fust.custom_package_id ? customPackages?.get(fust.custom_package_id) : undefined;
|
|
145
|
+
const has = (x) => !!x && (x.lengthMm != null || x.widthMm != null || x.heightMm != null);
|
|
146
|
+
const pick = (k, m) => fc?.[k] ?? cp?.[k] ?? fust[m] ?? null;
|
|
147
|
+
if (has(fc) || has(cp)) {
|
|
121
148
|
return {
|
|
122
|
-
length_mm:
|
|
123
|
-
width_mm:
|
|
124
|
-
height_mm:
|
|
125
|
-
source: "floricode",
|
|
149
|
+
length_mm: pick("lengthMm", "length_mm"),
|
|
150
|
+
width_mm: pick("widthMm", "width_mm"),
|
|
151
|
+
height_mm: pick("heightMm", "height_mm"),
|
|
152
|
+
source: has(fc) ? "floricode" : "floriday",
|
|
126
153
|
};
|
|
127
154
|
}
|
|
128
155
|
if (fust.length_mm != null || fust.width_mm != null || fust.height_mm != null) {
|
|
@@ -188,6 +215,8 @@ export async function fetchFustTypes(_connectionId) {
|
|
|
188
215
|
.from("fust_types")
|
|
189
216
|
.select("*")
|
|
190
217
|
.is("connection_id", null)
|
|
218
|
+
// Samengevoegde rijen (voorraad_correctie_1112) blijven bewaard maar tellen niet mee.
|
|
219
|
+
.is("merged_into", null)
|
|
191
220
|
.order("name");
|
|
192
221
|
if (error)
|
|
193
222
|
throw new Error(error.message);
|
|
@@ -341,6 +370,7 @@ export async function registerSaleFustUsage(params) {
|
|
|
341
370
|
.select("id")
|
|
342
371
|
.eq("fust_key", key)
|
|
343
372
|
.is("connection_id", null)
|
|
373
|
+
.is("merged_into", null)
|
|
344
374
|
.limit(1);
|
|
345
375
|
let fustTypeId = (data ?? [])[0]?.id;
|
|
346
376
|
if (!fustTypeId) {
|
|
@@ -350,6 +380,7 @@ export async function registerSaleFustUsage(params) {
|
|
|
350
380
|
.select("id")
|
|
351
381
|
.eq("fust_key", key)
|
|
352
382
|
.is("connection_id", null)
|
|
383
|
+
.is("merged_into", null)
|
|
353
384
|
.limit(1);
|
|
354
385
|
fustTypeId = (retry ?? [])[0]?.id;
|
|
355
386
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bewaking tegen opvraag-lussen en bundeling van herlaadacties.
|
|
3
|
+
* - Teller per tabel: meer dan MAX aanvragen binnen het venster → die tabel stopt
|
|
4
|
+
* (tot de pagina opnieuw geopend wordt), met console-melding en een regel voor
|
|
5
|
+
* "Details voor beheer".
|
|
6
|
+
* - Bundelaar: hooguit één uitvoering per interval; in een verborgen tabblad wordt
|
|
7
|
+
* alleen onthouden dat er iets veranderd is, en bij terugkeren één keer uitgevoerd.
|
|
8
|
+
*/
|
|
9
|
+
export declare const GUARD_MAX = 30;
|
|
10
|
+
export declare const GUARD_WINDOW_MS = 10000;
|
|
11
|
+
/** Minimaal interval voor periodieke opvragingen op de voorraadpagina. */
|
|
12
|
+
export declare const MIN_POLL_MS = 15000;
|
|
13
|
+
export type GuardTrip = {
|
|
14
|
+
table: string;
|
|
15
|
+
at: number;
|
|
16
|
+
count: number;
|
|
17
|
+
};
|
|
18
|
+
export declare function createRequestGuard(max?: number, windowMs?: number, now?: () => number): {
|
|
19
|
+
/** true = aanvraag mag; false = geblokkeerd. */
|
|
20
|
+
allow(table: string): boolean;
|
|
21
|
+
trips(): GuardTrip[];
|
|
22
|
+
subscribe(l: () => void): () => void;
|
|
23
|
+
reset(): void;
|
|
24
|
+
};
|
|
25
|
+
/** Eén bewaker per geopende pagina (module-instantie in de browser). */
|
|
26
|
+
export declare const pageRequestGuard: {
|
|
27
|
+
/** true = aanvraag mag; false = geblokkeerd. */
|
|
28
|
+
allow(table: string): boolean;
|
|
29
|
+
trips(): GuardTrip[];
|
|
30
|
+
subscribe(l: () => void): () => void;
|
|
31
|
+
reset(): void;
|
|
32
|
+
};
|
|
33
|
+
export declare function isTabHidden(): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Bundelt aanroepen: hooguit één `run` per `intervalMs`. Verborgen tabblad → uitgesteld
|
|
36
|
+
* tot `flushIfPending()` (bij terugkeren naar het tabblad).
|
|
37
|
+
*/
|
|
38
|
+
export declare function createBundler(run: () => void, intervalMs: number, opts?: {
|
|
39
|
+
isHidden?: () => boolean;
|
|
40
|
+
now?: () => number;
|
|
41
|
+
}): {
|
|
42
|
+
trigger(): void;
|
|
43
|
+
flushIfPending(): void;
|
|
44
|
+
cancel(): void;
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=request-guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-guard.d.ts","sourceRoot":"","sources":["../../src/lib/request-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,eAAO,MAAM,SAAS,KAAK,CAAC;AAC5B,eAAO,MAAM,eAAe,QAAS,CAAC;AACtC,0EAA0E;AAC1E,eAAO,MAAM,WAAW,QAAS,CAAC;AAElC,MAAM,MAAM,SAAS,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAErE,wBAAgB,kBAAkB,CAAC,GAAG,SAAY,EAAE,QAAQ,SAAkB,EAAE,GAAG,eAAmB;IAMlG,gDAAgD;iBACnC,MAAM,GAAG,OAAO;aAkBpB,SAAS,EAAE;iBAGP,MAAM,IAAI;;EAa1B;AAED,wEAAwE;AACxE,eAAO,MAAM,gBAAgB;IAtCzB,gDAAgD;iBACnC,MAAM,GAAG,OAAO;aAkBpB,SAAS,EAAE;iBAGP,MAAM,IAAI;;CAgByB,CAAC;AAErD,wBAAgB,WAAW,IAAI,OAAO,CAErC;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,MAAM,IAAI,EACf,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CAAO;;;;EAmC5D"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bewaking tegen opvraag-lussen en bundeling van herlaadacties.
|
|
3
|
+
* - Teller per tabel: meer dan MAX aanvragen binnen het venster → die tabel stopt
|
|
4
|
+
* (tot de pagina opnieuw geopend wordt), met console-melding en een regel voor
|
|
5
|
+
* "Details voor beheer".
|
|
6
|
+
* - Bundelaar: hooguit één uitvoering per interval; in een verborgen tabblad wordt
|
|
7
|
+
* alleen onthouden dat er iets veranderd is, en bij terugkeren één keer uitgevoerd.
|
|
8
|
+
*/
|
|
9
|
+
export const GUARD_MAX = 30;
|
|
10
|
+
export const GUARD_WINDOW_MS = 10000;
|
|
11
|
+
/** Minimaal interval voor periodieke opvragingen op de voorraadpagina. */
|
|
12
|
+
export const MIN_POLL_MS = 15000;
|
|
13
|
+
export function createRequestGuard(max = GUARD_MAX, windowMs = GUARD_WINDOW_MS, now = () => Date.now()) {
|
|
14
|
+
const hits = new Map();
|
|
15
|
+
const tripped = new Map();
|
|
16
|
+
const listeners = new Set();
|
|
17
|
+
let snapshot = [];
|
|
18
|
+
return {
|
|
19
|
+
/** true = aanvraag mag; false = geblokkeerd. */
|
|
20
|
+
allow(table) {
|
|
21
|
+
if (tripped.has(table))
|
|
22
|
+
return false;
|
|
23
|
+
const t = now();
|
|
24
|
+
const arr = (hits.get(table) ?? []).filter((x) => t - x < windowMs);
|
|
25
|
+
arr.push(t);
|
|
26
|
+
hits.set(table, arr);
|
|
27
|
+
if (arr.length > max) {
|
|
28
|
+
const trip = { table, at: t, count: arr.length };
|
|
29
|
+
tripped.set(table, trip);
|
|
30
|
+
snapshot = [...tripped.values()];
|
|
31
|
+
console.error(`[voorraad] Opvragingen naar "${table}" gestopt: ${arr.length} aanvragen in ${windowMs / 1000} s. Open de pagina opnieuw.`);
|
|
32
|
+
listeners.forEach((l) => l());
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
return true;
|
|
36
|
+
},
|
|
37
|
+
trips() {
|
|
38
|
+
return snapshot;
|
|
39
|
+
},
|
|
40
|
+
subscribe(l) {
|
|
41
|
+
listeners.add(l);
|
|
42
|
+
return () => {
|
|
43
|
+
listeners.delete(l);
|
|
44
|
+
};
|
|
45
|
+
},
|
|
46
|
+
reset() {
|
|
47
|
+
hits.clear();
|
|
48
|
+
tripped.clear();
|
|
49
|
+
snapshot = [];
|
|
50
|
+
listeners.forEach((l) => l());
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/** Eén bewaker per geopende pagina (module-instantie in de browser). */
|
|
55
|
+
export const pageRequestGuard = createRequestGuard();
|
|
56
|
+
export function isTabHidden() {
|
|
57
|
+
return typeof document !== "undefined" && document.visibilityState === "hidden";
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Bundelt aanroepen: hooguit één `run` per `intervalMs`. Verborgen tabblad → uitgesteld
|
|
61
|
+
* tot `flushIfPending()` (bij terugkeren naar het tabblad).
|
|
62
|
+
*/
|
|
63
|
+
export function createBundler(run, intervalMs, opts = {}) {
|
|
64
|
+
const isHidden = opts.isHidden ?? isTabHidden;
|
|
65
|
+
const now = opts.now ?? (() => Date.now());
|
|
66
|
+
let last = -Infinity;
|
|
67
|
+
let timer = null;
|
|
68
|
+
let pending = false;
|
|
69
|
+
const fire = () => {
|
|
70
|
+
timer = null;
|
|
71
|
+
if (isHidden()) {
|
|
72
|
+
pending = true;
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
pending = false;
|
|
76
|
+
last = now();
|
|
77
|
+
run();
|
|
78
|
+
};
|
|
79
|
+
return {
|
|
80
|
+
trigger() {
|
|
81
|
+
if (isHidden()) {
|
|
82
|
+
pending = true;
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (timer)
|
|
86
|
+
return;
|
|
87
|
+
const wait = Math.max(0, last + intervalMs - now());
|
|
88
|
+
timer = setTimeout(fire, wait);
|
|
89
|
+
},
|
|
90
|
+
flushIfPending() {
|
|
91
|
+
if (pending && !isHidden())
|
|
92
|
+
this.trigger();
|
|
93
|
+
},
|
|
94
|
+
cancel() {
|
|
95
|
+
if (timer)
|
|
96
|
+
clearTimeout(timer);
|
|
97
|
+
timer = null;
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|