gdc-common-utils-ts 1.0.4 → 1.0.7
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/AesManager.d.ts +27 -0
- package/dist/AesManager.js +62 -0
- package/dist/CryptographyService.d.ts +76 -0
- package/dist/CryptographyService.js +403 -0
- package/dist/constants/Schemas.d.ts +45 -0
- package/dist/constants/Schemas.js +48 -0
- package/dist/constants/index.js +1 -0
- package/{src/constants/schemaorg.ts → dist/constants/schemaorg.d.ts} +24 -116
- package/dist/constants/schemaorg.js +185 -0
- package/dist/cryptoDecode.d.ts +3 -0
- package/dist/cryptoDecode.js +90 -0
- package/dist/cryptoEncode.d.ts +1 -0
- package/dist/cryptoEncode.js +30 -0
- package/dist/cryptography.abstract.d.ts +13 -0
- package/{src/cryptography.abstract.ts → dist/cryptography.abstract.js} +6 -14
- package/dist/hmac.d.ts +2 -0
- package/{src/hmac.ts → dist/hmac.js} +4 -7
- package/dist/index.js +3 -0
- package/{src/interfaces/Cryptography.types.ts → dist/interfaces/Cryptography.types.d.ts} +71 -71
- package/dist/interfaces/Cryptography.types.js +8 -0
- package/dist/interfaces/ICryptoHelper.d.ts +28 -0
- package/dist/interfaces/ICryptoHelper.js +3 -0
- package/dist/interfaces/ICryptography.d.ts +154 -0
- package/dist/interfaces/ICryptography.js +3 -0
- package/dist/interfaces/IWallet.d.ts +55 -0
- package/dist/interfaces/IWallet.js +3 -0
- package/dist/interfaces/MlDsa.d.ts +9 -0
- package/{src/interfaces/MlDsa.ts → dist/interfaces/MlDsa.js} +1 -5
- package/dist/interfaces/MlKem.d.ts +11 -0
- package/{src/interfaces/MlKem.ts → dist/interfaces/MlKem.js} +0 -5
- package/dist/models/aes.d.ts +85 -0
- package/dist/models/aes.js +10 -0
- package/dist/models/auth.d.ts +35 -0
- package/dist/models/auth.js +3 -0
- package/{src/models/bundle.ts → dist/models/bundle.d.ts} +41 -63
- package/dist/models/bundle.js +26 -0
- package/dist/models/clinical-sections.d.ts +36 -0
- package/dist/models/clinical-sections.en.d.ts +75 -0
- package/dist/models/clinical-sections.en.js +81 -0
- package/dist/models/clinical-sections.js +32 -0
- package/dist/models/comm.d.ts +44 -0
- package/dist/models/comm.js +4 -0
- package/{src/models/confidential-job.ts → dist/models/confidential-job.d.ts} +23 -45
- package/dist/models/confidential-job.js +20 -0
- package/dist/models/confidential-message.d.ts +97 -0
- package/dist/models/confidential-message.js +4 -0
- package/{src/models/confidential-storage.ts → dist/models/confidential-storage.d.ts} +35 -56
- package/dist/models/confidential-storage.js +3 -0
- package/{src/models/consent-rule.ts → dist/models/consent-rule.d.ts} +22 -42
- package/dist/models/consent-rule.js +21 -0
- package/{src/models/crypto.ts → dist/models/crypto.d.ts} +5 -13
- package/dist/models/crypto.js +3 -0
- package/dist/models/device-license.d.ts +133 -0
- package/dist/models/device-license.js +3 -0
- package/{src/models/did.ts → dist/models/did.d.ts} +21 -30
- package/dist/models/did.js +3 -0
- package/dist/models/index.js +31 -0
- package/dist/models/indexing.d.ts +11 -0
- package/dist/models/indexing.js +18 -0
- package/dist/models/issue.d.ts +57 -0
- package/dist/models/issue.js +75 -0
- package/dist/models/jsonapi.d.ts +13 -0
- package/dist/models/jsonapi.js +3 -0
- package/{src/models/jwe.ts → dist/models/jwe.d.ts} +10 -22
- package/dist/models/jwe.js +3 -0
- package/{src/models/jwk.ts → dist/models/jwk.d.ts} +0 -11
- package/dist/models/jwk.js +3 -0
- package/{src/models/jws.ts → dist/models/jws.d.ts} +0 -7
- package/dist/models/jws.js +3 -0
- package/dist/models/jwt.d.ts +9 -0
- package/dist/models/jwt.js +3 -0
- package/dist/models/multibase58.d.ts +13 -0
- package/dist/models/multibase58.js +40 -0
- package/dist/models/oidc4ida.common.model.d.ts +33 -0
- package/dist/models/oidc4ida.common.model.js +3 -0
- package/dist/models/oidc4ida.document.model.d.ts +50 -0
- package/dist/models/oidc4ida.document.model.js +3 -0
- package/{src/models/oidc4ida.electronicRecord.model.ts → dist/models/oidc4ida.electronicRecord.model.d.ts} +18 -37
- package/dist/models/oidc4ida.electronicRecord.model.js +3 -0
- package/{src/models/oidc4ida.evidence.model.ts → dist/models/oidc4ida.evidence.model.d.ts} +17 -35
- package/dist/models/oidc4ida.evidence.model.js +5 -0
- package/dist/models/openid-device.d.ts +119 -0
- package/dist/models/openid-device.js +3 -0
- package/dist/models/operation-outcome.d.ts +26 -0
- package/dist/models/operation-outcome.js +3 -0
- package/{src/models/params.ts → dist/models/params.d.ts} +20 -29
- package/dist/models/params.js +3 -0
- package/dist/models/resource-document.d.ts +14 -0
- package/dist/models/resource-document.js +3 -0
- package/dist/models/response.d.ts +1 -0
- package/dist/models/response.js +3 -0
- package/dist/models/urlPath.d.ts +58 -0
- package/dist/models/urlPath.js +76 -0
- package/dist/models/verifiable-credential.d.ts +45 -0
- package/dist/models/verifiable-credential.js +8 -0
- package/dist/utils/actor.d.ts +18 -0
- package/dist/utils/actor.js +36 -0
- package/dist/utils/base-convert.d.ts +20 -0
- package/{src/utils/base-convert.ts → dist/utils/base-convert.js} +23 -36
- package/dist/utils/baseN.d.ts +35 -0
- package/dist/utils/baseN.js +174 -0
- package/dist/utils/bundle.d.ts +6 -0
- package/dist/utils/bundle.js +32 -0
- package/dist/utils/content.d.ts +55 -0
- package/{src/utils/content.ts → dist/utils/content.js} +4 -10
- package/dist/utils/did.d.ts +67 -0
- package/dist/utils/did.js +123 -0
- package/dist/utils/format-converter.d.ts +21 -0
- package/dist/utils/format-converter.js +109 -0
- package/dist/utils/index.js +13 -0
- package/dist/utils/jwt.d.ts +52 -0
- package/dist/utils/jwt.js +153 -0
- package/dist/utils/manager-error.d.ts +15 -0
- package/dist/utils/manager-error.js +23 -0
- package/dist/utils/multibase58.d.ts +13 -0
- package/dist/utils/multibase58.js +40 -0
- package/dist/utils/multibasehash.d.ts +8 -0
- package/{src/utils/multibasehash.ts → dist/utils/multibasehash.js} +8 -13
- package/dist/utils/normalize.d.ts +16 -0
- package/{src/utils/normalize.ts → dist/utils/normalize.js} +15 -18
- package/dist/utils/object-convert.d.ts +20 -0
- package/{src/utils/object-convert.ts → dist/utils/object-convert.js} +10 -16
- package/dist/utils/string-convert.d.ts +24 -0
- package/{src/utils/string-convert.ts → dist/utils/string-convert.js} +5 -14
- package/dist/utils/string-utils.d.ts +25 -0
- package/{src/utils/string-utils.ts → dist/utils/string-utils.js} +12 -16
- package/dist/utils/url.d.ts +27 -0
- package/{src/utils/url.ts → dist/utils/url.js} +6 -7
- package/package.json +56 -14
- package/PUBLISHING.md +0 -33
- package/__tests__/AesManager.test.ts +0 -53
- package/__tests__/CryptographyService.test.ts +0 -194
- package/__tests__/bundle.test.ts +0 -29
- package/__tests__/content.test.ts +0 -72
- package/__tests__/crypto-encode-decode.test.ts +0 -52
- package/__tests__/crypto-hmac.test.ts +0 -21
- package/__tests__/did-generateServiceId.errors.test.ts +0 -8
- package/__tests__/did-generateServiceId.test.ts +0 -18
- package/__tests__/models-clinical-sections.test.ts +0 -32
- package/__tests__/models-multibase58.test.ts +0 -33
- package/__tests__/multibase58.errors.test.ts +0 -7
- package/__tests__/multibase58.test.ts +0 -28
- package/__tests__/multibasehash.test.ts +0 -25
- package/__tests__/utils-actor.test.ts +0 -46
- package/__tests__/utils-base-convert.test.ts +0 -57
- package/__tests__/utils-baseN.test.ts +0 -40
- package/__tests__/utils-did-extra.test.ts +0 -33
- package/__tests__/utils-format-converter.test.ts +0 -87
- package/__tests__/utils-jwt.test.ts +0 -57
- package/__tests__/utils-manager-error.test.ts +0 -11
- package/__tests__/utils-normalize.test.ts +0 -15
- package/__tests__/utils-object-convert.test.ts +0 -38
- package/__tests__/utils-string-convert.test.ts +0 -20
- package/__tests__/utils-string-utils.test.ts +0 -25
- package/__tests__/utils-url.test.ts +0 -21
- package/babel.config.cjs +0 -5
- package/jest.config.ts +0 -47
- package/src/AesManager.ts +0 -82
- package/src/CryptographyService.ts +0 -461
- package/src/JweManager.ts.txt +0 -365
- package/src/KmsService.txt +0 -493
- package/src/constants/Schemas.ts +0 -61
- package/src/cryptoDecode.ts +0 -104
- package/src/cryptoEncode.ts +0 -36
- package/src/interfaces/ICryptoHelper.ts +0 -33
- package/src/interfaces/ICryptography.ts +0 -177
- package/src/interfaces/IWallet.ts +0 -62
- package/src/models/aes.ts +0 -93
- package/src/models/auth.ts +0 -38
- package/src/models/bundle.txt +0 -93
- package/src/models/clinical-sections.en.ts +0 -82
- package/src/models/clinical-sections.ts +0 -64
- package/src/models/comm.ts +0 -63
- package/src/models/confidential-message.ts +0 -137
- package/src/models/device-license.ts +0 -161
- package/src/models/indexing.ts +0 -20
- package/src/models/issue.ts +0 -85
- package/src/models/jsonapi.ts +0 -19
- package/src/models/jwt.ts +0 -15
- package/src/models/multibase58.ts +0 -46
- package/src/models/oidc4ida.common.model.ts +0 -39
- package/src/models/oidc4ida.document.model.ts +0 -61
- package/src/models/openid-device.ts +0 -146
- package/src/models/operation-outcome.ts +0 -34
- package/src/models/resource-document.ts +0 -21
- package/src/models/response.ts +0 -5
- package/src/models/urlPath.ts +0 -76
- package/src/models/verifiable-credential.ts +0 -52
- package/src/types/noble-hashes.d.ts +0 -4
- package/src/utils/actor.ts +0 -56
- package/src/utils/baseN.ts +0 -203
- package/src/utils/bundle.ts +0 -30
- package/src/utils/did.ts +0 -155
- package/src/utils/format-converter.ts +0 -119
- package/src/utils/jwt.ts +0 -165
- package/src/utils/manager-error.ts +0 -27
- package/src/utils/multibase58.ts +0 -46
- package/tsconfig.json +0 -15
- /package/{src/constants/index.ts → dist/constants/index.d.ts} +0 -0
- /package/{src/index.ts → dist/index.d.ts} +0 -0
- /package/{src/models/index.ts → dist/models/index.d.ts} +0 -0
- /package/{src/utils/index.ts → dist/utils/index.d.ts} +0 -0
package/src/utils/bundle.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
// Copyright 2025 Antifraud Services Inc. under the Apache License, Version 2.0.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Normalizes either FHIR Bundle (entry[]) or JSON:API bundle (data[])
|
|
5
|
-
* into an array of resources.
|
|
6
|
-
*/
|
|
7
|
-
export function extractResources(bundle: any): any[] {
|
|
8
|
-
if (!bundle) return [];
|
|
9
|
-
if (Array.isArray(bundle.entry)) {
|
|
10
|
-
return bundle.entry
|
|
11
|
-
.map((e: any) => e && (e.resource || e))
|
|
12
|
-
.filter(Boolean);
|
|
13
|
-
}
|
|
14
|
-
if (Array.isArray(bundle.data)) {
|
|
15
|
-
return bundle.data
|
|
16
|
-
.map((d: any) => d && (d.resource || d))
|
|
17
|
-
.filter(Boolean);
|
|
18
|
-
}
|
|
19
|
-
if (bundle.resourceType) return [bundle];
|
|
20
|
-
return [];
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function getNextLink(bundle: any): string | null {
|
|
24
|
-
if (Array.isArray(bundle?.link)) {
|
|
25
|
-
const next = bundle.link.find((l: any) => l.relation === 'next');
|
|
26
|
-
if (next?.url) return next.url;
|
|
27
|
-
}
|
|
28
|
-
if (bundle?.links?.next) return bundle.links.next;
|
|
29
|
-
return null;
|
|
30
|
-
}
|
package/src/utils/did.ts
DELETED
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
// crypto-ts/utils/did.ts
|
|
2
|
-
// Copyright 2025 Antifraud Services Inc. under the Apache License, Version 2.0.
|
|
3
|
-
|
|
4
|
-
import { ServiceEndpointSelector } from "../models/did";
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Generates a DID Service ID fragment from a selector object.
|
|
8
|
-
* The format is always `#<section>:<format>:<resourceType>:<action>`.
|
|
9
|
-
*
|
|
10
|
-
* This utility's only job is to correctly assemble the string. It contains no
|
|
11
|
-
* conditional logic about DID types, as that is handled by the data layer.
|
|
12
|
-
*
|
|
13
|
-
* @param selector The structured object containing the endpoint parts.
|
|
14
|
-
* @returns The formatted service ID fragment string.
|
|
15
|
-
*/
|
|
16
|
-
export function generateServiceId(selector: ServiceEndpointSelector): string {
|
|
17
|
-
// Canonical casing:
|
|
18
|
-
// - `section`, `format`, `resourceType` are matched case-insensitively by the backend router,
|
|
19
|
-
// and lowercasing them makes DID Document lookup deterministic across SDKs.
|
|
20
|
-
// - `action` is kept as-is (future actions may be case-sensitive identifiers).
|
|
21
|
-
const parts = [
|
|
22
|
-
selector.section?.toLowerCase(),
|
|
23
|
-
selector.format?.toLowerCase(),
|
|
24
|
-
selector.resourceType?.toLowerCase(),
|
|
25
|
-
selector.action,
|
|
26
|
-
];
|
|
27
|
-
|
|
28
|
-
return `#${parts.filter(p => p).join(':')}`;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Normalizes a did:web string to a canonical format to prevent resolution errors
|
|
33
|
-
* due to case sensitivity in the path component of the underlying URL.
|
|
34
|
-
*
|
|
35
|
-
* The rule is:
|
|
36
|
-
* - All segments are lowercased, EXCEPT the final segment.
|
|
37
|
-
* - If the final segment represents a `system|code` pair (e.g., for a role),
|
|
38
|
-
* the `system` part is lowercased, but the `code` is preserved as-is.
|
|
39
|
-
* - If the final segment is a unique identifier (like a Tax ID), it is preserved as-is.
|
|
40
|
-
*
|
|
41
|
-
* @param did The did:web string to normalize.
|
|
42
|
-
* @returns The canonicalized did:web string.
|
|
43
|
-
*/
|
|
44
|
-
export function normalizeDidWeb(did: string): string {
|
|
45
|
-
const parts = did.split(':');
|
|
46
|
-
if (parts[0] !== 'did' || parts[1] !== 'web' || parts.length < 3) {
|
|
47
|
-
// Not a valid did:web, return as is.
|
|
48
|
-
return did;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Lowercase all parts except the very last one.
|
|
52
|
-
const lowercasedParts = parts.slice(0, -1).map(part => part.toLowerCase());
|
|
53
|
-
let lastPart = parts[parts.length - 1];
|
|
54
|
-
|
|
55
|
-
// Special handling for the last part if it contains a role descriptor.
|
|
56
|
-
if (lastPart.includes('|')) {
|
|
57
|
-
const [system, ...codeParts] = lastPart.split('|');
|
|
58
|
-
const code = codeParts.join('|'); // Re-join in case the code itself has a pipe.
|
|
59
|
-
lastPart = `${system.toLowerCase()}|${code}`;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return [...lowercasedParts, lastPart].join(':');
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Encodes a hostname according to did:web spec (percent-encodes port colons).
|
|
67
|
-
* @param apiUrl The full base URL of the API.
|
|
68
|
-
* @returns The percent-encoded hostname.
|
|
69
|
-
*/
|
|
70
|
-
function getEncodedHost(apiUrl: string): string {
|
|
71
|
-
try {
|
|
72
|
-
const parsedUrl = new URL(apiUrl);
|
|
73
|
-
return parsedUrl.host.replace(':', '%3A');
|
|
74
|
-
} catch (e) {
|
|
75
|
-
console.error(`[getEncodedHost] Invalid apiUrl provided: ${apiUrl}`);
|
|
76
|
-
return 'localhost'; // Fallback
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Creates the deterministic "hosted" did:web for a tenant (Organization).
|
|
82
|
-
*
|
|
83
|
-
* @param hostDidWeb The DID of the host (e.g., 'did:web:host.example.com').
|
|
84
|
-
* @param tenantAlternateName The alternate name of the tenant (e.g., 'acme').
|
|
85
|
-
* @param context An object containing jurisdiction, version, and sector.
|
|
86
|
-
* @returns The tenant's full, correctly formatted hosted did:web.
|
|
87
|
-
* Example: 'did:web:host.example.com:acme:cds-es:v1:health-care'
|
|
88
|
-
*/
|
|
89
|
-
export function createHostedDidWeb(
|
|
90
|
-
hostDidWeb: string,
|
|
91
|
-
tenantAlternateName: string,
|
|
92
|
-
context: { jurisdiction: string; version: string; sector: string }
|
|
93
|
-
): string {
|
|
94
|
-
const hostPart = hostDidWeb.replace(/^did:web:/, '');
|
|
95
|
-
// The path in a did:web uses colons as separators.
|
|
96
|
-
const didPath = `cds-${context.jurisdiction}:${context.version}:${context.sector}`;
|
|
97
|
-
return `did:web:${hostPart}:${tenantAlternateName}:${didPath}`;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Builds the canonical details (URL and did:web URN) for a hosted DID.
|
|
103
|
-
* This is the single source of truth for constructing hosted identifiers in the app.
|
|
104
|
-
*
|
|
105
|
-
* @param options An object with the components of the DID.
|
|
106
|
-
* @param options.host The provider's domain (e.g., 'provider.com').
|
|
107
|
-
* @param options.alternateName The tenant's identifier (e.g., 'acme').
|
|
108
|
-
* @param options.jurisdiction The legal jurisdiction (defaults to 'ES').
|
|
109
|
-
* @param options.sector The business sector (defaults to 'health-care').
|
|
110
|
-
* @returns An object with the full URL (with trailing /) and the canonical did:web.
|
|
111
|
-
*/
|
|
112
|
-
export function buildHostedDidDetails({
|
|
113
|
-
host,
|
|
114
|
-
alternateName,
|
|
115
|
-
jurisdiction = 'ES',
|
|
116
|
-
sector = 'health-care',
|
|
117
|
-
}: {
|
|
118
|
-
host: string;
|
|
119
|
-
alternateName: string;
|
|
120
|
-
jurisdiction?: string;
|
|
121
|
-
sector?: string;
|
|
122
|
-
}) {
|
|
123
|
-
// 1. Build the path part of the DID/URL.
|
|
124
|
-
const pathPart = `${alternateName}/cds-${jurisdiction}/v1/${sector}`;
|
|
125
|
-
|
|
126
|
-
// 2. Build the full URL, ensuring a trailing slash.
|
|
127
|
-
const url = `https://${host}/${pathPart}/`;
|
|
128
|
-
|
|
129
|
-
// 3. Build the canonical did:web, replacing / with :.
|
|
130
|
-
const hostAndPath = `${host}/${pathPart}`;
|
|
131
|
-
const did = `did:web:${hostAndPath.replace(/\//g, ':')}`;
|
|
132
|
-
|
|
133
|
-
return { did, url };
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Converts a did:web identifier into a full HTTPS or HTTP base URL with a trailing slash.
|
|
138
|
-
* It correctly decodes percent-encoded ports for local development.
|
|
139
|
-
* @param did The did:web string (e.g., 'did:web:example.com' or 'did:web:localhost%3A3000:acme:cds-es:v1:health-care').
|
|
140
|
-
* @returns The full base URL (e.g., 'https://example.com/acme/cds-es/v1/health-care/').
|
|
141
|
-
*/
|
|
142
|
-
export function getBaseUrlFromDidWeb(did: string): string {
|
|
143
|
-
const didParts = did.replace(/^did:web:/, '').split(':');
|
|
144
|
-
const domainPart = didParts[0];
|
|
145
|
-
const pathParts = didParts.slice(1);
|
|
146
|
-
|
|
147
|
-
const decodedDomain = decodeURIComponent(domainPart);
|
|
148
|
-
const protocol = decodedDomain.startsWith('localhost') ? 'http' : 'https';
|
|
149
|
-
|
|
150
|
-
const path = pathParts.join('/').replace(/cds-(es|us|gb)/, (match, p1) => `cds-${p1.toUpperCase()}`);
|
|
151
|
-
|
|
152
|
-
// Ensure a trailing slash for the base URL, without double slashes when no path is present.
|
|
153
|
-
const normalizedPath = path ? `${path}/` : '';
|
|
154
|
-
return `${protocol}://${decodedDomain}/${normalizedPath}`;
|
|
155
|
-
}
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
// crypto-ts/utils/format-converter.ts
|
|
2
|
-
// Copyright 2025 Antifraud Services Inc. under the Apache License, Version 2.0.
|
|
3
|
-
|
|
4
|
-
import { safelyJoinUrl } from "./url";
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Normalizes a FHIR resource or Bundle into an array of entries.
|
|
8
|
-
*/
|
|
9
|
-
export const convertResourceDataToArrayOfDataEntries = (inputData: any, requestPath: string, webDomain: string): any[] => {
|
|
10
|
-
if (inputData.resourceType) { // It is FHIR data
|
|
11
|
-
if (inputData.resourceType === 'Bundle') {
|
|
12
|
-
return inputData.entry || [];
|
|
13
|
-
} else {
|
|
14
|
-
const resourceIdentifier = inputData.id || (inputData.identifier && inputData.identifier[0]?.value) || "";
|
|
15
|
-
const fullUrl = safelyJoinUrl(webDomain, safelyJoinUrl(requestPath, resourceIdentifier));
|
|
16
|
-
return [{ fullUrl, resource: inputData }];
|
|
17
|
-
}
|
|
18
|
-
} else { // Assume it's already a JSON:API-like object
|
|
19
|
-
const resourceIdentifier = inputData.id || "";
|
|
20
|
-
// const fullUrl = safelyJoinUrl(webDomain, safelyJoinUrl(requestPath, resourceIdentifier));
|
|
21
|
-
return [inputData];
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Converts a resource or a FHIR Bundle to a JSON:API Primary Document.
|
|
27
|
-
*/
|
|
28
|
-
export const convertResourceOrBundleToPrimaryDoc = (resourceData: any, specification: string, webDomain: string, requestPath: string): any => {
|
|
29
|
-
const entries = convertResourceDataToArrayOfDataEntries(resourceData, requestPath, webDomain);
|
|
30
|
-
|
|
31
|
-
// Handle FHIR entry structure vs. JSON:API data structure
|
|
32
|
-
const data = entries.map(entry => {
|
|
33
|
-
if (entry.resource) { // It's a FHIR entry
|
|
34
|
-
return {
|
|
35
|
-
type: `${specification}.${entry.resource.resourceType}`,
|
|
36
|
-
id: entry.resource.id,
|
|
37
|
-
attributes: { ...entry.resource }
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
return entry; // Assumes it's already a JSON:API resource object
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
return { data };
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Converts a JSON:API Primary Document back to a FHIR Bundle.
|
|
48
|
-
*/
|
|
49
|
-
export const convertPrimaryDocToBundleFHIR = (primaryDocument: any, bundleType: string): any => {
|
|
50
|
-
const entries: any[] = [];
|
|
51
|
-
if (primaryDocument.data) {
|
|
52
|
-
entries.push(...primaryDocument.data.map((jsonApiResourceObject: any) => ({
|
|
53
|
-
// fullUrl might need to be reconstructed based on context
|
|
54
|
-
resource: jsonApiResourceObject.attributes || jsonApiResourceObject
|
|
55
|
-
})));
|
|
56
|
-
}
|
|
57
|
-
if (primaryDocument.errors) {
|
|
58
|
-
entries.push(...primaryDocument.errors.map((errorObject: any) => ({
|
|
59
|
-
resource: {
|
|
60
|
-
resourceType: 'OperationOutcome',
|
|
61
|
-
id: errorObject.id,
|
|
62
|
-
issue: [{
|
|
63
|
-
code: errorObject.status,
|
|
64
|
-
severity: 'error',
|
|
65
|
-
details: { text: errorObject.detail },
|
|
66
|
-
}]
|
|
67
|
-
}
|
|
68
|
-
})));
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return {
|
|
72
|
-
entry: entries,
|
|
73
|
-
resourceType: 'Bundle',
|
|
74
|
-
total: primaryDocument.data ? primaryDocument.data.length : 0,
|
|
75
|
-
type: bundleType
|
|
76
|
-
};
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Converts a FHIR Bundle containing one or more OperationOutcome entries into a
|
|
82
|
-
* compliant JSON:API Error Document. Each error entry in the bundle is mapped
|
|
83
|
-
* to a corresponding error object in the JSON:API `errors` array.
|
|
84
|
-
*
|
|
85
|
-
* @param errorBundle The FHIR Bundle representing the error(s).
|
|
86
|
-
* @returns A JSON:API document with a top-level `errors` array.
|
|
87
|
-
*/
|
|
88
|
-
export const convertFhirErrorBundleToJsonApiError = (errorBundle: any): any => {
|
|
89
|
-
if (!errorBundle.entry || errorBundle.entry.length === 0) {
|
|
90
|
-
return {
|
|
91
|
-
errors: [{
|
|
92
|
-
status: '500',
|
|
93
|
-
title: 'Unknown Error',
|
|
94
|
-
detail: 'An unspecified error occurred and the error bundle was malformed or empty.'
|
|
95
|
-
}]
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const errorObjects = errorBundle.entry.map((entry: any) => {
|
|
100
|
-
const resource = entry.resource || {};
|
|
101
|
-
const issue = resource.issue ? resource.issue[0] : {};
|
|
102
|
-
const title = issue.details?.text || 'Processing Error';
|
|
103
|
-
|
|
104
|
-
return {
|
|
105
|
-
id: resource.id,
|
|
106
|
-
status: entry.response?.status?.toString() || '500',
|
|
107
|
-
code: issue.code || 'processing-error',
|
|
108
|
-
title: title,
|
|
109
|
-
detail: issue.diagnostics || 'An error occurred while processing the request.',
|
|
110
|
-
meta: {
|
|
111
|
-
severity: issue.severity || 'error'
|
|
112
|
-
}
|
|
113
|
-
};
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
return {
|
|
117
|
-
errors: errorObjects
|
|
118
|
-
};
|
|
119
|
-
};
|
package/src/utils/jwt.ts
DELETED
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
// crypto-ts/utils/jwt.ts
|
|
2
|
-
// Copyright 2025 Antifraud Services Inc. under the Apache License, Version 2.0.
|
|
3
|
-
|
|
4
|
-
// Use `import * as pako` to ensure compatibility with CommonJS/ESM module resolution.
|
|
5
|
-
// This resolves a stubborn TypeScript error (`esModuleInterop`) during testing.
|
|
6
|
-
import * as pako from 'pako';
|
|
7
|
-
import { Content } from './content';
|
|
8
|
-
import { DataCompactJWT, JwtCompactParts } from '../models/jwt';
|
|
9
|
-
|
|
10
|
-
// --- JWT Parsing and Decoding ---
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Splits a compact JWT string into its three parts.
|
|
14
|
-
* @param compactToken The compact JWT string.
|
|
15
|
-
* @returns A PartsJWT object or undefined if the format is invalid.
|
|
16
|
-
*/
|
|
17
|
-
export function getPartsJWT(compactToken: string | undefined): JwtCompactParts | undefined {
|
|
18
|
-
if (!compactToken) {
|
|
19
|
-
return undefined;
|
|
20
|
-
}
|
|
21
|
-
const parts = compactToken.split('.');
|
|
22
|
-
if (parts.length !== 3) {
|
|
23
|
-
return undefined;
|
|
24
|
-
}
|
|
25
|
-
return {
|
|
26
|
-
protected: parts[0],
|
|
27
|
-
payload: parts[1],
|
|
28
|
-
signature: parts[2],
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Decodes the Base64Url header of a JWT into a JSON object.
|
|
34
|
-
* @param headerB64Url The Base64Url-encoded header string.
|
|
35
|
-
* @returns A JSON object representing the header claims.
|
|
36
|
-
*/
|
|
37
|
-
export function decodeHeader(headerB64Url: string): any {
|
|
38
|
-
try {
|
|
39
|
-
const headerBytes = Content.base64ToBytes(headerB64Url);
|
|
40
|
-
const headerString = Content.bytesToStringASCII(headerBytes);
|
|
41
|
-
return JSON.parse(headerString);
|
|
42
|
-
} catch (e) {
|
|
43
|
-
console.error(`Cannot decode JWT header: ${e}`);
|
|
44
|
-
return {};
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Decodes the payload of a JWT, decompressing it if necessary.
|
|
50
|
-
* @param payloadB64Url The Base64Url-encoded payload string.
|
|
51
|
-
* @param isDeflated True if the payload is compressed with DEFLATE.
|
|
52
|
-
* @returns The decoded payload as a JSON object.
|
|
53
|
-
*/
|
|
54
|
-
export async function decodePayload(payloadB64Url: string, isDeflated?: boolean): Promise<object> {
|
|
55
|
-
try {
|
|
56
|
-
let payloadBytes = Content.base64ToBytes(payloadB64Url);
|
|
57
|
-
if (isDeflated) {
|
|
58
|
-
payloadBytes = pako.inflate(payloadBytes);
|
|
59
|
-
}
|
|
60
|
-
// CRITICAL: The output of a decompression library like pako is a raw binary
|
|
61
|
-
// stream. It is NOT guaranteed to be valid UTF-8. Using the strict
|
|
62
|
-
// `bytesToStringUTF8` can fail. `bytesToStringASCII` is a more permissive
|
|
63
|
-
// decoder that is robust enough to handle this binary data and convert it
|
|
64
|
-
// to a string that can be safely parsed by `JSON.parse()`.
|
|
65
|
-
const payloadString = Content.bytesToStringASCII(payloadBytes);
|
|
66
|
-
return JSON.parse(payloadString);
|
|
67
|
-
} catch (e) {
|
|
68
|
-
console.error(`Cannot decode JWT payload: ${e}`);
|
|
69
|
-
return {};
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Fully decodes a compact JWT into a `DataCompactJWT` object with JSON headers and payload.
|
|
75
|
-
* @returns A (compact) JWT object or undefined if parsing fails.
|
|
76
|
-
*/
|
|
77
|
-
export async function getDataJWT(compactJWT: string | undefined): Promise<DataCompactJWT | undefined> {
|
|
78
|
-
const parts = getPartsJWT(compactJWT);
|
|
79
|
-
if (!parts) {
|
|
80
|
-
return undefined;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const header = decodeHeader(parts.protected);
|
|
84
|
-
const isDeflated = header.zip === 'DEF';
|
|
85
|
-
const payload = await decodePayload(parts.payload, isDeflated);
|
|
86
|
-
|
|
87
|
-
return {
|
|
88
|
-
protected: header,
|
|
89
|
-
payload,
|
|
90
|
-
signature: parts.signature ? Content.base64ToBytes(parts.signature) : undefined,
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
// --- JWT Creation and Encoding ---
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Encodes a JSON object into a Base64Url string.
|
|
99
|
-
* @param header The header object.
|
|
100
|
-
* @returns The encoded string.
|
|
101
|
-
*/
|
|
102
|
-
export function encodeHeader(header: object): string {
|
|
103
|
-
try {
|
|
104
|
-
return Content.objectToRawBase64UrlSafe(header);
|
|
105
|
-
} catch (e) {
|
|
106
|
-
console.warn('Cannot encode JWT header', e);
|
|
107
|
-
return '';
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Encodes a JSON object into a Base64Url payload, compressing it if required.
|
|
113
|
-
* @param payload The payload object.
|
|
114
|
-
* @param deflate True to compress the payload with DEFLATE.
|
|
115
|
-
* @returns The encoded string.
|
|
116
|
-
*/
|
|
117
|
-
export async function encodePayload(payload: object, deflate?: boolean): Promise<string> {
|
|
118
|
-
try {
|
|
119
|
-
// CRITICAL: When creating a payload, we start with a JSON string, which IS
|
|
120
|
-
// valid UTF-8. We must use the strict `stringToBytesUTF8` encoder to ensure
|
|
121
|
-
// standards compliance.
|
|
122
|
-
let payloadBytes = Content.stringToBytesUTF8(JSON.stringify(payload));
|
|
123
|
-
if (deflate) {
|
|
124
|
-
payloadBytes = pako.deflate(payloadBytes);
|
|
125
|
-
}
|
|
126
|
-
return Content.bytesToRawBase64UrlSafe(payloadBytes);
|
|
127
|
-
} catch (e) {
|
|
128
|
-
console.warn('Cannot encode JWT payload', e);
|
|
129
|
-
return '';
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Encodes a signature byte array into a Base64Url string.
|
|
135
|
-
* @param signatureBytes The signature bytes.
|
|
136
|
-
* @returns The encoded string, or an empty string if no signature is provided.
|
|
137
|
-
*/
|
|
138
|
-
export function encodeSignature(signatureBytes?: Uint8Array): string {
|
|
139
|
-
if (!signatureBytes || signatureBytes.length < 1) {
|
|
140
|
-
return '';
|
|
141
|
-
}
|
|
142
|
-
try {
|
|
143
|
-
return Content.bytesToRawBase64UrlSafe(signatureBytes);
|
|
144
|
-
} catch (e) {
|
|
145
|
-
console.warn('Cannot encode JWT signature', e);
|
|
146
|
-
return '';
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Assembles a header, payload, and signature into a compact JWT string.
|
|
152
|
-
* @param header The header object.
|
|
153
|
-
* @param payload The payload object.
|
|
154
|
-
* @param signatureBytes The optional signature.
|
|
155
|
-
* @returns A compact JWT string.
|
|
156
|
-
*/
|
|
157
|
-
export async function compactJWT(header: object, payload: object, signatureBytes?: Uint8Array): Promise<string> {
|
|
158
|
-
const encodedHeader = encodeHeader(header);
|
|
159
|
-
const isDeflated = (header as any).zip === 'DEF';
|
|
160
|
-
const encodedPayload = await encodePayload(payload, isDeflated);
|
|
161
|
-
const encodedSignature = encodeSignature(signatureBytes);
|
|
162
|
-
|
|
163
|
-
return `${encodedHeader}.${encodedPayload}.${encodedSignature}`;
|
|
164
|
-
}
|
|
165
|
-
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
// src/utils/manager-error.ts
|
|
2
|
-
// Copyright 2025 Antifraud Services Inc. under the Apache License, Version 2.0.
|
|
3
|
-
|
|
4
|
-
import { IssueTypeCode, IssueTypeToHttpStatus } from "../models/issue";
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* A custom error class used to propagate specific operational failures from deep
|
|
8
|
-
* within the manager's logic to the central error handler.
|
|
9
|
-
* It carries the necessary information to build a well-formed ErrorEntry.
|
|
10
|
-
*/
|
|
11
|
-
export class ManagerError extends Error {
|
|
12
|
-
public readonly code: IssueTypeCode;
|
|
13
|
-
public readonly status: string; // This is a string
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* @param message The diagnostic message for the error.
|
|
17
|
-
* @param code The classification of the error, from which the HTTP status will be derived.
|
|
18
|
-
*/
|
|
19
|
-
constructor(message: string, code: IssueTypeCode) {
|
|
20
|
-
super(message);
|
|
21
|
-
this.name = 'ManagerError';
|
|
22
|
-
this.code = code;
|
|
23
|
-
// Automatically derive the HTTP status string from the issue code.
|
|
24
|
-
this.status = IssueTypeToHttpStatus[code] || '500';
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
package/src/utils/multibase58.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
// crypto-ts/crypto-ts/utils/multibase58.ts
|
|
2
|
-
// Copyright 2025 Antifraud Services Inc. under the Apache License, Version 2.0.
|
|
3
|
-
|
|
4
|
-
import baseX from "base-x";
|
|
5
|
-
|
|
6
|
-
const BASE58_BTC_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
7
|
-
const base58btc = baseX(BASE58_BTC_ALPHABET);
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Encode bytes into multibase base58btc string (prefixed with 'z').
|
|
11
|
-
* Equivalent to multiformats base58btc.encode.
|
|
12
|
-
*/
|
|
13
|
-
export function encodeMultibase58btc(data: Uint8Array): string {
|
|
14
|
-
return "z" + base58btc.encode(Buffer.from(data));
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Decode a multibase base58btc string (must start with 'z').
|
|
19
|
-
* Equivalent to multiformats base58btc.decode.
|
|
20
|
-
*/
|
|
21
|
-
export function decodeMultibase58btc(multibaseStr: string): Uint8Array {
|
|
22
|
-
if (!multibaseStr.startsWith("z")) {
|
|
23
|
-
throw new Error("Invalid multibase58btc string: missing 'z' prefix");
|
|
24
|
-
}
|
|
25
|
-
return new Uint8Array(base58btc.decode(multibaseStr.slice(1)));
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// HEX ➜ multibase base58btc (quita guiones si los hay)
|
|
29
|
-
export function encodeHexToMultibase58btc(hexStr: string): string {
|
|
30
|
-
const hexClean = hexStr.replace(/-/g, "").toLowerCase();
|
|
31
|
-
if (!/^[0-9a-f]{32}$/i.test(hexClean)) throw new Error("Invalid 16-byte hex string");
|
|
32
|
-
const bytes = new Uint8Array(hexClean.match(/.{1,2}/g)!.map(b => parseInt(b, 16)));
|
|
33
|
-
return encodeMultibase58btc(bytes);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// multibase base58btc ➜ hex (no hyppens)
|
|
37
|
-
export function decodeMultibase58btcToHex(b58str: string): string {
|
|
38
|
-
const bytes = decodeMultibase58btc(b58str);
|
|
39
|
-
return Array.from(bytes).map(b => b.toString(16).padStart(2, "0")).join("");
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// multibase base58btc ➜ UUID (with hyppens)
|
|
43
|
-
export function decodeMultibase58btcToUUID(b58str: string): string {
|
|
44
|
-
const hex = decodeMultibase58btcToHex(b58str);
|
|
45
|
-
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
46
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"module": "ESNext",
|
|
5
|
-
"moduleResolution": "bundler",
|
|
6
|
-
"lib": ["ES2022"],
|
|
7
|
-
"types": ["node", "jest"],
|
|
8
|
-
"strict": true,
|
|
9
|
-
"esModuleInterop": true,
|
|
10
|
-
"skipLibCheck": true,
|
|
11
|
-
"forceConsistentCasingInFileNames": true
|
|
12
|
-
},
|
|
13
|
-
"include": ["src/**/*.ts"],
|
|
14
|
-
"exclude": ["node_modules", "__tests__/**", "src/**/*.txt"]
|
|
15
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|