queria 0.0.0 → 0.1.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 (85) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +57 -1
  3. package/dist/boot.d.ts +24 -0
  4. package/dist/boot.js +137 -0
  5. package/dist/boot.js.map +1 -0
  6. package/dist/client.d.ts +56 -0
  7. package/dist/client.js +194 -0
  8. package/dist/client.js.map +1 -0
  9. package/dist/elements/define.d.ts +1 -0
  10. package/dist/elements/define.js +4 -0
  11. package/dist/elements/define.js.map +1 -0
  12. package/dist/elements/index.d.ts +40 -0
  13. package/dist/elements/index.js +144 -0
  14. package/dist/elements/index.js.map +1 -0
  15. package/dist/index.d.ts +3 -0
  16. package/dist/index.js +4 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/react/Chart.d.ts +12 -0
  19. package/dist/react/Chart.js +42 -0
  20. package/dist/react/Chart.js.map +1 -0
  21. package/dist/react/DataMap.d.ts +12 -0
  22. package/dist/react/DataMap.js +44 -0
  23. package/dist/react/DataMap.js.map +1 -0
  24. package/dist/react/MapView.d.ts +13 -0
  25. package/dist/react/MapView.js +31 -0
  26. package/dist/react/MapView.js.map +1 -0
  27. package/dist/react/PoweredBy.d.ts +2 -0
  28. package/dist/react/PoweredBy.js +5 -0
  29. package/dist/react/PoweredBy.js.map +1 -0
  30. package/dist/react/index.d.ts +5 -0
  31. package/dist/react/index.js +6 -0
  32. package/dist/react/index.js.map +1 -0
  33. package/dist/react/query.d.ts +20 -0
  34. package/dist/react/query.js +50 -0
  35. package/dist/react/query.js.map +1 -0
  36. package/dist/render/attribution.d.ts +6 -0
  37. package/dist/render/attribution.js +17 -0
  38. package/dist/render/attribution.js.map +1 -0
  39. package/dist/render/chart.d.ts +27 -0
  40. package/dist/render/chart.js +50 -0
  41. package/dist/render/chart.js.map +1 -0
  42. package/dist/render/data-map.d.ts +61 -0
  43. package/dist/render/data-map.js +200 -0
  44. package/dist/render/data-map.js.map +1 -0
  45. package/dist/render/escape.d.ts +2 -0
  46. package/dist/render/escape.js +4 -0
  47. package/dist/render/escape.js.map +1 -0
  48. package/dist/render/index.d.ts +5 -0
  49. package/dist/render/index.js +6 -0
  50. package/dist/render/index.js.map +1 -0
  51. package/dist/render/map.d.ts +7 -0
  52. package/dist/render/map.js +9 -0
  53. package/dist/render/map.js.map +1 -0
  54. package/dist/render/poweredBy.d.ts +2 -0
  55. package/dist/render/poweredBy.js +5 -0
  56. package/dist/render/poweredBy.js.map +1 -0
  57. package/dist/sql.d.ts +10 -0
  58. package/dist/sql.js +13 -0
  59. package/dist/sql.js.map +1 -0
  60. package/package.json +93 -1
  61. package/src/boot.test.ts +65 -0
  62. package/src/boot.ts +141 -0
  63. package/src/client.test.ts +77 -0
  64. package/src/client.ts +247 -0
  65. package/src/elements/define.ts +4 -0
  66. package/src/elements/index.ts +151 -0
  67. package/src/index.ts +12 -0
  68. package/src/react/Chart.tsx +49 -0
  69. package/src/react/DataMap.tsx +52 -0
  70. package/src/react/MapView.tsx +45 -0
  71. package/src/react/PoweredBy.tsx +4 -0
  72. package/src/react/index.ts +5 -0
  73. package/src/react/query.tsx +64 -0
  74. package/src/render/attribution.test.ts +22 -0
  75. package/src/render/attribution.ts +21 -0
  76. package/src/render/chart.test.ts +23 -0
  77. package/src/render/chart.ts +80 -0
  78. package/src/render/data-map.test.ts +40 -0
  79. package/src/render/data-map.ts +230 -0
  80. package/src/render/escape.ts +4 -0
  81. package/src/render/index.ts +12 -0
  82. package/src/render/map.ts +18 -0
  83. package/src/render/poweredBy.ts +6 -0
  84. package/src/sql.test.ts +21 -0
  85. package/src/sql.ts +19 -0
