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

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 (118) hide show
  1. package/README.md +42 -6
  2. package/dist/DeckJsonMap.d.ts.map +1 -1
  3. package/dist/DeckJsonMap.js +2 -6
  4. package/dist/DeckJsonMap.js.map +1 -1
  5. package/dist/DeckJsonMapSpec.d.ts +875 -53
  6. package/dist/DeckJsonMapSpec.d.ts.map +1 -1
  7. package/dist/DeckJsonMapSpec.js +7 -0
  8. package/dist/DeckJsonMapSpec.js.map +1 -1
  9. package/dist/DeckMapDefaultStylesProvider.d.ts +3 -4
  10. package/dist/DeckMapDefaultStylesProvider.d.ts.map +1 -1
  11. package/dist/DeckMapDefaultStylesProvider.js +13 -7
  12. package/dist/DeckMapDefaultStylesProvider.js.map +1 -1
  13. package/dist/MapSettings.d.ts.map +1 -1
  14. package/dist/MapSettings.js +25 -11
  15. package/dist/MapSettings.js.map +1 -1
  16. package/dist/ai.d.ts +19 -5
  17. package/dist/ai.d.ts.map +1 -1
  18. package/dist/ai.js +60 -112
  19. package/dist/ai.js.map +1 -1
  20. package/dist/aiNormalize.d.ts +31 -0
  21. package/dist/aiNormalize.d.ts.map +1 -0
  22. package/dist/aiNormalize.js +629 -0
  23. package/dist/aiNormalize.js.map +1 -0
  24. package/dist/dashboard.d.ts.map +1 -1
  25. package/dist/dashboard.js +72 -8
  26. package/dist/dashboard.js.map +1 -1
  27. package/dist/dashboardConfig.d.ts +10 -1
  28. package/dist/dashboardConfig.d.ts.map +1 -1
  29. package/dist/dashboardConfig.js +55 -22
  30. package/dist/dashboardConfig.js.map +1 -1
  31. package/dist/datasets/PreparedDatasetStore.d.ts.map +1 -1
  32. package/dist/datasets/PreparedDatasetStore.js +31 -2
  33. package/dist/datasets/PreparedDatasetStore.js.map +1 -1
  34. package/dist/datasets/wrapGeometryAsWkb.d.ts +20 -0
  35. package/dist/datasets/wrapGeometryAsWkb.d.ts.map +1 -0
  36. package/dist/datasets/wrapGeometryAsWkb.js +65 -0
  37. package/dist/datasets/wrapGeometryAsWkb.js.map +1 -0
  38. package/dist/index.d.ts +1 -0
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +1 -0
  41. package/dist/index.js.map +1 -1
  42. package/dist/json/compileGeoArrowAccessor.d.ts +5 -0
  43. package/dist/json/compileGeoArrowAccessor.d.ts.map +1 -1
  44. package/dist/json/compileGeoArrowAccessor.js +17 -3
  45. package/dist/json/compileGeoArrowAccessor.js.map +1 -1
  46. package/dist/json/createDeckJsonConfiguration.d.ts.map +1 -1
  47. package/dist/json/createDeckJsonConfiguration.js +85 -18
  48. package/dist/json/createDeckJsonConfiguration.js.map +1 -1
  49. package/dist/json/extractColorScaleLegends.d.ts.map +1 -1
  50. package/dist/json/extractColorScaleLegends.js +21 -7
  51. package/dist/json/extractColorScaleLegends.js.map +1 -1
  52. package/dist/json/layers/DeckH3HexagonLayer.d.ts.map +1 -1
  53. package/dist/json/layers/DeckH3HexagonLayer.js +9 -14
  54. package/dist/json/layers/DeckH3HexagonLayer.js.map +1 -1
  55. package/dist/json/layers/h3IndexFormat.d.ts +6 -0
  56. package/dist/json/layers/h3IndexFormat.d.ts.map +1 -0
  57. package/dist/json/layers/h3IndexFormat.js +17 -0
  58. package/dist/json/layers/h3IndexFormat.js.map +1 -0
  59. package/dist/json/layers/index.d.ts +1 -0
  60. package/dist/json/layers/index.d.ts.map +1 -1
  61. package/dist/json/layers/index.js +1 -0
  62. package/dist/json/layers/index.js.map +1 -1
  63. package/dist/json/rewriteGeoArrowAccessors.d.ts.map +1 -1
  64. package/dist/json/rewriteGeoArrowAccessors.js +9 -0
  65. package/dist/json/rewriteGeoArrowAccessors.js.map +1 -1
  66. package/dist/json/scaleFunction.d.ts +30 -0
  67. package/dist/json/scaleFunction.d.ts.map +1 -0
  68. package/dist/json/scaleFunction.js +126 -0
  69. package/dist/json/scaleFunction.js.map +1 -0
  70. package/dist/mapAiConfig.d.ts +2 -0
  71. package/dist/mapAiConfig.d.ts.map +1 -1
  72. package/dist/mapAiConfig.js +2 -1
  73. package/dist/mapAiConfig.js.map +1 -1
  74. package/dist/mapAiSharedInstructions.d.ts +3 -0
  75. package/dist/mapAiSharedInstructions.d.ts.map +1 -0
  76. package/dist/mapAiSharedInstructions.js +16 -0
  77. package/dist/mapAiSharedInstructions.js.map +1 -0
  78. package/dist/mapConfig.d.ts +6 -0
  79. package/dist/mapConfig.d.ts.map +1 -1
  80. package/dist/mapConfig.js.map +1 -1
  81. package/dist/mapConfigUtils.d.ts.map +1 -1
  82. package/dist/mapConfigUtils.js +2 -0
  83. package/dist/mapConfigUtils.js.map +1 -1
  84. package/dist/mapFit.d.ts +16 -0
  85. package/dist/mapFit.d.ts.map +1 -1
  86. package/dist/mapFit.js +208 -30
  87. package/dist/mapFit.js.map +1 -1
  88. package/dist/mapLayerConfigUtils.d.ts +9 -1
  89. package/dist/mapLayerConfigUtils.d.ts.map +1 -1
  90. package/dist/mapLayerConfigUtils.js +62 -12
  91. package/dist/mapLayerConfigUtils.js.map +1 -1
  92. package/dist/mapResourceAuthoring.d.ts +2 -0
  93. package/dist/mapResourceAuthoring.d.ts.map +1 -1
  94. package/dist/mapResourceAuthoring.js +402 -16
  95. package/dist/mapResourceAuthoring.js.map +1 -1
  96. package/dist/mosaic.d.ts +1 -1
  97. package/dist/mosaic.d.ts.map +1 -1
  98. package/dist/mosaic.js.map +1 -1
  99. package/dist/prepare/geoarrow.js.map +1 -1
  100. package/dist/prepare/wkbDecoder.d.ts +10 -0
  101. package/dist/prepare/wkbDecoder.d.ts.map +1 -1
  102. package/dist/prepare/wkbDecoder.js +93 -18
  103. package/dist/prepare/wkbDecoder.js.map +1 -1
  104. package/dist/prepare/wkbParser.d.ts +7 -0
  105. package/dist/prepare/wkbParser.d.ts.map +1 -1
  106. package/dist/prepare/wkbParser.js +21 -0
  107. package/dist/prepare/wkbParser.js.map +1 -1
  108. package/dist/selectStarAsWkbCollision.d.ts +3 -0
  109. package/dist/selectStarAsWkbCollision.d.ts.map +1 -0
  110. package/dist/selectStarAsWkbCollision.js +78 -0
  111. package/dist/selectStarAsWkbCollision.js.map +1 -0
  112. package/dist/types.d.ts +1 -1
  113. package/dist/types.d.ts.map +1 -1
  114. package/dist/types.js.map +1 -1
  115. package/dist/useDeckMapFitToBounds.d.ts.map +1 -1
  116. package/dist/useDeckMapFitToBounds.js +1 -1
  117. package/dist/useDeckMapFitToBounds.js.map +1 -1
  118. package/package.json +15 -15
