@cooperation/vc-storage 1.0.24 → 1.0.26

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.
@@ -6,185 +6,149 @@ import { Ed25519VerificationKey2020 } from '@digitalbazaar/ed25519-verification-
6
6
  import { generateDIDSchema } from '../utils/credential.js';
7
7
  import { inlineResumeContext } from '../utils/context.js';
8
8
  export class ResumeVC {
9
- async sign({ formData, issuerDid, keyPair }) {
10
- const unsignedCredential = this.generateUnsignedCredential({ formData, issuerDid });
11
- const suite = new Ed25519Signature2020({
12
- key: new Ed25519VerificationKey2020(keyPair), // Ensure proper initialization
13
- verificationMethod: keyPair.id,
14
- });
15
- try {
16
- const signedVC = await dbVc.issue({
17
- credential: unsignedCredential,
18
- suite,
19
- documentLoader: customDocumentLoader,
20
- });
21
- console.log('Signed VC:', signedVC);
22
- }
23
- catch (error) {
24
- console.error('Error signing VC:', error.message);
25
- if (error.details) {
26
- console.error('Error details:', JSON.stringify(error.details, null, 2));
27
- }
28
- throw error;
29
- }
30
- return unsignedCredential;
31
- }
32
- generateUnsignedCredential({ formData, issuerDid }) {
33
- const unsignedResumeVC = {
34
- '@context': [
35
- 'https://www.w3.org/2018/credentials/v1',
36
- inlineResumeContext['@context'], // Inline context
37
- ],
38
- id: `urn:uuid:${uuidv4()}`, // Generate a unique UUID
39
- type: ['VerifiableCredential', 'LERRSCredential'], // LER-RS compliant credential type
40
- issuer: issuerDid,
41
- issuanceDate: new Date().toISOString(), // Current date/time in ISO format
42
- credentialSubject: {
43
- type: 'Resume',
44
- person: {
45
- name: {
46
- formattedName: formData.name || '',
47
- },
48
- primaryLanguage: 'en',
49
- contact: {
50
- fullName: formData.contact.fullName || '',
51
- email: formData.contact.email || '',
52
- phone: formData.contact.phone || '',
53
- location: {
54
- street: formData.contact.location.street || '',
55
- city: formData.contact.location.city || '',
56
- state: formData.contact.location.state || '',
57
- country: formData.contact.location.country || '',
58
- postalCode: formData.contact.location.postalCode || '',
59
- },
60
- socialLinks: {
61
- linkedin: formData.contact.socialLinks.linkedin || '',
62
- github: formData.contact.socialLinks.github || '',
63
- portfolio: formData.contact.socialLinks.portfolio || '',
64
- twitter: formData.contact.socialLinks.twitter || '',
65
- },
66
- },
67
- },
68
- narrative: {
69
- text: formData.summary || '',
70
- },
71
- // Employment History
72
- employmentHistory: formData.experience.items.map((exp) => ({
73
- organization: {
74
- tradeName: exp.company || '',
75
- },
76
- title: exp.title || '',
77
- description: exp.description || '',
78
- startDate: exp.startDate || '',
79
- endDate: exp.endDate || '',
80
- stillEmployed: exp.stillEmployed || false,
81
- })),
82
- // Duplicated Experience (Raw)
83
- experience: formData.experience.items.map((exp) => ({
84
- company: exp.company || '',
85
- title: exp.title || '',
86
- description: exp.description || '',
87
- startDate: exp.startDate || '',
88
- endDate: exp.endDate || '',
89
- stillEmployed: exp.stillEmployed || false,
90
- })),
91
- // Skills
92
- skills: formData.skills.items.map((skill) => ({
93
- name: skill.name || '',
94
- })),
95
- // Education
96
- educationAndLearning: formData.education.items.map((edu) => ({
97
- institution: edu.institution || '',
98
- degree: edu.degree || '',
99
- fieldOfStudy: edu.fieldOfStudy || '',
100
- startDate: edu.startDate || '',
101
- endDate: edu.endDate || '',
102
- })),
103
- // Awards
104
- awards: formData.awards.items.map((award) => ({
105
- title: award.title || '',
106
- issuer: award.issuer || '',
107
- date: award.date || '',
108
- description: award.description || '',
109
- })),
110
- // Publications
111
- publications: formData.publications.items.map((pub) => ({
112
- title: pub.title || '',
113
- publisher: pub.publisher || '',
114
- date: pub.date || '',
115
- url: pub.url || '',
116
- })),
117
- // Certifications
118
- certifications: formData.certifications.items.map((cert) => ({
119
- name: cert.name || '',
120
- issuer: cert.issuer || '',
121
- date: cert.date || '',
122
- url: cert.url || '',
123
- })),
124
- // Professional Affiliations
125
- professionalAffiliations: formData.professionalAffiliations.items.map((aff) => ({
126
- organization: aff.organization || '',
127
- role: aff.role || '',
128
- startDate: aff.startDate || '',
129
- endDate: aff.endDate || '',
130
- })),
131
- // Volunteer Work
132
- volunteerWork: formData.volunteerWork.items.map((vol) => ({
133
- organization: vol.organization || '',
134
- role: vol.role || '',
135
- description: vol.description || '',
136
- startDate: vol.startDate || '',
137
- endDate: vol.endDate || '',
138
- })),
139
- // Hobbies and Interests
140
- hobbiesAndInterests: formData.hobbiesAndInterests || [],
141
- // Languages
142
- languages: formData.languages.items.map((lang) => ({
143
- language: lang.language || '',
144
- proficiency: lang.proficiency || '',
145
- })),
146
- // Testimonials
147
- testimonials: formData.testimonials.items.map((testi) => ({
148
- author: testi.author || '',
149
- text: testi.text || '',
150
- date: testi.date || '',
151
- })),
152
- // Projects
153
- projects: formData.projects.items.map((proj) => ({
154
- name: proj.name || '',
155
- description: proj.description || '',
156
- url: proj.url || '',
157
- startDate: proj.startDate || '',
158
- endDate: proj.endDate || '',
159
- })),
160
- },
161
- };
162
- return unsignedResumeVC;
163
- }
164
- generateKeyPair = async (address) => {
165
- // Generate the key pair using the library's method
166
- const keyPair = await Ed25519VerificationKey2020.generate();
167
- // Configure key pair attributes
168
- const a = address || keyPair.publicKeyMultibase;
169
- keyPair.controller = `did:key:${a}`;
170
- keyPair.id = `${keyPair.controller}#${a}`;
171
- keyPair.revoked = false;
172
- // The `signer` is already provided by the `Ed25519VerificationKey2020` instance
173
- return keyPair;
174
- };
175
- /**
176
- * Create a new DID with Digital Bazaar's Ed25519VerificationKey2020 key pair.
177
- * @returns {Promise<{didDocument: object, keyPair: object}>} The created DID document and key pair.
178
- * @throws Will throw an error if DID creation fails.
179
- */
180
- async createDID({ keyPair }) {
181
- try {
182
- const didDocument = await generateDIDSchema(keyPair);
183
- return didDocument;
184
- }
185
- catch (error) {
186
- console.error('Error creating DID:', error);
187
- throw error;
188
- }
189
- }
9
+ async sign({ formData, issuerDid, keyPair }) {
10
+ const unsignedCredential = this.generateUnsignedCredential({ formData, issuerDid });
11
+ const suite = new Ed25519Signature2020({
12
+ key: new Ed25519VerificationKey2020(keyPair), // Ensure proper initialization
13
+ verificationMethod: keyPair.id,
14
+ });
15
+ try {
16
+ const signedVC = await dbVc.issue({
17
+ credential: unsignedCredential,
18
+ suite,
19
+ documentLoader: customDocumentLoader,
20
+ });
21
+ console.log('🚀 ~ ResumeVC ~ sign ~ signedVC:', JSON.stringify(signedVC));
22
+ console.log('Signed VC:', JSON.stringify(signedVC));
23
+ } catch (error) {
24
+ console.error('Error signing VC:', error.message);
25
+ if (error.details) {
26
+ console.error('Error details:', JSON.stringify(error.details, null, 2));
27
+ }
28
+ throw error;
29
+ }
30
+ return unsignedCredential;
31
+ }
32
+ generateUnsignedCredential({ formData, issuerDid }) {
33
+ const unsignedResumeVC = {
34
+ '@context': ['https://www.w3.org/2018/credentials/v1', inlineResumeContext['@context']],
35
+ id: `urn:uuid:${uuidv4()}`,
36
+ type: ['VerifiableCredential', 'LERRSCredential'],
37
+ issuer: issuerDid,
38
+ issuanceDate: new Date().toISOString(),
39
+ credentialSubject: {
40
+ type: 'Resume',
41
+ person: {
42
+ name: {
43
+ formattedName: formData.name || '',
44
+ },
45
+ primaryLanguage: 'en',
46
+ contact: {
47
+ fullName: formData.contact.fullName || '',
48
+ email: formData.contact.email || '',
49
+ phone: formData.contact.phone || '',
50
+ location: {
51
+ street: formData.contact.location.street || '',
52
+ city: formData.contact.location.city || '',
53
+ state: formData.contact.location.state || '',
54
+ country: formData.contact.location.country || '',
55
+ postalCode: formData.contact.location.postalCode || '',
56
+ },
57
+ socialLinks: {
58
+ linkedin: formData.contact.socialLinks.linkedin || '',
59
+ github: formData.contact.socialLinks.github || '',
60
+ portfolio: formData.contact.socialLinks.portfolio || '',
61
+ twitter: formData.contact.socialLinks.twitter || '',
62
+ },
63
+ },
64
+ },
65
+ narrative: {
66
+ text: formData.summary || '',
67
+ },
68
+ employmentHistory: formData.experience.items.map((exp) => ({
69
+ id: exp.id ? `urn:uuid${exp.id}` : `urn:uuid:${uuidv4()}`, // Ensure each entry has an ID
70
+ organization: {
71
+ tradeName: exp.company || '',
72
+ },
73
+ title: exp.title || '',
74
+ description: exp.description || '',
75
+ duration: exp.duration || '',
76
+ startDate: exp.startDate || '',
77
+ endDate: exp.endDate || '',
78
+ stillEmployed: exp.stillEmployed || false,
79
+ verificationStatus: exp.verificationStatus || 'unverified',
80
+ credentialLink: exp.credentialLink || null,
81
+ verifiedCredentials: exp.verifiedCredentials || [],
82
+ })),
83
+ educationAndLearning: formData.education.items.map((edu) => ({
84
+ id: edu.id ? `urn:uuid${edu.id}` : `urn:uuid:${uuidv4()}`,
85
+ institution: edu.institution || '',
86
+ degree: edu.degree || '',
87
+ fieldOfStudy: edu.fieldOfStudy || '',
88
+ duration: edu.duration || '',
89
+ startDate: edu.startDate || '',
90
+ endDate: edu.endDate || '',
91
+ verificationStatus: edu.verificationStatus || 'unverified',
92
+ credentialLink: edu.credentialLink || null,
93
+ verifiedCredentials: edu.verifiedCredentials || [],
94
+ })),
95
+ skills: formData.skills.items.map((skill) => ({
96
+ id: skill.id ? `urn:uuid${skill.id}` : `urn:uuid:${uuidv4()}`,
97
+ name: skill.name || '',
98
+ verificationStatus: skill.verificationStatus || 'unverified',
99
+ credentialLink: skill.credentialLink || null,
100
+ verifiedCredentials: skill.verifiedCredentials || [],
101
+ })),
102
+ certifications: formData.certifications.items.map((cert) => ({
103
+ id: cert.id ? `urn:uuid:${cert.id}` : `urn:uuid:${uuidv4()}`,
104
+ name: cert.name || '',
105
+ issuer: cert.issuer || '',
106
+ date: cert.date || '',
107
+ url: cert.url || '',
108
+ verificationStatus: cert.verificationStatus || 'unverified',
109
+ credentialLink: cert.credentialLink || null,
110
+ verifiedCredentials: cert.verifiedCredentials || [],
111
+ })),
112
+ projects: formData.projects.items.map((proj) => ({
113
+ id: proj.id ? `urn:uuid${proj.id}` : `urn:uuid:${uuidv4()}`,
114
+ name: proj.name || '',
115
+ description: proj.description || '',
116
+ url: proj.url || '',
117
+ duration: proj.duration || '',
118
+ startDate: proj.startDate || '',
119
+ endDate: proj.endDate || '',
120
+ verificationStatus: proj.verificationStatus || 'unverified',
121
+ credentialLink: proj.credentialLink || null,
122
+ verifiedCredentials: proj.verifiedCredentials || [],
123
+ })),
124
+ },
125
+ };
126
+ console.log('🚀 ~ ResumeVC ~ generateUnsignedCredential ~ unsignedResumeVC:', JSON.stringify(unsignedResumeVC));
127
+ return unsignedResumeVC;
128
+ }
129
+ generateKeyPair = async (address) => {
130
+ // Generate the key pair using the library's method
131
+ const keyPair = await Ed25519VerificationKey2020.generate();
132
+ // Configure key pair attributes
133
+ const a = address || keyPair.publicKeyMultibase;
134
+ keyPair.controller = `did:key:${a}`;
135
+ keyPair.id = `${keyPair.controller}#${a}`;
136
+ keyPair.revoked = false;
137
+ // The `signer` is already provided by the `Ed25519VerificationKey2020` instance
138
+ return keyPair;
139
+ };
140
+ /**
141
+ * Create a new DID with Digital Bazaar's Ed25519VerificationKey2020 key pair.
142
+ * @returns {Promise<{didDocument: object, keyPair: object}>} The created DID document and key pair.
143
+ * @throws Will throw an error if DID creation fails.
144
+ */
145
+ async createDID({ keyPair }) {
146
+ try {
147
+ const didDocument = await generateDIDSchema(keyPair);
148
+ return didDocument;
149
+ } catch (error) {
150
+ console.error('Error creating DID:', error);
151
+ throw error;
152
+ }
153
+ }
190
154
  }
