@cooperation/vc-storage 1.0.44 → 1.0.46

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.
@@ -14,7 +14,7 @@ export declare class LCWStorage {
14
14
  ok: boolean;
15
15
  headers: [string, string][];
16
16
  status: number;
17
- blob(): Promise<import("buffer").Blob>;
17
+ blob(): Promise<import("node:buffer").Blob>;
18
18
  json(): Promise<unknown>;
19
19
  }>;
20
20
  read(key: string): Promise<unknown>;
@@ -22,7 +22,7 @@ export declare class LCWStorage {
22
22
  ok: boolean;
23
23
  headers: [string, string][];
24
24
  status: number;
25
- blob(): Promise<import("buffer").Blob>;
25
+ blob(): Promise<import("node:buffer").Blob>;
26
26
  json(): Promise<unknown>;
27
27
  }>;
28
28
  delete(key: string): Promise<boolean>;
@@ -148,6 +148,18 @@ export declare const volunteeringCredentialContext: {
148
148
  evidenceDescription: string;
149
149
  };
150
150
  };
151
+ /** JSON-LD terms for RecommendationCredential (schema.org + VC v2). */
152
+ export declare const recommendationCredentialContext: {
153
+ '@context': {
154
+ recipientName: string;
155
+ howKnow: string;
156
+ recommendationText: string;
157
+ qualifications: string;
158
+ explainAnswer: string;
159
+ portfolio: string;
160
+ skillsEndorsed: string;
161
+ };
162
+ };
151
163
  export declare const performanceReviewCredentialContext: {
152
164
  '@context': {
153
165
  '@vocab': string;
@@ -1,4 +1,4 @@
1
- import { KeyPair, DidDocument, FormDataI, RecommendationFormDataI, EmploymentFormDataI, VolunteeringFormDataI, PerformanceReviewFormDataI } from '../../types';
1
+ import { KeyPair, DidDocument, FormDataI, RecommendationFormDataI, EvidenceItem, EmploymentFormDataI, VolunteeringFormDataI, PerformanceReviewFormDataI } from '../../types';
2
2
  import type { ISkillClaimCredential } from 'hr-context';
3
3
  import { IVerifiableCredential } from '@digitalcredentials/ssi';
4
4
  /**
@@ -22,19 +22,14 @@ export declare function generateUnsignedVC({ formData, issuerDid }: {
22
22
  issuerDid: string;
23
23
  }): IVerifiableCredential;
24
24
  /**
25
- * Generate an unsigned Recommendation Credential.
26
- * Uses the hash of the VC to set the `id` for consistency.
27
- * @param {object} params
28
- * @param {IVerifiableCredential} params.vc - The Verifiable Credential to base the recommendation on.
29
- * @param {RecommendationFormDataI} params.recommendation - The recommendation form data.
30
- * @param {string} params.issuerDid - The DID of the issuer.
31
- * @returns {IVerifiableCredential} The created unsigned Recommendation Credential.
32
- * @throws Will throw an error if the recommendation creation fails or if issuance date exceeds expiration date.
25
+ * Generate an unsigned Recommendation Credential (VC Data Model v2).
26
+ * Uses the target skill-claim VC id on credentialSubject.id.
33
27
  */
34
- export declare function generateUnsignedRecommendation({ vcId, recommendation, issuerDid, }: {
28
+ export declare function generateUnsignedRecommendation({ vcId, recommendation, issuerDid, evidence, }: {
35
29
  vcId: string;
36
30
  recommendation: RecommendationFormDataI;
37
31
  issuerDid: string;
32
+ evidence?: EvidenceItem[];
38
33
  }): IVerifiableCredential;
39
34
  /**
40
35
  * Generate an unsigned Employment Credential.
@@ -166,6 +166,18 @@ export const volunteeringCredentialContext = {
166
166
  evidenceDescription: 'https://schema.org/description'
167
167
  }
168
168
  };
169
+ /** JSON-LD terms for RecommendationCredential (schema.org + VC v2). */
170
+ export const recommendationCredentialContext = {
171
+ '@context': {
172
+ recipientName: 'https://schema.org/name',
173
+ howKnow: 'https://schema.org/howKnow',
174
+ recommendationText: 'https://schema.org/recommendationText',
175
+ qualifications: 'https://schema.org/qualifications',
176
+ explainAnswer: 'https://schema.org/explainAnswer',
177
+ portfolio: 'https://schema.org/portfolio',
178
+ skillsEndorsed: 'https://schema.org/skillsEndorsed',
179
+ },
180
+ };
169
181
  // 3. Performance Review Credential Context
170
182
  export const performanceReviewCredentialContext = {
171
183
  '@context': {
@@ -1,7 +1,7 @@
1
1
  import { Ed25519VerificationKey2020 } from '@digitalcredentials/ed25519-verification-key-2020';
2
2
  import { v4 as uuidv4 } from 'uuid';
3
3
  import CryptoJS from 'crypto-js';
4
- import { employmentCredentialContext, volunteeringCredentialContext, performanceReviewCredentialContext } from './context.js';
4
+ import { employmentCredentialContext, volunteeringCredentialContext, performanceReviewCredentialContext, recommendationCredentialContext, } from './context.js';
5
5
  /**
6
6
  * Utility function to generate a hashed ID for a credential.
7
7
  * Excludes the `id` field when hashing.
@@ -123,54 +123,44 @@ export function generateUnsignedVC({ formData, issuerDid }) {
123
123
  return unsignedCredential;
124
124
  }
125
125
  /**
126
- * Generate an unsigned Recommendation Credential.
127
- * Uses the hash of the VC to set the `id` for consistency.
128
- * @param {object} params
129
- * @param {IVerifiableCredential} params.vc - The Verifiable Credential to base the recommendation on.
130
- * @param {RecommendationFormDataI} params.recommendation - The recommendation form data.
131
- * @param {string} params.issuerDid - The DID of the issuer.
132
- * @returns {IVerifiableCredential} The created unsigned Recommendation Credential.
133
- * @throws Will throw an error if the recommendation creation fails or if issuance date exceeds expiration date.
126
+ * Generate an unsigned Recommendation Credential (VC Data Model v2).
127
+ * Uses the target skill-claim VC id on credentialSubject.id.
134
128
  */
135
- export function generateUnsignedRecommendation({ vcId, recommendation, issuerDid, }) {
136
- const issuanceDate = new Date().toISOString();
137
- if (issuanceDate > recommendation.expirationDate)
138
- throw new Error('issuanceDate cannot be after expirationDate');
129
+ export function generateUnsignedRecommendation({ vcId, recommendation, issuerDid, evidence = [], }) {
139
130
  const unsignedRecommendation = {
140
131
  '@context': [
141
- 'https://www.w3.org/2018/credentials/v1',
132
+ 'https://www.w3.org/ns/credentials/v2',
142
133
  'https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json',
143
- {
144
- howKnow: 'https://schema.org/howKnow',
145
- recommendationText: 'https://schema.org/recommendationText',
146
- qualifications: 'https://schema.org/qualifications',
147
- explainAnswer: 'https://schema.org/explainAnswer',
148
- portfolio: 'https://schema.org/portfolio',
149
- },
134
+ 'https://w3id.org/hr/v1',
135
+ recommendationCredentialContext,
136
+ 'https://w3id.org/security/suites/ed25519-2020/v1',
150
137
  ],
151
- id: ``,
138
+ id: `urn:uuid:${uuidv4()}`,
152
139
  type: ['VerifiableCredential', 'https://schema.org/RecommendationCredential'],
153
- issuer: {
154
- id: issuerDid,
155
- type: ['Profile'],
156
- },
157
- issuanceDate,
158
- expirationDate: recommendation.expirationDate,
140
+ issuer: { id: issuerDid, type: ['Profile'] },
141
+ validFrom: new Date().toISOString(),
159
142
  credentialSubject: {
160
143
  id: vcId,
161
144
  name: recommendation.fullName,
145
+ ...(recommendation.recipientName ? { recipientName: recommendation.recipientName } : {}),
162
146
  howKnow: recommendation.howKnow,
163
147
  recommendationText: recommendation.recommendationText,
164
- qualifications: recommendation.qualifications,
165
- explainAnswer: recommendation.explainAnswer,
166
- portfolio: recommendation.portfolio.map((item) => ({
167
- name: item.name,
168
- url: item.url,
169
- })),
148
+ ...(recommendation.qualifications ? { qualifications: recommendation.qualifications } : {}),
149
+ ...(recommendation.explainAnswer ? { explainAnswer: recommendation.explainAnswer } : {}),
150
+ ...(recommendation.portfolio?.length ? { portfolio: recommendation.portfolio } : {}),
151
+ ...(recommendation.skillsEndorsed?.length ? { skillsEndorsed: recommendation.skillsEndorsed } : {}),
170
152
  },
153
+ ...(evidence.length
154
+ ? {
155
+ evidence: evidence.map((e) => ({
156
+ id: e.id,
157
+ type: Array.isArray(e.type) ? e.type[0] : e.type || 'Evidence',
158
+ name: e.name,
159
+ description: e.description || '',
160
+ })),
161
+ }
162
+ : {}),
171
163
  };
172
- // Generate the hashed ID
173
- unsignedRecommendation.id = 'urn:' + generateHashedId(unsignedRecommendation);
174
164
  return unsignedRecommendation;
175
165
  }
176
166
  /**
@@ -302,6 +292,8 @@ export function generateUnsignedSkillClaim({ formData, issuerDid, }) {
302
292
  durationPerformed: s.durationPerformed,
303
293
  narrative: s.narrative,
304
294
  image: s.image,
295
+ source: s.source,
296
+ frameworkMatch: s.frameworkMatch,
305
297
  })),
306
298
  },
307
299
  evidence: formData.evidence?.length ? formData.evidence.map((e) => ({
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cooperation/vc-storage",
3
3
  "type": "module",
4
- "version": "1.0.44",
4
+ "version": "1.0.46",
5
5
  "description": "Sign and store your verifiable credentials.",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/types/index.d.ts",
@@ -43,6 +43,7 @@
43
43
  "devDependencies": {
44
44
  "@types/fs-extra": "^11.0.4",
45
45
  "@types/jest": "^29.5.14",
46
+ "@types/node": "^25.9.0",
46
47
  "@types/uuid": "^10.0.0",
47
48
  "babel-jest": "^29.7.0",
48
49
  "typescript": "^5.8.3",