@@ -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"]}
@@ -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;AAWlB,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;;;;;;;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,yDAkR1C;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"}
@@ -4,6 +4,7 @@ import { isSqlDatasetInput, isTableDatasetInput, } from '../types';
4
4
  import { DEFAULT_MAX_PREPARED_DATASET_ENTRIES, cloneEntryWithConsumers, evictLruEntries, nextAccessTimestamp, resolvePreparedDatasetCacheKey, touchEntry, } 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]) => ({
@@ -50,11 +51,39 @@ export function createPreparedDatasetStore(options = {}) {
50
51
  const promise = Promise.resolve().then(async () => {
51
52
  try {
52
53
  let table = resolveArrowTable(input);
54
+ let geometryEncodingHint = input.geometryEncodingHint;
53
55
  if (!table &&
54
56
  (isSqlDatasetInput(input) || isTableDatasetInput(input))) {
55
- const sql = isSqlDatasetInput(input)
57
+ const baseSql = isSqlDatasetInput(input)
56
58
  ? input.sqlQuery
57
59
  : createDeckTableDatasetSql(input);
60
+ // Probe DuckDB logical types and project native GEOMETRY columns
61
+ // through ST_AsWKB so prepare/decode never sees undecodable blobs.
62
+ // Authored SQL is left intact — the wrap is a pipeline outer query.
63
+ let sql = baseSql;
64
+ try {
65
+ const describeHandle = await executeSql(createDescribeDatasetSql(baseSql));
66
+ if (describeHandle) {
67
+ const describeTable = await describeHandle;
68
+ const geometryColumns = geometryColumnsNeedingWkbWrap(parseDescribeSqlColumns(describeTable));
69
+ const wrapped = wrapSqlGeometryColumnsAsWkb(baseSql, geometryColumns);
70
+ if (wrapped) {
71
+ sql = wrapped;
72
+ // Only force the dataset-level hint to WKB when the configured
73
+ // geometry column was among the wrapped columns (or unset).
74
+ // An unrelated native GEOMETRY column must not make a WKT /
75
+ // GeoArrow geometryColumn decode as WKB.
76
+ const resolvedGeom = input.geometryColumn;
77
+ if (!resolvedGeom || geometryColumns.includes(resolvedGeom)) {
78
+ geometryEncodingHint = 'wkb';
79
+ }
80
+ }
81
+ }
82
+ }
83
+ catch {
84
+ // If DESCRIBE fails (e.g. missing spatial), fall through to the
85
+ // original SQL — prepare still surfaces decode errors.
86
+ }
58
87
  const queryHandle = await executeSql(sql);
59
88
  if (!queryHandle) {
60
89
  throw new Error(`Query for dataset "${datasetId}" was cancelled.`);
@@ -68,7 +97,7 @@ export function createPreparedDatasetStore(options = {}) {
68
97
  datasetId,
69
98
  table,
70
99
  geometryColumn: input.geometryColumn,
71
- geometryEncodingHint: input.geometryEncodingHint,
100
+ geometryEncodingHint,
72
101
  });
73
102
  set((state) => ({
74
103
  ...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":"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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';\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 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 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"]}
@@ -0,0 +1,20 @@
1
+ import type * as arrow from 'apache-arrow';
2
+ /** True for DuckDB native `GEOMETRY` / `GEOMETRY('CRS')` (not arrays/structs). */
3
+ export declare function isDuckDbNativeGeometryType(type: string | null | undefined): boolean;
4
+ /** `DESCRIBE SELECT * FROM (<sql>)` for logical column types. */
5
+ export declare function createDescribeDatasetSql(sql: string): string;
6
+ /** Column name + DuckDB type from a `DESCRIBE` result table. */
7
+ export type DescribedSqlColumn = {
8
+ name: string;
9
+ type: string;
10
+ };
11
+ /** Parse DuckDB DESCRIBE rows (`column_name`, `column_type`). */
12
+ export declare function parseDescribeSqlColumns(table: arrow.Table): DescribedSqlColumn[];
13
+ /** Names of columns whose DuckDB type is native `GEOMETRY`. */
14
+ export declare function geometryColumnsNeedingWkbWrap(columns: DescribedSqlColumn[]): string[];
15
+ /**
16
+ * `SELECT * REPLACE (ST_AsWKB(col) AS col, …) FROM (<sql>)` for native GEOMETRY.
17
+ * Returns null when there is nothing to wrap.
18
+ */
19
+ export declare function wrapSqlGeometryColumnsAsWkb(sql: string, geometryColumnNames: readonly string[]): string | null;
20
+ //# sourceMappingURL=wrapGeometryAsWkb.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wrapGeometryAsWkb.d.ts","sourceRoot":"","sources":["../../src/datasets/wrapGeometryAsWkb.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAC;AAM3C,kFAAkF;AAClF,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC9B,OAAO,CAIT;AAED,iEAAiE;AACjE,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAG5D;AAED,gEAAgE;AAChE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,iEAAiE;AACjE,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,KAAK,CAAC,KAAK,GACjB,kBAAkB,EAAE,CAgBtB;AAED,+DAA+D;AAC/D,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,kBAAkB,EAAE,GAC5B,MAAM,EAAE,CAIV;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,GAAG,EAAE,MAAM,EACX,mBAAmB,EAAE,SAAS,MAAM,EAAE,GACrC,MAAM,GAAG,IAAI,CAsBf"}
@@ -0,0 +1,65 @@
1
+ function quoteSqlIdentifier(identifier) {
2
+ return `"${identifier.replace(/"/g, '""')}"`;
3
+ }
4
+ /** True for DuckDB native `GEOMETRY` / `GEOMETRY('CRS')` (not arrays/structs). */
5
+ export function isDuckDbNativeGeometryType(type) {
6
+ if (!type)
7
+ return false;
8
+ const normalized = type.trim().toLowerCase();
9
+ return normalized === 'geometry' || normalized.startsWith('geometry(');
10
+ }
11
+ /** `DESCRIBE SELECT * FROM (<sql>)` for logical column types. */
12
+ export function createDescribeDatasetSql(sql) {
13
+ const cleaned = sql.trim().replace(/(?:\s*;+\s*)+$/, '');
14
+ return `DESCRIBE SELECT * FROM (${cleaned}) AS "__sqlrooms_describe_source"`;
15
+ }
16
+ /** Parse DuckDB DESCRIBE rows (`column_name`, `column_type`). */
17
+ export function parseDescribeSqlColumns(table) {
18
+ const names = table.getChild('column_name') ?? table.getChild('column_names');
19
+ const types = table.getChild('column_type') ?? table.getChild('column_types');
20
+ if (!names || !types)
21
+ return [];
22
+ const columns = [];
23
+ for (let i = 0; i < table.numRows; i++) {
24
+ const name = names.get(i);
25
+ const type = types.get(i);
26
+ if (typeof name !== 'string' || !name)
27
+ continue;
28
+ columns.push({
29
+ name,
30
+ type: typeof type === 'string' ? type : String(type ?? ''),
31
+ });
32
+ }
33
+ return columns;
34
+ }
35
+ /** Names of columns whose DuckDB type is native `GEOMETRY`. */
36
+ export function geometryColumnsNeedingWkbWrap(columns) {
37
+ return columns
38
+ .filter((column) => isDuckDbNativeGeometryType(column.type))
39
+ .map((column) => column.name);
40
+ }
41
+ /**
42
+ * `SELECT * REPLACE (ST_AsWKB(col) AS col, …) FROM (<sql>)` for native GEOMETRY.
43
+ * Returns null when there is nothing to wrap.
44
+ */
45
+ export function wrapSqlGeometryColumnsAsWkb(sql, geometryColumnNames) {
46
+ const unique = [
47
+ ...new Set(geometryColumnNames
48
+ .map((name) => name.trim())
49
+ .filter((name) => name.length > 0)),
50
+ ];
51
+ if (unique.length === 0)
52
+ return null;
53
+ const cleaned = sql.trim().replace(/(?:\s*;+\s*)+$/, '');
54
+ const replacements = unique
55
+ .map((name) => {
56
+ const quoted = quoteSqlIdentifier(name);
57
+ return `ST_AsWKB(${quoted}) AS ${quoted}`;
58
+ })
59
+ .join(', ');
60
+ return [
61
+ `SELECT * REPLACE (${replacements})`,
62
+ `FROM (${cleaned}) AS "__sqlrooms_as_wkb"`,
63
+ ].join('\n');
64
+ }
65
+ //# sourceMappingURL=wrapGeometryAsWkb.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wrapGeometryAsWkb.js","sourceRoot":"","sources":["../../src/datasets/wrapGeometryAsWkb.ts"],"names":[],"mappings":"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","sourcesContent":["import type * as arrow from 'apache-arrow';\n\nfunction quoteSqlIdentifier(identifier: string): string {\n return `\"${identifier.replace(/\"/g, '\"\"')}\"`;\n}\n\n/** True for DuckDB native `GEOMETRY` / `GEOMETRY('CRS')` (not arrays/structs). */\nexport function isDuckDbNativeGeometryType(\n type: string | null | undefined,\n): boolean {\n if (!type) return false;\n const normalized = type.trim().toLowerCase();\n return normalized === 'geometry' || normalized.startsWith('geometry(');\n}\n\n/** `DESCRIBE SELECT * FROM (<sql>)` for logical column types. */\nexport function createDescribeDatasetSql(sql: string): string {\n const cleaned = sql.trim().replace(/(?:\\s*;+\\s*)+$/, '');\n return `DESCRIBE SELECT * FROM (${cleaned}) AS \"__sqlrooms_describe_source\"`;\n}\n\n/** Column name + DuckDB type from a `DESCRIBE` result table. */\nexport type DescribedSqlColumn = {\n name: string;\n type: string;\n};\n\n/** Parse DuckDB DESCRIBE rows (`column_name`, `column_type`). */\nexport function parseDescribeSqlColumns(\n table: arrow.Table,\n): DescribedSqlColumn[] {\n const names = table.getChild('column_name') ?? table.getChild('column_names');\n const types = table.getChild('column_type') ?? table.getChild('column_types');\n if (!names || !types) return [];\n\n const columns: DescribedSqlColumn[] = [];\n for (let i = 0; i < table.numRows; i++) {\n const name = names.get(i);\n const type = types.get(i);\n if (typeof name !== 'string' || !name) continue;\n columns.push({\n name,\n type: typeof type === 'string' ? type : String(type ?? ''),\n });\n }\n return columns;\n}\n\n/** Names of columns whose DuckDB type is native `GEOMETRY`. */\nexport function geometryColumnsNeedingWkbWrap(\n columns: DescribedSqlColumn[],\n): string[] {\n return columns\n .filter((column) => isDuckDbNativeGeometryType(column.type))\n .map((column) => column.name);\n}\n\n/**\n * `SELECT * REPLACE (ST_AsWKB(col) AS col, …) FROM (<sql>)` for native GEOMETRY.\n * Returns null when there is nothing to wrap.\n */\nexport function wrapSqlGeometryColumnsAsWkb(\n sql: string,\n geometryColumnNames: readonly string[],\n): string | null {\n const unique = [\n ...new Set(\n geometryColumnNames\n .map((name) => name.trim())\n .filter((name) => name.length > 0),\n ),\n ];\n if (unique.length === 0) return null;\n\n const cleaned = sql.trim().replace(/(?:\\s*;+\\s*)+$/, '');\n const replacements = unique\n .map((name) => {\n const quoted = quoteSqlIdentifier(name);\n return `ST_AsWKB(${quoted}) AS ${quoted}`;\n })\n .join(', ');\n\n return [\n `SELECT * REPLACE (${replacements})`,\n `FROM (${cleaned}) AS \"__sqlrooms_as_wkb\"`,\n ].join('\\n');\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -14,6 +14,7 @@ export type { DeckMapConfigColumn, DeckMapFillColor, DeckMapTableReference, } fr
14
14
  export { getFirstDatasetSourceTableName, hasSqlOnlyDatasetSource, } from './datasetSourceUtils';
15
15
  export type { DeckMapDatasetSourceConfig } from './datasetSourceUtils';
16
16
  export { DeckMapResourceConfigParameter, DeckMapResourceToolParameters, } from './mapAiConfig';
17
+ export { normalizeAiDeckMapConfig, prepareAiDeckMapConfig, validateAndFixColorScaleFields, type NormalizeAiDeckMapConfigOptions, type PrepareAiDeckMapConfigOptions, type ResolveColorScaleTable, } from './aiNormalize';
17
18
  export { DeckMapResourceConfigError, assertDeckMapResourceConfig, getDeckMapResourceAiInstructions, getDeckMapResourceConfigIssues, mergeDeckMapResourceConfigPatch, type DeckMapResourceConfigMergeOptions, type DeckMapResourceConfigIssue, type DeckMapResourceConfigValidationOptions, } from './mapResourceAuthoring';
18
19
  export { createOrUpdateDeckMapResource, type CreateOrUpdateDeckMapResourceHost, type CreateOrUpdateDeckMapResourceParams, type CreateOrUpdateDeckMapResourceResult, } from './createOrUpdateDeckMapResource';
19
20
  export { DeckMapResourceSchema, DeckMapsSliceConfig, createDeckMapsSlice, useStoreWithDeckMaps, } from './DeckMapsSlice';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -12,6 +12,7 @@ export { getDeckMapDataPolicy } from './mapDataPolicy';
12
12
  export { createDeckMapDashboardConfigForTable, createDeckMapConfigForTable, createDeckMapDashboardPanelConfigForTable, createDeckMapPointTransformSql, findDeckMapLongitudeLatitudeColumns, findGeometryColumn, findLongitudeLatitudeColumns, normalizeDeckMapFillColor, normalizeDeckMapPointConfig, quoteDeckMapSqlIdentifier, quoteDeckMapSqlTableReference, regenerateMapConfigForTable, } from './mapConfigUtils';
13
13
  export { getFirstDatasetSourceTableName, hasSqlOnlyDatasetSource, } from './datasetSourceUtils';
14
14
  export { DeckMapResourceConfigParameter, DeckMapResourceToolParameters, } from './mapAiConfig';
15
+ export { normalizeAiDeckMapConfig, prepareAiDeckMapConfig, validateAndFixColorScaleFields, } from './aiNormalize';
15
16
  export { DeckMapResourceConfigError, assertDeckMapResourceConfig, getDeckMapResourceAiInstructions, getDeckMapResourceConfigIssues, mergeDeckMapResourceConfigPatch, } from './mapResourceAuthoring';
16
17
  export { createOrUpdateDeckMapResource, } from './createOrUpdateDeckMapResource';
17
18
  export { DeckMapResourceSchema, DeckMapsSliceConfig, createDeckMapsSlice, useStoreWithDeckMaps, } from './DeckMapsSlice';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAC,gBAAgB,EAAC,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAC,8BAA8B,EAAC,MAAM,kCAAkC,CAAC;AAChF,OAAO,EAAC,oBAAoB,EAAC,MAAM,oBAAoB,CAAC;AACxD,OAAO,EACL,oBAAoB,GAErB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,oBAAoB,EACpB,0BAA0B,GAE3B,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,iCAAiC,EACjC,gCAAgC,EAChC,6BAA6B,EAC7B,kCAAkC,EAClC,oCAAoC,GACrC,MAAM,aAAa,CAAC;AACrB,OAAO,EAAC,oBAAoB,EAAyB,MAAM,iBAAiB,CAAC;AAC7E,OAAO,EACL,oCAAoC,EACpC,2BAA2B,EAC3B,yCAAyC,EACzC,8BAA8B,EAC9B,mCAAmC,EACnC,kBAAkB,EAClB,4BAA4B,EAC5B,yBAAyB,EACzB,2BAA2B,EAC3B,yBAAyB,EACzB,6BAA6B,EAC7B,2BAA2B,GAC5B,MAAM,kBAAkB,CAAC;AAM1B,OAAO,EACL,8BAA8B,EAC9B,uBAAuB,GACxB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,8BAA8B,EAC9B,6BAA6B,GAC9B,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,EAC3B,gCAAgC,EAChC,8BAA8B,EAC9B,+BAA+B,GAIhC,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,6BAA6B,GAI9B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AAOzB,OAAO,EACL,cAAc,EACd,wBAAwB,GAGzB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,6BAA6B,EAC7B,4BAA4B,EAC5B,mBAAmB,EACnB,qCAAqC,EACrC,8BAA8B,GAE/B,MAAM,6BAA6B,CAAC;AAerC,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAC1C,OAAO,EACL,4BAA4B,EAC5B,mBAAmB,EACnB,uBAAuB,GAGxB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,kBAAkB,EAClB,oBAAoB,IAAI,wBAAwB,EAChD,oBAAoB,EACpB,eAAe,EACf,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAC,2BAA2B,EAAC,MAAM,oCAAoC,CAAC;AAC/E,OAAO,EAAC,kBAAkB,EAAC,MAAM,8BAA8B,CAAC;AAUhE,OAAO,EACL,wBAAwB,EACxB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,kCAAkC,EAClC,yBAAyB,GAC1B,MAAM,4BAA4B,CAAC","sourcesContent":["/**\n * {@include ../README.md}\n * @packageDocumentation\n */\n\nexport {ColorScaleLegend} from '@sqlrooms/color-scales';\nexport {createDeckJsonSpecFromDatasets} from './createDeckJsonSpecFromDatasets';\nexport {DeckMapBlockSettings} from './BlockMapSettings';\nexport {\n DeckMapSettingsPanel,\n type DeckMapSettingsPanelProps,\n} from './MapSettings';\nexport {\n DeckMapBlockRenderer,\n ensureDeckMapResourceState,\n type DeckMapBlockRendererProps,\n} from './block';\nexport {\n asDeckJsonMapConfig,\n createEmptyDeckMapConfig,\n createDeckMapDashboardPanelConfig,\n DEFAULT_DECK_MAP_MAX_DATA_POINTS,\n DECK_MAP_DASHBOARD_PANEL_TYPE,\n isDeckMapDashboardSqlDatasetSource,\n isDeckMapDashboardTableDatasetSource,\n} from './mapConfig';\nexport {getDeckMapDataPolicy, type DeckMapDataPolicy} from './mapDataPolicy';\nexport {\n createDeckMapDashboardConfigForTable,\n createDeckMapConfigForTable,\n createDeckMapDashboardPanelConfigForTable,\n createDeckMapPointTransformSql,\n findDeckMapLongitudeLatitudeColumns,\n findGeometryColumn,\n findLongitudeLatitudeColumns,\n normalizeDeckMapFillColor,\n normalizeDeckMapPointConfig,\n quoteDeckMapSqlIdentifier,\n quoteDeckMapSqlTableReference,\n regenerateMapConfigForTable,\n} from './mapConfigUtils';\nexport type {\n DeckMapConfigColumn,\n DeckMapFillColor,\n DeckMapTableReference,\n} from './mapConfigUtils';\nexport {\n getFirstDatasetSourceTableName,\n hasSqlOnlyDatasetSource,\n} from './datasetSourceUtils';\nexport type {DeckMapDatasetSourceConfig} from './datasetSourceUtils';\nexport {\n DeckMapResourceConfigParameter,\n DeckMapResourceToolParameters,\n} from './mapAiConfig';\nexport {\n DeckMapResourceConfigError,\n assertDeckMapResourceConfig,\n getDeckMapResourceAiInstructions,\n getDeckMapResourceConfigIssues,\n mergeDeckMapResourceConfigPatch,\n type DeckMapResourceConfigMergeOptions,\n type DeckMapResourceConfigIssue,\n type DeckMapResourceConfigValidationOptions,\n} from './mapResourceAuthoring';\nexport {\n createOrUpdateDeckMapResource,\n type CreateOrUpdateDeckMapResourceHost,\n type CreateOrUpdateDeckMapResourceParams,\n type CreateOrUpdateDeckMapResourceResult,\n} from './createOrUpdateDeckMapResource';\nexport {\n DeckMapResourceSchema,\n DeckMapsSliceConfig,\n createDeckMapsSlice,\n useStoreWithDeckMaps,\n} from './DeckMapsSlice';\nexport type {\n DeckMapResource,\n DeckMapRuntimeIssue,\n DeckMapRuntimeIssueReporter,\n DeckMapsSliceState,\n} from './DeckMapsSlice';\nexport {\n DeckMapSurface,\n directDeckMapDataAdapter,\n type DeckMapDataAdapter,\n type DeckMapSurfaceProps,\n} from './DeckMapSurface';\nexport {\n DECK_MAP_BLOCK_DEFAULT_HEIGHT,\n DECK_MAP_BLOCK_DEFAULT_TITLE,\n DECK_MAP_BLOCK_TYPE,\n createDeckMapBlockDocumentCommandType,\n createDeckMapBlockDocumentType,\n type DeckMapBlockDocumentRegistrationOptions,\n} from './blockDocumentRegistration';\nexport type {\n DeckMapConfigMode,\n DeckMapDashboardFitToDataConfig,\n CreateDeckMapDashboardPanelConfigOptions,\n DeckMapDashboardDatasetConfig,\n DeckMapDataPolicyOverride,\n DeckMapDashboardInteractionConfig,\n DeckMapDashboardPanelConfig,\n DeckMapConfig,\n DeckMapDatasetConfig,\n DeckMapDatasetSource,\n DeckMapFitToDataConfig,\n DeckMapInteractionConfig,\n} from './mapConfig';\nexport {DeckJsonMap} from './DeckJsonMap';\nexport {\n DeckMapDefaultStylesProvider,\n resolveDeckMapStyle,\n useDeckMapDefaultStyles,\n type DeckMapDefaultStyles,\n type DeckMapStyle,\n} from './DeckMapDefaultStylesProvider';\nexport {\n ColorScaleFunction,\n GeometryEncodingHint as DeckGeometryEncodingHint,\n DeckJsonMapLayerSpec,\n DeckJsonMapSpec,\n LayerBindingConfig,\n LayerBindingProps,\n} from './DeckJsonMapSpec';\nexport {createDeckJsonConfiguration} from './json/createDeckJsonConfiguration';\nexport {prepareDeckDataset} from './prepare/prepareDeckDataset';\n\nexport type {ColorLegendConfig, ColorScaleConfig} from '@sqlrooms/color-scales';\nexport type {\n GeometryEncodingHint,\n PreparedDeckDataset,\n PreparedGeoArrowLayerData,\n ResolvedGeometryColumn,\n ResolvedGeometryEncoding,\n} from './prepare/types';\nexport {\n isArrowTableDatasetInput,\n isSqlDatasetInput,\n isTableDatasetInput,\n} from './types';\nexport {\n DECK_TABLE_DATASET_SOURCE_RELATION,\n createDeckTableDatasetSql,\n} from './datasets/tableDatasetSql';\nexport type {\n CreateDeckJsonSpecFromDatasetsOptions,\n DeckArrowTableDatasetInput,\n DeckAutoLayerType,\n DeckDatasetInput,\n DeckJsonMapHandle,\n DeckJsonMapProps,\n DeckJsonSpecDatasetHint,\n DeckSqlDatasetInput,\n DeckTableDatasetInput,\n DeckTable,\n PreparedDeckDatasetState,\n} from './types';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAC,gBAAgB,EAAC,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAC,8BAA8B,EAAC,MAAM,kCAAkC,CAAC;AAChF,OAAO,EAAC,oBAAoB,EAAC,MAAM,oBAAoB,CAAC;AACxD,OAAO,EACL,oBAAoB,GAErB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,oBAAoB,EACpB,0BAA0B,GAE3B,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,iCAAiC,EACjC,gCAAgC,EAChC,6BAA6B,EAC7B,kCAAkC,EAClC,oCAAoC,GACrC,MAAM,aAAa,CAAC;AACrB,OAAO,EAAC,oBAAoB,EAAyB,MAAM,iBAAiB,CAAC;AAC7E,OAAO,EACL,oCAAoC,EACpC,2BAA2B,EAC3B,yCAAyC,EACzC,8BAA8B,EAC9B,mCAAmC,EACnC,kBAAkB,EAClB,4BAA4B,EAC5B,yBAAyB,EACzB,2BAA2B,EAC3B,yBAAyB,EACzB,6BAA6B,EAC7B,2BAA2B,GAC5B,MAAM,kBAAkB,CAAC;AAM1B,OAAO,EACL,8BAA8B,EAC9B,uBAAuB,GACxB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,8BAA8B,EAC9B,6BAA6B,GAC9B,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,wBAAwB,EACxB,sBAAsB,EACtB,8BAA8B,GAI/B,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,EAC3B,gCAAgC,EAChC,8BAA8B,EAC9B,+BAA+B,GAIhC,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,6BAA6B,GAI9B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AAOzB,OAAO,EACL,cAAc,EACd,wBAAwB,GAGzB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,6BAA6B,EAC7B,4BAA4B,EAC5B,mBAAmB,EACnB,qCAAqC,EACrC,8BAA8B,GAE/B,MAAM,6BAA6B,CAAC;AAerC,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAC1C,OAAO,EACL,4BAA4B,EAC5B,mBAAmB,EACnB,uBAAuB,GAGxB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,kBAAkB,EAClB,oBAAoB,IAAI,wBAAwB,EAChD,oBAAoB,EACpB,eAAe,EACf,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAC,2BAA2B,EAAC,MAAM,oCAAoC,CAAC;AAC/E,OAAO,EAAC,kBAAkB,EAAC,MAAM,8BAA8B,CAAC;AAUhE,OAAO,EACL,wBAAwB,EACxB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,kCAAkC,EAClC,yBAAyB,GAC1B,MAAM,4BAA4B,CAAC","sourcesContent":["/**\n * {@include ../README.md}\n * @packageDocumentation\n */\n\nexport {ColorScaleLegend} from '@sqlrooms/color-scales';\nexport {createDeckJsonSpecFromDatasets} from './createDeckJsonSpecFromDatasets';\nexport {DeckMapBlockSettings} from './BlockMapSettings';\nexport {\n DeckMapSettingsPanel,\n type DeckMapSettingsPanelProps,\n} from './MapSettings';\nexport {\n DeckMapBlockRenderer,\n ensureDeckMapResourceState,\n type DeckMapBlockRendererProps,\n} from './block';\nexport {\n asDeckJsonMapConfig,\n createEmptyDeckMapConfig,\n createDeckMapDashboardPanelConfig,\n DEFAULT_DECK_MAP_MAX_DATA_POINTS,\n DECK_MAP_DASHBOARD_PANEL_TYPE,\n isDeckMapDashboardSqlDatasetSource,\n isDeckMapDashboardTableDatasetSource,\n} from './mapConfig';\nexport {getDeckMapDataPolicy, type DeckMapDataPolicy} from './mapDataPolicy';\nexport {\n createDeckMapDashboardConfigForTable,\n createDeckMapConfigForTable,\n createDeckMapDashboardPanelConfigForTable,\n createDeckMapPointTransformSql,\n findDeckMapLongitudeLatitudeColumns,\n findGeometryColumn,\n findLongitudeLatitudeColumns,\n normalizeDeckMapFillColor,\n normalizeDeckMapPointConfig,\n quoteDeckMapSqlIdentifier,\n quoteDeckMapSqlTableReference,\n regenerateMapConfigForTable,\n} from './mapConfigUtils';\nexport type {\n DeckMapConfigColumn,\n DeckMapFillColor,\n DeckMapTableReference,\n} from './mapConfigUtils';\nexport {\n getFirstDatasetSourceTableName,\n hasSqlOnlyDatasetSource,\n} from './datasetSourceUtils';\nexport type {DeckMapDatasetSourceConfig} from './datasetSourceUtils';\nexport {\n DeckMapResourceConfigParameter,\n DeckMapResourceToolParameters,\n} from './mapAiConfig';\nexport {\n normalizeAiDeckMapConfig,\n prepareAiDeckMapConfig,\n validateAndFixColorScaleFields,\n type NormalizeAiDeckMapConfigOptions,\n type PrepareAiDeckMapConfigOptions,\n type ResolveColorScaleTable,\n} from './aiNormalize';\nexport {\n DeckMapResourceConfigError,\n assertDeckMapResourceConfig,\n getDeckMapResourceAiInstructions,\n getDeckMapResourceConfigIssues,\n mergeDeckMapResourceConfigPatch,\n type DeckMapResourceConfigMergeOptions,\n type DeckMapResourceConfigIssue,\n type DeckMapResourceConfigValidationOptions,\n} from './mapResourceAuthoring';\nexport {\n createOrUpdateDeckMapResource,\n type CreateOrUpdateDeckMapResourceHost,\n type CreateOrUpdateDeckMapResourceParams,\n type CreateOrUpdateDeckMapResourceResult,\n} from './createOrUpdateDeckMapResource';\nexport {\n DeckMapResourceSchema,\n DeckMapsSliceConfig,\n createDeckMapsSlice,\n useStoreWithDeckMaps,\n} from './DeckMapsSlice';\nexport type {\n DeckMapResource,\n DeckMapRuntimeIssue,\n DeckMapRuntimeIssueReporter,\n DeckMapsSliceState,\n} from './DeckMapsSlice';\nexport {\n DeckMapSurface,\n directDeckMapDataAdapter,\n type DeckMapDataAdapter,\n type DeckMapSurfaceProps,\n} from './DeckMapSurface';\nexport {\n DECK_MAP_BLOCK_DEFAULT_HEIGHT,\n DECK_MAP_BLOCK_DEFAULT_TITLE,\n DECK_MAP_BLOCK_TYPE,\n createDeckMapBlockDocumentCommandType,\n createDeckMapBlockDocumentType,\n type DeckMapBlockDocumentRegistrationOptions,\n} from './blockDocumentRegistration';\nexport type {\n DeckMapConfigMode,\n DeckMapDashboardFitToDataConfig,\n CreateDeckMapDashboardPanelConfigOptions,\n DeckMapDashboardDatasetConfig,\n DeckMapDataPolicyOverride,\n DeckMapDashboardInteractionConfig,\n DeckMapDashboardPanelConfig,\n DeckMapConfig,\n DeckMapDatasetConfig,\n DeckMapDatasetSource,\n DeckMapFitToDataConfig,\n DeckMapInteractionConfig,\n} from './mapConfig';\nexport {DeckJsonMap} from './DeckJsonMap';\nexport {\n DeckMapDefaultStylesProvider,\n resolveDeckMapStyle,\n useDeckMapDefaultStyles,\n type DeckMapDefaultStyles,\n type DeckMapStyle,\n} from './DeckMapDefaultStylesProvider';\nexport {\n ColorScaleFunction,\n GeometryEncodingHint as DeckGeometryEncodingHint,\n DeckJsonMapLayerSpec,\n DeckJsonMapSpec,\n LayerBindingConfig,\n LayerBindingProps,\n} from './DeckJsonMapSpec';\nexport {createDeckJsonConfiguration} from './json/createDeckJsonConfiguration';\nexport {prepareDeckDataset} from './prepare/prepareDeckDataset';\n\nexport type {ColorLegendConfig, ColorScaleConfig} from '@sqlrooms/color-scales';\nexport type {\n GeometryEncodingHint,\n PreparedDeckDataset,\n PreparedGeoArrowLayerData,\n ResolvedGeometryColumn,\n ResolvedGeometryEncoding,\n} from './prepare/types';\nexport {\n isArrowTableDatasetInput,\n isSqlDatasetInput,\n isTableDatasetInput,\n} from './types';\nexport {\n DECK_TABLE_DATASET_SOURCE_RELATION,\n createDeckTableDatasetSql,\n} from './datasets/tableDatasetSql';\nexport type {\n CreateDeckJsonSpecFromDatasetsOptions,\n DeckArrowTableDatasetInput,\n DeckAutoLayerType,\n DeckDatasetInput,\n DeckJsonMapHandle,\n DeckJsonMapProps,\n DeckJsonSpecDatasetHint,\n DeckSqlDatasetInput,\n DeckTableDatasetInput,\n DeckTable,\n PreparedDeckDatasetState,\n} from './types';\n"]}
@@ -1,4 +1,9 @@
1
1
  import type * as arrow from 'apache-arrow';
2
+ /**
3
+ * True when a column name can be safely embedded in a GeoArrow `@@=` expression
4
+ * (valid JS identifier that is not a reserved word or expression global).
5
+ */
6
+ export declare function isBindableGeoArrowFieldIdentifier(name: string): boolean;
2
7
  export declare function compileGeoArrowAccessor(expression: string, table: arrow.Table): ({ index, data, target, }: {
3
8
  index: number;
4
9
  data: {
@@ -1 +1 @@
1
- {"version":3,"file":"compileGeoArrowAccessor.d.ts","sourceRoot":"","sources":["../../src/json/compileGeoArrowAccessor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAC;AA8H3C,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,KAAK,CAAC,KAAK,8BAkBf;IACD,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE;QAAC,IAAI,EAAE;YAAC,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;SAAC,CAAA;KAAC,CAAC;IAC5D,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,aAiBF;AAED,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,CAAC,IAAI,EAAE;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE;QAAC,IAAI,EAAE,OAAO,CAAA;KAAC,CAAC;IACtB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,KAAK,OAAO,CASZ"}
1
+ {"version":3,"file":"compileGeoArrowAccessor.d.ts","sourceRoot":"","sources":["../../src/json/compileGeoArrowAccessor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAC;AA8E3C;;;GAGG;AACH,wBAAgB,iCAAiC,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEvE;AA0DD,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,KAAK,CAAC,KAAK,8BAkBf;IACD,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE;QAAC,IAAI,EAAE;YAAC,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;SAAC,CAAA;KAAC,CAAC;IAC5D,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,aAmBF;AAED,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,CAAC,IAAI,EAAE;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE;QAAC,IAAI,EAAE,OAAO,CAAA;KAAC,CAAC;IACtB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,KAAK,OAAO,CASZ"}
@@ -69,6 +69,13 @@ const RESERVED_IDENTIFIERS = new Set([
69
69
  // Accessor runtime parameter
70
70
  'target',
71
71
  ]);
72
+ /**
73
+ * True when a column name can be safely embedded in a GeoArrow `@@=` expression
74
+ * (valid JS identifier that is not a reserved word or expression global).
75
+ */
76
+ export function isBindableGeoArrowFieldIdentifier(name) {
77
+ return isValidIdentifier(name) && !RESERVED_IDENTIFIERS.has(name);
78
+ }
72
79
  function unique(values) {
73
80
  return [...new Set(values)];
74
81
  }
@@ -102,6 +109,13 @@ function copyArrayLikeIntoTarget(result) {
102
109
  // GeoArrow delegates to deck sublayers.
103
110
  return Array.from(result);
104
111
  }
112
+ /** Arrow Int64/Uint64 columns surface as bigint; deck.gl accessors need numbers. */
113
+ function coerceArrowValue(value) {
114
+ if (typeof value === 'bigint') {
115
+ return Number(value);
116
+ }
117
+ return value;
118
+ }
105
119
  export function compileGeoArrowAccessor(expression, table) {
106
120
  const trimmedExpression = expression.trim();
107
121
  const bindings = resolveColumnBindings(trimmedExpression, table);
@@ -110,11 +124,11 @@ export function compileGeoArrowAccessor(expression, table) {
110
124
  // {index, data: {data: batch}, target} from the upstream layer wrapper.
111
125
  const accessor = ({ index, data, target, }) => {
112
126
  const batch = data.data;
113
- const args = bindings.map((binding) => binding.columnName
127
+ const args = bindings.map((binding) => coerceArrowValue(binding.columnName
114
128
  ? batch.getChild(binding.columnName)?.get(index)
115
- : undefined);
129
+ : undefined));
116
130
  const result = evaluator(...args, target);
117
- return copyArrayLikeIntoTarget(result);
131
+ return coerceArrowValue(copyArrayLikeIntoTarget(result));
118
132
  };
119
133
  Object.defineProperty(accessor, GEOARROW_COMPILED_ACCESSOR, {
120
134
  value: true,
@@ -1 +1 @@
1
- {"version":3,"file":"compileGeoArrowAccessor.js","sourceRoot":"","sources":["../../src/json/compileGeoArrowAccessor.ts"],"names":[],"mappings":"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","sourcesContent":["import type * as arrow from 'apache-arrow';\n\nconst GEOARROW_COMPILED_ACCESSOR = Symbol.for(\n '@sqlrooms/deck/compiled-geoarrow-accessor',\n);\n\nfunction isValidIdentifier(name: string) {\n return /^[A-Za-z_$][\\w$]*$/.test(name);\n}\n\nconst RESERVED_IDENTIFIERS = new Set([\n // JS keywords & future reserved words\n 'abstract',\n 'arguments',\n 'async',\n 'await',\n 'break',\n 'case',\n 'catch',\n 'class',\n 'const',\n 'continue',\n 'debugger',\n 'default',\n 'delete',\n 'do',\n 'else',\n 'enum',\n 'eval',\n 'export',\n 'extends',\n 'finally',\n 'for',\n 'function',\n 'if',\n 'implements',\n 'import',\n 'in',\n 'instanceof',\n 'interface',\n 'let',\n 'new',\n 'of',\n 'package',\n 'private',\n 'protected',\n 'public',\n 'return',\n 'static',\n 'super',\n 'switch',\n 'this',\n 'throw',\n 'try',\n 'typeof',\n 'var',\n 'void',\n 'while',\n 'with',\n 'yield',\n // Literals & globals used in expressions\n 'true',\n 'false',\n 'null',\n 'undefined',\n 'NaN',\n 'Infinity',\n 'Math',\n 'Number',\n 'String',\n 'Boolean',\n 'Array',\n 'Object',\n 'Date',\n // Accessor runtime parameter\n 'target',\n]);\n\nfunction unique<T>(values: T[]) {\n return [...new Set(values)];\n}\n\nfunction resolveColumnBindings(expression: string, table: arrow.Table) {\n const schemaFieldNames = table.schema.fields\n .map((field) => field.name)\n .filter(isValidIdentifier);\n\n const identifiers = unique(\n Array.from(expression.matchAll(/\\b[A-Za-z_$][\\w$]*\\b/g))\n .map((match) => match[0])\n .filter((identifier) => !RESERVED_IDENTIFIERS.has(identifier)),\n );\n\n return identifiers.map((identifier) => {\n const exactMatch = schemaFieldNames.find(\n (fieldName) => fieldName === identifier,\n );\n if (exactMatch) {\n return {identifier, columnName: exactMatch};\n }\n\n const caseInsensitiveMatches = schemaFieldNames.filter(\n (fieldName) => fieldName.toLowerCase() === identifier.toLowerCase(),\n );\n\n return {\n identifier,\n columnName:\n caseInsensitiveMatches.length === 1\n ? caseInsensitiveMatches[0]!\n : undefined,\n };\n });\n}\n\nfunction copyArrayLikeIntoTarget(result: unknown) {\n if (!Array.isArray(result) && !ArrayBuffer.isView(result)) {\n return result;\n }\n\n // Keep returning plain JS arrays. Reusing deck's typed `target` buffer\n // causes `ScatterplotLayer` binary attribute errors (`Float64Array`) when\n // GeoArrow delegates to deck sublayers.\n return Array.from(result as ArrayLike<number>);\n}\n\nexport function compileGeoArrowAccessor(\n expression: string,\n table: arrow.Table,\n) {\n const trimmedExpression = expression.trim();\n\n const bindings = resolveColumnBindings(trimmedExpression, table);\n\n const evaluator = new Function(\n ...bindings.map((binding) => binding.identifier),\n 'target',\n `return (${trimmedExpression});`,\n ) as (...args: unknown[]) => unknown;\n\n // GeoArrow 0.4.x callbacks are batch-oriented: they receive\n // {index, data: {data: batch}, target} from the upstream layer wrapper.\n const accessor = ({\n index,\n data,\n target,\n }: {\n index: number;\n data: {data: {get: (i: number) => Record<string, unknown>}};\n target: number[];\n }) => {\n const batch = data.data as arrow.Table | arrow.RecordBatch;\n const args = bindings.map((binding) =>\n binding.columnName\n ? batch.getChild(binding.columnName)?.get(index)\n : undefined,\n );\n const result = evaluator(...args, target);\n return copyArrayLikeIntoTarget(result);\n };\n\n Object.defineProperty(accessor, GEOARROW_COMPILED_ACCESSOR, {\n value: true,\n enumerable: false,\n });\n\n return accessor;\n}\n\nexport function isCompiledGeoArrowAccessor(\n value: unknown,\n): value is (info: {\n index: number;\n data: {data: unknown};\n target: number[];\n}) => unknown {\n return (\n typeof value === 'function' &&\n Boolean(\n (value as {[GEOARROW_COMPILED_ACCESSOR]?: boolean})[\n GEOARROW_COMPILED_ACCESSOR\n ],\n )\n );\n}\n"]}
1
+ {"version":3,"file":"compileGeoArrowAccessor.js","sourceRoot":"","sources":["../../src/json/compileGeoArrowAccessor.ts"],"names":[],"mappings":"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","sourcesContent":["import type * as arrow from 'apache-arrow';\n\nconst GEOARROW_COMPILED_ACCESSOR = Symbol.for(\n '@sqlrooms/deck/compiled-geoarrow-accessor',\n);\n\nfunction isValidIdentifier(name: string) {\n return /^[A-Za-z_$][\\w$]*$/.test(name);\n}\n\nconst RESERVED_IDENTIFIERS = new Set([\n // JS keywords & future reserved words\n 'abstract',\n 'arguments',\n 'async',\n 'await',\n 'break',\n 'case',\n 'catch',\n 'class',\n 'const',\n 'continue',\n 'debugger',\n 'default',\n 'delete',\n 'do',\n 'else',\n 'enum',\n 'eval',\n 'export',\n 'extends',\n 'finally',\n 'for',\n 'function',\n 'if',\n 'implements',\n 'import',\n 'in',\n 'instanceof',\n 'interface',\n 'let',\n 'new',\n 'of',\n 'package',\n 'private',\n 'protected',\n 'public',\n 'return',\n 'static',\n 'super',\n 'switch',\n 'this',\n 'throw',\n 'try',\n 'typeof',\n 'var',\n 'void',\n 'while',\n 'with',\n 'yield',\n // Literals & globals used in expressions\n 'true',\n 'false',\n 'null',\n 'undefined',\n 'NaN',\n 'Infinity',\n 'Math',\n 'Number',\n 'String',\n 'Boolean',\n 'Array',\n 'Object',\n 'Date',\n // Accessor runtime parameter\n 'target',\n]);\n\n/**\n * True when a column name can be safely embedded in a GeoArrow `@@=` expression\n * (valid JS identifier that is not a reserved word or expression global).\n */\nexport function isBindableGeoArrowFieldIdentifier(name: string): boolean {\n return isValidIdentifier(name) && !RESERVED_IDENTIFIERS.has(name);\n}\n\nfunction unique<T>(values: T[]) {\n return [...new Set(values)];\n}\n\nfunction resolveColumnBindings(expression: string, table: arrow.Table) {\n const schemaFieldNames = table.schema.fields\n .map((field) => field.name)\n .filter(isValidIdentifier);\n\n const identifiers = unique(\n Array.from(expression.matchAll(/\\b[A-Za-z_$][\\w$]*\\b/g))\n .map((match) => match[0])\n .filter((identifier) => !RESERVED_IDENTIFIERS.has(identifier)),\n );\n\n return identifiers.map((identifier) => {\n const exactMatch = schemaFieldNames.find(\n (fieldName) => fieldName === identifier,\n );\n if (exactMatch) {\n return {identifier, columnName: exactMatch};\n }\n\n const caseInsensitiveMatches = schemaFieldNames.filter(\n (fieldName) => fieldName.toLowerCase() === identifier.toLowerCase(),\n );\n\n return {\n identifier,\n columnName:\n caseInsensitiveMatches.length === 1\n ? caseInsensitiveMatches[0]!\n : undefined,\n };\n });\n}\n\nfunction copyArrayLikeIntoTarget(result: unknown) {\n if (!Array.isArray(result) && !ArrayBuffer.isView(result)) {\n return result;\n }\n\n // Keep returning plain JS arrays. Reusing deck's typed `target` buffer\n // causes `ScatterplotLayer` binary attribute errors (`Float64Array`) when\n // GeoArrow delegates to deck sublayers.\n return Array.from(result as ArrayLike<number>);\n}\n\n/** Arrow Int64/Uint64 columns surface as bigint; deck.gl accessors need numbers. */\nfunction coerceArrowValue(value: unknown): unknown {\n if (typeof value === 'bigint') {\n return Number(value);\n }\n return value;\n}\n\nexport function compileGeoArrowAccessor(\n expression: string,\n table: arrow.Table,\n) {\n const trimmedExpression = expression.trim();\n\n const bindings = resolveColumnBindings(trimmedExpression, table);\n\n const evaluator = new Function(\n ...bindings.map((binding) => binding.identifier),\n 'target',\n `return (${trimmedExpression});`,\n ) as (...args: unknown[]) => unknown;\n\n // GeoArrow 0.4.x callbacks are batch-oriented: they receive\n // {index, data: {data: batch}, target} from the upstream layer wrapper.\n const accessor = ({\n index,\n data,\n target,\n }: {\n index: number;\n data: {data: {get: (i: number) => Record<string, unknown>}};\n target: number[];\n }) => {\n const batch = data.data as arrow.Table | arrow.RecordBatch;\n const args = bindings.map((binding) =>\n coerceArrowValue(\n binding.columnName\n ? batch.getChild(binding.columnName)?.get(index)\n : undefined,\n ),\n );\n const result = evaluator(...args, target);\n return coerceArrowValue(copyArrayLikeIntoTarget(result));\n };\n\n Object.defineProperty(accessor, GEOARROW_COMPILED_ACCESSOR, {\n value: true,\n enumerable: false,\n });\n\n return accessor;\n}\n\nexport function isCompiledGeoArrowAccessor(\n value: unknown,\n): value is (info: {\n index: number;\n data: {data: unknown};\n target: number[];\n}) => unknown {\n return (\n typeof value === 'function' &&\n Boolean(\n (value as {[GEOARROW_COMPILED_ACCESSOR]?: boolean})[\n GEOARROW_COMPILED_ACCESSOR\n ],\n )\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"createDeckJsonConfiguration.d.ts","sourceRoot":"","sources":["../../src/json/createDeckJsonConfiguration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,iBAAiB,EAAC,MAAM,eAAe,CAAC;AAKhD,OAAO,KAAK,EAAoB,wBAAwB,EAAC,MAAM,UAAU,CAAC;AAuB1E,KAAK,kCAAkC,GAAG;IACxC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC;IACxD,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB,CAAC;AAgLF,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,kCAAkC,qBA+N5C"}
1
+ {"version":3,"file":"createDeckJsonConfiguration.d.ts","sourceRoot":"","sources":["../../src/json/createDeckJsonConfiguration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,iBAAiB,EAAC,MAAM,eAAe,CAAC;AAUhD,OAAO,KAAK,EAAoB,wBAAwB,EAAC,MAAM,UAAU,CAAC;AA8B1E,KAAK,kCAAkC,GAAG;IACxC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC;IACxD,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB,CAAC;AAoOF,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,kCAAkC,qBA+P5C"}