@sqlite-sync/devtools 0.9.3 → 0.10.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/README.md +5 -3
- package/dist/index.d.ts +5 -2
- package/dist/index.js +847 -1666
- package/dist/index.js.map +1 -1
- package/package.json +8 -4
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
1
|
+
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
2
|
+
import { createPortal } from "react-dom";
|
|
2
3
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
4
|
//#region src/devtools-registry.ts
|
|
4
5
|
const devtoolsRegistrySymbol = Symbol.for("@sqlite-sync/devtools");
|
|
@@ -44,10 +45,31 @@ function getOrCreateSQLiteSyncDevtoolsRegistry() {
|
|
|
44
45
|
return registryGlobal[devtoolsRegistrySymbol];
|
|
45
46
|
}
|
|
46
47
|
//#endregion
|
|
48
|
+
//#region src/devtools.css?inline
|
|
49
|
+
var devtools_default = ":host {\n all: initial;\n z-index: 9998;\n --ss-bg: #0e1015;\n --ss-bg-panel: #161921;\n --ss-bg-card: #1c2030;\n --ss-bg-input: #111318;\n --ss-border: #2a2f3e;\n --ss-border-light: #343a4f;\n --ss-text: #e2e8f0;\n --ss-text-muted: #6b7280;\n --ss-text-dim: #9ca3af;\n --ss-teal: #2dd4bf;\n --ss-teal-dim: #2dd4bf1f;\n --ss-teal-glow: #2dd4bf0f;\n --ss-error: #f87171;\n --ss-error-bg: #f8717114;\n --ss-error-border: #f8717140;\n --ss-success: #34d399;\n --ss-success-bg: #34d39914;\n --ss-amber: #fbbf24;\n color: var(--ss-text);\n font-family: ui-sans-serif, system-ui, sans-serif;\n font-size: .88rem;\n display: block;\n position: relative;\n}\n\n:host *, :host :before, :host :after {\n box-sizing: border-box;\n}\n\n.mono {\n font-family: ui-monospace, monospace;\n}\n\n.sm {\n font-size: .78rem;\n}\n\n.alignCenter {\n text-align: center;\n}\n\n.mlAuto {\n margin-left: auto;\n}\n\n.hiddenInput {\n display: none;\n}\n\n.floatingRoot {\n pointer-events: none;\n z-index: 9998;\n position: fixed;\n inset: 0;\n}\n\n.triggerButton {\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-panel);\n color: var(--ss-text);\n box-shadow: 0 0 0 1px var(--ss-border),\n 0 4px 16px #00000080;\n cursor: grab;\n touch-action: none;\n user-select: none;\n pointer-events: auto;\n border-radius: 8px;\n align-items: center;\n gap: .3rem;\n padding: .3rem .45rem;\n display: inline-flex;\n position: absolute;\n bottom: 16px;\n right: 16px;\n}\n\n.triggerIcon {\n color: var(--ss-teal);\n font-size: .9rem;\n line-height: 1;\n}\n\n.triggerCount {\n background-color: var(--ss-teal-dim);\n min-width: 1.1rem;\n color: var(--ss-teal);\n text-align: center;\n border-radius: 4px;\n padding: .05rem .25rem;\n font-family: ui-monospace, monospace;\n font-size: .65rem;\n font-weight: 700;\n}\n\n.overlay {\n z-index: 9999;\n backdrop-filter: blur(8px);\n background-color: #000000b8;\n justify-content: center;\n align-items: center;\n padding: 1.5rem;\n display: flex;\n position: fixed;\n inset: 0;\n}\n\n.dialog {\n border: 1px solid var(--ss-border);\n background: var(--ss-bg);\n width: min(72rem, 100%);\n height: min(90vh, 860px);\n box-shadow: 0 0 0 1px var(--ss-border),\n 0 40px 80px #000c,\n 0 0 60px #2dd4bf0a;\n color: var(--ss-text);\n border-radius: 16px;\n flex-direction: column;\n font-family: ui-sans-serif, system-ui, sans-serif;\n font-size: .88rem;\n display: flex;\n overflow: hidden;\n}\n\n.header {\n border-bottom: 1px solid var(--ss-border);\n background: var(--ss-bg-panel);\n flex-shrink: 0;\n justify-content: space-between;\n align-items: center;\n gap: 1rem;\n padding: .85rem 1.1rem;\n display: flex;\n}\n\n.headerLeft {\n align-items: center;\n gap: .75rem;\n display: flex;\n}\n\n.headerLogo {\n color: var(--ss-teal);\n font-size: 1.3rem;\n line-height: 1;\n}\n\n.eyebrow {\n letter-spacing: .1em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n font-family: ui-monospace, monospace;\n font-size: .65rem;\n font-weight: 600;\n}\n\n.title {\n color: var(--ss-text);\n letter-spacing: -.01em;\n margin: .05rem 0 0;\n font-size: .95rem;\n font-weight: 700;\n}\n\n.headerRight {\n align-items: center;\n gap: .6rem;\n display: flex;\n}\n\n.instancePickerLabel {\n align-items: center;\n gap: .5rem;\n display: flex;\n}\n\n.instancePickerText {\n color: var(--ss-text-muted);\n text-transform: uppercase;\n letter-spacing: .06em;\n font-size: .72rem;\n font-weight: 600;\n}\n\n.instancePickerSelect {\n border: 1px solid var(--ss-border);\n background-color: var(--ss-bg-card);\n color: var(--ss-text);\n cursor: pointer;\n border-radius: 7px;\n padding: .35rem .6rem;\n font-family: ui-monospace, monospace;\n font-size: .82rem;\n}\n\n.instanceCountBadge {\n color: var(--ss-teal);\n background-color: var(--ss-teal-dim);\n border-radius: 5px;\n padding: .2rem .5rem;\n font-family: ui-monospace, monospace;\n font-size: .72rem;\n font-weight: 600;\n}\n\n.closeButton {\n border: 1px solid var(--ss-border);\n width: 28px;\n height: 28px;\n color: var(--ss-text-muted);\n cursor: pointer;\n background-color: #0000;\n border-radius: 7px;\n justify-content: center;\n align-items: center;\n font-size: .82rem;\n font-weight: 600;\n display: flex;\n}\n\n.hideLauncherButton {\n border: 1px solid var(--ss-border);\n color: var(--ss-text-dim);\n cursor: pointer;\n white-space: nowrap;\n background-color: #0000;\n border-radius: 7px;\n padding: .3rem .65rem;\n font-size: .75rem;\n font-weight: 600;\n}\n\n.emptyState {\n flex-direction: column;\n flex: 1;\n justify-content: center;\n align-items: center;\n gap: .75rem;\n padding: 4rem 2rem;\n display: flex;\n}\n\n.emptyStateIcon {\n color: var(--ss-text-muted);\n opacity: .4;\n font-size: 2.5rem;\n}\n\n.emptyStateText {\n color: var(--ss-text-dim);\n margin: 0;\n font-size: .95rem;\n font-weight: 600;\n}\n\n.emptyStateSubtext {\n color: var(--ss-text-muted);\n text-align: center;\n margin: 0;\n font-size: .82rem;\n}\n\n.inlineCode {\n background-color: var(--ss-bg-card);\n border: 1px solid var(--ss-border);\n color: var(--ss-teal);\n border-radius: 4px;\n padding: .1em .4em;\n font-family: ui-monospace, monospace;\n font-size: .88em;\n}\n\n.contentLayout {\n flex: 1;\n grid-template-columns: 200px minmax(0, 1fr);\n min-height: 0;\n display: grid;\n overflow: hidden;\n}\n\n.sidebar {\n border-right: 1px solid var(--ss-border);\n background: var(--ss-bg-panel);\n flex-direction: column;\n gap: 0;\n padding: .75rem;\n display: flex;\n overflow-y: auto;\n}\n\n.nav {\n flex-direction: column;\n gap: .25rem;\n margin-bottom: 1rem;\n display: flex;\n}\n\n.navIcon {\n opacity: .7;\n font-size: .7rem;\n}\n\n.sidebarInfo {\n background: var(--ss-bg-card);\n border: 1px solid var(--ss-border);\n border-radius: 8px;\n margin-top: auto;\n padding: .75rem;\n}\n\n.sidebarInfoLabel {\n letter-spacing: .08em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n margin-bottom: .3rem;\n font-size: .65rem;\n font-weight: 600;\n}\n\n.sidebarInfoValue {\n color: var(--ss-text);\n word-break: break-word;\n font-family: ui-monospace, monospace;\n font-size: .88rem;\n font-weight: 600;\n}\n\n.sidebarInfoSub {\n color: var(--ss-text-muted);\n margin-top: .25rem;\n font-family: ui-monospace, monospace;\n font-size: .72rem;\n}\n\n.mainPane {\n min-width: 0;\n padding: 1rem;\n overflow-y: auto;\n}\n\n.overviewLayout {\n flex-direction: column;\n gap: 1.25rem;\n display: flex;\n}\n\n.overviewCardsRow {\n grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));\n gap: .75rem;\n display: grid;\n}\n\n.overviewCard {\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n border-radius: 10px;\n padding: .9rem 1rem;\n}\n\n.overviewCardLabel {\n letter-spacing: .08em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n margin-bottom: .4rem;\n font-size: .68rem;\n font-weight: 600;\n}\n\n.overviewCardValue {\n color: var(--ss-text);\n word-break: break-word;\n font-size: 1rem;\n font-weight: 700;\n}\n\n.overviewCardSub {\n color: var(--ss-text-muted);\n margin-top: .25rem;\n font-family: ui-monospace, monospace;\n font-size: .68rem;\n}\n\n.overviewSection {\n flex-direction: column;\n gap: .5rem;\n display: flex;\n}\n\n.overviewSectionTitle {\n letter-spacing: .08em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n font-size: .72rem;\n font-weight: 600;\n}\n\n.overviewSectionHeader {\n justify-content: space-between;\n align-items: center;\n gap: .75rem;\n display: flex;\n}\n\n.refreshButton {\n border: 1px solid var(--ss-border);\n color: var(--ss-text-dim);\n cursor: pointer;\n background-color: #0000;\n border-radius: 7px;\n flex-shrink: 0;\n padding: .35rem .7rem;\n font-family: ui-monospace, monospace;\n font-size: .78rem;\n}\n\n.overviewAccumulatorValue {\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n color: var(--ss-text);\n word-break: break-all;\n border-radius: 8px;\n padding: .75rem;\n font-family: ui-monospace, monospace;\n font-size: .78rem;\n line-height: 1.5;\n}\n\n.overviewAccumulatorEmpty {\n color: var(--ss-text-muted);\n font-style: italic;\n}\n\n.overviewAccumulatorError {\n color: var(--ss-error);\n}\n\n.overviewEmpty {\n color: var(--ss-text-muted);\n font-size: .82rem;\n font-style: italic;\n}\n\n.eventCountGrid {\n grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr));\n gap: .5rem;\n display: grid;\n}\n\n.eventCountCard {\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n border-radius: 8px;\n padding: .75rem .85rem;\n}\n\n.eventCountValue {\n color: var(--ss-text);\n margin-bottom: .35rem;\n font-family: ui-monospace, monospace;\n font-size: 1.05rem;\n font-weight: 700;\n}\n\n.eventCountValue[data-tone=\"amber\"][data-emphasize=\"true\"] {\n color: var(--ss-amber);\n}\n\n.eventCountValue[data-tone=\"success\"][data-emphasize=\"true\"] {\n color: var(--ss-success);\n}\n\n.eventCountValue[data-tone=\"error\"][data-emphasize=\"true\"] {\n color: var(--ss-error);\n}\n\n.dataActions {\n gap: .4rem;\n display: flex;\n}\n\n.dataButton {\n border: 1px solid var(--ss-border);\n color: var(--ss-teal);\n cursor: pointer;\n white-space: nowrap;\n background-color: #0000;\n border-radius: 7px;\n padding: .4rem .8rem;\n font-size: .78rem;\n font-weight: 600;\n}\n\n.dataStatusSuccess {\n color: var(--ss-success);\n font-size: .75rem;\n}\n\n.dataStatusError {\n color: var(--ss-error);\n word-break: break-word;\n font-size: .75rem;\n}\n\n.dangerZone {\n border: 1px solid var(--ss-error-border);\n background: var(--ss-error-bg);\n border-radius: 10px;\n margin-top: auto;\n padding: .75rem 1rem;\n}\n\n.dangerZoneTitle {\n letter-spacing: .08em;\n text-transform: uppercase;\n color: var(--ss-error);\n margin-bottom: .5rem;\n font-size: .65rem;\n font-weight: 700;\n}\n\n.dangerZoneRow {\n justify-content: space-between;\n align-items: center;\n gap: 1rem;\n display: flex;\n}\n\n.dangerZoneDesc {\n color: var(--ss-text-muted);\n font-size: .75rem;\n line-height: 1.5;\n}\n\n.dangerZoneActions {\n flex-shrink: 0;\n gap: .4rem;\n display: flex;\n}\n\n.resetButton {\n border: 1px solid var(--ss-error-border);\n color: var(--ss-error);\n cursor: pointer;\n white-space: nowrap;\n background-color: #0000;\n border-radius: 7px;\n flex-shrink: 0;\n padding: .35rem .75rem;\n font-size: .78rem;\n font-weight: 600;\n}\n\n.resetCancelButton {\n border: 1px solid var(--ss-border);\n color: var(--ss-text-dim);\n cursor: pointer;\n white-space: nowrap;\n background-color: #0000;\n border-radius: 7px;\n padding: .35rem .65rem;\n font-size: .78rem;\n font-weight: 600;\n}\n\n.resetConfirmButton {\n background-color: var(--ss-error);\n color: #0e1015;\n cursor: pointer;\n white-space: nowrap;\n border: none;\n border-radius: 7px;\n padding: .35rem .75rem;\n font-size: .78rem;\n font-weight: 700;\n}\n\n.queryRunnerLayout {\n flex-direction: column;\n gap: .75rem;\n height: 100%;\n display: flex;\n}\n\n.queryToolbar {\n flex-wrap: wrap;\n justify-content: space-between;\n align-items: center;\n gap: .75rem;\n display: flex;\n}\n\n.targetToggle {\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n border-radius: 8px;\n gap: 0;\n display: flex;\n overflow: hidden;\n}\n\n.queryToolbarRight {\n align-items: center;\n gap: .6rem;\n display: flex;\n}\n\n.noInstanceWarning {\n color: var(--ss-amber);\n font-size: .75rem;\n font-weight: 500;\n}\n\n.shortcutHint {\n color: var(--ss-text-muted);\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n border-radius: 5px;\n padding: .2rem .5rem;\n font-family: ui-monospace, monospace;\n font-size: .72rem;\n}\n\n.editorWrapper {\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-input);\n border-radius: 10px;\n overflow: hidden;\n}\n\n.textarea {\n resize: vertical;\n width: 100%;\n min-height: 9rem;\n color: var(--ss-text);\n box-sizing: border-box;\n background-color: #0000;\n border: none;\n outline: none;\n padding: .85rem 1rem;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: .875rem;\n line-height: 1.6;\n}\n\n.helperText {\n color: var(--ss-text-muted);\n font-size: .75rem;\n line-height: 1.5;\n}\n\n.resultPanel {\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-panel);\n border-radius: 10px;\n flex-direction: column;\n gap: .6rem;\n display: flex;\n overflow: hidden;\n}\n\n.errorPanel {\n border: 1px solid var(--ss-error-border);\n background: var(--ss-error-bg);\n border-radius: 10px;\n flex-direction: column;\n gap: .6rem;\n padding: .85rem 1rem;\n display: flex;\n}\n\n.resultHeader {\n border-bottom: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n align-items: center;\n gap: .6rem;\n padding: .6rem .85rem;\n display: flex;\n}\n\n.successBadge {\n color: var(--ss-success);\n background-color: var(--ss-success-bg);\n border-radius: 5px;\n padding: .15rem .5rem;\n font-family: ui-monospace, monospace;\n font-size: .72rem;\n font-weight: 700;\n}\n\n.errorBadge {\n color: var(--ss-error);\n background-color: var(--ss-error-bg);\n border-radius: 5px;\n padding: .15rem .5rem;\n font-family: ui-monospace, monospace;\n font-size: .72rem;\n font-weight: 700;\n}\n\n.resultMeta {\n color: var(--ss-text-muted);\n font-family: ui-monospace, monospace;\n font-size: .72rem;\n}\n\n.resultEmpty {\n color: var(--ss-text-muted);\n text-align: center;\n padding: 1.5rem;\n font-size: .82rem;\n font-style: italic;\n}\n\n.resultRaw {\n white-space: pre-wrap;\n word-break: break-word;\n color: var(--ss-text);\n margin: 0;\n padding: .85rem 1rem;\n font-family: ui-monospace, monospace;\n font-size: .8rem;\n line-height: 1.5;\n overflow-x: auto;\n}\n\n.errorMessage {\n color: var(--ss-error);\n white-space: pre-wrap;\n word-break: break-word;\n margin: 0;\n font-family: ui-monospace, monospace;\n font-size: .82rem;\n line-height: 1.6;\n}\n\n.tableWrapper {\n max-height: 320px;\n overflow: auto;\n}\n\n.table {\n border-collapse: collapse;\n width: 100%;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: .8rem;\n}\n\n.table tbody tr:nth-child(2n) {\n background: var(--ss-teal-glow);\n}\n\n.th {\n text-align: left;\n letter-spacing: .05em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n border-bottom: 1px solid var(--ss-border);\n border-right: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n white-space: nowrap;\n padding: .5rem .85rem;\n font-size: .7rem;\n font-weight: 600;\n position: sticky;\n top: 0;\n}\n\n.thRowNum {\n text-align: right;\n letter-spacing: .05em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n border-bottom: 1px solid var(--ss-border);\n border-right: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n white-space: nowrap;\n opacity: .5;\n width: 2.5rem;\n padding: .5rem .85rem;\n font-size: .7rem;\n font-weight: 600;\n position: sticky;\n top: 0;\n}\n\n.td {\n border-bottom: 1px solid var(--ss-border);\n border-right: 1px solid var(--ss-border);\n color: var(--ss-text);\n white-space: nowrap;\n text-overflow: ellipsis;\n max-width: 300px;\n padding: .45rem .85rem;\n overflow: hidden;\n}\n\n.tdRowNum {\n border-bottom: 1px solid var(--ss-border);\n border-right: 1px solid var(--ss-border);\n color: var(--ss-text-muted);\n white-space: nowrap;\n text-overflow: ellipsis;\n opacity: .5;\n text-align: right;\n user-select: none;\n max-width: 300px;\n padding: .45rem .85rem;\n overflow: hidden;\n}\n\n.nullValue {\n color: var(--ss-text-muted);\n opacity: .6;\n font-style: italic;\n}\n\n.jsonValue {\n color: var(--ss-text-dim);\n}\n\n.tabButton {\n width: 100%;\n color: var(--ss-text-dim);\n text-align: left;\n cursor: pointer;\n background: none;\n border: none;\n border-left: 2px solid #0000;\n border-radius: 7px;\n align-items: center;\n gap: .5rem;\n padding: .6rem .75rem;\n font-size: .82rem;\n font-weight: 500;\n transition: background .15s;\n display: flex;\n}\n\n.tabButton[data-active=\"true\"] {\n background: var(--ss-teal-dim);\n color: var(--ss-teal);\n border-left: 2px solid var(--ss-teal);\n font-weight: 700;\n}\n\n.targetButton {\n border: none;\n border-right: 1px solid var(--ss-border);\n color: var(--ss-text-muted);\n cursor: pointer;\n white-space: nowrap;\n background: none;\n padding: .45rem .85rem;\n font-family: ui-monospace, monospace;\n font-size: .78rem;\n font-weight: 500;\n transition: background .1s;\n}\n\n.targetButton[data-active=\"true\"] {\n background: var(--ss-teal-dim);\n color: var(--ss-teal);\n font-weight: 700;\n}\n\n.runButton {\n background: var(--ss-bg-card);\n color: var(--ss-text-muted);\n cursor: not-allowed;\n opacity: 1;\n white-space: nowrap;\n border: none;\n border-radius: 7px;\n align-items: center;\n gap: .4rem;\n padding: .45rem .9rem;\n font-family: ui-monospace, monospace;\n font-size: .82rem;\n font-weight: 700;\n transition: background .15s;\n display: inline-flex;\n}\n\n.runButton[data-enabled=\"true\"] {\n background: var(--ss-teal);\n color: #0e1015;\n cursor: pointer;\n}\n\n.runButton[data-running=\"true\"] {\n opacity: .75;\n}\n\n.runningDot {\n background-color: currentColor;\n border-radius: 50%;\n width: 6px;\n height: 6px;\n}\n\n.schemaLayout {\n flex-direction: column;\n gap: 1.5rem;\n display: flex;\n}\n\n.schemaSection {\n flex-direction: column;\n gap: .65rem;\n display: flex;\n}\n\n.schemaSectionHeader {\n align-items: center;\n gap: .6rem;\n display: flex;\n}\n\n.schemaSectionTitle {\n letter-spacing: .08em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n font-size: .72rem;\n font-weight: 700;\n}\n\n.schemaBadge {\n color: var(--ss-teal);\n background-color: var(--ss-teal-dim);\n border-radius: 4px;\n padding: .1rem .4rem;\n font-family: ui-monospace, monospace;\n font-size: .68rem;\n font-weight: 700;\n}\n\n.schemaVersionChip {\n color: var(--ss-text-muted);\n background-color: var(--ss-bg-card);\n border: 1px solid var(--ss-border);\n border-radius: 4px;\n padding: .1rem .5rem;\n font-family: ui-monospace, monospace;\n font-size: .68rem;\n}\n\n.schemaTableGrid {\n border: 1px solid var(--ss-border);\n border-radius: 10px;\n overflow: hidden;\n}\n\n.schemaColHeader {\n letter-spacing: .07em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n border-right: 1px solid var(--ss-border);\n padding: .5rem .85rem;\n font-size: .68rem;\n font-weight: 700;\n}\n\n.schemaStatusCell {\n justify-content: center;\n align-items: center;\n padding: .6rem .5rem;\n display: flex;\n}\n\n.schemaActiveTag {\n color: var(--ss-success);\n background-color: var(--ss-success-bg);\n border-radius: 4px;\n padding: .15rem .45rem;\n font-family: ui-monospace, monospace;\n font-size: .68rem;\n font-weight: 700;\n}\n\n.schemaEmpty {\n color: var(--ss-text-muted);\n font-size: .82rem;\n font-style: italic;\n}\n\n.schemaTableList {\n flex-direction: column;\n gap: .85rem;\n display: flex;\n}\n\n.schemaTableCard {\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n border-radius: 10px;\n overflow: hidden;\n}\n\n.schemaTableCardHeader {\n border-bottom: 1px solid var(--ss-border);\n flex-direction: column;\n gap: .45rem;\n padding: .75rem .85rem .7rem;\n display: flex;\n}\n\n.schemaTableCardTitleRow {\n align-items: center;\n gap: .5rem;\n display: flex;\n}\n\n.schemaTableCardName {\n color: var(--ss-text);\n font-family: ui-monospace, monospace;\n font-size: .92rem;\n font-weight: 700;\n}\n\n.schemaTableCardDescription {\n color: var(--ss-text-dim);\n margin: 0;\n font-size: .78rem;\n line-height: 1.45;\n}\n\n.schemaTableCardMeta {\n flex-wrap: wrap;\n gap: .35rem;\n display: flex;\n}\n\n.schemaPolicyChip {\n color: var(--ss-text-muted);\n background: var(--ss-bg-input);\n border: 1px solid var(--ss-border);\n border-radius: 4px;\n padding: .12rem .4rem;\n font-family: ui-monospace, monospace;\n font-size: .65rem;\n}\n\n.schemaPolicyChip[data-tone=\"warn\"] {\n color: var(--ss-amber);\n background: #fbbf2414;\n border-color: #fbbf2440;\n}\n\n.schemaColumnGrid {\n flex-direction: column;\n display: flex;\n overflow-x: auto;\n}\n\n.schemaColumnRow {\n border-bottom: 1px solid var(--ss-border);\n grid-template-columns: minmax(6.5rem, .7fr) minmax(8rem, 1fr) minmax(7.5rem, .9fr) minmax(0, 1.8fr);\n min-width: 36rem;\n display: grid;\n}\n\n.schemaColumnRow:last-child {\n border-bottom: none;\n}\n\n.schemaColumnRow[data-system=\"true\"] {\n opacity: .62;\n}\n\n.schemaColumnHeaderRow {\n background: var(--ss-bg-panel);\n}\n\n.schemaColumnHeaderRow .schemaColHeader:last-child {\n border-right: none;\n}\n\n.schemaColumnName, .schemaColumnType, .schemaColumnFlags, .schemaColumnDescription {\n border-right: 1px solid var(--ss-border);\n min-width: 0;\n padding: .5rem .85rem;\n font-size: .76rem;\n}\n\n.schemaColumnDescription {\n color: var(--ss-text-dim);\n overflow-wrap: anywhere;\n border-right: none;\n}\n\n.schemaColumnName {\n color: var(--ss-text);\n font-family: ui-monospace, monospace;\n font-weight: 600;\n}\n\n.schemaColumnType {\n color: var(--ss-teal);\n flex-direction: column;\n gap: .15rem;\n font-family: ui-monospace, monospace;\n display: flex;\n}\n\n.schemaColumnTypeDetail {\n color: var(--ss-text-muted);\n overflow-wrap: anywhere;\n font-size: .65rem;\n font-weight: 400;\n}\n\n.schemaColumnFlags {\n color: var(--ss-text-muted);\n overflow-wrap: anywhere;\n font-family: ui-monospace, monospace;\n}\n\n.liveQueryHeaderRow {\n background-color: var(--ss-bg-card);\n border-bottom: 1px solid var(--ss-border);\n grid-template-columns: minmax(0, 1fr) 220px 110px;\n gap: 0;\n display: grid;\n}\n\n.liveQueryRow {\n border-bottom: 1px solid var(--ss-border);\n grid-template-columns: minmax(0, 1fr) 220px 110px;\n gap: 0;\n display: grid;\n}\n\n.liveQuerySql {\n color: var(--ss-text);\n border-right: 1px solid var(--ss-border);\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n padding: .6rem .85rem;\n font-family: ui-monospace, monospace;\n font-size: .78rem;\n}\n\n.liveQueryParameters {\n color: var(--ss-text-dim);\n border-right: 1px solid var(--ss-border);\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n padding: .6rem .85rem;\n font-family: ui-monospace, monospace;\n font-size: .78rem;\n}\n\n.liveQueryIdleTag {\n color: var(--ss-text-muted);\n background-color: var(--ss-bg-card);\n border: 1px solid var(--ss-border);\n border-radius: 4px;\n padding: .15rem .45rem;\n font-family: ui-monospace, monospace;\n font-size: .68rem;\n font-weight: 700;\n}\n\n.eventLogLayout {\n flex-direction: column;\n gap: .75rem;\n height: 100%;\n display: flex;\n}\n\n.eventLogToolbar {\n flex-wrap: wrap;\n flex-shrink: 0;\n align-items: center;\n gap: .5rem;\n display: flex;\n}\n\n.eventLogFilterSelect {\n border: 1px solid var(--ss-border);\n background-color: var(--ss-bg-card);\n color: var(--ss-text);\n cursor: pointer;\n border-radius: 7px;\n padding: .35rem .6rem;\n font-family: ui-monospace, monospace;\n font-size: .78rem;\n}\n\n.eventLogCount {\n color: var(--ss-text-muted);\n margin-left: auto;\n font-family: ui-monospace, monospace;\n font-size: .72rem;\n}\n\n.eventLogEmpty {\n text-align: center;\n color: var(--ss-text-muted);\n padding: 2rem;\n font-size: .82rem;\n font-style: italic;\n}\n\n.eventLogList {\n flex-direction: column;\n flex: 1;\n gap: .25rem;\n display: flex;\n overflow-y: auto;\n}\n\n.eventRow {\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n border-radius: 8px;\n flex-shrink: 0;\n overflow: hidden;\n}\n\n.eventRow[data-expanded=\"true\"] {\n background: var(--ss-teal-glow);\n border: 1px solid #2dd4bf40;\n}\n\n.eventRowHeader {\n cursor: pointer;\n text-align: left;\n background: none;\n border: none;\n flex-wrap: wrap;\n align-items: center;\n gap: .5rem;\n width: 100%;\n padding: .5rem .75rem;\n display: flex;\n}\n\n.eventSyncId {\n color: var(--ss-text-muted);\n min-width: 3.5rem;\n font-family: ui-monospace, monospace;\n font-size: .7rem;\n}\n\n.eventDataset {\n color: var(--ss-text);\n font-family: ui-monospace, monospace;\n font-size: .8rem;\n font-weight: 600;\n}\n\n.eventItemId {\n color: var(--ss-text-muted);\n text-overflow: ellipsis;\n white-space: nowrap;\n flex: 1;\n min-width: 0;\n font-family: ui-monospace, monospace;\n font-size: .75rem;\n overflow: hidden;\n}\n\n.eventTimestamp {\n color: var(--ss-text-muted);\n margin-left: auto;\n font-family: ui-monospace, monospace;\n font-size: .7rem;\n}\n\n.eventChevron {\n color: var(--ss-text-muted);\n margin-left: .25rem;\n font-size: .6rem;\n}\n\n.eventPayload {\n border-top: 1px solid var(--ss-border);\n padding: .6rem .75rem;\n}\n\n.eventPayloadMeta {\n gap: .75rem;\n margin-bottom: .5rem;\n display: flex;\n}\n\n.eventMetaItem {\n color: var(--ss-text-muted);\n font-family: ui-monospace, monospace;\n font-size: .68rem;\n}\n\n.eventPayloadPre {\n color: var(--ss-text);\n white-space: pre-wrap;\n word-break: break-word;\n margin: 0;\n font-family: ui-monospace, monospace;\n font-size: .78rem;\n line-height: 1.5;\n}\n\n.loadMoreButton {\n border: 1px solid var(--ss-border);\n width: 100%;\n color: var(--ss-text-dim);\n cursor: pointer;\n background-color: #0000;\n border-radius: 8px;\n flex-shrink: 0;\n padding: .6rem;\n font-family: ui-monospace, monospace;\n font-size: .78rem;\n}\n\n.eventBadge {\n white-space: nowrap;\n border-radius: 4px;\n padding: .1rem .4rem;\n font-family: ui-monospace, monospace;\n font-size: .65rem;\n font-weight: 700;\n}\n\n.eventBadge[data-variant=\"create\"] {\n color: var(--ss-teal);\n background-color: var(--ss-teal-dim);\n}\n\n.eventBadge[data-variant=\"update\"] {\n color: #a78bfa;\n background-color: #a78bfa1f;\n}\n\n.eventBadge[data-variant=\"delete\"] {\n color: var(--ss-error);\n background-color: #f871711f;\n}\n\n.eventBadge[data-variant=\"own\"], .eventBadge[data-variant=\"applied\"] {\n color: var(--ss-success);\n background-color: var(--ss-success-bg);\n}\n\n.eventBadge[data-variant=\"remote\"], .eventBadge[data-variant=\"pending\"] {\n color: var(--ss-amber);\n background-color: #fbbf241a;\n}\n\n.eventBadge[data-variant=\"local\"] {\n color: var(--ss-text-dim);\n background-color: var(--ss-bg-card);\n border: 1px solid var(--ss-border);\n}\n\n.eventBadge[data-variant=\"failed\"] {\n color: var(--ss-error);\n background-color: var(--ss-error-bg);\n}\n\n.eventBadge[data-variant=\"skipped\"] {\n color: var(--ss-text-muted);\n background-color: var(--ss-bg-card);\n}\n";
|
|
50
|
+
//#endregion
|
|
51
|
+
//#region src/shadow-root.tsx
|
|
52
|
+
function ShadowRoot({ children, className }) {
|
|
53
|
+
const hostRef = useRef(null);
|
|
54
|
+
const [shadowRoot, setShadowRoot] = useState(null);
|
|
55
|
+
useLayoutEffect(() => {
|
|
56
|
+
const host = hostRef.current;
|
|
57
|
+
if (!host) return;
|
|
58
|
+
setShadowRoot(host.shadowRoot ?? host.attachShadow({ mode: "open" }));
|
|
59
|
+
}, []);
|
|
60
|
+
return /* @__PURE__ */ jsx("div", {
|
|
61
|
+
ref: hostRef,
|
|
62
|
+
className,
|
|
63
|
+
children: shadowRoot ? createPortal(/* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("style", { children: devtools_default }), children] }), shadowRoot) : null
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
//#endregion
|
|
47
67
|
//#region src/devtools.tsx
|
|
48
68
|
const TRIGGER_POSITION_STORAGE_KEY = "sqlite-sync-devtools.trigger-position";
|
|
69
|
+
const TRIGGER_HIDDEN_STORAGE_KEY = "sqlite-sync-devtools.trigger-hidden";
|
|
49
70
|
const DRAG_THRESHOLD_PX = 4;
|
|
50
71
|
const VIEWPORT_MARGIN_PX = 8;
|
|
72
|
+
const TOGGLE_LAUNCHER_HINT = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform) ? "⌘⌥S" : "Ctrl+Alt+S";
|
|
51
73
|
function readStoredTriggerPosition() {
|
|
52
74
|
if (typeof window === "undefined") return null;
|
|
53
75
|
try {
|
|
@@ -130,16 +152,70 @@ function useDraggableTrigger() {
|
|
|
130
152
|
consumeDragClick
|
|
131
153
|
};
|
|
132
154
|
}
|
|
133
|
-
function
|
|
155
|
+
function readStoredTriggerHidden() {
|
|
156
|
+
if (typeof window === "undefined") return false;
|
|
157
|
+
try {
|
|
158
|
+
return window.localStorage.getItem(TRIGGER_HIDDEN_STORAGE_KEY) === "1";
|
|
159
|
+
} catch {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function isToggleLauncherShortcut(event) {
|
|
164
|
+
if (event.shiftKey || !event.altKey || event.code !== "KeyS") return false;
|
|
165
|
+
return event.ctrlKey || event.metaKey;
|
|
166
|
+
}
|
|
167
|
+
function useLauncherVisibility({ hidden: hiddenProp, onHiddenChange }) {
|
|
168
|
+
const isControlled = hiddenProp !== void 0;
|
|
169
|
+
const [uncontrolledHidden, setUncontrolledHidden] = useState(readStoredTriggerHidden);
|
|
170
|
+
const hidden = isControlled ? hiddenProp : uncontrolledHidden;
|
|
171
|
+
const canToggle = !isControlled || onHiddenChange !== void 0;
|
|
172
|
+
const setHidden = useCallback((next) => {
|
|
173
|
+
if (isControlled) {
|
|
174
|
+
onHiddenChange?.(next);
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
setUncontrolledHidden(next);
|
|
178
|
+
try {
|
|
179
|
+
window.localStorage.setItem(TRIGGER_HIDDEN_STORAGE_KEY, next ? "1" : "0");
|
|
180
|
+
} catch {}
|
|
181
|
+
}, [isControlled, onHiddenChange]);
|
|
182
|
+
useEffect(() => {
|
|
183
|
+
if (!canToggle) return;
|
|
184
|
+
const onKeyDown = (event) => {
|
|
185
|
+
if (!isToggleLauncherShortcut(event)) return;
|
|
186
|
+
event.preventDefault();
|
|
187
|
+
setHidden(!hidden);
|
|
188
|
+
};
|
|
189
|
+
window.addEventListener("keydown", onKeyDown);
|
|
190
|
+
return () => window.removeEventListener("keydown", onKeyDown);
|
|
191
|
+
}, [
|
|
192
|
+
canToggle,
|
|
193
|
+
hidden,
|
|
194
|
+
setHidden
|
|
195
|
+
]);
|
|
196
|
+
return {
|
|
197
|
+
hidden,
|
|
198
|
+
setHidden,
|
|
199
|
+
canToggle
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
function SQLiteSyncDevtools({ className, hidden: hiddenProp, onHiddenChange }) {
|
|
134
203
|
const registry = getOrCreateSQLiteSyncDevtoolsRegistry();
|
|
135
204
|
const instances = useSyncExternalStore(registry.subscribe, registry.getSnapshot, getEmptySnapshot).instances;
|
|
136
205
|
const { buttonRef, positionStyle, triggerHandlers, consumeDragClick } = useDraggableTrigger();
|
|
206
|
+
const { hidden, setHidden, canToggle } = useLauncherVisibility({
|
|
207
|
+
hidden: hiddenProp,
|
|
208
|
+
onHiddenChange
|
|
209
|
+
});
|
|
137
210
|
const [isOpen, setIsOpen] = useState(false);
|
|
138
211
|
const [activeTab, setActiveTab] = useState("overview");
|
|
139
212
|
const [selectedInstanceId, setSelectedInstanceId] = useState("");
|
|
140
213
|
const [queryTarget, setQueryTarget] = useState("memory");
|
|
141
214
|
const [query, setQuery] = useState("");
|
|
142
215
|
const [queryState, setQueryState] = useState({ status: "idle" });
|
|
216
|
+
useEffect(() => {
|
|
217
|
+
if (hidden) setIsOpen(false);
|
|
218
|
+
}, [hidden]);
|
|
143
219
|
useEffect(() => {
|
|
144
220
|
if (!isOpen) return;
|
|
145
221
|
const onKeyDown = (event) => {
|
|
@@ -208,210 +284,315 @@ function SQLiteSyncDevtools({ className }) {
|
|
|
208
284
|
});
|
|
209
285
|
}
|
|
210
286
|
};
|
|
211
|
-
return /* @__PURE__ */ jsxs(
|
|
212
|
-
|
|
213
|
-
children: /* @__PURE__ */
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
})]
|
|
233
|
-
})
|
|
234
|
-
}), isOpen ? /* @__PURE__ */ jsx("div", {
|
|
235
|
-
style: overlayStyles,
|
|
236
|
-
onClick: () => setIsOpen(false),
|
|
237
|
-
children: /* @__PURE__ */ jsxs("section", {
|
|
238
|
-
className,
|
|
239
|
-
role: "dialog",
|
|
240
|
-
"aria-modal": "true",
|
|
241
|
-
"aria-label": "SQLite Sync devtools",
|
|
242
|
-
style: dialogStyles,
|
|
243
|
-
onClick: (event) => event.stopPropagation(),
|
|
244
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
245
|
-
style: headerStyles,
|
|
246
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
247
|
-
style: headerLeftStyles,
|
|
248
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
249
|
-
style: headerLogoStyles,
|
|
250
|
-
children: "◈"
|
|
251
|
-
}), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
|
|
252
|
-
style: eyebrowStyles,
|
|
253
|
-
children: "sqlite-sync"
|
|
254
|
-
}), /* @__PURE__ */ jsx("h2", {
|
|
255
|
-
style: titleStyles,
|
|
256
|
-
children: "Devtools"
|
|
257
|
-
})] })]
|
|
258
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
259
|
-
style: headerRightStyles,
|
|
260
|
-
children: [
|
|
261
|
-
instances.length > 0 && /* @__PURE__ */ jsxs("label", {
|
|
262
|
-
style: instancePickerLabelStyles,
|
|
263
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
264
|
-
style: instancePickerTextStyles,
|
|
265
|
-
children: "DB"
|
|
266
|
-
}), /* @__PURE__ */ jsx("select", {
|
|
267
|
-
value: selectedInstanceId,
|
|
268
|
-
onChange: (event) => setSelectedInstanceId(event.target.value),
|
|
269
|
-
style: instancePickerSelectStyles,
|
|
270
|
-
children: instances.map((instance) => /* @__PURE__ */ jsx("option", {
|
|
271
|
-
value: instance.instanceId,
|
|
272
|
-
children: formatInstanceLabel(instance.dbId, instance.instanceId, dbIdCounts.get(instance.dbId) ?? 0)
|
|
273
|
-
}, instance.instanceId))
|
|
274
|
-
})]
|
|
275
|
-
}),
|
|
276
|
-
/* @__PURE__ */ jsxs("span", {
|
|
277
|
-
style: instanceCountBadgeStyles,
|
|
278
|
-
children: [
|
|
279
|
-
instances.length,
|
|
280
|
-
" instance",
|
|
281
|
-
instances.length !== 1 ? "s" : ""
|
|
282
|
-
]
|
|
283
|
-
}),
|
|
284
|
-
/* @__PURE__ */ jsx("button", {
|
|
285
|
-
type: "button",
|
|
286
|
-
style: closeButtonStyles,
|
|
287
|
-
onClick: () => setIsOpen(false),
|
|
288
|
-
"aria-label": "Close",
|
|
289
|
-
children: "✕"
|
|
290
|
-
})
|
|
291
|
-
]
|
|
287
|
+
return /* @__PURE__ */ jsxs(ShadowRoot, {
|
|
288
|
+
className,
|
|
289
|
+
children: [hidden ? null : /* @__PURE__ */ jsx("div", {
|
|
290
|
+
className: "floatingRoot",
|
|
291
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
292
|
+
ref: buttonRef,
|
|
293
|
+
type: "button",
|
|
294
|
+
className: "triggerButton",
|
|
295
|
+
style: positionStyle,
|
|
296
|
+
onClick: () => {
|
|
297
|
+
if (consumeDragClick()) return;
|
|
298
|
+
setIsOpen(true);
|
|
299
|
+
},
|
|
300
|
+
title: `SQLite Sync Devtools (${TOGGLE_LAUNCHER_HINT} to hide)`,
|
|
301
|
+
...triggerHandlers,
|
|
302
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
303
|
+
className: "triggerIcon",
|
|
304
|
+
children: "◈"
|
|
305
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
306
|
+
className: "triggerCount",
|
|
307
|
+
children: instances.length
|
|
292
308
|
})]
|
|
293
|
-
})
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
style: sidebarStyles,
|
|
320
|
-
children: [/* @__PURE__ */ jsxs("nav", {
|
|
321
|
-
style: navStyles,
|
|
309
|
+
})
|
|
310
|
+
}), isOpen ? /* @__PURE__ */ jsx("div", {
|
|
311
|
+
className: "overlay",
|
|
312
|
+
onClick: () => setIsOpen(false),
|
|
313
|
+
children: /* @__PURE__ */ jsxs("section", {
|
|
314
|
+
role: "dialog",
|
|
315
|
+
"aria-modal": "true",
|
|
316
|
+
"aria-label": "SQLite Sync devtools",
|
|
317
|
+
className: "dialog",
|
|
318
|
+
onClick: (event) => event.stopPropagation(),
|
|
319
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
320
|
+
className: "header",
|
|
321
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
322
|
+
className: "headerLeft",
|
|
323
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
324
|
+
className: "headerLogo",
|
|
325
|
+
children: "◈"
|
|
326
|
+
}), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
|
|
327
|
+
className: "eyebrow",
|
|
328
|
+
children: "sqlite-sync"
|
|
329
|
+
}), /* @__PURE__ */ jsx("h2", {
|
|
330
|
+
className: "title",
|
|
331
|
+
children: "Devtools"
|
|
332
|
+
})] })]
|
|
333
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
334
|
+
className: "headerRight",
|
|
322
335
|
children: [
|
|
323
|
-
/* @__PURE__ */ jsxs("
|
|
324
|
-
|
|
325
|
-
style: getTabButtonStyles(activeTab === "overview"),
|
|
326
|
-
onClick: () => setActiveTab("overview"),
|
|
336
|
+
instances.length > 0 && /* @__PURE__ */ jsxs("label", {
|
|
337
|
+
className: "instancePickerLabel",
|
|
327
338
|
children: [/* @__PURE__ */ jsx("span", {
|
|
328
|
-
|
|
329
|
-
children: "
|
|
330
|
-
}), "
|
|
339
|
+
className: "instancePickerText",
|
|
340
|
+
children: "DB"
|
|
341
|
+
}), /* @__PURE__ */ jsx("select", {
|
|
342
|
+
value: selectedInstanceId,
|
|
343
|
+
onChange: (event) => setSelectedInstanceId(event.target.value),
|
|
344
|
+
className: "instancePickerSelect",
|
|
345
|
+
children: instances.map((instance) => /* @__PURE__ */ jsx("option", {
|
|
346
|
+
value: instance.instanceId,
|
|
347
|
+
children: formatInstanceLabel(instance.dbId, instance.instanceId, dbIdCounts.get(instance.dbId) ?? 0)
|
|
348
|
+
}, instance.instanceId))
|
|
349
|
+
})]
|
|
331
350
|
}),
|
|
332
|
-
/* @__PURE__ */ jsxs("
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
}), "Schema"]
|
|
340
|
-
}),
|
|
341
|
-
/* @__PURE__ */ jsxs("button", {
|
|
342
|
-
type: "button",
|
|
343
|
-
style: getTabButtonStyles(activeTab === "live-queries"),
|
|
344
|
-
onClick: () => setActiveTab("live-queries"),
|
|
345
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
346
|
-
style: navIconStyles,
|
|
347
|
-
children: "◉"
|
|
348
|
-
}), "Live Queries"]
|
|
351
|
+
/* @__PURE__ */ jsxs("span", {
|
|
352
|
+
className: "instanceCountBadge",
|
|
353
|
+
children: [
|
|
354
|
+
instances.length,
|
|
355
|
+
" instance",
|
|
356
|
+
instances.length !== 1 ? "s" : ""
|
|
357
|
+
]
|
|
349
358
|
}),
|
|
350
|
-
/* @__PURE__ */
|
|
359
|
+
canToggle && /* @__PURE__ */ jsx("button", {
|
|
351
360
|
type: "button",
|
|
352
|
-
|
|
353
|
-
onClick: () =>
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
children: "≡"
|
|
357
|
-
}), "Event Log"]
|
|
361
|
+
className: "hideLauncherButton",
|
|
362
|
+
onClick: () => setHidden(true),
|
|
363
|
+
title: `Hide launcher (${TOGGLE_LAUNCHER_HINT} to show again)`,
|
|
364
|
+
children: "Hide"
|
|
358
365
|
}),
|
|
359
|
-
/* @__PURE__ */
|
|
366
|
+
/* @__PURE__ */ jsx("button", {
|
|
360
367
|
type: "button",
|
|
361
|
-
|
|
362
|
-
onClick: () =>
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
children: "▶"
|
|
366
|
-
}), "Query Runner"]
|
|
367
|
-
})
|
|
368
|
-
]
|
|
369
|
-
}), selectedInstance && /* @__PURE__ */ jsxs("div", {
|
|
370
|
-
style: sidebarInfoStyles,
|
|
371
|
-
children: [
|
|
372
|
-
/* @__PURE__ */ jsx("div", {
|
|
373
|
-
style: sidebarInfoLabelStyles,
|
|
374
|
-
children: "Active instance"
|
|
375
|
-
}),
|
|
376
|
-
/* @__PURE__ */ jsx("div", {
|
|
377
|
-
style: sidebarInfoValueStyles,
|
|
378
|
-
children: formatInstanceLabel(selectedInstance.dbId, selectedInstance.instanceId, dbIdCounts.get(selectedInstance.dbId) ?? 0)
|
|
379
|
-
}),
|
|
380
|
-
/* @__PURE__ */ jsxs("div", {
|
|
381
|
-
style: sidebarInfoSubStyles,
|
|
382
|
-
children: [
|
|
383
|
-
"id: ",
|
|
384
|
-
selectedInstance.instanceId.slice(0, 12),
|
|
385
|
-
"…"
|
|
386
|
-
]
|
|
368
|
+
className: "closeButton",
|
|
369
|
+
onClick: () => setIsOpen(false),
|
|
370
|
+
"aria-label": "Close",
|
|
371
|
+
children: "✕"
|
|
387
372
|
})
|
|
388
373
|
]
|
|
389
374
|
})]
|
|
390
|
-
}), /* @__PURE__ */
|
|
391
|
-
|
|
392
|
-
children:
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
375
|
+
}), instances.length === 0 ? /* @__PURE__ */ jsxs("div", {
|
|
376
|
+
className: "emptyState",
|
|
377
|
+
children: [
|
|
378
|
+
/* @__PURE__ */ jsx("div", {
|
|
379
|
+
className: "emptyStateIcon",
|
|
380
|
+
children: "◈"
|
|
381
|
+
}),
|
|
382
|
+
/* @__PURE__ */ jsx("p", {
|
|
383
|
+
className: "emptyStateText",
|
|
384
|
+
children: "No SQLite Sync database instances registered."
|
|
385
|
+
}),
|
|
386
|
+
/* @__PURE__ */ jsxs("p", {
|
|
387
|
+
className: "emptyStateSubtext",
|
|
388
|
+
children: [
|
|
389
|
+
"Call ",
|
|
390
|
+
/* @__PURE__ */ jsx("code", {
|
|
391
|
+
className: "inlineCode",
|
|
392
|
+
children: "registerDevtools(db)"
|
|
393
|
+
}),
|
|
394
|
+
" in your app to get started."
|
|
395
|
+
]
|
|
396
|
+
})
|
|
397
|
+
]
|
|
398
|
+
}) : /* @__PURE__ */ jsxs("div", {
|
|
399
|
+
className: "contentLayout",
|
|
400
|
+
children: [/* @__PURE__ */ jsxs("aside", {
|
|
401
|
+
className: "sidebar",
|
|
402
|
+
children: [/* @__PURE__ */ jsxs("nav", {
|
|
403
|
+
className: "nav",
|
|
404
|
+
children: [
|
|
405
|
+
/* @__PURE__ */ jsxs("button", {
|
|
406
|
+
type: "button",
|
|
407
|
+
className: "tabButton",
|
|
408
|
+
"data-active": activeTab === "overview" ? "true" : void 0,
|
|
409
|
+
onClick: () => setActiveTab("overview"),
|
|
410
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
411
|
+
className: "navIcon",
|
|
412
|
+
children: "▦"
|
|
413
|
+
}), "Overview"]
|
|
414
|
+
}),
|
|
415
|
+
/* @__PURE__ */ jsxs("button", {
|
|
416
|
+
type: "button",
|
|
417
|
+
className: "tabButton",
|
|
418
|
+
"data-active": activeTab === "schema" ? "true" : void 0,
|
|
419
|
+
onClick: () => setActiveTab("schema"),
|
|
420
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
421
|
+
className: "navIcon",
|
|
422
|
+
children: "⬡"
|
|
423
|
+
}), "Schema"]
|
|
424
|
+
}),
|
|
425
|
+
/* @__PURE__ */ jsxs("button", {
|
|
426
|
+
type: "button",
|
|
427
|
+
className: "tabButton",
|
|
428
|
+
"data-active": activeTab === "live-queries" ? "true" : void 0,
|
|
429
|
+
onClick: () => setActiveTab("live-queries"),
|
|
430
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
431
|
+
className: "navIcon",
|
|
432
|
+
children: "◉"
|
|
433
|
+
}), "Live Queries"]
|
|
434
|
+
}),
|
|
435
|
+
/* @__PURE__ */ jsxs("button", {
|
|
436
|
+
type: "button",
|
|
437
|
+
className: "tabButton",
|
|
438
|
+
"data-active": activeTab === "event-log" ? "true" : void 0,
|
|
439
|
+
onClick: () => setActiveTab("event-log"),
|
|
440
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
441
|
+
className: "navIcon",
|
|
442
|
+
children: "≡"
|
|
443
|
+
}), "Event Log"]
|
|
444
|
+
}),
|
|
445
|
+
/* @__PURE__ */ jsxs("button", {
|
|
446
|
+
type: "button",
|
|
447
|
+
className: "tabButton",
|
|
448
|
+
"data-active": activeTab === "query-runner" ? "true" : void 0,
|
|
449
|
+
onClick: () => setActiveTab("query-runner"),
|
|
450
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
451
|
+
className: "navIcon",
|
|
452
|
+
children: "▶"
|
|
453
|
+
}), "Query Runner"]
|
|
454
|
+
})
|
|
455
|
+
]
|
|
456
|
+
}), selectedInstance && /* @__PURE__ */ jsxs("div", {
|
|
457
|
+
className: "sidebarInfo",
|
|
458
|
+
children: [
|
|
459
|
+
/* @__PURE__ */ jsx("div", {
|
|
460
|
+
className: "sidebarInfoLabel",
|
|
461
|
+
children: "Active instance"
|
|
462
|
+
}),
|
|
463
|
+
/* @__PURE__ */ jsx("div", {
|
|
464
|
+
className: "sidebarInfoValue",
|
|
465
|
+
children: formatInstanceLabel(selectedInstance.dbId, selectedInstance.instanceId, dbIdCounts.get(selectedInstance.dbId) ?? 0)
|
|
466
|
+
}),
|
|
467
|
+
/* @__PURE__ */ jsxs("div", {
|
|
468
|
+
className: "sidebarInfoSub",
|
|
469
|
+
children: [
|
|
470
|
+
"id: ",
|
|
471
|
+
selectedInstance.instanceId.slice(0, 12),
|
|
472
|
+
"…"
|
|
473
|
+
]
|
|
474
|
+
})
|
|
475
|
+
]
|
|
476
|
+
})]
|
|
477
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
478
|
+
className: "mainPane",
|
|
479
|
+
children: activeTab === "overview" ? /* @__PURE__ */ jsx(OverviewTab, {
|
|
480
|
+
selectedInstance,
|
|
481
|
+
dbIdCounts
|
|
482
|
+
}) : activeTab === "schema" ? /* @__PURE__ */ jsx(SchemaTab, { selectedInstance }) : activeTab === "live-queries" ? /* @__PURE__ */ jsx(LiveQueriesTab, { selectedInstance }) : activeTab === "event-log" ? /* @__PURE__ */ jsx(EventLogTab, { selectedInstance }) : /* @__PURE__ */ jsx(QueryRunnerTab, {
|
|
483
|
+
selectedInstance,
|
|
484
|
+
queryTarget,
|
|
485
|
+
setQueryTarget,
|
|
486
|
+
query,
|
|
487
|
+
setQuery,
|
|
488
|
+
queryState,
|
|
489
|
+
canRunQuery,
|
|
490
|
+
runQuery
|
|
491
|
+
})
|
|
492
|
+
})]
|
|
405
493
|
})]
|
|
406
|
-
})
|
|
407
|
-
})
|
|
408
|
-
})
|
|
494
|
+
})
|
|
495
|
+
}) : null]
|
|
496
|
+
});
|
|
409
497
|
}
|
|
410
498
|
const EVENT_HLC_ACCUMULATOR_QUERY = `SELECT value FROM "worker"."kv" WHERE key = 'crdt.consistency.event_hlc_sum.v2'`;
|
|
499
|
+
const EVENT_STATUS_COUNTS_QUERY = `SELECT status, COUNT(*) AS count FROM "worker"."crdt_events" GROUP BY status`;
|
|
500
|
+
const MEMORY_DB_SIZE_QUERY = "SELECT (SELECT page_count FROM pragma_page_count()) * (SELECT page_size FROM pragma_page_size()) AS bytes";
|
|
501
|
+
const WORKER_DB_SIZE_QUERY = `SELECT
|
|
502
|
+
(SELECT page_count FROM pragma_page_count('main')) * (SELECT page_size FROM pragma_page_size('main'))
|
|
503
|
+
+ (SELECT page_count FROM pragma_page_count('worker')) * (SELECT page_size FROM pragma_page_size('worker'))
|
|
504
|
+
AS bytes`;
|
|
505
|
+
const EVENT_STATUS_META = {
|
|
506
|
+
pending: {
|
|
507
|
+
label: "Pending",
|
|
508
|
+
tone: "amber"
|
|
509
|
+
},
|
|
510
|
+
applied: {
|
|
511
|
+
label: "Applied",
|
|
512
|
+
tone: "success"
|
|
513
|
+
},
|
|
514
|
+
failed: {
|
|
515
|
+
label: "Failed",
|
|
516
|
+
tone: "error"
|
|
517
|
+
},
|
|
518
|
+
deduped: {
|
|
519
|
+
label: "Deduped",
|
|
520
|
+
tone: "muted"
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
function isEventStatus(value) {
|
|
524
|
+
return value === "pending" || value === "applied" || value === "failed" || value === "deduped";
|
|
525
|
+
}
|
|
526
|
+
function emptyEventStatusCounts() {
|
|
527
|
+
return {
|
|
528
|
+
total: 0,
|
|
529
|
+
pending: 0,
|
|
530
|
+
applied: 0,
|
|
531
|
+
failed: 0,
|
|
532
|
+
deduped: 0
|
|
533
|
+
};
|
|
534
|
+
}
|
|
535
|
+
function parseEventStatusCounts(rows) {
|
|
536
|
+
const counts = emptyEventStatusCounts();
|
|
537
|
+
for (const row of rows) {
|
|
538
|
+
if (typeof row !== "object" || row === null || !("status" in row) || !("count" in row)) continue;
|
|
539
|
+
const { status, count } = row;
|
|
540
|
+
if (!isEventStatus(status)) continue;
|
|
541
|
+
const n = typeof count === "number" ? count : Number(count);
|
|
542
|
+
if (!Number.isFinite(n)) continue;
|
|
543
|
+
counts[status] = n;
|
|
544
|
+
counts.total += n;
|
|
545
|
+
}
|
|
546
|
+
return counts;
|
|
547
|
+
}
|
|
548
|
+
function readCount(rows) {
|
|
549
|
+
const row = rows[0];
|
|
550
|
+
if (typeof row !== "object" || row === null || !("count" in row)) return 0;
|
|
551
|
+
const n = typeof row.count === "number" ? row.count : Number(row.count);
|
|
552
|
+
return Number.isFinite(n) ? n : 0;
|
|
553
|
+
}
|
|
554
|
+
function readBytes(rows) {
|
|
555
|
+
const row = rows[0];
|
|
556
|
+
if (typeof row !== "object" || row === null || !("bytes" in row)) return null;
|
|
557
|
+
const n = typeof row.bytes === "number" ? row.bytes : Number(row.bytes);
|
|
558
|
+
return Number.isFinite(n) ? n : null;
|
|
559
|
+
}
|
|
560
|
+
function formatByteSize(bytes) {
|
|
561
|
+
const exact = `${bytes.toLocaleString("en-US")} B`;
|
|
562
|
+
if (bytes < 1024) return {
|
|
563
|
+
label: exact,
|
|
564
|
+
exact
|
|
565
|
+
};
|
|
566
|
+
const units = [
|
|
567
|
+
"KB",
|
|
568
|
+
"MB",
|
|
569
|
+
"GB",
|
|
570
|
+
"TB"
|
|
571
|
+
];
|
|
572
|
+
let value = bytes / 1024;
|
|
573
|
+
let unitIndex = 0;
|
|
574
|
+
while (value >= 1024 && unitIndex < units.length - 1) {
|
|
575
|
+
value /= 1024;
|
|
576
|
+
unitIndex += 1;
|
|
577
|
+
}
|
|
578
|
+
const decimals = value >= 100 ? 0 : value >= 10 ? 1 : 2;
|
|
579
|
+
return {
|
|
580
|
+
label: `${Number(value.toFixed(decimals))} ${units[unitIndex]}`,
|
|
581
|
+
exact
|
|
582
|
+
};
|
|
583
|
+
}
|
|
411
584
|
function OverviewTab({ selectedInstance, dbIdCounts }) {
|
|
412
585
|
const [eventHlcAccumulator, setEventHlcAccumulator] = useState(null);
|
|
413
586
|
const [accumulatorError, setAccumulatorError] = useState(null);
|
|
414
587
|
const [isAccumulatorLoading, setIsAccumulatorLoading] = useState(false);
|
|
588
|
+
const [eventCounts, setEventCounts] = useState(null);
|
|
589
|
+
const [eventCountsError, setEventCountsError] = useState(null);
|
|
590
|
+
const [isEventCountsLoading, setIsEventCountsLoading] = useState(false);
|
|
591
|
+
const [memoryBytes, setMemoryBytes] = useState(null);
|
|
592
|
+
const [memorySizeError, setMemorySizeError] = useState(null);
|
|
593
|
+
const [workerBytes, setWorkerBytes] = useState(null);
|
|
594
|
+
const [workerSizeError, setWorkerSizeError] = useState(null);
|
|
595
|
+
const [isSizeLoading, setIsSizeLoading] = useState(false);
|
|
415
596
|
const refreshEventHlcAccumulator = useCallback(async () => {
|
|
416
597
|
if (!selectedInstance) return;
|
|
417
598
|
setIsAccumulatorLoading(true);
|
|
@@ -421,7 +602,8 @@ function OverviewTab({ selectedInstance, dbIdCounts }) {
|
|
|
421
602
|
sql: EVENT_HLC_ACCUMULATOR_QUERY,
|
|
422
603
|
parameters: []
|
|
423
604
|
})).rows[0];
|
|
424
|
-
|
|
605
|
+
const value = typeof row === "object" && row !== null && "value" in row && typeof row.value === "string" ? row.value : "";
|
|
606
|
+
setEventHlcAccumulator(value);
|
|
425
607
|
} catch (error) {
|
|
426
608
|
setAccumulatorError(error instanceof Error ? error.message : String(error));
|
|
427
609
|
setEventHlcAccumulator(null);
|
|
@@ -429,135 +611,201 @@ function OverviewTab({ selectedInstance, dbIdCounts }) {
|
|
|
429
611
|
setIsAccumulatorLoading(false);
|
|
430
612
|
}
|
|
431
613
|
}, [selectedInstance]);
|
|
614
|
+
const refreshEventCounts = useCallback(async () => {
|
|
615
|
+
if (!selectedInstance) return;
|
|
616
|
+
setIsEventCountsLoading(true);
|
|
617
|
+
setEventCountsError(null);
|
|
618
|
+
try {
|
|
619
|
+
const result = await selectedInstance.instance._internal.executeAsync({
|
|
620
|
+
sql: EVENT_STATUS_COUNTS_QUERY,
|
|
621
|
+
parameters: []
|
|
622
|
+
});
|
|
623
|
+
setEventCounts(parseEventStatusCounts(result.rows));
|
|
624
|
+
} catch (error) {
|
|
625
|
+
setEventCountsError(error instanceof Error ? error.message : String(error));
|
|
626
|
+
setEventCounts(null);
|
|
627
|
+
} finally {
|
|
628
|
+
setIsEventCountsLoading(false);
|
|
629
|
+
}
|
|
630
|
+
}, [selectedInstance]);
|
|
631
|
+
const refreshDbSizes = useCallback(async () => {
|
|
632
|
+
if (!selectedInstance) return;
|
|
633
|
+
setIsSizeLoading(true);
|
|
634
|
+
setMemorySizeError(null);
|
|
635
|
+
setWorkerSizeError(null);
|
|
636
|
+
const memoryResult = Promise.resolve().then(() => selectedInstance.instance.db.execute(MEMORY_DB_SIZE_QUERY)).then((result) => {
|
|
637
|
+
const bytes = readBytes(result.rows);
|
|
638
|
+
if (bytes === null) throw new Error("Memory DB did not return a size.");
|
|
639
|
+
return bytes;
|
|
640
|
+
});
|
|
641
|
+
const workerResult = selectedInstance.instance._internal.executeAsync({
|
|
642
|
+
sql: WORKER_DB_SIZE_QUERY,
|
|
643
|
+
parameters: []
|
|
644
|
+
}).then((result) => {
|
|
645
|
+
const bytes = readBytes(result.rows);
|
|
646
|
+
if (bytes === null) throw new Error("Worker DB did not return a size.");
|
|
647
|
+
return bytes;
|
|
648
|
+
});
|
|
649
|
+
const [memorySettled, workerSettled] = await Promise.allSettled([memoryResult, workerResult]);
|
|
650
|
+
if (memorySettled.status === "fulfilled") setMemoryBytes(memorySettled.value);
|
|
651
|
+
else {
|
|
652
|
+
setMemoryBytes(null);
|
|
653
|
+
setMemorySizeError(memorySettled.reason instanceof Error ? memorySettled.reason.message : String(memorySettled.reason));
|
|
654
|
+
}
|
|
655
|
+
if (workerSettled.status === "fulfilled") setWorkerBytes(workerSettled.value);
|
|
656
|
+
else {
|
|
657
|
+
setWorkerBytes(null);
|
|
658
|
+
setWorkerSizeError(workerSettled.reason instanceof Error ? workerSettled.reason.message : String(workerSettled.reason));
|
|
659
|
+
}
|
|
660
|
+
setIsSizeLoading(false);
|
|
661
|
+
}, [selectedInstance]);
|
|
432
662
|
useEffect(() => {
|
|
433
663
|
setEventHlcAccumulator(null);
|
|
434
664
|
setAccumulatorError(null);
|
|
665
|
+
setEventCounts(null);
|
|
666
|
+
setEventCountsError(null);
|
|
667
|
+
setMemoryBytes(null);
|
|
668
|
+
setMemorySizeError(null);
|
|
669
|
+
setWorkerBytes(null);
|
|
670
|
+
setWorkerSizeError(null);
|
|
435
671
|
refreshEventHlcAccumulator();
|
|
436
|
-
|
|
672
|
+
refreshEventCounts();
|
|
673
|
+
refreshDbSizes();
|
|
674
|
+
}, [
|
|
675
|
+
refreshEventHlcAccumulator,
|
|
676
|
+
refreshEventCounts,
|
|
677
|
+
refreshDbSizes
|
|
678
|
+
]);
|
|
437
679
|
if (!selectedInstance) return null;
|
|
438
680
|
const label = formatInstanceLabel(selectedInstance.dbId, selectedInstance.instanceId, dbIdCounts.get(selectedInstance.dbId) ?? 0);
|
|
439
|
-
const crdtTables = selectedInstance.instance._internal.crdtTableNames;
|
|
440
681
|
return /* @__PURE__ */ jsxs("div", {
|
|
441
|
-
|
|
682
|
+
className: "overviewLayout",
|
|
442
683
|
children: [
|
|
443
684
|
/* @__PURE__ */ jsxs("div", {
|
|
444
|
-
|
|
685
|
+
className: "overviewCardsRow",
|
|
445
686
|
children: [
|
|
446
687
|
/* @__PURE__ */ jsxs("div", {
|
|
447
|
-
|
|
688
|
+
className: "overviewCard",
|
|
448
689
|
children: [/* @__PURE__ */ jsx("div", {
|
|
449
|
-
|
|
690
|
+
className: "overviewCardLabel",
|
|
450
691
|
children: "Database"
|
|
451
692
|
}), /* @__PURE__ */ jsx("div", {
|
|
452
|
-
|
|
693
|
+
className: "overviewCardValue",
|
|
453
694
|
children: label
|
|
454
695
|
})]
|
|
455
696
|
}),
|
|
456
697
|
/* @__PURE__ */ jsxs("div", {
|
|
457
|
-
|
|
698
|
+
className: "overviewCard",
|
|
458
699
|
children: [/* @__PURE__ */ jsx("div", {
|
|
459
|
-
|
|
700
|
+
className: "overviewCardLabel",
|
|
460
701
|
children: "Instance ID"
|
|
461
702
|
}), /* @__PURE__ */ jsxs("div", {
|
|
462
|
-
|
|
463
|
-
...overviewCardValueStyles,
|
|
464
|
-
fontFamily: "ui-monospace, monospace",
|
|
465
|
-
fontSize: "0.78rem"
|
|
466
|
-
},
|
|
703
|
+
className: "overviewCardValue mono sm",
|
|
467
704
|
children: [selectedInstance.instanceId.slice(0, 16), "…"]
|
|
468
705
|
})]
|
|
469
706
|
}),
|
|
707
|
+
/* @__PURE__ */ jsx(DbSizeCard, {
|
|
708
|
+
label: "Memory DB",
|
|
709
|
+
bytes: memoryBytes,
|
|
710
|
+
error: memorySizeError,
|
|
711
|
+
loading: isSizeLoading
|
|
712
|
+
}),
|
|
713
|
+
/* @__PURE__ */ jsx(DbSizeCard, {
|
|
714
|
+
label: "Worker DB",
|
|
715
|
+
bytes: workerBytes,
|
|
716
|
+
error: workerSizeError,
|
|
717
|
+
loading: isSizeLoading
|
|
718
|
+
}),
|
|
470
719
|
/* @__PURE__ */ jsxs("div", {
|
|
471
|
-
|
|
720
|
+
className: "overviewCard",
|
|
472
721
|
children: [/* @__PURE__ */ jsx("div", {
|
|
473
|
-
|
|
474
|
-
children: "CRDT
|
|
722
|
+
className: "overviewCardLabel",
|
|
723
|
+
children: "CRDT Events"
|
|
475
724
|
}), /* @__PURE__ */ jsx("div", {
|
|
476
|
-
|
|
477
|
-
children:
|
|
725
|
+
className: "overviewCardValue",
|
|
726
|
+
children: eventCountsError ? "—" : isEventCountsLoading && eventCounts === null ? "…" : eventCounts?.total ?? 0
|
|
478
727
|
})]
|
|
479
728
|
})
|
|
480
729
|
]
|
|
481
730
|
}),
|
|
482
731
|
/* @__PURE__ */ jsxs("div", {
|
|
483
|
-
|
|
484
|
-
children: [
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
children:
|
|
732
|
+
className: "overviewSection",
|
|
733
|
+
children: [
|
|
734
|
+
/* @__PURE__ */ jsxs("div", {
|
|
735
|
+
className: "overviewSectionHeader",
|
|
736
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
737
|
+
className: "overviewSectionTitle",
|
|
738
|
+
children: "CRDT events"
|
|
739
|
+
}), /* @__PURE__ */ jsxs("button", {
|
|
740
|
+
type: "button",
|
|
741
|
+
className: "refreshButton",
|
|
742
|
+
disabled: isEventCountsLoading || isSizeLoading,
|
|
743
|
+
title: "Refresh event counts and DB sizes",
|
|
744
|
+
onClick: () => {
|
|
745
|
+
refreshEventCounts();
|
|
746
|
+
refreshDbSizes();
|
|
747
|
+
},
|
|
748
|
+
children: [isEventCountsLoading || isSizeLoading ? "…" : "↻", " Refresh"]
|
|
500
749
|
})]
|
|
501
|
-
},
|
|
502
|
-
|
|
750
|
+
}),
|
|
751
|
+
eventCountsError ? /* @__PURE__ */ jsx("div", {
|
|
752
|
+
className: "overviewAccumulatorError",
|
|
753
|
+
children: eventCountsError
|
|
754
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
755
|
+
className: "eventCountGrid",
|
|
756
|
+
children: [
|
|
757
|
+
"pending",
|
|
758
|
+
"applied",
|
|
759
|
+
"failed",
|
|
760
|
+
"deduped"
|
|
761
|
+
].map((status) => {
|
|
762
|
+
const item = EVENT_STATUS_META[status];
|
|
763
|
+
const value = eventCounts?.[status] ?? 0;
|
|
764
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
765
|
+
className: "eventCountCard",
|
|
766
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
767
|
+
className: "eventCountValue",
|
|
768
|
+
"data-tone": item.tone,
|
|
769
|
+
"data-emphasize": value > 0 ? "true" : void 0,
|
|
770
|
+
children: isEventCountsLoading && eventCounts === null ? "…" : value
|
|
771
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
772
|
+
className: "overviewCardLabel",
|
|
773
|
+
children: item.label
|
|
774
|
+
})]
|
|
775
|
+
}, status);
|
|
776
|
+
})
|
|
777
|
+
}),
|
|
778
|
+
/* @__PURE__ */ jsx("div", {
|
|
779
|
+
className: "overviewEmpty",
|
|
780
|
+
children: "Counts are remaining worker log rows after GC, not lifetime history."
|
|
781
|
+
})
|
|
782
|
+
]
|
|
503
783
|
}),
|
|
504
784
|
/* @__PURE__ */ jsxs("div", {
|
|
505
|
-
|
|
785
|
+
className: "overviewSection",
|
|
506
786
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
507
|
-
|
|
787
|
+
className: "overviewSectionHeader",
|
|
508
788
|
children: [/* @__PURE__ */ jsx("div", {
|
|
509
|
-
|
|
789
|
+
className: "overviewSectionTitle",
|
|
510
790
|
children: "Event HLC accumulator"
|
|
511
791
|
}), /* @__PURE__ */ jsxs("button", {
|
|
512
792
|
type: "button",
|
|
513
|
-
|
|
793
|
+
className: "refreshButton",
|
|
514
794
|
disabled: isAccumulatorLoading,
|
|
515
795
|
onClick: () => void refreshEventHlcAccumulator(),
|
|
516
796
|
children: [isAccumulatorLoading ? "…" : "↻", " Refresh"]
|
|
517
797
|
})]
|
|
518
798
|
}), /* @__PURE__ */ jsx("div", {
|
|
519
|
-
|
|
799
|
+
className: "overviewAccumulatorValue",
|
|
520
800
|
children: accumulatorError ? /* @__PURE__ */ jsx("span", {
|
|
521
|
-
|
|
801
|
+
className: "overviewAccumulatorError",
|
|
522
802
|
children: accumulatorError
|
|
523
803
|
}) : isAccumulatorLoading && eventHlcAccumulator === null ? "Loading…" : eventHlcAccumulator === "" ? /* @__PURE__ */ jsx("span", {
|
|
524
|
-
|
|
804
|
+
className: "overviewAccumulatorEmpty",
|
|
525
805
|
children: "(empty)"
|
|
526
806
|
}) : eventHlcAccumulator
|
|
527
807
|
})]
|
|
528
808
|
}),
|
|
529
|
-
/* @__PURE__ */ jsxs("div", {
|
|
530
|
-
style: overviewSectionStyles,
|
|
531
|
-
children: [
|
|
532
|
-
/* @__PURE__ */ jsx("div", {
|
|
533
|
-
style: overviewSectionTitleStyles,
|
|
534
|
-
children: "Write Permissions"
|
|
535
|
-
}),
|
|
536
|
-
/* @__PURE__ */ jsxs("div", {
|
|
537
|
-
style: permissionRowStyles,
|
|
538
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
539
|
-
style: permissionIconStyles,
|
|
540
|
-
children: "✓"
|
|
541
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
542
|
-
style: permissionTextStyles,
|
|
543
|
-
children: "Memory DB — CRDT tables only"
|
|
544
|
-
})]
|
|
545
|
-
}),
|
|
546
|
-
/* @__PURE__ */ jsxs("div", {
|
|
547
|
-
style: permissionRowStyles,
|
|
548
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
549
|
-
style: {
|
|
550
|
-
...permissionIconStyles,
|
|
551
|
-
color: "#f59e0b"
|
|
552
|
-
},
|
|
553
|
-
children: "⊘"
|
|
554
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
555
|
-
style: permissionTextStyles,
|
|
556
|
-
children: "Worker DB — read-only (SELECT, PRAGMA, EXPLAIN)"
|
|
557
|
-
})]
|
|
558
|
-
})
|
|
559
|
-
]
|
|
560
|
-
}),
|
|
561
809
|
/* @__PURE__ */ jsx(DataSection, {
|
|
562
810
|
dbId: selectedInstance.dbId,
|
|
563
811
|
instance: selectedInstance.instance
|
|
@@ -569,6 +817,38 @@ function OverviewTab({ selectedInstance, dbIdCounts }) {
|
|
|
569
817
|
]
|
|
570
818
|
});
|
|
571
819
|
}
|
|
820
|
+
function DbSizeCard({ label, bytes, error, loading }) {
|
|
821
|
+
let value = "…";
|
|
822
|
+
let sub;
|
|
823
|
+
let title;
|
|
824
|
+
if (error) {
|
|
825
|
+
value = "—";
|
|
826
|
+
title = error;
|
|
827
|
+
} else if (bytes !== null) {
|
|
828
|
+
const formatted = formatByteSize(bytes);
|
|
829
|
+
value = formatted.label;
|
|
830
|
+
title = formatted.exact;
|
|
831
|
+
sub = formatted.label === formatted.exact ? void 0 : formatted.exact;
|
|
832
|
+
} else if (!loading) value = "—";
|
|
833
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
834
|
+
className: "overviewCard",
|
|
835
|
+
title,
|
|
836
|
+
children: [
|
|
837
|
+
/* @__PURE__ */ jsx("div", {
|
|
838
|
+
className: "overviewCardLabel",
|
|
839
|
+
children: label
|
|
840
|
+
}),
|
|
841
|
+
/* @__PURE__ */ jsx("div", {
|
|
842
|
+
className: "overviewCardValue mono",
|
|
843
|
+
children: value
|
|
844
|
+
}),
|
|
845
|
+
sub ? /* @__PURE__ */ jsx("div", {
|
|
846
|
+
className: "overviewCardSub",
|
|
847
|
+
children: sub
|
|
848
|
+
}) : null
|
|
849
|
+
]
|
|
850
|
+
});
|
|
851
|
+
}
|
|
572
852
|
function DataSection({ dbId, instance }) {
|
|
573
853
|
const fileInputRef = useRef(null);
|
|
574
854
|
const [isImporting, setIsImporting] = useState(false);
|
|
@@ -616,28 +896,28 @@ function DataSection({ dbId, instance }) {
|
|
|
616
896
|
}
|
|
617
897
|
};
|
|
618
898
|
return /* @__PURE__ */ jsxs("div", {
|
|
619
|
-
|
|
899
|
+
className: "overviewSection",
|
|
620
900
|
children: [
|
|
621
901
|
/* @__PURE__ */ jsx("div", {
|
|
622
|
-
|
|
902
|
+
className: "overviewSectionTitle",
|
|
623
903
|
children: "Backup & Restore"
|
|
624
904
|
}),
|
|
625
905
|
/* @__PURE__ */ jsx("div", {
|
|
626
|
-
|
|
906
|
+
className: "dangerZoneDesc",
|
|
627
907
|
children: "Export the active rows of every CRDT table as JSON, or import a dump to seed/restore. Import overwrites rows with matching ids and is propagated to the server."
|
|
628
908
|
}),
|
|
629
909
|
/* @__PURE__ */ jsxs("div", {
|
|
630
|
-
|
|
910
|
+
className: "dataActions",
|
|
631
911
|
children: [
|
|
632
912
|
/* @__PURE__ */ jsx("button", {
|
|
633
913
|
type: "button",
|
|
634
|
-
|
|
914
|
+
className: "dataButton",
|
|
635
915
|
onClick: handleExport,
|
|
636
916
|
children: "↓ Export JSON"
|
|
637
917
|
}),
|
|
638
918
|
/* @__PURE__ */ jsx("button", {
|
|
639
919
|
type: "button",
|
|
640
|
-
|
|
920
|
+
className: "dataButton",
|
|
641
921
|
disabled: isImporting,
|
|
642
922
|
onClick: () => fileInputRef.current?.click(),
|
|
643
923
|
children: isImporting ? "Importing…" : "↑ Import JSON"
|
|
@@ -646,7 +926,7 @@ function DataSection({ dbId, instance }) {
|
|
|
646
926
|
ref: fileInputRef,
|
|
647
927
|
type: "file",
|
|
648
928
|
accept: "application/json,.json",
|
|
649
|
-
|
|
929
|
+
className: "hiddenInput",
|
|
650
930
|
onChange: (event) => {
|
|
651
931
|
const file = event.target.files?.[0];
|
|
652
932
|
event.target.value = "";
|
|
@@ -656,7 +936,7 @@ function DataSection({ dbId, instance }) {
|
|
|
656
936
|
]
|
|
657
937
|
}),
|
|
658
938
|
status && /* @__PURE__ */ jsx("div", {
|
|
659
|
-
|
|
939
|
+
className: status.kind === "error" ? "dataStatusError" : "dataStatusSuccess",
|
|
660
940
|
children: status.message
|
|
661
941
|
})
|
|
662
942
|
]
|
|
@@ -670,164 +950,209 @@ function ResetSection({ dbId, instance }) {
|
|
|
670
950
|
instance.requestReload({ clean: true });
|
|
671
951
|
};
|
|
672
952
|
return /* @__PURE__ */ jsxs("div", {
|
|
673
|
-
|
|
953
|
+
className: "dangerZone",
|
|
674
954
|
children: [/* @__PURE__ */ jsx("div", {
|
|
675
|
-
|
|
955
|
+
className: "dangerZoneTitle",
|
|
676
956
|
children: "Danger Zone"
|
|
677
957
|
}), /* @__PURE__ */ jsxs("div", {
|
|
678
|
-
|
|
958
|
+
className: "dangerZoneRow",
|
|
679
959
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
680
|
-
|
|
960
|
+
className: "dangerZoneDesc",
|
|
681
961
|
children: [
|
|
682
962
|
"Requests a clean reload, so ",
|
|
683
963
|
/* @__PURE__ */ jsx("code", {
|
|
684
|
-
|
|
964
|
+
className: "inlineCode",
|
|
685
965
|
children: dbId
|
|
686
966
|
}),
|
|
687
967
|
" is wiped on next load via",
|
|
688
968
|
" ",
|
|
689
969
|
/* @__PURE__ */ jsx("code", {
|
|
690
|
-
|
|
970
|
+
className: "inlineCode",
|
|
691
971
|
children: "clearOnInit"
|
|
692
972
|
}),
|
|
693
973
|
", then reloads all tabs."
|
|
694
974
|
]
|
|
695
975
|
}), confirming ? /* @__PURE__ */ jsxs("div", {
|
|
696
|
-
|
|
976
|
+
className: "dangerZoneActions",
|
|
697
977
|
children: [/* @__PURE__ */ jsx("button", {
|
|
698
978
|
type: "button",
|
|
699
|
-
|
|
979
|
+
className: "resetCancelButton",
|
|
700
980
|
disabled: isResetting,
|
|
701
981
|
onClick: () => setConfirming(false),
|
|
702
982
|
children: "Cancel"
|
|
703
983
|
}), /* @__PURE__ */ jsx("button", {
|
|
704
984
|
type: "button",
|
|
705
|
-
|
|
985
|
+
className: "resetConfirmButton",
|
|
706
986
|
disabled: isResetting,
|
|
707
987
|
onClick: handleReset,
|
|
708
988
|
children: isResetting ? "Resetting…" : "Confirm reset"
|
|
709
989
|
})]
|
|
710
990
|
}) : /* @__PURE__ */ jsx("button", {
|
|
711
991
|
type: "button",
|
|
712
|
-
|
|
992
|
+
className: "resetButton",
|
|
713
993
|
onClick: () => setConfirming(true),
|
|
714
994
|
children: "Reset DB"
|
|
715
995
|
})]
|
|
716
996
|
})]
|
|
717
997
|
});
|
|
718
998
|
}
|
|
999
|
+
const SYSTEM_COLUMNS = /* @__PURE__ */ new Set(["id", "tombstone"]);
|
|
1000
|
+
function formatDefaultValue(value) {
|
|
1001
|
+
if (typeof value === "string") return JSON.stringify(value);
|
|
1002
|
+
if (typeof value === "boolean" || typeof value === "number") return String(value);
|
|
1003
|
+
if (value === null) return "null";
|
|
1004
|
+
return JSON.stringify(value);
|
|
1005
|
+
}
|
|
719
1006
|
function SchemaTab({ selectedInstance }) {
|
|
720
1007
|
if (!selectedInstance) return null;
|
|
721
|
-
const {
|
|
722
|
-
const
|
|
723
|
-
return /* @__PURE__ */
|
|
724
|
-
|
|
725
|
-
children:
|
|
726
|
-
|
|
727
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
728
|
-
style: schemaSectionHeaderStyles,
|
|
729
|
-
children: [/* @__PURE__ */ jsx("div", {
|
|
730
|
-
style: schemaSectionTitleStyles,
|
|
731
|
-
children: "CRDT Tables"
|
|
732
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
733
|
-
style: schemaBadgeStyles,
|
|
734
|
-
children: crdtTablesConfig.length
|
|
735
|
-
})]
|
|
736
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
737
|
-
style: schemaTableGridStyles,
|
|
738
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
739
|
-
style: schemaTableHeaderRowStyles,
|
|
740
|
-
children: [
|
|
741
|
-
/* @__PURE__ */ jsx("div", {
|
|
742
|
-
style: schemaColHeaderStyles,
|
|
743
|
-
children: "Base Table"
|
|
744
|
-
}),
|
|
745
|
-
/* @__PURE__ */ jsx("div", {
|
|
746
|
-
style: schemaColHeaderStyles,
|
|
747
|
-
children: "CRDT Table"
|
|
748
|
-
}),
|
|
749
|
-
/* @__PURE__ */ jsx("div", {
|
|
750
|
-
style: {
|
|
751
|
-
...schemaColHeaderStyles,
|
|
752
|
-
textAlign: "center"
|
|
753
|
-
},
|
|
754
|
-
children: "Status"
|
|
755
|
-
})
|
|
756
|
-
]
|
|
757
|
-
}), crdtTablesConfig.map((table) => /* @__PURE__ */ jsxs("div", {
|
|
758
|
-
style: schemaTableRowStyles,
|
|
759
|
-
children: [
|
|
760
|
-
/* @__PURE__ */ jsxs("div", {
|
|
761
|
-
style: schemaTableNameStyles,
|
|
762
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
763
|
-
style: schemaTableIconStyles,
|
|
764
|
-
children: "▦"
|
|
765
|
-
}), table.baseTableName]
|
|
766
|
-
}),
|
|
767
|
-
/* @__PURE__ */ jsx("div", {
|
|
768
|
-
style: schemaCrdtNameStyles,
|
|
769
|
-
children: table.crdtTableName
|
|
770
|
-
}),
|
|
771
|
-
/* @__PURE__ */ jsx("div", {
|
|
772
|
-
style: schemaStatusCellStyles,
|
|
773
|
-
children: /* @__PURE__ */ jsx("span", {
|
|
774
|
-
style: schemaActiveTagStyles,
|
|
775
|
-
children: "active"
|
|
776
|
-
})
|
|
777
|
-
})
|
|
778
|
-
]
|
|
779
|
-
}, table.crdtTableName))]
|
|
780
|
-
})]
|
|
781
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
782
|
-
style: schemaSectionStyles,
|
|
1008
|
+
const { tables, schemaVersion } = selectedInstance.instance._internal;
|
|
1009
|
+
const tableEntries = Object.entries(tables);
|
|
1010
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1011
|
+
className: "schemaLayout",
|
|
1012
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
1013
|
+
className: "schemaSection",
|
|
783
1014
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
784
|
-
|
|
785
|
-
children: [
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
children:
|
|
793
|
-
}),
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
}), migrationVersions.length === 0 ? /* @__PURE__ */ jsx("div", {
|
|
804
|
-
style: schemaEmptyStyles,
|
|
805
|
-
children: "No migrations defined."
|
|
1015
|
+
className: "schemaSectionHeader",
|
|
1016
|
+
children: [
|
|
1017
|
+
/* @__PURE__ */ jsx("div", {
|
|
1018
|
+
className: "schemaSectionTitle",
|
|
1019
|
+
children: "Tables"
|
|
1020
|
+
}),
|
|
1021
|
+
/* @__PURE__ */ jsx("span", {
|
|
1022
|
+
className: "schemaBadge",
|
|
1023
|
+
children: tableEntries.length
|
|
1024
|
+
}),
|
|
1025
|
+
/* @__PURE__ */ jsxs("span", {
|
|
1026
|
+
className: "schemaVersionChip mlAuto",
|
|
1027
|
+
title: "Latest applied migration version",
|
|
1028
|
+
children: ["applied v", schemaVersion]
|
|
1029
|
+
})
|
|
1030
|
+
]
|
|
1031
|
+
}), tableEntries.length === 0 ? /* @__PURE__ */ jsx("div", {
|
|
1032
|
+
className: "schemaEmpty",
|
|
1033
|
+
children: "No tables declared on this schema."
|
|
806
1034
|
}) : /* @__PURE__ */ jsx("div", {
|
|
807
|
-
|
|
808
|
-
children:
|
|
809
|
-
const
|
|
810
|
-
const
|
|
1035
|
+
className: "schemaTableList",
|
|
1036
|
+
children: tableEntries.map(([crdtTableName, table]) => {
|
|
1037
|
+
const baseTableName = table.baseName ?? `_${crdtTableName}`;
|
|
1038
|
+
const columns = Object.entries(table.columns);
|
|
811
1039
|
return /* @__PURE__ */ jsxs("div", {
|
|
812
|
-
|
|
813
|
-
children: [
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
1040
|
+
className: "schemaTableCard",
|
|
1041
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
1042
|
+
className: "schemaTableCardHeader",
|
|
1043
|
+
children: [
|
|
1044
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1045
|
+
className: "schemaTableCardTitleRow",
|
|
1046
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
1047
|
+
className: "schemaTableCardName",
|
|
1048
|
+
children: crdtTableName
|
|
1049
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
1050
|
+
className: "schemaBadge",
|
|
1051
|
+
children: columns.length
|
|
1052
|
+
})]
|
|
1053
|
+
}),
|
|
1054
|
+
table.description ? /* @__PURE__ */ jsx("p", {
|
|
1055
|
+
className: "schemaTableCardDescription",
|
|
1056
|
+
children: table.description
|
|
1057
|
+
}) : null,
|
|
1058
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1059
|
+
className: "schemaTableCardMeta",
|
|
1060
|
+
children: [
|
|
1061
|
+
/* @__PURE__ */ jsx("span", {
|
|
1062
|
+
className: "schemaPolicyChip",
|
|
1063
|
+
title: "Base table",
|
|
1064
|
+
children: baseTableName
|
|
1065
|
+
}),
|
|
1066
|
+
/* @__PURE__ */ jsxs("span", {
|
|
1067
|
+
className: "schemaPolicyChip",
|
|
1068
|
+
"data-tone": table.writeOrigin === "server" ? "warn" : void 0,
|
|
1069
|
+
title: "Who may write CRDT events",
|
|
1070
|
+
children: ["writes ", table.writeOrigin]
|
|
1071
|
+
}),
|
|
1072
|
+
/* @__PURE__ */ jsxs("span", {
|
|
1073
|
+
className: "schemaPolicyChip",
|
|
1074
|
+
"data-tone": table.aiAccess === "read-write" ? void 0 : "warn",
|
|
1075
|
+
title: "AI agent access",
|
|
1076
|
+
children: ["ai ", table.aiAccess]
|
|
1077
|
+
}),
|
|
1078
|
+
/* @__PURE__ */ jsxs("span", {
|
|
1079
|
+
className: "schemaPolicyChip",
|
|
1080
|
+
"data-tone": table.exportImport === "ignore" ? "warn" : void 0,
|
|
1081
|
+
title: "Export / import",
|
|
1082
|
+
children: ["export ", table.exportImport]
|
|
1083
|
+
})
|
|
1084
|
+
]
|
|
1085
|
+
})
|
|
1086
|
+
]
|
|
1087
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
1088
|
+
className: "schemaColumnGrid",
|
|
1089
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
1090
|
+
className: "schemaColumnRow schemaColumnHeaderRow",
|
|
1091
|
+
children: [
|
|
1092
|
+
/* @__PURE__ */ jsx("div", {
|
|
1093
|
+
className: "schemaColHeader",
|
|
1094
|
+
children: "Column"
|
|
1095
|
+
}),
|
|
1096
|
+
/* @__PURE__ */ jsx("div", {
|
|
1097
|
+
className: "schemaColHeader",
|
|
1098
|
+
children: "Type"
|
|
1099
|
+
}),
|
|
1100
|
+
/* @__PURE__ */ jsx("div", {
|
|
1101
|
+
className: "schemaColHeader",
|
|
1102
|
+
children: "Flags"
|
|
1103
|
+
}),
|
|
1104
|
+
/* @__PURE__ */ jsx("div", {
|
|
1105
|
+
className: "schemaColHeader",
|
|
1106
|
+
children: "Description"
|
|
1107
|
+
})
|
|
1108
|
+
]
|
|
1109
|
+
}), columns.map(([name, meta]) => /* @__PURE__ */ jsx(SchemaColumnRow, {
|
|
1110
|
+
name,
|
|
1111
|
+
meta
|
|
1112
|
+
}, name))]
|
|
1113
|
+
})]
|
|
1114
|
+
}, crdtTableName);
|
|
828
1115
|
})
|
|
829
1116
|
})]
|
|
830
|
-
})
|
|
1117
|
+
})
|
|
1118
|
+
});
|
|
1119
|
+
}
|
|
1120
|
+
function SchemaColumnRow({ name, meta }) {
|
|
1121
|
+
const flags = [];
|
|
1122
|
+
if (name === "id") flags.push("pk");
|
|
1123
|
+
if (meta.nullable) flags.push("nullable");
|
|
1124
|
+
if (meta.hasDefault) flags.push(`default ${formatDefaultValue(meta.defaultValue)}`);
|
|
1125
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1126
|
+
className: "schemaColumnRow",
|
|
1127
|
+
"data-system": SYSTEM_COLUMNS.has(name) ? "true" : void 0,
|
|
1128
|
+
children: [
|
|
1129
|
+
/* @__PURE__ */ jsx("div", {
|
|
1130
|
+
className: "schemaColumnName",
|
|
1131
|
+
children: name
|
|
1132
|
+
}),
|
|
1133
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1134
|
+
className: "schemaColumnType",
|
|
1135
|
+
children: [
|
|
1136
|
+
/* @__PURE__ */ jsx("span", { children: meta.kind }),
|
|
1137
|
+
meta.kind === "boolean" ? /* @__PURE__ */ jsx("span", {
|
|
1138
|
+
className: "schemaColumnTypeDetail",
|
|
1139
|
+
children: "integer 0/1"
|
|
1140
|
+
}) : null,
|
|
1141
|
+
meta.kind === "enum" && meta.enumValues && meta.enumValues.length > 0 ? /* @__PURE__ */ jsx("span", {
|
|
1142
|
+
className: "schemaColumnTypeDetail",
|
|
1143
|
+
children: meta.enumValues.map((value) => `"${value}"`).join(" | ")
|
|
1144
|
+
}) : null
|
|
1145
|
+
]
|
|
1146
|
+
}),
|
|
1147
|
+
/* @__PURE__ */ jsx("div", {
|
|
1148
|
+
className: "schemaColumnFlags",
|
|
1149
|
+
children: flags.length > 0 ? flags.join(" · ") : "—"
|
|
1150
|
+
}),
|
|
1151
|
+
/* @__PURE__ */ jsx("div", {
|
|
1152
|
+
className: "schemaColumnDescription",
|
|
1153
|
+
children: meta.description ?? ""
|
|
1154
|
+
})
|
|
1155
|
+
]
|
|
831
1156
|
});
|
|
832
1157
|
}
|
|
833
1158
|
function LiveQueriesTab({ selectedInstance }) {
|
|
@@ -844,22 +1169,22 @@ function LiveQueriesTab({ selectedInstance }) {
|
|
|
844
1169
|
}, [refresh]);
|
|
845
1170
|
const totalSubscribers = queries.reduce((total, query) => total + query.subscriberCount, 0);
|
|
846
1171
|
return /* @__PURE__ */ jsx("div", {
|
|
847
|
-
|
|
1172
|
+
className: "schemaLayout",
|
|
848
1173
|
children: /* @__PURE__ */ jsxs("div", {
|
|
849
|
-
|
|
1174
|
+
className: "schemaSection",
|
|
850
1175
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
851
|
-
|
|
1176
|
+
className: "schemaSectionHeader",
|
|
852
1177
|
children: [
|
|
853
1178
|
/* @__PURE__ */ jsx("div", {
|
|
854
|
-
|
|
1179
|
+
className: "schemaSectionTitle",
|
|
855
1180
|
children: "Shared Live Queries"
|
|
856
1181
|
}),
|
|
857
1182
|
/* @__PURE__ */ jsx("span", {
|
|
858
|
-
|
|
1183
|
+
className: "schemaBadge",
|
|
859
1184
|
children: queries.length
|
|
860
1185
|
}),
|
|
861
1186
|
/* @__PURE__ */ jsxs("span", {
|
|
862
|
-
|
|
1187
|
+
className: "schemaVersionChip",
|
|
863
1188
|
children: [
|
|
864
1189
|
totalSubscribers,
|
|
865
1190
|
" subscriber",
|
|
@@ -868,63 +1193,57 @@ function LiveQueriesTab({ selectedInstance }) {
|
|
|
868
1193
|
}),
|
|
869
1194
|
/* @__PURE__ */ jsx("button", {
|
|
870
1195
|
type: "button",
|
|
871
|
-
|
|
872
|
-
...eventLogRefreshButtonStyles,
|
|
873
|
-
marginLeft: "auto"
|
|
874
|
-
},
|
|
1196
|
+
className: "refreshButton mlAuto",
|
|
875
1197
|
onClick: refresh,
|
|
876
1198
|
disabled: !selectedInstance,
|
|
877
1199
|
children: "↻ Refresh"
|
|
878
1200
|
})
|
|
879
1201
|
]
|
|
880
1202
|
}), queries.length === 0 ? /* @__PURE__ */ jsxs("div", {
|
|
881
|
-
|
|
1203
|
+
className: "schemaEmpty",
|
|
882
1204
|
children: [
|
|
883
1205
|
"No active live queries. Queries created via ",
|
|
884
1206
|
/* @__PURE__ */ jsx("code", {
|
|
885
|
-
|
|
1207
|
+
className: "inlineCode",
|
|
886
1208
|
children: "useDbQuery"
|
|
887
1209
|
}),
|
|
888
1210
|
" appear here while components are subscribed."
|
|
889
1211
|
]
|
|
890
1212
|
}) : /* @__PURE__ */ jsxs("div", {
|
|
891
|
-
|
|
1213
|
+
className: "schemaTableGrid",
|
|
892
1214
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
893
|
-
|
|
1215
|
+
className: "liveQueryHeaderRow",
|
|
894
1216
|
children: [
|
|
895
1217
|
/* @__PURE__ */ jsx("div", {
|
|
896
|
-
|
|
1218
|
+
className: "schemaColHeader",
|
|
897
1219
|
children: "SQL"
|
|
898
1220
|
}),
|
|
899
1221
|
/* @__PURE__ */ jsx("div", {
|
|
900
|
-
|
|
1222
|
+
className: "schemaColHeader",
|
|
901
1223
|
children: "Parameters"
|
|
902
1224
|
}),
|
|
903
1225
|
/* @__PURE__ */ jsx("div", {
|
|
904
|
-
|
|
905
|
-
...schemaColHeaderStyles,
|
|
906
|
-
textAlign: "center"
|
|
907
|
-
},
|
|
1226
|
+
className: "schemaColHeader alignCenter",
|
|
908
1227
|
children: "Subscribers"
|
|
909
1228
|
})
|
|
910
1229
|
]
|
|
911
1230
|
}), queries.map((query) => {
|
|
912
1231
|
const parameters = formatLiveQueryParameters(query.parameters);
|
|
913
1232
|
return /* @__PURE__ */ jsxs("div", {
|
|
914
|
-
|
|
1233
|
+
className: "liveQueryRow",
|
|
915
1234
|
children: [
|
|
916
1235
|
/* @__PURE__ */ jsx("div", {
|
|
917
|
-
|
|
1236
|
+
className: "liveQuerySql",
|
|
918
1237
|
children: query.sql
|
|
919
1238
|
}),
|
|
920
1239
|
/* @__PURE__ */ jsx("div", {
|
|
921
|
-
|
|
1240
|
+
className: "liveQueryParameters",
|
|
922
1241
|
children: parameters
|
|
923
1242
|
}),
|
|
924
1243
|
/* @__PURE__ */ jsx("div", {
|
|
925
|
-
|
|
1244
|
+
className: "schemaStatusCell",
|
|
926
1245
|
children: /* @__PURE__ */ jsx("span", {
|
|
927
|
-
|
|
1246
|
+
className: query.subscriberCount > 0 ? "schemaActiveTag" : "liveQueryIdleTag",
|
|
928
1247
|
children: query.subscriberCount
|
|
929
1248
|
})
|
|
930
1249
|
})
|
|
@@ -942,14 +1261,27 @@ function formatLiveQueryParameters(parameters) {
|
|
|
942
1261
|
return String(parameters);
|
|
943
1262
|
}
|
|
944
1263
|
}
|
|
1264
|
+
function isPersistedCrdtEvent(value) {
|
|
1265
|
+
if (typeof value !== "object" || value === null) return false;
|
|
1266
|
+
return "sync_id" in value && typeof value.sync_id === "number" && "status" in value && typeof value.status === "string" && "type" in value && typeof value.type === "string" && "origin" in value && typeof value.origin === "string" && "dataset" in value && typeof value.dataset === "string" && "item_id" in value && typeof value.item_id === "string" && "payload" in value && typeof value.payload === "string" && "timestamp" in value && typeof value.timestamp === "string";
|
|
1267
|
+
}
|
|
945
1268
|
const PAGE_SIZE = 50;
|
|
946
|
-
function
|
|
1269
|
+
function sqlStringLiteral(value) {
|
|
1270
|
+
return `'${value.replaceAll("'", "''")}'`;
|
|
1271
|
+
}
|
|
1272
|
+
function eventLogWhereClause(filters, afterSyncId) {
|
|
947
1273
|
const conditions = [];
|
|
948
|
-
if (filters.dataset) conditions.push(`dataset =
|
|
949
|
-
if (filters.origin) conditions.push(`origin =
|
|
950
|
-
if (filters.status) conditions.push(`status =
|
|
1274
|
+
if (filters.dataset) conditions.push(`dataset = ${sqlStringLiteral(filters.dataset)}`);
|
|
1275
|
+
if (filters.origin) conditions.push(`origin = ${sqlStringLiteral(filters.origin)}`);
|
|
1276
|
+
if (filters.status) conditions.push(`status = ${sqlStringLiteral(filters.status)}`);
|
|
951
1277
|
if (afterSyncId !== null) conditions.push(`sync_id < ${afterSyncId}`);
|
|
952
|
-
return
|
|
1278
|
+
return conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
1279
|
+
}
|
|
1280
|
+
function buildEventLogQuery(filters, afterSyncId) {
|
|
1281
|
+
return `SELECT * FROM "worker"."crdt_events" ${eventLogWhereClause(filters, afterSyncId)} ORDER BY sync_id DESC LIMIT 51`;
|
|
1282
|
+
}
|
|
1283
|
+
function buildEventLogCountQuery(filters) {
|
|
1284
|
+
return `SELECT COUNT(*) AS count FROM "worker"."crdt_events" ${eventLogWhereClause(filters, null)}`;
|
|
953
1285
|
}
|
|
954
1286
|
function EventLogTab({ selectedInstance }) {
|
|
955
1287
|
const baseTableNames = useMemo(() => selectedInstance?.instance._internal.crdtTablesConfig.map((table) => table.baseTableName) ?? [], [selectedInstance]);
|
|
@@ -959,12 +1291,13 @@ function EventLogTab({ selectedInstance }) {
|
|
|
959
1291
|
status: ""
|
|
960
1292
|
});
|
|
961
1293
|
const [events, setEvents] = useState([]);
|
|
1294
|
+
const [totalCount, setTotalCount] = useState(null);
|
|
962
1295
|
const [hasMore, setHasMore] = useState(false);
|
|
963
1296
|
const [isLoading, setIsLoading] = useState(false);
|
|
964
1297
|
const [expandedId, setExpandedId] = useState(null);
|
|
965
1298
|
const afterSyncIdRef = useRef(null);
|
|
966
1299
|
const isLoadingRef = useRef(false);
|
|
967
|
-
const
|
|
1300
|
+
const executeRows = useCallback(async (sql) => {
|
|
968
1301
|
if (!selectedInstance) return [];
|
|
969
1302
|
return (await selectedInstance.instance._internal.executeAsync({
|
|
970
1303
|
sql,
|
|
@@ -977,20 +1310,25 @@ function EventLogTab({ selectedInstance }) {
|
|
|
977
1310
|
setIsLoading(true);
|
|
978
1311
|
try {
|
|
979
1312
|
const sql = buildEventLogQuery(currentFilters, reset ? null : afterSyncIdRef.current);
|
|
980
|
-
const
|
|
981
|
-
const
|
|
1313
|
+
const rowsPromise = executeRows(sql);
|
|
1314
|
+
const countPromise = reset ? executeRows(buildEventLogCountQuery(currentFilters)) : Promise.resolve(null);
|
|
1315
|
+
const [rows, countRows] = await Promise.all([rowsPromise, countPromise]);
|
|
1316
|
+
const page = rows.filter(isPersistedCrdtEvent).slice(0, PAGE_SIZE);
|
|
982
1317
|
setHasMore(rows.length > PAGE_SIZE);
|
|
983
|
-
if (reset)
|
|
984
|
-
|
|
1318
|
+
if (reset) {
|
|
1319
|
+
setEvents(page);
|
|
1320
|
+
setTotalCount(countRows ? readCount(countRows) : null);
|
|
1321
|
+
} else setEvents((prev) => [...prev, ...page]);
|
|
985
1322
|
afterSyncIdRef.current = page.at(-1)?.sync_id ?? null;
|
|
986
1323
|
} finally {
|
|
987
1324
|
isLoadingRef.current = false;
|
|
988
1325
|
setIsLoading(false);
|
|
989
1326
|
}
|
|
990
|
-
}, [selectedInstance,
|
|
1327
|
+
}, [selectedInstance, executeRows]);
|
|
991
1328
|
useEffect(() => {
|
|
992
1329
|
afterSyncIdRef.current = null;
|
|
993
1330
|
setEvents([]);
|
|
1331
|
+
setTotalCount(null);
|
|
994
1332
|
load(true, filters);
|
|
995
1333
|
}, [filters, load]);
|
|
996
1334
|
const applyFilters = (next) => {
|
|
@@ -998,9 +1336,9 @@ function EventLogTab({ selectedInstance }) {
|
|
|
998
1336
|
};
|
|
999
1337
|
if (!selectedInstance) return null;
|
|
1000
1338
|
return /* @__PURE__ */ jsxs("div", {
|
|
1001
|
-
|
|
1339
|
+
className: "eventLogLayout",
|
|
1002
1340
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
1003
|
-
|
|
1341
|
+
className: "eventLogToolbar",
|
|
1004
1342
|
children: [
|
|
1005
1343
|
/* @__PURE__ */ jsxs("select", {
|
|
1006
1344
|
value: filters.dataset,
|
|
@@ -1008,7 +1346,7 @@ function EventLogTab({ selectedInstance }) {
|
|
|
1008
1346
|
...filters,
|
|
1009
1347
|
dataset: e.target.value
|
|
1010
1348
|
}),
|
|
1011
|
-
|
|
1349
|
+
className: "eventLogFilterSelect",
|
|
1012
1350
|
children: [/* @__PURE__ */ jsx("option", {
|
|
1013
1351
|
value: "",
|
|
1014
1352
|
children: "All datasets"
|
|
@@ -1023,7 +1361,7 @@ function EventLogTab({ selectedInstance }) {
|
|
|
1023
1361
|
...filters,
|
|
1024
1362
|
origin: e.target.value
|
|
1025
1363
|
}),
|
|
1026
|
-
|
|
1364
|
+
className: "eventLogFilterSelect",
|
|
1027
1365
|
children: [
|
|
1028
1366
|
/* @__PURE__ */ jsx("option", {
|
|
1029
1367
|
value: "",
|
|
@@ -1049,7 +1387,7 @@ function EventLogTab({ selectedInstance }) {
|
|
|
1049
1387
|
...filters,
|
|
1050
1388
|
status: e.target.value
|
|
1051
1389
|
}),
|
|
1052
|
-
|
|
1390
|
+
className: "eventLogFilterSelect",
|
|
1053
1391
|
children: [
|
|
1054
1392
|
/* @__PURE__ */ jsx("option", {
|
|
1055
1393
|
value: "",
|
|
@@ -1075,85 +1413,82 @@ function EventLogTab({ selectedInstance }) {
|
|
|
1075
1413
|
}),
|
|
1076
1414
|
/* @__PURE__ */ jsxs("button", {
|
|
1077
1415
|
type: "button",
|
|
1078
|
-
|
|
1416
|
+
className: "refreshButton",
|
|
1079
1417
|
disabled: isLoading,
|
|
1080
1418
|
onClick: () => void load(true, filters),
|
|
1081
1419
|
children: [isLoading ? "…" : "↻", " Refresh"]
|
|
1082
1420
|
}),
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
children:
|
|
1086
|
-
events.length,
|
|
1087
|
-
hasMore ? "+" : "",
|
|
1088
|
-
" events"
|
|
1089
|
-
]
|
|
1421
|
+
totalCount !== null && /* @__PURE__ */ jsx("span", {
|
|
1422
|
+
className: "eventLogCount",
|
|
1423
|
+
children: events.length === totalCount ? `${totalCount} event${totalCount === 1 ? "" : "s"}` : `${events.length} of ${totalCount}`
|
|
1090
1424
|
})
|
|
1091
1425
|
]
|
|
1092
1426
|
}), events.length === 0 && !isLoading ? /* @__PURE__ */ jsx("div", {
|
|
1093
|
-
|
|
1427
|
+
className: "eventLogEmpty",
|
|
1094
1428
|
children: "No events match the current filters."
|
|
1095
1429
|
}) : /* @__PURE__ */ jsxs("div", {
|
|
1096
|
-
|
|
1430
|
+
className: "eventLogList",
|
|
1097
1431
|
children: [events.map((event) => {
|
|
1098
1432
|
const isExpanded = expandedId === event.sync_id;
|
|
1099
1433
|
return /* @__PURE__ */ jsxs("div", {
|
|
1100
|
-
|
|
1434
|
+
className: "eventRow",
|
|
1435
|
+
"data-expanded": isExpanded ? "true" : void 0,
|
|
1101
1436
|
children: [/* @__PURE__ */ jsxs("button", {
|
|
1102
1437
|
type: "button",
|
|
1103
|
-
|
|
1438
|
+
className: "eventRowHeader",
|
|
1104
1439
|
onClick: () => setExpandedId(isExpanded ? null : event.sync_id),
|
|
1105
1440
|
children: [
|
|
1106
1441
|
/* @__PURE__ */ jsxs("span", {
|
|
1107
|
-
|
|
1442
|
+
className: "eventSyncId",
|
|
1108
1443
|
children: ["#", event.sync_id]
|
|
1109
1444
|
}),
|
|
1110
1445
|
/* @__PURE__ */ jsx(EventTypeBadge, { type: event.type }),
|
|
1111
1446
|
/* @__PURE__ */ jsx(EventOriginBadge, { origin: event.origin }),
|
|
1112
1447
|
/* @__PURE__ */ jsx(EventStatusBadge, { status: event.status }),
|
|
1113
1448
|
/* @__PURE__ */ jsx("span", {
|
|
1114
|
-
|
|
1449
|
+
className: "eventDataset",
|
|
1115
1450
|
children: event.dataset
|
|
1116
1451
|
}),
|
|
1117
1452
|
/* @__PURE__ */ jsx("span", {
|
|
1118
|
-
|
|
1453
|
+
className: "eventItemId",
|
|
1119
1454
|
children: event.item_id
|
|
1120
1455
|
}),
|
|
1121
1456
|
/* @__PURE__ */ jsx("span", {
|
|
1122
|
-
|
|
1457
|
+
className: "eventTimestamp",
|
|
1123
1458
|
children: formatHlcTimestamp(event.timestamp)
|
|
1124
1459
|
}),
|
|
1125
1460
|
/* @__PURE__ */ jsx("span", {
|
|
1126
|
-
|
|
1461
|
+
className: "eventChevron",
|
|
1127
1462
|
children: isExpanded ? "▲" : "▼"
|
|
1128
1463
|
})
|
|
1129
1464
|
]
|
|
1130
1465
|
}), isExpanded && /* @__PURE__ */ jsxs("div", {
|
|
1131
|
-
|
|
1466
|
+
className: "eventPayload",
|
|
1132
1467
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
1133
|
-
|
|
1468
|
+
className: "eventPayloadMeta",
|
|
1134
1469
|
children: [
|
|
1135
1470
|
/* @__PURE__ */ jsxs("span", {
|
|
1136
|
-
|
|
1471
|
+
className: "eventMetaItem",
|
|
1137
1472
|
children: ["schema v", event.schema_version]
|
|
1138
1473
|
}),
|
|
1139
1474
|
/* @__PURE__ */ jsxs("span", {
|
|
1140
|
-
|
|
1475
|
+
className: "eventMetaItem",
|
|
1141
1476
|
children: ["node: ", event.source_node_id || "—"]
|
|
1142
1477
|
}),
|
|
1143
1478
|
/* @__PURE__ */ jsxs("span", {
|
|
1144
|
-
|
|
1479
|
+
className: "eventMetaItem",
|
|
1145
1480
|
children: ["ts: ", event.timestamp]
|
|
1146
1481
|
})
|
|
1147
1482
|
]
|
|
1148
1483
|
}), /* @__PURE__ */ jsx("pre", {
|
|
1149
|
-
|
|
1484
|
+
className: "eventPayloadPre",
|
|
1150
1485
|
children: formatPayload(event.payload)
|
|
1151
1486
|
})]
|
|
1152
1487
|
})]
|
|
1153
1488
|
}, event.sync_id);
|
|
1154
1489
|
}), hasMore && /* @__PURE__ */ jsx("button", {
|
|
1155
1490
|
type: "button",
|
|
1156
|
-
|
|
1491
|
+
className: "loadMoreButton",
|
|
1157
1492
|
disabled: isLoading,
|
|
1158
1493
|
onClick: () => void load(false, filters),
|
|
1159
1494
|
children: isLoading ? "Loading…" : `Load ${PAGE_SIZE} more`
|
|
@@ -1162,30 +1497,33 @@ function EventLogTab({ selectedInstance }) {
|
|
|
1162
1497
|
});
|
|
1163
1498
|
}
|
|
1164
1499
|
function EventTypeBadge({ type }) {
|
|
1165
|
-
const {
|
|
1166
|
-
|
|
1500
|
+
const { variant, label } = type === "item-created" ? {
|
|
1501
|
+
variant: "create",
|
|
1167
1502
|
label: "create"
|
|
1168
1503
|
} : type === "item-deleted" ? {
|
|
1169
|
-
|
|
1504
|
+
variant: "delete",
|
|
1170
1505
|
label: "delete"
|
|
1171
1506
|
} : {
|
|
1172
|
-
|
|
1507
|
+
variant: "update",
|
|
1173
1508
|
label: "update"
|
|
1174
1509
|
};
|
|
1175
1510
|
return /* @__PURE__ */ jsx("span", {
|
|
1176
|
-
|
|
1511
|
+
className: "eventBadge",
|
|
1512
|
+
"data-variant": variant,
|
|
1177
1513
|
children: label
|
|
1178
1514
|
});
|
|
1179
1515
|
}
|
|
1180
1516
|
function EventOriginBadge({ origin }) {
|
|
1181
1517
|
return /* @__PURE__ */ jsx("span", {
|
|
1182
|
-
|
|
1518
|
+
className: "eventBadge",
|
|
1519
|
+
"data-variant": origin === "own" ? "own" : origin === "remote" ? "remote" : "local",
|
|
1183
1520
|
children: origin
|
|
1184
1521
|
});
|
|
1185
1522
|
}
|
|
1186
1523
|
function EventStatusBadge({ status }) {
|
|
1187
1524
|
return /* @__PURE__ */ jsx("span", {
|
|
1188
|
-
|
|
1525
|
+
className: "eventBadge",
|
|
1526
|
+
"data-variant": status === "applied" ? "applied" : status === "pending" ? "pending" : status === "failed" ? "failed" : "skipped",
|
|
1189
1527
|
children: status
|
|
1190
1528
|
});
|
|
1191
1529
|
}
|
|
@@ -1203,46 +1541,50 @@ function formatPayload(raw) {
|
|
|
1203
1541
|
}
|
|
1204
1542
|
function QueryRunnerTab({ selectedInstance, queryTarget, setQueryTarget, query, setQuery, queryState, canRunQuery, runQuery }) {
|
|
1205
1543
|
return /* @__PURE__ */ jsxs("div", {
|
|
1206
|
-
|
|
1544
|
+
className: "queryRunnerLayout",
|
|
1207
1545
|
children: [
|
|
1208
1546
|
/* @__PURE__ */ jsxs("div", {
|
|
1209
|
-
|
|
1547
|
+
className: "queryToolbar",
|
|
1210
1548
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
1211
|
-
|
|
1549
|
+
className: "targetToggle",
|
|
1212
1550
|
children: [/* @__PURE__ */ jsx("button", {
|
|
1213
1551
|
type: "button",
|
|
1214
|
-
|
|
1552
|
+
className: "targetButton",
|
|
1553
|
+
"data-active": queryTarget === "memory" ? "true" : void 0,
|
|
1215
1554
|
onClick: () => setQueryTarget("memory"),
|
|
1216
1555
|
children: "Memory DB"
|
|
1217
1556
|
}), /* @__PURE__ */ jsx("button", {
|
|
1218
1557
|
type: "button",
|
|
1219
|
-
|
|
1558
|
+
className: "targetButton",
|
|
1559
|
+
"data-active": queryTarget === "worker" ? "true" : void 0,
|
|
1220
1560
|
onClick: () => setQueryTarget("worker"),
|
|
1221
1561
|
children: "Worker DB"
|
|
1222
1562
|
})]
|
|
1223
1563
|
}), /* @__PURE__ */ jsxs("div", {
|
|
1224
|
-
|
|
1564
|
+
className: "queryToolbarRight",
|
|
1225
1565
|
children: [
|
|
1226
1566
|
!selectedInstance && /* @__PURE__ */ jsx("span", {
|
|
1227
|
-
|
|
1567
|
+
className: "noInstanceWarning",
|
|
1228
1568
|
children: "No instance selected"
|
|
1229
1569
|
}),
|
|
1230
1570
|
/* @__PURE__ */ jsx("span", {
|
|
1231
|
-
|
|
1571
|
+
className: "shortcutHint",
|
|
1232
1572
|
children: "⌘↵ to run"
|
|
1233
1573
|
}),
|
|
1234
1574
|
/* @__PURE__ */ jsx("button", {
|
|
1235
1575
|
type: "button",
|
|
1236
|
-
|
|
1576
|
+
className: "runButton",
|
|
1577
|
+
"data-enabled": canRunQuery ? "true" : void 0,
|
|
1578
|
+
"data-running": queryState.status === "running" ? "true" : void 0,
|
|
1237
1579
|
disabled: !canRunQuery,
|
|
1238
1580
|
onClick: () => void runQuery(),
|
|
1239
|
-
children: queryState.status === "running" ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
|
|
1581
|
+
children: queryState.status === "running" ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", { className: "runningDot" }), "Running…"] }) : /* @__PURE__ */ jsx(Fragment, { children: "▶ Run" })
|
|
1240
1582
|
})
|
|
1241
1583
|
]
|
|
1242
1584
|
})]
|
|
1243
1585
|
}),
|
|
1244
1586
|
/* @__PURE__ */ jsx("div", {
|
|
1245
|
-
|
|
1587
|
+
className: "editorWrapper",
|
|
1246
1588
|
children: /* @__PURE__ */ jsx("textarea", {
|
|
1247
1589
|
value: query,
|
|
1248
1590
|
onChange: (event) => setQuery(event.target.value),
|
|
@@ -1252,24 +1594,24 @@ function QueryRunnerTab({ selectedInstance, queryTarget, setQueryTarget, query,
|
|
|
1252
1594
|
runQuery();
|
|
1253
1595
|
}
|
|
1254
1596
|
},
|
|
1255
|
-
|
|
1597
|
+
className: "textarea",
|
|
1256
1598
|
placeholder: "SELECT * FROM your_table LIMIT 100",
|
|
1257
1599
|
spellCheck: false
|
|
1258
1600
|
})
|
|
1259
1601
|
}),
|
|
1260
1602
|
/* @__PURE__ */ jsx("div", {
|
|
1261
|
-
|
|
1603
|
+
className: "helperText",
|
|
1262
1604
|
children: queryTarget === "worker" ? "Worker DB is read-only — only SELECT, PRAGMA, and EXPLAIN are allowed." : "Memory DB allows writes only to CRDT tables."
|
|
1263
1605
|
}),
|
|
1264
1606
|
queryState.status === "error" && /* @__PURE__ */ jsxs("div", {
|
|
1265
|
-
|
|
1607
|
+
className: "errorPanel",
|
|
1266
1608
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
1267
|
-
|
|
1609
|
+
className: "resultHeader",
|
|
1268
1610
|
children: [/* @__PURE__ */ jsx("span", {
|
|
1269
|
-
|
|
1611
|
+
className: "errorBadge",
|
|
1270
1612
|
children: "Error"
|
|
1271
1613
|
}), /* @__PURE__ */ jsxs("span", {
|
|
1272
|
-
|
|
1614
|
+
className: "resultMeta",
|
|
1273
1615
|
children: [
|
|
1274
1616
|
queryState.error.target,
|
|
1275
1617
|
" · ",
|
|
@@ -1277,23 +1619,23 @@ function QueryRunnerTab({ selectedInstance, queryTarget, setQueryTarget, query,
|
|
|
1277
1619
|
]
|
|
1278
1620
|
})]
|
|
1279
1621
|
}), /* @__PURE__ */ jsx("pre", {
|
|
1280
|
-
|
|
1622
|
+
className: "errorMessage",
|
|
1281
1623
|
children: queryState.error.message
|
|
1282
1624
|
})]
|
|
1283
1625
|
}),
|
|
1284
1626
|
queryState.status === "success" && /* @__PURE__ */ jsxs("div", {
|
|
1285
|
-
|
|
1627
|
+
className: "resultPanel",
|
|
1286
1628
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
1287
|
-
|
|
1629
|
+
className: "resultHeader",
|
|
1288
1630
|
children: [/* @__PURE__ */ jsxs("span", {
|
|
1289
|
-
|
|
1631
|
+
className: "successBadge",
|
|
1290
1632
|
children: [
|
|
1291
1633
|
queryState.output.rowCount,
|
|
1292
1634
|
" row",
|
|
1293
1635
|
queryState.output.rowCount !== 1 ? "s" : ""
|
|
1294
1636
|
]
|
|
1295
1637
|
}), /* @__PURE__ */ jsxs("span", {
|
|
1296
|
-
|
|
1638
|
+
className: "resultMeta",
|
|
1297
1639
|
children: [
|
|
1298
1640
|
queryState.output.target,
|
|
1299
1641
|
" · ",
|
|
@@ -1308,44 +1650,41 @@ function QueryRunnerTab({ selectedInstance, queryTarget, setQueryTarget, query,
|
|
|
1308
1650
|
}
|
|
1309
1651
|
function ResultTable({ rows }) {
|
|
1310
1652
|
if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
1311
|
-
|
|
1653
|
+
className: "resultEmpty",
|
|
1312
1654
|
children: "Query returned 0 rows."
|
|
1313
1655
|
});
|
|
1314
1656
|
const firstRow = rows[0];
|
|
1315
1657
|
if (typeof firstRow !== "object" || firstRow === null) return /* @__PURE__ */ jsx("pre", {
|
|
1316
|
-
|
|
1658
|
+
className: "resultRaw",
|
|
1317
1659
|
children: JSON.stringify(rows, null, 2)
|
|
1318
1660
|
});
|
|
1319
1661
|
const columns = Object.keys(firstRow);
|
|
1320
1662
|
return /* @__PURE__ */ jsx("div", {
|
|
1321
|
-
|
|
1663
|
+
className: "tableWrapper",
|
|
1322
1664
|
children: /* @__PURE__ */ jsxs("table", {
|
|
1323
|
-
|
|
1665
|
+
className: "table",
|
|
1324
1666
|
children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("th", {
|
|
1325
|
-
|
|
1667
|
+
className: "thRowNum",
|
|
1326
1668
|
children: "#"
|
|
1327
1669
|
}), columns.map((col) => /* @__PURE__ */ jsx("th", {
|
|
1328
|
-
|
|
1670
|
+
className: "th",
|
|
1329
1671
|
children: col
|
|
1330
|
-
}, col))] }) }), /* @__PURE__ */ jsx("tbody", { children: rows.map((row, rowIdx) => /* @__PURE__ */ jsxs("tr", {
|
|
1331
|
-
|
|
1332
|
-
children:
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
children:
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
}, col);
|
|
1347
|
-
})]
|
|
1348
|
-
}, rowIdx)) })]
|
|
1672
|
+
}, col))] }) }), /* @__PURE__ */ jsx("tbody", { children: rows.map((row, rowIdx) => /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("td", {
|
|
1673
|
+
className: "tdRowNum",
|
|
1674
|
+
children: rowIdx + 1
|
|
1675
|
+
}), columns.map((col) => {
|
|
1676
|
+
const val = row[col];
|
|
1677
|
+
return /* @__PURE__ */ jsx("td", {
|
|
1678
|
+
className: "td",
|
|
1679
|
+
children: val === null ? /* @__PURE__ */ jsx("span", {
|
|
1680
|
+
className: "nullValue",
|
|
1681
|
+
children: "NULL"
|
|
1682
|
+
}) : typeof val === "object" ? /* @__PURE__ */ jsx("span", {
|
|
1683
|
+
className: "jsonValue",
|
|
1684
|
+
children: JSON.stringify(val)
|
|
1685
|
+
}) : String(val)
|
|
1686
|
+
}, col);
|
|
1687
|
+
})] }, rowIdx)) })]
|
|
1349
1688
|
})
|
|
1350
1689
|
});
|
|
1351
1690
|
}
|
|
@@ -1370,1164 +1709,6 @@ function getEmptySnapshot() {
|
|
|
1370
1709
|
return emptySnapshot;
|
|
1371
1710
|
}
|
|
1372
1711
|
const emptySnapshot = { instances: [] };
|
|
1373
|
-
const C = {
|
|
1374
|
-
bg: "#0e1015",
|
|
1375
|
-
bgPanel: "#161921",
|
|
1376
|
-
bgCard: "#1c2030",
|
|
1377
|
-
bgInput: "#111318",
|
|
1378
|
-
border: "#2a2f3e",
|
|
1379
|
-
borderLight: "#343a4f",
|
|
1380
|
-
text: "#e2e8f0",
|
|
1381
|
-
textMuted: "#6b7280",
|
|
1382
|
-
textDim: "#9ca3af",
|
|
1383
|
-
teal: "#2dd4bf",
|
|
1384
|
-
tealDim: "rgba(45,212,191,0.12)",
|
|
1385
|
-
tealGlow: "rgba(45,212,191,0.06)",
|
|
1386
|
-
error: "#f87171",
|
|
1387
|
-
errorBg: "rgba(248,113,113,0.08)",
|
|
1388
|
-
errorBorder: "rgba(248,113,113,0.25)",
|
|
1389
|
-
success: "#34d399",
|
|
1390
|
-
successBg: "rgba(52,211,153,0.08)",
|
|
1391
|
-
amber: "#fbbf24"
|
|
1392
|
-
};
|
|
1393
|
-
const floatingRootStyles = {
|
|
1394
|
-
position: "fixed",
|
|
1395
|
-
inset: 0,
|
|
1396
|
-
pointerEvents: "none",
|
|
1397
|
-
zIndex: 9998
|
|
1398
|
-
};
|
|
1399
|
-
const triggerButtonStyles = {
|
|
1400
|
-
position: "absolute",
|
|
1401
|
-
right: "16px",
|
|
1402
|
-
bottom: "16px",
|
|
1403
|
-
display: "inline-flex",
|
|
1404
|
-
alignItems: "center",
|
|
1405
|
-
gap: "0.3rem",
|
|
1406
|
-
border: `1px solid ${C.border}`,
|
|
1407
|
-
borderRadius: "8px",
|
|
1408
|
-
padding: "0.3rem 0.45rem",
|
|
1409
|
-
background: C.bgPanel,
|
|
1410
|
-
color: C.text,
|
|
1411
|
-
boxShadow: `0 0 0 1px ${C.border}, 0 4px 16px rgba(0,0,0,0.5)`,
|
|
1412
|
-
cursor: "grab",
|
|
1413
|
-
touchAction: "none",
|
|
1414
|
-
userSelect: "none",
|
|
1415
|
-
pointerEvents: "auto"
|
|
1416
|
-
};
|
|
1417
|
-
const triggerIconStyles = {
|
|
1418
|
-
color: C.teal,
|
|
1419
|
-
fontSize: "0.9rem",
|
|
1420
|
-
lineHeight: 1
|
|
1421
|
-
};
|
|
1422
|
-
const triggerCountStyles = {
|
|
1423
|
-
minWidth: "1.1rem",
|
|
1424
|
-
borderRadius: "4px",
|
|
1425
|
-
padding: "0.05rem 0.25rem",
|
|
1426
|
-
backgroundColor: C.tealDim,
|
|
1427
|
-
color: C.teal,
|
|
1428
|
-
fontSize: "0.65rem",
|
|
1429
|
-
fontWeight: 700,
|
|
1430
|
-
textAlign: "center",
|
|
1431
|
-
fontFamily: "ui-monospace, monospace"
|
|
1432
|
-
};
|
|
1433
|
-
const overlayStyles = {
|
|
1434
|
-
position: "fixed",
|
|
1435
|
-
inset: 0,
|
|
1436
|
-
zIndex: 9999,
|
|
1437
|
-
display: "flex",
|
|
1438
|
-
alignItems: "center",
|
|
1439
|
-
justifyContent: "center",
|
|
1440
|
-
padding: "1.5rem",
|
|
1441
|
-
backgroundColor: "rgba(0,0,0,0.72)",
|
|
1442
|
-
backdropFilter: "blur(8px)"
|
|
1443
|
-
};
|
|
1444
|
-
const dialogStyles = {
|
|
1445
|
-
width: "min(72rem, 100%)",
|
|
1446
|
-
height: "min(90vh, 860px)",
|
|
1447
|
-
display: "flex",
|
|
1448
|
-
flexDirection: "column",
|
|
1449
|
-
border: `1px solid ${C.border}`,
|
|
1450
|
-
borderRadius: "16px",
|
|
1451
|
-
background: C.bg,
|
|
1452
|
-
boxShadow: `0 0 0 1px ${C.border}, 0 40px 80px rgba(0,0,0,0.8), 0 0 60px rgba(45,212,191,0.04)`,
|
|
1453
|
-
overflow: "hidden",
|
|
1454
|
-
fontFamily: "ui-sans-serif, system-ui, sans-serif",
|
|
1455
|
-
color: C.text,
|
|
1456
|
-
fontSize: "0.88rem"
|
|
1457
|
-
};
|
|
1458
|
-
const headerStyles = {
|
|
1459
|
-
display: "flex",
|
|
1460
|
-
justifyContent: "space-between",
|
|
1461
|
-
alignItems: "center",
|
|
1462
|
-
gap: "1rem",
|
|
1463
|
-
padding: "0.85rem 1.1rem",
|
|
1464
|
-
borderBottom: `1px solid ${C.border}`,
|
|
1465
|
-
background: C.bgPanel,
|
|
1466
|
-
flexShrink: 0
|
|
1467
|
-
};
|
|
1468
|
-
const headerLeftStyles = {
|
|
1469
|
-
display: "flex",
|
|
1470
|
-
alignItems: "center",
|
|
1471
|
-
gap: "0.75rem"
|
|
1472
|
-
};
|
|
1473
|
-
const headerLogoStyles = {
|
|
1474
|
-
fontSize: "1.3rem",
|
|
1475
|
-
color: C.teal,
|
|
1476
|
-
lineHeight: 1
|
|
1477
|
-
};
|
|
1478
|
-
const eyebrowStyles = {
|
|
1479
|
-
fontSize: "0.65rem",
|
|
1480
|
-
fontWeight: 600,
|
|
1481
|
-
letterSpacing: "0.1em",
|
|
1482
|
-
textTransform: "uppercase",
|
|
1483
|
-
color: C.textMuted,
|
|
1484
|
-
fontFamily: "ui-monospace, monospace"
|
|
1485
|
-
};
|
|
1486
|
-
const titleStyles = {
|
|
1487
|
-
margin: "0.05rem 0 0",
|
|
1488
|
-
fontSize: "0.95rem",
|
|
1489
|
-
fontWeight: 700,
|
|
1490
|
-
color: C.text,
|
|
1491
|
-
letterSpacing: "-0.01em"
|
|
1492
|
-
};
|
|
1493
|
-
const headerRightStyles = {
|
|
1494
|
-
display: "flex",
|
|
1495
|
-
alignItems: "center",
|
|
1496
|
-
gap: "0.6rem"
|
|
1497
|
-
};
|
|
1498
|
-
const instancePickerLabelStyles = {
|
|
1499
|
-
display: "flex",
|
|
1500
|
-
alignItems: "center",
|
|
1501
|
-
gap: "0.5rem"
|
|
1502
|
-
};
|
|
1503
|
-
const instancePickerTextStyles = {
|
|
1504
|
-
fontSize: "0.72rem",
|
|
1505
|
-
fontWeight: 600,
|
|
1506
|
-
color: C.textMuted,
|
|
1507
|
-
textTransform: "uppercase",
|
|
1508
|
-
letterSpacing: "0.06em"
|
|
1509
|
-
};
|
|
1510
|
-
const instancePickerSelectStyles = {
|
|
1511
|
-
borderRadius: "7px",
|
|
1512
|
-
border: `1px solid ${C.border}`,
|
|
1513
|
-
padding: "0.35rem 0.6rem",
|
|
1514
|
-
backgroundColor: C.bgCard,
|
|
1515
|
-
color: C.text,
|
|
1516
|
-
fontSize: "0.82rem",
|
|
1517
|
-
fontFamily: "ui-monospace, monospace",
|
|
1518
|
-
cursor: "pointer"
|
|
1519
|
-
};
|
|
1520
|
-
const instanceCountBadgeStyles = {
|
|
1521
|
-
fontSize: "0.72rem",
|
|
1522
|
-
fontWeight: 600,
|
|
1523
|
-
color: C.teal,
|
|
1524
|
-
backgroundColor: C.tealDim,
|
|
1525
|
-
borderRadius: "5px",
|
|
1526
|
-
padding: "0.2rem 0.5rem",
|
|
1527
|
-
fontFamily: "ui-monospace, monospace"
|
|
1528
|
-
};
|
|
1529
|
-
const closeButtonStyles = {
|
|
1530
|
-
border: `1px solid ${C.border}`,
|
|
1531
|
-
borderRadius: "7px",
|
|
1532
|
-
width: "28px",
|
|
1533
|
-
height: "28px",
|
|
1534
|
-
display: "flex",
|
|
1535
|
-
alignItems: "center",
|
|
1536
|
-
justifyContent: "center",
|
|
1537
|
-
backgroundColor: "transparent",
|
|
1538
|
-
color: C.textMuted,
|
|
1539
|
-
fontSize: "0.82rem",
|
|
1540
|
-
fontWeight: 600,
|
|
1541
|
-
cursor: "pointer"
|
|
1542
|
-
};
|
|
1543
|
-
const emptyStateStyles = {
|
|
1544
|
-
display: "flex",
|
|
1545
|
-
flexDirection: "column",
|
|
1546
|
-
alignItems: "center",
|
|
1547
|
-
justifyContent: "center",
|
|
1548
|
-
padding: "4rem 2rem",
|
|
1549
|
-
gap: "0.75rem",
|
|
1550
|
-
flex: 1
|
|
1551
|
-
};
|
|
1552
|
-
const emptyStateIconStyles = {
|
|
1553
|
-
fontSize: "2.5rem",
|
|
1554
|
-
color: C.textMuted,
|
|
1555
|
-
opacity: .4
|
|
1556
|
-
};
|
|
1557
|
-
const emptyStateTextStyles = {
|
|
1558
|
-
margin: 0,
|
|
1559
|
-
fontSize: "0.95rem",
|
|
1560
|
-
fontWeight: 600,
|
|
1561
|
-
color: C.textDim
|
|
1562
|
-
};
|
|
1563
|
-
const emptyStateSubtextStyles = {
|
|
1564
|
-
margin: 0,
|
|
1565
|
-
fontSize: "0.82rem",
|
|
1566
|
-
color: C.textMuted,
|
|
1567
|
-
textAlign: "center"
|
|
1568
|
-
};
|
|
1569
|
-
const inlineCodeStyles = {
|
|
1570
|
-
fontFamily: "ui-monospace, monospace",
|
|
1571
|
-
backgroundColor: C.bgCard,
|
|
1572
|
-
border: `1px solid ${C.border}`,
|
|
1573
|
-
borderRadius: "4px",
|
|
1574
|
-
padding: "0.1em 0.4em",
|
|
1575
|
-
fontSize: "0.88em",
|
|
1576
|
-
color: C.teal
|
|
1577
|
-
};
|
|
1578
|
-
const contentLayoutStyles = {
|
|
1579
|
-
display: "grid",
|
|
1580
|
-
gridTemplateColumns: "200px minmax(0, 1fr)",
|
|
1581
|
-
flex: 1,
|
|
1582
|
-
minHeight: 0,
|
|
1583
|
-
overflow: "hidden"
|
|
1584
|
-
};
|
|
1585
|
-
const sidebarStyles = {
|
|
1586
|
-
display: "flex",
|
|
1587
|
-
flexDirection: "column",
|
|
1588
|
-
gap: "0",
|
|
1589
|
-
padding: "0.75rem",
|
|
1590
|
-
borderRight: `1px solid ${C.border}`,
|
|
1591
|
-
background: C.bgPanel,
|
|
1592
|
-
overflowY: "auto"
|
|
1593
|
-
};
|
|
1594
|
-
const navStyles = {
|
|
1595
|
-
display: "flex",
|
|
1596
|
-
flexDirection: "column",
|
|
1597
|
-
gap: "0.25rem",
|
|
1598
|
-
marginBottom: "1rem"
|
|
1599
|
-
};
|
|
1600
|
-
const navIconStyles = {
|
|
1601
|
-
fontSize: "0.7rem",
|
|
1602
|
-
opacity: .7
|
|
1603
|
-
};
|
|
1604
|
-
const sidebarInfoStyles = {
|
|
1605
|
-
marginTop: "auto",
|
|
1606
|
-
padding: "0.75rem",
|
|
1607
|
-
borderRadius: "8px",
|
|
1608
|
-
background: C.bgCard,
|
|
1609
|
-
border: `1px solid ${C.border}`
|
|
1610
|
-
};
|
|
1611
|
-
const sidebarInfoLabelStyles = {
|
|
1612
|
-
fontSize: "0.65rem",
|
|
1613
|
-
fontWeight: 600,
|
|
1614
|
-
letterSpacing: "0.08em",
|
|
1615
|
-
textTransform: "uppercase",
|
|
1616
|
-
color: C.textMuted,
|
|
1617
|
-
marginBottom: "0.3rem"
|
|
1618
|
-
};
|
|
1619
|
-
const sidebarInfoValueStyles = {
|
|
1620
|
-
fontSize: "0.88rem",
|
|
1621
|
-
fontWeight: 600,
|
|
1622
|
-
color: C.text,
|
|
1623
|
-
wordBreak: "break-word",
|
|
1624
|
-
fontFamily: "ui-monospace, monospace"
|
|
1625
|
-
};
|
|
1626
|
-
const sidebarInfoSubStyles = {
|
|
1627
|
-
fontSize: "0.72rem",
|
|
1628
|
-
color: C.textMuted,
|
|
1629
|
-
fontFamily: "ui-monospace, monospace",
|
|
1630
|
-
marginTop: "0.25rem"
|
|
1631
|
-
};
|
|
1632
|
-
const mainPaneStyles = {
|
|
1633
|
-
minWidth: 0,
|
|
1634
|
-
overflowY: "auto",
|
|
1635
|
-
padding: "1rem"
|
|
1636
|
-
};
|
|
1637
|
-
const overviewLayoutStyles = {
|
|
1638
|
-
display: "flex",
|
|
1639
|
-
flexDirection: "column",
|
|
1640
|
-
gap: "1.25rem"
|
|
1641
|
-
};
|
|
1642
|
-
const overviewCardsRowStyles = {
|
|
1643
|
-
display: "grid",
|
|
1644
|
-
gridTemplateColumns: "repeat(auto-fit, minmax(11rem, 1fr))",
|
|
1645
|
-
gap: "0.75rem"
|
|
1646
|
-
};
|
|
1647
|
-
const overviewCardStyles = {
|
|
1648
|
-
padding: "0.9rem 1rem",
|
|
1649
|
-
borderRadius: "10px",
|
|
1650
|
-
border: `1px solid ${C.border}`,
|
|
1651
|
-
background: C.bgCard
|
|
1652
|
-
};
|
|
1653
|
-
const overviewCardLabelStyles = {
|
|
1654
|
-
fontSize: "0.68rem",
|
|
1655
|
-
fontWeight: 600,
|
|
1656
|
-
letterSpacing: "0.08em",
|
|
1657
|
-
textTransform: "uppercase",
|
|
1658
|
-
color: C.textMuted,
|
|
1659
|
-
marginBottom: "0.4rem"
|
|
1660
|
-
};
|
|
1661
|
-
const overviewCardValueStyles = {
|
|
1662
|
-
fontSize: "1rem",
|
|
1663
|
-
fontWeight: 700,
|
|
1664
|
-
color: C.text,
|
|
1665
|
-
wordBreak: "break-word"
|
|
1666
|
-
};
|
|
1667
|
-
const overviewSectionStyles = {
|
|
1668
|
-
display: "flex",
|
|
1669
|
-
flexDirection: "column",
|
|
1670
|
-
gap: "0.5rem"
|
|
1671
|
-
};
|
|
1672
|
-
const overviewSectionTitleStyles = {
|
|
1673
|
-
fontSize: "0.72rem",
|
|
1674
|
-
fontWeight: 600,
|
|
1675
|
-
letterSpacing: "0.08em",
|
|
1676
|
-
textTransform: "uppercase",
|
|
1677
|
-
color: C.textMuted
|
|
1678
|
-
};
|
|
1679
|
-
const overviewSectionHeaderStyles = {
|
|
1680
|
-
display: "flex",
|
|
1681
|
-
alignItems: "center",
|
|
1682
|
-
justifyContent: "space-between",
|
|
1683
|
-
gap: "0.75rem"
|
|
1684
|
-
};
|
|
1685
|
-
const overviewRefreshButtonStyles = {
|
|
1686
|
-
border: `1px solid ${C.border}`,
|
|
1687
|
-
borderRadius: "7px",
|
|
1688
|
-
padding: "0.35rem 0.7rem",
|
|
1689
|
-
backgroundColor: "transparent",
|
|
1690
|
-
color: C.textDim,
|
|
1691
|
-
fontSize: "0.78rem",
|
|
1692
|
-
fontFamily: "ui-monospace, monospace",
|
|
1693
|
-
cursor: "pointer",
|
|
1694
|
-
flexShrink: 0
|
|
1695
|
-
};
|
|
1696
|
-
const overviewAccumulatorValueStyles = {
|
|
1697
|
-
padding: "0.75rem",
|
|
1698
|
-
borderRadius: "8px",
|
|
1699
|
-
border: `1px solid ${C.border}`,
|
|
1700
|
-
background: C.bgCard,
|
|
1701
|
-
fontFamily: "ui-monospace, monospace",
|
|
1702
|
-
fontSize: "0.78rem",
|
|
1703
|
-
color: C.text,
|
|
1704
|
-
lineHeight: 1.5,
|
|
1705
|
-
wordBreak: "break-all"
|
|
1706
|
-
};
|
|
1707
|
-
const overviewAccumulatorEmptyStyles = {
|
|
1708
|
-
color: C.textMuted,
|
|
1709
|
-
fontStyle: "italic"
|
|
1710
|
-
};
|
|
1711
|
-
const overviewAccumulatorErrorStyles = { color: C.error };
|
|
1712
|
-
const overviewEmptyStyles = {
|
|
1713
|
-
fontSize: "0.82rem",
|
|
1714
|
-
color: C.textMuted,
|
|
1715
|
-
fontStyle: "italic"
|
|
1716
|
-
};
|
|
1717
|
-
const crdtTableListStyles = {
|
|
1718
|
-
display: "flex",
|
|
1719
|
-
flexDirection: "column",
|
|
1720
|
-
gap: "0.25rem"
|
|
1721
|
-
};
|
|
1722
|
-
const crdtTableRowStyles = {
|
|
1723
|
-
display: "flex",
|
|
1724
|
-
alignItems: "center",
|
|
1725
|
-
gap: "0.6rem",
|
|
1726
|
-
padding: "0.5rem 0.75rem",
|
|
1727
|
-
borderRadius: "7px",
|
|
1728
|
-
background: C.bgCard,
|
|
1729
|
-
border: `1px solid ${C.border}`
|
|
1730
|
-
};
|
|
1731
|
-
const crdtTableIconStyles = {
|
|
1732
|
-
color: C.teal,
|
|
1733
|
-
fontSize: "0.72rem"
|
|
1734
|
-
};
|
|
1735
|
-
const crdtTableNameStyles = {
|
|
1736
|
-
fontFamily: "ui-monospace, monospace",
|
|
1737
|
-
fontSize: "0.85rem",
|
|
1738
|
-
color: C.text
|
|
1739
|
-
};
|
|
1740
|
-
const permissionRowStyles = {
|
|
1741
|
-
display: "flex",
|
|
1742
|
-
alignItems: "center",
|
|
1743
|
-
gap: "0.6rem",
|
|
1744
|
-
fontSize: "0.82rem",
|
|
1745
|
-
color: C.textDim
|
|
1746
|
-
};
|
|
1747
|
-
const permissionIconStyles = {
|
|
1748
|
-
color: C.success,
|
|
1749
|
-
fontWeight: 700,
|
|
1750
|
-
fontSize: "0.85rem",
|
|
1751
|
-
lineHeight: 1
|
|
1752
|
-
};
|
|
1753
|
-
const permissionTextStyles = { color: C.textDim };
|
|
1754
|
-
const dataActionsStyles = {
|
|
1755
|
-
display: "flex",
|
|
1756
|
-
gap: "0.4rem"
|
|
1757
|
-
};
|
|
1758
|
-
const dataButtonStyles = {
|
|
1759
|
-
border: `1px solid ${C.border}`,
|
|
1760
|
-
borderRadius: "7px",
|
|
1761
|
-
padding: "0.4rem 0.8rem",
|
|
1762
|
-
backgroundColor: "transparent",
|
|
1763
|
-
color: C.teal,
|
|
1764
|
-
fontSize: "0.78rem",
|
|
1765
|
-
fontWeight: 600,
|
|
1766
|
-
cursor: "pointer",
|
|
1767
|
-
whiteSpace: "nowrap"
|
|
1768
|
-
};
|
|
1769
|
-
const dataStatusSuccessStyles = {
|
|
1770
|
-
fontSize: "0.75rem",
|
|
1771
|
-
color: C.success
|
|
1772
|
-
};
|
|
1773
|
-
const dataStatusErrorStyles = {
|
|
1774
|
-
fontSize: "0.75rem",
|
|
1775
|
-
color: C.error,
|
|
1776
|
-
wordBreak: "break-word"
|
|
1777
|
-
};
|
|
1778
|
-
const dangerZoneStyles = {
|
|
1779
|
-
marginTop: "auto",
|
|
1780
|
-
borderRadius: "10px",
|
|
1781
|
-
border: `1px solid ${C.errorBorder}`,
|
|
1782
|
-
padding: "0.75rem 1rem",
|
|
1783
|
-
background: C.errorBg
|
|
1784
|
-
};
|
|
1785
|
-
const dangerZoneTitleStyles = {
|
|
1786
|
-
fontSize: "0.65rem",
|
|
1787
|
-
fontWeight: 700,
|
|
1788
|
-
letterSpacing: "0.08em",
|
|
1789
|
-
textTransform: "uppercase",
|
|
1790
|
-
color: C.error,
|
|
1791
|
-
marginBottom: "0.5rem"
|
|
1792
|
-
};
|
|
1793
|
-
const dangerZoneRowStyles = {
|
|
1794
|
-
display: "flex",
|
|
1795
|
-
alignItems: "center",
|
|
1796
|
-
justifyContent: "space-between",
|
|
1797
|
-
gap: "1rem"
|
|
1798
|
-
};
|
|
1799
|
-
const dangerZoneDescStyles = {
|
|
1800
|
-
fontSize: "0.75rem",
|
|
1801
|
-
color: C.textMuted,
|
|
1802
|
-
lineHeight: 1.5
|
|
1803
|
-
};
|
|
1804
|
-
const dangerZoneActionsStyles = {
|
|
1805
|
-
display: "flex",
|
|
1806
|
-
gap: "0.4rem",
|
|
1807
|
-
flexShrink: 0
|
|
1808
|
-
};
|
|
1809
|
-
const resetButtonStyles = {
|
|
1810
|
-
flexShrink: 0,
|
|
1811
|
-
border: `1px solid ${C.errorBorder}`,
|
|
1812
|
-
borderRadius: "7px",
|
|
1813
|
-
padding: "0.35rem 0.75rem",
|
|
1814
|
-
backgroundColor: "transparent",
|
|
1815
|
-
color: C.error,
|
|
1816
|
-
fontSize: "0.78rem",
|
|
1817
|
-
fontWeight: 600,
|
|
1818
|
-
cursor: "pointer",
|
|
1819
|
-
whiteSpace: "nowrap"
|
|
1820
|
-
};
|
|
1821
|
-
const resetCancelButtonStyles = {
|
|
1822
|
-
border: `1px solid ${C.border}`,
|
|
1823
|
-
borderRadius: "7px",
|
|
1824
|
-
padding: "0.35rem 0.65rem",
|
|
1825
|
-
backgroundColor: "transparent",
|
|
1826
|
-
color: C.textDim,
|
|
1827
|
-
fontSize: "0.78rem",
|
|
1828
|
-
fontWeight: 600,
|
|
1829
|
-
cursor: "pointer",
|
|
1830
|
-
whiteSpace: "nowrap"
|
|
1831
|
-
};
|
|
1832
|
-
const resetConfirmButtonStyles = {
|
|
1833
|
-
border: "none",
|
|
1834
|
-
borderRadius: "7px",
|
|
1835
|
-
padding: "0.35rem 0.75rem",
|
|
1836
|
-
backgroundColor: C.error,
|
|
1837
|
-
color: "#0e1015",
|
|
1838
|
-
fontSize: "0.78rem",
|
|
1839
|
-
fontWeight: 700,
|
|
1840
|
-
cursor: "pointer",
|
|
1841
|
-
whiteSpace: "nowrap"
|
|
1842
|
-
};
|
|
1843
|
-
const queryRunnerLayoutStyles = {
|
|
1844
|
-
display: "flex",
|
|
1845
|
-
flexDirection: "column",
|
|
1846
|
-
gap: "0.75rem",
|
|
1847
|
-
height: "100%"
|
|
1848
|
-
};
|
|
1849
|
-
const queryToolbarStyles = {
|
|
1850
|
-
display: "flex",
|
|
1851
|
-
alignItems: "center",
|
|
1852
|
-
justifyContent: "space-between",
|
|
1853
|
-
gap: "0.75rem",
|
|
1854
|
-
flexWrap: "wrap"
|
|
1855
|
-
};
|
|
1856
|
-
const targetToggleStyles = {
|
|
1857
|
-
display: "flex",
|
|
1858
|
-
gap: "0",
|
|
1859
|
-
borderRadius: "8px",
|
|
1860
|
-
border: `1px solid ${C.border}`,
|
|
1861
|
-
overflow: "hidden",
|
|
1862
|
-
background: C.bgCard
|
|
1863
|
-
};
|
|
1864
|
-
const queryToolbarRightStyles = {
|
|
1865
|
-
display: "flex",
|
|
1866
|
-
alignItems: "center",
|
|
1867
|
-
gap: "0.6rem"
|
|
1868
|
-
};
|
|
1869
|
-
const noInstanceWarningStyles = {
|
|
1870
|
-
fontSize: "0.75rem",
|
|
1871
|
-
color: C.amber,
|
|
1872
|
-
fontWeight: 500
|
|
1873
|
-
};
|
|
1874
|
-
const shortcutHintStyles = {
|
|
1875
|
-
fontSize: "0.72rem",
|
|
1876
|
-
color: C.textMuted,
|
|
1877
|
-
fontFamily: "ui-monospace, monospace",
|
|
1878
|
-
padding: "0.2rem 0.5rem",
|
|
1879
|
-
borderRadius: "5px",
|
|
1880
|
-
border: `1px solid ${C.border}`,
|
|
1881
|
-
background: C.bgCard
|
|
1882
|
-
};
|
|
1883
|
-
const editorWrapperStyles = {
|
|
1884
|
-
borderRadius: "10px",
|
|
1885
|
-
border: `1px solid ${C.border}`,
|
|
1886
|
-
overflow: "hidden",
|
|
1887
|
-
background: C.bgInput
|
|
1888
|
-
};
|
|
1889
|
-
const textareaStyles = {
|
|
1890
|
-
width: "100%",
|
|
1891
|
-
minHeight: "9rem",
|
|
1892
|
-
resize: "vertical",
|
|
1893
|
-
border: "none",
|
|
1894
|
-
padding: "0.85rem 1rem",
|
|
1895
|
-
backgroundColor: "transparent",
|
|
1896
|
-
color: C.text,
|
|
1897
|
-
fontSize: "0.875rem",
|
|
1898
|
-
fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
|
|
1899
|
-
lineHeight: 1.6,
|
|
1900
|
-
outline: "none",
|
|
1901
|
-
boxSizing: "border-box"
|
|
1902
|
-
};
|
|
1903
|
-
const helperTextStyles = {
|
|
1904
|
-
fontSize: "0.75rem",
|
|
1905
|
-
lineHeight: 1.5,
|
|
1906
|
-
color: C.textMuted
|
|
1907
|
-
};
|
|
1908
|
-
const resultPanelStyles = {
|
|
1909
|
-
display: "flex",
|
|
1910
|
-
flexDirection: "column",
|
|
1911
|
-
gap: "0.6rem",
|
|
1912
|
-
borderRadius: "10px",
|
|
1913
|
-
border: `1px solid ${C.border}`,
|
|
1914
|
-
overflow: "hidden",
|
|
1915
|
-
background: C.bgPanel
|
|
1916
|
-
};
|
|
1917
|
-
const errorPanelStyles = {
|
|
1918
|
-
display: "flex",
|
|
1919
|
-
flexDirection: "column",
|
|
1920
|
-
gap: "0.6rem",
|
|
1921
|
-
padding: "0.85rem 1rem",
|
|
1922
|
-
borderRadius: "10px",
|
|
1923
|
-
border: `1px solid ${C.errorBorder}`,
|
|
1924
|
-
background: C.errorBg
|
|
1925
|
-
};
|
|
1926
|
-
const resultHeaderStyles = {
|
|
1927
|
-
display: "flex",
|
|
1928
|
-
alignItems: "center",
|
|
1929
|
-
gap: "0.6rem",
|
|
1930
|
-
padding: "0.6rem 0.85rem",
|
|
1931
|
-
borderBottom: `1px solid ${C.border}`,
|
|
1932
|
-
background: C.bgCard
|
|
1933
|
-
};
|
|
1934
|
-
const successBadgeStyles = {
|
|
1935
|
-
fontSize: "0.72rem",
|
|
1936
|
-
fontWeight: 700,
|
|
1937
|
-
color: C.success,
|
|
1938
|
-
backgroundColor: C.successBg,
|
|
1939
|
-
borderRadius: "5px",
|
|
1940
|
-
padding: "0.15rem 0.5rem",
|
|
1941
|
-
fontFamily: "ui-monospace, monospace"
|
|
1942
|
-
};
|
|
1943
|
-
const errorBadgeStyles = {
|
|
1944
|
-
fontSize: "0.72rem",
|
|
1945
|
-
fontWeight: 700,
|
|
1946
|
-
color: C.error,
|
|
1947
|
-
backgroundColor: C.errorBg,
|
|
1948
|
-
borderRadius: "5px",
|
|
1949
|
-
padding: "0.15rem 0.5rem",
|
|
1950
|
-
fontFamily: "ui-monospace, monospace"
|
|
1951
|
-
};
|
|
1952
|
-
const resultMetaStyles = {
|
|
1953
|
-
fontSize: "0.72rem",
|
|
1954
|
-
color: C.textMuted,
|
|
1955
|
-
fontFamily: "ui-monospace, monospace"
|
|
1956
|
-
};
|
|
1957
|
-
const resultEmptyStyles = {
|
|
1958
|
-
padding: "1.5rem",
|
|
1959
|
-
fontSize: "0.82rem",
|
|
1960
|
-
color: C.textMuted,
|
|
1961
|
-
fontStyle: "italic",
|
|
1962
|
-
textAlign: "center"
|
|
1963
|
-
};
|
|
1964
|
-
const resultRawStyles = {
|
|
1965
|
-
margin: 0,
|
|
1966
|
-
padding: "0.85rem 1rem",
|
|
1967
|
-
overflowX: "auto",
|
|
1968
|
-
whiteSpace: "pre-wrap",
|
|
1969
|
-
wordBreak: "break-word",
|
|
1970
|
-
fontSize: "0.8rem",
|
|
1971
|
-
lineHeight: 1.5,
|
|
1972
|
-
color: C.text,
|
|
1973
|
-
fontFamily: "ui-monospace, monospace"
|
|
1974
|
-
};
|
|
1975
|
-
const errorMessageStyles = {
|
|
1976
|
-
margin: 0,
|
|
1977
|
-
fontSize: "0.82rem",
|
|
1978
|
-
lineHeight: 1.6,
|
|
1979
|
-
color: C.error,
|
|
1980
|
-
fontFamily: "ui-monospace, monospace",
|
|
1981
|
-
whiteSpace: "pre-wrap",
|
|
1982
|
-
wordBreak: "break-word"
|
|
1983
|
-
};
|
|
1984
|
-
const tableWrapperStyles = {
|
|
1985
|
-
overflowX: "auto",
|
|
1986
|
-
maxHeight: "320px",
|
|
1987
|
-
overflowY: "auto"
|
|
1988
|
-
};
|
|
1989
|
-
const tableStyles = {
|
|
1990
|
-
width: "100%",
|
|
1991
|
-
borderCollapse: "collapse",
|
|
1992
|
-
fontSize: "0.8rem",
|
|
1993
|
-
fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace"
|
|
1994
|
-
};
|
|
1995
|
-
const thStyles = {
|
|
1996
|
-
padding: "0.5rem 0.85rem",
|
|
1997
|
-
textAlign: "left",
|
|
1998
|
-
fontWeight: 600,
|
|
1999
|
-
fontSize: "0.7rem",
|
|
2000
|
-
letterSpacing: "0.05em",
|
|
2001
|
-
textTransform: "uppercase",
|
|
2002
|
-
color: C.textMuted,
|
|
2003
|
-
borderBottom: `1px solid ${C.border}`,
|
|
2004
|
-
borderRight: `1px solid ${C.border}`,
|
|
2005
|
-
background: C.bgCard,
|
|
2006
|
-
whiteSpace: "nowrap",
|
|
2007
|
-
position: "sticky",
|
|
2008
|
-
top: 0
|
|
2009
|
-
};
|
|
2010
|
-
const thRowNumStyles = {
|
|
2011
|
-
...thStyles,
|
|
2012
|
-
color: C.textMuted,
|
|
2013
|
-
opacity: .5,
|
|
2014
|
-
width: "2.5rem",
|
|
2015
|
-
textAlign: "right"
|
|
2016
|
-
};
|
|
2017
|
-
const trStyles = { background: "transparent" };
|
|
2018
|
-
const trAltStyles = { background: C.tealGlow };
|
|
2019
|
-
const tdStyles = {
|
|
2020
|
-
padding: "0.45rem 0.85rem",
|
|
2021
|
-
borderBottom: `1px solid ${C.border}`,
|
|
2022
|
-
borderRight: `1px solid ${C.border}`,
|
|
2023
|
-
color: C.text,
|
|
2024
|
-
whiteSpace: "nowrap",
|
|
2025
|
-
maxWidth: "300px",
|
|
2026
|
-
overflow: "hidden",
|
|
2027
|
-
textOverflow: "ellipsis"
|
|
2028
|
-
};
|
|
2029
|
-
const tdRowNumStyles = {
|
|
2030
|
-
...tdStyles,
|
|
2031
|
-
color: C.textMuted,
|
|
2032
|
-
opacity: .5,
|
|
2033
|
-
textAlign: "right",
|
|
2034
|
-
userSelect: "none"
|
|
2035
|
-
};
|
|
2036
|
-
const nullValueStyles = {
|
|
2037
|
-
color: C.textMuted,
|
|
2038
|
-
fontStyle: "italic",
|
|
2039
|
-
opacity: .6
|
|
2040
|
-
};
|
|
2041
|
-
const jsonValueStyles = { color: C.textDim };
|
|
2042
|
-
function getTabButtonStyles(isActive) {
|
|
2043
|
-
return {
|
|
2044
|
-
display: "flex",
|
|
2045
|
-
alignItems: "center",
|
|
2046
|
-
gap: "0.5rem",
|
|
2047
|
-
width: "100%",
|
|
2048
|
-
border: "none",
|
|
2049
|
-
borderRadius: "7px",
|
|
2050
|
-
padding: "0.6rem 0.75rem",
|
|
2051
|
-
background: isActive ? C.tealDim : "transparent",
|
|
2052
|
-
color: isActive ? C.teal : C.textDim,
|
|
2053
|
-
fontSize: "0.82rem",
|
|
2054
|
-
fontWeight: isActive ? 700 : 500,
|
|
2055
|
-
textAlign: "left",
|
|
2056
|
-
cursor: "pointer",
|
|
2057
|
-
transition: "background 0.15s",
|
|
2058
|
-
borderLeft: isActive ? `2px solid ${C.teal}` : "2px solid transparent"
|
|
2059
|
-
};
|
|
2060
|
-
}
|
|
2061
|
-
function getTargetButtonStyles(isActive) {
|
|
2062
|
-
return {
|
|
2063
|
-
border: "none",
|
|
2064
|
-
borderRight: `1px solid ${C.border}`,
|
|
2065
|
-
padding: "0.45rem 0.85rem",
|
|
2066
|
-
background: isActive ? C.tealDim : "transparent",
|
|
2067
|
-
color: isActive ? C.teal : C.textMuted,
|
|
2068
|
-
fontSize: "0.78rem",
|
|
2069
|
-
fontWeight: isActive ? 700 : 500,
|
|
2070
|
-
cursor: "pointer",
|
|
2071
|
-
fontFamily: "ui-monospace, monospace",
|
|
2072
|
-
transition: "background 0.1s",
|
|
2073
|
-
whiteSpace: "nowrap"
|
|
2074
|
-
};
|
|
2075
|
-
}
|
|
2076
|
-
function runButtonStyles(enabled, running) {
|
|
2077
|
-
return {
|
|
2078
|
-
display: "inline-flex",
|
|
2079
|
-
alignItems: "center",
|
|
2080
|
-
gap: "0.4rem",
|
|
2081
|
-
border: "none",
|
|
2082
|
-
borderRadius: "7px",
|
|
2083
|
-
padding: "0.45rem 0.9rem",
|
|
2084
|
-
background: enabled ? C.teal : C.bgCard,
|
|
2085
|
-
color: enabled ? "#0e1015" : C.textMuted,
|
|
2086
|
-
fontSize: "0.82rem",
|
|
2087
|
-
fontWeight: 700,
|
|
2088
|
-
fontFamily: "ui-monospace, monospace",
|
|
2089
|
-
cursor: enabled ? "pointer" : "not-allowed",
|
|
2090
|
-
opacity: running ? .75 : 1,
|
|
2091
|
-
transition: "background 0.15s",
|
|
2092
|
-
whiteSpace: "nowrap"
|
|
2093
|
-
};
|
|
2094
|
-
}
|
|
2095
|
-
const runningDotStyles = {
|
|
2096
|
-
width: "6px",
|
|
2097
|
-
height: "6px",
|
|
2098
|
-
borderRadius: "50%",
|
|
2099
|
-
backgroundColor: "currentColor"
|
|
2100
|
-
};
|
|
2101
|
-
const schemaLayoutStyles = {
|
|
2102
|
-
display: "flex",
|
|
2103
|
-
flexDirection: "column",
|
|
2104
|
-
gap: "1.5rem"
|
|
2105
|
-
};
|
|
2106
|
-
const schemaSectionStyles = {
|
|
2107
|
-
display: "flex",
|
|
2108
|
-
flexDirection: "column",
|
|
2109
|
-
gap: "0.65rem"
|
|
2110
|
-
};
|
|
2111
|
-
const schemaSectionHeaderStyles = {
|
|
2112
|
-
display: "flex",
|
|
2113
|
-
alignItems: "center",
|
|
2114
|
-
gap: "0.6rem"
|
|
2115
|
-
};
|
|
2116
|
-
const schemaSectionTitleStyles = {
|
|
2117
|
-
fontSize: "0.72rem",
|
|
2118
|
-
fontWeight: 700,
|
|
2119
|
-
letterSpacing: "0.08em",
|
|
2120
|
-
textTransform: "uppercase",
|
|
2121
|
-
color: C.textMuted
|
|
2122
|
-
};
|
|
2123
|
-
const schemaBadgeStyles = {
|
|
2124
|
-
fontSize: "0.68rem",
|
|
2125
|
-
fontWeight: 700,
|
|
2126
|
-
color: C.teal,
|
|
2127
|
-
backgroundColor: C.tealDim,
|
|
2128
|
-
borderRadius: "4px",
|
|
2129
|
-
padding: "0.1rem 0.4rem",
|
|
2130
|
-
fontFamily: "ui-monospace, monospace"
|
|
2131
|
-
};
|
|
2132
|
-
const schemaMigrationsMetaStyles = {
|
|
2133
|
-
display: "flex",
|
|
2134
|
-
alignItems: "center",
|
|
2135
|
-
gap: "0.5rem",
|
|
2136
|
-
marginLeft: "auto"
|
|
2137
|
-
};
|
|
2138
|
-
const schemaVersionChipStyles = {
|
|
2139
|
-
fontSize: "0.68rem",
|
|
2140
|
-
fontFamily: "ui-monospace, monospace",
|
|
2141
|
-
color: C.textMuted,
|
|
2142
|
-
backgroundColor: C.bgCard,
|
|
2143
|
-
border: `1px solid ${C.border}`,
|
|
2144
|
-
borderRadius: "4px",
|
|
2145
|
-
padding: "0.1rem 0.5rem"
|
|
2146
|
-
};
|
|
2147
|
-
const schemaTableGridStyles = {
|
|
2148
|
-
borderRadius: "10px",
|
|
2149
|
-
border: `1px solid ${C.border}`,
|
|
2150
|
-
overflow: "hidden"
|
|
2151
|
-
};
|
|
2152
|
-
const schemaTableHeaderRowStyles = {
|
|
2153
|
-
display: "grid",
|
|
2154
|
-
gridTemplateColumns: "1fr 1fr 90px",
|
|
2155
|
-
gap: 0,
|
|
2156
|
-
backgroundColor: C.bgCard,
|
|
2157
|
-
borderBottom: `1px solid ${C.border}`
|
|
2158
|
-
};
|
|
2159
|
-
const schemaColHeaderStyles = {
|
|
2160
|
-
padding: "0.5rem 0.85rem",
|
|
2161
|
-
fontSize: "0.68rem",
|
|
2162
|
-
fontWeight: 700,
|
|
2163
|
-
letterSpacing: "0.07em",
|
|
2164
|
-
textTransform: "uppercase",
|
|
2165
|
-
color: C.textMuted,
|
|
2166
|
-
borderRight: `1px solid ${C.border}`
|
|
2167
|
-
};
|
|
2168
|
-
const schemaTableRowStyles = {
|
|
2169
|
-
display: "grid",
|
|
2170
|
-
gridTemplateColumns: "1fr 1fr 90px",
|
|
2171
|
-
gap: 0,
|
|
2172
|
-
borderBottom: `1px solid ${C.border}`
|
|
2173
|
-
};
|
|
2174
|
-
const schemaTableNameStyles = {
|
|
2175
|
-
display: "flex",
|
|
2176
|
-
alignItems: "center",
|
|
2177
|
-
gap: "0.5rem",
|
|
2178
|
-
padding: "0.6rem 0.85rem",
|
|
2179
|
-
fontSize: "0.82rem",
|
|
2180
|
-
fontFamily: "ui-monospace, monospace",
|
|
2181
|
-
color: C.text,
|
|
2182
|
-
borderRight: `1px solid ${C.border}`
|
|
2183
|
-
};
|
|
2184
|
-
const schemaTableIconStyles = {
|
|
2185
|
-
color: C.teal,
|
|
2186
|
-
fontSize: "0.68rem",
|
|
2187
|
-
opacity: .8
|
|
2188
|
-
};
|
|
2189
|
-
const schemaCrdtNameStyles = {
|
|
2190
|
-
display: "flex",
|
|
2191
|
-
alignItems: "center",
|
|
2192
|
-
padding: "0.6rem 0.85rem",
|
|
2193
|
-
fontSize: "0.82rem",
|
|
2194
|
-
fontFamily: "ui-monospace, monospace",
|
|
2195
|
-
color: C.textDim,
|
|
2196
|
-
borderRight: `1px solid ${C.border}`
|
|
2197
|
-
};
|
|
2198
|
-
const schemaStatusCellStyles = {
|
|
2199
|
-
display: "flex",
|
|
2200
|
-
alignItems: "center",
|
|
2201
|
-
justifyContent: "center",
|
|
2202
|
-
padding: "0.6rem 0.5rem"
|
|
2203
|
-
};
|
|
2204
|
-
const schemaActiveTagStyles = {
|
|
2205
|
-
fontSize: "0.68rem",
|
|
2206
|
-
fontWeight: 700,
|
|
2207
|
-
color: C.success,
|
|
2208
|
-
backgroundColor: C.successBg,
|
|
2209
|
-
borderRadius: "4px",
|
|
2210
|
-
padding: "0.15rem 0.45rem",
|
|
2211
|
-
fontFamily: "ui-monospace, monospace"
|
|
2212
|
-
};
|
|
2213
|
-
const schemaEmptyStyles = {
|
|
2214
|
-
fontSize: "0.82rem",
|
|
2215
|
-
color: C.textMuted,
|
|
2216
|
-
fontStyle: "italic"
|
|
2217
|
-
};
|
|
2218
|
-
const migrationListStyles = {
|
|
2219
|
-
display: "flex",
|
|
2220
|
-
flexDirection: "column",
|
|
2221
|
-
gap: "0.35rem"
|
|
2222
|
-
};
|
|
2223
|
-
function getMigrationRowStyles(applied) {
|
|
2224
|
-
return {
|
|
2225
|
-
display: "grid",
|
|
2226
|
-
gridTemplateColumns: "3.5rem 1fr 70px",
|
|
2227
|
-
alignItems: "center",
|
|
2228
|
-
gap: "0.75rem",
|
|
2229
|
-
padding: "0.55rem 0.85rem",
|
|
2230
|
-
borderRadius: "8px",
|
|
2231
|
-
background: applied ? C.bgCard : "transparent",
|
|
2232
|
-
border: `1px solid ${applied ? C.border : C.borderLight}`,
|
|
2233
|
-
opacity: applied ? 1 : .55
|
|
2234
|
-
};
|
|
2235
|
-
}
|
|
2236
|
-
const migrationVersionStyles = {
|
|
2237
|
-
fontSize: "0.78rem",
|
|
2238
|
-
fontWeight: 700,
|
|
2239
|
-
fontFamily: "ui-monospace, monospace",
|
|
2240
|
-
color: C.textDim
|
|
2241
|
-
};
|
|
2242
|
-
const migrationBarTrackStyles = {
|
|
2243
|
-
height: "4px",
|
|
2244
|
-
borderRadius: "2px",
|
|
2245
|
-
backgroundColor: C.border,
|
|
2246
|
-
overflow: "hidden"
|
|
2247
|
-
};
|
|
2248
|
-
function getMigrationBarFillStyles(applied) {
|
|
2249
|
-
return {
|
|
2250
|
-
height: "100%",
|
|
2251
|
-
width: applied ? "100%" : "0%",
|
|
2252
|
-
borderRadius: "2px",
|
|
2253
|
-
backgroundColor: C.teal,
|
|
2254
|
-
transition: "width 0.3s ease"
|
|
2255
|
-
};
|
|
2256
|
-
}
|
|
2257
|
-
function getMigrationTagStyles(applied, isCurrent) {
|
|
2258
|
-
if (isCurrent) return {
|
|
2259
|
-
fontSize: "0.68rem",
|
|
2260
|
-
fontWeight: 700,
|
|
2261
|
-
color: C.teal,
|
|
2262
|
-
backgroundColor: C.tealDim,
|
|
2263
|
-
borderRadius: "4px",
|
|
2264
|
-
padding: "0.15rem 0.45rem",
|
|
2265
|
-
fontFamily: "ui-monospace, monospace",
|
|
2266
|
-
textAlign: "center"
|
|
2267
|
-
};
|
|
2268
|
-
if (applied) return {
|
|
2269
|
-
fontSize: "0.68rem",
|
|
2270
|
-
fontWeight: 600,
|
|
2271
|
-
color: C.success,
|
|
2272
|
-
backgroundColor: C.successBg,
|
|
2273
|
-
borderRadius: "4px",
|
|
2274
|
-
padding: "0.15rem 0.45rem",
|
|
2275
|
-
fontFamily: "ui-monospace, monospace",
|
|
2276
|
-
textAlign: "center"
|
|
2277
|
-
};
|
|
2278
|
-
return {
|
|
2279
|
-
fontSize: "0.68rem",
|
|
2280
|
-
fontWeight: 600,
|
|
2281
|
-
color: C.amber,
|
|
2282
|
-
backgroundColor: "rgba(251,191,36,0.08)",
|
|
2283
|
-
borderRadius: "4px",
|
|
2284
|
-
padding: "0.15rem 0.45rem",
|
|
2285
|
-
fontFamily: "ui-monospace, monospace",
|
|
2286
|
-
textAlign: "center"
|
|
2287
|
-
};
|
|
2288
|
-
}
|
|
2289
|
-
const liveQueryHeaderRowStyles = {
|
|
2290
|
-
display: "grid",
|
|
2291
|
-
gridTemplateColumns: "minmax(0, 1fr) 220px 110px",
|
|
2292
|
-
gap: 0,
|
|
2293
|
-
backgroundColor: C.bgCard,
|
|
2294
|
-
borderBottom: `1px solid ${C.border}`
|
|
2295
|
-
};
|
|
2296
|
-
const liveQueryRowStyles = {
|
|
2297
|
-
display: "grid",
|
|
2298
|
-
gridTemplateColumns: "minmax(0, 1fr) 220px 110px",
|
|
2299
|
-
gap: 0,
|
|
2300
|
-
borderBottom: `1px solid ${C.border}`
|
|
2301
|
-
};
|
|
2302
|
-
const liveQuerySqlStyles = {
|
|
2303
|
-
padding: "0.6rem 0.85rem",
|
|
2304
|
-
fontSize: "0.78rem",
|
|
2305
|
-
fontFamily: "ui-monospace, monospace",
|
|
2306
|
-
color: C.text,
|
|
2307
|
-
borderRight: `1px solid ${C.border}`,
|
|
2308
|
-
whiteSpace: "pre-wrap",
|
|
2309
|
-
overflowWrap: "anywhere"
|
|
2310
|
-
};
|
|
2311
|
-
const liveQueryParametersStyles = {
|
|
2312
|
-
padding: "0.6rem 0.85rem",
|
|
2313
|
-
fontSize: "0.78rem",
|
|
2314
|
-
fontFamily: "ui-monospace, monospace",
|
|
2315
|
-
color: C.textDim,
|
|
2316
|
-
borderRight: `1px solid ${C.border}`,
|
|
2317
|
-
whiteSpace: "pre-wrap",
|
|
2318
|
-
overflowWrap: "anywhere"
|
|
2319
|
-
};
|
|
2320
|
-
const liveQueryIdleTagStyles = {
|
|
2321
|
-
fontSize: "0.68rem",
|
|
2322
|
-
fontWeight: 700,
|
|
2323
|
-
color: C.textMuted,
|
|
2324
|
-
backgroundColor: C.bgCard,
|
|
2325
|
-
border: `1px solid ${C.border}`,
|
|
2326
|
-
borderRadius: "4px",
|
|
2327
|
-
padding: "0.15rem 0.45rem",
|
|
2328
|
-
fontFamily: "ui-monospace, monospace"
|
|
2329
|
-
};
|
|
2330
|
-
const eventLogLayoutStyles = {
|
|
2331
|
-
display: "flex",
|
|
2332
|
-
flexDirection: "column",
|
|
2333
|
-
gap: "0.75rem",
|
|
2334
|
-
height: "100%"
|
|
2335
|
-
};
|
|
2336
|
-
const eventLogToolbarStyles = {
|
|
2337
|
-
display: "flex",
|
|
2338
|
-
alignItems: "center",
|
|
2339
|
-
gap: "0.5rem",
|
|
2340
|
-
flexWrap: "wrap",
|
|
2341
|
-
flexShrink: 0
|
|
2342
|
-
};
|
|
2343
|
-
const eventLogFilterSelectStyles = {
|
|
2344
|
-
borderRadius: "7px",
|
|
2345
|
-
border: `1px solid ${C.border}`,
|
|
2346
|
-
padding: "0.35rem 0.6rem",
|
|
2347
|
-
backgroundColor: C.bgCard,
|
|
2348
|
-
color: C.text,
|
|
2349
|
-
fontSize: "0.78rem",
|
|
2350
|
-
fontFamily: "ui-monospace, monospace",
|
|
2351
|
-
cursor: "pointer"
|
|
2352
|
-
};
|
|
2353
|
-
const eventLogRefreshButtonStyles = {
|
|
2354
|
-
border: `1px solid ${C.border}`,
|
|
2355
|
-
borderRadius: "7px",
|
|
2356
|
-
padding: "0.35rem 0.7rem",
|
|
2357
|
-
backgroundColor: "transparent",
|
|
2358
|
-
color: C.textDim,
|
|
2359
|
-
fontSize: "0.78rem",
|
|
2360
|
-
fontFamily: "ui-monospace, monospace",
|
|
2361
|
-
cursor: "pointer"
|
|
2362
|
-
};
|
|
2363
|
-
const eventLogCountStyles = {
|
|
2364
|
-
marginLeft: "auto",
|
|
2365
|
-
fontSize: "0.72rem",
|
|
2366
|
-
fontFamily: "ui-monospace, monospace",
|
|
2367
|
-
color: C.textMuted
|
|
2368
|
-
};
|
|
2369
|
-
const eventLogEmptyStyles = {
|
|
2370
|
-
padding: "2rem",
|
|
2371
|
-
textAlign: "center",
|
|
2372
|
-
fontSize: "0.82rem",
|
|
2373
|
-
color: C.textMuted,
|
|
2374
|
-
fontStyle: "italic"
|
|
2375
|
-
};
|
|
2376
|
-
const eventLogListStyles = {
|
|
2377
|
-
display: "flex",
|
|
2378
|
-
flexDirection: "column",
|
|
2379
|
-
gap: "0.25rem",
|
|
2380
|
-
overflowY: "auto",
|
|
2381
|
-
flex: 1
|
|
2382
|
-
};
|
|
2383
|
-
function getEventRowStyles(isExpanded) {
|
|
2384
|
-
return {
|
|
2385
|
-
borderRadius: "8px",
|
|
2386
|
-
border: `1px solid ${isExpanded ? `${C.teal}40` : C.border}`,
|
|
2387
|
-
background: isExpanded ? C.tealGlow : C.bgCard,
|
|
2388
|
-
overflow: "hidden",
|
|
2389
|
-
flexShrink: 0
|
|
2390
|
-
};
|
|
2391
|
-
}
|
|
2392
|
-
const eventRowHeaderStyles = {
|
|
2393
|
-
display: "flex",
|
|
2394
|
-
alignItems: "center",
|
|
2395
|
-
gap: "0.5rem",
|
|
2396
|
-
width: "100%",
|
|
2397
|
-
padding: "0.5rem 0.75rem",
|
|
2398
|
-
background: "transparent",
|
|
2399
|
-
border: "none",
|
|
2400
|
-
cursor: "pointer",
|
|
2401
|
-
textAlign: "left",
|
|
2402
|
-
flexWrap: "wrap"
|
|
2403
|
-
};
|
|
2404
|
-
const eventSyncIdStyles = {
|
|
2405
|
-
fontSize: "0.7rem",
|
|
2406
|
-
fontFamily: "ui-monospace, monospace",
|
|
2407
|
-
color: C.textMuted,
|
|
2408
|
-
minWidth: "3.5rem"
|
|
2409
|
-
};
|
|
2410
|
-
const eventDatasetStyles = {
|
|
2411
|
-
fontSize: "0.8rem",
|
|
2412
|
-
fontFamily: "ui-monospace, monospace",
|
|
2413
|
-
color: C.text,
|
|
2414
|
-
fontWeight: 600
|
|
2415
|
-
};
|
|
2416
|
-
const eventItemIdStyles = {
|
|
2417
|
-
fontSize: "0.75rem",
|
|
2418
|
-
fontFamily: "ui-monospace, monospace",
|
|
2419
|
-
color: C.textMuted,
|
|
2420
|
-
flex: 1,
|
|
2421
|
-
overflow: "hidden",
|
|
2422
|
-
textOverflow: "ellipsis",
|
|
2423
|
-
whiteSpace: "nowrap",
|
|
2424
|
-
minWidth: 0
|
|
2425
|
-
};
|
|
2426
|
-
const eventTimestampStyles = {
|
|
2427
|
-
fontSize: "0.7rem",
|
|
2428
|
-
fontFamily: "ui-monospace, monospace",
|
|
2429
|
-
color: C.textMuted,
|
|
2430
|
-
marginLeft: "auto"
|
|
2431
|
-
};
|
|
2432
|
-
const eventChevronStyles = {
|
|
2433
|
-
fontSize: "0.6rem",
|
|
2434
|
-
color: C.textMuted,
|
|
2435
|
-
marginLeft: "0.25rem"
|
|
2436
|
-
};
|
|
2437
|
-
const eventPayloadStyles = {
|
|
2438
|
-
borderTop: `1px solid ${C.border}`,
|
|
2439
|
-
padding: "0.6rem 0.75rem"
|
|
2440
|
-
};
|
|
2441
|
-
const eventPayloadMetaStyles = {
|
|
2442
|
-
display: "flex",
|
|
2443
|
-
gap: "0.75rem",
|
|
2444
|
-
marginBottom: "0.5rem"
|
|
2445
|
-
};
|
|
2446
|
-
const eventMetaItemStyles = {
|
|
2447
|
-
fontSize: "0.68rem",
|
|
2448
|
-
fontFamily: "ui-monospace, monospace",
|
|
2449
|
-
color: C.textMuted
|
|
2450
|
-
};
|
|
2451
|
-
const eventPayloadPreStyles = {
|
|
2452
|
-
margin: 0,
|
|
2453
|
-
fontSize: "0.78rem",
|
|
2454
|
-
fontFamily: "ui-monospace, monospace",
|
|
2455
|
-
color: C.text,
|
|
2456
|
-
lineHeight: 1.5,
|
|
2457
|
-
whiteSpace: "pre-wrap",
|
|
2458
|
-
wordBreak: "break-word"
|
|
2459
|
-
};
|
|
2460
|
-
const loadMoreButtonStyles = {
|
|
2461
|
-
width: "100%",
|
|
2462
|
-
border: `1px solid ${C.border}`,
|
|
2463
|
-
borderRadius: "8px",
|
|
2464
|
-
padding: "0.6rem",
|
|
2465
|
-
backgroundColor: "transparent",
|
|
2466
|
-
color: C.textDim,
|
|
2467
|
-
fontSize: "0.78rem",
|
|
2468
|
-
fontFamily: "ui-monospace, monospace",
|
|
2469
|
-
cursor: "pointer",
|
|
2470
|
-
flexShrink: 0
|
|
2471
|
-
};
|
|
2472
|
-
const eventTypeBadgeBase = {
|
|
2473
|
-
fontSize: "0.65rem",
|
|
2474
|
-
fontWeight: 700,
|
|
2475
|
-
borderRadius: "4px",
|
|
2476
|
-
padding: "0.1rem 0.4rem",
|
|
2477
|
-
fontFamily: "ui-monospace, monospace",
|
|
2478
|
-
whiteSpace: "nowrap"
|
|
2479
|
-
};
|
|
2480
|
-
const eventTypeCreateStyles = {
|
|
2481
|
-
...eventTypeBadgeBase,
|
|
2482
|
-
color: C.teal,
|
|
2483
|
-
backgroundColor: C.tealDim
|
|
2484
|
-
};
|
|
2485
|
-
const eventTypeUpdateStyles = {
|
|
2486
|
-
...eventTypeBadgeBase,
|
|
2487
|
-
color: "#a78bfa",
|
|
2488
|
-
backgroundColor: "rgba(167,139,250,0.12)"
|
|
2489
|
-
};
|
|
2490
|
-
const eventTypeDeleteStyles = {
|
|
2491
|
-
...eventTypeBadgeBase,
|
|
2492
|
-
color: C.error,
|
|
2493
|
-
backgroundColor: "rgba(248,113,113,0.12)"
|
|
2494
|
-
};
|
|
2495
|
-
const eventOriginOwnStyles = {
|
|
2496
|
-
...eventTypeBadgeBase,
|
|
2497
|
-
color: C.success,
|
|
2498
|
-
backgroundColor: C.successBg
|
|
2499
|
-
};
|
|
2500
|
-
const eventOriginRemoteStyles = {
|
|
2501
|
-
...eventTypeBadgeBase,
|
|
2502
|
-
color: C.amber,
|
|
2503
|
-
backgroundColor: "rgba(251,191,36,0.1)"
|
|
2504
|
-
};
|
|
2505
|
-
const eventOriginLocalStyles = {
|
|
2506
|
-
...eventTypeBadgeBase,
|
|
2507
|
-
color: C.textDim,
|
|
2508
|
-
backgroundColor: C.bgCard,
|
|
2509
|
-
border: `1px solid ${C.border}`
|
|
2510
|
-
};
|
|
2511
|
-
const eventStatusAppliedStyles = {
|
|
2512
|
-
...eventTypeBadgeBase,
|
|
2513
|
-
color: C.success,
|
|
2514
|
-
backgroundColor: C.successBg
|
|
2515
|
-
};
|
|
2516
|
-
const eventStatusPendingStyles = {
|
|
2517
|
-
...eventTypeBadgeBase,
|
|
2518
|
-
color: C.amber,
|
|
2519
|
-
backgroundColor: "rgba(251,191,36,0.1)"
|
|
2520
|
-
};
|
|
2521
|
-
const eventStatusFailedStyles = {
|
|
2522
|
-
...eventTypeBadgeBase,
|
|
2523
|
-
color: C.error,
|
|
2524
|
-
backgroundColor: C.errorBg
|
|
2525
|
-
};
|
|
2526
|
-
const eventStatusSkippedStyles = {
|
|
2527
|
-
...eventTypeBadgeBase,
|
|
2528
|
-
color: C.textMuted,
|
|
2529
|
-
backgroundColor: C.bgCard
|
|
2530
|
-
};
|
|
2531
1712
|
//#endregion
|
|
2532
1713
|
export { SQLiteSyncDevtools };
|
|
2533
1714
|
|