@sqlrooms/deck 0.29.0-rc.10 → 0.29.0-rc.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/README.md +88 -16
  2. package/dist/BlockMapSettings.d.ts.map +1 -1
  3. package/dist/BlockMapSettings.js +4 -16
  4. package/dist/BlockMapSettings.js.map +1 -1
  5. package/dist/DashboardMapSettings.d.ts.map +1 -1
  6. package/dist/DashboardMapSettings.js +7 -10
  7. package/dist/DashboardMapSettings.js.map +1 -1
  8. package/dist/DeckJsonMap.d.ts.map +1 -1
  9. package/dist/DeckJsonMap.js +20 -18
  10. package/dist/DeckJsonMap.js.map +1 -1
  11. package/dist/DeckJsonMapSpec.d.ts +916 -53
  12. package/dist/DeckJsonMapSpec.d.ts.map +1 -1
  13. package/dist/DeckJsonMapSpec.js +9 -0
  14. package/dist/DeckJsonMapSpec.js.map +1 -1
  15. package/dist/DeckMapDefaultStylesProvider.d.ts +3 -4
  16. package/dist/DeckMapDefaultStylesProvider.d.ts.map +1 -1
  17. package/dist/DeckMapDefaultStylesProvider.js +13 -7
  18. package/dist/DeckMapDefaultStylesProvider.js.map +1 -1
  19. package/dist/DeckMapSurface.d.ts +1 -1
  20. package/dist/DeckMapSurface.js +1 -1
  21. package/dist/DeckMapSurface.js.map +1 -1
  22. package/dist/MapSettings.d.ts +14 -0
  23. package/dist/MapSettings.d.ts.map +1 -1
  24. package/dist/MapSettings.js +555 -186
  25. package/dist/MapSettings.js.map +1 -1
  26. package/dist/MapSettingsControls.d.ts +8 -1
  27. package/dist/MapSettingsControls.d.ts.map +1 -1
  28. package/dist/MapSettingsControls.js +24 -2
  29. package/dist/MapSettingsControls.js.map +1 -1
  30. package/dist/ai.d.ts +19 -5
  31. package/dist/ai.d.ts.map +1 -1
  32. package/dist/ai.js +63 -112
  33. package/dist/ai.js.map +1 -1
  34. package/dist/aiNormalize.d.ts +31 -0
  35. package/dist/aiNormalize.d.ts.map +1 -0
  36. package/dist/aiNormalize.js +630 -0
  37. package/dist/aiNormalize.js.map +1 -0
  38. package/dist/block.d.ts +1 -1
  39. package/dist/block.d.ts.map +1 -1
  40. package/dist/block.js +1 -1
  41. package/dist/block.js.map +1 -1
  42. package/dist/createOrUpdateDeckMapResource.d.ts +6 -2
  43. package/dist/createOrUpdateDeckMapResource.d.ts.map +1 -1
  44. package/dist/createOrUpdateDeckMapResource.js +57 -4
  45. package/dist/createOrUpdateDeckMapResource.js.map +1 -1
  46. package/dist/dashboard.d.ts.map +1 -1
  47. package/dist/dashboard.js +72 -8
  48. package/dist/dashboard.js.map +1 -1
  49. package/dist/dashboardConfig.d.ts +10 -1
  50. package/dist/dashboardConfig.d.ts.map +1 -1
  51. package/dist/dashboardConfig.js +55 -22
  52. package/dist/dashboardConfig.js.map +1 -1
  53. package/dist/datasets/PreparedDatasetStore.d.ts +3 -4
  54. package/dist/datasets/PreparedDatasetStore.d.ts.map +1 -1
  55. package/dist/datasets/PreparedDatasetStore.js +35 -10
  56. package/dist/datasets/PreparedDatasetStore.js.map +1 -1
  57. package/dist/datasets/helpers.d.ts +39 -2
  58. package/dist/datasets/helpers.d.ts.map +1 -1
  59. package/dist/datasets/helpers.js +86 -3
  60. package/dist/datasets/helpers.js.map +1 -1
  61. package/dist/datasets/usePreparedDatasetStates.d.ts.map +1 -1
  62. package/dist/datasets/usePreparedDatasetStates.js +12 -8
  63. package/dist/datasets/usePreparedDatasetStates.js.map +1 -1
  64. package/dist/datasets/wrapGeometryAsWkb.d.ts +20 -0
  65. package/dist/datasets/wrapGeometryAsWkb.d.ts.map +1 -0
  66. package/dist/datasets/wrapGeometryAsWkb.js +65 -0
  67. package/dist/datasets/wrapGeometryAsWkb.js.map +1 -0
  68. package/dist/index.d.ts +3 -2
  69. package/dist/index.d.ts.map +1 -1
  70. package/dist/index.js +2 -1
  71. package/dist/index.js.map +1 -1
  72. package/dist/json/colorScaleFunction.d.ts +12 -4
  73. package/dist/json/colorScaleFunction.d.ts.map +1 -1
  74. package/dist/json/colorScaleFunction.js.map +1 -1
  75. package/dist/json/compileColorScale.d.ts +3 -2
  76. package/dist/json/compileColorScale.d.ts.map +1 -1
  77. package/dist/json/compileColorScale.js +16 -1
  78. package/dist/json/compileColorScale.js.map +1 -1
  79. package/dist/json/compileGeoArrowAccessor.d.ts +5 -0
  80. package/dist/json/compileGeoArrowAccessor.d.ts.map +1 -1
  81. package/dist/json/compileGeoArrowAccessor.js +17 -3
  82. package/dist/json/compileGeoArrowAccessor.js.map +1 -1
  83. package/dist/json/createDeckJsonConfiguration.d.ts.map +1 -1
  84. package/dist/json/createDeckJsonConfiguration.js +278 -151
  85. package/dist/json/createDeckJsonConfiguration.js.map +1 -1
  86. package/dist/json/defaultClasses.d.ts.map +1 -1
  87. package/dist/json/defaultClasses.js +3 -3
  88. package/dist/json/defaultClasses.js.map +1 -1
  89. package/dist/json/extractColorScaleLegends.d.ts.map +1 -1
  90. package/dist/json/extractColorScaleLegends.js +43 -14
  91. package/dist/json/extractColorScaleLegends.js.map +1 -1
  92. package/dist/json/heatmapDefaults.d.ts +17 -7
  93. package/dist/json/heatmapDefaults.d.ts.map +1 -1
  94. package/dist/json/heatmapDefaults.js +54 -12
  95. package/dist/json/heatmapDefaults.js.map +1 -1
  96. package/dist/json/layers/DeckH3HexagonLayer.d.ts.map +1 -1
  97. package/dist/json/layers/DeckH3HexagonLayer.js +9 -14
  98. package/dist/json/layers/DeckH3HexagonLayer.js.map +1 -1
  99. package/dist/json/layers/DeckHeatmapLayer.d.ts +32 -0
  100. package/dist/json/layers/DeckHeatmapLayer.d.ts.map +1 -0
  101. package/dist/json/layers/DeckHeatmapLayer.js +69 -0
  102. package/dist/json/layers/DeckHeatmapLayer.js.map +1 -0
  103. package/dist/json/layers/h3IndexFormat.d.ts +6 -0
  104. package/dist/json/layers/h3IndexFormat.d.ts.map +1 -0
  105. package/dist/json/layers/h3IndexFormat.js +17 -0
  106. package/dist/json/layers/h3IndexFormat.js.map +1 -0
  107. package/dist/json/layers/index.d.ts +2 -0
  108. package/dist/json/layers/index.d.ts.map +1 -1
  109. package/dist/json/layers/index.js +2 -0
  110. package/dist/json/layers/index.js.map +1 -1
  111. package/dist/json/rewriteGeoArrowAccessors.d.ts.map +1 -1
  112. package/dist/json/rewriteGeoArrowAccessors.js +22 -5
  113. package/dist/json/rewriteGeoArrowAccessors.js.map +1 -1
  114. package/dist/json/scaleFunction.d.ts +27 -0
  115. package/dist/json/scaleFunction.d.ts.map +1 -0
  116. package/dist/json/scaleFunction.js +151 -0
  117. package/dist/json/scaleFunction.js.map +1 -0
  118. package/dist/mapAiConfig.d.ts +8 -0
  119. package/dist/mapAiConfig.d.ts.map +1 -1
  120. package/dist/mapAiConfig.js +9 -1
  121. package/dist/mapAiConfig.js.map +1 -1
  122. package/dist/mapAiSharedInstructions.d.ts +3 -0
  123. package/dist/mapAiSharedInstructions.d.ts.map +1 -0
  124. package/dist/mapAiSharedInstructions.js +16 -0
  125. package/dist/mapAiSharedInstructions.js.map +1 -0
  126. package/dist/mapConfig.d.ts +7 -1
  127. package/dist/mapConfig.d.ts.map +1 -1
  128. package/dist/mapConfig.js.map +1 -1
  129. package/dist/mapConfigUtils.d.ts +22 -0
  130. package/dist/mapConfigUtils.d.ts.map +1 -1
  131. package/dist/mapConfigUtils.js +147 -3
  132. package/dist/mapConfigUtils.js.map +1 -1
  133. package/dist/mapFit.d.ts +16 -0
  134. package/dist/mapFit.d.ts.map +1 -1
  135. package/dist/mapFit.js +208 -30
  136. package/dist/mapFit.js.map +1 -1
  137. package/dist/mapLayerConfigUtils.d.ts +64 -1
  138. package/dist/mapLayerConfigUtils.d.ts.map +1 -1
  139. package/dist/mapLayerConfigUtils.js +277 -16
  140. package/dist/mapLayerConfigUtils.js.map +1 -1
  141. package/dist/mapResourceAuthoring.d.ts +3 -1
  142. package/dist/mapResourceAuthoring.d.ts.map +1 -1
  143. package/dist/mapResourceAuthoring.js +413 -20
  144. package/dist/mapResourceAuthoring.js.map +1 -1
  145. package/dist/mosaic.d.ts +1 -1
  146. package/dist/mosaic.d.ts.map +1 -1
  147. package/dist/mosaic.js.map +1 -1
  148. package/dist/prepare/geoarrow.js.map +1 -1
  149. package/dist/prepare/prepareDeckDataset.d.ts.map +1 -1
  150. package/dist/prepare/prepareDeckDataset.js +1 -0
  151. package/dist/prepare/prepareDeckDataset.js.map +1 -1
  152. package/dist/prepare/types.d.ts +3 -0
  153. package/dist/prepare/types.d.ts.map +1 -1
  154. package/dist/prepare/types.js.map +1 -1
  155. package/dist/prepare/wkbDecoder.d.ts +10 -0
  156. package/dist/prepare/wkbDecoder.d.ts.map +1 -1
  157. package/dist/prepare/wkbDecoder.js +141 -20
  158. package/dist/prepare/wkbDecoder.js.map +1 -1
  159. package/dist/prepare/wkbParser.d.ts +9 -0
  160. package/dist/prepare/wkbParser.d.ts.map +1 -1
  161. package/dist/prepare/wkbParser.js +22 -0
  162. package/dist/prepare/wkbParser.js.map +1 -1
  163. package/dist/selectStarAsWkbCollision.d.ts +3 -0
  164. package/dist/selectStarAsWkbCollision.d.ts.map +1 -0
  165. package/dist/selectStarAsWkbCollision.js +78 -0
  166. package/dist/selectStarAsWkbCollision.js.map +1 -0
  167. package/dist/types.d.ts +1 -1
  168. package/dist/types.d.ts.map +1 -1
  169. package/dist/types.js.map +1 -1
  170. package/dist/useDeckMapFitToBounds.d.ts.map +1 -1
  171. package/dist/useDeckMapFitToBounds.js +1 -1
  172. package/dist/useDeckMapFitToBounds.js.map +1 -1
  173. package/package.json +15 -15
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../src/dashboard.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n column,\n type MosaicDashboardEntryType,\n type MosaicDashboardPanelConfigType,\n type MosaicDashboardPanelRenderer,\n type MosaicDashboardPanelRendererProps,\n sql,\n type ChartRuntimeIssue,\n type ChartRuntimeIssueContext,\n type ChartRuntimeIssueReporter,\n useMosaicClient,\n useStoreWithMosaicDashboard,\n usePanelClientRegistration,\n} from '@sqlrooms/mosaic';\nimport {Button, Tooltip, TooltipContent, TooltipTrigger} from '@sqlrooms/ui';\nimport type {MosaicClient} from '@uwdata/mosaic-core';\nimport type {Selection} from '@uwdata/mosaic-core';\nimport {AlertTriangleIcon, FocusIcon, MapIcon} from 'lucide-react';\nimport {useCallback, useEffect, useMemo, useRef, useState} from 'react';\nimport {DeckJsonMap} from './DeckJsonMap';\nimport type {DeckJsonMapHandle} from './types';\nimport {\n asDeckJsonMapConfig,\n createDeckMapDashboardPanelConfig,\n createDeckMapDashboardDatasetQuery,\n createDeckMapDashboardDatasets,\n DECK_MAP_DASHBOARD_PANEL_TYPE,\n DEFAULT_DECK_MAP_MAX_DATA_POINTS,\n isDeckMapDashboardSqlDatasetSource,\n isDeckMapDashboardTableDatasetSource,\n resolveDeckMapDashboardDatasetSource,\n type DeckMapDashboardFitToDataConfig,\n type DeckMapDashboardDatasetClientState,\n type DeckMapDashboardDatasetConfig,\n type DeckMapDashboardInteractionConfig,\n type DeckMapDashboardPanelConfig,\n} from './dashboardConfig';\nimport {\n useDeckMapFitToBounds,\n emitDeckMapDashboardFitRequest,\n createDeckMapBoundsQuery,\n} from './useDeckMapFitToBounds';\nexport {createDeckMapBoundsQuery};\nimport {useDeckMapDatasets} from './useDeckMapDatasets';\nimport {DeckMapDashboardSettings} from './DashboardMapSettings';\nimport {\n createDeckMapDashboardPanelConfigForTable,\n findGeometryColumn,\n findLongitudeLatitudeColumns,\n} from './mapConfigUtils';\nimport {isDeckMapGeneratedColumn} from './useDeckMapDatasetSchema';\n\nfunction createEmptyDeckMapDashboardPanelConfig(title = 'Map') {\n return createDeckMapDashboardPanelConfig({\n title,\n spec: {\n initialViewState: {longitude: 0, latitude: 20, zoom: 1.5},\n layers: [],\n },\n datasets: {},\n });\n}\n\n/**\n * Extracts column names from common DuckDB \"column not found\" error messages\n * and layer geometry incompatibility errors.\n * Returns the column names if detected, or null for unrecognized errors.\n */\nfunction parseMissingColumnsFromError(message: string): string[] | null {\n // \"Referenced column \"X\" not found in FROM clause!\" — may appear multiple times\n const refMatches = [\n ...message.matchAll(/Referenced column \"([^\"]+)\" not found/gi),\n ];\n if (refMatches.length > 0) return refMatches.map((m) => m[1]!);\n\n // \"Binder Error: Column \"X\" does not exist\" or \"column X not found\"\n const colMatch = message.match(\n /(?:Column|column)\\s+\"([^\"]+)\"\\s+(?:does not exist|not found)/i,\n );\n if (colMatch) return [colMatch[1]!];\n\n // \"Geometry column \"X\" was not found\"\n const geomNotFound = message.match(\n /Geometry column \"([^\"]+)\" was not found/i,\n );\n if (geomNotFound) return [geomNotFound[1]!];\n\n // \"Layer ... references unknown column \"X\" for getTimestamps.\"\n const unknownColumn = message.match(/references unknown column \"([^\"]+)\"/i);\n if (unknownColumn) return [unknownColumn[1]!];\n\n return null;\n}\n\n/**\n * Detects geometry type mismatch errors (e.g. polygon layer on point data).\n */\nfunction parseGeometryMismatchError(\n message: string,\n): {required: string; found: string} | null {\n const match = message.match(\n /requires (\\w+) geometry .+ but only (\\w+) coordinates were found/i,\n );\n if (match) return {required: match[1]!, found: match[2]!};\n return null;\n}\n\n/**\n * Detects columns referenced in layer config that are missing from the loaded dataset.\n */\nfunction detectMissingColumns(\n mapConfig: DeckMapDashboardPanelConfig | undefined,\n datasetStates: Record<string, DeckMapDashboardDatasetClientState>,\n): string[] {\n if (!mapConfig?.spec) return [];\n const missing: string[] = [];\n const spec = mapConfig.spec as Record<string, unknown>;\n const layers = Array.isArray(spec.layers) ? spec.layers : [];\n\n for (const layer of layers) {\n if (!layer || typeof layer !== 'object') continue;\n const layerObj = layer as Record<string, unknown>;\n const binding = layerObj._sqlroomsBinding as\n | Record<string, unknown>\n | undefined;\n const datasetId = binding?.dataset as string | undefined;\n const arrowTable = datasetId\n ? datasetStates[datasetId]?.arrowTable\n : undefined;\n if (!arrowTable) continue;\n\n const fieldNames = new Set(\n arrowTable.schema.fields.map((f) => f.name.toLowerCase()),\n );\n const check = (col: string | undefined) => {\n if (col && !fieldNames.has(col.toLowerCase())) {\n missing.push(col);\n }\n };\n\n for (const bindingColumn of [\n binding?.geometryColumn,\n binding?.sourceGeometryColumn,\n binding?.targetGeometryColumn,\n binding?.timestampColumn,\n binding?.hexagonColumn,\n ]) {\n check(bindingColumn as string | undefined);\n }\n\n // Check @@= accessors\n for (const [propName, propValue] of Object.entries(layerObj)) {\n // Skip elevation references when extrusion is disabled\n if (propName === 'getElevation' && !layerObj.extruded) continue;\n\n if (typeof propValue === 'string' && propValue.startsWith('@@=')) {\n const expression = propValue.slice(3).trim();\n const identifiers = expression.match(/\\b[A-Za-z_$][\\w$]*\\b/g);\n if (identifiers) {\n for (const id of identifiers) {\n check(id);\n }\n }\n }\n // Check @@function colorScale/scale field references\n if (\n propValue &&\n typeof propValue === 'object' &&\n '@@function' in (propValue as object)\n ) {\n const fn = propValue as Record<string, unknown>;\n if (typeof fn.field === 'string') {\n check(fn.field);\n }\n }\n }\n }\n\n return [...new Set(missing)];\n}\n\nfunction DeckMapRuntimeIssuePanel({issue}: {issue: ChartRuntimeIssue}) {\n if (issue.kind === 'sql-error' || issue.kind === 'render-error') {\n const missingColumns = parseMissingColumnsFromError(issue.message);\n if (missingColumns) {\n const generatedMissingColumns = missingColumns.filter(\n isDeckMapGeneratedColumn,\n );\n if (generatedMissingColumns.length > 0) {\n return (\n <div className=\"flex h-full min-h-[200px] flex-col items-center justify-center p-4\">\n <div className=\"mb-2 text-center font-semibold\">\n The visualization can&apos;t be displayed\n </div>\n <div className=\"text-center text-sm\">\n <span>\n The dataset transform did not produce required map output\n columns:{' '}\n </span>\n {generatedMissingColumns.map((col, idx) => (\n <span key={idx}>\n <span className=\"inline-flex items-center rounded-md border border-gray-600 bg-gray-800 px-1 py-0.5 text-xs font-medium text-gray-300\">\n {col}\n </span>{' '}\n </span>\n ))}\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"flex h-full min-h-[200px] flex-col items-center justify-center p-4\">\n <div className=\"mb-2 text-center font-semibold\">\n The visualization can&apos;t be displayed\n </div>\n <div className=\"text-center text-sm\">\n <span>Selected columns are missing in the dataset: </span>\n {missingColumns.map((col, idx) => (\n <span key={idx}>\n <span className=\"inline-flex items-center rounded-md border border-gray-600 bg-gray-800 px-1 py-0.5 text-xs font-medium text-gray-300\">\n {col}\n </span>{' '}\n </span>\n ))}\n </div>\n </div>\n );\n }\n\n const geomMismatch = parseGeometryMismatchError(issue.message);\n if (geomMismatch) {\n return (\n <div className=\"flex h-full min-h-[200px] flex-col items-center justify-center p-4\">\n <div className=\"mb-2 text-center font-semibold\">\n The visualization can&apos;t be displayed\n </div>\n <div className=\"text-center text-sm\">\n This layer requires {geomMismatch.required} geometry, but the\n current dataset only has {geomMismatch.found} coordinates.\n </div>\n </div>\n );\n }\n }\n\n const title =\n issue.kind === 'too-much-data'\n ? 'Too much data'\n : issue.kind === 'sql-error'\n ? 'Map query failed'\n : 'Unable to display map';\n\n return (\n <div className=\"flex h-full min-h-[200px] flex-col items-center justify-center p-4\">\n <div className=\"mb-2 text-center font-semibold\">{title}</div>\n <div className=\"text-center text-sm whitespace-pre-wrap\">\n {issue.message}\n </div>\n </div>\n );\n}\n\nfunction DeckMapDashboardDatasetClient({\n dashboard,\n dataset,\n datasetId,\n fitToData,\n panel,\n onDatasetState,\n runtimeIssueContext,\n runtimeIssueReporter,\n selectionName,\n maxRows,\n}: {\n dashboard: MosaicDashboardEntryType;\n dataset: DeckMapDashboardDatasetConfig;\n datasetId: string;\n fitToData?: DeckMapDashboardFitToDataConfig;\n panel: MosaicDashboardPanelConfigType;\n onDatasetState: (\n datasetId: string,\n state: DeckMapDashboardDatasetClientState | undefined,\n ) => void;\n runtimeIssueContext?: ChartRuntimeIssueContext;\n runtimeIssueReporter?: ChartRuntimeIssueReporter;\n selectionName: string;\n maxRows: number;\n}) {\n const datasetFitToData = useMemo(\n () => (fitToData?.dataset === datasetId ? fitToData : undefined),\n [datasetId, fitToData],\n );\n const source = useMemo(\n () =>\n resolveDeckMapDashboardDatasetSource({\n dashboard,\n panel,\n dataset,\n fitToData: datasetFitToData,\n }),\n [dashboard, dataset, datasetFitToData, panel],\n );\n const query = useCallback(\n (filter: unknown) =>\n source\n ? createDeckMapDashboardDatasetQuery(source, filter, {\n sampleRows: maxRows,\n })\n : createDeckMapDashboardDatasetQuery(\n {tableName: '__missing_dashboard_map_dataset__'},\n filter,\n {sampleRows: maxRows},\n ),\n [maxRows, source],\n );\n const queryError = useCallback(\n (err: Error) => {\n onDatasetState(datasetId, {\n arrowTable: undefined,\n error: err,\n isLoading: false,\n client: null,\n isSampled: false,\n });\n },\n [datasetId, onDatasetState],\n );\n const sourceKey = isDeckMapDashboardTableDatasetSource(source)\n ? source.tableName\n : isDeckMapDashboardSqlDatasetSource(source)\n ? ''\n : (dashboard.selectedTable ?? '');\n const sourceQueryKey = isDeckMapDashboardSqlDatasetSource(source)\n ? source.sqlQuery\n : isDeckMapDashboardTableDatasetSource(source)\n ? (source.transformSql ?? '')\n : '';\n const {data, error, isLoading, client} = useMosaicClient({\n id: `${panel.id}:${datasetId}:${sourceKey}:${sourceQueryKey}:${maxRows}`,\n selectionName,\n query,\n queryError,\n enabled: Boolean(source),\n runtimeIssueContext,\n runtimeIssueReporter,\n });\n\n // Register client for panel reset button\n usePanelClientRegistration(dashboard.id, panel.id, client ? [client] : []);\n\n const isSampled = Boolean(data && data.numRows >= maxRows);\n\n useEffect(() => {\n onDatasetState(datasetId, {\n arrowTable: data ?? undefined,\n error,\n isLoading,\n client,\n isSampled,\n });\n\n return () => {\n onDatasetState(datasetId, undefined);\n };\n }, [client, data, datasetId, error, isLoading, isSampled, onDatasetState]);\n\n return null;\n}\n\nfunction createPointRadiusPredicate(\n interaction: DeckMapDashboardInteractionConfig,\n coordinate: [number, number],\n) {\n const [longitude, latitude] = coordinate;\n const radiusMeters = interaction.radiusMeters ?? 500;\n const metersPerDegree = 111_320;\n const cosLatitude = Math.cos(latitude * (Math.PI / 180));\n const radiusSquared = radiusMeters * radiusMeters;\n\n return sql`(\n pow((${column(interaction.longitudeColumn)} - ${longitude}) * ${\n cosLatitude * metersPerDegree\n }, 2) +\n pow((${column(interaction.latitudeColumn)} - ${latitude}) * ${\n metersPerDegree\n }, 2)\n ) < ${radiusSquared}`;\n}\n\ntype DeckMapInteractionEvent = {\n coordinate?: number[] | null;\n object?: unknown;\n index?: number;\n picked?: boolean;\n};\n\nfunction getCoordinate(\n info: DeckMapInteractionEvent,\n): [number, number] | undefined {\n return info.coordinate && info.coordinate.length >= 2\n ? [info.coordinate[0]!, info.coordinate[1]!]\n : undefined;\n}\n\nfunction isPickedMapFeature(info: DeckMapInteractionEvent) {\n return Boolean(info.picked || info.object || (info.index ?? -1) >= 0);\n}\n\nfunction DeckMapDashboardHeaderActions({\n panel,\n}: MosaicDashboardPanelRendererProps) {\n const mapConfig = asDeckJsonMapConfig(panel.config);\n const canFitView = Boolean(mapConfig?.fitToData);\n const fitViewLabel = canFitView\n ? 'Fit map view to data'\n : 'Fit view unavailable for this map';\n\n return (\n <div className=\"flex items-center gap-0.5\">\n <Tooltip>\n <TooltipTrigger asChild>\n <span\n className=\"inline-flex\"\n tabIndex={canFitView ? undefined : 0}\n aria-label={canFitView ? undefined : fitViewLabel}\n >\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-6 w-6\"\n aria-label={fitViewLabel}\n disabled={!canFitView}\n onClick={() => emitDeckMapDashboardFitRequest(panel.id)}\n >\n <FocusIcon className=\"h-3.5 w-3.5\" />\n </Button>\n </span>\n </TooltipTrigger>\n <TooltipContent>{fitViewLabel}</TooltipContent>\n </Tooltip>\n </div>\n );\n}\n\nfunction DeckMapDashboardRenderer({\n dashboard,\n dashboardId,\n panel,\n selectionName,\n}: MosaicDashboardPanelRendererProps) {\n const mapConfig = asDeckJsonMapConfig(panel.config);\n const isCustomMode = mapConfig?.configMode === 'custom';\n const getSelection = useStoreWithMosaicDashboard(\n (state) => state.mosaic.getSelection,\n );\n const issue = useStoreWithMosaicDashboard((state) =>\n state.mosaicDashboard.getPanelIssue(dashboardId, panel.id),\n );\n const clearPanelIssue = useStoreWithMosaicDashboard(\n (state) => state.mosaicDashboard.clearPanelIssue,\n );\n\n // Clear runtime issues when the active table or panel config changes so\n // the map can recover (e.g., after switching tables or AI updating the map).\n useEffect(() => {\n clearPanelIssue(dashboardId, panel.id);\n }, [\n clearPanelIssue,\n dashboard.selectedTable,\n dashboardId,\n panel.config,\n panel.id,\n ]);\n\n const selection = useMemo<Selection>(\n () => getSelection(selectionName, 'crossfilter'),\n [getSelection, selectionName],\n );\n const [container, setContainer] = useState<HTMLDivElement | null>(null);\n const deckMapRef = useRef<DeckJsonMapHandle>(null);\n const [sampledDismissed, setSampledDismissed] = useState(false);\n\n const {\n datasetStates,\n handleDatasetState,\n runtimeIssueContext,\n runtimeIssueReporter,\n handleRenderingError,\n } = useDeckMapDatasets({dashboardId, panel});\n\n const {fitToData} = useDeckMapFitToBounds({\n panelId: panel.id,\n dashboard,\n panel,\n container,\n deckMapRef,\n });\n\n const handleBrushEvent = useCallback(\n (info: DeckMapInteractionEvent) => {\n const interaction = mapConfig?.interaction;\n if (!interaction) {\n return;\n }\n\n const client = datasetStates[interaction.dataset]?.client as\n | MosaicClient\n | null\n | undefined;\n if (!client) {\n return;\n }\n const coordinate = getCoordinate(info);\n if (!coordinate) {\n return;\n }\n if (interaction.event !== 'click' && !isPickedMapFeature(info)) {\n selection.reset(\n selection.clauses.filter((clause) => clause.source === client),\n );\n return;\n }\n\n const radiusMeters = interaction.radiusMeters ?? 500;\n selection.update({\n source: client,\n clients: new Set([client]),\n value: [coordinate[0], coordinate[1], radiusMeters],\n predicate: createPointRadiusPredicate(interaction, coordinate),\n });\n },\n [datasetStates, mapConfig?.interaction, selection],\n );\n\n const datasetError = useMemo(() => {\n for (const state of Object.values(datasetStates)) {\n if (state.error) return state.error;\n }\n return undefined;\n }, [datasetStates]);\n\n const missingColumns = useMemo(\n () => detectMissingColumns(mapConfig ?? undefined, datasetStates),\n [mapConfig, datasetStates],\n );\n\n const maxRows =\n mapConfig?.dataPolicy?.maxRows ?? DEFAULT_DECK_MAP_MAX_DATA_POINTS;\n\n const mapContent = !mapConfig ? (\n <div className=\"text-muted-foreground flex h-full items-center justify-center p-4 text-sm\">\n Invalid map panel config.\n </div>\n ) : Object.entries(mapConfig.datasets).length === 0 ? (\n <div className=\"text-muted-foreground flex h-full items-center justify-center p-4 text-sm\">\n Map panels require at least one dataset.\n </div>\n ) : (\n <>\n {Object.entries(mapConfig.datasets).map(([datasetId, dataset]) => (\n <DeckMapDashboardDatasetClient\n key={datasetId}\n dashboard={dashboard}\n dataset={dataset}\n datasetId={datasetId}\n fitToData={fitToData ?? undefined}\n panel={panel}\n onDatasetState={handleDatasetState}\n runtimeIssueContext={runtimeIssueContext}\n runtimeIssueReporter={runtimeIssueReporter}\n selectionName={selectionName}\n maxRows={maxRows}\n />\n ))}\n {issue ? (\n <DeckMapRuntimeIssuePanel issue={issue} />\n ) : datasetError ? (\n <DeckMapRuntimeIssuePanel\n issue={{\n kind: 'sql-error',\n panelId: panel.id,\n chartType: DECK_MAP_DASHBOARD_PANEL_TYPE,\n message: datasetError.message,\n recoverable: true,\n }}\n />\n ) : (\n <div ref={setContainer} className=\"relative h-full w-full\">\n {Object.values(datasetStates).some((s) => s.isSampled) &&\n !sampledDismissed && (\n <div className=\"bg-background/80 text-muted-foreground absolute top-2 left-2 z-10 flex items-center gap-1.5 rounded px-2 py-1 text-xs shadow\">\n <span>Data sampled to {maxRows.toLocaleString()} rows</span>\n <button\n className=\"text-muted-foreground/60 hover:text-foreground -mr-0.5 ml-0.5\"\n onClick={() => setSampledDismissed(true)}\n >\n ×\n </button>\n </div>\n )}\n {missingColumns.length > 0 && !isCustomMode && (\n <Tooltip>\n <TooltipTrigger asChild>\n <span\n className={`absolute left-2 z-10 flex h-5 w-5 items-center justify-center ${\n Object.values(datasetStates).some((s) => s.isSampled) &&\n !sampledDismissed\n ? 'top-9'\n : 'top-2'\n }`}\n >\n <AlertTriangleIcon className=\"h-4 w-4 text-amber-500 drop-shadow-sm\" />\n </span>\n </TooltipTrigger>\n <TooltipContent side=\"right\">\n <p className=\"text-xs font-medium\">Missing columns:</p>\n <p className=\"text-xs\">{missingColumns.join(', ')}</p>\n </TooltipContent>\n </Tooltip>\n )}\n <DeckJsonMap\n ref={deckMapRef}\n className=\"h-full w-full px-0.5 pb-0.5\"\n spec={mapConfig.spec}\n datasets={\n mapConfig\n ? createDeckMapDashboardDatasets(mapConfig, datasetStates)\n : {}\n }\n mapStyle={mapConfig.mapStyle}\n mapProps={mapConfig.mapProps}\n showLegends={mapConfig.showLegends !== false}\n onRenderingError={handleRenderingError}\n deckProps={{\n controller: true,\n ...(mapConfig.interaction\n ? (mapConfig.interaction.event ?? 'hover') === 'click'\n ? {onClick: handleBrushEvent}\n : {onHover: handleBrushEvent}\n : {}),\n }}\n />\n </div>\n )}\n </>\n );\n\n return mapContent;\n}\n\nexport const deckMapDashboardPanelRenderer: MosaicDashboardPanelRenderer = {\n component: DeckMapDashboardRenderer,\n headerActions: DeckMapDashboardHeaderActions,\n icon: MapIcon,\n settings: DeckMapDashboardSettings,\n};\n\nexport const deckMapDashboardAddPanelAction: import('@sqlrooms/mosaic').MosaicDashboardAddPanelAction =\n {\n type: DECK_MAP_DASHBOARD_PANEL_TYPE,\n label: 'Map',\n icon: MapIcon,\n createPanel: ({selectedTable}) => {\n if (\n selectedTable &&\n (findLongitudeLatitudeColumns(selectedTable) ??\n findGeometryColumn(selectedTable))\n ) {\n return createDeckMapDashboardPanelConfigForTable({\n title: `${selectedTable.tableName} map`,\n tableName: selectedTable.tableName,\n columns: selectedTable.columns,\n tableReference: selectedTable.table,\n });\n }\n\n return createEmptyDeckMapDashboardPanelConfig(\n selectedTable ? `${selectedTable.tableName} map` : 'Map',\n );\n },\n };\n"]}
1
+ {"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../src/dashboard.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n column,\n type MosaicDashboardEntryType,\n type MosaicDashboardPanelConfigType,\n type MosaicDashboardPanelRenderer,\n type MosaicDashboardPanelRendererProps,\n sql,\n type ChartRuntimeIssue,\n type ChartRuntimeIssueContext,\n type ChartRuntimeIssueReporter,\n useMosaicClient,\n useStoreWithMosaicDashboard,\n usePanelClientRegistration,\n} from '@sqlrooms/mosaic';\nimport {useStoreWithDuckDb} from '@sqlrooms/duckdb';\nimport {Button, Tooltip, TooltipContent, TooltipTrigger} from '@sqlrooms/ui';\nimport type {MosaicClient} from '@uwdata/mosaic-core';\nimport type {Selection} from '@uwdata/mosaic-core';\nimport {AlertTriangleIcon, FocusIcon, MapIcon} from 'lucide-react';\nimport {useCallback, useEffect, useMemo, useRef, useState} from 'react';\nimport {DeckJsonMap} from './DeckJsonMap';\nimport type {DeckJsonMapHandle} from './types';\nimport {\n asDeckJsonMapConfig,\n createDeckMapDashboardPanelConfig,\n createDeckMapDashboardDatasetQuery,\n createDeckMapDashboardDatasetSourceSql,\n createDeckMapDashboardDatasets,\n DECK_MAP_DASHBOARD_PANEL_TYPE,\n DEFAULT_DECK_MAP_MAX_DATA_POINTS,\n isDeckMapDashboardSqlDatasetSource,\n isDeckMapDashboardTableDatasetSource,\n resolveDeckMapDashboardDatasetSource,\n type DeckMapDashboardFitToDataConfig,\n type DeckMapDashboardDatasetClientState,\n type DeckMapDashboardDatasetConfig,\n type DeckMapDashboardInteractionConfig,\n type DeckMapDashboardPanelConfig,\n} from './dashboardConfig';\nimport {\n createDescribeDatasetSql,\n geometryColumnsNeedingWkbWrap,\n parseDescribeSqlColumns,\n} from './datasets/wrapGeometryAsWkb';\nimport {\n useDeckMapFitToBounds,\n emitDeckMapDashboardFitRequest,\n createDeckMapBoundsQuery,\n} from './useDeckMapFitToBounds';\nimport {useDeckMapDatasets} from './useDeckMapDatasets';\nimport {DeckMapDashboardSettings} from './DashboardMapSettings';\nimport {\n createDeckMapDashboardPanelConfigForTable,\n findGeometryColumn,\n findLongitudeLatitudeColumns,\n} from './mapConfigUtils';\nimport {isDeckMapGeneratedColumn} from './useDeckMapDatasetSchema';\n\n/** Stable fallback while the DESCRIBE geometry-wrap probe is pending. */\nconst EMPTY_WRAPPED_GEOMETRY_COLUMNS: readonly string[] = [];\n\nexport {createDeckMapBoundsQuery};\n\nfunction createEmptyDeckMapDashboardPanelConfig(title = 'Map') {\n return createDeckMapDashboardPanelConfig({\n title,\n spec: {\n initialViewState: {longitude: 0, latitude: 20, zoom: 1.5},\n layers: [],\n },\n datasets: {},\n });\n}\n\n/**\n * Extracts column names from common DuckDB \"column not found\" error messages\n * and layer geometry incompatibility errors.\n * Returns the column names if detected, or null for unrecognized errors.\n */\nfunction parseMissingColumnsFromError(message: string): string[] | null {\n // \"Referenced column \"X\" not found in FROM clause!\" — may appear multiple times\n const refMatches = [\n ...message.matchAll(/Referenced column \"([^\"]+)\" not found/gi),\n ];\n if (refMatches.length > 0) return refMatches.map((m) => m[1]!);\n\n // \"Binder Error: Column \"X\" does not exist\" or \"column X not found\"\n const colMatch = message.match(\n /(?:Column|column)\\s+\"([^\"]+)\"\\s+(?:does not exist|not found)/i,\n );\n if (colMatch) return [colMatch[1]!];\n\n // \"Geometry column \"X\" was not found\"\n const geomNotFound = message.match(\n /Geometry column \"([^\"]+)\" was not found/i,\n );\n if (geomNotFound) return [geomNotFound[1]!];\n\n // \"Layer ... references unknown column \"X\" for getTimestamps.\"\n const unknownColumn = message.match(/references unknown column \"([^\"]+)\"/i);\n if (unknownColumn) return [unknownColumn[1]!];\n\n return null;\n}\n\n/**\n * Detects geometry type mismatch errors (e.g. polygon layer on point data).\n */\nfunction parseGeometryMismatchError(\n message: string,\n): {required: string; found: string} | null {\n const match = message.match(\n /requires (\\w+) geometry .+ but only (\\w+) coordinates were found/i,\n );\n if (match) return {required: match[1]!, found: match[2]!};\n return null;\n}\n\n/**\n * Detects columns referenced in layer config that are missing from the loaded dataset.\n */\nfunction detectMissingColumns(\n mapConfig: DeckMapDashboardPanelConfig | undefined,\n datasetStates: Record<string, DeckMapDashboardDatasetClientState>,\n): string[] {\n if (!mapConfig?.spec) return [];\n const missing: string[] = [];\n const spec = mapConfig.spec as Record<string, unknown>;\n const layers = Array.isArray(spec.layers) ? spec.layers : [];\n\n for (const layer of layers) {\n if (!layer || typeof layer !== 'object') continue;\n const layerObj = layer as Record<string, unknown>;\n const binding = layerObj._sqlroomsBinding as\n | Record<string, unknown>\n | undefined;\n const datasetId = binding?.dataset as string | undefined;\n const arrowTable = datasetId\n ? datasetStates[datasetId]?.arrowTable\n : undefined;\n if (!arrowTable) continue;\n\n const fieldNames = new Set(\n arrowTable.schema.fields.map((f) => f.name.toLowerCase()),\n );\n const check = (col: string | undefined) => {\n if (col && !fieldNames.has(col.toLowerCase())) {\n missing.push(col);\n }\n };\n\n for (const bindingColumn of [\n binding?.geometryColumn,\n binding?.sourceGeometryColumn,\n binding?.targetGeometryColumn,\n binding?.timestampColumn,\n binding?.hexagonColumn,\n ]) {\n check(bindingColumn as string | undefined);\n }\n\n // Check @@= accessors\n for (const [propName, propValue] of Object.entries(layerObj)) {\n // Skip elevation references when extrusion is disabled\n if (propName === 'getElevation' && !layerObj.extruded) continue;\n\n if (typeof propValue === 'string' && propValue.startsWith('@@=')) {\n const expression = propValue.slice(3).trim();\n const identifiers = expression.match(/\\b[A-Za-z_$][\\w$]*\\b/g);\n if (identifiers) {\n for (const id of identifiers) {\n check(id);\n }\n }\n }\n // Check @@function colorScale/scale field references\n if (\n propValue &&\n typeof propValue === 'object' &&\n '@@function' in (propValue as object)\n ) {\n const fn = propValue as Record<string, unknown>;\n if (typeof fn.field === 'string') {\n check(fn.field);\n }\n }\n }\n }\n\n return [...new Set(missing)];\n}\n\nfunction DeckMapRuntimeIssuePanel({issue}: {issue: ChartRuntimeIssue}) {\n if (issue.kind === 'sql-error' || issue.kind === 'render-error') {\n const missingColumns = parseMissingColumnsFromError(issue.message);\n if (missingColumns) {\n const generatedMissingColumns = missingColumns.filter(\n isDeckMapGeneratedColumn,\n );\n if (generatedMissingColumns.length > 0) {\n return (\n <div className=\"flex h-full min-h-[200px] flex-col items-center justify-center p-4\">\n <div className=\"mb-2 text-center font-semibold\">\n The visualization can&apos;t be displayed\n </div>\n <div className=\"text-center text-sm\">\n <span>\n The dataset transform did not produce required map output\n columns:{' '}\n </span>\n {generatedMissingColumns.map((col, idx) => (\n <span key={idx}>\n <span className=\"inline-flex items-center rounded-md border border-gray-600 bg-gray-800 px-1 py-0.5 text-xs font-medium text-gray-300\">\n {col}\n </span>{' '}\n </span>\n ))}\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"flex h-full min-h-[200px] flex-col items-center justify-center p-4\">\n <div className=\"mb-2 text-center font-semibold\">\n The visualization can&apos;t be displayed\n </div>\n <div className=\"text-center text-sm\">\n <span>Selected columns are missing in the dataset: </span>\n {missingColumns.map((col, idx) => (\n <span key={idx}>\n <span className=\"inline-flex items-center rounded-md border border-gray-600 bg-gray-800 px-1 py-0.5 text-xs font-medium text-gray-300\">\n {col}\n </span>{' '}\n </span>\n ))}\n </div>\n </div>\n );\n }\n\n const geomMismatch = parseGeometryMismatchError(issue.message);\n if (geomMismatch) {\n return (\n <div className=\"flex h-full min-h-[200px] flex-col items-center justify-center p-4\">\n <div className=\"mb-2 text-center font-semibold\">\n The visualization can&apos;t be displayed\n </div>\n <div className=\"text-center text-sm\">\n This layer requires {geomMismatch.required} geometry, but the\n current dataset only has {geomMismatch.found} coordinates.\n </div>\n </div>\n );\n }\n }\n\n const title =\n issue.kind === 'too-much-data'\n ? 'Too much data'\n : issue.kind === 'sql-error'\n ? 'Map query failed'\n : 'Unable to display map';\n\n return (\n <div className=\"flex h-full min-h-[200px] flex-col items-center justify-center p-4\">\n <div className=\"mb-2 text-center font-semibold\">{title}</div>\n <div className=\"text-center text-sm whitespace-pre-wrap\">\n {issue.message}\n </div>\n </div>\n );\n}\n\nfunction DeckMapDashboardDatasetClient({\n dashboard,\n dataset,\n datasetId,\n fitToData,\n panel,\n onDatasetState,\n runtimeIssueContext,\n runtimeIssueReporter,\n selectionName,\n maxRows,\n}: {\n dashboard: MosaicDashboardEntryType;\n dataset: DeckMapDashboardDatasetConfig;\n datasetId: string;\n fitToData?: DeckMapDashboardFitToDataConfig;\n panel: MosaicDashboardPanelConfigType;\n onDatasetState: (\n datasetId: string,\n state: DeckMapDashboardDatasetClientState | undefined,\n ) => void;\n runtimeIssueContext?: ChartRuntimeIssueContext;\n runtimeIssueReporter?: ChartRuntimeIssueReporter;\n selectionName: string;\n maxRows: number;\n}) {\n const datasetFitToData = useMemo(\n () => (fitToData?.dataset === datasetId ? fitToData : undefined),\n [datasetId, fitToData],\n );\n const source = useMemo(\n () =>\n resolveDeckMapDashboardDatasetSource({\n dashboard,\n panel,\n dataset,\n fitToData: datasetFitToData,\n }),\n [dashboard, dataset, datasetFitToData, panel],\n );\n\n const connector = useStoreWithDuckDb((state) => state.db.connector);\n const [geometryWrapProbe, setGeometryWrapProbe] = useState<{\n sourceSqlKey: string;\n columns: string[];\n } | null>(null);\n\n const sourceSqlKey = useMemo(() => {\n if (!source) return '';\n try {\n return createDeckMapDashboardDatasetSourceSql(source);\n } catch {\n return '';\n }\n }, [source]);\n\n // Pending while probe key mismatches (avoids setState-in-effect).\n const geometryColumnsToWrapAsWkb = useMemo(() => {\n if (!source || !sourceSqlKey) return [];\n if (geometryWrapProbe?.sourceSqlKey !== sourceSqlKey) return null;\n return geometryWrapProbe.columns;\n }, [geometryWrapProbe, source, sourceSqlKey]);\n\n useEffect(() => {\n if (!source || !sourceSqlKey) {\n return;\n }\n\n let cancelled = false;\n void (async () => {\n try {\n const describeTable = await connector.query(\n createDescribeDatasetSql(sourceSqlKey),\n );\n if (cancelled) return;\n setGeometryWrapProbe({\n sourceSqlKey,\n columns: geometryColumnsNeedingWkbWrap(\n parseDescribeSqlColumns(describeTable),\n ),\n });\n } catch {\n if (cancelled) return;\n setGeometryWrapProbe({sourceSqlKey, columns: []});\n }\n })();\n\n return () => {\n cancelled = true;\n };\n }, [connector, source, sourceSqlKey]);\n\n const geometryProbeReady = geometryColumnsToWrapAsWkb !== null;\n const wrappedGeometryColumnNames =\n geometryColumnsToWrapAsWkb ?? EMPTY_WRAPPED_GEOMETRY_COLUMNS;\n\n const query = useCallback(\n (filter: unknown) =>\n source\n ? createDeckMapDashboardDatasetQuery(source, filter, {\n sampleRows: maxRows,\n geometryColumnsToWrapAsWkb: wrappedGeometryColumnNames,\n })\n : createDeckMapDashboardDatasetQuery(\n {tableName: '__missing_dashboard_map_dataset__'},\n filter,\n {sampleRows: maxRows},\n ),\n [wrappedGeometryColumnNames, maxRows, source],\n );\n const queryError = useCallback(\n (err: Error) => {\n onDatasetState(datasetId, {\n arrowTable: undefined,\n error: err,\n isLoading: false,\n client: null,\n isSampled: false,\n wrappedGeometryColumnNames,\n });\n },\n [datasetId, onDatasetState, wrappedGeometryColumnNames],\n );\n const sourceKey = isDeckMapDashboardTableDatasetSource(source)\n ? source.tableName\n : isDeckMapDashboardSqlDatasetSource(source)\n ? ''\n : (dashboard.selectedTable ?? '');\n const sourceQueryKey = isDeckMapDashboardSqlDatasetSource(source)\n ? source.sqlQuery\n : isDeckMapDashboardTableDatasetSource(source)\n ? (source.transformSql ?? '')\n : '';\n const {data, error, isLoading, client} = useMosaicClient({\n id: `${panel.id}:${datasetId}:${sourceKey}:${sourceQueryKey}:${maxRows}:${geometryColumnsToWrapAsWkb?.join(',') ?? 'pending'}`,\n selectionName,\n query,\n queryError,\n enabled: Boolean(source) && geometryProbeReady,\n runtimeIssueContext,\n runtimeIssueReporter,\n });\n\n // Register client for panel reset button\n usePanelClientRegistration(dashboard.id, panel.id, client ? [client] : []);\n\n const isSampled = Boolean(data && data.numRows >= maxRows);\n\n useEffect(() => {\n onDatasetState(datasetId, {\n arrowTable: data ?? undefined,\n error,\n isLoading: isLoading || !geometryProbeReady,\n client,\n isSampled,\n wrappedGeometryColumnNames,\n });\n\n return () => {\n onDatasetState(datasetId, undefined);\n };\n }, [\n client,\n data,\n datasetId,\n error,\n geometryProbeReady,\n isLoading,\n isSampled,\n onDatasetState,\n wrappedGeometryColumnNames,\n ]);\n\n return null;\n}\n\nfunction createPointRadiusPredicate(\n interaction: DeckMapDashboardInteractionConfig,\n coordinate: [number, number],\n) {\n const [longitude, latitude] = coordinate;\n const radiusMeters = interaction.radiusMeters ?? 500;\n const metersPerDegree = 111_320;\n const cosLatitude = Math.cos(latitude * (Math.PI / 180));\n const radiusSquared = radiusMeters * radiusMeters;\n\n return sql`(\n pow((${column(interaction.longitudeColumn)} - ${longitude}) * ${\n cosLatitude * metersPerDegree\n }, 2) +\n pow((${column(interaction.latitudeColumn)} - ${latitude}) * ${\n metersPerDegree\n }, 2)\n ) < ${radiusSquared}`;\n}\n\ntype DeckMapInteractionEvent = {\n coordinate?: number[] | null;\n object?: unknown;\n index?: number;\n picked?: boolean;\n};\n\nfunction getCoordinate(\n info: DeckMapInteractionEvent,\n): [number, number] | undefined {\n return info.coordinate && info.coordinate.length >= 2\n ? [info.coordinate[0]!, info.coordinate[1]!]\n : undefined;\n}\n\nfunction isPickedMapFeature(info: DeckMapInteractionEvent) {\n return Boolean(info.picked || info.object || (info.index ?? -1) >= 0);\n}\n\nfunction DeckMapDashboardHeaderActions({\n panel,\n}: MosaicDashboardPanelRendererProps) {\n const mapConfig = asDeckJsonMapConfig(panel.config);\n const canFitView = Boolean(mapConfig?.fitToData);\n const fitViewLabel = canFitView\n ? 'Fit map view to data'\n : 'Fit view unavailable for this map';\n\n return (\n <div className=\"flex items-center gap-0.5\">\n <Tooltip>\n <TooltipTrigger asChild>\n <span\n className=\"inline-flex\"\n tabIndex={canFitView ? undefined : 0}\n aria-label={canFitView ? undefined : fitViewLabel}\n >\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-6 w-6\"\n aria-label={fitViewLabel}\n disabled={!canFitView}\n onClick={() => emitDeckMapDashboardFitRequest(panel.id)}\n >\n <FocusIcon className=\"h-3.5 w-3.5\" />\n </Button>\n </span>\n </TooltipTrigger>\n <TooltipContent>{fitViewLabel}</TooltipContent>\n </Tooltip>\n </div>\n );\n}\n\nfunction DeckMapDashboardRenderer({\n dashboard,\n dashboardId,\n panel,\n selectionName,\n}: MosaicDashboardPanelRendererProps) {\n const mapConfig = asDeckJsonMapConfig(panel.config);\n const isCustomMode = mapConfig?.configMode === 'custom';\n const getSelection = useStoreWithMosaicDashboard(\n (state) => state.mosaic.getSelection,\n );\n const issue = useStoreWithMosaicDashboard((state) =>\n state.mosaicDashboard.getPanelIssue(dashboardId, panel.id),\n );\n const clearPanelIssue = useStoreWithMosaicDashboard(\n (state) => state.mosaicDashboard.clearPanelIssue,\n );\n\n // Clear runtime issues when the active table or panel config changes so\n // the map can recover (e.g., after switching tables or AI updating the map).\n useEffect(() => {\n clearPanelIssue(dashboardId, panel.id);\n }, [\n clearPanelIssue,\n dashboard.selectedTable,\n dashboardId,\n panel.config,\n panel.id,\n ]);\n\n const selection = useMemo<Selection>(\n () => getSelection(selectionName, 'crossfilter'),\n [getSelection, selectionName],\n );\n const [container, setContainer] = useState<HTMLDivElement | null>(null);\n const deckMapRef = useRef<DeckJsonMapHandle>(null);\n const [sampledDismissed, setSampledDismissed] = useState(false);\n\n const {\n datasetStates,\n handleDatasetState,\n runtimeIssueContext,\n runtimeIssueReporter,\n handleRenderingError,\n } = useDeckMapDatasets({dashboardId, panel});\n\n const {fitToData} = useDeckMapFitToBounds({\n panelId: panel.id,\n dashboard,\n panel,\n container,\n deckMapRef,\n });\n\n const handleBrushEvent = useCallback(\n (info: DeckMapInteractionEvent) => {\n const interaction = mapConfig?.interaction;\n if (!interaction) {\n return;\n }\n\n const client = datasetStates[interaction.dataset]?.client as\n | MosaicClient\n | null\n | undefined;\n if (!client) {\n return;\n }\n const coordinate = getCoordinate(info);\n if (!coordinate) {\n return;\n }\n if (interaction.event !== 'click' && !isPickedMapFeature(info)) {\n selection.reset(\n selection.clauses.filter((clause) => clause.source === client),\n );\n return;\n }\n\n const radiusMeters = interaction.radiusMeters ?? 500;\n selection.update({\n source: client,\n clients: new Set([client]),\n value: [coordinate[0], coordinate[1], radiusMeters],\n predicate: createPointRadiusPredicate(interaction, coordinate),\n });\n },\n [datasetStates, mapConfig?.interaction, selection],\n );\n\n const datasetError = useMemo(() => {\n for (const state of Object.values(datasetStates)) {\n if (state.error) return state.error;\n }\n return undefined;\n }, [datasetStates]);\n\n const missingColumns = useMemo(\n () => detectMissingColumns(mapConfig ?? undefined, datasetStates),\n [mapConfig, datasetStates],\n );\n\n const maxRows =\n mapConfig?.dataPolicy?.maxRows ?? DEFAULT_DECK_MAP_MAX_DATA_POINTS;\n\n const mapContent = !mapConfig ? (\n <div className=\"text-muted-foreground flex h-full items-center justify-center p-4 text-sm\">\n Invalid map panel config.\n </div>\n ) : Object.entries(mapConfig.datasets).length === 0 ? (\n <div className=\"text-muted-foreground flex h-full items-center justify-center p-4 text-sm\">\n Map panels require at least one dataset.\n </div>\n ) : (\n <>\n {Object.entries(mapConfig.datasets).map(([datasetId, dataset]) => (\n <DeckMapDashboardDatasetClient\n key={datasetId}\n dashboard={dashboard}\n dataset={dataset}\n datasetId={datasetId}\n fitToData={fitToData ?? undefined}\n panel={panel}\n onDatasetState={handleDatasetState}\n runtimeIssueContext={runtimeIssueContext}\n runtimeIssueReporter={runtimeIssueReporter}\n selectionName={selectionName}\n maxRows={maxRows}\n />\n ))}\n {issue ? (\n <DeckMapRuntimeIssuePanel issue={issue} />\n ) : datasetError ? (\n <DeckMapRuntimeIssuePanel\n issue={{\n kind: 'sql-error',\n panelId: panel.id,\n chartType: DECK_MAP_DASHBOARD_PANEL_TYPE,\n message: datasetError.message,\n recoverable: true,\n }}\n />\n ) : (\n <div ref={setContainer} className=\"relative h-full w-full\">\n {Object.values(datasetStates).some((s) => s.isSampled) &&\n !sampledDismissed && (\n <div className=\"bg-background/80 text-muted-foreground absolute top-2 left-2 z-10 flex items-center gap-1.5 rounded px-2 py-1 text-xs shadow\">\n <span>Data sampled to {maxRows.toLocaleString()} rows</span>\n <button\n className=\"text-muted-foreground/60 hover:text-foreground -mr-0.5 ml-0.5\"\n onClick={() => setSampledDismissed(true)}\n >\n ×\n </button>\n </div>\n )}\n {missingColumns.length > 0 && !isCustomMode && (\n <Tooltip>\n <TooltipTrigger asChild>\n <span\n className={`absolute left-2 z-10 flex h-5 w-5 items-center justify-center ${\n Object.values(datasetStates).some((s) => s.isSampled) &&\n !sampledDismissed\n ? 'top-9'\n : 'top-2'\n }`}\n >\n <AlertTriangleIcon className=\"h-4 w-4 text-amber-500 drop-shadow-sm\" />\n </span>\n </TooltipTrigger>\n <TooltipContent side=\"right\">\n <p className=\"text-xs font-medium\">Missing columns:</p>\n <p className=\"text-xs\">{missingColumns.join(', ')}</p>\n </TooltipContent>\n </Tooltip>\n )}\n <DeckJsonMap\n ref={deckMapRef}\n className=\"h-full w-full px-0.5 pb-0.5\"\n spec={mapConfig.spec}\n datasets={\n mapConfig\n ? createDeckMapDashboardDatasets(mapConfig, datasetStates)\n : {}\n }\n mapStyle={mapConfig.mapStyle}\n mapProps={mapConfig.mapProps}\n showLegends={mapConfig.showLegends !== false}\n onRenderingError={handleRenderingError}\n deckProps={{\n controller: true,\n ...(mapConfig.interaction\n ? (mapConfig.interaction.event ?? 'hover') === 'click'\n ? {onClick: handleBrushEvent}\n : {onHover: handleBrushEvent}\n : {}),\n }}\n />\n </div>\n )}\n </>\n );\n\n return mapContent;\n}\n\nexport const deckMapDashboardPanelRenderer: MosaicDashboardPanelRenderer = {\n component: DeckMapDashboardRenderer,\n headerActions: DeckMapDashboardHeaderActions,\n icon: MapIcon,\n settings: DeckMapDashboardSettings,\n};\n\nexport const deckMapDashboardAddPanelAction: import('@sqlrooms/mosaic').MosaicDashboardAddPanelAction =\n {\n type: DECK_MAP_DASHBOARD_PANEL_TYPE,\n label: 'Map',\n icon: MapIcon,\n createPanel: ({selectedTable}) => {\n if (\n selectedTable &&\n (findLongitudeLatitudeColumns(selectedTable) ??\n findGeometryColumn(selectedTable))\n ) {\n return createDeckMapDashboardPanelConfigForTable({\n title: `${selectedTable.tableName} map`,\n tableName: selectedTable.tableName,\n columns: selectedTable.columns,\n tableReference: selectedTable.table,\n });\n }\n\n return createEmptyDeckMapDashboardPanelConfig(\n selectedTable ? `${selectedTable.tableName} map` : 'Map',\n );\n },\n };\n"]}
@@ -11,6 +11,11 @@ export type DeckMapDashboardDatasetClientState = {
11
11
  error?: Error;
12
12
  client: unknown;
13
13
  isSampled?: boolean;
14
+ /**
15
+ * Native GEOMETRY columns wrapped via ST_AsWKB for this query.
16
+ * Only force `geometryEncodingHint: "wkb"` when the bound column is listed.
17
+ */
18
+ wrappedGeometryColumnNames?: readonly string[];
14
19
  };
