@agent-native/core 0.13.1 → 0.14.0
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/agent/production-agent.d.ts +23 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +82 -1
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +8 -2
- package/dist/agent/run-store.js.map +1 -1
- package/dist/agent/types.d.ts +1 -1
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +1 -1
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/ConnectBuilderCard.d.ts.map +1 -1
- package/dist/client/ConnectBuilderCard.js +24 -0
- package/dist/client/ConnectBuilderCard.js.map +1 -1
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +10 -1
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/extensions/ExtensionsSidebarSection.js +1 -1
- package/dist/client/extensions/ExtensionsSidebarSection.js.map +1 -1
- package/dist/client/use-db-sync.d.ts.map +1 -1
- package/dist/client/use-db-sync.js +3 -1
- package/dist/client/use-db-sync.js.map +1 -1
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +9 -0
- package/dist/db/client.js.map +1 -1
- package/dist/db/create-get-db.d.ts.map +1 -1
- package/dist/db/create-get-db.js +7 -0
- package/dist/db/create-get-db.js.map +1 -1
- package/dist/extensions/actions.js +1 -1
- package/dist/extensions/actions.js.map +1 -1
- package/dist/extensions/fetch-tool.d.ts.map +1 -1
- package/dist/extensions/fetch-tool.js +46 -5
- package/dist/extensions/fetch-tool.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +73 -7
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-discovery.d.ts +21 -0
- package/dist/server/agent-discovery.d.ts.map +1 -1
- package/dist/server/agent-discovery.js +18 -3
- package/dist/server/agent-discovery.js.map +1 -1
- package/dist/server/auth.d.ts +27 -0
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +71 -12
- package/dist/server/auth.js.map +1 -1
- package/dist/server/better-auth-instance.js +13 -0
- package/dist/server/better-auth-instance.js.map +1 -1
- package/dist/server/google-auth-mode.d.ts +20 -0
- package/dist/server/google-auth-mode.d.ts.map +1 -0
- package/dist/server/google-auth-mode.js +20 -0
- package/dist/server/google-auth-mode.js.map +1 -0
- package/dist/server/google-auth-plugin.d.ts +7 -0
- package/dist/server/google-auth-plugin.d.ts.map +1 -1
- package/dist/server/google-auth-plugin.js +21 -5
- package/dist/server/google-auth-plugin.js.map +1 -1
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/onboarding-html.d.ts +7 -0
- package/dist/server/onboarding-html.d.ts.map +1 -1
- package/dist/server/onboarding-html.js +22 -3
- package/dist/server/onboarding-html.js.map +1 -1
- package/dist/server/sentry.d.ts.map +1 -1
- package/dist/server/sentry.js +41 -0
- package/dist/server/sentry.js.map +1 -1
- package/package.json +1 -1
|
@@ -37,7 +37,9 @@ async function fetchPollJson(pollUrl, since, interval) {
|
|
|
37
37
|
const res = await fetch(`${pollUrl}?since=${since}`, controller ? { signal: controller.signal } : undefined);
|
|
38
38
|
if (!res.ok)
|
|
39
39
|
throw new Error("HTTP " + res.status);
|
|
40
|
-
|
|
40
|
+
// Await the json before the finally so a body-stream abort doesn't
|
|
41
|
+
// produce a dangling promise that escapes as an unhandled rejection.
|
|
42
|
+
return await res.json();
|
|
41
43
|
}
|
|
42
44
|
finally {
|
|
43
45
|
if (timeout)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-db-sync.js","sourceRoot":"","sources":["../../src/client/use-db-sync.ts"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport { agentNativePath } from \"./api-path.js\";\n\ninterface QueryClient {\n invalidateQueries(opts?: { queryKey?: string[] }): void;\n}\n\nconst POLL_ABORT_MIN_MS = 10_000;\nconst SSE_FALLBACK_INTERVAL_MS = 15_000;\n\ntype SyncEvent = {\n version?: number;\n source?: string;\n type?: string;\n key?: string;\n requestSource?: string;\n [k: string]: unknown;\n};\n\ntype PollResponse = {\n version: number;\n events: SyncEvent[];\n};\n\nfunction getPollAbortMs(interval: number): number {\n return Math.max(POLL_ABORT_MIN_MS, interval * 4);\n}\n\nfunction isDocumentHidden(): boolean {\n return (\n typeof document !== \"undefined\" && document.visibilityState === \"hidden\"\n );\n}\n\nfunction resolveSseUrl(sseUrl: string | false | undefined): string | false {\n if (sseUrl === false) return false;\n return agentNativePath(sseUrl ?? \"/_agent-native/events\");\n}\n\nfunction normalizeEventPayload(payload: unknown): SyncEvent[] {\n if (!payload || typeof payload !== \"object\") return [];\n const record = payload as { type?: unknown; events?: unknown };\n if (record.type === \"batch\" && Array.isArray(record.events)) {\n return record.events.filter(\n (event): event is SyncEvent => !!event && typeof event === \"object\",\n );\n }\n if (Array.isArray(record.events)) {\n return record.events.filter(\n (event): event is SyncEvent => !!event && typeof event === \"object\",\n );\n }\n return [payload as SyncEvent];\n}\n\nfunction eventVersion(event: SyncEvent): number {\n return typeof event.version === \"number\" ? event.version : 0;\n}\n\nasync function fetchPollJson<T>(\n pollUrl: string,\n since: number,\n interval: number,\n): Promise<T> {\n const controller =\n typeof AbortController === \"undefined\" ? null : new AbortController();\n const timeout = controller\n ? setTimeout(() => controller.abort(), getPollAbortMs(interval))\n : null;\n\n try {\n const res = await fetch(\n `${pollUrl}?since=${since}`,\n controller ? { signal: controller.signal } : undefined,\n );\n if (!res.ok) throw new Error(\"HTTP \" + res.status);\n return res.json();\n } finally {\n if (timeout) clearTimeout(timeout);\n }\n}\n\n/**\n * Hook that listens to /_agent-native/events for DB change events and\n * invalidates react-query caches when changes are detected. Falls back to\n * /_agent-native/poll so cross-process/serverless writes still show up.\n *\n * Works in all deployment environments (serverless, edge, long-lived server).\n * SSE is the fast path; polling is the safety net.\n *\n * @param options.queryClient - The react-query QueryClient instance\n * @param options.queryKeys - Array of query key prefixes to invalidate on change.\n * Default: [\"data\"]\n * @param options.pollUrl - Poll endpoint URL. Default: \"/_agent-native/poll\"\n * @param options.sseUrl - SSE endpoint URL. Default: \"/_agent-native/events\".\n * Pass false to disable SSE and use polling only.\n * @param options.onEvent - Optional callback for each change event\n * @param options.interval - Poll interval in ms. Default: 2000\n * @param options.fallbackInterval - Poll interval while SSE is connected.\n * Default: 15000\n * @param options.pauseWhenHidden - Pause polling while the tab is hidden.\n * Default: true\n * @param options.ignoreSource - Skip events whose `requestSource` matches this\n * value. Use a per-tab ID so the UI ignores its own writes while still\n * picking up changes from other tabs, agents, and scripts.\n */\nexport function useDbSync(\n options: {\n queryClient?: QueryClient;\n queryKeys?: string[];\n pollUrl?: string;\n sseUrl?: string | false;\n /** @deprecated Use pollUrl instead */\n eventsUrl?: string;\n onEvent?: (data: any) => void;\n interval?: number;\n fallbackInterval?: number;\n pauseWhenHidden?: boolean;\n ignoreSource?: string;\n } = {},\n): void {\n const {\n queryClient,\n queryKeys = [\"data\"],\n pollUrl = agentNativePath(options.eventsUrl ?? \"/_agent-native/poll\"),\n sseUrl = resolveSseUrl(options.sseUrl),\n interval = 2000,\n fallbackInterval = Math.max(\n options.fallbackInterval ?? SSE_FALLBACK_INTERVAL_MS,\n interval,\n ),\n pauseWhenHidden = true,\n } = options;\n\n const onEventRef = useRef(options.onEvent);\n onEventRef.current = options.onEvent;\n\n const keysRef = useRef(queryKeys);\n keysRef.current = queryKeys;\n\n const ignoreSourceRef = useRef(options.ignoreSource);\n ignoreSourceRef.current = options.ignoreSource;\n\n useEffect(() => {\n let versionRef = 0;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let stopped = false;\n let inFlight = false;\n let eventSource: EventSource | null = null;\n let sseConnected = false;\n\n function schedulePoll() {\n if (stopped) return;\n if (pauseWhenHidden && isDocumentHidden()) return;\n if (timer) clearTimeout(timer);\n timer = setTimeout(\n () => {\n timer = null;\n void poll();\n },\n sseConnected ? fallbackInterval : interval,\n );\n }\n\n function invalidateForEvents(events: SyncEvent[]) {\n const ignore = ignoreSourceRef.current;\n const relevant = ignore\n ? events.filter((e) => e.requestSource !== ignore)\n : events;\n\n if (relevant.length > 0 && queryClient) {\n for (const key of keysRef.current) {\n queryClient.invalidateQueries({ queryKey: [key] });\n }\n\n // Framework-level invalidation: always invalidate framework query\n // keys on any non-own change event so that mutating actions\n // (agent or HTTP) auto-refresh the UI — regardless of how the\n // template configured queryKeys / onEvent.\n queryClient.invalidateQueries({ queryKey: [\"action\"] });\n queryClient.invalidateQueries({ queryKey: [\"extension\"] });\n queryClient.invalidateQueries({ queryKey: [\"extensions\"] });\n queryClient.invalidateQueries({ queryKey: [\"extension-slots\"] });\n queryClient.invalidateQueries({ queryKey: [\"slot-installs\"] });\n queryClient.invalidateQueries({ queryKey: [\"slot-available\"] });\n queryClient.invalidateQueries({ queryKey: [\"tool\"] });\n queryClient.invalidateQueries({ queryKey: [\"tools\"] });\n queryClient.invalidateQueries({ queryKey: [\"app-state\"] });\n queryClient.invalidateQueries({ queryKey: [\"navigate-command\"] });\n queryClient.invalidateQueries({ queryKey: [\"show-questions\"] });\n queryClient.invalidateQueries({ queryKey: [\"__set_url__\"] });\n }\n\n // Always forward all events to onEvent — templates can decide.\n for (const evt of events) {\n onEventRef.current?.(evt);\n }\n }\n\n function applyEvents(events: SyncEvent[], version?: number) {\n const freshEvents = events.filter((event) => {\n const version = eventVersion(event);\n return version === 0 || version > versionRef;\n });\n\n if (freshEvents.length > 0) {\n invalidateForEvents(freshEvents);\n }\n\n const maxEventVersion = freshEvents.reduce(\n (max, event) => Math.max(max, eventVersion(event)),\n 0,\n );\n versionRef = Math.max(versionRef, version ?? 0, maxEventVersion);\n }\n\n function closeEvents() {\n if (!eventSource) return;\n eventSource.close();\n eventSource = null;\n sseConnected = false;\n }\n\n function connectEvents() {\n if (\n stopped ||\n !sseUrl ||\n eventSource ||\n typeof EventSource === \"undefined\" ||\n (pauseWhenHidden && isDocumentHidden())\n ) {\n return;\n }\n\n const source = new EventSource(sseUrl);\n eventSource = source;\n source.onopen = () => {\n sseConnected = true;\n schedulePoll();\n };\n source.onerror = () => {\n sseConnected = false;\n schedulePoll();\n };\n source.onmessage = (message) => {\n try {\n const payload = JSON.parse(message.data);\n const events = normalizeEventPayload(payload);\n const version =\n typeof payload?.version === \"number\" ? payload.version : undefined;\n applyEvents(events, version);\n } catch {\n // Ignore malformed SSE frames; polling is the safety net.\n }\n };\n }\n\n async function poll() {\n if (stopped || inFlight) return;\n inFlight = true;\n try {\n const data = await fetchPollJson<PollResponse>(\n pollUrl,\n versionRef,\n interval,\n );\n applyEvents(data.events ?? [], data.version);\n } catch {\n // Network error — will retry on next interval\n } finally {\n inFlight = false;\n schedulePoll();\n }\n }\n\n function pollNow() {\n if (pauseWhenHidden && isDocumentHidden()) {\n return;\n }\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n connectEvents();\n void poll();\n }\n\n function handleVisibilityChange() {\n if (document.visibilityState === \"visible\") {\n connectEvents();\n pollNow();\n } else if (pauseWhenHidden) {\n closeEvents();\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n }\n }\n\n // Initial poll immediately when visible. Hidden tabs catch up on focus.\n if (!pauseWhenHidden || !isDocumentHidden()) {\n connectEvents();\n void poll();\n }\n window.addEventListener(\"focus\", pollNow);\n document.addEventListener(\"visibilitychange\", handleVisibilityChange);\n\n return () => {\n stopped = true;\n closeEvents();\n if (timer) clearTimeout(timer);\n window.removeEventListener(\"focus\", pollNow);\n document.removeEventListener(\"visibilitychange\", handleVisibilityChange);\n };\n }, [\n pollUrl,\n sseUrl,\n queryClient,\n interval,\n fallbackInterval,\n pauseWhenHidden,\n ]);\n}\n\n/** @deprecated Use useDbSync instead */\nexport const useFileWatcher = useDbSync;\n\n/**\n * Subscribe to `refresh-screen` events from the agent. Returns an integer\n * that increments every time the agent invokes the framework's `refresh-screen`\n * tool. Apply it as a React `key` on the main content wrapper (the part\n * OUTSIDE the agent chat sidebar) so that region remounts and re-fetches its\n * data while the chat, sidebar, and any other persistent chrome keep their\n * in-flight state.\n *\n * Usage in a template's root:\n *\n * const screenKey = useScreenRefreshKey();\n * return (\n * <AppLayout>\n * <div key={screenKey}>\n * <Outlet />\n * </div>\n * </AppLayout>\n * );\n */\nexport function useScreenRefreshKey(\n options: {\n pollUrl?: string;\n sseUrl?: string | false;\n interval?: number;\n fallbackInterval?: number;\n pauseWhenHidden?: boolean;\n } = {},\n): number {\n const {\n pollUrl = agentNativePath(options.pollUrl ?? \"/_agent-native/poll\"),\n sseUrl = resolveSseUrl(options.sseUrl),\n interval = 2000,\n fallbackInterval = Math.max(\n options.fallbackInterval ?? SSE_FALLBACK_INTERVAL_MS,\n interval,\n ),\n pauseWhenHidden = true,\n } = options;\n const [key, setKey] = useState(0);\n\n useEffect(() => {\n let versionRef = 0;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let stopped = false;\n let inFlight = false;\n let eventSource: EventSource | null = null;\n let sseConnected = false;\n\n function schedulePoll() {\n if (stopped) return;\n if (pauseWhenHidden && isDocumentHidden()) return;\n if (timer) clearTimeout(timer);\n timer = setTimeout(\n () => {\n timer = null;\n void poll();\n },\n sseConnected ? fallbackInterval : interval,\n );\n }\n\n function applyEvents(events: SyncEvent[], version?: number) {\n const freshEvents = events.filter((event) => {\n const version = eventVersion(event);\n return version === 0 || version > versionRef;\n });\n if (freshEvents.some((e) => e.source === \"screen-refresh\")) {\n setKey((k) => k + 1);\n }\n const maxEventVersion = freshEvents.reduce(\n (max, event) => Math.max(max, eventVersion(event)),\n 0,\n );\n versionRef = Math.max(versionRef, version ?? 0, maxEventVersion);\n }\n\n function closeEvents() {\n if (!eventSource) return;\n eventSource.close();\n eventSource = null;\n sseConnected = false;\n }\n\n function connectEvents() {\n if (\n stopped ||\n !sseUrl ||\n eventSource ||\n typeof EventSource === \"undefined\" ||\n (pauseWhenHidden && isDocumentHidden())\n ) {\n return;\n }\n\n const source = new EventSource(sseUrl);\n eventSource = source;\n source.onopen = () => {\n sseConnected = true;\n schedulePoll();\n };\n source.onerror = () => {\n sseConnected = false;\n schedulePoll();\n };\n source.onmessage = (message) => {\n try {\n const payload = JSON.parse(message.data);\n const events = normalizeEventPayload(payload);\n const version =\n typeof payload?.version === \"number\" ? payload.version : undefined;\n applyEvents(events, version);\n } catch {\n // Polling will catch missed screen-refresh events.\n }\n };\n }\n\n async function poll() {\n if (stopped || inFlight) return;\n inFlight = true;\n try {\n const data = await fetchPollJson<PollResponse>(\n pollUrl,\n versionRef,\n interval,\n );\n applyEvents(data.events ?? [], data.version);\n } catch {\n // Network error — retry on next interval.\n } finally {\n inFlight = false;\n schedulePoll();\n }\n }\n\n function pollNow() {\n if (pauseWhenHidden && isDocumentHidden()) {\n return;\n }\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n connectEvents();\n void poll();\n }\n\n function handleVisibilityChange() {\n if (document.visibilityState === \"visible\") {\n connectEvents();\n pollNow();\n } else if (pauseWhenHidden) {\n closeEvents();\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n }\n }\n\n if (!pauseWhenHidden || !isDocumentHidden()) {\n connectEvents();\n void poll();\n }\n window.addEventListener(\"focus\", pollNow);\n document.addEventListener(\"visibilitychange\", handleVisibilityChange);\n\n return () => {\n stopped = true;\n closeEvents();\n if (timer) clearTimeout(timer);\n window.removeEventListener(\"focus\", pollNow);\n document.removeEventListener(\"visibilitychange\", handleVisibilityChange);\n };\n }, [pollUrl, sseUrl, interval, fallbackInterval, pauseWhenHidden]);\n\n return key;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"use-db-sync.js","sourceRoot":"","sources":["../../src/client/use-db-sync.ts"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport { agentNativePath } from \"./api-path.js\";\n\ninterface QueryClient {\n invalidateQueries(opts?: { queryKey?: string[] }): void;\n}\n\nconst POLL_ABORT_MIN_MS = 10_000;\nconst SSE_FALLBACK_INTERVAL_MS = 15_000;\n\ntype SyncEvent = {\n version?: number;\n source?: string;\n type?: string;\n key?: string;\n requestSource?: string;\n [k: string]: unknown;\n};\n\ntype PollResponse = {\n version: number;\n events: SyncEvent[];\n};\n\nfunction getPollAbortMs(interval: number): number {\n return Math.max(POLL_ABORT_MIN_MS, interval * 4);\n}\n\nfunction isDocumentHidden(): boolean {\n return (\n typeof document !== \"undefined\" && document.visibilityState === \"hidden\"\n );\n}\n\nfunction resolveSseUrl(sseUrl: string | false | undefined): string | false {\n if (sseUrl === false) return false;\n return agentNativePath(sseUrl ?? \"/_agent-native/events\");\n}\n\nfunction normalizeEventPayload(payload: unknown): SyncEvent[] {\n if (!payload || typeof payload !== \"object\") return [];\n const record = payload as { type?: unknown; events?: unknown };\n if (record.type === \"batch\" && Array.isArray(record.events)) {\n return record.events.filter(\n (event): event is SyncEvent => !!event && typeof event === \"object\",\n );\n }\n if (Array.isArray(record.events)) {\n return record.events.filter(\n (event): event is SyncEvent => !!event && typeof event === \"object\",\n );\n }\n return [payload as SyncEvent];\n}\n\nfunction eventVersion(event: SyncEvent): number {\n return typeof event.version === \"number\" ? event.version : 0;\n}\n\nasync function fetchPollJson<T>(\n pollUrl: string,\n since: number,\n interval: number,\n): Promise<T> {\n const controller =\n typeof AbortController === \"undefined\" ? null : new AbortController();\n const timeout = controller\n ? setTimeout(() => controller.abort(), getPollAbortMs(interval))\n : null;\n\n try {\n const res = await fetch(\n `${pollUrl}?since=${since}`,\n controller ? { signal: controller.signal } : undefined,\n );\n if (!res.ok) throw new Error(\"HTTP \" + res.status);\n // Await the json before the finally so a body-stream abort doesn't\n // produce a dangling promise that escapes as an unhandled rejection.\n return await res.json();\n } finally {\n if (timeout) clearTimeout(timeout);\n }\n}\n\n/**\n * Hook that listens to /_agent-native/events for DB change events and\n * invalidates react-query caches when changes are detected. Falls back to\n * /_agent-native/poll so cross-process/serverless writes still show up.\n *\n * Works in all deployment environments (serverless, edge, long-lived server).\n * SSE is the fast path; polling is the safety net.\n *\n * @param options.queryClient - The react-query QueryClient instance\n * @param options.queryKeys - Array of query key prefixes to invalidate on change.\n * Default: [\"data\"]\n * @param options.pollUrl - Poll endpoint URL. Default: \"/_agent-native/poll\"\n * @param options.sseUrl - SSE endpoint URL. Default: \"/_agent-native/events\".\n * Pass false to disable SSE and use polling only.\n * @param options.onEvent - Optional callback for each change event\n * @param options.interval - Poll interval in ms. Default: 2000\n * @param options.fallbackInterval - Poll interval while SSE is connected.\n * Default: 15000\n * @param options.pauseWhenHidden - Pause polling while the tab is hidden.\n * Default: true\n * @param options.ignoreSource - Skip events whose `requestSource` matches this\n * value. Use a per-tab ID so the UI ignores its own writes while still\n * picking up changes from other tabs, agents, and scripts.\n */\nexport function useDbSync(\n options: {\n queryClient?: QueryClient;\n queryKeys?: string[];\n pollUrl?: string;\n sseUrl?: string | false;\n /** @deprecated Use pollUrl instead */\n eventsUrl?: string;\n onEvent?: (data: any) => void;\n interval?: number;\n fallbackInterval?: number;\n pauseWhenHidden?: boolean;\n ignoreSource?: string;\n } = {},\n): void {\n const {\n queryClient,\n queryKeys = [\"data\"],\n pollUrl = agentNativePath(options.eventsUrl ?? \"/_agent-native/poll\"),\n sseUrl = resolveSseUrl(options.sseUrl),\n interval = 2000,\n fallbackInterval = Math.max(\n options.fallbackInterval ?? SSE_FALLBACK_INTERVAL_MS,\n interval,\n ),\n pauseWhenHidden = true,\n } = options;\n\n const onEventRef = useRef(options.onEvent);\n onEventRef.current = options.onEvent;\n\n const keysRef = useRef(queryKeys);\n keysRef.current = queryKeys;\n\n const ignoreSourceRef = useRef(options.ignoreSource);\n ignoreSourceRef.current = options.ignoreSource;\n\n useEffect(() => {\n let versionRef = 0;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let stopped = false;\n let inFlight = false;\n let eventSource: EventSource | null = null;\n let sseConnected = false;\n\n function schedulePoll() {\n if (stopped) return;\n if (pauseWhenHidden && isDocumentHidden()) return;\n if (timer) clearTimeout(timer);\n timer = setTimeout(\n () => {\n timer = null;\n void poll();\n },\n sseConnected ? fallbackInterval : interval,\n );\n }\n\n function invalidateForEvents(events: SyncEvent[]) {\n const ignore = ignoreSourceRef.current;\n const relevant = ignore\n ? events.filter((e) => e.requestSource !== ignore)\n : events;\n\n if (relevant.length > 0 && queryClient) {\n for (const key of keysRef.current) {\n queryClient.invalidateQueries({ queryKey: [key] });\n }\n\n // Framework-level invalidation: always invalidate framework query\n // keys on any non-own change event so that mutating actions\n // (agent or HTTP) auto-refresh the UI — regardless of how the\n // template configured queryKeys / onEvent.\n queryClient.invalidateQueries({ queryKey: [\"action\"] });\n queryClient.invalidateQueries({ queryKey: [\"extension\"] });\n queryClient.invalidateQueries({ queryKey: [\"extensions\"] });\n queryClient.invalidateQueries({ queryKey: [\"extension-slots\"] });\n queryClient.invalidateQueries({ queryKey: [\"slot-installs\"] });\n queryClient.invalidateQueries({ queryKey: [\"slot-available\"] });\n queryClient.invalidateQueries({ queryKey: [\"tool\"] });\n queryClient.invalidateQueries({ queryKey: [\"tools\"] });\n queryClient.invalidateQueries({ queryKey: [\"app-state\"] });\n queryClient.invalidateQueries({ queryKey: [\"navigate-command\"] });\n queryClient.invalidateQueries({ queryKey: [\"show-questions\"] });\n queryClient.invalidateQueries({ queryKey: [\"__set_url__\"] });\n }\n\n // Always forward all events to onEvent — templates can decide.\n for (const evt of events) {\n onEventRef.current?.(evt);\n }\n }\n\n function applyEvents(events: SyncEvent[], version?: number) {\n const freshEvents = events.filter((event) => {\n const version = eventVersion(event);\n return version === 0 || version > versionRef;\n });\n\n if (freshEvents.length > 0) {\n invalidateForEvents(freshEvents);\n }\n\n const maxEventVersion = freshEvents.reduce(\n (max, event) => Math.max(max, eventVersion(event)),\n 0,\n );\n versionRef = Math.max(versionRef, version ?? 0, maxEventVersion);\n }\n\n function closeEvents() {\n if (!eventSource) return;\n eventSource.close();\n eventSource = null;\n sseConnected = false;\n }\n\n function connectEvents() {\n if (\n stopped ||\n !sseUrl ||\n eventSource ||\n typeof EventSource === \"undefined\" ||\n (pauseWhenHidden && isDocumentHidden())\n ) {\n return;\n }\n\n const source = new EventSource(sseUrl);\n eventSource = source;\n source.onopen = () => {\n sseConnected = true;\n schedulePoll();\n };\n source.onerror = () => {\n sseConnected = false;\n schedulePoll();\n };\n source.onmessage = (message) => {\n try {\n const payload = JSON.parse(message.data);\n const events = normalizeEventPayload(payload);\n const version =\n typeof payload?.version === \"number\" ? payload.version : undefined;\n applyEvents(events, version);\n } catch {\n // Ignore malformed SSE frames; polling is the safety net.\n }\n };\n }\n\n async function poll() {\n if (stopped || inFlight) return;\n inFlight = true;\n try {\n const data = await fetchPollJson<PollResponse>(\n pollUrl,\n versionRef,\n interval,\n );\n applyEvents(data.events ?? [], data.version);\n } catch {\n // Network error — will retry on next interval\n } finally {\n inFlight = false;\n schedulePoll();\n }\n }\n\n function pollNow() {\n if (pauseWhenHidden && isDocumentHidden()) {\n return;\n }\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n connectEvents();\n void poll();\n }\n\n function handleVisibilityChange() {\n if (document.visibilityState === \"visible\") {\n connectEvents();\n pollNow();\n } else if (pauseWhenHidden) {\n closeEvents();\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n }\n }\n\n // Initial poll immediately when visible. Hidden tabs catch up on focus.\n if (!pauseWhenHidden || !isDocumentHidden()) {\n connectEvents();\n void poll();\n }\n window.addEventListener(\"focus\", pollNow);\n document.addEventListener(\"visibilitychange\", handleVisibilityChange);\n\n return () => {\n stopped = true;\n closeEvents();\n if (timer) clearTimeout(timer);\n window.removeEventListener(\"focus\", pollNow);\n document.removeEventListener(\"visibilitychange\", handleVisibilityChange);\n };\n }, [\n pollUrl,\n sseUrl,\n queryClient,\n interval,\n fallbackInterval,\n pauseWhenHidden,\n ]);\n}\n\n/** @deprecated Use useDbSync instead */\nexport const useFileWatcher = useDbSync;\n\n/**\n * Subscribe to `refresh-screen` events from the agent. Returns an integer\n * that increments every time the agent invokes the framework's `refresh-screen`\n * tool. Apply it as a React `key` on the main content wrapper (the part\n * OUTSIDE the agent chat sidebar) so that region remounts and re-fetches its\n * data while the chat, sidebar, and any other persistent chrome keep their\n * in-flight state.\n *\n * Usage in a template's root:\n *\n * const screenKey = useScreenRefreshKey();\n * return (\n * <AppLayout>\n * <div key={screenKey}>\n * <Outlet />\n * </div>\n * </AppLayout>\n * );\n */\nexport function useScreenRefreshKey(\n options: {\n pollUrl?: string;\n sseUrl?: string | false;\n interval?: number;\n fallbackInterval?: number;\n pauseWhenHidden?: boolean;\n } = {},\n): number {\n const {\n pollUrl = agentNativePath(options.pollUrl ?? \"/_agent-native/poll\"),\n sseUrl = resolveSseUrl(options.sseUrl),\n interval = 2000,\n fallbackInterval = Math.max(\n options.fallbackInterval ?? SSE_FALLBACK_INTERVAL_MS,\n interval,\n ),\n pauseWhenHidden = true,\n } = options;\n const [key, setKey] = useState(0);\n\n useEffect(() => {\n let versionRef = 0;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let stopped = false;\n let inFlight = false;\n let eventSource: EventSource | null = null;\n let sseConnected = false;\n\n function schedulePoll() {\n if (stopped) return;\n if (pauseWhenHidden && isDocumentHidden()) return;\n if (timer) clearTimeout(timer);\n timer = setTimeout(\n () => {\n timer = null;\n void poll();\n },\n sseConnected ? fallbackInterval : interval,\n );\n }\n\n function applyEvents(events: SyncEvent[], version?: number) {\n const freshEvents = events.filter((event) => {\n const version = eventVersion(event);\n return version === 0 || version > versionRef;\n });\n if (freshEvents.some((e) => e.source === \"screen-refresh\")) {\n setKey((k) => k + 1);\n }\n const maxEventVersion = freshEvents.reduce(\n (max, event) => Math.max(max, eventVersion(event)),\n 0,\n );\n versionRef = Math.max(versionRef, version ?? 0, maxEventVersion);\n }\n\n function closeEvents() {\n if (!eventSource) return;\n eventSource.close();\n eventSource = null;\n sseConnected = false;\n }\n\n function connectEvents() {\n if (\n stopped ||\n !sseUrl ||\n eventSource ||\n typeof EventSource === \"undefined\" ||\n (pauseWhenHidden && isDocumentHidden())\n ) {\n return;\n }\n\n const source = new EventSource(sseUrl);\n eventSource = source;\n source.onopen = () => {\n sseConnected = true;\n schedulePoll();\n };\n source.onerror = () => {\n sseConnected = false;\n schedulePoll();\n };\n source.onmessage = (message) => {\n try {\n const payload = JSON.parse(message.data);\n const events = normalizeEventPayload(payload);\n const version =\n typeof payload?.version === \"number\" ? payload.version : undefined;\n applyEvents(events, version);\n } catch {\n // Polling will catch missed screen-refresh events.\n }\n };\n }\n\n async function poll() {\n if (stopped || inFlight) return;\n inFlight = true;\n try {\n const data = await fetchPollJson<PollResponse>(\n pollUrl,\n versionRef,\n interval,\n );\n applyEvents(data.events ?? [], data.version);\n } catch {\n // Network error — retry on next interval.\n } finally {\n inFlight = false;\n schedulePoll();\n }\n }\n\n function pollNow() {\n if (pauseWhenHidden && isDocumentHidden()) {\n return;\n }\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n connectEvents();\n void poll();\n }\n\n function handleVisibilityChange() {\n if (document.visibilityState === \"visible\") {\n connectEvents();\n pollNow();\n } else if (pauseWhenHidden) {\n closeEvents();\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n }\n }\n\n if (!pauseWhenHidden || !isDocumentHidden()) {\n connectEvents();\n void poll();\n }\n window.addEventListener(\"focus\", pollNow);\n document.addEventListener(\"visibilitychange\", handleVisibilityChange);\n\n return () => {\n stopped = true;\n closeEvents();\n if (timer) clearTimeout(timer);\n window.removeEventListener(\"focus\", pollNow);\n document.removeEventListener(\"visibilitychange\", handleVisibilityChange);\n };\n }, [pollUrl, sseUrl, interval, fallbackInterval, pauseWhenHidden]);\n\n return key;\n}\n"]}
|
package/dist/db/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/db/client.ts"],"names":[],"mappings":"AAgBA,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,UAAU,GAAG,IAAI,CAAC;AAEnD,MAAM,WAAW,MAAM;IACrB,OAAO,CACL,GAAG,EAAE,MAAM,GAAG;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,GAAG,EAAE,CAAA;KAAE,GACzC,OAAO,CAAC;QAAE,IAAI,EAAE,GAAG,EAAE,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,GAAG,CAAC;CACjB;AAMD;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,QAAQ,SAAK,GAAG,MAAM,CAOpD;AAED,8EAA8E;AAC9E,wBAAgB,oBAAoB,IAAI,MAAM,GAAG,SAAS,CAOzD;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAErD;AAED,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAqBxE;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAQzD;AAMD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,CAO/D;AAMD;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,CAAC,EACrC,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,IAAI,GAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAC3E,OAAO,CAAC,CAAC,CAAC,CAkBZ;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,cAAc,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAOxE;AAiBD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,GAAG,GAAG,OAAO,CAejD;AAQD,wBAAgB,UAAU,IAAI,OAAO,CAyBpC;AAED,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAgBD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAIzC;AAED,iFAAiF;AACjF,wBAAgB,OAAO,IAAI,MAAM,CAEhC;AA0BD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAoBnD;AAED,wBAAsB,sBAAsB,CAAC,CAAC,EAC5C,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,WAAW,SAAI,GACd,OAAO,CAAC,CAAC,CAAC,CAYZ;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/db/client.ts"],"names":[],"mappings":"AAgBA,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,UAAU,GAAG,IAAI,CAAC;AAEnD,MAAM,WAAW,MAAM;IACrB,OAAO,CACL,GAAG,EAAE,MAAM,GAAG;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,GAAG,EAAE,CAAA;KAAE,GACzC,OAAO,CAAC;QAAE,IAAI,EAAE,GAAG,EAAE,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,GAAG,CAAC;CACjB;AAMD;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,QAAQ,SAAK,GAAG,MAAM,CAOpD;AAED,8EAA8E;AAC9E,wBAAgB,oBAAoB,IAAI,MAAM,GAAG,SAAS,CAOzD;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAErD;AAED,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAqBxE;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAQzD;AAMD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,CAO/D;AAMD;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,CAAC,EACrC,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,IAAI,GAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAC3E,OAAO,CAAC,CAAC,CAAC,CAkBZ;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,cAAc,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAOxE;AAiBD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,GAAG,GAAG,OAAO,CAejD;AAQD,wBAAgB,UAAU,IAAI,OAAO,CAyBpC;AAED,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAgBD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAIzC;AAED,iFAAiF;AACjF,wBAAgB,OAAO,IAAI,MAAM,CAEhC;AA0BD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAoBnD;AAED,wBAAsB,sBAAsB,CAAC,CAAC,EAC5C,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,WAAW,SAAI,GACd,OAAO,CAAC,CAAC,CAAC,CAYZ;AAgND,wBAAsB,YAAY,CAAC,MAAM,GAAE,YAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAE7E;AAiBD;;;GAGG;AACH,wBAAgB,SAAS,IAAI,MAAM,CA2BlC;AAED,qEAAqE;AACrE,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAejD"}
|
package/dist/db/client.js
CHANGED
|
@@ -341,6 +341,15 @@ async function createDbExecInternal(config = {}, trackSingletonResources = false
|
|
|
341
341
|
if (isNeonUrl(url)) {
|
|
342
342
|
const { Pool } = await import("@neondatabase/serverless");
|
|
343
343
|
const pool = new Pool({ connectionString: url });
|
|
344
|
+
// Neon's serverless Pool extends EventEmitter and emits 'error'
|
|
345
|
+
// when its WebSocket connection drops (idle timeout, Lambda
|
|
346
|
+
// suspend, network blip). Without a listener, Node 24 surfaces
|
|
347
|
+
// these as fatal `Unhandled error` / `Connection terminated
|
|
348
|
+
// unexpectedly` uncaught exceptions, even though the next query
|
|
349
|
+
// would have transparently re-connected. Log and swallow.
|
|
350
|
+
pool.on("error", (err) => {
|
|
351
|
+
console.warn("[db/neon] pool error (will reconnect on next query):", err instanceof Error ? err.message : err);
|
|
352
|
+
});
|
|
344
353
|
if (trackSingletonResources)
|
|
345
354
|
_neonPool = pool;
|
|
346
355
|
return {
|
package/dist/db/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/db/client.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Central database client abstraction.\n *\n * Detects the database backend from the environment (D1, Postgres, or SQLite/libsql)\n * and returns a unified `DbExec` interface that all core stores use.\n *\n * Imports for postgres, better-sqlite3, and @libsql/client/web are lazy\n * (dynamic import) so this module can be loaded in any runtime (Node.js,\n * Cloudflare Workers, edge) without failing on missing native deps.\n */\nimport path from \"path\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type Dialect = \"sqlite\" | \"postgres\" | \"d1\";\n\nexport interface DbExec {\n execute(\n sql: string | { sql: string; args: any[] },\n ): Promise<{ rows: any[]; rowsAffected: number }>;\n}\n\nexport interface DbExecConfig {\n url?: string;\n authToken?: string;\n d1Binding?: any;\n}\n\n// ---------------------------------------------------------------------------\n// Per-app DATABASE_URL resolution\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the database URL for the current app.\n *\n * Checks for `<APP_NAME>_DATABASE_URL` first (e.g. `MAIL_DATABASE_URL`),\n * then falls back to `DATABASE_URL`. This allows multiple apps to run in the\n * same process group (e.g. `dev:all` or builder.io) with separate databases.\n *\n * Set `APP_NAME=mail` in the child process env and\n * `MAIL_DATABASE_URL=postgres://...` in the shared env.\n */\nexport function getDatabaseUrl(fallback = \"\"): string {\n const appName = process.env.APP_NAME?.toUpperCase().replace(/-/g, \"_\");\n if (appName) {\n const prefixed = process.env[`${appName}_DATABASE_URL`];\n if (prefixed) return prefixed;\n }\n return process.env.DATABASE_URL || fallback;\n}\n\n/** Same per-app resolution for DATABASE_AUTH_TOKEN (used by Turso/libsql). */\nexport function getDatabaseAuthToken(): string | undefined {\n const appName = process.env.APP_NAME?.toUpperCase().replace(/-/g, \"_\");\n if (appName) {\n const prefixed = process.env[`${appName}_DATABASE_AUTH_TOKEN`];\n if (prefixed) return prefixed;\n }\n return process.env.DATABASE_AUTH_TOKEN;\n}\n\nexport function isLocalSqliteUrl(url: string): boolean {\n return url === \"\" || url.startsWith(\"file:\") || !url.includes(\"://\");\n}\n\nexport async function prepareLocalSqliteUrl(url: string): Promise<string> {\n if (!url.startsWith(\"file:\")) return url;\n\n // On serverless runtimes (Netlify, AWS Lambda) the working directory is\n // read-only. Detect this and redirect local SQLite to /tmp which IS writable\n // (ephemeral per invocation, but the server stays alive for the request).\n const isServerless =\n !!process.env.NETLIFY ||\n !!process.env.AWS_LAMBDA_FUNCTION_NAME ||\n !!process.env.LAMBDA_TASK_ROOT;\n try {\n const fs = await import(\"fs\");\n if (isServerless && url === \"file:./data/app.db\") {\n fs.mkdirSync(\"/tmp/data\", { recursive: true });\n return \"file:///tmp/data/app.db\";\n }\n fs.mkdirSync(path.join(process.cwd(), \"data\"), { recursive: true });\n } catch {\n // Edge runtime — no filesystem.\n }\n return url;\n}\n\nexport function sqliteFilenameFromUrl(url: string): string {\n if (url.startsWith(\"file://\")) {\n return decodeURIComponent(new URL(url).pathname);\n }\n if (url.startsWith(\"file:\")) {\n return url.slice(\"file:\".length) || \":memory:\";\n }\n return url || \"./data/app.db\";\n}\n\n// ---------------------------------------------------------------------------\n// Safe JSON column parsing\n// ---------------------------------------------------------------------------\n\n/**\n * Parse a JSON-serialized column value defensively. A malformed row — from a\n * hand-edit, dirty migration, or a misbehaving agent that wrote raw SQL —\n * must not break an entire list endpoint. Callers supply a fallback for the\n * malformed path; null/undefined values also fall back.\n */\nexport function safeJsonParse<T>(value: unknown, fallback: T): T {\n if (value == null) return fallback;\n try {\n return JSON.parse(String(value)) as T;\n } catch {\n return fallback;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SQLite retry helper\n// ---------------------------------------------------------------------------\n\n/**\n * Retry an async operation when it fails with SQLITE_BUSY.\n * Used during WAL initialization and migrations where a stale WAL from a\n * previous crash or HMR restart can briefly lock the database.\n */\nexport async function retrySqliteBusy<T>(\n fn: () => Promise<T>,\n opts: { maxAttempts?: number; baseDelayMs?: number; rethrow?: boolean } = {},\n): Promise<T> {\n const { maxAttempts = 5, baseDelayMs = 500, rethrow = false } = opts;\n let last: unknown;\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n try {\n return await fn();\n } catch (e: any) {\n last = e;\n const msg = String(e?.message || e);\n if (msg.includes(\"SQLITE_BUSY\") && attempt < maxAttempts - 1) {\n await new Promise((r) => setTimeout(r, baseDelayMs * (attempt + 1)));\n } else {\n break;\n }\n }\n }\n if (rethrow) throw last;\n return undefined as unknown as T; // caller handles undefined (e.g. PRAGMA setup)\n}\n\n/**\n * Retry a DDL statement (CREATE TABLE, CREATE INDEX) once when it fails due\n * to a Postgres pg_catalog race.\n *\n * Postgres's `IF NOT EXISTS` check is NOT atomic with the `pg_type` /\n * `pg_class` catalog insert. When multiple processes boot concurrently and\n * issue the same CREATE, both can pass the existence check and one fails\n * with code 23505 on `pg_type_typname_nsp_index` or similar. The table does\n * end up created by the winner, so rerunning the same `IF NOT EXISTS`\n * statement is a safe no-op.\n */\nexport async function retryOnDdlRace<T>(fn: () => Promise<T>): Promise<T> {\n try {\n return await fn();\n } catch (e: any) {\n if (!isPgCatalogRace(e)) throw e;\n return await fn();\n }\n}\n\nfunction isPgCatalogRace(e: any): boolean {\n if (e?.code === \"42P07\") return true;\n if (e?.code !== \"23505\") return false;\n const constraint = String(e?.constraint_name ?? e?.constraint ?? \"\");\n const detail = String(e?.detail ?? \"\");\n const msg = String(e?.message ?? \"\");\n return (\n constraint.startsWith(\"pg_type\") ||\n constraint.startsWith(\"pg_class\") ||\n detail.includes(\"pg_type\") ||\n detail.includes(\"pg_class\") ||\n /relation .* already exists/i.test(msg)\n );\n}\n\n/**\n * True when `e` is a UNIQUE / PRIMARY KEY constraint violation from any\n * supported driver (Postgres 23505, SQLite SQLITE_CONSTRAINT_PRIMARYKEY /\n * _UNIQUE, D1). Used by stores that accept caller-provided ids and want to\n * surface a clean \"already exists\" error instead of the raw SQL text.\n */\nexport function isUniqueViolation(e: any): boolean {\n if (e?.code === \"23505\") return true;\n const code = String(e?.code ?? \"\");\n if (\n code === \"SQLITE_CONSTRAINT_PRIMARYKEY\" ||\n code === \"SQLITE_CONSTRAINT_UNIQUE\"\n ) {\n return true;\n }\n const msg = String(e?.message ?? \"\").toLowerCase();\n return (\n msg.includes(\"unique constraint\") ||\n msg.includes(\"primary key constraint\") ||\n msg.includes(\"duplicate key\")\n );\n}\n\n// ---------------------------------------------------------------------------\n// Dialect detection\n// ---------------------------------------------------------------------------\n\nlet _dialect: Dialect | undefined;\n\nexport function getDialect(): Dialect {\n if (_dialect !== undefined) return _dialect;\n\n // DATABASE_URL takes priority over D1 when set.\n const url = getDatabaseUrl();\n if (url.startsWith(\"postgres://\") || url.startsWith(\"postgresql://\")) {\n _dialect = \"postgres\";\n return _dialect;\n }\n if (url && !url.startsWith(\"file:\")) {\n // Remote libsql (e.g. Turso)\n _dialect = \"sqlite\";\n return _dialect;\n }\n\n const d1 = globalThis.__cf_env?.DB;\n if (d1) {\n _dialect = \"d1\";\n return _dialect;\n }\n\n // Don't cache the fallthrough — on CF Workers, env bindings (__cf_env) aren't\n // available at import time. If we cache \"sqlite\" here, D1 will never be\n // detected once the bindings are set in the fetch handler.\n return \"sqlite\";\n}\n\nexport function isPostgres(): boolean {\n return getDialect() === \"postgres\";\n}\n\nfunction dialectForConfig(config: DbExecConfig): Dialect {\n const url = config.url ?? \"\";\n if (url.startsWith(\"postgres://\") || url.startsWith(\"postgresql://\")) {\n return \"postgres\";\n }\n if (url && !url.startsWith(\"file:\")) {\n return \"sqlite\";\n }\n if (config.d1Binding) {\n return \"d1\";\n }\n return \"sqlite\";\n}\n\n/**\n * Returns true when the database is a local-only SQLite file (or unset, which\n * defaults to a local SQLite file). Returns false for Postgres, remote libsql\n * (Turso), and D1 — any backend that could be shared across developers.\n *\n * Used to gate local@localhost mode: that mode uses a single shared virtual\n * user with no per-machine scoping, so on any shared database two developers\n * would read and write each other's settings, oauth tokens, and app state.\n */\nexport function isLocalDatabase(): boolean {\n if (getDialect() !== \"sqlite\") return false;\n const url = getDatabaseUrl();\n return url === \"\" || url.startsWith(\"file:\");\n}\n\n/** Returns BIGINT for Postgres (64-bit), INTEGER for SQLite (already 64-bit). */\nexport function intType(): string {\n return isPostgres() ? \"BIGINT\" : \"INTEGER\";\n}\n\n// ---------------------------------------------------------------------------\n// Parameter conversion: ? -> $1, $2, $3\n// ---------------------------------------------------------------------------\n\nfunction sqliteToPostgresParams(sql: string): string {\n let i = 0;\n return sql.replace(/\\?/g, () => `$${++i}`);\n}\n\n// ---------------------------------------------------------------------------\n// Connection error retry (ECONNRESET, etc.)\n// ---------------------------------------------------------------------------\n\n/** Error codes that indicate a dead/stale connection we can safely retry. */\nconst CONNECTION_ERROR_CODES = new Set([\n \"ECONNRESET\",\n \"ETIMEDOUT\",\n \"EPIPE\",\n \"ENOTFOUND\",\n \"CONNECTION_ENDED\",\n \"CONNECTION_DESTROYED\",\n \"CONNECTION_CLOSED\",\n]);\n\nexport function isConnectionError(err: any): boolean {\n if (!err) return false;\n const code = err.code || err.cause?.code;\n if (code && CONNECTION_ERROR_CODES.has(code)) return true;\n // Neon serverless WS driver: errors from the underlying undici WebSocket\n // closing mid-query come through as TypeError or ErrorEvent without a code.\n const name = err.name || err.cause?.name || \"\";\n if (name === \"ErrorEvent\") return true;\n const stack = String(err.stack || err.cause?.stack || \"\");\n if (\n /WebSocket\\.#onSocketClose|failWebsocketConnection|onSocketClose/.test(\n stack,\n )\n ) {\n return true;\n }\n const msg = String(err.message || err.cause?.message || \"\");\n return /ECONNRESET|ETIMEDOUT|EPIPE|connection.*(closed|ended|terminated)|socket hang up|websocket/i.test(\n msg,\n );\n}\n\nexport async function retryOnConnectionError<T>(\n fn: () => Promise<T>,\n maxAttempts = 3,\n): Promise<T> {\n let last: unknown;\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n try {\n return await fn();\n } catch (e) {\n last = e;\n if (!isConnectionError(e) || attempt === maxAttempts - 1) throw e;\n await new Promise((r) => setTimeout(r, 100 * (attempt + 1)));\n }\n }\n throw last;\n}\n\n// ---------------------------------------------------------------------------\n// Singleton client — lazy-initialized on first execute() call\n// ---------------------------------------------------------------------------\n\nlet _exec: DbExec | undefined;\nlet _pgPool: any;\nlet _neonPool: any;\nlet _sqlite: any;\nlet _initPromise: Promise<void> | undefined;\n\nasync function createDbExecInternal(\n config: DbExecConfig = {},\n trackSingletonResources = false,\n): Promise<DbExec> {\n const dialect = dialectForConfig(config);\n\n // Cloudflare D1\n if (dialect === \"d1\") {\n const d1 = config.d1Binding;\n return {\n async execute(sql) {\n if (typeof sql === \"string\") {\n const r = await d1.prepare(sql).all();\n return {\n rows: r.results || [],\n rowsAffected: r.meta?.changes ?? 0,\n };\n }\n const r = await d1\n .prepare(sql.sql)\n .bind(...sql.args)\n .all();\n return { rows: r.results || [], rowsAffected: r.meta?.changes ?? 0 };\n },\n };\n }\n\n let url = config.url || \"file:./data/app.db\";\n\n // Postgres — uses postgres.js. Works on Node.js natively and on Cloudflare\n // Workers with the nodejs_compat compatibility flag (provides net/tls polyfills).\n // On Workers, connections can't be shared across requests, so we create a\n // fresh connection per query (max:1) to avoid the \"I/O on behalf of a\n // different request\" error.\n if (dialect === \"postgres\") {\n const { isNeonUrl } = await import(\"./create-get-db.js\");\n\n // Neon over @neondatabase/serverless (WebSocket upgrade on port 443).\n // postgres-js uses a raw TCP socket on 5432 that frequently fails on\n // serverless runtimes (Netlify Functions, Vercel, CF Workers) when\n // Neon's pooler is cold — every request after an idle period times out\n // with CONNECT_TIMEOUT. The serverless Pool handles wake-up transparently\n // and keeps the same `pg`-compatible query(...) interface we need here.\n if (isNeonUrl(url)) {\n const { Pool } = await import(\"@neondatabase/serverless\");\n const pool = new Pool({ connectionString: url });\n if (trackSingletonResources) _neonPool = pool;\n return {\n async execute(sql) {\n const rawSql = typeof sql === \"string\" ? sql : sql.sql;\n const args = typeof sql === \"string\" ? [] : sql.args || [];\n const pgSql = sqliteToPostgresParams(rawSql);\n const result = await retryOnConnectionError<{\n rows: unknown[];\n rowCount?: number;\n }>(() => pool.query(pgSql, args as any[]));\n return {\n rows: result.rows,\n rowsAffected: result.rowCount ?? 0,\n };\n },\n };\n }\n\n const { default: postgres } = await import(\"postgres\");\n const isWorkers =\n \"__cf_env\" in globalThis ||\n (typeof navigator !== \"undefined\" &&\n navigator.userAgent === \"Cloudflare-Workers\");\n\n if (isWorkers) {\n // Workers: fresh connection per query — I/O can't be shared across requests\n return {\n async execute(sql) {\n const conn = postgres(url, {\n max: 1,\n idle_timeout: 0,\n onnotice: () => {},\n });\n try {\n const rawSql = typeof sql === \"string\" ? sql : sql.sql;\n const args = typeof sql === \"string\" ? [] : sql.args || [];\n const pgSql = sqliteToPostgresParams(rawSql);\n const result = await conn.unsafe(pgSql, args as any[]);\n return {\n rows: Array.from(result),\n rowsAffected: result.count ?? 0,\n };\n } finally {\n await conn.end();\n }\n },\n };\n } else {\n // Node.js: reuse connection pool.\n // idle_timeout:240 closes idle connections before Neon's ~5min server-side\n // timeout, avoiding ECONNRESET when the server hangs up on us.\n const pool = postgres(url, {\n onnotice: () => {},\n idle_timeout: 240,\n max_lifetime: 60 * 30,\n connect_timeout: 10,\n // Supabase's connection pooler (Transaction mode) requires prepare: false.\n // Only disable for Supabase URLs to avoid degrading other Postgres deployments.\n ...(url.includes(\"supabase\") ? { prepare: false } : {}),\n });\n if (trackSingletonResources) _pgPool = pool;\n\n return {\n async execute(sql) {\n const rawSql = typeof sql === \"string\" ? sql : sql.sql;\n const args = typeof sql === \"string\" ? [] : sql.args || [];\n const pgSql = sqliteToPostgresParams(rawSql);\n const result = await retryOnConnectionError<\n ArrayLike<unknown> & { count?: number }\n >(() => pool.unsafe(pgSql, args as any[]));\n return {\n rows: Array.from(result),\n rowsAffected: result.count ?? 0,\n };\n },\n };\n }\n }\n\n // SQLite / libsql (default). Local file databases use better-sqlite3 so\n // serverless bundles do not need libsql's platform-specific native package.\n if (isLocalSqliteUrl(url)) {\n url = await prepareLocalSqliteUrl(\n url.startsWith(\"file:\") ? url : `file:${url}`,\n );\n const { default: Database } = await import(\"better-sqlite3\");\n const sqlite = new Database(sqliteFilenameFromUrl(url));\n sqlite.pragma(\"busy_timeout = 10000\");\n sqlite.pragma(\"journal_mode = WAL\");\n if (trackSingletonResources) _sqlite = sqlite;\n\n return {\n async execute(sql) {\n const rawSql = typeof sql === \"string\" ? sql : sql.sql;\n const args = typeof sql === \"string\" ? [] : sql.args || [];\n const stmt = sqlite.prepare(rawSql);\n if (stmt.reader) {\n return {\n rows: stmt.all(...args),\n rowsAffected: 0,\n };\n }\n const result = stmt.run(...args);\n return {\n rows: [],\n rowsAffected: result.changes ?? 0,\n };\n },\n };\n }\n\n const { createClient } = await import(\"@libsql/client/web\");\n const client = createClient({\n url,\n authToken: config.authToken,\n });\n\n return {\n async execute(sql) {\n if (typeof sql === \"string\") {\n const r = await client.execute(sql);\n return {\n rows: r.rows as any[],\n rowsAffected: r.rowsAffected,\n };\n }\n const r = await client.execute({\n sql: sql.sql,\n args: sql.args as any[],\n });\n return {\n rows: r.rows as any[],\n rowsAffected: r.rowsAffected,\n };\n },\n };\n}\n\nexport async function createDbExec(config: DbExecConfig = {}): Promise<DbExec> {\n return createDbExecInternal(config, false);\n}\n\nasync function initClient(): Promise<void> {\n if (_exec) return;\n\n const dialect = getDialect();\n const url = getDatabaseUrl(\"file:./data/app.db\");\n _exec = await createDbExecInternal(\n {\n url,\n authToken: getDatabaseAuthToken(),\n d1Binding: dialect === \"d1\" ? globalThis.__cf_env?.DB : undefined,\n },\n true,\n );\n}\n\n/**\n * Get the singleton database client. Returns a `DbExec` whose first\n * `execute()` call lazily initializes the underlying driver.\n */\nexport function getDbExec(): DbExec {\n if (_exec) return _exec;\n\n // Sanitize args: replace undefined with null (libsql rejects undefined)\n function sanitize(\n sql: string | { sql: string; args: any[] },\n ): string | { sql: string; args: any[] } {\n if (typeof sql === \"object\" && sql.args) {\n return { ...sql, args: sql.args.map((a: any) => a ?? null) };\n }\n return sql;\n }\n\n // Return a proxy that lazy-inits on first call\n const proxy: DbExec = {\n async execute(sql) {\n if (!_initPromise) _initPromise = initClient();\n await _initPromise;\n // After init, swap to a sanitizing wrapper around the real client\n const wrapper: DbExec = {\n execute: (s) => _exec!.execute(sanitize(s)),\n };\n Object.assign(proxy, wrapper);\n return _exec!.execute(sanitize(sql));\n },\n };\n return proxy;\n}\n\n/** Close the database connection (for scripts that need cleanup). */\nexport async function closeDbExec(): Promise<void> {\n if (_pgPool) {\n await _pgPool.end();\n _pgPool = undefined;\n }\n if (_neonPool) {\n await _neonPool.end();\n _neonPool = undefined;\n }\n if (_sqlite) {\n _sqlite.close();\n _sqlite = undefined;\n }\n _exec = undefined;\n _initPromise = undefined;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/db/client.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Central database client abstraction.\n *\n * Detects the database backend from the environment (D1, Postgres, or SQLite/libsql)\n * and returns a unified `DbExec` interface that all core stores use.\n *\n * Imports for postgres, better-sqlite3, and @libsql/client/web are lazy\n * (dynamic import) so this module can be loaded in any runtime (Node.js,\n * Cloudflare Workers, edge) without failing on missing native deps.\n */\nimport path from \"path\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type Dialect = \"sqlite\" | \"postgres\" | \"d1\";\n\nexport interface DbExec {\n execute(\n sql: string | { sql: string; args: any[] },\n ): Promise<{ rows: any[]; rowsAffected: number }>;\n}\n\nexport interface DbExecConfig {\n url?: string;\n authToken?: string;\n d1Binding?: any;\n}\n\n// ---------------------------------------------------------------------------\n// Per-app DATABASE_URL resolution\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the database URL for the current app.\n *\n * Checks for `<APP_NAME>_DATABASE_URL` first (e.g. `MAIL_DATABASE_URL`),\n * then falls back to `DATABASE_URL`. This allows multiple apps to run in the\n * same process group (e.g. `dev:all` or builder.io) with separate databases.\n *\n * Set `APP_NAME=mail` in the child process env and\n * `MAIL_DATABASE_URL=postgres://...` in the shared env.\n */\nexport function getDatabaseUrl(fallback = \"\"): string {\n const appName = process.env.APP_NAME?.toUpperCase().replace(/-/g, \"_\");\n if (appName) {\n const prefixed = process.env[`${appName}_DATABASE_URL`];\n if (prefixed) return prefixed;\n }\n return process.env.DATABASE_URL || fallback;\n}\n\n/** Same per-app resolution for DATABASE_AUTH_TOKEN (used by Turso/libsql). */\nexport function getDatabaseAuthToken(): string | undefined {\n const appName = process.env.APP_NAME?.toUpperCase().replace(/-/g, \"_\");\n if (appName) {\n const prefixed = process.env[`${appName}_DATABASE_AUTH_TOKEN`];\n if (prefixed) return prefixed;\n }\n return process.env.DATABASE_AUTH_TOKEN;\n}\n\nexport function isLocalSqliteUrl(url: string): boolean {\n return url === \"\" || url.startsWith(\"file:\") || !url.includes(\"://\");\n}\n\nexport async function prepareLocalSqliteUrl(url: string): Promise<string> {\n if (!url.startsWith(\"file:\")) return url;\n\n // On serverless runtimes (Netlify, AWS Lambda) the working directory is\n // read-only. Detect this and redirect local SQLite to /tmp which IS writable\n // (ephemeral per invocation, but the server stays alive for the request).\n const isServerless =\n !!process.env.NETLIFY ||\n !!process.env.AWS_LAMBDA_FUNCTION_NAME ||\n !!process.env.LAMBDA_TASK_ROOT;\n try {\n const fs = await import(\"fs\");\n if (isServerless && url === \"file:./data/app.db\") {\n fs.mkdirSync(\"/tmp/data\", { recursive: true });\n return \"file:///tmp/data/app.db\";\n }\n fs.mkdirSync(path.join(process.cwd(), \"data\"), { recursive: true });\n } catch {\n // Edge runtime — no filesystem.\n }\n return url;\n}\n\nexport function sqliteFilenameFromUrl(url: string): string {\n if (url.startsWith(\"file://\")) {\n return decodeURIComponent(new URL(url).pathname);\n }\n if (url.startsWith(\"file:\")) {\n return url.slice(\"file:\".length) || \":memory:\";\n }\n return url || \"./data/app.db\";\n}\n\n// ---------------------------------------------------------------------------\n// Safe JSON column parsing\n// ---------------------------------------------------------------------------\n\n/**\n * Parse a JSON-serialized column value defensively. A malformed row — from a\n * hand-edit, dirty migration, or a misbehaving agent that wrote raw SQL —\n * must not break an entire list endpoint. Callers supply a fallback for the\n * malformed path; null/undefined values also fall back.\n */\nexport function safeJsonParse<T>(value: unknown, fallback: T): T {\n if (value == null) return fallback;\n try {\n return JSON.parse(String(value)) as T;\n } catch {\n return fallback;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SQLite retry helper\n// ---------------------------------------------------------------------------\n\n/**\n * Retry an async operation when it fails with SQLITE_BUSY.\n * Used during WAL initialization and migrations where a stale WAL from a\n * previous crash or HMR restart can briefly lock the database.\n */\nexport async function retrySqliteBusy<T>(\n fn: () => Promise<T>,\n opts: { maxAttempts?: number; baseDelayMs?: number; rethrow?: boolean } = {},\n): Promise<T> {\n const { maxAttempts = 5, baseDelayMs = 500, rethrow = false } = opts;\n let last: unknown;\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n try {\n return await fn();\n } catch (e: any) {\n last = e;\n const msg = String(e?.message || e);\n if (msg.includes(\"SQLITE_BUSY\") && attempt < maxAttempts - 1) {\n await new Promise((r) => setTimeout(r, baseDelayMs * (attempt + 1)));\n } else {\n break;\n }\n }\n }\n if (rethrow) throw last;\n return undefined as unknown as T; // caller handles undefined (e.g. PRAGMA setup)\n}\n\n/**\n * Retry a DDL statement (CREATE TABLE, CREATE INDEX) once when it fails due\n * to a Postgres pg_catalog race.\n *\n * Postgres's `IF NOT EXISTS` check is NOT atomic with the `pg_type` /\n * `pg_class` catalog insert. When multiple processes boot concurrently and\n * issue the same CREATE, both can pass the existence check and one fails\n * with code 23505 on `pg_type_typname_nsp_index` or similar. The table does\n * end up created by the winner, so rerunning the same `IF NOT EXISTS`\n * statement is a safe no-op.\n */\nexport async function retryOnDdlRace<T>(fn: () => Promise<T>): Promise<T> {\n try {\n return await fn();\n } catch (e: any) {\n if (!isPgCatalogRace(e)) throw e;\n return await fn();\n }\n}\n\nfunction isPgCatalogRace(e: any): boolean {\n if (e?.code === \"42P07\") return true;\n if (e?.code !== \"23505\") return false;\n const constraint = String(e?.constraint_name ?? e?.constraint ?? \"\");\n const detail = String(e?.detail ?? \"\");\n const msg = String(e?.message ?? \"\");\n return (\n constraint.startsWith(\"pg_type\") ||\n constraint.startsWith(\"pg_class\") ||\n detail.includes(\"pg_type\") ||\n detail.includes(\"pg_class\") ||\n /relation .* already exists/i.test(msg)\n );\n}\n\n/**\n * True when `e` is a UNIQUE / PRIMARY KEY constraint violation from any\n * supported driver (Postgres 23505, SQLite SQLITE_CONSTRAINT_PRIMARYKEY /\n * _UNIQUE, D1). Used by stores that accept caller-provided ids and want to\n * surface a clean \"already exists\" error instead of the raw SQL text.\n */\nexport function isUniqueViolation(e: any): boolean {\n if (e?.code === \"23505\") return true;\n const code = String(e?.code ?? \"\");\n if (\n code === \"SQLITE_CONSTRAINT_PRIMARYKEY\" ||\n code === \"SQLITE_CONSTRAINT_UNIQUE\"\n ) {\n return true;\n }\n const msg = String(e?.message ?? \"\").toLowerCase();\n return (\n msg.includes(\"unique constraint\") ||\n msg.includes(\"primary key constraint\") ||\n msg.includes(\"duplicate key\")\n );\n}\n\n// ---------------------------------------------------------------------------\n// Dialect detection\n// ---------------------------------------------------------------------------\n\nlet _dialect: Dialect | undefined;\n\nexport function getDialect(): Dialect {\n if (_dialect !== undefined) return _dialect;\n\n // DATABASE_URL takes priority over D1 when set.\n const url = getDatabaseUrl();\n if (url.startsWith(\"postgres://\") || url.startsWith(\"postgresql://\")) {\n _dialect = \"postgres\";\n return _dialect;\n }\n if (url && !url.startsWith(\"file:\")) {\n // Remote libsql (e.g. Turso)\n _dialect = \"sqlite\";\n return _dialect;\n }\n\n const d1 = globalThis.__cf_env?.DB;\n if (d1) {\n _dialect = \"d1\";\n return _dialect;\n }\n\n // Don't cache the fallthrough — on CF Workers, env bindings (__cf_env) aren't\n // available at import time. If we cache \"sqlite\" here, D1 will never be\n // detected once the bindings are set in the fetch handler.\n return \"sqlite\";\n}\n\nexport function isPostgres(): boolean {\n return getDialect() === \"postgres\";\n}\n\nfunction dialectForConfig(config: DbExecConfig): Dialect {\n const url = config.url ?? \"\";\n if (url.startsWith(\"postgres://\") || url.startsWith(\"postgresql://\")) {\n return \"postgres\";\n }\n if (url && !url.startsWith(\"file:\")) {\n return \"sqlite\";\n }\n if (config.d1Binding) {\n return \"d1\";\n }\n return \"sqlite\";\n}\n\n/**\n * Returns true when the database is a local-only SQLite file (or unset, which\n * defaults to a local SQLite file). Returns false for Postgres, remote libsql\n * (Turso), and D1 — any backend that could be shared across developers.\n *\n * Used to gate local@localhost mode: that mode uses a single shared virtual\n * user with no per-machine scoping, so on any shared database two developers\n * would read and write each other's settings, oauth tokens, and app state.\n */\nexport function isLocalDatabase(): boolean {\n if (getDialect() !== \"sqlite\") return false;\n const url = getDatabaseUrl();\n return url === \"\" || url.startsWith(\"file:\");\n}\n\n/** Returns BIGINT for Postgres (64-bit), INTEGER for SQLite (already 64-bit). */\nexport function intType(): string {\n return isPostgres() ? \"BIGINT\" : \"INTEGER\";\n}\n\n// ---------------------------------------------------------------------------\n// Parameter conversion: ? -> $1, $2, $3\n// ---------------------------------------------------------------------------\n\nfunction sqliteToPostgresParams(sql: string): string {\n let i = 0;\n return sql.replace(/\\?/g, () => `$${++i}`);\n}\n\n// ---------------------------------------------------------------------------\n// Connection error retry (ECONNRESET, etc.)\n// ---------------------------------------------------------------------------\n\n/** Error codes that indicate a dead/stale connection we can safely retry. */\nconst CONNECTION_ERROR_CODES = new Set([\n \"ECONNRESET\",\n \"ETIMEDOUT\",\n \"EPIPE\",\n \"ENOTFOUND\",\n \"CONNECTION_ENDED\",\n \"CONNECTION_DESTROYED\",\n \"CONNECTION_CLOSED\",\n]);\n\nexport function isConnectionError(err: any): boolean {\n if (!err) return false;\n const code = err.code || err.cause?.code;\n if (code && CONNECTION_ERROR_CODES.has(code)) return true;\n // Neon serverless WS driver: errors from the underlying undici WebSocket\n // closing mid-query come through as TypeError or ErrorEvent without a code.\n const name = err.name || err.cause?.name || \"\";\n if (name === \"ErrorEvent\") return true;\n const stack = String(err.stack || err.cause?.stack || \"\");\n if (\n /WebSocket\\.#onSocketClose|failWebsocketConnection|onSocketClose/.test(\n stack,\n )\n ) {\n return true;\n }\n const msg = String(err.message || err.cause?.message || \"\");\n return /ECONNRESET|ETIMEDOUT|EPIPE|connection.*(closed|ended|terminated)|socket hang up|websocket/i.test(\n msg,\n );\n}\n\nexport async function retryOnConnectionError<T>(\n fn: () => Promise<T>,\n maxAttempts = 3,\n): Promise<T> {\n let last: unknown;\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n try {\n return await fn();\n } catch (e) {\n last = e;\n if (!isConnectionError(e) || attempt === maxAttempts - 1) throw e;\n await new Promise((r) => setTimeout(r, 100 * (attempt + 1)));\n }\n }\n throw last;\n}\n\n// ---------------------------------------------------------------------------\n// Singleton client — lazy-initialized on first execute() call\n// ---------------------------------------------------------------------------\n\nlet _exec: DbExec | undefined;\nlet _pgPool: any;\nlet _neonPool: any;\nlet _sqlite: any;\nlet _initPromise: Promise<void> | undefined;\n\nasync function createDbExecInternal(\n config: DbExecConfig = {},\n trackSingletonResources = false,\n): Promise<DbExec> {\n const dialect = dialectForConfig(config);\n\n // Cloudflare D1\n if (dialect === \"d1\") {\n const d1 = config.d1Binding;\n return {\n async execute(sql) {\n if (typeof sql === \"string\") {\n const r = await d1.prepare(sql).all();\n return {\n rows: r.results || [],\n rowsAffected: r.meta?.changes ?? 0,\n };\n }\n const r = await d1\n .prepare(sql.sql)\n .bind(...sql.args)\n .all();\n return { rows: r.results || [], rowsAffected: r.meta?.changes ?? 0 };\n },\n };\n }\n\n let url = config.url || \"file:./data/app.db\";\n\n // Postgres — uses postgres.js. Works on Node.js natively and on Cloudflare\n // Workers with the nodejs_compat compatibility flag (provides net/tls polyfills).\n // On Workers, connections can't be shared across requests, so we create a\n // fresh connection per query (max:1) to avoid the \"I/O on behalf of a\n // different request\" error.\n if (dialect === \"postgres\") {\n const { isNeonUrl } = await import(\"./create-get-db.js\");\n\n // Neon over @neondatabase/serverless (WebSocket upgrade on port 443).\n // postgres-js uses a raw TCP socket on 5432 that frequently fails on\n // serverless runtimes (Netlify Functions, Vercel, CF Workers) when\n // Neon's pooler is cold — every request after an idle period times out\n // with CONNECT_TIMEOUT. The serverless Pool handles wake-up transparently\n // and keeps the same `pg`-compatible query(...) interface we need here.\n if (isNeonUrl(url)) {\n const { Pool } = await import(\"@neondatabase/serverless\");\n const pool = new Pool({ connectionString: url });\n // Neon's serverless Pool extends EventEmitter and emits 'error'\n // when its WebSocket connection drops (idle timeout, Lambda\n // suspend, network blip). Without a listener, Node 24 surfaces\n // these as fatal `Unhandled error` / `Connection terminated\n // unexpectedly` uncaught exceptions, even though the next query\n // would have transparently re-connected. Log and swallow.\n pool.on(\"error\", (err: unknown) => {\n console.warn(\n \"[db/neon] pool error (will reconnect on next query):\",\n err instanceof Error ? err.message : err,\n );\n });\n if (trackSingletonResources) _neonPool = pool;\n return {\n async execute(sql) {\n const rawSql = typeof sql === \"string\" ? sql : sql.sql;\n const args = typeof sql === \"string\" ? [] : sql.args || [];\n const pgSql = sqliteToPostgresParams(rawSql);\n const result = await retryOnConnectionError<{\n rows: unknown[];\n rowCount?: number;\n }>(() => pool.query(pgSql, args as any[]));\n return {\n rows: result.rows,\n rowsAffected: result.rowCount ?? 0,\n };\n },\n };\n }\n\n const { default: postgres } = await import(\"postgres\");\n const isWorkers =\n \"__cf_env\" in globalThis ||\n (typeof navigator !== \"undefined\" &&\n navigator.userAgent === \"Cloudflare-Workers\");\n\n if (isWorkers) {\n // Workers: fresh connection per query — I/O can't be shared across requests\n return {\n async execute(sql) {\n const conn = postgres(url, {\n max: 1,\n idle_timeout: 0,\n onnotice: () => {},\n });\n try {\n const rawSql = typeof sql === \"string\" ? sql : sql.sql;\n const args = typeof sql === \"string\" ? [] : sql.args || [];\n const pgSql = sqliteToPostgresParams(rawSql);\n const result = await conn.unsafe(pgSql, args as any[]);\n return {\n rows: Array.from(result),\n rowsAffected: result.count ?? 0,\n };\n } finally {\n await conn.end();\n }\n },\n };\n } else {\n // Node.js: reuse connection pool.\n // idle_timeout:240 closes idle connections before Neon's ~5min server-side\n // timeout, avoiding ECONNRESET when the server hangs up on us.\n const pool = postgres(url, {\n onnotice: () => {},\n idle_timeout: 240,\n max_lifetime: 60 * 30,\n connect_timeout: 10,\n // Supabase's connection pooler (Transaction mode) requires prepare: false.\n // Only disable for Supabase URLs to avoid degrading other Postgres deployments.\n ...(url.includes(\"supabase\") ? { prepare: false } : {}),\n });\n if (trackSingletonResources) _pgPool = pool;\n\n return {\n async execute(sql) {\n const rawSql = typeof sql === \"string\" ? sql : sql.sql;\n const args = typeof sql === \"string\" ? [] : sql.args || [];\n const pgSql = sqliteToPostgresParams(rawSql);\n const result = await retryOnConnectionError<\n ArrayLike<unknown> & { count?: number }\n >(() => pool.unsafe(pgSql, args as any[]));\n return {\n rows: Array.from(result),\n rowsAffected: result.count ?? 0,\n };\n },\n };\n }\n }\n\n // SQLite / libsql (default). Local file databases use better-sqlite3 so\n // serverless bundles do not need libsql's platform-specific native package.\n if (isLocalSqliteUrl(url)) {\n url = await prepareLocalSqliteUrl(\n url.startsWith(\"file:\") ? url : `file:${url}`,\n );\n const { default: Database } = await import(\"better-sqlite3\");\n const sqlite = new Database(sqliteFilenameFromUrl(url));\n sqlite.pragma(\"busy_timeout = 10000\");\n sqlite.pragma(\"journal_mode = WAL\");\n if (trackSingletonResources) _sqlite = sqlite;\n\n return {\n async execute(sql) {\n const rawSql = typeof sql === \"string\" ? sql : sql.sql;\n const args = typeof sql === \"string\" ? [] : sql.args || [];\n const stmt = sqlite.prepare(rawSql);\n if (stmt.reader) {\n return {\n rows: stmt.all(...args),\n rowsAffected: 0,\n };\n }\n const result = stmt.run(...args);\n return {\n rows: [],\n rowsAffected: result.changes ?? 0,\n };\n },\n };\n }\n\n const { createClient } = await import(\"@libsql/client/web\");\n const client = createClient({\n url,\n authToken: config.authToken,\n });\n\n return {\n async execute(sql) {\n if (typeof sql === \"string\") {\n const r = await client.execute(sql);\n return {\n rows: r.rows as any[],\n rowsAffected: r.rowsAffected,\n };\n }\n const r = await client.execute({\n sql: sql.sql,\n args: sql.args as any[],\n });\n return {\n rows: r.rows as any[],\n rowsAffected: r.rowsAffected,\n };\n },\n };\n}\n\nexport async function createDbExec(config: DbExecConfig = {}): Promise<DbExec> {\n return createDbExecInternal(config, false);\n}\n\nasync function initClient(): Promise<void> {\n if (_exec) return;\n\n const dialect = getDialect();\n const url = getDatabaseUrl(\"file:./data/app.db\");\n _exec = await createDbExecInternal(\n {\n url,\n authToken: getDatabaseAuthToken(),\n d1Binding: dialect === \"d1\" ? globalThis.__cf_env?.DB : undefined,\n },\n true,\n );\n}\n\n/**\n * Get the singleton database client. Returns a `DbExec` whose first\n * `execute()` call lazily initializes the underlying driver.\n */\nexport function getDbExec(): DbExec {\n if (_exec) return _exec;\n\n // Sanitize args: replace undefined with null (libsql rejects undefined)\n function sanitize(\n sql: string | { sql: string; args: any[] },\n ): string | { sql: string; args: any[] } {\n if (typeof sql === \"object\" && sql.args) {\n return { ...sql, args: sql.args.map((a: any) => a ?? null) };\n }\n return sql;\n }\n\n // Return a proxy that lazy-inits on first call\n const proxy: DbExec = {\n async execute(sql) {\n if (!_initPromise) _initPromise = initClient();\n await _initPromise;\n // After init, swap to a sanitizing wrapper around the real client\n const wrapper: DbExec = {\n execute: (s) => _exec!.execute(sanitize(s)),\n };\n Object.assign(proxy, wrapper);\n return _exec!.execute(sanitize(sql));\n },\n };\n return proxy;\n}\n\n/** Close the database connection (for scripts that need cleanup). */\nexport async function closeDbExec(): Promise<void> {\n if (_pgPool) {\n await _pgPool.end();\n _pgPool = undefined;\n }\n if (_neonPool) {\n await _neonPool.end();\n _neonPool = undefined;\n }\n if (_sqlite) {\n _sqlite.close();\n _sqlite = undefined;\n }\n _exec = undefined;\n _initPromise = undefined;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-get-db.d.ts","sourceRoot":"","sources":["../../src/db/create-get-db.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAuCzD;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAK9C;AA0BD,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"create-get-db.d.ts","sourceRoot":"","sources":["../../src/db/create-get-db.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAuCzD;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAK9C;AA0BD,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC,SAqHpD,cAAc,CAAC,CAAC,CAAC,CASpC"}
|
package/dist/db/create-get-db.js
CHANGED
|
@@ -86,6 +86,13 @@ export function createGetDb(schema) {
|
|
|
86
86
|
if (isNeonUrl(url)) {
|
|
87
87
|
_dbReady = getNeonServerlessDrizzle().then(({ drizzle, Pool }) => {
|
|
88
88
|
const pool = new Pool({ connectionString: url });
|
|
89
|
+
// Neon Pool emits 'error' on WebSocket drops (idle, Lambda
|
|
90
|
+
// suspend, network). Without a listener Node 24 throws
|
|
91
|
+
// `Unhandled error` as a fatal uncaught exception. The next
|
|
92
|
+
// query reconnects transparently, so just log and swallow.
|
|
93
|
+
pool.on("error", (err) => {
|
|
94
|
+
console.warn("[db/neon] pool error (will reconnect on next query):", err instanceof Error ? err.message : err);
|
|
95
|
+
});
|
|
89
96
|
_db = drizzle(pool, { schema });
|
|
90
97
|
});
|
|
91
98
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-get-db.js","sourceRoot":"","sources":["../../src/db/create-get-db.ts"],"names":[],"mappings":"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","sourcesContent":["import { drizzle as drizzleD1 } from \"drizzle-orm/d1\";\nimport type { LibSQLDatabase } from \"drizzle-orm/libsql\";\nimport {\n getDialect,\n getDatabaseUrl,\n getDatabaseAuthToken,\n isLocalSqliteUrl,\n prepareLocalSqliteUrl,\n sqliteFilenameFromUrl,\n} from \"./client.js\";\n\n// Lazy driver loaders — cached promises so dynamic import only runs once.\nlet _pgDrizzle: Promise<{ drizzle: any; postgres: any }> | undefined;\nfunction getPgDrizzle() {\n if (!_pgDrizzle) {\n _pgDrizzle = Promise.all([\n import(\"drizzle-orm/postgres-js\"),\n import(\"postgres\"),\n ]).then(([drizzleMod, pgMod]) => ({\n drizzle: drizzleMod.drizzle,\n postgres: pgMod.default,\n }));\n }\n return _pgDrizzle;\n}\n\nlet _neonServerlessDrizzle: Promise<{ drizzle: any; Pool: any }> | undefined;\nfunction getNeonServerlessDrizzle() {\n if (!_neonServerlessDrizzle) {\n _neonServerlessDrizzle = Promise.all([\n import(\"drizzle-orm/neon-serverless\"),\n import(\"@neondatabase/serverless\"),\n ]).then(([drizzleMod, neonMod]) => ({\n drizzle: drizzleMod.drizzle,\n Pool: neonMod.Pool,\n }));\n }\n return _neonServerlessDrizzle;\n}\n\n/**\n * Neon's pooler endpoints cold-start in 5–10s. Serverless environments\n * (Netlify Functions, Vercel Edge, CF Workers) have short cold-start\n * budgets of their own, and `postgres-js` opens a raw TCP connection on\n * port 5432 that can't negotiate around Neon's wake-up window — every\n * request after an idle period 502s. `@neondatabase/serverless` rides\n * over WebSockets (HTTP/443 upgrade) and handles Neon wake-up\n * transparently, supports transactions, and works in every serverless\n * runtime we deploy to, so we prefer it whenever the URL points at Neon.\n */\nexport function isNeonUrl(url: string): boolean {\n // Must match neon.tech followed by port/path/query/end — include `?` so\n // URLs like `postgres://…@ep.neon.tech?sslmode=require` (no explicit port\n // or path) still route through the serverless driver.\n return /\\.neon\\.tech([:/?]|$)/.test(url);\n}\n\nlet _libsqlWebDrizzle: Promise<{ drizzle: any }> | undefined;\nfunction getLibsqlWebDrizzle() {\n if (!_libsqlWebDrizzle) {\n _libsqlWebDrizzle = import(\"drizzle-orm/libsql/web\").then((mod) => ({\n drizzle: mod.drizzle,\n }));\n }\n return _libsqlWebDrizzle;\n}\n\nlet _betterSqliteDrizzle: Promise<{ drizzle: any; Database: any }> | undefined;\nfunction getBetterSqliteDrizzle() {\n if (!_betterSqliteDrizzle) {\n _betterSqliteDrizzle = Promise.all([\n import(\"drizzle-orm/better-sqlite3\"),\n import(\"better-sqlite3\"),\n ]).then(([drizzleMod, sqliteMod]) => ({\n drizzle: drizzleMod.drizzle,\n Database: sqliteMod.default,\n }));\n }\n return _betterSqliteDrizzle;\n}\n\nexport function createGetDb<T extends Record<string, unknown>>(schema: T) {\n let _db: any;\n let _dbReady: Promise<any> | undefined;\n\n function startInit(): Promise<any> {\n if (_dbReady) return _dbReady;\n\n const url = getDatabaseUrl(\"file:./data/app.db\");\n const dialect = getDialect();\n\n // D1 only if dialect detected it (DATABASE_URL takes priority)\n if (dialect === \"d1\") {\n const d1 = globalThis.__cf_env?.DB;\n if (d1) {\n _db = drizzleD1(d1, { schema }) as unknown as LibSQLDatabase<T>;\n _dbReady = Promise.resolve(_db);\n return _dbReady;\n }\n }\n\n if (dialect === \"postgres\") {\n if (isNeonUrl(url)) {\n _dbReady = getNeonServerlessDrizzle().then(({ drizzle, Pool }) => {\n const pool = new Pool({ connectionString: url });\n _db = drizzle(pool, { schema });\n });\n } else {\n _dbReady = getPgDrizzle().then(({ drizzle, postgres }) => {\n const client = postgres(url, {\n onnotice: () => {},\n idle_timeout: 240,\n max_lifetime: 60 * 30,\n connect_timeout: 10,\n ...(url.includes(\"supabase\") ? { prepare: false } : {}),\n });\n _db = drizzle(client, { schema });\n });\n }\n } else if (isLocalSqliteUrl(url)) {\n _dbReady = Promise.all([\n prepareLocalSqliteUrl(url.startsWith(\"file:\") ? url : `file:${url}`),\n getBetterSqliteDrizzle(),\n ]).then(([sqliteUrl, { drizzle, Database }]) => {\n const sqlite = new Database(sqliteFilenameFromUrl(sqliteUrl));\n sqlite.pragma(\"journal_mode = WAL\");\n _db = drizzle(sqlite, { schema });\n });\n } else {\n _dbReady = getLibsqlWebDrizzle().then(({ drizzle }) => {\n _db = drizzle({\n connection: { url, authToken: getDatabaseAuthToken() },\n schema,\n });\n });\n }\n return _dbReady;\n }\n\n /**\n * Create a lazy proxy that records property accesses and method calls,\n * then replays them on the real DB once init completes. Supports\n * Drizzle's chained API: db.select().from(table).where(...).\n *\n * When `.then()` is called (i.e. the chain is awaited), the proxy\n * awaits _dbReady and replays the recorded chain on the real _db.\n */\n function createLazyProxy(\n ready: Promise<any>,\n chain: Array<{ prop: string | symbol; args?: any[] }>,\n ): any {\n return new Proxy(function () {} as any, {\n get(_target, prop) {\n // When awaited, replay the chain on the real db\n if (prop === \"then\" || prop === \"catch\" || prop === \"finally\") {\n const promise = ready.then(() => {\n let result: any = _db;\n for (const step of chain) {\n const val = result[step.prop];\n result =\n typeof val === \"function\" ? val.apply(result, step.args) : val;\n }\n return result;\n });\n return (promise as any)[prop].bind(promise);\n }\n // Symbol.toStringTag, Symbol.iterator, etc. — return another proxy\n // Property access (e.g. db.query) — record and return another proxy\n return createLazyProxy(ready, [...chain, { prop }]);\n },\n apply(_target, _thisArg, args) {\n // Method call (e.g. .from(table)) — record args and return another proxy\n if (chain.length === 0) return createLazyProxy(ready, []);\n const last = chain[chain.length - 1];\n const newChain = chain.slice(0, -1);\n newChain.push({ prop: last.prop, args });\n return createLazyProxy(ready, newChain);\n },\n });\n }\n\n /**\n * Get the Drizzle DB instance. Kicks off lazy init on first call.\n * If the async init hasn't completed yet, returns a lazy Proxy that\n * records the Drizzle chain (select/from/where/etc.) and replays it\n * once the DB driver finishes loading. Since callers always `await`\n * the final result, the proxy is transparent.\n */\n function getDb(): LibSQLDatabase<T> {\n if (_db) return _db;\n startInit();\n if (_db) return _db;\n\n return createLazyProxy(_dbReady!, []) as LibSQLDatabase<T>;\n }\n\n return getDb;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"create-get-db.js","sourceRoot":"","sources":["../../src/db/create-get-db.ts"],"names":[],"mappings":"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","sourcesContent":["import { drizzle as drizzleD1 } from \"drizzle-orm/d1\";\nimport type { LibSQLDatabase } from \"drizzle-orm/libsql\";\nimport {\n getDialect,\n getDatabaseUrl,\n getDatabaseAuthToken,\n isLocalSqliteUrl,\n prepareLocalSqliteUrl,\n sqliteFilenameFromUrl,\n} from \"./client.js\";\n\n// Lazy driver loaders — cached promises so dynamic import only runs once.\nlet _pgDrizzle: Promise<{ drizzle: any; postgres: any }> | undefined;\nfunction getPgDrizzle() {\n if (!_pgDrizzle) {\n _pgDrizzle = Promise.all([\n import(\"drizzle-orm/postgres-js\"),\n import(\"postgres\"),\n ]).then(([drizzleMod, pgMod]) => ({\n drizzle: drizzleMod.drizzle,\n postgres: pgMod.default,\n }));\n }\n return _pgDrizzle;\n}\n\nlet _neonServerlessDrizzle: Promise<{ drizzle: any; Pool: any }> | undefined;\nfunction getNeonServerlessDrizzle() {\n if (!_neonServerlessDrizzle) {\n _neonServerlessDrizzle = Promise.all([\n import(\"drizzle-orm/neon-serverless\"),\n import(\"@neondatabase/serverless\"),\n ]).then(([drizzleMod, neonMod]) => ({\n drizzle: drizzleMod.drizzle,\n Pool: neonMod.Pool,\n }));\n }\n return _neonServerlessDrizzle;\n}\n\n/**\n * Neon's pooler endpoints cold-start in 5–10s. Serverless environments\n * (Netlify Functions, Vercel Edge, CF Workers) have short cold-start\n * budgets of their own, and `postgres-js` opens a raw TCP connection on\n * port 5432 that can't negotiate around Neon's wake-up window — every\n * request after an idle period 502s. `@neondatabase/serverless` rides\n * over WebSockets (HTTP/443 upgrade) and handles Neon wake-up\n * transparently, supports transactions, and works in every serverless\n * runtime we deploy to, so we prefer it whenever the URL points at Neon.\n */\nexport function isNeonUrl(url: string): boolean {\n // Must match neon.tech followed by port/path/query/end — include `?` so\n // URLs like `postgres://…@ep.neon.tech?sslmode=require` (no explicit port\n // or path) still route through the serverless driver.\n return /\\.neon\\.tech([:/?]|$)/.test(url);\n}\n\nlet _libsqlWebDrizzle: Promise<{ drizzle: any }> | undefined;\nfunction getLibsqlWebDrizzle() {\n if (!_libsqlWebDrizzle) {\n _libsqlWebDrizzle = import(\"drizzle-orm/libsql/web\").then((mod) => ({\n drizzle: mod.drizzle,\n }));\n }\n return _libsqlWebDrizzle;\n}\n\nlet _betterSqliteDrizzle: Promise<{ drizzle: any; Database: any }> | undefined;\nfunction getBetterSqliteDrizzle() {\n if (!_betterSqliteDrizzle) {\n _betterSqliteDrizzle = Promise.all([\n import(\"drizzle-orm/better-sqlite3\"),\n import(\"better-sqlite3\"),\n ]).then(([drizzleMod, sqliteMod]) => ({\n drizzle: drizzleMod.drizzle,\n Database: sqliteMod.default,\n }));\n }\n return _betterSqliteDrizzle;\n}\n\nexport function createGetDb<T extends Record<string, unknown>>(schema: T) {\n let _db: any;\n let _dbReady: Promise<any> | undefined;\n\n function startInit(): Promise<any> {\n if (_dbReady) return _dbReady;\n\n const url = getDatabaseUrl(\"file:./data/app.db\");\n const dialect = getDialect();\n\n // D1 only if dialect detected it (DATABASE_URL takes priority)\n if (dialect === \"d1\") {\n const d1 = globalThis.__cf_env?.DB;\n if (d1) {\n _db = drizzleD1(d1, { schema }) as unknown as LibSQLDatabase<T>;\n _dbReady = Promise.resolve(_db);\n return _dbReady;\n }\n }\n\n if (dialect === \"postgres\") {\n if (isNeonUrl(url)) {\n _dbReady = getNeonServerlessDrizzle().then(({ drizzle, Pool }) => {\n const pool = new Pool({ connectionString: url });\n // Neon Pool emits 'error' on WebSocket drops (idle, Lambda\n // suspend, network). Without a listener Node 24 throws\n // `Unhandled error` as a fatal uncaught exception. The next\n // query reconnects transparently, so just log and swallow.\n pool.on(\"error\", (err: unknown) => {\n console.warn(\n \"[db/neon] pool error (will reconnect on next query):\",\n err instanceof Error ? err.message : err,\n );\n });\n _db = drizzle(pool, { schema });\n });\n } else {\n _dbReady = getPgDrizzle().then(({ drizzle, postgres }) => {\n const client = postgres(url, {\n onnotice: () => {},\n idle_timeout: 240,\n max_lifetime: 60 * 30,\n connect_timeout: 10,\n ...(url.includes(\"supabase\") ? { prepare: false } : {}),\n });\n _db = drizzle(client, { schema });\n });\n }\n } else if (isLocalSqliteUrl(url)) {\n _dbReady = Promise.all([\n prepareLocalSqliteUrl(url.startsWith(\"file:\") ? url : `file:${url}`),\n getBetterSqliteDrizzle(),\n ]).then(([sqliteUrl, { drizzle, Database }]) => {\n const sqlite = new Database(sqliteFilenameFromUrl(sqliteUrl));\n sqlite.pragma(\"journal_mode = WAL\");\n _db = drizzle(sqlite, { schema });\n });\n } else {\n _dbReady = getLibsqlWebDrizzle().then(({ drizzle }) => {\n _db = drizzle({\n connection: { url, authToken: getDatabaseAuthToken() },\n schema,\n });\n });\n }\n return _dbReady;\n }\n\n /**\n * Create a lazy proxy that records property accesses and method calls,\n * then replays them on the real DB once init completes. Supports\n * Drizzle's chained API: db.select().from(table).where(...).\n *\n * When `.then()` is called (i.e. the chain is awaited), the proxy\n * awaits _dbReady and replays the recorded chain on the real _db.\n */\n function createLazyProxy(\n ready: Promise<any>,\n chain: Array<{ prop: string | symbol; args?: any[] }>,\n ): any {\n return new Proxy(function () {} as any, {\n get(_target, prop) {\n // When awaited, replay the chain on the real db\n if (prop === \"then\" || prop === \"catch\" || prop === \"finally\") {\n const promise = ready.then(() => {\n let result: any = _db;\n for (const step of chain) {\n const val = result[step.prop];\n result =\n typeof val === \"function\" ? val.apply(result, step.args) : val;\n }\n return result;\n });\n return (promise as any)[prop].bind(promise);\n }\n // Symbol.toStringTag, Symbol.iterator, etc. — return another proxy\n // Property access (e.g. db.query) — record and return another proxy\n return createLazyProxy(ready, [...chain, { prop }]);\n },\n apply(_target, _thisArg, args) {\n // Method call (e.g. .from(table)) — record args and return another proxy\n if (chain.length === 0) return createLazyProxy(ready, []);\n const last = chain[chain.length - 1];\n const newChain = chain.slice(0, -1);\n newChain.push({ prop: last.prop, args });\n return createLazyProxy(ready, newChain);\n },\n });\n }\n\n /**\n * Get the Drizzle DB instance. Kicks off lazy init on first call.\n * If the async init hasn't completed yet, returns a lazy Proxy that\n * records the Drizzle chain (select/from/where/etc.) and replays it\n * once the DB driver finishes loading. Since callers always `await`\n * the final result, the proxy is transparent.\n */\n function getDb(): LibSQLDatabase<T> {\n if (_db) return _db;\n startInit();\n if (_db) return _db;\n\n return createLazyProxy(_dbReady!, []) as LibSQLDatabase<T>;\n }\n\n return getDb;\n}\n"]}
|
|
@@ -56,7 +56,7 @@ export function createExtensionActionEntries() {
|
|
|
56
56
|
},
|
|
57
57
|
"create-extension": {
|
|
58
58
|
tool: {
|
|
59
|
-
description: "Create a sandboxed Alpine.js mini-app extension. Use this when the user asks to create, build, or make an extension/widget/dashboard/calculator. Call this action exactly once per requested extension. The content must be a self-contained Alpine.js HTML body snippet that can use appAction(), appFetch(), dbQuery(), dbExec(), extensionFetch(), and extensionData. Prefer appAction(name, params) for app data and actions, including read actions mounted as GET; do not call template /api/* routes from appFetch because the extension bridge only allows framework /_agent-native/* paths. Parse JSON string action results before aggregating; use dbQuery()/dbExec() only for known existing SQL tables.",
|
|
59
|
+
description: "Create a sandboxed Alpine.js mini-app extension. Use this when the user asks to create, build, or make an extension/widget/dashboard/calculator. Call this action exactly once per requested extension. The content must be a self-contained Alpine.js HTML body snippet that can use appAction(), appFetch(), dbQuery(), dbExec(), extensionFetch(), and extensionData. Prefer appAction(name, params) for app data and actions, including read actions mounted as GET; do not call template /api/* routes from appFetch because the extension bridge only allows framework /_agent-native/* paths. Parse JSON string action results before aggregating; use dbQuery()/dbExec() only for known existing SQL tables. For any non-trivial component (more than a couple of state fields, any methods, any string formatting, any branching) put the component in a <script> block via Alpine.data('name', () => ({...})) and reference it with x-data=\"name\" — do NOT cram methods, template literals, or branching logic into an inline x-data=\"{...}\" attribute (HTML parser pitfalls cause ReferenceError failures). Define every variable referenced from x-text/x-show/x-if/x-for on the data object's initial state. If the extension's value depends on an LLM call, require a real key via ${keys.OPENAI_API_KEY}/${keys.ANTHROPIC_API_KEY} (and tell the user to add it in Settings → Secrets if missing) or route the AI work to the agent chat — never ship a stubbed analysis step that renders a placeholder/boolean as the result.",
|
|
60
60
|
parameters: {
|
|
61
61
|
type: "object",
|
|
62
62
|
properties: {
|