@flowselections/floriday-authenticatie-module 1.0.50 → 1.0.52

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 (38) hide show
  1. package/dist-lib/integrations/supabase/auth-middleware.d.ts +713 -6
  2. package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
  3. package/dist-lib/integrations/supabase/client.server.d.ts +713 -6
  4. package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
  5. package/dist-lib/integrations/supabase/types.d.ts +729 -6
  6. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  7. package/dist-lib/lib/cron/index.d.ts +1 -0
  8. package/dist-lib/lib/cron/index.d.ts.map +1 -1
  9. package/dist-lib/lib/cron/index.js +1 -0
  10. package/dist-lib/lib/cron/retry-floriday-documents.d.ts +28 -0
  11. package/dist-lib/lib/cron/retry-floriday-documents.d.ts.map +1 -0
  12. package/dist-lib/lib/cron/retry-floriday-documents.js +220 -0
  13. package/dist-lib/lib/floricode.functions.d.ts +4991 -42
  14. package/dist-lib/lib/floricode.functions.d.ts.map +1 -1
  15. package/dist-lib/lib/floriday-api-log.functions.d.ts +6417 -54
  16. package/dist-lib/lib/floriday-api-log.functions.d.ts.map +1 -1
  17. package/dist-lib/lib/floriday-auction-letters.functions.d.ts +713 -6
  18. package/dist-lib/lib/floriday-auction-letters.functions.d.ts.map +1 -1
  19. package/dist-lib/lib/floriday-auction-letters.functions.js +22 -0
  20. package/dist-lib/lib/floriday-document-queue.d.ts +21 -0
  21. package/dist-lib/lib/floriday-document-queue.d.ts.map +1 -0
  22. package/dist-lib/lib/floriday-document-queue.js +96 -0
  23. package/dist-lib/lib/floriday-labels.functions.d.ts +713 -6
  24. package/dist-lib/lib/floriday-labels.functions.d.ts.map +1 -1
  25. package/dist-lib/lib/floriday-public.functions.d.ts +4278 -36
  26. package/dist-lib/lib/floriday-public.functions.d.ts.map +1 -1
  27. package/dist-lib/lib/floriday-stickers.functions.d.ts +713 -6
  28. package/dist-lib/lib/floriday-stickers.functions.d.ts.map +1 -1
  29. package/dist-lib/lib/floriday-stickers.functions.js +23 -0
  30. package/dist-lib/lib/floriday-sync.functions.d.ts +2 -2
  31. package/dist-lib/lib/floriday-sync.functions.d.ts.map +1 -1
  32. package/dist-lib/lib/floriday-tray-stickers.functions.d.ts.map +1 -1
  33. package/dist-lib/lib/floriday-tray-stickers.functions.js +21 -0
  34. package/dist-lib/lib/floriday-writes.functions.d.ts +5704 -48
  35. package/dist-lib/lib/floriday-writes.functions.d.ts.map +1 -1
  36. package/dist-lib/lib/floriday.functions.d.ts +15730 -440
  37. package/dist-lib/lib/floriday.functions.d.ts.map +1 -1
  38. package/package.json +2 -2
@@ -36,4 +36,5 @@ export { handleVerifyFloricodeCharacteristicsCoverage } from "./verify-floricode
36
36
  export { handleProcessStockQueue, runStockQueueRound, maybeTickStockQueue } from "./process-stock-queue.js";
37
37
  export { handlePruneFlorydayApiLog, runPruneFlorydayApiLog } from "./prune-floriday-api-log.js";
38
38
  export { handleReconcileTradeItems, reconcileTradeItemsForConnection, } from "./reconcile-trade-items.js";