@@ -0,0 +1,18 @@
1
+ import type { Map, MapOptions, StyleSpecification } from "maplibre-gl";
2
+
3
+ export type MapHandle = { map: Promise<Map>; destroy: () => void };
4
+
5
+ /** Create a MapLibre map in an element. maplibre-gl is loaded on first use; include its CSS in your page. */
6
+ export const mountMap = (
7
+ el: HTMLElement,
8
+ style: StyleSpecification | string,
9
+ options: Omit<MapOptions, "container" | "style"> = {},
10
+ ): MapHandle => {
11
+ const map = import("maplibre-gl").then(
12
+ ({ default: maplibregl }) => new maplibregl.Map({ container: el, style, ...options }),
13
+ );
14
+ const destroy = () => {
15
+ map.then((m) => m.remove(), console.error);
16
+ };
17
+ return { map, destroy };
18
+ };
@@ -0,0 +1,6 @@
1
+ const logo = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8373.1 2008.4"> <g transform="translate(0 127.1)"> <g fill="none" stroke="#7846BE" stroke-linecap="round" stroke-linejoin="round"> <circle cx="753.3" cy="753.3" r="604.3" stroke-width="297.9"/> <path d="M912.4 912.4 L1356.2 1356.2" stroke-width="291.7"/> <path d="M1560.4 1207.8 L1560.4 1560.4 L1207.8 1560.4" stroke-width="202.3"/> </g> <path fill="currentColor" d="M2665.5 1506.5Q2471.1 1506.5 2322.7 1415.4Q2174.2 1324.3 2091.2 1153.6Q2008.1 982.9 2008.1 745.9Q2008.1 508.6 2091.2 341.7Q2174.2 174.8 2322.7 87.4Q2471.1 0 2665.5 0Q2861.7 0 3009.3 88.3Q3156.8 176.6 3239.9 342.6Q3323 508.6 3323 745.9Q3323 982.9 3239.9 1153.6Q3156.8 1324.3 3009.3 1415.4Q2861.7 1506.5 2665.5 1506.5ZM2665.5 1245.1Q2767.5 1245.1 2841.7 1186.2Q2915.9 1127.3 2956.7 1014.8Q2997.6 902.4 2997.6 745.9Q2997.6 598.1 2956.7 492Q2915.9 385.9 2841.7 330Q2767.5 274 2665.5 274Q2563.8 274 2489.5 330Q2415.2 385.9 2375.2 492Q2335.2 598.1 2335.2 745.9Q2335.2 902.4 2375.2 1014.8Q2415.2 1127.3 2489.5 1186.2Q2563.8 1245.1 2665.5 1245.1ZM3142.5 1881.2Q2984.8 1881.2 2859.6 1827.7Q2734.4 1774.2 2646.5 1680.6Q2558.7 1587 2509.9 1468.9L2834.2 1435.8Q2861.8 1503.8 2915.7 1546.7Q2969.5 1589.7 3038.9 1608.7Q3108.4 1627.7 3178.2 1627.7Q3225.4 1627.7 3266.5 1620.2Q3307.6 1612.7 3340 1601.4L3397.6 1835.1Q3356.5 1855.1 3290.6 1868.2Q3224.7 1881.2 3142.5 1881.2Z M3906.6 1506.5Q3725.4 1506.5 3643.9 1387.1Q3562.3 1267.7 3562.3 1060.9V374.8H3880.1V1021.7Q3880.1 1141.5 3914.3 1188.1Q3948.6 1234.6 4022.2 1234.6Q4085 1234.6 4131.2 1205.2Q4177.3 1175.8 4226.2 1109.3V374.8H4544V1479.3H4284.8L4261.2 1324.1H4253.9Q4184.3 1407.1 4101.9 1456.8Q4019.5 1506.5 3906.6 1506.5Z M5330.3 1506.5Q5173.3 1506.5 5047.3 1437.6Q4921.4 1368.6 4847.4 1238.7Q4773.3 1108.8 4773.3 926.5Q4773.3 792.4 4816.5 685.6Q4859.7 578.8 4933.7 503Q5007.8 427.2 5101 387.4Q5194.2 347.6 5292.5 347.6Q5448.4 347.6 5552 416.4Q5655.7 485.1 5708 604.8Q5760.3 724.5 5760.3 877.2Q5760.3 920.7 5755.9 959.1Q5751.6 997.5 5745.9 1019.1H5081.1Q5095 1101.8 5135.3 1155.4Q5175.7 1208.9 5236.1 1235.7Q5296.5 1262.5 5372.5 1262.5Q5436.2 1262.5 5494.3 1244Q5552.3 1225.6 5612.8 1189.5L5719 1382.5Q5635.9 1440.4 5533 1473.4Q5430.1 1506.5 5330.3 1506.5ZM5075.9 808.2H5489.7Q5489.7 712 5444.3 651.8Q5399 591.6 5297.7 591.6Q5245.8 591.6 5199.5 615.4Q5153.2 639.2 5120.4 686.8Q5087.6 734.5 5075.9 808.2Z M5989.7 1479.3V374.8H6248.7L6272.6 568.6H6278.3Q6339.6 459 6423.6 403.3Q6507.5 347.6 6592.5 347.6Q6640.8 347.6 6670.4 354.2Q6700 360.7 6723.7 370.9L6671.2 644.5Q6640.6 636.5 6614.2 631.7Q6587.9 626.9 6551.4 626.9Q6489.8 626.9 6421.1 673.7Q6352.4 720.6 6307.5 834.9V1479.3Z M6870.3 1479.3V374.8H7188.1V1479.3ZM7029.4 208.6Q6947.6 208.6 6898.4 162.7Q6849.2 116.8 6849.2 39.5Q6849.2 -35.5 6898.4 -81.3Q6947.6 -127.1 7029.4 -127.1Q7109.3 -127.1 7159.5 -81.3Q7209.6 -35.5 7209.6 39.5Q7209.6 116.8 7159.5 162.7Q7109.3 208.6 7029.4 208.6Z M7758 1506.5Q7658.6 1506.5 7585 1462.3Q7511.4 1418.2 7471.2 1342.6Q7430.9 1267 7430.9 1174.4Q7430.9 998.7 7579.4 900.9Q7727.9 803.2 8055.4 767.5Q8052.3 718.2 8034.6 680.8Q8016.9 643.3 7978.6 622.7Q7940.4 602.1 7878 602.1Q7806.7 602.1 7734.4 629.5Q7662 656.8 7581.5 702.9L7469.6 492.9Q7539.5 450.3 7614.4 418.1Q7689.3 385.9 7770.6 366.8Q7851.8 347.6 7937.7 347.6Q8079.9 347.6 8176.4 402.3Q8272.8 457 8323 566.9Q8373.1 676.7 8373.1 843.3V1479.3H8114.1L8092.2 1365H8082.8Q8013.2 1426.1 7932.3 1466.3Q7851.3 1506.5 7758 1506.5ZM7864.9 1259Q7922 1259 7966.6 1233.3Q8011.1 1207.5 8055.4 1161.5V962.3Q7935 977.1 7863.9 1004.6Q7792.8 1032.1 7763 1068.7Q7733.2 1105.3 7733.2 1149.8Q7733.2 1206.5 7769.5 1232.8Q7805.8 1259 7864.9 1259Z"/> </g></svg>`;
2
+
3
+ /** Markup of a link that shows the app is built on Queria. */
4
+ export const poweredByHtml = (): string =>
5
+ '<a class="queria-powered" href="https://queria.io/" target="_blank" rel="noopener">Powered by ' +
6
+ `<span role="img" aria-label="Queria" style="display:inline-block;height:1em;width:4.2em;vertical-align:-0.15em">${logo}</span></a>`;
@@ -0,0 +1,21 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { datasetsIn, lit } from "./sql.js";
3
+
4
+ describe("datasetsIn", () => {
5
+ it("finds datasets of three-part names", () => {
6
+ expect(datasetsIn("SELECT * FROM e_stat.census.population p JOIN lg_code.main.cities c USING (code)")).toEqual([
7
+ "e_stat",
8
+ "lg_code",
9
+ ]);
10
+ });
11
+ it("ignores names inside string literals and two-part names", () => {
12
+ expect(datasetsIn("SELECT 'a.b.c' AS s, t.x FROM mlit.main.stations t")).toEqual(["mlit"]);
13
+ });
14
+ it("ignores comments and quoted identifiers", () => {
15
+ expect(datasetsIn('SELECT x AS "a.b.c" -- d.e.f\nFROM /* g.h.i */ mlit.main.stations')).toEqual(["mlit"]);
16
+ });
17
+ });
18
+
19
+ describe("lit", () => {
20
+ it("escapes quotes", () => expect(lit("O'Hare")).toBe("'O''Hare'"));
21
+ });
package/src/sql.ts ADDED
@@ -0,0 +1,19 @@
1
+ /** Quote a string as an SQL literal. */
2
+ export const lit = (s: string): string => `'${s.replaceAll("'", "''")}'`;
3
+
4
+ /** Blank out string literals, quoted identifiers and comments, scanning left to right. */
5
+ export const stripLiterals = (sql: string): string =>
6
+ sql.replace(/'(?:[^']|'')*'|"(?:[^"]|"")*"|--[^\n]*|\/\*[\s\S]*?\*\//g, (m) => (m.startsWith("'") ? "''" : " "));
7
+
8
+ /**
9
+ * Dataset names referenced in SQL. Tables are written as <dataset>.<schema>.<table>,
10
+ * so the first part of every three-part name outside string literals and comments is a dataset.
11
+ * A struct field read as alias.column.field also matches; the client skips names that are not datasets.
12
+ */
13
+ export const datasetsIn = (sql: string): string[] => [
14
+ ...new Set(
15
+ [...stripLiterals(sql).matchAll(/\b([a-z_][a-z0-9_]*)\.[a-z_][a-z0-9_]*\.[a-z_][a-z0-9_]*/gi)].map(
16
+ (m) => m[1].toLowerCase(),
17
+ ),
18
+ ),
19
+ ];