npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@learncard/ler-rs-plugin

v0.1.4

Published

LER-RS plugin for LearnCard: create, package, and verify Learning & Employment Record Resumes

Readme

@learncard/ler-rs-plugin

Create, package, and verify Learning & Employment Record Resume (LER-RS) credentials.

Install

This plugin is part of the LearnCard monorepo and is built with the workspace.

API

  • createLerRecord(params: CreateLerRecordParams): Promise<VC>
  • createLerPresentation(params: CreateLerPresentationParams): Promise<VP>
  • verifyLerPresentation(params: VerifyLerPresentationParams): Promise<VerificationResult>

See src/types.ts for types and src/ler-rs.ts for implementation details.

Notes

  • Follows the HR Open LER-RS container + verification pattern by embedding VCs in verifications arrays.
  • Ensures credential and presentation type fields are non-empty arrays.

Requirements

  • Your LearnCard must already have the VC plugin installed (provided by standard @learncard/init initializers).
  • Add this plugin by passing the base LearnCard to the factory and then calling addPlugin:
import { getLerRsPlugin } from '@learncard/ler-rs-plugin';

// baseLc should already include the VC plugin (e.g., via @learncard/init)
const lc = await baseLc.addPlugin(getLerRsPlugin(baseLc));

The plugin captures baseLc internally to issue and verify VCs/VPs.

Quick start

import type {
  PersonProfile,
  WorkHistoryItem,
  EducationHistoryItem,
  CertificationItem,
} from '@learncard/ler-rs-plugin';
import { getLerRsPlugin } from '@learncard/ler-rs-plugin';

// 1) Add plugin
const lc = await baseLc.addPlugin(getLerRsPlugin(baseLc));

// 2) Build a LER-RS credential (self-asserted + optional embedded VCs)
const person: PersonProfile = {
  id: 'did:example:alice',
  givenName: 'Alice',
  familyName: 'Anderson',
  email: '[email protected]',
};

const workHistory: WorkHistoryItem[] = [
  {
    position: 'Marketing Professional',
    employer: 'ABC Company',
    start: '2022-01-01',
    end: '2024-06-01',
    narrative: 'Led a multi-channel campaign with 200% ROI.',
  },
];

const educationHistory: EducationHistoryItem[] = [
  {
    institution: 'State University',
    degree: 'B.S. Business',
    specializations: ['Marketing Analytics'],
    start: '2018-09-01',
    end: '2022-05-15',
  },
];

const certifications: CertificationItem[] = [
  {
    name: 'Google Analytics Certification',
    issuingAuthority: 'Google',
    status: 'active',
    narrative: 'Validated proficiency in GA4 and attribution modeling.',
  },
];

const skills = ['SEO/SEM', 'Content Strategy', 'Team Leadership'];

const lerVc = await lc.invoke.createLerRecord({
  person,
  workHistory,
  educationHistory,
  certifications,
  skills,
});

// 3) Package into a VP (must include at least one LER-RS VC)
const vp = await lc.invoke.createLerPresentation({
  credentials: [lerVc],
  domain: 'apply.acme.com',
  challenge: 'a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8',
});

// 4) Verify the presentation
const verification = await lc.invoke.verifyLerPresentation({
  presentation: vp,
  domain: 'apply.acme.com',
  challenge: 'a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8',
});

console.log(verification.verified);
for (const r of verification.credentialResults) {
  console.log(r.credential.id, r.verified, r.isSelfIssued, r.errors);
}

Wrapping existing VCs inside containers

Each container item (workHistory, educationHistory, certifications) can embed externally issued VCs as verifications. Provide verifiableCredential in the item to include it under verifications:

// Assume employmentVc is a third-party or previously issued VC
const employmentVc = await lc.read.get('urn:uuid:employment-123');

const lerWithProof = await lc.invoke.createLerRecord({
  person,
  workHistory: [
    {
      narrative: 'My key responsibilities and outcomes.',
      verifiableCredential: employmentVc,
    },
  ],
});

Schema mapping guidance

This plugin follows a "Container + Verifiable Proof" model. For credentialSubject (LER-RS payload), we map as follows (see src/ler-rs.ts):

  • person

    • From params.person
    • Maps to credentialSubject.person with name.given, name.family, and name.formattedName
  • communication

    • If person.email is provided, becomes credentialSubject.communication.email = [{ address: email }]
  • skills

    • params.skills: string[]credentialSubject.skills = [{ name: string }]
  • employmentHistories (from params.workHistory)

    • employercontainer.organization.tradeName
    • position, start, endcontainer.positionHistories = [{ title, start, end }]
    • narrativecontainer.narrative
    • verifiableCredential or verificationscontainer.verifications = [VC]
    • Any other keys on the item are merged into the container as-is
  • educationAndLearnings (from params.educationHistory)

    • institutioncontainer.institution = { name: institution }
    • start, end → same key names on container
    • degree, specializationscontainer.educationDegrees = [{ name: degree, specializations: [{ name }] }]
    • narrativecontainer.narrative
    • verifiableCredential or verificationscontainer.verifications = [VC]
  • certifications (from params.certifications)

    • All provided keys are copied into the container
    • narrativecontainer.narrative
    • verifiableCredential or verificationscontainer.verifications = [VC]

Resulting VC shape (high-level):

{
  '@context': [
    'https://www.w3.org/ns/credentials/v2',
    'http://schema.hropenstandards.org/4.5/recruiting/json/VerifiableCredentialLER-RSType.json',
  ],
  type: ['VerifiableCredential', 'http://schema.hropenstandards.org/4.5/recruiting/json/LER-RSType.json'],
  issuer: 'did:...issuer',
  validFrom: '...',
  credentialSubject: {
    id: 'did:...subject',
    type: 'http://schema.hropenstandards.org/4.5/recruiting/json/LER-RSType.json',
    person: { name: { given, family, formattedName } },
    communication?: { email?: [{ address }] },
    skills?: [{ name }],
    employmentHistories?: [{ ...container, verifications?: [VC] }],
    educationAndLearnings?: [{ ...container, verifications?: [VC] }],
    certifications?: [{ ...container, verifications?: [VC] }],
  },
}

Verification behavior

  • verifyLerPresentation verifies the VP and each embedded VC.
  • VerificationResult.verified is true when:
    • The presentation verifies, and
    • Every credential either verifies OR is considered self-issued.
  • A credential is considered self-issued when:
    • It is recognized as an LER-RS credential by known legacy/current LER-RS types, or
    • Its issuer DID equals the VP holder DID.

Troubleshooting

  • Non-empty type arrays: VC/VP type are always emitted as non-empty arrays to satisfy validators (e.g., Zod schemas that require [string, ...string[]]).
  • Missing VC plugin: Ensure your base LearnCard already includes @learncard/vc-plugin (standard in @learncard/init initializers).

Contributing

  • Types live in src/types.ts. Implementation is in src/ler-rs.ts.
  • Please add tests for new behaviors and keep examples in this README up-to-date with the code.