39
+ export { handleRetryFlorydayDocuments, runDocumentRetryRound } from "./retry-floriday-documents.js";
39
40
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/cron/index.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAK5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAI9D,eAAO,MAAM,4BAA4B,GAAI,KAAK,OAAO,EAAE,IAAI,cAAc,sBACzB,CAAC;AACrD,eAAO,MAAM,mBAAmB,GAAI,KAAK,OAAO,EAAE,IAAI,cAAc,sBAA8C,CAAC;AACnH,eAAO,MAAM,qBAAqB,GAAI,KAAK,OAAO,EAAE,IAAI,cAAc,sBAA+C,CAAC;AACtH,eAAO,MAAM,gCAAgC,GAAI,KAAK,OAAO,EAAE,IAAI,cAAc,sBACxB,CAAC;AAC1D,eAAO,MAAM,iCAAiC,GAAI,KAAK,OAAO,EAAE,IAAI,cAAc,sBACvB,CAAC;AAC5D,eAAO,MAAM,+BAA+B,GAAI,KAAK,OAAO,EAAE,IAAI,cAAc,sBACxB,CAAC;AACzD,eAAO,MAAM,qBAAqB,GAAI,KAAK,OAAO,EAAE,IAAI,cAAc,sBAAgD,CAAC;AACvH,eAAO,MAAM,uBAAuB,GAAI,KAAK,OAAO,EAAE,IAAI,cAAc,sBACF,CAAC;AAEvE,eAAO,MAAM,yBAAyB,GAAI,KAAK,OAAO,EAAE,IAAI,cAAc,sBACzB,CAAC;AAGlD,eAAO,MAAM,uBAAuB,GAAI,KAAK,OAAO,EAAE,IAAI,cAAc,sBACF,CAAC;AACvE,eAAO,MAAM,kBAAkB,GAAI,KAAK,OAAO,EAAE,IAAI,cAAc,sBACH,CAAC;AACjE,eAAO,MAAM,mBAAmB,GAAI,KAAK,OAAO,EAAE,IAAI,cAAc,sBACH,CAAC;AAClE,eAAO,MAAM,+BAA+B,GAAI,KAAK,OAAO,EAAE,IAAI,cAAc,sBACF,CAAC;AAC/E,eAAO,MAAM,0BAA0B,GAAI,KAAK,OAAO,EAAE,IAAI,cAAc,sBACF,CAAC;AAC1E,eAAO,MAAM,2BAA2B,GAAI,KAAK,OAAO,EAAE,IAAI,cAAc,sBACF,CAAC;AAC3E,eAAO,MAAM,qBAAqB,GAAI,KAAK,OAAO,EAAE,IAAI,cAAc,sBACF,CAAC;AACrE,eAAO,MAAM,oBAAoB,GAAI,KAAK,OAAO,EAAE,IAAI,cAAc,sBACF,CAAC;AAGpE,eAAO,MAAM,uBAAuB,GAAI,KAAK,OAAO,EAAE,IAAI,cAAc,sBAClB,CAAC;AACvD,eAAO,MAAM,uBAAuB,GAAI,KAAK,OAAO,EAAE,IAAI,cAAc,sBAClB,CAAC;AACvD,eAAO,MAAM,2BAA2B,GAAI,KAAK,OAAO,EAAE,IAAI,cAAc,sBAClB,CAAC;AAC3D,eAAO,MAAM,wBAAwB,GAAI,KAAK,OAAO,EAAE,IAAI,cAAc,sBAClB,CAAC;AACxD,eAAO,MAAM,kBAAkB,GAAI,KAAK,OAAO,EAAE,IAAI,cAAc,sBAAmD,CAAC;AACvH,eAAO,MAAM,gCAAgC,GAAI,KAAK,OAAO,EAAE,IAAI,cAAc,sBACjB,CAAC;AACjE,eAAO,MAAM,oBAAoB,GAAI,KAAK,OAAO,EAAE,IAAI,cAAc,sBACnB,CAAC;AAGnD,eAAO,MAAM,6BAA6B,GAAI,KAAK,OAAO,EAAE,IAAI,cAAc,sBAAmC,CAAC;AAGlH,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,qCAAqC,EAAE,MAAM,yCAAyC,CAAC;AAChG,OAAO,EAAE,+BAA+B,EAAE,MAAM,kCAAkC,CAAC;AACnF,OAAO,EAAE,kCAAkC,EAAE,MAAM,sCAAsC,CAAC;AAC1F,OAAO,EAAE,2BAA2B,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,EAAE,4CAA4C,EAAE,MAAM,gDAAgD,CAAC;AAC9G,OAAO,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC5G,OAAO,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAChG,OAAO,EACL,yBAAyB,EACzB,gCAAgC,GACjC,MAAM,4BAA4B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/cron/index.ts"],"names":[],"mappings":"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"}
@@ -51,3 +51,4 @@ export { handleVerifyFloricodeCharacteristicsCoverage } from "./verify-floricode
51
51
  export { handleProcessStockQueue, runStockQueueRound, maybeTickStockQueue } from "./process-stock-queue.js";
