@learncard/helpers 1.3.1 → 1.3.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.
- package/dist/{helpers.cjs.development.js → helpers.cjs.development.cjs} +112 -9
- package/dist/helpers.cjs.development.cjs.map +7 -0
- package/dist/{helpers.cjs.production.min.js → helpers.cjs.production.min.cjs} +5 -5
- package/dist/helpers.cjs.production.min.cjs.map +7 -0
- package/dist/helpers.d.cts +901 -0
- package/dist/helpers.d.ts +101 -0
- package/dist/helpers.esm.js +112 -9
- package/dist/helpers.esm.js.map +4 -4
- package/dist/index.cjs +7 -0
- package/package.json +17 -4
- package/dist/helpers.cjs.development.js.map +0 -7
- package/dist/helpers.cjs.production.min.js.map +0 -7
- package/dist/index.js +0 -7
package/dist/helpers.d.ts
CHANGED
|
@@ -435,6 +435,81 @@ declare const VCValidator: z.ZodObject<{
|
|
|
435
435
|
]>;
|
|
436
436
|
}, z.core.$catchall<z.ZodAny>>;
|
|
437
437
|
export type VC = z.infer<typeof VCValidator>;
|
|
438
|
+
declare const CredentialFormatValidator: z.ZodEnum<{
|
|
439
|
+
"w3c-vc-2.0": "w3c-vc-2.0";
|
|
440
|
+
"w3c-vc-1.1": "w3c-vc-1.1";
|
|
441
|
+
"jwt-vc-json": "jwt-vc-json";
|
|
442
|
+
"dc+sd-jwt": "dc+sd-jwt";
|
|
443
|
+
"vc+sd-jwt": "vc+sd-jwt";
|
|
444
|
+
mso_mdoc: "mso_mdoc";
|
|
445
|
+
}>;
|
|
446
|
+
export type CredentialFormat = z.infer<typeof CredentialFormatValidator>;
|
|
447
|
+
/**
|
|
448
|
+
* Format-discriminated read view over a stored credential. Returned
|
|
449
|
+
* by `toStoredCredential(record)` in `@learncard/helpers`.
|
|
450
|
+
*
|
|
451
|
+
* The `data` field carries the correct wire-form representation for
|
|
452
|
+
* the credential's format:
|
|
453
|
+
* - W3C VCs: the JSON-LD VC object (also what `record.vc` holds)
|
|
454
|
+
* - JWT-VC: the compact JWS string (extracted from `record.vc.proof.jwt`
|
|
455
|
+
* if the record uses the legacy LDP-around-JWT envelope, otherwise
|
|
456
|
+
* the raw string from `record.rawWireForm`)
|
|
457
|
+
* - SD-JWT-VC: the compact `<JWT>~<disclosures>~` string
|
|
458
|
+
* - mDoc: base64url-encoded CBOR bytes (stored as a string for
|
|
459
|
+
* LearnCloud's JSON-only encrypted store; consumers base64-decode
|
|
460
|
+
* when they need raw bytes)
|
|
461
|
+
*
|
|
462
|
+
* Format-aware consumers pattern-match on `format` and use `data`.
|
|
463
|
+
* Legacy consumers continue to read `record.vc` directly — the
|
|
464
|
+
* projector is opt-in, never required.
|
|
465
|
+
*/
|
|
466
|
+
export type StoredCredential = {
|
|
467
|
+
format: "w3c-vc-2.0";
|
|
468
|
+
data: VC;
|
|
469
|
+
} | {
|
|
470
|
+
format: "w3c-vc-1.1";
|
|
471
|
+
data: VC;
|
|
472
|
+
} | {
|
|
473
|
+
format: "jwt-vc-json";
|
|
474
|
+
data: string;
|
|
475
|
+
} | {
|
|
476
|
+
format: "dc+sd-jwt";
|
|
477
|
+
data: string;
|
|
478
|
+
} | {
|
|
479
|
+
format: "vc+sd-jwt";
|
|
480
|
+
data: string;
|
|
481
|
+
} | {
|
|
482
|
+
format: "mso_mdoc";
|
|
483
|
+
data: string;
|
|
484
|
+
};
|
|
485
|
+
export type CredentialRecord<Metadata extends Record<string, any> = Record<never, never>> = {
|
|
486
|
+
id: string;
|
|
487
|
+
uri: string;
|
|
488
|
+
/**
|
|
489
|
+
* Wire-format discriminator for the credential. Optional — when
|
|
490
|
+
* absent, legacy readers infer it from `vc` shape (see
|
|
491
|
+
* `toStoredCredential` in `@learncard/helpers`). Populated on new
|
|
492
|
+
* writes once the consumer is format-aware.
|
|
493
|
+
*
|
|
494
|
+
* Added in ADR-0001 Phase 1 as additive metadata; existing
|
|
495
|
+
* records without this field continue to work unchanged.
|
|
496
|
+
*/
|
|
497
|
+
format?: CredentialFormat;
|
|
498
|
+
/**
|
|
499
|
+
* Optional semantic type hint for fast filtering without parsing
|
|
500
|
+
* the full credential — `vct` for SD-JWT-VC, last-non-VC type for
|
|
501
|
+
* W3C VCs, doctype for mDoc. Added in ADR-0001 Phase 1.
|
|
502
|
+
*/
|
|
503
|
+
semanticType?: string;
|
|
504
|
+
/**
|
|
505
|
+
* On-the-wire representation for formats whose `vc` field cannot
|
|
506
|
+
* hold the canonical form (SD-JWT compact, JWT-VC compact, base64
|
|
507
|
+
* mDoc CBOR). Undefined for W3C VCs (`vc` IS the wire form). Added
|
|
508
|
+
* in ADR-0001 Phase 1.
|
|
509
|
+
*/
|
|
510
|
+
rawWireForm?: string;
|
|
511
|
+
[key: string]: any;
|
|
512
|
+
} & Metadata;
|
|
438
513
|
declare const JWEValidator: z.ZodObject<{
|
|
439
514
|
protected: z.ZodString;
|
|
440
515
|
iv: z.ZodString;
|
|
@@ -769,6 +844,32 @@ export declare const AGE_RATING_TO_MIN_AGE: Record<string, number>;
|
|
|
769
844
|
* @returns Age in years, or null if the date is invalid
|
|
770
845
|
*/
|
|
771
846
|
export declare const calculateAgeFromDob: (dob?: string | null) => number | null;
|
|
847
|
+
/**
|
|
848
|
+
* Project a `CredentialRecord` into a format-discriminated read view.
|
|
849
|
+
*
|
|
850
|
+
* Two paths into the same output:
|
|
851
|
+
*
|
|
852
|
+
* 1. **Explicit format**: if the record carries an explicit `format`
|
|
853
|
+
* discriminator (and `rawWireForm` where required), the projector
|
|
854
|
+
* trusts it. This is the path new format-aware writers take.
|
|
855
|
+
*
|
|
856
|
+
* 2. **Inferred from shape** (legacy fallback): for records that
|
|
857
|
+
* pre-date ADR-0001 Phase 1, the projector inspects `record.vc` and
|
|
858
|
+
* infers the format. W3C VCs → `w3c-vc-2.0` / `w3c-vc-1.1` based
|
|
859
|
+
* on `@context`; transitional SD-JWT wrappers (which never shipped
|
|
860
|
+
* but exist on branch `lc-1796-3`) → `dc+sd-jwt` with the compact
|
|
861
|
+
* extracted from `proof.jwt`; legacy JWT-VC envelopes → `jwt-vc-json`.
|
|
862
|
+
*
|
|
863
|
+
* Returns a `StoredCredential` for every conceivable record. Never
|
|
864
|
+
* throws — credentials with unrecognizable shape fall back to
|
|
865
|
+
* `w3c-vc-1.1` with `data = record.vc` so legacy consumers keep
|
|
866
|
+
* something they can read.
|
|
867
|
+
*
|
|
868
|
+
* This projector is the SAFETY NET that makes the ADR-0001 migration
|
|
869
|
+
* non-breaking: writers can adopt format-tagging at their own pace;
|
|
870
|
+
* readers using this projector see the right discriminator either way.
|
|
871
|
+
*/
|
|
872
|
+
export declare const toStoredCredential: (record: CredentialRecord) => StoredCredential;
|
|
772
873
|
/**
|
|
773
874
|
* Determines whether or not a string is a valid hexadecimal string
|
|
774
875
|
*
|
package/dist/helpers.esm.js
CHANGED
|
@@ -29,9 +29,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
29
29
|
mod
|
|
30
30
|
));
|
|
31
31
|
|
|
32
|
-
// ../learn-card-types/dist/types.cjs.development.
|
|
32
|
+
// ../learn-card-types/dist/types.cjs.development.cjs
|
|
33
33
|
var require_types_cjs_development = __commonJS({
|
|
34
|
-
"../learn-card-types/dist/types.cjs.development.
|
|
34
|
+
"../learn-card-types/dist/types.cjs.development.cjs"(exports, module) {
|
|
35
35
|
"use strict";
|
|
36
36
|
var __defProp2 = Object.defineProperty;
|
|
37
37
|
var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
|
|
@@ -141,6 +141,7 @@ var require_types_cjs_development = __commonJS({
|
|
|
141
141
|
CredentialActivityStatsValidator: /* @__PURE__ */ __name(() => CredentialActivityStatsValidator, "CredentialActivityStatsValidator"),
|
|
142
142
|
CredentialActivityValidator: /* @__PURE__ */ __name(() => CredentialActivityValidator, "CredentialActivityValidator"),
|
|
143
143
|
CredentialActivityWithDetailsValidator: /* @__PURE__ */ __name(() => CredentialActivityWithDetailsValidator, "CredentialActivityWithDetailsValidator"),
|
|
144
|
+
CredentialFormatValidator: /* @__PURE__ */ __name(() => CredentialFormatValidator, "CredentialFormatValidator"),
|
|
144
145
|
CredentialInfoValidator: /* @__PURE__ */ __name(() => CredentialInfoValidator, "CredentialInfoValidator"),
|
|
145
146
|
CredentialNameRefValidator: /* @__PURE__ */ __name(() => CredentialNameRefValidator, "CredentialNameRefValidator"),
|
|
146
147
|
CredentialRecordValidator: /* @__PURE__ */ __name(() => CredentialRecordValidator, "CredentialRecordValidator"),
|
|
@@ -169,6 +170,8 @@ var require_types_cjs_development = __commonJS({
|
|
|
169
170
|
GetSkillPathResultValidator: /* @__PURE__ */ __name(() => GetSkillPathResultValidator, "GetSkillPathResultValidator"),
|
|
170
171
|
GetTemplateRecipientsEventValidator: /* @__PURE__ */ __name(() => GetTemplateRecipientsEventValidator, "GetTemplateRecipientsEventValidator"),
|
|
171
172
|
GuardianStatusValidator: /* @__PURE__ */ __name(() => GuardianStatusValidator, "GuardianStatusValidator"),
|
|
173
|
+
HolderExportConsentRecordValidator: /* @__PURE__ */ __name(() => HolderExportConsentRecordValidator, "HolderExportConsentRecordValidator"),
|
|
174
|
+
HolderExportMetadataValidator: /* @__PURE__ */ __name(() => HolderExportMetadataValidator, "HolderExportMetadataValidator"),
|
|
172
175
|
IdentifierEntryValidator: /* @__PURE__ */ __name(() => IdentifierEntryValidator, "IdentifierEntryValidator"),
|
|
173
176
|
IdentifierTypeValidator: /* @__PURE__ */ __name(() => IdentifierTypeValidator, "IdentifierTypeValidator"),
|
|
174
177
|
IdentityObjectValidator: /* @__PURE__ */ __name(() => IdentityObjectValidator, "IdentityObjectValidator"),
|
|
@@ -14116,6 +14119,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
14116
14119
|
var ClrCredentialValidator = UnsignedClrCredentialValidator.extend({
|
|
14117
14120
|
proof: ProofValidator.or(ProofValidator.array())
|
|
14118
14121
|
});
|
|
14122
|
+
var CredentialFormatValidator = external_exports.enum([
|
|
14123
|
+
"w3c-vc-2.0",
|
|
14124
|
+
"w3c-vc-1.1",
|
|
14125
|
+
"jwt-vc-json",
|
|
14126
|
+
"dc+sd-jwt",
|
|
14127
|
+
"vc+sd-jwt",
|
|
14128
|
+
"mso_mdoc"
|
|
14129
|
+
]);
|
|
14119
14130
|
var StatusCheckEntryValidator = external_exports.object({
|
|
14120
14131
|
/**
|
|
14121
14132
|
* The `credentialStatus.type` as it appeared on the credential.
|
|
@@ -14171,7 +14182,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
14171
14182
|
issuee: ProfileValidator.optional(),
|
|
14172
14183
|
credentialSubject: CredentialSubjectValidator.optional()
|
|
14173
14184
|
});
|
|
14174
|
-
var CredentialRecordValidator = external_exports.object({
|
|
14185
|
+
var CredentialRecordValidator = external_exports.object({
|
|
14186
|
+
id: external_exports.string(),
|
|
14187
|
+
uri: external_exports.string(),
|
|
14188
|
+
format: CredentialFormatValidator.optional(),
|
|
14189
|
+
semanticType: external_exports.string().optional(),
|
|
14190
|
+
rawWireForm: external_exports.string().optional()
|
|
14191
|
+
}).catchall(external_exports.any());
|
|
14175
14192
|
var PaginationOptionsValidator = external_exports.object({
|
|
14176
14193
|
limit: external_exports.number(),
|
|
14177
14194
|
cursor: external_exports.string().optional(),
|
|
@@ -14739,6 +14756,22 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
14739
14756
|
date: external_exports.string(),
|
|
14740
14757
|
uris: external_exports.string().array().optional()
|
|
14741
14758
|
});
|
|
14759
|
+
var HolderExportConsentRecordValidator = external_exports.object({
|
|
14760
|
+
termsUri: external_exports.string(),
|
|
14761
|
+
status: ConsentFlowTermsStatusValidator,
|
|
14762
|
+
contract: ConsentFlowContractDetailsValidator,
|
|
14763
|
+
terms: ConsentFlowTermsValidator,
|
|
14764
|
+
transactions: ConsentFlowTransactionValidator.array()
|
|
14765
|
+
});
|
|
14766
|
+
var HolderExportMetadataValidator = external_exports.object({
|
|
14767
|
+
consentRecords: HolderExportConsentRecordValidator.array(),
|
|
14768
|
+
truncated: external_exports.boolean().optional(),
|
|
14769
|
+
warnings: external_exports.string().array().optional(),
|
|
14770
|
+
limits: external_exports.object({
|
|
14771
|
+
maxConsentRecords: external_exports.number(),
|
|
14772
|
+
maxTransactionsPerConsentRecord: external_exports.number()
|
|
14773
|
+
}).optional()
|
|
14774
|
+
});
|
|
14742
14775
|
var PaginatedConsentFlowTransactionsValidator = PaginationResponseValidator.extend({
|
|
14743
14776
|
records: ConsentFlowTransactionValidator.array()
|
|
14744
14777
|
});
|
|
@@ -14825,10 +14858,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
14825
14858
|
var LCNNotificationValidator = external_exports.object({
|
|
14826
14859
|
type: LCNNotificationTypeEnumValidator,
|
|
14827
14860
|
to: LCNProfileValidator.partial().and(external_exports.object({ did: external_exports.string() })),
|
|
14828
|
-
from: external_exports.union([
|
|
14829
|
-
external_exports.string(),
|
|
14830
|
-
LCNProfileValidator.partial().and(external_exports.object({ did: external_exports.string() }))
|
|
14831
|
-
]),
|
|
14861
|
+
from: external_exports.union([external_exports.string(), LCNProfileValidator.partial().and(external_exports.object({ did: external_exports.string() }))]),
|
|
14832
14862
|
message: LCNNotificationMessageValidator.optional(),
|
|
14833
14863
|
data: LCNNotificationDataValidator.optional(),
|
|
14834
14864
|
sent: external_exports.iso.datetime().optional(),
|
|
@@ -15588,9 +15618,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15588
15618
|
}
|
|
15589
15619
|
});
|
|
15590
15620
|
|
|
15591
|
-
// ../learn-card-types/dist/index.
|
|
15621
|
+
// ../learn-card-types/dist/index.cjs
|
|
15592
15622
|
var require_dist = __commonJS({
|
|
15593
|
-
"../learn-card-types/dist/index.
|
|
15623
|
+
"../learn-card-types/dist/index.cjs"(exports, module) {
|
|
15594
15624
|
"use strict";
|
|
15595
15625
|
if (false) {
|
|
15596
15626
|
module.exports = null;
|
|
@@ -16538,6 +16568,78 @@ var calculateAgeFromDob = /* @__PURE__ */ __name((dob) => {
|
|
|
16538
16568
|
return age;
|
|
16539
16569
|
}, "calculateAgeFromDob");
|
|
16540
16570
|
|
|
16571
|
+
// src/credential-format.ts
|
|
16572
|
+
var toStoredCredential = /* @__PURE__ */ __name((record) => {
|
|
16573
|
+
if (record.format) {
|
|
16574
|
+
if (record.format === "dc+sd-jwt" || record.format === "vc+sd-jwt" || record.format === "jwt-vc-json" || record.format === "mso_mdoc") {
|
|
16575
|
+
const wireForm = record.rawWireForm ?? extractWireFormFromVc(record.vc);
|
|
16576
|
+
if (typeof wireForm === "string" && wireForm.length > 0) {
|
|
16577
|
+
return { format: record.format, data: wireForm };
|
|
16578
|
+
}
|
|
16579
|
+
}
|
|
16580
|
+
if (record.format === "w3c-vc-2.0" || record.format === "w3c-vc-1.1") {
|
|
16581
|
+
return { format: record.format, data: record.vc };
|
|
16582
|
+
}
|
|
16583
|
+
}
|
|
16584
|
+
const vc = record.vc;
|
|
16585
|
+
if (typeof vc === "string") {
|
|
16586
|
+
if (looksLikeSdJwtCompact(vc)) {
|
|
16587
|
+
return { format: "dc+sd-jwt", data: vc };
|
|
16588
|
+
}
|
|
16589
|
+
if (looksLikeJwsCompact(vc)) {
|
|
16590
|
+
return { format: "jwt-vc-json", data: vc };
|
|
16591
|
+
}
|
|
16592
|
+
}
|
|
16593
|
+
if (vc && typeof vc === "object") {
|
|
16594
|
+
const proof = getWireFormProof(vc, true);
|
|
16595
|
+
const wireFromProof = getWireFormFromProof(proof);
|
|
16596
|
+
if (wireFromProof) {
|
|
16597
|
+
const proofType = proof?.type;
|
|
16598
|
+
if (proofType === "SdJwtCompactProof") {
|
|
16599
|
+
return { format: "dc+sd-jwt", data: wireFromProof };
|
|
16600
|
+
}
|
|
16601
|
+
if (proofType === "JwtProof2020") {
|
|
16602
|
+
return { format: "jwt-vc-json", data: wireFromProof };
|
|
16603
|
+
}
|
|
16604
|
+
}
|
|
16605
|
+
const inferred = inferW3cVersionFromContext(vc);
|
|
16606
|
+
return { format: inferred, data: vc };
|
|
16607
|
+
}
|
|
16608
|
+
return { format: "w3c-vc-1.1", data: vc };
|
|
16609
|
+
}, "toStoredCredential");
|
|
16610
|
+
var SD_JWT_COMPACT_RE = /^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+~/;
|
|
16611
|
+
var JWS_COMPACT_RE = /^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/;
|
|
16612
|
+
var looksLikeSdJwtCompact = /* @__PURE__ */ __name((value) => SD_JWT_COMPACT_RE.test(value), "looksLikeSdJwtCompact");
|
|
16613
|
+
var looksLikeJwsCompact = /* @__PURE__ */ __name((value) => JWS_COMPACT_RE.test(value), "looksLikeJwsCompact");
|
|
16614
|
+
var getWireFormProof = /* @__PURE__ */ __name((vc, requireSupportedType = false) => {
|
|
16615
|
+
if (!vc || typeof vc !== "object") return void 0;
|
|
16616
|
+
const proof = vc.proof;
|
|
16617
|
+
if (Array.isArray(proof)) {
|
|
16618
|
+
for (const entry of proof) {
|
|
16619
|
+
const proofObject2 = asWireFormProof(entry);
|
|
16620
|
+
if (proofObject2 && isUsableWireFormProof(proofObject2, requireSupportedType)) {
|
|
16621
|
+
return proofObject2;
|
|
16622
|
+
}
|
|
16623
|
+
}
|
|
16624
|
+
return void 0;
|
|
16625
|
+
}
|
|
16626
|
+
const proofObject = asWireFormProof(proof);
|
|
16627
|
+
return proofObject && isUsableWireFormProof(proofObject, requireSupportedType) ? proofObject : void 0;
|
|
16628
|
+
}, "getWireFormProof");
|
|
16629
|
+
var asWireFormProof = /* @__PURE__ */ __name((proof) => proof && typeof proof === "object" ? proof : void 0, "asWireFormProof");
|
|
16630
|
+
var isUsableWireFormProof = /* @__PURE__ */ __name((proof, requireSupportedType) => typeof proof.jwt === "string" && proof.jwt.length > 0 && (!requireSupportedType || proof.type === "SdJwtCompactProof" || proof.type === "JwtProof2020"), "isUsableWireFormProof");
|
|
16631
|
+
var getWireFormFromProof = /* @__PURE__ */ __name((proof) => typeof proof?.jwt === "string" && proof.jwt.length > 0 ? proof.jwt : void 0, "getWireFormFromProof");
|
|
16632
|
+
var extractWireFormFromVc = /* @__PURE__ */ __name((vc) => getWireFormFromProof(getWireFormProof(vc)), "extractWireFormFromVc");
|
|
16633
|
+
var inferW3cVersionFromContext = /* @__PURE__ */ __name((vc) => {
|
|
16634
|
+
if (!vc || typeof vc !== "object") return "w3c-vc-1.1";
|
|
16635
|
+
const contextRaw = vc["@context"];
|
|
16636
|
+
const contexts = Array.isArray(contextRaw) ? contextRaw : contextRaw !== void 0 ? [contextRaw] : [];
|
|
16637
|
+
const isV2 = contexts.some(
|
|
16638
|
+
(c) => typeof c === "string" && c.includes("w3.org/ns/credentials/v2")
|
|
16639
|
+
);
|
|
16640
|
+
return isV2 ? "w3c-vc-2.0" : "w3c-vc-1.1";
|
|
16641
|
+
}, "inferW3cVersionFromContext");
|
|
16642
|
+
|
|
16541
16643
|
// src/index.ts
|
|
16542
16644
|
var isHex = /* @__PURE__ */ __name((str) => /^[0-9a-f]+$/i.test(str), "isHex");
|
|
16543
16645
|
var isEncrypted = /* @__PURE__ */ __name((item) => {
|
|
@@ -16629,5 +16731,6 @@ export {
|
|
|
16629
16731
|
quantizeValue,
|
|
16630
16732
|
resizeAndChangeQuality4 as resizeAndChangeQuality,
|
|
16631
16733
|
setBitstringStatusListBit,
|
|
16734
|
+
toStoredCredential,
|
|
16632
16735
|
unwrapBoostCredential
|
|
16633
16736
|
};
|