From 1d2f82c007c8f7677667812d49b9fb87f05013b5 Mon Sep 17 00:00:00 2001 From: Andrey Listopadov Date: Fri, 7 Nov 2025 18:52:05 +0300 Subject: [PATCH 01/39] wip aidbox client --- src/routes/rest.tsx | 47 +++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/src/routes/rest.tsx b/src/routes/rest.tsx index e8ef49aa..e92ff504 100644 --- a/src/routes/rest.tsx +++ b/src/routes/rest.tsx @@ -30,7 +30,6 @@ import React, { useRef, useState, } from "react"; -import { AidboxRequest, type AidboxResponse } from "../api/auth"; import { ActiveTabs, DEFAULT_TAB, @@ -51,8 +50,12 @@ import { CodeEditorMenubar } from "../components/ViewDefinition/code-editor-menu import { useLocalStorage } from "../hooks/useLocalStorage"; import { HTTP_STATUS_CODES, REST_CONSOLE_TABS_KEY } from "../shared/const"; import { parseHttpRequest } from "../utils"; +import { UI_BASE_PATH } from "../shared/const"; +import * as Aidbox from "@health-samurai/aidbox-client"; +// import type * as AidboxType from "@health-samurai/aidbox-client"; const TITLE = "REST Console"; +const aidboxClient = Aidbox.makeClient({ basepath: "http://localhost:8765" }); export const Route = createFileRoute("/rest")({ staticData: { @@ -749,18 +752,20 @@ function handleSendRequest( setIsLoading(true); - AidboxRequest({ - method: selectedTab.method, - url: selectedTab.path || "/", - headers, - body: selectedTab.body || "", - streamBody: false, - }) - .then((response: AidboxResponse) => { + aidboxClient + .aidboxRawRequest({ + method: selectedTab.method, + url: selectedTab.path || "/", + headers, + body: selectedTab.body || "", + }) + .then(async (response) => { const responseData = { - ...response.response, - body: response.response.body as string, - duration: response.meta.duration, + status: response.response.status, + statusText: response.response.statusText, + headers: response.responseHeaders, + body: (await response.response.text()) as string, + duration: response.duration, mode: responseMode, }; // Store response in tab @@ -770,20 +775,20 @@ function handleSendRequest( ), ); }) - .catch((error) => { - const cause: AidboxResponse = error.cause; - console.log("error", cause.response); - + .catch(async (error) => { + const cause = error.cause; const errorMode = - cause.response.headers["content-type"]?.toLowerCase().trim() === + cause.responseHeaders["content-type"]?.toLowerCase().trim() === "text/yaml" ? "yaml" : "json"; const errorResponse: ResponseData = { - ...cause.response, - body: cause.response.body as string, - duration: cause.meta.duration, + status: cause.response.status, + statusText: cause.response.statusText, + headers: cause.responseHeaders, + body: (await cause.response.text()) as string, + duration: cause.duration, mode: errorMode, }; @@ -854,7 +859,7 @@ async function saveToUIHistory( command: command, }; - await AidboxRequest({ + await aidboxClient.aidboxRawRequest({ method: "PUT", url: `/ui_history/${historyId}`, headers: { From 4e9a5cd4d3a8e21c27b81bb572a9e12079e9d3db Mon Sep 17 00:00:00 2001 From: Andrey Listopadov Date: Tue, 11 Nov 2025 15:21:52 +0300 Subject: [PATCH 02/39] provide aidbox client via the context provider --- src/AidboxClient.tsx | 36 ++++++++++++++++++++++++ src/components/ResourceEditor/action.tsx | 2 +- src/index.tsx | 5 +++- src/routes/rest.tsx | 23 ++++++++++----- 4 files changed, 57 insertions(+), 9 deletions(-) create mode 100644 src/AidboxClient.tsx diff --git a/src/AidboxClient.tsx b/src/AidboxClient.tsx new file mode 100644 index 00000000..7234e8fa --- /dev/null +++ b/src/AidboxClient.tsx @@ -0,0 +1,36 @@ +import { makeClient } from "@health-samurai/aidbox-client"; +import type * as Aidbox from "@health-samurai/aidbox-client"; +import * as React from "react"; + +export const AidboxClientContext = React.createContext< + Aidbox.Client | undefined +>(undefined); + +export type AidboxClientProviderProps = { + baseurl: string; + children: React.ReactNode; +}; + +export function AidboxClientProvider({ + baseurl, + children, +}: AidboxClientProviderProps): React.JSX.Element { + const client = makeClient({ baseurl }); + + return ( + + {children} + + ); +} + +export function useAidboxClient(aidboxClient?: Aidbox.Client): Aidbox.Client { + const client = React.useContext(AidboxClientContext); + + if (aidboxClient) return aidboxClient; + + if (!client) + throw new Error("No AidboxClient set, use AidboxClientProvider to set one"); + + return client; +} diff --git a/src/components/ResourceEditor/action.tsx b/src/components/ResourceEditor/action.tsx index ba1f0481..d116e86c 100644 --- a/src/components/ResourceEditor/action.tsx +++ b/src/components/ResourceEditor/action.tsx @@ -3,13 +3,13 @@ import * as HSComp from "@health-samurai/react-components"; import { useMutation } from "@tanstack/react-query"; import * as Router from "@tanstack/react-router"; import * as YAML from "js-yaml"; +import * as Utils from "../../api/utils"; import { createResource, deleteResource, type Resource, updateResource, } from "./api"; -import * as Utils from "../../api/utils"; import type { EditorMode } from "./types"; export const SaveButton = ({ diff --git a/src/index.tsx b/src/index.tsx index 60ede817..f831f4ae 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -4,6 +4,7 @@ import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; import { routeTree } from "./routeTree.gen"; import "./index.css"; +import { AidboxClientProvider } from "./AidboxClient"; import { UI_BASE_PATH } from "./shared/const"; const router = createRouter({ basepath: UI_BASE_PATH, routeTree }); @@ -25,7 +26,9 @@ if (root) { createRoot(root).render( - + + + , ); diff --git a/src/routes/rest.tsx b/src/routes/rest.tsx index e92ff504..bd406d82 100644 --- a/src/routes/rest.tsx +++ b/src/routes/rest.tsx @@ -1,3 +1,4 @@ +import type * as AidboxType from "@health-samurai/aidbox-client"; import { Button, CodeEditor, @@ -30,6 +31,7 @@ import React, { useRef, useState, } from "react"; +import { useAidboxClient } from "../AidboxClient"; import { ActiveTabs, DEFAULT_TAB, @@ -50,12 +52,8 @@ import { CodeEditorMenubar } from "../components/ViewDefinition/code-editor-menu import { useLocalStorage } from "../hooks/useLocalStorage"; import { HTTP_STATUS_CODES, REST_CONSOLE_TABS_KEY } from "../shared/const"; import { parseHttpRequest } from "../utils"; -import { UI_BASE_PATH } from "../shared/const"; -import * as Aidbox from "@health-samurai/aidbox-client"; -// import type * as AidboxType from "@health-samurai/aidbox-client"; const TITLE = "REST Console"; -const aidboxClient = Aidbox.makeClient({ basepath: "http://localhost:8765" }); export const Route = createFileRoute("/rest")({ staticData: { @@ -724,6 +722,7 @@ function handleSendRequest( queryClient: QueryClient, setIsLoading: (loading: boolean) => void, setTabs: (tabs: Tab[] | ((tabs: Tab[]) => Tab[])) => void, + aidboxClient: AidboxType.Client, ) { const headers = selectedTab.headers @@ -748,7 +747,7 @@ function handleSendRequest( acceptHeader?.value?.toLowerCase().trim() === "text/yaml" ? "yaml" : "json"; // Save to UI history (don't wait for it) - saveToUIHistory(selectedTab, queryClient); + saveToUIHistory(selectedTab, queryClient, aidboxClient); setIsLoading(true); @@ -847,6 +846,7 @@ function formatRequestAsHttpCommand(tab: Tab): string { async function saveToUIHistory( tab: Tab, queryClient: QueryClient, + aidboxClient: AidboxType.Client, ): Promise { try { const historyId = crypto.randomUUID(); @@ -892,6 +892,8 @@ function SendButton( } function RouteComponent() { + const aidboxClient = useAidboxClient(); + const [tabs, setTabs] = useLocalStorage({ key: REST_CONSOLE_TABS_KEY, getInitialValueInEffect: false, @@ -950,7 +952,13 @@ function RouteComponent() { (event.ctrlKey && event.key === "Enter") ) { event.preventDefault(); - handleSendRequest(selectedTab, queryClient, setIsLoading, setTabs); + handleSendRequest( + selectedTab, + queryClient, + setIsLoading, + setTabs, + aidboxClient, + ); } }; @@ -958,7 +966,7 @@ function RouteComponent() { return () => { document.removeEventListener("keydown", handleKeyDown); }; - }, [selectedTab, queryClient, setTabs]); + }, [selectedTab, queryClient, setTabs, aidboxClient]); function handleTabMethodChange(method: string) { setRequestLineVersion(crypto.randomUUID()); @@ -1236,6 +1244,7 @@ function RouteComponent() { queryClient, setIsLoading, setTabs, + aidboxClient, ) } /> From 6df3a7a82ca0dc70314e7c6f74496c9ff193eb5b Mon Sep 17 00:00:00 2001 From: Andrey Listopadov Date: Tue, 11 Nov 2025 19:02:15 +0300 Subject: [PATCH 03/39] start migrating to new client in viewdef builder --- .../ViewDefinition/editor-panel-content.tsx | 45 ++++++++++++++----- src/components/ViewDefinition/page.tsx | 14 ++++-- 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/src/components/ViewDefinition/editor-panel-content.tsx b/src/components/ViewDefinition/editor-panel-content.tsx index 9d6031d2..0cde3fe2 100644 --- a/src/components/ViewDefinition/editor-panel-content.tsx +++ b/src/components/ViewDefinition/editor-panel-content.tsx @@ -3,7 +3,8 @@ import { useMutation } from "@tanstack/react-query"; import { useNavigate, useSearch } from "@tanstack/react-router"; import * as Lucide from "lucide-react"; import React from "react"; -import { AidboxCallWithMeta } from "../../api/auth"; +import type * as AidboxType from "@health-samurai/aidbox-client"; +import { useAidboxClient } from "../../AidboxClient"; import * as utils from "../../api/utils"; import { CodeTabContent } from "./editor-code-tab-content"; @@ -36,14 +37,18 @@ export const EditorHeaderMenu = () => { ); }; -export const EditorPanelActions = () => { +export const EditorPanelActions = ({ + client, +}: { + client: AidboxType.Client; +}) => { const navigate = useNavigate({ from: "/resource/$resourceType/create" }); const viewDefinitionContext = React.useContext(ViewDefinitionContext); const viewDefinitionResource = viewDefinitionContext.viewDefinition; const viewDefinitionMutation = useMutation({ mutationFn: (viewDefinition: Types.ViewDefinition) => { - return AidboxCallWithMeta({ + return client.aidboxRequest({ method: "PUT", url: `/fhir/ViewDefinition/${viewDefinitionContext.originalId}`, body: JSON.stringify(viewDefinition), @@ -60,14 +65,14 @@ export const EditorPanelActions = () => { const viewDefinitionCreateMutation = useMutation({ mutationFn: (viewDefinition: Types.ViewDefinition) => { - return AidboxCallWithMeta({ + return client.aidboxRequest({ method: "POST", url: `/fhir/ViewDefinition/`, body: JSON.stringify(viewDefinition), }); }, - onSuccess: (resp) => { - const id = JSON.parse(resp.body).id; + onSuccess: (resp: AidboxType.AidboxResponse) => { + const id = JSON.parse(resp.response.body).id; navigate({ to: "/resource/$resourceType/edit/$id", params: { resourceType: "ViewDefinition", id: id }, @@ -103,7 +108,7 @@ export const EditorPanelActions = () => { }, ], }; - return AidboxCallWithMeta({ + return client.aidboxRawRequest({ method: "POST", url: "/fhir/ViewDefinition/$run", headers: { @@ -113,15 +118,31 @@ export const EditorPanelActions = () => { body: JSON.stringify(parametersPayload), }); }, - onSuccess: (data) => { - const decodedData = atob(JSON.parse(data.body).data); + onSuccess: async (data: AidboxType.AidboxRawResponse) => { + const body = JSON.parse(await data.response.text()); + const decodedData = atob(body.data); viewDefinitionContext.setRunResult(decodedData); HSComp.toast.success("ViewDefinition run successfully", { position: "bottom-right", style: { margin: "1rem" }, }); }, - onError: utils.onError(), + onError: async ( + error: AidboxType.AidboxClientError, + vars, + onMutateResult, + context, + ) => { + const body = await ( + error.cause as AidboxType.AidboxRawResponse + ).response.text(); + utils.onError()( + new Error(error.message, { cause: body }), + vars, + onMutateResult, + context, + ); + }, }); const handleSave = () => { @@ -164,6 +185,8 @@ export const EditorPanelActions = () => { }; export const EditorPanelContent = () => { + const aidboxClient: AidboxType.Client = useAidboxClient(); + const navigate = useNavigate(); const createSearch = useSearch({ @@ -205,7 +228,7 @@ export const EditorPanelContent = () => { - + ); }; diff --git a/src/components/ViewDefinition/page.tsx b/src/components/ViewDefinition/page.tsx index 8820536b..96713bf0 100644 --- a/src/components/ViewDefinition/page.tsx +++ b/src/components/ViewDefinition/page.tsx @@ -1,15 +1,16 @@ import * as HSComp from "@health-samurai/react-components"; import { useQuery } from "@tanstack/react-query"; import React from "react"; -import { AidboxCall } from "../../api/auth"; +import type * as AidboxType from "@health-samurai/aidbox-client"; +import { useAidboxClient } from "../../AidboxClient"; import * as Constants from "./constants"; import { EditorPanelContent } from "./editor-panel-content"; import { InfoPanel } from "./info-panel"; import { ResultPanel } from "./result-panel-content"; import type * as Types from "./types"; -const fetchViewDefinition = (id: string) => { - return AidboxCall({ +const fetchViewDefinition = (client: AidboxType.Client, id: string) => { + return client.aidboxRequest({ method: "GET", url: `/fhir/ViewDefinition/${id}`, }); @@ -54,6 +55,8 @@ export const ViewDefinitionErrorPage = ({ }; const ViewDefinitionPage = ({ id }: { id?: string }) => { + const aidboxClient = useAidboxClient(); + const [resouceTypeForViewDefinition, setResouceTypeForViewDefinition] = React.useState(); const [viewDefinition, setViewDefinition] = @@ -74,7 +77,10 @@ const ViewDefinitionPage = ({ id }: { id?: string }) => { select: [], }; let response: Types.ViewDefinition = viewDefinitionPlaceholder; - if (id) response = await fetchViewDefinition(id); + if (id) { + const resp = await fetchViewDefinition(aidboxClient, id); + response = resp.response.body; + } setResouceTypeForViewDefinition(response.resource); setViewDefinition(response); return response; From d9bedcac5ef30aaee9a433af81bbf9c4c5a902c7 Mon Sep 17 00:00:00 2001 From: Andrey Listopadov Date: Thu, 13 Nov 2025 12:23:31 +0300 Subject: [PATCH 04/39] migrate ViewDefinition builder to the new aidbox client --- src/AidboxClient.tsx | 2 +- .../ViewDefinition/editor-panel-content.tsx | 2 +- .../ViewDefinition/example-tab-content.tsx | 17 ++++++++---- src/components/ViewDefinition/page.tsx | 2 +- .../ViewDefinition/resource-type-select.tsx | 27 +++++++++++-------- .../ViewDefinition/result-panel-content.tsx | 11 +++++--- .../ViewDefinition/schema-tab-content.tsx | 12 ++++++--- .../ViewDefinition/sql-tab-content.tsx | 16 +++++++---- 8 files changed, 57 insertions(+), 32 deletions(-) diff --git a/src/AidboxClient.tsx b/src/AidboxClient.tsx index 7234e8fa..40f4371e 100644 --- a/src/AidboxClient.tsx +++ b/src/AidboxClient.tsx @@ -1,5 +1,5 @@ -import { makeClient } from "@health-samurai/aidbox-client"; import type * as Aidbox from "@health-samurai/aidbox-client"; +import { makeClient } from "@health-samurai/aidbox-client"; import * as React from "react"; export const AidboxClientContext = React.createContext< diff --git a/src/components/ViewDefinition/editor-panel-content.tsx b/src/components/ViewDefinition/editor-panel-content.tsx index 0cde3fe2..0a78ea3a 100644 --- a/src/components/ViewDefinition/editor-panel-content.tsx +++ b/src/components/ViewDefinition/editor-panel-content.tsx @@ -1,9 +1,9 @@ +import type * as AidboxType from "@health-samurai/aidbox-client"; import * as HSComp from "@health-samurai/react-components"; import { useMutation } from "@tanstack/react-query"; import { useNavigate, useSearch } from "@tanstack/react-router"; import * as Lucide from "lucide-react"; import React from "react"; -import type * as AidboxType from "@health-samurai/aidbox-client"; import { useAidboxClient } from "../../AidboxClient"; import * as utils from "../../api/utils"; diff --git a/src/components/ViewDefinition/example-tab-content.tsx b/src/components/ViewDefinition/example-tab-content.tsx index be0824ff..c3fc0eda 100644 --- a/src/components/ViewDefinition/example-tab-content.tsx +++ b/src/components/ViewDefinition/example-tab-content.tsx @@ -1,3 +1,4 @@ +import type * as AidboxTypes from "@health-samurai/aidbox-client"; import { Button, CodeEditor, @@ -7,11 +8,10 @@ import { TabsContent, } from "@health-samurai/react-components"; import { useQuery, useQueryClient } from "@tanstack/react-query"; - import * as yaml from "js-yaml"; import { ChevronLeft, ChevronRight } from "lucide-react"; import { useContext, useState } from "react"; -import { AidboxCall } from "../../api/auth"; +import { useAidboxClient } from "../../AidboxClient"; import { useLocalStorage } from "../../hooks"; import * as Constants from "./constants"; import { @@ -21,6 +21,7 @@ import { import { SearchBar } from "./search-bar"; const searchResources = async ( + client: AidboxTypes.Client, resourceType: string, searchParams: string, ): Promise[]> => { @@ -28,7 +29,9 @@ const searchResources = async ( ? `/fhir/${resourceType}?${searchParams}` : `/fhir/${resourceType}`; - const response = await AidboxCall<{ + console.log(url); + + const response = await client.aidboxRequest<{ entry?: Array<{ resource: Record }>; }>({ method: "GET", @@ -38,8 +41,10 @@ const searchResources = async ( }, }); - if (response?.entry && response.entry.length > 0) { - return response.entry.map((entry) => entry.resource); + if (response.response.body.entry && response.response.body.entry.length > 0) { + return response.response.body.entry.map( + (entry: Record) => entry.resource, + ); } else { return []; } @@ -97,6 +102,7 @@ const ExampleTabEditorMenu = ({ }; export function ExampleTabContent() { + const aidboxClient = useAidboxClient(); const viewDefinitionContext = useContext(ViewDefinitionContext); const viewDefinitionTypeContext = useContext( ViewDefinitionResourceTypeContext, @@ -119,6 +125,7 @@ export function ExampleTabContent() { queryFn: async () => { if (!viewDefinitionResourceType) return; const resources = await searchResources( + aidboxClient, viewDefinitionResourceType, query, ); diff --git a/src/components/ViewDefinition/page.tsx b/src/components/ViewDefinition/page.tsx index 96713bf0..bf758606 100644 --- a/src/components/ViewDefinition/page.tsx +++ b/src/components/ViewDefinition/page.tsx @@ -1,7 +1,7 @@ +import type * as AidboxType from "@health-samurai/aidbox-client"; import * as HSComp from "@health-samurai/react-components"; import { useQuery } from "@tanstack/react-query"; import React from "react"; -import type * as AidboxType from "@health-samurai/aidbox-client"; import { useAidboxClient } from "../../AidboxClient"; import * as Constants from "./constants"; import { EditorPanelContent } from "./editor-panel-content"; diff --git a/src/components/ViewDefinition/resource-type-select.tsx b/src/components/ViewDefinition/resource-type-select.tsx index 9f9f5cb7..fbb85925 100644 --- a/src/components/ViewDefinition/resource-type-select.tsx +++ b/src/components/ViewDefinition/resource-type-select.tsx @@ -1,30 +1,35 @@ +import type * as AidboxTypes from "@health-samurai/aidbox-client"; import * as HSComp from "@health-samurai/react-components"; import { useQuery } from "@tanstack/react-query"; import React from "react"; -import { AidboxCall } from "../../api/auth"; +import { useAidboxClient } from "../../AidboxClient"; import * as Constants from "./constants"; import { ViewDefinitionResourceTypeContext } from "./page"; import type * as Types from "./types"; -const fetchResourceTypes = () => { - return AidboxCall({ - method: "GET", - url: "/$resource-types", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - }); +const fetchResourceTypes = async (client: AidboxTypes.Client) => { + return ( + await client.aidboxRequest({ + method: "GET", + url: "/$resource-types", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + }) + ).response.body; }; export const ResourceTypeSelect = () => { + const client = useAidboxClient(); + const viewDefinitionResourceTypeContext = React.useContext( ViewDefinitionResourceTypeContext, ); const { data, isLoading } = useQuery({ queryKey: [Constants.PageID, "resource-types"], - queryFn: async () => await fetchResourceTypes(), + queryFn: async () => await fetchResourceTypes(client), refetchOnWindowFocus: false, }); diff --git a/src/components/ViewDefinition/result-panel-content.tsx b/src/components/ViewDefinition/result-panel-content.tsx index 831d8603..f3a2f2bf 100644 --- a/src/components/ViewDefinition/result-panel-content.tsx +++ b/src/components/ViewDefinition/result-panel-content.tsx @@ -1,3 +1,4 @@ +import type * as AidboxTypes from "@health-samurai/aidbox-client"; import { type AccessorKeyColumnDef, Button, @@ -12,7 +13,7 @@ import { import { useMutation } from "@tanstack/react-query"; import { Maximize2, Minimize2 } from "lucide-react"; import { useContext, useEffect, useMemo, useState } from "react"; -import { AidboxCallWithMeta } from "../../api/auth"; +import { useAidboxClient } from "../../AidboxClient"; import { ViewDefinitionContext } from "./page"; import type * as Types from "./types"; @@ -226,6 +227,8 @@ const ResultPagination = ({ }; export function ResultPanel() { + const client = useAidboxClient(); + const viewDefinitionContext = useContext(ViewDefinitionContext); const rows = viewDefinitionContext.runResult; const [isMaximized, setIsMaximized] = useState(false); @@ -254,7 +257,7 @@ export function ResultPanel() { { name: "_page", valueInteger: page }, ], }; - return AidboxCallWithMeta({ + return client.aidboxRawRequest({ method: "POST", url: "/fhir/ViewDefinition/$run", headers: { @@ -264,8 +267,8 @@ export function ResultPanel() { body: JSON.stringify(parametersPayload), }); }, - onSuccess: (data) => { - const decodedData = atob(JSON.parse(data.body).data); + onSuccess: async (data: AidboxTypes.AidboxRawResponse) => { + const decodedData = atob(JSON.parse(await data.response.text()).data); viewDefinitionContext.setRunResult(decodedData); }, onError: () => {}, diff --git a/src/components/ViewDefinition/schema-tab-content.tsx b/src/components/ViewDefinition/schema-tab-content.tsx index 5c0daaee..99835016 100644 --- a/src/components/ViewDefinition/schema-tab-content.tsx +++ b/src/components/ViewDefinition/schema-tab-content.tsx @@ -1,10 +1,11 @@ +import type * as AidboxTypes from "@health-samurai/aidbox-client"; import { FhirStructureView, TabsContent, } from "@health-samurai/react-components"; import { useQuery } from "@tanstack/react-query"; import { useContext } from "react"; -import { AidboxCallWithMeta } from "../../api/auth"; +import { useAidboxClient } from "../../AidboxClient"; import { transformSnapshotToTree } from "../../utils"; import * as Constants from "./constants"; import { ViewDefinitionResourceTypeContext } from "./page"; @@ -21,9 +22,10 @@ interface SchemaData { } const fetchSchema = async ( + client: AidboxTypes.Client, resourceType: string, ): Promise | undefined> => { - const response = await AidboxCallWithMeta({ + const response = await client.aidboxRawRequest({ method: "POST", url: "/rpc?_m=aidbox.introspector/get-schemas-by-resource-type", headers: { @@ -35,7 +37,7 @@ const fetchSchema = async ( }), }); - const data: SchemaData = JSON.parse(response.body); + const data: SchemaData = JSON.parse(await response.response.text()); if (!data?.result) return undefined; @@ -47,6 +49,8 @@ const fetchSchema = async ( }; export function SchemaTabContent() { + const client = useAidboxClient(); + const viewDefinitionTypeContext = useContext( ViewDefinitionResourceTypeContext, ); @@ -57,7 +61,7 @@ export function SchemaTabContent() { queryKey: [viewDefinitionResourceType, Constants.PageID], queryFn: () => { if (!viewDefinitionResourceType) return; - return fetchSchema(viewDefinitionResourceType); + return fetchSchema(client, viewDefinitionResourceType); }, retry: false, refetchOnWindowFocus: false, diff --git a/src/components/ViewDefinition/sql-tab-content.tsx b/src/components/ViewDefinition/sql-tab-content.tsx index 7655ef07..4ed807e7 100644 --- a/src/components/ViewDefinition/sql-tab-content.tsx +++ b/src/components/ViewDefinition/sql-tab-content.tsx @@ -1,13 +1,17 @@ +import type * as AidboxTypes from "@health-samurai/aidbox-client"; import { CodeEditor, TabsContent } from "@health-samurai/react-components"; import { useQuery } from "@tanstack/react-query"; import { useContext } from "react"; import { format as formatSQL } from "sql-formatter"; -import { AidboxCallWithMeta } from "../../api/auth"; +import { useAidboxClient } from "../../AidboxClient"; import * as Constants from "./constants"; import { ViewDefinitionContext } from "./page"; import type { ViewDefinition } from "./types"; -const fetchSQL = async (viewDefinition: ViewDefinition): Promise => { +const fetchSQL = async ( + client: AidboxTypes.Client, + viewDefinition: ViewDefinition, +): Promise => { const parametersPayload = { resourceType: "Parameters", parameter: [ @@ -18,7 +22,7 @@ const fetchSQL = async (viewDefinition: ViewDefinition): Promise => { ], }; - const response = await AidboxCallWithMeta({ + const response = await client.aidboxRawRequest({ method: "POST", url: "/fhir/ViewDefinition/$sql", headers: { @@ -28,7 +32,7 @@ const fetchSQL = async (viewDefinition: ViewDefinition): Promise => { body: JSON.stringify(parametersPayload), }); - const json = JSON.parse(response.body); + const json = JSON.parse(await response.response.text()); if (json.issue) { throw Error(`${json.issue[0]?.diagnostics || "Unknown error"}`); } @@ -44,6 +48,8 @@ const fetchSQL = async (viewDefinition: ViewDefinition): Promise => { }; export function SQLTab() { + const client = useAidboxClient(); + const viewDefinitionContext = useContext(ViewDefinitionContext); const viewDefinition = viewDefinitionContext.viewDefinition; @@ -52,7 +58,7 @@ export function SQLTab() { queryKey: [viewDefinition, Constants.PageID, "sql-tab"], queryFn: async () => { if (!viewDefinition) return ""; - return await fetchSQL(viewDefinition); + return await fetchSQL(client, viewDefinition); }, retry: false, refetchOnWindowFocus: false, From 92bcc523eeeecaad506d1c9fccfdde2101d5984d Mon Sep 17 00:00:00 2001 From: Andrey Listopadov Date: Thu, 13 Nov 2025 12:23:31 +0300 Subject: [PATCH 05/39] complete migration to the new client --- .gitignore | 1 + package.json | 13 +- pnpm-lock.yaml | 680 +++++++++++++++++- pnpm-workspace.yaml | 3 + scripts/generate-types.ts | 22 + src/AidboxClient.tsx | 6 +- src/api/auth.ts | 298 +------- src/components/ResourceBrowser/browser.tsx | 17 +- src/components/ResourceBrowser/page.tsx | 48 +- src/components/ResourceBrowser/types.tsx | 2 + src/components/ResourceEditor/action.tsx | 11 +- src/components/ResourceEditor/api.ts | 116 +-- src/components/ResourceEditor/page.tsx | 12 +- .../ResourceEditor/versions-tab.tsx | 14 +- .../ViewDefinition/editor-panel-content.tsx | 4 +- .../ViewDefinition/example-tab-content.tsx | 2 +- src/components/ViewDefinition/page.tsx | 2 +- .../ViewDefinition/resource-type-select.tsx | 2 +- .../ViewDefinition/schema-tab-content.tsx | 2 +- .../ViewDefinition/sql-tab-content.tsx | 2 +- src/components/rest/collections.tsx | 58 +- src/components/rest/left-menu.tsx | 13 +- src/routes/resource.$resourceType.index.tsx | 4 +- src/routes/resource.ViewDefinition.index.tsx | 4 +- src/routes/rest.tsx | 14 +- 25 files changed, 925 insertions(+), 425 deletions(-) create mode 100644 scripts/generate-types.ts diff --git a/.gitignore b/.gitignore index cc74ddc3..fd642397 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ /dist .DS_Store /.tanstack +/tmp diff --git a/package.json b/package.json index 5236fc5b..c025640a 100644 --- a/package.json +++ b/package.json @@ -15,13 +15,15 @@ "lint:fix": "biome check --write", "test": "echo \"Error: no test specified\" && exit 1", "all": "pnpm format && pnpm typecheck && biome check --write --diagnostic-level=error", - "hooks": "cp .hooks/* .git/hooks/" + "hooks": "cp .hooks/* .git/hooks/", + "generate-types": "pnpm exec tsx scripts/generate-types.ts" }, "keywords": [], "author": "Health Samurai", "license": "MIT", "packageManager": "pnpm@10.14.0", "devDependencies": { + "@atomic-ehr/codegen": "canary", "@biomejs/biome": "2.1.3", "@tailwindcss/vite": "^4.1.12", "@tanstack/router-plugin": "^1.131.13", @@ -36,6 +38,10 @@ "vite": "^7.1.2" }, "dependencies": { + "@git-diff-view/core": "^0.0.30", + "@git-diff-view/file": "^0.0.30", + "@git-diff-view/react": "^0.0.30", + "@health-samurai/aidbox-client": "link:../../Library/pnpm/global/5/node_modules/@health-samurai/aidbox-client", "@health-samurai/react-components": "^0.0.0-alpha.10", "@tanstack/react-query": "^5.85.3", "@tanstack/react-query-devtools": "^5.85.3", @@ -49,9 +55,6 @@ "lucide-react": "^0.539.0", "react": "^19.1.1", "react-dom": "^19.1.1", - "sql-formatter": "^15.6.9", - "@git-diff-view/core": "^0.0.30", - "@git-diff-view/file": "^0.0.30", - "@git-diff-view/react": "^0.0.30" + "sql-formatter": "^15.6.9" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 59d1c2d0..9a7242fd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,6 +4,9 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +overrides: + '@health-samurai/aidbox-client': link:../../Library/pnpm/global/5/node_modules/@health-samurai/aidbox-client + importers: .: @@ -17,6 +20,9 @@ importers: '@git-diff-view/react': specifier: ^0.0.30 version: 0.0.30(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@health-samurai/aidbox-client': + specifier: link:../../Library/pnpm/global/5/node_modules/@health-samurai/aidbox-client + version: link:../../Library/pnpm/global/5/node_modules/@health-samurai/aidbox-client '@health-samurai/react-components': specifier: ^0.0.0-alpha.10 version: 0.0.0-alpha.10(@types/react-dom@19.2.0(@types/react@19.2.0))(@types/react@19.2.0) @@ -31,7 +37,7 @@ importers: version: 1.132.23(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@tanstack/react-router-devtools': specifier: ^1.131.13 - version: 1.132.23(@tanstack/react-router@1.132.23(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@tanstack/router-core@1.132.21)(csstype@3.1.3)(jiti@2.6.0)(lightningcss@1.30.1)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.9)(tiny-invariant@1.3.3)(tsx@4.20.6) + version: 1.132.23(@tanstack/react-router@1.132.23(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@tanstack/router-core@1.132.21)(csstype@3.1.3)(jiti@2.6.0)(lightningcss@1.30.1)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.9)(tiny-invariant@1.3.3)(tsx@4.20.6)(yaml@2.8.1) '@types/js-cookie': specifier: ^3.0.6 version: 3.0.6 @@ -60,15 +66,18 @@ importers: specifier: ^15.6.9 version: 15.6.9 devDependencies: + '@atomic-ehr/codegen': + specifier: canary + version: 0.0.1-canary.20251110160104.576d657(typescript@5.9.2) '@biomejs/biome': specifier: 2.1.3 version: 2.1.3 '@tailwindcss/vite': specifier: ^4.1.12 - version: 4.1.13(vite@7.1.7(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.20.6)) + version: 4.1.13(vite@7.1.7(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.20.6)(yaml@2.8.1)) '@tanstack/router-plugin': specifier: ^1.131.13 - version: 1.132.23(@tanstack/react-router@1.132.23(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(vite@7.1.7(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.20.6)) + version: 1.132.23(@tanstack/react-router@1.132.23(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(vite@7.1.7(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.20.6)(yaml@2.8.1)) '@types/css': specifier: ^0.0.38 version: 0.0.38 @@ -83,7 +92,7 @@ importers: version: 19.2.0(@types/react@19.2.0) '@vitejs/plugin-react': specifier: ^4.7.0 - version: 4.7.0(vite@7.1.7(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.20.6)) + version: 4.7.0(vite@7.1.7(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.20.6)(yaml@2.8.1)) tailwindcss: specifier: ^4.1.12 version: 4.1.13 @@ -95,10 +104,25 @@ importers: version: 5.9.2 vite: specifier: ^7.1.2 - version: 7.1.7(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.20.6) + version: 7.1.7(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.20.6)(yaml@2.8.1) packages: + '@atomic-ehr/codegen@0.0.1-canary.20251110160104.576d657': + resolution: {integrity: sha512-25X1WJ8gd0p6Qmmx2045WEnQ+97VA7AB8MDp2HHTeZWlL1F2lyhGbYyN5flyXRvw03938fvixKHb9unHqozD0g==} + hasBin: true + + '@atomic-ehr/fhir-canonical-manager@0.0.11-canary.355d62d.20250926143544': + resolution: {integrity: sha512-3FOfV7yyPhkcQ5ug+uE7ESp2ZmM2nVTEI73geOT5uqqi3lBd+G22tZA/HVUaPm2mTbcjQ0KWERG1J+3qxzoB1g==} + hasBin: true + peerDependencies: + typescript: ^5 + + '@atomic-ehr/fhirschema@0.0.2': + resolution: {integrity: sha512-OA4CVjTUEdw43Efg5I5rj95je4GC3lRiLM/kUqadcK3Po24vnINUsB8YdOP/F3ffdUYKQcJ+z09sWQVeAC2z/A==} + peerDependencies: + typescript: ^5 + '@babel/code-frame@7.27.1': resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} @@ -534,6 +558,140 @@ packages: peerDependencies: react-hook-form: ^7.55.0 + '@inquirer/ansi@1.0.2': + resolution: {integrity: sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==} + engines: {node: '>=18'} + + '@inquirer/checkbox@4.3.1': + resolution: {integrity: sha512-rOcLotrptYIy59SGQhKlU0xBg1vvcVl2FdPIEclUvKHh0wo12OfGkId/01PIMJ/V+EimJ77t085YabgnQHBa5A==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/confirm@5.1.20': + resolution: {integrity: sha512-HDGiWh2tyRZa0M1ZnEIUCQro25gW/mN8ODByicQrbR1yHx4hT+IOpozCMi5TgBtUdklLwRI2mv14eNpftDluEw==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/core@10.3.1': + resolution: {integrity: sha512-hzGKIkfomGFPgxKmnKEKeA+uCYBqC+TKtRx5LgyHRCrF6S2MliwRIjp3sUaWwVzMp7ZXVs8elB0Tfe682Rpg4w==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/editor@4.2.22': + resolution: {integrity: sha512-8yYZ9TCbBKoBkzHtVNMF6PV1RJEUvMlhvmS3GxH4UvXMEHlS45jFyqFy0DU+K42jBs5slOaA78xGqqqWAx3u6A==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/expand@4.0.22': + resolution: {integrity: sha512-9XOjCjvioLjwlq4S4yXzhvBmAXj5tG+jvva0uqedEsQ9VD8kZ+YT7ap23i0bIXOtow+di4+u3i6u26nDqEfY4Q==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/external-editor@1.0.3': + resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/figures@1.0.15': + resolution: {integrity: sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==} + engines: {node: '>=18'} + + '@inquirer/input@4.3.0': + resolution: {integrity: sha512-h4fgse5zeGsBSW3cRQqu9a99OXRdRsNCvHoBqVmz40cjYjYFzcfwD0KA96BHIPlT7rZw0IpiefQIqXrjbzjS4Q==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/number@3.0.22': + resolution: {integrity: sha512-oAdMJXz++fX58HsIEYmvuf5EdE8CfBHHXjoi9cTcQzgFoHGZE+8+Y3P38MlaRMeBvAVnkWtAxMUF6urL2zYsbg==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/password@4.0.22': + resolution: {integrity: sha512-CbdqK1ioIr0Y3akx03k/+Twf+KSlHjn05hBL+rmubMll7PsDTGH0R4vfFkr+XrkB0FOHrjIwVP9crt49dgt+1g==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/prompts@7.10.0': + resolution: {integrity: sha512-X2HAjY9BClfFkJ2RP3iIiFxlct5JJVdaYYXhA7RKxsbc9KL+VbId79PSoUGH/OLS011NFbHHDMDcBKUj3T89+Q==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/rawlist@4.1.10': + resolution: {integrity: sha512-Du4uidsgTMkoH5izgpfyauTL/ItVHOLsVdcY+wGeoGaG56BV+/JfmyoQGniyhegrDzXpfn3D+LFHaxMDRygcAw==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/search@3.2.1': + resolution: {integrity: sha512-cKiuUvETublmTmaOneEermfG2tI9ABpb7fW/LqzZAnSv4ZaJnbEis05lOkiBuYX5hNdnX0Q9ryOQyrNidb55WA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/select@4.4.1': + resolution: {integrity: sha512-E9hbLU4XsNe2SAOSsFrtYtYQDVi1mfbqJrPDvXKnGlnRiApBdWMJz7r3J2Ff38AqULkPUD3XjQMD4492TymD7Q==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/type@3.0.10': + resolution: {integrity: sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + '@isaacs/fs-minipass@4.0.1': resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} engines: {node: '>=18.0.0'} @@ -1670,6 +1828,25 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} + ansis@4.2.0: resolution: {integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==} engines: {node: '>=14'} @@ -1715,6 +1892,13 @@ packages: caniuse-lite@1.0.30001745: resolution: {integrity: sha512-ywt6i8FzvdgrrrGbr1jZVObnVv6adj+0if2/omv9cmR2oiZs30zL4DIyaptKcbOrBdOIc74QTMoJvSE2QHh5UQ==} + chalk@5.6.2: + resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + chardet@2.1.1: + resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==} + chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} @@ -1726,6 +1910,22 @@ packages: class-variance-authority@0.7.1: resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} + cli-cursor@5.0.0: + resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} + engines: {node: '>=18'} + + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + + cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} + engines: {node: '>= 12'} + + cliui@9.0.1: + resolution: {integrity: sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==} + engines: {node: '>=20'} + clsx@2.1.1: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} @@ -1736,6 +1936,13 @@ packages: react: ^18 || ^19 || ^19.0.0-rc react-dom: ^18 || ^19 || ^19.0.0-rc + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} @@ -1857,6 +2064,12 @@ packages: embla-carousel@8.6.0: resolution: {integrity: sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA==} + emoji-regex@10.6.0: + resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + enhanced-resolve@5.18.3: resolution: {integrity: sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==} engines: {node: '>=10.13.0'} @@ -1878,6 +2091,9 @@ packages: eventemitter3@4.0.7: resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + fast-diff@1.3.0: resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} @@ -1889,6 +2105,9 @@ packages: resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} engines: {node: '>=8.6.0'} + fast-uri@3.1.0: + resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + fastq@1.19.1: resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} @@ -1914,6 +2133,14 @@ packages: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-east-asian-width@1.4.0: + resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==} + engines: {node: '>=18'} + get-nonce@1.0.1: resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} engines: {node: '>=6'} @@ -1933,10 +2160,19 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + handlebars@4.7.8: + resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} + engines: {node: '>=0.4.7'} + hasBin: true + highlight.js@11.11.1: resolution: {integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==} engines: {node: '>=12.0.0'} + iconv-lite@0.7.0: + resolution: {integrity: sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==} + engines: {node: '>=0.10.0'} + input-otp@1.4.2: resolution: {integrity: sha512-l3jWwYNvrEa6NTCt7BECfCm48GvwuZzkoeG3gBL2w4CHeOXW3eKFmf9UNYkNfYc3mxMrthMnxjIE07MT0zLBQA==} peerDependencies: @@ -1955,14 +2191,30 @@ packages: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} + is-interactive@2.0.0: + resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} + engines: {node: '>=12'} + is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} + is-unicode-supported@1.3.0: + resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} + engines: {node: '>=12'} + + is-unicode-supported@2.1.0: + resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} + engines: {node: '>=18'} + isbot@5.1.31: resolution: {integrity: sha512-DPgQshehErHAqSCKDb3rNW03pa2wS/v5evvUqtxt6TTnHRqAG8FdzcSSJs9656pK6Y+NT7K9R4acEYXLHYfpUQ==} engines: {node: '>=18'} @@ -1987,6 +2239,9 @@ packages: engines: {node: '>=6'} hasBin: true + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + json5@2.2.3: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} @@ -2059,6 +2314,10 @@ packages: lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + log-symbols@6.0.0: + resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==} + engines: {node: '>=18'} + loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true @@ -2085,6 +2344,13 @@ packages: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} + mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + minipass@7.1.2: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} @@ -2099,6 +2365,10 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + mute-stream@3.0.0: + resolution: {integrity: sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw==} + engines: {node: ^20.17.0 || >=22.9.0} + nanoid@3.3.11: resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -2108,6 +2378,9 @@ packages: resolution: {integrity: sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==} hasBin: true + neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + next-themes@0.4.6: resolution: {integrity: sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==} peerDependencies: @@ -2125,6 +2398,14 @@ packages: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} + onetime@7.0.0: + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} + engines: {node: '>=18'} + + ora@8.2.0: + resolution: {integrity: sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==} + engines: {node: '>=18'} + pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} @@ -2276,9 +2557,17 @@ packages: react: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + restore-cursor@5.1.0: + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} + engines: {node: '>=18'} + ret@0.1.15: resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==} engines: {node: '>=0.12'} @@ -2295,6 +2584,9 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + scheduler@0.26.0: resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==} @@ -2312,6 +2604,10 @@ packages: resolution: {integrity: sha512-RbcPH1n5cfwKrru7v7+zrZvjLurgHhGyso3HTyGtRivGWgYjbOmGuivCQaORNELjNONoK35nj28EoWul9sb1zQ==} engines: {node: '>=10'} + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + solid-js@1.9.9: resolution: {integrity: sha512-A0ZBPJQldAeGCTW0YRYJmt7RCeh5rbFfPZ2aOttgYnctHE7HgKeHCBB/PVc2P7eOfmNXqMFFFoYYdm3S4dcbkA==} @@ -2337,6 +2633,26 @@ packages: resolution: {integrity: sha512-r9VKnkRfKW7jbhTgytwbM+JqmFclQYN9L58Z3UTktuy9V1f1Y+rGK3t70Truh2wIOJzvZkzobAQ2PwGjjXsr6Q==} hasBin: true + stdin-discarder@0.2.2: + resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==} + engines: {node: '>=18'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.2: + resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} + engines: {node: '>=12'} + style-mod@4.1.3: resolution: {integrity: sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==} @@ -2384,6 +2700,11 @@ packages: engines: {node: '>=14.17'} hasBin: true + uglify-js@3.19.3: + resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} + engines: {node: '>=0.8.0'} + hasBin: true + unplugin@2.3.10: resolution: {integrity: sha512-6NCPkv1ClwH+/BGE9QeoTIl09nuiAt0gS28nn1PvYXsGKRwM2TCbFA2QiilmehPDTXIe684k4rZI1yl3A1PCUw==} engines: {node: '>=18.12.0'} @@ -2479,6 +2800,21 @@ packages: webpack-virtual-modules@0.6.2: resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + wordwrap@1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + + wrap-ansi@9.0.2: + resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} + engines: {node: '>=18'} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} @@ -2486,6 +2822,23 @@ packages: resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} engines: {node: '>=18'} + yaml@2.8.1: + resolution: {integrity: sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==} + engines: {node: '>= 14.6'} + hasBin: true + + yargs-parser@22.0.0: + resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==} + engines: {node: ^20.19.0 || ^22.12.0 || >=23} + + yargs@18.0.0: + resolution: {integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=23} + + yoctocolors-cjs@2.1.3: + resolution: {integrity: sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==} + engines: {node: '>=18'} + zod@3.25.76: resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} @@ -2494,6 +2847,29 @@ packages: snapshots: + '@atomic-ehr/codegen@0.0.1-canary.20251110160104.576d657(typescript@5.9.2)': + dependencies: + '@atomic-ehr/fhir-canonical-manager': 0.0.11-canary.355d62d.20250926143544(typescript@5.9.2) + '@atomic-ehr/fhirschema': 0.0.2(typescript@5.9.2) + '@inquirer/prompts': 7.10.0 + ajv: 8.17.1 + handlebars: 4.7.8 + ora: 8.2.0 + picocolors: 1.1.1 + yaml: 2.8.1 + yargs: 18.0.0 + transitivePeerDependencies: + - '@types/node' + - typescript + + '@atomic-ehr/fhir-canonical-manager@0.0.11-canary.355d62d.20250926143544(typescript@5.9.2)': + dependencies: + typescript: 5.9.2 + + '@atomic-ehr/fhirschema@0.0.2(typescript@5.9.2)': + dependencies: + typescript: 5.9.2 + '@babel/code-frame@7.27.1': dependencies: '@babel/helper-validator-identifier': 7.27.1 @@ -3008,6 +3384,103 @@ snapshots: '@standard-schema/utils': 0.3.0 react-hook-form: 7.65.0(react@19.1.1) + '@inquirer/ansi@1.0.2': {} + + '@inquirer/checkbox@4.3.1': + dependencies: + '@inquirer/ansi': 1.0.2 + '@inquirer/core': 10.3.1 + '@inquirer/figures': 1.0.15 + '@inquirer/type': 3.0.10 + yoctocolors-cjs: 2.1.3 + + '@inquirer/confirm@5.1.20': + dependencies: + '@inquirer/core': 10.3.1 + '@inquirer/type': 3.0.10 + + '@inquirer/core@10.3.1': + dependencies: + '@inquirer/ansi': 1.0.2 + '@inquirer/figures': 1.0.15 + '@inquirer/type': 3.0.10 + cli-width: 4.1.0 + mute-stream: 3.0.0 + signal-exit: 4.1.0 + wrap-ansi: 6.2.0 + yoctocolors-cjs: 2.1.3 + + '@inquirer/editor@4.2.22': + dependencies: + '@inquirer/core': 10.3.1 + '@inquirer/external-editor': 1.0.3 + '@inquirer/type': 3.0.10 + + '@inquirer/expand@4.0.22': + dependencies: + '@inquirer/core': 10.3.1 + '@inquirer/type': 3.0.10 + yoctocolors-cjs: 2.1.3 + + '@inquirer/external-editor@1.0.3': + dependencies: + chardet: 2.1.1 + iconv-lite: 0.7.0 + + '@inquirer/figures@1.0.15': {} + + '@inquirer/input@4.3.0': + dependencies: + '@inquirer/core': 10.3.1 + '@inquirer/type': 3.0.10 + + '@inquirer/number@3.0.22': + dependencies: + '@inquirer/core': 10.3.1 + '@inquirer/type': 3.0.10 + + '@inquirer/password@4.0.22': + dependencies: + '@inquirer/ansi': 1.0.2 + '@inquirer/core': 10.3.1 + '@inquirer/type': 3.0.10 + + '@inquirer/prompts@7.10.0': + dependencies: + '@inquirer/checkbox': 4.3.1 + '@inquirer/confirm': 5.1.20 + '@inquirer/editor': 4.2.22 + '@inquirer/expand': 4.0.22 + '@inquirer/input': 4.3.0 + '@inquirer/number': 3.0.22 + '@inquirer/password': 4.0.22 + '@inquirer/rawlist': 4.1.10 + '@inquirer/search': 3.2.1 + '@inquirer/select': 4.4.1 + + '@inquirer/rawlist@4.1.10': + dependencies: + '@inquirer/core': 10.3.1 + '@inquirer/type': 3.0.10 + yoctocolors-cjs: 2.1.3 + + '@inquirer/search@3.2.1': + dependencies: + '@inquirer/core': 10.3.1 + '@inquirer/figures': 1.0.15 + '@inquirer/type': 3.0.10 + yoctocolors-cjs: 2.1.3 + + '@inquirer/select@4.4.1': + dependencies: + '@inquirer/ansi': 1.0.2 + '@inquirer/core': 10.3.1 + '@inquirer/figures': 1.0.15 + '@inquirer/type': 3.0.10 + yoctocolors-cjs: 2.1.3 + + '@inquirer/type@3.0.10': {} + '@isaacs/fs-minipass@4.0.1': dependencies: minipass: 7.1.2 @@ -3948,12 +4421,12 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.1.13 '@tailwindcss/oxide-win32-x64-msvc': 4.1.13 - '@tailwindcss/vite@4.1.13(vite@7.1.7(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.20.6))': + '@tailwindcss/vite@4.1.13(vite@7.1.7(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.20.6)(yaml@2.8.1))': dependencies: '@tailwindcss/node': 4.1.13 '@tailwindcss/oxide': 4.1.13 tailwindcss: 4.1.13 - vite: 7.1.7(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.20.6) + vite: 7.1.7(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.20.6)(yaml@2.8.1) '@tanstack/history@1.132.21': {} @@ -3972,13 +4445,13 @@ snapshots: '@tanstack/query-core': 5.90.2 react: 19.1.1 - '@tanstack/react-router-devtools@1.132.23(@tanstack/react-router@1.132.23(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@tanstack/router-core@1.132.21)(csstype@3.1.3)(jiti@2.6.0)(lightningcss@1.30.1)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.9)(tiny-invariant@1.3.3)(tsx@4.20.6)': + '@tanstack/react-router-devtools@1.132.23(@tanstack/react-router@1.132.23(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@tanstack/router-core@1.132.21)(csstype@3.1.3)(jiti@2.6.0)(lightningcss@1.30.1)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.9)(tiny-invariant@1.3.3)(tsx@4.20.6)(yaml@2.8.1)': dependencies: '@tanstack/react-router': 1.132.23(react-dom@19.1.1(react@19.1.1))(react@19.1.1) - '@tanstack/router-devtools-core': 1.132.21(@tanstack/router-core@1.132.21)(csstype@3.1.3)(jiti@2.6.0)(lightningcss@1.30.1)(solid-js@1.9.9)(tiny-invariant@1.3.3)(tsx@4.20.6) + '@tanstack/router-devtools-core': 1.132.21(@tanstack/router-core@1.132.21)(csstype@3.1.3)(jiti@2.6.0)(lightningcss@1.30.1)(solid-js@1.9.9)(tiny-invariant@1.3.3)(tsx@4.20.6)(yaml@2.8.1) react: 19.1.1 react-dom: 19.1.1(react@19.1.1) - vite: 7.1.7(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.20.6) + vite: 7.1.7(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.20.6)(yaml@2.8.1) transitivePeerDependencies: - '@tanstack/router-core' - '@types/node' @@ -4030,14 +4503,14 @@ snapshots: tiny-invariant: 1.3.3 tiny-warning: 1.0.3 - '@tanstack/router-devtools-core@1.132.21(@tanstack/router-core@1.132.21)(csstype@3.1.3)(jiti@2.6.0)(lightningcss@1.30.1)(solid-js@1.9.9)(tiny-invariant@1.3.3)(tsx@4.20.6)': + '@tanstack/router-devtools-core@1.132.21(@tanstack/router-core@1.132.21)(csstype@3.1.3)(jiti@2.6.0)(lightningcss@1.30.1)(solid-js@1.9.9)(tiny-invariant@1.3.3)(tsx@4.20.6)(yaml@2.8.1)': dependencies: '@tanstack/router-core': 1.132.21 clsx: 2.1.1 goober: 2.1.16(csstype@3.1.3) solid-js: 1.9.9 tiny-invariant: 1.3.3 - vite: 7.1.7(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.20.6) + vite: 7.1.7(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.20.6)(yaml@2.8.1) optionalDependencies: csstype: 3.1.3 transitivePeerDependencies: @@ -4066,7 +4539,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/router-plugin@1.132.23(@tanstack/react-router@1.132.23(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(vite@7.1.7(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.20.6))': + '@tanstack/router-plugin@1.132.23(@tanstack/react-router@1.132.23(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(vite@7.1.7(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.20.6)(yaml@2.8.1))': dependencies: '@babel/core': 7.28.4 '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.4) @@ -4084,7 +4557,7 @@ snapshots: zod: 3.25.76 optionalDependencies: '@tanstack/react-router': 1.132.23(react-dom@19.1.1(react@19.1.1))(react@19.1.1) - vite: 7.1.7(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.20.6) + vite: 7.1.7(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.20.6)(yaml@2.8.1) transitivePeerDependencies: - supports-color @@ -4176,7 +4649,7 @@ snapshots: '@types/unist@3.0.3': {} - '@vitejs/plugin-react@4.7.0(vite@7.1.7(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.20.6))': + '@vitejs/plugin-react@4.7.0(vite@7.1.7(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.20.6)(yaml@2.8.1))': dependencies: '@babel/core': 7.28.4 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.4) @@ -4184,7 +4657,7 @@ snapshots: '@rolldown/pluginutils': 1.0.0-beta.27 '@types/babel__core': 7.20.5 react-refresh: 0.17.0 - vite: 7.1.7(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.20.6) + vite: 7.1.7(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.20.6)(yaml@2.8.1) transitivePeerDependencies: - supports-color @@ -4196,6 +4669,23 @@ snapshots: acorn@8.15.0: {} + ajv@8.17.1: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.0 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ansi-regex@5.0.1: {} + + ansi-regex@6.2.2: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@6.2.3: {} + ansis@4.2.0: {} anymatch@3.1.3: @@ -4244,6 +4734,10 @@ snapshots: caniuse-lite@1.0.30001745: {} + chalk@5.6.2: {} + + chardet@2.1.1: {} + chokidar@3.6.0: dependencies: anymatch: 3.1.3 @@ -4262,6 +4756,20 @@ snapshots: dependencies: clsx: 2.1.1 + cli-cursor@5.0.0: + dependencies: + restore-cursor: 5.1.0 + + cli-spinners@2.9.2: {} + + cli-width@4.1.0: {} + + cliui@9.0.1: + dependencies: + string-width: 7.2.0 + strip-ansi: 7.1.2 + wrap-ansi: 9.0.2 + clsx@2.1.1: {} cmdk@1.1.1(@types/react-dom@19.2.0(@types/react@19.2.0))(@types/react@19.2.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1): @@ -4276,6 +4784,12 @@ snapshots: - '@types/react' - '@types/react-dom' + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + commander@2.20.3: {} convert-source-map@2.0.0: {} @@ -4369,6 +4883,10 @@ snapshots: embla-carousel@8.6.0: {} + emoji-regex@10.6.0: {} + + emoji-regex@8.0.0: {} + enhanced-resolve@5.18.3: dependencies: graceful-fs: 4.2.11 @@ -4409,6 +4927,8 @@ snapshots: eventemitter3@4.0.7: {} + fast-deep-equal@3.1.3: {} + fast-diff@1.3.0: {} fast-equals@5.3.2: {} @@ -4421,6 +4941,8 @@ snapshots: merge2: 1.4.1 micromatch: 4.0.8 + fast-uri@3.1.0: {} + fastq@1.19.1: dependencies: reusify: 1.1.0 @@ -4438,6 +4960,10 @@ snapshots: gensync@1.0.0-beta.2: {} + get-caller-file@2.0.5: {} + + get-east-asian-width@1.4.0: {} + get-nonce@1.0.1: {} get-tsconfig@4.10.1: @@ -4454,8 +4980,21 @@ snapshots: graceful-fs@4.2.11: {} + handlebars@4.7.8: + dependencies: + minimist: 1.2.8 + neo-async: 2.6.2 + source-map: 0.6.1 + wordwrap: 1.0.0 + optionalDependencies: + uglify-js: 3.19.3 + highlight.js@11.11.1: {} + iconv-lite@0.7.0: + dependencies: + safer-buffer: 2.1.2 + input-otp@1.4.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1): dependencies: react: 19.1.1 @@ -4469,12 +5008,20 @@ snapshots: is-extglob@2.1.1: {} + is-fullwidth-code-point@3.0.0: {} + is-glob@4.0.3: dependencies: is-extglob: 2.1.1 + is-interactive@2.0.0: {} + is-number@7.0.0: {} + is-unicode-supported@1.3.0: {} + + is-unicode-supported@2.1.0: {} + isbot@5.1.31: {} jiti@2.6.0: {} @@ -4489,6 +5036,8 @@ snapshots: jsesc@3.1.0: {} + json-schema-traverse@1.0.0: {} + json5@2.2.3: {} lightningcss-darwin-arm64@1.30.1: @@ -4538,6 +5087,11 @@ snapshots: lodash@4.17.21: {} + log-symbols@6.0.0: + dependencies: + chalk: 5.6.2 + is-unicode-supported: 1.3.0 + loose-envify@1.4.0: dependencies: js-tokens: 4.0.0 @@ -4567,6 +5121,10 @@ snapshots: braces: 3.0.3 picomatch: 2.3.1 + mimic-function@5.0.1: {} + + minimist@1.2.8: {} + minipass@7.1.2: {} minizlib@3.1.0: @@ -4577,6 +5135,8 @@ snapshots: ms@2.1.3: {} + mute-stream@3.0.0: {} + nanoid@3.3.11: {} nearley@2.20.1: @@ -4586,6 +5146,8 @@ snapshots: railroad-diagrams: 1.0.0 randexp: 0.4.6 + neo-async@2.6.2: {} + next-themes@0.4.6(react-dom@19.1.1(react@19.1.1))(react@19.1.1): dependencies: react: 19.1.1 @@ -4597,6 +5159,22 @@ snapshots: object-assign@4.1.1: {} + onetime@7.0.0: + dependencies: + mimic-function: 5.0.1 + + ora@8.2.0: + dependencies: + chalk: 5.6.2 + cli-cursor: 5.0.0 + cli-spinners: 2.9.2 + is-interactive: 2.0.0 + is-unicode-supported: 2.1.0 + log-symbols: 6.0.0 + stdin-discarder: 0.2.2 + string-width: 7.2.0 + strip-ansi: 7.1.2 + pathe@2.0.3: {} picocolors@1.1.1: {} @@ -4800,8 +5378,15 @@ snapshots: tiny-invariant: 1.3.3 victory-vendor: 36.9.2 + require-from-string@2.0.2: {} + resolve-pkg-maps@1.0.0: {} + restore-cursor@5.1.0: + dependencies: + onetime: 7.0.0 + signal-exit: 4.1.0 + ret@0.1.15: {} reusify@1.1.0: {} @@ -4838,6 +5423,8 @@ snapshots: dependencies: queue-microtask: 1.2.3 + safer-buffer@2.1.2: {} + scheduler@0.26.0: {} semver@6.3.1: {} @@ -4848,6 +5435,8 @@ snapshots: seroval@1.3.2: {} + signal-exit@4.1.0: {} + solid-js@1.9.9: dependencies: csstype: 3.1.3 @@ -4870,6 +5459,28 @@ snapshots: argparse: 2.0.1 nearley: 2.20.1 + stdin-discarder@0.2.2: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@7.2.0: + dependencies: + emoji-regex: 10.6.0 + get-east-asian-width: 1.4.0 + strip-ansi: 7.1.2 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.2: + dependencies: + ansi-regex: 6.2.2 + style-mod@4.1.3: {} tailwind-merge@3.3.1: {} @@ -4912,6 +5523,9 @@ snapshots: typescript@5.9.2: {} + uglify-js@3.19.3: + optional: true + unplugin@2.3.10: dependencies: '@jridgewell/remapping': 2.3.5 @@ -4974,7 +5588,7 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - vite@7.1.7(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.20.6): + vite@7.1.7(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.20.6)(yaml@2.8.1): dependencies: esbuild: 0.25.10 fdir: 6.5.0(picomatch@4.0.3) @@ -4987,15 +5601,47 @@ snapshots: jiti: 2.6.0 lightningcss: 1.30.1 tsx: 4.20.6 + yaml: 2.8.1 w3c-keyname@2.2.8: {} webpack-virtual-modules@0.6.2: {} + wordwrap@1.0.0: {} + + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@9.0.2: + dependencies: + ansi-styles: 6.2.3 + string-width: 7.2.0 + strip-ansi: 7.1.2 + + y18n@5.0.8: {} + yallist@3.1.1: {} yallist@5.0.0: {} + yaml@2.8.1: {} + + yargs-parser@22.0.0: {} + + yargs@18.0.0: + dependencies: + cliui: 9.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + string-width: 7.2.0 + y18n: 5.0.8 + yargs-parser: 22.0.0 + + yoctocolors-cjs@2.1.3: {} + zod@3.25.76: {} zod@4.1.12: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 5b23a1c1..d59c0d6e 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,3 +1,6 @@ onlyBuiltDependencies: - '@tailwindcss/oxide' - esbuild + +overrides: + '@health-samurai/aidbox-client': link:../../Library/pnpm/global/5/node_modules/@health-samurai/aidbox-client diff --git a/scripts/generate-types.ts b/scripts/generate-types.ts new file mode 100644 index 00000000..858fe76b --- /dev/null +++ b/scripts/generate-types.ts @@ -0,0 +1,22 @@ +import { APIBuilder } from "@atomic-ehr/codegen"; + +console.log("📦 Generating FHIR R4 Core Types..."); + +const builder = new APIBuilder() + .verbose() + .throwException() + .fromPackage("hl7.fhir.r4.core", "4.0.1") + .typescript({ withDebugComment: false }) + .outputTo("./src/fhir-types") + .cleanOutput(true); + +const report = await builder.generate(); + +console.log(report); + +if (report.success) { + console.log("✅ FHIR R4 types generated successfully!"); +} else { + console.error("❌ FHIR R4 types generation failed."); + process.exit(1); +} diff --git a/src/AidboxClient.tsx b/src/AidboxClient.tsx index 40f4371e..5a81b8cc 100644 --- a/src/AidboxClient.tsx +++ b/src/AidboxClient.tsx @@ -3,7 +3,7 @@ import { makeClient } from "@health-samurai/aidbox-client"; import * as React from "react"; export const AidboxClientContext = React.createContext< - Aidbox.Client | undefined + Aidbox.AidboxClient | undefined >(undefined); export type AidboxClientProviderProps = { @@ -24,7 +24,9 @@ export function AidboxClientProvider({ ); } -export function useAidboxClient(aidboxClient?: Aidbox.Client): Aidbox.Client { +export function useAidboxClient( + aidboxClient?: Aidbox.AidboxClient, +): Aidbox.AidboxClient { const client = React.useContext(AidboxClientContext); if (aidboxClient) return aidboxClient; diff --git a/src/api/auth.ts b/src/api/auth.ts index dae44c2a..000d06c8 100644 --- a/src/api/auth.ts +++ b/src/api/auth.ts @@ -1,319 +1,39 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; -import Cookies from "js-cookie"; -import type { UIHistoryResponse } from "../shared/types"; -import { getAidboxBaseURL } from "../utils"; +import { useAidboxClient } from "../AidboxClient"; export interface UserInfo { id: string; email?: string; } -export interface AidboxRequestParams { - method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH"; - url: string; - headers?: Record; - params?: [string, string][]; - body?: string; - streamBody?: boolean; -} - -export interface AidboxResponse { - response: { - status: number; - statusText: string; - headers: Record; - body: string | ReadableStream | null; - }; - meta: { - duration: number; - request: { - method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH"; - url: string; - headers?: Record; - params?: [string, string][]; - body?: string; - }; - }; -} - -const defaultHeaders = { - "Content-Type": "application/json", - Accept: "application/json", -}; - -// A modified copy of AidboxCallWithMeta but with fixed error -// reporting, and unified types for successful response and error -// response. -export async function AidboxRequest({ - method, - url, - headers = {}, - params = [], - body, - streamBody = false, -}: AidboxRequestParams): Promise { - const startTime = Date.now(); - const baseURL = getAidboxBaseURL(); - - const urlObj = new URL(url.startsWith("/") ? url.slice(1) : url, baseURL); - params.forEach(([key, value]) => { - urlObj.searchParams.append(key, value); - }); - - const requestHeaders = { ...defaultHeaders, ...headers }; - - const response = await fetch(urlObj.toString(), { - method, - headers: requestHeaders, - body: body || null, - credentials: "include", - }); - const responseHeaders: Record = {}; - response.headers.forEach((value, key) => { - responseHeaders[key] = value; - }); - - const result: AidboxResponse = { - response: { - status: response.status, - statusText: response.statusText, - headers: responseHeaders, - body: streamBody ? response.body : await response.text(), - }, - meta: { - duration: Date.now() - startTime, - request: { - method, - url, - params, - headers: requestHeaders, - body: body || "", - }, - }, - }; - - if (!response.ok) { - if (response.status === 401 || response.status === 403) { - const encodedLocation = btoa(window.location.href); - window.location.href = `${baseURL}/auth/login?redirect_to=${encodedLocation}`; - throw Error("Authentication required", { cause: result }); - } - - throw Error(`HTTP ${response.status}: ${response.statusText}`, { - cause: result, - }); - } - - return result; -} - -export interface AidboxCallParams { - method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH"; - url: string; - headers?: Record; - params?: Record; - body?: string | object; -} - -// TODO: ditch AidboxCall and AidboxCallWithMeta in favor of -// AidboxRequest across the project. - -// assumes JSON too much -export async function AidboxCall({ - method, - url, - headers = {}, - params = {}, - body, -}: AidboxCallParams): Promise { - const baseURL = getAidboxBaseURL(); - - const urlObj = new URL(url.startsWith("/") ? url.slice(1) : url, baseURL); - Object.entries(params).forEach(([key, value]) => { - urlObj.searchParams.append(key, value); - }); - - const requestHeaders = { ...defaultHeaders, ...headers }; - - let requestBody: string | null = null; - if (body) { - if (typeof body === "string") { - requestBody = body; - } else { - requestBody = JSON.stringify(body); - } - } - - const response = await fetch(urlObj.toString(), { - method, - headers: requestHeaders, - body: requestBody, - credentials: "include", - }); - - if (!response.ok) { - if (response.status === 401 || response.status === 403) { - const encodedLocation = btoa(window.location.href); - window.location.href = `${baseURL}/auth/login?redirect_to=${encodedLocation}`; - throw new Error("Authentication required"); - } - throw Error(`HTTP ${response.status}: ${response.statusText}`, { - cause: await response.json(), - }); - } - - const contentType = response.headers.get("content-type"); - if (!contentType || !contentType.includes("application/json")) { - return null as T; - } - - return response.json() as T; -} - -// unusable errors: have to guess error content type. Hard to -// refactor, as error type is unspecified by TS -export async function AidboxCallWithMeta({ - method, - url, - headers = {}, - params = {}, - body, -}: AidboxCallParams): Promise<{ - status: number; - statusText: string; - headers: Record; - body: string; - duration: number; -}> { - const startTime = Date.now(); - const baseURL = getAidboxBaseURL(); - - const urlObj = new URL(url.startsWith("/") ? url.slice(1) : url, baseURL); - Object.entries(params).forEach(([key, value]) => { - urlObj.searchParams.append(key, value); - }); - - const requestHeaders = { ...defaultHeaders, ...headers }; - - let requestBody: string | null = null; - if (body) { - if (typeof body === "string") { - requestBody = body; - } else { - requestBody = JSON.stringify(body); - } - } - - const response = await fetch(urlObj.toString(), { - method, - headers: requestHeaders, - body: requestBody, - credentials: "include", - }); - - const duration = Date.now() - startTime; - - const responseHeaders: Record = {}; - response.headers.forEach((value, key) => { - responseHeaders[key] = value; - }); - - const bodyText = await response.text(); - - if (!response.ok) { - if (response.status === 401 || response.status === 403) { - const encodedLocation = btoa(window.location.href); - window.location.href = `${baseURL}/auth/login?redirect_to=${encodedLocation}`; - throw new Error("Authentication required"); - } - throw Error(`HTTP ${response.status}: ${response.statusText}`, { - cause: bodyText, - }); - } - - return { - status: response.status, - statusText: response.statusText, - headers: responseHeaders, - body: bodyText, - duration, - }; -} - -async function fetchUserInfo(): Promise { - const response = await fetch(`${getAidboxBaseURL()}/auth/userinfo`, { - method: "GET", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - credentials: "include", - }); - - if (!response.ok) { - const encodedLocation = btoa(window.location.href); - window.location.href = `${getAidboxBaseURL()}/auth/login?redirect_to=${encodedLocation}`; - } - - return response.json(); -} - export function useUserInfo() { + const client = useAidboxClient(); + return useQuery({ queryKey: ["userInfo"], - queryFn: fetchUserInfo, + queryFn: client.fetchUserInfo, refetchOnWindowFocus: false, }); } -async function performLogout() { - const response = await fetch(`${getAidboxBaseURL()}/auth/logout`, { - method: "POST", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - credentials: "include", - }); - - Cookies.remove("asid", { path: "/" }); - - const encodedLocation = btoa(window.location.href); - window.location.href = `${getAidboxBaseURL()}/auth/login?redirect_to=${encodedLocation}`; - - return response; -} - export function useLogout() { + const client = useAidboxClient(); const queryClient = useQueryClient(); return useMutation({ - mutationFn: performLogout, + mutationFn: client.performLogout, onSuccess: () => { queryClient.removeQueries({ queryKey: ["userInfo"] }); }, }); } -// UI History API -async function fetchUIHistory(): Promise { - const response = await AidboxCall({ - method: "GET", - url: "/ui_history", - params: { - ".type": "http", - _sort: "-_lastUpdated", - _count: "100", - }, - }); - - return response; -} - export function useUIHistory() { + const client = useAidboxClient(); + return useQuery({ queryKey: ["uiHistory"], - queryFn: fetchUIHistory, + queryFn: client.fetchUIHistory, refetchOnWindowFocus: false, staleTime: 30000, // 30 seconds }); diff --git a/src/components/ResourceBrowser/browser.tsx b/src/components/ResourceBrowser/browser.tsx index ad74eb65..9c39c40d 100644 --- a/src/components/ResourceBrowser/browser.tsx +++ b/src/components/ResourceBrowser/browser.tsx @@ -1,10 +1,11 @@ -import { AidboxCallWithMeta } from "@aidbox-ui/api/auth"; import { useLocalStorage } from "@aidbox-ui/hooks/useLocalStorage"; +import type * as AidboxTypes from "@health-samurai/aidbox-client"; import * as HSComp from "@health-samurai/react-components"; import { useQuery } from "@tanstack/react-query"; import { useNavigate } from "@tanstack/react-router"; import { Pin } from "lucide-react"; import { memo, useMemo, useState } from "react"; +import { useAidboxClient } from "../../AidboxClient"; type ResourceRow = { resourceType: string; @@ -182,23 +183,23 @@ type ResourceData = { stats: Record; }; -function useResourceData() { +function useResourceData(client: AidboxTypes.AidboxClient) { return useQuery({ queryKey: ["resource-browser-resources"], queryFn: async () => { const [resourceTypes, stats] = await Promise.all([ - AidboxCallWithMeta({ + client.aidboxRawRequest({ method: "GET", url: "/$resource-types", }), - AidboxCallWithMeta({ + client.aidboxRawRequest({ method: "GET", url: "/$resource-types-pg-stats", }), ]); return { - resources: JSON.parse(resourceTypes.body), - stats: JSON.parse(stats.body), + resources: JSON.parse(await resourceTypes.response.text()), + stats: JSON.parse(await stats.response.text()), }; }, }); @@ -261,6 +262,8 @@ function useProcessedData( } export function Browser() { + const client = useAidboxClient(); + const [selectedTab, setSelectedTab] = useLocalStorage({ key: "resource-browser-selected-tab", defaultValue: "all", @@ -280,7 +283,7 @@ export function Browser() { [favoritesRef.current], ); - const { data, isLoading } = useResourceData(); + const { data, isLoading } = useResourceData(client); const { subsets } = useProcessedData(data, favorites); const toggleFavorite = useMemo( diff --git a/src/components/ResourceBrowser/page.tsx b/src/components/ResourceBrowser/page.tsx index 56b4e2fd..ae0f6562 100644 --- a/src/components/ResourceBrowser/page.tsx +++ b/src/components/ResourceBrowser/page.tsx @@ -1,10 +1,9 @@ +import type * as AidboxTypes from "@health-samurai/aidbox-client"; import * as HSComp from "@health-samurai/react-components"; import * as ReactQuery from "@tanstack/react-query"; import * as Router from "@tanstack/react-router"; import * as Lucide from "lucide-react"; import * as React from "react"; -import * as AidboxClient from "../../api/auth"; -import { AidboxCallWithMeta } from "../../api/auth"; import * as Humanize from "../../humanize"; import * as Utils from "../../utils"; import type * as VDTypes from "../ViewDefinition/types"; @@ -131,9 +130,10 @@ export const ResourcesTabHeader = ({ }; const fetchSchemas = async ( + client: AidboxTypes.AidboxClient, resourceType: string, ): Promise | undefined> => { - const response = await AidboxCallWithMeta({ + const response = await client.aidboxRawRequest({ method: "POST", url: "/rpc?_m=aidbox.introspector/get-schemas-by-resource-type", headers: { @@ -145,7 +145,7 @@ const fetchSchemas = async ( }), }); - const data: SchemaData = JSON.parse(response.body); + const data: SchemaData = JSON.parse(await response.response.text()); if (!data?.result) return undefined; @@ -153,9 +153,10 @@ const fetchSchemas = async ( }; const fetchDefaultSchema = async ( + client: AidboxTypes.AidboxClient, resourceType: string, ): Promise => { - const schemas = await fetchSchemas(resourceType); + const schemas = await fetchSchemas(client, resourceType); if (!schemas) return undefined; @@ -262,7 +263,10 @@ type FhirBundle = { entry: { resource: T }[]; }; -const ResourcesTabContent = ({ resourceType }: Types.ResourcesPageProps) => { +const ResourcesTabContent = ({ + client, + resourceType, +}: Types.ResourcesPageProps) => { const resourcesPageContext = React.useContext(ResourcesPageContext); const navigate = Router.useNavigate(); @@ -277,16 +281,16 @@ const ResourcesTabContent = ({ resourceType }: Types.ResourcesPageProps) => { const { data, isLoading } = ReactQuery.useQuery({ queryKey: [Constants.PageID, "resource-list", decodedSearchQuery], queryFn: async () => { - const response = await AidboxClient.AidboxCallWithMeta({ + const response = await client.aidboxRawRequest({ method: "GET", url: `/fhir/${resourcesPageContext.resourceType}?${decodedSearchQuery}`, }); const bundle: FhirBundle> = JSON.parse( - response.body, + await response.response.text(), ); const data = bundle.entry.map((entry) => entry.resource); - const schema = await fetchDefaultSchema(resourceType); + const schema = await fetchDefaultSchema(client, resourceType); return resourcesWithKeys(schema, data); }, retry: false, @@ -312,7 +316,10 @@ const ResourcesTabContent = ({ resourceType }: Types.ResourcesPageProps) => { ); }; -const ProfilesTabContent = ({ resourceType }: Types.ResourcesPageProps) => { +const ProfilesTabContent = ({ + client, + resourceType, +}: Types.ResourcesPageProps) => { const [selectedProfile, setSelectedProfile] = React.useState( null, ); @@ -321,7 +328,7 @@ const ProfilesTabContent = ({ resourceType }: Types.ResourcesPageProps) => { const { data, isLoading } = ReactQuery.useQuery({ queryKey: [Constants.PageID, "resource-profiles-list"], queryFn: async () => { - const schema = await fetchSchemas(resourceType); + const schema = await fetchSchemas(client, resourceType); return schema; }, retry: false, @@ -519,12 +526,13 @@ type PartialFhirCapabilityStatement = { }; const SearchParametersTabContent = ({ + client, resourceType, }: Types.ResourcesPageProps) => { const { data, isLoading } = ReactQuery.useQuery({ queryKey: [Constants.PageID, "resource-search-parameters-list"], queryFn: async () => { - const response = await AidboxCallWithMeta({ + const response = await client.aidboxRawRequest({ method: "GET", url: "/fhir/metadata?include-custom-resources=true", headers: { @@ -532,7 +540,7 @@ const SearchParametersTabContent = ({ }, }); - const data = JSON.parse(response.body); + const data = JSON.parse(await response.response.text()); // FIXME: validate return data as PartialFhirCapabilityStatement; }, @@ -606,19 +614,25 @@ const SearchParametersTabContent = ({ ); }; -export const ResourcesPage = ({ resourceType }: Types.ResourcesPageProps) => { +export const ResourcesPage = ({ + client, + resourceType, +}: Types.ResourcesPageProps) => { return ( - + - + - + diff --git a/src/components/ResourceBrowser/types.tsx b/src/components/ResourceBrowser/types.tsx index 2a9c76b8..0efcc695 100644 --- a/src/components/ResourceBrowser/types.tsx +++ b/src/components/ResourceBrowser/types.tsx @@ -1,6 +1,8 @@ import type { Snapshot } from "@aidbox-ui/humanize"; +import type { AidboxClient } from "@health-samurai/aidbox-client"; export interface ResourcesPageProps { + client: AidboxClient; resourceType: string; } diff --git a/src/components/ResourceEditor/action.tsx b/src/components/ResourceEditor/action.tsx index d116e86c..d4980162 100644 --- a/src/components/ResourceEditor/action.tsx +++ b/src/components/ResourceEditor/action.tsx @@ -1,4 +1,5 @@ import { defaultToastPlacement } from "@aidbox-ui/components/config"; +import type * as AidboxTypes from "@health-samurai/aidbox-client"; import * as HSComp from "@health-samurai/react-components"; import { useMutation } from "@tanstack/react-query"; import * as Router from "@tanstack/react-router"; @@ -17,11 +18,13 @@ export const SaveButton = ({ id, resource, mode, + client, }: { resourceType: string; id: string | undefined; resource: string; mode: EditorMode; + client: AidboxTypes.AidboxClient; }) => { const navigate = Router.useNavigate(); const mutation = useMutation({ @@ -29,8 +32,8 @@ export const SaveButton = ({ const resource = ( mode === "json" ? JSON.parse(value) : YAML.load(value) ) as Resource; - if (id) return await updateResource(resourceType, id, resource); - return await createResource(resourceType, resource); + if (id) return await updateResource(client, resourceType, id, resource); + return await createResource(client, resourceType, resource); }, onError: Utils.onError(), onSuccess: (resource, _variables, _onMutateResult, _context) => { @@ -61,14 +64,16 @@ export const SaveButton = ({ export const DeleteButton = ({ resourceType, id, + client, }: { resourceType: string; id: string; + client: AidboxTypes.AidboxClient; }) => { const navigate = Router.useNavigate(); const mutation = useMutation({ mutationFn: async () => { - return await deleteResource(resourceType, id); + return await deleteResource(client, resourceType, id); }, onError: Utils.onError(), onSuccess: (_resource, _variables, _onMutateResult, _context) => { diff --git a/src/components/ResourceEditor/api.ts b/src/components/ResourceEditor/api.ts index b6b41418..4c3c9113 100644 --- a/src/components/ResourceEditor/api.ts +++ b/src/components/ResourceEditor/api.ts @@ -1,4 +1,4 @@ -import { AidboxCall } from "@aidbox-ui/api/auth"; +import type { AidboxClient } from "@health-samurai/aidbox-client"; export type Resource = { resourceType: string; @@ -6,15 +6,21 @@ export type Resource = { [key: string]: unknown; }; -export const fetchResource = async (resourceType: string, id: string) => { - const raw = await AidboxCall({ - method: "GET", - url: `/fhir/${resourceType}/${id}`, - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - }); +export const fetchResource = async ( + client: AidboxClient, + resourceType: string, + id: string, +) => { + const raw = ( + await client.aidboxRequest({ + method: "GET", + url: `/fhir/${resourceType}/${id}`, + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + }) + ).response.body; return raw; }; @@ -40,62 +46,80 @@ export interface HistoryEntry { } export const fetchResourceHistory = async ( + client: AidboxClient, resourceType: string, id: string, ) => { - const raw = await AidboxCall({ - method: "GET", - url: `/fhir/${resourceType}/${id}/_history`, - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - params: { _page: "1", _count: "100" }, - }); + const raw = ( + await client.aidboxRequest({ + method: "GET", + url: `/fhir/${resourceType}/${id}/_history`, + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + params: [ + ["_page", "1"], + ["_count", "100"], + ], + }) + ).response.body; return raw as HistoryBundle; }; export const createResource = async ( + client: AidboxClient, resourceType: string, resource: Resource, ) => { - const res = await AidboxCall({ - method: "POST", - url: `/fhir/${resourceType}`, - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - body: resource, - }); + const res = ( + await client.aidboxRequest({ + method: "POST", + url: `/fhir/${resourceType}`, + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + body: JSON.stringify(resource), + }) + ).response.body; return res; }; export const updateResource = async ( + client: AidboxClient, resourceType: string, id: string, resource: Resource, ) => { - const res = await AidboxCall({ - method: "PUT", - url: `/fhir/${resourceType}/${id}`, - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - body: resource, - }); + const res = ( + await client.aidboxRequest({ + method: "PUT", + url: `/fhir/${resourceType}/${id}`, + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + body: JSON.stringify(resource), + }) + ).response.body; return res; }; -export const deleteResource = async (resourceType: string, id: string) => { - const res = await AidboxCall({ - method: "DELETE", - url: `/fhir/${resourceType}/${id}`, - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - }); +export const deleteResource = async ( + client: AidboxClient, + resourceType: string, + id: string, +) => { + const res = ( + await client.aidboxRequest({ + method: "DELETE", + url: `/fhir/${resourceType}/${id}`, + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + }) + ).response.body; return res; }; diff --git a/src/components/ResourceEditor/page.tsx b/src/components/ResourceEditor/page.tsx index 4f28f1f6..aa7400a9 100644 --- a/src/components/ResourceEditor/page.tsx +++ b/src/components/ResourceEditor/page.tsx @@ -3,6 +3,7 @@ import { useQuery } from "@tanstack/react-query"; import type * as Router from "@tanstack/react-router"; import * as YAML from "js-yaml"; import React from "react"; +import { useAidboxClient } from "../../AidboxClient"; import { DeleteButton, SaveButton } from "./action"; import { fetchResource, type Resource } from "./api"; import { EditorTab } from "./editor-tab"; @@ -23,6 +24,8 @@ interface ResourceEditorPageProps { export const ResourceEditorPageWithLoader = ( props: ResourceEditorPageProps, ) => { + const client = useAidboxClient(); + const { resourceType, id } = props; const { @@ -34,7 +37,7 @@ export const ResourceEditorPageWithLoader = ( queryKey: [pageId, resourceType, id], queryFn: async () => { if (!id) throw new Error("Impossible"); - return await fetchResource(resourceType, id); + return await fetchResource(client, resourceType, id); }, retry: false, }); @@ -73,6 +76,8 @@ export const ResourceEditorPage = ({ navigate, initialResource, }: ResourceEditorPageProps & { initialResource: Resource }) => { + const client = useAidboxClient(); + const [resource, setResource] = React.useState(initialResource); const [resourceText, setResourceText] = React.useState(() => { if (mode === "yaml") { @@ -142,6 +147,7 @@ export const ResourceEditorPage = ({ id={id} resource={resourceText} mode={mode} + client={client} /> ), }, @@ -159,7 +165,9 @@ export const ResourceEditorPage = ({ ), }); actions.push({ - content: , + content: ( + + ), }); } diff --git a/src/components/ResourceEditor/versions-tab.tsx b/src/components/ResourceEditor/versions-tab.tsx index d171bd7c..d26991c9 100644 --- a/src/components/ResourceEditor/versions-tab.tsx +++ b/src/components/ResourceEditor/versions-tab.tsx @@ -1,9 +1,9 @@ -import { AidboxCallWithMeta } from "@aidbox-ui/api/auth"; import { DiffView } from "@git-diff-view/react"; import * as HSComp from "@health-samurai/react-components"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import * as YAML from "js-yaml"; import React from "react"; +import { useAidboxClient } from "../../AidboxClient"; import * as utils from "../../api/utils"; import { diff } from "../../utils/diff"; import { traverseTree } from "../../utils/tree-walker"; @@ -85,6 +85,8 @@ const VersionDiffDialog = ({ openState: OpenState; onOpenChange: (open: OpenState) => void; }) => { + const client = useAidboxClient(); + const diff = generateDiffFile( "prev.json", JSON.stringify(previous, null, " "), @@ -101,7 +103,7 @@ const VersionDiffDialog = ({ const mutation = useMutation({ mutationFn: (resource: string) => { - return AidboxCallWithMeta({ + return client.aidboxRequest({ method: "PUT", url: `/fhir/${resourceType}/${resourceId}`, headers: { @@ -179,6 +181,8 @@ const VersionViewDialog = ({ openState: OpenState; onOpenStateChange: (open: OpenState) => void; }) => { + const client = useAidboxClient(); + const queryClient = useQueryClient(); const [mode, setMode] = React.useState("json"); @@ -186,7 +190,7 @@ const VersionViewDialog = ({ const mutation = useMutation({ mutationFn: (resource: string) => { - return AidboxCallWithMeta({ + return client.aidboxRequest({ method: "PUT", url: `/fhir/${resourceType}/${resourceId}`, headers: { @@ -422,6 +426,8 @@ const calculateAffectedAttributes = ( }; export const VersionsTab = ({ id, resourceType }: VersionsTabProps) => { + const client = useAidboxClient(); + const [history, setHistory] = React.useState(); const { @@ -431,7 +437,7 @@ export const VersionsTab = ({ id, resourceType }: VersionsTabProps) => { } = useQuery({ queryKey: [pageId, resourceType, id, "history"], queryFn: async () => { - return await fetchResourceHistory(resourceType, id); + return await fetchResourceHistory(client, resourceType, id); }, }); diff --git a/src/components/ViewDefinition/editor-panel-content.tsx b/src/components/ViewDefinition/editor-panel-content.tsx index 0a78ea3a..6b2ca893 100644 --- a/src/components/ViewDefinition/editor-panel-content.tsx +++ b/src/components/ViewDefinition/editor-panel-content.tsx @@ -40,7 +40,7 @@ export const EditorHeaderMenu = () => { export const EditorPanelActions = ({ client, }: { - client: AidboxType.Client; + client: AidboxType.AidboxClient; }) => { const navigate = useNavigate({ from: "/resource/$resourceType/create" }); const viewDefinitionContext = React.useContext(ViewDefinitionContext); @@ -185,7 +185,7 @@ export const EditorPanelActions = ({ }; export const EditorPanelContent = () => { - const aidboxClient: AidboxType.Client = useAidboxClient(); + const aidboxClient: AidboxType.AidboxClient = useAidboxClient(); const navigate = useNavigate(); diff --git a/src/components/ViewDefinition/example-tab-content.tsx b/src/components/ViewDefinition/example-tab-content.tsx index c3fc0eda..d81cf633 100644 --- a/src/components/ViewDefinition/example-tab-content.tsx +++ b/src/components/ViewDefinition/example-tab-content.tsx @@ -21,7 +21,7 @@ import { import { SearchBar } from "./search-bar"; const searchResources = async ( - client: AidboxTypes.Client, + client: AidboxTypes.AidboxClient, resourceType: string, searchParams: string, ): Promise[]> => { diff --git a/src/components/ViewDefinition/page.tsx b/src/components/ViewDefinition/page.tsx index bf758606..b4eee908 100644 --- a/src/components/ViewDefinition/page.tsx +++ b/src/components/ViewDefinition/page.tsx @@ -9,7 +9,7 @@ import { InfoPanel } from "./info-panel"; import { ResultPanel } from "./result-panel-content"; import type * as Types from "./types"; -const fetchViewDefinition = (client: AidboxType.Client, id: string) => { +const fetchViewDefinition = (client: AidboxType.AidboxClient, id: string) => { return client.aidboxRequest({ method: "GET", url: `/fhir/ViewDefinition/${id}`, diff --git a/src/components/ViewDefinition/resource-type-select.tsx b/src/components/ViewDefinition/resource-type-select.tsx index fbb85925..0f126aa8 100644 --- a/src/components/ViewDefinition/resource-type-select.tsx +++ b/src/components/ViewDefinition/resource-type-select.tsx @@ -7,7 +7,7 @@ import * as Constants from "./constants"; import { ViewDefinitionResourceTypeContext } from "./page"; import type * as Types from "./types"; -const fetchResourceTypes = async (client: AidboxTypes.Client) => { +const fetchResourceTypes = async (client: AidboxTypes.AidboxClient) => { return ( await client.aidboxRequest({ method: "GET", diff --git a/src/components/ViewDefinition/schema-tab-content.tsx b/src/components/ViewDefinition/schema-tab-content.tsx index 99835016..1e0e10aa 100644 --- a/src/components/ViewDefinition/schema-tab-content.tsx +++ b/src/components/ViewDefinition/schema-tab-content.tsx @@ -22,7 +22,7 @@ interface SchemaData { } const fetchSchema = async ( - client: AidboxTypes.Client, + client: AidboxTypes.AidboxClient, resourceType: string, ): Promise | undefined> => { const response = await client.aidboxRawRequest({ diff --git a/src/components/ViewDefinition/sql-tab-content.tsx b/src/components/ViewDefinition/sql-tab-content.tsx index 4ed807e7..bf474bbf 100644 --- a/src/components/ViewDefinition/sql-tab-content.tsx +++ b/src/components/ViewDefinition/sql-tab-content.tsx @@ -9,7 +9,7 @@ import { ViewDefinitionContext } from "./page"; import type { ViewDefinition } from "./types"; const fetchSQL = async ( - client: AidboxTypes.Client, + client: AidboxTypes.AidboxClient, viewDefinition: ViewDefinition, ): Promise => { const parametersPayload = { diff --git a/src/components/rest/collections.tsx b/src/components/rest/collections.tsx index aae0b1c7..4ac09ee8 100644 --- a/src/components/rest/collections.tsx +++ b/src/components/rest/collections.tsx @@ -1,3 +1,4 @@ +import type * as AidboxTypes from "@health-samurai/aidbox-client"; import * as ReactComponents from "@health-samurai/react-components"; import { type QueryClient, @@ -6,7 +7,7 @@ import { } from "@tanstack/react-query"; import * as Lucide from "lucide-react"; import * as React from "react"; -import * as Auth from "../../api/auth"; +import { useAidboxClient } from "../../AidboxClient"; import { useLocalStorage } from "../../hooks"; import * as Utils from "../../utils"; import { parseHttpRequest } from "../../utils"; @@ -27,16 +28,21 @@ type FhirSearchBundle = { }[]; }; -export async function getCollectionsEntries(): Promise { - const response = await Auth.AidboxCallWithMeta({ +export async function getCollectionsEntries( + client: AidboxTypes.AidboxClient, +): Promise { + const response = await client.aidboxRawRequest({ method: "GET", url: `/ui_snippet`, }); - const bundle = JSON.parse(response.body) as FhirSearchBundle; + const bundle = JSON.parse( + await response.response.text(), + ) as FhirSearchBundle; return bundle.entry?.map((entry) => entry.resource) ?? []; } async function SaveRequest( + client: AidboxTypes.AidboxClient, tab: Tab, queryClient: QueryClient, collectionEntries: CollectionEntry[], @@ -77,7 +83,7 @@ async function SaveRequest( snippetId = tab.id; } - const result = await Auth.AidboxCallWithMeta({ + const result = await client.aidboxRequest({ method: "PUT", url: `/ui_snippet/${snippetId}`, body: JSON.stringify({ @@ -122,6 +128,7 @@ export const SaveButton = ({ setTabs: (tabs: Tab[]) => void; setLeftMenuOpen: (open: boolean) => void; }) => { + const client = useAidboxClient(); const queryClient = useQueryClient(); return ( @@ -129,6 +136,7 @@ export const SaveButton = ({ variant="secondary" onClick={() => { SaveRequest( + client, tab, queryClient, collectionEntries.data ?? [], @@ -180,6 +188,7 @@ export const SaveButton = ({ key={collectionName} onClick={() => { SaveRequest( + client, tab, queryClient, collectionEntries.data ?? [], @@ -202,6 +211,7 @@ export const SaveButton = ({ variant="link" onClick={() => { SaveRequest( + client, tab, queryClient, collectionEntries.data ?? [], @@ -284,6 +294,7 @@ function buildTreeView( } async function handleAddNewCollectionEntry( + client: AidboxTypes.AidboxClient, collectionName: string, queryClient: QueryClient, setSelectedCollectionItemId: (id: string) => void, @@ -291,7 +302,7 @@ async function handleAddNewCollectionEntry( tabs: Tab[], ) { const newTab = ActiveTabs.addTab(tabs, setTabs); - await Auth.AidboxCallWithMeta({ + await client.aidboxRequest({ method: "PUT", url: `/ui_snippet/${newTab.id}`, body: JSON.stringify({ @@ -305,13 +316,14 @@ async function handleAddNewCollectionEntry( } async function handleDeleteSnippet( + client: AidboxTypes.AidboxClient, itemData: ReactComponents.TreeViewItem, queryClient: QueryClient, _tabs: Tab[], _setTabs: (val: Tab[] | ((prev: Tab[]) => Tab[])) => void, ) { if (itemData?.meta?.id) { - await Auth.AidboxCallWithMeta({ + await client.aidboxRequest({ method: "DELETE", url: `/ui_snippet/${itemData.meta.id}`, }); @@ -321,18 +333,17 @@ async function handleDeleteSnippet( } async function handleDeleteCollection( + client: AidboxTypes.AidboxClient, itemData: ReactComponents.TreeViewItem, queryClient: QueryClient, ) { - await Auth.AidboxCallWithMeta({ + await client.aidboxRequest({ method: "DELETE", url: `/ui_snippet`, headers: { "x-conditional-delete": "remove-all", }, - params: { - id: itemData.children?.join(",") ?? "", - }, + params: [["id", itemData.children?.join(",") ?? ""]], }); queryClient.invalidateQueries({ queryKey: ["rest-console-collections"] }); } @@ -348,6 +359,7 @@ function CollectionMoreButton({ tree: ReactComponents.TreeInstance>; itemId: string; }) { + const client = useAidboxClient(); const [isAlertDialogOpen, setIsAlertDialogOpen] = React.useState(false); return ( @@ -402,7 +414,7 @@ function CollectionMoreButton({ variant="primary" danger onClick={() => { - handleDeleteCollection(itemData, queryClient); + handleDeleteCollection(client, itemData, queryClient); setIsAlertDialogOpen(false); }} asChild @@ -431,6 +443,7 @@ function SnippetMoreButton({ setTabs: (val: Tab[] | ((prev: Tab[]) => Tab[])) => void; tree: ReactComponents.TreeInstance>; }) { + const client = useAidboxClient(); const [isAlertDialogOpen, setIsAlertDialogOpen] = React.useState(false); return ( @@ -489,7 +502,13 @@ function SnippetMoreButton({ variant="primary" danger onClick={() => { - handleDeleteSnippet(itemData, queryClient, tabs, setTabs); + handleDeleteSnippet( + client, + itemData, + queryClient, + tabs, + setTabs, + ); setIsAlertDialogOpen(false); }} asChild @@ -506,6 +525,7 @@ function SnippetMoreButton({ } function customItemView( + client: AidboxTypes.AidboxClient, item: ReactComponents.ItemInstance>, setTabs: (val: Tab[] | ((prev: Tab[]) => Tab[])) => void, tabs: Tab[], @@ -541,6 +561,7 @@ function customItemView( e.stopPropagation(); e.preventDefault(); handleAddNewCollectionEntry( + client, itemData?.name, queryClient, setSelectedCollectionItemId, @@ -637,6 +658,7 @@ const NoCollectionsView = ({ setTabs: (tabs: Tab[]) => void; tabs: Tab[]; }) => { + const client = useAidboxClient(); const queryClient = useQueryClient(); if (selectedTab) { return ( @@ -649,6 +671,7 @@ const NoCollectionsView = ({ variant="link" onClick={() => SaveRequest( + client, selectedTab, queryClient, collectionEntries, @@ -671,13 +694,14 @@ const NoCollectionsView = ({ }; async function handleRenameSnippet( + client: AidboxTypes.AidboxClient, item: ReactComponents.ItemInstance>, newTitle: string, queryClient: QueryClient, ) { if (item.isFolder()) { const snippetIds = item.getChildren().map((child) => child.getId()); - await Auth.AidboxCallWithMeta({ + await client.aidboxRequest({ method: "POST", url: `/`, body: JSON.stringify({ @@ -696,7 +720,7 @@ async function handleRenameSnippet( }), }); } else { - await Auth.AidboxCallWithMeta({ + await client.aidboxRequest({ method: "PATCH", url: `/ui_snippet/${item.getItemData().meta?.id}`, body: JSON.stringify({ @@ -719,6 +743,7 @@ export const CollectionsView = ({ setSelectedCollectionItemId: (id: string) => void; selectedCollectionItemId: string | undefined; }) => { + const client = useAidboxClient(); const [pinnedCollections, setPinnedCollections] = useLocalStorage({ key: "rest-console-pinned-collections", defaultValue: [], @@ -751,10 +776,11 @@ export const CollectionsView = ({ rootItemId="root" items={tree} onRename={(item, newTitle) => { - handleRenameSnippet(item, newTitle, queryClient); + handleRenameSnippet(client, item, newTitle, queryClient); }} customItemView={(data, tree) => customItemView( + client, data, setTabs, tabs, diff --git a/src/components/rest/left-menu.tsx b/src/components/rest/left-menu.tsx index f2ceda15..99be8e68 100644 --- a/src/components/rest/left-menu.tsx +++ b/src/components/rest/left-menu.tsx @@ -1,3 +1,4 @@ +// import type { BundleEntry } from "@fhir-types/hl7-fhir-r4-core"; import { Button, Command, @@ -28,6 +29,16 @@ function cn(...inputs: (string | undefined | boolean | null)[]) { return inputs.filter(Boolean).join(" "); } +// FIXME: placeholder until typegen is a thing +interface BundleEntry { + fullUrl?: string; + link?: unknown[]; + request?: unknown; + resource?: unknown; + response?: unknown; + search?: unknown; +} + // ============================================================================= // STYLES // ============================================================================= @@ -386,7 +397,7 @@ export function LeftMenu({ // Group history items by time const groupedHistory = React.useMemo(() => { if (!historyData?.entry) return {}; - return groupHistoryByTime(historyData.entry.map((entry) => entry.resource)); + return groupHistoryByTime(historyData.entry.map((entry: BundleEntry) => entry.resource)); }, [historyData]); // Helper function to sort group keys in chronological order diff --git a/src/routes/resource.$resourceType.index.tsx b/src/routes/resource.$resourceType.index.tsx index 31ab3ddb..0b221ee3 100644 --- a/src/routes/resource.$resourceType.index.tsx +++ b/src/routes/resource.$resourceType.index.tsx @@ -1,4 +1,5 @@ import { createFileRoute } from "@tanstack/react-router"; +import { useAidboxClient } from "../AidboxClient"; import { ResourcesPage } from "../components/ResourceBrowser/page"; export const Route = createFileRoute("/resource/$resourceType/")({ @@ -23,5 +24,6 @@ export const Route = createFileRoute("/resource/$resourceType/")({ function RouteComponent() { const { resourceType } = Route.useParams(); - return ; + const client = useAidboxClient(); + return ; } diff --git a/src/routes/resource.ViewDefinition.index.tsx b/src/routes/resource.ViewDefinition.index.tsx index b37b7642..c3df437d 100644 --- a/src/routes/resource.ViewDefinition.index.tsx +++ b/src/routes/resource.ViewDefinition.index.tsx @@ -1,4 +1,5 @@ import { createFileRoute } from "@tanstack/react-router"; +import { useAidboxClient } from "../AidboxClient"; import { ResourcesPage } from "../components/ResourceBrowser/page"; export const Route = createFileRoute("/resource/ViewDefinition/")({ @@ -16,5 +17,6 @@ export const Route = createFileRoute("/resource/ViewDefinition/")({ }); function RouteComponent() { - return ; + const client = useAidboxClient(); + return ; } diff --git a/src/routes/rest.tsx b/src/routes/rest.tsx index bd406d82..2c092902 100644 --- a/src/routes/rest.tsx +++ b/src/routes/rest.tsx @@ -722,7 +722,7 @@ function handleSendRequest( queryClient: QueryClient, setIsLoading: (loading: boolean) => void, setTabs: (tabs: Tab[] | ((tabs: Tab[]) => Tab[])) => void, - aidboxClient: AidboxType.Client, + aidboxClient: AidboxType.AidboxClient, ) { const headers = selectedTab.headers @@ -846,7 +846,7 @@ function formatRequestAsHttpCommand(tab: Tab): string { async function saveToUIHistory( tab: Tab, queryClient: QueryClient, - aidboxClient: AidboxType.Client, + aidboxClient: AidboxType.AidboxClient, ): Promise { try { const historyId = crypto.randomUUID(); @@ -892,7 +892,7 @@ function SendButton( } function RouteComponent() { - const aidboxClient = useAidboxClient(); + const client = useAidboxClient(); const [tabs, setTabs] = useLocalStorage({ key: REST_CONSOLE_TABS_KEY, @@ -957,7 +957,7 @@ function RouteComponent() { queryClient, setIsLoading, setTabs, - aidboxClient, + client, ); } }; @@ -966,7 +966,7 @@ function RouteComponent() { return () => { document.removeEventListener("keydown", handleKeyDown); }; - }, [selectedTab, queryClient, setTabs, aidboxClient]); + }, [selectedTab, queryClient, setTabs, client]); function handleTabMethodChange(method: string) { setRequestLineVersion(crypto.randomUUID()); @@ -1198,7 +1198,7 @@ function RouteComponent() { const collectionEntries = useQuery({ queryKey: ["rest-console-collections"], - queryFn: RestCollections.getCollectionsEntries, + queryFn: () => RestCollections.getCollectionsEntries(client), refetchOnWindowFocus: false, }); @@ -1244,7 +1244,7 @@ function RouteComponent() { queryClient, setIsLoading, setTabs, - aidboxClient, + client, ) } /> From 358d68d4ee076cd559afc1d21a8d38c6e316d9fe Mon Sep 17 00:00:00 2001 From: Andrey Listopadov Date: Thu, 13 Nov 2025 12:23:31 +0300 Subject: [PATCH 06/39] use json method to parse response body --- src/components/ResourceBrowser/browser.tsx | 4 ++-- src/components/ResourceBrowser/page.tsx | 9 ++++----- .../ViewDefinition/editor-panel-content.tsx | 2 +- .../ViewDefinition/result-panel-content.tsx | 2 +- .../ViewDefinition/schema-tab-content.tsx | 2 +- .../ViewDefinition/sql-tab-content.tsx | 2 +- src/components/rest/collections.tsx | 5 ++--- src/components/rest/left-menu.tsx | 16 +++++++++------- 8 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/components/ResourceBrowser/browser.tsx b/src/components/ResourceBrowser/browser.tsx index 9c39c40d..11ffde00 100644 --- a/src/components/ResourceBrowser/browser.tsx +++ b/src/components/ResourceBrowser/browser.tsx @@ -198,8 +198,8 @@ function useResourceData(client: AidboxTypes.AidboxClient) { }), ]); return { - resources: JSON.parse(await resourceTypes.response.text()), - stats: JSON.parse(await stats.response.text()), + resources: await resourceTypes.response.json(), + stats: await stats.response.json(), }; }, }); diff --git a/src/components/ResourceBrowser/page.tsx b/src/components/ResourceBrowser/page.tsx index ae0f6562..9c856ce0 100644 --- a/src/components/ResourceBrowser/page.tsx +++ b/src/components/ResourceBrowser/page.tsx @@ -145,7 +145,7 @@ const fetchSchemas = async ( }), }); - const data: SchemaData = JSON.parse(await response.response.text()); + const data: SchemaData = await response.response.json(); if (!data?.result) return undefined; @@ -285,9 +285,8 @@ const ResourcesTabContent = ({ method: "GET", url: `/fhir/${resourcesPageContext.resourceType}?${decodedSearchQuery}`, }); - const bundle: FhirBundle> = JSON.parse( - await response.response.text(), - ); + const bundle: FhirBundle> = + await response.response.json(); const data = bundle.entry.map((entry) => entry.resource); const schema = await fetchDefaultSchema(client, resourceType); @@ -540,7 +539,7 @@ const SearchParametersTabContent = ({ }, }); - const data = JSON.parse(await response.response.text()); + const data = await response.response.json(); // FIXME: validate return data as PartialFhirCapabilityStatement; }, diff --git a/src/components/ViewDefinition/editor-panel-content.tsx b/src/components/ViewDefinition/editor-panel-content.tsx index 6b2ca893..f6a7670b 100644 --- a/src/components/ViewDefinition/editor-panel-content.tsx +++ b/src/components/ViewDefinition/editor-panel-content.tsx @@ -119,7 +119,7 @@ export const EditorPanelActions = ({ }); }, onSuccess: async (data: AidboxType.AidboxRawResponse) => { - const body = JSON.parse(await data.response.text()); + const body = await data.response.json(); const decodedData = atob(body.data); viewDefinitionContext.setRunResult(decodedData); HSComp.toast.success("ViewDefinition run successfully", { diff --git a/src/components/ViewDefinition/result-panel-content.tsx b/src/components/ViewDefinition/result-panel-content.tsx index f3a2f2bf..ee478fc5 100644 --- a/src/components/ViewDefinition/result-panel-content.tsx +++ b/src/components/ViewDefinition/result-panel-content.tsx @@ -268,7 +268,7 @@ export function ResultPanel() { }); }, onSuccess: async (data: AidboxTypes.AidboxRawResponse) => { - const decodedData = atob(JSON.parse(await data.response.text()).data); + const decodedData = atob((await data.response.json()).data); viewDefinitionContext.setRunResult(decodedData); }, onError: () => {}, diff --git a/src/components/ViewDefinition/schema-tab-content.tsx b/src/components/ViewDefinition/schema-tab-content.tsx index 1e0e10aa..36870434 100644 --- a/src/components/ViewDefinition/schema-tab-content.tsx +++ b/src/components/ViewDefinition/schema-tab-content.tsx @@ -37,7 +37,7 @@ const fetchSchema = async ( }), }); - const data: SchemaData = JSON.parse(await response.response.text()); + const data: SchemaData = await response.response.json(); if (!data?.result) return undefined; diff --git a/src/components/ViewDefinition/sql-tab-content.tsx b/src/components/ViewDefinition/sql-tab-content.tsx index bf474bbf..62745a36 100644 --- a/src/components/ViewDefinition/sql-tab-content.tsx +++ b/src/components/ViewDefinition/sql-tab-content.tsx @@ -32,7 +32,7 @@ const fetchSQL = async ( body: JSON.stringify(parametersPayload), }); - const json = JSON.parse(await response.response.text()); + const json = await response.response.json(); if (json.issue) { throw Error(`${json.issue[0]?.diagnostics || "Unknown error"}`); } diff --git a/src/components/rest/collections.tsx b/src/components/rest/collections.tsx index 4ac09ee8..4e8e862b 100644 --- a/src/components/rest/collections.tsx +++ b/src/components/rest/collections.tsx @@ -35,9 +35,8 @@ export async function getCollectionsEntries( method: "GET", url: `/ui_snippet`, }); - const bundle = JSON.parse( - await response.response.text(), - ) as FhirSearchBundle; + const bundle: FhirSearchBundle = + await response.response.json(); return bundle.entry?.map((entry) => entry.resource) ?? []; } diff --git a/src/components/rest/left-menu.tsx b/src/components/rest/left-menu.tsx index 99be8e68..b8bc1ed3 100644 --- a/src/components/rest/left-menu.tsx +++ b/src/components/rest/left-menu.tsx @@ -31,12 +31,12 @@ function cn(...inputs: (string | undefined | boolean | null)[]) { // FIXME: placeholder until typegen is a thing interface BundleEntry { - fullUrl?: string; - link?: unknown[]; - request?: unknown; - resource?: unknown; - response?: unknown; - search?: unknown; + fullUrl?: string; + link?: unknown[]; + request?: unknown; + resource?: unknown; + response?: unknown; + search?: unknown; } // ============================================================================= @@ -397,7 +397,9 @@ export function LeftMenu({ // Group history items by time const groupedHistory = React.useMemo(() => { if (!historyData?.entry) return {}; - return groupHistoryByTime(historyData.entry.map((entry: BundleEntry) => entry.resource)); + return groupHistoryByTime( + historyData.entry.map((entry: BundleEntry) => entry.resource), + ); }, [historyData]); // Helper function to sort group keys in chronological order From 824affe92c55d59a1065adad66df71555814f547 Mon Sep 17 00:00:00 2001 From: Andrey Listopadov Date: Fri, 14 Nov 2025 15:13:28 +0300 Subject: [PATCH 07/39] update to a newer client Co-authored-by: Aleksandr Penskoi --- src/AidboxClient.tsx | 19 ++++++++++++++++++- src/api/auth.ts | 8 +++++++- .../ViewDefinition/example-tab-content.tsx | 2 -- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/AidboxClient.tsx b/src/AidboxClient.tsx index 5a81b8cc..b822c8b7 100644 --- a/src/AidboxClient.tsx +++ b/src/AidboxClient.tsx @@ -1,5 +1,6 @@ import type * as Aidbox from "@health-samurai/aidbox-client"; import { makeClient } from "@health-samurai/aidbox-client"; +import { redirect } from "@tanstack/react-router"; import * as React from "react"; export const AidboxClientContext = React.createContext< @@ -11,11 +12,27 @@ export type AidboxClientProviderProps = { children: React.ReactNode; }; +function makeAuthHandler(baseurl: string) { + return (response: Aidbox.AidboxRawResponse) => { + if (response.response.status === 401 || response.response.status === 403) { + const encodedLocation = btoa(window.location.href); + const redirectTo = `${baseurl}/auth/login?redirect_to=${encodedLocation}`; + window.location.href = redirectTo + // FIXME: doesn't work without window.location.href + throw redirect({href: redirectTo}); + } + return response; + } +} + export function AidboxClientProvider({ baseurl, children, }: AidboxClientProviderProps): React.JSX.Element { - const client = makeClient({ baseurl }); + const client = makeClient({ + baseurl, + onRawResponseHook: makeAuthHandler(baseurl) + }); return ( diff --git a/src/api/auth.ts b/src/api/auth.ts index 000d06c8..6bf9960c 100644 --- a/src/api/auth.ts +++ b/src/api/auth.ts @@ -1,4 +1,5 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; +import { redirect } from "@tanstack/react-router"; import { useAidboxClient } from "../AidboxClient"; export interface UserInfo { @@ -24,7 +25,12 @@ export function useLogout() { mutationFn: client.performLogout, onSuccess: () => { queryClient.removeQueries({ queryKey: ["userInfo"] }); - }, + const encodedLocation = btoa(window.location.href); + const redirectTo = `${client.getAidboxBaseUrl()}/auth/login?redirect_to=${encodedLocation}`; + window.location.href = redirectTo; + // FIXME: doesn't work without window.location.href + throw redirect({href: redirectTo}); + } }); } diff --git a/src/components/ViewDefinition/example-tab-content.tsx b/src/components/ViewDefinition/example-tab-content.tsx index d81cf633..d641a493 100644 --- a/src/components/ViewDefinition/example-tab-content.tsx +++ b/src/components/ViewDefinition/example-tab-content.tsx @@ -29,8 +29,6 @@ const searchResources = async ( ? `/fhir/${resourceType}?${searchParams}` : `/fhir/${resourceType}`; - console.log(url); - const response = await client.aidboxRequest<{ entry?: Array<{ resource: Record }>; }>({ From a16acd72e8e7624b2ab141abaa1783a9b1503a27 Mon Sep 17 00:00:00 2001 From: Aleksandr Penskoi Date: Fri, 14 Nov 2025 13:27:38 +0100 Subject: [PATCH 08/39] Force to use codegen generated ViewDefinition. --- .gitignore | 1 + biome.json | 3 +- package.json | 4 +- pnpm-lock.yaml | 26 +-- scripts/generate-types.ts | 15 +- .../editor-code-tab-content.tsx | 3 +- .../editor-form-tab-content.tsx | 17 +- .../ViewDefinition/editor-panel-content.tsx | 8 +- src/components/ViewDefinition/page.tsx | 10 +- .../ViewDefinition/result-panel-content.tsx | 3 +- .../ViewDefinition/sql-tab-content.tsx | 2 +- src/components/ViewDefinition/types.tsx | 43 +---- src/fhir-types/hl7-fhir-r5-core/Address.ts | 32 ++++ src/fhir-types/hl7-fhir-r5-core/Age.ts | 11 ++ src/fhir-types/hl7-fhir-r5-core/Annotation.ts | 20 +++ src/fhir-types/hl7-fhir-r5-core/Attachment.ts | 37 +++++ .../hl7-fhir-r5-core/Availability.ts | 29 ++++ .../hl7-fhir-r5-core/BackboneElement.ts | 14 ++ .../hl7-fhir-r5-core/BackboneType.ts | 14 ++ src/fhir-types/hl7-fhir-r5-core/Base.ts | 7 + .../hl7-fhir-r5-core/CanonicalResource.ts | 53 ++++++ .../hl7-fhir-r5-core/CodeableConcept.ts | 16 ++ .../hl7-fhir-r5-core/CodeableReference.ts | 17 ++ src/fhir-types/hl7-fhir-r5-core/Coding.ts | 21 +++ .../hl7-fhir-r5-core/ContactDetail.ts | 16 ++ .../hl7-fhir-r5-core/ContactPoint.ts | 22 +++ src/fhir-types/hl7-fhir-r5-core/Count.ts | 11 ++ .../hl7-fhir-r5-core/DataRequirement.ts | 66 ++++++++ src/fhir-types/hl7-fhir-r5-core/DataType.ts | 11 ++ src/fhir-types/hl7-fhir-r5-core/Distance.ts | 11 ++ .../hl7-fhir-r5-core/DomainResource.ts | 20 +++ src/fhir-types/hl7-fhir-r5-core/Dosage.ts | 50 ++++++ src/fhir-types/hl7-fhir-r5-core/Duration.ts | 11 ++ src/fhir-types/hl7-fhir-r5-core/Element.ts | 14 ++ src/fhir-types/hl7-fhir-r5-core/Expression.ts | 21 +++ .../hl7-fhir-r5-core/ExtendedContactDetail.ts | 29 ++++ src/fhir-types/hl7-fhir-r5-core/Extension.ts | 155 ++++++++++++++++++ src/fhir-types/hl7-fhir-r5-core/HumanName.ts | 26 +++ src/fhir-types/hl7-fhir-r5-core/Identifier.ts | 26 +++ src/fhir-types/hl7-fhir-r5-core/Meta.ts | 23 +++ src/fhir-types/hl7-fhir-r5-core/Money.ts | 15 ++ src/fhir-types/hl7-fhir-r5-core/Narrative.ts | 15 ++ .../hl7-fhir-r5-core/ParameterDefinition.ts | 25 +++ src/fhir-types/hl7-fhir-r5-core/Period.ts | 15 ++ src/fhir-types/hl7-fhir-r5-core/Quantity.ts | 21 +++ src/fhir-types/hl7-fhir-r5-core/Range.ts | 15 ++ src/fhir-types/hl7-fhir-r5-core/Ratio.ts | 15 ++ src/fhir-types/hl7-fhir-r5-core/RatioRange.ts | 16 ++ src/fhir-types/hl7-fhir-r5-core/Reference.ts | 20 +++ .../hl7-fhir-r5-core/RelatedArtifact.ts | 34 ++++ src/fhir-types/hl7-fhir-r5-core/Resource.ts | 22 +++ .../hl7-fhir-r5-core/SampledData.ts | 32 ++++ src/fhir-types/hl7-fhir-r5-core/Signature.ts | 26 +++ src/fhir-types/hl7-fhir-r5-core/Timing.ts | 45 +++++ .../hl7-fhir-r5-core/TriggerDefinition.ts | 36 ++++ .../hl7-fhir-r5-core/UsageContext.ts | 26 +++ src/fhir-types/hl7-fhir-r5-core/index.ts | 44 +++++ .../org-sql-on-fhir-ig/ViewDefinition.ts | 76 +++++++++ src/fhir-types/org-sql-on-fhir-ig/index.ts | 1 + 59 files changed, 1335 insertions(+), 82 deletions(-) create mode 100644 src/fhir-types/hl7-fhir-r5-core/Address.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/Age.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/Annotation.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/Attachment.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/Availability.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/BackboneElement.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/BackboneType.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/Base.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/CanonicalResource.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/CodeableConcept.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/CodeableReference.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/Coding.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/ContactDetail.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/ContactPoint.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/Count.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/DataRequirement.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/DataType.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/Distance.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/DomainResource.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/Dosage.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/Duration.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/Element.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/Expression.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/ExtendedContactDetail.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/Extension.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/HumanName.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/Identifier.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/Meta.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/Money.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/Narrative.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/ParameterDefinition.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/Period.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/Quantity.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/Range.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/Ratio.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/RatioRange.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/Reference.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/RelatedArtifact.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/Resource.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/SampledData.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/Signature.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/Timing.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/TriggerDefinition.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/UsageContext.ts create mode 100644 src/fhir-types/hl7-fhir-r5-core/index.ts create mode 100644 src/fhir-types/org-sql-on-fhir-ig/ViewDefinition.ts create mode 100644 src/fhir-types/org-sql-on-fhir-ig/index.ts diff --git a/.gitignore b/.gitignore index fd642397..40cc7d0f 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ .DS_Store /.tanstack /tmp +/.codegen-cache/ diff --git a/biome.json b/biome.json index c90a82e3..b3568d96 100644 --- a/biome.json +++ b/biome.json @@ -16,7 +16,8 @@ "tsconfig.json", "tsconfig.node.json", "vite.config.ts", - "!src/**/routeTree.gen.ts" + "!src/**/routeTree.gen.ts", + "scripts/**" ], "ignoreUnknown": false }, diff --git a/package.json b/package.json index c025640a..e36f308b 100644 --- a/package.json +++ b/package.json @@ -21,9 +21,9 @@ "keywords": [], "author": "Health Samurai", "license": "MIT", - "packageManager": "pnpm@10.14.0", + "packageManager": "pnpm@10.22.0", "devDependencies": { - "@atomic-ehr/codegen": "canary", + "@atomic-ehr/codegen": "0.0.2", "@biomejs/biome": "2.1.3", "@tailwindcss/vite": "^4.1.12", "@tanstack/router-plugin": "^1.131.13", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9a7242fd..0423b352 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -67,8 +67,8 @@ importers: version: 15.6.9 devDependencies: '@atomic-ehr/codegen': - specifier: canary - version: 0.0.1-canary.20251110160104.576d657(typescript@5.9.2) + specifier: 0.0.2 + version: 0.0.2(typescript@5.9.2) '@biomejs/biome': specifier: 2.1.3 version: 2.1.3 @@ -108,18 +108,18 @@ importers: packages: - '@atomic-ehr/codegen@0.0.1-canary.20251110160104.576d657': - resolution: {integrity: sha512-25X1WJ8gd0p6Qmmx2045WEnQ+97VA7AB8MDp2HHTeZWlL1F2lyhGbYyN5flyXRvw03938fvixKHb9unHqozD0g==} + '@atomic-ehr/codegen@0.0.2': + resolution: {integrity: sha512-u3U1uiyN2ushbCB3h81a/ntVTk9nX56CXEbPhU1Bzi/a1pxZcJGyjH0h3BT2Pazu+PYJdeiN9b/d29Ci5hk92g==} hasBin: true - '@atomic-ehr/fhir-canonical-manager@0.0.11-canary.355d62d.20250926143544': - resolution: {integrity: sha512-3FOfV7yyPhkcQ5ug+uE7ESp2ZmM2nVTEI73geOT5uqqi3lBd+G22tZA/HVUaPm2mTbcjQ0KWERG1J+3qxzoB1g==} + '@atomic-ehr/fhir-canonical-manager@0.0.15': + resolution: {integrity: sha512-hVtvJrs7NjSuDx8RiUpEglaF3PuKESGRNslvEtsIl6cThnwSdovTCo+LgKD8u3W0aMdq0Dpbah9ISvkeB9+ASw==} hasBin: true peerDependencies: typescript: ^5 - '@atomic-ehr/fhirschema@0.0.2': - resolution: {integrity: sha512-OA4CVjTUEdw43Efg5I5rj95je4GC3lRiLM/kUqadcK3Po24vnINUsB8YdOP/F3ffdUYKQcJ+z09sWQVeAC2z/A==} + '@atomic-ehr/fhirschema@0.0.5': + resolution: {integrity: sha512-B/8ScNnnQUIR6d3FsIuGGvanOyE2j7W3mAubVmpPE2I/tho+meEBRrGgs5E+AY4jDz9mviTdOta08RpIhH2kew==} peerDependencies: typescript: ^5 @@ -2847,10 +2847,10 @@ packages: snapshots: - '@atomic-ehr/codegen@0.0.1-canary.20251110160104.576d657(typescript@5.9.2)': + '@atomic-ehr/codegen@0.0.2(typescript@5.9.2)': dependencies: - '@atomic-ehr/fhir-canonical-manager': 0.0.11-canary.355d62d.20250926143544(typescript@5.9.2) - '@atomic-ehr/fhirschema': 0.0.2(typescript@5.9.2) + '@atomic-ehr/fhir-canonical-manager': 0.0.15(typescript@5.9.2) + '@atomic-ehr/fhirschema': 0.0.5(typescript@5.9.2) '@inquirer/prompts': 7.10.0 ajv: 8.17.1 handlebars: 4.7.8 @@ -2862,11 +2862,11 @@ snapshots: - '@types/node' - typescript - '@atomic-ehr/fhir-canonical-manager@0.0.11-canary.355d62d.20250926143544(typescript@5.9.2)': + '@atomic-ehr/fhir-canonical-manager@0.0.15(typescript@5.9.2)': dependencies: typescript: 5.9.2 - '@atomic-ehr/fhirschema@0.0.2(typescript@5.9.2)': + '@atomic-ehr/fhirschema@0.0.5(typescript@5.9.2)': dependencies: typescript: 5.9.2 diff --git a/scripts/generate-types.ts b/scripts/generate-types.ts index 858fe76b..eb0f8dcd 100644 --- a/scripts/generate-types.ts +++ b/scripts/generate-types.ts @@ -5,9 +5,16 @@ console.log("📦 Generating FHIR R4 Core Types..."); const builder = new APIBuilder() .verbose() .throwException() - .fromPackage("hl7.fhir.r4.core", "4.0.1") - .typescript({ withDebugComment: false }) + .typescript({ withDebugComment: false, generateProfile: false }) + .fromPackageRef("https://build.fhir.org/ig/FHIR/sql-on-fhir-v2//package.tgz") .outputTo("./src/fhir-types") + // .writeTypeTree("./src/fhir-types/tree.yaml") + .treeShake({ + // "hl7.fhir.r5.core": {"http://hl7.org/fhir/StructureDefinition/Meta": {}}, + "org.sql-on-fhir.ig": { + "https://sql-on-fhir.org/ig/StructureDefinition/ViewDefinition": {}, + }, + }) .cleanOutput(true); const report = await builder.generate(); @@ -15,8 +22,8 @@ const report = await builder.generate(); console.log(report); if (report.success) { - console.log("✅ FHIR R4 types generated successfully!"); + console.log("✅ FHIR types generated successfully!"); } else { - console.error("❌ FHIR R4 types generation failed."); + console.error("❌ FHIR types generation failed."); process.exit(1); } diff --git a/src/components/ViewDefinition/editor-code-tab-content.tsx b/src/components/ViewDefinition/editor-code-tab-content.tsx index f5fd243f..b08dbfc2 100644 --- a/src/components/ViewDefinition/editor-code-tab-content.tsx +++ b/src/components/ViewDefinition/editor-code-tab-content.tsx @@ -1,3 +1,4 @@ +import type { ViewDefinition } from "@aidbox-ui/fhir-types/org-sql-on-fhir-ig"; import * as HSComp from "@health-samurai/react-components"; import * as yaml from "js-yaml"; import React from "react"; @@ -7,7 +8,7 @@ import { ViewDefinitionContext, ViewDefinitionResourceTypeContext, } from "./page"; -import type { ViewDefinition, ViewDefinitionEditorMode } from "./types"; +import type { ViewDefinitionEditorMode } from "./types"; export const ViewDefinitionCodeEditor = ({ codeMode, diff --git a/src/components/ViewDefinition/editor-form-tab-content.tsx b/src/components/ViewDefinition/editor-form-tab-content.tsx index 0a1a6793..0926f739 100644 --- a/src/components/ViewDefinition/editor-form-tab-content.tsx +++ b/src/components/ViewDefinition/editor-form-tab-content.tsx @@ -1,3 +1,4 @@ +import type { ViewDefinitionSelect } from "@aidbox-ui/fhir-types/org-sql-on-fhir-ig/ViewDefinition"; import { Button, Checkbox, @@ -105,7 +106,7 @@ interface SelectItemInternal { // Helper functions const parseSelectItems = ( - items: Types.ViewDefinitionSelectItem[], + items: ViewDefinitionSelect[], parentId = "", ): SelectItemInternal[] => { return items @@ -150,7 +151,7 @@ const parseSelectItems = ( const buildSelectArray = ( items: SelectItemInternal[], -): Types.ViewDefinitionSelectItem[] => { +): ViewDefinitionSelect[] => { return items .map((item) => { if (item.type === "column" && item.columns) { @@ -161,7 +162,7 @@ const buildSelectArray = ( })), }; } else if (item.type === "forEach") { - const result: Types.ViewDefinitionSelectItem = { + const result: ViewDefinitionSelect = { forEach: item.expression || "", }; if (item.children && item.children.length > 0) { @@ -169,7 +170,7 @@ const buildSelectArray = ( } return result; } else if (item.type === "forEachOrNull") { - const result: Types.ViewDefinitionSelectItem = { + const result: ViewDefinitionSelect = { forEachOrNull: item.expression || "", }; if (item.children && item.children.length > 0) { @@ -183,7 +184,7 @@ const buildSelectArray = ( } return null; }) - .filter(Boolean) as Types.ViewDefinitionSelectItem[]; + .filter(Boolean) as ViewDefinitionSelect[]; }; const findPath = ( @@ -355,10 +356,10 @@ export const FormTabContent = () => { if (selectArray.length > 0) { updatedViewDef.select = selectArray; } else { - delete updatedViewDef.select; + delete (updatedViewDef as any).select; } - viewDefinitionContext.setViewDefinition(updatedViewDef); + viewDefinitionContext.setViewDefinition(updatedViewDef as any); } }, [ @@ -1352,7 +1353,7 @@ export const FormTabContent = () => {
{ + mutationFn: (viewDefinition: ViewDefinition) => { return client.aidboxRequest({ method: "PUT", url: `/fhir/ViewDefinition/${viewDefinitionContext.originalId}`, @@ -64,7 +64,7 @@ export const EditorPanelActions = ({ }); const viewDefinitionCreateMutation = useMutation({ - mutationFn: (viewDefinition: Types.ViewDefinition) => { + mutationFn: (viewDefinition: ViewDefinition) => { return client.aidboxRequest({ method: "POST", url: `/fhir/ViewDefinition/`, @@ -83,7 +83,7 @@ export const EditorPanelActions = ({ }); const viewDefinitionRunMutation = useMutation({ - mutationFn: (viewDefinition: Types.ViewDefinition) => { + mutationFn: (viewDefinition: ViewDefinition) => { viewDefinitionContext.setRunResultPage(1); viewDefinitionContext.setRunViewDefinition(viewDefinition); diff --git a/src/components/ViewDefinition/page.tsx b/src/components/ViewDefinition/page.tsx index b4eee908..7101b852 100644 --- a/src/components/ViewDefinition/page.tsx +++ b/src/components/ViewDefinition/page.tsx @@ -1,3 +1,4 @@ +import type { ViewDefinition } from "@aidbox-ui/fhir-types/org-sql-on-fhir-ig"; import type * as AidboxType from "@health-samurai/aidbox-client"; import * as HSComp from "@health-samurai/react-components"; import { useQuery } from "@tanstack/react-query"; @@ -10,7 +11,7 @@ import { ResultPanel } from "./result-panel-content"; import type * as Types from "./types"; const fetchViewDefinition = (client: AidboxType.AidboxClient, id: string) => { - return client.aidboxRequest({ + return client.aidboxRequest({ method: "GET", url: `/fhir/ViewDefinition/${id}`, }); @@ -59,10 +60,9 @@ const ViewDefinitionPage = ({ id }: { id?: string }) => { const [resouceTypeForViewDefinition, setResouceTypeForViewDefinition] = React.useState(); - const [viewDefinition, setViewDefinition] = - React.useState(); + const [viewDefinition, setViewDefinition] = React.useState(); const [runViewDefinition, setRunViewDefinition] = - React.useState(); + React.useState(); const [runResult, setRunResult] = React.useState(); const [runResultPage, setRunResultPage] = React.useState(1); @@ -76,7 +76,7 @@ const ViewDefinitionPage = ({ id }: { id?: string }) => { resourceType: "ViewDefinition", select: [], }; - let response: Types.ViewDefinition = viewDefinitionPlaceholder; + let response: ViewDefinition = viewDefinitionPlaceholder as any; if (id) { const resp = await fetchViewDefinition(aidboxClient, id); response = resp.response.body; diff --git a/src/components/ViewDefinition/result-panel-content.tsx b/src/components/ViewDefinition/result-panel-content.tsx index ee478fc5..f867d585 100644 --- a/src/components/ViewDefinition/result-panel-content.tsx +++ b/src/components/ViewDefinition/result-panel-content.tsx @@ -1,3 +1,4 @@ +import type { ViewDefinition } from "@aidbox-ui/fhir-types/org-sql-on-fhir-ig"; import type * as AidboxTypes from "@health-samurai/aidbox-client"; import { type AccessorKeyColumnDef, @@ -244,7 +245,7 @@ export function ResultPanel() { page, pageSize, }: { - viewDefinition: Types.ViewDefinition | undefined; + viewDefinition: ViewDefinition | undefined; page: number; pageSize: number; }) => { diff --git a/src/components/ViewDefinition/sql-tab-content.tsx b/src/components/ViewDefinition/sql-tab-content.tsx index 62745a36..7e1de089 100644 --- a/src/components/ViewDefinition/sql-tab-content.tsx +++ b/src/components/ViewDefinition/sql-tab-content.tsx @@ -1,3 +1,4 @@ +import type { ViewDefinition } from "@aidbox-ui/fhir-types/org-sql-on-fhir-ig"; import type * as AidboxTypes from "@health-samurai/aidbox-client"; import { CodeEditor, TabsContent } from "@health-samurai/react-components"; import { useQuery } from "@tanstack/react-query"; @@ -6,7 +7,6 @@ import { format as formatSQL } from "sql-formatter"; import { useAidboxClient } from "../../AidboxClient"; import * as Constants from "./constants"; import { ViewDefinitionContext } from "./page"; -import type { ViewDefinition } from "./types"; const fetchSQL = async ( client: AidboxTypes.AidboxClient, diff --git a/src/components/ViewDefinition/types.tsx b/src/components/ViewDefinition/types.tsx index 0cab3766..0449dc66 100644 --- a/src/components/ViewDefinition/types.tsx +++ b/src/components/ViewDefinition/types.tsx @@ -1,45 +1,4 @@ -export interface ViewDefinitionSelectItem { - column?: Array<{ - name: string; - path: string; - type?: string; - }>; - forEach?: string; - forEachOrNull?: string; - unionAll?: ViewDefinitionSelectItem[]; - select?: ViewDefinitionSelectItem[]; -} - -export interface ViewDefinitionConstant { - name: string; - valueString?: string; -} - -export interface ViewDefinitionWhere { - path: string; -} - -export interface ViewDefinition { - resourceType: string; - resource: string; - name?: string; - id?: string; - select?: ViewDefinitionSelectItem[]; - constant?: ViewDefinitionConstant[]; - where?: ViewDefinitionWhere[]; - title?: string; - description?: string; - status?: string; - url?: string; - publisher?: string; - copyright?: string; - experimental?: boolean; - fhirVersion?: string[] | undefined; - identifier?: { - system?: string; - value?: string; - }[]; -} +import type { ViewDefinition } from "@aidbox-ui/fhir-types/org-sql-on-fhir-ig"; export interface ViewDefinitionContextProps { originalId?: string | undefined; diff --git a/src/fhir-types/hl7-fhir-r5-core/Address.ts b/src/fhir-types/hl7-fhir-r5-core/Address.ts new file mode 100644 index 00000000..7c3f7512 --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/Address.ts @@ -0,0 +1,32 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { DataType } from "../hl7-fhir-r5-core/DataType"; +import type { Period } from "../hl7-fhir-r5-core/Period"; + +export type { DataType } from "../hl7-fhir-r5-core/DataType"; +export type { Period } from "../hl7-fhir-r5-core/Period"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/Address +export interface Address extends DataType { + city?: string; + _city?: Element; + country?: string; + _country?: Element; + district?: string; + _district?: Element; + line?: string[]; + _line?: Element; + period?: Period; + postalCode?: string; + _postalCode?: Element; + state?: string; + _state?: Element; + text?: string; + _text?: Element; + type?: "postal" | "physical" | "both"; + _type?: Element; + use?: "home" | "work" | "temp" | "old" | "billing"; + _use?: Element; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/Age.ts b/src/fhir-types/hl7-fhir-r5-core/Age.ts new file mode 100644 index 00000000..f07ad14e --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/Age.ts @@ -0,0 +1,11 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { Quantity } from "../hl7-fhir-r5-core/Quantity"; + +export type { Quantity } from "../hl7-fhir-r5-core/Quantity"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/Age +export interface Age extends Quantity { +} diff --git a/src/fhir-types/hl7-fhir-r5-core/Annotation.ts b/src/fhir-types/hl7-fhir-r5-core/Annotation.ts new file mode 100644 index 00000000..80a1d51a --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/Annotation.ts @@ -0,0 +1,20 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { DataType } from "../hl7-fhir-r5-core/DataType"; +import type { Reference } from "../hl7-fhir-r5-core/Reference"; + +export type { DataType } from "../hl7-fhir-r5-core/DataType"; +export type { Reference } from "../hl7-fhir-r5-core/Reference"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/Annotation +export interface Annotation extends DataType { + authorReference?: Reference<"Organization" | "Patient" | "Practitioner" | "PractitionerRole" | "RelatedPerson">; + authorString?: string; + _authorString?: Element; + text: string; + _text?: Element; + time?: string; + _time?: Element; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/Attachment.ts b/src/fhir-types/hl7-fhir-r5-core/Attachment.ts new file mode 100644 index 00000000..6cbcab02 --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/Attachment.ts @@ -0,0 +1,37 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { DataType } from "../hl7-fhir-r5-core/DataType"; + +export type { DataType } from "../hl7-fhir-r5-core/DataType"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/Attachment +export interface Attachment extends DataType { + contentType?: string; + _contentType?: Element; + creation?: string; + _creation?: Element; + data?: string; + _data?: Element; + duration?: number; + _duration?: Element; + frames?: number; + _frames?: Element; + hash?: string; + _hash?: Element; + height?: number; + _height?: Element; + language?: string; + _language?: Element; + pages?: number; + _pages?: Element; + size?: number; + _size?: Element; + title?: string; + _title?: Element; + url?: string; + _url?: Element; + width?: number; + _width?: Element; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/Availability.ts b/src/fhir-types/hl7-fhir-r5-core/Availability.ts new file mode 100644 index 00000000..2d04e265 --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/Availability.ts @@ -0,0 +1,29 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { DataType } from "../hl7-fhir-r5-core/DataType"; +import type { Element } from "../hl7-fhir-r5-core/Element"; +import type { Period } from "../hl7-fhir-r5-core/Period"; + +export type { DataType } from "../hl7-fhir-r5-core/DataType"; +export type { Element } from "../hl7-fhir-r5-core/Element"; +export type { Period } from "../hl7-fhir-r5-core/Period"; + +export interface AvailabilityAvailableTime extends Element { + allDay?: boolean; + availableEndTime?: string; + availableStartTime?: string; + daysOfWeek?: "mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun"[]; +} + +export interface AvailabilityNotAvailableTime extends Element { + description?: string; + during?: Period; +} + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/Availability +export interface Availability extends DataType { + availableTime?: Element[]; + notAvailableTime?: Element[]; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/BackboneElement.ts b/src/fhir-types/hl7-fhir-r5-core/BackboneElement.ts new file mode 100644 index 00000000..a30e2e28 --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/BackboneElement.ts @@ -0,0 +1,14 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { Element } from "../hl7-fhir-r5-core/Element"; +import type { Extension } from "../hl7-fhir-r5-core/Extension"; + +export type { Element } from "../hl7-fhir-r5-core/Element"; +export type { Extension } from "../hl7-fhir-r5-core/Extension"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/BackboneElement +export interface BackboneElement extends Element { + modifierExtension?: Extension[]; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/BackboneType.ts b/src/fhir-types/hl7-fhir-r5-core/BackboneType.ts new file mode 100644 index 00000000..9be00aa2 --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/BackboneType.ts @@ -0,0 +1,14 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { DataType } from "../hl7-fhir-r5-core/DataType"; +import type { Extension } from "../hl7-fhir-r5-core/Extension"; + +export type { DataType } from "../hl7-fhir-r5-core/DataType"; +export type { Extension } from "../hl7-fhir-r5-core/Extension"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/BackboneType +export interface BackboneType extends DataType { + modifierExtension?: Extension[]; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/Base.ts b/src/fhir-types/hl7-fhir-r5-core/Base.ts new file mode 100644 index 00000000..bd7a228a --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/Base.ts @@ -0,0 +1,7 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/Base +export interface Base { +} diff --git a/src/fhir-types/hl7-fhir-r5-core/CanonicalResource.ts b/src/fhir-types/hl7-fhir-r5-core/CanonicalResource.ts new file mode 100644 index 00000000..a8c4640c --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/CanonicalResource.ts @@ -0,0 +1,53 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { CodeableConcept } from "../hl7-fhir-r5-core/CodeableConcept"; +import type { Coding } from "../hl7-fhir-r5-core/Coding"; +import type { ContactDetail } from "../hl7-fhir-r5-core/ContactDetail"; +import type { DomainResource } from "../hl7-fhir-r5-core/DomainResource"; +import type { Identifier } from "../hl7-fhir-r5-core/Identifier"; +import type { UsageContext } from "../hl7-fhir-r5-core/UsageContext"; + +export type { CodeableConcept } from "../hl7-fhir-r5-core/CodeableConcept"; +export type { Coding } from "../hl7-fhir-r5-core/Coding"; +export type { ContactDetail } from "../hl7-fhir-r5-core/ContactDetail"; +export type { Identifier } from "../hl7-fhir-r5-core/Identifier"; +export type { UsageContext } from "../hl7-fhir-r5-core/UsageContext"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/CanonicalResource +export interface CanonicalResource extends DomainResource { + resourceType: "CanonicalResource" | "ViewDefinition"; + + contact?: ContactDetail[]; + copyright?: string; + _copyright?: Element; + copyrightLabel?: string; + _copyrightLabel?: Element; + date?: string; + _date?: Element; + description?: string; + _description?: Element; + experimental?: boolean; + _experimental?: Element; + identifier?: Identifier[]; + jurisdiction?: CodeableConcept[]; + name?: string; + _name?: Element; + publisher?: string; + _publisher?: Element; + purpose?: string; + _purpose?: Element; + status: "draft" | "active" | "retired" | "unknown"; + _status?: Element; + title?: string; + _title?: Element; + url?: string; + _url?: Element; + useContext?: UsageContext[]; + version?: string; + _version?: Element; + versionAlgorithmCoding?: Coding; + versionAlgorithmString?: string; + _versionAlgorithmString?: Element; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/CodeableConcept.ts b/src/fhir-types/hl7-fhir-r5-core/CodeableConcept.ts new file mode 100644 index 00000000..545f02e1 --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/CodeableConcept.ts @@ -0,0 +1,16 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { Coding } from "../hl7-fhir-r5-core/Coding"; +import type { DataType } from "../hl7-fhir-r5-core/DataType"; + +export type { Coding } from "../hl7-fhir-r5-core/Coding"; +export type { DataType } from "../hl7-fhir-r5-core/DataType"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/CodeableConcept +export interface CodeableConcept extends DataType { + coding?: Coding[]; + text?: string; + _text?: Element; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/CodeableReference.ts b/src/fhir-types/hl7-fhir-r5-core/CodeableReference.ts new file mode 100644 index 00000000..a15ea3d6 --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/CodeableReference.ts @@ -0,0 +1,17 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { CodeableConcept } from "../hl7-fhir-r5-core/CodeableConcept"; +import type { DataType } from "../hl7-fhir-r5-core/DataType"; +import type { Reference } from "../hl7-fhir-r5-core/Reference"; + +export type { CodeableConcept } from "../hl7-fhir-r5-core/CodeableConcept"; +export type { DataType } from "../hl7-fhir-r5-core/DataType"; +export type { Reference } from "../hl7-fhir-r5-core/Reference"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/CodeableReference +export interface CodeableReference extends DataType { + concept?: CodeableConcept; + reference?: Reference; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/Coding.ts b/src/fhir-types/hl7-fhir-r5-core/Coding.ts new file mode 100644 index 00000000..0e301d29 --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/Coding.ts @@ -0,0 +1,21 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { DataType } from "../hl7-fhir-r5-core/DataType"; + +export type { DataType } from "../hl7-fhir-r5-core/DataType"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/Coding +export interface Coding extends DataType { + code?: string; + _code?: Element; + display?: string; + _display?: Element; + system?: string; + _system?: Element; + userSelected?: boolean; + _userSelected?: Element; + version?: string; + _version?: Element; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/ContactDetail.ts b/src/fhir-types/hl7-fhir-r5-core/ContactDetail.ts new file mode 100644 index 00000000..f097c3a8 --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/ContactDetail.ts @@ -0,0 +1,16 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { ContactPoint } from "../hl7-fhir-r5-core/ContactPoint"; +import type { DataType } from "../hl7-fhir-r5-core/DataType"; + +export type { ContactPoint } from "../hl7-fhir-r5-core/ContactPoint"; +export type { DataType } from "../hl7-fhir-r5-core/DataType"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/ContactDetail +export interface ContactDetail extends DataType { + name?: string; + _name?: Element; + telecom?: ContactPoint[]; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/ContactPoint.ts b/src/fhir-types/hl7-fhir-r5-core/ContactPoint.ts new file mode 100644 index 00000000..9fc4a6d8 --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/ContactPoint.ts @@ -0,0 +1,22 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { DataType } from "../hl7-fhir-r5-core/DataType"; +import type { Period } from "../hl7-fhir-r5-core/Period"; + +export type { DataType } from "../hl7-fhir-r5-core/DataType"; +export type { Period } from "../hl7-fhir-r5-core/Period"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/ContactPoint +export interface ContactPoint extends DataType { + period?: Period; + rank?: number; + _rank?: Element; + system?: "phone" | "fax" | "email" | "pager" | "url" | "sms" | "other"; + _system?: Element; + use?: "home" | "work" | "temp" | "old" | "mobile"; + _use?: Element; + value?: string; + _value?: Element; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/Count.ts b/src/fhir-types/hl7-fhir-r5-core/Count.ts new file mode 100644 index 00000000..717e57b9 --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/Count.ts @@ -0,0 +1,11 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { Quantity } from "../hl7-fhir-r5-core/Quantity"; + +export type { Quantity } from "../hl7-fhir-r5-core/Quantity"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/Count +export interface Count extends Quantity { +} diff --git a/src/fhir-types/hl7-fhir-r5-core/DataRequirement.ts b/src/fhir-types/hl7-fhir-r5-core/DataRequirement.ts new file mode 100644 index 00000000..de3806de --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/DataRequirement.ts @@ -0,0 +1,66 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { CodeableConcept } from "../hl7-fhir-r5-core/CodeableConcept"; +import type { Coding } from "../hl7-fhir-r5-core/Coding"; +import type { DataType } from "../hl7-fhir-r5-core/DataType"; +import type { Duration } from "../hl7-fhir-r5-core/Duration"; +import type { Element } from "../hl7-fhir-r5-core/Element"; +import type { Period } from "../hl7-fhir-r5-core/Period"; +import type { Reference } from "../hl7-fhir-r5-core/Reference"; + +export type { CodeableConcept } from "../hl7-fhir-r5-core/CodeableConcept"; +export type { Coding } from "../hl7-fhir-r5-core/Coding"; +export type { DataType } from "../hl7-fhir-r5-core/DataType"; +export type { Duration } from "../hl7-fhir-r5-core/Duration"; +export type { Element } from "../hl7-fhir-r5-core/Element"; +export type { Period } from "../hl7-fhir-r5-core/Period"; +export type { Reference } from "../hl7-fhir-r5-core/Reference"; + +export interface DataRequirementCodeFilter extends Element { + code?: Coding[]; + path?: string; + searchParam?: string; + valueSet?: string; +} + +export interface DataRequirementDateFilter extends Element { + path?: string; + searchParam?: string; + valueDateTime?: string; + valueDuration?: Duration; + valuePeriod?: Period; +} + +export interface DataRequirementSort extends Element { + direction: "ascending" | "descending"; + path: string; +} + +export interface DataRequirementValueFilter extends Element { + comparator?: "eq" | "gt" | "lt" | "ge" | "le" | "sa" | "eb"; + path?: string; + searchParam?: string; + valueDateTime?: string; + valueDuration?: Duration; + valuePeriod?: Period; +} + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/DataRequirement +export interface DataRequirement extends DataType { + codeFilter?: Element[]; + dateFilter?: Element[]; + limit?: number; + _limit?: Element; + mustSupport?: string[]; + _mustSupport?: Element; + profile?: string[]; + _profile?: Element; + sort?: Element[]; + subjectCodeableConcept?: CodeableConcept; + subjectReference?: Reference<"Group">; + type: string; + _type?: Element; + valueFilter?: Element[]; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/DataType.ts b/src/fhir-types/hl7-fhir-r5-core/DataType.ts new file mode 100644 index 00000000..53581579 --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/DataType.ts @@ -0,0 +1,11 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { Element } from "../hl7-fhir-r5-core/Element"; + +export type { Element } from "../hl7-fhir-r5-core/Element"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/DataType +export interface DataType extends Element { +} diff --git a/src/fhir-types/hl7-fhir-r5-core/Distance.ts b/src/fhir-types/hl7-fhir-r5-core/Distance.ts new file mode 100644 index 00000000..4d2e30d9 --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/Distance.ts @@ -0,0 +1,11 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { Quantity } from "../hl7-fhir-r5-core/Quantity"; + +export type { Quantity } from "../hl7-fhir-r5-core/Quantity"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/Distance +export interface Distance extends Quantity { +} diff --git a/src/fhir-types/hl7-fhir-r5-core/DomainResource.ts b/src/fhir-types/hl7-fhir-r5-core/DomainResource.ts new file mode 100644 index 00000000..5e38371d --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/DomainResource.ts @@ -0,0 +1,20 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { Extension } from "../hl7-fhir-r5-core/Extension"; +import type { Narrative } from "../hl7-fhir-r5-core/Narrative"; +import type { Resource } from "../hl7-fhir-r5-core/Resource"; + +export type { Extension } from "../hl7-fhir-r5-core/Extension"; +export type { Narrative } from "../hl7-fhir-r5-core/Narrative"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/DomainResource +export interface DomainResource extends Resource { + resourceType: "CanonicalResource" | "DomainResource" | "ViewDefinition"; + + contained?: Resource[]; + extension?: Extension[]; + modifierExtension?: Extension[]; + text?: Narrative; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/Dosage.ts b/src/fhir-types/hl7-fhir-r5-core/Dosage.ts new file mode 100644 index 00000000..07ad06ce --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/Dosage.ts @@ -0,0 +1,50 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { BackboneType } from "../hl7-fhir-r5-core/BackboneType"; +import type { CodeableConcept } from "../hl7-fhir-r5-core/CodeableConcept"; +import type { Element } from "../hl7-fhir-r5-core/Element"; +import type { Quantity } from "../hl7-fhir-r5-core/Quantity"; +import type { Range } from "../hl7-fhir-r5-core/Range"; +import type { Ratio } from "../hl7-fhir-r5-core/Ratio"; +import type { Timing } from "../hl7-fhir-r5-core/Timing"; + +export type { BackboneType } from "../hl7-fhir-r5-core/BackboneType"; +export type { CodeableConcept } from "../hl7-fhir-r5-core/CodeableConcept"; +export type { Element } from "../hl7-fhir-r5-core/Element"; +export type { Quantity } from "../hl7-fhir-r5-core/Quantity"; +export type { Range } from "../hl7-fhir-r5-core/Range"; +export type { Ratio } from "../hl7-fhir-r5-core/Ratio"; +export type { Timing } from "../hl7-fhir-r5-core/Timing"; + +export interface DosageDoseAndRate extends Element { + doseQuantity?: Quantity; + doseRange?: Range; + rateQuantity?: Quantity; + rateRange?: Range; + rateRatio?: Ratio; + type?: CodeableConcept; +} + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/Dosage +export interface Dosage extends BackboneType { + additionalInstruction?: CodeableConcept[]; + asNeeded?: boolean; + _asNeeded?: Element; + asNeededFor?: CodeableConcept[]; + doseAndRate?: Element[]; + maxDosePerAdministration?: Quantity; + maxDosePerLifetime?: Quantity; + maxDosePerPeriod?: Ratio[]; + method?: CodeableConcept; + patientInstruction?: string; + _patientInstruction?: Element; + route?: CodeableConcept; + sequence?: number; + _sequence?: Element; + site?: CodeableConcept; + text?: string; + _text?: Element; + timing?: Timing; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/Duration.ts b/src/fhir-types/hl7-fhir-r5-core/Duration.ts new file mode 100644 index 00000000..7f6c7d2e --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/Duration.ts @@ -0,0 +1,11 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { Quantity } from "../hl7-fhir-r5-core/Quantity"; + +export type { Quantity } from "../hl7-fhir-r5-core/Quantity"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/Duration +export interface Duration extends Quantity { +} diff --git a/src/fhir-types/hl7-fhir-r5-core/Element.ts b/src/fhir-types/hl7-fhir-r5-core/Element.ts new file mode 100644 index 00000000..ec1dca9e --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/Element.ts @@ -0,0 +1,14 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { Extension } from "../hl7-fhir-r5-core/Extension"; + +export type { Extension } from "../hl7-fhir-r5-core/Extension"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/Element +export interface Element { + extension?: Extension[]; + id?: string; + _id?: Element; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/Expression.ts b/src/fhir-types/hl7-fhir-r5-core/Expression.ts new file mode 100644 index 00000000..31af3529 --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/Expression.ts @@ -0,0 +1,21 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { DataType } from "../hl7-fhir-r5-core/DataType"; + +export type { DataType } from "../hl7-fhir-r5-core/DataType"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/Expression +export interface Expression extends DataType { + description?: string; + _description?: Element; + expression?: string; + _expression?: Element; + language?: string; + _language?: Element; + name?: string; + _name?: Element; + reference?: string; + _reference?: Element; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/ExtendedContactDetail.ts b/src/fhir-types/hl7-fhir-r5-core/ExtendedContactDetail.ts new file mode 100644 index 00000000..9f35ba64 --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/ExtendedContactDetail.ts @@ -0,0 +1,29 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { Address } from "../hl7-fhir-r5-core/Address"; +import type { CodeableConcept } from "../hl7-fhir-r5-core/CodeableConcept"; +import type { ContactPoint } from "../hl7-fhir-r5-core/ContactPoint"; +import type { DataType } from "../hl7-fhir-r5-core/DataType"; +import type { HumanName } from "../hl7-fhir-r5-core/HumanName"; +import type { Period } from "../hl7-fhir-r5-core/Period"; +import type { Reference } from "../hl7-fhir-r5-core/Reference"; + +export type { Address } from "../hl7-fhir-r5-core/Address"; +export type { CodeableConcept } from "../hl7-fhir-r5-core/CodeableConcept"; +export type { ContactPoint } from "../hl7-fhir-r5-core/ContactPoint"; +export type { DataType } from "../hl7-fhir-r5-core/DataType"; +export type { HumanName } from "../hl7-fhir-r5-core/HumanName"; +export type { Period } from "../hl7-fhir-r5-core/Period"; +export type { Reference } from "../hl7-fhir-r5-core/Reference"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/ExtendedContactDetail +export interface ExtendedContactDetail extends DataType { + address?: Address; + name?: HumanName[]; + organization?: Reference<"Organization">; + period?: Period; + purpose?: CodeableConcept; + telecom?: ContactPoint[]; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/Extension.ts b/src/fhir-types/hl7-fhir-r5-core/Extension.ts new file mode 100644 index 00000000..d5cc32e6 --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/Extension.ts @@ -0,0 +1,155 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { Address } from "../hl7-fhir-r5-core/Address"; +import type { Age } from "../hl7-fhir-r5-core/Age"; +import type { Annotation } from "../hl7-fhir-r5-core/Annotation"; +import type { Attachment } from "../hl7-fhir-r5-core/Attachment"; +import type { Availability } from "../hl7-fhir-r5-core/Availability"; +import type { CodeableConcept } from "../hl7-fhir-r5-core/CodeableConcept"; +import type { CodeableReference } from "../hl7-fhir-r5-core/CodeableReference"; +import type { Coding } from "../hl7-fhir-r5-core/Coding"; +import type { ContactDetail } from "../hl7-fhir-r5-core/ContactDetail"; +import type { ContactPoint } from "../hl7-fhir-r5-core/ContactPoint"; +import type { Count } from "../hl7-fhir-r5-core/Count"; +import type { DataRequirement } from "../hl7-fhir-r5-core/DataRequirement"; +import type { DataType } from "../hl7-fhir-r5-core/DataType"; +import type { Distance } from "../hl7-fhir-r5-core/Distance"; +import type { Dosage } from "../hl7-fhir-r5-core/Dosage"; +import type { Duration } from "../hl7-fhir-r5-core/Duration"; +import type { Expression } from "../hl7-fhir-r5-core/Expression"; +import type { ExtendedContactDetail } from "../hl7-fhir-r5-core/ExtendedContactDetail"; +import type { HumanName } from "../hl7-fhir-r5-core/HumanName"; +import type { Identifier } from "../hl7-fhir-r5-core/Identifier"; +import type { Meta } from "../hl7-fhir-r5-core/Meta"; +import type { Money } from "../hl7-fhir-r5-core/Money"; +import type { ParameterDefinition } from "../hl7-fhir-r5-core/ParameterDefinition"; +import type { Period } from "../hl7-fhir-r5-core/Period"; +import type { Quantity } from "../hl7-fhir-r5-core/Quantity"; +import type { Range } from "../hl7-fhir-r5-core/Range"; +import type { Ratio } from "../hl7-fhir-r5-core/Ratio"; +import type { RatioRange } from "../hl7-fhir-r5-core/RatioRange"; +import type { Reference } from "../hl7-fhir-r5-core/Reference"; +import type { RelatedArtifact } from "../hl7-fhir-r5-core/RelatedArtifact"; +import type { SampledData } from "../hl7-fhir-r5-core/SampledData"; +import type { Signature } from "../hl7-fhir-r5-core/Signature"; +import type { Timing } from "../hl7-fhir-r5-core/Timing"; +import type { TriggerDefinition } from "../hl7-fhir-r5-core/TriggerDefinition"; +import type { UsageContext } from "../hl7-fhir-r5-core/UsageContext"; + +export type { Address } from "../hl7-fhir-r5-core/Address"; +export type { Age } from "../hl7-fhir-r5-core/Age"; +export type { Annotation } from "../hl7-fhir-r5-core/Annotation"; +export type { Attachment } from "../hl7-fhir-r5-core/Attachment"; +export type { Availability } from "../hl7-fhir-r5-core/Availability"; +export type { CodeableConcept } from "../hl7-fhir-r5-core/CodeableConcept"; +export type { CodeableReference } from "../hl7-fhir-r5-core/CodeableReference"; +export type { Coding } from "../hl7-fhir-r5-core/Coding"; +export type { ContactDetail } from "../hl7-fhir-r5-core/ContactDetail"; +export type { ContactPoint } from "../hl7-fhir-r5-core/ContactPoint"; +export type { Count } from "../hl7-fhir-r5-core/Count"; +export type { DataRequirement } from "../hl7-fhir-r5-core/DataRequirement"; +export type { DataType } from "../hl7-fhir-r5-core/DataType"; +export type { Distance } from "../hl7-fhir-r5-core/Distance"; +export type { Dosage } from "../hl7-fhir-r5-core/Dosage"; +export type { Duration } from "../hl7-fhir-r5-core/Duration"; +export type { Expression } from "../hl7-fhir-r5-core/Expression"; +export type { ExtendedContactDetail } from "../hl7-fhir-r5-core/ExtendedContactDetail"; +export type { HumanName } from "../hl7-fhir-r5-core/HumanName"; +export type { Identifier } from "../hl7-fhir-r5-core/Identifier"; +export type { Meta } from "../hl7-fhir-r5-core/Meta"; +export type { Money } from "../hl7-fhir-r5-core/Money"; +export type { ParameterDefinition } from "../hl7-fhir-r5-core/ParameterDefinition"; +export type { Period } from "../hl7-fhir-r5-core/Period"; +export type { Quantity } from "../hl7-fhir-r5-core/Quantity"; +export type { Range } from "../hl7-fhir-r5-core/Range"; +export type { Ratio } from "../hl7-fhir-r5-core/Ratio"; +export type { RatioRange } from "../hl7-fhir-r5-core/RatioRange"; +export type { Reference } from "../hl7-fhir-r5-core/Reference"; +export type { RelatedArtifact } from "../hl7-fhir-r5-core/RelatedArtifact"; +export type { SampledData } from "../hl7-fhir-r5-core/SampledData"; +export type { Signature } from "../hl7-fhir-r5-core/Signature"; +export type { Timing } from "../hl7-fhir-r5-core/Timing"; +export type { TriggerDefinition } from "../hl7-fhir-r5-core/TriggerDefinition"; +export type { UsageContext } from "../hl7-fhir-r5-core/UsageContext"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/Extension +export interface Extension extends DataType { + url: string; + _url?: Element; + valueAddress?: Address; + valueAge?: Age; + valueAnnotation?: Annotation; + valueAttachment?: Attachment; + valueAvailability?: Availability; + valueBase64Binary?: string; + _valueBase64Binary?: Element; + valueBoolean?: boolean; + _valueBoolean?: Element; + valueCanonical?: string; + _valueCanonical?: Element; + valueCode?: string; + _valueCode?: Element; + valueCodeableConcept?: CodeableConcept; + valueCodeableReference?: CodeableReference; + valueCoding?: Coding; + valueContactDetail?: ContactDetail; + valueContactPoint?: ContactPoint; + valueCount?: Count; + valueDataRequirement?: DataRequirement; + valueDate?: string; + _valueDate?: Element; + valueDateTime?: string; + _valueDateTime?: Element; + valueDecimal?: number; + _valueDecimal?: Element; + valueDistance?: Distance; + valueDosage?: Dosage; + valueDuration?: Duration; + valueExpression?: Expression; + valueExtendedContactDetail?: ExtendedContactDetail; + valueHumanName?: HumanName; + valueId?: string; + _valueId?: Element; + valueIdentifier?: Identifier; + valueInstant?: string; + _valueInstant?: Element; + valueInteger?: number; + _valueInteger?: Element; + valueInteger64?: number; + _valueInteger64?: Element; + valueMarkdown?: string; + _valueMarkdown?: Element; + valueMeta?: Meta; + valueMoney?: Money; + valueOid?: string; + _valueOid?: Element; + valueParameterDefinition?: ParameterDefinition; + valuePeriod?: Period; + valuePositiveInt?: number; + _valuePositiveInt?: Element; + valueQuantity?: Quantity; + valueRange?: Range; + valueRatio?: Ratio; + valueRatioRange?: RatioRange; + valueReference?: Reference; + valueRelatedArtifact?: RelatedArtifact; + valueSampledData?: SampledData; + valueSignature?: Signature; + valueString?: string; + _valueString?: Element; + valueTime?: string; + _valueTime?: Element; + valueTiming?: Timing; + valueTriggerDefinition?: TriggerDefinition; + valueUnsignedInt?: number; + _valueUnsignedInt?: Element; + valueUri?: string; + _valueUri?: Element; + valueUrl?: string; + _valueUrl?: Element; + valueUsageContext?: UsageContext; + valueUuid?: string; + _valueUuid?: Element; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/HumanName.ts b/src/fhir-types/hl7-fhir-r5-core/HumanName.ts new file mode 100644 index 00000000..9a4e15ae --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/HumanName.ts @@ -0,0 +1,26 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { DataType } from "../hl7-fhir-r5-core/DataType"; +import type { Period } from "../hl7-fhir-r5-core/Period"; + +export type { DataType } from "../hl7-fhir-r5-core/DataType"; +export type { Period } from "../hl7-fhir-r5-core/Period"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/HumanName +export interface HumanName extends DataType { + family?: string; + _family?: Element; + given?: string[]; + _given?: Element; + period?: Period; + prefix?: string[]; + _prefix?: Element; + suffix?: string[]; + _suffix?: Element; + text?: string; + _text?: Element; + use?: "usual" | "official" | "temp" | "nickname" | "anonymous" | "old" | "maiden"; + _use?: Element; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/Identifier.ts b/src/fhir-types/hl7-fhir-r5-core/Identifier.ts new file mode 100644 index 00000000..c8839866 --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/Identifier.ts @@ -0,0 +1,26 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { CodeableConcept } from "../hl7-fhir-r5-core/CodeableConcept"; +import type { DataType } from "../hl7-fhir-r5-core/DataType"; +import type { Period } from "../hl7-fhir-r5-core/Period"; +import type { Reference } from "../hl7-fhir-r5-core/Reference"; + +export type { CodeableConcept } from "../hl7-fhir-r5-core/CodeableConcept"; +export type { DataType } from "../hl7-fhir-r5-core/DataType"; +export type { Period } from "../hl7-fhir-r5-core/Period"; +export type { Reference } from "../hl7-fhir-r5-core/Reference"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/Identifier +export interface Identifier extends DataType { + assigner?: Reference<"Organization">; + period?: Period; + system?: string; + _system?: Element; + type?: CodeableConcept; + use?: "usual" | "official" | "temp" | "secondary" | "old"; + _use?: Element; + value?: string; + _value?: Element; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/Meta.ts b/src/fhir-types/hl7-fhir-r5-core/Meta.ts new file mode 100644 index 00000000..a4016b53 --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/Meta.ts @@ -0,0 +1,23 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { Coding } from "../hl7-fhir-r5-core/Coding"; +import type { DataType } from "../hl7-fhir-r5-core/DataType"; + +export type { Coding } from "../hl7-fhir-r5-core/Coding"; +export type { DataType } from "../hl7-fhir-r5-core/DataType"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/Meta +export interface Meta extends DataType { + lastUpdated?: string; + _lastUpdated?: Element; + profile?: string[]; + _profile?: Element; + security?: Coding[]; + source?: string; + _source?: Element; + tag?: Coding[]; + versionId?: string; + _versionId?: Element; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/Money.ts b/src/fhir-types/hl7-fhir-r5-core/Money.ts new file mode 100644 index 00000000..e2dd3f65 --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/Money.ts @@ -0,0 +1,15 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { DataType } from "../hl7-fhir-r5-core/DataType"; + +export type { DataType } from "../hl7-fhir-r5-core/DataType"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/Money +export interface Money extends DataType { + currency?: string; + _currency?: Element; + value?: number; + _value?: Element; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/Narrative.ts b/src/fhir-types/hl7-fhir-r5-core/Narrative.ts new file mode 100644 index 00000000..3f8dc9e4 --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/Narrative.ts @@ -0,0 +1,15 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { DataType } from "../hl7-fhir-r5-core/DataType"; + +export type { DataType } from "../hl7-fhir-r5-core/DataType"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/Narrative +export interface Narrative extends DataType { + div: string; + _div?: Element; + status: "generated" | "extensions" | "additional" | "empty"; + _status?: Element; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/ParameterDefinition.ts b/src/fhir-types/hl7-fhir-r5-core/ParameterDefinition.ts new file mode 100644 index 00000000..e2d42764 --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/ParameterDefinition.ts @@ -0,0 +1,25 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { DataType } from "../hl7-fhir-r5-core/DataType"; + +export type { DataType } from "../hl7-fhir-r5-core/DataType"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/ParameterDefinition +export interface ParameterDefinition extends DataType { + documentation?: string; + _documentation?: Element; + max?: string; + _max?: Element; + min?: number; + _min?: Element; + name?: string; + _name?: Element; + profile?: string; + _profile?: Element; + type: string; + _type?: Element; + use: "in" | "out"; + _use?: Element; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/Period.ts b/src/fhir-types/hl7-fhir-r5-core/Period.ts new file mode 100644 index 00000000..ca86d1cb --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/Period.ts @@ -0,0 +1,15 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { DataType } from "../hl7-fhir-r5-core/DataType"; + +export type { DataType } from "../hl7-fhir-r5-core/DataType"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/Period +export interface Period extends DataType { + end?: string; + _end?: Element; + start?: string; + _start?: Element; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/Quantity.ts b/src/fhir-types/hl7-fhir-r5-core/Quantity.ts new file mode 100644 index 00000000..e7ec2afa --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/Quantity.ts @@ -0,0 +1,21 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { DataType } from "../hl7-fhir-r5-core/DataType"; + +export type { DataType } from "../hl7-fhir-r5-core/DataType"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/Quantity +export interface Quantity extends DataType { + code?: string; + _code?: Element; + comparator?: "<" | "<=" | ">=" | ">" | "ad"; + _comparator?: Element; + system?: string; + _system?: Element; + unit?: string; + _unit?: Element; + value?: number; + _value?: Element; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/Range.ts b/src/fhir-types/hl7-fhir-r5-core/Range.ts new file mode 100644 index 00000000..03e0e265 --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/Range.ts @@ -0,0 +1,15 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { DataType } from "../hl7-fhir-r5-core/DataType"; +import type { Quantity } from "../hl7-fhir-r5-core/Quantity"; + +export type { DataType } from "../hl7-fhir-r5-core/DataType"; +export type { Quantity } from "../hl7-fhir-r5-core/Quantity"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/Range +export interface Range extends DataType { + high?: Quantity; + low?: Quantity; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/Ratio.ts b/src/fhir-types/hl7-fhir-r5-core/Ratio.ts new file mode 100644 index 00000000..0d134776 --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/Ratio.ts @@ -0,0 +1,15 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { DataType } from "../hl7-fhir-r5-core/DataType"; +import type { Quantity } from "../hl7-fhir-r5-core/Quantity"; + +export type { DataType } from "../hl7-fhir-r5-core/DataType"; +export type { Quantity } from "../hl7-fhir-r5-core/Quantity"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/Ratio +export interface Ratio extends DataType { + denominator?: Quantity; + numerator?: Quantity; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/RatioRange.ts b/src/fhir-types/hl7-fhir-r5-core/RatioRange.ts new file mode 100644 index 00000000..0fcac1b5 --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/RatioRange.ts @@ -0,0 +1,16 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { DataType } from "../hl7-fhir-r5-core/DataType"; +import type { Quantity } from "../hl7-fhir-r5-core/Quantity"; + +export type { DataType } from "../hl7-fhir-r5-core/DataType"; +export type { Quantity } from "../hl7-fhir-r5-core/Quantity"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/RatioRange +export interface RatioRange extends DataType { + denominator?: Quantity; + highNumerator?: Quantity; + lowNumerator?: Quantity; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/Reference.ts b/src/fhir-types/hl7-fhir-r5-core/Reference.ts new file mode 100644 index 00000000..1ab66c22 --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/Reference.ts @@ -0,0 +1,20 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { DataType } from "../hl7-fhir-r5-core/DataType"; +import type { Identifier } from "../hl7-fhir-r5-core/Identifier"; + +export type { DataType } from "../hl7-fhir-r5-core/DataType"; +export type { Identifier } from "../hl7-fhir-r5-core/Identifier"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/Reference +export interface Reference extends DataType { + display?: string; + _display?: Element; + identifier?: Identifier; + reference?: `${T}/${string}`; + _reference?: Element; + type?: string; + _type?: Element; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/RelatedArtifact.ts b/src/fhir-types/hl7-fhir-r5-core/RelatedArtifact.ts new file mode 100644 index 00000000..469f8c67 --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/RelatedArtifact.ts @@ -0,0 +1,34 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { Attachment } from "../hl7-fhir-r5-core/Attachment"; +import type { CodeableConcept } from "../hl7-fhir-r5-core/CodeableConcept"; +import type { DataType } from "../hl7-fhir-r5-core/DataType"; +import type { Reference } from "../hl7-fhir-r5-core/Reference"; + +export type { Attachment } from "../hl7-fhir-r5-core/Attachment"; +export type { CodeableConcept } from "../hl7-fhir-r5-core/CodeableConcept"; +export type { DataType } from "../hl7-fhir-r5-core/DataType"; +export type { Reference } from "../hl7-fhir-r5-core/Reference"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/RelatedArtifact +export interface RelatedArtifact extends DataType { + citation?: string; + _citation?: Element; + classifier?: CodeableConcept[]; + display?: string; + _display?: Element; + document?: Attachment; + label?: string; + _label?: Element; + publicationDate?: string; + _publicationDate?: Element; + publicationStatus?: "draft" | "active" | "retired" | "unknown"; + _publicationStatus?: Element; + resource?: string; + _resource?: Element; + resourceReference?: Reference<"Resource">; + type: "documentation" | "justification" | "citation" | "predecessor" | "successor" | "derived-from" | "depends-on" | "composed-of" | "part-of" | "amends" | "amended-with" | "appends" | "appended-with" | "cites" | "cited-by" | "comments-on" | "comment-in" | "contains" | "contained-in" | "corrects" | "correction-in" | "replaces" | "replaced-with" | "retracts" | "retracted-by" | "signs" | "similar-to" | "supports" | "supported-with" | "transforms" | "transformed-into" | "transformed-with" | "documents" | "specification-of" | "created-with" | "cite-as"; + _type?: Element; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/Resource.ts b/src/fhir-types/hl7-fhir-r5-core/Resource.ts new file mode 100644 index 00000000..f9872835 --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/Resource.ts @@ -0,0 +1,22 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { Base } from "../hl7-fhir-r5-core/Base"; +import type { Meta } from "../hl7-fhir-r5-core/Meta"; + +export type { Base } from "../hl7-fhir-r5-core/Base"; +export type { Meta } from "../hl7-fhir-r5-core/Meta"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/Resource +export interface Resource extends Base { + resourceType: "CanonicalResource" | "DomainResource" | "Resource" | "ViewDefinition"; + + id?: string; + _id?: Element; + implicitRules?: string; + _implicitRules?: Element; + language?: string; + _language?: Element; + meta?: Meta; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/SampledData.ts b/src/fhir-types/hl7-fhir-r5-core/SampledData.ts new file mode 100644 index 00000000..9619fbeb --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/SampledData.ts @@ -0,0 +1,32 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { DataType } from "../hl7-fhir-r5-core/DataType"; +import type { Quantity } from "../hl7-fhir-r5-core/Quantity"; + +export type { DataType } from "../hl7-fhir-r5-core/DataType"; +export type { Quantity } from "../hl7-fhir-r5-core/Quantity"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/SampledData +export interface SampledData extends DataType { + codeMap?: string; + _codeMap?: Element; + data?: string; + _data?: Element; + dimensions: number; + _dimensions?: Element; + factor?: number; + _factor?: Element; + interval?: number; + _interval?: Element; + intervalUnit: string; + _intervalUnit?: Element; + lowerLimit?: number; + _lowerLimit?: Element; + offsets?: string; + _offsets?: Element; + origin: Quantity; + upperLimit?: number; + _upperLimit?: Element; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/Signature.ts b/src/fhir-types/hl7-fhir-r5-core/Signature.ts new file mode 100644 index 00000000..cfaefe73 --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/Signature.ts @@ -0,0 +1,26 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { Coding } from "../hl7-fhir-r5-core/Coding"; +import type { DataType } from "../hl7-fhir-r5-core/DataType"; +import type { Reference } from "../hl7-fhir-r5-core/Reference"; + +export type { Coding } from "../hl7-fhir-r5-core/Coding"; +export type { DataType } from "../hl7-fhir-r5-core/DataType"; +export type { Reference } from "../hl7-fhir-r5-core/Reference"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/Signature +export interface Signature extends DataType { + data?: string; + _data?: Element; + onBehalfOf?: Reference<"Device" | "Organization" | "Patient" | "Practitioner" | "PractitionerRole" | "RelatedPerson">; + sigFormat?: string; + _sigFormat?: Element; + targetFormat?: string; + _targetFormat?: Element; + type?: Coding[]; + when?: string; + _when?: Element; + who?: Reference<"Device" | "Organization" | "Patient" | "Practitioner" | "PractitionerRole" | "RelatedPerson">; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/Timing.ts b/src/fhir-types/hl7-fhir-r5-core/Timing.ts new file mode 100644 index 00000000..80afd67c --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/Timing.ts @@ -0,0 +1,45 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { BackboneType } from "../hl7-fhir-r5-core/BackboneType"; +import type { CodeableConcept } from "../hl7-fhir-r5-core/CodeableConcept"; +import type { Duration } from "../hl7-fhir-r5-core/Duration"; +import type { Element } from "../hl7-fhir-r5-core/Element"; +import type { Period } from "../hl7-fhir-r5-core/Period"; +import type { Range } from "../hl7-fhir-r5-core/Range"; + +export type { BackboneType } from "../hl7-fhir-r5-core/BackboneType"; +export type { CodeableConcept } from "../hl7-fhir-r5-core/CodeableConcept"; +export type { Duration } from "../hl7-fhir-r5-core/Duration"; +export type { Element } from "../hl7-fhir-r5-core/Element"; +export type { Period } from "../hl7-fhir-r5-core/Period"; +export type { Range } from "../hl7-fhir-r5-core/Range"; + +export interface TimingRepeat extends Element { + boundsDuration?: Duration; + boundsPeriod?: Period; + boundsRange?: Range; + count?: number; + countMax?: number; + dayOfWeek?: "mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun"[]; + duration?: number; + durationMax?: number; + durationUnit?: "s" | "min" | "h" | "d" | "wk" | "mo" | "a"; + frequency?: number; + frequencyMax?: number; + offset?: number; + period?: number; + periodMax?: number; + periodUnit?: "s" | "min" | "h" | "d" | "wk" | "mo" | "a"; + timeOfDay?: string[]; + when?: "MORN" | "MORN.early" | "MORN.late" | "NOON" | "AFT" | "AFT.early" | "AFT.late" | "EVE" | "EVE.early" | "EVE.late" | "NIGHT" | "PHS" | "IMD" | "HS" | "WAKE" | "C" | "CM" | "CD" | "CV" | "AC" | "ACM" | "ACD" | "ACV" | "PC" | "PCM" | "PCD" | "PCV"[]; +} + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/Timing +export interface Timing extends BackboneType { + code?: CodeableConcept; + event?: string[]; + _event?: Element; + repeat?: Element; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/TriggerDefinition.ts b/src/fhir-types/hl7-fhir-r5-core/TriggerDefinition.ts new file mode 100644 index 00000000..61b4c111 --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/TriggerDefinition.ts @@ -0,0 +1,36 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { CodeableConcept } from "../hl7-fhir-r5-core/CodeableConcept"; +import type { DataRequirement } from "../hl7-fhir-r5-core/DataRequirement"; +import type { DataType } from "../hl7-fhir-r5-core/DataType"; +import type { Expression } from "../hl7-fhir-r5-core/Expression"; +import type { Reference } from "../hl7-fhir-r5-core/Reference"; +import type { Timing } from "../hl7-fhir-r5-core/Timing"; + +export type { CodeableConcept } from "../hl7-fhir-r5-core/CodeableConcept"; +export type { DataRequirement } from "../hl7-fhir-r5-core/DataRequirement"; +export type { DataType } from "../hl7-fhir-r5-core/DataType"; +export type { Expression } from "../hl7-fhir-r5-core/Expression"; +export type { Reference } from "../hl7-fhir-r5-core/Reference"; +export type { Timing } from "../hl7-fhir-r5-core/Timing"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/TriggerDefinition +export interface TriggerDefinition extends DataType { + code?: CodeableConcept; + condition?: Expression; + data?: DataRequirement[]; + name?: string; + _name?: Element; + subscriptionTopic?: string; + _subscriptionTopic?: Element; + timingDate?: string; + _timingDate?: Element; + timingDateTime?: string; + _timingDateTime?: Element; + timingReference?: Reference<"Schedule">; + timingTiming?: Timing; + type: "named-event" | "periodic" | "data-changed" | "data-added" | "data-modified" | "data-removed" | "data-accessed" | "data-access-ended"; + _type?: Element; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/UsageContext.ts b/src/fhir-types/hl7-fhir-r5-core/UsageContext.ts new file mode 100644 index 00000000..83b3d8ef --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/UsageContext.ts @@ -0,0 +1,26 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { CodeableConcept } from "../hl7-fhir-r5-core/CodeableConcept"; +import type { Coding } from "../hl7-fhir-r5-core/Coding"; +import type { DataType } from "../hl7-fhir-r5-core/DataType"; +import type { Quantity } from "../hl7-fhir-r5-core/Quantity"; +import type { Range } from "../hl7-fhir-r5-core/Range"; +import type { Reference } from "../hl7-fhir-r5-core/Reference"; + +export type { CodeableConcept } from "../hl7-fhir-r5-core/CodeableConcept"; +export type { Coding } from "../hl7-fhir-r5-core/Coding"; +export type { DataType } from "../hl7-fhir-r5-core/DataType"; +export type { Quantity } from "../hl7-fhir-r5-core/Quantity"; +export type { Range } from "../hl7-fhir-r5-core/Range"; +export type { Reference } from "../hl7-fhir-r5-core/Reference"; + +// CanonicalURL: http://hl7.org/fhir/StructureDefinition/UsageContext +export interface UsageContext extends DataType { + code: Coding; + valueCodeableConcept?: CodeableConcept; + valueQuantity?: Quantity; + valueRange?: Range; + valueReference?: Reference<"Group" | "HealthcareService" | "InsurancePlan" | "Location" | "Organization" | "PlanDefinition" | "ResearchStudy">; +} diff --git a/src/fhir-types/hl7-fhir-r5-core/index.ts b/src/fhir-types/hl7-fhir-r5-core/index.ts new file mode 100644 index 00000000..f09ff73d --- /dev/null +++ b/src/fhir-types/hl7-fhir-r5-core/index.ts @@ -0,0 +1,44 @@ +export type { Address } from "./Address"; +export type { Age } from "./Age"; +export type { Annotation } from "./Annotation"; +export type { Attachment } from "./Attachment"; +export type { Availability } from "./Availability"; +export type { BackboneElement } from "./BackboneElement"; +export type { BackboneType } from "./BackboneType"; +export type { Base } from "./Base"; +export type { CanonicalResource } from "./CanonicalResource"; +export type { CodeableConcept } from "./CodeableConcept"; +export type { CodeableReference } from "./CodeableReference"; +export type { Coding } from "./Coding"; +export type { ContactDetail } from "./ContactDetail"; +export type { ContactPoint } from "./ContactPoint"; +export type { Count } from "./Count"; +export type { DataRequirement } from "./DataRequirement"; +export type { DataType } from "./DataType"; +export type { Distance } from "./Distance"; +export type { DomainResource } from "./DomainResource"; +export type { Dosage } from "./Dosage"; +export type { Duration } from "./Duration"; +export type { Element } from "./Element"; +export type { Expression } from "./Expression"; +export type { ExtendedContactDetail } from "./ExtendedContactDetail"; +export type { Extension } from "./Extension"; +export type { HumanName } from "./HumanName"; +export type { Identifier } from "./Identifier"; +export type { Meta } from "./Meta"; +export type { Money } from "./Money"; +export type { Narrative } from "./Narrative"; +export type { ParameterDefinition } from "./ParameterDefinition"; +export type { Period } from "./Period"; +export type { Quantity } from "./Quantity"; +export type { Range } from "./Range"; +export type { Ratio } from "./Ratio"; +export type { RatioRange } from "./RatioRange"; +export type { Reference } from "./Reference"; +export type { RelatedArtifact } from "./RelatedArtifact"; +export type { Resource } from "./Resource"; +export type { SampledData } from "./SampledData"; +export type { Signature } from "./Signature"; +export type { Timing } from "./Timing"; +export type { TriggerDefinition } from "./TriggerDefinition"; +export type { UsageContext } from "./UsageContext"; diff --git a/src/fhir-types/org-sql-on-fhir-ig/ViewDefinition.ts b/src/fhir-types/org-sql-on-fhir-ig/ViewDefinition.ts new file mode 100644 index 00000000..7642c78b --- /dev/null +++ b/src/fhir-types/org-sql-on-fhir-ig/ViewDefinition.ts @@ -0,0 +1,76 @@ +// WARNING: This file is autogenerated by @atomic-ehr/codegen. +// GitHub: https://github.com/orgs/atomic-ehr/repositories +// Any manual changes made to this file may be overwritten. + +import type { BackboneElement } from "../hl7-fhir-r5-core/BackboneElement"; +import type { CanonicalResource } from "../hl7-fhir-r5-core/CanonicalResource"; + +export type { BackboneElement } from "../hl7-fhir-r5-core/BackboneElement"; + +export interface ViewDefinitionConstant extends BackboneElement { + name: string; + valueBase64Binary?: string; + valueBoolean?: boolean; + valueCanonical?: string; + valueCode?: string; + valueDate?: string; + valueDateTime?: string; + valueDecimal?: number; + valueId?: string; + valueInstant?: string; + valueInteger?: number; + valueInteger64?: number; + valueOid?: string; + valuePositiveInt?: number; + valueString?: string; + valueTime?: string; + valueUnsignedInt?: number; + valueUri?: string; + valueUrl?: string; + valueUuid?: string; +} + +export interface ViewDefinitionSelect extends BackboneElement { + column?: ViewDefinitionSelectColumn[]; + forEach?: string; + forEachOrNull?: string; + repeat?: string[]; + select?: ViewDefinitionSelect[]; + unionAll?: ViewDefinitionSelect[]; +} + +export interface ViewDefinitionSelectColumn extends BackboneElement { + collection?: boolean; + description?: string; + name: string; + path: string; + tag?: ViewDefinitionSelectColumnTag[]; + type?: string; +} + +export interface ViewDefinitionSelectColumnTag extends BackboneElement { + name: string; + value: string; +} + +export interface ViewDefinitionWhere extends BackboneElement { + description?: string; + path: string; +} + +// CanonicalURL: https://sql-on-fhir.org/ig/StructureDefinition/ViewDefinition +export interface ViewDefinition extends CanonicalResource { + resourceType: "ViewDefinition"; + + constant?: ViewDefinitionConstant[]; + fhirVersion?: "0.01" | "0.05" | "0.06" | "0.11" | "0.0" | "0.0.80" | "0.0.81" | "0.0.82" | "0.4" | "0.4.0" | "0.5" | "0.5.0" | "1.0" | "1.0.0" | "1.0.1" | "1.0.2" | "1.1" | "1.1.0" | "1.4" | "1.4.0" | "1.6" | "1.6.0" | "1.8" | "1.8.0" | "3.0" | "3.0.0" | "3.0.1" | "3.0.2" | "3.3" | "3.3.0" | "3.5" | "3.5.0" | "4.0" | "4.0.0" | "4.0.1" | "4.1" | "4.1.0" | "4.2" | "4.2.0" | "4.3" | "4.3.0" | "4.3.0-cibuild" | "4.3.0-snapshot1" | "4.4" | "4.4.0" | "4.5" | "4.5.0" | "4.6" | "4.6.0" | "5.0" | "5.0.0" | "5.0.0-cibuild" | "5.0.0-snapshot1" | "5.0.0-snapshot2" | "5.0.0-ballot" | "5.0.0-snapshot3" | "5.0.0-draft-final"[]; + _fhirVersion?: Element; + name?: string; + _name?: Element; + profile?: string[]; + _profile?: Element; + resource: string; + _resource?: Element; + select: ViewDefinitionSelect[]; + where?: ViewDefinitionWhere[]; +} diff --git a/src/fhir-types/org-sql-on-fhir-ig/index.ts b/src/fhir-types/org-sql-on-fhir-ig/index.ts new file mode 100644 index 00000000..053f9296 --- /dev/null +++ b/src/fhir-types/org-sql-on-fhir-ig/index.ts @@ -0,0 +1 @@ +export type { ViewDefinition } from "./ViewDefinition"; From 345de88895c7d0315cc031b1bab28342489ff308 Mon Sep 17 00:00:00 2001 From: Andrey Listopadov Date: Fri, 14 Nov 2025 17:50:49 +0300 Subject: [PATCH 09/39] Migrate to new types in ViewDefinition builder Co-authored-by: Aleksandr Penskoi --- package.json | 2 +- pnpm-lock.yaml | 134 +++++------ src/AidboxClient.tsx | 8 +- src/api/auth.ts | 6 +- .../ViewDefinition/code-editor-menubar.tsx | 4 +- .../editor-form-tab-content.tsx | 224 ++++++++++-------- .../ViewDefinition/example-tab-content.tsx | 18 +- src/components/ViewDefinition/page.tsx | 5 +- .../ViewDefinition/result-panel-content.tsx | 1 - src/fhir-types/hl7-fhir-r5-core/Address.ts | 38 +-- src/fhir-types/hl7-fhir-r5-core/Age.ts | 3 +- src/fhir-types/hl7-fhir-r5-core/Annotation.ts | 20 +- src/fhir-types/hl7-fhir-r5-core/Attachment.ts | 52 ++-- .../hl7-fhir-r5-core/Availability.ts | 16 +- .../hl7-fhir-r5-core/BackboneElement.ts | 2 +- .../hl7-fhir-r5-core/BackboneType.ts | 2 +- src/fhir-types/hl7-fhir-r5-core/Base.ts | 3 +- .../hl7-fhir-r5-core/CanonicalResource.ts | 64 ++--- .../hl7-fhir-r5-core/CodeableConcept.ts | 6 +- .../hl7-fhir-r5-core/CodeableReference.ts | 4 +- src/fhir-types/hl7-fhir-r5-core/Coding.ts | 20 +- .../hl7-fhir-r5-core/ContactDetail.ts | 6 +- .../hl7-fhir-r5-core/ContactPoint.ts | 18 +- src/fhir-types/hl7-fhir-r5-core/Count.ts | 3 +- .../hl7-fhir-r5-core/DataRequirement.ts | 62 ++--- src/fhir-types/hl7-fhir-r5-core/DataType.ts | 3 +- src/fhir-types/hl7-fhir-r5-core/Distance.ts | 3 +- .../hl7-fhir-r5-core/DomainResource.ts | 10 +- src/fhir-types/hl7-fhir-r5-core/Dosage.ts | 48 ++-- src/fhir-types/hl7-fhir-r5-core/Duration.ts | 3 +- src/fhir-types/hl7-fhir-r5-core/Element.ts | 6 +- src/fhir-types/hl7-fhir-r5-core/Expression.ts | 20 +- .../hl7-fhir-r5-core/ExtendedContactDetail.ts | 12 +- src/fhir-types/hl7-fhir-r5-core/Extension.ts | 152 ++++++------ src/fhir-types/hl7-fhir-r5-core/HumanName.ts | 33 ++- src/fhir-types/hl7-fhir-r5-core/Identifier.ts | 18 +- src/fhir-types/hl7-fhir-r5-core/Meta.ts | 20 +- src/fhir-types/hl7-fhir-r5-core/Money.ts | 8 +- src/fhir-types/hl7-fhir-r5-core/Narrative.ts | 8 +- .../hl7-fhir-r5-core/ParameterDefinition.ts | 28 +-- src/fhir-types/hl7-fhir-r5-core/Period.ts | 8 +- src/fhir-types/hl7-fhir-r5-core/Quantity.ts | 20 +- src/fhir-types/hl7-fhir-r5-core/Range.ts | 4 +- src/fhir-types/hl7-fhir-r5-core/Ratio.ts | 4 +- src/fhir-types/hl7-fhir-r5-core/RatioRange.ts | 6 +- src/fhir-types/hl7-fhir-r5-core/Reference.ts | 14 +- .../hl7-fhir-r5-core/RelatedArtifact.ts | 70 ++++-- src/fhir-types/hl7-fhir-r5-core/Resource.ts | 20 +- .../hl7-fhir-r5-core/SampledData.ts | 38 +-- src/fhir-types/hl7-fhir-r5-core/Signature.ts | 36 ++- src/fhir-types/hl7-fhir-r5-core/Timing.ts | 70 ++++-- .../hl7-fhir-r5-core/TriggerDefinition.ts | 38 +-- .../hl7-fhir-r5-core/UsageContext.ts | 18 +- .../org-sql-on-fhir-ig/ViewDefinition.ts | 154 ++++++++---- src/fhir-types/org-sql-on-fhir-ig/index.ts | 9 +- tsconfig.app.json | 2 +- 56 files changed, 901 insertions(+), 703 deletions(-) diff --git a/package.json b/package.json index e36f308b..9fe13fca 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "license": "MIT", "packageManager": "pnpm@10.22.0", "devDependencies": { - "@atomic-ehr/codegen": "0.0.2", + "@atomic-ehr/codegen": "canary", "@biomejs/biome": "2.1.3", "@tailwindcss/vite": "^4.1.12", "@tanstack/router-plugin": "^1.131.13", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0423b352..1500402a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -67,8 +67,8 @@ importers: version: 15.6.9 devDependencies: '@atomic-ehr/codegen': - specifier: 0.0.2 - version: 0.0.2(typescript@5.9.2) + specifier: canary + version: 0.0.2-canary.20251114134039.790395b(typescript@5.9.2) '@biomejs/biome': specifier: 2.1.3 version: 2.1.3 @@ -108,8 +108,8 @@ importers: packages: - '@atomic-ehr/codegen@0.0.2': - resolution: {integrity: sha512-u3U1uiyN2ushbCB3h81a/ntVTk9nX56CXEbPhU1Bzi/a1pxZcJGyjH0h3BT2Pazu+PYJdeiN9b/d29Ci5hk92g==} + '@atomic-ehr/codegen@0.0.2-canary.20251114134039.790395b': + resolution: {integrity: sha512-aNC1YAo3kqPJRwbQvT9/CceDmfXi1fM4kDVP9HA7lYMW8lhD1HX9Y0jJXJa7I90TAtldtliwmDnqXHW4qxIhrg==} hasBin: true '@atomic-ehr/fhir-canonical-manager@0.0.15': @@ -562,8 +562,8 @@ packages: resolution: {integrity: sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==} engines: {node: '>=18'} - '@inquirer/checkbox@4.3.1': - resolution: {integrity: sha512-rOcLotrptYIy59SGQhKlU0xBg1vvcVl2FdPIEclUvKHh0wo12OfGkId/01PIMJ/V+EimJ77t085YabgnQHBa5A==} + '@inquirer/checkbox@4.3.2': + resolution: {integrity: sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -571,8 +571,8 @@ packages: '@types/node': optional: true - '@inquirer/confirm@5.1.20': - resolution: {integrity: sha512-HDGiWh2tyRZa0M1ZnEIUCQro25gW/mN8ODByicQrbR1yHx4hT+IOpozCMi5TgBtUdklLwRI2mv14eNpftDluEw==} + '@inquirer/confirm@5.1.21': + resolution: {integrity: sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -580,8 +580,8 @@ packages: '@types/node': optional: true - '@inquirer/core@10.3.1': - resolution: {integrity: sha512-hzGKIkfomGFPgxKmnKEKeA+uCYBqC+TKtRx5LgyHRCrF6S2MliwRIjp3sUaWwVzMp7ZXVs8elB0Tfe682Rpg4w==} + '@inquirer/core@10.3.2': + resolution: {integrity: sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -589,8 +589,8 @@ packages: '@types/node': optional: true - '@inquirer/editor@4.2.22': - resolution: {integrity: sha512-8yYZ9TCbBKoBkzHtVNMF6PV1RJEUvMlhvmS3GxH4UvXMEHlS45jFyqFy0DU+K42jBs5slOaA78xGqqqWAx3u6A==} + '@inquirer/editor@4.2.23': + resolution: {integrity: sha512-aLSROkEwirotxZ1pBaP8tugXRFCxW94gwrQLxXfrZsKkfjOYC1aRvAZuhpJOb5cu4IBTJdsCigUlf2iCOu4ZDQ==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -598,8 +598,8 @@ packages: '@types/node': optional: true - '@inquirer/expand@4.0.22': - resolution: {integrity: sha512-9XOjCjvioLjwlq4S4yXzhvBmAXj5tG+jvva0uqedEsQ9VD8kZ+YT7ap23i0bIXOtow+di4+u3i6u26nDqEfY4Q==} + '@inquirer/expand@4.0.23': + resolution: {integrity: sha512-nRzdOyFYnpeYTTR2qFwEVmIWypzdAx/sIkCMeTNTcflFOovfqUk+HcFhQQVBftAh9gmGrpFj6QcGEqrDMDOiew==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -620,8 +620,8 @@ packages: resolution: {integrity: sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==} engines: {node: '>=18'} - '@inquirer/input@4.3.0': - resolution: {integrity: sha512-h4fgse5zeGsBSW3cRQqu9a99OXRdRsNCvHoBqVmz40cjYjYFzcfwD0KA96BHIPlT7rZw0IpiefQIqXrjbzjS4Q==} + '@inquirer/input@4.3.1': + resolution: {integrity: sha512-kN0pAM4yPrLjJ1XJBjDxyfDduXOuQHrBB8aLDMueuwUGn+vNpF7Gq7TvyVxx8u4SHlFFj4trmj+a2cbpG4Jn1g==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -629,8 +629,8 @@ packages: '@types/node': optional: true - '@inquirer/number@3.0.22': - resolution: {integrity: sha512-oAdMJXz++fX58HsIEYmvuf5EdE8CfBHHXjoi9cTcQzgFoHGZE+8+Y3P38MlaRMeBvAVnkWtAxMUF6urL2zYsbg==} + '@inquirer/number@3.0.23': + resolution: {integrity: sha512-5Smv0OK7K0KUzUfYUXDXQc9jrf8OHo4ktlEayFlelCjwMXz0299Y8OrI+lj7i4gCBY15UObk76q0QtxjzFcFcg==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -638,8 +638,8 @@ packages: '@types/node': optional: true - '@inquirer/password@4.0.22': - resolution: {integrity: sha512-CbdqK1ioIr0Y3akx03k/+Twf+KSlHjn05hBL+rmubMll7PsDTGH0R4vfFkr+XrkB0FOHrjIwVP9crt49dgt+1g==} + '@inquirer/password@4.0.23': + resolution: {integrity: sha512-zREJHjhT5vJBMZX/IUbyI9zVtVfOLiTO66MrF/3GFZYZ7T4YILW5MSkEYHceSii/KtRk+4i3RE7E1CUXA2jHcA==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -647,8 +647,8 @@ packages: '@types/node': optional: true - '@inquirer/prompts@7.10.0': - resolution: {integrity: sha512-X2HAjY9BClfFkJ2RP3iIiFxlct5JJVdaYYXhA7RKxsbc9KL+VbId79PSoUGH/OLS011NFbHHDMDcBKUj3T89+Q==} + '@inquirer/prompts@7.10.1': + resolution: {integrity: sha512-Dx/y9bCQcXLI5ooQ5KyvA4FTgeo2jYj/7plWfV5Ak5wDPKQZgudKez2ixyfz7tKXzcJciTxqLeK7R9HItwiByg==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -656,8 +656,8 @@ packages: '@types/node': optional: true - '@inquirer/rawlist@4.1.10': - resolution: {integrity: sha512-Du4uidsgTMkoH5izgpfyauTL/ItVHOLsVdcY+wGeoGaG56BV+/JfmyoQGniyhegrDzXpfn3D+LFHaxMDRygcAw==} + '@inquirer/rawlist@4.1.11': + resolution: {integrity: sha512-+LLQB8XGr3I5LZN/GuAHo+GpDJegQwuPARLChlMICNdwW7OwV2izlCSCxN6cqpL0sMXmbKbFcItJgdQq5EBXTw==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -665,8 +665,8 @@ packages: '@types/node': optional: true - '@inquirer/search@3.2.1': - resolution: {integrity: sha512-cKiuUvETublmTmaOneEermfG2tI9ABpb7fW/LqzZAnSv4ZaJnbEis05lOkiBuYX5hNdnX0Q9ryOQyrNidb55WA==} + '@inquirer/search@3.2.2': + resolution: {integrity: sha512-p2bvRfENXCZdWF/U2BXvnSI9h+tuA8iNqtUKb9UWbmLYCRQxd8WkvwWvYn+3NgYaNwdUkHytJMGG4MMLucI1kA==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -674,8 +674,8 @@ packages: '@types/node': optional: true - '@inquirer/select@4.4.1': - resolution: {integrity: sha512-E9hbLU4XsNe2SAOSsFrtYtYQDVi1mfbqJrPDvXKnGlnRiApBdWMJz7r3J2Ff38AqULkPUD3XjQMD4492TymD7Q==} + '@inquirer/select@4.4.2': + resolution: {integrity: sha512-l4xMuJo55MAe+N7Qr4rX90vypFwCajSakx59qe/tMaC1aEHWLyw68wF4o0A4SLAY4E0nd+Vt+EyskeDIqu1M6w==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -2365,9 +2365,9 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - mute-stream@3.0.0: - resolution: {integrity: sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw==} - engines: {node: ^20.17.0 || >=22.9.0} + mute-stream@2.0.0: + resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==} + engines: {node: ^18.17.0 || >=20.5.0} nanoid@3.3.11: resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} @@ -2847,11 +2847,11 @@ packages: snapshots: - '@atomic-ehr/codegen@0.0.2(typescript@5.9.2)': + '@atomic-ehr/codegen@0.0.2-canary.20251114134039.790395b(typescript@5.9.2)': dependencies: '@atomic-ehr/fhir-canonical-manager': 0.0.15(typescript@5.9.2) '@atomic-ehr/fhirschema': 0.0.5(typescript@5.9.2) - '@inquirer/prompts': 7.10.0 + '@inquirer/prompts': 7.10.1 ajv: 8.17.1 handlebars: 4.7.8 ora: 8.2.0 @@ -3386,39 +3386,39 @@ snapshots: '@inquirer/ansi@1.0.2': {} - '@inquirer/checkbox@4.3.1': + '@inquirer/checkbox@4.3.2': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.1 + '@inquirer/core': 10.3.2 '@inquirer/figures': 1.0.15 '@inquirer/type': 3.0.10 yoctocolors-cjs: 2.1.3 - '@inquirer/confirm@5.1.20': + '@inquirer/confirm@5.1.21': dependencies: - '@inquirer/core': 10.3.1 + '@inquirer/core': 10.3.2 '@inquirer/type': 3.0.10 - '@inquirer/core@10.3.1': + '@inquirer/core@10.3.2': dependencies: '@inquirer/ansi': 1.0.2 '@inquirer/figures': 1.0.15 '@inquirer/type': 3.0.10 cli-width: 4.1.0 - mute-stream: 3.0.0 + mute-stream: 2.0.0 signal-exit: 4.1.0 wrap-ansi: 6.2.0 yoctocolors-cjs: 2.1.3 - '@inquirer/editor@4.2.22': + '@inquirer/editor@4.2.23': dependencies: - '@inquirer/core': 10.3.1 + '@inquirer/core': 10.3.2 '@inquirer/external-editor': 1.0.3 '@inquirer/type': 3.0.10 - '@inquirer/expand@4.0.22': + '@inquirer/expand@4.0.23': dependencies: - '@inquirer/core': 10.3.1 + '@inquirer/core': 10.3.2 '@inquirer/type': 3.0.10 yoctocolors-cjs: 2.1.3 @@ -3429,52 +3429,52 @@ snapshots: '@inquirer/figures@1.0.15': {} - '@inquirer/input@4.3.0': + '@inquirer/input@4.3.1': dependencies: - '@inquirer/core': 10.3.1 + '@inquirer/core': 10.3.2 '@inquirer/type': 3.0.10 - '@inquirer/number@3.0.22': + '@inquirer/number@3.0.23': dependencies: - '@inquirer/core': 10.3.1 + '@inquirer/core': 10.3.2 '@inquirer/type': 3.0.10 - '@inquirer/password@4.0.22': + '@inquirer/password@4.0.23': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.1 + '@inquirer/core': 10.3.2 '@inquirer/type': 3.0.10 - '@inquirer/prompts@7.10.0': + '@inquirer/prompts@7.10.1': dependencies: - '@inquirer/checkbox': 4.3.1 - '@inquirer/confirm': 5.1.20 - '@inquirer/editor': 4.2.22 - '@inquirer/expand': 4.0.22 - '@inquirer/input': 4.3.0 - '@inquirer/number': 3.0.22 - '@inquirer/password': 4.0.22 - '@inquirer/rawlist': 4.1.10 - '@inquirer/search': 3.2.1 - '@inquirer/select': 4.4.1 + '@inquirer/checkbox': 4.3.2 + '@inquirer/confirm': 5.1.21 + '@inquirer/editor': 4.2.23 + '@inquirer/expand': 4.0.23 + '@inquirer/input': 4.3.1 + '@inquirer/number': 3.0.23 + '@inquirer/password': 4.0.23 + '@inquirer/rawlist': 4.1.11 + '@inquirer/search': 3.2.2 + '@inquirer/select': 4.4.2 - '@inquirer/rawlist@4.1.10': + '@inquirer/rawlist@4.1.11': dependencies: - '@inquirer/core': 10.3.1 + '@inquirer/core': 10.3.2 '@inquirer/type': 3.0.10 yoctocolors-cjs: 2.1.3 - '@inquirer/search@3.2.1': + '@inquirer/search@3.2.2': dependencies: - '@inquirer/core': 10.3.1 + '@inquirer/core': 10.3.2 '@inquirer/figures': 1.0.15 '@inquirer/type': 3.0.10 yoctocolors-cjs: 2.1.3 - '@inquirer/select@4.4.1': + '@inquirer/select@4.4.2': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.1 + '@inquirer/core': 10.3.2 '@inquirer/figures': 1.0.15 '@inquirer/type': 3.0.10 yoctocolors-cjs: 2.1.3 @@ -5135,7 +5135,7 @@ snapshots: ms@2.1.3: {} - mute-stream@3.0.0: {} + mute-stream@2.0.0: {} nanoid@3.3.11: {} diff --git a/src/AidboxClient.tsx b/src/AidboxClient.tsx index b822c8b7..45694462 100644 --- a/src/AidboxClient.tsx +++ b/src/AidboxClient.tsx @@ -17,12 +17,12 @@ function makeAuthHandler(baseurl: string) { if (response.response.status === 401 || response.response.status === 403) { const encodedLocation = btoa(window.location.href); const redirectTo = `${baseurl}/auth/login?redirect_to=${encodedLocation}`; - window.location.href = redirectTo + window.location.href = redirectTo; // FIXME: doesn't work without window.location.href - throw redirect({href: redirectTo}); + throw redirect({ href: redirectTo }); } return response; - } + }; } export function AidboxClientProvider({ @@ -31,7 +31,7 @@ export function AidboxClientProvider({ }: AidboxClientProviderProps): React.JSX.Element { const client = makeClient({ baseurl, - onRawResponseHook: makeAuthHandler(baseurl) + onRawResponseHook: makeAuthHandler(baseurl), }); return ( diff --git a/src/api/auth.ts b/src/api/auth.ts index 6bf9960c..a561fd24 100644 --- a/src/api/auth.ts +++ b/src/api/auth.ts @@ -26,11 +26,11 @@ export function useLogout() { onSuccess: () => { queryClient.removeQueries({ queryKey: ["userInfo"] }); const encodedLocation = btoa(window.location.href); - const redirectTo = `${client.getAidboxBaseUrl()}/auth/login?redirect_to=${encodedLocation}`; + const redirectTo = `${client.getAidboxBaseURL()}/auth/login?redirect_to=${encodedLocation}`; window.location.href = redirectTo; // FIXME: doesn't work without window.location.href - throw redirect({href: redirectTo}); - } + throw redirect({ href: redirectTo }); + }, }); } diff --git a/src/components/ViewDefinition/code-editor-menubar.tsx b/src/components/ViewDefinition/code-editor-menubar.tsx index c53428c6..cbebfe0e 100644 --- a/src/components/ViewDefinition/code-editor-menubar.tsx +++ b/src/components/ViewDefinition/code-editor-menubar.tsx @@ -13,7 +13,9 @@ export const CodeEditorFormatSelect = ({ onModeChange(value as "json" | "yaml")} + onValueChange={(value) => + onModeChange(value as Types.ViewDefinitionEditorMode) + } > JSON YAML diff --git a/src/components/ViewDefinition/editor-form-tab-content.tsx b/src/components/ViewDefinition/editor-form-tab-content.tsx index 0926f739..c415aee1 100644 --- a/src/components/ViewDefinition/editor-form-tab-content.tsx +++ b/src/components/ViewDefinition/editor-form-tab-content.tsx @@ -1,4 +1,9 @@ -import type { ViewDefinitionSelect } from "@aidbox-ui/fhir-types/org-sql-on-fhir-ig/ViewDefinition"; +import type { CanonicalResource } from "@aidbox-ui/fhir-types/hl7-fhir-r5-core"; +import type { + ViewDefinition, + ViewDefinitionSelect, + ViewDefinitionSelectColumn, +} from "@aidbox-ui/fhir-types/org-sql-on-fhir-ig"; import { Button, Checkbox, @@ -36,7 +41,6 @@ import React, { } from "react"; import { useDebounce, useLocalStorage } from "../../hooks"; import { ViewDefinitionContext } from "./page"; -import type * as Types from "./types"; type ItemMeta = { type: @@ -105,86 +109,117 @@ interface SelectItemInternal { } // Helper functions + +const parseColumn = (id: string, column: ViewDefinitionSelectColumn[]) => { + return { + id, + type: "column" as const, + columns: column.map((c, idx) => ({ + id: `${id}-col-${idx}-${crypto.randomUUID()}`, + name: c.name || "", + path: c.path || "", + })), + }; +}; + +const parseForEach = ( + id: string, + forEach: string, + select: ViewDefinitionSelect[] | undefined, +) => { + return { + id, + type: "forEach" as const, + expression: forEach, + children: select ? parseSelectItems(select, `${id}-`) : [], + }; +}; + +const parseForEachOrNull = ( + id: string, + forEachOrNull: string, + select: ViewDefinitionSelect[] | undefined, +) => { + return { + id, + type: "forEachOrNull" as const, + expression: forEachOrNull, + children: select ? parseSelectItems(select, `${id}-`) : [], + }; +}; + +const parseUnionAll = ( + id: string, + unionAll: ViewDefinitionSelect[] | undefined, +) => { + return { + id, + type: "unionAll" as const, + children: unionAll ? parseSelectItems(unionAll, `${id}-`) : [], + }; +}; + const parseSelectItems = ( items: ViewDefinitionSelect[], parentId = "", ): SelectItemInternal[] => { - return items - .map((item, index) => { - const id = `${parentId}select-${index}-${crypto.randomUUID()}`; - - if (item.column) { - return { - id, - type: "column" as const, - columns: item.column.map((c, idx) => ({ - id: `${id}-col-${idx}-${crypto.randomUUID()}`, - name: c.name || "", - path: c.path || "", - })), - }; - } else if (item.forEach !== undefined) { - return { - id, - type: "forEach" as const, - expression: item.forEach, - children: item.select ? parseSelectItems(item.select, `${id}-`) : [], - }; - } else if (item.forEachOrNull !== undefined) { - return { - id, - type: "forEachOrNull" as const, - expression: item.forEachOrNull, - children: item.select ? parseSelectItems(item.select, `${id}-`) : [], - }; - } else if (item.unionAll) { - return { - id, - type: "unionAll" as const, - children: parseSelectItems(item.unionAll, `${id}-`), - }; - } - return null; - }) - .filter(Boolean) as SelectItemInternal[]; + return items.flatMap((item, index) => { + const id = `${parentId}select-${index}-${crypto.randomUUID()}`; + if (item.column) return parseColumn(id, item.column); + else if (item.forEach) return parseForEach(id, item.forEach, item.select); + else if (item.forEachOrNull) + return parseForEachOrNull(id, item.forEachOrNull, item.select); + else if (item.unionAll) return parseUnionAll(id, item.unionAll); + else return []; + }); +}; + +const buildColumn = (columns: ColumnItem[]) => { + return { + column: columns.map((col) => ({ + name: col.name, + path: col.path, + })), + }; +}; + +const buildForEach = ({ expression, children }: SelectItemInternal) => { + const result: ViewDefinitionSelect = { + forEach: expression || "", + }; + if (children && children.length > 0) { + result.select = buildSelectArray(children); + } + return result; +}; + +const buildForEachOrNull = ({ expression, children }: SelectItemInternal) => { + const result: ViewDefinitionSelect = { + forEachOrNull: expression || "", + }; + if (children && children.length > 0) { + result.select = buildSelectArray(children); + } + return result; +}; + +const buildUnionAll = ({ children }: SelectItemInternal) => { + return { + unionAll: children ? buildSelectArray(children) : [], + }; }; const buildSelectArray = ( items: SelectItemInternal[], ): ViewDefinitionSelect[] => { - return items - .map((item) => { - if (item.type === "column" && item.columns) { - return { - column: item.columns.map((col) => ({ - name: col.name, - path: col.path, - })), - }; - } else if (item.type === "forEach") { - const result: ViewDefinitionSelect = { - forEach: item.expression || "", - }; - if (item.children && item.children.length > 0) { - result.select = buildSelectArray(item.children); - } - return result; - } else if (item.type === "forEachOrNull") { - const result: ViewDefinitionSelect = { - forEachOrNull: item.expression || "", - }; - if (item.children && item.children.length > 0) { - result.select = buildSelectArray(item.children); - } - return result; - } else if (item.type === "unionAll") { - return { - unionAll: item.children ? buildSelectArray(item.children) : [], - }; - } - return null; - }) - .filter(Boolean) as ViewDefinitionSelect[]; + return items.flatMap((item) => { + if (item.type === "column" && item.columns) + return buildColumn(item.columns); + else if (item.type === "forEach") return buildForEach(item); + else if (item.type === "forEachOrNull") return buildForEachOrNull(item); + else if (item.type === "unionAll") return buildUnionAll(item); + else return []; + }); }; const findPath = ( @@ -310,18 +345,7 @@ export const FormTabContent = () => { ( updatedConstants?: ConstantItem[], updatedWhere?: WhereItem[], - updatedFields?: { - name?: string; - title?: string; - description?: string; - status?: string; - url?: string; - publisher?: string; - copyright?: string; - experimental?: boolean; - fhirVersion?: string[] | undefined; - identifier?: { system?: string; value?: string }[]; - }, + updatedFields?: Partial, updatedSelectItems?: SelectItemInternal[], ) => { if (viewDefinition) { @@ -336,7 +360,7 @@ export const FormTabContent = () => { const selectArray = buildSelectArray(updatedSelectItems || selectItems); - const updatedViewDef = { + const updatedViewDef: ViewDefinition = { ...viewDefinition, ...(updatedFields || {}), }; @@ -353,13 +377,9 @@ export const FormTabContent = () => { delete updatedViewDef.where; } - if (selectArray.length > 0) { - updatedViewDef.select = selectArray; - } else { - delete (updatedViewDef as any).select; - } + updatedViewDef.select = selectArray; - viewDefinitionContext.setViewDefinition(updatedViewDef as any); + viewDefinitionContext.setViewDefinition(updatedViewDef); } }, [ @@ -458,7 +478,7 @@ export const FormTabContent = () => { }; // Function to update status field - const updateStatus = (status: string) => { + const updateStatus = (status: CanonicalResource["status"]) => { updateViewDefinition(undefined, undefined, { status }); }; @@ -483,9 +503,10 @@ export const FormTabContent = () => { }; // Function to update fhirVersion field - const updateFhirVersions = (fhirVersions: string[]) => { + const updateFhirVersions = (fhirVersions: ViewDefinition["fhirVersion"]) => { updateViewDefinition(undefined, undefined, { - fhirVersion: fhirVersions.length > 0 ? fhirVersions : undefined, + fhirVersion: + fhirVersions && fhirVersions.length > 0 ? fhirVersions : undefined, }); }; @@ -956,7 +977,6 @@ export const FormTabContent = () => { item.getItemData().children = newChildren; const itemId = item.getId(); - const _itemMeta = item.getItemData()?.meta; // Handle reordering of constants if (itemId === "_constant") { @@ -1172,8 +1192,6 @@ export const FormTabContent = () => { const customItemView = (item: ItemInstance>) => { const metaType = item.getItemData()?.meta?.type; - const _itemId = item.getId(); - const _itemProps = item.getProps(); // Helper function to render drag handle for draggable items const renderDragHandle = () => { @@ -1250,7 +1268,9 @@ export const FormTabContent = () => {