52
52
  export { handlePruneFlorydayApiLog, runPruneFlorydayApiLog } from "./prune-floriday-api-log.js";
53
53
  export { handleReconcileTradeItems, reconcileTradeItemsForConnection, } from "./reconcile-trade-items.js";
54
+ export { handleRetryFlorydayDocuments, runDocumentRetryRound } from "./retry-floriday-documents.js";
@@ -0,0 +1,28 @@
1
+ import type { SupabaseClient } from "@supabase/supabase-js";
2
+ import type { FlorydayEnvironment } from "../floriday.functions.js";
3
+ interface QueueRow {
4
+ id: string;
5
+ connection_id: string;
6
+ environment: FlorydayEnvironment;
7
+ kind: "customer-sticker" | "auction-letter" | "tray-stickers";
8
+ document_key: string;
9
+ params: Record<string, any>;
10
+ order_ref: string | null;
11
+ attempts: number;
12
+ max_attempts: number;
13
+ }
14
+ /** Geeft een reden terug als de onderliggende order is geannuleerd. */
15
+ export declare function documentCancelReason(sb: SupabaseClient, row: QueueRow): Promise<string | null>;
16
+ export declare function runDocumentRetryRound(sb: SupabaseClient): Promise<{
17
+ picked: number;
18
+ done: number;
19
+ retry: number;
20
+ failed: number;
21
+ cancelled: number;
22
+ paused: boolean;
23
+ pauseReason: string | null;
24
+ }>;
25
+ /** Cron-route: herhaalpogingen voor documenten. */
26
+ export declare function handleRetryFlorydayDocuments(request: Request, supabase: SupabaseClient): Promise<Response>;
27
+ export {};
28
+ //# sourceMappingURL=retry-floriday-documents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry-floriday-documents.d.ts","sourceRoot":"","sources":["../../../src/lib/cron/retry-floriday-documents.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAU5D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAMpE,UAAU,QAAQ;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,mBAAmB,CAAC;IACjC,IAAI,EAAE,kBAAkB,GAAG,gBAAgB,GAAG,eAAe,CAAC;IAC9D,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB;AAKD,uEAAuE;AACvE,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,cAAc,EAClB,GAAG,EAAE,QAAQ,GACZ,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA8DxB;AA2BD,wBAAsB,qBAAqB,CAAC,EAAE,EAAE,cAAc;;;;;;;iBAaiD,MAAM,GAAG,IAAI;GAiF3H;AAED,mDAAmD;AACnD,wBAAsB,4BAA4B,CAChD,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,cAAc,GACvB,OAAO,CAAC,QAAQ,CAAC,CAgBnB"}
@@ -0,0 +1,220 @@
1
+ // ============================================================================
2
+ // Automatische herhaalpogingen voor Floriday-documenten (achtergrond).
3
+ // ----------------------------------------------------------------------------
4
+ // Verwerkt `floriday_document_fetch_queue`: klantstickers, veilingbrieven en
5
+ // fuststickers. Verzendbrief/logistiek label horen bij de Logistiek Engine.
6
+ //
7
+ // - Maximaal DOCUMENT_QUEUE_MAX_ATTEMPTS pogingen, oplopende wachttijd.
8
+ // - Na de limiet, of bij een blijvende fout (4xx behalve 408/429): "failed".
9
+ // - Is de onderliggende order/aanbod geannuleerd: direct "cancelled".
10
+ // - Begrensd per ronde (BATCH) en onder de gedeelde job-lock.
11
+ // ============================================================================
12
+ import { withJobLock } from "./job-lock.js";
13
+ import { DOCUMENT_QUEUE_BACKOFF_MIN, DOCUMENT_QUEUE_TABLE, httpStatusFromError, } from "../floriday-document-queue.js";
14
+ import { resolveCustomerSticker } from "../floriday-stickers.functions.js";
15
+ import { resolveAuctionLetter } from "../floriday-auction-letters.functions.js";
16
+ import { resolveTrayStickers } from "../floriday-tray-stickers.functions.js";
17
+ const BATCH = 20;
18
+ const LOCK_STALE_MS = 10 * 60000;
19
+ const OWNER = "retry-floriday-documents";
20
+ const isCancelled = (status, deleted) => deleted === true || String(status ?? "").toUpperCase() === "CANCELLED";
21
+ /** Geeft een reden terug als de onderliggende order is geannuleerd. */
22
+ export async function documentCancelReason(sb, row) {
23
+ const cid = row.connection_id;
24
+ const salesOrderCancelled = async (salesOrderId) => {
25
+ const { data } = await sb
26
+ .from("floriday_salesorders_cache")
27
+ .select("status, is_deleted")
28
+ .eq("connection_id", cid)
29
+ .eq("floriday_id", salesOrderId)
30
+ .maybeSingle();
31
+ return data && isCancelled(data.status, data.is_deleted);
32
+ };
33
+ if (row.kind === "customer-sticker") {
34
+ const { data: st } = await sb
35
+ .from("floriday_customer_stickers_cache")
36
+ .select("sales_order_id, status, is_deleted")
37
+ .eq("connection_id", cid)
38
+ .eq("floriday_id", row.params.stickerId)
39
+ .maybeSingle();
40
+ if (st && isCancelled(st.status, st.is_deleted)) {
41
+ return "Sticker in Floriday geannuleerd of verwijderd";
42
+ }
43
+ const so = st?.sales_order_id;
44
+ if (so && (await salesOrderCancelled(so)))
45
+ return `Verkooporder ${so} in Floriday geannuleerd`;
46
+ return null;
47
+ }
48
+ if (row.kind === "auction-letter") {
49
+ const { data } = await sb
50
+ .from("floriday_clock_supplies_cache")
51
+ .select("status, is_deleted")
52
+ .eq("connection_id", cid)
53
+ .eq("floriday_id", row.params.clockSupplyId)
54
+ .maybeSingle();
55
+ if (data && isCancelled(data.status, data.is_deleted)) {
56
+ return "Klokaanbod in Floriday geannuleerd of verwijderd";
57
+ }
58
+ return null;
59
+ }
60
+ // tray-stickers: delivery-order + bijbehorende fulfillment-orders
61
+ const doId = row.params.deliveryOrderId;
62
+ const { data: d } = await sb
63
+ .from("floriday_delivery_orders_cache")
64
+ .select("status, is_deleted, data")
65
+ .eq("connection_id", cid)
66
+ .eq("floriday_id", doId)
67
+ .maybeSingle();
68
+ if (d && isCancelled(d.status, d.is_deleted)) {
69
+ return `Leveropdracht ${doId} in Floriday geannuleerd`;
70
+ }
71
+ const { data: fos } = await sb
72
+ .from("floriday_fulfillment_orders_cache")
73
+ .select("status, is_deleted")
74
+ .eq("connection_id", cid)
75
+ .eq("delivery_order_id", doId);
76
+ if (fos && fos.length > 0 && fos.every((f) => isCancelled(f.status, f.is_deleted))) {
77
+ return `Fulfillment-order(s) voor leveropdracht ${doId} in Floriday geannuleerd`;
78
+ }
79
+ const so = d?.data?.salesOrderId;
80
+ if (so && (await salesOrderCancelled(so)))
81
+ return `Verkooporder ${so} in Floriday geannuleerd`;
82
+ return null;
83
+ }
84
+ async function attempt(sb, row) {
85
+ const env = row.environment;
86
+ if (row.kind === "customer-sticker") {
87
+ await resolveCustomerSticker(sb, { environment: env, stickerId: row.params.stickerId });
88
+ }
89
+ else if (row.kind === "auction-letter") {
90
+ await resolveAuctionLetter(sb, {
91
+ environment: env,
92
+ clockSupplyId: row.params.clockSupplyId,
93
+ auctionLetterCode: row.params.auctionLetterCode ?? null,
94
+ });
95
+ }
96
+ else {
97
+ await resolveTrayStickers(sb, { environment: env, deliveryOrderId: row.params.deliveryOrderId });
98
+ }
99
+ }
100
+ function isPermanent(status, msg) {
101
+ if (/Geen actieve Floriday-koppeling|token|Central Auth/i.test(msg))
102
+ return false;
103
+ if (status == null)
104
+ return false;
105
+ return status >= 400 && status < 500 && status !== 408 && status !== 429;
106
+ }
107
+ function isCancelledResponse(status, msg) {
108
+ return (status === 404 || status === 410 || status === 409) && /cancel|geannuleerd/i.test(msg);
109
+ }
110
+ export async function runDocumentRetryRound(sb) {
111
+ const nowIso = new Date().toISOString();
112
+ const staleIso = new Date(Date.now() - LOCK_STALE_MS).toISOString();
113
+ const { data: due, error } = await sb
114
+ .from(DOCUMENT_QUEUE_TABLE)
115
+ .select("id, connection_id, environment, kind, document_key, params, order_ref, attempts, max_attempts")
116
+ .eq("status", "pending")
117
+ .lte("next_attempt_at", nowIso)
118
+ .or(`locked_at.is.null,locked_at.lt.${staleIso}`)
119
+ .order("next_attempt_at", { ascending: true })
120
+ .limit(BATCH);
121
+ if (error)
122
+ throw new Error(error.message);
123
+ const summary = { picked: 0, done: 0, retry: 0, failed: 0, cancelled: 0, paused: false, pauseReason: null };
124
+ for (const r of (due ?? [])) {
125
+ // Claim (optimistisch): alleen als nog pending en niet vergrendeld.
126
+ const { data: claimed } = await sb
127
+ .from(DOCUMENT_QUEUE_TABLE)
128
+ .update({ locked_at: new Date().toISOString(), locked_by: OWNER })
129
+ .eq("id", r.id)
130
+ .eq("status", "pending")
131
+ .or(`locked_at.is.null,locked_at.lt.${staleIso}`)
132
+ .select("id");
133
+ if (!claimed || claimed.length === 0)
134
+ continue;
135
+ summary.picked++;
136
+ const cancel = await documentCancelReason(sb, r).catch(() => null);
137
+ if (cancel) {
138
+ await sb.from(DOCUMENT_QUEUE_TABLE).update({
139
+ status: "cancelled", cancelled_reason: cancel, completed_at: new Date().toISOString(),
140
+ locked_at: null, locked_by: null,
141
+ }).eq("id", r.id);
142
+ summary.cancelled++;
143
+ console.log(`[document-retry] ${r.kind} ${r.document_key}: gestopt — ${cancel}`);
144
+ continue;
145
+ }
146
+ try {
147
+ await attempt(sb, r);
148
+ await sb.from(DOCUMENT_QUEUE_TABLE).update({
149
+ status: "done", attempts: r.attempts + 1, completed_at: new Date().toISOString(),
150
+ locked_at: null, locked_by: null,
151
+ }).eq("id", r.id);
152
+ summary.done++;
153
+ }
154
+ catch (e) {
155
+ const msg = String(e?.message ?? e).slice(0, 1000);
156
+ const http = httpStatusFromError(e);
157
+ // Geen koppeling of tokenprobleem: ronde pauzeren, poging niet tellen.
158
+ if (/Geen actieve Floriday-koppeling|token-aanvraag|Central Auth|CENTRAL_AUTH/i.test(msg)) {
159
+ await sb.from(DOCUMENT_QUEUE_TABLE).update({
160
+ last_error: msg, last_http_status: http, locked_at: null, locked_by: null,
161
+ next_attempt_at: new Date(Date.now() + DOCUMENT_QUEUE_BACKOFF_MIN[0] * 60000).toISOString(),
162
+ }).eq("id", r.id);
163
+ summary.paused = true;
164
+ summary.pauseReason = msg;
165
+ break;
166
+ }
167
+ if (isCancelledResponse(http, msg)) {
168
+ await sb.from(DOCUMENT_QUEUE_TABLE).update({
169
+ status: "cancelled", cancelled_reason: `Floriday meldt annulering: ${msg}`,
170
+ attempts: r.attempts + 1, last_error: msg, last_http_status: http,
171
+ completed_at: new Date().toISOString(), locked_at: null, locked_by: null,
172
+ }).eq("id", r.id);
173
+ summary.cancelled++;
174
+ continue;
175
+ }
176
+ const attempts = r.attempts + 1;
177
+ const permanent = isPermanent(http, msg);
178
+ if (permanent || attempts >= r.max_attempts) {
179
+ await sb.from(DOCUMENT_QUEUE_TABLE).update({
180
+ status: "failed", attempts, last_error: permanent
181
+ ? `Blijvende fout (geen nieuwe poging): ${msg}`
182
+ : `Na ${attempts} pogingen mislukt: ${msg}`,
183
+ last_http_status: http, completed_at: new Date().toISOString(),
184
+ locked_at: null, locked_by: null,
185
+ }).eq("id", r.id);
186
+ summary.failed++;
187
+ console.error(`[document-retry] ${r.kind} ${r.document_key}: definitief mislukt — ${msg}`);
188
+ }
189
+ else {
190
+ const wait = DOCUMENT_QUEUE_BACKOFF_MIN[Math.min(attempts, DOCUMENT_QUEUE_BACKOFF_MIN.length - 1)];
191
+ await sb.from(DOCUMENT_QUEUE_TABLE).update({
192
+ attempts, last_error: msg, last_http_status: http,
193
+ next_attempt_at: new Date(Date.now() + wait * 60000).toISOString(),
194
+ locked_at: null, locked_by: null,
195
+ }).eq("id", r.id);
196
+ summary.retry++;
197
+ }
198
+ }
199
+ }
200
+ return summary;
201
+ }
202
+ /** Cron-route: herhaalpogingen voor documenten. */
203
+ export async function handleRetryFlorydayDocuments(request, supabase) {
204
+ try {
205
+ const apikey = request.headers.get("apikey") ?? request.headers.get("x-api-key");
206
+ const expected = process.env.SUPABASE_PUBLISHABLE_KEY;
207
+ if (!expected || !apikey || apikey !== expected) {
208
+ return new Response("Unauthorized", { status: 401 });
209
+ }
210
+ return await withJobLock(supabase, "floriday-sync:document-retry", async () => {
211
+ const summary = await runDocumentRetryRound(supabase);
212
+ return Response.json({ ok: true, resource: "document-retry", ...summary });
213
+ });
214
+ }
215
+ catch (e) {
216
+ const msg = String(e?.message ?? e);
217
+ console.error("[cron] retry-floriday-documents crashed:", msg);
218
+ return Response.json({ ok: false, error: msg }, { status: 500 });
219
+ }
220
+ }