gdc-common-utils-ts 2.6.2 → 2.6.3

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.
@@ -16,6 +16,11 @@ export declare const EmployeeLifecycleActions: Readonly<{
16
16
  export declare const EmployeeLifecycleQueryActions: Readonly<{
17
17
  readonly List: "list";
18
18
  }>;
19
+ /** Stable response-entry types for the shared employee and seat directory. */
20
+ export declare const OrganizationEmployeeSearchResponseEntryTypes: Readonly<{
21
+ readonly Employee: "Employee-search-response-v1.0";
22
+ readonly License: "License-search-response-v1.0";
23
+ }>;
19
24
  export type EmployeeLifecycleAction = typeof EmployeeLifecycleActions[keyof typeof EmployeeLifecycleActions];
20
25
  /** Version tag for routing metadata stored outside the high-entropy GW credential. */
21
26
  export declare const EmployeeActivationGrantVersions: Readonly<{
@@ -15,6 +15,11 @@ export const EmployeeLifecycleActions = Object.freeze({
15
15
  export const EmployeeLifecycleQueryActions = Object.freeze({
16
16
  List: 'list',
17
17
  });
18
+ /** Stable response-entry types for the shared employee and seat directory. */
19
+ export const OrganizationEmployeeSearchResponseEntryTypes = Object.freeze({
20
+ Employee: 'Employee-search-response-v1.0',
21
+ License: 'License-search-response-v1.0',
22
+ });
18
23
  /** Version tag for routing metadata stored outside the high-entropy GW credential. */
19
24
  export const EmployeeActivationGrantVersions = Object.freeze({
20
25
  V1: 'employee-activation-grant-v1',
@@ -75,11 +75,43 @@ export declare function buildExampleEmployeeClaims(record: ExampleEmployeeRecord
75
75
  * to show employee directory flows without reauthoring `meta.claims` by hand.
76
76
  */
77
77
  export declare const EXAMPLE_EMPLOYEE_SEARCH_RESPONSE_BODY: Readonly<{
78
+ readonly resourceType: "Bundle";
79
+ readonly type: "batch-response";
80
+ readonly total: 3;
78
81
  readonly data: {
79
- id: string;
80
- meta: {
82
+ type: "Employee-search-response-v1.0";
83
+ resource: {
84
+ id: string;
81
85
  status: "active" | "inactive" | "purged";
82
86
  claims: Readonly<Record<string, string>>;
87
+ meta: {
88
+ status: "active" | "inactive" | "purged";
89
+ claims: Readonly<Record<string, string>>;
90
+ };
91
+ };
92
+ response: {
93
+ status: "200";
83
94
  };
84
95
  }[];
85
96
  }>;
97
+ /** @deprecated Read-only fixture for GW versions that nested search rows. */
98
+ export declare const EXAMPLE_EMPLOYEE_SEARCH_RESPONSE_BODY_LEGACY: Readonly<{
99
+ readonly data: readonly [{
100
+ readonly type: "Employee-search-response-v1.0";
101
+ readonly resource: {
102
+ readonly total: 3;
103
+ readonly data: {
104
+ id: string;
105
+ status: "active" | "inactive" | "purged";
106
+ claims: Readonly<Record<string, string>>;
107
+ meta: {
108
+ status: "active" | "inactive" | "purged";
109
+ claims: Readonly<Record<string, string>>;
110
+ };
111
+ }[];
112
+ };
113
+ readonly response: {
114
+ readonly status: "200";
115
+ };
116
+ }];
117
+ }>;
@@ -1,4 +1,6 @@
1
+ import { OrganizationEmployeeSearchResponseEntryTypes } from '../constants/employee-lifecycle.js';
1
2
  import { ClaimsPersonSchemaorg } from '../constants/schemaorg.js';
3
+ import { EXAMPLE_BUNDLE_RESOURCE_TYPE, EXAMPLE_BUNDLE_TYPE_BATCH_RESPONSE, ExampleHttpStatusText, } from './shared.js';
2
4
  export const ExampleEmployeeEmails = Object.freeze({
3
5
  SharedProfessional: 'shared.professional@example.org',
4
6
  });
@@ -68,11 +70,31 @@ export function buildExampleEmployeeClaims(record) {
68
70
  * to show employee directory flows without reauthoring `meta.claims` by hand.
69
71
  */
70
72
  export const EXAMPLE_EMPLOYEE_SEARCH_RESPONSE_BODY = Object.freeze({
73
+ resourceType: EXAMPLE_BUNDLE_RESOURCE_TYPE,
74
+ type: EXAMPLE_BUNDLE_TYPE_BATCH_RESPONSE,
75
+ total: EXAMPLE_EMPLOYEE_DIRECTORY_RECORDS.length,
71
76
  data: EXAMPLE_EMPLOYEE_DIRECTORY_RECORDS.map((record) => ({
72
- id: record.resourceId,
73
- meta: {
77
+ type: OrganizationEmployeeSearchResponseEntryTypes.Employee,
78
+ resource: {
79
+ id: record.resourceId,
74
80
  status: record.status,
75
81
  claims: buildExampleEmployeeClaims(record),
82
+ meta: {
83
+ status: record.status,
84
+ claims: buildExampleEmployeeClaims(record),
85
+ },
76
86
  },
87
+ response: { status: ExampleHttpStatusText.Ok },
77
88
  })),
78
89
  });
90
+ /** @deprecated Read-only fixture for GW versions that nested search rows. */
91
+ export const EXAMPLE_EMPLOYEE_SEARCH_RESPONSE_BODY_LEGACY = Object.freeze({
92
+ data: [{
93
+ type: OrganizationEmployeeSearchResponseEntryTypes.Employee,
94
+ resource: {
95
+ total: EXAMPLE_EMPLOYEE_SEARCH_RESPONSE_BODY.total,
96
+ data: EXAMPLE_EMPLOYEE_SEARCH_RESPONSE_BODY.data.map(entry => entry.resource),
97
+ },
98
+ response: { status: ExampleHttpStatusText.Ok },
99
+ }],
100
+ });
@@ -141,9 +141,50 @@ export declare const EXAMPLE_LICENSE_ISSUE_RESPONSE_BODY: Readonly<{
141
141
  }>;
142
142
  /** Shared license search response containing the default two-installation state. */
143
143
  export declare const EXAMPLE_LICENSE_LIST_RESPONSE_BODY_WITH_DEVICES: Readonly<{
144
+ readonly body: {
145
+ readonly resourceType: "Bundle";
146
+ readonly type: "batch-response";
147
+ readonly total: 1;
148
+ readonly data: readonly [{
149
+ readonly type: "License-search-response-v1.0";
150
+ readonly resource: {
151
+ readonly id: "8a8a5e1b-0d8e-4a7c-8c39-3b8034440001";
152
+ readonly meta: {
153
+ readonly status: "active";
154
+ readonly subjectId: string;
155
+ readonly maxDevices: 2;
156
+ readonly deviceBindings: readonly [Readonly<{
157
+ clientId: "client-employee-primary";
158
+ clientInstanceId: "installation-employee-primary";
159
+ status: "active";
160
+ deviceInfo: Readonly<{
161
+ clientInstanceId: "installation-employee-primary";
162
+ model: "Shared browser profile";
163
+ }>;
164
+ activatedAt: 1786570800;
165
+ }>, Readonly<{
166
+ clientId: "client-employee-secondary";
167
+ clientInstanceId: "installation-employee-secondary";
168
+ status: "revoked";
169
+ deviceInfo: Readonly<{
170
+ clientInstanceId: "installation-employee-secondary";
171
+ }>;
172
+ activatedAt: 1786570900;
173
+ revokedAt: 1786571000;
174
+ }>];
175
+ };
176
+ };
177
+ readonly response: {
178
+ readonly status: "200";
179
+ };
180
+ }];
181
+ };
182
+ }>;
183
+ /** @deprecated Read-only fixture for GW versions that nested search rows. */
184
+ export declare const EXAMPLE_LICENSE_LIST_RESPONSE_BODY_WITH_DEVICES_LEGACY: Readonly<{
144
185
  readonly body: {
145
186
  readonly resource: {
146
- readonly data: readonly [{
187
+ readonly data: {
147
188
  readonly id: "8a8a5e1b-0d8e-4a7c-8c39-3b8034440001";
148
189
  readonly meta: {
149
190
  readonly status: "active";
@@ -169,7 +210,7 @@ export declare const EXAMPLE_LICENSE_LIST_RESPONSE_BODY_WITH_DEVICES: Readonly<{
169
210
  revokedAt: 1786571000;
170
211
  }>];
171
212
  };
172
- }];
213
+ }[];
173
214
  };
174
215
  };
175
216
  }>;
@@ -1,8 +1,9 @@
1
1
  import { DeviceAppTypes, DeviceBindingStatuses, DeviceUserClasses } from '../constants/device.js';
2
+ import { OrganizationEmployeeSearchResponseEntryTypes } from '../constants/employee-lifecycle.js';
2
3
  import { ClaimsOrderSchemaorg, ClaimsIndividualProductSchemaorg, ClaimsOfferSchemaorg, ClaimsPersonSchemaorg, } from '../constants/schemaorg.js';
3
4
  import { buildLicenseIssueClaims, buildLicensePurchaseClaims, LicenseClaimContext, LicenseCategories, LicenseStatuses, } from '../utils/license.js';
4
5
  import { createLicenseOfferOrderEditor } from '../utils/license-offer-order.js';
5
- import { EXAMPLE_LICENSE_ACCEPTED_OFFER_ID, EXAMPLE_LICENSE_AMOUNT, EXAMPLE_LICENSE_CHECKOUT_URL, EXAMPLE_LICENSE_CURRENCY, EXAMPLE_EMAIL_CONTROLLER_ORG, EXAMPLE_EMPLOYEE_ACTIVATION_CODE, EXAMPLE_EMPLOYEE_DEVICE_CLIENT_ID_PRIMARY, EXAMPLE_EMPLOYEE_DEVICE_CLIENT_ID_SECONDARY, EXAMPLE_EMPLOYEE_DEVICE_INSTANCE_ID_PRIMARY, EXAMPLE_EMPLOYEE_DEVICE_INSTANCE_ID_SECONDARY, EXAMPLE_EMPLOYEE_DEVICE_MODEL_PRIMARY, EXAMPLE_HEALTHCARE_ACTOR_ROLE_GENERALIST_MEDICAL_PRACTITIONER, EXAMPLE_LICENSE_INVOICE_ID, EXAMPLE_LICENSE_OFFER_ID, EXAMPLE_LICENSE_PLAN_DEFAULT, EXAMPLE_LICENSE_PAYMENT_METHOD_INVOICE, EXAMPLE_LICENSE_PAYMENT_URL, EXAMPLE_LICENSE_RENEWAL_CYCLE_YEARLY, EXAMPLE_LICENSE_PLAN_NAME, EXAMPLE_LICENSE_SEAT_UUID_ACTIVE, EXAMPLE_LICENSE_SEAT_UUID_AVAILABLE, EXAMPLE_LICENSE_SEAT_UUID_SECONDARY, EXAMPLE_LICENSE_SKU, EXAMPLE_LICENSE_SUBJECT_ID_ACTIVE, EXAMPLE_LICENSE_SUBJECT_ID_AVAILABLE, EXAMPLE_TENANT_IDENTIFIER, } from './shared.js';
6
+ import { EXAMPLE_LICENSE_ACCEPTED_OFFER_ID, EXAMPLE_LICENSE_AMOUNT, EXAMPLE_LICENSE_CHECKOUT_URL, EXAMPLE_LICENSE_CURRENCY, EXAMPLE_EMAIL_CONTROLLER_ORG, EXAMPLE_EMPLOYEE_ACTIVATION_CODE, EXAMPLE_EMPLOYEE_DEVICE_CLIENT_ID_PRIMARY, EXAMPLE_EMPLOYEE_DEVICE_CLIENT_ID_SECONDARY, EXAMPLE_EMPLOYEE_DEVICE_INSTANCE_ID_PRIMARY, EXAMPLE_EMPLOYEE_DEVICE_INSTANCE_ID_SECONDARY, EXAMPLE_EMPLOYEE_DEVICE_MODEL_PRIMARY, EXAMPLE_BUNDLE_RESOURCE_TYPE, EXAMPLE_BUNDLE_TYPE_BATCH_RESPONSE, EXAMPLE_HEALTHCARE_ACTOR_ROLE_GENERALIST_MEDICAL_PRACTITIONER, EXAMPLE_LICENSE_INVOICE_ID, EXAMPLE_LICENSE_OFFER_ID, EXAMPLE_LICENSE_PLAN_DEFAULT, EXAMPLE_LICENSE_PAYMENT_METHOD_INVOICE, EXAMPLE_LICENSE_PAYMENT_URL, EXAMPLE_LICENSE_RENEWAL_CYCLE_YEARLY, EXAMPLE_LICENSE_PLAN_NAME, EXAMPLE_LICENSE_SEAT_UUID_ACTIVE, EXAMPLE_LICENSE_SEAT_UUID_AVAILABLE, EXAMPLE_LICENSE_SEAT_UUID_SECONDARY, EXAMPLE_LICENSE_SKU, EXAMPLE_LICENSE_SUBJECT_ID_ACTIVE, EXAMPLE_LICENSE_SUBJECT_ID_AVAILABLE, EXAMPLE_TENANT_IDENTIFIER, ExampleHttpStatusText, } from './shared.js';
6
7
  import { DEFAULT_LICENSE_DEVICE_ALLOWANCE } from '../utils/license.js';
7
8
  import { EXAMPLE_EMPLOYEE_CONTROLLER_ACTIVE } from './employee.js';
8
9
  export const EXAMPLE_EMPLOYEE_DEVICE_BINDINGS = Object.freeze([
@@ -123,8 +124,12 @@ export const EXAMPLE_LICENSE_ISSUE_RESPONSE_BODY = Object.freeze({
123
124
  /** Shared license search response containing the default two-installation state. */
124
125
  export const EXAMPLE_LICENSE_LIST_RESPONSE_BODY_WITH_DEVICES = Object.freeze({
125
126
  body: {
126
- resource: {
127
- data: [{
127
+ resourceType: EXAMPLE_BUNDLE_RESOURCE_TYPE,
128
+ type: EXAMPLE_BUNDLE_TYPE_BATCH_RESPONSE,
129
+ total: 1,
130
+ data: [{
131
+ type: OrganizationEmployeeSearchResponseEntryTypes.License,
132
+ resource: {
128
133
  id: EXAMPLE_LICENSE_ACTIVE_RECORD.id,
129
134
  meta: {
130
135
  status: EXAMPLE_LICENSE_ACTIVE_RECORD.status,
@@ -132,7 +137,16 @@ export const EXAMPLE_LICENSE_LIST_RESPONSE_BODY_WITH_DEVICES = Object.freeze({
132
137
  maxDevices: DEFAULT_LICENSE_DEVICE_ALLOWANCE,
133
138
  deviceBindings: EXAMPLE_EMPLOYEE_DEVICE_BINDINGS,
134
139
  },
135
- }],
140
+ },
141
+ response: { status: ExampleHttpStatusText.Ok },
142
+ }],
143
+ },
144
+ });
145
+ /** @deprecated Read-only fixture for GW versions that nested search rows. */
146
+ export const EXAMPLE_LICENSE_LIST_RESPONSE_BODY_WITH_DEVICES_LEGACY = Object.freeze({
147
+ body: {
148
+ resource: {
149
+ data: EXAMPLE_LICENSE_LIST_RESPONSE_BODY_WITH_DEVICES.body.data.map(entry => entry.resource),
136
150
  },
137
151
  },
138
152
  });
@@ -247,6 +247,7 @@ export declare const EXAMPLE_CONTENT_TYPE_FHIR_JSON: "application/fhir+json";
247
247
  export declare const EXAMPLE_IPS_BUNDLE_ATTACHMENT_TITLE: "IPS Document Bundle";
248
248
  export declare const EXAMPLE_BUNDLE_RESOURCE_TYPE: "Bundle";
249
249
  export declare const EXAMPLE_BUNDLE_TYPE_BATCH: "batch";
250
+ export declare const EXAMPLE_BUNDLE_TYPE_BATCH_RESPONSE: "batch-response";
250
251
  export declare const EXAMPLE_BUNDLE_TYPE_DOCUMENT: "document";
251
252
  export declare const EXAMPLE_MEDICATION_STATEMENT_UUID: "urn:uuid:medication-statement-example-001";
252
253
  export declare const EXAMPLE_MEDICATION_STATEMENT_IDENTIFIER: "urn:uuid:medication-statement-example-001";
@@ -289,6 +289,7 @@ export const EXAMPLE_CONTENT_TYPE_FHIR_JSON = 'application/fhir+json';
289
289
  export const EXAMPLE_IPS_BUNDLE_ATTACHMENT_TITLE = 'IPS Document Bundle';
290
290
  export const EXAMPLE_BUNDLE_RESOURCE_TYPE = 'Bundle';
291
291
  export const EXAMPLE_BUNDLE_TYPE_BATCH = 'batch';
292
+ export const EXAMPLE_BUNDLE_TYPE_BATCH_RESPONSE = 'batch-response';
292
293
  export const EXAMPLE_BUNDLE_TYPE_DOCUMENT = 'document';
293
294
  export const EXAMPLE_MEDICATION_STATEMENT_UUID = 'urn:uuid:medication-statement-example-001';
294
295
  export const EXAMPLE_MEDICATION_STATEMENT_IDENTIFIER = EXAMPLE_MEDICATION_STATEMENT_UUID;
@@ -3,8 +3,16 @@ import type { EmployeeDeviceRevocationTarget, OrganizationEmployeeLifecycleRecor
3
3
  export declare function buildEmployeeDeviceRevocationBody(target: EmployeeDeviceRevocationTarget): Readonly<Record<string, string>>;
4
4
  /** Reads an employee activation credential from canonical and legacy GW envelopes. */
5
5
  export declare function readEmployeeActivationCode(value: unknown): string;
6
- /** Extracts GW search rows regardless of async job envelope depth. */
7
- export declare function extractGwSearchResources(value: unknown): ReadonlyArray<Record<string, unknown>>;
6
+ /**
7
+ * Extracts primary resources from a DIDComm FHIR-like response Bundle.
8
+ *
9
+ * Canonical search matches live at `body.data[].resource`. The deprecated
10
+ * `resource.{total,data}` aggregate remains a read-only compatibility path so
11
+ * an SDK can survive a rolling GW deployment; producers must not emit it.
12
+ */
13
+ export declare function extractBundleSearchResources(value: unknown): ReadonlyArray<Record<string, unknown>>;
14
+ /** @deprecated Use the transport-neutral `extractBundleSearchResources`. */
15
+ export declare const extractGwSearchResources: typeof extractBundleSearchResources;
8
16
  /** Combines employee directory and license search results into one typed view. */
9
17
  export declare function projectOrganizationEmployeeLifecycle(input: Readonly<{
10
18
  employeeResponse: unknown;
@@ -25,19 +25,47 @@ export function readEmployeeActivationCode(value) {
25
25
  }
26
26
  return '';
27
27
  }
28
- /** Extracts GW search rows regardless of async job envelope depth. */
29
- export function extractGwSearchResources(value) {
28
+ /**
29
+ * Extracts primary resources from a DIDComm FHIR-like response Bundle.
30
+ *
31
+ * Canonical search matches live at `body.data[].resource`. The deprecated
32
+ * `resource.{total,data}` aggregate remains a read-only compatibility path so
33
+ * an SDK can survive a rolling GW deployment; producers must not emit it.
34
+ */
35
+ export function extractBundleSearchResources(value) {
30
36
  for (const candidate of listNestedRecords(value)) {
31
- const data = record(candidate.resource)?.data || candidate.data;
32
- if (Array.isArray(data))
33
- return data.map(record).filter(isRecord);
37
+ if (!Array.isArray(candidate.data))
38
+ continue;
39
+ const entries = candidate.data.map(record).filter(isRecord);
40
+ if (entries.length === 0)
41
+ return [];
42
+ const resources = entries.flatMap((entry) => {
43
+ const resource = record(entry.resource);
44
+ if (!resource)
45
+ return [];
46
+ const legacyRows = resource.total !== undefined && Array.isArray(resource.data)
47
+ ? resource.data.map(record).filter(isRecord)
48
+ : undefined;
49
+ return legacyRows ?? [resource];
50
+ });
51
+ if (resources.length > 0)
52
+ return resources;
53
+ // Compatibility for older SDK fixtures that passed already-extracted rows.
54
+ return entries;
55
+ }
56
+ for (const candidate of listNestedRecords(value)) {
57
+ const legacyRows = record(candidate.resource)?.data;
58
+ if (Array.isArray(legacyRows))
59
+ return legacyRows.map(record).filter(isRecord);
34
60
  }
35
61
  return [];
36
62
  }
63
+ /** @deprecated Use the transport-neutral `extractBundleSearchResources`. */
64
+ export const extractGwSearchResources = extractBundleSearchResources;
37
65
  /** Combines employee directory and license search results into one typed view. */
38
66
  export function projectOrganizationEmployeeLifecycle(input) {
39
- const licenses = extractGwSearchResources(input.licenseResponse);
40
- return extractGwSearchResources(input.employeeResponse).map((employee) => {
67
+ const licenses = extractBundleSearchResources(input.licenseResponse);
68
+ return extractBundleSearchResources(input.employeeResponse).map((employee) => {
41
69
  const claims = record(employee.claims) || record(record(employee.meta)?.claims) || {};
42
70
  const resourceId = text(employee.id);
43
71
  const employeeDid = text(claims[ClaimsPersonSchemaorg.identifier]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gdc-common-utils-ts",
3
- "version": "2.6.2",
3
+ "version": "2.6.3",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },