@databricks/appkit-ui 0.1.4 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. package/AGENTS.md +89 -12
  2. package/CLAUDE.md +89 -12
  3. package/NOTICE.md +4 -0
  4. package/README.md +21 -15
  5. package/dist/js/arrow/arrow-client.js.map +1 -1
  6. package/dist/js/arrow/lazy-arrow.js.map +1 -1
  7. package/dist/js/sse/connect-sse.js.map +1 -1
  8. package/dist/react/charts/area/index.d.ts +2 -2
  9. package/dist/react/charts/bar/index.d.ts +2 -2
  10. package/dist/react/charts/base.d.ts +2 -2
  11. package/dist/react/charts/base.js.map +1 -1
  12. package/dist/react/charts/create-chart.d.ts +2 -2
  13. package/dist/react/charts/create-chart.js +2 -1
  14. package/dist/react/charts/create-chart.js.map +1 -1
  15. package/dist/react/charts/heatmap/index.d.ts +2 -2
  16. package/dist/react/charts/line/index.d.ts +2 -2
  17. package/dist/react/charts/normalize.d.ts +1 -1
  18. package/dist/react/charts/normalize.js +1 -1
  19. package/dist/react/charts/normalize.js.map +1 -1
  20. package/dist/react/charts/pie/index.d.ts +3 -3
  21. package/dist/react/charts/radar/index.d.ts +2 -2
  22. package/dist/react/charts/scatter/index.d.ts +2 -2
  23. package/dist/react/charts/theme.js.map +1 -1
  24. package/dist/react/charts/types.d.ts +5 -0
  25. package/dist/react/charts/types.d.ts.map +1 -1
  26. package/dist/react/charts/types.js.map +1 -1
  27. package/dist/react/charts/utils.js.map +1 -1
  28. package/dist/react/charts/wrapper.d.ts +4 -2
  29. package/dist/react/charts/wrapper.d.ts.map +1 -1
  30. package/dist/react/charts/wrapper.js +4 -2
  31. package/dist/react/charts/wrapper.js.map +1 -1
  32. package/dist/react/hooks/types.d.ts +2 -0
  33. package/dist/react/hooks/types.d.ts.map +1 -1
  34. package/dist/react/hooks/use-analytics-query.js +9 -3
  35. package/dist/react/hooks/use-analytics-query.js.map +1 -1
  36. package/dist/react/hooks/use-chart-data.d.ts +2 -0
  37. package/dist/react/hooks/use-chart-data.d.ts.map +1 -1
  38. package/dist/react/hooks/use-chart-data.js +3 -2
  39. package/dist/react/hooks/use-chart-data.js.map +1 -1
  40. package/dist/react/hooks/use-mobile.js +3 -3
  41. package/dist/react/hooks/use-mobile.js.map +1 -1
  42. package/dist/react/index.d.ts +3 -1
  43. package/dist/react/index.js +3 -1
  44. package/dist/react/lib/utils.d.ts +7 -0
  45. package/dist/react/lib/utils.d.ts.map +1 -0
  46. package/dist/react/portal-container-context.d.ts +48 -0
  47. package/dist/react/portal-container-context.d.ts.map +1 -0
  48. package/dist/react/portal-container-context.js +51 -0
  49. package/dist/react/portal-container-context.js.map +1 -0
  50. package/dist/react/table/data-table.d.ts +2 -2
  51. package/dist/react/table/data-table.d.ts.map +1 -1
  52. package/dist/react/table/table-wrapper.js +3 -2
  53. package/dist/react/table/table-wrapper.js.map +1 -1
  54. package/dist/react/table/types.d.ts.map +1 -1
  55. package/dist/react/ui/accordion.d.ts +6 -6
  56. package/dist/react/ui/accordion.d.ts.map +1 -1
  57. package/dist/react/ui/alert-dialog.d.ts +14 -13
  58. package/dist/react/ui/alert-dialog.d.ts.map +1 -1
  59. package/dist/react/ui/alert-dialog.js +3 -1
  60. package/dist/react/ui/alert-dialog.js.map +1 -1
  61. package/dist/react/ui/alert.d.ts +5 -5
  62. package/dist/react/ui/alert.d.ts.map +1 -1
  63. package/dist/react/ui/aspect-ratio.d.ts +2 -2
  64. package/dist/react/ui/avatar.d.ts +5 -5
  65. package/dist/react/ui/avatar.d.ts.map +1 -1
  66. package/dist/react/ui/badge.d.ts +6 -6
  67. package/dist/react/ui/badge.d.ts.map +1 -1
  68. package/dist/react/ui/breadcrumb.d.ts +10 -10
  69. package/dist/react/ui/breadcrumb.d.ts.map +1 -1
  70. package/dist/react/ui/button-group.d.ts +6 -6
  71. package/dist/react/ui/button.d.ts +6 -6
  72. package/dist/react/ui/button.d.ts.map +1 -1
  73. package/dist/react/ui/calendar.d.ts +6 -6
  74. package/dist/react/ui/calendar.d.ts.map +1 -1
  75. package/dist/react/ui/calendar.js +3 -3
  76. package/dist/react/ui/calendar.js.map +1 -1
  77. package/dist/react/ui/card.d.ts +9 -9
  78. package/dist/react/ui/card.d.ts.map +1 -1
  79. package/dist/react/ui/carousel.d.ts +7 -7
  80. package/dist/react/ui/carousel.d.ts.map +1 -1
  81. package/dist/react/ui/carousel.js +11 -11
  82. package/dist/react/ui/carousel.js.map +1 -1
  83. package/dist/react/ui/chart.d.ts +52 -16
  84. package/dist/react/ui/chart.d.ts.map +1 -1
  85. package/dist/react/ui/chart.js +23 -7
  86. package/dist/react/ui/chart.js.map +1 -1
  87. package/dist/react/ui/checkbox.d.ts +3 -3
  88. package/dist/react/ui/checkbox.d.ts.map +1 -1
  89. package/dist/react/ui/checkbox.js +1 -1
  90. package/dist/react/ui/checkbox.js.map +1 -1
  91. package/dist/react/ui/collapsible.d.ts +4 -4
  92. package/dist/react/ui/command.d.ts +12 -12
  93. package/dist/react/ui/command.d.ts.map +1 -1
  94. package/dist/react/ui/context-menu.d.ts +21 -20
  95. package/dist/react/ui/context-menu.d.ts.map +1 -1
  96. package/dist/react/ui/context-menu.js +11 -6
  97. package/dist/react/ui/context-menu.js.map +1 -1
  98. package/dist/react/ui/dialog.d.ts +14 -13
  99. package/dist/react/ui/dialog.d.ts.map +1 -1
  100. package/dist/react/ui/dialog.js +3 -1
  101. package/dist/react/ui/dialog.js.map +1 -1
  102. package/dist/react/ui/drawer.d.ts +13 -12
  103. package/dist/react/ui/drawer.d.ts.map +1 -1
  104. package/dist/react/ui/drawer.js +3 -1
  105. package/dist/react/ui/drawer.js.map +1 -1
  106. package/dist/react/ui/dropdown-menu.d.ts +21 -20
  107. package/dist/react/ui/dropdown-menu.d.ts.map +1 -1
  108. package/dist/react/ui/dropdown-menu.js +12 -7
  109. package/dist/react/ui/dropdown-menu.js.map +1 -1
  110. package/dist/react/ui/empty.d.ts +7 -7
  111. package/dist/react/ui/field.d.ts +11 -11
  112. package/dist/react/ui/form.d.ts +9 -9
  113. package/dist/react/ui/form.d.ts.map +1 -1
  114. package/dist/react/ui/form.js +6 -6
  115. package/dist/react/ui/form.js.map +1 -1
  116. package/dist/react/ui/hover-card.d.ts +5 -5
  117. package/dist/react/ui/hover-card.d.ts.map +1 -1
  118. package/dist/react/ui/hover-card.js +2 -0
  119. package/dist/react/ui/hover-card.js.map +1 -1
  120. package/dist/react/ui/input-group.d.ts +11 -11
  121. package/dist/react/ui/input-group.d.ts.map +1 -1
  122. package/dist/react/ui/input-otp.d.ts +8 -8
  123. package/dist/react/ui/input-otp.d.ts.map +1 -1
  124. package/dist/react/ui/input-otp.js +2 -2
  125. package/dist/react/ui/input-otp.js.map +1 -1
  126. package/dist/react/ui/input.d.ts +3 -3
  127. package/dist/react/ui/input.d.ts.map +1 -1
  128. package/dist/react/ui/item.d.ts +16 -16
  129. package/dist/react/ui/item.d.ts.map +1 -1
  130. package/dist/react/ui/kbd.d.ts +3 -3
  131. package/dist/react/ui/label.d.ts +3 -3
  132. package/dist/react/ui/label.d.ts.map +1 -1
  133. package/dist/react/ui/menubar.d.ts +22 -21
  134. package/dist/react/ui/menubar.d.ts.map +1 -1
  135. package/dist/react/ui/menubar.js +3 -1
  136. package/dist/react/ui/menubar.js.map +1 -1
  137. package/dist/react/ui/navigation-menu.d.ts +11 -11
  138. package/dist/react/ui/navigation-menu.d.ts.map +1 -1
  139. package/dist/react/ui/pagination.d.ts +10 -10
  140. package/dist/react/ui/pagination.d.ts.map +1 -1
  141. package/dist/react/ui/popover.d.ts +6 -6
  142. package/dist/react/ui/popover.d.ts.map +1 -1
  143. package/dist/react/ui/popover.js +11 -7
  144. package/dist/react/ui/popover.js.map +1 -1
  145. package/dist/react/ui/progress.d.ts +3 -3
  146. package/dist/react/ui/progress.d.ts.map +1 -1
  147. package/dist/react/ui/radio-group.d.ts +4 -4
  148. package/dist/react/ui/radio-group.d.ts.map +1 -1
  149. package/dist/react/ui/resizable.d.ts +6 -6
  150. package/dist/react/ui/resizable.d.ts.map +1 -1
  151. package/dist/react/ui/scroll-area.d.ts +4 -4
  152. package/dist/react/ui/scroll-area.d.ts.map +1 -1
  153. package/dist/react/ui/select.d.ts +13 -13
  154. package/dist/react/ui/select.d.ts.map +1 -1
  155. package/dist/react/ui/select.js +19 -15
  156. package/dist/react/ui/select.js.map +1 -1
  157. package/dist/react/ui/separator.d.ts +3 -3
  158. package/dist/react/ui/separator.d.ts.map +1 -1
  159. package/dist/react/ui/sheet.d.ts +11 -11
  160. package/dist/react/ui/sheet.d.ts.map +1 -1
  161. package/dist/react/ui/sheet.js +3 -1
  162. package/dist/react/ui/sheet.js.map +1 -1
  163. package/dist/react/ui/sidebar.d.ts +34 -34
  164. package/dist/react/ui/sidebar.d.ts.map +1 -1
  165. package/dist/react/ui/sidebar.js +10 -10
  166. package/dist/react/ui/sidebar.js.map +1 -1
  167. package/dist/react/ui/skeleton.d.ts +2 -2
  168. package/dist/react/ui/slider.d.ts +3 -3
  169. package/dist/react/ui/slider.d.ts.map +1 -1
  170. package/dist/react/ui/slider.js +2 -2
  171. package/dist/react/ui/slider.js.map +1 -1
  172. package/dist/react/ui/sonner.d.ts +2 -2
  173. package/dist/react/ui/spinner.d.ts +2 -2
  174. package/dist/react/ui/switch.d.ts +3 -3
  175. package/dist/react/ui/switch.d.ts.map +1 -1
  176. package/dist/react/ui/table.d.ts +10 -10
  177. package/dist/react/ui/table.d.ts.map +1 -1
  178. package/dist/react/ui/tabs.d.ts +6 -6
  179. package/dist/react/ui/tabs.d.ts.map +1 -1
  180. package/dist/react/ui/textarea.d.ts +3 -3
  181. package/dist/react/ui/textarea.d.ts.map +1 -1
  182. package/dist/react/ui/toggle-group.d.ts +5 -5
  183. package/dist/react/ui/toggle-group.d.ts.map +1 -1
  184. package/dist/react/ui/toggle-group.js +3 -3
  185. package/dist/react/ui/toggle-group.js.map +1 -1
  186. package/dist/react/ui/toggle.d.ts +3 -3
  187. package/dist/react/ui/toggle.d.ts.map +1 -1
  188. package/dist/react/ui/tooltip.d.ts +6 -6
  189. package/dist/react/ui/tooltip.d.ts.map +1 -1
  190. package/dist/react/ui/tooltip.js +11 -7
  191. package/dist/react/ui/tooltip.js.map +1 -1
  192. package/dist/shared/src/sql/helpers.js.map +1 -1
  193. package/llms.txt +89 -12
  194. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.js","names":["dateValue: string","timestampValue: string","numValue: string","stringValue: string","booleanValue: string","hexValue: string"],"sources":["../../../../../shared/src/sql/helpers.ts"],"sourcesContent":["import type {\n SQLBinaryMarker,\n SQLBooleanMarker,\n SQLDateMarker,\n SQLNumberMarker,\n SQLStringMarker,\n SQLTimestampMarker,\n SQLTypeMarker,\n} from \"./types\";\n\n/**\n * SQL helper namespace\n */\nexport const sql = {\n /**\n * Creates a DATE type parameter\n * Accepts Date objects or ISO date strings (YYYY-MM-DD format)\n * @param value - Date object or ISO date string\n * @returns Marker object for DATE type parameter\n * @example\n * ```typescript\n * const params = { startDate: sql.date(new Date(\"2024-01-01\")) };\n * params = { startDate: \"2024-01-01\" }\n * ```\n * @example\n * ```typescript\n * const params = { startDate: sql.date(\"2024-01-01\") };\n * params = { startDate: \"2024-01-01\" }\n * ```\n */\n date(value: Date | string): SQLDateMarker {\n let dateValue: string = \"\";\n\n // check if value is a Date object\n if (value instanceof Date) {\n dateValue = value.toISOString().split(\"T\")[0];\n }\n // check if value is a string\n else if (typeof value === \"string\") {\n // validate format\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(value)) {\n throw new Error(\n `sql.date() expects Date or ISO date string (YYYY-MM-DD format), got: ${value}`,\n );\n }\n dateValue = value;\n }\n // if value is not a Date object or string, throw an error\n else {\n throw new Error(\n `sql.date() expects Date or ISO date string (YYYY-MM-DD format), got: ${typeof value}`,\n );\n }\n\n return {\n __sql_type: \"DATE\",\n value: dateValue,\n };\n },\n\n /**\n * Creates a TIMESTAMP type parameter\n * Accepts Date objects, ISO timestamp strings, or Unix timestamp numbers\n * @param value - Date object, ISO timestamp string, or Unix timestamp number\n * @returns Marker object for TIMESTAMP type parameter\n * @example\n * ```typescript\n * const params = { createdTime: sql.timestamp(new Date(\"2024-01-01T12:00:00Z\")) };\n * params = { createdTime: \"2024-01-01T12:00:00Z\" }\n * ```\n * @example\n * ```typescript\n * const params = { createdTime: sql.timestamp(\"2024-01-01T12:00:00Z\") };\n * params = { createdTime: \"2024-01-01T12:00:00Z\" }\n * ```\n * @example\n * ```typescript\n * const params = { createdTime: sql.timestamp(1704110400000) };\n * params = { createdTime: \"2024-01-01T12:00:00Z\" }\n * ```\n */\n timestamp(value: Date | string | number): SQLTimestampMarker {\n let timestampValue: string = \"\";\n\n if (value instanceof Date) {\n timestampValue = value.toISOString().replace(/\\.000(Z|[+-])/, \"$1\");\n } else if (typeof value === \"string\") {\n const isoRegex =\n /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,9})?(Z|[+-]\\d{2}:\\d{2})?$/;\n if (!isoRegex.test(value)) {\n throw new Error(\n `sql.timestamp() expects ISO timestamp string (YYYY-MM-DDTHH:MM:SS.mmmZ or YYYY-MM-DDTHH:MM:SS.mmm+HH:MM), got: ${value}`,\n );\n }\n timestampValue = value;\n } else if (typeof value === \"number\") {\n const date = new Date(value > 1e12 ? value : value * 1000);\n timestampValue = date.toISOString().replace(/\\.000(Z|[+-])/, \"$1\");\n } else {\n throw new Error(\n `sql.timestamp() expects Date, ISO timestamp string, or Unix timestamp number, got: ${typeof value}`,\n );\n }\n\n return {\n __sql_type: \"TIMESTAMP\",\n value: timestampValue,\n };\n },\n\n /**\n * Creates a NUMERIC type parameter\n * Accepts numbers or numeric strings\n * @param value - Number or numeric string\n * @returns Marker object for NUMERIC type parameter\n * @example\n * ```typescript\n * const params = { userId: sql.number(123) };\n * params = { userId: \"123\" }\n * ```\n * @example\n * ```typescript\n * const params = { userId: sql.number(\"123\") };\n * params = { userId: \"123\" }\n * ```\n */\n number(value: number | string): SQLNumberMarker {\n let numValue: string = \"\";\n\n // check if value is a number\n if (typeof value === \"number\") {\n numValue = value.toString();\n }\n // check if value is a string\n else if (typeof value === \"string\") {\n if (value === \"\" || Number.isNaN(Number(value))) {\n throw new Error(\n `sql.number() expects number or numeric string, got: ${value === \"\" ? \"empty string\" : value}`,\n );\n }\n numValue = value;\n }\n // if value is not a number or string, throw an error\n else {\n throw new Error(\n `sql.number() expects number or numeric string, got: ${typeof value}`,\n );\n }\n\n return {\n __sql_type: \"NUMERIC\",\n value: numValue,\n };\n },\n\n /**\n * Creates a STRING type parameter\n * Accepts strings, numbers, or booleans\n * @param value - String, number, or boolean\n * @returns Marker object for STRING type parameter\n * @example\n * ```typescript\n * const params = { name: sql.string(\"John\") };\n * params = { name: \"John\" }\n * ```\n * @example\n * ```typescript\n * const params = { name: sql.string(123) };\n * params = { name: \"123\" }\n * ```\n * @example\n * ```typescript\n * const params = { name: sql.string(true) };\n * params = { name: \"true\" }\n * ```\n */\n string(value: string | number | boolean): SQLStringMarker {\n if (\n typeof value !== \"string\" &&\n typeof value !== \"number\" &&\n typeof value !== \"boolean\"\n ) {\n throw new Error(\n `sql.string() expects string or number or boolean, got: ${typeof value}`,\n );\n }\n\n let stringValue: string = \"\";\n\n if (typeof value === \"string\") {\n stringValue = value;\n } else {\n stringValue = value.toString();\n }\n\n return {\n __sql_type: \"STRING\",\n value: stringValue,\n };\n },\n\n /**\n * Create a BOOLEAN type parameter\n * Accepts booleans, strings, or numbers\n * @param value - Boolean, string, or number\n * @returns Marker object for BOOLEAN type parameter\n * @example\n * ```typescript\n * const params = { isActive: sql.boolean(true) };\n * params = { isActive: \"true\" }\n * ```\n * @example\n * ```typescript\n * const params = { isActive: sql.boolean(\"true\") };\n * params = { isActive: \"true\" }\n * ```\n * @example\n * ```typescript\n * const params = { isActive: sql.boolean(1) };\n * params = { isActive: \"true\" }\n * ```\n * @example\n * ```typescript\n * const params = { isActive: sql.boolean(\"false\") };\n * params = { isActive: \"false\" }\n * ```\n * @example\n * ```typescript\n * const params = { isActive: sql.boolean(0) };\n * params = { isActive: \"false\" }\n * ```\n * @returns\n */\n boolean(value: boolean | string | number): SQLBooleanMarker {\n if (\n typeof value !== \"boolean\" &&\n typeof value !== \"string\" &&\n typeof value !== \"number\"\n ) {\n throw new Error(\n `sql.boolean() expects boolean or string (true or false) or number (1 or 0), got: ${typeof value}`,\n );\n }\n\n let booleanValue: string = \"\";\n\n if (typeof value === \"boolean\") {\n booleanValue = value.toString();\n }\n // check if value is a number\n else if (typeof value === \"number\") {\n if (value !== 1 && value !== 0) {\n throw new Error(\n `sql.boolean() expects boolean or string (true or false) or number (1 or 0), got: ${value}`,\n );\n }\n booleanValue = value === 1 ? \"true\" : \"false\";\n }\n // check if value is a string\n else if (typeof value === \"string\") {\n if (value !== \"true\" && value !== \"false\") {\n throw new Error(\n `sql.boolean() expects boolean or string (true or false) or number (1 or 0), got: ${value}`,\n );\n }\n booleanValue = value;\n }\n\n return {\n __sql_type: \"BOOLEAN\",\n value: booleanValue,\n };\n },\n\n /**\n * Creates a BINARY parameter as hex-encoded STRING\n * Accepts Uint8Array, ArrayBuffer, or hex string\n * Note: Databricks SQL Warehouse doesn't support BINARY as parameter type,\n * so this helper returns a STRING with hex encoding. Use UNHEX(:param) in your SQL.\n * @param value - Uint8Array, ArrayBuffer, or hex string\n * @returns Marker object with STRING type and hex-encoded value\n * @example\n * ```typescript\n * // From Uint8Array:\n * const params = { data: sql.binary(new Uint8Array([0x53, 0x70, 0x61, 0x72, 0x6b])) };\n * // Returns: { __sql_type: \"STRING\", value: \"537061726B\" }\n * // SQL: SELECT UNHEX(:data) as binary_value\n * ```\n * @example\n * ```typescript\n * // From hex string:\n * const params = { data: sql.binary(\"537061726B\") };\n * // Returns: { __sql_type: \"STRING\", value: \"537061726B\" }\n * ```\n */\n binary(value: Uint8Array | ArrayBuffer | string): SQLBinaryMarker {\n let hexValue: string = \"\";\n\n if (value instanceof Uint8Array) {\n // if value is a Uint8Array, convert it to a hex string\n hexValue = Array.from(value)\n .map((b) => b.toString(16).padStart(2, \"0\").toUpperCase())\n .join(\"\");\n } else if (value instanceof ArrayBuffer) {\n // if value is an ArrayBuffer, convert it to a hex string\n hexValue = Array.from(new Uint8Array(value))\n .map((b) => b.toString(16).padStart(2, \"0\").toUpperCase())\n .join(\"\");\n } else if (typeof value === \"string\") {\n // validate hex string\n if (!/^[0-9A-Fa-f]*$/.test(value)) {\n throw new Error(\n `sql.binary() expects Uint8Array, ArrayBuffer, or hex string, got invalid hex: ${value}`,\n );\n }\n hexValue = value.toUpperCase();\n } else {\n throw new Error(\n `sql.binary() expects Uint8Array, ArrayBuffer, or hex string, got: ${typeof value}`,\n );\n }\n\n return {\n __sql_type: \"STRING\",\n value: hexValue,\n };\n },\n};\n\n/**\n * Type guard to check if a value is a SQL type marker\n * @param value - Value to check\n * @returns True if the value is a SQL type marker, false otherwise\n * @example\n * ```typescript\n * const value = {\n * __sql_type: \"DATE\",\n * value: \"2024-01-01\",\n * };\n * const isSQLTypeMarker = isSQLTypeMarker(value);\n * console.log(isSQLTypeMarker); // true\n * ```\n */\nexport function isSQLTypeMarker(value: any): value is SQLTypeMarker {\n return (\n value !== null &&\n typeof value === \"object\" &&\n \"__sql_type\" in value &&\n \"value\" in value &&\n typeof value.__sql_type === \"string\" &&\n typeof value.value === \"string\"\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"helpers.js","names":[],"sources":["../../../../../shared/src/sql/helpers.ts"],"sourcesContent":["import type {\n SQLBinaryMarker,\n SQLBooleanMarker,\n SQLDateMarker,\n SQLNumberMarker,\n SQLStringMarker,\n SQLTimestampMarker,\n SQLTypeMarker,\n} from \"./types\";\n\n/**\n * SQL helper namespace\n */\nexport const sql = {\n /**\n * Creates a DATE type parameter\n * Accepts Date objects or ISO date strings (YYYY-MM-DD format)\n * @param value - Date object or ISO date string\n * @returns Marker object for DATE type parameter\n * @example\n * ```typescript\n * const params = { startDate: sql.date(new Date(\"2024-01-01\")) };\n * params = { startDate: \"2024-01-01\" }\n * ```\n * @example\n * ```typescript\n * const params = { startDate: sql.date(\"2024-01-01\") };\n * params = { startDate: \"2024-01-01\" }\n * ```\n */\n date(value: Date | string): SQLDateMarker {\n let dateValue: string = \"\";\n\n // check if value is a Date object\n if (value instanceof Date) {\n dateValue = value.toISOString().split(\"T\")[0];\n }\n // check if value is a string\n else if (typeof value === \"string\") {\n // validate format\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(value)) {\n throw new Error(\n `sql.date() expects Date or ISO date string (YYYY-MM-DD format), got: ${value}`,\n );\n }\n dateValue = value;\n }\n // if value is not a Date object or string, throw an error\n else {\n throw new Error(\n `sql.date() expects Date or ISO date string (YYYY-MM-DD format), got: ${typeof value}`,\n );\n }\n\n return {\n __sql_type: \"DATE\",\n value: dateValue,\n };\n },\n\n /**\n * Creates a TIMESTAMP type parameter\n * Accepts Date objects, ISO timestamp strings, or Unix timestamp numbers\n * @param value - Date object, ISO timestamp string, or Unix timestamp number\n * @returns Marker object for TIMESTAMP type parameter\n * @example\n * ```typescript\n * const params = { createdTime: sql.timestamp(new Date(\"2024-01-01T12:00:00Z\")) };\n * params = { createdTime: \"2024-01-01T12:00:00Z\" }\n * ```\n * @example\n * ```typescript\n * const params = { createdTime: sql.timestamp(\"2024-01-01T12:00:00Z\") };\n * params = { createdTime: \"2024-01-01T12:00:00Z\" }\n * ```\n * @example\n * ```typescript\n * const params = { createdTime: sql.timestamp(1704110400000) };\n * params = { createdTime: \"2024-01-01T12:00:00Z\" }\n * ```\n */\n timestamp(value: Date | string | number): SQLTimestampMarker {\n let timestampValue: string = \"\";\n\n if (value instanceof Date) {\n timestampValue = value.toISOString().replace(/\\.000(Z|[+-])/, \"$1\");\n } else if (typeof value === \"string\") {\n const isoRegex =\n /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,9})?(Z|[+-]\\d{2}:\\d{2})?$/;\n if (!isoRegex.test(value)) {\n throw new Error(\n `sql.timestamp() expects ISO timestamp string (YYYY-MM-DDTHH:MM:SS.mmmZ or YYYY-MM-DDTHH:MM:SS.mmm+HH:MM), got: ${value}`,\n );\n }\n timestampValue = value;\n } else if (typeof value === \"number\") {\n const date = new Date(value > 1e12 ? value : value * 1000);\n timestampValue = date.toISOString().replace(/\\.000(Z|[+-])/, \"$1\");\n } else {\n throw new Error(\n `sql.timestamp() expects Date, ISO timestamp string, or Unix timestamp number, got: ${typeof value}`,\n );\n }\n\n return {\n __sql_type: \"TIMESTAMP\",\n value: timestampValue,\n };\n },\n\n /**\n * Creates a NUMERIC type parameter\n * Accepts numbers or numeric strings\n * @param value - Number or numeric string\n * @returns Marker object for NUMERIC type parameter\n * @example\n * ```typescript\n * const params = { userId: sql.number(123) };\n * params = { userId: \"123\" }\n * ```\n * @example\n * ```typescript\n * const params = { userId: sql.number(\"123\") };\n * params = { userId: \"123\" }\n * ```\n */\n number(value: number | string): SQLNumberMarker {\n let numValue: string = \"\";\n\n // check if value is a number\n if (typeof value === \"number\") {\n numValue = value.toString();\n }\n // check if value is a string\n else if (typeof value === \"string\") {\n if (value === \"\" || Number.isNaN(Number(value))) {\n throw new Error(\n `sql.number() expects number or numeric string, got: ${value === \"\" ? \"empty string\" : value}`,\n );\n }\n numValue = value;\n }\n // if value is not a number or string, throw an error\n else {\n throw new Error(\n `sql.number() expects number or numeric string, got: ${typeof value}`,\n );\n }\n\n return {\n __sql_type: \"NUMERIC\",\n value: numValue,\n };\n },\n\n /**\n * Creates a STRING type parameter\n * Accepts strings, numbers, or booleans\n * @param value - String, number, or boolean\n * @returns Marker object for STRING type parameter\n * @example\n * ```typescript\n * const params = { name: sql.string(\"John\") };\n * params = { name: \"John\" }\n * ```\n * @example\n * ```typescript\n * const params = { name: sql.string(123) };\n * params = { name: \"123\" }\n * ```\n * @example\n * ```typescript\n * const params = { name: sql.string(true) };\n * params = { name: \"true\" }\n * ```\n */\n string(value: string | number | boolean): SQLStringMarker {\n if (\n typeof value !== \"string\" &&\n typeof value !== \"number\" &&\n typeof value !== \"boolean\"\n ) {\n throw new Error(\n `sql.string() expects string or number or boolean, got: ${typeof value}`,\n );\n }\n\n let stringValue: string = \"\";\n\n if (typeof value === \"string\") {\n stringValue = value;\n } else {\n stringValue = value.toString();\n }\n\n return {\n __sql_type: \"STRING\",\n value: stringValue,\n };\n },\n\n /**\n * Create a BOOLEAN type parameter\n * Accepts booleans, strings, or numbers\n * @param value - Boolean, string, or number\n * @returns Marker object for BOOLEAN type parameter\n * @example\n * ```typescript\n * const params = { isActive: sql.boolean(true) };\n * params = { isActive: \"true\" }\n * ```\n * @example\n * ```typescript\n * const params = { isActive: sql.boolean(\"true\") };\n * params = { isActive: \"true\" }\n * ```\n * @example\n * ```typescript\n * const params = { isActive: sql.boolean(1) };\n * params = { isActive: \"true\" }\n * ```\n * @example\n * ```typescript\n * const params = { isActive: sql.boolean(\"false\") };\n * params = { isActive: \"false\" }\n * ```\n * @example\n * ```typescript\n * const params = { isActive: sql.boolean(0) };\n * params = { isActive: \"false\" }\n * ```\n * @returns\n */\n boolean(value: boolean | string | number): SQLBooleanMarker {\n if (\n typeof value !== \"boolean\" &&\n typeof value !== \"string\" &&\n typeof value !== \"number\"\n ) {\n throw new Error(\n `sql.boolean() expects boolean or string (true or false) or number (1 or 0), got: ${typeof value}`,\n );\n }\n\n let booleanValue: string = \"\";\n\n if (typeof value === \"boolean\") {\n booleanValue = value.toString();\n }\n // check if value is a number\n else if (typeof value === \"number\") {\n if (value !== 1 && value !== 0) {\n throw new Error(\n `sql.boolean() expects boolean or string (true or false) or number (1 or 0), got: ${value}`,\n );\n }\n booleanValue = value === 1 ? \"true\" : \"false\";\n }\n // check if value is a string\n else if (typeof value === \"string\") {\n if (value !== \"true\" && value !== \"false\") {\n throw new Error(\n `sql.boolean() expects boolean or string (true or false) or number (1 or 0), got: ${value}`,\n );\n }\n booleanValue = value;\n }\n\n return {\n __sql_type: \"BOOLEAN\",\n value: booleanValue,\n };\n },\n\n /**\n * Creates a BINARY parameter as hex-encoded STRING\n * Accepts Uint8Array, ArrayBuffer, or hex string\n * Note: Databricks SQL Warehouse doesn't support BINARY as parameter type,\n * so this helper returns a STRING with hex encoding. Use UNHEX(:param) in your SQL.\n * @param value - Uint8Array, ArrayBuffer, or hex string\n * @returns Marker object with STRING type and hex-encoded value\n * @example\n * ```typescript\n * // From Uint8Array:\n * const params = { data: sql.binary(new Uint8Array([0x53, 0x70, 0x61, 0x72, 0x6b])) };\n * // Returns: { __sql_type: \"STRING\", value: \"537061726B\" }\n * // SQL: SELECT UNHEX(:data) as binary_value\n * ```\n * @example\n * ```typescript\n * // From hex string:\n * const params = { data: sql.binary(\"537061726B\") };\n * // Returns: { __sql_type: \"STRING\", value: \"537061726B\" }\n * ```\n */\n binary(value: Uint8Array | ArrayBuffer | string): SQLBinaryMarker {\n let hexValue: string = \"\";\n\n if (value instanceof Uint8Array) {\n // if value is a Uint8Array, convert it to a hex string\n hexValue = Array.from(value)\n .map((b) => b.toString(16).padStart(2, \"0\").toUpperCase())\n .join(\"\");\n } else if (value instanceof ArrayBuffer) {\n // if value is an ArrayBuffer, convert it to a hex string\n hexValue = Array.from(new Uint8Array(value))\n .map((b) => b.toString(16).padStart(2, \"0\").toUpperCase())\n .join(\"\");\n } else if (typeof value === \"string\") {\n // validate hex string\n if (!/^[0-9A-Fa-f]*$/.test(value)) {\n throw new Error(\n `sql.binary() expects Uint8Array, ArrayBuffer, or hex string, got invalid hex: ${value}`,\n );\n }\n hexValue = value.toUpperCase();\n } else {\n throw new Error(\n `sql.binary() expects Uint8Array, ArrayBuffer, or hex string, got: ${typeof value}`,\n );\n }\n\n return {\n __sql_type: \"STRING\",\n value: hexValue,\n };\n },\n};\n\n/**\n * Type guard to check if a value is a SQL type marker\n * @param value - Value to check\n * @returns True if the value is a SQL type marker, false otherwise\n * @example\n * ```typescript\n * const value = {\n * __sql_type: \"DATE\",\n * value: \"2024-01-01\",\n * };\n * const isSQLTypeMarker = isSQLTypeMarker(value);\n * console.log(isSQLTypeMarker); // true\n * ```\n */\nexport function isSQLTypeMarker(value: any): value is SQLTypeMarker {\n return (\n value !== null &&\n typeof value === \"object\" &&\n \"__sql_type\" in value &&\n \"value\" in value &&\n typeof value.__sql_type === \"string\" &&\n typeof value.value === \"string\"\n );\n}\n"],"mappings":"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"}
