@health-samurai/react-components 0.0.0-alpha.18 → 0.0.0-alpha.20

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 (74) hide show
  1. package/LICENSE +21 -0
  2. package/dist/bundle.css +51 -33
  3. package/dist/src/components/code-editor/fhir-autocomplete.d.ts +70 -0
  4. package/dist/src/components/code-editor/fhir-autocomplete.d.ts.map +1 -0
  5. package/dist/src/components/code-editor/fhir-autocomplete.js +1849 -0
  6. package/dist/src/components/code-editor/fhir-autocomplete.js.map +1 -0
  7. package/dist/src/components/code-editor/fhir-autocomplete.test.js +1099 -0
  8. package/dist/src/components/code-editor/fhir-autocomplete.test.js.map +1 -0
  9. package/dist/src/components/code-editor/http/index.d.ts +9 -1
  10. package/dist/src/components/code-editor/http/index.d.ts.map +1 -1
  11. package/dist/src/components/code-editor/http/index.js +423 -3
  12. package/dist/src/components/code-editor/http/index.js.map +1 -1
  13. package/dist/src/components/code-editor/index.d.ts +13 -4
  14. package/dist/src/components/code-editor/index.d.ts.map +1 -1
  15. package/dist/src/components/code-editor/index.js +505 -96
  16. package/dist/src/components/code-editor/index.js.map +1 -1
  17. package/dist/src/components/code-editor/json-ast.d.ts +46 -0
  18. package/dist/src/components/code-editor/json-ast.d.ts.map +1 -0
  19. package/dist/src/components/code-editor/json-ast.js +465 -0
  20. package/dist/src/components/code-editor/json-ast.js.map +1 -0
  21. package/dist/src/components/code-editor/json-ast.test.js +206 -0
  22. package/dist/src/components/code-editor/json-ast.test.js.map +1 -0
  23. package/dist/src/components/code-editor/sql-completion.d.ts +22 -0
  24. package/dist/src/components/code-editor/sql-completion.d.ts.map +1 -0
  25. package/dist/src/components/code-editor/sql-completion.js +895 -0
  26. package/dist/src/components/code-editor/sql-completion.js.map +1 -0
  27. package/dist/src/components/date-picker-input.d.ts +10 -0
  28. package/dist/src/components/date-picker-input.d.ts.map +1 -0
  29. package/dist/src/components/date-picker-input.js +90 -0
  30. package/dist/src/components/date-picker-input.js.map +1 -0
  31. package/dist/src/components/date-picker-input.stories.js +76 -0
  32. package/dist/src/components/date-picker-input.stories.js.map +1 -0
  33. package/dist/src/index.d.ts +1 -0
  34. package/dist/src/index.d.ts.map +1 -1
  35. package/dist/src/index.js +1 -0
  36. package/dist/src/index.js.map +1 -1
  37. package/dist/src/shadcn/components/ui/alert-dialog.d.ts +1 -1
  38. package/dist/src/shadcn/components/ui/calendar.d.ts +1 -1
  39. package/dist/src/shadcn/components/ui/carousel.d.ts +1 -1
  40. package/dist/src/shadcn/components/ui/chart.d.ts +3 -3
  41. package/dist/src/shadcn/components/ui/chart.d.ts.map +1 -1
  42. package/dist/src/shadcn/components/ui/chart.js +1 -1
  43. package/dist/src/shadcn/components/ui/chart.js.map +1 -1
  44. package/dist/src/shadcn/components/ui/command.d.ts +1 -1
  45. package/dist/src/shadcn/components/ui/pagination.d.ts +1 -1
  46. package/dist/src/shadcn/components/ui/resizable.stories.js +2 -2
  47. package/dist/src/shadcn/components/ui/resizable.stories.js.map +1 -1
  48. package/dist/src/shadcn/components/ui/sidebar.d.ts +4 -4
  49. package/dist/src/shadcn/components/ui/tabs.d.ts +3 -1
  50. package/dist/src/shadcn/components/ui/tabs.d.ts.map +1 -1
  51. package/dist/src/shadcn/components/ui/tabs.js +129 -2
  52. package/dist/src/shadcn/components/ui/tabs.js.map +1 -1
  53. package/dist/src/shadcn/components/ui/tabs.stories.js +1 -1
  54. package/dist/src/shadcn/components/ui/tabs.stories.js.map +1 -1
  55. package/dist/src/shadcn/components/ui/toggle-group.d.ts +1 -1
  56. package/dist/src/typography.css +1 -1
  57. package/package.json +24 -19
  58. package/src/components/code-editor/fhir-autocomplete.test.ts +993 -0
  59. package/src/components/code-editor/fhir-autocomplete.ts +2321 -0
  60. package/src/components/code-editor/http/index.ts +339 -2
  61. package/src/components/code-editor/index.tsx +593 -102
  62. package/src/components/code-editor/json-ast.test.ts +230 -0
  63. package/src/components/code-editor/json-ast.ts +590 -0
  64. package/src/components/code-editor/sql-completion.ts +1105 -0
  65. package/src/components/date-picker-input.stories.tsx +79 -0
  66. package/src/components/date-picker-input.tsx +104 -0
  67. package/src/index.tsx +1 -0
  68. package/src/shadcn/components/ui/chart.tsx +6 -3
  69. package/src/shadcn/components/ui/resizable.stories.tsx +2 -2
  70. package/src/shadcn/components/ui/tabs.stories.tsx +1 -1
  71. package/src/shadcn/components/ui/tabs.tsx +160 -2
  72. package/src/typography.css +1 -1
  73. package/dist/src/components/code-editor/http/grammar/http.test.d.ts +0 -2
  74. package/dist/src/components/code-editor/http/grammar/http.test.d.ts.map +0 -1
