@flowselections/floriday-voorraad 1.0.30 → 1.0.32
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/StockSyncStatus.d.ts.map +1 -1
- package/dist-lib/components/voorraad/StockSyncStatus.js +20 -3
- package/dist-lib/components/voorraad/VoorraadPage.d.ts.map +1 -1
- package/dist-lib/components/voorraad/VoorraadPage.js +1 -4
- package/dist-lib/hooks/useStockSyncHealth.d.ts.map +1 -1
- package/dist-lib/hooks/useStockSyncHealth.js +7 -1
- package/dist-lib/integrations/supabase/auth-middleware.d.ts +9518 -6923
- package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.d.ts +9518 -6923
- package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.server.d.ts +9518 -6923
- package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.d.ts +9677 -7042
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/floricode-required-features.functions.d.ts +9518 -6923
- package/dist-lib/lib/floricode-required-features.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-customer-offer.functions.d.ts +9518 -6923
- package/dist-lib/lib/floriday-customer-offer.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-env.functions.d.ts +5742 -552
- package/dist-lib/lib/floriday-env.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-gateway.functions.d.ts +16126 -556
- package/dist-lib/lib/floriday-gateway.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-stock-supply.server.d.ts +53 -0
- package/dist-lib/lib/floriday-stock-supply.server.d.ts.map +1 -0
- package/dist-lib/lib/floriday-stock-supply.server.js +151 -0
- package/dist-lib/lib/floriday-vbn-required.functions.d.ts +5742 -552
- package/dist-lib/lib/floriday-vbn-required.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-warehouse.functions.d.ts +8338 -553
- package/dist-lib/lib/floriday-warehouse.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-writes.functions.d.ts +5742 -552
- package/dist-lib/lib/floriday-writes.functions.d.ts.map +1 -1
- package/dist-lib/lib/logistics-tasks.server.d.ts +17 -0
- package/dist-lib/lib/logistics-tasks.server.d.ts.map +1 -0
- package/dist-lib/lib/logistics-tasks.server.js +303 -0
- package/dist-lib/lib/module-runtime-config.functions.d.ts +1 -13
- package/dist-lib/lib/module-runtime-config.functions.d.ts.map +1 -1
- package/dist-lib/lib/module-runtime-config.functions.js +17 -93
- package/dist-lib/lib/module-runtime.server.d.ts +33 -0
- package/dist-lib/lib/module-runtime.server.d.ts.map +1 -0
- package/dist-lib/lib/module-runtime.server.js +184 -0
- package/dist-lib/lib/stock-sync.functions.d.ts +20452 -0
- package/dist-lib/lib/stock-sync.functions.d.ts.map +1 -0
- package/dist-lib/lib/stock-sync.functions.js +30 -0
- package/dist-lib/lib/supabase-admin.server.d.ts +15 -0
- package/dist-lib/lib/supabase-admin.server.d.ts.map +1 -0
- package/dist-lib/lib/supabase-admin.server.js +35 -0
- package/package.json +2 -2
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zelfregistratie van de module in de database waarin hij draait.
|
|
3
|
+
*
|
|
4
|
+
* De cron-functies `run_logistics_tasks_dispatch()` en
|
|
5
|
+
* `run_floriday_continuous_stock_sync()` bevatten geen hardgecodeerde host:
|
|
6
|
+
* ze lezen `module_runtime_config.voorraad_base_url` en
|
|
7
|
+
* `module_runtime_config.voorraad_hook_apikey`. Dit bestand schrijft die twee
|
|
8
|
+
* waarden weg zodra de module ergens een request afhandelt, zodat de cron
|
|
9
|
+
* out-of-the-box werkt in elke shell/database waar de module wordt gehangen —
|
|
10
|
+
* zonder handmatige instellingen en zonder iets in de UI.
|
|
11
|
+
*
|
|
12
|
+
* Server-only: nooit importeren vanuit componenten of client-code.
|
|
13
|
+
*/
|
|
14
|
+
const BASE_URL_KEY = "voorraad_base_url";
|
|
15
|
+
const APIKEY_KEY = "voorraad_hook_apikey";
|
|
16
|
+
/** Niet vaker dan eens per 5 minuten per worker-instantie schrijven. */
|
|
17
|
+
const THROTTLE_MS = 5 * 60000;
|
|
18
|
+
let lastRunAt = 0;
|
|
19
|
+
let inFlight = null;
|
|
20
|
+
function normalizeOrigin(raw) {
|
|
21
|
+
const trimmed = String(raw ?? "").trim();
|
|
22
|
+
if (!trimmed)
|
|
23
|
+
return null;
|
|
24
|
+
try {
|
|
25
|
+
const u = new URL(trimmed);
|
|
26
|
+
if (u.protocol !== "https:" && u.protocol !== "http:")
|
|
27
|
+
return null;
|
|
28
|
+
const host = u.hostname.toLowerCase();
|
|
29
|
+
// Lokale dev-origins nooit registreren: pg_net kan die niet bereiken.
|
|
30
|
+
if (host === "localhost" ||
|
|
31
|
+
host === "127.0.0.1" ||
|
|
32
|
+
host === "0.0.0.0" ||
|
|
33
|
+
host === "::1" ||
|
|
34
|
+
host.endsWith(".local")) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
return `${u.protocol}//${u.host}`;
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function originFromRequest(request) {
|
|
44
|
+
if (!request)
|
|
45
|
+
return null;
|
|
46
|
+
const forwardedHost = request.headers.get("x-forwarded-host") ?? request.headers.get("host");
|
|
47
|
+
if (forwardedHost) {
|
|
48
|
+
const proto = request.headers.get("x-forwarded-proto") ?? "https";
|
|
49
|
+
const fromHeaders = normalizeOrigin(`${proto}://${forwardedHost}`);
|
|
50
|
+
if (fromHeaders)
|
|
51
|
+
return fromHeaders;
|
|
52
|
+
}
|
|
53
|
+
return normalizeOrigin(request.url);
|
|
54
|
+
}
|
|
55
|
+
/** Pad dat de cron aanroept; wordt ook gebruikt om een host te verifiëren. */
|
|
56
|
+
const PROBE_PATH = "/api/public/hooks/floriday-continuous-stock";
|
|
57
|
+
/**
|
|
58
|
+
* Controleert of een host deze module écht bedient.
|
|
59
|
+
*
|
|
60
|
+
* Zonder deze check kan een shell-host worden vastgelegd die de module niet
|
|
61
|
+
* host: de cron krijgt dan eeuwig een 404-HTML-pagina terug en de wachtrij
|
|
62
|
+
* blijft ongemerkt staan. Zonder apikey hoort het endpoint 401 te geven —
|
|
63
|
+
* dat bewijst dat de route bestaat, zonder iets te verwerken.
|
|
64
|
+
*/
|
|
65
|
+
async function servesModule(baseUrl) {
|
|
66
|
+
try {
|
|
67
|
+
const res = await fetch(`${baseUrl}${PROBE_PATH}`, {
|
|
68
|
+
method: "POST",
|
|
69
|
+
headers: { "Content-Type": "application/json" },
|
|
70
|
+
body: "{}",
|
|
71
|
+
signal: AbortSignal.timeout(8000),
|
|
72
|
+
});
|
|
73
|
+
return res.status === 401 || res.status === 200;
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/** Kandidaten, in volgorde: PUBLIC_BASE_URL → request-origin → centrale shell-host. */
|
|
80
|
+
async function baseUrlCandidates(request) {
|
|
81
|
+
const out = [];
|
|
82
|
+
const push = (v) => {
|
|
83
|
+
if (v && !out.includes(v))
|
|
84
|
+
out.push(v);
|
|
85
|
+
};
|
|
86
|
+
push(normalizeOrigin(process.env.PUBLIC_BASE_URL));
|
|
87
|
+
push(originFromRequest(request));
|
|
88
|
+
try {
|
|
89
|
+
const { getShellHost } = await import("./centralSecrets.server");
|
|
90
|
+
push(normalizeOrigin(await getShellHost()));
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
// centrale module niet bereikbaar
|
|
94
|
+
}
|
|
95
|
+
return out;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Resolutie met verificatie: de eerste kandidaat die de module daadwerkelijk
|
|
99
|
+
* bedient wint. Bedient geen enkele kandidaat de module, dan wordt er niets
|
|
100
|
+
* geregistreerd (de bestaande, werkende waarde blijft staan).
|
|
101
|
+
*/
|
|
102
|
+
export async function resolveModuleBaseUrl(request) {
|
|
103
|
+
const candidates = await baseUrlCandidates(request);
|
|
104
|
+
for (const candidate of candidates) {
|
|
105
|
+
if (await servesModule(candidate))
|
|
106
|
+
return candidate;
|
|
107
|
+
}
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
function hookApiKey() {
|
|
111
|
+
const key = process.env.SUPABASE_PUBLISHABLE_KEY ??
|
|
112
|
+
process.env.SUPABASE_ANON_KEY ??
|
|
113
|
+
process.env.VITE_SUPABASE_PUBLISHABLE_KEY ??
|
|
114
|
+
"";
|
|
115
|
+
return key.trim() ? key.trim() : null;
|
|
116
|
+
}
|
|
117
|
+
async function upsertConfig(supabaseAdmin, key, value) {
|
|
118
|
+
const { data: existing } = await supabaseAdmin
|
|
119
|
+
.from("module_runtime_config")
|
|
120
|
+
.select("value")
|
|
121
|
+
.eq("key", key)
|
|
122
|
+
.maybeSingle();
|
|
123
|
+
if (existing?.value === value)
|
|
124
|
+
return false;
|
|
125
|
+
const { error } = await supabaseAdmin
|
|
126
|
+
.from("module_runtime_config")
|
|
127
|
+
.upsert({ key, value, updated_at: new Date().toISOString() }, { onConflict: "key" });
|
|
128
|
+
if (error)
|
|
129
|
+
throw new Error(error.message);
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
/** Schrijft basis-URL + hook-apikey weg (idempotent, schrijft alleen bij wijziging). */
|
|
133
|
+
export async function registerModuleRuntime(request) {
|
|
134
|
+
const baseUrl = await resolveModuleBaseUrl(request);
|
|
135
|
+
if (!baseUrl) {
|
|
136
|
+
return { ok: false, baseUrl: null, changed: false, reason: "geen origin resolvbaar" };
|
|
137
|
+
}
|
|
138
|
+
try {
|
|
139
|
+
const { supabaseAdmin } = await import("../integrations/supabase/client.server");
|
|
140
|
+
let changed = await upsertConfig(supabaseAdmin, BASE_URL_KEY, baseUrl);
|
|
141
|
+
const apikey = hookApiKey();
|
|
142
|
+
if (apikey) {
|
|
143
|
+
const apikeyChanged = await upsertConfig(supabaseAdmin, APIKEY_KEY, apikey);
|
|
144
|
+
changed = changed || apikeyChanged;
|
|
145
|
+
}
|
|
146
|
+
return { ok: true, baseUrl, changed };
|
|
147
|
+
}
|
|
148
|
+
catch (e) {
|
|
149
|
+
return {
|
|
150
|
+
ok: false,
|
|
151
|
+
baseUrl,
|
|
152
|
+
changed: false,
|
|
153
|
+
reason: e?.message ?? String(e),
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Fire-and-forget variant met throttle; veilig om bij élk request aan te roepen.
|
|
159
|
+
* Faalt nooit hard en logt alleen bij een echte fout.
|
|
160
|
+
*/
|
|
161
|
+
export function ensureModuleRuntimeRegistered(request) {
|
|
162
|
+
const now = Date.now();
|
|
163
|
+
if (inFlight || now - lastRunAt < THROTTLE_MS)
|
|
164
|
+
return;
|
|
165
|
+
lastRunAt = now;
|
|
166
|
+
inFlight = registerModuleRuntime(request)
|
|
167
|
+
.then((res) => {
|
|
168
|
+
if (!res.ok) {
|
|
169
|
+
// Mislukt: throttle resetten zodat een volgend request het opnieuw probeert.
|
|
170
|
+
lastRunAt = 0;
|
|
171
|
+
console.warn(`[voorraad] zelfregistratie mislukt: ${res.reason ?? "onbekend"}`);
|
|
172
|
+
}
|
|
173
|
+
else if (res.changed) {
|
|
174
|
+
console.info(`[voorraad] runtime geregistreerd op ${res.baseUrl}`);
|
|
175
|
+
}
|
|
176
|
+
})
|
|
177
|
+
.catch((e) => {
|
|
178
|
+
lastRunAt = 0;
|
|
179
|
+
console.warn("[voorraad] zelfregistratie fout:", e?.message ?? e);
|
|
180
|
+
})
|
|
181
|
+
.finally(() => {
|
|
182
|
+
inFlight = null;
|
|
183
|
+
});
|
|
184
|
+
}
|