@@ -102,7 +102,7 @@ export declare const inlineResumeContext: {
102
102
  Resume: string;
103
103
  };
104
104
  };
105
- declare let localOBContext: {
105
+ declare const localOBContext: {
106
106
  '@context': {
107
107
  '@protected': boolean;
108
108
  id: string;
@@ -546,7 +546,7 @@ declare let localOBContext: {
546
546
  };
547
547
  };
548
548
  };
549
- declare let localED25519Context: {
549
+ declare const localED25519Context: {
550
550
  '@context': {
551
551
  id: string;
552
552
  type: string;
@@ -118,7 +118,7 @@ export const inlineResumeContext = {
118
118
  Resume: 'https://schema.hropenstandards.org/4.4#Resume',
119
119
  },
120
120
  };
121
- let localOBContext = {
121
+ const localOBContext = {
122
122
  '@context': {
123
123
  '@protected': true,
124
124
  id: '@id',
@@ -562,7 +562,7 @@ let localOBContext = {
562
562
  },
563
563
  },
564
564
  };
565
- let localED25519Context = {
565
+ const localED25519Context = {
566
566
  '@context': {
567
567
  id: '@id',
568
568
  type: '@type',
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cooperation/vc-storage",
3
3
  "type": "module",
4
- "version": "1.0.24",
4
+ "version": "1.0.26",
5
5
  "description": "Sign and store your verifiable credentials.",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/types/index.d.ts",
@@ -33,7 +33,7 @@
33
33
  "@types/jest": "^29.5.14",
34
34
  "@types/uuid": "^10.0.0",
35
35
  "babel-jest": "^29.7.0",
36
- "typescript": "^5.6.2",
36
+ "typescript": "^5.8.2",
37
37
  "vitest": "^3.0.5"
38
38
  }
39
39
  }