@ovok/core 0.3.4 → 0.3.6
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/README.md +32 -0
- package/dist/client/ovok-client.d.ts +9 -2
- package/dist/client/ovok-client.js +11 -0
- package/dist/client/platform/methods.d.ts +41 -0
- package/dist/client/platform/methods.js +102 -0
- package/dist/client/platform/types.d.ts +114 -0
- package/dist/client/platform/types.js +27 -0
- package/dist/conformance/api-requirements.d.ts +42 -0
- package/dist/conformance/api-requirements.js +60 -0
- package/dist/conformance/capability-requirements.js +2 -2
- package/dist/conformance/capability.d.ts +15 -0
- package/dist/conformance/capability.js +40 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,6 +14,8 @@ Core TypeScript SDK for healthcare applications. Provides authentication, AI-FHI
|
|
|
14
14
|
- 🤖 Bot execution framework
|
|
15
15
|
- 📋 Questionnaire responses
|
|
16
16
|
- 📥 Opt-in durable offline measurement queue with idempotent retries
|
|
17
|
+
- 🧭 Runtime discovery of the backend FHIR and public API capabilities
|
|
18
|
+
- 🧩 Typed accounts, projects, localization, and patient-observation APIs
|
|
17
19
|
|
|
18
20
|
## Installation
|
|
19
21
|
|
|
@@ -40,6 +42,36 @@ const client = new OvokClient({
|
|
|
40
42
|
|
|
41
43
|
Full documentation and examples available at **[sdk.ovok.com](https://sdk.ovok.com/)**
|
|
42
44
|
|
|
45
|
+
## Backend capability discovery
|
|
46
|
+
|
|
47
|
+
`@ovok/core` can read the capability statement composed by `../ovok-core` and expose the
|
|
48
|
+
non-FHIR public routes published in Ovok's `ovok-public-api` extension:
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
const statement = await client.getCapabilityStatement();
|
|
52
|
+
const publicEndpoints = await client.getPublicApiEndpoints();
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The exported `OVOK_CORE_REQUIREMENTS` describes the FHIR operations used by the SDK, while
|
|
56
|
+
`OVOK_CORE_API_REQUIREMENTS` describes its ordinary HTTP dependencies. Billing is intentionally
|
|
57
|
+
not part of this SDK contract yet.
|
|
58
|
+
|
|
59
|
+
## Platform APIs
|
|
60
|
+
|
|
61
|
+
The client includes typed methods for application-level account and project flows already served
|
|
62
|
+
by Ovok: project switching and membership, project settings and feature flags, locales and
|
|
63
|
+
localization, and the existing patient-observation read surface.
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
const projects = await client.listAdministeredProjects();
|
|
67
|
+
const settings = await client.getProjectSettings();
|
|
68
|
+
const features = await client.getProjectFeatures();
|
|
69
|
+
const locales = await client.getLocales();
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
All methods preserve the backend HTTP verbs and return the backend response shapes. Billing is
|
|
73
|
+
not included until Ovok publishes a supported billing contract.
|
|
74
|
+
|
|
43
75
|
## Offline measurements
|
|
44
76
|
|
|
45
77
|
Pass a durable Medplum storage adapter and opt in to queue measurements while offline:
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { IClientStorage, MedplumClient, MedplumClientOptions, SubscriptionManager } from "@medplum/core";
|
|
2
|
-
import { Bundle, Observation } from "@medplum/fhirtypes";
|
|
2
|
+
import { Bundle, CapabilityStatement, Observation } from "@medplum/fhirtypes";
|
|
3
|
+
import { OvokPublicApiEndpoint } from "../conformance/capability";
|
|
3
4
|
import * as aiFhirMethods from "./ai-fhir/methods";
|
|
4
5
|
import * as authMethods from "./auth/methods";
|
|
5
6
|
import * as botMethods from "./bot/methods";
|
|
@@ -7,6 +8,7 @@ import * as aiMethods from "./chat/ai/methods";
|
|
|
7
8
|
import * as observationMethods from "./observation/methods";
|
|
8
9
|
import { GenerateObservationBodyParams } from "./observation/types/generate-observation-body/GenerateObservationBodyParams";
|
|
9
10
|
import { OfflineMeasurementFlushOptions, OfflineMeasurementFlushResult, OfflineMeasurementQueueOptions } from "./offline";
|
|
11
|
+
import * as platformMethods from "./platform/methods";
|
|
10
12
|
import * as questionnaireResponseMethods from "./questionnaire-response/methods";
|
|
11
13
|
export declare const MAX_CONDITIONAL_OBSERVATION_ENTRIES = 8;
|
|
12
14
|
export { MAX_OBSERVATION_BUNDLE_BYTES } from "./observation/observation-bundle-utils";
|
|
@@ -17,6 +19,7 @@ export type SaveObservationsResult = {
|
|
|
17
19
|
status: "queued";
|
|
18
20
|
queueId: string;
|
|
19
21
|
};
|
|
22
|
+
export type OvokFhirVersion = "R4" | "R5";
|
|
20
23
|
export declare class OvokClient extends MedplumClient {
|
|
21
24
|
protected socialLoginClientId: string;
|
|
22
25
|
clientStorage: IClientStorage | undefined;
|
|
@@ -32,6 +35,10 @@ export declare class OvokClient extends MedplumClient {
|
|
|
32
35
|
});
|
|
33
36
|
/** Saves a measurement immediately, or durably queues it when the opt-in queue is enabled. */
|
|
34
37
|
saveMeasurement(params: GenerateObservationBodyParams): Promise<SaveObservationsResult>;
|
|
38
|
+
/** Reads Ovok's composed FHIR and public-route capability statement. */
|
|
39
|
+
getCapabilityStatement(version?: OvokFhirVersion): Promise<CapabilityStatement>;
|
|
40
|
+
/** Returns the non-FHIR public routes published by the backend statement. */
|
|
41
|
+
getPublicApiEndpoints(version?: OvokFhirVersion): Promise<OvokPublicApiEndpoint[]>;
|
|
35
42
|
/** Saves observations with conditional creates so a retry cannot create a duplicate. */
|
|
36
43
|
saveObservations(observations: Observation[]): Promise<SaveObservationsResult>;
|
|
37
44
|
/** Flushes measurements queued while offline. Call this on connectivity/app-resume events. */
|
|
@@ -48,7 +55,7 @@ export declare class OvokClient extends MedplumClient {
|
|
|
48
55
|
*/
|
|
49
56
|
getSubscriptionManager(): SubscriptionManager;
|
|
50
57
|
}
|
|
51
|
-
type Methods = typeof authMethods & typeof observationMethods & typeof questionnaireResponseMethods & typeof aiMethods & typeof aiFhirMethods & typeof botMethods;
|
|
58
|
+
type Methods = typeof authMethods & typeof observationMethods & typeof questionnaireResponseMethods & typeof aiMethods & typeof aiFhirMethods & typeof botMethods & typeof platformMethods;
|
|
52
59
|
type Omitted<T> = Omit<T, "executeBot">;
|
|
53
60
|
declare module "./ovok-client" {
|
|
54
61
|
interface OvokClient extends Omitted<Methods> {
|
|
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.OvokClient = exports.MAX_OBSERVATION_BUNDLE_BYTES = exports.MAX_CONDITIONAL_OBSERVATION_ENTRIES = void 0;
|
|
37
37
|
/* eslint-disable @typescript-eslint/no-unsafe-function-type */ // TODO: fix this whenever find time
|
|
38
38
|
const core_1 = require("@medplum/core");
|
|
39
|
+
const capability_1 = require("../conformance/capability");
|
|
39
40
|
const aiFhirMethods = __importStar(require("./ai-fhir/methods"));
|
|
40
41
|
const authMethods = __importStar(require("./auth/methods"));
|
|
41
42
|
const botMethods = __importStar(require("./bot/methods"));
|
|
@@ -44,6 +45,7 @@ const rate_limit_error_1 = require("./errors/rate-limit-error");
|
|
|
44
45
|
const observationMethods = __importStar(require("./observation/methods"));
|
|
45
46
|
const observation_bundle_utils_1 = require("./observation/observation-bundle-utils");
|
|
46
47
|
const offline_1 = require("./offline");
|
|
48
|
+
const platformMethods = __importStar(require("./platform/methods"));
|
|
47
49
|
const questionnaireResponseMethods = __importStar(require("./questionnaire-response/methods"));
|
|
48
50
|
exports.MAX_CONDITIONAL_OBSERVATION_ENTRIES = 8;
|
|
49
51
|
var observation_bundle_utils_2 = require("./observation/observation-bundle-utils");
|
|
@@ -64,6 +66,7 @@ class OvokClient extends core_1.MedplumClient {
|
|
|
64
66
|
this.bindMethods(aiMethods);
|
|
65
67
|
this.bindMethods(aiFhirMethods);
|
|
66
68
|
this.bindMethods(botMethods);
|
|
69
|
+
this.bindMethods(platformMethods);
|
|
67
70
|
this.clientStorage = config.storage;
|
|
68
71
|
this.offlineQueueOptions = (_b = config.offlineQueue) !== null && _b !== void 0 ? _b : {};
|
|
69
72
|
}
|
|
@@ -72,6 +75,14 @@ class OvokClient extends core_1.MedplumClient {
|
|
|
72
75
|
const observations = await this.generateObservationBodiesByMeasurement(params);
|
|
73
76
|
return this.saveObservations(observations);
|
|
74
77
|
}
|
|
78
|
+
/** Reads Ovok's composed FHIR and public-route capability statement. */
|
|
79
|
+
async getCapabilityStatement(version = "R4") {
|
|
80
|
+
return this.get(`/fhir/${version}/metadata`);
|
|
81
|
+
}
|
|
82
|
+
/** Returns the non-FHIR public routes published by the backend statement. */
|
|
83
|
+
async getPublicApiEndpoints(version = "R4") {
|
|
84
|
+
return (0, capability_1.getOvokPublicApiEndpoints)(await this.getCapabilityStatement(version));
|
|
85
|
+
}
|
|
75
86
|
/** Saves observations with conditional creates so a retry cannot create a duplicate. */
|
|
76
87
|
async saveObservations(observations) {
|
|
77
88
|
const linkedObservations = (0, observation_bundle_utils_1.linkObservationMembers)(observations);
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { OvokClient } from "../ovok-client";
|
|
2
|
+
import { OvokAccount, OvokAdministeredProject, OvokCreateProject, OvokCreatedProject, OvokI18nDocument, OvokI18nValue, OvokInviteProjectMember, OvokLocalization, OvokLocalizationQuery, OvokLocalizationUpdate, OvokLocales, OvokPage, OvokPatientObservations, OvokProjectFeature, OvokProjectFeatures, OvokProjectMember, OvokProjectMemberResponse, OvokProjectSettings, OvokProjectSettingKey, OvokRemoveProjectMemberResponse, OvokUpdateProjectMember } from "./types";
|
|
3
|
+
export declare function getAccounts(this: OvokClient): Promise<OvokAccount[]>;
|
|
4
|
+
export declare function listAdministeredProjects(this: OvokClient, params?: {
|
|
5
|
+
page?: number;
|
|
6
|
+
count?: number;
|
|
7
|
+
}): Promise<OvokPage<OvokAdministeredProject>>;
|
|
8
|
+
export declare function createProject(this: OvokClient, body: OvokCreateProject): Promise<OvokCreatedProject>;
|
|
9
|
+
export declare function bootstrapProject(this: OvokClient, body: OvokCreateProject): Promise<OvokCreatedProject>;
|
|
10
|
+
export declare function getProjectTenantCode(this: OvokClient): Promise<{
|
|
11
|
+
tenantCode: string;
|
|
12
|
+
}>;
|
|
13
|
+
export declare function listProjectMembers(this: OvokClient, params?: {
|
|
14
|
+
accessPolicyId?: string;
|
|
15
|
+
profileId?: string;
|
|
16
|
+
userId?: string;
|
|
17
|
+
page?: number;
|
|
18
|
+
count?: number;
|
|
19
|
+
}): Promise<OvokPage<OvokProjectMember>>;
|
|
20
|
+
export declare function inviteProjectMember(this: OvokClient, body: OvokInviteProjectMember): Promise<OvokProjectMemberResponse>;
|
|
21
|
+
export declare function updateProjectMember(this: OvokClient, membershipId: string, body: OvokUpdateProjectMember): Promise<OvokProjectMemberResponse>;
|
|
22
|
+
export declare function removeProjectMember(this: OvokClient, membershipId: string): Promise<OvokRemoveProjectMemberResponse>;
|
|
23
|
+
export declare function getProjectFeatures(this: OvokClient): Promise<OvokProjectFeatures>;
|
|
24
|
+
export declare function updateProjectFeatures(this: OvokClient, features: OvokProjectFeature[]): Promise<OvokProjectFeatures>;
|
|
25
|
+
export declare function getProjectSettings(this: OvokClient): Promise<OvokProjectSettings>;
|
|
26
|
+
export declare function updateProjectSetting(this: OvokClient, key: OvokProjectSettingKey, enabled: boolean): Promise<OvokProjectSettings>;
|
|
27
|
+
export declare function getLocales(this: OvokClient): Promise<OvokLocales>;
|
|
28
|
+
export declare function updateLocales(this: OvokClient, locales: OvokLocales): Promise<OvokLocales>;
|
|
29
|
+
export declare function listLocalizations(this: OvokClient, language: string, params?: OvokLocalizationQuery): Promise<{
|
|
30
|
+
total: number;
|
|
31
|
+
resources: OvokLocalization[];
|
|
32
|
+
}>;
|
|
33
|
+
export declare function getLocalization(this: OvokClient, language: string, key: string): Promise<OvokLocalization>;
|
|
34
|
+
export declare function updateLocalization(this: OvokClient, language: string, key: string, body: OvokLocalizationUpdate): Promise<OvokLocalization>;
|
|
35
|
+
export declare function deleteLocalization(this: OvokClient, language: string, key: string): Promise<void>;
|
|
36
|
+
export declare function getI18nextDocument(this: OvokClient, language: string): Promise<OvokI18nDocument>;
|
|
37
|
+
export declare function updateI18nextDocument(this: OvokClient, language: string, document: Record<string, OvokI18nValue>): Promise<void>;
|
|
38
|
+
export declare function getPatientLastObservations(this: OvokClient, patientId: string, params: {
|
|
39
|
+
code: string;
|
|
40
|
+
max?: number;
|
|
41
|
+
}): Promise<OvokPatientObservations>;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getAccounts = getAccounts;
|
|
4
|
+
exports.listAdministeredProjects = listAdministeredProjects;
|
|
5
|
+
exports.createProject = createProject;
|
|
6
|
+
exports.bootstrapProject = bootstrapProject;
|
|
7
|
+
exports.getProjectTenantCode = getProjectTenantCode;
|
|
8
|
+
exports.listProjectMembers = listProjectMembers;
|
|
9
|
+
exports.inviteProjectMember = inviteProjectMember;
|
|
10
|
+
exports.updateProjectMember = updateProjectMember;
|
|
11
|
+
exports.removeProjectMember = removeProjectMember;
|
|
12
|
+
exports.getProjectFeatures = getProjectFeatures;
|
|
13
|
+
exports.updateProjectFeatures = updateProjectFeatures;
|
|
14
|
+
exports.getProjectSettings = getProjectSettings;
|
|
15
|
+
exports.updateProjectSetting = updateProjectSetting;
|
|
16
|
+
exports.getLocales = getLocales;
|
|
17
|
+
exports.updateLocales = updateLocales;
|
|
18
|
+
exports.listLocalizations = listLocalizations;
|
|
19
|
+
exports.getLocalization = getLocalization;
|
|
20
|
+
exports.updateLocalization = updateLocalization;
|
|
21
|
+
exports.deleteLocalization = deleteLocalization;
|
|
22
|
+
exports.getI18nextDocument = getI18nextDocument;
|
|
23
|
+
exports.updateI18nextDocument = updateI18nextDocument;
|
|
24
|
+
exports.getPatientLastObservations = getPatientLastObservations;
|
|
25
|
+
const query = (params) => {
|
|
26
|
+
const values = new URLSearchParams();
|
|
27
|
+
for (const [key, value] of Object.entries(params)) {
|
|
28
|
+
if (value !== undefined) {
|
|
29
|
+
values.set(key, String(value));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const encoded = values.toString();
|
|
33
|
+
return encoded === "" ? "" : `?${encoded}`;
|
|
34
|
+
};
|
|
35
|
+
const segment = (value) => encodeURIComponent(value);
|
|
36
|
+
async function getAccounts() {
|
|
37
|
+
return this.get("/accounts");
|
|
38
|
+
}
|
|
39
|
+
async function listAdministeredProjects(params = {}) {
|
|
40
|
+
return this.get(`/v1/projects${query(params)}`);
|
|
41
|
+
}
|
|
42
|
+
async function createProject(body) {
|
|
43
|
+
return this.post("/v1/projects", body);
|
|
44
|
+
}
|
|
45
|
+
async function bootstrapProject(body) {
|
|
46
|
+
return this.post("/v1/projects/bootstrap", body);
|
|
47
|
+
}
|
|
48
|
+
async function getProjectTenantCode() {
|
|
49
|
+
return this.get("/v1/projects/me/tenant-code");
|
|
50
|
+
}
|
|
51
|
+
async function listProjectMembers(params = {}) {
|
|
52
|
+
return this.get(`/v1/projects/me/members${query(params)}`);
|
|
53
|
+
}
|
|
54
|
+
async function inviteProjectMember(body) {
|
|
55
|
+
return this.post("/v1/projects/me/members", body);
|
|
56
|
+
}
|
|
57
|
+
async function updateProjectMember(membershipId, body) {
|
|
58
|
+
return (await this.patch(`/v1/projects/me/members/${segment(membershipId)}`, body));
|
|
59
|
+
}
|
|
60
|
+
async function removeProjectMember(membershipId) {
|
|
61
|
+
return (await this.delete(`/v1/projects/me/members/${segment(membershipId)}`));
|
|
62
|
+
}
|
|
63
|
+
async function getProjectFeatures() {
|
|
64
|
+
return this.get("/v1/projects/me/features");
|
|
65
|
+
}
|
|
66
|
+
async function updateProjectFeatures(features) {
|
|
67
|
+
const body = { features };
|
|
68
|
+
return (await this.patch("/v1/projects/me/features", body));
|
|
69
|
+
}
|
|
70
|
+
async function getProjectSettings() {
|
|
71
|
+
return this.get("/v1/project/settings");
|
|
72
|
+
}
|
|
73
|
+
async function updateProjectSetting(key, enabled) {
|
|
74
|
+
return (await this.put(`/v1/project/settings/${segment(key)}`, { enabled }));
|
|
75
|
+
}
|
|
76
|
+
async function getLocales() {
|
|
77
|
+
return this.get("/locales");
|
|
78
|
+
}
|
|
79
|
+
async function updateLocales(locales) {
|
|
80
|
+
return (await this.patch("/locales", locales));
|
|
81
|
+
}
|
|
82
|
+
async function listLocalizations(language, params = {}) {
|
|
83
|
+
return this.get(`/localization/${segment(language)}${query(params)}`);
|
|
84
|
+
}
|
|
85
|
+
async function getLocalization(language, key) {
|
|
86
|
+
return this.get(`/localization/${segment(language)}/${segment(key)}`);
|
|
87
|
+
}
|
|
88
|
+
async function updateLocalization(language, key, body) {
|
|
89
|
+
return (await this.put(`/localization/${segment(language)}/${segment(key)}`, body));
|
|
90
|
+
}
|
|
91
|
+
async function deleteLocalization(language, key) {
|
|
92
|
+
await this.delete(`/localization/${segment(language)}/${segment(key)}`);
|
|
93
|
+
}
|
|
94
|
+
async function getI18nextDocument(language) {
|
|
95
|
+
return this.get(`/localization/i18next/${segment(language)}`);
|
|
96
|
+
}
|
|
97
|
+
async function updateI18nextDocument(language, document) {
|
|
98
|
+
await this.patch(`/localization/i18next/${segment(language)}`, document);
|
|
99
|
+
}
|
|
100
|
+
async function getPatientLastObservations(patientId, params) {
|
|
101
|
+
return this.get(`/patient/${segment(patientId)}/observation${query(params)}`);
|
|
102
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { Bundle, Observation } from "@medplum/fhirtypes";
|
|
2
|
+
export type OvokPage<T> = {
|
|
3
|
+
total: number;
|
|
4
|
+
page: number;
|
|
5
|
+
count: number;
|
|
6
|
+
resources: T[];
|
|
7
|
+
};
|
|
8
|
+
export type OvokAccount = {
|
|
9
|
+
email: string;
|
|
10
|
+
name: string;
|
|
11
|
+
};
|
|
12
|
+
export type OvokAdministeredProject = {
|
|
13
|
+
projectId: string;
|
|
14
|
+
name: string | null;
|
|
15
|
+
tenantCode: string | null;
|
|
16
|
+
isMainProject: boolean | null;
|
|
17
|
+
parentProjectId: string | null;
|
|
18
|
+
};
|
|
19
|
+
export type OvokCreateProject = {
|
|
20
|
+
name: string;
|
|
21
|
+
};
|
|
22
|
+
export type OvokCreatedProject = {
|
|
23
|
+
projectId: string;
|
|
24
|
+
tenantCode: string;
|
|
25
|
+
name: string;
|
|
26
|
+
};
|
|
27
|
+
export type OvokProjectMemberReference = {
|
|
28
|
+
reference?: string;
|
|
29
|
+
display?: string;
|
|
30
|
+
[key: string]: unknown;
|
|
31
|
+
};
|
|
32
|
+
export type OvokProjectMember = {
|
|
33
|
+
membershipId: string;
|
|
34
|
+
userId?: string;
|
|
35
|
+
profile?: OvokProjectMemberReference;
|
|
36
|
+
accessPolicy?: OvokProjectMemberReference;
|
|
37
|
+
admin?: boolean;
|
|
38
|
+
};
|
|
39
|
+
export type OvokInviteProjectMember = {
|
|
40
|
+
email: string;
|
|
41
|
+
firstName: string | null;
|
|
42
|
+
lastName: string | null;
|
|
43
|
+
admin: boolean | null;
|
|
44
|
+
};
|
|
45
|
+
export type OvokUpdateProjectMember = {
|
|
46
|
+
admin: boolean | null;
|
|
47
|
+
};
|
|
48
|
+
export type OvokProjectMemberResponse = {
|
|
49
|
+
id: string;
|
|
50
|
+
email: string | null;
|
|
51
|
+
displayName: string | null;
|
|
52
|
+
firstName: string | null;
|
|
53
|
+
lastName: string | null;
|
|
54
|
+
admin: boolean;
|
|
55
|
+
profileType: "Practitioner" | "Patient" | "RelatedPerson" | null;
|
|
56
|
+
profileId: string | null;
|
|
57
|
+
pending: boolean;
|
|
58
|
+
invitedAt: string | null;
|
|
59
|
+
};
|
|
60
|
+
export type OvokRemoveProjectMemberResponse = {
|
|
61
|
+
success: true;
|
|
62
|
+
};
|
|
63
|
+
export declare const OVOK_PROJECT_FEATURE_VALUES: readonly ["ai", "aws-comprehend", "aws-textract", "bots", "cron", "email", "google-auth-required", "graphql-introspection", "websocket-subscriptions", "transaction-bundles", "validate-terminology"];
|
|
64
|
+
export type OvokProjectFeature = (typeof OVOK_PROJECT_FEATURE_VALUES)[number];
|
|
65
|
+
export type OvokProjectFeatures = {
|
|
66
|
+
features: string[];
|
|
67
|
+
};
|
|
68
|
+
export type OvokProjectFeaturesUpdate = {
|
|
69
|
+
features: OvokProjectFeature[];
|
|
70
|
+
};
|
|
71
|
+
export declare const OVOK_PROJECT_SETTING_KEYS: readonly ["CONTENT_ENABLED", "MAILING_ENABLED", "PATIENT_INVITATION_ENABLED", "PATIENT_REGISTRATION_ENABLED", "PATIENT_LOGIN_ENABLED", "PRACTITIONER_INVITATION_ENABLED", "PRACTITIONER_REGISTRATION_ENABLED", "PRACTITIONER_LOGIN_ENABLED", "IOT_ENABLED"];
|
|
72
|
+
export type OvokProjectSettingKey = (typeof OVOK_PROJECT_SETTING_KEYS)[number];
|
|
73
|
+
export type OvokProjectSettings = {
|
|
74
|
+
projectId: string;
|
|
75
|
+
settings: Record<OvokProjectSettingKey, boolean>;
|
|
76
|
+
};
|
|
77
|
+
export type OvokLocales = {
|
|
78
|
+
languages: string[];
|
|
79
|
+
defaultLanguage: string;
|
|
80
|
+
};
|
|
81
|
+
export type OvokLocalization = {
|
|
82
|
+
id?: string;
|
|
83
|
+
key: string;
|
|
84
|
+
language: string;
|
|
85
|
+
value: string;
|
|
86
|
+
author: {
|
|
87
|
+
reference: string;
|
|
88
|
+
display?: string;
|
|
89
|
+
};
|
|
90
|
+
date?: string;
|
|
91
|
+
projectId?: string;
|
|
92
|
+
};
|
|
93
|
+
export type OvokLocalizationQuery = {
|
|
94
|
+
_count?: number;
|
|
95
|
+
_offset?: number;
|
|
96
|
+
_sort?: string;
|
|
97
|
+
search?: string;
|
|
98
|
+
};
|
|
99
|
+
export type OvokLocalizationUpdate = {
|
|
100
|
+
value: string;
|
|
101
|
+
};
|
|
102
|
+
export type OvokI18nValue = string | {
|
|
103
|
+
[key: string]: OvokI18nValue;
|
|
104
|
+
};
|
|
105
|
+
export type OvokI18nDocument = {
|
|
106
|
+
key: string;
|
|
107
|
+
language: string;
|
|
108
|
+
[key: string]: unknown;
|
|
109
|
+
};
|
|
110
|
+
export type OvokPatientObservationQuery = {
|
|
111
|
+
code: string;
|
|
112
|
+
max?: number;
|
|
113
|
+
};
|
|
114
|
+
export type OvokPatientObservations = Bundle<Observation>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OVOK_PROJECT_SETTING_KEYS = exports.OVOK_PROJECT_FEATURE_VALUES = void 0;
|
|
4
|
+
exports.OVOK_PROJECT_FEATURE_VALUES = [
|
|
5
|
+
"ai",
|
|
6
|
+
"aws-comprehend",
|
|
7
|
+
"aws-textract",
|
|
8
|
+
"bots",
|
|
9
|
+
"cron",
|
|
10
|
+
"email",
|
|
11
|
+
"google-auth-required",
|
|
12
|
+
"graphql-introspection",
|
|
13
|
+
"websocket-subscriptions",
|
|
14
|
+
"transaction-bundles",
|
|
15
|
+
"validate-terminology",
|
|
16
|
+
];
|
|
17
|
+
exports.OVOK_PROJECT_SETTING_KEYS = [
|
|
18
|
+
"CONTENT_ENABLED",
|
|
19
|
+
"MAILING_ENABLED",
|
|
20
|
+
"PATIENT_INVITATION_ENABLED",
|
|
21
|
+
"PATIENT_REGISTRATION_ENABLED",
|
|
22
|
+
"PATIENT_LOGIN_ENABLED",
|
|
23
|
+
"PRACTITIONER_INVITATION_ENABLED",
|
|
24
|
+
"PRACTITIONER_REGISTRATION_ENABLED",
|
|
25
|
+
"PRACTITIONER_LOGIN_ENABLED",
|
|
26
|
+
"IOT_ENABLED",
|
|
27
|
+
];
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export type OvokHttpMethod = "DELETE" | "GET" | "PATCH" | "POST" | "PUT";
|
|
2
|
+
export type OvokApiRequirement = {
|
|
3
|
+
method: OvokHttpMethod;
|
|
4
|
+
path: string;
|
|
5
|
+
group: string;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* The non-FHIR HTTP routes used by @ovok/core itself.
|
|
9
|
+
*
|
|
10
|
+
* This is deliberately separate from OVOK_CORE_REQUIREMENTS: a FHIR
|
|
11
|
+
* CapabilityStatement cannot describe ordinary auth, AI, or bot routes.
|
|
12
|
+
* Billing is intentionally absent until Ovok has a supported billing SDK
|
|
13
|
+
* contract.
|
|
14
|
+
*/
|
|
15
|
+
export declare const OVOK_CORE_API_REQUIREMENTS: {
|
|
16
|
+
readonly capability: {
|
|
17
|
+
readonly method: "GET";
|
|
18
|
+
readonly path: "/fhir/{version}/metadata";
|
|
19
|
+
readonly group: "FHIR";
|
|
20
|
+
};
|
|
21
|
+
readonly nonFhir: ({
|
|
22
|
+
method: "POST";
|
|
23
|
+
path: string;
|
|
24
|
+
group: string;
|
|
25
|
+
} | {
|
|
26
|
+
method: "GET";
|
|
27
|
+
path: string;
|
|
28
|
+
group: string;
|
|
29
|
+
} | {
|
|
30
|
+
method: "DELETE";
|
|
31
|
+
path: string;
|
|
32
|
+
group: string;
|
|
33
|
+
} | {
|
|
34
|
+
method: "PATCH";
|
|
35
|
+
path: string;
|
|
36
|
+
group: string;
|
|
37
|
+
} | {
|
|
38
|
+
method: "PUT";
|
|
39
|
+
path: string;
|
|
40
|
+
group: string;
|
|
41
|
+
})[];
|
|
42
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OVOK_CORE_API_REQUIREMENTS = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* The non-FHIR HTTP routes used by @ovok/core itself.
|
|
6
|
+
*
|
|
7
|
+
* This is deliberately separate from OVOK_CORE_REQUIREMENTS: a FHIR
|
|
8
|
+
* CapabilityStatement cannot describe ordinary auth, AI, or bot routes.
|
|
9
|
+
* Billing is intentionally absent until Ovok has a supported billing SDK
|
|
10
|
+
* contract.
|
|
11
|
+
*/
|
|
12
|
+
exports.OVOK_CORE_API_REQUIREMENTS = {
|
|
13
|
+
capability: {
|
|
14
|
+
method: "GET",
|
|
15
|
+
path: "/fhir/{version}/metadata",
|
|
16
|
+
group: "FHIR",
|
|
17
|
+
},
|
|
18
|
+
nonFhir: [
|
|
19
|
+
{ method: "POST", path: "/auth/tenant/Patient/login/start", group: "Auth" },
|
|
20
|
+
{ method: "POST", path: "/auth/tenant/Practitioner/login/start", group: "Auth" },
|
|
21
|
+
{ method: "POST", path: "/auth/tenant/Patient/login/token", group: "Auth" },
|
|
22
|
+
{ method: "POST", path: "/auth/tenant/Practitioner/login/token", group: "Auth" },
|
|
23
|
+
{ method: "POST", path: "/auth/tenant/Practitioner/login/mfa", group: "Auth" },
|
|
24
|
+
{ method: "POST", path: "/auth/tenant/Patient/register", group: "Auth" },
|
|
25
|
+
{ method: "POST", path: "/auth/external/google", group: "Auth" },
|
|
26
|
+
{ method: "POST", path: "/auth/external/apple", group: "Auth" },
|
|
27
|
+
{ method: "POST", path: "/auth/change-password", group: "Auth" },
|
|
28
|
+
{ method: "POST", path: "/v2/auth/reset-password", group: "Auth" },
|
|
29
|
+
{ method: "POST", path: "/v2/auth/reset-password/process", group: "Auth" },
|
|
30
|
+
{ method: "GET", path: "/auth/session", group: "Auth" },
|
|
31
|
+
{ method: "DELETE", path: "/auth/session/current", group: "Auth" },
|
|
32
|
+
{ method: "DELETE", path: "/auth/session/:option", group: "Auth" },
|
|
33
|
+
{ method: "DELETE", path: "/auth/delete", group: "Auth" },
|
|
34
|
+
{ method: "POST", path: "/ai/session", group: "AI" },
|
|
35
|
+
{ method: "POST", path: "/ai/fhir/search", group: "AI" },
|
|
36
|
+
{ method: "POST", path: "/bots", group: "Bots" },
|
|
37
|
+
{ method: "GET", path: "/accounts", group: "Accounts" },
|
|
38
|
+
{ method: "GET", path: "/v1/projects", group: "Projects" },
|
|
39
|
+
{ method: "POST", path: "/v1/projects", group: "Projects" },
|
|
40
|
+
{ method: "POST", path: "/v1/projects/bootstrap", group: "Projects" },
|
|
41
|
+
{ method: "GET", path: "/v1/projects/me/tenant-code", group: "Projects" },
|
|
42
|
+
{ method: "GET", path: "/v1/projects/me/members", group: "Projects" },
|
|
43
|
+
{ method: "POST", path: "/v1/projects/me/members", group: "Projects" },
|
|
44
|
+
{ method: "PATCH", path: "/v1/projects/me/members/:membershipId", group: "Projects" },
|
|
45
|
+
{ method: "DELETE", path: "/v1/projects/me/members/:membershipId", group: "Projects" },
|
|
46
|
+
{ method: "GET", path: "/v1/projects/me/features", group: "Projects" },
|
|
47
|
+
{ method: "PATCH", path: "/v1/projects/me/features", group: "Projects" },
|
|
48
|
+
{ method: "GET", path: "/v1/project/settings", group: "Projects" },
|
|
49
|
+
{ method: "PUT", path: "/v1/project/settings/:key", group: "Projects" },
|
|
50
|
+
{ method: "GET", path: "/locales", group: "Localization" },
|
|
51
|
+
{ method: "PATCH", path: "/locales", group: "Localization" },
|
|
52
|
+
{ method: "GET", path: "/localization/:language", group: "Localization" },
|
|
53
|
+
{ method: "GET", path: "/localization/:language/:key", group: "Localization" },
|
|
54
|
+
{ method: "PUT", path: "/localization/:language/:key", group: "Localization" },
|
|
55
|
+
{ method: "DELETE", path: "/localization/:language/:key", group: "Localization" },
|
|
56
|
+
{ method: "GET", path: "/localization/i18next/:language", group: "Localization" },
|
|
57
|
+
{ method: "PATCH", path: "/localization/i18next/:language", group: "Localization" },
|
|
58
|
+
{ method: "GET", path: "/patient/:id/observation", group: "Patient" },
|
|
59
|
+
],
|
|
60
|
+
};
|
|
@@ -43,12 +43,12 @@ exports.OVOK_CORE_REQUIREMENTS = {
|
|
|
43
43
|
* report change where there is none. Bump it with `software.version` when
|
|
44
44
|
* the declared surface actually moves.
|
|
45
45
|
*/
|
|
46
|
-
date: "2026-09-
|
|
46
|
+
date: "2026-09-26",
|
|
47
47
|
kind: "requirements",
|
|
48
48
|
description: "The FHIR surface a server must provide for the @ovok/core client library's own methods to function.",
|
|
49
49
|
software: {
|
|
50
50
|
name: "@ovok/core",
|
|
51
|
-
version: "0.3.
|
|
51
|
+
version: "0.3.5",
|
|
52
52
|
},
|
|
53
53
|
fhirVersion: "4.0.1",
|
|
54
54
|
format: ["json"],
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { CapabilityStatement } from "@medplum/fhirtypes";
|
|
2
|
+
/** The extension used by ovok-core to publish non-FHIR public routes. */
|
|
3
|
+
export declare const OVOK_PUBLIC_API_EXTENSION = "https://fhir.ovok.com/fhir/StructureDefinition/ovok-public-api";
|
|
4
|
+
export type OvokPublicApiEndpoint = {
|
|
5
|
+
method: string;
|
|
6
|
+
path: string;
|
|
7
|
+
group: string;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Reads the public non-FHIR route catalog emitted by ../ovok-core.
|
|
11
|
+
*
|
|
12
|
+
* FHIR clients can ignore this extension safely. React applications can use
|
|
13
|
+
* it to feature-detect the rest of the Ovok API without hard-coding routes.
|
|
14
|
+
*/
|
|
15
|
+
export declare const getOvokPublicApiEndpoints: (statement: CapabilityStatement) => OvokPublicApiEndpoint[];
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getOvokPublicApiEndpoints = exports.OVOK_PUBLIC_API_EXTENSION = void 0;
|
|
4
|
+
/** The extension used by ovok-core to publish non-FHIR public routes. */
|
|
5
|
+
exports.OVOK_PUBLIC_API_EXTENSION = "https://fhir.ovok.com/fhir/StructureDefinition/ovok-public-api";
|
|
6
|
+
const ENDPOINT_EXTENSION = "endpoint";
|
|
7
|
+
const stringValue = (extension) => { var _a; return (_a = extension.valueCode) !== null && _a !== void 0 ? _a : extension.valueString; };
|
|
8
|
+
/**
|
|
9
|
+
* Reads the public non-FHIR route catalog emitted by ../ovok-core.
|
|
10
|
+
*
|
|
11
|
+
* FHIR clients can ignore this extension safely. React applications can use
|
|
12
|
+
* it to feature-detect the rest of the Ovok API without hard-coding routes.
|
|
13
|
+
*/
|
|
14
|
+
const getOvokPublicApiEndpoints = (statement) => {
|
|
15
|
+
var _a, _b;
|
|
16
|
+
const publicApi = (_a = statement.extension) === null || _a === void 0 ? void 0 : _a.find((extension) => extension.url === exports.OVOK_PUBLIC_API_EXTENSION);
|
|
17
|
+
return ((_b = publicApi === null || publicApi === void 0 ? void 0 : publicApi.extension) !== null && _b !== void 0 ? _b : []).flatMap((endpoint) => {
|
|
18
|
+
var _a, _b, _c;
|
|
19
|
+
if (endpoint.url !== ENDPOINT_EXTENSION) {
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
22
|
+
const method = (_a = endpoint.extension) === null || _a === void 0 ? void 0 : _a.find((extension) => extension.url === "method");
|
|
23
|
+
const path = (_b = endpoint.extension) === null || _b === void 0 ? void 0 : _b.find((extension) => extension.url === "path");
|
|
24
|
+
const group = (_c = endpoint.extension) === null || _c === void 0 ? void 0 : _c.find((extension) => extension.url === "group");
|
|
25
|
+
const methodValue = method === undefined ? undefined : stringValue(method);
|
|
26
|
+
const pathValue = path === undefined ? undefined : stringValue(path);
|
|
27
|
+
const groupValue = group === undefined ? undefined : stringValue(group);
|
|
28
|
+
if (methodValue === undefined || pathValue === undefined || groupValue === undefined) {
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
return [
|
|
32
|
+
{
|
|
33
|
+
method: methodValue.toUpperCase(),
|
|
34
|
+
path: pathValue,
|
|
35
|
+
group: groupValue,
|
|
36
|
+
},
|
|
37
|
+
];
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
exports.getOvokPublicApiEndpoints = getOvokPublicApiEndpoints;
|
package/dist/index.d.ts
CHANGED
|
@@ -933,3 +933,6 @@ export * from "./client/observation/services";
|
|
|
933
933
|
export * from "./client/observation/methods";
|
|
934
934
|
export { saveMeasurement } from "./client/observation/methods/saveMeasurement";
|
|
935
935
|
export * from "./conformance/capability-requirements";
|
|
936
|
+
export * from "./conformance/api-requirements";
|
|
937
|
+
export * from "./conformance/capability";
|
|
938
|
+
export * from "./client/platform/types";
|
package/dist/index.js
CHANGED
|
@@ -56,3 +56,6 @@ __exportStar(require("./client/observation/methods"), exports);
|
|
|
56
56
|
var saveMeasurement_1 = require("./client/observation/methods/saveMeasurement");
|
|
57
57
|
Object.defineProperty(exports, "saveMeasurement", { enumerable: true, get: function () { return saveMeasurement_1.saveMeasurement; } });
|
|
58
58
|
__exportStar(require("./conformance/capability-requirements"), exports);
|
|
59
|
+
__exportStar(require("./conformance/api-requirements"), exports);
|
|
60
|
+
__exportStar(require("./conformance/capability"), exports);
|
|
61
|
+
__exportStar(require("./client/platform/types"), exports);
|