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

@wemush/wols

v0.1.0

Published

Official WOLS (WeMush Open Labeling Standard) library for specimen labeling and traceability

Downloads

95

Readme

@wemush/wols

Official TypeScript library for WOLS (WeMush Open Labeling Standard) - the open standard for biological specimen labeling and traceability in mycology.

npm version License: Apache-2.0

Features

  • 🏷️ Create & Serialize - Generate WOLS-compliant specimen labels
  • Validate - Schema validation with detailed error reporting
  • 📜 Parse - Parse JSON/QR data back to typed specimens
  • 📱 QR Codes - Generate QR codes for specimens (PNG, SVG, Data URL)
  • 🔗 Compact URLs - Create short URLs for space-constrained labels
  • 🔐 Encryption - AES-256-GCM encryption for sensitive data

Installation

npm install @wemush/wols
# or
bun add @wemush/wols
# or
pnpm add @wemush/wols

Optional Peer Dependency

For QR code generation, install the qrcode package:

npm install qrcode

Quick Start

import { createSpecimen, parseSpecimen, validateSpecimen } from '@wemush/wols';

// Create a specimen
const specimen = createSpecimen({
  type: 'CULTURE',
  species: 'Pleurotus ostreatus',
  strain: 'Blue Oyster',
  stage: 'COLONIZATION',
});

console.log(specimen.id); // "wemush:abc123..."
console.log(specimen['@context']); // "https://wemush.com/wols/v1"

Core Module API

createSpecimen(input: SpecimenInput): Specimen

Creates a new specimen with auto-generated ID and JSON-LD fields.

const specimen = createSpecimen({
  type: 'SPAWN',
  species: 'Hericium erinaceus',
  strain: { name: "Lion's Mane", generation: 'F2' },
  stage: 'INOCULATION',
  batch: 'BATCH-2024-001',
  organization: 'org_123',
  custom: { substrate: 'hardwood' },
});

Parameters:

  • type - Specimen type: 'CULTURE', 'SPAWN', 'SUBSTRATE', 'FRUITING', 'HARVEST'
  • species - Scientific species name
  • strain - String (auto-expands to { name: string }) or full Strain object
  • stage - Growth stage: 'INOCULATION', 'COLONIZATION', 'FRUITING', 'HARVEST'
  • batch - Batch identifier
  • organization - Organization ID
  • creator - Creator user ID
  • custom - Custom vendor-specific fields

serializeSpecimen(specimen: Specimen): string

Serializes a specimen to a JSON-LD string, suitable for QR encoding.

const json = serializeSpecimen(specimen);
// Output: {"@context":"https://wemush.com/wols/v1","@type":"Specimen",...}

parseSpecimen(json: string): ParseResult<Specimen>

Parses a JSON string into a validated Specimen object.

const result = parseSpecimen(qrCodeContent);

if (result.success) {
  console.log(result.data.species);
} else {
  console.error(result.error.code, result.error.message);
}

validateSpecimen(data: unknown, options?): ValidationResult

Validates a specimen object against the WOLS schema.

const result = validateSpecimen(specimen, { level: 'strict' });

if (!result.valid) {
  for (const error of result.errors) {
    console.log(`${error.path}: ${error.message}`);
  }
}

Options:

  • allowUnknownFields - Allow unknown fields in custom namespace
  • level - Validation strictness: 'strict' or 'lenient'

QR Code Module API

Generate QR codes for specimens. Requires the qrcode peer dependency.

import { toQRCode, toQRCodeDataURL, toQRCodeSVG } from '@wemush/wols';
// Or import from submodule:
// import { toQRCode } from '@wemush/wols/qr';

toQRCode(specimen, options?): Promise<Buffer>

Generate a QR code as a PNG buffer.

import { writeFileSync } from 'fs';

const buffer = await toQRCode(specimen, {
  size: 400,
  errorCorrection: 'H',
});
writeFileSync('specimen.png', buffer);

toQRCodeDataURL(specimen, options?): Promise<string>

Generate a QR code as a data URL for web embedding.

const dataUrl = await toQRCodeDataURL(specimen);
document.getElementById('qr').src = dataUrl;

toQRCodeSVG(specimen, options?): Promise<string>

Generate a QR code as an SVG string.

const svg = await toQRCodeSVG(specimen);
document.getElementById('qr-container').innerHTML = svg;

QR Options:

  • size - Width/height in pixels (default: 300)
  • errorCorrection - Error correction level: 'L', 'M', 'Q', 'H' (default: 'M')
  • format - Encoding format: 'embedded' (full JSON) or 'compact' (URL)
  • margin - Quiet zone modules (default: 1)
  • color.dark - Dark module color (default: '#000000')
  • color.light - Light module color (default: '#ffffff')

Compact URL for Smaller QR Codes

Use compact URLs for space-constrained labels:

import { toCompactUrl, parseCompactUrl } from '@wemush/wols';

const url = toCompactUrl(specimen);
// Output: "wemush://v1/abc123?s=POSTR&st=COLONIZATION&ty=CULTURE"

const result = parseCompactUrl(url);
if (result.success) {
  console.log(result.data.species); // "Pleurotus ostreatus"
}

Encryption Module API

Encrypt specimens using AES-256-GCM for secure data handling.

import { encryptSpecimen, decryptSpecimen, isEncrypted } from '@wemush/wols';
// Or import from submodule:
// import { encryptSpecimen } from '@wemush/wols/crypto';

encryptSpecimen(specimen, options): Promise<EncryptedSpecimen>

Encrypt a specimen with a password or CryptoKey.

const encrypted = await encryptSpecimen(specimen, {
  key: 'my-secret-password',
});

console.log(encrypted);
// { encrypted: true, payload: "...", iv: "...", algorithm: "AES-256-GCM" }

decryptSpecimen(encrypted, options): Promise<ParseResult<Specimen>>

Decrypt an encrypted specimen.

const result = await decryptSpecimen(encrypted, {
  key: 'my-secret-password',
});

if (result.success) {
  console.log(result.data.species);
} else {
  console.error('Decryption failed:', result.error.message);
}

isEncrypted(value): boolean

Check if a value is an encrypted specimen.

if (isEncrypted(data)) {
  // Handle encrypted specimen
}

Encryption Options:

  • key - Password string (uses PBKDF2) or CryptoKey
  • fields - Encrypt only specific fields (partial encryption)

Types

All types are exported for TypeScript users:

import type {
  Specimen,
  SpecimenInput,
  SpecimenId,
  SpecimenType,
  GrowthStage,
  Strain,
  ParseResult,
  ValidationResult,
  ValidationError,
  EncryptedSpecimen,
  EncryptionOptions,
  QRCodeOptions,
} from '@wemush/wols';

Error Handling

All errors include a stable error code for programmatic handling:

import { WolsErrorCode } from '@wemush/wols';

const result = parseSpecimen(invalidJson);
if (!result.success) {
  switch (result.error.code) {
    case WolsErrorCode.INVALID_JSON:
      console.error('Invalid JSON syntax');
      break;
    case WolsErrorCode.REQUIRED_FIELD:
      console.error('Missing required field');
      break;
    case WolsErrorCode.INVALID_ID_FORMAT:
      console.error('Invalid specimen ID format');
      break;
  }
}

WOLS Specification

This library implements WOLS v1.1.0. For the full specification, see the WOLS Specification.

License

Apache-2.0