@@ -0,0 +1,206 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { buildJsonDocumentContext } from "./json-ast.js";
3
+ // Helpers
4
+ const at = (doc, marker = "|")=>{
5
+ const pos = doc.indexOf(marker);
6
+ return {
7
+ doc: doc.slice(0, pos) + doc.slice(pos + 1),
8
+ pos
9
+ };
10
+ };
11
+ describe("buildJsonDocumentContext", ()=>{
12
+ describe("fullPath", ()=>{
13
+ it("empty object root", ()=>{
14
+ const { doc, pos } = at("{\n |\n}");
15
+ const ctx = buildJsonDocumentContext(doc, pos);
16
+ expect(ctx.fullPath).toEqual([]);
17
+ });
18
+ it("one level deep", ()=>{
19
+ const { doc, pos } = at('{\n "name": [\n {\n |\n }\n ]\n}');
20
+ const ctx = buildJsonDocumentContext(doc, pos);
21
+ expect(ctx.fullPath).toEqual([
22
+ "name"
23
+ ]);
24
+ });
25
+ it("two levels deep", ()=>{
26
+ const { doc, pos } = at('{\n "address": [\n {\n "period": {\n |\n }\n }\n ]\n}');
27
+ const ctx = buildJsonDocumentContext(doc, pos);
28
+ expect(ctx.fullPath).toEqual([
29
+ "address",
30
+ "period"
31
+ ]);
32
+ });
33
+ it("second object in array has correct path", ()=>{
34
+ const { doc, pos } = at('{\n "parameter": [\n {"name": "a"},\n {\n |\n }\n ]\n}');
35
+ const ctx = buildJsonDocumentContext(doc, pos);
36
+ expect(ctx.fullPath).toEqual([
37
+ "parameter"
38
+ ]);
39
+ });
40
+ it("third object in array has correct path", ()=>{
41
+ const { doc, pos } = at('{\n "parameter": [\n {"name": "a"},\n {"name": "b"},\n {\n |\n }\n ]\n}');
42
+ const ctx = buildJsonDocumentContext(doc, pos);
43
+ expect(ctx.fullPath).toEqual([
44
+ "parameter"
45
+ ]);
46
+ });
47
+ it("nested array second item", ()=>{
48
+ const { doc, pos } = at('{\n "entry": [\n {"resource": {}},\n {\n "resource": {\n |\n }\n }\n ]\n}');
49
+ const ctx = buildJsonDocumentContext(doc, pos);
50
+ expect(ctx.fullPath).toEqual([
51
+ "entry",
52
+ "resource"
53
+ ]);
54
+ });
55
+ it("inside contained resource", ()=>{
56
+ const { doc, pos } = at('{\n "resourceType": "Bundle",\n "entry": [\n {\n "resource": {\n "resourceType": "Patient",\n |\n }\n }\n ]\n}');
57
+ const ctx = buildJsonDocumentContext(doc, pos);
58
+ expect(ctx.fullPath).toEqual([
59
+ "entry",
60
+ "resource"
61
+ ]);
62
+ });
63
+ });
64
+ describe("fullPath in HTTP mode", ()=>{
65
+ it("skips HTTP header", ()=>{
66
+ const { doc, pos } = at("POST /fhir/Patient\nContent-Type: application/json\n\n{\n |\n}");
67
+ const ctx = buildJsonDocumentContext(doc, pos);
68
+ expect(ctx.fullPath).toEqual([]);
69
+ });
70
+ it("nested path in HTTP mode", ()=>{
71
+ const { doc, pos } = at('PUT /fhir/Patient/1\n\n{\n "name": [\n {\n |\n }\n ]\n}');
72
+ const ctx = buildJsonDocumentContext(doc, pos);
73
+ expect(ctx.fullPath).toEqual([
74
+ "name"
75
+ ]);
76
+ });
77
+ });
78
+ describe("cursorPosition", ()=>{
79
+ it("property on empty line", ()=>{
80
+ const { doc, pos } = at("{\n |\n}");
81
+ const ctx = buildJsonDocumentContext(doc, pos);
82
+ expect(ctx.cursorPosition.kind).toBe("property");
83
+ });
84
+ it("property with partial word", ()=>{
85
+ const { doc, pos } = at('{\n "nam|\n}');
86
+ const ctx = buildJsonDocumentContext(doc, pos);
87
+ expect(ctx.cursorPosition.kind).toBe("property");
88
+ });
89
+ it("value after colon with string", ()=>{
90
+ const { doc, pos } = at('{\n "gender": "|\n}');
91
+ const ctx = buildJsonDocumentContext(doc, pos);
92
+ expect(ctx.cursorPosition).toEqual({
93
+ kind: "value",
94
+ key: "gender",
95
+ prefix: ""
96
+ });
97
+ });
98
+ it("value with partial text", ()=>{
99
+ const { doc, pos } = at('{\n "gender": "mal|\n}');
100
+ const ctx = buildJsonDocumentContext(doc, pos);
101
+ expect(ctx.cursorPosition).toEqual({
102
+ kind: "value",
103
+ key: "gender",
104
+ prefix: "mal"
105
+ });
106
+ });
107
+ it("value for resourceType", ()=>{
108
+ const { doc, pos } = at('{\n "resourceType": "|\n}');
109
+ const ctx = buildJsonDocumentContext(doc, pos);
110
+ expect(ctx.cursorPosition).toEqual({
111
+ kind: "value",
112
+ key: "resourceType",
113
+ prefix: ""
114
+ });
115
+ });
116
+ it("array-item inside canonical array", ()=>{
117
+ const { doc, pos } = at('{\n "profile": [\n "|\n ]\n}');
118
+ const ctx = buildJsonDocumentContext(doc, pos);
119
+ expect(ctx.cursorPosition.kind).toBe("array-item");
120
+ if (ctx.cursorPosition.kind === "array-item") {
121
+ expect(ctx.cursorPosition.parentKey).toBe("profile");
122
+ }
123
+ });
124
+ it("property after comma in object", ()=>{
125
+ const { doc, pos } = at('{\n "a": 1,\n |\n}');
126
+ const ctx = buildJsonDocumentContext(doc, pos);
127
+ expect(ctx.cursorPosition.kind).toBe("property");
128
+ });
129
+ it("property position after boolean value with comma on same line", ()=>{
130
+ const { doc, pos } = at('{\n "resourceType": "Patient",\n "active": true, |\n}');
131
+ const ctx = buildJsonDocumentContext(doc, pos);
132
+ expect(ctx.cursorPosition.kind).toBe("property");
133
+ });
134
+ });
135
+ describe("isInsideArray", ()=>{
136
+ it("false at object root", ()=>{
137
+ const { doc, pos } = at("{\n |\n}");
138
+ const ctx = buildJsonDocumentContext(doc, pos);
139
+ expect(ctx.isInsideArray()).toBe(false);
140
+ });
141
+ it("true inside array", ()=>{
142
+ const { doc, pos } = at('{\n "name": [\n |\n ]\n}');
143
+ const ctx = buildJsonDocumentContext(doc, pos);
144
+ expect(ctx.isInsideArray()).toBe(true);
145
+ });
146
+ it("false inside object inside array", ()=>{
147
+ const { doc, pos } = at('{\n "name": [\n {\n |\n }\n ]\n}');
148
+ const ctx = buildJsonDocumentContext(doc, pos);
149
+ expect(ctx.isInsideArray()).toBe(false);
150
+ });
151
+ });
152
+ describe("getScope", ()=>{
153
+ it("getString finds resourceType at level 0", ()=>{
154
+ const { doc, pos } = at('{\n "resourceType": "Patient",\n |\n}');
155
+ const ctx = buildJsonDocumentContext(doc, pos);
156
+ expect(ctx.getScope(0).getString("resourceType")).toBe("Patient");
157
+ });
158
+ it("getString finds resourceType in parent object (levelsUp=1)", ()=>{
159
+ const { doc, pos } = at('{\n "resourceType": "Patient",\n "name": [\n {\n |\n }\n ]\n}');
160
+ const ctx = buildJsonDocumentContext(doc, pos);
161
+ // level 0 is the inner {} (no resourceType)
162
+ expect(ctx.getScope(0).getString("resourceType")).toBe(null);
163
+ // level 1 is the outer {} with "Patient"
164
+ expect(ctx.getScope(1).getString("resourceType")).toBe("Patient");
165
+ });
166
+ it("getString finds inner resourceType for contained", ()=>{
167
+ const doc = [
168
+ "{",
169
+ ' "resourceType": "Bundle",',
170
+ ' "entry": [',
171
+ " {",
172
+ ' "resource": {',
173
+ ' "resourceType": "Patient",',
174
+ ' "name": [',
175
+ " {",
176
+ " |",
177
+ " }",
178
+ " ]",
179
+ " }",
180
+ " }",
181
+ " ]",
182
+ "}"
183
+ ].join("\n");
184
+ const { doc: d, pos } = at(doc);
185
+ const ctx = buildJsonDocumentContext(d, pos);
186
+ // level 0 = inner { } (name array item)
187
+ expect(ctx.getScope(0).getString("resourceType")).toBe(null);
188
+ // level 1 = resource { "resourceType": "Patient" }
189
+ expect(ctx.getScope(1).getString("resourceType")).toBe("Patient");
190
+ });
191
+ it("getStringArray finds meta.profile", ()=>{
192
+ const { doc, pos } = at('{\n "resourceType": "Patient",\n "meta": {\n "profile": ["http://example.com/Patient"]\n },\n |\n}');
193
+ const ctx = buildJsonDocumentContext(doc, pos);
194
+ expect(ctx.getScope(0).getStringArray("meta", "profile")).toEqual([
195
+ "http://example.com/Patient"
196
+ ]);
197
+ });
198
+ it("getStringArray returns empty for missing profile", ()=>{
199
+ const { doc, pos } = at('{\n "resourceType": "Patient",\n |\n}');
200
+ const ctx = buildJsonDocumentContext(doc, pos);
201
+ expect(ctx.getScope(0).getStringArray("meta", "profile")).toEqual([]);
202
+ });
203
+ });
204
+ });
205
+
206
+ //# sourceMappingURL=json-ast.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/components/code-editor/json-ast.test.ts"],"sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { buildJsonDocumentContext } from \"./json-ast\";\n\n// Helpers\nconst at = (doc: string, marker = \"|\") => {\n\tconst pos = doc.indexOf(marker);\n\treturn { doc: doc.slice(0, pos) + doc.slice(pos + 1), pos };\n};\n\ndescribe(\"buildJsonDocumentContext\", () => {\n\tdescribe(\"fullPath\", () => {\n\t\tit(\"empty object root\", () => {\n\t\t\tconst { doc, pos } = at(\"{\\n |\\n}\");\n\t\t\tconst ctx = buildJsonDocumentContext(doc, pos);\n\t\t\texpect(ctx.fullPath).toEqual([]);\n\t\t});\n\n\t\tit(\"one level deep\", () => {\n\t\t\tconst { doc, pos } = at('{\\n \"name\": [\\n {\\n |\\n }\\n ]\\n}');\n\t\t\tconst ctx = buildJsonDocumentContext(doc, pos);\n\t\t\texpect(ctx.fullPath).toEqual([\"name\"]);\n\t\t});\n\n\t\tit(\"two levels deep\", () => {\n\t\t\tconst { doc, pos } = at(\n\t\t\t\t'{\\n \"address\": [\\n {\\n \"period\": {\\n |\\n }\\n }\\n ]\\n}',\n\t\t\t);\n\t\t\tconst ctx = buildJsonDocumentContext(doc, pos);\n\t\t\texpect(ctx.fullPath).toEqual([\"address\", \"period\"]);\n\t\t});\n\n\t\tit(\"second object in array has correct path\", () => {\n\t\t\tconst { doc, pos } = at(\n\t\t\t\t'{\\n \"parameter\": [\\n {\"name\": \"a\"},\\n {\\n |\\n }\\n ]\\n}',\n\t\t\t);\n\t\t\tconst ctx = buildJsonDocumentContext(doc, pos);\n\t\t\texpect(ctx.fullPath).toEqual([\"parameter\"]);\n\t\t});\n\n\t\tit(\"third object in array has correct path\", () => {\n\t\t\tconst { doc, pos } = at(\n\t\t\t\t'{\\n \"parameter\": [\\n {\"name\": \"a\"},\\n {\"name\": \"b\"},\\n {\\n |\\n }\\n ]\\n}',\n\t\t\t);\n\t\t\tconst ctx = buildJsonDocumentContext(doc, pos);\n\t\t\texpect(ctx.fullPath).toEqual([\"parameter\"]);\n\t\t});\n\n\t\tit(\"nested array second item\", () => {\n\t\t\tconst { doc, pos } = at(\n\t\t\t\t'{\\n \"entry\": [\\n {\"resource\": {}},\\n {\\n \"resource\": {\\n |\\n }\\n }\\n ]\\n}',\n\t\t\t);\n\t\t\tconst ctx = buildJsonDocumentContext(doc, pos);\n\t\t\texpect(ctx.fullPath).toEqual([\"entry\", \"resource\"]);\n\t\t});\n\n\t\tit(\"inside contained resource\", () => {\n\t\t\tconst { doc, pos } = at(\n\t\t\t\t'{\\n \"resourceType\": \"Bundle\",\\n \"entry\": [\\n {\\n \"resource\": {\\n \"resourceType\": \"Patient\",\\n |\\n }\\n }\\n ]\\n}',\n\t\t\t);\n\t\t\tconst ctx = buildJsonDocumentContext(doc, pos);\n\t\t\texpect(ctx.fullPath).toEqual([\"entry\", \"resource\"]);\n\t\t});\n\t});\n\n\tdescribe(\"fullPath in HTTP mode\", () => {\n\t\tit(\"skips HTTP header\", () => {\n\t\t\tconst { doc, pos } = at(\n\t\t\t\t\"POST /fhir/Patient\\nContent-Type: application/json\\n\\n{\\n |\\n}\",\n\t\t\t);\n\t\t\tconst ctx = buildJsonDocumentContext(doc, pos);\n\t\t\texpect(ctx.fullPath).toEqual([]);\n\t\t});\n\n\t\tit(\"nested path in HTTP mode\", () => {\n\t\t\tconst { doc, pos } = at(\n\t\t\t\t'PUT /fhir/Patient/1\\n\\n{\\n \"name\": [\\n {\\n |\\n }\\n ]\\n}',\n\t\t\t);\n\t\t\tconst ctx = buildJsonDocumentContext(doc, pos);\n\t\t\texpect(ctx.fullPath).toEqual([\"name\"]);\n\t\t});\n\t});\n\n\tdescribe(\"cursorPosition\", () => {\n\t\tit(\"property on empty line\", () => {\n\t\t\tconst { doc, pos } = at(\"{\\n |\\n}\");\n\t\t\tconst ctx = buildJsonDocumentContext(doc, pos);\n\t\t\texpect(ctx.cursorPosition.kind).toBe(\"property\");\n\t\t});\n\n\t\tit(\"property with partial word\", () => {\n\t\t\tconst { doc, pos } = at('{\\n \"nam|\\n}');\n\t\t\tconst ctx = buildJsonDocumentContext(doc, pos);\n\t\t\texpect(ctx.cursorPosition.kind).toBe(\"property\");\n\t\t});\n\n\t\tit(\"value after colon with string\", () => {\n\t\t\tconst { doc, pos } = at('{\\n \"gender\": \"|\\n}');\n\t\t\tconst ctx = buildJsonDocumentContext(doc, pos);\n\t\t\texpect(ctx.cursorPosition).toEqual({\n\t\t\t\tkind: \"value\",\n\t\t\t\tkey: \"gender\",\n\t\t\t\tprefix: \"\",\n\t\t\t});\n\t\t});\n\n\t\tit(\"value with partial text\", () => {\n\t\t\tconst { doc, pos } = at('{\\n \"gender\": \"mal|\\n}');\n\t\t\tconst ctx = buildJsonDocumentContext(doc, pos);\n\t\t\texpect(ctx.cursorPosition).toEqual({\n\t\t\t\tkind: \"value\",\n\t\t\t\tkey: \"gender\",\n\t\t\t\tprefix: \"mal\",\n\t\t\t});\n\t\t});\n\n\t\tit(\"value for resourceType\", () => {\n\t\t\tconst { doc, pos } = at('{\\n \"resourceType\": \"|\\n}');\n\t\t\tconst ctx = buildJsonDocumentContext(doc, pos);\n\t\t\texpect(ctx.cursorPosition).toEqual({\n\t\t\t\tkind: \"value\",\n\t\t\t\tkey: \"resourceType\",\n\t\t\t\tprefix: \"\",\n\t\t\t});\n\t\t});\n\n\t\tit(\"array-item inside canonical array\", () => {\n\t\t\tconst { doc, pos } = at('{\\n \"profile\": [\\n \"|\\n ]\\n}');\n\t\t\tconst ctx = buildJsonDocumentContext(doc, pos);\n\t\t\texpect(ctx.cursorPosition.kind).toBe(\"array-item\");\n\t\t\tif (ctx.cursorPosition.kind === \"array-item\") {\n\t\t\t\texpect(ctx.cursorPosition.parentKey).toBe(\"profile\");\n\t\t\t}\n\t\t});\n\n\t\tit(\"property after comma in object\", () => {\n\t\t\tconst { doc, pos } = at('{\\n \"a\": 1,\\n |\\n}');\n\t\t\tconst ctx = buildJsonDocumentContext(doc, pos);\n\t\t\texpect(ctx.cursorPosition.kind).toBe(\"property\");\n\t\t});\n\n\t\tit(\"property position after boolean value with comma on same line\", () => {\n\t\t\tconst { doc, pos } = at(\n\t\t\t\t'{\\n \"resourceType\": \"Patient\",\\n \"active\": true, |\\n}',\n\t\t\t);\n\t\t\tconst ctx = buildJsonDocumentContext(doc, pos);\n\t\t\texpect(ctx.cursorPosition.kind).toBe(\"property\");\n\t\t});\n\t});\n\n\tdescribe(\"isInsideArray\", () => {\n\t\tit(\"false at object root\", () => {\n\t\t\tconst { doc, pos } = at(\"{\\n |\\n}\");\n\t\t\tconst ctx = buildJsonDocumentContext(doc, pos);\n\t\t\texpect(ctx.isInsideArray()).toBe(false);\n\t\t});\n\n\t\tit(\"true inside array\", () => {\n\t\t\tconst { doc, pos } = at('{\\n \"name\": [\\n |\\n ]\\n}');\n\t\t\tconst ctx = buildJsonDocumentContext(doc, pos);\n\t\t\texpect(ctx.isInsideArray()).toBe(true);\n\t\t});\n\n\t\tit(\"false inside object inside array\", () => {\n\t\t\tconst { doc, pos } = at('{\\n \"name\": [\\n {\\n |\\n }\\n ]\\n}');\n\t\t\tconst ctx = buildJsonDocumentContext(doc, pos);\n\t\t\texpect(ctx.isInsideArray()).toBe(false);\n\t\t});\n\t});\n\n\tdescribe(\"getScope\", () => {\n\t\tit(\"getString finds resourceType at level 0\", () => {\n\t\t\tconst { doc, pos } = at('{\\n \"resourceType\": \"Patient\",\\n |\\n}');\n\t\t\tconst ctx = buildJsonDocumentContext(doc, pos);\n\t\t\texpect(ctx.getScope(0).getString(\"resourceType\")).toBe(\"Patient\");\n\t\t});\n\n\t\tit(\"getString finds resourceType in parent object (levelsUp=1)\", () => {\n\t\t\tconst { doc, pos } = at(\n\t\t\t\t'{\\n \"resourceType\": \"Patient\",\\n \"name\": [\\n {\\n |\\n }\\n ]\\n}',\n\t\t\t);\n\t\t\tconst ctx = buildJsonDocumentContext(doc, pos);\n\t\t\t// level 0 is the inner {} (no resourceType)\n\t\t\texpect(ctx.getScope(0).getString(\"resourceType\")).toBe(null);\n\t\t\t// level 1 is the outer {} with \"Patient\"\n\t\t\texpect(ctx.getScope(1).getString(\"resourceType\")).toBe(\"Patient\");\n\t\t});\n\n\t\tit(\"getString finds inner resourceType for contained\", () => {\n\t\t\tconst doc = [\n\t\t\t\t\"{\",\n\t\t\t\t' \"resourceType\": \"Bundle\",',\n\t\t\t\t' \"entry\": [',\n\t\t\t\t\" {\",\n\t\t\t\t' \"resource\": {',\n\t\t\t\t' \"resourceType\": \"Patient\",',\n\t\t\t\t' \"name\": [',\n\t\t\t\t\" {\",\n\t\t\t\t\" |\",\n\t\t\t\t\" }\",\n\t\t\t\t\" ]\",\n\t\t\t\t\" }\",\n\t\t\t\t\" }\",\n\t\t\t\t\" ]\",\n\t\t\t\t\"}\",\n\t\t\t].join(\"\\n\");\n\t\t\tconst { doc: d, pos } = at(doc);\n\t\t\tconst ctx = buildJsonDocumentContext(d, pos);\n\t\t\t// level 0 = inner { } (name array item)\n\t\t\texpect(ctx.getScope(0).getString(\"resourceType\")).toBe(null);\n\t\t\t// level 1 = resource { \"resourceType\": \"Patient\" }\n\t\t\texpect(ctx.getScope(1).getString(\"resourceType\")).toBe(\"Patient\");\n\t\t});\n\n\t\tit(\"getStringArray finds meta.profile\", () => {\n\t\t\tconst { doc, pos } = at(\n\t\t\t\t'{\\n \"resourceType\": \"Patient\",\\n \"meta\": {\\n \"profile\": [\"http://example.com/Patient\"]\\n },\\n |\\n}',\n\t\t\t);\n\t\t\tconst ctx = buildJsonDocumentContext(doc, pos);\n\t\t\texpect(ctx.getScope(0).getStringArray(\"meta\", \"profile\")).toEqual([\n\t\t\t\t\"http://example.com/Patient\",\n\t\t\t]);\n\t\t});\n\n\t\tit(\"getStringArray returns empty for missing profile\", () => {\n\t\t\tconst { doc, pos } = at('{\\n \"resourceType\": \"Patient\",\\n |\\n}');\n\t\t\tconst ctx = buildJsonDocumentContext(doc, pos);\n\t\t\texpect(ctx.getScope(0).getStringArray(\"meta\", \"profile\")).toEqual([]);\n\t\t});\n\t});\n});\n"],"names":["describe","expect","it","buildJsonDocumentContext","at","doc","marker","pos","indexOf","slice","ctx","fullPath","toEqual","cursorPosition","kind","toBe","key","prefix","parentKey","isInsideArray","getScope","getString","join","d","getStringArray"],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import { type Extension } from "@codemirror/state";
2
+ export type SqlQueryType = "tables" | "columns" | "functions" | "jsonb_columns" | "structure_definition";
3
+ export interface SqlConfig {
4
+ executeSql: (query: string, type: SqlQueryType) => Promise<Record<string, unknown>[]>;
5
+ }
6
+ type SchemaMap = Record<string, string[]>;
7
+ type JsonbColumnMap = Record<string, string[]>;
8
+ type ColumnInfo = {
9
+ name: string;
10
+ dataType: string;
11
+ };
12
+ type ColumnMap = Record<string, ColumnInfo[]>;
13
+ export interface SqlMetadata {
14
+ schemas: SchemaMap;
15
+ jsonbColumns: JsonbColumnMap;
16
+ functions: string[];
17
+ columns: ColumnMap;
18
+ }
19
+ export declare function fetchSqlMetadata(executeSql: SqlConfig["executeSql"]): Promise<SqlMetadata>;
20
+ export declare function buildSqlCompletionExtensions(metadata: SqlMetadata, executeSql: SqlConfig["executeSql"]): Extension[];
21
+ export {};
22
+ //# sourceMappingURL=sql-completion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sql-completion.d.ts","sourceRoot":"","sources":["../../../../src/components/code-editor/sql-completion.ts"],"names":[],"mappings":"AAQA,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAKhE,MAAM,MAAM,YAAY,GACrB,QAAQ,GACR,SAAS,GACT,WAAW,GACX,eAAe,GACf,sBAAsB,CAAC;AAqB1B,MAAM,WAAW,SAAS;IACzB,UAAU,EAAE,CACX,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,YAAY,KACd,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;CACxC;AAID,KAAK,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;AAC1C,KAAK,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;AAC/C,KAAK,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AACrD,KAAK,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;AAuB9C,MAAM,WAAW,WAAW;IAC3B,OAAO,EAAE,SAAS,CAAC;IACnB,YAAY,EAAE,cAAc,CAAC;IAC7B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,EAAE,SAAS,CAAC;CACnB;AA21BD,wBAAsB,gBAAgB,CACrC,UAAU,EAAE,SAAS,CAAC,YAAY,CAAC,GACjC,OAAO,CAAC,WAAW,CAAC,CAqCtB;AAED,wBAAgB,4BAA4B,CAC3C,QAAQ,EAAE,WAAW,EACrB,UAAU,EAAE,SAAS,CAAC,YAAY,CAAC,GACjC,SAAS,EAAE,CA0Hb"}