@flowselections/floriday-authenticatie-module 1.0.28 → 1.0.30
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/TemplatePage.d.ts +1 -1
- package/dist-lib/components/TemplatePage.d.ts.map +1 -1
- package/dist-lib/components/floriday/FlorydayConnectionPage.d.ts +1 -1
- package/dist-lib/components/floriday/FlorydayConnectionPage.d.ts.map +1 -1
- package/dist-lib/components/floriday/FlorydaySyncHealthBanner.d.ts +1 -1
- package/dist-lib/components/floriday/FlorydaySyncHealthBanner.d.ts.map +1 -1
- package/dist-lib/components/floriday/FlorydaySyncJobsCard.d.ts +1 -1
- package/dist-lib/components/floriday/FlorydaySyncJobsCard.d.ts.map +1 -1
- package/dist-lib/components/floriday/TokenHealthCard.d.ts +1 -1
- package/dist-lib/components/floriday/TokenHealthCard.d.ts.map +1 -1
- package/dist-lib/components/settings/FloricodeSettingsCard.d.ts +1 -1
- package/dist-lib/components/settings/FloricodeSettingsCard.d.ts.map +1 -1
- package/dist-lib/components/settings/FlorydaySettingsCard.d.ts +1 -1
- package/dist-lib/components/settings/FlorydaySettingsCard.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
- package/dist-lib/lib/cron/index.d.ts +35 -0
- package/dist-lib/lib/cron/index.d.ts.map +1 -0
- package/dist-lib/lib/cron/index.js +49 -0
- package/dist-lib/lib/cron/refresh-floricode-codelists.d.ts +3 -0
- package/dist-lib/lib/cron/refresh-floricode-codelists.d.ts.map +1 -0
- package/dist-lib/lib/cron/refresh-floricode-codelists.js +26 -0
- package/dist-lib/lib/cron/refresh-floriday-reference-data.d.ts +3 -0
- package/dist-lib/lib/cron/refresh-floriday-reference-data.d.ts.map +1 -0
- package/dist-lib/lib/cron/refresh-floriday-reference-data.js +40 -0
- package/dist-lib/lib/cron/refresh-floriday-tokens.d.ts +3 -0
- package/dist-lib/lib/cron/refresh-floriday-tokens.d.ts.map +1 -0
- package/dist-lib/lib/cron/refresh-floriday-tokens.js +151 -0
- package/dist-lib/lib/cron/sync-connections.d.ts +3 -0
- package/dist-lib/lib/cron/sync-connections.d.ts.map +1 -0
- package/dist-lib/lib/cron/sync-connections.js +49 -0
- package/dist-lib/lib/cron/sync-floricode-all.d.ts +3 -0
- package/dist-lib/lib/cron/sync-floricode-all.d.ts.map +1 -0
- package/dist-lib/lib/cron/sync-floricode-all.js +23 -0
- package/dist-lib/lib/cron/sync-floricode-regulatory-features.d.ts +3 -0
- package/dist-lib/lib/cron/sync-floricode-regulatory-features.d.ts.map +1 -0
- package/dist-lib/lib/cron/sync-floricode-regulatory-features.js +31 -0
- package/dist-lib/lib/cron/sync-resource-compact.d.ts +4 -0
- package/dist-lib/lib/cron/sync-resource-compact.d.ts.map +1 -0
- package/dist-lib/lib/cron/sync-resource-compact.js +31 -0
- package/dist-lib/lib/cron/sync-resource.d.ts +6 -0
- package/dist-lib/lib/cron/sync-resource.d.ts.map +1 -0
- package/dist-lib/lib/cron/sync-resource.js +61 -0
- package/dist-lib/lib/cron/verify-floricode-characteristics-coverage.d.ts +3 -0
- package/dist-lib/lib/cron/verify-floricode-characteristics-coverage.d.ts.map +1 -0
- package/dist-lib/lib/cron/verify-floricode-characteristics-coverage.js +55 -0
- package/dist-lib/lib/error-page.js +30 -30
- package/dist-lib/lib/floricode.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-auction-letters.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-labels.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-public.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-stickers.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-sync.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-writes.functions.d.ts +6 -6
- package/dist-lib/lib/floriday-writes.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday.functions.d.ts +486 -18
- package/dist-lib/lib/floriday.functions.d.ts.map +1 -1
- package/package.json +475 -100
- package/dist-lib/assets/floriday-logo.png.asset.json +0 -11
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { FLORYDAY_STANDARD_SCOPE } from "../floriday-scopes";
|
|
2
|
+
const FLORYDAY_ENDPOINTS = {
|
|
3
|
+
staging: "https://idm.staging.floriday.io/oauth2/ausmw6b47z1BnlHkw0h7/v1/token",
|
|
4
|
+
live: "https://idm.floriday.io/oauth2/aus3testdcf2vyfs70i7/v1/token",
|
|
5
|
+
};
|
|
6
|
+
// De algemene token-refresh gebruikt alleen basisrechten. Module-specifieke
|
|
7
|
+
// rechten worden pas aangevraagd wanneer die module daadwerkelijk synchroniseert.
|
|
8
|
+
const DEFAULT_SCOPE = FLORYDAY_STANDARD_SCOPE;
|
|
9
|
+
const REFRESH_WINDOW_MS = 2 * 60 * 60 * 1000;
|
|
10
|
+
function sanitize(input) {
|
|
11
|
+
if (!input)
|
|
12
|
+
return "";
|
|
13
|
+
let s = String(input).normalize("NFKC");
|
|
14
|
+
s = s.replace(/[\u200B-\u200D\uFEFF]/g, "");
|
|
15
|
+
s = s.replace(/[\u202A-\u202E\u2066-\u2069]/g, "");
|
|
16
|
+
s = s.replace(/[\u00A0\u2007\u202F]/g, " ");
|
|
17
|
+
s = s.replace(/[\u2018\u2019]/g, "'").replace(/[\u201C\u201D]/g, '"');
|
|
18
|
+
s = s.replace(/[\u0000-\u001F\u007F]/g, "");
|
|
19
|
+
return s.trim();
|
|
20
|
+
}
|
|
21
|
+
async function refreshOne(admin, row) {
|
|
22
|
+
const res = await fetch(FLORYDAY_ENDPOINTS[row.environment], {
|
|
23
|
+
method: "POST",
|
|
24
|
+
headers: {
|
|
25
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
26
|
+
Accept: "application/json",
|
|
27
|
+
},
|
|
28
|
+
body: new URLSearchParams({
|
|
29
|
+
grant_type: "client_credentials",
|
|
30
|
+
client_id: sanitize(row.client_id),
|
|
31
|
+
client_secret: sanitize(row.client_secret),
|
|
32
|
+
scope: DEFAULT_SCOPE,
|
|
33
|
+
}).toString(),
|
|
34
|
+
});
|
|
35
|
+
const text = await res.text();
|
|
36
|
+
if (!res.ok) {
|
|
37
|
+
throw new Error(`Token request failed [${res.status}]: ${text.slice(0, 200)}`);
|
|
38
|
+
}
|
|
39
|
+
const json = JSON.parse(text);
|
|
40
|
+
const newExpiresAt = new Date(Date.now() + json.expires_in * 1000).toISOString();
|
|
41
|
+
const { error } = await admin
|
|
42
|
+
.from("floriday_connections")
|
|
43
|
+
.update({ access_token: json.access_token, token_expires_at: newExpiresAt })
|
|
44
|
+
.eq("id", row.id);
|
|
45
|
+
if (error)
|
|
46
|
+
throw new Error(`DB update failed: ${error.message}`);
|
|
47
|
+
return { id: row.id, environment: row.environment, expires_at: newExpiresAt };
|
|
48
|
+
}
|
|
49
|
+
export async function handleRefreshFlorydayTokens(request, supabase) {
|
|
50
|
+
console.log("[cron] refresh-floriday-tokens start");
|
|
51
|
+
try {
|
|
52
|
+
// Authenticate with Supabase anon key (cron uses apikey header).
|
|
53
|
+
const apikey = request.headers.get("apikey") ?? request.headers.get("x-api-key");
|
|
54
|
+
const expected = process.env.SUPABASE_PUBLISHABLE_KEY;
|
|
55
|
+
if (!expected || !apikey || apikey !== expected) {
|
|
56
|
+
return new Response("Unauthorized", { status: 401 });
|
|
57
|
+
}
|
|
58
|
+
const supabaseAdmin = supabase;
|
|
59
|
+
const { data: rows, error } = await supabaseAdmin
|
|
60
|
+
.from("floriday_connections")
|
|
61
|
+
.select("id, environment, client_id, client_secret, token_expires_at")
|
|
62
|
+
.eq("is_active", true);
|
|
63
|
+
if (error) {
|
|
64
|
+
await supabaseAdmin.from("floriday_token_refresh_log").insert({
|
|
65
|
+
connection_id: null,
|
|
66
|
+
environment: "staging",
|
|
67
|
+
ok: false,
|
|
68
|
+
error: `DB select failed: ${error.message}`.slice(0, 500),
|
|
69
|
+
});
|
|
70
|
+
return Response.json({ ok: false, error: error.message }, { status: 500 });
|
|
71
|
+
}
|
|
72
|
+
const now = Date.now();
|
|
73
|
+
const due = (rows ?? []).filter((r) => {
|
|
74
|
+
if (!r.client_id || !r.client_secret)
|
|
75
|
+
return false;
|
|
76
|
+
if (!r.token_expires_at)
|
|
77
|
+
return true;
|
|
78
|
+
return Date.parse(r.token_expires_at) - now < REFRESH_WINDOW_MS;
|
|
79
|
+
});
|
|
80
|
+
const results = [];
|
|
81
|
+
if (due.length === 0 && (rows?.length ?? 0) > 0) {
|
|
82
|
+
await supabaseAdmin.from("floriday_token_refresh_log").insert({
|
|
83
|
+
connection_id: rows[0].id,
|
|
84
|
+
environment: rows[0].environment,
|
|
85
|
+
ok: true,
|
|
86
|
+
expires_at: rows[0].token_expires_at,
|
|
87
|
+
error: "heartbeat: nog niet binnen refresh-window",
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
for (const r of due) {
|
|
91
|
+
try {
|
|
92
|
+
const out = await refreshOne(supabaseAdmin, {
|
|
93
|
+
id: r.id,
|
|
94
|
+
environment: r.environment,
|
|
95
|
+
client_id: r.client_id,
|
|
96
|
+
client_secret: r.client_secret,
|
|
97
|
+
});
|
|
98
|
+
results.push({ ...out, ok: true });
|
|
99
|
+
await supabaseAdmin.from("floriday_token_refresh_log").insert({
|
|
100
|
+
connection_id: r.id,
|
|
101
|
+
environment: r.environment,
|
|
102
|
+
ok: true,
|
|
103
|
+
expires_at: out.expires_at,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
catch (e) {
|
|
107
|
+
const msg = e?.message ?? "Onbekende fout";
|
|
108
|
+
results.push({
|
|
109
|
+
id: r.id,
|
|
110
|
+
environment: r.environment,
|
|
111
|
+
ok: false,
|
|
112
|
+
error: msg,
|
|
113
|
+
});
|
|
114
|
+
await supabaseAdmin.from("floriday_token_refresh_log").insert({
|
|
115
|
+
connection_id: r.id,
|
|
116
|
+
environment: r.environment,
|
|
117
|
+
ok: false,
|
|
118
|
+
error: String(msg).slice(0, 500),
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
await supabaseAdmin
|
|
123
|
+
.from("floriday_token_refresh_log")
|
|
124
|
+
.delete()
|
|
125
|
+
.lt("attempted_at", new Date(Date.now() - 14 * 24 * 60 * 60 * 1000).toISOString());
|
|
126
|
+
return Response.json({
|
|
127
|
+
ok: true,
|
|
128
|
+
checked: rows?.length ?? 0,
|
|
129
|
+
refreshed: results.filter((r) => r.ok).length,
|
|
130
|
+
failed: results.filter((r) => !r.ok).length,
|
|
131
|
+
results,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
catch (e) {
|
|
135
|
+
const msg = String(e?.message ?? e);
|
|
136
|
+
console.error("[cron] refresh-floriday-tokens crashed:", msg);
|
|
137
|
+
// best-effort log
|
|
138
|
+
try {
|
|
139
|
+
await supabase.from("floriday_token_refresh_log").insert({
|
|
140
|
+
connection_id: null,
|
|
141
|
+
environment: "staging",
|
|
142
|
+
ok: false,
|
|
143
|
+
error: `handler crash: ${msg}`.slice(0, 500),
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
// ignore
|
|
148
|
+
}
|
|
149
|
+
return Response.json({ ok: false, error: msg }, { status: 500 });
|
|
150
|
+
}
|
|
151
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-connections.d.ts","sourceRoot":"","sources":["../../../src/lib/cron/sync-connections.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAM5D,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,cAAc,GACvB,OAAO,CAAC,QAAQ,CAAC,CAyDnB"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Sync-runner voor `sync-floriday-connections`. Regel-voor-regel overgenomen
|
|
3
|
+
// uit `src/routes/api/public/cron/sync-floriday-connections.ts`. Roept de
|
|
4
|
+
// aparte `runFloridayConnectionsSync` aan (niet `runFloridayResourceSync`);
|
|
5
|
+
// envelope heeft géén `resource`-veld.
|
|
6
|
+
// ============================================================================
|
|
7
|
+
import { runFloridayConnectionsSync, } from "../floriday.functions";
|
|
8
|
+
export async function handleSyncConnections(request, supabase) {
|
|
9
|
+
console.log("[cron] sync-floriday-connections start");
|
|
10
|
+
try {
|
|
11
|
+
const apikey = request.headers.get("apikey") ?? request.headers.get("x-api-key");
|
|
12
|
+
const expected = process.env.SUPABASE_PUBLISHABLE_KEY;
|
|
13
|
+
if (!expected || !apikey || apikey !== expected) {
|
|
14
|
+
return new Response("Unauthorized", { status: 401 });
|
|
15
|
+
}
|
|
16
|
+
const { data: rows, error } = await supabase
|
|
17
|
+
.from("floriday_connections")
|
|
18
|
+
.select("id, environment")
|
|
19
|
+
.eq("is_active", true);
|
|
20
|
+
if (error) {
|
|
21
|
+
return Response.json({ ok: false, error: error.message }, { status: 500 });
|
|
22
|
+
}
|
|
23
|
+
const results = [];
|
|
24
|
+
for (const r of rows ?? []) {
|
|
25
|
+
try {
|
|
26
|
+
const out = await runFloridayConnectionsSync(supabase, r.environment);
|
|
27
|
+
results.push({ id: r.id, environment: r.environment, ok: true, ...out });
|
|
28
|
+
console.log(`[floriday-connections-sync] ${r.environment}: ${out.synced} synced (${out.fromSequence} → ${out.toSequence})`);
|
|
29
|
+
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
const msg = e?.message ?? "Onbekende fout";
|
|
32
|
+
results.push({ id: r.id, environment: r.environment, ok: false, error: msg });
|
|
33
|
+
console.error(`[floriday-connections-sync] ${r.environment} failed: ${msg}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return Response.json({
|
|
37
|
+
ok: true,
|
|
38
|
+
processed: results.length,
|
|
39
|
+
succeeded: results.filter((r) => r.ok).length,
|
|
40
|
+
failed: results.filter((r) => !r.ok).length,
|
|
41
|
+
results,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
const msg = String(e?.message ?? e);
|
|
46
|
+
console.error("[cron] sync-floriday-connections crashed:", msg);
|
|
47
|
+
return Response.json({ ok: false, error: msg }, { status: 500 });
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-floricode-all.d.ts","sourceRoot":"","sources":["../../../src/lib/cron/sync-floricode-all.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,cAAc,GACxB,OAAO,CAAC,QAAQ,CAAC,CAqBnB"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export async function handleSyncFloricodeAll(request, _supabase) {
|
|
2
|
+
console.log("[cron] sync-floricode-all start");
|
|
3
|
+
try {
|
|
4
|
+
const apikey = request.headers.get("apikey") ?? request.headers.get("x-api-key");
|
|
5
|
+
const expected = process.env.SUPABASE_PUBLISHABLE_KEY;
|
|
6
|
+
if (!expected || !apikey || apikey !== expected) {
|
|
7
|
+
return new Response("Unauthorized", { status: 401 });
|
|
8
|
+
}
|
|
9
|
+
const url = new URL(request.url);
|
|
10
|
+
const batchSize = Number(url.searchParams.get("batchSize") ?? "5000");
|
|
11
|
+
const maxBatches = Number(url.searchParams.get("maxBatchesPerResource") ?? "2");
|
|
12
|
+
const { syncAllFloricodeResources } = await import("../floricode-sync.server");
|
|
13
|
+
const result = await syncAllFloricodeResources({
|
|
14
|
+
batchSize: Number.isFinite(batchSize) ? batchSize : 5000,
|
|
15
|
+
maxBatchesPerResource: Number.isFinite(maxBatches) ? maxBatches : 2,
|
|
16
|
+
});
|
|
17
|
+
return Response.json(result);
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
console.error("[cron] sync-floricode-all crashed:", String(e?.message ?? e));
|
|
21
|
+
return Response.json({ ok: false, error: String(e?.message ?? e) }, { status: 500 });
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-floricode-regulatory-features.d.ts","sourceRoot":"","sources":["../../../src/lib/cron/sync-floricode-regulatory-features.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,wBAAsB,qCAAqC,CACzD,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,cAAc,GACvB,OAAO,CAAC,QAAQ,CAAC,CAkCnB"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export async function handleSyncFloricodeRegulatoryFeatures(request, supabase) {
|
|
2
|
+
console.log("[cron] sync-floricode-regulatory-features start");
|
|
3
|
+
try {
|
|
4
|
+
const apikey = request.headers.get("apikey") ?? request.headers.get("x-api-key");
|
|
5
|
+
const expected = process.env.SUPABASE_PUBLISHABLE_KEY;
|
|
6
|
+
if (!expected || !apikey || apikey !== expected) {
|
|
7
|
+
return new Response("Unauthorized", { status: 401 });
|
|
8
|
+
}
|
|
9
|
+
const { syncFloricodeRegulatoryFeatures } = await import("../floricode-regulatory-features");
|
|
10
|
+
const url = new URL(request.url);
|
|
11
|
+
const batchSize = Number(url.searchParams.get("batchSize") ?? "2000");
|
|
12
|
+
const maxBatchesRaw = url.searchParams.get("maxBatches");
|
|
13
|
+
// Default: 1 batch (~2k rijen) per invocation om Supabase Disk IO
|
|
14
|
+
// budget te sparen tijdens de initiële backfill. De cron tikt vaak
|
|
15
|
+
// genoeg om cumulatief door te lopen, met veel minder piek-IO.
|
|
16
|
+
const maxBatches = maxBatchesRaw == null ? 1 : Number(maxBatchesRaw);
|
|
17
|
+
const resumeParam = url.searchParams.get("resume");
|
|
18
|
+
const resume = resumeParam == null ? true : resumeParam !== "false";
|
|
19
|
+
const result = await syncFloricodeRegulatoryFeatures(supabase, {
|
|
20
|
+
batchSize: Number.isFinite(batchSize) ? batchSize : 2000,
|
|
21
|
+
maxBatches: Number.isFinite(maxBatches) ? maxBatches : 1,
|
|
22
|
+
resume,
|
|
23
|
+
});
|
|
24
|
+
return Response.json(result);
|
|
25
|
+
}
|
|
26
|
+
catch (e) {
|
|
27
|
+
const msg = String(e?.message ?? e);
|
|
28
|
+
console.error("[cron] sync-floricode-regulatory-features crashed:", msg);
|
|
29
|
+
return Response.json({ ok: false, error: msg }, { status: 500 });
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { SupabaseClient } from "@supabase/supabase-js";
|
|
2
|
+
import { type FlorydayResource } from "../floriday-sync.functions";
|
|
3
|
+
export declare function handleSyncResourceCompact(request: Request, supabase: SupabaseClient, resource: FlorydayResource): Promise<Response>;
|
|
4
|
+
//# sourceMappingURL=sync-resource-compact.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-resource-compact.d.ts","sourceRoot":"","sources":["../../../src/lib/cron/sync-resource-compact.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,4BAA4B,CAAC;AAGpC,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,gBAAgB,GACzB,OAAO,CAAC,QAAQ,CAAC,CAyBnB"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Compact-vorm sync-runner voor de 7 clock-/delivery-/warehouse-cron-routes.
|
|
3
|
+
// Regel-voor-regel overgenomen uit
|
|
4
|
+
// `src/routes/api/public/cron/sync-floriday-clock-presales.ts` — envelope
|
|
5
|
+
// bevat alleen {ok, resource, results}, results-rijen hebben géén
|
|
6
|
+
// `environment`, catch-msg-fallback = "err", geen top-level try/catch,
|
|
7
|
+
// geen start-log en geen DB-error-branch.
|
|
8
|
+
// ============================================================================
|
|
9
|
+
import { runFloridayResourceSync, } from "../floriday-sync.functions";
|
|
10
|
+
export async function handleSyncResourceCompact(request, supabase, resource) {
|
|
11
|
+
const RESOURCE = resource;
|
|
12
|
+
const apikey = request.headers.get("apikey") ?? request.headers.get("x-api-key");
|
|
13
|
+
const expected = process.env.SUPABASE_PUBLISHABLE_KEY;
|
|
14
|
+
if (!expected || !apikey || apikey !== expected)
|
|
15
|
+
return new Response("Unauthorized", { status: 401 });
|
|
16
|
+
const { data: rows } = await supabase
|
|
17
|
+
.from("floriday_connections")
|
|
18
|
+
.select("id, environment")
|
|
19
|
+
.eq("is_active", true);
|
|
20
|
+
const results = [];
|
|
21
|
+
for (const r of rows ?? []) {
|
|
22
|
+
try {
|
|
23
|
+
const out = await runFloridayResourceSync(supabase, r.environment, RESOURCE);
|
|
24
|
+
results.push({ id: r.id, ok: true, ...out });
|
|
25
|
+
}
|
|
26
|
+
catch (e) {
|
|
27
|
+
results.push({ id: r.id, ok: false, error: e?.message ?? "err" });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return Response.json({ ok: true, resource: RESOURCE, results });
|
|
31
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { SupabaseClient } from "@supabase/supabase-js";
|
|
2
|
+
import { type FlorydayResource } from "../floriday-sync.functions";
|
|
3
|
+
export declare function handleSyncResource(request: Request, supabase: SupabaseClient, resource: FlorydayResource, options?: {
|
|
4
|
+
logProgress?: boolean;
|
|
5
|
+
}): Promise<Response>;
|
|
6
|
+
//# sourceMappingURL=sync-resource.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-resource.d.ts","sourceRoot":"","sources":["../../../src/lib/cron/sync-resource.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,4BAA4B,CAAC;AAGpC,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,gBAAgB,EAC1B,OAAO,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,GAClC,OAAO,CAAC,QAAQ,CAAC,CAmDnB"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Standaard-vorm sync-runner voor de 16 "collections-vorm" cron-routes.
|
|
3
|
+
// Envelope, veldvolgorde, catch-tekst ("Onbekende fout"), start-log en
|
|
4
|
+
// DB-error-branch zijn regel-voor-regel overgenomen uit
|
|
5
|
+
// `src/routes/api/public/cron/sync-floriday-collections.ts`.
|
|
6
|
+
//
|
|
7
|
+
// De per-iteratie `console.log(... synced (${from} → ${to}))` is aanwezig in
|
|
8
|
+
// 8 van de 16 bronroutes (blanket-orders, carriers, contracts,
|
|
9
|
+
// customer-organizations, customer-stickers, fulfillment-orders, salesorders,
|
|
10
|
+
// trade-items) en afwezig in de andere 8. Om byte-identiek te blijven wordt
|
|
11
|
+
// dit gestuurd door de optionele `logProgress`-flag; de barrel-exports zetten
|
|
12
|
+
// hem per resource exact zoals de bron nu doet.
|
|
13
|
+
// ============================================================================
|
|
14
|
+
import { runFloridayResourceSync, } from "../floriday-sync.functions";
|
|
15
|
+
export async function handleSyncResource(request, supabase, resource, options) {
|
|
16
|
+
const RESOURCE = resource;
|
|
17
|
+
const logProgress = options?.logProgress === true;
|
|
18
|
+
console.log(`[cron] sync-floriday-${RESOURCE} start`);
|
|
19
|
+
try {
|
|
20
|
+
const apikey = request.headers.get("apikey") ?? request.headers.get("x-api-key");
|
|
21
|
+
const expected = process.env.SUPABASE_PUBLISHABLE_KEY;
|
|
22
|
+
if (!expected || !apikey || apikey !== expected) {
|
|
23
|
+
return new Response("Unauthorized", { status: 401 });
|
|
24
|
+
}
|
|
25
|
+
const { data: rows, error } = await supabase
|
|
26
|
+
.from("floriday_connections")
|
|
27
|
+
.select("id, environment")
|
|
28
|
+
.eq("is_active", true);
|
|
29
|
+
if (error) {
|
|
30
|
+
return Response.json({ ok: false, error: error.message }, { status: 500 });
|
|
31
|
+
}
|
|
32
|
+
const results = [];
|
|
33
|
+
for (const r of rows ?? []) {
|
|
34
|
+
try {
|
|
35
|
+
const out = await runFloridayResourceSync(supabase, r.environment, RESOURCE);
|
|
36
|
+
results.push({ id: r.id, environment: r.environment, ok: true, ...out });
|
|
37
|
+
if (logProgress) {
|
|
38
|
+
console.log(`[floriday-${RESOURCE}-sync] ${r.environment}: ${out.synced} synced (${out.fromSequence} → ${out.toSequence})`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
catch (e) {
|
|
42
|
+
const msg = e?.message ?? "Onbekende fout";
|
|
43
|
+
results.push({ id: r.id, environment: r.environment, ok: false, error: msg });
|
|
44
|
+
console.error(`[floriday-${RESOURCE}-sync] ${r.environment} failed: ${msg}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return Response.json({
|
|
48
|
+
ok: true,
|
|
49
|
+
resource: RESOURCE,
|
|
50
|
+
processed: results.length,
|
|
51
|
+
succeeded: results.filter((r) => r.ok).length,
|
|
52
|
+
failed: results.filter((r) => !r.ok).length,
|
|
53
|
+
results,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
catch (e) {
|
|
57
|
+
const msg = String(e?.message ?? e);
|
|
58
|
+
console.error(`[cron] sync-floriday-${RESOURCE} crashed:`, msg);
|
|
59
|
+
return Response.json({ ok: false, error: msg }, { status: 500 });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify-floricode-characteristics-coverage.d.ts","sourceRoot":"","sources":["../../../src/lib/cron/verify-floricode-characteristics-coverage.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,wBAAsB,4CAA4C,CAChE,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,cAAc,GACvB,OAAO,CAAC,QAAQ,CAAC,CA6DnB"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Cron-route: meet dekking van vbn-product-characteristic en herstel projectie
|
|
3
|
+
// als deze achterloopt op de raw RegulatoryFeatureType-cache.
|
|
4
|
+
// ============================================================================
|
|
5
|
+
export async function handleVerifyFloricodeCharacteristicsCoverage(request, supabase) {
|
|
6
|
+
try {
|
|
7
|
+
const apikey = request.headers.get("apikey") ?? request.headers.get("x-api-key");
|
|
8
|
+
const expected = process.env.SUPABASE_PUBLISHABLE_KEY;
|
|
9
|
+
if (!expected || !apikey || apikey !== expected) {
|
|
10
|
+
return new Response("Unauthorized", { status: 401 });
|
|
11
|
+
}
|
|
12
|
+
const [totalRes, projectedRes, rawCountRes] = await Promise.all([
|
|
13
|
+
supabase
|
|
14
|
+
.from("floricode_records")
|
|
15
|
+
.select("record_id", { count: "exact", head: true })
|
|
16
|
+
.eq("resource", "VbnProduct"),
|
|
17
|
+
supabase
|
|
18
|
+
.from("floriday_code_lists_cache")
|
|
19
|
+
.select("code", { count: "exact", head: true })
|
|
20
|
+
.eq("list_name", "vbn-product-characteristic"),
|
|
21
|
+
supabase.rpc("count_distinct_regulatory_products"),
|
|
22
|
+
]);
|
|
23
|
+
const totalVbn = totalRes?.count ?? null;
|
|
24
|
+
const projected = projectedRes?.count ?? null;
|
|
25
|
+
const vbnWithRaw = typeof rawCountRes?.data === "number"
|
|
26
|
+
? rawCountRes.data
|
|
27
|
+
: null;
|
|
28
|
+
let refreshed = false;
|
|
29
|
+
if (projected != null &&
|
|
30
|
+
vbnWithRaw != null &&
|
|
31
|
+
projected < vbnWithRaw) {
|
|
32
|
+
const { error } = await supabase.rpc("refresh_floricode_derived_code_lists");
|
|
33
|
+
if (error) {
|
|
34
|
+
console.warn("[verify-coverage] projection refresh failed:", error.message);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
refreshed = true;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return Response.json({
|
|
41
|
+
ok: true,
|
|
42
|
+
totals: {
|
|
43
|
+
vbn_products: totalVbn,
|
|
44
|
+
vbn_with_raw: vbnWithRaw,
|
|
45
|
+
vbn_projected: projected,
|
|
46
|
+
},
|
|
47
|
+
projection_refreshed: refreshed,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
catch (e) {
|
|
51
|
+
const msg = String(e?.message ?? e);
|
|
52
|
+
console.error("[verify-coverage] crashed:", msg);
|
|
53
|
+
return Response.json({ ok: false, error: msg }, { status: 500 });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -2,35 +2,35 @@
|
|
|
2
2
|
// MUST NOT import any other app code — it has to render even when the rest
|
|
3
3
|
// of the app fails to bundle/initialize.
|
|
4
4
|
export function renderErrorPage() {
|
|
5
|
-
return `<!doctype html>
|
|
6
|
-
<html lang="nl">
|
|
7
|
-
<head>
|
|
8
|
-
<meta charset="utf-8" />
|
|
9
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
10
|
-
<title>Er ging iets mis</title>
|
|
11
|
-
<style>
|
|
12
|
-
:root { color-scheme: light dark; }
|
|
13
|
-
body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
14
|
-
background: #0b0b0c; color: #f5f5f7; min-height: 100vh;
|
|
15
|
-
display: flex; align-items: center; justify-content: center; padding: 24px; }
|
|
16
|
-
.card { max-width: 420px; text-align: center; }
|
|
17
|
-
h1 { font-size: 24px; margin: 0 0 8px; }
|
|
18
|
-
p { color: #a1a1aa; margin: 0 0 24px; font-size: 14px; line-height: 1.5; }
|
|
19
|
-
.row { display: flex; gap: 12px; justify-content: center; }
|
|
20
|
-
button, a { font: inherit; padding: 10px 16px; border-radius: 8px; cursor: pointer;
|
|
21
|
-
border: 1px solid #333; background: transparent; color: inherit; text-decoration: none; }
|
|
22
|
-
button.primary { background: #f5f5f7; color: #0b0b0c; border-color: #f5f5f7; }
|
|
23
|
-
</style>
|
|
24
|
-
</head>
|
|
25
|
-
<body>
|
|
26
|
-
<div class="card">
|
|
27
|
-
<h1>Er ging iets mis</h1>
|
|
28
|
-
<p>Er is een onverwachte fout opgetreden tijdens het laden van de pagina. Probeer het opnieuw.</p>
|
|
29
|
-
<div class="row">
|
|
30
|
-
<button class="primary" onclick="location.reload()">Opnieuw proberen</button>
|
|
31
|
-
<a href="/">Naar startpagina</a>
|
|
32
|
-
</div>
|
|
33
|
-
</div>
|
|
34
|
-
</body>
|
|
5
|
+
return `<!doctype html>
|
|
6
|
+
<html lang="nl">
|
|
7
|
+
<head>
|
|
8
|
+
<meta charset="utf-8" />
|
|
9
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
10
|
+
<title>Er ging iets mis</title>
|
|
11
|
+
<style>
|
|
12
|
+
:root { color-scheme: light dark; }
|
|
13
|
+
body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
14
|
+
background: #0b0b0c; color: #f5f5f7; min-height: 100vh;
|
|
15
|
+
display: flex; align-items: center; justify-content: center; padding: 24px; }
|
|
16
|
+
.card { max-width: 420px; text-align: center; }
|
|
17
|
+
h1 { font-size: 24px; margin: 0 0 8px; }
|
|
18
|
+
p { color: #a1a1aa; margin: 0 0 24px; font-size: 14px; line-height: 1.5; }
|
|
19
|
+
.row { display: flex; gap: 12px; justify-content: center; }
|
|
20
|
+
button, a { font: inherit; padding: 10px 16px; border-radius: 8px; cursor: pointer;
|
|
21
|
+
border: 1px solid #333; background: transparent; color: inherit; text-decoration: none; }
|
|
22
|
+
button.primary { background: #f5f5f7; color: #0b0b0c; border-color: #f5f5f7; }
|
|
23
|
+
</style>
|
|
24
|
+
</head>
|
|
25
|
+
<body>
|
|
26
|
+
<div class="card">
|
|
27
|
+
<h1>Er ging iets mis</h1>
|
|
28
|
+
<p>Er is een onverwachte fout opgetreden tijdens het laden van de pagina. Probeer het opnieuw.</p>
|
|
29
|
+
<div class="row">
|
|
30
|
+
<button class="primary" onclick="location.reload()">Opnieuw proberen</button>
|
|
31
|
+
<a href="/">Naar startpagina</a>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
</body>
|
|
35
35
|
</html>`;
|
|
36
36
|
}
|