Created
July 15, 2026 07:27
-
-
Save ir4y/018110ad20bb4e2588f696f0632cfd4e to your computer and use it in GitHub Desktop.
upload-view-definitions.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bun | |
| // Uploads ViewDefinition resources from initBundle.json into a FHIR server, | |
| // then invokes $materialize on each uploaded ViewDefinition. | |
| // | |
| // Usage: | |
| // FHIR_BASE_URL=http://localhost:8080 CLIENT_ID=root CLIENT_SECRET=secret bun run upload-view-definitions.ts [path/to/bundle.json] | |
| const baseUrl = (process.env.FHIR_BASE_URL ?? "http://localhost:8080").replace(/\/$/, ""); | |
| const clientId = process.env.CLIENT_ID; | |
| const clientSecret = process.env.CLIENT_SECRET; | |
| const materializeType = process.env.MATERIALIZE_TYPE ?? "view"; // view | materialized-view | table | |
| if (!clientId || !clientSecret) { | |
| console.error("Missing CLIENT_ID / CLIENT_SECRET environment variables."); | |
| process.exit(1); | |
| } | |
| const authHeader = `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString("base64")}`; | |
| const bundlePath = process.argv[2] ?? new URL("./initBundle.json", import.meta.url).pathname; | |
| const bundle = await Bun.file(bundlePath).json(); | |
| const viewDefinitions = (bundle.entry ?? []) | |
| .map((entry: any) => entry.resource) | |
| .filter((resource: any) => resource?.resourceType === "ViewDefinition"); | |
| if (viewDefinitions.length === 0) { | |
| console.error(`No ViewDefinition resources found in ${bundlePath}`); | |
| process.exit(1); | |
| } | |
| console.log(`Found ${viewDefinitions.length} ViewDefinition resource(s) in ${bundlePath}`); | |
| async function fhirRequest(method: string, path: string, body?: unknown) { | |
| const response = await fetch(`${baseUrl}${path}`, { | |
| method, | |
| headers: { | |
| Authorization: authHeader, | |
| "Content-Type": "application/json", | |
| Accept: "application/json", | |
| }, | |
| body: body === undefined ? undefined : JSON.stringify(body), | |
| }); | |
| const text = await response.text(); | |
| const data = text ? JSON.parse(text) : undefined; | |
| if (!response.ok) { | |
| throw new Error( | |
| `${method} ${path} failed: ${response.status} ${response.statusText}\n${JSON.stringify(data, null, 2)}` | |
| ); | |
| } | |
| return data; | |
| } | |
| const uploaded: string[] = []; | |
| const failed: { id: string; stage: string; error: string }[] = []; | |
| for (const viewDefinition of viewDefinitions) { | |
| const id = viewDefinition.id; | |
| try { | |
| await fhirRequest("PUT", `/fhir/ViewDefinition/${id}`, viewDefinition); | |
| console.log(`Uploaded ViewDefinition/${id}`); | |
| uploaded.push(id); | |
| } catch (error) { | |
| console.error(`Failed to upload ViewDefinition/${id}: ${(error as Error).message}`); | |
| failed.push({ id, stage: "upload", error: (error as Error).message }); | |
| } | |
| } | |
| const materializeParameters = { | |
| resourceType: "Parameters", | |
| parameter: [{ name: "type", valueCode: materializeType }], | |
| }; | |
| for (const id of uploaded) { | |
| try { | |
| await fhirRequest("POST", `/fhir/ViewDefinition/${id}/$materialize`, materializeParameters); | |
| console.log(`Materialized ViewDefinition/${id}`); | |
| } catch (error) { | |
| console.error(`Failed to materialize ViewDefinition/${id}: ${(error as Error).message}`); | |
| failed.push({ id, stage: "materialize", error: (error as Error).message }); | |
| } | |
| } | |
| if (failed.length > 0) { | |
| console.error(`\n${failed.length} operation(s) failed:`); | |
| for (const failure of failed) { | |
| console.error(` - ${failure.id} (${failure.stage}): ${failure.error}`); | |
| } | |
| process.exit(1); | |
| } | |
| console.log(`\nDone. Uploaded and materialized ${uploaded.length} ViewDefinition resource(s).`); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment