gdc-common-utils-ts 1.20.0 → 1.20.2
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/constants/schemaorg.d.ts +14 -0
- package/dist/constants/schemaorg.js +15 -0
- package/dist/constants/service-capabilities.d.ts +4 -0
- package/dist/constants/service-capabilities.js +9 -0
- package/dist/examples/index.d.ts +1 -0
- package/dist/examples/index.js +1 -0
- package/dist/examples/license.d.ts +32 -0
- package/dist/examples/license.js +43 -0
- package/dist/utils/dataspace-discovery.js +9 -2
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/license.d.ts +149 -0
- package/dist/utils/license.js +188 -0
- package/dist/utils/service-act-reasons.d.ts +16 -0
- package/dist/utils/service-act-reasons.js +68 -0
- package/package.json +1 -1
|
@@ -109,6 +109,20 @@ export declare enum ClaimsOfferSchemaorg {
|
|
|
109
109
|
priceCurrency = "org.schema.Offer.priceCurrency",
|
|
110
110
|
serialNumber = "org.schema.Offer.serialNumber"
|
|
111
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* Canonical claim names used by the current GDC profile when a VC or flat
|
|
114
|
+
* request models a `schema.org/IndividualProduct`.
|
|
115
|
+
*
|
|
116
|
+
* Current GW licensing semantics use this family to represent:
|
|
117
|
+
* - the concrete seat/license serial number
|
|
118
|
+
* - the license category (`professional` or `individual`)
|
|
119
|
+
* - the target app/device form factor (`mobile` or `web`)
|
|
120
|
+
*/
|
|
121
|
+
export declare enum ClaimsIndividualProductSchemaorg {
|
|
122
|
+
category = "org.schema.IndividualProduct.category",
|
|
123
|
+
additionalType = "org.schema.IndividualProduct.additionalType",
|
|
124
|
+
serialNumber = "org.schema.IndividualProduct.serialNumber"
|
|
125
|
+
}
|
|
112
126
|
export declare enum ClaimsOrderSchemaorg {
|
|
113
127
|
orderedItemServiceType = "org.schema.Order.orderedItem.serviceType"
|
|
114
128
|
}
|
|
@@ -114,6 +114,21 @@ export var ClaimsOfferSchemaorg;
|
|
|
114
114
|
ClaimsOfferSchemaorg["priceCurrency"] = "org.schema.Offer.priceCurrency";
|
|
115
115
|
ClaimsOfferSchemaorg["serialNumber"] = "org.schema.Offer.serialNumber";
|
|
116
116
|
})(ClaimsOfferSchemaorg || (ClaimsOfferSchemaorg = {}));
|
|
117
|
+
/**
|
|
118
|
+
* Canonical claim names used by the current GDC profile when a VC or flat
|
|
119
|
+
* request models a `schema.org/IndividualProduct`.
|
|
120
|
+
*
|
|
121
|
+
* Current GW licensing semantics use this family to represent:
|
|
122
|
+
* - the concrete seat/license serial number
|
|
123
|
+
* - the license category (`professional` or `individual`)
|
|
124
|
+
* - the target app/device form factor (`mobile` or `web`)
|
|
125
|
+
*/
|
|
126
|
+
export var ClaimsIndividualProductSchemaorg;
|
|
127
|
+
(function (ClaimsIndividualProductSchemaorg) {
|
|
128
|
+
ClaimsIndividualProductSchemaorg["category"] = "org.schema.IndividualProduct.category";
|
|
129
|
+
ClaimsIndividualProductSchemaorg["additionalType"] = "org.schema.IndividualProduct.additionalType";
|
|
130
|
+
ClaimsIndividualProductSchemaorg["serialNumber"] = "org.schema.IndividualProduct.serialNumber";
|
|
131
|
+
})(ClaimsIndividualProductSchemaorg || (ClaimsIndividualProductSchemaorg = {}));
|
|
117
132
|
export var ClaimsOrderSchemaorg;
|
|
118
133
|
(function (ClaimsOrderSchemaorg) {
|
|
119
134
|
ClaimsOrderSchemaorg["orderedItemServiceType"] = "org.schema.Order.orderedItem.serviceType";
|
|
@@ -88,6 +88,10 @@ export type ServiceCapabilityTokenValue = typeof ServiceCapabilityToken[keyof ty
|
|
|
88
88
|
* Normalizes a service capability token into its canonical persisted form.
|
|
89
89
|
*/
|
|
90
90
|
export declare function normalizeServiceCapability(value: string | undefined | null): string | undefined;
|
|
91
|
+
/**
|
|
92
|
+
* Returns whether the token is one of the known persisted service capabilities.
|
|
93
|
+
*/
|
|
94
|
+
export declare function isKnownServiceCapability(value: string | undefined | null): boolean;
|
|
91
95
|
/**
|
|
92
96
|
* Parses the CSV stored in `org.schema.Service.serviceType`.
|
|
93
97
|
*/
|
|
@@ -108,6 +108,15 @@ export function normalizeServiceCapability(value) {
|
|
|
108
108
|
return undefined;
|
|
109
109
|
return CANONICAL_SERVICE_CAPABILITY_BY_VALUE.get(normalized.toLowerCase()) || normalized;
|
|
110
110
|
}
|
|
111
|
+
/**
|
|
112
|
+
* Returns whether the token is one of the known persisted service capabilities.
|
|
113
|
+
*/
|
|
114
|
+
export function isKnownServiceCapability(value) {
|
|
115
|
+
const normalized = String(value || '').trim().toLowerCase();
|
|
116
|
+
if (!normalized)
|
|
117
|
+
return false;
|
|
118
|
+
return CANONICAL_SERVICE_CAPABILITY_BY_VALUE.has(normalized);
|
|
119
|
+
}
|
|
111
120
|
/**
|
|
112
121
|
* Parses the CSV stored in `org.schema.Service.serviceType`.
|
|
113
122
|
*/
|
package/dist/examples/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export * from './organization-controller';
|
|
|
5
5
|
export * from './individual-controller';
|
|
6
6
|
export * from './professional';
|
|
7
7
|
export * from './employee';
|
|
8
|
+
export * from './license';
|
|
8
9
|
export * from './related-person';
|
|
9
10
|
export * from './consent-access';
|
|
10
11
|
export * from './relationship-access';
|
package/dist/examples/index.js
CHANGED
|
@@ -5,6 +5,7 @@ export * from './organization-controller.js';
|
|
|
5
5
|
export * from './individual-controller.js';
|
|
6
6
|
export * from './professional.js';
|
|
7
7
|
export * from './employee.js';
|
|
8
|
+
export * from './license.js';
|
|
8
9
|
export * from './related-person.js';
|
|
9
10
|
export * from './consent-access.js';
|
|
10
11
|
export * from './relationship-access.js';
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export declare const EXAMPLE_LICENSE_SEAT_UUIDS: readonly ["8a8a5e1b-0d8e-4a7c-8c39-3b8034440001", "8a8a5e1b-0d8e-4a7c-8c39-3b8034440002"];
|
|
2
|
+
export declare const EXAMPLE_LICENSE_ISSUE_INPUT: Readonly<{
|
|
3
|
+
readonly email: "controller@acme.org";
|
|
4
|
+
readonly role: "ISCO-08|2211";
|
|
5
|
+
readonly userClass: "employee";
|
|
6
|
+
readonly type: "mobile";
|
|
7
|
+
}>;
|
|
8
|
+
export declare const EXAMPLE_LICENSE_PURCHASE_INPUT: Readonly<{
|
|
9
|
+
readonly quantity: 2;
|
|
10
|
+
readonly userClass: "employee";
|
|
11
|
+
readonly type: "web";
|
|
12
|
+
readonly serialNumbers: readonly ["8a8a5e1b-0d8e-4a7c-8c39-3b8034440001", "8a8a5e1b-0d8e-4a7c-8c39-3b8034440002"];
|
|
13
|
+
}>;
|
|
14
|
+
export declare const EXAMPLE_LICENSE_ACTIVE_RECORD: Readonly<{
|
|
15
|
+
readonly id: "8a8a5e1b-0d8e-4a7c-8c39-3b8034440001";
|
|
16
|
+
readonly status: "active";
|
|
17
|
+
readonly activationCode: "ACT-001";
|
|
18
|
+
readonly subjectId: "urn:uuid:employee-controller-active-001";
|
|
19
|
+
readonly claims: {
|
|
20
|
+
readonly '@context': "org.schema";
|
|
21
|
+
readonly "org.schema.IndividualProduct.serialNumber": "8a8a5e1b-0d8e-4a7c-8c39-3b8034440001";
|
|
22
|
+
readonly "org.schema.IndividualProduct.category": "professional";
|
|
23
|
+
readonly "org.schema.IndividualProduct.additionalType": "mobile";
|
|
24
|
+
readonly "org.schema.Person.email": "controller@acme.org";
|
|
25
|
+
readonly "org.schema.Person.hasOccupation.identifier.value": "ISCO-08|2211";
|
|
26
|
+
};
|
|
27
|
+
}>;
|
|
28
|
+
export declare function buildExampleLicenseIssueClaims(): Readonly<Record<string, unknown>>;
|
|
29
|
+
export declare function buildExampleLicensePurchaseClaims(): Readonly<Record<string, unknown>>;
|
|
30
|
+
export declare const EXAMPLE_LICENSE_PURCHASE_CLAIMS: Readonly<Record<string, unknown>>;
|
|
31
|
+
export declare const EXAMPLE_LICENSE_ISSUE_CLAIMS: Readonly<Record<string, unknown>>;
|
|
32
|
+
export declare const EXAMPLE_LICENSE_PURCHASE_EXPECTED_SERIAL_NUMBER: string;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { DeviceAppTypes, DeviceUserClasses } from '../constants/device.js';
|
|
2
|
+
import { ClaimsIndividualProductSchemaorg, ClaimsOfferSchemaorg, ClaimsPersonSchemaorg, } from '../constants/schemaorg.js';
|
|
3
|
+
import { buildLicenseIssueClaims, buildLicensePurchaseClaims, LicenseCategories, LicenseStatuses, } from '../utils/license.js';
|
|
4
|
+
import { EXAMPLE_EMAIL_CONTROLLER_ORG, EXAMPLE_EMPLOYEE_ACTIVATION_CODE, EXAMPLE_HEALTHCARE_ACTOR_ROLE_GENERALIST_MEDICAL_PRACTITIONER, } from './shared.js';
|
|
5
|
+
export const EXAMPLE_LICENSE_SEAT_UUIDS = Object.freeze([
|
|
6
|
+
'8a8a5e1b-0d8e-4a7c-8c39-3b8034440001',
|
|
7
|
+
'8a8a5e1b-0d8e-4a7c-8c39-3b8034440002',
|
|
8
|
+
]);
|
|
9
|
+
export const EXAMPLE_LICENSE_ISSUE_INPUT = Object.freeze({
|
|
10
|
+
email: EXAMPLE_EMAIL_CONTROLLER_ORG,
|
|
11
|
+
role: EXAMPLE_HEALTHCARE_ACTOR_ROLE_GENERALIST_MEDICAL_PRACTITIONER,
|
|
12
|
+
userClass: DeviceUserClasses.Employee,
|
|
13
|
+
type: DeviceAppTypes.Mobile,
|
|
14
|
+
});
|
|
15
|
+
export const EXAMPLE_LICENSE_PURCHASE_INPUT = Object.freeze({
|
|
16
|
+
quantity: EXAMPLE_LICENSE_SEAT_UUIDS.length,
|
|
17
|
+
userClass: DeviceUserClasses.Employee,
|
|
18
|
+
type: DeviceAppTypes.Web,
|
|
19
|
+
serialNumbers: EXAMPLE_LICENSE_SEAT_UUIDS,
|
|
20
|
+
});
|
|
21
|
+
export const EXAMPLE_LICENSE_ACTIVE_RECORD = Object.freeze({
|
|
22
|
+
id: EXAMPLE_LICENSE_SEAT_UUIDS[0],
|
|
23
|
+
status: LicenseStatuses.Active,
|
|
24
|
+
activationCode: EXAMPLE_EMPLOYEE_ACTIVATION_CODE,
|
|
25
|
+
subjectId: 'urn:uuid:employee-controller-active-001',
|
|
26
|
+
claims: {
|
|
27
|
+
'@context': 'org.schema',
|
|
28
|
+
[ClaimsIndividualProductSchemaorg.serialNumber]: EXAMPLE_LICENSE_SEAT_UUIDS[0],
|
|
29
|
+
[ClaimsIndividualProductSchemaorg.category]: LicenseCategories.Professional,
|
|
30
|
+
[ClaimsIndividualProductSchemaorg.additionalType]: DeviceAppTypes.Mobile,
|
|
31
|
+
[ClaimsPersonSchemaorg.email]: EXAMPLE_EMAIL_CONTROLLER_ORG,
|
|
32
|
+
[ClaimsPersonSchemaorg.hasOccupationalRoleValue]: EXAMPLE_HEALTHCARE_ACTOR_ROLE_GENERALIST_MEDICAL_PRACTITIONER,
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
export function buildExampleLicenseIssueClaims() {
|
|
36
|
+
return Object.freeze(buildLicenseIssueClaims(EXAMPLE_LICENSE_ISSUE_INPUT));
|
|
37
|
+
}
|
|
38
|
+
export function buildExampleLicensePurchaseClaims() {
|
|
39
|
+
return Object.freeze(buildLicensePurchaseClaims(EXAMPLE_LICENSE_PURCHASE_INPUT));
|
|
40
|
+
}
|
|
41
|
+
export const EXAMPLE_LICENSE_PURCHASE_CLAIMS = buildExampleLicensePurchaseClaims();
|
|
42
|
+
export const EXAMPLE_LICENSE_ISSUE_CLAIMS = buildExampleLicenseIssueClaims();
|
|
43
|
+
export const EXAMPLE_LICENSE_PURCHASE_EXPECTED_SERIAL_NUMBER = EXAMPLE_LICENSE_PURCHASE_CLAIMS[ClaimsOfferSchemaorg.serialNumber];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
|
|
2
2
|
import { ClaimsOrganizationSchemaorg, ClaimsServiceSchemaorg } from '../constants/schemaorg.js';
|
|
3
3
|
import { isEuCountryCode, normalizeCountryCode } from '../constants/eu-countries.js';
|
|
4
|
-
import { isProviderServiceCapability, parseServiceCapabilityTokens, } from '../constants/service-capabilities.js';
|
|
4
|
+
import { isKnownServiceCapability, isProviderServiceCapability, parseServiceCapabilityTokens, } from '../constants/service-capabilities.js';
|
|
5
5
|
import { DataspaceCoverageScope, } from '../models/dataspace-discovery.js';
|
|
6
6
|
function asObject(value) {
|
|
7
7
|
return value && typeof value === 'object' && !Array.isArray(value)
|
|
@@ -142,13 +142,20 @@ export function parseServiceTypeCsv(value) {
|
|
|
142
142
|
}
|
|
143
143
|
return parseServiceCapabilityTokens(value);
|
|
144
144
|
}
|
|
145
|
+
function parseAdditionalTypeCapabilityCsv(value) {
|
|
146
|
+
if (Array.isArray(value)) {
|
|
147
|
+
return Array.from(new Set(value.flatMap((entry) => parseAdditionalTypeCapabilityCsv(entry))));
|
|
148
|
+
}
|
|
149
|
+
return parseServiceCapabilityTokens(value)
|
|
150
|
+
.filter((item) => isKnownServiceCapability(item));
|
|
151
|
+
}
|
|
145
152
|
/**
|
|
146
153
|
* Parses service capability tokens from both `serviceType` and `additionalType`.
|
|
147
154
|
*/
|
|
148
155
|
export function parseServiceTypeClaims(serviceTypeValue, additionalTypeValue) {
|
|
149
156
|
return Array.from(new Set([
|
|
150
157
|
...parseServiceTypeCsv(serviceTypeValue),
|
|
151
|
-
...
|
|
158
|
+
...parseAdditionalTypeCapabilityCsv(additionalTypeValue),
|
|
152
159
|
]));
|
|
153
160
|
}
|
|
154
161
|
/**
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -43,6 +43,7 @@ export * from './individual-onboarding-document-reference';
|
|
|
43
43
|
export * from './individual-organization-kyc';
|
|
44
44
|
export * from './ips-bundle-claims';
|
|
45
45
|
export * from './jwt';
|
|
46
|
+
export * from './license';
|
|
46
47
|
export * from './manager-error';
|
|
47
48
|
export * from './multibase58';
|
|
48
49
|
export * from './multibasehash';
|
|
@@ -52,5 +53,6 @@ export * from './object-convert';
|
|
|
52
53
|
export * from './normalize-uuid';
|
|
53
54
|
export * from './permission-templates';
|
|
54
55
|
export * from './smart-scope';
|
|
56
|
+
export * from './service-act-reasons';
|
|
55
57
|
export * from './activation-request';
|
|
56
58
|
export * from './vp-token';
|
package/dist/utils/index.js
CHANGED
|
@@ -43,6 +43,7 @@ export * from './individual-onboarding-document-reference.js';
|
|
|
43
43
|
export * from './individual-organization-kyc.js';
|
|
44
44
|
export * from './ips-bundle-claims.js';
|
|
45
45
|
export * from './jwt.js';
|
|
46
|
+
export * from './license.js';
|
|
46
47
|
export * from './manager-error.js';
|
|
47
48
|
export * from './multibase58.js';
|
|
48
49
|
export * from './multibasehash.js';
|
|
@@ -52,5 +53,6 @@ export * from './object-convert.js';
|
|
|
52
53
|
export * from './normalize-uuid.js';
|
|
53
54
|
export * from './permission-templates.js';
|
|
54
55
|
export * from './smart-scope.js';
|
|
56
|
+
export * from './service-act-reasons.js';
|
|
55
57
|
export * from './activation-request.js';
|
|
56
58
|
export * from './vp-token.js';
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { DeviceAppType, DeviceUserClass } from '../constants/device';
|
|
2
|
+
export type LicenseClaims = Record<string, unknown>;
|
|
3
|
+
export declare const LicenseClaimContext: Readonly<{
|
|
4
|
+
readonly SchemaOrg: "org.schema";
|
|
5
|
+
}>;
|
|
6
|
+
/**
|
|
7
|
+
* Canonical business categories currently used by GW licensing flows.
|
|
8
|
+
*
|
|
9
|
+
* Mapping:
|
|
10
|
+
* - employee -> professional
|
|
11
|
+
* - individual -> individual
|
|
12
|
+
*/
|
|
13
|
+
export declare const LicenseCategories: Readonly<{
|
|
14
|
+
readonly Professional: "professional";
|
|
15
|
+
readonly Individual: "individual";
|
|
16
|
+
}>;
|
|
17
|
+
export type LicenseCategory = typeof LicenseCategories[keyof typeof LicenseCategories];
|
|
18
|
+
/**
|
|
19
|
+
* Stable helper-level request type ids for license-oriented batch entries.
|
|
20
|
+
*
|
|
21
|
+
* These are request metadata strings emitted by SDK/common-utils helpers so
|
|
22
|
+
* callers do not handcraft type labels inline.
|
|
23
|
+
*/
|
|
24
|
+
export declare const LicenseEntryTypes: Readonly<{
|
|
25
|
+
readonly Issue: "License-issue-request-v1.0";
|
|
26
|
+
readonly Purchase: "License-purchase-request-v1.0";
|
|
27
|
+
readonly Search: "License-search-request-v1.0";
|
|
28
|
+
}>;
|
|
29
|
+
export declare const LicenseEntryOperations: Readonly<{
|
|
30
|
+
readonly Issue: "IndividualProduct:Issue";
|
|
31
|
+
readonly Purchase: "IndividualProduct:Purchase";
|
|
32
|
+
readonly Search: "IndividualProduct:Search";
|
|
33
|
+
}>;
|
|
34
|
+
export declare const LicenseRequestMethods: Readonly<{
|
|
35
|
+
readonly Post: "POST";
|
|
36
|
+
}>;
|
|
37
|
+
/**
|
|
38
|
+
* Runtime-facing lifecycle values commonly used when searching stored
|
|
39
|
+
* `DeviceLicense` documents.
|
|
40
|
+
*
|
|
41
|
+
* These are not schema.org claims. They are operational filters that runtime
|
|
42
|
+
* layers may attach alongside the canonical schema.org claims.
|
|
43
|
+
*/
|
|
44
|
+
export declare const LicenseStatuses: Readonly<{
|
|
45
|
+
readonly Available: "available";
|
|
46
|
+
readonly Issued: "issued";
|
|
47
|
+
readonly Active: "active";
|
|
48
|
+
readonly Inactive: "inactive";
|
|
49
|
+
}>;
|
|
50
|
+
export type LicenseStatus = typeof LicenseStatuses[keyof typeof LicenseStatuses];
|
|
51
|
+
export type LicenseIssueInput = Readonly<{
|
|
52
|
+
email: string;
|
|
53
|
+
role: string;
|
|
54
|
+
userClass?: DeviceUserClass;
|
|
55
|
+
type?: DeviceAppType;
|
|
56
|
+
additionalClaims?: LicenseClaims;
|
|
57
|
+
}>;
|
|
58
|
+
export type LicensePurchaseInput = Readonly<{
|
|
59
|
+
quantity: number;
|
|
60
|
+
userClass?: DeviceUserClass;
|
|
61
|
+
type?: DeviceAppType;
|
|
62
|
+
serialNumbers?: readonly string[];
|
|
63
|
+
additionalClaims?: LicenseClaims;
|
|
64
|
+
}>;
|
|
65
|
+
export type LicenseSearchInput = Readonly<{
|
|
66
|
+
serialNumbers?: readonly string[];
|
|
67
|
+
userClass?: DeviceUserClass;
|
|
68
|
+
type?: DeviceAppType;
|
|
69
|
+
email?: string;
|
|
70
|
+
role?: string;
|
|
71
|
+
status?: LicenseStatus;
|
|
72
|
+
subjectId?: string;
|
|
73
|
+
additionalClaims?: LicenseClaims;
|
|
74
|
+
}>;
|
|
75
|
+
/**
|
|
76
|
+
* Maps one canonical runtime user class to the schema.org-compatible
|
|
77
|
+
* `IndividualProduct.category` value used by current GW flows.
|
|
78
|
+
*/
|
|
79
|
+
export declare function mapLicenseCategoryFromUserClass(userClass?: DeviceUserClass): LicenseCategory;
|
|
80
|
+
/**
|
|
81
|
+
* Converts a list of seat ids / serial numbers into the compact string form
|
|
82
|
+
* currently stored in `org.schema.Offer.serialNumber`.
|
|
83
|
+
*/
|
|
84
|
+
export declare function serializeLicenseSerialNumbers(serialNumbers?: readonly string[]): string | undefined;
|
|
85
|
+
/**
|
|
86
|
+
* Builds canonical `org.schema.*` claims for `License/_issue`.
|
|
87
|
+
*
|
|
88
|
+
* The resulting payload keeps current GW semantics:
|
|
89
|
+
* - recipient identity/role comes from `Person.*`
|
|
90
|
+
* - seat/app semantics come from `IndividualProduct.*`
|
|
91
|
+
*/
|
|
92
|
+
export declare function buildLicenseIssueClaims(input: LicenseIssueInput): LicenseClaims;
|
|
93
|
+
/**
|
|
94
|
+
* Builds the canonical batch entry for `License/_issue`.
|
|
95
|
+
*/
|
|
96
|
+
export declare function buildLicenseIssueEntry(input: LicenseIssueInput): {
|
|
97
|
+
type: string;
|
|
98
|
+
request: {
|
|
99
|
+
method: 'POST';
|
|
100
|
+
};
|
|
101
|
+
meta: {
|
|
102
|
+
claims: LicenseClaims;
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* Builds canonical schema.org claims for a license purchase / seat-creation
|
|
107
|
+
* request.
|
|
108
|
+
*
|
|
109
|
+
* Current business semantics:
|
|
110
|
+
* - `Offer.eligibleQuantity.value` requests how many seats must exist
|
|
111
|
+
* - `Offer.serialNumber` can optionally carry the explicit seat ids when they
|
|
112
|
+
* are already known or preallocated
|
|
113
|
+
* - `IndividualProduct.*` classifies the target seat family/form factor
|
|
114
|
+
*/
|
|
115
|
+
export declare function buildLicensePurchaseClaims(input: LicensePurchaseInput): LicenseClaims;
|
|
116
|
+
/**
|
|
117
|
+
* Builds the canonical batch entry for a purchase/order-oriented license
|
|
118
|
+
* request.
|
|
119
|
+
*/
|
|
120
|
+
export declare function buildLicensePurchaseEntry(input: LicensePurchaseInput): {
|
|
121
|
+
type: string;
|
|
122
|
+
request: {
|
|
123
|
+
method: 'POST';
|
|
124
|
+
};
|
|
125
|
+
meta: {
|
|
126
|
+
claims: LicenseClaims;
|
|
127
|
+
};
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* Builds the canonical search envelope for license listing.
|
|
131
|
+
*
|
|
132
|
+
* Split of concerns:
|
|
133
|
+
* - schema.org-compatible selectors stay in `meta.claims`
|
|
134
|
+
* - document lifecycle stays in `meta.status`, mirroring the current
|
|
135
|
+
* `ConfidentialStorageDoc.status` usage
|
|
136
|
+
* - `subjectId` remains an explicit side-field until a canonical indexed claim
|
|
137
|
+
* is introduced for that lookup
|
|
138
|
+
*/
|
|
139
|
+
export declare function buildLicenseSearchEntry(input: LicenseSearchInput): {
|
|
140
|
+
type: string;
|
|
141
|
+
request: {
|
|
142
|
+
method: 'POST';
|
|
143
|
+
};
|
|
144
|
+
meta: {
|
|
145
|
+
claims: LicenseClaims;
|
|
146
|
+
status?: LicenseStatus;
|
|
147
|
+
subjectId?: string;
|
|
148
|
+
};
|
|
149
|
+
};
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { DeviceAppTypes, DeviceUserClasses } from '../constants/device.js';
|
|
2
|
+
import { ClaimsIndividualProductSchemaorg, ClaimsOfferSchemaorg, ClaimsPersonSchemaorg, } from '../constants/schemaorg.js';
|
|
3
|
+
export const LicenseClaimContext = Object.freeze({
|
|
4
|
+
SchemaOrg: 'org.schema',
|
|
5
|
+
});
|
|
6
|
+
/**
|
|
7
|
+
* Canonical business categories currently used by GW licensing flows.
|
|
8
|
+
*
|
|
9
|
+
* Mapping:
|
|
10
|
+
* - employee -> professional
|
|
11
|
+
* - individual -> individual
|
|
12
|
+
*/
|
|
13
|
+
export const LicenseCategories = Object.freeze({
|
|
14
|
+
Professional: 'professional',
|
|
15
|
+
Individual: 'individual',
|
|
16
|
+
});
|
|
17
|
+
/**
|
|
18
|
+
* Stable helper-level request type ids for license-oriented batch entries.
|
|
19
|
+
*
|
|
20
|
+
* These are request metadata strings emitted by SDK/common-utils helpers so
|
|
21
|
+
* callers do not handcraft type labels inline.
|
|
22
|
+
*/
|
|
23
|
+
export const LicenseEntryTypes = Object.freeze({
|
|
24
|
+
Issue: 'License-issue-request-v1.0',
|
|
25
|
+
Purchase: 'License-purchase-request-v1.0',
|
|
26
|
+
Search: 'License-search-request-v1.0',
|
|
27
|
+
});
|
|
28
|
+
export const LicenseEntryOperations = Object.freeze({
|
|
29
|
+
Issue: 'IndividualProduct:Issue',
|
|
30
|
+
Purchase: 'IndividualProduct:Purchase',
|
|
31
|
+
Search: 'IndividualProduct:Search',
|
|
32
|
+
});
|
|
33
|
+
export const LicenseRequestMethods = Object.freeze({
|
|
34
|
+
Post: 'POST',
|
|
35
|
+
});
|
|
36
|
+
/**
|
|
37
|
+
* Runtime-facing lifecycle values commonly used when searching stored
|
|
38
|
+
* `DeviceLicense` documents.
|
|
39
|
+
*
|
|
40
|
+
* These are not schema.org claims. They are operational filters that runtime
|
|
41
|
+
* layers may attach alongside the canonical schema.org claims.
|
|
42
|
+
*/
|
|
43
|
+
export const LicenseStatuses = Object.freeze({
|
|
44
|
+
Available: 'available',
|
|
45
|
+
Issued: 'issued',
|
|
46
|
+
Active: 'active',
|
|
47
|
+
Inactive: 'inactive',
|
|
48
|
+
});
|
|
49
|
+
function cloneClaims(claims) {
|
|
50
|
+
return { ...(claims || {}) };
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Maps one canonical runtime user class to the schema.org-compatible
|
|
54
|
+
* `IndividualProduct.category` value used by current GW flows.
|
|
55
|
+
*/
|
|
56
|
+
export function mapLicenseCategoryFromUserClass(userClass = DeviceUserClasses.Employee) {
|
|
57
|
+
return userClass === DeviceUserClasses.Individual
|
|
58
|
+
? LicenseCategories.Individual
|
|
59
|
+
: LicenseCategories.Professional;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Converts a list of seat ids / serial numbers into the compact string form
|
|
63
|
+
* currently stored in `org.schema.Offer.serialNumber`.
|
|
64
|
+
*/
|
|
65
|
+
export function serializeLicenseSerialNumbers(serialNumbers) {
|
|
66
|
+
const normalized = (serialNumbers || [])
|
|
67
|
+
.map((value) => String(value || '').trim())
|
|
68
|
+
.filter(Boolean);
|
|
69
|
+
return normalized.length > 0 ? normalized.join(',') : undefined;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Builds canonical `org.schema.*` claims for `License/_issue`.
|
|
73
|
+
*
|
|
74
|
+
* The resulting payload keeps current GW semantics:
|
|
75
|
+
* - recipient identity/role comes from `Person.*`
|
|
76
|
+
* - seat/app semantics come from `IndividualProduct.*`
|
|
77
|
+
*/
|
|
78
|
+
export function buildLicenseIssueClaims(input) {
|
|
79
|
+
const claims = {
|
|
80
|
+
'@context': LicenseClaimContext.SchemaOrg,
|
|
81
|
+
...cloneClaims(input.additionalClaims),
|
|
82
|
+
[ClaimsPersonSchemaorg.email]: input.email.trim(),
|
|
83
|
+
[ClaimsPersonSchemaorg.hasOccupationalRoleValue]: input.role.trim(),
|
|
84
|
+
[ClaimsIndividualProductSchemaorg.category]: mapLicenseCategoryFromUserClass(input.userClass || DeviceUserClasses.Employee),
|
|
85
|
+
[ClaimsIndividualProductSchemaorg.additionalType]: input.type || DeviceAppTypes.Mobile,
|
|
86
|
+
};
|
|
87
|
+
return claims;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Builds the canonical batch entry for `License/_issue`.
|
|
91
|
+
*/
|
|
92
|
+
export function buildLicenseIssueEntry(input) {
|
|
93
|
+
return {
|
|
94
|
+
type: LicenseEntryTypes.Issue,
|
|
95
|
+
request: { method: LicenseRequestMethods.Post },
|
|
96
|
+
meta: {
|
|
97
|
+
claims: {
|
|
98
|
+
...buildLicenseIssueClaims(input),
|
|
99
|
+
'@type': LicenseEntryOperations.Issue,
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Builds canonical schema.org claims for a license purchase / seat-creation
|
|
106
|
+
* request.
|
|
107
|
+
*
|
|
108
|
+
* Current business semantics:
|
|
109
|
+
* - `Offer.eligibleQuantity.value` requests how many seats must exist
|
|
110
|
+
* - `Offer.serialNumber` can optionally carry the explicit seat ids when they
|
|
111
|
+
* are already known or preallocated
|
|
112
|
+
* - `IndividualProduct.*` classifies the target seat family/form factor
|
|
113
|
+
*/
|
|
114
|
+
export function buildLicensePurchaseClaims(input) {
|
|
115
|
+
const claims = {
|
|
116
|
+
'@context': LicenseClaimContext.SchemaOrg,
|
|
117
|
+
...cloneClaims(input.additionalClaims),
|
|
118
|
+
[ClaimsIndividualProductSchemaorg.category]: mapLicenseCategoryFromUserClass(input.userClass || DeviceUserClasses.Employee),
|
|
119
|
+
[ClaimsIndividualProductSchemaorg.additionalType]: input.type || DeviceAppTypes.Mobile,
|
|
120
|
+
[ClaimsOfferSchemaorg.eligibleQuantityValue]: input.quantity,
|
|
121
|
+
};
|
|
122
|
+
const serializedSerialNumbers = serializeLicenseSerialNumbers(input.serialNumbers);
|
|
123
|
+
if (serializedSerialNumbers) {
|
|
124
|
+
claims[ClaimsOfferSchemaorg.serialNumber] = serializedSerialNumbers;
|
|
125
|
+
}
|
|
126
|
+
return claims;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Builds the canonical batch entry for a purchase/order-oriented license
|
|
130
|
+
* request.
|
|
131
|
+
*/
|
|
132
|
+
export function buildLicensePurchaseEntry(input) {
|
|
133
|
+
return {
|
|
134
|
+
type: LicenseEntryTypes.Purchase,
|
|
135
|
+
request: { method: LicenseRequestMethods.Post },
|
|
136
|
+
meta: {
|
|
137
|
+
claims: {
|
|
138
|
+
...buildLicensePurchaseClaims(input),
|
|
139
|
+
'@type': LicenseEntryOperations.Purchase,
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Builds the canonical search envelope for license listing.
|
|
146
|
+
*
|
|
147
|
+
* Split of concerns:
|
|
148
|
+
* - schema.org-compatible selectors stay in `meta.claims`
|
|
149
|
+
* - document lifecycle stays in `meta.status`, mirroring the current
|
|
150
|
+
* `ConfidentialStorageDoc.status` usage
|
|
151
|
+
* - `subjectId` remains an explicit side-field until a canonical indexed claim
|
|
152
|
+
* is introduced for that lookup
|
|
153
|
+
*/
|
|
154
|
+
export function buildLicenseSearchEntry(input) {
|
|
155
|
+
const claims = {
|
|
156
|
+
'@context': LicenseClaimContext.SchemaOrg,
|
|
157
|
+
...cloneClaims(input.additionalClaims),
|
|
158
|
+
};
|
|
159
|
+
if (input.serialNumbers && input.serialNumbers.length > 0) {
|
|
160
|
+
claims[ClaimsOfferSchemaorg.serialNumber] = serializeLicenseSerialNumbers(input.serialNumbers);
|
|
161
|
+
}
|
|
162
|
+
if (input.userClass) {
|
|
163
|
+
claims[ClaimsIndividualProductSchemaorg.category] = mapLicenseCategoryFromUserClass(input.userClass);
|
|
164
|
+
}
|
|
165
|
+
if (input.type) {
|
|
166
|
+
claims[ClaimsIndividualProductSchemaorg.additionalType] = input.type;
|
|
167
|
+
}
|
|
168
|
+
if (typeof input.email === 'string' && input.email.trim()) {
|
|
169
|
+
claims[ClaimsPersonSchemaorg.email] = input.email.trim();
|
|
170
|
+
}
|
|
171
|
+
if (typeof input.role === 'string' && input.role.trim()) {
|
|
172
|
+
claims[ClaimsPersonSchemaorg.hasOccupationalRoleValue] = input.role.trim();
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
type: LicenseEntryTypes.Search,
|
|
176
|
+
request: { method: LicenseRequestMethods.Post },
|
|
177
|
+
meta: {
|
|
178
|
+
claims: {
|
|
179
|
+
...claims,
|
|
180
|
+
'@type': LicenseEntryOperations.Search,
|
|
181
|
+
},
|
|
182
|
+
...(input.status ? { status: input.status } : {}),
|
|
183
|
+
...(typeof input.subjectId === 'string' && input.subjectId.trim()
|
|
184
|
+
? { subjectId: input.subjectId.trim() }
|
|
185
|
+
: {}),
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const HL7_ACT_REASON_CODE_SYSTEM = "http://terminology.hl7.org/CodeSystem/v3-ActReason";
|
|
2
|
+
export type ServiceActReasonCoding = Readonly<{
|
|
3
|
+
system: string;
|
|
4
|
+
code: string;
|
|
5
|
+
}>;
|
|
6
|
+
/**
|
|
7
|
+
* Parses the compact CSV form used by flat GDC claims for `Service.additionalType`.
|
|
8
|
+
*
|
|
9
|
+
* Accepted examples:
|
|
10
|
+
* - `http://terminology.hl7.org/CodeSystem/v3-ActReason|METAMGT,HRESCH`
|
|
11
|
+
* - `http://terminology.hl7.org/CodeSystem/v3-ActReason|METAMGT,http://terminology.hl7.org/CodeSystem/v3-ActReason|HRESCH`
|
|
12
|
+
*/
|
|
13
|
+
export declare function parseServiceActReasonCodings(value: unknown): ServiceActReasonCoding[];
|
|
14
|
+
export declare function parseServiceActReasonCodes(value: unknown): string[];
|
|
15
|
+
export declare function serializeServiceActReasonCodings(values: ReadonlyArray<ServiceActReasonCoding | undefined | null>): string | undefined;
|
|
16
|
+
export declare function serializeServiceActReasonCodes(codes: ReadonlyArray<string | undefined | null>, system?: string): string | undefined;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
|
|
2
|
+
export const HL7_ACT_REASON_CODE_SYSTEM = 'http://terminology.hl7.org/CodeSystem/v3-ActReason';
|
|
3
|
+
function normalizeText(value) {
|
|
4
|
+
return typeof value === 'string' ? value.trim() : '';
|
|
5
|
+
}
|
|
6
|
+
function normalizeCoding(input) {
|
|
7
|
+
const system = normalizeText(input?.system);
|
|
8
|
+
const code = normalizeText(input?.code).toUpperCase();
|
|
9
|
+
if (!system || !code)
|
|
10
|
+
return undefined;
|
|
11
|
+
return { system, code };
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Parses the compact CSV form used by flat GDC claims for `Service.additionalType`.
|
|
15
|
+
*
|
|
16
|
+
* Accepted examples:
|
|
17
|
+
* - `http://terminology.hl7.org/CodeSystem/v3-ActReason|METAMGT,HRESCH`
|
|
18
|
+
* - `http://terminology.hl7.org/CodeSystem/v3-ActReason|METAMGT,http://terminology.hl7.org/CodeSystem/v3-ActReason|HRESCH`
|
|
19
|
+
*/
|
|
20
|
+
export function parseServiceActReasonCodings(value) {
|
|
21
|
+
const raw = normalizeText(value);
|
|
22
|
+
if (!raw)
|
|
23
|
+
return [];
|
|
24
|
+
let currentSystem = '';
|
|
25
|
+
const codings = [];
|
|
26
|
+
for (const token of raw.split(',')) {
|
|
27
|
+
const normalizedToken = normalizeText(token);
|
|
28
|
+
if (!normalizedToken)
|
|
29
|
+
continue;
|
|
30
|
+
const pipeIndex = normalizedToken.indexOf('|');
|
|
31
|
+
if (pipeIndex >= 0) {
|
|
32
|
+
currentSystem = normalizeText(normalizedToken.slice(0, pipeIndex));
|
|
33
|
+
const coding = normalizeCoding({
|
|
34
|
+
system: currentSystem,
|
|
35
|
+
code: normalizedToken.slice(pipeIndex + 1),
|
|
36
|
+
});
|
|
37
|
+
if (coding)
|
|
38
|
+
codings.push(coding);
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const coding = normalizeCoding({
|
|
42
|
+
system: currentSystem,
|
|
43
|
+
code: normalizedToken,
|
|
44
|
+
});
|
|
45
|
+
if (coding)
|
|
46
|
+
codings.push(coding);
|
|
47
|
+
}
|
|
48
|
+
return Array.from(new Map(codings.map((coding) => [`${coding.system}|${coding.code}`, coding])).values());
|
|
49
|
+
}
|
|
50
|
+
export function parseServiceActReasonCodes(value) {
|
|
51
|
+
return parseServiceActReasonCodings(value).map((coding) => coding.code);
|
|
52
|
+
}
|
|
53
|
+
export function serializeServiceActReasonCodings(values) {
|
|
54
|
+
const normalized = values
|
|
55
|
+
.map((value) => normalizeCoding(value || undefined))
|
|
56
|
+
.filter((value) => Boolean(value));
|
|
57
|
+
if (!normalized.length)
|
|
58
|
+
return undefined;
|
|
59
|
+
const unique = Array.from(new Map(normalized.map((coding) => [`${coding.system}|${coding.code}`, coding])).values());
|
|
60
|
+
const firstSystem = unique[0]?.system || '';
|
|
61
|
+
if (firstSystem && unique.every((coding) => coding.system === firstSystem)) {
|
|
62
|
+
return `${firstSystem}|${unique.map((coding) => coding.code).join(',')}`;
|
|
63
|
+
}
|
|
64
|
+
return unique.map((coding) => `${coding.system}|${coding.code}`).join(',');
|
|
65
|
+
}
|
|
66
|
+
export function serializeServiceActReasonCodes(codes, system = HL7_ACT_REASON_CODE_SYSTEM) {
|
|
67
|
+
return serializeServiceActReasonCodings(codes.map((code) => ({ system, code: normalizeText(code).toUpperCase() })));
|
|
68
|
+
}
|