package/llms.txt CHANGED
@@ -440,23 +440,49 @@ Formats:
440
440
  - `format: "JSON"` (default) returns JSON rows
441
441
  - `format: "ARROW"` returns an Arrow “statement_id” payload over SSE, then the client fetches binary Arrow from `/api/analytics/arrow-result/:jobId`
442
442
 
443
- ### Request context (`getRequestContext()`)
443
+ ### Execution context and `asUser(req)`
444
444
 
445
- If a plugin sets `requiresDatabricksClient = true`, AppKit adds middleware that provides request context.
445
+ AppKit manages Databricks authentication via two contexts:
446
446
 
447
- Headers used:
447
+ - **ServiceContext** (singleton): Initialized at app startup with service principal credentials
448
+ - **ExecutionContext**: Determined at runtime - either service principal or user context
449
+
450
+ **Headers used for user context:**
448
451
 
449
452
  - `x-forwarded-user`: required in production; identifies the user
450
- - `x-forwarded-access-token`: optional; enables **user token passthrough** if `DATABRICKS_HOST` is set
453
+ - `x-forwarded-access-token`: required for user token passthrough
454
+
455
+ **Using `asUser(req)` for user-scoped operations:**
456
+
457
+ The `asUser(req)` pattern allows plugins to execute operations using the requesting user's credentials:
458
+
459
+ ```ts
460
+ // In a custom plugin route handler
461
+ router.post("/users/me/data", async (req, res) => {
462
+ // Execute as the user (uses their Databricks permissions)
463
+ const result = await this.asUser(req).query("SELECT ...");
464
+ res.json(result);
465
+ });
466
+
467
+ // Service principal execution (default)
468
+ router.post("/system/data", async (req, res) => {
469
+ const result = await this.query("SELECT ...");
470
+ res.json(result);
471
+ });
472
+ ```
473
+
474
+ **Context helper functions (exported from `@databricks/appkit`):**
451
475
 
