gdc-common-utils-ts 1.24.1 → 2.0.1
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 +39 -0
- package/dist/constants/index.d.ts +1 -0
- package/dist/constants/index.js +1 -0
- package/dist/constants/profile-runtime.d.ts +33 -0
- package/dist/constants/profile-runtime.js +30 -0
- package/dist/examples/frontend-session.js +2 -1
- package/dist/examples/ica-activation-proof.d.ts +11 -4
- package/dist/examples/ica-activation-proof.js +11 -4
- package/dist/examples/index.d.ts +1 -0
- package/dist/examples/index.js +1 -0
- package/dist/examples/lifecycle.js +5 -5
- package/dist/examples/organization-controller.d.ts +0 -1
- package/dist/examples/organization-controller.js +0 -1
- package/dist/examples/profile-runtime.d.ts +16 -0
- package/dist/examples/profile-runtime.js +18 -0
- package/dist/examples/shared.d.ts +9 -0
- package/dist/examples/shared.js +9 -0
- package/dist/interfaces/Cryptography.types.d.ts +15 -0
- package/dist/models/identity-bootstrap.d.ts +9 -0
- package/dist/utils/activation-policy.d.ts +45 -1
- package/dist/utils/activation-policy.js +65 -7
- package/dist/utils/activation-request.d.ts +63 -2
- package/dist/utils/activation-request.js +82 -0
- package/dist/utils/communication-participant-search-test-data.d.ts +17 -0
- package/dist/utils/communication-participant-search-test-data.js +39 -0
- package/dist/utils/communication-participant-search.d.ts +108 -0
- package/dist/utils/communication-participant-search.js +425 -0
- package/dist/utils/communication-retention-policy.d.ts +32 -0
- package/dist/utils/communication-retention-policy.js +41 -0
- package/dist/utils/communication-search-editor.d.ts +54 -0
- package/dist/utils/communication-search-editor.js +156 -0
- package/dist/utils/fhir-search.d.ts +32 -0
- package/dist/utils/fhir-search.js +45 -0
- package/dist/utils/index.d.ts +8 -0
- package/dist/utils/index.js +8 -0
- package/dist/utils/individual-organization-lifecycle.d.ts +15 -5
- package/dist/utils/individual-organization-lifecycle.js +53 -6
- package/dist/utils/interoperable-resource-operation.d.ts +4 -4
- package/dist/utils/interoperable-resource-operation.js +22 -22
- package/dist/utils/jwk-thumbprint.d.ts +40 -0
- package/dist/utils/jwk-thumbprint.js +57 -0
- package/dist/utils/legal-organization-onboarding.d.ts +97 -0
- package/dist/utils/legal-organization-onboarding.js +128 -0
- package/dist/utils/license-commercial-search.d.ts +6 -6
- package/dist/utils/license-commercial-search.js +2 -2
- package/dist/utils/license-list-search.d.ts +7 -7
- package/dist/utils/license-list-search.js +23 -23
- package/dist/utils/license-offer-order.d.ts +19 -19
- package/dist/utils/license-offer-order.js +68 -68
- package/dist/utils/organization-lifecycle.d.ts +59 -0
- package/dist/utils/organization-lifecycle.js +155 -0
- package/dist/utils/same-as.d.ts +41 -0
- package/dist/utils/same-as.js +83 -0
- package/package.json +2 -2
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { ResourceTypesFhirR4 } from '../constants/fhir-resource-types.js';
|
|
2
|
+
import { CommunicationClaim } from '../models/interoperable-claims/communication-claims.js';
|
|
3
|
+
import { buildCommunicationParticipantSearchBundle, buildCommunicationParticipantSearchParameters, normalizeCommunicationParticipantTokenList, } from './communication-participant-search.js';
|
|
4
|
+
export const CommunicationSearchEntryTypes = Object.freeze({
|
|
5
|
+
Search: 'Communication-search-request-v1.0',
|
|
6
|
+
});
|
|
7
|
+
export const CommunicationSearchOperationTypes = Object.freeze({
|
|
8
|
+
Search: 'search',
|
|
9
|
+
});
|
|
10
|
+
function normalizeText(value) {
|
|
11
|
+
const normalized = String(value ?? '').trim();
|
|
12
|
+
return normalized || undefined;
|
|
13
|
+
}
|
|
14
|
+
function normalizeInteger(value) {
|
|
15
|
+
const numeric = typeof value === 'number' ? value : Number(String(value ?? '').trim());
|
|
16
|
+
return Number.isInteger(numeric) && numeric > 0 ? numeric : undefined;
|
|
17
|
+
}
|
|
18
|
+
function normalizeSearchParamValue(claimKey, value) {
|
|
19
|
+
if (value === undefined || value === null) {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
if (Array.isArray(value)) {
|
|
23
|
+
if (isParticipantClaimKey(claimKey)) {
|
|
24
|
+
return normalizeCommunicationParticipantTokenList(value);
|
|
25
|
+
}
|
|
26
|
+
const normalized = value
|
|
27
|
+
.map((item) => typeof item === 'string' ? item.trim() : item)
|
|
28
|
+
.filter((item) => item !== '' && item !== undefined && item !== null);
|
|
29
|
+
return normalized.length > 0 ? normalized : undefined;
|
|
30
|
+
}
|
|
31
|
+
if (typeof value === 'boolean' || typeof value === 'number') {
|
|
32
|
+
return value;
|
|
33
|
+
}
|
|
34
|
+
if (isParticipantClaimKey(claimKey)) {
|
|
35
|
+
const normalized = normalizeCommunicationParticipantTokenList(value);
|
|
36
|
+
return normalized.length > 0 ? normalized : undefined;
|
|
37
|
+
}
|
|
38
|
+
return normalizeText(value);
|
|
39
|
+
}
|
|
40
|
+
function cloneDraft(draft) {
|
|
41
|
+
const searchParams = {};
|
|
42
|
+
for (const [key, value] of Object.entries(draft?.searchParams || {})) {
|
|
43
|
+
const normalizedKey = normalizeText(key);
|
|
44
|
+
if (!normalizedKey) {
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
const normalizedValue = normalizeSearchParamValue(normalizedKey, value);
|
|
48
|
+
if (normalizedValue !== undefined) {
|
|
49
|
+
searchParams[normalizedKey] = normalizedValue;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
searchParams,
|
|
54
|
+
periodStart: normalizeText(draft?.periodStart),
|
|
55
|
+
periodEnd: normalizeText(draft?.periodEnd),
|
|
56
|
+
page: normalizeInteger(draft?.page),
|
|
57
|
+
count: normalizeInteger(draft?.count),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function isParticipantClaimKey(claimKey) {
|
|
61
|
+
return claimKey === CommunicationClaim.Subject
|
|
62
|
+
|| claimKey === CommunicationClaim.Sender
|
|
63
|
+
|| claimKey === CommunicationClaim.Recipient;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* High-level chainable editor for `Communication/_search`.
|
|
67
|
+
*
|
|
68
|
+
* Design goals:
|
|
69
|
+
* - keep business filters near the caller instead of forcing ad-hoc `Parameters`
|
|
70
|
+
* - reuse canonical `CommunicationClaim.*` keys for search params
|
|
71
|
+
* - keep shared controls (`periodStart`, `periodEnd`, `page`, `count`) outside
|
|
72
|
+
* the claim bag because they are search controls, not resource claims
|
|
73
|
+
*/
|
|
74
|
+
export class CommunicationSearchEditor {
|
|
75
|
+
draft;
|
|
76
|
+
constructor(initial) {
|
|
77
|
+
this.draft = cloneDraft(initial);
|
|
78
|
+
}
|
|
79
|
+
setSearchParams(value) {
|
|
80
|
+
this.draft = cloneDraft({ ...this.draft, searchParams: value });
|
|
81
|
+
return this;
|
|
82
|
+
}
|
|
83
|
+
setSearchParam(claimKey, value) {
|
|
84
|
+
this.draft = cloneDraft({
|
|
85
|
+
...this.draft,
|
|
86
|
+
searchParams: {
|
|
87
|
+
...this.draft.searchParams,
|
|
88
|
+
[claimKey]: value,
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
return this;
|
|
92
|
+
}
|
|
93
|
+
setSearchParamSender(value) {
|
|
94
|
+
return this.setSearchParam(CommunicationClaim.Sender, value);
|
|
95
|
+
}
|
|
96
|
+
setSearchParamRecipient(value) {
|
|
97
|
+
return this.setSearchParam(CommunicationClaim.Recipient, value);
|
|
98
|
+
}
|
|
99
|
+
setSearchParamCategory(value) {
|
|
100
|
+
return this.setSearchParam(CommunicationClaim.Category, value);
|
|
101
|
+
}
|
|
102
|
+
setSearchParamTopic(value) {
|
|
103
|
+
return this.setSearchParam(CommunicationClaim.Topic, value);
|
|
104
|
+
}
|
|
105
|
+
getSearchParams() {
|
|
106
|
+
return { ...this.draft.searchParams };
|
|
107
|
+
}
|
|
108
|
+
setPeriodStart(value) {
|
|
109
|
+
this.draft = cloneDraft({ ...this.draft, periodStart: value });
|
|
110
|
+
return this;
|
|
111
|
+
}
|
|
112
|
+
setPeriodEnd(value) {
|
|
113
|
+
this.draft = cloneDraft({ ...this.draft, periodEnd: value });
|
|
114
|
+
return this;
|
|
115
|
+
}
|
|
116
|
+
setPaginationCount(value) {
|
|
117
|
+
this.draft = cloneDraft({ ...this.draft, count: value });
|
|
118
|
+
return this;
|
|
119
|
+
}
|
|
120
|
+
setPageNumber(value) {
|
|
121
|
+
this.draft = cloneDraft({ ...this.draft, page: value });
|
|
122
|
+
return this;
|
|
123
|
+
}
|
|
124
|
+
getState() {
|
|
125
|
+
return cloneDraft(this.draft);
|
|
126
|
+
}
|
|
127
|
+
toSearchInput() {
|
|
128
|
+
return {
|
|
129
|
+
searchParams: this.draft.searchParams,
|
|
130
|
+
periodStart: this.draft.periodStart,
|
|
131
|
+
periodEnd: this.draft.periodEnd,
|
|
132
|
+
page: this.draft.page,
|
|
133
|
+
count: this.draft.count,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
buildRequest() {
|
|
137
|
+
return buildCommunicationParticipantSearchParameters(this.toSearchInput());
|
|
138
|
+
}
|
|
139
|
+
buildEntry() {
|
|
140
|
+
const built = this.buildBundle().entry[0];
|
|
141
|
+
return {
|
|
142
|
+
type: CommunicationSearchEntryTypes.Search,
|
|
143
|
+
request: {
|
|
144
|
+
method: 'POST',
|
|
145
|
+
url: built?.request.url || `${ResourceTypesFhirR4.Communication}/_search`,
|
|
146
|
+
},
|
|
147
|
+
resource: built?.resource || this.buildRequest(),
|
|
148
|
+
meta: {
|
|
149
|
+
operationType: CommunicationSearchOperationTypes.Search,
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
buildBundle() {
|
|
154
|
+
return buildCommunicationParticipantSearchBundle(this.toSearchInput());
|
|
155
|
+
}
|
|
156
|
+
}
|
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
import { ParameterData } from '../models/params';
|
|
2
2
|
export type SearchParameterPrimitive = string | number | boolean | readonly (string | number | boolean)[];
|
|
3
3
|
export type SearchRequestEncoding = 'get-query' | 'post-parameters';
|
|
4
|
+
/**
|
|
5
|
+
* Canonical business-level bundle types used by search request/response flows.
|
|
6
|
+
*/
|
|
7
|
+
export declare const SearchBundleTypes: Readonly<{
|
|
8
|
+
readonly Search: "search";
|
|
9
|
+
readonly SearchResponse: "search-response";
|
|
10
|
+
}>;
|
|
11
|
+
export type SearchBundleOptions = Readonly<{
|
|
12
|
+
resourceType: string;
|
|
13
|
+
searchParams?: Readonly<Record<string, SearchParameterPrimitive | undefined>>;
|
|
14
|
+
encoding?: SearchRequestEncoding;
|
|
15
|
+
bundleType?: (typeof SearchBundleTypes)[keyof typeof SearchBundleTypes];
|
|
16
|
+
}>;
|
|
4
17
|
export type FhirParametersParameter = {
|
|
5
18
|
name: string;
|
|
6
19
|
valueString?: string;
|
|
@@ -24,3 +37,22 @@ export type FhirParametersResource = {
|
|
|
24
37
|
export declare function buildSearchQueryString(searchParams: Readonly<Record<string, SearchParameterPrimitive | undefined>>): string;
|
|
25
38
|
export declare function buildFhirParametersResourceFromSearchParams(searchParams: Readonly<Record<string, SearchParameterPrimitive | undefined>>): FhirParametersResource;
|
|
26
39
|
export declare function buildFhirParametersResourceFromParameterData(parameters: ReadonlyArray<ParameterData>): FhirParametersResource;
|
|
40
|
+
/**
|
|
41
|
+
* Builds one search bundle entry using either GET query parameters or POST
|
|
42
|
+
* `Parameters`.
|
|
43
|
+
*/
|
|
44
|
+
export declare function buildSearchBundleEntry(input: SearchBundleOptions): {
|
|
45
|
+
request: {
|
|
46
|
+
method: 'GET' | 'POST';
|
|
47
|
+
url: string;
|
|
48
|
+
};
|
|
49
|
+
resource?: FhirParametersResource;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Builds a one-entry batch bundle for runtime-neutral search operations.
|
|
53
|
+
*/
|
|
54
|
+
export declare function buildSearchBundle(input: SearchBundleOptions): {
|
|
55
|
+
resourceType: 'Bundle';
|
|
56
|
+
type: (typeof SearchBundleTypes)[keyof typeof SearchBundleTypes];
|
|
57
|
+
entry: Array<ReturnType<typeof buildSearchBundleEntry>>;
|
|
58
|
+
};
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical business-level bundle types used by search request/response flows.
|
|
3
|
+
*/
|
|
4
|
+
export const SearchBundleTypes = Object.freeze({
|
|
5
|
+
Search: 'search',
|
|
6
|
+
SearchResponse: 'search-response',
|
|
7
|
+
});
|
|
1
8
|
function normalizeSearchPrimitiveValues(value) {
|
|
2
9
|
const values = Array.isArray(value) ? [...value] : [value];
|
|
3
10
|
return values
|
|
@@ -82,3 +89,41 @@ export function buildFhirParametersResourceFromParameterData(parameters) {
|
|
|
82
89
|
.filter((parameter) => Boolean(parameter)),
|
|
83
90
|
};
|
|
84
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* Builds one search bundle entry using either GET query parameters or POST
|
|
94
|
+
* `Parameters`.
|
|
95
|
+
*/
|
|
96
|
+
export function buildSearchBundleEntry(input) {
|
|
97
|
+
const resourceType = String(input.resourceType || '').trim();
|
|
98
|
+
const encoding = input.encoding || 'post-parameters';
|
|
99
|
+
const searchParams = input.searchParams || {};
|
|
100
|
+
if (!resourceType) {
|
|
101
|
+
throw new Error('buildSearchBundleEntry requires resourceType.');
|
|
102
|
+
}
|
|
103
|
+
if (encoding === 'get-query') {
|
|
104
|
+
const query = buildSearchQueryString(searchParams);
|
|
105
|
+
return {
|
|
106
|
+
request: {
|
|
107
|
+
method: 'GET',
|
|
108
|
+
url: query ? `${resourceType}?${query}` : resourceType,
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
request: {
|
|
114
|
+
method: 'POST',
|
|
115
|
+
url: `${resourceType}/_search`,
|
|
116
|
+
},
|
|
117
|
+
resource: buildFhirParametersResourceFromSearchParams(searchParams),
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Builds a one-entry batch bundle for runtime-neutral search operations.
|
|
122
|
+
*/
|
|
123
|
+
export function buildSearchBundle(input) {
|
|
124
|
+
return {
|
|
125
|
+
resourceType: 'Bundle',
|
|
126
|
+
type: input.bundleType || SearchBundleTypes.Search,
|
|
127
|
+
entry: [buildSearchBundleEntry(input)],
|
|
128
|
+
};
|
|
129
|
+
}
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -33,6 +33,10 @@ export * from './communication-fhir-r4';
|
|
|
33
33
|
export * from './communication-document-reference';
|
|
34
34
|
export * from './communication-bundle-document-request';
|
|
35
35
|
export * from './communication-identity';
|
|
36
|
+
export * from './communication-search-editor';
|
|
37
|
+
export * from './communication-participant-search';
|
|
38
|
+
export * from './communication-participant-search-test-data';
|
|
39
|
+
export * from './communication-retention-policy';
|
|
36
40
|
export * from './communication-attached-bundle-session';
|
|
37
41
|
export * from './confidential-storage-persistence';
|
|
38
42
|
export * from './confidential-storage-test-data';
|
|
@@ -44,6 +48,7 @@ export * from './fhir-validator';
|
|
|
44
48
|
export * from './family-registration-test-data';
|
|
45
49
|
export * from './individual-form-pdf';
|
|
46
50
|
export * from './individual-organization-claims';
|
|
51
|
+
export * from './organization-lifecycle';
|
|
47
52
|
export * from './individual-organization-lifecycle';
|
|
48
53
|
export * from './individual-onboarding-editor';
|
|
49
54
|
export * from './individual-onboarding-document-reference';
|
|
@@ -53,6 +58,8 @@ export * from './invoice-bundle';
|
|
|
53
58
|
export * from './ips-bundle-claims';
|
|
54
59
|
export * from './interoperable-resource-operation';
|
|
55
60
|
export * from './jwt';
|
|
61
|
+
export * from './jwk-thumbprint';
|
|
62
|
+
export * from './legal-organization-onboarding';
|
|
56
63
|
export * from './license';
|
|
57
64
|
export * from './license-commercial-search';
|
|
58
65
|
export * from './license-list-search';
|
|
@@ -69,5 +76,6 @@ export * from './object-sanitize';
|
|
|
69
76
|
export * from './permission-templates';
|
|
70
77
|
export * from './smart-scope';
|
|
71
78
|
export * from './service-act-reasons';
|
|
79
|
+
export * from './same-as';
|
|
72
80
|
export * from './activation-request';
|
|
73
81
|
export * from './vp-token';
|
package/dist/utils/index.js
CHANGED
|
@@ -33,6 +33,10 @@ export * from './communication-fhir-r4.js';
|
|
|
33
33
|
export * from './communication-document-reference.js';
|
|
34
34
|
export * from './communication-bundle-document-request.js';
|
|
35
35
|
export * from './communication-identity.js';
|
|
36
|
+
export * from './communication-search-editor.js';
|
|
37
|
+
export * from './communication-participant-search.js';
|
|
38
|
+
export * from './communication-participant-search-test-data.js';
|
|
39
|
+
export * from './communication-retention-policy.js';
|
|
36
40
|
export * from './communication-attached-bundle-session.js';
|
|
37
41
|
export * from './confidential-storage-persistence.js';
|
|
38
42
|
export * from './confidential-storage-test-data.js';
|
|
@@ -44,6 +48,7 @@ export * from './fhir-validator.js';
|
|
|
44
48
|
export * from './family-registration-test-data.js';
|
|
45
49
|
export * from './individual-form-pdf.js';
|
|
46
50
|
export * from './individual-organization-claims.js';
|
|
51
|
+
export * from './organization-lifecycle.js';
|
|
47
52
|
export * from './individual-organization-lifecycle.js';
|
|
48
53
|
export * from './individual-onboarding-editor.js';
|
|
49
54
|
export * from './individual-onboarding-document-reference.js';
|
|
@@ -53,6 +58,8 @@ export * from './invoice-bundle.js';
|
|
|
53
58
|
export * from './ips-bundle-claims.js';
|
|
54
59
|
export * from './interoperable-resource-operation.js';
|
|
55
60
|
export * from './jwt.js';
|
|
61
|
+
export * from './jwk-thumbprint.js';
|
|
62
|
+
export * from './legal-organization-onboarding.js';
|
|
56
63
|
export * from './license.js';
|
|
57
64
|
export * from './license-commercial-search.js';
|
|
58
65
|
export * from './license-list-search.js';
|
|
@@ -69,5 +76,6 @@ export * from './object-sanitize.js';
|
|
|
69
76
|
export * from './permission-templates.js';
|
|
70
77
|
export * from './smart-scope.js';
|
|
71
78
|
export * from './service-act-reasons.js';
|
|
79
|
+
export * from './same-as.js';
|
|
72
80
|
export * from './activation-request.js';
|
|
73
81
|
export * from './vp-token.js';
|
|
@@ -47,7 +47,7 @@ export type IndividualOrganizationLifecyclePayload = Readonly<{
|
|
|
47
47
|
data: IndividualOrganizationLifecycleDataEntry[];
|
|
48
48
|
};
|
|
49
49
|
}>;
|
|
50
|
-
export type
|
|
50
|
+
export type IndividualOrganizationLifecycleEditorState = Readonly<{
|
|
51
51
|
operation: IndividualOrganizationLifecycleOperation;
|
|
52
52
|
claims: IndividualOrganizationLifecycleClaims;
|
|
53
53
|
resourceId?: string;
|
|
@@ -76,7 +76,7 @@ export declare function buildCurrentIndividualOrganizationLifecycleDataEntry(inp
|
|
|
76
76
|
*/
|
|
77
77
|
export declare function buildCurrentIndividualOrganizationLifecyclePayload(input: IndividualOrganizationLifecyclePayloadInput): IndividualOrganizationLifecyclePayload;
|
|
78
78
|
/**
|
|
79
|
-
* High-level chainable
|
|
79
|
+
* High-level chainable editor for hosted individual/family lifecycle work.
|
|
80
80
|
*
|
|
81
81
|
* Teaching goal:
|
|
82
82
|
* - authors one canonical flat `org.schema.Organization.*` claim set
|
|
@@ -84,11 +84,12 @@ export declare function buildCurrentIndividualOrganizationLifecyclePayload(input
|
|
|
84
84
|
* - can emit either a semantic lifecycle message or the current GW CORE
|
|
85
85
|
* payload shape used by `sdk-node`
|
|
86
86
|
*/
|
|
87
|
-
export declare class
|
|
87
|
+
export declare class IndividualOrganizationLifecycleEditor {
|
|
88
88
|
private draft;
|
|
89
|
-
constructor(initial?: Partial<
|
|
89
|
+
constructor(initial?: Partial<IndividualOrganizationLifecycleEditorState>);
|
|
90
90
|
mergeClaims(claims: IndividualOrganizationLifecycleClaims): this;
|
|
91
91
|
setClaims(claims: IndividualOrganizationLifecycleClaims): this;
|
|
92
|
+
setContext(context: string): this;
|
|
92
93
|
setIdentifier(identifier: string): this;
|
|
93
94
|
setAlternateName(alternateName: string): this;
|
|
94
95
|
setOwnerEmail(email: string): this;
|
|
@@ -96,8 +97,17 @@ export declare class IndividualOrganizationLifecycleDraft {
|
|
|
96
97
|
setResourceId(resourceId?: string): this;
|
|
97
98
|
setRequestType(requestType: string): this;
|
|
98
99
|
setThreadId(thid: string): this;
|
|
100
|
+
getIdentifier(): string | undefined;
|
|
101
|
+
getContext(): string | undefined;
|
|
102
|
+
getAlternateName(): string | undefined;
|
|
103
|
+
getOwnerEmail(): string | undefined;
|
|
104
|
+
getOperation(): IndividualOrganizationLifecycleOperation;
|
|
105
|
+
getResourceId(): string | undefined;
|
|
106
|
+
getRequestType(): string | undefined;
|
|
107
|
+
getThreadId(): string | undefined;
|
|
99
108
|
getClaims(): IndividualOrganizationLifecycleClaims;
|
|
100
|
-
|
|
109
|
+
getState(): IndividualOrganizationLifecycleEditorState;
|
|
110
|
+
getEditorState(): IndividualOrganizationLifecycleEditorState;
|
|
101
111
|
toSemanticMessage(): IndividualOrganizationLifecycleSemanticMessage;
|
|
102
112
|
buildCurrentGwDataEntry(): IndividualOrganizationLifecycleDataEntry;
|
|
103
113
|
buildCurrentGwPayload(): IndividualOrganizationLifecyclePayload;
|
|
@@ -17,7 +17,10 @@ function normalizeText(value) {
|
|
|
17
17
|
function normalizeDraft(draft) {
|
|
18
18
|
return {
|
|
19
19
|
operation: draft?.operation || IndividualOrganizationLifecycleOperations.Disable,
|
|
20
|
-
claims:
|
|
20
|
+
claims: {
|
|
21
|
+
'@context': 'org.schema',
|
|
22
|
+
...cloneClaims(draft?.claims),
|
|
23
|
+
},
|
|
21
24
|
resourceId: normalizeText(draft?.resourceId),
|
|
22
25
|
requestType: normalizeText(draft?.requestType),
|
|
23
26
|
thid: normalizeText(draft?.thid),
|
|
@@ -75,7 +78,7 @@ export function buildCurrentIndividualOrganizationLifecyclePayload(input) {
|
|
|
75
78
|
};
|
|
76
79
|
}
|
|
77
80
|
/**
|
|
78
|
-
* High-level chainable
|
|
81
|
+
* High-level chainable editor for hosted individual/family lifecycle work.
|
|
79
82
|
*
|
|
80
83
|
* Teaching goal:
|
|
81
84
|
* - authors one canonical flat `org.schema.Organization.*` claim set
|
|
@@ -83,7 +86,7 @@ export function buildCurrentIndividualOrganizationLifecyclePayload(input) {
|
|
|
83
86
|
* - can emit either a semantic lifecycle message or the current GW CORE
|
|
84
87
|
* payload shape used by `sdk-node`
|
|
85
88
|
*/
|
|
86
|
-
export class
|
|
89
|
+
export class IndividualOrganizationLifecycleEditor {
|
|
87
90
|
draft;
|
|
88
91
|
constructor(initial) {
|
|
89
92
|
this.draft = normalizeDraft(initial);
|
|
@@ -96,6 +99,15 @@ export class IndividualOrganizationLifecycleDraft {
|
|
|
96
99
|
this.draft = patchDraft(this.draft, { claims });
|
|
97
100
|
return this;
|
|
98
101
|
}
|
|
102
|
+
setContext(context) {
|
|
103
|
+
this.draft = patchDraft(this.draft, {
|
|
104
|
+
claims: {
|
|
105
|
+
...this.draft.claims,
|
|
106
|
+
'@context': String(context).trim(),
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
return this;
|
|
110
|
+
}
|
|
99
111
|
setIdentifier(identifier) {
|
|
100
112
|
this.draft = patchDraft(this.draft, {
|
|
101
113
|
claims: {
|
|
@@ -139,12 +151,47 @@ export class IndividualOrganizationLifecycleDraft {
|
|
|
139
151
|
this.draft = patchDraft(this.draft, { thid });
|
|
140
152
|
return this;
|
|
141
153
|
}
|
|
154
|
+
getIdentifier() {
|
|
155
|
+
const value = this.draft.claims[ClaimsOrganizationSchemaorg.identifier];
|
|
156
|
+
const normalized = normalizeText(value);
|
|
157
|
+
return normalized || undefined;
|
|
158
|
+
}
|
|
159
|
+
getContext() {
|
|
160
|
+
const value = this.draft.claims['@context'];
|
|
161
|
+
const normalized = normalizeText(value);
|
|
162
|
+
return normalized || undefined;
|
|
163
|
+
}
|
|
164
|
+
getAlternateName() {
|
|
165
|
+
const value = this.draft.claims[ClaimsOrganizationSchemaorg.alternateName];
|
|
166
|
+
const normalized = normalizeText(value);
|
|
167
|
+
return normalized || undefined;
|
|
168
|
+
}
|
|
169
|
+
getOwnerEmail() {
|
|
170
|
+
const value = this.draft.claims[ClaimsOrganizationSchemaorg.ownerEmail];
|
|
171
|
+
const normalized = normalizeText(value);
|
|
172
|
+
return normalized || undefined;
|
|
173
|
+
}
|
|
174
|
+
getOperation() {
|
|
175
|
+
return this.draft.operation;
|
|
176
|
+
}
|
|
177
|
+
getResourceId() {
|
|
178
|
+
return normalizeText(this.draft.resourceId) || undefined;
|
|
179
|
+
}
|
|
180
|
+
getRequestType() {
|
|
181
|
+
return normalizeText(this.draft.requestType) || undefined;
|
|
182
|
+
}
|
|
183
|
+
getThreadId() {
|
|
184
|
+
return normalizeText(this.draft.thid) || undefined;
|
|
185
|
+
}
|
|
142
186
|
getClaims() {
|
|
143
187
|
return cloneClaims(this.draft.claims);
|
|
144
188
|
}
|
|
145
|
-
|
|
189
|
+
getState() {
|
|
146
190
|
return normalizeDraft(this.draft);
|
|
147
191
|
}
|
|
192
|
+
getEditorState() {
|
|
193
|
+
return this.getState();
|
|
194
|
+
}
|
|
148
195
|
toSemanticMessage() {
|
|
149
196
|
return {
|
|
150
197
|
operation: this.draft.operation,
|
|
@@ -156,7 +203,7 @@ export class IndividualOrganizationLifecycleDraft {
|
|
|
156
203
|
buildCurrentGwDataEntry() {
|
|
157
204
|
const requestType = normalizeText(this.draft.requestType);
|
|
158
205
|
if (!requestType) {
|
|
159
|
-
throw new Error('
|
|
206
|
+
throw new Error('IndividualOrganizationLifecycleEditor.buildCurrentGwDataEntry requires requestType.');
|
|
160
207
|
}
|
|
161
208
|
return buildCurrentIndividualOrganizationLifecycleDataEntry({
|
|
162
209
|
claims: this.getClaims(),
|
|
@@ -167,7 +214,7 @@ export class IndividualOrganizationLifecycleDraft {
|
|
|
167
214
|
buildCurrentGwPayload() {
|
|
168
215
|
const requestType = normalizeText(this.draft.requestType);
|
|
169
216
|
if (!requestType) {
|
|
170
|
-
throw new Error('
|
|
217
|
+
throw new Error('IndividualOrganizationLifecycleEditor.buildCurrentGwPayload requires requestType.');
|
|
171
218
|
}
|
|
172
219
|
return {
|
|
173
220
|
thid: this.draft.thid || createLifecycleThreadId(this.draft.operation),
|
|
@@ -16,7 +16,7 @@ export declare const InteroperableLifecycleStatuses: Readonly<{
|
|
|
16
16
|
}>;
|
|
17
17
|
export type InteroperableLifecycleStatus = typeof InteroperableLifecycleStatuses[keyof typeof InteroperableLifecycleStatuses];
|
|
18
18
|
export type InteroperableSearchParams = Readonly<Record<string, SearchParameterPrimitive | undefined>>;
|
|
19
|
-
export type
|
|
19
|
+
export type InteroperableResourceOperationState = Readonly<{
|
|
20
20
|
resourceType: string;
|
|
21
21
|
identifierClaimKey: string;
|
|
22
22
|
identifierValue?: string;
|
|
@@ -45,7 +45,7 @@ export interface InteroperableResourceOperationEditor {
|
|
|
45
45
|
mergeClaims(claims: Record<string, unknown>): InteroperableResourceOperationEditor;
|
|
46
46
|
setLifecycleStatus(value: InteroperableLifecycleStatus): InteroperableResourceOperationEditor;
|
|
47
47
|
importFhirResource(resource: FhirResource): InteroperableResourceOperationEditor;
|
|
48
|
-
|
|
48
|
+
getState(): InteroperableResourceOperationState;
|
|
49
49
|
getBusinessIdentifier(): string | undefined;
|
|
50
50
|
getClaims(): Record<string, unknown>;
|
|
51
51
|
buildLifecycleResource(): {
|
|
@@ -140,7 +140,7 @@ export declare function buildInteroperableSearchPath(resourceType: string): stri
|
|
|
140
140
|
* - `resource.meta.status` carries lifecycle state without overloading
|
|
141
141
|
* resource-specific FHIR fields such as `status` or `active`
|
|
142
142
|
*/
|
|
143
|
-
export declare function buildLifecycleOperationResource(
|
|
143
|
+
export declare function buildLifecycleOperationResource(state: InteroperableResourceOperationState): {
|
|
144
144
|
resourceType: string;
|
|
145
145
|
id?: string;
|
|
146
146
|
identifier?: Array<{
|
|
@@ -155,4 +155,4 @@ export declare function buildLifecycleOperationResource(draft: InteroperableReso
|
|
|
155
155
|
/**
|
|
156
156
|
* Creates the shared chainable editor for search/disable/purge request shapes.
|
|
157
157
|
*/
|
|
158
|
-
export declare function createInteroperableResourceOperationEditor(initial?: Partial<
|
|
158
|
+
export declare function createInteroperableResourceOperationEditor(initial?: Partial<InteroperableResourceOperationState>): InteroperableResourceOperationEditor;
|
|
@@ -24,23 +24,23 @@ function cloneClaims(claims) {
|
|
|
24
24
|
function resolveDefaultIdentifierClaimKey(resourceType) {
|
|
25
25
|
return `${String(resourceType || '').trim()}.identifier`;
|
|
26
26
|
}
|
|
27
|
-
function normalizeDraft(
|
|
28
|
-
const resourceType = normalizeText(
|
|
27
|
+
function normalizeDraft(state) {
|
|
28
|
+
const resourceType = normalizeText(state?.resourceType) || 'Resource';
|
|
29
29
|
return {
|
|
30
30
|
resourceType,
|
|
31
|
-
identifierClaimKey: normalizeText(
|
|
32
|
-
identifierValue: normalizeText(
|
|
33
|
-
identifierSystem: normalizeText(
|
|
34
|
-
resourceId: normalizeText(
|
|
35
|
-
claims: cloneClaims(
|
|
36
|
-
lifecycleStatus:
|
|
31
|
+
identifierClaimKey: normalizeText(state?.identifierClaimKey) || resolveDefaultIdentifierClaimKey(resourceType),
|
|
32
|
+
identifierValue: normalizeText(state?.identifierValue),
|
|
33
|
+
identifierSystem: normalizeText(state?.identifierSystem),
|
|
34
|
+
resourceId: normalizeText(state?.resourceId),
|
|
35
|
+
claims: cloneClaims(state?.claims),
|
|
36
|
+
lifecycleStatus: state?.lifecycleStatus,
|
|
37
37
|
};
|
|
38
38
|
}
|
|
39
|
-
function patchDraft(
|
|
39
|
+
function patchDraft(state, patch) {
|
|
40
40
|
return normalizeDraft({
|
|
41
|
-
...
|
|
41
|
+
...state,
|
|
42
42
|
...patch,
|
|
43
|
-
claims: patch.claims ? cloneClaims(patch.claims) : cloneClaims(
|
|
43
|
+
claims: patch.claims ? cloneClaims(patch.claims) : cloneClaims(state.claims),
|
|
44
44
|
});
|
|
45
45
|
}
|
|
46
46
|
/**
|
|
@@ -118,23 +118,23 @@ export function buildInteroperableSearchPath(resourceType) {
|
|
|
118
118
|
* - `resource.meta.status` carries lifecycle state without overloading
|
|
119
119
|
* resource-specific FHIR fields such as `status` or `active`
|
|
120
120
|
*/
|
|
121
|
-
export function buildLifecycleOperationResource(
|
|
122
|
-
const claims = cloneClaims(
|
|
123
|
-
if (
|
|
124
|
-
claims[
|
|
121
|
+
export function buildLifecycleOperationResource(state) {
|
|
122
|
+
const claims = cloneClaims(state.claims);
|
|
123
|
+
if (state.identifierValue && !normalizeText(claims[state.identifierClaimKey])) {
|
|
124
|
+
claims[state.identifierClaimKey] = state.identifierValue;
|
|
125
125
|
}
|
|
126
126
|
return {
|
|
127
|
-
resourceType:
|
|
128
|
-
...(
|
|
129
|
-
...(
|
|
127
|
+
resourceType: state.resourceType,
|
|
128
|
+
...(state.resourceId ? { id: state.resourceId } : {}),
|
|
129
|
+
...(state.identifierValue ? {
|
|
130
130
|
identifier: [{
|
|
131
|
-
value:
|
|
132
|
-
...(
|
|
131
|
+
value: state.identifierValue,
|
|
132
|
+
...(state.identifierSystem ? { system: state.identifierSystem } : {}),
|
|
133
133
|
}],
|
|
134
134
|
} : {}),
|
|
135
135
|
meta: {
|
|
136
136
|
claims,
|
|
137
|
-
...(
|
|
137
|
+
...(state.lifecycleStatus ? { status: state.lifecycleStatus } : {}),
|
|
138
138
|
},
|
|
139
139
|
};
|
|
140
140
|
}
|
|
@@ -192,7 +192,7 @@ export function createInteroperableResourceOperationEditor(initial) {
|
|
|
192
192
|
});
|
|
193
193
|
return editor;
|
|
194
194
|
},
|
|
195
|
-
|
|
195
|
+
getState() {
|
|
196
196
|
return normalizeDraft(draft);
|
|
197
197
|
},
|
|
198
198
|
getBusinessIdentifier() {
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { PublicJwk } from '../interfaces/Cryptography.types';
|
|
2
|
+
/**
|
|
3
|
+
* Minimal RSA public JWK shape needed for RFC 7638 thumbprint derivation.
|
|
4
|
+
*/
|
|
5
|
+
export type RsaPublicJwk = {
|
|
6
|
+
kty: 'RSA';
|
|
7
|
+
e: string;
|
|
8
|
+
n: string;
|
|
9
|
+
kid?: string;
|
|
10
|
+
alg?: string;
|
|
11
|
+
use?: string;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Public JWK shapes supported by the RFC 7638 thumbprint helpers.
|
|
15
|
+
*
|
|
16
|
+
* Notes:
|
|
17
|
+
* - classic EC keys are identified by `kty: 'EC'` and use `crv`, `x`, `y`
|
|
18
|
+
* - this includes `secp256k1`, represented as `crv: 'secp256k1'`
|
|
19
|
+
* - ML-DSA keys are represented in this codebase as `kty: 'AKP'` and use
|
|
20
|
+
* `alg` plus `pub`; they do not use `crv`
|
|
21
|
+
*/
|
|
22
|
+
export type ThumbprintableJwk = PublicJwk | RsaPublicJwk;
|
|
23
|
+
/**
|
|
24
|
+
* Computes the RFC 7638 JWK thumbprint as a bare base64url string.
|
|
25
|
+
*
|
|
26
|
+
* Canonical fields per supported key family:
|
|
27
|
+
* - `EC`: `kty`, `crv`, `x`, `y`
|
|
28
|
+
* - `RSA`: `kty`, `e`, `n`
|
|
29
|
+
* - `OKP`: `kty`, `crv`, `x`
|
|
30
|
+
* - `AKP` / ML-DSA: `kty`, `alg`, `pub`
|
|
31
|
+
*
|
|
32
|
+
* For classical EC keys, the curve is taken from `crv`, so keys such as
|
|
33
|
+
* `secp256k1` are handled naturally through `crv: 'secp256k1'`.
|
|
34
|
+
*/
|
|
35
|
+
export declare function computeRfc7638JwkThumbprint(jwk: ThumbprintableJwk): string;
|
|
36
|
+
/**
|
|
37
|
+
* Returns the RFC 9278 thumbprint URI form:
|
|
38
|
+
* `urn:ietf:params:oauth:jwk-thumbprint:sha-256:<base64url>`
|
|
39
|
+
*/
|
|
40
|
+
export declare function toJwkThumbprintSha256Urn(jwk: ThumbprintableJwk): string;
|