@nhealth/fhir-terminology 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/runtime/app/components/App.d.vue.ts +25 -0
- package/dist/runtime/app/components/App.vue +9 -3
- package/dist/runtime/app/components/App.vue.d.ts +25 -0
- package/dist/runtime/server/api/fhir/terminology/[id]/import/history.get.js +4 -1
- package/dist/runtime/server/api/fhir/terminology/server/expand.get.js +4 -1
- package/dist/runtime/server/api/fhir/terminology/server/expand.post.js +4 -3
- package/dist/runtime/server/api/fhir/terminology/server/lookup.get.js +4 -1
- package/dist/runtime/server/api/fhir/terminology/server/resource.get.js +4 -1
- package/dist/runtime/server/api/fhir/terminology/server/resources.get.js +4 -1
- package/dist/runtime/server/api/fhir/terminology/server/subsumes.get.js +4 -1
- package/dist/runtime/server/api/fhir/terminology/server/validate.get.js +4 -1
- package/dist/runtime/server/functions/import.js +14 -12
- package/dist/runtime/server/utils/audit.d.ts +6 -1
- package/dist/runtime/server/utils/audit.js +2 -2
- package/dist/runtime/server/utils/state-tracker.d.ts +18 -3
- package/dist/runtime/server/utils/state-tracker.js +9 -9
- package/dist/runtime/server/utils/task.d.ts +37 -6
- package/dist/runtime/server/utils/task.js +12 -12
- package/package.json +1 -1
|
@@ -12,6 +12,31 @@ type __VLS_Props = {
|
|
|
12
12
|
* - 'memory' — in-memory only (no URL change, ideal for embedded use)
|
|
13
13
|
*/
|
|
14
14
|
mode?: 'query' | 'hash' | 'memory';
|
|
15
|
+
/**
|
|
16
|
+
* The layout orientation of the component shell.
|
|
17
|
+
* - 'horizontal' — Navigation bar at the top (default)
|
|
18
|
+
* - 'vertical' — Navigation sidebar on the left
|
|
19
|
+
* @default 'horizontal'
|
|
20
|
+
*/
|
|
21
|
+
orientation?: 'horizontal' | 'vertical';
|
|
22
|
+
/**
|
|
23
|
+
* How navigation items are matched against the current route.
|
|
24
|
+
* - 'prefix' — matches if route starts with item path (default)
|
|
25
|
+
* - 'exact' — matches only exact path
|
|
26
|
+
* @default 'prefix'
|
|
27
|
+
*/
|
|
28
|
+
activeMatch?: 'exact' | 'prefix';
|
|
29
|
+
/**
|
|
30
|
+
* The offset applied to the shell container height (e.g., for fixed headers).
|
|
31
|
+
* Can be a string (CSS value) or number (in pixels).
|
|
32
|
+
* @default 0
|
|
33
|
+
*/
|
|
34
|
+
pageOffset?: string | number;
|
|
35
|
+
/**
|
|
36
|
+
* Whether to show the leading slot (branding/logo area).
|
|
37
|
+
* @default true
|
|
38
|
+
*/
|
|
39
|
+
showLeading?: boolean;
|
|
15
40
|
};
|
|
16
41
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
17
42
|
declare const _default: typeof __VLS_export;
|
|
@@ -6,10 +6,12 @@
|
|
|
6
6
|
:mode="mode"
|
|
7
7
|
>
|
|
8
8
|
<NUtilsComponentShell
|
|
9
|
-
orientation="
|
|
9
|
+
:orientation="orientation"
|
|
10
10
|
:items="navItems"
|
|
11
|
+
:active-match="activeMatch"
|
|
12
|
+
:page-offset="pageOffset"
|
|
11
13
|
>
|
|
12
|
-
<template #leading>
|
|
14
|
+
<template v-if="showLeading" #leading>
|
|
13
15
|
<div class="px-4 py-3 border-gray-200 dark:border-gray-800 flex items-center gap-2.5">
|
|
14
16
|
<div class="flex items-center justify-center w-7 h-7 rounded-lg bg-primary-100 dark:bg-primary-900/40 shrink-0">
|
|
15
17
|
<UIcon name="i-lucide-book-marked" class="w-4 h-4 text-primary-600 dark:text-primary-400" />
|
|
@@ -32,7 +34,11 @@ import PackageImportPage from "../pages/packages/[id]/import.vue";
|
|
|
32
34
|
import ServerPage from "../pages/server.vue";
|
|
33
35
|
defineProps({
|
|
34
36
|
base: { type: String, required: false, default: "view" },
|
|
35
|
-
mode: { type: String, required: false, default: "query" }
|
|
37
|
+
mode: { type: String, required: false, default: "query" },
|
|
38
|
+
orientation: { type: String, required: false, default: "horizontal" },
|
|
39
|
+
activeMatch: { type: String, required: false, default: "prefix" },
|
|
40
|
+
pageOffset: { type: [String, Number], required: false, default: 0 },
|
|
41
|
+
showLeading: { type: Boolean, required: false, default: true }
|
|
36
42
|
});
|
|
37
43
|
const navItems = [
|
|
38
44
|
[
|
|
@@ -12,6 +12,31 @@ type __VLS_Props = {
|
|
|
12
12
|
* - 'memory' — in-memory only (no URL change, ideal for embedded use)
|
|
13
13
|
*/
|
|
14
14
|
mode?: 'query' | 'hash' | 'memory';
|
|
15
|
+
/**
|
|
16
|
+
* The layout orientation of the component shell.
|
|
17
|
+
* - 'horizontal' — Navigation bar at the top (default)
|
|
18
|
+
* - 'vertical' — Navigation sidebar on the left
|
|
19
|
+
* @default 'horizontal'
|
|
20
|
+
*/
|
|
21
|
+
orientation?: 'horizontal' | 'vertical';
|
|
22
|
+
/**
|
|
23
|
+
* How navigation items are matched against the current route.
|
|
24
|
+
* - 'prefix' — matches if route starts with item path (default)
|
|
25
|
+
* - 'exact' — matches only exact path
|
|
26
|
+
* @default 'prefix'
|
|
27
|
+
*/
|
|
28
|
+
activeMatch?: 'exact' | 'prefix';
|
|
29
|
+
/**
|
|
30
|
+
* The offset applied to the shell container height (e.g., for fixed headers).
|
|
31
|
+
* Can be a string (CSS value) or number (in pixels).
|
|
32
|
+
* @default 0
|
|
33
|
+
*/
|
|
34
|
+
pageOffset?: string | number;
|
|
35
|
+
/**
|
|
36
|
+
* Whether to show the leading slot (branding/logo area).
|
|
37
|
+
* @default true
|
|
38
|
+
*/
|
|
39
|
+
showLeading?: boolean;
|
|
15
40
|
};
|
|
16
41
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
17
42
|
declare const _default: typeof __VLS_export;
|
|
@@ -7,7 +7,10 @@ export default defineEventHandler(async (event) => {
|
|
|
7
7
|
const query = getQuery(event);
|
|
8
8
|
const dryRun = query.dryRun === "true";
|
|
9
9
|
const taskCode = dryRun ? "dry-run" : "import";
|
|
10
|
-
const fhir = useFhirServer(
|
|
10
|
+
const fhir = useFhirServer(void 0, {
|
|
11
|
+
useAppCredentials: true
|
|
12
|
+
// Use app-level credentials to read Task history
|
|
13
|
+
});
|
|
11
14
|
try {
|
|
12
15
|
const searchResult = await fhir.$fetch("/Task", {
|
|
13
16
|
query: {
|
|
@@ -12,7 +12,10 @@ export default defineEventHandler(async (event) => {
|
|
|
12
12
|
if (!url && !system) {
|
|
13
13
|
throw createError({ statusCode: 400, message: "url or system is required for ValueSet $expand" });
|
|
14
14
|
}
|
|
15
|
-
const fhir = useFhirServer(
|
|
15
|
+
const fhir = useFhirServer(void 0, {
|
|
16
|
+
useAppCredentials: true
|
|
17
|
+
// Use app-level credentials for terminology operations
|
|
18
|
+
});
|
|
16
19
|
const params = new URLSearchParams();
|
|
17
20
|
if (url) {
|
|
18
21
|
params.set("url", url);
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { useFhirServer, defineEventHandler, readBody, createError } from "#imports";
|
|
2
2
|
export default defineEventHandler(async (event) => {
|
|
3
|
-
const fhirServer = useFhirServer(
|
|
3
|
+
const fhirServer = useFhirServer(void 0, {
|
|
4
|
+
useAppCredentials: true
|
|
5
|
+
// Use app-level credentials for terminology operations
|
|
6
|
+
});
|
|
4
7
|
const valueSet = await readBody(event);
|
|
5
|
-
console.log("[expand.post] Request ValueSet:", JSON.stringify(valueSet, null, 2));
|
|
6
8
|
try {
|
|
7
9
|
const result = await fhirServer.$fetch("/ValueSet/$expand", {
|
|
8
10
|
method: "POST",
|
|
9
11
|
body: valueSet
|
|
10
12
|
});
|
|
11
|
-
console.log("[expand.post] Success, contains:", result?.expansion?.contains?.length || 0);
|
|
12
13
|
return result;
|
|
13
14
|
} catch (err) {
|
|
14
15
|
console.error("[expand.post] Error:", err.statusCode, err.statusMessage);
|
|
@@ -11,7 +11,10 @@ export default defineEventHandler(async (event) => {
|
|
|
11
11
|
if (!system) {
|
|
12
12
|
throw createError({ statusCode: 400, message: "system (canonical URL) is required" });
|
|
13
13
|
}
|
|
14
|
-
const fhir = useFhirServer(
|
|
14
|
+
const fhir = useFhirServer(void 0, {
|
|
15
|
+
useAppCredentials: true
|
|
16
|
+
// Use app-level credentials for terminology operations
|
|
17
|
+
});
|
|
15
18
|
const params = new URLSearchParams();
|
|
16
19
|
params.set("system", system);
|
|
17
20
|
params.set("code", code);
|
|
@@ -9,6 +9,9 @@ export default defineEventHandler(async (event) => {
|
|
|
9
9
|
if (!id) {
|
|
10
10
|
throw createError({ statusCode: 400, message: "id is required" });
|
|
11
11
|
}
|
|
12
|
-
const fhir = useFhirServer(
|
|
12
|
+
const fhir = useFhirServer(void 0, {
|
|
13
|
+
useAppCredentials: true
|
|
14
|
+
// Use app-level credentials for terminology operations
|
|
15
|
+
});
|
|
13
16
|
return fhir.read(resourceType, id);
|
|
14
17
|
});
|
|
@@ -25,7 +25,10 @@ export default defineEventHandler(async (event) => {
|
|
|
25
25
|
const status = query.status?.trim() || void 0;
|
|
26
26
|
const url = query.url?.trim() || void 0;
|
|
27
27
|
const version = query.version?.trim() || void 0;
|
|
28
|
-
const fhir = useFhirServer(
|
|
28
|
+
const fhir = useFhirServer(void 0, {
|
|
29
|
+
useAppCredentials: true
|
|
30
|
+
// Use app-level credentials for terminology operations
|
|
31
|
+
});
|
|
29
32
|
const offset = (page - 1) * pageSize;
|
|
30
33
|
const baseQuery = {
|
|
31
34
|
_count: String(pageSize),
|
|
@@ -11,7 +11,10 @@ export default defineEventHandler(async (event) => {
|
|
|
11
11
|
if (!system) {
|
|
12
12
|
throw createError({ statusCode: 400, message: "system (canonical URL) is required" });
|
|
13
13
|
}
|
|
14
|
-
const fhir = useFhirServer(
|
|
14
|
+
const fhir = useFhirServer(void 0, {
|
|
15
|
+
useAppCredentials: true
|
|
16
|
+
// Use app-level credentials for terminology operations
|
|
17
|
+
});
|
|
15
18
|
const params = new URLSearchParams();
|
|
16
19
|
params.set("system", system);
|
|
17
20
|
params.set("codeA", codeA);
|
|
@@ -19,7 +19,10 @@ export default defineEventHandler(async (event) => {
|
|
|
19
19
|
if (resourceType === "ValueSet" && !system) {
|
|
20
20
|
throw createError({ statusCode: 400, message: "system is required for ValueSet validation" });
|
|
21
21
|
}
|
|
22
|
-
const fhir = useFhirServer(
|
|
22
|
+
const fhir = useFhirServer(void 0, {
|
|
23
|
+
useAppCredentials: true
|
|
24
|
+
// Use app-level credentials for terminology operations
|
|
25
|
+
});
|
|
23
26
|
const params = new URLSearchParams();
|
|
24
27
|
params.set("code", code);
|
|
25
28
|
params.set("url", url);
|
|
@@ -29,7 +29,9 @@ function buildImportParameters(batch, systemUrl, serverAssignedId) {
|
|
|
29
29
|
const parameters = {
|
|
30
30
|
resourceType: "Parameters",
|
|
31
31
|
parameter: [
|
|
32
|
-
|
|
32
|
+
// Always include system URI to ensure import goes to correct CodeSystem,
|
|
33
|
+
// even when using /CodeSystem/{id}/$import endpoint
|
|
34
|
+
{ name: "system", valueUri: systemUrl },
|
|
33
35
|
...batch.map((concept) => ({
|
|
34
36
|
name: "concept",
|
|
35
37
|
valueCoding: {
|
|
@@ -127,7 +129,8 @@ async function submitImportBatch(fhir, importUrl, systemUrl, batch, codeSystemId
|
|
|
127
129
|
}
|
|
128
130
|
}
|
|
129
131
|
async function importCodeSystem(codeSystem, taskId) {
|
|
130
|
-
const
|
|
132
|
+
const appFhir = useFhirServer(void 0, { useAppCredentials: true });
|
|
133
|
+
const serviceAccountFhir = useFhirServer(void 0, { serviceAccount: true });
|
|
131
134
|
const url = codeSystem.url;
|
|
132
135
|
const version = codeSystem.version;
|
|
133
136
|
const id = codeSystem.id;
|
|
@@ -151,8 +154,8 @@ async function importCodeSystem(codeSystem, taskId) {
|
|
|
151
154
|
delete metadata.concept;
|
|
152
155
|
metadata.content = "not-present";
|
|
153
156
|
metadata.count = concepts?.length ?? 0;
|
|
154
|
-
const createdCodeSystem = await upsertResource(metadata, taskId);
|
|
155
|
-
const serverAssignedId = await resolveResourceId(createdCodeSystem, metadata, taskId);
|
|
157
|
+
const createdCodeSystem = await upsertResource(metadata, appFhir, taskId);
|
|
158
|
+
const serverAssignedId = await resolveResourceId(createdCodeSystem, metadata, appFhir, taskId);
|
|
156
159
|
logger.info("CodeSystem metadata upsert completed", {
|
|
157
160
|
codeSystemId: id,
|
|
158
161
|
url,
|
|
@@ -215,7 +218,7 @@ async function importCodeSystem(codeSystem, taskId) {
|
|
|
215
218
|
batchSize: batch.length
|
|
216
219
|
});
|
|
217
220
|
try {
|
|
218
|
-
await submitImportBatch(
|
|
221
|
+
await submitImportBatch(serviceAccountFhir, importUrl, url, batch, id, batchLabel, serverAssignedId);
|
|
219
222
|
importedConcepts += batch.length;
|
|
220
223
|
completedBatches += 1;
|
|
221
224
|
logger.info("CodeSystem $import batch succeeded", {
|
|
@@ -258,7 +261,7 @@ async function verifyImportedCodeSystem(input) {
|
|
|
258
261
|
if (!input.sampleConcept?.code) {
|
|
259
262
|
return;
|
|
260
263
|
}
|
|
261
|
-
const fhir = useFhirServer();
|
|
264
|
+
const fhir = useFhirServer(void 0, { useAppCredentials: true });
|
|
262
265
|
const lookupUrl = input.serverAssignedId ? `/CodeSystem/${input.serverAssignedId}/$lookup?code=${encodeURIComponent(input.sampleConcept.code)}` : `/CodeSystem/$lookup?system=${encodeURIComponent(input.url)}&code=${encodeURIComponent(input.sampleConcept.code)}${input.version ? `&version=${encodeURIComponent(input.version)}` : ""}`;
|
|
263
266
|
try {
|
|
264
267
|
const result = await fhir.$fetch(lookupUrl);
|
|
@@ -295,12 +298,11 @@ async function verifyImportedCodeSystem(input) {
|
|
|
295
298
|
throw new Error(`Post-import verification failed for CodeSystem "${input.codeSystemId}" and code "${input.sampleConcept.code}": ${toErrorMessage(error)}`);
|
|
296
299
|
}
|
|
297
300
|
}
|
|
298
|
-
async function resolveResourceId(upsertedResource, resource, taskId) {
|
|
301
|
+
async function resolveResourceId(upsertedResource, resource, fhir, taskId) {
|
|
299
302
|
const directId = upsertedResource?.id;
|
|
300
303
|
if (typeof directId === "string" && directId.length > 0) {
|
|
301
304
|
return directId;
|
|
302
305
|
}
|
|
303
|
-
const fhir = useFhirServer();
|
|
304
306
|
const resourceType = String(resource.resourceType || "");
|
|
305
307
|
const url = resource.url;
|
|
306
308
|
const version = resource.version;
|
|
@@ -343,8 +345,7 @@ async function resolveResourceId(upsertedResource, resource, taskId) {
|
|
|
343
345
|
return void 0;
|
|
344
346
|
}
|
|
345
347
|
}
|
|
346
|
-
async function upsertResource(resource, taskId) {
|
|
347
|
-
const fhir = useFhirServer();
|
|
348
|
+
async function upsertResource(resource, fhir, taskId) {
|
|
348
349
|
const resourceType = String(resource.resourceType || "");
|
|
349
350
|
const url = resource.url;
|
|
350
351
|
const version = resource.version;
|
|
@@ -501,6 +502,7 @@ async function runSinglePackageImport(packageId, dryRun, forceReimport, taskId)
|
|
|
501
502
|
};
|
|
502
503
|
}
|
|
503
504
|
if (!dryRun) {
|
|
505
|
+
const appFhir = useFhirServer(void 0, { useAppCredentials: true });
|
|
504
506
|
await saveImportState({
|
|
505
507
|
packageId,
|
|
506
508
|
version: manifest.version ?? "unknown",
|
|
@@ -514,10 +516,10 @@ async function runSinglePackageImport(packageId, dryRun, forceReimport, taskId)
|
|
|
514
516
|
if (resourceConcepts && resourceConcepts.length > 0) {
|
|
515
517
|
await importCodeSystem({ ...resource, concept: resourceConcepts }, taskId);
|
|
516
518
|
} else {
|
|
517
|
-
await upsertResource(resource, taskId);
|
|
519
|
+
await upsertResource(resource, appFhir, taskId);
|
|
518
520
|
}
|
|
519
521
|
} else {
|
|
520
|
-
await upsertResource(resource, taskId);
|
|
522
|
+
await upsertResource(resource, appFhir, taskId);
|
|
521
523
|
}
|
|
522
524
|
}
|
|
523
525
|
await saveImportState({
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type H3Event } from '#imports';
|
|
1
2
|
export interface TerminologyAuditInput {
|
|
2
3
|
action: 'C' | 'R' | 'U' | 'D' | 'E';
|
|
3
4
|
outcome?: '0' | '4' | '8' | '12';
|
|
@@ -12,7 +13,11 @@ export interface TerminologyAuditInput {
|
|
|
12
13
|
*
|
|
13
14
|
* This keeps import/upload activities traceable on the target FHIR server.
|
|
14
15
|
* Returns the created AuditEvent resource with its ID.
|
|
16
|
+
*
|
|
17
|
+
* @param input - The audit event input
|
|
18
|
+
* @param event - Optional H3Event (if available from request handler).
|
|
19
|
+
* If provided, uses user session auth. If not, uses app credentials.
|
|
15
20
|
*/
|
|
16
|
-
export declare function createTerminologyAuditEvent(input: TerminologyAuditInput): Promise<{
|
|
21
|
+
export declare function createTerminologyAuditEvent(input: TerminologyAuditInput, event?: H3Event): Promise<{
|
|
17
22
|
id: string;
|
|
18
23
|
}>;
|
|
@@ -48,8 +48,8 @@ function stringifyAuditDetails(details) {
|
|
|
48
48
|
summary: safeDetails
|
|
49
49
|
}).slice(0, MAX_AUDIT_DETAIL_LENGTH);
|
|
50
50
|
}
|
|
51
|
-
export async function createTerminologyAuditEvent(input) {
|
|
52
|
-
const fhir = useFhirServer();
|
|
51
|
+
export async function createTerminologyAuditEvent(input, event) {
|
|
52
|
+
const fhir = useFhirServer(event, event ? void 0 : { useAppCredentials: true });
|
|
53
53
|
const detailText = input.details ? stringifyAuditDetails(input.details) : void 0;
|
|
54
54
|
const entityName = [input.packageId, input.packageVersion].filter(Boolean).join("#") || "terminology";
|
|
55
55
|
const response = await fhir.create("AuditEvent", {
|
|
@@ -30,15 +30,24 @@
|
|
|
30
30
|
* ```
|
|
31
31
|
*/
|
|
32
32
|
import type { ImportState } from '../../types/state.js';
|
|
33
|
+
import { type H3Event } from '#imports';
|
|
33
34
|
/**
|
|
34
35
|
* Load the current import state for a package from the FHIR server.
|
|
35
36
|
* Returns `undefined` when no state exists yet.
|
|
37
|
+
*
|
|
38
|
+
* @param packageId - The package ID to load state for
|
|
39
|
+
* @param event - Optional H3Event (if available from request handler).
|
|
40
|
+
* If provided, uses user session auth. If not, uses service account.
|
|
36
41
|
*/
|
|
37
|
-
export declare function loadImportState(packageId: string): Promise<ImportState | undefined>;
|
|
42
|
+
export declare function loadImportState(packageId: string, event?: H3Event): Promise<ImportState | undefined>;
|
|
38
43
|
/**
|
|
39
44
|
* Persist (upsert) an import state record on the FHIR server.
|
|
45
|
+
*
|
|
46
|
+
* @param state - The import state to persist
|
|
47
|
+
* @param event - Optional H3Event (if available from request handler).
|
|
48
|
+
* If provided, uses user session auth. If not, uses app credentials.
|
|
40
49
|
*/
|
|
41
|
-
export declare function saveImportState(state: ImportState): Promise<void>;
|
|
50
|
+
export declare function saveImportState(state: ImportState, event?: H3Event): Promise<void>;
|
|
42
51
|
/**
|
|
43
52
|
* Check whether a package needs to be (re-)imported.
|
|
44
53
|
*
|
|
@@ -47,8 +56,14 @@ export declare function saveImportState(state: ImportState): Promise<void>;
|
|
|
47
56
|
* - The stored source hash differs from the current hash (file changed), OR
|
|
48
57
|
* - The stored version differs from the manifest version, OR
|
|
49
58
|
* - The previous import has status `failed`
|
|
59
|
+
*
|
|
60
|
+
* @param packageId - The package ID to check
|
|
61
|
+
* @param version - The current version from the manifest
|
|
62
|
+
* @param currentHash - The current source hash
|
|
63
|
+
* @param event - Optional H3Event (if available from request handler).
|
|
64
|
+
* If provided, uses user session auth. If not, uses service account.
|
|
50
65
|
*/
|
|
51
|
-
export declare function needsImport(packageId: string, version: string, currentHash: string): Promise<{
|
|
66
|
+
export declare function needsImport(packageId: string, version: string, currentHash: string, event?: H3Event): Promise<{
|
|
52
67
|
needed: boolean;
|
|
53
68
|
reason: string;
|
|
54
69
|
existing?: ImportState;
|
|
@@ -34,8 +34,8 @@ function compareByLastUpdatedDesc(a, b) {
|
|
|
34
34
|
const bUpdated = b.meta?.lastUpdated ?? "";
|
|
35
35
|
return bUpdated.localeCompare(aUpdated);
|
|
36
36
|
}
|
|
37
|
-
async function findLatestStateResource(packageId) {
|
|
38
|
-
const fhir = useFhirServer();
|
|
37
|
+
async function findLatestStateResource(packageId, event) {
|
|
38
|
+
const fhir = useFhirServer(event, event ? void 0 : { useAppCredentials: true });
|
|
39
39
|
const bundle = await fhir.search("Basic", {
|
|
40
40
|
code: `${TERMINOLOGY_STATE_SYSTEM}|import-state`,
|
|
41
41
|
_count: "200",
|
|
@@ -72,13 +72,13 @@ function parseBasicResource(resource) {
|
|
|
72
72
|
fhirResourceId: resource.id
|
|
73
73
|
};
|
|
74
74
|
}
|
|
75
|
-
export async function loadImportState(packageId) {
|
|
76
|
-
const resource = await findLatestStateResource(packageId);
|
|
75
|
+
export async function loadImportState(packageId, event) {
|
|
76
|
+
const resource = await findLatestStateResource(packageId, event);
|
|
77
77
|
return resource ? parseBasicResource(resource) ?? void 0 : void 0;
|
|
78
78
|
}
|
|
79
|
-
export async function saveImportState(state) {
|
|
80
|
-
const fhir = useFhirServer();
|
|
81
|
-
const existing = await findLatestStateResource(state.packageId);
|
|
79
|
+
export async function saveImportState(state, event) {
|
|
80
|
+
const fhir = useFhirServer(event, event ? void 0 : { useAppCredentials: true });
|
|
81
|
+
const existing = await findLatestStateResource(state.packageId, event);
|
|
82
82
|
if (existing?.id) {
|
|
83
83
|
const resource2 = buildBasicResource(state, existing.id);
|
|
84
84
|
await fhir.update("Basic", existing.id, resource2);
|
|
@@ -87,8 +87,8 @@ export async function saveImportState(state) {
|
|
|
87
87
|
const resource = buildBasicResource(state);
|
|
88
88
|
await fhir.create("Basic", resource);
|
|
89
89
|
}
|
|
90
|
-
export async function needsImport(packageId, version, currentHash) {
|
|
91
|
-
const existing = await loadImportState(packageId);
|
|
90
|
+
export async function needsImport(packageId, version, currentHash, event) {
|
|
91
|
+
const existing = await loadImportState(packageId, event);
|
|
92
92
|
if (!existing) {
|
|
93
93
|
return { needed: true, reason: "no-prior-state" };
|
|
94
94
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type H3Event } from '#imports';
|
|
1
2
|
export type TerminologyTaskCode = 'import' | 'dry-run';
|
|
2
3
|
export type TerminologyTaskStatus = 'requested' | 'in-progress' | 'completed' | 'failed' | 'cancelled';
|
|
3
4
|
export interface TerminologyTaskInput {
|
|
@@ -26,29 +27,59 @@ export interface TerminologyTaskUpdate {
|
|
|
26
27
|
* - Output fields for storing results (CodeSystems, ValueSets, concept counts, etc.)
|
|
27
28
|
* - Links to related AuditEvent resources
|
|
28
29
|
* - Full FHIR-native observability
|
|
30
|
+
*
|
|
31
|
+
* @param input - Task input parameters
|
|
32
|
+
* @param event - Optional H3Event (if available from request handler).
|
|
33
|
+
* If provided, uses user session auth. If not, uses app credentials.
|
|
34
|
+
*
|
|
35
|
+
* Uses app credentials for background jobs (no user session available).
|
|
29
36
|
*/
|
|
30
|
-
export declare function createTerminologyTask(input: TerminologyTaskInput): Promise<{
|
|
37
|
+
export declare function createTerminologyTask(input: TerminologyTaskInput, event?: H3Event): Promise<{
|
|
31
38
|
id: string;
|
|
32
39
|
taskUrl: string;
|
|
33
40
|
}>;
|
|
34
41
|
/**
|
|
35
42
|
* Update an existing FHIR Task resource with new status, progress, or output.
|
|
43
|
+
*
|
|
44
|
+
* @param taskId - The Task ID to update
|
|
45
|
+
* @param update - The update parameters
|
|
46
|
+
* @param event - Optional H3Event (if available from request handler).
|
|
47
|
+
* If provided, uses user session auth. If not, uses app credentials.
|
|
48
|
+
*
|
|
49
|
+
* Uses app credentials for background jobs (no user session available).
|
|
36
50
|
*/
|
|
37
|
-
export declare function updateTerminologyTask(taskId: string, update: TerminologyTaskUpdate): Promise<void>;
|
|
51
|
+
export declare function updateTerminologyTask(taskId: string, update: TerminologyTaskUpdate, event?: H3Event): Promise<void>;
|
|
38
52
|
/**
|
|
39
53
|
* Read a FHIR Task resource by ID.
|
|
54
|
+
*
|
|
55
|
+
* @param taskId - The Task ID to fetch
|
|
56
|
+
* @param event - Optional H3Event (if available from request handler).
|
|
57
|
+
* If provided, uses user session auth. If not, uses app credentials.
|
|
40
58
|
*/
|
|
41
|
-
export declare function getTerminologyTask(taskId: string): Promise<Record<string, unknown> | null>;
|
|
59
|
+
export declare function getTerminologyTask(taskId: string, event?: H3Event): Promise<Record<string, unknown> | null>;
|
|
42
60
|
/**
|
|
43
61
|
* Get the most recent completed Task for a given package ID and task code.
|
|
62
|
+
*
|
|
63
|
+
* @param packageId - The package ID to search for
|
|
64
|
+
* @param taskCode - The task code (dry-run or import)
|
|
65
|
+
* @param event - Optional H3Event (if available from request handler).
|
|
66
|
+
* If provided, uses user session auth. If not, uses app credentials.
|
|
44
67
|
*/
|
|
45
|
-
export declare function getLastCompletedTask(packageId: string, taskCode?: 'dry-run' | 'import'): Promise<Record<string, unknown> | null>;
|
|
68
|
+
export declare function getLastCompletedTask(packageId: string, taskCode?: 'dry-run' | 'import', event?: H3Event): Promise<Record<string, unknown> | null>;
|
|
46
69
|
/**
|
|
47
70
|
* Add an AuditEvent reference to a Task resource.
|
|
71
|
+
*
|
|
72
|
+
* @param taskId - The Task ID to update
|
|
73
|
+
* @param auditEventId - The AuditEvent ID to link
|
|
74
|
+
* @param event - Optional H3Event (if available from request handler)
|
|
48
75
|
*/
|
|
49
|
-
export declare function linkAuditEventToTask(taskId: string, auditEventId: string): Promise<void>;
|
|
76
|
+
export declare function linkAuditEventToTask(taskId: string, auditEventId: string, event?: H3Event): Promise<void>;
|
|
50
77
|
/**
|
|
51
78
|
* Add dry-run results to a Task's output.
|
|
79
|
+
*
|
|
80
|
+
* @param taskId - The Task ID to update
|
|
81
|
+
* @param results - The dry-run results to add
|
|
82
|
+
* @param event - Optional H3Event (if available from request handler)
|
|
52
83
|
*/
|
|
53
84
|
export declare function addDryRunResultsToTask(taskId: string, results: {
|
|
54
85
|
codeSystemCount?: number;
|
|
@@ -56,4 +87,4 @@ export declare function addDryRunResultsToTask(taskId: string, results: {
|
|
|
56
87
|
conceptCount?: number;
|
|
57
88
|
resources?: Array<Record<string, unknown>>;
|
|
58
89
|
message?: string;
|
|
59
|
-
}): Promise<void>;
|
|
90
|
+
}, event?: H3Event): Promise<void>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useFhirServer } from "#imports";
|
|
2
|
-
export async function createTerminologyTask(input) {
|
|
3
|
-
const fhir = useFhirServer();
|
|
2
|
+
export async function createTerminologyTask(input, event) {
|
|
3
|
+
const fhir = useFhirServer(event, event ? void 0 : { useAppCredentials: true });
|
|
4
4
|
const task = {
|
|
5
5
|
resourceType: "Task",
|
|
6
6
|
identifier: [
|
|
@@ -55,8 +55,8 @@ export async function createTerminologyTask(input) {
|
|
|
55
55
|
taskUrl: `/Task/${response.id}`
|
|
56
56
|
};
|
|
57
57
|
}
|
|
58
|
-
export async function updateTerminologyTask(taskId, update) {
|
|
59
|
-
const fhir = useFhirServer();
|
|
58
|
+
export async function updateTerminologyTask(taskId, update, event) {
|
|
59
|
+
const fhir = useFhirServer(event, event ? void 0 : { useAppCredentials: true });
|
|
60
60
|
const current = await fhir.$fetch(`/Task/${taskId}`);
|
|
61
61
|
const patched = {
|
|
62
62
|
...current,
|
|
@@ -98,8 +98,8 @@ export async function updateTerminologyTask(taskId, update) {
|
|
|
98
98
|
body: patched
|
|
99
99
|
});
|
|
100
100
|
}
|
|
101
|
-
export async function getTerminologyTask(taskId) {
|
|
102
|
-
const fhir = useFhirServer();
|
|
101
|
+
export async function getTerminologyTask(taskId, event) {
|
|
102
|
+
const fhir = useFhirServer(event, event ? void 0 : { useAppCredentials: true });
|
|
103
103
|
try {
|
|
104
104
|
const task = await fhir.$fetch(`/Task/${taskId}`);
|
|
105
105
|
return task;
|
|
@@ -111,8 +111,8 @@ export async function getTerminologyTask(taskId) {
|
|
|
111
111
|
throw error;
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
|
-
export async function getLastCompletedTask(packageId, taskCode = "dry-run") {
|
|
115
|
-
const fhir = useFhirServer();
|
|
114
|
+
export async function getLastCompletedTask(packageId, taskCode = "dry-run", event) {
|
|
115
|
+
const fhir = useFhirServer(event, event ? void 0 : { useAppCredentials: true });
|
|
116
116
|
try {
|
|
117
117
|
const searchResult = await fhir.$fetch("/Task", {
|
|
118
118
|
query: {
|
|
@@ -131,15 +131,15 @@ export async function getLastCompletedTask(packageId, taskCode = "dry-run") {
|
|
|
131
131
|
return null;
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
|
-
export async function linkAuditEventToTask(taskId, auditEventId) {
|
|
134
|
+
export async function linkAuditEventToTask(taskId, auditEventId, event) {
|
|
135
135
|
await updateTerminologyTask(taskId, {
|
|
136
136
|
output: [{
|
|
137
137
|
type: "auditEvent",
|
|
138
138
|
value: `AuditEvent/${auditEventId}`
|
|
139
139
|
}]
|
|
140
|
-
});
|
|
140
|
+
}, event);
|
|
141
141
|
}
|
|
142
|
-
export async function addDryRunResultsToTask(taskId, results) {
|
|
142
|
+
export async function addDryRunResultsToTask(taskId, results, event) {
|
|
143
143
|
const outputs = [];
|
|
144
144
|
if (results.codeSystemCount !== void 0) {
|
|
145
145
|
outputs.push({
|
|
@@ -177,5 +177,5 @@ export async function addDryRunResultsToTask(taskId, results) {
|
|
|
177
177
|
value: summary
|
|
178
178
|
});
|
|
179
179
|
}
|
|
180
|
-
await updateTerminologyTask(taskId, { output: outputs });
|
|
180
|
+
await updateTerminologyTask(taskId, { output: outputs }, event);
|
|
181
181
|
}
|