452
- Context fields (real behavior):
476
+ - `getExecutionContext()`: Returns current context (user or service)
477
+ - `getCurrentUserId()`: Returns user ID in user context, service user ID otherwise
478
+ - `getWorkspaceClient()`: Returns the appropriate WorkspaceClient for current context
479
+ - `getWarehouseId()`: `Promise<string>` (from `DATABRICKS_WAREHOUSE_ID` or auto-selected in dev)
480
+ - `getWorkspaceId()`: `Promise<string>` (from `DATABRICKS_WORKSPACE_ID` or fetched)
481
+ - `isInUserContext()`: Returns `true` if currently executing in user context
453
482
 
454
- - `userId`: derived from `x-forwarded-user` (in development it falls back to `serviceUserId`)
455
- - `serviceUserId`: service principal/user ID
456
- - `warehouseId`: `Promise<string>` (from `DATABRICKS_WAREHOUSE_ID`, or auto-selected in development)
457
- - `workspaceId`: `Promise<string>` (from `DATABRICKS_WORKSPACE_ID` or fetched)
458
- - `userDatabricksClient`: present only when passthrough is available (or in dev it equals service client)
459
- - `serviceDatabricksClient`: always present
483
+ **Development mode behavior:**
484
+
485
+ In local development (`NODE_ENV=development`), if `asUser(req)` is called without a user token, it logs a warning and falls back to the service principal.
460
486
 