15
20
  export declare function resolveDeckMapDashboardDatasetSource(options: {
16
21
  dashboard: MosaicDashboardEntryType;
@@ -18,8 +23,12 @@ export declare function resolveDeckMapDashboardDatasetSource(options: {
18
23
  dataset?: DeckMapDashboardDatasetConfig;
19
24
  fitToData?: DeckMapDashboardFitToDataConfig;
20
25
  }): DeckMapDashboardDatasetSource | undefined;
26
+ /** Unfiltered dataset SQL for DESCRIBE / Mosaic (before sample/filters). */
27
+ export declare function createDeckMapDashboardDatasetSourceSql(source: DeckMapDashboardDatasetSource): string;
21
28
  export declare function createDeckMapDashboardDatasetQuery(source: DeckMapDashboardDatasetSource, filter: unknown, options?: {
22
29
  sampleRows?: number;
30
+ /** Native GEOMETRY columns to project with ST_AsWKB (from DESCRIBE). */
31
+ geometryColumnsToWrapAsWkb?: readonly string[];
23
32
  }): import("@uwdata/mosaic-sql").SelectQuery;
24
- export declare function createDeckMapDashboardDatasets(mapConfig: DeckMapDashboardPanelConfig, datasetStates: Record<string, Pick<DeckMapDashboardDatasetClientState, 'arrowTable'>>): DeckJsonMapProps['datasets'];
33
+ export declare function createDeckMapDashboardDatasets(mapConfig: DeckMapDashboardPanelConfig, datasetStates: Record<string, Pick<DeckMapDashboardDatasetClientState, 'arrowTable' | 'wrappedGeometryColumnNames'>>): DeckJsonMapProps['datasets'];
25
34
  //# sourceMappingURL=dashboardConfig.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dashboardConfig.d.ts","sourceRoot":"","sources":["../src/dashboardConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,wBAAwB,EAC7B,KAAK,8BAA8B,EAEpC,MAAM,kBAAkB,CAAC;AAQ1B,OAAO,KAAK,EAAC,KAAK,IAAI,UAAU,EAAC,MAAM,cAAc,CAAC;AAEtD,OAAO,EAGL,KAAK,6BAA6B,EAClC,KAAK,6BAA6B,EAClC,KAAK,+BAA+B,EACpC,KAAK,2BAA2B,EACjC,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,mBAAmB,EACnB,iCAAiC,EACjC,6BAA6B,EAC7B,gCAAgC,EAChC,kCAAkC,EAClC,oCAAoC,GACrC,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,wCAAwC,EACxC,6BAA6B,EAC7B,6BAA6B,EAC7B,+BAA+B,EAC/B,iCAAiC,EACjC,2BAA2B,GAC5B,MAAM,aAAa,CAAC;AACrB,YAAY,EAAC,gBAAgB,EAAC,MAAM,SAAS,CAAC;AAC9C,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,SAAS,CAAC;AAE9C,MAAM,MAAM,kCAAkC,GAAG;IAC/C,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,wBAAgB,oCAAoC,CAAC,OAAO,EAAE;IAC5D,SAAS,EAAE,wBAAwB,CAAC;IACpC,KAAK,EAAE,8BAA8B,CAAC;IACtC,OAAO,CAAC,EAAE,6BAA6B,CAAC;IACxC,SAAS,CAAC,EAAE,+BAA+B,CAAC;CAC7C,GAAG,6BAA6B,GAAG,SAAS,CA6B5C;AAeD,wBAAgB,kCAAkC,CAChD,MAAM,EAAE,6BAA6B,EACrC,MAAM,EAAE,OAAO,EACf,OAAO,CAAC,EAAE;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAC,4CA2BhC;AAUD,wBAAgB,8BAA8B,CAC5C,SAAS,EAAE,2BAA2B,EACtC,aAAa,EAAE,MAAM,CACnB,MAAM,EACN,IAAI,CAAC,kCAAkC,EAAE,YAAY,CAAC,CACvD,GACA,gBAAgB,CAAC,UAAU,CAAC,CAW9B"}
1
+ {"version":3,"file":"dashboardConfig.d.ts","sourceRoot":"","sources":["../src/dashboardConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,wBAAwB,EAC7B,KAAK,8BAA8B,EAEpC,MAAM,kBAAkB,CAAC;AAQ1B,OAAO,KAAK,EAAC,KAAK,IAAI,UAAU,EAAC,MAAM,cAAc,CAAC;AAGtD,OAAO,EAGL,KAAK,6BAA6B,EAClC,KAAK,6BAA6B,EAClC,KAAK,+BAA+B,EACpC,KAAK,2BAA2B,EACjC,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,mBAAmB,EACnB,iCAAiC,EACjC,6BAA6B,EAC7B,gCAAgC,EAChC,kCAAkC,EAClC,oCAAoC,GACrC,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,wCAAwC,EACxC,6BAA6B,EAC7B,6BAA6B,EAC7B,+BAA+B,EAC/B,iCAAiC,EACjC,2BAA2B,GAC5B,MAAM,aAAa,CAAC;AACrB,YAAY,EAAC,gBAAgB,EAAC,MAAM,SAAS,CAAC;AAC9C,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,SAAS,CAAC;AAE9C,MAAM,MAAM,kCAAkC,GAAG;IAC/C,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,0BAA0B,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAChD,CAAC;AAEF,wBAAgB,oCAAoC,CAAC,OAAO,EAAE;IAC5D,SAAS,EAAE,wBAAwB,CAAC;IACpC,KAAK,EAAE,8BAA8B,CAAC;IACtC,OAAO,CAAC,EAAE,6BAA6B,CAAC;IACxC,SAAS,CAAC,EAAE,+BAA+B,CAAC;CAC7C,GAAG,6BAA6B,GAAG,SAAS,CA2B5C;AAeD,4EAA4E;AAC5E,wBAAgB,sCAAsC,CACpD,MAAM,EAAE,6BAA6B,GACpC,MAAM,CAWR;AAED,wBAAgB,kCAAkC,CAChD,MAAM,EAAE,6BAA6B,EACrC,MAAM,EAAE,OAAO,EACf,OAAO,CAAC,EAAE;IACR,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,0BAA0B,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAChD,4CA2CF;AAUD,wBAAgB,8BAA8B,CAC5C,SAAS,EAAE,2BAA2B,EACtC,aAAa,EAAE,MAAM,CACnB,MAAM,EACN,IAAI,CACF,kCAAkC,EAClC,YAAY,GAAG,4BAA4B,CAC5C,CACF,GACA,gBAAgB,CAAC,UAAU,CAAC,CAsB9B"}
@@ -2,14 +2,13 @@ import { Query, } from '@sqlrooms/mosaic';
2
2
  import { getTableIdentity, makeQualifiedTableName, parseQualifiedSqlIdentifier, quoteParsedRawSqlTableReference, } from '@sqlrooms/duckdb';
3
3
  import { verbatim } from '@uwdata/mosaic-sql';
4
4
  import { createDeckTableDatasetSql } from './datasets/tableDatasetSql';
5
+ import { wrapSqlGeometryColumnsAsWkb } from './datasets/wrapGeometryAsWkb';
5
6
  import { isDeckMapDashboardSqlDatasetSource, isDeckMapDashboardTableDatasetSource, } from './mapConfig';
6
7
  export { asDeckJsonMapConfig, createDeckMapDashboardPanelConfig, DECK_MAP_DASHBOARD_PANEL_TYPE, DEFAULT_DECK_MAP_MAX_DATA_POINTS, isDeckMapDashboardSqlDatasetSource, isDeckMapDashboardTableDatasetSource, } from './mapConfig';
7
8
  export function resolveDeckMapDashboardDatasetSource(options) {
8
9
  const datasetSource = options.dataset?.source;
9
10
  const dashboardTable = stripCatalogPrefix(options.dashboard.selectedTable);
10
- // The dashboard's selected table always takes precedence as the data source.
11
- // When the user switches the table in the selector, structured table-backed
12
- // datasets update while literal SQL remains pinned to its authored query.
11
+ // Selected table wins for table sources; sqlQuery stays pinned.
13
12
  if (isDeckMapDashboardSqlDatasetSource(datasetSource)) {
14
13
  return datasetSource;
15
14
  }
@@ -39,6 +38,17 @@ function stripCatalogPrefix(tableName) {
39
38
  table: parsed.table,
40
39
  }));
41
40
  }
41
+ /** Unfiltered dataset SQL for DESCRIBE / Mosaic (before sample/filters). */
42
+ export function createDeckMapDashboardDatasetSourceSql(source) {
43
+ if (isDeckMapDashboardSqlDatasetSource(source)) {
44
+ return source.sqlQuery.trim().replace(/(?:\s*;+\s*)+$/, '');
45
+ }
46
+ if (isDeckMapDashboardTableDatasetSource(source) &&
47
+ !source.transformSql?.trim()) {
48
+ return `SELECT * FROM ${getDeckMapDatasetSourceTableReference(source.tableName)}`;
49
+ }
50
+ return createDeckTableDatasetSql(source);
51
+ }
42
52
  export function createDeckMapDashboardDatasetQuery(source, filter, options) {
43
53
  const isSqlSource = isDeckMapDashboardSqlDatasetSource(source);
44
54
  const isTableSource = isDeckMapDashboardTableDatasetSource(source);
@@ -46,18 +56,32 @@ export function createDeckMapDashboardDatasetQuery(source, filter, options) {
46
56
  const tableReference = isDirectTableSource
47
57
  ? getDeckMapDatasetSourceTableReference(source.tableName)
48
58
  : '';
49
- // Apply USING SAMPLE at the source level so Mosaic filters work on top.
50
- const sourceExpr = isSqlSource
51
- ? `(${source.sqlQuery})`
52
- : isDirectTableSource
53
- ? tableReference
54
- : `(${createDeckTableDatasetSql(source)})`;
55
- const sampledSource = options?.sampleRows
56
- ? `(SELECT * FROM ${sourceExpr} USING SAMPLE ${options.sampleRows} ROWS)`
57
- : sourceExpr;
58
- const query = isSqlSource || !isDirectTableSource || options?.sampleRows
59
+ const baseSql = createDeckMapDashboardDatasetSourceSql(source);
60
+ // Sample before WKB so ST_AsWKB runs only on sampled rows.
61
+ const sampledSql = options?.sampleRows
62
+ ? `SELECT * FROM (${baseSql}) AS "__sqlrooms_sample_source" USING SAMPLE ${options.sampleRows} ROWS`
63
+ : baseSql;
64
+ const wrappedSql = wrapSqlGeometryColumnsAsWkb(sampledSql, options?.geometryColumnsToWrapAsWkb ?? []);
65
+ const usedWrap = Boolean(wrappedSql);
66
+ let sourceExpr;
67
+ if (wrappedSql) {
68
+ sourceExpr = `(${wrappedSql})`;
69
+ }
70
+ else if (options?.sampleRows) {
71
+ sourceExpr = `(${sampledSql})`;
72
+ }
73
+ else if (isSqlSource) {
74
+ sourceExpr = `(${source.sqlQuery})`;
75
+ }
76
+ else if (isDirectTableSource) {
77
+ sourceExpr = tableReference;
78
+ }
79
+ else {
80
+ sourceExpr = `(${createDeckTableDatasetSql(source)})`;
81
+ }
82
+ const query = usedWrap || options?.sampleRows || isSqlSource || !isDirectTableSource
59
83
  ? Query.from({
60
- __dashboard_map_dataset: verbatim(sampledSource),
84
+ __dashboard_map_dataset: verbatim(sourceExpr),
61
85
  })
62
86
  : Query.from({ __dashboard_map_dataset: verbatim(tableReference) });
63
87
  return query.select('*').where(filter);
@@ -70,13 +94,22 @@ function getDeckMapDatasetSourceTableReference(tableName) {
70
94
  return tableReference;
71
95
  }
72
96
  export function createDeckMapDashboardDatasets(mapConfig, datasetStates) {
73
- return Object.fromEntries(Object.entries(mapConfig.datasets).map(([datasetId, dataset]) => [
74
- datasetId,
75
- {
76
- arrowTable: datasetStates[datasetId]?.arrowTable,
77
- geometryColumn: dataset.geometryColumn,
78
- geometryEncodingHint: dataset.geometryEncodingHint,
79
- },
80
- ]));
97
+ return Object.fromEntries(Object.entries(mapConfig.datasets).map(([datasetId, dataset]) => {
98
+ const wrapped = datasetStates[datasetId]?.wrappedGeometryColumnNames ?? [];
99
+ const geometryColumn = dataset.geometryColumn;
100
+ const wrappedConfiguredColumn = typeof geometryColumn === 'string' &&
101
+ geometryColumn.length > 0 &&
102
+ wrapped.includes(geometryColumn);
103
+ return [
104
+ datasetId,
105
+ {
106
+ arrowTable: datasetStates[datasetId]?.arrowTable,
107
+ geometryColumn,
108
+ geometryEncodingHint: wrappedConfiguredColumn
109
+ ? 'wkb'
110
+ : dataset.geometryEncodingHint,
111
+ },
112
+ ];
113
+ }));
81
114
  }
82
115
  //# sourceMappingURL=dashboardConfig.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dashboardConfig.js","sourceRoot":"","sources":["../src/dashboardConfig.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type MosaicDashboardEntryType,\n type MosaicDashboardPanelConfigType,\n Query,\n} from '@sqlrooms/mosaic';\nimport {\n getTableIdentity,\n makeQualifiedTableName,\n parseQualifiedSqlIdentifier,\n quoteParsedRawSqlTableReference,\n} from '@sqlrooms/duckdb';\nimport {verbatim} from '@uwdata/mosaic-sql';\nimport type {Table as ArrowTable} from 'apache-arrow';\nimport {createDeckTableDatasetSql} from './datasets/tableDatasetSql';\nimport {\n isDeckMapDashboardSqlDatasetSource,\n isDeckMapDashboardTableDatasetSource,\n type DeckMapDashboardDatasetConfig,\n type DeckMapDashboardDatasetSource,\n type DeckMapDashboardFitToDataConfig,\n type DeckMapDashboardPanelConfig,\n} from './mapConfig';\nexport {\n asDeckJsonMapConfig,\n createDeckMapDashboardPanelConfig,\n DECK_MAP_DASHBOARD_PANEL_TYPE,\n DEFAULT_DECK_MAP_MAX_DATA_POINTS,\n isDeckMapDashboardSqlDatasetSource,\n isDeckMapDashboardTableDatasetSource,\n} from './mapConfig';\nexport type {\n CreateDeckMapDashboardPanelConfigOptions,\n DeckMapDashboardDatasetConfig,\n DeckMapDashboardDatasetSource,\n DeckMapDashboardFitToDataConfig,\n DeckMapDashboardInteractionConfig,\n DeckMapDashboardPanelConfig,\n} from './mapConfig';\nexport type {DeckJsonMapProps} from './types';\nimport type {DeckJsonMapProps} from './types';\n\nexport type DeckMapDashboardDatasetClientState = {\n arrowTable?: ArrowTable;\n isLoading: boolean;\n error?: Error;\n client: unknown;\n isSampled?: boolean;\n};\n\nexport function resolveDeckMapDashboardDatasetSource(options: {\n dashboard: MosaicDashboardEntryType;\n panel: MosaicDashboardPanelConfigType;\n dataset?: DeckMapDashboardDatasetConfig;\n fitToData?: DeckMapDashboardFitToDataConfig;\n}): DeckMapDashboardDatasetSource | undefined {\n const datasetSource = options.dataset?.source;\n const dashboardTable = stripCatalogPrefix(options.dashboard.selectedTable);\n\n // The dashboard's selected table always takes precedence as the data source.\n // When the user switches the table in the selector, structured table-backed\n // datasets update while literal SQL remains pinned to its authored query.\n if (isDeckMapDashboardSqlDatasetSource(datasetSource)) {\n return datasetSource;\n }\n\n const baseTableName =\n dashboardTable ||\n (isDeckMapDashboardTableDatasetSource(datasetSource)\n ? datasetSource.tableName\n : undefined);\n if (!baseTableName) {\n return undefined;\n }\n\n const resolvedSource: DeckMapDashboardDatasetSource = {\n tableName: baseTableName,\n ...(isDeckMapDashboardTableDatasetSource(datasetSource) &&\n datasetSource.transformSql\n ? {transformSql: datasetSource.transformSql}\n : {}),\n };\n\n return resolvedSource;\n}\n\nfunction stripCatalogPrefix(tableName: string | undefined) {\n const parsed = parseQualifiedSqlIdentifier(tableName);\n if (!parsed?.database || !parsed.schema || !parsed.table) {\n return tableName;\n }\n return getTableIdentity(\n makeQualifiedTableName({\n schema: parsed.schema,\n table: parsed.table,\n }),\n );\n}\n\nexport function createDeckMapDashboardDatasetQuery(\n source: DeckMapDashboardDatasetSource,\n filter: unknown,\n options?: {sampleRows?: number},\n) {\n const isSqlSource = isDeckMapDashboardSqlDatasetSource(source);\n const isTableSource = isDeckMapDashboardTableDatasetSource(source);\n const isDirectTableSource = isTableSource && !source.transformSql;\n const tableReference = isDirectTableSource\n ? getDeckMapDatasetSourceTableReference(source.tableName)\n : '';\n // Apply USING SAMPLE at the source level so Mosaic filters work on top.\n const sourceExpr: string = isSqlSource\n ? `(${source.sqlQuery})`\n : isDirectTableSource\n ? tableReference\n : `(${createDeckTableDatasetSql(source)})`;\n\n const sampledSource = options?.sampleRows\n ? `(SELECT * FROM ${sourceExpr} USING SAMPLE ${options.sampleRows} ROWS)`\n : sourceExpr;\n\n const query =\n isSqlSource || !isDirectTableSource || options?.sampleRows\n ? Query.from({\n __dashboard_map_dataset: verbatim(sampledSource),\n })\n : Query.from({__dashboard_map_dataset: verbatim(tableReference)});\n\n return query.select('*').where(filter as never);\n}\n\nfunction getDeckMapDatasetSourceTableReference(tableName: string | undefined) {\n const tableReference = quoteParsedRawSqlTableReference(tableName);\n if (!tableReference) {\n throw new Error('Deck map dataset query requires a valid table source.');\n }\n return tableReference;\n}\n\nexport function createDeckMapDashboardDatasets(\n mapConfig: DeckMapDashboardPanelConfig,\n datasetStates: Record<\n string,\n Pick<DeckMapDashboardDatasetClientState, 'arrowTable'>\n >,\n): DeckJsonMapProps['datasets'] {\n return Object.fromEntries(\n Object.entries(mapConfig.datasets).map(([datasetId, dataset]) => [\n datasetId,\n {\n arrowTable: datasetStates[datasetId]?.arrowTable,\n geometryColumn: dataset.geometryColumn,\n geometryEncodingHint: dataset.geometryEncodingHint,\n },\n ]),\n );\n}\n"]}
1
+ {"version":3,"file":"dashboardConfig.js","sourceRoot":"","sources":["../src/dashboardConfig.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type MosaicDashboardEntryType,\n type MosaicDashboardPanelConfigType,\n Query,\n} from '@sqlrooms/mosaic';\nimport {\n getTableIdentity,\n makeQualifiedTableName,\n parseQualifiedSqlIdentifier,\n quoteParsedRawSqlTableReference,\n} from '@sqlrooms/duckdb';\nimport {verbatim} from '@uwdata/mosaic-sql';\nimport type {Table as ArrowTable} from 'apache-arrow';\nimport {createDeckTableDatasetSql} from './datasets/tableDatasetSql';\nimport {wrapSqlGeometryColumnsAsWkb} from './datasets/wrapGeometryAsWkb';\nimport {\n isDeckMapDashboardSqlDatasetSource,\n isDeckMapDashboardTableDatasetSource,\n type DeckMapDashboardDatasetConfig,\n type DeckMapDashboardDatasetSource,\n type DeckMapDashboardFitToDataConfig,\n type DeckMapDashboardPanelConfig,\n} from './mapConfig';\nexport {\n asDeckJsonMapConfig,\n createDeckMapDashboardPanelConfig,\n DECK_MAP_DASHBOARD_PANEL_TYPE,\n DEFAULT_DECK_MAP_MAX_DATA_POINTS,\n isDeckMapDashboardSqlDatasetSource,\n isDeckMapDashboardTableDatasetSource,\n} from './mapConfig';\nexport type {\n CreateDeckMapDashboardPanelConfigOptions,\n DeckMapDashboardDatasetConfig,\n DeckMapDashboardDatasetSource,\n DeckMapDashboardFitToDataConfig,\n DeckMapDashboardInteractionConfig,\n DeckMapDashboardPanelConfig,\n} from './mapConfig';\nexport type {DeckJsonMapProps} from './types';\nimport type {DeckJsonMapProps} from './types';\n\nexport type DeckMapDashboardDatasetClientState = {\n arrowTable?: ArrowTable;\n isLoading: boolean;\n error?: Error;\n client: unknown;\n isSampled?: boolean;\n /**\n * Native GEOMETRY columns wrapped via ST_AsWKB for this query.\n * Only force `geometryEncodingHint: \"wkb\"` when the bound column is listed.\n */\n wrappedGeometryColumnNames?: readonly string[];\n};\n\nexport function resolveDeckMapDashboardDatasetSource(options: {\n dashboard: MosaicDashboardEntryType;\n panel: MosaicDashboardPanelConfigType;\n dataset?: DeckMapDashboardDatasetConfig;\n fitToData?: DeckMapDashboardFitToDataConfig;\n}): DeckMapDashboardDatasetSource | undefined {\n const datasetSource = options.dataset?.source;\n const dashboardTable = stripCatalogPrefix(options.dashboard.selectedTable);\n\n // Selected table wins for table sources; sqlQuery stays pinned.\n if (isDeckMapDashboardSqlDatasetSource(datasetSource)) {\n return datasetSource;\n }\n\n const baseTableName =\n dashboardTable ||\n (isDeckMapDashboardTableDatasetSource(datasetSource)\n ? datasetSource.tableName\n : undefined);\n if (!baseTableName) {\n return undefined;\n }\n\n const resolvedSource: DeckMapDashboardDatasetSource = {\n tableName: baseTableName,\n ...(isDeckMapDashboardTableDatasetSource(datasetSource) &&\n datasetSource.transformSql\n ? {transformSql: datasetSource.transformSql}\n : {}),\n };\n\n return resolvedSource;\n}\n\nfunction stripCatalogPrefix(tableName: string | undefined) {\n const parsed = parseQualifiedSqlIdentifier(tableName);\n if (!parsed?.database || !parsed.schema || !parsed.table) {\n return tableName;\n }\n return getTableIdentity(\n makeQualifiedTableName({\n schema: parsed.schema,\n table: parsed.table,\n }),\n );\n}\n\n/** Unfiltered dataset SQL for DESCRIBE / Mosaic (before sample/filters). */\nexport function createDeckMapDashboardDatasetSourceSql(\n source: DeckMapDashboardDatasetSource,\n): string {\n if (isDeckMapDashboardSqlDatasetSource(source)) {\n return source.sqlQuery.trim().replace(/(?:\\s*;+\\s*)+$/, '');\n }\n if (\n isDeckMapDashboardTableDatasetSource(source) &&\n !source.transformSql?.trim()\n ) {\n return `SELECT * FROM ${getDeckMapDatasetSourceTableReference(source.tableName)}`;\n }\n return createDeckTableDatasetSql(source);\n}\n\nexport function createDeckMapDashboardDatasetQuery(\n source: DeckMapDashboardDatasetSource,\n filter: unknown,\n options?: {\n sampleRows?: number;\n /** Native GEOMETRY columns to project with ST_AsWKB (from DESCRIBE). */\n geometryColumnsToWrapAsWkb?: readonly string[];\n },\n) {\n const isSqlSource = isDeckMapDashboardSqlDatasetSource(source);\n const isTableSource = isDeckMapDashboardTableDatasetSource(source);\n const isDirectTableSource = isTableSource && !source.transformSql;\n const tableReference = isDirectTableSource\n ? getDeckMapDatasetSourceTableReference(source.tableName)\n : '';\n\n const baseSql = createDeckMapDashboardDatasetSourceSql(source);\n\n // Sample before WKB so ST_AsWKB runs only on sampled rows.\n const sampledSql = options?.sampleRows\n ? `SELECT * FROM (${baseSql}) AS \"__sqlrooms_sample_source\" USING SAMPLE ${options.sampleRows} ROWS`\n : baseSql;\n\n const wrappedSql = wrapSqlGeometryColumnsAsWkb(\n sampledSql,\n options?.geometryColumnsToWrapAsWkb ?? [],\n );\n const usedWrap = Boolean(wrappedSql);\n\n let sourceExpr: string;\n if (wrappedSql) {\n sourceExpr = `(${wrappedSql})`;\n } else if (options?.sampleRows) {\n sourceExpr = `(${sampledSql})`;\n } else if (isSqlSource) {\n sourceExpr = `(${source.sqlQuery})`;\n } else if (isDirectTableSource) {\n sourceExpr = tableReference;\n } else {\n sourceExpr = `(${createDeckTableDatasetSql(source)})`;\n }\n\n const query =\n usedWrap || options?.sampleRows || isSqlSource || !isDirectTableSource\n ? Query.from({\n __dashboard_map_dataset: verbatim(sourceExpr),\n })\n : Query.from({__dashboard_map_dataset: verbatim(tableReference)});\n\n return query.select('*').where(filter as never);\n}\n\nfunction getDeckMapDatasetSourceTableReference(tableName: string | undefined) {\n const tableReference = quoteParsedRawSqlTableReference(tableName);\n if (!tableReference) {\n throw new Error('Deck map dataset query requires a valid table source.');\n }\n return tableReference;\n}\n\nexport function createDeckMapDashboardDatasets(\n mapConfig: DeckMapDashboardPanelConfig,\n datasetStates: Record<\n string,\n Pick<\n DeckMapDashboardDatasetClientState,\n 'arrowTable' | 'wrappedGeometryColumnNames'\n >\n >,\n): DeckJsonMapProps['datasets'] {\n return Object.fromEntries(\n Object.entries(mapConfig.datasets).map(([datasetId, dataset]) => {\n const wrapped =\n datasetStates[datasetId]?.wrappedGeometryColumnNames ?? [];\n const geometryColumn = dataset.geometryColumn;\n const wrappedConfiguredColumn =\n typeof geometryColumn === 'string' &&\n geometryColumn.length > 0 &&\n wrapped.includes(geometryColumn);\n return [\n datasetId,\n {\n arrowTable: datasetStates[datasetId]?.arrowTable,\n geometryColumn,\n geometryEncodingHint: wrappedConfiguredColumn\n ? 'wkb'\n : dataset.geometryEncodingHint,\n },\n ];\n }),\n );\n}\n"]}
@@ -26,10 +26,9 @@ type PreparedDatasetStoreState = {
26
26
  /**
27
27
  * Ensure a cache entry exists for the given dataset key.
28
28
  *
29
- * If an entry already exists, this is a no-op other than touching its LRU
30
- * metadata. Otherwise the store creates a `loading` entry, resolves the
31
- * source table through DuckDB if needed, runs `prepareDeckDataset(...)`, and
32
- * stores the resulting `ready` or `error` state.
29
+ * If an entry already exists, this is a no-op besides refreshing the
30
+ * in-place LRU timestamp. Subscribers are not notified: a cache hit is not
31
+ * a dataset change, and notifying would rebuild every mounted map's layers.
33
32
  */
34
33
  ensureEntry: (options: {
35
34
  cacheKey: string;
@@ -1 +1 @@
1
- {"version":3,"file":"PreparedDatasetStore.d.ts","sourceRoot":"","sources":["../../src/datasets/PreparedDatasetStore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAGlD,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,wBAAwB,EAC9B,MAAM,UAAU,CAAC;AAWlB,OAAO,KAAK,EACV,yBAAyB,EACzB,2BAA2B,EAC5B,MAAM,SAAS,CAAC;AAEjB;;;;;GAKG;AACH,KAAK,yBAAyB,GAAG;IAC/B;;;;;OAKG;IACH,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACvC;;;;;;OAMG;IACH,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC;IACnD;;;;;;;OAOG;IACH,WAAW,EAAE,CAAC,OAAO,EAAE;QACrB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,CACV,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,MAAM,KACb,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;QACjC,KAAK,EAAE,gBAAgB,CAAC;KACzB,KAAK,IAAI,CAAC;IACX;;;;;;OAMG;IACH,cAAc,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C;;;;;;OAMG;IACH,YAAY,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAC3D;;;;;;;OAOG;IACH,uBAAuB,EAAE,CAAC,OAAO,EAAE;QACjC,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;QAC3C,UAAU,EAAE,CACV,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,MAAM,KACb,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;QACjC,iBAAiB,EAAE,MAAM,CAAC;KAC3B,KAAK,IAAI,CAAC;CACZ,CAAC;AAwBF;;;;;;;;;;;;GAYG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,GAAE,2BAAgC,yDA8O1C;AAED;;;;;;;;;GASG;AACH,wBAAgB,+BAA+B,CAAC,OAAO,EAAE;IACvD,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,yBAAyB,CAAC;CACnC,GAAG,wBAAwB,CAqB3B;AAED;;;;;;GAMG;AACH,wBAAgB,gCAAgC,CAAC,OAAO,EAAE;IACxD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAC3C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC;IACnD,iBAAiB,EAAE,MAAM,CAAC;CAC3B,GAAG,MAAM,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAc3C;AAED;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,uDAA+B,CAAC"}
1
+ {"version":3,"file":"PreparedDatasetStore.d.ts","sourceRoot":"","sources":["../../src/datasets/PreparedDatasetStore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAGlD,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,wBAAwB,EAC9B,MAAM,UAAU,CAAC;AAUlB,OAAO,KAAK,EACV,yBAAyB,EACzB,2BAA2B,EAC5B,MAAM,SAAS,CAAC;AAQjB;;;;;GAKG;AACH,KAAK,yBAAyB,GAAG;IAC/B;;;;;OAKG;IACH,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACvC;;;;;;OAMG;IACH,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC;IACnD;;;;;;OAMG;IACH,WAAW,EAAE,CAAC,OAAO,EAAE;QACrB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,CACV,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,MAAM,KACb,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;QACjC,KAAK,EAAE,gBAAgB,CAAC;KACzB,KAAK,IAAI,CAAC;IACX;;;;;;OAMG;IACH,cAAc,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C;;;;;;OAMG;IACH,YAAY,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAC3D;;;;;;;OAOG;IACH,uBAAuB,EAAE,CAAC,OAAO,EAAE;QACjC,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;QAC3C,UAAU,EAAE,CACV,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,MAAM,KACb,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;QACjC,iBAAiB,EAAE,MAAM,CAAC;KAC3B,KAAK,IAAI,CAAC;CACZ,CAAC;AAwBF;;;;;;;;;;;;GAYG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,GAAE,2BAAgC,yDA8Q1C;AAED;;;;;;;;;GASG;AACH,wBAAgB,+BAA+B,CAAC,OAAO,EAAE;IACvD,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,yBAAyB,CAAC;CACnC,GAAG,wBAAwB,CAqB3B;AAED;;;;;;GAMG;AACH,wBAAgB,gCAAgC,CAAC,OAAO,EAAE;IACxD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAC3C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC;IACnD,iBAAiB,EAAE,MAAM,CAAC;CAC3B,GAAG,MAAM,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAc3C;AAED;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,uDAA+B,CAAC"}
@@ -1,9 +1,10 @@
1
1
  import { createStore } from 'zustand/vanilla';
2
2
  import { prepareDeckDataset } from '../prepare/prepareDeckDataset';
3
3
  import { isSqlDatasetInput, isTableDatasetInput, } from '../types';
4
- import { DEFAULT_MAX_PREPARED_DATASET_ENTRIES, cloneEntryWithConsumers, evictLruEntries, nextAccessTimestamp, resolvePreparedDatasetCacheKey, touchEntry, } from './helpers';
4
+ import { DEFAULT_MAX_PREPARED_DATASET_ENTRIES, cloneEntryWithConsumers, evictLruEntries, nextAccessTimestamp, resolvePreparedDatasetCacheKey, } from './helpers';
5
5
  import { resolveArrowTable } from './normalizeDatasets';
6
6
  import { createDeckTableDatasetSql } from './tableDatasetSql';
7
+ import { createDescribeDatasetSql, geometryColumnsNeedingWkbWrap, parseDescribeSqlColumns, wrapSqlGeometryColumnsAsWkb, } from './wrapGeometryAsWkb';
7
8
  function resolvePreparedDatasetDescriptors(options) {
8
9
  const { datasets, sqlSourceIdentity } = options;
9
10
  return Object.entries(datasets).map(([datasetId, input]) => ({
@@ -37,24 +38,48 @@ export function createPreparedDatasetStore(options = {}) {
37
38
  const existing = get().entries[cacheKey];
38
39
  if (existing) {
39
40
  if (existing.status !== 'loading') {
40
- set((state) => ({
41
- ...state,
42
- entries: {
43
- ...state.entries,
44
- [cacheKey]: touchEntry(existing),
45
- },
46
- }));
41
+ // Mutate the timestamp in place so LRU still works without replacing
42
+ // `entries` and forcing every DeckJsonMap to reconvert layers.
43
+ existing.lastAccessedAt = nextAccessTimestamp();
47
44
  }
48
45
  return;
49
46
  }
50
47
  const promise = Promise.resolve().then(async () => {
51
48
  try {
52
49
  let table = resolveArrowTable(input);
50
+ let geometryEncodingHint = input.geometryEncodingHint;
53
51
  if (!table &&
54
52
  (isSqlDatasetInput(input) || isTableDatasetInput(input))) {
55
- const sql = isSqlDatasetInput(input)
53
+ const baseSql = isSqlDatasetInput(input)
56
54
  ? input.sqlQuery
57
55
  : createDeckTableDatasetSql(input);
56
+ // Probe DuckDB logical types and project native GEOMETRY columns
57
+ // through ST_AsWKB so prepare/decode never sees undecodable blobs.
58
+ // Authored SQL is left intact — the wrap is a pipeline outer query.
59
+ let sql = baseSql;
60
+ try {
61
+ const describeHandle = await executeSql(createDescribeDatasetSql(baseSql));
62
+ if (describeHandle) {
63
+ const describeTable = await describeHandle;
64
+ const geometryColumns = geometryColumnsNeedingWkbWrap(parseDescribeSqlColumns(describeTable));
65
+ const wrapped = wrapSqlGeometryColumnsAsWkb(baseSql, geometryColumns);
66
+ if (wrapped) {
67
+ sql = wrapped;
68
+ // Only force the dataset-level hint to WKB when the configured
69
+ // geometry column was among the wrapped columns (or unset).
70
+ // An unrelated native GEOMETRY column must not make a WKT /
71
+ // GeoArrow geometryColumn decode as WKB.
72
+ const resolvedGeom = input.geometryColumn;
73
+ if (!resolvedGeom || geometryColumns.includes(resolvedGeom)) {
74
+ geometryEncodingHint = 'wkb';
75
+ }
76
+ }
77
+ }
78
+ }
79
+ catch {
80
+ // If DESCRIBE fails (e.g. missing spatial), fall through to the
81
+ // original SQL — prepare still surfaces decode errors.
82
+ }
58
83
  const queryHandle = await executeSql(sql);
59
84
  if (!queryHandle) {
60
85
  throw new Error(`Query for dataset "${datasetId}" was cancelled.`);
@@ -68,7 +93,7 @@ export function createPreparedDatasetStore(options = {}) {
68
93
  datasetId,
69
94
  table,
70
95
  geometryColumn: input.geometryColumn,
71
- geometryEncodingHint: input.geometryEncodingHint,
96
+ geometryEncodingHint,
72
97
  });
73
98
  set((state) => ({
74
99
  ...state,
@@ -1 +1 @@
1
- {"version":3,"file":"PreparedDatasetStore.js","sourceRoot":"","sources":["../../src/datasets/PreparedDatasetStore.ts"],"names":[],"mappings":"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","sourcesContent":["import type {QueryHandle} from '@sqlrooms/duckdb';\nimport {createStore} from 'zustand/vanilla';\nimport {prepareDeckDataset} from '../prepare/prepareDeckDataset';\nimport {\n isSqlDatasetInput,\n isTableDatasetInput,\n type DeckDatasetInput,\n type PreparedDeckDatasetState,\n} from '../types';\nimport {\n DEFAULT_MAX_PREPARED_DATASET_ENTRIES,\n cloneEntryWithConsumers,\n evictLruEntries,\n nextAccessTimestamp,\n resolvePreparedDatasetCacheKey,\n touchEntry,\n} from './helpers';\nimport {resolveArrowTable} from './normalizeDatasets';\nimport {createDeckTableDatasetSql} from './tableDatasetSql';\nimport type {\n PreparedDatasetCacheEntry,\n PreparedDatasetStoreOptions,\n} from './types';\n\n/**\n * Internal store state for the prepared-dataset cache.\n *\n * `DeckJsonMap` never talks to this shape directly; `usePreparedDatasetStates`\n * uses it as the backing state machine for preparation, reuse, and eviction.\n */\ntype PreparedDatasetStoreState = {\n /**\n * Cache keys currently referenced by each hook consumer.\n *\n * This lets the store update consumer memberships incrementally when a map's\n * dataset registry changes, instead of resetting all cache state.\n */\n consumerKeys: Record<string, string[]>;\n /**\n * Prepared entries keyed by resolved dataset identity.\n *\n * Keys are based on query/table identity plus geometry options, not dataset\n * id, so the same prepared result can be reused across multiple maps or\n * differently named datasets that point at the same underlying data.\n */\n entries: Record<string, PreparedDatasetCacheEntry>;\n /**\n * Ensure a cache entry exists for the given dataset key.\n *\n * If an entry already exists, this is a no-op other than touching its LRU\n * metadata. Otherwise the store creates a `loading` entry, resolves the\n * source table through DuckDB if needed, runs `prepareDeckDataset(...)`, and\n * stores the resulting `ready` or `error` state.\n */\n ensureEntry: (options: {\n cacheKey: string;\n datasetId: string;\n executeSql: (\n query: string,\n version?: number,\n ) => Promise<QueryHandle | null>;\n input: DeckDatasetInput;\n }) => void;\n /**\n * Remove all subscriptions for one hook consumer.\n *\n * This is called when a `DeckJsonMap` instance unmounts so the store can\n * release the consumer's references and allow now-unreferenced entries to be\n * evicted later.\n */\n removeConsumer: (consumerId: string) => void;\n /**\n * Reconcile the set of cache keys referenced by one hook consumer.\n *\n * This adds the consumer to newly needed entries, removes it from entries no\n * longer needed, and preserves existing entries in place so unrelated dataset\n * states do not get reset during prop changes.\n */\n syncConsumer: (consumerId: string, keys: string[]) => void;\n /**\n * Reconcile and ensure all prepared entries needed by one dataset registry.\n *\n * This is the store-level orchestration entrypoint used by\n * `usePreparedDatasetStates`. It computes cache keys for the current dataset\n * registry, syncs consumer memberships, and eagerly ensures any resolvable\n * entries exist.\n */\n syncDatasetsForConsumer: (options: {\n consumerId: string;\n datasets: Record<string, DeckDatasetInput>;\n executeSql: (\n query: string,\n version?: number,\n ) => Promise<QueryHandle | null>;\n sqlSourceIdentity: object;\n }) => void;\n};\n\ntype PreparedDatasetDescriptor = {\n datasetId: string;\n input: DeckDatasetInput;\n cacheKey: string | undefined;\n};\n\nfunction resolvePreparedDatasetDescriptors(options: {\n datasets: Record<string, DeckDatasetInput>;\n sqlSourceIdentity: object;\n}): PreparedDatasetDescriptor[] {\n const {datasets, sqlSourceIdentity} = options;\n\n return Object.entries(datasets).map(([datasetId, input]) => ({\n datasetId,\n input,\n cacheKey: resolvePreparedDatasetCacheKey({\n input,\n sqlSourceIdentity,\n }),\n }));\n}\n\n/**\n * Create a feature-local cache store for prepared deck datasets.\n *\n * The store is intentionally scoped to deck's preparation layer. It reuses the\n * expensive result of `prepareDeckDataset(...)` across consumers while leaving\n * raw query/result caching to the upstream data provider:\n *\n * - Mosaic handles cached query results through its coordinator/query manager\n * - DuckDB-backed SQL datasets still use the DuckDB slice execution path\n *\n * This keeps `@sqlrooms/deck` independent from either provider while still\n * avoiding repeated geometry decoding and GeoArrow/GeoJSON shaping work.\n */\nexport function createPreparedDatasetStore(\n options: PreparedDatasetStoreOptions = {},\n) {\n const {\n maxEntries = DEFAULT_MAX_PREPARED_DATASET_ENTRIES,\n prepareDataset = prepareDeckDataset,\n } = options;\n\n return createStore<PreparedDatasetStoreState>((set, get) => ({\n consumerKeys: {},\n entries: {},\n\n ensureEntry({cacheKey, datasetId, executeSql, input}) {\n const existing = get().entries[cacheKey];\n if (existing) {\n if (existing.status !== 'loading') {\n set((state) => ({\n ...state,\n entries: {\n ...state.entries,\n [cacheKey]: touchEntry(existing),\n },\n }));\n }\n return;\n }\n\n const promise = Promise.resolve().then(async () => {\n try {\n let table = resolveArrowTable(input);\n if (\n !table &&\n (isSqlDatasetInput(input) || isTableDatasetInput(input))\n ) {\n const sql = isSqlDatasetInput(input)\n ? input.sqlQuery\n : createDeckTableDatasetSql(input);\n const queryHandle = await executeSql(sql);\n if (!queryHandle) {\n throw new Error(\n `Query for dataset \"${datasetId}\" was cancelled.`,\n );\n }\n\n table = await queryHandle;\n }\n\n if (!table) {\n return;\n }\n\n const prepared = prepareDataset({\n datasetId,\n table,\n geometryColumn: input.geometryColumn,\n geometryEncodingHint: input.geometryEncodingHint,\n });\n\n set((state) => ({\n ...state,\n entries: evictLruEntries(\n {\n ...state.entries,\n [cacheKey]: {\n status: 'ready',\n prepared,\n consumers:\n state.entries[cacheKey]?.consumers ?? new Set<string>(),\n lastAccessedAt: nextAccessTimestamp(),\n },\n },\n maxEntries,\n ),\n }));\n } catch (error) {\n set((state) => ({\n ...state,\n entries: evictLruEntries(\n {\n ...state.entries,\n [cacheKey]: {\n status: 'error',\n error:\n error instanceof Error ? error : new Error(String(error)),\n consumers:\n state.entries[cacheKey]?.consumers ?? new Set<string>(),\n lastAccessedAt: nextAccessTimestamp(),\n },\n },\n maxEntries,\n ),\n }));\n }\n });\n\n set((state) => ({\n ...state,\n entries: {\n ...state.entries,\n [cacheKey]: {\n status: 'loading',\n promise,\n consumers: state.entries[cacheKey]?.consumers ?? new Set<string>(),\n lastAccessedAt: nextAccessTimestamp(),\n },\n },\n }));\n },\n\n syncConsumer(consumerId, keys) {\n const previousKeys = new Set(get().consumerKeys[consumerId] ?? []);\n const nextKeys = new Set(keys);\n\n set((state) => {\n let didChangeEntries = false;\n let nextEntries = state.entries;\n\n const updateEntry = (\n cacheKey: string,\n updater: (\n entry: PreparedDatasetCacheEntry,\n ) => PreparedDatasetCacheEntry,\n ) => {\n const currentEntry = nextEntries[cacheKey];\n if (!currentEntry) {\n return;\n }\n\n if (!didChangeEntries) {\n nextEntries = {...nextEntries};\n didChangeEntries = true;\n }\n\n nextEntries[cacheKey] = updater(currentEntry);\n };\n\n for (const cacheKey of previousKeys) {\n if (nextKeys.has(cacheKey)) {\n continue;\n }\n\n updateEntry(cacheKey, (entry) => {\n const consumers = new Set(entry.consumers);\n consumers.delete(consumerId);\n return cloneEntryWithConsumers(entry, consumers);\n });\n }\n\n for (const cacheKey of nextKeys) {\n updateEntry(cacheKey, (entry) => {\n const consumers = new Set(entry.consumers);\n consumers.add(consumerId);\n return cloneEntryWithConsumers(entry, consumers);\n });\n }\n\n return {\n ...state,\n consumerKeys: {\n ...state.consumerKeys,\n [consumerId]: [...nextKeys],\n },\n entries: didChangeEntries\n ? evictLruEntries(nextEntries, maxEntries)\n : state.entries,\n };\n });\n },\n\n removeConsumer(consumerId) {\n const previousKeys = get().consumerKeys[consumerId];\n if (!previousKeys) {\n return;\n }\n\n set((state) => {\n let didChangeEntries = false;\n let nextEntries = state.entries;\n\n for (const cacheKey of previousKeys) {\n const entry = nextEntries[cacheKey];\n if (!entry) {\n continue;\n }\n\n const consumers = new Set(entry.consumers);\n consumers.delete(consumerId);\n\n if (!didChangeEntries) {\n nextEntries = {...nextEntries};\n didChangeEntries = true;\n }\n\n nextEntries[cacheKey] = cloneEntryWithConsumers(entry, consumers);\n }\n\n const nextConsumerKeys = {...state.consumerKeys};\n delete nextConsumerKeys[consumerId];\n\n return {\n ...state,\n consumerKeys: nextConsumerKeys,\n entries: didChangeEntries\n ? evictLruEntries(nextEntries, maxEntries)\n : state.entries,\n };\n });\n },\n\n syncDatasetsForConsumer({\n consumerId,\n datasets,\n executeSql,\n sqlSourceIdentity,\n }) {\n const descriptors = resolvePreparedDatasetDescriptors({\n datasets,\n sqlSourceIdentity,\n });\n const cacheKeys = descriptors\n .map((descriptor) => descriptor.cacheKey)\n .filter((cacheKey): cacheKey is string => Boolean(cacheKey));\n\n for (const descriptor of descriptors) {\n if (!descriptor.cacheKey) {\n continue;\n }\n\n get().ensureEntry({\n cacheKey: descriptor.cacheKey,\n datasetId: descriptor.datasetId,\n executeSql,\n input: descriptor.input,\n });\n }\n\n get().syncConsumer(consumerId, cacheKeys);\n },\n }));\n}\n\n/**\n * Resolve a shared prepared-store entry back into the dataset-state shape\n * consumed by `DeckJsonMap`.\n *\n * Prepared entries are shared by cache key, while `datasetId` stays a\n * view-level label used by layer binding and user-facing errors. When a shared\n * prepared entry is reused for a different dataset id, this helper remaps the\n * prepared payload so downstream callers still see the dataset id they asked\n * for.\n */\nexport function resolvePreparedDeckDatasetState(options: {\n datasetId: string;\n entry?: PreparedDatasetCacheEntry;\n}): PreparedDeckDatasetState {\n const {datasetId, entry} = options;\n\n if (!entry || entry.status === 'loading') {\n return {status: 'loading'};\n }\n\n if (entry.status === 'error') {\n return {status: 'error', error: entry.error};\n }\n\n return {\n status: 'ready',\n prepared:\n entry.prepared.datasetId === datasetId\n ? entry.prepared\n : {\n ...entry.prepared,\n datasetId,\n },\n };\n}\n\n/**\n * Resolve the full `datasetId -> state` map for a dataset registry.\n *\n * This mirrors the lookup logic used by `DeckJsonMap`: unresolved Arrow\n * datasets remain `loading`, while resolvable datasets reuse shared prepared\n * entries keyed by data identity rather than by dataset id.\n */\nexport function resolvePreparedDeckDatasetStates(options: {\n datasets: Record<string, DeckDatasetInput>;\n entries: Record<string, PreparedDatasetCacheEntry>;\n sqlSourceIdentity: object;\n}): Record<string, PreparedDeckDatasetState> {\n const {datasets, entries, sqlSourceIdentity} = options;\n\n return Object.fromEntries(\n resolvePreparedDatasetDescriptors({datasets, sqlSourceIdentity}).map(\n ({datasetId, cacheKey}) => [\n datasetId,\n resolvePreparedDeckDatasetState({\n datasetId,\n entry: cacheKey ? entries[cacheKey] : undefined,\n }),\n ],\n ),\n );\n}\n\n/**\n * Module-global prepared dataset cache shared by all `DeckJsonMap` instances.\n *\n * The cache stores only deck-specific prepared payloads, not raw query\n * results, and applies a small internal LRU policy so settled entries do not\n * grow without bound.\n */\nexport const preparedDatasetStore = createPreparedDatasetStore();\n"]}
1
+ {"version":3,"file":"PreparedDatasetStore.js","sourceRoot":"","sources":["../../src/datasets/PreparedDatasetStore.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,WAAW,EAAC,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAC,kBAAkB,EAAC,MAAM,+BAA+B,CAAC;AACjE,OAAO,EACL,iBAAiB,EACjB,mBAAmB,GAGpB,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,oCAAoC,EACpC,uBAAuB,EACvB,eAAe,EACf,mBAAmB,EACnB,8BAA8B,GAC/B,MAAM,WAAW,CAAC;AACnB,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAC,yBAAyB,EAAC,MAAM,mBAAmB,CAAC;AAK5D,OAAO,EACL,wBAAwB,EACxB,6BAA6B,EAC7B,uBAAuB,EACvB,2BAA2B,GAC5B,MAAM,qBAAqB,CAAC;AAiF7B,SAAS,iCAAiC,CAAC,OAG1C;IACC,MAAM,EAAC,QAAQ,EAAE,iBAAiB,EAAC,GAAG,OAAO,CAAC;IAE9C,OAAO,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;QAC3D,SAAS;QACT,KAAK;QACL,QAAQ,EAAE,8BAA8B,CAAC;YACvC,KAAK;YACL,iBAAiB;SAClB,CAAC;KACH,CAAC,CAAC,CAAC;AACN,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,0BAA0B,CACxC,UAAuC,EAAE;IAEzC,MAAM,EACJ,UAAU,GAAG,oCAAoC,EACjD,cAAc,GAAG,kBAAkB,GACpC,GAAG,OAAO,CAAC;IAEZ,OAAO,WAAW,CAA4B,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QAC3D,YAAY,EAAE,EAAE;QAChB,OAAO,EAAE,EAAE;QAEX,WAAW,CAAC,EAAC,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK,EAAC;YAClD,MAAM,QAAQ,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YACzC,IAAI,QAAQ,EAAE,CAAC;gBACb,IAAI,QAAQ,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;oBAClC,qEAAqE;oBACrE,+DAA+D;oBAC/D,QAAQ,CAAC,cAAc,GAAG,mBAAmB,EAAE,CAAC;gBAClD,CAAC;gBACD,OAAO;YACT,CAAC;YAED,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE;gBAChD,IAAI,CAAC;oBACH,IAAI,KAAK,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;oBACrC,IAAI,oBAAoB,GAAG,KAAK,CAAC,oBAAoB,CAAC;oBACtD,IACE,CAAC,KAAK;wBACN,CAAC,iBAAiB,CAAC,KAAK,CAAC,IAAI,mBAAmB,CAAC,KAAK,CAAC,CAAC,EACxD,CAAC;wBACD,MAAM,OAAO,GAAG,iBAAiB,CAAC,KAAK,CAAC;4BACtC,CAAC,CAAC,KAAK,CAAC,QAAQ;4BAChB,CAAC,CAAC,yBAAyB,CAAC,KAAK,CAAC,CAAC;wBAErC,iEAAiE;wBACjE,mEAAmE;wBACnE,oEAAoE;wBACpE,IAAI,GAAG,GAAG,OAAO,CAAC;wBAClB,IAAI,CAAC;4BACH,MAAM,cAAc,GAAG,MAAM,UAAU,CACrC,wBAAwB,CAAC,OAAO,CAAC,CAClC,CAAC;4BACF,IAAI,cAAc,EAAE,CAAC;gCACnB,MAAM,aAAa,GAAG,MAAM,cAAc,CAAC;gCAC3C,MAAM,eAAe,GAAG,6BAA6B,CACnD,uBAAuB,CAAC,aAAa,CAAC,CACvC,CAAC;gCACF,MAAM,OAAO,GAAG,2BAA2B,CACzC,OAAO,EACP,eAAe,CAChB,CAAC;gCACF,IAAI,OAAO,EAAE,CAAC;oCACZ,GAAG,GAAG,OAAO,CAAC;oCACd,+DAA+D;oCAC/D,4DAA4D;oCAC5D,4DAA4D;oCAC5D,yCAAyC;oCACzC,MAAM,YAAY,GAAG,KAAK,CAAC,cAAc,CAAC;oCAC1C,IAAI,CAAC,YAAY,IAAI,eAAe,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;wCAC5D,oBAAoB,GAAG,KAAK,CAAC;oCAC/B,CAAC;gCACH,CAAC;4BACH,CAAC;wBACH,CAAC;wBAAC,MAAM,CAAC;4BACP,gEAAgE;4BAChE,uDAAuD;wBACzD,CAAC;wBAED,MAAM,WAAW,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC;wBAC1C,IAAI,CAAC,WAAW,EAAE,CAAC;4BACjB,MAAM,IAAI,KAAK,CACb,sBAAsB,SAAS,kBAAkB,CAClD,CAAC;wBACJ,CAAC;wBAED,KAAK,GAAG,MAAM,WAAW,CAAC;oBAC5B,CAAC;oBAED,IAAI,CAAC,KAAK,EAAE,CAAC;wBACX,OAAO;oBACT,CAAC;oBAED,MAAM,QAAQ,GAAG,cAAc,CAAC;wBAC9B,SAAS;wBACT,KAAK;wBACL,cAAc,EAAE,KAAK,CAAC,cAAc;wBACpC,oBAAoB;qBACrB,CAAC,CAAC;oBAEH,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;wBACd,GAAG,KAAK;wBACR,OAAO,EAAE,eAAe,CACtB;4BACE,GAAG,KAAK,CAAC,OAAO;4BAChB,CAAC,QAAQ,CAAC,EAAE;gCACV,MAAM,EAAE,OAAO;gCACf,QAAQ;gCACR,SAAS,EACP,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,SAAS,IAAI,IAAI,GAAG,EAAU;gCACzD,cAAc,EAAE,mBAAmB,EAAE;6BACtC;yBACF,EACD,UAAU,CACX;qBACF,CAAC,CAAC,CAAC;gBACN,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;wBACd,GAAG,KAAK;wBACR,OAAO,EAAE,eAAe,CACtB;4BACE,GAAG,KAAK,CAAC,OAAO;4BAChB,CAAC,QAAQ,CAAC,EAAE;gCACV,MAAM,EAAE,OAAO;gCACf,KAAK,EACH,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gCAC3D,SAAS,EACP,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,SAAS,IAAI,IAAI,GAAG,EAAU;gCACzD,cAAc,EAAE,mBAAmB,EAAE;6BACtC;yBACF,EACD,UAAU,CACX;qBACF,CAAC,CAAC,CAAC;gBACN,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBACd,GAAG,KAAK;gBACR,OAAO,EAAE;oBACP,GAAG,KAAK,CAAC,OAAO;oBAChB,CAAC,QAAQ,CAAC,EAAE;wBACV,MAAM,EAAE,SAAS;wBACjB,OAAO;wBACP,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,SAAS,IAAI,IAAI,GAAG,EAAU;wBAClE,cAAc,EAAE,mBAAmB,EAAE;qBACtC;iBACF;aACF,CAAC,CAAC,CAAC;QACN,CAAC;QAED,YAAY,CAAC,UAAU,EAAE,IAAI;YAC3B,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;YACnE,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;YAE/B,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;gBACZ,IAAI,gBAAgB,GAAG,KAAK,CAAC;gBAC7B,IAAI,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC;gBAEhC,MAAM,WAAW,GAAG,CAClB,QAAgB,EAChB,OAE8B,EAC9B,EAAE;oBACF,MAAM,YAAY,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;oBAC3C,IAAI,CAAC,YAAY,EAAE,CAAC;wBAClB,OAAO;oBACT,CAAC;oBAED,IAAI,CAAC,gBAAgB,EAAE,CAAC;wBACtB,WAAW,GAAG,EAAC,GAAG,WAAW,EAAC,CAAC;wBAC/B,gBAAgB,GAAG,IAAI,CAAC;oBAC1B,CAAC;oBAED,WAAW,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;gBAChD,CAAC,CAAC;gBAEF,KAAK,MAAM,QAAQ,IAAI,YAAY,EAAE,CAAC;oBACpC,IAAI,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;wBAC3B,SAAS;oBACX,CAAC;oBAED,WAAW,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;wBAC9B,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;wBAC3C,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;wBAC7B,OAAO,uBAAuB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;oBACnD,CAAC,CAAC,CAAC;gBACL,CAAC;gBAED,KAAK,MAAM,QAAQ,IAAI,QAAQ,EAAE,CAAC;oBAChC,WAAW,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;wBAC9B,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;wBAC3C,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;wBAC1B,OAAO,uBAAuB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;oBACnD,CAAC,CAAC,CAAC;gBACL,CAAC;gBAED,OAAO;oBACL,GAAG,KAAK;oBACR,YAAY,EAAE;wBACZ,GAAG,KAAK,CAAC,YAAY;wBACrB,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC;qBAC5B;oBACD,OAAO,EAAE,gBAAgB;wBACvB,CAAC,CAAC,eAAe,CAAC,WAAW,EAAE,UAAU,CAAC;wBAC1C,CAAC,CAAC,KAAK,CAAC,OAAO;iBAClB,CAAC;YACJ,CAAC,CAAC,CAAC;QACL,CAAC;QAED,cAAc,CAAC,UAAU;YACvB,MAAM,YAAY,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;YACpD,IAAI,CAAC,YAAY,EAAE,CAAC;gBAClB,OAAO;YACT,CAAC;YAED,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;gBACZ,IAAI,gBAAgB,GAAG,KAAK,CAAC;gBAC7B,IAAI,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC;gBAEhC,KAAK,MAAM,QAAQ,IAAI,YAAY,EAAE,CAAC;oBACpC,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;oBACpC,IAAI,CAAC,KAAK,EAAE,CAAC;wBACX,SAAS;oBACX,CAAC;oBAED,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;oBAC3C,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;oBAE7B,IAAI,CAAC,gBAAgB,EAAE,CAAC;wBACtB,WAAW,GAAG,EAAC,GAAG,WAAW,EAAC,CAAC;wBAC/B,gBAAgB,GAAG,IAAI,CAAC;oBAC1B,CAAC;oBAED,WAAW,CAAC,QAAQ,CAAC,GAAG,uBAAuB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;gBACpE,CAAC;gBAED,MAAM,gBAAgB,GAAG,EAAC,GAAG,KAAK,CAAC,YAAY,EAAC,CAAC;gBACjD,OAAO,gBAAgB,CAAC,UAAU,CAAC,CAAC;gBAEpC,OAAO;oBACL,GAAG,KAAK;oBACR,YAAY,EAAE,gBAAgB;oBAC9B,OAAO,EAAE,gBAAgB;wBACvB,CAAC,CAAC,eAAe,CAAC,WAAW,EAAE,UAAU,CAAC;wBAC1C,CAAC,CAAC,KAAK,CAAC,OAAO;iBAClB,CAAC;YACJ,CAAC,CAAC,CAAC;QACL,CAAC;QAED,uBAAuB,CAAC,EACtB,UAAU,EACV,QAAQ,EACR,UAAU,EACV,iBAAiB,GAClB;YACC,MAAM,WAAW,GAAG,iCAAiC,CAAC;gBACpD,QAAQ;gBACR,iBAAiB;aAClB,CAAC,CAAC;YACH,MAAM,SAAS,GAAG,WAAW;iBAC1B,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;iBACxC,MAAM,CAAC,CAAC,QAAQ,EAAsB,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;YAE/D,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;gBACrC,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC;oBACzB,SAAS;gBACX,CAAC;gBAED,GAAG,EAAE,CAAC,WAAW,CAAC;oBAChB,QAAQ,EAAE,UAAU,CAAC,QAAQ;oBAC7B,SAAS,EAAE,UAAU,CAAC,SAAS;oBAC/B,UAAU;oBACV,KAAK,EAAE,UAAU,CAAC,KAAK;iBACxB,CAAC,CAAC;YACL,CAAC;YAED,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAC5C,CAAC;KACF,CAAC,CAAC,CAAC;AACN,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,+BAA+B,CAAC,OAG/C;IACC,MAAM,EAAC,SAAS,EAAE,KAAK,EAAC,GAAG,OAAO,CAAC;IAEnC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACzC,OAAO,EAAC,MAAM,EAAE,SAAS,EAAC,CAAC;IAC7B,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;QAC7B,OAAO,EAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAC,CAAC;IAC/C,CAAC;IAED,OAAO;QACL,MAAM,EAAE,OAAO;QACf,QAAQ,EACN,KAAK,CAAC,QAAQ,CAAC,SAAS,KAAK,SAAS;YACpC,CAAC,CAAC,KAAK,CAAC,QAAQ;YAChB,CAAC,CAAC;gBACE,GAAG,KAAK,CAAC,QAAQ;gBACjB,SAAS;aACV;KACR,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gCAAgC,CAAC,OAIhD;IACC,MAAM,EAAC,QAAQ,EAAE,OAAO,EAAE,iBAAiB,EAAC,GAAG,OAAO,CAAC;IAEvD,OAAO,MAAM,CAAC,WAAW,CACvB,iCAAiC,CAAC,EAAC,QAAQ,EAAE,iBAAiB,EAAC,CAAC,CAAC,GAAG,CAClE,CAAC,EAAC,SAAS,EAAE,QAAQ,EAAC,EAAE,EAAE,CAAC;QACzB,SAAS;QACT,+BAA+B,CAAC;YAC9B,SAAS;YACT,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS;SAChD,CAAC;KACH,CACF,CACF,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,0BAA0B,EAAE,CAAC","sourcesContent":["import type {QueryHandle} from '@sqlrooms/duckdb';\nimport {createStore} from 'zustand/vanilla';\nimport {prepareDeckDataset} from '../prepare/prepareDeckDataset';\nimport {\n isSqlDatasetInput,\n isTableDatasetInput,\n type DeckDatasetInput,\n type PreparedDeckDatasetState,\n} from '../types';\nimport {\n DEFAULT_MAX_PREPARED_DATASET_ENTRIES,\n cloneEntryWithConsumers,\n evictLruEntries,\n nextAccessTimestamp,\n resolvePreparedDatasetCacheKey,\n} from './helpers';\nimport {resolveArrowTable} from './normalizeDatasets';\nimport {createDeckTableDatasetSql} from './tableDatasetSql';\nimport type {\n PreparedDatasetCacheEntry,\n PreparedDatasetStoreOptions,\n} from './types';\nimport {\n createDescribeDatasetSql,\n geometryColumnsNeedingWkbWrap,\n parseDescribeSqlColumns,\n wrapSqlGeometryColumnsAsWkb,\n} from './wrapGeometryAsWkb';\n\n/**\n * Internal store state for the prepared-dataset cache.\n *\n * `DeckJsonMap` never talks to this shape directly; `usePreparedDatasetStates`\n * uses it as the backing state machine for preparation, reuse, and eviction.\n */\ntype PreparedDatasetStoreState = {\n /**\n * Cache keys currently referenced by each hook consumer.\n *\n * This lets the store update consumer memberships incrementally when a map's\n * dataset registry changes, instead of resetting all cache state.\n */\n consumerKeys: Record<string, string[]>;\n /**\n * Prepared entries keyed by resolved dataset identity.\n *\n * Keys are based on query/table identity plus geometry options, not dataset\n * id, so the same prepared result can be reused across multiple maps or\n * differently named datasets that point at the same underlying data.\n */\n entries: Record<string, PreparedDatasetCacheEntry>;\n /**\n * Ensure a cache entry exists for the given dataset key.\n *\n * If an entry already exists, this is a no-op besides refreshing the\n * in-place LRU timestamp. Subscribers are not notified: a cache hit is not\n * a dataset change, and notifying would rebuild every mounted map's layers.\n */\n ensureEntry: (options: {\n cacheKey: string;\n datasetId: string;\n executeSql: (\n query: string,\n version?: number,\n ) => Promise<QueryHandle | null>;\n input: DeckDatasetInput;\n }) => void;\n /**\n * Remove all subscriptions for one hook consumer.\n *\n * This is called when a `DeckJsonMap` instance unmounts so the store can\n * release the consumer's references and allow now-unreferenced entries to be\n * evicted later.\n */\n removeConsumer: (consumerId: string) => void;\n /**\n * Reconcile the set of cache keys referenced by one hook consumer.\n *\n * This adds the consumer to newly needed entries, removes it from entries no\n * longer needed, and preserves existing entries in place so unrelated dataset\n * states do not get reset during prop changes.\n */\n syncConsumer: (consumerId: string, keys: string[]) => void;\n /**\n * Reconcile and ensure all prepared entries needed by one dataset registry.\n *\n * This is the store-level orchestration entrypoint used by\n * `usePreparedDatasetStates`. It computes cache keys for the current dataset\n * registry, syncs consumer memberships, and eagerly ensures any resolvable\n * entries exist.\n */\n syncDatasetsForConsumer: (options: {\n consumerId: string;\n datasets: Record<string, DeckDatasetInput>;\n executeSql: (\n query: string,\n version?: number,\n ) => Promise<QueryHandle | null>;\n sqlSourceIdentity: object;\n }) => void;\n};\n\ntype PreparedDatasetDescriptor = {\n datasetId: string;\n input: DeckDatasetInput;\n cacheKey: string | undefined;\n};\n\nfunction resolvePreparedDatasetDescriptors(options: {\n datasets: Record<string, DeckDatasetInput>;\n sqlSourceIdentity: object;\n}): PreparedDatasetDescriptor[] {\n const {datasets, sqlSourceIdentity} = options;\n\n return Object.entries(datasets).map(([datasetId, input]) => ({\n datasetId,\n input,\n cacheKey: resolvePreparedDatasetCacheKey({\n input,\n sqlSourceIdentity,\n }),\n }));\n}\n\n/**\n * Create a feature-local cache store for prepared deck datasets.\n *\n * The store is intentionally scoped to deck's preparation layer. It reuses the\n * expensive result of `prepareDeckDataset(...)` across consumers while leaving\n * raw query/result caching to the upstream data provider:\n *\n * - Mosaic handles cached query results through its coordinator/query manager\n * - DuckDB-backed SQL datasets still use the DuckDB slice execution path\n *\n * This keeps `@sqlrooms/deck` independent from either provider while still\n * avoiding repeated geometry decoding and GeoArrow/GeoJSON shaping work.\n */\nexport function createPreparedDatasetStore(\n options: PreparedDatasetStoreOptions = {},\n) {\n const {\n maxEntries = DEFAULT_MAX_PREPARED_DATASET_ENTRIES,\n prepareDataset = prepareDeckDataset,\n } = options;\n\n return createStore<PreparedDatasetStoreState>((set, get) => ({\n consumerKeys: {},\n entries: {},\n\n ensureEntry({cacheKey, datasetId, executeSql, input}) {\n const existing = get().entries[cacheKey];\n if (existing) {\n if (existing.status !== 'loading') {\n // Mutate the timestamp in place so LRU still works without replacing\n // `entries` and forcing every DeckJsonMap to reconvert layers.\n existing.lastAccessedAt = nextAccessTimestamp();\n }\n return;\n }\n\n const promise = Promise.resolve().then(async () => {\n try {\n let table = resolveArrowTable(input);\n let geometryEncodingHint = input.geometryEncodingHint;\n if (\n !table &&\n (isSqlDatasetInput(input) || isTableDatasetInput(input))\n ) {\n const baseSql = isSqlDatasetInput(input)\n ? input.sqlQuery\n : createDeckTableDatasetSql(input);\n\n // Probe DuckDB logical types and project native GEOMETRY columns\n // through ST_AsWKB so prepare/decode never sees undecodable blobs.\n // Authored SQL is left intact — the wrap is a pipeline outer query.\n let sql = baseSql;\n try {\n const describeHandle = await executeSql(\n createDescribeDatasetSql(baseSql),\n );\n if (describeHandle) {\n const describeTable = await describeHandle;\n const geometryColumns = geometryColumnsNeedingWkbWrap(\n parseDescribeSqlColumns(describeTable),\n );\n const wrapped = wrapSqlGeometryColumnsAsWkb(\n baseSql,\n geometryColumns,\n );\n if (wrapped) {\n sql = wrapped;\n // Only force the dataset-level hint to WKB when the configured\n // geometry column was among the wrapped columns (or unset).\n // An unrelated native GEOMETRY column must not make a WKT /\n // GeoArrow geometryColumn decode as WKB.\n const resolvedGeom = input.geometryColumn;\n if (!resolvedGeom || geometryColumns.includes(resolvedGeom)) {\n geometryEncodingHint = 'wkb';\n }\n }\n }\n } catch {\n // If DESCRIBE fails (e.g. missing spatial), fall through to the\n // original SQL — prepare still surfaces decode errors.\n }\n\n const queryHandle = await executeSql(sql);\n if (!queryHandle) {\n throw new Error(\n `Query for dataset \"${datasetId}\" was cancelled.`,\n );\n }\n\n table = await queryHandle;\n }\n\n if (!table) {\n return;\n }\n\n const prepared = prepareDataset({\n datasetId,\n table,\n geometryColumn: input.geometryColumn,\n geometryEncodingHint,\n });\n\n set((state) => ({\n ...state,\n entries: evictLruEntries(\n {\n ...state.entries,\n [cacheKey]: {\n status: 'ready',\n prepared,\n consumers:\n state.entries[cacheKey]?.consumers ?? new Set<string>(),\n lastAccessedAt: nextAccessTimestamp(),\n },\n },\n maxEntries,\n ),\n }));\n } catch (error) {\n set((state) => ({\n ...state,\n entries: evictLruEntries(\n {\n ...state.entries,\n [cacheKey]: {\n status: 'error',\n error:\n error instanceof Error ? error : new Error(String(error)),\n consumers:\n state.entries[cacheKey]?.consumers ?? new Set<string>(),\n lastAccessedAt: nextAccessTimestamp(),\n },\n },\n maxEntries,\n ),\n }));\n }\n });\n\n set((state) => ({\n ...state,\n entries: {\n ...state.entries,\n [cacheKey]: {\n status: 'loading',\n promise,\n consumers: state.entries[cacheKey]?.consumers ?? new Set<string>(),\n lastAccessedAt: nextAccessTimestamp(),\n },\n },\n }));\n },\n\n syncConsumer(consumerId, keys) {\n const previousKeys = new Set(get().consumerKeys[consumerId] ?? []);\n const nextKeys = new Set(keys);\n\n set((state) => {\n let didChangeEntries = false;\n let nextEntries = state.entries;\n\n const updateEntry = (\n cacheKey: string,\n updater: (\n entry: PreparedDatasetCacheEntry,\n ) => PreparedDatasetCacheEntry,\n ) => {\n const currentEntry = nextEntries[cacheKey];\n if (!currentEntry) {\n return;\n }\n\n if (!didChangeEntries) {\n nextEntries = {...nextEntries};\n didChangeEntries = true;\n }\n\n nextEntries[cacheKey] = updater(currentEntry);\n };\n\n for (const cacheKey of previousKeys) {\n if (nextKeys.has(cacheKey)) {\n continue;\n }\n\n updateEntry(cacheKey, (entry) => {\n const consumers = new Set(entry.consumers);\n consumers.delete(consumerId);\n return cloneEntryWithConsumers(entry, consumers);\n });\n }\n\n for (const cacheKey of nextKeys) {\n updateEntry(cacheKey, (entry) => {\n const consumers = new Set(entry.consumers);\n consumers.add(consumerId);\n return cloneEntryWithConsumers(entry, consumers);\n });\n }\n\n return {\n ...state,\n consumerKeys: {\n ...state.consumerKeys,\n [consumerId]: [...nextKeys],\n },\n entries: didChangeEntries\n ? evictLruEntries(nextEntries, maxEntries)\n : state.entries,\n };\n });\n },\n\n removeConsumer(consumerId) {\n const previousKeys = get().consumerKeys[consumerId];\n if (!previousKeys) {\n return;\n }\n\n set((state) => {\n let didChangeEntries = false;\n let nextEntries = state.entries;\n\n for (const cacheKey of previousKeys) {\n const entry = nextEntries[cacheKey];\n if (!entry) {\n continue;\n }\n\n const consumers = new Set(entry.consumers);\n consumers.delete(consumerId);\n\n if (!didChangeEntries) {\n nextEntries = {...nextEntries};\n didChangeEntries = true;\n }\n\n nextEntries[cacheKey] = cloneEntryWithConsumers(entry, consumers);\n }\n\n const nextConsumerKeys = {...state.consumerKeys};\n delete nextConsumerKeys[consumerId];\n\n return {\n ...state,\n consumerKeys: nextConsumerKeys,\n entries: didChangeEntries\n ? evictLruEntries(nextEntries, maxEntries)\n : state.entries,\n };\n });\n },\n\n syncDatasetsForConsumer({\n consumerId,\n datasets,\n executeSql,\n sqlSourceIdentity,\n }) {\n const descriptors = resolvePreparedDatasetDescriptors({\n datasets,\n sqlSourceIdentity,\n });\n const cacheKeys = descriptors\n .map((descriptor) => descriptor.cacheKey)\n .filter((cacheKey): cacheKey is string => Boolean(cacheKey));\n\n for (const descriptor of descriptors) {\n if (!descriptor.cacheKey) {\n continue;\n }\n\n get().ensureEntry({\n cacheKey: descriptor.cacheKey,\n datasetId: descriptor.datasetId,\n executeSql,\n input: descriptor.input,\n });\n }\n\n get().syncConsumer(consumerId, cacheKeys);\n },\n }));\n}\n\n/**\n * Resolve a shared prepared-store entry back into the dataset-state shape\n * consumed by `DeckJsonMap`.\n *\n * Prepared entries are shared by cache key, while `datasetId` stays a\n * view-level label used by layer binding and user-facing errors. When a shared\n * prepared entry is reused for a different dataset id, this helper remaps the\n * prepared payload so downstream callers still see the dataset id they asked\n * for.\n */\nexport function resolvePreparedDeckDatasetState(options: {\n datasetId: string;\n entry?: PreparedDatasetCacheEntry;\n}): PreparedDeckDatasetState {\n const {datasetId, entry} = options;\n\n if (!entry || entry.status === 'loading') {\n return {status: 'loading'};\n }\n\n if (entry.status === 'error') {\n return {status: 'error', error: entry.error};\n }\n\n return {\n status: 'ready',\n prepared:\n entry.prepared.datasetId === datasetId\n ? entry.prepared\n : {\n ...entry.prepared,\n datasetId,\n },\n };\n}\n\n/**\n * Resolve the full `datasetId -> state` map for a dataset registry.\n *\n * This mirrors the lookup logic used by `DeckJsonMap`: unresolved Arrow\n * datasets remain `loading`, while resolvable datasets reuse shared prepared\n * entries keyed by data identity rather than by dataset id.\n */\nexport function resolvePreparedDeckDatasetStates(options: {\n datasets: Record<string, DeckDatasetInput>;\n entries: Record<string, PreparedDatasetCacheEntry>;\n sqlSourceIdentity: object;\n}): Record<string, PreparedDeckDatasetState> {\n const {datasets, entries, sqlSourceIdentity} = options;\n\n return Object.fromEntries(\n resolvePreparedDatasetDescriptors({datasets, sqlSourceIdentity}).map(\n ({datasetId, cacheKey}) => [\n datasetId,\n resolvePreparedDeckDatasetState({\n datasetId,\n entry: cacheKey ? entries[cacheKey] : undefined,\n }),\n ],\n ),\n );\n}\n\n/**\n * Module-global prepared dataset cache shared by all `DeckJsonMap` instances.\n *\n * The cache stores only deck-specific prepared payloads, not raw query\n * results, and applies a small internal LRU policy so settled entries do not\n * grow without bound.\n */\nexport const preparedDatasetStore = createPreparedDatasetStore();\n"]}