@fhirfly-io/shl 0.3.2 → 0.5.0
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 +53 -0
- package/dist/{chunk-63Q54EKN.cjs → chunk-CN44QKWJ.cjs} +185 -36
- package/dist/chunk-CN44QKWJ.cjs.map +1 -0
- package/dist/{chunk-QXSWM5QV.cjs → chunk-H37YQWF2.cjs} +90 -11
- package/dist/chunk-H37YQWF2.cjs.map +1 -0
- package/dist/{chunk-ZEE5RXIS.js → chunk-IYRQRY4A.js} +90 -12
- package/dist/chunk-IYRQRY4A.js.map +1 -0
- package/dist/{chunk-YBDRWUQU.js → chunk-YUMCDN7I.js} +185 -36
- package/dist/chunk-YUMCDN7I.js.map +1 -0
- package/dist/cli.cjs +11 -11
- package/dist/cli.js +2 -2
- package/dist/express.cjs +12 -3
- package/dist/express.cjs.map +1 -1
- package/dist/express.d.cts +3 -2
- package/dist/express.d.ts +3 -2
- package/dist/express.js +11 -2
- package/dist/express.js.map +1 -1
- package/dist/fastify.cjs +22 -5
- package/dist/fastify.cjs.map +1 -1
- package/dist/fastify.d.cts +3 -2
- package/dist/fastify.d.ts +3 -2
- package/dist/fastify.js +21 -4
- package/dist/fastify.js.map +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.d.cts +15 -5
- package/dist/index.d.ts +15 -5
- package/dist/index.js +1 -1
- package/dist/lambda.cjs +4 -3
- package/dist/lambda.cjs.map +1 -1
- package/dist/lambda.d.cts +3 -2
- package/dist/lambda.d.ts +3 -2
- package/dist/lambda.js +3 -2
- package/dist/lambda.js.map +1 -1
- package/dist/server.cjs +6 -2
- package/dist/server.d.cts +4 -4
- package/dist/server.d.ts +4 -4
- package/dist/server.js +1 -1
- package/dist/{storage-B3GyJD2y.d.ts → storage-CvsOM1Eu.d.ts} +1 -1
- package/dist/{storage-BwszYwFo.d.cts → storage-DggeMhOI.d.cts} +1 -1
- package/dist/{types-BegxU0wQ.d.ts → types--SjcaaWT.d.ts} +26 -2
- package/dist/{types-hHf-a3hH.d.cts → types-BcfxBDTA.d.cts} +26 -2
- package/dist/{types-Doq5cGNm.d.ts → types-CmeXnyth.d.cts} +31 -3
- package/dist/{types-Doq5cGNm.d.cts → types-CmeXnyth.d.ts} +31 -3
- package/package.json +1 -1
- package/dist/chunk-63Q54EKN.cjs.map +0 -1
- package/dist/chunk-QXSWM5QV.cjs.map +0 -1
- package/dist/chunk-YBDRWUQU.js.map +0 -1
- package/dist/chunk-ZEE5RXIS.js.map +0 -1
package/README.md
CHANGED
|
@@ -90,6 +90,7 @@ const result = await SHL.create({
|
|
|
90
90
|
storage,
|
|
91
91
|
passcode: "1234",
|
|
92
92
|
label: "Maria's Health Summary",
|
|
93
|
+
expiresAt: "travel", // 90 days — or use "point-of-care" (15min), "appointment" (24h), "permanent"
|
|
93
94
|
});
|
|
94
95
|
|
|
95
96
|
console.log(result.url); // shlink:/eyJ1cmwiOiJodHRwczovL...
|
|
@@ -97,6 +98,35 @@ console.log(result.qrCode); // data:image/png;base64,...
|
|
|
97
98
|
console.log(result.passcode); // "1234"
|
|
98
99
|
```
|
|
99
100
|
|
|
101
|
+
### Expiration Presets
|
|
102
|
+
|
|
103
|
+
Instead of calculating `Date` objects, use named presets:
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
await SHL.create({ bundle, storage, expiresAt: "point-of-care" }); // 15 minutes
|
|
107
|
+
await SHL.create({ bundle, storage, expiresAt: "appointment" }); // 24 hours
|
|
108
|
+
await SHL.create({ bundle, storage, expiresAt: "travel" }); // 90 days
|
|
109
|
+
await SHL.create({ bundle, storage, expiresAt: "permanent" }); // no expiration
|
|
110
|
+
await SHL.create({ bundle, storage, expiresAt: new Date(...) }); // raw Date still works
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### PSHD Compliance
|
|
114
|
+
|
|
115
|
+
For CMS-aligned patient-to-provider sharing at the point of care:
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
const fhirBundle = await bundle.build({ profile: "pshd" }); // strips meta.profile, uses collection bundle
|
|
119
|
+
|
|
120
|
+
const result = await SHL.create({
|
|
121
|
+
bundle: fhirBundle,
|
|
122
|
+
storage,
|
|
123
|
+
compliance: "pshd",
|
|
124
|
+
expiresAt: "point-of-care",
|
|
125
|
+
});
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
See the [PSHD Guide](https://fhirfly.io/docs/shl/pshd) for full details.
|
|
129
|
+
|
|
100
130
|
## Storage Adapters
|
|
101
131
|
|
|
102
132
|
```typescript
|
|
@@ -171,6 +201,29 @@ app.listen(3000);
|
|
|
171
201
|
|
|
172
202
|
Also available for Fastify (`@fhirfly-io/shl/fastify`) and Lambda (`@fhirfly-io/shl/lambda`).
|
|
173
203
|
|
|
204
|
+
### Audit Logging
|
|
205
|
+
|
|
206
|
+
Use `AuditableStorage` to capture access events at the storage level — plug in any logging backend:
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
import { AuditableStorage, SHLServerStorage, AccessEvent } from "@fhirfly-io/shl/server";
|
|
210
|
+
|
|
211
|
+
class MyAuditStorage extends ServerLocalStorage implements AuditableStorage {
|
|
212
|
+
async onAccess(shlId: string, event: AccessEvent): Promise<void> {
|
|
213
|
+
await db.auditLog.insert({
|
|
214
|
+
shlId,
|
|
215
|
+
recipient: event.recipient,
|
|
216
|
+
ip: event.ip,
|
|
217
|
+
timestamp: event.timestamp,
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
app.use("/shl", expressMiddleware({ storage: new MyAuditStorage({ ... }) }));
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
The server handler detects `AuditableStorage` at runtime via `isAuditableStorage()` — existing storage implementations work unchanged.
|
|
226
|
+
|
|
174
227
|
## Live Exercise
|
|
175
228
|
|
|
176
229
|
Run the comprehensive integration test against the live API to exercise every SDK path:
|
|
@@ -180,7 +180,11 @@ var CODE_SYSTEMS = {
|
|
|
180
180
|
CVX: "http://hl7.org/fhir/sid/cvx",
|
|
181
181
|
ICD10CM: "http://hl7.org/fhir/sid/icd-10-cm",
|
|
182
182
|
CONDITION_CLINICAL: "http://terminology.hl7.org/CodeSystem/condition-clinical",
|
|
183
|
-
ALLERGY_CLINICAL: "http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical"
|
|
183
|
+
ALLERGY_CLINICAL: "http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical",
|
|
184
|
+
/** CMS Patient-Shared Health Document category code system */
|
|
185
|
+
CMS_PATIENT_SHARED_CATEGORY: "https://cms.gov/fhir/CodeSystem/patient-shared-category",
|
|
186
|
+
/** V3 ActCode security label for patient-asserted data */
|
|
187
|
+
SECURITY_PATAST: "PATAST"
|
|
184
188
|
};
|
|
185
189
|
|
|
186
190
|
// src/ips/medication.ts
|
|
@@ -1106,8 +1110,9 @@ function resolveDocuments(documents, patientRef, profile, generateUuid2) {
|
|
|
1106
1110
|
contentType,
|
|
1107
1111
|
data: base64Content
|
|
1108
1112
|
};
|
|
1109
|
-
const
|
|
1110
|
-
const
|
|
1113
|
+
const isPshd = profile === "pshd";
|
|
1114
|
+
const typeCode = isPshd ? "60591-5" : doc.typeCode ?? "34133-9";
|
|
1115
|
+
const typeDisplay = isPshd ? "Patient summary Document" : doc.typeDisplay ?? "Summarization of episode note";
|
|
1111
1116
|
const docRefResource = {
|
|
1112
1117
|
resourceType: "DocumentReference",
|
|
1113
1118
|
id: docRefId,
|
|
@@ -1133,7 +1138,29 @@ function resolveDocuments(documents, patientRef, profile, generateUuid2) {
|
|
|
1133
1138
|
}
|
|
1134
1139
|
]
|
|
1135
1140
|
};
|
|
1136
|
-
if (
|
|
1141
|
+
if (isPshd) {
|
|
1142
|
+
docRefResource.category = [
|
|
1143
|
+
{
|
|
1144
|
+
coding: [
|
|
1145
|
+
{
|
|
1146
|
+
system: CODE_SYSTEMS.CMS_PATIENT_SHARED_CATEGORY,
|
|
1147
|
+
code: "patient-shared",
|
|
1148
|
+
display: "Patient Shared"
|
|
1149
|
+
}
|
|
1150
|
+
]
|
|
1151
|
+
}
|
|
1152
|
+
];
|
|
1153
|
+
docRefResource.author = [{ reference: patientRef }];
|
|
1154
|
+
docRefResource.meta = {
|
|
1155
|
+
security: [
|
|
1156
|
+
{
|
|
1157
|
+
system: "http://terminology.hl7.org/CodeSystem/v3-ActCode",
|
|
1158
|
+
code: CODE_SYSTEMS.SECURITY_PATAST,
|
|
1159
|
+
display: "patient asserted"
|
|
1160
|
+
}
|
|
1161
|
+
]
|
|
1162
|
+
};
|
|
1163
|
+
} else if (profile === "ips") {
|
|
1137
1164
|
docRefResource.meta = {
|
|
1138
1165
|
profile: ["http://hl7.org/fhir/uv/ips/StructureDefinition/DocumentReference-uv-ips"]
|
|
1139
1166
|
};
|
|
@@ -1332,11 +1359,9 @@ var Bundle = class {
|
|
|
1332
1359
|
async build(options) {
|
|
1333
1360
|
const profile = options?.profile ?? "ips";
|
|
1334
1361
|
const bundleId = options?.bundleId ?? generateUuid();
|
|
1335
|
-
const compositionId = generateUuid();
|
|
1336
1362
|
const patientId = generateUuid();
|
|
1337
|
-
const
|
|
1363
|
+
const timestamp = options?.compositionDate ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
1338
1364
|
const patientFullUrl = `urn:uuid:${patientId}`;
|
|
1339
|
-
const compositionFullUrl = `urn:uuid:${compositionId}`;
|
|
1340
1365
|
const patientResource = normalizePatient(this._patient, patientId, profile);
|
|
1341
1366
|
const [medResult, condResult, allergyResult, immResult, resultResult] = await Promise.all([
|
|
1342
1367
|
resolveMedications(this._medications, patientFullUrl, profile, generateUuid),
|
|
@@ -1353,6 +1378,22 @@ var Bundle = class {
|
|
|
1353
1378
|
...immResult.warnings,
|
|
1354
1379
|
...resultResult.warnings
|
|
1355
1380
|
];
|
|
1381
|
+
if (profile === "pshd") {
|
|
1382
|
+
return this.buildPshdBundle(
|
|
1383
|
+
bundleId,
|
|
1384
|
+
timestamp,
|
|
1385
|
+
patientFullUrl,
|
|
1386
|
+
patientResource,
|
|
1387
|
+
medResult.entries,
|
|
1388
|
+
condResult.entries,
|
|
1389
|
+
allergyResult.entries,
|
|
1390
|
+
immResult.entries,
|
|
1391
|
+
resultResult.entries,
|
|
1392
|
+
docResult.entries
|
|
1393
|
+
);
|
|
1394
|
+
}
|
|
1395
|
+
const compositionId = generateUuid();
|
|
1396
|
+
const compositionFullUrl = `urn:uuid:${compositionId}`;
|
|
1356
1397
|
const medRefs = medResult.entries.map((e) => ({ reference: e.fullUrl }));
|
|
1357
1398
|
const condRefs = condResult.entries.map((e) => ({ reference: e.fullUrl }));
|
|
1358
1399
|
const allergyRefs = allergyResult.entries.map((e) => ({ reference: e.fullUrl }));
|
|
@@ -1361,7 +1402,7 @@ var Bundle = class {
|
|
|
1361
1402
|
const composition = this.buildComposition(
|
|
1362
1403
|
compositionId,
|
|
1363
1404
|
patientFullUrl,
|
|
1364
|
-
|
|
1405
|
+
timestamp,
|
|
1365
1406
|
profile,
|
|
1366
1407
|
medRefs,
|
|
1367
1408
|
allergyRefs,
|
|
@@ -1387,7 +1428,7 @@ var Bundle = class {
|
|
|
1387
1428
|
value: `urn:uuid:${bundleId}`
|
|
1388
1429
|
},
|
|
1389
1430
|
type: "document",
|
|
1390
|
-
timestamp
|
|
1431
|
+
timestamp,
|
|
1391
1432
|
entry: entries
|
|
1392
1433
|
};
|
|
1393
1434
|
return bundle;
|
|
@@ -1407,6 +1448,37 @@ var Bundle = class {
|
|
|
1407
1448
|
path: "Patient.birthDate"
|
|
1408
1449
|
});
|
|
1409
1450
|
}
|
|
1451
|
+
if (profile === "pshd") {
|
|
1452
|
+
if (this._documents.length === 0) {
|
|
1453
|
+
issues.push({
|
|
1454
|
+
severity: "error",
|
|
1455
|
+
message: "PSHD requires at least one DocumentReference (1..1)",
|
|
1456
|
+
path: "Bundle.entry:DocumentReference"
|
|
1457
|
+
});
|
|
1458
|
+
} else {
|
|
1459
|
+
const hasPdf = this._documents.some(
|
|
1460
|
+
(d) => (d.contentType ?? "application/pdf") === "application/pdf"
|
|
1461
|
+
);
|
|
1462
|
+
if (!hasPdf) {
|
|
1463
|
+
issues.push({
|
|
1464
|
+
severity: "error",
|
|
1465
|
+
message: "PSHD requires at least one PDF document (contentType application/pdf)",
|
|
1466
|
+
path: "DocumentReference.content.attachment.contentType"
|
|
1467
|
+
});
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
if (!this._patient.gender) {
|
|
1471
|
+
issues.push({
|
|
1472
|
+
severity: "warning",
|
|
1473
|
+
message: "Patient.gender recommended for PSHD demographic matching",
|
|
1474
|
+
path: "Patient.gender"
|
|
1475
|
+
});
|
|
1476
|
+
}
|
|
1477
|
+
return {
|
|
1478
|
+
valid: issues.filter((i) => i.severity === "error").length === 0,
|
|
1479
|
+
issues
|
|
1480
|
+
};
|
|
1481
|
+
}
|
|
1410
1482
|
if (profile === "ips") {
|
|
1411
1483
|
if (!this.hasValidName()) {
|
|
1412
1484
|
issues.push({
|
|
@@ -1482,6 +1554,37 @@ var Bundle = class {
|
|
|
1482
1554
|
const s = this._patient;
|
|
1483
1555
|
return !!(s.given || s.family || s.name);
|
|
1484
1556
|
}
|
|
1557
|
+
buildPshdBundle(bundleId, timestamp, patientFullUrl, patientResource, medEntries, condEntries, allergyEntries, immEntries, resultEntries, docEntries) {
|
|
1558
|
+
const entries = [
|
|
1559
|
+
{ fullUrl: patientFullUrl, resource: patientResource },
|
|
1560
|
+
...medEntries,
|
|
1561
|
+
...condEntries,
|
|
1562
|
+
...allergyEntries,
|
|
1563
|
+
...immEntries,
|
|
1564
|
+
...resultEntries,
|
|
1565
|
+
...docEntries
|
|
1566
|
+
];
|
|
1567
|
+
for (const entry of entries) {
|
|
1568
|
+
const meta = entry.resource.meta;
|
|
1569
|
+
if (meta?.profile) {
|
|
1570
|
+
delete meta.profile;
|
|
1571
|
+
if (Object.keys(meta).length === 0) {
|
|
1572
|
+
delete entry.resource.meta;
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1576
|
+
return {
|
|
1577
|
+
resourceType: "Bundle",
|
|
1578
|
+
id: bundleId,
|
|
1579
|
+
identifier: {
|
|
1580
|
+
system: "urn:ietf:rfc:3986",
|
|
1581
|
+
value: `urn:uuid:${bundleId}`
|
|
1582
|
+
},
|
|
1583
|
+
type: "collection",
|
|
1584
|
+
timestamp,
|
|
1585
|
+
entry: entries
|
|
1586
|
+
};
|
|
1587
|
+
}
|
|
1485
1588
|
buildComposition(id, patientRef, date, profile, medRefs, allergyRefs, condRefs, immRefs, resultRefs) {
|
|
1486
1589
|
const composition = {
|
|
1487
1590
|
resourceType: "Composition",
|
|
@@ -1610,6 +1713,7 @@ function generateUuid() {
|
|
|
1610
1713
|
var shl_exports = {};
|
|
1611
1714
|
chunkQ7SFCCGT_cjs.__export(shl_exports, {
|
|
1612
1715
|
AzureStorage: () => chunkUDS6UJAL_cjs.AzureStorage,
|
|
1716
|
+
EXPIRATION_PRESETS: () => EXPIRATION_PRESETS,
|
|
1613
1717
|
FhirflyStorage: () => chunkUDS6UJAL_cjs.FhirflyStorage,
|
|
1614
1718
|
GCSStorage: () => chunkUDS6UJAL_cjs.GCSStorage,
|
|
1615
1719
|
LocalStorage: () => chunkUDS6UJAL_cjs.LocalStorage,
|
|
@@ -1621,6 +1725,18 @@ chunkQ7SFCCGT_cjs.__export(shl_exports, {
|
|
|
1621
1725
|
getEntryContent: () => getEntryContent,
|
|
1622
1726
|
revoke: () => revoke
|
|
1623
1727
|
});
|
|
1728
|
+
|
|
1729
|
+
// src/shl/types.ts
|
|
1730
|
+
var EXPIRATION_PRESETS = {
|
|
1731
|
+
"point-of-care": 15 * 60 * 1e3,
|
|
1732
|
+
// 15 minutes
|
|
1733
|
+
"appointment": 24 * 60 * 60 * 1e3,
|
|
1734
|
+
// 24 hours
|
|
1735
|
+
"travel": 90 * 24 * 60 * 60 * 1e3,
|
|
1736
|
+
// 90 days
|
|
1737
|
+
"permanent": 0
|
|
1738
|
+
// no expiration
|
|
1739
|
+
};
|
|
1624
1740
|
function base64url(data) {
|
|
1625
1741
|
return data.toString("base64url");
|
|
1626
1742
|
}
|
|
@@ -1708,13 +1824,43 @@ async function generateQRCode(url) {
|
|
|
1708
1824
|
});
|
|
1709
1825
|
}
|
|
1710
1826
|
async function create(options) {
|
|
1711
|
-
const { bundle, passcode,
|
|
1827
|
+
const { bundle, passcode, maxAccesses, label, storage, debug } = options;
|
|
1828
|
+
let expiresAt;
|
|
1829
|
+
if (typeof options.expiresAt === "string") {
|
|
1830
|
+
const preset = options.expiresAt;
|
|
1831
|
+
const durationMs = EXPIRATION_PRESETS[preset];
|
|
1832
|
+
if (durationMs === void 0) {
|
|
1833
|
+
throw new chunkUDS6UJAL_cjs.ValidationError(`Unknown expiration preset: "${preset}"`);
|
|
1834
|
+
}
|
|
1835
|
+
expiresAt = durationMs > 0 ? new Date(Date.now() + durationMs) : void 0;
|
|
1836
|
+
} else {
|
|
1837
|
+
expiresAt = options.expiresAt;
|
|
1838
|
+
}
|
|
1712
1839
|
if (!bundle || typeof bundle !== "object") {
|
|
1713
1840
|
throw new chunkUDS6UJAL_cjs.ValidationError("bundle is required and must be an object");
|
|
1714
1841
|
}
|
|
1715
1842
|
if (!storage?.baseUrl) {
|
|
1716
1843
|
throw new chunkUDS6UJAL_cjs.ValidationError("storage with baseUrl is required");
|
|
1717
1844
|
}
|
|
1845
|
+
let mode = options.mode ?? "manifest";
|
|
1846
|
+
if (options.compliance === "pshd") {
|
|
1847
|
+
mode = "direct";
|
|
1848
|
+
if (passcode) {
|
|
1849
|
+
throw new chunkUDS6UJAL_cjs.ValidationError(
|
|
1850
|
+
"PSHD compliance forbids passcode (flag U is incompatible with flag P)"
|
|
1851
|
+
);
|
|
1852
|
+
}
|
|
1853
|
+
if (!expiresAt && options.expiresAt !== "permanent") {
|
|
1854
|
+
throw new chunkUDS6UJAL_cjs.ValidationError(
|
|
1855
|
+
"PSHD compliance requires expiresAt (short-lived links for point-of-care)"
|
|
1856
|
+
);
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
if (mode === "direct" && passcode) {
|
|
1860
|
+
throw new chunkUDS6UJAL_cjs.ValidationError(
|
|
1861
|
+
"Direct mode (flag U) is incompatible with passcode (flag P)"
|
|
1862
|
+
);
|
|
1863
|
+
}
|
|
1718
1864
|
const key = generateKey();
|
|
1719
1865
|
const shlId = generateShlId();
|
|
1720
1866
|
let jwe;
|
|
@@ -1774,31 +1920,34 @@ async function create(options) {
|
|
|
1774
1920
|
);
|
|
1775
1921
|
}
|
|
1776
1922
|
}
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1923
|
+
if (mode === "manifest") {
|
|
1924
|
+
const manifest = {
|
|
1925
|
+
files: [
|
|
1926
|
+
{
|
|
1927
|
+
contentType: "application/fhir+json;fhirVersion=4.0.1",
|
|
1928
|
+
location: `${baseUrl}/${shlId}/content`
|
|
1929
|
+
},
|
|
1930
|
+
...attachments.map((att, i) => ({
|
|
1931
|
+
contentType: att.contentType,
|
|
1932
|
+
location: `${baseUrl}/${shlId}/attachment/${i}`
|
|
1933
|
+
}))
|
|
1934
|
+
],
|
|
1935
|
+
status: "finalized",
|
|
1936
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
|
|
1937
|
+
};
|
|
1938
|
+
try {
|
|
1939
|
+
await storage.store(`${shlId}/manifest.json`, JSON.stringify(manifest));
|
|
1940
|
+
} catch (err) {
|
|
1941
|
+
throw new chunkUDS6UJAL_cjs.StorageError(
|
|
1942
|
+
`Failed to store manifest: ${err instanceof Error ? err.message : String(err)}`,
|
|
1943
|
+
"store"
|
|
1944
|
+
);
|
|
1945
|
+
}
|
|
1798
1946
|
}
|
|
1799
1947
|
const metadata = {
|
|
1800
1948
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1801
1949
|
};
|
|
1950
|
+
if (mode === "direct") metadata.mode = "direct";
|
|
1802
1951
|
if (passcode) {
|
|
1803
1952
|
metadata.passcode = crypto$1.createHash("sha256").update(passcode).digest("hex");
|
|
1804
1953
|
}
|
|
@@ -1812,7 +1961,7 @@ async function create(options) {
|
|
|
1812
1961
|
"store"
|
|
1813
1962
|
);
|
|
1814
1963
|
}
|
|
1815
|
-
const flags = buildFlags(passcode);
|
|
1964
|
+
const flags = buildFlags(mode, passcode);
|
|
1816
1965
|
const shlPayload = {
|
|
1817
1966
|
url: `${baseUrl}/${shlId}`,
|
|
1818
1967
|
key: base64url(key),
|
|
@@ -1839,8 +1988,8 @@ async function create(options) {
|
|
|
1839
1988
|
if (debug) result.debugBundlePath = `${shlId}/bundle.json`;
|
|
1840
1989
|
return result;
|
|
1841
1990
|
}
|
|
1842
|
-
function buildFlags(passcode) {
|
|
1843
|
-
const flags = ["L"];
|
|
1991
|
+
function buildFlags(mode, passcode) {
|
|
1992
|
+
const flags = [mode === "direct" ? "U" : "L"];
|
|
1844
1993
|
if (passcode) flags.push("P");
|
|
1845
1994
|
return flags.sort().join("");
|
|
1846
1995
|
}
|
|
@@ -1948,5 +2097,5 @@ async function revoke(shlId, storage) {
|
|
|
1948
2097
|
|
|
1949
2098
|
exports.ips_exports = ips_exports;
|
|
1950
2099
|
exports.shl_exports = shl_exports;
|
|
1951
|
-
//# sourceMappingURL=chunk-
|
|
1952
|
-
//# sourceMappingURL=chunk-
|
|
2100
|
+
//# sourceMappingURL=chunk-CN44QKWJ.cjs.map
|
|
2101
|
+
//# sourceMappingURL=chunk-CN44QKWJ.cjs.map
|