461
487
  ### Custom plugins (backend)
462
488
 
@@ -469,7 +495,6 @@ import type express from "express";
469
495
  class MyPlugin extends Plugin {
470
496
  name = "my-plugin";
471
497
  envVars = []; // list required env vars here
472
- requiresDatabricksClient = false; // set true if you need getRequestContext()
473
498
 
474
499
  injectRoutes(router: express.Router) {
475
500
  this.route(router, {
@@ -643,6 +668,56 @@ export function SpendChart() {
643
668
  }
644
669
  ```
645
670
 
671
+ **Chart props reference (important):**
672
+
673
+ Charts are **self-contained ECharts components**. Configure via props, NOT children:
674
+
675
+ ```tsx
676
+ // ✅ Correct: use props for customization
677
+ <BarChart
678
+ queryKey="sales_by_region"
679
+ parameters={{}}
680
+ xKey="region" // X-axis field
681
+ yKey={["revenue", "expenses"]} // Y-axis field(s) - string or string[]
682
+ colors={['#40d1f5', '#4462c9']} // Custom colors
683
+ stacked // Stack bars (BarChart, AreaChart)
684
+ orientation="horizontal" // "vertical" (default) | "horizontal"
685
+ showLegend // Show legend
686
+ height={400} // Height in pixels (default: 300)
687
+ />
688
+
689
+ <LineChart
690
+ queryKey="trend_data"
691
+ parameters={{}}
692
+ xKey="date"
693
+ yKey="value"
694
+ smooth // Smooth curves (default: true)
695
+ showSymbol={false} // Hide data point markers
696
+ />
697
+ ```
698
+
699
+ **❌ CRITICAL: Charts do NOT accept Recharts children**
700
+
701
+ ```tsx
702
+ // ❌ WRONG - AppKit charts are NOT Recharts wrappers
703
+ import { BarChart } from "@databricks/appkit-ui/react";
704
+ import { Bar, XAxis, YAxis, CartesianGrid } from "recharts";
705
+
706
+ <BarChart queryKey="data" parameters={{}}>
707
+ <CartesianGrid /> // ❌ This will cause TypeScript errors
708
+ <XAxis dataKey="x" /> // ❌ Not supported
709
+ <Bar dataKey="y" /> // ❌ Not supported
710
+ </BarChart>
711
+
712
+ // ✅ CORRECT - use props instead
713
+ <BarChart
714
+ queryKey="data"
715
+ parameters={{}}
716
+ xKey="x"
717
+ yKey="y"
718
+ />
719
+ ```
720
+
646
721
  ### SQL helpers (`sql.*`)
647
722
 
648
723
  Use these to build typed parameters (they return marker objects: `{ __sql_type, value }`):
@@ -1144,6 +1219,7 @@ env:
1144
1219
  - `useMemo` wraps parameters objects
1145
1220
  - Loading/error/empty states are explicit
1146
1221
  - Charts use `format="auto"` unless you have a reason to force `"json"`/`"arrow"`
1222
+ - Charts use props (`xKey`, `yKey`, `colors`) NOT children (they're ECharts-based, not Recharts)
1147
1223
  - If using tooltips: root is wrapped with `<TooltipProvider>`
1148
1224
 
1149
1225
  - **Never**
@@ -1151,4 +1227,5 @@ env:
1151
1227
  - Don't pass untyped raw params for annotated queries
1152
1228
  - Don't ignore `createApp()`'s promise
1153
1229
  - Don't invent UI components not listed in this file
1230
+ - Don't pass Recharts children (`<Bar>`, `<XAxis>`, etc.) to AppKit chart components
1154
1231
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@databricks/appkit-ui",
3
3
  "type": "module",
4
- "version": "0.1.4",
4
+ "version": "0.2.0",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/databricks/appkit.git"